diff --git a/CMakeLists.txt b/CMakeLists.txt index 36e380ae..0d6e059b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -267,8 +267,8 @@ set( data/models/mediapipe.with_runtime_opt.ort.license data/models/pphumanseg_fp32.with_runtime_opt.ort data/models/pphumanseg_fp32.with_runtime_opt.ort.license - data/models/rvm_mobilenetv3_fp32.with_runtime_opt.ort - data/models/rvm_mobilenetv3_fp32.with_runtime_opt.ort.license + data/models/rvm_mobilenetv3_fp32.onnx + data/models/rvm_mobilenetv3_fp32.onnx.license data/models/selfie_multiclass_256x256.with_runtime_opt.ort data/models/selfie_multiclass_256x256.with_runtime_opt.ort.license data/models/selfie_segmentation.with_runtime_opt.ort diff --git a/data/models/rvm_mobilenetv3_fp32.with_runtime_opt.ort b/data/models/rvm_mobilenetv3_fp32.onnx similarity index 98% rename from data/models/rvm_mobilenetv3_fp32.with_runtime_opt.ort rename to data/models/rvm_mobilenetv3_fp32.onnx index b5a32fa7..00279236 100644 Binary files a/data/models/rvm_mobilenetv3_fp32.with_runtime_opt.ort and b/data/models/rvm_mobilenetv3_fp32.onnx differ diff --git a/data/models/rvm_mobilenetv3_fp32.with_runtime_opt.ort.license b/data/models/rvm_mobilenetv3_fp32.onnx.license similarity index 100% rename from data/models/rvm_mobilenetv3_fp32.with_runtime_opt.ort.license rename to data/models/rvm_mobilenetv3_fp32.onnx.license diff --git a/src/consts.h b/src/consts.h index 412f0827..31828407 100644 --- a/src/consts.h +++ b/src/consts.h @@ -12,7 +12,9 @@ const char *const MODEL_SINET = "models/SINet_Softmax_simple.with_runtime_opt.or const char *const MODEL_MEDIAPIPE = "models/mediapipe.with_runtime_opt.ort"; const char *const MODEL_SELFIE = "models/selfie_segmentation.with_runtime_opt.ort"; const char *const MODEL_SELFIE_MULTICLASS = "models/selfie_multiclass_256x256.with_runtime_opt.ort"; -const char *const MODEL_RVM = "models/rvm_mobilenetv3_fp32.with_runtime_opt.ort"; +// Use the original ONNX model for RVM: the pre-optimized .ort variant is +// CPU-EP-targeted and crashes GPU execution providers (e.g. CUDA). +const char *const MODEL_RVM = "models/rvm_mobilenetv3_fp32.onnx"; const char *const MODEL_PPHUMANSEG = "models/pphumanseg_fp32.with_runtime_opt.ort"; const char *const MODEL_ENHANCE_TBEFN = "models/tbefn_fp32.with_runtime_opt.ort"; const char *const MODEL_ENHANCE_URETINEX = "models/uretinex_net_180x320.with_runtime_opt.ort"; diff --git a/src/models/Model.hpp b/src/models/Model.hpp index 03e03cc2..befd1e4f 100644 --- a/src/models/Model.hpp +++ b/src/models/Model.hpp @@ -15,6 +15,7 @@ #include #include +#include template T vectorProduct(const std::vector &v) { @@ -282,8 +283,25 @@ class Model { rawOutputNames.push_back(outputName.get()); } - session->Run(Ort::RunOptions{nullptr}, rawInputNames.data(), inputTensor.data(), inputNames.size(), - rawOutputNames.data(), outputTensor.data(), outputNames.size()); + // Let ORT allocate the output tensors itself, then copy the results + // back into the pre-allocated CPU buffers. Pre-binding CPU output + // tensors can misbehave on GPU execution providers for stateful + // multi-output models (e.g. RVM). + std::vector results = session->Run(Ort::RunOptions{nullptr}, rawInputNames.data(), + inputTensor.data(), inputNames.size(), + rawOutputNames.data(), outputNames.size()); + + for (size_t i = 0; i < results.size() && i < outputTensor.size(); i++) { + const float *src = results[i].GetTensorData(); + float *dst = outputTensor[i].GetTensorMutableData(); + const size_t srcCount = results[i].GetTensorTypeAndShapeInfo().GetElementCount(); + const size_t dstCount = outputTensor[i].GetTensorTypeAndShapeInfo().GetElementCount(); + if (srcCount != dstCount) { + obs_log(LOG_WARNING, "Output %d size mismatch: model produced %d elements, expected %d", + (int)i, (int)srcCount, (int)dstCount); + } + memcpy(dst, src, (srcCount < dstCount ? srcCount : dstCount) * sizeof(float)); + } } };