diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cf176b2..8d47dba 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -17,6 +17,9 @@ set( itkCudaImageFromImageFilterTest.cxx itkCudaImageToImageFilterTest.cxx itkCudaMemoryProbeTest.cxx + itkCudaDataManagerDirtyFlagTest.cxx + itkCudaDataManagerReleaseFreeTest.cxx + itkCudaImageRegionGraftTest.cxx ) createtestdriver(CudaCommon "${CudaCommon-Test_LIBRARIES}" "${CudaCommonTests}") @@ -41,6 +44,21 @@ itk_add_test(NAME itkCudaMemoryProbeTest itkCudaMemoryProbeTest ) +itk_add_test(NAME itkCudaDataManagerDirtyFlagTest + COMMAND CudaCommonTestDriver + itkCudaDataManagerDirtyFlagTest +) + +itk_add_test(NAME itkCudaDataManagerReleaseFreeTest + COMMAND CudaCommonTestDriver + itkCudaDataManagerReleaseFreeTest +) + +itk_add_test(NAME itkCudaImageRegionGraftTest + COMMAND CudaCommonTestDriver + itkCudaImageRegionGraftTest +) + if(ITK_WRAP_PYTHON) itk_python_add_test(NAME itkCudaImageFromImagePythonTest COMMAND itkCudaImageFromImageTest.py diff --git a/test/itkCudaDataManagerDirtyFlagTest.cxx b/test/itkCudaDataManagerDirtyFlagTest.cxx new file mode 100644 index 0000000..4755ad5 --- /dev/null +++ b/test/itkCudaDataManagerDirtyFlagTest.cxx @@ -0,0 +1,77 @@ +/*========================================================================= + * + * Copyright NumFOCUS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#include "itkCudaDataManager.h" +#include "itkTestingMacros.h" +#include +#include + +int +itkCudaDataManagerDirtyFlagTest(int, char *[]) +{ + constexpr size_t BUFFER_SIZE = 256 * sizeof(float); + + auto mgr = itk::CudaDataManager::New(); + mgr->SetBufferSize(BUFFER_SIZE); + mgr->Allocate(); + auto * cpuBuf = new float[256]; + mgr->SetCPUBufferPointer(cpuBuf); + + // Both-dirty error in Update + mgr->SetCPUDirtyFlag(true); + mgr->SetGPUDirtyFlag(true); + ITK_TRY_EXPECT_EXCEPTION(mgr->Update()); + + // Update with GPU dirty only: re-allocates GPU buffer and copies CPU→GPU + mgr->SetGPUDirtyFlag(false); + mgr->SetCPUDirtyFlag(false); + for (int i = 0; i < 256; ++i) + cpuBuf[i] = static_cast(i); + mgr->Update(); // sync both — GPU now holds {0,1,2,...} + mgr->SetGPUDirtyFlag(true); // frees GPU buffer + mgr->SetCPUDirtyFlag(false); + mgr->Update(); + if (std::abs(cpuBuf[0] - 0.0f) >= 1e-6f) + { + std::cerr << "CPU buffer should be unchanged after CPU→GPU copy" << std::endl; + delete[] cpuBuf; + return EXIT_FAILURE; + } + + // Update with CPU dirty only: copies GPU→CPU + mgr->SetCPUDirtyFlag(false); + mgr->SetGPUDirtyFlag(false); + for (int i = 0; i < 256; ++i) + cpuBuf[i] = static_cast(i); + mgr->Update(); // sync both — GPU now holds {0,1,2,...} + for (int i = 0; i < 256; ++i) + cpuBuf[i] = 99.0f; // make CPU stale + mgr->SetCPUDirtyFlag(true); + mgr->SetGPUDirtyFlag(false); + mgr->Update(); + if (std::abs(cpuBuf[0] - 0.0f) >= 1e-6f) + { + std::cerr << "CPU buffer should have GPU values after GPU→CPU copy" << std::endl; + delete[] cpuBuf; + return EXIT_FAILURE; + } + delete[] cpuBuf; + + std::cout << "CudaDataManagerDirtyFlagTest passed" << std::endl; + return EXIT_SUCCESS; +} diff --git a/test/itkCudaDataManagerReleaseFreeTest.cxx b/test/itkCudaDataManagerReleaseFreeTest.cxx new file mode 100644 index 0000000..00392dc --- /dev/null +++ b/test/itkCudaDataManagerReleaseFreeTest.cxx @@ -0,0 +1,53 @@ +/*========================================================================= + * + * Copyright NumFOCUS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#include "itkCudaDataManager.h" +#include + +int +itkCudaDataManagerReleaseFreeTest(int, char *[]) +{ + constexpr size_t BUFFER_SIZE = 256 * sizeof(float); + + // SetGPUBufferDirty frees GPU memory when release is true (default) + auto mgr = itk::CudaDataManager::New(); + mgr->SetBufferSize(BUFFER_SIZE); + mgr->Allocate(); + mgr->SetGPUBufferDirty(); + if (mgr->GetGPUBufferSize() != 0) + { + std::cerr << "GPU buffer should be freed after SetGPUBufferDirty" << std::endl; + return EXIT_FAILURE; + } + + // SetGPUBufferDirty does not free when release is false + auto mgr2 = itk::CudaDataManager::New(); + mgr2->SetReleaseDirtyGPUBuffer(false); + mgr2->SetBufferSize(BUFFER_SIZE); + mgr2->Allocate(); + size_t before = mgr2->GetGPUBufferSize(); + mgr2->SetGPUBufferDirty(); + if (mgr2->GetGPUBufferSize() != before) + { + std::cerr << "GPU buffer should not be freed when release is false" << std::endl; + return EXIT_FAILURE; + } + + std::cout << "CudaDataManagerReleaseFreeTest passed" << std::endl; + return EXIT_SUCCESS; +} diff --git a/test/itkCudaImageRegionGraftTest.cxx b/test/itkCudaImageRegionGraftTest.cxx new file mode 100644 index 0000000..23088eb --- /dev/null +++ b/test/itkCudaImageRegionGraftTest.cxx @@ -0,0 +1,43 @@ +/*========================================================================= + * + * Copyright NumFOCUS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#include "itkCudaImage.h" +#include + +using CudaImage2f = itk::CudaImage; + +int +itkCudaImageRegionGraftTest(int, char *[]) +{ + auto img = CudaImage2f::New(); + img->SetRegions(itk::MakeSize(32, 32)); + img->Allocate(); + + // Initialize creates a new DataManager + auto * dmBefore = img->GetCudaDataManager().GetPointer(); + img->Initialize(); + auto * dmAfter = img->GetCudaDataManager().GetPointer(); + if (dmBefore == dmAfter) + { + std::cerr << "Initialize should create a new DataManager" << std::endl; + return EXIT_FAILURE; + } + + std::cout << "CudaImageRegionGraftTest passed" << std::endl; + return EXIT_SUCCESS; +}