Search code examples
windowsdirect3dhlsldirect3d11

Load from multisampled texture fails on some Intel GPUs


I’ve implemented mouse picking in my app by using a stencil buffer.

Here’s the pixel shader that reads value under the mouse:

Texture2DMS<uint2> depthStencilTexture : register( t0 );

cbuffer ReadDepthInput : register( b2 )
{
    int2 readPosition;
}

// Produces vector3( x, y, stencilValue )
float4 main() : SV_Target0
{
    uint2 res = depthStencilTexture.Load( readPosition, 1 );
    float stencil = res.y;
    // Scale the result from integers to 0..1
    stencil /= 255.0f;
    return float4( float( readPosition.x ) / 65535.0f, float( readPosition.y ) / 65535.0f, stencil, 0 );
}

The code works on nVidia and AMD GPUs, works on Intel Iris 550.

The code fails on Intel Haswell GPUs (Intel HD 5000, Intel HD 4600). Texture2DMS.Load just returns 0. Any ideas what might be wrong?

Update: Only happens with 8x MSAA. Decreasing it to 4x works OK even on those affected Intel GPUs.


Solution

  • Looks like there’s a bug in Intel GPU driver or hardware.

    Here’s a workaround:

    HRESULT isIntelHaswellGPU( ID3D11Device* device )
    {
        CComQIPtr<IDXGIDevice> dxgiDev = device;
        if( !dxgiDev )
            return E_NOINTERFACE;
    
        CComPtr<IDXGIAdapter> adapter;
        CHECK( dxgiDev->GetAdapter( &adapter ) );
    
        DXGI_ADAPTER_DESC desc;
        CHECK( adapter->GetDesc( &desc ) );
    
        if( desc.VendorId != 0x8086 )
            return S_FALSE; // nVidia or AMD GPU
    
        // https://en.wikipedia.org/wiki/List_of_Intel_graphics_processing_units#Seventh_generation
        // https://github.com/GameTechDev/gpudetect/blob/master/DeviceId.cpp
        const UINT maskedDeviceId = ( desc.DeviceId & 0xFF00 );
        if( maskedDeviceId == 0x0400 || maskedDeviceId == 0x0A00 || maskedDeviceId == 0x0D00 )
            return S_OK;    // Detected Intel Haswell GPU
        return S_FALSE;
    }
    

    If this function returns S_OK, I limit max. MSAA level to 4.