# HG changeset patch # User Sebastien Jodogne # Date 1684337452 -7200 # Node ID 22a83fb9dd2396dbd5fb4d9e158116c1022da9ec # Parent 20222330cdf606457cb06dc8e084a6da97e3041e added AlignedMatrix and TimerLogger diff -r 20222330cdf6 -r 22a83fb9dd23 OrthancStone/Resources/CMake/OrthancStoneConfiguration.cmake --- a/OrthancStone/Resources/CMake/OrthancStoneConfiguration.cmake Tue May 16 11:26:05 2023 +0200 +++ b/OrthancStone/Resources/CMake/OrthancStoneConfiguration.cmake Wed May 17 17:30:52 2023 +0200 @@ -199,7 +199,6 @@ if (NOT ORTHANC_SANDBOXED AND ENABLE_THREADS AND ENABLE_WEB_CLIENT) list(APPEND ORTHANC_STONE_SOURCES ${ORTHANC_STONE_ROOT}/Loaders/GenericLoadersContext.cpp - ${ORTHANC_STONE_ROOT}/Loaders/GenericLoadersContext.h ${ORTHANC_STONE_ROOT}/Oracle/GenericOracleRunner.cpp ${ORTHANC_STONE_ROOT}/Oracle/ThreadedOracle.cpp ) @@ -209,7 +208,6 @@ if (ENABLE_PUGIXML) list(APPEND ORTHANC_STONE_SOURCES ${ORTHANC_STONE_ROOT}/Scene2D/OsiriXLayerFactory.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/OsiriXLayerFactory.h ${ORTHANC_STONE_ROOT}/Toolbox/OsiriX/AngleAnnotation.cpp ${ORTHANC_STONE_ROOT}/Toolbox/OsiriX/Annotation.cpp ${ORTHANC_STONE_ROOT}/Toolbox/OsiriX/ArrayValue.cpp @@ -236,36 +234,22 @@ ${ORTHANC_STONE_ROOT}/Fonts/TextBoundingBox.cpp ${ORTHANC_STONE_ROOT}/Loaders/BasicFetchingItemsSorter.cpp - ${ORTHANC_STONE_ROOT}/Loaders/BasicFetchingItemsSorter.h ${ORTHANC_STONE_ROOT}/Loaders/BasicFetchingStrategy.cpp - ${ORTHANC_STONE_ROOT}/Loaders/BasicFetchingStrategy.h ${ORTHANC_STONE_ROOT}/Loaders/DicomResourcesLoader.cpp ${ORTHANC_STONE_ROOT}/Loaders/DicomSource.cpp ${ORTHANC_STONE_ROOT}/Loaders/DicomStructureSetLoader.cpp - ${ORTHANC_STONE_ROOT}/Loaders/DicomStructureSetLoader.h ${ORTHANC_STONE_ROOT}/Loaders/DicomVolumeLoader.cpp - ${ORTHANC_STONE_ROOT}/Loaders/IFetchingItemsSorter.h - ${ORTHANC_STONE_ROOT}/Loaders/IFetchingStrategy.h ${ORTHANC_STONE_ROOT}/Loaders/LoadedDicomResources.cpp ${ORTHANC_STONE_ROOT}/Loaders/LoaderStateMachine.cpp - ${ORTHANC_STONE_ROOT}/Loaders/LoaderStateMachine.h ${ORTHANC_STONE_ROOT}/Loaders/OrthancMultiframeVolumeLoader.cpp - ${ORTHANC_STONE_ROOT}/Loaders/OrthancMultiframeVolumeLoader.h ${ORTHANC_STONE_ROOT}/Loaders/OracleScheduler.cpp ${ORTHANC_STONE_ROOT}/Loaders/OrthancSeriesVolumeProgressiveLoader.cpp - ${ORTHANC_STONE_ROOT}/Loaders/OrthancSeriesVolumeProgressiveLoader.h ${ORTHANC_STONE_ROOT}/Loaders/SeriesFramesLoader.cpp ${ORTHANC_STONE_ROOT}/Loaders/SeriesMetadataLoader.cpp ${ORTHANC_STONE_ROOT}/Loaders/SeriesOrderedFrames.cpp ${ORTHANC_STONE_ROOT}/Loaders/SeriesThumbnailsLoader.cpp - ${ORTHANC_STONE_ROOT}/Messages/ICallable.h - ${ORTHANC_STONE_ROOT}/Messages/IMessage.h - ${ORTHANC_STONE_ROOT}/Messages/IMessageEmitter.h ${ORTHANC_STONE_ROOT}/Messages/IObservable.cpp - ${ORTHANC_STONE_ROOT}/Messages/IObservable.h - ${ORTHANC_STONE_ROOT}/Messages/IObserver.h - ${ORTHANC_STONE_ROOT}/Messages/ObserverBase.h ${ORTHANC_STONE_ROOT}/Oracle/GetOrthancImageCommand.cpp ${ORTHANC_STONE_ROOT}/Oracle/GetOrthancWebViewerJpegCommand.cpp @@ -276,202 +260,102 @@ ${ORTHANC_STONE_ROOT}/Oracle/ParseDicomFromWadoCommand.cpp ${ORTHANC_STONE_ROOT}/Scene2D/AnnotationsSceneLayer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/AnnotationsSceneLayer.h ${ORTHANC_STONE_ROOT}/Scene2D/ArrowSceneLayer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/ArrowSceneLayer.h ${ORTHANC_STONE_ROOT}/Scene2D/CairoCompositor.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/CairoCompositor.h - ${ORTHANC_STONE_ROOT}/Scene2D/Color.h - ${ORTHANC_STONE_ROOT}/Scene2D/ColorSceneLayer.h ${ORTHANC_STONE_ROOT}/Scene2D/ColorTextureSceneLayer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/ColorTextureSceneLayer.h ${ORTHANC_STONE_ROOT}/Scene2D/CopyStyleConfigurator.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/CopyStyleConfigurator.h ${ORTHANC_STONE_ROOT}/Scene2D/FloatTextureSceneLayer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/FloatTextureSceneLayer.h ${ORTHANC_STONE_ROOT}/Scene2D/GrayscaleStyleConfigurator.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/GrayscaleStyleConfigurator.h ${ORTHANC_STONE_ROOT}/Scene2D/GrayscaleWindowingSceneTracker.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/GrayscaleWindowingSceneTracker.h - ${ORTHANC_STONE_ROOT}/Scene2D/ICompositor.h - ${ORTHANC_STONE_ROOT}/Scene2D/ILayerStyleConfigurator.h - ${ORTHANC_STONE_ROOT}/Scene2D/ISceneLayer.h ${ORTHANC_STONE_ROOT}/Scene2D/InfoPanelSceneLayer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/InfoPanelSceneLayer.h ${ORTHANC_STONE_ROOT}/Scene2D/LookupTableStyleConfigurator.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/LookupTableStyleConfigurator.h ${ORTHANC_STONE_ROOT}/Scene2D/LookupTableTextureSceneLayer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/LookupTableTextureSceneLayer.h ${ORTHANC_STONE_ROOT}/Scene2D/MacroSceneLayer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/MacroSceneLayer.h ${ORTHANC_STONE_ROOT}/Scene2D/MagnifyingGlassTracker.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/MagnifyingGlassTracker.h - ${ORTHANC_STONE_ROOT}/Scene2D/NullLayer.h ${ORTHANC_STONE_ROOT}/Scene2D/PanSceneTracker.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/PanSceneTracker.h ${ORTHANC_STONE_ROOT}/Scene2D/PointerEvent.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/PointerEvent.h ${ORTHANC_STONE_ROOT}/Scene2D/PolylineSceneLayer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/PolylineSceneLayer.h ${ORTHANC_STONE_ROOT}/Scene2D/RotateSceneTracker.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/RotateSceneTracker.h ${ORTHANC_STONE_ROOT}/Scene2D/Scene2D.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Scene2D.h ${ORTHANC_STONE_ROOT}/Scene2D/ScenePoint2D.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/ScenePoint2D.h ${ORTHANC_STONE_ROOT}/Scene2D/TextSceneLayer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/TextSceneLayer.h ${ORTHANC_STONE_ROOT}/Scene2D/TextureBaseSceneLayer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/TextureBaseSceneLayer.h ${ORTHANC_STONE_ROOT}/Scene2D/ZoomSceneTracker.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/ZoomSceneTracker.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoArrowRenderer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoArrowRenderer.h - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoBaseRenderer.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoColorTextureRenderer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoColorTextureRenderer.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoFloatTextureRenderer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoFloatTextureRenderer.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoInfoPanelRenderer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoInfoPanelRenderer.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoLookupTableTextureRenderer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoLookupTableTextureRenderer.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoPolylineRenderer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoPolylineRenderer.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoTextRenderer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoTextRenderer.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CompositorHelper.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CompositorHelper.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/FixedPointAligner.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/FixedPointAligner.h - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/ICairoContextProvider.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/MacroLayerRenderer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/MacroLayerRenderer.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/AngleMeasureTool.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/AngleMeasureTool.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/CreateAngleMeasureCommand.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/CreateAngleMeasureCommand.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/CreateAngleMeasureTracker.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/CreateAngleMeasureTracker.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/CreateCircleMeasureTracker.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/CreateCircleMeasureTracker.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/CreateLineMeasureCommand.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/CreateLineMeasureCommand.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/CreateLineMeasureTracker.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/CreateLineMeasureTracker.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/CreateMeasureTracker.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/CreateMeasureTracker.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/EditAngleMeasureCommand.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/EditAngleMeasureCommand.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/EditAngleMeasureTracker.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/EditAngleMeasureTracker.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/EditLineMeasureCommand.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/EditLineMeasureCommand.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/EditLineMeasureTracker.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/EditLineMeasureTracker.h - ${ORTHANC_STONE_ROOT}/Scene2DViewport/IFlexiblePointerTracker.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/LayerHolder.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/LayerHolder.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/LineMeasureTool.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/LineMeasureTool.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/MeasureCommands.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/MeasureCommands.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/MeasureTool.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/MeasureTool.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/MeasureToolsToolbox.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/MeasureToolsToolbox.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/MeasureTrackers.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/MeasureTrackers.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/OneGesturePointerTracker.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/OneGesturePointerTracker.h - ${ORTHANC_STONE_ROOT}/Scene2DViewport/PredeclaredTypes.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/UndoStack.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/UndoStack.h ${ORTHANC_STONE_ROOT}/Scene2DViewport/ViewportController.cpp - ${ORTHANC_STONE_ROOT}/Scene2DViewport/ViewportController.h ${ORTHANC_STONE_ROOT}/StoneEnumerations.cpp - ${ORTHANC_STONE_ROOT}/StoneException.h ${ORTHANC_STONE_ROOT}/StoneInitialization.cpp ${ORTHANC_STONE_ROOT}/Toolbox/AffineTransform2D.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/AffineTransform2D.h + ${ORTHANC_STONE_ROOT}/Toolbox/AlignedMatrix.cpp ${ORTHANC_STONE_ROOT}/Toolbox/BucketAccumulator1D.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/BucketAccumulator1D.h ${ORTHANC_STONE_ROOT}/Toolbox/BucketAccumulator2D.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/BucketAccumulator2D.h ${ORTHANC_STONE_ROOT}/Toolbox/CoordinateSystem3D.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/CoordinateSystem3D.h ${ORTHANC_STONE_ROOT}/Toolbox/DicomInstanceParameters.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/DicomInstanceParameters.h ${ORTHANC_STONE_ROOT}/Toolbox/DicomStructureSet.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/DicomStructureSet.h ${ORTHANC_STONE_ROOT}/Toolbox/DynamicBitmap.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/DynamicBitmap.h ${ORTHANC_STONE_ROOT}/Toolbox/Extent2D.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/Extent2D.h ${ORTHANC_STONE_ROOT}/Toolbox/FiniteProjectiveCamera.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/FiniteProjectiveCamera.h ${ORTHANC_STONE_ROOT}/Toolbox/GenericToolbox.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/GenericToolbox.h ${ORTHANC_STONE_ROOT}/Toolbox/GeometryToolbox.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/GeometryToolbox.h ${ORTHANC_STONE_ROOT}/Toolbox/ImageGeometry.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/ImageGeometry.h ${ORTHANC_STONE_ROOT}/Toolbox/ImageToolbox.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/ImageToolbox.h ${ORTHANC_STONE_ROOT}/Toolbox/Internals/BucketMapper.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/Internals/BucketMapper.h ${ORTHANC_STONE_ROOT}/Toolbox/Internals/OrientedIntegerLine2D.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/Internals/OrientedIntegerLine2D.h ${ORTHANC_STONE_ROOT}/Toolbox/Internals/RectanglesIntegerProjection.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/Internals/RectanglesIntegerProjection.h ${ORTHANC_STONE_ROOT}/Toolbox/LinearAlgebra.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/LinearAlgebra.h - ${ORTHANC_STONE_ROOT}/Toolbox/PixelTestPatterns.h ${ORTHANC_STONE_ROOT}/Toolbox/SegmentTree.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/SegmentTree.h ${ORTHANC_STONE_ROOT}/Toolbox/ShearWarpProjectiveTransform.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/ShearWarpProjectiveTransform.h ${ORTHANC_STONE_ROOT}/Toolbox/SlicesSorter.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/SlicesSorter.h ${ORTHANC_STONE_ROOT}/Toolbox/SortedFrames.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/SortedFrames.h - ${ORTHANC_STONE_ROOT}/Toolbox/SubpixelReader.h - ${ORTHANC_STONE_ROOT}/Toolbox/SubvoxelReader.h ${ORTHANC_STONE_ROOT}/Toolbox/TextRenderer.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/TextRenderer.h + ${ORTHANC_STONE_ROOT}/Toolbox/TimerLogger.cpp ${ORTHANC_STONE_ROOT}/Toolbox/UndoRedoStack.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/UndoRedoStack.h ${ORTHANC_STONE_ROOT}/Toolbox/UnionOfRectangles.cpp - ${ORTHANC_STONE_ROOT}/Toolbox/UnionOfRectangles.h ${ORTHANC_STONE_ROOT}/Viewport/DefaultViewportInteractor.cpp - ${ORTHANC_STONE_ROOT}/Viewport/IViewport.h ${ORTHANC_STONE_ROOT}/Viewport/ViewportLocker.cpp - ${ORTHANC_STONE_ROOT}/Volumes/IGeometryProvider.h ${ORTHANC_STONE_ROOT}/Volumes/IVolumeSlicer.cpp - ${ORTHANC_STONE_ROOT}/Volumes/IVolumeSlicer.h ${ORTHANC_STONE_ROOT}/Volumes/OrientedVolumeBoundingBox.cpp - ${ORTHANC_STONE_ROOT}/Volumes/OrientedVolumeBoundingBox.h ${ORTHANC_STONE_ROOT}/Volumes/VolumeImageGeometry.cpp - ${ORTHANC_STONE_ROOT}/Volumes/VolumeImageGeometry.h ${ORTHANC_STONE_ROOT}/Volumes/VolumeReslicer.cpp - ${ORTHANC_STONE_ROOT}/Volumes/VolumeReslicer.h ${ORTHANC_STONE_ROOT}/Volumes/VolumeSceneLayerSource.cpp - ${ORTHANC_STONE_ROOT}/Volumes/VolumeSceneLayerSource.h - ${ORTHANC_STONE_ROOT}/Volumes/DicomVolumeImage.h ${ORTHANC_STONE_ROOT}/Volumes/DicomVolumeImage.cpp - ${ORTHANC_STONE_ROOT}/Volumes/DicomVolumeImage.h ${ORTHANC_STONE_ROOT}/Volumes/DicomVolumeImageMPRSlicer.cpp - ${ORTHANC_STONE_ROOT}/Volumes/DicomVolumeImageMPRSlicer.h ${ORTHANC_STONE_ROOT}/Volumes/DicomVolumeImageReslicer.cpp - ${ORTHANC_STONE_ROOT}/Volumes/DicomVolumeImageReslicer.h ${ORTHANC_STONE_ROOT}/Volumes/ImageBuffer3D.cpp - ${ORTHANC_STONE_ROOT}/Volumes/ImageBuffer3D.h ${ORTHANC_STONE_ROOT}/Wrappers/CairoContext.cpp ${ORTHANC_STONE_ROOT}/Wrappers/CairoSurface.cpp @@ -493,52 +377,29 @@ if (ENABLE_OPENGL) list(APPEND ORTHANC_STONE_SOURCES - ${ORTHANC_STONE_ROOT}/Fonts/OpenGLTextCoordinates.h ${ORTHANC_STONE_ROOT}/Fonts/OpenGLTextCoordinates.cpp - ${ORTHANC_STONE_ROOT}/OpenGL/OpenGLProgram.h ${ORTHANC_STONE_ROOT}/OpenGL/OpenGLProgram.cpp - ${ORTHANC_STONE_ROOT}/OpenGL/OpenGLShader.h ${ORTHANC_STONE_ROOT}/OpenGL/OpenGLShader.cpp - ${ORTHANC_STONE_ROOT}/OpenGL/OpenGLTexture.h ${ORTHANC_STONE_ROOT}/OpenGL/OpenGLTexture.cpp - ${ORTHANC_STONE_ROOT}/OpenGL/OpenGLTextureArray.h ${ORTHANC_STONE_ROOT}/OpenGL/OpenGLTextureArray.cpp - ${ORTHANC_STONE_ROOT}/OpenGL/OpenGLTextureVolume.h ${ORTHANC_STONE_ROOT}/OpenGL/OpenGLTextureVolume.cpp - ${ORTHANC_STONE_ROOT}/OpenGL/OpenGLFramebuffer.h ${ORTHANC_STONE_ROOT}/OpenGL/OpenGLFramebuffer.cpp - ${ORTHANC_STONE_ROOT}/OpenGL/ImageProcessingProgram.h ${ORTHANC_STONE_ROOT}/OpenGL/ImageProcessingProgram.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/OpenGLCompositor.h ${ORTHANC_STONE_ROOT}/Scene2D/OpenGLCompositor.cpp ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLAdvancedPolylineRenderer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLAdvancedPolylineRenderer.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLArrowRenderer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLArrowRenderer.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLBasicPolylineRenderer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLBasicPolylineRenderer.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLColorTextureProgram.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLColorTextureProgram.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLColorTextureRenderer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLColorTextureRenderer.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLFloatTextureProgram.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLFloatTextureProgram.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLFloatTextureRenderer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLFloatTextureRenderer.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLInfoPanelRenderer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLInfoPanelRenderer.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLLinesProgram.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLLinesProgram.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLLookupTableTextureRenderer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLLookupTableTextureRenderer.h - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLShaderVersionDirective.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLTextProgram.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLTextProgram.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLTextRenderer.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLTextRenderer.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLTextureProgram.cpp - ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLTextureProgram.h ) endif() diff -r 20222330cdf6 -r 22a83fb9dd23 OrthancStone/Sources/Toolbox/AlignedMatrix.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancStone/Sources/Toolbox/AlignedMatrix.cpp Wed May 17 17:30:52 2023 +0200 @@ -0,0 +1,276 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2022 Osimis S.A., Belgium + * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * . + **/ + + +#include "AlignedMatrix.h" + +#include + +#include + +namespace OrthancStone +{ + static unsigned int Ceiling(unsigned int a, + unsigned int b) + { + if (a % b == 0) + { + return a / b; + } + else + { + return a / b + 1; + } + } + + + void AlignedMatrix::Setup(unsigned int rows, + unsigned int cols) + { + assert(sizeof(float) == 4); + + if (rows == 0 || + cols == 0) + { + rows_ = 0; + cols_ = 0; + pitch_ = 0; + pitchFloatPointer_ = 0; + content_ = NULL; + } + else + { + rows_ = rows; + cols_ = cols; + pitch_ = Ceiling(cols * sizeof(float), ORTHANC_MEMORY_ALIGNMENT) * ORTHANC_MEMORY_ALIGNMENT; + pitchFloatPointer_ = pitch_ / sizeof(float); + + void* tmp = NULL; + if (posix_memalign(&tmp, ORTHANC_MEMORY_ALIGNMENT, rows_ * pitch_) != 0) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NotEnoughMemory); + } + + assert(reinterpret_cast(tmp) % ORTHANC_MEMORY_ALIGNMENT == 0); + assert(pitch_ % ORTHANC_MEMORY_ALIGNMENT == 0); + assert(pitch_ % sizeof(float) == 0); + assert((rows_ * pitch_) % ORTHANC_MEMORY_ALIGNMENT == 0); + + content_ = static_cast(tmp); + } + } + + + AlignedMatrix::~AlignedMatrix() + { + if (content_ != NULL) + { + free(content_); + } + } + + + void AlignedMatrix::FillZeros() + { + memset(content_, 0, rows_ * pitch_); + } + + + void AlignedMatrix::ProductPlain(AlignedMatrix& c, + const AlignedMatrix& a, + const AlignedMatrix& b) + { + if (c.GetRows() != a.GetRows() || + c.GetColumns() != b.GetColumns() || + a.GetColumns() != b.GetRows()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); + } + + const unsigned int M = c.GetRows(); + const unsigned int N = c.GetColumns(); + const unsigned int K = a.GetColumns(); + + c.FillZeros(); + + for (unsigned int i = 0; i < M; i++) + { + // Loop over "k" to be more cache-friendly + // https://sahnimanas.github.io/post/anatomy-of-a-high-performance-convolution/ + for (unsigned int k = 0; k < K; k++) + { + for (unsigned int j = 0; j < N; j++) + { + c.AddValue(i, j, a.GetValue(i, k) * b.GetValue(k, j)); + } + } + } + } + + +#if ORTHANC_HAS_MATRIX_PRODUCT_TRANSPOSED_VECTORIZED == 1 + // Computes "C = A*B^T" + class AlignedMatrix::ProductTransposedVectorizedContext : public boost::noncopyable + { + private: + unsigned int vectorizedSteps_; + uint8_t finalSteps_; + + public: + ORTHANC_FORCE_INLINE + ProductTransposedVectorizedContext(const AlignedMatrix& a) + { +#if ORTHANC_HAS_AVX2 == 1 + const unsigned int blockSize = 8; +#elif ORTHANC_HAS_SSE2 == 1 || ORTHANC_HAS_WASM_SIMD == 1 + const unsigned int blockSize = 4; +#else +# error No supported SIMD instruction set +#endif + + vectorizedSteps_ = a.GetColumns() / blockSize; + finalSteps_ = a.GetColumns() - vectorizedSteps_ * blockSize; + } + + ORTHANC_FORCE_INLINE + float Apply(const float* ap, + const float* btp) const noexcept + { + float result; + +#if ORTHANC_HAS_AVX2 == 1 + __m256 accumulator = _mm256_set1_ps(0); + + for (unsigned int k = 0; k < vectorizedSteps_; k++) + { + __m256 a = _mm256_load_ps(ap); + __m256 b = _mm256_load_ps(btp); + //accumulator = _mm256_add_ps(accumulator, _mm256_mul_ps(a, b)); + accumulator = _mm256_fmadd_ps(a, b, accumulator); // Requires the "-mfma" compiler flag + + ap += 8; + btp += 8; + } + + float tmp[8] __attribute__ ((aligned (ORTHANC_MEMORY_ALIGNMENT))); + _mm256_store_ps(tmp, accumulator); + result = tmp[0] + tmp[1] + tmp[2] + tmp[3] + tmp[4] + tmp[5] + tmp[6] + tmp[7]; + +#elif ORTHANC_HAS_SSE2 == 1 + __m128 accumulator = _mm_set1_ps(0); + + for (unsigned int k = 0; k < vectorizedSteps_; k++) + { + __m128 a = _mm_load_ps(ap); + __m128 b = _mm_load_ps(btp); + accumulator = _mm_add_ps(accumulator, _mm_mul_ps(a, b)); + ap += 4; + btp += 4; + } + +#if 1 + float tmp[4] __attribute__ ((aligned (ORTHANC_MEMORY_ALIGNMENT))); + _mm_storeu_ps(tmp, accumulator); + result = tmp[0] + tmp[1] + tmp[2] + tmp[3]; +#else + // This trickier version is theoretically faster, but no much difference in practice + const __m128 sum2 = _mm_add_ps(accumulator, _mm_shuffle_ps(accumulator, accumulator, _MM_SHUFFLE(2, 3, 0, 1))); + const __m128 sum1 = _mm_add_ps(sum2, _mm_shuffle_ps(sum2, sum2, _MM_SHUFFLE(0, 1, 2, 3))); + result = _mm_cvtss_f32(sum1); +#endif + +#elif ORTHANC_HAS_WASM_SIMD == 1 + v128_t accumulator = wasm_f32x4_splat(0); + + for (unsigned int k = 0; k < vectorizedSteps_; k++) + { + v128_t a = wasm_v128_load(ap); + v128_t b = wasm_v128_load(btp); + accumulator = wasm_f32x4_add(accumulator, wasm_f32x4_mul(a, b)); + ap += 4; + btp += 4; + } + +#if 1 + float tmp[4]; + wasm_v128_store(tmp, accumulator); + result = tmp[0] + tmp[1] + tmp[2] + tmp[3]; +#else + const v128_t sum2 = wasm_f32x4_add(accumulator, wasm_i32x4_shuffle(accumulator, accumulator, 2, 3, 0, 0)); + const v128_t sum1 = wasm_f32x4_add(sum2, wasm_i32x4_shuffle(sum2, sum2, 1, 0, 0, 0)); + result = wasm_f32x4_extract_lane(sum1, 0); +#endif + +#else +# error No supported SIMD instruction set +#endif + + for (uint8_t k = 0; k < finalSteps_; k++) + { + result += (*ap) * (*btp); + ap++; + btp++; + } + + return result; + } + }; +#endif + + +#if ORTHANC_HAS_MATRIX_PRODUCT_TRANSPOSED_VECTORIZED == 1 + void AlignedMatrix::ProductTransposedVectorized(AlignedMatrix& c, + const AlignedMatrix& a, + const AlignedMatrix& bt) + { + if (c.GetRows() != a.GetRows() || + c.GetColumns() != bt.GetRows() || + a.GetColumns() != bt.GetColumns()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); + } + + AlignedMatrix::ProductTransposedVectorizedContext context(a); + + const unsigned int M = a.GetRows(); + const unsigned int N = bt.GetRows(); + + const size_t rowSizeA = a.GetPitch() / sizeof(float); + const size_t rowSizeB = bt.GetPitch() / sizeof(float); + + const float* ap = a.GetRowPointer(0); + for (unsigned int i = 0; i < M; i++) + { + float* cp = c.GetRowPointer(i); + + const float* btp = bt.GetRowPointer(0); + for (unsigned int j = 0; j < N; j++, cp++) + { + *cp = context.Apply(ap, btp); + btp += rowSizeB; + } + + ap += rowSizeA; + } + } +#endif +} diff -r 20222330cdf6 -r 22a83fb9dd23 OrthancStone/Sources/Toolbox/AlignedMatrix.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancStone/Sources/Toolbox/AlignedMatrix.h Wed May 17 17:30:52 2023 +0200 @@ -0,0 +1,135 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2022 Osimis S.A., Belgium + * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * . + **/ + + +#pragma once + +#include "SimdIncludes.h" + +#if (ORTHANC_HAS_AVX2 == 1 || ORTHANC_HAS_SSE2 == 1 || ORTHANC_HAS_WASM_SIMD == 1) +# define ORTHANC_HAS_MATRIX_PRODUCT_TRANSPOSED_VECTORIZED 1 +#else +# define ORTHANC_HAS_MATRIX_PRODUCT_TRANSPOSED_VECTORIZED 0 +#endif + + +#include +#include + +namespace OrthancStone +{ + /** + * 2D matrix whose rows are aligned for the largest SIMD + * instructions that are available. + **/ + class AlignedMatrix : public boost::noncopyable + { + private: + class ProductTransposedVectorizedContext; + + unsigned int rows_; + unsigned int cols_; + size_t pitch_; + size_t pitchFloatPointer_; + float* content_; + + void Setup(unsigned int rows, + unsigned int cols); + + public: + AlignedMatrix(unsigned int rows, + unsigned int cols) + { + Setup(rows, cols); + } + + ~AlignedMatrix(); + + unsigned int GetRows() const + { + return rows_; + } + + unsigned int GetColumns() const + { + return cols_; + } + + unsigned int GetPitch() const + { + return pitch_; + } + + float* GetRowPointer(unsigned int row) + { + assert(row < rows_); + return content_ + row * pitchFloatPointer_; + } + + const float* GetRowPointer(unsigned int row) const + { + assert(row < rows_); + return content_ + row * pitchFloatPointer_; + } + + size_t GetIndex(unsigned int row, + unsigned int col) const + { + assert(row < rows_ && col < cols_); + return row * pitchFloatPointer_ + col; + } + + float GetValue(unsigned int row, + unsigned int col) const + { + return content_[GetIndex(row, col)]; + } + + void SetValue(unsigned int row, + unsigned int col, + float value) const + { + content_[GetIndex(row, col)] = value; + } + + void AddValue(unsigned int row, + unsigned int col, + float value) + { + content_[GetIndex(row, col)] += value; + } + + void FillZeros(); + + // Computes "C = A * B" without SIMD operations + static void ProductPlain(AlignedMatrix& c, + const AlignedMatrix& a, + const AlignedMatrix& b); + +#if ORTHANC_HAS_MATRIX_PRODUCT_TRANSPOSED_VECTORIZED == 1 + // Computes "C = A * B^T" using SIMD operations + static void ProductTransposedVectorized(AlignedMatrix& c, + const AlignedMatrix& a, + const AlignedMatrix& bt); +#endif + }; +} diff -r 20222330cdf6 -r 22a83fb9dd23 OrthancStone/Sources/Toolbox/SimdIncludes.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancStone/Sources/Toolbox/SimdIncludes.h Wed May 17 17:30:52 2023 +0200 @@ -0,0 +1,57 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2022 Osimis S.A., Belgium + * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * . + **/ + + +#pragma once + +#if defined(__EMSCRIPTEN__) +# include +# include +#else +# include // portable to all x86 compilers +#endif + +#if __AVX2__ == 1 +# define ORTHANC_HAS_AVX2 1 +# define ORTHANC_HAS_SSE2 1 +# define ORTHANC_HAS_WASM_SIMD 0 +# define ORTHANC_MEMORY_ALIGNMENT 32 +#elif __SSE2__ == 1 +# define ORTHANC_HAS_AVX2 0 +# define ORTHANC_HAS_SSE2 1 +# define ORTHANC_HAS_WASM_SIMD 0 +# define ORTHANC_MEMORY_ALIGNMENT 16 +#elif defined(__EMSCRIPTEN__) +# define ORTHANC_HAS_AVX2 0 +# define ORTHANC_HAS_SSE2 0 +# define ORTHANC_HAS_WASM_SIMD 1 +# define ORTHANC_MEMORY_ALIGNMENT 16 +#elif defined(_MSC_VER) +# if _M_IX86_FP >= 2 // https://stackoverflow.com/a/18563988 +# define ORTHANC_HAS_AVX2 0 +# define ORTHANC_HAS_SSE2 0 +# define ORTHANC_HAS_WASM_SIMD 1 +# define ORTHANC_MEMORY_ALIGNMENT 16 +# endif +#else +# define ORTHANC_MEMORY_ALIGNMENT 8 +#endif diff -r 20222330cdf6 -r 22a83fb9dd23 OrthancStone/Sources/Toolbox/TimerLogger.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancStone/Sources/Toolbox/TimerLogger.cpp Wed May 17 17:30:52 2023 +0200 @@ -0,0 +1,53 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2022 Osimis S.A., Belgium + * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * . + **/ + + +#include "TimerLogger.h" + +#include + + +namespace OrthancStone +{ + TimerLogger::TimerLogger(const std::string& name) : + name_(name) + { +#if defined(__EMSCRIPTEN__) + start_ = emscripten_get_now(); +#else + start_ = boost::posix_time::microsec_clock::universal_time(); +#endif + } + + + TimerLogger::~TimerLogger() + { +#if defined(__EMSCRIPTEN__) + int elapsed = static_cast(round(emscripten_get_now() - start_)); +#else + const boost::posix_time::ptime end = boost::posix_time::microsec_clock::universal_time(); + int elapsed = (end - start_).total_milliseconds(); +#endif + + LOG(WARNING) << name_ << " - Elapsed time: " << elapsed << "ms"; + } +} diff -r 20222330cdf6 -r 22a83fb9dd23 OrthancStone/Sources/Toolbox/TimerLogger.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancStone/Sources/Toolbox/TimerLogger.h Wed May 17 17:30:52 2023 +0200 @@ -0,0 +1,54 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2022 Osimis S.A., Belgium + * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * . + **/ + + +#pragma once + +#include +#include + +#if defined(__EMSCRIPTEN__) +# include +#else +# include +#endif + + +namespace OrthancStone +{ + class TimerLogger : public boost::noncopyable + { + private: + std::string name_; + +#if defined(__EMSCRIPTEN__) + double start_; +#else + boost::posix_time::ptime start_; +#endif + + public: + TimerLogger(const std::string& name); + + ~TimerLogger(); + }; +}