diff --git a/cuBQL/builder/omp.h b/cuBQL/builder/omp.h index 17ba4c2..d8764cb 100644 --- a/cuBQL/builder/omp.h +++ b/cuBQL/builder/omp.h @@ -11,6 +11,10 @@ namespace cuBQL { void refit(BinaryBVH &bvh, const box_t *boxes, Context *ctx); + + template + void freeBVH(BinaryBVH &bvh, + Context *ctx); } } diff --git a/cuBQL/builder/omp/AtomicBox.h b/cuBQL/builder/omp/AtomicBox.h index 9ffac06..0bb5f1e 100644 --- a/cuBQL/builder/omp/AtomicBox.h +++ b/cuBQL/builder/omp/AtomicBox.h @@ -60,6 +60,42 @@ namespace cuBQL { #endif } + /*! iw - note: this implementation of atomic min/max via atomic + compare-exchange (CAS); which is cetainly not optimal on any + sort of modern GPU - but it works in any C++-21 compliant + compiler, so it's what we do for now */ + inline void atomic_min(double *ptr, double value) + { +#ifdef __NVCOMPILER +# if 1 + double &mem = *ptr; + if (mem <= value) return; + while (1) { + double wasBefore; +#pragma omp atomic capture + { wasBefore = mem; mem = value; } + if (wasBefore >= value) break; + value = wasBefore; + } +# else + double current = *(volatile double *)ptr; + while (current > value) { + bool wasChanged + = ((std::atomic*)ptr) + ->compare_exchange_weak((long long int&)current,(long long int&)value); + if (wasChanged) break; + } +# endif +#else + double &x = *ptr; +#pragma omp atomic compare + if (x > value) { x = value; } +// double t; +// #pragma omp atomic capture +// { t = *ptr; *ptr = std::min(t,value); } +#endif + } + /*! iw - note: this implementation of atomic min/max via atomic compare-exchange (CAS); which is cetainly not optimal on any sort of modern GPU - but it works in any C++-21 compliant @@ -96,6 +132,42 @@ namespace cuBQL { #endif } + /*! iw - note: this implementation of atomic min/max via atomic + compare-exchange (CAS); which is cetainly not optimal on any + sort of modern GPU - but it works in any C++-21 compliant + compiler, so it's what we do for now */ + inline void atomic_max(double *ptr, double value) + { +#ifdef __NVCOMPILER +# if 1 + double &mem = *ptr; + if (mem >= value) return; + while (1) { + double wasBefore; +#pragma omp atomic capture + { wasBefore = mem; mem = value; } + if (wasBefore <= value) break; + value = wasBefore; + } +# else + double current = *(volatile double *)ptr; + while (current < value) { + bool wasChanged + = ((std::atomic*)ptr) + ->compare_exchange_weak((long long int&)current,(long long int&)value); + if (wasChanged) break; + } +# endif +#else + double &x = *ptr; +#pragma omp atomic compare + if (x < value) { x = value; } + // double t; +// #pragma omp atomic capture +// { t = *ptr; *ptr = std::max(t,value); } +#endif + } + template inline void v_atomic_min(vec_t *ptr, vec_t v); template diff --git a/cuBQL/builder/omp/spatialMedian.h b/cuBQL/builder/omp/spatialMedian.h index 5cca265..a0b7099 100644 --- a/cuBQL/builder/omp/spatialMedian.h +++ b/cuBQL/builder/omp/spatialMedian.h @@ -423,6 +423,15 @@ namespace cuBQL { cuBQL::omp::refit(bvh,boxes,ctx); } + template + void freeBVH(BinaryBVH &bvh, + Context *ctx) + { + ctx->free(bvh.primIDs); + ctx->free(bvh.nodes); + bvh.primIDs = 0; + } + } template