diff --git a/docs/OperatorKernels.md b/docs/OperatorKernels.md index 481d36f3f6..414dfaab8d 100644 --- a/docs/OperatorKernels.md +++ b/docs/OperatorKernels.md @@ -984,7 +984,8 @@ Do not modify directly.* |Crop|*in* input:**T**
*out* output:**T**|1+|**T** = tensor(float), tensor(float16)| |CumSum|*in* x:**T**
*in* axis:**T2**
*out* y:**T**|14+|**T** = tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)| |||11+|**T** = tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)| -|DFT|*in* input:**T1**
*in* dft_length:**T2**
*in* axis:**tensor(int64)**
*out* output:**T1**

or

*in* input:**T1**
*in* dft_length:**T2**
*out* output:**T1**|17+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(int64)| +|DFT|*in* input:**T1**
*in* dft_length:**T2**
*in* axis:**tensor(int64)**
*out* output:**T1**

or

*in* input:**T1**
*in* dft_length:**T2**
*out* output:**T1**|20+|**T1** = tensor(double), tensor(float), tensor(float16)
**T2** = tensor(int32), tensor(int64)| +|||17+|**T1** = tensor(double), tensor(float), tensor(float16)
**T2** = tensor(int32), tensor(int64)| |DepthToSpace|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||11+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||1+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlDFT.h b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlDFT.h index a99d8bf655..1de88a61a0 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlDFT.h +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlDFT.h @@ -208,7 +208,7 @@ public: PrepareBluesteinZChirp(dataType); } - GpuDFTOperator(IMLOperatorKernelCreationContext* context) + GpuDFTOperator(IMLOperatorKernelCreationContext* context, int32_t version) { ComPtr executionObject; context->GetExecutionInterface(executionObject.GetAddressOf()); @@ -218,8 +218,6 @@ public: ORT_THROW_IF_FAILED(commandList->GetDevice(IID_ID3D12Device, &m_device)); - ORT_THROW_IF_FAILED(context->GetAttribute("axis", MLOperatorAttributeType::Int, 1, sizeof(int64_t), reinterpret_cast(&m_axis))); - int64_t isInverseInt; ORT_THROW_IF_FAILED(context->GetAttribute("inverse", MLOperatorAttributeType::Int, 1, sizeof(int64_t), reinterpret_cast(&isInverseInt))); m_isInverse = static_cast(isInverseInt); @@ -232,6 +230,15 @@ public: ORT_THROW_IF_FAILED(context->GetInputEdgeDescription(0, &edgeDesc)); assert(edgeDesc.edgeType == MLOperatorEdgeType::Tensor); + if (version == 17) + { + ORT_THROW_IF_FAILED(context->GetAttribute("axis", MLOperatorAttributeType::Int, 1, sizeof(int64_t), reinterpret_cast(&m_axis))); + } + else + { + m_axis = -2; //-2 is the default axis value for DFT-20 if the optional axis input is not provided + } + PrepareStockhamFFT(edgeDesc.tensorDataType); PrepareBluesteinZChirp(edgeDesc.tensorDataType); } @@ -398,7 +405,15 @@ public: // Get the input and output shape sizes auto inputDims = GetTensorDimensions(inputTensor.Get()); - ML_CHECK_VALID_ARGUMENT(static_cast(m_axis) < inputDims.size()) + auto rank = static_cast(inputDims.size()); + ComPtr axisTensor; + if (SUCCEEDED(context->GetInputTensor(2, &axisTensor)) && axisTensor != nullptr) + { + MLOperatorTensor tensor(axisTensor.Get()); + m_axis = OperatorHelper::ReadScalarTensorCastToInt64(tensor); + } + m_axis = OperatorHelper::HandleNegativeAxis(static_cast(m_axis), rank); + ML_CHECK_VALID_ARGUMENT(m_axis >= 0 && m_axis < rank); auto outputDims = GetTensorDimensions(outputTensor.Get()); ORT_THROW_HR_IF(E_FAIL, inputDims.size() != outputDims.size()); @@ -977,8 +992,6 @@ struct DFTShapeInferrer : public WRL::Base { try { - int64_t axis; - ORT_THROW_IF_FAILED(context->GetAttribute("axis", MLOperatorAttributeType::Int, 1, sizeof(int64_t), reinterpret_cast(&axis))); int64_t isInverseInt; ORT_THROW_IF_FAILED(context->GetAttribute("inverse", MLOperatorAttributeType::Int, 1, sizeof(int64_t), reinterpret_cast(&isInverseInt))); int64_t isOnesidedInt; @@ -999,7 +1012,25 @@ struct DFTShapeInferrer : public WRL::Base throw; } - auto axisIdx = OperatorHelper::HandleNegativeAxis(static_cast(axis), rank); + int64_t axisValue = -2; //Set default axis value to -2 for DFT-20 (last signal axis) + bool isDft17 = !context->IsInputValid(2); //Check if axis is provided as an input - if yes then it is DFT-20 + + if (isDft17) + { + axisValue = 1; //Default axis value for DFT-17 should be 1 if axis attribute is not provided + ORT_THROW_IF_FAILED(context->GetAttribute("axis", MLOperatorAttributeType::Int, 1, sizeof(int64_t), reinterpret_cast(&axisValue))); + } + else + { + ComPtr contextPrivate; + ORT_THROW_IF_FAILED(context->QueryInterface(IID_PPV_ARGS(&contextPrivate))); + ComPtr axisTensor; + ORT_THROW_IF_FAILED(contextPrivate->GetConstantInputTensor(2, &axisTensor)); + MLOperatorTensor tensor(axisTensor.Get()); + axisValue = OperatorHelper::ReadScalarTensorCastToInt64(tensor); + } + + auto axisIdx = OperatorHelper::HandleNegativeAxis(static_cast(axisValue), rank); // In general the output shape will match the input shape exactly // So initialize the output shape with the input shape @@ -1010,6 +1041,8 @@ struct DFTShapeInferrer : public WRL::Base // It corresponds to the real and imaginary parts of the DFT output. outputDims.back() = 2; + auto dftLength = inputDims[axisIdx]; + if (context->IsInputValid(1)) { // If dft_length is specified, then we should honor the shape. @@ -1019,10 +1052,11 @@ struct DFTShapeInferrer : public WRL::Base ComPtr dftLengthTensor; ORT_THROW_IF_FAILED(contextPrivate->GetConstantInputTensor(1, &dftLengthTensor)); MLOperatorTensor tensor(dftLengthTensor.Get()); - auto dftLength = onnxruntime::narrow(OperatorHelper::ReadScalarTensorCastToInt64(tensor)); - outputDims[axisIdx] = dftLength; + dftLength = onnxruntime::narrow(OperatorHelper::ReadScalarTensorCastToInt64(tensor)); } + outputDims[axisIdx] = dftLength; + // When DFT is onesided, the output shape is half the size of the input shape // along the specified axis. if (isOnesided) @@ -1056,7 +1090,14 @@ public: { try { - auto dftOperator = wil::MakeOrThrow(context); + //If the axis value is provided as an input use DFT-20, otherwise use DFT-17 + int32_t version = 17; + if (context->IsInputValid(2)) + { + version = 20; + } + + auto dftOperator = wil::MakeOrThrow(context, version); dftOperator.CopyTo(kernel); return S_OK; } @@ -1066,12 +1107,12 @@ public: } } - static void RegisterDFTKernel(IMLOperatorRegistry* registry) + static void RegisterDFTKernel(IMLOperatorRegistry* registry, int32_t version) { MLOperatorKernelDescription kernelDescription = {}; kernelDescription.domain = ""; kernelDescription.name = "DFT"; - kernelDescription.minimumOperatorSetVersion = 17; + kernelDescription.minimumOperatorSetVersion = version; kernelDescription.executionType = MLOperatorExecutionType::D3D12; // T1: tensor(float16), tensor(float), tensor(double), tensor(bfloat16) @@ -1081,7 +1122,7 @@ public: { MLOperatorEdgeDescription { MLOperatorEdgeType::Tensor, (uint64_t)MLOperatorTensorDataType::Float16 }, MLOperatorEdgeDescription { MLOperatorEdgeType::Tensor, (uint64_t)MLOperatorTensorDataType::Float }, - //MLOperatorEdgeDescription { MLOperatorEdgeType::Tensor, (uint64_t)MLOperatorTensorDataType::Double }, + MLOperatorEdgeDescription { MLOperatorEdgeType::Tensor, (uint64_t)MLOperatorTensorDataType::Double }, }; t1Constraint.allowedTypes = t1AllowedEdges.data(); t1Constraint.allowedTypeCount = static_cast(t1AllowedEdges.size()); @@ -1091,7 +1132,7 @@ public: t2Constraint.typeLabel = "T2"; std::vector t2AllowedEdges { - // MLOperatorEdgeDescription { MLOperatorEdgeType::Tensor, (uint64_t)MLOperatorTensorDataType::Int32 }, + MLOperatorEdgeDescription { MLOperatorEdgeType::Tensor, (uint64_t)MLOperatorTensorDataType::Int32 }, MLOperatorEdgeDescription { MLOperatorEdgeType::Tensor, (uint64_t)MLOperatorTensorDataType::Int64 }, }; t2Constraint.allowedTypes = t2AllowedEdges.data(); @@ -1101,13 +1142,6 @@ public: kernelDescription.typeConstraints = typeConstraints.data(); kernelDescription.typeConstraintCount = static_cast(typeConstraints.size()); - MLOperatorAttributeNameValue axisAttributeValue; - axisAttributeValue.name = "axis"; - axisAttributeValue.type = MLOperatorAttributeType::Int; - axisAttributeValue.valueCount = 1; - static const int64_t axis[] = { 1 }; - axisAttributeValue.ints = axis; - MLOperatorAttributeNameValue inverseAttributeValue; inverseAttributeValue.name = "inverse"; inverseAttributeValue.type = MLOperatorAttributeType::Int; @@ -1123,11 +1157,21 @@ public: onesidedAttributeValue.ints = onesided; std::vector attributeDefaultValues{ - axisAttributeValue, inverseAttributeValue, onesidedAttributeValue }; + if (version == 17) + { + MLOperatorAttributeNameValue axisAttributeValue; + axisAttributeValue.name = "axis"; + axisAttributeValue.type = MLOperatorAttributeType::Int; + axisAttributeValue.valueCount = 1; + static const int64_t axis[] = { 1 }; + axisAttributeValue.ints = axis; + attributeDefaultValues.push_back(axisAttributeValue); + } + kernelDescription.defaultAttributes = attributeDefaultValues.data(); kernelDescription.defaultAttributeCount = static_cast(attributeDefaultValues.size()); kernelDescription.options = MLOperatorKernelOptions::None; @@ -1136,7 +1180,7 @@ public: auto shareInferrer = wil::MakeOrThrow(); auto factory = wil::MakeOrThrow(); - std::array requiredConstantCpuInputs = { 1 }; + std::array requiredConstantCpuInputs = { 1, 2 }; ComPtr registryPrivate; ORT_THROW_IF_FAILED(registry->QueryInterface(IID_PPV_ARGS(®istryPrivate))); diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp index 96949e777f..27605a6ad8 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp @@ -1314,7 +1314,8 @@ void RegisterDmlOperators(IMLOperatorRegistry* registry) )); } - GpuDFTOperatorFactory::RegisterDFTKernel(registry); + GpuDFTOperatorFactory::RegisterDFTKernel(registry, 17); + GpuDFTOperatorFactory::RegisterDFTKernel(registry, 20); DmlSTFTOperatorFactory::RegisterSTFTKernel(registry); DmlGridSampleOperatorFactory::RegisterGridSampleKernel(registry); } diff --git a/onnxruntime/test/providers/cpu/signal/signal_ops_test.cc b/onnxruntime/test/providers/cpu/signal/signal_ops_test.cc index 54d725defe..9b44b5aa4c 100644 --- a/onnxruntime/test/providers/cpu/signal/signal_ops_test.cc +++ b/onnxruntime/test/providers/cpu/signal/signal_ops_test.cc @@ -33,6 +33,10 @@ static void TestNaiveDFTFloat(bool onesided, int since_version) { expected_output.resize(6); } test.AddInput("input", shape, input); + if (since_version == 20) { + test.AddInput("dft_length", {}, {5}); + test.AddInput("axis", {}, {-2}); + } test.AddAttribute("onesided", static_cast(onesided)); test.AddOutput("output", output_shape, expected_output); test.Run(); @@ -53,6 +57,10 @@ static void TestRadix2DFTFloat(bool onesided, int since_version) { expected_output.resize(10); } test.AddInput("input", shape, input); + if (since_version == 20) { + test.AddInput("dft_length", {}, {8}); + test.AddInput("axis", {}, {1}); + } test.AddAttribute("onesided", static_cast(onesided)); test.AddOutput("output", output_shape, expected_output); test.Run(); @@ -67,6 +75,10 @@ static void TestInverseFloat(int since_version) { vector expected_output = {1.000f, 0.000f, 2.000f, 0.000f, 3.000f, 0.000f, 4.000f, 0.000f, 5.000f, 0.000f}; test.AddInput("input", shape, input); + if (since_version == 20) { + test.AddInput("dft_length", {}, {5}); + test.AddInput("axis", {}, {1}); + } test.AddAttribute("inverse", static_cast(true)); test.AddOutput("output", shape, expected_output); test.Run();