Извините за поздний ответ, но я заметил, что до сих пор нет принятого ответа, так что, возможно, вы никогда не нашли тот, который работал. В настоящее время в Windows служба DesktopWindowManager (dwm.exe) координирует все и не может быть обойдена. Начиная с Windows 8, эта служба не может быть отключена.
Таким образом, DWM всегда будет контролировать частоту кадров, управление очередью рендеринга и окончательную композицию для всех различных IDXGISurface ( n ) объектов и IDXGIOutput ( n ) контролирует и не очень много пользуется для отслеживания VSync для цели закадрового рендера, если я что-то упустил (без сарказма). Что касается вашего вопроса, я не был уверен, что ваша цель:
- получить чрезвычайно точную информацию о времени, но только для диагностики, профилирования или информационного использования, или
- собиралось ли приложение затем (пытаться) использовать эти результаты для (попытки) планировать свои собственные текущие циклы.
Если это последнее, я считаю, что вы можете эффективно сделать это только в том случае, если приложение D3D работает в режиме в полноэкранном режиме . Это единственный случай, когда DWM - под видом DXGI - будет по-настоящему доверять клиенту обработку собственного Present
времени.
(едва) хорошая новость заключается в том, что если ваш интерес к VSync носит исключительно информационный характер, то есть вы попадаете в категорию пули (1.) сверху, то вы действительно можете получить все данные синхронизации, которые вам когда-либо понадобятся, и с разрешением QueryPerformanceFrequency , которое обычно составляет около 320 нс.
Вот как получить информацию о синхронизации видео в высоком разрешении. Но, опять же, просто для ясности, несмотря на очевидный успех (согласно обычному программному наблюдению), любая попытка обусловить детерминистический (и, следовательно, потенциально полезный) результат при чтениях, полученных следующим образом, в действительности будет сорвана посредничеством DWM:
DWM_TIMING_INFO
Указывает информацию о времени компоновки Desktop Window Manager (DWM). Используется функцией DwmGetCompositionTimingInfo .
typedef struct _DWM_TIMING_INFO
{
UINT32 cbSize; // size of this DWM_TIMING_INFO structure
URATIO rateRefresh; // monitor refresh rate
QPC_TIME qpcRefreshPeriod; // monitor refresh period
URATIO rateCompose; // composition rate
QPC_TIME qpcVBlank; // query performance counter value before the vertical blank
CFRAMES cRefresh; // DWM refresh counter
UINT cDXRefresh; // DirectX refresh counter
QPC_TIME qpcCompose; // query performance counter value for a frame composition
CFRAMES cFrame; // frame number that was composed at qpcCompose
UINT cDXPresent; // DirectX present number used to identify rendering frames
CFRAMES cRefreshFrame; // refresh count of the frame that was composed at qpcCompose
CFRAMES cFrameSubmitted; // DWM frame number that was last submitted
UINT cDXPresentSubmitted; // DirectX present number that was last submitted
CFRAMES cFrameConfirmed; // DWM frame number that was last confirmed as presented
UINT cDXPresentConfirmed; // DirectX present number that was last confirmed as presented
CFRAMES cRefreshConfirmed; // target refresh count of the last frame confirmed as completed by the GPU
UINT cDXRefreshConfirmed; // DirectX refresh count when the frame was confirmed as presented
CFRAMES cFramesLate; // number of frames the DWM presented late
UINT cFramesOutstanding; // number of composition frames that have been issued but have not been confirmed as completed
CFRAMES cFrameDisplayed; // last frame displayed
QPC_TIME qpcFrameDisplayed; // QPC time of the composition pass when the frame was displayed
CFRAMES cRefreshFrameDisplayed; // vertical refresh count when the frame should have become visible
CFRAMES cFrameComplete; // ID of the last frame marked as completed
QPC_TIME qpcFrameComplete; // QPC time when the last frame was marked as completed
CFRAMES cFramePending; // ID of the last frame marked as pending
QPC_TIME qpcFramePending; // QPC time when the last frame was marked as pending
CFRAMES cFramesDisplayed; // number of unique frames displayed
CFRAMES cFramesComplete; // number of new completed frames that have been received
CFRAMES cFramesPending; // number of new frames submitted to DirectX but not yet completed
CFRAMES cFramesAvailable; // number of frames available but not displayed, used, or dropped
CFRAMES cFramesDropped; // number of rendered frames that were never displayed because composition occurred too late
CFRAMES cFramesMissed; // number of times an old frame was composed when a new frame should have been used but was not available
CFRAMES cRefreshNextDisplayed; // frame count at which the next frame is scheduled to be displayed
CFRAMES cRefreshNextPresented; // frame count at which the next DirectX present is scheduled to be displayed
CFRAMES cRefreshesDisplayed; // total number of refreshes that have been displayed for the application since the DwmSetPresentParameters function was last called
CFRAMES cRefreshesPresented; // total number of refreshes that have been presented by the application since DwmSetPresentParameters was last called
CFRAMES cRefreshStarted; // refresh number when content for this window started to be displayed
ULONGLONG cPixelsReceived; // total number of pixels DirectX redirected to the DWM
ULONGLONG cPixelsDrawn; // number of pixels drawn
CFRAMES cBuffersEmpty; // number of empty buffers in the flip chain
}
DWM_TIMING_INFO;
(Примечание. Чтобы сжимать исходный код по горизонтали для отображения на этом веб-сайте по горизонтали, предположим, что добавлены следующие сокращения:)
typedef UNSIGNED_RATIO URATIO;
typedef DWM_FRAME_COUNT DWMFC;
typedef QPC_TIME QPCT;
Теперь для приложений, работающих в оконном режиме , вы, безусловно, можете получать эту подробную информацию так часто, как захотите. Если вам нужно только пассивное профилирование, то получение данных из DwmGetCompositionTimingInfo - это современный способ сделать это.
Если говорить о современном, так как вопрос намекает на модернизацию, вы можете рассмотреть возможность использования IDXGISwapChain1 , полученного из IDXGIFactory2 :: CreateSwapChainForComposition , чтобы включить использование нового DirectComposition компонент.
DirectComposition обеспечивает богатые и плавные переходы за счет достижения высокой частоты кадров, использования графического оборудования и работы независимо от потока пользовательского интерфейса. DirectComposition может принимать растровое содержимое, отображаемое различными библиотеками рендеринга, включая растровые изображения Microsoft DirectX и растровые изображения, отображаемые в окне (растровые изображения HWND). Кроме того, DirectComposition поддерживает различные преобразования, такие как двухмерные аффинные преобразования и трехмерные перспективные преобразования, а также основные эффекты, такие как отсечение и непрозрачность.
В любом случае, менее вероятно, что подробная информация о времени может с пользой сообщить поведение приложения во время выполнения; возможно это поможет вам предсказать ваш следующий VSync, но один не задается вопросом, какое значение может иметь «острое осознание периода гашения» для некоторого конкретного DWM-подчиненного закадровый обмен цепочки.
BecТак как поверхность вашего приложения - лишь одна из многих, с которыми DWM манипулирует, DWM будет выполнять все виды динамической адаптации самостоятельно, исходя из предположения, что каждый клиент ведет себя последовательно.Непредсказуемые адаптации не способствуют сотрудничеству в таком режиме и, скорее всего, просто приведут в замешательство обе стороны.
Примечания: 1.Разрешение QPC на много порядков выше разрешения тика
DateTime
, несмотря на предполагаемое использование последним 100 нс.единица наименования.Думайте о
DateTime.Now.Ticks
как о переупаковке (обозначенной в миллисекундах)
Environment.TickCount
, но преобразованной в единицы по 100 нс.Для максимально возможного разрешения используйте статический метод
Stopwatch.GetTimestamp()
вместо
DateTime.Now.Ticks
.