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