Crash in simple Direct Compute sample

Hi all

I am working on a Direct Compute based 3D scanning application. It is similar to Kinect Fusion with some additional features. In the application we start several threads that use deferred contexts to do version steps of the processing.

The problem is that we have some crashes that we can not explain, and where we are in doubt if we are doing something wrong or if we have found an issue in Direct Compute / NVidia’s drivers. I have made a small modification to the BasicCompute sample from the DX framework which reproduces our issue. It crashes with the following message:

Unhandled exception at 0x572796E6 (nvwgf2um.dll) in BasicCompute11.exe: 0xC0000005: Access violation writing location 0xBAADF011.

The code is pasted below and is very basic. We start several threads using a parallel_for, where each thread only creates some resources and disposes them again. This is obviously much simpler than our scanning application but the error appears to be the same.

Have I misunderstood something about what I am required to synchronize or is there some other expectable explanation to the crash I am seeing?

I appreciate any feedback you may be able to give.

Edit: I updated the code a bit to use the test boolean and lower the count in the parallel loop as 500 is unrealistically high. Code still crash with the edited code, although I now need to run it several times before it crash.

Code:

//--------------------------------------------------------------------------------------
// File: BasicCompute11.cpp
//
// Demonstrates the basics to get DirectX 11 Compute Shader (aka DirectCompute) up and
// running by implementing Array A + Array B
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------

#include <stdio.h>
#include <crtdbg.h>
#include <d3dcommon.h>
#include <d3d11.h>
#include <d3dcompiler.h>
#include <d3dx11.h>
#include <ppl.h>

using namespace concurrency;
using namespace std;

#ifndef SAFE_RELEASE
#define SAFE_RELEASE(p)      { if (p) { (p)->Release(); (p)=NULL; } }
#endif

//--------------------------------------------------------------------------------------
// Forward declarations 
//--------------------------------------------------------------------------------------
HRESULT CreateComputeDevice( ID3D11Device** ppDeviceOut, ID3D11DeviceContext** ppContextOut, BOOL bForceRef );
HRESULT CreateComputeShader( LPCWSTR pSrcFile, LPCSTR pFunctionName, 
                             ID3D11Device* pDevice, ID3D11ComputeShader** ppShaderOut );

//--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------
ID3D11Device*               g_pDevice = NULL;
ID3D11DeviceContext*        g_pContext = NULL;

reader_writer_lock			g_lock;

void FlushDeviceContext(ID3D11DeviceContext* context)
{
	g_lock.lock();
	ID3D11CommandList* list;
	context->FinishCommandList(true, &list);
	g_pContext->ExecuteCommandList(list, true);
	list->Release();
	g_lock.unlock();
}

void CreateVolumeTextureAndUAV()
{
	ID3D11DeviceContext* context;
	HRESULT hr = g_pDevice->CreateDeferredContext(0, &context);
	if( FAILED(hr) )
            return;

	ID3D11Texture3D* texture;
	D3D11_TEXTURE3D_DESC desc;
	desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
	desc.Format = DXGI_FORMAT_R32_FLOAT;
    desc.Width = 8;
    desc.Height = 4;
    desc.Depth = 4;
    desc.MipLevels = 1;
	desc.Usage = D3D11_USAGE_DEFAULT;
	desc.MiscFlags = 0;
	desc.CPUAccessFlags = 0;

	g_pDevice->CreateTexture3D(&desc, NULL, &texture);

	ID3D11UnorderedAccessView* uav;
	g_pDevice->CreateUnorderedAccessView(texture, NULL, &uav);

	FlushDeviceContext(context);

	context->Release();

	uav->Release();

	texture->Release();
}

void StartGpuCrashTest()
{
	parallel_for (0, 500, [] (int i) 
    { 
        CreateVolumeTextureAndUAV(); 
    });

	//for(int i=0; i<5; i++)
	//{
	//	CreateVolumeTextureAndUAV(); 
	//}
}

//--------------------------------------------------------------------------------------
// Entry point to the program
//--------------------------------------------------------------------------------------
int __cdecl main()
{
    printf( "Creating device..." );
    if ( FAILED( CreateComputeDevice( &g_pDevice, &g_pContext, FALSE ) ) )
        return 1;

	StartGpuCrashTest();

	printf( "Press any key to end\n" );
	getchar();

	printf( "Cleaning up...\n" );
    SAFE_RELEASE( g_pContext );
    SAFE_RELEASE( g_pDevice );

    return 0;
}

//--------------------------------------------------------------------------------------
// This is equivalent to D3D11CreateDevice, except it dynamically loads d3d11.dll,
// this gives us a graceful way to message the user on systems with no d3d11 installed
//--------------------------------------------------------------------------------------
HRESULT WINAPI Dynamic_D3D11CreateDevice( IDXGIAdapter* pAdapter,
                                          D3D_DRIVER_TYPE DriverType,
                                          HMODULE Software,
                                          UINT32 Flags,
                                          CONST D3D_FEATURE_LEVEL* pFeatureLevels,
                                          UINT FeatureLevels,
                                          UINT32 SDKVersion,
                                          ID3D11Device** ppDevice,
                                          D3D_FEATURE_LEVEL* pFeatureLevel,
                                          ID3D11DeviceContext** ppImmediateContext )
{
    typedef HRESULT (WINAPI * LPD3D11CREATEDEVICE)( IDXGIAdapter*, D3D_DRIVER_TYPE, HMODULE, UINT32, CONST D3D_FEATURE_LEVEL*, UINT, UINT32, ID3D11Device**, D3D_FEATURE_LEVEL*, ID3D11DeviceContext** );
    static LPD3D11CREATEDEVICE  s_DynamicD3D11CreateDevice = NULL;
    
    if ( s_DynamicD3D11CreateDevice == NULL )
    {            
        HMODULE hModD3D11 = LoadLibrary( L"d3d11.dll" );

        if ( hModD3D11 == NULL )
        {
            // Ensure this "D3D11 absent" message is shown only once. As sometimes, the app would like to try
            // to create device multiple times
            static bool bMessageAlreadyShwon = false;
            
            if ( !bMessageAlreadyShwon )
            {
                OSVERSIONINFOEX osv;
                memset( &osv, 0, sizeof(osv) );
                osv.dwOSVersionInfoSize = sizeof(osv);
                GetVersionEx( (LPOSVERSIONINFO)&osv );

                if ( ( osv.dwMajorVersion > 6 )
                    || ( osv.dwMajorVersion == 6 && osv.dwMinorVersion >= 1 ) 
                    || ( osv.dwMajorVersion == 6 && osv.dwMinorVersion == 0 && osv.dwBuildNumber > 6002 ) )
                {

                    MessageBox( 0, L"Direct3D 11 components were not found.", L"Error", MB_ICONEXCLAMATION );
                    // This should not happen, but is here for completeness as the system could be
                    // corrupted or some future OS version could pull D3D11.DLL for some reason
                }
                else if ( osv.dwMajorVersion == 6 && osv.dwMinorVersion == 0 && osv.dwBuildNumber == 6002 )
                {

                    MessageBox( 0, L"Direct3D 11 components were not found, but are available for"\
                        L" this version of Windows.\n"\
                        L"For details see Microsoft Knowledge Base Article #971644\n"\
                        L"http://support.microsoft.com/default.aspx/kb/971644/", L"Error", MB_ICONEXCLAMATION );

                }
                else if ( osv.dwMajorVersion == 6 && osv.dwMinorVersion == 0 )
                {
                    MessageBox( 0, L"Direct3D 11 components were not found. Please install the latest Service Pack.\n"\
                        L"For details see Microsoft Knowledge Base Article #935791\n"\
                        L" http://support.microsoft.com/default.aspx/kb/935791", L"Error", MB_ICONEXCLAMATION );

                }
                else
                {
                    MessageBox( 0, L"Direct3D 11 is not supported on this OS.", L"Error", MB_ICONEXCLAMATION );
                }

                bMessageAlreadyShwon = true;
            }            

            return E_FAIL;
        }

        s_DynamicD3D11CreateDevice = ( LPD3D11CREATEDEVICE )GetProcAddress( hModD3D11, "D3D11CreateDevice" );           
    }

    return s_DynamicD3D11CreateDevice( pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels,
                                       SDKVersion, ppDevice, pFeatureLevel, ppImmediateContext );
}

//--------------------------------------------------------------------------------------
// Create the D3D device and device context suitable for running Compute Shaders(CS)
//--------------------------------------------------------------------------------------
HRESULT CreateComputeDevice( ID3D11Device** ppDeviceOut, ID3D11DeviceContext** ppContextOut, BOOL bForceRef )
{    
    *ppDeviceOut = NULL;
    *ppContextOut = NULL;
    
    HRESULT hr = S_OK;

    UINT uCreationFlags = 0;
#if defined(DEBUG) || defined(_DEBUG)
    uCreationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
    D3D_FEATURE_LEVEL flOut;
    static const D3D_FEATURE_LEVEL flvl[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0 };
    
    BOOL bNeedRefDevice = FALSE;
    if ( !bForceRef )
    {
        hr = Dynamic_D3D11CreateDevice( NULL,                        // Use default graphics card
                                        D3D_DRIVER_TYPE_HARDWARE,    // Try to create a hardware accelerated device
                                        NULL,                        // Do not use external software rasterizer module
                                        uCreationFlags,              // Device creation flags
                                        flvl,
                                        sizeof(flvl) / sizeof(D3D_FEATURE_LEVEL),
                                        D3D11_SDK_VERSION,           // SDK version
                                        ppDeviceOut,                 // Device out
                                        &flOut,                      // Actual feature level created
                                        ppContextOut );              // Context out
    }
   
    return hr;
}