From 68bc885200617b416743b607fe3a6833636d0cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20G=C3=BCnther?= Date: Wed, 15 Sep 2021 07:57:18 +0200 Subject: [PATCH 01/22] Bump version --- cmake/ospray_version.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/ospray_version.cmake b/cmake/ospray_version.cmake index 2aab270de..cb1bdddf9 100644 --- a/cmake/ospray_version.cmake +++ b/cmake/ospray_version.cmake @@ -3,7 +3,7 @@ set(OSPRAY_VERSION_MAJOR 2) set(OSPRAY_VERSION_MINOR 7) -set(OSPRAY_VERSION_PATCH 0) +set(OSPRAY_VERSION_PATCH 1) set(OSPRAY_SOVERSION 2) set(OSPRAY_VERSION_GITHASH 0) set(OSPRAY_VERSION_NOTE "") From 54007424b617a22aac9a38f47d560a697b657318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20G=C3=BCnther?= Date: Mon, 13 Sep 2021 03:06:18 +0200 Subject: [PATCH 02/22] Fix typo in OSPRAY_APPS_BENCHMARK, closes #494 --- apps/common/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/common/CMakeLists.txt b/apps/common/CMakeLists.txt index 52eb78855..5094b5c26 100644 --- a/apps/common/CMakeLists.txt +++ b/apps/common/CMakeLists.txt @@ -1,7 +1,7 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009-2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 -if (NOT OSPRAY_APPS_BENCHARK AND +if (NOT OSPRAY_APPS_BENCHMARK AND NOT OSPRAY_APPS_EXAMPLES AND NOT OSPRAY_APPS_TESTING) return() From 1da53849313fb735b25981a0f5f4908a536ed79a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20G=C3=BCnther?= Date: Mon, 13 Sep 2021 03:09:40 +0200 Subject: [PATCH 03/22] MPI Tutorials need ImGui and thus OSPRAY_APPS_EXAMPLES --- CHANGELOG.md | 4 ++++ modules/mpi/CMakeLists.txt | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9962aac5..e43d0ddf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ Version History --------------- +### Changes in v2.7.1: + +- Fix CMake variables and logic + ### Changes in v2.7.0: - Add support for transformation and camera Motion Blur (with the path diff --git a/modules/mpi/CMakeLists.txt b/modules/mpi/CMakeLists.txt index 39b97856e..e077741b9 100644 --- a/modules/mpi/CMakeLists.txt +++ b/modules/mpi/CMakeLists.txt @@ -13,7 +13,7 @@ cmake_dependent_option( OSPRAY_MPI_BUILD_TUTORIALS "Enable MPI module sample apps" ON - "OSPRAY_MODULE_MPI;OSPRAY_ENABLE_APPS" + "OSPRAY_MODULE_MPI;OSPRAY_ENABLE_APPS;OSPRAY_APPS_EXAMPLES" OFF ) From d7824bb7d14acc259e7e33b3e43f2fc7762902b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20G=C3=BCnther?= Date: Tue, 31 Aug 2021 05:19:06 +0200 Subject: [PATCH 04/22] Guard against empty value ranges for VKL iterator --- CHANGELOG.md | 1 + ospray/volume/VolumetricModel.cpp | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e43d0ddf8..43604889a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Version History ### Changes in v2.7.1: - Fix CMake variables and logic +- Fix crash when transferfunction.opacity = 0 ### Changes in v2.7.0: diff --git a/ospray/volume/VolumetricModel.cpp b/ospray/volume/VolumetricModel.cpp index 4145387ab..20f2a2b61 100644 --- a/ospray/volume/VolumetricModel.cpp +++ b/ospray/volume/VolumetricModel.cpp @@ -56,6 +56,13 @@ void VolumetricModel::commit() vklIntervalContext = vklNewIntervalIteratorContext(volume->vklSampler); std::vector valueRanges = transferFunction->getPositiveOpacityValueRanges(); + if (valueRanges.empty()) { + // volume made completely transparent and could be removed, which is + // awkward here + // set an "empty" interesting value range instead, which will lead to a + // quick out during volume interation + valueRanges.push_back(range1f(neg_inf, neg_inf)); + } VKLData valueRangeData = vklNewData( volume->vklDevice, valueRanges.size(), VKL_BOX1F, valueRanges.data()); vklSetData(vklIntervalContext, "valueRanges", valueRangeData); From 5d88a8cd84268c07ec7632bd6a4a2e71f5c377b6 Mon Sep 17 00:00:00 2001 From: Trevor Thomson Date: Tue, 21 Sep 2021 14:25:26 +0000 Subject: [PATCH 05/22] Include secondary dependencies via -I instead of -isystem. --- scripts/superbuild/CMakeLists.txt | 11 +++++++++++ scripts/superbuild/build_ospray.cmake | 1 + scripts/superbuild/dependencies/dep_embree.cmake | 1 + scripts/superbuild/dependencies/dep_oidn.cmake | 1 + scripts/superbuild/dependencies/dep_openvkl.cmake | 1 + scripts/superbuild/dependencies/dep_rkcommon.cmake | 1 + 6 files changed, 16 insertions(+) diff --git a/scripts/superbuild/CMakeLists.txt b/scripts/superbuild/CMakeLists.txt index 2b71d811c..db05bba39 100644 --- a/scripts/superbuild/CMakeLists.txt +++ b/scripts/superbuild/CMakeLists.txt @@ -45,6 +45,17 @@ include(CMakeDependentOption) ## Superbuild options ## +## Include imported target headers with -I rather than -isystem to ensure they're +## included prior to any CPATH headers +cmake_dependent_option( + CMAKE_NO_SYSTEM_FROM_IMPORTED + "Disable -isystem for dependency include paths" + ON + "NOT BUILD_OSPRAY_CI_EXTRAS" + OFF +) +mark_as_advanced(CMAKE_NO_SYSTEM_FROM_IMPORTED) + ProcessorCount(PROCESSOR_COUNT) if(NOT PROCESSOR_COUNT EQUAL 0) diff --git a/scripts/superbuild/build_ospray.cmake b/scripts/superbuild/build_ospray.cmake index d9e048251..1dc5d5165 100644 --- a/scripts/superbuild/build_ospray.cmake +++ b/scripts/superbuild/build_ospray.cmake @@ -41,6 +41,7 @@ ExternalProject_Add(${COMPONENT_NAME} -DOSPRAY_MODULE_MULTIDEVICE=${OSPRAY_MODULE_MULTIDEVICE} $<$:-DISPC_EXECUTABLE=${ISPC_PATH}> $<$:-DRKCOMMON_TBB_ROOT=${TBB_PATH}> + -DCMAKE_NO_SYSTEM_FROM_IMPORTED=${CMAKE_NO_SYSTEM_FROM_IMPORTED} -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} BUILD_COMMAND ${DEFAULT_BUILD_COMMAND} diff --git a/scripts/superbuild/dependencies/dep_embree.cmake b/scripts/superbuild/dependencies/dep_embree.cmake index 8d4211fcc..a6aeac84f 100644 --- a/scripts/superbuild/dependencies/dep_embree.cmake +++ b/scripts/superbuild/dependencies/dep_embree.cmake @@ -34,6 +34,7 @@ if (BUILD_EMBREE_FROM_SOURCE) -DCMAKE_INSTALL_BINDIR=${CMAKE_INSTALL_BINDIR} $<$:-DEMBREE_TBB_ROOT=${TBB_PATH}> $<$:-DEMBREE_ISPC_EXECUTABLE=${ISPC_PATH}> + -DCMAKE_NO_SYSTEM_FROM_IMPORTED=${CMAKE_NO_SYSTEM_FROM_IMPORTED} -DCMAKE_BUILD_TYPE=${DEPENDENCIES_BUILD_TYPE} -DEMBREE_TUTORIALS=OFF -DBUILD_TESTING=OFF diff --git a/scripts/superbuild/dependencies/dep_oidn.cmake b/scripts/superbuild/dependencies/dep_oidn.cmake index 6393fcd40..2f72e9268 100644 --- a/scripts/superbuild/dependencies/dep_oidn.cmake +++ b/scripts/superbuild/dependencies/dep_oidn.cmake @@ -31,6 +31,7 @@ if (BUILD_OIDN_FROM_SOURCE) -DCMAKE_INSTALL_BINDIR=${CMAKE_INSTALL_BINDIR} $<$:-DTBB_ROOT=${TBB_PATH}> $<$:-DISPC_EXECUTABLE=${ISPC_PATH}> + -DCMAKE_NO_SYSTEM_FROM_IMPORTED=${CMAKE_NO_SYSTEM_FROM_IMPORTED} -DCMAKE_BUILD_TYPE=${DEPENDENCIES_BUILD_TYPE} -DOIDN_APPS=OFF -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} diff --git a/scripts/superbuild/dependencies/dep_openvkl.cmake b/scripts/superbuild/dependencies/dep_openvkl.cmake index 41977f48d..f2a9e540a 100644 --- a/scripts/superbuild/dependencies/dep_openvkl.cmake +++ b/scripts/superbuild/dependencies/dep_openvkl.cmake @@ -35,6 +35,7 @@ ExternalProject_Add(${COMPONENT_NAME} -DCMAKE_BUILD_TYPE=${DEPENDENCIES_BUILD_TYPE} $<$:-DRKCOMMON_TBB_ROOT=${TBB_PATH}> $<$:-DISPC_EXECUTABLE=${ISPC_PATH}> + -DCMAKE_NO_SYSTEM_FROM_IMPORTED=${CMAKE_NO_SYSTEM_FROM_IMPORTED} -DBUILD_BENCHMARKS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF diff --git a/scripts/superbuild/dependencies/dep_rkcommon.cmake b/scripts/superbuild/dependencies/dep_rkcommon.cmake index 9b9656c9c..e1e78093b 100644 --- a/scripts/superbuild/dependencies/dep_rkcommon.cmake +++ b/scripts/superbuild/dependencies/dep_rkcommon.cmake @@ -33,6 +33,7 @@ ExternalProject_Add(${COMPONENT_NAME} -DINSTALL_DEPS=OFF -DBUILD_TESTING=OFF $<$:-DRKCOMMON_TBB_ROOT=${TBB_PATH}> + -DCMAKE_NO_SYSTEM_FROM_IMPORTED=${CMAKE_NO_SYSTEM_FROM_IMPORTED} -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} BUILD_COMMAND ${DEFAULT_BUILD_COMMAND} From 1fd5b955f15a0f8ef9ecb3e9375490d258424043 Mon Sep 17 00:00:00 2001 From: Will Usher Date: Fri, 10 Sep 2021 17:06:24 -0700 Subject: [PATCH 06/22] Use Embree + Boxes geometry to compute accurate visibility info Remove leftover region ID: no longer needed, user does not specify anymore. after merging same regions simply based on testing if their bounds were equal, the region IDs were no longer really needed to distinguish regions. The ID just storing the index of the region in the allRegions array and was no longer needed. --- .../mpi/ospray/common/DistributedWorld.cpp | 101 ++++------- modules/mpi/ospray/common/DistributedWorld.h | 41 +---- modules/mpi/ospray/common/DistributedWorld.ih | 13 +- .../mpi/ospray/common/DistributedWorld.ispc | 11 +- .../ospray/render/DistributedLoadBalancer.cpp | 168 +++++++----------- .../AlphaCompositeTileOperation.cpp | 16 +- .../distributed/DistributedRaycast.ispc | 14 +- .../distributed/DistributedRenderer.cpp | 2 +- .../render/distributed/DistributedRenderer.h | 4 +- .../render/distributed/DistributedRenderer.ih | 6 +- .../distributed/DistributedRenderer.ispc | 51 ++++-- ospray/camera/Camera.cpp | 13 +- ospray/camera/Camera.h | 14 -- ospray/camera/PerspectiveCamera.cpp | 27 +-- ospray/camera/PerspectiveCamera.h | 15 +- ospray/camera/PerspectiveCamera.ispc | 97 +++++++++- ospray/common/World.h | 2 +- 17 files changed, 285 insertions(+), 310 deletions(-) diff --git a/modules/mpi/ospray/common/DistributedWorld.cpp b/modules/mpi/ospray/common/DistributedWorld.cpp index e55ca6627..4dfb2a474 100644 --- a/modules/mpi/ospray/common/DistributedWorld.cpp +++ b/modules/mpi/ospray/common/DistributedWorld.cpp @@ -16,55 +16,6 @@ namespace mpi { using namespace rkcommon; -void RegionScreenBounds::extend(const vec3f &p) -{ - if (p.z < 0) { - bounds = box2f(vec2f(0), vec2f(1)); - } else { - bounds.extend(vec2f(p.x * sign(p.z), p.y * sign(p.z))); - bounds.lower.x = clamp(bounds.lower.x); - bounds.upper.x = clamp(bounds.upper.x); - bounds.lower.y = clamp(bounds.lower.y); - bounds.upper.y = clamp(bounds.upper.y); - } -} - -Region::Region(const box3f &bounds, int id) : bounds(bounds), id(id) {} - -RegionScreenBounds Region::project(const Camera *camera) const -{ - RegionScreenBounds screen; - for (int k = 0; k < 2; ++k) { - vec3f pt; - pt.z = k == 0 ? bounds.lower.z : bounds.upper.z; - - for (int j = 0; j < 2; ++j) { - pt.y = j == 0 ? bounds.lower.y : bounds.upper.y; - - for (int i = 0; i < 2; ++i) { - pt.x = i == 0 ? bounds.lower.x : bounds.upper.x; - - ProjectedPoint proj = camera->projectPoint(pt); - screen.extend(proj.screenPos); - screen.depth = std::max(length(pt - camera->pos), screen.depth); - } - } - } - return screen; -} - -bool Region::operator==(const Region &b) const -{ - // TODO: Do we want users to specify the ID explitly? Or should we just - // assume that two objects with the same bounds have the same id? - return id == b.id; -} - -bool Region::operator<(const Region &b) const -{ - return id < b.id; -} - DistributedWorld::DistributedWorld() : mpiGroup(mpicommon::worker.dup()) { managedObjectType = OSP_WORLD; @@ -79,8 +30,8 @@ DistributedWorld::~DistributedWorld() box3f DistributedWorld::getBounds() const { box3f bounds; - for (const auto &r : allRegions) { - bounds.extend(r.bounds); + for (const auto &b : allRegions) { + bounds.extend(b); } return bounds; } @@ -129,16 +80,41 @@ void DistributedWorld::commit() // to the others to build the distributed world std::sort( myRegions.begin(), myRegions.end(), [](const box3f &a, const box3f &b) { - std::less op; - return op(a.lower, b.lower) - || (a.lower == b.lower && op(a.upper, b.upper)); + return a.lower < b.lower || (a.lower == b.lower && a.upper < b.upper); }); auto last = std::unique(myRegions.begin(), myRegions.end()); myRegions.erase(last, myRegions.end()); exchangeRegions(); - ispc::DistributedWorld_set(getIE(), allRegions.data(), allRegions.size()); + if (regionScene) { + rtcReleaseScene(regionScene); + regionScene = nullptr; + } + + if (allRegions.size() > 0) { + // Setup the boxes geometry which we'll use to leverage Embree for + // accurately determining region visibility + Data* allRegionsData = new Data(allRegions.data(), + OSP_BOX3F, + vec3ul(allRegions.size(), 1, 1), + vec3l(0)); + regionGeometry = new Boxes(); + regionGeometry->setParam("box", (ManagedObject *)allRegionsData); + regionGeometry->setDevice(embreeDevice); + regionGeometry->commit(); + + regionScene = rtcNewScene(embreeDevice); + rtcAttachGeometry(regionScene, regionGeometry->embreeGeometry); + rtcSetSceneFlags(regionScene, RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION); + rtcCommitScene(regionScene); + + regionGeometry->refDec(); + allRegionsData->refDec(); + } + + ispc::DistributedWorld_set( + getIE(), allRegions.data(), allRegions.size(), regionScene); } void DistributedWorld::exchangeRegions() @@ -160,11 +136,11 @@ void DistributedWorld::exchangeRegions() for (const auto &b : myRegions) { auto fnd = std::find_if(allRegions.begin(), allRegions.end(), - [&](const Region &r) { return r.bounds == b; }); + [&](const box3f &r) { return r == b; }); int id = -1; if (fnd == allRegions.end()) { id = allRegions.size(); - allRegions.push_back(Region(b, id)); + allRegions.push_back(b); } else { id = std::distance(allRegions.begin(), fnd); } @@ -189,11 +165,11 @@ void DistributedWorld::exchangeRegions() for (const auto &b : recv) { auto fnd = std::find_if(allRegions.begin(), allRegions.end(), - [&](const Region &r) { return r.bounds == b; }); + [&](const box3f &r) { return r == b; }); int id = -1; if (fnd == allRegions.end()) { id = allRegions.size(); - allRegions.push_back(Region(b, id)); + allRegions.push_back(b); } else { id = std::distance(allRegions.begin(), fnd); } @@ -230,10 +206,3 @@ void DistributedWorld::exchangeRegions() } // namespace mpi } // namespace ospray -using namespace ospray::mpi; - -std::ostream &operator<<(std::ostream &os, const Region &r) -{ - os << "Region { id = " << r.id << ", bounds = " << r.bounds << " }"; - return os; -} diff --git a/modules/mpi/ospray/common/DistributedWorld.h b/modules/mpi/ospray/common/DistributedWorld.h index 7a3ef2a69..c9a28ccb6 100644 --- a/modules/mpi/ospray/common/DistributedWorld.h +++ b/modules/mpi/ospray/common/DistributedWorld.h @@ -9,45 +9,12 @@ #include "common/MPICommon.h" #include "common/World.h" #include "embree3/rtcore.h" +#include "geometry/Boxes.h" #include "rkcommon/math/box.h" namespace ospray { namespace mpi { -// The bounds of a region projected onto the image plane -struct RegionScreenBounds -{ - rkcommon::math::box2f bounds; - // The max-depth of the box, for sorting the compositing order - float depth = -std::numeric_limits::infinity(); - - // Extend the screen-space bounds to include p.xy - // TODO WILL depth is treated separately by just getting the projection - // along the camera view axis. So either we need the camera here, or - // should just take the z val to only tell us if we should fill the whole - // window. - void extend(const rkcommon::math::vec3f &p); -}; - -/* A region is defined by its bounds and an ID, which allows us to group - * ranks with the same region and switch to do image-parallel rendering - */ -struct Region -{ - rkcommon::math::box3f bounds; - int id = -1; - - Region() = default; - Region(const rkcommon::math::box3f &bounds, int id); - - RegionScreenBounds project(const Camera *camera) const; - - // Compiler can't find these when I define them outside in the public - // namespace!???? - bool operator==(const Region &b) const; - bool operator<(const Region &b) const; -}; - /* The distributed world provides the renderer with the view of the local * and distributed objects in the entire scene across the cluster. For * remote objects we only store their bounds and the ID of the rank which @@ -83,12 +50,14 @@ struct DistributedWorld : public World std::vector myRegions; // The global list of unique regions across all nodes, (including this // one), sorted by region id. - std::vector allRegions; + std::vector allRegions; std::vector myRegionIds; // The ranks which own each region std::unordered_map> regionOwners; + + Ref regionGeometry; + RTCScene regionScene = nullptr; }; } // namespace mpi } // namespace ospray -std::ostream &operator<<(std::ostream &os, const ospray::mpi::Region &r); diff --git a/modules/mpi/ospray/common/DistributedWorld.ih b/modules/mpi/ospray/common/DistributedWorld.ih index 415ac4620..991e93475 100644 --- a/modules/mpi/ospray/common/DistributedWorld.ih +++ b/modules/mpi/ospray/common/DistributedWorld.ih @@ -1,20 +1,15 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ospray/common/World.ih" -struct Region -{ - box3f bounds; - int id; -}; - struct DistributedWorld { World super; - uniform Region *uniform regions; - uniform int numRegions; + box3f *uniform regions; + int numRegions; + RTCScene regionScene; }; diff --git a/modules/mpi/ospray/common/DistributedWorld.ispc b/modules/mpi/ospray/common/DistributedWorld.ispc index b2935227e..c78eedf2c 100644 --- a/modules/mpi/ospray/common/DistributedWorld.ispc +++ b/modules/mpi/ospray/common/DistributedWorld.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "DistributedWorld.ih" @@ -11,10 +11,13 @@ export void *uniform DistributedWorld_create(void *uniform cppE) return (void *uniform)world; } -export void DistributedWorld_set( - void *uniform _world, void *uniform _regions, uniform int numRegions) +export void DistributedWorld_set(void *uniform _world, + void *uniform _regions, + uniform int numRegions, + void *uniform _regionScene) { DistributedWorld *uniform world = (DistributedWorld * uniform) _world; - world->regions = (uniform Region * uniform) _regions; + world->regions = (box3f * uniform) _regions; world->numRegions = numRegions; + world->regionScene = (RTCScene)_regionScene; } diff --git a/modules/mpi/ospray/render/DistributedLoadBalancer.cpp b/modules/mpi/ospray/render/DistributedLoadBalancer.cpp index 0b9abeaa0..577c09811 100644 --- a/modules/mpi/ospray/render/DistributedLoadBalancer.cpp +++ b/modules/mpi/ospray/render/DistributedLoadBalancer.cpp @@ -42,7 +42,9 @@ void Distributed::renderFrame( } } - if (!reinterpret_cast(camera)) { + PerspectiveCamera *perspectiveCamera = + reinterpret_cast(camera); + if (!perspectiveCamera) { throw std::runtime_error( "DistributedRaycastRender only supports PerspectiveCamera"); } @@ -52,75 +54,53 @@ void Distributed::renderFrame( } dfb->startNewFrame(renderer->errorThreshold); - void *perFrameData = renderer->beginFrame(dfb, world); - - const auto fbSize = dfb->getNumPixels(); const size_t numRegions = world->allRegions.size(); - // Do a prepass and project each region's box to the screen to see - // which tiles it touches, and at what depth. - std::multimap regionOrdering; - std::vector projectedRegions( - numRegions, RegionScreenBounds()); - for (size_t i = 0; i < projectedRegions.size(); ++i) { - const auto &r = world->allRegions[i]; - auto &proj = projectedRegions[i]; - if (!r.bounds.empty()) { - proj = r.project(camera); - // Note that these bounds are very conservative, the bounds we - // compute below are much tighter, and better. We just use the depth - // from the projection to sort the tiles later - proj.bounds.lower = - max(proj.bounds.lower * fbSize - TILE_SIZE, vec2f(0.f)); - proj.bounds.upper = - min(proj.bounds.upper * fbSize + TILE_SIZE, vec2f(fbSize - 1.f)); - regionOrdering.insert(std::make_pair(proj.depth, i)); - } else { - proj = RegionScreenBounds(); - proj.depth = std::numeric_limits::infinity(); - regionOrdering.insert( - std::make_pair(std::numeric_limits::infinity(), i)); +#ifdef ENABLE_PROFILING + ProfilingPoint start = ProfilingPoint(); +#endif + std::set tilesForFrame; + for (int i = workerRank(); i < dfb->getTotalTiles(); i += workerSize()) { + const uint32_t tile_y = i / dfb->getNumTiles().x; + const uint32_t tile_x = i - tile_y * dfb->getNumTiles().x; + const vec2i tileID(tile_x, tile_y); + // Skip tiles that have been rendered to satisfactory error level + if (dfb->tileError(tileID) > renderer->errorThreshold) { + tilesForFrame.insert(i); } } - // Compute the sort order for the regions - std::vector sortOrder(numRegions, 0); - int depthIndex = 0; - for (const auto &e : regionOrdering) { - sortOrder[e.second] = depthIndex++; - } + const vec2i numTiles = dfb->getNumTiles(); + const vec2i fbSize = dfb->getNumPixels(); + for (const auto &id : world->myRegionIds) { + const auto &r = world->allRegions[id]; + box3f proj = perspectiveCamera->projectBox(r); + box2f screenRegion(vec2f(proj.lower) * fbSize, vec2f(proj.upper) * fbSize); - // Pre-compute the list of tiles that we actually need to render to, - // so we can get a better thread assignment when doing the real work - // TODO Will: is this going to help much? Going through all the rays - // to do this pre-pass may be too expensive, and instead we want - // to just do something coarser based on the projected regions - std::vector tilesForFrame; - for (const auto ®ion : world->allRegions) { - const auto &projection = projectedRegions[region.id]; - if (projection.bounds.empty() || projection.depth < 0) { + // Pad the region a bit + screenRegion.lower = max(screenRegion.lower - TILE_SIZE, vec2f(0.f)); + screenRegion.upper = min(screenRegion.upper + TILE_SIZE, vec2f(fbSize)); + + // Skip regions that are completely behind the camera + if (proj.upper.z < 0.f) { continue; } - // TODO: Should we push back by a few pixels as well just in case - // for the random sampling? May need to spill +/- a pixel? I'm not - // sure - const vec2i minTile(projection.bounds.lower.x / TILE_SIZE, - projection.bounds.lower.y / TILE_SIZE); - const vec2i numTiles = dfb->getNumTiles(); - const vec2i maxTile( - std::min(std::ceil(projection.bounds.upper.x / TILE_SIZE), - float(numTiles.x)), - std::min(std::ceil(projection.bounds.upper.y / TILE_SIZE), - float(numTiles.y))); - - tilesForFrame.reserve((maxTile.x - minTile.x) * (maxTile.y - minTile.y)); - for (int y = minTile.y; y < maxTile.y; ++y) { - for (int x = minTile.x; x < maxTile.x; ++x) { - // If we share ownership of this region but aren't responsible - // for rendering it to this tile, don't render it. - const size_t tileIndex = size_t(x) + size_t(y) * numTiles.x; - const auto &owners = world->regionOwners[region.id]; + + box2i tileRegion; + tileRegion.lower = screenRegion.lower / TILE_SIZE; + tileRegion.upper = vec2i(std::ceil(screenRegion.upper.x / TILE_SIZE), + std::ceil(screenRegion.upper.y / TILE_SIZE)); + tileRegion.upper = min(tileRegion.upper, numTiles); + for (int y = tileRegion.lower.y; y < tileRegion.upper.y; ++y) { + for (int x = tileRegion.lower.x; x < tileRegion.upper.x; ++x) { + // Skip tiles that have been rendered to satisfactory error level + if (dfb->tileError(vec2i(x, y)) <= renderer->errorThreshold) { + continue; + } + + const int tileIndex = x + y * numTiles.x; + const auto &owners = world->regionOwners[id]; const size_t numRegionOwners = owners.size(); const size_t ownerRank = std::distance(owners.begin(), owners.find(workerRank())); @@ -129,43 +109,24 @@ void Distributed::renderFrame( // the workload. const bool regionTileOwner = (tileIndex % numRegionOwners) == ownerRank; if (regionTileOwner) { - tilesForFrame.push_back(tileIndex); + tilesForFrame.insert(tileIndex); } } } } +#ifdef ENABLE_PROFILING + ProfilingPoint end = ProfilingPoint(); + std::cout << "Initial tile for frame determination " + << elapsedTimeMs(start, end) << "ms\n"; +#endif - // Be sure to include all the tiles that we're the owner for as well, - // in some cases none of our data might project to them. - for (int i = workerRank(); i < dfb->getTotalTiles(); i += workerSize()) { - tilesForFrame.push_back(i); - } - - std::sort(tilesForFrame.begin(), tilesForFrame.end()); - { - // Filter out any duplicate tiles, e.g. we double-count the background - // tile we have to render as the owner and our data projects to the - // same tile. - auto end = std::unique(tilesForFrame.begin(), tilesForFrame.end()); - tilesForFrame.erase(end, tilesForFrame.end()); - - // Filter any tiles which are finished due to reaching the - // error threshold. This should let TBB better allocate threads only - // to tiles that actually need work. - end = std::partition( - tilesForFrame.begin(), tilesForFrame.end(), [&](const int &i) { - const uint32_t tile_y = i / dfb->getNumTiles().x; - const uint32_t tile_x = i - tile_y * dfb->getNumTiles().x; - const vec2i tileID(tile_x, tile_y); - return dfb->tileError(tileID) > renderer->errorThreshold; - }); - tilesForFrame.erase(end, tilesForFrame.end()); - } - - // Render the tiles we've got to do now - tasking::parallel_for(tilesForFrame.size(), [&](size_t taskIndex) { - const int tileIndex = tilesForFrame[taskIndex]; - +#ifdef ENABLE_PROFILING + start = ProfilingPoint(); +#endif + tasking::parallel_for(tilesForFrame.size(), [&](size_t taskId) { + auto tileIter = tilesForFrame.begin(); + std::advance(tileIter, taskId); + const int tileIndex = *tileIter; const uint32_t numTiles_x = static_cast(dfb->getNumTiles().x); const uint32_t tile_y = tileIndex / numTiles_x; const uint32_t tile_x = tileIndex - tile_y * numTiles_x; @@ -217,6 +178,10 @@ void Distributed::renderFrame( myVisibleRegions.push_back(rid); } } + // If none of our regions are visible, we're done + if (myVisibleRegions.empty()) { + return; + } // TODO: Will it really be much benefit to run the regions in parallel // as well? We already are running in parallel on the tiles and the @@ -225,10 +190,10 @@ void Distributed::renderFrame( #define PARALLEL_REGION_RENDERING 1 #if PARALLEL_REGION_RENDERING tasking::parallel_for(myVisibleRegions.size(), [&](size_t vid) { - const size_t i = myVisibleRegions[vid]; + const size_t rid = myVisibleRegions[vid]; Tile __aligned(64) tile(tileID, fbSize, accumID); #else - for (const size_t &i : myVisibleRegions) { + for (const size_t &rid : myVisibleRegions) { Tile &tile = bgtile; #endif tile.generation = 1; @@ -238,8 +203,7 @@ void Distributed::renderFrame( // Note that we do need to double check here, since we could have // multiple shared regions projecting to the same tile, and we // could be the region tile owner for only some of those - const auto ®ion = world->allRegions[i]; - const auto &owners = world->regionOwners[region.id]; + const auto &owners = world->regionOwners[rid]; const size_t numRegionOwners = owners.size(); const size_t ownerRank = std::distance(owners.begin(), owners.find(workerRank())); @@ -249,12 +213,13 @@ void Distributed::renderFrame( renderer->renderRegionToTile(dfb, camera, world, - world->allRegions[i], + world->allRegions[rid], perFrameData, tile, tIdx); }); - tile.sortOrder = sortOrder[region.id]; + // Unused + // tile.sortOrder = sortOrder[rid]; dfb->setTile(tile); } #if PARALLEL_REGION_RENDERING @@ -263,6 +228,11 @@ void Distributed::renderFrame( } #endif }); +#ifdef ENABLE_PROFILING + end = ProfilingPoint(); + std::cout << "Local rendering for frame " << elapsedTimeMs(start, end) + << "ms\n"; +#endif dfb->waitUntilFinished(); renderer->endFrame(dfb, perFrameData); diff --git a/modules/mpi/ospray/render/distributed/AlphaCompositeTileOperation.cpp b/modules/mpi/ospray/render/distributed/AlphaCompositeTileOperation.cpp index 641ce13c7..de3571270 100644 --- a/modules/mpi/ospray/render/distributed/AlphaCompositeTileOperation.cpp +++ b/modules/mpi/ospray/render/distributed/AlphaCompositeTileOperation.cpp @@ -105,12 +105,16 @@ void LiveAlphaCompositeTile::process(const ospray::Tile &tile) if (missingInCurrentGeneration == 0) { // Sort for back-to-front blending - std::sort(bufferedTiles.begin(), - bufferedTiles.end(), - [](const std::unique_ptr &a, - const std::unique_ptr &b) { - return a->tile.sortOrder > b->tile.sortOrder; - }); + // TODO: This is redundant with sortAndBlend. We should actually just do + // this tile level sort, not sorting each pixel + /* + std::sort(bufferedTiles.begin(), + bufferedTiles.end(), + [](const std::unique_ptr &a, + const std::unique_ptr &b) { + return a->tile.sortOrder > b->tile.sortOrder; + }); + */ Tile **tileArray = STACK_BUFFER(Tile *, bufferedTiles.size()); std::transform(bufferedTiles.begin(), diff --git a/modules/mpi/ospray/render/distributed/DistributedRaycast.ispc b/modules/mpi/ospray/render/distributed/DistributedRaycast.ispc index 27d33f8e9..a2582100a 100644 --- a/modules/mpi/ospray/render/distributed/DistributedRaycast.ispc +++ b/modules/mpi/ospray/render/distributed/DistributedRaycast.ispc @@ -23,18 +23,6 @@ struct DistributedRaycastRenderer float volumeSamplingRate; }; -struct RegionInfo -{ - int numRegions; - int currentRegion; - bool computeVisibility; - // TODO: If the IDs are not "array indices" this gets a bit goofed up - // We should probably just remap the IDs when we move to generating them for - // the user - Region *uniform regions; - bool *uniform regionVisible; -}; - // The distributed raycast renderer uses its own volume interval integration // because we want to apply the jitter before offsetting our step size to stay // inside the region, not after. @@ -233,7 +221,7 @@ vec4f DRR_shadeSurface(const DistributedRaycastRenderer *uniform self, void DRR_renderRegionSample(DistributedRenderer *uniform _self, FrameBuffer *uniform fb, DistributedWorld *uniform world, - const Region *uniform region, + const box3f *uniform region, const vec2f ®ionInterval, void *uniform perFrameData, varying ScreenSample &sample) diff --git a/modules/mpi/ospray/render/distributed/DistributedRenderer.cpp b/modules/mpi/ospray/render/distributed/DistributedRenderer.cpp index 633255a1d..b6adad610 100644 --- a/modules/mpi/ospray/render/distributed/DistributedRenderer.cpp +++ b/modules/mpi/ospray/render/distributed/DistributedRenderer.cpp @@ -37,7 +37,7 @@ void DistributedRenderer::computeRegionVisibility(DistributedFrameBuffer *fb, void DistributedRenderer::renderRegionToTile(DistributedFrameBuffer *fb, Camera *camera, DistributedWorld *world, - const Region ®ion, + const box3f ®ion, void *perFrameData, Tile &tile, size_t jobID) const diff --git a/modules/mpi/ospray/render/distributed/DistributedRenderer.h b/modules/mpi/ospray/render/distributed/DistributedRenderer.h index 922946a9d..382589dff 100644 --- a/modules/mpi/ospray/render/distributed/DistributedRenderer.h +++ b/modules/mpi/ospray/render/distributed/DistributedRenderer.h @@ -15,7 +15,7 @@ namespace mpi { struct RegionInfo { int numRegions = 0; - Region *regions = nullptr; + box3f *regions = nullptr; bool *regionVisible = nullptr; }; @@ -35,7 +35,7 @@ struct DistributedRenderer : public Renderer void renderRegionToTile(DistributedFrameBuffer *fb, Camera *camera, DistributedWorld *world, - const Region ®ion, + const box3f ®ion, void *perFrameData, Tile &tile, size_t jobID) const; diff --git a/modules/mpi/ospray/render/distributed/DistributedRenderer.ih b/modules/mpi/ospray/render/distributed/DistributedRenderer.ih index ff0f83f74..c61a91fcc 100644 --- a/modules/mpi/ospray/render/distributed/DistributedRenderer.ih +++ b/modules/mpi/ospray/render/distributed/DistributedRenderer.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -24,7 +24,7 @@ typedef unmasked void (*DR_ComputeRegionVisibility)( typedef void (*DR_RenderRegionSampleFct)(DistributedRenderer *uniform self, FrameBuffer *uniform fb, DistributedWorld *uniform world, - const Region *uniform region, + const box3f *uniform region, const vec2f ®ionInterval, void *uniform perFrameData, varying ScreenSample &sample); @@ -34,7 +34,7 @@ typedef unmasked void (*DR_RenderRegionTileFct)( FrameBuffer *uniform fb, Camera *uniform camera, DistributedWorld *uniform world, - const Region *uniform region, + const box3f *uniform region, void *uniform perFrameData, uniform Tile &tile, uniform int taskIndex); diff --git a/modules/mpi/ospray/render/distributed/DistributedRenderer.ispc b/modules/mpi/ospray/render/distributed/DistributedRenderer.ispc index 95fae9864..4ff7165b5 100644 --- a/modules/mpi/ospray/render/distributed/DistributedRenderer.ispc +++ b/modules/mpi/ospray/render/distributed/DistributedRenderer.ispc @@ -4,10 +4,30 @@ #include "DistributedRenderer.ih" #include "common/DistributedWorld.ih" #include "common/Intersect.ih" +#include "common/Ray.ih" #include "common/World.ih" #include "math/random.ih" #include "render/util.ih" +void markRegionVisibleFilterFunction( + const RTCFilterFunctionNArguments *uniform args) +{ + if (!args->valid[programIndex]) { + return; + } + + EmbreeIntersectionContext *uniform ctx = + (EmbreeIntersectionContext * uniform) args->context; + + bool *uniform regionVisible = (bool *uniform)ctx->userPtr; + varying RTCHit *uniform hit = (varying RTCHit * uniform) args->hit; + regionVisible[hit->primID] = true; + + // Reject all hits, we want to find all intersections along the ray to find + // all visible regions + args->valid[programIndex] = 0; +} + unmasked void DR_default_computeRegionVisibility( DistributedRenderer *uniform self, FrameBuffer *uniform fb, @@ -76,17 +96,14 @@ unmasked void DR_default_computeRegionVisibility( camera->initRay(camera, screenSample.ray, cameraSample); screenSample.ray.t = min(screenSample.ray.t, tMax); - for (uniform int r = 0; r < world->numRegions; ++r) { - if (!regionVisible[r] && !isEmpty(world->regions[r].bounds)) { - Intersections isect = intersectBox(screenSample.ray.org, - screenSample.ray.dir, - world->regions[r].bounds); - if (isect.entry.t < isect.exit.t - && isect.exit.t >= screenSample.ray.t0 - && isect.entry.t <= screenSample.ray.t) { - regionVisible[r] = true; - } - } + if (world->regionScene) { + uniform EmbreeIntersectionContext context; + rtcInitIntersectContext(&context.ectx); + context.ectx.filter = markRegionVisibleFilterFunction; + context.userPtr = regionVisible; + rtcIntersectV(world->regionScene, + &context.ectx, + (varying RTCRayHit * uniform) & screenSample.ray); } } @@ -102,7 +119,7 @@ unmasked void DR_default_computeRegionVisibility( void DR_default_renderRegionSample(DistributedRenderer *uniform self, FrameBuffer *uniform fb, DistributedWorld *uniform world, - const Region *uniform region, + const box3f *uniform region, const vec2f ®ionInterval, void *uniform perFrameData, varying ScreenSample &sample) @@ -117,7 +134,7 @@ unmasked void DR_default_renderRegionToTile(DistributedRenderer *uniform self, FrameBuffer *uniform fb, Camera *uniform camera, DistributedWorld *uniform world, - const Region *uniform region, + const box3f *uniform region, void *uniform perFrameData, uniform Tile &tile, uniform int taskIndex) @@ -184,8 +201,8 @@ unmasked void DR_default_renderRegionToTile(DistributedRenderer *uniform self, // TODO: We could store and use the region t intervals from when // we did the visibility test? - Intersections isect = intersectBox( - screenSample.ray.org, screenSample.ray.dir, region->bounds); + Intersections isect = + intersectBox(screenSample.ray.org, screenSample.ray.dir, *region); if (isect.entry.t < isect.exit.t && isect.exit.t >= screenSample.ray.t0 && isect.entry.t <= screenSample.ray.t) { @@ -262,7 +279,7 @@ export void DistributedRenderer_renderRegionToTile(void *uniform _self, (FrameBuffer * uniform) fb, (Camera * uniform) camera, (DistributedWorld * uniform) world, - (const Region *uniform)region, + (const box3f *uniform)region, perFrameData, tile, taskIndex); @@ -307,7 +324,7 @@ export void DistributedRenderer_pick(const void *uniform _self, regionRay.t = min(ray.t, closestHit); const Intersections isect = - intersectBox(regionRay.org, regionRay.dir, world->regions[i].bounds); + intersectBox(regionRay.org, regionRay.dir, world->regions[i]); cif (isect.entry.t < isect.exit.t && isect.exit.t >= regionRay.t0 && isect.entry.t <= regionRay.t) { diff --git a/ospray/camera/Camera.cpp b/ospray/camera/Camera.cpp index 9989fd11f..f0999fa04 100644 --- a/ospray/camera/Camera.cpp +++ b/ospray/camera/Camera.cpp @@ -10,10 +10,6 @@ namespace ospray { static FactoryMap g_cameraMap; -ProjectedPoint::ProjectedPoint(const vec3f &pos, float radius) - : screenPos(pos), radius(radius) -{} - Camera::Camera() { managedObjectType = OSP_CAMERA; @@ -85,8 +81,8 @@ void Camera::commit() if (!motionBlur) { // apply transform right away pos = xfmPoint(single_xfm, pos); - dir = xfmVector(single_xfm, dir); - up = xfmVector(single_xfm, up); + dir = normalize(xfmVector(single_xfm, dir)); + up = normalize(xfmVector(single_xfm, up)); } ispc::Camera_set(getIE(), @@ -98,11 +94,6 @@ void Camera::commit() embreeGeometry); } -ProjectedPoint Camera::projectPoint(const vec3f &) const -{ - NOT_IMPLEMENTED; -} - void Camera::setDevice(RTCDevice device) { embreeDevice = device; diff --git a/ospray/camera/Camera.h b/ospray/camera/Camera.h index 5029cd015..0181e8592 100644 --- a/ospray/camera/Camera.h +++ b/ospray/camera/Camera.h @@ -8,16 +8,6 @@ namespace ospray { -struct OSPRAY_SDK_INTERFACE ProjectedPoint -{ - //! The screen space position and depth - vec3f screenPos; - //! The radius of the projected disk, in the case of depth of field - float radius; - - ProjectedPoint(const vec3f &pos, float radius); -}; - //! base camera class abstraction /*! the base class itself does not do anything useful; look into perspectivecamera etc for that */ @@ -29,10 +19,6 @@ struct OSPRAY_SDK_INTERFACE Camera : public MotionTransform std::string toString() const override; void commit() override; - // Project the world space point to the screen, and return the screen-space - // point (in normalized screen-space coordinates) along with the depth - virtual ProjectedPoint projectPoint(const vec3f &p) const; - static Camera *createInstance(const char *identifier); template static void registerType(const char *type); diff --git a/ospray/camera/PerspectiveCamera.cpp b/ospray/camera/PerspectiveCamera.cpp index 20af1f110..faf90adcf 100644 --- a/ospray/camera/PerspectiveCamera.cpp +++ b/ospray/camera/PerspectiveCamera.cpp @@ -41,6 +41,7 @@ void PerspectiveCamera::commit() break; } + vec2f imgPlaneSize; imgPlaneSize.y = 2.f * tanf(deg2rad(0.5f * fovy)); imgPlaneSize.x = imgPlaneSize.y * aspect; @@ -57,28 +58,12 @@ void PerspectiveCamera::commit() interpupillaryDistance); } -ProjectedPoint PerspectiveCamera::projectPoint(const vec3f &p) const +box3f PerspectiveCamera::projectBox(const box3f &b) const { - // We find the intersection of the ray through the point with the virtual - // film plane, then find the vector to this point from the origin of the - // film plane (screenDir) and project this point onto the x/y axes of - // the plane. - const vec3f v = p - pos; - const vec3f r = normalize(v); - const float denom = dot(-r, -dir); - if (denom == 0.0) { - return ProjectedPoint( - vec3f(-1, -1, std::numeric_limits::infinity()), -1); - } - const float t = 1.0 / denom; - - const vec3f screenDir = r * t - dir_00; - const vec2f sp = vec2f(dot(screenDir, normalize(dir_du)), - dot(screenDir, normalize(dir_dv))) - / imgPlaneSize; - const float depth = sign(t) * length(v); - // TODO: Depth of field radius, stereo - return ProjectedPoint(vec3f(sp.x, sp.y, depth), 0); + box3f projection; + ispc::PerspectiveCamera_projectBox( + getIE(), (const ispc::box3f &)b, (ispc::box3f &)projection); + return projection; } } // namespace ospray diff --git a/ospray/camera/PerspectiveCamera.h b/ospray/camera/PerspectiveCamera.h index b181dc4dc..a54eb8768 100644 --- a/ospray/camera/PerspectiveCamera.h +++ b/ospray/camera/PerspectiveCamera.h @@ -1,9 +1,10 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "camera/Camera.h" +#include "rkcommon/math/box.h" namespace ospray { @@ -14,7 +15,13 @@ struct OSPRAY_SDK_INTERFACE PerspectiveCamera : public Camera virtual std::string toString() const override; virtual void commit() override; - virtual ProjectedPoint projectPoint(const vec3f &p) const override; + + // Project the bounding box to the screen. Does not support motion blur, + // depth of field, or steroe. The projected box will be returned in normalized + // [0, 1] coordinates in the framebuffer, the z coordinate will store the min + // and max depth, in box.lower, box.upper respectively + // TODO: we can support this in the future. + box3f projectBox(const box3f &b) const; // Data members // @@ -24,10 +31,6 @@ struct OSPRAY_SDK_INTERFACE PerspectiveCamera : public Camera float focusDistance; bool architectural; // orient image plane to be parallel to 'up' and shift the // lens - vec3f dir_00; - vec3f dir_du; - vec3f dir_dv; - vec2f imgPlaneSize; OSPStereoMode stereoMode; float interpupillaryDistance; // distance between the two cameras (stereo) diff --git a/ospray/camera/PerspectiveCamera.ispc b/ospray/camera/PerspectiveCamera.ispc index 917479904..4dfa03c8e 100644 --- a/ospray/camera/PerspectiveCamera.ispc +++ b/ospray/camera/PerspectiveCamera.ispc @@ -22,6 +22,8 @@ struct PerspectiveCamera vec3f ipd_offset; // shift of camera position for left/right eye (only when // SIDE_BY_SIDE or TOP_BOTTOM); (0.5*ipd, focusDistance, 0) + vec2f imgPlaneSize; + float scaledAperture; // radius of aperture prescaled to focal plane, i.e., // divided by horizontal image plane size float aspect; // image plane size x / y @@ -40,7 +42,7 @@ void PerspectiveCamera_initRay(const Camera *uniform _self, const uniform bool sbs = self->stereoMode == OSP_STEREO_SIDE_BY_SIDE; varying float *uniform split = sbs ? &screen.x : &screen.y; - if (or(sbs, self->stereoMode == OSP_STEREO_TOP_BOTTOM)) { + if (or (sbs, self->stereoMode == OSP_STEREO_TOP_BOTTOM)) { *split *= 2.f; if (*split < 1.f) { org = org - self->ipd_offset; @@ -172,6 +174,7 @@ export void PerspectiveCamera_set(void *uniform _self, self->stereoMode = stereoMode; self->dir_00 = normalize(dir); self->org = org; + self->imgPlaneSize = imgPlaneSize; if (self->super.motionBlur) { self->super.initRay = PerspectiveCamera_initRayMB; @@ -215,3 +218,95 @@ export void PerspectiveCamera_set(void *uniform _self, } } } + +export void PerspectiveCamera_projectBox( + void *uniform _self, const uniform box3f &box, uniform box3f &projection) +{ + PerspectiveCamera *uniform self = (PerspectiveCamera * uniform) _self; + // The original viewing direction along the camera + const uniform vec3f dir = + normalize(self->dir_00 + 0.5f * self->du_size + 0.5f * self->dv_up); + const uniform vec3f du = normalize(self->du_size); + const uniform vec3f dv = normalize(self->dv_up); + + vec3f projectedPt = make_vec3f(-1.f, -1.f, 1e20f); + foreach (i = 0 ... 8) { + // Get the point we should be projecting + vec3f p; + switch (i) { + case 0: + p = box.lower; + break; + case 1: + p.x = box.upper.x; + p.y = box.lower.y; + p.z = box.lower.z; + break; + case 2: + p.x = box.upper.x; + p.y = box.upper.y; + p.z = box.lower.z; + break; + case 3: + p.x = box.lower.x; + p.y = box.upper.y; + p.z = box.lower.z; + break; + case 4: + p.x = box.lower.x; + p.y = box.lower.y; + p.z = box.upper.z; + break; + case 5: + p.x = box.upper.x; + p.y = box.lower.y; + p.z = box.upper.z; + break; + case 6: + p = box.upper; + break; + case 7: + p.x = box.lower.x; + p.y = box.upper.y; + p.z = box.upper.z; + break; + } + + // We find the intersection of the ray through the point with the virtual + // film plane, then find the vector to this point from the origin of the + // film plane (screenDir) and project this point onto the x/y axes of + // the plane. + const vec3f v = p - self->org; + const vec3f r = normalize(v); + const float denom = dot(neg(r), neg(dir)); + if (denom != 0.f) { + float t = 1.f / denom; + const vec3f screenDir = r * t - self->dir_00; + projectedPt.x = dot(screenDir, du) / self->imgPlaneSize.x; + projectedPt.y = dot(screenDir, dv) / self->imgPlaneSize.y; + projectedPt.z = signbits(t) ? -length(v) : length(v); + } + } + + // Find the projection of all points that projected to the screen + if (projectedPt.z < 1e20f) { + projection.lower.x = reduce_min(projectedPt.x); + projection.lower.y = reduce_min(projectedPt.y); + projection.lower.z = reduce_min(projectedPt.z); + + projection.upper.x = reduce_max(projectedPt.x); + projection.upper.y = reduce_max(projectedPt.y); + projection.upper.z = reduce_max(projectedPt.z); + } + // TODO: I think if points go behind the eye, we can don't need to just bail + // out to mark all tiles as touched but could project those points using an + // orthographic projection on to the plane to still have some tile overlap + // reduction. + if (projection.lower.z < 0.f && projection.upper.z > 0.f) { + projection.lower.x = 0.f; + projection.lower.y = 0.f; + + projection.upper.x = 1.f; + projection.upper.y = 1.f; + } +} diff --git a/ospray/common/World.h b/ospray/common/World.h index 0572bed4c..784e920bf 100644 --- a/ospray/common/World.h +++ b/ospray/common/World.h @@ -43,7 +43,7 @@ struct OSPRAY_SDK_INTERFACE World : public ManagedObject void setDevice(RTCDevice embreeDevice); - private: + protected: RTCDevice embreeDevice{nullptr}; }; From 18660cdbeb5d085f31a1d9a25ee6726f9e939f40 Mon Sep 17 00:00:00 2001 From: Will Usher Date: Fri, 10 Sep 2021 17:26:44 -0700 Subject: [PATCH 07/22] Fix parameter to C++ Material wrapper, must be empty str not null --- modules/mpi/tutorials/ospMPIDistribTutorialSpheres.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/mpi/tutorials/ospMPIDistribTutorialSpheres.cpp b/modules/mpi/tutorials/ospMPIDistribTutorialSpheres.cpp index e4a8a5ec6..fd986b71a 100644 --- a/modules/mpi/tutorials/ospMPIDistribTutorialSpheres.cpp +++ b/modules/mpi/tutorials/ospMPIDistribTutorialSpheres.cpp @@ -214,7 +214,7 @@ cpp::Instance makeLocalSpheres( sphereGeom.commit(); vec3f color(0.f, 0.f, (mpiRank + 1.f) / mpiWorldSize); - cpp::Material material(nullptr, "obj"); + cpp::Material material("", "obj"); material.setParam("kd", color); material.commit(); From f0b937d1c362dc753d168f247c1fae5b1aac19b6 Mon Sep 17 00:00:00 2001 From: Will Usher Date: Thu, 16 Sep 2021 11:32:36 -0700 Subject: [PATCH 08/22] Adding ospMPIDistributedExamples: data-parallel rendering of ospExamples --- modules/mpi/tutorials/CMakeLists.txt | 10 +- .../tutorials/ospMPIDistributedExamples.cpp | 176 ++++++++++++++++++ 2 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 modules/mpi/tutorials/ospMPIDistributedExamples.cpp diff --git a/modules/mpi/tutorials/CMakeLists.txt b/modules/mpi/tutorials/CMakeLists.txt index 67b6dc26b..4fc143218 100644 --- a/modules/mpi/tutorials/CMakeLists.txt +++ b/modules/mpi/tutorials/CMakeLists.txt @@ -83,7 +83,6 @@ target_link_libraries(mpi_tutorial_common PUBLIC MPI::MPI_CXX ) - target_compile_definitions(mpi_tutorial_common PUBLIC -DOSPRAY_CPP_RKCOMMON_TYPES) ospray_create_mpi_tutorial(ospMPIDistribTutorialSpheres @@ -113,3 +112,12 @@ target_link_libraries(ospMPIDistribTutorialReplicated PUBLIC ospray_testing ) +ospray_create_mpi_tutorial(ospMPIDistributedExamples + ospMPIDistributedExamples.cpp +) +ospray_sign_target(ospMPIDistributedExamples) + +target_link_libraries(ospMPIDistributedExamples PUBLIC + ospray_testing +) + diff --git a/modules/mpi/tutorials/ospMPIDistributedExamples.cpp b/modules/mpi/tutorials/ospMPIDistributedExamples.cpp new file mode 100644 index 000000000..01aa8fedf --- /dev/null +++ b/modules/mpi/tutorials/ospMPIDistributedExamples.cpp @@ -0,0 +1,176 @@ +// Copyright 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +/* This example generates the same data on each rank so that we can build + * off the existing OSPRay testing data generators, however each rank + * specifies a subregion as its local domain to render the data as if it was + * distributed. The scene to load can be passed as an argument to the + * application + */ + +#include +#include +#include +#include +#include +#include "GLFWDistribOSPRayWindow.h" +#include "ospray/ospray_cpp.h" +#include "ospray/ospray_cpp/ext/rkcommon.h" +#include "ospray/ospray_util.h" +#include "ospray_testing.h" + +using namespace ospray; +using namespace rkcommon; +using namespace rkcommon::math; + +bool computeDivisor(int x, int &divisor); + +// Compute an X x Y x Z grid to have 'num' grid cells, +// only gives a nice grid for numbers with even factors since +// we don't search for factors of the number, we just try dividing by two +vec3i computeGrid(int num); + +int main(int argc, char **argv) +{ + int mpiThreadCapability = 0; + MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &mpiThreadCapability); + if (mpiThreadCapability != MPI_THREAD_MULTIPLE + && mpiThreadCapability != MPI_THREAD_SERIALIZED) { + fprintf(stderr, + "OSPRay requires the MPI runtime to support thread " + "multiple or thread serialized.\n"); + return 1; + } + + std::string sceneName = "gravity_spheres_volume"; + if (argc == 2) { + sceneName = argv[1]; + } + + int mpiRank = 0; + int mpiWorldSize = 0; + MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); + MPI_Comm_size(MPI_COMM_WORLD, &mpiWorldSize); + + std::cout << "OSPRay rank " << mpiRank << "/" << mpiWorldSize << "\n"; + + // load the MPI module, and select the MPI distributed device. Here we + // do not call ospInit, as we want to explicitly pick the distributed + // device. This can also be done by passing --osp:mpi-distributed when + // using ospInit, however if the user doesn't pass this argument your + // application will likely not behave as expected + ospLoadModule("mpi"); + + { + cpp::Device mpiDevice("mpiDistributed"); + mpiDevice.commit(); + mpiDevice.setCurrent(); + + // set an error callback to catch any OSPRay errors and exit the application + mpiDevice.setErrorCallback( + [](void *, OSPError error, const char *errorDetails) { + std::cerr << "OSPRay error: " << errorDetails << std::endl; + exit(error); + }); + + // Regions are assigned to ranks in 3D grid, determine which brick of the + // grid is owned by this rank + const vec3i distribGrid = computeGrid(mpiWorldSize); + const vec3i distribBrickId(mpiRank % distribGrid.x, + (mpiRank / distribGrid.x) % distribGrid.y, + mpiRank / (distribGrid.x * distribGrid.y)); + + std::cout << "scene = " << sceneName << "\n"; + auto builder = testing::newBuilder(sceneName); + testing::setParam(builder, "rendererType", "scivis"); + testing::commit(builder); + + auto group = testing::buildGroup(builder); + const box3f worldBounds = group.getBounds(); + + cpp::Instance instance(group); + instance.commit(); + + cpp::World world; + world.setParam("instance", cpp::CopiedData(instance)); + + cpp::Light light("ambient"); + light.setParam("visible", false); + light.commit(); + + world.setParam("light", cpp::CopiedData(light)); + + // Determine the bounds of this rank's region in world space + const vec3f distribBrickDims = worldBounds.size() / vec3f(distribGrid); + box3f localRegion(distribBrickId * distribBrickDims + worldBounds.lower, + distribBrickId * distribBrickDims + distribBrickDims + + worldBounds.lower); + + // Special case for the ospray test data: we might have geometry right at + // the region bounding box which will z-fight with the clipping region. If + // we have a region at the edge of the domain, apply some padding + for (int i = 0; i < 3; ++i) { + if (localRegion.lower[i] == worldBounds.lower[i]) { + localRegion.lower[i] -= 0.001; + } + if (localRegion.upper[i] == worldBounds.upper[i]) { + localRegion.upper[i] += 0.001; + } + } + + // Set our region that represents the bounds of the local data we own on + // this rank + world.setParam("region", cpp::CopiedData(localRegion)); + world.commit(); + testing::release(builder); + + // create OSPRay renderer + cpp::Renderer renderer("mpiRaycast"); + + // create a GLFW OSPRay window: this object will create and manage the + // OSPRay frame buffer and camera directly + auto glfwOSPRayWindow = + std::unique_ptr(new GLFWDistribOSPRayWindow( + vec2i{1024, 768}, worldBounds, world, renderer)); + + // start the GLFW main loop, which will continuously render + glfwOSPRayWindow->mainLoop(); + } + // cleanly shut OSPRay down + ospShutdown(); + + MPI_Finalize(); + + return 0; +} + +bool computeDivisor(int x, int &divisor) +{ + int upperBound = std::sqrt(x); + for (int i = 2; i <= upperBound; ++i) { + if (x % i == 0) { + divisor = i; + return true; + } + } + return false; +} + +// Compute an X x Y x Z grid to have 'num' grid cells, +// only gives a nice grid for numbers with even factors since +// we don't search for factors of the number, we just try dividing by two +vec3i computeGrid(int num) +{ + vec3i grid(1); + int axis = 0; + int divisor = 0; + while (computeDivisor(num, divisor)) { + grid[axis] *= divisor; + num /= divisor; + axis = (axis + 1) % 3; + } + if (num != 1) { + grid[axis] *= num; + } + return grid; +} From f71056e28372cc142ffc4899ac02537e52dc7fad Mon Sep 17 00:00:00 2001 From: Will Usher Date: Mon, 20 Sep 2021 15:34:35 -0700 Subject: [PATCH 09/22] Add base Camera::projectBox fallback that returns the whole screen --- .../mpi/ospray/render/DistributedLoadBalancer.cpp | 11 ++--------- ospray/camera/Camera.cpp | 5 +++++ ospray/camera/Camera.h | 2 ++ ospray/camera/PerspectiveCamera.cpp | 3 +++ ospray/camera/PerspectiveCamera.h | 12 ++++++------ ospray/camera/PerspectiveCamera.ispc | 6 ++---- 6 files changed, 20 insertions(+), 19 deletions(-) diff --git a/modules/mpi/ospray/render/DistributedLoadBalancer.cpp b/modules/mpi/ospray/render/DistributedLoadBalancer.cpp index 577c09811..0d040ce95 100644 --- a/modules/mpi/ospray/render/DistributedLoadBalancer.cpp +++ b/modules/mpi/ospray/render/DistributedLoadBalancer.cpp @@ -7,7 +7,7 @@ #include #include "../fb/DistributedFrameBuffer.h" #include "WriteMultipleTileOperation.h" -#include "camera/PerspectiveCamera.h" +#include "camera/Camera.h" #include "common/MPICommon.h" #include "common/Profiling.h" #include "distributed/DistributedRenderer.h" @@ -42,13 +42,6 @@ void Distributed::renderFrame( } } - PerspectiveCamera *perspectiveCamera = - reinterpret_cast(camera); - if (!perspectiveCamera) { - throw std::runtime_error( - "DistributedRaycastRender only supports PerspectiveCamera"); - } - if (dfb->getLastRenderer() != renderer) { dfb->setTileOperation(renderer->tileOperation(), renderer); } @@ -75,7 +68,7 @@ void Distributed::renderFrame( const vec2i fbSize = dfb->getNumPixels(); for (const auto &id : world->myRegionIds) { const auto &r = world->allRegions[id]; - box3f proj = perspectiveCamera->projectBox(r); + box3f proj = camera->projectBox(r); box2f screenRegion(vec2f(proj.lower) * fbSize, vec2f(proj.upper) * fbSize); // Pad the region a bit diff --git a/ospray/camera/Camera.cpp b/ospray/camera/Camera.cpp index f0999fa04..e20d034e2 100644 --- a/ospray/camera/Camera.cpp +++ b/ospray/camera/Camera.cpp @@ -36,6 +36,11 @@ std::string Camera::toString() const return "ospray::Camera"; } +box3f Camera::projectBox(const box3f &) const +{ + return box3f(vec3f(0.f), vec3f(1.f)); +} + void Camera::commit() { MotionTransform::commit(); diff --git a/ospray/camera/Camera.h b/ospray/camera/Camera.h index 0181e8592..4f0f38572 100644 --- a/ospray/camera/Camera.h +++ b/ospray/camera/Camera.h @@ -19,6 +19,8 @@ struct OSPRAY_SDK_INTERFACE Camera : public MotionTransform std::string toString() const override; void commit() override; + virtual box3f projectBox(const box3f &b) const; + static Camera *createInstance(const char *identifier); template static void registerType(const char *type); diff --git a/ospray/camera/PerspectiveCamera.cpp b/ospray/camera/PerspectiveCamera.cpp index faf90adcf..e43d28889 100644 --- a/ospray/camera/PerspectiveCamera.cpp +++ b/ospray/camera/PerspectiveCamera.cpp @@ -60,6 +60,9 @@ void PerspectiveCamera::commit() box3f PerspectiveCamera::projectBox(const box3f &b) const { + if (motionBlur || stereoMode != OSP_STEREO_NONE || focusDistance != 1.f) { + return box3f(vec3f(0.f), vec3f(1.f)); + } box3f projection; ispc::PerspectiveCamera_projectBox( getIE(), (const ispc::box3f &)b, (ispc::box3f &)projection); diff --git a/ospray/camera/PerspectiveCamera.h b/ospray/camera/PerspectiveCamera.h index a54eb8768..65a64451a 100644 --- a/ospray/camera/PerspectiveCamera.h +++ b/ospray/camera/PerspectiveCamera.h @@ -16,12 +16,12 @@ struct OSPRAY_SDK_INTERFACE PerspectiveCamera : public Camera virtual std::string toString() const override; virtual void commit() override; - // Project the bounding box to the screen. Does not support motion blur, - // depth of field, or steroe. The projected box will be returned in normalized - // [0, 1] coordinates in the framebuffer, the z coordinate will store the min - // and max depth, in box.lower, box.upper respectively - // TODO: we can support this in the future. - box3f projectBox(const box3f &b) const; + // Project the bounding box to the screen. Will fall back to reporting the + // entire screen in the case of motion blur, depth of field, and stereo for + // now. The projected box will be returned in normalized [0, 1] coordinates in + // the framebuffer, the z coordinate will store the min and max depth, in + // box.lower, box.upper respectively + box3f projectBox(const box3f &b) const override; // Data members // diff --git a/ospray/camera/PerspectiveCamera.ispc b/ospray/camera/PerspectiveCamera.ispc index 4dfa03c8e..63c062088 100644 --- a/ospray/camera/PerspectiveCamera.ispc +++ b/ospray/camera/PerspectiveCamera.ispc @@ -298,10 +298,8 @@ export void PerspectiveCamera_projectBox( projection.upper.y = reduce_max(projectedPt.y); projection.upper.z = reduce_max(projectedPt.z); } - // TODO: I think if points go behind the eye, we can don't need to just bail - // out to mark all tiles as touched but could project those points using an - // orthographic projection on to the plane to still have some tile overlap - // reduction. + // If some points are behind and some are in front mark the box + // as covering the full screen if (projection.lower.z < 0.f && projection.upper.z > 0.f) { projection.lower.x = 0.f; projection.lower.y = 0.f; From 79e22dc37d77018369e5dacdf31e56faa8965778 Mon Sep 17 00:00:00 2001 From: Will Usher Date: Mon, 20 Sep 2021 16:34:24 -0700 Subject: [PATCH 10/22] Add OrthographicCamera::projectBox --- ospray/camera/OrthographicCamera.cpp | 11 ++++ ospray/camera/OrthographicCamera.h | 2 + ospray/camera/OrthographicCamera.ispc | 74 +++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/ospray/camera/OrthographicCamera.cpp b/ospray/camera/OrthographicCamera.cpp index 97894312b..bb73871b6 100644 --- a/ospray/camera/OrthographicCamera.cpp +++ b/ospray/camera/OrthographicCamera.cpp @@ -33,4 +33,15 @@ void OrthographicCamera::commit() (const ispc::vec2f &)size); } +box3f OrthographicCamera::projectBox(const box3f &b) const +{ + if (motionBlur) { + return box3f(vec3f(0.f), vec3f(1.f)); + } + box3f projection; + ispc::OrthographicCamera_projectBox( + getIE(), (const ispc::box3f &)b, (ispc::box3f &)projection); + return projection; +} + } // namespace ospray diff --git a/ospray/camera/OrthographicCamera.h b/ospray/camera/OrthographicCamera.h index c72b541da..8ad1fe9de 100644 --- a/ospray/camera/OrthographicCamera.h +++ b/ospray/camera/OrthographicCamera.h @@ -40,6 +40,8 @@ struct OSPRAY_SDK_INTERFACE OrthographicCamera : public Camera virtual std::string toString() const override; virtual void commit() override; + box3f projectBox(const box3f &b) const override; + // Data members // float height; // size of the camera's image plane in y, in world coordinates diff --git a/ospray/camera/OrthographicCamera.ispc b/ospray/camera/OrthographicCamera.ispc index 055a5b853..2a2ecdee8 100644 --- a/ospray/camera/OrthographicCamera.ispc +++ b/ospray/camera/OrthographicCamera.ispc @@ -81,3 +81,77 @@ export void OrthographicCamera_set(void *uniform _self, self->org = org - 0.5f * self->du_size - 0.5f * self->dv_up; // shift } } + +export void OrthographicCamera_projectBox( + void *uniform _self, const uniform box3f &box, uniform box3f &projection) +{ + OrthographicCamera *uniform self = (OrthographicCamera * uniform) _self; + const uniform vec3f du = normalize(self->du_size); + const uniform vec3f dv = normalize(self->dv_up); + + const uniform float imgPlaneSizeX = length(self->du_size); + const uniform float imgPlaneSizeY = length(self->dv_up); + + vec3f projectedPt = make_vec3f(-1.f, -1.f, 1e20f); + foreach (i = 0 ... 8) { + // Get the point we should be projecting + vec3f p; + switch (i) { + case 0: + p = box.lower; + break; + case 1: + p.x = box.upper.x; + p.y = box.lower.y; + p.z = box.lower.z; + break; + case 2: + p.x = box.upper.x; + p.y = box.upper.y; + p.z = box.lower.z; + break; + case 3: + p.x = box.lower.x; + p.y = box.upper.y; + p.z = box.lower.z; + break; + case 4: + p.x = box.lower.x; + p.y = box.lower.y; + p.z = box.upper.z; + break; + case 5: + p.x = box.upper.x; + p.y = box.lower.y; + p.z = box.upper.z; + break; + case 6: + p = box.upper; + break; + case 7: + p.x = box.lower.x; + p.y = box.upper.y; + p.z = box.upper.z; + break; + } + + // Project the point on to the film plane + const float depth = dot(p - self->org, self->dir); + const vec3f screenPt = p - depth * self->dir; + const vec3f screenDir = screenPt - self->org; + projectedPt.x = dot(screenDir, du) / imgPlaneSizeX; + projectedPt.y = dot(screenDir, dv) / imgPlaneSizeY; + projectedPt.z = depth; + } + + // Find the projection of all points that projected to the screen + if (projectedPt.z < 1e20f) { + projection.lower.x = reduce_min(projectedPt.x); + projection.lower.y = reduce_min(projectedPt.y); + projection.lower.z = reduce_min(projectedPt.z); + + projection.upper.x = reduce_max(projectedPt.x); + projection.upper.y = reduce_max(projectedPt.y); + projection.upper.z = reduce_max(projectedPt.z); + } +} From ae3efc0763ddabfb29ffa57e668ab686df414654 Mon Sep 17 00:00:00 2001 From: Will Usher Date: Tue, 21 Sep 2021 08:37:25 -0700 Subject: [PATCH 11/22] Update CHANGELOG --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43604889a..b7160edd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ Version History - Fix CMake variables and logic - Fix crash when transferfunction.opacity = 0 +- Fix bug in data-parallel rendering that caused rendering to hang +- Improved performance of data-parallel rendering for scenes with + a large number of regions. +- Expanded camera model support of the data-parallel renderer, + data-parallel rendering can now use all the camera models supported + by the scivis renderer. ### Changes in v2.7.0: From ab2c2cf0ef5c78a1699346da821e708034e94399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20G=C3=BCnther?= Date: Wed, 22 Sep 2021 03:07:06 +0200 Subject: [PATCH 12/22] No MB/DoF for DistributedRenderer as well; small refactor --- .../render/distributed/DistributedRenderer.ispc | 14 ++++++++------ ospray/camera/Camera.h | 5 +++++ ospray/camera/OrthographicCamera.cpp | 3 --- ospray/camera/OrthographicCamera.ispc | 12 +++++------- ospray/camera/PerspectiveCamera.cpp | 2 +- ospray/camera/PerspectiveCamera.h | 5 ----- ospray/camera/PerspectiveCamera.ispc | 8 ++++---- ospray/render/Renderer.ispc | 4 ++-- 8 files changed, 25 insertions(+), 28 deletions(-) diff --git a/modules/mpi/ospray/render/distributed/DistributedRenderer.ispc b/modules/mpi/ospray/render/distributed/DistributedRenderer.ispc index 4ff7165b5..277395db0 100644 --- a/modules/mpi/ospray/render/distributed/DistributedRenderer.ispc +++ b/modules/mpi/ospray/render/distributed/DistributedRenderer.ispc @@ -89,9 +89,10 @@ unmasked void DR_default_computeRegionVisibility( cameraSample.screen.y = (screenSample.sampleID.y + pixel_dv) * fb->rcpSize.y; - // TODO: fix correlations / better RNG - cameraSample.lens.x = pixel_du; - cameraSample.lens.y = pixel_dv; + // no DoF or MB per default + cameraSample.lens.x = 0.0f; + cameraSample.lens.y = 0.0f; + cameraSample.time = 0.5f; camera->initRay(camera, screenSample.ray, cameraSample); screenSample.ray.t = min(screenSample.ray.t, tMax); @@ -192,9 +193,10 @@ unmasked void DR_default_renderRegionToTile(DistributedRenderer *uniform self, cameraSample.screen.y = (screenSample.sampleID.y + pixel_dv) * fb->rcpSize.y; - // TODO: fix correlations / better RNG - cameraSample.lens.x = pixel_du; - cameraSample.lens.y = pixel_dv; + // no DoF or MB per default + cameraSample.lens.x = 0.0f; + cameraSample.lens.y = 0.0f; + cameraSample.time = 0.5f; camera->initRay(camera, screenSample.ray, cameraSample); screenSample.ray.t = min(screenSample.ray.t, tMax); diff --git a/ospray/camera/Camera.h b/ospray/camera/Camera.h index 4f0f38572..c69ff28b1 100644 --- a/ospray/camera/Camera.h +++ b/ospray/camera/Camera.h @@ -19,6 +19,11 @@ struct OSPRAY_SDK_INTERFACE Camera : public MotionTransform std::string toString() const override; void commit() override; + // Project the bounding box to the screen + // The projected box will be returned in normalized [0, 1] coordinates in + // the framebuffer, the z coordinate will store the min and max depth, in + // box.lower, box.upper respectively + // Assume no motion blur nor depth of field (true for SciVis) virtual box3f projectBox(const box3f &b) const; static Camera *createInstance(const char *identifier); diff --git a/ospray/camera/OrthographicCamera.cpp b/ospray/camera/OrthographicCamera.cpp index bb73871b6..bb81ac9a7 100644 --- a/ospray/camera/OrthographicCamera.cpp +++ b/ospray/camera/OrthographicCamera.cpp @@ -35,9 +35,6 @@ void OrthographicCamera::commit() box3f OrthographicCamera::projectBox(const box3f &b) const { - if (motionBlur) { - return box3f(vec3f(0.f), vec3f(1.f)); - } box3f projection; ispc::OrthographicCamera_projectBox( getIE(), (const ispc::box3f &)b, (ispc::box3f &)projection); diff --git a/ospray/camera/OrthographicCamera.ispc b/ospray/camera/OrthographicCamera.ispc index 2a2ecdee8..d7819ac3d 100644 --- a/ospray/camera/OrthographicCamera.ispc +++ b/ospray/camera/OrthographicCamera.ispc @@ -86,11 +86,9 @@ export void OrthographicCamera_projectBox( void *uniform _self, const uniform box3f &box, uniform box3f &projection) { OrthographicCamera *uniform self = (OrthographicCamera * uniform) _self; - const uniform vec3f du = normalize(self->du_size); - const uniform vec3f dv = normalize(self->dv_up); - - const uniform float imgPlaneSizeX = length(self->du_size); - const uniform float imgPlaneSizeY = length(self->dv_up); + // normalize to image plane size + const uniform vec3f dun = self->du_size / dot(self->du_size, self->du_size); + const uniform vec3f dvn = self->dv_up / dot(self->dv_up, self->dv_up); vec3f projectedPt = make_vec3f(-1.f, -1.f, 1e20f); foreach (i = 0 ... 8) { @@ -139,8 +137,8 @@ export void OrthographicCamera_projectBox( const float depth = dot(p - self->org, self->dir); const vec3f screenPt = p - depth * self->dir; const vec3f screenDir = screenPt - self->org; - projectedPt.x = dot(screenDir, du) / imgPlaneSizeX; - projectedPt.y = dot(screenDir, dv) / imgPlaneSizeY; + projectedPt.x = dot(screenDir, dun); + projectedPt.y = dot(screenDir, dvn); projectedPt.z = depth; } diff --git a/ospray/camera/PerspectiveCamera.cpp b/ospray/camera/PerspectiveCamera.cpp index e43d28889..1bc16ee61 100644 --- a/ospray/camera/PerspectiveCamera.cpp +++ b/ospray/camera/PerspectiveCamera.cpp @@ -60,7 +60,7 @@ void PerspectiveCamera::commit() box3f PerspectiveCamera::projectBox(const box3f &b) const { - if (motionBlur || stereoMode != OSP_STEREO_NONE || focusDistance != 1.f) { + if (stereoMode != OSP_STEREO_NONE) { return box3f(vec3f(0.f), vec3f(1.f)); } box3f projection; diff --git a/ospray/camera/PerspectiveCamera.h b/ospray/camera/PerspectiveCamera.h index 65a64451a..bcb71ca0b 100644 --- a/ospray/camera/PerspectiveCamera.h +++ b/ospray/camera/PerspectiveCamera.h @@ -16,11 +16,6 @@ struct OSPRAY_SDK_INTERFACE PerspectiveCamera : public Camera virtual std::string toString() const override; virtual void commit() override; - // Project the bounding box to the screen. Will fall back to reporting the - // entire screen in the case of motion blur, depth of field, and stereo for - // now. The projected box will be returned in normalized [0, 1] coordinates in - // the framebuffer, the z coordinate will store the min and max depth, in - // box.lower, box.upper respectively box3f projectBox(const box3f &b) const override; // Data members // diff --git a/ospray/camera/PerspectiveCamera.ispc b/ospray/camera/PerspectiveCamera.ispc index 63c062088..32a594f46 100644 --- a/ospray/camera/PerspectiveCamera.ispc +++ b/ospray/camera/PerspectiveCamera.ispc @@ -226,8 +226,8 @@ export void PerspectiveCamera_projectBox( // The original viewing direction along the camera const uniform vec3f dir = normalize(self->dir_00 + 0.5f * self->du_size + 0.5f * self->dv_up); - const uniform vec3f du = normalize(self->du_size); - const uniform vec3f dv = normalize(self->dv_up); + const uniform vec3f dun = normalize(self->du_size) / self->imgPlaneSize.x; + const uniform vec3f dvn = normalize(self->dv_up) / self->imgPlaneSize.y; vec3f projectedPt = make_vec3f(-1.f, -1.f, 1e20f); foreach (i = 0 ... 8) { @@ -282,8 +282,8 @@ export void PerspectiveCamera_projectBox( if (denom != 0.f) { float t = 1.f / denom; const vec3f screenDir = r * t - self->dir_00; - projectedPt.x = dot(screenDir, du) / self->imgPlaneSize.x; - projectedPt.y = dot(screenDir, dv) / self->imgPlaneSize.y; + projectedPt.x = dot(screenDir, dun); + projectedPt.y = dot(screenDir, dvn); projectedPt.z = signbits(t) ? -length(v) : length(v); } } diff --git a/ospray/render/Renderer.ispc b/ospray/render/Renderer.ispc index cf031a01f..6b98b6d05 100644 --- a/ospray/render/Renderer.ispc +++ b/ospray/render/Renderer.ispc @@ -105,8 +105,8 @@ unmasked void Renderer_default_renderTile(Renderer *uniform self, screenSample.pos = cameraSample.screen; // no DoF or MB per default - cameraSample.lens.x = 0.5f; - cameraSample.lens.y = 0.5f; + cameraSample.lens.x = 0.0f; + cameraSample.lens.y = 0.0f; cameraSample.time = 0.5f; camera->initRay(camera, screenSample.ray, cameraSample); From c3737f4c9c7b055a6d63c5053929cdf765f02f77 Mon Sep 17 00:00:00 2001 From: Will Usher Date: Thu, 23 Sep 2021 15:44:54 -0700 Subject: [PATCH 13/22] Workaround for linking issue on Windows, closes #496 Other issue fixed was missing unmasked for filter function callback --- CHANGELOG.md | 8 +++++--- .../distributed/DistributedRenderer.ispc | 18 +++++++++++------- ospray/camera/OrthographicCamera.h | 2 +- ospray/ispc_symbols.txt | 1 + ospray/render/util.ih | 4 +++- ospray/render/util.ispc | 7 ++++++- 6 files changed, 27 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b7160edd3..3885cadc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,14 @@ Version History - Fix CMake variables and logic - Fix crash when transferfunction.opacity = 0 -- Fix bug in data-parallel rendering that caused rendering to hang +- Fix bug in MPI data-parallel rendering that caused rendering to hang +- Workaround dynamic linking issue on Windows in MPI distributed + rendering - Improved performance of data-parallel rendering for scenes with - a large number of regions. + a large number of regions - Expanded camera model support of the data-parallel renderer, data-parallel rendering can now use all the camera models supported - by the scivis renderer. + by the scivis renderer ### Changes in v2.7.0: diff --git a/modules/mpi/ospray/render/distributed/DistributedRenderer.ispc b/modules/mpi/ospray/render/distributed/DistributedRenderer.ispc index 277395db0..afd166e35 100644 --- a/modules/mpi/ospray/render/distributed/DistributedRenderer.ispc +++ b/modules/mpi/ospray/render/distributed/DistributedRenderer.ispc @@ -9,7 +9,7 @@ #include "math/random.ih" #include "render/util.ih" -void markRegionVisibleFilterFunction( +unmasked void markRegionVisibleFilterFunction( const RTCFilterFunctionNArguments *uniform args) { if (!args->valid[programIndex]) { @@ -47,14 +47,16 @@ unmasked void DR_default_computeRegionVisibility( CameraSample cameraSample; + const z_order_t *uniform zOrder = get_zorder(); + const uniform int begin = taskIndex * RENDERTILE_PIXELS_PER_JOB; const uniform int end = begin + RENDERTILE_PIXELS_PER_JOB; const uniform int startSampleID = max(tile.accumID, 0) * spp; for (uniform uint32 i = begin; i < end; i += programCount) { const uint32 index = i + programIndex; - screenSample.sampleID.x = tile.region.lower.x + z_order.xs[index]; - screenSample.sampleID.y = tile.region.lower.y + z_order.ys[index]; + screenSample.sampleID.x = tile.region.lower.x + zOrder->xs[index]; + screenSample.sampleID.y = tile.region.lower.y + zOrder->ys[index]; if ((screenSample.sampleID.x >= fb->size.x) || (screenSample.sampleID.y >= fb->size.y)) @@ -74,7 +76,7 @@ unmasked void DR_default_computeRegionVisibility( tMax = min(get1f(self->super.maxDepthTexture, lookup), inf); } - const uint32 pixel = z_order.xs[index] + (z_order.ys[index] * TILE_SIZE); + const uint32 pixel = zOrder->xs[index] + (zOrder->ys[index] * TILE_SIZE); // TODO: Does spp still show some block boundary artifacts? Check // and maybe just support spp = 1 in DR @@ -148,14 +150,16 @@ unmasked void DR_default_renderRegionToTile(DistributedRenderer *uniform self, CameraSample cameraSample; + const z_order_t *uniform zOrder = get_zorder(); + const uniform int begin = taskIndex * RENDERTILE_PIXELS_PER_JOB; const uniform int end = begin + RENDERTILE_PIXELS_PER_JOB; const uniform int startSampleID = max(tile.accumID, 0) * spp; for (uniform uint32 i = begin; i < end; i += programCount) { const uint32 index = i + programIndex; - screenSample.sampleID.x = tile.region.lower.x + z_order.xs[index]; - screenSample.sampleID.y = tile.region.lower.y + z_order.ys[index]; + screenSample.sampleID.x = tile.region.lower.x + zOrder->xs[index]; + screenSample.sampleID.y = tile.region.lower.y + zOrder->ys[index]; if ((screenSample.sampleID.x >= fb->size.x) || (screenSample.sampleID.y >= fb->size.y)) @@ -179,7 +183,7 @@ unmasked void DR_default_renderRegionToTile(DistributedRenderer *uniform self, vec3f normal = make_vec3f(0.f); vec3f albedo = make_vec3f(0.f); - const uint32 pixel = z_order.xs[index] + (z_order.ys[index] * TILE_SIZE); + const uint32 pixel = zOrder->xs[index] + (zOrder->ys[index] * TILE_SIZE); // TODO: same note on spp > 1 issues for (uniform uint32 s = 0; s < spp; s++) { diff --git a/ospray/camera/OrthographicCamera.h b/ospray/camera/OrthographicCamera.h index 8ad1fe9de..fe25b72a5 100644 --- a/ospray/camera/OrthographicCamera.h +++ b/ospray/camera/OrthographicCamera.h @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/ispc_symbols.txt b/ospray/ispc_symbols.txt index a4d7bb4eb..945370f4f 100644 --- a/ospray/ispc_symbols.txt +++ b/ospray/ispc_symbols.txt @@ -15,3 +15,4 @@ clippingIntersectionFilterV___UM_un_3C_s_5B__c_unRTCFilterFunctionNArguments_5D_ delete_uniform___un_3C_unv_3E_, delete_uniform_, precomputedZOrder_create___, +get_zorder___, diff --git a/ospray/render/util.ih b/ospray/render/util.ih index e193125bc..2dd94992d 100644 --- a/ospray/render/util.ih +++ b/ospray/render/util.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -94,3 +94,5 @@ inline void precomputeZOrder() if (!z_order_initialized) precomputedZOrder_create(); } + +extern const z_order_t *uniform get_zorder(); diff --git a/ospray/render/util.ispc b/ospray/render/util.ispc index 03ce450e1..4eb2b43f3 100644 --- a/ospray/render/util.ispc +++ b/ospray/render/util.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/World.ih" @@ -60,3 +60,8 @@ float computeAO(const World *uniform world, // cancel return 1.0f - (hits / (float)sampleCnt); } + +const z_order_t *uniform get_zorder() +{ + return &z_order; +} From 00210bf259c9afe837be2308258401848b7d0b58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20G=C3=BCnther?= Date: Wed, 15 Sep 2021 08:04:52 +0200 Subject: [PATCH 14/22] Fix sporadic slowdowns with VDB and structuredRegular --- CHANGELOG.md | 2 ++ cmake/ospray_options.cmake | 2 +- doc/compilation.md | 2 +- scripts/superbuild/CMakeLists.txt | 6 +++--- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3885cadc9..7cbb22d7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ Version History ### Changes in v2.7.1: +- Use Open VKL v1.0.1 to fix sporadic slowdowns when rendering + structured regular and VDB volumes with the SciVis renderer - Fix CMake variables and logic - Fix crash when transferfunction.opacity = 0 - Fix bug in MPI data-parallel rendering that caused rendering to hang diff --git a/cmake/ospray_options.cmake b/cmake/ospray_options.cmake index 05b222057..2f90f5d5b 100644 --- a/cmake/ospray_options.cmake +++ b/cmake/ospray_options.cmake @@ -13,7 +13,7 @@ set(OSPRAY_CMAKECONFIG_DIR set(RKCOMMON_VERSION_REQUIRED 1.7.0) set(EMBREE_VERSION_REQUIRED 3.13.1) -set(OPENVKL_VERSION_REQUIRED 1.0.0) +set(OPENVKL_VERSION_REQUIRED 1.0.1) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) diff --git a/doc/compilation.md b/doc/compilation.md index 9944abdb4..468a71052 100644 --- a/doc/compilation.md +++ b/doc/compilation.md @@ -44,7 +44,7 @@ before you can build OSPRay you need the following prerequisites: or newer is required. If Embree is not found by CMake its location can be hinted with the variable `embree_DIR`. - OSPRay also heavily uses Intel [Open VKL](https://www.openvkl.org/), - installing version 1.0.0 or newer is required. If Open VKL is not + installing version 1.0.1 or newer is required. If Open VKL is not found by CMake its location can be hinted with the variable `openvkl_DIR`. - OSPRay also provides an optional module implementing the `denoiser` diff --git a/scripts/superbuild/CMakeLists.txt b/scripts/superbuild/CMakeLists.txt index db05bba39..81e807a7c 100644 --- a/scripts/superbuild/CMakeLists.txt +++ b/scripts/superbuild/CMakeLists.txt @@ -116,9 +116,9 @@ if (EMBREE_VERSION STREQUAL "3.13.1") endif() endif() -set(OPENVKL_VERSION "1.0.0" CACHE STRING "Which version of OpenVKL to build?") -if (OPENVKL_VERSION STREQUAL "1.0.0") - set(OPENVKL_HASH "c2df70bec784a5ae42e2931d76d4feae51700c0b42cd5c2428b8ce6a64fffc34") +set(OPENVKL_VERSION "1.0.1" CACHE STRING "Which version of OpenVKL to build?") +if (OPENVKL_VERSION STREQUAL "1.0.1") + set(OPENVKL_HASH "dc37113adb7de12e503202633e54854b88dd612c3f914c1b9a5ae195c4c6c1be") endif() option(BUILD_OIDN "Build OpenImageDenoise as a part of the superbuild." OFF) From 965dd3d0adccf08aa4805fb1c9aa651f84c7e8f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20G=C3=BCnther?= Date: Fri, 24 Sep 2021 03:58:13 +0200 Subject: [PATCH 15/22] Use TBB 2021.3.0 --- scripts/superbuild/CMakeLists.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/superbuild/CMakeLists.txt b/scripts/superbuild/CMakeLists.txt index 81e807a7c..0e4dd1c05 100644 --- a/scripts/superbuild/CMakeLists.txt +++ b/scripts/superbuild/CMakeLists.txt @@ -85,17 +85,17 @@ endif() option(DOWNLOAD_TBB "Download TBB or use the only found in the system environment?" ON) option(BUILD_TBB_FROM_SOURCE "Build TBB from source or use pre-built version?" OFF) -set(TBB_VERSION "2021.2.0" CACHE STRING "Which version of TBB to download?") -if (TBB_VERSION STREQUAL "2021.2.0") +set(TBB_VERSION "2021.3.0" CACHE STRING "Which version of TBB to download?") +if (TBB_VERSION STREQUAL "2021.3.0") if (BUILD_TBB_FROM_SOURCE) - set(TBB_HASH "d3a75d98701f53d3dbd663809c74e93348602d02bc33c2039b1cf61427f15278") + set(TBB_HASH "aadd36731bdc38702868303a8d08a7e34c5beb54031c99976533e2ca18d4e9ed") else() if (APPLE) - set(TBB_HASH "ed6545190b747af9585ab8eedd5c8ccdf7cef304b6caa8db25803389fb24ec62") + set(TBB_HASH "1356e744c29763ee0a6de06647954eb076798c0b7a5b3c1008108d1d76cd42a5") elseif (WIN32) - set(TBB_HASH "9be37b1cb604a5905db0a15b2b893d85579fd0b2f1024859e1f75e96d7331a02") + set(TBB_HASH "90e2055cd4be55f79eedd3d50b2010bf05d1739309c4cdd219192d129e931093") else() - set(TBB_HASH "bcaa0aa7c0d2851a730cb0f64ad120f06a7b63811c8cc49e51ea8e1579f51b05") + set(TBB_HASH "3b2290f3db5521901d43490a5e92a414413a8fd2feac8b4bf763dbc04ba28f63") endif() endif() endif() From 6df5ab4cb5836c1b08b85c1f5443c6e5d84bfd82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20G=C3=BCnther?= Date: Fri, 24 Sep 2021 09:03:22 +0200 Subject: [PATCH 16/22] Improve messages when checking array parameters, closes #498 --- ospray/common/Data.h | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/ospray/common/Data.h b/ospray/common/Data.h index 119935a29..9bbda4447 100644 --- a/ospray/common/Data.h +++ b/ospray/common/Data.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -321,14 +321,20 @@ inline const Ref> ManagedObject::getParamDataT( } } - if (required) - throw std::runtime_error(toString() + " must have '" + name - + "' array with element type " + stringFor(OSPTypeFor::value)); - else { + if (required) { + std::string msg(toString() + " must have '" + name + "' " + + std::to_string(DIM) + "D array with element type " + + stringFor(OSPTypeFor::value)); + if (data) + msg.append(", found " + std::to_string(data->dimensions) + + "D array with element type " + stringFor(data->type)); + throw std::runtime_error(msg); + } else { if (data) { postStatusMsg(OSP_LOG_DEBUG) - << toString() << " ignoring '" << name - << "' array with wrong element type (should be " + << toString() << " ignoring '" << name << "' " << data->dimensions + << "D array with element type " << stringFor(data->type) + << " (while looking for " << DIM << "D array of " << stringFor(OSPTypeFor::value) << ")"; } return nullptr; From 52bbab32ca31773927150f839716ba9df9120de3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20G=C3=BCnther?= Date: Fri, 24 Sep 2021 08:26:15 +0200 Subject: [PATCH 17/22] Hide CMake superbuild options that are not used --- scripts/superbuild/CMakeLists.txt | 79 +++++++++++++++++++------------ 1 file changed, 49 insertions(+), 30 deletions(-) diff --git a/scripts/superbuild/CMakeLists.txt b/scripts/superbuild/CMakeLists.txt index 0e4dd1c05..4a3cc5984 100644 --- a/scripts/superbuild/CMakeLists.txt +++ b/scripts/superbuild/CMakeLists.txt @@ -66,16 +66,21 @@ endif() option(ALWAYS_REBUILD "Force every project to always be rebuilt?" OFF) -option(DOWNLOAD_ISPC "Download ISPC or use the one found in ${PATH}?" ON) -set(ISPC_VERSION "1.16.1" CACHE STRING "Which version of ISPC to download?") -if (ISPC_VERSION STREQUAL "1.16.1") - if (APPLE) - set(ISPC_HASH "7dbce602d97227a9603aabfae6dc3b3aa24d1cd44f0ccfb5ae47ecd4d68e988e") - elseif (WIN32) - set(ISPC_HASH "b34de2c36aff2afaa56b669ea41f9e614a045564ca74fc0b138e17ccea4880b7") - else() - set(ISPC_HASH "88db3d0461147c10ed81053a561ec87d3e14265227c03318f4fcaaadc831037f") +option(DOWNLOAD_ISPC "Download ISPC or use the one found in the system environment?" ON) +if (DOWNLOAD_ISPC) + set(ISPC_VERSION "1.16.1" CACHE STRING "Which version of ISPC to download?") + mark_as_advanced(CLEAR ISPC_VERSION) + if (ISPC_VERSION STREQUAL "1.16.1") + if (APPLE) + set(ISPC_HASH "7dbce602d97227a9603aabfae6dc3b3aa24d1cd44f0ccfb5ae47ecd4d68e988e") + elseif (WIN32) + set(ISPC_HASH "b34de2c36aff2afaa56b669ea41f9e614a045564ca74fc0b138e17ccea4880b7") + else() + set(ISPC_HASH "88db3d0461147c10ed81053a561ec87d3e14265227c03318f4fcaaadc831037f") + endif() endif() +else() + mark_as_advanced(FORCE ISPC_VERSION) endif() set(RKCOMMON_VERSION "1.7.0" CACHE STRING "Which version of rkcommon to build?") @@ -83,21 +88,28 @@ if (RKCOMMON_VERSION STREQUAL "1.7.0") set(RKCOMMON_HASH "b2eabd1dc56fd9de7cae320711ae07696385dc3151a56b63562396d0f5e2708e") endif() -option(DOWNLOAD_TBB "Download TBB or use the only found in the system environment?" ON) -option(BUILD_TBB_FROM_SOURCE "Build TBB from source or use pre-built version?" OFF) -set(TBB_VERSION "2021.3.0" CACHE STRING "Which version of TBB to download?") -if (TBB_VERSION STREQUAL "2021.3.0") - if (BUILD_TBB_FROM_SOURCE) - set(TBB_HASH "aadd36731bdc38702868303a8d08a7e34c5beb54031c99976533e2ca18d4e9ed") - else() - if (APPLE) - set(TBB_HASH "1356e744c29763ee0a6de06647954eb076798c0b7a5b3c1008108d1d76cd42a5") - elseif (WIN32) - set(TBB_HASH "90e2055cd4be55f79eedd3d50b2010bf05d1739309c4cdd219192d129e931093") +option(DOWNLOAD_TBB "Download TBB or use the one found in the system environment?" ON) +if (DOWNLOAD_TBB) + set(TBB_VERSION "2021.3.0" CACHE STRING "Which version of TBB to download?") + mark_as_advanced(CLEAR TBB_VERSION) + option(BUILD_TBB_FROM_SOURCE "Build TBB from source or use pre-built version?" OFF) + mark_as_advanced(CLEAR BUILD_TBB_FROM_SOURCE) + if (TBB_VERSION STREQUAL "2021.3.0") + if (BUILD_TBB_FROM_SOURCE) + set(TBB_HASH "aadd36731bdc38702868303a8d08a7e34c5beb54031c99976533e2ca18d4e9ed") else() - set(TBB_HASH "3b2290f3db5521901d43490a5e92a414413a8fd2feac8b4bf763dbc04ba28f63") + if (APPLE) + set(TBB_HASH "1356e744c29763ee0a6de06647954eb076798c0b7a5b3c1008108d1d76cd42a5") + elseif (WIN32) + set(TBB_HASH "90e2055cd4be55f79eedd3d50b2010bf05d1739309c4cdd219192d129e931093") + else() + set(TBB_HASH "3b2290f3db5521901d43490a5e92a414413a8fd2feac8b4bf763dbc04ba28f63") + endif() endif() endif() +else() + mark_as_advanced(FORCE TBB_VERSION) + mark_as_advanced(FORCE BUILD_TBB_FROM_SOURCE) endif() option(BUILD_EMBREE_FROM_SOURCE "Build Embree or use pre-built version?" ON) @@ -122,16 +134,23 @@ if (OPENVKL_VERSION STREQUAL "1.0.1") endif() option(BUILD_OIDN "Build OpenImageDenoise as a part of the superbuild." OFF) -option(BUILD_OIDN_FROM_SOURCE "Build OpenImageDenoise or use pre-built version?" OFF) -set(OIDN_VERSION "1.4.1" CACHE STRING "Which version of OpenImageDenoise to build?") -if (OIDN_VERSION STREQUAL "1.4.1") - if (APPLE) - set(OIDN_HASH "0ac6b2e16ff5f1b7ff75f19e5889f291bb36d66b84446bee06ff169cfe19f265") - elseif (WIN32) - set(OIDN_HASH "4ea0492de4fc47951ab5fc53b4e3433f39677d3fbfc1541eabc4ccee82bfc4d1") - else() - set(OIDN_HASH "efdf8fafb47017d7b1b321cbc88cb1bfcbdbe2746be57ed4a2ae90431fc9eb3a") +if (BUILD_OIDN) + set(OIDN_VERSION "1.4.1" CACHE STRING "Which version of OpenImageDenoise to build?") + mark_as_advanced(CLEAR OIDN_VERSION) + option(BUILD_OIDN_FROM_SOURCE "Build OpenImageDenoise or use pre-built version?" OFF) + mark_as_advanced(CLEAR BUILD_OIDN_FROM_SOURCE) + if (OIDN_VERSION STREQUAL "1.4.1") + if (APPLE) + set(OIDN_HASH "0ac6b2e16ff5f1b7ff75f19e5889f291bb36d66b84446bee06ff169cfe19f265") + elseif (WIN32) + set(OIDN_HASH "4ea0492de4fc47951ab5fc53b4e3433f39677d3fbfc1541eabc4ccee82bfc4d1") + else() + set(OIDN_HASH "efdf8fafb47017d7b1b321cbc88cb1bfcbdbe2746be57ed4a2ae90431fc9eb3a") + endif() endif() +else() + mark_as_advanced(FORCE OIDN_VERSION) + mark_as_advanced(FORCE BUILD_OIDN_FROM_SOURCE) endif() option(BUILD_GLFW "Build glfw for OSPRay examples or use one in existing environment?" ON) From 9314f9d15445403ff4c5499ea19f46ba04dcf18d Mon Sep 17 00:00:00 2001 From: Trevor Thomson Date: Mon, 27 Sep 2021 17:42:21 -0400 Subject: [PATCH 18/22] Revert "Include secondary dependencies via -I instead of -isystem." This reverts commit 5d88a8cd84268c07ec7632bd6a4a2e71f5c377b6. --- scripts/superbuild/CMakeLists.txt | 11 ----------- scripts/superbuild/build_ospray.cmake | 1 - scripts/superbuild/dependencies/dep_embree.cmake | 1 - scripts/superbuild/dependencies/dep_oidn.cmake | 1 - scripts/superbuild/dependencies/dep_openvkl.cmake | 1 - scripts/superbuild/dependencies/dep_rkcommon.cmake | 1 - 6 files changed, 16 deletions(-) diff --git a/scripts/superbuild/CMakeLists.txt b/scripts/superbuild/CMakeLists.txt index 4a3cc5984..36252739c 100644 --- a/scripts/superbuild/CMakeLists.txt +++ b/scripts/superbuild/CMakeLists.txt @@ -45,17 +45,6 @@ include(CMakeDependentOption) ## Superbuild options ## -## Include imported target headers with -I rather than -isystem to ensure they're -## included prior to any CPATH headers -cmake_dependent_option( - CMAKE_NO_SYSTEM_FROM_IMPORTED - "Disable -isystem for dependency include paths" - ON - "NOT BUILD_OSPRAY_CI_EXTRAS" - OFF -) -mark_as_advanced(CMAKE_NO_SYSTEM_FROM_IMPORTED) - ProcessorCount(PROCESSOR_COUNT) if(NOT PROCESSOR_COUNT EQUAL 0) diff --git a/scripts/superbuild/build_ospray.cmake b/scripts/superbuild/build_ospray.cmake index 1dc5d5165..d9e048251 100644 --- a/scripts/superbuild/build_ospray.cmake +++ b/scripts/superbuild/build_ospray.cmake @@ -41,7 +41,6 @@ ExternalProject_Add(${COMPONENT_NAME} -DOSPRAY_MODULE_MULTIDEVICE=${OSPRAY_MODULE_MULTIDEVICE} $<$:-DISPC_EXECUTABLE=${ISPC_PATH}> $<$:-DRKCOMMON_TBB_ROOT=${TBB_PATH}> - -DCMAKE_NO_SYSTEM_FROM_IMPORTED=${CMAKE_NO_SYSTEM_FROM_IMPORTED} -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} BUILD_COMMAND ${DEFAULT_BUILD_COMMAND} diff --git a/scripts/superbuild/dependencies/dep_embree.cmake b/scripts/superbuild/dependencies/dep_embree.cmake index a6aeac84f..8d4211fcc 100644 --- a/scripts/superbuild/dependencies/dep_embree.cmake +++ b/scripts/superbuild/dependencies/dep_embree.cmake @@ -34,7 +34,6 @@ if (BUILD_EMBREE_FROM_SOURCE) -DCMAKE_INSTALL_BINDIR=${CMAKE_INSTALL_BINDIR} $<$:-DEMBREE_TBB_ROOT=${TBB_PATH}> $<$:-DEMBREE_ISPC_EXECUTABLE=${ISPC_PATH}> - -DCMAKE_NO_SYSTEM_FROM_IMPORTED=${CMAKE_NO_SYSTEM_FROM_IMPORTED} -DCMAKE_BUILD_TYPE=${DEPENDENCIES_BUILD_TYPE} -DEMBREE_TUTORIALS=OFF -DBUILD_TESTING=OFF diff --git a/scripts/superbuild/dependencies/dep_oidn.cmake b/scripts/superbuild/dependencies/dep_oidn.cmake index 2f72e9268..6393fcd40 100644 --- a/scripts/superbuild/dependencies/dep_oidn.cmake +++ b/scripts/superbuild/dependencies/dep_oidn.cmake @@ -31,7 +31,6 @@ if (BUILD_OIDN_FROM_SOURCE) -DCMAKE_INSTALL_BINDIR=${CMAKE_INSTALL_BINDIR} $<$:-DTBB_ROOT=${TBB_PATH}> $<$:-DISPC_EXECUTABLE=${ISPC_PATH}> - -DCMAKE_NO_SYSTEM_FROM_IMPORTED=${CMAKE_NO_SYSTEM_FROM_IMPORTED} -DCMAKE_BUILD_TYPE=${DEPENDENCIES_BUILD_TYPE} -DOIDN_APPS=OFF -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} diff --git a/scripts/superbuild/dependencies/dep_openvkl.cmake b/scripts/superbuild/dependencies/dep_openvkl.cmake index f2a9e540a..41977f48d 100644 --- a/scripts/superbuild/dependencies/dep_openvkl.cmake +++ b/scripts/superbuild/dependencies/dep_openvkl.cmake @@ -35,7 +35,6 @@ ExternalProject_Add(${COMPONENT_NAME} -DCMAKE_BUILD_TYPE=${DEPENDENCIES_BUILD_TYPE} $<$:-DRKCOMMON_TBB_ROOT=${TBB_PATH}> $<$:-DISPC_EXECUTABLE=${ISPC_PATH}> - -DCMAKE_NO_SYSTEM_FROM_IMPORTED=${CMAKE_NO_SYSTEM_FROM_IMPORTED} -DBUILD_BENCHMARKS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF diff --git a/scripts/superbuild/dependencies/dep_rkcommon.cmake b/scripts/superbuild/dependencies/dep_rkcommon.cmake index e1e78093b..9b9656c9c 100644 --- a/scripts/superbuild/dependencies/dep_rkcommon.cmake +++ b/scripts/superbuild/dependencies/dep_rkcommon.cmake @@ -33,7 +33,6 @@ ExternalProject_Add(${COMPONENT_NAME} -DINSTALL_DEPS=OFF -DBUILD_TESTING=OFF $<$:-DRKCOMMON_TBB_ROOT=${TBB_PATH}> - -DCMAKE_NO_SYSTEM_FROM_IMPORTED=${CMAKE_NO_SYSTEM_FROM_IMPORTED} -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} BUILD_COMMAND ${DEFAULT_BUILD_COMMAND} From c101314b1e2ff1695851bea113736ed1fc4ddc99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20G=C3=BCnther?= Date: Tue, 28 Sep 2021 04:22:14 +0200 Subject: [PATCH 19/22] Correctly init frameProgress, fixes #501 --- CHANGELOG.md | 1 + ospray/fb/FrameBuffer.cpp | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cbb22d7d..baf6558c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Version History - Fix bug in MPI data-parallel rendering that caused rendering to hang - Workaround dynamic linking issue on Windows in MPI distributed rendering +- Correctly initialize renderFrame progress - Improved performance of data-parallel rendering for scenes with a large number of regions - Expanded camera model support of the data-parallel renderer, diff --git a/ospray/fb/FrameBuffer.cpp b/ospray/fb/FrameBuffer.cpp index d18215ae8..3b84aabfa 100644 --- a/ospray/fb/FrameBuffer.cpp +++ b/ospray/fb/FrameBuffer.cpp @@ -75,6 +75,7 @@ utility::ArrayView FrameBuffer::getTileIDs() void FrameBuffer::beginFrame() { + frameProgress = 0.0f; cancelRender = false; frameID++; ispc::FrameBuffer_set_frameID(getIE(), frameID); @@ -87,6 +88,10 @@ std::string FrameBuffer::toString() const void FrameBuffer::setCompletedEvent(OSPSyncEvent event) { + if (event == OSP_NONE_FINISHED) + frameProgress = 0.0f; + if (event == OSP_FRAME_FINISHED) + frameProgress = 1.0f; stagesCompleted = event; } From 97d66513dfb9dc352ff2eb1b3d9ea63eacb2f229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20G=C3=BCnther?= Date: Wed, 29 Sep 2021 03:43:50 +0200 Subject: [PATCH 20/22] Clarify clipping, closes #500 --- doc/api.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/api.md b/doc/api.md index 0c844c736..c402b47e1 100644 --- a/doc/api.md +++ b/doc/api.md @@ -1697,16 +1697,16 @@ group. By adding `OSPGeometricModel`s to the `clippingGeometry` array a clipping geometry feature is enabled. Geometries assigned to this parameter will be used as clipping geometries. Any supported geometry -can be used for clipping. The only requirement is that it has to -distinctly partition space into clipping and non-clipping one. These -include: spheres, boxes, infinite planes, closed meshes, closed -subdivisions and curves. All geometries and volumes assigned to -`geometry` or `volume` will be clipped. Use of clipping geometry that is -not closed (or infinite) will result in rendering artifacts. User can -decide which part of space is clipped by changing shading normals -orientation with the `invertNormals` flag of the [GeometricModel]. When -more than single clipping geometry is defined all clipping areas will be -"added" together – an union of these areas will be applied. +can be used for clipping^[including spheres, boxes, infinite planes, +closed meshes, closed subdivisions and curves], the only requirement is +that it has to distinctly partition space into clipping and non-clipping +one. The use of clipping geometry that is not closed or infinite could +result in rendering artifacts. User can decide which part of space is +clipped by changing shading normals orientation with the `invertNormals` +flag of the [GeometricModel]. All geometries and volumes assigned to +`geometry` or `volume` will be clipped. All clipping geometries from all +groups and [Instances] will be combined together – a union of these +areas will be applied to all other objects in the [world]. -------------------- ---------------- ---------- -------------------------------------- Type Name Default Description From dc98c565530c212b364f4660d61049c91392e15a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20G=C3=BCnther?= Date: Thu, 30 Sep 2021 03:53:34 +0200 Subject: [PATCH 21/22] Clarify that API calls after shutdown are invalid, closes #432 --- CHANGELOG.md | 1 + ospray/api/API.cpp | 11 ++++++----- ospray/common/OSPCommon.cpp | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index baf6558c1..f2203ad5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Version History - Expanded camera model support of the data-parallel renderer, data-parallel rendering can now use all the camera models supported by the scivis renderer +- Clarify documentation and error messages ### Changes in v2.7.0: diff --git a/ospray/api/API.cpp b/ospray/api/API.cpp index 88c949e9a..8112d323c 100644 --- a/ospray/api/API.cpp +++ b/ospray/api/API.cpp @@ -31,11 +31,12 @@ using ospray::api::deviceIsSet; #define THROW_IF_NULL_OBJECT(obj) THROW_IF_NULL(obj, "handle") #define THROW_IF_NULL_STRING(str) THROW_IF_NULL(str, "string") -#define ASSERT_DEVICE() \ - if (!deviceIsSet()) \ - throw std::runtime_error( \ - "OSPRay not yet initialized (most likely this means you tried to " \ - "call an ospray API function before first calling ospInit()), pid: " \ +#define ASSERT_DEVICE() \ + if (!deviceIsSet()) \ + throw std::runtime_error( \ + "no valid OSPRay device while calling an API function, likely" \ + " either before calling ospInit() / ospNewDevice() plus ospSetCurrentDevice()," \ + " or after calling ospShutdown() / ospDeviceRelease(); pid: " \ + std::to_string(getpid())) #define OSPRAY_CATCH_BEGIN \ diff --git a/ospray/common/OSPCommon.cpp b/ospray/common/OSPCommon.cpp index 8f8ffaedb..3daf0cb85 100644 --- a/ospray/common/OSPCommon.cpp +++ b/ospray/common/OSPCommon.cpp @@ -811,7 +811,7 @@ void handleError(OSPError e, const std::string &message) } else { // NOTE: No device, but something should still get printed for the user to // debug the calling application. - std::cerr << "#ospray: INITIALIZATION ERROR --> " << message << std::endl; + std::cerr << "#ospray: INVALID device --> " << message << std::endl; } } From bdde2c848d0e26248abb4acb50a70359451ffcdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20G=C3=BCnther?= Date: Thu, 30 Sep 2021 04:28:48 +0200 Subject: [PATCH 22/22] Sync README --- README.md | 50 ++++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 8c15bb81c..06d06b412 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ OSPRay ====== -This is release v2.7.0 of Intel® OSPRay. For changes and new features +This is release v2.7.1 of Intel® OSPRay. For changes and new features see the [changelog](CHANGELOG.md). Visit http://www.ospray.org for more information. @@ -100,7 +100,7 @@ before you can build OSPRay you need the following prerequisites: `embree_DIR`. - OSPRay also heavily uses Intel [Open VKL](https://www.openvkl.org/), - installing version 1.0.0 or newer is required. If Open VKL is not + installing version 1.0.1 or newer is required. If Open VKL is not found by CMake its location can be hinted with the variable `openvkl_DIR`. @@ -1782,17 +1782,16 @@ group. By adding `OSPGeometricModel`s to the `clippingGeometry` array a clipping geometry feature is enabled. Geometries assigned to this parameter will be used as clipping geometries. Any supported geometry -can be used for clipping. The only requirement is that it has to -distinctly partition space into clipping and non-clipping one. These -include: spheres, boxes, infinite planes, closed meshes, closed -subdivisions and curves. All geometries and volumes assigned to -`geometry` or `volume` will be clipped. Use of clipping geometry that is -not closed (or infinite) will result in rendering artifacts. User can -decide which part of space is clipped by changing shading normals -orientation with the `invertNormals` flag of the -[GeometricModel](#geometricmodels). When more than single clipping -geometry is defined all clipping areas will be “added” together – an -union of these areas will be applied. +can be used for clipping[6], the only requirement is that it has to +distinctly partition space into clipping and non-clipping one. The use +of clipping geometry that is not closed or infinite could result in +rendering artifacts. User can decide which part of space is clipped by +changing shading normals orientation with the `invertNormals` flag of +the [GeometricModel](#geometricmodels). All geometries and volumes +assigned to `geometry` or `volume` will be clipped. All clipping +geometries from all groups and [Instances](#instances) will be combined +together – a union of these areas will be applied to all other objects +in the [world](#world). | Type | Name | Default | Description | |:-----------------------|:-----------------|--------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -1848,7 +1847,7 @@ world has been committed. To get this information, call OSPBounds ospGetBounds(OSPObject); ``` -The result is returned in the provided `OSPBounds`[6] struct: +The result is returned in the provided `OSPBounds`[7] struct: ``` cpp typedef struct { @@ -1957,7 +1956,7 @@ renderers, the SciVis renderer supports the following parameters: Special parameters understood by the SciVis renderer. Note that the intensity (and color) of AO is deduced from an [ambient -light](#ambient-light) in the `lights` array.[7] If `aoSamples` is zero +light](#ambient-light) in the `lights` array.[8] If `aoSamples` is zero (the default) then ambient lights cause ambient illumination (without occlusion). @@ -2074,7 +2073,7 @@ the opacity `d`. Normal mapping can simulate small geometric features via the texture `map_Bump`. The normals *n* in the normal map are with respect to the local tangential shading coordinate system and are encoded as -½(*n* + 1), thus a texel (0.5, 0.5, 1)[8] represents the unperturbed +½(*n* + 1), thus a texel (0.5, 0.5, 1)[9] represents the unperturbed shading normal (0, 0, 1). Because of this encoding an sRGB gamma [texture](#texture) format is ignored and normals are always fetched as linear from a normal map. Note that the orientation of normal maps is @@ -3225,7 +3224,7 @@ ospTutorial A minimal working example demonstrating how to use OSPRay can be found at -[`apps/tutorials/ospTutorial.c`](https://github.com/ospray/ospray/blob/master/apps/ospTutorial/ospTutorial.c)[9]. +[`apps/tutorials/ospTutorial.c`](https://github.com/ospray/ospray/blob/master/apps/ospTutorial/ospTutorial.c)[10]. An example of building `ospTutorial.c` with CMake can be found in [`apps/tutorials/ospTutorialFindospray/`](https://github.com/ospray/ospray/tree/master/apps/ospTutorial/ospTutorialFindospray). @@ -3384,7 +3383,7 @@ ospMPIDistribTutorial A minimal working example demonstrating how to use OSPRay for rendering distributed data can be found at -[`modules/mpi/tutorials/ospMPIDistribTutorial.c`](https://github.com/ospray/ospray/blob/master/modules/mpi/tutorials/ospMPIDistribTutorial.c)[10]. +[`modules/mpi/tutorials/ospMPIDistribTutorial.c`](https://github.com/ospray/ospray/blob/master/modules/mpi/tutorials/ospMPIDistribTutorial.c)[11]. The compilation process via CMake is the similar to [`apps/tutorials/ospTutorialFindospray/`](https://github.com/ospray/ospray/tree/master/apps/ospTutorial/ospTutorialFindospray), @@ -3508,22 +3507,25 @@ voxel changes the quickest. [5] actually a parallelogram -[6] `OSPBounds` has essentially the same layout as the `OSP_BOX3F` +[6] including spheres, boxes, infinite planes, closed meshes, closed +subdivisions and curves + +[7] `OSPBounds` has essentially the same layout as the `OSP_BOX3F` [`OSPDataType`](#data). -[7] If there are multiple ambient lights then their contribution is +[8] If there are multiple ambient lights then their contribution is added. -[8] respectively (127, 127, 255) for 8 bit textures and +[9] respectively (127, 127, 255) for 8 bit textures and (32767, 32767, 65535) for 16 bit textures -[9] A C++ version that uses the C++ convenience wrappers of OSPRay’s C99 -API via +[10] A C++ version that uses the C++ convenience wrappers of OSPRay’s +C99 API via [`include/ospray/ospray_cpp.h`](https://github.com/ospray/ospray/blob/master/ospray/include/ospray/ospray_cpp.h) is available at [`apps/tutorials/ospTutorial.cpp`](https://github.com/ospray/ospray/blob/master/apps/ospTutorial/ospTutorial.cpp). -[10] A C++ version that uses the C++ convenience wrappers of OSPRay’s +[11] A C++ version that uses the C++ convenience wrappers of OSPRay’s C99 API via [`include/ospray/ospray_cpp.h`](https://github.com/ospray/ospray/blob/master/ospray/include/ospray/ospray_cpp.h) is available at