Reintroduce experimental api changes and fix remote build break (#6385)
Co-authored-by: Ori Levari <orlevari@microsoft.com>
This commit is contained in:
Родитель
3c3d36334b
Коммит
6507b4f818
|
@ -106,21 +106,24 @@ target_cppwinrt(winml_api
|
|||
${target_folder} # the folder this target will be placed under
|
||||
"${winml_midl_defines}" # the midl compiler defines
|
||||
${winml_api_use_ns_prefix} # set ns_prefix
|
||||
"" # set additional cppwinrt ref path
|
||||
)
|
||||
add_dependencies(winml_api RESTORE_NUGET_PACKAGES)
|
||||
|
||||
# generate winml.experimental headers from idl
|
||||
target_cppwinrt(winml_api_experimental
|
||||
${winrt_experimental_idl} # winml winrt idl to compile
|
||||
${experimental_output_name} # outputs name
|
||||
${winml_lib_api_dir} # location for cppwinrt generated component sources
|
||||
${sdk_folder} # location of sdk folder
|
||||
${sdk_version} # sdk version
|
||||
${target_folder} # the folder this target will be placed under
|
||||
${winml_midl_defines} # the midl compiler defines
|
||||
${winml_api_use_ns_prefix} # set ns_prefix
|
||||
${winrt_experimental_idl} # winml winrt idl to compile
|
||||
${experimental_output_name} # outputs name
|
||||
${winml_lib_api_dir} # location for cppwinrt generated component sources
|
||||
${sdk_folder} # location of sdk folder
|
||||
${sdk_version} # sdk version
|
||||
${target_folder} # the folder this target will be placed under
|
||||
${winml_midl_defines} # the midl compiler defines
|
||||
${winml_api_use_ns_prefix} # set ns_prefix
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/Microsoft.AI.MachineLearning.winmd" # set additional cppwinrt ref path
|
||||
)
|
||||
add_dependencies(winml_api_experimental RESTORE_NUGET_PACKAGES)
|
||||
add_dependencies(winml_api_experimental winml_api)
|
||||
|
||||
target_midl(winml_api_native
|
||||
${idl_native} # winml native idl to compile
|
||||
|
@ -538,6 +541,10 @@ endif(onnxruntime_USE_DML)
|
|||
add_library(winml_lib_api_experimental STATIC
|
||||
${winml_lib_api_experimental_dir}/Dummy.cpp
|
||||
${winml_lib_api_experimental_dir}/Dummy.h
|
||||
${winml_lib_api_experimental_dir}/LearningModelSessionExperimental.cpp
|
||||
${winml_lib_api_experimental_dir}/LearningModelSessionExperimental.h
|
||||
${winml_lib_api_experimental_dir}/LearningModelSessionOptionsExperimental.cpp
|
||||
${winml_lib_api_experimental_dir}/LearningModelSessionOptionsExperimental.h
|
||||
)
|
||||
|
||||
# Compiler options
|
||||
|
@ -559,6 +566,7 @@ target_precompiled_header(winml_lib_api_experimental pch.h)
|
|||
# Includes
|
||||
target_include_directories(winml_lib_api_experimental PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/winml_api) # windows machine learning generated component headers
|
||||
target_include_directories(winml_lib_api_experimental PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/winml_api/comp_generated) # windows machine learning generated component headers
|
||||
target_include_directories(winml_lib_api_experimental PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/winml_api_experimental) # windows machine learning generated component headers
|
||||
target_include_directories(winml_lib_api_experimental PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/winml_api_experimental/comp_generated) # windows machine learning generated component headers
|
||||
target_include_directories(winml_lib_api_experimental PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/winml/sdk/cppwinrt/include) # sdk cppwinrt headers
|
||||
|
||||
|
@ -764,7 +772,9 @@ add_dependencies(winml_dll winml_api_native_internal)
|
|||
target_link_libraries(winml_dll PRIVATE re2)
|
||||
target_link_libraries(winml_dll PRIVATE wil)
|
||||
target_link_libraries(winml_dll PRIVATE winml_lib_api)
|
||||
target_link_libraries(winml_dll PRIVATE winml_lib_api_experimental)
|
||||
if (NOT winml_is_inbox)
|
||||
target_link_libraries(winml_dll PRIVATE winml_lib_api_experimental)
|
||||
endif()
|
||||
target_link_libraries(winml_dll PRIVATE winml_lib_image)
|
||||
target_link_libraries(winml_dll PRIVATE winml_lib_ort)
|
||||
target_link_libraries(winml_dll PRIVATE winml_lib_telemetry)
|
||||
|
|
|
@ -81,6 +81,7 @@ function(target_cppwinrt
|
|||
folder_name # folder this target will be placed
|
||||
midl_options # defines for the midl compiler
|
||||
set_ns_prefix # set ns_prefix option
|
||||
add_ref # set additional cppwinrt ref path
|
||||
)
|
||||
if (MSVC)
|
||||
# get sdk include paths for midl
|
||||
|
@ -107,7 +108,9 @@ function(target_cppwinrt
|
|||
# Get directory
|
||||
get_filename_component(idl_source_directory ${file} DIRECTORY)
|
||||
|
||||
convert_forward_slashes_to_back(${CMAKE_CURRENT_BINARY_DIR} cmake_current_binary_dir_back_slash)
|
||||
if (NOT "${add_ref}" STREQUAL "")
|
||||
convert_forward_slashes_to_back(${add_ref} add_ref)
|
||||
endif()
|
||||
|
||||
set(target_outputs ${CMAKE_CURRENT_BINARY_DIR}/${target_name})
|
||||
convert_forward_slashes_to_back(${target_outputs}/comp output_dir_back_slash)
|
||||
|
@ -152,7 +155,7 @@ function(target_cppwinrt
|
|||
${midl_options}
|
||||
${renamed_idl_fullpath_back_slash}
|
||||
COMMAND
|
||||
${cppwinrt_exe} -in ${winmd_filename} -comp ${output_dir_back_slash} -ref ${sdk_metadata_directory} -out ${generated_dir_back_slash} -verbose
|
||||
${cppwinrt_exe} -in ${winmd_filename} -comp ${output_dir_back_slash} -ref ${sdk_metadata_directory} ${add_ref} -out ${generated_dir_back_slash} -verbose
|
||||
COMMAND
|
||||
# copy the generated component files into a temporary directory where headers exclusions will be applied
|
||||
xcopy ${output_dir_back_slash} ${temp_dir_back_slash}\\ /Y /D
|
||||
|
|
|
@ -16,6 +16,7 @@ set(WINML_TEST_INC_DIR
|
|||
${CMAKE_CURRENT_BINARY_DIR}/winml_api
|
||||
${CMAKE_CURRENT_BINARY_DIR}/winml_api/comp_generated
|
||||
${CMAKE_CURRENT_BINARY_DIR}/winml/sdk/cppwinrt/include
|
||||
${CMAKE_CURRENT_BINARY_DIR}/winml_api_experimental
|
||||
${CMAKE_CURRENT_BINARY_DIR}/winml_api_experimental/comp_generated
|
||||
)
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ public:
|
|||
int dimOffset = gsl::narrow_cast<int>(m_inputTensorDescs[0].GetDimensionCount() - reducedDims.size());
|
||||
for (auto& dim : m_axes)
|
||||
{
|
||||
assert(dim < reducedDims.size()); // ReduceHelperBase already validated this.
|
||||
assert(dim < static_cast<int32_t>(reducedDims.size())); // ReduceHelperBase already validated this.
|
||||
reducedDims[dim] = 1;
|
||||
dmlAxes.push_back(static_cast<uint32_t>(dim + dimOffset));
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ ORT_API_STATUS(SessionRegisterGraphTransformers, _In_ OrtSession* session);
|
|||
ORT_API_STATUS(SessionRegisterCustomRegistry, _In_ OrtSession* session, _In_ IMLOperatorRegistry* registry);
|
||||
ORT_API_STATUS(SessionCopyOneInputAcrossDevices, _In_ OrtSession* session, _In_ const char* const input_name, _In_ OrtValue* orig_value, _Outptr_ OrtValue** new_value);
|
||||
ORT_API_STATUS(SessionGetNumberOfIntraOpThreads, _In_ OrtSession* session, _Out_ uint32_t* num_threads);
|
||||
ORT_API_STATUS(SessionGetNamedDimensionsOverrides, _In_ OrtSession* session, _Out_ winrt::Windows::Foundation::Collections::IMapView<winrt::hstring, uint32_t>& overrides);
|
||||
|
||||
// Dml methods (TODO need to figure out how these need to move to session somehow...)
|
||||
ORT_API_STATUS(DmlExecutionProviderSetDefaultRoundingMode, _In_ OrtExecutionProvider* dml_provider, _In_ bool is_enabled);
|
||||
|
|
|
@ -56,6 +56,7 @@ static constexpr WinmlAdapterApi winml_adapter_api_1 = {
|
|||
&winmla::SessionEndProfiling,
|
||||
&winmla::SessionCopyOneInputAcrossDevices,
|
||||
&winmla::SessionGetNumberOfIntraOpThreads,
|
||||
&winmla::SessionGetNamedDimensionsOverrides,
|
||||
|
||||
// Dml methods (TODO need to figure out how these need to move to session somehow...)
|
||||
&winmla::DmlExecutionProviderSetDefaultRoundingMode,
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/session/onnxruntime_c_api.h"
|
||||
#include "winrt/windows.foundation.collections.h"
|
||||
|
||||
/**
|
||||
* All APIs exported by winml_adapter_c_api.h are part of the private interface dedicated to supporting the WinML API.
|
||||
|
@ -295,6 +296,14 @@ struct WinmlAdapterApi {
|
|||
*/
|
||||
OrtStatus*(ORT_API_CALL* SessionGetNumberOfIntraOpThreads)(_In_ OrtSession* session, _Out_ uint32_t* num_threads)NO_EXCEPTION;
|
||||
|
||||
/**
|
||||
* SessionGetNamedDimensionsOverrides
|
||||
* This api returns the named dimension overrides that are specified for this session
|
||||
*
|
||||
* WinML uses this to determine that named dimension overrides were set correctly through OrtSessionOptions.
|
||||
*/
|
||||
OrtStatus*(ORT_API_CALL* SessionGetNamedDimensionsOverrides)(_In_ OrtSession* session, _Out_ winrt::Windows::Foundation::Collections::IMapView<winrt::hstring, uint32_t>& overrides)NO_EXCEPTION;
|
||||
|
||||
/**
|
||||
* DmlExecutionProviderSetDefaultRoundingMode
|
||||
* This api is used to configure the DML EP to turn on/off rounding.
|
||||
|
|
|
@ -252,3 +252,20 @@ ORT_API_STATUS_IMPL(winmla::SessionGetNumberOfIntraOpThreads, _In_ OrtSession* s
|
|||
return nullptr;
|
||||
API_IMPL_END
|
||||
}
|
||||
|
||||
ORT_API_STATUS_IMPL(winmla::SessionGetNamedDimensionsOverrides, _In_ OrtSession* session, _Out_ winrt::Windows::Foundation::Collections::IMapView<winrt::hstring, uint32_t>& named_dimension_overrides) {
|
||||
API_IMPL_BEGIN
|
||||
auto inference_session = reinterpret_cast<::onnxruntime::InferenceSession*>(session);
|
||||
auto session_options = inference_session->GetSessionOptions();
|
||||
winrt::Windows::Foundation::Collections::IMap<winrt::hstring, uint32_t> override_map = winrt::single_threaded_map<winrt::hstring, uint32_t>();
|
||||
for (auto freeDimOverride : session_options.free_dimension_overrides)
|
||||
{
|
||||
if (freeDimOverride.dim_identifer_type == onnxruntime::FreeDimensionOverrideType::Name)
|
||||
{
|
||||
override_map.Insert(winrt::to_hstring(freeDimOverride.dim_identifier), static_cast<uint32_t>(freeDimOverride.dim_value));
|
||||
}
|
||||
}
|
||||
named_dimension_overrides = override_map.GetView();
|
||||
return nullptr;
|
||||
API_IMPL_END
|
||||
}
|
|
@ -20,6 +20,7 @@ import "Windows.AI.MachineLearning.idl";
|
|||
#define ROOT_NS Microsoft
|
||||
#endif
|
||||
|
||||
|
||||
namespace ROOT_NS.AI.MachineLearning.Experimental {
|
||||
|
||||
[threading(both)]
|
||||
|
@ -30,4 +31,19 @@ namespace ROOT_NS.AI.MachineLearning.Experimental {
|
|||
|
||||
void Test();
|
||||
}
|
||||
|
||||
[marshaling_behavior(agile)]
|
||||
[dualapipartition(1)]
|
||||
runtimeclass LearningModelSessionOptionsExperimental {
|
||||
Windows.Foundation.Collections.IMapView<String, UINT32> GetNamedDimensionOverrides();
|
||||
}
|
||||
|
||||
[threading(both)]
|
||||
[marshaling_behavior(agile)]
|
||||
[dualapipartition(1)]
|
||||
runtimeclass LearningModelSessionExperimental {
|
||||
LearningModelSessionExperimental(ROOT_NS.AI.MachineLearning.LearningModelSession session);
|
||||
LearningModelSessionOptionsExperimental Options { get; };
|
||||
}
|
||||
|
||||
} // namespace Microsoft.AI.MachineLearning.Experimental
|
|
@ -7,6 +7,8 @@
|
|||
#include "LearningModelDevice.h"
|
||||
#include "OnnxruntimeProvider.h"
|
||||
#include "Dummy.h"
|
||||
#include "LearningModelSessionOptionsExperimental.h"
|
||||
#include "LearningModelSessionExperimental.h"
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define XSTRINGIFY(x) STRINGIFY(x)
|
||||
|
@ -97,13 +99,18 @@ STDAPI DllGetExperimentalActivationFactory(void* classId, void** factory) noexce
|
|||
return std::equal(left.rbegin(), left.rend(), right.rbegin(), right.rend());
|
||||
};
|
||||
|
||||
std::wostringstream dummy_class;
|
||||
dummy_class << XSTRINGIFY(WINML_ROOT_NS) << ".AI.MachineLearning.Experimental.Dummy";
|
||||
if (requal(name, dummy_class.str())) {
|
||||
winrt::hstring winml_namespace = winrt::to_hstring(XSTRINGIFY(WINML_ROOT_NS));
|
||||
|
||||
if (requal(name, winml_namespace + L".AI.MachineLearning.Experimental.Dummy")) {
|
||||
*factory = winrt::detach_abi(winrt::make<WINML_EXPERIMENTAL::factory_implementation::Dummy>());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (requal(name, winml_namespace + L".AI.MachineLearning.Experimental.LearningModelSessionExperimental")) {
|
||||
*factory = winrt::detach_abi(winrt::make<WINML_EXPERIMENTAL::factory_implementation::LearningModelSessionExperimental>());
|
||||
return 0;
|
||||
}
|
||||
|
||||
return winrt::hresult_class_not_available(name).to_abi();
|
||||
} catch (...) {
|
||||
return winrt::to_hresult();
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#include "pch.h"
|
||||
|
||||
#include "LearningModelSessionOptionsExperimental.h"
|
||||
#include "LearningModelSessionExperimental.h"
|
||||
|
||||
namespace WINML_EXPERIMENTALP {
|
||||
|
||||
LearningModelSessionExperimental::LearningModelSessionExperimental(const winml::LearningModelSession& session) : _session(session) {
|
||||
int i = 0;
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
WINML_EXPERIMENTAL::LearningModelSessionOptionsExperimental LearningModelSessionExperimental::Options() {
|
||||
return winrt::make<WINML_EXPERIMENTALP::LearningModelSessionOptionsExperimental>(_session);
|
||||
}
|
||||
|
||||
} // namespace WINML_EXPERIMENTALP
|
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include "LearningModelSessionExperimental.g.h"
|
||||
|
||||
namespace WINML_EXPERIMENTALP {
|
||||
|
||||
struct LearningModelSessionExperimental : LearningModelSessionExperimentalT<LearningModelSessionExperimental> {
|
||||
LearningModelSessionExperimental(const winml::LearningModelSession& session);
|
||||
|
||||
WINML_EXPERIMENTAL::LearningModelSessionOptionsExperimental Options();
|
||||
|
||||
private:
|
||||
winml::LearningModelSession _session;
|
||||
};
|
||||
|
||||
} // namespace WINML_EXPERIMENTALP
|
||||
|
||||
namespace WINML_EXPERIMENTAL::factory_implementation {
|
||||
|
||||
struct LearningModelSessionExperimental : LearningModelSessionExperimentalT<LearningModelSessionExperimental, implementation::LearningModelSessionExperimental> {
|
||||
};
|
||||
|
||||
} // namespace WINML_EXPERIMENTAL::factory_implementation
|
|
@ -0,0 +1,18 @@
|
|||
#include "pch.h"
|
||||
#include "LearningModelSessionOptionsExperimental.h"
|
||||
#include "winrt/Windows.Foundation.Collections.h"
|
||||
#include "LearningModelSession.h"
|
||||
#include "iengine.h"
|
||||
|
||||
namespace WINML_EXPERIMENTALP {
|
||||
LearningModelSessionOptionsExperimental::LearningModelSessionOptionsExperimental(const winml::LearningModelSession& session) {
|
||||
com_ptr<WINMLP::LearningModelSession> session_impl = session.as<WINMLP::LearningModelSession>();
|
||||
_winml::IEngine* engine = session_impl->GetEngine();
|
||||
engine->GetNamedDimensionOverrides(overrides_);
|
||||
}
|
||||
|
||||
wfc::IMapView<winrt::hstring, uint32_t> LearningModelSessionOptionsExperimental::GetNamedDimensionOverrides() {
|
||||
return overrides_;
|
||||
}
|
||||
|
||||
} // namespace WINML_EXPERIMENTALP
|
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include "LearningModelSessionOptionsExperimental.g.h"
|
||||
|
||||
namespace WINML_EXPERIMENTALP {
|
||||
|
||||
struct LearningModelSessionOptionsExperimental : LearningModelSessionOptionsExperimentalT<LearningModelSessionOptionsExperimental>
|
||||
{
|
||||
LearningModelSessionOptionsExperimental(const winml::LearningModelSession& options);
|
||||
|
||||
wfc::IMapView<winrt::hstring, uint32_t> GetNamedDimensionOverrides();
|
||||
|
||||
private:
|
||||
wfc::IMapView<winrt::hstring, uint32_t> overrides_;
|
||||
};
|
||||
|
||||
} // namespace WINML_EXPERIMENTALP
|
|
@ -1121,6 +1121,13 @@ HRESULT OnnxruntimeEngine::GetNumberOfIntraOpThreads(uint32_t* num_threads)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT OnnxruntimeEngine::GetNamedDimensionOverrides(wfc::IMapView<winrt::hstring, uint32_t>& overrides) {
|
||||
auto ort_api = engine_factory_->UseOrtApi();
|
||||
auto winml_adapter_api = engine_factory_->UseWinmlAdapterApi();
|
||||
RETURN_HR_IF_NOT_OK_MSG(winml_adapter_api->SessionGetNamedDimensionsOverrides(session_.get(), overrides), ort_api);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT OnnxruntimeEngine::CreateOneInputAcrossDevices(const char* name, IValue* src, IValue** out) {
|
||||
auto ort_api = engine_factory_->UseOrtApi();
|
||||
auto winml_adapter_api = engine_factory_->UseWinmlAdapterApi();
|
||||
|
|
|
@ -116,6 +116,9 @@ class OnnxruntimeEngine : public Microsoft::WRL::RuntimeClass<
|
|||
STDMETHOD(GetNumberOfIntraOpThreads)
|
||||
(uint32_t* num_threads) override;
|
||||
|
||||
STDMETHOD(GetNamedDimensionOverrides)
|
||||
(wfc::IMapView<winrt::hstring, uint32_t>& overrides) override;
|
||||
|
||||
OrtSession* UseOrtSession();
|
||||
const OrtApi* UseOrtApi();
|
||||
OnnxruntimeEngineFactory* GetEngineFactory();
|
||||
|
|
|
@ -149,6 +149,9 @@ IEngine : IUnknown {
|
|||
|
||||
STDMETHOD(GetNumberOfIntraOpThreads)
|
||||
(uint32_t * num_threads) PURE;
|
||||
|
||||
STDMETHOD(GetNamedDimensionOverrides)
|
||||
(wfc::IMapView<winrt::hstring, uint32_t>& overrides) PURE;
|
||||
};
|
||||
|
||||
MIDL_INTERFACE("8ac0b6b9-4561-492b-b63d-a07bdd8292c6")
|
||||
|
|
|
@ -329,12 +329,20 @@ static void NamedDimensionOverride()
|
|||
LearningModelSessionOptions options;
|
||||
options.OverrideNamedDimension(L"None", n);
|
||||
|
||||
// Verifies that if a Dim name doesn't exist the named dimension override does nothing
|
||||
// Verifies that if a Dim name doesn't exist the named dimension override does not interfere with successful evaluation
|
||||
// The override is still expected to be present in the internal onnxruntime override data
|
||||
options.OverrideNamedDimension(L"DimNameThatDoesntExist", n);
|
||||
|
||||
LearningModelSession session(nullptr);
|
||||
WINML_EXPECT_NO_THROW(session = LearningModelSession(model, device, options));
|
||||
|
||||
Experimental::LearningModelSessionExperimental experimental_session(session);
|
||||
Experimental::LearningModelSessionOptionsExperimental experimental_options = experimental_session.Options();
|
||||
wfc::IMapView<winrt::hstring, uint32_t> internal_overrides = experimental_options.GetNamedDimensionOverrides();
|
||||
|
||||
WINML_EXPECT_EQUAL(internal_overrides.Lookup(L"None"), n);
|
||||
WINML_EXPECT_EQUAL(internal_overrides.Lookup(L"DimNameThatDoesntExist"), n);
|
||||
|
||||
ILearningModelFeatureDescriptor descriptor = model.InputFeatures().GetAt(0);
|
||||
TensorFeatureDescriptor tensorDescriptor = nullptr;
|
||||
descriptor.as(tensorDescriptor);
|
||||
|
|
|
@ -24,13 +24,16 @@
|
|||
#define STRINGIFY(x) #x
|
||||
#define XSTRINGIFY(x) STRINGIFY(x)
|
||||
#define CPPWINRT_HEADER(root_ns) comp_generated/winrt/##root_ns##.AI.MachineLearning.h
|
||||
#define CPPWINRT_EXPERIMENTAL_HEADER(root_ns) comp_generated/winrt/##root_ns##.AI.MachineLearning.Experimental.h
|
||||
#define NATIVE_HEADER(root_ns) root_ns##.AI.MachineLearning.native.h
|
||||
#define NATIVE_INTERNAL_HEADER(root_ns) root_ns##.AI.MachineLearning.native.internal.h
|
||||
#define CREATE_CPPWINRT_COMPONENT_HEADER() XSTRINGIFY(CPPWINRT_HEADER(WINML_ROOT_NS))
|
||||
#define CREATE_CPPWINRT_EXPERIMENTAL_COMPONENT_HEADER() XSTRINGIFY(CPPWINRT_EXPERIMENTAL_HEADER(WINML_ROOT_NS))
|
||||
#define CREATE_NATIVE_HEADER() XSTRINGIFY(NATIVE_HEADER(WINML_ROOT_NS))
|
||||
#define CREATE_NATIVE_INTERNAL_HEADER() XSTRINGIFY(NATIVE_INTERNAL_HEADER(WINML_ROOT_NS))
|
||||
|
||||
#include CREATE_CPPWINRT_COMPONENT_HEADER()
|
||||
#include CREATE_CPPWINRT_EXPERIMENTAL_COMPONENT_HEADER()
|
||||
|
||||
// WinML Native Headers
|
||||
#include CREATE_NATIVE_HEADER()
|
||||
|
|
Загрузка…
Ссылка в новой задаче