Direct3D 11 отсутствует GetRasterStatus, как определить вертикальный пробел?

Я обновляю приложение, в котором измерение времени представления стимула на экране требует наибольшей точности. В настоящее время он написан с помощью DirectDraw, который давно вышел на пастбище, и там необходимо обновить нашу графическую библиотеку.

Способ измерения времени представления использует обнаружение конца периода вертикальной пустоты. В частности, мне нужно знать с максимально возможной точностью, когда все, что было перевернуто на первичную поверхность (или представлено в цепочке подкачки), на самом деле рисуется экраном. Обнаружение линии сканирования может повысить уверенность в этом измерении, но я мог бы работать только с обнаружением, когда период вертикальной пустой закончился сразу после вызова Flip или Present.

Direct 3D 9 имеет метод IDirect3DDevice9:: GetRasterStatus, который возвращает структуру D3DRASTER_STATUS, которая включает логическое значение InVBlank, которое описывает, находится ли устройство в вертикальную заготовку, а также текущую линию сканирования. DirectDraw имеет аналогичные функции (IDirectDraw:: GetVerticalBlankStatus, а также IDirectDraw:: GetScanLine, которая возвращает DDERR_VERTICALBLANKINPROGRESS во время вертикальной пустоты, может использоваться для обнаружения VB).

Однако я не смог найти подобную функцию в Direct3D11. Кто-нибудь знает, была ли эта функция перемещена или удалена между Direct3D9 и Direct3D11, а если последняя, ​​почему?

Ответ 1

Извините за поздний ответ, но я заметил, что до сих пор нет принятого ответа, поэтому, возможно, вы не нашли того, что сработало. В настоящее время в Windows служба DesktopWindowManager (dwm.exe) координирует все и не может быть обойдена. Начиная с Windows 8, эта служба не может быть отключена.

Итак, DWM всегда будет управлять частотой кадров, отображать управление очередью и окончательную композицию для всех различных IDXGISurface (n) объекты и IDXGIOutput (n) контролирует, и, если я не пропущу что-то, использование отслеживания VSync очень мало, если ваша цель рендеринга закадровый. Что касается вашего вопроса, я не был уверен, была ли ваша цель:

  • получить чрезвычайно точную информацию о времени, но только для диагностики, профилирования или использования информации или
  • было ли приложение затем (пытаться) использовать эти результаты для (планировать) расписание своих текущих циклов.

Если это последнее, я считаю, что вы можете эффективно это сделать только в том случае, если приложение D3D работает в режиме полноэкранного эксклюзивного. Единственный случай, когда DWM - под видом DXGI - по-настоящему доверяет клиенту обрабатывать свои собственные Present время.

Хорошая новость заключается в том, что вы можете получить все данные синхронизации, которые вы когда-либо хотели, и в разрешение QueryPerformanceFrequency, которое обычно вокруг 320 нс. Как вы, наверное, знаете, разрешение QPC является фактором в 20 000 000 (да, двадцать миллионов) улучшений по сравнению с тиком DateTime, несмотря на предположение о его 100 нс. span (DateTime.Now.Ticks имеет в основном идентичное разрешение для миллисекунды Environment.TickCount).

Здесь, как получить информацию о времени видео с высоким разрешением:

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 поддерживает множество преобразований, таких как 2D аффинные преобразования и 3D-перспективы, а также основные эффекты, такие как отсечение и непрозрачность.

В любом случае представляется менее вероятным, что подробная информация о сроках может с пользой информировать поведение среды выполнения приложения; может быть, это поможет вам предсказать ваш следующий VSync, но кто-то задается вопросом, какое значение имеет "повышенная осведомленность о периоде гашения", для какой-то определенной DWM-покоренной вне сети подкачки.

Поскольку ваша поверхность приложения является лишь одним из многих, которые DWM жонглирует, DWM будет делать все виды своей собственной динамической адаптации, при условии, что каждый клиент будет вести себя последовательно. Непредсказуемые адаптации несовместимы в таком режиме и, скорее всего, просто в конечном итоге нарушают обе стороны.

Ответ 2

Вопрос вот почему? Похоже, вы хотите решить симптом своей проблемы; возможно, это отвлечение от вашей реальной проблемы. Ожидание vsync было полезной техникой для Amiga или DOS. Это абсолютно неправильно в любой компоновке или многопотоковой ОС.

Во-первых, чего вы хотите достичь? Безрезультатный рендеринг выполняется путем установки интервала подкачки на D3D или OpenGL. Это вредно, чтобы попытаться сделать лучше, чем ОС там. Просто подумайте о случаях, таких как несколько мониторов, или о том, что произойдет, если более одного приложения попытаются синхронизировать.

Если вы являетесь клиентом какого-либо другого процесса и хотите запустить свое время на VSync, Windows, к сожалению, не предлагает объекта ждать, насколько я знаю. Лучше всего по-прежнему полагаться на настоящий вызов и оценить, что происходит.

Есть два случая: вы или рендеринг (представление) быстрее или медленнее, чем vsync. Если вы быстрее, Present должен блокировать вас уже. Если подарок никогда не ждет, и ваше время между вызовами составляет более 1/60 секунд, вы, вероятно, захотите сделать реже.

Наиболее распространенным случаем, почему люди заботятся о VSync, является видео. Вы можете выполнять намного быстрее, чем vsync, но хотите подождать только подходящее время для представления. Единственное, что нужно сделать, - запустить несколько кадров так быстро, как вы можете, и из этой оценки вы определяете временные рамки кадра. Используйте некоторый джиттер и обратную связь... или используйте встроенное аппаратное видео, которое достаточно радует, чтобы быть друзьями ядра с видеодрайвером.