Supporting the Windows Store Certification D3D Device Trim requirement

logoangleApplications submitted to the Windows Store must pass the Windows App Certification Kit.  This kit launches the application and performs multiple tests to ensure that the application meets the Windows Store requirements. 

A test category labeled Direct3D Feature Test checks if your application properly calls IDXGIDevice3::Trim when it is suspended. Starting in Windows 8.1, apps that render with Direct2D and/or Direct3D (including CoreWindow and XAML interop) must call Trim in response to the Process Lifetime Management (PLM) suspend callback.

The “Direct3D Trim after Suspended” test in the “Direct3D Feature Test” category will report the following error if the Trim requirement is not met.

"One or more applications in the package did not call Trim() on their DXGI Devices while being suspended."

What is Trim?

Trim is a mechanism that instructs the Direct3D runtime and the graphics driver that it is safe to discard internal memory buffers allocated for the app, reducing its memory footprint when needed. This is performed by calling DXGIDevice3::Trim( ).

How do I make my application pass this Trim requirement?

ANGLE provides two options to support this requirement.  An automatic option, where ANGLE will manage calling Trim for you, and a manual option where your application can control when Trim is called.  The default in ANGLE is to NOT automatically call Trim for the application.  Enabling automatic trim in ANGLE is recommended.

Enable Automatic Trim

To have ANGLE manage this trim requirement for your application, all you need to do is add EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE set to EGL_TRUE in your EGL display attributes passed to eglGetPlatformDisplayEXT( ).

Manual Trim

First you need to register for the Application suspended event handler.  Examples of this registration can be found on the DirectX Windows Store samples.

Next you need to let ANGLE know that you want to control calling Trim yourself.  This is done by adding EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE set to EGL_FALSE in your EGL display attributes passed to eglGetPlatformDisplayEXT( ).  After doing this ANGLE will no longer call DXGIDevice3::Trim( ) for your application.

The code snippet below shows how you can acquire the D3DDevice from the EGLDisplay and eventually call Trim.  The following snippets show how to register for the application suspending event.  Note the different versions of event registrations tailored for CoreWindow and XAML based applications.

CoreWindow application registration for Suspending event

void App::Initialize(CoreApplicationView^ applicationView)

{

    CoreApplication::Suspending +=

        ref new EventHandler<SuspendingEventArgs^>(this, &App::OnSuspending);

}

 

XAML application registration for Suspending event

App::App()

{

    InitializeComponent();

    Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending);

}

 

Suspending event handler

void App::OnSuspending(Object^ , SuspendingEventArgs^)

{

    // Call trim helper in response to the suspending event

    mOpenGLES.Trim();

}

 

In this example, the OpenGLES helper class is extended to contain a new public method called ‘Trim’ which can be called directly by the application object where the suspended event handler is registered.

Implementation for Trim( ) helper function

void OpenGLES::Trim()

{

    PFNEGLQUERYDISPLAYATTRIBEXTPROC QueryDisplayAttribEXT;

    PFNEGLQUERYDEVICEATTRIBEXTPROC QueryDeviceAttribEXT;

 

    QueryDisplayAttribEXT = (PFNEGLQUERYDISPLAYATTRIBEXTPROC)eglGetProcAddress("eglQueryDisplayAttribEXT");

    QueryDeviceAttribEXT = (PFNEGLQUERYDEVICEATTRIBEXTPROC)eglGetProcAddress("eglQueryDeviceAttribEXT");

 

    EGLBoolean result = EGL_FALSE;

    EGLAttrib device = 0;

    EGLAttrib angleDevice = 0;

    if (QueryDisplayAttribEXT(mEglDisplay, EGL_DEVICE_EXT, &angleDevice) == EGL_TRUE)

    {

        if (QueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice), EGL_D3D11_DEVICE_ANGLE, &device) == EGL_TRUE)

        {

            ComPtr<ID3D11Device> d3d11Device = reinterpret_cast<ID3D11Device*>(device);

            ComPtr<IDXGIDevice3> dxgiDevice3;

            if (SUCCEEDED(d3d11Device.As(&dxgiDevice3)))

            {

                dxgiDevice3->Trim();

            }

        }

    }

}

Cooper Partin

Senior Software Engineer