Fixes to determination of VkPhysicalDeviceLimits::timestampPeriod.

- On Apple GPUs, set timestampPeriod to 1.0.
- On non-Apple GPUs, calculate timestampPeriod each time it is retrieved.
- On older devices that do not support GPU timestamps, use nanosecond
  CPU timestamps to be consistent with timestampPeriod of 1.0.
- Change MVKConfiguration::timestampPeriodLowPassAlpha and environment
  variable MVK_CONFIG_TIMESTAMP_PERIOD_LOWPASS_ALPHA to 1.0, to use
  only latest value by default.
- Add build-time verification that MVKConfigMembers.def
  includes all members of MVKConfiguration (unrelated).
This commit is contained in:
Bill Hollings 2023-10-16 22:59:21 -04:00
parent 107cf2c34e
commit 3a77f4ea97
8 changed files with 27 additions and 16 deletions

View File

@ -617,9 +617,9 @@ vailable when you request it, resulting in frame delays and visual stuttering.
<a name="timestamping"></a>
### 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.

View File

@ -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`.

View File

@ -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.
*/

View File

@ -1601,7 +1601,8 @@ void MVKPhysicalDevice::updateTimestampPeriod() {
// 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 @@ void MVKPhysicalDevice::initLimits() {
_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) {

View File

@ -381,7 +381,7 @@ void MVKTimestampQueryPool::endQuery(uint32_t query, MVKCommandEncoder* cmdEncod
// If not using MTLCounterSampleBuffer, update timestamp values, then mark queries as available
void MVKTimestampQueryPool::finishQueries(MVKArrayRef<const uint32_t> queries) {
if ( !_mtlCounterBuffer ) {
uint64_t ts = mvkGetTimestamp();
uint64_t ts = mvkGetElapsedNanoseconds();
for (uint32_t qry : queries) { _timestamps[qry] = ts; }
}
MVKQueryPool::finishQueries(queries);

View File

@ -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)

View File

@ -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"

View File

@ -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