Multisampling nos apps UWP (Plataforma Universal do Windows) Multisampling in Universal Windows Platform (UWP) apps

Saiba como utilizar o multisampling em aplicativos da Plataforma Universal do Windows (UWP) desenvolvidos com Direct3D.Learn how to use multisampling in Universal Windows Platform (UWP) apps built with Direct3D. O multisampling, também conhecido como suavização de múltipla amostra, é uma técnica de elementos gráficos usada para reduzir a aparição de bordas suavizadas.Multisampling, also known as multi-sample antialiasing, is a graphics technique used to reduce the appearance of aliased edges. Essa técnica desenha mais pixels do que o que realmente existe no destino de renderização e, depois, faz uma média dos valores para manter a aparência de uma borda "parcial" em determinados pixels.It works by drawing more pixels than are actually in the final render target, then averaging values to maintain the appearance of a "partial" edge in certain pixels. Para uma descrição detalhada sobre como o multisampling funciona no Direct3D, consulte Regras de rasterização para suavização de várias amostras.For a detailed description of how multisampling actually works in Direct3D, see Multisample Anti-Aliasing Rasterization Rules.

Várias amostras e a cadeia de troca do modelo de virar a páginaMultisampling and the flip model swap chain

Os aplicativos UWP em DirectX devem usar cadeias de troca do modelo de inversão.UWP apps that use DirectX must use flip model swap chains. As cadeias de troca do modelo de inversão não dão suporte a várias amostras diretamente, mas esse método ainda pode ser aplicado de uma forma diferente, renderizando a cena para um modo de exibição de destino de renderização com várias amostras e, depois, resolvendo o destino de renderização com várias amostras para o buffer de fundo antes da apresentação.Flip model swap chains don't support multisampling directly, but multisampling can still be applied in a different way by rendering the scene to a multisampled render target view, and then resolving the multisampled render target to the back buffer before presenting. Este artigo explica as etapas necessárias para adicionar várias amostras a seu aplicativo UWP.This article explains the steps required to add multisampling to your UWP app.

Como usar várias amostrasHow to use multisampling

Os níveis de recursos do Direct3D garantem o suporte a funcionalidades específicas de contagem mínima de amostras e garantem que determinados formatos de buffer que dão suporte a várias amostras estarão disponíveis.Direct3D feature levels guarantee support for specific, minimum sample count capabilities, and guarantee certain buffer formats will be available that support multisampling. Os dispositivos gráficos costumam dar suporte a um número maior do que o mínimo necessário de formatos e contagens de amostras.Graphics devices often support a wider range of formats and sample counts than the minimum required. O suporte ao multisampling pode ser determinado no tempo de execução verificando o suporte ao recurso de multisampling para formatos DXGI específicos e, em seguida, verificando o número de amostras que podem ser usadas com cada formato com suporte.Multisampling support can be determined at run-time by checking feature support for multisampling with specific DXGI formats, and then checking the sample counts you can use with each supported format.

  1. Chame ID3D11Device::CheckFeatureSupport para descobrir quais formatos DXGI podem ser usados com o multisampling.Call ID3D11Device::CheckFeatureSupport to find out which DXGI formats can be used with multisampling. Forneça os formatos de destino de renderização que seu jogo pode usar.Supply the render target formats your game can use. Tanto o destino de processamento quanto o destino de resolução devem usar o mesmo formato, portanto, verifique se o ** _ formato D3D11 dá suporte a RENDERTARGET e formato _ _ multiamostra _ ** de suporte para ** _ _ _ _ resolução de multiamostrar**.Both the render target and resolve target must use the same format, so check for both D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET and D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE.

    **Nível de recurso 9:  ** Embora os dispositivos de nível de recurso 9 garantam suporte para formatos de destino de renderização com uma amostra, o suporte não é garantido para destinos de resolução de multiamostrar.**Feature level 9:  ** Although feature level 9 devices guarantee support for multisampled render target formats, support is not guaranteed for multisample resolve targets. Sendo assim, essa verificação é necessária antes de tentar usar a técnica de várias amostras descrita neste tópico.So this check is necessary before trying to use the multisampling technique described in this topic.

    O código a seguir verifica o suporte a multiamostrar para todos os _ valores de formato DXGI:The following code checks multisampling support for all the DXGI_FORMAT values:

    // Determine the format support for multisampling.
    for (UINT i = 1; i < DXGI_FORMAT_MAX; i++)
    {
        DXGI_FORMAT inFormat = safe_cast<DXGI_FORMAT>(i);
        UINT formatSupport = 0;
        HRESULT hr = m_d3dDevice->CheckFormatSupport(inFormat, &formatSupport);
    
        if ((formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE) &&
            (formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET)
            )
        {
            m_supportInfo->SetFormatSupport(i, true);
        }
        else
        {
            m_supportInfo->SetFormatSupport(i, false);
        }
    }
    
  2. Para cada formato com suporte, consulte o suporte a contagem de amostras chamando ID3D11Device::CheckMultisampleQualityLevels.For each supported format, query for sample count support by calling ID3D11Device::CheckMultisampleQualityLevels.

    O código a seguir verifica o suporte a tamanho da amostra para todos os formatos DXGI com suporte:The following code checks sample size support for supported DXGI formats:

    // Find available sample sizes for each supported format.
    for (unsigned int i = 0; i < DXGI_FORMAT_MAX; i++)
    {
        for (unsigned int j = 1; j < MAX_SAMPLES_CHECK; j++)
        {
            UINT numQualityFlags;
    
            HRESULT test = m_d3dDevice->CheckMultisampleQualityLevels(
                (DXGI_FORMAT) i,
                j,
                &numQualityFlags
                );
    
            if (SUCCEEDED(test) && (numQualityFlags > 0))
            {
                m_supportInfo->SetSampleSize(i, j, 1);
                m_supportInfo->SetQualityFlagsAt(i, j, numQualityFlags);
            }
        }
    }
    

    Observação    Use ID3D11Device2:: CheckMultisampleQualityLevels1 em vez disso, se você precisar verificar o suporte de multiamostra para buffers de recursos de lado.Note   Use ID3D11Device2::CheckMultisampleQualityLevels1 instead if you need to check multisample support for tiled resource buffers.

     

  3. Crie um buffer e renderize a visualização do destino com a contagem de amostras desejada.Create a buffer and render target view with the desired sample count. Use o mesmo _ formato, largura e altura de dxgi que a cadeia de permuta, mas especifique uma contagem de amostra maior que 1 e use uma dimensão de textura de multiamostra (D3D11 _ RTV _ Dimension _ TEXTURE2DMS , por exemplo).Use the same DXGI_FORMAT, width, and height as the swap chain, but specify a sample count greater than 1 and use a multisampled texture dimension (D3D11_RTV_DIMENSION_TEXTURE2DMS for example). Se necessário, você pode recriar a cadeia de troca com novas configurações que sejam ideais para o multisampling.If necessary, you can re-create the swap chain with new settings that are optimal for multisampling.

    O código a seguir cria um destino de renderização com várias amostras:The following code creates a multisampled render target:

    float widthMulti = m_d3dRenderTargetSize.Width;
    float heightMulti = m_d3dRenderTargetSize.Height;
    
    D3D11_TEXTURE2D_DESC offScreenSurfaceDesc;
    ZeroMemory(&offScreenSurfaceDesc, sizeof(D3D11_TEXTURE2D_DESC));
    
    offScreenSurfaceDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    offScreenSurfaceDesc.Width = static_cast<UINT>(widthMulti);
    offScreenSurfaceDesc.Height = static_cast<UINT>(heightMulti);
    offScreenSurfaceDesc.BindFlags = D3D11_BIND_RENDER_TARGET;
    offScreenSurfaceDesc.MipLevels = 1;
    offScreenSurfaceDesc.ArraySize = 1;
    offScreenSurfaceDesc.SampleDesc.Count = m_sampleSize;
    offScreenSurfaceDesc.SampleDesc.Quality = m_qualityFlags;
    
    // Create a surface that's multisampled.
    DX::ThrowIfFailed(
        m_d3dDevice->CreateTexture2D(
        &offScreenSurfaceDesc,
        nullptr,
        &m_offScreenSurface)
        );
    
    // Create a render target view. 
    CD3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc(D3D11_RTV_DIMENSION_TEXTURE2DMS);
    DX::ThrowIfFailed(
        m_d3dDevice->CreateRenderTargetView(
        m_offScreenSurface.Get(),
        &renderTargetViewDesc,
        &m_d3dRenderTargetView
        )
        );
    
  4. O buffer de profundidade deve ter a mesma largura, altura, contagem de amostras e dimensão de texturas para corresponder ao destino de renderização de várias amostras.The depth buffer must have the same width, height, sample count, and texture dimension to match the multisampled render target.

    O código a seguir cria um buffer de profundidade com várias amostras:The following code creates a multisampled depth buffer:

    // Create a depth stencil view for use with 3D rendering if needed.
    CD3D11_TEXTURE2D_DESC depthStencilDesc(
        DXGI_FORMAT_D24_UNORM_S8_UINT,
        static_cast<UINT>(widthMulti),
        static_cast<UINT>(heightMulti),
        1, // This depth stencil view has only one texture.
        1, // Use a single mipmap level.
        D3D11_BIND_DEPTH_STENCIL,
        D3D11_USAGE_DEFAULT,
        0,
        m_sampleSize,
        m_qualityFlags
        );
    
    ComPtr<ID3D11Texture2D> depthStencil;
    DX::ThrowIfFailed(
        m_d3dDevice->CreateTexture2D(
        &depthStencilDesc,
        nullptr,
        &depthStencil
        )
        );
    
    CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2DMS);
    DX::ThrowIfFailed(
        m_d3dDevice->CreateDepthStencilView(
        depthStencil.Get(),
        &depthStencilViewDesc,
        &m_d3dDepthStencilView
        )
        );
    
  5. Agora é uma boa hora para criar o visor, pois a largura e a altura do visor também devem corresponder ao destino de renderização.Now is a good time to create the viewport, because the viewport width and height must also match the render target.

    O código a seguir cria um visor:The following code creates a viewport:

    // Set the 3D rendering viewport to target the entire window.
    m_screenViewport = CD3D11_VIEWPORT(
        0.0f,
        0.0f,
        widthMulti / m_scalingFactor,
        heightMulti / m_scalingFactor
        );
    
    m_d3dContext->RSSetViewports(1, &m_screenViewport);
    
  6. Renderize cada quadro como um destino de renderização de várias amostras.Render each frame to the multisampled render target. Quando a renderização estiver concluída, chame ID3D11DeviceContext::ResolveSubresource antes de apresentar o quadro.When rendering is complete, call ID3D11DeviceContext::ResolveSubresource before presenting the frame. Isso instrui o Direct3D a realizar a operação de multisampling, calculando o valor de cada pixel para exibição e colocando o resultado no buffer de fundo.This instructs Direct3D to peform the multisampling operation, computing the value of each pixel for display and placing the result in the back buffer. O buffer de fundo contém então a imagem de suavização final e pode ser apresentado.The back buffer then contains the final anti-aliased image and can be presented.

    O código a seguir resolve o sub-recurso antes de apresentar o quadro:The following code resolves the subresource before presenting the frame:

    if (m_sampleSize > 1)
    {
        unsigned int sub = D3D11CalcSubresource(0, 0, 1);
    
        m_d3dContext->ResolveSubresource(
            m_backBuffer.Get(),
            sub,
            m_offScreenSurface.Get(),
            sub,
            DXGI_FORMAT_B8G8R8A8_UNORM
            );
    }
    
    // The first argument instructs DXGI to block until VSync, putting the application
    // to sleep until the next VSync. This ensures that we don't waste any cycles rendering
    // frames that will never be displayed to the screen.
    hr = m_swapChain->Present(1, 0);