From 7514c4b770ea885ff4b5266b87f61aed6de2e1c1 Mon Sep 17 00:00:00 2001 From: Varun Jaiswal <96684656+varun-jaiswal17@users.noreply.github.com> Date: Fri, 27 Mar 2026 14:15:51 +0530 Subject: [PATCH] Merge pull request #28687 from varun-jaiswal17:asan_pipeline 3d: fix depth precision inconsistency under ASan/RelWithDebInfo builds #28687 Resolves FMA inconsistency between build types by using std::fma(a, b, c) to get the same precision everywhere ASan, Release, Debug. Change optimisation : Without FMA : 96.54 ms FMA : 32.33 ms Merged with : opencv/ci-gha-workflow/pull/297 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/3d/src/rendering.cpp | 24 +++++++++++++++++------- modules/3d/test/test_rendering.cpp | 2 +- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/modules/3d/src/rendering.cpp b/modules/3d/src/rendering.cpp index 3c628b129a..ca0b9bbdf9 100644 --- a/modules/3d/src/rendering.cpp +++ b/modules/3d/src/rendering.cpp @@ -271,17 +271,27 @@ static void triangleRasterizeInternal(InputArray _vertices, InputArray _indices, { Vec3f vglobal = vertices.at(i); - Vec4f vndc = mvpMatrix * Vec4f(vglobal[0], vglobal[1], vglobal[2], 1.f); + float x_num = std::fma(mvpMatrix(0,0), vglobal[0], + std::fma(mvpMatrix(0,1), vglobal[1], + std::fma(mvpMatrix(0,2), vglobal[2], mvpMatrix(0,3)))); + float y_num = std::fma(mvpMatrix(1,0), vglobal[0], + std::fma(mvpMatrix(1,1), vglobal[1], + std::fma(mvpMatrix(1,2), vglobal[2], mvpMatrix(1,3)))); + float z_num = std::fma(mvpMatrix(2,0), vglobal[0], + std::fma(mvpMatrix(2,1), vglobal[1], + std::fma(mvpMatrix(2,2), vglobal[2], mvpMatrix(2,3)))); + float w_num = std::fma(mvpMatrix(3,0), vglobal[0], + std::fma(mvpMatrix(3,1), vglobal[1], + std::fma(mvpMatrix(3,2), vglobal[2], mvpMatrix(3,3)))); - float invw = 1.f / vndc[3]; - Vec4f vdiv = {vndc[0] * invw, vndc[1] * invw, vndc[2] * invw, invw}; + float invw = 1.f / w_num; // [-1, 1]^3 => [0, width] x [0, height] x [0, 1] Vec4f vscreen = { - (vdiv[0] + 1.f) * 0.5f * (float)imgSize.width, - (vdiv[1] + 1.f) * 0.5f * (float)imgSize.height, - (vdiv[2] + 1.f) * 0.5f, - vdiv[3] + std::fma(x_num * invw, 0.5f * (float)imgSize.width, 0.5f * (float)imgSize.width), + std::fma(y_num * invw, 0.5f * (float)imgSize.height, 0.5f * (float)imgSize.height), + std::fma(z_num * invw, 0.5f, 0.5f), + invw }; screenVertices.at(i) = vscreen; diff --git a/modules/3d/test/test_rendering.cpp b/modules/3d/test/test_rendering.cpp index 02e73fee26..4df888c5c2 100644 --- a/modules/3d/test/test_rendering.cpp +++ b/modules/3d/test/test_rendering.cpp @@ -649,7 +649,7 @@ TEST_P(RenderingTest, floatParams) { thr.rgbInfThreshold = 0.000229; thr.rgbL2Threshold = 6.37e-09; - thr.depthL2Threshold = 0.000427; + thr.depthL2Threshold = 0.00043; } else if (width == 700 && height == 700 && shadingType == RASTERIZE_SHADING_SHADED && cullingMode == RASTERIZE_CULLING_CW) {