Como usar a camada de depuração do DirectML

A camada de depuração do DirectML é um componente opcional do tempo de desenvolvimento que ajuda você a depurar seu código DirectML. Quando habilitada, a camada de depuração do DirectML encapsula chamadas de API do DirectML e fornece validação e mensagens adicionais para você como desenvolvedor. A camada de depuração é implementada em uma biblioteca separada, DirectML.Debug.dll, que é carregada condicionalmente no runtime pela biblioteca de runtime DirectML.dll principal.

É altamente recomendável que você habilite a camada de depuração ao desenvolver aplicativos usando DirectML, pois ela pode fornecer informações importantes no caso do uso inválido da API.

Visão geral das mensagens da camada de depuração

O exemplo de código abaixo ilustra como a camada de depuração pode ajudar no diagnóstico do uso incorreto da API. Esse código tenta construir uma operação de identidade DirectML. Assim, os tensores de entrada e saída devem ter a mesma forma e tipo de dados. No entanto, neste exemplo, ilustramos um erro nos parâmetros do tensor de saída.

uint32_t sizes[] = { 1 };

DML_BUFFER_TENSOR_DESC inputBufferDesc = {};
inputBufferDesc.DataType = DML_TENSOR_DATA_TYPE_FLOAT32;
inputBufferDesc.DimensionCount = ARRAYSIZE(sizes);
inputBufferDesc.Sizes = sizes;
inputBufferDesc.TotalTensorSizeInBytes = 256;

DML_BUFFER_TENSOR_DESC outputBufferDesc = {};
outputBufferDesc.DataType = DML_TENSOR_DATA_TYPE_FLOAT16; // Invalid: doesn't match input type!
outputBufferDesc.DimensionCount = ARRAYSIZE(sizes);
outputBufferDesc.Sizes = sizes;
outputBufferDesc.TotalTensorSizeInBytes = 256;

DML_TENSOR_DESC inputDesc = { DML_TENSOR_TYPE_BUFFER, &inputBufferDesc };
DML_TENSOR_DESC outputDesc = { DML_TENSOR_TYPE_BUFFER, &outputBufferDesc };

DML_ELEMENT_WISE_IDENTITY_OPERATOR_DESC identityDesc = {};
identityDesc.InputTensor = &inputDesc;
identityDesc.OutputTensor = &outputDesc;

DML_OPERATOR_DESC opDesc = { DML_OPERATOR_ELEMENT_WISE_IDENTITY, &identityDesc };

Microsoft::WRL::ComPtr<IDMLOperator> op;
THROW_IF_FAILED(dmlDevice->CreateOperator(&opDesc, IID_PPV_ARGS(&op)));

Sem a camada de depuração do DirectML, a linha final para criar o operador falha e retorna E_INVALIDARG (0x80070057). A macro THROW_IF_FAILED (para obter mais detalhes, consulte WIL) converte esse código de erro na mensagem genérica "o parâmetro está incorreto" e a imprime na janela de saída do depurador.

TensorValidator.h(203)\DirectML.dll!00007FF83D25ADC9: (caller: 00007FF83D267523) Exception(1) tid(3b54) 80070057 The parameter is incorrect.

Mas quando a camada de depuração do DirectML estiver habilitada, você verá informações adicionais para restringir a causa:

D3D12 ERROR: Mismatched tensor data types. Tensor 'Output' has DataType of DML_TENSOR_DATA_TYPE_FLOAT16, while tensor 'Input' has DataType of DML_TENSOR_DATA_TYPE_FLOAT32. Both tensors are expected to have the same DataType. [ UNKNOWN ERROR #1: STRING_FROM_APPLICATION]

TensorValidator.h(203)\DirectML.Debug.dll!00007FF86DF66ADA: (caller: 00007FF86DF81646) Exception(1) tid(9f34) 80070057 The parameter is incorrect.

Observe como as informações estendidas começam com D3D12 ERROR. Quando a camada de depuração do DirectML detecta um problema, ela sempre prefere enviar mensagens de erro para o ID3D12InfoQueue associado ao ID3D12Device, passado durante a criação do dispositivo DirectML. As mensagens de erro na fila de informações são sempre prefixadas com D3D12 ERROR, como mostrado acima, e também podem ser acessadas programaticamente usando um retorno de chamada de mensagem da camada de depuração do Direct3D 12 (consulte a postagem do blog D3D12 debug layer message callback).

O ID3D12InfoQueue estará disponível somente quando a camada de depuração do Direct3D 12 estiver habilitada com ID3D12Debug::EnableDebugLayer. Embora seja sempre melhor habilitar (ou desabilitar) as camadas de depuração do Direct3D 12 e do DirectML juntas, as versões mais recentes do DirectML oferecem suporte à validação de parâmetros básicos sem a camada de depuração do Direct3D 12. Se você criar um dispositivo DirectML com DML_CREATE_DEVICE_FLAG_DEBUG enquanto a camada de depuração do Direct3D 12 não tiver sido habilitada, as mensagens de erro serão impressas usando OutputDebugStringA:

[DIRECTML WARNING]: enable the D3D debug layer for enhanced validation with DML_CREATE_DEVICE_FLAG_DEBUG.

[DIRECTML ERROR]: Mismatched tensor data types. Tensor 'Output' has DataType of DML_TENSOR_DATA_TYPE_FLOAT16, while tensor 'Input' has DataType of DML_TENSOR_DATA_TYPE_FLOAT32. Both tensors are expected to have the same DataType.

TensorValidator.h(218)\DirectML.Debug.dll!00007FF820C43AFB: (caller: 00007FF820C01CD1) Exception(1) tid(5df8) 80070057 The parameter is incorrect.

Como a mensagem de aviso sugere, é melhor habilitar a camada de depuração do Direct3D 12 quando também a estiver usando. Alguns tipos de validação só são possíveis quando ambas as camadas de depuração estão habilitadas.

Como instalar as camadas de depuração do DirectML e Direct3D 12 (componente do sistema)

Ao usar o DirectML como um componente do sistema (consulte Histórico de versões do DirectML), a camada de depuração faz parte de um pacote separado de Ferramentas Gráficas, distribuído como um FOD (recurso sob demanda) (consulte Recursos sob demanda). O FOD de Ferramentas Gráficas deve ser adicionado ao seu sistema para usar a camada de depuração com a versão de sistema do DirectML. O FOD também contém a camada de depuração do Direct3D 12, que também é útil (mas não necessária) para depurar aplicativos DirectML.

Para adicionar o pacote FOD das Ferramentas Gráficas opcionais, execute o seguinte comando em um prompt do administrador do Powershell.

Add-WindowsCapability -Online -Name "Tools.Graphics.DirectX~~~~0.0.1.0"

Como alternativa, você pode adicionar o pacote de Ferramentas Gráficas nas Configurações do Windows. No Windows 10 22H2 e no Windows 11, navegue até Configurações>Sistema>Recursos opcionais>Adicione um recurso opcional e procure por Ferramentas Gráficas. Em versões anteriores ao Windows 10 22H2, navegue até Configurações>Aplicativos>Aplicativos e recursos>Recursos opcionais>Adicione um recurso opcional.

Como instalat a camada de depuração DirectML (redistribuível autônoma)

Ao usar o DirectML como uma biblioteca redistribuível autônoma (confira Microsoft.AI.DirectML), a camada de depuração do DirectML é fornecida no pacote junto com a biblioteca de runtime principal. Coloque DirectML.Debug.dll e DirectML.dll ao lado do executável do seu aplicativo.

Se você usar o Visual Studio para adicionar Microsoft.AI.DirectML como uma dependência de pacote NuGet, o projeto mostrará opções na página de configurações do projeto para copiar ou ignorar a cópia do runtime principal e das bibliotecas da camada de depuração. Por padrão, o pacote NuGet do DirectML é configurado para copiar sempre ambas as DLLs na pasta de saída do projeto. No entanto, convém ignorar a cópia da camada de depuração nas compilações de versão se a camada de depuração não for usada.

Redistributable Debug Layer in Visual Studio

Habilitar a camada de depuração do Direct3D 12

A camada de depuração do Direct3D 12 (d3d12sdklayers.dll) é independente da camada de depuração do DirectML (DirectML.Debug.dll): essa fornece validação aprimorada para o uso da API do DirectML e a camada de depuração do Direct3D 12 abrange o uso da API do Direct3D 12. Na prática, no entanto, é melhor habilitar ambas as camadas de depuração ao desenvolver aplicativos DirectML. A camada de depuração do Direct3D 12 é instalada como parte do FOD das Ferramentas Gráficas, o que é explicado acima. Consulte ID3D12Debug::EnableDebugLayer para obter um exemplo de como ativar a camada de depuração do Direct3D 12.

Importante

Você deve primeiro habilitar a camada de depuração do Direct3D 12. E, em seguida, habilite a camada de depuração do DirectML chamando o DMLCreateDevice.

Habilitar a camada de depuração do Direct3D

Você pode habilitar a camada de depuração do DirectML fornecendo o DML_CREATE_DEVICE_FLAG_DEBUG ao chamar DMLCreateDevice.

Após habilitar a camada de depuração do DirectML, todos os erros do DirectML ou as chamadas de API inválidas emitirão as informações de depuração como saída de depuração. Veja um exemplo.

DML_OPERATOR_CONVOLUTION: invalid D3D12_HEAP_TYPE. DirectML requires all bound buffers to be D3D12_HEAP_TYPE_DEFAULT.

Até DML_FEATURE_LEVEL_5_2, é um requisito habilitar a camada de depuração do Direct3D 12 para habilitar a camada de depuração do DirectML. Em versões anteriores do DirectML, se o sinalizador DML_CREATE_DEVICE_FLAG_DEBUG for especificado em sinalizadores e as camadas de depuração não estiverem instaladas, o DMLCreateDevice retornará o erro DXGI_ERROR_SDK_COMPONENT_MISSING. Em versões mais recentes do DirectML, as mensagens serão enviadas para OutputDebugStringA quando ID3D12InfoQueue não estiver disponível.

Exemplo de código

O código a seguir ilustra a habilitação das camadas de depuração Direct3D 12 e DirectML somente para as compilações de depuração.

// By default, disable the DirectML debug layer.
DML_CREATE_DEVICE_FLAGS dmlCreateDeviceFlags = DML_CREATE_DEVICE_FLAG_NONE;

#if defined(_DEBUG)
// If the project is in a debug build, then enable the Direct3D 12 debug layer.
// This is optional (starting in DML_FEATURE_LEVEL_5_2) but strongly recommended!
Microsoft::WRL::ComPtr<ID3D12Debug> debugController;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController))))
{
    debugController->EnableDebugLayer();
}

// If the project is in a debug build, then enable debugging via DirectML debug layers with this flag.
dmlCreateDeviceFlags |= DML_CREATE_DEVICE_FLAG_DEBUG;
#endif

// Create the DirectML device.
Microsoft::WRL::ComPtr<IDMLDevice> dmlDevice;
THROW_IF_FAILED(DMLCreateDevice(
    d3D12Device.Get(),
    dmlCreateDeviceFlags,
    IID_PPV_ARGS(&dmlDevice));

Confira também