diff --git a/.github/workflows/win-directml-x64-build.yml b/.github/workflows/win-directml-x64-build.yml index be8a61d857..850ba24c3a 100644 --- a/.github/workflows/win-directml-x64-build.yml +++ b/.github/workflows/win-directml-x64-build.yml @@ -21,6 +21,9 @@ env: dml_dir: "Microsoft.AI.DirectML.1.14.2" dml_zip: "Microsoft.AI.DirectML.1.14.2.zip" dml_url: "https://www.nuget.org/api/v2/package/Microsoft.AI.DirectML/1.14.2" + d3d12_dir: "Microsoft.Direct3D.D3D12.1.614.0" + d3d12_zip: "Microsoft.Direct3D.D3D12.1.614.0.zip" + d3d12_url: "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/1.614.0" binaryDir: 'build/directml' @@ -46,6 +49,10 @@ jobs: run: | Invoke-WebRequest -Uri $env:dml_url -OutFile $env:dml_zip + - name: Download the D3D12 Agility SDK + run: | + Invoke-WebRequest -Uri $env:d3d12_url -OutFile $env:d3d12_zip + - name: Unzip OnnxRuntime run: | Expand-Archive $env:ort_zip -DestinationPath $env:ort_dir @@ -56,6 +63,11 @@ jobs: Expand-Archive $env:dml_zip -DestinationPath $env:dml_dir Remove-Item -Path $env:dml_zip + - name: Unzip the D3D12 Agility SDK + run: | + Expand-Archive $env:d3d12_zip -DestinationPath $env:d3d12_dir + Remove-Item -Path $env:d3d12_zip + - name: Move the files to the ort directory run: | mkdir ort/lib @@ -63,6 +75,7 @@ jobs: mv $env:ort_dir\runtimes\win-x64\native\onnxruntime.dll ort\lib mv $env:ort_dir\runtimes\win-x64\native\onnxruntime.lib ort\lib mv $env:dml_dir\bin\x64-win\DirectML.dll ort\lib + mv $env:d3d12_dir\build\native\bin\x64\D3D12Core.dll ort\lib mv $env:ort_dir\build\native\include\dml_provider_factory.h ort\include mv $env:ort_dir\build\native\include\onnxruntime_c_api.h ort\include mv $env:dml_dir\include\DirectML.h ort\include diff --git a/.pipelines/stages/jobs/nuget-packaging-job.yml b/.pipelines/stages/jobs/nuget-packaging-job.yml index cdb5ec99fc..ada915890b 100644 --- a/.pipelines/stages/jobs/nuget-packaging-job.yml +++ b/.pipelines/stages/jobs/nuget-packaging-job.yml @@ -106,6 +106,13 @@ jobs: - name: ort_arm64_url value: "https://github.com/microsoft/onnxruntime/releases/download/v1.17.3/onnxruntime-win-arm64-1.17.3.zip" + - name: d3d12_dir + value: 'Microsoft.Direct3D.D3D12.1.614.0' + - name: d3d12_zip + value: 'Microsoft.Direct3D.D3D12.1.614.0.zip' + - name: d3d12_url + value: "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/1.614.0" + workspace: clean: all steps: diff --git a/.pipelines/stages/jobs/py-packaging-job.yml b/.pipelines/stages/jobs/py-packaging-job.yml index 213d72543a..1038354729 100644 --- a/.pipelines/stages/jobs/py-packaging-job.yml +++ b/.pipelines/stages/jobs/py-packaging-job.yml @@ -120,6 +120,13 @@ jobs: - name: ort_arm64_url value: "https://github.com/microsoft/onnxruntime/releases/download/v1.17.3/onnxruntime-win-arm64-1.17.3.zip" + - name: d3d12_dir + value: 'Microsoft.Direct3D.D3D12.1.614.0' + - name: d3d12_zip + value: 'Microsoft.Direct3D.D3D12.1.614.0.zip' + - name: d3d12_url + value: "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/1.614.0" + steps: - script: | MKDIR $(Agent.ToolsDirectory)\Python\3.12.3\arm64 diff --git a/.pipelines/stages/jobs/steps/capi-win-step.yml b/.pipelines/stages/jobs/steps/capi-win-step.yml index 8b248da21e..a8b7f62c91 100644 --- a/.pipelines/stages/jobs/steps/capi-win-step.yml +++ b/.pipelines/stages/jobs/steps/capi-win-step.yml @@ -54,6 +54,12 @@ steps: Get-ChildItem -Recurse $(dml_dir) mv $(dml_dir)\bin\x64-win\DirectML.dll ort\lib mv $(dml_dir)\include\DirectML.h ort\include + + Invoke-WebRequest -Uri $(d3d12_url) -OutFile $(d3d12_zip) + Expand-Archive $(d3d12_zip) -DestinationPath $(d3d12_dir) + Remove-Item -Path $(d3d12_zip) + Get-ChildItem -Recurse $(d3d12_dir) + mv $(d3d12_dir)\build\native\bin\x64\D3D12Core.dll ort\lib workingDirectory: '$(Build.Repository.LocalPath)' continueOnError: true diff --git a/CMakeLists.txt b/CMakeLists.txt index 3db217b243..33a21e7221 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,6 +87,7 @@ endif() if(USE_DML) list(APPEND onnxruntime_libs "${ORT_LIB_DIR}/DirectML.dll") + list(APPEND onnxruntime_libs "${ORT_LIB_DIR}/D3D12Core.dll") target_include_directories(onnxruntime-genai PRIVATE $) target_include_directories(onnxruntime-genai PRIVATE $/directx) target_include_directories(onnxruntime-genai PRIVATE $) diff --git a/src/dml/dml_helpers.cpp b/src/dml/dml_helpers.cpp index 963fcecc5b..430dc92ae0 100644 --- a/src/dml/dml_helpers.cpp +++ b/src/dml/dml_helpers.cpp @@ -80,7 +80,7 @@ static ComPtr CreatePerformantAdapter() { return filtered_adapters.front(); } -DmlObjects CreateDmlObjects() { +DmlObjects CreateDmlObjects(const std::string& current_module_path) { D3D12_COMMAND_QUEUE_DESC command_queue_description = { D3D12_COMMAND_LIST_TYPE_COMPUTE, 0, @@ -91,7 +91,21 @@ DmlObjects CreateDmlObjects() { DmlObjects dml_objects; auto adapter = CreatePerformantAdapter(); - THROW_IF_FAILED(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&dml_objects.d3d12_device))); + + ComPtr d3d12_sdk_config; + ComPtr d3d12_factory; + + // Get the version from https://devblogs.microsoft.com/directx/directx12agility/. We are currently using 1.614.0. + constexpr uint32_t agility_sdk_version = 614; + + if (SUCCEEDED(D3D12GetInterface(CLSID_D3D12SDKConfiguration, IID_PPV_ARGS(&d3d12_sdk_config))) && + SUCCEEDED(d3d12_sdk_config->CreateDeviceFactory(agility_sdk_version, current_module_path.c_str(), IID_PPV_ARGS(&d3d12_factory)))) { + THROW_IF_FAILED(d3d12_factory->CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&dml_objects.d3d12_device))); + } else { + printf("Warning: Unable to create a device from version 1.614.0 of the DirectX 12 Agility SDK. You can still use this library, but some scenarios may not work.\n"); + THROW_IF_FAILED(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&dml_objects.d3d12_device))); + } + THROW_IF_FAILED(dml_objects.d3d12_device->CreateCommandQueue(&command_queue_description, IID_PPV_ARGS(&dml_objects.command_queue))); THROW_IF_FAILED(dml_objects.d3d12_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&dml_objects.command_allocator))); THROW_IF_FAILED(dml_objects.d3d12_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, dml_objects.command_allocator.Get(), nullptr, IID_PPV_ARGS(&dml_objects.command_list))); diff --git a/src/dml/dml_helpers.h b/src/dml/dml_helpers.h index b3c5877f3d..2f530a0e48 100644 --- a/src/dml/dml_helpers.h +++ b/src/dml/dml_helpers.h @@ -31,7 +31,7 @@ struct DmlObjects { }; namespace DmlHelpers { -DmlObjects CreateDmlObjects(); +DmlObjects CreateDmlObjects(const std::string& current_module_path); DmlReusedCommandListState BuildReusableCommandList( IDMLDevice* dml_device, diff --git a/src/models/model.cpp b/src/models/model.cpp index 9ecdfc4375..7e87982ebf 100644 --- a/src/models/model.cpp +++ b/src/models/model.cpp @@ -18,16 +18,16 @@ EXTERN_C IMAGE_DOS_HEADER __ImageBase; -static std::wstring CurrentModulePath() { - wchar_t path[MAX_PATH]; - GetModuleFileNameW((HINSTANCE)&__ImageBase, path, _countof(path)); +static std::string CurrentModulePath() { + char path[MAX_PATH]; + GetModuleFileNameA((HINSTANCE)&__ImageBase, path, _countof(path)); - wchar_t absolute_path[MAX_PATH]; - wchar_t* name; - GetFullPathNameW(path, _countof(path), absolute_path, &name); + char absolute_path[MAX_PATH]; + char* name; + GetFullPathNameA(path, _countof(path), absolute_path, &name); auto idx = std::distance(absolute_path, name); - auto out_path = std::wstring(absolute_path); + auto out_path = std::string(absolute_path); out_path.resize(idx); return out_path; @@ -345,13 +345,14 @@ void Model::CreateSessionOptions() { ort_options.AppendExecutionProvider_ROCM(ort_provider_options); #if USE_DML } else if (provider_options.name == "dml") { - dml_objects_ = DmlHelpers::CreateDmlObjects(); + auto current_module_path = CurrentModulePath(); + dml_objects_ = DmlHelpers::CreateDmlObjects(current_module_path); - auto directml_dll = CurrentModulePath() + L"DirectML.dll"; - wil::unique_hmodule smart_directml_dll(LoadLibraryExW(directml_dll.c_str(), nullptr, 0)); + auto directml_dll = current_module_path + "DirectML.dll"; + wil::unique_hmodule smart_directml_dll(LoadLibraryEx(directml_dll.c_str(), nullptr, 0)); THROW_LAST_ERROR_IF(!smart_directml_dll); - if (LoadLibraryExW(directml_dll.c_str(), nullptr, 0) == NULL) { + if (LoadLibraryEx(directml_dll.c_str(), nullptr, 0) == NULL) { throw std::runtime_error("DirectML.dll not found"); }