diff --git a/Docs/MoltenVK_Runtime_UserGuide.md b/Docs/MoltenVK_Runtime_UserGuide.md index 080b4d0ce..c2f54985b 100644 --- a/Docs/MoltenVK_Runtime_UserGuide.md +++ b/Docs/MoltenVK_Runtime_UserGuide.md @@ -617,9 +617,9 @@ 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. +On non-Apple GPUs (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. diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index 6ab13f7ab..201d483c3 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -29,7 +29,9 @@ Released TBD - Fix MSL code used in `vkCmdBlitImage()` on depth-stencil formats. - Improve behavior of swapchain image presentation stalls caused by Metal regression. - Add several additional performance trackers, available via logging, or the `mvk_private_api.h` API. -- Add configurable lowpass filter for `VkPhysicalDeviceLimits::timestampPeriod`. +- Add `MVKConfiguration::timestampPeriodLowPassAlpha` and environment variable + `MVK_CONFIG_TIMESTAMP_PERIOD_LOWPASS_ALPHA`, to add a configurable lowpass filter + for varying `VkPhysicalDeviceLimits::timestampPeriod` on non-Apple GPUs. - Deprecate `MVK_DEBUG` env var, and add `MVK_CONFIG_DEBUG` env var to replace it. - Update `MVK_CONFIGURATION_API_VERSION` and `MVK_PRIVATE_API_VERSION` to `38`. diff --git a/MoltenVK/MoltenVK/API/mvk_config.h b/MoltenVK/MoltenVK/API/mvk_config.h index f72ef7770..21041efc1 100644 --- a/MoltenVK/MoltenVK/API/mvk_config.h +++ b/MoltenVK/MoltenVK/API/mvk_config.h @@ -955,7 +955,7 @@ typedef struct { * The initial value or this parameter is set by the * MVK_CONFIG_TIMESTAMP_PERIOD_LOWPASS_ALPHA * runtime environment variable or MoltenVK compile-time build setting. - * If neither is set, this parameter is set to 0.05 by default, + * If neither is set, this parameter is set to 1.0 by default, * indicating that the timestampPeriod will vary relatively slowly, * with the expectation that the app is querying this value infrequently. */ diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index 77b628ca5..7d342f689 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -1601,7 +1601,8 @@ // Basic lowpass filter TPout = (1 - A)TPout + (A * TPin). // The lower A is, the slower TPout will change over time. - float a = mvkConfig().timestampPeriodLowPassAlpha; + // First time through, just use the measured value directly. + float a = earlierCPUTs ? mvkConfig().timestampPeriodLowPassAlpha : 1.0; _properties.limits.timestampPeriod = ((1.0 - a) * _properties.limits.timestampPeriod) + (a * tsPeriod); } } @@ -2637,7 +2638,7 @@ _properties.limits.optimalBufferCopyRowPitchAlignment = 1; _properties.limits.timestampComputeAndGraphics = VK_TRUE; - _properties.limits.timestampPeriod = mvkGetTimestampPeriod(); // Will be 1.0 on Apple Silicon + _properties.limits.timestampPeriod = 1.0; // On non-Apple GPU's, this can vary over time, and is calculated based on actual GPU activity. _properties.limits.pointSizeRange[0] = 1; switch (_properties.vendorID) { diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.mm b/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.mm index 1bd0a6d01..7b16cb81b 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.mm @@ -381,7 +381,7 @@ // If not using MTLCounterSampleBuffer, update timestamp values, then mark queries as available void MVKTimestampQueryPool::finishQueries(MVKArrayRef queries) { if ( !_mtlCounterBuffer ) { - uint64_t ts = mvkGetTimestamp(); + uint64_t ts = mvkGetElapsedNanoseconds(); for (uint32_t qry : queries) { _timestamps[qry] = ts; } } MVKQueryPool::finishQueries(queries); diff --git a/MoltenVK/MoltenVK/Utility/MVKConfigMembers.def b/MoltenVK/MoltenVK/Utility/MVKConfigMembers.def index aff0cf33a..e148b1ac5 100644 --- a/MoltenVK/MoltenVK/Utility/MVKConfigMembers.def +++ b/MoltenVK/MoltenVK/Utility/MVKConfigMembers.def @@ -23,16 +23,13 @@ // To use this file, define the macros: // // MVK_CONFIG_MEMBER(member, mbrType, name) -// MVK_CONFIG_MEMBER_STRING(member, strObj, name) +// MVK_CONFIG_MEMBER_STRING(member, mbrType, name) // // then #include this file inline with your code. // // The name prameter is the name of the configuration parameter, which is used as the name // of the environment variable, and build setting, that sets the config value, and is entered // here without the "MVK_CONFIG_" prefix. -// -// Since string members are set from char pointers, the text must be copied to a std::string -// object, which is passed as a parameter to MVK_CONFIG_MEMBER_STRING. #ifndef MVK_CONFIG_MEMBER @@ -69,7 +66,7 @@ MVK_CONFIG_MEMBER(forceLowPowerGPU, VkBool32, MVK_CONFIG_MEMBER(semaphoreUseMTLFence, VkBool32, ALLOW_METAL_FENCES) // Deprecated legacy MVK_CONFIG_MEMBER(semaphoreSupportStyle, MVKVkSemaphoreSupportStyle, VK_SEMAPHORE_SUPPORT_STYLE) MVK_CONFIG_MEMBER(autoGPUCaptureScope, MVKConfigAutoGPUCaptureScope, AUTO_GPU_CAPTURE_SCOPE) -MVK_CONFIG_MEMBER_STRING(autoGPUCaptureOutputFilepath, evGPUCapFileStrObj, AUTO_GPU_CAPTURE_OUTPUT_FILE) +MVK_CONFIG_MEMBER_STRING(autoGPUCaptureOutputFilepath, char*, AUTO_GPU_CAPTURE_OUTPUT_FILE) MVK_CONFIG_MEMBER(texture1DAs2D, VkBool32, TEXTURE_1D_AS_2D) MVK_CONFIG_MEMBER(preallocateDescriptors, VkBool32, PREALLOCATE_DESCRIPTORS) MVK_CONFIG_MEMBER(useCommandPooling, VkBool32, USE_COMMAND_POOLING) diff --git a/MoltenVK/MoltenVK/Utility/MVKEnvironment.cpp b/MoltenVK/MoltenVK/Utility/MVKEnvironment.cpp index f2fa9e86e..fefceddd4 100644 --- a/MoltenVK/MoltenVK/Utility/MVKEnvironment.cpp +++ b/MoltenVK/MoltenVK/Utility/MVKEnvironment.cpp @@ -20,8 +20,19 @@ #include "MVKOSExtensions.h" #include "MVKFoundation.h" +// Return the expected size of MVKConfiguration, based on contents of MVKConfigMembers.def. +static constexpr uint32_t getExpectedMVKConfigurationSize() { +#define MVK_CONFIG_MEMBER_STRING(member, mbrType, name) MVK_CONFIG_MEMBER(member, mbrType, name) +#define MVK_CONFIG_MEMBER(member, mbrType, name) cfgSize += sizeof(mbrType); + uint32_t cfgSize = 0; +#include "MVKConfigMembers.def" + return cfgSize; +} + static bool _mvkConfigInitialized = false; static void mvkInitConfigFromEnvVars() { + static_assert(getExpectedMVKConfigurationSize() == sizeof(MVKConfiguration), "MVKConfigMembers.def does not match the members of MVKConfiguration."); + _mvkConfigInitialized = true; MVKConfiguration evCfg; @@ -32,8 +43,8 @@ static void mvkInitConfigFromEnvVars() { #define MVK_CONFIG_MEMBER(member, mbrType, name) \ evCfg.member = (mbrType)mvkGetEnvVarNumber(STR(MVK_CONFIG_##name), MVK_CONFIG_##name); -#define MVK_CONFIG_MEMBER_STRING(member, strObj, name) \ - evCfg.member = mvkGetEnvVarString(STR(MVK_CONFIG_##name), strObj, MVK_CONFIG_##name); +#define MVK_CONFIG_MEMBER_STRING(member, mbrType, name) \ + evCfg.member = mvkGetEnvVarString(STR(MVK_CONFIG_##name), evGPUCapFileStrObj, MVK_CONFIG_##name); #include "MVKConfigMembers.def" diff --git a/MoltenVK/MoltenVK/Utility/MVKEnvironment.h b/MoltenVK/MoltenVK/Utility/MVKEnvironment.h index f6f1ae9ed..6c50582a4 100644 --- a/MoltenVK/MoltenVK/Utility/MVKEnvironment.h +++ b/MoltenVK/MoltenVK/Utility/MVKEnvironment.h @@ -323,5 +323,5 @@ void mvkSetConfig(const MVKConfiguration& mvkConfig); * This can be set to a float between 0.0 and 1.0. */ #ifndef MVK_CONFIG_TIMESTAMP_PERIOD_LOWPASS_ALPHA -# define MVK_CONFIG_TIMESTAMP_PERIOD_LOWPASS_ALPHA 0.05 +# define MVK_CONFIG_TIMESTAMP_PERIOD_LOWPASS_ALPHA 1.0 #endif