Enable building with a GDK (#11126)

This commit is contained in:
Justin Stoecker 2022-04-07 15:06:31 -07:00 committed by GitHub
parent 4983d6e5d6
commit 7609694464
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 325 additions and 39 deletions

View file

@ -1908,7 +1908,8 @@ else()
list(APPEND onnxruntime_EXTERNAL_LIBRARIES ${CMAKE_DL_LIBS} Threads::Threads)
endif()
if (WIN32)
# When GDK_PLATFORM is set then WINAPI_FAMILY is defined in gdk_toolchain.cmake (along with other relevant flags/definitions).
if (WIN32 AND NOT GDK_PLATFORM)
add_compile_definitions(WINAPI_FAMILY=100) # Desktop app
if (onnxruntime_USE_WINML)
add_compile_definitions(WINVER=0x0602 _WIN32_WINNT=0x0602 NTDDI_VERSION=0x06020000) # Support Windows 8 and newer

View file

@ -24,6 +24,12 @@ FetchContent_Declare(
FetchContent_MakeAvailable(abseil_cpp)
FetchContent_GetProperties(abseil_cpp SOURCE_DIR)
if (GDK_PLATFORM)
# Abseil considers any partition that is NOT in the WINAPI_PARTITION_APP a viable platform
# for Win32 symbolize code (which depends on dbghelp.lib); this logic should really be flipped
# to only include partitions that are known to support it (e.g. DESKTOP). As a workaround we
# tell Abseil to pretend we're building an APP.
target_compile_definitions(absl_symbolize PRIVATE WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP)
endif()

91
cmake/gdk_toolchain.cmake Normal file
View file

@ -0,0 +1,91 @@
# Options to configure the toolchain.
set(GDK_EDITION 210602 CACHE STRING "GDK edition.")
set(GDK_PLATFORM Scarlett CACHE STRING "GDK target platform.")
# Required to propagate variables when CMake calls try_compile() to test the toolchain.
# https://cmake.org/cmake/help/latest/variable/CMAKE_TRY_COMPILE_PLATFORM_VARIABLES.html
set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES GDK_EDITION GDK_PLATFORM)
cmake_path(SET gdk_gxdk_path $ENV{GameDK}/${GDK_EDITION}/GXDK NORMALIZE)
# Set C/C++ compile flags and additional include directories.
foreach(lang C CXX)
set(CMAKE_${lang}_FLAGS_INIT "")
string(APPEND CMAKE_${lang}_FLAGS_INIT
" /D_GAMING_XBOX"
" /DWINAPI_FAMILY=WINAPI_FAMILY_GAMES"
" /D_ATL_NO_DEFAULT_LIBS"
" /D__WRL_NO_DEFAULT_LIB__"
" /D__WRL_CLASSIC_COM_STRICT__"
" /D_CRT_USE_WINAPI_PARTITION_APP"
" /DWIN32_LEAN_AND_MEAN"
" /favor:AMD64"
)
if(GDK_PLATFORM STREQUAL Scarlett)
string(APPEND CMAKE_${lang}_FLAGS_INIT " /D_GAMING_XBOX_SCARLETT /arch:AVX2")
elseif(GDK_PLATFORM STREQUAL XboxOne)
string(APPEND CMAKE_${lang}_FLAGS_INIT " /D_GAMING_XBOX_XBOXONE /arch:AVX")
endif()
set(CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES ${gdk_gxdk_path}/gameKit/Include/${GDK_PLATFORM})
set(CMAKE_${lang}_STANDARD_LIBRARIES "onecoreuap_apiset.lib" CACHE STRING "" FORCE)
endforeach()
# It's best to avoid inadvertently linking with any libraries not present in the OS.
list(APPEND nodefault_libs
advapi32.lib
comctl32.lib
comsupp.lib
dbghelp.lib
gdi32.lib
gdiplus.lib
guardcfw.lib
kernel32.lib
mmc.lib
msimg32.lib
msvcole.lib
msvcoled.lib
mswsock.lib
ntstrsafe.lib
ole2.lib
ole2autd.lib
ole2auto.lib
ole2d.lib
ole2ui.lib
ole2uid.lib
ole32.lib
oleacc.lib
oleaut32.lib
oledlg.lib
oledlgd.lib
oldnames.lib
runtimeobject.lib
shell32.lib
shlwapi.lib
strsafe.lib
urlmon.lib
user32.lib
userenv.lib
wlmole.lib
wlmoled.lib
onecore.lib
)
foreach(link_type EXE SHARED MODULE)
set(CMAKE_${link_type}_LINKER_FLAGS_INIT "")
foreach(lib ${nodefault_libs})
string(APPEND CMAKE_${link_type}_LINKER_FLAGS_INIT " /NODEFAULTLIB:${lib}")
endforeach()
string(APPEND CMAKE_${link_type}_LINKER_FLAGS_INIT " /DYNAMICBASE /NXCOMPAT /MANIFEST:NO")
endforeach()
set(gdk_dx_libs ${gdk_gxdk_path}/gameKit/lib/amd64/PIXEvt.lib)
if(GDK_PLATFORM STREQUAL Scarlett)
list(APPEND gdk_dx_libs ${gdk_gxdk_path}/gameKit/lib/amd64/Scarlett/d3d12_xs.lib)
list(APPEND gdk_dx_libs ${gdk_gxdk_path}/gameKit/lib/amd64/Scarlett/xg_xs.lib)
elseif(GDK_PLATFORM STREQUAL XboxOne)
list(APPEND gdk_dx_libs ${gdk_gxdk_path}/gameKit/lib/amd64/XboxOne/d3d12_x.lib)
list(APPEND gdk_dx_libs ${gdk_gxdk_path}/gameKit/lib/amd64/XboxOne/xg_x.lib)
endif()

View file

@ -28,3 +28,17 @@ if (NOT onnxruntime_BUILD_SHARED_LIB)
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
FRAMEWORK DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
if (GDK_PLATFORM)
# cstdlib only defines std::getenv when _CRT_USE_WINAPI_FAMILY_DESKTOP_APP is defined, which
# is probably an oversight for GDK/Xbox builds (::getenv exists and works).
file(WRITE ${CMAKE_BINARY_DIR}/gdk_cstdlib_wrapper.h [[
#pragma once
#ifdef __cplusplus
#include <cstdlib>
namespace std { using ::getenv; }
#endif
]])
target_compile_options(flatbuffers PRIVATE /FI${CMAKE_BINARY_DIR}/gdk_cstdlib_wrapper.h)
target_compile_options(flatc PRIVATE /FI${CMAKE_BINARY_DIR}/gdk_cstdlib_wrapper.h)
endif()

View file

@ -1070,7 +1070,11 @@ if (onnxruntime_USE_DML)
function(target_add_dml target)
if (onnxruntime_USE_CUSTOM_DIRECTML)
target_link_libraries(${target} PRIVATE DirectML)
if (dml_LIB_DIR)
target_link_libraries(${target} PRIVATE ${dml_LIB_DIR}/DirectML.lib)
else()
target_link_libraries(${target} PRIVATE DirectML)
endif()
else()
add_dependencies(${target} RESTORE_PACKAGES)
target_link_libraries(${target} PRIVATE "${DML_PACKAGE_DIR}/bin/${onnxruntime_target_platform}-win/DirectML.lib")
@ -1079,11 +1083,17 @@ if (onnxruntime_USE_DML)
endfunction()
target_add_dml(onnxruntime_providers_dml)
target_link_libraries(onnxruntime_providers_dml PRIVATE d3d12.lib dxgi.lib)
if (GDK_PLATFORM STREQUAL Scarlett)
target_link_libraries(onnxruntime_providers_dml PRIVATE ${gdk_dx_libs})
else()
target_link_libraries(onnxruntime_providers_dml PRIVATE d3d12.lib dxgi.lib)
endif()
target_link_libraries(onnxruntime_providers_dml PRIVATE delayimp.lib)
set(onnxruntime_DELAYLOAD_FLAGS "${onnxruntime_DELAYLOAD_FLAGS} /DELAYLOAD:DirectML.dll /DELAYLOAD:d3d12.dll /DELAYLOAD:dxgi.dll /DELAYLOAD:api-ms-win-core-com-l1-1-0.dll /DELAYLOAD:shlwapi.dll /DELAYLOAD:oleaut32.dll /ignore:4199")
if (NOT GDK_PLATFORM)
set(onnxruntime_DELAYLOAD_FLAGS "${onnxruntime_DELAYLOAD_FLAGS} /DELAYLOAD:DirectML.dll /DELAYLOAD:d3d12.dll /DELAYLOAD:dxgi.dll /DELAYLOAD:api-ms-win-core-com-l1-1-0.dll /DELAYLOAD:shlwapi.dll /DELAYLOAD:oleaut32.dll /ignore:4199")
endif()
target_compile_definitions(onnxruntime_providers_dml
PRIVATE

View file

@ -5,7 +5,13 @@
#pragma warning(push)
#pragma warning(disable : 4201) // nonstandard extension used: nameless struct/union
#ifdef _GAMING_XBOX_SCARLETT
#include <d3d12_xs.h>
#elif defined(_GAMING_XBOX_XBOXONE)
#include <d3d12_x.h>
#else
#include <d3d12.h>
#endif
#pragma warning(pop)
#ifdef __cplusplus

View file

@ -13,7 +13,16 @@
#include "core/common/common.h"
#ifdef _WIN32
#if defined(USE_PATHCCH_LIB)
#if _GAMING_XBOX
// Hacky, but the PathCch* APIs work on Xbox. Presumably PathCch.h needs to be updated to include the
// GAMES partition. It would be worthwhile to investigate this a bit more (or just use std::filesystem).
#pragma push_macro("WINAPI_FAMILY")
#undef WINAPI_FAMILY
#define WINAPI_FAMILY WINAPI_FAMILY_DESKTOP_APP
#include <PathCch.h>
#pragma pop_macro("WINAPI_FAMILY")
#pragma comment(lib, "PathCch.lib")
#elif defined(USE_PATHCCH_LIB)
#include <PathCch.h>
#pragma comment(lib, "PathCch.lib")
// Desktop apps need to support back to Windows 7, so we can't use PathCch.lib as it was added in Windows 8
@ -38,7 +47,7 @@ namespace {
Status RemoveFileSpec(PWSTR pszPath, size_t cchPath) {
assert(pszPath != nullptr && pszPath[0] != L'\0');
#if WINVER < _WIN32_WINNT_WIN8 && !defined(USE_PATHCCH_LIB)
#if WINVER < _WIN32_WINNT_WIN8 && !defined(USE_PATHCCH_LIB) && !defined(_GAMING_XBOX)
(void)cchPath;
for (PCWSTR t = L"\0"; *t == L'\0'; t = PathRemoveBackslashW(pszPath))
;

View file

@ -33,7 +33,7 @@ class CaptureStackTrace {
std::vector<std::string> GetStackTrace() {
#ifndef NDEBUG
// TVM need to run with shared CRT, so won't work with debug helper now
#if !(defined USE_NUPHAR_TVM) && !(defined _OPSCHEMA_LIB_)
#if !(defined USE_NUPHAR_TVM) && !(defined _OPSCHEMA_LIB_) && !(defined _GAMING_XBOX)
return detail::CaptureStackTrace().Trace();
#else
return {};
@ -45,7 +45,7 @@ std::vector<std::string> GetStackTrace() {
namespace detail {
#ifndef NDEBUG
#if !(defined USE_NUPHAR_TVM) && !(defined _OPSCHEMA_LIB_)
#if !(defined USE_NUPHAR_TVM) && !(defined _OPSCHEMA_LIB_) && !(defined _GAMING_XBOX)
class SymbolHelper {
public:
SymbolHelper() noexcept {

View file

@ -14,7 +14,7 @@
#include <cstdint>
#include <winapifamily.h>
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES)
static_assert(sizeof(bool) == 1, "Unsupported size for bool type");

View file

@ -118,7 +118,7 @@ namespace Dml
&buffer,
m_initialState,
nullptr,
IID_PPV_ARGS(&resource)
IID_GRAPHICS_PPV_ARGS(resource.ReleaseAndGetAddressOf())
));
resourceId = ++m_currentResourceId;
@ -143,7 +143,7 @@ namespace Dml
&buffer,
m_initialState,
nullptr,
IID_PPV_ARGS(&resource)
IID_GRAPHICS_PPV_ARGS(resource.ReleaseAndGetAddressOf())
));
resourceId = ++m_currentResourceId;
@ -203,7 +203,11 @@ namespace Dml
else
{
// Free the underlying allocation once queued work has completed.
#ifdef _GAMING_XBOX
m_context->QueueReference(WRAP_GRAPHICS_UNKNOWN(allocInfo->GetResource()).Get());
#else
m_context->QueueReference(allocInfo->GetResource());
#endif
allocInfo->DetachResource();
}

View file

@ -22,7 +22,7 @@ namespace Dml
{
ORT_THROW_IF_FAILED(device->CreateCommandAllocator(
commandListType,
IID_PPV_ARGS(&info.allocator)));
IID_GRAPHICS_PPV_ARGS(info.allocator.ReleaseAndGetAddressOf())));
info.completionEvent = initialEvent;
}

View file

@ -11,9 +11,8 @@ namespace Dml
, m_type(existingQueue->GetDesc().Type)
{
ComPtr<ID3D12Device> device;
ORT_THROW_IF_FAILED(m_queue->GetDevice(IID_PPV_ARGS(&device)));
ORT_THROW_IF_FAILED(device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence)));
GRAPHICS_THROW_IF_FAILED(m_queue->GetDevice(IID_GRAPHICS_PPV_ARGS(device.GetAddressOf())));
ORT_THROW_IF_FAILED(device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(m_fence.ReleaseAndGetAddressOf())));
}
void CommandQueue::ExecuteCommandList(ID3D12CommandList* commandList)

View file

@ -33,6 +33,17 @@ namespace Dml
GpuEvent GetNextCompletionEvent();
void QueueReference(IUnknown* object, bool waitForUnsubmittedWork);
#ifdef _GAMING_XBOX
void QueueReference(IGraphicsUnknown* object, bool waitForUnsubmittedWork)
{
// TODO(justoeck): consider changing QueuedReference to hold a variant of
// ComPtr<IUnknown>, ComPtr<IGraphicsUnknown>.
auto wrapper = Microsoft::WRL::Make<GraphicsUnknownWrapper>(object);
QueueReference(wrapper.Get(), waitForUnsubmittedWork);
}
#endif
void Close();
void ReleaseCompletedReferences();

View file

@ -13,8 +13,7 @@ namespace Dml
m_heapFlags(heap->GetDesc().Flags)
{
ComPtr<ID3D12Device> device;
ORT_THROW_IF_FAILED(heap->GetDevice(IID_PPV_ARGS(&device)));
GRAPHICS_THROW_IF_FAILED(heap->GetDevice(IID_GRAPHICS_PPV_ARGS(device.GetAddressOf())));
m_handleIncrementSize = device->GetDescriptorHandleIncrementSize(heap->GetDesc().Type);
}
@ -109,7 +108,7 @@ namespace Dml
desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
ComPtr<ID3D12DescriptorHeap> heap;
ORT_THROW_IF_FAILED(m_device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&heap)));
ORT_THROW_IF_FAILED(m_device->CreateDescriptorHeap(&desc, IID_GRAPHICS_PPV_ARGS(heap.GetAddressOf())));
m_heaps.push_back(DescriptorHeap{heap.Get()});
}

View file

@ -323,7 +323,7 @@ void DmlCommandRecorder::Open()
m_queue->GetType(),
m_commandAllocatorRing.GetCurrentAllocator(),
nullptr,
IID_PPV_ARGS(&m_currentCommandList)));
IID_GRAPHICS_PPV_ARGS(m_currentCommandList.ReleaseAndGetAddressOf())));
}
else
{

View file

@ -15,7 +15,7 @@ namespace Dml
: m_queue(std::make_shared<CommandQueue>(queue))
, m_dmlRecorder(d3d12Device, dmlDevice, m_queue)
{
ORT_THROW_IF_FAILED(dmlDevice->GetParentDevice(IID_PPV_ARGS(m_d3dDevice.GetAddressOf())));
ORT_THROW_IF_FAILED(dmlDevice->GetParentDevice(IID_GRAPHICS_PPV_ARGS(m_d3dDevice.GetAddressOf())));
}
void ExecutionContext::SetAllocator(std::weak_ptr<BucketizedBufferAllocator> allocator)
@ -178,7 +178,7 @@ namespace Dml
bool waitForUnsubmittedWork = (m_currentRecorder != nullptr);
m_queue->QueueReference(object, waitForUnsubmittedWork);
}
void ExecutionContext::Close()
{
assert(!m_closed);

View file

@ -25,7 +25,9 @@
#include "core/session/onnxruntime_c_api.h"
#include <wil/wrl.h>
#ifndef _GAMING_XBOX
#include <dxgi1_6.h>
#endif
#define ENABLE_GRAPH_COMPILATION
@ -71,7 +73,7 @@ namespace Dml
}
ComPtr<ID3D12Device> device;
ORT_THROW_IF_FAILED(commandQueue->GetDevice(IID_PPV_ARGS(&device)));
GRAPHICS_THROW_IF_FAILED(commandQueue->GetDevice(IID_GRAPHICS_PPV_ARGS(device.GetAddressOf())));
m_impl = wil::MakeOrThrow<ExecutionProviderImpl>(dmlDevice, device.Get(), commandQueue, enableMetacommands);
@ -668,8 +670,13 @@ namespace Dml
}
else
{
#ifdef _GAMING_XBOX
ComPtr<GraphicsUnknownWrapper> wrappedResource = Microsoft::WRL::Make<GraphicsUnknownWrapper>(m_allocator->DecodeDataHandle(data)->GetResource());
*abiData = wrappedResource.Detach();
#else
ComPtr<ID3D12Resource> resource = m_allocator->DecodeDataHandle(data)->GetResource();
*abiData = resource.Detach();
#endif
}
}
@ -696,7 +703,12 @@ namespace Dml
{
ComPtr<ID3D12GraphicsCommandList> commandList;
m_context->GetCommandListForRecording(commandList.GetAddressOf());
#ifdef _GAMING_XBOX
ComPtr<GraphicsUnknownWrapper> wrappedCommandList = Microsoft::WRL::Make<GraphicsUnknownWrapper>(commandList.Get());
*abiExecutionObject = wrappedCommandList.Detach();
#else
*abiExecutionObject = commandList.Detach();
#endif
}
}

View file

@ -164,7 +164,7 @@ namespace Dml
std::for_each(
initializeResourceRefs.begin(),
initializeResourceRefs.end(),
[&](ComPtr<ID3D12Resource>& resource){ m_winmlProvider->QueueReference(resource.Get()); }
[&](ComPtr<ID3D12Resource>& resource){ m_winmlProvider->QueueReference(WRAP_GRAPHICS_UNKNOWN(resource).Get()); }
);
if (graphDesc.reuseCommandList)
@ -312,7 +312,7 @@ namespace Dml
ComPtr<ID3D12Device> d3dDevice;
ORT_THROW_IF_FAILED(m_provider->GetD3DDevice(d3dDevice.GetAddressOf()));
ORT_THROW_IF_FAILED(d3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_heap)));
ORT_THROW_IF_FAILED(d3dDevice->CreateDescriptorHeap(&desc, IID_GRAPHICS_PPV_ARGS(m_heap.ReleaseAndGetAddressOf())));
// Create a binding table for execution.
DML_BINDING_TABLE_DESC bindingTableDesc = {};
@ -326,7 +326,7 @@ namespace Dml
ComPtr<ID3D12CommandAllocator> allocator;
ORT_THROW_IF_FAILED(d3dDevice->CreateCommandAllocator(
m_provider->GetCommandListTypeForQueue(),
IID_PPV_ARGS(&allocator)));
IID_GRAPHICS_PPV_ARGS(allocator.ReleaseAndGetAddressOf())));
ComPtr<ID3D12CommandList> commandList;
ORT_THROW_IF_FAILED(d3dDevice->CreateCommandList(
@ -334,7 +334,7 @@ namespace Dml
m_provider->GetCommandListTypeForQueue(),
allocator.Get(),
nullptr,
IID_PPV_ARGS(&commandList)));
IID_GRAPHICS_PPV_ARGS(commandList.ReleaseAndGetAddressOf())));
ORT_THROW_IF_FAILED(commandList.As(&m_graphicsCommandList));
@ -473,8 +473,8 @@ namespace Dml
m_completionValue = completionValue;
// Queue references to objects which must be kept alive until resulting GPU work completes
m_winmlProvider->QueueReference(m_graphicsCommandList.Get());
m_winmlProvider->QueueReference(m_heap.Get());
m_winmlProvider->QueueReference(WRAP_GRAPHICS_UNKNOWN(m_graphicsCommandList).Get());
m_winmlProvider->QueueReference(WRAP_GRAPHICS_UNKNOWN(m_heap).Get());
m_winmlProvider->QueueReference(m_bindingTable.Get());
m_winmlProvider->QueueReference(m_persistentResourceAllocatorUnk.Get());
}

View file

@ -37,7 +37,7 @@ namespace GraphKernelHelper
&resourceDesc,
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
nullptr,
IID_PPV_ARGS(buffer.GetAddressOf())));
IID_GRAPHICS_PPV_ARGS(buffer.GetAddressOf())));
ORT_THROW_IF_FAILED(provider->UploadToResource(buffer.Get(), tensorPtr, tensorByteSize));
@ -75,7 +75,7 @@ namespace GraphKernelHelper
&resourceDesc,
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
nullptr,
IID_PPV_ARGS(buffer.GetAddressOf())));
IID_GRAPHICS_PPV_ARGS(buffer.GetAddressOf())));
// Map the buffer and copy the data
void* bufferData = nullptr;

View file

@ -11,7 +11,9 @@
#include "core/graph/indexed_sub_graph.h"
#include "core/framework/compute_capability.h"
#include <wil/wrl.h>
#ifndef _GAMING_XBOX
#include <dxgi1_6.h>
#endif
#include "GraphPartitioner.h"
//#define PRINT_PARTITON_INFO

View file

@ -0,0 +1,57 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
namespace Dml
{
// D3D12.x interfaces inherit from IGraphicsUnknown, which does not inherit from IUnknown. This
// wrapper exists to pass IGraphicsUnknown-inheriting objects to functions with IUnknown parameters.
#ifdef _GAMING_XBOX
class GraphicsUnknownWrapper : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IUnknown>
{
public:
explicit GraphicsUnknownWrapper(Microsoft::WRL::ComPtr<IGraphicsUnknown> graphicsUnknown) : m_graphicsUnknown(std::move(graphicsUnknown)) {}
explicit GraphicsUnknownWrapper(IGraphicsUnknown* graphicsUnknown) : m_graphicsUnknown(graphicsUnknown) {}
HRESULT __stdcall QueryInterface(const IID& iid, void** object) noexcept final
{
if (iid == __uuidof(IUnknown))
{
return RuntimeClass::QueryInterface(iid, object);
}
return m_graphicsUnknown->QueryInterface(iid, object);
}
private:
Microsoft::WRL::ComPtr<IGraphicsUnknown> m_graphicsUnknown;
};
#endif
// Convenience macro for functions that take an IUnknown* parameter and are typically
// called with a D3D-typed ComPtr argument. Example:
// m_winmlProvider->QueueReference(WRAP_GRAPHICS_UNKNOWN(resource).Get());
// The macro is a no-op for PC (arg is convertible to IUnknown), and it will wrap
// any IGraphicsUnknown for _GAMING_XBOX platforms.
#ifdef _GAMING_XBOX
#define WRAP_GRAPHICS_UNKNOWN(expr) Microsoft::WRL::Make<GraphicsUnknownWrapper>(expr)
#else
#define WRAP_GRAPHICS_UNKNOWN(expr) (expr)
#endif
// IID_GRAPHICS_PPV_ARGS is to IGraphicsUnknown as IID_PPV_ARGS is to IUnknown.
// There is no IGraphicsUnknown in stock D3D, so this is the same as IID_PPV_ARGS.
// This macro should be used anywhere an interface is represented in both D3D12.x and
// D3D12.
#ifndef _GAMING_XBOX
#define IID_GRAPHICS_PPV_ARGS IID_PPV_ARGS
#endif
// APIs like ID3D12DeviceChild::GetDevice return void in D3D12.x, but return HRESULT in D3D12.
#ifdef _GAMING_XBOX
#define GRAPHICS_THROW_IF_FAILED(hr) (hr)
#else
#define GRAPHICS_THROW_IF_FAILED(hr) ORT_THROW_IF_FAILED(hr)
#endif
} // namespace Dml

View file

@ -105,7 +105,7 @@ namespace Dml
&buffer,
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&uploadBuffer)));
IID_GRAPHICS_PPV_ARGS(uploadBuffer.ReleaseAndGetAddressOf())));
return Chunk{ sizeInBytes, std::move(uploadBuffer) };
}

View file

@ -19,7 +19,7 @@ namespace Dml
&buffer,
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
IID_PPV_ARGS(&readbackHeap)));
IID_GRAPHICS_PPV_ARGS(readbackHeap.ReleaseAndGetAddressOf())));
return readbackHeap;
}

View file

@ -26,9 +26,19 @@
#include <gsl/gsl>
#ifdef _GAMING_XBOX_SCARLETT
#include <d3d12_xs.h>
#include <d3dx12_xs.h>
#elif defined(_GAMING_XBOX_XBOXONE)
#include <d3d12_x.h>
#include <d3dx12_x.h>
#else // Desktop
#include <d3d12.h>
#include <d3d12sdklayers.h>
#include "External/D3DX12/d3dx12.h"
#endif
#include "GraphicsUnknownHelper.h"
#include <DirectML.h>
#include "core/common/common.h"

View file

@ -2,7 +2,9 @@
// Licensed under the MIT License.
#include <DirectML.h>
#ifndef _GAMING_XBOX
#include <dxgi1_4.h>
#endif
#include <wrl/client.h>
using Microsoft::WRL::ComPtr;
@ -16,6 +18,7 @@ using Microsoft::WRL::ComPtr;
#include "core/session/ort_apis.h"
#include "core/framework/error_code_helper.h"
#include "DmlExecutionProvider/src/ErrorHandling.h"
#include "DmlExecutionProvider/src/GraphicsUnknownHelper.h"
#include "DmlExecutionProvider/inc/DmlExecutionProvider.h"
#include "core/platform/env.h"
@ -55,6 +58,7 @@ void DMLProviderFactory::SetMetacommandsEnabled(bool metacommands_enabled) {
std::shared_ptr<IExecutionProviderFactory> CreateExecutionProviderFactory_DML(IDMLDevice* dml_device,
ID3D12CommandQueue* cmd_queue) {
#ifndef _GAMING_XBOX
// Validate that the D3D12 devices match between DML and the command queue. This specifically asks for IUnknown in
// order to be able to compare the pointers for COM object identity.
ComPtr<IUnknown> d3d12_device_0;
@ -65,9 +69,10 @@ std::shared_ptr<IExecutionProviderFactory> CreateExecutionProviderFactory_DML(ID
if (d3d12_device_0 != d3d12_device_1) {
ORT_THROW_HR(E_INVALIDARG);
}
#endif
ComPtr<ID3D12Device> d3d12_device;
ORT_THROW_IF_FAILED(dml_device->GetParentDevice(IID_PPV_ARGS(&d3d12_device)));
ORT_THROW_IF_FAILED(dml_device->GetParentDevice(IID_GRAPHICS_PPV_ARGS(d3d12_device.ReleaseAndGetAddressOf())));
const Env& env = Env::Default();
auto luid = d3d12_device->GetAdapterLuid();
env.GetTelemetryProvider().LogExecutionProviderEvent(&luid);
@ -99,8 +104,17 @@ bool IsSoftwareAdapter(IDXGIAdapter1* adapter) {
}
std::shared_ptr<IExecutionProviderFactory> CreateExecutionProviderFactory_DML(int device_id) {
#ifdef _GAMING_XBOX
ComPtr<ID3D12Device> d3d12_device;
D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {};
params.Version = D3D12_SDK_VERSION;
params.GraphicsCommandQueueRingSizeBytes = static_cast<UINT>(D3D12XBOX_DEFAULT_SIZE_BYTES);
params.GraphicsScratchMemorySizeBytes = static_cast<UINT>(D3D12XBOX_DEFAULT_SIZE_BYTES);
params.ComputeScratchMemorySizeBytes = static_cast<UINT>(D3D12XBOX_DEFAULT_SIZE_BYTES);
ORT_THROW_IF_FAILED(D3D12XboxCreateDevice(nullptr, &params, IID_GRAPHICS_PPV_ARGS(d3d12_device.ReleaseAndGetAddressOf())));
#else
ComPtr<IDXGIFactory4> dxgi_factory;
ORT_THROW_IF_FAILED(CreateDXGIFactory2(0, IID_PPV_ARGS(&dxgi_factory)));
ORT_THROW_IF_FAILED(CreateDXGIFactory2(0, IID_GRAPHICS_PPV_ARGS(dxgi_factory.ReleaseAndGetAddressOf())));
ComPtr<IDXGIAdapter1> adapter;
ORT_THROW_IF_FAILED(dxgi_factory->EnumAdapters1(device_id, &adapter));
@ -109,19 +123,20 @@ std::shared_ptr<IExecutionProviderFactory> CreateExecutionProviderFactory_DML(in
ORT_THROW_HR_IF(E_INVALIDARG, IsSoftwareAdapter(adapter.Get()));
ComPtr<ID3D12Device> d3d12_device;
ORT_THROW_IF_FAILED(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&d3d12_device)));
ORT_THROW_IF_FAILED(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_GRAPHICS_PPV_ARGS(d3d12_device.ReleaseAndGetAddressOf())));
#endif
D3D12_COMMAND_QUEUE_DESC cmd_queue_desc = {};
cmd_queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
cmd_queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_DISABLE_GPU_TIMEOUT;
ComPtr<ID3D12CommandQueue> cmd_queue;
ORT_THROW_IF_FAILED(d3d12_device->CreateCommandQueue(&cmd_queue_desc, IID_PPV_ARGS(&cmd_queue)));
ORT_THROW_IF_FAILED(d3d12_device->CreateCommandQueue(&cmd_queue_desc, IID_GRAPHICS_PPV_ARGS(cmd_queue.ReleaseAndGetAddressOf())));
DML_CREATE_DEVICE_FLAGS flags = DML_CREATE_DEVICE_FLAG_NONE;
// In debug builds, enable the DML debug layer if the D3D12 debug layer is also enabled
#if _DEBUG
#if _DEBUG && !_GAMING_XBOX
ComPtr<ID3D12DebugDevice> debug_device;
(void)d3d12_device->QueryInterface(IID_PPV_ARGS(&debug_device)); // ignore failure
const bool is_d3d12_debug_layer_enabled = (debug_device != nullptr);

View file

@ -322,6 +322,11 @@ def parse_arguments():
parser.add_argument("--android_run_emulator", action="store_true",
help="Start up an Android emulator if needed.")
parser.add_argument("--use_gdk", action='store_true', help="Build with the GDK toolchain.")
parser.add_argument("--gdk_edition", default=os.path.normpath(os.environ.get("GameDKLatest", "")).split(os.sep)[-1],
help="Build with a specific GDK edition. Defaults to the latest installed.")
parser.add_argument("--gdk_platform", default="Scarlett", help="Sets the GDK target platform.")
parser.add_argument("--ios", action='store_true', help="build for ios")
parser.add_argument(
"--ios_sysroot", default="",
@ -483,6 +488,9 @@ def parse_arguments():
help="Test with multi-device. Mostly used for multi-device GPU")
parser.add_argument(
"--use_dml", action='store_true', help="Build with DirectML.")
parser.add_argument(
"--dml_path", type=str, default="",
help="Path to a custom DirectML installation (must have bin/, lib/, and include/ subdirectories).")
parser.add_argument(
"--use_winml", action='store_true', help="Build with WinML.")
parser.add_argument(
@ -977,6 +985,23 @@ def generate_build_tree(cmake_path, source_dir, build_dir, cuda_home, cudnn_home
if args.android_cpp_shared:
cmake_args += ["-DANDROID_STL=c++_shared"]
if args.dml_path:
cmake_args += [
"-Donnxruntime_USE_CUSTOM_DIRECTML=ON",
"-Ddml_INCLUDE_DIR=" + os.path.join(args.dml_path, "include"),
"-Ddml_LIB_DIR=" + os.path.join(args.dml_path, "lib"),
]
if args.use_gdk:
cmake_args += [
"-DCMAKE_TOOLCHAIN_FILE=" + os.path.join(source_dir, 'cmake', 'gdk_toolchain.cmake'),
"-DGDK_EDITION=" + args.gdk_edition,
"-DGDK_PLATFORM=" + args.gdk_platform,
"-Donnxruntime_BUILD_UNIT_TESTS=OFF" # gtest doesn't build for GDK
]
if args.use_dml and not args.dml_path:
raise BuildError("You must set dml_path when building with the GDK.")
if is_macOS() and not args.android:
cmake_args += ["-DCMAKE_OSX_ARCHITECTURES=" + args.osx_arch]
if args.use_xcode:
@ -1165,6 +1190,7 @@ def generate_build_tree(cmake_path, source_dir, build_dir, cuda_home, cudnn_home
"-Donnxruntime_ENABLE_MEMLEAK_CHECKER=" +
("ON" if config.lower() == 'debug' and not (args.use_nuphar or args.use_tvm) and not
args.use_openvino and not
args.use_gdk and not
args.enable_msvc_static_runtime and not
args.disable_memleak_checker
else "OFF"), "-DCMAKE_BUILD_TYPE={}".format(config)],
@ -1297,7 +1323,17 @@ def setup_migraphx_vars(args):
def setup_dml_build(args, cmake_path, build_dir, configs):
if args.use_dml:
if not args.use_dml:
return
if args.dml_path:
for expected_file in ["bin/DirectML.dll", "lib/DirectML.lib", "include/DirectML.h"]:
file_path = os.path.join(args.dml_path, expected_file)
if not os.path.exists(file_path):
raise BuildError("dml_path is invalid.",
"dml_path='{}' expected_file='{}'."
.format(args.dml_path, file_path))
else:
for config in configs:
# Run the RESTORE_PACKAGES target to perform the initial
# NuGet setup.
@ -2145,6 +2181,10 @@ def main():
if args.use_openvino != "CPU_FP32" and args.build_nuget:
args.test = False
# GDK builds don't support testing
if args.use_gdk:
args.test = False
configs = set(args.config)
# setup paths and directories