Multisampling in universellen Windows-apps-Plattform (UWP) Multisampling in Universal Windows Platform (UWP) apps

Hier erfahren Sie, wie Sie Multisampling in UWP-Apps (Apps für die universelle Windows-Plattform) verwenden, die mit Direct3D erstellt wurden.Learn how to use multisampling in Universal Windows Platform (UWP) apps built with Direct3D. Das Multisampling, das auch als Multiple Sample Antialiasing bezeichnet wird, ist ein Grafikverfahren, das treppenförmige Kanten reduziert.Multisampling, also known as multi-sample antialiasing, is a graphics technique used to reduce the appearance of aliased edges. Dazu werden mehr Pixel gezeichnet, als im endgültigen Renderziel tatsächlich enthalten sind, und anschließend wird der Mittelwert der Werte gebildet, um in bestimmten Pixeln die Darstellung einer "partiellen" Kante zu erreichen.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. Eine ausführliche Beschreibung der Funktionsweise des Multisamplings in Direct3D finden Sie unter Regeln für die Rasterung beim Multiple Sample Antialiasing.For a detailed description of how multisampling actually works in Direct3D, see Multisample Anti-Aliasing Rasterization Rules.

Multisampling und die Flipmodell-SwapchainMultisampling and the flip model swap chain

Für UWP-Apps, die DirectX nutzen, müssen Flipmodell-Swapchains verwendet werden.UWP apps that use DirectX must use flip model swap chains. Flipmodell-Swapchains verfügen über keine direkte Multisampling-Unterstützung. Das Multisampling kann aber auf andere Art und Weise angewendet werden. Hierzu wird die Szene in einer Renderzielansicht mit Multisampling gerendert und dieses Renderziel mit Multisampling vor dem Darstellen dann für den Hintergrundpuffer aufgelöst.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. Dieser Artikel beschreibt die Schritte, die erforderlich sind, um UWP-Apps mit Multisampling zu versehen.This article explains the steps required to add multisampling to your UWP app.

Verwenden von MultisamplingHow to use multisampling

Direct3D-Featureebenen stellen die Unterstützung für spezielle Mindestfunktionen für die Beispielanzahl sicher, und es sind bestimmte Pufferformate verfügbar, die das Multisampling unterstützen.Direct3D feature levels guarantee support for specific, minimum sample count capabilities, and guarantee certain buffer formats will be available that support multisampling. Grafikgeräte unterstützen häufig einen weiteren Bereich von Formaten und Beispielanzahlen als das erforderliche Minimum.Graphics devices often support a wider range of formats and sample counts than the minimum required. Sie können die Multisampling-Unterstützung zur Laufzeit bestimmen. Prüfen Sie zu diesem Zweck die Featureunterstützung für das Multisampling mit bestimmten DXGI-Formaten und anschließend die Beispielanzahlen, die Sie für die einzelnen unterstützten Formate verwenden können.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. Ermitteln Sie per Aufruf von ID3D11Device::CheckFeatureSupport, welche DXGI-Formate in Verbindung mit dem Multisampling verwendet werden können.Call ID3D11Device::CheckFeatureSupport to find out which DXGI formats can be used with multisampling. Geben Sie die Renderzielformate an, die vom Spiel verwendet werden können.Supply the render target formats your game can use. Sowohl die Renderziel als auch beheben müssen, verwenden das gleiche Format überprüfen Sie daher für beide D3D11_FORMAT_Unterstützung_MULTISAMPLE_renderTarget-Klasse und D3D11_FORMAT_Unterstützung_MULTISAMPLE_beheben.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.

    **Funktionsebene 9:  ** Obwohl die Feature-Ebene 9-Geräten garantieren Sie Unterstützung für Multisampling-renderzielformate, Unterstützung ist für für Multisampling Resolve-Ziele nicht garantiert.**Feature level 9:  ** Although feature level 9 devices guarantee support for multisampled render target formats, support is not guaranteed for multisample resolve targets. Diese Überprüfung ist also erforderlich, bevor versucht wird, das in diesem Thema beschriebene Multisampling-Verfahren anzuwenden.So this check is necessary before trying to use the multisampling technique described in this topic.

    Der folgende Code überprüft multisampling-Unterstützung für alle der DXGI_FORMATIERUNG von Werten: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. Fragen Sie für jedes unterstützte Format die Beispielanzahl ab, indem Sie ID3D11Device::CheckMultisampleQualityLevels aufrufen.For each supported format, query for sample count support by calling ID3D11Device::CheckMultisampleQualityLevels.

    Mit dem folgenden Code wird die Unterstützung der Beispielgröße für unterstützte DXGI-Formate überprüft: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);
            }
        }
    }
    

    Beachten Sie    verwenden ID3D11Device2::CheckMultisampleQualityLevels1 stattdessen bei Bedarf für Multisampling-Unterstützung für die unterteilten Ressourcen Puffer zu überprüfen.Note   Use ID3D11Device2::CheckMultisampleQualityLevels1 instead if you need to check multisample support for tiled resource buffers.

     

  3. Erstellen Sie einen Puffer und eine Renderzielansicht mit der gewünschten Beispielanzahl.Create a buffer and render target view with the desired sample count. Verwenden Sie die gleichen DXGI_FORMAT, Breite und Höhe der SwapChain, aber geben Sie eine Beispiel-Anzahl größer als 1 und verwenden eine Dimension Multisampling-Textur (D3D11_RTV_DIMENSION_TEXTURE2DMS z. B.).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). Bei Bedarf können Sie die Swapchain mit für das Multisampling optimalen Einstellungen neu erstellen.If necessary, you can re-create the swap chain with new settings that are optimal for multisampling.

    Mit dem folgenden Code wird ein Renderziel mit Multisampling erstellt: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. Der Tiefenpuffer muss die gleiche Breite, Höhe, Beispielanzahl und Texturdimension haben, um mit dem Renderziel mit Multisampling übereinzustimmen.The depth buffer must have the same width, height, sample count, and texture dimension to match the multisampled render target.

    Mit dem folgenden Code wird ein Tiefenpuffer mit Multisampling erstellt: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. Dies ist ein guter Zeitpunkt zum Erstellen des Viewports, da die Breite und Höhe des Viewports ebenfalls mit dem Renderziel übereinstimmen muss.Now is a good time to create the viewport, because the viewport width and height must also match the render target.

    Mit dem folgenden Code wird ein Viewport erstellt: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. Rendern Sie jeden Frame für das Renderziel mit Multisampling.Render each frame to the multisampled render target. Rufen Sie nach Abschluss des Renderings ID3D11DeviceContext::ResolveSubresource auf, bevor der Frame dargestellt wird.When rendering is complete, call ID3D11DeviceContext::ResolveSubresource before presenting the frame. Damit wird Direct3D angewiesen, den Multisampling-Vorgang durchzuführen, den Wert jedes Pixels für die Anzeige zu berechnen und das Ergebnis in den Hintergrundpuffer zu stellen.This instructs Direct3D to peform the multisampling operation, computing the value of each pixel for display and placing the result in the back buffer. Der Hintergrundpuffer enthält dann das endgültige Antialiasing-Bild für die Darstellung.The back buffer then contains the final anti-aliased image and can be presented.

    Mit dem folgenden Code wird die Unterressource aufgelöst, bevor der Frame dargestellt wird: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);