diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index cb7921959..aa78ff8b6 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -15,21 +15,17 @@ jobs: build: strategy: matrix: - xcode: [ "14.2" ] - platform: [ "macos", "maccat", "ios", "tvos" ] - os: [ "macos-latest" ] + xcode: [ "14.3.1" ] + platform: [ "all", "macos", "ios" ] + os: [ "macos-13" ] upload_artifacts: [ true ] - # additional specific configurations + + # Legacy configurations include: - # "Legacy" Xcode 12.5.1 & 11.7 macOS builds - xcode: "12.5.1" platform: "macos" os: "macos-11" upload_artifacts: false - - xcode: "11.7" - platform: "macos" - os: "macos-11" - upload_artifacts: false fail-fast: false name: 'MoltenVK (Xcode ${{ matrix.xcode }} - ${{ matrix.platform }})' @@ -41,7 +37,7 @@ jobs: steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Select Xcode version run: sudo xcode-select -switch "${XCODE_DEV_PATH}" @@ -54,12 +50,12 @@ jobs: echo "${XCODE_VERSION}" XCODE_VERSION="$(echo "${XCODE_VERSION}" | tr '\t\r\n ' '_')" echo "${XCODE_VERSION}" - echo "::set-output name=XCODE_VERSION::${XCODE_VERSION}" + echo "XCODE_VERSION=${XCODE_VERSION}" >> $GITHUB_OUTPUT - name: Cache Dependencies id: cache-dependencies if: success() && !(github.event_name == 'push' && contains(github.ref, 'refs/tags/')) # never cache dependencies for pushed tags - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | External/build @@ -94,11 +90,46 @@ jobs: - name: Tar Artifacts if: success() && matrix.upload_artifacts == true # See: https://github.com/actions/upload-artifact#maintaining-file-permissions-and-case-sensitive-files - run: tar -cvf "${{ matrix.platform }}.tar" Package/Release/ + # To reduce artifact size, don't include any stand-alone shader converter binaries. + run: | + rm -rf Package/Release/MoltenVKShaderConverter + tar -C Package -s/Release/MoltenVK/ -cvf "MoltenVK-${{ matrix.platform }}.tar" Release/ - name: Upload Artifacts if: success() && matrix.upload_artifacts == true - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 + with: + name: "MoltenVK-${{ matrix.platform }}" + path: "MoltenVK-${{ matrix.platform }}.tar" + + release: + name: 'Release' + + needs: [build] + + runs-on: ubuntu-latest + + if: ${{ startsWith(github.ref, 'refs/tags/') }} + + permissions: + contents: write + + steps: + - name: Download Artifacts + uses: actions/download-artifact@v3 + + - name: Create Release + uses: ncipollo/release-action@v1 with: - name: ${{ matrix.platform }} - path: "${{ matrix.platform }}.tar" + # Allow updating existing releases if the workflow is triggered by release creation or re-run. + allowUpdates: true + # When the release is updated, delete the existing artifacts for replacement. + removeArtifacts: true + # If a release is being replaced, omit updating the name and body. + # Allows for creating a release and filling these in before the workflow runs. + # Then, the workflow will populate the release with the artifacts. + omitNameDuringUpdate: true + omitBodyDuringUpdate: true + # Upload all MoltenVK CI artifacts as release assets. + artifacts: "MoltenVK*/*" + artifactErrorsFailBuild: true diff --git a/Common/MVKCommonEnvironment.h b/Common/MVKCommonEnvironment.h index ca6fe5239..a14ba91d0 100644 --- a/Common/MVKCommonEnvironment.h +++ b/Common/MVKCommonEnvironment.h @@ -62,6 +62,14 @@ extern "C" { # define MVK_TVOS TARGET_OS_TV #endif +/** Building for visionOS. */ +#ifndef TARGET_OS_XR +# define TARGET_OS_XR 0 // Older SDK's don't define TARGET_OS_XR +#endif +#ifndef MVK_VISIONOS +# define MVK_VISIONOS TARGET_OS_XR +#endif + /** Building for iOS or tvOS. */ #ifndef MVK_IOS_OR_TVOS # define MVK_IOS_OR_TVOS (MVK_IOS || MVK_TVOS) @@ -72,6 +80,11 @@ extern "C" { # define MVK_MACOS_OR_IOS (MVK_MACOS || MVK_IOS) #endif +/** Building for macOS, iOS or visionOS. */ +#ifndef MVK_MACOS_OR_IOS_OR_VISIONOS +# define MVK_MACOS_OR_IOS_OR_VISIONOS (MVK_MACOS || MVK_IOS | MVK_VISIONOS) +#endif + /** Building for a Simulator. */ #ifndef MVK_OS_SIMULATOR # define MVK_OS_SIMULATOR TARGET_OS_SIMULATOR @@ -87,18 +100,26 @@ extern "C" { # define MVK_MACOS_APPLE_SILICON (MVK_MACOS && MVK_APPLE_SILICON) #endif -/** Building with Xcode versions. */ +/** Building with Xcode versions. iOS version also covers tvOS. */ +#ifndef MVK_XCODE_15 +# define MVK_XCODE_15 ((__MAC_OS_X_VERSION_MAX_ALLOWED >= 140000) || \ + (__IPHONE_OS_VERSION_MAX_ALLOWED >= 170000)) +#endif +#ifndef MVK_XCODE_14_3 +# define MVK_XCODE_14_3 ((__MAC_OS_X_VERSION_MAX_ALLOWED >= 130300) || \ + (__IPHONE_OS_VERSION_MAX_ALLOWED >= 160400)) +#endif #ifndef MVK_XCODE_14 # define MVK_XCODE_14 ((__MAC_OS_X_VERSION_MAX_ALLOWED >= 130000) || \ - (__IPHONE_OS_VERSION_MAX_ALLOWED >= 160000)) // Also covers tvOS + (__IPHONE_OS_VERSION_MAX_ALLOWED >= 160000)) #endif #ifndef MVK_XCODE_13 # define MVK_XCODE_13 ((__MAC_OS_X_VERSION_MAX_ALLOWED >= 120000) || \ - (__IPHONE_OS_VERSION_MAX_ALLOWED >= 150000)) // Also covers tvOS + (__IPHONE_OS_VERSION_MAX_ALLOWED >= 150000)) #endif #ifndef MVK_XCODE_12 -# define MVK_XCODE_12 ((__MAC_OS_X_VERSION_MAX_ALLOWED >= 101600) || \ - (__IPHONE_OS_VERSION_MAX_ALLOWED >= 140000)) // Also covers tvOS +# define MVK_XCODE_12 ((__MAC_OS_X_VERSION_MAX_ALLOWED >= 110000) || \ + (__IPHONE_OS_VERSION_MAX_ALLOWED >= 140000)) #endif /** Directive to identify public symbols. */ diff --git a/Common/MVKOSExtensions.h b/Common/MVKOSExtensions.h index fde73c5c1..79d89216c 100644 --- a/Common/MVKOSExtensions.h +++ b/Common/MVKOSExtensions.h @@ -52,11 +52,13 @@ inline bool mvkOSVersionIsAtLeast(MVKOSVersion minVer) { return mvkOSVersion() > * to always fail on that OS, which is useful for indidicating functionalty guarded by * this test is not supported on that OS. */ -inline bool mvkOSVersionIsAtLeast(MVKOSVersion macOSMinVer, MVKOSVersion iOSMinVer) { +inline bool mvkOSVersionIsAtLeast(MVKOSVersion macOSMinVer, MVKOSVersion iOSMinVer, MVKOSVersion visionOSMinVer) { #if MVK_MACOS return mvkOSVersionIsAtLeast(macOSMinVer); #endif -#if MVK_IOS_OR_TVOS +#if MVK_VISIONOS + return mvkOSVersionIsAtLeast(visionOSMinVer); +#elif MVK_IOS_OR_TVOS return mvkOSVersionIsAtLeast(iOSMinVer); #endif } @@ -76,6 +78,14 @@ uint64_t mvkGetTimestamp(); /** Returns the number of nanoseconds between each increment of the value returned by mvkGetTimestamp(). */ double mvkGetTimestampPeriod(); +/** + * Returns the number of nanoseconds elapsed between startTimestamp and endTimestamp, + * each of which should be a value returned by mvkGetTimestamp(). + * If endTimestamp is zero or not supplied, it is taken to be the current time. + * If startTimestamp is zero or not supplied, it is taken to be the time the app was initialized. + */ +uint64_t mvkGetElapsedNanoseconds(uint64_t startTimestamp = 0, uint64_t endTimestamp = 0); + /** * Returns the number of milliseconds elapsed between startTimestamp and endTimestamp, * each of which should be a value returned by mvkGetTimestamp(). @@ -84,6 +94,9 @@ double mvkGetTimestampPeriod(); */ double mvkGetElapsedMilliseconds(uint64_t startTimestamp = 0, uint64_t endTimestamp = 0); +/** Returns the current absolute time in nanoseconds. */ +uint64_t mvkGetAbsoluteTime(); + /** Ensures the block is executed on the main thread. */ void mvkDispatchToMainAndWait(dispatch_block_t block); @@ -164,3 +177,9 @@ uint64_t mvkGetUsedMemorySize(); /** Returns the size of a page of host memory on this platform. */ uint64_t mvkGetHostMemoryPageSize(); + +#pragma mark - +#pragma mark Threading + +/** Returns the amount of avaliable CPU cores. */ +uint32_t mvkGetAvaliableCPUCores(); diff --git a/Common/MVKOSExtensions.mm b/Common/MVKOSExtensions.mm index 6c023086a..4e2c974c6 100644 --- a/Common/MVKOSExtensions.mm +++ b/Common/MVKOSExtensions.mm @@ -40,16 +40,23 @@ MVKOSVersion mvkOSVersion() { static uint64_t _mvkTimestampBase; static double _mvkTimestampPeriod; +static mach_timebase_info_data_t _mvkMachTimebase; uint64_t mvkGetTimestamp() { return mach_absolute_time() - _mvkTimestampBase; } double mvkGetTimestampPeriod() { return _mvkTimestampPeriod; } -double mvkGetElapsedMilliseconds(uint64_t startTimestamp, uint64_t endTimestamp) { +uint64_t mvkGetElapsedNanoseconds(uint64_t startTimestamp, uint64_t endTimestamp) { if (endTimestamp == 0) { endTimestamp = mvkGetTimestamp(); } - return (double)(endTimestamp - startTimestamp) * _mvkTimestampPeriod / 1e6; + return (endTimestamp - startTimestamp) * _mvkTimestampPeriod; +} + +double mvkGetElapsedMilliseconds(uint64_t startTimestamp, uint64_t endTimestamp) { + return mvkGetElapsedNanoseconds(startTimestamp, endTimestamp) / 1e6; } +uint64_t mvkGetAbsoluteTime() { return mach_continuous_time() * _mvkMachTimebase.numer / _mvkMachTimebase.denom; } + // Initialize timestamping capabilities on app startup. //Called automatically when the framework is loaded and initialized. static bool _mvkTimestampsInitialized = false; @@ -58,9 +65,8 @@ MVKOSVersion mvkOSVersion() { _mvkTimestampsInitialized = true; _mvkTimestampBase = mach_absolute_time(); - mach_timebase_info_data_t timebase; - mach_timebase_info(&timebase); - _mvkTimestampPeriod = (double)timebase.numer / (double)timebase.denom; + mach_timebase_info(&_mvkMachTimebase); + _mvkTimestampPeriod = (double)_mvkMachTimebase.numer / (double)_mvkMachTimebase.denom; } void mvkDispatchToMainAndWait(dispatch_block_t block) { @@ -97,7 +103,7 @@ bool mvkGetEnvVarBool(std::string varName, bool* pWasFound) { #pragma mark System memory uint64_t mvkGetSystemMemorySize() { -#if MVK_MACOS_OR_IOS +#if MVK_MACOS_OR_IOS_OR_VISIONOS mach_msg_type_number_t host_size = HOST_BASIC_INFO_COUNT; host_basic_info_data_t info; if (host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&info, &host_size) == KERN_SUCCESS) { @@ -138,3 +144,10 @@ uint64_t mvkGetUsedMemorySize() { uint64_t mvkGetHostMemoryPageSize() { return sysconf(_SC_PAGESIZE); } +#pragma mark - +#pragma mark Threading + +/** Returns the amount of avaliable CPU cores. */ +uint32_t mvkGetAvaliableCPUCores() { + return (uint32_t)[[NSProcessInfo processInfo] activeProcessorCount]; +} diff --git a/Common/MVKStrings.h b/Common/MVKStrings.h index ec78d9ad7..d3ce5316a 100644 --- a/Common/MVKStrings.h +++ b/Common/MVKStrings.h @@ -21,6 +21,8 @@ #include #include +#include +#include namespace mvk { @@ -59,6 +61,26 @@ namespace mvk { return varName; } + /** Returns a string containing the ordinal suffix for a numeric value.*/ + inline const char* getOrdinalSuffix(int64_t val) { + static const char* suffixes[] = {"th", "st", "nd", "rd"}; + auto ord = val % 100; + if (ord > 10 && ord < 20) { return suffixes[0]; } // All teens end in th. + ord = ord % 10; + if (ord > 3) { return suffixes[0]; } // 4-9 end in th. + return suffixes[ord]; + } + + /** Returns the name of a C++ type. */ + template + inline std::string getTypeName(const T* pObj) { + int status; + char* demangledName = abi::__cxa_demangle(typeid(*pObj).name(), 0, 0, &status); + std::string tName = demangledName; + free(demangledName); + return tName; + } + #pragma mark - #pragma mark Streams diff --git a/Demos/Cube/macOS/DemoViewController.m b/Demos/Cube/macOS/DemoViewController.m index 9586fa670..d8468bdc3 100644 --- a/Demos/Cube/macOS/DemoViewController.m +++ b/Demos/Cube/macOS/DemoViewController.m @@ -43,13 +43,29 @@ -(void) viewDidLoad { self.view.wantsLayer = YES; // Back the view with a layer created by the makeBackingLayer method. - const char* argv[] = { "cube" }; + // Enabling this will sync the rendering loop with the natural display link (60 fps). + // Disabling this will allow the rendering loop to run flat out, limited only by the rendering speed. + bool useDisplayLink = true; + + VkPresentModeKHR vkPresentMode = useDisplayLink ? VK_PRESENT_MODE_FIFO_KHR : VK_PRESENT_MODE_IMMEDIATE_KHR; + char vkPresentModeStr[64]; + sprintf(vkPresentModeStr, "%d", vkPresentMode); + + const char* argv[] = { "cube", "--present_mode", vkPresentModeStr }; int argc = sizeof(argv)/sizeof(char*); demo_main(&demo, self.view.layer, argc, argv); - CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink); - CVDisplayLinkSetOutputCallback(_displayLink, &DisplayLinkCallback, &demo); - CVDisplayLinkStart(_displayLink); + if (useDisplayLink) { + CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink); + CVDisplayLinkSetOutputCallback(_displayLink, &DisplayLinkCallback, &demo); + CVDisplayLinkStart(_displayLink); + } else { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + while(true) { + demo_draw(&demo); + } + }); + } } diff --git a/Docs/MoltenVK_Runtime_UserGuide.md b/Docs/MoltenVK_Runtime_UserGuide.md index a4d951594..f236a7e97 100644 --- a/Docs/MoltenVK_Runtime_UserGuide.md +++ b/Docs/MoltenVK_Runtime_UserGuide.md @@ -25,13 +25,14 @@ Table of Contents - [Install *MoltenVK* replacing the Vulkan SDK `libMoltenVK.dylib`](#install_vksdk) - [Build and Runtime Requirements](#requirements) - [Interacting with the **MoltenVK** Runtime](#interaction) - - [MoltenVK `VK_MVK_moltenvk` Extension](#moltenvk_extension) + - [MoltenVK Header Files](#moltenvk_headers) - [Configuring MoltenVK](#moltenvk_config) - [*Metal Shading Language* Shaders](#shaders) - [Troubleshooting Shader Conversion](#spv_vs_msl) - [Performance Considerations](#performance) - [Shader Loading Time](#shader_load_time) - [Swapchains](#swapchains) + - [Timestamping](#timestamping) - [Xcode Configuration](#xcode_config) - [Metal System Trace Tool](#trace_tool) - [Known **MoltenVK** Limitations](#limitations) @@ -327,6 +328,7 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll - `VK_KHR_get_surface_capabilities2` - `VK_KHR_imageless_framebuffer` - `VK_KHR_image_format_list` +- `VK_KHR_incremental_present` - `VK_KHR_maintenance1` - `VK_KHR_maintenance2` - `VK_KHR_maintenance3` @@ -341,6 +343,7 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll - `VK_KHR_shader_draw_parameters` - `VK_KHR_shader_float_controls` - `VK_KHR_shader_float16_int8` +- `VK_KHR_shader_non_semantic_info` - `VK_KHR_shader_subgroup_extended_types` *(requires Metal 2.1 on Mac or Metal 2.2 and Apple family 4 on iOS)* - `VK_KHR_spirv_1_4` - `VK_KHR_storage_buffer_storage_class` @@ -350,7 +353,9 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll - `VK_KHR_timeline_semaphore` - `VK_KHR_uniform_buffer_standard_layout` - `VK_KHR_variable_pointers` +- `VK_EXT_4444_formats` *(requires 16-bit formats and either native texture swizzling or manual swizzling to be enabled)* - `VK_EXT_buffer_device_address` *(requires GPU Tier 2 argument buffers support)* +- `VK_EXT_calibrated_timestamps` *(requires Metal 2.2)* - `VK_EXT_debug_marker` - `VK_EXT_debug_report` - `VK_EXT_debug_utils` @@ -366,6 +371,7 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll - `VK_EXT_metal_objects` - `VK_EXT_metal_surface` - `VK_EXT_pipeline_creation_cache_control` +- `VK_EXT_pipeline_creation_feedback` - `VK_EXT_post_depth_coverage` *(iOS and macOS, requires family 4 (A11) or better Apple GPU)* - `VK_EXT_private_data ` - `VK_EXT_robustness2` @@ -373,7 +379,10 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll - `VK_EXT_scalar_block_layout` - `VK_EXT_separate_stencil_usage` - `VK_EXT_shader_atomic_float` *(requires Metal 3.0)* +- `VK_EXT_shader_demote_to_helper_invocation` *(requires Metal Shading Language 2.3)* - `VK_EXT_shader_stencil_export` *(requires Mac GPU family 2 or iOS GPU family 5)* +- `VK_EXT_shader_subgroup_ballot` *(requires Mac GPU family 2 or Apple GPU family 4)* +- `VK_EXT_shader_subgroup_vote` *(requires Mac GPU family 2 or Apple GPU family 4)* - `VK_EXT_shader_viewport_index_layer` - `VK_EXT_subgroup_size_control` *(requires Metal 2.1 on Mac or Metal 2.2 and Apple family 4 on iOS)* - `VK_EXT_surface_maintenance1` @@ -384,7 +393,6 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll - `VK_EXT_texture_compression_astc_hdr` *(iOS and macOS, requires family 6 (A13) or better Apple GPU)* - `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_AMD_shader_image_load_store_lod` *(requires Apple GPU)* @@ -425,14 +433,12 @@ extension in the *Vulkan* specification for more information about the use of th `VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR` flag. + +### MoltenVK Header Files - -### MoltenVK `VK_MVK_moltenvk` Extension - -The `VK_MVK_moltenvk` *Vulkan* extension provides functionality beyond standard *Vulkan* functionality, -to support configuration options and behaviour that is specific to the **MoltenVK** implementation of *Vulkan* -functionality. You can access this functionality by including the `vk_mvk_moltenvk.h` header file in your code. -The `vk_mvk_moltenvk.h` file also includes the API documentation for this `VK_MVK_moltenvk` extension. +**MoltenVK** provides additional functionality beyond standard *Vulkan* functionality, +to support configuration options and query behaviour that is specific to the **MoltenVK** +implementation of *Vulkan* functionality. The following API header files are included in the **MoltenVK** package, each of which can be included in your application source code as follows: @@ -441,37 +447,33 @@ can be included in your application source code as follows: where `HEADER_FILE` is one of the following: -- `vk_mvk_moltenvk.h` - Contains declarations and documentation for the functions, structures, - and enumerations that define the behaviour of the `VK_MVK_moltenvk` *Vulkan* extension. - -- `mvk_vulkan.h` - This is a convenience header file that loads the `vulkan.h` header file - with the appropriate **MoltenVK** *Vulkan* platform surface extension automatically - enabled for *macOS*, *iOS*, or *tvOS*. Use this header file in place of the `vulkan.h` - header file, where access to a **MoltenVK** platform surface extension is required. - - The `mvk_vulkan.h` header file automatically enables the `VK_USE_PLATFORM_METAL_EXT` - build setting and `VK_EXT_metal_surface` *Vulkan* extension. +- `mvk_vulkan.h` - This is a convenience header file that loads the `` header file + with platform settings to enable the appropriate platform-surface and portability extensions. -- `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 - *Vulkan* and *Metal* datatypes automatically (using the functions declared in this header). - These functions are exposed in this header for your own purposes such as interacting with *Metal* - directly, or simply logging data values. - ->***Note:*** Except for `vkGetMoltenVKConfigurationMVK()` and `vkSetMoltenVKConfigurationMVK()`, - the functions in `vk_mvk_moltenvk.h` are not supported by the *Vulkan SDK Loader and Layers* - framework. The opaque Vulkan objects used by the functions in `vk_mvk_moltenvk.h` (`VkPhysicalDevice`, - `VkShaderModule`, `VKImage`, ...), must have been retrieved directly from **MoltenVK**, and not through - the *Vulkan SDK Loader and Layers* framework. The *Vulkan SDK Loader and Layers* framework often changes - these opaque objects, and passing them from a higher layer directly to **MoltenVK** will result in - undefined behaviour. +- `mvk_config.h` - Contains public functions and structures to allow you to configure and + optimize **MoltenVK** for your particular application runtime requirements. For more + information, see the [Configuring MoltenVK](#moltenvk_config) section just below. + +- `mvk_private_api.h` - Contains functions and structures to allow you to query **MoltenVK** + performance activity, and Metal capabilities on the platform. _**NOTE:**_ THESE + FUNCTIONS ARE NOT SUPPORTED BY THE *Vulkan Loader and Layers*, AND CAN ONLY BE USED + WHEN **MoltenVK** IS LINKED DIRECTLY TO YOUR APPLICATION. + +- `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 *Vulkan* and *Metal* datatypes automatically (using the functions declared + in this header). These functions are exposed in this header as a convienience for your own + purposes such as interacting with *Metal* directly, or simply logging data values. ### Configuring MoltenVK -The `VK_MVK_moltenvk` *Vulkan* extension provides the ability to configure and optimize -**MoltenVK** for your particular application runtime requirements. +The `mvk_config.h` header file provides the ability to configure and optimize **MoltenVK** +for your particular application runtime requirements. This can be helpful in situtations +where *Metal* behavior is different than *Vulkan* behavior, and the results or performance +you receive can depend on how **MoltenVK** works around those differences, which, in turn, may +depend on how you are using *Vulkan*. Different apps might benefit differently in this handling. There are three mechanisms for setting the values of the **MoltenVK** configuration parameters: @@ -488,9 +490,9 @@ by a corresponding environment variable, or if the environment variable is not s by a corresponding build setting at the time **MoltenVK** is compiled. The environment variable and build setting for each configuration parameter share the same name. -See the description of the `MVKConfiguration` structure parameters and corresponding environment -variables in the `vk_mvk_moltenvk.h` file for more info about configuring and optimizing -**MoltenVK** at runtime or build time. +See the description of the `MVKConfiguration` structure parameters and corresponding +environment variables in the `mvk_config.h` file for more info about configuring and +optimizing **MoltenVK** at runtime or build time. @@ -582,6 +584,20 @@ than when using an internal compositor, which increases the risk that a swapchai vailable when you request it, resulting in frame delays and visual stuttering. + +### Timestamping + +On non-Apple Silicon devices (older Mac devices), the GPU can switch power and performance +states as required by usage. This affects the GPU timestamps retrievable through the Vulkan +API. As a result, the value of `VkPhysicalDeviceLimits::timestampPeriod` can vary over time. +Consider calling `vkGetPhysicalDeviceProperties()`, when needed, and retrieve the current +value of `VkPhysicalDeviceLimits::timestampPeriod`, to help you calibrate recent GPU +timestamps queried through the Vulkan API. + +This is not needed on Apple Silicon devices, where all GPU timestamps are always returned +as nanoseconds, regardless of variations in power and performance states as the app runs. + + ### Xcode Configuration diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index ef3d3eb3d..82e9b1558 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -13,6 +13,103 @@ Copyright (c) 2015-2023 [The Brenwill Workshop Ltd.](http://www.brenwill.com) +MoltenVK 1.2.6 +-------------- + +Released TBD + +- Fix rare case where vertex attribute buffers are not bound to Metal + when no other bindings change between pipelines. + + + +MoltenVK 1.2.5 +-------------- + +Released 2023/08/15 + +- Add support for extensions: + - `VK_KHR_incremental_present` + - `VK_KHR_shader_non_semantic_info` + - `VK_EXT_4444_formats` + - `VK_EXT_calibrated_timestamps` + - `VK_EXT_pipeline_creation_feedback` + - `VK_EXT_shader_demote_to_helper_invocation` + - `VK_EXT_shader_subgroup_ballot` + - `VK_EXT_shader_subgroup_vote` +- Add support for `VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN`. +- Support building MoltenVK for visionOS. +- Ensure non-dispatch compute commands don't interfere with compute encoding state used by dispatch commands. +- Support maximizing the concurrent executing compilation tasks via `MVKConfiguration::shouldMaximizeConcurrentCompilation` +- Support `VK_PRESENT_MODE_IMMEDIATE_KHR` if `VkPresentTimeGOOGLE::desiredPresentTime` is zero. +- Add support for `VK_PRESENT_MODE_IMMEDIATE_KHR` to macOS Cube demo. +- Allow both `renderPass` and `VkPipelineRenderingCreateInfo` to be missing. +- Fix sync delay between calls to `vkQueueSubmit()` on non-Apple-Silicon devices. +- Ensure Xcode simulator always uses 256B buffer alignment. +- Don't attempt to force the window system to use the same high-power GPU as the app, on every swapchain creation. +- Log more info about SPIR-V to MSL conversion errors. +- Implement Deferred Host Operations. +- Support _MSL Version 3.1_. +- Drop official support for using *Xcode 11* to build MoltenVK. +- To allow building MoltenVK without an internet connection, don't fetch a submodule if the commit is already known. +- Update dependency libraries to match _Vulkan SDK 1.3.261_. +- Update to latest SPIRV-Cross: + - MSL: Fix argument buffer padding when content includes arrays. + - MSL: ray-query intersection params + - MSL: Support `SPV_KHR_shader_ballot` and `SPV_KHR_subgroup_vote`. + - Skip line directives when emitting loop condition blocks. + - MSL: Consider changed array types for array-of-constant-bool in struct. + - MSL: Consider bool-short remapping for constant expressions as well. + - Minor cleanup in constant_expression(). + - MSL: Add test for bool-in-struct edge cases. + - MSL: Handle more complex array copy scenarios with bool <-> short. + - MSL: Handle stores to struct bool[]. + - MSL: Consider bool/short remapping when dealing with composites. + - MSL: fix function constant deduplication misfire + + + +MoltenVK 1.2.4 +-------------- + +Released 2023/05/23 + +- Add support for extensions: + - `VK_KHR_map_memory2` +- Deprecate the obsolete and non-standard `VK_MVK_moltenvk` extension. + - Add `mvk_config.h`, `mvk_private_api.h`, and `mvk_deprecated_api.h`, and deprecate `vk_mvk_moltenvk.h`. +- Support BC compression on iOS/tvOS where available (iOS/tvOS 16.4 and above and supported by the GPU). +- Support separate depth and stencil attachments during dynamic rendering. +- Fix memory leak when waiting on timeline semaphores. +- Fix race condition when updating values in `VkPastPresentationTimingGOOGLE`, + and ensure swapchain image presented time is always populated when requested. +- Report error, but do not fail on request for timestamp query pool that is too + large for `MTLCounterSampleBuffer`, and fall back to emulation via CPU timestamps. +- Ensure shaders that use `PhysicalStorageBufferAddresses` encode the use of the associated `MTLBuffer`. +- Disable pipeline cache compression prior to macOS 10.15 and iOS/tvOS 13.0. +- Accumulate render stages when a resource is used by multiple descriptor bindings. +- Respect the bind point supplied to `vkCmdBindDescriptorSets()` / `vkCmdPushDescriptorSets()`. +- Check if shader compiled before adding it to a pipeline, to avoid Metal validation error. +- Identify each unsupported device feature flag that the app attempts to enable. +- Populate `deviceUUID` from `MTLDevice` location and peer group info, + which should be unique, and constant across OS reboots. +- Populate `deviceLUID` from `MTLDevice.registryID`. +- Avoid Metal validation warning when depth component swizzled away. +- Fix depth clamp and texture swizzle feature discovery on simulator builds. +- Advertise `VK_KHR_depth_stencil_resolve` extension on all devices. +- For correctness, set `VkPhysicalDeviceLimits::lineWidthGranularity` to `1`. +- Improve GitHub CI production of binary artifacts on submission and release. +- Update dependency libraries to match _Vulkan SDK 1.3.250_. +- Update to latest SPIRV-Cross: + - MSL: Fix for argument buffer index compare when invalid. + - MSL: Fix dref lod workaround on combined texture/samplers. + - MSL: Do not override variable name with v_ identifier. + - MSL: Use name_id consistently in argument declaration. + - MSL: Don't hit array copy path for pointer to array. + - MSL: Use templated array type when emitting BDA to arrays. + + + MoltenVK 1.2.3 -------------- diff --git a/ExternalDependencies.xcodeproj/project.pbxproj b/ExternalDependencies.xcodeproj/project.pbxproj index b450046ef..fdbcf75f2 100644 --- a/ExternalDependencies.xcodeproj/project.pbxproj +++ b/ExternalDependencies.xcodeproj/project.pbxproj @@ -63,6 +63,20 @@ name = ExternalDependencies; productName = "ExternalLibraries-macOS"; }; + DCFD7EC12A45BAAA007BBBF7 /* ExternalDependencies-xrOS */ = { + isa = PBXAggregateTarget; + buildConfigurationList = DCFD7EC92A45BAAA007BBBF7 /* Build configuration list for PBXAggregateTarget "ExternalDependencies-xrOS" */; + buildPhases = ( + DCFD7EC82A45BAAA007BBBF7 /* Package Libraries */, + ); + dependencies = ( + DCFD7ECD2A45BC08007BBBF7 /* PBXTargetDependency */, + DCFD7ECF2A45BC0C007BBBF7 /* PBXTargetDependency */, + DCFD7ED12A45BC10007BBBF7 /* PBXTargetDependency */, + ); + name = "ExternalDependencies-xrOS"; + productName = "ExternalLibraries-macOS"; + }; /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ @@ -1698,6 +1712,550 @@ A9F7BCF529425A1B00B30DA7 /* decoration.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B35829425A1800B30DA7 /* decoration.h */; }; A9F7BCF629425A1B00B30DA7 /* decoration.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B35829425A1800B30DA7 /* decoration.h */; }; A9F7BCF729425A1B00B30DA7 /* decoration.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B35829425A1800B30DA7 /* decoration.h */; }; + DCFD7C8B2A45BA7D007BBBF7 /* spirv_cfg.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A976290921CC60BC00B52A68 /* spirv_cfg.hpp */; }; + DCFD7C8C2A45BA7D007BBBF7 /* spirv_cross_parsed_ir.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A976290821CC60BC00B52A68 /* spirv_cross_parsed_ir.hpp */; }; + DCFD7C8D2A45BA7D007BBBF7 /* spirv_common.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A976290721CC60BC00B52A68 /* spirv_common.hpp */; }; + DCFD7C8E2A45BA7D007BBBF7 /* spirv_glsl.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A976290A21CC60BC00B52A68 /* spirv_glsl.hpp */; }; + DCFD7C8F2A45BA7D007BBBF7 /* spirv_parser.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A976290C21CC60BC00B52A68 /* spirv_parser.hpp */; }; + DCFD7C902A45BA7D007BBBF7 /* spirv_cross_util.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A9717C0B26EE8C730041AE82 /* spirv_cross_util.hpp */; }; + DCFD7C912A45BA7D007BBBF7 /* spirv_cross_containers.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A9717C0326EE8C570041AE82 /* spirv_cross_containers.hpp */; }; + DCFD7C922A45BA7D007BBBF7 /* spirv.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A9717C0F26EE8C9D0041AE82 /* spirv.hpp */; }; + DCFD7C932A45BA7D007BBBF7 /* spirv_cross_error_handling.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A9717C0426EE8C570041AE82 /* spirv_cross_error_handling.hpp */; }; + DCFD7C942A45BA7D007BBBF7 /* spirv_cross.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A976290321CC60BC00B52A68 /* spirv_cross.hpp */; }; + DCFD7C952A45BA7D007BBBF7 /* spirv_msl.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A976290221CC60BC00B52A68 /* spirv_msl.hpp */; }; + DCFD7C962A45BA7D007BBBF7 /* spirv_reflect.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 450A4F63221C5A95007203D7 /* spirv_reflect.hpp */; }; + DCFD7C982A45BA7D007BBBF7 /* spirv_msl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A976290D21CC60BC00B52A68 /* spirv_msl.cpp */; }; + DCFD7C992A45BA7D007BBBF7 /* spirv_parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A976290421CC60BC00B52A68 /* spirv_parser.cpp */; }; + DCFD7C9A2A45BA7D007BBBF7 /* spirv_cfg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A976290B21CC60BC00B52A68 /* spirv_cfg.cpp */; }; + DCFD7C9B2A45BA7D007BBBF7 /* spirv_cross.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A976290521CC60BC00B52A68 /* spirv_cross.cpp */; }; + DCFD7C9C2A45BA7D007BBBF7 /* spirv_reflect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 450A4F64221C5A95007203D7 /* spirv_reflect.cpp */; }; + DCFD7C9D2A45BA7D007BBBF7 /* spirv_glsl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A976290621CC60BC00B52A68 /* spirv_glsl.cpp */; }; + DCFD7C9E2A45BA7D007BBBF7 /* spirv_cross_parsed_ir.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A976290E21CC60BC00B52A68 /* spirv_cross_parsed_ir.cpp */; }; + DCFD7CA62A45BA92007BBBF7 /* propagateNoContraction.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F99626865A550006F71B /* propagateNoContraction.h */; }; + DCFD7CA72A45BA92007BBBF7 /* disassemble.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F95626865A550006F71B /* disassemble.h */; }; + DCFD7CA82A45BA92007BBBF7 /* PpContext.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F9B126865A550006F71B /* PpContext.h */; }; + DCFD7CA92A45BA92007BBBF7 /* InfoSink.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F98226865A550006F71B /* InfoSink.h */; }; + DCFD7CAA2A45BA92007BBBF7 /* bitutils.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F95526865A550006F71B /* bitutils.h */; }; + DCFD7CAB2A45BA92007BBBF7 /* SpvBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F94426865A550006F71B /* SpvBuilder.h */; }; + DCFD7CAC2A45BA92007BBBF7 /* GLSL.std.450.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F95826865A550006F71B /* GLSL.std.450.h */; }; + DCFD7CAD2A45BA92007BBBF7 /* Logger.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F95C26865A550006F71B /* Logger.h */; }; + DCFD7CAE2A45BA92007BBBF7 /* pch.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F98A26865A550006F71B /* pch.h */; }; + DCFD7CAF2A45BA92007BBBF7 /* LiveTraverser.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F9A226865A550006F71B /* LiveTraverser.h */; }; + DCFD7CB02A45BA92007BBBF7 /* spvIR.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F95426865A550006F71B /* spvIR.h */; }; + DCFD7CB12A45BA92007BBBF7 /* glslang_c_shader_types.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F97B26865A550006F71B /* glslang_c_shader_types.h */; }; + DCFD7CB22A45BA92007BBBF7 /* attribute.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F9A726865A550006F71B /* attribute.h */; }; + DCFD7CB32A45BA92007BBBF7 /* Scan.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F9B726865A550006F71B /* Scan.h */; }; + DCFD7CB42A45BA92007BBBF7 /* Types.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F97926865A550006F71B /* Types.h */; }; + DCFD7CB52A45BA92007BBBF7 /* PoolAlloc.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F98326865A550006F71B /* PoolAlloc.h */; }; + DCFD7CB62A45BA92007BBBF7 /* InitializeGlobals.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F97D26865A550006F71B /* InitializeGlobals.h */; }; + DCFD7CB72A45BA92007BBBF7 /* parseVersions.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F98726865A550006F71B /* parseVersions.h */; }; + DCFD7CB82A45BA92007BBBF7 /* osinclude.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F96E26865A550006F71B /* osinclude.h */; }; + DCFD7CB92A45BA92007BBBF7 /* gl_types.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F98826865A550006F71B /* gl_types.h */; }; + DCFD7CBA2A45BA92007BBBF7 /* localintermediate.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F98D26865A550006F71B /* localintermediate.h */; }; + DCFD7CBB2A45BA92007BBBF7 /* GLSL.ext.AMD.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F94C26865A550006F71B /* GLSL.ext.AMD.h */; }; + DCFD7CBC2A45BA92007BBBF7 /* reflection.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F9B626865A550006F71B /* reflection.h */; }; + DCFD7CBD2A45BA92007BBBF7 /* ShHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F97E26865A550006F71B /* ShHandle.h */; }; + DCFD7CBE2A45BA92007BBBF7 /* iomapper.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F98C26865A550006F71B /* iomapper.h */; }; + DCFD7CBF2A45BA92007BBBF7 /* GLSL.ext.NV.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F95226865A550006F71B /* GLSL.ext.NV.h */; }; + DCFD7CC02A45BA92007BBBF7 /* Versions.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F99726865A550006F71B /* Versions.h */; }; + DCFD7CC12A45BA92007BBBF7 /* SPVRemapper.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F94326865A550006F71B /* SPVRemapper.h */; }; + DCFD7CC22A45BA92007BBBF7 /* ConstantUnion.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F98126865A550006F71B /* ConstantUnion.h */; }; + DCFD7CC32A45BA92007BBBF7 /* doc.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F94D26865A550006F71B /* doc.h */; }; + DCFD7CC42A45BA92007BBBF7 /* Initialize.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F9A326865A550006F71B /* Initialize.h */; }; + DCFD7CC52A45BA92007BBBF7 /* GLSL.ext.EXT.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F95026865A550006F71B /* GLSL.ext.EXT.h */; }; + DCFD7CC62A45BA92007BBBF7 /* ResourceLimits.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F97626865A550006F71B /* ResourceLimits.h */; }; + DCFD7CC72A45BA92007BBBF7 /* Common.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F98026865A550006F71B /* Common.h */; }; + DCFD7CC82A45BA92007BBBF7 /* GLSL.ext.KHR.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F95126865A550006F71B /* GLSL.ext.KHR.h */; }; + DCFD7CC92A45BA92007BBBF7 /* intermediate.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F97A26865A550006F71B /* intermediate.h */; }; + DCFD7CCA2A45BA92007BBBF7 /* ShaderLang.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F9B926865A550006F71B /* ShaderLang.h */; }; + DCFD7CCB2A45BA92007BBBF7 /* ScanContext.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F98B26865A550006F71B /* ScanContext.h */; }; + DCFD7CCC2A45BA92007BBBF7 /* PpTokens.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F9AF26865A550006F71B /* PpTokens.h */; }; + DCFD7CCD2A45BA92007BBBF7 /* BaseTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F97C26865A550006F71B /* BaseTypes.h */; }; + DCFD7CCE2A45BA92007BBBF7 /* hex_float.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F95B26865A550006F71B /* hex_float.h */; }; + DCFD7CCF2A45BA92007BBBF7 /* SpvTools.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F94926865A550006F71B /* SpvTools.h */; }; + DCFD7CD02A45BA92007BBBF7 /* RemoveTree.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F99026865A550006F71B /* RemoveTree.h */; }; + DCFD7CD12A45BA92007BBBF7 /* SymbolTable.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F99D26865A550006F71B /* SymbolTable.h */; }; + DCFD7CD22A45BA92007BBBF7 /* arrays.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F97F26865A550006F71B /* arrays.h */; }; + DCFD7CD32A45BA92007BBBF7 /* spirv.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A997F94E26865A550006F71B /* spirv.hpp */; }; + DCFD7CD42A45BA92007BBBF7 /* glslang_c_interface.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F97726865A550006F71B /* glslang_c_interface.h */; }; + DCFD7CD52A45BA92007BBBF7 /* GlslangToSpv.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F95726865A550006F71B /* GlslangToSpv.h */; }; + DCFD7CD62A45BA92007BBBF7 /* SpirvIntrinsics.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F97826865A550006F71B /* SpirvIntrinsics.h */; }; + DCFD7CD72A45BA92007BBBF7 /* NonSemanticDebugPrintf.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F94226865A550006F71B /* NonSemanticDebugPrintf.h */; }; + DCFD7CD82A45BA92007BBBF7 /* glslang_tab.cpp.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F9A126865A550006F71B /* glslang_tab.cpp.h */; }; + DCFD7CD92A45BA92007BBBF7 /* ParseHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F9AC26865A550006F71B /* ParseHelper.h */; }; + DCFD7CDA2A45BA92007BBBF7 /* InitializeDll.h in Headers */ = {isa = PBXBuildFile; fileRef = A997F96126865A550006F71B /* InitializeDll.h */; }; + DCFD7CDC2A45BA92007BBBF7 /* ParseHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F98626865A550006F71B /* ParseHelper.cpp */; }; + DCFD7CDD2A45BA92007BBBF7 /* doc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F95D26865A550006F71B /* doc.cpp */; }; + DCFD7CDE2A45BA92007BBBF7 /* attribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F9A426865A550006F71B /* attribute.cpp */; }; + DCFD7CDF2A45BA92007BBBF7 /* IntermTraverse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F99826865A550006F71B /* IntermTraverse.cpp */; }; + DCFD7CE02A45BA92007BBBF7 /* Versions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F9A826865A550006F71B /* Versions.cpp */; }; + DCFD7CE12A45BA92007BBBF7 /* reflection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F9A526865A550006F71B /* reflection.cpp */; }; + DCFD7CE22A45BA92007BBBF7 /* spirv_c_interface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F94826865A550006F71B /* spirv_c_interface.cpp */; }; + DCFD7CE32A45BA92007BBBF7 /* propagateNoContraction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F98926865A550006F71B /* propagateNoContraction.cpp */; }; + DCFD7CE42A45BA92007BBBF7 /* glslang_c_interface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F97426865A550006F71B /* glslang_c_interface.cpp */; }; + DCFD7CE52A45BA92007BBBF7 /* SPVRemapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F95926865A550006F71B /* SPVRemapper.cpp */; }; + DCFD7CE62A45BA92007BBBF7 /* SpvTools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F94A26865A550006F71B /* SpvTools.cpp */; }; + DCFD7CE72A45BA92007BBBF7 /* Logger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F95A26865A550006F71B /* Logger.cpp */; }; + DCFD7CE82A45BA92007BBBF7 /* ossource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F96C26865A550006F71B /* ossource.cpp */; }; + DCFD7CE92A45BA92007BBBF7 /* SpvPostProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F94626865A550006F71B /* SpvPostProcess.cpp */; }; + DCFD7CEA2A45BA92007BBBF7 /* Scan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F98E26865A550006F71B /* Scan.cpp */; }; + DCFD7CEB2A45BA92007BBBF7 /* PpScanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F9B426865A550006F71B /* PpScanner.cpp */; }; + DCFD7CEC2A45BA92007BBBF7 /* PpContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F9B326865A550006F71B /* PpContext.cpp */; }; + DCFD7CED2A45BA92007BBBF7 /* disassemble.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F95E26865A550006F71B /* disassemble.cpp */; }; + DCFD7CEE2A45BA92007BBBF7 /* SpirvIntrinsics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F99426865A550006F71B /* SpirvIntrinsics.cpp */; }; + DCFD7CEF2A45BA92007BBBF7 /* linkValidate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F9AA26865A550006F71B /* linkValidate.cpp */; }; + DCFD7CF02A45BA92007BBBF7 /* parseConst.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F99526865A550006F71B /* parseConst.cpp */; }; + DCFD7CF12A45BA92007BBBF7 /* InitializeDll.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F96226865A550006F71B /* InitializeDll.cpp */; }; + DCFD7CF22A45BA92007BBBF7 /* Link.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F9CD26865A550006F71B /* Link.cpp */; }; + DCFD7CF32A45BA92007BBBF7 /* iomapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F99A26865A550006F71B /* iomapper.cpp */; }; + DCFD7CF42A45BA92007BBBF7 /* ParseContextBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F9B526865A550006F71B /* ParseContextBase.cpp */; }; + DCFD7CF52A45BA92007BBBF7 /* PpTokens.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F9B226865A550006F71B /* PpTokens.cpp */; }; + DCFD7CF62A45BA92007BBBF7 /* GlslangToSpv.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F95326865A550006F71B /* GlslangToSpv.cpp */; }; + DCFD7CF72A45BA92007BBBF7 /* limits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F99326865A550006F71B /* limits.cpp */; }; + DCFD7CF82A45BA92007BBBF7 /* glslang_tab.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F99226865A550006F71B /* glslang_tab.cpp */; }; + DCFD7CF92A45BA92007BBBF7 /* Constant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F9A926865A550006F71B /* Constant.cpp */; }; + DCFD7CFA2A45BA92007BBBF7 /* InfoSink.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F99E26865A550006F71B /* InfoSink.cpp */; }; + DCFD7CFB2A45BA92007BBBF7 /* RemoveTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F9A626865A550006F71B /* RemoveTree.cpp */; }; + DCFD7CFC2A45BA92007BBBF7 /* intermOut.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F99926865A550006F71B /* intermOut.cpp */; }; + DCFD7CFD2A45BA92007BBBF7 /* PoolAlloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F99B26865A550006F71B /* PoolAlloc.cpp */; }; + DCFD7CFE2A45BA92007BBBF7 /* Initialize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F99126865A550006F71B /* Initialize.cpp */; }; + DCFD7CFF2A45BA92007BBBF7 /* ShaderLang.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F99C26865A550006F71B /* ShaderLang.cpp */; }; + DCFD7D002A45BA92007BBBF7 /* Intermediate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F99F26865A550006F71B /* Intermediate.cpp */; }; + DCFD7D012A45BA92007BBBF7 /* InReadableOrder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F94B26865A550006F71B /* InReadableOrder.cpp */; }; + DCFD7D022A45BA92007BBBF7 /* PpAtom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F9AE26865A550006F71B /* PpAtom.cpp */; }; + DCFD7D032A45BA92007BBBF7 /* SpvBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F94F26865A550006F71B /* SpvBuilder.cpp */; }; + DCFD7D042A45BA92007BBBF7 /* CodeGen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F9CC26865A550006F71B /* CodeGen.cpp */; }; + DCFD7D052A45BA92007BBBF7 /* SymbolTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F9A026865A550006F71B /* SymbolTable.cpp */; }; + DCFD7D062A45BA92007BBBF7 /* Pp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A997F9B026865A550006F71B /* Pp.cpp */; }; + DCFD7D0E2A45BA9C007BBBF7 /* replace_invalid_opc.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0BC29425A1700B30DA7 /* replace_invalid_opc.h */; }; + DCFD7D0F2A45BA9C007BBBF7 /* convert_to_sampled_image_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0EE29425A1700B30DA7 /* convert_to_sampled_image_pass.h */; }; + DCFD7D102A45BA9C007BBBF7 /* text_handler.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B08C29425A1700B30DA7 /* text_handler.h */; }; + DCFD7D112A45BA9C007BBBF7 /* types.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0DA29425A1700B30DA7 /* types.h */; }; + DCFD7D122A45BA9C007BBBF7 /* dead_insert_elim_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B10E29425A1800B30DA7 /* dead_insert_elim_pass.h */; }; + DCFD7D132A45BA9C007BBBF7 /* parse_number.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B01F29425A1700B30DA7 /* parse_number.h */; }; + DCFD7D142A45BA9C007BBBF7 /* make_unique.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B02129425A1700B30DA7 /* make_unique.h */; }; + DCFD7D152A45BA9C007BBBF7 /* function.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B17A29425A1800B30DA7 /* function.h */; }; + DCFD7D162A45BA9C007BBBF7 /* inst_debug_printf_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B10A29425A1800B30DA7 /* inst_debug_printf_pass.h */; }; + DCFD7D172A45BA9C007BBBF7 /* block_merge_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0E029425A1700B30DA7 /* block_merge_pass.h */; }; + DCFD7D182A45BA9C007BBBF7 /* scalar_analysis.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0B529425A1700B30DA7 /* scalar_analysis.h */; }; + DCFD7D192A45BA9C007BBBF7 /* composite.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0AA29425A1700B30DA7 /* composite.h */; }; + DCFD7D1A2A45BA9C007BBBF7 /* enum_set.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B01729425A1700B30DA7 /* enum_set.h */; }; + DCFD7D1B2A45BA9C007BBBF7 /* lints.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B01529425A1700B30DA7 /* lints.h */; }; + DCFD7D1C2A45BA9C007BBBF7 /* freeze_spec_constant_value_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B11029425A1800B30DA7 /* freeze_spec_constant_value_pass.h */; }; + DCFD7D1D2A45BA9C007BBBF7 /* reduction_opportunity.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B05F29425A1700B30DA7 /* reduction_opportunity.h */; }; + DCFD7D1E2A45BA9C007BBBF7 /* ir_context.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0CB29425A1700B30DA7 /* ir_context.h */; }; + DCFD7D1F2A45BA9C007BBBF7 /* loop_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B16029425A1800B30DA7 /* loop_utils.h */; }; + DCFD7D202A45BA9C007BBBF7 /* relax_float_ops_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0EA29425A1700B30DA7 /* relax_float_ops_pass.h */; }; + DCFD7D212A45BA9C007BBBF7 /* pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B13B29425A1800B30DA7 /* pass.h */; }; + DCFD7D222A45BA9C007BBBF7 /* inline_opaque_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0A529425A1700B30DA7 /* inline_opaque_pass.h */; }; + DCFD7D232A45BA9C007BBBF7 /* strength_reduction_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B10729425A1800B30DA7 /* strength_reduction_pass.h */; }; + DCFD7D242A45BA9C007BBBF7 /* pch_source.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B07329425A1700B30DA7 /* pch_source.h */; }; + DCFD7D252A45BA9C007BBBF7 /* graphics_robust_access_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0B029425A1700B30DA7 /* graphics_robust_access_pass.h */; }; + DCFD7D262A45BA9C007BBBF7 /* scalar_analysis_nodes.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B14329425A1800B30DA7 /* scalar_analysis_nodes.h */; }; + DCFD7D272A45BA9C007BBBF7 /* operand_to_const_reduction_opportunity_finder.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B03829425A1700B30DA7 /* operand_to_const_reduction_opportunity_finder.h */; }; + DCFD7D282A45BA9C007BBBF7 /* basic_block.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0DD29425A1700B30DA7 /* basic_block.h */; }; + DCFD7D292A45BA9C007BBBF7 /* strip_nonsemantic_info_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0A229425A1700B30DA7 /* strip_nonsemantic_info_pass.h */; }; + DCFD7D2A2A45BA9C007BBBF7 /* fold.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B13F29425A1800B30DA7 /* fold.h */; }; + DCFD7D2B2A45BA9C007BBBF7 /* instruction.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B34E29425A1800B30DA7 /* instruction.h */; }; + DCFD7D2C2A45BA9C007BBBF7 /* unify_const_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0D729425A1700B30DA7 /* unify_const_pass.h */; }; + DCFD7D2D2A45BA9C007BBBF7 /* vector_dce.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B16E29425A1800B30DA7 /* vector_dce.h */; }; + DCFD7D2E2A45BA9C007BBBF7 /* structured_construct_to_block_reduction_opportunity.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B03629425A1700B30DA7 /* structured_construct_to_block_reduction_opportunity.h */; }; + DCFD7D2F2A45BA9C007BBBF7 /* spirv_target_env.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B02E29425A1700B30DA7 /* spirv_target_env.h */; }; + DCFD7D302A45BA9C007BBBF7 /* loop_fusion.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0A629425A1700B30DA7 /* loop_fusion.h */; }; + DCFD7D312A45BA9C007BBBF7 /* print.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B09A29425A1700B30DA7 /* print.h */; }; + DCFD7D322A45BA9C007BBBF7 /* structured_loop_to_selection_reduction_opportunity.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B04A29425A1700B30DA7 /* structured_loop_to_selection_reduction_opportunity.h */; }; + DCFD7D332A45BA9C007BBBF7 /* dominator_tree.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B18429425A1800B30DA7 /* dominator_tree.h */; }; + DCFD7D342A45BA9C007BBBF7 /* dead_branch_elim_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B14129425A1800B30DA7 /* dead_branch_elim_pass.h */; }; + DCFD7D352A45BA9C007BBBF7 /* ccp_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B17829425A1800B30DA7 /* ccp_pass.h */; }; + DCFD7D362A45BA9C007BBBF7 /* validate.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B33D29425A1800B30DA7 /* validate.h */; }; + DCFD7D372A45BA9C007BBBF7 /* construct.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B32829425A1800B30DA7 /* construct.h */; }; + DCFD7D382A45BA9C007BBBF7 /* null_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B15329425A1800B30DA7 /* null_pass.h */; }; + DCFD7D392A45BA9C007BBBF7 /* constants.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B12429425A1800B30DA7 /* constants.h */; }; + DCFD7D3A2A45BA9C007BBBF7 /* validation_state.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B33729425A1800B30DA7 /* validation_state.h */; }; + DCFD7D3B2A45BA9C007BBBF7 /* instruction.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B16A29425A1800B30DA7 /* instruction.h */; }; + DCFD7D3C2A45BA9C007BBBF7 /* loop_unswitch_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B16529425A1800B30DA7 /* loop_unswitch_pass.h */; }; + DCFD7D3D2A45BA9C007BBBF7 /* tree_iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0AE29425A1700B30DA7 /* tree_iterator.h */; }; + DCFD7D3E2A45BA9C007BBBF7 /* remove_struct_member_reduction_opportunity.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B04629425A1700B30DA7 /* remove_struct_member_reduction_opportunity.h */; }; + DCFD7D3F2A45BA9C007BBBF7 /* validate_scopes.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B34129425A1800B30DA7 /* validate_scopes.h */; }; + DCFD7D402A45BA9C007BBBF7 /* passes.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B14829425A1800B30DA7 /* passes.h */; }; + DCFD7D412A45BA9C007BBBF7 /* interp_fixup_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B10329425A1800B30DA7 /* interp_fixup_pass.h */; }; + DCFD7D422A45BA9C007BBBF7 /* validate_memory_semantics.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B34329425A1800B30DA7 /* validate_memory_semantics.h */; }; + DCFD7D432A45BA9C007BBBF7 /* hash_combine.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B02429425A1700B30DA7 /* hash_combine.h */; }; + DCFD7D442A45BA9C007BBBF7 /* conditional_branch_to_simple_conditional_branch_opportunity_finder.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B06029425A1700B30DA7 /* conditional_branch_to_simple_conditional_branch_opportunity_finder.h */; }; + DCFD7D452A45BA9C007BBBF7 /* strip_debug_info_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0B629425A1700B30DA7 /* strip_debug_info_pass.h */; }; + DCFD7D462A45BA9C007BBBF7 /* pch_source_opt.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B15829425A1800B30DA7 /* pch_source_opt.h */; }; + DCFD7D472A45BA9C007BBBF7 /* merge_blocks_reduction_opportunity_finder.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B05229425A1700B30DA7 /* merge_blocks_reduction_opportunity_finder.h */; }; + DCFD7D482A45BA9C007BBBF7 /* reduction_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B06F29425A1700B30DA7 /* reduction_pass.h */; }; + DCFD7D492A45BA9C007BBBF7 /* local_single_store_elim_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0B129425A1700B30DA7 /* local_single_store_elim_pass.h */; }; + DCFD7D4A2A45BA9C007BBBF7 /* latest_version_opencl_std_header.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B07029425A1700B30DA7 /* latest_version_opencl_std_header.h */; }; + DCFD7D4B2A45BA9C007BBBF7 /* remove_block_reduction_opportunity.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B03329425A1700B30DA7 /* remove_block_reduction_opportunity.h */; }; + DCFD7D4C2A45BA9C007BBBF7 /* remove_function_reduction_opportunity_finder.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B05929425A1700B30DA7 /* remove_function_reduction_opportunity_finder.h */; }; + DCFD7D4D2A45BA9C007BBBF7 /* instruction.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B31A29425A1800B30DA7 /* instruction.h */; }; + DCFD7D4E2A45BA9C007BBBF7 /* eliminate_dead_functions_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B13D29425A1800B30DA7 /* eliminate_dead_functions_pass.h */; }; + DCFD7D4F2A45BA9C007BBBF7 /* bit_vector.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B02829425A1700B30DA7 /* bit_vector.h */; }; + DCFD7D502A45BA9C007BBBF7 /* assembly_grammar.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B00F29425A1700B30DA7 /* assembly_grammar.h */; }; + DCFD7D512A45BA9C007BBBF7 /* loop_dependence.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B11C29425A1800B30DA7 /* loop_dependence.h */; }; + DCFD7D522A45BA9C007BBBF7 /* simple_conditional_branch_to_branch_reduction_opportunity.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B03D29425A1700B30DA7 /* simple_conditional_branch_to_branch_reduction_opportunity.h */; }; + DCFD7D532A45BA9C007BBBF7 /* folding_rules.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B13C29425A1800B30DA7 /* folding_rules.h */; }; + DCFD7D542A45BA9C007BBBF7 /* eliminate_dead_members_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B11529425A1800B30DA7 /* eliminate_dead_members_pass.h */; }; + DCFD7D552A45BA9C007BBBF7 /* reduction_util.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B06629425A1700B30DA7 /* reduction_util.h */; }; + DCFD7D562A45BA9C007BBBF7 /* table.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B18929425A1800B30DA7 /* table.h */; }; + DCFD7D572A45BA9C007BBBF7 /* basic_block.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B32F29425A1800B30DA7 /* basic_block.h */; }; + DCFD7D582A45BA9C007BBBF7 /* remove_block_reduction_opportunity_finder.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B06429425A1700B30DA7 /* remove_block_reduction_opportunity_finder.h */; }; + DCFD7D592A45BA9C007BBBF7 /* remove_dontinline_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0E929425A1700B30DA7 /* remove_dontinline_pass.h */; }; + DCFD7D5A2A45BA9C007BBBF7 /* operand_to_dominating_id_reduction_opportunity_finder.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B03429425A1700B30DA7 /* operand_to_dominating_id_reduction_opportunity_finder.h */; }; + DCFD7D5B2A45BA9C007BBBF7 /* operand.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B08029425A1700B30DA7 /* operand.h */; }; + DCFD7D5C2A45BA9C007BBBF7 /* disassemble.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B09C29425A1700B30DA7 /* disassemble.h */; }; + DCFD7D5D2A45BA9C007BBBF7 /* remove_unused_instruction_reduction_opportunity_finder.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B04C29425A1700B30DA7 /* remove_unused_instruction_reduction_opportunity_finder.h */; }; + DCFD7D5E2A45BA9C007BBBF7 /* value_number_table.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B11D29425A1800B30DA7 /* value_number_table.h */; }; + DCFD7D5F2A45BA9C007BBBF7 /* small_vector.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B02329425A1700B30DA7 /* small_vector.h */; }; + DCFD7D602A45BA9C007BBBF7 /* log.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B13129425A1800B30DA7 /* log.h */; }; + DCFD7D612A45BA9C007BBBF7 /* ilist_node.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B02029425A1700B30DA7 /* ilist_node.h */; }; + DCFD7D622A45BA9C007BBBF7 /* feature_manager.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B17F29425A1800B30DA7 /* feature_manager.h */; }; + DCFD7D632A45BA9C007BBBF7 /* loop_fission.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B12E29425A1800B30DA7 /* loop_fission.h */; }; + DCFD7D642A45BA9C007BBBF7 /* interface_var_sroa.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0AF29425A1700B30DA7 /* interface_var_sroa.h */; }; + DCFD7D652A45BA9C007BBBF7 /* licm_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B17629425A1800B30DA7 /* licm_pass.h */; }; + DCFD7D662A45BA9C007BBBF7 /* convert_to_half_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0E829425A1700B30DA7 /* convert_to_half_pass.h */; }; + DCFD7D672A45BA9C007BBBF7 /* structured_construct_to_block_reduction_opportunity_finder.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B03B29425A1700B30DA7 /* structured_construct_to_block_reduction_opportunity_finder.h */; }; + DCFD7D682A45BA9C007BBBF7 /* fold_spec_constant_op_and_composite_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0DB29425A1700B30DA7 /* fold_spec_constant_op_and_composite_pass.h */; }; + DCFD7D692A45BA9C007BBBF7 /* cfg.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B16629425A1800B30DA7 /* cfg.h */; }; + DCFD7D6A2A45BA9C007BBBF7 /* remove_selection_reduction_opportunity.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B04F29425A1700B30DA7 /* remove_selection_reduction_opportunity.h */; }; + DCFD7D6B2A45BA9C007BBBF7 /* opcode.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B31C29425A1800B30DA7 /* opcode.h */; }; + DCFD7D6C2A45BA9C007BBBF7 /* flatten_decoration_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B11F29425A1800B30DA7 /* flatten_decoration_pass.h */; }; + DCFD7D6D2A45BA9C007BBBF7 /* private_to_local_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0E729425A1700B30DA7 /* private_to_local_pass.h */; }; + DCFD7D6E2A45BA9C007BBBF7 /* wrap_opkill.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0FE29425A1700B30DA7 /* wrap_opkill.h */; }; + DCFD7D6F2A45BA9C007BBBF7 /* text.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B01B29425A1700B30DA7 /* text.h */; }; + DCFD7D702A45BA9C007BBBF7 /* string_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B02229425A1700B30DA7 /* string_utils.h */; }; + DCFD7D712A45BA9C007BBBF7 /* debug_info_manager.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0E229425A1700B30DA7 /* debug_info_manager.h */; }; + DCFD7D722A45BA9C007BBBF7 /* fix_storage_class.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B14529425A1800B30DA7 /* fix_storage_class.h */; }; + DCFD7D732A45BA9C007BBBF7 /* copy_prop_arrays.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B13229425A1800B30DA7 /* copy_prop_arrays.h */; }; + DCFD7D742A45BA9C007BBBF7 /* change_operand_to_undef_reduction_opportunity.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B04D29425A1700B30DA7 /* change_operand_to_undef_reduction_opportunity.h */; }; + DCFD7D752A45BA9C007BBBF7 /* lcs.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B08829425A1700B30DA7 /* lcs.h */; }; + DCFD7D762A45BA9C007BBBF7 /* ilist.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B02D29425A1700B30DA7 /* ilist.h */; }; + DCFD7D772A45BA9C007BBBF7 /* structured_loop_to_selection_reduction_opportunity_finder.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B04E29425A1700B30DA7 /* structured_loop_to_selection_reduction_opportunity_finder.h */; }; + DCFD7D782A45BA9C007BBBF7 /* function.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B35429425A1800B30DA7 /* function.h */; }; + DCFD7D792A45BA9C007BBBF7 /* eliminate_dead_constant_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B13329425A1800B30DA7 /* eliminate_dead_constant_pass.h */; }; + DCFD7D7A2A45BA9C007BBBF7 /* reduce_load_size.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0B229425A1700B30DA7 /* reduce_load_size.h */; }; + DCFD7D7B2A45BA9C007BBBF7 /* set_spec_constant_default_value_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B18329425A1800B30DA7 /* set_spec_constant_default_value_pass.h */; }; + DCFD7D7C2A45BA9C007BBBF7 /* diagnostic.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B09129425A1700B30DA7 /* diagnostic.h */; }; + DCFD7D7D2A45BA9C007BBBF7 /* dataflow.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B18029425A1800B30DA7 /* dataflow.h */; }; + DCFD7D7E2A45BA9C007BBBF7 /* merge_blocks_reduction_opportunity.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B06729425A1700B30DA7 /* merge_blocks_reduction_opportunity.h */; }; + DCFD7D7F2A45BA9C007BBBF7 /* module.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B16129425A1800B30DA7 /* module.h */; }; + DCFD7D802A45BA9C007BBBF7 /* spirv_optimizer_options.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B31B29425A1800B30DA7 /* spirv_optimizer_options.h */; }; + DCFD7D812A45BA9C007BBBF7 /* ext_inst.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B31629425A1800B30DA7 /* ext_inst.h */; }; + DCFD7D822A45BA9C007BBBF7 /* spirv_reducer_options.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B07629425A1700B30DA7 /* spirv_reducer_options.h */; }; + DCFD7D832A45BA9C007BBBF7 /* decoration.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B35829425A1800B30DA7 /* decoration.h */; }; + DCFD7D842A45BA9C007BBBF7 /* inst_buff_addr_check_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B10629425A1800B30DA7 /* inst_buff_addr_check_pass.h */; }; + DCFD7D852A45BA9C007BBBF7 /* iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B17529425A1800B30DA7 /* iterator.h */; }; + DCFD7D862A45BA9C007BBBF7 /* latest_version_glsl_std_450_header.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B31E29425A1800B30DA7 /* latest_version_glsl_std_450_header.h */; }; + DCFD7D872A45BA9C007BBBF7 /* pch_source_reduce.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B05A29425A1700B30DA7 /* pch_source_reduce.h */; }; + DCFD7D882A45BA9C007BBBF7 /* name_mapper.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B08E29425A1700B30DA7 /* name_mapper.h */; }; + DCFD7D892A45BA9C007BBBF7 /* liveness.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0D229425A1700B30DA7 /* liveness.h */; }; + DCFD7D8A2A45BA9C007BBBF7 /* local_redundancy_elimination.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0F229425A1700B30DA7 /* local_redundancy_elimination.h */; }; + DCFD7D8B2A45BA9C007BBBF7 /* simple_conditional_branch_to_branch_opportunity_finder.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B04729425A1700B30DA7 /* simple_conditional_branch_to_branch_opportunity_finder.h */; }; + DCFD7D8C2A45BA9C007BBBF7 /* instruction_list.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0C429425A1700B30DA7 /* instruction_list.h */; }; + DCFD7D8D2A45BA9C007BBBF7 /* diff.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B08729425A1700B30DA7 /* diff.h */; }; + DCFD7D8E2A45BA9C007BBBF7 /* instrument_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B11229425A1800B30DA7 /* instrument_pass.h */; }; + DCFD7D8F2A45BA9C007BBBF7 /* binary.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B32129425A1800B30DA7 /* binary.h */; }; + DCFD7D902A45BA9C007BBBF7 /* inline_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B11B29425A1800B30DA7 /* inline_pass.h */; }; + DCFD7D912A45BA9C007BBBF7 /* loop_fusion_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0F929425A1700B30DA7 /* loop_fusion_pass.h */; }; + DCFD7D922A45BA9C007BBBF7 /* dead_variable_elimination.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B13729425A1800B30DA7 /* dead_variable_elimination.h */; }; + DCFD7D932A45BA9C007BBBF7 /* remove_unused_interface_variables_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B18529425A1800B30DA7 /* remove_unused_interface_variables_pass.h */; }; + DCFD7D942A45BA9C007BBBF7 /* remove_unused_struct_member_reduction_opportunity_finder.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B05529425A1700B30DA7 /* remove_unused_struct_member_reduction_opportunity_finder.h */; }; + DCFD7D952A45BA9C007BBBF7 /* simplification_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B14C29425A1800B30DA7 /* simplification_pass.h */; }; + DCFD7D962A45BA9C007BBBF7 /* remove_duplicates_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B14E29425A1800B30DA7 /* remove_duplicates_pass.h */; }; + DCFD7D972A45BA9C007BBBF7 /* eliminate_dead_io_components_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B10429425A1800B30DA7 /* eliminate_dead_io_components_pass.h */; }; + DCFD7D982A45BA9C007BBBF7 /* enum_string_mapping.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B07429425A1700B30DA7 /* enum_string_mapping.h */; }; + DCFD7D992A45BA9C007BBBF7 /* hex_float.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B02A29425A1700B30DA7 /* hex_float.h */; }; + DCFD7D9A2A45BA9C007BBBF7 /* spirv_validator_options.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B08A29425A1700B30DA7 /* spirv_validator_options.h */; }; + DCFD7D9B2A45BA9C007BBBF7 /* desc_sroa_util.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B14F29425A1800B30DA7 /* desc_sroa_util.h */; }; + DCFD7D9C2A45BA9C007BBBF7 /* remove_selection_reduction_opportunity_finder.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B05129425A1700B30DA7 /* remove_selection_reduction_opportunity_finder.h */; }; + DCFD7D9D2A45BA9C007BBBF7 /* pass_manager.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B17029425A1800B30DA7 /* pass_manager.h */; }; + DCFD7D9E2A45BA9C007BBBF7 /* dominator_analysis.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B13929425A1800B30DA7 /* dominator_analysis.h */; }; + DCFD7D9F2A45BA9C007BBBF7 /* spirv_definition.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B07F29425A1700B30DA7 /* spirv_definition.h */; }; + DCFD7DA02A45BA9C007BBBF7 /* block_merge_util.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0F529425A1700B30DA7 /* block_merge_util.h */; }; + DCFD7DA12A45BA9C007BBBF7 /* remove_function_reduction_opportunity.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B04B29425A1700B30DA7 /* remove_function_reduction_opportunity.h */; }; + DCFD7DA22A45BA9C007BBBF7 /* reducer.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B05D29425A1700B30DA7 /* reducer.h */; }; + DCFD7DA32A45BA9C007BBBF7 /* def_use_manager.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0EC29425A1700B30DA7 /* def_use_manager.h */; }; + DCFD7DA42A45BA9C007BBBF7 /* type_manager.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B18629425A1800B30DA7 /* type_manager.h */; }; + DCFD7DA52A45BA9C007BBBF7 /* common_debug_info.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B09729425A1700B30DA7 /* common_debug_info.h */; }; + DCFD7DA62A45BA9C007BBBF7 /* cfg_cleanup_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0EF29425A1700B30DA7 /* cfg_cleanup_pass.h */; }; + DCFD7DA72A45BA9C007BBBF7 /* desc_sroa.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0F729425A1700B30DA7 /* desc_sroa.h */; }; + DCFD7DA82A45BA9C007BBBF7 /* local_single_block_elim_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B10229425A1800B30DA7 /* local_single_block_elim_pass.h */; }; + DCFD7DA92A45BA9C007BBBF7 /* spirv_endian.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B09229425A1700B30DA7 /* spirv_endian.h */; }; + DCFD7DAA2A45BA9C007BBBF7 /* redundancy_elimination.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B15A29425A1800B30DA7 /* redundancy_elimination.h */; }; + DCFD7DAB2A45BA9C007BBBF7 /* combine_access_chains.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B16F29425A1800B30DA7 /* combine_access_chains.h */; }; + DCFD7DAC2A45BA9C007BBBF7 /* latest_version_spirv_header.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B31829425A1800B30DA7 /* latest_version_spirv_header.h */; }; + DCFD7DAD2A45BA9C007BBBF7 /* eliminate_dead_output_stores_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0BD29425A1700B30DA7 /* eliminate_dead_output_stores_pass.h */; }; + DCFD7DAE2A45BA9C007BBBF7 /* spread_volatile_semantics.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B17129425A1800B30DA7 /* spread_volatile_semantics.h */; }; + DCFD7DAF2A45BA9C007BBBF7 /* ir_builder.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B16329425A1800B30DA7 /* ir_builder.h */; }; + DCFD7DB02A45BA9C007BBBF7 /* build_module.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B17729425A1800B30DA7 /* build_module.h */; }; + DCFD7DB12A45BA9C007BBBF7 /* inline_exhaustive_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B12329425A1800B30DA7 /* inline_exhaustive_pass.h */; }; + DCFD7DB22A45BA9C007BBBF7 /* reduction_opportunity_finder.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B06229425A1700B30DA7 /* reduction_opportunity_finder.h */; }; + DCFD7DB32A45BA9C007BBBF7 /* divergence_analysis.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B01629425A1700B30DA7 /* divergence_analysis.h */; }; + DCFD7DB42A45BA9C007BBBF7 /* upgrade_memory_model.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B12929425A1800B30DA7 /* upgrade_memory_model.h */; }; + DCFD7DB52A45BA9C007BBBF7 /* bitutils.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B02929425A1700B30DA7 /* bitutils.h */; }; + DCFD7DB62A45BA9C007BBBF7 /* parsed_operand.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B08D29425A1700B30DA7 /* parsed_operand.h */; }; + DCFD7DB72A45BA9C007BBBF7 /* spirv_constant.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B08329425A1700B30DA7 /* spirv_constant.h */; }; + DCFD7DB82A45BA9C007BBBF7 /* fix_func_call_arguments.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B17B29425A1800B30DA7 /* fix_func_call_arguments.h */; }; + DCFD7DB92A45BA9C007BBBF7 /* eliminate_dead_functions_util.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B13E29425A1800B30DA7 /* eliminate_dead_functions_util.h */; }; + DCFD7DBA2A45BA9C007BBBF7 /* loop_unroller.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0D329425A1700B30DA7 /* loop_unroller.h */; }; + DCFD7DBB2A45BA9C007BBBF7 /* ssa_rewrite_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B13529425A1800B30DA7 /* ssa_rewrite_pass.h */; }; + DCFD7DBC2A45BA9C007BBBF7 /* propagator.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0C329425A1700B30DA7 /* propagator.h */; }; + DCFD7DBD2A45BA9C007BBBF7 /* loop_descriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B16929425A1800B30DA7 /* loop_descriptor.h */; }; + DCFD7DBE2A45BA9C007BBBF7 /* merge_return_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0A429425A1700B30DA7 /* merge_return_pass.h */; }; + DCFD7DBF2A45BA9C007BBBF7 /* empty_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0FF29425A1800B30DA7 /* empty_pass.h */; }; + DCFD7DC02A45BA9C007BBBF7 /* scalar_replacement_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B15629425A1800B30DA7 /* scalar_replacement_pass.h */; }; + DCFD7DC12A45BA9C007BBBF7 /* code_sink.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B16729425A1800B30DA7 /* code_sink.h */; }; + DCFD7DC22A45BA9C007BBBF7 /* change_operand_reduction_opportunity.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B06329425A1700B30DA7 /* change_operand_reduction_opportunity.h */; }; + DCFD7DC32A45BA9C007BBBF7 /* analyze_live_input_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B12B29425A1800B30DA7 /* analyze_live_input_pass.h */; }; + DCFD7DC42A45BA9C007BBBF7 /* cfa.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B07229425A1700B30DA7 /* cfa.h */; }; + DCFD7DC52A45BA9C007BBBF7 /* amd_ext_to_khr.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0C929425A1700B30DA7 /* amd_ext_to_khr.h */; }; + DCFD7DC62A45BA9C007BBBF7 /* decoration_manager.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B10029425A1800B30DA7 /* decoration_manager.h */; }; + DCFD7DC72A45BA9C007BBBF7 /* loop_peeling.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0F329425A1700B30DA7 /* loop_peeling.h */; }; + DCFD7DC82A45BA9C007BBBF7 /* replace_desc_array_access_using_var_index.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0B729425A1700B30DA7 /* replace_desc_array_access_using_var_index.h */; }; + DCFD7DC92A45BA9C007BBBF7 /* reflect.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B15129425A1800B30DA7 /* reflect.h */; }; + DCFD7DCA2A45BA9C007BBBF7 /* compact_ids_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0AC29425A1700B30DA7 /* compact_ids_pass.h */; }; + DCFD7DCB2A45BA9C007BBBF7 /* macro.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B08229425A1700B30DA7 /* macro.h */; }; + DCFD7DCC2A45BA9C007BBBF7 /* timer.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B02629425A1700B30DA7 /* timer.h */; }; + DCFD7DCD2A45BA9C007BBBF7 /* extensions.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B31F29425A1800B30DA7 /* extensions.h */; }; + DCFD7DCE2A45BA9C007BBBF7 /* mem_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B11329425A1800B30DA7 /* mem_pass.h */; }; + DCFD7DCF2A45BA9C007BBBF7 /* local_access_chain_convert_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0BE29425A1700B30DA7 /* local_access_chain_convert_pass.h */; }; + DCFD7DD02A45BA9C007BBBF7 /* remove_instruction_reduction_opportunity.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B03F29425A1700B30DA7 /* remove_instruction_reduction_opportunity.h */; }; + DCFD7DD12A45BA9C007BBBF7 /* control_dependence.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0CD29425A1700B30DA7 /* control_dependence.h */; }; + DCFD7DD22A45BA9C007BBBF7 /* ir_loader.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0D829425A1700B30DA7 /* ir_loader.h */; }; + DCFD7DD32A45BA9C007BBBF7 /* conditional_branch_to_simple_conditional_branch_reduction_opportunity.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B04029425A1700B30DA7 /* conditional_branch_to_simple_conditional_branch_reduction_opportunity.h */; }; + DCFD7DD42A45BA9C007BBBF7 /* workaround1209.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B12F29425A1800B30DA7 /* workaround1209.h */; }; + DCFD7DD52A45BA9C007BBBF7 /* register_pressure.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0AD29425A1700B30DA7 /* register_pressure.h */; }; + DCFD7DD62A45BA9C007BBBF7 /* operand_to_undef_reduction_opportunity_finder.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B03129425A1700B30DA7 /* operand_to_undef_reduction_opportunity_finder.h */; }; + DCFD7DD72A45BA9C007BBBF7 /* struct_cfg_analysis.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B0FA29425A1700B30DA7 /* struct_cfg_analysis.h */; }; + DCFD7DD82A45BA9C007BBBF7 /* spirv_fuzzer_options.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B00E29425A1700B30DA7 /* spirv_fuzzer_options.h */; }; + DCFD7DD92A45BA9C007BBBF7 /* const_folding_rules.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B15529425A1800B30DA7 /* const_folding_rules.h */; }; + DCFD7DDA2A45BA9C007BBBF7 /* inst_bindless_check_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B18129425A1800B30DA7 /* inst_bindless_check_pass.h */; }; + DCFD7DDB2A45BA9C007BBBF7 /* aggressive_dead_code_elim_pass.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B16B29425A1800B30DA7 /* aggressive_dead_code_elim_pass.h */; }; + DCFD7DDC2A45BA9C007BBBF7 /* if_conversion.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F7B09F29425A1700B30DA7 /* if_conversion.h */; }; + DCFD7DDE2A45BA9C007BBBF7 /* spirv_reducer_options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B08F29425A1700B30DA7 /* spirv_reducer_options.cpp */; }; + DCFD7DDF2A45BA9C007BBBF7 /* register_pressure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0A029425A1700B30DA7 /* register_pressure.cpp */; }; + DCFD7DE02A45BA9C007BBBF7 /* loop_peeling.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B18829425A1800B30DA7 /* loop_peeling.cpp */; }; + DCFD7DE12A45BA9C007BBBF7 /* block_merge_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B13829425A1800B30DA7 /* block_merge_pass.cpp */; }; + DCFD7DE22A45BA9C007BBBF7 /* opcode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B09929425A1700B30DA7 /* opcode.cpp */; }; + DCFD7DE32A45BA9C007BBBF7 /* validate_builtins.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B33429425A1800B30DA7 /* validate_builtins.cpp */; }; + DCFD7DE42A45BA9C007BBBF7 /* validate_non_uniform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B32A29425A1800B30DA7 /* validate_non_uniform.cpp */; }; + DCFD7DE52A45BA9C007BBBF7 /* table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B02F29425A1700B30DA7 /* table.cpp */; }; + DCFD7DE62A45BA9C007BBBF7 /* validate_logicals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B34729425A1800B30DA7 /* validate_logicals.cpp */; }; + DCFD7DE72A45BA9C007BBBF7 /* change_operand_to_undef_reduction_opportunity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B05E29425A1700B30DA7 /* change_operand_to_undef_reduction_opportunity.cpp */; }; + DCFD7DE82A45BA9C007BBBF7 /* bit_vector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B02C29425A1700B30DA7 /* bit_vector.cpp */; }; + DCFD7DE92A45BA9C007BBBF7 /* ir_context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B11129425A1800B30DA7 /* ir_context.cpp */; }; + DCFD7DEA2A45BA9C007BBBF7 /* structured_loop_to_selection_reduction_opportunity_finder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B03C29425A1700B30DA7 /* structured_loop_to_selection_reduction_opportunity_finder.cpp */; }; + DCFD7DEB2A45BA9C007BBBF7 /* if_conversion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B12029425A1800B30DA7 /* if_conversion.cpp */; }; + DCFD7DEC2A45BA9C007BBBF7 /* remove_dontinline_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B16D29425A1800B30DA7 /* remove_dontinline_pass.cpp */; }; + DCFD7DED2A45BA9C007BBBF7 /* convert_to_sampled_image_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B13A29425A1800B30DA7 /* convert_to_sampled_image_pass.cpp */; }; + DCFD7DEE2A45BA9C007BBBF7 /* merge_return_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0CA29425A1700B30DA7 /* merge_return_pass.cpp */; }; + DCFD7DEF2A45BA9C007BBBF7 /* reducer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B05729425A1700B30DA7 /* reducer.cpp */; }; + DCFD7DF02A45BA9C007BBBF7 /* remove_function_reduction_opportunity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B04229425A1700B30DA7 /* remove_function_reduction_opportunity.cpp */; }; + DCFD7DF12A45BA9C007BBBF7 /* disassemble.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B32029425A1800B30DA7 /* disassemble.cpp */; }; + DCFD7DF22A45BA9C007BBBF7 /* composite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B11929425A1800B30DA7 /* composite.cpp */; }; + DCFD7DF32A45BA9C007BBBF7 /* validate_conversion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B33F29425A1800B30DA7 /* validate_conversion.cpp */; }; + DCFD7DF42A45BA9C007BBBF7 /* instruction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B34C29425A1800B30DA7 /* instruction.cpp */; }; + DCFD7DF52A45BA9C007BBBF7 /* validate_ray_query.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B32B29425A1800B30DA7 /* validate_ray_query.cpp */; }; + DCFD7DF62A45BA9C007BBBF7 /* operand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B31D29425A1800B30DA7 /* operand.cpp */; }; + DCFD7DF72A45BA9C007BBBF7 /* unify_const_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0E529425A1700B30DA7 /* unify_const_pass.cpp */; }; + DCFD7DF82A45BA9C007BBBF7 /* operand_to_const_reduction_opportunity_finder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B03729425A1700B30DA7 /* operand_to_const_reduction_opportunity_finder.cpp */; }; + DCFD7DF92A45BA9C007BBBF7 /* enum_string_mapping.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B08B29425A1700B30DA7 /* enum_string_mapping.cpp */; }; + DCFD7DFA2A45BA9C007BBBF7 /* validate_mode_setting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B34529425A1800B30DA7 /* validate_mode_setting.cpp */; }; + DCFD7DFB2A45BA9C007BBBF7 /* binary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B08429425A1700B30DA7 /* binary.cpp */; }; + DCFD7DFC2A45BA9C007BBBF7 /* struct_cfg_analysis.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B16C29425A1800B30DA7 /* struct_cfg_analysis.cpp */; }; + DCFD7DFD2A45BA9C007BBBF7 /* validate_capability.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B32729425A1800B30DA7 /* validate_capability.cpp */; }; + DCFD7DFE2A45BA9C007BBBF7 /* diagnostic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B31729425A1800B30DA7 /* diagnostic.cpp */; }; + DCFD7DFF2A45BA9C007BBBF7 /* libspirv.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B31929425A1800B30DA7 /* libspirv.cpp */; }; + DCFD7E002A45BA9C007BBBF7 /* validate_mesh_shading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B34F29425A1800B30DA7 /* validate_mesh_shading.cpp */; }; + DCFD7E012A45BA9C007BBBF7 /* build_module.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0A829425A1700B30DA7 /* build_module.cpp */; }; + DCFD7E022A45BA9C007BBBF7 /* cfg_cleanup_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0CE29425A1700B30DA7 /* cfg_cleanup_pass.cpp */; }; + DCFD7E032A45BA9C007BBBF7 /* spirv_fuzzer_options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B07529425A1700B30DA7 /* spirv_fuzzer_options.cpp */; }; + DCFD7E042A45BA9C007BBBF7 /* validate_adjacency.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B33E29425A1800B30DA7 /* validate_adjacency.cpp */; }; + DCFD7E052A45BA9C007BBBF7 /* validate_id.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B34229425A1800B30DA7 /* validate_id.cpp */; }; + DCFD7E062A45BA9C007BBBF7 /* parse_number.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B02B29425A1700B30DA7 /* parse_number.cpp */; }; + DCFD7E072A45BA9C007BBBF7 /* scalar_analysis.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B13629425A1800B30DA7 /* scalar_analysis.cpp */; }; + DCFD7E082A45BA9C007BBBF7 /* lint_divergent_derivatives.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B01229425A1700B30DA7 /* lint_divergent_derivatives.cpp */; }; + DCFD7E092A45BA9C007BBBF7 /* remove_struct_member_reduction_opportunity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B05429425A1700B30DA7 /* remove_struct_member_reduction_opportunity.cpp */; }; + DCFD7E0A2A45BA9C007BBBF7 /* validate_scopes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B32D29425A1800B30DA7 /* validate_scopes.cpp */; }; + DCFD7E0B2A45BA9C007BBBF7 /* strip_debug_info_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0D429425A1700B30DA7 /* strip_debug_info_pass.cpp */; }; + DCFD7E0C2A45BA9C007BBBF7 /* eliminate_dead_functions_util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B10929425A1800B30DA7 /* eliminate_dead_functions_util.cpp */; }; + DCFD7E0D2A45BA9C007BBBF7 /* remove_function_reduction_opportunity_finder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B03E29425A1700B30DA7 /* remove_function_reduction_opportunity_finder.cpp */; }; + DCFD7E0E2A45BA9C007BBBF7 /* ssa_rewrite_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0D529425A1700B30DA7 /* ssa_rewrite_pass.cpp */; }; + DCFD7E0F2A45BA9C007BBBF7 /* validate_image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B34A29425A1800B30DA7 /* validate_image.cpp */; }; + DCFD7E102A45BA9C007BBBF7 /* module.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0E129425A1700B30DA7 /* module.cpp */; }; + DCFD7E112A45BA9C007BBBF7 /* merge_blocks_reduction_opportunity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B04829425A1700B30DA7 /* merge_blocks_reduction_opportunity.cpp */; }; + DCFD7E122A45BA9C007BBBF7 /* constants.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0F829425A1700B30DA7 /* constants.cpp */; }; + DCFD7E132A45BA9C007BBBF7 /* remove_block_reduction_opportunity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B06B29425A1700B30DA7 /* remove_block_reduction_opportunity.cpp */; }; + DCFD7E142A45BA9C007BBBF7 /* spirv_target_env.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B00D29425A1700B30DA7 /* spirv_target_env.cpp */; }; + DCFD7E152A45BA9C007BBBF7 /* loop_fission.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0C729425A1700B30DA7 /* loop_fission.cpp */; }; + DCFD7E162A45BA9C007BBBF7 /* remove_block_reduction_opportunity_finder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B06529425A1700B30DA7 /* remove_block_reduction_opportunity_finder.cpp */; }; + DCFD7E172A45BA9C007BBBF7 /* remove_selection_reduction_opportunity_finder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B04429425A1700B30DA7 /* remove_selection_reduction_opportunity_finder.cpp */; }; + DCFD7E182A45BA9C007BBBF7 /* fold.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B14929425A1800B30DA7 /* fold.cpp */; }; + DCFD7E192A45BA9C007BBBF7 /* def_use_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0FD29425A1700B30DA7 /* def_use_manager.cpp */; }; + DCFD7E1A2A45BA9C007BBBF7 /* parsed_operand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B09029425A1700B30DA7 /* parsed_operand.cpp */; }; + DCFD7E1B2A45BA9C007BBBF7 /* eliminate_dead_members_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B12529425A1800B30DA7 /* eliminate_dead_members_pass.cpp */; }; + DCFD7E1C2A45BA9C007BBBF7 /* instruction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B15729425A1800B30DA7 /* instruction.cpp */; }; + DCFD7E1D2A45BA9C007BBBF7 /* name_mapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B09329425A1700B30DA7 /* name_mapper.cpp */; }; + DCFD7E1E2A45BA9C007BBBF7 /* analyze_live_input_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B17D29425A1800B30DA7 /* analyze_live_input_pass.cpp */; }; + DCFD7E1F2A45BA9C007BBBF7 /* validate_cfg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B32629425A1800B30DA7 /* validate_cfg.cpp */; }; + DCFD7E202A45BA9C007BBBF7 /* change_operand_reduction_opportunity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B04929425A1700B30DA7 /* change_operand_reduction_opportunity.cpp */; }; + DCFD7E212A45BA9C007BBBF7 /* validate_instruction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B33029425A1800B30DA7 /* validate_instruction.cpp */; }; + DCFD7E222A45BA9C007BBBF7 /* instrument_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0C229425A1700B30DA7 /* instrument_pass.cpp */; }; + DCFD7E232A45BA9C007BBBF7 /* validate_ray_tracing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B32C29425A1800B30DA7 /* validate_ray_tracing.cpp */; }; + DCFD7E242A45BA9C007BBBF7 /* pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0C629425A1700B30DA7 /* pass.cpp */; }; + DCFD7E252A45BA9C007BBBF7 /* ccp_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B10129425A1800B30DA7 /* ccp_pass.cpp */; }; + DCFD7E262A45BA9C007BBBF7 /* desc_sroa_util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0FB29425A1700B30DA7 /* desc_sroa_util.cpp */; }; + DCFD7E272A45BA9C007BBBF7 /* validate_bitwise.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B33929425A1800B30DA7 /* validate_bitwise.cpp */; }; + DCFD7E282A45BA9C007BBBF7 /* block_merge_util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B12829425A1800B30DA7 /* block_merge_util.cpp */; }; + DCFD7E292A45BA9C007BBBF7 /* validate_debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B33329425A1800B30DA7 /* validate_debug.cpp */; }; + DCFD7E2A2A45BA9C007BBBF7 /* loop_descriptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B11429425A1800B30DA7 /* loop_descriptor.cpp */; }; + DCFD7E2B2A45BA9C007BBBF7 /* linker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B09629425A1700B30DA7 /* linker.cpp */; }; + DCFD7E2C2A45BA9C007BBBF7 /* freeze_spec_constant_value_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0BB29425A1700B30DA7 /* freeze_spec_constant_value_pass.cpp */; }; + DCFD7E2D2A45BA9C007BBBF7 /* string_utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B02729425A1700B30DA7 /* string_utils.cpp */; }; + DCFD7E2E2A45BA9C007BBBF7 /* validate_memory_semantics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B34629425A1800B30DA7 /* validate_memory_semantics.cpp */; }; + DCFD7E2F2A45BA9C007BBBF7 /* types.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0B429425A1700B30DA7 /* types.cpp */; }; + DCFD7E302A45BA9C007BBBF7 /* pch_source.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B01D29425A1700B30DA7 /* pch_source.cpp */; }; + DCFD7E312A45BA9C007BBBF7 /* print.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B07E29425A1700B30DA7 /* print.cpp */; }; + DCFD7E322A45BA9C007BBBF7 /* function.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B33C29425A1800B30DA7 /* function.cpp */; }; + DCFD7E332A45BA9C007BBBF7 /* inline_exhaustive_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B12D29425A1800B30DA7 /* inline_exhaustive_pass.cpp */; }; + DCFD7E342A45BA9C007BBBF7 /* eliminate_dead_constant_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0CC29425A1700B30DA7 /* eliminate_dead_constant_pass.cpp */; }; + DCFD7E352A45BA9C007BBBF7 /* inline_opaque_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B15E29425A1800B30DA7 /* inline_opaque_pass.cpp */; }; + DCFD7E362A45BA9C007BBBF7 /* conditional_branch_to_simple_conditional_branch_opportunity_finder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B06829425A1700B30DA7 /* conditional_branch_to_simple_conditional_branch_opportunity_finder.cpp */; }; + DCFD7E372A45BA9C007BBBF7 /* linter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B01329425A1700B30DA7 /* linter.cpp */; }; + DCFD7E382A45BA9C007BBBF7 /* eliminate_dead_output_stores_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0A929425A1700B30DA7 /* eliminate_dead_output_stores_pass.cpp */; }; + DCFD7E392A45BA9C007BBBF7 /* compact_ids_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B18729425A1800B30DA7 /* compact_ids_pass.cpp */; }; + DCFD7E3A2A45BA9C007BBBF7 /* folding_rules.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B10F29425A1800B30DA7 /* folding_rules.cpp */; }; + DCFD7E3B2A45BA9C007BBBF7 /* strip_nonsemantic_info_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B11E29425A1800B30DA7 /* strip_nonsemantic_info_pass.cpp */; }; + DCFD7E3C2A45BA9C007BBBF7 /* private_to_local_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B14229425A1800B30DA7 /* private_to_local_pass.cpp */; }; + DCFD7E3D2A45BA9C007BBBF7 /* fold_spec_constant_op_and_composite_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0E329425A1700B30DA7 /* fold_spec_constant_op_and_composite_pass.cpp */; }; + DCFD7E3E2A45BA9C007BBBF7 /* validate_ray_tracing_reorder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B33129425A1800B30DA7 /* validate_ray_tracing_reorder.cpp */; }; + DCFD7E3F2A45BA9C007BBBF7 /* validate_derivatives.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B34829425A1800B30DA7 /* validate_derivatives.cpp */; }; + DCFD7E402A45BA9C007BBBF7 /* simple_conditional_branch_to_branch_reduction_opportunity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B04129425A1700B30DA7 /* simple_conditional_branch_to_branch_reduction_opportunity.cpp */; }; + DCFD7E412A45BA9C007BBBF7 /* control_dependence.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B11829425A1800B30DA7 /* control_dependence.cpp */; }; + DCFD7E422A45BA9C007BBBF7 /* spirv_optimizer_options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B07129425A1700B30DA7 /* spirv_optimizer_options.cpp */; }; + DCFD7E432A45BA9C007BBBF7 /* pch_source_reduce.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B05329425A1700B30DA7 /* pch_source_reduce.cpp */; }; + DCFD7E442A45BA9C007BBBF7 /* dead_variable_elimination.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0DF29425A1700B30DA7 /* dead_variable_elimination.cpp */; }; + DCFD7E452A45BA9C007BBBF7 /* conditional_branch_to_simple_conditional_branch_reduction_opportunity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B04529425A1700B30DA7 /* conditional_branch_to_simple_conditional_branch_reduction_opportunity.cpp */; }; + DCFD7E462A45BA9C007BBBF7 /* strength_reduction_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B12629425A1800B30DA7 /* strength_reduction_pass.cpp */; }; + DCFD7E472A45BA9C007BBBF7 /* scalar_analysis_simplification.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B18229425A1800B30DA7 /* scalar_analysis_simplification.cpp */; }; + DCFD7E482A45BA9C007BBBF7 /* validate_interfaces.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B33529425A1800B30DA7 /* validate_interfaces.cpp */; }; + DCFD7E492A45BA9C007BBBF7 /* validate_atomics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B32E29425A1800B30DA7 /* validate_atomics.cpp */; }; + DCFD7E4A2A45BA9C007BBBF7 /* ext_inst.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B09B29425A1700B30DA7 /* ext_inst.cpp */; }; + DCFD7E4B2A45BA9C007BBBF7 /* operand_to_dominating_id_reduction_opportunity_finder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B06129425A1700B30DA7 /* operand_to_dominating_id_reduction_opportunity_finder.cpp */; }; + DCFD7E4C2A45BA9C007BBBF7 /* decoration_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0B929425A1700B30DA7 /* decoration_manager.cpp */; }; + DCFD7E4D2A45BA9C007BBBF7 /* workaround1209.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B15229425A1800B30DA7 /* workaround1209.cpp */; }; + DCFD7E4E2A45BA9C007BBBF7 /* interp_fixup_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B17329425A1800B30DA7 /* interp_fixup_pass.cpp */; }; + DCFD7E4F2A45BA9C007BBBF7 /* validate_literals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B34B29425A1800B30DA7 /* validate_literals.cpp */; }; + DCFD7E502A45BA9C007BBBF7 /* diff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B08929425A1700B30DA7 /* diff.cpp */; }; + DCFD7E512A45BA9C007BBBF7 /* dominator_tree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0C829425A1700B30DA7 /* dominator_tree.cpp */; }; + DCFD7E522A45BA9C007BBBF7 /* interface_var_sroa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B14D29425A1800B30DA7 /* interface_var_sroa.cpp */; }; + DCFD7E532A45BA9C007BBBF7 /* upgrade_memory_model.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B17E29425A1800B30DA7 /* upgrade_memory_model.cpp */; }; + DCFD7E542A45BA9C007BBBF7 /* combine_access_chains.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0A729425A1700B30DA7 /* combine_access_chains.cpp */; }; + DCFD7E552A45BA9C007BBBF7 /* instruction_list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B11729425A1800B30DA7 /* instruction_list.cpp */; }; + DCFD7E562A45BA9C007BBBF7 /* aggressive_dead_code_elim_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B10829425A1800B30DA7 /* aggressive_dead_code_elim_pass.cpp */; }; + DCFD7E572A45BA9C007BBBF7 /* reduction_util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B03A29425A1700B30DA7 /* reduction_util.cpp */; }; + DCFD7E582A45BA9C007BBBF7 /* eliminate_dead_functions_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0F129425A1700B30DA7 /* eliminate_dead_functions_pass.cpp */; }; + DCFD7E592A45BA9C007BBBF7 /* validate_small_type_uses.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B34029425A1800B30DA7 /* validate_small_type_uses.cpp */; }; + DCFD7E5A2A45BA9C007BBBF7 /* validate_misc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B32529425A1800B30DA7 /* validate_misc.cpp */; }; + DCFD7E5B2A45BA9C007BBBF7 /* code_sink.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0B329425A1700B30DA7 /* code_sink.cpp */; }; + DCFD7E5C2A45BA9C007BBBF7 /* pass_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B12C29425A1800B30DA7 /* pass_manager.cpp */; }; + DCFD7E5D2A45BA9C007BBBF7 /* feature_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0C529425A1700B30DA7 /* feature_manager.cpp */; }; + DCFD7E5E2A45BA9C007BBBF7 /* wrap_opkill.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0CF29425A1700B30DA7 /* wrap_opkill.cpp */; }; + DCFD7E5F2A45BA9C007BBBF7 /* dataflow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B16829425A1800B30DA7 /* dataflow.cpp */; }; + DCFD7E602A45BA9C007BBBF7 /* validate_type.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B34D29425A1800B30DA7 /* validate_type.cpp */; }; + DCFD7E612A45BA9C007BBBF7 /* set_spec_constant_default_value_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B14729425A1800B30DA7 /* set_spec_constant_default_value_pass.cpp */; }; + DCFD7E622A45BA9C007BBBF7 /* remove_selection_reduction_opportunity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B03229425A1700B30DA7 /* remove_selection_reduction_opportunity.cpp */; }; + DCFD7E632A45BA9C007BBBF7 /* validate_constants.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B33829425A1800B30DA7 /* validate_constants.cpp */; }; + DCFD7E642A45BA9C007BBBF7 /* validate_layout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B35129425A1800B30DA7 /* validate_layout.cpp */; }; + DCFD7E652A45BA9C007BBBF7 /* const_folding_rules.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0D129425A1700B30DA7 /* const_folding_rules.cpp */; }; + DCFD7E662A45BA9C007BBBF7 /* replace_invalid_opc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B15F29425A1800B30DA7 /* replace_invalid_opc.cpp */; }; + DCFD7E672A45BA9C007BBBF7 /* eliminate_dead_io_components_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0D029425A1700B30DA7 /* eliminate_dead_io_components_pass.cpp */; }; + DCFD7E682A45BA9C007BBBF7 /* structured_construct_to_block_reduction_opportunity_finder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B06E29425A1700B30DA7 /* structured_construct_to_block_reduction_opportunity_finder.cpp */; }; + DCFD7E692A45BA9C007BBBF7 /* reduction_opportunity_finder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B06D29425A1700B30DA7 /* reduction_opportunity_finder.cpp */; }; + DCFD7E6A2A45BA9C007BBBF7 /* liveness.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0AB29425A1700B30DA7 /* liveness.cpp */; }; + DCFD7E6B2A45BA9C007BBBF7 /* debug_info_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B12229425A1800B30DA7 /* debug_info_manager.cpp */; }; + DCFD7E6C2A45BA9C007BBBF7 /* relax_float_ops_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B15429425A1800B30DA7 /* relax_float_ops_pass.cpp */; }; + DCFD7E6D2A45BA9C007BBBF7 /* value_number_table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B15C29425A1800B30DA7 /* value_number_table.cpp */; }; + DCFD7E6E2A45BA9C007BBBF7 /* text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B01929425A1700B30DA7 /* text.cpp */; }; + DCFD7E6F2A45BA9C007BBBF7 /* local_single_store_elim_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B14029425A1800B30DA7 /* local_single_store_elim_pass.cpp */; }; + DCFD7E702A45BA9C007BBBF7 /* remove_unused_instruction_reduction_opportunity_finder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B05629425A1700B30DA7 /* remove_unused_instruction_reduction_opportunity_finder.cpp */; }; + DCFD7E712A45BA9C007BBBF7 /* reduction_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B03529425A1700B30DA7 /* reduction_pass.cpp */; }; + DCFD7E722A45BA9C007BBBF7 /* convert_to_half_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B11A29425A1800B30DA7 /* convert_to_half_pass.cpp */; }; + DCFD7E732A45BA9C007BBBF7 /* reduce_load_size.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B15929425A1800B30DA7 /* reduce_load_size.cpp */; }; + DCFD7E742A45BA9C007BBBF7 /* local_access_chain_convert_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B17229425A1800B30DA7 /* local_access_chain_convert_pass.cpp */; }; + DCFD7E752A45BA9C007BBBF7 /* inst_bindless_check_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0BF29425A1700B30DA7 /* inst_bindless_check_pass.cpp */; }; + DCFD7E762A45BA9C007BBBF7 /* local_single_block_elim_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0BA29425A1700B30DA7 /* local_single_block_elim_pass.cpp */; }; + DCFD7E772A45BA9C007BBBF7 /* validate_execution_limitations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B35029425A1800B30DA7 /* validate_execution_limitations.cpp */; }; + DCFD7E782A45BA9C007BBBF7 /* function.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B11629425A1800B30DA7 /* function.cpp */; }; + DCFD7E792A45BA9C007BBBF7 /* fix_func_call_arguments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B12129425A1800B30DA7 /* fix_func_call_arguments.cpp */; }; + DCFD7E7A2A45BA9C007BBBF7 /* structured_loop_to_selection_reduction_opportunity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B06929425A1700B30DA7 /* structured_loop_to_selection_reduction_opportunity.cpp */; }; + DCFD7E7B2A45BA9C007BBBF7 /* graphics_robust_access_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B17929425A1800B30DA7 /* graphics_robust_access_pass.cpp */; }; + DCFD7E7C2A45BA9C007BBBF7 /* construct.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B33B29425A1800B30DA7 /* construct.cpp */; }; + DCFD7E7D2A45BA9C007BBBF7 /* loop_unroller.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0F629425A1700B30DA7 /* loop_unroller.cpp */; }; + DCFD7E7E2A45BA9C007BBBF7 /* spirv_validator_options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B07729425A1700B30DA7 /* spirv_validator_options.cpp */; }; + DCFD7E7F2A45BA9C007BBBF7 /* divergence_analysis.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B01429425A1700B30DA7 /* divergence_analysis.cpp */; }; + DCFD7E802A45BA9C007BBBF7 /* loop_utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0A129425A1700B30DA7 /* loop_utils.cpp */; }; + DCFD7E812A45BA9C007BBBF7 /* spread_volatile_semantics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0A329425A1700B30DA7 /* spread_volatile_semantics.cpp */; }; + DCFD7E822A45BA9C007BBBF7 /* desc_sroa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B12729425A1800B30DA7 /* desc_sroa.cpp */; }; + DCFD7E832A45BA9C007BBBF7 /* dead_insert_elim_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B13429425A1800B30DA7 /* dead_insert_elim_pass.cpp */; }; + DCFD7E842A45BA9C007BBBF7 /* validate_decorations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B33229425A1800B30DA7 /* validate_decorations.cpp */; }; + DCFD7E852A45BA9C007BBBF7 /* loop_fusion_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B13029425A1800B30DA7 /* loop_fusion_pass.cpp */; }; + DCFD7E862A45BA9C007BBBF7 /* merge_blocks_reduction_opportunity_finder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B05B29425A1700B30DA7 /* merge_blocks_reduction_opportunity_finder.cpp */; }; + DCFD7E872A45BA9C007BBBF7 /* flatten_decoration_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B10D29425A1800B30DA7 /* flatten_decoration_pass.cpp */; }; + DCFD7E882A45BA9C007BBBF7 /* fix_storage_class.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B15B29425A1800B30DA7 /* fix_storage_class.cpp */; }; + DCFD7E892A45BA9C007BBBF7 /* software_version.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B09829425A1700B30DA7 /* software_version.cpp */; }; + DCFD7E8A2A45BA9C007BBBF7 /* assembly_grammar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B01A29425A1700B30DA7 /* assembly_grammar.cpp */; }; + DCFD7E8B2A45BA9C007BBBF7 /* amd_ext_to_khr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B14A29425A1800B30DA7 /* amd_ext_to_khr.cpp */; }; + DCFD7E8C2A45BA9C007BBBF7 /* text_handler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B32229425A1800B30DA7 /* text_handler.cpp */; }; + DCFD7E8D2A45BA9C007BBBF7 /* optimizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B09E29425A1700B30DA7 /* optimizer.cpp */; }; + DCFD7E8E2A45BA9C007BBBF7 /* validation_state.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B35629425A1800B30DA7 /* validation_state.cpp */; }; + DCFD7E8F2A45BA9C007BBBF7 /* mem_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0DC29425A1700B30DA7 /* mem_pass.cpp */; }; + DCFD7E902A45BA9C007BBBF7 /* replace_desc_array_access_using_var_index.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B16429425A1800B30DA7 /* replace_desc_array_access_using_var_index.cpp */; }; + DCFD7E912A45BA9C007BBBF7 /* ir_loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0ED29425A1700B30DA7 /* ir_loader.cpp */; }; + DCFD7E922A45BA9C007BBBF7 /* extensions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B01C29425A1700B30DA7 /* extensions.cpp */; }; + DCFD7E932A45BA9C007BBBF7 /* type_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0E629425A1700B30DA7 /* type_manager.cpp */; }; + DCFD7E942A45BA9C007BBBF7 /* scalar_replacement_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B14B29425A1800B30DA7 /* scalar_replacement_pass.cpp */; }; + DCFD7E952A45BA9C007BBBF7 /* loop_unswitch_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0E429425A1700B30DA7 /* loop_unswitch_pass.cpp */; }; + DCFD7E962A45BA9C007BBBF7 /* reduction_opportunity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B05C29425A1700B30DA7 /* reduction_opportunity.cpp */; }; + DCFD7E972A45BA9C007BBBF7 /* validate_extensions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B33A29425A1800B30DA7 /* validate_extensions.cpp */; }; + DCFD7E982A45BA9C007BBBF7 /* remove_unused_struct_member_reduction_opportunity_finder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B06C29425A1700B30DA7 /* remove_unused_struct_member_reduction_opportunity_finder.cpp */; }; + DCFD7E992A45BA9C007BBBF7 /* timer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B02529425A1700B30DA7 /* timer.cpp */; }; + DCFD7E9A2A45BA9C007BBBF7 /* pch_source_opt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B10529425A1800B30DA7 /* pch_source_opt.cpp */; }; + DCFD7E9B2A45BA9C007BBBF7 /* inline_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0EB29425A1700B30DA7 /* inline_pass.cpp */; }; + DCFD7E9C2A45BA9C007BBBF7 /* inst_buff_addr_check_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0FC29425A1700B30DA7 /* inst_buff_addr_check_pass.cpp */; }; + DCFD7E9D2A45BA9C007BBBF7 /* validate_barriers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B32929425A1800B30DA7 /* validate_barriers.cpp */; }; + DCFD7E9E2A45BA9C007BBBF7 /* redundancy_elimination.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B15029425A1800B30DA7 /* redundancy_elimination.cpp */; }; + DCFD7E9F2A45BA9C007BBBF7 /* spirv_endian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B08129425A1700B30DA7 /* spirv_endian.cpp */; }; + DCFD7EA02A45BA9C007BBBF7 /* cfg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0B829425A1700B30DA7 /* cfg.cpp */; }; + DCFD7EA12A45BA9C007BBBF7 /* remove_duplicates_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0DE29425A1700B30DA7 /* remove_duplicates_pass.cpp */; }; + DCFD7EA22A45BA9C007BBBF7 /* validate_annotation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B32429425A1800B30DA7 /* validate_annotation.cpp */; }; + DCFD7EA32A45BA9C007BBBF7 /* loop_dependence_helpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B14629425A1800B30DA7 /* loop_dependence_helpers.cpp */; }; + DCFD7EA42A45BA9C007BBBF7 /* basic_block.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B17429425A1800B30DA7 /* basic_block.cpp */; }; + DCFD7EA52A45BA9C007BBBF7 /* loop_dependence.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0D629425A1700B30DA7 /* loop_dependence.cpp */; }; + DCFD7EA62A45BA9C007BBBF7 /* licm_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0F029425A1700B30DA7 /* licm_pass.cpp */; }; + DCFD7EA72A45BA9C007BBBF7 /* operand_to_undef_reduction_opportunity_finder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B05829425A1700B30DA7 /* operand_to_undef_reduction_opportunity_finder.cpp */; }; + DCFD7EA82A45BA9C007BBBF7 /* dead_branch_elim_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B10C29425A1800B30DA7 /* dead_branch_elim_pass.cpp */; }; + DCFD7EA92A45BA9C007BBBF7 /* inst_debug_printf_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0D929425A1700B30DA7 /* inst_debug_printf_pass.cpp */; }; + DCFD7EAA2A45BA9C007BBBF7 /* local_redundancy_elimination.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0C029425A1700B30DA7 /* local_redundancy_elimination.cpp */; }; + DCFD7EAB2A45BA9C007BBBF7 /* validate_memory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B34929425A1800B30DA7 /* validate_memory.cpp */; }; + DCFD7EAC2A45BA9C007BBBF7 /* dominator_analysis.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B16229425A1800B30DA7 /* dominator_analysis.cpp */; }; + DCFD7EAD2A45BA9C007BBBF7 /* validate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B33629425A1800B30DA7 /* validate.cpp */; }; + DCFD7EAE2A45BA9C007BBBF7 /* copy_prop_arrays.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B12A29425A1800B30DA7 /* copy_prop_arrays.cpp */; }; + DCFD7EAF2A45BA9C007BBBF7 /* structured_construct_to_block_reduction_opportunity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B06A29425A1700B30DA7 /* structured_construct_to_block_reduction_opportunity.cpp */; }; + DCFD7EB02A45BA9C007BBBF7 /* validate_composites.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B35529425A1800B30DA7 /* validate_composites.cpp */; }; + DCFD7EB12A45BA9C007BBBF7 /* loop_fusion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B17C29425A1800B30DA7 /* loop_fusion.cpp */; }; + DCFD7EB22A45BA9C007BBBF7 /* basic_block.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B35229425A1800B30DA7 /* basic_block.cpp */; }; + DCFD7EB32A45BA9C007BBBF7 /* remove_unused_interface_variables_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B15D29425A1800B30DA7 /* remove_unused_interface_variables_pass.cpp */; }; + DCFD7EB42A45BA9C007BBBF7 /* validate_function.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B35329425A1800B30DA7 /* validate_function.cpp */; }; + DCFD7EB52A45BA9C007BBBF7 /* vector_dce.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B0F429425A1700B30DA7 /* vector_dce.cpp */; }; + DCFD7EB62A45BA9C007BBBF7 /* validate_primitives.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B35729425A1800B30DA7 /* validate_primitives.cpp */; }; + DCFD7EB72A45BA9C007BBBF7 /* simplification_pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B10B29425A1800B30DA7 /* simplification_pass.cpp */; }; + DCFD7EB82A45BA9C007BBBF7 /* propagator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B14429425A1800B30DA7 /* propagator.cpp */; }; + DCFD7EB92A45BA9C007BBBF7 /* simple_conditional_branch_to_branch_opportunity_finder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B04329425A1700B30DA7 /* simple_conditional_branch_to_branch_opportunity_finder.cpp */; }; + DCFD7EBA2A45BA9C007BBBF7 /* remove_instruction_reduction_opportunity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B05029425A1700B30DA7 /* remove_instruction_reduction_opportunity.cpp */; }; + DCFD7EBB2A45BA9C007BBBF7 /* validate_arithmetics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9F7B34429425A1800B30DA7 /* validate_arithmetics.cpp */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -1785,6 +2343,27 @@ remoteGlobalIDString = A972ABDD21CED7CB0013AB25; remoteInfo = "glslang-macOS"; }; + DCFD7ECC2A45BC08007BBBF7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A9F55D25198BE6A7004EC31B /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCFD7C892A45BA7D007BBBF7; + remoteInfo = "SPIRV-Cross-xrOS"; + }; + DCFD7ECE2A45BC0C007BBBF7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A9F55D25198BE6A7004EC31B /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCFD7D0C2A45BA9C007BBBF7; + remoteInfo = "SPIRV-Tools-xrOS"; + }; + DCFD7ED02A45BC10007BBBF7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A9F55D25198BE6A7004EC31B /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCFD7CA42A45BA92007BBBF7; + remoteInfo = "glslang-xrOS"; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ @@ -2361,6 +2940,9 @@ A9F7B35729425A1800B30DA7 /* validate_primitives.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = validate_primitives.cpp; sourceTree = ""; }; A9F7B35829425A1800B30DA7 /* decoration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = decoration.h; sourceTree = ""; }; A9FC5F7F249DA96D003CB086 /* package_ext_libs_finish.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = package_ext_libs_finish.sh; sourceTree = ""; }; + DCFD7CA32A45BA7D007BBBF7 /* libSPIRVCross.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSPIRVCross.a; sourceTree = BUILT_PRODUCTS_DIR; }; + DCFD7D0B2A45BA92007BBBF7 /* libglslang.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libglslang.a; sourceTree = BUILT_PRODUCTS_DIR; }; + DCFD7EC02A45BA9C007BBBF7 /* libSPIRVTools.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSPIRVTools.a; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXGroup section */ @@ -2651,6 +3233,9 @@ A90FD9E921CC519E00B92BB2 /* External */, A9679AAB21D2699800856BF7 /* Scripts */, A972AD2421CEE30F0013AB25 /* Products */, + DCFD7CA32A45BA7D007BBBF7 /* libSPIRVCross.a */, + DCFD7D0B2A45BA92007BBBF7 /* libglslang.a */, + DCFD7EC02A45BA9C007BBBF7 /* libSPIRVTools.a */, ); sourceTree = ""; }; @@ -4034,6 +4619,299 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + DCFD7C8A2A45BA7D007BBBF7 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DCFD7C8B2A45BA7D007BBBF7 /* spirv_cfg.hpp in Headers */, + DCFD7C8C2A45BA7D007BBBF7 /* spirv_cross_parsed_ir.hpp in Headers */, + DCFD7C8D2A45BA7D007BBBF7 /* spirv_common.hpp in Headers */, + DCFD7C8E2A45BA7D007BBBF7 /* spirv_glsl.hpp in Headers */, + DCFD7C8F2A45BA7D007BBBF7 /* spirv_parser.hpp in Headers */, + DCFD7C902A45BA7D007BBBF7 /* spirv_cross_util.hpp in Headers */, + DCFD7C912A45BA7D007BBBF7 /* spirv_cross_containers.hpp in Headers */, + DCFD7C922A45BA7D007BBBF7 /* spirv.hpp in Headers */, + DCFD7C932A45BA7D007BBBF7 /* spirv_cross_error_handling.hpp in Headers */, + DCFD7C942A45BA7D007BBBF7 /* spirv_cross.hpp in Headers */, + DCFD7C952A45BA7D007BBBF7 /* spirv_msl.hpp in Headers */, + DCFD7C962A45BA7D007BBBF7 /* spirv_reflect.hpp in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCFD7CA52A45BA92007BBBF7 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DCFD7CA62A45BA92007BBBF7 /* propagateNoContraction.h in Headers */, + DCFD7CA72A45BA92007BBBF7 /* disassemble.h in Headers */, + DCFD7CA82A45BA92007BBBF7 /* PpContext.h in Headers */, + DCFD7CA92A45BA92007BBBF7 /* InfoSink.h in Headers */, + DCFD7CAA2A45BA92007BBBF7 /* bitutils.h in Headers */, + DCFD7CAB2A45BA92007BBBF7 /* SpvBuilder.h in Headers */, + DCFD7CAC2A45BA92007BBBF7 /* GLSL.std.450.h in Headers */, + DCFD7CAD2A45BA92007BBBF7 /* Logger.h in Headers */, + DCFD7CAE2A45BA92007BBBF7 /* pch.h in Headers */, + DCFD7CAF2A45BA92007BBBF7 /* LiveTraverser.h in Headers */, + DCFD7CB02A45BA92007BBBF7 /* spvIR.h in Headers */, + DCFD7CB12A45BA92007BBBF7 /* glslang_c_shader_types.h in Headers */, + DCFD7CB22A45BA92007BBBF7 /* attribute.h in Headers */, + DCFD7CB32A45BA92007BBBF7 /* Scan.h in Headers */, + DCFD7CB42A45BA92007BBBF7 /* Types.h in Headers */, + DCFD7CB52A45BA92007BBBF7 /* PoolAlloc.h in Headers */, + DCFD7CB62A45BA92007BBBF7 /* InitializeGlobals.h in Headers */, + DCFD7CB72A45BA92007BBBF7 /* parseVersions.h in Headers */, + DCFD7CB82A45BA92007BBBF7 /* osinclude.h in Headers */, + DCFD7CB92A45BA92007BBBF7 /* gl_types.h in Headers */, + DCFD7CBA2A45BA92007BBBF7 /* localintermediate.h in Headers */, + DCFD7CBB2A45BA92007BBBF7 /* GLSL.ext.AMD.h in Headers */, + DCFD7CBC2A45BA92007BBBF7 /* reflection.h in Headers */, + DCFD7CBD2A45BA92007BBBF7 /* ShHandle.h in Headers */, + DCFD7CBE2A45BA92007BBBF7 /* iomapper.h in Headers */, + DCFD7CBF2A45BA92007BBBF7 /* GLSL.ext.NV.h in Headers */, + DCFD7CC02A45BA92007BBBF7 /* Versions.h in Headers */, + DCFD7CC12A45BA92007BBBF7 /* SPVRemapper.h in Headers */, + DCFD7CC22A45BA92007BBBF7 /* ConstantUnion.h in Headers */, + DCFD7CC32A45BA92007BBBF7 /* doc.h in Headers */, + DCFD7CC42A45BA92007BBBF7 /* Initialize.h in Headers */, + DCFD7CC52A45BA92007BBBF7 /* GLSL.ext.EXT.h in Headers */, + DCFD7CC62A45BA92007BBBF7 /* ResourceLimits.h in Headers */, + DCFD7CC72A45BA92007BBBF7 /* Common.h in Headers */, + DCFD7CC82A45BA92007BBBF7 /* GLSL.ext.KHR.h in Headers */, + DCFD7CC92A45BA92007BBBF7 /* intermediate.h in Headers */, + DCFD7CCA2A45BA92007BBBF7 /* ShaderLang.h in Headers */, + DCFD7CCB2A45BA92007BBBF7 /* ScanContext.h in Headers */, + DCFD7CCC2A45BA92007BBBF7 /* PpTokens.h in Headers */, + DCFD7CCD2A45BA92007BBBF7 /* BaseTypes.h in Headers */, + DCFD7CCE2A45BA92007BBBF7 /* hex_float.h in Headers */, + DCFD7CCF2A45BA92007BBBF7 /* SpvTools.h in Headers */, + DCFD7CD02A45BA92007BBBF7 /* RemoveTree.h in Headers */, + DCFD7CD12A45BA92007BBBF7 /* SymbolTable.h in Headers */, + DCFD7CD22A45BA92007BBBF7 /* arrays.h in Headers */, + DCFD7CD32A45BA92007BBBF7 /* spirv.hpp in Headers */, + DCFD7CD42A45BA92007BBBF7 /* glslang_c_interface.h in Headers */, + DCFD7CD52A45BA92007BBBF7 /* GlslangToSpv.h in Headers */, + DCFD7CD62A45BA92007BBBF7 /* SpirvIntrinsics.h in Headers */, + DCFD7CD72A45BA92007BBBF7 /* NonSemanticDebugPrintf.h in Headers */, + DCFD7CD82A45BA92007BBBF7 /* glslang_tab.cpp.h in Headers */, + DCFD7CD92A45BA92007BBBF7 /* ParseHelper.h in Headers */, + DCFD7CDA2A45BA92007BBBF7 /* InitializeDll.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCFD7D0D2A45BA9C007BBBF7 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DCFD7D0E2A45BA9C007BBBF7 /* replace_invalid_opc.h in Headers */, + DCFD7D0F2A45BA9C007BBBF7 /* convert_to_sampled_image_pass.h in Headers */, + DCFD7D102A45BA9C007BBBF7 /* text_handler.h in Headers */, + DCFD7D112A45BA9C007BBBF7 /* types.h in Headers */, + DCFD7D122A45BA9C007BBBF7 /* dead_insert_elim_pass.h in Headers */, + DCFD7D132A45BA9C007BBBF7 /* parse_number.h in Headers */, + DCFD7D142A45BA9C007BBBF7 /* make_unique.h in Headers */, + DCFD7D152A45BA9C007BBBF7 /* function.h in Headers */, + DCFD7D162A45BA9C007BBBF7 /* inst_debug_printf_pass.h in Headers */, + DCFD7D172A45BA9C007BBBF7 /* block_merge_pass.h in Headers */, + DCFD7D182A45BA9C007BBBF7 /* scalar_analysis.h in Headers */, + DCFD7D192A45BA9C007BBBF7 /* composite.h in Headers */, + DCFD7D1A2A45BA9C007BBBF7 /* enum_set.h in Headers */, + DCFD7D1B2A45BA9C007BBBF7 /* lints.h in Headers */, + DCFD7D1C2A45BA9C007BBBF7 /* freeze_spec_constant_value_pass.h in Headers */, + DCFD7D1D2A45BA9C007BBBF7 /* reduction_opportunity.h in Headers */, + DCFD7D1E2A45BA9C007BBBF7 /* ir_context.h in Headers */, + DCFD7D1F2A45BA9C007BBBF7 /* loop_utils.h in Headers */, + DCFD7D202A45BA9C007BBBF7 /* relax_float_ops_pass.h in Headers */, + DCFD7D212A45BA9C007BBBF7 /* pass.h in Headers */, + DCFD7D222A45BA9C007BBBF7 /* inline_opaque_pass.h in Headers */, + DCFD7D232A45BA9C007BBBF7 /* strength_reduction_pass.h in Headers */, + DCFD7D242A45BA9C007BBBF7 /* pch_source.h in Headers */, + DCFD7D252A45BA9C007BBBF7 /* graphics_robust_access_pass.h in Headers */, + DCFD7D262A45BA9C007BBBF7 /* scalar_analysis_nodes.h in Headers */, + DCFD7D272A45BA9C007BBBF7 /* operand_to_const_reduction_opportunity_finder.h in Headers */, + DCFD7D282A45BA9C007BBBF7 /* basic_block.h in Headers */, + DCFD7D292A45BA9C007BBBF7 /* strip_nonsemantic_info_pass.h in Headers */, + DCFD7D2A2A45BA9C007BBBF7 /* fold.h in Headers */, + DCFD7D2B2A45BA9C007BBBF7 /* instruction.h in Headers */, + DCFD7D2C2A45BA9C007BBBF7 /* unify_const_pass.h in Headers */, + DCFD7D2D2A45BA9C007BBBF7 /* vector_dce.h in Headers */, + DCFD7D2E2A45BA9C007BBBF7 /* structured_construct_to_block_reduction_opportunity.h in Headers */, + DCFD7D2F2A45BA9C007BBBF7 /* spirv_target_env.h in Headers */, + DCFD7D302A45BA9C007BBBF7 /* loop_fusion.h in Headers */, + DCFD7D312A45BA9C007BBBF7 /* print.h in Headers */, + DCFD7D322A45BA9C007BBBF7 /* structured_loop_to_selection_reduction_opportunity.h in Headers */, + DCFD7D332A45BA9C007BBBF7 /* dominator_tree.h in Headers */, + DCFD7D342A45BA9C007BBBF7 /* dead_branch_elim_pass.h in Headers */, + DCFD7D352A45BA9C007BBBF7 /* ccp_pass.h in Headers */, + DCFD7D362A45BA9C007BBBF7 /* validate.h in Headers */, + DCFD7D372A45BA9C007BBBF7 /* construct.h in Headers */, + DCFD7D382A45BA9C007BBBF7 /* null_pass.h in Headers */, + DCFD7D392A45BA9C007BBBF7 /* constants.h in Headers */, + DCFD7D3A2A45BA9C007BBBF7 /* validation_state.h in Headers */, + DCFD7D3B2A45BA9C007BBBF7 /* instruction.h in Headers */, + DCFD7D3C2A45BA9C007BBBF7 /* loop_unswitch_pass.h in Headers */, + DCFD7D3D2A45BA9C007BBBF7 /* tree_iterator.h in Headers */, + DCFD7D3E2A45BA9C007BBBF7 /* remove_struct_member_reduction_opportunity.h in Headers */, + DCFD7D3F2A45BA9C007BBBF7 /* validate_scopes.h in Headers */, + DCFD7D402A45BA9C007BBBF7 /* passes.h in Headers */, + DCFD7D412A45BA9C007BBBF7 /* interp_fixup_pass.h in Headers */, + DCFD7D422A45BA9C007BBBF7 /* validate_memory_semantics.h in Headers */, + DCFD7D432A45BA9C007BBBF7 /* hash_combine.h in Headers */, + DCFD7D442A45BA9C007BBBF7 /* conditional_branch_to_simple_conditional_branch_opportunity_finder.h in Headers */, + DCFD7D452A45BA9C007BBBF7 /* strip_debug_info_pass.h in Headers */, + DCFD7D462A45BA9C007BBBF7 /* pch_source_opt.h in Headers */, + DCFD7D472A45BA9C007BBBF7 /* merge_blocks_reduction_opportunity_finder.h in Headers */, + DCFD7D482A45BA9C007BBBF7 /* reduction_pass.h in Headers */, + DCFD7D492A45BA9C007BBBF7 /* local_single_store_elim_pass.h in Headers */, + DCFD7D4A2A45BA9C007BBBF7 /* latest_version_opencl_std_header.h in Headers */, + DCFD7D4B2A45BA9C007BBBF7 /* remove_block_reduction_opportunity.h in Headers */, + DCFD7D4C2A45BA9C007BBBF7 /* remove_function_reduction_opportunity_finder.h in Headers */, + DCFD7D4D2A45BA9C007BBBF7 /* instruction.h in Headers */, + DCFD7D4E2A45BA9C007BBBF7 /* eliminate_dead_functions_pass.h in Headers */, + DCFD7D4F2A45BA9C007BBBF7 /* bit_vector.h in Headers */, + DCFD7D502A45BA9C007BBBF7 /* assembly_grammar.h in Headers */, + DCFD7D512A45BA9C007BBBF7 /* loop_dependence.h in Headers */, + DCFD7D522A45BA9C007BBBF7 /* simple_conditional_branch_to_branch_reduction_opportunity.h in Headers */, + DCFD7D532A45BA9C007BBBF7 /* folding_rules.h in Headers */, + DCFD7D542A45BA9C007BBBF7 /* eliminate_dead_members_pass.h in Headers */, + DCFD7D552A45BA9C007BBBF7 /* reduction_util.h in Headers */, + DCFD7D562A45BA9C007BBBF7 /* table.h in Headers */, + DCFD7D572A45BA9C007BBBF7 /* basic_block.h in Headers */, + DCFD7D582A45BA9C007BBBF7 /* remove_block_reduction_opportunity_finder.h in Headers */, + DCFD7D592A45BA9C007BBBF7 /* remove_dontinline_pass.h in Headers */, + DCFD7D5A2A45BA9C007BBBF7 /* operand_to_dominating_id_reduction_opportunity_finder.h in Headers */, + DCFD7D5B2A45BA9C007BBBF7 /* operand.h in Headers */, + DCFD7D5C2A45BA9C007BBBF7 /* disassemble.h in Headers */, + DCFD7D5D2A45BA9C007BBBF7 /* remove_unused_instruction_reduction_opportunity_finder.h in Headers */, + DCFD7D5E2A45BA9C007BBBF7 /* value_number_table.h in Headers */, + DCFD7D5F2A45BA9C007BBBF7 /* small_vector.h in Headers */, + DCFD7D602A45BA9C007BBBF7 /* log.h in Headers */, + DCFD7D612A45BA9C007BBBF7 /* ilist_node.h in Headers */, + DCFD7D622A45BA9C007BBBF7 /* feature_manager.h in Headers */, + DCFD7D632A45BA9C007BBBF7 /* loop_fission.h in Headers */, + DCFD7D642A45BA9C007BBBF7 /* interface_var_sroa.h in Headers */, + DCFD7D652A45BA9C007BBBF7 /* licm_pass.h in Headers */, + DCFD7D662A45BA9C007BBBF7 /* convert_to_half_pass.h in Headers */, + DCFD7D672A45BA9C007BBBF7 /* structured_construct_to_block_reduction_opportunity_finder.h in Headers */, + DCFD7D682A45BA9C007BBBF7 /* fold_spec_constant_op_and_composite_pass.h in Headers */, + DCFD7D692A45BA9C007BBBF7 /* cfg.h in Headers */, + DCFD7D6A2A45BA9C007BBBF7 /* remove_selection_reduction_opportunity.h in Headers */, + DCFD7D6B2A45BA9C007BBBF7 /* opcode.h in Headers */, + DCFD7D6C2A45BA9C007BBBF7 /* flatten_decoration_pass.h in Headers */, + DCFD7D6D2A45BA9C007BBBF7 /* private_to_local_pass.h in Headers */, + DCFD7D6E2A45BA9C007BBBF7 /* wrap_opkill.h in Headers */, + DCFD7D6F2A45BA9C007BBBF7 /* text.h in Headers */, + DCFD7D702A45BA9C007BBBF7 /* string_utils.h in Headers */, + DCFD7D712A45BA9C007BBBF7 /* debug_info_manager.h in Headers */, + DCFD7D722A45BA9C007BBBF7 /* fix_storage_class.h in Headers */, + DCFD7D732A45BA9C007BBBF7 /* copy_prop_arrays.h in Headers */, + DCFD7D742A45BA9C007BBBF7 /* change_operand_to_undef_reduction_opportunity.h in Headers */, + DCFD7D752A45BA9C007BBBF7 /* lcs.h in Headers */, + DCFD7D762A45BA9C007BBBF7 /* ilist.h in Headers */, + DCFD7D772A45BA9C007BBBF7 /* structured_loop_to_selection_reduction_opportunity_finder.h in Headers */, + DCFD7D782A45BA9C007BBBF7 /* function.h in Headers */, + DCFD7D792A45BA9C007BBBF7 /* eliminate_dead_constant_pass.h in Headers */, + DCFD7D7A2A45BA9C007BBBF7 /* reduce_load_size.h in Headers */, + DCFD7D7B2A45BA9C007BBBF7 /* set_spec_constant_default_value_pass.h in Headers */, + DCFD7D7C2A45BA9C007BBBF7 /* diagnostic.h in Headers */, + DCFD7D7D2A45BA9C007BBBF7 /* dataflow.h in Headers */, + DCFD7D7E2A45BA9C007BBBF7 /* merge_blocks_reduction_opportunity.h in Headers */, + DCFD7D7F2A45BA9C007BBBF7 /* module.h in Headers */, + DCFD7D802A45BA9C007BBBF7 /* spirv_optimizer_options.h in Headers */, + DCFD7D812A45BA9C007BBBF7 /* ext_inst.h in Headers */, + DCFD7D822A45BA9C007BBBF7 /* spirv_reducer_options.h in Headers */, + DCFD7D832A45BA9C007BBBF7 /* decoration.h in Headers */, + DCFD7D842A45BA9C007BBBF7 /* inst_buff_addr_check_pass.h in Headers */, + DCFD7D852A45BA9C007BBBF7 /* iterator.h in Headers */, + DCFD7D862A45BA9C007BBBF7 /* latest_version_glsl_std_450_header.h in Headers */, + DCFD7D872A45BA9C007BBBF7 /* pch_source_reduce.h in Headers */, + DCFD7D882A45BA9C007BBBF7 /* name_mapper.h in Headers */, + DCFD7D892A45BA9C007BBBF7 /* liveness.h in Headers */, + DCFD7D8A2A45BA9C007BBBF7 /* local_redundancy_elimination.h in Headers */, + DCFD7D8B2A45BA9C007BBBF7 /* simple_conditional_branch_to_branch_opportunity_finder.h in Headers */, + DCFD7D8C2A45BA9C007BBBF7 /* instruction_list.h in Headers */, + DCFD7D8D2A45BA9C007BBBF7 /* diff.h in Headers */, + DCFD7D8E2A45BA9C007BBBF7 /* instrument_pass.h in Headers */, + DCFD7D8F2A45BA9C007BBBF7 /* binary.h in Headers */, + DCFD7D902A45BA9C007BBBF7 /* inline_pass.h in Headers */, + DCFD7D912A45BA9C007BBBF7 /* loop_fusion_pass.h in Headers */, + DCFD7D922A45BA9C007BBBF7 /* dead_variable_elimination.h in Headers */, + DCFD7D932A45BA9C007BBBF7 /* remove_unused_interface_variables_pass.h in Headers */, + DCFD7D942A45BA9C007BBBF7 /* remove_unused_struct_member_reduction_opportunity_finder.h in Headers */, + DCFD7D952A45BA9C007BBBF7 /* simplification_pass.h in Headers */, + DCFD7D962A45BA9C007BBBF7 /* remove_duplicates_pass.h in Headers */, + DCFD7D972A45BA9C007BBBF7 /* eliminate_dead_io_components_pass.h in Headers */, + DCFD7D982A45BA9C007BBBF7 /* enum_string_mapping.h in Headers */, + DCFD7D992A45BA9C007BBBF7 /* hex_float.h in Headers */, + DCFD7D9A2A45BA9C007BBBF7 /* spirv_validator_options.h in Headers */, + DCFD7D9B2A45BA9C007BBBF7 /* desc_sroa_util.h in Headers */, + DCFD7D9C2A45BA9C007BBBF7 /* remove_selection_reduction_opportunity_finder.h in Headers */, + DCFD7D9D2A45BA9C007BBBF7 /* pass_manager.h in Headers */, + DCFD7D9E2A45BA9C007BBBF7 /* dominator_analysis.h in Headers */, + DCFD7D9F2A45BA9C007BBBF7 /* spirv_definition.h in Headers */, + DCFD7DA02A45BA9C007BBBF7 /* block_merge_util.h in Headers */, + DCFD7DA12A45BA9C007BBBF7 /* remove_function_reduction_opportunity.h in Headers */, + DCFD7DA22A45BA9C007BBBF7 /* reducer.h in Headers */, + DCFD7DA32A45BA9C007BBBF7 /* def_use_manager.h in Headers */, + DCFD7DA42A45BA9C007BBBF7 /* type_manager.h in Headers */, + DCFD7DA52A45BA9C007BBBF7 /* common_debug_info.h in Headers */, + DCFD7DA62A45BA9C007BBBF7 /* cfg_cleanup_pass.h in Headers */, + DCFD7DA72A45BA9C007BBBF7 /* desc_sroa.h in Headers */, + DCFD7DA82A45BA9C007BBBF7 /* local_single_block_elim_pass.h in Headers */, + DCFD7DA92A45BA9C007BBBF7 /* spirv_endian.h in Headers */, + DCFD7DAA2A45BA9C007BBBF7 /* redundancy_elimination.h in Headers */, + DCFD7DAB2A45BA9C007BBBF7 /* combine_access_chains.h in Headers */, + DCFD7DAC2A45BA9C007BBBF7 /* latest_version_spirv_header.h in Headers */, + DCFD7DAD2A45BA9C007BBBF7 /* eliminate_dead_output_stores_pass.h in Headers */, + DCFD7DAE2A45BA9C007BBBF7 /* spread_volatile_semantics.h in Headers */, + DCFD7DAF2A45BA9C007BBBF7 /* ir_builder.h in Headers */, + DCFD7DB02A45BA9C007BBBF7 /* build_module.h in Headers */, + DCFD7DB12A45BA9C007BBBF7 /* inline_exhaustive_pass.h in Headers */, + DCFD7DB22A45BA9C007BBBF7 /* reduction_opportunity_finder.h in Headers */, + DCFD7DB32A45BA9C007BBBF7 /* divergence_analysis.h in Headers */, + DCFD7DB42A45BA9C007BBBF7 /* upgrade_memory_model.h in Headers */, + DCFD7DB52A45BA9C007BBBF7 /* bitutils.h in Headers */, + DCFD7DB62A45BA9C007BBBF7 /* parsed_operand.h in Headers */, + DCFD7DB72A45BA9C007BBBF7 /* spirv_constant.h in Headers */, + DCFD7DB82A45BA9C007BBBF7 /* fix_func_call_arguments.h in Headers */, + DCFD7DB92A45BA9C007BBBF7 /* eliminate_dead_functions_util.h in Headers */, + DCFD7DBA2A45BA9C007BBBF7 /* loop_unroller.h in Headers */, + DCFD7DBB2A45BA9C007BBBF7 /* ssa_rewrite_pass.h in Headers */, + DCFD7DBC2A45BA9C007BBBF7 /* propagator.h in Headers */, + DCFD7DBD2A45BA9C007BBBF7 /* loop_descriptor.h in Headers */, + DCFD7DBE2A45BA9C007BBBF7 /* merge_return_pass.h in Headers */, + DCFD7DBF2A45BA9C007BBBF7 /* empty_pass.h in Headers */, + DCFD7DC02A45BA9C007BBBF7 /* scalar_replacement_pass.h in Headers */, + DCFD7DC12A45BA9C007BBBF7 /* code_sink.h in Headers */, + DCFD7DC22A45BA9C007BBBF7 /* change_operand_reduction_opportunity.h in Headers */, + DCFD7DC32A45BA9C007BBBF7 /* analyze_live_input_pass.h in Headers */, + DCFD7DC42A45BA9C007BBBF7 /* cfa.h in Headers */, + DCFD7DC52A45BA9C007BBBF7 /* amd_ext_to_khr.h in Headers */, + DCFD7DC62A45BA9C007BBBF7 /* decoration_manager.h in Headers */, + DCFD7DC72A45BA9C007BBBF7 /* loop_peeling.h in Headers */, + DCFD7DC82A45BA9C007BBBF7 /* replace_desc_array_access_using_var_index.h in Headers */, + DCFD7DC92A45BA9C007BBBF7 /* reflect.h in Headers */, + DCFD7DCA2A45BA9C007BBBF7 /* compact_ids_pass.h in Headers */, + DCFD7DCB2A45BA9C007BBBF7 /* macro.h in Headers */, + DCFD7DCC2A45BA9C007BBBF7 /* timer.h in Headers */, + DCFD7DCD2A45BA9C007BBBF7 /* extensions.h in Headers */, + DCFD7DCE2A45BA9C007BBBF7 /* mem_pass.h in Headers */, + DCFD7DCF2A45BA9C007BBBF7 /* local_access_chain_convert_pass.h in Headers */, + DCFD7DD02A45BA9C007BBBF7 /* remove_instruction_reduction_opportunity.h in Headers */, + DCFD7DD12A45BA9C007BBBF7 /* control_dependence.h in Headers */, + DCFD7DD22A45BA9C007BBBF7 /* ir_loader.h in Headers */, + DCFD7DD32A45BA9C007BBBF7 /* conditional_branch_to_simple_conditional_branch_reduction_opportunity.h in Headers */, + DCFD7DD42A45BA9C007BBBF7 /* workaround1209.h in Headers */, + DCFD7DD52A45BA9C007BBBF7 /* register_pressure.h in Headers */, + DCFD7DD62A45BA9C007BBBF7 /* operand_to_undef_reduction_opportunity_finder.h in Headers */, + DCFD7DD72A45BA9C007BBBF7 /* struct_cfg_analysis.h in Headers */, + DCFD7DD82A45BA9C007BBBF7 /* spirv_fuzzer_options.h in Headers */, + DCFD7DD92A45BA9C007BBBF7 /* const_folding_rules.h in Headers */, + DCFD7DDA2A45BA9C007BBBF7 /* inst_bindless_check_pass.h in Headers */, + DCFD7DDB2A45BA9C007BBBF7 /* aggressive_dead_code_elim_pass.h in Headers */, + DCFD7DDC2A45BA9C007BBBF7 /* if_conversion.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ @@ -4190,6 +5068,57 @@ productReference = A972ABF021CED7CB0013AB25 /* libglslang.a */; productType = "com.apple.product-type.library.static"; }; + DCFD7C892A45BA7D007BBBF7 /* SPIRV-Cross-xrOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = DCFD7CA02A45BA7D007BBBF7 /* Build configuration list for PBXNativeTarget "SPIRV-Cross-xrOS" */; + buildPhases = ( + DCFD7C8A2A45BA7D007BBBF7 /* Headers */, + DCFD7C972A45BA7D007BBBF7 /* Sources */, + DCFD7C9F2A45BA7D007BBBF7 /* Copy to Staging */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "SPIRV-Cross-xrOS"; + productName = "SPIRV-Cross-xrOS"; + productReference = DCFD7CA32A45BA7D007BBBF7 /* libSPIRVCross.a */; + productType = "com.apple.product-type.library.static"; + }; + DCFD7CA42A45BA92007BBBF7 /* glslang-xrOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = DCFD7D082A45BA92007BBBF7 /* Build configuration list for PBXNativeTarget "glslang-xrOS" */; + buildPhases = ( + DCFD7CA52A45BA92007BBBF7 /* Headers */, + DCFD7CDB2A45BA92007BBBF7 /* Sources */, + DCFD7D072A45BA92007BBBF7 /* Copy to Staging */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "glslang-xrOS"; + productName = "SPIRV-Cross-xrOS"; + productReference = DCFD7D0B2A45BA92007BBBF7 /* libglslang.a */; + productType = "com.apple.product-type.library.static"; + }; + DCFD7D0C2A45BA9C007BBBF7 /* SPIRV-Tools-xrOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = DCFD7EBD2A45BA9C007BBBF7 /* Build configuration list for PBXNativeTarget "SPIRV-Tools-xrOS" */; + buildPhases = ( + DCFD7D0D2A45BA9C007BBBF7 /* Headers */, + DCFD7DDD2A45BA9C007BBBF7 /* Sources */, + DCFD7EBC2A45BA9C007BBBF7 /* Copy to Staging */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "SPIRV-Tools-xrOS"; + productName = "SPIRV-Cross-xrOS"; + productReference = DCFD7EC02A45BA9C007BBBF7 /* libSPIRVTools.a */; + productType = "com.apple.product-type.library.static"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -4212,6 +5141,9 @@ A972A7F221CEC81B0013AB25 = { ProvisioningStyle = Automatic; }; + DCFD7EC12A45BAAA007BBBF7 = { + ProvisioningStyle = Automatic; + }; }; }; buildConfigurationList = A9F55D28198BE6A7004EC31B /* Build configuration list for PBXProject "ExternalDependencies" */; @@ -4230,15 +5162,19 @@ A972A7F221CEC81B0013AB25 /* ExternalDependencies */, A972A7EA21CEC8030013AB25 /* ExternalDependencies-iOS */, 2FEA0ADD2490320500EEF3AD /* ExternalDependencies-tvOS */, + DCFD7EC12A45BAAA007BBBF7 /* ExternalDependencies-xrOS */, A972A7E421CEC72F0013AB25 /* ExternalDependencies-macOS */, A90FD75B21CC4EAB00B92BB2 /* SPIRV-Cross-iOS */, 2FEA0CD92490322B00EEF3AD /* SPIRV-Cross-tvOS */, + DCFD7C892A45BA7D007BBBF7 /* SPIRV-Cross-xrOS */, A90FD8A021CC4EB900B92BB2 /* SPIRV-Cross-macOS */, A972A7FC21CECBBF0013AB25 /* SPIRV-Tools-iOS */, 2FEA0B4B2490322100EEF3AD /* SPIRV-Tools-tvOS */, + DCFD7D0C2A45BA9C007BBBF7 /* SPIRV-Tools-xrOS */, A972A81021CECBE90013AB25 /* SPIRV-Tools-macOS */, A972ABC921CED7BC0013AB25 /* glslang-iOS */, 2FEA0AE82490321700EEF3AD /* glslang-tvOS */, + DCFD7CA42A45BA92007BBBF7 /* glslang-xrOS */, A972ABDD21CED7CB0013AB25 /* glslang-macOS */, ); }; @@ -4505,6 +5441,86 @@ shellPath = /bin/sh; shellScript = ". \"${SRCROOT}/Scripts/create_ext_lib_xcframeworks.sh\"\n. \"${SRCROOT}/Scripts/package_ext_libs_finish.sh\"\n"; }; + DCFD7C9F2A45BA7D007BBBF7 /* Copy to Staging */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${BUILT_PRODUCTS_DIR}/lib${PRODUCT_NAME}.a", + ); + name = "Copy to Staging"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/$(TARGET_NAME)/CopyPhaseDummyOutputFile", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = ". \"${SRCROOT}/Scripts/copy_ext_lib_to_staging.sh\"\n"; + }; + DCFD7D072A45BA92007BBBF7 /* Copy to Staging */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${BUILT_PRODUCTS_DIR}/lib${PRODUCT_NAME}.a", + ); + name = "Copy to Staging"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/$(TARGET_NAME)/CopyPhaseDummyOutputFile", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = ". \"${SRCROOT}/Scripts/copy_ext_lib_to_staging.sh\"\n"; + }; + DCFD7EBC2A45BA9C007BBBF7 /* Copy to Staging */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${BUILT_PRODUCTS_DIR}/lib${PRODUCT_NAME}.a", + ); + name = "Copy to Staging"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/$(TARGET_NAME)/CopyPhaseDummyOutputFile", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = ". \"${SRCROOT}/Scripts/copy_ext_lib_to_staging.sh\"\n"; + }; + DCFD7EC82A45BAAA007BBBF7 /* Package Libraries */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PROJECT_DIR}/External/build/Intermediates/XCFrameworkStaging", + ); + name = "Package Libraries"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/$(TARGET_NAME)/PackagePhaseDummyOutputFile", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = ". \"${SRCROOT}/Scripts/create_ext_lib_xcframeworks.sh\"\n. \"${SRCROOT}/Scripts/package_ext_libs_finish.sh\"\n"; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -5387,6 +6403,299 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + DCFD7C972A45BA7D007BBBF7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DCFD7C982A45BA7D007BBBF7 /* spirv_msl.cpp in Sources */, + DCFD7C992A45BA7D007BBBF7 /* spirv_parser.cpp in Sources */, + DCFD7C9A2A45BA7D007BBBF7 /* spirv_cfg.cpp in Sources */, + DCFD7C9B2A45BA7D007BBBF7 /* spirv_cross.cpp in Sources */, + DCFD7C9C2A45BA7D007BBBF7 /* spirv_reflect.cpp in Sources */, + DCFD7C9D2A45BA7D007BBBF7 /* spirv_glsl.cpp in Sources */, + DCFD7C9E2A45BA7D007BBBF7 /* spirv_cross_parsed_ir.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCFD7CDB2A45BA92007BBBF7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DCFD7CDC2A45BA92007BBBF7 /* ParseHelper.cpp in Sources */, + DCFD7CDD2A45BA92007BBBF7 /* doc.cpp in Sources */, + DCFD7CDE2A45BA92007BBBF7 /* attribute.cpp in Sources */, + DCFD7CDF2A45BA92007BBBF7 /* IntermTraverse.cpp in Sources */, + DCFD7CE02A45BA92007BBBF7 /* Versions.cpp in Sources */, + DCFD7CE12A45BA92007BBBF7 /* reflection.cpp in Sources */, + DCFD7CE22A45BA92007BBBF7 /* spirv_c_interface.cpp in Sources */, + DCFD7CE32A45BA92007BBBF7 /* propagateNoContraction.cpp in Sources */, + DCFD7CE42A45BA92007BBBF7 /* glslang_c_interface.cpp in Sources */, + DCFD7CE52A45BA92007BBBF7 /* SPVRemapper.cpp in Sources */, + DCFD7CE62A45BA92007BBBF7 /* SpvTools.cpp in Sources */, + DCFD7CE72A45BA92007BBBF7 /* Logger.cpp in Sources */, + DCFD7CE82A45BA92007BBBF7 /* ossource.cpp in Sources */, + DCFD7CE92A45BA92007BBBF7 /* SpvPostProcess.cpp in Sources */, + DCFD7CEA2A45BA92007BBBF7 /* Scan.cpp in Sources */, + DCFD7CEB2A45BA92007BBBF7 /* PpScanner.cpp in Sources */, + DCFD7CEC2A45BA92007BBBF7 /* PpContext.cpp in Sources */, + DCFD7CED2A45BA92007BBBF7 /* disassemble.cpp in Sources */, + DCFD7CEE2A45BA92007BBBF7 /* SpirvIntrinsics.cpp in Sources */, + DCFD7CEF2A45BA92007BBBF7 /* linkValidate.cpp in Sources */, + DCFD7CF02A45BA92007BBBF7 /* parseConst.cpp in Sources */, + DCFD7CF12A45BA92007BBBF7 /* InitializeDll.cpp in Sources */, + DCFD7CF22A45BA92007BBBF7 /* Link.cpp in Sources */, + DCFD7CF32A45BA92007BBBF7 /* iomapper.cpp in Sources */, + DCFD7CF42A45BA92007BBBF7 /* ParseContextBase.cpp in Sources */, + DCFD7CF52A45BA92007BBBF7 /* PpTokens.cpp in Sources */, + DCFD7CF62A45BA92007BBBF7 /* GlslangToSpv.cpp in Sources */, + DCFD7CF72A45BA92007BBBF7 /* limits.cpp in Sources */, + DCFD7CF82A45BA92007BBBF7 /* glslang_tab.cpp in Sources */, + DCFD7CF92A45BA92007BBBF7 /* Constant.cpp in Sources */, + DCFD7CFA2A45BA92007BBBF7 /* InfoSink.cpp in Sources */, + DCFD7CFB2A45BA92007BBBF7 /* RemoveTree.cpp in Sources */, + DCFD7CFC2A45BA92007BBBF7 /* intermOut.cpp in Sources */, + DCFD7CFD2A45BA92007BBBF7 /* PoolAlloc.cpp in Sources */, + DCFD7CFE2A45BA92007BBBF7 /* Initialize.cpp in Sources */, + DCFD7CFF2A45BA92007BBBF7 /* ShaderLang.cpp in Sources */, + DCFD7D002A45BA92007BBBF7 /* Intermediate.cpp in Sources */, + DCFD7D012A45BA92007BBBF7 /* InReadableOrder.cpp in Sources */, + DCFD7D022A45BA92007BBBF7 /* PpAtom.cpp in Sources */, + DCFD7D032A45BA92007BBBF7 /* SpvBuilder.cpp in Sources */, + DCFD7D042A45BA92007BBBF7 /* CodeGen.cpp in Sources */, + DCFD7D052A45BA92007BBBF7 /* SymbolTable.cpp in Sources */, + DCFD7D062A45BA92007BBBF7 /* Pp.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCFD7DDD2A45BA9C007BBBF7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DCFD7DDE2A45BA9C007BBBF7 /* spirv_reducer_options.cpp in Sources */, + DCFD7DDF2A45BA9C007BBBF7 /* register_pressure.cpp in Sources */, + DCFD7DE02A45BA9C007BBBF7 /* loop_peeling.cpp in Sources */, + DCFD7DE12A45BA9C007BBBF7 /* block_merge_pass.cpp in Sources */, + DCFD7DE22A45BA9C007BBBF7 /* opcode.cpp in Sources */, + DCFD7DE32A45BA9C007BBBF7 /* validate_builtins.cpp in Sources */, + DCFD7DE42A45BA9C007BBBF7 /* validate_non_uniform.cpp in Sources */, + DCFD7DE52A45BA9C007BBBF7 /* table.cpp in Sources */, + DCFD7DE62A45BA9C007BBBF7 /* validate_logicals.cpp in Sources */, + DCFD7DE72A45BA9C007BBBF7 /* change_operand_to_undef_reduction_opportunity.cpp in Sources */, + DCFD7DE82A45BA9C007BBBF7 /* bit_vector.cpp in Sources */, + DCFD7DE92A45BA9C007BBBF7 /* ir_context.cpp in Sources */, + DCFD7DEA2A45BA9C007BBBF7 /* structured_loop_to_selection_reduction_opportunity_finder.cpp in Sources */, + DCFD7DEB2A45BA9C007BBBF7 /* if_conversion.cpp in Sources */, + DCFD7DEC2A45BA9C007BBBF7 /* remove_dontinline_pass.cpp in Sources */, + DCFD7DED2A45BA9C007BBBF7 /* convert_to_sampled_image_pass.cpp in Sources */, + DCFD7DEE2A45BA9C007BBBF7 /* merge_return_pass.cpp in Sources */, + DCFD7DEF2A45BA9C007BBBF7 /* reducer.cpp in Sources */, + DCFD7DF02A45BA9C007BBBF7 /* remove_function_reduction_opportunity.cpp in Sources */, + DCFD7DF12A45BA9C007BBBF7 /* disassemble.cpp in Sources */, + DCFD7DF22A45BA9C007BBBF7 /* composite.cpp in Sources */, + DCFD7DF32A45BA9C007BBBF7 /* validate_conversion.cpp in Sources */, + DCFD7DF42A45BA9C007BBBF7 /* instruction.cpp in Sources */, + DCFD7DF52A45BA9C007BBBF7 /* validate_ray_query.cpp in Sources */, + DCFD7DF62A45BA9C007BBBF7 /* operand.cpp in Sources */, + DCFD7DF72A45BA9C007BBBF7 /* unify_const_pass.cpp in Sources */, + DCFD7DF82A45BA9C007BBBF7 /* operand_to_const_reduction_opportunity_finder.cpp in Sources */, + DCFD7DF92A45BA9C007BBBF7 /* enum_string_mapping.cpp in Sources */, + DCFD7DFA2A45BA9C007BBBF7 /* validate_mode_setting.cpp in Sources */, + DCFD7DFB2A45BA9C007BBBF7 /* binary.cpp in Sources */, + DCFD7DFC2A45BA9C007BBBF7 /* struct_cfg_analysis.cpp in Sources */, + DCFD7DFD2A45BA9C007BBBF7 /* validate_capability.cpp in Sources */, + DCFD7DFE2A45BA9C007BBBF7 /* diagnostic.cpp in Sources */, + DCFD7DFF2A45BA9C007BBBF7 /* libspirv.cpp in Sources */, + DCFD7E002A45BA9C007BBBF7 /* validate_mesh_shading.cpp in Sources */, + DCFD7E012A45BA9C007BBBF7 /* build_module.cpp in Sources */, + DCFD7E022A45BA9C007BBBF7 /* cfg_cleanup_pass.cpp in Sources */, + DCFD7E032A45BA9C007BBBF7 /* spirv_fuzzer_options.cpp in Sources */, + DCFD7E042A45BA9C007BBBF7 /* validate_adjacency.cpp in Sources */, + DCFD7E052A45BA9C007BBBF7 /* validate_id.cpp in Sources */, + DCFD7E062A45BA9C007BBBF7 /* parse_number.cpp in Sources */, + DCFD7E072A45BA9C007BBBF7 /* scalar_analysis.cpp in Sources */, + DCFD7E082A45BA9C007BBBF7 /* lint_divergent_derivatives.cpp in Sources */, + DCFD7E092A45BA9C007BBBF7 /* remove_struct_member_reduction_opportunity.cpp in Sources */, + DCFD7E0A2A45BA9C007BBBF7 /* validate_scopes.cpp in Sources */, + DCFD7E0B2A45BA9C007BBBF7 /* strip_debug_info_pass.cpp in Sources */, + DCFD7E0C2A45BA9C007BBBF7 /* eliminate_dead_functions_util.cpp in Sources */, + DCFD7E0D2A45BA9C007BBBF7 /* remove_function_reduction_opportunity_finder.cpp in Sources */, + DCFD7E0E2A45BA9C007BBBF7 /* ssa_rewrite_pass.cpp in Sources */, + DCFD7E0F2A45BA9C007BBBF7 /* validate_image.cpp in Sources */, + DCFD7E102A45BA9C007BBBF7 /* module.cpp in Sources */, + DCFD7E112A45BA9C007BBBF7 /* merge_blocks_reduction_opportunity.cpp in Sources */, + DCFD7E122A45BA9C007BBBF7 /* constants.cpp in Sources */, + DCFD7E132A45BA9C007BBBF7 /* remove_block_reduction_opportunity.cpp in Sources */, + DCFD7E142A45BA9C007BBBF7 /* spirv_target_env.cpp in Sources */, + DCFD7E152A45BA9C007BBBF7 /* loop_fission.cpp in Sources */, + DCFD7E162A45BA9C007BBBF7 /* remove_block_reduction_opportunity_finder.cpp in Sources */, + DCFD7E172A45BA9C007BBBF7 /* remove_selection_reduction_opportunity_finder.cpp in Sources */, + DCFD7E182A45BA9C007BBBF7 /* fold.cpp in Sources */, + DCFD7E192A45BA9C007BBBF7 /* def_use_manager.cpp in Sources */, + DCFD7E1A2A45BA9C007BBBF7 /* parsed_operand.cpp in Sources */, + DCFD7E1B2A45BA9C007BBBF7 /* eliminate_dead_members_pass.cpp in Sources */, + DCFD7E1C2A45BA9C007BBBF7 /* instruction.cpp in Sources */, + DCFD7E1D2A45BA9C007BBBF7 /* name_mapper.cpp in Sources */, + DCFD7E1E2A45BA9C007BBBF7 /* analyze_live_input_pass.cpp in Sources */, + DCFD7E1F2A45BA9C007BBBF7 /* validate_cfg.cpp in Sources */, + DCFD7E202A45BA9C007BBBF7 /* change_operand_reduction_opportunity.cpp in Sources */, + DCFD7E212A45BA9C007BBBF7 /* validate_instruction.cpp in Sources */, + DCFD7E222A45BA9C007BBBF7 /* instrument_pass.cpp in Sources */, + DCFD7E232A45BA9C007BBBF7 /* validate_ray_tracing.cpp in Sources */, + DCFD7E242A45BA9C007BBBF7 /* pass.cpp in Sources */, + DCFD7E252A45BA9C007BBBF7 /* ccp_pass.cpp in Sources */, + DCFD7E262A45BA9C007BBBF7 /* desc_sroa_util.cpp in Sources */, + DCFD7E272A45BA9C007BBBF7 /* validate_bitwise.cpp in Sources */, + DCFD7E282A45BA9C007BBBF7 /* block_merge_util.cpp in Sources */, + DCFD7E292A45BA9C007BBBF7 /* validate_debug.cpp in Sources */, + DCFD7E2A2A45BA9C007BBBF7 /* loop_descriptor.cpp in Sources */, + DCFD7E2B2A45BA9C007BBBF7 /* linker.cpp in Sources */, + DCFD7E2C2A45BA9C007BBBF7 /* freeze_spec_constant_value_pass.cpp in Sources */, + DCFD7E2D2A45BA9C007BBBF7 /* string_utils.cpp in Sources */, + DCFD7E2E2A45BA9C007BBBF7 /* validate_memory_semantics.cpp in Sources */, + DCFD7E2F2A45BA9C007BBBF7 /* types.cpp in Sources */, + DCFD7E302A45BA9C007BBBF7 /* pch_source.cpp in Sources */, + DCFD7E312A45BA9C007BBBF7 /* print.cpp in Sources */, + DCFD7E322A45BA9C007BBBF7 /* function.cpp in Sources */, + DCFD7E332A45BA9C007BBBF7 /* inline_exhaustive_pass.cpp in Sources */, + DCFD7E342A45BA9C007BBBF7 /* eliminate_dead_constant_pass.cpp in Sources */, + DCFD7E352A45BA9C007BBBF7 /* inline_opaque_pass.cpp in Sources */, + DCFD7E362A45BA9C007BBBF7 /* conditional_branch_to_simple_conditional_branch_opportunity_finder.cpp in Sources */, + DCFD7E372A45BA9C007BBBF7 /* linter.cpp in Sources */, + DCFD7E382A45BA9C007BBBF7 /* eliminate_dead_output_stores_pass.cpp in Sources */, + DCFD7E392A45BA9C007BBBF7 /* compact_ids_pass.cpp in Sources */, + DCFD7E3A2A45BA9C007BBBF7 /* folding_rules.cpp in Sources */, + DCFD7E3B2A45BA9C007BBBF7 /* strip_nonsemantic_info_pass.cpp in Sources */, + DCFD7E3C2A45BA9C007BBBF7 /* private_to_local_pass.cpp in Sources */, + DCFD7E3D2A45BA9C007BBBF7 /* fold_spec_constant_op_and_composite_pass.cpp in Sources */, + DCFD7E3E2A45BA9C007BBBF7 /* validate_ray_tracing_reorder.cpp in Sources */, + DCFD7E3F2A45BA9C007BBBF7 /* validate_derivatives.cpp in Sources */, + DCFD7E402A45BA9C007BBBF7 /* simple_conditional_branch_to_branch_reduction_opportunity.cpp in Sources */, + DCFD7E412A45BA9C007BBBF7 /* control_dependence.cpp in Sources */, + DCFD7E422A45BA9C007BBBF7 /* spirv_optimizer_options.cpp in Sources */, + DCFD7E432A45BA9C007BBBF7 /* pch_source_reduce.cpp in Sources */, + DCFD7E442A45BA9C007BBBF7 /* dead_variable_elimination.cpp in Sources */, + DCFD7E452A45BA9C007BBBF7 /* conditional_branch_to_simple_conditional_branch_reduction_opportunity.cpp in Sources */, + DCFD7E462A45BA9C007BBBF7 /* strength_reduction_pass.cpp in Sources */, + DCFD7E472A45BA9C007BBBF7 /* scalar_analysis_simplification.cpp in Sources */, + DCFD7E482A45BA9C007BBBF7 /* validate_interfaces.cpp in Sources */, + DCFD7E492A45BA9C007BBBF7 /* validate_atomics.cpp in Sources */, + DCFD7E4A2A45BA9C007BBBF7 /* ext_inst.cpp in Sources */, + DCFD7E4B2A45BA9C007BBBF7 /* operand_to_dominating_id_reduction_opportunity_finder.cpp in Sources */, + DCFD7E4C2A45BA9C007BBBF7 /* decoration_manager.cpp in Sources */, + DCFD7E4D2A45BA9C007BBBF7 /* workaround1209.cpp in Sources */, + DCFD7E4E2A45BA9C007BBBF7 /* interp_fixup_pass.cpp in Sources */, + DCFD7E4F2A45BA9C007BBBF7 /* validate_literals.cpp in Sources */, + DCFD7E502A45BA9C007BBBF7 /* diff.cpp in Sources */, + DCFD7E512A45BA9C007BBBF7 /* dominator_tree.cpp in Sources */, + DCFD7E522A45BA9C007BBBF7 /* interface_var_sroa.cpp in Sources */, + DCFD7E532A45BA9C007BBBF7 /* upgrade_memory_model.cpp in Sources */, + DCFD7E542A45BA9C007BBBF7 /* combine_access_chains.cpp in Sources */, + DCFD7E552A45BA9C007BBBF7 /* instruction_list.cpp in Sources */, + DCFD7E562A45BA9C007BBBF7 /* aggressive_dead_code_elim_pass.cpp in Sources */, + DCFD7E572A45BA9C007BBBF7 /* reduction_util.cpp in Sources */, + DCFD7E582A45BA9C007BBBF7 /* eliminate_dead_functions_pass.cpp in Sources */, + DCFD7E592A45BA9C007BBBF7 /* validate_small_type_uses.cpp in Sources */, + DCFD7E5A2A45BA9C007BBBF7 /* validate_misc.cpp in Sources */, + DCFD7E5B2A45BA9C007BBBF7 /* code_sink.cpp in Sources */, + DCFD7E5C2A45BA9C007BBBF7 /* pass_manager.cpp in Sources */, + DCFD7E5D2A45BA9C007BBBF7 /* feature_manager.cpp in Sources */, + DCFD7E5E2A45BA9C007BBBF7 /* wrap_opkill.cpp in Sources */, + DCFD7E5F2A45BA9C007BBBF7 /* dataflow.cpp in Sources */, + DCFD7E602A45BA9C007BBBF7 /* validate_type.cpp in Sources */, + DCFD7E612A45BA9C007BBBF7 /* set_spec_constant_default_value_pass.cpp in Sources */, + DCFD7E622A45BA9C007BBBF7 /* remove_selection_reduction_opportunity.cpp in Sources */, + DCFD7E632A45BA9C007BBBF7 /* validate_constants.cpp in Sources */, + DCFD7E642A45BA9C007BBBF7 /* validate_layout.cpp in Sources */, + DCFD7E652A45BA9C007BBBF7 /* const_folding_rules.cpp in Sources */, + DCFD7E662A45BA9C007BBBF7 /* replace_invalid_opc.cpp in Sources */, + DCFD7E672A45BA9C007BBBF7 /* eliminate_dead_io_components_pass.cpp in Sources */, + DCFD7E682A45BA9C007BBBF7 /* structured_construct_to_block_reduction_opportunity_finder.cpp in Sources */, + DCFD7E692A45BA9C007BBBF7 /* reduction_opportunity_finder.cpp in Sources */, + DCFD7E6A2A45BA9C007BBBF7 /* liveness.cpp in Sources */, + DCFD7E6B2A45BA9C007BBBF7 /* debug_info_manager.cpp in Sources */, + DCFD7E6C2A45BA9C007BBBF7 /* relax_float_ops_pass.cpp in Sources */, + DCFD7E6D2A45BA9C007BBBF7 /* value_number_table.cpp in Sources */, + DCFD7E6E2A45BA9C007BBBF7 /* text.cpp in Sources */, + DCFD7E6F2A45BA9C007BBBF7 /* local_single_store_elim_pass.cpp in Sources */, + DCFD7E702A45BA9C007BBBF7 /* remove_unused_instruction_reduction_opportunity_finder.cpp in Sources */, + DCFD7E712A45BA9C007BBBF7 /* reduction_pass.cpp in Sources */, + DCFD7E722A45BA9C007BBBF7 /* convert_to_half_pass.cpp in Sources */, + DCFD7E732A45BA9C007BBBF7 /* reduce_load_size.cpp in Sources */, + DCFD7E742A45BA9C007BBBF7 /* local_access_chain_convert_pass.cpp in Sources */, + DCFD7E752A45BA9C007BBBF7 /* inst_bindless_check_pass.cpp in Sources */, + DCFD7E762A45BA9C007BBBF7 /* local_single_block_elim_pass.cpp in Sources */, + DCFD7E772A45BA9C007BBBF7 /* validate_execution_limitations.cpp in Sources */, + DCFD7E782A45BA9C007BBBF7 /* function.cpp in Sources */, + DCFD7E792A45BA9C007BBBF7 /* fix_func_call_arguments.cpp in Sources */, + DCFD7E7A2A45BA9C007BBBF7 /* structured_loop_to_selection_reduction_opportunity.cpp in Sources */, + DCFD7E7B2A45BA9C007BBBF7 /* graphics_robust_access_pass.cpp in Sources */, + DCFD7E7C2A45BA9C007BBBF7 /* construct.cpp in Sources */, + DCFD7E7D2A45BA9C007BBBF7 /* loop_unroller.cpp in Sources */, + DCFD7E7E2A45BA9C007BBBF7 /* spirv_validator_options.cpp in Sources */, + DCFD7E7F2A45BA9C007BBBF7 /* divergence_analysis.cpp in Sources */, + DCFD7E802A45BA9C007BBBF7 /* loop_utils.cpp in Sources */, + DCFD7E812A45BA9C007BBBF7 /* spread_volatile_semantics.cpp in Sources */, + DCFD7E822A45BA9C007BBBF7 /* desc_sroa.cpp in Sources */, + DCFD7E832A45BA9C007BBBF7 /* dead_insert_elim_pass.cpp in Sources */, + DCFD7E842A45BA9C007BBBF7 /* validate_decorations.cpp in Sources */, + DCFD7E852A45BA9C007BBBF7 /* loop_fusion_pass.cpp in Sources */, + DCFD7E862A45BA9C007BBBF7 /* merge_blocks_reduction_opportunity_finder.cpp in Sources */, + DCFD7E872A45BA9C007BBBF7 /* flatten_decoration_pass.cpp in Sources */, + DCFD7E882A45BA9C007BBBF7 /* fix_storage_class.cpp in Sources */, + DCFD7E892A45BA9C007BBBF7 /* software_version.cpp in Sources */, + DCFD7E8A2A45BA9C007BBBF7 /* assembly_grammar.cpp in Sources */, + DCFD7E8B2A45BA9C007BBBF7 /* amd_ext_to_khr.cpp in Sources */, + DCFD7E8C2A45BA9C007BBBF7 /* text_handler.cpp in Sources */, + DCFD7E8D2A45BA9C007BBBF7 /* optimizer.cpp in Sources */, + DCFD7E8E2A45BA9C007BBBF7 /* validation_state.cpp in Sources */, + DCFD7E8F2A45BA9C007BBBF7 /* mem_pass.cpp in Sources */, + DCFD7E902A45BA9C007BBBF7 /* replace_desc_array_access_using_var_index.cpp in Sources */, + DCFD7E912A45BA9C007BBBF7 /* ir_loader.cpp in Sources */, + DCFD7E922A45BA9C007BBBF7 /* extensions.cpp in Sources */, + DCFD7E932A45BA9C007BBBF7 /* type_manager.cpp in Sources */, + DCFD7E942A45BA9C007BBBF7 /* scalar_replacement_pass.cpp in Sources */, + DCFD7E952A45BA9C007BBBF7 /* loop_unswitch_pass.cpp in Sources */, + DCFD7E962A45BA9C007BBBF7 /* reduction_opportunity.cpp in Sources */, + DCFD7E972A45BA9C007BBBF7 /* validate_extensions.cpp in Sources */, + DCFD7E982A45BA9C007BBBF7 /* remove_unused_struct_member_reduction_opportunity_finder.cpp in Sources */, + DCFD7E992A45BA9C007BBBF7 /* timer.cpp in Sources */, + DCFD7E9A2A45BA9C007BBBF7 /* pch_source_opt.cpp in Sources */, + DCFD7E9B2A45BA9C007BBBF7 /* inline_pass.cpp in Sources */, + DCFD7E9C2A45BA9C007BBBF7 /* inst_buff_addr_check_pass.cpp in Sources */, + DCFD7E9D2A45BA9C007BBBF7 /* validate_barriers.cpp in Sources */, + DCFD7E9E2A45BA9C007BBBF7 /* redundancy_elimination.cpp in Sources */, + DCFD7E9F2A45BA9C007BBBF7 /* spirv_endian.cpp in Sources */, + DCFD7EA02A45BA9C007BBBF7 /* cfg.cpp in Sources */, + DCFD7EA12A45BA9C007BBBF7 /* remove_duplicates_pass.cpp in Sources */, + DCFD7EA22A45BA9C007BBBF7 /* validate_annotation.cpp in Sources */, + DCFD7EA32A45BA9C007BBBF7 /* loop_dependence_helpers.cpp in Sources */, + DCFD7EA42A45BA9C007BBBF7 /* basic_block.cpp in Sources */, + DCFD7EA52A45BA9C007BBBF7 /* loop_dependence.cpp in Sources */, + DCFD7EA62A45BA9C007BBBF7 /* licm_pass.cpp in Sources */, + DCFD7EA72A45BA9C007BBBF7 /* operand_to_undef_reduction_opportunity_finder.cpp in Sources */, + DCFD7EA82A45BA9C007BBBF7 /* dead_branch_elim_pass.cpp in Sources */, + DCFD7EA92A45BA9C007BBBF7 /* inst_debug_printf_pass.cpp in Sources */, + DCFD7EAA2A45BA9C007BBBF7 /* local_redundancy_elimination.cpp in Sources */, + DCFD7EAB2A45BA9C007BBBF7 /* validate_memory.cpp in Sources */, + DCFD7EAC2A45BA9C007BBBF7 /* dominator_analysis.cpp in Sources */, + DCFD7EAD2A45BA9C007BBBF7 /* validate.cpp in Sources */, + DCFD7EAE2A45BA9C007BBBF7 /* copy_prop_arrays.cpp in Sources */, + DCFD7EAF2A45BA9C007BBBF7 /* structured_construct_to_block_reduction_opportunity.cpp in Sources */, + DCFD7EB02A45BA9C007BBBF7 /* validate_composites.cpp in Sources */, + DCFD7EB12A45BA9C007BBBF7 /* loop_fusion.cpp in Sources */, + DCFD7EB22A45BA9C007BBBF7 /* basic_block.cpp in Sources */, + DCFD7EB32A45BA9C007BBBF7 /* remove_unused_interface_variables_pass.cpp in Sources */, + DCFD7EB42A45BA9C007BBBF7 /* validate_function.cpp in Sources */, + DCFD7EB52A45BA9C007BBBF7 /* vector_dce.cpp in Sources */, + DCFD7EB62A45BA9C007BBBF7 /* validate_primitives.cpp in Sources */, + DCFD7EB72A45BA9C007BBBF7 /* simplification_pass.cpp in Sources */, + DCFD7EB82A45BA9C007BBBF7 /* propagator.cpp in Sources */, + DCFD7EB92A45BA9C007BBBF7 /* simple_conditional_branch_to_branch_opportunity_finder.cpp in Sources */, + DCFD7EBA2A45BA9C007BBBF7 /* remove_instruction_reduction_opportunity.cpp in Sources */, + DCFD7EBB2A45BA9C007BBBF7 /* validate_arithmetics.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -5450,6 +6759,21 @@ target = A972ABDD21CED7CB0013AB25 /* glslang-macOS */; targetProxy = A972ABF321CED8C20013AB25 /* PBXContainerItemProxy */; }; + DCFD7ECD2A45BC08007BBBF7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCFD7C892A45BA7D007BBBF7 /* SPIRV-Cross-xrOS */; + targetProxy = DCFD7ECC2A45BC08007BBBF7 /* PBXContainerItemProxy */; + }; + DCFD7ECF2A45BC0C007BBBF7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCFD7D0C2A45BA9C007BBBF7 /* SPIRV-Tools-xrOS */; + targetProxy = DCFD7ECE2A45BC0C007BBBF7 /* PBXContainerItemProxy */; + }; + DCFD7ED12A45BC10007BBBF7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCFD7CA42A45BA92007BBBF7 /* glslang-xrOS */; + targetProxy = DCFD7ED02A45BC10007BBBF7 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -5880,11 +7204,11 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = NO; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACH_O_TYPE = staticlib; MACOSX_DEPLOYMENT_TARGET = 10.13; SKIP_INSTALL = YES; - TVOS_DEPLOYMENT_TARGET = 11.0; + TVOS_DEPLOYMENT_TARGET = 12.0; }; name = Debug; }; @@ -5930,15 +7254,137 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = NO; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACH_O_TYPE = staticlib; MACOSX_DEPLOYMENT_TARGET = 10.13; SKIP_INSTALL = YES; - TVOS_DEPLOYMENT_TARGET = 11.0; + TVOS_DEPLOYMENT_TARGET = 12.0; VALIDATE_PRODUCT = YES; }; name = Release; }; + DCFD7CA12A45BA7D007BBBF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SPIRV_CROSS_NAMESPACE_OVERRIDE=MVK_spirv_cross", + ); + PRODUCT_NAME = SPIRVCross; + SDKROOT = xros; + }; + name = Debug; + }; + DCFD7CA22A45BA7D007BBBF7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SPIRV_CROSS_NAMESPACE_OVERRIDE=MVK_spirv_cross", + ); + PRODUCT_NAME = SPIRVCross; + SDKROOT = xros; + }; + name = Release; + }; + DCFD7D092A45BA92007BBBF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = NO; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "AMD_EXTENSIONS=1", + "NV_EXTENSIONS=1", + ); + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = NO; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO; + GCC_WARN_CHECK_SWITCH_STATEMENTS = NO; + GCC_WARN_UNUSED_PARAMETER = NO; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/External/glslang\"", + "\"$(SRCROOT)/External/glslang/build/include\"", + ); + PRODUCT_NAME = glslang; + SDKROOT = xros; + }; + name = Debug; + }; + DCFD7D0A2A45BA92007BBBF7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = NO; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "AMD_EXTENSIONS=1", + "NV_EXTENSIONS=1", + ); + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = NO; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO; + GCC_WARN_CHECK_SWITCH_STATEMENTS = NO; + GCC_WARN_UNUSED_PARAMETER = NO; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/External/glslang\"", + "\"$(SRCROOT)/External/glslang/build/include\"", + ); + PRODUCT_NAME = glslang; + SDKROOT = xros; + }; + name = Release; + }; + DCFD7EBE2A45BA9C007BBBF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = NO; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO; + GCC_WARN_CHECK_SWITCH_STATEMENTS = NO; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/External/glslang/External/spirv-tools/\"", + "\"$(SRCROOT)/External/glslang/External/spirv-tools/include\"", + "\"$(SRCROOT)/External/glslang/External/spirv-tools/external/spirv-headers/include\"", + "\"$(SRCROOT)/External/glslang/External/spirv-tools/build\"", + ); + PRODUCT_NAME = SPIRVTools; + SDKROOT = xros; + }; + name = Debug; + }; + DCFD7EBF2A45BA9C007BBBF7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = NO; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO; + GCC_WARN_CHECK_SWITCH_STATEMENTS = NO; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/External/glslang/External/spirv-tools/\"", + "\"$(SRCROOT)/External/glslang/External/spirv-tools/include\"", + "\"$(SRCROOT)/External/glslang/External/spirv-tools/external/spirv-headers/include\"", + "\"$(SRCROOT)/External/glslang/External/spirv-tools/build\"", + ); + PRODUCT_NAME = SPIRVTools; + SDKROOT = xros; + }; + name = Release; + }; + DCFD7ECA2A45BAAA007BBBF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + DCFD7ECB2A45BAAA007BBBF7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -6068,6 +7514,42 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + DCFD7CA02A45BA7D007BBBF7 /* Build configuration list for PBXNativeTarget "SPIRV-Cross-xrOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DCFD7CA12A45BA7D007BBBF7 /* Debug */, + DCFD7CA22A45BA7D007BBBF7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DCFD7D082A45BA92007BBBF7 /* Build configuration list for PBXNativeTarget "glslang-xrOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DCFD7D092A45BA92007BBBF7 /* Debug */, + DCFD7D0A2A45BA92007BBBF7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DCFD7EBD2A45BA9C007BBBF7 /* Build configuration list for PBXNativeTarget "SPIRV-Tools-xrOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DCFD7EBE2A45BA9C007BBBF7 /* Debug */, + DCFD7EBF2A45BA9C007BBBF7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DCFD7EC92A45BAAA007BBBF7 /* Build configuration list for PBXAggregateTarget "ExternalDependencies-xrOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DCFD7ECA2A45BAAA007BBBF7 /* Debug */, + DCFD7ECB2A45BAAA007BBBF7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = A9F55D25198BE6A7004EC31B /* Project object */; diff --git a/ExternalDependencies.xcodeproj/xcshareddata/xcschemes/ExternalDependencies-xrOS.xcscheme b/ExternalDependencies.xcodeproj/xcshareddata/xcschemes/ExternalDependencies-xrOS.xcscheme new file mode 100644 index 000000000..27214297a --- /dev/null +++ b/ExternalDependencies.xcodeproj/xcshareddata/xcschemes/ExternalDependencies-xrOS.xcscheme @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ExternalDependencies.xcodeproj/xcshareddata/xcschemes/SPIRV-Cross-xrOS.xcscheme b/ExternalDependencies.xcodeproj/xcshareddata/xcschemes/SPIRV-Cross-xrOS.xcscheme new file mode 100644 index 000000000..e94a658a6 --- /dev/null +++ b/ExternalDependencies.xcodeproj/xcshareddata/xcschemes/SPIRV-Cross-xrOS.xcscheme @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ExternalDependencies.xcodeproj/xcshareddata/xcschemes/SPIRV-Tools-xrOS.xcscheme b/ExternalDependencies.xcodeproj/xcshareddata/xcschemes/SPIRV-Tools-xrOS.xcscheme new file mode 100644 index 000000000..18e609a79 --- /dev/null +++ b/ExternalDependencies.xcodeproj/xcshareddata/xcschemes/SPIRV-Tools-xrOS.xcscheme @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ExternalDependencies.xcodeproj/xcshareddata/xcschemes/glslang-xrOS.xcscheme b/ExternalDependencies.xcodeproj/xcshareddata/xcschemes/glslang-xrOS.xcscheme new file mode 100644 index 000000000..9feb36b2c --- /dev/null +++ b/ExternalDependencies.xcodeproj/xcshareddata/xcschemes/glslang-xrOS.xcscheme @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ExternalRevisions/SPIRV-Cross_repo_revision b/ExternalRevisions/SPIRV-Cross_repo_revision index 623b20930..05bf0fae3 100644 --- a/ExternalRevisions/SPIRV-Cross_repo_revision +++ b/ExternalRevisions/SPIRV-Cross_repo_revision @@ -1 +1 @@ -3550a54ae01b295c40ce972d951b420b388b9401 +7a1e3e7586b9b10a6286cad912940b7a501e93ea diff --git a/ExternalRevisions/Vulkan-Headers_repo_revision b/ExternalRevisions/Vulkan-Headers_repo_revision index c0981ee2e..a8ebecec5 100644 --- a/ExternalRevisions/Vulkan-Headers_repo_revision +++ b/ExternalRevisions/Vulkan-Headers_repo_revision @@ -1 +1 @@ -fa204df59c6caea6b9be3cf0754a88cd89056a87 +85c2334e92e215cce34e8e0ed8b2dce4700f4a50 diff --git a/ExternalRevisions/Vulkan-Tools_repo_revision b/ExternalRevisions/Vulkan-Tools_repo_revision index a36355f59..bf77fda05 100644 --- a/ExternalRevisions/Vulkan-Tools_repo_revision +++ b/ExternalRevisions/Vulkan-Tools_repo_revision @@ -1 +1 @@ -f196c8d3cafcaf7e628b7b76a799c940999ee984 +300d9bf6b3cf7b237ee5e2c1d0ae10b9236f82d3 diff --git a/ExternalRevisions/glslang_repo_revision b/ExternalRevisions/glslang_repo_revision index 4ec3c5381..aba7fbb10 100644 --- a/ExternalRevisions/glslang_repo_revision +++ b/ExternalRevisions/glslang_repo_revision @@ -1 +1 @@ -14e5a04e70057972eef8a40df422e30a3b70e4b5 +76b52ebf77833908dc4c0dd6c70a9c357ac720bd diff --git a/Makefile b/Makefile index 62e1ab5f8..89523db11 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,8 @@ MAKEARGS := $(strip \ $(v)=$(value $(v)) ,))) # Specify individually (not as dependencies) so the sub-targets don't run in parallel +# visionos and visionossim are currently excluded from `all` because they require +# Xcode 15+ and will abort a multi-platform build on earlier Xcode versions. .PHONY: all all: @$(MAKE) macos @@ -29,6 +31,8 @@ all: @$(MAKE) maccat @$(MAKE) tvos @$(MAKE) tvossim +# @$(MAKE) visionos # Requires Xcode 15+ +# @$(MAKE) visionossim # Requires Xcode 15+ .PHONY: all-debug all-debug: @@ -38,6 +42,8 @@ all-debug: @$(MAKE) maccat-debug @$(MAKE) tvos-debug @$(MAKE) tvossim-debug +# @$(MAKE) visionos-debug # Requires Xcode 15+ +# @$(MAKE) visionossim-debug # Requires Xcode 15+ .PHONY: macos macos: @@ -87,6 +93,22 @@ tvossim: tvossim-debug: $(XCODEBUILD) build -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (tvOS only)" -destination "generic/platform=tvOS Simulator" -configuration "Debug" GCC_PREPROCESSOR_DEFINITIONS='$${inherited} $(MAKEARGS)' $(OUTPUT_FMT_CMD) +.PHONY: visionos +visionos: + $(XCODEBUILD) build -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (visionOS only)" -destination "generic/platform=xrOS" GCC_PREPROCESSOR_DEFINITIONS='$${inherited} $(MAKEARGS)' $(OUTPUT_FMT_CMD) + +.PHONY: visionos-debug +visionos-debug: + $(XCODEBUILD) build -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (visionOS only)" -destination "generic/platform=xrOS" -configuration "Debug" GCC_PREPROCESSOR_DEFINITIONS='$${inherited} $(MAKEARGS)' $(OUTPUT_FMT_CMD) + +.PHONY: visionossim +visionossim: + $(XCODEBUILD) build -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (visionOS only)" -destination "generic/platform=xrOS Simulator" GCC_PREPROCESSOR_DEFINITIONS='$${inherited} $(MAKEARGS)' $(OUTPUT_FMT_CMD) + +.PHONY: visionossim-debug +visionossim-debug: + $(XCODEBUILD) build -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (visionOS only)" -destination "generic/platform=xrOS Simulator" -configuration "Debug" GCC_PREPROCESSOR_DEFINITIONS='$${inherited} $(MAKEARGS)' $(OUTPUT_FMT_CMD) + .PHONY: clean clean: $(XCODEBUILD) clean -project "$(XC_PROJ)" -scheme "$(XC_SCHEME) (macOS only)" -destination "generic/platform=macOS" $(OUTPUT_FMT_CMD) diff --git a/MoltenVK/MoltenVK.xcodeproj/project.pbxproj b/MoltenVK/MoltenVK.xcodeproj/project.pbxproj index 2c4b87eb0..202efa912 100644 --- a/MoltenVK/MoltenVK.xcodeproj/project.pbxproj +++ b/MoltenVK/MoltenVK.xcodeproj/project.pbxproj @@ -105,7 +105,7 @@ 2FEA0AA324902F9F00EEF3AD /* MVKRenderPass.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7941C7DFB4800632CA3 /* MVKRenderPass.mm */; }; 2FEA0AA424902F9F00EEF3AD /* MVKCmdTransfer.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB76D1C7DFB4800632CA3 /* MVKCmdTransfer.mm */; }; 2FEA0AA524902F9F00EEF3AD /* MVKCmdQueries.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7711C7DFB4800632CA3 /* MVKCmdQueries.mm */; }; - 2FEA0AA624902F9F00EEF3AD /* vk_mvk_moltenvk.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7AC1C7DFB4800632CA3 /* vk_mvk_moltenvk.mm */; }; + 2FEA0AA624902F9F00EEF3AD /* mvk_api.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7AC1C7DFB4800632CA3 /* mvk_api.mm */; }; 2FEA0AA724902F9F00EEF3AD /* MVKSwapchain.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB79C1C7DFB4800632CA3 /* MVKSwapchain.mm */; }; 2FEA0AA824902F9F00EEF3AD /* MVKCommandEncoderState.mm in Sources */ = {isa = PBXBuildFile; fileRef = A95B7D681D3EE486003183D3 /* MVKCommandEncoderState.mm */; }; 2FEA0AA924902F9F00EEF3AD /* MVKGPUCapture.mm in Sources */ = {isa = PBXBuildFile; fileRef = A93E83342121F0C8001FEBD4 /* MVKGPUCapture.mm */; }; @@ -261,8 +261,8 @@ A94FB81F1C7DFB4800632CA3 /* MVKLayers.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7A11C7DFB4800632CA3 /* MVKLayers.mm */; }; A94FB82A1C7DFB4800632CA3 /* mvk_datatypes.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7A91C7DFB4800632CA3 /* mvk_datatypes.mm */; }; A94FB82B1C7DFB4800632CA3 /* mvk_datatypes.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7A91C7DFB4800632CA3 /* mvk_datatypes.mm */; }; - A94FB8301C7DFB4800632CA3 /* vk_mvk_moltenvk.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7AC1C7DFB4800632CA3 /* vk_mvk_moltenvk.mm */; }; - A94FB8311C7DFB4800632CA3 /* vk_mvk_moltenvk.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7AC1C7DFB4800632CA3 /* vk_mvk_moltenvk.mm */; }; + A94FB8301C7DFB4800632CA3 /* mvk_api.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7AC1C7DFB4800632CA3 /* mvk_api.mm */; }; + A94FB8311C7DFB4800632CA3 /* mvk_api.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7AC1C7DFB4800632CA3 /* mvk_api.mm */; }; A94FB8321C7DFB4800632CA3 /* vulkan.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7AD1C7DFB4800632CA3 /* vulkan.mm */; }; A94FB8331C7DFB4800632CA3 /* vulkan.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7AD1C7DFB4800632CA3 /* vulkan.mm */; }; A95870F81C90D29F009EB096 /* MVKCommandResourceFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = A95870F61C90D29F009EB096 /* MVKCommandResourceFactory.h */; }; @@ -318,6 +318,15 @@ A9A5E9C725C0822700E9085E /* MVKEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9A5E9C525C0822700E9085E /* MVKEnvironment.cpp */; }; A9A5E9C825C0822700E9085E /* MVKEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9A5E9C525C0822700E9085E /* MVKEnvironment.cpp */; }; A9A5E9C925C0822700E9085E /* MVKEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9A5E9C525C0822700E9085E /* MVKEnvironment.cpp */; }; + A9B3D73B29F9B3B100745CD4 /* mvk_deprecated_api.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B3D73829F9B3B100745CD4 /* mvk_deprecated_api.h */; }; + A9B3D73C29F9B3B100745CD4 /* mvk_deprecated_api.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B3D73829F9B3B100745CD4 /* mvk_deprecated_api.h */; }; + A9B3D73D29F9B3B100745CD4 /* mvk_deprecated_api.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B3D73829F9B3B100745CD4 /* mvk_deprecated_api.h */; }; + A9B3D73E29F9B3B100745CD4 /* mvk_config.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B3D73A29F9B3B100745CD4 /* mvk_config.h */; }; + A9B3D73F29F9B3B100745CD4 /* mvk_config.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B3D73A29F9B3B100745CD4 /* mvk_config.h */; }; + A9B3D74029F9B3B100745CD4 /* mvk_config.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B3D73A29F9B3B100745CD4 /* mvk_config.h */; }; + A9B3D74229F9BDEE00745CD4 /* mvk_private_api.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B3D74129F9BDEE00745CD4 /* mvk_private_api.h */; }; + A9B3D74329F9BDEE00745CD4 /* mvk_private_api.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B3D74129F9BDEE00745CD4 /* mvk_private_api.h */; }; + A9B3D74429F9BDEE00745CD4 /* mvk_private_api.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B3D74129F9BDEE00745CD4 /* mvk_private_api.h */; }; A9B51BD7225E986A00AC74D2 /* MVKOSExtensions.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9B51BD2225E986A00AC74D2 /* MVKOSExtensions.mm */; }; A9B51BD8225E986A00AC74D2 /* MVKOSExtensions.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9B51BD2225E986A00AC74D2 /* MVKOSExtensions.mm */; }; A9B51BD9225E986A00AC74D2 /* MVKOSExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B51BD6225E986A00AC74D2 /* MVKOSExtensions.h */; }; @@ -365,6 +374,126 @@ A9F3D9DD24732A4D00745190 /* MVKSmallVectorAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F3D9D924732A4C00745190 /* MVKSmallVectorAllocator.h */; }; A9F3D9DE24732A4D00745190 /* MVKSmallVector.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F3D9DB24732A4D00745190 /* MVKSmallVector.h */; }; A9F3D9DF24732A4D00745190 /* MVKSmallVector.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F3D9DB24732A4D00745190 /* MVKSmallVector.h */; }; + DCFD7EE42A45BC6E007BBBF7 /* MVKExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = A909F65A213B190600FCD6BE /* MVKExtensions.h */; }; + DCFD7EE52A45BC6E007BBBF7 /* vk_mvk_moltenvk.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7691C7DFB4800632CA3 /* vk_mvk_moltenvk.h */; }; + DCFD7EE62A45BC6E007BBBF7 /* MVKDeviceFeatureStructs.def in Headers */ = {isa = PBXBuildFile; fileRef = A987B666289AFB2400F933C8 /* MVKDeviceFeatureStructs.def */; }; + DCFD7EE72A45BC6E007BBBF7 /* mvk_datatypes.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7671C7DFB4800632CA3 /* mvk_datatypes.h */; }; + DCFD7EE82A45BC6E007BBBF7 /* mvk_vulkan.h in Headers */ = {isa = PBXBuildFile; fileRef = A948BB7E1E51642700DE59F2 /* mvk_vulkan.h */; }; + DCFD7EE92A45BC6E007BBBF7 /* MVKEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = A98149431FB6A3F7005F00B4 /* MVKEnvironment.h */; }; + DCFD7EEA2A45BC6E007BBBF7 /* MVKSurface.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7991C7DFB4800632CA3 /* MVKSurface.h */; }; + DCFD7EEB2A45BC6E007BBBF7 /* MTLRenderPipelineDescriptor+MoltenVK.h in Headers */ = {isa = PBXBuildFile; fileRef = A9E53DFE21064F84002781DD /* MTLRenderPipelineDescriptor+MoltenVK.h */; }; + DCFD7EEC2A45BC6E007BBBF7 /* MVKInstance.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB78B1C7DFB4800632CA3 /* MVKInstance.h */; }; + DCFD7EED2A45BC6E007BBBF7 /* MVKCommandResourceFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = A95870F61C90D29F009EB096 /* MVKCommandResourceFactory.h */; }; + DCFD7EEE2A45BC6E007BBBF7 /* MVKQueryPool.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB78F1C7DFB4800632CA3 /* MVKQueryPool.h */; }; + DCFD7EEF2A45BC6E007BBBF7 /* MVKCommandEncoderState.h in Headers */ = {isa = PBXBuildFile; fileRef = A95B7D671D3EE486003183D3 /* MVKCommandEncoderState.h */; }; + DCFD7EF02A45BC6E007BBBF7 /* MVKCommandPipelineStateFactoryShaderSource.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB77C1C7DFB4800632CA3 /* MVKCommandPipelineStateFactoryShaderSource.h */; }; + DCFD7EF12A45BC6E007BBBF7 /* MVKDescriptorSet.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7811C7DFB4800632CA3 /* MVKDescriptorSet.h */; }; + DCFD7EF22A45BC6E007BBBF7 /* MVKBitArray.h in Headers */ = {isa = PBXBuildFile; fileRef = A9D7104E25CDE05E00E38106 /* MVKBitArray.h */; }; + DCFD7EF32A45BC6E007BBBF7 /* NSString+MoltenVK.h in Headers */ = {isa = PBXBuildFile; fileRef = A9E53DD22100B197002781DD /* NSString+MoltenVK.h */; }; + DCFD7EF42A45BC6E007BBBF7 /* CAMetalLayer+MoltenVK.h in Headers */ = {isa = PBXBuildFile; fileRef = A9E53DD12100B197002781DD /* CAMetalLayer+MoltenVK.h */; }; + DCFD7EF52A45BC6E007BBBF7 /* MVKCodec.h in Headers */ = {isa = PBXBuildFile; fileRef = 45557A5121C9EFF3008868BD /* MVKCodec.h */; }; + DCFD7EF62A45BC6E007BBBF7 /* MVKRenderPass.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7931C7DFB4800632CA3 /* MVKRenderPass.h */; }; + DCFD7EF72A45BC6E007BBBF7 /* MVKLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F0429E1FB4CF82009FCCB8 /* MVKLogging.h */; }; + DCFD7EF82A45BC6E007BBBF7 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h in Headers */ = {isa = PBXBuildFile; fileRef = 4536382D2508A4C6000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h */; }; + DCFD7EF92A45BC6E007BBBF7 /* MVKQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7911C7DFB4800632CA3 /* MVKQueue.h */; }; + DCFD7EFA2A45BC6E007BBBF7 /* MVKFramebuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7871C7DFB4800632CA3 /* MVKFramebuffer.h */; }; + DCFD7EFB2A45BC6E007BBBF7 /* MVKWatermarkShaderSource.h in Headers */ = {isa = PBXBuildFile; fileRef = A981494B1FB6A3F7005F00B4 /* MVKWatermarkShaderSource.h */; }; + DCFD7EFC2A45BC6E007BBBF7 /* MTLSamplerDescriptor+MoltenVK.h in Headers */ = {isa = PBXBuildFile; fileRef = A9E53DD32100B197002781DD /* MTLSamplerDescriptor+MoltenVK.h */; }; + DCFD7EFD2A45BC6E007BBBF7 /* MVKSync.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB79D1C7DFB4800632CA3 /* MVKSync.h */; }; + DCFD7EFE2A45BC6E007BBBF7 /* MVKDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7831C7DFB4800632CA3 /* MVKDevice.h */; }; + DCFD7EFF2A45BC6E007BBBF7 /* MVKSmallVector.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F3D9DB24732A4D00745190 /* MVKSmallVector.h */; }; + DCFD7F002A45BC6E007BBBF7 /* MVKCommandPool.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB77A1C7DFB4800632CA3 /* MVKCommandPool.h */; }; + DCFD7F012A45BC6E007BBBF7 /* MVKShaderModule.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7971C7DFB4800632CA3 /* MVKShaderModule.h */; }; + DCFD7F022A45BC6E007BBBF7 /* MVKVulkanAPIObject.h in Headers */ = {isa = PBXBuildFile; fileRef = A99C91012295FAC500A061DA /* MVKVulkanAPIObject.h */; }; + DCFD7F032A45BC6E007BBBF7 /* MVKCmdQueries.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7701C7DFB4800632CA3 /* MVKCmdQueries.h */; }; + DCFD7F042A45BC6E007BBBF7 /* MVKCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7761C7DFB4800632CA3 /* MVKCommand.h */; }; + DCFD7F052A45BC6E007BBBF7 /* MVKBaseObject.h in Headers */ = {isa = PBXBuildFile; fileRef = A98149421FB6A3F7005F00B4 /* MVKBaseObject.h */; }; + DCFD7F062A45BC6E007BBBF7 /* MVKMTLBufferAllocation.h in Headers */ = {isa = PBXBuildFile; fileRef = A9C96DCE1DDC20C20053187F /* MVKMTLBufferAllocation.h */; }; + DCFD7F072A45BC6E007BBBF7 /* MVKObjectPool.h in Headers */ = {isa = PBXBuildFile; fileRef = A98149461FB6A3F7005F00B4 /* MVKObjectPool.h */; }; + DCFD7F082A45BC6E007BBBF7 /* MVKSwapchain.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB79B1C7DFB4800632CA3 /* MVKSwapchain.h */; }; + DCFD7F092A45BC6E007BBBF7 /* MVKGPUCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = A93E832E2121C5D3001FEBD4 /* MVKGPUCapture.h */; }; + DCFD7F0A2A45BC6E007BBBF7 /* MVKBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB77F1C7DFB4800632CA3 /* MVKBuffer.h */; }; + DCFD7F0B2A45BC6E007BBBF7 /* MVKCommonEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F0429D1FB4CF82009FCCB8 /* MVKCommonEnvironment.h */; }; + DCFD7F0C2A45BC6E007BBBF7 /* MVKWatermark.h in Headers */ = {isa = PBXBuildFile; fileRef = A98149491FB6A3F7005F00B4 /* MVKWatermark.h */; }; + DCFD7F0D2A45BC6E007BBBF7 /* MVKOSExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B51BD6225E986A00AC74D2 /* MVKOSExtensions.h */; }; + DCFD7F0E2A45BC6E007BBBF7 /* MVKCmdRenderPass.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7721C7DFB4800632CA3 /* MVKCmdRenderPass.h */; }; + DCFD7F0F2A45BC6E007BBBF7 /* MVKCmdPipeline.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB76E1C7DFB4800632CA3 /* MVKCmdPipeline.h */; }; + DCFD7F102A45BC6E007BBBF7 /* MVKSmallVectorAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F3D9D924732A4C00745190 /* MVKSmallVectorAllocator.h */; }; + DCFD7F112A45BC6E007BBBF7 /* MVKPipeline.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB78D1C7DFB4800632CA3 /* MVKPipeline.h */; }; + DCFD7F122A45BC6E007BBBF7 /* MVKImage.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7891C7DFB4800632CA3 /* MVKImage.h */; }; + DCFD7F132A45BC6E007BBBF7 /* MVKBlockObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4553AEFA2251617100E8EBCD /* MVKBlockObserver.h */; }; + DCFD7F142A45BC6E007BBBF7 /* MVKCmdTransfer.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB76C1C7DFB4800632CA3 /* MVKCmdTransfer.h */; }; + DCFD7F152A45BC6E007BBBF7 /* MVKDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = A966A5DC23C535D000BBF9B4 /* MVKDescriptor.h */; }; + DCFD7F162A45BC6E007BBBF7 /* MVKCmdDraw.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7741C7DFB4800632CA3 /* MVKCmdDraw.h */; }; + DCFD7F172A45BC6E007BBBF7 /* MVKCommandBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7781C7DFB4800632CA3 /* MVKCommandBuffer.h */; }; + DCFD7F182A45BC6E007BBBF7 /* MTLRenderPassDescriptor+MoltenVK.h in Headers */ = {isa = PBXBuildFile; fileRef = A9E53DEE2100B302002781DD /* MTLRenderPassDescriptor+MoltenVK.h */; }; + DCFD7F192A45BC6E007BBBF7 /* MVKCmdDebug.h in Headers */ = {isa = PBXBuildFile; fileRef = A99C90EC229455B200A061DA /* MVKCmdDebug.h */; }; + DCFD7F1A2A45BC6E007BBBF7 /* MVKWatermarkTextureContent.h in Headers */ = {isa = PBXBuildFile; fileRef = A981494C1FB6A3F7005F00B4 /* MVKWatermarkTextureContent.h */; }; + DCFD7F1B2A45BC6E007BBBF7 /* MVKFoundation.h in Headers */ = {isa = PBXBuildFile; fileRef = A98149441FB6A3F7005F00B4 /* MVKFoundation.h */; }; + DCFD7F1C2A45BC6E007BBBF7 /* MVKDeviceMemory.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7851C7DFB4800632CA3 /* MVKDeviceMemory.h */; }; + DCFD7F1D2A45BC6E007BBBF7 /* MVKMTLResourceBindings.h in Headers */ = {isa = PBXBuildFile; fileRef = A9E4B7881E1D8AF10046A4CE /* MVKMTLResourceBindings.h */; }; + DCFD7F1E2A45BC6E007BBBF7 /* MVKExtensions.def in Headers */ = {isa = PBXBuildFile; fileRef = 45003E6F214AD4C900E989CB /* MVKExtensions.def */; }; + DCFD7F1F2A45BC6E007BBBF7 /* mvk_datatypes.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A9CEAAD1227378D400FAF779 /* mvk_datatypes.hpp */; }; + DCFD7F202A45BC6E007BBBF7 /* MVKCommandEncodingPool.h in Headers */ = {isa = PBXBuildFile; fileRef = A90C8DE81F45354D009CB32C /* MVKCommandEncodingPool.h */; }; + DCFD7F212A45BC6E007BBBF7 /* MVKResource.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7951C7DFB4800632CA3 /* MVKResource.h */; }; + DCFD7F222A45BC6E007BBBF7 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h in Headers */ = {isa = PBXBuildFile; fileRef = 453638312508A4C7000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h */; }; + DCFD7F232A45BC6E007BBBF7 /* MTLTextureDescriptor+MoltenVK.h in Headers */ = {isa = PBXBuildFile; fileRef = A9E53DD02100B197002781DD /* MTLTextureDescriptor+MoltenVK.h */; }; + DCFD7F242A45BC6E007BBBF7 /* MVKPixelFormats.h in Headers */ = {isa = PBXBuildFile; fileRef = A9653FB724129C84005999D7 /* MVKPixelFormats.h */; }; + DCFD7F252A45BC6E007BBBF7 /* MVKStrings.h in Headers */ = {isa = PBXBuildFile; fileRef = A981496A1FB6A998005F00B4 /* MVKStrings.h */; }; + DCFD7F262A45BC6E007BBBF7 /* MVKLayers.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7A01C7DFB4800632CA3 /* MVKLayers.h */; }; + DCFD7F282A45BC6E007BBBF7 /* MVKBlockObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 4553AEF62251617100E8EBCD /* MVKBlockObserver.m */; }; + DCFD7F292A45BC6E007BBBF7 /* MTLRenderPipelineDescriptor+MoltenVK.m in Sources */ = {isa = PBXBuildFile; fileRef = A9E53DFA21064F84002781DD /* MTLRenderPipelineDescriptor+MoltenVK.m */; }; + DCFD7F2A2A45BC6E007BBBF7 /* MVKResource.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7961C7DFB4800632CA3 /* MVKResource.mm */; }; + DCFD7F2B2A45BC6E007BBBF7 /* MVKDescriptorSet.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7821C7DFB4800632CA3 /* MVKDescriptorSet.mm */; }; + DCFD7F2C2A45BC6E007BBBF7 /* MVKVulkanAPIObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = A99C91002295FAC500A061DA /* MVKVulkanAPIObject.mm */; }; + DCFD7F2D2A45BC6E007BBBF7 /* MTLTextureDescriptor+MoltenVK.m in Sources */ = {isa = PBXBuildFile; fileRef = A9E53DD52100B197002781DD /* MTLTextureDescriptor+MoltenVK.m */; }; + DCFD7F2E2A45BC6E007BBBF7 /* MVKCommandResourceFactory.mm in Sources */ = {isa = PBXBuildFile; fileRef = A95870F71C90D29F009EB096 /* MVKCommandResourceFactory.mm */; }; + DCFD7F2F2A45BC6E007BBBF7 /* MVKCommandEncodingPool.mm in Sources */ = {isa = PBXBuildFile; fileRef = A90C8DE91F45354D009CB32C /* MVKCommandEncodingPool.mm */; }; + DCFD7F302A45BC6E007BBBF7 /* MVKWatermark.mm in Sources */ = {isa = PBXBuildFile; fileRef = A981494A1FB6A3F7005F00B4 /* MVKWatermark.mm */; }; + DCFD7F312A45BC6E007BBBF7 /* MVKBaseObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = A98149411FB6A3F7005F00B4 /* MVKBaseObject.mm */; }; + DCFD7F322A45BC6E007BBBF7 /* NSString+MoltenVK.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9E53DD42100B197002781DD /* NSString+MoltenVK.mm */; }; + DCFD7F332A45BC6E007BBBF7 /* vulkan.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7AD1C7DFB4800632CA3 /* vulkan.mm */; }; + DCFD7F342A45BC6E007BBBF7 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.m in Sources */ = {isa = PBXBuildFile; fileRef = 4536382F2508A4C6000EFFD3 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.m */; }; + DCFD7F352A45BC6E007BBBF7 /* MVKSurface.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB79A1C7DFB4800632CA3 /* MVKSurface.mm */; }; + DCFD7F362A45BC6E007BBBF7 /* MVKQueryPool.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7901C7DFB4800632CA3 /* MVKQueryPool.mm */; }; + DCFD7F372A45BC6E007BBBF7 /* MVKInstance.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB78C1C7DFB4800632CA3 /* MVKInstance.mm */; }; + DCFD7F382A45BC6E007BBBF7 /* MVKDeviceMemory.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7861C7DFB4800632CA3 /* MVKDeviceMemory.mm */; }; + DCFD7F392A45BC6E007BBBF7 /* MVKImage.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB78A1C7DFB4800632CA3 /* MVKImage.mm */; }; + DCFD7F3A2A45BC6E007BBBF7 /* MVKCommandPool.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB77B1C7DFB4800632CA3 /* MVKCommandPool.mm */; }; + DCFD7F3B2A45BC6E007BBBF7 /* MVKCmdDraw.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7751C7DFB4800632CA3 /* MVKCmdDraw.mm */; }; + DCFD7F3C2A45BC6E007BBBF7 /* MVKCommandBuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7791C7DFB4800632CA3 /* MVKCommandBuffer.mm */; }; + DCFD7F3D2A45BC6E007BBBF7 /* MVKCmdRenderPass.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7731C7DFB4800632CA3 /* MVKCmdRenderPass.mm */; }; + DCFD7F3E2A45BC6E007BBBF7 /* MVKBuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7801C7DFB4800632CA3 /* MVKBuffer.mm */; }; + DCFD7F3F2A45BC6E007BBBF7 /* MVKEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9A5E9C525C0822700E9085E /* MVKEnvironment.cpp */; }; + DCFD7F402A45BC6E007BBBF7 /* mvk_datatypes.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7A91C7DFB4800632CA3 /* mvk_datatypes.mm */; }; + DCFD7F412A45BC6E007BBBF7 /* MVKExtensions.mm in Sources */ = {isa = PBXBuildFile; fileRef = A909F65E213B190700FCD6BE /* MVKExtensions.mm */; }; + DCFD7F422A45BC6E007BBBF7 /* MVKFoundation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A98149451FB6A3F7005F00B4 /* MVKFoundation.cpp */; }; + DCFD7F432A45BC6E007BBBF7 /* MVKPixelFormats.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9653FB924129C84005999D7 /* MVKPixelFormats.mm */; }; + DCFD7F442A45BC6E007BBBF7 /* MVKDevice.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7841C7DFB4800632CA3 /* MVKDevice.mm */; }; + DCFD7F452A45BC6E007BBBF7 /* MTLRenderPassDescriptor+MoltenVK.m in Sources */ = {isa = PBXBuildFile; fileRef = A9E53DF22100B302002781DD /* MTLRenderPassDescriptor+MoltenVK.m */; }; + DCFD7F462A45BC6E007BBBF7 /* MVKDescriptor.mm in Sources */ = {isa = PBXBuildFile; fileRef = A966A5DE23C535D000BBF9B4 /* MVKDescriptor.mm */; }; + DCFD7F472A45BC6E007BBBF7 /* MVKPipeline.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB78E1C7DFB4800632CA3 /* MVKPipeline.mm */; }; + DCFD7F482A45BC6E007BBBF7 /* MVKQueue.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7921C7DFB4800632CA3 /* MVKQueue.mm */; }; + DCFD7F492A45BC6E007BBBF7 /* MTLSamplerDescriptor+MoltenVK.m in Sources */ = {isa = PBXBuildFile; fileRef = A9E53DCD2100B197002781DD /* MTLSamplerDescriptor+MoltenVK.m */; }; + DCFD7F4A2A45BC6E007BBBF7 /* MVKRenderPass.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7941C7DFB4800632CA3 /* MVKRenderPass.mm */; }; + DCFD7F4B2A45BC6E007BBBF7 /* MVKCmdTransfer.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB76D1C7DFB4800632CA3 /* MVKCmdTransfer.mm */; }; + DCFD7F4C2A45BC6E007BBBF7 /* MVKCmdQueries.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7711C7DFB4800632CA3 /* MVKCmdQueries.mm */; }; + DCFD7F4D2A45BC6E007BBBF7 /* mvk_api.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7AC1C7DFB4800632CA3 /* mvk_api.mm */; }; + DCFD7F4E2A45BC6E007BBBF7 /* MVKSwapchain.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB79C1C7DFB4800632CA3 /* MVKSwapchain.mm */; }; + DCFD7F4F2A45BC6E007BBBF7 /* MVKCommandEncoderState.mm in Sources */ = {isa = PBXBuildFile; fileRef = A95B7D681D3EE486003183D3 /* MVKCommandEncoderState.mm */; }; + DCFD7F502A45BC6E007BBBF7 /* MVKGPUCapture.mm in Sources */ = {isa = PBXBuildFile; fileRef = A93E83342121F0C8001FEBD4 /* MVKGPUCapture.mm */; }; + DCFD7F512A45BC6E007BBBF7 /* MVKOSExtensions.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9B51BD2225E986A00AC74D2 /* MVKOSExtensions.mm */; }; + DCFD7F522A45BC6E007BBBF7 /* MVKShaderModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7981C7DFB4800632CA3 /* MVKShaderModule.mm */; }; + DCFD7F532A45BC6E007BBBF7 /* MVKSync.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB79E1C7DFB4800632CA3 /* MVKSync.mm */; }; + DCFD7F542A45BC6E007BBBF7 /* MVKCodec.mm in Sources */ = {isa = PBXBuildFile; fileRef = 45557A4D21C9EFF3008868BD /* MVKCodec.mm */; }; + DCFD7F552A45BC6E007BBBF7 /* MVKCmdPipeline.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB76F1C7DFB4800632CA3 /* MVKCmdPipeline.mm */; }; + DCFD7F562A45BC6E007BBBF7 /* MVKLayers.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7A11C7DFB4800632CA3 /* MVKLayers.mm */; }; + DCFD7F572A45BC6E007BBBF7 /* MVKFramebuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7881C7DFB4800632CA3 /* MVKFramebuffer.mm */; }; + DCFD7F582A45BC6E007BBBF7 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.m in Sources */ = {isa = PBXBuildFile; fileRef = 453638302508A4C6000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.m */; }; + DCFD7F592A45BC6E007BBBF7 /* MVKMTLBufferAllocation.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9C96DCF1DDC20C20053187F /* MVKMTLBufferAllocation.mm */; }; + DCFD7F5A2A45BC6E007BBBF7 /* CAMetalLayer+MoltenVK.m in Sources */ = {isa = PBXBuildFile; fileRef = A9E53DD62100B197002781DD /* CAMetalLayer+MoltenVK.m */; }; + DCFD7F5B2A45BC6E007BBBF7 /* MVKCmdDispatch.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9096E5D1F81E16300DFBEA6 /* MVKCmdDispatch.mm */; }; + DCFD7F5C2A45BC6E007BBBF7 /* MVKCmdDebug.mm in Sources */ = {isa = PBXBuildFile; fileRef = A99C90ED229455B300A061DA /* MVKCmdDebug.mm */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -417,6 +546,20 @@ remoteGlobalIDString = A9092A8C1A81717B00051823; remoteInfo = MoltenVKShaderConverter; }; + DCA2CEAE2A45DFD400FB75B6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A9C86CB61C55B8350096CAF2 /* MoltenVKShaderConverter.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = DCFD7F6F2A45BDA0007BBBF7; + remoteInfo = "MoltenVKShaderConverter-xrOS"; + }; + DCBC41212A45DB1000F49BD1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A9C86CB61C55B8350096CAF2 /* MoltenVKShaderConverter.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = DCFD7F882A45BDA0007BBBF7; + remoteInfo = MoltenVKShaderConverter; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ @@ -493,7 +636,7 @@ A94FB7A01C7DFB4800632CA3 /* MVKLayers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKLayers.h; sourceTree = ""; }; A94FB7A11C7DFB4800632CA3 /* MVKLayers.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MVKLayers.mm; sourceTree = ""; }; A94FB7A91C7DFB4800632CA3 /* mvk_datatypes.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = mvk_datatypes.mm; sourceTree = ""; }; - A94FB7AC1C7DFB4800632CA3 /* vk_mvk_moltenvk.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = vk_mvk_moltenvk.mm; sourceTree = ""; }; + A94FB7AC1C7DFB4800632CA3 /* mvk_api.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = mvk_api.mm; sourceTree = ""; }; A94FB7AD1C7DFB4800632CA3 /* vulkan.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = vulkan.mm; sourceTree = ""; }; A95870F61C90D29F009EB096 /* MVKCommandResourceFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKCommandResourceFactory.h; sourceTree = ""; }; A95870F71C90D29F009EB096 /* MVKCommandResourceFactory.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MVKCommandResourceFactory.mm; sourceTree = ""; }; @@ -521,6 +664,9 @@ A99C91012295FAC500A061DA /* MVKVulkanAPIObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKVulkanAPIObject.h; sourceTree = ""; }; A9A5E9C525C0822700E9085E /* MVKEnvironment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MVKEnvironment.cpp; sourceTree = ""; }; A9AD67C72054DD6C00ED3C08 /* vulkan */ = {isa = PBXFileReference; lastKnownFileType = folder; path = vulkan; sourceTree = ""; }; + A9B3D73829F9B3B100745CD4 /* mvk_deprecated_api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mvk_deprecated_api.h; sourceTree = ""; }; + A9B3D73A29F9B3B100745CD4 /* mvk_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mvk_config.h; sourceTree = ""; }; + A9B3D74129F9BDEE00745CD4 /* mvk_private_api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mvk_private_api.h; sourceTree = ""; }; A9B51BD2225E986A00AC74D2 /* MVKOSExtensions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MVKOSExtensions.mm; sourceTree = ""; }; A9B51BD6225E986A00AC74D2 /* MVKOSExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKOSExtensions.h; sourceTree = ""; }; A9B8EE0A1A98D796009C5A02 /* libMoltenVK.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libMoltenVK.a; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -549,6 +695,7 @@ A9F0429E1FB4CF82009FCCB8 /* MVKLogging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKLogging.h; sourceTree = ""; }; A9F3D9D924732A4C00745190 /* MVKSmallVectorAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKSmallVectorAllocator.h; sourceTree = ""; }; A9F3D9DB24732A4D00745190 /* MVKSmallVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKSmallVector.h; sourceTree = ""; }; + DCFD7F622A45BC6E007BBBF7 /* libMoltenVK.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libMoltenVK.a; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXGroup section */ @@ -569,7 +716,10 @@ A94FB7651C7DFB4800632CA3 /* API */ = { isa = PBXGroup; children = ( + A9B3D73A29F9B3B100745CD4 /* mvk_config.h */, A94FB7671C7DFB4800632CA3 /* mvk_datatypes.h */, + A9B3D73829F9B3B100745CD4 /* mvk_deprecated_api.h */, + A9B3D74129F9BDEE00745CD4 /* mvk_private_api.h */, A948BB7E1E51642700DE59F2 /* mvk_vulkan.h */, A94FB7691C7DFB4800632CA3 /* vk_mvk_moltenvk.h */, ); @@ -676,7 +826,7 @@ children = ( A9CEAAD1227378D400FAF779 /* mvk_datatypes.hpp */, A94FB7A91C7DFB4800632CA3 /* mvk_datatypes.mm */, - A94FB7AC1C7DFB4800632CA3 /* vk_mvk_moltenvk.mm */, + A94FB7AC1C7DFB4800632CA3 /* mvk_api.mm */, A94FB7AD1C7DFB4800632CA3 /* vulkan.mm */, ); path = Vulkan; @@ -716,6 +866,7 @@ A98149821FB6B566005F00B4 /* libMoltenVKShaderConverter.a */, 2FEA0D1C249040CA00EEF3AD /* libMoltenVKShaderConverter.a */, A98149841FB6B566005F00B4 /* libMoltenVKShaderConverter.a */, + DCBC41222A45DB1000F49BD1 /* libMoltenVKShaderConverter.a */, ); name = Products; sourceTree = ""; @@ -783,6 +934,7 @@ A9B8EE0A1A98D796009C5A02 /* libMoltenVK.a */, A9CBEE011B6299D800E45FDC /* libMoltenVK.a */, 2FEA0ABA24902F9F00EEF3AD /* libMoltenVK.a */, + DCFD7F622A45BC6E007BBBF7 /* libMoltenVK.a */, ); name = Products; sourceTree = ""; @@ -819,9 +971,11 @@ 2FEA0A5624902F9F00EEF3AD /* MVKWatermarkShaderSource.h in Headers */, 2FEA0A5724902F9F00EEF3AD /* MTLSamplerDescriptor+MoltenVK.h in Headers */, 2FEA0A5824902F9F00EEF3AD /* MVKSync.h in Headers */, + A9B3D73F29F9B3B100745CD4 /* mvk_config.h in Headers */, 2FEA0A5924902F9F00EEF3AD /* MVKDevice.h in Headers */, 2FEA0A5A24902F9F00EEF3AD /* MVKSmallVector.h in Headers */, 2FEA0A5C24902F9F00EEF3AD /* MVKCommandPool.h in Headers */, + A9B3D74329F9BDEE00745CD4 /* mvk_private_api.h in Headers */, 2FEA0A5D24902F9F00EEF3AD /* MVKShaderModule.h in Headers */, 2FEA0A5E24902F9F00EEF3AD /* MVKVulkanAPIObject.h in Headers */, 2FEA0A5F24902F9F00EEF3AD /* MVKCmdQueries.h in Headers */, @@ -844,6 +998,7 @@ 2FEA0A7024902F9F00EEF3AD /* MVKCmdTransfer.h in Headers */, 2FEA0A7124902F9F00EEF3AD /* MVKDescriptor.h in Headers */, 2FEA0A7224902F9F00EEF3AD /* MVKCmdDraw.h in Headers */, + A9B3D73C29F9B3B100745CD4 /* mvk_deprecated_api.h in Headers */, 2FEA0A7324902F9F00EEF3AD /* MVKCommandBuffer.h in Headers */, 2FEA0A7424902F9F00EEF3AD /* MTLRenderPassDescriptor+MoltenVK.h in Headers */, 2FEA0A7524902F9F00EEF3AD /* MVKCmdDebug.h in Headers */, @@ -870,6 +1025,7 @@ A909F65F213B190700FCD6BE /* MVKExtensions.h in Headers */, A94FB7B41C7DFB4800632CA3 /* vk_mvk_moltenvk.h in Headers */, A987B669289AFB8A00F933C8 /* MVKDeviceFeatureStructs.def in Headers */, + A9B3D73E29F9B3B100745CD4 /* mvk_config.h in Headers */, A94FB7B01C7DFB4800632CA3 /* mvk_datatypes.h in Headers */, A948BB7F1E51642700DE59F2 /* mvk_vulkan.h in Headers */, A98149511FB6A3F7005F00B4 /* MVKEnvironment.h in Headers */, @@ -899,10 +1055,12 @@ A94FB80C1C7DFB4800632CA3 /* MVKShaderModule.h in Headers */, A99C91042295FAC600A061DA /* MVKVulkanAPIObject.h in Headers */, A94FB7C01C7DFB4800632CA3 /* MVKCmdQueries.h in Headers */, + A9B3D73B29F9B3B100745CD4 /* mvk_deprecated_api.h in Headers */, A94FB7CC1C7DFB4800632CA3 /* MVKCommand.h in Headers */, A981494F1FB6A3F7005F00B4 /* MVKBaseObject.h in Headers */, A9C96DD01DDC20C20053187F /* MVKMTLBufferAllocation.h in Headers */, A98149571FB6A3F7005F00B4 /* MVKObjectPool.h in Headers */, + A9B3D74229F9BDEE00745CD4 /* mvk_private_api.h in Headers */, A94FB8141C7DFB4800632CA3 /* MVKSwapchain.h in Headers */, A93E832F2121C5D4001FEBD4 /* MVKGPUCapture.h in Headers */, A94FB7DC1C7DFB4800632CA3 /* MVKBuffer.h in Headers */, @@ -944,6 +1102,7 @@ A909F660213B190700FCD6BE /* MVKExtensions.h in Headers */, A94FB7B51C7DFB4800632CA3 /* vk_mvk_moltenvk.h in Headers */, A987B66B289AFB8C00F933C8 /* MVKDeviceFeatureStructs.def in Headers */, + A9B3D74029F9B3B100745CD4 /* mvk_config.h in Headers */, A94FB7B11C7DFB4800632CA3 /* mvk_datatypes.h in Headers */, A948BB801E51642700DE59F2 /* mvk_vulkan.h in Headers */, A98149521FB6A3F7005F00B4 /* MVKEnvironment.h in Headers */, @@ -973,10 +1132,12 @@ A99C91052295FAC600A061DA /* MVKVulkanAPIObject.h in Headers */, A94FB7C11C7DFB4800632CA3 /* MVKCmdQueries.h in Headers */, A94FB7CD1C7DFB4800632CA3 /* MVKCommand.h in Headers */, + A9B3D73D29F9B3B100745CD4 /* mvk_deprecated_api.h in Headers */, A98149501FB6A3F7005F00B4 /* MVKBaseObject.h in Headers */, A9C96DD11DDC20C20053187F /* MVKMTLBufferAllocation.h in Headers */, A98149581FB6A3F7005F00B4 /* MVKObjectPool.h in Headers */, A94FB8151C7DFB4800632CA3 /* MVKSwapchain.h in Headers */, + A9B3D74429F9BDEE00745CD4 /* mvk_private_api.h in Headers */, A93E83302121C5D4001FEBD4 /* MVKGPUCapture.h in Headers */, A94FB7DD1C7DFB4800632CA3 /* MVKBuffer.h in Headers */, A9F042A51FB4CF83009FCCB8 /* MVKCommonEnvironment.h in Headers */, @@ -1011,6 +1172,80 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + DCFD7EE32A45BC6E007BBBF7 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DCFD7EE42A45BC6E007BBBF7 /* MVKExtensions.h in Headers */, + DCFD7EE52A45BC6E007BBBF7 /* vk_mvk_moltenvk.h in Headers */, + DCFD7EE62A45BC6E007BBBF7 /* MVKDeviceFeatureStructs.def in Headers */, + DCFD7EE72A45BC6E007BBBF7 /* mvk_datatypes.h in Headers */, + DCFD7EE82A45BC6E007BBBF7 /* mvk_vulkan.h in Headers */, + DCFD7EE92A45BC6E007BBBF7 /* MVKEnvironment.h in Headers */, + DCFD7EEA2A45BC6E007BBBF7 /* MVKSurface.h in Headers */, + DCFD7EEB2A45BC6E007BBBF7 /* MTLRenderPipelineDescriptor+MoltenVK.h in Headers */, + DCFD7EEC2A45BC6E007BBBF7 /* MVKInstance.h in Headers */, + DCFD7EED2A45BC6E007BBBF7 /* MVKCommandResourceFactory.h in Headers */, + DCFD7EEE2A45BC6E007BBBF7 /* MVKQueryPool.h in Headers */, + DCFD7EEF2A45BC6E007BBBF7 /* MVKCommandEncoderState.h in Headers */, + DCFD7EF02A45BC6E007BBBF7 /* MVKCommandPipelineStateFactoryShaderSource.h in Headers */, + DCFD7EF12A45BC6E007BBBF7 /* MVKDescriptorSet.h in Headers */, + DCFD7EF22A45BC6E007BBBF7 /* MVKBitArray.h in Headers */, + DCFD7EF32A45BC6E007BBBF7 /* NSString+MoltenVK.h in Headers */, + DCFD7EF42A45BC6E007BBBF7 /* CAMetalLayer+MoltenVK.h in Headers */, + DCFD7EF52A45BC6E007BBBF7 /* MVKCodec.h in Headers */, + DCFD7EF62A45BC6E007BBBF7 /* MVKRenderPass.h in Headers */, + DCFD7EF72A45BC6E007BBBF7 /* MVKLogging.h in Headers */, + DCFD7EF82A45BC6E007BBBF7 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h in Headers */, + DCFD7EF92A45BC6E007BBBF7 /* MVKQueue.h in Headers */, + DCFD7EFA2A45BC6E007BBBF7 /* MVKFramebuffer.h in Headers */, + DCFD7EFB2A45BC6E007BBBF7 /* MVKWatermarkShaderSource.h in Headers */, + DCFD7EFC2A45BC6E007BBBF7 /* MTLSamplerDescriptor+MoltenVK.h in Headers */, + DCFD7EFD2A45BC6E007BBBF7 /* MVKSync.h in Headers */, + DCFD7EFE2A45BC6E007BBBF7 /* MVKDevice.h in Headers */, + DCFD7EFF2A45BC6E007BBBF7 /* MVKSmallVector.h in Headers */, + DCFD7F002A45BC6E007BBBF7 /* MVKCommandPool.h in Headers */, + DCFD7F012A45BC6E007BBBF7 /* MVKShaderModule.h in Headers */, + DCFD7F022A45BC6E007BBBF7 /* MVKVulkanAPIObject.h in Headers */, + DCFD7F032A45BC6E007BBBF7 /* MVKCmdQueries.h in Headers */, + DCFD7F042A45BC6E007BBBF7 /* MVKCommand.h in Headers */, + DCFD7F052A45BC6E007BBBF7 /* MVKBaseObject.h in Headers */, + DCFD7F062A45BC6E007BBBF7 /* MVKMTLBufferAllocation.h in Headers */, + DCFD7F072A45BC6E007BBBF7 /* MVKObjectPool.h in Headers */, + DCFD7F082A45BC6E007BBBF7 /* MVKSwapchain.h in Headers */, + DCFD7F092A45BC6E007BBBF7 /* MVKGPUCapture.h in Headers */, + DCFD7F0A2A45BC6E007BBBF7 /* MVKBuffer.h in Headers */, + DCFD7F0B2A45BC6E007BBBF7 /* MVKCommonEnvironment.h in Headers */, + DCFD7F0C2A45BC6E007BBBF7 /* MVKWatermark.h in Headers */, + DCFD7F0D2A45BC6E007BBBF7 /* MVKOSExtensions.h in Headers */, + DCFD7F0E2A45BC6E007BBBF7 /* MVKCmdRenderPass.h in Headers */, + DCFD7F0F2A45BC6E007BBBF7 /* MVKCmdPipeline.h in Headers */, + DCFD7F102A45BC6E007BBBF7 /* MVKSmallVectorAllocator.h in Headers */, + DCFD7F112A45BC6E007BBBF7 /* MVKPipeline.h in Headers */, + DCFD7F122A45BC6E007BBBF7 /* MVKImage.h in Headers */, + DCFD7F132A45BC6E007BBBF7 /* MVKBlockObserver.h in Headers */, + DCFD7F142A45BC6E007BBBF7 /* MVKCmdTransfer.h in Headers */, + DCFD7F152A45BC6E007BBBF7 /* MVKDescriptor.h in Headers */, + DCFD7F162A45BC6E007BBBF7 /* MVKCmdDraw.h in Headers */, + DCFD7F172A45BC6E007BBBF7 /* MVKCommandBuffer.h in Headers */, + DCFD7F182A45BC6E007BBBF7 /* MTLRenderPassDescriptor+MoltenVK.h in Headers */, + DCFD7F192A45BC6E007BBBF7 /* MVKCmdDebug.h in Headers */, + DCFD7F1A2A45BC6E007BBBF7 /* MVKWatermarkTextureContent.h in Headers */, + DCFD7F1B2A45BC6E007BBBF7 /* MVKFoundation.h in Headers */, + DCFD7F1C2A45BC6E007BBBF7 /* MVKDeviceMemory.h in Headers */, + DCFD7F1D2A45BC6E007BBBF7 /* MVKMTLResourceBindings.h in Headers */, + DCFD7F1E2A45BC6E007BBBF7 /* MVKExtensions.def in Headers */, + DCFD7F1F2A45BC6E007BBBF7 /* mvk_datatypes.hpp in Headers */, + DCFD7F202A45BC6E007BBBF7 /* MVKCommandEncodingPool.h in Headers */, + DCFD7F212A45BC6E007BBBF7 /* MVKResource.h in Headers */, + DCFD7F222A45BC6E007BBBF7 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.h in Headers */, + DCFD7F232A45BC6E007BBBF7 /* MTLTextureDescriptor+MoltenVK.h in Headers */, + DCFD7F242A45BC6E007BBBF7 /* MVKPixelFormats.h in Headers */, + DCFD7F252A45BC6E007BBBF7 /* MVKStrings.h in Headers */, + DCFD7F262A45BC6E007BBBF7 /* MVKLayers.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ @@ -1074,6 +1309,26 @@ productReference = A9CBEE011B6299D800E45FDC /* libMoltenVK.a */; productType = "com.apple.product-type.library.static"; }; + DCFD7EDF2A45BC6E007BBBF7 /* MoltenVK-xrOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = DCFD7F5F2A45BC6E007BBBF7 /* Build configuration list for PBXNativeTarget "MoltenVK-xrOS" */; + buildPhases = ( + DCFD7EE22A45BC6E007BBBF7 /* Generate Version Header */, + DCFD7EE32A45BC6E007BBBF7 /* Headers */, + DCFD7F272A45BC6E007BBBF7 /* Sources */, + DCFD7F5D2A45BC6E007BBBF7 /* Copy to Staging */, + DCFD7F5E2A45BC6E007BBBF7 /* Create Dynamic Library */, + ); + buildRules = ( + ); + dependencies = ( + DCA2CEAF2A45DFD400FB75B6 /* PBXTargetDependency */, + ); + name = "MoltenVK-xrOS"; + productName = MoltenVK; + productReference = DCFD7F622A45BC6E007BBBF7 /* libMoltenVK.a */; + productType = "com.apple.product-type.library.static"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -1114,6 +1369,7 @@ A9B8EE091A98D796009C5A02 /* MoltenVK-iOS */, 2FEA0A3B24902F9F00EEF3AD /* MoltenVK-tvOS */, A9CBED861B6299D800E45FDC /* MoltenVK-macOS */, + DCFD7EDF2A45BC6E007BBBF7 /* MoltenVK-xrOS */, ); }; /* End PBXProject section */ @@ -1147,6 +1403,13 @@ remoteRef = A98149831FB6B566005F00B4 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + DCBC41222A45DB1000F49BD1 /* libMoltenVKShaderConverter.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libMoltenVKShaderConverter.a; + remoteRef = DCBC41212A45DB1000F49BD1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; /* End PBXReferenceProxy section */ /* Begin PBXShellScriptBuildPhase section */ @@ -1317,6 +1580,63 @@ shellPath = /bin/sh; shellScript = ". \"${SRCROOT}/../Scripts/copy_to_staging.sh\"\n\n"; }; + DCFD7EE22A45BC6E007BBBF7 /* Generate Version Header */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Generate Version Header"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(BUILT_PRODUCTS_DIR)/mvkGitRevDerived.h", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/../Scripts/gen_moltenvk_rev_hdr.sh\"\n"; + }; + DCFD7F5D2A45BC6E007BBBF7 /* Copy to Staging */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${BUILT_PRODUCTS_DIR}/lib${PRODUCT_NAME}.a", + ); + name = "Copy to Staging"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/$(TARGET_NAME)/CopyPhaseDummyOutputFile", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = ". \"${SRCROOT}/../Scripts/copy_to_staging.sh\"\n"; + }; + DCFD7F5E2A45BC6E007BBBF7 /* Create Dynamic Library */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${BUILT_PRODUCTS_DIR}/lib${PRODUCT_NAME}.a", + ); + name = "Create Dynamic Library"; + outputPaths = ( + "${BUILT_PRODUCTS_DIR}/dynamic/lib${PRODUCT_NAME}.dylib", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = ". \"${SRCROOT}/../Scripts/create_dylib_xros.sh\"\n"; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -1361,7 +1681,7 @@ 2FEA0AA324902F9F00EEF3AD /* MVKRenderPass.mm in Sources */, 2FEA0AA424902F9F00EEF3AD /* MVKCmdTransfer.mm in Sources */, 2FEA0AA524902F9F00EEF3AD /* MVKCmdQueries.mm in Sources */, - 2FEA0AA624902F9F00EEF3AD /* vk_mvk_moltenvk.mm in Sources */, + 2FEA0AA624902F9F00EEF3AD /* mvk_api.mm in Sources */, 2FEA0AA724902F9F00EEF3AD /* MVKSwapchain.mm in Sources */, 2FEA0AA824902F9F00EEF3AD /* MVKCommandEncoderState.mm in Sources */, 2FEA0AA924902F9F00EEF3AD /* MVKGPUCapture.mm in Sources */, @@ -1420,7 +1740,7 @@ A94FB8061C7DFB4800632CA3 /* MVKRenderPass.mm in Sources */, A94FB7BA1C7DFB4800632CA3 /* MVKCmdTransfer.mm in Sources */, A94FB7C21C7DFB4800632CA3 /* MVKCmdQueries.mm in Sources */, - A94FB8301C7DFB4800632CA3 /* vk_mvk_moltenvk.mm in Sources */, + A94FB8301C7DFB4800632CA3 /* mvk_api.mm in Sources */, A94FB8161C7DFB4800632CA3 /* MVKSwapchain.mm in Sources */, A95B7D6B1D3EE486003183D3 /* MVKCommandEncoderState.mm in Sources */, A93E83352121F0C8001FEBD4 /* MVKGPUCapture.mm in Sources */, @@ -1480,7 +1800,7 @@ A94FB8071C7DFB4800632CA3 /* MVKRenderPass.mm in Sources */, A94FB7BB1C7DFB4800632CA3 /* MVKCmdTransfer.mm in Sources */, A94FB7C31C7DFB4800632CA3 /* MVKCmdQueries.mm in Sources */, - A94FB8311C7DFB4800632CA3 /* vk_mvk_moltenvk.mm in Sources */, + A94FB8311C7DFB4800632CA3 /* mvk_api.mm in Sources */, A94FB8171C7DFB4800632CA3 /* MVKSwapchain.mm in Sources */, A95B7D6C1D3EE486003183D3 /* MVKCommandEncoderState.mm in Sources */, A93E83362121F0C8001FEBD4 /* MVKGPUCapture.mm in Sources */, @@ -1499,6 +1819,66 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + DCFD7F272A45BC6E007BBBF7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DCFD7F282A45BC6E007BBBF7 /* MVKBlockObserver.m in Sources */, + DCFD7F292A45BC6E007BBBF7 /* MTLRenderPipelineDescriptor+MoltenVK.m in Sources */, + DCFD7F2A2A45BC6E007BBBF7 /* MVKResource.mm in Sources */, + DCFD7F2B2A45BC6E007BBBF7 /* MVKDescriptorSet.mm in Sources */, + DCFD7F2C2A45BC6E007BBBF7 /* MVKVulkanAPIObject.mm in Sources */, + DCFD7F2D2A45BC6E007BBBF7 /* MTLTextureDescriptor+MoltenVK.m in Sources */, + DCFD7F2E2A45BC6E007BBBF7 /* MVKCommandResourceFactory.mm in Sources */, + DCFD7F2F2A45BC6E007BBBF7 /* MVKCommandEncodingPool.mm in Sources */, + DCFD7F302A45BC6E007BBBF7 /* MVKWatermark.mm in Sources */, + DCFD7F312A45BC6E007BBBF7 /* MVKBaseObject.mm in Sources */, + DCFD7F322A45BC6E007BBBF7 /* NSString+MoltenVK.mm in Sources */, + DCFD7F332A45BC6E007BBBF7 /* vulkan.mm in Sources */, + DCFD7F342A45BC6E007BBBF7 /* MTLRenderPassDepthAttachmentDescriptor+MoltenVK.m in Sources */, + DCFD7F352A45BC6E007BBBF7 /* MVKSurface.mm in Sources */, + DCFD7F362A45BC6E007BBBF7 /* MVKQueryPool.mm in Sources */, + DCFD7F372A45BC6E007BBBF7 /* MVKInstance.mm in Sources */, + DCFD7F382A45BC6E007BBBF7 /* MVKDeviceMemory.mm in Sources */, + DCFD7F392A45BC6E007BBBF7 /* MVKImage.mm in Sources */, + DCFD7F3A2A45BC6E007BBBF7 /* MVKCommandPool.mm in Sources */, + DCFD7F3B2A45BC6E007BBBF7 /* MVKCmdDraw.mm in Sources */, + DCFD7F3C2A45BC6E007BBBF7 /* MVKCommandBuffer.mm in Sources */, + DCFD7F3D2A45BC6E007BBBF7 /* MVKCmdRenderPass.mm in Sources */, + DCFD7F3E2A45BC6E007BBBF7 /* MVKBuffer.mm in Sources */, + DCFD7F3F2A45BC6E007BBBF7 /* MVKEnvironment.cpp in Sources */, + DCFD7F402A45BC6E007BBBF7 /* mvk_datatypes.mm in Sources */, + DCFD7F412A45BC6E007BBBF7 /* MVKExtensions.mm in Sources */, + DCFD7F422A45BC6E007BBBF7 /* MVKFoundation.cpp in Sources */, + DCFD7F432A45BC6E007BBBF7 /* MVKPixelFormats.mm in Sources */, + DCFD7F442A45BC6E007BBBF7 /* MVKDevice.mm in Sources */, + DCFD7F452A45BC6E007BBBF7 /* MTLRenderPassDescriptor+MoltenVK.m in Sources */, + DCFD7F462A45BC6E007BBBF7 /* MVKDescriptor.mm in Sources */, + DCFD7F472A45BC6E007BBBF7 /* MVKPipeline.mm in Sources */, + DCFD7F482A45BC6E007BBBF7 /* MVKQueue.mm in Sources */, + DCFD7F492A45BC6E007BBBF7 /* MTLSamplerDescriptor+MoltenVK.m in Sources */, + DCFD7F4A2A45BC6E007BBBF7 /* MVKRenderPass.mm in Sources */, + DCFD7F4B2A45BC6E007BBBF7 /* MVKCmdTransfer.mm in Sources */, + DCFD7F4C2A45BC6E007BBBF7 /* MVKCmdQueries.mm in Sources */, + DCFD7F4D2A45BC6E007BBBF7 /* mvk_api.mm in Sources */, + DCFD7F4E2A45BC6E007BBBF7 /* MVKSwapchain.mm in Sources */, + DCFD7F4F2A45BC6E007BBBF7 /* MVKCommandEncoderState.mm in Sources */, + DCFD7F502A45BC6E007BBBF7 /* MVKGPUCapture.mm in Sources */, + DCFD7F512A45BC6E007BBBF7 /* MVKOSExtensions.mm in Sources */, + DCFD7F522A45BC6E007BBBF7 /* MVKShaderModule.mm in Sources */, + DCFD7F532A45BC6E007BBBF7 /* MVKSync.mm in Sources */, + DCFD7F542A45BC6E007BBBF7 /* MVKCodec.mm in Sources */, + DCFD7F552A45BC6E007BBBF7 /* MVKCmdPipeline.mm in Sources */, + DCFD7F562A45BC6E007BBBF7 /* MVKLayers.mm in Sources */, + DCFD7F572A45BC6E007BBBF7 /* MVKFramebuffer.mm in Sources */, + DCFD7F582A45BC6E007BBBF7 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.m in Sources */, + DCFD7F592A45BC6E007BBBF7 /* MVKMTLBufferAllocation.mm in Sources */, + DCFD7F5A2A45BC6E007BBBF7 /* CAMetalLayer+MoltenVK.m in Sources */, + DCFD7F5B2A45BC6E007BBBF7 /* MVKCmdDispatch.mm in Sources */, + DCFD7F5C2A45BC6E007BBBF7 /* MVKCmdDebug.mm in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -1517,6 +1897,11 @@ name = MoltenVKShaderConverter; targetProxy = A9B1C7F4251AA5AF001D12CC /* PBXContainerItemProxy */; }; + DCA2CEAF2A45DFD400FB75B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "MoltenVKShaderConverter-xrOS"; + targetProxy = DCA2CEAE2A45DFD400FB75B6 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -1616,7 +2001,7 @@ "\"$(SRCROOT)/../External/cereal/include\"", "\"${BUILT_PRODUCTS_DIR}\"", ); - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACH_O_TYPE = staticlib; MACOSX_DEPLOYMENT_TARGET = 10.13; MTL_ENABLE_DEBUG_INFO = YES; @@ -1626,7 +2011,7 @@ PRELINK_LIBS = "${CONFIGURATION_BUILD_DIR}/libMoltenVKShaderConverter.a"; PRODUCT_NAME = MoltenVK; SKIP_INSTALL = YES; - TVOS_DEPLOYMENT_TARGET = 11.0; + TVOS_DEPLOYMENT_TARGET = 12.0; WARNING_CFLAGS = "-Wreorder"; }; name = Debug; @@ -1687,7 +2072,7 @@ "\"$(SRCROOT)/../External/cereal/include\"", "\"${BUILT_PRODUCTS_DIR}\"", ); - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACH_O_TYPE = staticlib; MACOSX_DEPLOYMENT_TARGET = 10.13; MTL_ENABLE_DEBUG_INFO = NO; @@ -1697,12 +2082,26 @@ PRELINK_LIBS = "${CONFIGURATION_BUILD_DIR}/libMoltenVKShaderConverter.a"; PRODUCT_NAME = MoltenVK; SKIP_INSTALL = YES; - TVOS_DEPLOYMENT_TARGET = 11.0; + TVOS_DEPLOYMENT_TARGET = 12.0; VALIDATE_PRODUCT = YES; WARNING_CFLAGS = "-Wreorder"; }; name = Release; }; + DCFD7F602A45BC6E007BBBF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + SDKROOT = xros; + }; + name = Debug; + }; + DCFD7F612A45BC6E007BBBF7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + SDKROOT = xros; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -1742,6 +2141,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + DCFD7F5F2A45BC6E007BBBF7 /* Build configuration list for PBXNativeTarget "MoltenVK-xrOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DCFD7F602A45BC6E007BBBF7 /* Debug */, + DCFD7F612A45BC6E007BBBF7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = A9F55D25198BE6A7004EC31B /* Project object */; diff --git a/MoltenVK/MoltenVK.xcodeproj/xcshareddata/xcschemes/MoltenVK-xrOS.xcscheme b/MoltenVK/MoltenVK.xcodeproj/xcshareddata/xcschemes/MoltenVK-xrOS.xcscheme new file mode 100644 index 000000000..e80fa8c3b --- /dev/null +++ b/MoltenVK/MoltenVK.xcodeproj/xcshareddata/xcschemes/MoltenVK-xrOS.xcscheme @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MoltenVK/MoltenVK/API/mvk_config.h b/MoltenVK/MoltenVK/API/mvk_config.h new file mode 100644 index 000000000..360007e16 --- /dev/null +++ b/MoltenVK/MoltenVK/API/mvk_config.h @@ -0,0 +1,1071 @@ +/* + * mvk_config.h + * + * Copyright (c) 2015-2023 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. + */ + + + +#ifndef __mvk_config_h_ +#define __mvk_config_h_ 1 + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#include + + +/** This header contains the public configuration API for MoltenVK. */ + + +/** + * The version number of MoltenVK is a single integer value, derived from the Major, Minor, + * and Patch version values, where each of the Major, Minor, and Patch components is allocated + * two decimal digits, in the format MjMnPt. This creates a version number that is both human + * readable and allows efficient computational comparisons to a single integer number. + * + * The following examples illustrate how the MoltenVK version number is built from its components: + * - 002000 (version 0.20.0) + * - 010000 (version 1.0.0) + * - 030104 (version 3.1.4) + * - 401215 (version 4.12.15) + */ +#define MVK_VERSION_MAJOR 1 +#define MVK_VERSION_MINOR 2 +#define MVK_VERSION_PATCH 5 + +#define MVK_MAKE_VERSION(major, minor, patch) (((major) * 10000) + ((minor) * 100) + (patch)) +#define MVK_VERSION MVK_MAKE_VERSION(MVK_VERSION_MAJOR, MVK_VERSION_MINOR, MVK_VERSION_PATCH) + + +#define MVK_CONFIGURATION_API_VERSION 37 + +/** Identifies the level of logging MoltenVK should be limited to outputting. */ +typedef enum MVKConfigLogLevel { + MVK_CONFIG_LOG_LEVEL_NONE = 0, /**< No logging. */ + MVK_CONFIG_LOG_LEVEL_ERROR = 1, /**< Log errors only. */ + MVK_CONFIG_LOG_LEVEL_WARNING = 2, /**< Log errors and warning messages. */ + MVK_CONFIG_LOG_LEVEL_INFO = 3, /**< Log errors, warnings and informational messages. */ + MVK_CONFIG_LOG_LEVEL_DEBUG = 4, /**< Log errors, warnings, infos and debug messages. */ + MVK_CONFIG_LOG_LEVEL_MAX_ENUM = 0x7FFFFFFF +} MVKConfigLogLevel; + +/** Identifies the level of Vulkan call trace logging MoltenVK should perform. */ +typedef enum MVKConfigTraceVulkanCalls { + MVK_CONFIG_TRACE_VULKAN_CALLS_NONE = 0, /**< No Vulkan call logging. */ + MVK_CONFIG_TRACE_VULKAN_CALLS_ENTER = 1, /**< Log the name of each Vulkan call when the call is entered. */ + MVK_CONFIG_TRACE_VULKAN_CALLS_ENTER_THREAD_ID = 2, /**< Log the name and thread ID of each Vulkan call when the call is entered. */ + MVK_CONFIG_TRACE_VULKAN_CALLS_ENTER_EXIT = 3, /**< Log the name of each Vulkan call when the call is entered and exited. This effectively brackets any other logging activity within the scope of the Vulkan call. */ + MVK_CONFIG_TRACE_VULKAN_CALLS_ENTER_EXIT_THREAD_ID = 4, /**< Log the name and thread ID of each Vulkan call when the call is entered and name when exited. This effectively brackets any other logging activity within the scope of the Vulkan call. */ + MVK_CONFIG_TRACE_VULKAN_CALLS_DURATION = 5, /**< Same as MVK_CONFIG_TRACE_VULKAN_CALLS_ENTER_EXIT, plus logs the time spent inside the Vulkan function. */ + MVK_CONFIG_TRACE_VULKAN_CALLS_DURATION_THREAD_ID = 6, /**< Same as MVK_CONFIG_TRACE_VULKAN_CALLS_ENTER_EXIT_THREAD_ID, plus logs the time spent inside the Vulkan function. */ + MVK_CONFIG_TRACE_VULKAN_CALLS_MAX_ENUM = 0x7FFFFFFF +} MVKConfigTraceVulkanCalls; + +/** Identifies the scope for Metal to run an automatic GPU capture for diagnostic debugging purposes. */ +typedef enum MVKConfigAutoGPUCaptureScope { + MVK_CONFIG_AUTO_GPU_CAPTURE_SCOPE_NONE = 0, /**< No automatic GPU capture. */ + MVK_CONFIG_AUTO_GPU_CAPTURE_SCOPE_DEVICE = 1, /**< Automatically capture all GPU activity during the lifetime of a VkDevice. */ + MVK_CONFIG_AUTO_GPU_CAPTURE_SCOPE_FRAME = 2, /**< Automatically capture all GPU activity during the rendering and presentation of the first frame. */ + MVK_CONFIG_AUTO_GPU_CAPTURE_SCOPE_MAX_ENUM = 0x7FFFFFFF +} MVKConfigAutoGPUCaptureScope; + +/** Identifies extensions to advertise as part of MoltenVK configuration. */ +typedef enum MVKConfigAdvertiseExtensionBits { + MVK_CONFIG_ADVERTISE_EXTENSIONS_ALL = 0x00000001, /**< All supported extensions. */ + MVK_CONFIG_ADVERTISE_EXTENSIONS_WSI = 0x00000002, /**< WSI extensions supported on the platform. */ + MVK_CONFIG_ADVERTISE_EXTENSIONS_PORTABILITY = 0x00000004, /**< Vulkan Portability Subset extensions. */ + MVK_CONFIG_ADVERTISE_EXTENSIONS_MAX_ENUM = 0x7FFFFFFF +} MVKConfigAdvertiseExtensionBits; +typedef VkFlags MVKConfigAdvertiseExtensions; + +/** Identifies the use of Metal Argument Buffers. */ +typedef enum MVKUseMetalArgumentBuffers { + MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS_NEVER = 0, /**< Don't use Metal Argument Buffers. */ + MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS_ALWAYS = 1, /**< Use Metal Argument Buffers for all pipelines. */ + MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS_DESCRIPTOR_INDEXING = 2, /**< Use Metal Argument Buffers only if VK_EXT_descriptor_indexing extension is enabled. */ + MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS_MAX_ENUM = 0x7FFFFFFF +} MVKUseMetalArgumentBuffers; + +/** Identifies the Metal functionality used to support Vulkan semaphore functionality (VkSemaphore). */ +typedef enum MVKVkSemaphoreSupportStyle { + MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_SINGLE_QUEUE = 0, /**< Limit Vulkan to a single queue, with no explicit semaphore synchronization, and use Metal's implicit guarantees that all operations submitted to a queue will give the same result as if they had been run in submission order. */ + MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_METAL_EVENTS_WHERE_SAFE = 1, /**< Use Metal events (MTLEvent) when available on the platform, and where safe. This will revert to same as MVK_CONFIG_VK_SEMAPHORE_USE_SINGLE_QUEUE on some NVIDIA GPUs and Rosetta2, due to potential challenges with MTLEvents on those platforms, or in older environments where MTLEvents are not supported. */ + MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_METAL_EVENTS = 2, /**< Always use Metal events (MTLEvent) when available on the platform. This will revert to same as MVK_CONFIG_VK_SEMAPHORE_USE_SINGLE_QUEUE in older environments where MTLEvents are not supported. */ + MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_CALLBACK = 3, /**< Use CPU callbacks upon GPU submission completion. This is the slowest technique, but allows multiple queues, compared to MVK_CONFIG_VK_SEMAPHORE_USE_SINGLE_QUEUE. */ + MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_MAX_ENUM = 0x7FFFFFFF +} MVKVkSemaphoreSupportStyle; + +/** Identifies the style of Metal command buffer pre-filling to be used. */ +typedef enum MVKPrefillMetalCommandBuffersStyle { + MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS_STYLE_NO_PREFILL = 0, /**< During Vulkan command buffer filling, do not prefill a Metal command buffer for each Vulkan command buffer. A single Metal command buffer is created and encoded for all the Vulkan command buffers included when vkQueueSubmit() is called. MoltenVK automatically creates and drains a single Metal object autorelease pool when vkQueueSubmit() is called. This is the fastest option, but potentially has the largest memory footprint. */ + MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS_STYLE_DEFERRED_ENCODING = 1, /**< During Vulkan command buffer filling, encode to the Metal command buffer when vkEndCommandBuffer() is called. MoltenVK automatically creates and drains a single Metal object autorelease pool when vkEndCommandBuffer() is called. This option has the fastest performance, and the largest memory footprint, of the prefilling options using autorelease pools. */ + MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS_STYLE_IMMEDIATE_ENCODING = 2, /**< During Vulkan command buffer filling, immediately encode to the Metal command buffer, as each command is submitted to the Vulkan command buffer, and do not retain any command content in the Vulkan command buffer. MoltenVK automatically creates and drains a Metal object autorelease pool for each and every command added to the Vulkan command buffer. This option has the smallest memory footprint, and the slowest performance, of the prefilling options using autorelease pools. */ + MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS_STYLE_IMMEDIATE_ENCODING_NO_AUTORELEASE = 3, /**< During Vulkan command buffer filling, immediately encode to the Metal command buffer, as each command is submitted to the Vulkan command buffer, do not retain any command content in the Vulkan command buffer, and assume the app will ensure that each thread that fills commands into a Vulkan command buffer has a Metal autorelease pool. MoltenVK will not create and drain any autorelease pools during encoding. This is the fastest prefilling option, and generally has a small memory footprint, depending on when the app-provided autorelease pool drains. */ + MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS_STYLE_MAX_ENUM = 0x7FFFFFFF +} MVKPrefillMetalCommandBuffersStyle; + +/** Identifies when Metal shaders will be compiled with the fast math option. */ +typedef enum MVKConfigFastMath { + MVK_CONFIG_FAST_MATH_NEVER = 0, /**< Metal shaders will never be compiled with the fast math option. */ + MVK_CONFIG_FAST_MATH_ALWAYS = 1, /**< Metal shaders will always be compiled with the fast math option. */ + MVK_CONFIG_FAST_MATH_ON_DEMAND = 2, /**< Metal shaders will be compiled with the fast math option, unless the shader includes execution modes that require it to be compiled without fast math. */ + MVK_CONFIG_FAST_MATH_MAX_ENUM = 0x7FFFFFFF +} MVKConfigFastMath; + +/** Identifies available system data compression algorithms. */ +typedef enum MVKConfigCompressionAlgorithm { + MVK_CONFIG_COMPRESSION_ALGORITHM_NONE = 0, /**< No compression. */ + MVK_CONFIG_COMPRESSION_ALGORITHM_LZFSE = 1, /**< Apple proprietary. Good balance of high performance and small compression size, particularly for larger data content. */ + MVK_CONFIG_COMPRESSION_ALGORITHM_ZLIB = 2, /**< Open cross-platform ZLib format. For smaller data content, has better performance and smaller size than LZFSE. */ + MVK_CONFIG_COMPRESSION_ALGORITHM_LZ4 = 3, /**< Fastest performance. Largest compression size. */ + MVK_CONFIG_COMPRESSION_ALGORITHM_LZMA = 4, /**< Slowest performance. Smallest compression size, particular with larger content. */ + MVK_CONFIG_COMPRESSION_ALGORITHM_MAX_ENUM = 0x7FFFFFFF, +} MVKConfigCompressionAlgorithm; + +/** Identifies the style of activity performance logging to use. */ +typedef enum MVKConfigActivityPerformanceLoggingStyle { + MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_FRAME_COUNT = 0, /**< Repeatedly log performance after a configured number of frames. */ + MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_IMMEDIATE = 1, /**< Log immediately after each performance measurement. */ + MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_DEVICE_LIFETIME = 2, /**< Log at the end of the VkDevice lifetime. This is useful for one-shot apps such as testing frameworks. */ + MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_MAX_ENUM = 0x7FFFFFFF, +} MVKConfigActivityPerformanceLoggingStyle; + +/** + * MoltenVK configuration settings. + * + * To be active, some configuration settings must be set before a VkDevice is created. + * See the description of the individual configuration structure members for more information. + * + * There are three mechanisms for setting the values of the MoltenVK configuration parameters: + * - Runtime API via the vkGetMoltenVKConfigurationMVK()/vkSetMoltenVKConfigurationMVK() functions. + * - Application runtime environment variables. + * - Build settings at MoltenVK build time. + * + * To change the MoltenVK configuration settings at runtime using a programmatic API, + * use the vkGetMoltenVKConfigurationMVK() and vkSetMoltenVKConfigurationMVK() functions + * to retrieve, modify, and set a copy of the MVKConfiguration structure. To be active, + * some configuration settings must be set before a VkInstance or VkDevice is created. + * See the description of each member for more information. + * + * The initial value of each of the configuration settings can established at runtime + * by a corresponding environment variable, or if the environment variable is not set, + * by a corresponding build setting at the time MoltenVK is compiled. The environment + * variable and build setting for each configuration parameter share the same name. + * + * For example, the initial value of the shaderConversionFlipVertexY configuration setting + * is set by the MVK_CONFIG_SHADER_CONVERSION_FLIP_VERTEX_Y at runtime, or by the + * MVK_CONFIG_SHADER_CONVERSION_FLIP_VERTEX_Y build setting when MoltenVK is compiled. + * + * This structure may be extended as new features are added to MoltenVK. If you are linking to + * an implementation of MoltenVK that was compiled from a different MVK_CONFIGURATION_API_VERSION + * than your app was, the size of this structure in your app may be larger or smaller than the + * struct in MoltenVK. See the description of the vkGetMoltenVKConfigurationMVK() and + * vkSetMoltenVKConfigurationMVK() functions for information about how to handle this. + * + * TO SUPPORT DYNAMIC LINKING TO THIS STRUCTURE AS DESCRIBED ABOVE, THIS STRUCTURE SHOULD NOT + * BE CHANGED EXCEPT TO ADD ADDITIONAL MEMBERS ON THE END. EXISTING MEMBERS, AND THEIR ORDER, + * SHOULD NOT BE CHANGED. + */ +typedef struct { + + /** + * If enabled, debugging capabilities will be enabled, including logging + * shader code during runtime shader conversion. + * + * The value of this parameter may be changed at any time during application runtime, + * and the changed value will immediately effect subsequent MoltenVK behaviour. + * + * The initial value or this parameter is set by the + * MVK_DEBUG + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, the value of this parameter is false if MoltenVK was + * built in Release mode, and true if MoltenVK was built in Debug mode. + */ + VkBool32 debugMode; + + /** + * If enabled, MSL vertex shader code created during runtime shader conversion will + * flip the Y-axis of each vertex, as the Vulkan Y-axis is the inverse of OpenGL. + * + * An alternate way to reverse the Y-axis is to employ a negative Y-axis value on + * the viewport, in which case this parameter can be disabled. + * + * The value of this parameter may be changed at any time during application runtime, + * and the changed value will immediately effect subsequent MoltenVK behaviour. + * Specifically, this parameter can be enabled when compiling some pipelines, + * and disabled when compiling others. Existing pipelines are not automatically + * re-compiled when this parameter is changed. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_SHADER_CONVERSION_FLIP_VERTEX_Y + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, the value of this parameter defaults to true. + */ + VkBool32 shaderConversionFlipVertexY; + + /** + * If enabled, queue command submissions (vkQueueSubmit() & vkQueuePresentKHR()) will be + * processed on the thread that called the submission function. If disabled, processing + * will be dispatched to a GCD dispatch_queue whose priority is determined by + * VkDeviceQueueCreateInfo::pQueuePriorities during vkCreateDevice(). + * + * The value of this parameter must be changed before creating a VkDevice, + * for the change to take effect. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_SYNCHRONOUS_QUEUE_SUBMITS + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, the value of this parameter defaults to true for macOS 10.14 + * and above or iOS 12 and above, and false otherwise. The reason for this distinction + * is that this feature should be disabled when emulation is required to support VkEvents + * because native support for events (MTLEvent) is not available. + */ + VkBool32 synchronousQueueSubmits; + + /** + * If set to MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS_STYLE_NO_PREFILL, a single Metal + * command buffer will be created and filled when the Vulkan command buffers are submitted + * to the Vulkan queue. This allows a single Metal command buffer to be used for all of the + * Vulkan command buffers in a queue submission. The Metal command buffer is filled on the + * thread that processes the command queue submission. + * + * If set to any value other than MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS_STYLE_NO_PREFILL, + * where possible, a Metal command buffer will be created and filled when each Vulkan + * command buffer is filled. For applications that parallelize the filling of Vulkan + * commmand buffers across multiple threads, this allows the Metal command buffers to also + * be filled on the same parallel thread. Because each command buffer is filled separately, + * this requires that each Vulkan command buffer have a dedicated Metal command buffer. + * + * See the definition of the MVKPrefillMetalCommandBuffersStyle enumeration above for + * descriptions of the various values that can be used for this setting. The differences + * are primarily distinguished by how memory recovery is handled for autoreleased Metal + * objects that are created under the covers as the commands added to the Vulkan command + * buffer are encoded into the corresponding Metal command buffer. You can decide whether + * your app will recover all autoreleased Metal objects, or how agressively MoltenVK should + * recover autoreleased Metal objects, based on your approach to command buffer filling. + * + * Depending on the nature of your application, you may find performance is improved by filling + * the Metal command buffers on parallel threads, or you may find that performance is improved by + * consolidating all Vulkan command buffers onto a single Metal command buffer during queue submission. + * + * When enabling this feature, be aware that one Metal command buffer is required for each Vulkan + * command buffer. Depending on the number of command buffers that you use, you may also need to + * change the value of the maxActiveMetalCommandBuffersPerQueue setting. + * + * If this feature is enabled, be aware that if you have recorded commands to a Vulkan command buffer, + * and then choose to reset that command buffer instead of submitting it, the corresponding prefilled + * Metal command buffer will still be submitted. This is because Metal command buffers do not support + * the concept of being reset after being filled. Depending on when and how often you do this, + * it may cause unexpected visual artifacts and unnecessary GPU load. + * + * Prefilling of a Metal command buffer will not occur during the filling of secondary command + * buffers (VK_COMMAND_BUFFER_LEVEL_SECONDARY), or for primary command buffers that are intended + * to be submitted to multiple queues concurrently (VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT). + * + * This feature is incompatible with updating descriptors after binding. If any of the + * *UpdateAfterBind feature flags of VkPhysicalDeviceDescriptorIndexingFeatures or + * VkPhysicalDeviceInlineUniformBlockFeatures have been enabled, the value of this + * setting will be ignored and treated as if it is false. + * + * The value of this parameter may be changed at any time during application runtime, + * and the changed value will immediately effect subsequent MoltenVK behaviour. + * Specifically, this parameter can be enabled when filling some command buffers, + * and disabled when later filling others. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, the value of this parameter defaults to + * MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS_STYLE_NO_PREFILL. + */ + MVKPrefillMetalCommandBuffersStyle prefillMetalCommandBuffers; + + /** + * The maximum number of Metal command buffers that can be concurrently active per Vulkan queue. + * The number of active Metal command buffers required depends on the prefillMetalCommandBuffers + * setting. If prefillMetalCommandBuffers is enabled, one Metal command buffer is required per + * Vulkan command buffer. If prefillMetalCommandBuffers is disabled, one Metal command buffer + * is required per command buffer queue submission, which may be significantly less than the + * number of Vulkan command buffers. + * + * The value of this parameter must be changed before creating a VkDevice, + * for the change to take effect. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_MAX_ACTIVE_METAL_COMMAND_BUFFERS_PER_QUEUE + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, the value of this parameter defaults to 64. + */ + uint32_t maxActiveMetalCommandBuffersPerQueue; + + /** + * Depending on the GPU, Metal allows 8192 or 32768 occlusion queries per MTLBuffer. + * If enabled, MoltenVK allocates a MTLBuffer for each query pool, allowing each query + * pool to support that permitted number of queries. This may slow performance or cause + * unexpected behaviour if the query pool is not established prior to a Metal renderpass, + * or if the query pool is changed within a renderpass. If disabled, one MTLBuffer will + * be shared by all query pools, which improves performance, but limits the total device + * queries to the permitted number. + * + * The value of this parameter may be changed at any time during application runtime, + * and the changed value will immediately effect subsequent MoltenVK behaviour. + * Specifically, this parameter can be enabled when creating some query pools, + * and disabled when creating others. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_SUPPORT_LARGE_QUERY_POOLS + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, the value of this parameter defaults to true. + */ + VkBool32 supportLargeQueryPools; + + /** Obsolete, ignored, and deprecated. All surface presentations are performed with a command buffer. */ + VkBool32 presentWithCommandBuffer; + + /** + * If enabled, swapchain images will use simple Nearest sampling when minifying or magnifying + * the swapchain image to fit a physical display surface. If disabled, swapchain images will + * use Linear sampling when magnifying the swapchain image to fit a physical display surface. + * Enabling this setting avoids smearing effects when swapchain images are simple interger + * multiples of display pixels (eg- macOS Retina, and typical of graphics apps and games), + * but may cause aliasing effects when using non-integer display scaling. + * + * The value of this parameter must be changed before creating a VkSwapchain, + * for the change to take effect. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_SWAPCHAIN_MIN_MAG_FILTER_USE_NEAREST + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, the value of this parameter defaults to true. + */ + VkBool32 swapchainMinMagFilterUseNearest; +#define swapchainMagFilterUseNearest swapchainMinMagFilterUseNearest + + /** + * The maximum amount of time, in nanoseconds, to wait for a Metal library, function, or + * pipeline state object to be compiled and created by the Metal compiler. An internal error + * within the Metal compiler can stall the thread for up to 30 seconds. Setting this value + * limits that delay to a specified amount of time, allowing shader compilations to fail fast. + * + * The value of this parameter may be changed at any time during application runtime, + * and the changed value will immediately effect subsequent MoltenVK behaviour. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_METAL_COMPILE_TIMEOUT + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, the value of this parameter defaults to infinite. + */ + uint64_t metalCompileTimeout; + + /** + * If enabled, performance statistics, as defined by the MVKPerformanceStatistics structure, + * are collected, and can be retrieved via the vkGetPerformanceStatisticsMVK() function. + * + * You can also use the activityPerformanceLoggingStyle and performanceLoggingFrameCount + * parameters to configure when to log the performance statistics collected by this parameter. + * + * The value of this parameter must be changed before creating a VkDevice, + * for the change to take effect. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_PERFORMANCE_TRACKING + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, the value of this parameter defaults to false. + */ + VkBool32 performanceTracking; + + /** + * If non-zero, performance statistics, frame-based statistics will be logged, on a + * repeating cycle, once per this many frames. The performanceTracking parameter must + * also be enabled. If this parameter is zero, or the performanceTracking parameter + * is disabled, no frame-based performance statistics will be logged. + * + * The value of this parameter may be changed at any time during application runtime, + * and the changed value will immediately effect subsequent MoltenVK behaviour. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_PERFORMANCE_LOGGING_FRAME_COUNT + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, the value of this parameter defaults to zero. + */ + uint32_t performanceLoggingFrameCount; + + /** + * If enabled, a MoltenVK logo watermark will be rendered on top of the scene. + * This can be enabled for publicity during demos. + * + * The value of this parameter may be changed at any time during application runtime, + * and the changed value will immediately effect subsequent MoltenVK behaviour. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_DISPLAY_WATERMARK + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, the value of this parameter defaults to false. + */ + VkBool32 displayWatermark; + + /** + * Metal does not distinguish functionality between queues, which would normally mean only + * a single general-purpose queue family with multiple queues is needed. However, Vulkan + * associates command buffers with a queue family, whereas Metal associates command buffers + * with a specific Metal queue. In order to allow a Metal command buffer to be prefilled + * before is is formally submitted to a Vulkan queue, each Vulkan queue family can support + * only a single Metal queue. As a result, in order to provide parallel queue operations, + * MoltenVK provides multiple queue families, each with a single queue. + * + * If this parameter is disabled, all queue families will be advertised as having general-purpose + * graphics + compute + transfer functionality, which is how the actual Metal queues behave. + * + * If this parameter is enabled, one queue family will be advertised as having general-purpose + * graphics + compute + transfer functionality, and the remaining queue families will be advertised + * as having specialized graphics OR compute OR transfer functionality, to make it easier for some + * apps to select a queue family with the appropriate requirements. + * + * The value of this parameter must be changed before creating a VkDevice, and before + * querying a VkPhysicalDevice for queue family properties, for the change to take effect. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_SPECIALIZED_QUEUE_FAMILIES + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, the value of this parameter defaults to false. + */ + VkBool32 specializedQueueFamilies; + + /** + * If enabled, when the app creates a VkDevice from a VkPhysicalDevice (GPU) that is neither + * headless nor low-power, and is different than the GPU used by the windowing system, the + * windowing system will be forced to switch to use the GPU selected by the Vulkan app. + * When the Vulkan app is ended, the windowing system will automatically switch back to + * using the previous GPU, depending on the usage requirements of other running apps. + * + * If disabled, the Vulkan app will render using its selected GPU, and if the windowing + * system uses a different GPU, the windowing system compositor will automatically copy + * framebuffer content from the app GPU to the windowing system GPU. + * + * The value of this parmeter has no effect on systems with a single GPU, or when the + * Vulkan app creates a VkDevice from a low-power or headless VkPhysicalDevice (GPU). + * + * Switching the windowing system GPU to match the Vulkan app GPU maximizes app performance, + * because it avoids the windowing system compositor from having to copy framebuffer content + * between GPUs on each rendered frame. However, doing so forces the entire system to + * potentially switch to using a GPU that may consume more power while the app is running. + * + * Some Vulkan apps may want to render using a high-power GPU, but leave it up to the + * system window compositor to determine how best to blend content with the windowing + * system, and as a result, may want to disable this parameter. + * + * The value of this parameter must be changed before creating a VkDevice, + * for the change to take effect. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_SWITCH_SYSTEM_GPU + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, the value of this parameter defaults to true. + */ + VkBool32 switchSystemGPU; + + /** + * Older versions of Metal do not natively support per-texture swizzling. When running on + * such a system, and this parameter is enabled, arbitrary VkImageView component swizzles + * are supported, as defined in VkImageViewCreateInfo::components when creating a VkImageView. + * + * If disabled, and native Metal per-texture swizzling is not available on the platform, + * a very limited set of VkImageView component swizzles are supported via format substitutions. + * + * If Metal supports native per-texture swizzling, this parameter is ignored. + * + * When running on an older version of Metal that does not support native per-texture + * swizzling, if this parameter is enabled, both when a VkImageView is created, and + * when any pipeline that uses that VkImageView is compiled, VkImageView swizzling is + * automatically performed in the converted Metal shader code during all texture sampling + * and reading operations, regardless of whether a swizzle is required for the VkImageView + * associated with the Metal texture. This may result in reduced performance. + * + * The value of this parameter may be changed at any time during application runtime, + * and the changed value will immediately effect subsequent MoltenVK behaviour. + * Specifically, this parameter can be enabled when creating VkImageViews that need it, + * and compiling pipelines that use those VkImageViews, and can be disabled when creating + * VkImageViews that don't need it, and compiling pipelines that use those VkImageViews. + * + * Existing pipelines are not automatically re-compiled when this parameter is changed. + * + * An error is logged and returned during VkImageView creation if that VkImageView + * requires full image view swizzling and this feature is not enabled. An error is + * also logged when a pipeline that was not compiled with full image view swizzling + * is presented with a VkImageView that is expecting it. + * + * An error is also retuned and logged when a VkPhysicalDeviceImageFormatInfo2KHR is passed + * in a call to vkGetPhysicalDeviceImageFormatProperties2KHR() to query for an VkImageView + * format that will require full swizzling to be enabled, and this feature is not enabled. + * + * If this parameter is disabled, and native Metal per-texture swizzling is not available + * on the platform, the following limited set of VkImageView swizzles are supported by + * MoltenVK, via automatic format substitution: + * + * Texture format Swizzle + * -------------- ------- + * VK_FORMAT_R8_UNORM ZERO, ANY, ANY, RED + * VK_FORMAT_A8_UNORM ALPHA, ANY, ANY, ZERO + * VK_FORMAT_R8G8B8A8_UNORM BLUE, GREEN, RED, ALPHA + * VK_FORMAT_R8G8B8A8_SRGB BLUE, GREEN, RED, ALPHA + * VK_FORMAT_B8G8R8A8_UNORM BLUE, GREEN, RED, ALPHA + * VK_FORMAT_B8G8R8A8_SRGB BLUE, GREEN, RED, ALPHA + * VK_FORMAT_D32_SFLOAT_S8_UINT RED, ANY, ANY, ANY (stencil only) + * VK_FORMAT_D24_UNORM_S8_UINT RED, ANY, ANY, ANY (stencil only) + * + * The initial value or this parameter is set by the + * MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, the value of this parameter defaults to false. + */ + VkBool32 fullImageViewSwizzle; + + /** + * The index of the queue family whose presentation submissions will + * be used as the default GPU Capture Scope during debugging in Xcode. + * + * The value of this parameter must be changed before creating a VkDevice, + * for the change to take effect. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_DEFAULT_GPU_CAPTURE_SCOPE_QUEUE_FAMILY_INDEX + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, the value of this parameter defaults to zero (the first queue family). + */ + uint32_t defaultGPUCaptureScopeQueueFamilyIndex; + + /** + * The index of the queue, within the queue family identified by the + * defaultGPUCaptureScopeQueueFamilyIndex parameter, whose presentation submissions + * will be used as the default GPU Capture Scope during debugging in Xcode. + * + * The value of this parameter must be changed before creating a VkDevice, + * for the change to take effect. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_DEFAULT_GPU_CAPTURE_SCOPE_QUEUE_INDEX + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, the value of this parameter defaults to zero (the first queue). + */ + uint32_t defaultGPUCaptureScopeQueueIndex; + + /** + * Identifies when Metal shaders will be compiled with the Metal fastMathEnabled property + * enabled. For shaders compiled with the Metal fastMathEnabled property enabled, shader + * floating point math is significantly faster, but it may cause the Metal Compiler to + * optimize floating point operations in ways that may violate the IEEE 754 standard. + * + * Enabling Metal fast math can dramatically improve shader performance, and has little + * practical effect on the numerical accuracy of most shaders. As such, disabling fast + * math should be done carefully and deliberately. For most applications, always enabling + * fast math, by setting the value of this property to MVK_CONFIG_FAST_MATH_ALWAYS, + * is the preferred choice. + * + * Apps that have specific accuracy and handling needs for particular shaders, may elect to + * set the value of this property to MVK_CONFIG_FAST_MATH_ON_DEMAND, so that fast math will + * be disabled when compiling shaders that request capabilities such as SignedZeroInfNanPreserve. + * + * The value of this parameter may be changed at any time during application runtime, + * and the changed value will be applied to future Metal shader compilations. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_FAST_MATH_ENABLED + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, the value of this parameter defaults to MVK_CONFIG_FAST_MATH_ALWAYS. + */ + MVKConfigFastMath fastMathEnabled; + + /** + * Controls the level of logging performned by MoltenVK. + * + * The value of this parameter may be changed at any time during application runtime, + * and the changed value will immediately effect subsequent MoltenVK behaviour. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_LOG_LEVEL + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, errors and informational messages are logged. + */ + MVKConfigLogLevel logLevel; + + /** + * Causes MoltenVK to log the name of each Vulkan call made by the application, + * along with the Mach thread ID, global system thread ID, and thread name. + * + * The value of this parameter may be changed at any time during application runtime, + * and the changed value will immediately effect subsequent MoltenVK behaviour. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_TRACE_VULKAN_CALLS + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, no Vulkan call logging will occur. + */ + MVKConfigTraceVulkanCalls traceVulkanCalls; + + /** + * Force MoltenVK to use a low-power GPU, if one is availble on the device. + * + * The value of this parameter must be changed before creating a VkInstance, + * for the change to take effect. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_FORCE_LOW_POWER_GPU + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, this setting is disabled by default, allowing both + * low-power and high-power GPU's to be used. + */ + VkBool32 forceLowPowerGPU; + + /** Deprecated. Vulkan sempphores using MTLFence are no longer supported. Use semaphoreSupportStyle instead. */ + VkBool32 semaphoreUseMTLFence; + + /** + * Determines the style used to implement Vulkan semaphore (VkSemaphore) functionality in Metal. + * See the documentation of the MVKVkSemaphoreSupportStyle for the options. + * + * In the special case of VK_SEMAPHORE_TYPE_TIMELINE semaphores, MoltenVK will always use + * MTLSharedEvent if it is available on the platform, regardless of the value of this parameter. + * + * The value of this parameter must be changed before creating a VkInstance, + * for the change to take effect. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, this setting is set to + * MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_METAL_EVENTS_WHERE_SAFE by default, + * and MoltenVK will use MTLEvent, except on NVIDIA GPU and Rosetta2 environments, + * or where MTLEvents are not supported, where it will use a single queue with + * implicit synchronization (as if this parameter was set to + * MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_SINGLE_QUEUE). + * + * This parameter interacts with the deprecated legacy parameters semaphoreUseMTLEvent + * and semaphoreUseMTLFence. If semaphoreUseMTLEvent is enabled, this parameter will be + * set to MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_METAL_EVENTS_WHERE_SAFE. + * If semaphoreUseMTLEvent is disabled, this parameter will be set to + * MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_SINGLE_QUEUE if semaphoreUseMTLFence is enabled, + * or MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_CALLBACK if semaphoreUseMTLFence is disabled. + * Structurally, this parameter replaces, and is aliased by, semaphoreUseMTLEvent. + */ + MVKVkSemaphoreSupportStyle semaphoreSupportStyle; +#define semaphoreUseMTLEvent semaphoreSupportStyle + + /** + * Controls whether Metal should run an automatic GPU capture without the user having to + * trigger it manually via the Xcode user interface, and controls the scope under which + * that GPU capture will occur. This is useful when trying to capture a one-shot GPU trace, + * such as when running a Vulkan CTS test case. For the automatic GPU capture to occur, the + * Xcode scheme under which the app is run must have the Metal GPU capture option enabled. + * This parameter should not be set to manually trigger a GPU capture via the Xcode user interface. + * + * When the value of this parameter is MVK_CONFIG_AUTO_GPU_CAPTURE_SCOPE_FRAME, + * the queue for which the GPU activity is captured is identifed by the values of + * the defaultGPUCaptureScopeQueueFamilyIndex and defaultGPUCaptureScopeQueueIndex + * configuration parameters. + * + * The value of this parameter must be changed before creating a VkDevice, + * for the change to take effect. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_AUTO_GPU_CAPTURE_SCOPE + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, no automatic GPU capture will occur. + */ + MVKConfigAutoGPUCaptureScope autoGPUCaptureScope; + + /** + * The path to a file where the automatic GPU capture should be saved, if autoGPUCaptureScope + * is enabled. In this case, the Xcode scheme need not have Metal GPU capture enabled, and in + * fact the app need not be run under Xcode's control at all. This is useful in case the app + * cannot be run under Xcode's control. A path starting with '~' can be used to place it in a + * user's home directory, as in the shell. This feature requires Metal 3.0 (macOS 10.15, iOS 13). + * + * If this parameter is NULL or an empty string, and autoGPUCaptureScope is enabled, automatic + * GPU capture will be handled by the Xcode user interface. + * + * The value of this parameter must be changed before creating a VkDevice, + * for the change to take effect. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_AUTO_GPU_CAPTURE_OUTPUT_FILE + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, automatic GPU capture will be handled by the Xcode user interface. + */ + const char* autoGPUCaptureOutputFilepath; + + /** + * Controls whether MoltenVK should use a Metal 2D texture with a height of 1 for a + * Vulkan 1D image, or use a native Metal 1D texture. Metal imposes significant restrictions + * on native 1D textures, including not being renderable, clearable, or permitting mipmaps. + * Using a Metal 2D texture allows Vulkan 1D textures to support this additional functionality. + * + * The value of this parameter should only be changed before creating the VkInstance. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_TEXTURE_1D_AS_2D + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, this setting is enabled by default, and MoltenVK will + * use a Metal 2D texture for each Vulkan 1D image. + */ + VkBool32 texture1DAs2D; + + /** + * Controls whether MoltenVK should preallocate memory in each VkDescriptorPool according + * to the values of the VkDescriptorPoolSize parameters. Doing so may improve descriptor set + * allocation performance and memory stability at a cost of preallocated application memory. + * If this setting is disabled, the descriptors required for a descriptor set will be individually + * dynamically allocated in application memory when the descriptor set itself is allocated. + * + * The value of this parameter may be changed at any time during application runtime, and the + * changed value will affect the behavior of VkDescriptorPools created after the value is changed. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_PREALLOCATE_DESCRIPTORS + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, this setting is enabled by default, and MoltenVK will + * allocate a pool of descriptors when a VkDescriptorPool is created. + */ + VkBool32 preallocateDescriptors; + + /** + * Controls whether MoltenVK should use pools to manage memory used when adding commands + * to command buffers. If this setting is enabled, MoltenVK will use a pool to hold command + * resources for reuse during command execution. If this setting is disabled, command memory + * is allocated and destroyed each time a command is executed. This is a classic time-space + * trade off. When command pooling is active, the memory in the pool can be cleared via a + * call to the vkTrimCommandPoolKHR() command. + * + * The value of this parameter may be changed at any time during application runtime, + * and the changed value will immediately effect behavior of VkCommandPools created + * after the setting is changed. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_USE_COMMAND_POOLING + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, this setting is enabled by default, and MoltenVK will pool command memory. + */ + VkBool32 useCommandPooling; + + /** + * Controls whether MoltenVK should use MTLHeaps for allocating textures and buffers + * from device memory. If this setting is enabled, and placement MTLHeaps are + * available on the platform, MoltenVK will allocate a placement MTLHeap for each VkDeviceMemory + * instance, and allocate textures and buffers from that placement heap. If this environment + * variable is disabled, MoltenVK will allocate textures and buffers from general device memory. + * + * Apple recommends that MTLHeaps should only be used for specific requirements such as aliasing + * or hazard tracking, and MoltenVK testing has shown that allocating multiple textures of + * different types or usages from one MTLHeap can occassionally cause corruption issues under + * certain circumstances. + * + * The value of this parameter must be changed before creating a VkInstance, + * for the change to take effect. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_USE_MTLHEAP + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, this setting is disabled by default, and MoltenVK + * will allocate texures and buffers from general device memory. + */ + VkBool32 useMTLHeap; + + /** + * Controls when MoltenVK should log activity performance events. + * + * The value of this parameter must be changed before creating a VkDevice, + * for the change to take effect. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, this setting is set to + * MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_FRAME_COUNT by default, + * and activity performance will be logged when frame activity is logged. + */ + MVKConfigActivityPerformanceLoggingStyle activityPerformanceLoggingStyle; +#define logActivityPerformanceInline activityPerformanceLoggingStyle + + /** + * Controls the Vulkan API version that MoltenVK should advertise in vkEnumerateInstanceVersion(). + * When reading this value, it will be one of the VK_API_VERSION_1_* values, including the latest + * VK_HEADER_VERSION component. When setting this value, it should be set to one of: + * + * VK_API_VERSION_1_2 (equivalent decimal number 4202496) + * VK_API_VERSION_1_1 (equivalent decimal number 4198400) + * VK_API_VERSION_1_0 (equivalent decimal number 4194304) + * + * MoltenVK will automatically add the VK_HEADER_VERSION component. + * + * The value of this parameter must be changed before creating a VkInstance, + * for the change to take effect. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_API_VERSION_TO_ADVERTISE + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, the value of this parameter defaults to the highest API version + * currently supported by MoltenVK, including the latest VK_HEADER_VERSION component. + */ + uint32_t apiVersionToAdvertise; + + /** + * Controls which extensions MoltenVK should advertise it supports in + * vkEnumerateInstanceExtensionProperties() and vkEnumerateDeviceExtensionProperties(). + * The value of this parameter is a bitwise OR of values from the MVKConfigAdvertiseExtensionBits + * enumeration. Any prerequisite extensions are also advertised. + * If the flag MVK_CONFIG_ADVERTISE_EXTENSIONS_ALL is included, all supported extensions + * will be advertised. A value of zero means no extensions will be advertised. + * + * The value of this parameter must be changed before creating a VkInstance, + * for the change to take effect. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_ADVERTISE_EXTENSIONS + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, the value of this setting defaults to + * MVK_CONFIG_ADVERTISE_EXTENSIONS_ALL, and all supported extensions will be advertised. + */ + MVKConfigAdvertiseExtensions advertiseExtensions; + + /** + * Controls whether MoltenVK should treat a lost VkDevice as resumable, unless the + * corresponding VkPhysicalDevice has also been lost. The VK_ERROR_DEVICE_LOST error has + * a broad definitional range, and can mean anything from a GPU hiccup on the current + * command buffer submission, to a physically removed GPU. In the case where this error does + * not impact the VkPhysicalDevice, Vulkan requires that the app destroy and re-create a new + * VkDevice. However, not all apps (including CTS) respect that requirement, leading to what + * might be a transient command submission failure causing an unexpected catastrophic app failure. + * + * If this setting is enabled, in the case of a VK_ERROR_DEVICE_LOST error that does NOT impact + * the VkPhysicalDevice, MoltenVK will log the error, but will not mark the VkDevice as lost, + * allowing the VkDevice to continue to be used. If this setting is disabled, MoltenVK will + * mark the VkDevice as lost, and subsequent use of that VkDevice will be reduced or prohibited. + * + * The value of this parameter may be changed at any time during application runtime, + * and the changed value will affect the error behavior of subsequent command submissions. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_RESUME_LOST_DEVICE + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, this setting is disabled by default, and MoltenVK + * will mark the VkDevice as lost when a command submission failure occurs. + */ + VkBool32 resumeLostDevice; + + /** + * Controls whether MoltenVK should use Metal argument buffers for resources defined in + * descriptor sets, if Metal argument buffers are supported on the platform. Using Metal + * argument buffers dramatically increases the number of buffers, textures and samplers + * that can be bound to a pipeline shader, and in most cases improves performance. + * This setting is an enumeration that specifies the conditions under which MoltenVK + * will use Metal argument buffers. + * + * NOTE: Currently, Metal argument buffer support is in beta stage, and is only supported + * on macOS 11.0 (Big Sur) or later, or on older versions of macOS using an Intel GPU. + * Metal argument buffers support is not available on iOS. Development to support iOS + * and a wider combination of GPU's on older macOS versions is under way. + * + * The value of this parameter must be changed before creating a VkDevice, + * for the change to take effect. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, this setting is set to + * MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS_NEVER by default, + * and MoltenVK will not use Metal argument buffers. + */ + MVKUseMetalArgumentBuffers useMetalArgumentBuffers; + + /** + * Controls the type of compression to use on the MSL source code that is stored in memory + * for use in a pipeline cache. After being converted from SPIR-V, or loaded directly into + * a VkShaderModule, and then compiled into a MTLLibrary, the MSL source code is no longer + * needed for operation, but it is retained so it can be written out as part of a pipeline + * cache export. When a large number of shaders are loaded, this can consume significant + * memory. In such a case, this parameter can be used to compress the MSL source code that + * is awaiting export as part of a pipeline cache. + * + * Pipeline cache compression is available for macOS 10.15 and above, and iOS/tvOS 13.0 and above. + * + * The value of this parameter can be changed at any time, and will affect the size of + * the cached MSL from subsequent shader compilations. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_SHADER_COMPRESSION_ALGORITHM + * runtime environment variable or MoltenVK compile-time build setting. + * If neither is set, this setting is set to + * MVK_CONFIG_COMPRESSION_ALGORITHM_NONE by default, + * and MoltenVK will not compress the MSL source code after compilation into a MTLLibrary. + */ + MVKConfigCompressionAlgorithm shaderSourceCompressionAlgorithm; + + /** + * Maximize the concurrent executing compilation tasks. + * + * The initial value or this parameter is set by the + * MVK_CONFIG_SHOULD_MAXIMIZE_CONCURRENT_COMPILATION + * runtime environment variable or MoltenVK compile-time build setting. + * This setting requires macOS 13.3 & is disabled by default. + */ + VkBool32 shouldMaximizeConcurrentCompilation; + +} MVKConfiguration; + + + +#pragma mark - +#pragma mark Function types + + typedef VkResult (VKAPI_PTR *PFN_vkGetMoltenVKConfigurationMVK)(VkInstance ignored, MVKConfiguration* pConfiguration, size_t* pConfigurationSize); + typedef VkResult (VKAPI_PTR *PFN_vkSetMoltenVKConfigurationMVK)(VkInstance ignored, const MVKConfiguration* pConfiguration, size_t* pConfigurationSize); + + +#pragma mark - +#pragma mark Function prototypes + +#ifndef VK_NO_PROTOTYPES + +/** + * Populates the pConfiguration structure with the current MoltenVK configuration settings. + * + * To change a specific configuration value, call vkGetMoltenVKConfigurationMVK() to retrieve + * the current configuration, make changes, and call vkSetMoltenVKConfigurationMVK() to + * update all of the values. + * + * The VkInstance object you provide here is ignored, and a VK_NULL_HANDLE value can be provided. + * This function can be called before the VkInstance has been created. It is safe to call this function + * with a VkInstance retrieved from a different layer in the Vulkan SDK Loader and Layers framework. + * + * To be active, some configuration settings must be set before a VkInstance or VkDevice + * is created. See the description of the MVKConfiguration members for more information. + * + * If you are linking to an implementation of MoltenVK that was compiled from a different + * MVK_CONFIGURATION_API_VERSION than your app was, the size of the MVKConfiguration structure + * in your app may be larger or smaller than the same struct as expected by MoltenVK. + * + * When calling this function, set the value of *pConfigurationSize to sizeof(MVKConfiguration), + * to tell MoltenVK the limit of the size of your MVKConfiguration structure. Upon return from + * this function, the value of *pConfigurationSize will hold the actual number of bytes copied + * into your passed MVKConfiguration structure, which will be the smaller of what your app + * thinks is the size of MVKConfiguration, and what MoltenVK thinks it is. This represents the + * safe access area within the structure for both MoltenVK and your app. + * + * If the size that MoltenVK expects for MVKConfiguration is different than the value passed in + * *pConfigurationSize, this function will return VK_INCOMPLETE, otherwise it will return VK_SUCCESS. + * + * Although it is not necessary, you can use this function to determine in advance the value + * that MoltenVK expects the size of MVKConfiguration to be by setting the value of pConfiguration + * to NULL. In that case, this function will set *pConfigurationSize to the size that MoltenVK + * expects MVKConfiguration to be. + */ +VKAPI_ATTR VkResult VKAPI_CALL vkGetMoltenVKConfigurationMVK( + VkInstance ignored, + MVKConfiguration* pConfiguration, + size_t* pConfigurationSize); + +/** + * Sets the MoltenVK configuration settings to those found in the pConfiguration structure. + * + * To change a specific configuration value, call vkGetMoltenVKConfigurationMVK() + * to retrieve the current configuration, make changes, and call + * vkSetMoltenVKConfigurationMVK() to update all of the values. + * + * The VkInstance object you provide here is ignored, and a VK_NULL_HANDLE value can be provided. + * This function can be called before the VkInstance has been created. It is safe to call this function + * with a VkInstance retrieved from a different layer in the Vulkan SDK Loader and Layers framework. + * + * To be active, some configuration settings must be set before a VkInstance or VkDevice + * is created. See the description of the MVKConfiguration members for more information. + * + * If you are linking to an implementation of MoltenVK that was compiled from a different + * MVK_CONFIGURATION_API_VERSION than your app was, the size of the MVKConfiguration structure + * in your app may be larger or smaller than the same struct as expected by MoltenVK. + * + * When calling this function, set the value of *pConfigurationSize to sizeof(MVKConfiguration), + * to tell MoltenVK the limit of the size of your MVKConfiguration structure. Upon return from + * this function, the value of *pConfigurationSize will hold the actual number of bytes copied + * out of your passed MVKConfiguration structure, which will be the smaller of what your app + * thinks is the size of MVKConfiguration, and what MoltenVK thinks it is. This represents the + * safe access area within the structure for both MoltenVK and your app. + * + * If the size that MoltenVK expects for MVKConfiguration is different than the value passed in + * *pConfigurationSize, this function will return VK_INCOMPLETE, otherwise it will return VK_SUCCESS. + * + * Although it is not necessary, you can use this function to determine in advance the value + * that MoltenVK expects the size of MVKConfiguration to be by setting the value of pConfiguration + * to NULL. In that case, this function will set *pConfigurationSize to the size that MoltenVK + * expects MVKConfiguration to be. + */ +VKAPI_ATTR VkResult VKAPI_CALL vkSetMoltenVKConfigurationMVK( + VkInstance ignored, + const MVKConfiguration* pConfiguration, + size_t* pConfigurationSize); + + +#pragma mark - +#pragma mark Shaders + + /** + * NOTE: Shader code should be submitted as SPIR-V. Although some simple direct MSL shaders may work, + * direct loading of MSL source code or compiled MSL code is not officially supported at this time. + * Future versions of MoltenVK may support direct MSL submission again. + * + * Enumerates the magic number values to set in the MVKMSLSPIRVHeader when + * submitting a SPIR-V stream that contains either Metal Shading Language source + * code or Metal Shading Language compiled binary code in place of SPIR-V code. + */ + typedef enum { + kMVKMagicNumberSPIRVCode = 0x07230203, /**< SPIR-V stream contains standard SPIR-V code. */ + kMVKMagicNumberMSLSourceCode = 0x19960412, /**< SPIR-V stream contains Metal Shading Language source code. */ + kMVKMagicNumberMSLCompiledCode = 0x19981215, /**< SPIR-V stream contains Metal Shading Language compiled binary code. */ + } MVKMSLMagicNumber; + + /** + * NOTE: Shader code should be submitted as SPIR-V. Although some simple direct MSL shaders may work, + * direct loading of MSL source code or compiled MSL code is not officially supported at this time. + * Future versions of MoltenVK may support direct MSL submission again. + * + * Describes the header at the start of an SPIR-V stream, when it contains either + * Metal Shading Language source code or Metal Shading Language compiled binary code. + * + * To submit MSL source code to the vkCreateShaderModule() function in place of SPIR-V + * code, prepend a MVKMSLSPIRVHeader containing the kMVKMagicNumberMSLSourceCode magic + * number to the MSL source code. The MSL source code must be null-terminated. + * + * To submit MSL compiled binary code to the vkCreateShaderModule() function in place of + * SPIR-V code, prepend a MVKMSLSPIRVHeader containing the kMVKMagicNumberMSLCompiledCode + * magic number to the MSL compiled binary code. + * + * In both cases, the pCode element of VkShaderModuleCreateInfo should pointer to the + * location of the MVKMSLSPIRVHeader, and the MSL code should start at the byte immediately + * after the MVKMSLSPIRVHeader. + * + * The codeSize element of VkShaderModuleCreateInfo should be set to the entire size of + * the submitted code memory, including the additional sizeof(MVKMSLSPIRVHeader) bytes + * taken up by the MVKMSLSPIRVHeader, and, in the case of MSL source code, including + * the null-terminator byte. + */ + typedef uint32_t MVKMSLSPIRVHeader; + + +#endif // VK_NO_PROTOTYPES + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif diff --git a/MoltenVK/MoltenVK/API/mvk_datatypes.h b/MoltenVK/MoltenVK/API/mvk_datatypes.h index 76470233c..a7098288f 100644 --- a/MoltenVK/MoltenVK/API/mvk_datatypes.h +++ b/MoltenVK/MoltenVK/API/mvk_datatypes.h @@ -16,14 +16,6 @@ * limitations under the License. */ - -/* - * This file contains functions for converting between Vulkan and Metal data types. - * - * The functions here are used internally by MoltenVK, and are exposed here - * as a convenience for use elsewhere within applications using MoltenVK. - */ - #ifndef __mvkDataTypes_h_ #define __mvkDataTypes_h_ 1 @@ -37,6 +29,14 @@ extern "C" { #import +/* + * This file contains functions for converting between Vulkan and Metal data types. + * + * The functions here are used internally by MoltenVK, and are exposed here + * as a convenience for use elsewhere within applications using MoltenVK. + */ + + #pragma mark - #pragma mark Image properties @@ -227,6 +227,15 @@ MTLTextureSwizzle mvkMTLTextureSwizzleFromVkComponentSwizzle(VkComponentSwizzle /** Returns all four Metal texture swizzles from the Vulkan component mapping. */ MTLTextureSwizzleChannels mvkMTLTextureSwizzleChannelsFromVkComponentMapping(VkComponentMapping vkMapping); +/** Maps a clear color according to the specified VkComponentSwizzle. */ +float mvkVkClearColorFloatValueFromVkComponentSwizzle(float *colors, uint32_t index, VkComponentSwizzle vkSwizzle); + +/** Maps a clear color according to the specified VkComponentSwizzle. */ +uint32_t mvkVkClearColorUIntValueFromVkComponentSwizzle(uint32_t *colors, uint32_t index, VkComponentSwizzle vkSwizzle); + +/** Maps a clear color according to the specified VkComponentSwizzle. */ +int32_t mvkVkClearColorIntValueFromVkComponentSwizzle(int32_t *colors, uint32_t index, VkComponentSwizzle vkSwizzle); + #pragma mark Mipmaps @@ -318,6 +327,7 @@ typedef enum { kMVKShaderStageVertex = 0, kMVKShaderStageTessCtl, kMVKShaderStageTessEval, + kMVKShaderStageGeometry, kMVKShaderStageFragment, kMVKShaderStageCompute, kMVKShaderStageCount, @@ -425,6 +435,12 @@ VkExtent2D mvkVkExtent2DFromCGSize(CGSize cgSize); /** Returns a CGSize that corresponds to the specified VkExtent2D. */ CGSize mvkCGSizeFromVkExtent2D(VkExtent2D vkExtent); +/** Returns a CGPoint that corresponds to the specified VkOffset2D. */ +CGPoint mvkCGPointFromVkOffset2D(VkOffset2D vkOffset); + +/** Returns a CGRect that corresponds to the specified VkRectLayerKHR. The layer is ignored. */ +CGRect mvkCGRectFromVkRectLayerKHR(VkRectLayerKHR vkRect); + /** Returns a Metal MTLOrigin constructed from a VkOffset3D. */ static inline MTLOrigin mvkMTLOriginFromVkOffset3D(VkOffset3D vkOffset) { return MTLOriginMake(vkOffset.x, vkOffset.y, vkOffset.z); diff --git a/MoltenVK/MoltenVK/API/mvk_deprecated_api.h b/MoltenVK/MoltenVK/API/mvk_deprecated_api.h new file mode 100644 index 000000000..d6fc4aadd --- /dev/null +++ b/MoltenVK/MoltenVK/API/mvk_deprecated_api.h @@ -0,0 +1,233 @@ +/* + * mvk_deprecated_api.h + * + * Copyright (c) 2015-2023 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. + */ + + +#ifndef __mvk_deprecated_api_h_ +#define __mvk_deprecated_api_h_ 1 + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#include +#include + + +#define VK_MVK_MOLTENVK_SPEC_VERSION 37 +#define VK_MVK_MOLTENVK_EXTENSION_NAME "VK_MVK_moltenvk" + +/** + * This header contains obsolete and deprecated MoltenVK functions, that were originally + * part of the obsolete and deprecated non-standard VK_MVK_moltenvk extension. + * + * NOTE: USE OF THE FUNCTIONS BELOW IS NOT RECOMMENDED. THE VK_MVK_moltenvk EXTENSION, + * AND THE FUNCTIONS BELOW ARE NOT SUPPORTED BY THE VULKAN LOADER AND LAYERS. + * THE VULKAN OBJECTS PASSED IN THESE FUNCTIONS MUST HAVE BEEN RETRIEVED DIRECTLY + * FROM MOLTENVK, WITHOUT LINKING THROUGH THE VULKAN LOADER AND LAYERS. + * + * To interact with the Metal objects underlying Vulkan objects in MoltenVK, + * use the standard Vulkan VK_EXT_metal_objects extension. + * The VK_EXT_metal_objects extension is supported by the Vulkan Loader and Layers. + */ + + +#pragma mark - +#pragma mark Function types + +typedef void (VKAPI_PTR *PFN_vkGetVersionStringsMVK)(char* pMoltenVersionStringBuffer, uint32_t moltenVersionStringBufferLength, char* pVulkanVersionStringBuffer, uint32_t vulkanVersionStringBufferLength); +typedef void (VKAPI_PTR *PFN_vkSetWorkgroupSizeMVK)(VkShaderModule shaderModule, uint32_t x, uint32_t y, uint32_t z); +typedef VkResult (VKAPI_PTR *PFN_vkUseIOSurfaceMVK)(VkImage image, IOSurfaceRef ioSurface); +typedef void (VKAPI_PTR *PFN_vkGetIOSurfaceMVK)(VkImage image, IOSurfaceRef* pIOSurface); + +#ifdef __OBJC__ +typedef void (VKAPI_PTR *PFN_vkGetMTLDeviceMVK)(VkPhysicalDevice physicalDevice, id* pMTLDevice); +typedef VkResult (VKAPI_PTR *PFN_vkSetMTLTextureMVK)(VkImage image, id mtlTexture); +typedef void (VKAPI_PTR *PFN_vkGetMTLTextureMVK)(VkImage image, id* pMTLTexture); +typedef void (VKAPI_PTR *PFN_vkGetMTLBufferMVK)(VkBuffer buffer, id* pMTLBuffer); +typedef void (VKAPI_PTR *PFN_vkGetMTLCommandQueueMVK)(VkQueue queue, id* pMTLCommandQueue); +#endif // __OBJC__ + + +#pragma mark - +#pragma mark Function prototypes + +#ifndef VK_NO_PROTOTYPES + +#define MVK_DEPRECATED VKAPI_ATTR [[deprecated]] +#define MVK_DEPRECATED_USE_MTL_OBJS VKAPI_ATTR [[deprecated("Use the VK_EXT_metal_objects extension instead.")]] + + +/** + * DEPRECATED. + * Returns a human readable version of the MoltenVK and Vulkan versions. + * + * This function is provided as a convenience for reporting. Use the MVK_VERSION, + * VK_API_VERSION_1_0, and VK_HEADER_VERSION macros for programmatically accessing + * the corresponding version numbers. + */ +MVK_DEPRECATED +void VKAPI_CALL vkGetVersionStringsMVK( + char* pMoltenVersionStringBuffer, + uint32_t moltenVersionStringBufferLength, + char* pVulkanVersionStringBuffer, + uint32_t vulkanVersionStringBufferLength); + +/** + * DEPRECATED. + * Sets the number of threads in a workgroup for a compute kernel. + * + * This needs to be called if you are creating compute shader modules from MSL source code + * or MSL compiled code. If you are using SPIR-V, workgroup size is determined automatically. + * + * This function is not supported by the Vulkan SDK Loader and Layers framework + * and is unavailable when using the Vulkan SDK Loader and Layers framework. + */ +MVK_DEPRECATED +void VKAPI_CALL vkSetWorkgroupSizeMVK( + VkShaderModule shaderModule, + uint32_t x, + uint32_t y, + uint32_t z); + +#ifdef __OBJC__ + +/** + * DEPRECATED. Use the VK_EXT_metal_objects extension instead. + * Returns, in the pMTLDevice pointer, the MTLDevice used by the VkPhysicalDevice. + * + * This function is not supported by the Vulkan SDK Loader and Layers framework + * and is unavailable when using the Vulkan SDK Loader and Layers framework. + */ +MVK_DEPRECATED_USE_MTL_OBJS +void VKAPI_CALL vkGetMTLDeviceMVK( + VkPhysicalDevice physicalDevice, + id* pMTLDevice); + +/** + * DEPRECATED. Use the VK_EXT_metal_objects extension instead. + * Sets the VkImage to use the specified MTLTexture. + * + * Any differences in the properties of mtlTexture and this image will modify the + * properties of this image. + * + * If a MTLTexture has already been created for this image, it will be destroyed. + * + * Returns VK_SUCCESS. + * + * This function is not supported by the Vulkan SDK Loader and Layers framework + * and is unavailable when using the Vulkan SDK Loader and Layers framework. + */ +MVK_DEPRECATED_USE_MTL_OBJS +VkResult VKAPI_CALL vkSetMTLTextureMVK( + VkImage image, + id mtlTexture); + +/** + * DEPRECATED. Use the VK_EXT_metal_objects extension instead. + * Returns, in the pMTLTexture pointer, the MTLTexture currently underlaying the VkImage. + * + * This function is not supported by the Vulkan SDK Loader and Layers framework + * and is unavailable when using the Vulkan SDK Loader and Layers framework. + */ +MVK_DEPRECATED_USE_MTL_OBJS +void VKAPI_CALL vkGetMTLTextureMVK( + VkImage image, + id* pMTLTexture); + +/** + * DEPRECATED. Use the VK_EXT_metal_objects extension instead. +* Returns, in the pMTLBuffer pointer, the MTLBuffer currently underlaying the VkBuffer. +* + * This function is not supported by the Vulkan SDK Loader and Layers framework + * and is unavailable when using the Vulkan SDK Loader and Layers framework. +*/ +MVK_DEPRECATED_USE_MTL_OBJS +void VKAPI_CALL vkGetMTLBufferMVK( + VkBuffer buffer, + id* pMTLBuffer); + +/** + * DEPRECATED. Use the VK_EXT_metal_objects extension instead. +* Returns, in the pMTLCommandQueue pointer, the MTLCommandQueue currently underlaying the VkQueue. +* + * This function is not supported by the Vulkan SDK Loader and Layers framework + * and is unavailable when using the Vulkan SDK Loader and Layers framework. +*/ +MVK_DEPRECATED_USE_MTL_OBJS +void VKAPI_CALL vkGetMTLCommandQueueMVK( + VkQueue queue, + id* pMTLCommandQueue); + +#endif // __OBJC__ + +/** + * DEPRECATED. Use the VK_EXT_metal_objects extension instead. + * Indicates that a VkImage should use an IOSurface to underlay the Metal texture. + * + * If ioSurface is not null, it will be used as the IOSurface, and any differences + * in the properties of that IOSurface will modify the properties of this image. + * + * If ioSurface is null, this image will create and use an IOSurface + * whose properties are compatible with the properties of this image. + * + * If a MTLTexture has already been created for this image, it will be destroyed. + * + * IOSurfaces are supported on the following platforms: + * - macOS 10.11 and above + * - iOS 11.0 and above + * + * To enable IOSurface support, ensure the Deployment Target build setting + * (MACOSX_DEPLOYMENT_TARGET or IPHONEOS_DEPLOYMENT_TARGET) is set to at least + * one of the values above when compiling MoltenVK, and any app that uses MoltenVK. + * + * Returns: + * - VK_SUCCESS. + * - VK_ERROR_FEATURE_NOT_PRESENT if IOSurfaces are not supported on the platform. + * - VK_ERROR_INITIALIZATION_FAILED if ioSurface is specified and is not compatible with this VkImage. + * + * This function is not supported by the Vulkan SDK Loader and Layers framework + * and is unavailable when using the Vulkan SDK Loader and Layers framework. + */ +MVK_DEPRECATED_USE_MTL_OBJS +VkResult VKAPI_CALL vkUseIOSurfaceMVK( + VkImage image, + IOSurfaceRef ioSurface); + +/** + * DEPRECATED. Use the VK_EXT_metal_objects extension instead. + * Returns, in the pIOSurface pointer, the IOSurface currently underlaying the VkImage, + * as set by the useIOSurfaceMVK() function, or returns null if the VkImage is not using + * an IOSurface, or if the platform does not support IOSurfaces. + * + * This function is not supported by the Vulkan SDK Loader and Layers framework + * and is unavailable when using the Vulkan SDK Loader and Layers framework. + */ +MVK_DEPRECATED_USE_MTL_OBJS +void VKAPI_CALL vkGetIOSurfaceMVK( + VkImage image, + IOSurfaceRef* pIOSurface); + + +#endif // VK_NO_PROTOTYPES + + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif diff --git a/MoltenVK/MoltenVK/API/mvk_private_api.h b/MoltenVK/MoltenVK/API/mvk_private_api.h new file mode 100644 index 000000000..87bc8ad99 --- /dev/null +++ b/MoltenVK/MoltenVK/API/mvk_private_api.h @@ -0,0 +1,296 @@ +/* + * mvk_private_api.h + * + * Copyright (c) 2015-2023 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. + */ + +#ifndef __mvk_private_api_h_ +#define __mvk_private_api_h_ 1 + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#include + +#ifdef __OBJC__ +#import +#else +typedef unsigned long MTLLanguageVersion; +typedef unsigned long MTLArgumentBuffersTier; +#endif + + +/** + * This header contains functions to query MoltenVK about + * available Metal features, and runtime performance information. + * + * NOTE: THE FUNCTIONS BELOW SHOULD BE USED WITH CARE. THESE FUNCTIONS ARE + * NOT PART OF VULKAN, AND ARE NOT SUPPORTED BY THE VULKAN LOADER AND LAYERS. + * THE VULKAN OBJECTS PASSED IN THESE FUNCTIONS MUST HAVE BEEN RETRIEVED + * DIRECTLY FROM MOLTENVK, WITHOUT LINKING THROUGH THE VULKAN LOADER AND LAYERS. + */ + + +#define MVK_PRIVATE_API_VERSION 37 + + +/** Identifies the type of rounding Metal uses for float to integer conversions in particular calculatons. */ +typedef enum MVKFloatRounding { + MVK_FLOAT_ROUNDING_NEAREST = 0, /**< Metal rounds to nearest. */ + MVK_FLOAT_ROUNDING_UP = 1, /**< Metal rounds towards positive infinity. */ + MVK_FLOAT_ROUNDING_DOWN = 2, /**< Metal rounds towards negative infinity. */ + MVK_FLOAT_ROUNDING_UP_MAX_ENUM = 0x7FFFFFFF +} MVKFloatRounding; + +/** Identifies the pipeline points where GPU counter sampling can occur. Maps to MTLCounterSamplingPoint. */ +typedef enum MVKCounterSamplingBits { + MVK_COUNTER_SAMPLING_AT_DRAW = 0x00000001, + MVK_COUNTER_SAMPLING_AT_DISPATCH = 0x00000002, + MVK_COUNTER_SAMPLING_AT_BLIT = 0x00000004, + MVK_COUNTER_SAMPLING_AT_PIPELINE_STAGE = 0x00000008, + MVK_COUNTER_SAMPLING_MAX_ENUM = 0X7FFFFFFF +} MVKCounterSamplingBits; +typedef VkFlags MVKCounterSamplingFlags; + +/** + * Features provided by the current implementation of Metal on the current device. You can + * retrieve a copy of this structure using the vkGetPhysicalDeviceMetalFeaturesMVK() function. + * + * This structure may be extended as new features are added to MoltenVK. If you are linking to + * an implementation of MoltenVK that was compiled from a different MVK_PRIVATE_API_VERSION + * than your app was, the size of this structure in your app may be larger or smaller than the + * struct in MoltenVK. See the description of the vkGetPhysicalDeviceMetalFeaturesMVK() function + * for information about how to handle this. + * + * TO SUPPORT DYNAMIC LINKING TO THIS STRUCTURE AS DESCRIBED ABOVE, THIS STRUCTURE SHOULD NOT + * BE CHANGED EXCEPT TO ADD ADDITIONAL MEMBERS ON THE END. EXISTING MEMBERS, AND THEIR ORDER, + * SHOULD NOT BE CHANGED. + */ +typedef struct { + uint32_t mslVersion; /**< The version of the Metal Shading Language available on this device. The format of the integer is MMmmpp, with two decimal digts each for Major, minor, and patch version values (eg. MSL 1.2 would appear as 010200). */ + VkBool32 indirectDrawing; /**< If true, draw calls support parameters held in a GPU buffer. */ + VkBool32 baseVertexInstanceDrawing; /**< If true, draw calls support specifiying the base vertex and instance. */ + uint32_t dynamicMTLBufferSize; /**< If greater than zero, dynamic MTLBuffers for setting vertex, fragment, and compute bytes are supported, and their content must be below this value. */ + VkBool32 shaderSpecialization; /**< If true, shader specialization (aka Metal function constants) is supported. */ + VkBool32 ioSurfaces; /**< If true, VkImages can be underlaid by IOSurfaces via the vkUseIOSurfaceMVK() function, to support inter-process image transfers. */ + VkBool32 texelBuffers; /**< If true, texel buffers are supported, allowing the contents of a buffer to be interpreted as an image via a VkBufferView. */ + VkBool32 layeredRendering; /**< If true, layered rendering to multiple cube or texture array layers is supported. */ + VkBool32 presentModeImmediate; /**< If true, immediate surface present mode (VK_PRESENT_MODE_IMMEDIATE_KHR), allowing a swapchain image to be presented immediately, without waiting for the vertical sync period of the display, is supported. */ + VkBool32 stencilViews; /**< If true, stencil aspect views are supported through the MTLPixelFormatX24_Stencil8 and MTLPixelFormatX32_Stencil8 formats. */ + VkBool32 multisampleArrayTextures; /**< If true, MTLTextureType2DMultisampleArray is supported. */ + VkBool32 samplerClampToBorder; /**< If true, the border color set when creating a sampler will be respected. */ + uint32_t maxTextureDimension; /**< The maximum size of each texture dimension (width, height, or depth). */ + uint32_t maxPerStageBufferCount; /**< The total number of per-stage Metal buffers available for shader uniform content and attributes. */ + uint32_t maxPerStageTextureCount; /**< The total number of per-stage Metal textures available for shader uniform content. */ + uint32_t maxPerStageSamplerCount; /**< The total number of per-stage Metal samplers available for shader uniform content. */ + VkDeviceSize maxMTLBufferSize; /**< The max size of a MTLBuffer (in bytes). */ + VkDeviceSize mtlBufferAlignment; /**< The alignment used when allocating memory for MTLBuffers. Must be PoT. */ + VkDeviceSize maxQueryBufferSize; /**< The maximum size of an occlusion query buffer (in bytes). */ + VkDeviceSize mtlCopyBufferAlignment; /**< The alignment required during buffer copy operations (in bytes). */ + VkSampleCountFlags supportedSampleCounts; /**< A bitmask identifying the sample counts supported by the device. */ + uint32_t minSwapchainImageCount; /**< The minimum number of swapchain images that can be supported by a surface. */ + uint32_t maxSwapchainImageCount; /**< The maximum number of swapchain images that can be supported by a surface. */ + VkBool32 combinedStoreResolveAction; /**< If true, the device supports VK_ATTACHMENT_STORE_OP_STORE with a simultaneous resolve attachment. */ + VkBool32 arrayOfTextures; /**< If true, arrays of textures is supported. */ + VkBool32 arrayOfSamplers; /**< If true, arrays of texture samplers is supported. */ + MTLLanguageVersion mslVersionEnum; /**< The version of the Metal Shading Language available on this device, as a Metal enumeration. */ + VkBool32 depthSampleCompare; /**< If true, depth texture samplers support the comparison of the pixel value against a reference value. */ + VkBool32 events; /**< If true, Metal synchronization events (MTLEvent) are supported. */ + VkBool32 memoryBarriers; /**< If true, full memory barriers within Metal render passes are supported. */ + VkBool32 multisampleLayeredRendering; /**< If true, layered rendering to multiple multi-sampled cube or texture array layers is supported. */ + VkBool32 stencilFeedback; /**< If true, fragment shaders that write to [[stencil]] outputs are supported. */ + VkBool32 textureBuffers; /**< If true, textures of type MTLTextureTypeBuffer are supported. */ + VkBool32 postDepthCoverage; /**< If true, coverage masks in fragment shaders post-depth-test are supported. */ + VkBool32 fences; /**< If true, Metal synchronization fences (MTLFence) are supported. */ + VkBool32 rasterOrderGroups; /**< If true, Raster order groups in fragment shaders are supported. */ + VkBool32 native3DCompressedTextures; /**< If true, 3D compressed images are supported natively, without manual decompression. */ + VkBool32 nativeTextureSwizzle; /**< If true, component swizzle is supported natively, without manual swizzling in shaders. */ + VkBool32 placementHeaps; /**< If true, MTLHeap objects support placement of resources. */ + VkDeviceSize pushConstantSizeAlignment; /**< The alignment used internally when allocating memory for push constants. Must be PoT. */ + uint32_t maxTextureLayers; /**< The maximum number of layers in an array texture. */ + uint32_t maxSubgroupSize; /**< The maximum number of threads in a SIMD-group. */ + VkDeviceSize vertexStrideAlignment; /**< The alignment used for the stride of vertex attribute bindings. */ + VkBool32 indirectTessellationDrawing; /**< If true, tessellation draw calls support parameters held in a GPU buffer. */ + VkBool32 nonUniformThreadgroups; /**< If true, the device supports arbitrary-sized grids in compute workloads. */ + VkBool32 renderWithoutAttachments; /**< If true, we don't have to create a dummy attachment for a render pass if there isn't one. */ + VkBool32 deferredStoreActions; /**< If true, render pass store actions can be specified after the render encoder is created. */ + VkBool32 sharedLinearTextures; /**< If true, linear textures and texture buffers can be created from buffers in Shared storage. */ + VkBool32 depthResolve; /**< If true, resolving depth textures with filters other than Sample0 is supported. */ + VkBool32 stencilResolve; /**< If true, resolving stencil textures with filters other than Sample0 is supported. */ + uint32_t maxPerStageDynamicMTLBufferCount; /**< The maximum number of inline buffers that can be set on a command buffer. */ + uint32_t maxPerStageStorageTextureCount; /**< The total number of per-stage Metal textures with read-write access available for writing to from a shader. */ + VkBool32 astcHDRTextures; /**< If true, ASTC HDR pixel formats are supported. */ + VkBool32 renderLinearTextures; /**< If true, linear textures are renderable. */ + VkBool32 pullModelInterpolation; /**< If true, explicit interpolation functions are supported. */ + VkBool32 samplerMirrorClampToEdge; /**< If true, the mirrored clamp to edge address mode is supported in samplers. */ + VkBool32 quadPermute; /**< If true, quadgroup permutation functions (vote, ballot, shuffle) are supported in shaders. */ + VkBool32 simdPermute; /**< If true, SIMD-group permutation functions (vote, ballot, shuffle) are supported in shaders. */ + VkBool32 simdReduction; /**< If true, SIMD-group reduction functions (arithmetic) are supported in shaders. */ + uint32_t minSubgroupSize; /**< The minimum number of threads in a SIMD-group. */ + VkBool32 textureBarriers; /**< If true, texture barriers are supported within Metal render passes. */ + VkBool32 tileBasedDeferredRendering; /**< If true, this device uses tile-based deferred rendering. */ + VkBool32 argumentBuffers; /**< If true, Metal argument buffers are supported. */ + VkBool32 descriptorSetArgumentBuffers; /**< If true, a Metal argument buffer can be assigned to a descriptor set, and used on any pipeline and pipeline stage. If false, a different Metal argument buffer must be used for each pipeline-stage/descriptor-set combination. */ + MVKFloatRounding clearColorFloatRounding; /**< Identifies the type of rounding Metal uses for MTLClearColor float to integer conversions. */ + MVKCounterSamplingFlags counterSamplingPoints; /**< Identifies the points where pipeline GPU counter sampling may occur. */ + VkBool32 programmableSamplePositions; /**< If true, programmable MSAA sample positions are supported. */ + VkBool32 shaderBarycentricCoordinates; /**< If true, fragment shader barycentric coordinates are supported. */ + MTLArgumentBuffersTier argumentBuffersTier; /**< The argument buffer tier available on this device, as a Metal enumeration. */ + VkBool32 needsSampleDrefLodArrayWorkaround; /**< If true, sampling from arrayed depth images with explicit LoD is broken and needs a workaround. */ + VkDeviceSize hostMemoryPageSize; /**< The size of a page of host memory on this platform. */ +} MVKPhysicalDeviceMetalFeatures; + +/** MoltenVK performance of a particular type of activity. */ +typedef struct { + uint32_t count; /**< The number of activities of this type. */ + double latestDuration; /**< The latest (most recent) duration of the activity, in milliseconds. */ + double averageDuration; /**< The average duration of the activity, in milliseconds. */ + double minimumDuration; /**< The minimum duration of the activity, in milliseconds. */ + double maximumDuration; /**< The maximum duration of the activity, in milliseconds. */ +} MVKPerformanceTracker; + +/** MoltenVK performance of shader compilation activities. */ +typedef struct { + MVKPerformanceTracker hashShaderCode; /** Create a hash from the incoming shader code. */ + MVKPerformanceTracker spirvToMSL; /** Convert SPIR-V to MSL source code. */ + MVKPerformanceTracker mslCompile; /** Compile MSL source code into a MTLLibrary. */ + MVKPerformanceTracker mslLoad; /** Load pre-compiled MSL code into a MTLLibrary. */ + MVKPerformanceTracker mslCompress; /** Compress MSL source code after compiling a MTLLibrary, to hold it in a pipeline cache. */ + MVKPerformanceTracker mslDecompress; /** Decompress MSL source code to write the MSL when serializing a pipeline cache. */ + MVKPerformanceTracker shaderLibraryFromCache; /** Retrieve a shader library from the cache, lazily creating it if needed. */ + MVKPerformanceTracker functionRetrieval; /** Retrieve a MTLFunction from a MTLLibrary. */ + MVKPerformanceTracker functionSpecialization; /** Specialize a retrieved MTLFunction. */ + MVKPerformanceTracker pipelineCompile; /** Compile MTLFunctions into a pipeline. */ + MVKPerformanceTracker glslToSPRIV; /** Convert GLSL to SPIR-V code. */ +} MVKShaderCompilationPerformance; + +/** MoltenVK performance of pipeline cache activities. */ +typedef struct { + MVKPerformanceTracker sizePipelineCache; /** Calculate the size of cache data required to write MSL to pipeline cache data stream. */ + MVKPerformanceTracker writePipelineCache; /** Write MSL to pipeline cache data stream. */ + MVKPerformanceTracker readPipelineCache; /** Read MSL from pipeline cache data stream. */ +} MVKPipelineCachePerformance; + +/** MoltenVK performance of queue activities. */ +typedef struct { + MVKPerformanceTracker mtlQueueAccess; /** Create an MTLCommandQueue or access an existing cached instance. */ + MVKPerformanceTracker mtlCommandBufferCompletion; /** Completion of a MTLCommandBuffer on the GPU, from commit to completion callback. */ + MVKPerformanceTracker nextCAMetalDrawable; /** Retrieve next CAMetalDrawable from CAMetalLayer during presentation. */ + MVKPerformanceTracker frameInterval; /** Frame presentation interval (1000/FPS). */ +} MVKQueuePerformance; + +/** + * MoltenVK performance. You can retrieve a copy of this structure using the vkGetPerformanceStatisticsMVK() function. + * + * This structure may be extended as new features are added to MoltenVK. If you are linking to + * an implementation of MoltenVK that was compiled from a different MVK_PRIVATE_API_VERSION + * than your app was, the size of this structure in your app may be larger or smaller than the + * struct in MoltenVK. See the description of the vkGetPerformanceStatisticsMVK() function for + * information about how to handle this. + * + * TO SUPPORT DYNAMIC LINKING TO THIS STRUCTURE AS DESCRIBED ABOVE, THIS STRUCTURE SHOULD NOT + * BE CHANGED EXCEPT TO ADD ADDITIONAL MEMBERS ON THE END. EXISTING MEMBERS, AND THEIR ORDER, + * SHOULD NOT BE CHANGED. + */ +typedef struct { + MVKShaderCompilationPerformance shaderCompilation; /** Shader compilations activities. */ + MVKPipelineCachePerformance pipelineCache; /** Pipeline cache activities. */ + MVKQueuePerformance queue; /** Queue activities. */ +} MVKPerformanceStatistics; + + +#pragma mark - +#pragma mark Function types + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceMetalFeaturesMVK)(VkPhysicalDevice physicalDevice, MVKPhysicalDeviceMetalFeatures* pMetalFeatures, size_t* pMetalFeaturesSize); +typedef VkResult (VKAPI_PTR *PFN_vkGetPerformanceStatisticsMVK)(VkDevice device, MVKPerformanceStatistics* pPerf, size_t* pPerfSize); + + +#pragma mark - +#pragma mark Function prototypes + +#ifndef VK_NO_PROTOTYPES + +/** + * Populates the pMetalFeatures structure with the Metal-specific features + * supported by the specified physical device. + * + * If you are linking to an implementation of MoltenVK that was compiled from a different + * MVK_PRIVATE_API_VERSION than your app was, the size of the MVKPhysicalDeviceMetalFeatures + * structure in your app may be larger or smaller than the same struct as expected by MoltenVK. + * + * When calling this function, set the value of *pMetalFeaturesSize to sizeof(MVKPhysicalDeviceMetalFeatures), + * to tell MoltenVK the limit of the size of your MVKPhysicalDeviceMetalFeatures structure. Upon return from + * this function, the value of *pMetalFeaturesSize will hold the actual number of bytes copied into your + * passed MVKPhysicalDeviceMetalFeatures structure, which will be the smaller of what your app thinks is the + * size of MVKPhysicalDeviceMetalFeatures, and what MoltenVK thinks it is. This represents the safe access + * area within the structure for both MoltenVK and your app. + * + * If the size that MoltenVK expects for MVKPhysicalDeviceMetalFeatures is different than the value passed in + * *pMetalFeaturesSize, this function will return VK_INCOMPLETE, otherwise it will return VK_SUCCESS. + * + * Although it is not necessary, you can use this function to determine in advance the value that MoltenVK + * expects the size of MVKPhysicalDeviceMetalFeatures to be by setting the value of pMetalFeatures to NULL. + * In that case, this function will set *pMetalFeaturesSize to the size that MoltenVK expects + * MVKPhysicalDeviceMetalFeatures to be. + * + * This function is not supported by the Vulkan SDK Loader and Layers framework + * and is unavailable when using the Vulkan SDK Loader and Layers framework. + */ +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceMetalFeaturesMVK( + VkPhysicalDevice physicalDevice, + MVKPhysicalDeviceMetalFeatures* pMetalFeatures, + size_t* pMetalFeaturesSize); + +/** + * Populates the pPerf structure with the current performance statistics for the device. + * + * If you are linking to an implementation of MoltenVK that was compiled from a different + * MVK_PRIVATE_API_VERSION than your app was, the size of the MVKPerformanceStatistics + * structure in your app may be larger or smaller than the same struct as expected by MoltenVK. + * + * When calling this function, set the value of *pPerfSize to sizeof(MVKPerformanceStatistics), + * to tell MoltenVK the limit of the size of your MVKPerformanceStatistics structure. Upon return + * from this function, the value of *pPerfSize will hold the actual number of bytes copied into + * your passed MVKPerformanceStatistics structure, which will be the smaller of what your app + * thinks is the size of MVKPerformanceStatistics, and what MoltenVK thinks it is. This + * represents the safe access area within the structure for both MoltenVK and your app. + * + * If the size that MoltenVK expects for MVKPerformanceStatistics is different than the value passed + * in *pPerfSize, this function will return VK_INCOMPLETE, otherwise it will return VK_SUCCESS. + * + * Although it is not necessary, you can use this function to determine in advance the value + * that MoltenVK expects the size of MVKPerformanceStatistics to be by setting the value of + * pPerf to NULL. In that case, this function will set *pPerfSize to the size that MoltenVK + * expects MVKPerformanceStatistics to be. + * + * This function is not supported by the Vulkan SDK Loader and Layers framework + * and is unavailable when using the Vulkan SDK Loader and Layers framework. + */ +VKAPI_ATTR VkResult VKAPI_CALL vkGetPerformanceStatisticsMVK( + VkDevice device, + MVKPerformanceStatistics* pPerf, + size_t* pPerfSize); + + +#endif // VK_NO_PROTOTYPES + + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif diff --git a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h index 44a5be5a4..a9b2d67d8 100644 --- a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h +++ b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h @@ -16,1422 +16,25 @@ * limitations under the License. */ - -/** Vulkan extension VK_MVK_moltenvk. */ - -#ifndef __vk_mvk_moltenvk_h_ -#define __vk_mvk_moltenvk_h_ 1 - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -#include "mvk_vulkan.h" -#include - -#ifdef __OBJC__ -#import -#else -typedef unsigned long MTLLanguageVersion; -typedef unsigned long MTLArgumentBuffersTier; -#endif - - -/** - * The version number of MoltenVK is a single integer value, derived from the Major, Minor, - * and Patch version values, where each of the Major, Minor, and Patch components is allocated - * two decimal digits, in the format MjMnPt. This creates a version number that is both human - * readable and allows efficient computational comparisons to a single integer number. - * - * The following examples illustrate how the MoltenVK version number is built from its components: - * - 002000 (version 0.20.0) - * - 010000 (version 1.0.0) - * - 030104 (version 3.1.4) - * - 401215 (version 4.12.15) - */ -#define MVK_VERSION_MAJOR 1 -#define MVK_VERSION_MINOR 2 -#define MVK_VERSION_PATCH 3 - -#define MVK_MAKE_VERSION(major, minor, patch) (((major) * 10000) + ((minor) * 100) + (patch)) -#define MVK_VERSION MVK_MAKE_VERSION(MVK_VERSION_MAJOR, MVK_VERSION_MINOR, MVK_VERSION_PATCH) - -#define VK_MVK_MOLTENVK_SPEC_VERSION 37 -#define VK_MVK_MOLTENVK_EXTENSION_NAME "VK_MVK_moltenvk" - -/** Identifies the level of logging MoltenVK should be limited to outputting. */ -typedef enum MVKConfigLogLevel { - MVK_CONFIG_LOG_LEVEL_NONE = 0, /**< No logging. */ - MVK_CONFIG_LOG_LEVEL_ERROR = 1, /**< Log errors only. */ - MVK_CONFIG_LOG_LEVEL_WARNING = 2, /**< Log errors and warning messages. */ - MVK_CONFIG_LOG_LEVEL_INFO = 3, /**< Log errors, warnings and informational messages. */ - MVK_CONFIG_LOG_LEVEL_DEBUG = 4, /**< Log errors, warnings, infos and debug messages. */ - MVK_CONFIG_LOG_LEVEL_MAX_ENUM = 0x7FFFFFFF -} MVKConfigLogLevel; - -/** Identifies the level of Vulkan call trace logging MoltenVK should perform. */ -typedef enum MVKConfigTraceVulkanCalls { - MVK_CONFIG_TRACE_VULKAN_CALLS_NONE = 0, /**< No Vulkan call logging. */ - MVK_CONFIG_TRACE_VULKAN_CALLS_ENTER = 1, /**< Log the name of each Vulkan call when the call is entered. */ - MVK_CONFIG_TRACE_VULKAN_CALLS_ENTER_THREAD_ID = 2, /**< Log the name and thread ID of each Vulkan call when the call is entered. */ - MVK_CONFIG_TRACE_VULKAN_CALLS_ENTER_EXIT = 3, /**< Log the name of each Vulkan call when the call is entered and exited. This effectively brackets any other logging activity within the scope of the Vulkan call. */ - MVK_CONFIG_TRACE_VULKAN_CALLS_ENTER_EXIT_THREAD_ID = 4, /**< Log the name and thread ID of each Vulkan call when the call is entered and name when exited. This effectively brackets any other logging activity within the scope of the Vulkan call. */ - MVK_CONFIG_TRACE_VULKAN_CALLS_DURATION = 5, /**< Same as MVK_CONFIG_TRACE_VULKAN_CALLS_ENTER_EXIT, plus logs the time spent inside the Vulkan function. */ - MVK_CONFIG_TRACE_VULKAN_CALLS_DURATION_THREAD_ID = 6, /**< Same as MVK_CONFIG_TRACE_VULKAN_CALLS_ENTER_EXIT_THREAD_ID, plus logs the time spent inside the Vulkan function. */ - MVK_CONFIG_TRACE_VULKAN_CALLS_MAX_ENUM = 0x7FFFFFFF -} MVKConfigTraceVulkanCalls; - -/** Identifies the scope for Metal to run an automatic GPU capture for diagnostic debugging purposes. */ -typedef enum MVKConfigAutoGPUCaptureScope { - MVK_CONFIG_AUTO_GPU_CAPTURE_SCOPE_NONE = 0, /**< No automatic GPU capture. */ - MVK_CONFIG_AUTO_GPU_CAPTURE_SCOPE_DEVICE = 1, /**< Automatically capture all GPU activity during the lifetime of a VkDevice. */ - MVK_CONFIG_AUTO_GPU_CAPTURE_SCOPE_FRAME = 2, /**< Automatically capture all GPU activity during the rendering and presentation of the first frame. */ - MVK_CONFIG_AUTO_GPU_CAPTURE_SCOPE_MAX_ENUM = 0x7FFFFFFF -} MVKConfigAutoGPUCaptureScope; - -/** Identifies extensions to advertise as part of MoltenVK configuration. */ -typedef enum MVKConfigAdvertiseExtensionBits { - MVK_CONFIG_ADVERTISE_EXTENSIONS_ALL = 0x00000001, /**< All supported extensions. */ - MVK_CONFIG_ADVERTISE_EXTENSIONS_MOLTENVK = 0x00000002, /**< This VK_MVK_moltenvk extension. */ - MVK_CONFIG_ADVERTISE_EXTENSIONS_WSI = 0x00000004, /**< WSI extensions supported on the platform. */ - MVK_CONFIG_ADVERTISE_EXTENSIONS_PORTABILITY = 0x00000008, /**< Vulkan Portability Subset extensions. */ - MVK_CONFIG_ADVERTISE_EXTENSIONS_MAX_ENUM = 0x7FFFFFFF -} MVKConfigAdvertiseExtensionBits; -typedef VkFlags MVKConfigAdvertiseExtensions; - -/** Identifies the use of Metal Argument Buffers. */ -typedef enum MVKUseMetalArgumentBuffers { - MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS_NEVER = 0, /**< Don't use Metal Argument Buffers. */ - MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS_ALWAYS = 1, /**< Use Metal Argument Buffers for all pipelines. */ - MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS_DESCRIPTOR_INDEXING = 2, /**< Use Metal Argument Buffers only if VK_EXT_descriptor_indexing extension is enabled. */ - MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS_MAX_ENUM = 0x7FFFFFFF -} MVKUseMetalArgumentBuffers; - -/** Identifies the Metal functionality used to support Vulkan semaphore functionality (VkSemaphore). */ -typedef enum MVKVkSemaphoreSupportStyle { - MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_SINGLE_QUEUE = 0, /**< Limit Vulkan to a single queue, with no explicit semaphore synchronization, and use Metal's implicit guarantees that all operations submitted to a queue will give the same result as if they had been run in submission order. */ - MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_METAL_EVENTS_WHERE_SAFE = 1, /**< Use Metal events (MTLEvent) when available on the platform, and where safe. This will revert to same as MVK_CONFIG_VK_SEMAPHORE_USE_SINGLE_QUEUE on some NVIDIA GPUs and Rosetta2, due to potential challenges with MTLEvents on those platforms, or in older environments where MTLEvents are not supported. */ - MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_METAL_EVENTS = 2, /**< Always use Metal events (MTLEvent) when available on the platform. This will revert to same as MVK_CONFIG_VK_SEMAPHORE_USE_SINGLE_QUEUE in older environments where MTLEvents are not supported. */ - MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_CALLBACK = 3, /**< Use CPU callbacks upon GPU submission completion. This is the slowest technique, but allows multiple queues, compared to MVK_CONFIG_VK_SEMAPHORE_USE_SINGLE_QUEUE. */ - MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_MAX_ENUM = 0x7FFFFFFF -} MVKVkSemaphoreSupportStyle; - -/** Identifies the style of Metal command buffer pre-filling to be used. */ -typedef enum MVKPrefillMetalCommandBuffersStyle { - MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS_STYLE_NO_PREFILL = 0, /**< During Vulkan command buffer filling, do not prefill a Metal command buffer for each Vulkan command buffer. A single Metal command buffer is created and encoded for all the Vulkan command buffers included when vkQueueSubmit() is called. MoltenVK automatically creates and drains a single Metal object autorelease pool when vkQueueSubmit() is called. This is the fastest option, but potentially has the largest memory footprint. */ - MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS_STYLE_DEFERRED_ENCODING = 1, /**< During Vulkan command buffer filling, encode to the Metal command buffer when vkEndCommandBuffer() is called. MoltenVK automatically creates and drains a single Metal object autorelease pool when vkEndCommandBuffer() is called. This option has the fastest performance, and the largest memory footprint, of the prefilling options using autorelease pools. */ - MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS_STYLE_IMMEDIATE_ENCODING = 2, /**< During Vulkan command buffer filling, immediately encode to the Metal command buffer, as each command is submitted to the Vulkan command buffer, and do not retain any command content in the Vulkan command buffer. MoltenVK automatically creates and drains a Metal object autorelease pool for each and every command added to the Vulkan command buffer. This option has the smallest memory footprint, and the slowest performance, of the prefilling options using autorelease pools. */ - MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS_STYLE_IMMEDIATE_ENCODING_NO_AUTORELEASE = 3, /**< During Vulkan command buffer filling, immediately encode to the Metal command buffer, as each command is submitted to the Vulkan command buffer, do not retain any command content in the Vulkan command buffer, and assume the app will ensure that each thread that fills commands into a Vulkan command buffer has a Metal autorelease pool. MoltenVK will not create and drain any autorelease pools during encoding. This is the fastest prefilling option, and generally has a small memory footprint, depending on when the app-provided autorelease pool drains. */ - MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS_STYLE_MAX_ENUM = 0x7FFFFFFF -} MVKPrefillMetalCommandBuffersStyle; - -/** Identifies when Metal shaders will be compiled with the fast math option. */ -typedef enum MVKConfigFastMath { - MVK_CONFIG_FAST_MATH_NEVER = 0, /**< Metal shaders will never be compiled with the fast math option. */ - MVK_CONFIG_FAST_MATH_ALWAYS = 1, /**< Metal shaders will always be compiled with the fast math option. */ - MVK_CONFIG_FAST_MATH_ON_DEMAND = 2, /**< Metal shaders will be compiled with the fast math option, unless the shader includes execution modes that require it to be compiled without fast math. */ - MVK_CONFIG_FAST_MATH_MAX_ENUM = 0x7FFFFFFF -} MVKConfigFastMath; - -/** Identifies available system data compression algorithms. */ -typedef enum MVKConfigCompressionAlgorithm { - MVK_CONFIG_COMPRESSION_ALGORITHM_NONE = 0, /**< No compression. */ - MVK_CONFIG_COMPRESSION_ALGORITHM_LZFSE = 1, /**< Apple proprietary. Good balance of high performance and small compression size, particularly for larger data content. */ - MVK_CONFIG_COMPRESSION_ALGORITHM_ZLIB = 2, /**< Open cross-platform ZLib format. For smaller data content, has better performance and smaller size than LZFSE. */ - MVK_CONFIG_COMPRESSION_ALGORITHM_LZ4 = 3, /**< Fastest performance. Largest compression size. */ - MVK_CONFIG_COMPRESSION_ALGORITHM_LZMA = 4, /**< Slowest performance. Smallest compression size, particular with larger content. */ - MVK_CONFIG_COMPRESSION_ALGORITHM_MAX_ENUM = 0x7FFFFFFF, -} MVKConfigCompressionAlgorithm; - -/** Identifies the style of activity performance logging to use. */ -typedef enum MVKConfigActivityPerformanceLoggingStyle { - MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_FRAME_COUNT = 0, /**< Repeatedly log performance after a configured number of frames. */ - MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_IMMEDIATE = 1, /**< Log immediately after each performance measurement. */ - MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_DEVICE_LIFETIME = 2, /**< Log at the end of the VkDevice lifetime. This is useful for one-shot apps such as testing frameworks. */ - MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_MAX_ENUM = 0x7FFFFFFF, -} MVKConfigActivityPerformanceLoggingStyle; - /** - * MoltenVK configuration settings. + * This header is provided for legacy compatibility only. This header contains obsolete and + * deprecated MoltenVK functions, that were originally part of the obsolete and deprecated + * non-standard VK_MVK_moltenvk extension, and use of this header is not recommended. * - * To be active, some configuration settings must be set before a VkDevice is created. - * See the description of the individual configuration structure members for more information. - * - * There are three mechanisms for setting the values of the MoltenVK configuration parameters: - * - Runtime API via the vkGetMoltenVKConfigurationMVK()/vkSetMoltenVKConfigurationMVK() functions. - * - Application runtime environment variables. - * - Build settings at MoltenVK build time. - * - * To change the MoltenVK configuration settings at runtime using a programmatic API, - * use the vkGetMoltenVKConfigurationMVK() and vkSetMoltenVKConfigurationMVK() functions - * to retrieve, modify, and set a copy of the MVKConfiguration structure. To be active, - * some configuration settings must be set before a VkInstance or VkDevice is created. - * See the description of each member for more information. - * - * The initial value of each of the configuration settings can established at runtime - * by a corresponding environment variable, or if the environment variable is not set, - * by a corresponding build setting at the time MoltenVK is compiled. The environment - * variable and build setting for each configuration parameter share the same name. - * - * For example, the initial value of the shaderConversionFlipVertexY configuration setting - * is set by the MVK_CONFIG_SHADER_CONVERSION_FLIP_VERTEX_Y at runtime, or by the - * MVK_CONFIG_SHADER_CONVERSION_FLIP_VERTEX_Y build setting when MoltenVK is compiled. - * - * This structure may be extended as new features are added to MoltenVK. If you are linking to - * an implementation of MoltenVK that was compiled from a different VK_MVK_MOLTENVK_SPEC_VERSION - * than your app was, the size of this structure in your app may be larger or smaller than the - * struct in MoltenVK. See the description of the vkGetMoltenVKConfigurationMVK() and - * vkSetMoltenVKConfigurationMVK() functions for information about how to handle this. - * - * TO SUPPORT DYNAMIC LINKING TO THIS STRUCTURE AS DESCRIBED ABOVE, THIS STRUCTURE SHOULD NOT - * BE CHANGED EXCEPT TO ADD ADDITIONAL MEMBERS ON THE END. EXISTING MEMBERS, AND THEIR ORDER, - * SHOULD NOT BE CHANGED. - */ -typedef struct { - - /** - * If enabled, debugging capabilities will be enabled, including logging - * shader code during runtime shader conversion. - * - * The value of this parameter may be changed at any time during application runtime, - * and the changed value will immediately effect subsequent MoltenVK behaviour. - * - * The initial value or this parameter is set by the - * MVK_DEBUG - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, the value of this parameter is false if MoltenVK was - * built in Release mode, and true if MoltenVK was built in Debug mode. - */ - VkBool32 debugMode; - - /** - * If enabled, MSL vertex shader code created during runtime shader conversion will - * flip the Y-axis of each vertex, as the Vulkan Y-axis is the inverse of OpenGL. - * - * An alternate way to reverse the Y-axis is to employ a negative Y-axis value on - * the viewport, in which case this parameter can be disabled. - * - * The value of this parameter may be changed at any time during application runtime, - * and the changed value will immediately effect subsequent MoltenVK behaviour. - * Specifically, this parameter can be enabled when compiling some pipelines, - * and disabled when compiling others. Existing pipelines are not automatically - * re-compiled when this parameter is changed. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_SHADER_CONVERSION_FLIP_VERTEX_Y - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, the value of this parameter defaults to true. - */ - VkBool32 shaderConversionFlipVertexY; - - /** - * If enabled, queue command submissions (vkQueueSubmit() & vkQueuePresentKHR()) will be - * processed on the thread that called the submission function. If disabled, processing - * will be dispatched to a GCD dispatch_queue whose priority is determined by - * VkDeviceQueueCreateInfo::pQueuePriorities during vkCreateDevice(). - * - * The value of this parameter must be changed before creating a VkDevice, - * for the change to take effect. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_SYNCHRONOUS_QUEUE_SUBMITS - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, the value of this parameter defaults to true for macOS 10.14 - * and above or iOS 12 and above, and false otherwise. The reason for this distinction - * is that this feature should be disabled when emulation is required to support VkEvents - * because native support for events (MTLEvent) is not available. - */ - VkBool32 synchronousQueueSubmits; - - /** - * If set to MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS_STYLE_NO_PREFILL, a single Metal - * command buffer will be created and filled when the Vulkan command buffers are submitted - * to the Vulkan queue. This allows a single Metal command buffer to be used for all of the - * Vulkan command buffers in a queue submission. The Metal command buffer is filled on the - * thread that processes the command queue submission. - * - * If set to any value other than MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS_STYLE_NO_PREFILL, - * where possible, a Metal command buffer will be created and filled when each Vulkan - * command buffer is filled. For applications that parallelize the filling of Vulkan - * commmand buffers across multiple threads, this allows the Metal command buffers to also - * be filled on the same parallel thread. Because each command buffer is filled separately, - * this requires that each Vulkan command buffer have a dedicated Metal command buffer. - * - * See the definition of the MVKPrefillMetalCommandBuffersStyle enumeration above for - * descriptions of the various values that can be used for this setting. The differences - * are primarily distinguished by how memory recovery is handled for autoreleased Metal - * objects that are created under the covers as the commands added to the Vulkan command - * buffer are encoded into the corresponding Metal command buffer. You can decide whether - * your app will recover all autoreleased Metal objects, or how agressively MoltenVK should - * recover autoreleased Metal objects, based on your approach to command buffer filling. - * - * Depending on the nature of your application, you may find performance is improved by filling - * the Metal command buffers on parallel threads, or you may find that performance is improved by - * consolidating all Vulkan command buffers onto a single Metal command buffer during queue submission. - * - * When enabling this feature, be aware that one Metal command buffer is required for each Vulkan - * command buffer. Depending on the number of command buffers that you use, you may also need to - * change the value of the maxActiveMetalCommandBuffersPerQueue setting. - * - * If this feature is enabled, be aware that if you have recorded commands to a Vulkan command buffer, - * and then choose to reset that command buffer instead of submitting it, the corresponding prefilled - * Metal command buffer will still be submitted. This is because Metal command buffers do not support - * the concept of being reset after being filled. Depending on when and how often you do this, - * it may cause unexpected visual artifacts and unnecessary GPU load. - * - * Prefilling of a Metal command buffer will not occur during the filling of secondary command - * buffers (VK_COMMAND_BUFFER_LEVEL_SECONDARY), or for primary command buffers that are intended - * to be submitted to multiple queues concurrently (VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT). - * - * This feature is incompatible with updating descriptors after binding. If any of the - * *UpdateAfterBind feature flags of VkPhysicalDeviceDescriptorIndexingFeatures or - * VkPhysicalDeviceInlineUniformBlockFeatures have been enabled, the value of this - * setting will be ignored and treated as if it is false. - * - * The value of this parameter may be changed at any time during application runtime, - * and the changed value will immediately effect subsequent MoltenVK behaviour. - * Specifically, this parameter can be enabled when filling some command buffers, - * and disabled when later filling others. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, the value of this parameter defaults to - * MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS_STYLE_NO_PREFILL. - */ - MVKPrefillMetalCommandBuffersStyle prefillMetalCommandBuffers; - - /** - * The maximum number of Metal command buffers that can be concurrently active per Vulkan queue. - * The number of active Metal command buffers required depends on the prefillMetalCommandBuffers - * setting. If prefillMetalCommandBuffers is enabled, one Metal command buffer is required per - * Vulkan command buffer. If prefillMetalCommandBuffers is disabled, one Metal command buffer - * is required per command buffer queue submission, which may be significantly less than the - * number of Vulkan command buffers. - * - * The value of this parameter must be changed before creating a VkDevice, - * for the change to take effect. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_MAX_ACTIVE_METAL_COMMAND_BUFFERS_PER_QUEUE - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, the value of this parameter defaults to 64. - */ - uint32_t maxActiveMetalCommandBuffersPerQueue; - - /** - * Depending on the GPU, Metal allows 8192 or 32768 occlusion queries per MTLBuffer. - * If enabled, MoltenVK allocates a MTLBuffer for each query pool, allowing each query - * pool to support that permitted number of queries. This may slow performance or cause - * unexpected behaviour if the query pool is not established prior to a Metal renderpass, - * or if the query pool is changed within a renderpass. If disabled, one MTLBuffer will - * be shared by all query pools, which improves performance, but limits the total device - * queries to the permitted number. - * - * The value of this parameter may be changed at any time during application runtime, - * and the changed value will immediately effect subsequent MoltenVK behaviour. - * Specifically, this parameter can be enabled when creating some query pools, - * and disabled when creating others. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_SUPPORT_LARGE_QUERY_POOLS - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, the value of this parameter defaults to true. - */ - VkBool32 supportLargeQueryPools; - - /** Obsolete, ignored, and deprecated. All surface presentations are performed with a command buffer. */ - VkBool32 presentWithCommandBuffer; - - /** - * If enabled, swapchain images will use simple Nearest sampling when minifying or magnifying - * the swapchain image to fit a physical display surface. If disabled, swapchain images will - * use Linear sampling when magnifying the swapchain image to fit a physical display surface. - * Enabling this setting avoids smearing effects when swapchain images are simple interger - * multiples of display pixels (eg- macOS Retina, and typical of graphics apps and games), - * but may cause aliasing effects when using non-integer display scaling. - * - * The value of this parameter must be changed before creating a VkSwapchain, - * for the change to take effect. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_SWAPCHAIN_MIN_MAG_FILTER_USE_NEAREST - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, the value of this parameter defaults to true. - */ - VkBool32 swapchainMinMagFilterUseNearest; -#define swapchainMagFilterUseNearest swapchainMinMagFilterUseNearest - - /** - * The maximum amount of time, in nanoseconds, to wait for a Metal library, function, or - * pipeline state object to be compiled and created by the Metal compiler. An internal error - * within the Metal compiler can stall the thread for up to 30 seconds. Setting this value - * limits that delay to a specified amount of time, allowing shader compilations to fail fast. - * - * The value of this parameter may be changed at any time during application runtime, - * and the changed value will immediately effect subsequent MoltenVK behaviour. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_METAL_COMPILE_TIMEOUT - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, the value of this parameter defaults to infinite. - */ - uint64_t metalCompileTimeout; - - /** - * If enabled, performance statistics, as defined by the MVKPerformanceStatistics structure, - * are collected, and can be retrieved via the vkGetPerformanceStatisticsMVK() function. - * - * You can also use the activityPerformanceLoggingStyle and performanceLoggingFrameCount - * parameters to configure when to log the performance statistics collected by this parameter. - * - * The value of this parameter must be changed before creating a VkDevice, - * for the change to take effect. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_PERFORMANCE_TRACKING - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, the value of this parameter defaults to false. - */ - VkBool32 performanceTracking; - - /** - * If non-zero, performance statistics, frame-based statistics will be logged, on a - * repeating cycle, once per this many frames. The performanceTracking parameter must - * also be enabled. If this parameter is zero, or the performanceTracking parameter - * is disabled, no frame-based performance statistics will be logged. - * - * The value of this parameter may be changed at any time during application runtime, - * and the changed value will immediately effect subsequent MoltenVK behaviour. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_PERFORMANCE_LOGGING_FRAME_COUNT - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, the value of this parameter defaults to zero. - */ - uint32_t performanceLoggingFrameCount; - - /** - * If enabled, a MoltenVK logo watermark will be rendered on top of the scene. - * This can be enabled for publicity during demos. - * - * The value of this parameter may be changed at any time during application runtime, - * and the changed value will immediately effect subsequent MoltenVK behaviour. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_DISPLAY_WATERMARK - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, the value of this parameter defaults to false. - */ - VkBool32 displayWatermark; - - /** - * Metal does not distinguish functionality between queues, which would normally mean only - * a single general-purpose queue family with multiple queues is needed. However, Vulkan - * associates command buffers with a queue family, whereas Metal associates command buffers - * with a specific Metal queue. In order to allow a Metal command buffer to be prefilled - * before is is formally submitted to a Vulkan queue, each Vulkan queue family can support - * only a single Metal queue. As a result, in order to provide parallel queue operations, - * MoltenVK provides multiple queue families, each with a single queue. - * - * If this parameter is disabled, all queue families will be advertised as having general-purpose - * graphics + compute + transfer functionality, which is how the actual Metal queues behave. - * - * If this parameter is enabled, one queue family will be advertised as having general-purpose - * graphics + compute + transfer functionality, and the remaining queue families will be advertised - * as having specialized graphics OR compute OR transfer functionality, to make it easier for some - * apps to select a queue family with the appropriate requirements. - * - * The value of this parameter must be changed before creating a VkDevice, and before - * querying a VkPhysicalDevice for queue family properties, for the change to take effect. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_SPECIALIZED_QUEUE_FAMILIES - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, the value of this parameter defaults to false. - */ - VkBool32 specializedQueueFamilies; - - /** - * If enabled, when the app creates a VkDevice from a VkPhysicalDevice (GPU) that is neither - * headless nor low-power, and is different than the GPU used by the windowing system, the - * windowing system will be forced to switch to use the GPU selected by the Vulkan app. - * When the Vulkan app is ended, the windowing system will automatically switch back to - * using the previous GPU, depending on the usage requirements of other running apps. - * - * If disabled, the Vulkan app will render using its selected GPU, and if the windowing - * system uses a different GPU, the windowing system compositor will automatically copy - * framebuffer content from the app GPU to the windowing system GPU. - * - * The value of this parmeter has no effect on systems with a single GPU, or when the - * Vulkan app creates a VkDevice from a low-power or headless VkPhysicalDevice (GPU). - * - * Switching the windowing system GPU to match the Vulkan app GPU maximizes app performance, - * because it avoids the windowing system compositor from having to copy framebuffer content - * between GPUs on each rendered frame. However, doing so forces the entire system to - * potentially switch to using a GPU that may consume more power while the app is running. - * - * Some Vulkan apps may want to render using a high-power GPU, but leave it up to the - * system window compositor to determine how best to blend content with the windowing - * system, and as a result, may want to disable this parameter. - * - * The value of this parameter must be changed before creating a VkDevice, - * for the change to take effect. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_SWITCH_SYSTEM_GPU - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, the value of this parameter defaults to true. - */ - VkBool32 switchSystemGPU; - - /** - * Older versions of Metal do not natively support per-texture swizzling. When running on - * such a system, and this parameter is enabled, arbitrary VkImageView component swizzles - * are supported, as defined in VkImageViewCreateInfo::components when creating a VkImageView. - * - * If disabled, and native Metal per-texture swizzling is not available on the platform, - * a very limited set of VkImageView component swizzles are supported via format substitutions. - * - * If Metal supports native per-texture swizzling, this parameter is ignored. - * - * When running on an older version of Metal that does not support native per-texture - * swizzling, if this parameter is enabled, both when a VkImageView is created, and - * when any pipeline that uses that VkImageView is compiled, VkImageView swizzling is - * automatically performed in the converted Metal shader code during all texture sampling - * and reading operations, regardless of whether a swizzle is required for the VkImageView - * associated with the Metal texture. This may result in reduced performance. - * - * The value of this parameter may be changed at any time during application runtime, - * and the changed value will immediately effect subsequent MoltenVK behaviour. - * Specifically, this parameter can be enabled when creating VkImageViews that need it, - * and compiling pipelines that use those VkImageViews, and can be disabled when creating - * VkImageViews that don't need it, and compiling pipelines that use those VkImageViews. - * - * Existing pipelines are not automatically re-compiled when this parameter is changed. - * - * An error is logged and returned during VkImageView creation if that VkImageView - * requires full image view swizzling and this feature is not enabled. An error is - * also logged when a pipeline that was not compiled with full image view swizzling - * is presented with a VkImageView that is expecting it. - * - * An error is also retuned and logged when a VkPhysicalDeviceImageFormatInfo2KHR is passed - * in a call to vkGetPhysicalDeviceImageFormatProperties2KHR() to query for an VkImageView - * format that will require full swizzling to be enabled, and this feature is not enabled. - * - * If this parameter is disabled, and native Metal per-texture swizzling is not available - * on the platform, the following limited set of VkImageView swizzles are supported by - * MoltenVK, via automatic format substitution: - * - * Texture format Swizzle - * -------------- ------- - * VK_FORMAT_R8_UNORM ZERO, ANY, ANY, RED - * VK_FORMAT_A8_UNORM ALPHA, ANY, ANY, ZERO - * VK_FORMAT_R8G8B8A8_UNORM BLUE, GREEN, RED, ALPHA - * VK_FORMAT_R8G8B8A8_SRGB BLUE, GREEN, RED, ALPHA - * VK_FORMAT_B8G8R8A8_UNORM BLUE, GREEN, RED, ALPHA - * VK_FORMAT_B8G8R8A8_SRGB BLUE, GREEN, RED, ALPHA - * VK_FORMAT_D32_SFLOAT_S8_UINT RED, ANY, ANY, ANY (stencil only) - * VK_FORMAT_D24_UNORM_S8_UINT RED, ANY, ANY, ANY (stencil only) - * - * The initial value or this parameter is set by the - * MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, the value of this parameter defaults to false. - */ - VkBool32 fullImageViewSwizzle; - - /** - * The index of the queue family whose presentation submissions will - * be used as the default GPU Capture Scope during debugging in Xcode. - * - * The value of this parameter must be changed before creating a VkDevice, - * for the change to take effect. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_DEFAULT_GPU_CAPTURE_SCOPE_QUEUE_FAMILY_INDEX - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, the value of this parameter defaults to zero (the first queue family). - */ - uint32_t defaultGPUCaptureScopeQueueFamilyIndex; - - /** - * The index of the queue, within the queue family identified by the - * defaultGPUCaptureScopeQueueFamilyIndex parameter, whose presentation submissions - * will be used as the default GPU Capture Scope during debugging in Xcode. - * - * The value of this parameter must be changed before creating a VkDevice, - * for the change to take effect. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_DEFAULT_GPU_CAPTURE_SCOPE_QUEUE_INDEX - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, the value of this parameter defaults to zero (the first queue). - */ - uint32_t defaultGPUCaptureScopeQueueIndex; - - /** - * Identifies when Metal shaders will be compiled with the Metal fastMathEnabled property - * enabled. For shaders compiled with the Metal fastMathEnabled property enabled, shader - * floating point math is significantly faster, but it may cause the Metal Compiler to - * optimize floating point operations in ways that may violate the IEEE 754 standard. - * - * Enabling Metal fast math can dramatically improve shader performance, and has little - * practical effect on the numerical accuracy of most shaders. As such, disabling fast - * math should be done carefully and deliberately. For most applications, always enabling - * fast math, by setting the value of this property to MVK_CONFIG_FAST_MATH_ALWAYS, - * is the preferred choice. - * - * Apps that have specific accuracy and handling needs for particular shaders, may elect to - * set the value of this property to MVK_CONFIG_FAST_MATH_ON_DEMAND, so that fast math will - * be disabled when compiling shaders that request capabilities such as SignedZeroInfNanPreserve. - * - * The value of this parameter may be changed at any time during application runtime, - * and the changed value will be applied to future Metal shader compilations. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_FAST_MATH_ENABLED - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, the value of this parameter defaults to MVK_CONFIG_FAST_MATH_ALWAYS. - */ - MVKConfigFastMath fastMathEnabled; - - /** - * Controls the level of logging performned by MoltenVK. - * - * The value of this parameter may be changed at any time during application runtime, - * and the changed value will immediately effect subsequent MoltenVK behaviour. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_LOG_LEVEL - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, errors and informational messages are logged. - */ - MVKConfigLogLevel logLevel; - - /** - * Causes MoltenVK to log the name of each Vulkan call made by the application, - * along with the Mach thread ID, global system thread ID, and thread name. - * - * The value of this parameter may be changed at any time during application runtime, - * and the changed value will immediately effect subsequent MoltenVK behaviour. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_TRACE_VULKAN_CALLS - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, no Vulkan call logging will occur. - */ - MVKConfigTraceVulkanCalls traceVulkanCalls; - - /** - * Force MoltenVK to use a low-power GPU, if one is availble on the device. - * - * The value of this parameter must be changed before creating a VkInstance, - * for the change to take effect. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_FORCE_LOW_POWER_GPU - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, this setting is disabled by default, allowing both - * low-power and high-power GPU's to be used. - */ - VkBool32 forceLowPowerGPU; - - /** Deprecated. Vulkan sempphores using MTLFence are no longer supported. Use semaphoreSupportStyle instead. */ - VkBool32 semaphoreUseMTLFence; - - /** - * Determines the style used to implement Vulkan semaphore (VkSemaphore) functionality in Metal. - * See the documentation of the MVKVkSemaphoreSupportStyle for the options. - * - * In the special case of VK_SEMAPHORE_TYPE_TIMELINE semaphores, MoltenVK will always use - * MTLSharedEvent if it is available on the platform, regardless of the value of this parameter. - * - * The value of this parameter must be changed before creating a VkInstance, - * for the change to take effect. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, this setting is set to - * MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_METAL_EVENTS_WHERE_SAFE by default, - * and MoltenVK will use MTLEvent, except on NVIDIA GPU and Rosetta2 environments, - * or where MTLEvents are not supported, where it will use a single queue with - * implicit synchronization (as if this parameter was set to - * MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_SINGLE_QUEUE). - * - * This parameter interacts with the deprecated legacy parameters semaphoreUseMTLEvent - * and semaphoreUseMTLFence. If semaphoreUseMTLEvent is enabled, this parameter will be - * set to MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_METAL_EVENTS_WHERE_SAFE. - * If semaphoreUseMTLEvent is disabled, this parameter will be set to - * MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_SINGLE_QUEUE if semaphoreUseMTLFence is enabled, - * or MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE_CALLBACK if semaphoreUseMTLFence is disabled. - * Structurally, this parameter replaces, and is aliased by, semaphoreUseMTLEvent. - */ - MVKVkSemaphoreSupportStyle semaphoreSupportStyle; -#define semaphoreUseMTLEvent semaphoreSupportStyle - - /** - * Controls whether Metal should run an automatic GPU capture without the user having to - * trigger it manually via the Xcode user interface, and controls the scope under which - * that GPU capture will occur. This is useful when trying to capture a one-shot GPU trace, - * such as when running a Vulkan CTS test case. For the automatic GPU capture to occur, the - * Xcode scheme under which the app is run must have the Metal GPU capture option enabled. - * This parameter should not be set to manually trigger a GPU capture via the Xcode user interface. - * - * When the value of this parameter is MVK_CONFIG_AUTO_GPU_CAPTURE_SCOPE_FRAME, - * the queue for which the GPU activity is captured is identifed by the values of - * the defaultGPUCaptureScopeQueueFamilyIndex and defaultGPUCaptureScopeQueueIndex - * configuration parameters. - * - * The value of this parameter must be changed before creating a VkDevice, - * for the change to take effect. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_AUTO_GPU_CAPTURE_SCOPE - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, no automatic GPU capture will occur. - */ - MVKConfigAutoGPUCaptureScope autoGPUCaptureScope; - - /** - * The path to a file where the automatic GPU capture should be saved, if autoGPUCaptureScope - * is enabled. In this case, the Xcode scheme need not have Metal GPU capture enabled, and in - * fact the app need not be run under Xcode's control at all. This is useful in case the app - * cannot be run under Xcode's control. A path starting with '~' can be used to place it in a - * user's home directory, as in the shell. This feature requires Metal 3.0 (macOS 10.15, iOS 13). - * - * If this parameter is NULL or an empty string, and autoGPUCaptureScope is enabled, automatic - * GPU capture will be handled by the Xcode user interface. - * - * The value of this parameter must be changed before creating a VkDevice, - * for the change to take effect. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_AUTO_GPU_CAPTURE_OUTPUT_FILE - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, automatic GPU capture will be handled by the Xcode user interface. - */ - const char* autoGPUCaptureOutputFilepath; - - /** - * Controls whether MoltenVK should use a Metal 2D texture with a height of 1 for a - * Vulkan 1D image, or use a native Metal 1D texture. Metal imposes significant restrictions - * on native 1D textures, including not being renderable, clearable, or permitting mipmaps. - * Using a Metal 2D texture allows Vulkan 1D textures to support this additional functionality. - * - * The value of this parameter should only be changed before creating the VkInstance. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_TEXTURE_1D_AS_2D - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, this setting is enabled by default, and MoltenVK will - * use a Metal 2D texture for each Vulkan 1D image. - */ - VkBool32 texture1DAs2D; - - /** - * Controls whether MoltenVK should preallocate memory in each VkDescriptorPool according - * to the values of the VkDescriptorPoolSize parameters. Doing so may improve descriptor set - * allocation performance and memory stability at a cost of preallocated application memory. - * If this setting is disabled, the descriptors required for a descriptor set will be individually - * dynamically allocated in application memory when the descriptor set itself is allocated. - * - * The value of this parameter may be changed at any time during application runtime, and the - * changed value will affect the behavior of VkDescriptorPools created after the value is changed. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_PREALLOCATE_DESCRIPTORS - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, this setting is enabled by default, and MoltenVK will - * allocate a pool of descriptors when a VkDescriptorPool is created. - */ - VkBool32 preallocateDescriptors; - - /** - * Controls whether MoltenVK should use pools to manage memory used when adding commands - * to command buffers. If this setting is enabled, MoltenVK will use a pool to hold command - * resources for reuse during command execution. If this setting is disabled, command memory - * is allocated and destroyed each time a command is executed. This is a classic time-space - * trade off. When command pooling is active, the memory in the pool can be cleared via a - * call to the vkTrimCommandPoolKHR() command. - * - * The value of this parameter may be changed at any time during application runtime, - * and the changed value will immediately effect behavior of VkCommandPools created - * after the setting is changed. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_USE_COMMAND_POOLING - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, this setting is enabled by default, and MoltenVK will pool command memory. - */ - VkBool32 useCommandPooling; - - /** - * Controls whether MoltenVK should use MTLHeaps for allocating textures and buffers - * from device memory. If this setting is enabled, and placement MTLHeaps are - * available on the platform, MoltenVK will allocate a placement MTLHeap for each VkDeviceMemory - * instance, and allocate textures and buffers from that placement heap. If this environment - * variable is disabled, MoltenVK will allocate textures and buffers from general device memory. - * - * Apple recommends that MTLHeaps should only be used for specific requirements such as aliasing - * or hazard tracking, and MoltenVK testing has shown that allocating multiple textures of - * different types or usages from one MTLHeap can occassionally cause corruption issues under - * certain circumstances. - * - * The value of this parameter must be changed before creating a VkInstance, - * for the change to take effect. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_USE_MTLHEAP - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, this setting is disabled by default, and MoltenVK - * will allocate texures and buffers from general device memory. - */ - VkBool32 useMTLHeap; - - /** - * Controls when MoltenVK should log activity performance events. - * - * The value of this parameter must be changed before creating a VkDevice, - * for the change to take effect. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, this setting is set to - * MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_FRAME_COUNT by default, - * and activity performance will be logged when frame activity is logged. - */ - MVKConfigActivityPerformanceLoggingStyle activityPerformanceLoggingStyle; -#define logActivityPerformanceInline activityPerformanceLoggingStyle - - /** - * Controls the Vulkan API version that MoltenVK should advertise in vkEnumerateInstanceVersion(). - * When reading this value, it will be one of the VK_API_VERSION_1_* values, including the latest - * VK_HEADER_VERSION component. When setting this value, it should be set to one of: - * - * VK_API_VERSION_1_2 (equivalent decimal number 4202496) - * VK_API_VERSION_1_1 (equivalent decimal number 4198400) - * VK_API_VERSION_1_0 (equivalent decimal number 4194304) - * - * MoltenVK will automatically add the VK_HEADER_VERSION component. - * - * The value of this parameter must be changed before creating a VkInstance, - * for the change to take effect. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_API_VERSION_TO_ADVERTISE - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, the value of this parameter defaults to the highest API version - * currently supported by MoltenVK, including the latest VK_HEADER_VERSION component. - */ - uint32_t apiVersionToAdvertise; - - /** - * Controls which extensions MoltenVK should advertise it supports in - * vkEnumerateInstanceExtensionProperties() and vkEnumerateDeviceExtensionProperties(). - * The value of this parameter is a bitwise OR of values from the MVKConfigAdvertiseExtensionBits - * enumeration. Any prerequisite extensions are also advertised. - * If the flag MVK_CONFIG_ADVERTISE_EXTENSIONS_ALL is included, all supported extensions - * will be advertised. A value of zero means no extensions will be advertised. - * - * The value of this parameter must be changed before creating a VkInstance, - * for the change to take effect. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_ADVERTISE_EXTENSIONS - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, the value of this setting defaults to - * MVK_CONFIG_ADVERTISE_EXTENSIONS_ALL, and all supported extensions will be advertised. - */ - MVKConfigAdvertiseExtensions advertiseExtensions; - - /** - * Controls whether MoltenVK should treat a lost VkDevice as resumable, unless the - * corresponding VkPhysicalDevice has also been lost. The VK_ERROR_DEVICE_LOST error has - * a broad definitional range, and can mean anything from a GPU hiccup on the current - * command buffer submission, to a physically removed GPU. In the case where this error does - * not impact the VkPhysicalDevice, Vulkan requires that the app destroy and re-create a new - * VkDevice. However, not all apps (including CTS) respect that requirement, leading to what - * might be a transient command submission failure causing an unexpected catastrophic app failure. - * - * If this setting is enabled, in the case of a VK_ERROR_DEVICE_LOST error that does NOT impact - * the VkPhysicalDevice, MoltenVK will log the error, but will not mark the VkDevice as lost, - * allowing the VkDevice to continue to be used. If this setting is disabled, MoltenVK will - * mark the VkDevice as lost, and subsequent use of that VkDevice will be reduced or prohibited. - * - * The value of this parameter may be changed at any time during application runtime, - * and the changed value will affect the error behavior of subsequent command submissions. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_RESUME_LOST_DEVICE - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, this setting is disabled by default, and MoltenVK - * will mark the VkDevice as lost when a command submission failure occurs. - */ - VkBool32 resumeLostDevice; - - /** - * Controls whether MoltenVK should use Metal argument buffers for resources defined in - * descriptor sets, if Metal argument buffers are supported on the platform. Using Metal - * argument buffers dramatically increases the number of buffers, textures and samplers - * that can be bound to a pipeline shader, and in most cases improves performance. - * This setting is an enumeration that specifies the conditions under which MoltenVK - * will use Metal argument buffers. - * - * NOTE: Currently, Metal argument buffer support is in beta stage, and is only supported - * on macOS 11.0 (Big Sur) or later, or on older versions of macOS using an Intel GPU. - * Metal argument buffers support is not available on iOS. Development to support iOS - * and a wider combination of GPU's on older macOS versions is under way. - * - * The value of this parameter must be changed before creating a VkDevice, - * for the change to take effect. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, this setting is set to - * MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS_NEVER by default, - * and MoltenVK will not use Metal argument buffers. - */ - MVKUseMetalArgumentBuffers useMetalArgumentBuffers; - - /** - * Controls the type of compression to use on the MSL source code that is stored in memory - * for use in a pipeline cache. After being converted from SPIR-V, or loaded directly into - * a VkShaderModule, and then compiled into a MTLLibrary, the MSL source code is no longer - * needed for operation, but it is retained so it can be written out as part of a pipeline - * cache export. When a large number of shaders are loaded, this can consume significant - * memory. In such a case, this parameter can be used to compress the MSL source code that - * is awaiting export as part of a pipeline cache. - * - * The value of this parameter can be changed at any time, and will affect the size of - * the cached MSL from subsequent shader compilations. - * - * The initial value or this parameter is set by the - * MVK_CONFIG_SHADER_COMPRESSION_ALGORITHM - * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, this setting is set to - * MVK_CONFIG_COMPRESSION_ALGORITHM_NONE by default, - * and MoltenVK will not compress the MSL source code after compilation into a MTLLibrary. - */ - MVKConfigCompressionAlgorithm shaderSourceCompressionAlgorithm; - -} MVKConfiguration; - -/** Identifies the type of rounding Metal uses for float to integer conversions in particular calculatons. */ -typedef enum MVKFloatRounding { - MVK_FLOAT_ROUNDING_NEAREST = 0, /**< Metal rounds to nearest. */ - MVK_FLOAT_ROUNDING_UP = 1, /**< Metal rounds towards positive infinity. */ - MVK_FLOAT_ROUNDING_DOWN = 2, /**< Metal rounds towards negative infinity. */ - MVK_FLOAT_ROUNDING_UP_MAX_ENUM = 0x7FFFFFFF -} MVKFloatRounding; - -/** Identifies the pipeline points where GPU counter sampling can occur. Maps to MTLCounterSamplingPoint. */ -typedef enum MVKCounterSamplingBits { - MVK_COUNTER_SAMPLING_AT_DRAW = 0x00000001, - MVK_COUNTER_SAMPLING_AT_DISPATCH = 0x00000002, - MVK_COUNTER_SAMPLING_AT_BLIT = 0x00000004, - MVK_COUNTER_SAMPLING_AT_PIPELINE_STAGE = 0x00000008, - MVK_COUNTER_SAMPLING_MAX_ENUM = 0X7FFFFFFF -} MVKCounterSamplingBits; -typedef VkFlags MVKCounterSamplingFlags; - -/** - * Features provided by the current implementation of Metal on the current device. You can - * retrieve a copy of this structure using the vkGetPhysicalDeviceMetalFeaturesMVK() function. + * Instead, in your application, use the following header file: * - * This structure may be extended as new features are added to MoltenVK. If you are linking to - * an implementation of MoltenVK that was compiled from a different VK_MVK_MOLTENVK_SPEC_VERSION - * than your app was, the size of this structure in your app may be larger or smaller than the - * struct in MoltenVK. See the description of the vkGetPhysicalDeviceMetalFeaturesMVK() function - * for information about how to handle this. + * #include * - * TO SUPPORT DYNAMIC LINKING TO THIS STRUCTURE AS DESCRIBED ABOVE, THIS STRUCTURE SHOULD NOT - * BE CHANGED EXCEPT TO ADD ADDITIONAL MEMBERS ON THE END. EXISTING MEMBERS, AND THEIR ORDER, - * SHOULD NOT BE CHANGED. - */ -typedef struct { - uint32_t mslVersion; /**< The version of the Metal Shading Language available on this device. The format of the integer is MMmmpp, with two decimal digts each for Major, minor, and patch version values (eg. MSL 1.2 would appear as 010200). */ - VkBool32 indirectDrawing; /**< If true, draw calls support parameters held in a GPU buffer. */ - VkBool32 baseVertexInstanceDrawing; /**< If true, draw calls support specifiying the base vertex and instance. */ - uint32_t dynamicMTLBufferSize; /**< If greater than zero, dynamic MTLBuffers for setting vertex, fragment, and compute bytes are supported, and their content must be below this value. */ - VkBool32 shaderSpecialization; /**< If true, shader specialization (aka Metal function constants) is supported. */ - VkBool32 ioSurfaces; /**< If true, VkImages can be underlaid by IOSurfaces via the vkUseIOSurfaceMVK() function, to support inter-process image transfers. */ - VkBool32 texelBuffers; /**< If true, texel buffers are supported, allowing the contents of a buffer to be interpreted as an image via a VkBufferView. */ - VkBool32 layeredRendering; /**< If true, layered rendering to multiple cube or texture array layers is supported. */ - VkBool32 presentModeImmediate; /**< If true, immediate surface present mode (VK_PRESENT_MODE_IMMEDIATE_KHR), allowing a swapchain image to be presented immediately, without waiting for the vertical sync period of the display, is supported. */ - VkBool32 stencilViews; /**< If true, stencil aspect views are supported through the MTLPixelFormatX24_Stencil8 and MTLPixelFormatX32_Stencil8 formats. */ - VkBool32 multisampleArrayTextures; /**< If true, MTLTextureType2DMultisampleArray is supported. */ - VkBool32 samplerClampToBorder; /**< If true, the border color set when creating a sampler will be respected. */ - uint32_t maxTextureDimension; /**< The maximum size of each texture dimension (width, height, or depth). */ - uint32_t maxPerStageBufferCount; /**< The total number of per-stage Metal buffers available for shader uniform content and attributes. */ - uint32_t maxPerStageTextureCount; /**< The total number of per-stage Metal textures available for shader uniform content. */ - uint32_t maxPerStageSamplerCount; /**< The total number of per-stage Metal samplers available for shader uniform content. */ - VkDeviceSize maxMTLBufferSize; /**< The max size of a MTLBuffer (in bytes). */ - VkDeviceSize mtlBufferAlignment; /**< The alignment used when allocating memory for MTLBuffers. Must be PoT. */ - VkDeviceSize maxQueryBufferSize; /**< The maximum size of an occlusion query buffer (in bytes). */ - VkDeviceSize mtlCopyBufferAlignment; /**< The alignment required during buffer copy operations (in bytes). */ - VkSampleCountFlags supportedSampleCounts; /**< A bitmask identifying the sample counts supported by the device. */ - uint32_t minSwapchainImageCount; /**< The minimum number of swapchain images that can be supported by a surface. */ - uint32_t maxSwapchainImageCount; /**< The maximum number of swapchain images that can be supported by a surface. */ - VkBool32 combinedStoreResolveAction; /**< If true, the device supports VK_ATTACHMENT_STORE_OP_STORE with a simultaneous resolve attachment. */ - VkBool32 arrayOfTextures; /**< If true, arrays of textures is supported. */ - VkBool32 arrayOfSamplers; /**< If true, arrays of texture samplers is supported. */ - MTLLanguageVersion mslVersionEnum; /**< The version of the Metal Shading Language available on this device, as a Metal enumeration. */ - VkBool32 depthSampleCompare; /**< If true, depth texture samplers support the comparison of the pixel value against a reference value. */ - VkBool32 events; /**< If true, Metal synchronization events (MTLEvent) are supported. */ - VkBool32 memoryBarriers; /**< If true, full memory barriers within Metal render passes are supported. */ - VkBool32 multisampleLayeredRendering; /**< If true, layered rendering to multiple multi-sampled cube or texture array layers is supported. */ - VkBool32 stencilFeedback; /**< If true, fragment shaders that write to [[stencil]] outputs are supported. */ - VkBool32 textureBuffers; /**< If true, textures of type MTLTextureTypeBuffer are supported. */ - VkBool32 postDepthCoverage; /**< If true, coverage masks in fragment shaders post-depth-test are supported. */ - VkBool32 fences; /**< If true, Metal synchronization fences (MTLFence) are supported. */ - VkBool32 rasterOrderGroups; /**< If true, Raster order groups in fragment shaders are supported. */ - VkBool32 native3DCompressedTextures; /**< If true, 3D compressed images are supported natively, without manual decompression. */ - VkBool32 nativeTextureSwizzle; /**< If true, component swizzle is supported natively, without manual swizzling in shaders. */ - VkBool32 placementHeaps; /**< If true, MTLHeap objects support placement of resources. */ - VkDeviceSize pushConstantSizeAlignment; /**< The alignment used internally when allocating memory for push constants. Must be PoT. */ - uint32_t maxTextureLayers; /**< The maximum number of layers in an array texture. */ - uint32_t maxSubgroupSize; /**< The maximum number of threads in a SIMD-group. */ - VkDeviceSize vertexStrideAlignment; /**< The alignment used for the stride of vertex attribute bindings. */ - VkBool32 indirectTessellationDrawing; /**< If true, tessellation draw calls support parameters held in a GPU buffer. */ - VkBool32 nonUniformThreadgroups; /**< If true, the device supports arbitrary-sized grids in compute workloads. */ - VkBool32 renderWithoutAttachments; /**< If true, we don't have to create a dummy attachment for a render pass if there isn't one. */ - VkBool32 deferredStoreActions; /**< If true, render pass store actions can be specified after the render encoder is created. */ - VkBool32 sharedLinearTextures; /**< If true, linear textures and texture buffers can be created from buffers in Shared storage. */ - VkBool32 depthResolve; /**< If true, resolving depth textures with filters other than Sample0 is supported. */ - VkBool32 stencilResolve; /**< If true, resolving stencil textures with filters other than Sample0 is supported. */ - uint32_t maxPerStageDynamicMTLBufferCount; /**< The maximum number of inline buffers that can be set on a command buffer. */ - uint32_t maxPerStageStorageTextureCount; /**< The total number of per-stage Metal textures with read-write access available for writing to from a shader. */ - VkBool32 astcHDRTextures; /**< If true, ASTC HDR pixel formats are supported. */ - VkBool32 renderLinearTextures; /**< If true, linear textures are renderable. */ - VkBool32 pullModelInterpolation; /**< If true, explicit interpolation functions are supported. */ - VkBool32 samplerMirrorClampToEdge; /**< If true, the mirrored clamp to edge address mode is supported in samplers. */ - VkBool32 quadPermute; /**< If true, quadgroup permutation functions (vote, ballot, shuffle) are supported in shaders. */ - VkBool32 simdPermute; /**< If true, SIMD-group permutation functions (vote, ballot, shuffle) are supported in shaders. */ - VkBool32 simdReduction; /**< If true, SIMD-group reduction functions (arithmetic) are supported in shaders. */ - uint32_t minSubgroupSize; /**< The minimum number of threads in a SIMD-group. */ - VkBool32 textureBarriers; /**< If true, texture barriers are supported within Metal render passes. */ - VkBool32 tileBasedDeferredRendering; /**< If true, this device uses tile-based deferred rendering. */ - VkBool32 argumentBuffers; /**< If true, Metal argument buffers are supported. */ - VkBool32 descriptorSetArgumentBuffers; /**< If true, a Metal argument buffer can be assigned to a descriptor set, and used on any pipeline and pipeline stage. If false, a different Metal argument buffer must be used for each pipeline-stage/descriptor-set combination. */ - MVKFloatRounding clearColorFloatRounding; /**< Identifies the type of rounding Metal uses for MTLClearColor float to integer conversions. */ - MVKCounterSamplingFlags counterSamplingPoints; /**< Identifies the points where pipeline GPU counter sampling may occur. */ - VkBool32 programmableSamplePositions; /**< If true, programmable MSAA sample positions are supported. */ - VkBool32 shaderBarycentricCoordinates; /**< If true, fragment shader barycentric coordinates are supported. */ - MTLArgumentBuffersTier argumentBuffersTier; /**< The argument buffer tier available on this device, as a Metal enumeration. */ - VkBool32 needsSampleDrefLodArrayWorkaround; /**< If true, sampling from arrayed depth images with explicit LoD is broken and needs a workaround. */ - VkDeviceSize hostMemoryPageSize; /**< The size of a page of host memory on this platform. */ -} MVKPhysicalDeviceMetalFeatures; - -/** MoltenVK performance of a particular type of activity. */ -typedef struct { - uint32_t count; /**< The number of activities of this type. */ - double latestDuration; /**< The latest (most recent) duration of the activity, in milliseconds. */ - double averageDuration; /**< The average duration of the activity, in milliseconds. */ - double minimumDuration; /**< The minimum duration of the activity, in milliseconds. */ - double maximumDuration; /**< The maximum duration of the activity, in milliseconds. */ -} MVKPerformanceTracker; - -/** MoltenVK performance of shader compilation activities. */ -typedef struct { - MVKPerformanceTracker hashShaderCode; /** Create a hash from the incoming shader code. */ - MVKPerformanceTracker spirvToMSL; /** Convert SPIR-V to MSL source code. */ - MVKPerformanceTracker mslCompile; /** Compile MSL source code into a MTLLibrary. */ - MVKPerformanceTracker mslLoad; /** Load pre-compiled MSL code into a MTLLibrary. */ - MVKPerformanceTracker mslCompress; /** Compress MSL source code after compiling a MTLLibrary, to hold it in a pipeline cache. */ - MVKPerformanceTracker mslDecompress; /** Decompress MSL source code to write the MSL when serializing a pipeline cache. */ - MVKPerformanceTracker shaderLibraryFromCache; /** Retrieve a shader library from the cache, lazily creating it if needed. */ - MVKPerformanceTracker functionRetrieval; /** Retrieve a MTLFunction from a MTLLibrary. */ - MVKPerformanceTracker functionSpecialization; /** Specialize a retrieved MTLFunction. */ - MVKPerformanceTracker pipelineCompile; /** Compile MTLFunctions into a pipeline. */ - MVKPerformanceTracker glslToSPRIV; /** Convert GLSL to SPIR-V code. */ -} MVKShaderCompilationPerformance; - -/** MoltenVK performance of pipeline cache activities. */ -typedef struct { - MVKPerformanceTracker sizePipelineCache; /** Calculate the size of cache data required to write MSL to pipeline cache data stream. */ - MVKPerformanceTracker writePipelineCache; /** Write MSL to pipeline cache data stream. */ - MVKPerformanceTracker readPipelineCache; /** Read MSL from pipeline cache data stream. */ -} MVKPipelineCachePerformance; - -/** MoltenVK performance of queue activities. */ -typedef struct { - MVKPerformanceTracker mtlQueueAccess; /** Create an MTLCommandQueue or access an existing cached instance. */ - MVKPerformanceTracker mtlCommandBufferCompletion; /** Completion of a MTLCommandBuffer on the GPU, from commit to completion callback. */ - MVKPerformanceTracker nextCAMetalDrawable; /** Retrieve next CAMetalDrawable from CAMetalLayer during presentation. */ - MVKPerformanceTracker frameInterval; /** Frame presentation interval (1000/FPS). */ -} MVKQueuePerformance; - -/** - * MoltenVK performance. You can retrieve a copy of this structure using the vkGetPerformanceStatisticsMVK() function. + * And if you require the MoltenVK Configuration API, also include the following header file: * - * This structure may be extended as new features are added to MoltenVK. If you are linking to - * an implementation of MoltenVK that was compiled from a different VK_MVK_MOLTENVK_SPEC_VERSION - * than your app was, the size of this structure in your app may be larger or smaller than the - * struct in MoltenVK. See the description of the vkGetPerformanceStatisticsMVK() function for - * information about how to handle this. + * #include * - * TO SUPPORT DYNAMIC LINKING TO THIS STRUCTURE AS DESCRIBED ABOVE, THIS STRUCTURE SHOULD NOT - * BE CHANGED EXCEPT TO ADD ADDITIONAL MEMBERS ON THE END. EXISTING MEMBERS, AND THEIR ORDER, - * SHOULD NOT BE CHANGED. + * If you require access to Metal objects underlying equivalent Vulkan objects, + * use the standard Vulkan VK_EXT_metal_objects extension. */ -typedef struct { - MVKShaderCompilationPerformance shaderCompilation; /** Shader compilations activities. */ - MVKPipelineCachePerformance pipelineCache; /** Pipeline cache activities. */ - MVKQueuePerformance queue; /** Queue activities. */ -} MVKPerformanceStatistics; - - -#pragma mark - -#pragma mark Function types -typedef VkResult (VKAPI_PTR *PFN_vkGetMoltenVKConfigurationMVK)(VkInstance ignored, MVKConfiguration* pConfiguration, size_t* pConfigurationSize); -typedef VkResult (VKAPI_PTR *PFN_vkSetMoltenVKConfigurationMVK)(VkInstance ignored, const MVKConfiguration* pConfiguration, size_t* pConfigurationSize); -typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceMetalFeaturesMVK)(VkPhysicalDevice physicalDevice, MVKPhysicalDeviceMetalFeatures* pMetalFeatures, size_t* pMetalFeaturesSize); -typedef VkResult (VKAPI_PTR *PFN_vkGetPerformanceStatisticsMVK)(VkDevice device, MVKPerformanceStatistics* pPerf, size_t* pPerfSize); -typedef void (VKAPI_PTR *PFN_vkGetVersionStringsMVK)(char* pMoltenVersionStringBuffer, uint32_t moltenVersionStringBufferLength, char* pVulkanVersionStringBuffer, uint32_t vulkanVersionStringBufferLength); -typedef void (VKAPI_PTR *PFN_vkSetWorkgroupSizeMVK)(VkShaderModule shaderModule, uint32_t x, uint32_t y, uint32_t z); -typedef VkResult (VKAPI_PTR *PFN_vkUseIOSurfaceMVK)(VkImage image, IOSurfaceRef ioSurface); -typedef void (VKAPI_PTR *PFN_vkGetIOSurfaceMVK)(VkImage image, IOSurfaceRef* pIOSurface); - -#ifdef __OBJC__ -typedef void (VKAPI_PTR *PFN_vkGetMTLDeviceMVK)(VkPhysicalDevice physicalDevice, id* pMTLDevice); -typedef VkResult (VKAPI_PTR *PFN_vkSetMTLTextureMVK)(VkImage image, id mtlTexture); -typedef void (VKAPI_PTR *PFN_vkGetMTLTextureMVK)(VkImage image, id* pMTLTexture); -typedef void (VKAPI_PTR *PFN_vkGetMTLBufferMVK)(VkBuffer buffer, id* pMTLBuffer); -typedef void (VKAPI_PTR *PFN_vkGetMTLCommandQueueMVK)(VkQueue queue, id* pMTLCommandQueue); -#endif // __OBJC__ - - -#pragma mark - -#pragma mark Function prototypes - -#ifndef VK_NO_PROTOTYPES - -/** - * Populates the pConfiguration structure with the current MoltenVK configuration settings. - * - * To change a specific configuration value, call vkGetMoltenVKConfigurationMVK() to retrieve - * the current configuration, make changes, and call vkSetMoltenVKConfigurationMVK() to - * update all of the values. - * - * The VkInstance object you provide here is ignored, and a VK_NULL_HANDLE value can be provided. - * This function can be called before the VkInstance has been created. It is safe to call this function - * with a VkInstance retrieved from a different layer in the Vulkan SDK Loader and Layers framework. - * - * To be active, some configuration settings must be set before a VkInstance or VkDevice - * is created. See the description of the MVKConfiguration members for more information. - * - * If you are linking to an implementation of MoltenVK that was compiled from a different - * VK_MVK_MOLTENVK_SPEC_VERSION than your app was, the size of the MVKConfiguration structure - * in your app may be larger or smaller than the same struct as expected by MoltenVK. - * - * When calling this function, set the value of *pConfigurationSize to sizeof(MVKConfiguration), - * to tell MoltenVK the limit of the size of your MVKConfiguration structure. Upon return from - * this function, the value of *pConfigurationSize will hold the actual number of bytes copied - * into your passed MVKConfiguration structure, which will be the smaller of what your app - * thinks is the size of MVKConfiguration, and what MoltenVK thinks it is. This represents the - * safe access area within the structure for both MoltenVK and your app. - * - * If the size that MoltenVK expects for MVKConfiguration is different than the value passed in - * *pConfigurationSize, this function will return VK_INCOMPLETE, otherwise it will return VK_SUCCESS. - * - * Although it is not necessary, you can use this function to determine in advance the value - * that MoltenVK expects the size of MVKConfiguration to be by setting the value of pConfiguration - * to NULL. In that case, this function will set *pConfigurationSize to the size that MoltenVK - * expects MVKConfiguration to be. - */ -VKAPI_ATTR VkResult VKAPI_CALL vkGetMoltenVKConfigurationMVK( - VkInstance ignored, - MVKConfiguration* pConfiguration, - size_t* pConfigurationSize); - -/** - * Sets the MoltenVK configuration settings to those found in the pConfiguration structure. - * - * To change a specific configuration value, call vkGetMoltenVKConfigurationMVK() - * to retrieve the current configuration, make changes, and call - * vkSetMoltenVKConfigurationMVK() to update all of the values. - * - * The VkInstance object you provide here is ignored, and a VK_NULL_HANDLE value can be provided. - * This function can be called before the VkInstance has been created. It is safe to call this function - * with a VkInstance retrieved from a different layer in the Vulkan SDK Loader and Layers framework. - * - * To be active, some configuration settings must be set before a VkInstance or VkDevice - * is created. See the description of the MVKConfiguration members for more information. - * - * If you are linking to an implementation of MoltenVK that was compiled from a different - * VK_MVK_MOLTENVK_SPEC_VERSION than your app was, the size of the MVKConfiguration structure - * in your app may be larger or smaller than the same struct as expected by MoltenVK. - * - * When calling this function, set the value of *pConfigurationSize to sizeof(MVKConfiguration), - * to tell MoltenVK the limit of the size of your MVKConfiguration structure. Upon return from - * this function, the value of *pConfigurationSize will hold the actual number of bytes copied - * out of your passed MVKConfiguration structure, which will be the smaller of what your app - * thinks is the size of MVKConfiguration, and what MoltenVK thinks it is. This represents the - * safe access area within the structure for both MoltenVK and your app. - * - * If the size that MoltenVK expects for MVKConfiguration is different than the value passed in - * *pConfigurationSize, this function will return VK_INCOMPLETE, otherwise it will return VK_SUCCESS. - * - * Although it is not necessary, you can use this function to determine in advance the value - * that MoltenVK expects the size of MVKConfiguration to be by setting the value of pConfiguration - * to NULL. In that case, this function will set *pConfigurationSize to the size that MoltenVK - * expects MVKConfiguration to be. - */ -VKAPI_ATTR VkResult VKAPI_CALL vkSetMoltenVKConfigurationMVK( - VkInstance ignored, - const MVKConfiguration* pConfiguration, - size_t* pConfigurationSize); - -/** - * Populates the pMetalFeatures structure with the Metal-specific features - * supported by the specified physical device. - * - * If you are linking to an implementation of MoltenVK that was compiled from a different - * VK_MVK_MOLTENVK_SPEC_VERSION than your app was, the size of the MVKPhysicalDeviceMetalFeatures - * structure in your app may be larger or smaller than the same struct as expected by MoltenVK. - * - * When calling this function, set the value of *pMetalFeaturesSize to sizeof(MVKPhysicalDeviceMetalFeatures), - * to tell MoltenVK the limit of the size of your MVKPhysicalDeviceMetalFeatures structure. Upon return from - * this function, the value of *pMetalFeaturesSize will hold the actual number of bytes copied into your - * passed MVKPhysicalDeviceMetalFeatures structure, which will be the smaller of what your app thinks is the - * size of MVKPhysicalDeviceMetalFeatures, and what MoltenVK thinks it is. This represents the safe access - * area within the structure for both MoltenVK and your app. - * - * If the size that MoltenVK expects for MVKPhysicalDeviceMetalFeatures is different than the value passed in - * *pMetalFeaturesSize, this function will return VK_INCOMPLETE, otherwise it will return VK_SUCCESS. - * - * Although it is not necessary, you can use this function to determine in advance the value that MoltenVK - * expects the size of MVKPhysicalDeviceMetalFeatures to be by setting the value of pMetalFeatures to NULL. - * In that case, this function will set *pMetalFeaturesSize to the size that MoltenVK expects - * MVKPhysicalDeviceMetalFeatures to be. - * - * This function is not supported by the Vulkan SDK Loader and Layers framework - * and is unavailable when using the Vulkan SDK Loader and Layers framework. - */ -VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceMetalFeaturesMVK( - VkPhysicalDevice physicalDevice, - MVKPhysicalDeviceMetalFeatures* pMetalFeatures, - size_t* pMetalFeaturesSize); - -/** - * Populates the pPerf structure with the current performance statistics for the device. - * - * If you are linking to an implementation of MoltenVK that was compiled from a different - * VK_MVK_MOLTENVK_SPEC_VERSION than your app was, the size of the MVKPerformanceStatistics - * structure in your app may be larger or smaller than the same struct as expected by MoltenVK. - * - * When calling this function, set the value of *pPerfSize to sizeof(MVKPerformanceStatistics), - * to tell MoltenVK the limit of the size of your MVKPerformanceStatistics structure. Upon return - * from this function, the value of *pPerfSize will hold the actual number of bytes copied into - * your passed MVKPerformanceStatistics structure, which will be the smaller of what your app - * thinks is the size of MVKPerformanceStatistics, and what MoltenVK thinks it is. This - * represents the safe access area within the structure for both MoltenVK and your app. - * - * If the size that MoltenVK expects for MVKPerformanceStatistics is different than the value passed - * in *pPerfSize, this function will return VK_INCOMPLETE, otherwise it will return VK_SUCCESS. - * - * Although it is not necessary, you can use this function to determine in advance the value - * that MoltenVK expects the size of MVKPerformanceStatistics to be by setting the value of - * pPerf to NULL. In that case, this function will set *pPerfSize to the size that MoltenVK - * expects MVKPerformanceStatistics to be. - * - * This function is not supported by the Vulkan SDK Loader and Layers framework - * and is unavailable when using the Vulkan SDK Loader and Layers framework. - */ -VKAPI_ATTR VkResult VKAPI_CALL vkGetPerformanceStatisticsMVK( - VkDevice device, - MVKPerformanceStatistics* pPerf, - size_t* pPerfSize); - -/** - * Returns a human readable version of the MoltenVK and Vulkan versions. - * - * This function is provided as a convenience for reporting. Use the MVK_VERSION, - * VK_API_VERSION_1_0, and VK_HEADER_VERSION macros for programmatically accessing - * the corresponding version numbers. - */ -VKAPI_ATTR void VKAPI_CALL vkGetVersionStringsMVK( - char* pMoltenVersionStringBuffer, - uint32_t moltenVersionStringBufferLength, - char* pVulkanVersionStringBuffer, - uint32_t vulkanVersionStringBufferLength); - -/** - * Sets the number of threads in a workgroup for a compute kernel. - * - * This needs to be called if you are creating compute shader modules from MSL source code - * or MSL compiled code. If you are using SPIR-V, workgroup size is determined automatically. - * - * This function is not supported by the Vulkan SDK Loader and Layers framework - * and is unavailable when using the Vulkan SDK Loader and Layers framework. - */ -VKAPI_ATTR void VKAPI_CALL vkSetWorkgroupSizeMVK( - VkShaderModule shaderModule, - uint32_t x, - uint32_t y, - uint32_t z); - -#ifdef __OBJC__ - -/** - * Returns, in the pMTLDevice pointer, the MTLDevice used by the VkPhysicalDevice. - * - * This function is not supported by the Vulkan SDK Loader and Layers framework - * and is unavailable when using the Vulkan SDK Loader and Layers framework. - */ -VKAPI_ATTR void VKAPI_CALL vkGetMTLDeviceMVK( - VkPhysicalDevice physicalDevice, - id* pMTLDevice); - -/** - * Sets the VkImage to use the specified MTLTexture. - * - * Any differences in the properties of mtlTexture and this image will modify the - * properties of this image. - * - * If a MTLTexture has already been created for this image, it will be destroyed. - * - * Returns VK_SUCCESS. - * - * This function is not supported by the Vulkan SDK Loader and Layers framework - * and is unavailable when using the Vulkan SDK Loader and Layers framework. - */ -VKAPI_ATTR VkResult VKAPI_CALL vkSetMTLTextureMVK( - VkImage image, - id mtlTexture); - -/** - * Returns, in the pMTLTexture pointer, the MTLTexture currently underlaying the VkImage. - * - * This function is not supported by the Vulkan SDK Loader and Layers framework - * and is unavailable when using the Vulkan SDK Loader and Layers framework. - */ -VKAPI_ATTR void VKAPI_CALL vkGetMTLTextureMVK( - VkImage image, - id* pMTLTexture); - -/** -* Returns, in the pMTLBuffer pointer, the MTLBuffer currently underlaying the VkBuffer. -* - * This function is not supported by the Vulkan SDK Loader and Layers framework - * and is unavailable when using the Vulkan SDK Loader and Layers framework. -*/ -VKAPI_ATTR void VKAPI_CALL vkGetMTLBufferMVK( - VkBuffer buffer, - id* pMTLBuffer); - -/** -* Returns, in the pMTLCommandQueue pointer, the MTLCommandQueue currently underlaying the VkQueue. -* - * This function is not supported by the Vulkan SDK Loader and Layers framework - * and is unavailable when using the Vulkan SDK Loader and Layers framework. -*/ -VKAPI_ATTR void VKAPI_CALL vkGetMTLCommandQueueMVK( - VkQueue queue, - id* pMTLCommandQueue); - -#endif // __OBJC__ - -/** - * Indicates that a VkImage should use an IOSurface to underlay the Metal texture. - * - * If ioSurface is not null, it will be used as the IOSurface, and any differences - * in the properties of that IOSurface will modify the properties of this image. - * - * If ioSurface is null, this image will create and use an IOSurface - * whose properties are compatible with the properties of this image. - * - * If a MTLTexture has already been created for this image, it will be destroyed. - * - * IOSurfaces are supported on the following platforms: - * - macOS 10.11 and above - * - iOS 11.0 and above - * - * To enable IOSurface support, ensure the Deployment Target build setting - * (MACOSX_DEPLOYMENT_TARGET or IPHONEOS_DEPLOYMENT_TARGET) is set to at least - * one of the values above when compiling MoltenVK, and any app that uses MoltenVK. - * - * Returns: - * - VK_SUCCESS. - * - VK_ERROR_FEATURE_NOT_PRESENT if IOSurfaces are not supported on the platform. - * - VK_ERROR_INITIALIZATION_FAILED if ioSurface is specified and is not compatible with this VkImage. - * - * This function is not supported by the Vulkan SDK Loader and Layers framework - * and is unavailable when using the Vulkan SDK Loader and Layers framework. - */ -VKAPI_ATTR VkResult VKAPI_CALL vkUseIOSurfaceMVK( - VkImage image, - IOSurfaceRef ioSurface); - -/** - * Returns, in the pIOSurface pointer, the IOSurface currently underlaying the VkImage, - * as set by the useIOSurfaceMVK() function, or returns null if the VkImage is not using - * an IOSurface, or if the platform does not support IOSurfaces. - * - * This function is not supported by the Vulkan SDK Loader and Layers framework - * and is unavailable when using the Vulkan SDK Loader and Layers framework. - */ -VKAPI_ATTR void VKAPI_CALL vkGetIOSurfaceMVK( - VkImage image, - IOSurfaceRef* pIOSurface); - - -#pragma mark - -#pragma mark Shaders - -/** - * NOTE: Shader code should be submitted as SPIR-V. Although some simple direct MSL shaders may work, - * direct loading of MSL source code or compiled MSL code is not officially supported at this time. - * Future versions of MoltenVK may support direct MSL submission again. - * - * Enumerates the magic number values to set in the MVKMSLSPIRVHeader when - * submitting a SPIR-V stream that contains either Metal Shading Language source - * code or Metal Shading Language compiled binary code in place of SPIR-V code. - */ -typedef enum { - kMVKMagicNumberSPIRVCode = 0x07230203, /**< SPIR-V stream contains standard SPIR-V code. */ - kMVKMagicNumberMSLSourceCode = 0x19960412, /**< SPIR-V stream contains Metal Shading Language source code. */ - kMVKMagicNumberMSLCompiledCode = 0x19981215, /**< SPIR-V stream contains Metal Shading Language compiled binary code. */ -} MVKMSLMagicNumber; - -/** - * NOTE: Shader code should be submitted as SPIR-V. Although some simple direct MSL shaders may work, - * direct loading of MSL source code or compiled MSL code is not officially supported at this time. - * Future versions of MoltenVK may support direct MSL submission again. - * - * Describes the header at the start of an SPIR-V stream, when it contains either - * Metal Shading Language source code or Metal Shading Language compiled binary code. - * - * To submit MSL source code to the vkCreateShaderModule() function in place of SPIR-V - * code, prepend a MVKMSLSPIRVHeader containing the kMVKMagicNumberMSLSourceCode magic - * number to the MSL source code. The MSL source code must be null-terminated. - * - * To submit MSL compiled binary code to the vkCreateShaderModule() function in place of - * SPIR-V code, prepend a MVKMSLSPIRVHeader containing the kMVKMagicNumberMSLCompiledCode - * magic number to the MSL compiled binary code. - * - * In both cases, the pCode element of VkShaderModuleCreateInfo should pointer to the - * location of the MVKMSLSPIRVHeader, and the MSL code should start at the byte immediately - * after the MVKMSLSPIRVHeader. - * - * The codeSize element of VkShaderModuleCreateInfo should be set to the entire size of - * the submitted code memory, including the additional sizeof(MVKMSLSPIRVHeader) bytes - * taken up by the MVKMSLSPIRVHeader, and, in the case of MSL source code, including - * the null-terminator byte. - */ -typedef uint32_t MVKMSLSPIRVHeader; - - -#endif // VK_NO_PROTOTYPES - - -#ifdef __cplusplus -} -#endif // __cplusplus +#include "mvk_vulkan.h" +#include "mvk_config.h" -#endif +#include "mvk_private_api.h" +#include "mvk_deprecated_api.h" diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.h b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.h index 2c3fca39c..c1e4a6936 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.h +++ b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.h @@ -91,6 +91,7 @@ class MVKCmdDraw : public MVKCommand { uint32_t firstInstance); void encode(MVKCommandEncoder* cmdEncoder) override; + void encodeIndexedIndirect(MVKCommandEncoder* cmdEncoder); protected: MVKCommandTypePool* getTypePool(MVKCommandPool* cmdPool) override; @@ -120,6 +121,7 @@ class MVKCmdDrawIndexed : public MVKCommand { protected: MVKCommandTypePool* getTypePool(MVKCommandPool* cmdPool) override; + void encodeIndexedIndirect(MVKCommandEncoder* cmdEncoder); uint32_t _firstIndex; uint32_t _indexCount; @@ -146,6 +148,7 @@ class MVKCmdDrawIndirect : public MVKCommand { protected: MVKCommandTypePool* getTypePool(MVKCommandPool* cmdPool) override; + void encodeIndexedIndirect(MVKCommandEncoder* cmdEncoder); id _mtlIndirectBuffer; VkDeviceSize _mtlIndirectBufferOffset; @@ -167,7 +170,15 @@ class MVKCmdDrawIndexedIndirect : public MVKCommand { uint32_t count, uint32_t stride); + VkResult setContent(MVKCommandBuffer* cmdBuff, + id indirectMTLBuff, + VkDeviceSize indirectMTLBuffOffset, + uint32_t drawCount, + uint32_t stride, + uint32_t directCmdFirstInstance); + void encode(MVKCommandEncoder* cmdEncoder) override; + void encode(MVKCommandEncoder* cmdEncoder, const MVKIndexMTLBufferBinding& ibbOrig); protected: MVKCommandTypePool* getTypePool(MVKCommandPool* cmdPool) override; @@ -176,4 +187,5 @@ class MVKCmdDrawIndexedIndirect : public MVKCommand { VkDeviceSize _mtlIndirectBufferOffset; uint32_t _mtlIndirectBufferStride; uint32_t _drawCount; + uint32_t _directCmdFirstInstance; }; diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm index 83a48ed56..56750d23d 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm @@ -79,6 +79,14 @@ cmdEncoder->_graphicsResourcesState.bindIndexBuffer(_binding); } +#pragma mark - + +/* Describes the draw parameters for mesh pipelines. */ +struct DrawInfo { + int32_t indexed; + int32_t indexSize; + uint64_t indexBuffer; +}; #pragma mark - #pragma mark MVKCmdDraw @@ -101,6 +109,44 @@ return VK_SUCCESS; } +// Populates and encodes a MVKCmdDrawIndexedIndirect command, after populating indexed indirect buffers. +void MVKCmdDraw::encodeIndexedIndirect(MVKCommandEncoder* cmdEncoder) { + + // Create an indexed indirect buffer and populate it from the draw arguments. + uint32_t indirectIdxBuffStride = sizeof(MTLDrawIndexedPrimitivesIndirectArguments); + auto* indirectIdxBuff = cmdEncoder->getTempMTLBuffer(indirectIdxBuffStride); + auto* pIndArg = (MTLDrawIndexedPrimitivesIndirectArguments*)indirectIdxBuff->getContents(); + pIndArg->indexCount = _vertexCount; + pIndArg->indexStart = _firstVertex; + pIndArg->baseVertex = 0; + pIndArg->instanceCount = _instanceCount; + pIndArg->baseInstance = _firstInstance; + + // Create an index buffer populated with synthetic indexes. + // Start populating indexes below _firstVertex so that indexes align with their corresponding vertexes + MTLIndexType mtlIdxType = MTLIndexTypeUInt32; + auto* vtxIdxBuff = cmdEncoder->getTempMTLBuffer(mvkMTLIndexTypeSizeInBytes(mtlIdxType) * _vertexCount); + auto* pIdxBuff = (uint32_t*)vtxIdxBuff->getContents(); + uint32_t idxCnt = _firstVertex + _vertexCount; + for (uint32_t idx = 0; idx < idxCnt; idx++) { + pIdxBuff[idx] = idx; + } + + MVKIndexMTLBufferBinding ibb; + ibb.mtlIndexType = mtlIdxType; + ibb.mtlBuffer = vtxIdxBuff->_mtlBuffer; + ibb.offset = vtxIdxBuff->_offset; + + MVKCmdDrawIndexedIndirect diiCmd; + diiCmd.setContent(cmdEncoder->_cmdBuffer, + indirectIdxBuff->_mtlBuffer, + indirectIdxBuff->_offset, + 1, + indirectIdxBuffStride, + _firstInstance); + diiCmd.encode(cmdEncoder, ibb); +} + void MVKCmdDraw::encode(MVKCommandEncoder* cmdEncoder) { if (_vertexCount == 0 || _instanceCount == 0) { @@ -108,9 +154,15 @@ return; } - cmdEncoder->_isIndexedDraw = false; + auto* pipeline = (MVKGraphicsPipeline*)cmdEncoder->_graphicsPipelineState.getPipeline(); - auto* pipeline = (MVKGraphicsPipeline*)cmdEncoder->_graphicsPipelineState.getPipeline(); + // Metal doesn't support triangle fans, so encode it as triangles via an indexed indirect triangles command instead. + if (pipeline->getVkPrimitiveTopology() == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN) { + encodeIndexedIndirect(cmdEncoder); + return; + } + + cmdEncoder->_isIndexedDraw = false; MVKPiplineStages stages; pipeline->getStages(stages); @@ -246,6 +298,28 @@ cmdEncoder->_graphicsPipelineState.beginMetalRenderPass(); cmdEncoder->_graphicsResourcesState.beginMetalRenderPass(); cmdEncoder->getPushConstants(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)->beginMetalRenderPass(); +#if MVK_XCODE_14 + } else if (pipeline->isGeometryPipeline()) { + DrawInfo drawInfo = {}; + drawInfo.indexed = false; + + [cmdEncoder->_mtlRenderEncoder setObjectBytes: &drawInfo length: sizeof(drawInfo) atIndex: pipeline->getDrawInfoBufferIndex()]; + + int threadCount = 0; + if (cmdEncoder->_mtlPrimitiveType == MTLPrimitiveTypeTriangle) + threadCount = _vertexCount / 3; + else if (cmdEncoder->_mtlPrimitiveType == MTLPrimitiveTypeTriangleStrip) + threadCount = _vertexCount - 2; + else + reportMessage(MVK_CONFIG_LOG_LEVEL_ERROR, "Unsupported primitive type: %lu", cmdEncoder->_mtlPrimitiveType); + + if (_firstVertex) reportMessage(MVK_CONFIG_LOG_LEVEL_ERROR, "First vertex not supported yet."); + if (_firstInstance) reportMessage(MVK_CONFIG_LOG_LEVEL_ERROR, "First instance not supported yet."); + + [cmdEncoder->_mtlRenderEncoder drawMeshThreadgroups: MTLSizeMake(threadCount, _instanceCount, 1) + threadsPerObjectThreadgroup: MTLSizeMake(1, 1, 1) + threadsPerMeshThreadgroup: MTLSizeMake(1, 1, 1)]; +#endif } else { MVKRenderSubpass* subpass = cmdEncoder->getSubpass(); uint32_t viewCount = subpass->isMultiview() ? subpass->getViewCountInMetalPass(cmdEncoder->getMultiviewPassIndex()) : 1; @@ -297,6 +371,29 @@ return VK_SUCCESS; } +// Populates and encodes a MVKCmdDrawIndexedIndirect command, after populating an indexed indirect buffer. +void MVKCmdDrawIndexed::encodeIndexedIndirect(MVKCommandEncoder* cmdEncoder) { + + // Create an indexed indirect buffer and populate it from the draw arguments. + uint32_t indirectIdxBuffStride = sizeof(MTLDrawIndexedPrimitivesIndirectArguments); + auto* indirectIdxBuff = cmdEncoder->getTempMTLBuffer(indirectIdxBuffStride); + auto* pIndArg = (MTLDrawIndexedPrimitivesIndirectArguments*)indirectIdxBuff->getContents(); + pIndArg->indexCount = _indexCount; + pIndArg->indexStart = _firstIndex; + pIndArg->baseVertex = _vertexOffset; + pIndArg->instanceCount = _instanceCount; + pIndArg->baseInstance = _firstInstance; + + MVKCmdDrawIndexedIndirect diiCmd; + diiCmd.setContent(cmdEncoder->_cmdBuffer, + indirectIdxBuff->_mtlBuffer, + indirectIdxBuff->_offset, + 1, + indirectIdxBuffStride, + _firstInstance); + diiCmd.encode(cmdEncoder); +} + void MVKCmdDrawIndexed::encode(MVKCommandEncoder* cmdEncoder) { if (_indexCount == 0 || _instanceCount == 0) { @@ -304,9 +401,15 @@ return; } - cmdEncoder->_isIndexedDraw = true; + auto* pipeline = (MVKGraphicsPipeline*)cmdEncoder->_graphicsPipelineState.getPipeline(); - auto* pipeline = (MVKGraphicsPipeline*)cmdEncoder->_graphicsPipelineState.getPipeline(); + // Metal doesn't support triangle fans, so encode it as triangles via an indexed indirect triangles command instead. + if (pipeline->getVkPrimitiveTopology() == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN) { + encodeIndexedIndirect(cmdEncoder); + return; + } + + cmdEncoder->_isIndexedDraw = true; MVKPiplineStages stages; pipeline->getStages(stages); @@ -451,6 +554,31 @@ cmdEncoder->_graphicsPipelineState.beginMetalRenderPass(); cmdEncoder->_graphicsResourcesState.beginMetalRenderPass(); cmdEncoder->getPushConstants(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)->beginMetalRenderPass(); +#if MVK_XCODE_14 + } else if (pipeline->isGeometryPipeline()) { + DrawInfo drawInfo = {}; + drawInfo.indexed = true; + drawInfo.indexSize = (int)idxSize; + drawInfo.indexBuffer = ibb.mtlBuffer.gpuAddress + idxBuffOffset; + + [cmdEncoder->_mtlRenderEncoder useResource: ibb.mtlBuffer usage: MTLResourceUsageRead stages: MTLRenderStageObject]; + [cmdEncoder->_mtlRenderEncoder setObjectBytes: &drawInfo length: sizeof(drawInfo) atIndex: pipeline->getDrawInfoBufferIndex()]; + + int threadCount = 0; + if (cmdEncoder->_mtlPrimitiveType == MTLPrimitiveTypeTriangle) + threadCount = _indexCount / 3; + else if (cmdEncoder->_mtlPrimitiveType == MTLPrimitiveTypeTriangleStrip) + threadCount = _indexCount - 2; + else + reportMessage(MVK_CONFIG_LOG_LEVEL_ERROR, "Unsupported primitive type %lu.", cmdEncoder->_mtlPrimitiveType); + + if (_vertexOffset) reportMessage(MVK_CONFIG_LOG_LEVEL_ERROR, "Vertex offset not supported yet."); + if (_firstInstance) reportMessage(MVK_CONFIG_LOG_LEVEL_ERROR, "First instance not supported yet."); + + [cmdEncoder->_mtlRenderEncoder drawMeshThreadgroups:MTLSizeMake(threadCount, _instanceCount, 1) + threadsPerObjectThreadgroup:MTLSizeMake(1, 1, 1) + threadsPerMeshThreadgroup:MTLSizeMake(1, 1, 1)]; +#endif } else { MVKRenderSubpass* subpass = cmdEncoder->getSubpass(); uint32_t viewCount = subpass->isMultiview() ? subpass->getViewCountInMetalPass(cmdEncoder->getMultiviewPassIndex()) : 1; @@ -480,6 +608,12 @@ } +// This is totally arbitrary, but we're forced to do this because we don't know how many vertices +// there are at encoding time. And this will probably be inadequate for large instanced draws. +// TODO: Consider breaking up such draws using different base instance values. But this will +// require yet more munging of the indirect buffers... +static const uint32_t kMVKMaxDrawIndirectVertexCount = 128 * KIBI; + #pragma mark - #pragma mark MVKCmdDrawIndirect @@ -506,17 +640,84 @@ return VK_SUCCESS; } -// This is totally arbitrary, but we're forced to do this because we don't know how many vertices -// there are at encoding time. And this will probably be inadequate for large instanced draws. -// TODO: Consider breaking up such draws using different base instance values. But this will -// require yet more munging of the indirect buffers... -static const uint32_t kMVKDrawIndirectVertexCountUpperBound = 131072; +// Populates and encodes a MVKCmdDrawIndexedIndirect command, after populating indexed indirect buffers. +void MVKCmdDrawIndirect::encodeIndexedIndirect(MVKCommandEncoder* cmdEncoder) { + + // Create an indexed indirect buffer to be populated from the non-indexed indirect buffer. + uint32_t indirectIdxBuffStride = sizeof(MTLDrawIndexedPrimitivesIndirectArguments); + auto* indirectIdxBuff = cmdEncoder->getTempMTLBuffer(indirectIdxBuffStride * _drawCount, true); + + // Create an index buffer to be populated with synthetic indexes. + MTLIndexType mtlIdxType = MTLIndexTypeUInt32; + auto* vtxIdxBuff = cmdEncoder->getTempMTLBuffer(mvkMTLIndexTypeSizeInBytes(mtlIdxType) * kMVKMaxDrawIndirectVertexCount, true); + MVKIndexMTLBufferBinding ibb; + ibb.mtlIndexType = mtlIdxType; + ibb.mtlBuffer = vtxIdxBuff->_mtlBuffer; + ibb.offset = vtxIdxBuff->_offset; + + // Schedule a compute action to populate indexed buffers from non-indexed buffers. + cmdEncoder->encodeStoreActions(true); + id mtlConvertEncoder = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDrawIndirectConvertBuffers); + id mtlConvertState = cmdEncoder->getCommandEncodingPool()->getCmdDrawIndirectPopulateIndexesMTLComputePipelineState(); + [mtlConvertEncoder setComputePipelineState: mtlConvertState]; + [mtlConvertEncoder setBuffer: _mtlIndirectBuffer + offset: _mtlIndirectBufferOffset + atIndex: 0]; + [mtlConvertEncoder setBuffer: indirectIdxBuff->_mtlBuffer + offset: indirectIdxBuff->_offset + atIndex: 1]; + cmdEncoder->setComputeBytes(mtlConvertEncoder, + &_mtlIndirectBufferStride, + sizeof(_mtlIndirectBufferStride), + 2); + cmdEncoder->setComputeBytes(mtlConvertEncoder, + &_drawCount, + sizeof(_drawCount), + 3); + [mtlConvertEncoder setBuffer: ibb.mtlBuffer + offset: ibb.offset + atIndex: 4]; + if (cmdEncoder->getDevice()->_pMetalFeatures->nonUniformThreadgroups) { +#if MVK_MACOS_OR_IOS + [mtlConvertEncoder dispatchThreads: MTLSizeMake(_drawCount, 1, 1) + threadsPerThreadgroup: MTLSizeMake(mtlConvertState.threadExecutionWidth, 1, 1)]; +#endif + } else { + [mtlConvertEncoder dispatchThreadgroups: MTLSizeMake(mvkCeilingDivide(_drawCount, mtlConvertState.threadExecutionWidth), 1, 1) + threadsPerThreadgroup: MTLSizeMake(mtlConvertState.threadExecutionWidth, 1, 1)]; + } + // Switch back to rendering now. + cmdEncoder->beginMetalRenderPass(kMVKCommandUseRestartSubpass); + + MVKCmdDrawIndexedIndirect diiCmd; + diiCmd.setContent(cmdEncoder->_cmdBuffer, + indirectIdxBuff->_mtlBuffer, + indirectIdxBuff->_offset, + _drawCount, + indirectIdxBuffStride, + 0); + diiCmd.encode(cmdEncoder, ibb); +} void MVKCmdDrawIndirect::encode(MVKCommandEncoder* cmdEncoder) { + auto* pipeline = (MVKGraphicsPipeline*)cmdEncoder->_graphicsPipelineState.getPipeline(); + +#if MVK_XCODE_14 + if (pipeline->isGeometryPipeline()) { + reportMessage(MVK_CONFIG_LOG_LEVEL_ERROR, "CmdDrawIndirect with geometry shader is not yet supported."); + return; + } +#endif + + // Metal doesn't support triangle fans, so encode it as indexed indirect triangles instead. + if (pipeline->getVkPrimitiveTopology() == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN) { + encodeIndexedIndirect(cmdEncoder); + return; + } + cmdEncoder->_isIndexedDraw = false; - auto* pipeline = (MVKGraphicsPipeline*)cmdEncoder->_graphicsPipelineState.getPipeline(); bool needsInstanceAdjustment = cmdEncoder->getSubpass()->isMultiview() && cmdEncoder->getPhysicalDevice()->canUseInstancingForMultiview(); // The indirect calls for dispatchThreadgroups:... and drawPatches:... have different formats. @@ -546,7 +747,7 @@ // But not too many, or we'll exhaust available VRAM. inControlPointCount = pipeline->getInputControlPointCount(); outControlPointCount = pipeline->getOutputControlPointCount(); - vertexCount = kMVKDrawIndirectVertexCountUpperBound; + vertexCount = kMVKMaxDrawIndirectVertexCount; patchCount = mvkCeilingDivide(vertexCount, inControlPointCount); VkDeviceSize indirectSize = (2 * sizeof(MTLDispatchThreadgroupsIndirectArguments) + sizeof(MTLDrawPatchIndirectArguments)) * _drawCount; if (cmdEncoder->_pDeviceMetalFeatures->mslVersion >= 20100) { @@ -653,8 +854,8 @@ // Unfortunately, this requires switching to compute. // TODO: Consider using tile shaders to avoid this cost. cmdEncoder->encodeStoreActions(true); - id mtlConvertEncoder = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseMultiviewInstanceCountAdjust); - id mtlConvertState = cmdEncoder->getCommandEncodingPool()->getCmdDrawIndirectMultiviewConvertBuffersMTLComputePipelineState(false); + id mtlConvertEncoder = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDrawIndirectConvertBuffers); + id mtlConvertState = cmdEncoder->getCommandEncodingPool()->getCmdDrawIndirectConvertBuffersMTLComputePipelineState(false); uint32_t viewCount; [mtlConvertEncoder setComputePipelineState: mtlConvertState]; [mtlConvertEncoder setBuffer: _mtlIndirectBuffer @@ -801,22 +1002,45 @@ #pragma mark - #pragma mark MVKCmdDrawIndexedIndirect +typedef struct MVKVertexAdjustments { + uint8_t mtlIndexType = MTLIndexTypeUInt16; // Enum must match enum in shader + bool isMultiView = false; + bool isTriangleFan = false; + + bool needsAdjustment() { return isMultiView || isTriangleFan; } +} MVKVertexAdjustments; + VkResult MVKCmdDrawIndexedIndirect::setContent(MVKCommandBuffer* cmdBuff, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride) { - MVKBuffer* mvkBuffer = (MVKBuffer*)buffer; - _mtlIndirectBuffer = mvkBuffer->getMTLBuffer(); - _mtlIndirectBufferOffset = mvkBuffer->getMTLBufferOffset() + offset; + auto* mvkBuff = (MVKBuffer*)buffer; + return setContent(cmdBuff, + mvkBuff->getMTLBuffer(), + mvkBuff->getMTLBufferOffset() + offset, + drawCount, + stride, + 0); +} + +VkResult MVKCmdDrawIndexedIndirect::setContent(MVKCommandBuffer* cmdBuff, + id indirectMTLBuff, + VkDeviceSize indirectMTLBuffOffset, + uint32_t drawCount, + uint32_t stride, + uint32_t directCmdFirstInstance) { + _mtlIndirectBuffer = indirectMTLBuff; + _mtlIndirectBufferOffset = indirectMTLBuffOffset; _mtlIndirectBufferStride = stride; _drawCount = drawCount; + _directCmdFirstInstance = directCmdFirstInstance; - // Validate + // Validate MVKDevice* mvkDvc = cmdBuff->getDevice(); - if ( !mvkDvc->_pMetalFeatures->indirectDrawing ) { - return cmdBuff->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdDrawIndexedIndirect(): The current device does not support indirect drawing."); - } + if ( !mvkDvc->_pMetalFeatures->indirectDrawing ) { + return cmdBuff->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdDrawIndexedIndirect(): The current device does not support indirect drawing."); + } if (cmdBuff->_lastTessellationPipeline && !mvkDvc->_pMetalFeatures->indirectTessellationDrawing) { return cmdBuff->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdDrawIndexedIndirect(): The current device does not support indirect tessellated drawing."); } @@ -825,14 +1049,31 @@ } void MVKCmdDrawIndexedIndirect::encode(MVKCommandEncoder* cmdEncoder) { + encode(cmdEncoder, cmdEncoder->_graphicsResourcesState._mtlIndexBufferBinding); +} + +void MVKCmdDrawIndexedIndirect::encode(MVKCommandEncoder* cmdEncoder, const MVKIndexMTLBufferBinding& ibbOrig) { cmdEncoder->_isIndexedDraw = true; - MVKIndexMTLBufferBinding& ibb = cmdEncoder->_graphicsResourcesState._mtlIndexBufferBinding; + MVKIndexMTLBufferBinding ibb = ibbOrig; + MVKIndexMTLBufferBinding ibbTriFan = ibb; auto* pipeline = (MVKGraphicsPipeline*)cmdEncoder->_graphicsPipelineState.getPipeline(); - bool needsInstanceAdjustment = cmdEncoder->getSubpass()->isMultiview() && - cmdEncoder->getPhysicalDevice()->canUseInstancingForMultiview(); - // The indirect calls for dispatchThreadgroups:... and drawPatches:... have different formats. + +#if MVK_XCODE_14 + if (pipeline->isGeometryPipeline()) { + reportMessage(MVK_CONFIG_LOG_LEVEL_ERROR, "CmdDrawIndexedIndirect with geometry shader is not yet supported."); + return; + } +#endif + + MVKVertexAdjustments vtxAdjmts; + vtxAdjmts.mtlIndexType = ibb.mtlIndexType; + vtxAdjmts.isMultiView = (cmdEncoder->getSubpass()->isMultiview() && + cmdEncoder->getPhysicalDevice()->canUseInstancingForMultiview()); + vtxAdjmts.isTriangleFan = pipeline->getVkPrimitiveTopology() == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN; + + // The indirect calls for dispatchThreadgroups:... and drawPatches:... have different formats. // We have to convert from the drawIndexedPrimitives:... format to them. // While we're at it, we can create the temporary output buffers once and reuse them // for each draw. @@ -861,7 +1102,7 @@ // But not too many, or we'll exhaust available VRAM. inControlPointCount = pipeline->getInputControlPointCount(); outControlPointCount = pipeline->getOutputControlPointCount(); - vertexCount = kMVKDrawIndirectVertexCountUpperBound; + vertexCount = kMVKMaxDrawIndirectVertexCount; patchCount = mvkCeilingDivide(vertexCount, inControlPointCount); VkDeviceSize indirectSize = (sizeof(MTLDispatchThreadgroupsIndirectArguments) + sizeof(MTLDrawPatchIndirectArguments)) * _drawCount; if (cmdEncoder->_pDeviceMetalFeatures->mslVersion >= 20100) { @@ -896,12 +1137,17 @@ sgSize >>= 1; tcWorkgroupSize = mvkLeastCommonMultiple(outControlPointCount, sgSize); } - } else if (needsInstanceAdjustment) { + } else if (vtxAdjmts.needsAdjustment()) { // In this case, we need to adjust the instance count for the views being drawn. VkDeviceSize indirectSize = sizeof(MTLDrawIndexedPrimitivesIndirectArguments) * _drawCount; tempIndirectBuff = cmdEncoder->getTempMTLBuffer(indirectSize, true); mtlIndBuff = tempIndirectBuff->_mtlBuffer; mtlTempIndBuffOfst = tempIndirectBuff->_offset; + if (vtxAdjmts.isTriangleFan) { + auto* triVtxBuff = cmdEncoder->getTempMTLBuffer(mvkMTLIndexTypeSizeInBytes((MTLIndexType)ibb.mtlIndexType) * kMVKMaxDrawIndirectVertexCount, true); + ibb.mtlBuffer = triVtxBuff->_mtlBuffer; + ibb.offset = triVtxBuff->_offset; + } } MVKPiplineStages stages; @@ -980,14 +1226,14 @@ cmdEncoder->_graphicsPipelineState.beginMetalRenderPass(); cmdEncoder->_graphicsResourcesState.beginMetalRenderPass(); cmdEncoder->getPushConstants(VK_SHADER_STAGE_VERTEX_BIT)->beginMetalRenderPass(); - } else if (drawIdx == 0 && needsInstanceAdjustment) { + } else if (drawIdx == 0 && vtxAdjmts.needsAdjustment()) { // Similarly, for multiview, we need to adjust the instance count now. // Unfortunately, this requires switching to compute. Luckily, we don't also // have to copy the index buffer. // TODO: Consider using tile shaders to avoid this cost. cmdEncoder->encodeStoreActions(true); - id mtlConvertEncoder = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseMultiviewInstanceCountAdjust); - id mtlConvertState = cmdEncoder->getCommandEncodingPool()->getCmdDrawIndirectMultiviewConvertBuffersMTLComputePipelineState(true); + id mtlConvertEncoder = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDrawIndirectConvertBuffers); + id mtlConvertState = cmdEncoder->getCommandEncodingPool()->getCmdDrawIndirectConvertBuffersMTLComputePipelineState(true); uint32_t viewCount; [mtlConvertEncoder setComputePipelineState: mtlConvertState]; [mtlConvertEncoder setBuffer: _mtlIndirectBuffer @@ -1009,6 +1255,16 @@ &viewCount, sizeof(viewCount), 4); + cmdEncoder->setComputeBytes(mtlConvertEncoder, + &vtxAdjmts, + sizeof(vtxAdjmts), + 5); + [mtlConvertEncoder setBuffer: ibb.mtlBuffer + offset: ibb.offset + atIndex: 6]; + [mtlConvertEncoder setBuffer: ibbTriFan.mtlBuffer + offset: ibbTriFan.offset + atIndex: 7]; if (cmdEncoder->getDevice()->_pMetalFeatures->nonUniformThreadgroups) { #if MVK_MACOS_OR_IOS [mtlConvertEncoder dispatchThreads: MTLSizeMake(_drawCount, 1, 1) @@ -1043,6 +1299,9 @@ indirectBufferOffset: mtlTempIndBuffOfst]; mtlTempIndBuffOfst += sizeof(MTLStageInRegionIndirectArguments); } + // If this is a synthetic command that originated in a direct call, and there are vertex bindings with a zero vertex + // divisor, I need to offset them by _firstInstance * stride, since that is the expected behaviour for a divisor of 0. + cmdEncoder->_graphicsResourcesState.offsetZeroDivisorVertexBuffers(stage, pipeline, _directCmdFirstInstance); [mtlTessCtlEncoder dispatchThreadgroupsWithIndirectBuffer: mtlIndBuff indirectBufferOffset: mtlTempIndBuffOfst threadsPerThreadgroup: MTLSizeMake(vtxThreadExecWidth, 1, 1)]; @@ -1121,13 +1380,14 @@ cmdEncoder->_graphicsResourcesState.beginMetalRenderPass(); cmdEncoder->getPushConstants(VK_SHADER_STAGE_VERTEX_BIT)->beginMetalRenderPass(); } else { + cmdEncoder->_graphicsResourcesState.offsetZeroDivisorVertexBuffers(stage, pipeline, _directCmdFirstInstance); [cmdEncoder->_mtlRenderEncoder drawIndexedPrimitives: cmdEncoder->_mtlPrimitiveType indexType: (MTLIndexType)ibb.mtlIndexType indexBuffer: ibb.mtlBuffer indexBufferOffset: ibb.offset indirectBuffer: mtlIndBuff indirectBufferOffset: mtlTempIndBuffOfst]; - mtlTempIndBuffOfst += needsInstanceAdjustment ? sizeof(MTLDrawIndexedPrimitivesIndirectArguments) : _mtlIndirectBufferStride; + mtlTempIndBuffOfst += vtxAdjmts.needsAdjustment() ? sizeof(MTLDrawIndexedPrimitivesIndirectArguments) : _mtlIndirectBufferStride; } break; } diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm index 2a818c635..5b44bef1f 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm @@ -23,7 +23,6 @@ #include "MVKBuffer.h" #include "MVKPipeline.h" #include "MVKFoundation.h" -#include "MVKEnvironment.h" #include "mvk_datatypes.hpp" @@ -313,6 +312,7 @@ VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, + VK_SHADER_STAGE_GEOMETRY_BIT, VK_SHADER_STAGE_FRAGMENT_BIT, VK_SHADER_STAGE_COMPUTE_BIT }; @@ -394,7 +394,7 @@ } void MVKCmdPushDescriptorSet::encode(MVKCommandEncoder* cmdEncoder) { - _pipelineLayout->pushDescriptorSet(cmdEncoder, _descriptorWrites.contents(), _set); + _pipelineLayout->pushDescriptorSet(cmdEncoder, _pipelineBindPoint, _descriptorWrites.contents(), _set); } MVKCmdPushDescriptorSet::~MVKCmdPushDescriptorSet() { diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h index 4d6614752..66c7c304f 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h +++ b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h @@ -262,7 +262,7 @@ class MVKCmdSetViewport : public MVKCommand { // Concrete template class implementations. typedef MVKCmdSetViewport<1> MVKCmdSetViewport1; -typedef MVKCmdSetViewport MVKCmdSetViewportMulti; +typedef MVKCmdSetViewport MVKCmdSetViewportMulti; #pragma mark - @@ -292,7 +292,7 @@ class MVKCmdSetScissor : public MVKCommand { // Concrete template class implementations. typedef MVKCmdSetScissor<1> MVKCmdSetScissor1; -typedef MVKCmdSetScissor MVKCmdSetScissorMulti; +typedef MVKCmdSetScissor MVKCmdSetScissorMulti; #pragma mark - diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm index 829264d3c..08bbe8513 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm @@ -282,7 +282,7 @@ } template class MVKCmdSetViewport<1>; -template class MVKCmdSetViewport; +template class MVKCmdSetViewport; #pragma mark - @@ -309,7 +309,7 @@ } template class MVKCmdSetScissor<1>; -template class MVKCmdSetScissor; +template class MVKCmdSetScissor; #pragma mark - diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.h b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.h index ce0af39fd..e25158b6f 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.h +++ b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.h @@ -284,8 +284,6 @@ class MVKCmdClearAttachments : public MVKCommand { float _mtlDepthVal; uint32_t _mtlStencilValue; MVKCommandUse _commandUse; - bool _isClearingDepth; - bool _isClearingStencil; }; @@ -326,7 +324,7 @@ class MVKCmdClearMultiAttachments : public MVKCmdClearAttachments { VkClearValue& getClearValue(uint32_t attIdx) override { return _vkClearValues[attIdx]; } void setClearValue(uint32_t attIdx, const VkClearValue& clearValue) override { _vkClearValues[attIdx] = clearValue; } - VkClearValue _vkClearValues[kMVKCachedColorAttachmentCount]; + VkClearValue _vkClearValues[kMVKMaxColorAttachmentCount]; }; typedef MVKCmdClearMultiAttachments<1> MVKCmdClearMultiAttachments1; diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm index d72df15ee..2c0ef5465 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm @@ -25,7 +25,6 @@ #include "MVKFramebuffer.h" #include "MVKRenderPass.h" #include "MTLRenderPassDescriptor+MoltenVK.h" -#include "MVKEnvironment.h" #include "mvk_datatypes.hpp" #include #include @@ -375,6 +374,7 @@ static inline MTLSize mvkClampMTLSize(MTLSize size, MTLOrigin origin, MTLSize ma uint8_t srcPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(region.srcSubresource.aspectMask); uint8_t dstPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(region.dstSubresource.aspectMask); return ((_srcImage->getMTLPixelFormat(srcPlaneIndex) == _dstImage->getMTLPixelFormat(dstPlaneIndex)) && + !_srcImage->needsSwizzle() && (_dstImage->getSampleCount() == _srcImage->getSampleCount())); } @@ -457,7 +457,7 @@ static inline MTLSize mvkClampMTLSize(MTLSize size, MTLOrigin origin, MTLSize ma uint32_t copyCnt = 0; uint32_t blitCnt = 0; - // Separate BLITs into those that are really just simple texure region copies, + // Separate BLITs into those that are really just simple texture region copies, // and those that require rendering for (auto& vkIB : _vkImageBlits) { if (canCopyFormats(vkIB) && canCopy(vkIB)) { @@ -501,6 +501,15 @@ static inline MTLSize mvkClampMTLSize(MTLSize size, MTLOrigin origin, MTLSize ma id srcMTLTex = _srcImage->getMTLTexture(srcPlaneIndex); id dstMTLTex = _dstImage->getMTLTexture(dstPlaneIndex); if (blitCnt && srcMTLTex && dstMTLTex) { + if (cmdEncoder->getDevice()->_pMetalFeatures->nativeTextureSwizzle && + _srcImage->needsSwizzle()) { + // Use a view that has a swizzle on it. + srcMTLTex = [[srcMTLTex newTextureViewWithPixelFormat:srcMTLTex.pixelFormat + textureType:srcMTLTex.textureType + levels:NSMakeRange(0, srcMTLTex.mipmapLevelCount) + slices:NSMakeRange(0, srcMTLTex.arrayLength) + swizzle:_srcImage->getPixelFormats()->getMTLTextureSwizzleChannels(_srcImage->getVkFormat())] autorelease]; + } cmdEncoder->endCurrentMetalEncoding(); MTLRenderPassDescriptor* mtlRPD = [MTLRenderPassDescriptor renderPassDescriptor]; @@ -550,6 +559,14 @@ static inline MTLSize mvkClampMTLSize(MTLSize size, MTLOrigin origin, MTLSize ma blitKey.srcFilter = mvkMTLSamplerMinMagFilterFromVkFilter(_filter); blitKey.srcAspect = mvkIBR.region.srcSubresource.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); blitKey.dstSampleCount = mvkSampleCountFromVkSampleCountFlagBits(_dstImage->getSampleCount()); + if (!cmdEncoder->getDevice()->_pMetalFeatures->nativeTextureSwizzle && + _srcImage->needsSwizzle()) { + VkComponentMapping vkMapping = _srcImage->getPixelFormats()->getVkComponentMapping(_srcImage->getVkFormat()); + blitKey.srcSwizzleR = vkMapping.r; + blitKey.srcSwizzleG = vkMapping.g; + blitKey.srcSwizzleB = vkMapping.b; + blitKey.srcSwizzleA = vkMapping.a; + } id mtlRPS = cmdEncoder->getCommandEncodingPool()->getCmdBlitImageMTLRenderPipelineState(blitKey); bool isBlittingDepth = mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_DEPTH_BIT)); bool isBlittingStencil = mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_STENCIL_BIT)); @@ -956,7 +973,7 @@ static inline MTLSize mvkClampMTLSize(MTLSize size, MTLOrigin origin, MTLSize ma copyInfo.dstOffset = (uint32_t)cpyRgn.dstOffset; copyInfo.size = (uint32_t)cpyRgn.size; - id mtlComputeEnc = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseCopyBuffer); + id mtlComputeEnc = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseCopyBuffer, true); [mtlComputeEnc pushDebugGroup: @"vkCmdCopyBuffer"]; [mtlComputeEnc setComputePipelineState: cmdEncoder->getCommandEncodingPool()->getCmdCopyBufferBytesMTLComputePipelineState()]; [mtlComputeEnc setBuffer:srcMTLBuff offset: srcMTLBuffOffset atIndex: 0]; @@ -1142,7 +1159,7 @@ static inline MTLSize mvkClampMTLSize(MTLSize size, MTLOrigin origin, MTLSize ma info.offset = cpyRgn.imageOffset; info.extent = cpyRgn.imageExtent; bool needsTempBuff = mipLevel != 0; - id mtlComputeEnc = cmdEncoder->getMTLComputeEncoder(cmdUse); + id mtlComputeEnc = cmdEncoder->getMTLComputeEncoder(cmdUse, false); // Compute state will be marked dirty on next compute encoder after Blit encoder below. id mtlComputeState = cmdEncoder->getCommandEncodingPool()->getCmdCopyBufferToImage3DDecompressMTLComputePipelineState(needsTempBuff); [mtlComputeEnc pushDebugGroup: @"vkCmdCopyBufferToImage"]; [mtlComputeEnc setComputePipelineState: mtlComputeState]; @@ -1260,8 +1277,6 @@ static inline MTLSize mvkClampMTLSize(MTLSize size, MTLOrigin origin, MTLSize ma _commandUse = cmdUse; _mtlDepthVal = 0.0; _mtlStencilValue = 0; - _isClearingDepth = false; - _isClearingStencil = false; MVKPixelFormats* pixFmts = cmdBuff->getPixelFormats(); // For each attachment to be cleared, mark it so in the render pipeline state @@ -1279,14 +1294,12 @@ static inline MTLSize mvkClampMTLSize(MTLSize size, MTLOrigin origin, MTLSize ma } if (mvkIsAnyFlagEnabled(clrAtt.aspectMask, VK_IMAGE_ASPECT_DEPTH_BIT)) { - _isClearingDepth = true; - _rpsKey.enableAttachment(kMVKClearAttachmentDepthStencilIndex); + _rpsKey.enableAttachment(kMVKClearAttachmentDepthIndex); _mtlDepthVal = pixFmts->getMTLClearDepthValue(clrAtt.clearValue); } if (mvkIsAnyFlagEnabled(clrAtt.aspectMask, VK_IMAGE_ASPECT_STENCIL_BIT)) { - _isClearingStencil = true; - _rpsKey.enableAttachment(kMVKClearAttachmentDepthStencilIndex); + _rpsKey.enableAttachment(kMVKClearAttachmentStencilIndex); _mtlStencilValue = pixFmts->getMTLClearStencilValue(clrAtt.clearValue); } } @@ -1443,31 +1456,24 @@ static inline MTLSize mvkClampMTLSize(MTLSize size, MTLOrigin origin, MTLSize ma clearColors[caIdx] = { (float)mtlCC.red, (float)mtlCC.green, (float)mtlCC.blue, (float)mtlCC.alpha}; } - // The depth value (including vertex position Z value) is held in the last index. - clearColors[kMVKClearAttachmentDepthStencilIndex] = { _mtlDepthVal, _mtlDepthVal, _mtlDepthVal, _mtlDepthVal }; + // The depth value is the vertex position Z value. + clearColors[kMVKClearAttachmentDepthIndex] = { _mtlDepthVal, _mtlDepthVal, _mtlDepthVal, _mtlDepthVal }; - VkFormat vkAttFmt = subpass->getDepthStencilFormat(); - MTLPixelFormat mtlAttFmt = pixFmts->getMTLPixelFormat(vkAttFmt); - _rpsKey.attachmentMTLPixelFormats[kMVKClearAttachmentDepthStencilIndex] = mtlAttFmt; + _rpsKey.attachmentMTLPixelFormats[kMVKClearAttachmentDepthIndex] = pixFmts->getMTLPixelFormat(subpass->getDepthFormat()); + if ( !subpass->isDepthAttachmentUsed() ) { _rpsKey.disableAttachment(kMVKClearAttachmentDepthIndex); } - bool isClearingDepth = _isClearingDepth && pixFmts->isDepthFormat(mtlAttFmt); - bool isClearingStencil = _isClearingStencil && pixFmts->isStencilFormat(mtlAttFmt); - if (!isClearingDepth && !isClearingStencil) { - // If the subpass attachment isn't actually used, don't try to clear it. - _rpsKey.disableAttachment(kMVKClearAttachmentDepthStencilIndex); - } + _rpsKey.attachmentMTLPixelFormats[kMVKClearAttachmentStencilIndex] = pixFmts->getMTLPixelFormat(subpass->getStencilFormat()); + if ( !subpass->isStencilAttachmentUsed() ) { _rpsKey.disableAttachment(kMVKClearAttachmentStencilIndex); } - if (!_rpsKey.isAnyAttachmentEnabled()) { - // Nothing to do. - return; - } + if ( !_rpsKey.isAnyAttachmentEnabled() ) { return; } // Render the clear colors to the attachments MVKCommandEncodingPool* cmdEncPool = cmdEncoder->getCommandEncodingPool(); id mtlRendEnc = cmdEncoder->_mtlRenderEncoder; [mtlRendEnc pushDebugGroup: getMTLDebugGroupLabel()]; [mtlRendEnc setRenderPipelineState: cmdEncPool->getCmdClearMTLRenderPipelineState(_rpsKey)]; - [mtlRendEnc setDepthStencilState: cmdEncPool->getMTLDepthStencilState(isClearingDepth, isClearingStencil)]; + [mtlRendEnc setDepthStencilState: cmdEncPool->getMTLDepthStencilState(_rpsKey.isAttachmentUsed(kMVKClearAttachmentDepthIndex), + _rpsKey.isAttachmentUsed(kMVKClearAttachmentStencilIndex))]; [mtlRendEnc setStencilReferenceValue: _mtlStencilValue]; [mtlRendEnc setCullMode: MTLCullModeNone]; [mtlRendEnc setTriangleFillMode: MTLTriangleFillModeFill]; @@ -1592,7 +1598,7 @@ static inline MTLSize mvkClampMTLSize(MTLSize size, MTLOrigin origin, MTLSize ma // Luckily for us, linear images only have one mip and one array layer under Metal. assert( !isDS ); id mtlClearState = cmdEncoder->getCommandEncodingPool()->getCmdClearColorImageMTLComputePipelineState(pixFmts->getFormatType(_image->getVkFormat())); - id mtlComputeEnc = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseClearColorImage); + id mtlComputeEnc = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseClearColorImage, true); [mtlComputeEnc pushDebugGroup: @"vkCmdClearColorImage"]; [mtlComputeEnc setComputePipelineState: mtlClearState]; [mtlComputeEnc setTexture: imgMTLTex atIndex: 0]; @@ -1759,7 +1765,7 @@ static inline MTLSize mvkClampMTLSize(MTLSize size, MTLOrigin origin, MTLSize ma NSUInteger tgWidth = std::min(cps.maxTotalThreadsPerThreadgroup, cmdEncoder->getMTLDevice().maxThreadsPerThreadgroup.width); NSUInteger tgCount = _wordCount / tgWidth; - id mtlComputeEnc = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseFillBuffer); + id mtlComputeEnc = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseFillBuffer, true); [mtlComputeEnc pushDebugGroup: @"vkCmdFillBuffer"]; [mtlComputeEnc setComputePipelineState: cps]; [mtlComputeEnc setBytes: &_dataValue length: sizeof(_dataValue) atIndex: 1]; diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h index 1a7a7d5cc..90082966f 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h +++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h @@ -337,10 +337,12 @@ class MVKCommandEncoder : public MVKBaseDeviceObject { * Returns the current Metal compute encoder for the specified use, * which determines the label assigned to the returned encoder. * - * If the current encoder is not a compute encoder, this function ends current before - * beginning compute encoding. + * If the current encoder is a compute encoder, the compute state being tracked can + * optionally be marked dirty. Otherwise, if the current encoder is not a compute + * encoder, this function ends the current encoder before beginning compute encoding. */ - id getMTLComputeEncoder(MVKCommandUse cmdUse); + id getMTLComputeEncoder(MVKCommandUse cmdUse, + bool markCurrentComputeStateDirty = false); /** * Returns the current Metal BLIT encoder for the specified use, @@ -519,6 +521,7 @@ class MVKCommandEncoder : public MVKBaseDeviceObject { MVKPushConstantsCommandEncoderState _tessEvalPushConstants; MVKPushConstantsCommandEncoderState _fragmentPushConstants; MVKPushConstantsCommandEncoderState _computePushConstants; + MVKPushConstantsCommandEncoderState _geometryPushConstants; MVKOcclusionQueryCommandEncoderState _occlusionQueryState; MVKPrefillMetalCommandBuffersStyle _prefillStyle; VkSubpassContents _subpassContents; diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm index c42056850..0832b6954 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm @@ -401,10 +401,17 @@ ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : VK_SUBPASS_CONTENTS_INLINE); - uint32_t maxAttCnt = (pRenderingInfo->colorAttachmentCount + 1) * 2; - MVKImageView* attachments[maxAttCnt]; + uint32_t maxAttCnt = (pRenderingInfo->colorAttachmentCount + 2) * 2; + MVKImageView* imageViews[maxAttCnt]; VkClearValue clearValues[maxAttCnt]; - uint32_t attCnt = mvkGetAttachments(pRenderingInfo, attachments, clearValues); + + uint32_t attCnt = 0; + MVKRenderingAttachmentIterator attIter(pRenderingInfo); + attIter.iterate([&](const VkRenderingAttachmentInfo* pAttInfo, VkImageAspectFlagBits aspect, bool isResolveAttachment)->void { + imageViews[attCnt] = (MVKImageView*)(isResolveAttachment ? pAttInfo->resolveImageView : pAttInfo->imageView); + clearValues[attCnt] = pAttInfo->clearValue; + attCnt++; + }); // If we're resuming a suspended renderpass, continue to use the existing renderpass // (with updated rendering flags) and framebuffer. Otherwise, create new transient @@ -419,13 +426,14 @@ mvkRP->setRenderingFlags(pRenderingInfo->flags); mvkFB = _pEncodingContext->getFramebuffer(); } else { - mvkRP = mvkCreateRenderPass(getDevice(), pRenderingInfo); - mvkFB = mvkCreateFramebuffer(getDevice(), pRenderingInfo, mvkRP); + auto* mvkDev = getDevice(); + mvkRP = mvkDev->createRenderPass(pRenderingInfo, nullptr); + mvkFB = mvkDev->createFramebuffer(pRenderingInfo, nullptr); } beginRenderpass(rendCmd, contents, mvkRP, mvkFB, pRenderingInfo->renderArea, MVKArrayRef(clearValues, attCnt), - MVKArrayRef(attachments, attCnt), + MVKArrayRef(imageViews, attCnt), MVKArrayRef>(), kMVKCommandUseBeginRendering); @@ -832,8 +840,8 @@ endMetalRenderEncoding(); _computePipelineState.markDirty(); - _computeResourcesState.markDirty(); _computePushConstants.markDirty(); + _computeResourcesState.markDirty(); if (_mtlComputeEncoder && _cmdBuffer->_hasStageCounterTimestampCommand) { [_mtlComputeEncoder updateFence: getStageCountersMTLFence()]; } endMetalEncoding(_mtlComputeEncoder); @@ -846,12 +854,18 @@ encodeTimestampStageCounterSamples(); } -id MVKCommandEncoder::getMTLComputeEncoder(MVKCommandUse cmdUse) { +id MVKCommandEncoder::getMTLComputeEncoder(MVKCommandUse cmdUse, bool markCurrentComputeStateDirty) { if ( !_mtlComputeEncoder ) { endCurrentMetalEncoding(); _mtlComputeEncoder = [_mtlCmdBuffer computeCommandEncoder]; retainIfImmediatelyEncoding(_mtlComputeEncoder); beginMetalComputeEncoding(cmdUse); + markCurrentComputeStateDirty = false; // Already marked dirty above in endCurrentMetalEncoding() + } + if(markCurrentComputeStateDirty) { + _computePipelineState.markDirty(); + _computePushConstants.markDirty(); + _computeResourcesState.markDirty(); } if (_mtlComputeEncoderUse != cmdUse) { _mtlComputeEncoderUse = cmdUse; @@ -887,6 +901,7 @@ case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: return &_tessEvalPushConstants; case VK_SHADER_STAGE_FRAGMENT_BIT: return &_fragmentPushConstants; case VK_SHADER_STAGE_COMPUTE_BIT: return &_computePushConstants; + case VK_SHADER_STAGE_GEOMETRY_BIT: return &_geometryPushConstants; default: MVKAssert(false, "Invalid shader stage: %u", shaderStage); return nullptr; @@ -1110,8 +1125,8 @@ MVKCommandEncoder::MVKCommandEncoder(MVKCommandBuffer* cmdBuffer, MVKPrefillMetalCommandBuffersStyle prefillStyle) : MVKBaseDeviceObject(cmdBuffer->getDevice()), _cmdBuffer(cmdBuffer), - _graphicsPipelineState(this), - _computePipelineState(this), + _graphicsPipelineState(this, VK_PIPELINE_BIND_POINT_GRAPHICS), + _computePipelineState(this, VK_PIPELINE_BIND_POINT_COMPUTE), _viewportState(this), _scissorState(this), _depthBiasState(this), @@ -1125,8 +1140,9 @@ _tessEvalPushConstants(this, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT), _fragmentPushConstants(this, VK_SHADER_STAGE_FRAGMENT_BIT), _computePushConstants(this, VK_SHADER_STAGE_COMPUTE_BIT), + _geometryPushConstants(this, VK_SHADER_STAGE_GEOMETRY_BIT), _occlusionQueryState(this), - _prefillStyle(prefillStyle){ + _prefillStyle(prefillStyle){ _pDeviceFeatures = &_device->_enabledFeatures; _pDeviceMetalFeatures = _device->_pMetalFeatures; @@ -1210,7 +1226,7 @@ case kMVKCommandUseClearColorImage: return @"vkCmdClearColorImage ComputeEncoder"; case kMVKCommandUseResolveImage: return @"Resolve Subpass Attachment ComputeEncoder"; case kMVKCommandUseTessellationVertexTessCtl: return @"vkCmdDraw (vertex and tess control stages) ComputeEncoder"; - case kMVKCommandUseMultiviewInstanceCountAdjust: return @"vkCmdDraw (multiview instance count adjustment) ComputeEncoder"; + case kMVKCommandUseDrawIndirectConvertBuffers: return @"vkCmdDraw (convert indirect buffers) ComputeEncoder"; case kMVKCommandUseCopyQueryPoolResults: return @"vkCmdCopyQueryPoolResults ComputeEncoder"; case kMVKCommandUseAccumOcclusionQuery: return @"Post-render-pass occlusion query accumulation ComputeEncoder"; default: return @"Unknown Use ComputeEncoder"; diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h index 8667aabf3..53bc543b0 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h +++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h @@ -81,6 +81,8 @@ class MVKCommandEncoderState : public MVKBaseObject { /** * If the content of this instance is dirty, marks this instance as no longer dirty * and calls the encodeImpl() function to encode the content onto the Metal encoder. + * Marking dirty is done in advance so that subclass encodeImpl() implementations + * can override to leave this instance in a dirty state. * Subclasses must override the encodeImpl() function to do the actual work. */ void encode(uint32_t stage = 0) { @@ -118,13 +120,14 @@ class MVKPipelineCommandEncoderState : public MVKCommandEncoderState { MVKPipeline* getPipeline(); /** Constructs this instance for the specified command encoder. */ - MVKPipelineCommandEncoderState(MVKCommandEncoder* cmdEncoder) - : MVKCommandEncoderState(cmdEncoder) {} + MVKPipelineCommandEncoderState(MVKCommandEncoder* cmdEncoder, VkPipelineBindPoint bindPoint) + : MVKCommandEncoderState(cmdEncoder), _bindPoint(bindPoint) {} protected: void encodeImpl(uint32_t stage) override; MVKPipeline* _pipeline = nullptr; + VkPipelineBindPoint _bindPoint; }; @@ -152,7 +155,7 @@ class MVKViewportCommandEncoderState : public MVKCommandEncoderState { protected: void encodeImpl(uint32_t stage) override; - MVKSmallVector _viewports, _dynamicViewports; + MVKSmallVector _viewports, _dynamicViewports; }; @@ -180,7 +183,7 @@ class MVKScissorCommandEncoderState : public MVKCommandEncoderState { protected: void encodeImpl(uint32_t stage) override; - MVKSmallVector _scissors, _dynamicScissors; + MVKSmallVector _scissors, _dynamicScissors; }; @@ -355,11 +358,11 @@ class MVKResourcesCommandEncoderState : public MVKCommandEncoderState { MVKArrayRef dynamicOffsets, uint32_t& dynamicOffsetIndex); - /** Encodes the Metal resource to the Metal command encoder. */ - virtual void encodeArgumentBufferResourceUsage(MVKShaderStage stage, - id mtlResource, - MTLResourceUsage mtlUsage, - MTLRenderStages mtlStages) = 0; + /** Encodes the indirect use of the Metal resource to the Metal command encoder. */ + virtual void encodeResourceUsage(MVKShaderStage stage, + id mtlResource, + MTLResourceUsage mtlUsage, + MTLRenderStages mtlStages) = 0; void markDirty() override; @@ -430,7 +433,8 @@ class MVKResourcesCommandEncoderState : public MVKCommandEncoderState { // Template function that executes a lambda expression on each dirty element of // a vector of bindings, and marks the bindings and the vector as no longer dirty. - // Clear isDirty flag before operation to allow operation to possibly override. + // Clear binding isDirty flag before operation to allow operation to possibly override. + // If it does override, leave both the bindings and this instance as dirty. template void encodeBinding(V& bindings, bool& bindingsDirtyFlag, @@ -441,7 +445,7 @@ class MVKResourcesCommandEncoderState : public MVKCommandEncoderState { if (b.isDirty) { b.isDirty = false; mtlOperation(_cmdEncoder, b); - if (b.isDirty) { bindingsDirtyFlag = true; } + if (b.isDirty) { _isDirty = bindingsDirtyFlag = true; } } } } @@ -548,10 +552,10 @@ class MVKGraphicsResourcesCommandEncoderState : public MVKResourcesCommandEncode std::function bindTexture, std::function bindSampler); - void encodeArgumentBufferResourceUsage(MVKShaderStage stage, - id mtlResource, - MTLResourceUsage mtlUsage, - MTLRenderStages mtlStages) override; + void encodeResourceUsage(MVKShaderStage stage, + id mtlResource, + MTLResourceUsage mtlUsage, + MTLRenderStages mtlStages) override; /** Offset all buffers for vertex attribute bindings with zero divisors by the given number of strides. */ void offsetZeroDivisorVertexBuffers(MVKGraphicsStage stage, MVKGraphicsPipeline* pipeline, uint32_t firstInstance); @@ -565,7 +569,10 @@ class MVKGraphicsResourcesCommandEncoderState : public MVKResourcesCommandEncode /** Marks any overridden buffer indexes as dirty. */ void markOverriddenBufferIndexesDirty(); + void endMetalRenderPass() override; + void markDirty() override; + void markDirty(MVKShaderStage stage); #pragma mark Construction @@ -577,6 +584,7 @@ class MVKGraphicsResourcesCommandEncoderState : public MVKResourcesCommandEncode void bindMetalArgumentBuffer(MVKShaderStage stage, MVKMTLBufferBinding& buffBind) override; ResourceBindings<8> _shaderStageResourceBindings[kMVKShaderStageFragment + 1]; + std::unordered_map, MTLRenderStages> _renderUsageStages; }; @@ -609,10 +617,10 @@ class MVKComputeResourcesCommandEncoderState : public MVKResourcesCommandEncoder /** Sets the current dynamic offset buffer state. */ void bindDynamicOffsetBuffer(const MVKShaderImplicitRezBinding& binding, bool needDynamicOffsetBuffer); - void encodeArgumentBufferResourceUsage(MVKShaderStage stage, - id mtlResource, - MTLResourceUsage mtlUsage, - MTLRenderStages mtlStages) override; + void encodeResourceUsage(MVKShaderStage stage, + id mtlResource, + MTLResourceUsage mtlUsage, + MTLRenderStages mtlStages) override; /** * Marks the buffer binding using the index as having been overridden, diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm index d8fc5d210..078f35756 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm @@ -22,6 +22,7 @@ #include "MVKRenderPass.h" #include "MVKPipeline.h" #include "MVKQueryPool.h" +#include "MVKBuffer.h" using namespace std; @@ -37,8 +38,18 @@ #pragma mark MVKPipelineCommandEncoderState void MVKPipelineCommandEncoderState::bindPipeline(MVKPipeline* pipeline) { - if (pipeline != _pipeline) markDirty(); - _pipeline = pipeline; + if (pipeline != _pipeline) { + markDirty(); + if (_bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS) { + bool beforeGS = _pipeline && static_cast(_pipeline)->isGeometryPipeline(); + bool afterGS = pipeline && static_cast(pipeline)->isGeometryPipeline(); + // GS and VS use different bind points for vertex bindings (GS uses object shader, VS uses vertex shader) + // So we need to rebind everything if it changes + if (beforeGS != afterGS) + _cmdEncoder->_graphicsResourcesState.markDirty(kMVKShaderStageVertex); + } + } + _pipeline = pipeline; } MVKPipeline* MVKPipelineCommandEncoderState::getPipeline() { return _pipeline; } @@ -328,15 +339,12 @@ MVKCommandEncoderState::beginMetalRenderPass(); MVKRenderSubpass* mvkSubpass = _cmdEncoder->getSubpass(); - MVKPixelFormats* pixFmts = _cmdEncoder->getPixelFormats(); - MTLPixelFormat mtlDSFormat = pixFmts->getMTLPixelFormat(mvkSubpass->getDepthStencilFormat()); - bool prevHasDepthAttachment = _hasDepthAttachment; - _hasDepthAttachment = pixFmts->isDepthFormat(mtlDSFormat); + _hasDepthAttachment = mvkSubpass->isDepthAttachmentUsed(); if (_hasDepthAttachment != prevHasDepthAttachment) { markDirty(); } bool prevHasStencilAttachment = _hasStencilAttachment; - _hasStencilAttachment = pixFmts->isStencilFormat(mtlDSFormat); + _hasStencilAttachment = mvkSubpass->isStencilAttachmentUsed(); if (_hasStencilAttachment != prevHasStencilAttachment) { markDirty(); } } @@ -693,6 +701,11 @@ encodeMetalArgumentBuffer(stage); + MVKPipeline* pipeline = getPipeline(); + if (pipeline && pipeline->usesPhysicalStorageBufferAddressesCapability(stage)) { + getDevice()->encodeGPUAddressableBuffers(this, stage); + } + auto& shaderStage = _shaderStageResourceBindings[stage]; if (shaderStage.swizzleBufferBinding.isDirty) { @@ -755,14 +768,23 @@ } } +void MVKGraphicsResourcesCommandEncoderState::endMetalRenderPass() { + MVKResourcesCommandEncoderState::endMetalRenderPass(); + _renderUsageStages.clear(); +} + // Mark everything as dirty void MVKGraphicsResourcesCommandEncoderState::markDirty() { MVKResourcesCommandEncoderState::markDirty(); - for (uint32_t i = kMVKShaderStageVertex; i <= kMVKShaderStageFragment; i++) { - MVKResourcesCommandEncoderState::markDirty(_shaderStageResourceBindings[i].bufferBindings, _shaderStageResourceBindings[i].areBufferBindingsDirty); - MVKResourcesCommandEncoderState::markDirty(_shaderStageResourceBindings[i].textureBindings, _shaderStageResourceBindings[i].areTextureBindingsDirty); - MVKResourcesCommandEncoderState::markDirty(_shaderStageResourceBindings[i].samplerStateBindings, _shaderStageResourceBindings[i].areSamplerStateBindingsDirty); - } + for (uint32_t i = kMVKShaderStageVertex; i <= kMVKShaderStageFragment; i++) { + markDirty(static_cast(i)); + } +} + +void MVKGraphicsResourcesCommandEncoderState::markDirty(MVKShaderStage stage) { + MVKResourcesCommandEncoderState::markDirty(_shaderStageResourceBindings[stage].bufferBindings, _shaderStageResourceBindings[stage].areBufferBindingsDirty); + MVKResourcesCommandEncoderState::markDirty(_shaderStageResourceBindings[stage].textureBindings, _shaderStageResourceBindings[stage].areTextureBindingsDirty); + MVKResourcesCommandEncoderState::markDirty(_shaderStageResourceBindings[stage].samplerStateBindings, _shaderStageResourceBindings[stage].areSamplerStateBindingsDirty); } void MVKGraphicsResourcesCommandEncoderState::encodeImpl(uint32_t stage) { @@ -804,8 +826,51 @@ }); } else if (!forTessellation && stage == kMVKGraphicsStageRasterization) { +#if MVK_XCODE_14 + if (pipeline->isGeometryPipeline()) { + encodeBindings(kMVKShaderStageGeometry, "geometry", fullImageViewSwizzle, + [pipeline](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void { + if (b.isInline) + [cmdEncoder->_mtlRenderEncoder setMeshBytes: b.mtlBytes + length: b.size + atIndex: b.index]; + else + [cmdEncoder->_mtlRenderEncoder setMeshBuffer: b.mtlBuffer + offset: b.offset + atIndex: b.index]; + }, + [pipeline](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b, const MVKArrayRef s)->void { + [cmdEncoder->_mtlRenderEncoder setMeshBytes: s.data + length: s.size * sizeof(uint32_t) + atIndex: b.index]; + }, + [](MVKCommandEncoder* cmdEncoder, MVKMTLTextureBinding& b)->void { + [cmdEncoder->_mtlRenderEncoder setMeshTexture: b.mtlTexture + atIndex: b.index]; + }, + [](MVKCommandEncoder* cmdEncoder, MVKMTLSamplerStateBinding& b)->void { + [cmdEncoder->_mtlRenderEncoder setMeshSamplerState: b.mtlSamplerState + atIndex: b.index]; + }); + } +#endif encodeBindings(kMVKShaderStageVertex, "vertex", fullImageViewSwizzle, [pipeline](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void { +#if MVK_XCODE_14 + if (pipeline->isGeometryPipeline()) { + if (b.isInline) + [cmdEncoder->_mtlRenderEncoder setObjectBytes: b.mtlBytes + length: b.size + atIndex: b.index]; + else + [cmdEncoder->_mtlRenderEncoder setObjectBuffer: b.mtlBuffer + offset: b.offset + atIndex: b.index]; + + return; + } +#endif + // The app may have bound more vertex attribute buffers than used by the pipeline. // We must not bind those extra buffers to the shader because they might overwrite // any implicit buffers used by the pipeline. @@ -839,19 +904,46 @@ b.isDirty = true; // We haven't written it out, so leave dirty until next time. } }, - [](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b, const MVKArrayRef s)->void { - cmdEncoder->setVertexBytes(cmdEncoder->_mtlRenderEncoder, - s.data, - s.size * sizeof(uint32_t), - b.index); + [pipeline](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b, const MVKArrayRef s)->void { +#if MVK_XCODE_14 + if (pipeline->isGeometryPipeline()) { + [cmdEncoder->_mtlRenderEncoder setObjectBytes: s.data + length: s.size * sizeof(uint32_t) + atIndex: b.index]; + } else +#endif + { + if (b.isInline) + cmdEncoder->setVertexBytes(cmdEncoder->_mtlRenderEncoder, s.data, s.size * sizeof(uint32_t), b.index); + else + [cmdEncoder->_mtlRenderEncoder setVertexBuffer: b.mtlBuffer + offset: b.offset + atIndex: b.index]; + } }, - [](MVKCommandEncoder* cmdEncoder, MVKMTLTextureBinding& b)->void { - [cmdEncoder->_mtlRenderEncoder setVertexTexture: b.mtlTexture - atIndex: b.index]; + [pipeline](MVKCommandEncoder* cmdEncoder, MVKMTLTextureBinding& b)->void { +#if MVK_XCODE_14 + if (pipeline->isGeometryPipeline()) { + [cmdEncoder->_mtlRenderEncoder setObjectTexture: b.mtlTexture + atIndex: b.index]; + } else +#endif + { + [cmdEncoder->_mtlRenderEncoder setVertexTexture: b.mtlTexture + atIndex: b.index]; + } }, - [](MVKCommandEncoder* cmdEncoder, MVKMTLSamplerStateBinding& b)->void { - [cmdEncoder->_mtlRenderEncoder setVertexSamplerState: b.mtlSamplerState - atIndex: b.index]; + [pipeline](MVKCommandEncoder* cmdEncoder, MVKMTLSamplerStateBinding& b)->void { +#if MVK_XCODE_14 + if (pipeline->isGeometryPipeline()) { + [cmdEncoder->_mtlRenderEncoder setObjectSamplerState: b.mtlSamplerState + atIndex: b.index]; + } else +#endif + { + [cmdEncoder->_mtlRenderEncoder setVertexSamplerState: b.mtlSamplerState + atIndex: b.index]; + } }); } @@ -963,10 +1055,10 @@ bindBuffer(stage, buffBind); } -void MVKGraphicsResourcesCommandEncoderState::encodeArgumentBufferResourceUsage(MVKShaderStage stage, - id mtlResource, - MTLResourceUsage mtlUsage, - MTLRenderStages mtlStages) { +void MVKGraphicsResourcesCommandEncoderState::encodeResourceUsage(MVKShaderStage stage, + id mtlResource, + MTLResourceUsage mtlUsage, + MTLRenderStages mtlStages) { if (mtlResource && mtlStages) { if (stage == kMVKShaderStageTessCtl) { auto* mtlCompEnc = _cmdEncoder->getMTLComputeEncoder(kMVKCommandUseTessellationVertexTessCtl); @@ -974,7 +1066,12 @@ } else { auto* mtlRendEnc = _cmdEncoder->_mtlRenderEncoder; if ([mtlRendEnc respondsToSelector: @selector(useResource:usage:stages:)]) { - [mtlRendEnc useResource: mtlResource usage: mtlUsage stages: mtlStages]; + // Within a renderpass, a resource may be used by multiple descriptor bindings, + // each of which may assign a different usage stage. Dynamically accumulate + // usage stages across all descriptor bindings using the resource. + auto& accumStages = _renderUsageStages[mtlResource]; + accumStages |= mtlStages; + [mtlRendEnc useResource: mtlResource usage: mtlUsage stages: accumStages]; } else { [mtlRendEnc useResource: mtlResource usage: mtlUsage]; } @@ -1039,8 +1136,10 @@ encodeMetalArgumentBuffer(kMVKShaderStageCompute); - MVKPipeline* pipeline = getPipeline(); - bool fullImageViewSwizzle = pipeline ? pipeline->fullImageViewSwizzle() : false; + MVKPipeline* pipeline = getPipeline(); + if (pipeline && pipeline->usesPhysicalStorageBufferAddressesCapability(kMVKShaderStageCompute)) { + getDevice()->encodeGPUAddressableBuffers(this, kMVKShaderStageCompute); + } if (_resourceBindings.swizzleBufferBinding.isDirty) { for (auto& b : _resourceBindings.textureBindings) { @@ -1053,6 +1152,7 @@ _resourceBindings.swizzleBufferBinding.index); } else { + bool fullImageViewSwizzle = pipeline ? pipeline->fullImageViewSwizzle() : false; assertMissingSwizzles(_resourceBindings.needsSwizzle && !fullImageViewSwizzle, "compute", _resourceBindings.textureBindings.contents()); } @@ -1116,10 +1216,10 @@ bindBuffer(buffBind); } -void MVKComputeResourcesCommandEncoderState::encodeArgumentBufferResourceUsage(MVKShaderStage stage, - id mtlResource, - MTLResourceUsage mtlUsage, - MTLRenderStages mtlStages) { +void MVKComputeResourcesCommandEncoderState::encodeResourceUsage(MVKShaderStage stage, + id mtlResource, + MTLResourceUsage mtlUsage, + MTLRenderStages mtlStages) { if (mtlResource) { auto* mtlCompEnc = _cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDispatch); [mtlCompEnc useResource: mtlResource usage: mtlUsage]; @@ -1145,7 +1245,7 @@ if ( !_hasRasterized || !vizBuff || _mtlRenderPassQueries.empty() ) { return; } // Nothing to do. id mtlAccumState = _cmdEncoder->getCommandEncodingPool()->getAccumulateOcclusionQueryResultsMTLComputePipelineState(); - id mtlAccumEncoder = _cmdEncoder->getMTLComputeEncoder(kMVKCommandUseAccumOcclusionQuery); + id mtlAccumEncoder = _cmdEncoder->getMTLComputeEncoder(kMVKCommandUseAccumOcclusionQuery, true); [mtlAccumEncoder setComputePipelineState: mtlAccumState]; for (auto& qryLoc : _mtlRenderPassQueries) { // Accumulate the current results to the query pool's buffer. @@ -1158,7 +1258,6 @@ [mtlAccumEncoder dispatchThreadgroups: MTLSizeMake(1, 1, 1) threadsPerThreadgroup: MTLSizeMake(1, 1, 1)]; } - _cmdEncoder->endCurrentMetalEncoding(); _mtlRenderPassQueries.clear(); _hasRasterized = false; } diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.h b/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.h index ba9caf053..ca19abd0c 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.h +++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.h @@ -118,8 +118,11 @@ class MVKCommandEncodingPool : public MVKBaseObject { /** Returns a MTLComputePipelineState for decompressing a buffer into a 3D image. */ id getCmdCopyBufferToImage3DDecompressMTLComputePipelineState(bool needsTempBuff); - /** Returns a MTLComputePipelineState for converting an indirect buffer for use in a multiview draw. */ - id getCmdDrawIndirectMultiviewConvertBuffersMTLComputePipelineState(bool indexed); + /** Returns a MTLComputePipelineState for populating an indirect index buffer from a non-indexed indirect buffer. */ + id getCmdDrawIndirectPopulateIndexesMTLComputePipelineState(); + + /** Returns a MTLComputePipelineState for converting the contents of an indirect buffer. */ + id getCmdDrawIndirectConvertBuffersMTLComputePipelineState(bool indexed); /** Returns a MTLComputePipelineState for converting an indirect buffer for use in a tessellated draw. */ id getCmdDrawIndirectTessConvertBuffersMTLComputePipelineState(bool indexed); @@ -162,10 +165,11 @@ class MVKCommandEncodingPool : public MVKBaseObject { id _cmdClearDefaultDepthStencilState = nil; id _mtlCopyBufferBytesComputePipelineState = nil; id _mtlFillBufferComputePipelineState = nil; + id _mtlDrawIndirectPopulateIndexesComputePipelineState = nil; id _mtlClearColorImageComputePipelineState[3] = {nil, nil, nil}; id _mtlResolveColorImageComputePipelineState[3] = {nil, nil, nil}; id _mtlCopyBufferToImage3DDecompressComputePipelineState[2] = {nil, nil}; - id _mtlDrawIndirectMultiviewConvertBuffersComputePipelineState[2] = {nil, nil}; + id _mtlDrawIndirectConvertBuffersComputePipelineState[2] = {nil, nil}; id _mtlDrawIndirectTessConvertBuffersComputePipelineState[2] = {nil, nil}; id _mtlDrawIndexedCopyIndexBufferComputePipelineState[2] = {nil, nil}; id _mtlCopyQueryPoolResultsComputePipelineState = nil; diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.mm b/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.mm index 1d8c893d7..c2ca7b089 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.mm @@ -139,8 +139,12 @@ static constexpr uint32_t getRenderpassLoadStoreStateIndex(MVKFormatType type) { MVK_ENC_REZ_ACCESS(_mtlCopyBufferToImage3DDecompressComputePipelineState[needsTempBuff ? 1 : 0], newCmdCopyBufferToImage3DDecompressMTLComputePipelineState(needsTempBuff, _commandPool)); } -id MVKCommandEncodingPool::getCmdDrawIndirectMultiviewConvertBuffersMTLComputePipelineState(bool indexed) { - MVK_ENC_REZ_ACCESS(_mtlDrawIndirectMultiviewConvertBuffersComputePipelineState[indexed ? 1 : 0], newCmdDrawIndirectMultiviewConvertBuffersMTLComputePipelineState(indexed, _commandPool)); +id MVKCommandEncodingPool::getCmdDrawIndirectPopulateIndexesMTLComputePipelineState() { + MVK_ENC_REZ_ACCESS(_mtlDrawIndirectPopulateIndexesComputePipelineState, newCmdDrawIndirectPopulateIndexesMTLComputePipelineState(_commandPool)); +} + +id MVKCommandEncodingPool::getCmdDrawIndirectConvertBuffersMTLComputePipelineState(bool indexed) { + MVK_ENC_REZ_ACCESS(_mtlDrawIndirectConvertBuffersComputePipelineState[indexed ? 1 : 0], newCmdDrawIndirectConvertBuffersMTLComputePipelineState(indexed, _commandPool)); } id MVKCommandEncodingPool::getCmdDrawIndirectTessConvertBuffersMTLComputePipelineState(bool indexed) { @@ -217,6 +221,9 @@ static constexpr uint32_t getRenderpassLoadStoreStateIndex(MVKFormatType type) { [_mtlFillBufferComputePipelineState release]; _mtlFillBufferComputePipelineState = nil; + [_mtlDrawIndirectPopulateIndexesComputePipelineState release]; + _mtlDrawIndirectPopulateIndexesComputePipelineState = nil; + [_mtlClearColorImageComputePipelineState[0] release]; [_mtlClearColorImageComputePipelineState[1] release]; [_mtlClearColorImageComputePipelineState[2] release]; @@ -236,10 +243,10 @@ static constexpr uint32_t getRenderpassLoadStoreStateIndex(MVKFormatType type) { _mtlCopyBufferToImage3DDecompressComputePipelineState[0] = nil; _mtlCopyBufferToImage3DDecompressComputePipelineState[1] = nil; - [_mtlDrawIndirectMultiviewConvertBuffersComputePipelineState[0] release]; - [_mtlDrawIndirectMultiviewConvertBuffersComputePipelineState[1] release]; - _mtlDrawIndirectMultiviewConvertBuffersComputePipelineState[0] = nil; - _mtlDrawIndirectMultiviewConvertBuffersComputePipelineState[1] = nil; + [_mtlDrawIndirectConvertBuffersComputePipelineState[0] release]; + [_mtlDrawIndirectConvertBuffersComputePipelineState[1] release]; + _mtlDrawIndirectConvertBuffersComputePipelineState[0] = nil; + _mtlDrawIndirectConvertBuffersComputePipelineState[1] = nil; [_mtlDrawIndirectTessConvertBuffersComputePipelineState[0] release]; [_mtlDrawIndirectTessConvertBuffersComputePipelineState[1] release]; diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandPipelineStateFactoryShaderSource.h b/MoltenVK/MoltenVK/Commands/MVKCommandPipelineStateFactoryShaderSource.h index acd492fc9..39060f537 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandPipelineStateFactoryShaderSource.h +++ b/MoltenVK/MoltenVK/Commands/MVKCommandPipelineStateFactoryShaderSource.h @@ -222,28 +222,119 @@ struct MTLStageInRegionIndirectArguments { }; \n\ #endif \n\ \n\ -kernel void cmdDrawIndirectMultiviewConvertBuffers(const device char* srcBuff [[buffer(0)]], \n\ - device MTLDrawPrimitivesIndirectArguments* destBuff [[buffer(1)]],\n\ - constant uint32_t& srcStride [[buffer(2)]], \n\ - constant uint32_t& drawCount [[buffer(3)]], \n\ - constant uint32_t& viewCount [[buffer(4)]], \n\ - uint idx [[thread_position_in_grid]]) { \n\ +typedef enum : uint8_t { \n\ + MTLIndexTypeUInt16 = 0, \n\ + MTLIndexTypeUInt32 = 1, \n\ +} MTLIndexType; \n\ + \n\ +typedef struct MVKVtxAdj { \n\ + MTLIndexType idxType; \n\ + bool isMultiView; \n\ + bool isTriFan; \n\ +} MVKVtxAdj; \n\ + \n\ +// Populates triangle vertex indexes for a triangle fan. \n\ +template \n\ +static inline void populateTriIndxsFromTriFan(device T* triIdxs, \n\ + constant T* triFanIdxs, \n\ + uint32_t triFanIdxCnt) { \n\ + T primRestartSentinel = (T)0xFFFFFFFF; \n\ + uint32_t triIdxIdx = 0; \n\ + uint32_t triFanBaseIdx = 0; \n\ + uint32_t triFanIdxIdx = triFanBaseIdx + 2; \n\ + while (triFanIdxIdx < triFanIdxCnt) { \n\ + uint32_t triFanBaseIdxCurr = triFanBaseIdx; \n\ + \n\ + // Detect primitive restart on any index, to catch possible consecutive restarts \n\ + T triIdx0 = triFanIdxs[triFanBaseIdx]; \n\ + if (triIdx0 == primRestartSentinel) \n\ + triFanBaseIdx++; \n\ + \n\ + T triIdx1 = triFanIdxs[triFanIdxIdx - 1]; \n\ + if (triIdx1 == primRestartSentinel) \n\ + triFanBaseIdx = triFanIdxIdx; \n\ + \n\ + T triIdx2 = triFanIdxs[triFanIdxIdx]; \n\ + if (triIdx2 == primRestartSentinel) \n\ + triFanBaseIdx = triFanIdxIdx + 1; \n\ + \n\ + if (triFanBaseIdx != triFanBaseIdxCurr) { // Restart the triangle fan \n\ + triFanIdxIdx = triFanBaseIdx + 2; \n\ + } else { \n\ + // Provoking vertex is 1 in triangle fan but 0 in triangle list \n\ + triIdxs[triIdxIdx++] = triIdx1; \n\ + triIdxs[triIdxIdx++] = triIdx2; \n\ + triIdxs[triIdxIdx++] = triIdx0; \n\ + triFanIdxIdx++; \n\ + } \n\ + } \n\ +} \n\ + \n\ +kernel void cmdDrawIndirectPopulateIndexes(const device char* srcBuff [[buffer(0)]], \n\ + device MTLDrawIndexedPrimitivesIndirectArguments* destBuff [[buffer(1)]],\n\ + constant uint32_t& srcStride [[buffer(2)]], \n\ + constant uint32_t& drawCount [[buffer(3)]], \n\ + device uint32_t* idxBuff [[buffer(4)]], \n\ + uint idx [[thread_position_in_grid]]) { \n\ + if (idx >= drawCount) { return; } \n\ + const device auto& src = *reinterpret_cast(srcBuff + idx * srcStride);\n\ + device auto& dst = destBuff[idx]; \n\ + dst.indexCount = src.vertexCount; \n\ + dst.indexStart = src.vertexStart; \n\ + dst.baseVertex = 0; \n\ + dst.instanceCount = src.instanceCount; \n\ + dst.baseInstance = src.baseInstance; \n\ + \n\ + for (uint32_t idxIdx = 0; idxIdx < dst.indexCount; idxIdx++) { \n\ + uint32_t idxBuffIdx = dst.indexStart + idxIdx; \n\ + idxBuff[idxBuffIdx] = idxBuffIdx; \n\ + } \n\ +} \n\ + \n\ +kernel void cmdDrawIndirectConvertBuffers(const device char* srcBuff [[buffer(0)]], \n\ + device MTLDrawPrimitivesIndirectArguments* destBuff [[buffer(1)]], \n\ + constant uint32_t& srcStride [[buffer(2)]], \n\ + constant uint32_t& drawCount [[buffer(3)]], \n\ + constant uint32_t& viewCount [[buffer(4)]], \n\ + uint idx [[thread_position_in_grid]]) { \n\ if (idx >= drawCount) { return; } \n\ const device auto& src = *reinterpret_cast(srcBuff + idx * srcStride);\n\ destBuff[idx] = src; \n\ destBuff[idx].instanceCount *= viewCount; \n\ } \n\ \n\ -kernel void cmdDrawIndexedIndirectMultiviewConvertBuffers(const device char* srcBuff [[buffer(0)]], \n\ - device MTLDrawIndexedPrimitivesIndirectArguments* destBuff [[buffer(1)]],\n\ - constant uint32_t& srcStride [[buffer(2)]], \n\ - constant uint32_t& drawCount [[buffer(3)]], \n\ - constant uint32_t& viewCount [[buffer(4)]], \n\ - uint idx [[thread_position_in_grid]]) { \n\ +kernel void cmdDrawIndexedIndirectConvertBuffers(const device char* srcBuff [[buffer(0)]], \n\ + device MTLDrawIndexedPrimitivesIndirectArguments* destBuff [[buffer(1)]],\n\ + constant uint32_t& srcStride [[buffer(2)]], \n\ + constant uint32_t& drawCount [[buffer(3)]], \n\ + constant uint32_t& viewCount [[buffer(4)]], \n\ + constant MVKVtxAdj& vtxAdj [[buffer(5)]], \n\ + device void* triIdxs [[buffer(6)]], \n\ + constant void* triFanIdxs [[buffer(7)]], \n\ + uint idx [[thread_position_in_grid]]) { \n\ if (idx >= drawCount) { return; } \n\ const device auto& src = *reinterpret_cast(srcBuff + idx * srcStride);\n\ destBuff[idx] = src; \n\ - destBuff[idx].instanceCount *= viewCount; \n\ + \n\ + device auto& dst = destBuff[idx]; \n\ + if (vtxAdj.isMultiView) { \n\ + dst.instanceCount *= viewCount; \n\ + } \n\ + if (vtxAdj.isTriFan) { \n\ + dst.indexCount = (src.indexCount - 2) * 3; \n\ + switch (vtxAdj.idxType) { \n\ + case MTLIndexTypeUInt16: \n\ + populateTriIndxsFromTriFan(&((device uint16_t*)triIdxs)[dst.indexStart], \n\ + &((constant uint16_t*)triFanIdxs)[src.indexStart], \n\ + src.indexCount); \n\ + break; \n\ + case MTLIndexTypeUInt32: \n\ + populateTriIndxsFromTriFan(&((device uint32_t*)triIdxs)[dst.indexStart], \n\ + &((constant uint32_t*)triFanIdxs)[src.indexStart], \n\ + src.indexCount); \n\ + break; \n\ + } \n\ + } \n\ } \n\ \n\ #if __METAL_VERSION__ >= 120 \n\ @@ -292,16 +383,16 @@ kernel void cmdDrawIndirectTessConvertBuffers(const device char* srcBuff [[buffe #endif \n\ } \n\ \n\ -kernel void cmdDrawIndexedIndirectConvertBuffers(const device char* srcBuff [[buffer(0)]], \n\ - device char* destBuff [[buffer(1)]], \n\ - device char* paramsBuff [[buffer(2)]], \n\ - constant uint32_t& srcStride [[buffer(3)]], \n\ - constant uint32_t& inControlPointCount [[buffer(4)]], \n\ - constant uint32_t& outControlPointCount [[buffer(5)]], \n\ - constant uint32_t& drawCount [[buffer(6)]], \n\ - constant uint32_t& vtxThreadExecWidth [[buffer(7)]], \n\ - constant uint32_t& tcWorkgroupSize [[buffer(8)]], \n\ - uint idx [[thread_position_in_grid]]) { \n\ +kernel void cmdDrawIndexedIndirectTessConvertBuffers(const device char* srcBuff [[buffer(0)]], \n\ + device char* destBuff [[buffer(1)]], \n\ + device char* paramsBuff [[buffer(2)]], \n\ + constant uint32_t& srcStride [[buffer(3)]], \n\ + constant uint32_t& inControlPointCount [[buffer(4)]], \n\ + constant uint32_t& outControlPointCount [[buffer(5)]], \n\ + constant uint32_t& drawCount [[buffer(6)]], \n\ + constant uint32_t& vtxThreadExecWidth [[buffer(7)]], \n\ + constant uint32_t& tcWorkgroupSize [[buffer(8)]], \n\ + uint idx [[thread_position_in_grid]]) { \n\ if (idx >= drawCount) { return; } \n\ const device auto& src = *reinterpret_cast(srcBuff + idx * srcStride);\n\ device char* dest; \n\ diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.h b/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.h index bd30da20c..84fa37b64 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.h +++ b/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.h @@ -37,20 +37,31 @@ class MVKQueryPool; * This structure can be used as a key in a std::map and std::unordered_map. */ typedef struct MVKRPSKeyBlitImg { - uint16_t srcMTLPixelFormat = 0; /**< as MTLPixelFormat */ - uint16_t dstMTLPixelFormat = 0; /**< as MTLPixelFormat */ - uint8_t srcMTLTextureType = 0; /**< as MTLTextureType */ + uint16_t srcMTLPixelFormat : 12; /**< as MTLPixelFormat */ + uint16_t dstMTLPixelFormat : 12; /**< as MTLPixelFormat */ + uint8_t srcMTLTextureType : 4; /**< as MTLTextureType */ + uint8_t srcFilter : 4; /**< as MTLSamplerMinMagFilter */ uint8_t srcAspect = 0; /**< as VkImageAspectFlags */ - uint8_t srcFilter = 0; /**< as MTLSamplerMinMagFilter */ uint8_t dstSampleCount = 0; + uint8_t srcSwizzleR : 4; /**< as VkComponentSwizzle */ + uint8_t srcSwizzleG : 4; /**< as VkComponentSwizzle */ + uint8_t srcSwizzleB : 4; /**< as VkComponentSwizzle */ + uint8_t srcSwizzleA : 4; /**< as VkComponentSwizzle */ + + MVKRPSKeyBlitImg() : srcMTLPixelFormat(0), dstMTLPixelFormat(0), srcMTLTextureType(0), srcFilter(0), + srcSwizzleR(0), srcSwizzleG(0), srcSwizzleB(0), srcSwizzleA(0) {} bool operator==(const MVKRPSKeyBlitImg& rhs) const { if (srcMTLPixelFormat != rhs.srcMTLPixelFormat) { return false; } if (dstMTLPixelFormat != rhs.dstMTLPixelFormat) { return false; } if (srcMTLTextureType != rhs.srcMTLTextureType) { return false; } - if (srcAspect != rhs.srcAspect) { return false; } if (srcFilter != rhs.srcFilter) { return false; } + if (srcAspect != rhs.srcAspect) { return false; } if (dstSampleCount != rhs.dstSampleCount) { return false; } + if (srcSwizzleR != rhs.srcSwizzleR) { return false; } + if (srcSwizzleG != rhs.srcSwizzleG) { return false; } + if (srcSwizzleB != rhs.srcSwizzleB) { return false; } + if (srcSwizzleA != rhs.srcSwizzleA) { return false; } return true; } @@ -70,23 +81,40 @@ typedef struct MVKRPSKeyBlitImg { srcMTLTextureType == MTLTextureType1DArray); } + VkComponentMapping getSrcSwizzle() { + return { (VkComponentSwizzle)srcSwizzleR, (VkComponentSwizzle)srcSwizzleG, + (VkComponentSwizzle)srcSwizzleB, (VkComponentSwizzle)srcSwizzleA }; + } + std::size_t hash() const { std::size_t hash = srcMTLPixelFormat; - hash <<= 16; + hash <<= 12; hash |= dstMTLPixelFormat; - hash <<= 8; + hash <<= 4; hash |= srcMTLTextureType; - hash <<= 8; - hash |= srcAspect; + hash <<= 4; + hash |= srcFilter; hash <<= 8; - hash |= srcFilter; + hash |= srcAspect; hash <<= 8; hash |= dstSampleCount; + + hash <<= 4; + hash |= srcSwizzleR; + + hash <<= 4; + hash |= srcSwizzleG; + + hash <<= 4; + hash |= srcSwizzleB; + + hash <<= 4; + hash |= srcSwizzleA; return hash; } @@ -107,9 +135,11 @@ namespace std { #pragma mark - #pragma mark MVKRPSKeyClearAtt -#define kMVKClearAttachmentCount (kMVKCachedColorAttachmentCount + 1) -#define kMVKClearAttachmentDepthStencilIndex (kMVKClearAttachmentCount - 1) -#define kMVKClearAttachmentLayeredRenderingBitIndex kMVKClearAttachmentCount +const static uint32_t kMVKClearColorAttachmentCount = kMVKMaxColorAttachmentCount; +const static uint32_t kMVKClearAttachmentDepthIndex = kMVKClearColorAttachmentCount; +const static uint32_t kMVKClearAttachmentStencilIndex = kMVKClearAttachmentDepthIndex + 1; +const static uint32_t kMVKClearAttachmentCount = kMVKClearAttachmentStencilIndex + 1; +const static uint32_t kMVKClearAttachmentLayeredRenderingBitIndex = kMVKClearAttachmentStencilIndex + 1; /** * Key to use for looking up cached MTLRenderPipelineState instances. @@ -439,9 +469,12 @@ class MVKCommandResourceFactory : public MVKBaseDeviceObject { id newCmdCopyBufferToImage3DDecompressMTLComputePipelineState(bool needTempBuf, MVKVulkanAPIDeviceObject* owner); - /** Returns a new MTLComputePipelineState for converting an indirect buffer for use in a multiview draw. */ - id newCmdDrawIndirectMultiviewConvertBuffersMTLComputePipelineState(bool indexed, - MVKVulkanAPIDeviceObject* owner); + /** Returns a new MTLComputePipelineState for populating an indirect index buffer from a non-indexed indirect buffer. */ + id newCmdDrawIndirectPopulateIndexesMTLComputePipelineState(MVKVulkanAPIDeviceObject* owner); + + /** Returns a new MTLComputePipelineState for converting the contents of an indirect buffer. */ + id newCmdDrawIndirectConvertBuffersMTLComputePipelineState(bool indexed, + MVKVulkanAPIDeviceObject* owner); /** Returns a new MTLComputePipelineState for converting an indirect buffer for use in a tessellated draw. */ id newCmdDrawIndirectTessConvertBuffersMTLComputePipelineState(bool indexed, diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm b/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm index d6c6efb6d..b3003507c 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm @@ -113,6 +113,8 @@ id MVKCommandResourceFactory::newCmdClearMTLRenderPipelineState(MVKRPSKeyClearAtt& attKey, MVKVulkanAPIDeviceObject* owner) { + MVKPixelFormats* pixFmts = getPixelFormats(); + id vtxFunc = newClearVertFunction(attKey); // temp retain id fragFunc = newClearFragFunction(attKey); // temp retain MTLRenderPipelineDescriptor* plDesc = [MTLRenderPipelineDescriptor new]; // temp retain @@ -122,15 +124,17 @@ plDesc.sampleCount = attKey.mtlSampleCount; plDesc.inputPrimitiveTopologyMVK = MTLPrimitiveTopologyClassTriangle; - for (uint32_t caIdx = 0; caIdx < kMVKClearAttachmentDepthStencilIndex; caIdx++) { + for (uint32_t caIdx = 0; caIdx < kMVKClearColorAttachmentCount; caIdx++) { MTLRenderPipelineColorAttachmentDescriptor* colorDesc = plDesc.colorAttachments[caIdx]; colorDesc.pixelFormat = (MTLPixelFormat)attKey.attachmentMTLPixelFormats[caIdx]; colorDesc.writeMask = attKey.isAttachmentEnabled(caIdx) ? MTLColorWriteMaskAll : MTLColorWriteMaskNone; } - MVKPixelFormats* pixFmts = getPixelFormats(); - MTLPixelFormat mtlDSFormat = (MTLPixelFormat)attKey.attachmentMTLPixelFormats[kMVKClearAttachmentDepthStencilIndex]; - if (pixFmts->isDepthFormat(mtlDSFormat)) { plDesc.depthAttachmentPixelFormat = mtlDSFormat; } - if (pixFmts->isStencilFormat(mtlDSFormat)) { plDesc.stencilAttachmentPixelFormat = mtlDSFormat; } + + MTLPixelFormat mtlDepthFormat = (MTLPixelFormat)attKey.attachmentMTLPixelFormats[kMVKClearAttachmentDepthIndex]; + if (pixFmts->isDepthFormat(mtlDepthFormat)) { plDesc.depthAttachmentPixelFormat = mtlDepthFormat; } + + MTLPixelFormat mtlStencilFormat = (MTLPixelFormat)attKey.attachmentMTLPixelFormats[kMVKClearAttachmentStencilIndex]; + if (pixFmts->isStencilFormat(mtlStencilFormat)) { plDesc.stencilAttachmentPixelFormat = mtlStencilFormat; } MTLVertexDescriptor* vtxDesc = plDesc.vertexDescriptor; @@ -163,6 +167,25 @@ return rps; } +static char getSwizzleChar(char defaultChar, VkComponentSwizzle vkSwizzle) { + switch (vkSwizzle) { + case VK_COMPONENT_SWIZZLE_IDENTITY: return defaultChar; + // FIXME: 0 and 1 (currently not used in any default swizzles) + case VK_COMPONENT_SWIZZLE_R: return 'x'; + case VK_COMPONENT_SWIZZLE_G: return 'y'; + case VK_COMPONENT_SWIZZLE_B: return 'z'; + case VK_COMPONENT_SWIZZLE_A: return 'w'; + default: return defaultChar; + } +} + +static void getSwizzleString(char swizzleStr[4], VkComponentMapping vkMapping) { + swizzleStr[0] = getSwizzleChar('x', vkMapping.r); + swizzleStr[1] = getSwizzleChar('y', vkMapping.g); + swizzleStr[2] = getSwizzleChar('z', vkMapping.b); + swizzleStr[3] = getSwizzleChar('w', vkMapping.a); +} + id MVKCommandResourceFactory::newBlitFragFunction(MVKRPSKeyBlitImg& blitKey) { @autoreleasepool { bool isLayeredBlit = blitKey.dstSampleCount > 1 ? _device->_pMetalFeatures->multisampleLayeredRendering : _device->_pMetalFeatures->layeredRendering; @@ -173,6 +196,7 @@ NSString* typePrefix = @"texture"; NSString* typeSuffix; NSString* coordArg; + char swizzleArg[4] = { 'x', 'y', 'z', 'w' }; if (mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_DEPTH_BIT))) { typePrefix = @"depth"; } @@ -204,6 +228,9 @@ } NSString* sliceArg = isArrayType ? (isLayeredBlit ? @", subRez.slice + varyings.v_layer" : @", subRez.slice") : @""; NSString* srcFilter = isLinearFilter ? @"linear" : @"nearest"; + if (!getDevice()->_pMetalFeatures->nativeTextureSwizzle) { + getSwizzleString(swizzleArg, blitKey.getSrcSwizzle()); + } NSMutableString* msl = [NSMutableString stringWithCapacity: (2 * KIBI) ]; [msl appendLineMVK: @"#include "]; @@ -259,21 +286,21 @@ [msl appendLineMVK: @" constant TexSubrez& subRez [[buffer(0)]]) {"]; [msl appendLineMVK: @" FragmentOutputs out;"]; if (mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_DEPTH_BIT))) { - [msl appendFormat: @" out.depth = tex.sample(ce_sampler, varyings.v_texCoord%@%@, level(subRez.lod));", coordArg, sliceArg]; + [msl appendFormat: @" out.depth = tex.sample(ce_sampler, varyings.v_texCoord%@%@, level(subRez.lod)).%c;", coordArg, sliceArg, swizzleArg[0]]; [msl appendLineMVK]; } if (mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_STENCIL_BIT))) { - [msl appendFormat: @" out.stencil = stencilTex.sample(ce_stencil_sampler, varyings.v_texCoord%@%@, level(subRez.lod)).x;", coordArg, sliceArg]; + [msl appendFormat: @" out.stencil = stencilTex.sample(ce_stencil_sampler, varyings.v_texCoord%@%@, level(subRez.lod)).%c;", coordArg, sliceArg, swizzleArg[0]]; [msl appendLineMVK]; } if (!mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))) { - [msl appendFormat: @" out.color = tex.sample(ce_sampler, varyings.v_texCoord%@%@, level(subRez.lod));", coordArg, sliceArg]; + [msl appendFormat: @" out.color = tex.sample(ce_sampler, varyings.v_texCoord%@%@, level(subRez.lod)).%.4s;", coordArg, sliceArg, swizzleArg]; [msl appendLineMVK]; } [msl appendLineMVK: @" return out;"]; [msl appendLineMVK: @"}"]; -// MVKLogDebug("\n%s", msl.UTF8String); +// MVKLogInfo("\n%s", msl.UTF8String); return newMTLFunction(msl, funcName); } @@ -300,15 +327,16 @@ [msl appendLineMVK]; NSString* funcName = @"vertClear"; - [msl appendFormat: @"vertex VaryingsPos %@(AttributesPos attributes [[stage_in]], constant ClearColorsIn& ccIn [[buffer(0)]]) {", funcName]; + [msl appendFormat: @"vertex VaryingsPos %@(AttributesPos attributes [[stage_in]], constant ClearColorsIn& ccIn [[buffer(0)]]) {", funcName]; [msl appendLineMVK]; [msl appendLineMVK: @" VaryingsPos varyings;"]; - [msl appendLineMVK: @" varyings.v_position = float4(attributes.a_position.x, -attributes.a_position.y, ccIn.colors[8].r, 1.0);"]; + [msl appendFormat: @" varyings.v_position = float4(attributes.a_position.x, -attributes.a_position.y, ccIn.colors[%d].r, 1.0);", kMVKClearAttachmentDepthIndex]; + [msl appendLineMVK]; [msl appendLineMVK: @" varyings.layer = uint(attributes.a_position.w);"]; [msl appendLineMVK: @" return varyings;"]; [msl appendLineMVK: @"}"]; -// MVKLogDebug("\n%s", msl.UTF8String); +// MVKLogInfo("\n%s", msl.UTF8String); return newMTLFunction(msl, funcName); } @@ -329,7 +357,7 @@ [msl appendLineMVK: @"} ClearColorsIn;"]; [msl appendLineMVK]; [msl appendLineMVK: @"typedef struct {"]; - for (uint32_t caIdx = 0; caIdx < kMVKClearAttachmentDepthStencilIndex; caIdx++) { + for (uint32_t caIdx = 0; caIdx < kMVKClearColorAttachmentCount; caIdx++) { if (attKey.isAttachmentUsed(caIdx)) { NSString* typeStr = getMTLFormatTypeString((MTLPixelFormat)attKey.attachmentMTLPixelFormats[caIdx]); [msl appendFormat: @" %@4 color%u [[color(%u)]];", typeStr, caIdx, caIdx]; @@ -343,7 +371,7 @@ [msl appendFormat: @"fragment ClearColorsOut %@(VaryingsPos varyings [[stage_in]], constant ClearColorsIn& ccIn [[buffer(0)]]) {", funcName]; [msl appendLineMVK]; [msl appendLineMVK: @" ClearColorsOut ccOut;"]; - for (uint32_t caIdx = 0; caIdx < kMVKClearAttachmentDepthStencilIndex; caIdx++) { + for (uint32_t caIdx = 0; caIdx < kMVKClearColorAttachmentCount; caIdx++) { if (attKey.isAttachmentUsed(caIdx)) { NSString* typeStr = getMTLFormatTypeString((MTLPixelFormat)attKey.attachmentMTLPixelFormats[caIdx]); [msl appendFormat: @" ccOut.color%u = %@4(ccIn.colors[%u]);", caIdx, typeStr, caIdx]; @@ -353,7 +381,7 @@ [msl appendLineMVK: @" return ccOut;"]; [msl appendLineMVK: @"}"]; -// MVKLogDebug("\n%s", msl.UTF8String); +// MVKLogInfo("\n%s", msl.UTF8String); return newMTLFunction(msl, funcName); } @@ -552,11 +580,15 @@ : "cmdCopyBufferToImage3DDecompressDXTn", owner); } -id MVKCommandResourceFactory::newCmdDrawIndirectMultiviewConvertBuffersMTLComputePipelineState(bool indexed, - MVKVulkanAPIDeviceObject* owner) { +id MVKCommandResourceFactory::newCmdDrawIndirectConvertBuffersMTLComputePipelineState(bool indexed, + MVKVulkanAPIDeviceObject* owner) { return newMTLComputePipelineState(indexed - ? "cmdDrawIndexedIndirectMultiviewConvertBuffers" - : "cmdDrawIndirectMultiviewConvertBuffers", owner); + ? "cmdDrawIndexedIndirectConvertBuffers" + : "cmdDrawIndirectConvertBuffers", owner); +} + +id MVKCommandResourceFactory::newCmdDrawIndirectPopulateIndexesMTLComputePipelineState(MVKVulkanAPIDeviceObject* owner) { + return newMTLComputePipelineState("cmdDrawIndirectPopulateIndexes", owner); } id MVKCommandResourceFactory::newCmdDrawIndirectTessConvertBuffersMTLComputePipelineState(bool indexed, diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm index 181b220c5..a99f4f0fc 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm @@ -19,7 +19,6 @@ #include "MVKBuffer.h" #include "MVKCommandBuffer.h" #include "MVKFoundation.h" -#include "MVKEnvironment.h" #include "mvk_datatypes.hpp" using namespace std; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h index 229b65dc8..d3851e6a9 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.h @@ -120,6 +120,7 @@ class MVKDescriptorSetLayoutBinding : public MVKBaseDeviceObject { /** Encodes the descriptors in the descriptor set that are specified by this layout, */ void bind(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKDescriptorSet* descSet, MVKShaderResourceBinding& dslMTLRezIdxOffsets, MVKArrayRef dynamicOffsets, @@ -127,6 +128,7 @@ class MVKDescriptorSetLayoutBinding : public MVKBaseDeviceObject { /** Encodes this binding layout and the specified descriptor on the specified command encoder immediately. */ void push(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, uint32_t& dstArrayElement, uint32_t& descriptorCount, uint32_t& descriptorsPushed, @@ -207,6 +209,7 @@ class MVKDescriptor : public MVKBaseObject { /** Encodes this descriptor (based on its layout binding index) on the the command encoder. */ virtual void bind(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKDescriptorSetLayoutBinding* mvkDSLBind, uint32_t elementIndex, bool stages[], @@ -273,6 +276,7 @@ class MVKBufferDescriptor : public MVKDescriptor { public: void bind(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKDescriptorSetLayoutBinding* mvkDSLBind, uint32_t elementIndex, bool stages[], @@ -362,6 +366,7 @@ class MVKInlineUniformBlockDescriptor : public MVKDescriptor { VkDescriptorType getDescriptorType() override { return VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT; } void bind(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKDescriptorSetLayoutBinding* mvkDSLBind, uint32_t elementIndex, bool stages[], @@ -411,6 +416,7 @@ class MVKImageDescriptor : public MVKDescriptor { public: void bind(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKDescriptorSetLayoutBinding* mvkDSLBind, uint32_t elementIndex, bool stages[], @@ -491,6 +497,7 @@ class MVKSamplerDescriptorMixin { protected: void bind(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKDescriptorSetLayoutBinding* mvkDSLBind, uint32_t elementIndex, bool stages[], @@ -538,6 +545,7 @@ class MVKSamplerDescriptor : public MVKDescriptor, public MVKSamplerDescriptorMi VkDescriptorType getDescriptorType() override { return VK_DESCRIPTOR_TYPE_SAMPLER; } void bind(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKDescriptorSetLayoutBinding* mvkDSLBind, uint32_t elementIndex, bool stages[], @@ -585,6 +593,7 @@ class MVKCombinedImageSamplerDescriptor : public MVKImageDescriptor, public MVKS VkDescriptorType getDescriptorType() override { return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; } void bind(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKDescriptorSetLayoutBinding* mvkDSLBind, uint32_t elementIndex, bool stages[], @@ -630,6 +639,7 @@ class MVKTexelBufferDescriptor : public MVKDescriptor { public: void bind(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKDescriptorSetLayoutBinding* mvkDSLBind, uint32_t elementIndex, bool stages[], diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm index 172fb0366..556defa3f 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptor.mm @@ -20,6 +20,16 @@ #include "MVKDescriptorSet.h" #include "MVKBuffer.h" +#define BIND_GRAPHICS_OR_COMPUTE(cmdEncoder, bind, pipelineBindPoint, stage, ...) \ + do { \ + if ((stage) == kMVKShaderStageCompute) { \ + if ((cmdEncoder) && (pipelineBindPoint) == VK_PIPELINE_BIND_POINT_COMPUTE) \ + (cmdEncoder)->_computeResourcesState.bind(__VA_ARGS__); \ + } else { \ + if ((cmdEncoder) && (pipelineBindPoint) == VK_PIPELINE_BIND_POINT_GRAPHICS) \ + (cmdEncoder)->_graphicsResourcesState.bind(static_cast(stage), __VA_ARGS__); \ + } \ + } while (0) #pragma mark MVKShaderStageResourceBinding @@ -124,6 +134,7 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s spv::ExecutionModelVertex, spv::ExecutionModelTessellationControl, spv::ExecutionModelTessellationEvaluation, + spv::ExecutionModelGeometry, spv::ExecutionModelFragment, spv::ExecutionModelGLCompute }; @@ -195,6 +206,7 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s // A null cmdEncoder can be passed to perform a validation pass void MVKDescriptorSetLayoutBinding::bind(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKDescriptorSet* descSet, MVKShaderResourceBinding& dslMTLRezIdxOffsets, MVKArrayRef dynamicOffsets, @@ -208,7 +220,7 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s for (uint32_t descIdx = 0; descIdx < descCnt; descIdx++) { MVKDescriptor* mvkDesc = descSet->getDescriptor(getBinding(), descIdx); if (mvkDesc->getDescriptorType() == descType) { - mvkDesc->bind(cmdEncoder, this, descIdx, _applyToStage, mtlIdxs, dynamicOffsets, dynamicOffsetIndex); + mvkDesc->bind(cmdEncoder, pipelineBindPoint, this, descIdx, _applyToStage, mtlIdxs, dynamicOffsets, dynamicOffsetIndex); } } } @@ -220,6 +232,7 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s // A null cmdEncoder can be passed to perform a validation pass void MVKDescriptorSetLayoutBinding::push(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, uint32_t& dstArrayElement, uint32_t& descriptorCount, uint32_t& descriptorsPushed, @@ -271,11 +284,7 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageCount; i++) { if (_applyToStage[i]) { bb.index = mtlIdxs.stages[i].bufferIndex + rezIdx; - if (i == kMVKShaderStageCompute) { - if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindBuffer(bb); } - } else { - if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindBuffer(MVKShaderStage(i), bb); } - } + BIND_GRAPHICS_OR_COMPUTE(cmdEncoder, bindBuffer, pipelineBindPoint, i, bb); } } break; @@ -289,11 +298,7 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageCount; i++) { if (_applyToStage[i]) { bb.index = mtlIdxs.stages[i].bufferIndex; - if (i == kMVKShaderStageCompute) { - if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindBuffer(bb); } - } else { - if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindBuffer(MVKShaderStage(i), bb); } - } + BIND_GRAPHICS_OR_COMPUTE(cmdEncoder, bindBuffer, pipelineBindPoint, i, bb); } } break; @@ -318,18 +323,10 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageCount; i++) { if (_applyToStage[i]) { tb.index = mtlIdxs.stages[i].textureIndex + rezIdx + planeIndex; - if (i == kMVKShaderStageCompute) { - if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindTexture(tb); } - } else { - if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindTexture(MVKShaderStage(i), tb); } - } + BIND_GRAPHICS_OR_COMPUTE(cmdEncoder, bindTexture, pipelineBindPoint, i, tb); if (_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) { bb.index = mtlIdxs.stages[i].bufferIndex + rezIdx; - if (i == kMVKShaderStageCompute) { - if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindBuffer(bb); } - } else { - if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindBuffer(MVKShaderStage(i), bb); } - } + BIND_GRAPHICS_OR_COMPUTE(cmdEncoder, bindBuffer, pipelineBindPoint, i, bb); } } } @@ -351,18 +348,10 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageCount; i++) { if (_applyToStage[i]) { tb.index = mtlIdxs.stages[i].textureIndex + rezIdx; - if (i == kMVKShaderStageCompute) { - if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindTexture(tb); } - } else { - if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindTexture(MVKShaderStage(i), tb); } - } + BIND_GRAPHICS_OR_COMPUTE(cmdEncoder, bindTexture, pipelineBindPoint, i, tb); if (_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) { bb.index = mtlIdxs.stages[i].bufferIndex + rezIdx; - if (i == kMVKShaderStageCompute) { - if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindBuffer(bb); } - } else { - if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindBuffer(MVKShaderStage(i), bb); } - } + BIND_GRAPHICS_OR_COMPUTE(cmdEncoder, bindBuffer, pipelineBindPoint, i, bb); } } } @@ -381,11 +370,7 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageCount; i++) { if (_applyToStage[i]) { sb.index = mtlIdxs.stages[i].samplerIndex + rezIdx; - if (i == kMVKShaderStageCompute) { - if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindSamplerState(sb); } - } else { - if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindSamplerState(MVKShaderStage(i), sb); } - } + BIND_GRAPHICS_OR_COMPUTE(cmdEncoder, bindSamplerState, pipelineBindPoint, i, sb); } } break; @@ -410,13 +395,8 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s if (_applyToStage[i]) { tb.index = mtlIdxs.stages[i].textureIndex + rezIdx + planeIndex; sb.index = mtlIdxs.stages[i].samplerIndex + rezIdx; - if (i == kMVKShaderStageCompute) { - if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindTexture(tb); } - if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindSamplerState(sb); } - } else { - if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindTexture(MVKShaderStage(i), tb); } - if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindSamplerState(MVKShaderStage(i), sb); } - } + BIND_GRAPHICS_OR_COMPUTE(cmdEncoder, bindTexture, pipelineBindPoint, i, tb); + BIND_GRAPHICS_OR_COMPUTE(cmdEncoder, bindSamplerState, pipelineBindPoint, i, sb); } } } @@ -547,8 +527,15 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s case kMVKShaderStageTessCtl: case kMVKShaderStageTessEval: mtlStages |= MTLRenderStageVertex; +#if MVK_XCODE_14 + mtlStages |= MTLRenderStageObject; +#endif break; - +#if MVK_XCODE_14 + case kMVKShaderStageGeometry: + mtlStages |= MTLRenderStageMesh; + break; +#endif case kMVKShaderStageFragment: mtlStages |= MTLRenderStageFragment; break; @@ -742,6 +729,7 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s // A null cmdEncoder can be passed to perform a validation pass void MVKBufferDescriptor::bind(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKDescriptorSetLayoutBinding* mvkDSLBind, uint32_t elementIndex, bool stages[], @@ -762,11 +750,7 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageCount; i++) { if (stages[i]) { bb.index = mtlIndexes.stages[i].bufferIndex + elementIndex; - if (i == kMVKShaderStageCompute) { - if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindBuffer(bb); } - } else { - if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindBuffer(MVKShaderStage(i), bb); } - } + BIND_GRAPHICS_OR_COMPUTE(cmdEncoder, bindBuffer, pipelineBindPoint, i, bb); } } } @@ -786,10 +770,8 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s atIndex: argIdx]; } if (encodeUsage) { - rezEncState->encodeArgumentBufferResourceUsage(stage, - _mvkBuffer ? _mvkBuffer->getMTLBuffer() : nil, - getMTLResourceUsage(), - mvkDSLBind->getMTLRenderStages()); + id mtlBuffer = _mvkBuffer ? _mvkBuffer->getMTLBuffer() : nil; + rezEncState->encodeResourceUsage(stage, mtlBuffer, getMTLResourceUsage(), mvkDSLBind->getMTLRenderStages()); } } @@ -836,6 +818,7 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s // A null cmdEncoder can be passed to perform a validation pass void MVKInlineUniformBlockDescriptor::bind(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKDescriptorSetLayoutBinding* mvkDSLBind, uint32_t elementIndex, bool stages[], @@ -852,11 +835,7 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageCount; i++) { if (stages[i]) { bb.index = mtlIndexes.stages[i].bufferIndex; - if (i == kMVKShaderStageCompute) { - if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindBuffer(bb); } - } else { - if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindBuffer(MVKShaderStage(i), bb); } - } + BIND_GRAPHICS_OR_COMPUTE(cmdEncoder, bindBuffer, pipelineBindPoint, i, bb); } } } @@ -876,10 +855,8 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s atIndex: argIdx]; } if (encodeUsage) { - rezEncState->encodeArgumentBufferResourceUsage(stage, - _mvkMTLBufferAllocation ? _mvkMTLBufferAllocation->_mtlBuffer : nil, - getMTLResourceUsage(), - mvkDSLBind->getMTLRenderStages()); + id mtlBuffer = _mvkMTLBufferAllocation ? _mvkMTLBufferAllocation->_mtlBuffer : nil; + rezEncState->encodeResourceUsage(stage, mtlBuffer, getMTLResourceUsage(), mvkDSLBind->getMTLRenderStages()); } } @@ -927,6 +904,7 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s // A null cmdEncoder can be passed to perform a validation pass void MVKImageDescriptor::bind(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKDescriptorSetLayoutBinding* mvkDSLBind, uint32_t elementIndex, bool stages[], @@ -956,18 +934,10 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageCount; i++) { if (stages[i]) { tb.index = mtlIndexes.stages[i].textureIndex + elementIndex + planeIndex; - if (i == kMVKShaderStageCompute) { - if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindTexture(tb); } - } else { - if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindTexture(MVKShaderStage(i), tb); } - } + BIND_GRAPHICS_OR_COMPUTE(cmdEncoder, bindTexture, pipelineBindPoint, i, tb); if (descType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) { bb.index = mtlIndexes.stages[i].bufferIndex + elementIndex + planeIndex; - if (i == kMVKShaderStageCompute) { - if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindBuffer(bb); } - } else { - if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindBuffer(MVKShaderStage(i), bb); } - } + BIND_GRAPHICS_OR_COMPUTE(cmdEncoder, bindBuffer, pipelineBindPoint, i, bb); } } } @@ -994,7 +964,7 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s [mtlArgEncoder setTexture: mtlTexture atIndex: argIdx]; } if (encodeUsage) { - rezEncState->encodeArgumentBufferResourceUsage(stage, mtlTexture, getMTLResourceUsage(), mvkDSLBind->getMTLRenderStages()); + rezEncState->encodeResourceUsage(stage, mtlTexture, getMTLResourceUsage(), mvkDSLBind->getMTLRenderStages()); } if (descType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) { id mtlTex = mtlTexture.parentTexture ? mtlTexture.parentTexture : mtlTexture; @@ -1005,7 +975,7 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s [mtlArgEncoder setBuffer: mtlBuff offset: mtlTex.bufferOffset atIndex: argIdx]; } if (encodeUsage) { - rezEncState->encodeArgumentBufferResourceUsage(stage, mtlBuff, getMTLResourceUsage(), mvkDSLBind->getMTLRenderStages()); + rezEncState->encodeResourceUsage(stage, mtlBuff, getMTLResourceUsage(), mvkDSLBind->getMTLRenderStages()); } } } @@ -1052,6 +1022,7 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s // Metal validation requires each sampler in an array of samplers to be populated, // even if not used, so populate a default if one hasn't been set. void MVKSamplerDescriptorMixin::bind(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKDescriptorSetLayoutBinding* mvkDSLBind, uint32_t elementIndex, bool stages[], @@ -1069,11 +1040,7 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageCount; i++) { if (stages[i]) { sb.index = mtlIndexes.stages[i].samplerIndex + elementIndex; - if (i == kMVKShaderStageCompute) { - if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindSamplerState(sb); } - } else { - if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindSamplerState(MVKShaderStage(i), sb); } - } + BIND_GRAPHICS_OR_COMPUTE(cmdEncoder, bindSamplerState, pipelineBindPoint, i, sb); } } } @@ -1140,13 +1107,14 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s // A null cmdEncoder can be passed to perform a validation pass void MVKSamplerDescriptor::bind(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKDescriptorSetLayoutBinding* mvkDSLBind, uint32_t elementIndex, bool stages[], MVKShaderResourceBinding& mtlIndexes, MVKArrayRef dynamicOffsets, uint32_t& dynamicOffsetIndex) { - MVKSamplerDescriptorMixin::bind(cmdEncoder, mvkDSLBind, elementIndex, stages, mtlIndexes, dynamicOffsets, dynamicOffsetIndex); + MVKSamplerDescriptorMixin::bind(cmdEncoder, pipelineBindPoint, mvkDSLBind, elementIndex, stages, mtlIndexes, dynamicOffsets, dynamicOffsetIndex); } void MVKSamplerDescriptor::encodeToMetalArgumentBuffer(MVKResourcesCommandEncoderState* rezEncState, @@ -1189,14 +1157,15 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s // A null cmdEncoder can be passed to perform a validation pass void MVKCombinedImageSamplerDescriptor::bind(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKDescriptorSetLayoutBinding* mvkDSLBind, uint32_t elementIndex, bool stages[], MVKShaderResourceBinding& mtlIndexes, MVKArrayRef dynamicOffsets, uint32_t& dynamicOffsetIndex) { - MVKImageDescriptor::bind(cmdEncoder, mvkDSLBind, elementIndex, stages, mtlIndexes, dynamicOffsets, dynamicOffsetIndex); - MVKSamplerDescriptorMixin::bind(cmdEncoder, mvkDSLBind, elementIndex, stages, mtlIndexes, dynamicOffsets, dynamicOffsetIndex); + MVKImageDescriptor::bind(cmdEncoder, pipelineBindPoint, mvkDSLBind, elementIndex, stages, mtlIndexes, dynamicOffsets, dynamicOffsetIndex); + MVKSamplerDescriptorMixin::bind(cmdEncoder, pipelineBindPoint, mvkDSLBind, elementIndex, stages, mtlIndexes, dynamicOffsets, dynamicOffsetIndex); } void MVKCombinedImageSamplerDescriptor::encodeToMetalArgumentBuffer(MVKResourcesCommandEncoderState* rezEncState, @@ -1242,6 +1211,7 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s // A null cmdEncoder can be passed to perform a validation pass void MVKTexelBufferDescriptor::bind(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKDescriptorSetLayoutBinding* mvkDSLBind, uint32_t elementIndex, bool stages[], @@ -1263,18 +1233,10 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageCount; i++) { if (stages[i]) { tb.index = mtlIndexes.stages[i].textureIndex + elementIndex; - if (i == kMVKShaderStageCompute) { - if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindTexture(tb); } - } else { - if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindTexture(MVKShaderStage(i), tb); } - } + BIND_GRAPHICS_OR_COMPUTE(cmdEncoder, bindTexture, pipelineBindPoint, i, tb); if (descType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) { bb.index = mtlIndexes.stages[i].bufferIndex + elementIndex; - if (i == kMVKShaderStageCompute) { - if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindBuffer(bb); } - } else { - if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindBuffer(MVKShaderStage(i), bb); } - } + BIND_GRAPHICS_OR_COMPUTE(cmdEncoder, bindBuffer, pipelineBindPoint, i, bb); } } } @@ -1294,7 +1256,7 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s [mtlArgEncoder setTexture: mtlTexture atIndex: argIdx]; } if (encodeUsage) { - rezEncState->encodeArgumentBufferResourceUsage(stage, mtlTexture, getMTLResourceUsage(), mvkDSLBind->getMTLRenderStages()); + rezEncState->encodeResourceUsage(stage, mtlTexture, getMTLResourceUsage(), mvkDSLBind->getMTLRenderStages()); } if (descType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) { @@ -1305,7 +1267,7 @@ void mvkPopulateShaderConversionConfig(mvk::SPIRVToMSLConversionConfiguration& s [mtlArgEncoder setBuffer: mtlBuff offset: mtlTexture.bufferOffset atIndex: argIdx]; } if (encodeUsage) { - rezEncState->encodeArgumentBufferResourceUsage(stage, mtlBuff, getMTLResourceUsage(), mvkDSLBind->getMTLRenderStages()); + rezEncState->encodeResourceUsage(stage, mtlBuff, getMTLResourceUsage(), mvkDSLBind->getMTLRenderStages()); } } } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h index 8964c9019..552ca1728 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h @@ -81,6 +81,7 @@ class MVKDescriptorSetLayout : public MVKVulkanAPIDeviceObject { /** Encodes this descriptor set layout and the specified descriptor updates on the specified command encoder immediately. */ void pushDescriptorSet(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKArrayRef descriptorWrites, MVKShaderResourceBinding& dslMTLRezIdxOffsets); @@ -338,6 +339,9 @@ class MVKDescriptorUpdateTemplate : public MVKVulkanAPIDeviceObject { /** Get the type of this template. */ VkDescriptorUpdateTemplateType getType() const; + /** Get the bind point of this template */ + VkPipelineBindPoint getBindPoint() const { return _pipelineBindPoint; } + /** Constructs an instance for the specified device. */ MVKDescriptorUpdateTemplate(MVKDevice* device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo); @@ -347,6 +351,7 @@ class MVKDescriptorUpdateTemplate : public MVKVulkanAPIDeviceObject { protected: void propagateDebugName() override {} + VkPipelineBindPoint _pipelineBindPoint; VkDescriptorUpdateTemplateType _type; MVKSmallVector _entries; }; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm index 5ebeed4b9..ff5f0a4f4 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm @@ -43,7 +43,7 @@ dynamicOffsets, dynamicOffsetIndex); } if ( !isUsingMetalArgumentBuffers() ) { for (auto& dslBind : _bindings) { - dslBind.bind(cmdEncoder, descSet, dslMTLRezIdxOffsets, dynamicOffsets, dynamicOffsetIndex); + dslBind.bind(cmdEncoder, pipelineBindPoint, descSet, dslMTLRezIdxOffsets, dynamicOffsets, dynamicOffsetIndex); } } } @@ -91,6 +91,7 @@ // A null cmdEncoder can be passed to perform a validation pass void MVKDescriptorSetLayout::pushDescriptorSet(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKArrayRef descriptorWrites, MVKShaderResourceBinding& dslMTLRezIdxOffsets) { @@ -127,7 +128,7 @@ pBufferInfo, pTexelBufferView, pInlineUniformBlock, stride); uint32_t descriptorsPushed = 0; uint32_t bindIdx = _bindingToIndex[dstBinding]; - _bindings[bindIdx].push(cmdEncoder, dstArrayElement, descriptorCount, + _bindings[bindIdx].push(cmdEncoder, pipelineBindPoint, dstArrayElement, descriptorCount, descriptorsPushed, descWrite.descriptorType, stride, pData, dslMTLRezIdxOffsets); pBufferInfo += descriptorsPushed; @@ -148,6 +149,7 @@ return; if (!cmdEncoder) { clearConfigurationResult(); } + VkPipelineBindPoint bindPoint = descUpdateTemplate->getBindPoint(); for (uint32_t i = 0; i < descUpdateTemplate->getNumberOfEntries(); i++) { const VkDescriptorUpdateTemplateEntry* pEntry = descUpdateTemplate->getEntry(i); uint32_t dstBinding = pEntry->dstBinding; @@ -161,7 +163,7 @@ if (!_bindingToIndex.count(dstBinding)) continue; uint32_t descriptorsPushed = 0; uint32_t bindIdx = _bindingToIndex[dstBinding]; - _bindings[bindIdx].push(cmdEncoder, dstArrayElement, descriptorCount, + _bindings[bindIdx].push(cmdEncoder, bindPoint, dstArrayElement, descriptorCount, descriptorsPushed, pEntry->descriptorType, pEntry->stride, pCurData, dslMTLRezIdxOffsets); pCurData = (const char*)pCurData + pEntry->stride * descriptorsPushed; @@ -183,24 +185,29 @@ } } +static const spv::ExecutionModel getExecModel(MVKShaderStage stage) { + switch (stage) { + case kMVKShaderStageVertex: return spv::ExecutionModelVertex; + case kMVKShaderStageTessCtl: return spv::ExecutionModelTessellationControl; + case kMVKShaderStageTessEval: return spv::ExecutionModelTessellationEvaluation; + case kMVKShaderStageGeometry: return spv::ExecutionModelGeometry; + case kMVKShaderStageFragment: return spv::ExecutionModelFragment; + case kMVKShaderStageCompute: return spv::ExecutionModelGLCompute; + case kMVKShaderStageCount: assert(0); __builtin_unreachable(); + } +} + bool MVKDescriptorSetLayout::populateBindingUse(MVKBitArray& bindingUse, SPIRVToMSLConversionConfiguration& context, MVKShaderStage stage, uint32_t descSetIndex) { - static const spv::ExecutionModel spvExecModels[] = { - spv::ExecutionModelVertex, - spv::ExecutionModelTessellationControl, - spv::ExecutionModelTessellationEvaluation, - spv::ExecutionModelFragment, - spv::ExecutionModelGLCompute - }; bool descSetIsUsed = false; uint32_t bindCnt = (uint32_t)_bindings.size(); bindingUse.resize(bindCnt); for (uint32_t bindIdx = 0; bindIdx < bindCnt; bindIdx++) { auto& dslBind = _bindings[bindIdx]; - if (context.isResourceUsed(spvExecModels[stage], descSetIndex, dslBind.getBinding())) { + if (context.isResourceUsed(getExecModel(stage), descSetIndex, dslBind.getBinding())) { bindingUse.setBit(bindIdx); descSetIsUsed = true; } @@ -876,7 +883,7 @@ MVKDescriptorUpdateTemplate::MVKDescriptorUpdateTemplate(MVKDevice* device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo) : - MVKVulkanAPIDeviceObject(device), _type(pCreateInfo->templateType) { + MVKVulkanAPIDeviceObject(device), _pipelineBindPoint(pCreateInfo->pipelineBindPoint), _type(pCreateInfo->templateType) { for (uint32_t i = 0; i < pCreateInfo->descriptorUpdateEntryCount; i++) _entries.push_back(pCreateInfo->pDescriptorUpdateEntries[i]); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h index 22f8649eb..450fad661 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h @@ -18,7 +18,6 @@ #pragma once -#include "MVKEnvironment.h" #include "MVKFoundation.h" #include "MVKVulkanAPIObject.h" #include "MVKMTLResourceBindings.h" @@ -27,6 +26,7 @@ #include "MVKSmallVector.h" #include "MVKPixelFormats.h" #include "MVKOSExtensions.h" +#include "mvk_private_api.h" #include "mvk_datatypes.hpp" #include #include @@ -51,6 +51,7 @@ class MVKDeviceMemory; class MVKFence; class MVKSemaphore; class MVKTimelineSemaphore; +class MVKDeferredOperation; class MVKEvent; class MVKSemaphoreImpl; class MVKQueryPool; @@ -63,6 +64,7 @@ class MVKSamplerYcbcrConversion; class MVKDescriptorSetLayout; class MVKDescriptorPool; class MVKDescriptorUpdateTemplate; +class MVKResourcesCommandEncoderState; class MVKFramebuffer; class MVKRenderPass; class MVKCommandPool; @@ -79,8 +81,8 @@ const static uint32_t kMVKQueueFamilyCount = 4; const static uint32_t kMVKQueueCountPerQueueFamily = 1; // Must be 1. See comments in MVKPhysicalDevice::getQueueFamilies() const static uint32_t kMVKMinSwapchainImageCount = 2; const static uint32_t kMVKMaxSwapchainImageCount = 3; -const static uint32_t kMVKCachedViewportScissorCount = 16; -const static uint32_t kMVKCachedColorAttachmentCount = 8; +const static uint32_t kMVKMaxColorAttachmentCount = 8; +const static uint32_t kMVKMaxViewportScissorCount = 16; const static uint32_t kMVKMaxDescriptorSetCount = SPIRV_CROSS_NAMESPACE::kMaxArgumentBuffers; #if !MVK_XCODE_12 @@ -137,7 +139,7 @@ class MVKPhysicalDevice : public MVKDispatchableVulkanAPIObject { void getProperties(VkPhysicalDeviceProperties2* properties); /** Returns the name of this device. */ - inline const char* getName() { return _properties.deviceName; } + const char* getName() { return _properties.deviceName; } /** Populates the specified structure with the format properties of this device. */ void getFormatProperties(VkFormat format, VkFormatProperties* pFormatProperties); @@ -173,6 +175,9 @@ class MVKPhysicalDevice : public MVKDispatchableVulkanAPIObject { void getExternalSemaphoreProperties(const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties); + /** Returns the supported time domains for calibration on this device. */ + VkResult getCalibrateableTimeDomains(uint32_t* pTimeDomainCount, VkTimeDomainEXT* pTimeDomains); + #pragma mark Surfaces /** @@ -284,7 +289,7 @@ class MVKPhysicalDevice : public MVKDispatchableVulkanAPIObject { #pragma mark Memory models /** Returns a pointer to the memory characteristics of this device. */ - inline const VkPhysicalDeviceMemoryProperties* getMemoryProperties() { return &_memoryProperties; } + const VkPhysicalDeviceMemoryProperties* getMemoryProperties() { return &_memoryProperties; } /** Populates the specified memory properties with the memory characteristics of this device. */ VkResult getMemoryProperties(VkPhysicalDeviceMemoryProperties* pMemoryProperties); @@ -296,31 +301,31 @@ class MVKPhysicalDevice : public MVKDispatchableVulkanAPIObject { * Returns a bit mask of all memory type indices. * Each bit [0..31] in the returned bit mask indicates a distinct memory type. */ - inline uint32_t getAllMemoryTypes() { return _allMemoryTypes; } + uint32_t getAllMemoryTypes() { return _allMemoryTypes; } /** * Returns a bit mask of all memory type indices that allow host visibility to the memory. * Each bit [0..31] in the returned bit mask indicates a distinct memory type. */ - inline uint32_t getHostVisibleMemoryTypes() { return _hostVisibleMemoryTypes; } + uint32_t getHostVisibleMemoryTypes() { return _hostVisibleMemoryTypes; } /** * Returns a bit mask of all memory type indices that are coherent between host and device. * Each bit [0..31] in the returned bit mask indicates a distinct memory type. */ - inline uint32_t getHostCoherentMemoryTypes() { return _hostCoherentMemoryTypes; } + uint32_t getHostCoherentMemoryTypes() { return _hostCoherentMemoryTypes; } /** * Returns a bit mask of all memory type indices that do NOT allow host visibility to the memory. * Each bit [0..31] in the returned bit mask indicates a distinct memory type. */ - inline uint32_t getPrivateMemoryTypes() { return _privateMemoryTypes; } + uint32_t getPrivateMemoryTypes() { return _privateMemoryTypes; } /** * Returns a bit mask of all memory type indices that are lazily allocated. * Each bit [0..31] in the returned bit mask indicates a distinct memory type. */ - inline uint32_t getLazilyAllocatedMemoryTypes() { return _lazilyAllocatedMemoryTypes; } + uint32_t getLazilyAllocatedMemoryTypes() { return _lazilyAllocatedMemoryTypes; } /** Returns whether this is a unified memory device. */ bool getHasUnifiedMemory(); @@ -335,21 +340,13 @@ class MVKPhysicalDevice : public MVKDispatchableVulkanAPIObject { #pragma mark Metal /** Populates the specified structure with the Metal-specific features of this device. */ - inline const MVKPhysicalDeviceMetalFeatures* getMetalFeatures() { return &_metalFeatures; } + const MVKPhysicalDeviceMetalFeatures* getMetalFeatures() { return &_metalFeatures; } /** Returns whether or not vertex instancing can be used to implement multiview. */ - inline bool canUseInstancingForMultiview() { return _metalFeatures.layeredRendering && _metalFeatures.deferredStoreActions; } + bool canUseInstancingForMultiview() { return _metalFeatures.layeredRendering && _metalFeatures.deferredStoreActions; } /** Returns the underlying Metal device. */ - inline id getMTLDevice() { return _mtlDevice; } - - /*** Replaces the underlying Metal device .*/ - inline void replaceMTLDevice(id mtlDevice) { - if (mtlDevice != _mtlDevice) { - [_mtlDevice release]; - _mtlDevice = [mtlDevice retain]; - } - } + id getMTLDevice() { return _mtlDevice; } /** Returns whether the MSL version is supported on this device. */ bool mslVersionIsAtLeast(MTLLanguageVersion minVer) { return _metalFeatures.mslVersionEnum >= minVer; } @@ -359,20 +356,6 @@ class MVKPhysicalDevice : public MVKDispatchableVulkanAPIObject { return _metalFeatures.argumentBuffers && mvkConfig().useMetalArgumentBuffers != MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS_NEVER; }; - /** - * Returns the start timestamps of a timestamp correlation. - * The returned values should be later passed back to updateTimestampPeriod(). - */ - void startTimestampCorrelation(MTLTimestamp& cpuStart, MTLTimestamp& gpuStart); - - /** - * Updates the current value of VkPhysicalDeviceLimits::timestampPeriod, based on the - * correlation between the CPU time tickes and GPU time ticks, from the specified start - * values, to the current values. The cpuStart and gpuStart values should have been - * retrieved from a prior call to startTimestampCorrelation(). - */ - void updateTimestampPeriod(MTLTimestamp cpuStart, MTLTimestamp gpuStart); - #pragma mark Construction @@ -386,7 +369,7 @@ class MVKPhysicalDevice : public MVKDispatchableVulkanAPIObject { * Returns a reference to this object suitable for use as a Vulkan API handle. * This is the compliment of the getMVKPhysicalDevice() method. */ - inline VkPhysicalDevice getVkPhysicalDevice() { return (VkPhysicalDevice)getVkHandle(); } + VkPhysicalDevice getVkPhysicalDevice() { return (VkPhysicalDevice)getVkHandle(); } /** * Retrieves the MVKPhysicalDevice instance referenced by the VkPhysicalDevice handle. @@ -403,6 +386,7 @@ class MVKPhysicalDevice : public MVKDispatchableVulkanAPIObject { MTLFeatureSet getMaximalMTLFeatureSet(); void initMetalFeatures(); void initFeatures(); + void initMTLDevice(); void initProperties(); void initLimits(); void initGPUInfoProperties(); @@ -418,6 +402,7 @@ class MVKPhysicalDevice : public MVKDispatchableVulkanAPIObject { void initExtensions(); void initCounterSets(); bool needsCounterSetRetained(); + void updateTimestampsAndPeriod(); MVKArrayRef getQueueFamilies(); void initPipelineCacheUUID(); uint32_t getHighestGPUCapability(); @@ -437,16 +422,18 @@ class MVKPhysicalDevice : public MVKDispatchableVulkanAPIObject { VkPhysicalDeviceMemoryProperties _memoryProperties; MVKSmallVector _queueFamilies; MVKPixelFormats _pixelFormats; + VkExternalMemoryProperties _hostPointerExternalMemoryProperties; + VkExternalMemoryProperties _mtlBufferExternalMemoryProperties; + VkExternalMemoryProperties _mtlTextureExternalMemoryProperties; id _timestampMTLCounterSet; MVKSemaphoreStyle _vkSemaphoreStyle; + MTLTimestamp _prevCPUTimestamp = 0; + MTLTimestamp _prevGPUTimestamp = 0; uint32_t _allMemoryTypes; uint32_t _hostVisibleMemoryTypes; uint32_t _hostCoherentMemoryTypes; uint32_t _privateMemoryTypes; uint32_t _lazilyAllocatedMemoryTypes; - VkExternalMemoryProperties _hostPointerExternalMemoryProperties; - VkExternalMemoryProperties _mtlBufferExternalMemoryProperties; - VkExternalMemoryProperties _mtlTextureExternalMemoryProperties; }; @@ -473,16 +460,16 @@ class MVKDevice : public MVKDispatchableVulkanAPIObject { MVKInstance* getInstance() override { return _physicalDevice->getInstance(); } /** Returns the physical device underlying this logical device. */ - inline MVKPhysicalDevice* getPhysicalDevice() { return _physicalDevice; } + MVKPhysicalDevice* getPhysicalDevice() { return _physicalDevice; } /** Returns info about the pixel format supported by the physical device. */ - inline MVKPixelFormats* getPixelFormats() { return &_physicalDevice->_pixelFormats; } + MVKPixelFormats* getPixelFormats() { return &_physicalDevice->_pixelFormats; } /** Returns the name of this device. */ - inline const char* getName() { return _pProperties->deviceName; } + const char* getName() { return _pProperties->deviceName; } /** Returns the common resource factory for creating command resources. */ - inline MVKCommandResourceFactory* getCommandResourceFactory() { return _commandResourceFactory; } + MVKCommandResourceFactory* getCommandResourceFactory() { return _commandResourceFactory; } /** Returns the function pointer corresponding to the specified named entry point. */ PFN_vkVoidFunction getProcAddr(const char* pName); @@ -520,6 +507,11 @@ class MVKDevice : public MVKDispatchableVulkanAPIObject { const void* pHostPointer, VkMemoryHostPointerPropertiesEXT* pMemHostPtrProps); + /** Samples timestamps from the specified domains and returns the sampled values. */ + void getCalibratedTimestamps(uint32_t timestampCount, + const VkCalibratedTimestampInfoEXT* pTimestampInfos, + uint64_t* pTimestamps, + uint64_t* pMaxDeviation); #pragma mark Object lifecycle @@ -563,6 +555,10 @@ class MVKDevice : public MVKDispatchableVulkanAPIObject { const VkAllocationCallbacks* pAllocator); void destroySemaphore(MVKSemaphore* mvkSem4, const VkAllocationCallbacks* pAllocator); + + MVKDeferredOperation* createDeferredOperation(const VkAllocationCallbacks* pAllocator); + void destroyDeferredOperation(MVKDeferredOperation* mvkDeferredOperation, + const VkAllocationCallbacks* pAllocator); MVKEvent* createEvent(const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator); @@ -630,6 +626,8 @@ class MVKDevice : public MVKDispatchableVulkanAPIObject { MVKFramebuffer* createFramebuffer(const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator); + MVKFramebuffer* createFramebuffer(const VkRenderingInfo* pRenderingInfo, + const VkAllocationCallbacks* pAllocator); void destroyFramebuffer(MVKFramebuffer* mvkFB, const VkAllocationCallbacks* pAllocator); @@ -637,6 +635,8 @@ class MVKDevice : public MVKDispatchableVulkanAPIObject { const VkAllocationCallbacks* pAllocator); MVKRenderPass* createRenderPass(const VkRenderPassCreateInfo2* pCreateInfo, const VkAllocationCallbacks* pAllocator); + MVKRenderPass* createRenderPass(const VkRenderingInfo* pRenderingInfo, + const VkAllocationCallbacks* pAllocator); void destroyRenderPass(MVKRenderPass* mvkRP, const VkAllocationCallbacks* pAllocator); @@ -660,6 +660,22 @@ class MVKDevice : public MVKDispatchableVulkanAPIObject { #pragma mark Operations + /** Tell the GPU to be ready to use any of the GPU-addressable buffers. */ + void encodeGPUAddressableBuffers(MVKResourcesCommandEncoderState* rezEncState, + MVKShaderStage stage); + + /** Adds the specified host semaphore to be woken upon device loss. */ + void addSemaphore(MVKSemaphoreImpl* sem4); + + /** Removes the specified host semaphore. */ + void removeSemaphore(MVKSemaphoreImpl* sem4); + + /** Adds the specified timeline semaphore to be woken at the specified value upon device loss. */ + void addTimelineSemaphore(MVKTimelineSemaphore* sem4, uint64_t value); + + /** Removes the specified timeline semaphore. */ + void removeTimelineSemaphore(MVKTimelineSemaphore* sem4, uint64_t value); + /** Applies the specified global memory barrier to all resource issued by this device. */ void applyMemoryBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, @@ -677,7 +693,7 @@ class MVKDevice : public MVKDispatchableVulkanAPIObject { * number of nanoseconds between the two calls. The convenience function mvkGetElapsedMilliseconds() * can be used to perform this calculation. */ - inline uint64_t getPerformanceTimestamp() { return _isPerformanceTracking ? mvkGetTimestamp() : 0; } + uint64_t getPerformanceTimestamp() { return _isPerformanceTracking ? mvkGetTimestamp() : 0; } /** * If performance is being tracked, adds the performance for an activity with a duration @@ -685,8 +701,8 @@ class MVKDevice : public MVKDispatchableVulkanAPIObject { * * If endTime is zero or not supplied, the current time is used. */ - inline void addActivityPerformance(MVKPerformanceTracker& activityTracker, - uint64_t startTime, uint64_t endTime = 0) { + void addActivityPerformance(MVKPerformanceTracker& activityTracker, + uint64_t startTime, uint64_t endTime = 0) { if (_isPerformanceTracking) { updateActivityPerformance(activityTracker, startTime, endTime); @@ -720,7 +736,7 @@ class MVKDevice : public MVKDispatchableVulkanAPIObject { #pragma mark Metal /** Returns the underlying Metal device. */ - inline id getMTLDevice() { return _physicalDevice->getMTLDevice(); } + id getMTLDevice() { return _physicalDevice->getMTLDevice(); } /** Returns whether this device is using Metal argument buffers. */ bool isUsingMetalArgumentBuffers() { return _isUsingMetalArgumentBuffers; }; @@ -796,7 +812,7 @@ class MVKDevice : public MVKDispatchableVulkanAPIObject { void stopAutoGPUCapture(MVKConfigAutoGPUCaptureScope autoGPUCaptureScope); /** Returns whether this instance is currently automatically capturing a GPU trace. */ - inline bool isCurrentlyAutoGPUCapturing() { return _isCurrentlyAutoGPUCapturing; } + bool isCurrentlyAutoGPUCapturing() { return _isCurrentlyAutoGPUCapturing; } /** Returns the Metal objects underpinning the Vulkan objects indicated in the pNext chain of pMetalObjectsInfo. */ void getMetalObjects(VkExportMetalObjectsInfoEXT* pMetalObjectsInfo); @@ -844,7 +860,7 @@ class MVKDevice : public MVKDispatchableVulkanAPIObject { * Returns a reference to this object suitable for use as a Vulkan API handle. * This is the compliment of the getMVKDevice() method. */ - inline VkDevice getVkDevice() { return (VkDevice)getVkHandle(); } + VkDevice getVkDevice() { return (VkDevice)getVkHandle(); } /** * Retrieves the MVKDevice instance referenced by the VkDevice handle. @@ -855,26 +871,18 @@ class MVKDevice : public MVKDispatchableVulkanAPIObject { } protected: - friend class MVKSemaphoreEmulated; - friend class MVKTimelineSemaphoreMTLEvent; - friend class MVKTimelineSemaphoreEmulated; - friend class MVKFence; - friend class MVKEventEmulated; - void propagateDebugName() override {} - MVKResource* addResource(MVKResource* rez); - MVKResource* removeResource(MVKResource* rez); - void addSemaphore(MVKSemaphoreImpl* sem4); - void removeSemaphore(MVKSemaphoreImpl* sem4); - void addTimelineSemaphore(MVKTimelineSemaphore* sem4, uint64_t value); - void removeTimelineSemaphore(MVKTimelineSemaphore* sem4, uint64_t value); + MVKBuffer* addBuffer(MVKBuffer* mvkBuff); + MVKBuffer* removeBuffer(MVKBuffer* mvkBuff); + MVKImage* addImage(MVKImage* mvkImg); + MVKImage* removeImage(MVKImage* mvkImg); void initPerformanceTracking(); void initPhysicalDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo* pCreateInfo); void initQueues(const VkDeviceCreateInfo* pCreateInfo); void reservePrivateData(const VkDeviceCreateInfo* pCreateInfo); void enableFeatures(const VkDeviceCreateInfo* pCreateInfo); - void enableFeatures(VkBaseInStructure* pEnabled, const VkBaseInStructure* pRequested, const VkBaseInStructure* pAvailable, uint32_t count); - void enableFeatures(VkBool32* pEnabledBools, const VkBool32* pRequestedBools, const VkBool32* pAvailableBools, uint32_t count); + template void enableFeatures(S* pEnabled, const S* pRequested, const S* pAvailable, uint32_t count); + template void enableFeatures(S* pRequested, VkBool32* pEnabledBools, const VkBool32* pRequestedBools, const VkBool32* pAvailableBools, uint32_t count); void enableExtensions(const VkDeviceCreateInfo* pCreateInfo); const char* getActivityPerformanceDescription(MVKPerformanceTracker& activity, MVKPerformanceStatistics& perfStats); void logActivityPerformance(MVKPerformanceTracker& activity, MVKPerformanceStatistics& perfStats, bool isInline = false); @@ -887,6 +895,7 @@ class MVKDevice : public MVKDispatchableVulkanAPIObject { MVKCommandResourceFactory* _commandResourceFactory = nullptr; MVKSmallVector, kMVKQueueFamilyCount> _queuesByQueueFamilyIndex; MVKSmallVector _resources; + MVKSmallVector _gpuAddressableBuffers; MVKSmallVector _privateDataSlots; MVKSmallVector _privateDataSlotsAvailability; MVKSmallVector _awaitingSemaphores; @@ -1050,6 +1059,14 @@ class MVKDeviceObjectPool : public MVKObjectPool, public MVKDeviceTrackingMix /** Returns the registry ID of the specified device, or zero if the device does not have a registry ID. */ uint64_t mvkGetRegistryID(id mtlDevice); +/** + * Returns a value identifying the physical location of the specified device. + * The returned value is a hash of the location, locationNumber, peerGroupID, + * and peerIndex properties of the device. On devices with only one built-in GPU, + * the returned value will be zero. + */ +uint64_t mvkGetLocationID(id mtlDevice); + /** Returns whether the MTLDevice supports BC texture compression. */ bool mvkSupportsBCTextureCompression(id mtlDevice); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index 3494740e7..769a1d79d 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -32,7 +32,7 @@ #include "MVKCommandPool.h" #include "MVKFoundation.h" #include "MVKCodec.h" -#include "MVKEnvironment.h" +#include "MVKStrings.h" #include #import "CAMetalLayer+MoltenVK.h" @@ -78,6 +78,8 @@ static const VkExtent2D kMetalSamplePositionGridSize = { 1, 1 }; static const VkExtent2D kMetalSamplePositionGridSizeNotSupported = { 0, 0 }; +static const uint32_t kMaxTimeDomains = 2; + #pragma clang diagnostic pop @@ -154,7 +156,7 @@ .separateDepthStencilLayouts = true, .hostQueryReset = true, .timelineSemaphore = true, - .bufferDeviceAddress = mvkOSVersionIsAtLeast(12.05, 16.0), + .bufferDeviceAddress = mvkOSVersionIsAtLeast(12.05, 16.0, 1.0), .bufferDeviceAddressCaptureReplay = false, .bufferDeviceAddressMultiDevice = false, .vulkanMemoryModel = false, @@ -367,10 +369,19 @@ portabilityFeatures->shaderSampleRateInterpolationFunctions = _metalFeatures.pullModelInterpolation; portabilityFeatures->tessellationIsolines = false; portabilityFeatures->tessellationPointMode = false; - portabilityFeatures->triangleFans = false; + portabilityFeatures->triangleFans = true; portabilityFeatures->vertexAttributeAccessBeyondStride = true; // Costs additional buffers. Should make configuration switch. break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: { + auto* formatFeatures = (VkPhysicalDevice4444FormatsFeaturesEXT*)next; + bool canSupport4444 = _metalFeatures.tileBasedDeferredRendering && + (_metalFeatures.nativeTextureSwizzle || + mvkConfig().fullImageViewSwizzle); + formatFeatures->formatA4R4G4B4 = canSupport4444; + formatFeatures->formatA4B4G4R4 = canSupport4444; + break; + } case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT: { auto* interlockFeatures = (VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT*)next; interlockFeatures->fragmentShaderSampleInterlock = _metalFeatures.rasterOrderGroups; @@ -407,6 +418,11 @@ atomicFloatFeatures->sparseImageFloat32AtomicAdd = false; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT: { + auto* demoteFeatures = (VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT*)next; + demoteFeatures->shaderDemoteToHelperInvocation = mvkOSVersionIsAtLeast(11.0, 14.0, 1.0); + break; + } case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT: { auto* swapchainMaintenance1Features = (VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT*)next; swapchainMaintenance1Features->swapchainMaintenance1 = true; @@ -435,10 +451,17 @@ } void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties* properties) { + updateTimestampsAndPeriod(); *properties = _properties; } void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties2* properties) { + + properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + getProperties(&properties->properties); + + if ( !properties->pNext ) { return; } + uint32_t uintMax = std::numeric_limits::max(); uint32_t maxSamplerCnt = getMaxSamplerCount(); bool isTier2 = supportsMetalArgumentBuffers() && (_metalFeatures.argumentBuffersTier >= MTLArgumentBuffersTier2); @@ -520,8 +543,6 @@ supportedProps12.maxTimelineSemaphoreValueDifference = std::numeric_limits::max(); supportedProps12.framebufferIntegerColorSampleCounts = _metalFeatures.supportedSampleCounts; - properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; - properties->properties = _properties; for (auto* next = (VkBaseOutStructure*)properties->pNext; next; next = next->pNext) { switch ((uint32_t)next->sType) { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES: { @@ -727,15 +748,21 @@ } } +// Since these are uint8_t arrays, use Big-Endian byte ordering, +// so a hex dump of the array is human readable in its parts. void MVKPhysicalDevice::populateDeviceIDProperties(VkPhysicalDeviceVulkan11Properties* pVk11Props) { uint8_t* uuid; size_t uuidComponentOffset; - // ---- Device ID ---------------------------------------------- + // ---- Device UUID ---------------------------------------------- uuid = pVk11Props->deviceUUID; uuidComponentOffset = 0; mvkClear(uuid, VK_UUID_SIZE); + // From Vulkan spec: deviceUUID must be universally unique for the device, + // AND must be immutable for a given device across instances, processes, + // driver APIs, driver versions, and system reboots. + // First 4 bytes contains GPU vendor ID uint32_t vendorID = _properties.vendorID; *(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(vendorID); @@ -746,10 +773,10 @@ *(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(deviceID); uuidComponentOffset += sizeof(deviceID); - // Last 8 bytes contain the GPU registry ID - uint64_t regID = mvkGetRegistryID(_mtlDevice); - *(uint64_t*)&uuid[uuidComponentOffset] = NSSwapHostLongLongToBig(regID); - uuidComponentOffset += sizeof(regID); + // Last 8 bytes contain the GPU location identifier + uint64_t locID = mvkGetLocationID(_mtlDevice); + *(uint64_t*)&uuid[uuidComponentOffset] = NSSwapHostLongLongToBig(locID); + uuidComponentOffset += sizeof(locID); // ---- Driver ID ---------------------------------------------- uuid = pVk11Props->driverUUID; @@ -772,10 +799,10 @@ *(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(gpuCap); uuidComponentOffset += sizeof(gpuCap); - // ---- LUID ignored for Metal devices ------------------------ - mvkClear(pVk11Props->deviceLUID, VK_LUID_SIZE); - pVk11Props->deviceNodeMask = 0; - pVk11Props->deviceLUIDValid = VK_FALSE; + // ---- Device LUID ------------------------ + *(uint64_t*)pVk11Props->deviceLUID = NSSwapHostLongLongToBig(mvkGetRegistryID(_mtlDevice)); + pVk11Props->deviceNodeMask = 1; // Per Vulkan spec + pVk11Props->deviceLUIDValid = VK_TRUE; } void MVKPhysicalDevice::populateSubgroupProperties(VkPhysicalDeviceVulkan11Properties* pVk11Props) { @@ -784,7 +811,7 @@ if (_features.tessellationShader) { pVk11Props->subgroupSupportedStages |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; } - if (mvkOSVersionIsAtLeast(10.15, 13.0)) { + if (mvkOSVersionIsAtLeast(10.15, 13.0, 1.0)) { pVk11Props->subgroupSupportedStages |= VK_SHADER_STAGE_FRAGMENT_BIT; } pVk11Props->subgroupSupportedOperations = VK_SUBGROUP_FEATURE_BASIC_BIT; @@ -1100,6 +1127,22 @@ pExternalSemaphoreProperties->pNext = next; } +VkResult MVKPhysicalDevice::getCalibrateableTimeDomains(uint32_t* pTimeDomainCount, VkTimeDomainEXT* pTimeDomains) { + if (!pTimeDomains) { + *pTimeDomainCount = kMaxTimeDomains; + return VK_SUCCESS; + } + // XXX CLOCK_MONOTONIC_RAW is mach_continuous_time(), but + // -[MTLDevice sampleTimestamps:gpuTimestamp:] returns the CPU + // timestamp in the mach_absolute_time() domain, which is CLOCK_UPTIME_RAW + // (cf. Libc/gen/clock_gettime.c). + static const VkTimeDomainEXT domains[] = { VK_TIME_DOMAIN_DEVICE_EXT, VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT }; + std::copy_n(domains, min(*pTimeDomainCount, kMaxTimeDomains), pTimeDomains); + if (*pTimeDomainCount < kMaxTimeDomains) { return VK_INCOMPLETE; } + *pTimeDomainCount = kMaxTimeDomains; + return VK_SUCCESS; +} + #pragma mark Surfaces @@ -1524,23 +1567,25 @@ return rslt; } -// Don't need to do this for Apple GPUs, where the GPU and CPU timestamps -// are the same, or if we're not using GPU timestamp counters. -void MVKPhysicalDevice::startTimestampCorrelation(MTLTimestamp& cpuStart, MTLTimestamp& gpuStart) { - if (_properties.vendorID == kAppleVendorId || !_timestampMTLCounterSet) { return; } - [_mtlDevice sampleTimestamps: &cpuStart gpuTimestamp: &gpuStart]; -} +// If needed, update the timestamp period for this device, using a crude lowpass filter to level out +// wild temporary changes, particularly during initial queries before much GPU activity has occurred. +// On Apple GPUs, CPU & GPU timestamps are the same, and timestamp period never changes. +void MVKPhysicalDevice::updateTimestampsAndPeriod() { + if (_properties.vendorID == kAppleVendorId) { return; } -// Don't need to do this for Apple GPUs, where the GPU and CPU timestamps -// are the same, or if we're not using GPU timestamp counters. -void MVKPhysicalDevice::updateTimestampPeriod(MTLTimestamp cpuStart, MTLTimestamp gpuStart) { - if (_properties.vendorID == kAppleVendorId || !_timestampMTLCounterSet) { return; } + MTLTimestamp earlierCPUTs = _prevCPUTimestamp; + MTLTimestamp earlierGPUTs = _prevGPUTimestamp; + [_mtlDevice sampleTimestamps: &_prevCPUTimestamp gpuTimestamp: &_prevGPUTimestamp]; + double elapsedCPUNanos = _prevCPUTimestamp - earlierCPUTs; + double elapsedGPUTicks = _prevGPUTimestamp - earlierGPUTs; + if (elapsedCPUNanos && elapsedGPUTicks) { // Ensure not zero + float tsPeriod = elapsedCPUNanos / elapsedGPUTicks; - MTLTimestamp cpuEnd; - MTLTimestamp gpuEnd; - [_mtlDevice sampleTimestamps: &cpuEnd gpuTimestamp: &gpuEnd]; - - _properties.limits.timestampPeriod = (double)(cpuEnd - cpuStart) / (double)(gpuEnd - gpuStart); + // Basic lowpass filter Y = (1 - a)Y + a*X. + // The lower a is, the slower Y will change over time. + static const float a = 0.05; + _properties.limits.timestampPeriod = ((1.0 - a) * _properties.limits.timestampPeriod) + (a * tsPeriod); + } } @@ -1585,6 +1630,7 @@ _supportedExtensions(this, true), _pixelFormats(this) { // Set after _mtlDevice + initMTLDevice(); initProperties(); // Call first. initMetalFeatures(); // Call second. initFeatures(); // Call third. @@ -1597,6 +1643,15 @@ logGPUInfo(); } +void MVKPhysicalDevice::initMTLDevice() { +#if MVK_XCODE_14_3 && MVK_MACOS && !MVK_MACCAT + if ([_mtlDevice respondsToSelector: @selector(setShouldMaximizeConcurrentCompilation:)]) { + [_mtlDevice setShouldMaximizeConcurrentCompilation: mvkConfig().shouldMaximizeConcurrentCompilation]; + MVKLogInfoIf(mvkConfig().debugMode, "maximumConcurrentCompilationTaskCount %lu", _mtlDevice.maximumConcurrentCompilationTaskCount); + } +#endif +} + // Initializes the physical device properties (except limits). void MVKPhysicalDevice::initProperties() { mvkClear(&_properties); // Start with everything cleared @@ -1645,7 +1700,9 @@ break; case kAppleVendorId: // TODO: Other GPUs? - _metalFeatures.needsSampleDrefLodArrayWorkaround = true; + if (!mvkOSVersionIsAtLeast(14.0, 17.0, 1.0)) { + _metalFeatures.needsSampleDrefLodArrayWorkaround = true; + } // fallthrough case kIntelVendorId: case kNVVendorId: @@ -1732,6 +1789,12 @@ } #endif +#if MVK_XCODE_15 + if ( mvkOSVersionIsAtLeast(17.0) ) { + _metalFeatures.mslVersionEnum = MTLLanguageVersion3_1; + } +#endif + #endif #if MVK_IOS @@ -1803,7 +1866,11 @@ if ( mvkOSVersionIsAtLeast(13.0) ) { _metalFeatures.mslVersionEnum = MTLLanguageVersion2_2; _metalFeatures.placementHeaps = mvkConfig().useMTLHeap; +#if MVK_OS_SIMULATOR + _metalFeatures.nativeTextureSwizzle = false; +#else _metalFeatures.nativeTextureSwizzle = true; +#endif if (supportsMTLGPUFamily(Apple3)) { _metalFeatures.native3DCompressedTextures = true; } @@ -1845,6 +1912,11 @@ _metalFeatures.mslVersionEnum = MTLLanguageVersion3_0; } #endif +#if MVK_XCODE_15 + if ( mvkOSVersionIsAtLeast(17.0) ) { + _metalFeatures.mslVersionEnum = MTLLanguageVersion3_1; + } +#endif #endif @@ -1930,6 +2002,11 @@ _metalFeatures.mslVersionEnum = MTLLanguageVersion3_0; } #endif +#if MVK_XCODE_15 + if ( mvkOSVersionIsAtLeast(14.0) ) { + _metalFeatures.mslVersionEnum = MTLLanguageVersion3_1; + } +#endif // This is an Apple GPU--treat it accordingly. if (supportsMTLGPUFamily(Apple1)) { @@ -2045,6 +2122,11 @@ _metalFeatures.mslVersion = SPIRV_CROSS_NAMESPACE::CompilerMSL::Options::make_msl_version(maj, min); switch (_metalFeatures.mslVersionEnum) { +#if MVK_XCODE_15 + case MTLLanguageVersion3_1: + setMSLVersion(3, 1); + break; +#endif #if MVK_XCODE_14 case MTLLanguageVersion3_0: setMSLVersion(3, 0); @@ -2082,9 +2164,9 @@ #endif } -// iOS and tvOS adjustments necessary when running in the simulator on non-Apple GPUs. -#if MVK_OS_SIMULATOR && !MVK_APPLE_SILICON - _metalFeatures.mtlBufferAlignment = 256; +// iOS and tvOS adjustments necessary when running on the simulator. +#if MVK_OS_SIMULATOR + _metalFeatures.mtlBufferAlignment = 256; // Even on Apple Silicon #endif // Currently, Metal argument buffer support is in beta stage, and is only supported @@ -2093,7 +2175,7 @@ // and a wider combination of GPU's on older macOS versions is under way. #if MVK_MACOS _metalFeatures.descriptorSetArgumentBuffers = (_metalFeatures.argumentBuffers && - (mvkOSVersionIsAtLeast(10.16) || + (mvkOSVersionIsAtLeast(11.0) || _properties.vendorID == kIntelVendorId)); #endif // Currently, if we don't support descriptor set argument buffers, we can't support argument buffers. @@ -2149,6 +2231,7 @@ _features.shaderInt16 = true; _features.multiDrawIndirect = true; _features.inheritedQueries = true; + _features.geometryShader = true; _features.shaderSampledImageArrayDynamicIndexing = _metalFeatures.arrayOfTextures; _features.textureCompressionBC = mvkSupportsBCTextureCompression(_mtlDevice); @@ -2197,9 +2280,13 @@ _features.dualSrcBlend = true; } +#if MVK_OS_SIMULATOR + _features.depthClamp = false; +#else if (supportsMTLFeatureSet(iOS_GPUFamily2_v4)) { _features.depthClamp = true; } +#endif if (supportsMTLFeatureSet(iOS_GPUFamily3_v2)) { _features.tessellationShader = true; @@ -2269,17 +2356,17 @@ void MVKPhysicalDevice::initLimits() { #if MVK_TVOS - _properties.limits.maxColorAttachments = kMVKCachedColorAttachmentCount; + _properties.limits.maxColorAttachments = kMVKMaxColorAttachmentCount; #endif #if MVK_IOS if (supportsMTLFeatureSet(iOS_GPUFamily2_v1)) { - _properties.limits.maxColorAttachments = kMVKCachedColorAttachmentCount; + _properties.limits.maxColorAttachments = kMVKMaxColorAttachmentCount; } else { - _properties.limits.maxColorAttachments = 4; // < kMVKCachedColorAttachmentCount + _properties.limits.maxColorAttachments = 4; // < kMVKMaxColorAttachmentCount } #endif #if MVK_MACOS - _properties.limits.maxColorAttachments = kMVKCachedColorAttachmentCount; + _properties.limits.maxColorAttachments = kMVKMaxColorAttachmentCount; #endif _properties.limits.maxFragmentOutputAttachments = _properties.limits.maxColorAttachments; @@ -2309,7 +2396,7 @@ float maxVPDim = max(_properties.limits.maxViewportDimensions[0], _properties.limits.maxViewportDimensions[1]); _properties.limits.viewportBoundsRange[0] = (-2.0 * maxVPDim); _properties.limits.viewportBoundsRange[1] = (2.0 * maxVPDim) - 1; - _properties.limits.maxViewports = _features.multiViewport ? kMVKCachedViewportScissorCount : 1; + _properties.limits.maxViewports = _features.multiViewport ? kMVKMaxViewportScissorCount : 1; _properties.limits.maxImageDimension3D = _metalFeatures.maxTextureLayers; _properties.limits.maxImageArrayLayers = _metalFeatures.maxTextureLayers; @@ -2527,7 +2614,7 @@ _properties.limits.optimalBufferCopyRowPitchAlignment = 1; _properties.limits.timestampComputeAndGraphics = VK_TRUE; - _properties.limits.timestampPeriod = _metalFeatures.counterSamplingPoints ? 1.0 : mvkGetTimestampPeriod(); + _properties.limits.timestampPeriod = mvkGetTimestampPeriod(); // Will be 1.0 on Apple Silicon _properties.limits.pointSizeRange[0] = 1; switch (_properties.vendorID) { @@ -2547,7 +2634,7 @@ _properties.limits.pointSizeGranularity = 1; _properties.limits.lineWidthRange[0] = 1; _properties.limits.lineWidthRange[1] = 1; - _properties.limits.lineWidthGranularity = 0; + _properties.limits.lineWidthGranularity = 1; _properties.limits.standardSampleLocations = VK_TRUE; _properties.limits.strictLines = _properties.vendorID == kIntelVendorId || _properties.vendorID == kNVVendorId; @@ -2724,6 +2811,8 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope } #endif //MVK_IOS_OR_TVOS +// Since this is a uint8_t array, use Big-Endian byte ordering, +// so a hex dump of the array is human readable in its parts. void MVKPhysicalDevice::initPipelineCacheUUID() { // Clear the UUID @@ -3034,11 +3123,6 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope MVKExtensionList* pWritableExtns = (MVKExtensionList*)&_supportedExtensions; pWritableExtns->disableAllButEnabledDeviceExtensions(); -#if MVK_IOS_OR_TVOS - if (!_metalFeatures.depthResolve) { - pWritableExtns->vk_KHR_depth_stencil_resolve.enabled = false; - } -#endif if (!_metalFeatures.samplerMirrorClampToEdge) { pWritableExtns->vk_KHR_sampler_mirror_clamp_to_edge.enabled = false; } @@ -3059,6 +3143,8 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope } if (!_metalFeatures.simdPermute && !_metalFeatures.quadPermute) { pWritableExtns->vk_KHR_shader_subgroup_extended_types.enabled = false; + pWritableExtns->vk_EXT_shader_subgroup_ballot.enabled = false; + pWritableExtns->vk_EXT_shader_subgroup_vote.enabled = false; } if (!_metalFeatures.shaderBarycentricCoordinates) { pWritableExtns->vk_KHR_fragment_shader_barycentric.enabled = false; @@ -3509,6 +3595,36 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope return VK_SUCCESS; } +void MVKDevice::getCalibratedTimestamps(uint32_t timestampCount, + const VkCalibratedTimestampInfoEXT* pTimestampInfos, + uint64_t* pTimestamps, + uint64_t* pMaxDeviation) { + MTLTimestamp cpuStamp, gpuStamp; + uint64_t cpuStart, cpuEnd; + + cpuStart = mvkGetAbsoluteTime(); + [getMTLDevice() sampleTimestamps: &cpuStamp gpuTimestamp: &gpuStamp]; + // Sample again to calculate the maximum deviation. Note that the + // -[MTLDevice sampleTimestamps:gpuTimestamp:] method guarantees that CPU + // timestamps are in nanoseconds. We don't want to call the method again, + // because that could result in an expensive syscall to query the GPU time- + // stamp. + cpuEnd = mvkGetAbsoluteTime(); + for (uint32_t tsIdx = 0; tsIdx < timestampCount; ++tsIdx) { + switch (pTimestampInfos[tsIdx].timeDomain) { + case VK_TIME_DOMAIN_DEVICE_EXT: + pTimestamps[tsIdx] = gpuStamp; + break; + // XXX Should be VK_TIME_DOMAIN_CLOCK_UPTIME_RAW_EXT + case VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT: + pTimestamps[tsIdx] = cpuStart; + break; + default: + continue; + } + } + *pMaxDeviation = cpuEnd - cpuStart; +} #pragma mark Object lifecycle @@ -3545,15 +3661,14 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope MVKBuffer* MVKDevice::createBuffer(const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator) { - return (MVKBuffer*)addResource(new MVKBuffer(this, pCreateInfo)); + return addBuffer(new MVKBuffer(this, pCreateInfo)); } void MVKDevice::destroyBuffer(MVKBuffer* mvkBuff, const VkAllocationCallbacks* pAllocator) { - if (mvkBuff) { - removeResource(mvkBuff); - mvkBuff->destroy(); - } + if ( !mvkBuff ) { return; } + removeBuffer(mvkBuff); + mvkBuff->destroy(); } MVKBufferView* MVKDevice::createBufferView(const VkBufferViewCreateInfo* pCreateInfo, @@ -3582,20 +3697,14 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope MVKImage* mvkImg = (swapchainInfo) ? new MVKPeerSwapchainImage(this, pCreateInfo, (MVKSwapchain*)swapchainInfo->swapchain, uint32_t(-1)) : new MVKImage(this, pCreateInfo); - for (auto& memoryBinding : mvkImg->_memoryBindings) { - addResource(memoryBinding); - } - return mvkImg; + return addImage(mvkImg); } void MVKDevice::destroyImage(MVKImage* mvkImg, const VkAllocationCallbacks* pAllocator) { - if (mvkImg) { - for (auto& memoryBinding : mvkImg->_memoryBindings) { - removeResource(memoryBinding); - } - mvkImg->destroy(); - } + if ( !mvkImg ) { return; } + removeImage(mvkImg); + mvkImg->destroy(); } MVKImageView* MVKDevice::createImageView(const VkImageViewCreateInfo* pCreateInfo, @@ -3610,20 +3719,6 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope MVKSwapchain* MVKDevice::createSwapchain(const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator) { -#if MVK_MACOS - // If we have selected a high-power GPU and want to force the window system - // to use it, force the window system to use a high-power GPU by calling the - // MTLCreateSystemDefaultDevice function, and if that GPU is the same as the - // selected GPU, update the MTLDevice instance used by the MVKPhysicalDevice. - id mtlDevice = _physicalDevice->getMTLDevice(); - if (mvkConfig().switchSystemGPU && !(mtlDevice.isLowPower || mtlDevice.isHeadless) ) { - id sysMTLDevice = MTLCreateSystemDefaultDevice(); - if (mvkGetRegistryID(sysMTLDevice) == mvkGetRegistryID(mtlDevice)) { - _physicalDevice->replaceMTLDevice(sysMTLDevice); - } - } -#endif - return new MVKSwapchain(this, pCreateInfo); } @@ -3636,22 +3731,16 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope MVKSwapchain* swapchain, uint32_t swapchainIndex, const VkAllocationCallbacks* pAllocator) { - MVKPresentableSwapchainImage* mvkImg = new MVKPresentableSwapchainImage(this, pCreateInfo, - swapchain, swapchainIndex); - for (auto& memoryBinding : mvkImg->_memoryBindings) { - addResource(memoryBinding); - } - return mvkImg; + auto* pImg = new MVKPresentableSwapchainImage(this, pCreateInfo, swapchain, swapchainIndex); + addImage(pImg); + return pImg; } void MVKDevice::destroyPresentableSwapchainImage(MVKPresentableSwapchainImage* mvkImg, const VkAllocationCallbacks* pAllocator) { - if (mvkImg) { - for (auto& memoryBinding : mvkImg->_memoryBindings) { - removeResource(memoryBinding); - } - mvkImg->destroy(); - } + if ( !mvkImg ) { return; } + removeImage(mvkImg); + mvkImg->destroy(); } MVKFence* MVKDevice::createFence(const VkFenceCreateInfo* pCreateInfo, @@ -3705,6 +3794,15 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope if (mvkSem4) { mvkSem4->destroy(); } } +MVKDeferredOperation* MVKDevice::createDeferredOperation(const VkAllocationCallbacks* pAllocator) { + return new MVKDeferredOperation(this); +} + +void MVKDevice::destroyDeferredOperation(MVKDeferredOperation* mvkDeferredOperation, + const VkAllocationCallbacks* pAllocator) { + if(mvkDeferredOperation) { mvkDeferredOperation->destroy(); } +} + MVKEvent* MVKDevice::createEvent(const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator) { const VkExportMetalObjectCreateInfoEXT* pExportInfo = nullptr; @@ -3906,6 +4004,11 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope return new MVKFramebuffer(this, pCreateInfo); } +MVKFramebuffer* MVKDevice::createFramebuffer(const VkRenderingInfo* pRenderingInfo, + const VkAllocationCallbacks* pAllocator) { + return new MVKFramebuffer(this, pRenderingInfo); +} + void MVKDevice::destroyFramebuffer(MVKFramebuffer* mvkFB, const VkAllocationCallbacks* pAllocator) { if (mvkFB) { mvkFB->destroy(); } @@ -3921,6 +4024,11 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope return new MVKRenderPass(this, pCreateInfo); } +MVKRenderPass* MVKDevice::createRenderPass(const VkRenderingInfo* pRenderingInfo, + const VkAllocationCallbacks* pAllocator) { + return new MVKRenderPass(this, pRenderingInfo); +} + void MVKDevice::destroyRenderPass(MVKRenderPass* mvkRP, const VkAllocationCallbacks* pAllocator) { if (mvkRP) { mvkRP->destroy(); } @@ -3987,42 +4095,79 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope mvkPDS->destroy(); } - #pragma mark Operations -// Adds the specified resource for tracking, and returns the added resource. -MVKResource* MVKDevice::addResource(MVKResource* rez) { +// If the underlying MTLBuffer is referenced in a shader only via its gpuAddress, +// the GPU might not be aware that the MTLBuffer needs to be made resident. +// Track the buffer as needing to be made resident if a shader is bound that uses +// PhysicalStorageBufferAddresses to access the contents of the underlying MTLBuffer. +MVKBuffer* MVKDevice::addBuffer(MVKBuffer* mvkBuff) { + if ( !mvkBuff ) { return mvkBuff; } + + lock_guard lock(_rezLock); + _resources.push_back(mvkBuff); + if (mvkIsAnyFlagEnabled(mvkBuff->getUsage(), VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)) { + _gpuAddressableBuffers.push_back(mvkBuff); + } + return mvkBuff; +} + +MVKBuffer* MVKDevice::removeBuffer(MVKBuffer* mvkBuff) { + if ( !mvkBuff ) { return mvkBuff; } + + lock_guard lock(_rezLock); + mvkRemoveFirstOccurance(_resources, mvkBuff); + if (mvkIsAnyFlagEnabled(mvkBuff->getUsage(), VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)) { + mvkRemoveFirstOccurance(_gpuAddressableBuffers, mvkBuff); + } + return mvkBuff; +} + +void MVKDevice::encodeGPUAddressableBuffers(MVKResourcesCommandEncoderState* rezEncState, MVKShaderStage stage) { + MTLResourceUsage mtlUsage = MTLResourceUsageRead | MTLResourceUsageWrite; + MTLRenderStages mtlRendStage = (stage == kMVKShaderStageFragment) ? MTLRenderStageFragment : MTLRenderStageVertex; + + lock_guard lock(_rezLock); + for (auto& buff : _gpuAddressableBuffers) { + rezEncState->encodeResourceUsage(stage, buff->getMTLBuffer(), mtlUsage, mtlRendStage); + } +} + +MVKImage* MVKDevice::addImage(MVKImage* mvkImg) { + if ( !mvkImg ) { return mvkImg; } + lock_guard lock(_rezLock); - _resources.push_back(rez); - return rez; + for (auto& mb : mvkImg->_memoryBindings) { + _resources.push_back(mb); + } + return mvkImg; } -// Removes the specified resource for tracking and returns the removed resource. -MVKResource* MVKDevice::removeResource(MVKResource* rez) { +MVKImage* MVKDevice::removeImage(MVKImage* mvkImg) { + if ( !mvkImg ) { return mvkImg; } + lock_guard lock(_rezLock); - mvkRemoveFirstOccurance(_resources, rez); - return rez; + for (auto& mb : mvkImg->_memoryBindings) { + mvkRemoveFirstOccurance(_resources, mb); + } + return mvkImg; } -// Adds the specified host semaphore to be woken upon device loss. void MVKDevice::addSemaphore(MVKSemaphoreImpl* sem4) { lock_guard lock(_sem4Lock); _awaitingSemaphores.push_back(sem4); } -// Removes the specified host semaphore. void MVKDevice::removeSemaphore(MVKSemaphoreImpl* sem4) { lock_guard lock(_sem4Lock); mvkRemoveFirstOccurance(_awaitingSemaphores, sem4); } -// Adds the specified timeline semaphore to be woken at the specified value upon device loss. void MVKDevice::addTimelineSemaphore(MVKTimelineSemaphore* sem4, uint64_t value) { lock_guard lock(_sem4Lock); _awaitingTimelineSem4s.emplace_back(sem4, value); } -// Removes the specified timeline semaphore. void MVKDevice::removeTimelineSemaphore(MVKTimelineSemaphore* sem4, uint64_t value) { lock_guard lock(_sem4Lock); mvkRemoveFirstOccurance(_awaitingTimelineSem4s, make_pair(sem4, value)); @@ -4069,7 +4214,6 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope } void MVKDevice::logPerformanceSummary() { - if (_activityPerformanceLoggingStyle == MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_IMMEDIATE) { return; } // Get a copy to minimize time under lock MVKPerformanceStatistics perfStats; @@ -4429,6 +4573,18 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope initQueues(pCreateInfo); reservePrivateData(pCreateInfo); +#if MVK_MACOS + // After enableExtensions + // If the VK_KHR_swapchain extension is enabled, we expect to render to the screen. + // In a multi-GPU system, if we are using the high-power GPU and want the window system + // to also use that GPU to avoid copying content between GPUs, force the window system + // to use the high-power GPU by calling the MTLCreateSystemDefaultDevice() function. + if (_enabledExtensions.vk_KHR_swapchain.enabled && mvkConfig().switchSystemGPU && + !(_physicalDevice->_mtlDevice.isLowPower || _physicalDevice->_mtlDevice.isHeadless) ) { + MTLCreateSystemDefaultDevice(); + } +#endif + // After enableExtensions && enableFeatures // Use Metal arg buffs if available, and either config wants them always, // or config wants them with descriptor indexing and descriptor indexing has been enabled. @@ -4549,7 +4705,8 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope //Enable device features based on requested and available features, // including extended features that are requested in the pNext chain. if (pCreateInfo->pEnabledFeatures) { - enableFeatures(&_enabledFeatures.robustBufferAccess, + enableFeatures(pCreateInfo->pEnabledFeatures, + &_enabledFeatures.robustBufferAccess, &pCreateInfo->pEnabledFeatures->robustBufferAccess, &pdFeats2.features.robustBufferAccess, 55); } @@ -4558,29 +4715,36 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope switch ((uint32_t)next->sType) { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2: { auto* requestedFeatures = (VkPhysicalDeviceFeatures2*)next; - enableFeatures(&_enabledFeatures.robustBufferAccess, + enableFeatures(requestedFeatures, + &_enabledFeatures.robustBufferAccess, &requestedFeatures->features.robustBufferAccess, &pdFeats2.features.robustBufferAccess, 55); break; } case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES: { auto* requestedFeatures = (VkPhysicalDeviceVulkan11Features*)next; - enableFeatures(&_enabled16BitStorageFeatures.storageBuffer16BitAccess, + enableFeatures(requestedFeatures, + &_enabled16BitStorageFeatures.storageBuffer16BitAccess, &requestedFeatures->storageBuffer16BitAccess, &pd16BitStorageFeatures.storageBuffer16BitAccess, 4); - enableFeatures(&_enabledMultiviewFeatures.multiview, + enableFeatures(requestedFeatures, + &_enabledMultiviewFeatures.multiview, &requestedFeatures->multiview, &pdMultiviewFeatures.multiview, 3); - enableFeatures(&_enabledVariablePointerFeatures.variablePointersStorageBuffer, + enableFeatures(requestedFeatures, + &_enabledVariablePointerFeatures.variablePointersStorageBuffer, &requestedFeatures->variablePointersStorageBuffer, &pdVariablePointerFeatures.variablePointersStorageBuffer, 2); - enableFeatures(&_enabledProtectedMemoryFeatures.protectedMemory, + enableFeatures(requestedFeatures, + &_enabledProtectedMemoryFeatures.protectedMemory, &requestedFeatures->protectedMemory, &pdProtectedMemoryFeatures.protectedMemory, 1); - enableFeatures(&_enabledSamplerYcbcrConversionFeatures.samplerYcbcrConversion, + enableFeatures(requestedFeatures, + &_enabledSamplerYcbcrConversionFeatures.samplerYcbcrConversion, &requestedFeatures->samplerYcbcrConversion, &pdSamplerYcbcrConversionFeatures.samplerYcbcrConversion, 1); - enableFeatures(&_enabledShaderDrawParametersFeatures.shaderDrawParameters, + enableFeatures(requestedFeatures, + &_enabledShaderDrawParametersFeatures.shaderDrawParameters, &requestedFeatures->shaderDrawParameters, &pdShaderDrawParametersFeatures.shaderDrawParameters, 1); break; @@ -4588,55 +4752,72 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES: { auto& pdvulkan12FeaturesNoExt = _physicalDevice->_vulkan12FeaturesNoExt; auto* requestedFeatures = (VkPhysicalDeviceVulkan12Features*)next; - enableFeatures(&_enabledVulkan12FeaturesNoExt.samplerMirrorClampToEdge, + enableFeatures(requestedFeatures, + &_enabledVulkan12FeaturesNoExt.samplerMirrorClampToEdge, &requestedFeatures->samplerMirrorClampToEdge, &pdvulkan12FeaturesNoExt.samplerMirrorClampToEdge, 2); - enableFeatures(&_enabled8BitStorageFeatures.storageBuffer8BitAccess, + enableFeatures(requestedFeatures, + &_enabled8BitStorageFeatures.storageBuffer8BitAccess, &requestedFeatures->storageBuffer8BitAccess, &pd8BitStorageFeatures.storageBuffer8BitAccess, 3); - enableFeatures(&_enabledShaderAtomicInt64Features.shaderBufferInt64Atomics, + enableFeatures(requestedFeatures, + &_enabledShaderAtomicInt64Features.shaderBufferInt64Atomics, &requestedFeatures->shaderBufferInt64Atomics, &pdShaderAtomicInt64Features.shaderBufferInt64Atomics, 2); - enableFeatures(&_enabledShaderFloat16Int8Features.shaderFloat16, + enableFeatures(requestedFeatures, + &_enabledShaderFloat16Int8Features.shaderFloat16, &requestedFeatures->shaderFloat16, &pdShaderFloat16Int8Features.shaderFloat16, 2); - enableFeatures(&_enabledVulkan12FeaturesNoExt.descriptorIndexing, + enableFeatures(requestedFeatures, + &_enabledVulkan12FeaturesNoExt.descriptorIndexing, &requestedFeatures->descriptorIndexing, &pdvulkan12FeaturesNoExt.descriptorIndexing, 1); - enableFeatures(&_enabledDescriptorIndexingFeatures.shaderInputAttachmentArrayDynamicIndexing, + enableFeatures(requestedFeatures, + &_enabledDescriptorIndexingFeatures.shaderInputAttachmentArrayDynamicIndexing, &requestedFeatures->shaderInputAttachmentArrayDynamicIndexing, &pdDescriptorIndexingFeatures.shaderInputAttachmentArrayDynamicIndexing, 20); - enableFeatures(&_enabledVulkan12FeaturesNoExt.samplerFilterMinmax, + enableFeatures(requestedFeatures, + &_enabledVulkan12FeaturesNoExt.samplerFilterMinmax, &requestedFeatures->samplerFilterMinmax, &pdvulkan12FeaturesNoExt.samplerFilterMinmax, 1); - enableFeatures(&_enabledScalarBlockLayoutFeatures.scalarBlockLayout, + enableFeatures(requestedFeatures, + &_enabledScalarBlockLayoutFeatures.scalarBlockLayout, &requestedFeatures->scalarBlockLayout, &pdScalarBlockLayoutFeatures.scalarBlockLayout, 1); - enableFeatures(&_enabledImagelessFramebufferFeatures.imagelessFramebuffer, + enableFeatures(requestedFeatures, + &_enabledImagelessFramebufferFeatures.imagelessFramebuffer, &requestedFeatures->imagelessFramebuffer, &pdImagelessFramebufferFeatures.imagelessFramebuffer, 1); - enableFeatures(&_enabledUniformBufferStandardLayoutFeatures.uniformBufferStandardLayout, + enableFeatures(requestedFeatures, + &_enabledUniformBufferStandardLayoutFeatures.uniformBufferStandardLayout, &requestedFeatures->uniformBufferStandardLayout, &pdUniformBufferStandardLayoutFeatures.uniformBufferStandardLayout, 1); - enableFeatures(&_enabledShaderSubgroupExtendedTypesFeatures.shaderSubgroupExtendedTypes, + enableFeatures(requestedFeatures, + &_enabledShaderSubgroupExtendedTypesFeatures.shaderSubgroupExtendedTypes, &requestedFeatures->shaderSubgroupExtendedTypes, &pdShaderSubgroupExtendedTypesFeatures.shaderSubgroupExtendedTypes, 1); - enableFeatures(&_enabledSeparateDepthStencilLayoutsFeatures.separateDepthStencilLayouts, + enableFeatures(requestedFeatures, + &_enabledSeparateDepthStencilLayoutsFeatures.separateDepthStencilLayouts, &requestedFeatures->separateDepthStencilLayouts, &pdSeparateDepthStencilLayoutsFeatures.separateDepthStencilLayouts, 1); - enableFeatures(&_enabledHostQueryResetFeatures.hostQueryReset, + enableFeatures(requestedFeatures, + &_enabledHostQueryResetFeatures.hostQueryReset, &requestedFeatures->hostQueryReset, &pdHostQueryResetFeatures.hostQueryReset, 1); - enableFeatures(&_enabledTimelineSemaphoreFeatures.timelineSemaphore, + enableFeatures(requestedFeatures, + &_enabledTimelineSemaphoreFeatures.timelineSemaphore, &requestedFeatures->timelineSemaphore, &pdTimelineSemaphoreFeatures.timelineSemaphore, 1); - enableFeatures(&_enabledBufferDeviceAddressFeatures.bufferDeviceAddress, + enableFeatures(requestedFeatures, + &_enabledBufferDeviceAddressFeatures.bufferDeviceAddress, &requestedFeatures->bufferDeviceAddress, &pdBufferDeviceAddressFeatures.bufferDeviceAddress, 3); - enableFeatures(&_enabledVulkanMemoryModelFeatures.vulkanMemoryModel, + enableFeatures(requestedFeatures, + &_enabledVulkanMemoryModelFeatures.vulkanMemoryModel, &requestedFeatures->vulkanMemoryModel, &pdVulkanMemoryModelFeatures.vulkanMemoryModel, 3); - enableFeatures(&_enabledVulkan12FeaturesNoExt.shaderOutputViewportIndex, + enableFeatures(requestedFeatures, + &_enabledVulkan12FeaturesNoExt.shaderOutputViewportIndex, &requestedFeatures->shaderOutputViewportIndex, &pdvulkan12FeaturesNoExt.shaderOutputViewportIndex, 3); break; @@ -4644,17 +4825,17 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope #define MVK_DEVICE_FEATURE(structName, enumName, flagCount) \ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_##enumName##_FEATURES: { \ - enableFeatures((VkBaseInStructure*)&_enabled##structName##Features, \ - next, \ - (VkBaseInStructure*)&pd##structName##Features, \ + enableFeatures(&_enabled##structName##Features, \ + (VkPhysicalDevice##structName##Features*)next, \ + &pd##structName##Features, \ flagCount); \ break; \ } #define MVK_DEVICE_FEATURE_EXTN(structName, enumName, extnSfx, flagCount) \ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_##enumName##_FEATURES_##extnSfx: { \ - enableFeatures((VkBaseInStructure*)&_enabled##structName##Features, \ - next, \ - (VkBaseInStructure*)&pd##structName##Features, \ + enableFeatures(&_enabled##structName##Features, \ + (VkPhysicalDevice##structName##Features##extnSfx*)next, \ + &pd##structName##Features, \ flagCount); \ break; \ } @@ -4666,18 +4847,23 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope } } -void MVKDevice::enableFeatures(VkBaseInStructure* pEnabled, const VkBaseInStructure* pRequested, const VkBaseInStructure* pAvailable, uint32_t count) { - enableFeatures((VkBool32*)(&(pEnabled->pNext) + 1), - (VkBool32*)(&(pRequested->pNext) + 1), - (VkBool32*)(&(pAvailable->pNext) + 1), +template +void MVKDevice::enableFeatures(S* pEnabled, const S* pRequested, const S* pAvailable, uint32_t count) { + enableFeatures(pRequested, + (VkBool32*)mvkGetAddressOfFirstMember(pEnabled), + (VkBool32*)mvkGetAddressOfFirstMember(pRequested), + (VkBool32*)mvkGetAddressOfFirstMember(pAvailable), count); } -void MVKDevice::enableFeatures(VkBool32* pEnabledBools, const VkBool32* pRequestedBools, const VkBool32* pAvailableBools, uint32_t count) { +template +void MVKDevice::enableFeatures(S* pRequested, VkBool32* pEnabledBools, const VkBool32* pRequestedBools, const VkBool32* pAvailableBools, uint32_t count) { for (uint32_t i = 0; i < count; i++) { pEnabledBools[i] = pRequestedBools[i] && pAvailableBools[i]; if (pRequestedBools[i] && !pAvailableBools[i]) { - setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateDevice(): Requested feature is not available on this device.")); + uintptr_t mbrOffset = (uintptr_t)&pRequestedBools[i] - (uintptr_t)mvkGetAddressOfFirstMember(pRequested); + size_t mbrIdxOrd = (mbrOffset / sizeof(VkBool32)) + 1; + setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateDevice(): Requested physical device feature specified by the %zu%s flag in %s is not available on this device.", mbrIdxOrd, mvk::getOrdinalSuffix(mbrIdxOrd), mvk::getTypeName(pRequested).c_str())); } } } @@ -4763,20 +4949,39 @@ uint64_t mvkGetRegistryID(id mtlDevice) { return [mtlDevice respondsToSelector: @selector(registryID)] ? mtlDevice.registryID : 0; } -// Since MacCatalyst does not support supportsBCTextureCompression, it is not possible -// for Apple Silicon to indicate a lack of support for BCn when running MacCatalyst. -// Therefore, assume for now that this means MacCatalyst does not actually support BCn. -// Further evidence may change this approach. -bool mvkSupportsBCTextureCompression(id mtlDevice) { -#if MVK_IOS || MVK_TVOS || MVK_MACCAT - return false; -#endif +uint64_t mvkGetLocationID(id mtlDevice) { + uint64_t hash = 0; + #if MVK_MACOS && !MVK_MACCAT -#if MVK_XCODE_12 + // All of these device properties were added at the same time, + // so only need to check for the presence of one of them. + if ([mtlDevice respondsToSelector: @selector(location)]) { + uint64_t val; + + val = mtlDevice.location; + hash = mvkHash(&val, 1, hash); + + val = mtlDevice.locationNumber; + hash = mvkHash(&val, 1, hash); + + val = mtlDevice.peerGroupID; + hash = mvkHash(&val, 1, hash); + + val = mtlDevice.peerIndex; + hash = mvkHash(&val, 1, hash); + } +#endif + + return hash; +} + +// If the supportsBCTextureCompression query is available, use it. +// Otherwise only macOS supports BC compression. +bool mvkSupportsBCTextureCompression(id mtlDevice) { +#if MVK_XCODE_14_3 || (MVK_XCODE_12 && MVK_MACOS && !MVK_MACCAT) if ([mtlDevice respondsToSelector: @selector(supportsBCTextureCompression)]) { return mtlDevice.supportsBCTextureCompression; } #endif - return true; -#endif + return MVK_MACOS && !MVK_MACCAT; } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceFeatureStructs.def b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceFeatureStructs.def index 0674e4c18..c0bbb4816 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceFeatureStructs.def +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceFeatureStructs.def @@ -62,6 +62,7 @@ MVK_DEVICE_FEATURE(VariablePointer, VARIABLE_POINTER, MVK_DEVICE_FEATURE(VulkanMemoryModel, VULKAN_MEMORY_MODEL, 3) MVK_DEVICE_FEATURE_EXTN(FragmentShaderBarycentric, FRAGMENT_SHADER_BARYCENTRIC, KHR, 1) MVK_DEVICE_FEATURE_EXTN(PortabilitySubset, PORTABILITY_SUBSET, KHR, 15) +MVK_DEVICE_FEATURE_EXTN(4444Formats, 4444_FORMATS, EXT, 2) MVK_DEVICE_FEATURE_EXTN(FragmentShaderInterlock, FRAGMENT_SHADER_INTERLOCK, EXT, 3) MVK_DEVICE_FEATURE_EXTN(PipelineCreationCacheControl, PIPELINE_CREATION_CACHE_CONTROL, EXT, 1) MVK_DEVICE_FEATURE_EXTN(Robustness2, ROBUSTNESS_2, EXT, 3) diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm index e7e97ea9f..08a6fb9f7 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm @@ -20,7 +20,6 @@ #include "MVKBuffer.h" #include "MVKImage.h" #include "MVKQueue.h" -#include "MVKEnvironment.h" #include "mvk_datatypes.hpp" #include "MVKFoundation.h" #include @@ -160,7 +159,7 @@ // If a dedicated alloc, ensure this image is the one and only image // I am dedicated to. If my image is aliasable, though, allow other aliasable // images to bind to me. - if (_isDedicated && (_imageMemoryBindings.empty() || !(contains(_imageMemoryBindings, mvkImg) || (_imageMemoryBindings[0]->_image->getIsAliasable() && mvkImg->_image->getIsAliasable()))) ) { + if (_isDedicated && (_imageMemoryBindings.empty() || !(mvkContains(_imageMemoryBindings, mvkImg) || (_imageMemoryBindings[0]->_image->getIsAliasable() && mvkImg->_image->getIsAliasable()))) ) { return reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not bind VkImage %p to a VkDeviceMemory dedicated to resource %p. A dedicated allocation may only be used with the resource it was dedicated to.", mvkImg, getDedicatedResource() ); } @@ -180,7 +179,7 @@ if (_mtlHeap) { return true; } - // Can't create a MTLHeap on a imported memory + // Can't create a MTLHeap on imported memory if (_isHostMemImported) { return true; } // Don't bother if we don't have placement heaps. @@ -284,6 +283,7 @@ const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator) : MVKVulkanAPIDeviceObject(device) { // Set Metal memory parameters + _vkMemAllocFlags = 0; _vkMemPropFlags = _device->_pMemoryProperties->memoryTypes[pAllocateInfo->memoryTypeIndex].propertyFlags; _mtlStorageMode = mvkMTLStorageModeFromVkMemoryPropertyFlags(_vkMemPropFlags); _mtlCPUCacheMode = mvkMTLCPUCacheModeFromVkMemoryPropertyFlags(_vkMemPropFlags); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h index ec9b3fdfa..d5e9c469c 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h @@ -58,6 +58,8 @@ class MVKFramebuffer : public MVKVulkanAPIDeviceObject { MVKFramebuffer(MVKDevice* device, const VkFramebufferCreateInfo* pCreateInfo); + MVKFramebuffer(MVKDevice* device, const VkRenderingInfo* pRenderingInfo); + ~MVKFramebuffer() override; protected: @@ -69,12 +71,3 @@ class MVKFramebuffer : public MVKVulkanAPIDeviceObject { VkExtent2D _extent; uint32_t _layerCount; }; - - -#pragma mark - -#pragma mark Support functions - -/** Returns an image-less MVKFramebuffer object created from the rendering info. */ -MVKFramebuffer* mvkCreateFramebuffer(MVKDevice* device, - const VkRenderingInfo* pRenderingInfo, - MVKRenderPass* mvkRenderPass); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm index c6f56bc75..d0c376ad5 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm @@ -82,8 +82,8 @@ MVKFramebuffer::MVKFramebuffer(MVKDevice* device, const VkFramebufferCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) { - _extent = { .width = pCreateInfo->width, .height = pCreateInfo->height }; _layerCount = pCreateInfo->layers; + _extent = { .width = pCreateInfo->width, .height = pCreateInfo->height }; // If this is not an image-less framebuffer, add the attachments if ( !mvkIsAnyFlagEnabled(pCreateInfo->flags, VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT) ) { @@ -94,51 +94,25 @@ } } -MVKFramebuffer::~MVKFramebuffer() { - [_mtlDummyTex release]; -} - - -#pragma mark - -#pragma mark Support functions +MVKFramebuffer::MVKFramebuffer(MVKDevice* device, + const VkRenderingInfo* pRenderingInfo) : MVKVulkanAPIDeviceObject(device) { + _layerCount = pRenderingInfo->layerCount; -MVKFramebuffer* mvkCreateFramebuffer(MVKDevice* device, - const VkRenderingInfo* pRenderingInfo, - MVKRenderPass* mvkRenderPass) { - uint32_t attCnt = 0; - VkExtent3D fbExtent = {}; + _extent = {}; for (uint32_t caIdx = 0; caIdx < pRenderingInfo->colorAttachmentCount; caIdx++) { auto& clrAtt = pRenderingInfo->pColorAttachments[caIdx]; if (clrAtt.imageView) { - fbExtent = ((MVKImageView*)clrAtt.imageView)->getExtent3D(); - attCnt++; - if (clrAtt.resolveImageView && clrAtt.resolveMode != VK_RESOLVE_MODE_NONE) { - attCnt++; - } + _extent = mvkVkExtent2DFromVkExtent3D(((MVKImageView*)clrAtt.imageView)->getExtent3D()); } } - auto* pDSAtt = pRenderingInfo->pDepthAttachment ? pRenderingInfo->pDepthAttachment : pRenderingInfo->pStencilAttachment; - if (pDSAtt) { - if (pDSAtt->imageView) { - fbExtent = ((MVKImageView*)pDSAtt->imageView)->getExtent3D(); - attCnt++; - } - if (pDSAtt->resolveImageView && pDSAtt->resolveMode != VK_RESOLVE_MODE_NONE) { - attCnt++; - } + if (pRenderingInfo->pDepthAttachment && pRenderingInfo->pDepthAttachment->imageView) { + _extent = mvkVkExtent2DFromVkExtent3D(((MVKImageView*)pRenderingInfo->pDepthAttachment->imageView)->getExtent3D()); + } + if (pRenderingInfo->pStencilAttachment && pRenderingInfo->pStencilAttachment->imageView) { + _extent = mvkVkExtent2DFromVkExtent3D(((MVKImageView*)pRenderingInfo->pStencilAttachment->imageView)->getExtent3D()); } - - VkFramebufferCreateInfo fbCreateInfo; - fbCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - fbCreateInfo.pNext = nullptr; - fbCreateInfo.flags = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT; - fbCreateInfo.renderPass = (VkRenderPass)mvkRenderPass; - fbCreateInfo.attachmentCount = attCnt; - fbCreateInfo.pAttachments = nullptr; - fbCreateInfo.width = fbExtent.width; - fbCreateInfo.height = fbExtent.height; - fbCreateInfo.layers = pRenderingInfo->layerCount; - - return device->createFramebuffer(&fbCreateInfo, nullptr); } +MVKFramebuffer::~MVKFramebuffer() { + [_mtlDummyTex release]; +} diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h index c2a03ee53..572e8f06a 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h @@ -224,6 +224,9 @@ class MVKImage : public MVKVulkanAPIDeviceObject { /** Returns the number of planes of this image view. */ uint8_t getPlaneCount() { return _planes.size(); } + /** Returns whether or not the image format requires swizzling. */ + bool needsSwizzle() { return getPixelFormats()->needsSwizzle(_vkFormat); } + /** Populates the specified layout for the specified sub-resource. */ VkResult getSubresourceLayout(const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout); @@ -449,7 +452,7 @@ class MVKPresentableSwapchainImage : public MVKSwapchainImage { #pragma mark Metal /** Presents the contained drawable to the OS. */ - void presentCAMetalDrawable(id mtlCmdBuff, MVKImagePresentInfo& presentInfo); + void presentCAMetalDrawable(id mtlCmdBuff, MVKImagePresentInfo presentInfo); #pragma mark Construction @@ -463,7 +466,7 @@ class MVKPresentableSwapchainImage : public MVKSwapchainImage { friend MVKSwapchain; id getCAMetalDrawable() override; - void addPresentedHandler(id mtlDrawable, MVKImagePresentInfo& presentInfo); + void addPresentedHandler(id mtlDrawable, MVKImagePresentInfo presentInfo); void releaseMetalDrawable(); MVKSwapchainImageAvailability getAvailability(); void makeAvailable(const MVKSwapchainSignaler& signaler); @@ -560,6 +563,9 @@ class MVKImageView : public MVKVulkanAPIDeviceObject { /** Returns the 3D extent of this image at the specified mipmap level. */ VkExtent3D getExtent3D(uint8_t planeIndex = 0, uint32_t mipLevel = 0) { return _image->getExtent3D(planeIndex, mipLevel); } + /** Return the underlying image. */ + MVKImage* getImage() { return _image; } + #pragma mark Metal /** Returns the Metal texture underlying this image view. */ diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm index 19822de6a..7db141221 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm @@ -21,7 +21,6 @@ #include "MVKSwapchain.h" #include "MVKCommandBuffer.h" #include "MVKCmdDebug.h" -#include "MVKEnvironment.h" #include "MVKFoundation.h" #include "MVKOSExtensions.h" #include "MVKCodec.h" @@ -63,7 +62,7 @@ offset: memoryBinding->getDeviceMemoryOffset() + _subresources[0].layout.offset]; if (_image->_isAliasable) { [_mtlTexture makeAliasable]; } } else if (_image->_isAliasable && dvcMem && dvcMem->isDedicatedAllocation() && - !contains(dvcMem->_imageMemoryBindings, memoryBinding)) { + !mvkContains(dvcMem->_imageMemoryBindings, memoryBinding)) { // This is a dedicated allocation, but it belongs to another aliasable image. // In this case, use the MTLTexture from the memory's dedicated image. // We know the other image must be aliasable, or I couldn't have been bound @@ -935,6 +934,9 @@ (_hasMutableFormat && pixFmts->getViewClass(_vkFormat) == MVKMTLViewClass::Color32 && (getIsValidViewFormat(VK_FORMAT_R32_UINT) || getIsValidViewFormat(VK_FORMAT_R32_SINT))))); + if (mvkIsAnyFlagEnabled(getCombinedUsage(), VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) && !getDevice()->getPhysicalDevice()->getMetalFeatures()->renderLinearTextures) + _isLinearForAtomics = false; + _is3DCompressed = (getImageType() == VK_IMAGE_TYPE_3D) && (pixFmts->getFormatType(pCreateInfo->format) == kMVKFormatCompressed) && !_device->_pMetalFeatures->native3DCompressedTextures; _isDepthStencilAttachment = (mvkAreAllFlagsEnabled(pCreateInfo->usage, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) || mvkAreAllFlagsEnabled(pixFmts->getVkFormatProperties(pCreateInfo->format).optimalTilingFeatures, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)); @@ -1295,8 +1297,9 @@ static void signalAndUnmarkAsTracked(const MVKSwapchainSignaler& signaler) { } // Present the drawable and make myself available only once the command buffer has completed. +// Pass MVKImagePresentInfo by value because it may not exist when the callback runs. void MVKPresentableSwapchainImage::presentCAMetalDrawable(id mtlCmdBuff, - MVKImagePresentInfo& presentInfo) { + MVKImagePresentInfo presentInfo) { lock_guard lock(_availabilityLock); _swapchain->willPresentSurface(getMTLTexture(0), mtlCmdBuff); @@ -1313,8 +1316,9 @@ static void signalAndUnmarkAsTracked(const MVKSwapchainSignaler& signaler) { mtlDrwbl.layer.displaySyncEnabledMVK = (presentInfo.presentMode != VK_PRESENT_MODE_IMMEDIATE_KHR); } if (presentInfo.hasPresentTime) { - // Convert from nsecs to seconds for Metal addPresentedHandler(mtlDrwbl, presentInfo); + } + if (presentInfo.desiredPresentTime) { [mtlDrwbl presentAtTime: (double)presentInfo.desiredPresentTime * 1.0e-9]; } else { [mtlDrwbl present]; @@ -1358,8 +1362,9 @@ static void signalAndUnmarkAsTracked(const MVKSwapchainSignaler& signaler) { signalPresentationSemaphore(signaler, mtlCmdBuff); } +// Pass MVKImagePresentInfo by value because it may not exist when the callback runs. void MVKPresentableSwapchainImage::addPresentedHandler(id mtlDrawable, - MVKImagePresentInfo& presentInfo) { + MVKImagePresentInfo presentInfo) { #if !MVK_OS_SIMULATOR if ([mtlDrawable respondsToSelector: @selector(addPresentedHandler:)]) { retain(); // Ensure this image is not destroyed while awaiting presentation @@ -1573,6 +1578,26 @@ static void signalAndUnmarkAsTracked(const MVKSwapchainSignaler& signaler) { VkImageAspectFlags aspectMask = pCreateInfo->subresourceRange.aspectMask; #define adjustComponentSwizzleValue(comp, currVal, newVal) if (_componentSwizzle.comp == VK_COMPONENT_SWIZZLE_ ##currVal) { _componentSwizzle.comp = VK_COMPONENT_SWIZZLE_ ##newVal; } +#define adjustAnyComponentSwizzleValue(comp, I, R, G, B, A) \ + switch (_componentSwizzle.comp) { \ + case VK_COMPONENT_SWIZZLE_IDENTITY: \ + _componentSwizzle.comp = VK_COMPONENT_SWIZZLE_##I; \ + break; \ + case VK_COMPONENT_SWIZZLE_R: \ + _componentSwizzle.comp = VK_COMPONENT_SWIZZLE_##R; \ + break; \ + case VK_COMPONENT_SWIZZLE_G: \ + _componentSwizzle.comp = VK_COMPONENT_SWIZZLE_##G; \ + break; \ + case VK_COMPONENT_SWIZZLE_B: \ + _componentSwizzle.comp = VK_COMPONENT_SWIZZLE_##B; \ + break; \ + case VK_COMPONENT_SWIZZLE_A: \ + _componentSwizzle.comp = VK_COMPONENT_SWIZZLE_##A; \ + break; \ + default: \ + break; \ + } // Use swizzle adjustment to bridge some differences between Vulkan and Metal pixel formats. // Do this ahead of other tests and adjustments so that swizzling will be enabled by tests below. @@ -1587,6 +1612,24 @@ static void signalAndUnmarkAsTracked(const MVKSwapchainSignaler& signaler) { adjustComponentSwizzleValue(a, IDENTITY, ONE); break; + case VK_FORMAT_A4R4G4B4_UNORM_PACK16: + // Metal doesn't (publicly) support this directly, so use a swizzle to get the ordering right. + // n.b. **Do NOT use adjustComponentSwizzleValue if multiple values need substitution, + // and some of the substitutes are keys for other substitutions!** + adjustAnyComponentSwizzleValue(r, G, G, B, A, R); + adjustAnyComponentSwizzleValue(g, B, G, B, A, R); + adjustAnyComponentSwizzleValue(b, A, G, B, A, R); + adjustAnyComponentSwizzleValue(a, R, G, B, A, R); + break; + + case VK_FORMAT_A4B4G4R4_UNORM_PACK16: + // Metal doesn't support this directly, so use a swizzle to get the ordering right. + adjustAnyComponentSwizzleValue(r, A, A, B, G, R); + adjustAnyComponentSwizzleValue(g, B, A, B, G, R); + adjustAnyComponentSwizzleValue(b, G, A, B, G, R); + adjustAnyComponentSwizzleValue(a, R, A, B, G, R); + break; + default: break; } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.h b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.h index 6f9066402..9e41ac71c 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.h @@ -18,7 +18,6 @@ #pragma once -#include "MVKEnvironment.h" #include "MVKLayers.h" #include "MVKVulkanAPIObject.h" #include "MVKSmallVector.h" diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm index 8988f7763..5c6e6cb9b 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm @@ -22,6 +22,7 @@ #include "MVKFoundation.h" #include "MVKSurface.h" #include "MVKOSExtensions.h" +#include "mvk_deprecated_api.h" using namespace std; @@ -340,11 +341,6 @@ initProcAddrs(); // Init function pointers - setConfigurationResult(verifyLayers(pCreateInfo->enabledLayerCount, pCreateInfo->ppEnabledLayerNames)); - MVKExtensionList* pWritableExtns = (MVKExtensionList*)&_enabledExtensions; - setConfigurationResult(pWritableExtns->enable(pCreateInfo->enabledExtensionCount, - pCreateInfo->ppEnabledExtensionNames, - getDriverLayer()->getSupportedInstanceExtensions())); logVersions(); // Log the MoltenVK and Vulkan versions // Populate the array of physical GPU devices. @@ -366,6 +362,13 @@ setConfigurationResult(reportError(VK_ERROR_INCOMPATIBLE_DRIVER, "To support Mac Catalyst, MoltenVK requires macOS 11.0 or above.")); } + // Enable extensions after logging the system and GPU info, for any logging done during extension enablement. + setConfigurationResult(verifyLayers(pCreateInfo->enabledLayerCount, pCreateInfo->ppEnabledLayerNames)); + MVKExtensionList* pWritableExtns = (MVKExtensionList*)&_enabledExtensions; + setConfigurationResult(pWritableExtns->enable(pCreateInfo->enabledExtensionCount, + pCreateInfo->ppEnabledExtensionNames, + getDriverLayer()->getSupportedInstanceExtensions())); + MVKLogInfo("Created VkInstance for Vulkan version %s, as requested by app, with the following %d Vulkan extensions enabled:%s", mvkGetVulkanVersionString(_appInfo.apiVersion).c_str(), _enabledExtensions.getEnabledCount(), @@ -437,10 +440,14 @@ #define ADD_INST_EXT2_ENTRY_POINT(func, EXT1, EXT2) ADD_ENTRY_POINT(func, 0, VK_##EXT1##_EXTENSION_NAME, VK_##EXT2##_EXTENSION_NAME, false) #define ADD_DVC_EXT2_ENTRY_POINT(func, EXT1, EXT2) ADD_ENTRY_POINT(func, 0, VK_##EXT1##_EXTENSION_NAME, VK_##EXT2##_EXTENSION_NAME, true) +// Add an open function, not tied to core or an extension. +#define ADD_INST_OPEN_ENTRY_POINT(func) ADD_ENTRY_POINT(func, 0, nullptr, nullptr, false) +#define ADD_DVC_OPEN_ENTRY_POINT(func) ADD_ENTRY_POINT(func, 0, nullptr, nullptr, true) + // Initializes the function pointer map. void MVKInstance::initProcAddrs() { - // Instance functions + // Instance functions. ADD_INST_ENTRY_POINT(vkDestroyInstance); ADD_INST_ENTRY_POINT(vkEnumeratePhysicalDevices); ADD_INST_ENTRY_POINT(vkGetPhysicalDeviceFeatures); @@ -468,7 +475,57 @@ ADD_INST_1_3_PROMOTED_ENTRY_POINT(vkGetPhysicalDeviceToolProperties, EXT_TOOLING_INFO); - // Device functions: + // Instance extension functions. + ADD_INST_EXT_ENTRY_POINT(vkDestroySurfaceKHR, KHR_SURFACE); + ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceSurfaceSupportKHR, KHR_SURFACE); + ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR, KHR_SURFACE); + ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceSurfaceFormatsKHR, KHR_SURFACE); + ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceSurfacePresentModesKHR, KHR_SURFACE); + ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceSurfaceCapabilities2KHR, KHR_GET_SURFACE_CAPABILITIES_2); + ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceSurfaceFormats2KHR, KHR_GET_SURFACE_CAPABILITIES_2); + ADD_INST_EXT_ENTRY_POINT(vkCreateDebugReportCallbackEXT, EXT_DEBUG_REPORT); + ADD_INST_EXT_ENTRY_POINT(vkDestroyDebugReportCallbackEXT, EXT_DEBUG_REPORT); + ADD_INST_EXT_ENTRY_POINT(vkDebugReportMessageEXT, EXT_DEBUG_REPORT); + ADD_INST_EXT_ENTRY_POINT(vkSetDebugUtilsObjectNameEXT, EXT_DEBUG_UTILS); + ADD_INST_EXT_ENTRY_POINT(vkSetDebugUtilsObjectTagEXT, EXT_DEBUG_UTILS); + ADD_INST_EXT_ENTRY_POINT(vkQueueBeginDebugUtilsLabelEXT, EXT_DEBUG_UTILS); + ADD_INST_EXT_ENTRY_POINT(vkQueueEndDebugUtilsLabelEXT, EXT_DEBUG_UTILS); + ADD_INST_EXT_ENTRY_POINT(vkQueueInsertDebugUtilsLabelEXT, EXT_DEBUG_UTILS); + ADD_INST_EXT_ENTRY_POINT(vkCmdBeginDebugUtilsLabelEXT, EXT_DEBUG_UTILS); + ADD_INST_EXT_ENTRY_POINT(vkCmdEndDebugUtilsLabelEXT, EXT_DEBUG_UTILS); + ADD_INST_EXT_ENTRY_POINT(vkCmdInsertDebugUtilsLabelEXT, EXT_DEBUG_UTILS); + 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); +#endif +#ifdef VK_USE_PLATFORM_MACOS_MVK + ADD_INST_EXT_ENTRY_POINT(vkCreateMacOSSurfaceMVK, MVK_MACOS_SURFACE); +#endif + + // MoltenVK-specific instannce functions, not tied to a Vulkan API version or an extension. + ADD_INST_OPEN_ENTRY_POINT(vkGetMoltenVKConfigurationMVK); + ADD_INST_OPEN_ENTRY_POINT(vkSetMoltenVKConfigurationMVK); + ADD_INST_OPEN_ENTRY_POINT(vkGetPhysicalDeviceMetalFeaturesMVK); + ADD_INST_OPEN_ENTRY_POINT(vkGetPerformanceStatisticsMVK); + + // For deprecated MoltenVK-specific functions, suppress compiler deprecation warning. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + ADD_INST_EXT_ENTRY_POINT(vkGetVersionStringsMVK, MVK_MOLTENVK); + ADD_INST_EXT_ENTRY_POINT(vkGetMTLDeviceMVK, MVK_MOLTENVK); + ADD_INST_EXT_ENTRY_POINT(vkSetMTLTextureMVK, MVK_MOLTENVK); + ADD_INST_EXT_ENTRY_POINT(vkGetMTLTextureMVK, MVK_MOLTENVK); + ADD_INST_EXT_ENTRY_POINT(vkGetMTLBufferMVK, MVK_MOLTENVK); + ADD_INST_EXT_ENTRY_POINT(vkUseIOSurfaceMVK, MVK_MOLTENVK); + ADD_INST_EXT_ENTRY_POINT(vkGetIOSurfaceMVK, MVK_MOLTENVK); + ADD_INST_EXT_ENTRY_POINT(vkGetMTLCommandQueueMVK, MVK_MOLTENVK); +#pragma clang diagnostic pop + + // Device functions. ADD_DVC_ENTRY_POINT(vkGetDeviceProcAddr); ADD_DVC_ENTRY_POINT(vkDestroyDevice); ADD_DVC_ENTRY_POINT(vkGetDeviceQueue); @@ -660,51 +717,12 @@ ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkQueueSubmit2, KHR, KHR_SYNCHRONIZATION_2); ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkSetPrivateData, EXT, EXT_PRIVATE_DATA); - // Instance extension functions: - ADD_INST_EXT_ENTRY_POINT(vkDestroySurfaceKHR, KHR_SURFACE); - ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceSurfaceSupportKHR, KHR_SURFACE); - ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR, KHR_SURFACE); - ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceSurfaceFormatsKHR, KHR_SURFACE); - ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceSurfacePresentModesKHR, KHR_SURFACE); - ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceSurfaceCapabilities2KHR, KHR_GET_SURFACE_CAPABILITIES_2); - ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceSurfaceFormats2KHR, KHR_GET_SURFACE_CAPABILITIES_2); - ADD_INST_EXT_ENTRY_POINT(vkCreateDebugReportCallbackEXT, EXT_DEBUG_REPORT); - ADD_INST_EXT_ENTRY_POINT(vkDestroyDebugReportCallbackEXT, EXT_DEBUG_REPORT); - ADD_INST_EXT_ENTRY_POINT(vkDebugReportMessageEXT, EXT_DEBUG_REPORT); - ADD_INST_EXT_ENTRY_POINT(vkSetDebugUtilsObjectNameEXT, EXT_DEBUG_UTILS); - ADD_INST_EXT_ENTRY_POINT(vkSetDebugUtilsObjectTagEXT, EXT_DEBUG_UTILS); - ADD_INST_EXT_ENTRY_POINT(vkQueueBeginDebugUtilsLabelEXT, EXT_DEBUG_UTILS); - ADD_INST_EXT_ENTRY_POINT(vkQueueEndDebugUtilsLabelEXT, EXT_DEBUG_UTILS); - ADD_INST_EXT_ENTRY_POINT(vkQueueInsertDebugUtilsLabelEXT, EXT_DEBUG_UTILS); - ADD_INST_EXT_ENTRY_POINT(vkCmdBeginDebugUtilsLabelEXT, EXT_DEBUG_UTILS); - ADD_INST_EXT_ENTRY_POINT(vkCmdEndDebugUtilsLabelEXT, EXT_DEBUG_UTILS); - ADD_INST_EXT_ENTRY_POINT(vkCmdInsertDebugUtilsLabelEXT, EXT_DEBUG_UTILS); - 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); -#endif -#ifdef VK_USE_PLATFORM_MACOS_MVK - ADD_INST_EXT_ENTRY_POINT(vkCreateMacOSSurfaceMVK, MVK_MACOS_SURFACE); -#endif - - ADD_INST_EXT_ENTRY_POINT(vkGetMoltenVKConfigurationMVK, MVK_MOLTENVK); - ADD_INST_EXT_ENTRY_POINT(vkSetMoltenVKConfigurationMVK, MVK_MOLTENVK); - ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceMetalFeaturesMVK, MVK_MOLTENVK); - ADD_INST_EXT_ENTRY_POINT(vkGetPerformanceStatisticsMVK, MVK_MOLTENVK); - ADD_INST_EXT_ENTRY_POINT(vkGetVersionStringsMVK, MVK_MOLTENVK); - ADD_INST_EXT_ENTRY_POINT(vkGetMTLDeviceMVK, MVK_MOLTENVK); - ADD_INST_EXT_ENTRY_POINT(vkSetMTLTextureMVK, MVK_MOLTENVK); - ADD_INST_EXT_ENTRY_POINT(vkGetMTLTextureMVK, MVK_MOLTENVK); - ADD_INST_EXT_ENTRY_POINT(vkGetMTLBufferMVK, MVK_MOLTENVK); - ADD_INST_EXT_ENTRY_POINT(vkUseIOSurfaceMVK, MVK_MOLTENVK); - ADD_INST_EXT_ENTRY_POINT(vkGetIOSurfaceMVK, MVK_MOLTENVK); - ADD_INST_EXT_ENTRY_POINT(vkGetMTLCommandQueueMVK, MVK_MOLTENVK); - - // Device extension functions: + // Device extension functions. + ADD_DVC_EXT_ENTRY_POINT(vkCreateDeferredOperationKHR, KHR_DEFERRED_HOST_OPERATIONS); + ADD_DVC_EXT_ENTRY_POINT(vkDeferredOperationJoinKHR, KHR_DEFERRED_HOST_OPERATIONS); + ADD_DVC_EXT_ENTRY_POINT(vkDestroyDeferredOperationKHR, KHR_DEFERRED_HOST_OPERATIONS); + ADD_DVC_EXT_ENTRY_POINT(vkGetDeferredOperationMaxConcurrencyKHR, KHR_DEFERRED_HOST_OPERATIONS); + ADD_DVC_EXT_ENTRY_POINT(vkGetDeferredOperationResultKHR, KHR_DEFERRED_HOST_OPERATIONS); ADD_DVC_EXT_ENTRY_POINT(vkMapMemory2KHR, KHR_MAP_MEMORY_2); ADD_DVC_EXT_ENTRY_POINT(vkUnmapMemory2KHR, KHR_MAP_MEMORY_2); ADD_DVC_EXT_ENTRY_POINT(vkCmdPushDescriptorSetKHR, KHR_PUSH_DESCRIPTOR); @@ -718,6 +736,8 @@ ADD_DVC_EXT2_ENTRY_POINT(vkGetDeviceGroupSurfacePresentModesKHR, KHR_SWAPCHAIN, KHR_DEVICE_GROUP); ADD_DVC_EXT2_ENTRY_POINT(vkGetPhysicalDevicePresentRectanglesKHR, KHR_SWAPCHAIN, KHR_DEVICE_GROUP); ADD_DVC_EXT2_ENTRY_POINT(vkAcquireNextImage2KHR, KHR_SWAPCHAIN, KHR_DEVICE_GROUP); + ADD_DVC_EXT_ENTRY_POINT(vkGetCalibratedTimestampsEXT, EXT_CALIBRATED_TIMESTAMPS); + ADD_DVC_EXT_ENTRY_POINT(vkGetPhysicalDeviceCalibrateableTimeDomainsEXT, EXT_CALIBRATED_TIMESTAMPS); ADD_DVC_EXT_ENTRY_POINT(vkDebugMarkerSetObjectTagEXT, EXT_DEBUG_MARKER); ADD_DVC_EXT_ENTRY_POINT(vkDebugMarkerSetObjectNameEXT, EXT_DEBUG_MARKER); ADD_DVC_EXT_ENTRY_POINT(vkCmdDebugMarkerBeginEXT, EXT_DEBUG_MARKER); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h index caffd5c24..0cd3ccd60 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h @@ -63,6 +63,7 @@ class MVKPipelineLayout : public MVKVulkanAPIDeviceObject { /** Updates a descriptor set in a command encoder. */ void pushDescriptorSet(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKArrayRef descriptorWrites, uint32_t set); @@ -164,6 +165,9 @@ class MVKPipeline : public MVKVulkanAPIDeviceObject { mvkIsAnyFlagEnabled(_flags, VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT)); } + /** Returns whether the shader for the stage uses physical storage buffer addresses. */ + virtual bool usesPhysicalStorageBufferAddressesCapability(MVKShaderStage stage) = 0; + /** Constructs an instance for the device. layout, and parent (which may be NULL). */ MVKPipeline(MVKDevice* device, MVKPipelineCache* pipelineCache, MVKPipelineLayout* layout, VkPipelineCreateFlags flags, MVKPipeline* parent); @@ -204,14 +208,16 @@ struct MVKTranslatedVertexBinding { /** Describes a vertex buffer binding whose divisor is zero. */ typedef std::pair MVKZeroDivisorVertexBinding; -typedef MVKSmallVector MVKPiplineStages; +static constexpr uint32_t kMVKNumGraphicsShaderStages = kMVKShaderStageCompute; + +typedef MVKSmallVector MVKPiplineStages; struct MVKStagedMTLArgumentEncoders { - MVKMTLArgumentEncoder stages[4] = {}; + MVKMTLArgumentEncoder stages[kMVKNumGraphicsShaderStages] = {}; }; struct MVKStagedDescriptorBindingUse { - MVKBitArray stages[4] = {}; + MVKBitArray stages[kMVKNumGraphicsShaderStages] = {}; }; /** Represents an Vulkan graphics pipeline. */ @@ -229,7 +235,10 @@ class MVKGraphicsPipeline : public MVKPipeline { bool supportsDynamicState(VkDynamicState state); /** Returns whether this pipeline has tessellation shaders. */ - bool isTessellationPipeline() { return _pTessCtlSS && _pTessEvalSS && _tessInfo.patchControlPoints > 0; } + bool isTessellationPipeline() { return _tessInfo.patchControlPoints > 0; } + + /** Returns whether this pipeline has geometry shaders. */ + bool isGeometryPipeline() { return _isGeometryPipeline; } /** Returns the number of input tessellation patch control points. */ uint32_t getInputControlPointCount() { return _tessInfo.patchControlPoints; } @@ -247,13 +256,13 @@ class MVKGraphicsPipeline : public MVKPipeline { uint32_t getTessCtlLevelBufferIndex() { return _tessCtlLevelBufferIndex; } /** Returns the MTLComputePipelineState object for the vertex stage of a tessellated draw with no indices. */ - id getTessVertexStageState(); + id getTessVertexStageState() { return _mtlTessVertexStageState; } /** Returns the MTLComputePipelineState object for the vertex stage of a tessellated draw with 16-bit indices. */ - id getTessVertexStageIndex16State(); + id getTessVertexStageIndex16State() { return _mtlTessVertexStageIndex16State; } /** Returns the MTLComputePipelineState object for the vertex stage of a tessellated draw with 32-bit indices. */ - id getTessVertexStageIndex32State(); + id getTessVertexStageIndex32State() { return _mtlTessVertexStageIndex32State; } /** Returns the MTLComputePipelineState object for the tessellation control stage of a tessellated draw. */ id getTessControlStageState() { return _mtlTessControlStageState; } @@ -270,6 +279,14 @@ class MVKGraphicsPipeline : public MVKPipeline { /** Returns whether this pipeline has custom sample positions enabled. */ bool isUsingCustomSamplePositions() { return _isUsingCustomSamplePositions; } + /** Returns the current draw info buffer binding for the mesh shader. */ + uint32_t getDrawInfoBufferIndex() { return _meshDrawInfoBufferIndex; } + + /** Returns the Vulkan primitive topology. */ + VkPrimitiveTopology getVkPrimitiveTopology() { return _vkPrimitiveTopology; } + + bool usesPhysicalStorageBufferAddressesCapability(MVKShaderStage stage) override; + /** * Returns whether the MTLBuffer vertex shader buffer index is valid for a stage of this pipeline. * It is if it is a descriptor binding within the descriptor binding range, @@ -308,28 +325,43 @@ class MVKGraphicsPipeline : public MVKPipeline { typedef MVKSmallVector SPIRVShaderInputs; id getOrCompilePipeline(MTLRenderPipelineDescriptor* plDesc, id& plState); +#if MVK_XCODE_14 + id getOrCompilePipeline(MTLMeshRenderPipelineDescriptor* plDesc, id& plState); +#endif id getOrCompilePipeline(MTLComputePipelineDescriptor* plDesc, id& plState, const char* compilerType); + bool compileTessVertexStageState(MTLComputePipelineDescriptor* vtxPLDesc, MVKMTLFunction* pVtxFunctions, VkPipelineCreationFeedback* pVertexFB); + bool compileTessControlStageState(MTLComputePipelineDescriptor* tcPLDesc, VkPipelineCreationFeedback* pTessCtlFB); void initCustomSamplePositions(const VkGraphicsPipelineCreateInfo* pCreateInfo); - void initMTLRenderPipelineState(const VkGraphicsPipelineCreateInfo* pCreateInfo, const SPIRVTessReflectionData& reflectData); + void initMTLRenderPipelineState(const VkGraphicsPipelineCreateInfo* pCreateInfo, const SPIRVTessReflectionData& reflectData, VkPipelineCreationFeedback* pPipelineFB, const VkPipelineShaderStageCreateInfo* pVertexSS, VkPipelineCreationFeedback* pVertexFB, const VkPipelineShaderStageCreateInfo* pTessCtlSS, VkPipelineCreationFeedback* pTessCtlFB, const VkPipelineShaderStageCreateInfo* pTessEvalSS, VkPipelineCreationFeedback* pTessEvalFB, const VkPipelineShaderStageCreateInfo* pGeometrySS, VkPipelineCreationFeedback* pGeometryFB, const VkPipelineShaderStageCreateInfo* pFragmentSS, VkPipelineCreationFeedback* pFragmentFB); void initShaderConversionConfig(SPIRVToMSLConversionConfiguration& shaderConfig, const VkGraphicsPipelineCreateInfo* pCreateInfo, const SPIRVTessReflectionData& reflectData); void initReservedVertexAttributeBufferCount(const VkGraphicsPipelineCreateInfo* pCreateInfo); void addVertexInputToShaderConversionConfig(SPIRVToMSLConversionConfiguration& shaderConfig, const VkGraphicsPipelineCreateInfo* pCreateInfo); void addNextStageInputToShaderConversionConfig(SPIRVToMSLConversionConfiguration& shaderConfig, SPIRVShaderInputs& inputs); void addPrevStageOutputToShaderConversionConfig(SPIRVToMSLConversionConfiguration& shaderConfig, SPIRVShaderOutputs& outputs); - MTLRenderPipelineDescriptor* newMTLRenderPipelineDescriptor(const VkGraphicsPipelineCreateInfo* pCreateInfo, const SPIRVTessReflectionData& reflectData); - MTLComputePipelineDescriptor* newMTLTessVertexStageDescriptor(const VkGraphicsPipelineCreateInfo* pCreateInfo, const SPIRVTessReflectionData& reflectData, SPIRVToMSLConversionConfiguration& shaderConfig); - MTLComputePipelineDescriptor* newMTLTessControlStageDescriptor(const VkGraphicsPipelineCreateInfo* pCreateInfo, const SPIRVTessReflectionData& reflectData, SPIRVToMSLConversionConfiguration& shaderConfig); - MTLRenderPipelineDescriptor* newMTLTessRasterStageDescriptor(const VkGraphicsPipelineCreateInfo* pCreateInfo, const SPIRVTessReflectionData& reflectData, SPIRVToMSLConversionConfiguration& shaderConfig); - bool addVertexShaderToPipeline(MTLRenderPipelineDescriptor* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo, SPIRVToMSLConversionConfiguration& shaderConfig); - bool addVertexShaderToPipeline(MTLComputePipelineDescriptor* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo, SPIRVToMSLConversionConfiguration& shaderConfig, SPIRVShaderInputs& nextInputs); - bool addTessCtlShaderToPipeline(MTLComputePipelineDescriptor* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo, SPIRVToMSLConversionConfiguration& shaderConfig, SPIRVShaderOutputs& prevOutput, SPIRVShaderInputs& nextInputs); - bool addTessEvalShaderToPipeline(MTLRenderPipelineDescriptor* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo, SPIRVToMSLConversionConfiguration& shaderConfig, SPIRVShaderOutputs& prevOutput); - bool addFragmentShaderToPipeline(MTLRenderPipelineDescriptor* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo, SPIRVToMSLConversionConfiguration& shaderConfig, SPIRVShaderOutputs& prevOutput); + MTLRenderPipelineDescriptor* newMTLRenderPipelineDescriptor(const VkGraphicsPipelineCreateInfo* pCreateInfo, const SPIRVTessReflectionData& reflectData, const VkPipelineShaderStageCreateInfo* pVertexSS, VkPipelineCreationFeedback* pVertexFB, const VkPipelineShaderStageCreateInfo* pFragmentSS, VkPipelineCreationFeedback* pFragmentFB); +#if MVK_XCODE_14 + MTLMeshRenderPipelineDescriptor* newMTLMeshRenderPipelineDescriptor(const VkGraphicsPipelineCreateInfo* pCreateInfo, const SPIRVTessReflectionData& reflectData, const VkPipelineShaderStageCreateInfo* pVertexSS, VkPipelineCreationFeedback* pVertexFB, const VkPipelineShaderStageCreateInfo* pGeometrySS, VkPipelineCreationFeedback* pGeometryFB, const VkPipelineShaderStageCreateInfo* pFragmentSS, VkPipelineCreationFeedback* pFragmentFB); +#endif + MTLComputePipelineDescriptor* newMTLTessVertexStageDescriptor(const VkGraphicsPipelineCreateInfo* pCreateInfo, const SPIRVTessReflectionData& reflectData, SPIRVToMSLConversionConfiguration& shaderConfig, const VkPipelineShaderStageCreateInfo* pVertexSS, VkPipelineCreationFeedback* pVertexFB, const VkPipelineShaderStageCreateInfo* pTessCtlSS, MVKMTLFunction* pVtxFunctions); + MTLComputePipelineDescriptor* newMTLTessControlStageDescriptor(const VkGraphicsPipelineCreateInfo* pCreateInfo, const SPIRVTessReflectionData& reflectData, SPIRVToMSLConversionConfiguration& shaderConfig, const VkPipelineShaderStageCreateInfo* pTessCtlSS, VkPipelineCreationFeedback* pTessCtlFB, const VkPipelineShaderStageCreateInfo* pVertexSS, const VkPipelineShaderStageCreateInfo* pTessEvalSS); + MTLRenderPipelineDescriptor* newMTLTessRasterStageDescriptor(const VkGraphicsPipelineCreateInfo* pCreateInfo, const SPIRVTessReflectionData& reflectData, SPIRVToMSLConversionConfiguration& shaderConfig, const VkPipelineShaderStageCreateInfo* pTessEvalSS, VkPipelineCreationFeedback* pTessEvalFB, const VkPipelineShaderStageCreateInfo* pFragmentSS, VkPipelineCreationFeedback* pFragmentFB, const VkPipelineShaderStageCreateInfo* pTessCtlSS); + bool addVertexShaderToPipeline(MTLRenderPipelineDescriptor* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo, SPIRVToMSLConversionConfiguration& shaderConfig, const VkPipelineShaderStageCreateInfo* pVertexSS, VkPipelineCreationFeedback* pVertexFB, const VkPipelineShaderStageCreateInfo*& pFragmentSS); + bool addVertexShaderToPipeline(MTLComputePipelineDescriptor* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo, SPIRVToMSLConversionConfiguration& shaderConfig, SPIRVShaderInputs& nextInputs, const VkPipelineShaderStageCreateInfo* pVertexSS, VkPipelineCreationFeedback* pVertexFB, MVKMTLFunction* pVtxFunctions); + bool addTessCtlShaderToPipeline(MTLComputePipelineDescriptor* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo, SPIRVToMSLConversionConfiguration& shaderConfig, SPIRVShaderOutputs& prevOutput, SPIRVShaderInputs& nextInputs, const VkPipelineShaderStageCreateInfo* pTessCtlSS, VkPipelineCreationFeedback* pTessCtlFB); + bool addTessEvalShaderToPipeline(MTLRenderPipelineDescriptor* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo, SPIRVToMSLConversionConfiguration& shaderConfig, SPIRVShaderOutputs& prevOutput, const VkPipelineShaderStageCreateInfo* pTessEvalSS, VkPipelineCreationFeedback* pTessEvalFB, const VkPipelineShaderStageCreateInfo*& pFragmentSS); +#if MVK_XCODE_14 + bool addPreRasterShadersToPipeline(MTLMeshRenderPipelineDescriptor* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo, SPIRVToMSLConversionConfiguration& shaderConfig, const VkPipelineShaderStageCreateInfo* pVertexSS, VkPipelineCreationFeedback* pVertexFB, const VkPipelineShaderStageCreateInfo* pGeometrySS, VkPipelineCreationFeedback* pGeometryFB); + bool addVertexShaderToPipeline(MTLMeshRenderPipelineDescriptor* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo, SPIRVToMSLConversionConfiguration& shaderConfig, const VkPipelineShaderStageCreateInfo* pVertexSS, VkPipelineCreationFeedback* pVertexFB); + bool addGeometryShaderToPipeline(MTLMeshRenderPipelineDescriptor* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo, SPIRVToMSLConversionConfiguration& shaderConfig, const VkPipelineShaderStageCreateInfo* pGeometrySS, VkPipelineCreationFeedback* pGeometryFB, SPIRVShaderOutputs &vertexOutputs); +#endif + template + bool addFragmentShaderToPipeline(T* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo, SPIRVToMSLConversionConfiguration& shaderConfig, SPIRVShaderOutputs& prevOutput, const VkPipelineShaderStageCreateInfo* pFragmentSS, VkPipelineCreationFeedback* pFragmentFB); template bool addVertexInputToPipeline(T* inputDesc, const VkPipelineVertexInputStateCreateInfo* pVI, const SPIRVToMSLConversionConfiguration& shaderConfig); void adjustVertexInputForMultiview(MTLVertexDescriptor* inputDesc, const VkPipelineVertexInputStateCreateInfo* pVI, uint32_t viewCount, uint32_t oldViewCount = 1); void addTessellationToPipeline(MTLRenderPipelineDescriptor* plDesc, const SPIRVTessReflectionData& reflectData, const VkPipelineTessellationStateCreateInfo* pTS); - void addFragmentOutputToPipeline(MTLRenderPipelineDescriptor* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo); + template + void addFragmentOutputToPipeline(T* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo); bool isRenderingPoints(const VkGraphicsPipelineCreateInfo* pCreateInfo); bool isRasterizationDisabled(const VkGraphicsPipelineCreateInfo* pCreateInfo); bool verifyImplicitBuffer(bool needsBuffer, MVKShaderImplicitRezBinding& index, MVKShaderStage stage, const char* name); @@ -337,48 +369,46 @@ class MVKGraphicsPipeline : public MVKPipeline { uint32_t getImplicitBufferIndex(MVKShaderStage stage, uint32_t bufferIndexOffset); MVKMTLFunction getMTLFunction(SPIRVToMSLConversionConfiguration& shaderConfig, const VkPipelineShaderStageCreateInfo* pShaderStage, + VkPipelineCreationFeedback* pStageFB, const char* pStageName); - - const VkPipelineShaderStageCreateInfo* _pVertexSS = nullptr; - const VkPipelineShaderStageCreateInfo* _pTessCtlSS = nullptr; - const VkPipelineShaderStageCreateInfo* _pTessEvalSS = nullptr; - const VkPipelineShaderStageCreateInfo* _pFragmentSS = nullptr; + void markIfUsingPhysicalStorageBufferAddressesCapability(SPIRVToMSLConversionResultInfo& resultsInfo, + MVKShaderStage stage); VkPipelineTessellationStateCreateInfo _tessInfo; VkPipelineRasterizationStateCreateInfo _rasterInfo; VkPipelineDepthStencilStateCreateInfo _depthStencilInfo; - MVKSmallVector _viewports; - MVKSmallVector _scissors; + MVKSmallVector _viewports; + MVKSmallVector _scissors; MVKSmallVector _dynamicState; MVKSmallVector _customSamplePositions; MVKSmallVector _translatedVertexBindings; MVKSmallVector _zeroDivisorVertexBindings; MVKSmallVector _mtlArgumentEncoders; MVKSmallVector _descriptorBindingUse; - - MTLComputePipelineDescriptor* _mtlTessVertexStageDesc = nil; - id _mtlTessVertexFunctions[3] = {nil, nil, nil}; + MVKSmallVector _stagesUsingPhysicalStorageBufferAddressesCapability; + std::unordered_map> _multiviewMTLPipelineStates; id _mtlTessVertexStageState = nil; id _mtlTessVertexStageIndex16State = nil; id _mtlTessVertexStageIndex32State = nil; id _mtlTessControlStageState = nil; id _mtlPipelineState = nil; - std::unordered_map> _multiviewMTLPipelineStates; + + float _blendConstants[4] = { 0.0, 0.0, 0.0, 1.0 }; MTLCullMode _mtlCullMode; MTLWinding _mtlFrontWinding; MTLTriangleFillMode _mtlFillMode; MTLDepthClipMode _mtlDepthClipMode; - MTLPrimitiveType _mtlPrimitiveType; - - float _blendConstants[4] = { 0.0, 0.0, 0.0, 1.0 }; - uint32_t _outputControlPointCount; + MTLPrimitiveType _mtlPrimitiveType; MVKShaderImplicitRezBinding _reservedVertexAttributeBufferCount; MVKShaderImplicitRezBinding _viewRangeBufferIndex; MVKShaderImplicitRezBinding _outputBufferIndex; + VkPrimitiveTopology _vkPrimitiveTopology; + uint32_t _outputControlPointCount; uint32_t _tessCtlPatchOutputBufferIndex = 0; uint32_t _tessCtlLevelBufferIndex = 0; + uint32_t _meshDrawInfoBufferIndex = 20; bool _needsVertexSwizzleBuffer = false; bool _needsVertexBufferSizeBuffer = false; @@ -400,8 +430,8 @@ class MVKGraphicsPipeline : public MVKPipeline { bool _needsFragmentViewRangeBuffer = false; bool _isRasterizing = false; bool _isRasterizingColor = false; - bool _isRasterizingDepthStencil = false; bool _isUsingCustomSamplePositions = false; + bool _isGeometryPipeline = false; }; @@ -425,6 +455,8 @@ class MVKComputePipeline : public MVKPipeline { /** Returns the array of descriptor binding use for the descriptor set. */ MVKBitArray& getDescriptorBindingUse(uint32_t descSetIndex, MVKShaderStage stage) override { return _descriptorBindingUse[descSetIndex]; } + bool usesPhysicalStorageBufferAddressesCapability(MVKShaderStage stage) override; + /** Constructs an instance for the device and parent (which may be NULL). */ MVKComputePipeline(MVKDevice* device, MVKPipelineCache* pipelineCache, @@ -434,7 +466,8 @@ class MVKComputePipeline : public MVKPipeline { ~MVKComputePipeline() override; protected: - MVKMTLFunction getMTLFunction(const VkComputePipelineCreateInfo* pCreateInfo); + MVKMTLFunction getMTLFunction(const VkComputePipelineCreateInfo* pCreateInfo, + VkPipelineCreationFeedback* pStageFB); uint32_t getImplicitBufferIndex(uint32_t bufferIndexOffset); id _mtlPipelineState; @@ -446,6 +479,7 @@ class MVKComputePipeline : public MVKPipeline { bool _needsDynamicOffsetBuffer = false; bool _needsDispatchBaseBuffer = false; bool _allowsDispatchBase = false; + bool _usesPhysicalStorageBufferAddressesCapability = false; }; @@ -477,6 +511,7 @@ class MVKPipelineCache : public MVKVulkanAPIDeviceObject { MVKShaderLibrary* getShaderLibrary(SPIRVToMSLConversionConfiguration* pContext, MVKShaderModule* shaderModule, MVKPipeline* pipeline, + VkPipelineCreationFeedback* pShaderFeedback = nullptr, uint64_t startTime = 0); /** Merges the contents of the specified number of pipeline caches into this cache. */ @@ -497,6 +532,7 @@ class MVKPipelineCache : public MVKVulkanAPIDeviceObject { MVKShaderLibrary* getShaderLibraryImpl(SPIRVToMSLConversionConfiguration* pContext, MVKShaderModule* shaderModule, MVKPipeline* pipeline, + VkPipelineCreationFeedback* pShaderFeedback, uint64_t startTime); VkResult writeDataImpl(size_t* pDataSize, void* pData); VkResult mergePipelineCachesImpl(uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches); @@ -528,7 +564,9 @@ class MVKRenderPipelineCompiler : public MVKMetalCompiler { * nanoseconds, an error will be generated and logged, and nil will be returned. */ id newMTLRenderPipelineState(MTLRenderPipelineDescriptor* mtlRPLDesc); - +#if MVK_XCODE_14 + id newMTLRenderPipelineState(MTLMeshRenderPipelineDescriptor* mtlRPLDesc); +#endif #pragma mark Construction diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm index 652699ac2..f26dab6f2 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm @@ -64,11 +64,12 @@ // A null cmdEncoder can be passed to perform a validation pass void MVKPipelineLayout::pushDescriptorSet(MVKCommandEncoder* cmdEncoder, + VkPipelineBindPoint pipelineBindPoint, MVKArrayRef descriptorWrites, uint32_t set) { if (!cmdEncoder) { clearConfigurationResult(); } MVKDescriptorSetLayout* dsl = _descriptorSetLayouts[set]; - dsl->pushDescriptorSet(cmdEncoder, descriptorWrites, _dslMTLResourceIndexOffsets[set]); + dsl->pushDescriptorSet(cmdEncoder, pipelineBindPoint, descriptorWrites, _dslMTLResourceIndexOffsets[set]); if (!cmdEncoder) { setConfigurationResult(dsl->getConfigurationResult()); } } @@ -299,7 +300,7 @@ cmdEncoder->_depthBiasState.setDepthBias(_rasterInfo); cmdEncoder->_viewportState.setViewports(_viewports.contents(), 0, false); cmdEncoder->_scissorState.setScissors(_scissors.contents(), 0, false); - cmdEncoder->_mtlPrimitiveType = _mtlPrimitiveType; + cmdEncoder->_mtlPrimitiveType = mvkMTLPrimitiveTypeFromVkPrimitiveTopology(_vkPrimitiveTopology); [mtlCmdEnc setCullMode: _mtlCullMode]; [mtlCmdEnc setFrontFacingWinding: _mtlFrontWinding]; @@ -336,48 +337,63 @@ static const char vtxCompilerType[] = "Vertex stage pipeline for tessellation"; -id MVKGraphicsPipeline::getTessVertexStageState() { - MTLComputePipelineDescriptor* plDesc = [_mtlTessVertexStageDesc copy]; // temp retain a copy to be thread-safe. - plDesc.computeFunction = _mtlTessVertexFunctions[0]; - id plState = getOrCompilePipeline(plDesc, _mtlTessVertexStageState, vtxCompilerType); - [plDesc release]; // temp release - return plState; -} +bool MVKGraphicsPipeline::compileTessVertexStageState(MTLComputePipelineDescriptor* vtxPLDesc, + MVKMTLFunction* pVtxFunctions, + VkPipelineCreationFeedback* pVertexFB) { + uint64_t startTime = 0; + if (pVertexFB) { + startTime = mvkGetTimestamp(); + } + vtxPLDesc.computeFunction = pVtxFunctions[0].getMTLFunction(); + bool res = !!getOrCompilePipeline(vtxPLDesc, _mtlTessVertexStageState, vtxCompilerType); -id MVKGraphicsPipeline::getTessVertexStageIndex16State() { - MTLComputePipelineDescriptor* plDesc = [_mtlTessVertexStageDesc copy]; // temp retain a copy to be thread-safe. - plDesc.computeFunction = _mtlTessVertexFunctions[1]; - plDesc.stageInputDescriptor.indexType = MTLIndexTypeUInt16; + vtxPLDesc.computeFunction = pVtxFunctions[1].getMTLFunction(); + vtxPLDesc.stageInputDescriptor.indexType = MTLIndexTypeUInt16; for (uint32_t i = 0; i < 31; i++) { - MTLBufferLayoutDescriptor* blDesc = plDesc.stageInputDescriptor.layouts[i]; + MTLBufferLayoutDescriptor* blDesc = vtxPLDesc.stageInputDescriptor.layouts[i]; if (blDesc.stepFunction == MTLStepFunctionThreadPositionInGridX) { blDesc.stepFunction = MTLStepFunctionThreadPositionInGridXIndexed; } } - id plState = getOrCompilePipeline(plDesc, _mtlTessVertexStageIndex16State, vtxCompilerType); - [plDesc release]; // temp release - return plState; + res |= !!getOrCompilePipeline(vtxPLDesc, _mtlTessVertexStageIndex16State, vtxCompilerType); + + vtxPLDesc.computeFunction = pVtxFunctions[2].getMTLFunction(); + vtxPLDesc.stageInputDescriptor.indexType = MTLIndexTypeUInt32; + res |= !!getOrCompilePipeline(vtxPLDesc, _mtlTessVertexStageIndex32State, vtxCompilerType); + + if (pVertexFB) { + if (!res) { + // Compilation of the shader will have enabled the flag, so I need to turn it off. + mvkDisableFlags(pVertexFB->flags, VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT); + } + pVertexFB->duration += mvkGetElapsedNanoseconds(startTime); + } + return res; } -id MVKGraphicsPipeline::getTessVertexStageIndex32State() { - MTLComputePipelineDescriptor* plDesc = [_mtlTessVertexStageDesc copy]; // temp retain a copy to be thread-safe. - plDesc.computeFunction = _mtlTessVertexFunctions[2]; - plDesc.stageInputDescriptor.indexType = MTLIndexTypeUInt32; - for (uint32_t i = 0; i < 31; i++) { - MTLBufferLayoutDescriptor* blDesc = plDesc.stageInputDescriptor.layouts[i]; - if (blDesc.stepFunction == MTLStepFunctionThreadPositionInGridX) { - blDesc.stepFunction = MTLStepFunctionThreadPositionInGridXIndexed; - } - } - id plState = getOrCompilePipeline(plDesc, _mtlTessVertexStageIndex32State, vtxCompilerType); - [plDesc release]; // temp release - return plState; +bool MVKGraphicsPipeline::compileTessControlStageState(MTLComputePipelineDescriptor* tcPLDesc, + VkPipelineCreationFeedback* pTessCtlFB) { + uint64_t startTime = 0; + if (pTessCtlFB) { + startTime = mvkGetTimestamp(); + } + bool res = !!getOrCompilePipeline(tcPLDesc, _mtlTessControlStageState, "Tessellation control"); + if (pTessCtlFB) { + if (!res) { + mvkDisableFlags(pTessCtlFB->flags, VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT); + } + pTessCtlFB->duration += mvkGetElapsedNanoseconds(startTime); + } + return res; } #pragma mark Construction -// Extracts and returns a VkPipelineRenderingCreateInfo from the renderPass or pNext chain of pCreateInfo, or returns null if not found +// Extracts and returns a VkPipelineRenderingCreateInfo from the renderPass or pNext +// chain of pCreateInfo, or returns an empty struct if neither of those are found. +// Although the Vulkan spec is vague and unclear, there are CTS that set both renderPass +// and VkPipelineRenderingCreateInfo to null in VkGraphicsPipelineCreateInfo. static const VkPipelineRenderingCreateInfo* getRenderingCreateInfo(const VkGraphicsPipelineCreateInfo* pCreateInfo) { if (pCreateInfo->renderPass) { return ((MVKRenderPass*)pCreateInfo->renderPass)->getSubpass(pCreateInfo->subpass)->getPipelineRenderingCreateInfo(); @@ -388,7 +404,8 @@ default: break; } } - return nullptr; + static VkPipelineRenderingCreateInfo emptyRendInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO }; + return &emptyRendInfo; } MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device, @@ -401,28 +418,92 @@ const VkPipelineRenderingCreateInfo* pRendInfo = getRenderingCreateInfo(pCreateInfo); _isRasterizing = !isRasterizationDisabled(pCreateInfo); _isRasterizingColor = _isRasterizing && mvkHasColorAttachments(pRendInfo); - _isRasterizingDepthStencil = _isRasterizing && mvkGetDepthStencilFormat(pRendInfo) != VK_FORMAT_UNDEFINED; - // Get the tessellation shaders, if present. Do this now, because we need to extract + const VkPipelineCreationFeedbackCreateInfo* pFeedbackInfo = nullptr; + for (const auto* next = (VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) { + switch (next->sType) { + case VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO: + pFeedbackInfo = (VkPipelineCreationFeedbackCreateInfo*)next; + break; + default: + break; + } + } + + // Initialize feedback. The VALID bit must be initialized, either set or cleared. + // We'll set the VALID bits later, after successful compilation. + VkPipelineCreationFeedback* pPipelineFB = nullptr; + if (pFeedbackInfo) { + pPipelineFB = pFeedbackInfo->pPipelineCreationFeedback; + // n.b. Do *NOT* use mvkClear(). That would also clear the sType and pNext fields. + pPipelineFB->flags = 0; + pPipelineFB->duration = 0; + for (uint32_t i = 0; i < pFeedbackInfo->pipelineStageCreationFeedbackCount; ++i) { + pFeedbackInfo->pPipelineStageCreationFeedbacks[i].flags = 0; + pFeedbackInfo->pPipelineStageCreationFeedbacks[i].duration = 0; + } + } + + // Get the shader stages. Do this now, because we need to extract // reflection data from them that informs everything else. + const VkPipelineShaderStageCreateInfo* pVertexSS = nullptr; + const VkPipelineShaderStageCreateInfo* pTessCtlSS = nullptr; + const VkPipelineShaderStageCreateInfo* pTessEvalSS = nullptr; + const VkPipelineShaderStageCreateInfo* pFragmentSS = nullptr; + const VkPipelineShaderStageCreateInfo* pGeometrySS = nullptr; + VkPipelineCreationFeedback* pVertexFB = nullptr; + VkPipelineCreationFeedback* pTessCtlFB = nullptr; + VkPipelineCreationFeedback* pTessEvalFB = nullptr; + VkPipelineCreationFeedback* pFragmentFB = nullptr; + VkPipelineCreationFeedback* pGeometryFB = nullptr; for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) { const auto* pSS = &pCreateInfo->pStages[i]; - if (pSS->stage == VK_SHADER_STAGE_VERTEX_BIT) { - _pVertexSS = pSS; - } else if (pSS->stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) { - _pTessCtlSS = pSS; - } else if (pSS->stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) { - _pTessEvalSS = pSS; - } else if (pSS->stage == VK_SHADER_STAGE_FRAGMENT_BIT) { - _pFragmentSS = pSS; + switch (pSS->stage) { + case VK_SHADER_STAGE_VERTEX_BIT: + pVertexSS = pSS; + if (pFeedbackInfo && pFeedbackInfo->pPipelineStageCreationFeedbacks) { + pVertexFB = &pFeedbackInfo->pPipelineStageCreationFeedbacks[i]; + } + break; + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: + pTessCtlSS = pSS; + if (pFeedbackInfo && pFeedbackInfo->pPipelineStageCreationFeedbacks) { + pTessCtlFB = &pFeedbackInfo->pPipelineStageCreationFeedbacks[i]; + } + break; + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + pTessEvalSS = pSS; + if (pFeedbackInfo && pFeedbackInfo->pPipelineStageCreationFeedbacks) { + pTessEvalFB = &pFeedbackInfo->pPipelineStageCreationFeedbacks[i]; + } + break; + case VK_SHADER_STAGE_FRAGMENT_BIT: + pFragmentSS = pSS; + if (pFeedbackInfo && pFeedbackInfo->pPipelineStageCreationFeedbacks) { + pFragmentFB = &pFeedbackInfo->pPipelineStageCreationFeedbacks[i]; + } + break; + case VK_SHADER_STAGE_GEOMETRY_BIT: +#if MVK_XCODE_14 + if (getDevice()->getPhysicalDevice()->mslVersionIsAtLeast(MTLLanguageVersion3_0)) { + pGeometrySS = pSS; + _isGeometryPipeline = true; + if (pFeedbackInfo && pFeedbackInfo->pPipelineStageCreationFeedbacks) { + pGeometryFB = &pFeedbackInfo->pPipelineStageCreationFeedbacks[i]; + } + } +#endif + break; + default: + break; } } // Get the tessellation parameters from the shaders. SPIRVTessReflectionData reflectData; std::string reflectErrorLog; - if (_pTessCtlSS && _pTessEvalSS) { - if (!getTessReflectionData(((MVKShaderModule*)_pTessCtlSS->module)->getSPIRV(), _pTessCtlSS->pName, ((MVKShaderModule*)_pTessEvalSS->module)->getSPIRV(), _pTessEvalSS->pName, reflectData, reflectErrorLog) ) { + if (pTessCtlSS && pTessEvalSS) { + if (!getTessReflectionData(((MVKShaderModule*)pTessCtlSS->module)->getSPIRV(), pTessCtlSS->pName, ((MVKShaderModule*)pTessEvalSS->module)->getSPIRV(), pTessEvalSS->pName, reflectData, reflectErrorLog) ) { setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Failed to reflect tessellation shaders: %s", reflectErrorLog.c_str())); return; } @@ -435,10 +516,21 @@ // Tessellation - must ignore allowed bad pTessellationState pointer if not tess pipeline _outputControlPointCount = reflectData.numControlPoints; - mvkSetOrClear(&_tessInfo, (_pTessCtlSS && _pTessEvalSS) ? pCreateInfo->pTessellationState : nullptr); + mvkSetOrClear(&_tessInfo, (pTessCtlSS && pTessEvalSS) ? pCreateInfo->pTessellationState : nullptr); + + // Topology + _mtlPrimitiveType = MTLPrimitiveTypePoint; + if (pCreateInfo->pInputAssemblyState && !isRenderingPoints(pCreateInfo)) { + _mtlPrimitiveType = mvkMTLPrimitiveTypeFromVkPrimitiveTopology(pCreateInfo->pInputAssemblyState->topology); + // Explicitly fail creation with triangle fan topology. + if (pCreateInfo->pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN) { + setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "Metal does not support triangle fans.")); + return; + } + } // Render pipeline state. Do this as early as possible, to fail fast if pipeline requires a fail on cache-miss. - initMTLRenderPipelineState(pCreateInfo, reflectData); + initMTLRenderPipelineState(pCreateInfo, reflectData, pPipelineFB, pVertexSS, pVertexFB, pTessCtlSS, pTessCtlFB, pTessEvalSS, pTessEvalFB, pGeometrySS, pGeometryFB, pFragmentSS, pFragmentFB); if ( !_hasValidMTLPipelineStates ) { return; } // Track dynamic state @@ -455,15 +547,9 @@ } // Topology - _mtlPrimitiveType = MTLPrimitiveTypePoint; - if (pCreateInfo->pInputAssemblyState && !isRenderingPoints(pCreateInfo)) { - _mtlPrimitiveType = mvkMTLPrimitiveTypeFromVkPrimitiveTopology(pCreateInfo->pInputAssemblyState->topology); - // Explicitly fail creation with triangle fan topology. - if (pCreateInfo->pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN) { - setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "Metal does not support triangle fans.")); - return; - } - } + _vkPrimitiveTopology = (pCreateInfo->pInputAssemblyState && !isRenderingPoints(pCreateInfo) + ? pCreateInfo->pInputAssemblyState->topology + : VK_PRIMITIVE_TOPOLOGY_POINT_LIST); // Rasterization _mtlCullMode = MTLCullModeNone; @@ -488,8 +574,9 @@ initCustomSamplePositions(pCreateInfo); // Depth stencil content - clearing will disable depth and stencil testing - // Must ignore allowed bad pDepthStencilState pointer if rasterization disabled or no depth attachment - mvkSetOrClear(&_depthStencilInfo, _isRasterizingDepthStencil ? pCreateInfo->pDepthStencilState : nullptr); + // Must ignore allowed bad pDepthStencilState pointer if rasterization disabled or no depth or stencil attachment format + bool isRasterizingDepthStencil = _isRasterizing && (pRendInfo->depthAttachmentFormat || pRendInfo->stencilAttachmentFormat); + mvkSetOrClear(&_depthStencilInfo, isRasterizingDepthStencil ? pCreateInfo->pDepthStencilState : nullptr); // Viewports and scissors - must ignore allowed bad pViewportState pointer if rasterization is disabled auto pVPState = _isRasterizing ? pCreateInfo->pViewportState : nullptr; @@ -526,6 +613,20 @@ return plState; } +#if MVK_XCODE_14 +// Either returns an existing pipeline state or compiles a new one. +id MVKGraphicsPipeline::getOrCompilePipeline(MTLMeshRenderPipelineDescriptor* plDesc, + id& plState) { + if ( !plState ) { + MVKRenderPipelineCompiler* plc = new MVKRenderPipelineCompiler(this); + plState = plc->newMTLRenderPipelineState(plDesc); // retained + plc->destroy(); + if ( !plState ) { _hasValidMTLPipelineStates = false; } + } + return plState; +} +#endif + // Either returns an existing pipeline state or compiles a new one. id MVKGraphicsPipeline::getOrCompilePipeline(MTLComputePipelineDescriptor* plDesc, id& plState, @@ -565,20 +666,64 @@ } // Constructs the underlying Metal render pipeline. -void MVKGraphicsPipeline::initMTLRenderPipelineState(const VkGraphicsPipelineCreateInfo* pCreateInfo, const SPIRVTessReflectionData& reflectData) { +void MVKGraphicsPipeline::initMTLRenderPipelineState(const VkGraphicsPipelineCreateInfo* pCreateInfo, + const SPIRVTessReflectionData& reflectData, + VkPipelineCreationFeedback* pPipelineFB, + const VkPipelineShaderStageCreateInfo* pVertexSS, + VkPipelineCreationFeedback* pVertexFB, + const VkPipelineShaderStageCreateInfo* pTessCtlSS, + VkPipelineCreationFeedback* pTessCtlFB, + const VkPipelineShaderStageCreateInfo* pTessEvalSS, + VkPipelineCreationFeedback* pTessEvalFB, + const VkPipelineShaderStageCreateInfo* pGeometrySS, + VkPipelineCreationFeedback* pGeometryFB, + const VkPipelineShaderStageCreateInfo* pFragmentSS, + VkPipelineCreationFeedback* pFragmentFB) { _mtlTessVertexStageState = nil; _mtlTessVertexStageIndex16State = nil; _mtlTessVertexStageIndex32State = nil; _mtlTessControlStageState = nil; _mtlPipelineState = nil; - _mtlTessVertexStageDesc = nil; - for (uint32_t i = 0; i < 3; i++) { _mtlTessVertexFunctions[i] = nil; } + + uint64_t pipelineStart = 0; + if (pPipelineFB) { + pipelineStart = mvkGetTimestamp(); + } if (isUsingMetalArgumentBuffers()) { _descriptorBindingUse.resize(_descriptorSetCount); } if (isUsingPipelineStageMetalArgumentBuffers()) { _mtlArgumentEncoders.resize(_descriptorSetCount); } - if (!isTessellationPipeline()) { - MTLRenderPipelineDescriptor* plDesc = newMTLRenderPipelineDescriptor(pCreateInfo, reflectData); // temp retain + if (isTessellationPipeline()) { + // In this case, we need to create three render pipelines. But, the way Metal handles + // index buffers for compute stage-in means we have to create three pipelines for + // stage 1 (five pipelines in total). + SPIRVToMSLConversionConfiguration shaderConfig; + initShaderConversionConfig(shaderConfig, pCreateInfo, reflectData); + + MVKMTLFunction vtxFunctions[3] = {}; + MTLComputePipelineDescriptor* vtxPLDesc = newMTLTessVertexStageDescriptor(pCreateInfo, reflectData, shaderConfig, pVertexSS, pVertexFB, pTessCtlSS, vtxFunctions); // temp retained + MTLComputePipelineDescriptor* tcPLDesc = newMTLTessControlStageDescriptor(pCreateInfo, reflectData, shaderConfig, pTessCtlSS, pTessCtlFB, pVertexSS, pTessEvalSS); // temp retained + MTLRenderPipelineDescriptor* rastPLDesc = newMTLTessRasterStageDescriptor(pCreateInfo, reflectData, shaderConfig, pTessEvalSS, pTessEvalFB, pFragmentSS, pFragmentFB, pTessCtlSS); // temp retained + if (vtxPLDesc && tcPLDesc && rastPLDesc) { + if (compileTessVertexStageState(vtxPLDesc, vtxFunctions, pVertexFB)) { + if (compileTessControlStageState(tcPLDesc, pTessCtlFB)) { + getOrCompilePipeline(rastPLDesc, _mtlPipelineState); + } + } + } else { + _hasValidMTLPipelineStates = false; + } + [vtxPLDesc release]; // temp release + [tcPLDesc release]; // temp release + [rastPLDesc release]; // temp release +#if MVK_XCODE_14 + } else if (isGeometryPipeline()) { + MTLMeshRenderPipelineDescriptor* plDesc = newMTLMeshRenderPipelineDescriptor(pCreateInfo, reflectData, pVertexSS, pVertexFB, pGeometrySS, pGeometryFB, pFragmentSS, pFragmentFB); // temp retain + if (plDesc) getOrCompilePipeline(plDesc, _mtlPipelineState); + [plDesc release]; // temp release +#endif + } else { + MTLRenderPipelineDescriptor* plDesc = newMTLRenderPipelineDescriptor(pCreateInfo, reflectData, pVertexSS, pVertexFB, pFragmentSS, pFragmentFB); // temp retain if (plDesc) { const VkPipelineRenderingCreateInfo* pRendInfo = getRenderingCreateInfo(pCreateInfo); if (pRendInfo && mvkIsMultiview(pRendInfo->viewMask)) { @@ -612,32 +757,24 @@ } else { _hasValidMTLPipelineStates = false; } - } else { - // In this case, we need to create three render pipelines. But, the way Metal handles - // index buffers for compute stage-in means we have to defer creation of stage 1 until - // draw time. In the meantime, we'll create and retain a descriptor for it. - SPIRVToMSLConversionConfiguration shaderConfig; - initShaderConversionConfig(shaderConfig, pCreateInfo, reflectData); - - _mtlTessVertexStageDesc = newMTLTessVertexStageDescriptor(pCreateInfo, reflectData, shaderConfig); // retained - MTLComputePipelineDescriptor* tcPLDesc = newMTLTessControlStageDescriptor(pCreateInfo, reflectData, shaderConfig); // temp retained - MTLRenderPipelineDescriptor* rastPLDesc = newMTLTessRasterStageDescriptor(pCreateInfo, reflectData, shaderConfig); // temp retained - if (_mtlTessVertexStageDesc && tcPLDesc && rastPLDesc) { - if (getOrCompilePipeline(tcPLDesc, _mtlTessControlStageState, "Tessellation control")) { - getOrCompilePipeline(rastPLDesc, _mtlPipelineState); - } - } else { - _hasValidMTLPipelineStates = false; + } + + if (pPipelineFB) { + if ( _hasValidMTLPipelineStates ) { + mvkEnableFlags(pPipelineFB->flags, VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT); } - [tcPLDesc release]; // temp release - [rastPLDesc release]; // temp release + pPipelineFB->duration = mvkGetElapsedNanoseconds(pipelineStart); } } // Returns a retained MTLRenderPipelineDescriptor constructed from this instance, or nil if an error occurs. // It is the responsibility of the caller to release the returned descriptor. MTLRenderPipelineDescriptor* MVKGraphicsPipeline::newMTLRenderPipelineDescriptor(const VkGraphicsPipelineCreateInfo* pCreateInfo, - const SPIRVTessReflectionData& reflectData) { + const SPIRVTessReflectionData& reflectData, + const VkPipelineShaderStageCreateInfo* pVertexSS, + VkPipelineCreationFeedback* pVertexFB, + const VkPipelineShaderStageCreateInfo* pFragmentSS, + VkPipelineCreationFeedback* pFragmentFB) { SPIRVToMSLConversionConfiguration shaderConfig; initShaderConversionConfig(shaderConfig, pCreateInfo, reflectData); @@ -645,20 +782,20 @@ SPIRVShaderOutputs vtxOutputs; std::string errorLog; - if (!getShaderOutputs(((MVKShaderModule*)_pVertexSS->module)->getSPIRV(), spv::ExecutionModelVertex, _pVertexSS->pName, vtxOutputs, errorLog) ) { + if (!getShaderOutputs(((MVKShaderModule*)pVertexSS->module)->getSPIRV(), spv::ExecutionModelVertex, pVertexSS->pName, vtxOutputs, errorLog) ) { setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Failed to get vertex outputs: %s", errorLog.c_str())); return nil; } // Add shader stages. Compile vertex shader before others just in case conversion changes anything...like rasterizaion disable. - if (!addVertexShaderToPipeline(plDesc, pCreateInfo, shaderConfig)) { return nil; } + if (!addVertexShaderToPipeline(plDesc, pCreateInfo, shaderConfig, pVertexSS, pVertexFB, pFragmentSS)) { return nil; } // Vertex input // This needs to happen before compiling the fragment shader, or we'll lose information on vertex attributes. if (!addVertexInputToPipeline(plDesc.vertexDescriptor, pCreateInfo->pVertexInputState, shaderConfig)) { return nil; } // Fragment shader - only add if rasterization is enabled - if (!addFragmentShaderToPipeline(plDesc, pCreateInfo, shaderConfig, vtxOutputs)) { return nil; } + if (!addFragmentShaderToPipeline(plDesc, pCreateInfo, shaderConfig, vtxOutputs, pFragmentSS, pFragmentFB)) { return nil; } // Output addFragmentOutputToPipeline(plDesc, pCreateInfo); @@ -671,16 +808,69 @@ return plDesc; } +#if MVK_XCODE_14 +// Returns a retained MTLRenderPipelineDescriptor constructed from this instance, or nil if an error occurs. +// It is the responsibility of the caller to release the returned descriptor. +MTLMeshRenderPipelineDescriptor* MVKGraphicsPipeline::newMTLMeshRenderPipelineDescriptor(const VkGraphicsPipelineCreateInfo* pCreateInfo, + const SPIRVTessReflectionData& reflectData, + const VkPipelineShaderStageCreateInfo* pVertexSS, + VkPipelineCreationFeedback* pVertexFB, + const VkPipelineShaderStageCreateInfo* pGeometrySS, + VkPipelineCreationFeedback* pGeometryFB, + const VkPipelineShaderStageCreateInfo* pFragmentSS, + VkPipelineCreationFeedback* pFragmentFB) { + SPIRVToMSLConversionConfiguration shaderConfig; + initShaderConversionConfig(shaderConfig, pCreateInfo, reflectData); + + MTLMeshRenderPipelineDescriptor* plDesc = [MTLMeshRenderPipelineDescriptor new]; // retained + + plDesc.rasterSampleCount = mvkSampleCountFromVkSampleCountFlagBits(pCreateInfo->pMultisampleState->rasterizationSamples); + + if (!addVertexShaderToPipeline(plDesc, pCreateInfo, shaderConfig, pVertexSS, pVertexFB)) + return nullptr; + + std::string errorLog; + SPIRVShaderOutputs vertexOutputs, geometryOutputs; + if (!getShaderOutputs(((MVKShaderModule*)pVertexSS->module)->getSPIRV(), spv::ExecutionModelVertex, pVertexSS->pName, vertexOutputs, errorLog)) { + reportError(VK_ERROR_INITIALIZATION_FAILED, "Failed to get vertex outputs: %s", errorLog.c_str()); + return nullptr; + } + + if (!addGeometryShaderToPipeline(plDesc, pCreateInfo, shaderConfig, pGeometrySS, pGeometryFB, vertexOutputs)) + return nullptr; + + if (!getShaderOutputs(((MVKShaderModule*)pGeometrySS->module)->getSPIRV(), spv::ExecutionModelGeometry, pGeometrySS->pName, geometryOutputs, errorLog)) { + reportError(VK_ERROR_INITIALIZATION_FAILED, "Failed to get vertex outputs: %s", errorLog.c_str()); + return nullptr; + } + + if (!addFragmentShaderToPipeline(plDesc, pCreateInfo, shaderConfig, geometryOutputs, pFragmentSS, pFragmentFB)) { return nullptr; } + + addFragmentOutputToPipeline(plDesc, pCreateInfo); + + // Metal does not allow the name of the pipeline to be changed after it has been created, + // and we need to create the Metal pipeline immediately to provide error feedback to app. + // The best we can do at this point is set the pipeline name from the layout. + setLabelIfNotNil(plDesc, ((MVKPipelineLayout*)pCreateInfo->layout)->getDebugName()); + + return plDesc; +} +#endif + // Returns a retained MTLComputePipelineDescriptor for the vertex stage of a tessellated draw constructed from this instance, or nil if an error occurs. // It is the responsibility of the caller to release the returned descriptor. MTLComputePipelineDescriptor* MVKGraphicsPipeline::newMTLTessVertexStageDescriptor(const VkGraphicsPipelineCreateInfo* pCreateInfo, - const SPIRVTessReflectionData& reflectData, - SPIRVToMSLConversionConfiguration& shaderConfig) { + const SPIRVTessReflectionData& reflectData, + SPIRVToMSLConversionConfiguration& shaderConfig, + const VkPipelineShaderStageCreateInfo* pVertexSS, + VkPipelineCreationFeedback* pVertexFB, + const VkPipelineShaderStageCreateInfo* pTessCtlSS, + MVKMTLFunction* pVtxFunctions) { MTLComputePipelineDescriptor* plDesc = [MTLComputePipelineDescriptor new]; // retained SPIRVShaderInputs tcInputs; std::string errorLog; - if (!getShaderInputs(((MVKShaderModule*)_pTessCtlSS->module)->getSPIRV(), spv::ExecutionModelTessellationControl, _pTessCtlSS->pName, tcInputs, errorLog) ) { + if (!getShaderInputs(((MVKShaderModule*)pTessCtlSS->module)->getSPIRV(), spv::ExecutionModelTessellationControl, pTessCtlSS->pName, tcInputs, errorLog) ) { setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Failed to get tessellation control inputs: %s", errorLog.c_str())); return nil; } @@ -692,7 +882,7 @@ }), tcInputs.end()); // Add shader stages. - if (!addVertexShaderToPipeline(plDesc, pCreateInfo, shaderConfig, tcInputs)) { return nil; } + if (!addVertexShaderToPipeline(plDesc, pCreateInfo, shaderConfig, tcInputs, pVertexSS, pVertexFB, pVtxFunctions)) { return nil; } // Vertex input plDesc.stageInputDescriptor = [MTLStageInputOutputDescriptor stageInputOutputDescriptor]; @@ -812,17 +1002,21 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 // It is the responsibility of the caller to release the returned descriptor. MTLComputePipelineDescriptor* MVKGraphicsPipeline::newMTLTessControlStageDescriptor(const VkGraphicsPipelineCreateInfo* pCreateInfo, const SPIRVTessReflectionData& reflectData, - SPIRVToMSLConversionConfiguration& shaderConfig) { + SPIRVToMSLConversionConfiguration& shaderConfig, + const VkPipelineShaderStageCreateInfo* pTessCtlSS, + VkPipelineCreationFeedback* pTessCtlFB, + const VkPipelineShaderStageCreateInfo* pVertexSS, + const VkPipelineShaderStageCreateInfo* pTessEvalSS) { MTLComputePipelineDescriptor* plDesc = [MTLComputePipelineDescriptor new]; // retained SPIRVShaderOutputs vtxOutputs; SPIRVShaderInputs teInputs; std::string errorLog; - if (!getShaderOutputs(((MVKShaderModule*)_pVertexSS->module)->getSPIRV(), spv::ExecutionModelVertex, _pVertexSS->pName, vtxOutputs, errorLog) ) { + if (!getShaderOutputs(((MVKShaderModule*)pVertexSS->module)->getSPIRV(), spv::ExecutionModelVertex, pVertexSS->pName, vtxOutputs, errorLog) ) { setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Failed to get vertex outputs: %s", errorLog.c_str())); return nil; } - if (!getShaderInputs(((MVKShaderModule*)_pTessEvalSS->module)->getSPIRV(), spv::ExecutionModelTessellationEvaluation, _pTessEvalSS->pName, teInputs, errorLog) ) { + if (!getShaderInputs(((MVKShaderModule*)pTessEvalSS->module)->getSPIRV(), spv::ExecutionModelTessellationEvaluation, pTessEvalSS->pName, teInputs, errorLog) ) { setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Failed to get tessellation evaluation inputs: %s", errorLog.c_str())); return nil; } @@ -834,7 +1028,7 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 }), teInputs.end()); // Add shader stages. - if (!addTessCtlShaderToPipeline(plDesc, pCreateInfo, shaderConfig, vtxOutputs, teInputs)) { + if (!addTessCtlShaderToPipeline(plDesc, pCreateInfo, shaderConfig, vtxOutputs, teInputs, pTessCtlSS, pTessCtlFB)) { [plDesc release]; return nil; } @@ -851,29 +1045,34 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 // It is the responsibility of the caller to release the returned descriptor. MTLRenderPipelineDescriptor* MVKGraphicsPipeline::newMTLTessRasterStageDescriptor(const VkGraphicsPipelineCreateInfo* pCreateInfo, const SPIRVTessReflectionData& reflectData, - SPIRVToMSLConversionConfiguration& shaderConfig) { + SPIRVToMSLConversionConfiguration& shaderConfig, + const VkPipelineShaderStageCreateInfo* pTessEvalSS, + VkPipelineCreationFeedback* pTessEvalFB, + const VkPipelineShaderStageCreateInfo* pFragmentSS, + VkPipelineCreationFeedback* pFragmentFB, + const VkPipelineShaderStageCreateInfo* pTessCtlSS) { MTLRenderPipelineDescriptor* plDesc = [MTLRenderPipelineDescriptor new]; // retained SPIRVShaderOutputs tcOutputs, teOutputs; SPIRVShaderInputs teInputs; std::string errorLog; - if (!getShaderOutputs(((MVKShaderModule*)_pTessCtlSS->module)->getSPIRV(), spv::ExecutionModelTessellationControl, _pTessCtlSS->pName, tcOutputs, errorLog) ) { + if (!getShaderOutputs(((MVKShaderModule*)pTessCtlSS->module)->getSPIRV(), spv::ExecutionModelTessellationControl, pTessCtlSS->pName, tcOutputs, errorLog) ) { setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Failed to get tessellation control outputs: %s", errorLog.c_str())); return nil; } - if (!getShaderOutputs(((MVKShaderModule*)_pTessEvalSS->module)->getSPIRV(), spv::ExecutionModelTessellationEvaluation, _pTessEvalSS->pName, teOutputs, errorLog) ) { + if (!getShaderOutputs(((MVKShaderModule*)pTessEvalSS->module)->getSPIRV(), spv::ExecutionModelTessellationEvaluation, pTessEvalSS->pName, teOutputs, errorLog) ) { setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Failed to get tessellation evaluation outputs: %s", errorLog.c_str())); return nil; } // Add shader stages. Compile tessellation evaluation shader before others just in case conversion changes anything...like rasterizaion disable. - if (!addTessEvalShaderToPipeline(plDesc, pCreateInfo, shaderConfig, tcOutputs)) { + if (!addTessEvalShaderToPipeline(plDesc, pCreateInfo, shaderConfig, tcOutputs, pTessEvalSS, pTessEvalFB, pFragmentSS)) { [plDesc release]; return nil; } // Fragment shader - only add if rasterization is enabled - if (!addFragmentShaderToPipeline(plDesc, pCreateInfo, shaderConfig, teOutputs)) { + if (!addFragmentShaderToPipeline(plDesc, pCreateInfo, shaderConfig, teOutputs, pFragmentSS, pFragmentFB)) { [plDesc release]; return nil; } @@ -904,9 +1103,12 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 // Adds a vertex shader to the pipeline description. bool MVKGraphicsPipeline::addVertexShaderToPipeline(MTLRenderPipelineDescriptor* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo, - SPIRVToMSLConversionConfiguration& shaderConfig) { + SPIRVToMSLConversionConfiguration& shaderConfig, + const VkPipelineShaderStageCreateInfo* pVertexSS, + VkPipelineCreationFeedback* pVertexFB, + const VkPipelineShaderStageCreateInfo*& pFragmentSS) { shaderConfig.options.entryPointStage = spv::ExecutionModelVertex; - shaderConfig.options.entryPointName = _pVertexSS->pName; + shaderConfig.options.entryPointName = pVertexSS->pName; shaderConfig.options.mslOptions.swizzle_buffer_index = _swizzleBufferIndex.stages[kMVKShaderStageVertex]; shaderConfig.options.mslOptions.indirect_params_buffer_index = _indirectParamsIndex.stages[kMVKShaderStageVertex]; shaderConfig.options.mslOptions.shader_output_buffer_index = _outputBufferIndex.stages[kMVKShaderStageVertex]; @@ -917,7 +1119,7 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 shaderConfig.options.mslOptions.disable_rasterization = !_isRasterizing; addVertexInputToShaderConversionConfig(shaderConfig, pCreateInfo); - MVKMTLFunction func = getMTLFunction(shaderConfig, _pVertexSS, "Vertex"); + MVKMTLFunction func = getMTLFunction(shaderConfig, pVertexSS, pVertexFB, "Vertex"); id mtlFunc = func.getMTLFunction(); plDesc.vertexFunction = mtlFunc; if ( !mtlFunc ) { return false; } @@ -929,11 +1131,12 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 _needsVertexDynamicOffsetBuffer = funcRslts.needsDynamicOffsetBuffer; _needsVertexViewRangeBuffer = funcRslts.needsViewRangeBuffer; _needsVertexOutputBuffer = funcRslts.needsOutputBuffer; + markIfUsingPhysicalStorageBufferAddressesCapability(funcRslts, kMVKShaderStageVertex); addMTLArgumentEncoders(func, pCreateInfo, shaderConfig, kMVKShaderStageVertex); if (funcRslts.isRasterizationDisabled) { - _pFragmentSS = nullptr; + pFragmentSS = nullptr; } // If we need the swizzle buffer and there's no place to put it, we're in serious trouble. @@ -961,13 +1164,173 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 return true; } +#if MVK_XCODE_14 + +struct MSLVertexFormatInfo { + uint8_t num_elements : 7; + bool normalized : 1; +}; + +static constexpr MSLVertexFormatInfo vertexFormatInfo[] = { + [VK_FORMAT_R8_UNORM] = {1, true}, + [VK_FORMAT_R8_SNORM] = {1, true}, + [VK_FORMAT_R8_USCALED] = {1, false}, + [VK_FORMAT_R8_SSCALED] = {1, false}, + [VK_FORMAT_R8_UINT] = {1, false}, + [VK_FORMAT_R8_SINT] = {1, false}, + [VK_FORMAT_R8G8_UNORM] = {2, true}, + [VK_FORMAT_R8G8_SNORM] = {2, true}, + [VK_FORMAT_R8G8_USCALED] = {2, false}, + [VK_FORMAT_R8G8_SSCALED] = {2, false}, + [VK_FORMAT_R8G8_UINT] = {2, false}, + [VK_FORMAT_R8G8_SINT] = {2, false}, + [VK_FORMAT_R8G8B8_UNORM] = {3, true}, + [VK_FORMAT_R8G8B8_SNORM] = {3, true}, + [VK_FORMAT_R8G8B8_USCALED] = {3, false}, + [VK_FORMAT_R8G8B8_SSCALED] = {3, false}, + [VK_FORMAT_R8G8B8_UINT] = {3, false}, + [VK_FORMAT_R8G8B8_SINT] = {3, false}, + [VK_FORMAT_R8G8B8A8_UNORM] = {4, true}, + [VK_FORMAT_R8G8B8A8_SNORM] = {4, true}, + [VK_FORMAT_R8G8B8A8_USCALED] = {4, false}, + [VK_FORMAT_R8G8B8A8_SSCALED] = {4, false}, + [VK_FORMAT_R8G8B8A8_UINT] = {4, false}, + [VK_FORMAT_R8G8B8A8_SINT] = {4, false}, + [VK_FORMAT_B8G8R8A8_UNORM] = {4, true}, + [VK_FORMAT_B8G8R8A8_SNORM] = {4, true}, + [VK_FORMAT_B8G8R8A8_USCALED] = {4, false}, + [VK_FORMAT_B8G8R8A8_SSCALED] = {4, false}, + [VK_FORMAT_B8G8R8A8_UINT] = {4, false}, + [VK_FORMAT_B8G8R8A8_SINT] = {4, false}, + [VK_FORMAT_R16_UNORM] = {1, true}, + [VK_FORMAT_R16_SNORM] = {1, true}, + [VK_FORMAT_R16_USCALED] = {1, false}, + [VK_FORMAT_R16_SSCALED] = {1, false}, + [VK_FORMAT_R16_UINT] = {1, false}, + [VK_FORMAT_R16_SINT] = {1, false}, + [VK_FORMAT_R16_SFLOAT] = {1, false}, + [VK_FORMAT_R16G16_UNORM] = {2, true}, + [VK_FORMAT_R16G16_SNORM] = {2, true}, + [VK_FORMAT_R16G16_USCALED] = {2, false}, + [VK_FORMAT_R16G16_SSCALED] = {2, false}, + [VK_FORMAT_R16G16_UINT] = {2, false}, + [VK_FORMAT_R16G16_SINT] = {2, false}, + [VK_FORMAT_R16G16_SFLOAT] = {2, false}, + [VK_FORMAT_R16G16B16_UNORM] = {3, true}, + [VK_FORMAT_R16G16B16_SNORM] = {3, true}, + [VK_FORMAT_R16G16B16_USCALED] = {3, false}, + [VK_FORMAT_R16G16B16_SSCALED] = {3, false}, + [VK_FORMAT_R16G16B16_UINT] = {3, false}, + [VK_FORMAT_R16G16B16_SINT] = {3, false}, + [VK_FORMAT_R16G16B16_SFLOAT] = {3, false}, + [VK_FORMAT_R16G16B16A16_UNORM] = {4, true}, + [VK_FORMAT_R16G16B16A16_SNORM] = {4, true}, + [VK_FORMAT_R16G16B16A16_USCALED] = {4, false}, + [VK_FORMAT_R16G16B16A16_SSCALED] = {4, false}, + [VK_FORMAT_R16G16B16A16_UINT] = {4, false}, + [VK_FORMAT_R16G16B16A16_SINT] = {4, false}, + [VK_FORMAT_R16G16B16A16_SFLOAT] = {4, false}, + [VK_FORMAT_R32_UINT] = {1, false}, + [VK_FORMAT_R32_SINT] = {1, false}, + [VK_FORMAT_R32_SFLOAT] = {1, false}, + [VK_FORMAT_R32G32_UINT] = {2, false}, + [VK_FORMAT_R32G32_SINT] = {2, false}, + [VK_FORMAT_R32G32_SFLOAT] = {2, false}, + [VK_FORMAT_R32G32B32_UINT] = {3, false}, + [VK_FORMAT_R32G32B32_SINT] = {3, false}, + [VK_FORMAT_R32G32B32_SFLOAT] = {3, false}, + [VK_FORMAT_R32G32B32A32_UINT] = {4, false}, + [VK_FORMAT_R32G32B32A32_SINT] = {4, false}, + [VK_FORMAT_R32G32B32A32_SFLOAT] = {4, false}, +}; + +bool MVKGraphicsPipeline::addVertexShaderToPipeline(MTLMeshRenderPipelineDescriptor* plDesc, + const VkGraphicsPipelineCreateInfo* pCreateInfo, + SPIRVToMSLConversionConfiguration& shaderConfig, + const VkPipelineShaderStageCreateInfo* pVertexSS, + VkPipelineCreationFeedback* pVertexFB) { + + shaderConfig.options.entryPointStage = spv::ExecutionModelVertex; + shaderConfig.options.entryPointName = pVertexSS->pName; + shaderConfig.options.mslOptions.swizzle_buffer_index = _swizzleBufferIndex.stages[kMVKShaderStageVertex]; + shaderConfig.options.mslOptions.indirect_params_buffer_index = _indirectParamsIndex.stages[kMVKShaderStageVertex]; + shaderConfig.options.mslOptions.shader_output_buffer_index = _outputBufferIndex.stages[kMVKShaderStageVertex]; + shaderConfig.options.mslOptions.buffer_size_buffer_index = _bufferSizeBufferIndex.stages[kMVKShaderStageVertex]; + shaderConfig.options.mslOptions.dynamic_offsets_buffer_index = _dynamicOffsetBufferIndex.stages[kMVKShaderStageVertex]; + shaderConfig.options.mslOptions.view_mask_buffer_index = _viewRangeBufferIndex.stages[kMVKShaderStageVertex]; + shaderConfig.options.mslOptions.capture_output_to_buffer = false; + shaderConfig.options.mslOptions.disable_rasterization = !_isRasterizing; + shaderConfig.options.mslOptions.for_mesh_pipeline = true; + shaderConfig.options.mslOptions.msl_version = getDevice()->getPhysicalDevice()->getMetalFeatures()->mslVersion; + shaderConfig.options.shouldFlipVertexY = false; + + if (_mtlPrimitiveType == MTLPrimitiveTypeTriangleStrip) + shaderConfig.options.mslOptions.input_primitive_type = CompilerMSL::Options::PrimitiveTopology::TriangleStrip; + else if (_mtlPrimitiveType == MTLPrimitiveTypeTriangle) + shaderConfig.options.mslOptions.input_primitive_type = CompilerMSL::Options::PrimitiveTopology::Triangles; + else if (_mtlPrimitiveType == MTLPrimitiveTypePoint) + shaderConfig.options.mslOptions.input_primitive_type = CompilerMSL::Options::PrimitiveTopology::Points; + else + reportMessage(MVK_CONFIG_LOG_LEVEL_ERROR, "Unsupported topology: %lu", _mtlPrimitiveType); + + addVertexInputToShaderConversionConfig(shaderConfig, pCreateInfo); + + MVKMTLFunction vertexFunc = getMTLFunction(shaderConfig, pVertexSS, pVertexFB, "Vertex"); + + plDesc.objectFunction = vertexFunc.getMTLFunction(); + return true; +} + +bool MVKGraphicsPipeline::addGeometryShaderToPipeline(MTLMeshRenderPipelineDescriptor* plDesc, + const VkGraphicsPipelineCreateInfo* pCreateInfo, + SPIRVToMSLConversionConfiguration& shaderConfig, + const VkPipelineShaderStageCreateInfo* pGeometrySS, + VkPipelineCreationFeedback* pGeometryFB, + SPIRVShaderOutputs &vertexOutputs) { + + shaderConfig.options.entryPointStage = spv::ExecutionModelGeometry; + shaderConfig.options.entryPointName = pGeometrySS->pName; + shaderConfig.options.mslOptions.swizzle_buffer_index = _swizzleBufferIndex.stages[kMVKShaderStageGeometry]; + shaderConfig.options.mslOptions.indirect_params_buffer_index = _indirectParamsIndex.stages[kMVKShaderStageGeometry]; + shaderConfig.options.mslOptions.shader_output_buffer_index = _outputBufferIndex.stages[kMVKShaderStageGeometry]; + shaderConfig.options.mslOptions.buffer_size_buffer_index = _bufferSizeBufferIndex.stages[kMVKShaderStageGeometry]; + shaderConfig.options.mslOptions.dynamic_offsets_buffer_index = _dynamicOffsetBufferIndex.stages[kMVKShaderStageGeometry]; + shaderConfig.options.mslOptions.view_mask_buffer_index = _viewRangeBufferIndex.stages[kMVKShaderStageGeometry]; + shaderConfig.options.mslOptions.capture_output_to_buffer = false; + shaderConfig.options.mslOptions.disable_rasterization = !_isRasterizing; + shaderConfig.options.mslOptions.for_mesh_pipeline = true; + shaderConfig.options.mslOptions.msl_version = getDevice()->getPhysicalDevice()->getMetalFeatures()->mslVersion; + shaderConfig.options.shouldFlipVertexY = true; + + if (_mtlPrimitiveType == MTLPrimitiveTypeTriangleStrip) + shaderConfig.options.mslOptions.input_primitive_type = CompilerMSL::Options::PrimitiveTopology::TriangleStrip; + else if (_mtlPrimitiveType == MTLPrimitiveTypeTriangle) + shaderConfig.options.mslOptions.input_primitive_type = CompilerMSL::Options::PrimitiveTopology::Triangles; + else if (_mtlPrimitiveType == MTLPrimitiveTypePoint) + shaderConfig.options.mslOptions.input_primitive_type = CompilerMSL::Options::PrimitiveTopology::Points; + else + reportMessage(MVK_CONFIG_LOG_LEVEL_ERROR, "Unsupported topology: %lu", _mtlPrimitiveType); + + addPrevStageOutputToShaderConversionConfig(shaderConfig, vertexOutputs); + + MVKMTLFunction geometryFunc = getMTLFunction(shaderConfig, pGeometrySS, pGeometryFB, "Geometry"); + + plDesc.meshFunction = geometryFunc.getMTLFunction(); + return true; +} + +#endif + // Adds a vertex shader compiled as a compute kernel to the pipeline description. bool MVKGraphicsPipeline::addVertexShaderToPipeline(MTLComputePipelineDescriptor* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo, SPIRVToMSLConversionConfiguration& shaderConfig, - SPIRVShaderInputs& tcInputs) { + SPIRVShaderInputs& tcInputs, + const VkPipelineShaderStageCreateInfo* pVertexSS, + VkPipelineCreationFeedback* pVertexFB, + MVKMTLFunction* pVtxFunctions) { shaderConfig.options.entryPointStage = spv::ExecutionModelVertex; - shaderConfig.options.entryPointName = _pVertexSS->pName; + shaderConfig.options.entryPointName = pVertexSS->pName; shaderConfig.options.mslOptions.swizzle_buffer_index = _swizzleBufferIndex.stages[kMVKShaderStageVertex]; shaderConfig.options.mslOptions.shader_index_buffer_index = _indirectParamsIndex.stages[kMVKShaderStageVertex]; shaderConfig.options.mslOptions.shader_output_buffer_index = _outputBufferIndex.stages[kMVKShaderStageVertex]; @@ -988,16 +1351,17 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 MVKMTLFunction func; for (uint32_t i = 0; i < sizeof(indexTypes)/sizeof(indexTypes[0]); i++) { shaderConfig.options.mslOptions.vertex_index_type = indexTypes[i]; - func = getMTLFunction(shaderConfig, _pVertexSS, "Vertex"); - id mtlFunc = func.getMTLFunction(); - _mtlTessVertexFunctions[i] = [mtlFunc retain]; - if ( !mtlFunc ) { return false; } + func = getMTLFunction(shaderConfig, pVertexSS, pVertexFB, "Vertex"); + if ( !func.getMTLFunction() ) { return false; } + + pVtxFunctions[i] = func; auto& funcRslts = func.shaderConversionResults; _needsVertexSwizzleBuffer = funcRslts.needsSwizzleBuffer; _needsVertexBufferSizeBuffer = funcRslts.needsBufferSizeBuffer; _needsVertexDynamicOffsetBuffer = funcRslts.needsDynamicOffsetBuffer; _needsVertexOutputBuffer = funcRslts.needsOutputBuffer; + markIfUsingPhysicalStorageBufferAddressesCapability(funcRslts, kMVKShaderStageVertex); } addMTLArgumentEncoders(func, pCreateInfo, shaderConfig, kMVKShaderStageVertex); @@ -1028,9 +1392,11 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 const VkGraphicsPipelineCreateInfo* pCreateInfo, SPIRVToMSLConversionConfiguration& shaderConfig, SPIRVShaderOutputs& vtxOutputs, - SPIRVShaderInputs& teInputs) { + SPIRVShaderInputs& teInputs, + const VkPipelineShaderStageCreateInfo* pTessCtlSS, + VkPipelineCreationFeedback* pTessCtlFB) { shaderConfig.options.entryPointStage = spv::ExecutionModelTessellationControl; - shaderConfig.options.entryPointName = _pTessCtlSS->pName; + shaderConfig.options.entryPointName = pTessCtlSS->pName; shaderConfig.options.mslOptions.swizzle_buffer_index = _swizzleBufferIndex.stages[kMVKShaderStageTessCtl]; shaderConfig.options.mslOptions.indirect_params_buffer_index = _indirectParamsIndex.stages[kMVKShaderStageTessCtl]; shaderConfig.options.mslOptions.shader_input_buffer_index = getMetalBufferIndexForVertexAttributeBinding(kMVKTessCtlInputBufferBinding); @@ -1041,14 +1407,14 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 shaderConfig.options.mslOptions.dynamic_offsets_buffer_index = _dynamicOffsetBufferIndex.stages[kMVKShaderStageTessCtl]; shaderConfig.options.mslOptions.capture_output_to_buffer = true; shaderConfig.options.mslOptions.multi_patch_workgroup = true; - shaderConfig.options.mslOptions.fixed_subgroup_size = mvkIsAnyFlagEnabled(_pTessCtlSS->flags, VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT) ? 0 : _device->_pMetalFeatures->maxSubgroupSize; + shaderConfig.options.mslOptions.fixed_subgroup_size = mvkIsAnyFlagEnabled(pTessCtlSS->flags, VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT) ? 0 : _device->_pMetalFeatures->maxSubgroupSize; addPrevStageOutputToShaderConversionConfig(shaderConfig, vtxOutputs); addNextStageInputToShaderConversionConfig(shaderConfig, teInputs); - MVKMTLFunction func = getMTLFunction(shaderConfig, _pTessCtlSS, "Tessellation control"); + MVKMTLFunction func = getMTLFunction(shaderConfig, pTessCtlSS, pTessCtlFB, "Tessellation control"); id mtlFunc = func.getMTLFunction(); - plDesc.computeFunction = mtlFunc; if ( !mtlFunc ) { return false; } + plDesc.computeFunction = mtlFunc; auto& funcRslts = func.shaderConversionResults; _needsTessCtlSwizzleBuffer = funcRslts.needsSwizzleBuffer; @@ -1057,6 +1423,7 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 _needsTessCtlOutputBuffer = funcRslts.needsOutputBuffer; _needsTessCtlPatchOutputBuffer = funcRslts.needsPatchOutputBuffer; _needsTessCtlInputBuffer = funcRslts.needsInputThreadgroupMem; + markIfUsingPhysicalStorageBufferAddressesCapability(funcRslts, kMVKShaderStageTessCtl); addMTLArgumentEncoders(func, pCreateInfo, shaderConfig, kMVKShaderStageTessCtl); @@ -1089,9 +1456,12 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 bool MVKGraphicsPipeline::addTessEvalShaderToPipeline(MTLRenderPipelineDescriptor* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo, SPIRVToMSLConversionConfiguration& shaderConfig, - SPIRVShaderOutputs& tcOutputs) { + SPIRVShaderOutputs& tcOutputs, + const VkPipelineShaderStageCreateInfo* pTessEvalSS, + VkPipelineCreationFeedback* pTessEvalFB, + const VkPipelineShaderStageCreateInfo*& pFragmentSS) { shaderConfig.options.entryPointStage = spv::ExecutionModelTessellationEvaluation; - shaderConfig.options.entryPointName = _pTessEvalSS->pName; + shaderConfig.options.entryPointName = pTessEvalSS->pName; shaderConfig.options.mslOptions.swizzle_buffer_index = _swizzleBufferIndex.stages[kMVKShaderStageTessEval]; shaderConfig.options.mslOptions.shader_input_buffer_index = getMetalBufferIndexForVertexAttributeBinding(kMVKTessEvalInputBufferBinding); shaderConfig.options.mslOptions.shader_patch_input_buffer_index = getMetalBufferIndexForVertexAttributeBinding(kMVKTessEvalPatchInputBufferBinding); @@ -1103,7 +1473,7 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 shaderConfig.options.mslOptions.disable_rasterization = !_isRasterizing; addPrevStageOutputToShaderConversionConfig(shaderConfig, tcOutputs); - MVKMTLFunction func = getMTLFunction(shaderConfig, _pTessEvalSS, "Tessellation evaluation"); + MVKMTLFunction func = getMTLFunction(shaderConfig, pTessEvalSS, pTessEvalFB, "Tessellation evaluation"); id mtlFunc = func.getMTLFunction(); plDesc.vertexFunction = mtlFunc; // Yeah, you read that right. Tess. eval functions are a kind of vertex function in Metal. if ( !mtlFunc ) { return false; } @@ -1113,11 +1483,12 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 _needsTessEvalSwizzleBuffer = funcRslts.needsSwizzleBuffer; _needsTessEvalBufferSizeBuffer = funcRslts.needsBufferSizeBuffer; _needsTessEvalDynamicOffsetBuffer = funcRslts.needsDynamicOffsetBuffer; + markIfUsingPhysicalStorageBufferAddressesCapability(funcRslts, kMVKShaderStageTessEval); addMTLArgumentEncoders(func, pCreateInfo, shaderConfig, kMVKShaderStageTessEval); if (funcRslts.isRasterizationDisabled) { - _pFragmentSS = nullptr; + pFragmentSS = nullptr; } if (!verifyImplicitBuffer(_needsTessEvalSwizzleBuffer, _swizzleBufferIndex, kMVKShaderStageTessEval, "swizzle")) { @@ -1132,23 +1503,27 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 return true; } -bool MVKGraphicsPipeline::addFragmentShaderToPipeline(MTLRenderPipelineDescriptor* plDesc, +template +bool MVKGraphicsPipeline::addFragmentShaderToPipeline(T* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo, SPIRVToMSLConversionConfiguration& shaderConfig, - SPIRVShaderOutputs& shaderOutputs) { - if (_pFragmentSS) { + SPIRVShaderOutputs& shaderOutputs, + const VkPipelineShaderStageCreateInfo* pFragmentSS, + VkPipelineCreationFeedback* pFragmentFB) { + if (pFragmentSS) { shaderConfig.options.entryPointStage = spv::ExecutionModelFragment; shaderConfig.options.mslOptions.swizzle_buffer_index = _swizzleBufferIndex.stages[kMVKShaderStageFragment]; shaderConfig.options.mslOptions.buffer_size_buffer_index = _bufferSizeBufferIndex.stages[kMVKShaderStageFragment]; shaderConfig.options.mslOptions.dynamic_offsets_buffer_index = _dynamicOffsetBufferIndex.stages[kMVKShaderStageFragment]; shaderConfig.options.mslOptions.view_mask_buffer_index = _viewRangeBufferIndex.stages[kMVKShaderStageFragment]; - shaderConfig.options.entryPointName = _pFragmentSS->pName; + shaderConfig.options.entryPointName = pFragmentSS->pName; shaderConfig.options.mslOptions.capture_output_to_buffer = false; - shaderConfig.options.mslOptions.fixed_subgroup_size = mvkIsAnyFlagEnabled(_pFragmentSS->flags, VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT) ? 0 : _device->_pMetalFeatures->maxSubgroupSize; + shaderConfig.options.mslOptions.fixed_subgroup_size = mvkIsAnyFlagEnabled(pFragmentSS->flags, VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT) ? 0 : _device->_pMetalFeatures->maxSubgroupSize; shaderConfig.options.mslOptions.check_discarded_frag_stores = true; if (_device->_pMetalFeatures->needsSampleDrefLodArrayWorkaround) { shaderConfig.options.mslOptions.sample_dref_lod_array_as_grad = true; } + shaderConfig.options.mslOptions.for_mesh_pipeline = false; if (_isRasterizing && pCreateInfo->pMultisampleState) { // Must ignore allowed bad pMultisampleState pointer if rasterization disabled if (pCreateInfo->pMultisampleState->pSampleMask && pCreateInfo->pMultisampleState->pSampleMask[0] != 0xffffffff) { shaderConfig.options.mslOptions.additional_fixed_sample_mask = pCreateInfo->pMultisampleState->pSampleMask[0]; @@ -1160,7 +1535,7 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 } addPrevStageOutputToShaderConversionConfig(shaderConfig, shaderOutputs); - MVKMTLFunction func = getMTLFunction(shaderConfig, _pFragmentSS, "Fragment"); + MVKMTLFunction func = getMTLFunction(shaderConfig, pFragmentSS, pFragmentFB, "Fragment"); id mtlFunc = func.getMTLFunction(); plDesc.fragmentFunction = mtlFunc; if ( !mtlFunc ) { return false; } @@ -1170,6 +1545,7 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 _needsFragmentBufferSizeBuffer = funcRslts.needsBufferSizeBuffer; _needsFragmentDynamicOffsetBuffer = funcRslts.needsDynamicOffsetBuffer; _needsFragmentViewRangeBuffer = funcRslts.needsViewRangeBuffer; + markIfUsingPhysicalStorageBufferAddressesCapability(funcRslts, kMVKShaderStageFragment); addMTLArgumentEncoders(func, pCreateInfo, shaderConfig, kMVKShaderStageFragment); @@ -1419,10 +1795,10 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 plDesc.tessellationPartitionMode = mvkMTLTessellationPartitionModeFromSpvExecutionMode(reflectData.partitionMode); } -void MVKGraphicsPipeline::addFragmentOutputToPipeline(MTLRenderPipelineDescriptor* plDesc, - const VkGraphicsPipelineCreateInfo* pCreateInfo) { +template +void MVKGraphicsPipeline::addFragmentOutputToPipeline(T* plDesc, const VkGraphicsPipelineCreateInfo* pCreateInfo) { // Topology - if (pCreateInfo->pInputAssemblyState) { + if (pCreateInfo->pInputAssemblyState && !isGeometryPipeline()) { plDesc.inputPrimitiveTopologyMVK = isRenderingPoints(pCreateInfo) ? MTLPrimitiveTopologyClassPoint : mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology(pCreateInfo->pInputAssemblyState->topology); @@ -1464,16 +1840,19 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 } } - // Depth & stencil attachments + // Depth & stencil attachment formats MVKPixelFormats* pixFmts = getPixelFormats(); - MTLPixelFormat mtlDSFormat = pixFmts->getMTLPixelFormat(mvkGetDepthStencilFormat(pRendInfo)); - if (pixFmts->isDepthFormat(mtlDSFormat)) { plDesc.depthAttachmentPixelFormat = mtlDSFormat; } - if (pixFmts->isStencilFormat(mtlDSFormat)) { plDesc.stencilAttachmentPixelFormat = mtlDSFormat; } - // In Vulkan, it's perfectly valid to render with no attachments. In Metal we need to check for - // support for it. If we have no attachments, then we may have to add a dummy attachment. - if (!caCnt && !pixFmts->isDepthFormat(mtlDSFormat) && !pixFmts->isStencilFormat(mtlDSFormat) && - !getDevice()->_pMetalFeatures->renderWithoutAttachments) { + MTLPixelFormat mtlDepthPixFmt = pixFmts->getMTLPixelFormat(pRendInfo->depthAttachmentFormat); + if (pixFmts->isDepthFormat(mtlDepthPixFmt)) { plDesc.depthAttachmentPixelFormat = mtlDepthPixFmt; } + + MTLPixelFormat mtlStencilPixFmt = pixFmts->getMTLPixelFormat(pRendInfo->stencilAttachmentFormat); + if (pixFmts->isStencilFormat(mtlStencilPixFmt)) { plDesc.stencilAttachmentPixelFormat = mtlStencilPixFmt; } + + // In Vulkan, it's perfectly valid to render without any attachments. In Metal, if that + // isn't supported, and we have no attachments, then we have to add a dummy attachment. + if (!getDevice()->_pMetalFeatures->renderWithoutAttachments && + !caCnt && !pRendInfo->depthAttachmentFormat && !pRendInfo->stencilAttachmentFormat) { MTLRenderPipelineColorAttachmentDescriptor* colorDesc = plDesc.colorAttachments[0]; colorDesc.pixelFormat = MTLPixelFormatR8Unorm; @@ -1482,7 +1861,7 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 // Multisampling - must ignore allowed bad pMultisampleState pointer if rasterization disabled if (_isRasterizing && pCreateInfo->pMultisampleState) { - plDesc.sampleCount = mvkSampleCountFromVkSampleCountFlagBits(pCreateInfo->pMultisampleState->rasterizationSamples); + plDesc.rasterSampleCount = mvkSampleCountFromVkSampleCountFlagBits(pCreateInfo->pMultisampleState->rasterizationSamples); plDesc.alphaToCoverageEnabled = pCreateInfo->pMultisampleState->alphaToCoverageEnable; plDesc.alphaToOneEnabled = pCreateInfo->pMultisampleState->alphaToOneEnable; @@ -1549,7 +1928,6 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 const VkPipelineRenderingCreateInfo* pRendInfo = getRenderingCreateInfo(pCreateInfo); MVKPixelFormats* pixFmts = getPixelFormats(); - MTLPixelFormat mtlDSFormat = pixFmts->getMTLPixelFormat(mvkGetDepthStencilFormat(pRendInfo)); // Disable any unused color attachments, because Metal validation can complain if the // fragment shader outputs a color value without a corresponding color attachment. @@ -1569,8 +1947,8 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 shaderConfig.options.mslOptions.ios_support_base_vertex_instance = getDevice()->_pMetalFeatures->baseVertexInstanceDrawing; shaderConfig.options.mslOptions.texture_1D_as_2D = mvkConfig().texture1DAs2D; shaderConfig.options.mslOptions.enable_point_size_builtin = isRenderingPoints(pCreateInfo) || reflectData.pointMode; - shaderConfig.options.mslOptions.enable_frag_depth_builtin = pixFmts->isDepthFormat(mtlDSFormat); - shaderConfig.options.mslOptions.enable_frag_stencil_ref_builtin = pixFmts->isStencilFormat(mtlDSFormat); + shaderConfig.options.mslOptions.enable_frag_depth_builtin = pixFmts->isDepthFormat(pixFmts->getMTLPixelFormat(pRendInfo->depthAttachmentFormat)); + shaderConfig.options.mslOptions.enable_frag_stencil_ref_builtin = pixFmts->isStencilFormat(pixFmts->getMTLPixelFormat(pRendInfo->stencilAttachmentFormat)); shaderConfig.options.shouldFlipVertexY = mvkConfig().shaderConversionFlipVertexY; shaderConfig.options.mslOptions.swizzle_texture_samples = _fullImageViewSwizzle && !getDevice()->_pMetalFeatures->nativeTextureSwizzle; shaderConfig.options.mslOptions.tess_domain_origin_lower_left = pTessDomainOriginState && pTessDomainOriginState->domainOrigin == VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT; @@ -1633,18 +2011,48 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 return mtlBufferIndex < _descriptorBufferCounts.stages[stage] || mtlBufferIndex > getImplicitBufferIndex(stage, 0); } +static MVK_spirv_cross::MSLShaderVariableFormat toMslShaderFormat(MVKFormatType type) { + switch (type) { + case kMVKFormatColorInt8: return MSL_SHADER_VARIABLE_FORMAT_INT8; + case kMVKFormatColorUInt8: return MSL_SHADER_VARIABLE_FORMAT_UINT8; + case kMVKFormatColorInt16: return MSL_SHADER_VARIABLE_FORMAT_INT16; + case kMVKFormatColorUInt16: return MSL_SHADER_VARIABLE_FORMAT_UINT16; + case kMVKFormatColorInt32: return MSL_SHADER_VARIABLE_FORMAT_INT32; + case kMVKFormatColorUInt32: return MSL_SHADER_VARIABLE_FORMAT_UINT32; + case kMVKFormatColorFloat: return MSL_SHADER_VARIABLE_FORMAT_FLOAT; + case kMVKFormatColorHalf: return MSL_SHADER_VARIABLE_FORMAT_HALF; + default: return MSL_SHADER_VARIABLE_FORMAT_OTHER; + } +} + // Initializes the vertex attributes in a shader conversion configuration. void MVKGraphicsPipeline::addVertexInputToShaderConversionConfig(SPIRVToMSLConversionConfiguration& shaderConfig, const VkGraphicsPipelineCreateInfo* pCreateInfo) { // Set the shader conversion config vertex attribute information shaderConfig.shaderInputs.clear(); uint32_t vaCnt = pCreateInfo->pVertexInputState->vertexAttributeDescriptionCount; + uint32_t vbCnt = pCreateInfo->pVertexInputState->vertexBindingDescriptionCount; for (uint32_t vaIdx = 0; vaIdx < vaCnt; vaIdx++) { const VkVertexInputAttributeDescription* pVKVA = &pCreateInfo->pVertexInputState->pVertexAttributeDescriptions[vaIdx]; + const VkVertexInputBindingDescription* pVKVB = nullptr; + + for (uint32_t vbIdx = 0; vbIdx < vbCnt; vbIdx++) { + pVKVB = &pCreateInfo->pVertexInputState->pVertexBindingDescriptions[vbIdx]; + if (pVKVA->binding == pVKVB->binding) break; + } // Set binding and offset from Vulkan vertex attribute mvk::MSLShaderInput si; si.shaderVar.location = pVKVA->location; + si.shaderVar.offset = pVKVA->offset; + si.shaderVar.stride = pVKVB->stride; + + if (shaderConfig.options.mslOptions.for_mesh_pipeline) { + si.shaderVar.vecsize = vertexFormatInfo[pVKVA->format].num_elements; + si.shaderVar.normalized = vertexFormatInfo[pVKVA->format].normalized; + si.shaderVar.binding = getDevice()->getMetalBufferIndexForVertexAttributeBinding(pVKVA->binding); + } + si.binding = pVKVA->binding; // Metal can't do signedness conversions on vertex buffers (rdar://45922847). If the shader @@ -1652,33 +2060,29 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 // to match the vertex attribute. So tell SPIRV-Cross if we're expecting an unsigned format. // Only do this if the attribute could be reasonably expected to fit in the shader's // declared type. Programs that try to invoke undefined behavior are on their own. - switch (getPixelFormats()->getFormatType(pVKVA->format) ) { - case kMVKFormatColorUInt8: - si.shaderVar.format = MSL_VERTEX_FORMAT_UINT8; - break; - - case kMVKFormatColorUInt16: - si.shaderVar.format = MSL_VERTEX_FORMAT_UINT16; - break; - - case kMVKFormatDepthStencil: - // Only some depth/stencil formats have unsigned components. - switch (pVKVA->format) { - case VK_FORMAT_S8_UINT: - case VK_FORMAT_D16_UNORM_S8_UINT: - case VK_FORMAT_D24_UNORM_S8_UINT: - case VK_FORMAT_D32_SFLOAT_S8_UINT: - si.shaderVar.format = MSL_VERTEX_FORMAT_UINT8; + auto mvkFormat = getPixelFormats()->getFormatType(pVKVA->format); + si.shaderVar.format = toMslShaderFormat(mvkFormat); + + if (si.shaderVar.format == MSL_VERTEX_FORMAT_OTHER) { + switch (getPixelFormats()->getFormatType(pVKVA->format) ) { + case kMVKFormatDepthStencil: + // Only some depth/stencil formats have unsigned components. + switch (pVKVA->format) { + case VK_FORMAT_S8_UINT: + case VK_FORMAT_D16_UNORM_S8_UINT: + case VK_FORMAT_D24_UNORM_S8_UINT: + case VK_FORMAT_D32_SFLOAT_S8_UINT: + si.shaderVar.format = MSL_VERTEX_FORMAT_UINT8; + break; + + default: + break; + } break; default: break; } - break; - - default: - break; - } shaderConfig.shaderInputs.push_back(si); @@ -1700,30 +2104,8 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 so.shaderVar.builtin = shaderInputs[soIdx].builtin; so.shaderVar.vecsize = shaderInputs[soIdx].vecWidth; so.shaderVar.rate = shaderInputs[soIdx].perPatch ? MSL_SHADER_VARIABLE_RATE_PER_PATCH : MSL_SHADER_VARIABLE_RATE_PER_VERTEX; - - switch (getPixelFormats()->getFormatType(mvkFormatFromOutput(shaderInputs[soIdx]) ) ) { - case kMVKFormatColorUInt8: - so.shaderVar.format = MSL_SHADER_INPUT_FORMAT_UINT8; - break; - - case kMVKFormatColorUInt16: - so.shaderVar.format = MSL_SHADER_INPUT_FORMAT_UINT16; - break; - - case kMVKFormatColorHalf: - case kMVKFormatColorInt16: - so.shaderVar.format = MSL_SHADER_INPUT_FORMAT_ANY16; - break; - - case kMVKFormatColorFloat: - case kMVKFormatColorInt32: - case kMVKFormatColorUInt32: - so.shaderVar.format = MSL_SHADER_INPUT_FORMAT_ANY32; - break; - - default: - break; - } + so.shaderVar.type = shaderInputs[soIdx].baseType; + so.shaderVar.format = toMslShaderFormat(getPixelFormats()->getFormatType(mvkFormatFromOutput(shaderInputs[soIdx]))); shaderConfig.shaderOutputs.push_back(so); } @@ -1743,31 +2125,9 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 si.shaderVar.component = shaderOutputs[siIdx].component; si.shaderVar.builtin = shaderOutputs[siIdx].builtin; si.shaderVar.vecsize = shaderOutputs[siIdx].vecWidth; + si.shaderVar.type = shaderOutputs[siIdx].baseType; si.shaderVar.rate = shaderOutputs[siIdx].perPatch ? MSL_SHADER_VARIABLE_RATE_PER_PATCH : MSL_SHADER_VARIABLE_RATE_PER_VERTEX; - - switch (getPixelFormats()->getFormatType(mvkFormatFromOutput(shaderOutputs[siIdx]) ) ) { - case kMVKFormatColorUInt8: - si.shaderVar.format = MSL_SHADER_INPUT_FORMAT_UINT8; - break; - - case kMVKFormatColorUInt16: - si.shaderVar.format = MSL_SHADER_INPUT_FORMAT_UINT16; - break; - - case kMVKFormatColorHalf: - case kMVKFormatColorInt16: - si.shaderVar.format = MSL_SHADER_INPUT_FORMAT_ANY16; - break; - - case kMVKFormatColorFloat: - case kMVKFormatColorInt32: - case kMVKFormatColorUInt32: - si.shaderVar.format = MSL_SHADER_INPUT_FORMAT_ANY32; - break; - - default: - break; - } + si.shaderVar.format = toMslShaderFormat(getPixelFormats()->getFormatType(mvkFormatFromOutput(shaderOutputs[siIdx]))); shaderConfig.shaderInputs.push_back(si); } @@ -1789,11 +2149,13 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 MVKMTLFunction MVKGraphicsPipeline::getMTLFunction(SPIRVToMSLConversionConfiguration& shaderConfig, const VkPipelineShaderStageCreateInfo* pShaderStage, + VkPipelineCreationFeedback* pStageFB, const char* pStageName) { MVKShaderModule* shaderModule = (MVKShaderModule*)pShaderStage->module; MVKMTLFunction func = shaderModule->getMTLFunction(&shaderConfig, pShaderStage->pSpecializationInfo, - this); + this, + pStageFB); if ( !func.getMTLFunction() ) { if (shouldFailOnPipelineCompileRequired()) { setConfigurationResult(VK_PIPELINE_COMPILE_REQUIRED); @@ -1804,17 +2166,24 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 return func; } +void MVKGraphicsPipeline::markIfUsingPhysicalStorageBufferAddressesCapability(SPIRVToMSLConversionResultInfo& resultsInfo, + MVKShaderStage stage) { + if (resultsInfo.usesPhysicalStorageBufferAddressesCapability) { + _stagesUsingPhysicalStorageBufferAddressesCapability.push_back(stage); + } +} + +bool MVKGraphicsPipeline::usesPhysicalStorageBufferAddressesCapability(MVKShaderStage stage) { + return mvkContains(_stagesUsingPhysicalStorageBufferAddressesCapability, stage); +} + MVKGraphicsPipeline::~MVKGraphicsPipeline() { @synchronized (getMTLDevice()) { - [_mtlTessVertexStageDesc release]; - [_mtlTessVertexStageState release]; [_mtlTessVertexStageIndex16State release]; [_mtlTessVertexStageIndex32State release]; [_mtlTessControlStageState release]; [_mtlPipelineState release]; - - for (id func : _mtlTessVertexFunctions) { [func release]; } } } @@ -1845,7 +2214,36 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 if (isUsingMetalArgumentBuffers()) { _descriptorBindingUse.resize(_descriptorSetCount); } if (isUsingPipelineStageMetalArgumentBuffers()) { _mtlArgumentEncoders.resize(_descriptorSetCount); } - MVKMTLFunction func = getMTLFunction(pCreateInfo); + const VkPipelineCreationFeedbackCreateInfo* pFeedbackInfo = nullptr; + for (const auto* next = (VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) { + switch (next->sType) { + case VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO: + pFeedbackInfo = (VkPipelineCreationFeedbackCreateInfo*)next; + break; + default: + break; + } + } + + // Initialize feedback. The VALID bit must be initialized, either set or cleared. + // We'll set the VALID bit on the stage feedback when we compile it. + VkPipelineCreationFeedback* pPipelineFB = nullptr; + VkPipelineCreationFeedback* pStageFB = nullptr; + uint64_t pipelineStart = 0; + if (pFeedbackInfo) { + pPipelineFB = pFeedbackInfo->pPipelineCreationFeedback; + // n.b. Do *NOT* use mvkClear(). + pPipelineFB->flags = 0; + pPipelineFB->duration = 0; + for (uint32_t i = 0; i < pFeedbackInfo->pipelineStageCreationFeedbackCount; ++i) { + pFeedbackInfo->pPipelineStageCreationFeedbacks[i].flags = 0; + pFeedbackInfo->pPipelineStageCreationFeedbacks[i].duration = 0; + } + pStageFB = &pFeedbackInfo->pPipelineStageCreationFeedbacks[0]; + pipelineStart = mvkGetTimestamp(); + } + + MVKMTLFunction func = getMTLFunction(pCreateInfo, pStageFB); _mtlThreadgroupSize = func.threadGroupSize; _mtlPipelineState = nil; @@ -1873,6 +2271,10 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 } else { _hasValidMTLPipelineStates = false; } + if (pPipelineFB) { + if (_hasValidMTLPipelineStates) { mvkEnableFlags(pPipelineFB->flags, VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT); } + pPipelineFB->duration = mvkGetElapsedNanoseconds(pipelineStart); + } if (_needsSwizzleBuffer && _swizzleBufferIndex.stages[kMVKShaderStageCompute] > _device->_pMetalFeatures->maxPerStageBufferCount) { setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV, "Compute shader requires swizzle buffer, but there is no free slot to pass it.")); @@ -1889,7 +2291,8 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 } // Returns a MTLFunction to use when creating the MTLComputePipelineState. -MVKMTLFunction MVKComputePipeline::getMTLFunction(const VkComputePipelineCreateInfo* pCreateInfo) { +MVKMTLFunction MVKComputePipeline::getMTLFunction(const VkComputePipelineCreateInfo* pCreateInfo, + VkPipelineCreationFeedback* pStageFB) { const VkPipelineShaderStageCreateInfo* pSS = &pCreateInfo->stage; if ( !mvkAreAllFlagsEnabled(pSS->stage, VK_SHADER_STAGE_COMPUTE_BIT) ) { return MVKMTLFunctionNull; } @@ -1939,7 +2342,7 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 shaderConfig.options.mslOptions.dynamic_offsets_buffer_index = _dynamicOffsetBufferIndex.stages[kMVKShaderStageCompute]; shaderConfig.options.mslOptions.indirect_params_buffer_index = _indirectParamsIndex.stages[kMVKShaderStageCompute]; - MVKMTLFunction func = ((MVKShaderModule*)pSS->module)->getMTLFunction(&shaderConfig, pSS->pSpecializationInfo, this); + MVKMTLFunction func = ((MVKShaderModule*)pSS->module)->getMTLFunction(&shaderConfig, pSS->pSpecializationInfo, this, pStageFB); if ( !func.getMTLFunction() ) { if (shouldFailOnPipelineCompileRequired()) { setConfigurationResult(VK_PIPELINE_COMPILE_REQUIRED); @@ -1952,6 +2355,7 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 _needsBufferSizeBuffer = funcRslts.needsBufferSizeBuffer; _needsDynamicOffsetBuffer = funcRslts.needsDynamicOffsetBuffer; _needsDispatchBaseBuffer = funcRslts.needsDispatchBaseBuffer; + _usesPhysicalStorageBufferAddressesCapability = funcRslts.usesPhysicalStorageBufferAddressesCapability; addMTLArgumentEncoders(func, pCreateInfo, shaderConfig, kMVKShaderStageCompute); @@ -1962,6 +2366,10 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 return _device->_pMetalFeatures->maxPerStageBufferCount - (bufferIndexOffset + 1); } +bool MVKComputePipeline::usesPhysicalStorageBufferAddressesCapability(MVKShaderStage stage) { + return _usesPhysicalStorageBufferAddressesCapability; +} + MVKComputePipeline::~MVKComputePipeline() { @synchronized (getMTLDevice()) { [_mtlPipelineState release]; @@ -1976,23 +2384,26 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3 MVKShaderLibrary* MVKPipelineCache::getShaderLibrary(SPIRVToMSLConversionConfiguration* pContext, MVKShaderModule* shaderModule, MVKPipeline* pipeline, + VkPipelineCreationFeedback* pShaderFeedback, uint64_t startTime) { if (_isExternallySynchronized) { - return getShaderLibraryImpl(pContext, shaderModule, pipeline, startTime); + return getShaderLibraryImpl(pContext, shaderModule, pipeline, pShaderFeedback, startTime); } else { lock_guard lock(_shaderCacheLock); - return getShaderLibraryImpl(pContext, shaderModule, pipeline, startTime); + return getShaderLibraryImpl(pContext, shaderModule, pipeline, pShaderFeedback, startTime); } } MVKShaderLibrary* MVKPipelineCache::getShaderLibraryImpl(SPIRVToMSLConversionConfiguration* pContext, MVKShaderModule* shaderModule, MVKPipeline* pipeline, + VkPipelineCreationFeedback* pShaderFeedback, uint64_t startTime) { bool wasAdded = false; MVKShaderLibraryCache* slCache = getShaderLibraryCache(shaderModule->getKey()); - MVKShaderLibrary* shLib = slCache->getShaderLibrary(pContext, shaderModule, pipeline, &wasAdded, startTime); + MVKShaderLibrary* shLib = slCache->getShaderLibrary(pContext, shaderModule, pipeline, &wasAdded, pShaderFeedback, startTime); if (wasAdded) { markDirty(); } + else if (pShaderFeedback) { mvkEnableFlags(pShaderFeedback->flags, VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT); } return shLib; } @@ -2428,7 +2839,8 @@ void serialize(Archive & archive, SPIRVToMSLConversionResultInfo& scr) { scr.needsDynamicOffsetBuffer, scr.needsInputThreadgroupMem, scr.needsDispatchBaseBuffer, - scr.needsViewRangeBuffer); + scr.needsViewRangeBuffer, + scr.usesPhysicalStorageBufferAddressesCapability); } } @@ -2483,6 +2895,26 @@ void serialize(Archive & archive, MVKCompressor& comp) { return [_mtlRenderPipelineState retain]; } +#if MVK_XCODE_14 +id MVKRenderPipelineCompiler::newMTLRenderPipelineState(MTLMeshRenderPipelineDescriptor* mtlRPLDesc) { + unique_lock lock(_completionLock); + + compile(lock, ^{ + auto mtlDev = _owner->getMTLDevice(); + @synchronized (mtlDev) { + [mtlDev newRenderPipelineStateWithMeshDescriptor: mtlRPLDesc + options: MTLPipelineOptionNone + completionHandler: ^(id ps, MTLRenderPipelineReflection *refl, NSError* error) { + bool isLate = compileComplete(ps, error); + if (isLate) { destroy(); } + }]; + } + }); + + return [_mtlRenderPipelineState retain]; +} +#endif + bool MVKRenderPipelineCompiler::compileComplete(id mtlRenderPipelineState, NSError* compileError) { lock_guard lock(_completionLock); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h index 37bbf10e6..479965b48 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h @@ -18,10 +18,9 @@ #pragma once -#include "mvk_datatypes.h" -#include "MVKEnvironment.h" -#include "MVKOSExtensions.h" #include "MVKBaseObject.h" +#include "MVKOSExtensions.h" +#include "mvk_datatypes.h" #include #include @@ -149,6 +148,7 @@ typedef struct MVKVkFormatDesc { uint32_t bytesPerBlock; MVKFormatType formatType; VkFormatProperties properties; + VkComponentMapping componentMapping; const char* name; bool hasReportedSubstitution; @@ -159,6 +159,13 @@ typedef struct MVKVkFormatDesc { inline bool vertexIsSupported() const { return (mtlVertexFormat != MTLVertexFormatInvalid); }; inline bool vertexIsSupportedOrSubstitutable() const { return vertexIsSupported() || (mtlVertexFormatSubstitute != MTLVertexFormatInvalid); }; + + bool needsSwizzle() const { + return componentMapping.r != VK_COMPONENT_SWIZZLE_IDENTITY || + componentMapping.g != VK_COMPONENT_SWIZZLE_IDENTITY || + componentMapping.b != VK_COMPONENT_SWIZZLE_IDENTITY || + componentMapping.a != VK_COMPONENT_SWIZZLE_IDENTITY; + } } MVKVkFormatDesc; /** Describes the properties of a MTLPixelFormat or MTLVertexFormat. */ @@ -321,6 +328,21 @@ class MVKPixelFormats : public MVKBaseObject { */ size_t getBytesPerLayer(MTLPixelFormat mtlFormat, size_t bytesPerRow, uint32_t texelRowsPerLayer); + /** Returns whether or not the specified Vulkan format requires swizzling to use with Metal. */ + bool needsSwizzle(VkFormat vkFormat); + + /** Returns any VkComponentMapping needed to use the specified Vulkan format. */ + VkComponentMapping getVkComponentMapping(VkFormat vkFormat); + + /** + * Returns the inverse of the VkComponentMapping needed to use the specified Vulkan format. + * If the original mapping is not a one-to-one function, the behaviour is undefined. + */ + VkComponentMapping getInverseComponentMapping(VkFormat vkFormat); + + /** Returns any MTLTextureSwizzleChannels needed to use the specified Vulkan format. */ + MTLTextureSwizzleChannels getMTLTextureSwizzleChannels(VkFormat vkFormat); + /** Returns the default properties for the specified Vulkan format. */ VkFormatProperties& getVkFormatProperties(VkFormat vkFormat); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm index 39a2ad8f0..3044f66d9 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm @@ -109,24 +109,26 @@ #endif #if MVK_IOS_OR_TVOS -# define MTLPixelFormatDepth24Unorm_Stencil8 MTLPixelFormatInvalid -# define MTLPixelFormatX24_Stencil8 MTLPixelFormatInvalid -# define MTLPixelFormatBC1_RGBA MTLPixelFormatInvalid -# define MTLPixelFormatBC1_RGBA_sRGB MTLPixelFormatInvalid -# define MTLPixelFormatBC2_RGBA MTLPixelFormatInvalid -# define MTLPixelFormatBC2_RGBA_sRGB MTLPixelFormatInvalid -# define MTLPixelFormatBC3_RGBA MTLPixelFormatInvalid -# define MTLPixelFormatBC3_RGBA_sRGB MTLPixelFormatInvalid -# define MTLPixelFormatBC4_RUnorm MTLPixelFormatInvalid -# define MTLPixelFormatBC4_RSnorm MTLPixelFormatInvalid -# define MTLPixelFormatBC5_RGUnorm MTLPixelFormatInvalid -# define MTLPixelFormatBC5_RGSnorm MTLPixelFormatInvalid -# define MTLPixelFormatBC6H_RGBUfloat MTLPixelFormatInvalid -# define MTLPixelFormatBC6H_RGBFloat MTLPixelFormatInvalid -# define MTLPixelFormatBC7_RGBAUnorm MTLPixelFormatInvalid -# define MTLPixelFormatBC7_RGBAUnorm_sRGB MTLPixelFormatInvalid +# if !MVK_XCODE_14_3 // iOS/tvOS 16.4 +# define MTLPixelFormatBC1_RGBA MTLPixelFormatInvalid +# define MTLPixelFormatBC1_RGBA_sRGB MTLPixelFormatInvalid +# define MTLPixelFormatBC2_RGBA MTLPixelFormatInvalid +# define MTLPixelFormatBC2_RGBA_sRGB MTLPixelFormatInvalid +# define MTLPixelFormatBC3_RGBA MTLPixelFormatInvalid +# define MTLPixelFormatBC3_RGBA_sRGB MTLPixelFormatInvalid +# define MTLPixelFormatBC4_RUnorm MTLPixelFormatInvalid +# define MTLPixelFormatBC4_RSnorm MTLPixelFormatInvalid +# define MTLPixelFormatBC5_RGUnorm MTLPixelFormatInvalid +# define MTLPixelFormatBC5_RGSnorm MTLPixelFormatInvalid +# define MTLPixelFormatBC6H_RGBUfloat MTLPixelFormatInvalid +# define MTLPixelFormatBC6H_RGBFloat MTLPixelFormatInvalid +# define MTLPixelFormatBC7_RGBAUnorm MTLPixelFormatInvalid +# define MTLPixelFormatBC7_RGBAUnorm_sRGB MTLPixelFormatInvalid +# endif # define MTLPixelFormatDepth16Unorm_Stencil8 MTLPixelFormatDepth32Float_Stencil8 +# define MTLPixelFormatDepth24Unorm_Stencil8 MTLPixelFormatInvalid +# define MTLPixelFormatX24_Stencil8 MTLPixelFormatInvalid #endif #if MVK_TVOS @@ -375,6 +377,44 @@ return mvkCeilingDivide(texelRowsPerLayer, getVkFormatDesc(mtlFormat).blockTexelSize.height) * bytesPerRow; } +bool MVKPixelFormats::needsSwizzle(VkFormat vkFormat) { + return getVkFormatDesc(vkFormat).needsSwizzle(); +} + +VkComponentMapping MVKPixelFormats::getVkComponentMapping(VkFormat vkFormat) { + return getVkFormatDesc(vkFormat).componentMapping; +} + +VkComponentMapping MVKPixelFormats::getInverseComponentMapping(VkFormat vkFormat) { +#define INVERT_SWIZZLE(x, X, Y) \ + case VK_COMPONENT_SWIZZLE_##X: \ + inverse.x = VK_COMPONENT_SWIZZLE_##Y; \ + break +#define INVERT_MAPPING(y, Y) \ + switch (mapping.y) { \ + case VK_COMPONENT_SWIZZLE_IDENTITY: \ + inverse.y = VK_COMPONENT_SWIZZLE_IDENTITY; \ + break; \ + INVERT_SWIZZLE(r, R, Y); \ + INVERT_SWIZZLE(g, G, Y); \ + INVERT_SWIZZLE(b, B, Y); \ + INVERT_SWIZZLE(a, A, Y); \ + default: break; \ + } + VkComponentMapping mapping = getVkComponentMapping(vkFormat), inverse; + INVERT_MAPPING(r, R) + INVERT_MAPPING(g, G) + INVERT_MAPPING(b, B) + INVERT_MAPPING(a, A) + return inverse; +#undef INVERT_MAPPING +#undef INVERT_SWIZZLE +} + +MTLTextureSwizzleChannels MVKPixelFormats::getMTLTextureSwizzleChannels(VkFormat vkFormat) { + return mvkMTLTextureSwizzleChannelsFromVkComponentMapping(getVkComponentMapping(vkFormat)); +} + VkFormatProperties& MVKPixelFormats::getVkFormatProperties(VkFormat vkFormat) { return getVkFormatDesc(vkFormat).properties; } @@ -462,13 +502,18 @@ MTLClearColor MVKPixelFormats::getMTLClearColor(VkClearValue vkClearValue, VkFormat vkFormat) { MTLClearColor mtlClr; + // The VkComponentMapping (and its MTLTextureSwizzleChannels equivalent) define the *sources* + // for the texture color components for reading. Since we're *writing* to the texture, + // we need to *invert* the mapping. + // n.b. Bad things might happen if the original swizzle isn't one-to-one! + VkComponentMapping inverseMap = getInverseComponentMapping(vkFormat); switch (getFormatType(vkFormat)) { case kMVKFormatColorHalf: - case kMVKFormatColorFloat: - mtlClr.red = vkClearValue.color.float32[0]; - mtlClr.green = vkClearValue.color.float32[1]; - mtlClr.blue = vkClearValue.color.float32[2]; - mtlClr.alpha = vkClearValue.color.float32[3]; + case kMVKFormatColorFloat: { + mtlClr.red = mvkVkClearColorFloatValueFromVkComponentSwizzle(vkClearValue.color.float32, 0, inverseMap.r); + mtlClr.green = mvkVkClearColorFloatValueFromVkComponentSwizzle(vkClearValue.color.float32, 1, inverseMap.g); + mtlClr.blue = mvkVkClearColorFloatValueFromVkComponentSwizzle(vkClearValue.color.float32, 2, inverseMap.b); + mtlClr.alpha = mvkVkClearColorFloatValueFromVkComponentSwizzle(vkClearValue.color.float32, 3, inverseMap.a); if (_physicalDevice && _physicalDevice->getMetalFeatures()->clearColorFloatRounding == MVK_FLOAT_ROUNDING_DOWN) { // For normalized formats, increment the clear value by half the ULP @@ -484,6 +529,8 @@ #define OFFSET_SNORM(COLOR, BIT_WIDTH) OFFSET_NORM(-1.0, COLOR, BIT_WIDTH - 1) switch (vkFormat) { case VK_FORMAT_R4G4B4A4_UNORM_PACK16: + case VK_FORMAT_A4R4G4B4_UNORM_PACK16: + case VK_FORMAT_A4B4G4R4_UNORM_PACK16: OFFSET_UNORM(red, 4) OFFSET_UNORM(green, 4) OFFSET_UNORM(blue, 4) @@ -569,21 +616,22 @@ #undef OFFSET_NORM } break; + } case kMVKFormatColorUInt8: case kMVKFormatColorUInt16: case kMVKFormatColorUInt32: - mtlClr.red = vkClearValue.color.uint32[0]; - mtlClr.green = vkClearValue.color.uint32[1]; - mtlClr.blue = vkClearValue.color.uint32[2]; - mtlClr.alpha = vkClearValue.color.uint32[3]; + mtlClr.red = mvkVkClearColorUIntValueFromVkComponentSwizzle(vkClearValue.color.uint32, 0, inverseMap.r); + mtlClr.green = mvkVkClearColorUIntValueFromVkComponentSwizzle(vkClearValue.color.uint32, 1, inverseMap.g); + mtlClr.blue = mvkVkClearColorUIntValueFromVkComponentSwizzle(vkClearValue.color.uint32, 2, inverseMap.b); + mtlClr.alpha = mvkVkClearColorUIntValueFromVkComponentSwizzle(vkClearValue.color.uint32, 3, inverseMap.a); break; case kMVKFormatColorInt8: case kMVKFormatColorInt16: case kMVKFormatColorInt32: - mtlClr.red = vkClearValue.color.int32[0]; - mtlClr.green = vkClearValue.color.int32[1]; - mtlClr.blue = vkClearValue.color.int32[2]; - mtlClr.alpha = vkClearValue.color.int32[3]; + mtlClr.red = mvkVkClearColorIntValueFromVkComponentSwizzle(vkClearValue.color.int32, 0, inverseMap.r); + mtlClr.green = mvkVkClearColorIntValueFromVkComponentSwizzle(vkClearValue.color.int32, 1, inverseMap.g); + mtlClr.blue = mvkVkClearColorIntValueFromVkComponentSwizzle(vkClearValue.color.int32, 2, inverseMap.b); + mtlClr.alpha = mvkVkClearColorIntValueFromVkComponentSwizzle(vkClearValue.color.int32, 3, inverseMap.a); break; default: mtlClr.red = 0.0; @@ -754,16 +802,21 @@ buildVkFormatMaps(); } -#define addVkFormatDescFull(VK_FMT, MTL_FMT, MTL_FMT_ALT, MTL_VTX_FMT, MTL_VTX_FMT_ALT, CSPC, CSCB, BLK_W, BLK_H, BLK_BYTE_CNT, MVK_FMT_TYPE) \ +#define addVkFormatDescFull(VK_FMT, MTL_FMT, MTL_FMT_ALT, MTL_VTX_FMT, MTL_VTX_FMT_ALT, CSPC, CSCB, BLK_W, BLK_H, BLK_BYTE_CNT, MVK_FMT_TYPE, SWIZ_R, SWIZ_G, SWIZ_B, SWIZ_A) \ MVKAssert(fmtIdx < _vkFormatCount, "Attempting to describe %d VkFormats, but only have space for %d. Increase the value of _vkFormatCount", fmtIdx + 1, _vkFormatCount); \ _vkFormatDescriptions[fmtIdx++] = { VK_FORMAT_ ##VK_FMT, MTLPixelFormat ##MTL_FMT, MTLPixelFormat ##MTL_FMT_ALT, MTLVertexFormat ##MTL_VTX_FMT, MTLVertexFormat ##MTL_VTX_FMT_ALT, \ - CSPC, CSCB, { BLK_W, BLK_H }, BLK_BYTE_CNT, kMVKFormat ##MVK_FMT_TYPE, { 0, 0, 0 }, "VK_FORMAT_" #VK_FMT, false } + CSPC, CSCB, { BLK_W, BLK_H }, BLK_BYTE_CNT, kMVKFormat ##MVK_FMT_TYPE, { 0, 0, 0 }, \ + { VK_COMPONENT_SWIZZLE_ ##SWIZ_R, VK_COMPONENT_SWIZZLE_ ##SWIZ_G, VK_COMPONENT_SWIZZLE_ ##SWIZ_B, VK_COMPONENT_SWIZZLE_ ##SWIZ_A }, \ + "VK_FORMAT_" #VK_FMT, false } #define addVkFormatDesc(VK_FMT, MTL_FMT, MTL_FMT_ALT, MTL_VTX_FMT, MTL_VTX_FMT_ALT, BLK_W, BLK_H, BLK_BYTE_CNT, MVK_FMT_TYPE) \ - addVkFormatDescFull(VK_FMT, MTL_FMT, MTL_FMT_ALT, MTL_VTX_FMT, MTL_VTX_FMT_ALT, 0, 0, BLK_W, BLK_H, BLK_BYTE_CNT, MVK_FMT_TYPE) + addVkFormatDescFull(VK_FMT, MTL_FMT, MTL_FMT_ALT, MTL_VTX_FMT, MTL_VTX_FMT_ALT, 0, 0, BLK_W, BLK_H, BLK_BYTE_CNT, MVK_FMT_TYPE, IDENTITY, IDENTITY, IDENTITY, IDENTITY) + +#define addVkFormatDescSwizzled(VK_FMT, MTL_FMT, MTL_FMT_ALT, MTL_VTX_FMT, MTL_VTX_FMT_ALT, BLK_W, BLK_H, BLK_BYTE_CNT, MVK_FMT_TYPE, SWIZ_R, SWIZ_G, SWIZ_B, SWIZ_A) \ + addVkFormatDescFull(VK_FMT, MTL_FMT, MTL_FMT_ALT, MTL_VTX_FMT, MTL_VTX_FMT_ALT, 0, 0, BLK_W, BLK_H, BLK_BYTE_CNT, MVK_FMT_TYPE, SWIZ_R, SWIZ_G, SWIZ_B, SWIZ_A) #define addVkFormatDescChromaSubsampling(VK_FMT, MTL_FMT, CSPC, CSCB, BLK_W, BLK_H, BLK_BYTE_CNT) \ - addVkFormatDescFull(VK_FMT, MTL_FMT, Invalid, Invalid, Invalid, CSPC, CSCB, BLK_W, BLK_H, BLK_BYTE_CNT, ColorFloat) + addVkFormatDescFull(VK_FMT, MTL_FMT, Invalid, Invalid, Invalid, CSPC, CSCB, BLK_W, BLK_H, BLK_BYTE_CNT, ColorFloat, IDENTITY, IDENTITY, IDENTITY, IDENTITY) void MVKPixelFormats::initVkFormatCapabilities() { @@ -779,6 +832,8 @@ addVkFormatDesc( R4G4_UNORM_PACK8, Invalid, Invalid, Invalid, Invalid, 1, 1, 1, ColorFloat ); addVkFormatDesc( R4G4B4A4_UNORM_PACK16, ABGR4Unorm, Invalid, Invalid, Invalid, 1, 1, 2, ColorFloat ); addVkFormatDesc( B4G4R4A4_UNORM_PACK16, Invalid, Invalid, Invalid, Invalid, 1, 1, 2, ColorFloat ); + addVkFormatDescSwizzled( A4R4G4B4_UNORM_PACK16, ABGR4Unorm, Invalid, Invalid, Invalid, 1, 1, 2, ColorFloat, G, B, A, R ); + addVkFormatDescSwizzled( A4B4G4R4_UNORM_PACK16, ABGR4Unorm, Invalid, Invalid, Invalid, 1, 1, 2, ColorFloat, A, B, G, R ); addVkFormatDesc( R5G6B5_UNORM_PACK16, B5G6R5Unorm, Invalid, Invalid, Invalid, 1, 1, 2, ColorFloat ); addVkFormatDesc( B5G6R5_UNORM_PACK16, Invalid, Invalid, Invalid, Invalid, 1, 1, 2, ColorFloat ); @@ -1217,20 +1272,20 @@ addMTLPixelFormatDescSRGB( ASTC_12x12_sRGB, ASTC_12x12, None, None, ASTC_12x12_LDR ); addMTLPixelFormatDesc ( ASTC_12x12_HDR, ASTC_12x12, None, None ); - addMTLPixelFormatDesc ( BC1_RGBA, BC1_RGBA, None, RF ); - addMTLPixelFormatDescSRGB( BC1_RGBA_sRGB, BC1_RGBA, None, RF, BC1_RGBA ); - addMTLPixelFormatDesc ( BC2_RGBA, BC2_RGBA, None, RF ); - addMTLPixelFormatDescSRGB( BC2_RGBA_sRGB, BC2_RGBA, None, RF, BC2_RGBA ); - addMTLPixelFormatDesc ( BC3_RGBA, BC3_RGBA, None, RF ); - addMTLPixelFormatDescSRGB( BC3_RGBA_sRGB, BC3_RGBA, None, RF, BC3_RGBA ); - addMTLPixelFormatDesc ( BC4_RUnorm, BC4_R, None, RF ); - addMTLPixelFormatDesc ( BC4_RSnorm, BC4_R, None, RF ); - addMTLPixelFormatDesc ( BC5_RGUnorm, BC5_RG, None, RF ); - addMTLPixelFormatDesc ( BC5_RGSnorm, BC5_RG, None, RF ); - addMTLPixelFormatDesc ( BC6H_RGBUfloat, BC6H_RGB, None, RF ); - addMTLPixelFormatDesc ( BC6H_RGBFloat, BC6H_RGB, None, RF ); - addMTLPixelFormatDesc ( BC7_RGBAUnorm, BC7_RGBA, None, RF ); - addMTLPixelFormatDescSRGB( BC7_RGBAUnorm_sRGB, BC7_RGBA, None, RF, BC7_RGBAUnorm ); + addMTLPixelFormatDesc ( BC1_RGBA, BC1_RGBA, RF, RF ); + addMTLPixelFormatDescSRGB( BC1_RGBA_sRGB, BC1_RGBA, RF, RF, BC1_RGBA ); + addMTLPixelFormatDesc ( BC2_RGBA, BC2_RGBA, RF, RF ); + addMTLPixelFormatDescSRGB( BC2_RGBA_sRGB, BC2_RGBA, RF, RF, BC2_RGBA ); + addMTLPixelFormatDesc ( BC3_RGBA, BC3_RGBA, RF, RF ); + addMTLPixelFormatDescSRGB( BC3_RGBA_sRGB, BC3_RGBA, RF, RF, BC3_RGBA ); + addMTLPixelFormatDesc ( BC4_RUnorm, BC4_R, RF, RF ); + addMTLPixelFormatDesc ( BC4_RSnorm, BC4_R, RF, RF ); + addMTLPixelFormatDesc ( BC5_RGUnorm, BC5_RG, RF, RF ); + addMTLPixelFormatDesc ( BC5_RGSnorm, BC5_RG, RF, RF ); + addMTLPixelFormatDesc ( BC6H_RGBUfloat, BC6H_RGB, RF, RF ); + addMTLPixelFormatDesc ( BC6H_RGBFloat, BC6H_RGB, RF, RF ); + addMTLPixelFormatDesc ( BC7_RGBAUnorm, BC7_RGBA, RF, RF ); + addMTLPixelFormatDescSRGB( BC7_RGBAUnorm_sRGB, BC7_RGBA, RF, RF, BC7_RGBAUnorm ); // YUV pixel formats addMTLPixelFormatDesc ( GBGR422, None, RF, RF ); @@ -1450,10 +1505,10 @@ // Mac Catalyst does not support feature sets, so we redefine them to GPU families in MVKDevice.h. #if MVK_MACCAT #define addFeatSetMTLPixFmtCaps(FEAT_SET, MTL_FMT, CAPS) \ - addMTLPixelFormatCapabilities(mtlDevice, MTLFeatureSet_ ##FEAT_SET, 10.16, MTLPixelFormat ##MTL_FMT, kMVKMTLFmtCaps ##CAPS) + addMTLPixelFormatCapabilities(mtlDevice, MTLFeatureSet_ ##FEAT_SET, 11.0, MTLPixelFormat ##MTL_FMT, kMVKMTLFmtCaps ##CAPS) #define addFeatSetMTLVtxFmtCaps(FEAT_SET, MTL_FMT, CAPS) \ - addMTLVertexFormatCapabilities(mtlDevice, MTLFeatureSet_ ##FEAT_SET, 10.16, MTLVertexFormat ##MTL_FMT, kMVKMTLFmtCaps ##CAPS) + addMTLVertexFormatCapabilities(mtlDevice, MTLFeatureSet_ ##FEAT_SET, 11.0, MTLVertexFormat ##MTL_FMT, kMVKMTLFmtCaps ##CAPS) #else #define addFeatSetMTLPixFmtCaps(FEAT_SET, MTL_FMT, CAPS) \ @@ -1477,20 +1532,23 @@ addMTLVertexFormatCapabilities(mtlDevice, MTLGPUFamily ##GPU_FAM, OS_VER, MTLVertexFormat ##MTL_FMT, kMVKMTLFmtCaps ##CAPS) // Modifies the format capability tables based on the capabilities of the specific MTLDevice -#if MVK_MACOS void MVKPixelFormats::modifyMTLFormatCapabilities(id mtlDevice) { - - addFeatSetMTLPixFmtCaps( macOS_GPUFamily1_v1, R32Uint, Atomic ); - addFeatSetMTLPixFmtCaps( macOS_GPUFamily1_v1, R32Sint, Atomic ); - - if (mtlDevice.isDepth24Stencil8PixelFormatSupported) { - addFeatSetMTLPixFmtCaps( macOS_GPUFamily1_v1, Depth24Unorm_Stencil8, DRFMR ); + if ( !mvkSupportsBCTextureCompression(mtlDevice) ) { + disableAllMTLPixFmtCaps( BC1_RGBA ); + disableAllMTLPixFmtCaps( BC1_RGBA_sRGB ); + disableAllMTLPixFmtCaps( BC2_RGBA ); + disableAllMTLPixFmtCaps( BC2_RGBA_sRGB ); + disableAllMTLPixFmtCaps( BC3_RGBA ); + disableAllMTLPixFmtCaps( BC3_RGBA_sRGB ); + disableAllMTLPixFmtCaps( BC4_RUnorm ); + disableAllMTLPixFmtCaps( BC4_RSnorm ); + disableAllMTLPixFmtCaps( BC5_RGUnorm ); + disableAllMTLPixFmtCaps( BC5_RGSnorm ); + disableAllMTLPixFmtCaps( BC6H_RGBUfloat ); + disableAllMTLPixFmtCaps( BC6H_RGBFloat ); + disableAllMTLPixFmtCaps( BC7_RGBAUnorm ); + disableAllMTLPixFmtCaps( BC7_RGBAUnorm_sRGB ); } - - addFeatSetMTLPixFmtCaps( macOS_GPUFamily1_v2, Depth16Unorm, DRFMR ); - - addFeatSetMTLPixFmtCaps( macOS_GPUFamily1_v3, BGR10A2Unorm, RFCMRB ); - #if MVK_XCODE_12 if ([mtlDevice respondsToSelector: @selector(supports32BitMSAA)] && !mtlDevice.supports32BitMSAA) { @@ -1522,104 +1580,101 @@ disableMTLPixFmtCaps( RG32Float, Filter ); disableMTLPixFmtCaps( RGBA32Float, Filter ); } +#endif - if ( !mvkSupportsBCTextureCompression(mtlDevice) ) { - disableAllMTLPixFmtCaps( BC1_RGBA ); - disableAllMTLPixFmtCaps( BC1_RGBA_sRGB ); - disableAllMTLPixFmtCaps( BC2_RGBA ); - disableAllMTLPixFmtCaps( BC2_RGBA_sRGB ); - disableAllMTLPixFmtCaps( BC3_RGBA ); - disableAllMTLPixFmtCaps( BC3_RGBA_sRGB ); - disableAllMTLPixFmtCaps( BC4_RUnorm ); - disableAllMTLPixFmtCaps( BC4_RSnorm ); - disableAllMTLPixFmtCaps( BC5_RGUnorm ); - disableAllMTLPixFmtCaps( BC5_RGSnorm ); - disableAllMTLPixFmtCaps( BC6H_RGBUfloat ); - disableAllMTLPixFmtCaps( BC6H_RGBFloat ); - disableAllMTLPixFmtCaps( BC7_RGBAUnorm ); - disableAllMTLPixFmtCaps( BC7_RGBAUnorm_sRGB ); +#if MVK_MACOS + addFeatSetMTLPixFmtCaps( macOS_GPUFamily1_v1, R32Uint, Atomic ); + addFeatSetMTLPixFmtCaps( macOS_GPUFamily1_v1, R32Sint, Atomic ); + + if (mtlDevice.isDepth24Stencil8PixelFormatSupported) { + addFeatSetMTLPixFmtCaps( macOS_GPUFamily1_v1, Depth24Unorm_Stencil8, DRFMR ); } - addGPUOSMTLPixFmtCaps( Apple5, 10.16, R8Unorm_sRGB, All ); + addFeatSetMTLPixFmtCaps( macOS_GPUFamily1_v2, Depth16Unorm, DRFMR ); + + addFeatSetMTLPixFmtCaps( macOS_GPUFamily1_v3, BGR10A2Unorm, RFCMRB ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, RG8Unorm_sRGB, All ); +#if MVK_XCODE_12 + addGPUOSMTLPixFmtCaps( Apple5, 11.0, R8Unorm_sRGB, All ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, B5G6R5Unorm, RFCMRB ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, A1BGR5Unorm, RFCMRB ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ABGR4Unorm, RFCMRB ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, BGR5A1Unorm, RFCMRB ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, RG8Unorm_sRGB, All ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, RGBA8Unorm_sRGB, All ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, BGRA8Unorm_sRGB, All ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, B5G6R5Unorm, RFCMRB ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, A1BGR5Unorm, RFCMRB ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ABGR4Unorm, RFCMRB ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, BGR5A1Unorm, RFCMRB ); + + addGPUOSMTLPixFmtCaps( Apple5, 11.0, RGBA8Unorm_sRGB, All ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, BGRA8Unorm_sRGB, All ); // Blending is actually supported for this format, but format channels cannot be individually write-enabled during blending. // Disabling blending is the least-intrusive way to handle this in a Vulkan-friendly way. - addGPUOSMTLPixFmtCaps( Apple5, 10.16, RGB9E5Float, All ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, RGB9E5Float, All ); disableMTLPixFmtCaps ( RGB9E5Float, Blend); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, PVRTC_RGBA_2BPP, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, PVRTC_RGBA_2BPP_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, PVRTC_RGBA_4BPP, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, PVRTC_RGBA_4BPP_sRGB, RF ); - - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ETC2_RGB8, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ETC2_RGB8_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ETC2_RGB8A1, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ETC2_RGB8A1_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, EAC_RGBA8, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, EAC_RGBA8_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, EAC_R11Unorm, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, EAC_R11Snorm, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, EAC_RG11Unorm, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, EAC_RG11Snorm, RF ); - - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_4x4_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_4x4_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 10.16, ASTC_4x4_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_5x4_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_5x4_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 10.16, ASTC_5x4_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_5x5_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_5x5_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 10.16, ASTC_5x5_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_6x5_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_6x5_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 10.16, ASTC_6x5_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_6x6_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_6x6_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 10.16, ASTC_6x6_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_8x5_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_8x5_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 10.16, ASTC_8x5_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_8x6_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_8x6_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 10.16, ASTC_8x6_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_8x8_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_8x8_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 10.16, ASTC_8x8_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_10x5_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_10x5_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 10.16, ASTC_10x5_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_10x6_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_10x6_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 10.16, ASTC_10x6_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_10x8_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_10x8_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 10.16, ASTC_10x8_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_10x10_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_10x10_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 10.16, ASTC_10x10_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_12x10_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_12x10_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 10.16, ASTC_12x10_HDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_12x12_LDR, RF ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, ASTC_12x12_sRGB, RF ); - addGPUOSMTLPixFmtCaps( Apple6, 10.16, ASTC_12x12_HDR, RF ); - - addGPUOSMTLPixFmtCaps( Apple5, 10.16, BGRA10_XR, All ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, BGRA10_XR_sRGB, All ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, BGR10_XR, All ); - addGPUOSMTLPixFmtCaps( Apple5, 10.16, BGR10_XR_sRGB, All ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, PVRTC_RGBA_2BPP, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, PVRTC_RGBA_2BPP_sRGB, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, PVRTC_RGBA_4BPP, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, PVRTC_RGBA_4BPP_sRGB, RF ); + + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ETC2_RGB8, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ETC2_RGB8_sRGB, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ETC2_RGB8A1, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ETC2_RGB8A1_sRGB, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, EAC_RGBA8, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, EAC_RGBA8_sRGB, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, EAC_R11Unorm, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, EAC_R11Snorm, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, EAC_RG11Unorm, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, EAC_RG11Snorm, RF ); + + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_4x4_LDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_4x4_sRGB, RF ); + addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_4x4_HDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_5x4_LDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_5x4_sRGB, RF ); + addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_5x4_HDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_5x5_LDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_5x5_sRGB, RF ); + addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_5x5_HDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_6x5_LDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_6x5_sRGB, RF ); + addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_6x5_HDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_6x6_LDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_6x6_sRGB, RF ); + addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_6x6_HDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_8x5_LDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_8x5_sRGB, RF ); + addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_8x5_HDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_8x6_LDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_8x6_sRGB, RF ); + addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_8x6_HDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_8x8_LDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_8x8_sRGB, RF ); + addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_8x8_HDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_10x5_LDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_10x5_sRGB, RF ); + addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_10x5_HDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_10x6_LDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_10x6_sRGB, RF ); + addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_10x6_HDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_10x8_LDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_10x8_sRGB, RF ); + addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_10x8_HDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_10x10_LDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_10x10_sRGB, RF ); + addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_10x10_HDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_12x10_LDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_12x10_sRGB, RF ); + addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_12x10_HDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_12x12_LDR, RF ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, ASTC_12x12_sRGB, RF ); + addGPUOSMTLPixFmtCaps( Apple6, 11.0, ASTC_12x12_HDR, RF ); + + addGPUOSMTLPixFmtCaps( Apple5, 11.0, BGRA10_XR, All ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, BGRA10_XR_sRGB, All ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, BGR10_XR, All ); + addGPUOSMTLPixFmtCaps( Apple5, 11.0, BGR10_XR_sRGB, All ); #endif addFeatSetMTLVtxFmtCaps( macOS_GPUFamily1_v3, UCharNormalized, Vertex ); @@ -1632,11 +1687,9 @@ addFeatSetMTLVtxFmtCaps( macOS_GPUFamily1_v3, Short, Vertex ); addFeatSetMTLVtxFmtCaps( macOS_GPUFamily1_v3, Half, Vertex ); addFeatSetMTLVtxFmtCaps( macOS_GPUFamily1_v3, UChar4Normalized_BGRA, Vertex ); -} #endif #if MVK_TVOS -void MVKPixelFormats::modifyMTLFormatCapabilities(id mtlDevice) { addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v2, R8Unorm_sRGB, All ); addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, R8Unorm_sRGB, All ); @@ -1675,43 +1728,43 @@ addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, RGBA32Sint, RWC ); addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, RGBA32Float, RWC ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_4x4_LDR, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_4x4_sRGB, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_5x4_LDR, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_5x4_sRGB, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_5x5_LDR, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_5x5_sRGB, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_6x5_LDR, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_6x5_sRGB, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_6x6_LDR, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_6x6_sRGB, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_8x5_LDR, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_8x5_sRGB, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_8x6_LDR, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_8x6_sRGB, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_8x8_LDR, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_8x8_sRGB, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_10x5_LDR, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_10x5_sRGB, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_10x6_LDR, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_10x6_sRGB, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_10x8_LDR, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_10x8_sRGB, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_10x10_LDR, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_10x10_sRGB, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_12x10_LDR, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_12x10_sRGB, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_12x12_LDR, RF ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily1_v1, ASTC_12x12_sRGB, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_4x4_LDR, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_4x4_sRGB, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_5x4_LDR, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_5x4_sRGB, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_5x5_LDR, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_5x5_sRGB, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_6x5_LDR, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_6x5_sRGB, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_6x6_LDR, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_6x6_sRGB, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_8x5_LDR, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_8x5_sRGB, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_8x6_LDR, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_8x6_sRGB, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_8x8_LDR, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_8x8_sRGB, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_10x5_LDR, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_10x5_sRGB, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_10x6_LDR, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_10x6_sRGB, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_10x8_LDR, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_10x8_sRGB, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_10x10_LDR, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_10x10_sRGB, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_12x10_LDR, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_12x10_sRGB, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_12x12_LDR, RF ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily1_v1, ASTC_12x12_sRGB, RF ); addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, Depth32Float, DRMR ); addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, Depth32Float_Stencil8, DRMR ); addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, Stencil8, DRMR ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily2_v1, BGRA10_XR, All ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily2_v1, BGRA10_XR_sRGB, All ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily2_v1, BGR10_XR, All ); - addFeatSetMTLPixFmtCaps(tvOS_GPUFamily2_v1, BGR10_XR_sRGB, All ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, BGRA10_XR, All ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, BGRA10_XR_sRGB, All ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, BGR10_XR, All ); + addFeatSetMTLPixFmtCaps( tvOS_GPUFamily2_v1, BGR10_XR_sRGB, All ); addGPUOSMTLPixFmtCaps( Apple1, 13.0, Depth16Unorm, DRFM ); addGPUOSMTLPixFmtCaps( Apple3, 13.0, Depth16Unorm, DRFMR ); @@ -1732,53 +1785,51 @@ #if MVK_OS_SIMULATOR if (!([mtlDevice respondsToSelector: @selector(supportsFamily:)] && [mtlDevice supportsFamily: MTLGPUFamilyApple5])) { - disableAllMTLPixFmtCaps(R8Unorm_sRGB); - disableAllMTLPixFmtCaps(RG8Unorm_sRGB); - disableAllMTLPixFmtCaps(B5G6R5Unorm); - disableAllMTLPixFmtCaps(A1BGR5Unorm); - disableAllMTLPixFmtCaps(ABGR4Unorm); - disableAllMTLPixFmtCaps(BGR5A1Unorm); - - disableAllMTLPixFmtCaps(BGRA10_XR); - disableAllMTLPixFmtCaps(BGRA10_XR_sRGB); - disableAllMTLPixFmtCaps(BGR10_XR); - disableAllMTLPixFmtCaps(BGR10_XR_sRGB); - - disableAllMTLPixFmtCaps(GBGR422); - disableAllMTLPixFmtCaps(BGRG422); - - disableMTLPixFmtCaps(RGB9E5Float, ColorAtt); - - disableMTLPixFmtCaps(R8Unorm_sRGB, Write); - disableMTLPixFmtCaps(RG8Unorm_sRGB, Write); - disableMTLPixFmtCaps(RGBA8Unorm_sRGB, Write); - disableMTLPixFmtCaps(BGRA8Unorm_sRGB, Write); - disableMTLPixFmtCaps(PVRTC_RGBA_2BPP_sRGB, Write); - disableMTLPixFmtCaps(PVRTC_RGBA_4BPP_sRGB, Write); - disableMTLPixFmtCaps(ETC2_RGB8_sRGB, Write); - disableMTLPixFmtCaps(ETC2_RGB8A1_sRGB, Write); - disableMTLPixFmtCaps(EAC_RGBA8_sRGB, Write); - disableMTLPixFmtCaps(ASTC_4x4_sRGB, Write); - disableMTLPixFmtCaps(ASTC_5x4_sRGB, Write); - disableMTLPixFmtCaps(ASTC_5x5_sRGB, Write); - disableMTLPixFmtCaps(ASTC_6x5_sRGB, Write); - disableMTLPixFmtCaps(ASTC_6x6_sRGB, Write); - disableMTLPixFmtCaps(ASTC_8x5_sRGB, Write); - disableMTLPixFmtCaps(ASTC_8x6_sRGB, Write); - disableMTLPixFmtCaps(ASTC_8x8_sRGB, Write); - disableMTLPixFmtCaps(ASTC_10x5_sRGB, Write); - disableMTLPixFmtCaps(ASTC_10x6_sRGB, Write); - disableMTLPixFmtCaps(ASTC_10x8_sRGB, Write); - disableMTLPixFmtCaps(ASTC_10x10_sRGB, Write); - disableMTLPixFmtCaps(ASTC_12x10_sRGB, Write); - disableMTLPixFmtCaps(ASTC_12x12_sRGB, Write); + disableAllMTLPixFmtCaps( R8Unorm_sRGB ); + disableAllMTLPixFmtCaps( RG8Unorm_sRGB ); + disableAllMTLPixFmtCaps( B5G6R5Unorm ); + disableAllMTLPixFmtCaps( A1BGR5Unorm ); + disableAllMTLPixFmtCaps( ABGR4Unorm ); + disableAllMTLPixFmtCaps( BGR5A1Unorm ); + + disableAllMTLPixFmtCaps( BGRA10_XR ); + disableAllMTLPixFmtCaps( BGRA10_XR_sRGB ); + disableAllMTLPixFmtCaps( BGR10_XR ); + disableAllMTLPixFmtCaps( BGR10_XR_sRGB ); + + disableAllMTLPixFmtCaps( GBGR422 ); + disableAllMTLPixFmtCaps( BGRG422 ); + + disableMTLPixFmtCaps( RGB9E5Float, ColorAtt ); + + disableMTLPixFmtCaps( R8Unorm_sRGB, Write ); + disableMTLPixFmtCaps( RG8Unorm_sRGB, Write ); + disableMTLPixFmtCaps( RGBA8Unorm_sRGB, Write ); + disableMTLPixFmtCaps( BGRA8Unorm_sRGB, Write ); + disableMTLPixFmtCaps( PVRTC_RGBA_2BPP_sRGB, Write ); + disableMTLPixFmtCaps( PVRTC_RGBA_4BPP_sRGB, Write ); + disableMTLPixFmtCaps( ETC2_RGB8_sRGB, Write ); + disableMTLPixFmtCaps( ETC2_RGB8A1_sRGB, Write ); + disableMTLPixFmtCaps( EAC_RGBA8_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_4x4_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_5x4_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_5x5_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_6x5_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_6x6_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_8x5_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_8x6_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_8x8_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_10x5_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_10x6_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_10x8_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_10x10_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_12x10_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_12x12_sRGB, Write ); } #endif -} #endif #if MVK_IOS -void MVKPixelFormats::modifyMTLFormatCapabilities(id mtlDevice) { addFeatSetMTLPixFmtCaps( iOS_GPUFamily2_v3, R8Unorm_sRGB, All ); addFeatSetMTLPixFmtCaps( iOS_GPUFamily3_v1, R8Unorm_sRGB, All ); @@ -1891,50 +1942,50 @@ #if MVK_OS_SIMULATOR if (!([mtlDevice respondsToSelector: @selector(supportsFamily:)] && [mtlDevice supportsFamily: MTLGPUFamilyApple5])) { - disableAllMTLPixFmtCaps(R8Unorm_sRGB); - disableAllMTLPixFmtCaps(RG8Unorm_sRGB); - disableAllMTLPixFmtCaps(B5G6R5Unorm); - disableAllMTLPixFmtCaps(A1BGR5Unorm); - disableAllMTLPixFmtCaps(ABGR4Unorm); - disableAllMTLPixFmtCaps(BGR5A1Unorm); - - disableAllMTLPixFmtCaps(BGRA10_XR); - disableAllMTLPixFmtCaps(BGRA10_XR_sRGB); - disableAllMTLPixFmtCaps(BGR10_XR); - disableAllMTLPixFmtCaps(BGR10_XR_sRGB); - - disableAllMTLPixFmtCaps(GBGR422); - disableAllMTLPixFmtCaps(BGRG422); - - disableMTLPixFmtCaps(RGB9E5Float, ColorAtt); - - disableMTLPixFmtCaps(R8Unorm_sRGB, Write); - disableMTLPixFmtCaps(RG8Unorm_sRGB, Write); - disableMTLPixFmtCaps(RGBA8Unorm_sRGB, Write); - disableMTLPixFmtCaps(BGRA8Unorm_sRGB, Write); - disableMTLPixFmtCaps(PVRTC_RGBA_2BPP_sRGB, Write); - disableMTLPixFmtCaps(PVRTC_RGBA_4BPP_sRGB, Write); - disableMTLPixFmtCaps(ETC2_RGB8_sRGB, Write); - disableMTLPixFmtCaps(ETC2_RGB8A1_sRGB, Write); - disableMTLPixFmtCaps(EAC_RGBA8_sRGB, Write); - disableMTLPixFmtCaps(ASTC_4x4_sRGB, Write); - disableMTLPixFmtCaps(ASTC_5x4_sRGB, Write); - disableMTLPixFmtCaps(ASTC_5x5_sRGB, Write); - disableMTLPixFmtCaps(ASTC_6x5_sRGB, Write); - disableMTLPixFmtCaps(ASTC_6x6_sRGB, Write); - disableMTLPixFmtCaps(ASTC_8x5_sRGB, Write); - disableMTLPixFmtCaps(ASTC_8x6_sRGB, Write); - disableMTLPixFmtCaps(ASTC_8x8_sRGB, Write); - disableMTLPixFmtCaps(ASTC_10x5_sRGB, Write); - disableMTLPixFmtCaps(ASTC_10x6_sRGB, Write); - disableMTLPixFmtCaps(ASTC_10x8_sRGB, Write); - disableMTLPixFmtCaps(ASTC_10x10_sRGB, Write); - disableMTLPixFmtCaps(ASTC_12x10_sRGB, Write); - disableMTLPixFmtCaps(ASTC_12x12_sRGB, Write); + disableAllMTLPixFmtCaps( R8Unorm_sRGB ); + disableAllMTLPixFmtCaps( RG8Unorm_sRGB ); + disableAllMTLPixFmtCaps( B5G6R5Unorm ); + disableAllMTLPixFmtCaps( A1BGR5Unorm ); + disableAllMTLPixFmtCaps( ABGR4Unorm ); + disableAllMTLPixFmtCaps( BGR5A1Unorm ); + + disableAllMTLPixFmtCaps( BGRA10_XR ); + disableAllMTLPixFmtCaps( BGRA10_XR_sRGB ); + disableAllMTLPixFmtCaps( BGR10_XR ); + disableAllMTLPixFmtCaps( BGR10_XR_sRGB ); + + disableAllMTLPixFmtCaps( GBGR422 ); + disableAllMTLPixFmtCaps( BGRG422 ); + + disableMTLPixFmtCaps( RGB9E5Float, ColorAtt ); + + disableMTLPixFmtCaps( R8Unorm_sRGB, Write ); + disableMTLPixFmtCaps( RG8Unorm_sRGB, Write ); + disableMTLPixFmtCaps( RGBA8Unorm_sRGB, Write ); + disableMTLPixFmtCaps( BGRA8Unorm_sRGB, Write ); + disableMTLPixFmtCaps( PVRTC_RGBA_2BPP_sRGB, Write ); + disableMTLPixFmtCaps( PVRTC_RGBA_4BPP_sRGB, Write ); + disableMTLPixFmtCaps( ETC2_RGB8_sRGB, Write ); + disableMTLPixFmtCaps( ETC2_RGB8A1_sRGB, Write ); + disableMTLPixFmtCaps( EAC_RGBA8_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_4x4_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_5x4_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_5x5_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_6x5_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_6x6_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_8x5_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_8x6_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_8x8_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_10x5_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_10x6_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_10x8_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_10x10_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_12x10_sRGB, Write ); + disableMTLPixFmtCaps( ASTC_12x12_sRGB, Write ); } #endif -} #endif +} #undef addFeatSetMTLPixFmtCaps #undef addGPUOSMTLPixFmtCaps @@ -1964,6 +2015,23 @@ _vkFormatDescIndicesByVkFormatsExt[vkFmt] = fmtIdx; } + if (vkDesc.needsSwizzle()) { + if (_physicalDevice) { + id mtlDev = _physicalDevice->getMTLDevice(); +#if MVK_MACCAT + bool supportsNativeTextureSwizzle = [mtlDev supportsFamily: MTLGPUFamilyMacCatalyst2]; +#elif MVK_MACOS + bool supportsNativeTextureSwizzle = mvkOSVersionIsAtLeast(10.15) && [mtlDev supportsFeatureSet: MTLFeatureSet_macOS_GPUFamily2_v1]; +#endif +#if MVK_IOS || MVK_TVOS + bool supportsNativeTextureSwizzle = mtlDev && mvkOSVersionIsAtLeast(13.0); +#endif + if (!supportsNativeTextureSwizzle && !mvkConfig().fullImageViewSwizzle) { + vkDesc.mtlPixelFormat = vkDesc.mtlPixelFormatSubstitute = MTLPixelFormatInvalid; + } + } + } + // Populate the back reference from the Metal formats to the Vulkan format. // Validate the corresponding Metal formats for the platform, and clear them // in the Vulkan format if not supported. @@ -2080,6 +2148,13 @@ mvkDisableFlags(vkProps.optimalTilingFeatures, (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT)); } + // These formats require swizzling. In order to support rendering, we'll have to swizzle + // in the fragment shader, but that hasn't been implemented yet. + if (vkDesc.needsSwizzle()) { + mvkDisableFlags(vkProps.optimalTilingFeatures, (kMVKVkFormatFeatureFlagsTexColorAtt | + kMVKVkFormatFeatureFlagsTexBlend)); + } + // Linear tiling is not available to depth/stencil or compressed formats. // GBGR and BGRG formats also do not support linear tiling in Metal. if ( !(vkDesc.formatType == kMVKFormatDepthStencil || vkDesc.formatType == kMVKFormatCompressed || diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.mm b/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.mm index 1f6470063..2e0e13682 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.mm @@ -284,7 +284,7 @@ } id MVKOcclusionQueryPool::encodeComputeCopyResults(MVKCommandEncoder* cmdEncoder, uint32_t firstQuery, uint32_t, uint32_t index) { - id mtlCmdEnc = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseCopyQueryPoolResults); + id mtlCmdEnc = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseCopyQueryPoolResults, true); [mtlCmdEnc setBuffer: getVisibilityResultMTLBuffer() offset: getVisibilityResultOffset(firstQuery) atIndex: index]; return mtlCmdEnc; } @@ -316,7 +316,9 @@ VkDeviceSize newBuffLen = min(reqBuffLen, maxBuffLen); if (reqBuffLen > maxBuffLen) { - reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "vkCreateQueryPool(): Each query pool can support a maximum of %d queries.", uint32_t(newBuffLen / kMVKQuerySlotSizeInBytes)); + reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, + "vkCreateQueryPool(): Each occlusion query pool can support a maximum of %d queries.", + uint32_t(newBuffLen / kMVKQuerySlotSizeInBytes)); } NSUInteger mtlBuffLen = mvkAlignByteCount(newBuffLen, _device->_pMetalFeatures->mtlBufferAlignment); @@ -356,9 +358,9 @@ NSError* err = nil; _mtlCounterBuffer = [getMTLDevice() newCounterSampleBufferWithDescriptor: tsDesc error: &err]; if (err) { - setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, - "Could not create MTLCounterSampleBuffer for query pool of type %s. Reverting to emulated behavior. (Error code %li): %s", - queryTypeName, (long)err.code, err.localizedDescription.UTF8String)); + reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, + "Could not create MTLCounterSampleBuffer of size %llu, for %d queries, in query pool of type %s. Reverting to emulated behavior. (Error code %li): %s", + (VkDeviceSize)pCreateInfo->queryCount * kMVKQuerySlotSizeInBytes, pCreateInfo->queryCount, queryTypeName, (long)err.code, err.localizedDescription.UTF8String); } } }; @@ -432,12 +434,12 @@ destinationBuffer: tempBuff->_mtlBuffer destinationOffset: tempBuff->_offset]; - id mtlCmdEnc = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseCopyQueryPoolResults); + id mtlCmdEnc = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseCopyQueryPoolResults, true); [mtlCmdEnc setBuffer: tempBuff->_mtlBuffer offset: tempBuff->_offset atIndex: index]; return mtlCmdEnc; } else { // We can set the timestamp bytes into the compute encoder. - id mtlCmdEnc = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseCopyQueryPoolResults); + id mtlCmdEnc = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseCopyQueryPoolResults, true); cmdEncoder->setComputeBytes(mtlCmdEnc, &_timestamps[firstQuery], queryCount * _queryElementCount * sizeof(uint64_t), index); return mtlCmdEnc; } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h index 96d77bc18..bcefd2f37 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h @@ -255,11 +255,8 @@ class MVKQueueFullCommandBufferSubmission : public MVKQueueCommandBufferSubmissi protected: void submitCommandBuffers() override; - void finish() override; MVKSmallVector _cmdBuffers; - MTLTimestamp _cpuStart = 0; - MTLTimestamp _gpuStart = 0; }; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm index fc234c010..0ad143072 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm @@ -524,16 +524,9 @@ template void MVKQueueFullCommandBufferSubmission::submitCommandBuffers() { - _queue->getPhysicalDevice()->startTimestampCorrelation(_cpuStart, _gpuStart); for (auto& cb : _cmdBuffers) { cb->submit(this, &_encodingContext); } } -template -void MVKQueueFullCommandBufferSubmission::finish() { - _queue->getPhysicalDevice()->updateTimestampPeriod(_cpuStart, _gpuStart); - MVKQueueCommandBufferSubmission::finish(); -} - #pragma mark - #pragma mark MVKQueuePresentSurfaceSubmission @@ -583,8 +576,12 @@ const VkPresentTimesInfoGOOGLE* pPresentTimesInfo = nullptr; const VkSwapchainPresentFenceInfoEXT* pPresentFenceInfo = nullptr; const VkSwapchainPresentModeInfoEXT* pPresentModeInfo = nullptr; + const VkPresentRegionsKHR* pPresentRegions = nullptr; for (auto* next = (const VkBaseInStructure*)pPresentInfo->pNext; next; next = next->pNext) { switch (next->sType) { + case VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR: + pPresentRegions = (const VkPresentRegionsKHR*) next; + break; case VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_EXT: pPresentFenceInfo = (const VkSwapchainPresentFenceInfoEXT*) next; break; @@ -616,12 +613,16 @@ pFences = pPresentFenceInfo->pFences; MVKAssert(pPresentFenceInfo->swapchainCount == scCnt, "VkSwapchainPresentFenceInfoEXT swapchainCount must match VkPresentInfo swapchainCount."); } + const VkPresentRegionKHR* pRegions = nullptr; + if (pPresentRegions) { + pRegions = pPresentRegions->pRegions; + } VkResult* pSCRslts = pPresentInfo->pResults; _presentInfo.reserve(scCnt); for (uint32_t scIdx = 0; scIdx < scCnt; scIdx++) { MVKSwapchain* mvkSC = (MVKSwapchain*)pPresentInfo->pSwapchains[scIdx]; - MVKImagePresentInfo presentInfo = {}; + MVKImagePresentInfo presentInfo = {}; // Start with everything zeroed presentInfo.presentableImage = mvkSC->getPresentableImage(pPresentInfo->pImageIndices[scIdx]); presentInfo.presentMode = pPresentModes ? pPresentModes[scIdx] : VK_PRESENT_MODE_MAX_ENUM_KHR; presentInfo.fence = pFences ? (MVKFence*)pFences[scIdx] : nullptr; @@ -629,9 +630,8 @@ presentInfo.hasPresentTime = true; presentInfo.presentID = pPresentTimes[scIdx].presentID; presentInfo.desiredPresentTime = pPresentTimes[scIdx].desiredPresentTime; - } else { - presentInfo.hasPresentTime = false; } + mvkSC->setLayerNeedsDisplay(pRegions ? &pRegions[scIdx] : nullptr); _presentInfo.push_back(presentInfo); VkResult scRslt = mvkSC->getSurfaceStatus(); if (pSCRslts) { pSCRslts[scIdx] = scRslt; } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h index 3b88f5b07..534ec018f 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h @@ -54,9 +54,6 @@ class MVKRenderSubpass : public MVKBaseObject { /** Returns whether this subpass has any color attachments. */ bool hasColorAttachments(); - /** Returns whether this subpass has a depth/stencil attachment. */ - bool hasDepthStencilAttachment() { return _depthStencilAttachment.attachment != VK_ATTACHMENT_UNUSED; } - /** Returns the number of color attachments, which may be zero for depth-only rendering. */ uint32_t getColorAttachmentCount() { return uint32_t(_colorAttachments.size()); } @@ -69,8 +66,17 @@ class MVKRenderSubpass : public MVKBaseObject { /** Returns whether or not the color attachment is used as both a color attachment and an input attachment. */ bool isColorAttachmentAlsoInputAttachment(uint32_t colorAttIdx); - /** Returns the format of the depth/stencil attachment. */ - VkFormat getDepthStencilFormat(); + /** Returns whether or not the depth attachment is being used. */ + bool isDepthAttachmentUsed() { return _depthAttachment.attachment != VK_ATTACHMENT_UNUSED; } + + /** Returns whether or not the stencil attachment is being used. */ + bool isStencilAttachmentUsed() { return _stencilAttachment.attachment != VK_ATTACHMENT_UNUSED; } + + /** Return the depth attachment format. */ + VkFormat getDepthFormat(); + + /** Return the stencil attachment format. */ + VkFormat getStencilFormat(); /** Returns the Vulkan sample count of the attachments used in this subpass. */ VkSampleCountFlagBits getSampleCount(); @@ -146,10 +152,11 @@ class MVKRenderSubpass : public MVKBaseObject { MVKRenderSubpass(MVKRenderPass* renderPass, const VkSubpassDescription2* pCreateInfo); -private: + MVKRenderSubpass(MVKRenderPass* renderPass, const VkRenderingInfo* pRenderingInfo); +protected: friend class MVKRenderPass; - friend class MVKRenderPassAttachment; + friend class MVKAttachmentDescription; uint32_t getViewMaskGroupForMetalPass(uint32_t passIdx); MVKMTLFmtCaps getRequiredFormatCapabilitiesForAttachmentAt(uint32_t rpAttIdx); @@ -162,8 +169,10 @@ class MVKRenderSubpass : public MVKBaseObject { MVKSmallVector _preserveAttachments; MVKSmallVector _colorAttachmentFormats; VkPipelineRenderingCreateInfo _pipelineRenderingCreateInfo; - VkAttachmentReference2 _depthStencilAttachment; - VkAttachmentReference2 _depthStencilResolveAttachment; + VkAttachmentReference2 _depthAttachment; + VkAttachmentReference2 _stencilAttachment; + VkAttachmentReference2 _depthResolveAttachment; + VkAttachmentReference2 _stencilResolveAttachment; VkResolveModeFlagBits _depthResolveMode = VK_RESOLVE_MODE_NONE; VkResolveModeFlagBits _stencilResolveMode = VK_RESOLVE_MODE_NONE; VkSampleCountFlagBits _defaultSampleCount = VK_SAMPLE_COUNT_1_BIT; @@ -172,10 +181,10 @@ class MVKRenderSubpass : public MVKBaseObject { #pragma mark - -#pragma mark MVKRenderPassAttachment +#pragma mark MVKAttachmentDescription /** Represents an attachment within a Vulkan render pass. */ -class MVKRenderPassAttachment : public MVKBaseObject { +class MVKAttachmentDescription : public MVKBaseObject { public: @@ -218,13 +227,20 @@ class MVKRenderPassAttachment : public MVKBaseObject { /** Returns whether this attachment should be cleared in the subpass. */ bool shouldClearAttachment(MVKRenderSubpass* subpass, bool isStencil); - MVKRenderPassAttachment(MVKRenderPass* renderPass, + MVKAttachmentDescription(MVKRenderPass* renderPass, const VkAttachmentDescription* pCreateInfo); - MVKRenderPassAttachment(MVKRenderPass* renderPass, + MVKAttachmentDescription(MVKRenderPass* renderPass, const VkAttachmentDescription2* pCreateInfo); + MVKAttachmentDescription(MVKRenderPass* renderPass, + const VkRenderingAttachmentInfo* pAttInfo, + bool isResolveAttachment); + protected: + friend class MVKRenderPass; + friend class MVKRenderSubpass; + bool isFirstUseOfAttachment(MVKRenderSubpass* subpass); bool isLastUseOfAttachment(MVKRenderSubpass* subpass); MTLStoreAction getMTLStoreAction(MVKRenderSubpass* subpass, @@ -234,7 +250,7 @@ class MVKRenderPassAttachment : public MVKBaseObject { bool canResolveFormat, bool isStencil, bool storeOverride); - void validateFormat(); + void linkToSubpasses(); VkAttachmentDescription2 _info; MVKRenderPass* _renderPass; @@ -282,13 +298,15 @@ class MVKRenderPass : public MVKVulkanAPIDeviceObject { MVKRenderPass(MVKDevice* device, const VkRenderPassCreateInfo2* pCreateInfo); + MVKRenderPass(MVKDevice* device, const VkRenderingInfo* pRenderingInfo); + protected: friend class MVKRenderSubpass; - friend class MVKRenderPassAttachment; + friend class MVKAttachmentDescription; void propagateDebugName() override {} - MVKSmallVector _attachments; + MVKSmallVector _attachments; MVKSmallVector _subpasses; MVKSmallVector _subpassDependencies; VkRenderingFlags _renderingFlags = 0; @@ -297,21 +315,47 @@ class MVKRenderPass : public MVKVulkanAPIDeviceObject { #pragma mark - -#pragma mark Support functions +#pragma mark MVKRenderingAttachmentIterator -/** Returns a MVKRenderPass object created from the rendering info. */ -MVKRenderPass* mvkCreateRenderPass(MVKDevice* device, const VkRenderingInfo* pRenderingInfo); +typedef std::function MVKRenderingAttachmentInfoOperation; /** - * Extracts the usable attachments and their clear values from the rendering info, - * and sets them in the corresponding arrays, which must be large enough to hold - * all of the extracted values, and returns the number of attachments extracted. - * For consistency, the clear value of any resolve attachments are populated, - * even though they are ignored. + * Iterates the attachments in a VkRenderingInfo, and processes an operation + * on each attachment, once for the imageView, and once for the resolveImageView. + * + * Attachments are sequentially processed in this order: + * [color, color-resolve], ..., + * depth, depth-resolve, + * stencil, stencil-resolve + * skipping any attachments that do not have a VkImageView */ -uint32_t mvkGetAttachments(const VkRenderingInfo* pRenderingInfo, - MVKImageView* attachments[], - VkClearValue clearValues[]); +class MVKRenderingAttachmentIterator : public MVKBaseObject { + +public: + + MVKVulkanAPIObject* getVulkanAPIObject() override { return nullptr; } + + /** Iterates the attachments with the specified lambda function. */ + void iterate(MVKRenderingAttachmentInfoOperation attOperation); + + MVKRenderingAttachmentIterator(const VkRenderingInfo* pRenderingInfo); + +protected: + void handleAttachment(const VkRenderingAttachmentInfo* pAttInfo, + VkImageAspectFlagBits aspect, + MVKRenderingAttachmentInfoOperation attOperation); + const VkRenderingAttachmentInfo* getAttachmentInfo(const VkRenderingAttachmentInfo* pAtt, + const VkRenderingAttachmentInfo* pAltAtt, + bool isStencil); + + VkRenderingInfo _renderingInfo; +}; + + +#pragma mark - +#pragma mark Support functions /** Returns whether the view mask uses multiview. */ static constexpr bool mvkIsMultiview(uint32_t viewMask) { return viewMask != 0; } @@ -322,9 +366,6 @@ bool mvkIsColorAttachmentUsed(const VkPipelineRenderingCreateInfo* pRendInfo, ui /** Returns whether any attachment is being used. */ bool mvkHasColorAttachments(const VkPipelineRenderingCreateInfo* pRendInfo); -/** Extracts and returns the combined depth/stencil format . */ -VkFormat mvkGetDepthStencilFormat(const VkPipelineRenderingCreateInfo* pRendInfo); - /** * Extracts the first view, number of views, and the portion of the mask * to be rendered from the lowest clump of set bits in a view mask. diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm index 662bf2bbd..762d72d9b 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm @@ -53,9 +53,7 @@ } bool MVKRenderSubpass::isColorAttachmentUsed(uint32_t colorAttIdx) { - if (colorAttIdx >= _colorAttachments.size()) { - return false; - } + if (colorAttIdx >= _colorAttachments.size()) { return false; } return _colorAttachments[colorAttIdx].attachment != VK_ATTACHMENT_UNUSED; } @@ -72,10 +70,12 @@ return false; } -VkFormat MVKRenderSubpass::getDepthStencilFormat() { - uint32_t rpAttIdx = _depthStencilAttachment.attachment; - if (rpAttIdx == VK_ATTACHMENT_UNUSED) { return VK_FORMAT_UNDEFINED; } - return _renderPass->_attachments[rpAttIdx].getFormat(); +VkFormat MVKRenderSubpass::getDepthFormat() { + return isDepthAttachmentUsed() ? _renderPass->_attachments[_depthAttachment.attachment].getFormat() : VK_FORMAT_UNDEFINED; +} + +VkFormat MVKRenderSubpass::getStencilFormat() { + return isStencilAttachmentUsed() ? _renderPass->_attachments[_stencilAttachment.attachment].getFormat() : VK_FORMAT_UNDEFINED; } VkSampleCountFlagBits MVKRenderSubpass::getSampleCount() { @@ -85,11 +85,12 @@ return _renderPass->_attachments[rpAttIdx].getSampleCount(); } } - uint32_t rpAttIdx = _depthStencilAttachment.attachment; - if (rpAttIdx != VK_ATTACHMENT_UNUSED) { - return _renderPass->_attachments[rpAttIdx].getSampleCount(); + if (_depthAttachment.attachment != VK_ATTACHMENT_UNUSED) { + return _renderPass->_attachments[_depthAttachment.attachment].getSampleCount(); + } + if (_stencilAttachment.attachment != VK_ATTACHMENT_UNUSED) { + return _renderPass->_attachments[_stencilAttachment.attachment].getSampleCount(); } - return VK_SAMPLE_COUNT_1_BIT; } @@ -176,7 +177,7 @@ } // Configure the color attachment - MVKRenderPassAttachment* clrMVKRPAtt = &_renderPass->_attachments[clrRPAttIdx]; + MVKAttachmentDescription* clrMVKRPAtt = &_renderPass->_attachments[clrRPAttIdx]; if (clrMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc, this, attachments[clrRPAttIdx], isRenderingEntireAttachment, hasResolveAttachment, canResolveFormat, @@ -193,66 +194,75 @@ } } - // Populate the Metal depth and stencil attachments - uint32_t dsRPAttIdx = _depthStencilAttachment.attachment; - uint32_t dsRslvRPAttIdx = _depthStencilResolveAttachment.attachment; - if (dsRPAttIdx != VK_ATTACHMENT_UNUSED) { - MVKRenderPassAttachment* dsMVKRPAtt = &_renderPass->_attachments[dsRPAttIdx]; - MVKImageView* dsImage = attachments[dsRPAttIdx]; - MVKImageView* dsRslvImage = nullptr; - MTLPixelFormat mtlDSFormat = dsImage->getMTLPixelFormat(0); + // Populate the Metal depth attachment + uint32_t depthRPAttIdx = _depthAttachment.attachment; + if (depthRPAttIdx != VK_ATTACHMENT_UNUSED) { + MVKAttachmentDescription* depthMVKRPAtt = &_renderPass->_attachments[depthRPAttIdx]; + MVKImageView* depthImage = attachments[depthRPAttIdx]; - if (dsRslvRPAttIdx != VK_ATTACHMENT_UNUSED) { - dsRslvImage = attachments[dsRslvRPAttIdx]; + MVKImageView* depthRslvImage = nullptr; + uint32_t depthRslvRPAttIdx = _depthResolveAttachment.attachment; + if (depthRslvRPAttIdx != VK_ATTACHMENT_UNUSED) { + depthRslvImage = attachments[depthRslvRPAttIdx]; } - if (pixFmts->isDepthFormat(mtlDSFormat)) { - MTLRenderPassDepthAttachmentDescriptor* mtlDepthAttDesc = mtlRPDesc.depthAttachment; - bool hasResolveAttachment = (dsRslvRPAttIdx != VK_ATTACHMENT_UNUSED && _depthResolveMode != VK_RESOLVE_MODE_NONE); - if (hasResolveAttachment) { - dsRslvImage->populateMTLRenderPassAttachmentDescriptorResolve(mtlDepthAttDesc); - mtlDepthAttDesc.depthResolveFilterMVK = mvkMTLMultisampleDepthResolveFilterFromVkResolveModeFlagBits(_depthResolveMode); - if (isMultiview()) { - mtlDepthAttDesc.resolveSlice += getFirstViewIndexInMetalPass(passIdx); - } - } - if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlDepthAttDesc, this, dsImage, - isRenderingEntireAttachment, - hasResolveAttachment, true, - false, loadOverride)) { - mtlDepthAttDesc.clearDepth = pixFmts->getMTLClearDepthValue(clearValues[dsRPAttIdx]); - } + MTLRenderPassDepthAttachmentDescriptor* mtlDepthAttDesc = mtlRPDesc.depthAttachment; + bool hasDepthResolve = depthRslvRPAttIdx != VK_ATTACHMENT_UNUSED && _depthResolveMode != VK_RESOLVE_MODE_NONE; + if (hasDepthResolve) { + depthRslvImage->populateMTLRenderPassAttachmentDescriptorResolve(mtlDepthAttDesc); + mtlDepthAttDesc.depthResolveFilterMVK = mvkMTLMultisampleDepthResolveFilterFromVkResolveModeFlagBits(_depthResolveMode); if (isMultiview()) { - mtlDepthAttDesc.slice += getFirstViewIndexInMetalPass(passIdx); + mtlDepthAttDesc.resolveSlice += getFirstViewIndexInMetalPass(passIdx); } } - if (pixFmts->isStencilFormat(mtlDSFormat)) { - MTLRenderPassStencilAttachmentDescriptor* mtlStencilAttDesc = mtlRPDesc.stencilAttachment; - bool hasResolveAttachment = (dsRslvRPAttIdx != VK_ATTACHMENT_UNUSED && _stencilResolveMode != VK_RESOLVE_MODE_NONE); - if (hasResolveAttachment) { - dsRslvImage->populateMTLRenderPassAttachmentDescriptorResolve(mtlStencilAttDesc); + if (depthMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlDepthAttDesc, this, depthImage, + isRenderingEntireAttachment, + hasDepthResolve, true, + false, loadOverride)) { + mtlDepthAttDesc.clearDepth = pixFmts->getMTLClearDepthValue(clearValues[depthRPAttIdx]); + } + if (isMultiview()) { + mtlDepthAttDesc.slice += getFirstViewIndexInMetalPass(passIdx); + } + } + + // Populate the Metal stencil attachment + uint32_t stencilRPAttIdx = _stencilAttachment.attachment; + if (stencilRPAttIdx != VK_ATTACHMENT_UNUSED) { + MVKAttachmentDescription* stencilMVKRPAtt = &_renderPass->_attachments[stencilRPAttIdx]; + MVKImageView* stencilImage = attachments[stencilRPAttIdx]; + + MVKImageView* stencilRslvImage = nullptr; + uint32_t stencilRslvRPAttIdx = _stencilResolveAttachment.attachment; + if (stencilRslvRPAttIdx != VK_ATTACHMENT_UNUSED) { + stencilRslvImage = attachments[stencilRslvRPAttIdx]; + } + + MTLRenderPassStencilAttachmentDescriptor* mtlStencilAttDesc = mtlRPDesc.stencilAttachment; + bool hasStencilResolve = (stencilRslvRPAttIdx != VK_ATTACHMENT_UNUSED && _stencilResolveMode != VK_RESOLVE_MODE_NONE); + if (hasStencilResolve) { + stencilRslvImage->populateMTLRenderPassAttachmentDescriptorResolve(mtlStencilAttDesc); #if MVK_MACOS_OR_IOS - mtlStencilAttDesc.stencilResolveFilterMVK = mvkMTLMultisampleStencilResolveFilterFromVkResolveModeFlagBits(_stencilResolveMode); + mtlStencilAttDesc.stencilResolveFilterMVK = mvkMTLMultisampleStencilResolveFilterFromVkResolveModeFlagBits(_stencilResolveMode); #endif - if (isMultiview()) { - mtlStencilAttDesc.resolveSlice += getFirstViewIndexInMetalPass(passIdx); - } - } - if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlStencilAttDesc, this, dsImage, - isRenderingEntireAttachment, - hasResolveAttachment, true, - true, loadOverride)) { - mtlStencilAttDesc.clearStencil = pixFmts->getMTLClearStencilValue(clearValues[dsRPAttIdx]); - } if (isMultiview()) { - mtlStencilAttDesc.slice += getFirstViewIndexInMetalPass(passIdx); + mtlStencilAttDesc.resolveSlice += getFirstViewIndexInMetalPass(passIdx); } } + if (stencilMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlStencilAttDesc, this, stencilImage, + isRenderingEntireAttachment, + hasStencilResolve, true, + true, loadOverride)) { + mtlStencilAttDesc.clearStencil = pixFmts->getMTLClearStencilValue(clearValues[stencilRPAttIdx]); + } + if (isMultiview()) { + mtlStencilAttDesc.slice += getFirstViewIndexInMetalPass(passIdx); + } } // Vulkan supports rendering without attachments, but older Metal does not. // If Metal does not support rendering without attachments, create a dummy attachment to pass Metal validation. - if (caUsedCnt == 0 && dsRPAttIdx == VK_ATTACHMENT_UNUSED) { + if (caUsedCnt == 0 && depthRPAttIdx == VK_ATTACHMENT_UNUSED && stencilRPAttIdx == VK_ATTACHMENT_UNUSED) { if (_renderPass->getDevice()->_pMetalFeatures->renderWithoutAttachments) { mtlRPDesc.defaultRasterSampleCount = mvkSampleCountFromVkSampleCountFlagBits(_defaultSampleCount); } else { @@ -285,42 +295,42 @@ _renderPass->_attachments[clrRPAttIdx].encodeStoreAction(cmdEncoder, this, attachments[clrRPAttIdx], isRenderingEntireAttachment, hasResolveAttachment, canResolveFormat, caIdx, false, storeOverride); } } - uint32_t dsRPAttIdx = _depthStencilAttachment.attachment; - if (dsRPAttIdx != VK_ATTACHMENT_UNUSED) { - bool hasResolveAttachment = _depthStencilResolveAttachment.attachment != VK_ATTACHMENT_UNUSED; - bool hasDepthResolveAttachment = hasResolveAttachment && _depthResolveMode != VK_RESOLVE_MODE_NONE; - bool hasStencilResolveAttachment = hasResolveAttachment && _stencilResolveMode != VK_RESOLVE_MODE_NONE; - bool canResolveFormat = true; - _renderPass->_attachments[dsRPAttIdx].encodeStoreAction(cmdEncoder, this, attachments[dsRPAttIdx], isRenderingEntireAttachment, hasDepthResolveAttachment, canResolveFormat, 0, false, storeOverride); - _renderPass->_attachments[dsRPAttIdx].encodeStoreAction(cmdEncoder, this, attachments[dsRPAttIdx], isRenderingEntireAttachment, hasStencilResolveAttachment, canResolveFormat, 0, true, storeOverride); - } + if (_depthAttachment.attachment != VK_ATTACHMENT_UNUSED) { + _renderPass->_attachments[_depthAttachment.attachment].encodeStoreAction(cmdEncoder, this, attachments[_depthAttachment.attachment], isRenderingEntireAttachment, + (_depthResolveAttachment.attachment != VK_ATTACHMENT_UNUSED && _depthResolveMode != VK_RESOLVE_MODE_NONE), + true, 0, false, storeOverride); + } + if (_stencilAttachment.attachment != VK_ATTACHMENT_UNUSED) { + _renderPass->_attachments[_stencilAttachment.attachment].encodeStoreAction(cmdEncoder, this, attachments[_stencilAttachment.attachment], isRenderingEntireAttachment, + (_stencilResolveAttachment.attachment != VK_ATTACHMENT_UNUSED && _stencilResolveMode != VK_RESOLVE_MODE_NONE), + true, 0, true, storeOverride); + } } void MVKRenderSubpass::populateClearAttachments(MVKClearAttachments& clearAtts, const MVKArrayRef clearValues) { - uint32_t attIdx; uint32_t caCnt = getColorAttachmentCount(); for (uint32_t caIdx = 0; caIdx < caCnt; caIdx++) { - attIdx = _colorAttachments[caIdx].attachment; + uint32_t attIdx = _colorAttachments[caIdx].attachment; if ((attIdx != VK_ATTACHMENT_UNUSED) && _renderPass->_attachments[attIdx].shouldClearAttachment(this, false)) { clearAtts.push_back( { VK_IMAGE_ASPECT_COLOR_BIT, caIdx, clearValues[attIdx] } ); } } - attIdx = _depthStencilAttachment.attachment; - if (attIdx != VK_ATTACHMENT_UNUSED) { - MVKPixelFormats* pixFmts = _renderPass->getPixelFormats(); - MTLPixelFormat mtlDSFmt = pixFmts->getMTLPixelFormat(getDepthStencilFormat()); - auto& rpAtt = _renderPass->_attachments[attIdx]; - VkImageAspectFlags aspectMask = 0; - if (rpAtt.shouldClearAttachment(this, false) && pixFmts->isDepthFormat(mtlDSFmt)) { - mvkEnableFlags(aspectMask, VK_IMAGE_ASPECT_DEPTH_BIT); - } - if (rpAtt.shouldClearAttachment(this, true) && pixFmts->isStencilFormat(mtlDSFmt)) { - mvkEnableFlags(aspectMask, VK_IMAGE_ASPECT_STENCIL_BIT); + // If depth and stencil both need clearing and are the same attachment, just clear once, otherwise, clear them separately. + bool shouldClearDepth = (_depthAttachment.attachment != VK_ATTACHMENT_UNUSED && + _renderPass->_attachments[_depthAttachment.attachment].shouldClearAttachment(this, false)); + bool shouldClearStencil = (_stencilAttachment.attachment != VK_ATTACHMENT_UNUSED && + _renderPass->_attachments[_stencilAttachment.attachment].shouldClearAttachment(this, true)); + + if (shouldClearDepth && shouldClearStencil && _depthAttachment.attachment == _stencilAttachment.attachment) { + clearAtts.push_back( { VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 0, clearValues[_depthAttachment.attachment] } ); + } else { + if (shouldClearDepth) { + clearAtts.push_back( { VK_IMAGE_ASPECT_DEPTH_BIT, 0, clearValues[_depthAttachment.attachment] } ); } - if (aspectMask) { - clearAtts.push_back( { aspectMask, 0, clearValues[attIdx] } ); + if (shouldClearStencil) { + clearAtts.push_back( { VK_IMAGE_ASPECT_STENCIL_BIT, 0, clearValues[_stencilAttachment.attachment] } ); } } } @@ -328,18 +338,24 @@ void MVKRenderSubpass::populateMultiviewClearRects(MVKSmallVector& clearRects, MVKCommandEncoder* cmdEncoder, uint32_t caIdx, VkImageAspectFlags aspectMask) { - uint32_t attIdx; - assert(this == cmdEncoder->getSubpass()); - if (mvkIsAnyFlagEnabled(aspectMask, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { - attIdx = _depthStencilAttachment.attachment; - if (attIdx != VK_ATTACHMENT_UNUSED) { - _renderPass->_attachments[attIdx].populateMultiviewClearRects(clearRects, cmdEncoder); + if (mvkIsAnyFlagEnabled(aspectMask, VK_IMAGE_ASPECT_COLOR_BIT)) { + uint32_t clrAttIdx = _colorAttachments[caIdx].attachment; + if (clrAttIdx != VK_ATTACHMENT_UNUSED) { + _renderPass->_attachments[clrAttIdx].populateMultiviewClearRects(clearRects, cmdEncoder); } - return; } - attIdx = _colorAttachments[caIdx].attachment; - if (attIdx != VK_ATTACHMENT_UNUSED) { - _renderPass->_attachments[attIdx].populateMultiviewClearRects(clearRects, cmdEncoder); + + // If depth and stencil are the same attachment, only clear once. + if (mvkIsAnyFlagEnabled(aspectMask, VK_IMAGE_ASPECT_DEPTH_BIT) && + _depthAttachment.attachment != VK_ATTACHMENT_UNUSED) { + + _renderPass->_attachments[_depthAttachment.attachment].populateMultiviewClearRects(clearRects, cmdEncoder); + } + if (mvkIsAnyFlagEnabled(aspectMask, VK_IMAGE_ASPECT_STENCIL_BIT) && + _stencilAttachment.attachment != VK_ATTACHMENT_UNUSED && + _stencilAttachment.attachment != _depthAttachment.attachment) { + + _renderPass->_attachments[_stencilAttachment.attachment].populateMultiviewClearRects(clearRects, cmdEncoder); } } @@ -368,8 +384,12 @@ break; } } - if (_depthStencilAttachment.attachment == rpAttIdx) { mvkEnableFlags(caps, kMVKMTLFmtCapsDSAtt); } - if (_depthStencilResolveAttachment.attachment == rpAttIdx) { mvkEnableFlags(caps, kMVKMTLFmtCapsResolve); } + if (_depthAttachment.attachment == rpAttIdx || _stencilAttachment.attachment == rpAttIdx) { + mvkEnableFlags(caps, kMVKMTLFmtCapsDSAtt); + } + if (_depthResolveAttachment.attachment == rpAttIdx || _stencilResolveAttachment.attachment == rpAttIdx) { + mvkEnableFlags(caps, kMVKMTLFmtCapsResolve); + } return caps; } @@ -405,9 +425,7 @@ } } -// Must be called after renderpass has both subpasses and attachments bound void MVKRenderSubpass::populatePipelineRenderingCreateInfo() { - MVKPixelFormats* pixFmts = _renderPass->getPixelFormats(); _pipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO; _pipelineRenderingCreateInfo.pNext = nullptr; @@ -415,141 +433,220 @@ for (uint32_t caIdx = 0; caIdx < caCnt; caIdx++) { _colorAttachmentFormats.push_back(getColorAttachmentFormat(caIdx)); } - _pipelineRenderingCreateInfo.pColorAttachmentFormats = _colorAttachmentFormats.data(); _pipelineRenderingCreateInfo.colorAttachmentCount = caCnt; - - VkFormat dsFmt = getDepthStencilFormat(); - MTLPixelFormat dsMTLFmt = pixFmts->getMTLPixelFormat(dsFmt); - _pipelineRenderingCreateInfo.depthAttachmentFormat = pixFmts->isDepthFormat(dsMTLFmt) ? dsFmt : VK_FORMAT_UNDEFINED; - _pipelineRenderingCreateInfo.stencilAttachmentFormat = pixFmts->isStencilFormat(dsMTLFmt) ? dsFmt : VK_FORMAT_UNDEFINED; + _pipelineRenderingCreateInfo.pColorAttachmentFormats = _colorAttachmentFormats.data(); + _pipelineRenderingCreateInfo.depthAttachmentFormat = getDepthFormat(); + _pipelineRenderingCreateInfo.stencilAttachmentFormat = getStencilFormat(); } -MVKRenderSubpass::MVKRenderSubpass(MVKRenderPass* renderPass, - const VkSubpassDescription* pCreateInfo, - const VkRenderPassInputAttachmentAspectCreateInfo* pInputAspects, - uint32_t viewMask) { +static const VkAttachmentReference2 _unusedAttachment = {VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, nullptr, VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_UNDEFINED, 0}; + +MVKRenderSubpass::MVKRenderSubpass(MVKRenderPass* renderPass, const VkSubpassDescription2* pCreateInfo) { + + VkSubpassDescriptionDepthStencilResolve* pDSResolveInfo = nullptr; + for (auto* next = (const VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) { + switch (next->sType) { + case VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE: + pDSResolveInfo = (VkSubpassDescriptionDepthStencilResolve*)next; + break; + default: + break; + } + } + _renderPass = renderPass; _subpassIndex = (uint32_t)_renderPass->_subpasses.size(); - _pipelineRenderingCreateInfo.viewMask = viewMask; + _pipelineRenderingCreateInfo.viewMask = pCreateInfo->viewMask; // Add attachments _inputAttachments.reserve(pCreateInfo->inputAttachmentCount); for (uint32_t i = 0; i < pCreateInfo->inputAttachmentCount; i++) { - const VkAttachmentReference& att = pCreateInfo->pInputAttachments[i]; - _inputAttachments.push_back({VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, nullptr, att.attachment, att.layout, 0}); - } - if (pInputAspects && pInputAspects->aspectReferenceCount) { - for (uint32_t i = 0; i < pInputAspects->aspectReferenceCount; i++) { - const VkInputAttachmentAspectReference& aspectRef = pInputAspects->pAspectReferences[i]; - if (aspectRef.subpass == _subpassIndex) { - _inputAttachments[aspectRef.inputAttachmentIndex].aspectMask = aspectRef.aspectMask; - } - } + _inputAttachments.push_back(pCreateInfo->pInputAttachments[i]); } _colorAttachments.reserve(pCreateInfo->colorAttachmentCount); for (uint32_t i = 0; i < pCreateInfo->colorAttachmentCount; i++) { - const VkAttachmentReference& att = pCreateInfo->pColorAttachments[i]; - _colorAttachments.push_back({VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, nullptr, att.attachment, att.layout, 0}); + _colorAttachments.push_back(pCreateInfo->pColorAttachments[i]); } if (pCreateInfo->pResolveAttachments) { _resolveAttachments.reserve(pCreateInfo->colorAttachmentCount); for (uint32_t i = 0; i < pCreateInfo->colorAttachmentCount; i++) { - const VkAttachmentReference& att = pCreateInfo->pResolveAttachments[i]; - _resolveAttachments.push_back({VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, nullptr, att.attachment, att.layout, 0}); + _resolveAttachments.push_back(pCreateInfo->pResolveAttachments[i]); } } - if (pCreateInfo->pDepthStencilAttachment) { - _depthStencilAttachment.attachment = pCreateInfo->pDepthStencilAttachment->attachment; - _depthStencilAttachment.layout = pCreateInfo->pDepthStencilAttachment->layout; - } else { - _depthStencilAttachment.attachment = VK_ATTACHMENT_UNUSED; + MVKPixelFormats* pixFmts = _renderPass->getPixelFormats(); + + _depthAttachment = _unusedAttachment; + _stencilAttachment = _unusedAttachment; + const auto* pDSAtt = pCreateInfo->pDepthStencilAttachment; + if (pDSAtt && pDSAtt->attachment != VK_ATTACHMENT_UNUSED) { + MTLPixelFormat mtlDSFormat = pixFmts->getMTLPixelFormat(_renderPass->_attachments[pDSAtt->attachment].getFormat()); + if (pixFmts->isDepthFormat(mtlDSFormat)) { + _depthAttachment = *pCreateInfo->pDepthStencilAttachment; + } + if (pixFmts->isStencilFormat(mtlDSFormat)) { + _stencilAttachment = *pCreateInfo->pDepthStencilAttachment; + } } - _depthStencilResolveAttachment.attachment = VK_ATTACHMENT_UNUSED; + _depthResolveAttachment = _unusedAttachment; + _stencilResolveAttachment = _unusedAttachment; + const auto* pDSRslvAtt = pDSResolveInfo ? pDSResolveInfo->pDepthStencilResolveAttachment : nullptr; + if (pDSRslvAtt && pDSRslvAtt->attachment != VK_ATTACHMENT_UNUSED) { + MTLPixelFormat mtlDSFormat = pixFmts->getMTLPixelFormat(_renderPass->_attachments[pDSRslvAtt->attachment].getFormat()); + if (pixFmts->isDepthFormat(mtlDSFormat)) { + _depthResolveAttachment = *pDSResolveInfo->pDepthStencilResolveAttachment; + _depthResolveMode = pDSResolveInfo->depthResolveMode; + } + if (pixFmts->isStencilFormat(mtlDSFormat)) { + _stencilResolveAttachment = *pDSResolveInfo->pDepthStencilResolveAttachment; + _stencilResolveMode = pDSResolveInfo->stencilResolveMode; + } + } _preserveAttachments.reserve(pCreateInfo->preserveAttachmentCount); for (uint32_t i = 0; i < pCreateInfo->preserveAttachmentCount; i++) { _preserveAttachments.push_back(pCreateInfo->pPreserveAttachments[i]); } + + populatePipelineRenderingCreateInfo(); } MVKRenderSubpass::MVKRenderSubpass(MVKRenderPass* renderPass, - const VkSubpassDescription2* pCreateInfo) { - - VkSubpassDescriptionDepthStencilResolve* pDSResolveInfo = nullptr; - for (auto* next = (const VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) { - switch (next->sType) { - case VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE: - pDSResolveInfo = (VkSubpassDescriptionDepthStencilResolve*)next; - break; - default: - break; - } - } - + const VkSubpassDescription* pCreateInfo, + const VkRenderPassInputAttachmentAspectCreateInfo* pInputAspects, + uint32_t viewMask) { _renderPass = renderPass; _subpassIndex = (uint32_t)_renderPass->_subpasses.size(); - _pipelineRenderingCreateInfo.viewMask = pCreateInfo->viewMask; + _pipelineRenderingCreateInfo.viewMask = viewMask; // Add attachments _inputAttachments.reserve(pCreateInfo->inputAttachmentCount); for (uint32_t i = 0; i < pCreateInfo->inputAttachmentCount; i++) { - _inputAttachments.push_back(pCreateInfo->pInputAttachments[i]); + const VkAttachmentReference& att = pCreateInfo->pInputAttachments[i]; + _inputAttachments.push_back({VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, nullptr, att.attachment, att.layout, VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT}); + } + if (pInputAspects && pInputAspects->aspectReferenceCount) { + for (uint32_t i = 0; i < pInputAspects->aspectReferenceCount; i++) { + const VkInputAttachmentAspectReference& aspectRef = pInputAspects->pAspectReferences[i]; + if (aspectRef.subpass == _subpassIndex) { + _inputAttachments[aspectRef.inputAttachmentIndex].aspectMask = aspectRef.aspectMask; + } + } } _colorAttachments.reserve(pCreateInfo->colorAttachmentCount); for (uint32_t i = 0; i < pCreateInfo->colorAttachmentCount; i++) { - _colorAttachments.push_back(pCreateInfo->pColorAttachments[i]); + const VkAttachmentReference& att = pCreateInfo->pColorAttachments[i]; + _colorAttachments.push_back({VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, nullptr, att.attachment, att.layout, VK_IMAGE_ASPECT_COLOR_BIT}); } if (pCreateInfo->pResolveAttachments) { _resolveAttachments.reserve(pCreateInfo->colorAttachmentCount); for (uint32_t i = 0; i < pCreateInfo->colorAttachmentCount; i++) { - _resolveAttachments.push_back(pCreateInfo->pResolveAttachments[i]); + const VkAttachmentReference& att = pCreateInfo->pResolveAttachments[i]; + _resolveAttachments.push_back({VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, nullptr, att.attachment, att.layout, VK_IMAGE_ASPECT_COLOR_BIT}); } } + _depthAttachment = _unusedAttachment; + _stencilAttachment = _unusedAttachment; if (pCreateInfo->pDepthStencilAttachment) { - _depthStencilAttachment = *pCreateInfo->pDepthStencilAttachment; - } else { - _depthStencilAttachment.attachment = VK_ATTACHMENT_UNUSED; + auto* dsAtt = pCreateInfo->pDepthStencilAttachment; + uint32_t dsAttIdx = dsAtt->attachment; + if (dsAttIdx != VK_ATTACHMENT_UNUSED) { + MVKPixelFormats* pixFmts = _renderPass->getPixelFormats(); + MTLPixelFormat mtlDSFormat = pixFmts->getMTLPixelFormat(_renderPass->_attachments[dsAttIdx].getFormat()); + if (pixFmts->isDepthFormat(mtlDSFormat)) { + _depthAttachment = {VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, nullptr, dsAtt->attachment, dsAtt->layout, VK_IMAGE_ASPECT_DEPTH_BIT}; + } + if (pixFmts->isStencilFormat(mtlDSFormat)) { + _stencilAttachment = {VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, nullptr, dsAtt->attachment, dsAtt->layout, VK_IMAGE_ASPECT_STENCIL_BIT}; + } + } } - if (pDSResolveInfo && pDSResolveInfo->pDepthStencilResolveAttachment) { - _depthStencilResolveAttachment = *pDSResolveInfo->pDepthStencilResolveAttachment; - _depthResolveMode = pDSResolveInfo->depthResolveMode; - _stencilResolveMode = pDSResolveInfo->stencilResolveMode; - } else { - _depthStencilResolveAttachment.attachment = VK_ATTACHMENT_UNUSED; - } + _depthResolveAttachment = _unusedAttachment; + _stencilResolveAttachment = _unusedAttachment; _preserveAttachments.reserve(pCreateInfo->preserveAttachmentCount); for (uint32_t i = 0; i < pCreateInfo->preserveAttachmentCount; i++) { _preserveAttachments.push_back(pCreateInfo->pPreserveAttachments[i]); } + + populatePipelineRenderingCreateInfo(); + +} + +MVKRenderSubpass::MVKRenderSubpass(MVKRenderPass* renderPass, const VkRenderingInfo* pRenderingInfo) { + + _renderPass = renderPass; + _subpassIndex = (uint32_t)_renderPass->_subpasses.size(); + _pipelineRenderingCreateInfo.viewMask = pRenderingInfo->viewMask; + + _depthAttachment = _unusedAttachment; + _depthResolveAttachment = _unusedAttachment; + _stencilAttachment = _unusedAttachment; + _stencilResolveAttachment = _unusedAttachment; + + uint32_t attIdx = 0; + MVKRenderingAttachmentIterator attIter(pRenderingInfo); + attIter.iterate([&](const VkRenderingAttachmentInfo* pAttInfo, VkImageAspectFlagBits aspect, bool isResolveAttachment)->void { + VkAttachmentReference2 attRef = {VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, nullptr, attIdx++, pAttInfo->imageLayout, aspect}; + switch (aspect) { + case VK_IMAGE_ASPECT_COLOR_BIT: + if (isResolveAttachment) { + _resolveAttachments.push_back(attRef); + } else { + _colorAttachments.push_back(attRef); + } + break; + + case VK_IMAGE_ASPECT_DEPTH_BIT: + if (isResolveAttachment) { + _depthResolveAttachment = attRef; + _depthResolveMode = pAttInfo->resolveMode; + } else { + _depthAttachment = attRef; + } + break; + case VK_IMAGE_ASPECT_STENCIL_BIT: + if (isResolveAttachment) { + _stencilResolveAttachment = attRef; + _stencilResolveMode = pAttInfo->resolveMode; + } else { + _stencilAttachment = attRef; + } + break; + + default: + break; + } + }); + + populatePipelineRenderingCreateInfo(); } #pragma mark - -#pragma mark MVKRenderPassAttachment +#pragma mark MVKAttachmentDescription -MVKVulkanAPIObject* MVKRenderPassAttachment::getVulkanAPIObject() { return _renderPass->getVulkanAPIObject(); }; +MVKVulkanAPIObject* MVKAttachmentDescription::getVulkanAPIObject() { return _renderPass->getVulkanAPIObject(); }; -VkFormat MVKRenderPassAttachment::getFormat() { return _info.format; } +VkFormat MVKAttachmentDescription::getFormat() { return _info.format; } -VkSampleCountFlagBits MVKRenderPassAttachment::getSampleCount() { return _info.samples; } +VkSampleCountFlagBits MVKAttachmentDescription::getSampleCount() { return _info.samples; } -bool MVKRenderPassAttachment::populateMTLRenderPassAttachmentDescriptor(MTLRenderPassAttachmentDescriptor* mtlAttDesc, - MVKRenderSubpass* subpass, - MVKImageView* attachment, - bool isRenderingEntireAttachment, - bool hasResolveAttachment, - bool canResolveFormat, - bool isStencil, - bool loadOverride) { +bool MVKAttachmentDescription::populateMTLRenderPassAttachmentDescriptor(MTLRenderPassAttachmentDescriptor* mtlAttDesc, + MVKRenderSubpass* subpass, + MVKImageView* attachment, + bool isRenderingEntireAttachment, + bool hasResolveAttachment, + bool canResolveFormat, + bool isStencil, + bool loadOverride) { // Populate from the attachment image view attachment->populateMTLRenderPassAttachmentDescriptor(mtlAttDesc); @@ -597,40 +694,46 @@ return (mtlLA == MTLLoadActionClear); } -void MVKRenderPassAttachment::encodeStoreAction(MVKCommandEncoder* cmdEncoder, - MVKRenderSubpass* subpass, - MVKImageView* attachment, - bool isRenderingEntireAttachment, - bool hasResolveAttachment, - bool canResolveFormat, - uint32_t caIdx, - bool isStencil, - bool storeOverride) { +void MVKAttachmentDescription::encodeStoreAction(MVKCommandEncoder* cmdEncoder, + MVKRenderSubpass* subpass, + MVKImageView* attachment, + bool isRenderingEntireAttachment, + bool hasResolveAttachment, + bool canResolveFormat, + uint32_t caIdx, + bool isStencil, + bool storeOverride) { // For a combined depth-stencil format in an attachment with VK_IMAGE_ASPECT_STENCIL_BIT, // the attachment format may have been swizzled to a stencil-only format. In this case, - // we want to guard against an attempt to store the non-existent depth component. + // we must avoid either storing, or leaving unknown, the non-existent depth component. + // We check for depth swizzling by looking at the original image format as well. MTLPixelFormat mtlFmt = attachment->getMTLPixelFormat(); MVKPixelFormats* pixFmts = _renderPass->getPixelFormats(); - bool isDepthFormat = pixFmts->isDepthFormat(mtlFmt); bool isStencilFormat = pixFmts->isStencilFormat(mtlFmt); + bool isDepthFormat = pixFmts->isDepthFormat(mtlFmt); + bool isDepthSwizzled = false; + if (isStencilFormat && !isDepthFormat) { + isDepthFormat = pixFmts->isDepthFormat(attachment->getImage()->getMTLPixelFormat()); + isDepthSwizzled = isDepthFormat; + } bool isColorFormat = !(isDepthFormat || isStencilFormat); bool isMemorylessAttachment = false; #if MVK_APPLE_SILICON isMemorylessAttachment = attachment->getMTLTexture().storageMode == MTLStorageModeMemoryless; #endif - MTLStoreAction storeAction = getMTLStoreAction(subpass, isRenderingEntireAttachment, isMemorylessAttachment, hasResolveAttachment, canResolveFormat, isStencil, storeOverride); - + MTLStoreAction storeAction = getMTLStoreAction(subpass, isRenderingEntireAttachment, isMemorylessAttachment, + hasResolveAttachment, canResolveFormat, isStencil, storeOverride); if (isColorFormat) { [cmdEncoder->_mtlRenderEncoder setColorStoreAction: storeAction atIndex: caIdx]; } else if (isDepthFormat && !isStencil) { - [cmdEncoder->_mtlRenderEncoder setDepthStoreAction: storeAction]; + [cmdEncoder->_mtlRenderEncoder setDepthStoreAction: (isDepthSwizzled ? MTLStoreActionDontCare : storeAction)]; } else if (isStencilFormat && isStencil) { [cmdEncoder->_mtlRenderEncoder setStencilStoreAction: storeAction]; } } -void MVKRenderPassAttachment::populateMultiviewClearRects(MVKSmallVector& clearRects, MVKCommandEncoder* cmdEncoder) { +void MVKAttachmentDescription::populateMultiviewClearRects(MVKSmallVector& clearRects, MVKCommandEncoder* cmdEncoder) { MVKRenderSubpass* subpass = cmdEncoder->getSubpass(); uint32_t clearMask = subpass->getViewMaskGroupForMetalPass(cmdEncoder->getMultiviewPassIndex()) & _firstUseViewMasks[subpass->_subpassIndex]; @@ -643,7 +746,7 @@ } while (clearMask); } -bool MVKRenderPassAttachment::isFirstUseOfAttachment(MVKRenderSubpass* subpass) { +bool MVKAttachmentDescription::isFirstUseOfAttachment(MVKRenderSubpass* subpass) { if ( subpass->isMultiview() ) { return _firstUseViewMasks[subpass->_subpassIndex] == subpass->_pipelineRenderingCreateInfo.viewMask; } else { @@ -651,7 +754,7 @@ } } -bool MVKRenderPassAttachment::isLastUseOfAttachment(MVKRenderSubpass* subpass) { +bool MVKAttachmentDescription::isLastUseOfAttachment(MVKRenderSubpass* subpass) { if ( subpass->isMultiview() ) { return _lastUseViewMasks[subpass->_subpassIndex] == subpass->_pipelineRenderingCreateInfo.viewMask; } else { @@ -659,13 +762,13 @@ } } -MTLStoreAction MVKRenderPassAttachment::getMTLStoreAction(MVKRenderSubpass* subpass, - bool isRenderingEntireAttachment, - bool isMemorylessAttachment, - bool hasResolveAttachment, - bool canResolveFormat, - bool isStencil, - bool storeOverride) { +MTLStoreAction MVKAttachmentDescription::getMTLStoreAction(MVKRenderSubpass* subpass, + bool isRenderingEntireAttachment, + bool isMemorylessAttachment, + bool hasResolveAttachment, + bool canResolveFormat, + bool isStencil, + bool storeOverride) { // If the renderpass is going to be suspended, and resumed later, store the contents to preserve them until then. if (mvkIsAnyFlagEnabled(_renderPass->getRenderingFlags(), VK_RENDERING_SUSPENDING_BIT)) { @@ -690,7 +793,7 @@ return mvkMTLStoreActionFromVkAttachmentStoreOp(storeOp, hasResolveAttachment, canResolveFormat); } -bool MVKRenderPassAttachment::shouldClearAttachment(MVKRenderSubpass* subpass, bool isStencil) { +bool MVKAttachmentDescription::shouldClearAttachment(MVKRenderSubpass* subpass, bool isStencil) { // If the renderpass is being resumed after being suspended, don't clear this attachment. if (mvkIsAnyFlagEnabled(_renderPass->getRenderingFlags(), VK_RENDERING_RESUMING_BIT_KHR)) { return false; } @@ -705,7 +808,8 @@ return loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR; } -void MVKRenderPassAttachment::validateFormat() { +// Must be called after renderpass has both subpasses and attachments bound +void MVKAttachmentDescription::linkToSubpasses() { // Validate pixel format is supported MVKPixelFormats* pixFmts = _renderPass->getPixelFormats(); if ( !pixFmts->isSupportedOrSubstitutable(_info.format) ) { @@ -715,7 +819,7 @@ // Determine the indices of the first and last render subpasses to use this attachment. _firstUseSubpassIdx = kMVKUndefinedLargeUInt32; _lastUseSubpassIdx = 0; - if ( _renderPass->isMultiview() ) { + if (_renderPass->_subpasses[0].isMultiview()) { _firstUseViewMasks.reserve(_renderPass->_subpasses.size()); _lastUseViewMasks.reserve(_renderPass->_subpasses.size()); } @@ -746,8 +850,8 @@ } } -MVKRenderPassAttachment::MVKRenderPassAttachment(MVKRenderPass* renderPass, - const VkAttachmentDescription* pCreateInfo) { +MVKAttachmentDescription::MVKAttachmentDescription(MVKRenderPass* renderPass, + const VkAttachmentDescription* pCreateInfo) { _info.flags = pCreateInfo->flags; _info.format = pCreateInfo->format; _info.samples = pCreateInfo->samples; @@ -759,17 +863,41 @@ _info.finalLayout = pCreateInfo->finalLayout; _renderPass = renderPass; _attachmentIndex = uint32_t(_renderPass->_attachments.size()); - - validateFormat(); } -MVKRenderPassAttachment::MVKRenderPassAttachment(MVKRenderPass* renderPass, - const VkAttachmentDescription2* pCreateInfo) { +MVKAttachmentDescription::MVKAttachmentDescription(MVKRenderPass* renderPass, + const VkAttachmentDescription2* pCreateInfo) { _info = *pCreateInfo; _renderPass = renderPass; _attachmentIndex = uint32_t(_renderPass->_attachments.size()); +} - validateFormat(); +MVKAttachmentDescription::MVKAttachmentDescription(MVKRenderPass* renderPass, + const VkRenderingAttachmentInfo* pAttInfo, + bool isResolveAttachment) { + if (isResolveAttachment) { + _info.flags = 0; + _info.format = ((MVKImageView*)pAttInfo->resolveImageView)->getVkFormat(); + _info.samples = VK_SAMPLE_COUNT_1_BIT; + _info.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + _info.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + _info.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + _info.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; + _info.initialLayout = pAttInfo->resolveImageLayout; + _info.finalLayout = pAttInfo->resolveImageLayout; + } else { + _info.flags = 0; + _info.format = ((MVKImageView*)pAttInfo->imageView)->getVkFormat(); + _info.samples = ((MVKImageView*)pAttInfo->imageView)->getSampleCount(); + _info.loadOp = pAttInfo->loadOp; + _info.storeOp = pAttInfo->storeOp; + _info.stencilLoadOp = pAttInfo->loadOp; + _info.stencilStoreOp = pAttInfo->storeOp; + _info.initialLayout = pAttInfo->imageLayout; + _info.finalLayout = pAttInfo->imageLayout; + } + _renderPass = renderPass; + _attachmentIndex = uint32_t(_renderPass->_attachments.size()); } @@ -786,8 +914,6 @@ return { 1, 1 }; } -bool MVKRenderPass::isMultiview() const { return _subpasses[0].isMultiview(); } - MVKRenderPass::MVKRenderPass(MVKDevice* device, const VkRenderPassCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) { @@ -815,7 +941,13 @@ viewOffsets = pMultiviewCreateInfo->pViewOffsets; } - // Add subpasses and dependencies first + // Add attachments first so subpasses can access them during creation + _attachments.reserve(pCreateInfo->attachmentCount); + for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) { + _attachments.emplace_back(this, &pCreateInfo->pAttachments[i]); + } + + // Add subpasses and dependencies _subpasses.reserve(pCreateInfo->subpassCount); for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) { _subpasses.emplace_back(this, &pCreateInfo->pSubpasses[i], pInputAspectCreateInfo, viewMasks ? viewMasks[i] : 0); @@ -837,23 +969,22 @@ _subpassDependencies.push_back(dependency); } - // Add attachments after subpasses, so each attachment can link to subpasses - _attachments.reserve(pCreateInfo->attachmentCount); - for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) { - _attachments.emplace_back(this, &pCreateInfo->pAttachments[i]); - } - - // Populate additional subpass info after attachments added. - for (auto& mvkSP : _subpasses) { - mvkSP.populatePipelineRenderingCreateInfo(); + // Link attachments to subpasses + for (auto& att : _attachments) { + att.linkToSubpasses(); } } - MVKRenderPass::MVKRenderPass(MVKDevice* device, const VkRenderPassCreateInfo2* pCreateInfo) : MVKVulkanAPIDeviceObject(device) { - // Add subpasses and dependencies first + // Add attachments first so subpasses can access them during creation + _attachments.reserve(pCreateInfo->attachmentCount); + for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) { + _attachments.emplace_back(this, &pCreateInfo->pAttachments[i]); + } + + // Add subpasses and dependencies _subpasses.reserve(pCreateInfo->subpassCount); for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) { _subpasses.emplace_back(this, &pCreateInfo->pSubpasses[i]); @@ -863,214 +994,85 @@ _subpassDependencies.push_back(pCreateInfo->pDependencies[i]); } - // Add attachments after subpasses, so each attachment can link to subpasses - _attachments.reserve(pCreateInfo->attachmentCount); - for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) { - _attachments.emplace_back(this, &pCreateInfo->pAttachments[i]); + // Link attachments to subpasses + for (auto& att : _attachments) { + att.linkToSubpasses(); } +} - // Populate additional subpass info after attachments added. - for (auto& mvkSP : _subpasses) { - mvkSP.populatePipelineRenderingCreateInfo(); +MVKRenderPass::MVKRenderPass(MVKDevice* device, const VkRenderingInfo* pRenderingInfo) : MVKVulkanAPIDeviceObject(device) { + + _renderingFlags = pRenderingInfo->flags; + + // Add attachments first so subpasses can access them during creation + uint32_t attCnt = 0; + MVKRenderingAttachmentIterator attIter(pRenderingInfo); + attIter.iterate([&](const VkRenderingAttachmentInfo* pAttInfo, VkImageAspectFlagBits aspect, bool isResolveAttachment)->void { attCnt++; }); + _attachments.reserve(attCnt); + attIter.iterate([&](const VkRenderingAttachmentInfo* pAttInfo, VkImageAspectFlagBits aspect, bool isResolveAttachment)->void { + _attachments.emplace_back(this, pAttInfo, isResolveAttachment); + }); + + // Add subpass + _subpasses.emplace_back(this, pRenderingInfo); + + // Link attachments to subpasses + for (auto& att : _attachments) { + att.linkToSubpasses(); } } #pragma mark - -#pragma mark Support functions +#pragma mark MVKRenderingAttachmentIterator -// Adds the rendering attachment info to the array of attachment descriptors at the index, -// and increments the index, for both the base view and the resolve view, if it is present. -static void mvkAddAttachmentDescriptor(const VkRenderingAttachmentInfo* pAttInfo, - const VkRenderingAttachmentInfo* pStencilAttInfo, - VkAttachmentDescription2 attachmentDescriptors[], - uint32_t& attDescIdx) { - VkAttachmentDescription2 attDesc; - attDesc.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2; - attDesc.pNext = nullptr; - attDesc.flags = 0; - attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attDesc.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - - // Handle stencil-only possibility. - if ( !pAttInfo ) { pAttInfo = pStencilAttInfo; } +void MVKRenderingAttachmentIterator::iterate(MVKRenderingAttachmentInfoOperation attOperation) { + for (uint32_t caIdx = 0; caIdx < _renderingInfo.colorAttachmentCount; caIdx++) { + handleAttachment(&_renderingInfo.pColorAttachments[caIdx], VK_IMAGE_ASPECT_COLOR_BIT, attOperation); + } + handleAttachment(_renderingInfo.pDepthAttachment, VK_IMAGE_ASPECT_DEPTH_BIT, attOperation); + handleAttachment(_renderingInfo.pStencilAttachment, VK_IMAGE_ASPECT_STENCIL_BIT, attOperation); +} +void MVKRenderingAttachmentIterator::handleAttachment(const VkRenderingAttachmentInfo* pAttInfo, + VkImageAspectFlagBits aspect, + MVKRenderingAttachmentInfoOperation attOperation) { if (pAttInfo && pAttInfo->imageView) { - MVKImageView* mvkImgView = (MVKImageView*)pAttInfo->imageView; - attDesc.format = mvkImgView->getVkFormat(); - attDesc.samples = mvkImgView->getSampleCount(); - attDesc.loadOp = pAttInfo->loadOp; - attDesc.storeOp = pAttInfo->storeOp; - attDesc.stencilLoadOp = pStencilAttInfo ? pStencilAttInfo->loadOp : VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attDesc.stencilStoreOp = pStencilAttInfo ? pStencilAttInfo->storeOp : VK_ATTACHMENT_STORE_OP_DONT_CARE; - attDesc.initialLayout = pAttInfo->imageLayout; - attDesc.finalLayout = pAttInfo->imageLayout; - attachmentDescriptors[attDescIdx++] = attDesc; - + attOperation(pAttInfo, aspect, false); if (pAttInfo->resolveImageView && pAttInfo->resolveMode != VK_RESOLVE_MODE_NONE) { - attDesc.samples = VK_SAMPLE_COUNT_1_BIT; - attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attDesc.stencilStoreOp = pStencilAttInfo ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE; - attDesc.initialLayout = pAttInfo->resolveImageLayout; - attDesc.finalLayout = pAttInfo->resolveImageLayout; - attachmentDescriptors[attDescIdx++] = attDesc; + attOperation(pAttInfo, aspect, true); } } } -MVKRenderPass* mvkCreateRenderPass(MVKDevice* device, const VkRenderingInfo* pRenderingInfo) { - - // Renderpass attachments are sequentially indexed in this order: - // [color, color-resolve], ..., ds, ds-resolve - // skipping any attachments that do not have a VkImageView - uint32_t maxAttDescCnt = (pRenderingInfo->colorAttachmentCount + 1) * 2; - VkAttachmentDescription2 attachmentDescriptors[maxAttDescCnt]; - VkAttachmentReference2 colorAttachmentRefs[pRenderingInfo->colorAttachmentCount]; - VkAttachmentReference2 resolveAttachmentRefs[pRenderingInfo->colorAttachmentCount]; - - VkAttachmentReference2 attRef; - attRef.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2; - attRef.pNext = nullptr; - attRef.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - uint32_t attDescIdx = 0; - uint32_t caRefIdx = 0; - bool hasClrRslvAtt = false; - for (uint32_t caIdx = 0; caIdx < pRenderingInfo->colorAttachmentCount; caIdx++) { - auto& clrAtt = pRenderingInfo->pColorAttachments[caIdx]; - if (clrAtt.imageView) { - attRef.layout = clrAtt.imageLayout; - attRef.attachment = attDescIdx; - colorAttachmentRefs[caRefIdx] = attRef; - - if (clrAtt.resolveImageView && clrAtt.resolveMode != VK_RESOLVE_MODE_NONE) { - attRef.layout = clrAtt.resolveImageLayout; - attRef.attachment = attDescIdx + 1; - resolveAttachmentRefs[caRefIdx] = attRef; - hasClrRslvAtt = true; - } - caRefIdx++; - } - mvkAddAttachmentDescriptor(&clrAtt, nullptr, attachmentDescriptors, attDescIdx); - } - - // Combine depth and stencil attachments into one depth-stencil attachment. - // If both depth and stencil are present, their views and layouts must match. - VkAttachmentReference2 dsAttRef; - VkAttachmentReference2 dsRslvAttRef; - VkResolveModeFlagBits depthResolveMode = VK_RESOLVE_MODE_NONE; - VkResolveModeFlagBits stencilResolveMode = VK_RESOLVE_MODE_NONE; - - attRef.aspectMask = 0; - attRef.layout = VK_IMAGE_LAYOUT_UNDEFINED; - VkImageLayout rslvLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - if (pRenderingInfo->pDepthAttachment && pRenderingInfo->pDepthAttachment->imageView) { - attRef.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; - depthResolveMode = pRenderingInfo->pDepthAttachment->resolveMode; - attRef.layout = pRenderingInfo->pDepthAttachment->imageLayout; - rslvLayout = pRenderingInfo->pDepthAttachment->resolveImageLayout; - } - if (pRenderingInfo->pStencilAttachment && pRenderingInfo->pStencilAttachment->imageView) { - attRef.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - stencilResolveMode = pRenderingInfo->pStencilAttachment->resolveMode; - attRef.layout = pRenderingInfo->pStencilAttachment->imageLayout; - rslvLayout = pRenderingInfo->pStencilAttachment->resolveImageLayout; - } - - attRef.attachment = attRef.aspectMask ? attDescIdx : VK_ATTACHMENT_UNUSED; - dsAttRef = attRef; - - attRef.layout = rslvLayout; - attRef.attachment = attDescIdx + 1; - dsRslvAttRef = attRef; - - mvkAddAttachmentDescriptor(pRenderingInfo->pDepthAttachment, - pRenderingInfo->pStencilAttachment, - attachmentDescriptors, attDescIdx); - - // Depth/stencil resolve handled via VkSubpassDescription2 pNext - VkSubpassDescriptionDepthStencilResolve dsRslv; - dsRslv.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE; - dsRslv.pNext = nullptr; - dsRslv.depthResolveMode = depthResolveMode; - dsRslv.stencilResolveMode = stencilResolveMode; - dsRslv.pDepthStencilResolveAttachment = &dsRslvAttRef; - bool hasDSRslvAtt = depthResolveMode != VK_RESOLVE_MODE_NONE || stencilResolveMode != VK_RESOLVE_MODE_NONE; - - // Define the subpass - VkSubpassDescription2 spDesc; - spDesc.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2; - spDesc.pNext = hasDSRslvAtt ? &dsRslv : nullptr; - spDesc.flags = 0; - spDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - spDesc.viewMask = pRenderingInfo->viewMask; - spDesc.inputAttachmentCount = 0; - spDesc.pInputAttachments = nullptr; - spDesc.colorAttachmentCount = caRefIdx; - spDesc.pColorAttachments = colorAttachmentRefs; - spDesc.pResolveAttachments = hasClrRslvAtt ? resolveAttachmentRefs : nullptr;; - spDesc.pDepthStencilAttachment = &dsAttRef; - spDesc.preserveAttachmentCount = 0; - spDesc.pPreserveAttachments = nullptr; - - // Define the renderpass - VkRenderPassCreateInfo2 rpCreateInfo; - rpCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2; - rpCreateInfo.pNext = nullptr; - rpCreateInfo.flags = 0; - rpCreateInfo.attachmentCount = attDescIdx; - rpCreateInfo.pAttachments = attachmentDescriptors; - rpCreateInfo.subpassCount = 1; - rpCreateInfo.pSubpasses = &spDesc; - rpCreateInfo.dependencyCount = 0; - rpCreateInfo.pDependencies = nullptr; - rpCreateInfo.correlatedViewMaskCount = 0; - rpCreateInfo.pCorrelatedViewMasks = nullptr; - - auto* mvkRP = device->createRenderPass(&rpCreateInfo, nullptr); - mvkRP->setRenderingFlags(pRenderingInfo->flags); - return mvkRP; +MVKRenderingAttachmentIterator::MVKRenderingAttachmentIterator(const VkRenderingInfo* pRenderingInfo) { + _renderingInfo = *pRenderingInfo; + _renderingInfo.pDepthAttachment = getAttachmentInfo(pRenderingInfo->pDepthAttachment, pRenderingInfo->pStencilAttachment, false); + _renderingInfo.pStencilAttachment = getAttachmentInfo(pRenderingInfo->pStencilAttachment, pRenderingInfo->pDepthAttachment, true); } -uint32_t mvkGetAttachments(const VkRenderingInfo* pRenderingInfo, - MVKImageView* attachments[], - VkClearValue clearValues[]) { - - // Renderpass attachments are sequentially indexed in this order: - // [color, color-resolve], ..., ds, ds-resolve - // skipping any attachments that do not have a VkImageView - // For consistency, we populate the clear value of any resolve attachments, even though they are ignored. - uint32_t attIdx = 0; - for (uint32_t caIdx = 0; caIdx < pRenderingInfo->colorAttachmentCount; caIdx++) { - auto& clrAtt = pRenderingInfo->pColorAttachments[caIdx]; - if (clrAtt.imageView) { - clearValues[attIdx] = clrAtt.clearValue; - attachments[attIdx++] = (MVKImageView*)clrAtt.imageView; - if (clrAtt.resolveImageView && clrAtt.resolveMode != VK_RESOLVE_MODE_NONE) { - clearValues[attIdx] = clrAtt.clearValue; - attachments[attIdx++] = (MVKImageView*)clrAtt.resolveImageView; - } - } - } +// If the depth/stencil attachment is not in use, but the alternate stencil/depth attachment is, +// and the MTLPixelFormat is usable by both attachments, force the use of the alternate attachment +// for both attachments, to avoid Metal validation errors when a pipeline expects both depth and +// stencil, but only one of the attachments has been provided here. +// Check the MTLPixelFormat of the MVKImage underlying the MVKImageView, to bypass possible +// substitution of MTLPixelFormat in the MVKImageView due to swizzling, or stencil-only access. +const VkRenderingAttachmentInfo* MVKRenderingAttachmentIterator::getAttachmentInfo(const VkRenderingAttachmentInfo* pAtt, + const VkRenderingAttachmentInfo* pAltAtt, + bool isStencil) { + bool useAlt = false; + if ( !(pAtt && pAtt->imageView) && (pAltAtt && pAltAtt->imageView) ) { + MVKImage* mvkImg = ((MVKImageView*)pAltAtt->imageView)->getImage(); + useAlt = (isStencil + ? mvkImg->getPixelFormats()->isStencilFormat(mvkImg->getMTLPixelFormat()) + : mvkImg->getPixelFormats()->isDepthFormat(mvkImg->getMTLPixelFormat())); + } + return useAlt ? pAltAtt : pAtt; +} - // We need to combine the DS attachments into one - auto* pDSAtt = pRenderingInfo->pDepthAttachment ? pRenderingInfo->pDepthAttachment : pRenderingInfo->pStencilAttachment; - if (pDSAtt) { - if (pDSAtt->imageView) { - clearValues[attIdx] = pDSAtt->clearValue; - attachments[attIdx++] = (MVKImageView*)pDSAtt->imageView; - } - if (pDSAtt->resolveImageView && pDSAtt->resolveMode != VK_RESOLVE_MODE_NONE) { - clearValues[attIdx] = pDSAtt->clearValue; - attachments[attIdx++] = (MVKImageView*)pDSAtt->resolveImageView; - } - } - return attIdx; -} +#pragma mark - +#pragma mark Support functions bool mvkIsColorAttachmentUsed(const VkPipelineRenderingCreateInfo* pRendInfo, uint32_t colorAttIdx) { return pRendInfo && pRendInfo->pColorAttachmentFormats[colorAttIdx]; @@ -1085,14 +1087,6 @@ bool mvkHasColorAttachments(const VkPipelineRenderingCreateInfo* pRendInfo) { return false; } -VkFormat mvkGetDepthStencilFormat(const VkPipelineRenderingCreateInfo* pRendInfo) { - return (pRendInfo - ? (pRendInfo->depthAttachmentFormat - ? pRendInfo->depthAttachmentFormat - : pRendInfo->stencilAttachmentFormat) - : VK_FORMAT_UNDEFINED); -} - uint32_t mvkGetNextViewMaskGroup(uint32_t viewMask, uint32_t* startView, uint32_t* viewCount, uint32_t *groupMask) { // First, find the first set bit. This is the start of the next clump of views to be rendered. // n.b. ffs(3) returns a 1-based index. This actually bit me during development of this feature. diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKResource.mm b/MoltenVK/MoltenVK/GPUObjects/MVKResource.mm index 0e2131dcd..51b438ae8 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKResource.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKResource.mm @@ -18,7 +18,6 @@ #include "MVKResource.h" #include "MVKCommandBuffer.h" -#include "MVKEnvironment.h" #pragma mark MVKResource diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h index a7e3417fb..87418edd1 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h @@ -107,7 +107,9 @@ class MVKShaderLibrary : public MVKBaseObject { friend MVKShaderLibraryCache; friend MVKShaderModule; - MVKMTLFunction getMTLFunction(const VkSpecializationInfo* pSpecializationInfo, MVKShaderModule* shaderModule); + MVKMTLFunction getMTLFunction(const VkSpecializationInfo* pSpecializationInfo, + VkPipelineCreationFeedback* pShaderFeedback, + MVKShaderModule* shaderModule); void handleCompilationError(NSError* err, const char* opDesc); MTLFunctionConstant* getFunctionConstant(NSArray* mtlFCs, NSUInteger mtlFCID); void compileLibrary(const std::string& msl); @@ -144,7 +146,8 @@ class MVKShaderLibraryCache : public MVKBaseObject { */ MVKShaderLibrary* getShaderLibrary(SPIRVToMSLConversionConfiguration* pShaderConfig, MVKShaderModule* shaderModule, MVKPipeline* pipeline, - bool* pWasAdded, uint64_t startTime = 0); + bool* pWasAdded, VkPipelineCreationFeedback* pShaderFeedback, + uint64_t startTime = 0); MVKShaderLibraryCache(MVKVulkanAPIDeviceObject* owner) : _owner(owner) {}; @@ -155,7 +158,9 @@ class MVKShaderLibraryCache : public MVKBaseObject { friend MVKPipelineCache; friend MVKShaderModule; - MVKShaderLibrary* findShaderLibrary(SPIRVToMSLConversionConfiguration* pShaderConfig, uint64_t startTime = 0); + MVKShaderLibrary* findShaderLibrary(SPIRVToMSLConversionConfiguration* pShaderConfig, + VkPipelineCreationFeedback* pShaderFeedback = nullptr, + uint64_t startTime = 0); MVKShaderLibrary* addShaderLibrary(const SPIRVToMSLConversionConfiguration* pShaderConfig, const SPIRVToMSLConversionResult& conversionResult); MVKShaderLibrary* addShaderLibrary(const SPIRVToMSLConversionConfiguration* pShaderConfig, @@ -207,7 +212,8 @@ class MVKShaderModule : public MVKVulkanAPIDeviceObject { /** Returns the Metal shader function, possibly specialized. */ MVKMTLFunction getMTLFunction(SPIRVToMSLConversionConfiguration* pShaderConfig, const VkSpecializationInfo* pSpecializationInfo, - MVKPipeline* pipeline); + MVKPipeline* pipeline, + VkPipelineCreationFeedback* pShaderFeedback); /** Convert the SPIR-V to MSL, using the specified shader conversion configuration. */ bool convert(SPIRVToMSLConversionConfiguration* pShaderConfig, diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm index 2eb57ebb4..a47a65b77 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm @@ -67,7 +67,9 @@ static uint32_t getWorkgroupDimensionSize(const SPIRVWorkgroupSizeDimension& wgD return wgDim.size; } -MVKMTLFunction MVKShaderLibrary::getMTLFunction(const VkSpecializationInfo* pSpecializationInfo, MVKShaderModule* shaderModule) { +MVKMTLFunction MVKShaderLibrary::getMTLFunction(const VkSpecializationInfo* pSpecializationInfo, + VkPipelineCreationFeedback* pShaderFeedback, + MVKShaderModule* shaderModule) { if ( !_mtlLibrary ) { return MVKMTLFunctionNull; } @@ -76,9 +78,15 @@ static uint32_t getWorkgroupDimensionSize(const SPIRVWorkgroupSizeDimension& wgD NSString* mtlFuncName = @(_shaderConversionResultInfo.entryPoint.mtlFunctionName.c_str()); MVKDevice* mvkDev = _owner->getDevice(); - uint64_t startTime = mvkDev->getPerformanceTimestamp(); + uint64_t startTime = pShaderFeedback ? mvkGetTimestamp() : mvkDev->getPerformanceTimestamp(); id mtlFunc = [[_mtlLibrary newFunctionWithName: mtlFuncName] autorelease]; mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.shaderCompilation.functionRetrieval, startTime); + if (pShaderFeedback) { + if (mtlFunc) { + mvkEnableFlags(pShaderFeedback->flags, VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT); + } + pShaderFeedback->duration += mvkGetElapsedNanoseconds(startTime); + } if (mtlFunc) { // If the Metal device supports shader specialization, and the Metal function expects to be specialized, @@ -108,11 +116,15 @@ static uint32_t getWorkgroupDimensionSize(const SPIRVWorkgroupSizeDimension& wgD // Compile the specialized Metal function, and use it instead of the unspecialized Metal function. MVKFunctionSpecializer fs(_owner); + if (pShaderFeedback) { + startTime = mvkGetTimestamp(); + } mtlFunc = [fs.newMTLFunction(_mtlLibrary, mtlFuncName, mtlFCVals) autorelease]; + if (pShaderFeedback) { + pShaderFeedback->duration += mvkGetElapsedNanoseconds(startTime); + } } } - } else { - reportError(VK_ERROR_INVALID_SHADER_NV, "Shader module does not contain an entry point named '%s'.", mtlFuncName.UTF8String); } // Set the debug name. First try name of shader module, otherwise try name of owner. @@ -242,13 +254,17 @@ static uint32_t getWorkgroupDimensionSize(const SPIRVWorkgroupSizeDimension& wgD MVKShaderLibrary* MVKShaderLibraryCache::getShaderLibrary(SPIRVToMSLConversionConfiguration* pShaderConfig, MVKShaderModule* shaderModule, MVKPipeline* pipeline, - bool* pWasAdded, uint64_t startTime) { + bool* pWasAdded, VkPipelineCreationFeedback* pShaderFeedback, + uint64_t startTime) { bool wasAdded = false; - MVKShaderLibrary* shLib = findShaderLibrary(pShaderConfig, startTime); + MVKShaderLibrary* shLib = findShaderLibrary(pShaderConfig, pShaderFeedback, startTime); if ( !shLib && !pipeline->shouldFailOnPipelineCompileRequired() ) { SPIRVToMSLConversionResult conversionResult; if (shaderModule->convert(pShaderConfig, conversionResult)) { shLib = addShaderLibrary(pShaderConfig, conversionResult); + if (pShaderFeedback) { + pShaderFeedback->duration += mvkGetElapsedNanoseconds(startTime); + } wasAdded = true; } } @@ -261,12 +277,16 @@ static uint32_t getWorkgroupDimensionSize(const SPIRVWorkgroupSizeDimension& wgD // Finds and returns a shader library matching the shader config, or returns nullptr if it doesn't exist. // If a match is found, the shader config is aligned with the shader config of the matching library. MVKShaderLibrary* MVKShaderLibraryCache::findShaderLibrary(SPIRVToMSLConversionConfiguration* pShaderConfig, + VkPipelineCreationFeedback* pShaderFeedback, uint64_t startTime) { for (auto& slPair : _shaderLibraries) { if (slPair.first.matches(*pShaderConfig)) { pShaderConfig->alignWith(slPair.first); MVKDevice* mvkDev = _owner->getDevice(); mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.shaderCompilation.shaderLibraryFromCache, startTime); + if (pShaderFeedback) { + pShaderFeedback->duration += mvkGetElapsedNanoseconds(startTime); + } return slPair.second; } } @@ -311,23 +331,24 @@ static uint32_t getWorkgroupDimensionSize(const SPIRVWorkgroupSizeDimension& wgD MVKMTLFunction MVKShaderModule::getMTLFunction(SPIRVToMSLConversionConfiguration* pShaderConfig, const VkSpecializationInfo* pSpecializationInfo, - MVKPipeline* pipeline) { + MVKPipeline* pipeline, + VkPipelineCreationFeedback* pShaderFeedback) { MVKShaderLibrary* mvkLib = _directMSLLibrary; if ( !mvkLib ) { - uint64_t startTime = _device->getPerformanceTimestamp(); + uint64_t startTime = pShaderFeedback ? mvkGetTimestamp() : _device->getPerformanceTimestamp(); MVKPipelineCache* pipelineCache = pipeline->getPipelineCache(); if (pipelineCache) { - mvkLib = pipelineCache->getShaderLibrary(pShaderConfig, this, pipeline, startTime); + mvkLib = pipelineCache->getShaderLibrary(pShaderConfig, this, pipeline, pShaderFeedback, startTime); } else { lock_guard lock(_accessLock); - mvkLib = _shaderLibraryCache.getShaderLibrary(pShaderConfig, this, pipeline, nullptr, startTime); + mvkLib = _shaderLibraryCache.getShaderLibrary(pShaderConfig, this, pipeline, nullptr, pShaderFeedback, startTime); } } else { mvkLib->setEntryPointName(pShaderConfig->options.entryPointName); pShaderConfig->markAllInterfaceVarsAndResourcesUsed(); } - return mvkLib ? mvkLib->getMTLFunction(pSpecializationInfo, this) : MVKMTLFunctionNull; + return mvkLib ? mvkLib->getMTLFunction(pSpecializationInfo, pShaderFeedback, this) : MVKMTLFunctionNull; } bool MVKShaderModule::convert(SPIRVToMSLConversionConfiguration* pShaderConfig, diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSurface.h b/MoltenVK/MoltenVK/GPUObjects/MVKSurface.h index 544c8dfac..0bcceb5d1 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKSurface.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKSurface.h @@ -19,7 +19,6 @@ #pragma once #include "MVKVulkanAPIObject.h" -#include "MVKEnvironment.h" #include #import diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h index 47a26d2a7..523a58072 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h @@ -99,6 +99,9 @@ class MVKSwapchain : public MVKVulkanAPIDeviceObject { /** VK_GOOGLE_display_timing - returns past presentation times */ VkResult getPastPresentationTiming(uint32_t *pCount, VkPastPresentationTimingGOOGLE *pPresentationTimings); + /** Marks parts of the underlying CAMetalLayer as needing update. */ + void setLayerNeedsDisplay(const VkPresentRegionKHR* pRegion); + void destroy() override; #pragma mark Construction @@ -121,7 +124,7 @@ class MVKSwapchain : public MVKVulkanAPIDeviceObject { void willPresentSurface(id mtlTexture, id mtlCmdBuff); void renderWatermark(id mtlTexture, id mtlCmdBuff); void markFrameInterval(); - void recordPresentTime(MVKImagePresentInfo& presentInfo, uint64_t actualPresentTime = 0); + void recordPresentTime(const MVKImagePresentInfo& presentInfo, uint64_t actualPresentTime = 0); CAMetalLayer* _mtlLayer = nil; MVKWatermark* _licenseWatermark = nullptr; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm index 53aba660a..601fbc544 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm @@ -175,7 +175,9 @@ perfLogCntLimit, (1000.0 / _device->_performanceStatistics.queue.frameInterval.averageDuration), mvkGetElapsedMilliseconds() / 1000.0); - _device->logPerformanceSummary(); + if (mvkConfig().activityPerformanceLoggingStyle == MVK_CONFIG_ACTIVITY_PERFORMANCE_LOGGING_STYLE_FRAME_COUNT) { + _device->logPerformanceSummary(); + } } } @@ -503,14 +505,16 @@ static CALayerContentsGravity getCALayerContentsGravity(VkSwapchainPresentScalin VkResult MVKSwapchain::getRefreshCycleDuration(VkRefreshCycleDurationGOOGLE *pRefreshCycleDuration) { if (_device->getConfigurationResult() != VK_SUCCESS) { return _device->getConfigurationResult(); } -#if MVK_IOS_OR_TVOS || MVK_MACCAT +#if MVK_VISIONOS + // TODO: See if this can be obtained from OS instead + NSInteger framesPerSecond = 90; +#elif MVK_IOS_OR_TVOS || MVK_MACCAT NSInteger framesPerSecond = 60; UIScreen* screen = _mtlLayer.screenMVK; if ([screen respondsToSelector: @selector(maximumFramesPerSecond)]) { framesPerSecond = screen.maximumFramesPerSecond; } -#endif -#if MVK_MACOS && !MVK_MACCAT +#elif MVK_MACOS && !MVK_MACCAT NSScreen* screen = _mtlLayer.screenMVK; CGDirectDisplayID displayId = [[[screen deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue]; CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayId); @@ -557,7 +561,7 @@ static CALayerContentsGravity getCALayerContentsGravity(VkSwapchainPresentScalin return res; } -void MVKSwapchain::recordPresentTime(MVKImagePresentInfo& presentInfo, uint64_t actualPresentTime) { +void MVKSwapchain::recordPresentTime(const MVKImagePresentInfo& presentInfo, uint64_t actualPresentTime) { std::lock_guard lock(_presentHistoryLock); if (_presentHistoryCount < kMaxPresentationHistory) { _presentHistoryCount++; @@ -565,8 +569,11 @@ static CALayerContentsGravity getCALayerContentsGravity(VkSwapchainPresentScalin _presentHistoryHeadIndex = (_presentHistoryHeadIndex + 1) % kMaxPresentationHistory; } - // If actual time not supplied, use desired time instead + // If actual present time is not available, use desired time instead, and if that + // hasn't been set, use the current time, which should be reasonably accurate (sub-ms), + // since we are here as part of the addPresentedHandler: callback. if (actualPresentTime == 0) { actualPresentTime = presentInfo.desiredPresentTime; } + if (actualPresentTime == 0) { actualPresentTime = CACurrentMediaTime() * 1.0e9; } _presentTimingHistory[_presentHistoryIndex].presentID = presentInfo.presentID; _presentTimingHistory[_presentHistoryIndex].desiredPresentTime = presentInfo.desiredPresentTime; @@ -577,6 +584,30 @@ static CALayerContentsGravity getCALayerContentsGravity(VkSwapchainPresentScalin _presentHistoryIndex = (_presentHistoryIndex + 1) % kMaxPresentationHistory; } +void MVKSwapchain::setLayerNeedsDisplay(const VkPresentRegionKHR* pRegion) { + if (!pRegion || pRegion->rectangleCount == 0) { + [_mtlLayer setNeedsDisplay]; + return; + } + + for (uint32_t i = 0; i < pRegion->rectangleCount; ++i) { + CGRect cgRect = mvkCGRectFromVkRectLayerKHR(pRegion->pRectangles[i]); +#if MVK_MACOS + // VK_KHR_incremental_present specifies an upper-left origin, but macOS by default + // uses a lower-left origin. + cgRect.origin.y = _mtlLayer.bounds.size.height - cgRect.origin.y; +#endif + // We were given rectangles in pixels, but -[CALayer setNeedsDisplayInRect:] wants them + // in points, which is pixels / contentsScale. + CGFloat scaleFactor = _mtlLayer.contentsScale; + cgRect.origin.x /= scaleFactor; + cgRect.origin.y /= scaleFactor; + cgRect.size.width /= scaleFactor; + cgRect.size.height /= scaleFactor; + [_mtlLayer setNeedsDisplayInRect:cgRect]; + } +} + // A retention loop exists between the swapchain and its images. The swapchain images // retain the swapchain because they can be in flight when the app destroys the swapchain. // Release the images now, when the app destroys the swapchain, so they will be destroyed when diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSync.h b/MoltenVK/MoltenVK/GPUObjects/MVKSync.h index c8d9da452..ad87f715a 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKSync.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKSync.h @@ -459,6 +459,8 @@ class MVKFenceSitter : public MVKBaseObject { MVKFenceSitter(bool waitAll) : _blocker(waitAll, 0) {} + ~MVKFenceSitter() override { [_listener release]; } + private: friend class MVKFence; friend class MVKTimelineSemaphoreMTLEvent; @@ -634,3 +636,89 @@ class MVKMetalCompiler : public MVKBaseObject { std::string _compilerType = "Unknown"; MVKPerformanceTracker* _pPerformanceTracker = nullptr; }; + +#pragma mark - +#pragma mark MVKDeferredOperation + +/** The maximum number of function parameters for all functions added to MVKDeferredOperationFunctionPointer. */ +static const int kMVKMaxDeferredFunctionParameters = 3; + +/** Defines the function pointer for each dependent function. */ +union MVKDeferredOperationFunctionPointer { + // Empty until deferred functions from other extensions have been defined. + // Planning to use std::functions + // Each function should take a pointer to a MVKDeferredOperation instance, to allow + // the function to call setMaxConcurrency() and setOperationResult(), and should + // return a VkResult representing the value returned by vkDeferredOperationJoinKHR(). +}; + +/** Indicates what kind of function is being deferred. */ +enum MVKDeferredOperationFunctionType { + // Empty until deferred functions from other extensions have been defined +}; + +/** + * Holds and invokes a deferred operation. + * + * Deferred operations are added by as required by future extensions that require them, + * and are implemented by each of those extensions as a function pointer added to + * MVKDeferredOperationFunctionPointer, plus a corresponding type identifier added + * to MVKDeferredOperationFunctionType. + */ +class MVKDeferredOperation : public MVKVulkanAPIDeviceObject { +public: + VkObjectType getVkObjectType() override { return VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR; } + + VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT; } + + /** Begins executing the deferred operation on the current thread. */ + VkResult join(); + + /** Gets the result of the execution of the deferred operation */ + VkResult getOperationResult(); + + /** + * Sets the result of the execution of the deferred operation. + * Called from the function that is implementing the deferred operation. + */ + void setOperationResult(VkResult opResult); + + /** Gets the max number of threads that can execute the deferred operation concurrently. */ + uint32_t getMaxConcurrency(); + + /** + * Sets the max number of threads that can execute the deferred operation concurrently. + * Called from the function that is implementing the deferred operation. + */ + void setMaxConcurrency(uint32_t maxConCurr); + + /** + * Sets the result of the execution of the deferred operation, and updates the max concurrently. + * Equivalent to calling setOperationResult() and setMaxConcurrency(), but with a single concurrency mutex lock. + * Called from the function that is implementing the deferred operation. + */ + void updateResults(VkResult opResult, uint32_t maxConCurr); + + /** + * Sets all the variables needed for a deferred operation. + * Called from the code that implements a deferred operation. + */ + void deferOperation(const MVKDeferredOperationFunctionPointer& pointer, + MVKDeferredOperationFunctionType type, + void** parameters, + uint32_t paramCount); + +#pragma mark Construction + MVKDeferredOperation(MVKDevice* device) : MVKVulkanAPIDeviceObject(device) {} + +protected: + void propagateDebugName() override {} + + std::mutex _lock; + MVKSmallVector _functionParameters; + MVKDeferredOperationFunctionPointer _functionPointer = {}; + MVKDeferredOperationFunctionType _functionType; + VkResult _operationResult = VK_SUCCESS; + uint32_t _maxConcurrency = 0; + +}; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm b/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm index 47bf78a23..efde21cb9 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm @@ -620,5 +620,57 @@ VkResult mvkWaitSemaphores(MVKDevice* device, [_compileError release]; } +#pragma mark - +#pragma mark MVKDeferredOperation + +// Call appropriate function from MVKDeferredOperationFunctionPointer with parameters. +// While executing, the function can call setOperationResult() and setMaxConcurrency() +// to update status of the operation, and should return a VkResult that is returned here. +VkResult MVKDeferredOperation::join() { + switch(_functionType) { + // ..... + default: return VK_SUCCESS; + }; +} + +void MVKDeferredOperation::deferOperation(const MVKDeferredOperationFunctionPointer& pointer, + MVKDeferredOperationFunctionType type, + void** parameters, + uint32_t paramCount) { + _functionPointer = pointer; + _functionType = type; + + _functionParameters.reserve(paramCount); + for(int i = 0; i < paramCount; i++) { + _functionParameters.push_back(parameters[i]); + } + + updateResults(VK_SUCCESS, mvkGetAvaliableCPUCores()); +} + +VkResult MVKDeferredOperation::getOperationResult() { + lock_guard lock(_lock); + return _operationResult; +} + +void MVKDeferredOperation::setOperationResult(VkResult opResult) { + lock_guard lock(_lock); + _operationResult = opResult; +} +uint32_t MVKDeferredOperation::getMaxConcurrency() { + lock_guard lock(_lock); + return _maxConcurrency; +} + +void MVKDeferredOperation::setMaxConcurrency(uint32_t maxConCurr) { + lock_guard lock(_lock); + _maxConcurrency = maxConCurr; +} + +void MVKDeferredOperation::updateResults(VkResult opResult, uint32_t maxConCurr) { + lock_guard lock(_lock); + _operationResult = opResult; + _maxConcurrency = maxConCurr; +} diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.def b/MoltenVK/MoltenVK/Layers/MVKExtensions.def index ce68d29f8..74a006290 100644 --- a/MoltenVK/MoltenVK/Layers/MVKExtensions.def +++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.def @@ -16,7 +16,7 @@ * limitations under the License. */ -// To use this file, define the macro MVK_EXTENSION(var, EXT, type, macos, ios), then #include this file. +// To use this file, define the macro MVK_EXTENSION(var, EXT, type, macos, ios, xros), then #include this file. // To add a new extension, simply add an MVK_EXTENSION line below. The macro takes the // portion of the extension name without the leading "VK_", both in lowercase and uppercase, // plus a value representing the extension type (instance/device/...). @@ -38,105 +38,114 @@ #endif #ifndef MVK_EXTENSION_LAST -#define MVK_EXTENSION_LAST(var, EXT, type, macos, ios) MVK_EXTENSION(var, EXT, type, macos, ios) +#define MVK_EXTENSION_LAST(var, EXT, type, macos, ios, xros) MVK_EXTENSION(var, EXT, type, macos, ios, xros) #endif -MVK_EXTENSION(KHR_16bit_storage, KHR_16BIT_STORAGE, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_8bit_storage, KHR_8BIT_STORAGE, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_bind_memory2, KHR_BIND_MEMORY_2, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_buffer_device_address, KHR_BUFFER_DEVICE_ADDRESS, DEVICE, 13.0, 16.0) -MVK_EXTENSION(KHR_copy_commands2, KHR_COPY_COMMANDS_2, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_create_renderpass2, KHR_CREATE_RENDERPASS_2, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_dedicated_allocation, KHR_DEDICATED_ALLOCATION, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_depth_stencil_resolve, KHR_DEPTH_STENCIL_RESOLVE, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_descriptor_update_template, KHR_DESCRIPTOR_UPDATE_TEMPLATE, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_device_group, KHR_DEVICE_GROUP, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_device_group_creation, KHR_DEVICE_GROUP_CREATION, INSTANCE, 10.11, 8.0) -MVK_EXTENSION(KHR_draw_indirect_count, KHR_DRAW_INDIRECT_COUNT, DEVICE, MVK_NA, MVK_NA) -MVK_EXTENSION(KHR_driver_properties, KHR_DRIVER_PROPERTIES, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_dynamic_rendering, KHR_DYNAMIC_RENDERING, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_external_fence, KHR_EXTERNAL_FENCE, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_external_fence_capabilities, KHR_EXTERNAL_FENCE_CAPABILITIES, INSTANCE, 10.11, 8.0) -MVK_EXTENSION(KHR_external_memory, KHR_EXTERNAL_MEMORY, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_external_memory_capabilities, KHR_EXTERNAL_MEMORY_CAPABILITIES, INSTANCE, 10.11, 8.0) -MVK_EXTENSION(KHR_external_semaphore, KHR_EXTERNAL_SEMAPHORE, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_external_semaphore_capabilities, KHR_EXTERNAL_SEMAPHORE_CAPABILITIES, INSTANCE, 10.11, 8.0) -MVK_EXTENSION(KHR_fragment_shader_barycentric, KHR_FRAGMENT_SHADER_BARYCENTRIC, DEVICE, 10.15, 14.0) -MVK_EXTENSION(KHR_get_memory_requirements2, KHR_GET_MEMORY_REQUIREMENTS_2, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_get_physical_device_properties2, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2, INSTANCE, 10.11, 8.0) -MVK_EXTENSION(KHR_get_surface_capabilities2, KHR_GET_SURFACE_CAPABILITIES_2, INSTANCE, 10.11, 8.0) -MVK_EXTENSION(KHR_imageless_framebuffer, KHR_IMAGELESS_FRAMEBUFFER, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_image_format_list, KHR_IMAGE_FORMAT_LIST, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_maintenance1, KHR_MAINTENANCE1, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_maintenance2, KHR_MAINTENANCE2, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_maintenance3, KHR_MAINTENANCE3, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_map_memory2, KHR_MAP_MEMORY_2, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_multiview, KHR_MULTIVIEW, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_portability_subset, KHR_PORTABILITY_SUBSET, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_push_descriptor, KHR_PUSH_DESCRIPTOR, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_relaxed_block_layout, KHR_RELAXED_BLOCK_LAYOUT, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_sampler_mirror_clamp_to_edge, KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE, DEVICE, 10.11, 14.0) -MVK_EXTENSION(KHR_sampler_ycbcr_conversion, KHR_SAMPLER_YCBCR_CONVERSION, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_separate_depth_stencil_layouts, KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_shader_atomic_int64, KHR_SHADER_ATOMIC_INT64, DEVICE, MVK_NA, MVK_NA) -MVK_EXTENSION(KHR_shader_draw_parameters, KHR_SHADER_DRAW_PARAMETERS, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_shader_float_controls, KHR_SHADER_FLOAT_CONTROLS, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_shader_float16_int8, KHR_SHADER_FLOAT16_INT8, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_shader_subgroup_extended_types, KHR_SHADER_SUBGROUP_EXTENDED_TYPES, DEVICE, 10.14, 13.0) -MVK_EXTENSION(KHR_spirv_1_4, KHR_SPIRV_1_4, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_storage_buffer_storage_class, KHR_STORAGE_BUFFER_STORAGE_CLASS, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_surface, KHR_SURFACE, INSTANCE, 10.11, 8.0) -MVK_EXTENSION(KHR_swapchain, KHR_SWAPCHAIN, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_swapchain_mutable_format, KHR_SWAPCHAIN_MUTABLE_FORMAT, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_timeline_semaphore, KHR_TIMELINE_SEMAPHORE, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_uniform_buffer_standard_layout, KHR_UNIFORM_BUFFER_STANDARD_LAYOUT, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_variable_pointers, KHR_VARIABLE_POINTERS, DEVICE, 10.11, 8.0) -MVK_EXTENSION(KHR_vulkan_memory_model, KHR_VULKAN_MEMORY_MODEL, DEVICE, MVK_NA, MVK_NA) -MVK_EXTENSION(EXT_buffer_device_address, EXT_BUFFER_DEVICE_ADDRESS, DEVICE, 13.0, 16.0) -MVK_EXTENSION(EXT_debug_marker, EXT_DEBUG_MARKER, DEVICE, 10.11, 8.0) -MVK_EXTENSION(EXT_debug_report, EXT_DEBUG_REPORT, INSTANCE, 10.11, 8.0) -MVK_EXTENSION(EXT_debug_utils, EXT_DEBUG_UTILS, INSTANCE, 10.11, 8.0) -MVK_EXTENSION(EXT_descriptor_indexing, EXT_DESCRIPTOR_INDEXING, DEVICE, 10.11, 8.0) -MVK_EXTENSION(EXT_external_memory_host, EXT_EXTERNAL_MEMORY_HOST, DEVICE, 10.11, 8.0) -MVK_EXTENSION(EXT_fragment_shader_interlock, EXT_FRAGMENT_SHADER_INTERLOCK, DEVICE, 10.13, 11.0) -MVK_EXTENSION(EXT_hdr_metadata, EXT_HDR_METADATA, DEVICE, 10.15, MVK_NA) -MVK_EXTENSION(EXT_host_query_reset, EXT_HOST_QUERY_RESET, DEVICE, 10.11, 8.0) -MVK_EXTENSION(EXT_image_robustness, EXT_IMAGE_ROBUSTNESS, DEVICE, 10.11, 8.0) -MVK_EXTENSION(EXT_inline_uniform_block, EXT_INLINE_UNIFORM_BLOCK, DEVICE, 10.11, 8.0) -MVK_EXTENSION(EXT_memory_budget, EXT_MEMORY_BUDGET, DEVICE, 10.13, 11.0) -MVK_EXTENSION(EXT_metal_objects, EXT_METAL_OBJECTS, DEVICE, 10.11, 8.0) -MVK_EXTENSION(EXT_metal_surface, EXT_METAL_SURFACE, INSTANCE, 10.11, 8.0) -MVK_EXTENSION(EXT_pipeline_creation_cache_control, EXT_PIPELINE_CREATION_CACHE_CONTROL, DEVICE, 10.11, 8.0) -MVK_EXTENSION(EXT_post_depth_coverage, EXT_POST_DEPTH_COVERAGE, DEVICE, 11.0, 11.0) -MVK_EXTENSION(EXT_private_data, EXT_PRIVATE_DATA, DEVICE, 10.11, 8.0) -MVK_EXTENSION(EXT_robustness2, EXT_ROBUSTNESS_2, DEVICE, 10.11, 8.0) -MVK_EXTENSION(EXT_sample_locations, EXT_SAMPLE_LOCATIONS, DEVICE, 10.13, 11.0) -MVK_EXTENSION(EXT_sampler_filter_minmax, EXT_SAMPLER_FILTER_MINMAX, DEVICE, MVK_NA, MVK_NA) -MVK_EXTENSION(EXT_scalar_block_layout, EXT_SCALAR_BLOCK_LAYOUT, DEVICE, 10.11, 8.0) -MVK_EXTENSION(EXT_separate_stencil_usage, EXT_SEPARATE_STENCIL_USAGE, DEVICE, 10.11, 8.0) -MVK_EXTENSION(EXT_shader_atomic_float, EXT_SHADER_ATOMIC_FLOAT, DEVICE, 13.0, 16.0) -MVK_EXTENSION(EXT_shader_stencil_export, EXT_SHADER_STENCIL_EXPORT, DEVICE, 10.14, 12.0) -MVK_EXTENSION(EXT_shader_viewport_index_layer, EXT_SHADER_VIEWPORT_INDEX_LAYER, DEVICE, 10.11, 8.0) -MVK_EXTENSION(EXT_subgroup_size_control, EXT_SUBGROUP_SIZE_CONTROL, DEVICE, 10.14, 13.0) -MVK_EXTENSION(EXT_surface_maintenance1, EXT_SURFACE_MAINTENANCE_1, INSTANCE, 10.11, 8.0) -MVK_EXTENSION(EXT_swapchain_colorspace, EXT_SWAPCHAIN_COLOR_SPACE, INSTANCE, 10.11, 9.0) -MVK_EXTENSION(EXT_swapchain_maintenance1, EXT_SWAPCHAIN_MAINTENANCE_1, DEVICE, 10.11, 8.0) -MVK_EXTENSION(EXT_texel_buffer_alignment, EXT_TEXEL_BUFFER_ALIGNMENT, DEVICE, 10.13, 11.0) -MVK_EXTENSION(EXT_texture_compression_astc_hdr, EXT_TEXTURE_COMPRESSION_ASTC_HDR, DEVICE, 11.0, 13.0) -MVK_EXTENSION(EXT_vertex_attribute_divisor, EXT_VERTEX_ATTRIBUTE_DIVISOR, DEVICE, 10.11, 8.0) -MVK_EXTENSION(AMD_draw_indirect_count, AMD_DRAW_INDIRECT_COUNT, DEVICE, MVK_NA, MVK_NA) -MVK_EXTENSION(AMD_gpu_shader_half_float, AMD_GPU_SHADER_HALF_FLOAT, DEVICE, 10.11, 8.0) -MVK_EXTENSION(AMD_negative_viewport_height, AMD_NEGATIVE_VIEWPORT_HEIGHT, DEVICE, 10.11, 8.0) -MVK_EXTENSION(AMD_shader_image_load_store_lod, AMD_SHADER_IMAGE_LOAD_STORE_LOD, DEVICE, 11.0, 8.0) -MVK_EXTENSION(AMD_shader_trinary_minmax, AMD_SHADER_TRINARY_MINMAX, DEVICE, 10.14, 12.0) -MVK_EXTENSION(IMG_format_pvrtc, IMG_FORMAT_PVRTC, DEVICE, 11.0, 8.0) -MVK_EXTENSION(INTEL_shader_integer_functions2, INTEL_SHADER_INTEGER_FUNCTIONS_2, DEVICE, 10.11, 8.0) -MVK_EXTENSION(GOOGLE_display_timing, GOOGLE_DISPLAY_TIMING, DEVICE, 10.11, 8.0) -MVK_EXTENSION(MVK_ios_surface, MVK_IOS_SURFACE, INSTANCE, MVK_NA, 8.0) -MVK_EXTENSION(MVK_macos_surface, MVK_MACOS_SURFACE, INSTANCE, 10.11, MVK_NA) -MVK_EXTENSION(MVK_moltenvk, MVK_MOLTENVK, INSTANCE, 10.11, 8.0) -MVK_EXTENSION(NV_fragment_shader_barycentric, NV_FRAGMENT_SHADER_BARYCENTRIC, DEVICE, 10.15, 14.0) -MVK_EXTENSION_LAST(NV_glsl_shader, NV_GLSL_SHADER, DEVICE, 10.11, 8.0) +MVK_EXTENSION(KHR_16bit_storage, KHR_16BIT_STORAGE, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_8bit_storage, KHR_8BIT_STORAGE, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_bind_memory2, KHR_BIND_MEMORY_2, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_buffer_device_address, KHR_BUFFER_DEVICE_ADDRESS, DEVICE, 13.0, 16.0, 1.0) +MVK_EXTENSION(KHR_copy_commands2, KHR_COPY_COMMANDS_2, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_create_renderpass2, KHR_CREATE_RENDERPASS_2, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_dedicated_allocation, KHR_DEDICATED_ALLOCATION, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_deferred_host_operations, KHR_DEFERRED_HOST_OPERATIONS, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_depth_stencil_resolve, KHR_DEPTH_STENCIL_RESOLVE, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_descriptor_update_template, KHR_DESCRIPTOR_UPDATE_TEMPLATE, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_device_group, KHR_DEVICE_GROUP, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_device_group_creation, KHR_DEVICE_GROUP_CREATION, INSTANCE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_draw_indirect_count, KHR_DRAW_INDIRECT_COUNT, DEVICE, MVK_NA, MVK_NA, MVK_NA) +MVK_EXTENSION(KHR_driver_properties, KHR_DRIVER_PROPERTIES, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_dynamic_rendering, KHR_DYNAMIC_RENDERING, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_external_fence, KHR_EXTERNAL_FENCE, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_external_fence_capabilities, KHR_EXTERNAL_FENCE_CAPABILITIES, INSTANCE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_external_memory, KHR_EXTERNAL_MEMORY, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_external_memory_capabilities, KHR_EXTERNAL_MEMORY_CAPABILITIES, INSTANCE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_external_semaphore, KHR_EXTERNAL_SEMAPHORE, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_external_semaphore_capabilities, KHR_EXTERNAL_SEMAPHORE_CAPABILITIES, INSTANCE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_fragment_shader_barycentric, KHR_FRAGMENT_SHADER_BARYCENTRIC, DEVICE, 10.15, 14.0, 1.0) +MVK_EXTENSION(KHR_get_memory_requirements2, KHR_GET_MEMORY_REQUIREMENTS_2, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_get_physical_device_properties2, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2, INSTANCE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_get_surface_capabilities2, KHR_GET_SURFACE_CAPABILITIES_2, INSTANCE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_imageless_framebuffer, KHR_IMAGELESS_FRAMEBUFFER, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_image_format_list, KHR_IMAGE_FORMAT_LIST, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_incremental_present, KHR_INCREMENTAL_PRESENT, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_maintenance1, KHR_MAINTENANCE1, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_maintenance2, KHR_MAINTENANCE2, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_maintenance3, KHR_MAINTENANCE3, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_map_memory2, KHR_MAP_MEMORY_2, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_multiview, KHR_MULTIVIEW, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_portability_subset, KHR_PORTABILITY_SUBSET, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_push_descriptor, KHR_PUSH_DESCRIPTOR, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_relaxed_block_layout, KHR_RELAXED_BLOCK_LAYOUT, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_sampler_mirror_clamp_to_edge, KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE, DEVICE, 10.11, 14.0, 1.0) +MVK_EXTENSION(KHR_sampler_ycbcr_conversion, KHR_SAMPLER_YCBCR_CONVERSION, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_separate_depth_stencil_layouts, KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_shader_atomic_int64, KHR_SHADER_ATOMIC_INT64, DEVICE, MVK_NA, MVK_NA, MVK_NA) +MVK_EXTENSION(KHR_shader_draw_parameters, KHR_SHADER_DRAW_PARAMETERS, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_shader_float_controls, KHR_SHADER_FLOAT_CONTROLS, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_shader_float16_int8, KHR_SHADER_FLOAT16_INT8, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_shader_non_semantic_info, KHR_SHADER_NON_SEMANTIC_INFO, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_shader_subgroup_extended_types, KHR_SHADER_SUBGROUP_EXTENDED_TYPES, DEVICE, 10.14, 13.0, 1.0) +MVK_EXTENSION(KHR_spirv_1_4, KHR_SPIRV_1_4, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_storage_buffer_storage_class, KHR_STORAGE_BUFFER_STORAGE_CLASS, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_surface, KHR_SURFACE, INSTANCE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_swapchain, KHR_SWAPCHAIN, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_swapchain_mutable_format, KHR_SWAPCHAIN_MUTABLE_FORMAT, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_timeline_semaphore, KHR_TIMELINE_SEMAPHORE, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_uniform_buffer_standard_layout, KHR_UNIFORM_BUFFER_STANDARD_LAYOUT, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_variable_pointers, KHR_VARIABLE_POINTERS, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(KHR_vulkan_memory_model, KHR_VULKAN_MEMORY_MODEL, DEVICE, MVK_NA, MVK_NA, MVK_NA) +MVK_EXTENSION(EXT_4444_formats, EXT_4444_FORMATS, DEVICE, 11.0, 13.0, 1.0) +MVK_EXTENSION(EXT_buffer_device_address, EXT_BUFFER_DEVICE_ADDRESS, DEVICE, 13.0, 16.0, 1.0) +MVK_EXTENSION(EXT_calibrated_timestamps, EXT_CALIBRATED_TIMESTAMPS, DEVICE, 10.15, 14.0, 1.0) +MVK_EXTENSION(EXT_debug_marker, EXT_DEBUG_MARKER, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_debug_report, EXT_DEBUG_REPORT, INSTANCE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_debug_utils, EXT_DEBUG_UTILS, INSTANCE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_descriptor_indexing, EXT_DESCRIPTOR_INDEXING, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_external_memory_host, EXT_EXTERNAL_MEMORY_HOST, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_fragment_shader_interlock, EXT_FRAGMENT_SHADER_INTERLOCK, DEVICE, 10.13, 11.0, 1.0) +MVK_EXTENSION(EXT_hdr_metadata, EXT_HDR_METADATA, DEVICE, 10.15, MVK_NA, MVK_NA) +MVK_EXTENSION(EXT_host_query_reset, EXT_HOST_QUERY_RESET, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_image_robustness, EXT_IMAGE_ROBUSTNESS, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_inline_uniform_block, EXT_INLINE_UNIFORM_BLOCK, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_memory_budget, EXT_MEMORY_BUDGET, DEVICE, 10.13, 11.0, 1.0) +MVK_EXTENSION(EXT_metal_objects, EXT_METAL_OBJECTS, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_metal_surface, EXT_METAL_SURFACE, INSTANCE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_pipeline_creation_cache_control, EXT_PIPELINE_CREATION_CACHE_CONTROL, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_pipeline_creation_feedback, EXT_PIPELINE_CREATION_FEEDBACK, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_post_depth_coverage, EXT_POST_DEPTH_COVERAGE, DEVICE, 11.0, 11.0, 1.0) +MVK_EXTENSION(EXT_private_data, EXT_PRIVATE_DATA, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_robustness2, EXT_ROBUSTNESS_2, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_sample_locations, EXT_SAMPLE_LOCATIONS, DEVICE, 10.13, 11.0, 1.0) +MVK_EXTENSION(EXT_sampler_filter_minmax, EXT_SAMPLER_FILTER_MINMAX, DEVICE, MVK_NA, MVK_NA, MVK_NA) +MVK_EXTENSION(EXT_scalar_block_layout, EXT_SCALAR_BLOCK_LAYOUT, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_separate_stencil_usage, EXT_SEPARATE_STENCIL_USAGE, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_shader_atomic_float, EXT_SHADER_ATOMIC_FLOAT, DEVICE, 13.0, 16.0, 1.0) +MVK_EXTENSION(EXT_shader_demote_to_helper_invocation, EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION, DEVICE, 11.0, 14.0, 1.0) +MVK_EXTENSION(EXT_shader_stencil_export, EXT_SHADER_STENCIL_EXPORT, DEVICE, 10.14, 12.0, 1.0) +MVK_EXTENSION(EXT_shader_subgroup_ballot, EXT_SHADER_SUBGROUP_BALLOT, DEVICE, 10.14, 13.0, 1.0) +MVK_EXTENSION(EXT_shader_subgroup_vote, EXT_SHADER_SUBGROUP_VOTE, DEVICE, 10.14, 13.0, 1.0) +MVK_EXTENSION(EXT_shader_viewport_index_layer, EXT_SHADER_VIEWPORT_INDEX_LAYER, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_subgroup_size_control, EXT_SUBGROUP_SIZE_CONTROL, DEVICE, 10.14, 13.0, 1.0) +MVK_EXTENSION(EXT_surface_maintenance1, EXT_SURFACE_MAINTENANCE_1, INSTANCE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_swapchain_colorspace, EXT_SWAPCHAIN_COLOR_SPACE, INSTANCE, 10.11, 9.0, 1.0) +MVK_EXTENSION(EXT_swapchain_maintenance1, EXT_SWAPCHAIN_MAINTENANCE_1, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(EXT_texel_buffer_alignment, EXT_TEXEL_BUFFER_ALIGNMENT, DEVICE, 10.13, 11.0, 1.0) +MVK_EXTENSION(EXT_texture_compression_astc_hdr, EXT_TEXTURE_COMPRESSION_ASTC_HDR, DEVICE, 11.0, 13.0, 1.0) +MVK_EXTENSION(EXT_vertex_attribute_divisor, EXT_VERTEX_ATTRIBUTE_DIVISOR, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(AMD_draw_indirect_count, AMD_DRAW_INDIRECT_COUNT, DEVICE, MVK_NA, MVK_NA, MVK_NA) +MVK_EXTENSION(AMD_gpu_shader_half_float, AMD_GPU_SHADER_HALF_FLOAT, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(AMD_negative_viewport_height, AMD_NEGATIVE_VIEWPORT_HEIGHT, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(AMD_shader_image_load_store_lod, AMD_SHADER_IMAGE_LOAD_STORE_LOD, DEVICE, 11.0, 8.0, 1.0) +MVK_EXTENSION(AMD_shader_trinary_minmax, AMD_SHADER_TRINARY_MINMAX, DEVICE, 10.14, 12.0, 1.0) +MVK_EXTENSION(IMG_format_pvrtc, IMG_FORMAT_PVRTC, DEVICE, 11.0, 8.0, 1.0) +MVK_EXTENSION(INTEL_shader_integer_functions2, INTEL_SHADER_INTEGER_FUNCTIONS_2, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(GOOGLE_display_timing, GOOGLE_DISPLAY_TIMING, DEVICE, 10.11, 8.0, 1.0) +MVK_EXTENSION(MVK_ios_surface, MVK_IOS_SURFACE, INSTANCE, MVK_NA, 8.0, MVK_NA) +MVK_EXTENSION(MVK_macos_surface, MVK_MACOS_SURFACE, INSTANCE, 10.11, MVK_NA, MVK_NA) +MVK_EXTENSION(MVK_moltenvk, MVK_MOLTENVK, INSTANCE, 10.11, 8.0, 1.0) +MVK_EXTENSION(NV_fragment_shader_barycentric, NV_FRAGMENT_SHADER_BARYCENTRIC, DEVICE, 10.15, 14.0, 1.0) +MVK_EXTENSION_LAST(NV_glsl_shader, NV_GLSL_SHADER, DEVICE, 10.11, 8.0, 1.0) #undef MVK_EXTENSION #undef MVK_EXTENSION_LAST diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.h b/MoltenVK/MoltenVK/Layers/MVKExtensions.h index 64b35e360..c368da8c7 100644 --- a/MoltenVK/MoltenVK/Layers/MVKExtensions.h +++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.h @@ -52,7 +52,7 @@ class MVKExtensionList : public MVKBaseObject { union { struct { -#define MVK_EXTENSION(var, EXT, type, macos, ios) MVKExtension vk_ ##var; +#define MVK_EXTENSION(var, EXT, type, macos, ios, xros) MVKExtension vk_ ##var; #include "MVKExtensions.def" }; MVKExtension extensionArray; diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.mm b/MoltenVK/MoltenVK/Layers/MVKExtensions.mm index 596f5882a..11f98b49e 100644 --- a/MoltenVK/MoltenVK/Layers/MVKExtensions.mm +++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.mm @@ -19,7 +19,7 @@ #include "MVKExtensions.h" #include "MVKFoundation.h" #include "MVKOSExtensions.h" -#include "MVKEnvironment.h" +#include "mvk_deprecated_api.h" #include #include @@ -39,33 +39,30 @@ static VkExtensionProperties mvkMakeExtProps(const char* extensionName, uint32_t } // Extension properties -#define MVK_EXTENSION(var, EXT, type, macos, ios) \ +#define MVK_EXTENSION(var, EXT, type, macos, ios, xros) \ static VkExtensionProperties kVkExtProps_ ##EXT = mvkMakeExtProps(VK_ ##EXT ##_EXTENSION_NAME, VK_ ##EXT ##_SPEC_VERSION); #include "MVKExtensions.def" // Returns whether the specified properties are valid for this platform static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) { -#define MVK_EXTENSION_MIN_OS(EXT, MAC, IOS) \ - if (pProperties == &kVkExtProps_##EXT) { return mvkOSVersionIsAtLeast(MAC, IOS); } +#define MVK_EXTENSION_MIN_OS(EXT, MAC, IOS, XROS) \ + if (pProperties == &kVkExtProps_##EXT) { return mvkOSVersionIsAtLeast(MAC, IOS, XROS); } // If the config indicates that not all supported extensions should be advertised, // only advertise those supported extensions that have been specifically configured. auto advExtns = mvkConfig().advertiseExtensions; if ( !mvkIsAnyFlagEnabled(advExtns, MVK_CONFIG_ADVERTISE_EXTENSIONS_ALL) ) { #define MVK_NA kMVKOSVersionUnsupported - if (mvkIsAnyFlagEnabled(advExtns, MVK_CONFIG_ADVERTISE_EXTENSIONS_MOLTENVK)) { - MVK_EXTENSION_MIN_OS(MVK_MOLTENVK, 10.11, 8.0) - } if (mvkIsAnyFlagEnabled(advExtns, MVK_CONFIG_ADVERTISE_EXTENSIONS_WSI)) { - MVK_EXTENSION_MIN_OS(EXT_METAL_SURFACE, 10.11, 8.0) - MVK_EXTENSION_MIN_OS(MVK_IOS_SURFACE, MVK_NA, 8.0) - MVK_EXTENSION_MIN_OS(MVK_MACOS_SURFACE, 10.11, MVK_NA) - MVK_EXTENSION_MIN_OS(KHR_SURFACE, 10.11, 8.0) - MVK_EXTENSION_MIN_OS(KHR_SWAPCHAIN, 10.11, 8.0) + MVK_EXTENSION_MIN_OS(EXT_METAL_SURFACE, 10.11, 8.0, 1.0) + MVK_EXTENSION_MIN_OS(MVK_IOS_SURFACE, MVK_NA, 8.0, 1.0) + MVK_EXTENSION_MIN_OS(MVK_MACOS_SURFACE, 10.11, MVK_NA, MVK_NA) + MVK_EXTENSION_MIN_OS(KHR_SURFACE, 10.11, 8.0, 1.0) + MVK_EXTENSION_MIN_OS(KHR_SWAPCHAIN, 10.11, 8.0, 1.0) } if (mvkIsAnyFlagEnabled(advExtns, MVK_CONFIG_ADVERTISE_EXTENSIONS_PORTABILITY)) { - MVK_EXTENSION_MIN_OS(KHR_PORTABILITY_SUBSET, 10.11, 8.0) - MVK_EXTENSION_MIN_OS(KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2, 10.11, 8.0) + MVK_EXTENSION_MIN_OS(KHR_PORTABILITY_SUBSET, 10.11, 8.0, 1.0) + MVK_EXTENSION_MIN_OS(KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2, 10.11, 8.0, 1.0) } #undef MVK_NA @@ -73,7 +70,7 @@ static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) { } // Otherwise, emumerate all available extensions to match the extension being validated for OS support. -#define MVK_EXTENSION(var, EXT, type, macos, ios) MVK_EXTENSION_MIN_OS(EXT, macos, ios) +#define MVK_EXTENSION(var, EXT, type, macos, ios, xros) MVK_EXTENSION_MIN_OS(EXT, macos, ios, xros) #include "MVKExtensions.def" #undef MVK_EXTENSION_MIN_OS @@ -91,8 +88,8 @@ static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) { #pragma mark MVKExtensionList MVKExtensionList::MVKExtensionList(MVKVulkanAPIObject* apiObject, bool enableForPlatform) : -#define MVK_EXTENSION_LAST(var, EXT, type, macos, ios) vk_ ##var(&kVkExtProps_ ##EXT, enableForPlatform) -#define MVK_EXTENSION(var, EXT, type, macos, ios) MVK_EXTENSION_LAST(var, EXT, type, macos, ios), +#define MVK_EXTENSION_LAST(var, EXT, type, macos, ios, xros) vk_ ##var(&kVkExtProps_ ##EXT, enableForPlatform) +#define MVK_EXTENSION(var, EXT, type, macos, ios, xros) MVK_EXTENSION_LAST(var, EXT, type, macos, ios, xros), #include "MVKExtensions.def" , _apiObject(apiObject) { @@ -104,7 +101,7 @@ static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) { void MVKExtensionList::initCount() { _count = 0; -#define MVK_EXTENSION(var, EXT, type, macos, ios) _count++; +#define MVK_EXTENSION(var, EXT, type, macos, ios, xros) _count++; #include "MVKExtensions.def" } @@ -113,14 +110,14 @@ static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) { void MVKExtensionList::disableAllButEnabledInstanceExtensions() { #define MVK_EXTENSION_INSTANCE true #define MVK_EXTENSION_DEVICE false -#define MVK_EXTENSION(var, EXT, type, macos, ios) MVK_ENSURE_EXTENSION_TYPE(var, EXT, type) +#define MVK_EXTENSION(var, EXT, type, macos, ios, xros) MVK_ENSURE_EXTENSION_TYPE(var, EXT, type) #include "MVKExtensions.def" } void MVKExtensionList::disableAllButEnabledDeviceExtensions() { #define MVK_EXTENSION_INSTANCE false #define MVK_EXTENSION_DEVICE true -#define MVK_EXTENSION(var, EXT, type, macos, ios) MVK_ENSURE_EXTENSION_TYPE(var, EXT, type) +#define MVK_EXTENSION(var, EXT, type, macos, ios, xros) MVK_ENSURE_EXTENSION_TYPE(var, EXT, type) #include "MVKExtensions.def" } @@ -168,6 +165,11 @@ static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) { result = reportError(VK_ERROR_EXTENSION_NOT_PRESENT, "Vulkan extension %s is not supported.", extnName); } else { enable(extnName); + if (mvkStringsAreEqual(extnName, VK_MVK_MOLTENVK_EXTENSION_NAME)) { + reportMessage(MVK_CONFIG_LOG_LEVEL_WARNING, "Extension %s is deprecated. For access to Metal objects, use extension %s. " + "For MoltenVK configuration, use the global vkGetMoltenVKConfigurationMVK() and vkSetMoltenVKConfigurationMVK() functions.", + VK_MVK_MOLTENVK_EXTENSION_NAME, VK_EXT_METAL_OBJECTS_EXTENSION_NAME); + } } } return result; diff --git a/MoltenVK/MoltenVK/Layers/MVKLayers.mm b/MoltenVK/MoltenVK/Layers/MVKLayers.mm index 040712b31..875722b89 100644 --- a/MoltenVK/MoltenVK/Layers/MVKLayers.mm +++ b/MoltenVK/MoltenVK/Layers/MVKLayers.mm @@ -17,7 +17,6 @@ */ #include "MVKLayers.h" -#include "MVKEnvironment.h" #include "MVKFoundation.h" #include diff --git a/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.h b/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.h index 7181b237c..61a5c4396 100644 --- a/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.h +++ b/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.h @@ -76,7 +76,9 @@ */ @property(nonatomic, readwrite) CFStringRef colorspaceNameMVK; +#if !MVK_VISIONOS /** Returns the screen on which this layer is rendering. */ @property(nonatomic, readonly) PLATFORM_SCREEN_CLASS* screenMVK; +#endif @end diff --git a/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.m b/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.m index a9e5a009a..9a8b10d8d 100644 --- a/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.m +++ b/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.m @@ -80,7 +80,7 @@ -(void) setColorspaceNameMVK: (CFStringRef) name { CGColorSpaceRelease(csRef); } -#if MVK_IOS_OR_TVOS || MVK_MACCAT +#if (MVK_IOS_OR_TVOS || MVK_MACCAT) && !MVK_VISIONOS -(UIScreen*) screenMVK { return UIScreen.mainScreen; } diff --git a/MoltenVK/MoltenVK/OS/MTLRenderPipelineDescriptor+MoltenVK.h b/MoltenVK/MoltenVK/OS/MTLRenderPipelineDescriptor+MoltenVK.h index b8cd92308..e889bafa0 100644 --- a/MoltenVK/MoltenVK/OS/MTLRenderPipelineDescriptor+MoltenVK.h +++ b/MoltenVK/MoltenVK/OS/MTLRenderPipelineDescriptor+MoltenVK.h @@ -34,3 +34,13 @@ @property(nonatomic, readwrite) MTLPrimitiveTopologyClass inputPrimitiveTopologyMVK; @end + +#if MVK_XCODE_14 + +@interface MTLMeshRenderPipelineDescriptor (MoltenVK) + +@property(nonatomic, readwrite) MTLPrimitiveTopologyClass inputPrimitiveTopologyMVK; + +@end + +#endif diff --git a/MoltenVK/MoltenVK/OS/MTLRenderPipelineDescriptor+MoltenVK.m b/MoltenVK/MoltenVK/OS/MTLRenderPipelineDescriptor+MoltenVK.m index ab46bcebf..3e2b9d7f8 100644 --- a/MoltenVK/MoltenVK/OS/MTLRenderPipelineDescriptor+MoltenVK.m +++ b/MoltenVK/MoltenVK/OS/MTLRenderPipelineDescriptor+MoltenVK.m @@ -32,3 +32,18 @@ -(void) setInputPrimitiveTopologyMVK: (MTLPrimitiveTopologyClass) topology { } @end + +#if MVK_XCODE_14 + +@implementation MTLMeshRenderPipelineDescriptor (MoltenVK) + +-(MTLPrimitiveTopologyClass) inputPrimitiveTopologyMVK { + return MTLPrimitiveTopologyClassUnspecified; +} + +-(void) setInputPrimitiveTopologyMVK: (MTLPrimitiveTopologyClass) topology { +} + +@end + +#endif diff --git a/MoltenVK/MoltenVK/OS/MVKGPUCapture.mm b/MoltenVK/MoltenVK/OS/MVKGPUCapture.mm index 785694cd2..03cabc73a 100644 --- a/MoltenVK/MoltenVK/OS/MVKGPUCapture.mm +++ b/MoltenVK/MoltenVK/OS/MVKGPUCapture.mm @@ -17,9 +17,7 @@ */ #include "MVKGPUCapture.h" -#include "MVKQueue.h" #include "MVKOSExtensions.h" -#include "MVKEnvironment.h" #pragma mark - @@ -69,7 +67,7 @@ MVKGPUCaptureScope::MVKGPUCaptureScope(MVKQueue* mvkQueue) { _mtlQueue = [mvkQueue->getMTLCommandQueue() retain]; // retained - if (mvkOSVersionIsAtLeast(10.13, 11.0)) { + if (mvkOSVersionIsAtLeast(10.13, 11.0, 1.0)) { _mtlCaptureScope = [[MTLCaptureManager sharedCaptureManager] newCaptureScopeWithCommandQueue: _mtlQueue]; // retained _mtlCaptureScope.label = @(mvkQueue->getName().c_str()); @@ -79,7 +77,7 @@ // that depends on Apple not taking internal references to capture scopes, but without it, // we could get hung up waiting for a new queue, because the old queues are still outstanding. // This bug was fixed by Apple in macOS 12.4 and iOS 15.4. - if ( !mvkOSVersionIsAtLeast(12.04, 15.04) ) { + if ( !mvkOSVersionIsAtLeast(12.04, 15.04, 1.0) ) { while (_mtlCaptureScope.retainCount > 1) { [_mtlCaptureScope release]; } diff --git a/MoltenVK/MoltenVK/Utility/MVKBaseObject.h b/MoltenVK/MoltenVK/Utility/MVKBaseObject.h index d71a37f89..7005e9850 100644 --- a/MoltenVK/MoltenVK/Utility/MVKBaseObject.h +++ b/MoltenVK/MoltenVK/Utility/MVKBaseObject.h @@ -18,7 +18,7 @@ #pragma once -#include "vk_mvk_moltenvk.h" +#include "MVKEnvironment.h" #include #include diff --git a/MoltenVK/MoltenVK/Utility/MVKBaseObject.mm b/MoltenVK/MoltenVK/Utility/MVKBaseObject.mm index d2dc3c91f..427c32278 100644 --- a/MoltenVK/MoltenVK/Utility/MVKBaseObject.mm +++ b/MoltenVK/MoltenVK/Utility/MVKBaseObject.mm @@ -21,7 +21,7 @@ #include "MVKInstance.h" #include "MVKFoundation.h" #include "MVKOSExtensions.h" -#include +#include "MVKStrings.h" using namespace std; @@ -44,13 +44,7 @@ #pragma mark - #pragma mark MVKBaseObject -string MVKBaseObject::getClassName() { - int status; - char* demangled = abi::__cxa_demangle(typeid(*this).name(), 0, 0, &status); - string clzName = demangled; - free(demangled); - return clzName; -} +string MVKBaseObject::getClassName() { return mvk::getTypeName(this); } void MVKBaseObject::reportMessage(MVKConfigLogLevel logLevel, const char* format, ...) { va_list args; diff --git a/MoltenVK/MoltenVK/Utility/MVKCodec.h b/MoltenVK/MoltenVK/Utility/MVKCodec.h index 595a50fa6..a366dd786 100644 --- a/MoltenVK/MoltenVK/Utility/MVKCodec.h +++ b/MoltenVK/MoltenVK/Utility/MVKCodec.h @@ -20,7 +20,6 @@ #pragma once #include "MVKEnvironment.h" - #include #include diff --git a/MoltenVK/MoltenVK/Utility/MVKCodec.mm b/MoltenVK/MoltenVK/Utility/MVKCodec.mm index 7c07d6afd..d75578f7d 100644 --- a/MoltenVK/MoltenVK/Utility/MVKCodec.mm +++ b/MoltenVK/MoltenVK/Utility/MVKCodec.mm @@ -24,6 +24,8 @@ #include #include +#import + using namespace std; using simd::float3; @@ -148,7 +150,9 @@ static size_t mvkCompressDecompress(const uint8_t* srcBytes, size_t srcSize, MVKConfigCompressionAlgorithm compAlgo, bool isCompressing) { size_t dstByteCount = 0; - if (compAlgo != MVK_CONFIG_COMPRESSION_ALGORITHM_NONE) { + bool compressionSupported = ([NSData instancesRespondToSelector: @selector(compressedDataUsingAlgorithm:error:)] && + [NSData instancesRespondToSelector: @selector(decompressedDataUsingAlgorithm:error:)]); + if (compressionSupported && compAlgo != MVK_CONFIG_COMPRESSION_ALGORITHM_NONE) { @autoreleasepool { NSDataCompressionAlgorithm sysCompAlgo = getSystemCompressionAlgo(compAlgo); NSData* srcData = [NSData dataWithBytesNoCopy: (void*)srcBytes length: srcSize freeWhenDone: NO]; diff --git a/MoltenVK/MoltenVK/Utility/MVKEnvironment.cpp b/MoltenVK/MoltenVK/Utility/MVKEnvironment.cpp index 1381c616b..5aa6f7dbc 100644 --- a/MoltenVK/MoltenVK/Utility/MVKEnvironment.cpp +++ b/MoltenVK/MoltenVK/Utility/MVKEnvironment.cpp @@ -63,6 +63,7 @@ static void mvkInitConfigFromEnvVars() { MVK_SET_FROM_ENV_OR_BUILD_BOOL (evCfg.resumeLostDevice, MVK_CONFIG_RESUME_LOST_DEVICE); MVK_SET_FROM_ENV_OR_BUILD_INT32 (evCfg.useMetalArgumentBuffers, MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS); MVK_SET_FROM_ENV_OR_BUILD_INT32 (evCfg.shaderSourceCompressionAlgorithm, MVK_CONFIG_SHADER_COMPRESSION_ALGORITHM); + MVK_SET_FROM_ENV_OR_BUILD_BOOL (evCfg.shouldMaximizeConcurrentCompilation, MVK_CONFIG_SHOULD_MAXIMIZE_CONCURRENT_COMPILATION); // Deprected legacy VkSemaphore MVK_ALLOW_METAL_FENCES and MVK_ALLOW_METAL_EVENTS config. // Legacy MVK_ALLOW_METAL_EVENTS is covered by MVK_CONFIG_VK_SEMAPHORE_SUPPORT_STYLE, diff --git a/MoltenVK/MoltenVK/Utility/MVKEnvironment.h b/MoltenVK/MoltenVK/Utility/MVKEnvironment.h index cec1740e7..86215bf9f 100644 --- a/MoltenVK/MoltenVK/Utility/MVKEnvironment.h +++ b/MoltenVK/MoltenVK/Utility/MVKEnvironment.h @@ -20,8 +20,9 @@ #pragma once #include "MVKCommonEnvironment.h" +#include "mvk_vulkan.h" +#include "mvk_config.h" #include "MVKLogging.h" -#include "vk_mvk_moltenvk.h" // Expose MoltenVK Apple surface extension functionality @@ -294,3 +295,11 @@ void mvkSetConfig(const MVKConfiguration& mvkConfig); #ifndef MVK_CONFIG_SHADER_COMPRESSION_ALGORITHM # define MVK_CONFIG_SHADER_COMPRESSION_ALGORITHM MVK_CONFIG_COMPRESSION_ALGORITHM_NONE #endif + +/** + * Maximize the concurrent executing compilation tasks. + * This functionality requires macOS 13.3. Disabled by default. + */ +#ifndef MVK_CONFIG_SHOULD_MAXIMIZE_CONCURRENT_COMPILATION +# define MVK_CONFIG_SHOULD_MAXIMIZE_CONCURRENT_COMPILATION 0 +#endif diff --git a/MoltenVK/MoltenVK/Utility/MVKFoundation.h b/MoltenVK/MoltenVK/Utility/MVKFoundation.h index 58b85d150..b8f10720f 100644 --- a/MoltenVK/MoltenVK/Utility/MVKFoundation.h +++ b/MoltenVK/MoltenVK/Utility/MVKFoundation.h @@ -20,8 +20,7 @@ #pragma once -#include "MVKCommonEnvironment.h" -#include "mvk_vulkan.h" +#include "MVKEnvironment.h" #include #include #include @@ -92,7 +91,7 @@ typedef enum : uint8_t { kMVKCommandUseResetQueryPool, /**< vkCmdResetQueryPool. */ kMVKCommandUseDispatch, /**< vkCmdDispatch. */ kMVKCommandUseTessellationVertexTessCtl, /**< vkCmdDraw* - vertex and tessellation control stages. */ - kMVKCommandUseMultiviewInstanceCountAdjust, /**< vkCmdDrawIndirect* - adjust instance count for multiview. */ + kMVKCommandUseDrawIndirectConvertBuffers, /**< vkCmdDrawIndirect* convert indirect buffers. */ kMVKCommandUseCopyQueryPoolResults, /**< vkCmdCopyQueryPoolResults. */ kMVKCommandUseAccumOcclusionQuery, /**< Any command terminating a Metal render pass with active visibility buffer. */ kMVKCommandUseRecordGPUCounterSample /**< Any command triggering the recording of a GPU counter sample. */ @@ -218,6 +217,44 @@ static constexpr uint64_t mvkAlignByteCount(uint64_t byteCount, uint64_t byteAli return mvkAlignByteRef(byteCount, byteAlignment, alignDown); } +/** + * Compile time indication if the struct contains a specific member. + * + * If S::mbr is well-formed because the struct contains that member, the decltype() and + * comma operator together trigger a true_type, otherwise it falls back to a false_type. + * + * Credit to: https://fekir.info/post/detect-member-variables/ + */ +#define mvk_define_has_member(mbr) \ + template struct mvk_has_##mbr : std::false_type {}; \ + template struct mvk_has_##mbr : std::true_type {}; + +mvk_define_has_member(pNext); // Defines the mvk_has_pNext() function. + +/** Returns the address of the first member of a structure, which is just the address of the structure. */ +template +void* mvkGetAddressOfFirstMember(const S* pStruct, std::false_type){ + return (void*)pStruct; +} + +/** + * Returns the address of the first member of a Vulkan structure containing a pNext member. + * The first member is the one after the pNext member. + */ +template +void* mvkGetAddressOfFirstMember(const S* pStruct, std::true_type){ + return (void*)(&(pStruct->pNext) + 1); +} + +/** + * Returns the address of the first member of a structure. If the structure is a Vulkan + * structure containing a pNext member, the first member is the one after the pNext member. + */ +template +void* mvkGetAddressOfFirstMember(const S* pStruct){ + return mvkGetAddressOfFirstMember(pStruct, mvk_has_pNext{}); +} + /** * Reverses the order of the rows in the specified data block. * The transformation is performed in-place. @@ -484,7 +521,7 @@ void mvkReleaseContainerContents(C& container) { /** Returns whether the container contains an item equal to the value. */ template -bool contains(C& container, const T& val) { +bool mvkContains(C& container, const T& val) { for (const T& cVal : container) { if (cVal == val) { return true; } } return false; } @@ -553,12 +590,13 @@ bool mvkAreEqual(const T* pV1, const T* pV2, size_t count = 1) { } /** - * If both pV1 and pV2 are not null, returns whether the contents of the two strings are equal, - * otherwise returns false. This functionality is different than the char version of mvkAreEqual(), + * Returns whether the contents of the two strings are equal, otherwise returns false. + * This functionality is different than the char version of mvkAreEqual(), * which works on individual chars or char arrays, not strings. + * Returns false if either string is null. */ static constexpr bool mvkStringsAreEqual(const char* pV1, const char* pV2, size_t count = 1) { - return (pV1 && pV2) ? (strcmp(pV1, pV2) == 0) : false; + return pV1 && pV2 && (pV1 == pV2 || strcmp(pV1, pV2) == 0); } /** diff --git a/MoltenVK/MoltenVK/Utility/MVKWatermark.mm b/MoltenVK/MoltenVK/Utility/MVKWatermark.mm index a016f98fe..7542b9b75 100644 --- a/MoltenVK/MoltenVK/Utility/MVKWatermark.mm +++ b/MoltenVK/MoltenVK/Utility/MVKWatermark.mm @@ -17,10 +17,10 @@ */ +#include "MVKEnvironment.h" #include "MVKWatermark.h" #include "MVKOSExtensions.h" #include "MTLTextureDescriptor+MoltenVK.h" -#include "MVKEnvironment.h" /** The structure to hold shader uniforms. */ diff --git a/MoltenVK/MoltenVK/Vulkan/vk_mvk_moltenvk.mm b/MoltenVK/MoltenVK/Vulkan/mvk_api.mm similarity index 89% rename from MoltenVK/MoltenVK/Vulkan/vk_mvk_moltenvk.mm rename to MoltenVK/MoltenVK/Vulkan/mvk_api.mm index c6f7844ce..b2151e9bb 100644 --- a/MoltenVK/MoltenVK/Vulkan/vk_mvk_moltenvk.mm +++ b/MoltenVK/MoltenVK/Vulkan/mvk_api.mm @@ -1,5 +1,5 @@ /* - * vk_mvk_moltenvk.mm + * mvk_api.mm * * Copyright (c) 2015-2023 The Brenwill Workshop Ltd. (http://www.brenwill.com) * @@ -17,9 +17,10 @@ */ -#include "MVKInstance.h" -#include "vk_mvk_moltenvk.h" #include "MVKEnvironment.h" +#include "mvk_private_api.h" +#include "mvk_deprecated_api.h" +#include "MVKInstance.h" #include "MVKSwapchain.h" #include "MVKImage.h" #include "MVKBuffer.h" @@ -30,6 +31,7 @@ using namespace std; +// Copies the contents of a struct that might grow larger across MoltenVK versions. // If pSrc and pDst are not null, copies at most *pCopySize bytes from the contents of the // source struct to the destination struct, and sets *pCopySize to the number of bytes copied, // which is the smaller of the original value of *pCopySize and the actual size of the struct. @@ -37,7 +39,7 @@ // the struct, or VK_INCOMPLETE otherwise. If either pSrc or pDst are null, sets the value // of *pCopySize to the size of the struct and returns VK_SUCCESS. template -VkResult mvkCopy(S* pDst, const S* pSrc, size_t* pCopySize) { +VkResult mvkCopyGrowingStruct(S* pDst, const S* pSrc, size_t* pCopySize) { if (pSrc && pDst) { size_t origSize = *pCopySize; *pCopySize = std::min(origSize, sizeof(S)); @@ -49,12 +51,16 @@ VkResult mvkCopy(S* pDst, const S* pSrc, size_t* pCopySize) { } } + +#pragma mark - +#pragma mark mvk_config.h + MVK_PUBLIC_VULKAN_SYMBOL VkResult vkGetMoltenVKConfigurationMVK( VkInstance ignored, MVKConfiguration* pConfiguration, size_t* pConfigurationSize) { - return mvkCopy(pConfiguration, &mvkConfig(), pConfigurationSize); + return mvkCopyGrowingStruct(pConfiguration, &mvkConfig(), pConfigurationSize); } MVK_PUBLIC_VULKAN_SYMBOL VkResult vkSetMoltenVKConfigurationMVK( @@ -64,18 +70,22 @@ MVK_PUBLIC_VULKAN_SYMBOL VkResult vkSetMoltenVKConfigurationMVK( // Start with copy of current config, in case incoming is not fully copied MVKConfiguration mvkCfg = mvkConfig(); - VkResult rslt = mvkCopy(&mvkCfg, pConfiguration, pConfigurationSize); + VkResult rslt = mvkCopyGrowingStruct(&mvkCfg, pConfiguration, pConfigurationSize); mvkSetConfig(mvkCfg); return rslt; } + +#pragma mark - +#pragma mark mvk_private_api.h + MVK_PUBLIC_VULKAN_SYMBOL VkResult vkGetPhysicalDeviceMetalFeaturesMVK( VkPhysicalDevice physicalDevice, MVKPhysicalDeviceMetalFeatures* pMetalFeatures, size_t* pMetalFeaturesSize) { MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice); - return mvkCopy(pMetalFeatures, mvkPD->getMetalFeatures(), pMetalFeaturesSize); + return mvkCopyGrowingStruct(pMetalFeatures, mvkPD->getMetalFeatures(), pMetalFeaturesSize); } MVK_PUBLIC_VULKAN_SYMBOL VkResult vkGetPerformanceStatisticsMVK( @@ -85,9 +95,13 @@ MVK_PUBLIC_VULKAN_SYMBOL VkResult vkGetPerformanceStatisticsMVK( MVKPerformanceStatistics mvkPerf; MVKDevice::getMVKDevice(device)->getPerformanceStatistics(&mvkPerf); - return mvkCopy(pPerf, &mvkPerf, pPerfSize); + return mvkCopyGrowingStruct(pPerf, &mvkPerf, pPerfSize); } + +#pragma mark - +#pragma mark mvk_deprecated_api.h + MVK_PUBLIC_VULKAN_SYMBOL void vkGetVersionStringsMVK( char* pMoltenVersionStringBuffer, uint32_t moltenVersionStringBufferLength, diff --git a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm index 1960dedd9..1bb3d7e59 100644 --- a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm +++ b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm @@ -228,6 +228,45 @@ MVK_PUBLIC_SYMBOL MTLTextureSwizzleChannels mvkMTLTextureSwizzleChannelsFromVkCo #undef convert } +MVK_PUBLIC_SYMBOL float mvkVkClearColorFloatValueFromVkComponentSwizzle(float *colors, uint32_t index, VkComponentSwizzle vkSwizzle) { + switch (vkSwizzle) { + case VK_COMPONENT_SWIZZLE_IDENTITY: return colors[index]; + case VK_COMPONENT_SWIZZLE_ZERO: return 0.f; + case VK_COMPONENT_SWIZZLE_ONE: return 1.f; + case VK_COMPONENT_SWIZZLE_R: return colors[0]; + case VK_COMPONENT_SWIZZLE_G: return colors[1]; + case VK_COMPONENT_SWIZZLE_B: return colors[2]; + case VK_COMPONENT_SWIZZLE_A: return colors[3]; + default: return colors[index]; + } +} + +MVK_PUBLIC_SYMBOL uint32_t mvkVkClearColorUIntValueFromVkComponentSwizzle(uint32_t *colors, uint32_t index, VkComponentSwizzle vkSwizzle) { + switch (vkSwizzle) { + case VK_COMPONENT_SWIZZLE_IDENTITY: return colors[index]; + case VK_COMPONENT_SWIZZLE_ZERO: return 0U; + case VK_COMPONENT_SWIZZLE_ONE: return 1U; + case VK_COMPONENT_SWIZZLE_R: return colors[0]; + case VK_COMPONENT_SWIZZLE_G: return colors[1]; + case VK_COMPONENT_SWIZZLE_B: return colors[2]; + case VK_COMPONENT_SWIZZLE_A: return colors[3]; + default: return colors[index]; + } +} + +MVK_PUBLIC_SYMBOL int32_t mvkVkClearColorIntValueFromVkComponentSwizzle(int32_t *colors, uint32_t index, VkComponentSwizzle vkSwizzle) { + switch (vkSwizzle) { + case VK_COMPONENT_SWIZZLE_IDENTITY: return colors[index]; + case VK_COMPONENT_SWIZZLE_ZERO: return 0; + case VK_COMPONENT_SWIZZLE_ONE: return 1; + case VK_COMPONENT_SWIZZLE_R: return colors[0]; + case VK_COMPONENT_SWIZZLE_G: return colors[1]; + case VK_COMPONENT_SWIZZLE_B: return colors[2]; + case VK_COMPONENT_SWIZZLE_A: return colors[3]; + default: return colors[index]; + } +} + #pragma mark Mipmaps @@ -412,13 +451,13 @@ MTLPrimitiveType mvkMTLPrimitiveTypeFromVkPrimitiveTopologyInObj(VkPrimitiveTopo case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: + case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: return MTLPrimitiveTypeTriangle; case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: return MTLPrimitiveTypeTriangleStrip; - case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: default: MVKBaseObject::reportError(mvkObj, VK_ERROR_FORMAT_NOT_SUPPORTED, "VkPrimitiveTopology value %d is not supported for rendering.", vkTopology); return MTLPrimitiveTypePoint; @@ -634,7 +673,7 @@ MVKShaderStage mvkShaderStageFromVkShaderStageFlagBitsInObj(VkShaderStageFlagBit case VK_SHADER_STAGE_VERTEX_BIT: return kMVKShaderStageVertex; case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return kMVKShaderStageTessCtl; case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: return kMVKShaderStageTessEval; - /* FIXME: VK_SHADER_STAGE_GEOMETRY_BIT */ + case VK_SHADER_STAGE_GEOMETRY_BIT: return kMVKShaderStageGeometry; case VK_SHADER_STAGE_FRAGMENT_BIT: return kMVKShaderStageFragment; case VK_SHADER_STAGE_COMPUTE_BIT: return kMVKShaderStageCompute; default: @@ -648,7 +687,7 @@ MVK_PUBLIC_SYMBOL VkShaderStageFlagBits mvkVkShaderStageFlagBitsFromMVKShaderSta case kMVKShaderStageVertex: return VK_SHADER_STAGE_VERTEX_BIT; case kMVKShaderStageTessCtl: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; case kMVKShaderStageTessEval: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; - /* FIXME: kMVKShaderStageGeometry */ + case kMVKShaderStageGeometry: return VK_SHADER_STAGE_GEOMETRY_BIT; case kMVKShaderStageFragment: return VK_SHADER_STAGE_FRAGMENT_BIT; case kMVKShaderStageCompute: return VK_SHADER_STAGE_COMPUTE_BIT; case kMVKShaderStageCount: @@ -741,10 +780,15 @@ MVK_PUBLIC_SYMBOL VkExtent2D mvkVkExtent2DFromCGSize(CGSize cgSize) { } MVK_PUBLIC_SYMBOL CGSize mvkCGSizeFromVkExtent2D(VkExtent2D vkExtent) { - CGSize cgSize; - cgSize.width = vkExtent.width; - cgSize.height = vkExtent.height; - return cgSize; + return CGSizeMake(vkExtent.width, vkExtent.height); +} + +MVK_PUBLIC_SYMBOL CGPoint mvkCGPointFromVkOffset2D(VkOffset2D vkOffset) { + return CGPointMake(vkOffset.x, vkOffset.y); +} + +MVK_PUBLIC_SYMBOL CGRect mvkCGRectFromVkRectLayerKHR(VkRectLayerKHR vkRect) { + return { mvkCGPointFromVkOffset2D(vkRect.offset), mvkCGSizeFromVkExtent2D(vkRect.extent) }; } diff --git a/MoltenVK/MoltenVK/Vulkan/vulkan.mm b/MoltenVK/MoltenVK/Vulkan/vulkan.mm index be2307cbb..44b0e5f69 100644 --- a/MoltenVK/MoltenVK/Vulkan/vulkan.mm +++ b/MoltenVK/MoltenVK/Vulkan/vulkan.mm @@ -2653,13 +2653,67 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdResolveImage2( MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdNextSubpass2, KHR); MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdEndRenderPass2, KHR); - #pragma mark - -#pragma mark VK_KHR_dynamic_rendering extension +#pragma mark VK_KHR_deferred_host_operations extension -MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdBeginRendering, KHR); -MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdEndRendering, KHR); +MVK_PUBLIC_VULKAN_SYMBOL VkResult vkCreateDeferredOperationKHR( + VkDevice device, + const VkAllocationCallbacks* pAllocator, + VkDeferredOperationKHR* pDeferredOperation) { + + MVKTraceVulkanCallStart(); + MVKDevice* mvkDev = MVKDevice::getMVKDevice(device); + MVKDeferredOperation* mvkDeferredOperation = mvkDev->createDeferredOperation(pAllocator); + *pDeferredOperation = (VkDeferredOperationKHR)mvkDeferredOperation; + VkResult rslt = mvkDeferredOperation->getConfigurationResult(); + MVKTraceVulkanCallEnd(); + return rslt; +} + +MVK_PUBLIC_VULKAN_SYMBOL VkResult vkGetDeferredOperationResultKHR( + VkDevice device, + VkDeferredOperationKHR operation) { + + MVKTraceVulkanCallStart(); + MVKDeferredOperation* mvkDeferredOperation = (MVKDeferredOperation*)operation; + VkResult rslt = mvkDeferredOperation->getOperationResult(); + MVKTraceVulkanCallEnd(); + return rslt; +} + +MVK_PUBLIC_VULKAN_SYMBOL VkResult vkDeferredOperationJoinKHR( + VkDevice device, + VkDeferredOperationKHR operation) { + + MVKTraceVulkanCallStart(); + MVKDeferredOperation* mvkDeferredOperation = (MVKDeferredOperation*)operation; + VkResult rslt = mvkDeferredOperation->join(); + MVKTraceVulkanCallEnd(); + return rslt; +} + +MVK_PUBLIC_VULKAN_SYMBOL uint32_t vkGetDeferredOperationMaxConcurrencyKHR( + VkDevice device, + VkDeferredOperationKHR operation) { + + MVKTraceVulkanCallStart(); + MVKDeferredOperation* mvkDeferredOperation = (MVKDeferredOperation*)operation; + uint32_t getMaxConcurrencyKHR = mvkDeferredOperation->getMaxConcurrency(); + MVKTraceVulkanCallEnd(); + return getMaxConcurrencyKHR; +} +MVK_PUBLIC_VULKAN_SYMBOL void vkDestroyDeferredOperationKHR( + VkDevice device, + VkDeferredOperationKHR operation, + const VkAllocationCallbacks* pAllocator) { + + MVKTraceVulkanCallStart(); + MVKDevice* mvkDev = MVKDevice::getMVKDevice(device); + MVKDeferredOperation* mvkDeferredOperation = (MVKDeferredOperation*)operation; + mvkDev->destroyDeferredOperation(mvkDeferredOperation, pAllocator); + MVKTraceVulkanCallEnd(); +} #pragma mark - #pragma mark VK_KHR_descriptor_update_template extension @@ -2689,6 +2743,11 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdResolveImage2( MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdDrawIndexedIndirectCount, KHR); MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdDrawIndirectCount, KHR); +#pragma mark - +#pragma mark VK_KHR_dynamic_rendering extension + +MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdBeginRendering, KHR); +MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdEndRendering, KHR); #pragma mark - #pragma mark VK_KHR_external_fence_capabilities extension @@ -3057,6 +3116,34 @@ MVK_PUBLIC_VULKAN_SYMBOL VkResult vkGetPhysicalDeviceSurfaceFormats2KHR( MVK_PUBLIC_VULKAN_CORE_ALIAS(vkGetBufferDeviceAddress, EXT); +#pragma mark - +#pragma mark VK_EXT_calibrated_timestamps extension + +MVK_PUBLIC_VULKAN_SYMBOL VkResult vkGetPhysicalDeviceCalibrateableTimeDomainsEXT( + VkPhysicalDevice physicalDevice, + uint32_t* pTimeDomainCount, + VkTimeDomainEXT* pTimeDomains) { + MVKTraceVulkanCallStart(); + MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice); + mvkPD->getCalibrateableTimeDomains(pTimeDomainCount, pTimeDomains); + MVKTraceVulkanCallEnd(); + return VK_SUCCESS; +} + +MVK_PUBLIC_VULKAN_SYMBOL VkResult vkGetCalibratedTimestampsEXT( + VkDevice device, + uint32_t timestampCount, + const VkCalibratedTimestampInfoEXT* pTimestampInfos, + uint64_t* pTimestamps, + uint64_t* pMaxDeviation) { + MVKTraceVulkanCallStart(); + MVKDevice* mvkDev = MVKDevice::getMVKDevice(device); + mvkDev->getCalibratedTimestamps(timestampCount, pTimestampInfos, pTimestamps, pMaxDeviation); + MVKTraceVulkanCallEnd(); + return VK_SUCCESS; +} + + #pragma mark - #pragma mark VK_EXT_debug_report extension diff --git a/MoltenVKPackaging.xcodeproj/project.pbxproj b/MoltenVKPackaging.xcodeproj/project.pbxproj index 3483c1361..29899ab6a 100644 --- a/MoltenVKPackaging.xcodeproj/project.pbxproj +++ b/MoltenVKPackaging.xcodeproj/project.pbxproj @@ -69,6 +69,18 @@ name = MoltenVK; productName = Package; }; + DCFD7ED52A45BC56007BBBF7 /* MoltenVK-xrOS */ = { + isa = PBXAggregateTarget; + buildConfigurationList = DCFD7ED92A45BC56007BBBF7 /* Build configuration list for PBXAggregateTarget "MoltenVK-xrOS" */; + buildPhases = ( + DCFD7ED82A45BC56007BBBF7 /* Package MoltenVK */, + ); + dependencies = ( + DCFD7F682A45BC81007BBBF7 /* PBXTargetDependency */, + ); + name = "MoltenVK-xrOS"; + productName = Package; + }; /* End PBXAggregateTarget section */ /* Begin PBXContainerItemProxy section */ @@ -170,6 +182,20 @@ remoteGlobalIDString = 2FEA0D142490381A00EEF3AD; remoteInfo = "MoltenVKSPIRVToMSLConverter-tvOS"; }; + DCFD7F652A45BC7D007BBBF7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A92DB3EE1CE0F72500FBC835 /* MoltenVK.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = DCFD7F622A45BC6E007BBBF7; + remoteInfo = "MoltenVK-xrOS"; + }; + DCFD7F672A45BC81007BBBF7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A92DB3EE1CE0F72500FBC835 /* MoltenVK.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = DCFD7EDF2A45BC6E007BBBF7; + remoteInfo = "MoltenVK-xrOS"; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ @@ -229,6 +255,7 @@ A92DB3F51CE0F72500FBC835 /* libMoltenVK.a */, 2FEA0ABE2490302F00EEF3AD /* libMoltenVK.a */, A92DB3F71CE0F72500FBC835 /* libMoltenVK.a */, + DCFD7F662A45BC7D007BBBF7 /* libMoltenVK.a */, ); name = Products; sourceTree = ""; @@ -317,6 +344,7 @@ 2FEA0A2F24902F5E00EEF3AD /* MoltenVK-tvOS */, A975D58B2140586700D4834F /* MoltenVK-macOS */, A9AD700D2440ED3B00B9E254 /* MVKShaderConverterTool */, + DCFD7ED52A45BC56007BBBF7 /* MoltenVK-xrOS */, ); }; /* End PBXProject section */ @@ -371,6 +399,13 @@ remoteRef = A9FC5F5C249D2547003CB086 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + DCFD7F662A45BC7D007BBBF7 /* libMoltenVK.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libMoltenVK.a"; + remoteRef = DCFD7F652A45BC7D007BBBF7 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; /* End PBXReferenceProxy section */ /* Begin PBXShellScriptBuildPhase section */ @@ -458,6 +493,22 @@ shellPath = /bin/sh; shellScript = ". \"${SRCROOT}/Scripts/package_all.sh\"\n. \"${SRCROOT}/Scripts/package_shader_converter_tool.sh\"\n\n"; }; + DCFD7ED82A45BC56007BBBF7 /* Package MoltenVK */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${BUILT_PRODUCTS_DIR}/../XCFrameworkStaging", + ); + name = "Package MoltenVK"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/$(TARGET_NAME)/PackagePhaseDummyOutputFile", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = ". \"${SRCROOT}/Scripts/package_all.sh\"\n"; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -496,6 +547,11 @@ name = "MoltenVK-tvOS"; targetProxy = A9B1008424F84BA700EADC6E /* PBXContainerItemProxy */; }; + DCFD7F682A45BC81007BBBF7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "MoltenVK-xrOS"; + targetProxy = DCFD7F672A45BC81007BBBF7 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -583,6 +639,20 @@ }; name = Release; }; + DCFD7EDA2A45BC56007BBBF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + DCFD7EDB2A45BC56007BBBF7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -640,6 +710,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + DCFD7ED92A45BC56007BBBF7 /* Build configuration list for PBXAggregateTarget "MoltenVK-xrOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DCFD7EDA2A45BC56007BBBF7 /* Debug */, + DCFD7EDB2A45BC56007BBBF7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = A90B2B1D1A9B6170008EE819 /* Project object */; diff --git a/MoltenVKPackaging.xcodeproj/xcshareddata/xcschemes/MoltenVK Package (visionOS only).xcscheme b/MoltenVKPackaging.xcodeproj/xcshareddata/xcschemes/MoltenVK Package (visionOS only).xcscheme new file mode 100644 index 000000000..df10d0755 --- /dev/null +++ b/MoltenVKPackaging.xcodeproj/xcshareddata/xcschemes/MoltenVK Package (visionOS only).xcscheme @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MoltenVKShaderConverter/MoltenVKShaderConverter.xcodeproj/project.pbxproj b/MoltenVKShaderConverter/MoltenVKShaderConverter.xcodeproj/project.pbxproj index 56957d746..6372955e5 100644 --- a/MoltenVKShaderConverter/MoltenVKShaderConverter.xcodeproj/project.pbxproj +++ b/MoltenVKShaderConverter/MoltenVKShaderConverter.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -65,6 +65,23 @@ A9B51BDD225E98BB00AC74D2 /* MVKOSExtensions.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9B51BDB225E98BB00AC74D2 /* MVKOSExtensions.mm */; }; A9F042B21FB4D060009FCCB8 /* MVKCommonEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F042AA1FB4D060009FCCB8 /* MVKCommonEnvironment.h */; }; A9F042B31FB4D060009FCCB8 /* MVKCommonEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F042AA1FB4D060009FCCB8 /* MVKCommonEnvironment.h */; }; + DCFD7F712A45BDA0007BBBF7 /* SPIRVReflection.h in Headers */ = {isa = PBXBuildFile; fileRef = 450A4F5E220CB180007203D7 /* SPIRVReflection.h */; }; + DCFD7F722A45BDA0007BBBF7 /* GLSLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = A920A8A0251B75B70076851C /* GLSLConversion.h */; }; + DCFD7F732A45BDA0007BBBF7 /* MVKStrings.h in Headers */ = {isa = PBXBuildFile; fileRef = A98149651FB6A98A005F00B4 /* MVKStrings.h */; }; + DCFD7F742A45BDA0007BBBF7 /* SPIRVSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = A9546B242672A3B8004BA3E6 /* SPIRVSupport.h */; }; + DCFD7F752A45BDA0007BBBF7 /* SPIRVConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = A928C9171D0488DC00071B88 /* SPIRVConversion.h */; }; + DCFD7F762A45BDA0007BBBF7 /* GLSLToSPIRVConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = A920A8A2251B75B70076851C /* GLSLToSPIRVConverter.h */; }; + DCFD7F772A45BDA0007BBBF7 /* SPIRVToMSLConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = A9093F5B1C58013E0094110D /* SPIRVToMSLConverter.h */; }; + DCFD7F782A45BDA0007BBBF7 /* MVKCommonEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F042AA1FB4D060009FCCB8 /* MVKCommonEnvironment.h */; }; + DCFD7F7A2A45BDA0007BBBF7 /* FileSupport.mm in Sources */ = {isa = PBXBuildFile; fileRef = A925B70A1C7754B2006E7ECD /* FileSupport.mm */; }; + DCFD7F7B2A45BDA0007BBBF7 /* GLSLConversion.mm in Sources */ = {isa = PBXBuildFile; fileRef = A920A8A1251B75B70076851C /* GLSLConversion.mm */; }; + DCFD7F7C2A45BDA0007BBBF7 /* GLSLToSPIRVConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A920A89F251B75B70076851C /* GLSLToSPIRVConverter.cpp */; }; + DCFD7F7D2A45BDA0007BBBF7 /* SPIRVToMSLConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9093F5A1C58013E0094110D /* SPIRVToMSLConverter.cpp */; }; + DCFD7F7E2A45BDA0007BBBF7 /* SPIRVConversion.mm in Sources */ = {isa = PBXBuildFile; fileRef = A928C9181D0488DC00071B88 /* SPIRVConversion.mm */; }; + DCFD7F7F2A45BDA0007BBBF7 /* SPIRVSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9546B232672A3B8004BA3E6 /* SPIRVSupport.cpp */; }; + DCFD7F812A45BDA0007BBBF7 /* SPIRVTools.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = A983870224EEE94800199A05 /* SPIRVTools.xcframework */; }; + DCFD7F822A45BDA0007BBBF7 /* SPIRVCross.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = A98386F824EEE91A00199A05 /* SPIRVCross.xcframework */; }; + DCFD7F832A45BDA0007BBBF7 /* glslang.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = A98386FD24EEE93700199A05 /* glslang.xcframework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -108,6 +125,7 @@ A9B51BDB225E98BB00AC74D2 /* MVKOSExtensions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MVKOSExtensions.mm; sourceTree = ""; }; A9B51BDC225E98BB00AC74D2 /* MVKOSExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKOSExtensions.h; sourceTree = ""; }; A9F042AA1FB4D060009FCCB8 /* MVKCommonEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKCommonEnvironment.h; sourceTree = ""; }; + DCFD7F882A45BDA0007BBBF7 /* libMoltenVKShaderConverter.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libMoltenVKShaderConverter.a; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -150,6 +168,16 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + DCFD7F802A45BDA0007BBBF7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DCFD7F812A45BDA0007BBBF7 /* SPIRVTools.xcframework in Frameworks */, + DCFD7F822A45BDA0007BBBF7 /* SPIRVCross.xcframework in Frameworks */, + DCFD7F832A45BDA0007BBBF7 /* glslang.xcframework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -228,6 +256,7 @@ A9F042A81FB4D060009FCCB8 /* Common */, A964B28D1C57EBC400D930D8 /* Products */, A972AD2921CEE6A80013AB25 /* Frameworks */, + DCFD7F882A45BDA0007BBBF7 /* libMoltenVKShaderConverter.a */, ); sourceTree = ""; }; @@ -279,6 +308,21 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + DCFD7F702A45BDA0007BBBF7 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DCFD7F712A45BDA0007BBBF7 /* SPIRVReflection.h in Headers */, + DCFD7F722A45BDA0007BBBF7 /* GLSLConversion.h in Headers */, + DCFD7F732A45BDA0007BBBF7 /* MVKStrings.h in Headers */, + DCFD7F742A45BDA0007BBBF7 /* SPIRVSupport.h in Headers */, + DCFD7F752A45BDA0007BBBF7 /* SPIRVConversion.h in Headers */, + DCFD7F762A45BDA0007BBBF7 /* GLSLToSPIRVConverter.h in Headers */, + DCFD7F772A45BDA0007BBBF7 /* SPIRVToMSLConverter.h in Headers */, + DCFD7F782A45BDA0007BBBF7 /* MVKCommonEnvironment.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ @@ -353,6 +397,24 @@ productReference = A93903C71C57E9ED00FE90DC /* libMoltenVKShaderConverter.a */; productType = "com.apple.product-type.library.static"; }; + DCFD7F6F2A45BDA0007BBBF7 /* MoltenVKShaderConverter-xrOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = DCFD7F852A45BDA0007BBBF7 /* Build configuration list for PBXNativeTarget "MoltenVKShaderConverter-xrOS" */; + buildPhases = ( + DCFD7F702A45BDA0007BBBF7 /* Headers */, + DCFD7F792A45BDA0007BBBF7 /* Sources */, + DCFD7F802A45BDA0007BBBF7 /* Frameworks */, + DCFD7F842A45BDA0007BBBF7 /* Copy to Staging */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "MoltenVKShaderConverter-xrOS"; + productName = "MetalGLShaderConverter-macOS"; + productReference = DCFD7F882A45BDA0007BBBF7 /* libMoltenVKShaderConverter.a */; + productType = "com.apple.product-type.library.static"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -391,6 +453,7 @@ A93903B81C57E9D700FE90DC /* MoltenVKShaderConverter-iOS */, 2FEA0CFF2490381A00EEF3AD /* MoltenVKShaderConverter-tvOS */, A93903C01C57E9ED00FE90DC /* MoltenVKShaderConverter-macOS */, + DCFD7F6F2A45BDA0007BBBF7 /* MoltenVKShaderConverter-xrOS */, ); }; /* End PBXProject section */ @@ -456,6 +519,26 @@ shellPath = /bin/sh; shellScript = ". \"${SRCROOT}/../Scripts/copy_to_staging.sh\"\n"; }; + DCFD7F842A45BDA0007BBBF7 /* Copy to Staging */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${BUILT_PRODUCTS_DIR}/lib${PRODUCT_NAME}.a", + ); + name = "Copy to Staging"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/$(TARGET_NAME)/CopyPhaseDummyOutputFile", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = ". \"${SRCROOT}/../Scripts/copy_to_staging.sh\"\n"; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -510,6 +593,19 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + DCFD7F792A45BDA0007BBBF7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DCFD7F7A2A45BDA0007BBBF7 /* FileSupport.mm in Sources */, + DCFD7F7B2A45BDA0007BBBF7 /* GLSLConversion.mm in Sources */, + DCFD7F7C2A45BDA0007BBBF7 /* GLSLToSPIRVConverter.cpp in Sources */, + DCFD7F7D2A45BDA0007BBBF7 /* SPIRVToMSLConverter.cpp in Sources */, + DCFD7F7E2A45BDA0007BBBF7 /* SPIRVConversion.mm in Sources */, + DCFD7F7F2A45BDA0007BBBF7 /* SPIRVSupport.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -636,12 +732,12 @@ "\"$(SRCROOT)/glslang\"", "\"$(SRCROOT)/glslang/External/spirv-tools/include\"", ); - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACH_O_TYPE = staticlib; MACOSX_DEPLOYMENT_TARGET = 10.13; PRODUCT_NAME = MoltenVKShaderConverter; SKIP_INSTALL = YES; - TVOS_DEPLOYMENT_TARGET = 11.0; + TVOS_DEPLOYMENT_TARGET = 12.0; WARNING_CFLAGS = "-Wreorder"; }; name = Debug; @@ -696,17 +792,31 @@ "\"$(SRCROOT)/glslang\"", "\"$(SRCROOT)/glslang/External/spirv-tools/include\"", ); - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACH_O_TYPE = staticlib; MACOSX_DEPLOYMENT_TARGET = 10.13; PRODUCT_NAME = MoltenVKShaderConverter; SKIP_INSTALL = YES; - TVOS_DEPLOYMENT_TARGET = 11.0; + TVOS_DEPLOYMENT_TARGET = 12.0; VALIDATE_PRODUCT = YES; WARNING_CFLAGS = "-Wreorder"; }; name = Release; }; + DCFD7F862A45BDA0007BBBF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + SDKROOT = xros; + }; + name = Debug; + }; + DCFD7F872A45BDA0007BBBF7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + SDKROOT = xros; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -755,6 +865,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + DCFD7F852A45BDA0007BBBF7 /* Build configuration list for PBXNativeTarget "MoltenVKShaderConverter-xrOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DCFD7F862A45BDA0007BBBF7 /* Debug */, + DCFD7F872A45BDA0007BBBF7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = A9F55D25198BE6A7004EC31B /* Project object */; diff --git a/MoltenVKShaderConverter/MoltenVKShaderConverter.xcodeproj/xcshareddata/xcschemes/MoltenVKShaderConverter-xrOS.xcscheme b/MoltenVKShaderConverter/MoltenVKShaderConverter.xcodeproj/xcshareddata/xcschemes/MoltenVKShaderConverter-xrOS.xcscheme new file mode 100644 index 000000000..b78877057 --- /dev/null +++ b/MoltenVKShaderConverter/MoltenVKShaderConverter.xcodeproj/xcshareddata/xcschemes/MoltenVKShaderConverter-xrOS.xcscheme @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.cpp b/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.cpp index f1672e2ba..42c60e964 100644 --- a/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.cpp +++ b/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.cpp @@ -344,7 +344,7 @@ MVK_PUBLIC_SYMBOL bool SPIRVToMSLConverter::convert(SPIRVToMSLConversionConfigur #ifndef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS } catch (CompilerError& ex) { - string errMsg("MSL conversion error: "); + string errMsg("SPIR-V to MSL conversion error: "); errMsg += ex.what(); logError(conversionResult.resultLog, errMsg.data()); if (shouldLogMSL && pMSLCompiler) { @@ -366,6 +366,7 @@ MVK_PUBLIC_SYMBOL bool SPIRVToMSLConverter::convert(SPIRVToMSLConversionConfigur conversionResult.resultInfo.needsInputThreadgroupMem = pMSLCompiler && pMSLCompiler->needs_input_threadgroup_mem(); conversionResult.resultInfo.needsDispatchBaseBuffer = pMSLCompiler && pMSLCompiler->needs_dispatch_base_buffer(); conversionResult.resultInfo.needsViewRangeBuffer = pMSLCompiler && pMSLCompiler->needs_view_mask_buffer(); + conversionResult.resultInfo.usesPhysicalStorageBufferAddressesCapability = usesPhysicalStorageBufferAddressesCapability(pMSLCompiler); // When using Metal argument buffers, if the shader is provided with dynamic buffer offsets, // then it needs a buffer to hold these dynamic offsets. @@ -378,29 +379,31 @@ MVK_PUBLIC_SYMBOL bool SPIRVToMSLConverter::convert(SPIRVToMSLConversionConfigur } } - for (auto& ctxSI : shaderConfig.shaderInputs) { - if (ctxSI.shaderVar.builtin != spv::BuiltInMax) { - ctxSI.outIsUsedByShader = pMSLCompiler->has_active_builtin(ctxSI.shaderVar.builtin, spv::StorageClassInput); - } else { - ctxSI.outIsUsedByShader = pMSLCompiler->is_msl_shader_input_used(ctxSI.shaderVar.location); - } - } - for (auto& ctxSO : shaderConfig.shaderOutputs) { - if (ctxSO.shaderVar.builtin != spv::BuiltInMax) { - ctxSO.outIsUsedByShader = pMSLCompiler->has_active_builtin(ctxSO.shaderVar.builtin, spv::StorageClassOutput); - } else { - ctxSO.outIsUsedByShader = pMSLCompiler->is_msl_shader_output_used(ctxSO.shaderVar.location); - } - } - for (auto& ctxRB : shaderConfig.resourceBindings) { - if (ctxRB.resourceBinding.stage == shaderConfig.options.entryPointStage) { - ctxRB.outIsUsedByShader = pMSLCompiler->is_msl_resource_binding_used(ctxRB.resourceBinding.stage, - ctxRB.resourceBinding.desc_set, - ctxRB.resourceBinding.binding); - } - } - - delete pMSLCompiler; + if (pMSLCompiler) { + for (auto& ctxSI : shaderConfig.shaderInputs) { + if (ctxSI.shaderVar.builtin != spv::BuiltInMax) { + ctxSI.outIsUsedByShader = pMSLCompiler->has_active_builtin(ctxSI.shaderVar.builtin, spv::StorageClassInput); + } else { + ctxSI.outIsUsedByShader = pMSLCompiler->is_msl_shader_input_used(ctxSI.shaderVar.location); + } + } + for (auto& ctxSO : shaderConfig.shaderOutputs) { + if (ctxSO.shaderVar.builtin != spv::BuiltInMax) { + ctxSO.outIsUsedByShader = pMSLCompiler->has_active_builtin(ctxSO.shaderVar.builtin, spv::StorageClassOutput); + } else { + ctxSO.outIsUsedByShader = pMSLCompiler->is_msl_shader_output_used(ctxSO.shaderVar.location); + } + } + for (auto& ctxRB : shaderConfig.resourceBindings) { + if (ctxRB.resourceBinding.stage == shaderConfig.options.entryPointStage) { + ctxRB.outIsUsedByShader = pMSLCompiler->is_msl_resource_binding_used(ctxRB.resourceBinding.stage, + ctxRB.resourceBinding.desc_set, + ctxRB.resourceBinding.binding); + } + } + + delete pMSLCompiler; + } // To check GLSL conversion if (shouldLogGLSL) { @@ -445,6 +448,7 @@ void SPIRVToMSLConverter::logMsg(string& log, const char* logMsg) { // Appends the error text to the result log, and returns false to indicate an error. bool SPIRVToMSLConverter::logError(string& log, const char* errMsg) { logMsg(log, errMsg); + fprintf(stderr, "[mvk-error] %s\n", errMsg); return false; } @@ -533,3 +537,15 @@ void SPIRVToMSLConverter::populateEntryPoint(Compiler* pCompiler, populateWorkgroupDimension(wgSize.height, spvEP.workgroup_size.y, heightSC); populateWorkgroupDimension(wgSize.depth, spvEP.workgroup_size.z, depthSC); } + +bool SPIRVToMSLConverter::usesPhysicalStorageBufferAddressesCapability(Compiler* pCompiler) { + if (pCompiler) { + auto& declaredCapabilities = pCompiler->get_declared_capabilities(); + for(auto dc: declaredCapabilities) { + if (dc == CapabilityPhysicalStorageBufferAddresses) { + return true; + } + } + } + return false; +} diff --git a/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.h b/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.h index 765e110ff..1789ee93c 100644 --- a/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.h +++ b/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.h @@ -244,6 +244,7 @@ namespace mvk { bool needsInputThreadgroupMem = false; bool needsDispatchBaseBuffer = false; bool needsViewRangeBuffer = false; + bool usesPhysicalStorageBufferAddressesCapability = false; } SPIRVToMSLConversionResultInfo; @@ -300,6 +301,7 @@ namespace mvk { void writeSPIRVToFile(std::string spvFilepath, std::string& log); void populateWorkgroupDimension(SPIRVWorkgroupSizeDimension& wgDim, uint32_t size, SPIRV_CROSS_NAMESPACE::SpecializationConstant& spvSpecConst); void populateEntryPoint(SPIRV_CROSS_NAMESPACE::Compiler* pCompiler, SPIRVToMSLConversionOptions& options, SPIRVEntryPoint& entryPoint); + bool usesPhysicalStorageBufferAddressesCapability(SPIRV_CROSS_NAMESPACE::Compiler* pCompiler); std::vector _spirv; }; diff --git a/MoltenVKShaderConverter/MoltenVKShaderConverterTool/OSSupport.mm b/MoltenVKShaderConverter/MoltenVKShaderConverterTool/OSSupport.mm index 965d6cb03..fda97f5f5 100644 --- a/MoltenVKShaderConverter/MoltenVKShaderConverterTool/OSSupport.mm +++ b/MoltenVKShaderConverter/MoltenVKShaderConverterTool/OSSupport.mm @@ -71,6 +71,11 @@ #define mslVer(MJ, MN, PT) mslVersionMajor == MJ && mslVersionMinor == MN && mslVersionPoint == PT MTLLanguageVersion mslVerEnum = (MTLLanguageVersion)0; +#if MVK_XCODE_15 + if (mslVer(3, 1, 0)) { + mslVerEnum = MTLLanguageVersion3_1; + } else +#endif #if MVK_XCODE_14 if (mslVer(3, 0, 0)) { mslVerEnum = MTLLanguageVersion3_0; diff --git a/README.md b/README.md index 20249d647..e44e34a61 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,10 @@ Copyright (c) 2015-2023 [The Brenwill Workshop Ltd.](http://www.brenwill.com) Table of Contents ----------------- -- [Developing Vulkan Applications on *macOS, iOS, and tvOS*](#developing_vulkan) - [Introduction to **MoltenVK**](#intro) +- [Developing Vulkan Applications on *macOS, iOS, tvOS, and visionOS*](#developing_vulkan) + - [Using the *Vulkan SDK*](#sdk) + - [Using MoltenVK Directly](#download) - [Fetching **MoltenVK** Source Code](#install) - [Building **MoltenVK**](#building) - [Running **MoltenVK** Demo Applications](#demos) @@ -30,9 +32,47 @@ Table of Contents + +Introduction to MoltenVK +------------------------ + +**MoltenVK** is a layered implementation of [*Vulkan 1.2*](https://www.khronos.org/vulkan) +graphics and compute functionality, that is built on Apple's [*Metal*](https://developer.apple.com/metal) +graphics and compute framework on *macOS*, *iOS*, *tvOS*, and *visionOS*. **MoltenVK** allows +you to use *Vulkan* graphics and compute functionality to develop modern, cross-platform, +high-performance graphical games and applications, and to run them across many platforms, +including *macOS*, *iOS*, *tvOS*, *visionOS*, *Simulators*, and *Mac Catalyst* on *macOS 11.0+*, +and all *Apple* architectures, including *Apple Silicon*. + +*Metal* uses a different shading language, the *Metal Shading Language (MSL)*, than +*Vulkan*, which uses *SPIR-V*. **MoltenVK** automatically converts your *SPIR-V* shaders +to their *MSL* equivalents. + +To provide *Vulkan* capability to the *macOS*, *iOS*, *tvOS*, and *visionOS* platforms, +**MoltenVK** uses *Apple's* publicly available API's, including *Metal*. **MoltenVK** +does **_not_** use any private or undocumented API calls or features, so your app will +be compatible with all standard distribution channels, including *Apple's App Store*. + +The **MoltenVK** runtime package contains two products: + +- **MoltenVK** is a implementation of an almost-complete subset of the + [*Vulkan 1.2*](https://www.khronos.org/vulkan) graphics and compute API. + +- **MoltenVKShaderConverter** converts *SPIR-V* shader code to *Metal Shading Language (MSL)* + shader code, and converts *GLSL* shader source code to *SPIR-V* shader code and/or + *Metal Shading Language (MSL)* shader code. The converter is embedded in the **MoltenVK** + runtime to automatically convert *SPIR-V* shaders to their *MSL* equivalents. In addition, + both the *SPIR-V* and *GLSL* converters are packaged into a stand-alone command-line + `MoltenVKShaderConverter` *macOS* tool for converting shaders at development time from the command line. + + + -Developing Vulkan Applications for *macOS, iOS, and tvOS* ---------------------------------------------------------- +Developing *Vulkan* Applications for *macOS, iOS, tvOS, and visionOS* +--------------------------------------------------------------------- + + +### Using the *Vulkan SDK* The recommended method for developing a *Vulkan* application for *macOS* is to use the [*Vulkan SDK*](https://vulkan.lunarg.com/sdk/home). @@ -54,48 +94,22 @@ flag is enabled in `vkCreateInstance()`. See the description of the `VK_KHR_port extension in the *Vulkan* specification for more information about the use of the `VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR` flag. -If you are developing a *Vulkan* application for *iOS* or *tvOS*, or are developing a *Vulkan* -application for *macOS* and want to use a different version of the **MoltenVK** runtime library -provided in the *macOS Vulkan SDK*, you can use this document to learn how to build a **MoltenVK** -runtime library from source code. - -To learn how to integrate the **MoltenVK** runtime library into a game or application, -see the [`MoltenVK_Runtime_UserGuide.md `](Docs/MoltenVK_Runtime_UserGuide.md) -document in the `Docs` directory. - + +### Using MoltenVK Directly +If you are developing a *Vulkan* application for *iOS*, *tvOS*, or *visionOS*, or are +developing a *Vulkan* application for *macOS* and want to use a different version or +build of the **MoltenVK** runtime library than provided in the *macOS Vulkan SDK*, +you can access a pre-built MoltenVK binary library from the **MoltenVK** repository, by +[selecting a repository commit from the list](https://github.com/KhronosGroup/MoltenVK/actions), +and downloading the associated **MoltenVK** runtime library artifact. - -Introduction to MoltenVK ------------------------- - -**MoltenVK** is a layered implementation of [*Vulkan 1.2*](https://www.khronos.org/vulkan) -graphics and compute functionality, that is built on Apple's [*Metal*](https://developer.apple.com/metal) -graphics and compute framework on *macOS*, *iOS*, and *tvOS*. **MoltenVK** allows you to use *Vulkan* -graphics and compute functionality to develop modern, cross-platform, high-performance graphical -games and applications, and to run them across many platforms, including *macOS*, *iOS*, *tvOS*, -*Simulators*, and *Mac Catalyst* on *macOS 11.0+*, and all *Apple* architectures, including *Apple Silicon*. - -*Metal* uses a different shading language, the *Metal Shading Language (MSL)*, than -*Vulkan*, which uses *SPIR-V*. **MoltenVK** automatically converts your *SPIR-V* shaders -to their *MSL* equivalents. - -To provide *Vulkan* capability to the *macOS*, *iOS*, and *tvOS* platforms, **MoltenVK** uses *Apple's* -publicly available API's, including *Metal*. **MoltenVK** does **_not_** use any private or -undocumented API calls or features, so your app will be compatible with all standard distribution -channels, including *Apple's App Store*. - -The **MoltenVK** runtime package contains two products: +Finally, if you want a customized build of **MoltenVK**, you can follow the [instructions below](#install) +to create a **MoltenVK** runtime library by fetching and building the **MoltenVK** source code. -- **MoltenVK** is a implementation of an almost-complete subset of the - [*Vulkan 1.2*](https://www.khronos.org/vulkan) graphics and compute API. - -- **MoltenVKShaderConverter** converts *SPIR-V* shader code to *Metal Shading Language (MSL)* - shader code, and converts *GLSL* shader source code to *SPIR-V* shader code and/or - *Metal Shading Language (MSL)* shader code. The converter is embedded in the **MoltenVK** - runtime to automatically convert *SPIR-V* shaders to their *MSL* equivalents. In addition, - both the *SPIR-V* and *GLSL* converters are packaged into a stand-alone command-line - `MoltenVKShaderConverter` *macOS* tool for converting shaders at development time from the command line. +To learn how to integrate the **MoltenVK** runtime library into a game or application, +see the [`MoltenVK_Runtime_UserGuide.md `](Docs/MoltenVK_Runtime_UserGuide.md) +document in the `Docs` directory. @@ -135,14 +149,21 @@ for which to build the external libraries. The platform choices include: --maccat --tvos --tvossim + --visionos + --visionossim + +The `visionos` and `visionossim` selections require Xcode 15+. You can specify multiple of these selections. The result is a single `XCFramework` for each external dependency library, with each `XCFramework` containing binaries for each of the requested platforms. -The `--all` selection is the same as entering all of the other platform choices, -and will result in a single `XCFramework` for each external dependency library, -with each `XCFramework` containing binaries for all supported platforms and simulators. +The `--all` selection is the same as entering all of the other platform choices, except +`--visionos` and `--visionossim`, and will result in a single `XCFramework` for each +external dependency library, with each `XCFramework` containing binaries for all supported +platforms and simulators. The `--visionos` and `--visionossim` selections must be invoked +with a separate invocation of `fetchDependencies`, because those selections require +Xcode 15+, and will cause a multi-platform build on older versions of Xcode to abort. Running `fetchDependencies` repeatedly with different platforms will accumulate targets in the `XCFramework`. @@ -183,11 +204,11 @@ _Xcode_ version. If you require support for earlier OS versions, modify the `MAC build setting of `iOS 11.0` or greater, or a minimum **tvOS Deployment Target** (aka `TVOS_DEPLOYMENT_TARGET `) build setting of `tvOS 11.0` or greater. -Once built, the **MoltenVK** libraries can be run on *macOS*, *iOS* or *tvOS* devices that support *Metal*, -or on the *Xcode* *iOS Simulator* or *tvOS Simulator*. +Once built, the **MoltenVK** libraries can be run on *macOS*, *iOS*, *tvOS*, or *visionOS* devices +that support *Metal*,or on the *Xcode* *iOS Simulator*, *tvOS Simulator*, or *visionOS Simulator*. -- At runtime, **MoltenVK** requires at least *macOS 10.11*, *iOS 9*, or *tvOS 9* - (or *iOS 11* or *tvOS 11* if using `IOSurfaces`). +- At runtime, **MoltenVK** requires at least *macOS 10.11*, *iOS 9.0*, *tvOS 9.0*, + or *visionOS 1.0* (or *iOS 11* or *tvOS 11* if using `IOSurfaces`). - Information on *macOS* devices that are compatible with *Metal* can be found in [this article](http://www.idownloadblog.com/2015/06/22/how-to-find-mac-el-capitan-metal-compatible). - Information on *iOS* devices that are compatible with *Metal* can be found in @@ -207,6 +228,7 @@ platforms, or just one platform (in **_Release_** configuration): - **MoltenVK Package (macOS only)** - **MoltenVK Package (iOS only)** - **MoltenVK Package (tvOS only)** +- **MoltenVK Package (visionOS only)** _(requires Xcode 15+)_ Each of these`MoltenVKPackaging.xcodeproj` *Xcode* project *Schemes* puts the resulting packages in the `Package` directory, creating it if necessary. This directory contains separate `Release` and `Debug` @@ -241,6 +263,8 @@ from the command line. The following `make` targets are provided: make maccat make tvos make tvossim + make visionos + make visionossim make all-debug make macos-debug @@ -249,12 +273,15 @@ from the command line. The following `make` targets are provided: make maccat-debug make tvos-debug make tvossim-debug + make visionos-debug + make visionossim-debug make clean make install - Running `make` repeatedly with different targets will accumulate binaries for these different targets. -- The `all` target executes all platform targets. +- The `all` target executes all platform targets, except `visionos` and `visionossim`, as these require + Xcode 15+, and will abort a multi-platform build on older versions of Xcode. - The `all` target is the default target. Running `make` with no arguments is the same as running `make all`. - The `*-debug` targets build the binaries using the **_Debug_** configuration. - The `install` target will copy the most recently built `MoltenVK.xcframework` into the @@ -268,14 +295,14 @@ The `make` targets all require that *Xcode* is installed on your system. Building from the command line creates the same `Package` folder structure described above when building from within *Xcode*. -When building from the command line, you can set any of the build settings documented in -the `vk_mvk_moltenvk.h` file for `MVKConfiguration`, by passing them in the command line, +When building from the command line, you can set any of the build settings documented +in the `mvk_config.h` file for `MVKConfiguration`, by passing them in the command line, as in the following examples: make MVK_CONFIG_LOG_LEVEL=0 or - make macos MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS=1 + make macos MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=2 ...etc. @@ -293,7 +320,7 @@ or it can be included in any of the `make` build commands. For example: or make macos MVK_HIDE_VULKAN_SYMBOLS=1 - + ...etc. @@ -333,14 +360,14 @@ the contents of that directory out of this **MoltenVK** repository into your own ------------------------------------ **MoltenVK** is designed to be an implementation of a *Vulkan 1.2* subset that runs on *macOS*, *iOS*, -and *tvOS* platforms by mapping *Vulkan* capability to native *Metal* capability. +*tvOS*, and *visionOS* platforms by mapping *Vulkan* capability to native *Metal* capability. The fundamental design and development goal of **MoltenVK** is to provide this capability in a way that is both maximally compliant with the *Vulkan 1.2* specification, and maximally performant. -Such compliance and performance is inherently affected by the capability available through *Metal*, as the -native graphics driver on *macOS*, *iOS*, and *tvOS* platforms. *Vulkan* compliance may fall into one of -the following categories: +Such compliance and performance is inherently affected by the capability available through *Metal*, +as the native graphics driver on *macOS*, *iOS*, *tvOS*, and *visionOS* platforms. *Vulkan* +compliance may fall into one of the following categories: - Direct mapping between *Vulkan* capabilities and *Metal* capabilities. Within **MoltenVK**, the vast majority of *Vulkan* capability is the result of this type of direct mapping. @@ -363,7 +390,7 @@ be implemented or worked around. [*Khronos Vulkan Portability Initiative*](https://www.khronos.org/vulkan/portability-initiative), whose intention is to provide specifications, resources, and tools to allow developers to understand and design their *Vulkan* apps for maximum cross-platform compatibility and portability, including on platforms, such as -*macOS*, *iOS*, and *tvOS*, where a native *Vulkan* driver is not available. +*macOS*, *iOS*, *tvOS*, and *visionOS*, where a native *Vulkan* driver is not available. diff --git a/Scripts/create_dylib.sh b/Scripts/create_dylib.sh index 5ba75f67f..27acd1440 100755 --- a/Scripts/create_dylib.sh +++ b/Scripts/create_dylib.sh @@ -45,7 +45,7 @@ clang++ \ -stdlib=${CLANG_CXX_LIBRARY} \ -dynamiclib \ $(printf -- "-arch %s " ${ARCHS}) \ --m${MVK_OS_CLANG}-version-min=${MVK_MIN_OS_VERSION} \ +${MVK_CLANG_OS_MIN_VERSION} \ -compatibility_version 1.0.0 -current_version 1.0.0 \ -install_name "@rpath/${MVK_DYLIB_NAME}" \ -Wno-incompatible-sysroot \ diff --git a/Scripts/create_dylib_ios.sh b/Scripts/create_dylib_ios.sh index a3672f926..b3ae4b8d9 100755 --- a/Scripts/create_dylib_ios.sh +++ b/Scripts/create_dylib_ios.sh @@ -7,7 +7,6 @@ if [ "${IS_MACCATALYST}" == "YES" ]; then exit 0 fi -export MVK_OS_CLANG="ios" export MVK_UX_FWK="UIKit" export MVK_MIN_OS_VERSION=${IPHONEOS_DEPLOYMENT_TARGET} export MVK_IOSURFACE_FWK="-framework IOSurface" diff --git a/Scripts/create_dylib_macos.sh b/Scripts/create_dylib_macos.sh index 0f3447c52..0f72594ca 100755 --- a/Scripts/create_dylib_macos.sh +++ b/Scripts/create_dylib_macos.sh @@ -2,9 +2,9 @@ set -e -export MVK_OS_CLANG="macosx" export MVK_UX_FWK="AppKit" export MVK_MIN_OS_VERSION=${MACOSX_DEPLOYMENT_TARGET} +export MVK_CLANG_OS_MIN_VERSION="-mmacosx-version-min=${MVK_MIN_OS_VERSION}" export MVK_IOSURFACE_FWK="-framework IOSurface" export MVK_IOKIT_FWK="-framework IOKit" diff --git a/Scripts/create_dylib_tvos.sh b/Scripts/create_dylib_tvos.sh index 33cea2ec4..27c223529 100755 --- a/Scripts/create_dylib_tvos.sh +++ b/Scripts/create_dylib_tvos.sh @@ -2,9 +2,9 @@ set -e -export MVK_OS_CLANG="tvos" export MVK_UX_FWK="UIKit" export MVK_MIN_OS_VERSION=${TVOS_DEPLOYMENT_TARGET} +export MVK_CLANG_OS_MIN_VERSION="-mtvos-version-min=${MVK_MIN_OS_VERSION}" export MVK_IOSURFACE_FWK="-framework IOSurface" export MVK_IOKIT_FWK="" diff --git a/Scripts/create_dylib_xros.sh b/Scripts/create_dylib_xros.sh new file mode 100755 index 000000000..23cfacaef --- /dev/null +++ b/Scripts/create_dylib_xros.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -e + +export MVK_UX_FWK="UIKit" +export MVK_MIN_OS_VERSION=${XROS_DEPLOYMENT_TARGET} +export MVK_CLANG_OS_MIN_VERSION="" #"-mxros-version-min=${MVK_MIN_OS_VERSION}" +export MVK_IOSURFACE_FWK="-framework IOSurface" +export MVK_IOKIT_FWK="-framework IOKit" + +. "${SRCROOT}/../Scripts/create_dylib.sh" diff --git a/Scripts/package_moltenvk.sh b/Scripts/package_moltenvk.sh index 396dd129f..cce0dfaf0 100755 --- a/Scripts/package_moltenvk.sh +++ b/Scripts/package_moltenvk.sh @@ -38,6 +38,8 @@ copy_dylib "-iphoneos" "iOS" copy_dylib "-iphonesimulator" "iOS-simulator" copy_dylib "-appletvos" "tvOS" copy_dylib "-appletvsimulator" "tvOS-simulator" +copy_dylib "-xrvos" "xrOS" +copy_dylib "-xrsimulator" "xrOS-simulator" # Remove and replace header include folder rm -rf "${MVK_PKG_PROD_PATH}/include" diff --git a/Scripts/runcts b/Scripts/runcts index 2349e75d0..20ae1abe5 100755 --- a/Scripts/runcts +++ b/Scripts/runcts @@ -39,7 +39,6 @@ # only Vulkan 1.0, and only the following extensions: # VK_KHR_get_physical_device_properties2 # VK_KHR_portability_subset -# VK_MVK_moltenvk # cts_vk_dir="../../VK-GL-CTS/build/external/vulkancts/modules/vulkan/Debug" @@ -85,7 +84,7 @@ fi # -------------- MoltenVK configuration -------------------- # As documented above, the portability option restricts to Vulkan 1.0 and a very limited set of extensions. -# The values used here are documented in vk_mvk_moltenvk.h. +# The values used here are documented in mvk_config.h. # - MVK_CONFIG_API_VERSION_TO_ADVERTISE = VK_API_VERSION_1_0 (4194304) # - MVK_CONFIG_ADVERTISE_EXTENSIONS selects support for a very limited set of extensions, # using a bit-or of values in MVKConfigAdvertiseExtensions (extension list documented above). @@ -94,6 +93,9 @@ if [ "${is_portability}" != "" ]; then export MVK_CONFIG_ADVERTISE_EXTENSIONS=0xA fi +# ----- System settings ------ +export DYLD_LIBRARY_PATH="/usr/local/lib" + # ----- Metal validation settings ------ export METAL_DEVICE_WRAPPER_TYPE=1 export METAL_ERROR_MODE=3 diff --git a/Templates/spirv-tools/build.zip b/Templates/spirv-tools/build.zip index c78f151c3..3879c9b83 100644 Binary files a/Templates/spirv-tools/build.zip and b/Templates/spirv-tools/build.zip differ diff --git a/fetchDependencies b/fetchDependencies index 052cf6045..e4b233015 100755 --- a/fetchDependencies +++ b/fetchDependencies @@ -4,7 +4,8 @@ # # fetchDependencies - Retrieves the correct versions of all dependencies # -# macOS usage: ./fetchDependencies [--macos] [--ios] [--iossim] [--tvos] [--tvossim] [--all] [--none] +# macOS usage: ./fetchDependencies [--macos] [--ios] [--iossim] [--tvos] [--tvossim] +# [--visionos] [--visionossim] [--all] [--none] # [-v] [--debug] [--build-spirv-tools] # [--v-headers-root path] [--spirv-cross-root path] [--glslang-root path] # @@ -26,10 +27,18 @@ # --tvossim # Build the external libraries for the tvOS Simulator platform. # +# --visionos +# Build the external libraries for the visionOS platform. +# +# --visionossim +# Build the external libraries for the visionOS Simulator platform. +# # --all # Equivalent to specifying [--macos --ios --iossim --maccat --tvos --tvossim]. # Results in one XCFramework for each external library, each containing # binaries for all supported platforms. +# Currently excludes --visionos and --visionossim targets because those +# require Xcode 15+ and will abort a multi-platform build. # # --none # Don't build the external libraries for any platform (this is the default). @@ -94,6 +103,8 @@ BLD_IOS_SIM="" BLD_MAC_CAT="" BLD_TVOS="" BLD_TVOS_SIM="" +BLD_VISIONOS="" +BLD_VISIONOS_SIM="" BLD_MACOS="" BLD_SPECIFIED="" XC_CONFIG="Release" @@ -129,17 +140,27 @@ while (( "$#" )); do BLD_TVOS_SIM="Y" shift 1 ;; + --visionos) + BLD_VISIONOS="Y" + shift 1 + ;; + --visionossim) + BLD_VISIONOS_SIM="Y" + shift 1 + ;; --macos) BLD_MACOS="Y" shift 1 ;; --all) + BLD_MACOS="Y" BLD_IOS="Y" BLD_IOS_SIM="Y" BLD_MAC_CAT="Y" BLD_TVOS="Y" BLD_TVOS_SIM="Y" - BLD_MACOS="Y" +# BLD_VISIONOS="Y" # Requires Xcode 15+ +# BLD_VISIONOS_SIM="Y" # Requires Xcode 15+ shift 1 ;; --none) @@ -211,7 +232,7 @@ function update_repo() { if [ -d $1 -a -d $1/.git ]; then cd $1 - git fetch --all + git cat-file -e $3 || git fetch --all git checkout --force $3 cd - > /dev/null else @@ -304,7 +325,7 @@ if [ ! "$SPIRV_CROSS_ROOT" = "" ]; then rm -rf ${REPO_NAME} ln -sfn ${SPIRV_CROSS_ROOT} ${REPO_NAME} else - REPO_URL="https://github.com/KhronosGroup/${REPO_NAME}.git" + REPO_URL="https://github.com/js6i/${REPO_NAME}.git" REPO_REV=$(cat "${EXT_REV_DIR}/${REPO_NAME}_repo_revision") update_repo ${REPO_NAME} ${REPO_URL} ${REPO_REV} @@ -477,6 +498,14 @@ if [ "$BLD_TVOS_SIM" != "" ]; then build "tvOS" "tvOS Simulator" fi +if [ "$BLD_VISIONOS" != "" ]; then + build "xrOS" "xrOS" +fi + +if [ "$BLD_VISIONOS_SIM" != "" ]; then + build "xrOS" "xrOS Simulator" +fi + # Wait for any background process (if selected) to finish if [ "$XC_USE_BCKGND" != "" ]; then wait @@ -495,7 +524,7 @@ else echo "WARNING: You did not specify a platform to build." echo "To build the external libraries, include one or" echo "more of the following platform options:" - echo " --macos --ios --iossim --maccat --tvos --tvossim --all" + echo " --macos --ios --iossim --maccat --tvos --tvossim --visionos --visionossim --all" echo "See the instructions in the fetchDependencies script for more info." fi fi