> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Agendamento e apresentação de quadros no XBOX One

> Agendamento e apresentação de quadros no XBOX One

* [Substituição das cadeias de troca pela apresentação direta e pelo agendamento de quadros](#ID4SwapChainsRIP)
  * [Migração do Windows e da ERA ](#ID4Migration)
  * [Fluxo de trabalho de alto nível](#ID4WorkflowPrimer)
  * [Código de exemplo](#ID4ExampleCode)

<a id="ID4SwapChainsRIP" />

## Substituição das cadeias de troca pela apresentação direta e pelo agendamento de quadros

O Game OS reformulou o processo de apresentação gráfica. O objetivo é fazer o seguinte.

* Fornecer um controle mais direto sobre a criação e o gerenciamento de recursos exibíveis
* Reduzir a latência de ponta a ponta, desde a amostragem do dispositivo de entrada até a varredura do recurso de quadro apresentado
* Ampliar a flexibilidade na configuração dinâmica de planos e parâmetros de exibição
* Aumentar a liberdade na seleção da fila de comandos para o envio da apresentação
* Estabelecer um mecanismo explícito de limitação da CPU para um controle refinado da execução do pipeline de simulação e renderização
* Aprimorar a manutenção e o relatório de estatísticas do pipeline de quadros

Alguns dos recursos mais notáveis oferecidos pela nova abordagem são os seguintes.

* A apresentação direta de objetos ID3D12Resource exibíveis permite versatilidade na organização e na seleção de recursos de troca, à medida que a cadeia evolui para um pool gerenciado pelo usuário.
* A capacidade de apresentar em qualquer fila de comandos gráficos ou de computação pode eliminar uma paralisação da fila gráfica aguardando um fence de apresentação sinalizado por uma fila de computação após o processamento de um recurso de troca (suporte em breve).
* Introdução de um método de identificação formal de quadros na forma de um token de pipeline. O token de pipeline de quadros fornece um meio de correlacionar a limitação de quadros, a amostragem de entrada, os eventos de gravação de listas de comandos da CPU, os eventos de renderização da GPU e os eventos do pipeline de exibição para quadros cujas durações de pipeline abrangem vários intervalos de v-sync. Estatísticas coerentes para quadros individuais podem então ser consultadas por token e exibidas por meio do PIX. O conhecimento do sistema sobre o tempo de vida de um quadro, incluindo todos os eventos notáveis que ocorrem nele, também beneficia o monitoramento e o ajuste do serviço XBOX Game Streaming.
* Agendamento baseado em eventos e controlado por interrupções da produção de novos quadros para exibição, permitindo a especificação de tempos de origem no pipeline de quadros na cadência do intervalo de apresentação, com deslocamento automático de fase em resposta a quadros perdidos. O agendamento permite a especificação opcional de eventos criados pelo usuário para uma sinalização ampliada.
* Sistema para sondar ou bloquear eventos de origem do pipeline de quadros como um mecanismo formal de limitação. O sistema permite a especificação opcional de eventos criados pelo usuário como condições adicionais para uma espera.
* Expressão mais abstrata da frequência de renderização e apresentação, com o intervalo de apresentação especificado como uma duração de tempo em vez de um intervalo em v-blanks inteiros. A alteração permite preservar uma renderização de quadros consistente em hardware de console fixo diante de taxas de saída de tela variáveis (por exemplo, renderização a 60 Hertz em uma tela de 60 Hz ou de 120 Hz) e permite o suporte futuro simples à renderização nativa em frequências superiores a 60 Hz (por exemplo, 120 Hz nativos).
* Ampliação das estatísticas de quadros rastreadas, com um mecanismo de relatório filtrável e extensível para adições futuras.
* A identificação dos tempos de origem dos quadros, em conjunto com a futura adição de relógios sincronizados da tela e dos dispositivos de entrada (para evitar desvios contínuos), permite que a plataforma oriente a coleta de amostras de entrada pelo firmware do gamepad (ou de outro dispositivo) e a disponibilidade just-in-time para consultas do jogo, ajudando a minimizar a latência geral.

<a id="ID4Migration" />

## Migração do Windows e da ERA

As APIs relacionadas a cadeias de troca, apresentação e agendamento sem suporte no Game OS têm equivalentes comparáveis. Como auxílio de orientação, um conjunto de APIs e parâmetros herdados comumente usados é fornecido na tabela a seguir, com suas substituições correspondentes na coluna adjacente.

| Herdado | Game OS |
| - | - |
| IDXGIFactory::CreateSwapChain, <br />IDXGIFactory2::CreateSwapChainForCoreWindow e <br />IDXGIFactory2::CreateSwapChainForComposition<br /><br />    - *DXGIX\_SWAP\_CHAIN\_FLAG\_QUANTIZATION\_RGB\_FULL*<br />    - *DXGIX\_SWAP\_CHAIN\_FLAG\_COLORIMETRY\_*<br />*RGB\_BT2020\_ST2084*<br />    - *DXGIX\_SWAP\_CHAIN\_MATCH\_XBOX360\_AND\_PC*<br /><br />     - *DXGIX\_SWAP\_CHAIN\_MATCH\_OTHER\_CONSOLES*<br />    - *DXGIX\_SWAP\_CHAIN\_FLAG\_*<br />*QUANTIZATION\_RGB\_LIMITED*<br />    - *DXGIX\_SWAP\_CHAIN\_FLAG\_*<br />*COLORIMETRY\_sRGB\_TO\_REC709*<br /><br />    - *DXGIX\_SWAP\_CHAIN\_FLAG\_*<br />*AUTOMATIC\_GAMEDVR\_TONEMAP* | [ID3D12Device::CreateCommittedResource](https://learn.microsoft.com/windows/desktop/api/d3d12/nf-d3d12-id3d12device-createcommittedresource) com <br />*HeapFlags* incluindo [D3D12\_HEAP\_FLAG\_ALLOW\_DISPLAY](https://learn.microsoft.com/windows/desktop/api/d3d12/ne-d3d12-d3d12_heap_flags)<br /><br /> <br />    - [ColorSpace](/pt-BR/reference/graphics/d3d12_x/structs/d3d12xbox_present_plane_parameters) [DXGI\_COLOR\_SPACE\_RGB\_FULL\_G22\_NONE\_P709](https://learn.microsoft.com/windows/desktop/api/dxgicommon/ne-dxgicommon-dxgi_color_space_type)<br />   - [ColorSpace](/pt-BR/reference/graphics/d3d12_x/structs/d3d12xbox_present_plane_parameters) [DXGI\_COLOR\_SPACE\_RGB\_STUDIO\_G22\_NONE\_P2020](https://learn.microsoft.com/windows/desktop/api/dxgicommon/ne-dxgicommon-dxgi_color_space_type)<br /> <br />    - Sem suporte ([DXGI\_COLOR\_SPACE\_RGB\_FULL\_G22\_NONE\_P709](https://learn.microsoft.com/windows/desktop/api/dxgicommon/ne-dxgicommon-dxgi_color_space_type)<br />  sem *sRGB\_TO\_REC709*)<br />    - [ColorSpace](/pt-BR/reference/graphics/d3d12_x/structs/d3d12xbox_present_plane_parameters) [DXGI\_COLOR\_SPACE\_RGB\_FULL\_G22\_NONE\_P709](https://learn.microsoft.com/windows/desktop/api/dxgicommon/ne-dxgicommon-dxgi_color_space_type)<br />    - Sem suporte<br /><br />    - Sem suporte<br /><br /> <br />   - [D3D12XBOX\_RESOURCE\_FLAG\_ALLOW\_](/pt-BR/reference/graphics/d3d12_x/enums/d3d12_resource_flags)<br />[AUTOMATIC\_GAMEDVR\_TONE\_MAP](/pt-BR/reference/graphics/d3d12_x/enums/d3d12_resource_flags) |
| IDXGISwapChain1::SetHDRToneMapper | [ID3D12CommandQueue::SetHDRToneMapperX](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12commandqueue/methods/id3d12commandqueue_sethdrtonemapperx) |
| IDXGISwapChain::Present e DXGIXPresentArray<br /><br />   - *SyncInterval* 1 - 4<br />    - *SyncInterval* 0<br />    - *PresentImmediateThreshold*<br /><br />    - *DXGI\_PRESENT\_DO\_NOT\_WAIT*<br />    - *DXGIX\_PRESENT\_DISABLE\_VARIABLE\_REFRESH\_RATE*<br />    - *DXGIX\_PRESENT\_PRESERVE\_FRAMEBUFFER*<br />    - *DXGIX\_PRESENT\_UPSCALE\_FILTER\_* \* | [ID3D12CommandQueue::PresentX](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12commandqueue/methods/id3d12commandqueue_presentx)<br /><br />   - [ID3D12Device::SetFrameIntervalX](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_setframeintervalx)(..., *LengthInMicroseconds*, ...);<br />   - [D3D12XBOX\_PRESENT\_FLAG\_IMMEDIATE](/pt-BR/reference/graphics/d3d12_x/enums/d3d12xbox_present_flags) (substituição de PresentX)<br />    - [ImmediateThresholdPercent](/pt-BR/reference/graphics/d3d12_x/structs/d3d12xbox_present_parameters)<br /><br />    - [D3D12XBOX\_PRESENT\_FLAG\_DO\_NOT\_WAIT](/pt-BR/reference/graphics/d3d12_x/enums/d3d12xbox_present_flags)<br />    - [D3D12XBOX\_PRESENT\_FLAG\_DISABLE\_VARIABLE\_REFRESH\_RATE](/pt-BR/reference/graphics/d3d12_x/enums/d3d12xbox_present_flags)<br />    - [D3D12XBOX\_PRESENT\_FLAG\_PERSIST](/pt-BR/reference/graphics/d3d12_x/enums/d3d12xbox_present_flags)<br />    - [D3D12XBOX\_PRESENT\_PLANE\_SCALE\_FILTER](/pt-BR/reference/graphics/d3d12_x/enums/d3d12xbox_present_plane_scale_filter) |
| IDXGISwapChain::GetFrameStatistics e DXGIXGetFrameStatistics | [ID3D12Device::GetFrameStatisticsX](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_getframestatisticsx) |
| DXGIX\_FRAME\_STATISTICS<br /><br />    - *GPUCountTitleUsed*<br /><br /><br /> | [D3D12XBOX\_RENDER\_STATISTICS](/pt-BR/reference/graphics/d3d12_x/structs/d3d12xbox_render_statistics)<br /><br />    - *GPUBusyDuration* x [GetTimeStampFrequency](https://learn.microsoft.com/windows/desktop/api/d3d12/nf-d3d12-id3d12commandqueue-gettimestampfrequency)() / <br />QueryPerformanceFrequency().QuadPart <br />(abrangendo o intervalo de quadros) |
| DXGIX\_FRAME\_STATISTICS<br /><br />    - *CPUTimePresentCalled*<br />    - *CPUTimeAddedToQueue*<br />    - *CPUTimeFrameComplete*<br />    - *QueueLengthAddedToQueue*<br /> | [D3D12XBOX\_PRESENT\_STATISTICS](/pt-BR/reference/graphics/d3d12_x/structs/d3d12xbox_present_statistics)<br /><br />    - *PresentCallTime*<br />    - *PresentQueueTime*<br />    - *GPUProcessTime*<br />    - *QueuedFrameCount* |
| DXGIX\_FRAME\_STATISTICS<br /><br />    - *CPUTimeVSync*<br />    - *CPUTimeFlip*<br />    - *PercentScanned*<br />    - *VSyncCount* | [D3D12XBOX\_DISPLAY\_STATISTICS](/pt-BR/reference/graphics/d3d12_x/structs/d3d12xbox_display_statistics)<br /><br />    - *VSyncTime*<br />    - *FlipTime*<br />    - *PercentScanned*<br />    - Sem suporte |
| DXGIX\_FRAME\_STATISTICS<br /><br />    - *Cookie*<br /><br /><br /><br />    - *VSyncCount* | <br /><br />    - [D3D12XBOX\_FRAME\_PIPELINE\_TOKEN](/pt-BR/reference/graphics/d3d12_x/enums/d3d12xbox_frame_pipeline_token) atua como <br />identificador de quadro (a associação com o <br />Cookie personalizado deve ser feita manualmente)<br /><br />    - Sem suporte |
| DXGIXSetVLineNotification<br /><br />   - VLINECOUNTER0<br />   - VLINECOUNTER1 | [ID3D12Device::ScheduleFrameEventX](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_scheduleframeeventx)<br /><br />   - [D3D12XBOX\_FRAME\_EVENT\_DISPLAY\_VBLANK](/pt-BR/reference/graphics/d3d12_x/enums/d3d12xbox_frame_event_type)<br />   - [D3D12XBOX\_FRAME\_EVENT\_ORIGIN](/pt-BR/reference/graphics/d3d12_x/enums/d3d12xbox_frame_event_type) |
| DXGIXSetFrameNotification<br /><br />   - FRAME\_NOTIFICATION\_FLIPPED | ID3D12Device::ScheduleFrameEventX<br /><br />   - [D3D12XBOX\_FRAME\_EVENT\_DISPLAY\_FLIP](/pt-BR/reference/graphics/d3d12_x/enums/d3d12xbox_frame_event_type) |
| DXGIXSetVLineNotification (ou Present) como mecanismo de limitação | [ID3D12Device::ScheduleFrameEventX](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_scheduleframeeventx) e [ID3D12Device::WaitFrameEventX](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_waitframeeventx) com [D3D12XBOX\_FRAME\_EVENT\_ORIGIN](/pt-BR/reference/graphics/d3d12_x/enums/d3d12xbox_frame_event_type) |

<a id="ID4WorkflowPrimer" />

## Fluxo de trabalho de alto nível

A abordagem geral para criar um pool de recursos exibíveis, agendar quadros como um mecanismo explícito de limitação e apresentar recursos de quadro na tela consiste em algumas etapas de inicialização, seguidas por uma sequência de operações no loop do jogo. Para obter mais informações sobre cada etapa (descrições detalhadas, implicações e uso sugerido), consulte as páginas de referência.

**Inicialização**

* Chame [ID3D12Device::CreateCommittedResource](https://learn.microsoft.com/windows/desktop/api/d3d12/nf-d3d12-id3d12device-createcommittedresource) com *HeapFlags* que incluam [D3D12\_HEAP\_FLAG\_ALLOW\_DISPLAY](https://learn.microsoft.com/windows/desktop/api/d3d12/ne-d3d12-d3d12_heap_flags) para criar uma coleção de objetos [ID3D12Resource](https://learn.microsoft.com/windows/desktop/api/d3d12/nn-d3d12-id3d12resource) que servirão como um pool de recursos trocáveis com suporte à apresentação na tela (ou seja, uma "cadeia de troca").
* Chame [ID3D12Device::SetFrameIntervalX](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_setframeintervalx) para estabelecer uma taxa de atualização e um período de quadros. *LengthInMicroseconds* define o intervalo de tempo entre as apresentações de quadros na tela (flips). *PeriodInIntervals* define o quanto a CPU pode se adiantar em relação à GPU, em intervalos de quadros inteiros. A CPU pode se adiantar *PeriodInIntervals* - 1 quadros em relação à GPU antes de ser limitada (por exemplo, um *PeriodInIntervals* de 2 permite que a CPU grave e envie comandos de renderização para o quadro *n* + 1 enquanto a GPU processa os comandos enviados para o quadro *n*).
* Chame [ID3D12Device::ScheduleFrameEventX](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_scheduleframeeventx) para estabelecer o momento, dentro de um intervalo de quadros, em que a CPU será limitada. Especifique um Type [D3D12XBOX\_FRAME\_EVENT\_ORIGIN](/pt-BR/reference/graphics/d3d12_x/enums/d3d12xbox_frame_event_type) e um deslocamento de tempo *IntervalOffsetInMicroseconds* para agendar o evento de origem dos quadros. A CPU é limitada até que a quantidade de tempo *IntervalOffsetInMicroseconds* especificada dentro do intervalo tenha decorrido.

**Loop do jogo**

* Chame [ID3D12Device::WaitFrameEventX](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_waitframeeventx) com um Type [D3D12XBOX\_FRAME\_EVENT\_ORIGIN](/pt-BR/reference/graphics/d3d12_x/enums/d3d12xbox_frame_event_type) para executar a limitação da CPU. Especifique um *TimeOutInMs* de **D3D12XBOX\_WAIT\_FRAME\_EVENT\_INFINITE** para bloquear até que a origem chegue, ou um tempo limite fixo em milissegundos para sondar o evento de origem (**S\_FALSE** será retornado se a origem ainda não tiver chegado). Especifique um ponteiro para um [D3D12XBOX\_FRAME\_PIPELINE\_TOKEN](/pt-BR/reference/graphics/d3d12_x/enums/d3d12xbox_frame_pipeline_token) em *pToken* que, ao retornar com a chegada da origem, é definido como um valor de token que identifica exclusivamente o quadro. Esse token deve ser rastreado para o quadro e fornecido no momento de sua apresentação na tela.
* Consulte a entrada do controle e renderize o quadro nos objetos [ID3D12Resource](https://learn.microsoft.com/windows/desktop/api/d3d12/nn-d3d12-id3d12resource) criados com suporte à exibição.
* Chame [ID3D12CommandQueue::PresentX](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12commandqueue/methods/id3d12commandqueue_presentx) para enfileirar os recursos do quadro renderizado para apresentação na tela. Os recursos e os tokens de quadro são fornecidos na matriz *pPlaneParameters*.
* Chame [ID3D12Device::GetFrameStatisticsX](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_getframestatisticsx) usando o token do último quadro que deveria ter chegado à tela (ou faça várias chamadas para diferentes quadros de interesse). Analise as estatísticas de quadros retornadas para orientar as atualizações do ponto de limitação de quadros estabelecido, com o objetivo de minimizar a latência entre a entrada do controle e a exibição. Chame [ID3D12Device::ScheduleFrameEventX](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_scheduleframeeventx) com o tipo [D3D12XBOX\_FRAME\_EVENT\_ORIGIN](/pt-BR/reference/graphics/d3d12_x/enums/d3d12xbox_frame_event_type) para executar as atualizações, que serão aplicadas quando o próximo quadro a ser apresentado após a chamada for invertido para a tela.
* Execute qualquer trabalho independente de entrada na CPU/GPU antes de prosseguir para aguardar a próxima origem de quadro (ou enquanto a sonda).

<a id="ID4ExampleCode" />

## Código de exemplo

O exemplo de código a seguir demonstra o fluxo de trabalho de alto nível para uma renderização a 60 FPS em 1080p, com um único plano de fundo e um pool de troca de 2 recursos.

```cpp theme={null}
    // Game initialization.

    HRESULT hr;

    D3D12_HEAP_PROPERTIES heapProperties = {};
    heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
    heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
    heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
    heapProperties.CreationNodeMask = D3D12XBOX_NODE_MASK;
    heapProperties.VisibleNodeMask = D3D12XBOX_NODE_MASK;

    D3D12_RESOURCE_DESC swapResourceDesc = {};
    swapResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
    swapResourceDesc.Alignment = 0;
    swapResourceDesc.Width = 1920;
    swapResourceDesc.Height = 1080;
    swapResourceDesc.DepthOrArraySize = 1;
    swapResourceDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM;
    swapResourceDesc.MipLevels = 1;
    swapResourceDesc.SampleDesc.Count = 1;
    swapResourceDesc.SampleDesc.Quality = 0;
    swapResourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
    swapResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;

    // Create a swap pool of two displayable resources.

    ID3D12Resource* pSwapResources[2];

    for (UINT i = 0; i < 2; ++i)
    {
        hr = pd3dDevice->CreateCommittedResource(
            &heapProperties,
            D3D12_HEAP_FLAG_ALLOW_DISPLAY,
            &swapResourceDesc,
            D3D12_RESOURCE_STATE_PRESENT,
            nullptr,
            __uuidof(ID3D12Resource),
            (void**)&pSwapResources[i]);

        if (FAILED(hr))
        {
            return hr;
        }
    }

    // Establish a 60 Hz frame-rate interval and a frame period spanning two intervals, which permits the
    // CPU to begin recording and submitting commands for one frame while the GPU is still processing
    // commands submitted on the previous frame (if the CPU attempts to begin work on frame n + 2 before
    // the GPU has completed frame n and flipped it to the display, it will be throttled until the interval
    // following the flip).

    hr = pd3dDevice->SetFrameIntervalX(
        nullptr,
        D3D12XBOX_FRAME_INTERVAL_60_HZ,         // 16,667 microseconds between flips (60 flips per second).
        2,                                      // Frame period of 2 intervals (frame started during one
                                                // interval and finished on the next).
        D3D12XBOX_FRAME_INTERVAL_FLAG_NONE);

    if (FAILED(hr))
    {
        return hr;
    }

    // Schedule a frame origin event to establish the CPU throttle point for the game. The frame
    // origin is the time that a new frame is generated, and is generally expected to be the
    // moment when input is queried and directly used in the construction of the frame. The
    // origin should be scheduled as near to the time of frame display as possible to minimize latency,
    // based on expected frame duration (and informed by statistics feedback). In this example,
    // the game anticipates an initial end-to-end frame duration (from input query, to CPU rendering,
    // to GPU processing, to presentation for display) of 27,778 microseconds (1.66 frame intervals).
    // This translates into a frame period of 2 intervals and an interval offset of 5,556 microseconds.

    hr = pd3dDevice->ScheduleFrameEventX(
        D3D12XBOX_FRAME_EVENT_ORIGIN,              // Origin event type.
        5556,                                      // Begin the frame after one-third of the interval has passed.
        nullptr,                                   // Don't signal any additional game events at the origin.
        D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE);

    if (FAILED(hr))
    {
        return hr;
    }

    {...}

    // Game loop.

    D3D12XBOX_FRAME_PIPELINE_TOKEN frameToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL;

    do
    {
        // Perform a modest, measured amount of CPU/GPU processing not directly dependent on user input
        // (for example, texture streaming).
        {...}

        // Poll on the origin event for the frame, throttling the CPU as necessary.

        hr = pd3dDevice->WaitFrameEventX(
            D3D12XBOX_FRAME_EVENT_ORIGIN,
            0,                                    // Poll with an immediate timeout.
            nullptr,                              // Don't wait on additional game events in
                                                  // conjunction with origin.
            D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE,
            &token);                              // Obtain the frame's identifying token.

        if (hr == D3DERR_DEVICEREMOVED)
        {
            // The GPU may have stopped responding, preventing it from reaching the present submitted for
            // a previous frame and flipping it to the display. This would in turn prevent
            // the new frame origin event from being signaled due to the throttle. Alternatively,
            // another thread responsible for processing suspend events may have called
            // SuspendX during the origin wait, causing it to fail. Test and handle these
            // conditions as appropriate.
            {...}
        }

    } while (hr == S_FALSE);

    ++m_FrameIndex;

    // Store the frame token for later statistics retrieval.

    m_FrameToken[m_FrameIndex % 16] = token;

    // Query user input from the gamepad.

    IGameInputReading* pReading;

    pGameInput->GetCurrentReading(
        GameInputKindGamepad,
        pGamepadDevice,
        &pReading);

    // Render the frame based on the input reading to pSwapResources[m_FrameIndex % 2].

    {...}

    pReading->Release();

    // Queue the rendered frame for presentation to the display. Effective frame scheduling
    // will contrive to minimize the amount of time the swap resource remains in the queue
    // before being flipped and scanned out.

    D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters = {};

    planeParameters.Token = token;                          // Identify the frame being presented.
    planeParameters.ResourceCount = 1;
    planeParameters.ppResources = &pSwapResources[m_FrameIndex % 2]; // Present the associated swap resource.
    planeParameters.pSrcViewRects = nullptr;                // Display the entire resource (no dynamic scaling
                                                            // or split-screen multiplayer).
    planeParameters.pDestPlacementBase = nullptr;           // Full coverage of the display.
    planeParameters.ColorSpace = DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020 // HDR color space.
    planeParameters.ScaleFilter = D3D12XBOX_PRESENT_PLANE_SCALE_FILTER_DEFAULT;
    planeParameters.Flags = D3D12XBOX_PRESENT_PLANE_FLAG_NONE;

    D3D12XBOX_PRESENT_PARAMETERS presentParameters = {};

    presentParameters.ImmediateThresholdPercent = 5.0f;     // Allow tearing in the top 5 percent of the frame.
    presentParameters.ViewCount = 1;                        // No split-screen multiplayer.
    presentParameters.Flags = D3D12XBOX_PRESENT_FLAG_NONE;

    pd3dCommandQueue->PresentX(
        1,
        &planeParameters,

    // Collect statistics for the most recently flipped frame.

    D3D12XBOX_FRAME_STATISTICS statisticsList[4];
    UINT statisticsCount = _countof(statisticsList);

    hr = pd3dDevice->GetFrameStatisticsX(
        m_FrameToken[(m_FrameIndex + 14) % 16],             // Query the frame originating 2 intervals in the past
                                                            // (display flip guaranteed).
        D3D12XBOX_FRAME_STATISTICS_TYPE_FRAME_EVENT |
            D3D12XBOX_FRAME_STATISTICS_TYPE_RENDER |
            D3D12XBOX_FRAME_STATISTICS_TYPE_PRESENT |
            D3D12XBOX_FRAME_STATISTICS_TYPE_DISPLAY,        // Query statistics relevant to latency analysis.
        &statisticsCount,                                   // Four entries is sufficient given no overlay and
        statisticsList);                                    // a single frame event type scheduled.

    if (SUCCEEDED(hr) &&
        (statisticsCount != 0))
    {
        bool originUpdate = false;
        UINT intervalOffsetInUs;

        // Analyze the returned statistics list to determine such things as frame length from origin to GPU
        // completion and display. Use the information to inform updates to frame scheduling with the goals
        // of minimizing latency while avoiding missed vblanks due to processing spikes.

        // Some possible considerations:
        //   Is D3D12XBOX_PRESENT_STATISTICS::GPUProcessTime too far from D3D12XBOX_DISPLAY_STATISTICS::VSyncTime?
        //     (Wasted latency from early frame completion.)
        //   Is D3D12XBOX_PRESENT_STATISTICS::GPUProcessTime too near to D3D12XBOX_DISPLAY_STATISTICS::VSyncTime?
        //     (Risk of frame drop from late frame completion.)
        //   Is D3D12XBOX_PRESENT_STATISTICS::GPUProcessTime not arriving soon after D3D12XBOX_RENDER_STATISTICS::
        //     GPUWriteCompleteTime? (Frame independent work done between swap resource completion and present
        //     instead of after present.)
        //   Is D3D12XBOX_FRAME_EVENT_STATISTICS::WaitCallTime too far from D3D12XBOX_FRAME_EVENT_STATISTICS::
        //     SignalTime? (Wait thread blocked on origin signal.)

        // When frame latency conditions have changed beyond some threshold margin, update the frame origin to
        // move it nearer to the target vblank (reduce latency) or further fom the vblank (avoid vblank miss).  
        // The frame origin update will be applied when the swap resource of the subsequent frame
        // (m_FrameIndex + 1) has been flipped to the display.

        if (originUpdate)
        {
            pd3dDevice->ScheduleFrameEventX(
                D3D12XBOX_FRAME_EVENT_ORIGIN,
                intervalOffsetInUs,
                nullptr,
                D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE);
        }
    }
```

<a id="ID4EABAC" />


## Related topics

- [Diretório de tópicos NDA: links ativos do Microsoft Learn](/pt-BR/nda/nda-topic-directory.md)
- [A arquitetura de áudio no XBOX One](/pt-BR/build/console-features/audio/overviews/xbox-one-audio-architecture.md)
- [Visão geral do DirectCapture](/pt-BR/build/core-features/common/game-streaming/game-streaming-directcapture-overview.md)
- [Xfest2022](/pt-BR/build/core-features/graphics/overviews/presentations/xfest2022/index.md)
- [Xdd2024](/pt-BR/build/core-features/graphics/overviews/presentations/xdd2024/index.md)
