moltenvk/Common/MVKOSExtensions.mm

154 lines
4.6 KiB
Plaintext
Raw Normal View History

/*
* MVKOSExtensions.mm
*
2023-01-13 12:19:37 -05:00
* 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.
*/
#include "MVKOSExtensions.h"
#include "MVKCommonEnvironment.h"
#include <mach/mach_host.h>
#include <mach/mach_time.h>
#include <mach/task.h>
#include <os/proc.h>
#import <Foundation/Foundation.h>
using namespace std;
MVKOSVersion mvkOSVersion() {
static MVKOSVersion _mvkOSVersion = 0;
if ( !_mvkOSVersion ) {
NSOperatingSystemVersion osVer = [[NSProcessInfo processInfo] operatingSystemVersion];
_mvkOSVersion = mvkMakeOSVersion((uint32_t)osVer.majorVersion, (uint32_t)osVer.minorVersion, (uint32_t)osVer.patchVersion);
}
return _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; }
Support the `VK_EXT_pipeline_creation_feedback` extension. This provides feedback that indicates: * how long it took to compile each shader stage and the pipeline as a whole; * whether or not the pipeline or any shader stage were found in any supplied pipeline cache; and * whether or not any supplied base pipeline were used to accelerate pipeline creation. This is similar to the performance statistics that MoltenVK already collects. Since we don't use any supplied base pipeline at all, this implementation never sets `VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT`. However, I've identified several places where we could probably use the base pipeline to accelerate pipeline creation. One day, I should probably implement that. Likewise, because we don't yet support using `MTLBinaryArchive`s, `VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT` is never set on the whole pipeline, though it *is* set for individual stages, on the assumption that any shader found in a cache is likely to be found in Metal's own implicit cache. In this implementation, shader stage compilation time includes any time needed to build the `MTLComputePipelineState`s needed for vertex and tessellation control shaders in tessellated pipelines. This patch also changes compilation of the vertex stage `MTLComputePipelineState`s in tessellated pipelines to be eager instead of lazy. We really ought to have been doing this anyway, in order to report pipeline failures at creation time instead of draw time. I'm not happy, though, that we now pay the cost of all three pipeline states all the time, instead of just the ones that are used. This also gets rid of some fields of `MVKGraphicsPipeline` that were only used during pipeline construction, which should save some memory, particularly for apps that create lots of pipelines.
2023-07-07 00:25:37 -07:00
uint64_t mvkGetElapsedNanoseconds(uint64_t startTimestamp, uint64_t endTimestamp) {
if (endTimestamp == 0) { endTimestamp = mvkGetTimestamp(); }
Support the `VK_EXT_pipeline_creation_feedback` extension. This provides feedback that indicates: * how long it took to compile each shader stage and the pipeline as a whole; * whether or not the pipeline or any shader stage were found in any supplied pipeline cache; and * whether or not any supplied base pipeline were used to accelerate pipeline creation. This is similar to the performance statistics that MoltenVK already collects. Since we don't use any supplied base pipeline at all, this implementation never sets `VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT`. However, I've identified several places where we could probably use the base pipeline to accelerate pipeline creation. One day, I should probably implement that. Likewise, because we don't yet support using `MTLBinaryArchive`s, `VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT` is never set on the whole pipeline, though it *is* set for individual stages, on the assumption that any shader found in a cache is likely to be found in Metal's own implicit cache. In this implementation, shader stage compilation time includes any time needed to build the `MTLComputePipelineState`s needed for vertex and tessellation control shaders in tessellated pipelines. This patch also changes compilation of the vertex stage `MTLComputePipelineState`s in tessellated pipelines to be eager instead of lazy. We really ought to have been doing this anyway, in order to report pipeline failures at creation time instead of draw time. I'm not happy, though, that we now pay the cost of all three pipeline states all the time, instead of just the ones that are used. This also gets rid of some fields of `MVKGraphicsPipeline` that were only used during pipeline construction, which should save some memory, particularly for apps that create lots of pipelines.
2023-07-07 00:25:37 -07:00
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; }
Add support for the VK_EXT_debug_report extension. Add MVKDebugReportCallback class. Add MVKVulkanAPIObject class as base class of classes exposed in Vulkan API. Remove MVKRefCountedDeviceObject class and move ref-counting to MVKVulkanAPIObject. Rename MVKDispatchableObject class to MVKDispatchableVulkanAPIObject. Introduce multiple inheritance mixin classes into class hierarchy. Add MVKBaseObject::getVulkanAPIObject() function to find Vulkan API object controlling any subobject that needs to report something. MVKCommandResourceFactory functions pass in calling object for reporting. Add MVKBaseObject::reportMessage() & reportError() functions. Replace mvkNotifyErrorWithText() static function with reportError() instance function to allow access to debug reporting. Redefine MVKLog*() functions to call reportError() instance method. Delete MVKLogging.cpp. Remove MVKLogging.h from MoltenVKShaderConverter project. Add mvk_datatypes.hpp to redirect errors in mvk_datatypes.h functions to debug reporting. Use mvk_datatypes.hpp internally for all references to these functions. Convert several static methods to instance methods. Refactor platform defines in MVKSurface.h. Explicitly count MVKExtensionList extension count to avoid relying on struct size. Remove MVKCommandBuffer::recordResult() and use setConfigurationResult(). Change log indication of error in logs from [***MoltenVK ERROR***] to [mvk-error], for consistency with other log level indications. Update MoltenVK version to 1.0.35.
2019-05-01 22:27:03 -04:00
// Initialize timestamping capabilities on app startup.
//Called automatically when the framework is loaded and initialized.
static bool _mvkTimestampsInitialized = false;
__attribute__((constructor)) static void MVKInitTimestamps() {
if (_mvkTimestampsInitialized ) { return; }
_mvkTimestampsInitialized = true;
_mvkTimestampBase = mach_absolute_time();
mach_timebase_info(&_mvkMachTimebase);
_mvkTimestampPeriod = (double)_mvkMachTimebase.numer / (double)_mvkMachTimebase.denom;
}
void mvkDispatchToMainAndWait(dispatch_block_t block) {
if (NSThread.isMainThread) {
block();
} else {
dispatch_sync(dispatch_get_main_queue(), block);
}
}
#pragma mark -
#pragma mark Process environment
string mvkGetEnvVar(string varName, bool* pWasFound) {
@autoreleasepool {
NSDictionary* nsEnv = [[NSProcessInfo processInfo] environment];
NSString* envStr = nsEnv[@(varName.c_str())];
if (pWasFound) { *pWasFound = envStr != nil; }
return envStr ? envStr.UTF8String : "";
}
}
int64_t mvkGetEnvVarInt64(string varName, bool* pWasFound) {
return strtoll(mvkGetEnvVar(varName, pWasFound).c_str(), NULL, 0);
}
bool mvkGetEnvVarBool(std::string varName, bool* pWasFound) {
return mvkGetEnvVarInt64(varName, pWasFound) != 0;
}
#pragma mark -
#pragma mark System memory
uint64_t mvkGetSystemMemorySize() {
#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) {
return info.max_mem;
}
2020-06-18 16:36:45 -07:00
return 0;
#endif
2020-06-17 17:14:31 -07:00
#if MVK_TVOS
return 0;
2020-06-17 17:14:31 -07:00
#endif
}
uint64_t mvkGetAvailableMemorySize() {
2020-06-15 16:33:51 -07:00
#if MVK_IOS_OR_TVOS
if (mvkOSVersionIsAtLeast(13.0)) { return os_proc_available_memory(); }
#endif
mach_port_t host_port;
mach_msg_type_number_t host_size;
vm_size_t pagesize;
host_port = mach_host_self();
host_size = HOST_VM_INFO_COUNT;
host_page_size(host_port, &pagesize);
vm_statistics_data_t vm_stat;
if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) == KERN_SUCCESS ) {
return vm_stat.free_count * pagesize;
}
return 0;
}
uint64_t mvkGetUsedMemorySize() {
task_vm_info_data_t task_vm_info;
mach_msg_type_number_t task_size = TASK_VM_INFO_COUNT;
if (task_info(mach_task_self(), TASK_VM_INFO, (task_info_t)&task_vm_info, &task_size) == KERN_SUCCESS) {
return task_vm_info.phys_footprint;
}
return 0;
}
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];
}