Search code examples
visual-studio-2022raytracingwindows-11directx-12direct3d12

Fullscreen mode not working in D3D12 raytracing samples


Presently I'm learning the basics of real-time raytracing with the DXR API in DirectX 12 Ultimate. I'm studying the D3D12 raytracing samples on the official GitHub and am using an i9/Intel Iris Xe/RTX3070 laptop and building the programs in VS2022.

Since the samples were written for Windows 10 and I'm using a hybrid graphics PC, a Debug build will run in Windows 11 after adding D3D12_MESSAGE_ID_RESOURCE_BARRIER_MISMATCHING_COMMAND_LIST_TYPE to D3D12_INFO_QUEUE_FILTER during device creation (see DirectX 12 application is crashing in Windows 11). The only trouble is that none of the sample programs change to fullscreen (i.e. borderless windowed) mode when pressing the Alt+Enter key combination. The programs always stay in windowed mode.

This hasn't worried me so far, because I've been copying the raytracing code over to a template (based on DirectX Tool Kit for Windows desktop) where fullscreen toggling works properly. In this way, I was able to run the HelloWorld and SimpleLighting samples successfully in both windowed mode and fullscreen (2560x1440 monitor resolution).

However, this hasn't been so successful for the ProceduralGeometry sample, which introduces intersection shaders. Once again, the original sample program renders the scene properly, but only in a bordered window. But when the code is reproduced in the template where I can toggle to fullscreen, the raytraced scene does not render properly.

In the scene, the triangle geometry used for the ground plane of the scene renders ok, but a translucent bounding box around the fractal pyramid is visible, and all other procedural geometry also appears translucent. Every couple of seconds, the bounding box for the metaballs also appears briefly, then vanishes.

I was able to determine that by freezing the scene, the reason for the translucency was that the following frames were being presented in sequence:

  • triangle ground plane quad only
  • floor geometry plus opaque fractal pyramid bounding box
  • all of the above plus opaque metaball bounding box
  • completed scene with opaque geometry and no bounding boxes

At the native framerate (165Hz on my machine), this results in both the procedural geometry and bounding boxes always being visible, but 'see-through' due to all the partially complete frames being presented to the display. This happens in both windowed and fullscreen modes, but it's worse in fullscreen, because the scene gets affected by random image corruption not seen in windowed mode.

I've been grappling with this issue for a few days and can't work out the problem. The only changes I've made to the sample program are the Windows 11 fix, and using a template for proper fullscreen rendering, which the original sample ignores or doesn't implement properly.

Hopefully someone can shed light on this perplexing issue!


Solution

  • I found the problem. Each sample has a header file called DXSampleHelper.h. For the ProceduralGeometry sample, this header file was updated with a helper class to manage structured buffers, which is very similar to the helper class for constant buffers.

    The CopyStagingToGpu() method, which consists of a one line memcpy operation in both classes, is slightly different for the structured buffer class:

    memcpy(m_mappedBuffers + instanceIndex * NumElementsPerInstance(), &m_staging[0], InstanceSize());
        
    

    The same method in the constant buffer class is:

    memcpy(m_mappedBuffers + instanceIndex, &m_staging[0], InstanceSize());
    

    I.e. I was missing instanceIndex * NumElementsPerInstance() and thus the procedural geometry instances within the structured buffer were not correctly aligned in GPU memory.