diff --git a/.gitignore b/.gitignore index f069c56858..953d84646b 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,5 @@ readme.pdf .idea/ premake.local.* cmake-build*/ +.clangd +compile_commands.json diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 482d5fecb0..1a33d7d1b5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 stages: @@ -16,21 +16,41 @@ variables: GIT_DEPTH: "15" ErrorActionPreference: STOP -.job_template: &build_job_docker - stage: build - tags: [docker] - image: $DOCKER_REGISTRY/ospray/docker-images:arch # default image - script: - - scripts/build_gitlab/linux.sh +.job_template: &archlinux + tags: [ docker ] + image: $DOCKER_REGISTRY/ospray/docker-images:arch -.job_template: &build_job_docker_modules - stage: build - tags: - - docker - - modules +.job_template: ¢os7 + tags: [ docker, modules ] + image: $DOCKER_REGISTRY/centos:7 + +.job_template: ¢os7-gcc4 + tags: [ docker, modules ] image: $DOCKER_REGISTRY/ospray/docker-images:centos7-mod - script: - - scripts/build_gitlab/linux.sh + +.job_template: ¢os8 + tags: [ docker ] + image: $DOCKER_REGISTRY/ospray/docker-images:centos8 + +.job_template: &ubuntu1604 + tags: [ docker ] + image: $DOCKER_REGISTRY/ospray/docker-images:ubuntu16.04 + +.job_template: &ubuntu1804 + tags: [ docker ] + image: $DOCKER_REGISTRY/ospray/docker-images:ubuntu18.04 + +.job_template: &ubuntu2004 + tags: [ docker ] + image: $DOCKER_REGISTRY/ospray/docker-images:ubuntu20.04 + +.job_template: &docu + tags: [docker] + image: $DOCKER_REGISTRY/ospray/docker-images:docu + +.job_template: &clamav + tags: [docker] + image: $DOCKER_REGISTRY/clamav:ubuntu20.04 .job_template: &build_artifacts artifacts: @@ -122,31 +142,36 @@ variables: ### BUILD JOBS ### build-arch-gcc: - <<: *build_job_docker + <<: *archlinux + stage: build script: - scripts/build_gitlab/linux.sh -G Ninja -DBUILD_GLFW=OFF build-arch-clang: - <<: *build_job_docker + <<: *archlinux + stage: build script: - export CC=clang - export CXX=clang++ - scripts/build_gitlab/linux.sh -G Ninja -DBUILD_GLFW=OFF build-arch-gcc-extras: - <<: *build_job_docker + <<: *archlinux + stage: build script: - scripts/build_gitlab/linux.sh -G Ninja -DBUILD_GLFW=OFF -DBUILD_OSPRAY_CI_EXTRAS=ON -DBUILD_OIDN=ON build-arch-clang-extras: - <<: *build_job_docker + <<: *archlinux + stage: build script: - export CC=clang - export CXX=clang++ - scripts/build_gitlab/linux.sh -G Ninja -DBUILD_GLFW=OFF -DBUILD_OSPRAY_CI_EXTRAS=ON -DBUILD_OIDN=ON build-arch-clang-devel: - <<: *build_job_docker + <<: *archlinux + stage: build script: - export CC=clang - export CXX=clang++ @@ -154,7 +179,8 @@ build-arch-clang-devel: only: [schedules] build-linux-debug-all: - <<: *build_job_docker + <<: *archlinux + stage: build script: - export CC=clang - export CXX=clang++ @@ -163,35 +189,36 @@ build-linux-debug-all: only: [schedules] build-ubuntu1604-gcc: - <<: *build_job_docker - image: $DOCKER_REGISTRY/ospray/docker-images:ubuntu16.04 + <<: *ubuntu1604 + stage: build script: - scripts/build_gitlab/linux.sh -G Ninja <<: *build_artifacts build-ubuntu1804-gcc: - <<: *build_job_docker - image: $DOCKER_REGISTRY/ospray/docker-images:ubuntu18.04 + <<: *ubuntu1804 + stage: build script: - scripts/build_gitlab/linux.sh -G Ninja -DBUILD_GLFW=OFF <<: *build_artifacts build-ubuntu2004-gcc: - <<: *build_job_docker - image: $DOCKER_REGISTRY/ospray/docker-images:ubuntu20.04 + <<: *ubuntu2004 + stage: build script: - scripts/build_gitlab/linux.sh -G Ninja -DBUILD_GLFW=OFF -DBUILD_OSPRAY_MODULE_MULTIDEVICE=ON <<: *build_artifacts build-centos8: - <<: *build_job_docker - image: $DOCKER_REGISTRY/ospray/docker-images:centos8 + <<: *centos8 + stage: build script: - scripts/build_gitlab/linux.sh -G Ninja <<: *build_artifacts build-centos7-icc: - <<: *build_job_docker_modules + <<: *centos7-gcc4 + stage: build script: - module load cmake - module load intel @@ -200,7 +227,8 @@ build-centos7-icc: - scripts/build_gitlab/linux.sh build-centos7-icc15: - <<: *build_job_docker_modules + <<: *centos7-gcc4 + stage: build script: - module load cmake - module load intel/2015 @@ -208,13 +236,29 @@ build-centos7-icc15: - export CXX=icpc - scripts/build_gitlab/linux.sh +build-centos7-icx: + <<: *centos7 + stage: build + script: + - module load cmake + - module load intel/2022.1 + - export CC=icx + - export CXX=icpx + - export CXXFLAGS="-fhonor-infinities -fhonor-nans" + - export LDFLAGS="-static-intel" + - scripts/build_gitlab/linux.sh + <<: *build_artifacts + build-centos7-gcc: - <<: *build_job_docker - image: $DOCKER_REGISTRY/ospray/docker-images:centos7 + <<: *centos7 + stage: build + script: + - scripts/build_gitlab/linux.sh <<: *build_artifacts build-centos7-mpi-impi: - <<: *build_job_docker_modules + <<: *centos7 + stage: build script: - module load cmake - module load intel/2021.2 @@ -222,14 +266,16 @@ build-centos7-mpi-impi: <<: *build_artifacts build-centos7-mpi-openmpi: - <<: *build_job_docker_modules + <<: *centos7 + stage: build script: - module load cmake - module load mpi/openmpi-x86_64 - scripts/build_gitlab/linux.sh -DBUILD_OSPRAY_MODULE_MPI=ON build-centos7-mpi-mpich: - <<: *build_job_docker_modules + <<: *centos7 + stage: build script: - module load cmake - module load mpi/mpich-x86_64 @@ -237,15 +283,15 @@ build-centos7-mpi-mpich: <<: *build_artifacts build-centos8-mpi-openmpi: - <<: *build_job_docker - image: $DOCKER_REGISTRY/ospray/docker-images:centos8 + <<: *centos8 + stage: build script: - module load mpi/openmpi-x86_64 - scripts/build_gitlab/linux.sh -DBUILD_OSPRAY_MODULE_MPI=ON build-centos8-mpi-mpich: - <<: *build_job_docker - image: $DOCKER_REGISTRY/ospray/docker-images:centos8 + <<: *centos8 + stage: build script: - module load mpi/mpich-x86_64 - scripts/build_gitlab/linux.sh -DBUILD_OSPRAY_MODULE_MPI=ON @@ -262,7 +308,8 @@ build-mpi-cluster: only: [schedules] build-linux-debug: - <<: *build_job_docker + <<: *archlinux + stage: build script: - export CFLAGS=-fsanitize=address - export CXXFLAGS=-fsanitize=address @@ -330,48 +377,53 @@ build-windows-msvc16-mpi_and_md: ### TEST JOBS ### test-centos7-gcc-avx2: + <<: *centos7 <<: *test_job_unix_avx2 - image: $DOCKER_REGISTRY/ospray/docker-images:centos7 needs: [build-centos7-gcc] +test-centos7-icx-avx2: + <<: *centos7 + <<: *test_job_unix_avx2 + needs: [build-centos7-icx] + test-centos8-avx512skx: + <<: *centos8 <<: *test_job_unix_avx512skx - image: $DOCKER_REGISTRY/ospray/docker-images:centos8 needs: [build-centos8] test-ubuntu1604-gcc-avx2: + <<: *ubuntu1604 <<: *test_job_unix_avx2 - image: $DOCKER_REGISTRY/ospray/docker-images:ubuntu16.04 needs: [build-ubuntu1604-gcc] test-ubuntu1804-gcc-avx512skx: + <<: *ubuntu1804 <<: *test_job_unix_avx512skx - image: $DOCKER_REGISTRY/ospray/docker-images:ubuntu18.04 needs: [build-ubuntu1804-gcc] test-ubuntu2004-gcc-avx2: + <<: *ubuntu2004 <<: *test_job_unix_avx2 - image: $DOCKER_REGISTRY/ospray/docker-images:ubuntu20.04 needs: [build-ubuntu2004-gcc] test-ubuntu2004-gcc-avx512skx: + <<: *ubuntu2004 <<: *test_job_unix_avx512skx - image: $DOCKER_REGISTRY/ospray/docker-images:ubuntu20.04 needs: [build-ubuntu2004-gcc] script: - LD_LIBRARY_PATH="$CI_PROJECT_DIR/build/install/ospray/lib:$LD_LIBRARY_PATH" PATH="$CI_PROJECT_DIR/build/install/ospray/bin:$PATH" scripts/tests/run_tests.sh "$CI_PROJECT_DIR" AVX512SKX TEST_MULTIDEVICE test-centos7-gcc-mpi-mpich-avx2: + <<: *centos7 <<: *test_job_unix_mpi_avx2 - image: $DOCKER_REGISTRY/ospray/docker-images:centos7-mod needs: [build-centos7-mpi-mpich] before_script: - module load cmake - module load mpi/mpich-x86_64 test-centos7-gcc-mpi-impi-avx2: + <<: *centos7 <<: *test_job_unix_mpi_avx2 - image: $DOCKER_REGISTRY/ospray/docker-images:centos7-mod needs: [build-centos7-mpi-impi] before_script: - module load cmake @@ -391,13 +443,13 @@ test-mpi-cluster: only: [schedules] sanitize-linux-debug: + <<: *archlinux <<: *test_job_unix_sanitize - image: $DOCKER_REGISTRY/ospray/docker-images:arch needs: [build-linux-debug] test-linux-debug-all: + <<: *archlinux <<: *test_job_unix_avx512skx - image: $DOCKER_REGISTRY/ospray/docker-images:arch needs: [build-linux-debug-all] only: [schedules] @@ -413,22 +465,18 @@ test-osx-arm: tags: [mac-arm] needs: [build-osx-arm] script: - - DYLD_FALLBACK_LIBRARY_PATH="$CI_PROJECT_DIR/build/install/ospray/lib:$DYLD_FALLBACK_LIBRARY_PATH" PATH="$CI_PROJECT_DIR/build/install/ospray/bin:$PATH" scripts/tests/run_tests.sh "$CI_PROJECT_DIR" AVX2 + - DYLD_FALLBACK_LIBRARY_PATH="$CI_PROJECT_DIR/build/install/ospray/lib:$DYLD_FALLBACK_LIBRARY_PATH" PATH="$CI_PROJECT_DIR/build/install/ospray/bin:$PATH" scripts/tests/run_tests.sh "$CI_PROJECT_DIR" AVX512SKX test-tutorials: + <<: *centos7 stage: test - tags: [docker] - image: $DOCKER_REGISTRY/ospray/docker-images:centos7 needs: [build-centos7-gcc] script: - scripts/tests/run_tutorials.sh test-find-ospray: + <<: *centos7 stage: test - tags: - - docker - - modules - image: $DOCKER_REGISTRY/ospray/docker-images:centos7-mod needs: [build-centos7-gcc] script: - module load cmake @@ -439,7 +487,7 @@ test-find-ospray: test-windows-msvc15-avx2: <<: *test_job_windows_avx2 - tags: [win, msvc15, avx2] + tags: [win, msvc15, only-avx2] needs: [build-windows-msvc15] allow_failure: true @@ -450,13 +498,13 @@ test-windows-msvc15-avx512skx: test-windows-debug-all: <<: *test_job_windows_avx2 - tags: [win, msvc15, avx2] + tags: [win, msvc15, only-avx2] needs: [build-windows-debug-all] only: [schedules] test-windows-msvc16-avx2: <<: *test_job_windows_avx2 - tags: [win, msvc16, avx2, mpi] + tags: [win, msvc16, only-avx2, mpi] needs: [build-windows-msvc16-mpi_and_md] allow_failure: true script: @@ -472,8 +520,8 @@ test-windows-msvc16-avx512skx: - scripts\tests\run_tests.ps1 "$CI_PROJECT_DIR" AVX512SKX TEST_MULTIDEVICE TEST_MPI generate-ci-baseline-avx2: + <<: *ubuntu2004 <<: *test_job_unix_avx2 - image: $DOCKER_REGISTRY/ospray/docker-images:ubuntu20.04 needs: [build-ubuntu2004-gcc] script: - LD_LIBRARY_PATH="$CI_PROJECT_DIR/build/install/ospray/lib:$LD_LIBRARY_PATH" PATH="$CI_PROJECT_DIR/build/install/ospray/bin:$PATH" scripts/tests/generate_baseline.sh @@ -484,8 +532,8 @@ generate-ci-baseline-avx2: when: manual generate-ci-baseline-avx512skx: + <<: *ubuntu2004 <<: *test_job_unix_avx512skx - image: $DOCKER_REGISTRY/ospray/docker-images:ubuntu20.04 needs: [build-ubuntu2004-gcc] script: - LD_LIBRARY_PATH="$CI_PROJECT_DIR/build/install/ospray/lib:$LD_LIBRARY_PATH" PATH="$CI_PROJECT_DIR/build/install/ospray/bin:$PATH" scripts/tests/generate_baseline.sh @@ -542,9 +590,8 @@ benchmark-tgl-1-schedule: ### Documentation ### .job_template: &doc-defaults + <<: *docu stage: docu - tags: [docker] - image: $DOCKER_REGISTRY/ospray/docker-images:docu needs: [] variables: GIT_SUBMODULE_STRATEGY: normal @@ -586,13 +633,17 @@ spec: ### RELEASE JOBS ### release-linux: + <<: *centos7 <<: *release_job - tags: [modules] - image: $DOCKER_REGISTRY/ospray/docker-images:centos7-mod script: - source $SPACK_SETUP_ENV - module load cmake/3.15.2 - module load mpich/3.2 + - module load intel/2022.1 + - export CC=icx + - export CXX=icpx + - export CXXFLAGS="-fhonor-infinities -fhonor-nans" + - export LDFLAGS="-static-intel" - scripts/release/linux.sh artifacts: paths: @@ -636,9 +687,8 @@ release-windows: ### SCAN JOBS ### kw-build: + <<: *centos7 stage: scan1 - tags: [docker] - image: $DOCKER_REGISTRY/ospray/docker-images:centos7-mod needs: [] script: - module load cmake @@ -652,25 +702,22 @@ kw-build: expire_in: 3 day protex: + <<: *centos7 stage: scan1 - tags: [docker] - image: $DOCKER_REGISTRY/ospray/docker-images:centos7 needs: [] script: - scripts/scan/protex.sh kw-scan: + <<: *centos7 stage: scan2 - tags: [docker] - image: $DOCKER_REGISTRY/ospray/docker-images:centos7 needs: [kw-build] script: - scripts/scan/kw-check-issues.sh kw-gen-report: + <<: *centos7 stage: scan2 - tags: [docker] - image: $DOCKER_REGISTRY/ospray/docker-images:centos7 needs: [kw-build] only: - devel @@ -684,10 +731,9 @@ kw-gen-report: - ./klocwork/report.log bdba: + <<: *centos7 <<: *release_job stage: scan3 - tags: [docker] - image: $DOCKER_REGISTRY/ospray/docker-images:centos7 needs: - release-linux - release-osx-clang @@ -702,10 +748,9 @@ bdba: - ospray-* av: + <<: *clamav <<: *release_job stage: scan3 - tags: [docker] - image: $DOCKER_REGISTRY/clamav:ubuntu20.04 needs: - release-linux - release-osx-clang @@ -719,10 +764,10 @@ av: - build_release/ospray-* test-release-linux: + <<: *centos7 <<: *test_job_unix_avx512skx <<: *release_job stage: scan3 - image: $DOCKER_REGISTRY/ospray/docker-images:centos7-mod needs: [release-linux] script: - source $SPACK_SETUP_ENV @@ -770,9 +815,8 @@ test-release-windows-msi: ### Mirror ### mirror: + <<: *centos7 stage: mirror - tags: [docker] - image: $DOCKER_REGISTRY/ospray/docker-images:centos7-mod only: [devel] dependencies: [] script: diff --git a/CHANGELOG.md b/CHANGELOG.md index 35a53c1a9e..3c3a63d79e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,34 @@ Version History --------------- +### Changes in v2.10.0: + +- Add support for primitive, object, and instance ID buffers as + framebuffer channels +- Support face-varying attributes for Mesh and Subdivision geometry +- Replace CMake variable `OSPRAY_PIXELS_PER_JOB` by + `OSPRAY_RENDER_TASK_SIZE`; variance tracking for adaptive + accumulation is now per task instead of per tile, allowing for more + granular adaptation +- OSPRay now requires minimum Open VKL v1.3.0 to bring the following + improvements: + - VDB volumes added support for contiguous data layouts, which can + provide improved performance (`nodesPackedDense`, + `nodesPackedTile` parameters) + - Particle volumes are more memory efficiency and improved + performance +- OSPRay now requires minimum ISPC v1.18.0 for Open VKL and to include + a fix for parallel dispatch of uniform function pointers +- MPI Offload: resolve object life time tracking issue that would + result in framebuffer and data info being release too early, leading + to a crash +- Fix crash with OpenMPI due to argument handling +- Fix clipping when rays are parallel to clipping planes +- Fix missing SDK headers from CPU and MPI module +- Deprecated the `vec2f valueRange` parameter of the `piecewiseLinear` + transfer function, use `box1f value` instead + + ### Changes in v2.9.0: - Add support for multi-segment deformation motion blur for `mesh` @@ -31,7 +59,7 @@ Version History `cpu` - Minimum version of rkcommon is 1.9.0, which brings the following improvements: - - Add support for Intel oneAPI DPCPP compiler + - Add detection of Intel oneAPI DPC++/C++ compiler - Fix memory leak ### Changes in v2.8.0: diff --git a/CMakeLists.txt b/CMakeLists.txt index e8ad6af55a..04034c72ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 cmake_minimum_required(VERSION 3.1) diff --git a/README.md b/README.md index e03448b35c..c29ca6ccb9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ OSPRay ====== -This is release v2.9.0 of Intel® OSPRay. For changes and new features +This is release v2.10.0 of Intel® OSPRay. For changes and new features see the [changelog](CHANGELOG.md). Visit http://www.ospray.org for more information. @@ -75,7 +75,7 @@ before you can build OSPRay you need the following prerequisites: Linux development tools. - Additionally you require a copy of the [Intel® Implicit SPMD Program - Compiler (ISPC)](http://ispc.github.io), version 1.16.0 or later. + Compiler (ISPC)](http://ispc.github.io), version 1.18.0 or later. Please obtain a release of ISPC from the [ISPC downloads page](https://ispc.github.io/downloads.html). The build system looks for ISPC in the `PATH` and in the directory right “next to” the @@ -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.2.0 or newer is required. If Open VKL is not + installing version 1.3.0 or newer is required. If Open VKL is not found by CMake its location can be hinted with the variable `openvkl_DIR`. @@ -787,7 +787,7 @@ The enum type `OSPDataType` describes the different element types that can be represented in OSPRay; valid constants are listed in the table below. -| Type/Name | Description | +| Type / Name | Description | |:-----------------------------|:---------------------------------------------------------------------------------------------| | OSP_DEVICE | API device object reference | | OSP_DATA | data reference | @@ -1142,12 +1142,19 @@ VDB volumes have the following parameters: | uint32\[\] | node.level | level on which each input node exists, may be 1, 2 or 3 (levels are counted from the root level = 0 down) | | vec3i\[\] | node.origin | the node origin index (per input node) | | OSPData\[\] | node.data | [data](#data) arrays with the node data (per input node). Nodes that are tiles are expected to have single-item arrays. Leaf-nodes with grid data expected to have compact 3D arrays in zyx layout (z changes most quickly) with the correct number of voxels for the `level`. Only `OSP_FLOAT` is supported as field `OSPDataType`. | +| OSPData | nodesPackedDense | optionally provided instead of `node.data`, a single array of all dense node data in a contiguous zyx layout, provided in the same order as the corresponding `node.*` parameters | +| OSPData | nodesPackedTile | optionally provided instead of `node.data`, a single array of all tile node data in a contiguous layout, provided in the same order as the corresponding `node.*` parameters | +| uint32\[\] | node.format | for each input node, whether it is of format `OSP_VOLUME_FORMAT_DENSE_ZYX` (and thus stored in `nodesPackedDense`), or `OSP_VOLUME_FORMAT_TILE` (stored in `nodesPackedTile`) | | int | filter | filter used for reconstructing the field, default is `OSP_VOLUME_FILTER_TRILINEAR`, alternatively `OSP_VOLUME_FILTER_NEAREST`, or `OSP_VOLUME_FILTER_TRICUBIC`. | | int | gradientFilter | filter used for reconstructing the field during gradient computations, default same as `filter` | | float | background | value that is used when sampling an undefined region outside the volume domain, default `NaN` | Configuration parameters for VDB volumes. +The `nodesPackedDense` and `nodesPackedTile` together with `node.format` +parameters may be provided instead of `node.data`; this packed data +layout may provide better performance. + 1. Museth, K. VDB: High-Resolution Sparse Volumes with Dynamic Topology. ACM Transactions on Graphics 32(3), 2013. DOI: 10.1145/2487228.2487235 @@ -1211,11 +1218,11 @@ transfer function, which interpolates between given equidistant colors and opacities. It is create by passing the string “`piecewiseLinear`” to `ospNewTransferFunction` and it is controlled by these parameters: -| Type | Name | Description | -|:----------|:-----------|:----------------------------------------------| -| vec3f\[\] | color | [data](#data) array of colors (linear RGB) | -| float\[\] | opacity | [data](#data) array of opacities | -| vec2f | valueRange | domain (scalar range) this function maps from | +| Type | Name | Description | +|:----------|:--------|:----------------------------------------------| +| vec3f\[\] | color | [data](#data) array of colors (linear RGB) | +| float\[\] | opacity | [data](#data) array of opacities | +| box1f | value | domain (scalar range) this function maps from | Parameters accepted by the linear transfer function. @@ -1245,6 +1252,7 @@ used. | OSPTransferFunction | transferFunction | | [transfer function](#transfer-function) to use | | float | densityScale | 1.0 | makes volumes uniformly thinner or thicker | | float | anisotropy | 0.0 | anisotropy of the (Henyey-Greenstein) phase function in \[-1–1\] ([path tracer](#path-tracer) only), default to isotropic scattering | +| uint32 | id | -1u | optional user ID, for [framebuffer](#framebuffer) channel `OSP_FB_ID_OBJECT` | Parameters understood by VolumetricModel. @@ -1270,12 +1278,16 @@ recognizes the following parameters: | Type | Name | Description | |:------------------------|:-----------------------|:-------------------------------------------------------------------------------------------------------------| | vec3f\[\] | vertex.position | [data](#data) array of vertex positions, overridden by `motion.*` arrays | -| vec3f\[\] | vertex.normal | [data](#data) array of vertex normals, overridden by `motion.*` arrays | -| vec4f\[\] / vec3f\[\] | vertex.color | [data](#data) array of vertex colors (linear RGBA/RGB) | -| vec2f\[\] | vertex.texcoord | [data](#data) array of vertex texture coordinates | +| vec3f\[\] | normal | [data](#data) array of face-varying normals, overridden by `motion.*` arrays | +| vec3f\[\] | vertex.normal | [data](#data) array of vertex-varying normals, overridden by `motion.*` arrays | +| vec4f\[\] / vec3f\[\] | color | [data](#data) array of face-varying colors (linear RGBA/RGB) | +| vec4f\[\] / vec3f\[\] | vertex.color | [data](#data) array of vertex-varying colors (linear RGBA/RGB) | +| vec2f\[\] | texcoord | [data](#data) array of face-varying texture coordinates | +| vec2f\[\] | vertex.texcoord | [data](#data) array of vertex-varying texture coordinates | | vec3ui\[\] / vec4ui\[\] | index | [data](#data) array of (either triangle or quad) indices (into the vertex array(s)) | | vec3f\[\]\[\] | motion.vertex.position | [data](#data) array of vertex position arrays (uniformly distributed keys for deformation motion blur) | -| vec3f\[\]\[\] | motion.vertex.normal | [data](#data) array of vertex normal arrays (uniformly distributed keys for deformation motion blur) | +| vec3f\[\]\[\] | motion.normal | [data](#data) array of face-varying normal arrays (uniformly distributed keys for deformation motion blur) | +| vec3f\[\]\[\] | motion.vertex.normal | [data](#data) array of vertex-varying normal arrays (uniformly distributed keys for deformation motion blur) | | box1f | time | time associated with first and last key in `motion.*` arrays (for deformation motion blur), default \[0, 1\] | Parameters defining a mesh geometry. @@ -1299,8 +1311,10 @@ the following parameters: | Type | Name | Description | |:----------|:--------------------|:----------------------------------------------------------------------------------------------------------------------| | vec3f\[\] | vertex.position | [data](#data) array of vertex positions | -| vec4f\[\] | vertex.color | optional [data](#data) array of vertex colors (linear RGBA) | -| vec2f\[\] | vertex.texcoord | optional [data](#data) array of vertex texture coordinates | +| vec4f\[\] | color | optional [data](#data) array of face-varying colors (linear RGBA) | +| vec4f\[\] | vertex.color | optional [data](#data) array of vertex-varying colors (linear RGBA) | +| vec2f\[\] | texcoord | optional [data](#data) array of vertex-varying texture coordinates | +| vec2f\[\] | vertex.texcoord | optional [data](#data) array of vertex-varying texture coordinates | | float | level | global level of tessellation, default 5 | | uint\[\] | index | [data](#data) array of indices (into the vertex array(s)) | | float\[\] | index.level | optional [data](#data) array of per-edge levels of tessellation, overrides global level | @@ -1516,15 +1530,14 @@ normal vectors orientation one can control whether inside or outside of the clipping geometry is being removed. For example, a clipping geometry with normals oriented outside clips everything what’s inside. -| Type | Name | Description | -|:-----------------------------|:--------------|:----------------------------------------------------------------------------------------------------------------------------------------------------| -| OSPGeometry | geometry | optional [geometry](#geometries) object this model references | -| OSPMaterial / uint32 | material | optional [material](#materials) applied to the geometry, may be an index into the `material` parameter on the [renderer](#renderers) (if it exists) | -| vec4f | color | optional color assigned to the geometry (linear RGBA) | -| OSPMaterial\[\] / uint32\[\] | material | optional [data](#data) array of (per-primitive) materials, may be an index into the `material` parameter on the renderer (if it exists) | -| vec4f\[\] | color | optional [data](#data) array of (per-primitive) colors (linear RGBA) | -| uint8\[\] | index | optional [data](#data) array of per-primitive indices into `color` and `material` | -| bool | invertNormals | inverts all shading normals (Ns), default false | +| Type | Name | Description | +|:----------------------------------------------------|:--------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------| +| OSPGeometry | geometry | optional [geometry](#geometries) object this model references | +| OSPMaterial / OSPMaterial\[\] / uint32 / uint32\[\] | material | optional ([data](#data) array of per-primitive) [material](#materials), may be an index into the `material` parameter on the renderer (if it exists) | +| vec4f / vec4f\[\] | color | optional ([data](#data) array of per-primitive) color assigned to the geometry (linear RGBA) | +| uint8\[\] | index | optional [data](#data) array of per-primitive indices into `color` and `material` | +| bool | invertNormals | inverts all shading normals (Ns), default false | +| uint32 | id | optional user ID, for [framebuffer](#framebuffer) channel `OSP_FB_ID_OBJECT`, default -1u | Parameters understood by GeometricModel. @@ -1881,6 +1894,7 @@ used. | quatf\[\] | motion.rotation | | uniformly distributed world-space quaternion rotation, overridden by `motion.transform` | | vec3f\[\] | motion.translation | | uniformly distributed world-space translation, overridden by `motion.transform` | | box1f | time | \[0, 1\] | time associated with first and last key in `motion.*` arrays (for motion blur) | +| uint32 | id | -1u | optional user ID, for [framebuffer](#framebuffer) channel `OSP_FB_ID_INSTANCE` | Parameters understood by instances. @@ -2819,14 +2833,17 @@ The parameter `frameBufferChannels` specifies which channels the framebuffer holds, and can be combined together by bitwise OR from the values of `OSPFrameBufferChannel` listed in the table below. -| Name | Description | -|:----------------|:-------------------------------------------------------------------------------------------------------------------------------------------| -| OSP_FB_COLOR | RGB color including alpha | -| OSP_FB_DEPTH | euclidean distance to the camera (*not* to the image plane), as linear 32 bit float; for multiple samples per pixel their minimum is taken | -| OSP_FB_ACCUM | accumulation buffer for progressive refinement | -| OSP_FB_VARIANCE | for estimation of the current noise level if OSP_FB_ACCUM is also present, see [rendering](#rendering) | -| OSP_FB_NORMAL | accumulated world-space normal of the first non-specular hit, as vec3f | -| OSP_FB_ALBEDO | accumulated material albedo (color without illumination) at the first hit, as vec3f | +| Name | Description | +|:--------------------|:-------------------------------------------------------------------------------------------------------------------------------------------| +| OSP_FB_COLOR | RGB color including alpha | +| OSP_FB_DEPTH | euclidean distance to the camera (*not* to the image plane), as linear 32 bit float; for multiple samples per pixel their minimum is taken | +| OSP_FB_ACCUM | accumulation buffer for progressive refinement | +| OSP_FB_VARIANCE | for estimation of the current noise level if OSP_FB_ACCUM is also present, see [rendering](#rendering) | +| OSP_FB_NORMAL | accumulated world-space normal of the first non-specular hit, as vec3f | +| OSP_FB_ALBEDO | accumulated material albedo (color without illumination) at the first hit, as vec3f | +| OSP_FB_ID_PRIMITIVE | primitive index of the first hit, as uint32 | +| OSP_FB_ID_OBJECT | geometric/volumetric model `id`, if specified, or index in [group](#groups) of first hit, as uint32 | +| OSP_FB_ID_INSTANCE | user defined [instance](#instances) `id`, if specified, or instance index of first hit, as uint32 | Framebuffer channels constants (of type `OSPFrameBufferChannel`), naming optional information the framebuffer can store. These values can be @@ -3563,7 +3580,7 @@ possible to copy the entire data set on to each rank, or to accelerate loading of a large model by leveraging a parallel file system. [1] For example, if OSPRay is in `~/Projects/ospray`, ISPC will also be -searched in `~/Projects/ispc-v1.17.0-linux`. +searched in `~/Projects/ispc-v1.18.0-linux`. [2] This file is usually in `${install_location}/[lib|lib64]/cmake/ospray-${version}/`. If CMake diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 915bb211bc..92e063c1ce 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 cmake_dependent_option( diff --git a/apps/common/CMakeLists.txt b/apps/common/CMakeLists.txt index 34c571ff9d..735db6ad02 100644 --- a/apps/common/CMakeLists.txt +++ b/apps/common/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 if (NOT OSPRAY_ENABLE_APPS_BENCHMARK AND diff --git a/apps/common/arcball_camera/ArcballCamera.cpp b/apps/common/arcball_camera/ArcballCamera.cpp index 89b5b2b97a..b7ec5b8ad0 100644 --- a/apps/common/arcball_camera/ArcballCamera.cpp +++ b/apps/common/arcball_camera/ArcballCamera.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2021 Intel Corporation +// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ArcballCamera.h" diff --git a/apps/common/arcball_camera/ArcballCamera.h b/apps/common/arcball_camera/ArcballCamera.h index e8f4cf0063..2800684df9 100644 --- a/apps/common/arcball_camera/ArcballCamera.h +++ b/apps/common/arcball_camera/ArcballCamera.h @@ -1,4 +1,4 @@ -// Copyright 2017-2021 Intel Corporation +// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/apps/common/arcball_camera/CMakeLists.txt b/apps/common/arcball_camera/CMakeLists.txt index cffe9f3ad8..67e495f2bd 100644 --- a/apps/common/arcball_camera/CMakeLists.txt +++ b/apps/common/arcball_camera/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 add_library(arcball_camera STATIC ArcballCamera.cpp) diff --git a/apps/common/external/CMakeLists.txt b/apps/common/external/CMakeLists.txt index 3acd5fa3b6..53faf839e4 100644 --- a/apps/common/external/CMakeLists.txt +++ b/apps/common/external/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ospray_disable_compiler_warnings() diff --git a/apps/common/external/imgui/CMakeLists.txt b/apps/common/external/imgui/CMakeLists.txt index fdf4e2ba9d..f6f9092584 100644 --- a/apps/common/external/imgui/CMakeLists.txt +++ b/apps/common/external/imgui/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ospray_disable_compiler_warnings() diff --git a/apps/common/external/stb_image/CMakeLists.txt b/apps/common/external/stb_image/CMakeLists.txt index 9032d187d9..f3a3e33547 100644 --- a/apps/common/external/stb_image/CMakeLists.txt +++ b/apps/common/external/stb_image/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2019 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 add_library(stb_image INTERFACE) diff --git a/apps/common/ospray_testing/CMakeLists.txt b/apps/common/ospray_testing/CMakeLists.txt index 33358ee1f9..93271db4e7 100644 --- a/apps/common/ospray_testing/CMakeLists.txt +++ b/apps/common/ospray_testing/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 include(GenerateExportHeader) @@ -9,6 +9,7 @@ add_library(ospray_testing SHARED ospray_testing.cpp builders/Boxes.cpp + builders/Interpolation.cpp builders/Builder.cpp builders/CornellBox.cpp builders/Curves.cpp diff --git a/apps/common/ospray_testing/builders/Boxes.cpp b/apps/common/ospray_testing/builders/Boxes.cpp index eedf86d264..b54a2daf20 100644 --- a/apps/common/ospray_testing/builders/Boxes.cpp +++ b/apps/common/ospray_testing/builders/Boxes.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" diff --git a/apps/common/ospray_testing/builders/Builder.cpp b/apps/common/ospray_testing/builders/Builder.cpp index ebdcb03c1f..ca930c3652 100644 --- a/apps/common/ospray_testing/builders/Builder.cpp +++ b/apps/common/ospray_testing/builders/Builder.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" @@ -166,10 +166,13 @@ cpp::Instance Builder::makeGroundPlane(const box3f &bounds) const // z-direction stripes startingIndex = v_position.size(); - v_position.emplace_back(coord - stripeWidth, yLevel, -paddedExtent); - v_position.emplace_back(coord + stripeWidth, yLevel, -paddedExtent); - v_position.emplace_back(coord + stripeWidth, yLevel, paddedExtent); - v_position.emplace_back(coord - stripeWidth, yLevel, paddedExtent); + // offset another epsilon to avoid z-figthing for primID AOV + const float yLevel2 = yLevel + 1e-4f; + + v_position.emplace_back(coord - stripeWidth, yLevel2, -paddedExtent); + v_position.emplace_back(coord + stripeWidth, yLevel2, -paddedExtent); + v_position.emplace_back(coord + stripeWidth, yLevel2, paddedExtent); + v_position.emplace_back(coord - stripeWidth, yLevel2, paddedExtent); v_normal.push_back(up); v_normal.push_back(up); diff --git a/apps/common/ospray_testing/builders/Builder.h b/apps/common/ospray_testing/builders/Builder.h index 6116c67c09..a1380c8fd1 100644 --- a/apps/common/ospray_testing/builders/Builder.h +++ b/apps/common/ospray_testing/builders/Builder.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/apps/common/ospray_testing/builders/ClippingGeometries.cpp b/apps/common/ospray_testing/builders/ClippingGeometries.cpp index 0c0cf52e1f..bc4c08fa00 100644 --- a/apps/common/ospray_testing/builders/ClippingGeometries.cpp +++ b/apps/common/ospray_testing/builders/ClippingGeometries.cpp @@ -1,4 +1,4 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" diff --git a/apps/common/ospray_testing/builders/CornellBox.cpp b/apps/common/ospray_testing/builders/CornellBox.cpp index 508bb1f7d5..e7f5c219cd 100644 --- a/apps/common/ospray_testing/builders/CornellBox.cpp +++ b/apps/common/ospray_testing/builders/CornellBox.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" diff --git a/apps/common/ospray_testing/builders/Curves.cpp b/apps/common/ospray_testing/builders/Curves.cpp index 81ae4437d2..a13d77bb14 100644 --- a/apps/common/ospray_testing/builders/Curves.cpp +++ b/apps/common/ospray_testing/builders/Curves.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include diff --git a/apps/common/ospray_testing/builders/Empty.cpp b/apps/common/ospray_testing/builders/Empty.cpp index 3f579ba0be..cc307fa20b 100644 --- a/apps/common/ospray_testing/builders/Empty.cpp +++ b/apps/common/ospray_testing/builders/Empty.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" diff --git a/apps/common/ospray_testing/builders/GravitySpheresVolume.cpp b/apps/common/ospray_testing/builders/GravitySpheresVolume.cpp index 83e6f91a22..064c36019d 100644 --- a/apps/common/ospray_testing/builders/GravitySpheresVolume.cpp +++ b/apps/common/ospray_testing/builders/GravitySpheresVolume.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" diff --git a/apps/common/ospray_testing/builders/Instancing.cpp b/apps/common/ospray_testing/builders/Instancing.cpp index 35d17c7cfb..29443922e5 100644 --- a/apps/common/ospray_testing/builders/Instancing.cpp +++ b/apps/common/ospray_testing/builders/Instancing.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" @@ -31,6 +31,7 @@ struct Instancing : public detail::Builder private: vec2ui numInstances{10, 10}; + bool useIDs{false}; }; // Inlined definitions //////////////////////////////////////////////////// @@ -46,8 +47,10 @@ cpp::Geometry makeBoxGeometry(const box3f &box) return ospGeometry; } -cpp::GeometricModel makeGeometricModel( - cpp::Geometry geo, const std::string &rendererType, const vec3f &kd) +cpp::GeometricModel makeGeometricModel(cpp::Geometry geo, + const std::string &rendererType, + const vec3f &kd, + bool useIDs) { cpp::GeometricModel geometricModel(geo); @@ -58,6 +61,8 @@ cpp::GeometricModel makeGeometricModel( objMaterial.commit(); geometricModel.setParam("material", objMaterial); } + if (useIDs) + geometricModel.setParam("id", 44u); geometricModel.commit(); return geometricModel; @@ -81,7 +86,7 @@ cpp::Volume makeVolume(const vec3f ¢er) return volume; } -cpp::VolumetricModel makeVolumetricModel(cpp::Volume volume) +cpp::VolumetricModel makeVolumetricModel(cpp::Volume volume, bool useIDs) { cpp::VolumetricModel vModel(volume); { @@ -99,6 +104,8 @@ cpp::VolumetricModel makeVolumetricModel(cpp::Volume volume) vModel.setParam("transferFunction", transferFunction); vModel.setParam("densityScale", .5f); vModel.setParam("gradientShadingScale", 1.f); + if (useIDs) + vModel.setParam("id", 3u); vModel.commit(); } return vModel; @@ -113,6 +120,7 @@ void Instancing::commit() Builder::commit(); numInstances = getParam("numInstances", numInstances); + useIDs = getParam("useIDs", useIDs); } cpp::Group Instancing::buildGroupA() const @@ -121,7 +129,7 @@ cpp::Group Instancing::buildGroupA() const cpp::Geometry box = makeBoxGeometry(box3f(vec3f(-1.f), vec3f(1.f))); cpp::GeometricModel geometricModel = - makeGeometricModel(box, rendererType, vec3f(.1f, .4f, .8f)); + makeGeometricModel(box, rendererType, vec3f(.1f, .4f, .8f), useIDs); group.setParam("geometry", cpp::CopiedData(geometricModel)); cpp::Light light("quad"); @@ -140,16 +148,19 @@ cpp::Group Instancing::buildGroupA() const cpp::Group Instancing::buildGroupB() const { cpp::Group group; + std::vector models; - cpp::Geometry box = makeBoxGeometry(box3f(vec3f(-1.f), vec3f(1.f))); - cpp::GeometricModel geometricModel = - makeGeometricModel(box, rendererType, vec3f(.1f, .4f, .8f)); - group.setParam("geometry", cpp::CopiedData(geometricModel)); + cpp::Geometry box = makeBoxGeometry(box3f(vec3f(-1.f), vec3f(0.f, 1.f, 1.f))); + models.emplace_back( + makeGeometricModel(box, rendererType, vec3f(.1f, .4f, .8f), useIDs)); + box = makeBoxGeometry(box3f(vec3f(0.f, -1.f, -1.f), vec3f(1.f))); + models.emplace_back( + makeGeometricModel(box, rendererType, vec3f(.1f, .4f, .8f), useIDs)); + group.setParam("geometry", cpp::CopiedData(models)); cpp::Light light("spot"); light.setParam("position", vec3f(0.f, 6.f, 0.f)); light.setParam("direction", vec3f(0.f, -1.f, 0.f)); - light.setParam("c0", vec3f(0.f, 1.f, 0.f)); light.setParam("openingAngle", 180.f); light.setParam("penumbraAngle", 0.f); light.setParam("radius", 0.3f); @@ -169,8 +180,8 @@ cpp::Group Instancing::buildGroupC() const cpp::Group group; // Create volumetric model - group.setParam( - "volume", cpp::CopiedData(makeVolumetricModel(makeVolume(vec3f(0.f))))); + group.setParam("volume", + cpp::CopiedData(makeVolumetricModel(makeVolume(vec3f(0.f)), useIDs))); cpp::Light light("sphere"); light.setParam("position", vec3f(0.f, 2.f, 0.f)); @@ -206,6 +217,8 @@ cpp::World Instancing::buildWorld() const const float d = length(vec2f(position.x, position.z)); const int gId = int(.18f * d) % groups.size(); cpp::Instance instance(groups[gId]); + if (useIDs) + instance.setParam("id", i.y + 1); const affine3f xfm = affine3f::translate(position) * affine3f::rotate(vec3f(0.f, 1.f, 0.f), .03f * (15.f - d)); instance.setParam("transform", diff --git a/apps/common/ospray_testing/builders/Interpolation.cpp b/apps/common/ospray_testing/builders/Interpolation.cpp new file mode 100644 index 0000000000..ba5997998b --- /dev/null +++ b/apps/common/ospray_testing/builders/Interpolation.cpp @@ -0,0 +1,194 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "Builder.h" +#include "ospray_testing.h" +// stl +#include + +using namespace rkcommon::math; + +namespace ospray { +namespace testing { + +struct Interpolation : public detail::Builder +{ + Interpolation( + bool subd = false, unsigned int attrib = 0, unsigned int interp = 0) + : useSubd(subd), attribute(attrib), interpolation(interp) + {} + ~Interpolation() override = default; + + void commit() override; + + cpp::Group buildGroup() const override; + cpp::World buildWorld() const override; + + // TODO: support triangles + bool useSubd{false}; // otherwise Mesh + unsigned int attribute; // color, texcoord, normal + unsigned int interpolation; // face varying, vertex varying, uniform, constant +}; + +// quad mesh data +static std::vector vertices = { + // Left + {0.f, 0.f, 0.f}, + {1.f, 0.f, 0.f}, + {1.f, 1.f, 0.f}, + {0.f, 1.f, 0.f}, + // Right + {2.f, 0.f, 0.f}, + {2.f, 1.f, 0.f}}; + +static std::vector quad_indices = { + {0, 1, 2, 3}, // Left + {1, 4, 5, 2} // Right +}; + +static std::vector subd_indices = {0, 1, 2, 3, 1, 4, 5, 2}; + +static std::vector texcoords = {{0.0f, 0.0f}, + {0.1f, 0.0f}, + {0.2f, 0.0f}, + {0.3f, 0.0f}, + {0.4f, 0.0f}, + {0.5f, 0.0f}, + {0.6f, 0.0f}, + {0.7f, 0.0f}}; + +static std::vector colors = {{1.f, 0.f, 0.f, 1.f}, + {0.f, 1.f, 0.f, 1.f}, + {0.f, 0.f, 1.f, 1.f}, + {1.f, 1.f, 0.f, 1.f}, + {1.f, 0.f, 1.f, 1.f}, + {1.f, 0.f, 1.f, 1.f}}; + +static std::vector colors_fv = {{1.f, 0.f, 0.f, 1.f}, + {0.f, 1.f, 0.f, 1.f}, + {0.f, 0.f, 1.f, 1.f}, + {1.f, 1.f, 0.f, 1.f}, + {1.f, 0.f, 1.f, 1.f}, + {1.f, 0.f, 1.f, 1.f}, + {1.f, 0.f, 1.f, 1.f}, + {1.f, 0.f, 1.f, 1.f}}; + +static std::vector normals = {{1.f, 0.f, 0.f}, + {0.f, 1.f, 0.f}, + {0.f, 0.f, 1.f}, + {1.f, 1.f, 0.f}, + {1.f, 0.f, 1.f}, + {1.f, 0.f, 1.f}, + {1.f, 0.f, 1.f}, + {1.f, 0.f, 1.f}}; + +// number of vertex indices per face +static std::vector faces = {4, 4}; + +// Inlined definitions //////////////////////////////////////////////////// + +void Interpolation::commit() +{ + Builder::commit(); + useSubd = getParam("useSubd", useSubd); + attribute = getParam("attribute", attribute); + interpolation = getParam("interpolation", interpolation); + addPlane = false; +} + +cpp::Group Interpolation::buildGroup() const +{ + cpp::Geometry mesh; + std::vector colors_mod = colors; + if (interpolation == 0) + colors_mod = colors_fv; + else if (interpolation == 2) + colors_mod.resize(2); + else if (interpolation == 3) + colors_mod.resize(1); + + cpp::Texture tex("texture2d"); + tex.setParam("format", OSP_TEXTURE_RGBA32F); + tex.setParam( + "data", cpp::CopiedData(colors_mod.data(), vec2ul(colors_mod.size(), 1))); + tex.commit(); + cpp::Material mat(rendererType, "obj"); + if (attribute == 1) // texture + mat.setParam("map_kd", tex); + mat.commit(); + if (useSubd) { + mesh = cpp::Geometry("subdivision"); + mesh.setParam("vertex.position", cpp::CopiedData(vertices)); + mesh.setParam("face", cpp::CopiedData(faces)); + mesh.setParam("level", 1.0f); // global level + mesh.setParam("index", cpp::CopiedData(subd_indices)); + mesh.setParam("mode", OSP_SUBDIVISION_PIN_CORNERS); + } else { + mesh = cpp::Geometry("mesh"); + mesh.setParam("vertex.position", cpp::CopiedData(vertices)); + mesh.setParam("index", cpp::CopiedData(quad_indices)); + } + if (interpolation == 0) { + if (attribute == 1) + mesh.setParam("texcoord", cpp::CopiedData(texcoords)); + else if (attribute == 2) + mesh.setParam("normal", cpp::CopiedData(normals)); + else + mesh.setParam("color", cpp::CopiedData(colors_mod)); + } else if (interpolation == 1) { + if (attribute == 1) + mesh.setParam("vertex.texcoord", cpp::CopiedData(texcoords)); + else if (attribute == 2) + mesh.setParam("vertex.normal", cpp::CopiedData(normals)); + else + mesh.setParam("vertex.color", cpp::CopiedData(colors_mod)); + } + mesh.commit(); + + cpp::GeometricModel model(mesh); + + // create and setup a material + if (rendererType == "pathtracer" || rendererType == "scivis" + || rendererType == "ao") { + model.setParam("material", mat); + } + + if ((attribute == 0) && interpolation == 2) + model.setParam("color", cpp::CopiedData(colors_mod)); + else if ((attribute == 0) && interpolation == 3) + model.setParam("color", colors_mod[0]); + + // Put the mesh and material into a model + model.commit(); + + cpp::Group group; + + group.setParam("geometry", cpp::CopiedData(model)); + group.commit(); + + return group; +} + +cpp::World Interpolation::buildWorld() const +{ + auto world = Builder::buildWorld(); + + cpp::Light light("distant"); + light.setParam("color", vec3f(0.78f, 0.551f, 0.183f)); + light.setParam("intensity", 3.14f); + light.setParam("direction", vec3f(-0.8f, -0.6f, 0.3f)); + light.commit(); + cpp::Light ambient("ambient"); + ambient.setParam("intensity", 0.35f); + ambient.setParam("visible", false); + ambient.commit(); + std::vector lights{light, ambient}; + world.setParam("light", cpp::CopiedData(lights)); + + return world; +} + +OSP_REGISTER_TESTING_BUILDER(Interpolation, interpolation); + +} // namespace testing +} // namespace ospray diff --git a/apps/common/ospray_testing/builders/Noise.cpp b/apps/common/ospray_testing/builders/Noise.cpp index 4dd3de198b..806b53e56d 100644 --- a/apps/common/ospray_testing/builders/Noise.cpp +++ b/apps/common/ospray_testing/builders/Noise.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Noise.h" diff --git a/apps/common/ospray_testing/builders/Noise.h b/apps/common/ospray_testing/builders/Noise.h index 8d49c796e7..e0e93acb09 100644 --- a/apps/common/ospray_testing/builders/Noise.h +++ b/apps/common/ospray_testing/builders/Noise.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ospray_testing.h" diff --git a/apps/common/ospray_testing/builders/PerlinNoiseVolumes.cpp b/apps/common/ospray_testing/builders/PerlinNoiseVolumes.cpp index dbe37510a7..a5aa7282a0 100644 --- a/apps/common/ospray_testing/builders/PerlinNoiseVolumes.cpp +++ b/apps/common/ospray_testing/builders/PerlinNoiseVolumes.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" @@ -98,7 +98,7 @@ cpp::VolumetricModel createProceduralVolumetricModel( volume.commit(); cpp::TransferFunction tfn("piecewiseLinear"); - tfn.setParam("valueRange", voxelRange.toVec2()); + tfn.setParam("value", voxelRange); tfn.setParam("color", cpp::CopiedData(colors)); tfn.setParam("opacity", cpp::CopiedData(opacities)); tfn.commit(); diff --git a/apps/common/ospray_testing/builders/Planes.cpp b/apps/common/ospray_testing/builders/Planes.cpp index a74ff46660..a3f6e24532 100644 --- a/apps/common/ospray_testing/builders/Planes.cpp +++ b/apps/common/ospray_testing/builders/Planes.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" diff --git a/apps/common/ospray_testing/builders/RandomSpheres.cpp b/apps/common/ospray_testing/builders/RandomSpheres.cpp index 7de3551613..bcc2824d74 100644 --- a/apps/common/ospray_testing/builders/RandomSpheres.cpp +++ b/apps/common/ospray_testing/builders/RandomSpheres.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" diff --git a/apps/common/ospray_testing/builders/Streamlines.cpp b/apps/common/ospray_testing/builders/Streamlines.cpp index 4fc5f71dc9..22cafcc52e 100644 --- a/apps/common/ospray_testing/builders/Streamlines.cpp +++ b/apps/common/ospray_testing/builders/Streamlines.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" diff --git a/apps/common/ospray_testing/builders/SubdivisionCube.cpp b/apps/common/ospray_testing/builders/SubdivisionCube.cpp index 95d5d8bc42..c6f9b778e6 100644 --- a/apps/common/ospray_testing/builders/SubdivisionCube.cpp +++ b/apps/common/ospray_testing/builders/SubdivisionCube.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" diff --git a/apps/common/ospray_testing/builders/UnstructuredVolumeGen.cpp b/apps/common/ospray_testing/builders/UnstructuredVolumeGen.cpp index 5805bb3216..caf2dab43f 100644 --- a/apps/common/ospray_testing/builders/UnstructuredVolumeGen.cpp +++ b/apps/common/ospray_testing/builders/UnstructuredVolumeGen.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" diff --git a/apps/common/ospray_testing/builders/UnstructuredVolumeSimple.cpp b/apps/common/ospray_testing/builders/UnstructuredVolumeSimple.cpp index 23b3babbfe..c463a97595 100644 --- a/apps/common/ospray_testing/builders/UnstructuredVolumeSimple.cpp +++ b/apps/common/ospray_testing/builders/UnstructuredVolumeSimple.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" diff --git a/apps/common/ospray_testing/builders/VdbVolume.cpp b/apps/common/ospray_testing/builders/VdbVolume.cpp index aeaf7939e7..2458943299 100644 --- a/apps/common/ospray_testing/builders/VdbVolume.cpp +++ b/apps/common/ospray_testing/builders/VdbVolume.cpp @@ -1,4 +1,4 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" @@ -14,7 +14,7 @@ namespace testing { struct VdbVolume : public detail::Builder { - VdbVolume() = default; + VdbVolume(bool packed = false) : packed(packed) {} ~VdbVolume() override = default; void commit() override; @@ -25,6 +25,7 @@ struct VdbVolume : public detail::Builder private: float densityScale{1.f}; float anisotropy{0.f}; + bool packed{false}; static constexpr uint32_t domainRes = 128; }; @@ -42,17 +43,17 @@ cpp::Group VdbVolume::buildGroup() const { cpp::Volume volume("vdb"); - std::vector level; std::vector origin; std::vector data; + std::vector dataPacked; constexpr uint32_t leafRes = 8; constexpr uint32_t N = domainRes / leafRes; constexpr size_t numLeaves = N * static_cast(N) * N; - level.reserve(numLeaves); origin.reserve(numLeaves); - data.reserve(numLeaves); + if (!packed) + data.reserve(numLeaves); std::vector leaf(leafRes * (size_t)leafRes * leafRes, 0.f); for (uint32_t z = 0; z < N; ++z) @@ -80,21 +81,30 @@ cpp::Group VdbVolume::buildGroup() const leafValueRange[0].extend(vr); if (leafValueRange[0].lower != 0.f || leafValueRange[0].upper != 0.f) { - level.push_back(3); origin.push_back(vec3i(x * leafRes, y * leafRes, z * leafRes)); - data.emplace_back( - cpp::CopiedData(leaf.data(), vec3ul(leafRes, leafRes, leafRes))); + if (packed) + std::copy(leaf.begin(), leaf.end(), std::back_inserter(dataPacked)); + else + data.emplace_back(cpp::CopiedData( + leaf.data(), vec3ul(leafRes, leafRes, leafRes))); } } - if (level.empty()) + if (origin.empty()) throw std::runtime_error("vdb volume is empty."); volume.setParam("filter", (int)OSP_VOLUME_FILTER_TRILINEAR); volume.setParam("gradientFilter", (int)OSP_VOLUME_FILTER_TRILINEAR); - volume.setParam("node.level", cpp::CopiedData(level)); + volume.setParam( + "node.level", cpp::CopiedData(std::vector(origin.size(), 3))); volume.setParam("node.origin", cpp::CopiedData(origin)); - volume.setParam("node.data", cpp::CopiedData(data)); + if (packed) { + volume.setParam("nodesPackedDense", cpp::CopiedData(dataPacked)); + volume.setParam("node.format", + cpp::CopiedData(std::vector( + origin.size(), OSP_VOLUME_FORMAT_DENSE_ZYX))); + } else + volume.setParam("node.data", cpp::CopiedData(data)); volume.commit(); cpp::VolumetricModel model(volume); @@ -145,6 +155,7 @@ cpp::World VdbVolume::buildWorld() const } OSP_REGISTER_TESTING_BUILDER(VdbVolume, vdb_volume); +OSP_REGISTER_TESTING_BUILDER(VdbVolume(true), vdb_volume_packed); } // namespace testing } // namespace ospray diff --git a/apps/common/ospray_testing/builders/test_pt_glass.cpp b/apps/common/ospray_testing/builders/test_pt_glass.cpp index bf66f7578c..0fc91822e7 100644 --- a/apps/common/ospray_testing/builders/test_pt_glass.cpp +++ b/apps/common/ospray_testing/builders/test_pt_glass.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" diff --git a/apps/common/ospray_testing/builders/test_pt_luminous.cpp b/apps/common/ospray_testing/builders/test_pt_luminous.cpp index fa7df211e6..4460506b9f 100644 --- a/apps/common/ospray_testing/builders/test_pt_luminous.cpp +++ b/apps/common/ospray_testing/builders/test_pt_luminous.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" diff --git a/apps/common/ospray_testing/builders/test_pt_metal_roughness.cpp b/apps/common/ospray_testing/builders/test_pt_metal_roughness.cpp index 92426a2fb5..3dd78b3330 100644 --- a/apps/common/ospray_testing/builders/test_pt_metal_roughness.cpp +++ b/apps/common/ospray_testing/builders/test_pt_metal_roughness.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" diff --git a/apps/common/ospray_testing/builders/test_pt_metallic_flakes.cpp b/apps/common/ospray_testing/builders/test_pt_metallic_flakes.cpp index f4e9264d11..d74133eb32 100644 --- a/apps/common/ospray_testing/builders/test_pt_metallic_flakes.cpp +++ b/apps/common/ospray_testing/builders/test_pt_metallic_flakes.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" diff --git a/apps/common/ospray_testing/builders/test_pt_obj.cpp b/apps/common/ospray_testing/builders/test_pt_obj.cpp index e83f6bd1b0..29840a0e58 100644 --- a/apps/common/ospray_testing/builders/test_pt_obj.cpp +++ b/apps/common/ospray_testing/builders/test_pt_obj.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" diff --git a/apps/common/ospray_testing/detail/ospray_testing.inl b/apps/common/ospray_testing/detail/ospray_testing.inl index 3a5f9c579a..687a434c39 100644 --- a/apps/common/ospray_testing/detail/ospray_testing.inl +++ b/apps/common/ospray_testing/detail/ospray_testing.inl @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../builders/Builder.h" diff --git a/apps/common/ospray_testing/ospray_testing.cpp b/apps/common/ospray_testing/ospray_testing.cpp index 57f1d2fce2..8070941260 100644 --- a/apps/common/ospray_testing/ospray_testing.cpp +++ b/apps/common/ospray_testing/ospray_testing.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray_testing diff --git a/apps/common/ospray_testing/ospray_testing.h b/apps/common/ospray_testing/ospray_testing.h index e00c705e17..e70a92e672 100644 --- a/apps/common/ospray_testing/ospray_testing.h +++ b/apps/common/ospray_testing/ospray_testing.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/apps/common/raw_to_amr/CMakeLists.txt b/apps/common/raw_to_amr/CMakeLists.txt index bdf548a0ce..14c2414785 100644 --- a/apps/common/raw_to_amr/CMakeLists.txt +++ b/apps/common/raw_to_amr/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 add_library(raw_to_amr STATIC rawToAMR.cpp) diff --git a/apps/common/raw_to_amr/rawToAMR.cpp b/apps/common/raw_to_amr/rawToAMR.cpp index b6d7ee2c21..ffebc466f5 100644 --- a/apps/common/raw_to_amr/rawToAMR.cpp +++ b/apps/common/raw_to_amr/rawToAMR.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma clang diagnostic push diff --git a/apps/common/raw_to_amr/rawToAMR.h b/apps/common/raw_to_amr/rawToAMR.h index d26d4a7a4a..45056e4274 100644 --- a/apps/common/raw_to_amr/rawToAMR.h +++ b/apps/common/raw_to_amr/rawToAMR.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "rkcommon/math/box.h" diff --git a/apps/ospBenchmark/BaseFixture.cpp b/apps/ospBenchmark/BaseFixture.cpp index 191a9739de..cf7fe5b645 100644 --- a/apps/ospBenchmark/BaseFixture.cpp +++ b/apps/ospBenchmark/BaseFixture.cpp @@ -1,4 +1,4 @@ -// Copyright 2018-2020 Intel Corporation +// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "BaseFixture.h" diff --git a/apps/ospBenchmark/BaseFixture.h b/apps/ospBenchmark/BaseFixture.h index 08eb8362ea..7a48504dec 100644 --- a/apps/ospBenchmark/BaseFixture.h +++ b/apps/ospBenchmark/BaseFixture.h @@ -1,4 +1,4 @@ -// Copyright 2018-2020 Intel Corporation +// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/apps/ospBenchmark/CMakeLists.txt b/apps/ospBenchmark/CMakeLists.txt index 7d68b87c01..3b695f13db 100644 --- a/apps/ospBenchmark/CMakeLists.txt +++ b/apps/ospBenchmark/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2018-2021 Intel Corporation +## Copyright 2018 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 if (NOT OSPRAY_ENABLE_APPS_BENCHMARK) diff --git a/apps/ospBenchmark/benchmarks/CornellBoxSpp.cpp b/apps/ospBenchmark/benchmarks/CornellBoxSpp.cpp index c21491f792..b0554ff5af 100644 --- a/apps/ospBenchmark/benchmarks/CornellBoxSpp.cpp +++ b/apps/ospBenchmark/benchmarks/CornellBoxSpp.cpp @@ -1,4 +1,4 @@ -// Copyright 2018-2020 Intel Corporation +// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../BaseFixture.h" diff --git a/apps/ospBenchmark/benchmarks/GravitySpheresVolume.cpp b/apps/ospBenchmark/benchmarks/GravitySpheresVolume.cpp index f90e0a9a93..54b436f381 100644 --- a/apps/ospBenchmark/benchmarks/GravitySpheresVolume.cpp +++ b/apps/ospBenchmark/benchmarks/GravitySpheresVolume.cpp @@ -1,4 +1,4 @@ -// Copyright 2018-2020 Intel Corporation +// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../BaseFixture.h" diff --git a/apps/ospBenchmark/benchmarks/PerlinNoiseVolumes.cpp b/apps/ospBenchmark/benchmarks/PerlinNoiseVolumes.cpp index 6a2f14d1d3..40af3994ea 100644 --- a/apps/ospBenchmark/benchmarks/PerlinNoiseVolumes.cpp +++ b/apps/ospBenchmark/benchmarks/PerlinNoiseVolumes.cpp @@ -1,4 +1,4 @@ -// Copyright 2018-2020 Intel Corporation +// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../BaseFixture.h" diff --git a/apps/ospBenchmark/ospBenchmark.cpp b/apps/ospBenchmark/ospBenchmark.cpp index 35dd955139..2940398121 100644 --- a/apps/ospBenchmark/ospBenchmark.cpp +++ b/apps/ospBenchmark/ospBenchmark.cpp @@ -1,4 +1,4 @@ -// Copyright 2018-2021 Intel Corporation +// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "BaseFixture.h" diff --git a/apps/ospExamples/CMakeLists.txt b/apps/ospExamples/CMakeLists.txt index de7e8adbd1..25a5b31f62 100644 --- a/apps/ospExamples/CMakeLists.txt +++ b/apps/ospExamples/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2018-2021 Intel Corporation +## Copyright 2018 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 if (NOT OSPRAY_ENABLE_APPS_EXAMPLES) diff --git a/apps/ospExamples/GLFWOSPRayWindow.cpp b/apps/ospExamples/GLFWOSPRayWindow.cpp index d1923d61e2..fead0bde70 100644 --- a/apps/ospExamples/GLFWOSPRayWindow.cpp +++ b/apps/ospExamples/GLFWOSPRayWindow.cpp @@ -1,10 +1,11 @@ -// Copyright 2018-2022 Intel Corporation +// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "GLFWOSPRayWindow.h" #include "imgui_impl_glfw_gl3.h" // ospray_testing #include "ospray_testing.h" +#include "rkcommon/utility/random.h" // imgui #include "imgui.h" // std @@ -51,6 +52,7 @@ static const std::vector g_scenes = {"boxes_lit", "particle_volume", "particle_volume_isosurface", "vdb_volume", + "vdb_volume_packed", "instancing"}; static const std::vector g_curveVariant = { @@ -74,6 +76,9 @@ static const std::vector g_debugRendererTypes = {"eyeLight", static const std::vector g_pixelFilterTypes = { "point", "box", "gaussian", "mitchell", "blackmanHarris"}; +static const std::vector g_AOVs = { + "color", "depth", "albedo", "primID", "objID", "instID"}; + bool sceneUI_callback(void *, int index, const char **out_text) { *out_text = g_scenes[index].c_str(); @@ -104,6 +109,12 @@ bool pixelFilterTypeUI_callback(void *, int index, const char **out_text) return true; } +bool AOVUI_callback(void *, int index, const char **out_text) +{ + *out_text = g_AOVs[index].c_str(); + return true; +} + // GLFWOSPRayWindow definitions /////////////////////////////////////////////// void error_callback(int error, const char *desc) @@ -260,7 +271,8 @@ void GLFWOSPRayWindow::reshape(const vec2i &newWindowSize) // create new frame buffer auto buffers = OSP_FB_COLOR | OSP_FB_DEPTH | OSP_FB_ACCUM | OSP_FB_ALBEDO - | OSP_FB_NORMAL; + | OSP_FB_NORMAL | OSP_FB_ID_PRIMITIVE | OSP_FB_ID_OBJECT + | OSP_FB_ID_INSTANCE; framebuffer = cpp::FrameBuffer(windowSize.x, windowSize.y, OSP_FB_RGBA32F, buffers); @@ -359,8 +371,18 @@ void GLFWOSPRayWindow::display() latestFPS = 1.f / currentFrame.duration(); - auto *fb = framebuffer.map( - showDepth ? OSP_FB_DEPTH : (showAlbedo ? OSP_FB_ALBEDO : OSP_FB_COLOR)); + auto fbChannel = OSP_FB_COLOR; + if (showDepth) + fbChannel = OSP_FB_DEPTH; + if (showAlbedo) + fbChannel = OSP_FB_ALBEDO; + if (showPrimID) + fbChannel = OSP_FB_ID_PRIMITIVE; + if (showGeomID) + fbChannel = OSP_FB_ID_OBJECT; + if (showInstID) + fbChannel = OSP_FB_ID_INSTANCE; + auto *fb = framebuffer.map(fbChannel); // Copy and normalize depth layer if showDepth is on float *depthFb = static_cast(fb); @@ -384,17 +406,34 @@ void GLFWOSPRayWindow::display() depthFb[i] = (depthFb[i] - minDepth) * rcpDepthRange; } } + unsigned int *ids = static_cast(fb); + std::vector idFbArray(windowSize.x * windowSize.y); + float *idFb = reinterpret_cast(idFbArray.data()); + if (showPrimID || showGeomID || showInstID) { + for (int i = 0; i < windowSize.x * windowSize.y; i++) { + const unsigned int id = ids[i]; + idFbArray[i] = + id == -1u ? vec3f(0.f) : rkcommon::utility::makeRandomColor(id); + } + } glBindTexture(GL_TEXTURE_2D, framebufferTexture); glTexImage2D(GL_TEXTURE_2D, 0, - showDepth ? GL_DEPTH_COMPONENT : (showAlbedo ? GL_RGB32F : GL_RGBA32F), + showDepth ? GL_DEPTH_COMPONENT + : ((showAlbedo || showPrimID || showGeomID || showInstID) + ? GL_RGB32F + : GL_RGBA32F), windowSize.x, windowSize.y, 0, - showDepth ? GL_DEPTH_COMPONENT : (showAlbedo ? GL_RGB : GL_RGBA), + showDepth ? GL_DEPTH_COMPONENT + : ((showAlbedo || showPrimID || showGeomID || showInstID) + ? GL_RGB + : GL_RGBA), GL_FLOAT, - showDepth ? depthFb : fb); + showDepth ? depthFb + : ((showPrimID || showGeomID || showInstID) ? idFb : fb)); framebuffer.unmap(fb); @@ -554,11 +593,28 @@ void GLFWOSPRayWindow::buildUI() } ImGui::Checkbox("cancel frame on interaction", &cancelFrameOnInteraction); - ImGui::Checkbox("show depth", &showDepth); - if (showDepth) - showAlbedo = false; - else - ImGui::Checkbox("show albedo", &showAlbedo); + + static int whichAOV = 0; + if (ImGui::Combo("AOV Display##whichAOV", + &whichAOV, + AOVUI_callback, + nullptr, + g_AOVs.size())) { + auto aovStr = g_AOVs[whichAOV]; + showDepth = showAlbedo = showPrimID = showGeomID = showInstID = false; + if (aovStr == "depth") + showDepth = true; + if (aovStr == "albedo") + showAlbedo = true; + if (aovStr == "primID") + showPrimID = true; + if (aovStr == "objID") + showGeomID = true; + if (aovStr == "instID") + showInstID = true; + } + + ImGui::Separator(); if (denoiserAvailable) { if (ImGui::Checkbox("denoiser", &denoiserEnabled)) updateFrameOpsNextFrame = true; @@ -635,6 +691,38 @@ void GLFWOSPRayWindow::buildUI() addObjectToCommit(renderer->handle()); } + if (ImGui::Checkbox("renderSunSky", &renderSunSky)) { + if (renderSunSky) { + sunSky.setParam("direction", sunDirection); + world.setParam("light", cpp::CopiedData(sunSky)); + addObjectToCommit(sunSky.handle()); + } else { + cpp::Light light("ambient"); + light.setParam("visible", false); + light.commit(); + world.setParam("light", cpp::CopiedData(light)); + } + addObjectToCommit(world.handle()); + } + if (renderSunSky) { + if (ImGui::DragFloat3("sunDirection", sunDirection, 0.01f, -1.f, 1.f)) { + sunSky.setParam("direction", sunDirection); + addObjectToCommit(sunSky.handle()); + addObjectToCommit(world.handle()); + } + if (ImGui::DragFloat("turbidity", &turbidity, 0.1f, 1.f, 10.f)) { + sunSky.setParam("turbidity", turbidity); + addObjectToCommit(sunSky.handle()); + addObjectToCommit(world.handle()); + } + if (ImGui::DragFloat( + "horizonExtension", &horizonExtension, 0.01f, 0.f, 1.f)) { + sunSky.setParam("horizonExtension", horizonExtension); + addObjectToCommit(sunSky.handle()); + addObjectToCommit(world.handle()); + } + } + if (rendererType == OSPRayRendererType::PATHTRACER) { static int maxDepth = 20; if (ImGui::SliderInt("maxPathLength", &maxDepth, 1, 64)) { @@ -687,35 +775,6 @@ void GLFWOSPRayWindow::buildUI() updateCamera(); addObjectToCommit(camera.handle()); } - - if (ImGui::Checkbox("renderSunSky", &renderSunSky)) { - if (renderSunSky) { - sunSky.setParam("direction", sunDirection); - world.setParam("light", cpp::CopiedData(sunSky)); - addObjectToCommit(sunSky.handle()); - } else { - cpp::Light light("ambient"); - light.setParam("visible", false); - light.commit(); - world.setParam("light", cpp::CopiedData(light)); - } - addObjectToCommit(world.handle()); - } - if (renderSunSky) { - if (ImGui::DragFloat3("sunDirection", sunDirection, 0.01f, -1.f, 1.f)) { - sunSky.setParam("direction", sunDirection); - addObjectToCommit(sunSky.handle()); - } - if (ImGui::DragFloat("turbidity", &turbidity, 0.1f, 1.f, 10.f)) { - sunSky.setParam("turbidity", turbidity); - addObjectToCommit(sunSky.handle()); - } - if (ImGui::DragFloat( - "horizonExtension", &horizonExtension, 0.01f, 0.f, 1.f)) { - sunSky.setParam("horizonExtension", horizonExtension); - addObjectToCommit(sunSky.handle()); - } - } } else if (rendererType == OSPRayRendererType::SCIVIS) { static bool shadowsEnabled = false; if (ImGui::Checkbox("shadows", &shadowsEnabled)) { diff --git a/apps/ospExamples/GLFWOSPRayWindow.h b/apps/ospExamples/GLFWOSPRayWindow.h index 0c13fbd25c..5896bde717 100644 --- a/apps/ospExamples/GLFWOSPRayWindow.h +++ b/apps/ospExamples/GLFWOSPRayWindow.h @@ -1,4 +1,4 @@ -// Copyright 2018-2021 Intel Corporation +// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -61,6 +61,9 @@ class GLFWOSPRayWindow bool denoiserEnabled{false}; bool showAlbedo{false}; bool showDepth{false}; + bool showPrimID{false}; + bool showGeomID{false}; + bool showInstID{false}; bool renderSunSky{false}; bool cancelFrameOnInteraction{false}; bool showUnstructuredCells{false}; diff --git a/apps/ospExamples/example_common.h b/apps/ospExamples/example_common.h index f2c48e1350..c2b7231446 100644 --- a/apps/ospExamples/example_common.h +++ b/apps/ospExamples/example_common.h @@ -1,4 +1,4 @@ -// Copyright 2018-2020 Intel Corporation +// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/apps/ospExamples/ospExample.cpp b/apps/ospExamples/ospExample.cpp index d07549d387..147aa303c6 100644 --- a/apps/ospExamples/ospExample.cpp +++ b/apps/ospExamples/ospExample.cpp @@ -1,4 +1,4 @@ -// Copyright 2018-2020 Intel Corporation +// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "GLFWOSPRayWindow.h" diff --git a/apps/ospTestSuite/CMakeLists.txt b/apps/ospTestSuite/CMakeLists.txt index e0a58b2248..c65ba56fd5 100644 --- a/apps/ospTestSuite/CMakeLists.txt +++ b/apps/ospTestSuite/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2017-2021 Intel Corporation +## Copyright 2017 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 if (NOT OSPRAY_ENABLE_APPS_TESTING) @@ -39,6 +39,8 @@ add_executable(ospTestSuite $<$:test_glm_compat.cpp> test_camera.cpp test_motionblur.cpp + test_framebuffer.cpp + test_interpolation.cpp ospTestSuite.cpp ) diff --git a/apps/ospTestSuite/environment.cpp b/apps/ospTestSuite/environment.cpp index c55b0a3ac0..a1308e5940 100644 --- a/apps/ospTestSuite/environment.cpp +++ b/apps/ospTestSuite/environment.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2021 Intel Corporation +// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "environment.h" diff --git a/apps/ospTestSuite/environment.h b/apps/ospTestSuite/environment.h index 9bea074e19..2421e57e90 100644 --- a/apps/ospTestSuite/environment.h +++ b/apps/ospTestSuite/environment.h @@ -1,4 +1,4 @@ -// Copyright 2017-2021 Intel Corporation +// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/apps/ospTestSuite/ospTestSuite.cpp b/apps/ospTestSuite/ospTestSuite.cpp index b213f862cb..e8eec9099b 100644 --- a/apps/ospTestSuite/ospTestSuite.cpp +++ b/apps/ospTestSuite/ospTestSuite.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2021 Intel Corporation +// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_fixture.h" diff --git a/apps/ospTestSuite/test_camera.cpp b/apps/ospTestSuite/test_camera.cpp index 2158d0208c..023e948108 100644 --- a/apps/ospTestSuite/test_camera.cpp +++ b/apps/ospTestSuite/test_camera.cpp @@ -1,4 +1,4 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_camera.h" @@ -38,7 +38,6 @@ void Stereo::SetUp() camera.setParam("position", pos); camera.setParam("stereoMode", stereoMode); camera.setParam("transform", affine3f(one)); - camera.commit(); } // Test Instantiations ////////////////////////////////////////////////////// diff --git a/apps/ospTestSuite/test_enums.cpp b/apps/ospTestSuite/test_enums.cpp index c9a98ae1f8..80fe44524a 100644 --- a/apps/ospTestSuite/test_enums.cpp +++ b/apps/ospTestSuite/test_enums.cpp @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Intel Corporation +// Copyright 2019 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include @@ -110,7 +110,14 @@ TEST(Enums, VKLFilter) ASSERT_EQ(OSP_VOLUME_FILTER_TRILINEAR, VKL_FILTER_TRILINEAR); ASSERT_EQ(OSP_VOLUME_FILTER_TRICUBIC, VKL_FILTER_TRICUBIC); } - + +TEST(Enums, VKLFormat) +{ + ASSERT_LE(sizeof(OSPVolumeFormat), sizeof(VKLFormat)); + ASSERT_EQ(OSP_VOLUME_FORMAT_TILE, VKL_FORMAT_TILE); + ASSERT_EQ(OSP_VOLUME_FORMAT_DENSE_ZYX, VKL_FORMAT_DENSE_ZYX); +} + TEST(Enums, VKLError) { ASSERT_LE(sizeof(OSPError), sizeof(VKLError)); diff --git a/apps/ospTestSuite/test_fixture.cpp b/apps/ospTestSuite/test_fixture.cpp index 3c10de8a97..73342b6b32 100644 --- a/apps/ospTestSuite/test_fixture.cpp +++ b/apps/ospTestSuite/test_fixture.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2021 Intel Corporation +// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_fixture.h" diff --git a/apps/ospTestSuite/test_fixture.h b/apps/ospTestSuite/test_fixture.h index c7e8474493..aebe332ad4 100644 --- a/apps/ospTestSuite/test_fixture.h +++ b/apps/ospTestSuite/test_fixture.h @@ -1,4 +1,4 @@ -// Copyright 2017-2021 Intel Corporation +// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/apps/ospTestSuite/test_framebuffer.cpp b/apps/ospTestSuite/test_framebuffer.cpp new file mode 100644 index 0000000000..5307bdce24 --- /dev/null +++ b/apps/ospTestSuite/test_framebuffer.cpp @@ -0,0 +1,123 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "ArcballCamera.h" +#include "ospray_testing.h" +#include "rkcommon/utility/random.h" +#include "test_fixture.h" + +extern OSPRayEnvironment *ospEnv; + +namespace OSPRayTestScenes { + +class IDBuffer + : public Base, + public ::testing::TestWithParam> +{ + public: + IDBuffer(); + void SetUp() override; + void PerformRenderTest() override; + + protected: + OSPFrameBufferChannel idBuffer{OSP_FB_ID_PRIMITIVE}; + bool appIDs{false}; +}; + +IDBuffer::IDBuffer() +{ + auto params = GetParam(); + idBuffer = std::get<0>(params); + appIDs = std::get<1>(params); + rendererType = std::get<2>(params); + + framebuffer = + cpp::FrameBuffer(imgSize.x, imgSize.y, frameBufferFormat, idBuffer); + samplesPerPixel = 2; +} + +void IDBuffer::SetUp() +{ + Base::SetUp(); + + instances.clear(); + + auto builder = ospray::testing::newBuilder( + idBuffer == OSP_FB_ID_PRIMITIVE ? "perlin_noise_volumes" : "instancing"); + ospray::testing::setParam(builder, "rendererType", rendererType); + ospray::testing::setParam(builder, "numInstances", vec2ui(10, 3)); + ospray::testing::setParam(builder, "useIDs", appIDs); + ospray::testing::commit(builder); + + world = ospray::testing::buildWorld(builder); + ospray::testing::release(builder); +} + +inline uint8_t to_uc(const float f) +{ + return 255.f * clamp(f, 0.f, 1.0f); +} +inline uint32_t to_rgba8(const vec3f c) +{ + return to_uc(c.x) | (to_uc(c.y) << 8) | (to_uc(c.z) << 16) | 0xff000000; +} + +void IDBuffer::PerformRenderTest() +{ + if (!instances.empty()) + world.setParam("instance", cpp::CopiedData(instances)); + + world.commit(); + + ArcballCamera arcballCamera(world.getBounds(), imgSize); + camera.setParam("position", arcballCamera.eyePos()); + camera.setParam("direction", arcballCamera.lookDir()); + camera.setParam("up", arcballCamera.upDir()); + camera.setParam("fovy", 45.0f); + camera.commit(); + + renderer.commit(); + + framebuffer.resetAccumulation(); + + RenderFrame(); + + auto *framebuffer_data = (uint32_t *)framebuffer.map(idBuffer); + std::vector framebufferData(imgSize.product()); + for (int i = 0; i < imgSize.product(); i++) + framebufferData[i] = framebuffer_data[i] == -1u + ? 0 + : to_rgba8(rkcommon::utility::makeRandomColor(framebuffer_data[i])); + framebuffer.unmap(framebuffer_data); + + if (ospEnv->GetDumpImg()) { + EXPECT_EQ( + imageTool->saveTestImage(framebufferData.data()), OsprayStatus::Ok); + } else { + EXPECT_EQ(imageTool->compareImgWithBaseline(framebufferData.data()), + OsprayStatus::Ok); + } +} + +// Test Instantiations ////////////////////////////////////////////////////// + +TEST_P(IDBuffer, IDBuffer) +{ + PerformRenderTest(); +} + +INSTANTIATE_TEST_SUITE_P(Primitive, + IDBuffer, + ::testing::Combine(::testing::Values(OSP_FB_ID_PRIMITIVE), + ::testing::Values(false), + ::testing::Values("scivis", "pathtracer"))); + +INSTANTIATE_TEST_SUITE_P(ObjectInstance, + IDBuffer, + ::testing::Combine(::testing::Values(OSP_FB_ID_OBJECT, OSP_FB_ID_INSTANCE), + ::testing::Bool(), + ::testing::Values("scivis", "pathtracer"))); + +} // namespace OSPRayTestScenes diff --git a/apps/ospTestSuite/test_geometry.cpp b/apps/ospTestSuite/test_geometry.cpp index 0c0300bbea..d590f99953 100644 --- a/apps/ospTestSuite/test_geometry.cpp +++ b/apps/ospTestSuite/test_geometry.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2021 Intel Corporation +// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_geometry.h" @@ -119,6 +119,37 @@ void Curves::SetUp() camera.setParam("up", arcballCamera.upDir()); } +class ClippingParallel : public Base, public ::testing::Test +{ + public: + ClippingParallel(); + void SetUp() override; +}; + +ClippingParallel::ClippingParallel() +{ + rendererType = "pathtracer"; +} + +void ClippingParallel::SetUp() +{ + Base::SetUp(); + + instances.clear(); + + auto builder = ospray::testing::newBuilder("clip_with_planes"); + ospray::testing::setParam(builder, "rendererType", rendererType); + ospray::testing::commit(builder); + + world = ospray::testing::buildWorld(builder); + ospray::testing::release(builder); + + camera = cpp::Camera("orthographic"); + camera.setParam("height", 2.5f); + camera.setParam("direction", vec3f(-0.5f, -0.5f, 1.0f)); + camera.setParam("position", vec3f(1.0f, 1.0f, -2.0f)); +} + // Test Instantiations ////////////////////////////////////////////////////// TEST_P(SpherePrecision, sphere) @@ -152,6 +183,23 @@ INSTANTIATE_TEST_SUITE_P(TestScenesGeometry, ::testing::Values("scivis", "pathtracer", "ao"), ::testing::Values(16))); +// INSTANTIATE_TEST_SUITE_P(TestScenesInterpolation, +// FromOsprayTesting, +// ::testing::Combine(::testing::Values("interpolation_quads_color_fv", +// "interpolation_subd_color_fv", +// "interpolation_quads_color_vv", +// "interpolation_subd_color_vv", +// "interpolation_quads_color_u", +// "interpolation_subd_color_u", +// "interpolation_quads_color_c", +// "interpolation_subd_color_c", +// "interpolation_quads_tex_fv", +// "interpolation_subd_tex_fv", +// "interpolation_quads_tex_vv", +// "interpolation_subd_tex_vv"), +// ::testing::Values("scivis"), +// ::testing::Values(1))); + TEST_P(Curves, test_scenes) { PerformRenderTest(); @@ -181,6 +229,11 @@ INSTANTIATE_TEST_SUITE_P(TestScenesClipping, ::testing::Values("scivis", "pathtracer", "ao"), ::testing::Values(16))); +TEST_F(ClippingParallel, planes) +{ + PerformRenderTest(); +} + TEST_P(FromOsprayTestingMaxDepth, test_scenes) { PerformRenderTest(); diff --git a/apps/ospTestSuite/test_interpolation.cpp b/apps/ospTestSuite/test_interpolation.cpp new file mode 100644 index 0000000000..d1d0b73fd4 --- /dev/null +++ b/apps/ospTestSuite/test_interpolation.cpp @@ -0,0 +1,137 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "ArcballCamera.h" +#include "ospray_testing.h" +#include "rkcommon/utility/random.h" +#include "test_fixture.h" + +extern OSPRayEnvironment *ospEnv; + +namespace OSPRayTestScenes { + +class Interpolation + : public Base, + public ::testing::TestWithParam> +{ + public: + Interpolation(); + void SetUp() override; + void PerformRenderTest() override; + + protected: + OSPFrameBufferChannel idBuffer{OSP_FB_COLOR}; + bool useSubd{false}; + unsigned int attribute{0}; + unsigned int interpolation{0}; +}; + +Interpolation::Interpolation() +{ + samplesPerPixel = 2; + rendererType = "scivis"; + + auto params = GetParam(); + useSubd = std::get<0>(params); + attribute = std::get<1>(params); + interpolation = std::get<2>(params); + + if (attribute == 2) + idBuffer = OSP_FB_NORMAL; + + framebuffer = + cpp::FrameBuffer(imgSize.x, imgSize.y, frameBufferFormat, idBuffer); +} + +void Interpolation::SetUp() +{ + Base::SetUp(); + + instances.clear(); + + auto builder = ospray::testing::newBuilder("interpolation"); + ospray::testing::setParam(builder, "rendererType", rendererType); + ospray::testing::setParam(builder, "useSubd", useSubd); + ospray::testing::setParam(builder, "attribute", attribute); + ospray::testing::setParam(builder, "interpolation", interpolation); + ospray::testing::commit(builder); + + world = ospray::testing::buildWorld(builder); + ospray::testing::release(builder); +} + +inline uint8_t to_uc(const float f) +{ + return 255.f * clamp(f, 0.f, 1.0f); +} +inline uint32_t to_rgba8(const vec3f c) +{ + return to_uc(c.x) | (to_uc(c.y) << 8) | (to_uc(c.z) << 16) | 0xff000000; +} + +void Interpolation::PerformRenderTest() +{ + if (!instances.empty()) + world.setParam("instance", cpp::CopiedData(instances)); + + world.commit(); + + ArcballCamera arcballCamera(world.getBounds(), imgSize); + camera.setParam("position", arcballCamera.eyePos()); + camera.setParam("direction", arcballCamera.lookDir()); + camera.setParam("up", arcballCamera.upDir()); + camera.commit(); + + renderer.commit(); + + framebuffer.resetAccumulation(); + + RenderFrame(); + + auto *framebuffer_data = (uint32_t *)framebuffer.map(idBuffer); + std::vector framebufferData(imgSize.product()); + for (int i = 0; i < imgSize.product(); i++) { + if (attribute == 2) { // normals + const vec3f normal = ((vec3f *)framebuffer_data)[i]; + framebufferData[i] = to_rgba8(0.5f * normal + 0.5f); + } else + framebufferData[i] = framebuffer_data[i]; + } + framebuffer.unmap(framebuffer_data); + + if (ospEnv->GetDumpImg()) { + EXPECT_EQ( + imageTool->saveTestImage(framebufferData.data()), OsprayStatus::Ok); + } else { + EXPECT_EQ(imageTool->compareImgWithBaseline(framebufferData.data()), + OsprayStatus::Ok); + } +} + +// Test Instantiations ////////////////////////////////////////////////////// + +TEST_P(Interpolation, Interpolation) +{ + PerformRenderTest(); +} + +INSTANTIATE_TEST_SUITE_P(Color, + Interpolation, + ::testing::Combine(::testing::Bool(), + ::testing::Values(0), + ::testing::Values(0, 1, 2, 3))); + +INSTANTIATE_TEST_SUITE_P(Texcoord, + Interpolation, + ::testing::Combine( + ::testing::Bool(), ::testing::Values(1), ::testing::Values(0, 1))); + +INSTANTIATE_TEST_SUITE_P(Normal, + Interpolation, + ::testing::Combine(::testing::Values(false), + ::testing::Values(2), + ::testing::Values(0, 1))); + +} // namespace OSPRayTestScenes diff --git a/apps/ospTestSuite/test_light.cpp b/apps/ospTestSuite/test_light.cpp index 29421ba4a4..db06974e89 100644 --- a/apps/ospTestSuite/test_light.cpp +++ b/apps/ospTestSuite/test_light.cpp @@ -1,4 +1,4 @@ -// Copyright 2020-2022 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_light.h" diff --git a/apps/ospTestSuite/test_light.h b/apps/ospTestSuite/test_light.h index 5bd673e9f0..316c47f3dc 100644 --- a/apps/ospTestSuite/test_light.h +++ b/apps/ospTestSuite/test_light.h @@ -1,4 +1,4 @@ -// Copyright 2020-2022 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_fixture.h" diff --git a/apps/ospTestSuite/test_motionblur.cpp b/apps/ospTestSuite/test_motionblur.cpp index 70828c7f49..8e398023c3 100644 --- a/apps/ospTestSuite/test_motionblur.cpp +++ b/apps/ospTestSuite/test_motionblur.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2021 Intel Corporation +// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ospray_testing.h" diff --git a/apps/ospTestSuite/test_tools.cpp b/apps/ospTestSuite/test_tools.cpp index 124882166c..65084c389d 100644 --- a/apps/ospTestSuite/test_tools.cpp +++ b/apps/ospTestSuite/test_tools.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2021 Intel Corporation +// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #define STB_IMAGE_WRITE_IMPLEMENTATION diff --git a/apps/ospTestSuite/test_tools.h b/apps/ospTestSuite/test_tools.h index 84b6f1f541..b103e75cf3 100644 --- a/apps/ospTestSuite/test_tools.h +++ b/apps/ospTestSuite/test_tools.h @@ -1,4 +1,4 @@ -// Copyright 2017-2021 Intel Corporation +// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/apps/ospTestSuite/test_volumetric.cpp b/apps/ospTestSuite/test_volumetric.cpp index 8420dbf972..d5ccf591c1 100644 --- a/apps/ospTestSuite/test_volumetric.cpp +++ b/apps/ospTestSuite/test_volumetric.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2021 Intel Corporation +// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_volumetric.h" @@ -342,6 +342,7 @@ INSTANTIATE_TEST_SUITE_P(TestScenesVolumes, "unstructured_volume_simple", "particle_volume", "vdb_volume", + "vdb_volume_packed", "gravity_spheres_amr"), ::testing::Values("scivis", "pathtracer", "ao"), ::testing::Values(16))); diff --git a/apps/ospTutorial/CMakeLists.txt b/apps/ospTutorial/CMakeLists.txt index 64ff6d0784..765bfba766 100644 --- a/apps/ospTutorial/CMakeLists.txt +++ b/apps/ospTutorial/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2018-2021 Intel Corporation +## Copyright 2018 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 if (NOT OSPRAY_ENABLE_APPS_TUTORIALS) diff --git a/apps/ospTutorial/ospTutorial.c b/apps/ospTutorial/ospTutorial.c index be3c319c84..ff26781a10 100644 --- a/apps/ospTutorial/ospTutorial.c +++ b/apps/ospTutorial/ospTutorial.c @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This is a small example tutorial how to use OSPRay in an application. diff --git a/apps/ospTutorial/ospTutorial.cpp b/apps/ospTutorial/ospTutorial.cpp index 276ba7b9bf..f16bf2f2fd 100644 --- a/apps/ospTutorial/ospTutorial.cpp +++ b/apps/ospTutorial/ospTutorial.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This is a small example tutorial how to use OSPRay in an application. diff --git a/apps/ospTutorial/ospTutorialAsync.c b/apps/ospTutorial/ospTutorialAsync.c index 320446ac27..4f1d7d9673 100644 --- a/apps/ospTutorial/ospTutorialAsync.c +++ b/apps/ospTutorial/ospTutorialAsync.c @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This is a small example tutorial of how to use OSPRay's async API in an diff --git a/apps/ospTutorial/ospTutorialFindospray/CMakeLists.txt b/apps/ospTutorial/ospTutorialFindospray/CMakeLists.txt index d6f74e4d6f..a1c1661ff7 100644 --- a/apps/ospTutorial/ospTutorialFindospray/CMakeLists.txt +++ b/apps/ospTutorial/ospTutorialFindospray/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2019-2020 Intel Corporation +## Copyright 2019 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # NOTE: This CMakeLists.txt is intended to be used to exercise an OSPRay diff --git a/apps/ospTutorial/ospTutorialGLM.cpp b/apps/ospTutorial/ospTutorialGLM.cpp index f061feac81..afcd0548d3 100644 --- a/apps/ospTutorial/ospTutorialGLM.cpp +++ b/apps/ospTutorial/ospTutorialGLM.cpp @@ -1,4 +1,4 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This is a small example tutorial how to use OSPRay in an application using diff --git a/apps/utility/CMakeLists.txt b/apps/utility/CMakeLists.txt index b9c738c195..b256ee89cc 100644 --- a/apps/utility/CMakeLists.txt +++ b/apps/utility/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 if (NOT OSPRAY_ENABLE_APPS_TESTING) diff --git a/apps/utility/ospConvertRawToAMR.cpp b/apps/utility/ospConvertRawToAMR.cpp index 394db5b097..c9d1ce3b5c 100644 --- a/apps/utility/ospConvertRawToAMR.cpp +++ b/apps/utility/ospConvertRawToAMR.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "rawToAMR.h" diff --git a/cmake/clang-format.cmake b/cmake/clang-format.cmake index 6a64c45560..ab60db2d93 100644 --- a/cmake/clang-format.cmake +++ b/cmake/clang-format.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2019 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # additional target to run clang-format on all source files diff --git a/cmake/compiler/clang.cmake b/cmake/compiler/clang.cmake index 808fcc5d3d..ef378b6e3f 100644 --- a/cmake/compiler/clang.cmake +++ b/cmake/compiler/clang.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(OSPRAY_CXX_FLAGS "-fno-strict-aliasing -Wno-narrowing") diff --git a/cmake/compiler/dpcpp.cmake b/cmake/compiler/dpcpp.cmake index ba514c0d75..68154e0b72 100644 --- a/cmake/compiler/dpcpp.cmake +++ b/cmake/compiler/dpcpp.cmake @@ -1,7 +1,7 @@ -## Copyright 2009-2022 Intel Corporation +## Copyright 2022 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 -set(OSPRAY_CXX_FLAGS "-fno-strict-aliasing -Wno-narrowing") +set(OSPRAY_CXX_FLAGS "-fno-strict-aliasing -Wno-narrowing -fhonor-infinities -fhonor-nans") if(OSPRAY_STRICT_BUILD) # OK to turn off. @@ -60,3 +60,9 @@ set(CMAKE_CXX_FLAGS "${OSPRAY_CXX_FLAGS} ${CMAKE_CXX_FLAGS}") if (APPLE) set(CMAKE_CXX_FLAGS "-mmacosx-version-min=10.9 ${CMAKE_CXX_FLAGS}") # we only use MacOSX 10.9 features endif() + +# enable -static-intel +set(CMAKE_EXE_LINKER_FLAGS "-static-intel ${CMAKE_EXE_LINKER_FLAGS}") +set(CMAKE_SHARED_LINKER_FLAGS "-static-intel ${CMAKE_SHARED_LINKER_FLAGS}") +set(CMAKE_STATIC_LINKER_FLAGS "-static-intel ${CMAKE_STATIC_LINKER_FLAGS}") +set(CMAKE_MODULE_LINKER_FLAGS "-static-intel ${CMAKE_MODULE_LINKER_FLAGS}") diff --git a/cmake/compiler/gcc.cmake b/cmake/compiler/gcc.cmake index bbe87370b1..da34108ed6 100644 --- a/cmake/compiler/gcc.cmake +++ b/cmake/compiler/gcc.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2019 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(OSPRAY_CXX_FLAGS "-fno-strict-aliasing -Wno-narrowing -Wno-unknown-pragmas") diff --git a/cmake/compiler/icc.cmake b/cmake/compiler/icc.cmake index da6c5ca25a..c57e58211e 100644 --- a/cmake/compiler/icc.cmake +++ b/cmake/compiler/icc.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2019 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(OSPRAY_CXX_FLAGS "-fno-strict-aliasing -no-ansi-alias -Wno-unknown-pragmas") diff --git a/cmake/compiler/ispc.cmake b/cmake/compiler/ispc.cmake index 9d8eef671a..663f0d3720 100644 --- a/cmake/compiler/ispc.cmake +++ b/cmake/compiler/ispc.cmake @@ -1,8 +1,8 @@ -## Copyright 2009-2022 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # ISPC versions to look for, in descending order (newest first) -set(ISPC_VERSION_WORKING "1.17.0" "1.16.1" "1.16.0") +set(ISPC_VERSION_WORKING "1.18.0") list(GET ISPC_VERSION_WORKING -1 ISPC_VERSION_REQUIRED) if (NOT ISPC_EXECUTABLE) diff --git a/cmake/compiler/msvc.cmake b/cmake/compiler/msvc.cmake index fc691dc5a0..b7eeca37db 100644 --- a/cmake/compiler/msvc.cmake +++ b/cmake/compiler/msvc.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2019 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMMON_CXX_FLAGS "/EHsc /MP /GR /bigobj") diff --git a/cmake/ospray_cmake_config.cmake b/cmake/ospray_cmake_config.cmake index cc628b144d..093f69bef6 100644 --- a/cmake/ospray_cmake_config.cmake +++ b/cmake/ospray_cmake_config.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2019 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # Version header diff --git a/cmake/ospray_cmake_config/osprayConfig.cmake.in b/cmake/ospray_cmake_config/osprayConfig.cmake.in index 8d1a7e18d1..a46461339d 100644 --- a/cmake/ospray_cmake_config/osprayConfig.cmake.in +++ b/cmake/ospray_cmake_config/osprayConfig.cmake.in @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # Called if we failed to find OSPRay or any of it's required dependencies, @@ -95,7 +95,6 @@ set(OSPRAY_ISPC_TARGET_LIST @OSPRAY_ISPC_TARGET_LIST@) set(OSPRAY_ISPC_ADDRESSING @OSPRAY_ISPC_ADDRESSING@) set(OSPRAY_TILE_SIZE @OSPRAY_TILE_SIZE@) -set(OSPRAY_PIXELS_PER_JOB @OSPRAY_PIXELS_PER_JOB@) set(RKCOMMON_VERSION_REQUIRED @RKCOMMON_VERSION_REQUIRED@) set(EMBREE_VERSION_REQUIRED @EMBREE_VERSION_REQUIRED@) diff --git a/cmake/ospray_cmake_config/osprayConfigVersion.cmake.in b/cmake/ospray_cmake_config/osprayConfigVersion.cmake.in index 716179f3d6..85734ee759 100644 --- a/cmake/ospray_cmake_config/osprayConfigVersion.cmake.in +++ b/cmake/ospray_cmake_config/osprayConfigVersion.cmake.in @@ -1,4 +1,4 @@ -## Copyright 2009-2019 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(PACKAGE_VERSION "@OSPRAY_VERSION@") diff --git a/cmake/ospray_cmake_config/osprayUse.cmake.in b/cmake/ospray_cmake_config/osprayUse.cmake.in index 0e453c5103..db7be901fc 100644 --- a/cmake/ospray_cmake_config/osprayUse.cmake.in +++ b/cmake/ospray_cmake_config/osprayUse.cmake.in @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # NOTE(jda) - Add CMake commands which will be invoked when find_package(ospray) diff --git a/cmake/ospray_macros.cmake b/cmake/ospray_macros.cmake index a1a8800e2e..b1f4d76227 100644 --- a/cmake/ospray_macros.cmake +++ b/cmake/ospray_macros.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2022 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 include(CMakeFindDependencyMacro) diff --git a/cmake/ospray_options.cmake b/cmake/ospray_options.cmake index 529cce9a8a..fd28c4485e 100644 --- a/cmake/ospray_options.cmake +++ b/cmake/ospray_options.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2022 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ############################################################## @@ -11,9 +11,9 @@ include(CMakeDependentOption) set(OSPRAY_CMAKECONFIG_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/ospray-${OSPRAY_VERSION}") -set(RKCOMMON_VERSION_REQUIRED 1.9.0) +set(RKCOMMON_VERSION_REQUIRED 1.10.0) set(EMBREE_VERSION_REQUIRED 3.13.1) -set(OPENVKL_VERSION_REQUIRED 1.2.0) +set(OPENVKL_VERSION_REQUIRED 1.3.0) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) diff --git a/cmake/ospray_redistribute_deps.cmake b/cmake/ospray_redistribute_deps.cmake index 21fe0de384..4aef88a3f6 100644 --- a/cmake/ospray_redistribute_deps.cmake +++ b/cmake/ospray_redistribute_deps.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 macro(ospray_install_namelink NAME) diff --git a/cmake/ospray_version.cmake b/cmake/ospray_version.cmake index 0d0defcbfe..1226cc3bc5 100644 --- a/cmake/ospray_version.cmake +++ b/cmake/ospray_version.cmake @@ -1,8 +1,8 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(OSPRAY_VERSION_MAJOR 2) -set(OSPRAY_VERSION_MINOR 9) +set(OSPRAY_VERSION_MINOR 10) set(OSPRAY_VERSION_PATCH 0) set(OSPRAY_SOVERSION 2) set(OSPRAY_VERSION_GITHASH 0) diff --git a/cmake/package.cmake b/cmake/package.cmake index f251fb68dc..106dbc16cc 100644 --- a/cmake/package.cmake +++ b/cmake/package.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(CMAKE_INSTALL_SCRIPTDIR scripts) diff --git a/doc/api.md b/doc/api.md index 0f6d2ef314..855d5b6f33 100644 --- a/doc/api.md +++ b/doc/api.md @@ -426,7 +426,7 @@ can be represented in OSPRay; valid constants are listed in the table below. -------------------------- --------------------------------------------------- - Type/Name Description + Type / Name Description -------------------------- --------------------------------------------------- OSP_DEVICE API device object reference @@ -905,6 +905,21 @@ VDB volumes have the following parameters: of voxels for the `level`. Only `OSP_FLOAT` is supported as field `OSPDataType`. + OSPData nodesPackedDense optionally provided instead of `node.data`, a + single array of all dense node data in a + contiguous zyx layout, provided in the same order + as the corresponding `node.*` parameters + + OSPData nodesPackedTile optionally provided instead of `node.data`, a + single array of all tile node data in a + contiguous layout, provided in the same order as + the corresponding `node.*` parameters + + uint32[] node.format for each input node, whether it is of format + `OSP_VOLUME_FORMAT_DENSE_ZYX` (and thus stored in + `nodesPackedDense`), or `OSP_VOLUME_FORMAT_TILE` + (stored in `nodesPackedTile`) + int filter filter used for reconstructing the field, default is `OSP_VOLUME_FILTER_TRILINEAR`, alternatively `OSP_VOLUME_FILTER_NEAREST`, or @@ -913,11 +928,15 @@ VDB volumes have the following parameters: int gradientFilter filter used for reconstructing the field during gradient computations, default same as `filter` - float background value that is used when sampling an undefined region - outside the volume domain, default `NaN` + float background value that is used when sampling an undefined + region outside the volume domain, default `NaN` ---------- ----------------- ------------------------------------------------- : Configuration parameters for VDB volumes. +The `nodesPackedDense` and `nodesPackedTile` together with `node.format` +parameters may be provided instead of `node.data`; this packed data +layout may provide better performance. + 1. Museth, K. VDB: High-Resolution Sparse Volumes with Dynamic Topology. ACM Transactions on Graphics 32(3), 2013. DOI: 10.1145/2487228.2487235 @@ -1013,7 +1032,7 @@ to `ospNewTransferFunction` and it is controlled by these parameters: ------------ ----------- ---------------------------------------------- vec3f[] color [data] array of colors (linear RGB) float[] opacity [data] array of opacities - vec2f valueRange domain (scalar range) this function maps from + box1f value domain (scalar range) this function maps from ------------ ----------- ---------------------------------------------- : Parameters accepted by the linear transfer function. @@ -1049,6 +1068,8 @@ used. float anisotropy 0.0 anisotropy of the (Henyey-Greenstein) phase function in [-1–1] ([path tracer] only), default to isotropic scattering + + uint32 id -1u optional user ID, for [framebuffer] channel `OSP_FB_ID_OBJECT` -------------------- ----------------- -------- --------------------------------------- : Parameters understood by VolumetricModel. @@ -1073,12 +1094,16 @@ recognizes the following parameters: Type Name Description -------------------- ----------------------- ------------------------------------------------- vec3f[] vertex.position [data] array of vertex positions, overridden by `motion.*` arrays - vec3f[] vertex.normal [data] array of vertex normals, overridden by `motion.*` arrays - vec4f[] / vec3f[] vertex.color [data] array of vertex colors (linear RGBA/RGB) - vec2f[] vertex.texcoord [data] array of vertex texture coordinates + vec3f[] normal [data] array of face-varying normals, overridden by `motion.*` arrays + vec3f[] vertex.normal [data] array of vertex-varying normals, overridden by `motion.*` arrays + vec4f[] / vec3f[] color [data] array of face-varying colors (linear RGBA/RGB) + vec4f[] / vec3f[] vertex.color [data] array of vertex-varying colors (linear RGBA/RGB) + vec2f[] texcoord [data] array of face-varying texture coordinates + vec2f[] vertex.texcoord [data] array of vertex-varying texture coordinates vec3ui[] / vec4ui[] index [data] array of (either triangle or quad) indices (into the vertex array(s)) vec3f[][] motion.vertex.position [data] array of vertex position arrays (uniformly distributed keys for deformation motion blur) - vec3f[][] motion.vertex.normal [data] array of vertex normal arrays (uniformly distributed keys for deformation motion blur) + vec3f[][] motion.normal [data] array of face-varying normal arrays (uniformly distributed keys for deformation motion blur) + vec3f[][] motion.vertex.normal [data] array of vertex-varying normal arrays (uniformly distributed keys for deformation motion blur) box1f time time associated with first and last key in `motion.*` arrays (for deformation motion blur), default [0, 1] -------------------- ----------------------- ------------------------------------------------- : Parameters defining a mesh geometry. @@ -1104,10 +1129,16 @@ the following parameters: ------- ------------------- -------------------------------------------------- vec3f[] vertex.position [data] array of vertex positions - vec4f[] vertex.color optional [data] array of vertex colors (linear + vec4f[] color optional [data] array of face-varying colors (linear + RGBA) + + vec4f[] vertex.color optional [data] array of vertex-varying colors (linear RGBA) - vec2f[] vertex.texcoord optional [data] array of vertex texture + vec2f[] texcoord optional [data] array of vertex-varying texture + coordinates + + vec2f[] vertex.texcoord optional [data] array of vertex-varying texture coordinates float level global level of tessellation, default 5 @@ -1370,30 +1401,26 @@ normal vectors orientation one can control whether inside or outside of the clipping geometry is being removed. For example, a clipping geometry with normals oriented outside clips everything what's inside. - ------------------------ -------------- ---------------------------------------------------- - Type Name Description - ------------------------ -------------- ---------------------------------------------------- - OSPGeometry geometry optional [geometry] object this model references + ----------------------------------------------- ------------- ---------------------------------------------------- + Type Name Description + ----------------------------------------------- ------------- ---------------------------------------------------- + OSPGeometry geometry optional [geometry] object this model references - OSPMaterial / uint32 material optional [material] applied to the geometry, may be - an index into the `material` parameter on the - [renderer] (if it exists) + OSPMaterial / OSPMaterial[] / uint32 / uint32[] material optional ([data] array of per-primitive) [material], + may be an index into the `material` parameter on + the renderer (if it exists) - vec4f color optional color assigned to the geometry (linear - RGBA) + vec4f / vec4f[] color optional ([data] array of per-primitive) color + assigned to the geometry (linear RGBA) - OSPMaterial[] / uint32[] material optional [data] array of (per-primitive) materials, - may be an index into the `material` parameter on - the renderer (if it exists) + uint8[] index optional [data] array of per-primitive indices into + `color` and `material` - vec4f[] color optional [data] array of (per-primitive) colors - (linear RGBA) + bool invertNormals inverts all shading normals (Ns), default false - uint8[] index optional [data] array of per-primitive indices into - `color` and `material` - - bool invertNormals inverts all shading normals (Ns), default false - ------------------------ -------------- ---------------------------------------------------- + uint32 id optional user ID, for [framebuffer] channel + `OSP_FB_ID_OBJECT`, default -1u + ----------------------------------------------- ------------- ---------------------------------------------------- : Parameters understood by GeometricModel. @@ -1828,6 +1855,8 @@ used. box1f time [0, 1] time associated with first and last key in `motion.*` arrays (for motion blur) + + uint32 id -1u optional user ID, for [framebuffer] channel `OSP_FB_ID_INSTANCE` ------------ ----------------- ---------- -------------------------------------------------------- : Parameters understood by instances. @@ -2890,15 +2919,18 @@ The parameter `frameBufferChannels` specifies which channels the framebuffer holds, and can be combined together by bitwise OR from the values of `OSPFrameBufferChannel` listed in the table below. - Name Description - ---------------- ----------------------------------------------------------- - OSP_FB_COLOR RGB color including alpha - OSP_FB_DEPTH euclidean distance to the camera (_not_ to the image plane), as linear 32\ bit float; for multiple samples per pixel their minimum is taken - OSP_FB_ACCUM accumulation buffer for progressive refinement - OSP_FB_VARIANCE for estimation of the current noise level if OSP_FB_ACCUM is also present, see [rendering] - OSP_FB_NORMAL accumulated world-space normal of the first non-specular hit, as vec3f - OSP_FB_ALBEDO accumulated material albedo (color without illumination) at the first hit, as vec3f - ---------------- ----------------------------------------------------------- + Name Description + ------------------- ---------------------------------------------------------- + OSP_FB_COLOR RGB color including alpha + OSP_FB_DEPTH euclidean distance to the camera (_not_ to the image plane), as linear 32\ bit float; for multiple samples per pixel their minimum is taken + OSP_FB_ACCUM accumulation buffer for progressive refinement + OSP_FB_VARIANCE for estimation of the current noise level if OSP_FB_ACCUM is also present, see [rendering] + OSP_FB_NORMAL accumulated world-space normal of the first non-specular hit, as vec3f + OSP_FB_ALBEDO accumulated material albedo (color without illumination) at the first hit, as vec3f + OSP_FB_ID_PRIMITIVE primitive index of the first hit, as uint32 + OSP_FB_ID_OBJECT geometric/volumetric model `id`, if specified, or index in [group] of first hit, as uint32 + OSP_FB_ID_INSTANCE user defined [instance] `id`, if specified, or instance index of first hit, as uint32 + ------------------- ---------------------------------------------------------- : Framebuffer channels constants (of type `OSPFrameBufferChannel`), naming optional information the framebuffer can store. These values can be combined by bitwise OR when passed to `ospNewFrameBuffer`. diff --git a/doc/compilation.md b/doc/compilation.md index 882807a5bd..06d89a335a 100644 --- a/doc/compilation.md +++ b/doc/compilation.md @@ -21,13 +21,13 @@ before you can build OSPRay you need the following prerequisites: (icc)](https://software.intel.com/en-us/c-compilers)), and standard Linux development tools. - Additionally you require a copy of the [Intel® Implicit SPMD Program - Compiler (ISPC)](http://ispc.github.io), version 1.16.0 or later. + Compiler (ISPC)](http://ispc.github.io), version 1.18.0 or later. Please obtain a release of ISPC from the [ISPC downloads page](https://ispc.github.io/downloads.html). The build system looks for ISPC in the `PATH` and in the directory right "next to" the checked-out OSPRay sources.^[For example, if OSPRay is in `~/Projects/ospray`, ISPC will also be searched in - `~/Projects/ispc-v1.17.0-linux`.] Alternatively set the CMake + `~/Projects/ispc-v1.18.0-linux`.] Alternatively set the CMake variable `ISPC_EXECUTABLE` to the location of the ISPC compiler. - OSPRay builds on top of the [Intel oneAPI Rendering Toolkit common library (rkcommon)](https://www.github.com/ospray/rkcommon). The @@ -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.2.0 or newer is required. If Open VKL is not + installing version 1.3.0 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/doc/legal.md b/doc/legal.md index cdab80ac27..a6dcc25b0b 100644 --- a/doc/legal.md +++ b/doc/legal.md @@ -1,7 +1,7 @@ Disclaimer and Legal Information ================================ -© 2013–2021 Intel Corporation +© 2013 Intel Corporation [Privacy Notice](https://www.intel.com/privacy) diff --git a/doc/links.md b/doc/links.md index b82ed5b3da..40436bc5d0 100644 --- a/doc/links.md +++ b/doc/links.md @@ -10,6 +10,7 @@ [volume]: documentation.html#volumes [curves]: documentation.html#curves [group]: documentation.html#groups +[instance]: documentation.html#instances [world]: documentation.html#world [data]: documentation.html#data [GeometricModel]: documentation.html#geometricmodels diff --git a/doc/preamble.tex b/doc/preamble.tex index 5bb30bd15d..c6d9a6aa8b 100644 --- a/doc/preamble.tex +++ b/doc/preamble.tex @@ -108,7 +108,7 @@ linkcolor=blue, pdfborder={0 0 0}} -\copyrightyears{2013--2021} +\copyrightyears{2013} \trademarkacknowledgment{% Intel, the Intel logo, Xeon, Intel Xeon Phi, and Intel Core are trademarks of Intel Corporation in the U.S. and/or other countries. diff --git a/doc/webtemplate.html b/doc/webtemplate.html index 77e0946af8..e1efe8893c 100644 --- a/doc/webtemplate.html +++ b/doc/webtemplate.html @@ -58,7 +58,7 @@ $if(select_legal)$ $else$ $endif$ diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 7bb410de9c..57ac187546 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 add_subdirectory(cpu) diff --git a/modules/cpu/CMakeLists.txt b/modules/cpu/CMakeLists.txt index bb5c5e52e6..08200e41d3 100644 --- a/modules/cpu/CMakeLists.txt +++ b/modules/cpu/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2022 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 cmake_dependent_option( @@ -31,9 +31,7 @@ set(OSPRAY_ISPC_DEVICE_SOURCES common/Data.cpp common/Future.cpp common/Group.cpp - common/Group.ispc common/Instance.cpp - common/Instance.ispc common/MotionTransform.cpp common/Managed.cpp common/OSPCommon.ispc @@ -46,9 +44,10 @@ set(OSPRAY_ISPC_DEVICE_SOURCES fb/FrameBufferView.cpp fb/LocalFB.ispc fb/LocalFB.cpp + fb/SparseFB.cpp + fb/SparseFB.ispc fb/ImageOp.cpp - fb/Tile.h - fb/TileError.cpp + fb/TaskError.cpp fb/registration.cpp fb/frame_ops/Blur.cpp @@ -57,9 +56,8 @@ set(OSPRAY_ISPC_DEVICE_SOURCES fb/frame_ops/SSAO.cpp fb/frame_ops/SSAO.ispc - fb/tile_ops/SaveTiles.cpp - fb/tile_ops/ToneMapper.cpp - fb/tile_ops/ToneMapper.ispc + fb/pixel_ops/ToneMapper.cpp + fb/pixel_ops/ToneMapper.ispc pf/PixelFilter.ih pf/PixelFilter.ispc @@ -68,7 +66,6 @@ set(OSPRAY_ISPC_DEVICE_SOURCES pf/PixelFilter.cpp camera/Camera.cpp - camera/Camera.ispc camera/PerspectiveCamera.ispc camera/PerspectiveCamera.cpp camera/OrthographicCamera.ispc @@ -77,7 +74,6 @@ set(OSPRAY_ISPC_DEVICE_SOURCES camera/PanoramicCamera.cpp camera/registration.cpp - geometry/Geometry.ispc geometry/Geometry.cpp geometry/GeometricModel.ispc geometry/GeometricModel.cpp @@ -147,14 +143,17 @@ set(OSPRAY_ISPC_DEVICE_SOURCES render/scivis/SciVis.cpp render/scivis/SciVis.ispc + render/scivis/SciVisData.cpp render/scivis/surfaces.ispc render/scivis/volumes.ispc render/scivis/lightAlpha.ispc render/pathtracer/PathTracer.ispc render/pathtracer/PathTracer.cpp + render/pathtracer/PathTracerData.cpp render/pathtracer/PathSampler.ispc render/pathtracer/GeometryLight.ispc + render/pathtracer/GeometryLight.cpp render/pathtracer/VirtualLight.ispc render/pathtracer/TransparentShadow.ispc render/pathtracer/ShadowCatcher.ispc @@ -236,6 +235,11 @@ set(OSPRAY_TILE_SIZE 64 CACHE STRING "Tile size (x,y dimensions)") set_property(CACHE OSPRAY_TILE_SIZE PROPERTY STRINGS 8 16 32 64 128 256 512) mark_as_advanced(OSPRAY_TILE_SIZE) +set(OSPRAY_RENDER_TASK_SIZE 8 CACHE STRING + "Render task size (x,y dimensions). 8 is the default, -1 indicates to use a SIMD-width render task size determined at runtime. Must be less than OSPRAY_TILE_SIZE.") +set_property(CACHE OSPRAY_RENDER_TASK_SIZE PROPERTY STRINGS -1 2 4 8 16 32 64) +mark_as_advanced(OSPRAY_RENDER_TASK_SIZE) + if (WIN32) set(TILE_STACK_DEFAULT_SIZE 64) elseif (APPLE) @@ -249,10 +253,6 @@ set(OSPRAY_MAX_STACK_TILE_SIZE ${TILE_STACK_DEFAULT_SIZE} CACHE STRING set_property(CACHE OSPRAY_MAX_STACK_TILE_SIZE PROPERTY STRINGS 8 16 32 64 128 256 512) mark_as_advanced(OSPRAY_MAX_STACK_TILE_SIZE) -set(OSPRAY_PIXELS_PER_JOB 64 CACHE STRING - "Must be multiple of largest vector width *and* <= OSPRAY_TILE_SIZE") -mark_as_advanced(OSPRAY_PIXELS_PER_JOB) - option(OSPRAY_DEBUG_NO_TASKING "Remove tasking parallelism system for debugging" OFF) @@ -309,11 +309,32 @@ target_compile_definitions(ospray_module_cpu PUBLIC TILE_SIZE=${OSPRAY_TILE_SIZE} MAX_TILE_SIZE=${OSPRAY_MAX_STACK_TILE_SIZE} - RENDERTILE_PIXELS_PER_JOB=${OSPRAY_PIXELS_PER_JOB} $<$:OSPRAY_SERIAL_RENDERING> ) +# ------------------------------------------------------- +# Install SDK headers +# ------------------------------------------------------- + +get_subdirectories(SUBDIRS ${CMAKE_CURRENT_LIST_DIR}) + +foreach(dir ${SUBDIRS}) + install(DIRECTORY ${dir} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ospray/SDK/modules/cpu + COMPONENT devel + FILES_MATCHING + PATTERN *.h + PATTERN *.ih + ) + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${dir} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ospray/SDK/modules/cpu + COMPONENT devel + FILES_MATCHING + PATTERN *_ispc.h + ) +endforeach() + ############################################################## # Additional interface targets ############################################################## diff --git a/modules/cpu/ISPCDevice.cpp b/modules/cpu/ISPCDevice.cpp index 7b982f60a5..67071f5d90 100644 --- a/modules/cpu/ISPCDevice.cpp +++ b/modules/cpu/ISPCDevice.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray @@ -452,7 +452,7 @@ OSPImageOperation ISPCDevice::newImageOp(const char *type) const void *ISPCDevice::frameBufferMap( OSPFrameBuffer _fb, OSPFrameBufferChannel channel) { - LocalFrameBuffer *fb = (LocalFrameBuffer *)_fb; + FrameBuffer *fb = (FrameBuffer *)_fb; return fb->mapBuffer(channel); } @@ -470,7 +470,7 @@ float ISPCDevice::getVariance(OSPFrameBuffer _fb) void ISPCDevice::resetAccumulation(OSPFrameBuffer _fb) { - LocalFrameBuffer *fb = (LocalFrameBuffer *)_fb; + FrameBuffer *fb = (FrameBuffer *)_fb; fb->clear(); } diff --git a/modules/cpu/ISPCDevice.h b/modules/cpu/ISPCDevice.h index 257d711886..041cfa6ce1 100644 --- a/modules/cpu/ISPCDevice.h +++ b/modules/cpu/ISPCDevice.h @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/ISPCDevice.ispc b/modules/cpu/ISPCDevice.ispc index ba769157f7..234dea312b 100644 --- a/modules/cpu/ISPCDevice.ispc +++ b/modules/cpu/ISPCDevice.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 export uniform int ISPCDevice_programCount() diff --git a/modules/cpu/camera/Camera.cpp b/modules/cpu/camera/Camera.cpp index 791d44eca0..2da5e31129 100644 --- a/modules/cpu/camera/Camera.cpp +++ b/modules/cpu/camera/Camera.cpp @@ -1,9 +1,8 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Camera.h" -#include "camera/Camera_ispc.h" #include "common/Util.h" namespace ospray { @@ -97,17 +96,16 @@ void Camera::commit() std::swap(shutter.lower, shutter.upper); } - ispc::Camera_set(getIE(), - nearClip, - (const ispc::vec2f &)imageStart, - (const ispc::vec2f &)imageEnd, - (const ispc::box1f &)shutter, - shutterType == OSP_SHUTTER_GLOBAL, - rollingShutterDuration, - shutterType == OSP_SHUTTER_ROLLING_RIGHT - || shutterType == OSP_SHUTTER_ROLLING_LEFT, - motionTransform.motionBlur, - embreeGeometry); + getSh()->nearClip = nearClip; + getSh()->subImage.lower = imageStart; + getSh()->subImage.upper = imageEnd; + getSh()->shutter = shutter; + getSh()->motionBlur = motionTransform.motionBlur; + getSh()->geom = embreeGeometry; + getSh()->globalShutter = shutterType == OSP_SHUTTER_GLOBAL; + getSh()->rollingShutterHorizontal = (shutterType == OSP_SHUTTER_ROLLING_RIGHT + || shutterType == OSP_SHUTTER_ROLLING_LEFT); + getSh()->rollingShutterDuration = rollingShutterDuration; } void Camera::setDevice(RTCDevice device) diff --git a/modules/cpu/camera/Camera.h b/modules/cpu/camera/Camera.h index a84345d5f1..780baeda6b 100644 --- a/modules/cpu/camera/Camera.h +++ b/modules/cpu/camera/Camera.h @@ -1,17 +1,20 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/MotionTransform.h" #include "common/Util.h" +// ispc shared +#include "CameraShared.h" namespace ospray { -//! base camera class abstraction -/*! the base class itself does not do anything useful; look into - perspectivecamera etc for that */ -struct OSPRAY_SDK_INTERFACE Camera : public ManagedObject +// base camera class abstraction +// the base class itself does not do anything useful; look into +// perspectivecamera etc for that +struct OSPRAY_SDK_INTERFACE Camera + : public AddStructShared { Camera(); ~Camera() override; diff --git a/modules/cpu/camera/Camera.ih b/modules/cpu/camera/Camera.ih index 3031eeb94d..20d8fbb462 100644 --- a/modules/cpu/camera/Camera.ih +++ b/modules/cpu/camera/Camera.ih @@ -1,17 +1,17 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 +// camera.ih Defines the abstract base class of an ISPC-side camera + #pragma once #include "common/Ray.ih" #include "rkcommon/math/box.ih" +// c++ shared +#include "CameraShared.h" -/*! \file camera.ih Defines the abstract base class of an ISPC-side camera */ - -struct Camera; - -/*! \brief Specifies the input parameters (time, screen, and lens - samples) required for 'initRay' to generate a primary ray */ +// Specifies the input parameters (time, screen, and lens +// samples) required for 'initRay' to generate a primary ray struct CameraSample { vec2f screen; // normalized screen sample, in [0..1] @@ -19,27 +19,6 @@ struct CameraSample float time; }; -/*! \brief Fct pointer type for 'virtual' method that sets a pixel */ -// generated ray.dir must be normalized to ensure ray.t is world-space distance -typedef void (*Camera_initRay)(const Camera *uniform, - varying Ray &ray, - const varying CameraSample &sample); - -struct Camera -{ - Camera_initRay initRay; /*!< the 'virtual' initRay() method */ - - bool motionBlur; // for the camera itself only, not in general - - float nearClip; - box2f subImage; // viewable tile / subrange to compute, in [0..1]^2 x [0..1]^2 - range1f shutter; // camera shutter open start and end time, in [0..1] - bool globalShutter; - bool rollingShutterHorizontal; - float rollingShutterDuration; - RTCGeometry geom; // only to access rtcGetGeometryTransform -}; - inline vec2f Camera_subRegion(const Camera *uniform self, const vec2f &screen) { return lerp(screen, self->subImage.lower, self->subImage.upper); diff --git a/modules/cpu/camera/Camera.ispc b/modules/cpu/camera/Camera.ispc deleted file mode 100644 index dcc53c8424..0000000000 --- a/modules/cpu/camera/Camera.ispc +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2009-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#include "Camera.ih" - -export void Camera_set(void *uniform _self, - const uniform float nearClip, - const uniform vec2f &imageStart, - const uniform vec2f &imageEnd, - const uniform box1f &shutter, - const uniform bool globalShutter, - const uniform float rollingShutterDuration, - const uniform bool rollingShutterHorizontal, - const uniform bool motionBlur, - RTCGeometry geom) -{ - uniform Camera *uniform self = (uniform Camera * uniform) _self; - self->nearClip = nearClip; - self->subImage.lower = imageStart; - self->subImage.upper = imageEnd; - self->shutter = shutter; - self->motionBlur = motionBlur; - self->geom = geom; - self->globalShutter = globalShutter; - self->rollingShutterHorizontal = rollingShutterHorizontal; - self->rollingShutterDuration = rollingShutterDuration; -} diff --git a/modules/cpu/camera/CameraShared.h b/modules/cpu/camera/CameraShared.h new file mode 100644 index 0000000000..581792a5e7 --- /dev/null +++ b/modules/cpu/camera/CameraShared.h @@ -0,0 +1,51 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef __cplusplus +#include "common/StructShared.h" +namespace ispc { +typedef void *Camera_initRay; +#else +struct Camera; +struct CameraSample; + +// Fct pointer type for 'virtual' method that sets a pixel, +// generated ray.dir must be normalized to ensure ray.t is world-space distance +typedef void (*Camera_initRay)(const Camera *uniform, + varying Ray &ray, + const varying CameraSample &sample); +#endif // __cplusplus + +struct Camera +{ + Camera_initRay initRay; // the 'virtual' initRay() method + + bool motionBlur; // for the camera itself only, not in general + + float nearClip; + box2f subImage; // viewable tile / subrange to compute, in [0..1]^2 x [0..1]^2 + range1f shutter; // camera shutter open start and end time, in [0..1] + bool globalShutter; + bool rollingShutterHorizontal; + float rollingShutterDuration; + RTCGeometry geom; // only to access rtcGetGeometryTransform + +#ifdef __cplusplus + Camera() + : initRay(nullptr), + motionBlur(false), + nearClip(1e-6f), + subImage(0.f), + shutter(0.f), + globalShutter(false), + rollingShutterHorizontal(false), + rollingShutterDuration(0.f), + geom(nullptr) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/camera/OrthographicCamera.cpp b/modules/cpu/camera/OrthographicCamera.cpp index 9862db087a..520a715b54 100644 --- a/modules/cpu/camera/OrthographicCamera.cpp +++ b/modules/cpu/camera/OrthographicCamera.cpp @@ -1,14 +1,15 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "OrthographicCamera.h" +// ispc exports #include "camera/OrthographicCamera_ispc.h" namespace ospray { OrthographicCamera::OrthographicCamera() { - ispcEquivalent = ispc::OrthographicCamera_create(); + getSh()->super.initRay = ispc::OrthographicCamera_initRay_addr(); } std::string OrthographicCamera::toString() const @@ -26,18 +27,26 @@ void OrthographicCamera::commit() vec2f size = height; size.x *= aspect; - ispc::OrthographicCamera_set(getIE(), - (const ispc::vec3f &)pos, - (const ispc::vec3f &)dir, - (const ispc::vec3f &)up, - (const ispc::vec2f &)size); + if (getSh()->super.motionBlur) { + getSh()->dir = dir; + getSh()->du_size = vec3f(size.x, size.y, 1.0f); + getSh()->dv_up = up; + getSh()->org = pos; + } else { + getSh()->dir = normalize(dir); + getSh()->du_size = normalize(cross(getSh()->dir, up)); + getSh()->dv_up = cross(getSh()->du_size, getSh()->dir) * size.y; + getSh()->du_size = getSh()->du_size * size.x; + getSh()->org = + pos - 0.5f * getSh()->du_size - 0.5f * getSh()->dv_up; // shift + } } box3f OrthographicCamera::projectBox(const box3f &b) const { box3f projection; ispc::OrthographicCamera_projectBox( - getIE(), (const ispc::box3f &)b, (ispc::box3f &)projection); + getSh(), (const ispc::box3f &)b, (ispc::box3f &)projection); return projection; } diff --git a/modules/cpu/camera/OrthographicCamera.h b/modules/cpu/camera/OrthographicCamera.h index fe25b72a5d..2e7a784d12 100644 --- a/modules/cpu/camera/OrthographicCamera.h +++ b/modules/cpu/camera/OrthographicCamera.h @@ -1,39 +1,27 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "camera/Camera.h" +// ispc shared +#include "OrthographicCameraShared.h" namespace ospray { -/*! \defgroup orthographic_camera The Orthographic Camera ("orthographic") - - \brief Implements a straightforward orthographic camera for orthographic - projections, without support for Depth of Field or Motion Blur - - \ingroup ospray_supported_cameras - - A simple orthographic camera. This camera type is loaded by passing - the type string "orthographic" to \ref ospNewCamera - - The orthographic camera supports the following parameters -
-  vec3f(a) pos;    // camera position
-  vec3f(a) dir;    // camera direction
-  vec3f(a) up;     // up vector
-  float    height; // size of the camera's image plane in y, in world
-  coordinates float    aspect; // aspect ratio (x/y)
-  
- - The functionality for a orthographic camera is implemented via the - \ref ospray::OrthographicCamera class. -*/ - -//! Implements a simple orthographic camera (see \subpage orthographic_camera) -struct OSPRAY_SDK_INTERFACE OrthographicCamera : public Camera +// The Orthographic Camera ("orthographic") +// +// Implements a straightforward orthographic camera for orthographic +// projections, without support for Depth of Field +// +// A simple orthographic camera. This camera type is loaded by passing +// the type string "orthographic" to ospNewCamera +// +// The functionality for a orthographic camera is implemented via the +// ospray::OrthographicCamera class. +struct OSPRAY_SDK_INTERFACE OrthographicCamera + : public AddStructShared { - /*! \brief constructor \internal also creates the ispc-side data structure */ OrthographicCamera(); ~OrthographicCamera() override = default; @@ -44,8 +32,9 @@ struct OSPRAY_SDK_INTERFACE OrthographicCamera : public Camera // Data members // - float height; // size of the camera's image plane in y, in world coordinates - float aspect; + float height{ + 1.f}; // size of the camera's image plane in y, in world coordinates + float aspect{1.f}; }; } // namespace ospray diff --git a/modules/cpu/camera/OrthographicCamera.ispc b/modules/cpu/camera/OrthographicCamera.ispc index 2b3ef84bf5..e6bf28f04c 100644 --- a/modules/cpu/camera/OrthographicCamera.ispc +++ b/modules/cpu/camera/OrthographicCamera.ispc @@ -1,22 +1,10 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Camera.ih" #include "common/MotionTransform.ih" - -struct OrthographicCamera -{ - Camera super; - - vec3f dir; - // below are essentially unions: 1. if no motionBlur; 2. if motionBlur - vec3f org; // lower left position of the camera image plane; - // origin of camera - vec3f du_size; // delta of ray origin between two pixels in x; - // sensor size (in x and y) - vec3f dv_up; // delta of ray origin between two pixels in y; - // up direction of camera -}; +// c++ shared +#include "OrthographicCameraShared.h" void OrthographicCamera_initRay(const Camera *uniform _self, varying Ray &ray, @@ -51,34 +39,11 @@ void OrthographicCamera_initRay(const Camera *uniform _self, setRay(ray, org, dir, self->super.nearClip, inf, time); } -export void *uniform OrthographicCamera_create() -{ - uniform OrthographicCamera *uniform cam = - uniform new uniform OrthographicCamera; - cam->super.initRay = OrthographicCamera_initRay; - return cam; -} +// Exports (called from C++) ////////////////////////////////////////////////// -export void OrthographicCamera_set(void *uniform _self, - const uniform vec3f &org, - const uniform vec3f &dir, - const uniform vec3f &up, - const uniform vec2f &size) +export void *uniform OrthographicCamera_initRay_addr() { - OrthographicCamera *uniform self = (OrthographicCamera * uniform) _self; - - if (self->super.motionBlur) { - self->dir = dir; - self->du_size = make_vec3f(size.x, size.y, 1.0f); - self->dv_up = up; - self->org = org; - } else { - self->dir = normalize(dir); - self->du_size = normalize(cross(self->dir, up)); - self->dv_up = cross(self->du_size, self->dir) * size.y; - self->du_size = self->du_size * size.x; - self->org = org - 0.5f * self->du_size - 0.5f * self->dv_up; // shift - } + return OrthographicCamera_initRay; } export void OrthographicCamera_projectBox( diff --git a/modules/cpu/camera/OrthographicCameraShared.h b/modules/cpu/camera/OrthographicCameraShared.h new file mode 100644 index 0000000000..9298469cf6 --- /dev/null +++ b/modules/cpu/camera/OrthographicCameraShared.h @@ -0,0 +1,31 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "CameraShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +struct OrthographicCamera +{ + Camera super; + + vec3f dir; + // below are essentially unions: 1. if no motionBlur; 2. if motionBlur + vec3f org; // lower left position of the camera image plane; + // origin of camera + vec3f du_size; // delta of ray origin between two pixels in x; + // sensor size (in x and y) + vec3f dv_up; // delta of ray origin between two pixels in y; + // up direction of camera + +#ifdef __cplusplus + OrthographicCamera() : dir(0.f), org(0.f), du_size(0.f), dv_up(0.f) {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/camera/PanoramicCamera.cpp b/modules/cpu/camera/PanoramicCamera.cpp index e007852fc3..3f3e79f916 100644 --- a/modules/cpu/camera/PanoramicCamera.cpp +++ b/modules/cpu/camera/PanoramicCamera.cpp @@ -1,14 +1,15 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "PanoramicCamera.h" +// ispc exports #include "camera/PanoramicCamera_ispc.h" namespace ospray { PanoramicCamera::PanoramicCamera() { - ispcEquivalent = ispc::PanoramicCamera_create(); + getSh()->super.initRay = ispc::PanoramicCamera_initRay_addr(); } std::string PanoramicCamera::toString() const @@ -20,13 +21,25 @@ void PanoramicCamera::commit() { Camera::commit(); - ispc::PanoramicCamera_set(getIE(), - (const ispc::vec3f &)pos, - (const ispc::vec3f &)dir, - (const ispc::vec3f &)up, - (OSPStereoMode)getParam( - "stereoMode", getParam("stereoMode", OSP_STEREO_NONE)), - getParam("interpupillaryDistance", 0.0635f)); + getSh()->org = pos; + + if (getSh()->super.motionBlur) { + getSh()->frame.vz = -dir; + getSh()->frame.vy = up; + } else { + getSh()->frame.vz = -normalize(dir); + getSh()->frame.vx = normalize(cross(up, getSh()->frame.vz)); + getSh()->frame.vy = cross(getSh()->frame.vz, getSh()->frame.vx); + } + + getSh()->stereoMode = (OSPStereoMode)getParam( + "stereoMode", getParam("stereoMode", OSP_STEREO_NONE)); + getSh()->ipd_offset = + 0.5f * getParam("interpupillaryDistance", 0.0635f); + + // flip offset to have left eye at top (image coord origin at lower left) + if (getSh()->stereoMode == OSP_STEREO_TOP_BOTTOM) + getSh()->ipd_offset = -getSh()->ipd_offset; } } // namespace ospray diff --git a/modules/cpu/camera/PanoramicCamera.h b/modules/cpu/camera/PanoramicCamera.h index df07cd0a46..2d1da6247e 100644 --- a/modules/cpu/camera/PanoramicCamera.h +++ b/modules/cpu/camera/PanoramicCamera.h @@ -1,14 +1,17 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "camera/Camera.h" +// ispc shared +#include "PanoramicCameraShared.h" namespace ospray { // Implements a panoramic camera with latitude/longitude mapping -struct OSPRAY_SDK_INTERFACE PanoramicCamera : public Camera +struct OSPRAY_SDK_INTERFACE PanoramicCamera + : public AddStructShared { PanoramicCamera(); virtual ~PanoramicCamera() override = default; diff --git a/modules/cpu/camera/PanoramicCamera.ispc b/modules/cpu/camera/PanoramicCamera.ispc index 97193f916a..bfadbedcf6 100644 --- a/modules/cpu/camera/PanoramicCamera.ispc +++ b/modules/cpu/camera/PanoramicCamera.ispc @@ -1,20 +1,12 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Camera.ih" #include "common/MotionTransform.ih" #include "math/sampling.ih" #include "ospray/OSPEnums.h" - -struct PanoramicCamera -{ - Camera super; - - vec3f org; - linear3f frame; // union: precomputed frame; or (xxx, up, -dir) if motion blur - int stereoMode; - float ipd_offset; // half of the interpupillary distance -}; +// c++ shared +#include "PanoramicCameraShared.h" void PanoramicCamera_initRay(const Camera *uniform _self, varying Ray &ray, @@ -80,38 +72,9 @@ void PanoramicCamera_initRay(const Camera *uniform _self, setRay(ray, org, dir, self->super.nearClip, inf, time); } -export void *uniform PanoramicCamera_create() -{ - PanoramicCamera *uniform self = uniform new PanoramicCamera; - self->super.initRay = PanoramicCamera_initRay; - self->stereoMode = OSP_STEREO_NONE; - self->ipd_offset = 0.f; - return self; -} +// Exports (called from C++) ////////////////////////////////////////////////// -export void PanoramicCamera_set(void *uniform _self, - const uniform vec3f &org, - const uniform vec3f &dir, - const uniform vec3f &up, - const uniform int stereoMode, - const uniform float ipd) +export void *uniform PanoramicCamera_initRay_addr() { - PanoramicCamera *uniform self = (PanoramicCamera * uniform) _self; - - self->org = org; - - if (self->super.motionBlur) { - self->frame.vz = neg(dir); - self->frame.vy = up; - } else { - self->frame.vz = neg(normalize(dir)); - self->frame.vx = normalize(cross(up, self->frame.vz)); - self->frame.vy = cross(self->frame.vz, self->frame.vx); - } - - self->stereoMode = stereoMode; - self->ipd_offset = 0.5f * ipd; - // flip offset to have left eye at top (image coord origin at lower left) - if (stereoMode == OSP_STEREO_TOP_BOTTOM) - self->ipd_offset = -self->ipd_offset; + return PanoramicCamera_initRay; } diff --git a/modules/cpu/camera/PanoramicCameraShared.h b/modules/cpu/camera/PanoramicCameraShared.h new file mode 100644 index 0000000000..bcc5593707 --- /dev/null +++ b/modules/cpu/camera/PanoramicCameraShared.h @@ -0,0 +1,29 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "CameraShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +struct PanoramicCamera +{ + Camera super; + + vec3f org; + linear3f frame; // union: precomputed frame; or (xxx, up, -dir) if motion blur + int stereoMode; + float ipd_offset; // half of the interpupillary distance + +#ifdef __cplusplus + PanoramicCamera() + : org(0.f), frame(one), stereoMode(OSP_STEREO_NONE), ipd_offset(0.f) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/camera/PerspectiveCamera.cpp b/modules/cpu/camera/PerspectiveCamera.cpp index f2c0973056..3b29ba898c 100644 --- a/modules/cpu/camera/PerspectiveCamera.cpp +++ b/modules/cpu/camera/PerspectiveCamera.cpp @@ -1,14 +1,15 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "PerspectiveCamera.h" +// ispc exports #include "camera/PerspectiveCamera_ispc.h" namespace ospray { PerspectiveCamera::PerspectiveCamera() { - ispcEquivalent = ispc::PerspectiveCamera_create(); + getSh()->super.initRay = ispc::PerspectiveCamera_initRay_addr(); } std::string PerspectiveCamera::toString() const @@ -45,17 +46,60 @@ void PerspectiveCamera::commit() imgPlaneSize.y = 2.f * tanf(deg2rad(0.5f * fovy)); imgPlaneSize.x = imgPlaneSize.y * aspect; - ispc::PerspectiveCamera_set(getIE(), - (const ispc::vec3f &)pos, - (const ispc::vec3f &)dir, - (const ispc::vec3f &)up, - (const ispc::vec2f &)imgPlaneSize, - apertureRadius / (imgPlaneSize.x * focusDistance), - focusDistance, - aspect, - architectural, - stereoMode, - interpupillaryDistance); + // Set shared structure members + { + getSh()->scaledAperture = apertureRadius / (imgPlaneSize.x * focusDistance); + getSh()->aspect = aspect; + getSh()->stereoMode = stereoMode; + getSh()->dir_00 = normalize(dir); + getSh()->org = pos; + getSh()->imgPlaneSize = imgPlaneSize; + + if (getSh()->super.motionBlur) { + getSh()->super.initRay = ispc::PerspectiveCamera_initRayMB_addr(); + getSh()->du_size = vec3f(imgPlaneSize.x, imgPlaneSize.y, architectural); + getSh()->dv_up = up; + getSh()->ipd_offset = + vec3f(0.5f * interpupillaryDistance, focusDistance, 0.0f); + } else { + getSh()->super.initRay = ispc::PerspectiveCamera_initRay_addr(); + getSh()->du_size = normalize(cross(getSh()->dir_00, up)); + if (architectural) // orient film to be parallel to 'up' + getSh()->dv_up = normalize(up); + else // rotate film to be perpendicular to 'dir' + getSh()->dv_up = cross(getSh()->du_size, getSh()->dir_00); + + getSh()->ipd_offset = 0.5f * interpupillaryDistance * getSh()->du_size; + + switch (stereoMode) { + case OSP_STEREO_LEFT: + getSh()->org = getSh()->org - getSh()->ipd_offset; + break; + case OSP_STEREO_RIGHT: + getSh()->org = getSh()->org + getSh()->ipd_offset; + break; + case OSP_STEREO_TOP_BOTTOM: + // flip offset to have left eye at top (image coord origin at lower + // left) + getSh()->ipd_offset = -getSh()->ipd_offset; + break; + default: + break; + } + + getSh()->du_size = getSh()->du_size * imgPlaneSize.x; + getSh()->dv_up = getSh()->dv_up * imgPlaneSize.y; + getSh()->dir_00 = + getSh()->dir_00 - 0.5f * getSh()->du_size - 0.5f * getSh()->dv_up; + + // prescale to focal plane + if (getSh()->scaledAperture > 0.f) { + getSh()->du_size = getSh()->du_size * focusDistance; + getSh()->dv_up = getSh()->dv_up * focusDistance; + getSh()->dir_00 = getSh()->dir_00 * focusDistance; + } + } + } } box3f PerspectiveCamera::projectBox(const box3f &b) const @@ -65,7 +109,7 @@ box3f PerspectiveCamera::projectBox(const box3f &b) const } box3f projection; ispc::PerspectiveCamera_projectBox( - getIE(), (const ispc::box3f &)b, (ispc::box3f &)projection); + getSh(), (const ispc::box3f &)b, (ispc::box3f &)projection); return projection; } diff --git a/modules/cpu/camera/PerspectiveCamera.h b/modules/cpu/camera/PerspectiveCamera.h index bcb71ca0b2..ecf76a1576 100644 --- a/modules/cpu/camera/PerspectiveCamera.h +++ b/modules/cpu/camera/PerspectiveCamera.h @@ -1,14 +1,17 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "camera/Camera.h" #include "rkcommon/math/box.h" +// ispc shared +#include "PerspectiveCameraShared.h" namespace ospray { -struct OSPRAY_SDK_INTERFACE PerspectiveCamera : public Camera +struct OSPRAY_SDK_INTERFACE PerspectiveCamera + : public AddStructShared { PerspectiveCamera(); virtual ~PerspectiveCamera() override = default; @@ -20,15 +23,15 @@ struct OSPRAY_SDK_INTERFACE PerspectiveCamera : public Camera // Data members // - float fovy; - float aspect; - float apertureRadius; - float focusDistance; - bool architectural; // orient image plane to be parallel to 'up' and shift the - // lens - - OSPStereoMode stereoMode; - float interpupillaryDistance; // distance between the two cameras (stereo) + float fovy{60.f}; + float aspect{1.f}; + float apertureRadius{0.f}; + float focusDistance{1.f}; + bool architectural{false}; // orient image plane to be parallel to 'up' and + // shift the lens + OSPStereoMode stereoMode{OSP_STEREO_NONE}; + float interpupillaryDistance{ + 0.0635f}; // distance between the two cameras (stereo) }; } // namespace ospray diff --git a/modules/cpu/camera/PerspectiveCamera.ispc b/modules/cpu/camera/PerspectiveCamera.ispc index 2dc848fa2d..962339cd2a 100644 --- a/modules/cpu/camera/PerspectiveCamera.ispc +++ b/modules/cpu/camera/PerspectiveCamera.ispc @@ -1,34 +1,12 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Camera.ih" #include "common/MotionTransform.ih" #include "math/sampling.ih" #include "ospray/OSPEnums.h" - -struct PerspectiveCamera -{ - Camera super; - - vec3f org; // position of camera, already contains shift when - // STEREO_{LEFT|RIGHT} - vec3f dir_00; // direction of ray with screenSample=(0,0); scaled to - // focusDistance if no motionBlur - // below are essentially unions: 1. if no motionBlur; 2. if motionBlur - vec3f du_size; // delta of ray direction between two pixels in x, scaled to - // focusDistance; sensor size (in x and y) and architectural - vec3f dv_up; // delta of ray direction between two pixels in y, scaled to - // focusDistance; up direction of camera - 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 - int stereoMode; -}; +// c++ shared +#include "PerspectiveCameraShared.h" void PerspectiveCamera_initRay(const Camera *uniform _self, varying Ray &ray, @@ -142,76 +120,16 @@ void PerspectiveCamera_initRayMB(const Camera *uniform _self, setRay(ray, org, normalize(dir), self->super.nearClip, inf, time); } -export void *uniform PerspectiveCamera_create() +// Exports (called from C++) ////////////////////////////////////////////////// + +export void *uniform PerspectiveCamera_initRay_addr() { - uniform PerspectiveCamera *uniform self = - uniform new uniform PerspectiveCamera; - self->super.initRay = PerspectiveCamera_initRay; - return self; + return PerspectiveCamera_initRay; } -export void PerspectiveCamera_set(void *uniform _self, - const uniform vec3f &org, - const uniform vec3f &dir, - const uniform vec3f &up, - const uniform vec2f &imgPlaneSize, - const uniform float scaledAperture, - const uniform float focusDistance, - const uniform float aspect, - const uniform bool architectural, - const uniform int stereoMode, - const uniform float ipd) +export void *uniform PerspectiveCamera_initRayMB_addr() { - PerspectiveCamera *uniform self = (PerspectiveCamera * uniform) _self; - - self->scaledAperture = scaledAperture; - self->aspect = aspect; - self->stereoMode = stereoMode; - self->dir_00 = normalize(dir); - self->org = org; - self->imgPlaneSize = imgPlaneSize; - - if (self->super.motionBlur) { - self->super.initRay = PerspectiveCamera_initRayMB; - self->du_size = make_vec3f(imgPlaneSize.x, imgPlaneSize.y, architectural); - self->dv_up = up; - self->ipd_offset = make_vec3f(0.5f * ipd, focusDistance, 0.0f); - } else { - self->super.initRay = PerspectiveCamera_initRay; - self->du_size = normalize(cross(self->dir_00, up)); - if (architectural) // orient film to be parallel to 'up' - self->dv_up = normalize(up); - else // rotate film to be perpendicular to 'dir' - self->dv_up = cross(self->du_size, self->dir_00); - - self->ipd_offset = 0.5f * ipd * self->du_size; - - switch (stereoMode) { - case OSP_STEREO_LEFT: - self->org = self->org - self->ipd_offset; - break; - case OSP_STEREO_RIGHT: - self->org = self->org + self->ipd_offset; - break; - case OSP_STEREO_TOP_BOTTOM: - // flip offset to have left eye at top (image coord origin at lower left) - self->ipd_offset = neg(self->ipd_offset); - break; - default: - break; - } - - self->du_size = self->du_size * imgPlaneSize.x; - self->dv_up = self->dv_up * imgPlaneSize.y; - self->dir_00 = self->dir_00 - 0.5f * self->du_size - 0.5f * self->dv_up; - - // prescale to focal plane - if (scaledAperture > 0.f) { - self->du_size = self->du_size * focusDistance; - self->dv_up = self->dv_up * focusDistance; - self->dir_00 = self->dir_00 * focusDistance; - } - } + return PerspectiveCamera_initRayMB; } export void PerspectiveCamera_projectBox( diff --git a/modules/cpu/camera/PerspectiveCameraShared.h b/modules/cpu/camera/PerspectiveCameraShared.h new file mode 100644 index 0000000000..24c8c485d0 --- /dev/null +++ b/modules/cpu/camera/PerspectiveCameraShared.h @@ -0,0 +1,51 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "CameraShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +struct PerspectiveCamera +{ + Camera super; + + vec3f org; // position of camera, already contains shift when + // STEREO_{LEFT|RIGHT} + vec3f dir_00; // direction of ray with screenSample=(0,0); scaled to + // focusDistance if no motionBlur + // below are essentially unions: 1. if no motionBlur; 2. if motionBlur + vec3f du_size; // delta of ray direction between two pixels in x, scaled to + // focusDistance; sensor size (in x and y) and architectural + vec3f dv_up; // delta of ray direction between two pixels in y, scaled to + // focusDistance; up direction of camera + 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 + int stereoMode; + +#ifdef __cplusplus + PerspectiveCamera() + : org(0.f), + dir_00(0.f), + du_size(0.f), + dv_up(0.f), + ipd_offset(0.f), + imgPlaneSize(0.f), + scaledAperture(0.f), + aspect(1.f), + stereoMode(OSP_STEREO_NONE) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/common/Clipping.ih b/modules/cpu/common/Clipping.ih index 19ce506cd0..471d1c1e54 100644 --- a/modules/cpu/common/Clipping.ih +++ b/modules/cpu/common/Clipping.ih @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Intel Corporation +// Copyright 2019 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/common/DGEnum.h b/modules/cpu/common/DGEnum.h new file mode 100644 index 0000000000..37389009c3 --- /dev/null +++ b/modules/cpu/common/DGEnum.h @@ -0,0 +1,25 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef __cplusplus +namespace ospray { +#endif // __cplusplus + +typedef enum +{ + DG_FACEFORWARD = (1 << 0), // face-forward normals + DG_NORMALIZE = (1 << 1), // normalize normals + DG_NG = (1 << 2), // need geometry normal Ng + DG_NS = (1 << 3), // need shading normal Ns + DG_COLOR = (1 << 5), // hack for now - need interpolated vertex color + DG_TEXCOORD = (1 << 6), // calculate texture coords st + DG_TANGENTS = (1 << 7), // calculate tangents, i.e. the partial derivatives of + // position wrt. texture coordinates + DG_MOTIONBLUR = (1 << 8), // calculate interpolated transformations for MB +} DG_PostIntersectFlags; + +#ifdef __cplusplus +} // namespace ospray +#endif // __cplusplus \ No newline at end of file diff --git a/modules/cpu/common/Data.cpp b/modules/cpu/common/Data.cpp index 0f0c3705bd..5e294cd019 100644 --- a/modules/cpu/common/Data.cpp +++ b/modules/cpu/common/Data.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray diff --git a/modules/cpu/common/Data.h b/modules/cpu/common/Data.h index a15e552ed3..b32d3d1bef 100644 --- a/modules/cpu/common/Data.h +++ b/modules/cpu/common/Data.h @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -349,24 +349,10 @@ inline const Ref> ManagedObject::getParamDataT( } } -template -inline typename std::enable_if::value, - std::vector>::type -createArrayOfIE(const DataT &data) -{ - std::vector retval; - retval.reserve(data.size()); - - for (auto &&obj : data) - retval.push_back(obj->getIE()); - - return retval; -} - -template -std::vector createArrayOfSh(const DataT &data) +template +std::vector createArrayOfSh(const DataT &data) { - std::vector retval; + std::vector retval; retval.reserve(data.size()); for (auto &&obj : data) diff --git a/modules/cpu/common/Data.ih b/modules/cpu/common/Data.ih index 0ec9dd7675..49a2bd000b 100644 --- a/modules/cpu/common/Data.ih +++ b/modules/cpu/common/Data.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/common/DifferentialGeometry.ih b/modules/cpu/common/DifferentialGeometry.ih index 35dc07b77e..6684bd1a3b 100644 --- a/modules/cpu/common/DifferentialGeometry.ih +++ b/modules/cpu/common/DifferentialGeometry.ih @@ -1,27 +1,13 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#include "DGEnum.h" #include "rkcommon/math/vec.ih" -struct Geometry; struct Material; struct Renderer; -struct World; - -typedef enum -{ - DG_FACEFORWARD = (1 << 0), // face-forward normals - DG_NORMALIZE = (1 << 1), // normalize normals - DG_NG = (1 << 2), // need geometry normal Ng - DG_NS = (1 << 3), // need shading normal Ns - DG_COLOR = (1 << 5), // hack for now - need interpolated vertex color - DG_TEXCOORD = (1 << 6), // calculate texture coords st - DG_TANGENTS = (1 << 7), // calculate tangents, i.e. the partial derivatives of - // position wrt. texture coordinates - DG_MOTIONBLUR = (1 << 8), // calculate interpolated transformations for MB -} DG_PostIntersectFlags; /* differential geometry information that gives more detailed information on the actual geometry that a ray has hit */ @@ -48,6 +34,8 @@ struct DifferentialGeometry Material *material; // pointer to hit-point's material const Renderer *uniform renderer; // pointer to renderer being used + unsigned int objID; // user definable model id (0xffff none) + unsigned int instID; // user definable instance id (0xffff none) }; // assumed precision of intersection routines diff --git a/modules/cpu/common/FilterIntersect.ih b/modules/cpu/common/FilterIntersect.ih index 42dbf8e14f..a5c601cf81 100644 --- a/modules/cpu/common/FilterIntersect.ih +++ b/modules/cpu/common/FilterIntersect.ih @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Intel Corporation +// Copyright 2019 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/common/Future.cpp b/modules/cpu/common/Future.cpp index 87379521d1..b2658fa0db 100644 --- a/modules/cpu/common/Future.cpp +++ b/modules/cpu/common/Future.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Future.h" diff --git a/modules/cpu/common/Future.h b/modules/cpu/common/Future.h index b2052b9b07..5918f594ec 100644 --- a/modules/cpu/common/Future.h +++ b/modules/cpu/common/Future.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/common/Group.cpp b/modules/cpu/common/Group.cpp index fe90bb5b48..59a7f6d510 100644 --- a/modules/cpu/common/Group.cpp +++ b/modules/cpu/common/Group.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray @@ -6,31 +6,17 @@ #include "geometry/GeometricModel.h" #include "lights/Light.h" #include "volume/VolumetricModel.h" -// ispc exports -#include "common/Group_ispc.h" namespace ospray { // Embree helper functions ////////////////////////////////////////////////// +template inline void createEmbreeScene( - RTCScene &scene, const DataT &objects, int embreeFlags) + RTCScene &scene, const DataT &objects, int embreeFlags) { - for (auto &&obj : objects) { - Geometry &geom = obj->geometry(); - rtcAttachGeometry(scene, geom.embreeGeometry); - } - - rtcSetSceneFlags(scene, static_cast(embreeFlags)); -} - -inline void createEmbreeScene( - RTCScene &scene, const DataT &objects, int embreeFlags) -{ - for (auto &&obj : objects) { - auto geomID = rtcAttachGeometry(scene, obj->embreeGeometryHandle()); - obj->setGeomID(geomID); - } + for (auto &&obj : objects) + rtcAttachGeometry(scene, obj->embreeGeometryHandle()); rtcSetSceneFlags(scene, static_cast(embreeFlags)); } @@ -48,7 +34,6 @@ static void freeAndNullifyEmbreeScene(RTCScene &scene) Group::Group() { managedObjectType = OSP_GROUP; - this->ispcEquivalent = ispc::Group_create(); } Group::~Group() @@ -56,6 +41,13 @@ Group::~Group() freeAndNullifyEmbreeScene(sceneGeometries); freeAndNullifyEmbreeScene(sceneVolumes); freeAndNullifyEmbreeScene(sceneClippers); + + BufferSharedDelete(getSh()->geometricModels); + BufferSharedDelete(getSh()->volumetricModels); + BufferSharedDelete(getSh()->clipModels); + getSh()->geometricModels = nullptr; + getSh()->volumetricModels = nullptr; + getSh()->clipModels = nullptr; } std::string Group::toString() const @@ -93,9 +85,12 @@ void Group::commit() freeAndNullifyEmbreeScene(sceneVolumes); freeAndNullifyEmbreeScene(sceneClippers); - geometricModelIEs.clear(); - volumetricModelIEs.clear(); - clipModelIEs.clear(); + BufferSharedDelete(getSh()->geometricModels); + BufferSharedDelete(getSh()->volumetricModels); + BufferSharedDelete(getSh()->clipModels); + getSh()->geometricModels = nullptr; + getSh()->volumetricModels = nullptr; + getSh()->clipModels = nullptr; if (!embreeDevice) { throw std::runtime_error("invalid Embree device"); @@ -105,7 +100,9 @@ void Group::commit() sceneGeometries = rtcNewScene(embreeDevice); createEmbreeScene(sceneGeometries, *geometricModels, sceneFlags); - geometricModelIEs = createArrayOfIE(*geometricModels); + getSh()->geometricModels = + BufferSharedCreate(numGeometries, + createArrayOfSh(*geometricModels).data()); rtcCommitScene(sceneGeometries); } @@ -114,7 +111,9 @@ void Group::commit() sceneVolumes = rtcNewScene(embreeDevice); createEmbreeScene(sceneVolumes, *volumetricModels, sceneFlags); - volumetricModelIEs = createArrayOfSh(*volumetricModels); + getSh()->volumetricModels = + BufferSharedCreate(numVolumes, + createArrayOfSh(*volumetricModels).data()); rtcCommitScene(sceneVolumes); } @@ -126,7 +125,8 @@ void Group::commit() *clipModels, sceneFlags | RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION | RTC_SCENE_FLAG_ROBUST); - clipModelIEs = createArrayOfIE(*clipModels); + getSh()->clipModels = BufferSharedCreate( + numClippers, createArrayOfSh(*clipModels).data()); numInvertedClippers = 0; for (auto &&obj : *clipModels) @@ -135,6 +135,10 @@ void Group::commit() rtcCommitScene(sceneClippers); } + getSh()->numGeometricModels = numGeometries; + getSh()->numVolumetricModels = numVolumes; + getSh()->numClipModels = numClippers; + // Create empty scene for lights-only group, // it is needed to have rtcGeometry created in Instance object // which in turn is needed for motion blur matrices interpolation @@ -143,14 +147,6 @@ void Group::commit() sceneGeometries = rtcNewScene(embreeDevice); rtcCommitScene(sceneGeometries); } - - ispc::Group_set(getIE(), - geometricModels ? geometricModelIEs.data() : nullptr, - numGeometries, - volumetricModels ? volumetricModelIEs.data() : nullptr, - numVolumes, - clipModels ? clipModelIEs.data() : nullptr, - numClippers); } box3f Group::getBounds() const diff --git a/modules/cpu/common/Group.h b/modules/cpu/common/Group.h index ff2e05504c..a9138b604f 100644 --- a/modules/cpu/common/Group.h +++ b/modules/cpu/common/Group.h @@ -1,15 +1,17 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray stuff -#include "./Data.h" -#include "./Managed.h" +#include "Data.h" +#include "Managed.h" // stl #include // embree #include "embree3/rtcore.h" +// ispc shared +#include "GroupShared.h" namespace ospray { @@ -17,7 +19,8 @@ struct GeometricModel; struct VolumetricModel; struct Light; -struct OSPRAY_SDK_INTERFACE Group : public ManagedObject +struct OSPRAY_SDK_INTERFACE Group + : public AddStructShared { Group(); ~Group() override; @@ -30,13 +33,8 @@ struct OSPRAY_SDK_INTERFACE Group : public ManagedObject // Data members // Ref> geometricModels; - std::vector geometricModelIEs; - Ref> volumetricModels; - std::vector volumetricModelIEs; - Ref> clipModels; - std::vector clipModelIEs; int numInvertedClippers{0}; Ref> lights; diff --git a/modules/cpu/common/Group.ih b/modules/cpu/common/Group.ih deleted file mode 100644 index 4d4e31b223..0000000000 --- a/modules/cpu/common/Group.ih +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2009-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -// ospray stuff -#include "../geometry/GeometricModel.ih" -#include "../volume/VolumetricModel.ih" -#include "Ray.ih" - -struct Group -{ - GeometricModel **geometricModels; - int32 numGeometricModels; - - VolumetricModel **volumetricModels; - int32 numVolumetricModels; - - GeometricModel **clipModels; - int32 numClipModels; -}; diff --git a/modules/cpu/common/Group.ispc b/modules/cpu/common/Group.ispc deleted file mode 100644 index ace089b70a..0000000000 --- a/modules/cpu/common/Group.ispc +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2009-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#include "Group.ih" - -export void *uniform Group_create() -{ - Group *uniform group = uniform new Group; - - group->geometricModels = NULL; - group->numGeometricModels = 0; - - group->volumetricModels = NULL; - group->numVolumetricModels = 0; - - group->clipModels = NULL; - group->numClipModels = 0; - - return (void *uniform)group; -} - -export void Group_set(void *uniform _group, - void *uniform _geomModels, - uniform int32 numGeomModels, - void *uniform _volModels, - uniform int32 numVolModels, - void *uniform _clipModels, - uniform int32 numClipModels) -{ - Group *uniform group = (Group * uniform) _group; - - group->geometricModels = (GeometricModel * *uniform) _geomModels; - group->numGeometricModels = numGeomModels; - - group->volumetricModels = (VolumetricModel * *uniform) _volModels; - group->numVolumetricModels = numVolModels; - - group->clipModels = (GeometricModel * *uniform) _clipModels; - group->numClipModels = numClipModels; -} diff --git a/modules/cpu/common/GroupShared.h b/modules/cpu/common/GroupShared.h new file mode 100644 index 0000000000..720681d071 --- /dev/null +++ b/modules/cpu/common/GroupShared.h @@ -0,0 +1,38 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef __cplusplus +#include "common/StructShared.h" +namespace ispc { +#endif // __cplusplus + +struct GeometricModel; +struct VolumetricModel; + +struct Group +{ + GeometricModel **geometricModels; + int32 numGeometricModels; + + VolumetricModel **volumetricModels; + int32 numVolumetricModels; + + GeometricModel **clipModels; + int32 numClipModels; + +#ifdef __cplusplus + Group() + : geometricModels(nullptr), + numGeometricModels(0), + volumetricModels(nullptr), + numVolumetricModels(0), + clipModels(nullptr), + numClipModels(0) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/common/Instance.cpp b/modules/cpu/common/Instance.cpp index 679109e4a9..751a47a128 100644 --- a/modules/cpu/common/Instance.cpp +++ b/modules/cpu/common/Instance.cpp @@ -1,20 +1,14 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Instance.h" -#include "Data.h" -// ispc exports -#include "common/Instance_ispc.h" -#include "common/OSPCommon_ispc.h" -#include "geometry/Geometry_ispc.h" namespace ospray { Instance::Instance(Group *_group) : groupAPI(_group) { managedObjectType = OSP_INSTANCE; - this->ispcEquivalent = ispc::Instance_create(); } std::string Instance::toString() const @@ -30,10 +24,12 @@ void Instance::commit() motionTransform.readParams(*this); - ispc::Instance_set(getIE(), - group->getIE(), - (ispc::AffineSpace3f &)motionTransform.transform[0], - motionTransform.motionBlur); + // Initialize shared structure + getSh()->group = group->getSh(); + getSh()->xfm = motionTransform.transform; + getSh()->rcp_xfm = rcp(getSh()->xfm); + getSh()->motionBlur = motionTransform.motionBlur; + getSh()->userID = getParam("id", RTC_INVALID_GEOMETRY_ID); } box3f Instance::getBounds() const @@ -54,6 +50,19 @@ box3f Instance::getBounds() const return bounds; } +void Instance::setEmbreeGeom(RTCGeometry geom) +{ + motionTransform.setEmbreeTransform(geom); + getSh()->geom = geom; + if (getSh()->motionBlur) { + rtcGetGeometryTransform(geom, + .5f, + RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR, + &getSh()->xfm); // for SciVis + getSh()->rcp_xfm = rcp(getSh()->xfm); + } +} + OSPTYPEFOR_DEFINITION(Instance *); } // namespace ospray diff --git a/modules/cpu/common/Instance.h b/modules/cpu/common/Instance.h index 2d12a13c9c..74f55da274 100644 --- a/modules/cpu/common/Instance.h +++ b/modules/cpu/common/Instance.h @@ -1,17 +1,20 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray stuff -#include "./Group.h" -#include "./MotionTransform.h" +#include "Group.h" +#include "MotionTransform.h" // embree #include "embree3/rtcore.h" +// ispc shared +#include "InstanceShared.h" namespace ospray { -struct OSPRAY_SDK_INTERFACE Instance : public ManagedObject +struct OSPRAY_SDK_INTERFACE Instance + : public AddStructShared { Instance(Group *group); ~Instance() override = default; @@ -22,6 +25,8 @@ struct OSPRAY_SDK_INTERFACE Instance : public ManagedObject box3f getBounds() const override; + void setEmbreeGeom(RTCGeometry geom); + Ref group; const Ref groupAPI; MotionTransform motionTransform; diff --git a/modules/cpu/common/Instance.ih b/modules/cpu/common/Instance.ih index bb3d49ea33..5de372d387 100644 --- a/modules/cpu/common/Instance.ih +++ b/modules/cpu/common/Instance.ih @@ -1,27 +1,19 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray stuff -#include "Group.ih" +#include "../geometry/GeometricModel.ih" +#include "DifferentialGeometry.ih" #include "MotionTransform.ih" #include "Ray.ih" +// c++ shared +#include "GroupShared.h" +#include "InstanceShared.h" struct Renderer; -struct Instance -{ - Group *group; - RTCGeometry geom; // only to access rtcGetGeometryTransform - - AffineSpace3f xfm; - AffineSpace3f rcp_xfm; - bool motionBlur; -}; -typedef Instance *uniform InstancePtr; -typedef InstancePtr *uniform InstanceArray; - inline uniform AffineSpace3f Instance_getTransform( const Instance *uniform self, const uniform float time) { @@ -46,6 +38,9 @@ inline void Instance_postIntersect(const Instance *uniform self, foreach_unique (geomID in ray.geomID) GeometricModel_postIntersect(*(models + geomID), renderer, dg, ray, flags); + dg.instID = + (self->userID == RTC_INVALID_GEOMETRY_ID) ? ray.instID : self->userID; + uniform AffineSpace3f uxfm = self->xfm; uniform AffineSpace3f rcp_uxfm = self->rcp_xfm; diff --git a/modules/cpu/common/Instance.ispc b/modules/cpu/common/Instance.ispc deleted file mode 100644 index d5c870f063..0000000000 --- a/modules/cpu/common/Instance.ispc +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2009-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#include "Instance.ih" - -export void *uniform Instance_create() -{ - Instance *uniform inst = uniform new Instance; - - inst->group = NULL; - - return (void *uniform)inst; -} - -export void Instance_set(void *uniform _inst, - void *uniform _group, - const uniform AffineSpace3f &xfm, - const uniform bool motionBlur) -{ - Instance *uniform inst = (Instance * uniform) _inst; - - inst->group = (Group * uniform) _group; - - inst->xfm = xfm; - inst->rcp_xfm = rcp(xfm); - inst->motionBlur = motionBlur; -} - -export void Instance_set_embreeGeom(void *uniform _inst, RTCGeometry geom) -{ - Instance *uniform inst = (Instance * uniform) _inst; - inst->geom = geom; - if (inst->motionBlur) { - inst->xfm = Instance_getTransform(inst, 0.5f); // for SciVis - inst->rcp_xfm = rcp(inst->xfm); - } -} diff --git a/modules/cpu/common/InstanceShared.h b/modules/cpu/common/InstanceShared.h new file mode 100644 index 0000000000..7f2f9c9ee7 --- /dev/null +++ b/modules/cpu/common/InstanceShared.h @@ -0,0 +1,32 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef __cplusplus +#include "common/StructShared.h" +namespace ispc { +#endif // __cplusplus + +struct Group; + +struct Instance +{ + Group *group; + RTCGeometry geom; // only to access rtcGetGeometryTransform + + AffineSpace3f xfm; + AffineSpace3f rcp_xfm; + bool motionBlur; + // user defined id. Typically used for picking + uint32 userID; + +#ifdef __cplusplus + Instance() + : group(nullptr), geom(nullptr), xfm(one), rcp_xfm(one), motionBlur(false) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/common/Intersect.ih b/modules/cpu/common/Intersect.ih index 353975bd10..030830cd2e 100644 --- a/modules/cpu/common/Intersect.ih +++ b/modules/cpu/common/Intersect.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/common/Managed.cpp b/modules/cpu/common/Managed.cpp index 6f8e538b4e..42094b5a3d 100644 --- a/modules/cpu/common/Managed.cpp +++ b/modules/cpu/common/Managed.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Managed.h" @@ -9,9 +9,6 @@ namespace ospray { ManagedObject::~ManagedObject() { - ispc::delete_uniform(ispcEquivalent); - ispcEquivalent = nullptr; - std::for_each(params_begin(), params_end(), [&](std::shared_ptr &p) { auto ¶m = *p; if (param.data.is()) { diff --git a/modules/cpu/common/Managed.h b/modules/cpu/common/Managed.h index a910d8f8f1..98109aaf69 100644 --- a/modules/cpu/common/Managed.h +++ b/modules/cpu/common/Managed.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -31,8 +31,6 @@ struct OSPRAY_SDK_INTERFACE ManagedObject : public memory::RefCount, virtual std::string toString() const; - void *getIE() const; - template T getParam(const char *name, T valIfNotFound = T()); @@ -52,7 +50,6 @@ struct OSPRAY_SDK_INTERFACE ManagedObject : public memory::RefCount, // Data members // - void *ispcEquivalent{nullptr}; OSPDataType managedObjectType{OSP_OBJECT}; private: @@ -64,11 +61,6 @@ OSPTYPEFOR_SPECIALIZATION(ManagedObject *, OSP_OBJECT); // Inlined ManagedObject definitions //////////////////////////////////////// -inline void *ManagedObject::getIE() const -{ - return ispcEquivalent; -} - template inline T ManagedObject::getParam(const char *name, T valIfNotFound) { diff --git a/modules/cpu/common/OSPCommon.ih b/modules/cpu/common/OSPCommon.ih index 0d2f76acad..40de860873 100644 --- a/modules/cpu/common/OSPCommon.ih +++ b/modules/cpu/common/OSPCommon.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/common/OSPCommon.ispc b/modules/cpu/common/OSPCommon.ispc index c0a97501ab..24d6df0db1 100644 --- a/modules/cpu/common/OSPCommon.ispc +++ b/modules/cpu/common/OSPCommon.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "OSPCommon.ih" diff --git a/modules/cpu/common/OSPConfig.h.in b/modules/cpu/common/OSPConfig.h.in index a4f19d81b1..6b3981ef2b 100644 --- a/modules/cpu/common/OSPConfig.h.in +++ b/modules/cpu/common/OSPConfig.h.in @@ -1,13 +1,9 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #define TILE_SIZE @OSPRAY_TILE_SIZE@ #define MAX_TILE_SIZE @OSPRAY_MAX_STACK_TILE_SIZE@ +#define OSPRAY_RENDER_TASK_SIZE @OSPRAY_RENDER_TASK_SIZE@ -/*! number of pixels that each job in a parallel rendertile task - executes together. Must be a multipel of the maximum possible - programCount (16), and must be smaller than TILE_SIZE (in one - dimension) */ -#define RENDERTILE_PIXELS_PER_JOB @OSPRAY_PIXELS_PER_JOB@ diff --git a/modules/cpu/common/Ray.ih b/modules/cpu/common/Ray.ih index fe9342186a..7ffc866616 100644 --- a/modules/cpu/common/Ray.ih +++ b/modules/cpu/common/Ray.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -69,9 +69,9 @@ inline void setRay(Ray &ray, ray.t = t1; ray.time = time; ray.mask = -1; - ray.geomID = -1; - ray.primID = -1; - ray.instID = -1; + ray.geomID = RTC_INVALID_GEOMETRY_ID; + ray.primID = RTC_INVALID_GEOMETRY_ID; + ray.instID = RTC_INVALID_GEOMETRY_ID; } inline void setRay(Ray &ray, diff --git a/modules/cpu/common/StructShared.h b/modules/cpu/common/StructShared.h index 7293bb6cd5..9046bb0d62 100644 --- a/modules/cpu/common/StructShared.h +++ b/modules/cpu/common/StructShared.h @@ -4,8 +4,22 @@ #pragma once #include +#include #include +namespace ispc { + +// Shared structure members may use types from rkcommon +using namespace rkcommon; +using namespace rkcommon::math; + +// Shared structure members may use ispc specific types +using uint8 = uint8_t; +using int32 = int32_t; +using uint32 = uint32_t; +using int64 = int64_t; +} // namespace ispc + namespace ospray { /* @@ -21,6 +35,31 @@ namespace ospray { the same). */ +inline void *BufferSharedCreate(size_t size) +{ + return malloc(size); +} + +inline void BufferSharedDelete(void *ptr) +{ + free(ptr); +} + +template +T *BufferSharedCreate(size_t count, const T *data) +{ + T *ptr = (T *)BufferSharedCreate(sizeof(T) * count); + if (data) + memcpy(ptr, data, sizeof(T) * count); + return ptr; +} + +template +inline T *StructSharedCreate() +{ + return new (BufferSharedCreate(sizeof(T))) T; +} + struct StructSharedPtr { ~StructSharedPtr(); @@ -91,8 +130,12 @@ struct AddStructShared std::is_same::type, typename get_super_or::type>::value, "StructShared_t needs to have 'super' member of type Base::StructShared_t"); - AddStructShared() - : StructSharedGet>(&structSharedPtr) + + template + AddStructShared(Args... args) + : StructSharedGet>( + &structSharedPtr), + Base(args...) {} }; @@ -100,14 +143,14 @@ struct AddStructShared inline StructSharedPtr::~StructSharedPtr() { - free(structSharedPtr); + BufferSharedDelete(structSharedPtr); } template StructSharedGet::StructSharedGet(void **ptr) { if (!*ptr) - *ptr = new (malloc(sizeof(T))) T; + *ptr = StructSharedCreate(); } template diff --git a/modules/cpu/common/VolumeIntervals.ih b/modules/cpu/common/VolumeIntervals.ih index 8f85289b0e..12011ef051 100644 --- a/modules/cpu/common/VolumeIntervals.ih +++ b/modules/cpu/common/VolumeIntervals.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/common/World.cpp b/modules/cpu/common/World.cpp index e98cc1520d..408225f9ce 100644 --- a/modules/cpu/common/World.cpp +++ b/modules/cpu/common/World.cpp @@ -1,11 +1,10 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "World.h" -// ispc exports -#include "common/Instance_ispc.h" -#include "common/World_ispc.h" +#include "Instance.h" +#include "lights/Light.h" namespace ospray { @@ -13,8 +12,9 @@ namespace ospray { static void addGeometryInstance(RTCScene &scene, RTCScene instScene, - const Instance *inst, - RTCDevice embreeDevice) + Instance *inst, + RTCDevice embreeDevice, + unsigned int id) { if (!embreeDevice) throw std::runtime_error("invalid Embree device"); @@ -26,11 +26,9 @@ static void addGeometryInstance(RTCScene &scene, // Create geometry instance auto eInst = rtcNewGeometry(embreeDevice, RTC_GEOMETRY_TYPE_INSTANCE); rtcSetGeometryInstancedScene(eInst, instScene); - inst->motionTransform.setEmbreeTransform(eInst); + inst->setEmbreeGeom(eInst); - ispc::Instance_set_embreeGeom(inst->getIE(), eInst); - - rtcAttachGeometry(scene, eInst); + rtcAttachGeometryByID(scene, eInst, id); rtcReleaseGeometry(eInst); } @@ -46,17 +44,22 @@ static void freeAndNullifyEmbreeScene(RTCScene &scene) World::~World() { - freeAndNullifyEmbreeScene(embreeSceneHandleGeometries); - freeAndNullifyEmbreeScene(embreeSceneHandleVolumes); - freeAndNullifyEmbreeScene(embreeSceneHandleClippers); - ispc::World_destroy(getIE()); - ispcEquivalent = nullptr; + // Release Embree scenes + freeAndNullifyEmbreeScene(getSh()->embreeSceneHandleGeometries); + freeAndNullifyEmbreeScene(getSh()->embreeSceneHandleVolumes); + freeAndNullifyEmbreeScene(getSh()->embreeSceneHandleClippers); + + // Release instances arrays + BufferSharedDelete(getSh()->instances); + + // Release renderers data + getSh()->scivisData.destroy(); + getSh()->pathtracerData.destroy(); } World::World() { managedObjectType = OSP_WORLD; - this->ispcEquivalent = ispc::World_create(); } std::string World::toString() const @@ -66,9 +69,13 @@ std::string World::toString() const void World::commit() { - freeAndNullifyEmbreeScene(embreeSceneHandleGeometries); - freeAndNullifyEmbreeScene(embreeSceneHandleVolumes); - freeAndNullifyEmbreeScene(embreeSceneHandleClippers); + RTCScene &esGeom = getSh()->embreeSceneHandleGeometries; + RTCScene &esVol = getSh()->embreeSceneHandleVolumes; + RTCScene &esClip = getSh()->embreeSceneHandleClippers; + + freeAndNullifyEmbreeScene(esGeom); + freeAndNullifyEmbreeScene(esVol); + freeAndNullifyEmbreeScene(esClip); scivisDataValid = false; pathtracerDataValid = false; @@ -91,70 +98,51 @@ void World::commit() << "Committing world, which has " << numInstances << " instances and " << (lights ? lights->size() : 0) << " lights"; - geometriesInstIEs.clear(); - volumesInstIEs.clear(); - clippersInstIEs.clear(); + BufferSharedDelete(getSh()->instances); + getSh()->instances = nullptr; + getSh()->numInvertedClippers = 0; - int numInvertedClippers = 0; if (instances) { + for (auto &&inst : *instances) + if (inst->group->sceneClippers) + getSh()->numInvertedClippers += inst->group->numInvertedClippers; + + // Create shared buffers for instance pointers + getSh()->instances = (ispc::Instance **)BufferSharedCreate( + sizeof(ispc::Instance *) * numInstances); + + // Populate shared buffer with instance pointers, + // create Embree instances + unsigned int id = 0; for (auto &&inst : *instances) { - if (inst->group->sceneGeometries) { - geometriesInstIEs.push_back(inst->getIE()); - addGeometryInstance(embreeSceneHandleGeometries, - inst->group->sceneGeometries, - inst, - embreeDevice); - } - if (inst->group->sceneVolumes) { - volumesInstIEs.push_back(inst->getIE()); - addGeometryInstance(embreeSceneHandleVolumes, - inst->group->sceneVolumes, - inst, - embreeDevice); - } - if (inst->group->sceneClippers) { - clippersInstIEs.push_back(inst->getIE()); - addGeometryInstance(embreeSceneHandleClippers, - inst->group->sceneClippers, - inst, - embreeDevice); - numInvertedClippers += inst->group->numInvertedClippers; - } + getSh()->instances[id] = inst->getSh(); + if (inst->group->sceneGeometries) + addGeometryInstance( + esGeom, inst->group->sceneGeometries, inst, embreeDevice, id); + if (inst->group->sceneVolumes) + addGeometryInstance( + esVol, inst->group->sceneVolumes, inst, embreeDevice, id); + if (inst->group->sceneClippers) + addGeometryInstance( + esClip, inst->group->sceneClippers, inst, embreeDevice, id); + id++; } } - if (embreeSceneHandleGeometries) { - rtcSetSceneFlags( - embreeSceneHandleGeometries, static_cast(sceneFlags)); - rtcCommitScene(embreeSceneHandleGeometries); + if (esGeom) { + rtcSetSceneFlags(esGeom, static_cast(sceneFlags)); + rtcCommitScene(esGeom); } - if (embreeSceneHandleVolumes) { - rtcSetSceneFlags( - embreeSceneHandleVolumes, static_cast(sceneFlags)); - rtcCommitScene(embreeSceneHandleVolumes); + if (esVol) { + rtcSetSceneFlags(esVol, static_cast(sceneFlags)); + rtcCommitScene(esVol); } - if (embreeSceneHandleClippers) { - rtcSetSceneFlags(embreeSceneHandleClippers, + if (esClip) { + rtcSetSceneFlags(esClip, static_cast( sceneFlags | RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION)); - rtcCommitScene(embreeSceneHandleClippers); + rtcCommitScene(esClip); } - - const auto numGeometriesInst = geometriesInstIEs.size(); - const auto numVolumesInst = volumesInstIEs.size(); - const auto numClippersInst = clippersInstIEs.size(); - - ispc::World_set(getIE(), - numGeometriesInst ? geometriesInstIEs.data() : nullptr, - numGeometriesInst, - numVolumesInst ? volumesInstIEs.data() : nullptr, - numVolumesInst, - numClippersInst ? clippersInstIEs.data() : nullptr, - numClippersInst, - embreeSceneHandleGeometries, - embreeSceneHandleVolumes, - embreeSceneHandleClippers, - numInvertedClippers); } box3f World::getBounds() const @@ -162,13 +150,14 @@ box3f World::getBounds() const box3f sceneBounds; box4f bounds; // NOTE(jda) - Embree expects box4f, NOT box3f... - if (embreeSceneHandleGeometries) { - rtcGetSceneBounds(embreeSceneHandleGeometries, (RTCBounds *)&bounds); + if (getSh()->embreeSceneHandleGeometries) { + rtcGetSceneBounds( + getSh()->embreeSceneHandleGeometries, (RTCBounds *)&bounds); sceneBounds.extend(box3f(vec3f(&bounds.lower[0]), vec3f(&bounds.upper[0]))); } - if (embreeSceneHandleVolumes) { - rtcGetSceneBounds(embreeSceneHandleVolumes, (RTCBounds *)&bounds); + if (getSh()->embreeSceneHandleVolumes) { + rtcGetSceneBounds(getSh()->embreeSceneHandleVolumes, (RTCBounds *)&bounds); sceneBounds.extend(box3f(vec3f(&bounds.lower[0]), vec3f(&bounds.upper[0]))); } diff --git a/modules/cpu/common/World.h b/modules/cpu/common/World.h index 784e920bfa..c41078c3b3 100644 --- a/modules/cpu/common/World.h +++ b/modules/cpu/common/World.h @@ -1,21 +1,25 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray stuff -#include "./Data.h" -#include "./Managed.h" -#include "Instance.h" -#include "lights/Light.h" +#include "Data.h" +#include "Managed.h" // stl #include // embree #include "embree3/rtcore.h" +// ispc shared +#include "WorldShared.h" namespace ospray { -struct OSPRAY_SDK_INTERFACE World : public ManagedObject +struct Instance; +struct Light; + +struct OSPRAY_SDK_INTERFACE World + : public AddStructShared { World(); virtual ~World() override; @@ -29,17 +33,9 @@ struct OSPRAY_SDK_INTERFACE World : public ManagedObject Ref> instances; Ref> lights; - std::vector geometriesInstIEs; - std::vector volumesInstIEs; - std::vector clippersInstIEs; - - //! \brief the embree scene handle for this geometry - RTCScene embreeSceneHandleGeometries{nullptr}; - RTCScene embreeSceneHandleVolumes{nullptr}; - RTCScene embreeSceneHandleClippers{nullptr}; - bool scivisDataValid; - bool pathtracerDataValid; + bool scivisDataValid{false}; + bool pathtracerDataValid{false}; void setDevice(RTCDevice embreeDevice); diff --git a/modules/cpu/common/World.ih b/modules/cpu/common/World.ih index 5e8207e978..a166fc65ae 100644 --- a/modules/cpu/common/World.ih +++ b/modules/cpu/common/World.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -7,54 +7,10 @@ #include "common/Clipping.ih" #include "common/Ray.ih" #include "common/VolumeIntervals.ih" +// c++ shared +#include "WorldShared.h" struct Renderer; -struct Light; - -struct SciVisData -{ - // array containing the scene light sources - // the lights are sorted: first lights that are not sampled (visible only), - // then lights that are both sampled and visible - Light **lights; - uint32 numLights; // total number of light sources - uint32 numLightsVisibleOnly; // number of lights that are not sampled (visible - // only) - vec3f aoColorPi; -}; - -struct PathtracerData -{ - // array containing the scene light sources - // the lights are sorted: first geometric, then virtual lights - Light **lights; - uint32 numLights; // total number of light sources (geometric + virtual) - uint32 numGeoLights; // number of geometric light sources - float *lightsCDF; // CDF used by NEE for randomly picking lights -}; - -struct World -{ - Instance **geometriesInst; - int32 numGeometriesInst; - - Instance **volumesInst; - int32 numVolumesInst; - - Instance **clippersInst; - int32 numClippersInst; - - RTCScene embreeSceneHandleGeometries; - RTCScene embreeSceneHandleVolumes; - RTCScene embreeSceneHandleClippers; - - int32 numInvertedClippers; - - SciVisData scivisData; - PathtracerData pathtracerData; -}; - -void World_Constructor(World *uniform world); inline void traceGeometryRay(const World *uniform world, varying Ray &ray) { @@ -87,7 +43,7 @@ inline void traceVolumeRay( (varying RTCRayHit * uniform) & ray); if (intervals.numVolumeIntervals > 0 && hasInterval(intervals.intervals[0])) { - interval.instance = *(world->volumesInst + intervals.intervals[0].instID); + interval.instance = *(world->instances + intervals.intervals[0].instID); interval.volumetricModel = interval.instance->group ->volumetricModels[intervals.intervals[0].geomID]; @@ -112,7 +68,7 @@ inline void traceVolumeRay( if (intervals.numVolumeIntervals > 0) { for (uniform int i = 0; i < intervals.numVolumeIntervals; ++i) { const Instance *const instance = - *(world->volumesInst + intervals.intervals[i].instID); + *(world->instances + intervals.intervals[i].instID); intervals.intervals[i].instance = instance; intervals.intervals[i].volumetricModel = instance->group->volumetricModels[intervals.intervals[i].geomID]; @@ -353,7 +309,7 @@ inline void postIntersect(const World *uniform world, foreach_unique (instID in ray.instID) { if (instID != RTC_INVALID_GEOMETRY_ID) { - Instance *uniform instance = *(world->geometriesInst + instID); + Instance *uniform instance = *(world->instances + instID); Instance_postIntersect(instance, renderer, dg, ray, flags); } else { dg.Ns = dg.Ng = ray.Ng; diff --git a/modules/cpu/common/World.ispc b/modules/cpu/common/World.ispc index 838664aadd..20c020d328 100644 --- a/modules/cpu/common/World.ispc +++ b/modules/cpu/common/World.ispc @@ -1,10 +1,11 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "World.ih" -#include "lights/Light.ih" #include "math/Distribution1D.ih" #include "render/pathtracer/GeometryLight.ih" +// c++ shared +#include "lights/LightShared.h" unmasked void clippingIntersectionFilterV( const struct RTCFilterFunctionNArguments *uniform args) @@ -45,7 +46,7 @@ unmasked void clippingIntersectionFilterV( // We need to call postIntersect on clipping geometry foreach_unique (instID in hit->instID[0]) { // Call postIntersect to get shading normal - Instance *uniform instance = *(context->world->clippersInst + instID); + Instance *uniform instance = *(context->world->instances + instID); Instance_postIntersect(instance, NULL, dg, *ray, DG_NG | DG_NS, true); // Use geometry normal for clipping @@ -97,148 +98,3 @@ unmasked void clippingIntersectionFilterV( context->hits[context->hitsCount] = cHit; context->hitsCount++; } - -void World_Constructor(World *uniform world) -{ - world->geometriesInst = NULL; - world->numGeometriesInst = 0; - world->volumesInst = NULL; - world->numVolumesInst = 0; - world->clippersInst = NULL; - world->numClippersInst = 0; - - world->embreeSceneHandleGeometries = NULL; - world->embreeSceneHandleVolumes = NULL; - world->embreeSceneHandleClippers = NULL; - - world->numInvertedClippers = 0; - - world->scivisData.lights = NULL; - world->scivisData.numLights = 0; - world->scivisData.numLightsVisibleOnly = 0; - - world->pathtracerData.numLights = 0; - world->pathtracerData.numGeoLights = 0; - world->pathtracerData.lights = NULL; - world->pathtracerData.lightsCDF = NULL; -} - -inline void SciVisData_destroy(SciVisData *uniform self) -{ - // Delete all lights - for (uniform int i = 0; i < self->numLights; i++) - delete self->lights[i]; - - delete[] self->lights; -} - -inline void PathtracerData_destroy(PathtracerData *uniform self) -{ - for (uniform int i = 0; i < self->numGeoLights; i++) - GeometryLight_destroy(self->lights[i]); - - for (uniform int i = self->numGeoLights; i < self->numLights; i++) - delete self->lights[i]; - - delete[] self->lights; - delete[] self->lightsCDF; -} - -export void *uniform World_create() -{ - World *uniform world = uniform new World; - World_Constructor(world); - return (void *uniform)world; -} - -export void World_destroy(void *uniform _self) -{ - World *uniform self = (World * uniform) _self; - - SciVisData_destroy(&self->scivisData); - PathtracerData_destroy(&self->pathtracerData); - - delete self; -} - -export void World_set(void *uniform _self, - void *uniform _geometriesInst, - uniform int32 numGeometriesInst, - void *uniform _volumesInst, - uniform int32 numVolumesInst, - void *uniform _clippersInst, - uniform int32 numClippersInst, - void *uniform embreeGeometryScene, - void *uniform embreeVolumeScene, - void *uniform embreeClipScene, - uniform int32 numInvertedClippers) -{ - World *uniform self = (World * uniform) _self; - Instance **uniform geometriesInst = (Instance * *uniform) _geometriesInst; - Instance **uniform volumesInst = (Instance * *uniform) _volumesInst; - Instance **uniform clippersInst = (Instance * *uniform) _clippersInst; - - self->geometriesInst = geometriesInst; - self->numGeometriesInst = numGeometriesInst; - - self->volumesInst = volumesInst; - self->numVolumesInst = numVolumesInst; - - self->clippersInst = clippersInst; - self->numClippersInst = numClippersInst; - - self->embreeSceneHandleGeometries = (RTCScene)embreeGeometryScene; - self->embreeSceneHandleVolumes = (RTCScene)embreeVolumeScene; - self->embreeSceneHandleClippers = (RTCScene)embreeClipScene; - - self->numInvertedClippers = numInvertedClippers; -} - -export void World_setSciVisData(void *uniform _self, - const uniform vec3f &aoColor, - void **uniform lights, - const uniform uint32 numLights, - const uniform uint32 numLightsVisibleOnly) -{ - World *uniform self = (World * uniform) _self; - SciVisData *uniform svData = &self->scivisData; - - SciVisData_destroy(svData); - - svData->aoColorPi = aoColor * pi; - svData->lights = NULL; - svData->numLights = numLights; - svData->numLightsVisibleOnly = numLightsVisibleOnly; - if (numLights) { - svData->lights = uniform new uniform LightPtr[numLights]; - LightArray srcLights = (LightArray)lights; - for (uniform int i = 0; i < numLights; i++) - svData->lights[i] = srcLights[i]; - } -} - -export void World_setPathtracerData(void *uniform _self, - void **uniform lights, - const uniform uint32 numLights, - const uniform uint32 numGeoLights) -{ - World *uniform self = (World * uniform) _self; - PathtracerData *uniform ptData = &self->pathtracerData; - - PathtracerData_destroy(ptData); - - ptData->lights = NULL; - ptData->lightsCDF = NULL; - ptData->numLights = numLights; - ptData->numGeoLights = numGeoLights; - if (numLights) { - ptData->lights = uniform new uniform LightPtr[numLights]; - ptData->lightsCDF = uniform new uniform float[numLights]; - LightArray srcLights = (LightArray)lights; - for (uniform int i = 0; i < numLights; i++) { - ptData->lights[i] = srcLights[i]; - ptData->lightsCDF[i] = 1.0f; - } - Distribution1D_create(numLights, ptData->lightsCDF); - } -} diff --git a/modules/cpu/common/WorldShared.h b/modules/cpu/common/WorldShared.h new file mode 100644 index 0000000000..3be3bc0dde --- /dev/null +++ b/modules/cpu/common/WorldShared.h @@ -0,0 +1,40 @@ +// Copyright 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "render/pathtracer/PathTracerDataShared.h" +#include "render/scivis/SciVisDataShared.h" + +#ifdef __cplusplus +#include "common/StructShared.h" +namespace ispc { +#endif // __cplusplus + +struct Instance; + +struct World +{ + Instance **instances; + int32 numInvertedClippers; + + RTCScene embreeSceneHandleGeometries; + RTCScene embreeSceneHandleVolumes; + RTCScene embreeSceneHandleClippers; + + SciVisData scivisData; + PathtracerData pathtracerData; + +#ifdef __cplusplus + World() + : instances(nullptr), + numInvertedClippers(0), + embreeSceneHandleGeometries(nullptr), + embreeSceneHandleVolumes(nullptr), + embreeSceneHandleClippers(nullptr) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/fb/FrameBuffer.cpp b/modules/cpu/fb/FrameBuffer.cpp index 3b84aabfac..4f996fde69 100644 --- a/modules/cpu/fb/FrameBuffer.cpp +++ b/modules/cpu/fb/FrameBuffer.cpp @@ -1,8 +1,26 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "FrameBuffer.h" -#include "fb/FrameBuffer_ispc.h" +#include "ISPCDevice_ispc.h" +#include "OSPConfig.h" + +namespace { +// Internal utilities for thread local progress tracking +thread_local int threadLastFrameID = -1; +thread_local uint32_t threadNumPixelsRendered = 0; + +extern "C" uint32_t *getThreadNumPixelsRendered() +{ + return &threadNumPixelsRendered; +} + +extern "C" int *getThreadLastFrameID() +{ + return &threadLastFrameID; +} + +}; // namespace namespace ospray { @@ -10,27 +28,41 @@ FrameBuffer::FrameBuffer(const vec2i &_size, ColorBufferFormat _colorBufferFormat, const uint32 channels) : size(_size), - numTiles(divRoundUp(size, getTileSize())), - maxValidPixelID(size - vec2i(1)), - colorBufferFormat(_colorBufferFormat), hasDepthBuffer(channels & OSP_FB_DEPTH), hasAccumBuffer(channels & OSP_FB_ACCUM), hasVarianceBuffer( (channels & OSP_FB_VARIANCE) && (channels & OSP_FB_ACCUM)), hasNormalBuffer(channels & OSP_FB_NORMAL), hasAlbedoBuffer(channels & OSP_FB_ALBEDO), - frameID(-1) + hasPrimitiveIDBuffer(channels & OSP_FB_ID_PRIMITIVE), + hasObjectIDBuffer(channels & OSP_FB_ID_OBJECT), + hasInstanceIDBuffer(channels & OSP_FB_ID_INSTANCE) { managedObjectType = OSP_FRAMEBUFFER; - if (size.x <= 0 || size.y <= 0) { + if (_size.x <= 0 || _size.y <= 0) { throw std::runtime_error( "framebuffer has invalid size. Dimensions must be greater than 0"); } - - tileIDs.reserve(getTotalTiles()); - for (int i = 0; i < getTotalTiles(); ++i) { - tileIDs.push_back(i); + getSh()->size = _size; + getSh()->rcpSize = vec2f(1.f) / vec2f(_size); + getSh()->channels = channels; + getSh()->colorBufferFormat = _colorBufferFormat; + +#if OSPRAY_RENDER_TASK_SIZE == -1 + // Compute render task size based on the simd width to get as "square" as + // possible a task size that has simdWidth pixels + const int simdWidth = ispc::ISPCDevice_programCount(); + vec2i renderTaskSize(simdWidth, 1); + while (renderTaskSize.x / 2 > renderTaskSize.y) { + renderTaskSize.y *= 2; + renderTaskSize.x /= 2; } +#else + // Note: we could also allow changing this at runtime if we want to add this + // to the API + vec2i renderTaskSize(OSPRAY_RENDER_TASK_SIZE); +#endif + getSh()->renderTaskSize = renderTaskSize; } void FrameBuffer::commit() @@ -38,29 +70,19 @@ void FrameBuffer::commit() imageOpData = getParamDataT("imageOperation"); } -vec2i FrameBuffer::getTileSize() const -{ - return vec2i(TILE_SIZE); -} - -vec2i FrameBuffer::getNumTiles() const +vec2i FrameBuffer::getRenderTaskSize() const { - return numTiles; -} - -int FrameBuffer::getTotalTiles() const -{ - return numTiles.x * numTiles.y; + return getSh()->renderTaskSize; } vec2i FrameBuffer::getNumPixels() const { - return size; + return getSh()->size; } OSPFrameBufferFormat FrameBuffer::getColorBufferFormat() const { - return colorBufferFormat; + return getSh()->colorBufferFormat; } float FrameBuffer::getVariance() const @@ -68,17 +90,12 @@ float FrameBuffer::getVariance() const return frameVariance; } -utility::ArrayView FrameBuffer::getTileIDs() -{ - return utility::ArrayView(tileIDs); -} - void FrameBuffer::beginFrame() { - frameProgress = 0.0f; cancelRender = false; - frameID++; - ispc::FrameBuffer_set_frameID(getIE(), frameID); + getSh()->cancelRender = 0; + getSh()->numPixelsRendered = 0; + getSh()->frameID++; } std::string FrameBuffer::toString() const @@ -88,10 +105,12 @@ std::string FrameBuffer::toString() const void FrameBuffer::setCompletedEvent(OSPSyncEvent event) { + // We won't be running ISPC-side rendering tasks when updating the + // progress values here in C++ if (event == OSP_NONE_FINISHED) - frameProgress = 0.0f; + getSh()->numPixelsRendered = 0; if (event == OSP_FRAME_FINISHED) - frameProgress = 1.0f; + getSh()->numPixelsRendered = getNumPixels().long_product(); stagesCompleted = event; } @@ -107,19 +126,16 @@ void FrameBuffer::waitForEvent(OSPSyncEvent event) const ; } -void FrameBuffer::reportProgress(float newValue) -{ - frameProgress = clamp(newValue, 0.f, 1.f); -} - -float FrameBuffer::getCurrentProgress() +float FrameBuffer::getCurrentProgress() const { - return frameProgress; + return static_cast(getSh()->numPixelsRendered) + / getNumPixels().long_product(); } void FrameBuffer::cancelFrame() { cancelRender = true; + getSh()->cancelRender = 1; } bool FrameBuffer::frameCancelled() const @@ -127,6 +143,12 @@ bool FrameBuffer::frameCancelled() const return cancelRender; } +void FrameBuffer::prepareImageOps() +{ + findFirstFrameOperation(); + setPixelOpShs(); +} + void FrameBuffer::findFirstFrameOperation() { firstFrameOperation = -1; @@ -141,13 +163,26 @@ void FrameBuffer::findFirstFrameOperation() if (firstFrameOperation == imageOps.size() && isFrameOp) firstFrameOperation = i; else if (firstFrameOperation < imageOps.size() && !isFrameOp) { - throw std::runtime_error( - "frame operation must be before pixel and tile operations in the " - "image operation pipeline"); + postStatusMsg(OSP_LOG_WARNING) + << "Invalid pixel/frame op pipeline: all frame operations " + "must come after all pixel operations"; } } } +void FrameBuffer::setPixelOpShs() +{ + pixelOpShs.clear(); + for (auto &op : imageOps) { + LivePixelOp *pop = dynamic_cast(op.get()); + if (pop) { + pixelOpShs.push_back(pop->getSh()); + } + } + getSh()->pixelOps = pixelOpShs.empty() ? nullptr : pixelOpShs.data(); + getSh()->numPixelOps = pixelOpShs.size(); +} + bool FrameBuffer::hasAccumBuf() const { return hasAccumBuffer; @@ -168,6 +203,47 @@ bool FrameBuffer::hasAlbedoBuf() const return hasAlbedoBuffer; } +uint32 FrameBuffer::getChannelFlags() const +{ + uint32 channels = 0; + if (hasDepthBuffer) { + channels |= OSP_FB_DEPTH; + } + if (hasAccumBuffer) { + channels |= OSP_FB_ACCUM; + } + if (hasVarianceBuffer) { + channels |= OSP_FB_VARIANCE; + } + if (hasNormalBuffer) { + channels |= OSP_FB_NORMAL; + } + if (hasAlbedoBuffer) { + channels |= OSP_FB_ALBEDO; + } + return channels; +} + +int32 FrameBuffer::getFrameID() const +{ + return getSh()->frameID; +} + +bool FrameBuffer::hasPrimitiveIDBuf() const +{ + return hasPrimitiveIDBuffer; +} + +bool FrameBuffer::hasObjectIDBuf() const +{ + return hasObjectIDBuffer; +} + +bool FrameBuffer::hasInstanceIDBuf() const +{ + return hasInstanceIDBuffer; +} + OSPTYPEFOR_DEFINITION(FrameBuffer *); } // namespace ospray diff --git a/modules/cpu/fb/FrameBuffer.h b/modules/cpu/fb/FrameBuffer.h index e08dec5956..f5153a9489 100644 --- a/modules/cpu/fb/FrameBuffer.h +++ b/modules/cpu/fb/FrameBuffer.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -10,19 +10,23 @@ #include "fb/ImageOp.h" #include "ospray/ospray.h" #include "rkcommon/utility/ArrayView.h" +// ispc shared +#include "FrameBufferShared.h" namespace ospray { -/*! abstract frame buffer class */ -struct OSPRAY_SDK_INTERFACE FrameBuffer : public ManagedObject +// abstract frame buffer class +struct OSPRAY_SDK_INTERFACE FrameBuffer + : public AddStructShared { - /*! app-mappable format of the color buffer. make sure that this - matches the definition on the ISPC side */ + // app-mappable format of the color buffer. make sure that this + // matches the definition on the ISPC side using ColorBufferFormat = OSPFrameBufferFormat; FrameBuffer(const vec2i &size, ColorBufferFormat colorBufferFormat, const uint32 channels); + virtual ~FrameBuffer() override = default; virtual void commit() override; @@ -30,99 +34,98 @@ struct OSPRAY_SDK_INTERFACE FrameBuffer : public ManagedObject virtual const void *mapBuffer(OSPFrameBufferChannel channel) = 0; virtual void unmap(const void *mappedMem) = 0; - virtual void setTile(Tile &tile) = 0; - /*! \brief clear (the specified channels of) this frame buffer */ + // clear (the specified channels of) this frame buffer virtual void clear() = 0; - //! get number of pixels per tile, in x and y direction - vec2i getTileSize() const; + // Get number of pixels per render task, in x and y direction + vec2i getRenderTaskSize() const; + + // Return the number of render tasks in the x and y direction + // This is the kernel launch dims to render the image + virtual vec2i getNumRenderTasks() const = 0; - //! return number of tiles in x and y direction - vec2i getNumTiles() const; + virtual uint32_t getTotalRenderTasks() const = 0; - int getTotalTiles() const; + virtual utility::ArrayView getRenderTaskIDs() = 0; - //! get number of pixels in x and y diretion + // get number of pixels in x and y diretion vec2i getNumPixels() const; - //! get the color format type for this Buffer + // get the color format type for this Buffer ColorBufferFormat getColorBufferFormat() const; float getVariance() const; - utility::ArrayView getTileIDs(); - - /*! how often has been accumulated into that tile - Note that it is up to the application to properly - reset the accumulationIDs (using ospClearAccum(fb)) if anything - changes that requires clearing the accumulation buffer. */ - virtual int32 accumID(const vec2i &tile) = 0; - virtual float tileError(const vec2i &tile) = 0; + virtual float taskError(const uint32_t taskID) const = 0; virtual void beginFrame(); - //! end the frame and run any final post-processing frame ops + // end the frame and run any final post-processing frame ops virtual void endFrame(const float errorThreshold, const Camera *camera) = 0; - //! \brief common function to help printf-debugging - /*! \detailed Every derived class should override this! */ + // common function to help printf-debugging, every derived class should + // override this virtual std::string toString() const override; void setCompletedEvent(OSPSyncEvent event); OSPSyncEvent getLatestCompleteEvent() const; void waitForEvent(OSPSyncEvent event) const; - void reportProgress(float newValue); - float getCurrentProgress(); + virtual float getCurrentProgress() const; - void cancelFrame(); + virtual void cancelFrame(); bool frameCancelled() const; bool hasAccumBuf() const; bool hasVarianceBuf() const; bool hasNormalBuf() const; bool hasAlbedoBuf() const; + bool hasPrimitiveIDBuf() const; + bool hasObjectIDBuf() const; + bool hasInstanceIDBuf() const; + + uint32 getChannelFlags() const; + + int32 getFrameID() const; protected: + // Finalize the pixel op and frame op state for rendering on commit + void prepareImageOps(); + /*! Find the index of the first frameoperation included in * the imageop pipeline */ void findFirstFrameOperation(); - const vec2i size; - vec2i numTiles; - vec2i maxValidPixelID; + // Find all the LivePixelOps and set their ISPC-side data on the FrameBuffer + void setPixelOpShs(); - /*! buffer format of the color buffer */ - ColorBufferFormat colorBufferFormat; + const vec2i size; - /*! indicates whether the app requested this frame buffer to have - an (application-mappable) depth buffer */ + // indicates whether the app requested this frame buffer to have + // an (application-mappable) depth buffer bool hasDepthBuffer; - /*! indicates whether the app requested this frame buffer to have - an accumulation buffer */ + // indicates whether the app requested this frame buffer to have + // an accumulation buffer bool hasAccumBuffer; bool hasVarianceBuffer; bool hasNormalBuffer; bool hasAlbedoBuffer; - - //! This marks the global number of frames that have been rendered since - //! the last ospFramebufferClear() has been called. - int32 frameID; + bool hasPrimitiveIDBuffer; + bool hasObjectIDBuffer; + bool hasInstanceIDBuffer; float frameVariance{0.f}; - std::atomic frameProgress{1.f}; std::atomic cancelRender{false}; std::atomic stagesCompleted{OSP_FRAME_FINISHED}; Ref> imageOpData; std::vector> imageOps; + std::vector pixelOpShs; size_t firstFrameOperation = -1; - - std::vector tileIDs; }; OSPTYPEFOR_SPECIALIZATION(FrameBuffer *, OSP_FRAMEBUFFER); diff --git a/modules/cpu/fb/FrameBuffer.ih b/modules/cpu/fb/FrameBuffer.ih index c31602a61d..e19c755dc7 100644 --- a/modules/cpu/fb/FrameBuffer.ih +++ b/modules/cpu/fb/FrameBuffer.ih @@ -1,42 +1,44 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once -#include "Tile.ih" -/*! \file framebuffer.ih Defines the abstract base class of an ISPC frame buffer - */ +#include "FrameBufferShared.h" +#include "common/OSPCommon.ih" -struct FrameBuffer; +extern "C" uint32 *uniform getThreadNumPixelsRendered(); -/*! app-mappable format of the color buffer. make sure that this - matches the definition on the ISPC side */ -typedef enum -{ - ColorBufferFormat_NONE, /*!< app will never map the color buffer (e.g., for a - framebuffer attached to a display wall that will - likely have a different res that the app has...) */ - ColorBufferFormat_RGBA_UINT8, /*! app will map in RGBA, one uint8 per channel - */ - ColorBufferFormat_RGB_UINT8, /*! app will map in RGBA, one uint8 per channel - */ - ColorBufferFormat_RGBA_FLOAT32, /*! app will map in RBGA, one float per - channel */ -} FrameBuffer_ColorBufferFormat; - -struct FrameBuffer -{ - vec2i size; /*!< size (width x height) of frame buffer, in pixels */ - vec2f rcpSize; /*! one over size (precomputed) */ - int32 frameID; +extern "C" int *uniform getThreadLastFrameID(); - FrameBuffer_ColorBufferFormat colorBufferFormat; -}; +// Run the chain of pixel ops (if any) to produce the final color to be written +// into the framebuffer +vec4f FrameBuffer_runPixelOps(FrameBuffer *uniform self, + const vec4f &color, + const float depth, + const vec3f &normal, + const vec3f &albedo); -void FrameBuffer_Constructor( - FrameBuffer *uniform self); - -void FrameBuffer_set(FrameBuffer *uniform self, - const uniform uint32 size_x, - const uniform uint32 size_y, - int32 uniform colorBufferFormat); +inline void FrameBuffer_updateProgress( + FrameBuffer *uniform self, const uniform uint32 numPixelsRendered) +{ + uint32 *uniform pixelsRendered = getThreadNumPixelsRendered(); + + // Reset the pixels rendered counter for each new frame + int *uniform lastFrameID = getThreadLastFrameID(); + if (self->frameID != *lastFrameID) { + *pixelsRendered = 0; + *lastFrameID = self->frameID; + } + + // Update the pixels rendered count and report back to the atomic if we've + // reached the reporting threshold + *pixelsRendered += numPixelsRendered; + + // Report rendering results at the same frequency they would have been + // reported (each tile) when using the old nested parallel fors over tiles + // then pixels. + if (*pixelsRendered >= TILE_SIZE * TILE_SIZE) { + atomic_add_global(&self->numPixelsRendered, *pixelsRendered); + *pixelsRendered = 0; + } +} diff --git a/modules/cpu/fb/FrameBuffer.ispc b/modules/cpu/fb/FrameBuffer.ispc index 3316a77872..bdf5d39dfa 100644 --- a/modules/cpu/fb/FrameBuffer.ispc +++ b/modules/cpu/fb/FrameBuffer.ispc @@ -1,32 +1,18 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "fb/FrameBuffer.ih" -void FrameBuffer_Constructor(FrameBuffer *uniform self) +vec4f FrameBuffer_runPixelOps(FrameBuffer *uniform self, + const vec4f &color, + const float depth, + const vec3f &normal, + const vec3f &albedo) { - self->size.x = 0; - self->size.y = 0; - self->rcpSize.x = 0.f; - self->rcpSize.y = 0.f; - self->colorBufferFormat = ColorBufferFormat_NONE; -} - -void FrameBuffer_set(FrameBuffer *uniform self, - const uniform uint32 size_x, - const uniform uint32 size_y, - uniform int32 colorBufferFormat) -{ - self->size.x = size_x; - self->size.y = size_y; - self->rcpSize.x = 1.f / size_x; - self->rcpSize.y = 1.f / size_y; - self->colorBufferFormat = - (uniform FrameBuffer_ColorBufferFormat)colorBufferFormat; -} - -export void FrameBuffer_set_frameID(void *uniform _self, uniform int32 frameID) -{ - uniform FrameBuffer *uniform self = (uniform FrameBuffer * uniform) _self; - self->frameID = frameID; + vec4f outColor = color; + for (uniform int i = 0; i < self->numPixelOps; ++i) { + outColor = self->pixelOps[i]->processPixel( + self->pixelOps[i], outColor, depth, normal, albedo); + } + return outColor; } diff --git a/modules/cpu/fb/FrameBufferShared.h b/modules/cpu/fb/FrameBufferShared.h new file mode 100644 index 0000000000..013d43a785 --- /dev/null +++ b/modules/cpu/fb/FrameBufferShared.h @@ -0,0 +1,107 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "fb/ImageOpShared.h" +#include "ospray/OSPEnums.h" + +#ifdef __cplusplus +#include "common/StructShared.h" +namespace ispc { +typedef void *FrameBuffer_accumulateSampleFct; +typedef void *FrameBuffer_getRenderTaskDescFct; +typedef void *FrameBuffer_completeTaskFct; +#else +#include "fb/RenderTaskDesc.ih" +#include "render/ScreenSample.ih" + +struct FrameBuffer; + +typedef void (*FrameBuffer_accumulateSampleFct)(FrameBuffer *uniform fb, + const varying ScreenSample &sample, + uniform RenderTaskDesc &taskDesc); + +typedef uniform RenderTaskDesc (*FrameBuffer_getRenderTaskDescFct)( + FrameBuffer *uniform fb, const uniform uint32 taskID); + +typedef void (*FrameBuffer_completeTaskFct)( + FrameBuffer *uniform fb, const uniform RenderTaskDesc &taskDesc); +#endif // __cplusplus + +/* The ISPC-side FrameBuffer allows tasks to write directly to the framebuffer + * memory from ISPC. Given the set of task IDs to be rendered, a renderer must: + * + * 1. Get the RenderTaskDesc by calling getRenderTaskDesc and render the region + * of pixels specified in the task description. + * + * 2. Write the result of rendering each pixel to the framebuffer by calling + * accumulateSample + * + * 3. Update task-level values (accum ID and error) by calling completeTask + */ +struct FrameBuffer +{ + /* Get the task description for a given render task ID. The task description + * stores the region that should be rendered for the task and its accumID + */ + FrameBuffer_getRenderTaskDescFct getRenderTaskDesc; + + /* Accumulate samples taken for this render task into the framebuffer. + * Task error will also be computed and accumulated on the render task, + * to handle cases where there are more pixels in a task than the SIMD width. + */ + FrameBuffer_accumulateSampleFct accumulateSample; + + /* Perform final task updates for the given task, updating its accum ID (if + * accumulation buffering is enabled) and its error if variance termination is + * enabled + */ + FrameBuffer_completeTaskFct completeTask; + + // The size of the framebuffer, in pixels + vec2i size; + // 1/size (precomputed) + vec2f rcpSize; + // The default size of each each render task, in pixels + vec2i renderTaskSize; + + int32 frameID; + + // The channels stored in the framebuffer + uint32 channels; + + OSPFrameBufferFormat colorBufferFormat; + + LivePixelOp **pixelOps; + uint32 numPixelOps; + + // If the frame has been cancelled or not. Note: we don't share bools between + // ISPC and C++ as the true value representation may differ (as it does with + // gcc) + uint32 cancelRender; + + // The number of pixels rendered this frame, for tracking rendering progress + uint32 numPixelsRendered; + +#ifdef __cplusplus + FrameBuffer() + : getRenderTaskDesc(nullptr), + accumulateSample(nullptr), + completeTask(nullptr), + size(0), + rcpSize(0.f), + renderTaskSize(4), + frameID(-1), + channels(0), + colorBufferFormat(OSP_FB_NONE), + pixelOps(nullptr), + numPixelOps(0), + cancelRender(0), + numPixelsRendered(0) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/fb/FrameBufferView.cpp b/modules/cpu/fb/FrameBufferView.cpp index af86d7c1d9..6f377e4a62 100644 --- a/modules/cpu/fb/FrameBufferView.cpp +++ b/modules/cpu/fb/FrameBufferView.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "FrameBufferView.h" diff --git a/modules/cpu/fb/FrameBufferView.h b/modules/cpu/fb/FrameBufferView.h index 264cace6a9..3439cb15b9 100644 --- a/modules/cpu/fb/FrameBufferView.h +++ b/modules/cpu/fb/FrameBufferView.h @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/fb/FrameBufferView.ih b/modules/cpu/fb/FrameBufferView.ih index 2d0eab029c..c076fa7671 100644 --- a/modules/cpu/fb/FrameBufferView.ih +++ b/modules/cpu/fb/FrameBufferView.ih @@ -1,10 +1,11 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once -#include "FrameBuffer.ih" #include "math/AffineSpace.ih" +// c++ shared +#include "FrameBufferShared.h" struct FrameBufferView { @@ -15,15 +16,15 @@ struct FrameBufferView // The additional halo region pixels included in the view, if requested vec2i haloDims; - FrameBuffer_ColorBufferFormat colorBufferFormat; - /*! Color buffer of the image, exact pixel format depends - * on `colorBufferFormat` - */ + OSPFrameBufferFormat colorBufferFormat; + + // Color buffer of the image, exact pixel format depends + // on `colorBufferFormat` void *colorBuffer; - //! One float per pixel, may be NULL + // One float per pixel, may be NULL float *depthBuffer; - //! accumulated world-space normal per pixel + // accumulated world-space normal per pixel vec3f *normalBuffer; - //! accumulated albedo, one RGBF32 per pixel + // accumulated albedo, one RGBF32 per pixel vec3f *albedoBuffer; }; diff --git a/modules/cpu/fb/ImageOp.cpp b/modules/cpu/fb/ImageOp.cpp index 05e09196c8..95a0c50625 100644 --- a/modules/cpu/fb/ImageOp.cpp +++ b/modules/cpu/fb/ImageOp.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ImageOp.h" @@ -33,7 +33,7 @@ std::string ImageOp::toString() const return "ospray::ImageOp(base class)"; } -LiveTileOp::LiveTileOp(FrameBufferView &_fbView) : LiveImageOp(_fbView) {} +LivePixelOp::LivePixelOp(FrameBufferView &_fbView) : AddStructShared(_fbView) {} LiveFrameOp::LiveFrameOp(FrameBufferView &_fbView) : LiveImageOp(_fbView) {} diff --git a/modules/cpu/fb/ImageOp.h b/modules/cpu/fb/ImageOp.h index 4808394f66..63c9553c38 100644 --- a/modules/cpu/fb/ImageOp.h +++ b/modules/cpu/fb/ImageOp.h @@ -1,17 +1,18 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "FrameBufferView.h" +#include "ImageOpShared.h" #include "common/Util.h" -#include "fb/Tile.h" +#include "fb/TileShared.h" namespace ospray { struct Camera; -/*! An instance of an image op which is actually attached to a framebuffer */ +// An instance of an image op that is actually attached to a framebuffer struct OSPRAY_SDK_INTERFACE LiveImageOp { FrameBufferView fbView; @@ -21,6 +22,7 @@ struct OSPRAY_SDK_INTERFACE LiveImageOp virtual ~LiveImageOp() = default; virtual void beginFrame() {} + virtual void endFrame() {} }; @@ -57,9 +59,9 @@ struct OSPRAY_SDK_INTERFACE ImageOp : public ManagedObject OSPTYPEFOR_SPECIALIZATION(ImageOp *, OSP_IMAGE_OPERATION); -struct OSPRAY_SDK_INTERFACE TileOp : public ImageOp +struct OSPRAY_SDK_INTERFACE PixelOp : public ImageOp { - ~TileOp() override = default; + ~PixelOp() override = default; }; struct OSPRAY_SDK_INTERFACE FrameOp : public ImageOp @@ -71,17 +73,11 @@ struct OSPRAY_SDK_INTERFACE FrameOp : public ImageOp } }; -struct OSPRAY_SDK_INTERFACE LiveTileOp : public LiveImageOp +struct OSPRAY_SDK_INTERFACE LivePixelOp + : public AddStructShared { - LiveTileOp(FrameBufferView &fbView); - ~LiveTileOp() override = default; - - /*! called right after the tile got accumulated; i.e., the - tile's RGBA values already contain the accu-buffer blended - values (assuming an accubuffer exists), and this function - defines how these pixels are being processed before written - into the color buffer */ - virtual void process(Tile &) = 0; + LivePixelOp(FrameBufferView &fbView); + ~LivePixelOp() override = default; }; struct OSPRAY_SDK_INTERFACE LiveFrameOp : public LiveImageOp diff --git a/modules/cpu/fb/ImageOpShared.h b/modules/cpu/fb/ImageOpShared.h new file mode 100644 index 0000000000..62c548d501 --- /dev/null +++ b/modules/cpu/fb/ImageOpShared.h @@ -0,0 +1,32 @@ +// Copyright 2009 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef __cplusplus +#include "common/StructShared.h" +namespace ispc { +typedef void *LivePixelOp_processPixel; +#else +#include "rkcommon/math/vec.ih" +struct LivePixelOp; + +typedef vec4f (*LivePixelOp_processPixel)(const LivePixelOp *uniform self, + const vec4f &color, + const float depth, + const vec3f &normal, + const vec3f &albedo); +#endif + +struct LivePixelOp +{ + LivePixelOp_processPixel processPixel; + +#ifdef __cplusplus + LivePixelOp() : processPixel(nullptr) {} +#endif +}; + +#ifdef __cplusplus +} +#endif diff --git a/modules/cpu/fb/LocalFB.cpp b/modules/cpu/fb/LocalFB.cpp index d8d7f330c4..dd9af5e2be 100644 --- a/modules/cpu/fb/LocalFB.cpp +++ b/modules/cpu/fb/LocalFB.cpp @@ -1,43 +1,39 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "LocalFB.h" +#include +#include #include #include "ImageOp.h" +#include "SparseFB.h" #include "fb/LocalFB_ispc.h" +#include "render/util.h" +#include "rkcommon/common.h" +#include "rkcommon/tasking/parallel_for.h" namespace ospray { -template -static T *getDataSafe(std::vector &v) -{ - return v.empty() ? nullptr : v.data(); -} - LocalFrameBuffer::LocalFrameBuffer(const vec2i &_size, ColorBufferFormat _colorBufferFormat, const uint32 channels) - : FrameBuffer(_size, _colorBufferFormat, channels), - tileErrorRegion(hasVarianceBuffer ? getNumTiles() : vec2i(0)) + : AddStructShared(_size, _colorBufferFormat, channels), + numRenderTasks(divRoundUp(size, getRenderTaskSize())), + taskErrorRegion(hasVarianceBuffer ? getNumRenderTasks() : vec2i(0)) { - if (size.x <= 0 || size.y <= 0) { - throw std::runtime_error( - "local framebuffer has invalid size. Dimensions must be greater than " - "0"); - } - - const size_t pixelBytes = sizeOf(colorBufferFormat); - const size_t numPixels = size.long_product(); + const size_t pixelBytes = sizeOf(_colorBufferFormat); + const size_t numPixels = _size.long_product(); colorBuffer.resize(pixelBytes * numPixels); if (hasDepthBuffer) depthBuffer.resize(numPixels); - if (hasAccumBuffer) + if (hasAccumBuffer) { accumBuffer.resize(numPixels); - tileAccumID.resize(getTotalTiles(), 0); + taskAccumID.resize(getTotalRenderTasks(), 0); + } if (hasVarianceBuffer) varianceBuffer.resize(numPixels); @@ -48,16 +44,51 @@ LocalFrameBuffer::LocalFrameBuffer(const vec2i &_size, if (hasAlbedoBuffer) albedoBuffer.resize(numPixels); - ispcEquivalent = ispc::LocalFrameBuffer_create(size.x, - size.y, - colorBufferFormat, - getDataSafe(colorBuffer), - getDataSafe(depthBuffer), - getDataSafe(accumBuffer), - getDataSafe(varianceBuffer), - getDataSafe(normalBuffer), - getDataSafe(albedoBuffer), - getDataSafe(tileAccumID)); + if (hasPrimitiveIDBuffer) + primitiveIDBuffer.resize(numPixels); + + if (hasObjectIDBuffer) + objectIDBuffer.resize(numPixels); + + if (hasInstanceIDBuffer) + instanceIDBuffer.resize(numPixels); + + // TODO: Better way to pass the task IDs that doesn't require just storing + // them all? Maybe as blocks/tiles similar to when we just had tiles? Will + // make task ID lookup more expensive for sparse case though + renderTaskIDs.reserve(getTotalRenderTasks()); + for (uint32_t i = 0; i < getTotalRenderTasks(); ++i) { + renderTaskIDs.push_back(i); + } + + // TODO: Could use TBB parallel sort here if it's exposed through the rkcommon + // tasking system + std::sort(renderTaskIDs.begin(), + renderTaskIDs.end(), + [&](const uint32_t &a, const uint32_t &b) { + const vec2i p_a = getTaskStartPos(a); + const vec2i p_b = getTaskStartPos(b); + return interleaveZOrder(p_a.x, p_a.y) < interleaveZOrder(p_b.x, p_b.y); + }); + + getSh()->super.accumulateSample = + ispc::LocalFrameBuffer_accumulateSample_addr(); + getSh()->super.getRenderTaskDesc = + ispc::LocalFrameBuffer_getRenderTaskDesc_addr(); + getSh()->super.completeTask = ispc::LocalFrameBuffer_completeTask_addr(); + + getSh()->colorBuffer = getDataSafe(colorBuffer); + getSh()->depthBuffer = getDataSafe(depthBuffer); + getSh()->accumBuffer = getDataSafe(accumBuffer); + getSh()->varianceBuffer = getDataSafe(varianceBuffer); + getSh()->normalBuffer = getDataSafe(normalBuffer); + getSh()->albedoBuffer = getDataSafe(albedoBuffer); + getSh()->taskAccumID = getDataSafe(taskAccumID); + getSh()->taskRegionError = taskErrorRegion.errorBuffer(); + getSh()->numRenderTasks = numRenderTasks; + getSh()->primitiveIDBuffer = getDataSafe(primitiveIDBuffer); + getSh()->objectIDBuffer = getDataSafe(objectIDBuffer); + getSh()->instanceIDBuffer = getDataSafe(instanceIDBuffer); } void LocalFrameBuffer::commit() @@ -67,7 +98,7 @@ void LocalFrameBuffer::commit() imageOps.clear(); if (imageOpData) { FrameBufferView fbv(this, - colorBufferFormat, + getColorBufferFormat(), getDataSafe(colorBuffer), getDataSafe(depthBuffer), getDataSafe(normalBuffer), @@ -75,9 +106,23 @@ void LocalFrameBuffer::commit() for (auto &&obj : *imageOpData) imageOps.push_back(obj->attach(fbv)); - - findFirstFrameOperation(); } + prepareImageOps(); +} + +vec2i LocalFrameBuffer::getNumRenderTasks() const +{ + return numRenderTasks; +} + +uint32_t LocalFrameBuffer::getTotalRenderTasks() const +{ + return numRenderTasks.long_product(); +} + +utility::ArrayView LocalFrameBuffer::getRenderTaskIDs() +{ + return utility::ArrayView(renderTaskIDs); } std::string LocalFrameBuffer::toString() const @@ -87,87 +132,116 @@ std::string LocalFrameBuffer::toString() const void LocalFrameBuffer::clear() { - frameID = -1; // we increment at the start of the frame + getSh()->super.frameID = -1; // we increment at the start of the frame // it is only necessary to reset the accumID, // LocalFrameBuffer_accumulateTile takes care of clearing the // accumulating buffers - std::fill(tileAccumID.begin(), tileAccumID.end(), 0); + std::fill(taskAccumID.begin(), taskAccumID.end(), 0); // always also clear error buffer (if present) if (hasVarianceBuffer) { - tileErrorRegion.clear(); + taskErrorRegion.clear(); } } -void LocalFrameBuffer::setTile(Tile &tile) +void LocalFrameBuffer::writeTiles(const containers::AlignedVector &tiles) { - if (hasAccumBuffer) { - const float err = - ispc::LocalFrameBuffer_accumulateTile(getIE(), (ispc::Tile &)tile); - if ((tile.accumID & 1) == 1) - tileErrorRegion.update(tile.region.lower / TILE_SIZE, err); - } + // TODO: The parallel dispatch part of this should be moved into ISPC as an + // ISPC launch that calls the individual (currently) exported functions that + // we call below in this loop + tasking::parallel_for(tiles.size(), [&](const size_t i) { + const Tile *tile = &tiles[i]; + if (hasDepthBuffer) { + ispc::LocalFrameBuffer_writeDepthTile(getSh(), tile); + } - if (hasDepthBuffer) { - ispc::LocalFrameBuffer_accumulateWriteDepthTile( - getIE(), (ispc::Tile &)tile); - } + if (hasAlbedoBuffer) { + ispc::LocalFrameBuffer_writeAuxTile(getSh(), + tile, + (ispc::vec3f *)albedoBuffer.data(), + tile->ar, + tile->ag, + tile->ab); + } - if (hasAlbedoBuffer) { - ispc::LocalFrameBuffer_accumulateAuxTile(getIE(), - (ispc::Tile &)tile, - (ispc::vec3f *)albedoBuffer.data(), - tile.ar, - tile.ag, - tile.ab); - } + if (hasPrimitiveIDBuffer) { + ispc::LocalFrameBuffer_writeIDTile( + getSh(), tile, getSh()->primitiveIDBuffer, tile->pid); + } - if (hasNormalBuffer) - ispc::LocalFrameBuffer_accumulateAuxTile(getIE(), - (ispc::Tile &)tile, - (ispc::vec3f *)normalBuffer.data(), - tile.nx, - tile.ny, - tile.nz); - - if (!imageOps.empty()) { - std::for_each(imageOps.begin(), - imageOps.begin() + firstFrameOperation, - [&](std::unique_ptr &iop) { - LiveTileOp *top = dynamic_cast(iop.get()); - if (top) { - top->process(tile); - } - // TODO: For now, frame operations must be last - // in the pipeline - }); + if (hasObjectIDBuffer) { + ispc::LocalFrameBuffer_writeIDTile( + getSh(), tile, getSh()->objectIDBuffer, tile->gid); + } + + if (hasInstanceIDBuffer) { + ispc::LocalFrameBuffer_writeIDTile( + getSh(), tile, getSh()->instanceIDBuffer, tile->iid); + } + + if (hasNormalBuffer) + ispc::LocalFrameBuffer_writeAuxTile(getSh(), + tile, + (ispc::vec3f *)normalBuffer.data(), + tile->nx, + tile->ny, + tile->nz); + + if (!colorBuffer.empty()) { + switch (getColorBufferFormat()) { + case OSP_FB_RGBA8: + ispc::LocalFrameBuffer_writeTile_RGBA8(getSh(), tile); + break; + case OSP_FB_SRGBA: + ispc::LocalFrameBuffer_writeTile_SRGBA(getSh(), tile); + break; + case OSP_FB_RGBA32F: + ispc::LocalFrameBuffer_writeTile_RGBA32F(getSh(), tile); + break; + default: + NOT_IMPLEMENTED; + } + } + }); +} + +void LocalFrameBuffer::writeTiles(const SparseFrameBuffer *sparseFb) +{ + const auto &tiles = sparseFb->getTiles(); + writeTiles(tiles); + + assert(getRenderTaskSize() == sparseFb->getRenderTaskSize()); + const vec2i renderTaskSize = getRenderTaskSize(); + + if (!hasVarianceBuffer) { + return; } - if (!colorBuffer.empty()) { - switch (colorBufferFormat) { - case OSP_FB_RGBA8: - ispc::LocalFrameBuffer_writeTile_RGBA8(getIE(), (ispc::Tile &)tile); - break; - case OSP_FB_SRGBA: - ispc::LocalFrameBuffer_writeTile_SRGBA(getIE(), (ispc::Tile &)tile); - break; - case OSP_FB_RGBA32F: - ispc::LocalFrameBuffer_writeTile_RGBA32F(getIE(), (ispc::Tile &)tile); - break; - default: - NOT_IMPLEMENTED; + uint32_t renderTaskID = 0; + for (size_t i = 0; i < tiles.size(); ++i) { + const auto &tile = tiles[i]; + const box2i taskRegion( + tile.region.lower / renderTaskSize, tile.region.upper / renderTaskSize); + for (int y = taskRegion.lower.y; y < taskRegion.upper.y; ++y) { + for (int x = taskRegion.lower.x; x < taskRegion.upper.x; + ++x, ++renderTaskID) { + const vec2i task(x, y); + taskErrorRegion.update(task, sparseFb->taskError(renderTaskID)); + } } } } -int32 LocalFrameBuffer::accumID(const vec2i &tile) +vec2i LocalFrameBuffer::getTaskStartPos(const uint32_t taskID) const { - return tileAccumID[tile.y * numTiles.x + tile.x]; + const vec2i numRenderTasks = getNumRenderTasks(); + vec2i taskStart(taskID % numRenderTasks.x, taskID / numRenderTasks.x); + return taskStart * getRenderTaskSize(); } -float LocalFrameBuffer::tileError(const vec2i &tile) +float LocalFrameBuffer::taskError(const uint32_t taskID) const { - return tileErrorRegion[tile]; + return taskErrorRegion[taskID]; } void LocalFrameBuffer::beginFrame() @@ -196,7 +270,7 @@ void LocalFrameBuffer::endFrame( imageOps.end(), [](std::unique_ptr &p) { p->endFrame(); }); - frameVariance = tileErrorRegion.refine(errorThreshold); + frameVariance = taskErrorRegion.refine(errorThreshold); } const void *LocalFrameBuffer::mapBuffer(OSPFrameBufferChannel channel) @@ -216,6 +290,15 @@ const void *LocalFrameBuffer::mapBuffer(OSPFrameBufferChannel channel) case OSP_FB_ALBEDO: buf = getDataSafe(albedoBuffer); break; + case OSP_FB_ID_PRIMITIVE: + buf = getDataSafe(primitiveIDBuffer); + break; + case OSP_FB_ID_OBJECT: + buf = getDataSafe(objectIDBuffer); + break; + case OSP_FB_ID_INSTANCE: + buf = getDataSafe(instanceIDBuffer); + break; default: break; } diff --git a/modules/cpu/fb/LocalFB.h b/modules/cpu/fb/LocalFB.h index d8adf2a88d..451625e6c2 100644 --- a/modules/cpu/fb/LocalFB.h +++ b/modules/cpu/fb/LocalFB.h @@ -1,40 +1,71 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray #include "fb/FrameBuffer.h" -#include "fb/TileError.h" +#include "fb/TaskError.h" // rkcommon #include "rkcommon/containers/AlignedVector.h" +// ispc shared +#include "LocalFBShared.h" +#include "TileShared.h" namespace ospray { -struct OSPRAY_SDK_INTERFACE LocalFrameBuffer : public FrameBuffer +struct SparseFrameBuffer; + +struct OSPRAY_SDK_INTERFACE LocalFrameBuffer + : public AddStructShared { LocalFrameBuffer(const vec2i &size, ColorBufferFormat colorBufferFormat, const uint32 channels); + virtual ~LocalFrameBuffer() override = default; virtual void commit() override; - //! \brief common function to help printf-debugging - /*! \detailed Every derived class should override this! */ + // Return the number of render tasks in the x and y direction + // This is the kernel launch dims to render the image + virtual vec2i getNumRenderTasks() const override; + + virtual uint32_t getTotalRenderTasks() const override; + + virtual utility::ArrayView getRenderTaskIDs() override; + + // common function to help printf-debugging, every derived class should + // override this! virtual std::string toString() const override; - void setTile(Tile &tile) override; - int32 accumID(const vec2i &tile) override; - float tileError(const vec2i &tile) override; + float taskError(const uint32_t taskID) const override; + void beginFrame() override; + void endFrame(const float errorThreshold, const Camera *camera) override; const void *mapBuffer(OSPFrameBufferChannel channel) override; + void unmap(const void *mappedMem) override; + void clear() override; - //// Data //// + /* Write the tile into this framebuffer's row-major storage. This does not + * perform accumulation or buffering, data is taken directly from the tile and + * written to the row-major image stored by the LocalFrameBuffer + * Safe to call in parallel from multiple threads, as long as each thread is + * writing different tiles + */ + void writeTiles(const containers::AlignedVector &tiles); + + /* Write the tiles of the sparse fb into this framebuffer's row-major storage. + * Will also copy error data from the sparseFb the full framebuffer task error + * buffer, if variance buffer is enabled. + * Safe to call in parallel from multiple threads, as long as each thread is + * writing different tiles + */ + void writeTiles(const SparseFrameBuffer *sparseFb); // NOTE: All per-pixel data is only allocated if the corresponding channel // flag was passed on construction @@ -51,10 +82,23 @@ struct OSPRAY_SDK_INTERFACE LocalFrameBuffer : public FrameBuffer containers::AlignedVector normalBuffer; // accumulated, one RGB per pixel containers::AlignedVector albedoBuffer; - // holds accumID per tile, for adaptive accumulation - containers::AlignedVector tileAccumID; + // primitive ID, object ID, and instance ID + containers::AlignedVector primitiveIDBuffer; + containers::AlignedVector objectIDBuffer; + containers::AlignedVector instanceIDBuffer; + + protected: + vec2i getTaskStartPos(const uint32_t taskID) const; + + //// Data //// + + vec2i numRenderTasks; + std::vector renderTaskIDs; + + // holds accumID per render task, for adaptive accumulation + containers::AlignedVector taskAccumID; // holds error per tile and adaptive regions - TileError tileErrorRegion; + TaskError taskErrorRegion; }; } // namespace ospray diff --git a/modules/cpu/fb/LocalFB.ih b/modules/cpu/fb/LocalFB.ih deleted file mode 100644 index b62143ff37..0000000000 --- a/modules/cpu/fb/LocalFB.ih +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2009-2019 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "fb/FrameBuffer.ih" -#include "fb/Tile.ih" -#include "render/util.ih" - -/*! a Local FrameBuffer that stores all pixel values (color, depth, - accum) in a plain 2D array of pixels (one array per component) */ -struct LocalFB -{ - FrameBuffer super; /*!< superclass that we inherit from */ - void *colorBuffer; - uniform float *depthBuffer; - uniform vec4f *accumBuffer; - uniform vec4f *varianceBuffer; // accumulates every other sample, for variance - // estimation / stopping - uniform vec3f *normalBuffer; - uniform vec3f *albedoBuffer; - uniform int32 - *tileAccumID; //< holds accumID per tile, for adaptive accumulation - vec2i numTiles; -}; diff --git a/modules/cpu/fb/LocalFB.ispc b/modules/cpu/fb/LocalFB.ispc index 9c4a7e0fbe..b5e981d7f1 100644 --- a/modules/cpu/fb/LocalFB.ispc +++ b/modules/cpu/fb/LocalFB.ispc @@ -1,29 +1,34 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "LocalFB.ih" +#include "fb/FrameBuffer.ih" +#include "fb/Tile.ih" +// c++ shared +#include "LocalFBShared.h" -//! \brief write tile into the given frame buffer's color buffer -/*! \detailed this buffer _must_ exist when this fct is called, and it - _must_ have format 'name' */ +// write tile into the given frame buffer's color buffer, +// this buffer _must_ exist when this fct is called, and it +// _must_ have format 'name' #define template_writeTile(name, type, cvt) \ export void LocalFrameBuffer_writeTile_##name( \ - void *uniform _fb, uniform Tile &tile) \ + void *uniform _fb, const void *uniform _tile) \ { \ + Tile *uniform tile = (Tile * uniform) _tile; \ uniform LocalFB *uniform fb = (uniform LocalFB * uniform) _fb; \ uniform type *uniform color = (uniform type * uniform) fb->colorBuffer; \ if (!color) \ /* actually, this should never happen ... */ \ return; \ \ - color += (uniform uint64)tile.region.lower.y * fb->super.size.x; \ - VaryingTile *uniform varyTile = (VaryingTile * uniform) & tile; \ - for (uniform uint32 iiy = tile.region.lower.y; iiy < tile.region.upper.y; \ + color += (uniform uint64)tile->region.lower.y * fb->super.size.x; \ + VaryingTile *uniform varyTile = (VaryingTile * uniform) tile; \ + for (uniform uint32 iiy = tile->region.lower.y; \ + iiy < tile->region.upper.y; \ iiy++) { \ uniform uint32 chunkID = \ - (iiy - tile.region.lower.y) * (TILE_SIZE / programCount); \ - for (uint32 iix = tile.region.lower.x + programIndex; \ - iix < tile.region.upper.x; \ + (iiy - tile->region.lower.y) * (TILE_SIZE / programCount); \ + for (uint32 iix = tile->region.lower.x + programIndex; \ + iix < tile->region.upper.x; \ iix += programCount, chunkID++) { \ unmasked \ { \ @@ -49,203 +54,338 @@ inline vec4f cvt_nop(const vec4f &v) template_writeTile(RGBA32F, vec4f, cvt_nop); #undef template_writeTile -//! \brief accumulate tile into BOTH accum buffer AND tile. -/*! \detailed After this call, the frame buffer will contain 'prev - accum value + tile value', while the tile will contain '(prev - accum value + tile value)/numAccums' - return tile error - -Implementation based on -Dammertz et al., "A Hierarchical Automatic Stopping Condition for Monte Carlo -Global Illumination", WSCG 2010 */ -export uniform float LocalFrameBuffer_accumulateTile( - void *uniform _fb, uniform Tile &tile) +// Write the samples into the given frame buffers color buffer in the color +// buffer's format +#define template_writeSample(name, type, cvt) \ + inline void LocalFB_writeSample_##name( \ + LocalFB *uniform fb, vec4f &col, const int pixelID) \ + { \ + uniform type *uniform color = (uniform type * uniform) fb->colorBuffer; \ + if (!color) \ + /* actually, this should never happen ... */ \ + return; \ + \ + const type cvtCol = cvt(col); \ + color[pixelID] = cvtCol; \ + } + +template_writeSample(RGBA8, uint32, cvt_uint32); +template_writeSample(SRGBA, uint32, linear_to_srgba8); +template_writeSample(RGBA32F, vec4f, cvt_nop); +#undef template_writeSample + +/* Accumulates the screenSample color and alpha into the framebuffer's + * accumulation buffer. The accumulation buffer will store + * + * prevAccum + sampleValue + * + * while the returned current accumulated color will be + * + * (prevAccum + sampleValue) / numAccumulated + * + * I.e., the color to be written to the final framebuffer for display for + * the current frame + * + * Variance and error computation based based on + * Dammertz et al., "A Hierarchical Automatic Stopping Condition for Monte Carlo + * Global Illumination", WSCG 2010 + */ +inline vec4f LocalFB_accumulateColorSample(LocalFB *uniform fb, + const ScreenSample &screenSample, + const int pixelID, + uniform RenderTaskDesc &taskDesc) { - uniform LocalFB *uniform fb = (uniform LocalFB * uniform) _fb; uniform vec4f *uniform accum = fb->accumBuffer; - if (!accum) - return inf; - - VaryingTile *uniform varyTile = (VaryingTile * uniform) & tile; uniform vec4f *uniform variance = fb->varianceBuffer; + const uniform float accScale = rcpf(taskDesc.accumID + 1); + const uniform float accHalfScale = rcpf(taskDesc.accumID / 2 + 1); - const uniform float accScale = rcpf(tile.accumID + 1); - const uniform float accHalfScale = rcpf(tile.accumID / 2 + 1); - float err = 0.f; - - accum += (uniform uint64)tile.region.lower.y * fb->super.size.x; - if (variance) - variance += (uniform uint64)tile.region.lower.y * fb->super.size.x; + const vec4f sampleValue = make_vec4f(screenSample.rgb, screenSample.alpha); - for (uniform uint32 iiy = tile.region.lower.y; iiy < tile.region.upper.y; - iiy++) { - uniform uint32 chunkID = - (iiy - tile.region.lower.y) * (TILE_SIZE / programCount); + vec4f acc = make_vec4f(0.f); + if (taskDesc.accumID > 0) { + acc = accum[pixelID]; + } + acc = acc + sampleValue; + accum[pixelID] = acc; - for (uint32 iix = tile.region.lower.x + programIndex; - iix < tile.region.upper.x; - iix += programCount, chunkID++) { - /* TODO: rather than gathering, replace this code with - 'load4f's and swizzles */ - varying vec4f acc = make_vec4f(0.f); - if (tile.accumID > 0) - acc = accum[iix]; - unmasked - { - acc.x += varyTile->r[chunkID]; - acc.y += varyTile->g[chunkID]; - acc.z += varyTile->b[chunkID]; - acc.w += varyTile->a[chunkID]; - } - accum[iix] = acc; - acc = acc * accScale; - - // variance buffer accumulates every other frame - if (variance && (tile.accumID & 1) == 1) { - varying vec4f vari = make_vec4f(0.f); - if (tile.accumID > 1) - vari = variance[iix]; - unmasked - { - vari.x += varyTile->r[chunkID]; - vari.y += varyTile->g[chunkID]; - vari.z += varyTile->b[chunkID]; - vari.w += varyTile->a[chunkID]; - } - variance[iix] = vari; + acc = acc * accScale; - // invert alpha (bright alpha is more important) - const float den2 = reduce_add(make_vec3f(acc)) + (1.f - acc.w); - if (den2 > 0.0f) { - const vec4f diff = absf(acc - accHalfScale * vari); - err += reduce_add(diff) * rsqrtf(den2); - } - } + // Variance and error buffers accumulate every other frame to ensure we get a + // monotonically decreasing sequence of error values + if (variance && (taskDesc.accumID & 1)) { + vec4f vari = make_vec4f(0.f); + if (taskDesc.accumID > 1) { + vari = variance[pixelID]; + } + vari = vari + sampleValue; + variance[pixelID] = vari; - unmasked - { - varyTile->r[chunkID] = acc.x; - varyTile->g[chunkID] = acc.y; - varyTile->b[chunkID] = acc.z; - varyTile->a[chunkID] = acc.w; - } + float err = 0.f; + // Invert alpha (bright alpha is more important) + const float den2 = reduce_add(make_vec3f(acc)) + (1.f - acc.w); + if (den2 > 0.f) { + const vec4f diff = absf(acc - accHalfScale * vari); + err += reduce_add(diff) * rsqrtf(den2); } + // We sum over the task because we may have more pixels in the task than + // the SIMD width + taskDesc.error += reduce_add(err); + } + return acc; +} + +inline void LocalFB_accumulateDepth(LocalFB *uniform fb, + const float &sampleDepth, + const int pixelID, + const uniform int accumID) +{ + uniform float *uniform depth = (uniform float *uniform)fb->depthBuffer; + + float acc = accumID > 0 ? depth[pixelID] : inf; + depth[pixelID] = min(acc, sampleDepth); +} + +inline void LocalFB_accumulateAux(uniform vec3f *uniform auxBuffer, + const vec3f &sampleAux, + const int pixelID, + const uniform int accumID) +{ + const uniform float accScale = rcpf(accumID + 1); + + vec3f acc = accumID > 0 ? auxBuffer[pixelID] : make_vec3f(0.f); + acc = (acc * accumID + sampleAux) * accScale; + auxBuffer[pixelID] = acc; +} + +/* Write the samples into the framebuffer. Accumulates color (if accumulation is + * enabled) and writes aux channels (depth, normal, albedo) that the framebuffer + * has and writes the accumulated color in to the framebuffer for display. + */ +void LocalFB_accumulateSample(FrameBuffer *uniform _fb, + const varying ScreenSample &screenSample, + uniform RenderTaskDesc &taskDesc) +{ + LocalFB *uniform fb = (LocalFB * uniform) _fb; + const int pixelID = + screenSample.sampleID.x + fb->super.size.x * screenSample.sampleID.y; + + // Default final color is the current sample color, used if we don't have + // accumulation enabled + vec4f finalColor = make_vec4f(screenSample.rgb, screenSample.alpha); + if (fb->accumBuffer) { + finalColor = + LocalFB_accumulateColorSample(fb, screenSample, pixelID, taskDesc); + } + + float depth = inf; + if (fb->depthBuffer) { + LocalFB_accumulateDepth(fb, screenSample.z, pixelID, taskDesc.accumID); + + depth = fb->depthBuffer[pixelID]; + } + + vec3f normal = make_vec3f(0.f); + if (fb->normalBuffer) { + LocalFB_accumulateAux( + fb->normalBuffer, screenSample.normal, pixelID, taskDesc.accumID); + + normal = fb->normalBuffer[pixelID]; + } - accum += fb->super.size.x; - if (variance) - variance += fb->super.size.x; + vec3f albedo = make_vec3f(0.f); + if (fb->albedoBuffer) { + LocalFB_accumulateAux( + fb->albedoBuffer, screenSample.albedo, pixelID, taskDesc.accumID); + + albedo = fb->albedoBuffer[pixelID]; + } + + if (fb->primitiveIDBuffer) { + if (taskDesc.accumID == 0) + fb->primitiveIDBuffer[pixelID] = screenSample.primID; + } + + if (fb->objectIDBuffer) { + if (taskDesc.accumID == 0) + fb->objectIDBuffer[pixelID] = screenSample.geomID; + } + + if (fb->instanceIDBuffer) { + if (taskDesc.accumID == 0) + fb->instanceIDBuffer[pixelID] = screenSample.instID; } - const uniform vec2i tileIdx = tile.region.lower / TILE_SIZE; - const uniform int32 tileId = tileIdx.y * fb->numTiles.x + tileIdx.x; - fb->tileAccumID[tileId]++; + // Run any pixel ops for this pixel + // TODO: Best as inline in this kernel? Or a separate kernel? + finalColor = + FrameBuffer_runPixelOps(&fb->super, finalColor, depth, normal, albedo); - // error is also only updated every other frame to avoid alternating error - // (get a monotone sequence) - uniform float errf = inf; - if (variance && (tile.accumID & 1) == 1) { - uniform vec2i dia = tile.region.upper - tile.region.lower; - uniform float cntu = (uniform float)dia.x * dia.y; - // scaling factor to stay backward compatible to default TILE_SIZE=64 - errf = reduce_add(err) * rcp(cntu) * 64.f; + // Write the final color out to the color buffer in the color format + // requested by the app + if (fb->colorBuffer) { + switch (fb->super.colorBufferFormat) { + case OSP_FB_RGBA8: + LocalFB_writeSample_RGBA8(fb, finalColor, pixelID); + break; + case OSP_FB_SRGBA: + LocalFB_writeSample_SRGBA(fb, finalColor, pixelID); + break; + case OSP_FB_RGBA32F: + LocalFB_writeSample_RGBA32F(fb, finalColor, pixelID); + break; + default: + // Nothing to do for color format none + break; + } } - return errf; + + FrameBuffer_updateProgress(&fb->super, popcnt(lanemask())); } -// "accumulate" (using minimum) and write into depth buffer -export void LocalFrameBuffer_accumulateWriteDepthTile( - void *uniform _fb, const uniform Tile &tile) +uniform RenderTaskDesc LocalFB_getRenderTaskDesc( + FrameBuffer *uniform _fb, const uniform uint32 taskID) +{ + LocalFB *uniform fb = (LocalFB * uniform) _fb; + uniform RenderTaskDesc desc; + desc.taskID = taskID; + desc.accumID = fb->taskAccumID ? fb->taskAccumID[taskID] : 0; + desc.error = 0.f; + + uniform vec2i renderTaskSize = fb->super.renderTaskSize; + uniform vec2i taskStart = + make_vec2i(taskID % fb->numRenderTasks.x, taskID / fb->numRenderTasks.x); + desc.region.lower = taskStart * renderTaskSize; + desc.region.upper = min(desc.region.lower + renderTaskSize, fb->super.size); + return desc; +} + +void LocalFB_completeTask( + FrameBuffer *uniform _fb, const uniform RenderTaskDesc &taskDesc) +{ + LocalFB *uniform fb = (LocalFB * uniform) _fb; + + // Write error for the task every other frame to get a monotonically + // decreasing sequence of error values + if (fb->varianceBuffer && (taskDesc.accumID & 1)) { + // Scale to be backwards compatible with the old default tile/task + // size of 64x64 + const uniform vec2i dia = box_size(taskDesc.region); + const uniform float taskSize = (uniform float)dia.x * dia.y; + fb->taskRegionError[taskDesc.taskID] = + taskDesc.error * rcp(taskSize) * 64.f; + } + + // Increment accumID for this task + if (fb->taskAccumID) { + fb->taskAccumID[taskDesc.taskID] = taskDesc.accumID + 1; + } +} + +// Write the input tile into the row-major framebuffer's depth buffer +export void LocalFrameBuffer_writeDepthTile( + void *uniform _fb, const void *uniform _tile) { uniform LocalFB *uniform fb = (uniform LocalFB * uniform) _fb; - VaryingTile *uniform varyTile = (VaryingTile * uniform) & tile; + const Tile *uniform tile = (const Tile *uniform)_tile; + + VaryingTile *uniform varyTile = (VaryingTile * uniform) tile; uniform float *uniform depth = (uniform float *uniform)fb->depthBuffer; - depth += (uniform uint64)tile.region.lower.y * fb->super.size.x; + depth += (uniform uint64)tile->region.lower.y * fb->super.size.x; - for (uniform uint32 iiy = tile.region.lower.y; iiy < tile.region.upper.y; + for (uniform uint32 iiy = tile->region.lower.y; iiy < tile->region.upper.y; iiy++) { uniform uint32 chunkID = - (iiy - tile.region.lower.y) * (TILE_SIZE / programCount); + (iiy - tile->region.lower.y) * (TILE_SIZE / programCount); - for (uint32 iix = tile.region.lower.x + programIndex; - iix < tile.region.upper.x; + for (uint32 iix = tile->region.lower.x + programIndex; + iix < tile->region.upper.x; iix += programCount, chunkID++) { - varying float acc = inf; - if (tile.accumID > 0) - acc = depth[iix]; - unmasked - { - acc = min(acc, varyTile->z[chunkID]); - } - depth[iix] = acc; + depth[iix] = varyTile->z[chunkID]; } depth += fb->super.size.x; } } -// accumulate into a (valid) normal or albedo buffer -export void LocalFrameBuffer_accumulateAuxTile(void *uniform _fb, - const uniform Tile &tile, +// "accumulate" first frame only and write into buffer +export void LocalFrameBuffer_writeIDTile(void *uniform _fb, + const void *uniform _tile, + uniform uint32 *uniform dst, + const void *uniform src) +{ + uniform LocalFB *uniform fb = (uniform LocalFB * uniform) _fb; + const Tile *uniform tile = (const Tile *uniform)_tile; + VaryingTile *uniform varyTile = (VaryingTile * uniform) tile; + uniform uint32 *uniform buffer = + dst; //(uniform uint32 *uniform)fb->primitiveIDBuffer; + buffer += (uniform uint64)tile->region.lower.y * fb->super.size.x; + const void *uniform upid = src; //(const void* uniform)tile->pid; + const varying int32 *uniform pid = (const varying int32 *uniform)upid; + + for (uniform uint32 iiy = tile->region.lower.y; iiy < tile->region.upper.y; + iiy++) { + uniform uint32 chunkID = + (iiy - tile->region.lower.y) * (TILE_SIZE / programCount); + + for (uint32 iix = tile->region.lower.x + programIndex; + iix < tile->region.upper.x; + iix += programCount, chunkID++) { + if (tile->accumID == 0) { + varying uint32 val = -1; + unmasked + { + val = pid[chunkID]; + } + buffer[iix] = val; + } + } + buffer += fb->super.size.x; + } +} + +// Write a Tile's auxiliary buffer into the framebuffer's row major storage +export void LocalFrameBuffer_writeAuxTile(void *uniform _fb, + const void *uniform _tile, uniform vec3f *uniform aux, const void *uniform _ax, const void *uniform _ay, const void *uniform _az) { uniform LocalFB *uniform fb = (uniform LocalFB * uniform) _fb; + const Tile *uniform tile = (const Tile *uniform)_tile; const varying float *uniform ax = (const varying float *uniform)_ax; const varying float *uniform ay = (const varying float *uniform)_ay; const varying float *uniform az = (const varying float *uniform)_az; - const uniform float accumID = tile.accumID; - const uniform float accScale = rcpf(tile.accumID + 1); - aux += (uniform uint64)tile.region.lower.y * fb->super.size.x; + const uniform float accumID = tile->accumID; + const uniform float accScale = rcpf(tile->accumID + 1); + aux += (uniform uint64)tile->region.lower.y * fb->super.size.x; - for (uniform uint32 iiy = tile.region.lower.y; iiy < tile.region.upper.y; + for (uniform uint32 iiy = tile->region.lower.y; iiy < tile->region.upper.y; iiy++) { uniform uint32 chunkID = - (iiy - tile.region.lower.y) * (TILE_SIZE / programCount); + (iiy - tile->region.lower.y) * (TILE_SIZE / programCount); - for (uint32 iix = tile.region.lower.x + programIndex; - iix < tile.region.upper.x; + for (uint32 iix = tile->region.lower.x + programIndex; + iix < tile->region.upper.x; iix += programCount, chunkID++) { - varying vec3f acc = make_vec3f(0.f); - if (tile.accumID > 0) - acc = aux[iix]; - unmasked - { - acc.x = (acc.x * accumID + ax[chunkID]) * accScale; - acc.y = (acc.y * accumID + ay[chunkID]) * accScale; - acc.z = (acc.z * accumID + az[chunkID]) * accScale; - } - aux[iix] = acc; + aux[iix] = make_vec3f(ax[chunkID], ay[chunkID], az[chunkID]); } - aux += fb->super.size.x; } } -export void *uniform LocalFrameBuffer_create(const uniform uint32 size_x, - const uniform uint32 size_y, - uniform int32 colorBufferFormat, - void *uniform colorBuffer, - void *uniform depthBuffer, - void *uniform accumBuffer, - void *uniform varianceBuffer, - void *uniform normalBuffer, - void *uniform albedoBuffer, - void *uniform tileAccumID) +export void *uniform LocalFrameBuffer_accumulateSample_addr() +{ + return LocalFB_accumulateSample; +} + +export void *uniform LocalFrameBuffer_getRenderTaskDesc_addr() +{ + return LocalFB_getRenderTaskDesc; +} + +export void *uniform LocalFrameBuffer_completeTask_addr() { - uniform LocalFB *uniform self = uniform new uniform LocalFB; - FrameBuffer_Constructor(&self->super); - FrameBuffer_set(&self->super, size_x, size_y, colorBufferFormat); - - self->colorBuffer = colorBuffer; - self->depthBuffer = (uniform float *uniform)depthBuffer; - self->accumBuffer = (uniform vec4f * uniform) accumBuffer; - self->varianceBuffer = (uniform vec4f * uniform) varianceBuffer; - self->normalBuffer = (uniform vec3f * uniform) normalBuffer; - self->albedoBuffer = (uniform vec3f * uniform) albedoBuffer; - self->numTiles = (self->super.size + (TILE_SIZE - 1)) / TILE_SIZE; - self->tileAccumID = (uniform int32 * uniform) tileAccumID; - - return self; + return LocalFB_completeTask; } diff --git a/modules/cpu/fb/LocalFBShared.h b/modules/cpu/fb/LocalFBShared.h new file mode 100644 index 0000000000..0487be59a7 --- /dev/null +++ b/modules/cpu/fb/LocalFBShared.h @@ -0,0 +1,52 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "FrameBufferShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +// a Local FrameBuffer that stores all pixel values (color, depth, +// accum) in a plain 2D array of pixels (one array per component) +struct LocalFB +{ + FrameBuffer super; // superclass that we inherit from + void *colorBuffer; + float *depthBuffer; + vec4f *accumBuffer; + + // accumulates every other sample, for variance estimation / stopping + vec4f *varianceBuffer; + vec3f *normalBuffer; + vec3f *albedoBuffer; + // holds accumID per tile, for adaptive accumulation + int32 *taskAccumID; + float *taskRegionError; + vec2i numRenderTasks; + uint32 *primitiveIDBuffer; + uint32 *objectIDBuffer; + uint32 *instanceIDBuffer; + +#ifdef __cplusplus + LocalFB() + : colorBuffer(nullptr), + depthBuffer(nullptr), + accumBuffer(nullptr), + varianceBuffer(nullptr), + normalBuffer(nullptr), + albedoBuffer(nullptr), + taskAccumID(nullptr), + taskRegionError(nullptr), + numRenderTasks(0), + primitiveIDBuffer(nullptr), + objectIDBuffer(nullptr), + instanceIDBuffer(nullptr) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/fb/RenderTaskDesc.ih b/modules/cpu/fb/RenderTaskDesc.ih new file mode 100644 index 0000000000..352e4beca4 --- /dev/null +++ b/modules/cpu/fb/RenderTaskDesc.ih @@ -0,0 +1,14 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "rkcommon/math/box.ih" + +struct RenderTaskDesc +{ + box2i region; // screen region that this corresponds to + uint32 taskID; + int accumID; + float error; +}; diff --git a/modules/cpu/fb/SparseFB.cpp b/modules/cpu/fb/SparseFB.cpp new file mode 100644 index 0000000000..235cfbcf93 --- /dev/null +++ b/modules/cpu/fb/SparseFB.cpp @@ -0,0 +1,261 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "SparseFB.h" +#include +#include +#include "ImageOp.h" +#include "fb/SparseFB_ispc.h" +#include "render/util.h" +#include "rkcommon/common.h" + +namespace ospray { + +SparseFrameBuffer::SparseFrameBuffer(const vec2i &_size, + ColorBufferFormat _colorBufferFormat, + const uint32 channels, + const std::vector &_tileIDs, + const bool overrideUseTaskAccumIDs) + : AddStructShared(_size, _colorBufferFormat, channels), + useTaskAccumIDs((channels & OSP_FB_ACCUM) || overrideUseTaskAccumIDs), + totalTiles(divRoundUp(size, vec2i(TILE_SIZE))) +{ + if (size.x <= 0 || size.y <= 0) { + throw std::runtime_error( + "local framebuffer has invalid size. Dimensions must be greater than " + "0"); + } + + if (!_tileIDs.empty()) { + setTiles(_tileIDs); + } +} + +SparseFrameBuffer::SparseFrameBuffer(const vec2i &_size, + ColorBufferFormat _colorBufferFormat, + const uint32 channels, + const bool overrideUseTaskAccumIDs) + : AddStructShared(_size, _colorBufferFormat, channels), + useTaskAccumIDs((channels & OSP_FB_ACCUM) || overrideUseTaskAccumIDs), + totalTiles(divRoundUp(size, vec2i(TILE_SIZE))) +{ + if (size.x <= 0 || size.y <= 0) { + throw std::runtime_error( + "local framebuffer has invalid size. Dimensions must be greater than " + "0"); + } +} + +void SparseFrameBuffer::commit() +{ + FrameBuffer::commit(); + + imageOps.clear(); + if (imageOpData) { + FrameBufferView fbv( + this, getColorBufferFormat(), nullptr, nullptr, nullptr, nullptr); + + // Sparse framebuffer cannot execute frame operations because it doesn't + // have the full framebuffer. This is handled by the parent object managing + // the set of sparse framebuffer's, so here we just ignore them + for (auto &&obj : *imageOpData) { + if (dynamic_cast(obj)) { + imageOps.push_back(obj->attach(fbv)); + } + } + } + prepareImageOps(); +} + +vec2i SparseFrameBuffer::getNumRenderTasks() const +{ + return numRenderTasks; +} + +uint32_t SparseFrameBuffer::getTotalRenderTasks() const +{ + return numRenderTasks.product(); +} + +utility::ArrayView SparseFrameBuffer::getRenderTaskIDs() +{ + return utility::ArrayView(renderTaskIDs); +} + +std::string SparseFrameBuffer::toString() const +{ + return "ospray::SparseFrameBuffer"; +} + +float SparseFrameBuffer::taskError(const uint32_t taskID) const +{ + return taskErrorBuffer[taskID]; +} + +void SparseFrameBuffer::setTaskError(const uint32_t taskID, const float error) +{ + taskErrorBuffer[taskID] = error; +} + +void SparseFrameBuffer::setTaskAccumID(const uint32_t taskID, const int accumID) +{ + taskAccumID[taskID] = accumID; +} + +void SparseFrameBuffer::beginFrame() +{ + FrameBuffer::beginFrame(); + + for (auto &tile : tiles) { + tile.accumID = getFrameID(); + } + + std::for_each(imageOps.begin(), + imageOps.end(), + [](std::unique_ptr &p) { p->beginFrame(); }); +} + +void SparseFrameBuffer::endFrame(const float, const Camera *) +{ + std::for_each(imageOps.begin(), + imageOps.end(), + [](std::unique_ptr &p) { p->endFrame(); }); +} + +const void *SparseFrameBuffer::mapBuffer(OSPFrameBufferChannel) +{ + return nullptr; +} + +void SparseFrameBuffer::unmap(const void *) {} + +void SparseFrameBuffer::clear() +{ + // we increment at the start of the frame + getSh()->super.frameID = -1; + + // We only need to reset the accumID, SparseFB_accumulateWriteSample will + // handle overwriting the image when accumID == 0 + std::fill(taskAccumID.begin(), taskAccumID.end(), 0); + + // also clear the task error buffer if present + if (hasVarianceBuffer) { + std::fill(taskErrorBuffer.begin(), taskErrorBuffer.end(), inf); + } +} + +const containers::AlignedVector &SparseFrameBuffer::getTiles() const +{ + return tiles; +} + +const std::vector &SparseFrameBuffer::getTileIDs() const +{ + return tileIDs; +} + +uint32_t SparseFrameBuffer::getTileIndexForTask(uint32_t taskID) const +{ + // Find which tile this task falls into + // tileIdx -> index in the SparseFB's list of tiles + return taskID / getNumTasksPerTile(); +} + +void SparseFrameBuffer::setTiles(const std::vector &_tileIDs) +{ + // (Re-)configure the sparse framebuffer based on the tileIDs we're passed + tileIDs = _tileIDs; + numRenderTasks = + vec2i(tileIDs.size() * TILE_SIZE, TILE_SIZE) / getRenderTaskSize(); + + if (hasVarianceBuffer) { + taskErrorBuffer.resize(numRenderTasks.long_product()); + std::fill(taskErrorBuffer.begin(), taskErrorBuffer.end(), inf); + } + + tiles.resize(tileIDs.size()); + const vec2f rcpSize = rcp(vec2f(size)); + for (size_t i = 0; i < tileIDs.size(); ++i) { + vec2i tilePos; + tilePos.x = tileIDs[i] % totalTiles.x; + tilePos.y = tileIDs[i] / totalTiles.x; + + tiles[i].fbSize = size; + tiles[i].rcp_fbSize = rcpSize; + tiles[i].region.lower = tilePos * TILE_SIZE; + tiles[i].region.upper = min(tiles[i].region.lower + TILE_SIZE, size); + tiles[i].accumID = 0; + } + + const size_t numPixels = tileIDs.size() * TILE_SIZE * TILE_SIZE; + if (hasVarianceBuffer) { + varianceBuffer.resize(numPixels); + } + + if (hasAccumBuffer) { + accumulationBuffer.resize(numPixels); + } + + if (hasAccumBuffer || useTaskAccumIDs) { + taskAccumID.resize(getTotalRenderTasks(), 0); + } + + // TODO: Should find a better way for allowing sparse task id sets + // here we have this array b/c the tasks will be filtered down based on + // variance termination + renderTaskIDs.resize(getTotalRenderTasks()); + for (uint32_t i = 0; i < getTotalRenderTasks(); ++i) { + renderTaskIDs[i] = i; + } + + const uint32_t nTasksPerTile = getNumTasksPerTile(); + + // Sort each tile's tasks in Z order + rkcommon::tasking::parallel_for(tiles.size(), [&](const size_t i) { + std::sort(renderTaskIDs.begin() + i * nTasksPerTile, + renderTaskIDs.begin() + (i + 1) * nTasksPerTile, + [&](const uint32_t &a, const uint32_t &b) { + const vec2i p_a = getTaskPosInTile(a); + const vec2i p_b = getTaskPosInTile(b); + return interleaveZOrder(p_a.x, p_a.y) + < interleaveZOrder(p_b.x, p_b.y); + }); + }); + + clear(); + + getSh()->super.accumulateSample = + ispc::SparseFrameBuffer_accumulateSample_addr(); + getSh()->super.getRenderTaskDesc = + ispc::SparseFrameBuffer_getRenderTaskDesc_addr(); + getSh()->super.completeTask = ispc::SparseFrameBuffer_completeTask_addr(); + + getSh()->numRenderTasks = numRenderTasks; + getSh()->totalTiles = totalTiles; + + getSh()->tiles = tiles.data(); + getSh()->numTiles = tiles.size(); + + getSh()->taskAccumID = getDataSafe(taskAccumID); + getSh()->accumulationBuffer = getDataSafe(accumulationBuffer); + getSh()->varianceBuffer = getDataSafe(varianceBuffer); + getSh()->taskRegionError = getDataSafe(taskErrorBuffer); +} + +vec2i SparseFrameBuffer::getTaskPosInTile(const uint32_t taskID) const +{ + // Find where this task is supposed to render within this tile + const vec2i tasksPerTile = vec2i(TILE_SIZE) / getRenderTaskSize(); + const uint32 taskTileID = taskID % (tasksPerTile.x * tasksPerTile.y); + vec2i taskStart(taskTileID % tasksPerTile.x, taskTileID / tasksPerTile.x); + return taskStart * getRenderTaskSize(); +} + +uint32_t SparseFrameBuffer::getNumTasksPerTile() const +{ + const vec2i tileDims(TILE_SIZE); + const vec2i tasksPerTile = tileDims / getRenderTaskSize(); + return tasksPerTile.long_product(); +} + +} // namespace ospray diff --git a/modules/cpu/fb/SparseFB.h b/modules/cpu/fb/SparseFB.h new file mode 100644 index 0000000000..6b9c058112 --- /dev/null +++ b/modules/cpu/fb/SparseFB.h @@ -0,0 +1,142 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "TileShared.h" +#include "fb/FrameBuffer.h" +#include "fb/LocalFB.h" +#include "fb/SparseFBShared.h" +#include "fb/TaskError.h" +#include "rkcommon/containers/AlignedVector.h" + +namespace ospray { +/* The sparse framebuffer stores a subset of tiles of a larger framebuffer + * to allow rendering tasks to directly write to this allocated tile memory, + * rather than requiring on the fly allocation of tiles. The sparse framebuffer + * is used as a component of a "parent" framebuffer that is responsible for + * distributing the full image among different sparse framebuffers and + * collecting the tiles from them into a complete image in some way. + * + * The sparse framebuffer doesn't store the entire image data and thus doesn't + * support frame/tile operations or mapping. + */ +struct OSPRAY_SDK_INTERFACE SparseFrameBuffer + : public AddStructShared +{ + /* Create a sparse framebuffer holding the tiles specified in tileIDs + * overrideUseTaskAccumIDs specifies whether task accumIDs should still + * be used even if the sparsefb is not performing accumulation buffering + */ + SparseFrameBuffer(const vec2i &size, + ColorBufferFormat colorBufferFormat, + const uint32 channels, + const std::vector &tileIDs, + const bool overrideUseTaskAccumIDs = false); + + /* Create a sparse framebuffer that stores no image tiles. Tiles can be added + * to the empty sparse framebuffer by calling setTiles + * overrideUseTaskAccumIDs specifies whether task accumIDs should still + * be used even if the sparsefb is not performing accumulation buffering + */ + SparseFrameBuffer(const vec2i &size, + ColorBufferFormat colorBufferFormat, + const uint32 channels, + const bool overrideUseTaskAccumIDs = false); + + virtual void commit() override; + + // Return the number of render tasks in the x and y direction + // This is the kernel launch dims to render the image + virtual vec2i getNumRenderTasks() const override; + + virtual uint32_t getTotalRenderTasks() const override; + + virtual utility::ArrayView getRenderTaskIDs() override; + + //! \brief common function to help printf-debugging + /*! \detailed Every derived class should override this! */ + virtual std::string toString() const override; + + float taskError(const uint32_t taskID) const override; + + /* Set the error for a given task, used by the parent framebuffer managing the + * sparse framebuffers to sync error computed over the entire image + */ + void setTaskError(const uint32_t taskID, const float error); + + /* Set the accum ID for a given task, used by the parent framebuffer managing + * the sparse framebuffers to sync the task accumulation IDs. + */ + void setTaskAccumID(const uint32_t taskID, const int accumID); + + void beginFrame() override; + + void endFrame(const float errorThreshold, const Camera *camera) override; + + // Mapping sparse framebuffers is not supported, will return null + const void *mapBuffer(OSPFrameBufferChannel channel) override; + + void unmap(const void *mappedMem) override; + + void clear() override; + + const containers::AlignedVector &getTiles() const; + + const std::vector &getTileIDs() const; + + // Get the index of the tile in the tile ID and Tiles lists that this task + // falls into + uint32_t getTileIndexForTask(uint32_t taskID) const; + + /* Change the tiles stored in this SparseFrameBuffer, re-using the existing + * storage. New tiles will be allocated if the size of the tileIDs passed + * exceeds those currently stored in the SparseFrameBuffer + */ + void setTiles(const std::vector &tileIDs); + + //// Data //// + protected: + // Get the position of a task in its tile + vec2i getTaskPosInTile(const uint32_t taskID) const; + + uint32_t getNumTasksPerTile() const; + + // The tiles in this framebuffer + containers::AlignedVector tiles; + + // Accumulation buffer for the tile colors for accumulation buffering. The + // rgba data in the Tiles stores the final color for display in float format, + // while the accumulation buffer is used for progressive refinement + std::vector accumulationBuffer; + + // Variance data for the image, stored in tiled order with one RGBA value per + // pixel, accumulates every other sample, for variance estimation + std::vector varianceBuffer; + + // holds accumID per render task, for adaptive accumulation + std::vector taskAccumID; + + // The sparsefb can also use task accum IDs without accumulation buffering, + // when it's being used as a component of another framebuffer. + // this is true by default when created with OSP_FB_ACCUM + bool useTaskAccumIDs; + + std::vector tileIDs; + + // Total number of tiles that the framebuffer is divided into, including those + // not owned by this sparsefb + vec2i totalTiles; + + // Total number of render tasks that the framebuffer is divided into, + // including those not owned by this sparsefb + vec2i numRenderTasks; + + // holds error per task for each tile, stored in tiled order. + // The SparseFB doesn't do its own error refinement since it doesn't have + // access to error data for the entire framebuffer + std::vector taskErrorBuffer; + + std::vector renderTaskIDs; +}; +} // namespace ospray diff --git a/modules/cpu/fb/SparseFB.ih b/modules/cpu/fb/SparseFB.ih new file mode 100644 index 0000000000..7ae39ea2fa --- /dev/null +++ b/modules/cpu/fb/SparseFB.ih @@ -0,0 +1,18 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "SparseFBShared.h" +#include "fb/Tile.ih" + +inline uniform uint32 SparseFB_getTileIndexForTask( + const SparseFB *uniform fb, const uniform uint32 taskID) +{ + // Find which tile this task falls into + const uniform vec2i tileDims = make_vec2i(TILE_SIZE); + const uniform vec2i tasksPerTile = tileDims / fb->super.renderTaskSize; + const uniform int nTasksPerTile = tasksPerTile.x * tasksPerTile.y; + // tileIdx -> index in the SparseFB's list of tiles + return taskID / nTasksPerTile; +} diff --git a/modules/cpu/fb/SparseFB.ispc b/modules/cpu/fb/SparseFB.ispc new file mode 100644 index 0000000000..d8fe7e1564 --- /dev/null +++ b/modules/cpu/fb/SparseFB.ispc @@ -0,0 +1,221 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "SparseFB.ih" +#include "fb/FrameBuffer.ih" +#include "fb/RenderTaskDesc.ih" +#include "fb/Tile.ih" +#include "ospray/OSPEnums.h" +#include "render/Renderer.ih" +#include "render/util.ih" + +/* Return the position of the screen sample within its tile + */ +inline vec2i SparseFB_getTilePixelPos(SparseFB *uniform fb, + const ScreenSample &screenSample, + const uniform uint32 tileIdx) +{ + uniform vec2i tilePos = fb->tiles[tileIdx].region.lower; + const vec2i tilePixelPos = + make_vec2i(screenSample.sampleID.x, screenSample.sampleID.y) - tilePos; + return tilePixelPos; +} + +/* Accumulates the screenSample color and alpha into the framebuffer's + accumulation buffer. The accumulation buffer will store + + prevAccum + sampleValue + + while the returned current accumulated color will be + + (prevAccum + sampleValue) / numAccumulated + + I.e., the color to be written to the final framebuffer for display for + the current frame + + tileIdx is the index of the tile that this task/sample belongs to, as + computed by SparseFB_getTileIndexForTask. sampleTilePos is the position of + the sample within this tile, via SparseFB_getTilePixelPos + */ +inline void SparseFB_accumulateTileSample(SparseFB *uniform fb, + const ScreenSample &screenSample, + const uniform uint32 tileIdx, + const vec2i &sampleTilePos, + uniform RenderTaskDesc &taskDesc) +{ + uniform vec4f *uniform accumulation = fb->accumulationBuffer; + uniform vec4f *uniform variance = fb->varianceBuffer; + // The location of this pixel's data within the tiled accumulation and + // variance buffers + const uint32 varianceAccumIndex = tileIdx * TILE_SIZE * TILE_SIZE + + sampleTilePos.x + TILE_SIZE * sampleTilePos.y; + const uint32 tilePixelIdx = sampleTilePos.x + TILE_SIZE * sampleTilePos.y; + + const uniform float accScale = rcpf(taskDesc.accumID + 1); + const uniform float accHalfScale = rcpf(taskDesc.accumID / 2 + 1); + + const vec4f sampleValue = make_vec4f(screenSample.rgb, screenSample.alpha); + uniform Tile *uniform tile = fb->tiles + tileIdx; + + vec4f acc = sampleValue; + float depth = screenSample.z; + vec3f normal = screenSample.normal; + vec3f albedo = screenSample.albedo; + + if (accumulation) { + if (taskDesc.accumID > 0) { + acc = accumulation[varianceAccumIndex] + sampleValue; + + depth = min(tile->z[tilePixelIdx], screenSample.z); + + normal = make_vec3f(tile->nx[tilePixelIdx], + tile->ny[tilePixelIdx], + tile->nz[tilePixelIdx]); + normal = (normal * taskDesc.accumID + screenSample.normal) * accScale; + + albedo = make_vec3f(tile->ar[tilePixelIdx], + tile->ag[tilePixelIdx], + tile->ab[tilePixelIdx]); + albedo = (albedo * taskDesc.accumID + screenSample.albedo) * accScale; + } + accumulation[varianceAccumIndex] = acc; + acc = acc * accScale; + } + + const vec4f finalColor = + FrameBuffer_runPixelOps(&fb->super, acc, depth, normal, albedo); + + tile->r[tilePixelIdx] = finalColor.x; + tile->g[tilePixelIdx] = finalColor.y; + tile->b[tilePixelIdx] = finalColor.z; + tile->a[tilePixelIdx] = finalColor.w; + + tile->z[tilePixelIdx] = depth; + + tile->nx[tilePixelIdx] = normal.x; + tile->ny[tilePixelIdx] = normal.y; + tile->nz[tilePixelIdx] = normal.z; + + tile->ar[tilePixelIdx] = albedo.x; + tile->ag[tilePixelIdx] = albedo.y; + tile->ab[tilePixelIdx] = albedo.z; + + tile->pid[tilePixelIdx] = screenSample.primID; + tile->gid[tilePixelIdx] = screenSample.geomID; + tile->iid[tilePixelIdx] = screenSample.instID; + + // Variance and error accumulates every other frame to ensure we get a + // monotonically decreasing sequence of error values + if (variance && (taskDesc.accumID & 1)) { + vec4f vari = make_vec4f(0.f); + if (taskDesc.accumID > 1) { + vari = variance[varianceAccumIndex]; + } + vari = vari + sampleValue; + variance[varianceAccumIndex] = vari; + + float err = 0.f; + const float den2 = reduce_add(make_vec3f(acc)) + (1.f - acc.w); + if (den2 > 0.f) { + const vec4f diff = absf(acc - accHalfScale * vari); + err += reduce_add(diff) * rsqrt(den2); + } + // We sum over the task because we may have more pixels in the task than + // SIMD width + taskDesc.error += reduce_add(err); + } +} + +void SparseFB_accumulateSample(FrameBuffer *uniform _fb, + const varying ScreenSample &screenSample, + uniform RenderTaskDesc &taskDesc) +{ + SparseFB *uniform fb = (SparseFB * uniform) _fb; + + // tileIdx -> index in the SparseFB's list of tiles + const uniform uint32 tileIdx = + SparseFB_getTileIndexForTask(fb, taskDesc.taskID); + const vec2i sampleTilePos = + SparseFB_getTilePixelPos(fb, screenSample, tileIdx); + + SparseFB_accumulateTileSample( + fb, screenSample, tileIdx, sampleTilePos, taskDesc); + + FrameBuffer_updateProgress(&fb->super, popcnt(lanemask())); +} + +uniform RenderTaskDesc SparseFB_getRenderTaskDesc( + FrameBuffer *uniform _fb, const uniform uint32 taskID) +{ + SparseFB *uniform fb = (SparseFB * uniform) _fb; + // Map to the tile and then the set of pixels within that tile. + uniform RenderTaskDesc desc; + desc.taskID = taskID; + desc.accumID = fb->taskAccumID ? fb->taskAccumID[taskID] : 0; + desc.error = 0.f; + + const uniform uint32 tileIdx = SparseFB_getTileIndexForTask(fb, taskID); + + // Find where this task is supposed to render within this tile + const uniform vec2i tileDims = make_vec2i(TILE_SIZE); + const uniform vec2i tasksPerTile = tileDims / fb->super.renderTaskSize; + const uniform uint32 taskTileID = taskID % (tasksPerTile.x * tasksPerTile.y); + + uniform vec2i taskStart = + make_vec2i(taskTileID % tasksPerTile.x, taskTileID / tasksPerTile.x); + desc.region.lower = taskStart * fb->super.renderTaskSize; + desc.region.upper = desc.region.lower + fb->super.renderTaskSize; + + // Offset the task's region by the tile location + const uniform vec2i tilePos = fb->tiles[tileIdx].region.lower; + desc.region.lower = desc.region.lower + tilePos; + desc.region.upper = min(desc.region.upper + tilePos, fb->super.size); + + // TODO: In the end, shouldn't generate these out of bounds tasks for the + // padded framebuffer region? For now just mark them as having no error + // In the past the tiled load balancer would also generate these though, with + // how we padded out to the tile dims + if (isEmpty(desc.region) && fb->taskRegionError) { + fb->taskRegionError[taskID] = 0.f; + } + + return desc; +} + +void SparseFB_completeTask( + FrameBuffer *uniform _fb, const uniform RenderTaskDesc &taskDesc) +{ + SparseFB *uniform fb = (SparseFB * uniform) _fb; + + // Write error for the task every other frame to get a monotonically + // decreasing sequence of error values + if (fb->varianceBuffer && (taskDesc.accumID & 1)) { + // Scale to be backwards compatible with the old default tile/task + // size of 64x64 + const uniform vec2i dia = taskDesc.region.upper - taskDesc.region.lower; + const uniform float taskSize = dia.x * dia.y; + + fb->taskRegionError[taskDesc.taskID] = + taskDesc.error * rcp(taskSize) * 64.f; + } + + // Increment accumID for this task + if (fb->taskAccumID) { + fb->taskAccumID[taskDesc.taskID] = taskDesc.accumID + 1; + } +} + +export void *uniform SparseFrameBuffer_accumulateSample_addr() +{ + return SparseFB_accumulateSample; +} + +export void *uniform SparseFrameBuffer_getRenderTaskDesc_addr() +{ + return SparseFB_getRenderTaskDesc; +} + +export void *uniform SparseFrameBuffer_completeTask_addr() +{ + return SparseFB_completeTask; +} diff --git a/modules/cpu/fb/SparseFBShared.h b/modules/cpu/fb/SparseFBShared.h new file mode 100644 index 0000000000..2a188f840b --- /dev/null +++ b/modules/cpu/fb/SparseFBShared.h @@ -0,0 +1,49 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "FrameBufferShared.h" +#include "TileShared.h" + +#ifdef __cplusplus +namespace ispc { +#else +#include "rkcommon/math/vec.ih" +#endif // __cplusplus + +// a SparseFrameBuffer stores a subset of the full framebuffer as Tiles +struct SparseFB +{ + // superclass that we inherit from + FrameBuffer super; + // Number of tasks being used to render the image in x & y + vec2i numRenderTasks; + // The total number of tiles that the framebuffer is divided into + vec2i totalTiles; + uint32 numTiles; + // Image data for the tiles in this SparseFrameBuffer + Tile *tiles; + // holds accumID per task region, for adaptive accumulation + int32 *taskAccumID; + // holds the accumulated color for each tile, tile's rgba stores the final + // color + vec4f *accumulationBuffer; + // accumulates every other sample, for variance estimation / stopping + vec4f *varianceBuffer; + // holds error per task region, for adaptive accumulation + float *taskRegionError; + +#ifdef __cplusplus + SparseFB() + : tiles(nullptr), + taskAccumID(nullptr), + accumulationBuffer(nullptr), + varianceBuffer(nullptr), + taskRegionError(nullptr) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/fb/TileError.cpp b/modules/cpu/fb/TaskError.cpp similarity index 54% rename from modules/cpu/fb/TileError.cpp rename to modules/cpu/fb/TaskError.cpp index 17a620dbdf..b845938276 100644 --- a/modules/cpu/fb/TileError.cpp +++ b/modules/cpu/fb/TaskError.cpp @@ -1,61 +1,61 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "TileError.h" +#include "TaskError.h" #include namespace ospray { -TileError::TileError(const vec2i &_numTiles) - : numTiles(_numTiles), - tiles(_numTiles.x * _numTiles.y), - tileErrorBuffer(tiles) +TaskError::TaskError(const vec2i &_numTasks) + : numTasks(_numTasks), taskErrorBuffer(numTasks.long_product()) { // maximum number of regions: all regions are of size 3 are split in half - errorRegion.reserve(divRoundUp(tiles * 2, 3)); + errorRegion.reserve(divRoundUp(taskErrorBuffer.size() * 2, size_t(3))); clear(); } -void TileError::clear() +void TaskError::clear() { - for (int i = 0; i < tiles; i++) - tileErrorBuffer[i] = inf; + std::fill(taskErrorBuffer.begin(), taskErrorBuffer.end(), inf); errorRegion.clear(); - // initially create one region covering the complete image - errorRegion.push_back(box2i(vec2i(0), numTiles)); + // initially create one region covering the complete tile/image + errorRegion.push_back(box2i(vec2i(0), numTasks)); } -float TileError::operator[](const vec2i &tile) const +float TaskError::operator[](const int id) const { - if (tiles <= 0) + if (taskErrorBuffer.empty()) { return inf; + } - return tileErrorBuffer[tile.y * numTiles.x + tile.x]; + return taskErrorBuffer[id]; } -void TileError::update(const vec2i &tile, const float err) +void TaskError::update(const vec2i &task, const float err) { - if (tiles > 0) - tileErrorBuffer[tile.y * numTiles.x + tile.x] = err; + if (!taskErrorBuffer.empty()) { + taskErrorBuffer[task.y * numTasks.x + task.x] = err; + } } -float TileError::refine(const float errorThreshold) +float TaskError::refine(const float errorThreshold) { - if (tiles <= 0) + if (taskErrorBuffer.empty()) { return inf; + } float maxErr = 0.f; float sumActErr = 0.f; - int actTiles = 0; - for (int i = 0; i < tiles; i++) { - maxErr = std::max(maxErr, tileErrorBuffer[i]); - if (tileErrorBuffer[i] > errorThreshold) { - sumActErr += tileErrorBuffer[i]; - actTiles++; + int activeTasks = 0; + for (const auto &err : taskErrorBuffer) { + maxErr = std::max(maxErr, err); + if (err > errorThreshold) { + sumActErr += err; + activeTasks++; } } - const float error = actTiles ? sumActErr / actTiles : maxErr; + const float error = activeTasks ? sumActErr / activeTasks : maxErr; // process regions first, but don't process newly split regions again int regions = errorThreshold > 0.f ? errorRegion.size() : 0; @@ -65,25 +65,25 @@ float TileError::refine(const float errorThreshold) float maxErr = 0.f; for (int y = region.lower.y; y < region.upper.y; y++) for (int x = region.lower.x; x < region.upper.x; x++) { - int idx = y * numTiles.x + x; - err += tileErrorBuffer[idx]; - maxErr = std::max(maxErr, tileErrorBuffer[idx]); + int idx = y * numTasks.x + x; + err += taskErrorBuffer[idx]; + maxErr = std::max(maxErr, taskErrorBuffer[idx]); } if (maxErr > errorThreshold) { - // set all tiles of this region to >errorThreshold to enforce their + // set all tasks of this region to >errorThreshold to enforce their // refinement as a group const float minErr = nextafter(errorThreshold, inf); for (int y = region.lower.y; y < region.upper.y; y++) for (int x = region.lower.x; x < region.upper.x; x++) { - int idx = y * numTiles.x + x; - tileErrorBuffer[idx] = std::max(tileErrorBuffer[idx], minErr); + int idx = y * numTasks.x + x; + taskErrorBuffer[idx] = std::max(taskErrorBuffer[idx], minErr); } } const vec2i size = region.size(); const int area = reduce_mul(size); err /= area; // == avg if (err <= 4.f * errorThreshold) { // split region? - // if would just contain single tile after split or wholly done: remove + // if would just contain single task after split or wholly done: remove if (area <= 2 || maxErr <= errorThreshold) { regions--; errorRegion[i] = errorRegion[regions]; @@ -104,7 +104,15 @@ float TileError::refine(const float errorThreshold) } } } - return error; } + +float *TaskError::errorBuffer() +{ + if (taskErrorBuffer.empty()) { + return nullptr; + } + return taskErrorBuffer.data(); +} + } // namespace ospray diff --git a/modules/cpu/fb/TaskError.h b/modules/cpu/fb/TaskError.h new file mode 100644 index 0000000000..01de52a5af --- /dev/null +++ b/modules/cpu/fb/TaskError.h @@ -0,0 +1,43 @@ +// Copyright 2009 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include "common/OSPCommon.h" +#include "rkcommon/containers/AlignedVector.h" + +namespace ospray { + +/* manages error per tile and adaptive regions, for variance estimation + Implementation based on Dammertz et al., "A Hierarchical Automatic Stopping + Condition for Monte Carlo Global Illumination", WSCG 2010 */ +class OSPRAY_SDK_INTERFACE TaskError +{ + public: + TaskError(const vec2i &numTasks); + + // The default constructor will make an empty task error region + TaskError() = default; + + void clear(); + + float operator[](const int id) const; + + void update(const vec2i &task, const float error); + + float refine(const float errorThreshold); + + // Return the error buffer, or null if there are no tiles that error is + // tracked for + float *errorBuffer(); + + protected: + vec2i numTasks = vec2i(0); + // holds error per task + containers::AlignedVector taskErrorBuffer; + // image regions (in #tasks) that do not yet estimate the error on + // per-task basis + std::vector errorRegion; +}; +} // namespace ospray diff --git a/modules/cpu/fb/Tile.h b/modules/cpu/fb/Tile.h deleted file mode 100644 index 6b1ed69180..0000000000 --- a/modules/cpu/fb/Tile.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2009-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "common/OSPCommon.h" - -namespace ospray { - -static_assert(TILE_SIZE > 0 && (TILE_SIZE & (TILE_SIZE - 1)) == 0, - "OSPRay config error: TILE_SIZE must be a positive power of two."); - -//! a tile of pixels used by any tile-based renderer -/*! pixels in the tile are in a row-major TILE_SIZE x TILE_SIZE - pattern. the 'region' specifies which part of the screen this - tile belongs to: tile.lower is the lower-left coordinate of this - tile (and a multiple of TILE_SIZE); the 'upper' value may be - smaller than the upper-right edge of the "full" tile. - - note that a tile contains "all" of the values a renderer might - want to use. not all renderers nor all frame buffers will use - all those values; it's up to the renderer and frame buffer to - agree on which fields will be set. Similarly, the frame buffer - may actually use uchars, but the tile will always store - floats. */ -struct OSPRAY_SDK_INTERFACE __aligned(64) Tile -{ - region2i region; // screen region that this corresponds to - vec2i fbSize; // total frame buffer size, for the camera - vec2f rcp_fbSize; - int32 generation{0}; - int32 children{0}; - int32 sortOrder{0}; - int32 accumID; //!< how often has been accumulated into this tile - float pad[4]; //!< padding to match the ISPC-side layout - float r[TILE_SIZE * TILE_SIZE]; // 'red' component - float g[TILE_SIZE * TILE_SIZE]; // 'green' component - float b[TILE_SIZE * TILE_SIZE]; // 'blue' component - float a[TILE_SIZE * TILE_SIZE]; // 'alpha' component - float z[TILE_SIZE * TILE_SIZE]; // 'depth' component - float nx[TILE_SIZE * TILE_SIZE]; // normal x - float ny[TILE_SIZE * TILE_SIZE]; // normal y - float nz[TILE_SIZE * TILE_SIZE]; // normal z - float ar[TILE_SIZE * TILE_SIZE]; // albedo red - float ag[TILE_SIZE * TILE_SIZE]; // albedo green - float ab[TILE_SIZE * TILE_SIZE]; // albedo blue - - Tile() = default; - Tile(const vec2i &tile, const vec2i &fbsize, const int32 accumId) - : fbSize(fbsize), - rcp_fbSize(rcp(vec2f(fbsize))), - accumID(accumId) - { - region.lower = tile * TILE_SIZE; - region.upper = min(region.lower + TILE_SIZE, fbsize); - } -}; - -} // namespace ospray diff --git a/modules/cpu/fb/Tile.ih b/modules/cpu/fb/Tile.ih index 6b5ee70ddc..a999a54e37 100644 --- a/modules/cpu/fb/Tile.ih +++ b/modules/cpu/fb/Tile.ih @@ -1,61 +1,12 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#include "TileShared.h" #include "common/OSPCommon.ih" #include "rkcommon/math/box.ih" -/*! a screen tile. the memory layout of this class has to _exactly_ - match the (C++-)one in tile.h */ -struct Tile -{ - uniform range2i region; - uniform vec2i fbSize; - uniform vec2f rcp_fbSize; - uniform int32 generation; - uniform int32 children; - uniform int32 sortOrder; - uniform int32 accumID; - uniform float pad[4]; // padding to match the varying tile layout - uniform float r[TILE_SIZE * TILE_SIZE]; // red - uniform float g[TILE_SIZE * TILE_SIZE]; // green - uniform float b[TILE_SIZE * TILE_SIZE]; // blue - uniform float a[TILE_SIZE * TILE_SIZE]; // alpha - uniform float z[TILE_SIZE * TILE_SIZE]; // depth - uniform float nx[TILE_SIZE * TILE_SIZE]; // normal x - uniform float ny[TILE_SIZE * TILE_SIZE]; // normal y - uniform float nz[TILE_SIZE * TILE_SIZE]; // normal z - uniform float ar[TILE_SIZE * TILE_SIZE]; // albedo red - uniform float ag[TILE_SIZE * TILE_SIZE]; // albedo green - uniform float ab[TILE_SIZE * TILE_SIZE]; // albedo blue -}; - -struct VaryingTile -{ - uniform range2i region; // 4 ints - uniform vec2i fbSize; // 2 ints - uniform vec2f rcp_fbSize; // 2 floats - uniform int32 generation; - uniform int32 children; - uniform int32 sortOrder; - uniform int32 accumID; - uniform float pad[4]; // explicit padding to match on SSE, this padding is - // implicitly added on AVX and AVX512 to align the - // vectors though. We need it here to match on SSE - varying float r[TILE_SIZE * TILE_SIZE / programCount]; - varying float g[TILE_SIZE * TILE_SIZE / programCount]; - varying float b[TILE_SIZE * TILE_SIZE / programCount]; - varying float a[TILE_SIZE * TILE_SIZE / programCount]; - varying float z[TILE_SIZE * TILE_SIZE / programCount]; - varying float nx[TILE_SIZE * TILE_SIZE / programCount]; - varying float ny[TILE_SIZE * TILE_SIZE / programCount]; - varying float nz[TILE_SIZE * TILE_SIZE / programCount]; - varying float ar[TILE_SIZE * TILE_SIZE / programCount]; - varying float ag[TILE_SIZE * TILE_SIZE / programCount]; - varying float ab[TILE_SIZE * TILE_SIZE / programCount]; -}; - inline void setRGBA(uniform Tile &tile, const varying uint32 i, const varying vec3f rgb, diff --git a/modules/cpu/fb/TileError.h b/modules/cpu/fb/TileError.h deleted file mode 100644 index e54a7ef036..0000000000 --- a/modules/cpu/fb/TileError.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2009-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include "common/OSPCommon.h" -#include "rkcommon/containers/AlignedVector.h" - -namespace ospray { - -/* manages error per tile and adaptive regions, for variance estimation - Implementation based on Dammertz et al., "A Hierarchical Automatic Stopping - Condition for Monte Carlo Global Illumination", WSCG 2010 */ -class OSPRAY_SDK_INTERFACE TileError -{ - public: - TileError(const vec2i &numTiles); - - void clear(); - - float operator[](const vec2i &tile) const; - - void update(const vec2i &tile, const float error); - - float refine(const float errorThreshold); - - protected: - vec2i numTiles; - int tiles; - // holds error per tile - containers::AlignedVector tileErrorBuffer; - // image regions (in #tiles) which do not yet estimate the error on - // per-tile base - std::vector errorRegion; -}; -} // namespace ospray diff --git a/modules/cpu/fb/TileShared.h b/modules/cpu/fb/TileShared.h new file mode 100644 index 0000000000..71012f2728 --- /dev/null +++ b/modules/cpu/fb/TileShared.h @@ -0,0 +1,130 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef __cplusplus +#include "common/OSPCommon.h" +#include "common/StructShared.h" +#include "rkcommon/math/box.h" +#include "rkcommon/math/vec.h" +namespace ispc { +#else +#include "common/OSPCommon.ih" +#include "rkcommon/math/box.ih" + +#endif + +#ifdef __cplusplus +static_assert(TILE_SIZE > 0 && (TILE_SIZE & (TILE_SIZE - 1)) == 0, + "OSPRay config error: TILE_SIZE must be a positive power of two."); +#endif + +// Extra defines to hide some differences between ISPC/C++ to unify the +// declaration +#ifdef __cplusplus +#define uniform +#else +#define OSPRAY_SDK_INTERFACE +#endif + +//! a tile of pixels used by any tile-based renderer +/*! pixels in the tile are in a row-major TILE_SIZE x TILE_SIZE + pattern. the 'region' specifies which part of the screen this + tile belongs to: tile.lower is the lower-left coordinate of this + tile (and a multiple of TILE_SIZE); the 'upper' value may be + smaller than the upper-right edge of the "full" tile. + + note that a tile contains "all" of the values a renderer might + want to use. not all renderers nor all frame buffers will use + all those values; it's up to the renderer and frame buffer to + agree on which fields will be set. Similarly, the frame buffer + may actually use uchars, but the tile will always store + floats. */ +struct OSPRAY_SDK_INTERFACE Tile +{ + uniform range2i region; + uniform vec2i fbSize; + uniform vec2f rcp_fbSize; + uniform int32 generation; + uniform int32 children; + uniform int32 sortOrder; + uniform int32 accumID; + uniform float pad[4]; // padding to match the varying tile layout + uniform float r[TILE_SIZE * TILE_SIZE]; // red + uniform float g[TILE_SIZE * TILE_SIZE]; // green + uniform float b[TILE_SIZE * TILE_SIZE]; // blue + uniform float a[TILE_SIZE * TILE_SIZE]; // alpha + uniform float z[TILE_SIZE * TILE_SIZE]; // depth + uniform float nx[TILE_SIZE * TILE_SIZE]; // normal x + uniform float ny[TILE_SIZE * TILE_SIZE]; // normal y + uniform float nz[TILE_SIZE * TILE_SIZE]; // normal z + uniform float ar[TILE_SIZE * TILE_SIZE]; // albedo red + uniform float ag[TILE_SIZE * TILE_SIZE]; // albedo green + uniform float ab[TILE_SIZE * TILE_SIZE]; // albedo blue + uniform uint32 pid[TILE_SIZE * TILE_SIZE]; // primID + uniform uint32 gid[TILE_SIZE * TILE_SIZE]; // objID + uniform uint32 iid[TILE_SIZE * TILE_SIZE]; // instanceID + +#ifdef __cplusplus + Tile() + : region(empty), + fbSize(0), + rcp_fbSize(0), + generation(0), + children(0), + sortOrder(0), + accumID(0) + {} + + Tile(const vec2i &tile, const vec2i &fbsize, const int32 accumId) + : fbSize(fbsize), rcp_fbSize(rcp(vec2f(fbsize))), accumID(accumId) + { + region.lower = tile * TILE_SIZE; + region.upper = min(region.lower + TILE_SIZE, fbsize); + } +#endif +}; + +#ifndef __cplusplus +struct VaryingTile +{ + uniform range2i region; // 4 ints + uniform vec2i fbSize; // 2 ints + uniform vec2f rcp_fbSize; // 2 floats + uniform int32 generation; + uniform int32 children; + uniform int32 sortOrder; + uniform int32 accumID; + uniform float pad[4]; // explicit padding to match on SSE, this padding is + // implicitly added on AVX and AVX512 to align the + // vectors though. We need it here to match on SSE + varying float r[TILE_SIZE * TILE_SIZE / programCount]; + varying float g[TILE_SIZE * TILE_SIZE / programCount]; + varying float b[TILE_SIZE * TILE_SIZE / programCount]; + varying float a[TILE_SIZE * TILE_SIZE / programCount]; + varying float z[TILE_SIZE * TILE_SIZE / programCount]; + varying float nx[TILE_SIZE * TILE_SIZE / programCount]; + varying float ny[TILE_SIZE * TILE_SIZE / programCount]; + varying float nz[TILE_SIZE * TILE_SIZE / programCount]; + varying float ar[TILE_SIZE * TILE_SIZE / programCount]; + varying float ag[TILE_SIZE * TILE_SIZE / programCount]; + varying float ab[TILE_SIZE * TILE_SIZE / programCount]; + varying uint32 pid[TILE_SIZE * TILE_SIZE / programCount]; // primID + varying uint32 gid[TILE_SIZE * TILE_SIZE / programCount]; // objID + varying uint32 iid[TILE_SIZE * TILE_SIZE / programCount]; // instanceID +}; +#endif + +#ifdef __cplusplus +#undef uniform +#else +#undef OSPRAY_SDK_INTERFACE +#endif + +#ifdef __cplusplus +} +namespace ospray { +using Tile = ispc::Tile; +} +#endif diff --git a/modules/cpu/fb/frame_ops/Blur.cpp b/modules/cpu/fb/frame_ops/Blur.cpp index f95024364f..5007af6160 100644 --- a/modules/cpu/fb/frame_ops/Blur.cpp +++ b/modules/cpu/fb/frame_ops/Blur.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Blur.h" diff --git a/modules/cpu/fb/frame_ops/Debug.cpp b/modules/cpu/fb/frame_ops/Debug.cpp index 6734a1b4d9..d312f1925f 100644 --- a/modules/cpu/fb/frame_ops/Debug.cpp +++ b/modules/cpu/fb/frame_ops/Debug.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Debug.h" diff --git a/modules/cpu/fb/frame_ops/Depth.cpp b/modules/cpu/fb/frame_ops/Depth.cpp index a1283781a6..59b3625f08 100644 --- a/modules/cpu/fb/frame_ops/Depth.cpp +++ b/modules/cpu/fb/frame_ops/Depth.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Depth.h" diff --git a/modules/cpu/fb/frame_ops/SSAO.cpp b/modules/cpu/fb/frame_ops/SSAO.cpp index 23e584401a..0e0bd78a92 100644 --- a/modules/cpu/fb/frame_ops/SSAO.cpp +++ b/modules/cpu/fb/frame_ops/SSAO.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "SSAO.h" diff --git a/modules/cpu/fb/frame_ops/SSAO.ispc b/modules/cpu/fb/frame_ops/SSAO.ispc index 2d132aa02f..0eae6eaec4 100644 --- a/modules/cpu/fb/frame_ops/SSAO.ispc +++ b/modules/cpu/fb/frame_ops/SSAO.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray @@ -135,12 +135,12 @@ export void LiveSSAOFrameOp_applyOcclusion(void *uniform _self, for (uint32 pixelID = 0; pixelID < fb->fbDims.x * fb->fbDims.y; pixelID++) { if (occlusionBuffer[pixelID] >= 0) { for (uint32 c = 0; c < 3; ++c) { - if ((fb->colorBufferFormat == ColorBufferFormat_RGB_UINT8) - || (fb->colorBufferFormat == ColorBufferFormat_RGBA_UINT8)) { + if ((fb->colorBufferFormat == OSP_FB_RGBA8) + || (fb->colorBufferFormat == OSP_FB_SRGBA)) { uint8 *uniform color = (uint8 * uniform) _color; color[pixelID * 4 + c] = color[pixelID * 4 + c] * (occlusionBuffer[pixelID]); - } else if (fb->colorBufferFormat == ColorBufferFormat_RGBA_FLOAT32) { + } else if (fb->colorBufferFormat == OSP_FB_RGBA32F) { float *uniform color = (float *uniform)_color; color[pixelID * 4 + c] *= (occlusionBuffer[pixelID]); } else { diff --git a/modules/cpu/fb/tile_ops/ToneMapper.cpp b/modules/cpu/fb/pixel_ops/ToneMapper.cpp similarity index 74% rename from modules/cpu/fb/tile_ops/ToneMapper.cpp rename to modules/cpu/fb/pixel_ops/ToneMapper.cpp index b8d068eb2a..b6f4dc2a7a 100644 --- a/modules/cpu/fb/tile_ops/ToneMapper.cpp +++ b/modules/cpu/fb/pixel_ops/ToneMapper.cpp @@ -1,8 +1,8 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ToneMapper.h" -#include "fb/tile_ops/ToneMapper_ispc.h" +#include "fb/pixel_ops/ToneMapper_ispc.h" using namespace rkcommon; @@ -49,9 +49,8 @@ void ToneMapper::commit() std::unique_ptr ToneMapper::attach(FrameBufferView &fbView) { - void *ispcEquiv = ispc::ToneMapper_create(); - ispc::ToneMapper_set(ispcEquiv, exposure, a, b, c, d, acesColor); - return rkcommon::make_unique(fbView, ispcEquiv); + return rkcommon::make_unique( + fbView, exposure, a, b, c, d, acesColor); } std::string ToneMapper::toString() const @@ -59,18 +58,22 @@ std::string ToneMapper::toString() const return "ospray::ToneMapper"; } -LiveToneMapper::LiveToneMapper(FrameBufferView &_fbView, void *ispcEquiv) - : LiveTileOp(_fbView), ispcEquiv(ispcEquiv) -{} - -LiveToneMapper::~LiveToneMapper() -{ - // TODO WILL: Release the ISPC equiv -} - -void LiveToneMapper::process(Tile &tile) +LiveToneMapper::LiveToneMapper(FrameBufferView &_fbView, + float exposure, + float a, + float b, + float c, + float d, + bool acesColor) + : AddStructShared(_fbView) { - ToneMapper_apply(ispcEquiv, (ispc::Tile &)tile); + getSh()->super.processPixel = ispc::LiveToneMapper_processPixel_addr(); + getSh()->exposure = exposure; + getSh()->a = a; + getSh()->b = b; + getSh()->c = c; + getSh()->d = d; + getSh()->acesColor = acesColor; } } // namespace ospray diff --git a/modules/cpu/fb/tile_ops/ToneMapper.h b/modules/cpu/fb/pixel_ops/ToneMapper.h similarity index 54% rename from modules/cpu/fb/tile_ops/ToneMapper.h rename to modules/cpu/fb/pixel_ops/ToneMapper.h index 86d2af68a3..7c77418381 100644 --- a/modules/cpu/fb/tile_ops/ToneMapper.h +++ b/modules/cpu/fb/pixel_ops/ToneMapper.h @@ -1,14 +1,15 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../ImageOp.h" +#include "ToneMapperShared.h" using namespace rkcommon; namespace ospray { /*! \brief Generic tone mapping operator approximating ACES by default. */ -struct OSPRAY_SDK_INTERFACE ToneMapper : public TileOp +struct OSPRAY_SDK_INTERFACE ToneMapper : public PixelOp { void commit() override; @@ -22,15 +23,16 @@ struct OSPRAY_SDK_INTERFACE ToneMapper : public TileOp float exposure; }; -struct OSPRAY_SDK_INTERFACE LiveToneMapper : public LiveTileOp +struct OSPRAY_SDK_INTERFACE LiveToneMapper + : public AddStructShared { - LiveToneMapper(FrameBufferView &fbView, void *ispcEquiv); - - ~LiveToneMapper() override; - - void process(Tile &t) override; - - void *ispcEquiv; + LiveToneMapper(FrameBufferView &fbView, + float exposure, + float a, + float b, + float c, + float d, + bool acesColor); }; } // namespace ospray diff --git a/modules/cpu/fb/pixel_ops/ToneMapper.ispc b/modules/cpu/fb/pixel_ops/ToneMapper.ispc new file mode 100644 index 0000000000..0ba6a3a650 --- /dev/null +++ b/modules/cpu/fb/pixel_ops/ToneMapper.ispc @@ -0,0 +1,49 @@ +// Copyright 2009 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "fb/pixel_ops/ToneMapperShared.h" +#include "math/LinearSpace.ih" +#include "rkcommon/math/vec.ih" + +// ACES input transform matrix = RRT_SAT_MAT * XYZ_2_AP1_MAT * D65_2_D60_CAT * +// REC709_2_XYZ_PRI_MAT +static const uniform LinearSpace3f acesInputMat = { + {0.5972782409, 0.0760130499, 0.0284085382}, + {0.3545713181, 0.9083220973, 0.1338243154}, + {0.0482176639, 0.0156579968, 0.8375684636}}; + +// ACES output transform matrix = XYZ_2_REC709_PRI_MAT * D60_2_D65_CAT * +// AP1_2_XYZ_MAT * ODT_SAT_MAT +static const uniform LinearSpace3f acesOutputMat = { + {1.6047539945, -0.1020831870, -0.0032670420}, + {-0.5310794927, 1.1081322801, -0.0727552477}, + {-0.0736720338, -0.0060518756, 1.0760219533}}; + +inline vec3f toneMap(const LiveToneMapper *uniform self, const vec3f &col) +{ + vec3f x = col * self->exposure; + if (self->acesColor) + x = acesInputMat * x; + x = pow(x, self->a) / (pow(x, self->a * self->d) * self->b + self->c); + if (self->acesColor) + x = acesOutputMat * x; + x = clamp(x, make_vec3f(0.f), make_vec3f(1.f)); + return x; +} + +vec4f LiveToneMapper_processPixel(void *uniform _self, + const vec4f &color, + const float, + const vec3f &, + const vec3f &) +{ + const LiveToneMapper *uniform self = (const LiveToneMapper *uniform)_self; + + vec3f tonemapped = toneMap(self, make_vec3f(color)); + return make_vec4f(tonemapped, color.w); +} + +export void *uniform LiveToneMapper_processPixel_addr() +{ + return LiveToneMapper_processPixel; +} diff --git a/modules/cpu/fb/pixel_ops/ToneMapperShared.h b/modules/cpu/fb/pixel_ops/ToneMapperShared.h new file mode 100644 index 0000000000..68e93fdb02 --- /dev/null +++ b/modules/cpu/fb/pixel_ops/ToneMapperShared.h @@ -0,0 +1,27 @@ +// Copyright 2009 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "../ImageOpShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif + +// Based on the generic filmic tone mapping operator from +// [Lottes, 2016, "Advanced Techniques and Optimization of HDR Color Pipelines"] +struct LiveToneMapper +{ + LivePixelOp super; + // linear exposure adjustment + float exposure; + // coefficients + float a, b, c, d; + // ACES color transform flag + bool acesColor; +}; + +#ifdef __cplusplus +} +#endif diff --git a/modules/cpu/fb/registration.cpp b/modules/cpu/fb/registration.cpp index 319af9a5f6..02dcf08f4c 100644 --- a/modules/cpu/fb/registration.cpp +++ b/modules/cpu/fb/registration.cpp @@ -1,12 +1,11 @@ -// Copyright 2020 Intel Corporation +// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "frame_ops/Blur.h" #include "frame_ops/Debug.h" #include "frame_ops/Depth.h" #include "frame_ops/SSAO.h" -#include "tile_ops/SaveTiles.h" -#include "tile_ops/ToneMapper.h" +#include "pixel_ops/ToneMapper.h" namespace ospray { @@ -16,7 +15,6 @@ void registerAllImageOps() ImageOp::registerType("debug"); ImageOp::registerType("depth"); ImageOp::registerType("ssao"); - ImageOp::registerType("save"); ImageOp::registerType("tonemapper"); } diff --git a/modules/cpu/fb/tile_ops/SaveTiles.cpp b/modules/cpu/fb/tile_ops/SaveTiles.cpp deleted file mode 100644 index f5fb14688c..0000000000 --- a/modules/cpu/fb/tile_ops/SaveTiles.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2009-2020 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -// ospray -#include "SaveTiles.h" -#include "rkcommon/utility/SaveImage.h" - -namespace ospray { - -void SaveTiles::commit() -{ - prefix = getParam("prefix", ""); - addColor = getParam("addColor", vec3f(0.f)); -} - -std::unique_ptr SaveTiles::attach(FrameBufferView &fbView) -{ - return rkcommon::make_unique(fbView, prefix, addColor); -} - -std::string SaveTiles::toString() const -{ - return "SaveTiles"; -} - -LiveSaveTiles::LiveSaveTiles( - FrameBufferView &_fbView, const std::string &prefix, const vec3f &addColor) - : LiveTileOp(_fbView), prefix(prefix), addColor(addColor) -{} - -inline float convert_srgb(const float x) -{ - if (x < 0.0031308) { - return 12.92 * x; - } else { - return 1.055 * std::pow(x, 1.f / 2.4f) - 0.055; - } -} - -void LiveSaveTiles::process(Tile &tile) -{ - const int tile_x = tile.region.lower.x / TILE_SIZE; - // TODO WILL: Why does tile store the fbsize? - const int tile_y = (tile.fbSize.y - tile.region.upper.y) / TILE_SIZE; - const int tile_id = tile_x + tile_y * (tile.fbSize.x / TILE_SIZE); - - const uint32_t w = TILE_SIZE, h = TILE_SIZE; - // Convert to SRGB8 color - std::vector data(w * h * 4, 0); - size_t pixelID = 0; - for (size_t iy = 0; iy < h; ++iy) { - for (size_t ix = 0; ix < w; ++ix, ++pixelID) { - if (!prefix.empty()) { - data[pixelID * 4] = - 255.f * convert_srgb(clamp(tile.r[pixelID], 0.f, 1.f)); - data[pixelID * 4 + 1] = - 255.f * convert_srgb(clamp(tile.g[pixelID], 0.f, 1.f)); - data[pixelID * 4 + 2] = - 255.f * convert_srgb(clamp(tile.b[pixelID], 0.f, 1.f)); - } - - // We write out the tile that came as input, then apply the color to - // pass down the pipeline - tile.r[pixelID] += addColor.x; - tile.g[pixelID] += addColor.y; - tile.b[pixelID] += addColor.z; - } - } - - if (!prefix.empty()) { - const std::string file = prefix + std::to_string(tile_id) + ".ppm"; - rkcommon::utility::writePPM( - file, w, h, reinterpret_cast(data.data())); - } -} - -} // namespace ospray diff --git a/modules/cpu/fb/tile_ops/SaveTiles.h b/modules/cpu/fb/tile_ops/SaveTiles.h deleted file mode 100644 index 28609f66ca..0000000000 --- a/modules/cpu/fb/tile_ops/SaveTiles.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -// ospray -#include "../ImageOp.h" - -namespace ospray { - -/*! The debug TileOp just dumps the input tiles out as PPM files, - with some optional filename prefix. It can also add a color to the - tile which will be passed down the pipeline after it, for testing - the tile pipeline itself. - To combine the output tiles into a single - image you can use ImageMagick's montage command: - montage `ls *.ppm | sort -V` -geometry +0+0 -tile MxN out.jpg - where M is the number of tiles along X, and N the number of tiles along Y - */ -struct OSPRAY_SDK_INTERFACE SaveTiles : public TileOp -{ - void commit() override; - - std::unique_ptr attach(FrameBufferView &fbView) override; - - std::string toString() const override; - - std::string prefix; - vec3f addColor; -}; - -struct OSPRAY_SDK_INTERFACE LiveSaveTiles : public LiveTileOp -{ - LiveSaveTiles(FrameBufferView &fbView, - const std::string &prefix, - const vec3f &addColor); - - void process(Tile &t) override; - - std::string prefix; - vec3f addColor; -}; - -} // namespace ospray diff --git a/modules/cpu/fb/tile_ops/ToneMapper.ispc b/modules/cpu/fb/tile_ops/ToneMapper.ispc deleted file mode 100644 index e65351adc6..0000000000 --- a/modules/cpu/fb/tile_ops/ToneMapper.ispc +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2009-2020 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#include "../Tile.ih" -#include "math/LinearSpace.ih" -#include "rkcommon/math/vec.ih" - -// Based on the generic filmic tone mapping operator from -// [Lottes, 2016, "Advanced Techniques and Optimization of HDR Color Pipelines"] -struct ToneMapper -{ - float exposure; // linear exposure adjustment - float a, b, c, d; // coefficients - bool acesColor; // ACES color transform flag -}; - -// ACES input transform matrix = RRT_SAT_MAT * XYZ_2_AP1_MAT * D65_2_D60_CAT * -// REC709_2_XYZ_PRI_MAT -static const uniform LinearSpace3f acesInputMat = { - {0.5972782409, 0.0760130499, 0.0284085382}, - {0.3545713181, 0.9083220973, 0.1338243154}, - {0.0482176639, 0.0156579968, 0.8375684636}}; - -// ACES output transform matrix = XYZ_2_REC709_PRI_MAT * D60_2_D65_CAT * -// AP1_2_XYZ_MAT * ODT_SAT_MAT -static const uniform LinearSpace3f acesOutputMat = { - {1.6047539945, -0.1020831870, -0.0032670420}, - {-0.5310794927, 1.1081322801, -0.0727552477}, - {-0.0736720338, -0.0060518756, 1.0760219533}}; - -inline vec3f toneMap(const ToneMapper *uniform self, const vec3f &col) -{ - vec3f x = col * self->exposure; - if (self->acesColor) - x = acesInputMat * x; - x = pow(x, self->a) / (pow(x, self->a * self->d) * self->b + self->c); - if (self->acesColor) - x = acesOutputMat * x; - x = clamp(x, make_vec3f(0.f), make_vec3f(1.f)); - return x; -} - -export void *uniform ToneMapper_create() -{ - ToneMapper *uniform self = uniform new uniform ToneMapper; - self->exposure = 1.f; - self->a = 1.f; - self->b = 1.f; - self->c = 0.f; - self->d = 1.f; - self->acesColor = false; - return self; -} - -export void ToneMapper_set(void *uniform _self, - uniform float exposure, - uniform float a, - uniform float b, - uniform float c, - uniform float d, - uniform bool acesColor) -{ - ToneMapper *uniform self = (ToneMapper * uniform) _self; - self->exposure = exposure; - self->a = a; - self->b = b; - self->c = c; - self->d = d; - self->acesColor = acesColor; -} - -export void ToneMapper_apply(const void *uniform _self, uniform Tile &tile) -{ - const ToneMapper *uniform self = (const ToneMapper *uniform)_self; - VaryingTile *uniform varyTile = (VaryingTile * uniform) & tile; - - for (uniform uint32 iy = 0; iy < TILE_SIZE; iy++) { - uniform uint32 iiy = tile.region.lower.y + iy; - if (iiy >= tile.region.upper.y) - continue; - - uniform uint32 chunkID = iy * (TILE_SIZE / programCount); - - for (uint32 iix = tile.region.lower.x + programIndex; - iix < tile.region.upper.x; - iix += programCount, chunkID++) { - unmasked - { - varying vec3f col = make_vec3f( - varyTile->r[chunkID], varyTile->g[chunkID], varyTile->b[chunkID]); - - col = toneMap(self, col); - - varyTile->r[chunkID] = col.x; - varyTile->g[chunkID] = col.y; - varyTile->b[chunkID] = col.z; - } - } - } -} diff --git a/modules/cpu/geometry/Boxes.cpp b/modules/cpu/geometry/Boxes.cpp index dec64172fb..59c02834ff 100644 --- a/modules/cpu/geometry/Boxes.cpp +++ b/modules/cpu/geometry/Boxes.cpp @@ -1,10 +1,9 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Boxes.h" #include "common/Data.h" -#include "common/World.h" // ispc-generated files #include "geometry/Boxes_ispc.h" @@ -12,7 +11,7 @@ namespace ospray { Boxes::Boxes() { - ispcEquivalent = ispc::Boxes_create(); + getSh()->super.postIntersect = ispc::Boxes_postIntersect_addr(); } std::string Boxes::toString() const @@ -22,15 +21,13 @@ std::string Boxes::toString() const void Boxes::commit() { - if (!embreeDevice) { - throw std::runtime_error("invalid Embree device"); - } - if (!embreeGeometry) { - embreeGeometry = rtcNewGeometry(embreeDevice, RTC_GEOMETRY_TYPE_USER); - } boxData = getParamDataT("box", true); - ispc::Boxes_set(getIE(), embreeGeometry, ispc(boxData)); + createEmbreeUserGeometry((RTCBoundsFunction)&ispc::Boxes_bounds, + (RTCIntersectFunctionN)&ispc::Boxes_intersect, + (RTCOccludedFunctionN)&ispc::Boxes_occluded); + getSh()->boxes = *ispc(boxData); + getSh()->super.numPrimitives = numPrimitives(); postCreationInfo(); } diff --git a/modules/cpu/geometry/Boxes.h b/modules/cpu/geometry/Boxes.h index f12e690110..70209acc76 100644 --- a/modules/cpu/geometry/Boxes.h +++ b/modules/cpu/geometry/Boxes.h @@ -1,14 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Geometry.h" -#include "volume/Volume.h" +// ispc shared +#include "BoxesShared.h" namespace ospray { -struct OSPRAY_SDK_INTERFACE Boxes : public Geometry +struct OSPRAY_SDK_INTERFACE Boxes + : public AddStructShared { Boxes(); virtual ~Boxes() override = default; diff --git a/modules/cpu/geometry/Boxes.ispc b/modules/cpu/geometry/Boxes.ispc index d635984e26..57cfd0231f 100644 --- a/modules/cpu/geometry/Boxes.ispc +++ b/modules/cpu/geometry/Boxes.ispc @@ -1,23 +1,18 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "common/Data.ih" +#include "common/DifferentialGeometry.ih" #include "common/FilterIntersect.ih" #include "common/Intersect.ih" #include "common/Ray.ih" -#include "common/World.ih" -#include "geometry/Geometry.ih" #include "rkcommon/math/box.ih" #include "rkcommon/math/vec.ih" +// c++ shared +#include "BoxesShared.h" -struct Boxes -{ - Geometry super; - Data1D boxes; -}; - -unmasked void Boxes_bounds(const RTCBoundsFunctionArguments *uniform args) +export void Boxes_bounds(const RTCBoundsFunctionArguments *uniform args) { Boxes *uniform self = (Boxes * uniform) args->geometryUserPtr; uniform int primID = args->primID; @@ -46,19 +41,19 @@ void Boxes_intersect_kernel(const RTCIntersectFunctionNArguments *uniform args, filterIntersectionBoth(args, isect, isOcclusionTest); } -unmasked void Boxes_intersect( +export void Boxes_intersect( const struct RTCIntersectFunctionNArguments *uniform args) { Boxes_intersect_kernel(args, false); } -unmasked void Boxes_occluded( +export void Boxes_occluded( const struct RTCOccludedFunctionNArguments *uniform args) { Boxes_intersect_kernel((RTCIntersectFunctionNArguments * uniform) args, true); } -static void Boxes_postIntersect(const Geometry *uniform geometry, +void Boxes_postIntersect(const Geometry *uniform geometry, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags) @@ -66,28 +61,7 @@ static void Boxes_postIntersect(const Geometry *uniform geometry, dg.Ng = dg.Ns = ray.Ng; } -export void *uniform Boxes_create() -{ - Boxes *uniform self = uniform new Boxes; - - Geometry_Constructor(&self->super, Boxes_postIntersect); - Data1D_Constructor(&self->boxes); - - return self; -} - -export void *uniform Boxes_set(void *uniform _self, - void *uniform _embreeGeometry, - const Data1D *uniform boxes) +export void *uniform Boxes_postIntersect_addr() { - Boxes *uniform self = (Boxes * uniform) _self; - - self->boxes = *boxes; - self->super.numPrimitives = boxes->numItems; - - Geometry_setEmbreeUserGeometry(&self->super, - (RTCGeometry)_embreeGeometry, - Boxes_bounds, - Boxes_intersect, - Boxes_occluded); -} + return Boxes_postIntersect; +} \ No newline at end of file diff --git a/modules/cpu/geometry/BoxesShared.h b/modules/cpu/geometry/BoxesShared.h new file mode 100644 index 0000000000..70b5749e00 --- /dev/null +++ b/modules/cpu/geometry/BoxesShared.h @@ -0,0 +1,20 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "GeometryShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +struct Boxes +{ + Geometry super; + Data1D boxes; +}; + +#ifdef __cplusplus +} // namespace ispc +#endif // __cplusplus diff --git a/modules/cpu/geometry/Curves.cpp b/modules/cpu/geometry/Curves.cpp index 5adfcd934d..f0746477a9 100644 --- a/modules/cpu/geometry/Curves.cpp +++ b/modules/cpu/geometry/Curves.cpp @@ -1,10 +1,9 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Curves.h" -#include "common/Data.h" -#include "common/World.h" +#include "common/DGEnum.h" // ispc-generated files #include "geometry/Curves_ispc.h" @@ -48,7 +47,8 @@ static std::map, RTCGeometryType> Curves::Curves() { - ispcEquivalent = ispc::Curves_create(); + getSh()->super.postIntersect = ispc::Curves_postIntersect_addr(); + // TODO implement area sampling of OldCurves for geometry lights } std::string Curves::toString() const @@ -117,6 +117,14 @@ void Curves::commit() createEmbreeGeometry(); + getSh()->geom = embreeGeometry; + getSh()->flagMask = -1; + if (!colorData) + getSh()->flagMask &= ispc::int64(~DG_COLOR); + if (!texcoordData) + getSh()->flagMask &= ispc::int64(~DG_TEXCOORD); + getSh()->super.numPrimitives = numPrimitives(); + postCreationInfo(vertexData->size()); } @@ -127,13 +135,7 @@ size_t Curves::numPrimitives() const void Curves::createEmbreeGeometry() { - if (embreeGeometry) - rtcReleaseGeometry(embreeGeometry); - - if (!embreeDevice) { - throw std::runtime_error("invalid Embree device"); - } - embreeGeometry = rtcNewGeometry(embreeDevice, embreeCurveType); + Geometry::createEmbreeGeometry(embreeCurveType); Ref> vertex4f(&vertexData->as()); setEmbreeGeometryBuffer(embreeGeometry, RTC_BUFFER_TYPE_VERTEX, vertex4f); @@ -151,9 +153,6 @@ void Curves::createEmbreeGeometry() embreeGeometry, RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE, texcoordData, 1); } - ispc::Curves_set( - getIE(), embreeGeometry, colorData, texcoordData, indexData->size()); - rtcCommitGeometry(embreeGeometry); } diff --git a/modules/cpu/geometry/Curves.h b/modules/cpu/geometry/Curves.h index d86bb91579..9a7c10cf68 100644 --- a/modules/cpu/geometry/Curves.h +++ b/modules/cpu/geometry/Curves.h @@ -1,13 +1,17 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Geometry.h" +#include "common/Data.h" +// ispc shared +#include "CurvesShared.h" namespace ospray { -struct OSPRAY_SDK_INTERFACE Curves : public Geometry +struct OSPRAY_SDK_INTERFACE Curves + : public AddStructShared { Curves(); virtual ~Curves() override = default; @@ -25,7 +29,7 @@ struct OSPRAY_SDK_INTERFACE Curves : public Geometry Ref> colorData; Ref> texcoordData; - RTCGeometryType embreeCurveType; + RTCGeometryType embreeCurveType{(RTCGeometryType)-1}; OSPCurveType curveType{OSP_UNKNOWN_CURVE_TYPE}; OSPCurveBasis curveBasis{OSP_UNKNOWN_CURVE_BASIS}; diff --git a/modules/cpu/geometry/Curves.ispc b/modules/cpu/geometry/Curves.ispc index 86c59771a7..ecbeef510c 100644 --- a/modules/cpu/geometry/Curves.ispc +++ b/modules/cpu/geometry/Curves.ispc @@ -1,20 +1,10 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray -#include "common/Data.ih" -#include "geometry/Geometry.ih" - -struct Curves -{ - Geometry super; //!< inherited geometry fields - Data1D index; - Data1D vertex; - Data1D color; - Data1D texcoord; - int64 flagMask; - RTCGeometry geom; -}; +#include "Geometry.ih" +// c++ shared +#include "CurvesShared.h" static void Curves_postIntersect(const Geometry *uniform _self, varying DifferentialGeometry &dg, @@ -50,40 +40,7 @@ static void Curves_postIntersect(const Geometry *uniform _self, } } -void Curves_Constructor(Curves *uniform self) -{ - Geometry_Constructor(&self->super, NULL); - Data1D_Constructor(&self->index); - Data1D_Constructor(&self->vertex); - Data1D_Constructor(&self->color); - Data1D_Constructor(&self->texcoord); -} - -export void *uniform Curves_create() +export void *uniform Curves_postIntersect_addr() { - Curves *uniform self = uniform new Curves; - Curves_Constructor(self); - return self; -} - -export void *uniform Curves_set(void *uniform _self, - RTCGeometry geom, - uniform bool haveColor, - uniform bool haveTexture, - int32 uniform numSegments) -{ - Curves *uniform self = (Curves * uniform) _self; - self->geom = geom; - self->flagMask = -1; - if (!haveColor) - self->flagMask &= ~DG_COLOR; - if (!haveTexture) - self->flagMask &= ~DG_TEXCOORD; - - self->super.numPrimitives = numSegments; - self->super.postIntersect = Curves_postIntersect; - - // TODO implement area sampling of OldCurves for geometry lights - self->super.getAreas = NULL; - self->super.sampleArea = NULL; + return Curves_postIntersect; } \ No newline at end of file diff --git a/modules/cpu/geometry/CurvesShared.h b/modules/cpu/geometry/CurvesShared.h new file mode 100644 index 0000000000..b3383a0854 --- /dev/null +++ b/modules/cpu/geometry/CurvesShared.h @@ -0,0 +1,24 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "GeometryShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +struct Curves +{ + Geometry super; // inherited geometry fields + RTCGeometry geom; + int64 flagMask; + +#ifdef __cplusplus + Curves() : geom(nullptr), flagMask(-1) {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/geometry/GeometricModel.cpp b/modules/cpu/geometry/GeometricModel.cpp index 8870e8b630..20a60c6381 100644 --- a/modules/cpu/geometry/GeometricModel.cpp +++ b/modules/cpu/geometry/GeometricModel.cpp @@ -1,19 +1,15 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "GeometricModel.h" -#include "../render/Material.h" -// ispc exports -#include "geometry/GeometricModel_ispc.h" -#include "geometry/Geometry_ispc.h" +#include "render/Material.h" namespace ospray { GeometricModel::GeometricModel(Geometry *_geometry) : geomAPI(_geometry) { managedObjectType = OSP_GEOMETRIC_MODEL; - this->ispcEquivalent = ispc::GeometricModel_create(); } std::string GeometricModel::toString() const @@ -31,7 +27,8 @@ void GeometricModel::commit() bool useRendererMaterialList = false; materialData = getParamDataT("material", false, true); if (materialData) { - ispcMaterialPtrs = createArrayOfSh(materialData->as()); + ispcMaterialPtrs = + createArrayOfSh(materialData->as()); auto *data = new Data(ispcMaterialPtrs.data(), OSP_VOID_PTR, @@ -71,15 +68,13 @@ void GeometricModel::commit() << " potentially not enough 'color' elements for 'geometry', clamping"; } - invertNormals = getParam("invertNormals"); - - ispc::GeometricModel_set(getIE(), - geometry().getIE(), - ispc(colorData), - ispc(indexData), - ispc(materialData), - useRendererMaterialList, - invertNormals); + getSh()->geom = geom->getSh(); + getSh()->color = *ispc(colorData); + getSh()->index = *ispc(indexData); + getSh()->material = *ispc(materialData); + getSh()->useRendererMaterialList = useRendererMaterialList; + getSh()->invertedNormals = getParam("invertNormals", false); + getSh()->userID = getParam("id", RTC_INVALID_GEOMETRY_ID); } OSPTYPEFOR_DEFINITION(GeometricModel *); diff --git a/modules/cpu/geometry/GeometricModel.h b/modules/cpu/geometry/GeometricModel.h index 87915231ea..f60886152d 100644 --- a/modules/cpu/geometry/GeometricModel.h +++ b/modules/cpu/geometry/GeometricModel.h @@ -1,14 +1,21 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Geometry.h" #include "common/Data.h" +// ispc shared +#include "GeometricModelShared.h" + +namespace ispc { +struct Material; +} namespace ospray { -struct OSPRAY_SDK_INTERFACE GeometricModel : public ManagedObject +struct OSPRAY_SDK_INTERFACE GeometricModel + : public AddStructShared { GeometricModel(Geometry *geometry); ~GeometricModel() override = default; @@ -18,6 +25,7 @@ struct OSPRAY_SDK_INTERFACE GeometricModel : public ManagedObject void commit() override; Geometry &geometry(); + RTCGeometry embreeGeometryHandle() const; bool invertedNormals() const; @@ -27,10 +35,7 @@ struct OSPRAY_SDK_INTERFACE GeometricModel : public ManagedObject Ref materialData; Ref> colorData; Ref> indexData; - std::vector ispcMaterialPtrs; - - // geometry normals will be inverted if set to true - bool invertNormals{false}; + std::vector ispcMaterialPtrs; friend struct PathTracer; // TODO: fix this! friend struct Renderer; @@ -45,9 +50,14 @@ inline Geometry &GeometricModel::geometry() return *geom; } +inline RTCGeometry GeometricModel::embreeGeometryHandle() const +{ + return geom->getEmbreeGeometry(); +} + inline bool GeometricModel::invertedNormals() const { - return invertNormals; + return getSh()->invertedNormals; } } // namespace ospray diff --git a/modules/cpu/geometry/GeometricModel.ih b/modules/cpu/geometry/GeometricModel.ih index e8f90512ba..c677b3d2fc 100644 --- a/modules/cpu/geometry/GeometricModel.ih +++ b/modules/cpu/geometry/GeometricModel.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -7,21 +7,8 @@ #include "common/Data.ih" #include "math/AffineSpace.ih" #include "render/Renderer.ih" - -struct GeometricModel -{ - Geometry *geom; - - Data1D color; - Data1D index; // per-primitive property mapping - Data1D material; - - bool useRendererMaterialList; - - bool invertedNormals; - - float areaPDF; -}; +// c++ shared +#include "GeometricModelShared.h" inline Material *GeometricModel_getMaterial(const GeometricModel *uniform self, const Renderer *uniform renderer, @@ -58,6 +45,8 @@ inline void GeometricModel_postIntersect(const GeometricModel *uniform self, geom->postIntersect(geom, dg, ray, flags); dg.areaPDF = self->areaPDF; + dg.objID = + (self->userID == RTC_INVALID_GEOMETRY_ID) ? ray.geomID : self->userID; if (flags & DG_COLOR && valid(self->color)) { uint32 idx = ray.primID; diff --git a/modules/cpu/geometry/GeometricModel.ispc b/modules/cpu/geometry/GeometricModel.ispc index 810cf89889..e3f3a2bb1b 100644 --- a/modules/cpu/geometry/GeometricModel.ispc +++ b/modules/cpu/geometry/GeometricModel.ispc @@ -1,44 +1,46 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "GeometricModel.ih" -#include "common/Ray.ih" -#include "rkcommon/math/box.ih" -#include "rkcommon/math/vec.ih" - -export void *uniform GeometricModel_create() +#include "math/Distribution1D.ih" +#include "render/Material.ih" +// c++ shared +#include "common/InstanceShared.h" + +export uniform int GeometricModel_gatherEmissivePrimIDs(void *uniform _model, + void *uniform _renderer, + void *uniform _instance, + int *uniform primIDs, + float *uniform distribution, + uniform float &pdf) { - GeometricModel *uniform self = uniform new GeometricModel; - - self->geom = NULL; - - Data1D_Constructor(&self->color); - Data1D_Constructor(&self->index); - Data1D_Constructor(&self->material); - self->useRendererMaterialList = false; - - self->areaPDF = 0.f; - - return self; -} - -export void GeometricModel_set(void *uniform _self, - void *uniform _geom, - const Data1D *uniform color, - const Data1D *uniform index, - const Data1D *uniform material, - const uniform bool useRendererMaterialList, - const uniform bool invertedNormals) -{ - GeometricModel *uniform self = (GeometricModel * uniform) _self; - - self->geom = (Geometry * uniform) _geom; - - self->color = *color; - self->index = *index; - self->material = *material; - - self->useRendererMaterialList = useRendererMaterialList; - self->invertedNormals = invertedNormals; + GeometricModel *uniform model = (GeometricModel * uniform) _model; + const Renderer *uniform renderer = (Renderer * uniform) _renderer; + const Geometry *uniform geo = model->geom; + const Instance *uniform instance = (Instance * uniform) _instance; + + // create the list of emissive primitive IDs + uniform int32 numEmissivePrims = 0; + foreach (primID = 0 ... geo->numPrimitives) { + Material *mat = + (Material *)GeometricModel_getMaterial(model, renderer, primID); + const vec3f emission = mat->emission; + if (reduce_max(emission) > 0.f) { + int offset = exclusive_scan_add(1); + + primIDs[numEmissivePrims + offset] = primID; + numEmissivePrims += reduce_add(1); + } + } + + // create the sampling distribution + // TODO: use emissive power instead of just area + // TODO: motion blur can introduce scale, which means areas cannot accurately + // be precomputed + geo->getAreas(geo, primIDs, numEmissivePrims, instance->xfm, distribution); + pdf = model->areaPDF = + 1.f / Distribution1D_create(numEmissivePrims, distribution); + + return numEmissivePrims; } diff --git a/modules/cpu/geometry/GeometricModelShared.h b/modules/cpu/geometry/GeometricModelShared.h new file mode 100644 index 0000000000..4781a371b3 --- /dev/null +++ b/modules/cpu/geometry/GeometricModelShared.h @@ -0,0 +1,38 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "GeometryShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +struct GeometricModel +{ + Geometry *geom; + + Data1D color; + Data1D index; // per-primitive property mapping + Data1D material; + + bool useRendererMaterialList; + bool invertedNormals; + + float areaPDF; + unsigned int userID; + +#ifdef __cplusplus + GeometricModel() + : geom(nullptr), + useRendererMaterialList(false), + invertedNormals(false), + areaPDF(0.f), + userID(RTC_INVALID_GEOMETRY_ID) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/geometry/Geometry.cpp b/modules/cpu/geometry/Geometry.cpp index 01a0671274..3c739a8f0d 100644 --- a/modules/cpu/geometry/Geometry.cpp +++ b/modules/cpu/geometry/Geometry.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray @@ -52,6 +52,33 @@ void Geometry::setDevice(RTCDevice device) embreeDevice = device; } +void Geometry::createEmbreeGeometry(RTCGeometryType type) +{ + if (embreeGeometry) + rtcReleaseGeometry(embreeGeometry); + + if (!embreeDevice) { + throw std::runtime_error("invalid Embree device"); + } + + embreeGeometry = rtcNewGeometry(embreeDevice, type); +} + +void Geometry::createEmbreeUserGeometry(RTCBoundsFunction boundsFn, + RTCIntersectFunctionN intersectFn, + RTCOccludedFunctionN occludedFn) +{ + createEmbreeGeometry(RTC_GEOMETRY_TYPE_USER); + + // Setup Embree user-defined geometry + rtcSetGeometryUserData(embreeGeometry, getSh()); + rtcSetGeometryUserPrimitiveCount(embreeGeometry, numPrimitives()); + rtcSetGeometryBoundsFunction(embreeGeometry, boundsFn, getSh()); + rtcSetGeometryIntersectFunction(embreeGeometry, intersectFn); + rtcSetGeometryOccludedFunction(embreeGeometry, occludedFn); + rtcCommitGeometry(embreeGeometry); +} + OSPTYPEFOR_DEFINITION(Geometry *); } // namespace ospray diff --git a/modules/cpu/geometry/Geometry.h b/modules/cpu/geometry/Geometry.h index 849a915f62..3aa27b6c42 100644 --- a/modules/cpu/geometry/Geometry.h +++ b/modules/cpu/geometry/Geometry.h @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -8,10 +8,13 @@ #include "common/Util.h" // embree #include "embree3/rtcore.h" +// ispc shared +#include "GeometryShared.h" namespace ospray { -struct OSPRAY_SDK_INTERFACE Geometry : public ManagedObject +struct OSPRAY_SDK_INTERFACE Geometry + : public AddStructShared { Geometry(); virtual ~Geometry() override; @@ -22,18 +25,25 @@ struct OSPRAY_SDK_INTERFACE Geometry : public ManagedObject void postCreationInfo(size_t numVerts = 0) const; - // Object factory // - + // Object factory static Geometry *createInstance(const char *type); template static void registerType(const char *type); - RTCGeometry embreeGeometry{nullptr}; - void setDevice(RTCDevice embreeDevice); + RTCGeometry getEmbreeGeometry() const; + + bool supportAreaLighting() const; + protected: RTCDevice embreeDevice{nullptr}; + RTCGeometry embreeGeometry{nullptr}; + + void createEmbreeGeometry(RTCGeometryType type); + void createEmbreeUserGeometry(RTCBoundsFunction boundsFn, + RTCIntersectFunctionN intersectFn, + RTCOccludedFunctionN occludedFn); private: template @@ -51,6 +61,16 @@ inline void Geometry::registerType(const char *type) registerTypeHelper(type); } +inline RTCGeometry Geometry::getEmbreeGeometry() const +{ + return embreeGeometry; +} + +inline bool Geometry::supportAreaLighting() const +{ + return (getSh()->sampleArea != nullptr) && (getSh()->getAreas != nullptr); +} + // convenience wrappers to set Embree buffer ////////////////////////////////// template diff --git a/modules/cpu/geometry/Geometry.ih b/modules/cpu/geometry/Geometry.ih index 5f257c38b7..5cbbb77a09 100644 --- a/modules/cpu/geometry/Geometry.ih +++ b/modules/cpu/geometry/Geometry.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -10,78 +10,5 @@ // embree #include "embree3/rtcore.isph" -struct Geometry; - -/*! Geometries are supposed to fill certain members of DifferentialGeometry: - calculate Ng, Ns, st, color, and materialID if the respective bit DG_NG, - DG_NS, DG_TEXCOORD, DG_COLOR, and DG_MATERIALID, in flags is set. - Important with instancing: P and ray are in world-coordinates, whereas Ng - and Ns are in object-coordinates and transformed to world-space by - Instance_postIntersect. - World::postIntersect already set the hit point P, color, geometry, and - material before, and handles normalization/faceforwarding - (DG_NORMALIZE/DG_FACEFORWARD) after Geometry_postIntersectFct is called. - Thus the material pointer only needs to be set if different to - geometry->material, or the color when different to vec4f(1.0f). -*/ -typedef void (*Geometry_postIntersectFct)(const Geometry *uniform self, - varying DifferentialGeometry &dg, - const varying Ray &ray, - uniform int64 flags); - -struct SampleAreaRes -{ - vec3f pos; //!< sampled point, in world-space - vec3f normal; //!< geometry normal Ng at the sampled point -}; - -typedef void (*Geometry_GetAreasFct)(const Geometry *const uniform, - const int32 *const uniform primIDs //!< primitive IDs - , - const uniform int32 numPrims //!< number of primitives - , - const uniform affine3f &xfm //!< instance transformation (obj2world) - , - float *const uniform areas //!< array to return area per primitive - // in world-space -); - -// sample the given primitive uniformly wrt. area -typedef SampleAreaRes (*Geometry_SampleAreaFct)(const Geometry *const uniform, - const int32 primID, - const uniform affine3f &xfm, // instance transformation (obj2world) - const uniform affine3f &rcp_xfm, // inverse transformation (world2obj) - const vec2f &s, // random numbers to generate the sample - const float time // for deformation motion blur -); - -struct Geometry -{ - /*! 'virtual' post-intersect function that fills in a - DifferentialGeometry struct, see above prototype for details */ - Geometry_postIntersectFct postIntersect; - - Geometry_GetAreasFct getAreas; - Geometry_SampleAreaFct sampleArea; - - //! number of primitives this geometry has - int32 numPrimitives; -}; - -inline void Geometry_setEmbreeUserGeometry(Geometry *uniform self, - RTCGeometry geom, - uniform RTCBoundsFunction bounds, - uniform RTCIntersectFunctionN intersect, - uniform RTCOccludedFunctionN occluded) -{ - rtcSetGeometryUserData(geom, self); - rtcSetGeometryUserPrimitiveCount(geom, self->numPrimitives); - rtcSetGeometryBoundsFunction(geom, bounds, self); - rtcSetGeometryIntersectFunction(geom, intersect); - rtcSetGeometryOccludedFunction(geom, occluded); - rtcCommitGeometry(geom); -} - -//! constructor for ispc-side Geometry object -void Geometry_Constructor(Geometry *uniform geometry, - uniform Geometry_postIntersectFct postIntersect); +// c++ shared +#include "GeometryShared.h" diff --git a/modules/cpu/geometry/Geometry.ispc b/modules/cpu/geometry/Geometry.ispc deleted file mode 100644 index 26991dd721..0000000000 --- a/modules/cpu/geometry/Geometry.ispc +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2009-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#include "Geometry.ih" - -void Geometry_Constructor( - Geometry *uniform self, uniform Geometry_postIntersectFct postIntersect) -{ - self->numPrimitives = 0; - self->postIntersect = postIntersect; - self->sampleArea = NULL; - self->getAreas = NULL; -} diff --git a/modules/cpu/geometry/GeometryShared.h b/modules/cpu/geometry/GeometryShared.h new file mode 100644 index 0000000000..992adef464 --- /dev/null +++ b/modules/cpu/geometry/GeometryShared.h @@ -0,0 +1,78 @@ +// Copyright 2009 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef __cplusplus +#include "common/StructShared.h" +namespace ispc { +typedef void *Geometry_postIntersectFct; +typedef void *Geometry_GetAreasFct; +typedef void *Geometry_SampleAreaFct; +#else +struct Geometry; + +// Geometries are supposed to fill certain members of DifferentialGeometry: +// calculate Ng, Ns, st, color, and materialID if the respective bit DG_NG, +// DG_NS, DG_TEXCOORD, DG_COLOR, and DG_MATERIALID, in flags is set. +// Important with instancing: P and ray are in world-coordinates, whereas Ng +// and Ns are in object-coordinates and transformed to world-space by +// Instance_postIntersect. +// World::postIntersect already set the hit point P, color, geometry, and +// material before, and handles normalization/faceforwarding +// (DG_NORMALIZE/DG_FACEFORWARD) after Geometry_postIntersectFct is called. +// Thus the material pointer only needs to be set if different to +// geometry->material, or the color when different to vec4f(1.0f). +typedef void (*Geometry_postIntersectFct)(const Geometry *uniform self, + varying DifferentialGeometry &dg, + const varying Ray &ray, + uniform int64 flags); + +typedef void (*Geometry_GetAreasFct)(const Geometry *const uniform, + const int32 *const uniform primIDs, // primitive IDs + const uniform int32 numPrims, // number of primitives + const uniform affine3f &xfm, // instance transformation (obj2world) + float *const uniform + areas // array to return area per primitive in world-space +); + +struct SampleAreaRes +{ + vec3f pos; // sampled point, in world-space + vec3f normal; // geometry normal Ng at the sampled point +}; + +// sample the given primitive uniformly wrt. area +typedef SampleAreaRes (*Geometry_SampleAreaFct)(const Geometry *const uniform, + const int32 primID, + const uniform affine3f &xfm, // instance transformation (obj2world) + const uniform affine3f &rcp_xfm, // inverse transformation (world2obj) + const vec2f &s, // random numbers to generate the sample + const float time // for deformation motion blur +); +#endif // __cplusplus + +struct Geometry +{ + // 'virtual' post-intersect function that fills in a + // DifferentialGeometry struct, see above prototype for details + Geometry_postIntersectFct postIntersect; + + Geometry_GetAreasFct getAreas; + Geometry_SampleAreaFct sampleArea; + + // number of primitives this geometry has + int32 numPrimitives; + +#ifdef __cplusplus + Geometry() + : postIntersect(nullptr), + getAreas(nullptr), + sampleArea(nullptr), + numPrimitives(0) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/geometry/Isosurfaces.cpp b/modules/cpu/geometry/Isosurfaces.cpp index 8277914a2b..bdef3b97b4 100644 --- a/modules/cpu/geometry/Isosurfaces.cpp +++ b/modules/cpu/geometry/Isosurfaces.cpp @@ -1,10 +1,9 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Isosurfaces.h" #include "common/Data.h" -#include "common/World.h" // openvkl #include "openvkl/openvkl.h" // ispc-generated files @@ -14,7 +13,7 @@ namespace ospray { Isosurfaces::Isosurfaces() { - ispcEquivalent = ispc::Isosurfaces_create(); + getSh()->super.postIntersect = ispc::Isosurfaces_postIntersect_addr(); } Isosurfaces::~Isosurfaces() @@ -32,12 +31,6 @@ std::string Isosurfaces::toString() const void Isosurfaces::commit() { - if (!embreeDevice) { - throw std::runtime_error("invalid Embree device"); - } - if (!embreeGeometry) { - embreeGeometry = rtcNewGeometry(embreeDevice, RTC_GEOMETRY_TYPE_USER); - } isovaluesData = getParamDataT("isovalue", true, true); model = nullptr; @@ -86,13 +79,14 @@ void Isosurfaces::commit() vklCommit(vklHitContext); - ispc::Isosurfaces_set(getIE(), - embreeGeometry, - isovaluesData->size(), - isovaluesData->data(), - model ? model->getIE() : nullptr, - volume ? volume->getSh() : nullptr, - vklHitContext); + createEmbreeUserGeometry((RTCBoundsFunction)&ispc::Isosurfaces_bounds, + (RTCIntersectFunctionN)&ispc::Isosurfaces_intersect, + (RTCOccludedFunctionN)&ispc::Isosurfaces_occluded); + getSh()->isovalues = isovaluesData->data(); + getSh()->volumetricModel = model ? model->getSh() : nullptr; + getSh()->volume = volume ? volume->getSh() : nullptr; + getSh()->super.numPrimitives = numPrimitives(); + getSh()->vklHitContext = vklHitContext; postCreationInfo(); } diff --git a/modules/cpu/geometry/Isosurfaces.h b/modules/cpu/geometry/Isosurfaces.h index 98367a98cc..9990b149b3 100644 --- a/modules/cpu/geometry/Isosurfaces.h +++ b/modules/cpu/geometry/Isosurfaces.h @@ -1,14 +1,17 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Geometry.h" #include "volume/VolumetricModel.h" +// ispc shared +#include "IsosurfacesShared.h" namespace ospray { -struct OSPRAY_SDK_INTERFACE Isosurfaces : public Geometry +struct OSPRAY_SDK_INTERFACE Isosurfaces + : public AddStructShared { Isosurfaces(); virtual ~Isosurfaces() override; diff --git a/modules/cpu/geometry/Isosurfaces.ispc b/modules/cpu/geometry/Isosurfaces.ispc index 11a7888161..529e504785 100644 --- a/modules/cpu/geometry/Isosurfaces.ispc +++ b/modules/cpu/geometry/Isosurfaces.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray @@ -8,18 +8,9 @@ #include "openvkl/iterator.isph" #include "rkcommon/math/box.ih" #include "rkcommon/math/vec.ih" -#include "volume/Volume.ih" - -struct Isosurfaces -{ - Geometry super; //!< inherited geometry fields - float *isovalues; - // For backwards compatibility, a volumetric model was used to set - // the volume and color - VolumetricModel *volumetricModel; - Volume *volume; - VKLHitIteratorContext vklHitContext; -}; +#include "volume/VolumetricModel.ih" +// c++ shared +#include "IsosurfacesShared.h" int Isosurfaces_primID(const Isosurfaces *uniform self, const float isovalue) { @@ -40,7 +31,7 @@ Volume *uniform Isosurfaces_getVolume(const Isosurfaces *uniform self) return self->volumetricModel->volume; } -unmasked void Isosurfaces_bounds(const RTCBoundsFunctionArguments *uniform args) +export void Isosurfaces_bounds(const RTCBoundsFunctionArguments *uniform args) { uniform Isosurfaces *uniform self = (uniform Isosurfaces * uniform) args->geometryUserPtr; @@ -97,20 +88,20 @@ void Isosurfaces_intersect_kernel( } } -unmasked void Isosurfaces_intersect( +export void Isosurfaces_intersect( const struct RTCIntersectFunctionNArguments *uniform args) { Isosurfaces_intersect_kernel(args, false); } -unmasked void Isosurfaces_occluded( +export void Isosurfaces_occluded( const struct RTCOccludedFunctionNArguments *uniform args) { Isosurfaces_intersect_kernel( (RTCIntersectFunctionNArguments * uniform) args, true); } -static void Isosurfaces_postIntersect(const Geometry *uniform geometry, +void Isosurfaces_postIntersect(const Geometry *uniform geometry, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags) @@ -132,38 +123,7 @@ static void Isosurfaces_postIntersect(const Geometry *uniform geometry, } } -export void *uniform Isosurfaces_create() -{ - uniform Isosurfaces *uniform isosurfaces = uniform new uniform Isosurfaces; - Geometry_Constructor(&isosurfaces->super, Isosurfaces_postIntersect); - return isosurfaces; -} - -export void *uniform Isosurfaces_set(void *uniform _self, - void *uniform _embreeGeometry, - int32 uniform numIsovalues, - uniform float *uniform isovalues, - void *uniform _volumetricModel, - void *uniform _volume, - void *uniform _vklHitContext) +export void *uniform Isosurfaces_postIntersect_addr() { - Isosurfaces *uniform self = (Isosurfaces * uniform) _self; - VolumetricModel *uniform volumetricModel = - (VolumetricModel * uniform) _volumetricModel; - Volume *uniform volume = (Volume * uniform) _volume; - VKLHitIteratorContext vklHitContext = (VKLHitIteratorContext)_vklHitContext; - - self->isovalues = isovalues; - self->volumetricModel = volumetricModel; - self->volume = volume; - self->super.numPrimitives = 1; // for embree it is just one prim - self->vklHitContext = vklHitContext; - - Geometry_setEmbreeUserGeometry(&self->super, - (RTCGeometry)_embreeGeometry, - Isosurfaces_bounds, - Isosurfaces_intersect, - Isosurfaces_occluded); - - self->super.numPrimitives = numIsovalues; + return Isosurfaces_postIntersect; } diff --git a/modules/cpu/geometry/IsosurfacesShared.h b/modules/cpu/geometry/IsosurfacesShared.h new file mode 100644 index 0000000000..8fd2db800c --- /dev/null +++ b/modules/cpu/geometry/IsosurfacesShared.h @@ -0,0 +1,33 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "GeometryShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +struct Isosurfaces +{ + Geometry super; // inherited geometry fields + float *isovalues; + // For backwards compatibility, a volumetric model was used to set + // the volume and color + VolumetricModel *volumetricModel; + Volume *volume; + VKLHitIteratorContext vklHitContext; + +#ifdef __cplusplus + Isosurfaces() + : isovalues(nullptr), + volumetricModel(nullptr), + volume(nullptr), + vklHitContext(nullptr) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/geometry/Mesh.cpp b/modules/cpu/geometry/Mesh.cpp index 7c134cb9ee..8547673a7e 100644 --- a/modules/cpu/geometry/Mesh.cpp +++ b/modules/cpu/geometry/Mesh.cpp @@ -1,19 +1,20 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Mesh.h" -#include "ospray/ospray.h" -#include "common/World.h" +#include "common/DGEnum.h" // ispc exports -#include #include "geometry/Mesh_ispc.h" +// std +#include namespace ospray { Mesh::Mesh() { - ispcEquivalent = ispc::Mesh_create(); + getSh()->super.getAreas = ispc::Mesh_getAreas_addr(); + getSh()->super.sampleArea = ispc::Mesh_sampleArea_addr(); } std::string Mesh::toString() const @@ -23,15 +24,9 @@ std::string Mesh::toString() const void Mesh::commit() { - if (embreeGeometry) - rtcReleaseGeometry(embreeGeometry); - - if (!embreeDevice) { - throw std::runtime_error("invalid Embree device"); - } - motionVertexAddr.clear(); motionNormalAddr.clear(); + bool isNormalFaceVarying = true; motionVertexData = getParamDataT *>("motion.vertex.position"); @@ -49,12 +44,16 @@ void Mesh::commit() " of same size and stride and have type vec3f"); motionVertexAddr.push_back(vtxData->data()); } - motionNormalData = - getParamDataT *>("motion.vertex.normal"); + motionNormalData = getParamDataT *>("motion.normal"); + if (!motionNormalData) { + motionNormalData = + getParamDataT *>("motion.vertex.normal"); + isNormalFaceVarying = false; + } if (motionNormalData) { if (motionNormalData->size() < motionVertexData->size()) throw std::runtime_error( - "Mesh 'motion.vertex.normal' array has less keys than" + "Mesh 'motion*.normal' array has less keys than" " 'motion.vertex.position'"); // check types and strides normalData = (*motionNormalData)[0]; // use 1st key as fallback @@ -63,7 +62,7 @@ void Mesh::commit() if (norData->type != OSP_VEC3F || norData->ispc.numItems != size || norData->ispc.byteStride != stride) throw std::runtime_error( - "Mesh 'motion.vertex.normal' arrays need to be" + "Mesh 'motion*.normal' arrays need to be" " of same size and stride and have type vec3f"); motionNormalAddr.push_back(norData->data()); } @@ -72,18 +71,32 @@ void Mesh::commit() } else { motionBlur = false; vertexData = getParamDataT("vertex.position", true); - normalData = getParamDataT("vertex.normal"); + normalData = getParamDataT("normal"); + if (!normalData) { + normalData = getParamDataT("vertex.normal"); + isNormalFaceVarying = false; + } } - colorData = getParam("vertex.color"); - texcoordData = getParamDataT("vertex.texcoord"); + colorData = getParam("color"); + bool isColorFaceVarying = true; + if (!colorData) { + colorData = getParam("vertex.color"); + isColorFaceVarying = false; + } + bool isTexcoordFaceVarying = true; + texcoordData = getParamDataT("texcoord"); + if (!texcoordData) { + texcoordData = getParamDataT("vertex.texcoord"); + isTexcoordFaceVarying = false; + } indexData = getParamDataT("index"); if (!indexData) indexData = getParamDataT("index", true); const bool isTri = indexData->type == OSP_VEC3UI; - embreeGeometry = rtcNewGeometry(embreeDevice, + createEmbreeGeometry( isTri ? RTC_GEOMETRY_TYPE_TRIANGLE : RTC_GEOMETRY_TYPE_QUAD); time = range1f(0.0f, 1.0f); @@ -112,18 +125,31 @@ void Mesh::commit() indexData->size()); rtcCommitGeometry(embreeGeometry); - ispc::Mesh_set(getIE(), - ispc(indexData), - ispc(vertexData), - ispc(normalData), - ispc(colorData), - ispc(texcoordData), - motionVertexAddr.data(), - motionNormalAddr.data(), - motionBlur ? motionVertexData->size() : 0, - (const ispc::box1f &)time, - colorData && colorData->type == OSP_VEC4F, - isTri); + getSh()->isColorFaceVarying = isColorFaceVarying; + getSh()->isTexcoordFaceVarying = isTexcoordFaceVarying; + getSh()->isNormalFaceVarying = isNormalFaceVarying; + getSh()->index = *ispc(indexData); + getSh()->vertex = *ispc(vertexData); + getSh()->normal = *ispc(normalData); + getSh()->color = *ispc(colorData); + getSh()->texcoord = *ispc(texcoordData); + getSh()->motionVertex = (uint8_t **)motionVertexAddr.data(); + getSh()->motionNormal = (uint8_t **)motionNormalAddr.data(); + getSh()->motionKeys = motionBlur ? motionVertexData->size() : 0; + getSh()->time = time; + getSh()->has_alpha = colorData && colorData->type == OSP_VEC4F; + getSh()->is_triangleMesh = isTri; + getSh()->super.numPrimitives = numPrimitives(); + getSh()->super.postIntersect = isTri ? ispc::TriangleMesh_PostIntersect_addr() + : ispc::QuadMesh_postIntersect_addr(); + + getSh()->flagMask = -1; + if (!normalData) + getSh()->flagMask &= ispc::int64(~DG_NS); + if (!colorData) + getSh()->flagMask &= ispc::int64(~DG_COLOR); + if (!texcoordData) + getSh()->flagMask &= ispc::int64(~DG_TEXCOORD); postCreationInfo(vertexData->size()); } diff --git a/modules/cpu/geometry/Mesh.h b/modules/cpu/geometry/Mesh.h index 33c83d38ea..dcfbb95740 100644 --- a/modules/cpu/geometry/Mesh.h +++ b/modules/cpu/geometry/Mesh.h @@ -1,14 +1,16 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Geometry.h" #include "common/Data.h" +// ispc shared +#include "MeshShared.h" namespace ospray { -struct OSPRAY_SDK_INTERFACE Mesh : public Geometry +struct OSPRAY_SDK_INTERFACE Mesh : public AddStructShared { Mesh(); virtual ~Mesh() override = default; diff --git a/modules/cpu/geometry/Mesh.ispc b/modules/cpu/geometry/Mesh.ispc index 0a06adb0ab..15eeba0d30 100644 --- a/modules/cpu/geometry/Mesh.ispc +++ b/modules/cpu/geometry/Mesh.ispc @@ -1,29 +1,13 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Geometry.ih" #include "common/Data.ih" -#include "common/World.ih" #include "math/LinearSpace.ih" #include "math/sampling.ih" - -struct Mesh -{ - Geometry super; - Data1D index; - Data1D vertex; - Data1D normal; - Data1D color; - Data1D texcoord; - uint8 **motionVertex; - uint8 **motionNormal; - uint32 motionKeys; - box1f time; - int64 flagMask; // which attributes are missing and cannot be interpolated - bool has_alpha; // 4th color component is valid - bool is_triangleMesh; -}; +// c++ shared +#include "MeshShared.h" // Create quad_interpolate for vec2f, vec3f, and vec4f types #define __define_quad_interpolate(T) \ @@ -61,7 +45,7 @@ inline vec3f interpolate_vec3f(const uniform int64 byteStride, return lerp(t, v0, v1); } -static void QuadMesh_postIntersect(const Geometry *uniform _self, +void QuadMesh_postIntersect(const Geometry *uniform _self, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags) @@ -69,6 +53,9 @@ static void QuadMesh_postIntersect(const Geometry *uniform _self, Mesh *uniform self = (Mesh * uniform) _self; dg.Ng = dg.Ns = ray.Ng; const vec4ui index = get_vec4ui(self->index, ray.primID); + const iOffset = ray.primID * 4; + const vec4ui findex = make_vec4ui( + iOffset, iOffset + 1, iOffset + 2, iOffset + 3); // face indices const float u = ray.u; const float v = ray.v; vec4f uv; @@ -87,31 +74,33 @@ static void QuadMesh_postIntersect(const Geometry *uniform _self, flags &= self->flagMask; if (flags & DG_NS) { + const vec4ui tindex = self->isNormalFaceVarying ? findex : index; if (self->motionKeys) { int idx; const float t = Mesh_calcKey(self, ray.time, idx); const uniform int64 byteStride = self->normal.byteStride; const uint8 *a0 = self->motionNormal[idx]; const uint8 *a1 = self->motionNormal[idx + 1]; - const vec3f a = interpolate_vec3f(byteStride, a0, a1, index.x, t); - const vec3f b = interpolate_vec3f(byteStride, a0, a1, index.y, t); - const vec3f c = interpolate_vec3f(byteStride, a0, a1, index.z, t); - const vec3f d = interpolate_vec3f(byteStride, a0, a1, index.w, t); + const vec3f a = interpolate_vec3f(byteStride, a0, a1, tindex.x, t); + const vec3f b = interpolate_vec3f(byteStride, a0, a1, tindex.y, t); + const vec3f c = interpolate_vec3f(byteStride, a0, a1, tindex.z, t); + const vec3f d = interpolate_vec3f(byteStride, a0, a1, tindex.w, t); dg.Ns = quad_interpolate(uv, a, b, c, d); } else { - const vec3f a = get_vec3f(self->normal, index.x); - const vec3f b = get_vec3f(self->normal, index.y); - const vec3f c = get_vec3f(self->normal, index.z); - const vec3f d = get_vec3f(self->normal, index.w); + const vec3f a = get_vec3f(self->normal, tindex.x); + const vec3f b = get_vec3f(self->normal, tindex.y); + const vec3f c = get_vec3f(self->normal, tindex.z); + const vec3f d = get_vec3f(self->normal, tindex.w); dg.Ns = quad_interpolate(uv, a, b, c, d); } } if (flags & DG_COLOR) { - const vec4f a = get_vec4f(self->color, index.x); - const vec4f b = get_vec4f(self->color, index.y); - const vec4f c = get_vec4f(self->color, index.z); - const vec4f d = get_vec4f(self->color, index.w); + const vec4ui tindex = self->isColorFaceVarying ? findex : index; + const vec4f a = get_vec4f(self->color, tindex.x); + const vec4f b = get_vec4f(self->color, tindex.y); + const vec4f c = get_vec4f(self->color, tindex.z); + const vec4f d = get_vec4f(self->color, tindex.w); dg.color = quad_interpolate(uv, a, b, c, d); if (!self->has_alpha) dg.color.w = 1.f; @@ -120,11 +109,12 @@ static void QuadMesh_postIntersect(const Geometry *uniform _self, const uniform bool compute_texcoord = flags & DG_TEXCOORD; bool compute_tangents = flags & DG_TANGENTS; if (and(or (compute_texcoord, compute_tangents), valid(self->texcoord))) { - const vec2f a = get_vec2f(self->texcoord, index.x); - const vec2f b = get_vec2f(self->texcoord, index.y); - const vec2f d = get_vec2f(self->texcoord, index.w); + const vec4ui tindex = self->isTexcoordFaceVarying ? findex : index; + const vec2f a = get_vec2f(self->texcoord, tindex.x); + const vec2f b = get_vec2f(self->texcoord, tindex.y); + const vec2f d = get_vec2f(self->texcoord, tindex.w); if (compute_texcoord) { - const vec2f c = get_vec2f(self->texcoord, index.z); + const vec2f c = get_vec2f(self->texcoord, tindex.z); dg.st = quad_interpolate(uv, a, b, c, d); } if (compute_tangents) { @@ -164,7 +154,7 @@ static void QuadMesh_postIntersect(const Geometry *uniform _self, } } -static void TriangleMesh_PostIntersect(const Geometry *uniform _self, +void TriangleMesh_PostIntersect(const Geometry *uniform _self, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags) @@ -172,33 +162,38 @@ static void TriangleMesh_PostIntersect(const Geometry *uniform _self, Mesh *uniform self = (Mesh * uniform) _self; dg.Ng = dg.Ns = ray.Ng; const vec3ui index = get_vec3ui(self->index, ray.primID); + const iOffset = ray.primID * 3; + const vec3ui findex = + make_vec3ui(iOffset, iOffset + 1, iOffset + 2); // face indices const vec3f uv = make_vec3f(1.0f - ray.u - ray.v, ray.u, ray.v); flags &= self->flagMask; if (flags & DG_NS) { + const vec3ui tindex = self->isNormalFaceVarying ? findex : index; if (self->motionKeys) { int idx; const float t = Mesh_calcKey(self, ray.time, idx); const uniform int64 byteStride = self->normal.byteStride; const uint8 *a0 = self->motionNormal[idx]; const uint8 *a1 = self->motionNormal[idx + 1]; - const vec3f a = interpolate_vec3f(byteStride, a0, a1, index.x, t); - const vec3f b = interpolate_vec3f(byteStride, a0, a1, index.y, t); - const vec3f c = interpolate_vec3f(byteStride, a0, a1, index.z, t); + const vec3f a = interpolate_vec3f(byteStride, a0, a1, tindex.x, t); + const vec3f b = interpolate_vec3f(byteStride, a0, a1, tindex.y, t); + const vec3f c = interpolate_vec3f(byteStride, a0, a1, tindex.z, t); dg.Ns = interpolate(uv, a, b, c); } else { - const vec3f a = get_vec3f(self->normal, index.x); - const vec3f b = get_vec3f(self->normal, index.y); - const vec3f c = get_vec3f(self->normal, index.z); + const vec3f a = get_vec3f(self->normal, tindex.x); + const vec3f b = get_vec3f(self->normal, tindex.y); + const vec3f c = get_vec3f(self->normal, tindex.z); dg.Ns = interpolate(uv, a, b, c); } } if (flags & DG_COLOR) { - const vec4f a = get_vec4f(self->color, index.x); - const vec4f b = get_vec4f(self->color, index.y); - const vec4f c = get_vec4f(self->color, index.z); + const vec3ui tindex = self->isColorFaceVarying ? findex : index; + const vec4f a = get_vec4f(self->color, tindex.x); + const vec4f b = get_vec4f(self->color, tindex.y); + const vec4f c = get_vec4f(self->color, tindex.z); dg.color = interpolate(uv, a, b, c); if (!self->has_alpha) dg.color.w = 1.f; @@ -207,9 +202,10 @@ static void TriangleMesh_PostIntersect(const Geometry *uniform _self, const uniform bool compute_texcoord = flags & DG_TEXCOORD; bool compute_tangents = flags & DG_TANGENTS; if (and(or (compute_texcoord, compute_tangents), valid(self->texcoord))) { - const vec2f a = get_vec2f(self->texcoord, index.x); - const vec2f b = get_vec2f(self->texcoord, index.y); - const vec2f c = get_vec2f(self->texcoord, index.z); + const vec3ui tindex = self->isTexcoordFaceVarying ? findex : index; + const vec2f a = get_vec2f(self->texcoord, tindex.x); + const vec2f b = get_vec2f(self->texcoord, tindex.y); + const vec2f c = get_vec2f(self->texcoord, tindex.z); if (compute_texcoord) dg.st = interpolate(uv, a, b, c); if (compute_tangents) { @@ -351,59 +347,22 @@ void Mesh_getAreas(const Geometry *const uniform _self, } } -void Mesh_Constructor(Mesh *uniform self) +export void *uniform QuadMesh_postIntersect_addr() { - Geometry_Constructor(&self->super, NULL); - self->super.getAreas = Mesh_getAreas; - self->super.sampleArea = Mesh_sampleArea; - Data1D_Constructor(&self->index); - Data1D_Constructor(&self->vertex); - Data1D_Constructor(&self->normal); - Data1D_Constructor(&self->color); - Data1D_Constructor(&self->texcoord); + return QuadMesh_postIntersect; } -export void *uniform Mesh_create() +export void *uniform TriangleMesh_PostIntersect_addr() { - Mesh *uniform self = uniform new Mesh; - Mesh_Constructor(self); - return self; + return TriangleMesh_PostIntersect; } -export void *uniform Mesh_set(void *uniform _self, - const Data1D *uniform index, - const Data1D *uniform vertex, - const Data1D *uniform normal, - const Data1D *uniform color, - const Data1D *uniform texcoord, - void *uniform motionVertex, - void *uniform motionNormal, - uniform unsigned int motionKeys, - const uniform box1f &time, - uniform bool has_alpha, - uniform bool is_triangleMesh) +export void *uniform Mesh_sampleArea_addr() { - Mesh *uniform self = (Mesh * uniform) _self; - self->index = *index; - self->vertex = *vertex; - self->normal = *normal; - self->color = *color; - self->texcoord = *texcoord; - self->motionVertex = (uint8 * *uniform) motionVertex; - self->motionNormal = (uint8 * *uniform) motionNormal; - self->motionKeys = motionKeys; - self->time = time; - self->has_alpha = has_alpha; - self->super.numPrimitives = index->numItems; - self->is_triangleMesh = is_triangleMesh; - self->super.postIntersect = self->is_triangleMesh ? TriangleMesh_PostIntersect - : QuadMesh_postIntersect; + return Mesh_sampleArea; +} - self->flagMask = -1; - if (!valid(self->normal)) - self->flagMask &= ~DG_NS; - if (!valid(self->color)) - self->flagMask &= ~DG_COLOR; - if (!valid(self->texcoord)) - self->flagMask &= ~DG_TEXCOORD; +export void *uniform Mesh_getAreas_addr() +{ + return Mesh_getAreas; } diff --git a/modules/cpu/geometry/MeshShared.h b/modules/cpu/geometry/MeshShared.h new file mode 100644 index 0000000000..356c01ae81 --- /dev/null +++ b/modules/cpu/geometry/MeshShared.h @@ -0,0 +1,48 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "GeometryShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +struct Mesh +{ + Geometry super; + Data1D index; + Data1D vertex; + Data1D normal; + Data1D color; + Data1D texcoord; + uint8 **motionVertex; + uint8 **motionNormal; + uint32 motionKeys; + box1f time; + int64 flagMask; // which attributes are missing and cannot be interpolated + bool has_alpha; // 4th color component is valid + bool is_triangleMesh; + bool isColorFaceVarying; + bool isTexcoordFaceVarying; + bool isNormalFaceVarying; + +#ifdef __cplusplus + Mesh() + : motionVertex(nullptr), + motionNormal(nullptr), + motionKeys(0), + time(0.f, 1.f), + flagMask(-1), + has_alpha(false), + is_triangleMesh(false), + isColorFaceVarying(false), + isTexcoordFaceVarying(false), + isNormalFaceVarying(false) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/geometry/Planes.cpp b/modules/cpu/geometry/Planes.cpp index d329f3f1e7..0b14a9ec13 100644 --- a/modules/cpu/geometry/Planes.cpp +++ b/modules/cpu/geometry/Planes.cpp @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Intel Corporation +// Copyright 2019 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #undef NDEBUG @@ -6,7 +6,6 @@ // ospray #include "Planes.h" #include "common/Data.h" -#include "common/World.h" // ispc-generated files #include "geometry/Planes_ispc.h" @@ -14,7 +13,7 @@ namespace ospray { Planes::Planes() { - ispcEquivalent = ispc::Planes_create(); + getSh()->super.postIntersect = ispc::Planes_postIntersect_addr(); } std::string Planes::toString() const @@ -24,17 +23,15 @@ std::string Planes::toString() const void Planes::commit() { - if (!embreeDevice) { - throw std::runtime_error("invalid Embree device"); - } - if (!embreeGeometry) { - embreeGeometry = rtcNewGeometry(embreeDevice, RTC_GEOMETRY_TYPE_USER); - } - coeffsData = getParamDataT("plane.coefficients", true); boundsData = getParamDataT("plane.bounds"); - ispc::Planes_set(getIE(), embreeGeometry, ispc(coeffsData), ispc(boundsData)); + createEmbreeUserGeometry((RTCBoundsFunction)&ispc::Planes_bounds, + (RTCIntersectFunctionN)&ispc::Planes_intersect, + (RTCOccludedFunctionN)&ispc::Planes_occluded); + getSh()->coeffs = *ispc(coeffsData); + getSh()->bounds = *ispc(boundsData); + getSh()->super.numPrimitives = numPrimitives(); postCreationInfo(); } diff --git a/modules/cpu/geometry/Planes.h b/modules/cpu/geometry/Planes.h index ac2ccb7b88..4256177e48 100644 --- a/modules/cpu/geometry/Planes.h +++ b/modules/cpu/geometry/Planes.h @@ -1,13 +1,16 @@ -// Copyright 2019-2020 Intel Corporation +// Copyright 2019 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Geometry.h" +// ispc shared +#include "PlanesShared.h" namespace ospray { -struct OSPRAY_SDK_INTERFACE Planes : public Geometry +struct OSPRAY_SDK_INTERFACE Planes + : public AddStructShared { Planes(); virtual ~Planes() override = default; diff --git a/modules/cpu/geometry/Planes.ispc b/modules/cpu/geometry/Planes.ispc index 6d957ffca3..805d73dcb2 100644 --- a/modules/cpu/geometry/Planes.ispc +++ b/modules/cpu/geometry/Planes.ispc @@ -1,27 +1,23 @@ -// Copyright 2019-2022 Intel Corporation +// Copyright 2019 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "common/Data.ih" +#include "common/DifferentialGeometry.ih" #include "common/FilterIntersect.ih" #include "common/Intersect.ih" #include "common/Ray.ih" -#include "common/World.ih" #include "geometry/Geometry.ih" #include "rkcommon/math/box.ih" #include "rkcommon/math/vec.ih" +// c++ shared +#include "PlanesShared.h" // The plane can't be truly infinite because Embree has a limit on object size #define PLANE_MAX_SIZE 1e18 +#define DUMMY_MAX_T 1e38 -struct Planes -{ - Geometry super; - Data1D coeffs; - Data1D bounds; -}; - -unmasked void Planes_bounds(const RTCBoundsFunctionArguments *uniform args) +export void Planes_bounds(const RTCBoundsFunctionArguments *uniform args) { const uniform vec3f lo = make_vec3f(-PLANE_MAX_SIZE, -PLANE_MAX_SIZE, -PLANE_MAX_SIZE); @@ -75,6 +71,19 @@ void Planes_intersect_kernel(const RTCIntersectFunctionNArguments *uniform args, if (filterIntersectionSingle(args, hit, isOcclusionTest, false)) return; + // handle plane parallel to ray, which breaks interval logic for clipping + if (!hit.hit) { + const uniform vec3f normal = make_vec3f(coeffs); + if (coeffs.w > dot(ray->org, normal)) { // within clipping half-space? + Hit hitExitDummy; + hitExitDummy.hit = true; + hitExitDummy.t = DUMMY_MAX_T; + hitExitDummy.N = ray->dir; + filterIntersectionSingle(args, hitExitDummy, isOcclusionTest, true); + } + return; + } + // The second implicit plane is needed just for infinite planes if (valid(self->bounds)) return; @@ -92,20 +101,20 @@ void Planes_intersect_kernel(const RTCIntersectFunctionNArguments *uniform args, filterIntersectionSingle(args, hitImplicit, isOcclusionTest, true); } -unmasked void Planes_intersect( +export void Planes_intersect( const struct RTCIntersectFunctionNArguments *uniform args) { Planes_intersect_kernel(args, false); } -unmasked void Planes_occluded( +export void Planes_occluded( const struct RTCOccludedFunctionNArguments *uniform args) { Planes_intersect_kernel( (RTCIntersectFunctionNArguments * uniform) args, true); } -static void Planes_postIntersect(const Geometry *uniform geometry, +void Planes_postIntersect(const Geometry *uniform geometry, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags) @@ -113,31 +122,7 @@ static void Planes_postIntersect(const Geometry *uniform geometry, dg.Ng = dg.Ns = ray.Ng; } -export void *uniform Planes_create() -{ - Planes *uniform self = uniform new Planes; - - Geometry_Constructor(&self->super, Planes_postIntersect); - Data1D_Constructor(&self->coeffs); - Data1D_Constructor(&self->bounds); - - return self; -} - -export void *uniform Planes_set(void *uniform _self, - void *uniform _embreeGeometry, - const Data1D *uniform coeffs, - const Data1D *uniform bounds) +export void *uniform Planes_postIntersect_addr() { - Planes *uniform self = (Planes * uniform) _self; - - self->coeffs = *coeffs; - self->bounds = *bounds; - self->super.numPrimitives = coeffs->numItems; - - Geometry_setEmbreeUserGeometry(&self->super, - (RTCGeometry)_embreeGeometry, - Planes_bounds, - Planes_intersect, - Planes_occluded); + return Planes_postIntersect; } diff --git a/modules/cpu/geometry/PlanesShared.h b/modules/cpu/geometry/PlanesShared.h new file mode 100644 index 0000000000..8050e0c072 --- /dev/null +++ b/modules/cpu/geometry/PlanesShared.h @@ -0,0 +1,21 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "GeometryShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +struct Planes +{ + Geometry super; + Data1D coeffs; + Data1D bounds; +}; + +#ifdef __cplusplus +} // namespace ispc +#endif // __cplusplus diff --git a/modules/cpu/geometry/Spheres.cpp b/modules/cpu/geometry/Spheres.cpp index e553c73563..3b5debf458 100644 --- a/modules/cpu/geometry/Spheres.cpp +++ b/modules/cpu/geometry/Spheres.cpp @@ -1,10 +1,9 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Spheres.h" #include "common/Data.h" -#include "common/World.h" // ispc-generated files #include "geometry/Spheres_ispc.h" @@ -12,7 +11,9 @@ namespace ospray { Spheres::Spheres() { - ispcEquivalent = ispc::Spheres_create(); + getSh()->super.postIntersect = ispc::Spheres_postIntersect_addr(); + getSh()->super.getAreas = ispc::Spheres_getAreas_addr(); + getSh()->super.sampleArea = ispc::Spheres_sampleArea_addr(); } std::string Spheres::toString() const @@ -22,23 +23,19 @@ std::string Spheres::toString() const void Spheres::commit() { - if (!embreeDevice) { - throw std::runtime_error("invalid Embree device"); - } - if (!embreeGeometry) { - embreeGeometry = rtcNewGeometry(embreeDevice, RTC_GEOMETRY_TYPE_USER); - } radius = getParam("radius", 0.01f); vertexData = getParamDataT("sphere.position", true); radiusData = getParamDataT("sphere.radius"); texcoordData = getParamDataT("sphere.texcoord"); - ispc::SpheresGeometry_set(getIE(), - embreeGeometry, - ispc(vertexData), - ispc(radiusData), - ispc(texcoordData), - radius); + createEmbreeUserGeometry((RTCBoundsFunction)&ispc::Spheres_bounds, + (RTCIntersectFunctionN)&ispc::Spheres_intersect, + (RTCOccludedFunctionN)&ispc::Spheres_occluded); + getSh()->vertex = *ispc(vertexData); + getSh()->radius = *ispc(radiusData); + getSh()->texcoord = *ispc(texcoordData); + getSh()->global_radius = radius; + getSh()->super.numPrimitives = numPrimitives(); postCreationInfo(); } diff --git a/modules/cpu/geometry/Spheres.h b/modules/cpu/geometry/Spheres.h index f747acf39f..9513cdace9 100644 --- a/modules/cpu/geometry/Spheres.h +++ b/modules/cpu/geometry/Spheres.h @@ -1,13 +1,16 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Geometry.h" +// ispc shared +#include "SpheresShared.h" namespace ospray { -struct OSPRAY_SDK_INTERFACE Spheres : public Geometry +struct OSPRAY_SDK_INTERFACE Spheres + : public AddStructShared { Spheres(); virtual ~Spheres() override = default; @@ -19,7 +22,7 @@ struct OSPRAY_SDK_INTERFACE Spheres : public Geometry virtual size_t numPrimitives() const override; protected: - float radius{0.01}; // default radius, if no per-sphere radius + float radius{.01f}; // default radius, if no per-sphere radius Ref> vertexData; Ref> radiusData; Ref> texcoordData; diff --git a/modules/cpu/geometry/Spheres.ispc b/modules/cpu/geometry/Spheres.ispc index 91ea3e784a..d733216c1e 100644 --- a/modules/cpu/geometry/Spheres.ispc +++ b/modules/cpu/geometry/Spheres.ispc @@ -1,28 +1,21 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "common/Data.ih" +#include "common/DifferentialGeometry.ih" #include "common/FilterIntersect.ih" #include "common/ISPCMessages.h" #include "common/Intersect.ih" #include "common/Ray.ih" -#include "common/World.ih" #include "geometry/Geometry.ih" #include "math/sampling.ih" #include "rkcommon/math/box.ih" #include "rkcommon/math/vec.ih" +// c++ shared +#include "SpheresShared.h" -struct Spheres -{ - Geometry super; - Data1D vertex; - Data1D radius; - Data1D texcoord; - float global_radius; -}; - -static void Spheres_postIntersect(const Geometry *uniform geometry, +void Spheres_postIntersect(const Geometry *uniform geometry, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags) @@ -43,7 +36,7 @@ static void Spheres_postIntersect(const Geometry *uniform geometry, dg.st = get_vec2f(self->texcoord, ray.primID); } -unmasked void Spheres_bounds(const RTCBoundsFunctionArguments *uniform args) +export void Spheres_bounds(const RTCBoundsFunctionArguments *uniform args) { Spheres *uniform self = (Spheres * uniform) args->geometryUserPtr; uniform int primID = args->primID; @@ -79,13 +72,13 @@ void Spheres_intersect_kernel( filterIntersectionBoth(args, isect, isOcclusionTest); } -unmasked void Spheres_intersect( +export void Spheres_intersect( const struct RTCIntersectFunctionNArguments *uniform args) { Spheres_intersect_kernel(args, false); } -unmasked void Spheres_occluded( +export void Spheres_occluded( const struct RTCOccludedFunctionNArguments *uniform args) { Spheres_intersect_kernel((RTCIntersectFunctionNArguments *)args, true); @@ -144,42 +137,17 @@ void Spheres_getAreas(const Geometry *const uniform _self, } } -void Spheres_Constructor(Spheres *uniform self) +export void *uniform Spheres_postIntersect_addr() { - Geometry_Constructor(&self->super, Spheres_postIntersect); - self->super.getAreas = Spheres_getAreas; - self->super.sampleArea = Spheres_sampleArea; - Data1D_Constructor(&self->vertex); - Data1D_Constructor(&self->radius); - Data1D_Constructor(&self->texcoord); - self->global_radius = 0.01; + return Spheres_postIntersect; } -export void *uniform Spheres_create() +export void *uniform Spheres_sampleArea_addr() { - Spheres *uniform self = uniform new Spheres; - Spheres_Constructor(self); - return self; + return Spheres_sampleArea; } -export void SpheresGeometry_set(void *uniform _self, - void *uniform _embreeGeometry, - const Data1D *uniform vertex, - const Data1D *uniform radius, - const Data1D *uniform texcoord, - uniform float global_radius) +export void *uniform Spheres_getAreas_addr() { - Spheres *uniform self = (Spheres * uniform) _self; - - self->vertex = *vertex; - self->radius = *radius; - self->texcoord = *texcoord; - self->global_radius = global_radius; - self->super.numPrimitives = vertex->numItems; - - Geometry_setEmbreeUserGeometry(&self->super, - (RTCGeometry)_embreeGeometry, - Spheres_bounds, - Spheres_intersect, - Spheres_occluded); + return Spheres_getAreas; } diff --git a/modules/cpu/geometry/SpheresShared.h b/modules/cpu/geometry/SpheresShared.h new file mode 100644 index 0000000000..fe69a64855 --- /dev/null +++ b/modules/cpu/geometry/SpheresShared.h @@ -0,0 +1,26 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "GeometryShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +struct Spheres +{ + Geometry super; + Data1D vertex; + Data1D radius; + Data1D texcoord; + float global_radius; + +#ifdef __cplusplus + Spheres() : global_radius(.01f) {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/geometry/Subdivision.cpp b/modules/cpu/geometry/Subdivision.cpp index 3784a0be02..97711cae1e 100644 --- a/modules/cpu/geometry/Subdivision.cpp +++ b/modules/cpu/geometry/Subdivision.cpp @@ -1,10 +1,10 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Subdivision.h" -#include "ospray/ospray.h" -#include "common/World.h" +#include "common/DGEnum.h" + // ispc exports #include #include "geometry/Subdivision_ispc.h" @@ -13,7 +13,7 @@ namespace ospray { Subdivision::Subdivision() { - ispcEquivalent = ispc::Subdivision_create(); + getSh()->super.postIntersect = ispc::Subdivision_postIntersect_addr(); } std::string Subdivision::toString() const @@ -23,17 +23,21 @@ std::string Subdivision::toString() const void Subdivision::commit() { - if (!embreeDevice) { - throw std::runtime_error("invalid Embree device"); - } - if (!embreeGeometry) { - embreeGeometry = - rtcNewGeometry(embreeDevice, RTC_GEOMETRY_TYPE_SUBDIVISION); - } + createEmbreeGeometry(RTC_GEOMETRY_TYPE_SUBDIVISION); vertexData = getParamDataT("vertex.position", true); - colorsData = getParamDataT("vertex.color"); - texcoordData = getParamDataT("vertex.texcoord"); + colorsData = getParamDataT("color"); + bool isColorsFaceVarying = true; + if (!colorsData) { + colorsData = getParamDataT("vertex.color"); + isColorsFaceVarying = false; + } + texcoordData = getParamDataT("texcoord"); + bool isTexcoordFaceVarying = true; + if (!texcoordData) { + texcoordData = getParamDataT("vertex.texcoord"); + isTexcoordFaceVarying = false; + } level = getParam("level", 5.f); @@ -105,16 +109,37 @@ void Subdivision::commit() } } + if ((colorsData && isColorsFaceVarying) + || (texcoordData && isTexcoordFaceVarying)) { + if (generatedIndicesSize != indexData->size()) { + auto data = new Data(OSP_UINT, vec3ui(indexData->size(), 1, 1)); + generatedIndicesData = &(data->as()); + data->refDec(); + uint32_t *dataptr = static_cast(generatedIndicesData->data()); + for (unsigned int i = 0; i < indexData->size(); i++) + *(dataptr++) = i; + generatedIndicesSize = indexData->size(); + } + rtcSetGeometryTopologyCount(embreeGeometry, 2); + setEmbreeGeometryBuffer( + embreeGeometry, RTC_BUFFER_TYPE_INDEX, generatedIndicesData, 1); + rtcSetGeometrySubdivisionMode(embreeGeometry, 1, (RTCSubdivisionMode)mode); + } + if (colorsData) { rtcSetGeometryVertexAttributeCount(embreeGeometry, 1); setEmbreeGeometryBuffer( - embreeGeometry, RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE, colorsData); + embreeGeometry, RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE, colorsData, 0); + if (isColorsFaceVarying) + rtcSetGeometryVertexAttributeTopology(embreeGeometry, 0, 1); } if (texcoordData) { rtcSetGeometryVertexAttributeCount(embreeGeometry, 2); setEmbreeGeometryBuffer( embreeGeometry, RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE, texcoordData, 1); + if (isTexcoordFaceVarying) + rtcSetGeometryVertexAttributeTopology(embreeGeometry, 1, 1); } if (!indexLevelData) @@ -126,7 +151,13 @@ void Subdivision::commit() rtcCommitGeometry(embreeGeometry); - ispc::Subdivision_set(getIE(), embreeGeometry, colorsData, texcoordData); + getSh()->geom = embreeGeometry; + getSh()->flagMask = -1; + if (!colorsData) + getSh()->flagMask &= ispc::int64(~DG_COLOR); + if (!texcoordData) + getSh()->flagMask &= ispc::int64(~DG_TEXCOORD); + getSh()->super.numPrimitives = numPrimitives(); postCreationInfo(vertexData->size()); } diff --git a/modules/cpu/geometry/Subdivision.h b/modules/cpu/geometry/Subdivision.h index 21e5828318..c822074f0f 100644 --- a/modules/cpu/geometry/Subdivision.h +++ b/modules/cpu/geometry/Subdivision.h @@ -1,14 +1,17 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Geometry.h" #include "common/Data.h" +// ispc shared +#include "SubdivisionShared.h" namespace ospray { -struct OSPRAY_SDK_INTERFACE Subdivision : public Geometry +struct OSPRAY_SDK_INTERFACE Subdivision + : public AddStructShared { Subdivision(); virtual ~Subdivision() override = default; @@ -24,8 +27,11 @@ struct OSPRAY_SDK_INTERFACE Subdivision : public Geometry Ref> vertexData; Ref> colorsData; + size_t generatedIndicesSize{0}; // indices for face varying params + Ref> generatedIndicesData; Ref> texcoordData; Ref> indexData; + Ref> colorIndexData; Ref> indexLevelData; Ref> facesData; Ref> edge_crease_indicesData; @@ -33,7 +39,7 @@ struct OSPRAY_SDK_INTERFACE Subdivision : public Geometry Ref> vertex_crease_indicesData; Ref> vertex_crease_weightsData; - OSPSubdivisionMode mode; + OSPSubdivisionMode mode{OSP_SUBDIVISION_SMOOTH_BOUNDARY}; }; } // namespace ospray diff --git a/modules/cpu/geometry/Subdivision.ispc b/modules/cpu/geometry/Subdivision.ispc index 0cc381de74..848475c958 100644 --- a/modules/cpu/geometry/Subdivision.ispc +++ b/modules/cpu/geometry/Subdivision.ispc @@ -1,18 +1,11 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Geometry.ih" -#include "common/World.ih" -#include "math/LinearSpace.ih" -#include "math/sampling.ih" - -struct Subdivision -{ - Geometry super; - RTCGeometry geom; - int64 flagMask; // which attributes are missing and cannot be interpolated -}; +#include "common/Data.ih" +// c++ shared +#include "SubdivisionShared.h" static void Subdivision_postIntersect(const Geometry *uniform _self, varying DifferentialGeometry &dg, @@ -40,57 +33,29 @@ static void Subdivision_postIntersect(const Geometry *uniform _self, } if (flags & DG_COLOR) { - rtcInterpolateV1(self->geom, + rtcInterpolateV0(self->geom, ray.primID, ray.u, ray.v, RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE, 0, &dg.color.x, - NULL, - NULL, 4); } if (flags & DG_TEXCOORD) { - rtcInterpolateV1(self->geom, + rtcInterpolateV0(self->geom, ray.primID, ray.u, ray.v, RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE, 1, &dg.st.x, - NULL, - NULL, 2); } } -void Subdivision_Constructor(uniform Subdivision *uniform mesh) +export void *uniform Subdivision_postIntersect_addr() { - Geometry_Constructor(&mesh->super, Subdivision_postIntersect); - - mesh->geom = NULL; - mesh->flagMask = 0; -} - -export void *uniform Subdivision_create() -{ - Subdivision *uniform mesh = uniform new Subdivision; - Subdivision_Constructor(mesh); - return mesh; -} - -export void *uniform Subdivision_set(void *uniform _mesh, - RTCGeometry geom, - uniform bool haveColor, - uniform bool haveTC) -{ - Subdivision *uniform mesh = (Subdivision * uniform) _mesh; - mesh->geom = geom; - mesh->flagMask = -1; - if (!haveColor) - mesh->flagMask &= ~DG_COLOR; - if (!haveTC) - mesh->flagMask &= ~DG_TEXCOORD; -} + return Subdivision_postIntersect; +} \ No newline at end of file diff --git a/modules/cpu/geometry/SubdivisionShared.h b/modules/cpu/geometry/SubdivisionShared.h new file mode 100644 index 0000000000..6c9fa61b62 --- /dev/null +++ b/modules/cpu/geometry/SubdivisionShared.h @@ -0,0 +1,24 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "GeometryShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +struct Subdivision +{ + Geometry super; + RTCGeometry geom; + int64 flagMask; // which attributes are missing and cannot be interpolated + +#ifdef __cplusplus + Subdivision() : geom(nullptr), flagMask(-1) {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/ispc_symbols.txt b/modules/cpu/ispc_symbols.txt index 360dbd206e..d7e3bf068c 100644 --- a/modules/cpu/ispc_symbols.txt +++ b/modules/cpu/ispc_symbols.txt @@ -2,16 +2,11 @@ Distribution2D_create___s_5B__c_unvec2i_5D_un_3C_unf_3E_, Distribution2D_destroy___un_3C_s_5B_unDistribution2D_5D__3E_, Distribution2D_pdf___un_3C_s_5B__c_unDistribution2D_5D__3E_REFs_5B__c_vyvec2f_5D_, Distribution2D_sample___un_3C_s_5B__c_unDistribution2D_5D__3E_REFs_5B__c_vyvec2f_5D_, -FrameBuffer_Constructor___un_3C_s_5B_unFrameBuffer_5D__3E_, -FrameBuffer_set___un_3C_s_5B_unFrameBuffer_5D__3E_CunuCunuuni, -Geometry_Constructor___un_3C_s_5B_unGeometry_5D__3E_un_3C____un_3C_s_5B__c_unGeometry_5D__3E_REFs_5B_vyDifferentialGeometry_5D_REFs_5B__c_vyRay_5D_unI_3E_, +FrameBuffer_runPixelOps___un_3C_s_5B_unFrameBuffer_5D__3E_REFs_5B__c_vyvec4f_5D_CvyfREFs_5B__c_vyvec3f_5D_REFs_5B__c_vyvec3f_5D_, Light_eval___un_3C_s_5B__c_unLight_5D__3E_REFs_5B__c_vyDifferentialGeometry_5D_REFs_5B__c_vyvec3f_5D_CvyfCvyfCvyf, -Renderer_Constructor___un_3C_s_5B_unRenderer_5D__3E_, Renderer_getBackground___un_3C_s_5B__c_unRenderer_5D__3E_REFs_5B__c_vyvec2f_5D_, Renderer_getMaxDepth___un_3C_s_5B__c_unRenderer_5D__3E_REFs_5B__c_vyvec2f_5D_, -World_Constructor___un_3C_s_5B_unWorld_5D__3E_, clippingIntersectionFilterV___UM_un_3C_s_5B__c_unRTCFilterFunctionNArguments_5D__3E_, delete_uniform___un_3C_unv_3E_, delete_uniform_, -precomputedZOrder_create___, get_zorder___, diff --git a/modules/cpu/ispc_tasksys.cpp b/modules/cpu/ispc_tasksys.cpp index 6993fd7653..29183d50c6 100644 --- a/modules/cpu/ispc_tasksys.cpp +++ b/modules/cpu/ispc_tasksys.cpp @@ -1,13 +1,13 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include #include +#include "common/OSPCommon.h" #include "rkcommon/memory/malloc.h" #include "rkcommon/tasking/parallel_for.h" namespace rkcommon { -#define __dllexport /**/ /* Signature of ispc-generated 'task' functions */ using ISPCTaskFunc = void (*)(void *data, @@ -22,7 +22,7 @@ using ISPCTaskFunc = void (*)(void *data, int taskCount1, int taskCount2); -extern "C" __dllexport void *ISPCAlloc( +extern "C" OSPRAY_SDK_INTERFACE void *ISPCAlloc( void **taskPtr, int64_t size, int32_t alignment) { if (*taskPtr == nullptr) @@ -33,7 +33,7 @@ extern "C" __dllexport void *ISPCAlloc( return ptr; } -extern "C" __dllexport void ISPCSync(void *task) +extern "C" OSPRAY_SDK_INTERFACE void ISPCSync(void *task) { std::vector *lst = (std::vector *)task; for (size_t i = 0; i < lst->size(); i++) @@ -41,7 +41,7 @@ extern "C" __dllexport void ISPCSync(void *task) delete lst; } -extern "C" __dllexport void ISPCLaunch(void ** /*taskPtr*/, +extern "C" OSPRAY_SDK_INTERFACE void ISPCLaunch(void ** /*taskPtr*/, void *func, void *data, int taskCount0, diff --git a/modules/cpu/lights/AmbientLight.cpp b/modules/cpu/lights/AmbientLight.cpp index bbb9d49dcd..7254482c50 100644 --- a/modules/cpu/lights/AmbientLight.cpp +++ b/modules/cpu/lights/AmbientLight.cpp @@ -1,18 +1,23 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "AmbientLight.h" #include "lights/AmbientLight_ispc.h" -#include "lights/Light_ispc.h" +// ispc shared +#include "AmbientLightShared.h" namespace ospray { -void *AmbientLight::createIE(const void *instance) const +ispc::Light *AmbientLight::createSh( + uint32_t, const ispc::Instance *instance) const { - void *ie = ispc::AmbientLight_create(); - ispc::Light_set(ie, visible, (const ispc::Instance *)instance); - ispc::AmbientLight_set(ie, (ispc::vec3f &)radiance); - return ie; + ispc::AmbientLight *sh = StructSharedCreate(); + sh->super.sample = ispc::AmbientLight_sample_addr(); + sh->super.eval = ispc::AmbientLight_eval_addr(); + sh->super.isVisible = visible; + sh->super.instance = instance; + sh->radiance = radiance; + return &sh->super; } std::string AmbientLight::toString() const diff --git a/modules/cpu/lights/AmbientLight.h b/modules/cpu/lights/AmbientLight.h index e95f2b4712..1c50ef2b93 100644 --- a/modules/cpu/lights/AmbientLight.h +++ b/modules/cpu/lights/AmbientLight.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -12,7 +12,8 @@ struct OSPRAY_SDK_INTERFACE AmbientLight : public Light { AmbientLight() = default; virtual ~AmbientLight() override = default; - virtual void *createIE(const void *instance) const override; + virtual ispc::Light *createSh( + uint32_t, const ispc::Instance *instance = nullptr) const override; virtual std::string toString() const override; virtual void commit() override; diff --git a/modules/cpu/lights/AmbientLight.ispc b/modules/cpu/lights/AmbientLight.ispc index d37828f1b3..deb5c84cb4 100644 --- a/modules/cpu/lights/AmbientLight.ispc +++ b/modules/cpu/lights/AmbientLight.ispc @@ -1,15 +1,11 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "Light.ih" +#include "common/DifferentialGeometry.ih" #include "math/LinearSpace.ih" #include "math/sampling.ih" - -struct AmbientLight -{ - Light super; //!< inherited light fields - vec3f radiance; //!< emitted RGB radiance -}; +// c++ shared +#include "AmbientLightShared.h" // Implementation ////////////////////////////////////////////////////////////////////////////// @@ -57,27 +53,15 @@ Light_EvalRes AmbientLight_eval(const Light *uniform super, return res; } -void AmbientLight_Constructor(uniform AmbientLight *uniform self) -{ - Light_Constructor(&self->super); - self->super.sample = AmbientLight_sample; - self->super.eval = AmbientLight_eval; -} - // Exports (called from C++) ////////////////////////////////////////////////////////////////////////////// -//! Create an ispc-side AmbientLight object -export void *uniform AmbientLight_create() +export void *uniform AmbientLight_sample_addr() { - uniform AmbientLight *uniform self = uniform new uniform AmbientLight; - AmbientLight_Constructor(self); - return self; + return AmbientLight_sample; } -//! Set the parameters of an ispc-side AmbientLight object -export void AmbientLight_set(void *uniform super, const uniform vec3f &radiance) +export void *uniform AmbientLight_eval_addr() { - uniform AmbientLight *uniform self = (uniform AmbientLight * uniform) super; - self->radiance = radiance; -} + return AmbientLight_eval; +} \ No newline at end of file diff --git a/modules/cpu/lights/AmbientLightShared.h b/modules/cpu/lights/AmbientLightShared.h new file mode 100644 index 0000000000..cc949e6f25 --- /dev/null +++ b/modules/cpu/lights/AmbientLightShared.h @@ -0,0 +1,23 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "LightShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +struct AmbientLight +{ + Light super; // inherited light fields + vec3f radiance; // emitted RGB radiance + +#ifdef __cplusplus + AmbientLight() : radiance(1.f) {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/lights/CylinderCapSolidAngleTable.ih b/modules/cpu/lights/CylinderCapSolidAngleTable.ih index 8a50fa9224..cff890fb86 100644 --- a/modules/cpu/lights/CylinderCapSolidAngleTable.ih +++ b/modules/cpu/lights/CylinderCapSolidAngleTable.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/lights/CylinderLight.cpp b/modules/cpu/lights/CylinderLight.cpp index 6a0fea271c..4ea1692ef7 100644 --- a/modules/cpu/lights/CylinderLight.cpp +++ b/modules/cpu/lights/CylinderLight.cpp @@ -1,27 +1,47 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "CylinderLight.h" +// embree +#include "embree3/rtcore.h" + #include "lights/CylinderLight_ispc.h" -#include "lights/Light_ispc.h" + +#include "CylinderLightShared.h" +#include "common/InstanceShared.h" namespace ospray { -CylinderLight::CylinderLight() +ispc::Light *CylinderLight::createSh( + uint32_t, const ispc::Instance *instance) const { - ispcEquivalent = ispc::CylinderLight_create(); -} + ispc::CylinderLight *sh = StructSharedCreate(); + sh->super.sample = ispc::CylinderLight_sample_addr(); + sh->super.eval = ispc::CylinderLight_eval_addr(); + sh->super.isVisible = visible; + sh->super.instance = instance; -void *CylinderLight::createIE(const void *instance) const -{ - void *ie = ispc::CylinderLight_create(); - ispc::Light_set(ie, visible, (const ispc::Instance *)instance); - ispc::CylinderLight_set(ie, - (ispc::vec3f &)radiance, - (ispc::vec3f &)position0, - (ispc::vec3f &)position1, - radius); - return ie; + const float zMax = length(position1 - position0); + if (zMax <= 0.f || radius <= 0.f) { + sh->radiance = 0.f; + return &sh->super; + } + + sh->radiance = radiance; + sh->radius = radius; + sh->pre.position0 = position0; + sh->pre.position1 = position1; + + // Enable dynamic runtime instancing or apply static transformation + if (instance) { + if (instance->motionBlur) { + sh->super.sample = ispc::CylinderLight_sample_instanced_addr(); + sh->super.eval = ispc::CylinderLight_eval_instanced_addr(); + } else + ispc::CylinderLight_Transform(sh, instance->xfm, &sh->pre); + } + + return &sh->super; } std::string CylinderLight::toString() const diff --git a/modules/cpu/lights/CylinderLight.h b/modules/cpu/lights/CylinderLight.h index a06e28aa53..917683cf8b 100644 --- a/modules/cpu/lights/CylinderLight.h +++ b/modules/cpu/lights/CylinderLight.h @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -11,9 +11,10 @@ namespace ospray { * cylindrical area into outward space */ struct OSPRAY_SDK_INTERFACE CylinderLight : public Light { - CylinderLight(); + CylinderLight() = default; virtual ~CylinderLight() override = default; - virtual void *createIE(const void *instance) const override; + virtual ispc::Light *createSh( + uint32_t, const ispc::Instance *instance = nullptr) const override; virtual std::string toString() const override; virtual void commit() override; diff --git a/modules/cpu/lights/CylinderLight.ispc b/modules/cpu/lights/CylinderLight.ispc index 95c54d49ec..d56cba7420 100644 --- a/modules/cpu/lights/CylinderLight.ispc +++ b/modules/cpu/lights/CylinderLight.ispc @@ -1,38 +1,33 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../math/AffineSpace.ih" #include "CylinderCapSolidAngleTable.ih" -#include "Light.ih" #include "SphericalQuadSampling.ih" +#include "common/DifferentialGeometry.ih" #include "common/Instance.ih" #include "common/Intersect.ih" - -// state that changes under transformations -struct CylinderLightDynamic -{ - vec3f position0; - vec3f position1; -}; - -struct CylinderLight -{ - Light super; - vec3f radiance; - float radius; - CylinderLightDynamic pre; // un- or pre-transformed state -}; +// c++ shared +#include "CylinderLightShared.h" // Implementation ////////////////////////////////////////////////////////////////////////////// inline void Transform(const CylinderLight *uniform self, - const uniform affine3f xfm, + const uniform affine3f &xfm, uniform CylinderLightDynamic &dyn) { dyn.position0 = xfmPoint(xfm, self->pre.position0); dyn.position1 = xfmPoint(xfm, self->pre.position1); } +export void CylinderLight_Transform( + const void *uniform self, const void *uniform xfm, void *uniform dyn) +{ + Transform((CylinderLight * uniform) self, + *((affine3f * uniform) xfm), + *((CylinderLightDynamic * uniform) dyn)); +} + inline float cylinderAxialSolidAngle( float c, float b, float h0, float h1, float b2c2) { @@ -269,45 +264,22 @@ Light_EvalRes CylinderLight_eval_instanced(const Light *uniform super, // Exports (called from C++) ////////////////////////////////////////////////////////////////////////////// -export void CylinderLight_set(void *uniform super, - const uniform vec3f &radiance, - const uniform vec3f &position0, - const uniform vec3f &position1, - const uniform float radius) +export void *uniform CylinderLight_sample_addr() { - CylinderLight *uniform self = (CylinderLight * uniform) super; - uniform float zMax = length(position1 - position0); - if (zMax <= 0.f | radius <= 0.f) { - self->radiance = make_vec3f(0.f); - return; - } - - self->radiance = radiance; - self->radius = radius; - self->pre.position0 = position0; - self->pre.position1 = position1; - - // Enable dynamic runtime instancing or apply static transformation - const Instance *uniform instance = self->super.instance; - if (instance) { - if (instance->motionBlur) { - self->super.sample = CylinderLight_sample_instanced; - self->super.eval = CylinderLight_eval_instanced; - } else - Transform(self, instance->xfm, self->pre); - } + return CylinderLight_sample; } -export void *uniform CylinderLight_create() +export void *uniform CylinderLight_sample_instanced_addr() { - CylinderLight *uniform self = uniform new CylinderLight; - - Light_Constructor(&self->super); - self->super.sample = CylinderLight_sample; - self->super.eval = CylinderLight_eval; + return CylinderLight_sample_instanced; +} - CylinderLight_set( - self, make_vec3f(0.f), make_vec3f(0.f), make_vec3f(0.f, 0.f, 1.f), 1.f); +export void *uniform CylinderLight_eval_addr() +{ + return CylinderLight_eval; +} - return self; +export void *uniform CylinderLight_eval_instanced_addr() +{ + return CylinderLight_eval_instanced; } diff --git a/modules/cpu/lights/CylinderLightShared.h b/modules/cpu/lights/CylinderLightShared.h new file mode 100644 index 0000000000..8885a20b09 --- /dev/null +++ b/modules/cpu/lights/CylinderLightShared.h @@ -0,0 +1,36 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "LightShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +// state that changes under transformations +struct CylinderLightDynamic +{ + vec3f position0; + vec3f position1; + +#ifdef __cplusplus + CylinderLightDynamic() : position0(0.f), position1(0.f, 0.f, 1.f) {} +#endif +}; + +struct CylinderLight +{ + Light super; + vec3f radiance; + float radius; + CylinderLightDynamic pre; // un- or pre-transformed state + +#ifdef __cplusplus + CylinderLight() : radiance(1.f), radius(1.f) {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/lights/DirectionalLight.cpp b/modules/cpu/lights/DirectionalLight.cpp index d3cb0c08e5..5a1a4be315 100644 --- a/modules/cpu/lights/DirectionalLight.cpp +++ b/modules/cpu/lights/DirectionalLight.cpp @@ -1,19 +1,54 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "DirectionalLight.h" +#include "math/sampling.h" +// embree +#include "embree3/rtcore.h" +// ispc exports #include "lights/DirectionalLight_ispc.h" -#include "lights/Light_ispc.h" +// ispc shared +#include "DirectionalLightShared.h" +#include "common/InstanceShared.h" + +namespace ispc { + +void DirectionalLight::set(bool isVisible, + const Instance *instance, + const vec3f &direction, + const vec3f &irradiance, + float cosAngle) +{ + super.isVisible = isVisible; + super.instance = instance; + super.sample = ispc::DirectionalLight_sample_addr(); + super.eval = ispc::DirectionalLight_eval_addr(); + + frame = rkcommon::math::frame(direction); + this->irradiance = irradiance; + this->cosAngle = cosAngle; + pdf = cosAngle < COS_ANGLE_MAX ? ospray::uniformSampleConePDF(cosAngle) : inf; + + // Enable dynamic runtime instancing or apply static transformation + if (instance) { + if (instance->motionBlur) { + super.sample = ispc::DirectionalLight_sample_instanced_addr(); + super.eval = ispc::DirectionalLight_eval_instanced_addr(); + } else { + frame = instance->xfm.l * frame; + } + } +} +} // namespace ispc namespace ospray { -void *DirectionalLight::createIE(const void *instance) const +ispc::Light *DirectionalLight::createSh( + uint32_t, const ispc::Instance *instance) const { - void *ie = ispc::DirectionalLight_create(); - ispc::Light_set(ie, visible, (const ispc::Instance *)instance); - ispc::DirectionalLight_set( - ie, (ispc::vec3f &)irradiance, (ispc::vec3f &)direction, cosAngle); - return ie; + ispc::DirectionalLight *sh = StructSharedCreate(); + sh->set(visible, instance, direction, irradiance, cosAngle); + return &sh->super; } std::string DirectionalLight::toString() const diff --git a/modules/cpu/lights/DirectionalLight.h b/modules/cpu/lights/DirectionalLight.h index 7826803cc4..3975f13ad6 100644 --- a/modules/cpu/lights/DirectionalLight.h +++ b/modules/cpu/lights/DirectionalLight.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -13,7 +13,8 @@ struct OSPRAY_SDK_INTERFACE DirectionalLight : public Light { DirectionalLight() = default; virtual ~DirectionalLight() override = default; - virtual void *createIE(const void *instance) const override; + virtual ispc::Light *createSh( + uint32_t, const ispc::Instance *instance = nullptr) const override; virtual std::string toString() const override; virtual void commit() override; diff --git a/modules/cpu/lights/DirectionalLight.ispc b/modules/cpu/lights/DirectionalLight.ispc index 89501dd927..bbd98f671d 100644 --- a/modules/cpu/lights/DirectionalLight.ispc +++ b/modules/cpu/lights/DirectionalLight.ispc @@ -1,26 +1,11 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "Light.ih" #include "common/Instance.ih" #include "math/LinearSpace.ih" #include "math/sampling.ih" - -struct DirectionalLight -{ - Light super; //!< inherited light fields - - linear3f frame; //!< coordinate frame, with vz == direction *towards* the - //!< light source - vec3f irradiance; //!< RGB irradiance contribution of the light - float cosAngle; //!< Angular limit of the cone light in an easier to use form: - //!< cosine of the half angle in radians - float pdf; //!< Probability to sample a direction to the light -}; - -// for very small cones treat as singular light, because float precision is not -// good enough -#define COS_ANGLE_MAX 0.99999988f +// c++ shared +#include "DirectionalLightShared.h" // Implementation ////////////////////////////////////////////////////////////////////////////// @@ -125,39 +110,22 @@ Light_EvalRes DirectionalLight_eval_instanced(const Light *uniform super, // Exports (called from C++) ////////////////////////////////////////////////////////////////////////////// -//! Set the parameters of an ispc-side DirectionalLight object -export void DirectionalLight_set(void *uniform super, - const uniform vec3f &irradiance, - const uniform vec3f &direction, - uniform float cosAngle) +export void *uniform DirectionalLight_sample_addr() { - DirectionalLight *uniform self = (DirectionalLight * uniform) super; - self->frame = frame(direction); - self->irradiance = irradiance; - self->cosAngle = cosAngle; - self->pdf = cosAngle < COS_ANGLE_MAX ? uniformSampleConePDF(cosAngle) : inf; + return DirectionalLight_sample; +} - // Enable dynamic runtime instancing or apply static transformation - const Instance *uniform instance = self->super.instance; - if (instance) { - if (instance->motionBlur) { - self->super.sample = DirectionalLight_sample_instanced; - self->super.eval = DirectionalLight_eval_instanced; - } else { - self->frame = instance->xfm.l * self->frame; - } - } +export void *uniform DirectionalLight_sample_instanced_addr() +{ + return DirectionalLight_sample_instanced; } -//! Create an ispc-side DirectionalLight object -export void *uniform DirectionalLight_create() +export void *uniform DirectionalLight_eval_addr() { - DirectionalLight *uniform self = uniform new uniform DirectionalLight; - Light_Constructor(&self->super); - self->super.sample = DirectionalLight_sample; - self->super.eval = DirectionalLight_eval; - - DirectionalLight_set( - self, make_vec3f(0.f, 0.f, 0.f), make_vec3f(0.f, 0.f, 1.f), 1.f); - return self; + return DirectionalLight_eval; } + +export void *uniform DirectionalLight_eval_instanced_addr() +{ + return DirectionalLight_eval_instanced; +} \ No newline at end of file diff --git a/modules/cpu/lights/DirectionalLightShared.h b/modules/cpu/lights/DirectionalLightShared.h new file mode 100644 index 0000000000..102417e324 --- /dev/null +++ b/modules/cpu/lights/DirectionalLightShared.h @@ -0,0 +1,38 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "LightShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +// for very small cones treat as singular light, because float precision is not +// good enough +#define COS_ANGLE_MAX 0.99999988f + +struct DirectionalLight +{ + Light super; // inherited light fields + + linear3f frame; // coordinate frame, with vz == direction *towards* the + // light source + vec3f irradiance; // RGB irradiance contribution of the light + float cosAngle; // Angular limit of the cone light in an easier to use form: + // cosine of the half angle in radians + float pdf; // Probability to sample a direction to the light + +#ifdef __cplusplus + DirectionalLight() : frame(one), irradiance(0.f), cosAngle(1.f), pdf(inf) {} + void set(bool isVisible, + const Instance *instance, + const vec3f &direction, + const vec3f &irradiance, + float cosAngle); +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/lights/HDRILight.cpp b/modules/cpu/lights/HDRILight.cpp index 5ba1c3d8c8..201fbe0884 100644 --- a/modules/cpu/lights/HDRILight.cpp +++ b/modules/cpu/lights/HDRILight.cpp @@ -1,9 +1,53 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "HDRILight.h" +// embree +#include "embree3/rtcore.h" +// ispc exports #include "lights/HDRILight_ispc.h" #include "lights/Light_ispc.h" +// ispc shared +#include "HDRILightShared.h" +#include "common/InstanceShared.h" + +namespace ispc { +void HDRILight::set(bool isVisible, + const Instance *instance, + const vec3f &radianceScale, + const linear3f &light2world, + const Texture2D *map, + const Distribution2D *distribution) +{ + super.isVisible = isVisible; + super.instance = instance; + super.sample = ispc::HDRILight_sample_addr(); + super.eval = ispc::HDRILight_eval_addr(); + + this->radianceScale = radianceScale; + if (map) { + this->map = map; + this->distribution = distribution; + + this->rcpSize = 1.f / this->map->sizef; + this->light2world = light2world; + + // Enable dynamic runtime instancing or apply static transformation + if (instance) { + if (instance->motionBlur) { + super.sample = ispc::HDRILight_sample_instanced_addr(); + super.eval = ispc::HDRILight_eval_instanced_addr(); + } else { + this->light2world = instance->xfm.l * this->light2world; + } + } + world2light = rcp(this->light2world); + } else { + super.sample = ispc::HDRILight_sample_dummy_addr(); + super.eval = ispc::Light_eval_addr(); + } +} +} // namespace ispc namespace ospray { @@ -12,16 +56,16 @@ HDRILight::~HDRILight() ispc::HDRILight_destroyDistribution(distributionIE); } -void *HDRILight::createIE(const void *instance) const +ispc::Light *HDRILight::createSh(uint32_t, const ispc::Instance *instance) const { - void *ie = ispc::HDRILight_create(); - ispc::Light_set(ie, visible, (const ispc::Instance *)instance); - ispc::HDRILight_set(ie, - (ispc::vec3f &)coloredIntensity, - (const ispc::LinearSpace3f &)frame, - map ? map->getSh() : nullptr, - distributionIE); - return ie; + ispc::HDRILight *sh = StructSharedCreate(); + sh->set(visible, + instance, + coloredIntensity, + frame, + map->getSh(), + (const ispc::Distribution2D *)distributionIE); + return &sh->super; } std::string HDRILight::toString() const diff --git a/modules/cpu/lights/HDRILight.h b/modules/cpu/lights/HDRILight.h index 7919528e83..8babc4916e 100644 --- a/modules/cpu/lights/HDRILight.h +++ b/modules/cpu/lights/HDRILight.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -14,7 +14,8 @@ struct OSPRAY_SDK_INTERFACE HDRILight : public Light { HDRILight() = default; virtual ~HDRILight() override; - virtual void *createIE(const void *instance) const override; + virtual ispc::Light *createSh( + uint32_t, const ispc::Instance *instance = nullptr) const override; virtual std::string toString() const override; virtual void commit() override; diff --git a/modules/cpu/lights/HDRILight.ispc b/modules/cpu/lights/HDRILight.ispc index 747d85d8ee..4fb55f0e1c 100644 --- a/modules/cpu/lights/HDRILight.ispc +++ b/modules/cpu/lights/HDRILight.ispc @@ -1,26 +1,13 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "Light.ih" #include "common/Instance.ih" #include "math/Distribution2D.ih" #include "math/LinearSpace.ih" #include "math/sampling.ih" #include "texture/Texture2D.ih" - -struct HDRILight -{ - Light super; - - linear3f light2world; - linear3f world2light; - const Texture2D *uniform - map; // Environment map in latitude / longitude format - const Distribution2D *uniform - distribution; // The 2D distribution used to importance sample - vec2f rcpSize; // precomputed 1/map.size - vec3f radianceScale; // scaling factor of emitted RGB radiance -}; +// c++ shared +#include "HDRILightShared.h" // Implementation ////////////////////////////////////////////////////////////////////////////// @@ -195,52 +182,29 @@ task unmasked void HDRILight_calcRowImportance( // Exports (called from C++) ////////////////////////////////////////////////////////////////////////////// -//! Set the parameters of an ispc-side HDRILight object -export void HDRILight_set(void *uniform super, - const uniform vec3f &radianceScale, - const uniform linear3f &light2world, - const void *uniform map, - const void *uniform distribution) +export void *uniform HDRILight_sample_dummy_addr() { - HDRILight *uniform self = (HDRILight * uniform) super; - self->radianceScale = radianceScale; - - if (map) { - self->map = (uniform Texture2D * uniform) map; - self->distribution = (const uniform Distribution2D *uniform)distribution; - - self->rcpSize = 1.f / self->map->sizef; - self->light2world = light2world; - self->super.sample = HDRILight_sample; - self->super.eval = HDRILight_eval; - - // Enable dynamic runtime instancing or apply static transformation - const Instance *uniform instance = self->super.instance; - if (instance) { - if (instance->motionBlur) { - self->super.sample = HDRILight_sample_instanced; - self->super.eval = HDRILight_eval_instanced; - } else { - self->light2world = instance->xfm.l * self->light2world; - } - } - self->world2light = rcp(self->light2world); - } else { - self->super.sample = HDRILight_sample_dummy; - self->super.eval = Light_eval; - } + return HDRILight_sample_dummy; +} + +export void *uniform HDRILight_sample_addr() +{ + return HDRILight_sample; +} + +export void *uniform HDRILight_sample_instanced_addr() +{ + return HDRILight_sample_instanced; } -//! Create an ispc-side HDRILight object -export void *uniform HDRILight_create() +export void *uniform HDRILight_eval_addr() { - HDRILight *uniform self = uniform new HDRILight; + return HDRILight_eval; +} - Light_Constructor(&self->super); - self->super.sample = HDRILight_sample_dummy; - HDRILight_set( - self, make_vec3f(1.0f), make_LinearSpace3f_identity(), NULL, NULL); - return self; +export void *uniform HDRILight_eval_instanced_addr() +{ + return HDRILight_eval_instanced; } export void *uniform HDRILight_createDistribution(const void *uniform map) diff --git a/modules/cpu/lights/HDRILightShared.h b/modules/cpu/lights/HDRILightShared.h new file mode 100644 index 0000000000..0522b24c5b --- /dev/null +++ b/modules/cpu/lights/HDRILightShared.h @@ -0,0 +1,46 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "LightShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +struct Texture2D; +struct Distribution2D; + +struct HDRILight +{ + Light super; + + linear3f light2world; + linear3f world2light; + const Texture2D *map; // Environment map in latitude / longitude format + const Distribution2D + *distribution; // The 2D distribution used to importance sample + vec2f rcpSize; // precomputed 1/map.size + vec3f radianceScale; // scaling factor of emitted RGB radiance + +#ifdef __cplusplus + HDRILight() + : light2world(one), + world2light(one), + map(nullptr), + distribution(nullptr), + rcpSize(0.f), + radianceScale(1.f) + {} + void set(bool isVisible, + const Instance *instance, + const vec3f &radianceScale, + const linear3f &light2world, + const Texture2D *map, + const Distribution2D *distribution); +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/lights/IntensityDistribution.cpp b/modules/cpu/lights/IntensityDistribution.cpp index 2256bbfea0..450d5ce6ee 100644 --- a/modules/cpu/lights/IntensityDistribution.cpp +++ b/modules/cpu/lights/IntensityDistribution.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 #include "IntensityDistribution.h" +#include "IntensityDistributionShared.h" namespace ospray { @@ -30,4 +31,12 @@ void IntensityDistribution::readParams(ManagedObject &obj) } } +void IntensityDistribution::setSh(ispc::IntensityDistribution &sh) const +{ + sh.lid = lid ? lid->data() : nullptr; + sh.size = size; + sh.scale.x = nextafter(float(size.x - 1) * float(one_over_pi), -1.0f); + sh.scale.y = nextafter(float(size.y) * float(one_over_two_pi), -1.0f); +} + } // namespace ospray diff --git a/modules/cpu/lights/IntensityDistribution.h b/modules/cpu/lights/IntensityDistribution.h index abbc4e7a7a..2290b2cce8 100644 --- a/modules/cpu/lights/IntensityDistribution.h +++ b/modules/cpu/lights/IntensityDistribution.h @@ -5,6 +5,9 @@ #include "common/Data.h" +namespace ispc { +struct IntensityDistribution; +} namespace ospray { struct OSPRAY_SDK_INTERFACE IntensityDistribution @@ -15,10 +18,7 @@ struct OSPRAY_SDK_INTERFACE IntensityDistribution { return lid; } - float *data() const - { - return lid ? lid->data() : nullptr; - } + void setSh(ispc::IntensityDistribution &sh) const; vec2i size{0}; vec3f c0{1.f, 0.f, 0.f}; diff --git a/modules/cpu/lights/IntensityDistribution.ih b/modules/cpu/lights/IntensityDistribution.ih index 8f16ec13e1..842ffb52b0 100644 --- a/modules/cpu/lights/IntensityDistribution.ih +++ b/modules/cpu/lights/IntensityDistribution.ih @@ -4,13 +4,7 @@ #pragma once #include "rkcommon/math/vec.ih" - -struct IntensityDistribution -{ - float *lid; // luminance intensity distribution - vec2i size; - vec2f scale; -}; +#include "IntensityDistributionShared.h" inline float IntensityDistribution_eval( const IntensityDistribution *uniform self, @@ -40,13 +34,3 @@ inline float IntensityDistribution_eval( } return intensity; } - -inline float IntensityDistribution_set(IntensityDistribution *uniform self, - float *uniform lid, - const uniform vec2i &size) -{ - self->lid = lid; - self->size = size; - self->scale = make_vec2f(nextafter((size.x - 1) * one_over_pi, -1.0f), - nextafter(self->size.y * one_over_two_pi, -1.0f)); -} diff --git a/modules/cpu/lights/IntensityDistributionShared.h b/modules/cpu/lights/IntensityDistributionShared.h new file mode 100644 index 0000000000..a5635dbed9 --- /dev/null +++ b/modules/cpu/lights/IntensityDistributionShared.h @@ -0,0 +1,22 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +struct IntensityDistribution +{ + float *lid; // luminance intensity distribution + vec2i size; + vec2f scale; + +#ifdef __cplusplus + IntensityDistribution() : lid{nullptr}, size(0), scale(1.f) {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/lights/Light.cpp b/modules/cpu/lights/Light.cpp index f0101ca2f0..9060f9630a 100644 --- a/modules/cpu/lights/Light.cpp +++ b/modules/cpu/lights/Light.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray @@ -17,11 +17,6 @@ Light::Light() managedObjectType = OSP_LIGHT; } -void *Light::createSecondIE(const void *) const -{ - return nullptr; -} - void Light::commit() { visible = getParam("visible", true); diff --git a/modules/cpu/lights/Light.h b/modules/cpu/lights/Light.h index 118ad7c926..2e6864704a 100644 --- a/modules/cpu/lights/Light.h +++ b/modules/cpu/lights/Light.h @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -6,6 +6,11 @@ #include "common/Managed.h" #include "common/Util.h" +namespace ispc { +struct Light; +struct Instance; +} // namespace ispc + namespace ospray { //! Base class for Light objects @@ -18,8 +23,9 @@ struct OSPRAY_SDK_INTERFACE Light : public ManagedObject template static void registerType(const char *type); - virtual void *createIE(const void *instance = nullptr) const = 0; - virtual void *createSecondIE(const void *instance = nullptr) const; + virtual uint32_t getShCount() const; + virtual ispc::Light *createSh( + uint32_t index, const ispc::Instance *instance = nullptr) const = 0; virtual void commit() override; virtual std::string toString() const override; @@ -40,6 +46,11 @@ OSPTYPEFOR_SPECIALIZATION(Light *, OSP_LIGHT); // Inlined definitions ///////////////////////////////////////////////////////// +inline uint32_t Light::getShCount() const +{ + return 1; +} + template inline void Light::registerType(const char *type) { diff --git a/modules/cpu/lights/Light.ispc b/modules/cpu/lights/Light.ispc index 0ac7d60789..bb7e2d943a 100644 --- a/modules/cpu/lights/Light.ispc +++ b/modules/cpu/lights/Light.ispc @@ -1,7 +1,9 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "Light.ih" +#include "common/DifferentialGeometry.ih" +// c++ shared +#include "LightShared.h" Light_EvalRes Light_eval(const Light *uniform, const DifferentialGeometry &, @@ -18,12 +20,7 @@ Light_EvalRes Light_eval(const Light *uniform, // Exports (called from C++) ////////////////////////////////////////////////////////////////////////////// -//! Set the parameters of an ispc-side Light object -export void Light_set(void *uniform _self, - const uniform bool isVisible, - const Instance *uniform instance) +export void *uniform Light_eval_addr() { - Light *uniform self = (Light * uniform) _self; - self->isVisible = isVisible; - self->instance = instance; + return Light_eval; } diff --git a/modules/cpu/lights/Light.ih b/modules/cpu/lights/LightShared.h similarity index 55% rename from modules/cpu/lights/Light.ih rename to modules/cpu/lights/LightShared.h index ebd1ae9765..6e6ecb4312 100644 --- a/modules/cpu/lights/Light.ih +++ b/modules/cpu/lights/LightShared.h @@ -1,25 +1,28 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once -#include "common/DifferentialGeometry.ih" -#include "math/AffineSpace.ih" - +#ifdef __cplusplus +#include "common/StructShared.h" +namespace ispc { +typedef void *Light_SampleFunc; +typedef void *Light_EvalFunc; +#else struct Light; -struct Instance; +struct DifferentialGeometry; struct Light_SampleRes { - vec3f weight; //!< radiance that arrives at the given point divided by pdf - vec3f dir; //!< direction towards the light source, normalized - float dist; //!< largest valid t_far value for a shadow ray, including epsilon - //!< to avoid self-intersection - float pdf; //!< probability density that this sample was taken + vec3f weight; // radiance that arrives at the given point divided by pdf + vec3f dir; // direction towards the light source, normalized + float dist; // largest valid t_far value for a shadow ray, including epsilon + // to avoid self-intersection + float pdf; // probability density that this sample was taken }; -//! compute the weighted radiance at a point caused by a sample on the light -//! source +// compute the weighted radiance at a point caused by a sample on the light +// source // by convention, giving (0, 0) as "random" numbers should sample the "center" // of the light source (used by the raytracing renderers such as the SciVis // renderer) @@ -30,9 +33,9 @@ typedef Light_SampleRes (*Light_SampleFunc)(const Light *uniform self, struct Light_EvalRes { - vec3f radiance; //!< radiance that arrives at the given point (not weighted by - //!< pdf) - float pdf; //!< probability density that the direction would have been sampled + vec3f radiance; // radiance that arrives at the given point (not weighted by + // pdf) + float pdf; // probability density that the direction would have been sampled }; //! compute the radiance and pdf caused by the light source (pointed to by the @@ -43,6 +46,9 @@ typedef Light_EvalRes (*Light_EvalFunc)(const Light *uniform self, const float minDist, // minimum distance to look for light contribution const float maxDist, // maximum distance to look for light contribution const float time = 0.5f); // evaluate at time (motion blur) +#endif // __cplusplus + +struct Instance; struct Light { @@ -51,21 +57,12 @@ struct Light bool isVisible; // either directly in camera, or via a straight path (i.e. // through ThinGlass) const Instance *instance; -}; -typedef Light *uniform LightPtr; -typedef LightPtr *uniform LightArray; -Light_EvalRes Light_eval(const Light *uniform, - const DifferentialGeometry &, - const vec3f &, - const float, - const float, - const float); - -inline void Light_Constructor(Light *uniform self) -{ - assert(self); - self->eval = Light_eval; - self->isVisible = true; - self->instance = NULL; -} +#ifdef __cplusplus + Light() : sample(nullptr), eval(nullptr), isVisible(true), instance(nullptr) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/lights/PointLight.cpp b/modules/cpu/lights/PointLight.cpp index 266bb691a7..f26b0999ef 100644 --- a/modules/cpu/lights/PointLight.cpp +++ b/modules/cpu/lights/PointLight.cpp @@ -1,26 +1,47 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "PointLight.h" -#include "lights/Light_ispc.h" +// embree +#include "embree3/rtcore.h" + #include "lights/PointLight_ispc.h" +#include "PointLightShared.h" +#include "common/InstanceShared.h" + namespace ospray { -void *PointLight::createIE(const void *instance) const +ispc::Light *PointLight::createSh( + uint32_t, const ispc::Instance *instance) const { - void *ie = ispc::PointLight_create(); - ispc::Light_set(ie, visible, (const ispc::Instance *)instance); - ispc::PointLight_set(ie, - (ispc::vec3f &)position, - (ispc::vec3f &)radiance, - (ispc::vec3f &)radIntensity, - radius, - intensityDistribution.data(), - (const ispc::vec2i &)intensityDistribution.size, - (ispc::vec3f &)direction, - (const ispc::vec3f &)intensityDistribution.c0); - return ie; + ispc::PointLight *sh = StructSharedCreate(); + sh->super.sample = ispc::PointLight_sample_addr(); + sh->super.eval = ispc::PointLight_eval_addr(); + sh->super.isVisible = visible; + sh->super.instance = instance; + + sh->radiance = radiance; + sh->intensity = radIntensity; + sh->radius = radius; + sh->pre.position = position; + sh->pre.direction = normalize(direction); + intensityDistribution.setSh(sh->intensityDistribution); + + // Enable dynamic runtime instancing or apply static transformation + if (instance) { + sh->pre.c0 = intensityDistribution.c0; + if (instance->motionBlur) { + sh->super.sample = ispc::PointLight_sample_instanced_addr(); + sh->super.eval = ispc::PointLight_eval_instanced_addr(); + } else + ispc::PointLight_Transform(sh, instance->xfm, &sh->pre); + } else { + sh->pre.c90 = normalize(cross(intensityDistribution.c0, sh->pre.direction)); + sh->pre.c0 = cross(sh->pre.direction, sh->pre.c90); + } + + return &sh->super; } std::string PointLight::toString() const diff --git a/modules/cpu/lights/PointLight.h b/modules/cpu/lights/PointLight.h index ec2a1ece47..ec8385c7ca 100644 --- a/modules/cpu/lights/PointLight.h +++ b/modules/cpu/lights/PointLight.h @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -14,7 +14,8 @@ struct OSPRAY_SDK_INTERFACE PointLight : public Light { PointLight() = default; virtual ~PointLight() override = default; - virtual void *createIE(const void *instance) const override; + virtual ispc::Light *createSh( + uint32_t, const ispc::Instance *instance = nullptr) const override; virtual std::string toString() const override; virtual void commit() override; diff --git a/modules/cpu/lights/PointLight.ispc b/modules/cpu/lights/PointLight.ispc index 2772e349b1..5f57f1bb3a 100644 --- a/modules/cpu/lights/PointLight.ispc +++ b/modules/cpu/lights/PointLight.ispc @@ -1,37 +1,19 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "IntensityDistribution.ih" -#include "Light.ih" #include "common/Instance.ih" #include "common/Intersect.ih" #include "common/Ray.ih" #include "math/LinearSpace.ih" #include "math/sampling.ih" - -// state that changes under transformations -struct PointLightDynamic -{ - vec3f position; - vec3f direction; - vec3f c0; // orientation for intensityDistribution: direction of the C0- - vec3f c90; // and the C90-(half)plane -}; - -struct PointLight -{ - Light super; - vec3f intensity; // RGB color and intensity of light - vec3f radiance; // emitted RGB radiance - float radius; // defines the size of the SphereLight - IntensityDistribution intensityDistribution; - PointLightDynamic pre; // un- or pre-transformed state -}; +// c++ shared +#include "PointLightShared.h" // Implementation ////////////////////////////////////////////////////////////////////////////// inline void Transform(const PointLight *uniform self, - const uniform affine3f xfm, + const uniform affine3f &xfm, uniform PointLightDynamic &dyn) { dyn.position = xfmPoint(xfm, self->pre.position); @@ -43,6 +25,14 @@ inline void Transform(const PointLight *uniform self, } } +export void PointLight_Transform( + const void *uniform self, const void *uniform xfm, void *uniform dyn) +{ + Transform((PointLight * uniform) self, + *((affine3f * uniform) xfm), + *((PointLightDynamic * uniform) dyn)); +} + inline Light_SampleRes Sample(const PointLight *uniform self, const uniform PointLightDynamic &dyn, const DifferentialGeometry &dg, @@ -199,59 +189,22 @@ Light_EvalRes PointLight_eval_instanced(const Light *uniform super, // Exports (called from C++) ////////////////////////////////////////////////////////////////////////////// -//! Set the parameters of an ispc-side PointLight object -export void PointLight_set(void *uniform super, - const uniform vec3f &position, - const uniform vec3f &radiance, - const uniform vec3f &intensity, - uniform float radius, - float *uniform lid, - const uniform vec2i &size, - const uniform vec3f &direction, - const uniform vec3f &c0) +export void *uniform PointLight_sample_addr() { - PointLight *uniform self = (PointLight * uniform) super; - - self->radiance = radiance; - self->intensity = intensity; - self->radius = radius; - self->pre.position = position; - self->pre.direction = normalize(direction); - - IntensityDistribution_set(&self->intensityDistribution, lid, size); - - // Enable dynamic runtime instancing or apply static transformation - const Instance *uniform instance = self->super.instance; - if (instance) { - self->pre.c0 = c0; - if (instance->motionBlur) { - self->super.sample = PointLight_sample_instanced; - self->super.eval = PointLight_eval_instanced; - } else - Transform(self, instance->xfm, self->pre); - } else { - self->pre.c90 = normalize(cross(c0, self->pre.direction)); - self->pre.c0 = cross(self->pre.direction, self->pre.c90); - } + return PointLight_sample; } -//! Create an ispc-side PointLight object -export void *uniform PointLight_create() +export void *uniform PointLight_sample_instanced_addr() { - PointLight *uniform self = uniform new PointLight; - Light_Constructor(&self->super); - self->super.sample = PointLight_sample; - self->super.eval = PointLight_eval; + return PointLight_sample_instanced; +} - PointLight_set(self, - make_vec3f(0.f), - make_vec3f(1.f), - make_vec3f(1.f), - 0.f, - NULL, - make_vec2i(0), - make_vec3f(0.f, 1.f, 0.f), - make_vec3f(0.f, 0.f, 1.f)); +export void *uniform PointLight_eval_addr() +{ + return PointLight_eval; +} - return self; +export void *uniform PointLight_eval_instanced_addr() +{ + return PointLight_eval_instanced; } diff --git a/modules/cpu/lights/PointLightShared.h b/modules/cpu/lights/PointLightShared.h new file mode 100644 index 0000000000..017a1ae94f --- /dev/null +++ b/modules/cpu/lights/PointLightShared.h @@ -0,0 +1,45 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "LightShared.h" +#include "IntensityDistributionShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +// state that changes under transformations +struct PointLightDynamic +{ + vec3f position; + vec3f direction; + vec3f c0; // orientation for intensityDistribution: direction of the C0- + vec3f c90; // and the C90-(half)plane +#ifdef __cplusplus + PointLightDynamic() + : position(0.f), + direction(0.f, 0.f, 1.f), + c0(1.f, 0.f, 0.f), + c90(0.f, 1.f, 0.f) + {} +#endif +}; + +struct PointLight +{ + Light super; + vec3f intensity; // RGB color and intensity of light + vec3f radiance; // emitted RGB radiance + float radius; // defines the size of the SphereLight + IntensityDistribution intensityDistribution; + PointLightDynamic pre; // un- or pre-transformed state + +#ifdef __cplusplus + PointLight() : intensity(1.f), radiance(1.f), radius(0.f) {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/lights/QuadLight.cpp b/modules/cpu/lights/QuadLight.cpp index 1971f1cb7b..c6112ef21b 100644 --- a/modules/cpu/lights/QuadLight.cpp +++ b/modules/cpu/lights/QuadLight.cpp @@ -1,25 +1,50 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "QuadLight.h" -#include "lights/Light_ispc.h" +// embree +#include "embree3/rtcore.h" + #include "lights/QuadLight_ispc.h" +#include "QuadLightShared.h" +#include "common/InstanceShared.h" + namespace ospray { -void *QuadLight::createIE(const void *instance) const +ispc::Light *QuadLight::createSh(uint32_t, const ispc::Instance *instance) const { - void *ie = ispc::QuadLight_create(); - ispc::Light_set(ie, visible, (const ispc::Instance *)instance); - ispc::QuadLight_set(ie, - (ispc::vec3f &)radiance, - (ispc::vec3f &)position, - (ispc::vec3f &)edge1, - (ispc::vec3f &)edge2, - intensityDistribution.data(), - (const ispc::vec2i &)intensityDistribution.size, - (const ispc::vec3f &)intensityDistribution.c0); - return ie; + ispc::QuadLight *sh = StructSharedCreate(); + sh->super.sample = ispc::QuadLight_sample_addr(); + sh->super.eval = ispc::QuadLight_eval_addr(); + sh->super.isVisible = visible; + sh->super.instance = instance; + + sh->radiance = radiance; + + sh->pre.position = position; + sh->pre.edge1 = edge1; + sh->pre.edge2 = edge2; + + intensityDistribution.setSh(sh->intensityDistribution); + + // Enable dynamic runtime instancing or apply static transformation + if (instance) { + sh->pre.c0 = intensityDistribution.c0; + if (instance->motionBlur) { + sh->super.sample = ispc::QuadLight_sample_instanced_addr(); + sh->super.eval = ispc::QuadLight_eval_instanced_addr(); + } else + ispc::QuadLight_Transform(sh, instance->xfm, &sh->pre); + } else { + const vec3f ndirection = cross(edge2, edge1); + sh->pre.ppdf = rcp(length(ndirection)); // 1/area + sh->pre.nnormal = ndirection * sh->pre.ppdf; // normalize + sh->pre.c90 = normalize(cross(sh->pre.nnormal, intensityDistribution.c0)); + sh->pre.c0 = cross(sh->pre.c90, sh->pre.nnormal); + } + + return &sh->super; } std::string QuadLight::toString() const diff --git a/modules/cpu/lights/QuadLight.h b/modules/cpu/lights/QuadLight.h index 64304459fc..624454b0c5 100644 --- a/modules/cpu/lights/QuadLight.h +++ b/modules/cpu/lights/QuadLight.h @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -14,7 +14,8 @@ struct OSPRAY_SDK_INTERFACE QuadLight : public Light { QuadLight() = default; virtual ~QuadLight() override = default; - virtual void *createIE(const void *instance) const override; + virtual ispc::Light *createSh( + uint32_t, const ispc::Instance *instance = nullptr) const override; virtual std::string toString() const override; virtual void commit() override; diff --git a/modules/cpu/lights/QuadLight.ispc b/modules/cpu/lights/QuadLight.ispc index a66458e8fa..ebebecf114 100644 --- a/modules/cpu/lights/QuadLight.ispc +++ b/modules/cpu/lights/QuadLight.ispc @@ -1,36 +1,17 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "IntensityDistribution.ih" -#include "Light.ih" #include "SphericalQuadSampling.ih" +#include "common/DifferentialGeometry.ih" #include "common/Instance.ih" - -// state that changes under transformations -struct QuadLightDynamic -{ - vec3f position; - vec3f edge1; - vec3f edge2; - vec3f nnormal; // negated normal, the direction that the QuadLight is not - // emitting; normalized - float ppdf; // probability to sample point on light = 1/area - vec3f c0; // orientation for intensityDistribution: direction of the C0- - vec3f c90; // and the C90-(half)plane -}; - -struct QuadLight -{ - Light super; - vec3f radiance; // emitted RGB radiance - IntensityDistribution intensityDistribution; - QuadLightDynamic pre; // un- or pre-transformed state -}; +// c++ shared +#include "QuadLightShared.h" // Implementation ////////////////////////////////////////////////////////////////////////////// inline void Transform(const QuadLight *uniform self, - const uniform affine3f xfm, + const uniform affine3f &xfm, uniform QuadLightDynamic &dyn) { // transform light into the world space @@ -49,6 +30,14 @@ inline void Transform(const QuadLight *uniform self, } } +export void QuadLight_Transform( + const void *uniform self, const void *uniform xfm, void *uniform dyn) +{ + Transform((QuadLight * uniform) self, + *((affine3f * uniform) xfm), + *((QuadLightDynamic * uniform) dyn)); +} + inline Light_SampleRes SampleArea(const QuadLight *uniform self, const uniform QuadLightDynamic &dyn, const DifferentialGeometry &dg, @@ -259,59 +248,22 @@ Light_EvalRes QuadLight_eval_instanced(const Light *uniform super, // Exports (called from C++) ////////////////////////////////////////////////////////////////////////////// -export void QuadLight_set(void *uniform super, - const uniform vec3f &radiance, - const uniform vec3f &position, - const uniform vec3f &edge1, - const uniform vec3f &edge2, - float *uniform lid, - const uniform vec2i &size, - const uniform vec3f &c0) +export void *uniform QuadLight_sample_addr() { - QuadLight *uniform self = (QuadLight * uniform) super; - self->radiance = radiance; - - self->pre.position = position; - self->pre.edge1 = edge1; - self->pre.edge2 = edge2; + return QuadLight_sample; +} - IntensityDistribution_set(&self->intensityDistribution, lid, size); +export void *uniform QuadLight_sample_instanced_addr() +{ + return QuadLight_sample_instanced; +} - // Enable dynamic runtime instancing or apply static transformation - const Instance *uniform instance = self->super.instance; - if (instance) { - self->pre.c0 = c0; - if (instance->motionBlur) { - self->super.sample = QuadLight_sample_instanced; - self->super.eval = QuadLight_eval_instanced; - } else - Transform(self, instance->xfm, self->pre); - } else { - const uniform vec3f ndirection = cross(edge2, edge1); - self->pre.ppdf = rcp(length(ndirection)); // 1/area - self->pre.nnormal = ndirection * self->pre.ppdf; // normalize - self->pre.c90 = normalize(cross(self->pre.nnormal, c0)); - self->pre.c0 = cross(self->pre.c90, self->pre.nnormal); - } +export void *uniform QuadLight_eval_addr() +{ + return QuadLight_eval; } -//! Create an ispc-side QuadLight object -export void *uniform QuadLight_create() +export void *uniform QuadLight_eval_instanced_addr() { - QuadLight *uniform self = uniform new QuadLight; - - Light_Constructor(&self->super); - self->super.sample = QuadLight_sample; - self->super.eval = QuadLight_eval; - - QuadLight_set(self, - make_vec3f(0.f), - make_vec3f(0.f), - make_vec3f(1.f, 0.f, 0.f), - make_vec3f(0.f, 1.f, 0.f), - NULL, - make_vec2i(0), - make_vec3f(0.f, 1.f, 0.f)); - - return self; + return QuadLight_eval_instanced; } diff --git a/modules/cpu/lights/QuadLightShared.h b/modules/cpu/lights/QuadLightShared.h new file mode 100644 index 0000000000..70dd011a10 --- /dev/null +++ b/modules/cpu/lights/QuadLightShared.h @@ -0,0 +1,49 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "LightShared.h" +#include "IntensityDistributionShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +// state that changes under transformations +struct QuadLightDynamic +{ + vec3f position; + vec3f edge1; + vec3f edge2; + vec3f nnormal; // negated normal, the direction that the QuadLight is not + // emitting; normalized + float ppdf; // probability to sample point on light = 1/area + vec3f c0; // orientation for intensityDistribution: direction of the C0- + vec3f c90; // and the C90-(half)plane + +#ifdef __cplusplus + QuadLightDynamic() + : position(0.f), + edge1(1.f, 0.f, 0.f), + edge2(0.f, 1.f, 0.f), + nnormal(0.f, 0.f, 1.f), + ppdf(inf) + {} +#endif +}; + +struct QuadLight +{ + Light super; + vec3f radiance; // emitted RGB radiance + IntensityDistribution intensityDistribution; + QuadLightDynamic pre; // un- or pre-transformed state + +#ifdef __cplusplus + QuadLight() : radiance(0.f) {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/lights/SphericalQuadSampling.ih b/modules/cpu/lights/SphericalQuadSampling.ih index 601f529d78..09eb1235d6 100644 --- a/modules/cpu/lights/SphericalQuadSampling.ih +++ b/modules/cpu/lights/SphericalQuadSampling.ih @@ -1,9 +1,9 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once -#include "Light.ih" +#include "rkcommon/math/vec.ih" struct SphericalQuad { diff --git a/modules/cpu/lights/SpotLight.cpp b/modules/cpu/lights/SpotLight.cpp index 36bbd48505..8bd818e0da 100644 --- a/modules/cpu/lights/SpotLight.cpp +++ b/modules/cpu/lights/SpotLight.cpp @@ -1,29 +1,53 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "SpotLight.h" -#include "lights/Light_ispc.h" +#include "math/sampling.h" +// embree +#include "embree3/rtcore.h" + #include "lights/SpotLight_ispc.h" +#include "SpotLightShared.h" +#include "common/InstanceShared.h" + namespace ospray { -void *SpotLight::createIE(const void *instance) const +ispc::Light *SpotLight::createSh(uint32_t, const ispc::Instance *instance) const { - void *ie = ispc::SpotLight_create(); - ispc::Light_set(ie, visible, (const ispc::Instance *)instance); - ispc::SpotLight_set(ie, - (const ispc::vec3f &)position, - (const ispc::vec3f &)direction, - (const ispc::vec3f &)intensityDistribution.c0, - (const ispc::vec3f &)radiance, - (const ispc::vec3f &)radIntensity, - cosAngleMax, - cosAngleScale, - radius, - innerRadius, - (const ispc::vec2i &)intensityDistribution.size, - intensityDistribution.data()); - return ie; + ispc::SpotLight *sh = StructSharedCreate(); + sh->super.sample = ispc::SpotLight_sample_addr(); + sh->super.eval = ispc::SpotLight_eval_addr(); + sh->super.isVisible = visible; + sh->super.instance = instance; + + sh->pre.position = position; + sh->pre.direction = normalize(direction); + + intensityDistribution.setSh(sh->intensityDistribution); + + // Enable dynamic runtime instancing or apply static transformation + if (instance) { + sh->pre.c0 = intensityDistribution.c0; + if (instance->motionBlur) { + sh->super.sample = ispc::SpotLight_sample_instanced_addr(); + sh->super.eval = ispc::SpotLight_eval_instanced_addr(); + } else + ispc::SpotLight_Transform(&sh->pre, instance->xfm, &sh->pre); + } else { + sh->pre.c90 = normalize(cross(intensityDistribution.c0, sh->pre.direction)); + sh->pre.c0 = cross(sh->pre.direction, sh->pre.c90); + } + + sh->radiance = radiance; + sh->intensity = radIntensity; + sh->cosAngleMax = cosAngleMax; + sh->cosAngleScale = cosAngleScale; + sh->radius = radius; + sh->innerRadius = innerRadius; + sh->areaPdf = uniformSampleRingPDF(radius, innerRadius); + + return &sh->super; } std::string SpotLight::toString() const diff --git a/modules/cpu/lights/SpotLight.h b/modules/cpu/lights/SpotLight.h index 79537b2110..e60e02ea70 100644 --- a/modules/cpu/lights/SpotLight.h +++ b/modules/cpu/lights/SpotLight.h @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -14,7 +14,8 @@ struct OSPRAY_SDK_INTERFACE SpotLight : public Light { SpotLight() = default; virtual ~SpotLight() override = default; - virtual void *createIE(const void *instance) const override; + virtual ispc::Light *createSh( + uint32_t, const ispc::Instance *instance = nullptr) const override; virtual std::string toString() const override; virtual void commit() override; diff --git a/modules/cpu/lights/SpotLight.ispc b/modules/cpu/lights/SpotLight.ispc index 0ee2385ab5..fa49535117 100644 --- a/modules/cpu/lights/SpotLight.ispc +++ b/modules/cpu/lights/SpotLight.ispc @@ -1,42 +1,16 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "IntensityDistribution.ih" -#include "Light.ih" #include "common/Instance.ih" #include "math/sampling.ih" - -// state that changes under transformations -struct SpotLightDynamic -{ - vec3f position; - vec3f direction; - vec3f c0; - vec3f c90; -}; - -struct SpotLight -{ - Light super; - vec3f intensity; // RGB radiative intensity of the SpotLight - vec3f radiance; // emitted RGB radiance - float cosAngleMax; // Angular limit of the spot in an easier to use form: - // cosine of the half angle in radians - float cosAngleScale; // 1/(cos(border of the penumbra area) - cosAngleMax); - // positive - float radius; // defines the size of the DiskLight represented using - // the (extended) SpotLight - float innerRadius; // defines the size of the inner cut out of the DiskLight - // to represent a RingLight - float areaPdf; // pdf of disk/ring with radius/innerRadius - IntensityDistribution intensityDistribution; - SpotLightDynamic pre; // un- or pre-transformed state -}; +// c++ shared +#include "SpotLightShared.h" // Implementation ////////////////////////////////////////////////////////////////////////////// inline void Transform(const uniform SpotLightDynamic &pre, - const uniform affine3f xfm, + const uniform affine3f &xfm, uniform SpotLightDynamic &dyn) { dyn.position = xfmPoint(xfm, pre.position); @@ -45,6 +19,14 @@ inline void Transform(const uniform SpotLightDynamic &pre, dyn.c0 = cross(dyn.direction, dyn.c90); } +export void SpotLight_Transform( + const void *uniform self, const void *uniform xfm, void *uniform dyn) +{ + Transform(*((const SpotLightDynamic *uniform)self), + *((affine3f * uniform) xfm), + *((SpotLightDynamic * uniform) dyn)); +} + inline float AngularAttenuation(const SpotLight *uniform self, float cosAngle) { return clamp((cosAngle - self->cosAngleMax) * self->cosAngleScale); @@ -221,69 +203,22 @@ Light_EvalRes SpotLight_eval_instanced(const Light *uniform super, // Exports (called from C++) ////////////////////////////////////////////////////////////////////////////// -export void SpotLight_set(void *uniform super, - const uniform vec3f &position, - const uniform vec3f &direction, - const uniform vec3f &c0, - const uniform vec3f &radiance, - const uniform vec3f &intensity, - uniform float cosAngleMax, - uniform float cosAngleScale, - uniform float radius, - uniform float innerRadius, - const uniform vec2i &size, - float *uniform lid) +export void *uniform SpotLight_sample_addr() { - SpotLight *uniform self = (SpotLight * uniform) super; - - self->pre.position = position; - self->pre.direction = normalize(direction); - - IntensityDistribution_set(&self->intensityDistribution, lid, size); - - // Enable dynamic runtime instancing or apply static transformation - const Instance *uniform instance = self->super.instance; - if (instance) { - self->pre.c0 = c0; - if (instance->motionBlur) { - self->super.sample = SpotLight_sample_instanced; - self->super.eval = SpotLight_eval_instanced; - } else - Transform(self->pre, instance->xfm, self->pre); - } else { - self->pre.c90 = normalize(cross(c0, self->pre.direction)); - self->pre.c0 = cross(self->pre.direction, self->pre.c90); - } - - self->radiance = radiance; - self->intensity = intensity; - self->cosAngleMax = cosAngleMax; - self->cosAngleScale = cosAngleScale; - self->radius = radius; - self->innerRadius = innerRadius; - self->areaPdf = uniformSampleRingPDF(radius, innerRadius); + return SpotLight_sample; } -export void *uniform SpotLight_create() +export void *uniform SpotLight_sample_instanced_addr() { - SpotLight *uniform self = uniform new SpotLight; - - Light_Constructor(&self->super); - self->super.sample = SpotLight_sample; - self->super.eval = SpotLight_eval; + return SpotLight_sample_instanced; +} - SpotLight_set(self, - make_vec3f(0.f), - make_vec3f(0.f, 0.f, 1.f), - make_vec3f(0.f, 1.f, 0.f), - make_vec3f(1.f), - make_vec3f(1.f), - 0.f, - 100.f, - 0.f, - 0.f, - make_vec2i(0), - NULL); +export void *uniform SpotLight_eval_addr() +{ + return SpotLight_eval; +} - return self; +export void *uniform SpotLight_eval_instanced_addr() +{ + return SpotLight_eval_instanced; } diff --git a/modules/cpu/lights/SpotLightShared.h b/modules/cpu/lights/SpotLightShared.h new file mode 100644 index 0000000000..3ebbfb0523 --- /dev/null +++ b/modules/cpu/lights/SpotLightShared.h @@ -0,0 +1,62 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "LightShared.h" +#include "IntensityDistributionShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +// state that changes under transformations +struct SpotLightDynamic +{ + vec3f position; + vec3f direction; + vec3f c0; + vec3f c90; + +#ifdef __cplusplus + SpotLightDynamic() + : position(0.f), + direction(0.f, 0.f, 1.f), + c0(1.f, 0.f, 0.f), + c90(0.f, 1.f, 0.f) + {} +#endif // __cplusplus +}; + +struct SpotLight +{ + Light super; + vec3f intensity; // RGB radiative intensity of the SpotLight + vec3f radiance; // emitted RGB radiance + float cosAngleMax; // Angular limit of the spot in an easier to use form: + // cosine of the half angle in radians + float cosAngleScale; // 1/(cos(border of the penumbra area) - cosAngleMax); + // positive + float radius; // defines the size of the DiskLight represented using + // the (extended) SpotLight + float innerRadius; // defines the size of the inner cut out of the DiskLight + // to represent a RingLight + float areaPdf; // pdf of disk/ring with radius/innerRadius + IntensityDistribution intensityDistribution; + SpotLightDynamic pre; // un- or pre-transformed state + +#ifdef __cplusplus + SpotLight() + : intensity(0.f), + radiance(1.f), + cosAngleMax(1.f), + cosAngleScale(1.f), + radius(0.f), + innerRadius(0.f), + areaPdf(inf) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/lights/SunSkyLight.cpp b/modules/cpu/lights/SunSkyLight.cpp index 3babbec918..5e53015fe7 100644 --- a/modules/cpu/lights/SunSkyLight.cpp +++ b/modules/cpu/lights/SunSkyLight.cpp @@ -1,14 +1,16 @@ -// Copyright 2020-2022 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "SunSkyLight.h" - -#include "common/OSPCommon_ispc.h" -#include "lights/DirectionalLight_ispc.h" -#include "lights/HDRILight_ispc.h" -#include "lights/Light_ispc.h" #include "texture/Texture2D.h" +// embree +#include "embree3/rtcore.h" +// ispc exports +#include "lights/HDRILight_ispc.h" +// ispc shared +#include "DirectionalLightShared.h" +#include "HDRILightShared.h" namespace ospray { @@ -20,7 +22,7 @@ SunSkyLight::SunSkyLight() static auto format = static_cast(OSP_TEXTURE_RGB32F); static auto filter = static_cast(OSP_TEXTURE_FILTER_BILINEAR); - mapIE.Set(skySize, skyImage.data(), format, filter); + mapSh.set(skySize, skyImage.data(), format, filter); } SunSkyLight::~SunSkyLight() @@ -28,25 +30,30 @@ SunSkyLight::~SunSkyLight() ispc::HDRILight_destroyDistribution(distributionIE); } -void *SunSkyLight::createIE(const void *instance) const +ispc::Light *SunSkyLight::createSh( + uint32_t index, const ispc::Instance *instance) const { - void *ie = ispc::HDRILight_create(); - ispc::Light_set(ie, visible, (const ispc::Instance *)instance); - ispc::HDRILight_set(ie, - (ispc::vec3f &)coloredIntensity, - (const ispc::LinearSpace3f &)frame, - &mapIE, - distributionIE); - return ie; -} + switch (index) { + case 0: { + ispc::HDRILight *sh = StructSharedCreate(); + sh->set(visible, + instance, + coloredIntensity, + frame, + &mapSh, + (const ispc::Distribution2D *)distributionIE); + return &sh->super; + } + case 1: { + ispc::DirectionalLight *sh = StructSharedCreate(); + sh->set(visible, instance, direction, solarIrradiance, cosAngle); + return &sh->super; + } -void *SunSkyLight::createSecondIE(const void *instance) const -{ - void *ie = ispc::DirectionalLight_create(); - ispc::Light_set(ie, visible, (const ispc::Instance *)instance); - ispc::DirectionalLight_set( - ie, (ispc::vec3f &)solarIrradiance, (ispc::vec3f &)direction, cosAngle); - return ie; + default: + assert(false && "Incorrect SunSky sublight index"); + } + return nullptr; } std::string SunSkyLight::toString() const @@ -163,7 +170,7 @@ void SunSkyLight::commit() // recreate distribution ispc::HDRILight_destroyDistribution(distributionIE); - distributionIE = ispc::HDRILight_createDistribution(&mapIE); + distributionIE = ispc::HDRILight_createDistribution(&mapSh); } void SunSkyLight::processIntensityQuantityType() diff --git a/modules/cpu/lights/SunSkyLight.h b/modules/cpu/lights/SunSkyLight.h index 1af11cb658..e9815335f8 100644 --- a/modules/cpu/lights/SunSkyLight.h +++ b/modules/cpu/lights/SunSkyLight.h @@ -1,4 +1,4 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -8,6 +8,7 @@ #include "rkcommon/tasking/parallel_for.h" #include "sky_model/color_info.h" #include "sky_model/sky_model.h" +// ispc shared #include "texture/Texture2DShared.h" // Sun and sky environment lights @@ -37,8 +38,9 @@ struct OSPRAY_SDK_INTERFACE SunSkyLight : public Light { SunSkyLight(); virtual ~SunSkyLight() override; - virtual void *createIE(const void *instance = nullptr) const override; - virtual void *createSecondIE(const void *instance = nullptr) const override; + virtual uint32_t getShCount() const override; + virtual ispc::Light *createSh( + uint32_t index, const ispc::Instance *instance = nullptr) const override; virtual std::string toString() const override; virtual void commit() override; @@ -46,7 +48,7 @@ struct OSPRAY_SDK_INTERFACE SunSkyLight : public Light void processIntensityQuantityType(); std::vector skyImage; - ispc::Texture2D mapIE; + ispc::Texture2D mapSh; void *distributionIE{nullptr}; vec2i skySize; linear3f frame{one}; // sky orientation @@ -57,4 +59,11 @@ struct OSPRAY_SDK_INTERFACE SunSkyLight : public Light float intensityScale{0.025f}; }; +// Inlined defintions ///////////////////////////////////////////////////////// + +inline uint32_t SunSkyLight::getShCount() const +{ + return 2; +} + } // namespace ospray diff --git a/modules/cpu/lights/registration.cpp b/modules/cpu/lights/registration.cpp index 122c19787c..ab568ebe1a 100644 --- a/modules/cpu/lights/registration.cpp +++ b/modules/cpu/lights/registration.cpp @@ -1,4 +1,4 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "AmbientLight.h" diff --git a/modules/cpu/lights/sky_model/color_info.h b/modules/cpu/lights/sky_model/color_info.h index 81b0f0bf83..4312fb8fd1 100644 --- a/modules/cpu/lights/sky_model/color_info.h +++ b/modules/cpu/lights/sky_model/color_info.h @@ -1,5 +1,5 @@ // Copyright 2010-2020 Attila T. Afra -// Copyright 2015-2020 Intel Corporation +// Copyright 2015 Intel Corporation // SPDX-License-Identifier: Apache-2.0 namespace ospray { diff --git a/modules/cpu/lights/sky_model/sky_model.cpp b/modules/cpu/lights/sky_model/sky_model.cpp index 8244276e9c..a0b8520f3b 100644 --- a/modules/cpu/lights/sky_model/sky_model.cpp +++ b/modules/cpu/lights/sky_model/sky_model.cpp @@ -28,7 +28,7 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // with slight modifications -// Copyright 2020-2022 Intel Corporation +// Copyright 2020 Intel Corporation /* ============================================================================ diff --git a/modules/cpu/lights/sky_model/sky_model.h b/modules/cpu/lights/sky_model/sky_model.h index bf5f9ae7b9..aea12fb51d 100644 --- a/modules/cpu/lights/sky_model/sky_model.h +++ b/modules/cpu/lights/sky_model/sky_model.h @@ -28,7 +28,7 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // with slight modifications -// Copyright 2020-2022 Intel Corporation +// Copyright 2020 Intel Corporation /* ============================================================================ diff --git a/modules/cpu/math/AffineSpace.ih b/modules/cpu/math/AffineSpace.ih index 2d5a9a7ca5..8a7e937ee0 100644 --- a/modules/cpu/math/AffineSpace.ih +++ b/modules/cpu/math/AffineSpace.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/math/Distribution1D.ih b/modules/cpu/math/Distribution1D.ih index c803cc8438..378396f68d 100644 --- a/modules/cpu/math/Distribution1D.ih +++ b/modules/cpu/math/Distribution1D.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -6,7 +6,7 @@ // input: importance in 'cdf' // output: cdf of importance in 'cdf' // return sum -uniform float Distribution1D_create( +export uniform float Distribution1D_create( const uniform int size, uniform float *uniform cdf); struct Sample1D diff --git a/modules/cpu/math/Distribution1D.ispc b/modules/cpu/math/Distribution1D.ispc index f0bade25a1..86724a8d6d 100644 --- a/modules/cpu/math/Distribution1D.ispc +++ b/modules/cpu/math/Distribution1D.ispc @@ -1,9 +1,9 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Distribution1D.ih" -uniform float Distribution1D_create( +export uniform float Distribution1D_create( const uniform int size, uniform float *uniform cdf) { // accumulate the function diff --git a/modules/cpu/math/Distribution2D.ih b/modules/cpu/math/Distribution2D.ih index 438fa1aa0e..476c767065 100644 --- a/modules/cpu/math/Distribution2D.ih +++ b/modules/cpu/math/Distribution2D.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/math/Distribution2D.ispc b/modules/cpu/math/Distribution2D.ispc index 052e8a6d4b..bfdf86b645 100644 --- a/modules/cpu/math/Distribution2D.ispc +++ b/modules/cpu/math/Distribution2D.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Distribution2D.ih" diff --git a/modules/cpu/math/LinearSpace.ih b/modules/cpu/math/LinearSpace.ih index b1f83cee48..bbba289bfd 100644 --- a/modules/cpu/math/LinearSpace.ih +++ b/modules/cpu/math/LinearSpace.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/math/interpolation.ih b/modules/cpu/math/interpolation.ih index 11a150e680..0c5e941916 100644 --- a/modules/cpu/math/interpolation.ih +++ b/modules/cpu/math/interpolation.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/math/random.ih b/modules/cpu/math/random.ih index c988f19b35..4cd4576595 100644 --- a/modules/cpu/math/random.ih +++ b/modules/cpu/math/random.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/math/sampling.h b/modules/cpu/math/sampling.h new file mode 100644 index 0000000000..7672a22f39 --- /dev/null +++ b/modules/cpu/math/sampling.h @@ -0,0 +1,27 @@ +// Copyright 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +// utility library containing sampling functions + +// convention is to return the sample (vec3f) generated from given vec2f +// 's'ample as last parameter sampling functions often come in pairs: sample and +// pdf (needed later for MIS) good reference is "Total Compendium" by Philip +// Dutre http://people.cs.kuleuven.be/~philip.dutre/GI/ + +#include "rkcommon/math/rkmath.h" + +namespace ospray { + +inline float uniformSampleConePDF(const float cosAngle) +{ + return rcp(float(two_pi) * (1.0f - cosAngle)); +} + +inline float uniformSampleRingPDF(const float radius, const float innerRadius) +{ + return rcp(float(pi) * ((radius * radius) - (innerRadius * innerRadius))); +} + +} // namespace ospray diff --git a/modules/cpu/math/sampling.ih b/modules/cpu/math/sampling.ih index a0d2aff122..26b1dc98b1 100644 --- a/modules/cpu/math/sampling.ih +++ b/modules/cpu/math/sampling.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/math/sobol.ih b/modules/cpu/math/sobol.ih index 168019dcc5..68b0b75a1a 100644 --- a/modules/cpu/math/sobol.ih +++ b/modules/cpu/math/sobol.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // Copyright (c) 2012 Leonhard Gruenschloss (leonhard@gruenschloss.org) diff --git a/modules/cpu/math/sobol.ispc b/modules/cpu/math/sobol.ispc index 682fddba66..ee4e853a13 100644 --- a/modules/cpu/math/sobol.ispc +++ b/modules/cpu/math/sobol.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // Copyright (c) 2012 Leonhard Gruenschloss (leonhard@gruenschloss.org) diff --git a/modules/cpu/math/spectrum.h b/modules/cpu/math/spectrum.h index 46958fc5a6..bf7e4f0950 100644 --- a/modules/cpu/math/spectrum.h +++ b/modules/cpu/math/spectrum.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/math/spectrum.ih b/modules/cpu/math/spectrum.ih index 3a8ff9592b..2402c4bef4 100644 --- a/modules/cpu/math/spectrum.ih +++ b/modules/cpu/math/spectrum.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/math/spectrum.ispc b/modules/cpu/math/spectrum.ispc index 40444d5c66..7ca95775fc 100644 --- a/modules/cpu/math/spectrum.ispc +++ b/modules/cpu/math/spectrum.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "math/spectrum.ih" diff --git a/modules/cpu/render/LoadBalancer.cpp b/modules/cpu/render/LoadBalancer.cpp index 947033d34e..d7f1f57d66 100644 --- a/modules/cpu/render/LoadBalancer.cpp +++ b/modules/cpu/render/LoadBalancer.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "LoadBalancer.h" @@ -14,7 +14,8 @@ void LocalTiledLoadBalancer::renderFrame( fb->beginFrame(); void *perFrameData = renderer->beginFrame(fb, world); - renderTiles(fb, renderer, camera, world, fb->getTileIDs(), perFrameData); + runRenderTasks( + fb, renderer, camera, world, fb->getRenderTaskIDs(), perFrameData); renderer->endFrame(fb, perFrameData); @@ -23,63 +24,29 @@ void LocalTiledLoadBalancer::renderFrame( fb->setCompletedEvent(OSP_FRAME_FINISHED); } -void LocalTiledLoadBalancer::renderTiles(FrameBuffer *fb, +void LocalTiledLoadBalancer::runRenderTasks(FrameBuffer *fb, Renderer *renderer, Camera *camera, World *world, - const utility::ArrayView &tileIDs, + const utility::ArrayView &renderTaskIDs, void *perFrameData) { - bool cancel = false; - std::atomic pixelsDone{0}; - - const auto fbSize = fb->getNumPixels(); - const float rcpPixels = 1.0f / (TILE_SIZE * TILE_SIZE * tileIDs.size()); - -#ifdef OSPRAY_SERIAL_RENDERING - tasking::serial_for(tileIDs.size(), [&](size_t taskIndex) { -#else - tasking::parallel_for(tileIDs.size(), [&](size_t taskIndex) { -#endif - if (cancel) - return; - const size_t numTiles_x = fb->getNumTiles().x; - const size_t tile_y = tileIDs[taskIndex] / numTiles_x; - const size_t tile_x = tileIDs[taskIndex] - tile_y * numTiles_x; - const vec2i tileID(tile_x, tile_y); - const int32 accumID = fb->accumID(tileID); - - // increment also for finished tiles - vec2i numPixels = min(vec2i(TILE_SIZE), fbSize - tileID * TILE_SIZE); - pixelsDone += numPixels.product(); - - if (fb->tileError(tileID) <= renderer->errorThreshold) - return; - -#if TILE_SIZE > MAX_TILE_SIZE - auto tilePtr = make_unique(tileID, fbSize, accumID); - auto &tile = *tilePtr; -#else - Tile __aligned(64) tile(tileID, fbSize, accumID); -#endif - -#ifdef OSPRAY_SERIAL_RENDERING - tasking::serial_for(numJobs(renderer->spp, accumID), [&](size_t tIdx) { -#else - tasking::parallel_for(numJobs(renderer->spp, accumID), [&](size_t tIdx) { -#endif - renderer->renderTile(fb, camera, world, perFrameData, tile, tIdx); - }); - - fb->setTile(tile); - // TODO: Maybe change progress reporting to sum an atomic float instead? - // with multidevice there will be many parallel updates to report progress, - // each reporting their progress on some subset of pixels. - fb->reportProgress(pixelsDone * rcpPixels); - - if (fb->frameCancelled()) - cancel = true; - }); + if (renderer->errorThreshold > 0.f) { + std::vector activeTasks; + for (auto &i : renderTaskIDs) { + const float error = fb->taskError(i); + if (error > renderer->errorThreshold) { + activeTasks.push_back(i); + } + } + renderer->renderTasks(fb, + camera, + world, + perFrameData, + utility::ArrayView(activeTasks)); + } else { + renderer->renderTasks(fb, camera, world, perFrameData, renderTaskIDs); + } } std::string LocalTiledLoadBalancer::toString() const diff --git a/modules/cpu/render/LoadBalancer.h b/modules/cpu/render/LoadBalancer.h index 298512d1cc..ae8e68adf2 100644 --- a/modules/cpu/render/LoadBalancer.h +++ b/modules/cpu/render/LoadBalancer.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -27,27 +27,16 @@ struct OSPRAY_SDK_INTERFACE TiledLoadBalancer /*! Render the specified subset of tiles using the given renderer, camera and * world configuration using the load balancer to parallelize the work */ - virtual void renderTiles(FrameBuffer *fb, + virtual void runRenderTasks(FrameBuffer *fb, Renderer *renderer, Camera *camera, World *world, - const utility::ArrayView &tileIDs, + const utility::ArrayView &renderTaskIDs, void *perFrameData) = 0; - - static size_t numJobs(const int spp, int accumID); }; // Inlined definitions ////////////////////////////////////////////////////// -inline size_t TiledLoadBalancer::numJobs(const int spp, int accumID) -{ - const int blocks = (accumID > 0 || spp > 0) - ? 1 - : std::min(1 << -2 * spp, TILE_SIZE * TILE_SIZE); - return divRoundUp( - (TILE_SIZE * TILE_SIZE) / RENDERTILE_PIXELS_PER_JOB, blocks); -} - //! tiled load balancer for local rendering on the given machine /*! a tiled load balancer that orchestrates (multi-threaded) rendering on a local machine, without any cross-node @@ -60,11 +49,11 @@ struct OSPRAY_SDK_INTERFACE LocalTiledLoadBalancer : public TiledLoadBalancer Camera *camera, World *world) override; - void renderTiles(FrameBuffer *fb, + void runRenderTasks(FrameBuffer *fb, Renderer *renderer, Camera *camera, World *world, - const utility::ArrayView &tileIDs, + const utility::ArrayView &renderTaskIDs, void *perFrameData) override; std::string toString() const override; diff --git a/modules/cpu/render/Material.cpp b/modules/cpu/render/Material.cpp index 5befc4583b..585981a4b0 100644 --- a/modules/cpu/render/Material.cpp +++ b/modules/cpu/render/Material.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray diff --git a/modules/cpu/render/Material.h b/modules/cpu/render/Material.h index eb48840b9d..8dc6c9e951 100644 --- a/modules/cpu/render/Material.h +++ b/modules/cpu/render/Material.h @@ -1,12 +1,11 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/Managed.h" -#include "common/StructShared.h" #include "common/Util.h" - +// ispc shared #include "MaterialShared.h" #include "texture/TextureParamShared.h" diff --git a/modules/cpu/render/Material.ih b/modules/cpu/render/Material.ih index 84f27d0625..fe2d472542 100644 --- a/modules/cpu/render/Material.ih +++ b/modules/cpu/render/Material.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/Material.ispc b/modules/cpu/render/Material.ispc index d11987bcb2..24c82830c3 100644 --- a/modules/cpu/render/Material.ispc +++ b/modules/cpu/render/Material.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Material.ih" diff --git a/modules/cpu/render/MaterialShared.h b/modules/cpu/render/MaterialShared.h index de1e357312..bf4d17409b 100644 --- a/modules/cpu/render/MaterialShared.h +++ b/modules/cpu/render/MaterialShared.h @@ -6,7 +6,7 @@ #define EPS 1e-5f #ifdef __cplusplus -using namespace rkcommon::math; +#include "common/StructShared.h" namespace ispc { typedef void *Material_GetBSDFFunc; typedef void *Material_GetTransparencyFunc; @@ -73,7 +73,8 @@ struct Material // radiance; TODO SV-EDFs #ifdef __cplusplus Material(const vec3f &emission = vec3f(0.f)) - : getBSDF(nullptr), + : type(MATERIAL_TYPE_OBJ), + getBSDF(nullptr), getTransparency(nullptr), selectNextMedium(nullptr), emission(emission) diff --git a/modules/cpu/render/RenderTask.h b/modules/cpu/render/RenderTask.h index 7999d09c95..60d94dc03f 100644 --- a/modules/cpu/render/RenderTask.h +++ b/modules/cpu/render/RenderTask.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/Renderer.cpp b/modules/cpu/render/Renderer.cpp index 5c6f1a91d2..dee222bba3 100644 --- a/modules/cpu/render/Renderer.cpp +++ b/modules/cpu/render/Renderer.cpp @@ -1,15 +1,17 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Renderer.h" +#include "LoadBalancer.h" +#include "Material.h" #include "common/Instance.h" #include "common/Util.h" #include "geometry/GeometricModel.h" +#include "pf/PixelFilter.h" // ispc exports #include "render/Renderer_ispc.h" -// ospray -#include "LoadBalancer.h" +#include "render/util_ispc.h" namespace ospray { @@ -21,6 +23,7 @@ Renderer::Renderer() { managedObjectType = OSP_RENDERER; pixelFilter = nullptr; + getSh()->renderSample = ispc::Renderer_default_renderSample_addr(); } std::string Renderer::toString() const @@ -57,22 +60,23 @@ void Renderer::commit() setupPixelFilter(); if (materialData) - ispcMaterialPtrs = createArrayOfSh(*materialData); + ispcMaterialPtrs = createArrayOfSh(*materialData); else ispcMaterialPtrs.clear(); - if (getIE()) { - ispc::Renderer_set(getIE(), - spp, - maxDepth, - minContribution, - (ispc::vec4f &)bgColor, - backplate ? backplate->getSh() : nullptr, - ispcMaterialPtrs.size(), - ispcMaterialPtrs.data(), - maxDepthTexture ? maxDepthTexture->getSh() : nullptr, - pixelFilter ? pixelFilter->getIE() : nullptr); - } + getSh()->spp = spp; + getSh()->maxDepth = maxDepth; + getSh()->minContribution = minContribution; + getSh()->bgColor = bgColor; + getSh()->backplate = backplate ? backplate->getSh() : nullptr; + getSh()->numMaterials = ispcMaterialPtrs.size(); + getSh()->material = ispcMaterialPtrs.data(); + getSh()->maxDepthTexture = + maxDepthTexture ? maxDepthTexture->getSh() : nullptr; + getSh()->pixelFilter = + (ispc::PixelFilter *)(pixelFilter ? pixelFilter->getIE() : nullptr); + + ispc::precomputeZOrder(); } Renderer *Renderer::createInstance(const char *type) @@ -85,20 +89,19 @@ void Renderer::registerType(const char *type, FactoryFcn f) g_renderersMap[type] = f; } -void Renderer::renderTile(FrameBuffer *fb, +void Renderer::renderTasks(FrameBuffer *fb, Camera *camera, World *world, void *perFrameData, - Tile &tile, - size_t jobID) const + const utility::ArrayView &taskIDs) const { - ispc::Renderer_renderTile(getIE(), - fb->getIE(), - camera->getIE(), - world->getIE(), + ispc::Renderer_renderTasks(getSh(), + fb->getSh(), + camera->getSh(), + world->getSh(), perFrameData, - (ispc::Tile &)tile, - jobID); + taskIDs.data(), + taskIDs.size()); } OSPPickResult Renderer::pick( @@ -108,16 +111,16 @@ OSPPickResult Renderer::pick( res.instance = nullptr; res.model = nullptr; - res.primID = -1; + res.primID = RTC_INVALID_GEOMETRY_ID; - int instID = -1; - int geomID = -1; - int primID = -1; + int instID = RTC_INVALID_GEOMETRY_ID; + int geomID = RTC_INVALID_GEOMETRY_ID; + int primID = RTC_INVALID_GEOMETRY_ID; - ispc::Renderer_pick(getIE(), - fb->getIE(), - camera->getIE(), - world->getIE(), + ispc::Renderer_pick(getSh(), + fb->getSh(), + camera->getSh(), + world->getSh(), (const ispc::vec2f &)screenPos, (ispc::vec3f &)res.worldPosition[0], instID, diff --git a/modules/cpu/render/Renderer.h b/modules/cpu/render/Renderer.h index 11aa8d0334..000c572038 100644 --- a/modules/cpu/render/Renderer.h +++ b/modules/cpu/render/Renderer.h @@ -1,26 +1,30 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once -#include "Material.h" -#include "camera/Camera.h" -#include "common/Util.h" -#include "common/World.h" -#include "fb/FrameBuffer.h" #include "pf/PixelFilter.h" +#include "rkcommon/utility/ArrayView.h" #include "texture/Texture2D.h" +// ispc shared +#include "RendererShared.h" namespace ospray { -/*! \brief abstract base class for all ospray renderers. - - \detailed Tthis base renderer abstraction only knows about - 'rendering a frame'; most actual renderers will be derived from a - tile renderer, but this abstraction level also allows for frame - compositing or even projection/splatting based approaches - */ -struct OSPRAY_SDK_INTERFACE Renderer : public ManagedObject +struct Camera; +struct World; +struct Material; +struct FrameBuffer; +struct PixelFilter; + +// abstract base class for all ospray renderers. +// +// This base renderer abstraction only knows about +// 'rendering a frame'; most actual renderers will be derived from a +// tile renderer, but this abstraction level also allows for frame +// compositing or even projection/splatting based approaches +struct OSPRAY_SDK_INTERFACE Renderer + : public AddStructShared { Renderer(); virtual ~Renderer() override = default; @@ -32,28 +36,27 @@ struct OSPRAY_SDK_INTERFACE Renderer : public ManagedObject virtual void commit() override; virtual std::string toString() const override; - //! \brief called to initialize a new frame - /*! this function gets called exactly once (on each node) at the - beginning of each frame, and allows the renderer to do whatever - is required to initialize a new frame. In particular, this - function _can_ return a pointer to some "per-frame-data"; this - pointer (can be NULL) is then passed to 'renderFrame' and - 'endFrame' to do with as they please - - \returns pointer to per-frame data, or NULL if this does not apply - */ + // called to initialize a new frame + // + // this function gets called exactly once (on each node) at the + // beginning of each frame, and allows the renderer to do whatever + // is required to initialize a new frame. In particular, this + // function _can_ return a pointer to some "per-frame-data"; this + // pointer (can be NULL) is then passed to 'renderFrame' and + // 'endFrame' to do with as they please + // + // returns pointer to per-frame data, or NULL if this does not apply virtual void *beginFrame(FrameBuffer *fb, World *world); - /*! \brief called exactly once (on each node) at the end of each frame */ + // called exactly once (on each node) at the end of each frame virtual void endFrame(FrameBuffer *fb, void *perFrameData); - /*! \brief called by the load balancer to render one tile of "samples" */ - virtual void renderTile(FrameBuffer *fb, + // called by the load balancer to render one "sample" for each task + virtual void renderTasks(FrameBuffer *fb, Camera *camera, World *world, void *perFrameData, - Tile &tile, - size_t jobID) const; + const utility::ArrayView &taskIDs) const; virtual OSPPickResult pick( FrameBuffer *fb, Camera *camera, World *world, const vec2f &screenPos); @@ -70,7 +73,7 @@ struct OSPRAY_SDK_INTERFACE Renderer : public ManagedObject std::unique_ptr pixelFilter; Ref> materialData; - std::vector ispcMaterialPtrs; + std::vector ispcMaterialPtrs; private: template diff --git a/modules/cpu/render/Renderer.ih b/modules/cpu/render/Renderer.ih index 290ab85bf2..1cced898dc 100644 --- a/modules/cpu/render/Renderer.ih +++ b/modules/cpu/render/Renderer.ih @@ -1,92 +1,15 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once -#include "camera/Camera.ih" -#include "fb/FrameBuffer.ih" +#include "common/Ray.ih" #include "fb/Tile.ih" -#include "pf/PixelFilter.ih" -#include "texture/Texture2D.ih" - -#include "MaterialShared.h" - -struct Renderer; -struct World; -struct Camera; - -struct ScreenSample -{ - // input values to 'renderSample' - vec3i sampleID; // x/y=pixelID, z=accumID/sampleID - vec2f pos; // normalized screen position - Ray ray; // the primary ray generated by the camera - - // return values from 'renderSample' - vec3f rgb; - float alpha; - float z; - vec3f normal; - vec3f albedo; -}; - -inline void setTile(uniform Tile &tile, - const varying uint32 pixel, - const varying ScreenSample screenSample) -{ - setRGBAZ(tile, pixel, screenSample.rgb, screenSample.alpha, screenSample.z); - setNormalAlbedo(tile, pixel, screenSample.normal, screenSample.albedo); -} - -/*! Render a given screen sample (as specified in sampleID), and - returns the radiance in 'retVal'. sampleID.x and .y refer to the - pixel ID in the frame buffer, sampleID.z indicates that this should - be the 'z'th sample in a sequence of samples for renderers that - support multi-sampling and/or accumulation. - - Note that it is perfectly valid for different samples to have the - same x, y, or even z values. For example, a accumulation-based - renderer may issue chunks of pixels with sampleID.z all 0 in the - first frame, sampleID.z all 1 in the second, etc, while a - super-sampling renderer make issue a chunk of N samples together for - the same pixel coordinates in the same call. - */ -typedef void (*Renderer_RenderSampleFct)(Renderer *uniform self, - FrameBuffer *uniform fb, - World *uniform model, - void *uniform perFrameData, - varying ScreenSample &retValue); - -typedef unmasked void (*Renderer_RenderTileFct)(Renderer *uniform self, - FrameBuffer *uniform fb, - Camera *uniform camera, - World *uniform model, - void *uniform perFrameData, - uniform Tile &tile, - uniform int taskIndex); - -struct Renderer -{ - Renderer_RenderSampleFct renderSample; - Renderer_RenderTileFct renderTile; - - int32 spp; - vec4f bgColor; // background color and alpha - Texture2D *backplate; - Texture2D *maxDepthTexture; // optional maximum depth texture used for early - // ray termination - int maxDepth; - float minContribution; - - int32 numMaterials; - Material **material; - - PixelFilter *pixelFilter; -}; +#include "render/ScreenSample.ih" +// c++ shared +#include "RendererShared.h" vec4f Renderer_getBackground( const Renderer *uniform self, const vec2f &screenPos); float Renderer_getMaxDepth( const Renderer *uniform self, const vec2f &screenPos); - -void Renderer_Constructor(Renderer *uniform self); diff --git a/modules/cpu/render/Renderer.ispc b/modules/cpu/render/Renderer.ispc index 9989958e2c..3227410485 100644 --- a/modules/cpu/render/Renderer.ispc +++ b/modules/cpu/render/Renderer.ispc @@ -1,11 +1,15 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Renderer.ih" #include "camera/Camera.ih" #include "common/World.ih" #include "math/random.ih" +#include "pf/PixelFilter.ih" #include "render/util.ih" +#include "texture/Texture2D.ih" +// c++ shared +#include "fb/FrameBufferShared.h" vec4f Renderer_getBackground( const Renderer *uniform self, const vec2f &screenPos) @@ -41,13 +45,12 @@ void Renderer_default_renderSample(Renderer *uniform self, sample.rgb = make_vec3f(bg); } -unmasked void Renderer_default_renderTile(Renderer *uniform self, +task void Renderer_default_renderTask(Renderer *uniform self, FrameBuffer *uniform fb, Camera *uniform camera, World *uniform world, void *uniform perFrameData, - uniform Tile &tile, - uniform int taskIndex) + const uint32 *uniform taskIDs) { const uniform int32 spp = self->spp; @@ -57,18 +60,19 @@ unmasked void Renderer_default_renderTile(Renderer *uniform self, CameraSample cameraSample; - 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; + uniform RenderTaskDesc taskDesc = + fb->getRenderTaskDesc(fb, taskIDs[taskIndex0]); - 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]; + const uniform int startSampleID = max(taskDesc.accumID, 0) * spp; - if ((screenSample.sampleID.x >= fb->size.x) - | (screenSample.sampleID.y >= fb->size.y)) - continue; + if (fb->cancelRender || isEmpty(taskDesc.region)) { + return; + } + + foreach_tiled (y = taskDesc.region.lower.y... taskDesc.region.upper.y, + x = taskDesc.region.lower.x... taskDesc.region.upper.x) { + screenSample.sampleID.x = x; + screenSample.sampleID.y = y; // set ray t value for early ray termination (from maximum depth texture) vec2f center = @@ -81,8 +85,6 @@ unmasked void Renderer_default_renderTile(Renderer *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); - for (uniform uint32 s = 0; s < spp; s++) { const float pixel_du = Halton_sample2(startSampleID + s); const float pixel_dv = CranleyPattersonRotation( @@ -90,10 +92,10 @@ unmasked void Renderer_default_renderTile(Renderer *uniform self, 1.f / 6.f); // rotate to sample center (0.5) of pixel for sampleID=0 const vec2f pixelSample = make_vec2f(pixel_du, pixel_dv); + const PixelFilter *uniform pf = self->pixelFilter; vec2f pfSample = pixelSample; - if (self->pixelFilter) { - pfSample = self->pixelFilter->sample(self->pixelFilter, pixelSample) - + make_vec2f(0.5f); + if (pf) { + pfSample = pf->sample(pf, pixelSample) + make_vec2f(0.5f); } screenSample.sampleID.z = startSampleID + s; @@ -113,6 +115,9 @@ unmasked void Renderer_default_renderTile(Renderer *uniform self, screenSample.ray.t = min(screenSample.ray.t, tMax); screenSample.z = inf; + screenSample.primID = RTC_INVALID_GEOMETRY_ID; + screenSample.geomID = RTC_INVALID_GEOMETRY_ID; + screenSample.instID = RTC_INVALID_GEOMETRY_ID; screenSample.albedo = make_vec3f(Renderer_getBackground(self, screenSample.pos)); screenSample.normal = make_vec3f(0.f); @@ -131,69 +136,37 @@ unmasked void Renderer_default_renderTile(Renderer *uniform self, screenSample.z = depth; screenSample.normal = normal * rspp; screenSample.albedo = albedo * rspp; - setTile(tile, pixel, screenSample); + + // Accumulate rendering result directly into the framebuffer, to remove + // the need to call setTile separately on the CPU (but image ops needs + // handling separately, etc.) + fb->accumulateSample(fb, screenSample, taskDesc); } + fb->completeTask(fb, taskDesc); } -export void Renderer_set(void *uniform _self, - const uniform int32 spp, - const uniform int32 maxDepth, - const uniform float minContribution, - const uniform vec4f &bgColor, - void *uniform backplate, - const uniform int32 numMaterials, - void *uniform materials, - void *uniform _maxDepthTexture, - void *uniform pixelFilter); - -void Renderer_Constructor(Renderer *uniform self) +// Exports (called from C++) ////////////////////////////////////////////////// + +export void *uniform Renderer_default_renderSample_addr() { - self->renderSample = Renderer_default_renderSample; - self->renderTile = Renderer_default_renderTile; - Renderer_set(self, 1, 20, 0.001f, make_vec4f(0.f), NULL, 0, NULL, NULL, NULL); + return Renderer_default_renderSample; } -// Exports (called from C++) ////////////////////////////////////////////////// - -export void Renderer_renderTile(void *uniform _self, +export void Renderer_renderTasks(void *uniform _self, void *uniform _fb, void *uniform _camera, void *uniform _world, void *uniform perFrameData, - uniform Tile &tile, - uniform int jobID) + void *uniform _taskIDs, + uniform uint32 numTasks) { Renderer *uniform self = (Renderer * uniform) _self; FrameBuffer *uniform fb = (FrameBuffer * uniform) _fb; Camera *uniform camera = (Camera * uniform) _camera; World *uniform world = (World * uniform) _world; - self->renderTile(self, fb, camera, world, perFrameData, tile, jobID); -} - -export void Renderer_set(void *uniform _self, - const uniform int32 spp, - const uniform int32 maxDepth, - const uniform float minContribution, - const uniform vec4f &bgColor, - void *uniform backplate, - const uniform int32 numMaterials, - void *uniform materials, - void *uniform _maxDepthTexture, - void *uniform pixelFilter) -{ - uniform Renderer *uniform self = (uniform Renderer * uniform) _self; - - self->spp = spp; - self->maxDepth = maxDepth; - self->minContribution = minContribution; - self->bgColor = bgColor; - self->backplate = (uniform Texture2D * uniform) backplate; - self->numMaterials = numMaterials; - self->material = (Material * *uniform) materials; - self->maxDepthTexture = (Texture2D * uniform) _maxDepthTexture; - self->pixelFilter = (PixelFilter * uniform) pixelFilter; - - precomputeZOrder(); + const uint32 *uniform taskIDs = (const uint32 *uniform)_taskIDs; + launch[numTasks] Renderer_default_renderTask( + self, fb, camera, world, perFrameData, taskIDs); } export void Renderer_pick(const void *uniform _self, diff --git a/modules/cpu/render/RendererShared.h b/modules/cpu/render/RendererShared.h new file mode 100644 index 0000000000..695dcbc86d --- /dev/null +++ b/modules/cpu/render/RendererShared.h @@ -0,0 +1,74 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef __cplusplus +#include "common/StructShared.h" +namespace ispc { +typedef void *Renderer_RenderSampleFct; +#else +struct Renderer; +struct World; +struct Camera; +struct FrameBuffer; +struct ScreenSample; +struct Tile; + +// Render a given screen sample (as specified in sampleID), and +// returns the radiance in 'retVal'. sampleID.x and .y refer to the +// pixel ID in the frame buffer, sampleID.z indicates that this should +// be the 'z'th sample in a sequence of samples for renderers that +// support multi-sampling and/or accumulation. +// Note that it is perfectly valid for different samples to have the +// same x, y, or even z values. For example, a accumulation-based +// renderer may issue chunks of pixels with sampleID.z all 0 in the +// first frame, sampleID.z all 1 in the second, etc, while a +// super-sampling renderer make issue a chunk of N samples together for +// the same pixel coordinates in the same call. +typedef void (*Renderer_RenderSampleFct)(Renderer *uniform self, + FrameBuffer *uniform fb, + World *uniform model, + void *uniform perFrameData, + varying ScreenSample &retValue); +#endif // __cplusplus + +struct Texture2D; +struct Material; +struct PixelFilter; + +struct Renderer +{ + Renderer_RenderSampleFct renderSample; + + int32 spp; + vec4f bgColor; // background color and alpha + Texture2D *backplate; + Texture2D *maxDepthTexture; // optional maximum depth texture used for early + // ray termination + int maxDepth; + float minContribution; + + int32 numMaterials; + Material **material; + + PixelFilter *pixelFilter; + +#ifdef __cplusplus + Renderer() + : renderSample(nullptr), + spp(1), + bgColor(0.f), + backplate(nullptr), + maxDepthTexture(nullptr), + maxDepth(20), + minContribution(.001f), + numMaterials(0), + material(nullptr), + pixelFilter(nullptr) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/render/ScreenSample.ih b/modules/cpu/render/ScreenSample.ih new file mode 100644 index 0000000000..37da719e08 --- /dev/null +++ b/modules/cpu/render/ScreenSample.ih @@ -0,0 +1,27 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "common/Ray.ih" +#include "rkcommon/math/vec.ih" + +struct ScreenSample +{ + // input values to 'renderSample' + vec3i sampleID; // x/y=pixelID, z=accumID/sampleID + vec2f pos; // normalized screen position + Ray ray; // the primary ray generated by the camera + + // return values from 'renderSample' + vec3f rgb; + float alpha; + float z; + vec3f normal; + vec3f albedo; + + // IDs of primary ray hits. Invalid: unsigned RTC_INVALID_GEOMETRY_ID, 0xffff + unsigned int primID; + unsigned int geomID; + unsigned int instID; +}; diff --git a/modules/cpu/render/ao/AORenderer.cpp b/modules/cpu/render/ao/AORenderer.cpp index 942e9590a5..2c27a503d7 100644 --- a/modules/cpu/render/ao/AORenderer.cpp +++ b/modules/cpu/render/ao/AORenderer.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "AORenderer.h" @@ -8,7 +8,7 @@ namespace ospray { AORenderer::AORenderer(int defaultNumSamples) : aoSamples(defaultNumSamples) { - ispcEquivalent = ispc::AORenderer_create(); + getSh()->super.renderSample = ispc::AORenderer_renderSample_addr(); } std::string AORenderer::toString() const @@ -20,11 +20,11 @@ void AORenderer::commit() { Renderer::commit(); - ispc::AORenderer_set(getIE(), - getParam("aoSamples", aoSamples), - getParam("aoDistance", getParam("aoRadius", 1e20f)), - getParam("aoIntensity", 1.f), - getParam("volumeSamplingRate", 1.f)); + getSh()->aoSamples = getParam("aoSamples", aoSamples); + getSh()->aoRadius = + getParam("aoDistance", getParam("aoRadius", 1e20f)); + getSh()->aoIntensity = getParam("aoIntensity", 1.f); + getSh()->volumeSamplingRate = getParam("volumeSamplingRate", 1.f); } } // namespace ospray diff --git a/modules/cpu/render/ao/AORenderer.h b/modules/cpu/render/ao/AORenderer.h index cb4e8b51d6..5fbacaadc7 100644 --- a/modules/cpu/render/ao/AORenderer.h +++ b/modules/cpu/render/ao/AORenderer.h @@ -2,11 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 // ospray -#include "../Renderer.h" +#include "render/Renderer.h" +// ispc shared +#include "AORendererShared.h" namespace ospray { -struct AORenderer : public Renderer +struct AORenderer : public AddStructShared { AORenderer(int defaultAORendererSamples = 1); std::string toString() const override; diff --git a/modules/cpu/render/ao/AORenderer.ih b/modules/cpu/render/ao/AORenderer.ih deleted file mode 100644 index b6933034e7..0000000000 --- a/modules/cpu/render/ao/AORenderer.ih +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2009-2020 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "common/World.ih" -#include "render/Renderer.ih" - -struct AORenderer -{ - Renderer super; - int aoSamples; - float aoRadius; - float aoIntensity; - float volumeSamplingRate; -}; diff --git a/modules/cpu/render/ao/AORenderer.ispc b/modules/cpu/render/ao/AORenderer.ispc index f89ad6cb70..b34d04edc6 100644 --- a/modules/cpu/render/ao/AORenderer.ispc +++ b/modules/cpu/render/ao/AORenderer.ispc @@ -1,12 +1,14 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "math/random.ih" #include "render/Renderer.ih" // AO renderer -#include "AORenderer.ih" #include "surfaces.ih" #include "volumes.ih" +// c++ shared +#include "AORendererShared.h" +#include "fb/FrameBufferShared.h" void AORenderer_renderSample(Renderer *uniform _self, FrameBuffer *uniform fb, @@ -108,25 +110,7 @@ void AORenderer_renderSample(Renderer *uniform _self, // AORenderer C++ interface //////////////////////////////////////////////////// -export void *uniform AORenderer_create() +export void *uniform AORenderer_renderSample_addr() { - uniform AORenderer *uniform self = uniform new uniform AORenderer; - Renderer_Constructor(&self->super); - self->super.renderSample = AORenderer_renderSample; - return self; -} - -export void AORenderer_set(void *uniform _self, - uniform int aoSamples, - uniform float aoRadius, - uniform float aoIntensity, - uniform float volumeSamplingRate) -{ - uniform AORenderer *uniform self = (uniform AORenderer * uniform) _self; - - self->aoSamples = aoSamples; - self->aoRadius = aoRadius; - self->aoIntensity = aoIntensity; - - self->volumeSamplingRate = volumeSamplingRate; -} + return AORenderer_renderSample; +} \ No newline at end of file diff --git a/modules/cpu/render/ao/AORendererShared.h b/modules/cpu/render/ao/AORendererShared.h new file mode 100644 index 0000000000..8a4408733c --- /dev/null +++ b/modules/cpu/render/ao/AORendererShared.h @@ -0,0 +1,28 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "render/RendererShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +struct AORenderer +{ + Renderer super; + int aoSamples; + float aoRadius; + float aoIntensity; + float volumeSamplingRate; + +#ifdef __cplusplus + AORenderer() + : aoSamples(1), aoRadius(1e20f), aoIntensity(1.f), volumeSamplingRate(1.f) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/render/ao/surfaces.ih b/modules/cpu/render/ao/surfaces.ih index a421d08397..b8fdfc0a3c 100644 --- a/modules/cpu/render/ao/surfaces.ih +++ b/modules/cpu/render/ao/surfaces.ih @@ -1,9 +1,13 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once -#include "AORenderer.ih" +#include "common/World.ih" +// c++ shared +#include "AORendererShared.h" + +struct DifferentialGeometry; struct SurfaceShadingInfo { diff --git a/modules/cpu/render/ao/surfaces.ispc b/modules/cpu/render/ao/surfaces.ispc index 5d37f93df8..3633310339 100644 --- a/modules/cpu/render/ao/surfaces.ispc +++ b/modules/cpu/render/ao/surfaces.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "math/random.ih" diff --git a/modules/cpu/render/ao/volumes.ih b/modules/cpu/render/ao/volumes.ih index 898bb343fe..f5e03d27b2 100644 --- a/modules/cpu/render/ao/volumes.ih +++ b/modules/cpu/render/ao/volumes.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -6,11 +6,8 @@ #include "common/Clipping.ih" #include "common/Ray.ih" #include "common/VolumeIntervals.ih" -#include "math/random.ih" -#include "volume/VolumetricModel.ih" struct LDSampler; -struct RandomSampler; vec4f integrateVolumeIntervals(const VolumeIntervals &intervals, const RayIntervals &rayIntervals, diff --git a/modules/cpu/render/ao/volumes.ispc b/modules/cpu/render/ao/volumes.ispc index 3cfe4c7ce6..0cf4aa0b8b 100644 --- a/modules/cpu/render/ao/volumes.ispc +++ b/modules/cpu/render/ao/volumes.ispc @@ -1,13 +1,11 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "volumes.ih" -// ispc device #include "math/random.ih" #include "math/sampling.ih" #include "render/util.ih" - -#include "openvkl/openvkl.isph" +#include "volume/VolumetricModel.ih" +#include "volumes.ih" struct VolumeContext { diff --git a/modules/cpu/render/bsdfs/BSDF.ih b/modules/cpu/render/bsdfs/BSDF.ih index 96b61de8b4..4e69dae423 100644 --- a/modules/cpu/render/bsdfs/BSDF.ih +++ b/modules/cpu/render/bsdfs/BSDF.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/BeckmannDistribution.ih b/modules/cpu/render/bsdfs/BeckmannDistribution.ih index 1cf68a4c84..728a13aed9 100644 --- a/modules/cpu/render/bsdfs/BeckmannDistribution.ih +++ b/modules/cpu/render/bsdfs/BeckmannDistribution.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/Conductor.ih b/modules/cpu/render/bsdfs/Conductor.ih index 44084d4062..eccbdc4162 100644 --- a/modules/cpu/render/bsdfs/Conductor.ih +++ b/modules/cpu/render/bsdfs/Conductor.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/Dielectric.ih b/modules/cpu/render/bsdfs/Dielectric.ih index e139110498..24cca1899d 100644 --- a/modules/cpu/render/bsdfs/Dielectric.ih +++ b/modules/cpu/render/bsdfs/Dielectric.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/DielectricLayer.ih b/modules/cpu/render/bsdfs/DielectricLayer.ih index d90f8d5536..8a9fbac57c 100644 --- a/modules/cpu/render/bsdfs/DielectricLayer.ih +++ b/modules/cpu/render/bsdfs/DielectricLayer.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/Fresnel.ih b/modules/cpu/render/bsdfs/Fresnel.ih index 862d4f68ab..5a8b0e816a 100644 --- a/modules/cpu/render/bsdfs/Fresnel.ih +++ b/modules/cpu/render/bsdfs/Fresnel.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/GGXDistribution.ih b/modules/cpu/render/bsdfs/GGXDistribution.ih index 0640bf8612..40d25be479 100644 --- a/modules/cpu/render/bsdfs/GGXDistribution.ih +++ b/modules/cpu/render/bsdfs/GGXDistribution.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/Lambert.ih b/modules/cpu/render/bsdfs/Lambert.ih index 74134867e7..4ea03ff83b 100644 --- a/modules/cpu/render/bsdfs/Lambert.ih +++ b/modules/cpu/render/bsdfs/Lambert.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/LambertTransmission.ih b/modules/cpu/render/bsdfs/LambertTransmission.ih index 89cdb87378..c834fc9a61 100644 --- a/modules/cpu/render/bsdfs/LambertTransmission.ih +++ b/modules/cpu/render/bsdfs/LambertTransmission.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/MicrofacetAlbedo.ih b/modules/cpu/render/bsdfs/MicrofacetAlbedo.ih index ca37f90e21..d0172c9f65 100644 --- a/modules/cpu/render/bsdfs/MicrofacetAlbedo.ih +++ b/modules/cpu/render/bsdfs/MicrofacetAlbedo.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/MicrofacetAlbedoTables.ih b/modules/cpu/render/bsdfs/MicrofacetAlbedoTables.ih index 9b085987e4..ada8c9f74e 100644 --- a/modules/cpu/render/bsdfs/MicrofacetAlbedoTables.ih +++ b/modules/cpu/render/bsdfs/MicrofacetAlbedoTables.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -70,8 +70,6 @@ extern uniform float * MICROFACET_SHEEN_ALBEDO_TABLE_SIZE]; // directional 2D table // (cosThetaO, roughness) -void precomputeMicrofacetAlbedoTables(); - inline float MicrofacetAlbedoTable_eval(float cosThetaO, float roughness) { const uniform int size = MICROFACET_ALBEDO_TABLE_SIZE; diff --git a/modules/cpu/render/bsdfs/MicrofacetAlbedoTables.ispc b/modules/cpu/render/bsdfs/MicrofacetAlbedoTables.ispc index 4ce130f93c..83969c8141 100644 --- a/modules/cpu/render/bsdfs/MicrofacetAlbedoTables.ispc +++ b/modules/cpu/render/bsdfs/MicrofacetAlbedoTables.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "MicrofacetAlbedo.ih" @@ -178,7 +178,7 @@ static void MicrofacetSheenAlbedoTable_precompute() } } -void precomputeMicrofacetAlbedoTables() +export void precomputeMicrofacetAlbedoTables() { if (MicrofacetAlbedoTable_initialized) return; diff --git a/modules/cpu/render/bsdfs/MicrofacetConductor.ih b/modules/cpu/render/bsdfs/MicrofacetConductor.ih index 39161fa181..b253c847b3 100644 --- a/modules/cpu/render/bsdfs/MicrofacetConductor.ih +++ b/modules/cpu/render/bsdfs/MicrofacetConductor.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/MicrofacetDielectric.ih b/modules/cpu/render/bsdfs/MicrofacetDielectric.ih index 390bdc0a23..340aaf3405 100644 --- a/modules/cpu/render/bsdfs/MicrofacetDielectric.ih +++ b/modules/cpu/render/bsdfs/MicrofacetDielectric.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/MicrofacetDielectricLayer.ih b/modules/cpu/render/bsdfs/MicrofacetDielectricLayer.ih index dff64b4f84..4afb1615f3 100644 --- a/modules/cpu/render/bsdfs/MicrofacetDielectricLayer.ih +++ b/modules/cpu/render/bsdfs/MicrofacetDielectricLayer.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/MicrofacetDistribution.ih b/modules/cpu/render/bsdfs/MicrofacetDistribution.ih index a2925866fe..53b9215a43 100644 --- a/modules/cpu/render/bsdfs/MicrofacetDistribution.ih +++ b/modules/cpu/render/bsdfs/MicrofacetDistribution.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/MicrofacetSheenLayer.ih b/modules/cpu/render/bsdfs/MicrofacetSheenLayer.ih index 936740036b..44badd4ccb 100644 --- a/modules/cpu/render/bsdfs/MicrofacetSheenLayer.ih +++ b/modules/cpu/render/bsdfs/MicrofacetSheenLayer.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/Minneart.ih b/modules/cpu/render/bsdfs/Minneart.ih index 100c055654..e6ebcf8a5c 100644 --- a/modules/cpu/render/bsdfs/Minneart.ih +++ b/modules/cpu/render/bsdfs/Minneart.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/MultiBSDF.ih b/modules/cpu/render/bsdfs/MultiBSDF.ih index da25496079..1a24df9668 100644 --- a/modules/cpu/render/bsdfs/MultiBSDF.ih +++ b/modules/cpu/render/bsdfs/MultiBSDF.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/Optics.ih b/modules/cpu/render/bsdfs/Optics.ih index 3391d0baa1..1985d17c73 100644 --- a/modules/cpu/render/bsdfs/Optics.ih +++ b/modules/cpu/render/bsdfs/Optics.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/OrenNayar.ih b/modules/cpu/render/bsdfs/OrenNayar.ih index b4848ea337..0e8f0d5821 100644 --- a/modules/cpu/render/bsdfs/OrenNayar.ih +++ b/modules/cpu/render/bsdfs/OrenNayar.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/PowerCosineDistribution.ih b/modules/cpu/render/bsdfs/PowerCosineDistribution.ih index 91c0705f39..2048be0cb3 100644 --- a/modules/cpu/render/bsdfs/PowerCosineDistribution.ih +++ b/modules/cpu/render/bsdfs/PowerCosineDistribution.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/Reflection.ih b/modules/cpu/render/bsdfs/Reflection.ih index a90cee6f93..3cf2085134 100644 --- a/modules/cpu/render/bsdfs/Reflection.ih +++ b/modules/cpu/render/bsdfs/Reflection.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/RobustDielectric.ih b/modules/cpu/render/bsdfs/RobustDielectric.ih index 8dfd1b3102..70560279d5 100644 --- a/modules/cpu/render/bsdfs/RobustDielectric.ih +++ b/modules/cpu/render/bsdfs/RobustDielectric.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/RobustThinDielectric.ih b/modules/cpu/render/bsdfs/RobustThinDielectric.ih index 1463014fe7..1715429b2b 100644 --- a/modules/cpu/render/bsdfs/RobustThinDielectric.ih +++ b/modules/cpu/render/bsdfs/RobustThinDielectric.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/Scale.ih b/modules/cpu/render/bsdfs/Scale.ih index e21f8c4abe..99f5caa59c 100644 --- a/modules/cpu/render/bsdfs/Scale.ih +++ b/modules/cpu/render/bsdfs/Scale.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/ShadingContext.ih b/modules/cpu/render/bsdfs/ShadingContext.ih index eb0c2cbe15..96974d39a9 100644 --- a/modules/cpu/render/bsdfs/ShadingContext.ih +++ b/modules/cpu/render/bsdfs/ShadingContext.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/SheenDistribution.ih b/modules/cpu/render/bsdfs/SheenDistribution.ih index 81a63c0ea6..9b3fa24e21 100644 --- a/modules/cpu/render/bsdfs/SheenDistribution.ih +++ b/modules/cpu/render/bsdfs/SheenDistribution.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/Specular.ih b/modules/cpu/render/bsdfs/Specular.ih index 845da601c4..e9c3518d1b 100644 --- a/modules/cpu/render/bsdfs/Specular.ih +++ b/modules/cpu/render/bsdfs/Specular.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/ThinDielectric.ih b/modules/cpu/render/bsdfs/ThinDielectric.ih index a478f6a4da..eb1cbdf5df 100644 --- a/modules/cpu/render/bsdfs/ThinDielectric.ih +++ b/modules/cpu/render/bsdfs/ThinDielectric.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/ThinMicrofacetDielectric.ih b/modules/cpu/render/bsdfs/ThinMicrofacetDielectric.ih index d56e8d0f4a..fbf370ee1c 100644 --- a/modules/cpu/render/bsdfs/ThinMicrofacetDielectric.ih +++ b/modules/cpu/render/bsdfs/ThinMicrofacetDielectric.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/Transmission.ih b/modules/cpu/render/bsdfs/Transmission.ih index 5ca8f6d6ae..e2be5011f9 100644 --- a/modules/cpu/render/bsdfs/Transmission.ih +++ b/modules/cpu/render/bsdfs/Transmission.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/bsdfs/Velvety.ih b/modules/cpu/render/bsdfs/Velvety.ih index aee9e879e2..a29f828738 100644 --- a/modules/cpu/render/bsdfs/Velvety.ih +++ b/modules/cpu/render/bsdfs/Velvety.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/debug/DebugRenderer.cpp b/modules/cpu/render/debug/DebugRenderer.cpp index a66ba8efb5..79b16feb89 100644 --- a/modules/cpu/render/debug/DebugRenderer.cpp +++ b/modules/cpu/render/debug/DebugRenderer.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray @@ -49,7 +49,7 @@ static DebugRendererType typeFromString(const std::string &name) DebugRenderer::DebugRenderer() { - ispcEquivalent = ispc::DebugRenderer_create(); + getSh()->renderSample = ispc::DebugRenderer_testFrame_addr(); } std::string DebugRenderer::toString() const @@ -60,8 +60,56 @@ std::string DebugRenderer::toString() const void DebugRenderer::commit() { Renderer::commit(); + std::string method = getParam("method", "eyeLight"); - ispc::DebugRenderer_set(getIE(), typeFromString(method)); + switch (typeFromString(method)) { + case RAY_DIR: + getSh()->renderSample = ispc::DebugRenderer_rayDir_addr(); + break; + case EYE_LIGHT: + getSh()->renderSample = ispc::DebugRenderer_eyeLight_addr(); + break; + case NG: + getSh()->renderSample = ispc::DebugRenderer_Ng_addr(); + break; + case NS: + getSh()->renderSample = ispc::DebugRenderer_Ns_addr(); + break; + case COLOR: + getSh()->renderSample = ispc::DebugRenderer_vertexColor_addr(); + break; + case TEX_COORD: + getSh()->renderSample = ispc::DebugRenderer_texCoord_addr(); + break; + case DPDS: + getSh()->renderSample = ispc::DebugRenderer_dPds_addr(); + break; + case DPDT: + getSh()->renderSample = ispc::DebugRenderer_dPdt_addr(); + break; + case PRIM_ID: + getSh()->renderSample = ispc::DebugRenderer_primID_addr(); + break; + case GEOM_ID: + getSh()->renderSample = ispc::DebugRenderer_geomID_addr(); + break; + case INST_ID: + getSh()->renderSample = ispc::DebugRenderer_instID_addr(); + break; + case BACKFACING_NG: + getSh()->renderSample = ispc::DebugRenderer_backfacing_Ng_addr(); + break; + case BACKFACING_NS: + getSh()->renderSample = ispc::DebugRenderer_backfacing_Ns_addr(); + break; + case VOLUME: + getSh()->renderSample = ispc::DebugRenderer_volume_addr(); + break; + case TEST_FRAME: + default: + getSh()->renderSample = ispc::DebugRenderer_testFrame_addr(); + break; + } } } // namespace ospray diff --git a/modules/cpu/render/debug/DebugRenderer.h b/modules/cpu/render/debug/DebugRenderer.h index adc0855c80..36410a96ef 100644 --- a/modules/cpu/render/debug/DebugRenderer.h +++ b/modules/cpu/render/debug/DebugRenderer.h @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/debug/DebugRenderer.ispc b/modules/cpu/render/debug/DebugRenderer.ispc index b7e039df5a..1419d88f95 100644 --- a/modules/cpu/render/debug/DebugRenderer.ispc +++ b/modules/cpu/render/debug/DebugRenderer.ispc @@ -1,17 +1,15 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray +#include "DebugRendererType.h" #include "common/World.ih" -#include "fb/FrameBuffer.ih" #include "math/random.ih" #include "render/Renderer.ih" -#include "render/util.ih" +#include "rkcommon/utility/random.ih" #include "volume/VolumetricModel.ih" - -#include "DebugRendererType.h" - -#include "openvkl/openvkl.isph" +// c++ shared +#include "fb/FrameBufferShared.h" // common utility function, traces ray and handles default and background bool hitBackground( @@ -332,64 +330,24 @@ void DebugRenderer_volume(Renderer *uniform self, // DebugRenderer C++ interface //////////////////////////////////////////////// -export void *uniform DebugRenderer_create() -{ - Renderer *uniform self = uniform new Renderer; - Renderer_Constructor(self); - self->renderSample = DebugRenderer_testFrame; - return self; -} - -export void DebugRenderer_set(void *uniform _self, uniform int type) -{ - Renderer *uniform self = (Renderer * uniform) _self; - - switch (type) { - case RAY_DIR: - self->renderSample = DebugRenderer_rayDir; - break; - case EYE_LIGHT: - self->renderSample = DebugRenderer_eyeLight; - break; - case NG: - self->renderSample = DebugRenderer_Ng; - break; - case NS: - self->renderSample = DebugRenderer_Ns; - break; - case COLOR: - self->renderSample = DebugRenderer_vertexColor; - break; - case TEX_COORD: - self->renderSample = DebugRenderer_texCoord; - break; - case DPDS: - self->renderSample = DebugRenderer_dPds; - break; - case DPDT: - self->renderSample = DebugRenderer_dPdt; - break; - case PRIM_ID: - self->renderSample = DebugRenderer_primID; - break; - case GEOM_ID: - self->renderSample = DebugRenderer_geomID; - break; - case INST_ID: - self->renderSample = DebugRenderer_instID; - break; - case BACKFACING_NG: - self->renderSample = DebugRenderer_backfacing_Ng; - break; - case BACKFACING_NS: - self->renderSample = DebugRenderer_backfacing_Ns; - break; - case VOLUME: - self->renderSample = DebugRenderer_volume; - break; - case TEST_FRAME: - default: - self->renderSample = DebugRenderer_testFrame; - break; +#define EXPORT_FN_ADDR(name) \ + export void *uniform name##_addr() \ + { \ + return name; \ } -} + +EXPORT_FN_ADDR(DebugRenderer_testFrame); +EXPORT_FN_ADDR(DebugRenderer_rayDir); +EXPORT_FN_ADDR(DebugRenderer_eyeLight); +EXPORT_FN_ADDR(DebugRenderer_Ng); +EXPORT_FN_ADDR(DebugRenderer_Ns); +EXPORT_FN_ADDR(DebugRenderer_vertexColor); +EXPORT_FN_ADDR(DebugRenderer_texCoord); +EXPORT_FN_ADDR(DebugRenderer_dPds); +EXPORT_FN_ADDR(DebugRenderer_dPdt); +EXPORT_FN_ADDR(DebugRenderer_primID); +EXPORT_FN_ADDR(DebugRenderer_geomID); +EXPORT_FN_ADDR(DebugRenderer_instID); +EXPORT_FN_ADDR(DebugRenderer_backfacing_Ng); +EXPORT_FN_ADDR(DebugRenderer_backfacing_Ns); +EXPORT_FN_ADDR(DebugRenderer_volume); diff --git a/modules/cpu/render/debug/DebugRendererType.h b/modules/cpu/render/debug/DebugRendererType.h index 06c1d42d54..f03158a4a3 100644 --- a/modules/cpu/render/debug/DebugRendererType.h +++ b/modules/cpu/render/debug/DebugRendererType.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/materials/Alloy.cpp b/modules/cpu/render/materials/Alloy.cpp index ff6c641867..2262b43c29 100644 --- a/modules/cpu/render/materials/Alloy.cpp +++ b/modules/cpu/render/materials/Alloy.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Alloy.h" diff --git a/modules/cpu/render/materials/Alloy.h b/modules/cpu/render/materials/Alloy.h index 5fa93e4cd4..b7aa7685bf 100644 --- a/modules/cpu/render/materials/Alloy.h +++ b/modules/cpu/render/materials/Alloy.h @@ -1,8 +1,8 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" - +// ispc shared #include "AlloyShared.h" namespace ospray { diff --git a/modules/cpu/render/materials/Alloy.ispc b/modules/cpu/render/materials/Alloy.ispc index 2b6f5326a6..7f24579981 100644 --- a/modules/cpu/render/materials/Alloy.ispc +++ b/modules/cpu/render/materials/Alloy.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.ih" diff --git a/modules/cpu/render/materials/CarPaint.cpp b/modules/cpu/render/materials/CarPaint.cpp index 18aa401dfe..3301842bf7 100644 --- a/modules/cpu/render/materials/CarPaint.cpp +++ b/modules/cpu/render/materials/CarPaint.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "CarPaint.h" diff --git a/modules/cpu/render/materials/CarPaint.h b/modules/cpu/render/materials/CarPaint.h index 7eec4de70a..8bd8d96735 100644 --- a/modules/cpu/render/materials/CarPaint.h +++ b/modules/cpu/render/materials/CarPaint.h @@ -1,8 +1,8 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" - +// ispc shared #include "CarPaintShared.h" namespace ospray { diff --git a/modules/cpu/render/materials/CarPaint.ispc b/modules/cpu/render/materials/CarPaint.ispc index 6518808341..daa34177ab 100644 --- a/modules/cpu/render/materials/CarPaint.ispc +++ b/modules/cpu/render/materials/CarPaint.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.ih" diff --git a/modules/cpu/render/materials/Glass.cpp b/modules/cpu/render/materials/Glass.cpp index e2acb8f995..355ef93bed 100644 --- a/modules/cpu/render/materials/Glass.cpp +++ b/modules/cpu/render/materials/Glass.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Glass.h" diff --git a/modules/cpu/render/materials/Glass.h b/modules/cpu/render/materials/Glass.h index a02b033054..70762f685c 100644 --- a/modules/cpu/render/materials/Glass.h +++ b/modules/cpu/render/materials/Glass.h @@ -1,8 +1,8 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" - +// ispc shared #include "GlassShared.h" namespace ospray { diff --git a/modules/cpu/render/materials/Glass.ispc b/modules/cpu/render/materials/Glass.ispc index 184d1de423..6f284f89b1 100644 --- a/modules/cpu/render/materials/Glass.ispc +++ b/modules/cpu/render/materials/Glass.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Medium.ih" diff --git a/modules/cpu/render/materials/Luminous.cpp b/modules/cpu/render/materials/Luminous.cpp index 2d408a4ea6..c2731142f1 100644 --- a/modules/cpu/render/materials/Luminous.cpp +++ b/modules/cpu/render/materials/Luminous.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Luminous.h" diff --git a/modules/cpu/render/materials/Luminous.h b/modules/cpu/render/materials/Luminous.h index 06a3de638b..b487e58c8e 100644 --- a/modules/cpu/render/materials/Luminous.h +++ b/modules/cpu/render/materials/Luminous.h @@ -1,8 +1,8 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" - +// ispc shared #include "LuminousShared.h" namespace ospray { diff --git a/modules/cpu/render/materials/Luminous.ispc b/modules/cpu/render/materials/Luminous.ispc index bd6a170b54..0f977c9d11 100644 --- a/modules/cpu/render/materials/Luminous.ispc +++ b/modules/cpu/render/materials/Luminous.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.ih" diff --git a/modules/cpu/render/materials/Medium.ih b/modules/cpu/render/materials/Medium.ih index 82296bc27a..8d7773adcc 100644 --- a/modules/cpu/render/materials/Medium.ih +++ b/modules/cpu/render/materials/Medium.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/materials/Metal.cpp b/modules/cpu/render/materials/Metal.cpp index cd1db3b533..c747057649 100644 --- a/modules/cpu/render/materials/Metal.cpp +++ b/modules/cpu/render/materials/Metal.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Metal.h" diff --git a/modules/cpu/render/materials/Metal.h b/modules/cpu/render/materials/Metal.h index 38f7f00370..2ad5aaea93 100644 --- a/modules/cpu/render/materials/Metal.h +++ b/modules/cpu/render/materials/Metal.h @@ -1,9 +1,9 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "math/spectrum.h" #include "render/Material.h" - +// ispc shared #include "MetalShared.h" namespace ospray { diff --git a/modules/cpu/render/materials/Metal.ispc b/modules/cpu/render/materials/Metal.ispc index e80a90d7c8..bb8cd6c851 100644 --- a/modules/cpu/render/materials/Metal.ispc +++ b/modules/cpu/render/materials/Metal.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "math/spectrum.ih" diff --git a/modules/cpu/render/materials/MetallicPaint.cpp b/modules/cpu/render/materials/MetallicPaint.cpp index e3be7759c8..bc49c30240 100644 --- a/modules/cpu/render/materials/MetallicPaint.cpp +++ b/modules/cpu/render/materials/MetallicPaint.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "MetallicPaint.h" diff --git a/modules/cpu/render/materials/MetallicPaint.h b/modules/cpu/render/materials/MetallicPaint.h index 7b518e4704..bf5a78c352 100644 --- a/modules/cpu/render/materials/MetallicPaint.h +++ b/modules/cpu/render/materials/MetallicPaint.h @@ -1,9 +1,9 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "math/spectrum.h" #include "render/Material.h" - +// ispc shared #include "MetallicPaintShared.h" namespace ospray { diff --git a/modules/cpu/render/materials/MetallicPaint.ispc b/modules/cpu/render/materials/MetallicPaint.ispc index 7ad974d65d..0898d75b77 100644 --- a/modules/cpu/render/materials/MetallicPaint.ispc +++ b/modules/cpu/render/materials/MetallicPaint.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.ih" diff --git a/modules/cpu/render/materials/Mix.cpp b/modules/cpu/render/materials/Mix.cpp index 64245049e8..274cc904d8 100644 --- a/modules/cpu/render/materials/Mix.cpp +++ b/modules/cpu/render/materials/Mix.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Mix.h" diff --git a/modules/cpu/render/materials/Mix.h b/modules/cpu/render/materials/Mix.h index 1fd30d9711..9ed149cef5 100644 --- a/modules/cpu/render/materials/Mix.h +++ b/modules/cpu/render/materials/Mix.h @@ -1,8 +1,8 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" - +// ispc shared #include "MixShared.h" namespace ospray { diff --git a/modules/cpu/render/materials/Mix.ispc b/modules/cpu/render/materials/Mix.ispc index f867023e2f..2929a1c255 100644 --- a/modules/cpu/render/materials/Mix.ispc +++ b/modules/cpu/render/materials/Mix.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.ih" diff --git a/modules/cpu/render/materials/OBJ.cpp b/modules/cpu/render/materials/OBJ.cpp index 63c613523b..d2bb5376e9 100644 --- a/modules/cpu/render/materials/OBJ.cpp +++ b/modules/cpu/render/materials/OBJ.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "OBJ.h" diff --git a/modules/cpu/render/materials/OBJ.h b/modules/cpu/render/materials/OBJ.h index ca0511cf88..56679e348a 100644 --- a/modules/cpu/render/materials/OBJ.h +++ b/modules/cpu/render/materials/OBJ.h @@ -1,8 +1,8 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" - +// ispc shared #include "OBJShared.h" namespace ospray { diff --git a/modules/cpu/render/materials/OBJ.ih b/modules/cpu/render/materials/OBJ.ih index 3d802155bf..d5c3550050 100644 --- a/modules/cpu/render/materials/OBJ.ih +++ b/modules/cpu/render/materials/OBJ.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/materials/OBJ.ispc b/modules/cpu/render/materials/OBJ.ispc index 629fef134e..2dcce8e9ea 100644 --- a/modules/cpu/render/materials/OBJ.ispc +++ b/modules/cpu/render/materials/OBJ.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "OBJ.ih" diff --git a/modules/cpu/render/materials/Plastic.cpp b/modules/cpu/render/materials/Plastic.cpp index b88df90b7a..04c3f85b9a 100644 --- a/modules/cpu/render/materials/Plastic.cpp +++ b/modules/cpu/render/materials/Plastic.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Plastic.h" diff --git a/modules/cpu/render/materials/Plastic.h b/modules/cpu/render/materials/Plastic.h index 58c418ffac..08947706ba 100644 --- a/modules/cpu/render/materials/Plastic.h +++ b/modules/cpu/render/materials/Plastic.h @@ -1,8 +1,8 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" - +// ispc shared #include "PlasticShared.h" namespace ospray { diff --git a/modules/cpu/render/materials/Plastic.ispc b/modules/cpu/render/materials/Plastic.ispc index 98af3aad25..3318daae38 100644 --- a/modules/cpu/render/materials/Plastic.ispc +++ b/modules/cpu/render/materials/Plastic.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.ih" diff --git a/modules/cpu/render/materials/Principled.cpp b/modules/cpu/render/materials/Principled.cpp index 40a88e9220..d8c49bd784 100644 --- a/modules/cpu/render/materials/Principled.cpp +++ b/modules/cpu/render/materials/Principled.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Principled.h" diff --git a/modules/cpu/render/materials/Principled.h b/modules/cpu/render/materials/Principled.h index b7b760c19d..5db89af74e 100644 --- a/modules/cpu/render/materials/Principled.h +++ b/modules/cpu/render/materials/Principled.h @@ -1,8 +1,8 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" - +// ispc shared #include "PrincipledShared.h" namespace ospray { diff --git a/modules/cpu/render/materials/Principled.ispc b/modules/cpu/render/materials/Principled.ispc index 40bf97c6f3..31f05968ea 100644 --- a/modules/cpu/render/materials/Principled.ispc +++ b/modules/cpu/render/materials/Principled.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Medium.ih" diff --git a/modules/cpu/render/materials/ThinGlass.cpp b/modules/cpu/render/materials/ThinGlass.cpp index e099a40210..3e2361ffef 100644 --- a/modules/cpu/render/materials/ThinGlass.cpp +++ b/modules/cpu/render/materials/ThinGlass.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ThinGlass.h" diff --git a/modules/cpu/render/materials/ThinGlass.h b/modules/cpu/render/materials/ThinGlass.h index 6fbf60260a..5dacd496b0 100644 --- a/modules/cpu/render/materials/ThinGlass.h +++ b/modules/cpu/render/materials/ThinGlass.h @@ -1,8 +1,8 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" - +// ispc shared #include "ThinGlassShared.h" namespace ospray { diff --git a/modules/cpu/render/materials/ThinGlass.ispc b/modules/cpu/render/materials/ThinGlass.ispc index 3757e5c6d8..965a2d8819 100644 --- a/modules/cpu/render/materials/ThinGlass.ispc +++ b/modules/cpu/render/materials/ThinGlass.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.ih" diff --git a/modules/cpu/render/materials/Velvet.cpp b/modules/cpu/render/materials/Velvet.cpp index 81a02d3edb..b976d5f4cc 100644 --- a/modules/cpu/render/materials/Velvet.cpp +++ b/modules/cpu/render/materials/Velvet.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Velvet.h" diff --git a/modules/cpu/render/materials/Velvet.h b/modules/cpu/render/materials/Velvet.h index 1f55308bcf..f0fbdb2f86 100644 --- a/modules/cpu/render/materials/Velvet.h +++ b/modules/cpu/render/materials/Velvet.h @@ -1,8 +1,8 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" - +// ispc shared #include "VelvetShared.h" namespace ospray { diff --git a/modules/cpu/render/materials/Velvet.ispc b/modules/cpu/render/materials/Velvet.ispc index 036a6b305f..1434002c83 100644 --- a/modules/cpu/render/materials/Velvet.ispc +++ b/modules/cpu/render/materials/Velvet.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.ih" diff --git a/modules/cpu/render/pathtracer/GeometryLight.cpp b/modules/cpu/render/pathtracer/GeometryLight.cpp new file mode 100644 index 0000000000..9891e2efe4 --- /dev/null +++ b/modules/cpu/render/pathtracer/GeometryLight.cpp @@ -0,0 +1,40 @@ +// Copyright 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "rkcommon/math/rkmath.h" +// ispc exports +#include "render/pathtracer/GeometryLight_ispc.h" +// ispc shared +#include "GeometryLightShared.h" + +namespace ispc { + +using namespace ospray; + +void GeometryLight::create(const Instance *instance, + const GeometricModel *model, + int32 numPrimitives, + int32 *primIDs, + float *distribution, + float pdf) +{ + super.instance = instance; + super.sample = ispc::GeometryLight_sample_addr(); + super.eval = nullptr; // geometry lights are hit and explicitly handled + + this->model = model; + this->numPrimitives = numPrimitives; + this->pdf = pdf; + + this->primIDs = BufferSharedCreate(numPrimitives, primIDs); + this->distribution = BufferSharedCreate(numPrimitives, distribution); +} + +void GeometryLight::destroy() +{ + BufferSharedDelete(primIDs); + BufferSharedDelete(distribution); + primIDs = nullptr; + distribution = nullptr; +} +} // namespace ispc \ No newline at end of file diff --git a/modules/cpu/render/pathtracer/GeometryLight.ih b/modules/cpu/render/pathtracer/GeometryLight.ih index e097684faf..036b628123 100644 --- a/modules/cpu/render/pathtracer/GeometryLight.ih +++ b/modules/cpu/render/pathtracer/GeometryLight.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -15,5 +15,3 @@ vec3f evaluateGeometryLights(const PathContext &pathContext, const PathVertex &lastVertex, const PathVertex &pathVertex, Ray &ray); - -void GeometryLight_destroy(void *uniform _self); diff --git a/modules/cpu/render/pathtracer/GeometryLight.ispc b/modules/cpu/render/pathtracer/GeometryLight.ispc index eab35e41e1..201e6ad713 100644 --- a/modules/cpu/render/pathtracer/GeometryLight.ispc +++ b/modules/cpu/render/pathtracer/GeometryLight.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/pathtracer/GeometryLight.ih" @@ -7,10 +7,12 @@ #include "render/Material.ih" +#include "common/Instance.ih" #include "geometry/GeometricModel.ih" -#include "lights/Light.ih" #include "math/AffineSpace.ih" #include "math/Distribution1D.ih" +// c++ shared +#include "GeometryLightShared.h" vec3f evaluateGeometryLights(const PathContext &pathContext, const PathState &pathState, @@ -41,22 +43,6 @@ vec3f evaluateGeometryLights(const PathContext &pathContext, return L; } -/* The GeometryLight is a proxy object fulfilling the Light.ih API. - It is generated internally for each emitting geometry modelance to facilitate - explicit importance sampling (currently wrt. the surface area). -*/ - -struct GeometryLight -{ - Light super; // inherited light fields - - GeometricModel *model; // underlying geometry - int32 numPrimitives; // number of emissive primitives - int32 *primIDs; // IDs of emissive primitives to sample - float *distribution; // pdf over prims proportional to (world-space) area - float pdf; // probability density to sample point on surface := 1/area -}; - // Implementation ///////////////////////////////////////////////////////////// Light_SampleRes GeometryLight_sample(const Light *uniform super, @@ -116,85 +102,7 @@ Light_SampleRes GeometryLight_sample(const Light *uniform super, // Exports (called from C++) ////////////////////////////////////////////////// -export bool uniform GeometryLight_isSupported(const void *uniform _model) -{ - GeometricModel *uniform model = (GeometricModel * uniform) _model; - const Geometry *uniform geo = model->geom; - return geo->sampleArea && geo->getAreas; -} - -export void *uniform GeometryLight_create( - void *uniform _model, void *uniform _renderer, void *uniform _instance) +export void *uniform GeometryLight_sample_addr() { - GeometricModel *uniform model = (GeometricModel * uniform) _model; - - if (!GeometryLight_isSupported(model)) { - // set pdf to zero, indicating that this emissive geometry cannot be - // sampled, but only be hit (and thus MIS weight for BSDF samples will be 1) - model->areaPDF = 0.f; - return NULL; - } - - GeometryLight *uniform self = uniform new GeometryLight; - const Renderer *uniform renderer = (Renderer * uniform) _renderer; - const Geometry *uniform geo = model->geom; - const Instance *uniform instance = (Instance * uniform) _instance; - - Light_Constructor(&self->super); - self->super.sample = GeometryLight_sample; - self->super.eval = NULL; // geometry lights are hit and explicitly handled - self->super.instance = instance; - self->model = model; - - // create the list of emissive primitive IDs - self->primIDs = uniform new uniform int32[geo->numPrimitives]; - uniform int32 numEmissivePrims = 0; - foreach (primID = 0 ... geo->numPrimitives) { - Material *mat = - (Material *)GeometricModel_getMaterial(model, renderer, primID); - const vec3f emission = mat->emission; - if (reduce_max(emission) > 0.f) { - int offset = exclusive_scan_add(1); - - self->primIDs[numEmissivePrims + offset] = primID; - numEmissivePrims += reduce_add(1); - } - } - - if (numEmissivePrims == 0) { - // no emissive primitives, return NULL - delete[] self->primIDs; - model->areaPDF = 0.f; - return NULL; - } else if (numEmissivePrims < geo->numPrimitives) { - // save memory - int32 *uniform newPrimIDs = uniform new uniform int32[numEmissivePrims]; - memcpy(newPrimIDs, self->primIDs, numEmissivePrims * sizeof(uniform int32)); - delete[] self->primIDs; - self->primIDs = newPrimIDs; - } - - self->numPrimitives = numEmissivePrims; - - // create the sampling distribution - // TODO: use emissive power instead of just area - // TODO: motion blur can introduce scale, which means areas cannot accurately - // be precomputed - self->distribution = uniform new uniform float[numEmissivePrims]; - geo->getAreas( - geo, self->primIDs, numEmissivePrims, instance->xfm, self->distribution); - self->pdf = 1.f / Distribution1D_create(numEmissivePrims, self->distribution); - model->areaPDF = self->pdf; - - return self; -} - -void GeometryLight_destroy(void *uniform _self) -{ - GeometryLight *uniform self = (GeometryLight * uniform) _self; - if (self) { - delete[] self->primIDs; - delete[] self->distribution; - } - delete self; + return GeometryLight_sample; } diff --git a/modules/cpu/render/pathtracer/GeometryLightShared.h b/modules/cpu/render/pathtracer/GeometryLightShared.h new file mode 100644 index 0000000000..13203691bd --- /dev/null +++ b/modules/cpu/render/pathtracer/GeometryLightShared.h @@ -0,0 +1,46 @@ +// Copyright 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "lights/LightShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +struct GeometricModel; + +// The GeometryLight is a proxy object fulfilling the Light.ih API. +// It is generated internally for each emitting geometry modelance to facilitate +// explicit importance sampling (currently wrt. the surface area). +struct GeometryLight +{ + Light super; // inherited light fields + + const GeometricModel *model; // underlying geometry + int32 numPrimitives; // number of emissive primitives + int32 *primIDs; // IDs of emissive primitives to sample + float *distribution; // pdf over prims proportional to (world-space) area + float pdf; // probability density to sample point on surface := 1/area + +#ifdef __cplusplus + GeometryLight() + : model(nullptr), + numPrimitives(0), + primIDs(nullptr), + distribution(nullptr), + pdf(inf) + {} + void create(const Instance *instance, + const GeometricModel *model, + int32 numPrimitives, + int32 *primIDs, + float *distribution, + float pdf); + void destroy(); +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/render/pathtracer/NextEventEstimation.ih b/modules/cpu/render/pathtracer/NextEventEstimation.ih index 9c11490332..b474b478b9 100644 --- a/modules/cpu/render/pathtracer/NextEventEstimation.ih +++ b/modules/cpu/render/pathtracer/NextEventEstimation.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/pathtracer/NextEventEstimation.ispc b/modules/cpu/render/pathtracer/NextEventEstimation.ispc index ea8d3c06cf..d6b7857a22 100644 --- a/modules/cpu/render/pathtracer/NextEventEstimation.ispc +++ b/modules/cpu/render/pathtracer/NextEventEstimation.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/pathtracer/NextEventEstimation.ih" @@ -9,8 +9,11 @@ #include "render/pathtracer/volumes/VolumeSampler.ih" +#include "common/World.ih" #include "math/Distribution1D.ih" #include "math/sampling.ih" +// c++ shared +#include "lights/LightShared.h" vec3f nextEventEstimation(const PathContext &pathContext, const PathState &pathState, @@ -26,8 +29,8 @@ vec3f nextEventEstimation(const PathContext &pathContext, pathContext.numLights, pathContext.lightsCDF, 0, s1); const float lightSelectionProb = lSelectSample.prob * pathContext.numLightSamples; - const Light *light = - pathContext.world->pathtracerData.lights[lSelectSample.idx]; + const World *uniform world = pathContext.world; + const Light *light = world->pathtracerData.lights[lSelectSample.idx]; // sample the contribution from the random light source const vec2f s2 = LDSampler_getFloat2( pathContext.ldSampler, pathState.sampleDim + 4 + i * 3 + 1); diff --git a/modules/cpu/render/pathtracer/PathSampler.ih b/modules/cpu/render/pathtracer/PathSampler.ih index ec63e43fe7..3efcd24a5f 100644 --- a/modules/cpu/render/pathtracer/PathSampler.ih +++ b/modules/cpu/render/pathtracer/PathSampler.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/pathtracer/PathSampler.ispc b/modules/cpu/render/pathtracer/PathSampler.ispc index 94b9605cd5..ec2929d580 100644 --- a/modules/cpu/render/pathtracer/PathSampler.ispc +++ b/modules/cpu/render/pathtracer/PathSampler.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/pathtracer/GeometryLight.ih" @@ -12,37 +12,44 @@ #include "render/pathtracer/VirtualLight.ih" #include "common/Intersect.ih" +#include "common/World.ih" #include "render/Material.ih" -#include "render/bsdfs/BSDF.ih" #include "render/bsdfs/MicrofacetAlbedoTables.ih" #include "render/materials/Medium.ih" #include "render/pathtracer/volumes/VolumeSampler.ih" +// c++ shared +#include "PathTracerShared.h" + inline void postIntersect(const PathContext &pathContext, const PathState &pathState, PathVertex &pathVertex, Ray &ray) { + const PathTracer *uniform pt = pathContext.context; if (pathVertex.type == SURFACE) { postIntersect(pathContext.world, - &pathContext.context->super, + &pt->super, pathVertex.dg, ray, DG_NS | DG_NG | DG_FACEFORWARD | DG_NORMALIZE | DG_TEXCOORD | DG_COLOR | DG_TANGENTS | DG_MOTIONBLUR); } if (pathVertex.type == VOLUME) { - pathVertex.dg.Ng = make_vec3f(0.f); - pathVertex.dg.Ns = make_vec3f(0.f); - pathVertex.dg.dPds = make_vec3f(0.f); - pathVertex.dg.dPdt = make_vec3f(0.f); - pathVertex.dg.st = make_vec2f(0); - pathVertex.dg.color = make_vec4f(0.f); - pathVertex.dg.primID = RTC_INVALID_GEOMETRY_ID; - pathVertex.dg.areaPDF = 0.f; - pathVertex.dg.epsilon = 0.f; - pathVertex.dg.material = NULL; - pathVertex.dg.renderer = &pathContext.context->super; + pathVertex.dg.P = ray.org + ray.t * ray.dir; + pathVertex.dg.renderer = &pt->super; + + pathVertex.dg.instID = ray.instID; + foreach_unique (instID in ray.instID) + if (instID != RTC_INVALID_GEOMETRY_ID) { + const World *uniform world = pathContext.world; + const Instance *uniform instance = *(world->instances + instID); + if (instance->userID != RTC_INVALID_GEOMETRY_ID) + pathVertex.dg.instID = instance->userID; + } + + foreach_unique (volm in pathVertex.volume) + VolumetricModel_postIntersect(volm, pathVertex.dg, ray, 0); } } @@ -123,10 +130,6 @@ void samplePath(const PathContext &pathContext, pathVertex.type = SURFACE; } - // record depth of primary rays - if (pathState.depth == 0) - sample.z = ray.t; - if (shadowCatcher(pathContext, pathState, pathVertex, ray, sample)) pathVertex.type = ENVIRONMENT; @@ -144,10 +147,13 @@ void samplePath(const PathContext &pathContext, pathVertex.albedo); if (freePath < inf) { pathVertex.type = VOLUME; - pathVertex.dg.P = make_vec3f(ray.org + ray.dir * freePath); pathState.throughput = pathState.throughput * pathVertex.albedo; } + // record depth of primary rays + if (pathState.depth == 0) + sample.z = ray.t; + // background handling if (pathVertex.type == ENVIRONMENT && (pathContext.context->backgroundRefraction @@ -174,8 +180,9 @@ void samplePath(const PathContext &pathContext, // terminate after evaluation of lights and before next shading to always // have both samples for MIS except if we have geometry lights (which we // still need to evaluate for MIS) + const World *uniform w = pathContext.world; if (pathState.depth >= pathContext.context->super.maxDepth - && pathContext.world->pathtracerData.numGeoLights == 0) + && w->pathtracerData.numGeoLights == 0) break; postIntersect(pathContext, pathState, pathVertex, ray); @@ -186,6 +193,13 @@ void samplePath(const PathContext &pathContext, pathContext, pathState, lastVertex, pathVertex, ray); } + // record IDs of primary rays + if (pathState.depth == 0) { + sample.primID = pathVertex.dg.primID; + sample.geomID = pathVertex.dg.objID; + sample.instID = pathVertex.dg.instID; + } + // terminate after evaluation of lights and before next shading to always // have both samples for MIS if (pathState.depth >= pathContext.context->super.maxDepth) diff --git a/modules/cpu/render/pathtracer/PathStructs.ih b/modules/cpu/render/pathtracer/PathStructs.ih index 7d4cd25eea..d1522e0562 100644 --- a/modules/cpu/render/pathtracer/PathStructs.ih +++ b/modules/cpu/render/pathtracer/PathStructs.ih @@ -1,18 +1,18 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once -#include "render/pathtracer/PathTracer.ih" -#include "render/pathtracer/Scattering.ih" - +#include "common/DifferentialGeometry.ih" #include "render/bsdfs/BSDF.ih" #include "render/materials/Medium.ih" - -#include "common/DifferentialGeometry.ih" -#include "common/World.ih" -#include "math/random.ih" #include "volume/VolumetricModel.ih" +// c++ shared +#include "PathTracerShared.h" + +struct World; +struct LDSampler; +struct RandomSampler; enum PathVertexType { diff --git a/modules/cpu/render/pathtracer/PathTracer.cpp b/modules/cpu/render/pathtracer/PathTracer.cpp index 4960062f57..991efbdfe4 100644 --- a/modules/cpu/render/pathtracer/PathTracer.cpp +++ b/modules/cpu/render/pathtracer/PathTracer.cpp @@ -1,34 +1,34 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "PathTracer.h" // ospray +#include "camera/Camera.h" #include "common/Data.h" #include "common/Instance.h" +#include "common/World.h" +#include "fb/FrameBuffer.h" #include "geometry/GeometricModel.h" #include "lights/Light.h" #include "render/Material.h" // ispc exports -#include "common/World_ispc.h" -#include "render/pathtracer/GeometryLight_ispc.h" +#include "geometry/GeometricModel_ispc.h" +#include "render/bsdfs/MicrofacetAlbedoTables_ispc.h" #include "render/pathtracer/PathTracer_ispc.h" +// ispc shared +#include "render/pathtracer/GeometryLightShared.h" // std #include namespace ospray { -PathTracer::PathTracer() -{ - ispcEquivalent = ispc::PathTracer_create(); -} - std::string PathTracer::toString() const { return "ospray::PathTracer"; } void PathTracer::generateGeometryLights( - const World &world, std::vector &lightArray) + const World &world, std::vector &lightArray) { if (!world.instances) return; @@ -44,7 +44,7 @@ void PathTracer::generateGeometryLights( // check whether the model has any emissive materials bool hasEmissive = false; for (auto mat : model->ispcMaterialPtrs) { - if (mat && ((ispc::Material *)mat)->isEmissive()) { + if (mat && mat->isEmissive()) { hasEmissive = true; break; } @@ -60,13 +60,30 @@ void PathTracer::generateGeometryLights( } if (hasEmissive) { - if (ispc::GeometryLight_isSupported(model->getIE())) { - void *light = ispc::GeometryLight_create( - model->getIE(), getIE(), instance->getIE()); + if (model->geometry().supportAreaLighting()) { + std::vector primIDs(model->geometry().numPrimitives()); + std::vector distribution(model->geometry().numPrimitives()); + float pdf = 0.f; + unsigned int numPrimIDs = + ispc::GeometricModel_gatherEmissivePrimIDs(model->getSh(), + getSh(), + instance->getSh(), + primIDs.data(), + distribution.data(), + pdf); // check whether the geometry has any emissive primitives - if (light) - lightArray.push_back(light); + if (numPrimIDs) { + ispc::GeometryLight *light = + StructSharedCreate(); + light->create(instance->getSh(), + model->getSh(), + numPrimIDs, + primIDs.data(), + distribution.data(), + pdf); + lightArray.push_back(&light->super); + } } else { postStatusMsg(OSP_LOG_WARNING) << "#osp:pt Geometry " << model->toString() @@ -84,19 +101,23 @@ void PathTracer::commit() { Renderer::commit(); - const int32 rouletteDepth = getParam("roulettePathLength", 5); - const int32 numLightSamples = getParam("lightSamples", -1); - const float maxRadiance = getParam("maxContribution", inf); - vec4f shadowCatcherPlane = getParam("shadowCatcherPlane", vec4f(0.f)); + getSh()->rouletteDepth = getParam("roulettePathLength", 5); + getSh()->maxRadiance = getParam("maxContribution", inf); + getSh()->numLightSamples = getParam("lightSamples", -1); + + // Set shadow catcher plane + const vec4f shadowCatcherPlane = + getParam("shadowCatcherPlane", vec4f(0.f)); + const vec3f normal = vec3f(shadowCatcherPlane); + const float l = length(normal); + getSh()->shadowCatcher = l > 0.f; + const float rl = rcp(l); + getSh()->shadowCatcherPlane = vec4f(normal * rl, shadowCatcherPlane.w * rl); + importanceSampleGeometryLights = getParam("geometryLights", true); - const bool bgRefraction = getParam("backgroundRefraction", false); - - ispc::PathTracer_set(getIE(), - rouletteDepth, - maxRadiance, - (ispc::vec4f &)shadowCatcherPlane, - numLightSamples, - bgRefraction); + getSh()->backgroundRefraction = getParam("backgroundRefraction", false); + + ispc::precomputeMicrofacetAlbedoTables(); } void *PathTracer::beginFrame(FrameBuffer *, World *world) @@ -110,7 +131,7 @@ void *PathTracer::beginFrame(FrameBuffer *, World *world) if (world->pathtracerDataValid && geometryLightListValid) return nullptr; - std::vector lightArray; + std::vector lightArray; size_t geometryLights{0}; if (importanceSampleGeometryLights) { @@ -120,10 +141,8 @@ void *PathTracer::beginFrame(FrameBuffer *, World *world) if (world->lights) { for (auto &&obj : *world->lights) { - lightArray.push_back(obj->createIE()); - void *secondIE = obj->createSecondIE(); - if (secondIE) - lightArray.push_back(secondIE); + for (uint32_t id = 0; id < obj->getShCount(); id++) + lightArray.push_back(obj->createSh(id)); } } @@ -136,17 +155,21 @@ void *PathTracer::beginFrame(FrameBuffer *, World *world) // Add instance lights to array for (auto &&obj : *inst->group->lights) { - lightArray.push_back(obj->createIE(inst->getIE())); - void *secondIE = obj->createSecondIE(inst->getIE()); - if (secondIE) - lightArray.push_back(secondIE); + for (uint32_t id = 0; id < obj->getShCount(); id++) + lightArray.push_back(obj->createSh(id, inst->getSh())); } } } - void **lightPtr = lightArray.empty() ? nullptr : &lightArray[0]; - ispc::World_setPathtracerData( - world->getIE(), lightPtr, lightArray.size(), geometryLights); + // Prepare light cumulative distribution function + std::vector lightsCDF(lightArray.size(), 1.f); + ispc::Distribution1D_create(lightsCDF.size(), lightsCDF.data()); + + // Prepare pathtracer data structure + ispc::PathtracerData &pd = world->getSh()->pathtracerData; + pd.destroy(); + pd.create( + lightArray.data(), lightArray.size(), geometryLights, lightsCDF.data()); world->pathtracerDataValid = true; scannedGeometryLights = importanceSampleGeometryLights; @@ -154,4 +177,19 @@ void *PathTracer::beginFrame(FrameBuffer *, World *world) return nullptr; } +void PathTracer::renderTasks(FrameBuffer *fb, + Camera *camera, + World *world, + void *perFrameData, + const utility::ArrayView &taskIDs) const +{ + ispc::PathTracer_renderTasks(getSh(), + fb->getSh(), + camera->getSh(), + world->getSh(), + perFrameData, + taskIDs.data(), + taskIDs.size()); +} + } // namespace ospray diff --git a/modules/cpu/render/pathtracer/PathTracer.h b/modules/cpu/render/pathtracer/PathTracer.h index d05fdb5988..545b52980e 100644 --- a/modules/cpu/render/pathtracer/PathTracer.h +++ b/modules/cpu/render/pathtracer/PathTracer.h @@ -1,22 +1,32 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once -#include "render/Material.h" #include "render/Renderer.h" +// ispc shared +#include "PathTracerShared.h" + +namespace ispc { +struct Light; +} namespace ospray { -struct PathTracer : public Renderer +struct PathTracer : public AddStructShared { - PathTracer(); virtual std::string toString() const override; virtual void commit() override; virtual void *beginFrame(FrameBuffer *, World *) override; + virtual void renderTasks(FrameBuffer *fb, + Camera *camera, + World *world, + void *perFrameData, + const utility::ArrayView &taskIDs) const override; + private: - void generateGeometryLights(const World &, std::vector &); + void generateGeometryLights(const World &, std::vector &); bool importanceSampleGeometryLights{ true}; // if geometry lights are importance // sampled using NEE (requires scanning diff --git a/modules/cpu/render/pathtracer/PathTracer.ispc b/modules/cpu/render/pathtracer/PathTracer.ispc index ad4c10ad21..4cfd4e4afd 100644 --- a/modules/cpu/render/pathtracer/PathTracer.ispc +++ b/modules/cpu/render/pathtracer/PathTracer.ispc @@ -1,24 +1,29 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "PathSampler.ih" #include "PathStructs.ih" -#include "PathTracer.ih" #include "PathTracerDefines.ih" #include "PathTracerUtil.ih" -#include "lights/Light.ih" +#include "render/Renderer.ih" #include "render/bsdfs/BSDF.ih" #include "render/bsdfs/MicrofacetAlbedoTables.ih" #include "render/materials/Medium.ih" +#include "render/util.ih" #include "volumes/VolumeSampler.ih" -#include "render/MaterialShared.h" - #include "camera/Camera.ih" -#include "fb/LocalFB.ih" +#include "common/World.ih" #include "math/Distribution1D.ih" #include "math/random.ih" +#include "pf/PixelFilter.ih" +// c++ shared +#include "PathTracerShared.h" +#include "fb/FrameBufferShared.h" +#include "render/MaterialShared.h" + +#define MAX_LIGHTS 1000u ScreenSample PathTraceIntegrator_Li(const PathTracer *uniform self, const World *uniform world, @@ -35,6 +40,9 @@ ScreenSample PathTraceIntegrator_Li(const PathTracer *uniform self, sample.alpha = 1.f; sample.normal = make_vec3f(0.0f); sample.albedo = make_vec3f(0.0f); + sample.primID = RTC_INVALID_GEOMETRY_ID; + sample.geomID = RTC_INVALID_GEOMETRY_ID; + sample.instID = RTC_INVALID_GEOMETRY_ID; const uniform int numLights = world->pathtracerData.lights ? min(MAX_LIGHTS, world->pathtracerData.numLights) @@ -97,6 +105,10 @@ inline ScreenSample PathTracer_renderPixel(PathTracer *uniform self, screenSample.sampleID.x = ix; screenSample.sampleID.y = iy; + screenSample.primID = RTC_INVALID_GEOMETRY_ID; + screenSample.geomID = RTC_INVALID_GEOMETRY_ID; + screenSample.instID = RTC_INVALID_GEOMETRY_ID; + LDSampler ldSamplerObj; RandomSampler randomSamplerObj; varying LDSampler *uniform ldSampler = &ldSamplerObj; @@ -114,10 +126,9 @@ inline ScreenSample PathTracer_renderPixel(PathTracer *uniform self, const vec2f pixelSample = LDSampler_getFloat2(ldSampler, 0); vec2f pfSample = pixelSample; - if (self->super.pixelFilter) { - pfSample = - self->super.pixelFilter->sample(self->super.pixelFilter, pixelSample) - + make_vec2f(0.5f); + PixelFilter *uniform pf = self->super.pixelFilter; + if (pf) { + pfSample = pf->sample(pf, pixelSample) + make_vec2f(0.5f); } cameraSample.screen.x = @@ -144,9 +155,14 @@ inline ScreenSample PathTracer_renderPixel(PathTracer *uniform self, screenSample.rgb = screenSample.rgb + min(sample.rgb, make_vec3f(self->maxRadiance)); screenSample.alpha = screenSample.alpha + sample.alpha; - screenSample.z = min(screenSample.z, sample.z); screenSample.normal = screenSample.normal + sample.normal; screenSample.albedo = screenSample.albedo + sample.albedo; + if (sample.z < screenSample.z) { + screenSample.z = sample.z; + screenSample.primID = sample.primID; + screenSample.geomID = sample.geomID; + screenSample.instID = sample.instID; + } } const float rspp = rcpf(spp); @@ -158,76 +174,46 @@ inline ScreenSample PathTracer_renderPixel(PathTracer *uniform self, return screenSample; } -void PathTracer_renderTileJob(PathTracer *uniform self, +task void PathTracer_renderTask(PathTracer *uniform self, FrameBuffer *uniform fb, Camera *uniform camera, World *uniform world, - uniform Tile &tile, - uniform int taskIndex) + void *uniform perFrameData, + const uint32 *uniform taskIDs) { - const uniform int begin = taskIndex * RENDERTILE_PIXELS_PER_JOB; - const uniform int end = - min(begin + RENDERTILE_PIXELS_PER_JOB, TILE_SIZE * TILE_SIZE); + uniform RenderTaskDesc taskDesc = + fb->getRenderTaskDesc(fb, taskIDs[taskIndex0]); - for (uint32 i = begin + programIndex; i < end; i += programCount) { - const uint32 ix = tile.region.lower.x + z_order.xs[i]; - const uint32 iy = tile.region.lower.y + z_order.ys[i]; - if (ix >= fb->size.x || iy >= fb->size.y) - continue; + if (fb->cancelRender || isEmpty(taskDesc.region)) { + return; + } + foreach_tiled (y = taskDesc.region.lower.y... taskDesc.region.upper.y, + x = taskDesc.region.lower.x... taskDesc.region.upper.x) { ScreenSample screenSample = - PathTracer_renderPixel(self, fb, camera, world, ix, iy, tile.accumID); + PathTracer_renderPixel(self, fb, camera, world, x, y, taskDesc.accumID); - const uint32 pixel = z_order.xs[i] + (z_order.ys[i] * TILE_SIZE); - setTile(tile, pixel, screenSample); + fb->accumulateSample(fb, screenSample, taskDesc); } -} - -unmasked void PathTracer_renderTile(Renderer *uniform _self, - FrameBuffer *uniform fb, - Camera *uniform camera, - World *uniform world, - void *uniform perFrameData, - uniform Tile &tile, - uniform int jobID) -{ - PathTracer *uniform self = (PathTracer * uniform) _self; - PathTracer_renderTileJob(self, fb, camera, world, tile, jobID); + fb->completeTask(fb, taskDesc); } // Exports (called from C++) ////////////////////////////////////////////////// -export void PathTracer_set(void *uniform _self, - const uniform int32 rouletteDepth, - const uniform float maxRadiance, - const uniform vec4f &shadowCatcherPlane, - const uniform int32 numLightSamples, - const uniform bool backgroundRefraction) +export void PathTracer_renderTasks(void *uniform _self, + void *uniform _fb, + void *uniform _camera, + void *uniform _world, + void *uniform perFrameData, + void *uniform _taskIDs, + uniform uint32 numTasks) { PathTracer *uniform self = (PathTracer * uniform) _self; + FrameBuffer *uniform fb = (FrameBuffer * uniform) _fb; + Camera *uniform camera = (Camera * uniform) _camera; + World *uniform world = (World * uniform) _world; + const uint32 *uniform taskIDs = (const uint32 *uniform)_taskIDs; - self->rouletteDepth = rouletteDepth; - self->maxRadiance = maxRadiance; - self->numLightSamples = numLightSamples; - self->backgroundRefraction = backgroundRefraction; - - uniform vec3f normal = make_vec3f(shadowCatcherPlane); - const uniform float l = length(normal); - self->shadowCatcher = l > 0.f; - const uniform float rl = rcp(l); - self->shadowCatcherPlane = make_vec4f(normal * rl, shadowCatcherPlane.w * rl); -} - -export void *uniform PathTracer_create() -{ - uniform PathTracer *uniform self = uniform new uniform PathTracer; - Renderer_Constructor(&self->super); - self->super.renderTile = PathTracer_renderTile; - - PathTracer_set(self, 5, inf, make_vec4f(0.f), 1, false); - - precomputeMicrofacetAlbedoTables(); - precomputeZOrder(); - - return self; + launch[numTasks] PathTracer_renderTask( + self, fb, camera, world, perFrameData, taskIDs); } diff --git a/modules/cpu/render/pathtracer/PathTracerData.cpp b/modules/cpu/render/pathtracer/PathTracerData.cpp new file mode 100644 index 0000000000..063679b053 --- /dev/null +++ b/modules/cpu/render/pathtracer/PathTracerData.cpp @@ -0,0 +1,43 @@ +// Copyright 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "rkcommon/math/rkmath.h" +// ispc shared +#include "GeometryLightShared.h" +#include "PathTracerDataShared.h" + +using namespace ospray; + +namespace ispc { + +void PathtracerData::create( + Light **lights, uint32 numLights, uint32 numGeoLights, float *lightsCDF) +{ + this->numLights = numLights; + this->numGeoLights = numGeoLights; + if (numLights) { + // Allocate shared buffers and copy light pointers there + this->lights = BufferSharedCreate(numLights, lights); + this->lightsCDF = BufferSharedCreate(numLights, lightsCDF); + } +} + +void PathtracerData::destroy() +{ + // Delete GeometryLights first + for (unsigned int i = 0; i < numGeoLights; i++) { + ((GeometryLight *)lights[i])->destroy(); + BufferSharedDelete(lights[i]); + } + + // Delete remaining shared lights structures + for (unsigned int i = numGeoLights; i < numLights; i++) + BufferSharedDelete(lights[i]); + + // Release array memory + BufferSharedDelete(lights); + BufferSharedDelete(lightsCDF); + lights = nullptr; + lightsCDF = nullptr; +} +} // namespace ispc \ No newline at end of file diff --git a/modules/cpu/render/pathtracer/PathTracerDataShared.h b/modules/cpu/render/pathtracer/PathTracerDataShared.h new file mode 100644 index 0000000000..21a8d958c8 --- /dev/null +++ b/modules/cpu/render/pathtracer/PathTracerDataShared.h @@ -0,0 +1,33 @@ +// Copyright 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef __cplusplus +#include "common/StructShared.h" +namespace ispc { +#endif // __cplusplus + +struct Light; + +struct PathtracerData +{ + // array containing the scene light sources + // the lights are sorted: first geometric, then virtual lights + Light **lights; + uint32 numLights; // total number of light sources (geometric + virtual) + uint32 numGeoLights; // number of geometric light sources + float *lightsCDF; // CDF used by NEE for randomly picking lights + +#ifdef __cplusplus + PathtracerData() + : lights(nullptr), numLights(0), numGeoLights(0), lightsCDF(nullptr) + {} + void create( + Light **lights, uint32 numLights, uint32 numGeoLights, float *lightsCDF); + void destroy(); +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/render/pathtracer/PathTracerDefines.ih b/modules/cpu/render/pathtracer/PathTracerDefines.ih index 72c41f8652..a4f76433a2 100644 --- a/modules/cpu/render/pathtracer/PathTracerDefines.ih +++ b/modules/cpu/render/pathtracer/PathTracerDefines.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/pathtracer/PathTracer.ih b/modules/cpu/render/pathtracer/PathTracerShared.h similarity index 53% rename from modules/cpu/render/pathtracer/PathTracer.ih rename to modules/cpu/render/pathtracer/PathTracerShared.h index 1fb61f622c..3273de1dc6 100644 --- a/modules/cpu/render/pathtracer/PathTracer.ih +++ b/modules/cpu/render/pathtracer/PathTracerShared.h @@ -1,15 +1,13 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once -#include "fb/FrameBuffer.ih" -#include "lights/Light.ih" -#include "render/Renderer.ih" -#include "render/util.ih" -#include "rkcommon/math/vec.ih" +#include "render/RendererShared.h" -#define MAX_LIGHTS 1000u +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus struct PathTracer { @@ -23,4 +21,18 @@ struct PathTracer bool shadowCatcher; // preprocessed bool backgroundRefraction; int32 numLightSamples; // number of light samples used for NEE + +#ifdef __cplusplus + PathTracer() + : rouletteDepth(5), + maxRadiance(inf), + shadowCatcherPlane(0.f), + shadowCatcher(false), + backgroundRefraction(false), + numLightSamples(1) + {} +}; +} // namespace ispc +#else }; +#endif // __cplusplus diff --git a/modules/cpu/render/pathtracer/PathTracerUtil.ih b/modules/cpu/render/pathtracer/PathTracerUtil.ih index 11bfc998f9..d06c08222a 100644 --- a/modules/cpu/render/pathtracer/PathTracerUtil.ih +++ b/modules/cpu/render/pathtracer/PathTracerUtil.ih @@ -1,11 +1,10 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#include "render/Renderer.ih" #include "render/pathtracer/PathStructs.ih" - -#include "render/bsdfs/BSDF.ih" #include "render/pathtracer/volumes/VolumeSampler.ih" inline bool isSmooth(const PathVertex &pathVertex) diff --git a/modules/cpu/render/pathtracer/Scattering.ih b/modules/cpu/render/pathtracer/Scattering.ih index 471cfc5ef1..dcdeb043e4 100644 --- a/modules/cpu/render/pathtracer/Scattering.ih +++ b/modules/cpu/render/pathtracer/Scattering.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/pathtracer/ShadowCatcher.ih b/modules/cpu/render/pathtracer/ShadowCatcher.ih index 32fff5138a..ad44d758c6 100644 --- a/modules/cpu/render/pathtracer/ShadowCatcher.ih +++ b/modules/cpu/render/pathtracer/ShadowCatcher.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/pathtracer/ShadowCatcher.ispc b/modules/cpu/render/pathtracer/ShadowCatcher.ispc index d244a2b5db..31f2fcbf0c 100644 --- a/modules/cpu/render/pathtracer/ShadowCatcher.ispc +++ b/modules/cpu/render/pathtracer/ShadowCatcher.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/pathtracer/PathStructs.ih" @@ -10,6 +10,8 @@ #include "common/Ray.ih" #include "common/World.ih" +// c++ shared +#include "lights/LightShared.h" bool shadowCatcher(const PathContext &pathContext, PathState &pathState, @@ -43,7 +45,8 @@ bool shadowCatcher(const PathContext &pathContext, vec3f unshaded = make_vec3f(0.f); // illumination without occluders vec3f shaded = make_vec3f(0.f); // illumination including shadows for (uniform int i = 0; i < pathContext.numLights; i++) { - const Light *uniform light = pathContext.world->pathtracerData.lights[i]; + const World *uniform world = pathContext.world; + const Light *uniform light = world->pathtracerData.lights[i]; const vec2f s = LDSampler_getFloat2( pathContext.ldSampler, pathState.sampleDim + 4 + i * 2); Light_SampleRes ls = diff --git a/modules/cpu/render/pathtracer/TransparentShadow.ih b/modules/cpu/render/pathtracer/TransparentShadow.ih index 71763831ae..33d5a60725 100644 --- a/modules/cpu/render/pathtracer/TransparentShadow.ih +++ b/modules/cpu/render/pathtracer/TransparentShadow.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/pathtracer/TransparentShadow.ispc b/modules/cpu/render/pathtracer/TransparentShadow.ispc index 9c4368bdcb..8c39224837 100644 --- a/modules/cpu/render/pathtracer/TransparentShadow.ispc +++ b/modules/cpu/render/pathtracer/TransparentShadow.ispc @@ -1,7 +1,6 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "render/pathtracer/PathTracer.ih" #include "render/pathtracer/TransparentShadow.ih" #include "render/Material.ih" @@ -10,6 +9,9 @@ #include "common/Ray.ih" #include "common/World.ih" +// c++ shared +#include "PathTracerShared.h" + vec3f transparentShadow(const uniform PathTracer *uniform self, const World *uniform world, vec3f lightContrib, @@ -58,10 +60,6 @@ vec3f transparentShadow(const uniform PathTracer *uniform self, if (m != NULL) m->selectNextMedium(m, dg, medium); - shadowRay.t0 = shadowRay.t + dg.epsilon; - shadowRay.t = tOriginal; - shadowRay.primID = -1; - shadowRay.geomID = -1; - shadowRay.instID = -1; + setRay(shadowRay, shadowRay.t + dg.epsilon, tOriginal); } } diff --git a/modules/cpu/render/pathtracer/VirtualLight.ih b/modules/cpu/render/pathtracer/VirtualLight.ih index 767c4895f6..14301b06d6 100644 --- a/modules/cpu/render/pathtracer/VirtualLight.ih +++ b/modules/cpu/render/pathtracer/VirtualLight.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/pathtracer/VirtualLight.ispc b/modules/cpu/render/pathtracer/VirtualLight.ispc index 0389084de1..34969cd4a1 100644 --- a/modules/cpu/render/pathtracer/VirtualLight.ispc +++ b/modules/cpu/render/pathtracer/VirtualLight.ispc @@ -1,10 +1,13 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 +#include "common/World.ih" #include "render/pathtracer/PathStructs.ih" #include "render/pathtracer/PathTracerUtil.ih" #include "render/pathtracer/VirtualLight.ih" #include "render/pathtracer/volumes/VolumeSampler.ih" +// c++ shared +#include "lights/LightShared.h" inline box1f getMinMaxDistForVirtualLights(const PathContext &pathContext, const PathState &pathState, @@ -38,18 +41,19 @@ vec3f evaluateVirtualLights(const PathContext &pathContext, // add light from *virtual* lights by intersecting them vec3f L = make_vec3f(0.f); - if (pathContext.numLights <= pathContext.world->pathtracerData.numGeoLights) + const World *uniform w = pathContext.world; + if (pathContext.numLights <= w->pathtracerData.numGeoLights) return L; // return if no virtual lights at all box1f intervalLightDist = getMinMaxDistForVirtualLights( pathContext, pathState, lastVertex, pathVertex, ray); - const uniform float selectionPDF = rcp((uniform float)pathContext.numLights - - pathContext.world->pathtracerData.numGeoLights); - for (uniform int i = pathContext.world->pathtracerData.numGeoLights; + const uniform float selectionPDF = rcp( + (uniform float)pathContext.numLights - w->pathtracerData.numGeoLights); + for (uniform int i = w->pathtracerData.numGeoLights; i < pathContext.numLights; i++) { - const Light *uniform light = pathContext.world->pathtracerData.lights[i]; + const Light *uniform light = w->pathtracerData.lights[i]; if (!pathState.straightPath || light->isVisible) { // to correctly handle MIS through transparencies the light pdf needs to // be calculated wrt. lastVertex.dg however, we only have a valid diff --git a/modules/cpu/render/pathtracer/volumes/HenyeyGreenstein.ih b/modules/cpu/render/pathtracer/volumes/HenyeyGreenstein.ih index 6c0871f207..c7374219ce 100644 --- a/modules/cpu/render/pathtracer/volumes/HenyeyGreenstein.ih +++ b/modules/cpu/render/pathtracer/volumes/HenyeyGreenstein.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/pathtracer/volumes/VolumeSampler.ih b/modules/cpu/render/pathtracer/volumes/VolumeSampler.ih index 89c5bde8d3..99136fe01a 100644 --- a/modules/cpu/render/pathtracer/volumes/VolumeSampler.ih +++ b/modules/cpu/render/pathtracer/volumes/VolumeSampler.ih @@ -1,19 +1,17 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#include "render/pathtracer/PathStructs.ih" +#include "render/pathtracer/volumes/HenyeyGreenstein.ih" +#include "rkcommon/math/vec.ih" + struct World; struct LDSampler; struct RandomSampler; struct Ray; - -#include "render/pathtracer/volumes/HenyeyGreenstein.ih" - -#include "render/pathtracer/PathStructs.ih" - -#include "rkcommon/math/vec.ih" -#include "volume/VolumetricModel.ih" +struct RayIntervals; float volumeSampleFreePath(const PathState &pathState, const World *uniform world, @@ -35,4 +33,4 @@ float volumeTransmittance(const PathState &pathState, inline bool isSmoothVolumeVertex(const PathVertex &pathVertex) { return HenyeyGreenstein_isSmooth(pathVertex.volume->anisotropy); -} \ No newline at end of file +} diff --git a/modules/cpu/render/pathtracer/volumes/VolumeSampler.ispc b/modules/cpu/render/pathtracer/volumes/VolumeSampler.ispc index 28e49d822f..7078248a4b 100644 --- a/modules/cpu/render/pathtracer/volumes/VolumeSampler.ispc +++ b/modules/cpu/render/pathtracer/volumes/VolumeSampler.ispc @@ -1,11 +1,8 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "render/pathtracer/volumes/VolumeSampler.ih" - #include "common/World.ih" - -#include "openvkl/openvkl.isph" +#include "render/pathtracer/volumes/VolumeSampler.ih" float delta_tracking(VolumetricModel *uniform vModel, const range1f &rInterval, @@ -140,6 +137,10 @@ float volumeSampleFreePath(const PathState &pathState, *sampledInstance = inst; sampledExtinctionCoefficient = extinctionCoefficient; sampledAlbedo = albedo; + ray.t = dist; + ray.primID = 0; + ray.geomID = volumeIntervals.intervals[i].geomID; + ray.instID = volumeIntervals.intervals[i].instID; } break; } diff --git a/modules/cpu/render/registration.cpp b/modules/cpu/render/registration.cpp index e0737f9ceb..4ee3cedf1e 100644 --- a/modules/cpu/render/registration.cpp +++ b/modules/cpu/render/registration.cpp @@ -1,4 +1,4 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ao/AORenderer.h" diff --git a/modules/cpu/render/scivis/SciVis.cpp b/modules/cpu/render/scivis/SciVis.cpp index 9a770a1c65..c04a381f91 100644 --- a/modules/cpu/render/scivis/SciVis.cpp +++ b/modules/cpu/render/scivis/SciVis.cpp @@ -1,45 +1,46 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "SciVis.h" +#include "common/Instance.h" +#include "common/World.h" #include "lights/AmbientLight.h" #include "lights/HDRILight.h" #include "lights/SunSkyLight.h" // ispc exports -#include "common/World_ispc.h" #include "render/scivis/SciVis_ispc.h" namespace ospray { namespace { -void addVisibleOnlyToArray( - std::vector &lightIEs, uint32_t &visibleOnly, void *lightIE) +void addVisibleOnlyToArray(std::vector &lightShs, + uint32_t &visibleOnly, + ispc::Light *lightSh) { - if (visibleOnly == lightIEs.size()) - lightIEs.push_back(lightIE); + if (visibleOnly == lightShs.size()) + lightShs.push_back(lightSh); else { - lightIEs.push_back(lightIEs[visibleOnly]); - lightIEs[visibleOnly] = lightIE; + // insert light at the visibleOnly index + lightShs.push_back(lightShs[visibleOnly]); + lightShs[visibleOnly] = lightSh; } visibleOnly++; } -vec3f addLightsToArray(std::vector &lightIEs, +vec3f addLightsToArray(std::vector &lightShs, uint32_t &visibleOnly, Ref> &lights, - const void *instanceIE) + const ispc::Instance *instanceSh) { vec3f aoColor = vec3f(0.f); for (auto &&light : *lights) { - // create ISPC equivalent for the light - void *lightIE = light->createIE(instanceIE); - // just extract color from ambient lights const auto ambient = dynamic_cast(light); if (ambient) { - addVisibleOnlyToArray(lightIEs, visibleOnly, lightIE); + addVisibleOnlyToArray( + lightShs, visibleOnly, light->createSh(0, instanceSh)); aoColor += ambient->radiance; continue; } @@ -47,21 +48,24 @@ vec3f addLightsToArray(std::vector &lightIEs, // no illumination from HDRI lights const auto hdri = dynamic_cast(light); if (hdri) { - addVisibleOnlyToArray(lightIEs, visibleOnly, lightIE); + addVisibleOnlyToArray( + lightShs, visibleOnly, light->createSh(0, instanceSh)); continue; } // sun-sky: only sun illuminates const auto sunsky = dynamic_cast(light); if (sunsky) { - // just sky visible - addVisibleOnlyToArray(lightIEs, visibleOnly, lightIE); - lightIEs.push_back(light->createSecondIE(instanceIE)); // sun + addVisibleOnlyToArray(lightShs, + visibleOnly, + light->createSh(0, instanceSh)); // sky visible only + lightShs.push_back(light->createSh(1, instanceSh)); // sun continue; } // handle the remaining types of lights - lightIEs.push_back(lightIE); + for (uint32_t id = 0; id < light->getShCount(); id++) + lightShs.push_back(light->createSh(id, instanceSh)); } return aoColor; } @@ -70,7 +74,7 @@ vec3f addLightsToArray(std::vector &lightIEs, SciVis::SciVis() { - ispcEquivalent = ispc::SciVis_create(); + getSh()->super.renderSample = ispc::SciVis_renderSample_addr(); } std::string SciVis::toString() const @@ -82,12 +86,12 @@ void SciVis::commit() { Renderer::commit(); - ispc::SciVis_set(getIE(), - getParam("shadows", false), - getParam("visibleLights", false), - getParam("aoSamples", 0), - getParam("aoDistance", getParam("aoRadius", 1e20f)), - getParam("volumeSamplingRate", 1.f)); + getSh()->shadowsEnabled = getParam("shadows", false); + getSh()->visibleLights = getParam("visibleLights", false); + getSh()->aoSamples = getParam("aoSamples", 0); + getSh()->aoRadius = + getParam("aoDistance", getParam("aoRadius", 1e20f)); + getSh()->volumeSamplingRate = getParam("volumeSamplingRate", 1.f); } void *SciVis::beginFrame(FrameBuffer *, World *world) @@ -98,7 +102,7 @@ void *SciVis::beginFrame(FrameBuffer *, World *world) if (world->scivisDataValid) return nullptr; - std::vector lightArray; + std::vector lightArray; vec3f aoColor = vec3f(0.f); uint32_t visibleOnly = 0; @@ -116,17 +120,16 @@ void *SciVis::beginFrame(FrameBuffer *, World *world) // Add instance lights to array aoColor += addLightsToArray( - lightArray, visibleOnly, inst->group->lights, inst->getIE()); + lightArray, visibleOnly, inst->group->lights, inst->getSh()); } } - ispc::World_setSciVisData(world->getIE(), - (ispc::vec3f &)aoColor, - lightArray.empty() ? nullptr : lightArray.data(), - lightArray.size(), - visibleOnly); - + // Prepare scivis data structure + ispc::SciVisData &sd = world->getSh()->scivisData; + sd.destroy(); + sd.create(lightArray.data(), lightArray.size(), visibleOnly, aoColor); world->scivisDataValid = true; + return nullptr; } diff --git a/modules/cpu/render/scivis/SciVis.h b/modules/cpu/render/scivis/SciVis.h index ea25135dad..9c3a0e488f 100644 --- a/modules/cpu/render/scivis/SciVis.h +++ b/modules/cpu/render/scivis/SciVis.h @@ -1,12 +1,14 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray -#include "../Renderer.h" +#include "render/Renderer.h" +// ispc shared +#include "SciVisShared.h" namespace ospray { -struct SciVis : public Renderer +struct SciVis : public AddStructShared { SciVis(); std::string toString() const override; diff --git a/modules/cpu/render/scivis/SciVis.ih b/modules/cpu/render/scivis/SciVis.ih index e3e3a7b2b6..c386fe61e5 100644 --- a/modules/cpu/render/scivis/SciVis.ih +++ b/modules/cpu/render/scivis/SciVis.ih @@ -1,21 +1,14 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once -#include "common/World.ih" -#include "math/random.ih" #include "render/Renderer.ih" +// c++ shared +#include "SciVisShared.h" -struct SciVis -{ - Renderer super; - bool shadowsEnabled; - bool visibleLights; - int aoSamples; - float aoRadius; - float volumeSamplingRate; -}; +struct LDSampler; +struct DifferentialGeometry; struct SciVisRenderContext { @@ -26,8 +19,6 @@ struct SciVisRenderContext varying LDSampler *uniform ldSampler; }; -struct LDSampler; - vec3f lightAlpha(const uniform SciVis *uniform self, Ray &ray, const FrameBuffer *uniform fb, diff --git a/modules/cpu/render/scivis/SciVis.ispc b/modules/cpu/render/scivis/SciVis.ispc index 62d38d2b00..93c573a8a0 100644 --- a/modules/cpu/render/scivis/SciVis.ispc +++ b/modules/cpu/render/scivis/SciVis.ispc @@ -1,13 +1,15 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "render/Renderer.ih" -// ao renderer #include "SciVis.ih" +#include "common/World.ih" #include "math/random.ih" #include "math/sampling.ih" #include "surfaces.ih" +#include "volume/VolumetricModel.ih" #include "volumes.ih" +// c++ shared +#include "fb/FrameBufferShared.h" void SciVis_renderSample(Renderer *uniform _self, FrameBuffer *uniform fb, @@ -42,6 +44,7 @@ void SciVis_renderSample(Renderer *uniform _self, // Iterate over all translucent geometry till we are fully opaque vec3f outColor = make_vec3f(0.f); vec3f outTransmission = make_vec3f(1.f); + int minVolIndex = 0; // interval index of closest volume while (true) { // Then trace normal geometry using calculated ray intervals, // if hit ray.t will be updated @@ -59,6 +62,7 @@ void SciVis_renderSample(Renderer *uniform _self, rc.world = world; rc.sample = sample; rc.ldSampler = ldSampler; + volumeRay.geomID = RTC_INVALID_GEOMETRY_ID; vec4f volumeColor = integrateVolumeIntervalsGradient(rc, volumeIntervals, rayIntervals, @@ -70,6 +74,23 @@ void SciVis_renderSample(Renderer *uniform _self, // Blend volume outColor = outColor + outTransmission * make_vec3f(volumeColor); outTransmission = outTransmission * volumeColor.w; + + if (hadHit(volumeRay) && sample.geomID == RTC_INVALID_GEOMETRY_ID) { + sample.primID = 0; + foreach_unique (instID in volumeRay.instID) + if (instID != RTC_INVALID_GEOMETRY_ID) { + const Instance *uniform instance = *(world->instances + instID); + sample.instID = (instance->userID == RTC_INVALID_GEOMETRY_ID) + ? instID + : instance->userID; + const VolumetricModel *volms = + *(instance->group->volumetricModels + volumeRay.geomID); + foreach_unique (volm in volms) + sample.geomID = (volm->userID == RTC_INVALID_GEOMETRY_ID) + ? volumeRay.geomID + : volm->userID; + } + } } // Add contribution from visible lights, P is used by light @@ -101,9 +122,14 @@ void SciVis_renderSample(Renderer *uniform _self, // transmissive hits will lead the normal/albedo to be replaced by the // current hit if (firstHit || allHitsFullyTransmissive) { - sample.z = ray.t; + sample.z = min(ray.t, volumeRay.t); sample.albedo = surfaceShading.albedo; sample.normal = dg.Ns; + if (sample.geomID == RTC_INVALID_GEOMETRY_ID) { + sample.instID = dg.instID; + sample.geomID = dg.objID; + sample.primID = ray.primID; + } firstHit = false; } @@ -137,8 +163,8 @@ void SciVis_renderSample(Renderer *uniform _self, // If the ray hits the background and comes from a fully transmissive // path, we overwrite normals/albedo by background values if (firstHit || allHitsFullyTransmissive) { - sample.z = ray.t; - sample.albedo = make_vec3f(backgroundColor); + sample.z = min(ray.t, volumeRay.t); + sample.albedo = make_vec3f(backgroundColor); // TODO volume albedo sample.normal = make_vec3f(0.f); } @@ -152,33 +178,6 @@ void SciVis_renderSample(Renderer *uniform _self, sample.alpha = 1.f - luminance(outTransmission); } -// SciVis C++ interface ///////////////////////////////////////////////////// - -export void *uniform SciVis_create() -{ - uniform SciVis *uniform self = uniform new uniform SciVis; - Renderer_Constructor(&self->super); - self->super.renderSample = SciVis_renderSample; - return self; -} - -export void SciVis_set(void *uniform _self, - uniform bool shadowsEnabled, - uniform bool visibleLights, - uniform int aoSamples, - uniform float aoRadius, - uniform float volumeSamplingRate) -{ - uniform SciVis *uniform self = (uniform SciVis * uniform) _self; - - self->shadowsEnabled = shadowsEnabled; - self->visibleLights = visibleLights; - self->aoSamples = aoSamples; - self->aoRadius = aoRadius; - - self->volumeSamplingRate = volumeSamplingRate; -} - vec3f SciVis_computeAO(const uniform SciVis *uniform self, const FrameBuffer *uniform fb, const World *uniform world, @@ -234,3 +233,10 @@ vec3f SciVis_computeAO(const uniform SciVis *uniform self, // cancel return 1.0f - (hits / (float)sampleCnt); } + +// SciVis C++ interface ///////////////////////////////////////////////////// + +export void *uniform SciVis_renderSample_addr() +{ + return SciVis_renderSample; +} diff --git a/modules/cpu/render/scivis/SciVisData.cpp b/modules/cpu/render/scivis/SciVisData.cpp new file mode 100644 index 0000000000..4fcee84a78 --- /dev/null +++ b/modules/cpu/render/scivis/SciVisData.cpp @@ -0,0 +1,38 @@ +// Copyright 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "rkcommon/math/rkmath.h" +#include "rkcommon/math/vec.h" +// ispc shared +#include "SciVisDataShared.h" +#include "lights/LightShared.h" + +using namespace ospray; + +namespace ispc { + +void SciVisData::create(Light **lightsPtr, + uint32 numLights, + uint32 numLightsVisibleOnly, + const vec3f &aoColor) +{ + this->numLights = numLights; + this->numLightsVisibleOnly = numLightsVisibleOnly; + aoColorPi = aoColor * float(pi); + if (numLights) { + // Allocate shared buffer and copy light pointers there + lights = BufferSharedCreate(numLights, lightsPtr); + } +} + +void SciVisData::destroy() +{ + // Delete all lights structures + for (unsigned int i = 0; i < numLights; i++) + BufferSharedDelete(lights[i]); + + // Release shared arrays + BufferSharedDelete(lights); + lights = nullptr; +} +} // namespace ispc diff --git a/modules/cpu/render/scivis/SciVisDataShared.h b/modules/cpu/render/scivis/SciVisDataShared.h new file mode 100644 index 0000000000..da39629fde --- /dev/null +++ b/modules/cpu/render/scivis/SciVisDataShared.h @@ -0,0 +1,37 @@ +// Copyright 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef __cplusplus +#include "common/StructShared.h" +namespace ispc { +#endif // __cplusplus + +struct Light; + +struct SciVisData +{ + // array containing the scene light sources + // the lights are sorted: first lights that are not sampled (visible only), + // then lights that are both sampled and visible + Light **lights; + uint32 numLights; // total number of light sources + uint32 numLightsVisibleOnly; // number of lights that are not sampled + // (visible only) + vec3f aoColorPi; + +#ifdef __cplusplus + SciVisData() + : lights(nullptr), numLights(0), numLightsVisibleOnly(0), aoColorPi(0.f) + {} + void create(Light **lightsPtr, + uint32 numLights, + uint32 numLightsVisibleOnly, + const vec3f &aoColor); + void destroy(); +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/render/scivis/SciVisShared.h b/modules/cpu/render/scivis/SciVisShared.h new file mode 100644 index 0000000000..0983c3c091 --- /dev/null +++ b/modules/cpu/render/scivis/SciVisShared.h @@ -0,0 +1,33 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "render/RendererShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +struct SciVis +{ + Renderer super; + bool shadowsEnabled; + bool visibleLights; + int aoSamples; + float aoRadius; + float volumeSamplingRate; + +#ifdef __cplusplus + SciVis() + : shadowsEnabled(false), + visibleLights(false), + aoSamples(0), + aoRadius(1e20f), + volumeSamplingRate(1.f) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/cpu/render/scivis/lightAlpha.ispc b/modules/cpu/render/scivis/lightAlpha.ispc index 44ace66fed..026821885d 100644 --- a/modules/cpu/render/scivis/lightAlpha.ispc +++ b/modules/cpu/render/scivis/lightAlpha.ispc @@ -1,7 +1,6 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "lights/Light.ih" #include "math/random.ih" #include "math/sampling.ih" #include "render/util.ih" diff --git a/modules/cpu/render/scivis/surfaces.ih b/modules/cpu/render/scivis/surfaces.ih index 5ea5ba46f1..6f97532aff 100644 --- a/modules/cpu/render/scivis/surfaces.ih +++ b/modules/cpu/render/scivis/surfaces.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/scivis/surfaces.ispc b/modules/cpu/render/scivis/surfaces.ispc index 15661c3b24..025b8d11b6 100644 --- a/modules/cpu/render/scivis/surfaces.ispc +++ b/modules/cpu/render/scivis/surfaces.ispc @@ -1,12 +1,12 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "math/random.ih" #include "math/sampling.ih" #include "render/util.ih" -// SciVis renderer -#include "lights/Light.ih" #include "surfaces.ih" +// c++ shared +#include "lights/LightShared.h" vec3f directIllumination(const uniform SciVis *uniform self, const FrameBuffer *uniform fb, diff --git a/modules/cpu/render/scivis/volumes.ih b/modules/cpu/render/scivis/volumes.ih index ad2d9cc67d..8b128d4b92 100644 --- a/modules/cpu/render/scivis/volumes.ih +++ b/modules/cpu/render/scivis/volumes.ih @@ -1,17 +1,13 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once -#include "SciVis.ih" #include "common/Clipping.ih" #include "common/Ray.ih" #include "common/VolumeIntervals.ih" -#include "math/random.ih" -#include "volume/VolumetricModel.ih" struct LDSampler; -struct RandomSampler; vec4f integrateVolumeIntervalsGradient(SciVisRenderContext &rc, const VolumeIntervals &intervals, diff --git a/modules/cpu/render/scivis/volumes.ispc b/modules/cpu/render/scivis/volumes.ispc index 9b56f5215a..f7eeeaf3a8 100644 --- a/modules/cpu/render/scivis/volumes.ispc +++ b/modules/cpu/render/scivis/volumes.ispc @@ -1,14 +1,12 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "surfaces.ih" -#include "volumes.ih" -// ispc device #include "math/random.ih" #include "math/sampling.ih" #include "render/util.ih" - -#include "openvkl/openvkl.isph" +#include "surfaces.ih" +#include "volume/VolumetricModel.ih" +#include "volumes.ih" struct VolumeContext { @@ -86,7 +84,8 @@ static void sampleVolume(SciVisRenderContext &rc, } // Apply transfer function to get color with alpha - vc.sample = m->transferFunction->get(m->transferFunction, sampleVal); + TransferFunction *uniform tf = m->transferFunction; + vc.sample = tf->get(tf, sampleVal); // compute gradient shading lighting if (gsc > 0.0f) { @@ -104,7 +103,8 @@ static void sampleVolume(SciVisRenderContext &rc, dg.material = NULL; dg.epsilon = dt / 2.f; // transform to world coords - dg.Ns = dg.Ng = normalize(xfmVector(transposed(vi.instance->rcp_xfm.l), ns)); + dg.Ns = dg.Ng = + normalize(xfmVector(transposed(vi.instance->rcp_xfm.l), ns)); dg.P = ray.org + vc.distance * ray.dir; SSI shading = computeShading( rc.renderer, rc.fb, rc.world, dg, rc.sample, rc.ldSampler, ray.dir); @@ -149,6 +149,12 @@ static float sampleAllVolumes(SciVisRenderContext &rc, minDist = vc.distance; sampledColor = vc.sample; usedSampleId = i; + if (minDist < ray.t + && sampledColor.w < 1.0f - rc.renderer->super.minContribution) { + ray.t = minDist; + ray.geomID = volumeIntervals.intervals[i].geomID; + ray.instID = volumeIntervals.intervals[i].instID; + } } } diff --git a/modules/cpu/render/shaders/Flakes.ih b/modules/cpu/render/shaders/Flakes.ih index b856635389..7575dc2a63 100644 --- a/modules/cpu/render/shaders/Flakes.ih +++ b/modules/cpu/render/shaders/Flakes.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/shaders/Noise.ih b/modules/cpu/render/shaders/Noise.ih index 3f1ab12e31..58d1b93d43 100644 --- a/modules/cpu/render/shaders/Noise.ih +++ b/modules/cpu/render/shaders/Noise.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/render/util.h b/modules/cpu/render/util.h index c9ee6f8adc..67ae715bb9 100644 --- a/modules/cpu/render/util.h +++ b/modules/cpu/render/util.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -10,16 +10,37 @@ namespace ospray { -//! generates a "random" color from an int. -inline vec3f makeRandomColor(const int i) +// TODO: Could use pdep/pext +inline uint32_t partitionZOrder(uint32_t n) { - const int mx = 13 * 17 * 43; - const int my = 11 * 29; - const int mz = 7 * 23 * 63; - const uint32 g = (i * (3 * 5 * 127) + 12312314); - return vec3f((g % mx) * (1.f / (mx - 1)), - (g % my) * (1.f / (my - 1)), - (g % mz) * (1.f / (mz - 1))); + n &= 0x0000FFFF; + n = (n | (n << 8)) & 0x00FF00FF; + n = (n | (n << 4)) & 0x0F0F0F0F; + n = (n | (n << 2)) & 0x33333333; + n = (n | (n << 1)) & 0x55555555; + return n; +} + +inline uint32_t unpartitionZOrder(uint32_t n) +{ + n &= 0x55555555; + n = (n ^ (n >> 1)) & 0x33333333; + n = (n ^ (n >> 2)) & 0x0F0F0F0F; + n = (n ^ (n >> 4)) & 0x00FF00FF; + n = (n ^ (n >> 8)) & 0x0000FFFF; + return n; +} + +inline uint32_t interleaveZOrder(uint32_t x, uint32_t y) +{ + return partitionZOrder(x) | (partitionZOrder(y) << 1); +} + +inline void deinterleaveZOrder(uint32_t z, uint32_t &x, uint32_t &y) +{ + x = y = 0; + x = unpartitionZOrder(z); + y = unpartitionZOrder(z >> 1); } } // namespace ospray diff --git a/modules/cpu/render/util.ih b/modules/cpu/render/util.ih index 2dd94992dc..60eec91990 100644 --- a/modules/cpu/render/util.ih +++ b/modules/cpu/render/util.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -6,31 +6,20 @@ #include "common/World.ih" #include "rkcommon/math/vec.ih" -inline vec3f make_random_color(const int i) -{ - const int mx = 13 * 17 * 43; - const int my = 11 * 29; - const int mz = 7 * 23 * 63; - const uint32 g = (i * (3 * 5 * 127) + 12312314); - return make_vec3f((g % mx) * (1.f / (mx - 1)), - (g % my) * (1.f / (my - 1)), - (g % mz) * (1.f / (mz - 1))); -} - float computeAO(const World *uniform, const varying DifferentialGeometry &, const uniform int sampleCnt, const uniform float aoRadius, const varying vec3i &sampleID); -/*! struct that stores a precomputed z-order for tiles of TILE_SIZE x TILE_SIZE - * pixels */ +// struct that stores a precomputed z-order for tiles of TILE_SIZE x TILE_SIZE +// pixels struct z_order_t { - /*! 32-bit field specifying both x and y coordinate of the z-order, - with upper 16 bits for the y coordinate, and lower 16 for the x - coordinate. Compared to using two uint32-arrays, this saves on - gather-loop */ + // 32-bit field specifying both x and y coordinate of the z-order, + // with upper 16 bits for the y coordinate, and lower 16 for the x + // coordinate. Compared to using two uint32-arrays, this saves on + // gather-loop uniform uint32 xyIdx[TILE_SIZE * TILE_SIZE]; uniform uint32 xs[TILE_SIZE * TILE_SIZE]; uniform uint32 ys[TILE_SIZE * TILE_SIZE]; @@ -85,14 +74,4 @@ inline void deinterleaveZOrder( *y = unpartitionZOrder(z >> 1); } -/*! precompute a per-pixel z-order to be used within a tile */ -extern void precomputedZOrder_create(); - -/*! precompute a per-pixel z-order to be used within a tile */ -inline void precomputeZOrder() -{ - if (!z_order_initialized) - precomputedZOrder_create(); -} - extern const z_order_t *uniform get_zorder(); diff --git a/modules/cpu/render/util.ispc b/modules/cpu/render/util.ispc index 4eb2b43f3e..29482e8ec2 100644 --- a/modules/cpu/render/util.ispc +++ b/modules/cpu/render/util.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/World.ih" @@ -9,14 +9,16 @@ uniform z_order_t z_order; uniform bool z_order_initialized = false; -void precomputedZOrder_create() +// precompute a per-pixel z-order to be used within a tile +export void precomputeZOrder() { - for (uniform uint32 i = 0; i < TILE_SIZE * TILE_SIZE; i++) { - deinterleaveZOrder(i, &z_order.xs[i], &z_order.ys[i]); - z_order.xyIdx[i] = z_order.xs[i] | (z_order.ys[i] << 16); + if (!z_order_initialized) { + for (uniform uint32 i = 0; i < TILE_SIZE * TILE_SIZE; i++) { + deinterleaveZOrder(i, &z_order.xs[i], &z_order.ys[i]); + z_order.xyIdx[i] = z_order.xs[i] | (z_order.ys[i] << 16); + } + z_order_initialized = true; } - - z_order_initialized = true; } float computeAO(const World *uniform world, diff --git a/modules/cpu/texture/Texture.cpp b/modules/cpu/texture/Texture.cpp index 013ea22f82..4bf035b127 100644 --- a/modules/cpu/texture/Texture.cpp +++ b/modules/cpu/texture/Texture.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Texture.h" diff --git a/modules/cpu/texture/Texture.h b/modules/cpu/texture/Texture.h index 16614f94a8..08337e0eb0 100644 --- a/modules/cpu/texture/Texture.h +++ b/modules/cpu/texture/Texture.h @@ -1,12 +1,11 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/Managed.h" -#include "common/StructShared.h" #include "common/Util.h" - +// ispc shared #include "TextureShared.h" namespace ospray { diff --git a/modules/cpu/texture/Texture.ih b/modules/cpu/texture/Texture.ih index 6ea2e9c1d7..fffca2caeb 100644 --- a/modules/cpu/texture/Texture.ih +++ b/modules/cpu/texture/Texture.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/texture/Texture2D.cpp b/modules/cpu/texture/Texture2D.cpp index 29e0b1eb3a..cfb5e3dff0 100644 --- a/modules/cpu/texture/Texture2D.cpp +++ b/modules/cpu/texture/Texture2D.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Texture2D.h" @@ -9,7 +9,7 @@ namespace ispc { -void Texture2D::Set(const vec2i &aSize, +void Texture2D::set(const vec2i &aSize, void *aData, OSPTextureFormat type, OSPTextureFilter flags) @@ -77,7 +77,8 @@ void Texture2D::commit() + "' does not match type of 'data'='" + stringFor(texData->type) + "'!"); - getSh()->Set(size, texData->data(), format, filter); + // Initialize ispc shared structure + getSh()->set(size, texData->data(), format, filter); } } // namespace ospray diff --git a/modules/cpu/texture/Texture2D.h b/modules/cpu/texture/Texture2D.h index de3dec7293..6aa9f48fe4 100644 --- a/modules/cpu/texture/Texture2D.h +++ b/modules/cpu/texture/Texture2D.h @@ -1,12 +1,11 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Texture.h" #include "common/Data.h" -#include "common/StructShared.h" - +// ispc shared #include "Texture2DShared.h" namespace ospray { diff --git a/modules/cpu/texture/Texture2D.ih b/modules/cpu/texture/Texture2D.ih index 23f2b9bb57..a4a1bb9f1a 100644 --- a/modules/cpu/texture/Texture2D.ih +++ b/modules/cpu/texture/Texture2D.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/texture/Texture2D.ispc b/modules/cpu/texture/Texture2D.ispc index b8184d937f..1b583c751f 100644 --- a/modules/cpu/texture/Texture2D.ispc +++ b/modules/cpu/texture/Texture2D.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Texture2D.ih" diff --git a/modules/cpu/texture/Texture2DShared.h b/modules/cpu/texture/Texture2DShared.h index 9f4633cdb8..490582af64 100644 --- a/modules/cpu/texture/Texture2DShared.h +++ b/modules/cpu/texture/Texture2DShared.h @@ -6,7 +6,6 @@ #include "TextureShared.h" #ifdef __cplusplus -using namespace rkcommon::math; namespace ispc { #endif // __cplusplus @@ -22,7 +21,7 @@ struct Texture2D #ifdef __cplusplus Texture2D() : size(0), sizef(0.f), halfTexel(0.f), data(nullptr) {} - void Set(const vec2i &aSize, + void set(const vec2i &aSize, void *aData, OSPTextureFormat type, OSPTextureFilter flags); diff --git a/modules/cpu/texture/TextureParam.ih b/modules/cpu/texture/TextureParam.ih index cd5aacf585..de3b02a5fd 100644 --- a/modules/cpu/texture/TextureParam.ih +++ b/modules/cpu/texture/TextureParam.ih @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/cpu/texture/TextureParamShared.h b/modules/cpu/texture/TextureParamShared.h index 4083d278dc..61669647df 100644 --- a/modules/cpu/texture/TextureParamShared.h +++ b/modules/cpu/texture/TextureParamShared.h @@ -6,7 +6,6 @@ #include "TextureShared.h" #ifdef __cplusplus -using namespace rkcommon::math; namespace ispc { #endif // __cplusplus diff --git a/modules/cpu/texture/TextureShared.h b/modules/cpu/texture/TextureShared.h index 1e1a2e995b..5d76770fa9 100644 --- a/modules/cpu/texture/TextureShared.h +++ b/modules/cpu/texture/TextureShared.h @@ -4,6 +4,7 @@ #pragma once #ifdef __cplusplus +#include "common/StructShared.h" namespace ispc { typedef void *Texture_get; typedef void *Texture_getN; diff --git a/modules/cpu/texture/TextureVolume.cpp b/modules/cpu/texture/TextureVolume.cpp index 50fb72ae3d..04f1461485 100644 --- a/modules/cpu/texture/TextureVolume.cpp +++ b/modules/cpu/texture/TextureVolume.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "TextureVolume.h" diff --git a/modules/cpu/texture/TextureVolume.h b/modules/cpu/texture/TextureVolume.h index b28601a1ab..a95131ed7c 100644 --- a/modules/cpu/texture/TextureVolume.h +++ b/modules/cpu/texture/TextureVolume.h @@ -1,14 +1,13 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Texture.h" -#include "common/StructShared.h" #include "volume/Volume.h" #include "volume/VolumetricModel.h" #include "volume/transferFunction/TransferFunction.h" - +// ispc shared #include "TextureVolumeShared.h" namespace ospray { diff --git a/modules/cpu/texture/TextureVolume.ispc b/modules/cpu/texture/TextureVolume.ispc index 21c13fa0a3..4afda1daf9 100644 --- a/modules/cpu/texture/TextureVolume.ispc +++ b/modules/cpu/texture/TextureVolume.ispc @@ -1,10 +1,10 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Texture.ih" #include "volume/Volume.ih" -#include "volume/transferFunction/TransferFunction.ih" - +#include "volume/transferFunction/TransferFunctionShared.h" +// c++ shared #include "TextureVolumeShared.h" vec4f TextureVolume_get( diff --git a/modules/cpu/volume/Volume.cpp b/modules/cpu/volume/Volume.cpp index 31cbbd59fa..9257df836a 100644 --- a/modules/cpu/volume/Volume.cpp +++ b/modules/cpu/volume/Volume.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray @@ -191,6 +191,12 @@ void Volume::handleParams() vklSetVec3i(vklVolume, "dimensions", dim.x, dim.y, dim.z); vklSetInt(vklVolume, "voxelType", (VKLDataType)data->type); } + if (name == "nodesPackedDense" || name == "nodesPackedTile") { + // packed VDB volumes: wrap attribute + VKLData vklDataWrapper = vklNewData(vklDevice, 1, VKL_DATA, &vklData); + vklRelease(vklData); + vklData = vklDataWrapper; + } vklSetData(vklVolume, name.c_str(), vklData); vklRelease(vklData); } @@ -206,11 +212,6 @@ void Volume::setDevice(RTCDevice embreed, VKLDevice vkld) vklDevice = vkld; } -void Volume::setGeomID(int geomID) -{ - getSh()->volumeID = geomID; -} - OSPTYPEFOR_DEFINITION(Volume *); } // namespace ospray diff --git a/modules/cpu/volume/Volume.h b/modules/cpu/volume/Volume.h index 0a5180889c..5c5cab9dd7 100644 --- a/modules/cpu/volume/Volume.h +++ b/modules/cpu/volume/Volume.h @@ -1,16 +1,16 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ISPCDevice.h" #include "common/Managed.h" -#include "common/StructShared.h" // embree #include "embree3/rtcore.h" - +// openvkl #include "openvkl/volume.h" -#include "volume/VolumeShared.h" +// ispc shared +#include "VolumeShared.h" namespace ospray { @@ -23,7 +23,6 @@ struct OSPRAY_SDK_INTERFACE Volume std::string toString() const override; void commit() override; void setDevice(RTCDevice embreeDevice, VKLDevice vklDevice); - void setGeomID(int geomID); private: void checkDataStride(const Data *) const; diff --git a/modules/cpu/volume/Volume.ih b/modules/cpu/volume/Volume.ih index a286157b17..23b295a68d 100644 --- a/modules/cpu/volume/Volume.ih +++ b/modules/cpu/volume/Volume.ih @@ -1,11 +1,11 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "openvkl/openvkl.isph" #include "rkcommon/math/box.ih" - +// c++ shared #include "VolumeShared.h" // Helper functions /////////////////////////////////////////////////////////// diff --git a/modules/cpu/volume/Volume.ispc b/modules/cpu/volume/Volume.ispc index d7dce9ae3c..879d71b14b 100644 --- a/modules/cpu/volume/Volume.ispc +++ b/modules/cpu/volume/Volume.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/Intersect.ih" @@ -23,8 +23,6 @@ export void Volume_intersect_kernel( Volume *uniform self = (Volume * uniform) args->geometryUserPtr; varying Ray *uniform ray = (varying Ray * uniform) args->rayhit; - uniform int primID = args->primID; - box3f *uniform box = &self->boundingBox; const Intersections isect = intersectBox(ray->org, ray->dir, *box); @@ -34,7 +32,7 @@ export void Volume_intersect_kernel( if (t_min < t_max) { ray->instID = args->context->instID[0]; - ray->geomID = self->volumeID; + ray->geomID = args->geomID; ray->primID = 0; EmbreeIntersectionContext *uniform ctx = @@ -55,7 +53,7 @@ export void Volume_intersect_kernel( * varying)(vIntervals->intervals + vIntervals->numVolumeIntervals); vInterval->primID = 0; - vInterval->geomID = self->volumeID; + vInterval->geomID = args->geomID; vInterval->instID = args->context->instID[0]; vInterval->interval.lower = t_min; vInterval->interval.upper = t_max; diff --git a/modules/cpu/volume/VolumeShared.h b/modules/cpu/volume/VolumeShared.h index 5f49e9be31..c984cc75e1 100644 --- a/modules/cpu/volume/VolumeShared.h +++ b/modules/cpu/volume/VolumeShared.h @@ -4,7 +4,7 @@ #pragma once #ifdef __cplusplus -using namespace rkcommon::math; +#include "common/StructShared.h" namespace ispc { #endif // __cplusplus @@ -14,8 +14,6 @@ namespace ispc { // representing a "derived" class to allow casting to that class). struct Volume { - int volumeID; - VKLVolume vklVolume; VKLSampler vklSampler; @@ -23,8 +21,11 @@ struct Volume // This is an internal derived parameter and not meant to be // redefined externally. box3f boundingBox; -}; #ifdef __cplusplus + Volume() : vklVolume(nullptr), vklSampler(nullptr), boundingBox(0.f, 0.f) {} +}; } // namespace ispc +#else +}; #endif // __cplusplus diff --git a/modules/cpu/volume/VolumetricModel.cpp b/modules/cpu/volume/VolumetricModel.cpp index 3ce885008c..9eab690f10 100644 --- a/modules/cpu/volume/VolumetricModel.cpp +++ b/modules/cpu/volume/VolumetricModel.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray @@ -72,6 +72,7 @@ void VolumetricModel::commit() getSh()->densityScale = getParam("densityScale", 1.f); getSh()->anisotropy = getParam("anisotropy", 0.f); getSh()->gradientShadingScale = getParam("gradientShadingScale", 0.f); + getSh()->userID = getParam("id", RTC_INVALID_GEOMETRY_ID); } RTCGeometry VolumetricModel::embreeGeometryHandle() const diff --git a/modules/cpu/volume/VolumetricModel.h b/modules/cpu/volume/VolumetricModel.h index 50d01ac7c2..9fa3487367 100644 --- a/modules/cpu/volume/VolumetricModel.h +++ b/modules/cpu/volume/VolumetricModel.h @@ -1,12 +1,11 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Volume.h" -#include "common/StructShared.h" #include "openvkl/openvkl.h" - +// ispc shared #include "volume/VolumetricModelShared.h" namespace ospray { @@ -26,11 +25,6 @@ struct OSPRAY_SDK_INTERFACE VolumetricModel Ref getVolume() const; - void setGeomID(int geomID) - { - volume->setGeomID(geomID); - } - private: box3f volumeBounds; Ref volume; diff --git a/modules/cpu/volume/VolumetricModel.ih b/modules/cpu/volume/VolumetricModel.ih index 15f3f6f8a7..5056960c35 100644 --- a/modules/cpu/volume/VolumetricModel.ih +++ b/modules/cpu/volume/VolumetricModel.ih @@ -1,15 +1,15 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once -#include "Volume.ih" -#include "math/AffineSpace.ih" -#include "transferFunction/TransferFunction.ih" - #include "../common/DifferentialGeometry.ih" #include "../common/Ray.ih" - +#include "Volume.ih" +#include "transferFunction/TransferFunctionShared.h" +// openvkl +#include "openvkl/openvkl.isph" +// c++ shared #include "VolumetricModelShared.h" inline void VolumetricModel_postIntersect(const VolumetricModel *uniform self, @@ -17,6 +17,16 @@ inline void VolumetricModel_postIntersect(const VolumetricModel *uniform self, const varying Ray &ray, uniform int64 flags) { - dg.areaPDF = 0.f; + dg.Ng = make_vec3f(0.f); + dg.Ns = make_vec3f(0.f); + dg.dPds = make_vec3f(0.f); + dg.dPdt = make_vec3f(0.f); + dg.st = make_vec2f(0); dg.color = make_vec4f(0.f); + dg.primID = 0; + dg.objID = + (self->userID == RTC_INVALID_GEOMETRY_ID) ? ray.geomID : self->userID; + dg.areaPDF = 0.f; + dg.epsilon = 0.f; + dg.material = NULL; } diff --git a/modules/cpu/volume/VolumetricModelShared.h b/modules/cpu/volume/VolumetricModelShared.h index 52bf91ce9b..73d19a4e6c 100644 --- a/modules/cpu/volume/VolumetricModelShared.h +++ b/modules/cpu/volume/VolumetricModelShared.h @@ -4,7 +4,7 @@ #pragma once #ifdef __cplusplus -using namespace rkcommon::math; +#include "common/StructShared.h" namespace ispc { #endif // __cplusplus @@ -23,8 +23,21 @@ struct VolumetricModel float anisotropy; // the anisotropy of the volume's phase function // (Heyney-Greenstein) float gradientShadingScale; -}; + unsigned int userID; #ifdef __cplusplus + VolumetricModel() + : volume(nullptr), + transferFunction(nullptr), + vklIntervalContext(nullptr), + boundingBox(0.f, 0.f), + densityScale(1.f), + anisotropy(0.f), + gradientShadingScale(0.f), + userID(RTC_INVALID_GEOMETRY_ID) + {} +}; } // namespace ispc +#else +}; #endif // __cplusplus diff --git a/modules/cpu/volume/transferFunction/LinearTransferFunction.cpp b/modules/cpu/volume/transferFunction/LinearTransferFunction.cpp index 1837188cb3..c1636b82b0 100644 --- a/modules/cpu/volume/transferFunction/LinearTransferFunction.cpp +++ b/modules/cpu/volume/transferFunction/LinearTransferFunction.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "LinearTransferFunction.h" diff --git a/modules/cpu/volume/transferFunction/LinearTransferFunction.h b/modules/cpu/volume/transferFunction/LinearTransferFunction.h index b72f5b246e..5a1419e82e 100644 --- a/modules/cpu/volume/transferFunction/LinearTransferFunction.h +++ b/modules/cpu/volume/transferFunction/LinearTransferFunction.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -6,7 +6,7 @@ // ospray #include "TransferFunction.h" #include "common/Data.h" - +// ispc shared #include "LinearTransferFunctionShared.h" namespace ospray { diff --git a/modules/cpu/volume/transferFunction/LinearTransferFunction.ih b/modules/cpu/volume/transferFunction/LinearTransferFunction.ih deleted file mode 100644 index 0ae05345bc..0000000000 --- a/modules/cpu/volume/transferFunction/LinearTransferFunction.ih +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2009-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "TransferFunction.ih" -#include "common/Data.ih" - -#include "LinearTransferFunctionShared.h" diff --git a/modules/cpu/volume/transferFunction/LinearTransferFunction.ispc b/modules/cpu/volume/transferFunction/LinearTransferFunction.ispc index 8f5ad331b1..8d3348ae32 100644 --- a/modules/cpu/volume/transferFunction/LinearTransferFunction.ispc +++ b/modules/cpu/volume/transferFunction/LinearTransferFunction.ispc @@ -1,7 +1,9 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "LinearTransferFunction.ih" +#include "common/Data.ih" +// c++ shared +#include "LinearTransferFunctionShared.h" vec4f LinearTransferFunction_get(const void *uniform _self, float value) { diff --git a/modules/cpu/volume/transferFunction/TransferFunction.cpp b/modules/cpu/volume/transferFunction/TransferFunction.cpp index 761c54babf..8ffdf3b26c 100644 --- a/modules/cpu/volume/transferFunction/TransferFunction.cpp +++ b/modules/cpu/volume/transferFunction/TransferFunction.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray @@ -19,7 +19,7 @@ TransferFunction::TransferFunction() void TransferFunction::commit() { auto param = getParam("valueRange", vec2f(0.0f, 1.0f)); - valueRange = range1f(param.x, param.y); + valueRange = getParam("value", range1f(param.x, param.y)); getSh()->valueRange = valueRange; } diff --git a/modules/cpu/volume/transferFunction/TransferFunction.h b/modules/cpu/volume/transferFunction/TransferFunction.h index afd76613f6..0a37373756 100644 --- a/modules/cpu/volume/transferFunction/TransferFunction.h +++ b/modules/cpu/volume/transferFunction/TransferFunction.h @@ -1,12 +1,11 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/Managed.h" -#include "common/StructShared.h" #include "common/Util.h" - +// ispc shared #include "TransferFunctionShared.h" namespace ospray { diff --git a/modules/cpu/volume/transferFunction/TransferFunction.ih b/modules/cpu/volume/transferFunction/TransferFunction.ih deleted file mode 100644 index 865722fc53..0000000000 --- a/modules/cpu/volume/transferFunction/TransferFunction.ih +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2009-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "common/OSPCommon.ih" -#include "rkcommon/math/box.ih" -#include "rkcommon/math/vec.ih" - -#include "TransferFunctionShared.h" \ No newline at end of file diff --git a/modules/cpu/volume/transferFunction/TransferFunctionShared.h b/modules/cpu/volume/transferFunction/TransferFunctionShared.h index b45be2b232..4ead8b9468 100644 --- a/modules/cpu/volume/transferFunction/TransferFunctionShared.h +++ b/modules/cpu/volume/transferFunction/TransferFunctionShared.h @@ -4,7 +4,7 @@ #pragma once #ifdef __cplusplus -using namespace rkcommon::math; +#include "common/StructShared.h" namespace ispc { typedef void *TransferFunction_getFct; typedef void *TransferFunction_getMaxOpacityFct; @@ -22,8 +22,13 @@ struct TransferFunction TransferFunction_getFct get; TransferFunction_getMaxOpacityFct getMaxOpacity; -}; #ifdef __cplusplus + TransferFunction() + : valueRange(0.f, 1.f), get(nullptr), getMaxOpacity(nullptr) + {} +}; } // namespace ispc +#else +}; #endif // __cplusplus diff --git a/modules/denoiser/CMakeLists.txt b/modules/denoiser/CMakeLists.txt index 22a73ef42d..55d2eced1c 100644 --- a/modules/denoiser/CMakeLists.txt +++ b/modules/denoiser/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 cmake_dependent_option( diff --git a/modules/denoiser/DenoiseFrameOp.cpp b/modules/denoiser/DenoiseFrameOp.cpp index 483784fb64..360636c9da 100644 --- a/modules/denoiser/DenoiseFrameOp.cpp +++ b/modules/denoiser/DenoiseFrameOp.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "DenoiseFrameOp.h" diff --git a/modules/denoiser/DenoiseFrameOp.h b/modules/denoiser/DenoiseFrameOp.h index 4092e283af..69d0d26b18 100644 --- a/modules/denoiser/DenoiseFrameOp.h +++ b/modules/denoiser/DenoiseFrameOp.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/mpi/CMakeLists.txt b/modules/mpi/CMakeLists.txt index 02a2ae70f4..0c4c254ce9 100644 --- a/modules/mpi/CMakeLists.txt +++ b/modules/mpi/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 cmake_dependent_option( diff --git a/modules/mpi/common/CMakeLists.txt b/modules/mpi/common/CMakeLists.txt index 1302f72476..61eb6611c2 100644 --- a/modules/mpi/common/CMakeLists.txt +++ b/modules/mpi/common/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 add_library(ospray_mpi_common STATIC diff --git a/modules/mpi/common/Collectives.cpp b/modules/mpi/common/Collectives.cpp index 9ab873f43d..5d53a5d25b 100644 --- a/modules/mpi/common/Collectives.cpp +++ b/modules/mpi/common/Collectives.cpp @@ -1,4 +1,4 @@ -// Copyright 2016-2021 Intel Corporation +// Copyright 2016 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Collectives.h" diff --git a/modules/mpi/common/Collectives.h b/modules/mpi/common/Collectives.h index 27156a0d33..52986c185a 100644 --- a/modules/mpi/common/Collectives.h +++ b/modules/mpi/common/Collectives.h @@ -1,4 +1,4 @@ -// Copyright 2016-2022 Intel Corporation +// Copyright 2016 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/mpi/common/MPIBcastFabric.cpp b/modules/mpi/common/MPIBcastFabric.cpp index 80a2bd871e..ada5a6ecff 100644 --- a/modules/mpi/common/MPIBcastFabric.cpp +++ b/modules/mpi/common/MPIBcastFabric.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include diff --git a/modules/mpi/common/MPIBcastFabric.h b/modules/mpi/common/MPIBcastFabric.h index c21cfb2976..0d0773948a 100644 --- a/modules/mpi/common/MPIBcastFabric.h +++ b/modules/mpi/common/MPIBcastFabric.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/mpi/common/MPICommon.cpp b/modules/mpi/common/MPICommon.cpp index 9247df4c91..3a78e61beb 100644 --- a/modules/mpi/common/MPICommon.cpp +++ b/modules/mpi/common/MPICommon.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "MPICommon.h" diff --git a/modules/mpi/common/MPICommon.h b/modules/mpi/common/MPICommon.h index aeff58631b..5298ec8759 100644 --- a/modules/mpi/common/MPICommon.h +++ b/modules/mpi/common/MPICommon.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/mpi/common/ObjectHandle.cpp b/modules/mpi/common/ObjectHandle.cpp index b7a4cbc360..7aefc46b5b 100644 --- a/modules/mpi/common/ObjectHandle.cpp +++ b/modules/mpi/common/ObjectHandle.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ObjectHandle.h" diff --git a/modules/mpi/common/ObjectHandle.h b/modules/mpi/common/ObjectHandle.h index 706585d840..575ec22e60 100644 --- a/modules/mpi/common/ObjectHandle.h +++ b/modules/mpi/common/ObjectHandle.h @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/mpi/common/Profiling.cpp b/modules/mpi/common/Profiling.cpp index 23e9f97cb6..db7c9f0c48 100644 --- a/modules/mpi/common/Profiling.cpp +++ b/modules/mpi/common/Profiling.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef ENABLE_PROFILING diff --git a/modules/mpi/common/Profiling.h b/modules/mpi/common/Profiling.h index d98a46ba55..5a8da6b6f2 100644 --- a/modules/mpi/common/Profiling.h +++ b/modules/mpi/common/Profiling.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/mpi/common/maml/Context.cpp b/modules/mpi/common/maml/Context.cpp index ebf6ff1841..cf57ed99da 100644 --- a/modules/mpi/common/maml/Context.cpp +++ b/modules/mpi/common/maml/Context.cpp @@ -1,4 +1,4 @@ -// Copyright 2016-2020 Intel Corporation +// Copyright 2016 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Context.h" diff --git a/modules/mpi/common/maml/Context.h b/modules/mpi/common/maml/Context.h index 61d4290678..9a2d4b43b6 100644 --- a/modules/mpi/common/maml/Context.h +++ b/modules/mpi/common/maml/Context.h @@ -1,4 +1,4 @@ -// Copyright 2016-2021 Intel Corporation +// Copyright 2016 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/mpi/common/maml/maml.cpp b/modules/mpi/common/maml/maml.cpp index dcfb15c751..8a78d9b752 100644 --- a/modules/mpi/common/maml/maml.cpp +++ b/modules/mpi/common/maml/maml.cpp @@ -1,4 +1,4 @@ -// Copyright 2016-2020 Intel Corporation +// Copyright 2016 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "maml.h" diff --git a/modules/mpi/common/maml/maml.h b/modules/mpi/common/maml/maml.h index 5c4009980b..f28ecd2799 100644 --- a/modules/mpi/common/maml/maml.h +++ b/modules/mpi/common/maml/maml.h @@ -1,4 +1,4 @@ -// Copyright 2016-2021 Intel Corporation +// Copyright 2016 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/mpi/external/CMakeLists.txt b/modules/mpi/external/CMakeLists.txt index b06bfe0f3e..d6c3208b01 100644 --- a/modules/mpi/external/CMakeLists.txt +++ b/modules/mpi/external/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 add_subdirectory(pico_bench) diff --git a/modules/mpi/external/pico_bench/CMakeLists.txt b/modules/mpi/external/pico_bench/CMakeLists.txt index 7f42af5237..559dc7e2b4 100644 --- a/modules/mpi/external/pico_bench/CMakeLists.txt +++ b/modules/mpi/external/pico_bench/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2020 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 add_library(ospray_pico_bench INTERFACE) diff --git a/modules/mpi/ospray/CMakeLists.txt b/modules/mpi/ospray/CMakeLists.txt index fd0ec4d552..668bd1b6e1 100644 --- a/modules/mpi/ospray/CMakeLists.txt +++ b/modules/mpi/ospray/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2022 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ## Options ## @@ -29,7 +29,6 @@ ispc_target_add_sources(ospray_module_mpi MPIDistributedDevice.ispc ModuleInit.cpp common/DistributedWorld.cpp - common/DistributedWorld.ispc common/OSPWork.cpp common/Messaging.cpp @@ -85,3 +84,26 @@ install(TARGETS ospray_mpi_worker ospray_sign_target(ospray_mpi_worker) +# ------------------------------------------------------- +# Install SDK headers +# ------------------------------------------------------- + +get_subdirectories(SUBDIRS ${CMAKE_CURRENT_LIST_DIR}) + +foreach(dir ${SUBDIRS}) + install(DIRECTORY ${dir} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ospray/SDK/modules/mpi + COMPONENT devel + FILES_MATCHING + PATTERN *.h + PATTERN *.ih + ) + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${dir} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ospray/SDK/modules/mpi + COMPONENT devel + FILES_MATCHING + PATTERN *_ispc.h + ) +endforeach() + + diff --git a/modules/mpi/ospray/MPIDistributedDevice.cpp b/modules/mpi/ospray/MPIDistributedDevice.cpp index b74ef702f7..0cfe26a285 100644 --- a/modules/mpi/ospray/MPIDistributedDevice.cpp +++ b/modules/mpi/ospray/MPIDistributedDevice.cpp @@ -1,10 +1,10 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "MPIDistributedDevice.h" #include + #include "ISPCDevice.h" -#include "MPIDistributedDevice_ispc.h" +#include "MPIDistributedDevice.h" #include "camera/Camera.h" #include "common/Data.h" #include "common/DistributedWorld.h" @@ -17,6 +17,7 @@ #include "lights/Light.h" #include "openvkl/openvkl.h" #include "render/DistributedLoadBalancer.h" +#include "render/Material.h" #include "render/ThreadedRenderTask.h" #include "render/distributed/DistributedRaycast.h" #include "rkcommon/tasking/tasking_system_init.h" @@ -25,6 +26,8 @@ #include "volume/Volume.h" #include "volume/VolumetricModel.h" #include "volume/transferFunction/TransferFunction.h" +// ispc exports +#include "MPIDistributedDevice_ispc.h" namespace ospray { namespace mpi { @@ -391,8 +394,7 @@ OSPFuture MPIDistributedDevice::renderFrame(OSPFrameBuffer _fb, auto *world = lookupObject(_world); ObjectHandle handle = allocateHandle(); - std::shared_ptr loadBalancer = - std::make_shared(); + auto loadBalancer = std::make_shared(); loadBalancer->setObjectHandle(handle); fb->setCompletedEvent(OSP_NONE_FINISHED); diff --git a/modules/mpi/ospray/MPIDistributedDevice.h b/modules/mpi/ospray/MPIDistributedDevice.h index a17ea2bfda..083c55c6d1 100644 --- a/modules/mpi/ospray/MPIDistributedDevice.h +++ b/modules/mpi/ospray/MPIDistributedDevice.h @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/mpi/ospray/MPIDistributedDevice.ispc b/modules/mpi/ospray/MPIDistributedDevice.ispc index 18c16d095b..badb7fac98 100644 --- a/modules/mpi/ospray/MPIDistributedDevice.ispc +++ b/modules/mpi/ospray/MPIDistributedDevice.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 export uniform int MPIDistributedDevice_programCount() diff --git a/modules/mpi/ospray/MPIOffloadDevice.cpp b/modules/mpi/ospray/MPIOffloadDevice.cpp index 8c6cc16136..df99f234c0 100644 --- a/modules/mpi/ospray/MPIOffloadDevice.cpp +++ b/modules/mpi/ospray/MPIOffloadDevice.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifndef _WIN32 @@ -227,8 +227,8 @@ void MPIOffloadDevice::initializeDevice() initialized = true; - int _ac = 2; - const char *_av[] = {"ospray_mpi_worker", "--osp:mpi"}; + int _ac = 1; + const char *_av[] = {"ospray_mpi_worker"}; std::string mode = getParam("mpiMode", "mpi"); @@ -521,23 +521,25 @@ OSPData MPIOffloadDevice::newSharedData(const void *sharedData, { ObjectHandle handle = allocateHandle(); - ApplicationData appData; - appData.workerType = format; + Ref appData = new ApplicationData; + appData->workerType = format; if (mpicommon::isManagedObject(format)) { format = OSP_ULONG; } - appData.data = new Data(sharedData, format, numItems, byteStride); + appData->data = new Data(sharedData, format, numItems, byteStride); this->sharedData[handle.i64] = appData; sendWork( [&](networking::WriteStream &writer) { // Data on the workers is always compact, so we don't send the stride - writer << work::NEW_SHARED_DATA << handle.i64 << appData.workerType + writer << work::NEW_SHARED_DATA << handle.i64 << appData->workerType << numItems; - sendDataWork(writer, this->sharedData[handle.i64]); + sendDataWork(writer, *this->sharedData[handle.i64]); }, false); + // Release the local ref to the appData, see issue about Ref + appData->refDec(); return (OSPData)(int64)handle; } @@ -756,7 +758,7 @@ void MPIOffloadDevice::commit(OSPObject _object) [&](networking::WriteStream &writer) { writer << work::COMMIT << handle.i64; if (d != sharedData.end()) { - sendDataWork(writer, d->second); + sendDataWork(writer, *d->second); } }, false); @@ -783,13 +785,19 @@ void MPIOffloadDevice::release(OSPObject _object) // buffer we aren't actually sharing the pointer with the app anymore auto d = sharedData.find(handle.i64); if (d != sharedData.end()) { - if (d->second.releaseHazard) { - postStatusMsg(OSP_LOG_DEBUG) - << "#osp.mpi.app: ospRelease: data reference hazard exists, " - << " flushing pending sends"; - fabric->flushBcastSends(); + if (d->second->useCount() == 1) { + // Make sure there's no pending send referencing this data if we're going + // to delete it + if (d->second->releaseHazard) { + postStatusMsg(OSP_LOG_DEBUG) + << "#osp.mpi.app: ospRelease: data reference hazard exists, " + << " flushing pending sends"; + fabric->flushBcastSends(); + } + sharedData.erase(handle.i64); + } else { + d->second->refDec(); } - sharedData.erase(handle.i64); } } @@ -802,6 +810,12 @@ void MPIOffloadDevice::retain(OSPObject _obj) writer << work::RETAIN << handle.i64; }, false); + + // Increment the local shared data ref count so we match the app + auto d = sharedData.find(handle.i64); + if (d != sharedData.end()) { + d->second->refInc(); + } } /////////////////////////////////////////////////////////////////////////// @@ -854,6 +868,10 @@ const void *MPIOffloadDevice::frameBufferMap( ArrayView(reinterpret_cast(&nbytes), sizeof(nbytes)); fabric->recv(bytesView, rootWorkerRank()); + if (nbytes == 0) { + throw std::runtime_error( + "Attempt to map framebuffer channel which does not exist!"); + } auto mapping = rkcommon::make_unique>(); mapping->resize(nbytes, 0); diff --git a/modules/mpi/ospray/MPIOffloadDevice.h b/modules/mpi/ospray/MPIOffloadDevice.h index 2ce4c949da..6512ca01a3 100644 --- a/modules/mpi/ospray/MPIOffloadDevice.h +++ b/modules/mpi/ospray/MPIOffloadDevice.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -144,7 +144,7 @@ struct MPIOffloadDevice : public api::Device * local data objects see them as OSP_ULONG types, while the worker type * is the true managed object type */ - struct ApplicationData + struct ApplicationData : RefCountedObject { Data *data = nullptr; // We can't tell the local Data object that the contained type @@ -175,7 +175,7 @@ struct MPIOffloadDevice : public api::Device std::unordered_map framebufferMappings; - std::unordered_map sharedData; + std::unordered_map> sharedData; std::unordered_set futures; diff --git a/modules/mpi/ospray/MPIOffloadWorker.cpp b/modules/mpi/ospray/MPIOffloadWorker.cpp index 7daf2c4a72..7adc9c1b60 100644 --- a/modules/mpi/ospray/MPIOffloadWorker.cpp +++ b/modules/mpi/ospray/MPIOffloadWorker.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ospray/ospray.h" diff --git a/modules/mpi/ospray/ModuleInit.cpp b/modules/mpi/ospray/ModuleInit.cpp index 6f70bba447..1255f1dace 100644 --- a/modules/mpi/ospray/ModuleInit.cpp +++ b/modules/mpi/ospray/ModuleInit.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "MPIDistributedDevice.h" diff --git a/modules/mpi/ospray/common/DistributedWorld.cpp b/modules/mpi/ospray/common/DistributedWorld.cpp index 57b4b69c0b..02abb35e58 100644 --- a/modules/mpi/ospray/common/DistributedWorld.cpp +++ b/modules/mpi/ospray/common/DistributedWorld.cpp @@ -1,15 +1,13 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "DistributedWorld.h" #include #include -#include "DistributedWorld.h" #include "MPICommon.h" #include "Messaging.h" #include "ISPCDevice.h" #include "common/Data.h" -#include "common/DistributedWorld_ispc.h" namespace ospray { namespace mpi { @@ -19,7 +17,6 @@ using namespace rkcommon; DistributedWorld::DistributedWorld() : mpiGroup(mpicommon::worker.dup()) { managedObjectType = OSP_WORLD; - this->ispcEquivalent = ispc::DistributedWorld_create(); } DistributedWorld::~DistributedWorld() @@ -60,16 +57,18 @@ void DistributedWorld::commit() // either for data-parallel rendering or to switch to replicated // rendering box3f localBounds; - if (embreeSceneHandleGeometries) { + if (getSh()->super.embreeSceneHandleGeometries) { box4f b; - rtcGetSceneBounds(embreeSceneHandleGeometries, (RTCBounds *)&b); + rtcGetSceneBounds( + getSh()->super.embreeSceneHandleGeometries, (RTCBounds *)&b); localBounds.extend(box3f(vec3f(b.lower.x, b.lower.y, b.lower.z), vec3f(b.upper.x, b.upper.y, b.upper.z))); } - if (embreeSceneHandleVolumes) { + if (getSh()->super.embreeSceneHandleVolumes) { box4f b; - rtcGetSceneBounds(embreeSceneHandleVolumes, (RTCBounds *)&b); + rtcGetSceneBounds( + getSh()->super.embreeSceneHandleVolumes, (RTCBounds *)&b); localBounds.extend(box3f(vec3f(b.lower.x, b.lower.y, b.lower.z), vec3f(b.upper.x, b.upper.y, b.upper.z))); } @@ -105,7 +104,7 @@ void DistributedWorld::commit() regionGeometry->commit(); regionScene = rtcNewScene(embreeDevice); - rtcAttachGeometry(regionScene, regionGeometry->embreeGeometry); + rtcAttachGeometry(regionScene, regionGeometry->getEmbreeGeometry()); rtcSetSceneFlags(regionScene, RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION); rtcCommitScene(regionScene); @@ -113,8 +112,9 @@ void DistributedWorld::commit() allRegionsData->refDec(); } - ispc::DistributedWorld_set( - getIE(), allRegions.data(), allRegions.size(), regionScene); + getSh()->regions = allRegions.data(); + getSh()->numRegions = allRegions.size(); + getSh()->regionScene = regionScene; } void DistributedWorld::exchangeRegions() diff --git a/modules/mpi/ospray/common/DistributedWorld.h b/modules/mpi/ospray/common/DistributedWorld.h index c9a28ccb6b..1846aea46d 100644 --- a/modules/mpi/ospray/common/DistributedWorld.h +++ b/modules/mpi/ospray/common/DistributedWorld.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -11,6 +11,8 @@ #include "embree3/rtcore.h" #include "geometry/Boxes.h" #include "rkcommon/math/box.h" +// ispc shared +#include "DistributedWorldShared.h" namespace ospray { namespace mpi { @@ -22,7 +24,7 @@ namespace mpi { * some mix of volumes and geometries to be rendered, with rays clipped * against the bounds of this box. */ -struct DistributedWorld : public World +struct DistributedWorld : public AddStructShared { DistributedWorld(); ~DistributedWorld() override; @@ -60,4 +62,3 @@ struct DistributedWorld : public World }; } // namespace mpi } // namespace ospray - diff --git a/modules/mpi/ospray/common/DistributedWorld.ih b/modules/mpi/ospray/common/DistributedWorld.ih deleted file mode 100644 index 34b34fb405..0000000000 --- a/modules/mpi/ospray/common/DistributedWorld.ih +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2009-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "common/World.ih" - -struct DistributedWorld -{ - World super; - - box3f *uniform regions; - int numRegions; - RTCScene regionScene; -}; diff --git a/modules/mpi/ospray/common/DistributedWorld.ispc b/modules/mpi/ospray/common/DistributedWorld.ispc deleted file mode 100644 index 5b5fcb77d8..0000000000 --- a/modules/mpi/ospray/common/DistributedWorld.ispc +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2009-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#include "DistributedWorld.ih" -#include "common/World.ih" - -export void *uniform DistributedWorld_create() -{ - DistributedWorld *uniform world = uniform new DistributedWorld; - World_Constructor(&world->super); - return (void *uniform)world; -} - -export void DistributedWorld_set(void *uniform _world, - void *uniform _regions, - uniform int numRegions, - void *uniform _regionScene) -{ - DistributedWorld *uniform world = (DistributedWorld * uniform) _world; - world->regions = (box3f * uniform) _regions; - world->numRegions = numRegions; - world->regionScene = (RTCScene)_regionScene; -} diff --git a/modules/mpi/ospray/common/DistributedWorldShared.h b/modules/mpi/ospray/common/DistributedWorldShared.h new file mode 100644 index 0000000000..b1a0e1ed92 --- /dev/null +++ b/modules/mpi/ospray/common/DistributedWorldShared.h @@ -0,0 +1,26 @@ +// Copyright 2009 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "common/WorldShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +struct DistributedWorld +{ + World super; + + box3f *regions; + int numRegions; + RTCScene regionScene; + +#ifdef __cplusplus + DistributedWorld() : regions(nullptr), numRegions(0), regionScene(nullptr) {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/mpi/ospray/common/DynamicLoadBalancer.cpp b/modules/mpi/ospray/common/DynamicLoadBalancer.cpp index e388d0e8f8..66ee986f73 100644 --- a/modules/mpi/ospray/common/DynamicLoadBalancer.cpp +++ b/modules/mpi/ospray/common/DynamicLoadBalancer.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // This code is for DynamicLoadBalancer using the lifeline scheduling method @@ -98,7 +98,7 @@ std::vector DynamicLoadBalancer::rankToCoords( // -------------------------------------------------------------------- // This function Takes coords of a rank and returns the rank id -unsigned int DynamicLoadBalancer::coordsToRank(std::vector &coords, +int DynamicLoadBalancer::coordsToRank(std::vector &coords, unsigned int base, unsigned int power, int numRanks) @@ -109,14 +109,12 @@ unsigned int DynamicLoadBalancer::coordsToRank(std::vector &coords, return -1; } - unsigned int result = 0; + int result = 0; for (unsigned int i = 0; i < power; i++) result += coords[i] * pow(base, power - i - 1); if (numRanks <= result) - result = result - numRanks; - if (result < 0) - result = 0; + result -= numRanks; return result; } @@ -142,7 +140,7 @@ std::vector DynamicLoadBalancer::getLifelineID( // loop over coords of lifeline i for (unsigned int j = 0; j < power; j++) { if (i == j) { - if (base - 1 <= rankCoords[i]) + if (int(base - 1) <= rankCoords[i]) lifelineCoords[j] = 0; else lifelineCoords[j] = rankCoords[i] + 1; @@ -186,12 +184,9 @@ void DynamicLoadBalancer::incoming( else if (header->type == RECV_WORK) { auto *workMsg = (DynamicLBSendWorkMessage *)message->data; int numRecvWork = workMsg->numWorkItems; - const int recvBuffSize = - sizeof(DynamicLBSendWorkMessage) + numRecvWork * sizeof(Work); auto *workItems = (Work *)(message->data + sizeof(DynamicLBSendWorkMessage)); Work myWork; - int senderRank = header->senderRank; int workSize; for (int i = 0; i < numRecvWork; i++) { myWork.ntasks = workItems[i].ntasks; @@ -223,11 +218,10 @@ void DynamicLoadBalancer::requestWork() else power = int(p) + 1; - int victimID = 0; myLifelines = getMyLifeLines(workerRank(), workerSize(), base, power); - for (int i = 0; i < myLifelines.size(); i++) { - if (myLifelines[i] == workerRank()) + for (size_t i = 0; i < myLifelines.size(); i++) { + if (myLifelines[i] == (unsigned int)workerRank()) continue; else { auto msg = std::make_shared(msgSize); diff --git a/modules/mpi/ospray/common/DynamicLoadBalancer.h b/modules/mpi/ospray/common/DynamicLoadBalancer.h index c84a47231a..dc31c84319 100644 --- a/modules/mpi/ospray/common/DynamicLoadBalancer.h +++ b/modules/mpi/ospray/common/DynamicLoadBalancer.h @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -23,9 +23,9 @@ enum MSG struct Work { - int ntasks; - int offset; - int ownerRank; + int ntasks = 0; + int offset = 0; + int ownerRank = -1; }; struct DynamicLBMessage @@ -47,7 +47,7 @@ struct DynamicLBSendWorkMessage : DynamicLBMessage struct DynamicLoadBalancer : public mpi::messaging::MessageHandler { DynamicLoadBalancer(ObjectHandle myHandle, int numTasks); - virtual ~DynamicLoadBalancer() = default; + ~DynamicLoadBalancer() override = default; void setActiveTasks(int numTasks); void updateActiveTasks(int term); @@ -96,7 +96,7 @@ struct DynamicLoadBalancer : public mpi::messaging::MessageHandler */ std::vector rankToCoords( int rank, unsigned int base, unsigned int power); - unsigned int coordsToRank(std::vector &coords, + int coordsToRank(std::vector &coords, unsigned int base, unsigned int power, int numRanks); @@ -126,7 +126,7 @@ std::vector DynamicLoadBalancer::getWorkItems( if (numReqWorkItems == 0 || numReqWorkItems > workQueue.size()) { return reqWorkItems; } - for (int i = 0; i < numReqWorkItems; i++) { + for (size_t i = 0; i < numReqWorkItems; i++) { Work workItem = workQueue.back(); workQueue.pop_back(); reqWorkItems.push_back(workItem); diff --git a/modules/mpi/ospray/common/Messaging.cpp b/modules/mpi/ospray/common/Messaging.cpp index 008ed338bf..1ee0e63c67 100644 --- a/modules/mpi/ospray/common/Messaging.cpp +++ b/modules/mpi/ospray/common/Messaging.cpp @@ -1,10 +1,10 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Messaging.h" -#include "rkcommon/memory/DeletedUniquePtr.h" -// stl +#include #include +#include "rkcommon/memory/DeletedUniquePtr.h" namespace ospray { namespace mpi { @@ -31,6 +31,7 @@ struct ObjectMessageHandler : maml::MessageHandler mpicommon::Group group; private: + std::mutex objectListenersMutex; std::unordered_map objectListeners; }; @@ -39,6 +40,8 @@ struct ObjectMessageHandler : maml::MessageHandler inline void ObjectMessageHandler::registerMessageListener( int handleObjID, MessageHandler *listener) { + std::lock_guard lock(objectListenersMutex); + if (objectListeners.find(handleObjID) != objectListeners.end()) postStatusMsg() << "WARNING: overwriting an existing listener!"; @@ -47,12 +50,14 @@ inline void ObjectMessageHandler::registerMessageListener( inline void ObjectMessageHandler::removeMessageListener(int handleObjID) { + std::lock_guard lock(objectListenersMutex); objectListeners.erase(handleObjID); } inline void ObjectMessageHandler::incoming( const std::shared_ptr &message) { + std::lock_guard lock(objectListenersMutex); auto obj = objectListeners.find(message->tag); if (obj != objectListeners.end()) { obj->second->incoming(message); diff --git a/modules/mpi/ospray/common/Messaging.h b/modules/mpi/ospray/common/Messaging.h index 9974ab3098..907a337e6e 100644 --- a/modules/mpi/ospray/common/Messaging.h +++ b/modules/mpi/ospray/common/Messaging.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/mpi/ospray/common/OSPWork.cpp b/modules/mpi/ospray/common/OSPWork.cpp index 08e4997b08..6ad5fc2f0e 100644 --- a/modules/mpi/ospray/common/OSPWork.cpp +++ b/modules/mpi/ospray/common/OSPWork.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include @@ -47,6 +47,12 @@ size_t FrameBufferInfo::pixelSize(uint32_t channel) const return channels & OSP_FB_NORMAL ? sizeof(vec3f) : 0; case OSP_FB_ALBEDO: return channels & OSP_FB_ALBEDO ? sizeof(vec3f) : 0; + case OSP_FB_ID_PRIMITIVE: + return channels & OSP_FB_ID_PRIMITIVE ? sizeof(uint32) : 0; + case OSP_FB_ID_OBJECT: + return channels & OSP_FB_ID_OBJECT ? sizeof(uint32) : 0; + case OSP_FB_ID_INSTANCE: + return channels & OSP_FB_ID_INSTANCE ? sizeof(uint32) : 0; default: return 0; } @@ -61,7 +67,7 @@ Data *OSPState::getSharedDataHandle(int64_t handle) const { auto fnd = appSharedData.find(handle); if (fnd != appSharedData.end()) { - return fnd->second; + return fnd->second.ptr; } return nullptr; } @@ -211,12 +217,15 @@ Data *retrieveData(OSPState &state, auto data = state.dataTransfers.front(); state.dataTransfers.pop(); - if (outputData) { + if (!outputData) { + outputData = data; + } else { // All data on the workers is compact, with the compaction done by the // app rank before sending std::memcpy(outputData->data(), data->data(), nbytes); - } else { - outputData = data; + + // Release the temporary data transfer object + data->refDec(); } } @@ -260,6 +269,9 @@ void newSharedData(OSPState &state, ospRelease(forsubs); state.objects[handle] = (OSPData)subscopy; state.appSharedData[handle] = data; + + // Need to release the local scope's ref count, see issue about Ref + data->refDec(); } void newData( @@ -356,22 +368,30 @@ void release( // Note: we keep the handle in the state.objects list as it may be referenced // by other objects in the scene as a parameter or data. - // Check if we can release a referenced framebuffer info + // Check if we should release a framebuffer info for this object { auto fnd = state.framebuffers.find(handle); if (fnd != state.framebuffers.end()) { - OSPObject obj = state.objects[handle]; - ManagedObject *m = lookupDistributedObject(obj); - state.framebuffers.erase(fnd); + if (fnd->second->useCount() == 1) { + state.framebuffers.erase(fnd); + } else { + fnd->second->refDec(); + } } } - Data *appData = state.getSharedDataHandle(handle); - if (appData) { - appData->refDec(); - state.appSharedData.erase(handle); + // Check if we should release a shared data info for this object + { + auto fnd = state.appSharedData.find(handle); + if (fnd != state.appSharedData.end()) { + if (fnd->second->useCount() == 1) { + state.appSharedData.erase(fnd); + } else { + fnd->second->refDec(); + } + } } -} +} // namespace work void retain( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) @@ -379,6 +399,22 @@ void retain( int64_t handle = 0; cmdBuf >> handle; ospRetain(state.objects[handle]); + + // Mirror the app's ref count for framebuffer info + { + auto fnd = state.framebuffers.find(handle); + if (fnd != state.framebuffers.end()) { + fnd->second->refInc(); + } + } + + // Mirror the app's ref count for shared data transfer buffers + { + auto fnd = state.appSharedData.find(handle); + if (fnd != state.appSharedData.end()) { + fnd->second->refInc(); + } + } } void loadModule( @@ -399,8 +435,12 @@ void createFramebuffer( cmdBuf >> handle >> size >> format >> channels; state.objects[handle] = ospNewFrameBuffer(size.x, size.y, (OSPFrameBufferFormat)format, channels); - state.framebuffers[handle] = - FrameBufferInfo(size, (OSPFrameBufferFormat)format, channels); + + Ref fbInfo = + new FrameBufferInfo(size, (OSPFrameBufferFormat)format, channels); + state.framebuffers[handle] = fbInfo; + // Release the local scope ref (see open issue about Ref) + fbInfo->refDec(); } void mapFramebuffer(OSPState &state, @@ -415,8 +455,8 @@ void mapFramebuffer(OSPState &state, if (mpicommon::worker.rank == 0) { using namespace utility; - const FrameBufferInfo &fbInfo = state.framebuffers[handle]; - uint64_t nbytes = fbInfo.pixelSize(channel) * fbInfo.getNumPixels(); + const FrameBufferInfo *fbInfo = state.framebuffers[handle].ptr; + uint64_t nbytes = fbInfo->pixelSize(channel) * fbInfo->getNumPixels(); auto bytesView = std::make_shared>( reinterpret_cast(&nbytes), sizeof(nbytes)); diff --git a/modules/mpi/ospray/common/OSPWork.h b/modules/mpi/ospray/common/OSPWork.h index fb219c1f72..7f6de1cee4 100644 --- a/modules/mpi/ospray/common/OSPWork.h +++ b/modules/mpi/ospray/common/OSPWork.h @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -11,6 +11,7 @@ #include "MPICommon.h" #include "common/ObjectHandle.h" +#include "rkcommon/memory/RefCount.h" #include "rkcommon/networking/DataStreaming.h" #include "rkcommon/networking/Fabric.h" #include "rkcommon/utility/ArrayView.h" @@ -74,7 +75,7 @@ enum TAG FINALIZE }; -struct FrameBufferInfo +struct FrameBufferInfo : rkcommon::memory::RefCountedObject { vec2i size = vec2i(0, 0); OSPFrameBufferFormat format = OSP_FB_NONE; @@ -92,9 +93,9 @@ struct OSPState { std::unordered_map objects; // Data objects that are conceptually "shared" by the application - std::unordered_map appSharedData; + std::unordered_map> appSharedData; - std::unordered_map framebuffers; + std::unordered_map> framebuffers; // Large data which is transferred separately from the command buffer, // prior to sending the command buffer diff --git a/modules/mpi/ospray/fb/DistributedFrameBuffer.cpp b/modules/mpi/ospray/fb/DistributedFrameBuffer.cpp index 4e881d01cb..0127af9226 100644 --- a/modules/mpi/ospray/fb/DistributedFrameBuffer.cpp +++ b/modules/mpi/ospray/fb/DistributedFrameBuffer.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "DistributedFrameBuffer.h" @@ -29,15 +29,17 @@ using DFB = DistributedFrameBuffer; DistributedTileError::DistributedTileError( const vec2i &numTiles, mpicommon::Group group) - : TileError(numTiles), group(group) + : TaskError(numTiles), group(group) {} void DistributedTileError::sync() { - if (tiles <= 0) + if (taskErrorBuffer.empty()) { return; + } - mpicommon::bcast(tileErrorBuffer.data(), tiles, MPI_FLOAT, 0, group.comm) + mpicommon::bcast( + taskErrorBuffer.data(), taskErrorBuffer.size(), MPI_FLOAT, 0, group.comm) .wait(); } @@ -55,18 +57,13 @@ DFB::DistributedFrameBuffer(const vec2i &numPixels, : MessageHandler(myId), FrameBuffer(numPixels, colorBufferFormat, channels), mpiGroup(mpicommon::worker.dup()), - tileErrorRegion(hasVarianceBuffer ? getNumTiles() : vec2i(0), mpiGroup), + totalTiles(divRoundUp(size, vec2i(TILE_SIZE))), + numRenderTasks((totalTiles * TILE_SIZE) / getRenderTaskSize()), + tileErrorRegion(hasVarianceBuffer ? totalTiles : vec2i(0), mpiGroup), localFBonMaster(nullptr), frameIsActive(false), frameIsDone(false) { - this->ispcEquivalent = ispc::DFB_create(); - ispc::DFB_set(getIE(), numPixels.x, numPixels.y, colorBufferFormat); - - // TODO: accumID is eventually only needed on master once static - // loadbalancing is removed - tileAccumID.resize(getTotalTiles(), 0); - if (mpicommon::IamTheMaster() && colorBufferFormat != OSP_FB_NONE) { localFBonMaster = rkcommon::make_unique(numPixels, colorBufferFormat, @@ -87,7 +84,7 @@ void DFB::commit() if (imageOpData) { FrameBufferView fbv(localFBonMaster ? localFBonMaster.get() : static_cast(this), - colorBufferFormat, + getSh()->colorBufferFormat, localFBonMaster ? localFBonMaster->colorBuffer.data() : nullptr, localFBonMaster ? localFBonMaster->depthBuffer.data() : nullptr, localFBonMaster ? localFBonMaster->normalBuffer.data() : nullptr, @@ -98,7 +95,7 @@ void DFB::commit() imageOps.push_back(i->attach(fbv)); }); } - findFirstFrameOperation(); + prepareImageOps(); } mpicommon::Group DFB::getMPIGroup() @@ -112,11 +109,14 @@ void DFB::startNewFrame(const float errorThreshold) nextTileWrite = 0; tileBufferOffsets.clear(); } - if (colorBufferFormat != OSP_FB_NONE) { + if (getSh()->colorBufferFormat != OSP_FB_NONE) { // Allocate a conservative upper bound of space which we'd need to // store the compressed tiles - const size_t uncompressedSize = masterMsgSize( - colorBufferFormat, hasDepthBuffer, hasNormalBuffer, hasAlbedoBuffer); + const size_t uncompressedSize = masterMsgSize(getSh()->colorBufferFormat, + hasDepthBuffer, + hasNormalBuffer, + hasAlbedoBuffer, + hasIDBuf()); const size_t compressedSize = snappy::MaxCompressedLength(uncompressedSize); tileGatherBuffer.resize(myTiles.size() * compressedSize, 0); } @@ -130,6 +130,8 @@ void DFB::startNewFrame(const float errorThreshold) "Attempt to start frame on already started frame!"); } + frameProgress = 0.f; + FrameBuffer::beginFrame(); std::for_each(imageOps.begin(), @@ -141,7 +143,7 @@ void DFB::startNewFrame(const float errorThreshold) tileErrorRegion.sync(); - if (colorBufferFormat == OSP_FB_NONE) { + if (getSh()->colorBufferFormat == OSP_FB_NONE) { std::lock_guard errsLock(tileErrorsMutex); tileIDs.clear(); tileErrors.clear(); @@ -154,6 +156,10 @@ void DFB::startNewFrame(const float errorThreshold) for (auto &tile : myTiles) tile->newFrame(); + for (auto &l : layers) { + l->beginFrame(); + } + if (mpicommon::IamTheMaster()) { numTilesExpected.resize(mpicommon::workerSize(), 0); std::fill(numTilesExpected.begin(), numTilesExpected.end(), 0); @@ -161,12 +167,8 @@ void DFB::startNewFrame(const float errorThreshold) globalTilesCompletedThisFrame = 0; numTilesCompletedThisFrame = 0; - for (int t = 0; t < getTotalTiles(); t++) { - const uint32_t nx = static_cast(getNumTiles().x); - const uint32_t ty = t / nx; - const uint32_t tx = t - ty * nx; - const vec2i tileID(tx, ty); - if (hasAccumBuffer && tileError(tileID) <= errorThreshold) { + for (uint32_t t = 0; t < getGlobalTotalTiles(); t++) { + if (hasAccumBuffer && tileError(t) <= errorThreshold) { if (allTiles[t]->mine()) { numTilesCompletedThisFrame++; } @@ -199,7 +201,7 @@ bool DFB::isFrameComplete(const size_t numTiles) ProgressMessage *msgData = reinterpret_cast(msg->data); msgData->command = PROGRESS_MESSAGE; msgData->numCompleted = renderingProgressTiles; - msgData->frameID = frameID; + msgData->frameID = getSh()->frameID; mpi::messaging::sendTo(mpicommon::masterRank(), myId, msg); renderingProgressTiles = 0; @@ -214,26 +216,95 @@ size_t DFB::ownerIDFromTileID(size_t tileID) const return tileID % mpicommon::workerSize(); } +void DistributedFrameBuffer::setSparseFBLayerCount(size_t numLayers) +{ + // Layer 0 is the base owned tiles layer created by the DFB, so we'll always + // have numLayers + 1 layers + layers.resize(numLayers + 1, nullptr); + // The sparse layers don't do accumulation and variance calculation because + // this needs data from all ranks rendering a given tile + const int channelFlags = + getChannelFlags() & ~(OSP_FB_ACCUM | OSP_FB_VARIANCE); + const bool sparseFbTrackAccumIDs = getChannelFlags() & OSP_FB_ACCUM; + // Allocate any new layers that have been added to the DFB + for (size_t i = 1; i < layers.size(); ++i) { + if (!layers[i]) { + layers[i] = rkcommon::make_unique( + size, getColorBufferFormat(), channelFlags, sparseFbTrackAccumIDs); + } + } +} + +size_t DistributedFrameBuffer::getSparseLayerCount() const +{ + return layers.size(); +} + +SparseFrameBuffer *DistributedFrameBuffer::getSparseFBLayer(size_t l) +{ + return layers[l].get(); +} + +void DFB::cancelFrame() +{ + FrameBuffer::cancelFrame(); + + // Propagate the frame cancellation to the sparse fb layers as well + for (auto &l : layers) { + l->cancelFrame(); + } +} + +float DFB::getCurrentProgress() const +{ + if (stagesCompleted == OSP_FRAME_FINISHED) { + return 1.f; + } + return frameProgress; +} + void DFB::createTiles() { allTiles.clear(); myTiles.clear(); - size_t tileID = 0; - vec2i numPixels = getNumPixels(); - for (int y = 0; y < numPixels.y; y += TILE_SIZE) { - for (int x = 0; x < numPixels.x; x += TILE_SIZE, tileID++) { + const vec2i totalTiles = divRoundUp(size, vec2i(TILE_SIZE)); + std::vector myTileIDs; + for (int y = 0; y < totalTiles.y; ++y) { + for (int x = 0; x < totalTiles.x; ++x) { + size_t tileID = size_t(x) + size_t(totalTiles.x) * size_t(y); const size_t ownerID = ownerIDFromTileID(tileID); - const vec2i tileStart(x, y); + const vec2i tileStart(x * TILE_SIZE, y * TILE_SIZE); if (ownerID == size_t(mpicommon::workerRank())) { auto td = tileOperation->makeTile(this, tileStart, tileID, ownerID); myTiles.push_back(td.get()); allTiles.push_back(std::move(td)); + myTileIDs.push_back(tileID); } else { allTiles.push_back(make_unique(tileStart, tileID, ownerID)); } } } + + // Allocate the sparse fb for the tiles we own + uint32 channels = OSP_FB_DEPTH; + // Accum and variance are not done in the sparse FB for the DFB + if (hasNormalBuf()) { + channels |= OSP_FB_NORMAL; + } + if (hasAlbedoBuf()) { + channels |= OSP_FB_ALBEDO; + } + + const bool sparseFbTrackAccumIDs = getChannelFlags() & OSP_FB_ACCUM; + if (layers.empty()) { + layers.push_back(rkcommon::make_unique( + size, OSP_FB_NONE, channels, myTileIDs, sparseFbTrackAccumIDs)); + } else { + layers[0]->setTiles(myTileIDs); + layers[0]->clear(); + } + layers[0]->commit(); } void DFB::setTileOperation( @@ -302,8 +373,6 @@ void DFB::waitUntilFinished() << elapsedTimeMs(start, end) << "ms\n"; #endif - // Report that we're 100% done and do a final check for cancellation - reportProgress(1.0f); setCompletedEvent(OSP_WORLD_RENDERED); if (frameCancelled()) { @@ -313,7 +382,7 @@ void DFB::waitUntilFinished() #ifdef ENABLE_PROFILING start = ProfilingPoint(); #endif - if (colorBufferFormat != OSP_FB_NONE) { + if (getSh()->colorBufferFormat != OSP_FB_NONE) { gatherFinalTiles(); } else if (hasVarianceBuffer) { gatherFinalErrors(); @@ -327,8 +396,9 @@ void DFB::waitUntilFinished() void DFB::processMessage(WriteTileMessage *msg) { - ospray::Tile tile; - unpackWriteTileMessage(msg, tile, hasNormalBuffer || hasAlbedoBuffer); + ispc::Tile tile; + unpackWriteTileMessage( + msg, tile, hasNormalBuffer || hasAlbedoBuffer || hasIDBuf()); auto *tileDesc = this->getTileDescFor(tile.region.lower); LiveTileOperation *td = (LiveTileOperation *)tileDesc; @@ -340,8 +410,9 @@ void DistributedFrameBuffer::processMessage(MasterTileMessage_FB *msg) { if (hasVarianceBuffer) { const vec2i tileID = msg->coords / TILE_SIZE; - if (msg->error < (float)inf) + if (msg->error < (float)inf) { tileErrorRegion.update(tileID, msg->error); + } } vec2i numPixels = getNumPixels(); @@ -355,6 +426,39 @@ void DistributedFrameBuffer::processMessage(MasterTileMessage_FB *msg) if (msg->command & MASTER_TILE_HAS_AUX) aux = reinterpret_cast *>(msg); + uint32 *pidBuf = nullptr; + uint32 *gidBuf = nullptr; + uint32 *iidBuf = nullptr; + // TODO: Make the rest of the tile more dynamically sized and use a buffer + // cursor style to get the pointers to the individual tile components + if (msg->command & MASTER_TILE_HAS_ID) { + // The ID buffer data comes at the end of the tile message + uint8 *data = reinterpret_cast(msg); + if (!aux) { + if (depth) { + data += sizeof(MasterTileMessage_FB_Depth); + } else { + data += sizeof(MasterTileMessage_FB); + } + } else { + data += sizeof(MasterTileMessage_FB_Depth_Aux); + } + // All IDs are sent if any were requested, however we need to write only the + // ones that actually exist in the local FB since it doesn't allocate + // buffers for the non-existant channels + if (hasPrimitiveIDBuffer) { + pidBuf = reinterpret_cast(data); + } + if (hasObjectIDBuffer) { + gidBuf = reinterpret_cast( + data + sizeof(uint32) * TILE_SIZE * TILE_SIZE); + } + if (hasInstanceIDBuffer) { + iidBuf = reinterpret_cast( + data + 2 * sizeof(uint32) * TILE_SIZE * TILE_SIZE); + } + } + ColorT *color = reinterpret_cast(&localFBonMaster->colorBuffer[0]); for (int iy = 0; iy < TILE_SIZE; iy++) { int iiy = iy + msg->coords.y; @@ -381,30 +485,42 @@ void DistributedFrameBuffer::processMessage(MasterTileMessage_FB *msg) localFBonMaster->albedoBuffer[iix + iiy * numPixels.x] = aux->albedo[ix + iy * TILE_SIZE]; } + if (pidBuf) { + localFBonMaster->primitiveIDBuffer[iix + iiy * numPixels.x] = + pidBuf[ix + iy * TILE_SIZE]; + } + if (gidBuf) { + localFBonMaster->objectIDBuffer[iix + iiy * numPixels.x] = + gidBuf[ix + iy * TILE_SIZE]; + } + if (iidBuf) { + localFBonMaster->instanceIDBuffer[iix + iiy * numPixels.x] = + iidBuf[ix + iy * TILE_SIZE]; + } } } } +bool DFB::hasIDBuf() const +{ + // ID buffers are only needed on the first frame when rendering with + // accumulation + return getFrameID() == 0 + && (hasPrimitiveIDBuffer || hasObjectIDBuffer || hasInstanceIDBuffer); +} + void DFB::tileIsFinished(LiveTileOperation *tile) { - if (!imageOps.empty()) { - std::for_each(imageOps.begin(), - imageOps.begin() + firstFrameOperation, - [&](std::unique_ptr &iop) { - LiveTileOp *top = dynamic_cast(iop.get()); - if (top) { - top->process(tile->finished); - } - // TODO: For now, frame operations must be last - // in the pipeline - }); + // Run any pixel operations we have for this tile + if (!pixelOpShs.empty()) { + ispc::DFB_runPixelOpsForTile(getSh(), (ispc::Tile *)&tile->finished); } // Write the final colors into the color buffer // normalize and write final color, and compute error - if (colorBufferFormat != OSP_FB_NONE) { + if (getSh()->colorBufferFormat != OSP_FB_NONE) { auto DFB_writeTile = &ispc::DFB_writeTile_RGBA32F; - switch (colorBufferFormat) { + switch (getSh()->colorBufferFormat) { case OSP_FB_RGBA8: DFB_writeTile = &ispc::DFB_writeTile_RGBA8; break; @@ -418,21 +534,25 @@ void DFB::tileIsFinished(LiveTileOperation *tile) } auto msg = [&] { - MasterTileMessageBuilder msg(colorBufferFormat, + MasterTileMessageBuilder msg(getSh()->colorBufferFormat, hasDepthBuffer, hasNormalBuffer, hasAlbedoBuffer, + hasIDBuf(), tile->begin, tile->error); msg.setColor(tile->color); msg.setDepth(tile->finished.z); msg.setNormal((vec3f *)tile->finished.nx); msg.setAlbedo((vec3f *)tile->finished.ar); + msg.setPrimitiveID(tile->finished.pid); + msg.setObjectID(tile->finished.gid); + msg.setInstanceID(tile->finished.iid); return msg; }; // TODO still send normal & albedo? - if (colorBufferFormat == OSP_FB_NONE) { + if (getSh()->colorBufferFormat == OSP_FB_NONE) { std::lock_guard lock(tileErrorsMutex); tileIDs.push_back(tile->begin / TILE_SIZE); tileErrors.push_back(tile->error); @@ -464,8 +584,7 @@ void DFB::tileIsFinished(LiveTileOperation *tile) void DFB::updateProgress(ProgressMessage *msg) { globalTilesCompletedThisFrame += msg->numCompleted; - const float progress = globalTilesCompletedThisFrame / (float)getTotalTiles(); - reportProgress(progress); + frameProgress = globalTilesCompletedThisFrame / (float)getGlobalTotalTiles(); } size_t DFB::numMyTiles() const @@ -480,7 +599,7 @@ TileDesc *DFB::getTileDescFor(const vec2i &coords) const size_t DFB::getTileIDof(const vec2i &c) const { - return (c.x / TILE_SIZE) + (c.y / TILE_SIZE) * numTiles.x; + return (c.x / TILE_SIZE) + (c.y / TILE_SIZE) * totalTiles.x; } std::string DFB::toString() const @@ -545,8 +664,11 @@ void DFB::gatherFinalTiles() ProfilingPoint preGatherComputeStart; #endif - const size_t tileSize = masterMsgSize( - colorBufferFormat, hasDepthBuffer, hasNormalBuffer, hasAlbedoBuffer); + const size_t tileSize = masterMsgSize(getSh()->colorBufferFormat, + hasDepthBuffer, + hasNormalBuffer, + hasAlbedoBuffer, + hasIDBuf()); const int totalTilesExpected = std::accumulate(numTilesExpected.begin(), numTilesExpected.end(), 0); @@ -746,13 +868,14 @@ void DFB::closeCurrentFrame() //! write given tile data into the frame buffer, sending to remote owner if //! required -void DFB::setTile(ospray::Tile &tile) +void DFB::setTile(const ispc::Tile &tile) { auto *tileDesc = this->getTileDescFor(tile.region.lower); // Note my tile, send to the owner if (!tileDesc->mine()) { - auto msg = makeWriteTileMessage(tile, hasNormalBuffer || hasAlbedoBuffer); + auto msg = makeWriteTileMessage( + tile, hasNormalBuffer || hasAlbedoBuffer || hasIDBuf()); int dstRank = tileDesc->ownerID; mpi::messaging::sendTo(dstRank, myId, msg); @@ -767,8 +890,7 @@ void DFB::setTile(ospray::Tile &tile) void DFB::clear() { - frameID = -1; // we increment at the start of the frame - std::fill(tileAccumID.begin(), tileAccumID.end(), 0); + getSh()->frameID = -1; // we increment at the start of the frame if (hasAccumBuffer) { tileErrorRegion.clear(); @@ -776,27 +898,48 @@ void DFB::clear() if (localFBonMaster) { localFBonMaster->clear(); } + for (auto &l : layers) { + l->clear(); + } } -int32 DFB::accumID(const vec2i &tile) +vec2i DFB::getNumRenderTasks() const { - if (!hasAccumBuffer) { - return 0; - } - return tileAccumID[tile.y * numTiles.x + tile.x]; + return numRenderTasks; +} + +uint32_t DFB::getTotalRenderTasks() const +{ + return numRenderTasks.product(); } -float DFB::tileError(const vec2i &tile) +vec2i DFB::getGlobalNumTiles() const { - return tileErrorRegion[tile]; + return totalTiles; +} + +uint32_t DFB::getGlobalTotalTiles() const +{ + return totalTiles.product(); +} + +utility::ArrayView DFB::getRenderTaskIDs() +{ + return layers[0]->getRenderTaskIDs(); +} + +float DFB::taskError(const uint32_t) const +{ + NOT_IMPLEMENTED; +} + +float DFB::tileError(const uint32_t tileID) +{ + return tileErrorRegion[tileID]; } void DFB::endFrame(const float errorThreshold, const Camera *camera) { - // TODO: FrameOperations should just be run on the master process for now, - // but in the offload device the master process doesn't get any OSPData - // or pixel ops or etc. created, just the handles. So it doesn't even - // know about the frame operation to run if (localFBonMaster && !imageOps.empty() && firstFrameOperation < imageOps.size()) { std::for_each(imageOps.begin() + firstFrameOperation, @@ -817,12 +960,8 @@ void DFB::endFrame(const float errorThreshold, const Camera *camera) if (mpicommon::IamTheMaster()) { frameVariance = tileErrorRegion.refine(errorThreshold); } - - if (hasAccumBuffer) { - std::transform(tileAccumID.begin(), - tileAccumID.end(), - tileAccumID.begin(), - [](const uint32_t &x) { return x + 1; }); + for (auto &l : layers) { + l->endFrame(errorThreshold, camera); } setCompletedEvent(OSP_FRAME_FINISHED); diff --git a/modules/mpi/ospray/fb/DistributedFrameBuffer.h b/modules/mpi/ospray/fb/DistributedFrameBuffer.h index 8c5425492f..6edd3b6960 100644 --- a/modules/mpi/ospray/fb/DistributedFrameBuffer.h +++ b/modules/mpi/ospray/fb/DistributedFrameBuffer.h @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -8,6 +8,7 @@ #include "../common/Messaging.h" #include "DistributedFrameBuffer_TileMessages.h" #include "fb/LocalFB.h" +#include "fb/SparseFB.h" #include "render/Renderer.h" #include "rkcommon/containers/AlignedVector.h" @@ -16,12 +17,13 @@ struct TileDesc; struct TileOperation; struct LiveTileOperation; -class DistributedTileError : public TileError +class DistributedTileError : public TaskError { mpicommon::Group group; public: DistributedTileError(const vec2i &numTiles, mpicommon::Group group); + // broadcast tileErrorBuffer to all workers in this group void sync(); }; @@ -33,16 +35,18 @@ struct DistributedFrameBuffer : public mpi::messaging::MessageHandler, ObjectHandle myHandle, ColorBufferFormat, const uint32 channels); + ~DistributedFrameBuffer() override; // ================================================================== // framebuffer / device interface // ================================================================== + void commit() override; + const void *mapBuffer(OSPFrameBufferChannel channel) override; - void unmap(const void *mappedMem) override; - void commit() override; + void unmap(const void *mappedMem) override; /*! \brief clear (the specified channels of) this frame buffer @@ -57,23 +61,45 @@ struct DistributedFrameBuffer : public mpi::messaging::MessageHandler, // framebuffer-renderer/loadbalancer interface // ================================================================== + // Return the number of render tasks in the x and y direction + // This is the kernel launch dims to render the image + vec2i getNumRenderTasks() const override; + + uint32_t getTotalRenderTasks() const override; + + vec2i getGlobalNumTiles() const; + + uint32_t getGlobalTotalTiles() const; + + /* Get render task IDs will return the render task IDs for layer 0, + * the tiles owned by the DFB for compositing. + */ + utility::ArrayView getRenderTaskIDs() override; + + // Task error is not valid for the DFB, as error is tracked at a per-tile + // level. Use tileError to get rendering error + float taskError(const uint32_t taskID) const override; + + float tileError(const uint32_t tileID); + /*! framebuffer-renderer/loadbalancer interface: loadbalancer calls this function whenever a local node has finished a tile, and wants the (distributed) frame buffer to process it */ - void setTile(ospray::Tile &tile) override; + void setTile(const ispc::Tile &tile); void startNewFrame(const float errorThreshold); + void closeCurrentFrame(); void waitUntilFinished(); - int32 accumID(const vec2i &) override; - float tileError(const vec2i &tile) override; void endFrame(const float errorThreshold, const Camera *camera) override; void setTileOperation( std::shared_ptr tileOp, const Renderer *renderer); + std::shared_ptr getTileOperation(); + const Renderer *getLastRenderer() const; mpicommon::Group getMPIGroup(); @@ -95,16 +121,21 @@ struct DistributedFrameBuffer : public mpi::messaging::MessageHandler, size_t ownerIDFromTileID(size_t tileID) const; - private: - std::vector tileGatherBuffer; - std::vector compressedResults; - // Locations of the compressed tiles in the tileGatherBuffer - std::vector tileBufferOffsets; - uint32_t nextTileWrite; - std::mutex finalTileBufferMutex; + void setSparseFBLayerCount(size_t numLayers); + + size_t getSparseLayerCount() const; + + SparseFrameBuffer *getSparseFBLayer(size_t l); + + void cancelFrame() override; + + float getCurrentProgress() const override; + private: friend struct LiveTileOperation; + bool hasIDBuf() const; + // ================================================================== // internal helper functions // ================================================================== @@ -162,8 +193,24 @@ struct DistributedFrameBuffer : public mpi::messaging::MessageHandler, // conflicts with other framebuffers mpicommon::Group mpiGroup; - // Holds accumID per tile, for adaptive accumulation - rkcommon::containers::AlignedVector tileAccumID; + // Total number of tiles that the framebuffer is divided into, including those + // not owned by this sparsefb + vec2i totalTiles; + + // Total number of render tasks that the framebuffer is divided into, + // including those not owned by this sparsefb + vec2i numRenderTasks; + + std::vector tileGatherBuffer; + + std::vector compressedResults; + + // Locations of the compressed tiles in the tileGatherBuffer + std::vector tileBufferOffsets; + + uint32_t nextTileWrite{0}; + + std::mutex finalTileBufferMutex; /*! holds error per tile and adaptive regions, for variance estimation / stopping */ @@ -174,17 +221,26 @@ struct DistributedFrameBuffer : public mpi::messaging::MessageHandler, master if the master does not have a color buffer */ std::unique_ptr localFBonMaster; + /* SparseFrameBuffer layers in the DFB, layer 0 stores the tiles owned by DFB + * for compositing, and layers 1-N are those added by the renderer. For + * renderers whose local rendering work is dynamic/data-dependent (e.g., + * data-parallel rendering), layers can be allocated and resized as needed to + * avoid having to reallocate the set of SparseFrameBuffer(s) needed each + * frame. + */ + std::vector> layers; + /*! #tiles we've (already) sent to / received by the master this frame (used to track when current node is done with this frame - we are done exactly once we've completed sending / receiving the last tile to / by the master) */ - size_t numTilesCompletedThisFrame; + size_t numTilesCompletedThisFrame{0}; /*! The total number of tiles completed by all workers during this frame, to track progress for the user's progress callback. NOTE: This is not the numTilesCompletedThisFrame , which tracks how many tiles this rank has finished of the ones it's responsible for completing */ - size_t globalTilesCompletedThisFrame; + size_t globalTilesCompletedThisFrame{0}; /*! The number of tiles the master is expecting to receive from each rank */ std::vector numTilesExpected; @@ -214,15 +270,17 @@ struct DistributedFrameBuffer : public mpi::messaging::MessageHandler, //! set to true when the frame becomes 'active', and write tile //! messages can be consumed. - std::atomic frameIsActive; + std::atomic frameIsActive{false}; /*! set to true when the framebuffer is done for the given frame */ - bool frameIsDone; + bool frameIsDone{false}; - int renderingProgressTiles; + int renderingProgressTiles{0}; std::chrono::steady_clock::time_point lastProgressReport; + std::atomic frameProgress{0.f}; + //! condition that gets triggered when the frame is done std::condition_variable frameDoneCond; diff --git a/modules/mpi/ospray/fb/DistributedFrameBuffer.ispc b/modules/mpi/ospray/fb/DistributedFrameBuffer.ispc index 3f6aef8597..e7295289b5 100644 --- a/modules/mpi/ospray/fb/DistributedFrameBuffer.ispc +++ b/modules/mpi/ospray/fb/DistributedFrameBuffer.ispc @@ -1,13 +1,11 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "fb/FrameBuffer.ih" +#include "fb/Tile.ih" #include "rkcommon/math/vec.ih" -struct DistributedFrameBuffer -{ - FrameBuffer super; -}; +#include "fb/FrameBufferShared.h" // accumulates the colors in a tile, writes the final normalized colors into a // separate tile, and computes the error @@ -38,6 +36,11 @@ export uniform float DFB_accumulateTile(const VaryingTile *uniform tile, final->b[i] = col.z; final->a[i] = col.w; final->z[i] = tile->z[i]; + + // ID buffers only written on the first frame + final->pid[i] = tile->pid[i]; + final->gid[i] = tile->gid[i]; + final->iid[i] = tile->iid[i]; } } else { const uniform float rcpAccumID = rcpf(accumID + 1); @@ -82,8 +85,11 @@ export uniform float DFB_accumulateTile(const VaryingTile *uniform tile, } /* error is also only updated every other frame to avoid alternating * error (get a monotone sequence) */ - if (accumulateVariance) - errf = reduce_add(err) * rsqrtf(size.x * size.y); + if (accumulateVariance) { + uniform float cntu = (uniform float)size.x * size.y; + // scaling factor to stay backward compatible to default TILE_SIZE=64 + errf = reduce_add(err) * rcp(cntu) * 64.f; + } } return errf; } @@ -119,9 +125,10 @@ export void DFB_accumulateTileSimple(const VaryingTile *uniform tile, // accumulate normal and albedo export void DFB_accumulateAuxTile(const VaryingTile *uniform tile, - Tile *uniform final, + void *uniform _final, VaryingTile *uniform accum) { + Tile *uniform final = (Tile * uniform) _final; const uniform vec2i size = box_size(tile->region); const uniform int maxi = size.y * (TILE_SIZE / programCount); if (tile->accumID < 1) @@ -172,7 +179,7 @@ export uniform float DFB_computeErrorForTile(const uniform vec2i &size, { const uniform int maxi = size.y * (TILE_SIZE / programCount); const uniform float rcpAccumID = rcpf(accumID + 1); - const uniform float accHalfScale = rcpf((accumID + 1) / 2); + const uniform float accHalfScale = rcpf(accumID / 2 + 1); float err = 0.f; for (uniform int i = 0; i < maxi; i++) { vec4f acc = make_vec4f(accum->r[i], accum->g[i], accum->b[i], accum->a[i]); @@ -188,7 +195,9 @@ export uniform float DFB_computeErrorForTile(const uniform vec2i &size, err += reduce_add(diff) * rsqrtf(den2); } } - return reduce_add(err) * rsqrtf(size.x * size.y); + uniform float cntu = (uniform float)size.x * size.y; + // scaling factor to stay backward compatible to default TILE_SIZE=64 + return reduce_add(err) * rcp(cntu) * 64.f; } // writes the final normalized colors in a tile into a color buffer @@ -230,42 +239,64 @@ export void DFB_zComposite( } } -export void *uniform DFB_create() -{ - DistributedFrameBuffer *uniform self = - uniform new uniform DistributedFrameBuffer; - FrameBuffer_Constructor(&self->super); - - return self; -} - -export void DFB_set(void *uniform _self, - const uniform uint32 size_x, - const uniform uint32 size_y, - uniform int32 colorBufferFormat) -{ - DistributedFrameBuffer *uniform self = (DistributedFrameBuffer *)_self; - FrameBuffer_set(&self->super, size_x, size_y, colorBufferFormat); -} - inline void swapFragments( VaryingTile *uniform t0, VaryingTile *uniform t1, uniform int fragID) { float r = t0->r[fragID]; t0->r[fragID] = t1->r[fragID]; t1->r[fragID] = r; + float g = t0->g[fragID]; t0->g[fragID] = t1->g[fragID]; t1->g[fragID] = g; + float b = t0->b[fragID]; t0->b[fragID] = t1->b[fragID]; t1->b[fragID] = b; + float a = t0->a[fragID]; t0->a[fragID] = t1->a[fragID]; t1->a[fragID] = a; + float z = t0->z[fragID]; t0->z[fragID] = t1->z[fragID]; t1->z[fragID] = z; + + float nx = t0->nx[fragID]; + t0->nx[fragID] = t1->nx[fragID]; + t1->nx[fragID] = nx; + + float ny = t0->ny[fragID]; + t0->ny[fragID] = t1->ny[fragID]; + t1->ny[fragID] = ny; + + float nz = t0->nz[fragID]; + t0->nz[fragID] = t1->nz[fragID]; + t1->nz[fragID] = nz; + + float ar = t0->ar[fragID]; + t0->ar[fragID] = t1->ar[fragID]; + t1->ar[fragID] = ar; + + float ag = t0->ag[fragID]; + t0->ag[fragID] = t1->ag[fragID]; + t1->ag[fragID] = ag; + + float ab = t0->ab[fragID]; + t0->ab[fragID] = t1->ab[fragID]; + t1->ab[fragID] = ab; + + uint32 pid = t0->pid[fragID]; + t0->pid[fragID] = t1->pid[fragID]; + t1->pid[fragID] = pid; + + uint32 gid = t0->gid[fragID]; + t0->gid[fragID] = t1->gid[fragID]; + t1->gid[fragID] = gid; + + uint32 iid = t0->iid[fragID]; + t0->iid[fragID] = t1->iid[fragID]; + t1->iid[fragID] = iid; } #define PIXELS_PER_BLEND_JOB 64 @@ -318,3 +349,35 @@ export void DFB_sortAndBlendFragments( sortAndBlendFragments( tileArray, numTiles, 0, TILE_SIZE * TILE_SIZE / programCount); } + +task void DFB_runPixelOpsTask( + FrameBuffer *uniform fb, VaryingTile *uniform tile) +{ + const uniform int chunk = taskIndex0; + vec4f color = make_vec4f( + tile->r[chunk], tile->g[chunk], tile->b[chunk], tile->a[chunk]); + + const float depth = tile->z[chunk]; + + const vec3f normal = + make_vec3f(tile->nx[chunk], tile->ny[chunk], tile->nz[chunk]); + + const vec3f albedo = + make_vec3f(tile->ar[chunk], tile->ag[chunk], tile->ab[chunk]); + + color = FrameBuffer_runPixelOps(fb, color, depth, normal, albedo); + + tile->r[chunk] = color.x; + tile->g[chunk] = color.y; + tile->b[chunk] = color.z; + tile->a[chunk] = color.w; +} + +export void DFB_runPixelOpsForTile(void *uniform _self, void *uniform _tile) +{ + Tile *uniform tile = (Tile * uniform) _tile; + FrameBuffer *uniform fb = (FrameBuffer * uniform) _self; + // Each task processes programCount pixels + const uniform int ntasks = TILE_SIZE * TILE_SIZE / programCount; + launch[ntasks] DFB_runPixelOpsTask(fb, (VaryingTile * uniform) tile); +} diff --git a/modules/mpi/ospray/fb/DistributedFrameBuffer_TileMessages.cpp b/modules/mpi/ospray/fb/DistributedFrameBuffer_TileMessages.cpp index 0c760bc0f9..48f0b462f8 100644 --- a/modules/mpi/ospray/fb/DistributedFrameBuffer_TileMessages.cpp +++ b/modules/mpi/ospray/fb/DistributedFrameBuffer_TileMessages.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "DistributedFrameBuffer_TileMessages.h" #include "../common/Messaging.h" @@ -6,10 +6,9 @@ namespace ospray { std::shared_ptr makeWriteTileMessage( - const ospray::Tile &tile, bool hasAux) + const ispc::Tile &tile, bool hasAux) { - const size_t msgSize = - hasAux ? sizeof(ospray::Tile) : sizeof(WriteTileMessage); + const size_t msgSize = hasAux ? sizeof(ispc::Tile) : sizeof(WriteTileMessage); auto msg = std::make_shared(msgSize + sizeof(int)); const static int header = WORKER_WRITE_TILE; std::memcpy(msg->data, &header, sizeof(int)); @@ -18,15 +17,17 @@ std::shared_ptr makeWriteTileMessage( } void unpackWriteTileMessage( - WriteTileMessage *msg, ospray::Tile &tile, bool hasAux) + WriteTileMessage *msg, ispc::Tile &tile, bool hasAux) { - const size_t msgSize = - hasAux ? sizeof(ospray::Tile) : sizeof(WriteTileMessage); + const size_t msgSize = hasAux ? sizeof(ispc::Tile) : sizeof(WriteTileMessage); std::memcpy(&tile, reinterpret_cast(msg) + sizeof(int), msgSize); } -size_t masterMsgSize( - OSPFrameBufferFormat fmt, bool hasDepth, bool hasNormal, bool hasAlbedo) +size_t masterMsgSize(OSPFrameBufferFormat fmt, + bool hasDepth, + bool hasNormal, + bool hasAlbedo, + bool hasIDBuffers) { size_t msgSize = 0; switch (fmt) { @@ -48,6 +49,10 @@ size_t masterMsgSize( if (hasNormal || hasAlbedo) { msgSize += 2 * sizeof(vec3f) * TILE_SIZE * TILE_SIZE; } + // If any ID buffer is present we allocate space for all of them to be sent + if (hasIDBuffers) { + msgSize += 3 * sizeof(uint32) * TILE_SIZE * TILE_SIZE; + } return msgSize; } @@ -55,15 +60,18 @@ MasterTileMessageBuilder::MasterTileMessageBuilder(OSPFrameBufferFormat fmt, bool hasDepth, bool hasNormal, bool hasAlbedo, + bool hasIDBuffers, vec2i coords, float error) : colorFormat(fmt), hasDepth(hasDepth), hasNormal(hasNormal), - hasAlbedo(hasAlbedo) + hasAlbedo(hasAlbedo), + hasIDBuffers(hasIDBuffers) { int command = 0; - const size_t msgSize = masterMsgSize(fmt, hasDepth, hasNormal, hasAlbedo); + const size_t msgSize = + masterMsgSize(fmt, hasDepth, hasNormal, hasAlbedo, hasIDBuffers); switch (fmt) { case OSP_FB_NONE: throw std::runtime_error( @@ -79,18 +87,22 @@ MasterTileMessageBuilder::MasterTileMessageBuilder(OSPFrameBufferFormat fmt, break; } // AUX also includes depth - if (hasDepth) { + if (hasDepth || hasNormal || hasAlbedo) { command |= MASTER_TILE_HAS_DEPTH; } if (hasNormal || hasAlbedo) { command |= MASTER_TILE_HAS_AUX; } + if (hasIDBuffers) { + command |= MASTER_TILE_HAS_ID; + } message = std::make_shared(msgSize); header = reinterpret_cast(message->data); header->command = command; header->coords = coords; header->error = error; } + void MasterTileMessageBuilder::setColor(const vec4f *color) { if (colorFormat != OSP_FB_NONE) { @@ -99,32 +111,93 @@ void MasterTileMessageBuilder::setColor(const vec4f *color) std::copy(input, input + pixelSize * TILE_SIZE * TILE_SIZE, out); } } + void MasterTileMessageBuilder::setDepth(const float *depth) { if (hasDepth) { - float *out = reinterpret_cast(message->data - + sizeof(MasterTileMessage_NONE) + pixelSize * TILE_SIZE * TILE_SIZE); + float *out = reinterpret_cast( + message->data + sizeof(MasterTileMessage_NONE) + colorBufferSize()); std::copy(depth, depth + TILE_SIZE * TILE_SIZE, out); } } + void MasterTileMessageBuilder::setNormal(const vec3f *normal) { if (hasNormal) { - auto out = reinterpret_cast(message->data - + sizeof(MasterTileMessage_NONE) + pixelSize * TILE_SIZE * TILE_SIZE - + sizeof(float) * TILE_SIZE * TILE_SIZE); + vec3f *out = + reinterpret_cast(message->data + sizeof(MasterTileMessage_NONE) + + colorBufferSize() + depthBufferSize()); std::copy(normal, normal + TILE_SIZE * TILE_SIZE, out); } } + void MasterTileMessageBuilder::setAlbedo(const vec3f *albedo) { if (hasAlbedo) { - auto out = reinterpret_cast(message->data - + sizeof(MasterTileMessage_NONE) + pixelSize * TILE_SIZE * TILE_SIZE - + sizeof(float) * TILE_SIZE * TILE_SIZE - + sizeof(vec3f) * TILE_SIZE * TILE_SIZE); + vec3f *out = + reinterpret_cast(message->data + sizeof(MasterTileMessage_NONE) + + colorBufferSize() + depthBufferSize() + normalBufferSize()); std::copy(albedo, albedo + TILE_SIZE * TILE_SIZE, out); } } +void MasterTileMessageBuilder::setPrimitiveID(const uint32 *primID) +{ + if (hasIDBuffers) { + size_t offset = sizeof(MasterTileMessage_NONE) + colorBufferSize() + + depthBufferSize() + normalBufferSize() + albedoBufferSize(); + uint32 *out = reinterpret_cast(message->data + offset); + std::copy(primID, primID + TILE_SIZE * TILE_SIZE, out); + } +} + +void MasterTileMessageBuilder::setObjectID(const uint32 *geomID) +{ + if (hasIDBuffers) { + size_t offset = sizeof(MasterTileMessage_NONE) + colorBufferSize() + + depthBufferSize() + normalBufferSize() + albedoBufferSize() + + sizeof(uint32) * TILE_SIZE * TILE_SIZE; + uint32 *out = reinterpret_cast(message->data + offset); + std::copy(geomID, geomID + TILE_SIZE * TILE_SIZE, out); + } +} + +void MasterTileMessageBuilder::setInstanceID(const uint32 *instID) +{ + if (hasIDBuffers) { + size_t offset = sizeof(MasterTileMessage_NONE) + colorBufferSize() + + depthBufferSize() + normalBufferSize() + albedoBufferSize() + + 2 * sizeof(uint32) * TILE_SIZE * TILE_SIZE; + uint32 *out = reinterpret_cast(message->data + offset); + std::copy(instID, instID + TILE_SIZE * TILE_SIZE, out); + } +} + +size_t MasterTileMessageBuilder::colorBufferSize() const +{ + return pixelSize * TILE_SIZE * TILE_SIZE; +} + +size_t MasterTileMessageBuilder::depthBufferSize() const +{ + return hasDepth || hasNormal || hasAlbedo + ? sizeof(float) * TILE_SIZE * TILE_SIZE + : 0; +} + +size_t MasterTileMessageBuilder::normalBufferSize() const +{ + return (hasNormal || hasAlbedo) ? sizeof(vec3f) * TILE_SIZE * TILE_SIZE : 0; +} + +size_t MasterTileMessageBuilder::albedoBufferSize() const +{ + return (hasNormal || hasAlbedo) ? sizeof(vec3f) * TILE_SIZE * TILE_SIZE : 0; +} + +size_t MasterTileMessageBuilder::idBufferSize() const +{ + return hasIDBuffers ? 3 * sizeof(uint32) * TILE_SIZE * TILE_SIZE : 0; +} + } // namespace ospray diff --git a/modules/mpi/ospray/fb/DistributedFrameBuffer_TileMessages.h b/modules/mpi/ospray/fb/DistributedFrameBuffer_TileMessages.h index 0df5bb869f..45e3578613 100644 --- a/modules/mpi/ospray/fb/DistributedFrameBuffer_TileMessages.h +++ b/modules/mpi/ospray/fb/DistributedFrameBuffer_TileMessages.h @@ -1,10 +1,11 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "../common/Messaging.h" #include "fb/LocalFB.h" +#include "fb/TileShared.h" namespace ospray { @@ -24,14 +25,16 @@ enum COMMANDTAG to let the master know when we're done. */ MASTER_WRITE_TILE_I8 = 1 << 2, MASTER_WRITE_TILE_F32 = 1 << 3, - // Modifier to indicate the tile also has depth values + // Modifier to indicate the tile has depth values MASTER_TILE_HAS_DEPTH = 1 << 4, - // Indicates that the tile additionally also has normal and/or albedo values + // Indicates that the tile has normal and/or albedo values MASTER_TILE_HAS_AUX = 1 << 5, + // Indicates that the tile has ID buffer values + MASTER_TILE_HAS_ID = 1 << 6, // abort rendering the current frame - CANCEL_RENDERING = 1 << 6, + CANCEL_RENDERING = 1 << 7, // Worker updating us on tiles completed - PROGRESS_MESSAGE = 1 << 7 + PROGRESS_MESSAGE = 1 << 8 }; struct TileMessage @@ -101,13 +104,16 @@ struct WriteTileMessage : public TileMessage }; std::shared_ptr makeWriteTileMessage( - const ospray::Tile &tile, bool hasAux); + const ispc::Tile &tile, bool hasAux); void unpackWriteTileMessage( - WriteTileMessage *msg, ospray::Tile &tile, bool hasAux); + WriteTileMessage *msg, ispc::Tile &tile, bool hasAux); -size_t masterMsgSize( - OSPFrameBufferFormat fmt, bool hasDepth, bool hasNormal, bool hasAlbedo); +size_t masterMsgSize(OSPFrameBufferFormat fmt, + bool hasDepth, + bool hasNormal, + bool hasAlbedo, + bool hasIDBuffers); /*! The message builder lets us abstractly fill messages of different * types, while keeping the underlying message structs POD so they're @@ -119,6 +125,7 @@ class MasterTileMessageBuilder bool hasDepth; bool hasNormal; bool hasAlbedo; + bool hasIDBuffers; size_t pixelSize; MasterTileMessage_NONE *header; @@ -129,11 +136,42 @@ class MasterTileMessageBuilder bool hasDepth, bool hasNormal, bool hasAlbedo, + bool hasIDBuffers, vec2i coords, float error); + void setColor(const vec4f *color); + void setDepth(const float *depth); + void setNormal(const vec3f *normal); + void setAlbedo(const vec3f *albedo); + + void setPrimitiveID(const uint32 *primID); + + void setObjectID(const uint32 *geomID); + + void setInstanceID(const uint32 *instID); + + private: + // Return the size in bytes of the color data in the message + size_t colorBufferSize() const; + + // Return the size in bytes of the depth data in the message. Returns 0 if + // depth is not being sent + size_t depthBufferSize() const; + + // Return the size in bytes of the normal data in the message. Returns 0 if + // normals are not being sent + size_t normalBufferSize() const; + + // Return the size in bytes of the albedo data in the message. Returns 0 if + // albedo is not being sent + size_t albedoBufferSize() const; + + // Return the size in bytes of the ID data in the message. Returns 0 if + // IDs are not being sent + size_t idBufferSize() const; }; } // namespace ospray diff --git a/modules/mpi/ospray/fb/TileOperation.cpp b/modules/mpi/ospray/fb/TileOperation.cpp index eccba1b1de..f68f4f724d 100644 --- a/modules/mpi/ospray/fb/TileOperation.cpp +++ b/modules/mpi/ospray/fb/TileOperation.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "TileOperation.h" @@ -20,7 +20,7 @@ LiveTileOperation::LiveTileOperation( : TileDesc(begin, tileID, ownerID), dfb(dfb) {} -void LiveTileOperation::accumulate(const ospray::Tile &tile) +void LiveTileOperation::accumulate(const ispc::Tile &tile) { // accumulate, compute the finished normalized colors, and compute the // error, but don't write the finished colors into the color buffer yet diff --git a/modules/mpi/ospray/fb/TileOperation.h b/modules/mpi/ospray/fb/TileOperation.h index c465a4cb8b..468972e02e 100644 --- a/modules/mpi/ospray/fb/TileOperation.h +++ b/modules/mpi/ospray/fb/TileOperation.h @@ -1,11 +1,11 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include -#include "fb/Tile.h" +#include "fb/TileShared.h" namespace ospray { @@ -84,17 +84,17 @@ struct LiveTileOperation : public TileDesc return true; } - /* Called for each ospray::Tile rendered locally or received over the + /* Called for each Tile rendered locally or received over the * network for this image tile. */ - virtual void process(const ospray::Tile &tile) = 0; + virtual void process(const ispc::Tile &tile) = 0; /* Utility method provided to accumulate the finished tile data from the * passed tile into the "finished" tile data, which will be passed on to any * ImageOps or written to the framebuffer. * TODO: Maybe just manage this on the DFB side? */ - void accumulate(const ospray::Tile &tile); + void accumulate(const ispc::Tile &tile); /* Method to be called when the tile operation is finished and the computed * image written to the "finished" member of the struct @@ -104,22 +104,21 @@ struct LiveTileOperation : public TileDesc DistributedFrameBuffer *dfb; // estimated variance of this tile - float error; + float error{0.f}; // TODO: dynamically allocate to save memory when no ACCUM or VARIANCE // even more TODO: Tile contains much more data (e.g. AUX), but using only // the color buffer here ==> much wasted memory // also holds accumulated normal&albedo - ospray::Tile __aligned(64) accum; - ospray::Tile __aligned(64) variance; + ispc::Tile __aligned(64) accum; + ispc::Tile __aligned(64) variance; - /* iw: TODO - have to change this. right now, to be able to give + /* To be able to give the 'postaccum' pixel op a readily normalized tile we have to create a local copy (the tile stores only the accum value, and we cannot change this) */ // also holds normalized normal&albedo in AOS format - // TODO WILL: Is this really such a big deal? - ospray::Tile __aligned(64) finished; + ispc::Tile __aligned(64) finished; //! the rbga32-converted colors // TODO: dynamically allocate to save memory when only uint32 / I8 colors diff --git a/modules/mpi/ospray/mpi_offload_worker_main.cpp b/modules/mpi/ospray/mpi_offload_worker_main.cpp index 4eca3fb479..d933fc5d2c 100644 --- a/modules/mpi/ospray/mpi_offload_worker_main.cpp +++ b/modules/mpi/ospray/mpi_offload_worker_main.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include diff --git a/modules/mpi/ospray/render/DistributedLoadBalancer.cpp b/modules/mpi/ospray/render/DistributedLoadBalancer.cpp index ea5a460e4c..db9278410e 100644 --- a/modules/mpi/ospray/render/DistributedLoadBalancer.cpp +++ b/modules/mpi/ospray/render/DistributedLoadBalancer.cpp @@ -1,10 +1,12 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "DistributedLoadBalancer.h" #include #include #include +#include "../common/DistributedWorld.h" +#include "../common/DynamicLoadBalancer.h" #include "../fb/DistributedFrameBuffer.h" #include "WriteMultipleTileOperation.h" #include "camera/Camera.h" @@ -16,17 +18,16 @@ namespace ospray { namespace mpi { -namespace staticLoadBalancer { using namespace mpicommon; using namespace rkcommon; -Distributed::Distributed() {} +DistributedLoadBalancer::DistributedLoadBalancer() {} -Distributed::~Distributed() +DistributedLoadBalancer::~DistributedLoadBalancer() { handle.free(); } -void Distributed::renderFrame( +void DistributedLoadBalancer::renderFrame( FrameBuffer *_fb, Renderer *_renderer, Camera *camera, World *_world) { auto *dfb = dynamic_cast(_fb); @@ -48,7 +49,6 @@ void Distributed::renderFrame( "distributed renderer!"); } } - if (dfb->getLastRenderer() != renderer) { dfb->setTileOperation(renderer->tileOperation(), renderer); } @@ -60,20 +60,12 @@ void Distributed::renderFrame( #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); - } - } - const vec2i numTiles = dfb->getNumTiles(); + std::vector> regionTileIds(world->myRegionIds.size()); + const vec2i numTiles = dfb->getGlobalNumTiles(); const vec2i fbSize = dfb->getNumPixels(); - for (const auto &id : world->myRegionIds) { + for (size_t i = 0; i < world->myRegionIds.size(); ++i) { + const size_t id = world->myRegionIds[i]; const auto &r = world->allRegions[id]; box3f proj = camera->projectBox(r); box2f screenRegion(vec2f(proj.lower) * fbSize, vec2f(proj.upper) * fbSize); @@ -94,339 +86,438 @@ void Distributed::renderFrame( 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 uint32_t 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())); + // TODO: Can we do a better than round-robin over all tiles // assignment here? It could be that we end up not evenly dividing // the workload. const bool regionTileOwner = (tileIndex % numRegionOwners) == ownerRank; + + // If we're the owner and this tile isn't completed by adaptive + // refinement, we need to render it if (regionTileOwner) { - tilesForFrame.insert(tileIndex); + regionTileIds[i].push_back(tileIndex); } } } } + + // Set up the DFB sparse layers for each region we're rendering locally + // We need one SparseFB layer in the DFB per region we're rendering locally + dfb->setSparseFBLayerCount(world->myRegionIds.size()); + for (size_t i = 0; i < world->myRegionIds.size(); ++i) { + // Layer 0 is the base "background" tiles, regions are rendered to + // layers 1..# regions + 1 + auto *layer = dfb->getSparseFBLayer(i + 1); + // Check if this layer already stores the tiles we want, and if so don't + // reset it + const auto &layerTiles = layer->getTileIDs(); + // TODO: it'd be nice if we had some other change tracking that would let us + // know when we have different tiles rather than having to check the lists + // of IDs against each other. + // If this is a new FB, or the camera/scene has changed, we should set the + // new tiles because they've probably changed. If nothing in the scene is + // different from the previous render, then we don't need to set new tiles + // because we're just accumulating. + if (layerTiles.size() != regionTileIds[i].size() + || !std::equal( + layerTiles.begin(), layerTiles.end(), regionTileIds[i].begin())) { + layer->setTiles(regionTileIds[i]); + } + } + #ifdef ENABLE_PROFILING ProfilingPoint end = ProfilingPoint(); std::cout << "Initial tile for frame determination " << elapsedTimeMs(start, end) << "ms\n"; #endif -#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; - const vec2i tileID(tile_x, tile_y); - const int32 accumID = dfb->accumID(tileID); - const bool tileOwner = (tileIndex % workerSize()) == workerRank(); - const int NUM_JOBS = (TILE_SIZE * TILE_SIZE) / RENDERTILE_PIXELS_PER_JOB; - - const auto fbSize = dfb->getNumPixels(); - - Tile __aligned(64) bgtile(tileID, fbSize, accumID); - - // The visibility entries are sorted by the region id, matching - // the order of the allRegions vector. - bool *regionVisible = STACK_BUFFER(bool, numRegions); - std::fill(regionVisible, regionVisible + numRegions, false); - - // The first renderTile doesn't actually do any rendering, and instead - // just computes which tiles the region projects to, giving us the - // exact bounds of the region's projection onto the image - tasking::parallel_for(static_cast(NUM_JOBS), [&](size_t tIdx) { - renderer->computeRegionVisibility( - dfb, camera, world, regionVisible, perFrameData, bgtile, tIdx); - }); - - // If we own the tile send the background color and the count of - // children for the number of regions projecting to it that will be - // sent. - if (tileOwner) { - bgtile.sortOrder = std::numeric_limits::max(); - bgtile.generation = 0; - bgtile.children = 0; - // Note: not using std::count here as seems to not count properly in debug - // builds - for (size_t i = 0; i < numRegions; ++i) { - if (regionVisible[i]) { - ++bgtile.children; + // Note: Later this will be a set of tasks we enqueue at the same time and + // want to run in parallel to each other. For now this still runs as a + // parallel for here so we don't end up having to do a more sync/blocking + // style render + tasking::parallel_for(dfb->getSparseLayerCount(), [&](size_t layer) { + // Just render the background color and compute visibility information for + // the tiles we own for layer "0" + SparseFrameBuffer *sparseFb = dfb->getSparseFBLayer(layer); + + // Explicitly avoiding std::vector because we need to match ISPC's + // memory layout + const auto &tiles = sparseFb->getTiles(); + const auto &tileIDs = sparseFb->getTileIDs(); + + // We use uint8 instead of bool to avoid hitting UB with differing "true" + // values used by ISPC and C++ + std::vector regionVisible(numRegions * tiles.size(), 0); + + // Compute visibility for the tasks we're rendering + auto renderTaskIDs = sparseFb->getRenderTaskIDs(); + + renderer->computeRegionVisibility(sparseFb, + camera, + world, + regionVisible.data(), + perFrameData, + renderTaskIDs); + + // If we're rendering the background tiles send them over now + if (layer == 0) { + tasking::parallel_for(tiles.size(), [&](size_t i) { + // Don't send anything if this tile was finished due to adaptive + // refinement + if (dfb->tileError(tileIDs[i]) <= renderer->errorThreshold) { + return; } - } - dfb->setTile(bgtile); - } - // Render our regions that project to this tile and ship them off - // to the tile owner. - std::vector myVisibleRegions; - myVisibleRegions.reserve(world->myRegionIds.size()); - for (const auto &rid : world->myRegionIds) { - if (regionVisible[rid]) { - 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 - // pixels within the tiles, so adding another level may actually just - // give us worse cache coherence. -#define PARALLEL_REGION_RENDERING 1 -#if PARALLEL_REGION_RENDERING - tasking::parallel_for(myVisibleRegions.size(), [&](size_t vid) { - const size_t rid = myVisibleRegions[vid]; - Tile __aligned(64) tile(tileID, fbSize, accumID); -#else - for (const size_t &rid : myVisibleRegions) { - Tile &tile = bgtile; -#endif - tile.generation = 1; - tile.children = 0; - // If we share ownership of this region but aren't responsible - // for rendering it to this tile, don't render it. - // 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 &owners = world->regionOwners[rid]; - const size_t numRegionOwners = owners.size(); - const size_t ownerRank = - std::distance(owners.begin(), owners.find(workerRank())); - const bool regionTileOwner = (tileIndex % numRegionOwners) == ownerRank; - if (regionTileOwner) { - tasking::parallel_for(NUM_JOBS, [&](int tIdx) { - renderer->renderRegionToTile(dfb, - camera, - world, - world->allRegions[rid], - perFrameData, - tile, - tIdx); - }); - // Unused - // tile.sortOrder = sortOrder[rid]; - dfb->setTile(tile); - } -#if PARALLEL_REGION_RENDERING - }); -#else + // TODO: Would be nice to not copy here, but not sure about makign the + // tiles modifiable either in SparseFrameBuffer::getTile. + Tile bgtile = tiles[i]; + + bgtile.sortOrder = std::numeric_limits::max(); + bgtile.generation = 0; + bgtile.children = 0; + bgtile.accumID = dfb->getFrameID(); + for (size_t r = 0; r < numRegions; ++r) { + if (regionVisible[numRegions * i + r]) { + ++bgtile.children; + } + } + // Fill the tile with the background color + // TODO: Should replace this with a smaller metadata message so we don't + // need to send a full tile + std::fill( + bgtile.r, bgtile.r + TILE_SIZE * TILE_SIZE, renderer->bgColor.x); + std::fill( + bgtile.g, bgtile.g + TILE_SIZE * TILE_SIZE, renderer->bgColor.y); + std::fill( + bgtile.b, bgtile.b + TILE_SIZE * TILE_SIZE, renderer->bgColor.z); + std::fill( + bgtile.a, bgtile.a + TILE_SIZE * TILE_SIZE, renderer->bgColor.w); + std::fill(bgtile.z, + bgtile.z + TILE_SIZE * TILE_SIZE, + std::numeric_limits::infinity()); + dfb->setTile(bgtile); + }); + } else { + // If we're rendering a region, render it and send over the tile data + + // Remove any tasks for tiles that we found the region isn't actually + // visible to. The region projection is conservative in its bounds, so + // we can often remove a substantial number of tasks, resulting in better + // utilization. This also removes tasks that have completed due to + // adaptive refinement + const size_t rid = world->myRegionIds[layer - 1]; + std::vector activeTasks( + renderTaskIDs.begin(), renderTaskIDs.end()); + auto removeTasks = std::partition( + activeTasks.begin(), activeTasks.end(), [&](const uint32_t taskID) { + const uint32_t tileIdx = sparseFb->getTileIndexForTask(taskID); + return regionVisible[numRegions * tileIdx + rid] + && dfb->tileError(tileIDs[tileIdx]) > renderer->errorThreshold; + }); + activeTasks.erase(removeTasks, activeTasks.end()); + + renderer->renderRegionTasks(sparseFb, + camera, + world, + world->allRegions[rid], + perFrameData, + utility::ArrayView(activeTasks)); + + tasking::parallel_for(tiles.size(), [&](size_t i) { + if (!regionVisible[numRegions * i + rid] + || dfb->tileError(tileIDs[i]) <= renderer->errorThreshold) { + return; + } + // TODO: Would be nice to not copy here, but not sure about making + // the tiles modifiable either in SparseFrameBuffer::getTile. + Tile regionTile = tiles[i]; + + regionTile.generation = 1; + regionTile.children = 0; + regionTile.accumID = dfb->getFrameID(); + dfb->setTile(regionTile); + }); } -#endif }); -#ifdef ENABLE_PROFILING - end = ProfilingPoint(); - std::cout << "Local rendering for frame " << elapsedTimeMs(start, end) - << "ms\n"; -#endif dfb->waitUntilFinished(); renderer->endFrame(dfb, perFrameData); dfb->endFrame(renderer->errorThreshold, camera); -} // end func +} -// *************************************************************************** -void Distributed::renderFrameReplicated(DistributedFrameBuffer *fb, +void DistributedLoadBalancer::renderFrameReplicated(DistributedFrameBuffer *dfb, Renderer *renderer, Camera *camera, DistributedWorld *world) { - bool askedForWork = false; - int enableStaticBalancer; + int enableStaticBalancer = 0; auto OSPRAY_STATIC_BALANCER = utility::getEnvVar("OSPRAY_STATIC_BALANCER"); enableStaticBalancer = OSPRAY_STATIC_BALANCER.value_or(0); std::shared_ptr tileOperation = nullptr; - if (fb->getLastRenderer() != renderer) { + if (dfb->getLastRenderer() != renderer) { tileOperation = std::make_shared(); - fb->setTileOperation(tileOperation, renderer); + dfb->setTileOperation(tileOperation, renderer); } else { - tileOperation = fb->getTileOperation(); + tileOperation = dfb->getTileOperation(); } #ifdef ENABLE_PROFILING ProfilingPoint start; #endif - fb->startNewFrame(renderer->errorThreshold); - void *perFrameData = renderer->beginFrame(fb, world); + dfb->startNewFrame(renderer->errorThreshold); + void *perFrameData = renderer->beginFrame(dfb, world); #ifdef ENABLE_PROFILING ProfilingPoint end; std::cout << "Start new frame took: " << elapsedTimeMs(start, end) << "ms\n"; #endif - const auto fbSize = fb->getNumPixels(); + if (enableStaticBalancer) { + renderFrameReplicatedStaticLB(dfb, renderer, camera, world, perFrameData); + } else { + renderFrameReplicatedDynamicLB(dfb, renderer, camera, world, perFrameData); + } + +#ifdef ENABLE_PROFILING + end = ProfilingPoint(); + std::cout << "Render loop took: " << elapsedTimeMs(start, end) + << "ms, CPU %: " << cpuUtilization(start, end) << "%\n"; + + start = ProfilingPoint(); +#endif + + dfb->waitUntilFinished(); + +#ifdef ENABLE_PROFILING + end = ProfilingPoint(); + std::cout << "Wait finished took: " << elapsedTimeMs(start, end) + << "ms, CPU %: " << cpuUtilization(start, end) << "%\n"; + + start = ProfilingPoint(); +#endif + + renderer->endFrame(dfb, perFrameData); + dfb->endFrame(renderer->errorThreshold, camera); + +#ifdef ENABLE_PROFILING + end = ProfilingPoint(); + std::cout << "End frame took: " << elapsedTimeMs(start, end) + << "ms, CPU %: " << cpuUtilization(start, end) << "%\n"; +#endif +} - const int ALLTASKS = fb->getTotalTiles(); - int NTASKS = ALLTASKS / workerSize(); +std::string DistributedLoadBalancer::toString() const +{ + return "ospray::mpi::Distributed"; +} + +void DistributedLoadBalancer::setObjectHandle(ObjectHandle &handle_) +{ + handle = handle_; +} + +void DistributedLoadBalancer::renderFrameReplicatedDynamicLB( + DistributedFrameBuffer *dfb, + Renderer *renderer, + Camera *camera, + DistributedWorld *world, + void *perFrameData) +{ + bool askedForWork = false; + + const int ALLTILES = dfb->getGlobalTotalTiles(); + int NTILES = ALLTILES / workerSize(); // NOTE(jda) - If all tiles do not divide evenly among all worker ranks - // (a.k.a. ALLTASKS / worker.size has a remainder), then - // some ranks will have one extra tile to do. Thus NTASKS + // (a.k.a. ALLTILES / worker.size has a remainder), then + // some ranks will have one extra tile to do. Thus NTILES // is incremented if we are one of those ranks. - if ((ALLTASKS % workerSize()) > workerRank()) - NTASKS++; + if ((ALLTILES % workerSize()) > workerRank()) + NTILES++; - // do not pass all tasks at once, this way if other ranks want to steal work, + // Do not pass all tiles at once, this way if other ranks want to steal work, // they can - int maxTasksPerRound = 20; - int numRounds = std::max(NTASKS / maxTasksPerRound, 1); - int tasksPerRound = NTASKS / numRounds; - int remainTasks = NTASKS % numRounds; - int terminatedTasks = 0; - int minActiveTasks = (ALLTASKS / workerSize()) * 0.25; - - std::unique_ptr dynamicLB = - make_unique(handle, ALLTASKS); - - mpicommon::barrier(fb->getMPIGroup().comm).wait(); - int totalActiveTasks = ALLTASKS; + const int maxTilesPerRound = 20; + const int numRounds = std::max(NTILES / maxTilesPerRound, 1); + const int tilesPerRound = NTILES / numRounds; + const int remainTiles = NTILES % numRounds; + const int minActiveTiles = (ALLTILES / workerSize()) * 0.25; + int terminatedTiles = 0; + + auto dynamicLB = make_unique(handle, ALLTILES); + + mpicommon::barrier(dfb->getMPIGroup().comm).wait(); + int totalActiveTiles = ALLTILES; // push current work to workQueue for (int i = 0; i < numRounds; i++) { Work myWork; - myWork.ntasks = tasksPerRound; - myWork.offset = i * tasksPerRound; + myWork.ntasks = tilesPerRound; + myWork.offset = i * tilesPerRound; myWork.ownerRank = workerRank(); dynamicLB->addWork(myWork); } - // Extra round for any remainder tasks - if (remainTasks > 0) { + // Extra round for any remainder tiles + if (remainTiles > 0) { Work myWork; - myWork.ntasks = remainTasks; - myWork.offset = numRounds * tasksPerRound; + myWork.ntasks = remainTiles; + myWork.offset = numRounds * tilesPerRound; myWork.ownerRank = workerRank(); dynamicLB->addWork(myWork); } + #ifdef ENABLE_PROFILING start = ProfilingPoint(); #endif - /* TODO WILL: This can dispatch back to LocalTiledLoadBalancer::renderTiles - * to render the tiles instead of repeating this loop here ourselves. - */ - - while (0 < totalActiveTasks) { - int currentTasks = 0; - int offset = 0; - int ownerRank; - if (0 < dynamicLB->getWorkSize()) { - Work currWorkItem = dynamicLB->getWorkItemFront(); - currentTasks = currWorkItem.ntasks; - offset = currWorkItem.offset; - ownerRank = currWorkItem.ownerRank; - askedForWork = false; - } + const int sparseFbChannelFlags = + dfb->getChannelFlags() & ~(OSP_FB_ACCUM | OSP_FB_VARIANCE); + const bool sparseFbTrackAccumIDs = dfb->getChannelFlags() & OSP_FB_ACCUM; - if (0 < currentTasks) { - tasking::parallel_for(currentTasks, [&](int taskIndex) { - const size_t tileID = (taskIndex + offset) * workerSize() + ownerRank; - const size_t numTiles_x = fb->getNumTiles().x; - const size_t tile_y = tileID / numTiles_x; - const size_t tile_x = tileID - tile_y * numTiles_x; - const vec2i tileId(tile_x, tile_y); - const int32 accumID = fb->accumID(tileId); + auto sparseFb = rkcommon::make_unique(dfb->getNumPixels(), + dfb->getColorBufferFormat(), + sparseFbChannelFlags, + sparseFbTrackAccumIDs); - if (fb->tileError(tileId) <= renderer->errorThreshold) - return; - -#if TILE_SIZE > MAX_TILE_SIZE - auto tilePtr = make_unique(tileId, fbSize, accumID); - auto &tile = *tilePtr; -#else - Tile __aligned(64) tile(tileId, fbSize, accumID); -#endif + while (0 < totalActiveTiles) { + Work currentWorkItem; + if (0 < dynamicLB->getWorkSize()) { + currentWorkItem = dynamicLB->getWorkItemFront(); + askedForWork = false; + } - if (!fb->frameCancelled()) { - tasking::parallel_for( - numJobs(renderer->spp, accumID), [&](size_t tid) { - renderer->renderTile( - fb, camera, world, perFrameData, tile, tid); - }); + if (0 < currentWorkItem.ntasks) { + // Allocate a sparse framebuffer to hold the render output data + std::vector taskTileIDs; + taskTileIDs.reserve(currentWorkItem.ntasks); + for (int i = 0; i < currentWorkItem.ntasks; ++i) { + const int tileID = (i + currentWorkItem.offset) * workerSize() + + currentWorkItem.ownerRank; + // Only render tiles if they haven't reached the error threshold + if (dfb->tileError(tileID) > renderer->errorThreshold) { + taskTileIDs.push_back(tileID); + } + } + sparseFb->setTiles(taskTileIDs); + + // Set the right accumID for the tiles we're going to render + // TODO: would be nice if there was a more efficient way to run this as + // well. + if (sparseFbTrackAccumIDs) { + for (uint32_t i = 0; i < sparseFb->getTotalRenderTasks(); ++i) { + sparseFb->setTaskAccumID(i, dfb->getFrameID()); } + } - fb->setTile(tile); + renderer->renderTasks(sparseFb.get(), + camera, + world, + perFrameData, + sparseFb->getRenderTaskIDs()); + + // TODO: Now the tile setting happens as a bulk-sync operation after + // rendering, because we still need to send them through the compositing + // pipeline. The ISPC-side rendering code doesn't know about this and in + // the future wouldn't be able to do it + // One option with the Dynamic LB would be to at least ping-poing + // sparseFb's, one is being rendered into while tiles from the previous + // task set are sent out + const auto &tiles = sparseFb->getTiles(); + tasking::serial_for(tiles.size(), [&](size_t i) { + // TODO: Same note as distributed case, would be nice here to not have + // to copy the tile to change the accum ID. + Tile tile = tiles[i]; + tile.accumID = dfb->getFrameID(); + dfb->setTile(tile); }); + dynamicLB->sendTerm(currentWorkItem.ntasks); + terminatedTiles = terminatedTiles + currentWorkItem.ntasks; + } + + if (0 < terminatedTiles) { + dynamicLB->updateActiveTasks(terminatedTiles); } - dynamicLB->sendTerm(currentTasks); - terminatedTasks = terminatedTasks + currentTasks; - - if (0 < terminatedTasks) - dynamicLB->updateActiveTasks(terminatedTasks); - totalActiveTasks = dynamicLB->getActiveTasks(); - terminatedTasks = 0; - - // if the total active tasks over all workers is more than some min, request - // work - if (currentTasks <= 0 && minActiveTasks < totalActiveTasks && !askedForWork - && !enableStaticBalancer) { + + totalActiveTiles = dynamicLB->getActiveTasks(); + terminatedTiles = 0; + + // if the total active tiles over all workers is more than some min, + // request work + if (currentWorkItem.ntasks <= 0 && minActiveTiles < totalActiveTiles + && !askedForWork) { dynamicLB->requestWork(); askedForWork = true; } } -#ifdef ENABLE_PROFILING - end = ProfilingPoint(); - std::cout << "Render loop took: " << elapsedTimeMs(start, end) - << "ms, CPU %: " << cpuUtilization(start, end) << "%\n"; - - start = ProfilingPoint(); -#endif - - fb->waitUntilFinished(); - -#ifdef ENABLE_PROFILING - end = ProfilingPoint(); - std::cout << "Wait finished took: " << elapsedTimeMs(start, end) - << "ms, CPU %: " << cpuUtilization(start, end) << "%\n"; - - start = ProfilingPoint(); -#endif - - renderer->endFrame(fb, perFrameData); - fb->endFrame(renderer->errorThreshold, camera); - -#ifdef ENABLE_PROFILING - end = ProfilingPoint(); - std::cout << "End frame took: " << elapsedTimeMs(start, end) - << "ms, CPU %: " << cpuUtilization(start, end) << "%\n"; -#endif + // We need to wait for the other ranks to finish here to keep our local DLB + // alive to respond to any work requests that come in while other ranks finish + // their final local set of tasks + mpicommon::barrier(dfb->getMPIGroup().comm).wait(); } -// *************************************************************************** -std::string Distributed::toString() const +void DistributedLoadBalancer::renderFrameReplicatedStaticLB( + DistributedFrameBuffer *dfb, + Renderer *renderer, + Camera *camera, + DistributedWorld *world, + void *perFrameData) { - return "ospray::mpi::staticLoadBalancer::Distributed"; -} + SparseFrameBuffer *ownedTilesFb = dfb->getSparseFBLayer(0); + + const auto &tiles = ownedTilesFb->getTiles(); + const auto &tileIDs = ownedTilesFb->getTileIDs(); + auto renderTaskIDs = ownedTilesFb->getRenderTaskIDs(); + + if (renderer->errorThreshold > 0.f) { + std::vector activeTasks; + for (auto &i : renderTaskIDs) { + const uint32_t tileID = tileIDs[ownedTilesFb->getTileIndexForTask(i)]; + const float error = dfb->tileError(tileID); + if (error > renderer->errorThreshold) { + activeTasks.push_back(i); + } + } -void Distributed::setObjectHandle(ObjectHandle &handle_) -{ - handle = handle_; + renderer->renderTasks(ownedTilesFb, + camera, + world, + perFrameData, + utility::ArrayView(activeTasks)); + } else { + renderer->renderTasks( + ownedTilesFb, camera, world, perFrameData, renderTaskIDs); + } + + // TODO: Now the tile setting happens as a bulk-sync operation after + // rendering, because we still need to send them through the compositing + // pipeline. The ISPC-side rendering code doesn't know about this and in the + // future wouldn't be able to do it + tasking::parallel_for(tiles.size(), [&](size_t i) { + // Don't send anything if this tile was finished due to adaptive + // refinement + if (dfb->tileError(tileIDs[i]) <= renderer->errorThreshold) { + return; + } + dfb->setTile(tiles[i]); + }); } -void Distributed::renderTiles(FrameBuffer *, + +void DistributedLoadBalancer::runRenderTasks(FrameBuffer *, Renderer *, Camera *, World *, - const utility::ArrayView &, + const utility::ArrayView &, void *) { NOT_IMPLEMENTED; } -} // namespace staticLoadBalancer } // namespace mpi } // namespace ospray diff --git a/modules/mpi/ospray/render/DistributedLoadBalancer.h b/modules/mpi/ospray/render/DistributedLoadBalancer.h index bd9ff107b6..97519aee67 100644 --- a/modules/mpi/ospray/render/DistributedLoadBalancer.h +++ b/modules/mpi/ospray/render/DistributedLoadBalancer.h @@ -1,10 +1,8 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once -#include "../common/DistributedWorld.h" -#include "../common/DynamicLoadBalancer.h" #include "../fb/DistributedFrameBuffer.h" #include "camera/Camera.h" #include "common/World.h" @@ -12,7 +10,8 @@ namespace ospray { namespace mpi { -namespace staticLoadBalancer { + +struct DistributedWorld; /* The distributed load balancer manages both data and image * parallel distributed rendering, based on the renderer and @@ -20,10 +19,10 @@ namespace staticLoadBalancer { * rendering, while a non-distributed renderer with a world with * one global region will give image-parallel rendering */ -struct Distributed : public TiledLoadBalancer +struct DistributedLoadBalancer : public TiledLoadBalancer { - Distributed(); - ~Distributed() override; + DistributedLoadBalancer(); + ~DistributedLoadBalancer() override; void renderFrame(FrameBuffer *fb, Renderer *renderer, Camera *camera, @@ -41,19 +40,30 @@ struct Distributed : public TiledLoadBalancer * the actual tile list rendering after computing the list of tiles * to be rendered by this rank in renderFrame */ - void renderTiles(FrameBuffer *fb, + void runRenderTasks(FrameBuffer *fb, Renderer *renderer, Camera *camera, World *world, - const utility::ArrayView &tileIDs, + const utility::ArrayView &renderTaskIDs, void *perFrameData) override; std::string toString() const override; private: + void renderFrameReplicatedDynamicLB(DistributedFrameBuffer *dfb, + Renderer *renderer, + Camera *camera, + DistributedWorld *world, + void *perFrameData); + + void renderFrameReplicatedStaticLB(DistributedFrameBuffer *dfb, + Renderer *renderer, + Camera *camera, + DistributedWorld *world, + void *perFrameData); + ObjectHandle handle; }; -} // namespace staticLoadBalancer } // namespace mpi } // namespace ospray diff --git a/modules/mpi/ospray/render/ThreadedRenderTask.h b/modules/mpi/ospray/render/ThreadedRenderTask.h index 61d4ebd2ae..0e90f02717 100644 --- a/modules/mpi/ospray/render/ThreadedRenderTask.h +++ b/modules/mpi/ospray/render/ThreadedRenderTask.h @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -17,7 +17,7 @@ namespace mpi { struct ThreadedRenderTask : public Future { ThreadedRenderTask(FrameBuffer *, - const std::shared_ptr &, + const std::shared_ptr &, std::function fcn); ~ThreadedRenderTask() override; @@ -31,7 +31,7 @@ struct ThreadedRenderTask : public Future private: Ref fb; - std::shared_ptr loadBalancer; + std::shared_ptr loadBalancer; std::atomic taskDuration{0.f}; std::atomic finished; std::thread thread; @@ -40,7 +40,7 @@ struct ThreadedRenderTask : public Future // Inlined definitions ////////////////////////////////////////////////////// inline ThreadedRenderTask::ThreadedRenderTask(FrameBuffer *_fb, - const std::shared_ptr &_loadBalancer, + const std::shared_ptr &_loadBalancer, std::function fcn) : fb(_fb), loadBalancer(_loadBalancer), finished(false) { diff --git a/modules/mpi/ospray/render/WriteMultipleTileOperation.cpp b/modules/mpi/ospray/render/WriteMultipleTileOperation.cpp index 934fb299e1..d4e20b0083 100644 --- a/modules/mpi/ospray/render/WriteMultipleTileOperation.cpp +++ b/modules/mpi/ospray/render/WriteMultipleTileOperation.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "WriteMultipleTileOperation.h" @@ -22,14 +22,14 @@ struct LiveWriteMultipleTile : public LiveTileOperation void newFrame() override; // accumulate into ACCUM and VARIANCE, and for last tile read-out - void process(const ospray::Tile &tile) override; + void process(const ispc::Tile &tile) override; private: int maxAccumID = 0; size_t instances = 1; bool writeOnceTile = true; // defer accumulation to get correct variance estimate - ospray::Tile bufferedTile; + ispc::Tile bufferedTile; bool tileBuffered = false; WriteMultipleTileOperation *parent = nullptr; // serialize when multiple instances of this tile arrive at the same time @@ -52,7 +52,7 @@ void LiveWriteMultipleTile::newFrame() tileBuffered = false; } -void LiveWriteMultipleTile::process(const ospray::Tile &tile) +void LiveWriteMultipleTile::process(const ispc::Tile &tile) { if (writeOnceTile) { finished.region = tile.region; @@ -78,7 +78,7 @@ void LiveWriteMultipleTile::process(const ospray::Tile &tile) std::lock_guard lock(mutex); maxAccumID = std::max(maxAccumID, tile.accumID); if (!tileBuffered && (tile.accumID & 1) == 0) { - memcpy(&bufferedTile, &tile, sizeof(ospray::Tile)); + memcpy(&bufferedTile, &tile, sizeof(ispc::Tile)); tileBuffered = true; } else { ispc::DFB_accumulateTileSimple((const ispc::VaryingTile *)&tile, @@ -141,7 +141,7 @@ void LiveWriteMultipleTile::process(const ospray::Tile &tile) void WriteMultipleTileOperation::attach(DistributedFrameBuffer *dfb) { mpiGroup = mpicommon::worker.dup(); - tileInstances.resize(dfb->getTotalTiles(), 1); + tileInstances.resize(dfb->getGlobalTotalTiles(), 1); } std::unique_ptr WriteMultipleTileOperation::makeTile( diff --git a/modules/mpi/ospray/render/WriteMultipleTileOperation.h b/modules/mpi/ospray/render/WriteMultipleTileOperation.h index d154200558..9bdf597bc5 100644 --- a/modules/mpi/ospray/render/WriteMultipleTileOperation.h +++ b/modules/mpi/ospray/render/WriteMultipleTileOperation.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/mpi/ospray/render/distributed/AlphaCompositeTileOperation.cpp b/modules/mpi/ospray/render/distributed/AlphaCompositeTileOperation.cpp index de35712700..046875d32b 100644 --- a/modules/mpi/ospray/render/distributed/AlphaCompositeTileOperation.cpp +++ b/modules/mpi/ospray/render/distributed/AlphaCompositeTileOperation.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "AlphaCompositeTileOperation.h" @@ -10,7 +10,7 @@ namespace ospray { struct BufferedTile { - ospray::Tile tile; + ispc::Tile tile; /*! determines order of this tile relative to other tiles. Tiles will get blended with the 'over' operator in @@ -30,13 +30,13 @@ struct LiveAlphaCompositeTile : public LiveTileOperation void newFrame() override; - void process(const ospray::Tile &tile) override; + void process(const ispc::Tile &tile) override; private: std::vector> bufferedTiles; - int currentGeneration; - int expectedInNextGeneration; - int missingInCurrentGeneration; + int currentGeneration{0}; + int expectedInNextGeneration{0}; + int missingInCurrentGeneration{1}; std::mutex mutex; void reportCompositingError(const vec2i &tile); @@ -63,7 +63,7 @@ void LiveAlphaCompositeTile::newFrame() } } -void LiveAlphaCompositeTile::process(const ospray::Tile &tile) +void LiveAlphaCompositeTile::process(const ispc::Tile &tile) { std::lock_guard lock(mutex); { @@ -139,9 +139,9 @@ void LiveAlphaCompositeTile::reportCompositingError(const vec2i &tile) { std::stringstream str; str << "negative missing on " << mpicommon::workerRank() - << ", missing = " << missingInCurrentGeneration - << ", expectedInNex = " << expectedInNextGeneration - << ", current generation = " << currentGeneration << ", tile = " << tile; + << ", missingInCurrent = " << missingInCurrentGeneration + << ", expectedInNext = " << expectedInNextGeneration + << ", currentGeneration = " << currentGeneration << ", tile = " << tile; handleError(OSP_INVALID_OPERATION, str.str()); } diff --git a/modules/mpi/ospray/render/distributed/AlphaCompositeTileOperation.h b/modules/mpi/ospray/render/distributed/AlphaCompositeTileOperation.h index 3e7d23ed93..907fc51c56 100644 --- a/modules/mpi/ospray/render/distributed/AlphaCompositeTileOperation.h +++ b/modules/mpi/ospray/render/distributed/AlphaCompositeTileOperation.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/mpi/ospray/render/distributed/DistributedRaycast.cpp b/modules/mpi/ospray/render/distributed/DistributedRaycast.cpp index 90562dcbb1..0d0b77d187 100644 --- a/modules/mpi/ospray/render/distributed/DistributedRaycast.cpp +++ b/modules/mpi/ospray/render/distributed/DistributedRaycast.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include @@ -17,7 +17,7 @@ #include "../../fb/DistributedFrameBuffer.h" #include "AlphaCompositeTileOperation.h" #include "DistributedRaycast.h" - +// ispc exports #include "render/distributed/DistributedRaycast_ispc.h" namespace ospray { @@ -32,7 +32,7 @@ static bool DETAILED_LOGGING = false; DistributedRaycastRenderer::DistributedRaycastRenderer() : mpiGroup(mpicommon::worker.dup()) { - ispcEquivalent = ispc::DistributedRaycastRenderer_create(); + getSh()->super.renderRegionSample = ispc::DRR_renderRegionSample_addr(); DETAILED_LOGGING = utility::getEnvVar("OSPRAY_DP_API_TRACING").value_or(0); @@ -57,11 +57,12 @@ void DistributedRaycastRenderer::commit() { Renderer::commit(); - ispc::DistributedRaycastRenderer_set(getIE(), - getParam("aoSamples", 0), - getParam("aoDistance", getParam("aoRadius", 1e20f)), - getParam("shadows", getParam("shadowsEnabled", 0)), - getParam("volumeSamplingRate", 1.f)); + getSh()->aoSamples = getParam("aoSamples", 0); + getSh()->aoRadius = + getParam("aoDistance", getParam("aoRadius", 1e20f)); + getSh()->shadowsEnabled = + getParam("shadows", getParam("shadowsEnabled", 0)); + getSh()->volumeSamplingRate = getParam("volumeSamplingRate", 1.f); } std::shared_ptr DistributedRaycastRenderer::tileOperation() diff --git a/modules/mpi/ospray/render/distributed/DistributedRaycast.h b/modules/mpi/ospray/render/distributed/DistributedRaycast.h index a42ccdeec8..a54d904694 100644 --- a/modules/mpi/ospray/render/distributed/DistributedRaycast.h +++ b/modules/mpi/ospray/render/distributed/DistributedRaycast.h @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -10,6 +10,8 @@ #include "DistributedRenderer.h" #include "camera/PerspectiveCamera.h" #include "common/MPICommon.h" +// ispc shared +#include "DistributedRaycastShared.h" namespace ospray { namespace mpi { @@ -25,7 +27,8 @@ namespace mpi { * Also see apps/ospRandSciVisTest.cpp and apps/ospRandSphereTest.cpp for * example usage. */ -struct DistributedRaycastRenderer : public DistributedRenderer +struct DistributedRaycastRenderer : public AddStructShared { DistributedRaycastRenderer(); virtual ~DistributedRaycastRenderer() override; diff --git a/modules/mpi/ospray/render/distributed/DistributedRaycast.ispc b/modules/mpi/ospray/render/distributed/DistributedRaycast.ispc index 0800f6e962..c1501e7ab5 100644 --- a/modules/mpi/ospray/render/distributed/DistributedRaycast.ispc +++ b/modules/mpi/ospray/render/distributed/DistributedRaycast.ispc @@ -1,8 +1,6 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "../../common/DistributedWorld.ih" -#include "DistributedRenderer.ih" #include "common/Instance.ih" #include "common/World.ih" #include "math/random.ih" @@ -13,15 +11,12 @@ #include "render/scivis/volumes.ih" #include "render/util.ih" #include "rkcommon/math/box.ih" - -struct DistributedRaycastRenderer -{ - DistributedRenderer super; - int aoSamples; - float aoRadius; - bool shadowsEnabled; - float volumeSamplingRate; -}; +#include "volume/VolumetricModel.ih" +// c++ shared +#include "../../common/DistributedWorldShared.h" +#include "DistributedRaycastShared.h" +#include "fb/FrameBufferShared.h" +#include "fb/SparseFBShared.h" // The distributed raycast renderer uses its own volume interval integration // because we want to apply the jitter before offsetting our step size to stay @@ -219,7 +214,7 @@ vec4f DRR_shadeSurface(const DistributedRaycastRenderer *uniform self, } void DRR_renderRegionSample(DistributedRenderer *uniform _self, - FrameBuffer *uniform fb, + SparseFB *uniform fb, DistributedWorld *uniform world, const box3f *uniform region, const vec2f ®ionInterval, @@ -270,8 +265,8 @@ void DRR_renderRegionSample(DistributedRenderer *uniform _self, geomRay, DG_NG | DG_NS | DG_NORMALIZE | DG_FACEFORWARD | DG_COLOR | DG_TEXCOORD); - surfaceColor = - DRR_shadeSurface(self, fb, world, sample.sampleID, geomRay, dg); + surfaceColor = DRR_shadeSurface( + self, &fb->super, world, sample.sampleID, geomRay, dg); } // Always just integrate the volume when it comes in front of the geometry @@ -345,30 +340,7 @@ void DRR_renderRegionSample(DistributedRenderer *uniform _self, // Exported functions ///////////////////////////////////////////////////////// -export void *uniform DistributedRaycastRenderer_create() +export void *uniform DRR_renderRegionSample_addr() { - DistributedRaycastRenderer *uniform self = - uniform new uniform DistributedRaycastRenderer; - - DistributedRenderer_Constructor(&self->super); - self->super.renderRegionSample = DRR_renderRegionSample; - self->aoSamples = 0; - self->shadowsEnabled = false; - - return self; -} - -export void DistributedRaycastRenderer_set(void *uniform _self, - const uniform int aoSamples, - const uniform float aoRadius, - const uniform bool shadowsEnabled, - const uniform float volumeSamplingRate) -{ - DistributedRaycastRenderer *uniform self = - (DistributedRaycastRenderer * uniform) _self; - - self->aoSamples = aoSamples; - self->aoRadius = aoRadius; - self->shadowsEnabled = shadowsEnabled; - self->volumeSamplingRate = volumeSamplingRate; + return DRR_renderRegionSample; } diff --git a/modules/mpi/ospray/render/distributed/DistributedRaycastShared.h b/modules/mpi/ospray/render/distributed/DistributedRaycastShared.h new file mode 100644 index 0000000000..980cf165c6 --- /dev/null +++ b/modules/mpi/ospray/render/distributed/DistributedRaycastShared.h @@ -0,0 +1,31 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "DistributedRendererShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +struct DistributedRaycastRenderer +{ + DistributedRenderer super; + int aoSamples; + float aoRadius; + bool shadowsEnabled; + float volumeSamplingRate; + +#ifdef __cplusplus + DistributedRaycastRenderer() + : aoSamples(0), + aoRadius(1e20f), + shadowsEnabled(false), + volumeSamplingRate(1.f) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/mpi/ospray/render/distributed/DistributedRenderer.cpp b/modules/mpi/ospray/render/distributed/DistributedRenderer.cpp index 53c524bdf7..14addee628 100644 --- a/modules/mpi/ospray/render/distributed/DistributedRenderer.cpp +++ b/modules/mpi/ospray/render/distributed/DistributedRenderer.cpp @@ -1,57 +1,63 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "DistributedRenderer.h" -#include "render/distributed/DistributedRenderer_ispc.h" +#include "../../common/DistributedWorld.h" +#include "common/Instance.h" #include "geometry/GeometricModel.h" +// ispc exports +#include "render/distributed/DistributedRenderer_ispc.h" namespace ospray { namespace mpi { DistributedRenderer::DistributedRenderer() : mpiGroup(mpicommon::worker.dup()) -{} +{ + getSh()->computeRegionVisibility = + ispc::DR_default_computeRegionVisibility_addr(); + getSh()->renderRegionSample = ispc::DR_default_renderRegionSample_addr(); + getSh()->renderRegionToTile = ispc::DR_default_renderRegionToTile_addr(); +} DistributedRenderer::~DistributedRenderer() { MPI_Comm_free(&mpiGroup.comm); } -void DistributedRenderer::computeRegionVisibility(DistributedFrameBuffer *fb, +void DistributedRenderer::computeRegionVisibility(SparseFrameBuffer *fb, Camera *camera, DistributedWorld *world, - bool *regionVisible, + uint8_t *regionVisible, void *perFrameData, - Tile &tile, - size_t jobID) const + const utility::ArrayView &taskIDs) const { // TODO this needs an exported function - ispc::DistributedRenderer_computeRegionVisibility(getIE(), - fb->getIE(), - camera->getIE(), - world->getIE(), + ispc::DistributedRenderer_computeRegionVisibility(getSh(), + fb->getSh(), + camera->getSh(), + world->getSh(), regionVisible, perFrameData, - (ispc::Tile &)tile, - jobID); + taskIDs.data(), + taskIDs.size()); } -void DistributedRenderer::renderRegionToTile(DistributedFrameBuffer *fb, +void DistributedRenderer::renderRegionTasks(SparseFrameBuffer *fb, Camera *camera, DistributedWorld *world, const box3f ®ion, void *perFrameData, - Tile &tile, - size_t jobID) const + const utility::ArrayView &taskIDs) const { // TODO: exported fcn - ispc::DistributedRenderer_renderRegionToTile(getIE(), - fb->getIE(), - camera->getIE(), - world->getIE(), + ispc::DistributedRenderer_renderRegionToTile(getSh(), + fb->getSh(), + camera->getSh(), + world->getSh(), ®ion, perFrameData, - (ispc::Tile &)tile, - jobID); + taskIDs.data(), + taskIDs.size()); } OSPPickResult DistributedRenderer::pick( @@ -61,18 +67,18 @@ OSPPickResult DistributedRenderer::pick( res.instance = nullptr; res.model = nullptr; - res.primID = -1; + res.primID = RTC_INVALID_GEOMETRY_ID; res.hasHit = false; - int instID = -1; - int geomID = -1; - int primID = -1; + int instID = RTC_INVALID_GEOMETRY_ID; + int geomID = RTC_INVALID_GEOMETRY_ID; + int primID = RTC_INVALID_GEOMETRY_ID; float depth = 1e20f; - ispc::DistributedRenderer_pick(getIE(), - fb->getIE(), - camera->getIE(), - world->getIE(), + ispc::DistributedRenderer_pick(getSh(), + fb->getSh(), + camera->getSh(), + world->getSh(), (const ispc::vec2f &)screenPos, (ispc::vec3f &)res.worldPosition[0], instID, diff --git a/modules/mpi/ospray/render/distributed/DistributedRenderer.h b/modules/mpi/ospray/render/distributed/DistributedRenderer.h index 382589dff8..41aced1dcd 100644 --- a/modules/mpi/ospray/render/distributed/DistributedRenderer.h +++ b/modules/mpi/ospray/render/distributed/DistributedRenderer.h @@ -1,44 +1,46 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once -#include "../../common/DistributedWorld.h" #include "../../fb/DistributedFrameBuffer.h" #include "../../fb/TileOperation.h" #include "camera/Camera.h" #include "render/Renderer.h" +// ispc shared +#include "DistributedRendererShared.h" namespace ospray { namespace mpi { +struct DistributedWorld; + struct RegionInfo { int numRegions = 0; box3f *regions = nullptr; - bool *regionVisible = nullptr; + uint8_t *regionVisible = nullptr; }; -struct DistributedRenderer : public Renderer +struct DistributedRenderer + : public AddStructShared { DistributedRenderer(); ~DistributedRenderer() override; - void computeRegionVisibility(DistributedFrameBuffer *fb, + void computeRegionVisibility(SparseFrameBuffer *fb, Camera *camera, DistributedWorld *world, - bool *regionVisible, + uint8_t *regionVisible, void *perFrameData, - Tile &tile, - size_t jobID) const; + const utility::ArrayView &taskIDs) const; - void renderRegionToTile(DistributedFrameBuffer *fb, + void renderRegionTasks(SparseFrameBuffer *fb, Camera *camera, DistributedWorld *world, const box3f ®ion, void *perFrameData, - Tile &tile, - size_t jobID) const; + const utility::ArrayView &taskIDs) const; virtual std::shared_ptr tileOperation() = 0; diff --git a/modules/mpi/ospray/render/distributed/DistributedRenderer.ih b/modules/mpi/ospray/render/distributed/DistributedRenderer.ih deleted file mode 100644 index 03d5ee3792..0000000000 --- a/modules/mpi/ospray/render/distributed/DistributedRenderer.ih +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2009-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "camera/Camera.ih" -#include "common/DistributedWorld.ih" -#include "fb/FrameBuffer.ih" -#include "fb/Tile.ih" -#include "render/Renderer.ih" - -struct DistributedRenderer; - -typedef unmasked void (*DR_ComputeRegionVisibility)( - DistributedRenderer *uniform self, - FrameBuffer *uniform fb, - Camera *uniform camera, - DistributedWorld *uniform world, - bool *uniform regionVisible, - void *uniform perFrameData, - uniform Tile &tile, - uniform int taskIndex); - -typedef void (*DR_RenderRegionSampleFct)(DistributedRenderer *uniform self, - FrameBuffer *uniform fb, - DistributedWorld *uniform world, - const box3f *uniform region, - const vec2f ®ionInterval, - void *uniform perFrameData, - varying ScreenSample &sample); - -typedef unmasked void (*DR_RenderRegionTileFct)( - DistributedRenderer *uniform self, - FrameBuffer *uniform fb, - Camera *uniform camera, - DistributedWorld *uniform world, - const box3f *uniform region, - void *uniform perFrameData, - uniform Tile &tile, - uniform int taskIndex); - -struct DistributedRenderer -{ - Renderer super; - - DR_ComputeRegionVisibility computeRegionVisibility; - DR_RenderRegionSampleFct renderRegionSample; - DR_RenderRegionTileFct renderRegionToTile; -}; - -void DistributedRenderer_Constructor(uniform DistributedRenderer *uniform self); diff --git a/modules/mpi/ospray/render/distributed/DistributedRenderer.ispc b/modules/mpi/ospray/render/distributed/DistributedRenderer.ispc index bdb4a8c275..5a2dd004e8 100644 --- a/modules/mpi/ospray/render/distributed/DistributedRenderer.ispc +++ b/modules/mpi/ospray/render/distributed/DistributedRenderer.ispc @@ -1,13 +1,19 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include "DistributedRenderer.ih" -#include "common/DistributedWorld.ih" +#include "camera/Camera.ih" #include "common/Intersect.ih" #include "common/Ray.ih" #include "common/World.ih" +#include "fb/SparseFB.ih" #include "math/random.ih" -#include "render/util.ih" +#include "rkcommon/utility/random.ih" +#include "texture/Texture2D.ih" +// c++ shared +#include "DistributedRendererShared.h" +#include "common/DistributedWorldShared.h" +#include "fb/FrameBufferShared.h" +#include "fb/SparseFBShared.h" unmasked void markRegionVisibleFilterFunction( const RTCFilterFunctionNArguments *uniform args) @@ -19,24 +25,22 @@ unmasked void markRegionVisibleFilterFunction( EmbreeIntersectionContext *uniform ctx = (EmbreeIntersectionContext * uniform) args->context; - bool *uniform regionVisible = (bool *uniform)ctx->userPtr; + uint8 *uniform regionVisible = (uint8 * uniform) ctx->userPtr; varying RTCHit *uniform hit = (varying RTCHit * uniform) args->hit; - regionVisible[hit->primID] = true; + regionVisible[hit->primID] = 0xff; // 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, +task void DR_default_computeRegionVisibility(DistributedRenderer *uniform self, + SparseFB *uniform fb, Camera *uniform camera, DistributedWorld *uniform world, - bool *uniform regionVisible, + uint8 *uniform regionVisible, void *uniform perFrameData, - uniform Tile &tile, - uniform int taskIndex) + const int *uniform taskIDs) { // TODO: merge the copy-paste here somewhat? const uniform int32 spp = self->super.spp; @@ -47,20 +51,41 @@ unmasked void DR_default_computeRegionVisibility( CameraSample cameraSample; - const z_order_t *uniform zOrder = get_zorder(); + uniform RenderTaskDesc taskDesc = + fb->super.getRenderTaskDesc(&fb->super, taskIDs[taskIndex0]); - 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 + zOrder->xs[index]; - screenSample.sampleID.y = tile.region.lower.y + zOrder->ys[index]; + if (fb->super.cancelRender || isEmpty(taskDesc.region)) { + return; + } - if ((screenSample.sampleID.x >= fb->size.x) - || (screenSample.sampleID.y >= fb->size.y)) - continue; + // Get the region visibility info for this tile + uint8 *uniform tileRegionVisible = regionVisible + + world->numRegions * SparseFB_getTileIndexForTask(fb, taskDesc.taskID); + + // Take fixed, consistent samples to determine if a region is really visible + // for a tile. We can trace up to 5 rays, one through the center of the pixel + // and one through each corner, or 4 (one through each corner), or just 1 + // (through the middle). Tracing 5 against the boxes may be a bit much? It + // shouldn't impact performance too badly, but is actually a lot of rays being + // traced Alternatively we could just base this on the region projection, and + // accept the more conservative bounds. This would require some benchmarking + // to see where the scaling trade off hits of sending tiles we don't actually + // need. + // Right now just taking 1 sample, can benchmark this in the future and/or + // refactor code further to use this result to do a scan/compaction on the + // render task IDs to reduce tasks launched. Then the accumIDs can be sync'd + // up again + const uniform int nVisibilitySamples = 1; + const uniform vec2f visibilitySamples[5] = {make_vec2f(0.5f, 0.5f), + make_vec2f(0.0f, 0.0f), + make_vec2f(1.0f, 0.0f), + make_vec2f(0.0f, 1.0f), + make_vec2f(1.0f, 1.0f)}; + + foreach_tiled (y = taskDesc.region.lower.y... taskDesc.region.upper.y, + x = taskDesc.region.lower.x... taskDesc.region.upper.x) { + screenSample.sampleID.x = x; + screenSample.sampleID.y = y; float tMax = inf; // set ray t value for early ray termination if we have a maximum depth @@ -68,28 +93,21 @@ unmasked void DR_default_computeRegionVisibility( if (self->super.maxDepthTexture) { // always sample center of pixel vec2f depthTexCoord; - depthTexCoord.x = (screenSample.sampleID.x + 0.5f) * fb->rcpSize.x; - depthTexCoord.y = (screenSample.sampleID.y + 0.5f) * fb->rcpSize.y; + depthTexCoord.x = (screenSample.sampleID.x + 0.5f) * fb->super.rcpSize.x; + depthTexCoord.y = (screenSample.sampleID.y + 0.5f) * fb->super.rcpSize.y; DifferentialGeometry lookup; initDgFromTexCoord(lookup, depthTexCoord); tMax = min(get1f(self->super.maxDepthTexture, lookup), inf); } - const uint32 pixel = zOrder->xs[index] + (zOrder->ys[index] * TILE_SIZE); + for (uniform uint32 s = 0; s < nVisibilitySamples; s++) { + screenSample.sampleID.z = s; - // TODO: Does spp still show some block boundary artifacts? Check - // and maybe just support spp = 1 in DR - for (uniform uint32 s = 0; s < spp; s++) { - const float pixel_du = Halton_sample2(startSampleID + s); - const float pixel_dv = CranleyPattersonRotation( - Halton_sample3(startSampleID + s), 1.f / 6.f); - screenSample.sampleID.z = startSampleID + s; - - cameraSample.screen.x = - (screenSample.sampleID.x + pixel_du) * fb->rcpSize.x; - cameraSample.screen.y = - (screenSample.sampleID.y + pixel_dv) * fb->rcpSize.y; + cameraSample.screen.x = (screenSample.sampleID.x + visibilitySamples[s].x) + * fb->super.rcpSize.x; + cameraSample.screen.y = (screenSample.sampleID.y + visibilitySamples[s].y) + * fb->super.rcpSize.y; // no DoF or MB per default cameraSample.lens.x = 0.0f; @@ -102,25 +120,19 @@ unmasked void DR_default_computeRegionVisibility( if (world->regionScene) { uniform EmbreeIntersectionContext context; rtcInitIntersectContext(&context.ectx); + context.ectx.flags = RTC_INTERSECT_CONTEXT_FLAG_COHERENT; context.ectx.filter = markRegionVisibleFilterFunction; - context.userPtr = regionVisible; + context.userPtr = tileRegionVisible; rtcIntersectV(world->regionScene, &context.ectx, (varying RTCRayHit * uniform) & screenSample.ray); } } - - screenSample.rgb = make_vec3f( - self->super.bgColor.x, self->super.bgColor.y, self->super.bgColor.z); - screenSample.alpha = self->super.bgColor.z; - screenSample.normal = make_vec3f(0.f); - screenSample.albedo = make_vec3f(0.f); - setTile(tile, pixel, screenSample); } } void DR_default_renderRegionSample(DistributedRenderer *uniform self, - FrameBuffer *uniform fb, + SparseFB *uniform fb, DistributedWorld *uniform world, const box3f *uniform region, const vec2f ®ionInterval, @@ -133,14 +145,13 @@ void DR_default_renderRegionSample(DistributedRenderer *uniform self, + (sample.sampleID.y << 14) + (sample.sampleID.z << 28)); } -unmasked void DR_default_renderRegionToTile(DistributedRenderer *uniform self, - FrameBuffer *uniform fb, +task void DR_default_renderRegionToTile(DistributedRenderer *uniform self, + SparseFB *uniform fb, Camera *uniform camera, DistributedWorld *uniform world, const box3f *uniform region, void *uniform perFrameData, - uniform Tile &tile, - uniform int taskIndex) + const int *uniform taskIDs) { const uniform int32 spp = self->super.spp; @@ -150,20 +161,19 @@ unmasked void DR_default_renderRegionToTile(DistributedRenderer *uniform self, CameraSample cameraSample; - const z_order_t *uniform zOrder = get_zorder(); + uniform RenderTaskDesc taskDesc = + fb->super.getRenderTaskDesc(&fb->super, taskIDs[taskIndex0]); - 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; + const uniform int startSampleID = max(taskDesc.accumID, 0) * spp; - for (uniform uint32 i = begin; i < end; i += programCount) { - const uint32 index = i + programIndex; - screenSample.sampleID.x = tile.region.lower.x + zOrder->xs[index]; - screenSample.sampleID.y = tile.region.lower.y + zOrder->ys[index]; + if (isEmpty(taskDesc.region)) { + return; + } - if ((screenSample.sampleID.x >= fb->size.x) - || (screenSample.sampleID.y >= fb->size.y)) - continue; + foreach_tiled (y = taskDesc.region.lower.y... taskDesc.region.upper.y, + x = taskDesc.region.lower.x... taskDesc.region.upper.x) { + screenSample.sampleID.x = x; + screenSample.sampleID.y = y; float tMax = inf; // set ray t value for early ray termination if we have a maximum depth @@ -171,8 +181,8 @@ unmasked void DR_default_renderRegionToTile(DistributedRenderer *uniform self, if (self->super.maxDepthTexture) { // always sample center of pixel vec2f depthTexCoord; - depthTexCoord.x = (screenSample.sampleID.x + 0.5f) * fb->rcpSize.x; - depthTexCoord.y = (screenSample.sampleID.y + 0.5f) * fb->rcpSize.y; + depthTexCoord.x = (screenSample.sampleID.x + 0.5f) * fb->super.rcpSize.x; + depthTexCoord.y = (screenSample.sampleID.y + 0.5f) * fb->super.rcpSize.y; DifferentialGeometry lookup; initDgFromTexCoord(lookup, depthTexCoord); @@ -183,8 +193,6 @@ unmasked void DR_default_renderRegionToTile(DistributedRenderer *uniform self, vec3f normal = make_vec3f(0.f); vec3f albedo = make_vec3f(0.f); - 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++) { const float pixel_du = Halton_sample2(startSampleID + s); @@ -193,9 +201,9 @@ unmasked void DR_default_renderRegionToTile(DistributedRenderer *uniform self, screenSample.sampleID.z = startSampleID + s; cameraSample.screen.x = - (screenSample.sampleID.x + pixel_du) * fb->rcpSize.x; + (screenSample.sampleID.x + pixel_du) * fb->super.rcpSize.x; cameraSample.screen.y = - (screenSample.sampleID.y + pixel_dv) * fb->rcpSize.y; + (screenSample.sampleID.y + pixel_dv) * fb->super.rcpSize.y; // no DoF or MB per default cameraSample.lens.x = 0.0f; @@ -235,38 +243,31 @@ unmasked void DR_default_renderRegionToTile(DistributedRenderer *uniform self, screenSample.alpha = alpha * rspp; screenSample.normal = normal * rspp; screenSample.albedo = albedo * rspp; - setTile(tile, pixel, screenSample); - } -} - -void DistributedRenderer_Constructor(uniform DistributedRenderer *uniform self) -{ - Renderer_Constructor(&self->super); - self->computeRegionVisibility = DR_default_computeRegionVisibility; - self->renderRegionSample = DR_default_renderRegionSample; - self->renderRegionToTile = DR_default_renderRegionToTile; + fb->super.accumulateSample(&fb->super, screenSample, taskDesc); + } + fb->super.completeTask(&fb->super, taskDesc); } export void DistributedRenderer_computeRegionVisibility(void *uniform _self, void *uniform fb, void *uniform camera, void *uniform world, - bool *uniform regionVisible, + uint8 *uniform regionVisible, void *uniform perFrameData, - uniform Tile &tile, - uniform int taskIndex) + void *uniform _taskIDs, + uniform int numTasks) { DistributedRenderer *uniform self = (uniform DistributedRenderer * uniform) _self; - self->computeRegionVisibility(self, - (FrameBuffer * uniform) fb, + const int *uniform taskIDs = (const int *uniform)_taskIDs; + launch[numTasks] self->computeRegionVisibility(self, + (SparseFB * uniform) fb, (Camera * uniform) camera, (DistributedWorld * uniform) world, regionVisible, perFrameData, - tile, - taskIndex); + taskIDs); } export void DistributedRenderer_renderRegionToTile(void *uniform _self, @@ -275,19 +276,19 @@ export void DistributedRenderer_renderRegionToTile(void *uniform _self, void *uniform world, const void *uniform region, void *uniform perFrameData, - uniform Tile &tile, - uniform int taskIndex) + void *uniform _taskIDs, + uniform int numTasks) { DistributedRenderer *uniform self = (uniform DistributedRenderer * uniform) _self; - self->renderRegionToTile(self, - (FrameBuffer * uniform) fb, + const int *uniform taskIDs = (const int *uniform)_taskIDs; + launch[numTasks] self->renderRegionToTile(self, + (SparseFB * uniform) fb, (Camera * uniform) camera, (DistributedWorld * uniform) world, (const box3f *uniform)region, perFrameData, - tile, - taskIndex); + taskIDs); } export void DistributedRenderer_pick(const void *uniform _self, @@ -353,3 +354,18 @@ export void DistributedRenderer_pick(const void *uniform _self, } } } + +export void *uniform DR_default_computeRegionVisibility_addr() +{ + return DR_default_computeRegionVisibility; +} + +export void *uniform DR_default_renderRegionSample_addr() +{ + return DR_default_renderRegionSample; +} + +export void *uniform DR_default_renderRegionToTile_addr() +{ + return DR_default_renderRegionToTile; +} diff --git a/modules/mpi/ospray/render/distributed/DistributedRendererShared.h b/modules/mpi/ospray/render/distributed/DistributedRendererShared.h new file mode 100644 index 0000000000..9d664b647d --- /dev/null +++ b/modules/mpi/ospray/render/distributed/DistributedRendererShared.h @@ -0,0 +1,62 @@ +// Copyright 2009 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "render/RendererShared.h" + +#ifdef __cplusplus +namespace ispc { +typedef void *DR_ComputeRegionVisibility; +typedef void *DR_RenderRegionSampleFct; +typedef void *DR_RenderRegionTileFct; +#else +struct DistributedWorld; +struct DistributedRenderer; +struct SparseFB; + +typedef task void (*DR_ComputeRegionVisibility)( + DistributedRenderer *uniform self, + SparseFB *uniform fb, + Camera *uniform camera, + DistributedWorld *uniform world, + uint8 *uniform regionVisible, + void *uniform perFrameData, + const int *uniform taskIDs); + +typedef void (*DR_RenderRegionSampleFct)(DistributedRenderer *uniform self, + SparseFB *uniform fb, + DistributedWorld *uniform world, + const box3f *uniform region, + const vec2f ®ionInterval, + void *uniform perFrameData, + varying ScreenSample &sample); + +typedef task void (*DR_RenderRegionTileFct)(DistributedRenderer *uniform self, + SparseFB *uniform fb, + Camera *uniform camera, + DistributedWorld *uniform world, + const box3f *uniform region, + void *uniform perFrameData, + const int *uniform taskIDs); +#endif // __cplusplus + +struct DistributedRenderer +{ + Renderer super; + + DR_ComputeRegionVisibility computeRegionVisibility; + DR_RenderRegionSampleFct renderRegionSample; + DR_RenderRegionTileFct renderRegionToTile; + +#ifdef __cplusplus + DistributedRenderer() + : computeRegionVisibility(nullptr), + renderRegionSample(nullptr), + renderRegionToTile(nullptr) + {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/mpi/tutorials/CMakeLists.txt b/modules/mpi/tutorials/CMakeLists.txt index 4fc1432189..8440c967f8 100644 --- a/modules/mpi/tutorials/CMakeLists.txt +++ b/modules/mpi/tutorials/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 macro(ospray_create_mpi_tutorial tutorial_name) diff --git a/modules/mpi/tutorials/GLFWDistribOSPRayWindow.cpp b/modules/mpi/tutorials/GLFWDistribOSPRayWindow.cpp index ec1fd01345..5455c7e34c 100644 --- a/modules/mpi/tutorials/GLFWDistribOSPRayWindow.cpp +++ b/modules/mpi/tutorials/GLFWDistribOSPRayWindow.cpp @@ -1,4 +1,4 @@ -// Copyright 2018-2020 Intel Corporation +// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "GLFWDistribOSPRayWindow.h" @@ -362,7 +362,7 @@ void GLFWDistribOSPRayWindow::startNewOSPRayFrame() } if (fbNeedsClear) { - framebuffer.resetAccumulation(); + resetAccumulation(); } currentFrame = framebuffer.renderFrame(renderer, camera, world); diff --git a/modules/mpi/tutorials/GLFWDistribOSPRayWindow.h b/modules/mpi/tutorials/GLFWDistribOSPRayWindow.h index 17ec78e522..fc551fcc1b 100644 --- a/modules/mpi/tutorials/GLFWDistribOSPRayWindow.h +++ b/modules/mpi/tutorials/GLFWDistribOSPRayWindow.h @@ -1,4 +1,4 @@ -// Copyright 2018-2020 Intel Corporation +// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/mpi/tutorials/example_common.h b/modules/mpi/tutorials/example_common.h index 866e192a79..c2b7231446 100644 --- a/modules/mpi/tutorials/example_common.h +++ b/modules/mpi/tutorials/example_common.h @@ -1,4 +1,4 @@ -// Copyright 2018-2021 Intel Corporation +// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/mpi/tutorials/ospMPIDistribTutorial.c b/modules/mpi/tutorials/ospMPIDistribTutorial.c index cf89e5830d..d28a685c83 100644 --- a/modules/mpi/tutorials/ospMPIDistribTutorial.c +++ b/modules/mpi/tutorials/ospMPIDistribTutorial.c @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This is a small example tutorial how to use OSPRay and the diff --git a/modules/mpi/tutorials/ospMPIDistribTutorial.cpp b/modules/mpi/tutorials/ospMPIDistribTutorial.cpp index 350b414159..e955df4f11 100644 --- a/modules/mpi/tutorials/ospMPIDistribTutorial.cpp +++ b/modules/mpi/tutorials/ospMPIDistribTutorial.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This is a small example tutorial how to use OSPRay and the diff --git a/modules/mpi/tutorials/ospMPIDistribTutorialAsync.c b/modules/mpi/tutorials/ospMPIDistribTutorialAsync.c index 4514f0cceb..8bcb979040 100644 --- a/modules/mpi/tutorials/ospMPIDistribTutorialAsync.c +++ b/modules/mpi/tutorials/ospMPIDistribTutorialAsync.c @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This is a small example tutorial how to use OSPRay and the diff --git a/modules/mpi/tutorials/ospMPIDistribTutorialPartialRepl.cpp b/modules/mpi/tutorials/ospMPIDistribTutorialPartialRepl.cpp index e4a37b0deb..bd8a3adb13 100644 --- a/modules/mpi/tutorials/ospMPIDistribTutorialPartialRepl.cpp +++ b/modules/mpi/tutorials/ospMPIDistribTutorialPartialRepl.cpp @@ -1,4 +1,4 @@ -// Copyright 2018-2021 Intel Corporation +// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This larger example shows how to use the MPIDistributedDevice to write an diff --git a/modules/mpi/tutorials/ospMPIDistribTutorialReplicated.cpp b/modules/mpi/tutorials/ospMPIDistribTutorialReplicated.cpp index 2f79990737..ac9ab81c4f 100644 --- a/modules/mpi/tutorials/ospMPIDistribTutorialReplicated.cpp +++ b/modules/mpi/tutorials/ospMPIDistribTutorialReplicated.cpp @@ -1,4 +1,4 @@ -// Copyright 2018-2021 Intel Corporation +// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This tutorial demonstrates how MPI-parallel applications can be diff --git a/modules/mpi/tutorials/ospMPIDistribTutorialSpheres.cpp b/modules/mpi/tutorials/ospMPIDistribTutorialSpheres.cpp index fd986b71a7..40dbcd91e5 100644 --- a/modules/mpi/tutorials/ospMPIDistribTutorialSpheres.cpp +++ b/modules/mpi/tutorials/ospMPIDistribTutorialSpheres.cpp @@ -1,4 +1,4 @@ -// Copyright 2018-2021 Intel Corporation +// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This larger example shows how to use the MPIDistributedDevice to write an diff --git a/modules/mpi/tutorials/ospMPIDistribTutorialVolume.cpp b/modules/mpi/tutorials/ospMPIDistribTutorialVolume.cpp index 06607b51aa..ab0c21fe61 100644 --- a/modules/mpi/tutorials/ospMPIDistribTutorialVolume.cpp +++ b/modules/mpi/tutorials/ospMPIDistribTutorialVolume.cpp @@ -1,4 +1,4 @@ -// Copyright 2018-2021 Intel Corporation +// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This larger example shows how to use the MPIDistributedDevice to write an diff --git a/modules/multiDevice/CMakeLists.txt b/modules/multiDevice/CMakeLists.txt index 22643132c0..6b934f34ad 100644 --- a/modules/multiDevice/CMakeLists.txt +++ b/modules/multiDevice/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 cmake_dependent_option( diff --git a/modules/multiDevice/ModuleInit.cpp b/modules/multiDevice/ModuleInit.cpp index 6a442406f1..f062aa3a21 100644 --- a/modules/multiDevice/ModuleInit.cpp +++ b/modules/multiDevice/ModuleInit.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "MultiDevice.h" diff --git a/modules/multiDevice/MultiDevice.cpp b/modules/multiDevice/MultiDevice.cpp index 3c241c105f..2c4972b5cd 100644 --- a/modules/multiDevice/MultiDevice.cpp +++ b/modules/multiDevice/MultiDevice.cpp @@ -1,11 +1,13 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "MultiDevice.h" +#include "MultiDeviceFrameBuffer.h" #include "MultiDeviceRenderTask.h" #include "camera/registration.h" #include "fb/LocalFB.h" +#include "fb/SparseFB.h" #include "fb/registration.h" #include "geometry/registration.h" #include "lights/registration.h" @@ -357,9 +359,22 @@ void MultiDevice::retain(OSPObject object) OSPFrameBuffer MultiDevice::frameBufferCreate( const vec2i &size, const OSPFrameBufferFormat mode, const uint32 channels) { - MultiDeviceObject *o = new MultiDeviceObject(); + MultiDeviceFrameBuffer *o = new MultiDeviceFrameBuffer(); + o->rowmajorFb = new LocalFrameBuffer(size, mode, channels); + // Need one refDec here for the local scope ref (see issue about Ref<>) + o->rowmajorFb->refDec(); + + const vec2i totalTiles = divRoundUp(size, vec2i(TILE_SIZE)); for (size_t i = 0; i < subdevices.size(); ++i) { - FrameBuffer *fbi = new LocalFrameBuffer(size, mode, channels); + // Assign tiles round-robin among the subdevices + std::vector tileIDs; + for (uint32_t tid = 0; tid < totalTiles.long_product(); ++tid) { + if (tid % subdevices.size() == i) { + tileIDs.push_back(tid); + } + } + + FrameBuffer *fbi = new SparseFrameBuffer(size, mode, channels, tileIDs); o->objects.push_back((OSPFrameBuffer)fbi); } return (OSPFrameBuffer)o; @@ -381,30 +396,28 @@ OSPImageOperation MultiDevice::newImageOp(const char *type) const void *MultiDevice::frameBufferMap( OSPFrameBuffer _fb, const OSPFrameBufferChannel channel) { - MultiDeviceObject *o = (MultiDeviceObject *)_fb; - LocalFrameBuffer *fb = (LocalFrameBuffer *)o->objects[0]; - return fb->mapBuffer(channel); + MultiDeviceFrameBuffer *o = (MultiDeviceFrameBuffer *)_fb; + return o->rowmajorFb->mapBuffer(channel); } void MultiDevice::frameBufferUnmap(const void *mapped, OSPFrameBuffer _fb) { - MultiDeviceObject *o = (MultiDeviceObject *)_fb; - LocalFrameBuffer *fb = (LocalFrameBuffer *)o->objects[0]; - fb->unmap(mapped); + MultiDeviceFrameBuffer *o = (MultiDeviceFrameBuffer *)_fb; + o->rowmajorFb->unmap(mapped); } float MultiDevice::getVariance(OSPFrameBuffer _fb) { - MultiDeviceObject *o = (MultiDeviceObject *)_fb; - LocalFrameBuffer *fb = (LocalFrameBuffer *)o->objects[0]; - return fb->getVariance(); + MultiDeviceFrameBuffer *o = (MultiDeviceFrameBuffer *)_fb; + return o->rowmajorFb->getVariance(); } void MultiDevice::resetAccumulation(OSPFrameBuffer _fb) { - MultiDeviceObject *o = (MultiDeviceObject *)_fb; + MultiDeviceFrameBuffer *o = (MultiDeviceFrameBuffer *)_fb; + o->rowmajorFb->clear(); for (size_t i = 0; i < subdevices.size(); ++i) { - LocalFrameBuffer *fbi = (LocalFrameBuffer *)o->objects[i]; + SparseFrameBuffer *fbi = (SparseFrameBuffer *)o->objects[i]; fbi->clear(); } } @@ -425,9 +438,13 @@ OSPFuture MultiDevice::renderFrame(OSPFrameBuffer _framebuffer, OSPCamera _camera, OSPWorld _world) { - MultiDeviceObject *multiFb = (MultiDeviceObject *)_framebuffer; - FrameBuffer *fb0 = (FrameBuffer *)multiFb->objects[0]; - fb0->setCompletedEvent(OSP_NONE_FINISHED); + MultiDeviceFrameBuffer *multiFb = (MultiDeviceFrameBuffer *)_framebuffer; + multiFb->rowmajorFb->setCompletedEvent(OSP_NONE_FINISHED); + for (size_t i = 0; i < multiFb->objects.size(); ++i) { + SparseFrameBuffer *fbi = (SparseFrameBuffer *)multiFb->objects[i]; + fbi->setCompletedEvent(OSP_NONE_FINISHED); + } + MultiDeviceObject *multiRenderer = (MultiDeviceObject *)_renderer; MultiDeviceObject *multiCamera = (MultiDeviceObject *)_camera; MultiDeviceObject *multiWorld = (MultiDeviceObject *)_world; diff --git a/modules/multiDevice/MultiDevice.h b/modules/multiDevice/MultiDevice.h index e41c5918a8..a457d2b558 100644 --- a/modules/multiDevice/MultiDevice.h +++ b/modules/multiDevice/MultiDevice.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/modules/multiDevice/MultiDeviceFrameBuffer.h b/modules/multiDevice/MultiDeviceFrameBuffer.h new file mode 100644 index 0000000000..0de97c3b97 --- /dev/null +++ b/modules/multiDevice/MultiDeviceFrameBuffer.h @@ -0,0 +1,23 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "MultiDeviceObject.h" +#include "fb/LocalFB.h" + +namespace ospray { +namespace api { + +/* The MultiDeviceFrameBuffer stores a SparseFB for each subdevice containing + * the tiles the subdevice will render, along with a rowmajorFb that will be + * exposed to the application. After rendering, the sparse framebuffers are + * untiled into the rowmajorFb to return the rendered image to the app + */ +struct MultiDeviceFrameBuffer : MultiDeviceObject +{ + Ref rowmajorFb = nullptr; +}; + +} // namespace api +} // namespace ospray diff --git a/modules/multiDevice/MultiDeviceLoadBalancer.cpp b/modules/multiDevice/MultiDeviceLoadBalancer.cpp index 7623da15a0..0fc9adb22b 100644 --- a/modules/multiDevice/MultiDeviceLoadBalancer.cpp +++ b/modules/multiDevice/MultiDeviceLoadBalancer.cpp @@ -1,9 +1,10 @@ -// Copyright 2021-2022 Intel Corporation +// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "MultiDeviceLoadBalancer.h" #include "MultiDevice.h" #include "fb/LocalFB.h" +#include "fb/SparseFB.h" #include @@ -15,314 +16,72 @@ MultiDeviceLoadBalancer::MultiDeviceLoadBalancer( {} -void MultiDeviceLoadBalancer::renderFrame(api::MultiDeviceObject *framebuffer, +void MultiDeviceLoadBalancer::renderFrame( + api::MultiDeviceFrameBuffer *framebuffer, api::MultiDeviceObject *renderer, api::MultiDeviceObject *camera, api::MultiDeviceObject *world) { - // At this level we will distribute the tiles among the subdevices - // and assign them the tiles to render. - FrameBuffer *fb0 = nullptr; - for (size_t i = 0; i < loadBalancers.size(); ++i) { - FrameBuffer *fbi = (FrameBuffer *)framebuffer->objects[i]; - if (i==0) { - fb0 = fbi; - } - fbi->beginFrame(); - } - - // We need these after all subdevices have finished rendering, so hang - // on to the per frame data pointer each subdevice's renderer returned - std::vector perFrameDatas; - perFrameDatas.resize(loadBalancers.size(), nullptr); - - renderTiles(framebuffer, - renderer, - camera, - world, - fb0->getTileIDs(), - perFrameDatas); + framebuffer->rowmajorFb->beginFrame(); - for (size_t i = 0; i < loadBalancers.size(); ++i) { + tasking::parallel_for(framebuffer->objects.size(), [&](size_t i) { + SparseFrameBuffer *fbi = (SparseFrameBuffer *)framebuffer->objects[i]; Renderer *ri = (Renderer *)renderer->objects[i]; - FrameBuffer *fbi = (FrameBuffer *)framebuffer->objects[i]; - ri->endFrame(fbi, perFrameDatas[i]); - } - for (size_t i = 0; i < loadBalancers.size(); ++i) { - FrameBuffer *fbi = (FrameBuffer *)framebuffer->objects[i]; - fbi->setCompletedEvent(OSP_WORLD_RENDERED); - } - - // TODO For now everything is replicated, so just pick one, - // but in the future we will have issues because this also executes - // the image operations on the FB, which we may want to distribute - // among the subdevices. - { - Renderer *r0 = (Renderer *)renderer->objects[0]; - Camera *c0 = (Camera *)camera->objects[0]; - fb0->endFrame(r0->errorThreshold, c0); - } - for (size_t i = 0; i < loadBalancers.size(); ++i) { - FrameBuffer *fbi = (FrameBuffer *)framebuffer->objects[i]; - fbi->setCompletedEvent(OSP_FRAME_FINISHED); - } -} - -void MultiDeviceLoadBalancer::renderTiles(api::MultiDeviceObject *framebuffer, - api::MultiDeviceObject *renderer, - api::MultiDeviceObject *camera, - api::MultiDeviceObject *world, - const utility::ArrayView &tileIDs, - std::vector &perFrameDatas) -{ - //TODO: - //investigate unrolling the foreach loadbalancers.size() and loadbalancers->renderTiles() loops - //that should give tbb finer granularity to work with in its workstealing thing and delay load imbalances + Camera *ci = (Camera *)camera->objects[i]; + World *wi = (World *)world->objects[i]; - // Shuffle tile list into a round-robin ordering among the subdevices for better load balance. - FrameBuffer *fb0 = (FrameBuffer *)framebuffer->objects[0]; - std::vector allTileIDs; - allTileIDs.reserve(tileIDs.size()); - for (unsigned int j = 0; j < loadBalancers.size(); ++j) { - unsigned int tilesForSubdevice = tileIDs.size() / loadBalancers.size(); - // All tiles may not divide evenly among the subdevices - if ((tileIDs.size() % loadBalancers.size()) > j) { - tilesForSubdevice++; - } - for (int i = 0; i < static_cast(tilesForSubdevice); ++i) { - allTileIDs.push_back(i * loadBalancers.size() + j); - } - } + if (!fbi->getTileIDs().empty()) { + loadBalancers[i]->renderFrame(fbi, ri, ci, wi); - // Render the whole frame distributing the tiles among the subdevices - const int numTiles = tileIDs.size(); - tasking::parallel_for(loadBalancers.size(), [&](size_t subdeviceID) { - // Tiles are assigned contiguously in chunks to the subdevices - // from the tileIDs array but the contents of the array can - // create a round robin or random assignment - - const int tilesForSubdevice = numTiles / loadBalancers.size(); - // All tiles may not divide evenly among the subdevices - const int numExtraTiles = numTiles % loadBalancers.size(); - int tilesForThisDevice = tilesForSubdevice; - int additionalTileOffset = 0; - if (numExtraTiles != 0) { - additionalTileOffset = - std::min(static_cast(subdeviceID), numExtraTiles); - if (static_cast(subdeviceID) < numExtraTiles) { - tilesForThisDevice++; - } + framebuffer->rowmajorFb->writeTiles(fbi); } - const int startTileIndex = - subdeviceID * tilesForSubdevice + additionalTileOffset; - utility::ArrayView subdeviceTileIDs( - &allTileIDs.at(startTileIndex), tilesForThisDevice); - - FrameBuffer *fb = (FrameBuffer *)framebuffer->objects[subdeviceID]; - Renderer *r = (Renderer *)renderer->objects[subdeviceID]; - Camera *c = (Camera *)camera->objects[subdeviceID]; - World *w = (World *)world->objects[subdeviceID]; - - // TODO Note: potential issues with shared framebuffer but - // per-subdevice renderers and worlds? Per-frame data issues? - perFrameDatas[subdeviceID] = r->beginFrame(fb, w); - loadBalancers[subdeviceID]->renderTiles( - fb, r, c, w, subdeviceTileIDs, perFrameDatas[subdeviceID]); }); - - //gather individual tiles down to fb 0. - const auto fbSize = fb0->getNumPixels(); - LocalFrameBuffer* fb0asLFB = (LocalFrameBuffer*)fb0; //todo: revise when we support other types - - OSPFrameBufferFormat colorBufferFormat = fb0->getColorBufferFormat(); - - tasking::parallel_for(loadBalancers.size(), [&](size_t subdeviceID) { - if (subdeviceID == 0) - return; // gather of fb0's tiles to fb0 is unnecessary - - FrameBuffer *fbi = (FrameBuffer *)framebuffer->objects[subdeviceID]; - //get a hold of the pixels - - const void *color = fbi->mapBuffer(OSP_FB_COLOR); - int *colorI = (int*)color; - float *colorF = (float*)color; - float *depth = (float*)fbi->mapBuffer(OSP_FB_DEPTH); - vec3f *normal = (vec3f*)fbi->mapBuffer(OSP_FB_NORMAL); - vec3f *albedo = (vec3f*)fbi->mapBuffer(OSP_FB_ALBEDO); - - //get a hold of the list of tiles on this subdevice - const int tilesForSubdevice = numTiles / loadBalancers.size(); - const int numExtraTiles = numTiles % loadBalancers.size(); - int tilesForThisDevice = tilesForSubdevice; - int additionalTileOffset = 0; - if (numExtraTiles != 0) { - additionalTileOffset = - std::min(static_cast(subdeviceID), numExtraTiles); - if (static_cast(subdeviceID) < numExtraTiles) { - tilesForThisDevice++; - } - } - const int startTileIndex = - subdeviceID * tilesForSubdevice + additionalTileOffset; - utility::ArrayView subdeviceTileIDs( - &allTileIDs.at(startTileIndex), tilesForThisDevice); - - tasking::parallel_for(subdeviceTileIDs.size(), [&](size_t taskIndex) { - const size_t numTiles_x = fbi->getNumTiles().x; - const size_t tile_y = subdeviceTileIDs[taskIndex] / numTiles_x; - const size_t tile_x = subdeviceTileIDs[taskIndex] - tile_y * numTiles_x; - const vec2i tileID(tile_x, tile_y); - const int32 accumID = 0;//fbi->accumID(tileID); this prevents re-accum across source and dest, which is good as dest's accum pixels are not valid (LocalFB.ispc:92) - -#if TILE_SIZE > MAX_TILE_SIZE - auto tilePtr = make_unique(tileID, fbSize, accumID); - auto &tile = *tilePtr; - #else - Tile __aligned(64) tile(tileID, fbSize, accumID); - #endif - -#if 0 - const float showRanks = 0.5+(float)subdeviceID/loadBalancers.size()*0.5; -#else - const float showRanks = 1.f; -#endif - //TODO: think about means to access floats directly and avoid - //the repeated conversions into, out of and back into RGB - //TODO: these 'getTile' loops are unoptimized. Consider implementing in - //ispc to accelerate. - if (colorI && colorBufferFormat == OSP_FB_RGBA8) { - int cnt = 0; - for (int i=0; i < TILE_SIZE; ++i) { - for (int j=0; j < TILE_SIZE; ++j) { - int px = tile.region.lower.x+j; - int py = tile.region.lower.y+i; - if ((px >= fbSize.x) - || (py >= fbSize.y)) { - cnt++; - continue; - } - int *cS = colorI+(py*fb0->getNumPixels().x)+px; - //RGBA8 - tile.a[cnt] = (float)((*cS&0xFF000000)>>24)/255.0; - tile.b[cnt] = (float)((*cS&0x00FF0000)>>16)/255.0*showRanks; - tile.g[cnt] = (float)((*cS&0x0000FF00)>>8)/255.0*showRanks; - tile.r[cnt] = (float)((*cS&0x000000FF))/255.0*showRanks; - cnt++; - } - } - } - if (colorI && colorBufferFormat == OSP_FB_SRGBA) { - int cnt = 0; - for (int i=0; i < TILE_SIZE; ++i) { - for (int j=0; j < TILE_SIZE; ++j) { - int px = tile.region.lower.x+j; - int py = tile.region.lower.y+i; - if ((px >= fbSize.x) - || (py >= fbSize.y)) { - cnt++; - continue; - } - int *cS = colorI+(py*fb0->getNumPixels().x)+px; - //SRGBA - from LocalFB.ispc - tile.a[cnt] = ((*cS&0xFF000000)>>24)/255.0; - tile.b[cnt] = pow((float)((*cS&0x00FF0000)>>16)/255.0, 2.2f)*showRanks; - tile.g[cnt] = pow((float)((*cS&0x0000FF00)>>8)/255.0, 2.2f)*showRanks; - tile.r[cnt] = pow((float)((*cS&0x000000FF))/255.0, 2.2f)*showRanks; - cnt++; - } - } - } - - if (colorF && colorBufferFormat == OSP_FB_RGBA32F) { - int cnt = 0; - for (int i=0; i < TILE_SIZE; ++i) { - for (int j=0; j < TILE_SIZE; ++j) { - int px = tile.region.lower.x+j; - int py = tile.region.lower.y+i; - if ((px >= fbSize.x) - || (py >= fbSize.y)) { - cnt++; - continue; - } - float *cF = colorF+((py*fb0->getNumPixels().x)+px)*4; - tile.r[cnt] = *(cF+0)*showRanks; - tile.g[cnt] = *(cF+1)*showRanks; - tile.b[cnt] = *(cF+2)*showRanks; - tile.a[cnt] = *(cF+3); - cnt++; - } - } - } - if (depth) { - int cnt = 0; - for (int i=0; i < TILE_SIZE; ++i) { - for (int j=0; j < TILE_SIZE; ++j) { - int px = tile.region.lower.x+j; - int py = tile.region.lower.y+i; - if ((px >= fbSize.x) - || (py >= fbSize.y)) { - cnt++; - continue; - } - tile.z[cnt] = *(depth+(py*fb0->getNumPixels().x)+px); - cnt++; - } - } - } - if (normal) { - int cnt = 0; - for (int i=0; i < TILE_SIZE; ++i) { - for (int j=0; j < TILE_SIZE; ++j) { - int px = tile.region.lower.x+j; - int py = tile.region.lower.y+i; - if ((px >= fbSize.x) - || (py >= fbSize.y)) { - cnt++; - continue; - } - vec3f *cF = normal+(py*fb0->getNumPixels().x)+px; - tile.nx[cnt] = cF->x; - tile.ny[cnt] = cF->y; - tile.nz[cnt] = cF->z; - cnt++; - } - } - } - - if (albedo) { - int cnt = 0; - for (int i=0; i < TILE_SIZE; ++i) { - for (int j=0; j < TILE_SIZE; ++j) { - int px = tile.region.lower.x+j; - int py = tile.region.lower.y+i; - if ((px >= fbSize.x) - || (py >= fbSize.y)) { - cnt++; - continue; - } - vec3f *cF = albedo+(py*fb0->getNumPixels().x)+px; - tile.nx[cnt] = cF->x; - tile.ny[cnt] = cF->y; - tile.nz[cnt] = cF->z; - cnt++; + framebuffer->rowmajorFb->setCompletedEvent(OSP_WORLD_RENDERED); + + // TODO: These might not be accessible to the local fb on the CPU, + // so the multidevice needs to kind of manage "a bit" of a CPU device? + // Also here, for executing frame ops, the rowmajorFb doesn't get parameters + // set on it. It either needs params to be set on it (and then params from + // which subdevice?) or borrow them here from a subdevice, which also doesn't + // fit well + Renderer *r0 = (Renderer *)renderer->objects[0]; + Camera *c0 = (Camera *)camera->objects[0]; + framebuffer->rowmajorFb->endFrame(r0->errorThreshold, c0); + + // Now copy the task error data back into the sparse fb's task error buffer, + // since the rowmajorFb has done the task error region refinement on the full + // framebuffer + if (framebuffer->rowmajorFb->hasVarianceBuf()) { + tasking::parallel_for(framebuffer->objects.size(), [&](size_t i) { + SparseFrameBuffer *fbi = (SparseFrameBuffer *)framebuffer->objects[i]; + const vec2i totalRenderTasks = + framebuffer->rowmajorFb->getNumRenderTasks(); + const vec2i renderTaskSize = fbi->getRenderTaskSize(); + const auto &tiles = fbi->getTiles(); + + uint32_t renderTaskID = 0; + for (size_t tid = 0; tid < tiles.size(); ++tid) { + const auto &tile = tiles[tid]; + const box2i taskRegion(tile.region.lower / renderTaskSize, + tile.region.upper / renderTaskSize); + for (int y = taskRegion.lower.y; y < taskRegion.upper.y; ++y) { + for (int x = taskRegion.lower.x; x < taskRegion.upper.x; + ++x, ++renderTaskID) { + const vec2i task(x, y); + float error = framebuffer->rowmajorFb->taskError( + task.x + task.y * totalRenderTasks.x); + fbi->setTaskError(renderTaskID, error); } } } - - fb0->setTile(tile); - - //todo: For now we assume LocalFrameBuffer for rank 0 (see MultiDevice). - //When that assumption no longer holds asLFB will be invalid and we'll need to - //do better. - float tileError = fbi->tileError(tileID); - fb0asLFB->tileErrorRegion.update(tile.region.lower / TILE_SIZE, tileError); }); + } - fbi->unmap(color); - fbi->unmap(depth); - fbi->unmap(normal); - fbi->unmap(albedo); - }); + for (size_t i = 0; i < framebuffer->objects.size(); ++i) { + SparseFrameBuffer *fbi = (SparseFrameBuffer *)framebuffer->objects[i]; + fbi->setCompletedEvent(OSP_FRAME_FINISHED); + } + framebuffer->rowmajorFb->setCompletedEvent(OSP_FRAME_FINISHED); } std::string MultiDeviceLoadBalancer::toString() const diff --git a/modules/multiDevice/MultiDeviceLoadBalancer.h b/modules/multiDevice/MultiDeviceLoadBalancer.h index 069539da32..0b4ea1604e 100644 --- a/modules/multiDevice/MultiDeviceLoadBalancer.h +++ b/modules/multiDevice/MultiDeviceLoadBalancer.h @@ -1,12 +1,13 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include +#include "MultiDeviceFrameBuffer.h" +#include "MultiDeviceObject.h" #include "render/LoadBalancer.h" #include "rkcommon/utility/ArrayView.h" -#include "MultiDeviceObject.h" namespace ospray { @@ -15,18 +16,11 @@ struct MultiDeviceLoadBalancer MultiDeviceLoadBalancer( const std::vector> &loadBalancers); - void renderFrame(api::MultiDeviceObject *framebuffer, + void renderFrame(api::MultiDeviceFrameBuffer *framebuffer, api::MultiDeviceObject *renderer, api::MultiDeviceObject *camera, api::MultiDeviceObject *world); - void renderTiles(api::MultiDeviceObject *framebuffer, - api::MultiDeviceObject *renderer, - api::MultiDeviceObject *camera, - api::MultiDeviceObject *world, - const utility::ArrayView &tileIDs, - std::vector &perFrameDatas); - std::string toString() const; private: diff --git a/modules/multiDevice/MultiDeviceObject.h b/modules/multiDevice/MultiDeviceObject.h index 26e6252126..1d9f2d9d21 100644 --- a/modules/multiDevice/MultiDeviceObject.h +++ b/modules/multiDevice/MultiDeviceObject.h @@ -1,8 +1,10 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#include "common/Data.h" + namespace ospray { namespace api { @@ -14,10 +16,11 @@ struct MultiDeviceObject : public memory::RefCount // sharedDataDirtyReference is held temporarily to ensure consistency Data *sharedDataDirtyReference = nullptr; - ~MultiDeviceObject() override { + virtual ~MultiDeviceObject() override + { delete sharedDataDirtyReference; } }; -} -} +} // namespace api +} // namespace ospray diff --git a/modules/multiDevice/MultiDeviceRenderTask.h b/modules/multiDevice/MultiDeviceRenderTask.h index 44c04b498f..0b726c31ed 100644 --- a/modules/multiDevice/MultiDeviceRenderTask.h +++ b/modules/multiDevice/MultiDeviceRenderTask.h @@ -1,10 +1,10 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include -#include "MultiDeviceObject.h" +#include "MultiDeviceFrameBuffer.h" // ospray #include "common/Future.h" @@ -15,7 +15,7 @@ namespace api { struct MultiDeviceRenderTask : public Future { - MultiDeviceRenderTask(MultiDeviceObject *fb, std::function fcn); + MultiDeviceRenderTask(MultiDeviceFrameBuffer *fb, std::function fcn); ~MultiDeviceRenderTask() override; bool isFinished(OSPSyncEvent event = OSP_TASK_FINISHED) override; @@ -27,7 +27,7 @@ struct MultiDeviceRenderTask : public Future float getTaskDuration() override; private: - Ref fb; + Ref fb; std::atomic taskDuration{0.f}; std::atomic finished; std::thread thread; @@ -36,8 +36,8 @@ struct MultiDeviceRenderTask : public Future // Inlined definitions ////////////////////////////////////////////////////// inline MultiDeviceRenderTask::MultiDeviceRenderTask( - MultiDeviceObject *_fb, std::function fcn) - : fb(_fb), finished(false) + MultiDeviceFrameBuffer *fb, std::function fcn) + : fb(fb), finished(false) { thread = std::thread([this, fcn]() { taskDuration = fcn(); @@ -54,8 +54,7 @@ inline MultiDeviceRenderTask::~MultiDeviceRenderTask() inline bool MultiDeviceRenderTask::isFinished(OSPSyncEvent event) { - FrameBuffer *fb0 = (FrameBuffer *)fb->objects[0]; - return finished == true || fb0->getLatestCompleteEvent() >= event; + return finished == true || fb->rowmajorFb->getLatestCompleteEvent() >= event; } inline void MultiDeviceRenderTask::wait(OSPSyncEvent event) @@ -65,10 +64,9 @@ inline void MultiDeviceRenderTask::wait(OSPSyncEvent event) std::this_thread::yield(); } } else { - for (size_t i = 0; i < fb->objects.size(); ++i) { - FrameBuffer *fbi = (FrameBuffer *)fb->objects[i]; - fbi->waitForEvent(event); - } + // the rowmajorFb tracks the same events as the subdevices, so we can wait + // on it + fb->rowmajorFb->waitForEvent(event); } } @@ -82,20 +80,19 @@ inline void MultiDeviceRenderTask::cancel() inline float MultiDeviceRenderTask::getProgress() { - float progress = 1.0; + // The frame is done when all the subdevices are done, so the total progress + // works out to be the average + float progress = 0.0; for (size_t i = 0; i < fb->objects.size(); ++i) { FrameBuffer *fbi = (FrameBuffer *)fb->objects[i]; - float pn = fbi->getCurrentProgress(); - if (pn < progress) { - progress = pn; - } + progress += fbi->getCurrentProgress(); } - return progress; + return progress / fb->objects.size(); } inline float MultiDeviceRenderTask::getTaskDuration() { - return taskDuration.load(); + return taskDuration.load(); } } // namespace api diff --git a/modules/pluggableGeometryExample/CMakeLists.txt b/modules/pluggableGeometryExample/CMakeLists.txt index d13406c4cd..9fe86f9ca8 100644 --- a/modules/pluggableGeometryExample/CMakeLists.txt +++ b/modules/pluggableGeometryExample/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # Define an option to enable/disable this module. diff --git a/modules/pluggableGeometryExample/ospray/CMakeLists.txt b/modules/pluggableGeometryExample/ospray/CMakeLists.txt index 7cb962a8d4..b47258f16b 100644 --- a/modules/pluggableGeometryExample/ospray/CMakeLists.txt +++ b/modules/pluggableGeometryExample/ospray/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # this subdirectory builds the actual ospray plugin into a library diff --git a/modules/pluggableGeometryExample/ospray/geometry/BilinearPatches.cpp b/modules/pluggableGeometryExample/ospray/geometry/BilinearPatches.cpp index d63afccbd2..97b06ebd66 100644 --- a/modules/pluggableGeometryExample/ospray/geometry/BilinearPatches.cpp +++ b/modules/pluggableGeometryExample/ospray/geometry/BilinearPatches.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "BilinearPatches.h" @@ -7,58 +7,45 @@ // ospray core: #include -/*! _everything_ in the ospray core universe should _always_ be in the - 'ospray' namespace. */ +// _everything_ in the ospray core universe should _always_ be in the +// 'ospray' namespace. namespace ospray { -/*! though not required, it is good practice to put any module into - its own namespace (isnide of ospray:: ). Unlike for the naming of - library and init function, the naming for this namespace doesn't - particularlly matter. E.g., 'bilinearPatch', 'module_blp', - 'bilinar_patch' etc would all work equally well. */ +// though not required, it is good practice to put any module into +// its own namespace (isnide of ospray:: ). Unlike for the naming of +// library and init function, the naming for this namespace doesn't +// particularlly matter. E.g., 'bilinearPatch', 'module_blp', +// 'bilinar_patch' etc would all work equally well. namespace blp { BilinearPatches::BilinearPatches() { - /*! create the 'ispc equivalent': ie, the ispc-side class that - implements all the ispc-side code for intersection, - postintersect, etc. See BilinearPatches.ispc */ - ispcEquivalent = ispc::BilinearPatches_create(); + getSh()->super.postIntersect = ispc::BilinearPatches_postIntersect_addr(); } -/*! commit - this is the function that parses all the parameters - that the app has proivded for this geometry. In this simple - example we're looking for a single parameter named 'patches', - which is supposed to contain a data array of all the patches' - control points */ +// commit - this is the function that parses all the parameters +// that the app has proivded for this geometry. In this simple +// example we're looking for a single parameter named 'patches', +// which is supposed to contain a data array of all the patches' +// control points. void BilinearPatches::commit() { - // The embree device is available on commit, but not in the constructor - // as it is set by the device creating this geometry - if (!embreeDevice) { - throw std::runtime_error("invalid Embree device"); - } - if (!embreeGeometry) { - embreeGeometry = rtcNewGeometry(embreeDevice, RTC_GEOMETRY_TYPE_USER); - } - - this->patchesData = getParamDataT("vertices", true); - + patchesData = getParamDataT("vertices", true); if (!patchesData && !patchesData->compact()) throw std::runtime_error("BilinearPatches needs compact 'vertices' data!"); - // look at the data we were provided with .... - size_t numPatchesInInput = numPrimitives(); - - ispc::BilinearPatches_finalize( - getIE(), embreeGeometry, (float *)patchesData->data(), numPatchesInInput); + createEmbreeUserGeometry((RTCBoundsFunction)&ispc::BilinearPatches_bounds, + (RTCIntersectFunctionN)&ispc::BilinearPatches_intersect, + (RTCOccludedFunctionN)&ispc::BilinearPatches_occluded); + getSh()->patchArray = (ispc::Patch *)patchesData->data(); + getSh()->super.numPrimitives = numPrimitives(); postCreationInfo(patchesData->size()); } size_t BilinearPatches::numPrimitives() const { - return patchesData->size() * sizeOf(patchesData->type) / sizeof(Patch); + return patchesData->size() * sizeOf(patchesData->type) / sizeof(ispc::Patch); } } // namespace blp diff --git a/modules/pluggableGeometryExample/ospray/geometry/BilinearPatches.h b/modules/pluggableGeometryExample/ospray/geometry/BilinearPatches.h index 41ee0ceed4..d5f858f7e0 100644 --- a/modules/pluggableGeometryExample/ospray/geometry/BilinearPatches.h +++ b/modules/pluggableGeometryExample/ospray/geometry/BilinearPatches.h @@ -1,73 +1,73 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once -/*! \file ospray/geometry/BilinearPatches.h Defines a new ospray - geometry type (of name 'bilinear_patches'). Input to the geometry is - a single data array (named 'patches') that consists of for vec3fs - per patch. */ +// ospray/geometry/BilinearPatches.h Defines a new ospray +// geometry type (of name 'bilinear_patches'). Input to the geometry is +// a single data array (named 'patches') that consists of for vec3fs +// per patch. // ospcomon: vec3f, box3f, etcpp - generic helper stuff #include "rkcommon/math/box.h" #include "rkcommon/math/vec.h" // ospray: everything that's related to the ospray ray tracing core #include "geometry/Geometry.h" +// ispc shared: header containing structures shared with ispc +#include "BilinearPatchesShared.h" -/*! _everything_ in the ospray core universe should _always_ be in the - 'ospray' namespace. */ +// _everything_ in the ospray core universe should _always_ be in the +// 'ospray' namespace. namespace ospray { -/*! though not required, it is good practice to put any module into - its own namespace (isnide of ospray:: ). Unlike for the naming of - library and init function, the naming for this namespace doesn't - particularlly matter. E.g., 'bilinearPatch', 'module_blp', - 'bilinar_patch' etc would all work equally well. */ +// though not required, it is good practice to put any module into +// its own namespace (isnide of ospray:: ). Unlike for the naming of +// library and init function, the naming for this namespace doesn't +// particularlly matter. E.g., 'bilinearPatch', 'module_blp', +// 'bilinar_patch' etc would all work equally well. namespace blp { // import rkcommon component - vec3f etc using namespace rkcommon; -/*! a geometry type that implements (a set of) bi-linear - patches. This implements a new ospray geometry, and as such has - to - - a) derive from ospray::Geometry - b) implement a 'commit()' message that parses the - parameters/data arrays that the app has specified as inputs - c) create an actual ospray geometry instance with the - proper intersect() and postIntersect() functions. - - Note that how this class is called does not particularly matter; - all that matters is under which name it is registered in the cpp - file (see comments on OSPRAY_REGISTER_GEOMETRY) -*/ -struct BilinearPatches : public ospray::Geometry +// a geometry type that implements (a set of) bi-linear +// patches. This implements a new ospray geometry, and as such has +// to +// a) derive from ospray::Geometry +// b) implement a 'commit()' message that parses the +// parameters/data arrays that the app has specified as inputs +// c) create an actual ospray geometry instance with the +// proper intersect() and postIntersect() functions. +// Note that how this class is called does not particularly matter; +// all that matters is under which name it is registered in the cpp +// file (see comments on OSPRAY_REGISTER_GEOMETRY) +struct BilinearPatches : public AddStructShared { - /*! data layout of a single patch. note we do not actually use - this class anywhere on the c++ side of this example, it is - only for illustrative purposes. The input data should come - as a data array of N such patches (we compute N - automatically based on the size of this array) */ - struct Patch - { - vec3f controlPoint[2][2]; - }; + // data layout of a single patch. note we do not actually use + // this class anywhere on the c++ side of this example, it is + // only for illustrative purposes. The input data should come + // as a data array of N such patches (we compute N + // automatically based on the size of this array) + // + // struct Patch + // { + // vec3f controlPoint[2][2]; + // }; BilinearPatches(); virtual ~BilinearPatches() override = default; - /*! the commit() message that gets called upon the app calling - "ospCommit()" */ + // the commit() message that gets called upon the app calling + // "ospCommit()" virtual void commit() override; virtual size_t numPrimitives() const override; protected: - /*! the input data array. the data array contains a list of - patches, each of which consists of four vec3fs. Note in this - example we do not particularly care about whether this comes - as a plain array of floats (with 12 floats per patch), or as - a array of vec3fs. */ + // the input data array. the data array contains a list of + // patches, each of which consists of four vec3fs. Note in this + // example we do not particularly care about whether this comes + // as a plain array of floats (with 12 floats per patch), or as + // a array of vec3fs. Ref> patchesData; }; diff --git a/modules/pluggableGeometryExample/ospray/geometry/BilinearPatches.ispc b/modules/pluggableGeometryExample/ospray/geometry/BilinearPatches.ispc index 2f80de6244..6b8aa3ef17 100644 --- a/modules/pluggableGeometryExample/ospray/geometry/BilinearPatches.ispc +++ b/modules/pluggableGeometryExample/ospray/geometry/BilinearPatches.ispc @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray @@ -7,26 +7,10 @@ #include "math/LinearSpace.ih" #include "rkcommon/math/box.ih" #include "rkcommon/math/vec.ih" +// c++ shared +#include "BilinearPatchesShared.h" -/*! input data for a single patch */ -struct Patch -{ - vec3f v00, v01, v10, v11; -}; - -struct BilinearPatches -{ - /*! inherit from "Geometry" class: since ISPC doesn't support - inheritance we simply put the "parent" class as the first - member; this way any typecast to the parent class will get the - right members (including 'virtual' function pointers, etc) */ - Geometry super; - - size_t numPatches; - Patch *uniform patchArray; -}; - -static void BilinearPatches_postIntersect(const Geometry *uniform geometry, +void BilinearPatches_postIntersect(const Geometry *uniform geometry, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags) @@ -36,28 +20,11 @@ static void BilinearPatches_postIntersect(const Geometry *uniform geometry, dg.Ng = dg.Ns = normalize(ray.Ng); } -/*! create a new ispc equivalent for the C++ class (this returns a void * that - the c++ side can use to call back to us when needed. Note this return values - _has_ to be a untyped 'void*' because ISPC cannot currently export 'real' - class types - with function pointers etcpp - to a c header file */ -export void *uniform BilinearPatches_create() -{ - BilinearPatches *uniform self = uniform new uniform BilinearPatches; - - /* recursively call the 'inherited' constructor, and pass our - 'overridden' functions for intersect and postintersect. note we - do not have to set the 'intersect' and 'occluded' functions - because we use embree to do the traversal for us (see - BilinearPatches_set()) below */ - Geometry_Constructor(&self->super, BilinearPatches_postIntersect); - return self; -} - -/*! to be able to have embree build a data structure over us we have - to be able to tell it the bounding box for each primitimve. this - is the callback embree calls for querying the (uniform) bounding - box for a single given primitmive 'primID' */ -unmasked void BilinearPatches_bounds( +// to be able to have embree build a data structure over us we have +// to be able to tell it the bounding box for each primitimve. this +// is the callback embree calls for querying the (uniform) bounding +// box for a single given primitmive 'primID' +export void BilinearPatches_bounds( const RTCBoundsFunctionArguments *uniform args) { uniform BilinearPatches *uniform self = @@ -204,11 +171,11 @@ bool recursiveBisection(varying Ray &ray, } } -/*! this is the function callback the embree calls to compute a single - ray-primitive intersection. For sake of simplicity we'll use a very, - very simple recursive test here - this is neither fast nor elegant, - but does show that you can do mere arbitrary stuff in a ISPC kernel, - including 'true' recursion. */ +// this is the function callback the embree calls to compute a single +// ray-primitive intersection. For sake of simplicity we'll use a very, +// very simple recursive test here - this is neither fast nor elegant, +// but does show that you can do mere arbitrary stuff in a ISPC kernel, +// including 'true' recursion. void BilinearPatches_intersect_kernel( const RTCIntersectFunctionNArguments *uniform args, const uniform bool isOcclusionTest) @@ -254,51 +221,19 @@ void BilinearPatches_intersect_kernel( } } -unmasked void BilinearPatches_intersect( +export void BilinearPatches_intersect( const struct RTCIntersectFunctionNArguments *uniform args) { BilinearPatches_intersect_kernel(args, false); } -unmasked void BilinearPatches_occluded( +export void BilinearPatches_occluded( const struct RTCIntersectFunctionNArguments *uniform args) { BilinearPatches_intersect_kernel(args, true); } -/*! the function called by BilinearPatches::commit() to pass the - actual user data over. for simplicity we assume that this functoin - gets called exactly once; in practice a user may also _change_ an - existing class'es data members, but handling this would make this - code significantly larger */ -export void BilinearPatches_finalize(void *uniform _self, - void *uniform _embreeGeometry, - float *uniform patchesDataMemory, - uniform size_t numPatches) +export void *uniform BilinearPatches_postIntersect_addr() { - // first, typecast to our 'real' type. since ispc can't export real - // types to c we have to pass 'self' in as a void*, and typecast - // here. - BilinearPatches *uniform self = (BilinearPatches * uniform) _self; - - // set our internal data. - self->numPatches = numPatches; - self->patchArray = (Patch * uniform) patchesDataMemory; - - RTCGeometry geom = (RTCGeometry)_embreeGeometry; - - rtcSetGeometryUserPrimitiveCount(geom, numPatches); - - // set 'us' as user data (this will be the first arg in intersect() - // and computebounds() callbacks - rtcSetGeometryUserData(geom, self); - - // set function pointers: - rtcSetGeometryBoundsFunction( - geom, (uniform RTCBoundsFunction)&BilinearPatches_bounds, self); - rtcSetGeometryIntersectFunction( - geom, (uniform RTCIntersectFunctionN)&BilinearPatches_intersect); - rtcSetGeometryOccludedFunction( - geom, (uniform RTCOccludedFunctionN)&BilinearPatches_occluded); - rtcCommitGeometry(geom); + return BilinearPatches_postIntersect; } diff --git a/modules/pluggableGeometryExample/ospray/geometry/BilinearPatchesShared.h b/modules/pluggableGeometryExample/ospray/geometry/BilinearPatchesShared.h new file mode 100644 index 0000000000..22246784e7 --- /dev/null +++ b/modules/pluggableGeometryExample/ospray/geometry/BilinearPatchesShared.h @@ -0,0 +1,35 @@ +// Copyright 2022 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "geometry/GeometryShared.h" + +#ifdef __cplusplus +namespace ispc { +#endif // __cplusplus + +// input data for a single patch +struct Patch +{ + vec3f v00, v01, v10, v11; +}; + +struct BilinearPatches +{ + // inherit from "Geometry" class: since ISPC doesn't support + // inheritance we simply put the "parent" class as the first + // member; this way any typecast to the parent class will get the + // right members (including 'virtual' function pointers, etc) + Geometry super; + + size_t numPatches; + Patch *patchArray; + +#ifdef __cplusplus + BilinearPatches() : numPatches(0), patchArray(nullptr) {} +}; +} // namespace ispc +#else +}; +#endif // __cplusplus diff --git a/modules/pluggableGeometryExample/ospray/moduleInit.cpp b/modules/pluggableGeometryExample/ospray/moduleInit.cpp index 54715783f7..153cddc3de 100644 --- a/modules/pluggableGeometryExample/ospray/moduleInit.cpp +++ b/modules/pluggableGeometryExample/ospray/moduleInit.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /*! \file ospray/moduleInit \brief Defines the module initialization callback */ diff --git a/ospray/CMakeLists.txt b/ospray/CMakeLists.txt index 90f43fbf62..baf1c60b57 100644 --- a/ospray/CMakeLists.txt +++ b/ospray/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # ------------------------------------------------------- @@ -51,13 +51,6 @@ foreach(dir ${SUBDIRS}) COMPONENT devel FILES_MATCHING PATTERN *.h - PATTERN *.ih - ) - install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${dir} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ospray/SDK - COMPONENT devel - FILES_MATCHING - PATTERN *_ispc.h ) endif() endforeach() diff --git a/ospray/api/API.cpp b/ospray/api/API.cpp index 5a8d93899b..6f394c1b57 100644 --- a/ospray/api/API.cpp +++ b/ospray/api/API.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "rkcommon/os/library.h" @@ -176,7 +176,7 @@ extern "C" void ospSetCurrentDevice(OSPDevice _device) OSPRAY_CATCH_BEGIN { auto *device = (Device *)_device; - if (!device->isCommitted()) { + if ((device) && (!device->isCommitted())) { throw std::runtime_error("You must commit the device before using it!"); } diff --git a/ospray/api/Device.cpp b/ospray/api/Device.cpp index e03a25e269..10158b17ca 100644 --- a/ospray/api/Device.cpp +++ b/ospray/api/Device.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray diff --git a/ospray/api/Device.h b/ospray/api/Device.h index 7b98b59791..f14c30562f 100644 --- a/ospray/api/Device.h +++ b/ospray/api/Device.h @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/api/ospray_cpp_defs.cpp b/ospray/api/ospray_cpp_defs.cpp index de9c5c4775..5de043d95e 100644 --- a/ospray/api/ospray_cpp_defs.cpp +++ b/ospray/api/ospray_cpp_defs.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/OSPCommon.h" diff --git a/ospray/api/ospray_util_impl.cpp b/ospray/api/ospray_util_impl.cpp index 942035e9fd..55e28a04a3 100644 --- a/ospray/api/ospray_util_impl.cpp +++ b/ospray/api/ospray_util_impl.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ospray/ospray_cpp.h" diff --git a/ospray/common/Library.h b/ospray/common/Library.h index 33a8c82461..43f055385c 100644 --- a/ospray/common/Library.h +++ b/ospray/common/Library.h @@ -1,4 +1,4 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/common/OSPCommon.cpp b/ospray/common/OSPCommon.cpp index 51fdccd14a..9459e21a1d 100644 --- a/ospray/common/OSPCommon.cpp +++ b/ospray/common/OSPCommon.cpp @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // must be first diff --git a/ospray/common/OSPCommon.h b/ospray/common/OSPCommon.h index b30627ca61..2d6681920d 100644 --- a/ospray/common/OSPCommon.h +++ b/ospray/common/OSPCommon.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/common/Util.h b/ospray/common/Util.h index d2c332eb8d..9e46078ebc 100644 --- a/ospray/common/Util.h +++ b/ospray/common/Util.h @@ -1,8 +1,10 @@ -// Copyright 2009-2020 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once +#include "OSPCommon.h" + namespace ospray { template diff --git a/ospray/include/ospray/OSPEnums.h b/ospray/include/ospray/OSPEnums.h index 59cb65c71f..cfcee2434f 100644 --- a/ospray/include/ospray/OSPEnums.h +++ b/ospray/include/ospray/OSPEnums.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // This header is shared with ISPC @@ -241,7 +241,10 @@ typedef enum OSP_FB_ACCUM = (1 << 2), OSP_FB_VARIANCE = (1 << 3), OSP_FB_NORMAL = (1 << 4), // in world-space - OSP_FB_ALBEDO = (1 << 5) + OSP_FB_ALBEDO = (1 << 5), + OSP_FB_ID_PRIMITIVE = (1 << 6), + OSP_FB_ID_OBJECT = (1 << 7), + OSP_FB_ID_INSTANCE = (1 << 8) } OSPFrameBufferChannel; // OSPRay events which can be waited on via ospWait() @@ -346,7 +349,7 @@ typedef enum OSP_AMR_OCTANT } OSPAMRMethod; -// Filter modes that can be set on 'VDB' type OSPVolume, compatible with VKL +// Filter modes for VDB and structured volumes, compatible with VKL typedef enum #if __cplusplus >= 201103L : uint32_t @@ -357,6 +360,16 @@ typedef enum OSP_VOLUME_FILTER_TRICUBIC = 200 // tricubic interpolation } OSPVolumeFilter; +// VDB node data format +typedef enum +#if __cplusplus > 201103L + : uint32_t +#endif +{ + OSP_VOLUME_FORMAT_TILE = 0, // node with no spatial variation. + OSP_VOLUME_FORMAT_DENSE_ZYX // a dense grid of voxels in zyx layout +} OSPVolumeFormat; + // OSPRay pixel filter types typedef enum #if __cplusplus >= 201103L diff --git a/ospray/include/ospray/ospray.h b/ospray/include/ospray/ospray.h index f0a1de8b25..c83a9994b1 100644 --- a/ospray/include/ospray/ospray.h +++ b/ospray/include/ospray/ospray.h @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp.h b/ospray/include/ospray/ospray_cpp.h index bcdd7fcb11..50284426d4 100644 --- a/ospray/include/ospray/ospray_cpp.h +++ b/ospray/include/ospray/ospray_cpp.h @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // \file ospray/ospray.h Defines the external OSPRay API */ diff --git a/ospray/include/ospray/ospray_cpp/Camera.h b/ospray/include/ospray/ospray_cpp/Camera.h index 305fe25fe5..09edc1e467 100644 --- a/ospray/include/ospray/ospray_cpp/Camera.h +++ b/ospray/include/ospray/ospray_cpp/Camera.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp/Data.h b/ospray/include/ospray/ospray_cpp/Data.h index 8ed4e862d9..defdbcfb6c 100644 --- a/ospray/include/ospray/ospray_cpp/Data.h +++ b/ospray/include/ospray/ospray_cpp/Data.h @@ -1,4 +1,4 @@ -// Copyright 2009-2022 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp/Device.h b/ospray/include/ospray/ospray_cpp/Device.h index e6abefea32..7a850cf2ae 100644 --- a/ospray/include/ospray/ospray_cpp/Device.h +++ b/ospray/include/ospray/ospray_cpp/Device.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp/FrameBuffer.h b/ospray/include/ospray/ospray_cpp/FrameBuffer.h index fd938011b7..e3ebe689f5 100644 --- a/ospray/include/ospray/ospray_cpp/FrameBuffer.h +++ b/ospray/include/ospray/ospray_cpp/FrameBuffer.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp/Future.h b/ospray/include/ospray/ospray_cpp/Future.h index f44b01d886..58c4d835ea 100644 --- a/ospray/include/ospray/ospray_cpp/Future.h +++ b/ospray/include/ospray/ospray_cpp/Future.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp/GeometricModel.h b/ospray/include/ospray/ospray_cpp/GeometricModel.h index b1362c4124..b0656ef0be 100644 --- a/ospray/include/ospray/ospray_cpp/GeometricModel.h +++ b/ospray/include/ospray/ospray_cpp/GeometricModel.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp/Geometry.h b/ospray/include/ospray/ospray_cpp/Geometry.h index bf8ba27ba6..6154104a01 100644 --- a/ospray/include/ospray/ospray_cpp/Geometry.h +++ b/ospray/include/ospray/ospray_cpp/Geometry.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp/Group.h b/ospray/include/ospray/ospray_cpp/Group.h index 3166819a94..65214a2b14 100644 --- a/ospray/include/ospray/ospray_cpp/Group.h +++ b/ospray/include/ospray/ospray_cpp/Group.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp/ImageOperation.h b/ospray/include/ospray/ospray_cpp/ImageOperation.h index c2ed8c0da5..450750b17c 100644 --- a/ospray/include/ospray/ospray_cpp/ImageOperation.h +++ b/ospray/include/ospray/ospray_cpp/ImageOperation.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp/Instance.h b/ospray/include/ospray/ospray_cpp/Instance.h index 14124d9316..61a0c1b2dd 100644 --- a/ospray/include/ospray/ospray_cpp/Instance.h +++ b/ospray/include/ospray/ospray_cpp/Instance.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp/Light.h b/ospray/include/ospray/ospray_cpp/Light.h index 871d12a32a..802f53c285 100644 --- a/ospray/include/ospray/ospray_cpp/Light.h +++ b/ospray/include/ospray/ospray_cpp/Light.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp/ManagedObject.h b/ospray/include/ospray/ospray_cpp/ManagedObject.h index 63ebed8c51..429c8c7442 100644 --- a/ospray/include/ospray/ospray_cpp/ManagedObject.h +++ b/ospray/include/ospray/ospray_cpp/ManagedObject.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp/Material.h b/ospray/include/ospray/ospray_cpp/Material.h index 843207fe8b..ff7a2e3efb 100644 --- a/ospray/include/ospray/ospray_cpp/Material.h +++ b/ospray/include/ospray/ospray_cpp/Material.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp/Renderer.h b/ospray/include/ospray/ospray_cpp/Renderer.h index 3b850a1a99..7b5d90fa68 100644 --- a/ospray/include/ospray/ospray_cpp/Renderer.h +++ b/ospray/include/ospray/ospray_cpp/Renderer.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp/Texture.h b/ospray/include/ospray/ospray_cpp/Texture.h index 27961d8710..109b112a78 100644 --- a/ospray/include/ospray/ospray_cpp/Texture.h +++ b/ospray/include/ospray/ospray_cpp/Texture.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp/Traits.h b/ospray/include/ospray/ospray_cpp/Traits.h index d6f81f28e7..205a2bba61 100644 --- a/ospray/include/ospray/ospray_cpp/Traits.h +++ b/ospray/include/ospray/ospray_cpp/Traits.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -78,6 +78,7 @@ OSPTYPEFOR_SPECIALIZATION(OSPAMRMethod, OSP_UCHAR); OSPTYPEFOR_SPECIALIZATION(OSPSubdivisionMode, OSP_UCHAR); OSPTYPEFOR_SPECIALIZATION(OSPPixelFilterTypes, OSP_UCHAR); OSPTYPEFOR_SPECIALIZATION(OSPIntensityQuantity, OSP_UCHAR); +OSPTYPEFOR_SPECIALIZATION(OSPVolumeFormat, OSP_UINT); #define OSPTYPEFOR_DEFINITION(type) \ constexpr OSPDataType OSPTypeFor::value diff --git a/ospray/include/ospray/ospray_cpp/TransferFunction.h b/ospray/include/ospray/ospray_cpp/TransferFunction.h index 320cd09912..19eefeefea 100644 --- a/ospray/include/ospray/ospray_cpp/TransferFunction.h +++ b/ospray/include/ospray/ospray_cpp/TransferFunction.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp/Volume.h b/ospray/include/ospray/ospray_cpp/Volume.h index 7300124f98..ec6f9b36d2 100644 --- a/ospray/include/ospray/ospray_cpp/Volume.h +++ b/ospray/include/ospray/ospray_cpp/Volume.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp/VolumetricModel.h b/ospray/include/ospray/ospray_cpp/VolumetricModel.h index 839193dd95..d3859c3b57 100644 --- a/ospray/include/ospray/ospray_cpp/VolumetricModel.h +++ b/ospray/include/ospray/ospray_cpp/VolumetricModel.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp/World.h b/ospray/include/ospray/ospray_cpp/World.h index 9112bd94f1..95f5d78b66 100644 --- a/ospray/include/ospray/ospray_cpp/World.h +++ b/ospray/include/ospray/ospray_cpp/World.h @@ -1,4 +1,4 @@ -// Copyright 2009-2021 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_cpp/ext/rkcommon.h b/ospray/include/ospray/ospray_cpp/ext/rkcommon.h index fe41e44573..1179e2b2a1 100644 --- a/ospray/include/ospray/ospray_cpp/ext/rkcommon.h +++ b/ospray/include/ospray/ospray_cpp/ext/rkcommon.h @@ -1,4 +1,4 @@ -// Copyright 2020-2021 Intel Corporation +// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/include/ospray/ospray_util.h b/ospray/include/ospray/ospray_util.h index 98f689a418..04caf7d3fe 100644 --- a/ospray/include/ospray/ospray_util.h +++ b/ospray/include/ospray/ospray_util.h @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once diff --git a/ospray/ospray.rc b/ospray/ospray.rc index dfa42849b2..0360c91f7d 100644 --- a/ospray/ospray.rc +++ b/ospray/ospray.rc @@ -1,4 +1,4 @@ -// Copyright 2016-2020 Intel Corporation +// Copyright 2016 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ospray/version.h" @@ -24,7 +24,7 @@ BEGIN VALUE "FileDescription", "OSPRay Ray Tracing Rendering Engine" VALUE "FileVersion", OSPRAY_VERSION VALUE "ProductVersion", OSPRAY_VERSION - VALUE "LegalCopyright", "© 2009-2021 Intel Corporation" + VALUE "LegalCopyright", "© 2009 Intel Corporation" VALUE "InternalName", "OSPRay" VALUE "ProductName", "Intel® OSPRay" END diff --git a/ospray/version.h.in b/ospray/version.h.in index bc648bfe2e..7da6fa5187 100644 --- a/ospray/version.h.in +++ b/ospray/version.h.in @@ -1,4 +1,4 @@ -// Copyright 2009-2019 Intel Corporation +// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #define OSPRAY_VERSION_MAJOR @OSPRAY_VERSION_MAJOR@ diff --git a/scripts/build_gitlab/kw.sh b/scripts/build_gitlab/kw.sh index ebe0176fb3..3236b8ef6e 100755 --- a/scripts/build_gitlab/kw.sh +++ b/scripts/build_gitlab/kw.sh @@ -1,5 +1,5 @@ #!/bin/bash -## Copyright 2019-2021 Intel Corporation +## Copyright 2019 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set -e diff --git a/scripts/build_gitlab/linux.sh b/scripts/build_gitlab/linux.sh index 6021ae0c0e..6711ee65a9 100755 --- a/scripts/build_gitlab/linux.sh +++ b/scripts/build_gitlab/linux.sh @@ -1,5 +1,5 @@ #!/bin/bash -## Copyright 2015-2020 Intel Corporation +## Copyright 2015 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 mkdir build diff --git a/scripts/build_gitlab/win.ps1 b/scripts/build_gitlab/win.ps1 index 0be1ae7b3b..27e6f8178f 100755 --- a/scripts/build_gitlab/win.ps1 +++ b/scripts/build_gitlab/win.ps1 @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 md build diff --git a/scripts/files-to-md5.sh b/scripts/files-to-md5.sh index d6ab85ece9..a279713f06 100755 --- a/scripts/files-to-md5.sh +++ b/scripts/files-to-md5.sh @@ -1,5 +1,5 @@ #!/bin/bash -## Copyright 2017-2019 Intel Corporation +## Copyright 2017 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # This script should be called from build directory (OSPRay root should be in ../) diff --git a/scripts/install_linux_gcc.sh b/scripts/install_linux_gcc.sh index cb4674b495..67e08a9871 100755 --- a/scripts/install_linux_gcc.sh +++ b/scripts/install_linux_gcc.sh @@ -1,5 +1,5 @@ #!/bin/bash -## Copyright 2014-2019 Intel Corporation +## Copyright 2014 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 dest=$HOME/devtools-2 diff --git a/scripts/release/linux.sh b/scripts/release/linux.sh index 811931737c..2ac2997008 100755 --- a/scripts/release/linux.sh +++ b/scripts/release/linux.sh @@ -1,5 +1,5 @@ #!/bin/bash -## Copyright 2014-2021 Intel Corporation +## Copyright 2014 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 #### Helper functions #### diff --git a/scripts/release/macosx.sh b/scripts/release/macosx.sh index d3a8a664c0..e65405737a 100755 --- a/scripts/release/macosx.sh +++ b/scripts/release/macosx.sh @@ -1,5 +1,5 @@ #!/bin/bash -## Copyright 2014-2021 Intel Corporation +## Copyright 2014 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 #### Helper functions #### diff --git a/scripts/release/macosx_notarization.sh b/scripts/release/macosx_notarization.sh index a4f24494e0..08a504314f 100755 --- a/scripts/release/macosx_notarization.sh +++ b/scripts/release/macosx_notarization.sh @@ -1,5 +1,5 @@ #!/bin/bash -## Copyright 2014-2020 Intel Corporation +## Copyright 2014 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set -e # terminate if some error occurs diff --git a/scripts/release/win.ps1 b/scripts/release/win.ps1 index 64f9ce4112..b6d226cdf4 100755 --- a/scripts/release/win.ps1 +++ b/scripts/release/win.ps1 @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 $ROOT_DIR = pwd diff --git a/scripts/scan/bdba.sh b/scripts/scan/bdba.sh index cff43f201d..ecbb965e53 100755 --- a/scripts/scan/bdba.sh +++ b/scripts/scan/bdba.sh @@ -1,5 +1,5 @@ #!/bin/bash -## Copyright 2019-2021 Intel Corporation +## Copyright 2019 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 files=$1 diff --git a/scripts/scan/kw-check-issues.sh b/scripts/scan/kw-check-issues.sh index 1307aa725b..79c0c3186a 100755 --- a/scripts/scan/kw-check-issues.sh +++ b/scripts/scan/kw-check-issues.sh @@ -1,5 +1,5 @@ #!/bin/bash -xe -## Copyright 2020-2021 Intel Corporation +## Copyright 2020 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 KW_ISSUES_FILE=/tmp/issues diff --git a/scripts/scan/kw-gen-report.sh b/scripts/scan/kw-gen-report.sh index ec9f6af2ed..c364b62b31 100755 --- a/scripts/scan/kw-gen-report.sh +++ b/scripts/scan/kw-gen-report.sh @@ -1,5 +1,5 @@ #!/bin/bash -xe -## Copyright 2020-2021 Intel Corporation +## Copyright 2020 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 KW_SERVER_API_URL=http://$KW_SERVER_IP:$KW_SERVER_PORT/review/api diff --git a/scripts/scan/protex.sh b/scripts/scan/protex.sh index 288897bc26..be47cea11d 100755 --- a/scripts/scan/protex.sh +++ b/scripts/scan/protex.sh @@ -1,5 +1,5 @@ #!/bin/bash -## Copyright 2020-2021 Intel Corporation +## Copyright 2020 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # enable early exit on fail diff --git a/scripts/scan/store-files.sh b/scripts/scan/store-files.sh index 56de756f59..cffe2f574d 100755 --- a/scripts/scan/store-files.sh +++ b/scripts/scan/store-files.sh @@ -1,5 +1,5 @@ #!/bin/bash -xe -## Copyright 2019-2021 Intel Corporation +## Copyright 2019 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 project_name=$1 diff --git a/scripts/superbuild/CMakeLists.txt b/scripts/superbuild/CMakeLists.txt index 8ba036c980..88fc3fc69b 100644 --- a/scripts/superbuild/CMakeLists.txt +++ b/scripts/superbuild/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2022 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ## Global settings ## @@ -68,24 +68,24 @@ option(ALWAYS_REBUILD "Force every project to always be rebuilt?" OFF) option(DOWNLOAD_ISPC "Download ISPC or use the one found in the system environment?" ON) if (DOWNLOAD_ISPC) - set(ISPC_VERSION "1.17.0" CACHE STRING "Which version of ISPC to download?") + set(ISPC_VERSION "1.18.0" CACHE STRING "Which version of ISPC to download?") mark_as_advanced(CLEAR ISPC_VERSION) - if (ISPC_VERSION STREQUAL "1.17.0") + if (ISPC_VERSION STREQUAL "1.18.0") if (APPLE) - set(ISPC_HASH "e7fdcdbd5c272955249148c452ccd7295d7cf77b35ca1dec377e72b49c847bff") + set(ISPC_HASH "d1435b541182406ff6b18446d31ecceef0eae3aed7654391ae676d3142e0000d") elseif (WIN32) - set(ISPC_HASH "e9a7cc98f69357482985bcbf69fa006632cee7b3606069b4d5e16dc62092d660") + set(ISPC_HASH "9210bb2d9d3711367faccb37acf49966696132560b565471c1c6121f4924a17e") else() - set(ISPC_HASH "6acc5df75efdce437f79b1b6489be8567c6d009e19dcc4851b9b37012afce1f7") + set(ISPC_HASH "6c379bb97962e9de7d24fd48b3f7e647dc42be898e9d187948220268c646b692") endif() endif() else() mark_as_advanced(FORCE ISPC_VERSION) endif() -set(RKCOMMON_VERSION "1.9.0" CACHE STRING "Which version of rkcommon to build?") -if (RKCOMMON_VERSION STREQUAL "1.9.0") - set(RKCOMMON_HASH "54ef58226b5f2b6eb80091d806b94d563ce748a6c8d04db7836c20945fd99929") +set(RKCOMMON_VERSION "1.10.0" CACHE STRING "Which version of rkcommon to build?") +if (RKCOMMON_VERSION STREQUAL "1.10.0") + set(RKCOMMON_HASH "eb968868b85254680c59ff3e091e9a7634d407cf0375d2b52840bf9044716a48") endif() option(DOWNLOAD_TBB "Download TBB or use the one found in the system environment?" ON) @@ -128,9 +128,9 @@ if (EMBREE_VERSION STREQUAL "3.13.3") endif() endif() -set(OPENVKL_VERSION "1.2.0" CACHE STRING "Which version of OpenVKL to build?") -if (OPENVKL_VERSION STREQUAL "1.2.0") - set(OPENVKL_HASH "5a3ae6cf4fc1379d326d929e91d3a95409d6e79773544ca12a02e28476ad905b") +set(OPENVKL_VERSION "1.3.0" CACHE STRING "Which version of OpenVKL to build?") +if (OPENVKL_VERSION STREQUAL "1.3.0") + set(OPENVKL_HASH "4e456dfa566a57e5f00da91a24ecbf76223d4e0722d12d978a9c07e0af26785d") endif() option(BUILD_OIDN "Build OpenImageDenoise as a part of the superbuild." OFF) @@ -163,6 +163,24 @@ option(BUILD_OSPRAY_MODULE_CPU "Enable building module_cpu" ON) option(BUILD_OSPRAY_MODULE_MPI "Enable building module_mpi" OFF) option(BUILD_OSPRAY_MODULE_MULTIDEVICE "Enable building module_multidevice" OFF) +if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm64|aarch64") + set(ISA_X86 OFF) + set(ISA_NEON ON) +else() + set(ISA_X86 ON) + set(ISA_NEON OFF) +endif() +option(BUILD_ISA_SSE4 "Build for SSE4" ${ISA_X86}) +mark_as_advanced(BUILD_ISA_SSE4) +option(BUILD_ISA_AVX "Build for AVX" ${ISA_X86}) +mark_as_advanced(BUILD_ISA_AVX) +option(BUILD_ISA_AVX2 "Build for AVX2" ${ISA_X86}) +mark_as_advanced(BUILD_ISA_AVX2) +option(BUILD_ISA_AVX512 "Build for AVX512" ${ISA_X86}) +mark_as_advanced(BUILD_ISA_AVX512) +option(BUILD_ISA_NEON "Build for NEON" ${ISA_NEON}) +mark_as_advanced(BUILD_ISA_NEON) + option(INSTALL_IN_SEPARATE_DIRECTORIES "Install libraries into their own directories under CMAKE_INSTALL_PREFIX" ON diff --git a/scripts/superbuild/build_ospray.cmake b/scripts/superbuild/build_ospray.cmake index d9e0482512..0d5e3b1718 100644 --- a/scripts/superbuild/build_ospray.cmake +++ b/scripts/superbuild/build_ospray.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME ospray) diff --git a/scripts/superbuild/dependencies/dep_benchmark.cmake b/scripts/superbuild/dependencies/dep_benchmark.cmake index 779dda6b13..4f54fec620 100644 --- a/scripts/superbuild/dependencies/dep_benchmark.cmake +++ b/scripts/superbuild/dependencies/dep_benchmark.cmake @@ -1,4 +1,4 @@ -## Copyright 2021-2022 Intel Corporation +## Copyright 2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME benchmark) diff --git a/scripts/superbuild/dependencies/dep_embree.cmake b/scripts/superbuild/dependencies/dep_embree.cmake index 8d4211fcc8..6f72fabb67 100644 --- a/scripts/superbuild/dependencies/dep_embree.cmake +++ b/scripts/superbuild/dependencies/dep_embree.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME embree) @@ -39,6 +39,11 @@ if (BUILD_EMBREE_FROM_SOURCE) -DBUILD_TESTING=OFF -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} + -DEMBREE_ISA_SSE42=${BUILD_ISA_SSE4} + -DEMBREE_ISA_AVX=${BUILD_ISA_AVX} + -DEMBREE_ISA_AVX2=${BUILD_ISA_AVX2} + -DEMBREE_ISA_AVX512=${BUILD_ISA_AVX512} + -DEMBREE_ISA_NEON=${BUILD_ISA_NEON} BUILD_COMMAND ${DEFAULT_BUILD_COMMAND} BUILD_ALWAYS ${ALWAYS_REBUILD} ) diff --git a/scripts/superbuild/dependencies/dep_glfw.cmake b/scripts/superbuild/dependencies/dep_glfw.cmake index c9d84d6307..9865c8a066 100644 --- a/scripts/superbuild/dependencies/dep_glfw.cmake +++ b/scripts/superbuild/dependencies/dep_glfw.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME glfw) diff --git a/scripts/superbuild/dependencies/dep_glm.cmake b/scripts/superbuild/dependencies/dep_glm.cmake index 5ee2313cab..2a2930cce6 100644 --- a/scripts/superbuild/dependencies/dep_glm.cmake +++ b/scripts/superbuild/dependencies/dep_glm.cmake @@ -1,4 +1,4 @@ -## Copyright 2020-2021 Intel Corporation +## Copyright 2020 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME glm) diff --git a/scripts/superbuild/dependencies/dep_gtest.cmake b/scripts/superbuild/dependencies/dep_gtest.cmake index fc59a83480..dbeac35f5d 100644 --- a/scripts/superbuild/dependencies/dep_gtest.cmake +++ b/scripts/superbuild/dependencies/dep_gtest.cmake @@ -21,6 +21,7 @@ ExternalProject_Add(${COMPONENT_NAME} -Dgtest_force_shared_crt=ON -DCMAKE_INSTALL_PREFIX:PATH=${COMPONENT_PATH} -DCMAKE_BUILD_TYPE=${DEPENDENCIES_BUILD_TYPE} + -DBUILD_GMOCK=OFF ) list(APPEND CMAKE_PREFIX_PATH ${COMPONENT_PATH}) diff --git a/scripts/superbuild/dependencies/dep_ispc.cmake b/scripts/superbuild/dependencies/dep_ispc.cmake index 34fef6e265..d174fd5fa5 100644 --- a/scripts/superbuild/dependencies/dep_ispc.cmake +++ b/scripts/superbuild/dependencies/dep_ispc.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME ispc) diff --git a/scripts/superbuild/dependencies/dep_oidn.cmake b/scripts/superbuild/dependencies/dep_oidn.cmake index 6393fcd404..7fa6891cfb 100644 --- a/scripts/superbuild/dependencies/dep_oidn.cmake +++ b/scripts/superbuild/dependencies/dep_oidn.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME oidn) diff --git a/scripts/superbuild/dependencies/dep_openvkl.cmake b/scripts/superbuild/dependencies/dep_openvkl.cmake index 41977f48dd..00dc44949d 100644 --- a/scripts/superbuild/dependencies/dep_openvkl.cmake +++ b/scripts/superbuild/dependencies/dep_openvkl.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME openvkl) @@ -40,6 +40,11 @@ ExternalProject_Add(${COMPONENT_NAME} -DBUILD_TESTING=OFF -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} + -DOPENVKL_ISA_SSE4=${BUILD_ISA_SSE4} + -DOPENVKL_ISA_AVX=${BUILD_ISA_AVX} + -DOPENVKL_ISA_AVX2=${BUILD_ISA_AVX2} + -DOPENVKL_ISA_AVX512SKX=${BUILD_ISA_AVX512} + -DOPENVKL_ISA_NEON=${BUILD_ISA_NEON} BUILD_COMMAND ${DEFAULT_BUILD_COMMAND} BUILD_ALWAYS ${ALWAYS_REBUILD} ) diff --git a/scripts/superbuild/dependencies/dep_rkcommon.cmake b/scripts/superbuild/dependencies/dep_rkcommon.cmake index 9b9656c9c3..4c40ea66cd 100644 --- a/scripts/superbuild/dependencies/dep_rkcommon.cmake +++ b/scripts/superbuild/dependencies/dep_rkcommon.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME rkcommon) diff --git a/scripts/superbuild/dependencies/dep_snappy.cmake b/scripts/superbuild/dependencies/dep_snappy.cmake index 7bcac0f266..34e9af003a 100644 --- a/scripts/superbuild/dependencies/dep_snappy.cmake +++ b/scripts/superbuild/dependencies/dep_snappy.cmake @@ -9,11 +9,17 @@ else() set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}) endif() +if (NOT WIN32) + set(PATCH sed -ie "s/size_t AdvanceToNextTag/inline \\0/" snappy.cc) +endif() + ExternalProject_Add(${COMPONENT_NAME} - URL "https://github.com/google/snappy/archive/refs/tags/1.1.8.zip" - URL_HASH "SHA256=38b4aabf88eb480131ed45bfb89c19ca3e2a62daeb081bdf001cfb17ec4cd303" + URL "https://github.com/google/snappy/archive/refs/tags/1.1.9.zip" + URL_HASH "SHA256=e170ce0def2c71d0403f5cda61d6e2743373f9480124bcfcd0fa9b3299d428d9" + + PATCH_COMMAND ${PATCH} - # # Skip updating on subsequent builds (faster) + # Skip updating on subsequent builds (faster) UPDATE_COMMAND "" CMAKE_ARGS diff --git a/scripts/superbuild/dependencies/dep_tbb.cmake b/scripts/superbuild/dependencies/dep_tbb.cmake index ca9f339a9b..ebdb57dd4f 100644 --- a/scripts/superbuild/dependencies/dep_tbb.cmake +++ b/scripts/superbuild/dependencies/dep_tbb.cmake @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME tbb) diff --git a/scripts/tests/README b/scripts/tests/README index a2f1d5e512..115d019439 100644 --- a/scripts/tests/README +++ b/scripts/tests/README @@ -14,7 +14,7 @@ to this directory as ${OSPRAY_BUILD_DIR}. Build OSPRay with OSPRAY_TESTING on. Only generate new images for a test that has changed. To generate new images for a specific -test run ./ospTestSuite --gtest_filter="*TESTNAME*" --dump-img test_image_data/ +test run ./ospTestSuite --gtest_filter="*TESTNAME*" --dump-img --baseline-dir=test_image_data/ which will create images in a folder called test_image_data. To make new images for all tests, In ${OSPRAY_BUILD_DIR}, run the @@ -24,16 +24,21 @@ To make new images for all tests, In ${OSPRAY_BUILD_DIR}, run the This will output generated images in a folder named generated_test_images. These images will not automatically be used as baseline images for the tests -unless put into the correct folder or the update script is used (5). +unless put into the correct folder (/build_regression_tests/regression_test_baseline/) +or the update script is used (5). 3. Run regression tests To verify whether a change to the codebase broke anything, run -% ${OSPRAY_SOURCE_DIR}/scripts/tests/run_tests.sh ${OSPRAY_SOURCE_DIR} +% ${OSPRAY_SOURCE_DIR}/scripts/tests/run_tests.sh ${OSPRAY_SOURCE_DIR} -This will download baseline images and run tests to compare them -in a folder named build_regression_tests. +* where ISA is empty if using own generated images, or "AVX2" or "AVX512SKX" to +* download golden images for that ISA target + +This will download golden baseline images into a folder named +build_regression_tests/regression_test_baseline in +the current working directory (OSPRAY_BUILD_DIR) and run tests to compare them. 4. To run an individual test ./ospTestSuite --gtest_list_tests diff --git a/scripts/tests/generate_baseline.bat b/scripts/tests/generate_baseline.bat index dcdbaef392..974c4479bb 100644 --- a/scripts/tests/generate_baseline.bat +++ b/scripts/tests/generate_baseline.bat @@ -1,5 +1,5 @@ @echo off -rem Copyright 2016-2020 Intel Corporation +rem Copyright 2016 Intel Corporation rem SPDX-License-Identifier: Apache-2.0 setlocal diff --git a/scripts/tests/generate_baseline.sh b/scripts/tests/generate_baseline.sh index 82542721ee..c27bc71e17 100755 --- a/scripts/tests/generate_baseline.sh +++ b/scripts/tests/generate_baseline.sh @@ -1,5 +1,5 @@ #!/bin/bash -## Copyright 2016-2020 Intel Corporation +## Copyright 2016 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # results are put in a new folder called generated_test_images diff --git a/scripts/tests/run_tests.ps1 b/scripts/tests/run_tests.ps1 index 879c0dc95f..46ed3a3485 100755 --- a/scripts/tests/run_tests.ps1 +++ b/scripts/tests/run_tests.ps1 @@ -1,4 +1,4 @@ -## Copyright 2009-2022 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # to run: ./run_tests.ps1 [TEST_MPI] diff --git a/scripts/tests/run_tests.sh b/scripts/tests/run_tests.sh index 048b7ff840..d7d8c4496c 100755 --- a/scripts/tests/run_tests.sh +++ b/scripts/tests/run_tests.sh @@ -1,5 +1,5 @@ #!/bin/bash -## Copyright 2016-2021 Intel Corporation +## Copyright 2016 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # to run: ./run_tests.sh [TEST_MPI] [TEST_MULTIDEVICE] diff --git a/scripts/tests/run_tutorials.sh b/scripts/tests/run_tutorials.sh index 9a657e386c..1f675a3413 100755 --- a/scripts/tests/run_tutorials.sh +++ b/scripts/tests/run_tutorials.sh @@ -1,5 +1,5 @@ #!/bin/bash -## Copyright 2016-2020 Intel Corporation +## Copyright 2016 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 export LD_LIBRARY_PATH=`pwd`/build/install/ospray/lib:$LD_LIBRARY_PATH diff --git a/scripts/tests/update_test_baseline.sh b/scripts/tests/update_test_baseline.sh index 93675667ca..e78612ef74 100755 --- a/scripts/tests/update_test_baseline.sh +++ b/scripts/tests/update_test_baseline.sh @@ -1,5 +1,5 @@ #!/bin/bash -## Copyright 2016-2021 Intel Corporation +## Copyright 2016 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 #author=Carson Brownlee #generates md5 checksums for generated regression test image diff --git a/test_image_data/CMakeLists.txt b/test_image_data/CMakeLists.txt index d037c9cbdc..c7218a1a4e 100644 --- a/test_image_data/CMakeLists.txt +++ b/test_image_data/CMakeLists.txt @@ -1,4 +1,4 @@ -## Copyright 2009-2021 Intel Corporation +## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 cmake_minimum_required(VERSION 3.1) diff --git a/test_image_data/baseline/AVX2/ClippingParallel_planes.png.md5 b/test_image_data/baseline/AVX2/ClippingParallel_planes.png.md5 new file mode 100644 index 0000000000..8e9f0ca4ad --- /dev/null +++ b/test_image_data/baseline/AVX2/ClippingParallel_planes.png.md5 @@ -0,0 +1 @@ +24936b121705fd9cc9fdc59c216a1c53 diff --git a/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_15.png.md5 b/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_15.png.md5 index f2be463632..0a28c4875c 100644 --- a/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_15.png.md5 +++ b/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_15.png.md5 @@ -1 +1 @@ -9e6bfa920c7579632fd07ae633fde44a +e9255f5d5978373819db855bfbaacd6e diff --git a/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_16.png.md5 b/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_16.png.md5 index 311f8210fa..0d834f2bbd 100644 --- a/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_16.png.md5 +++ b/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_16.png.md5 @@ -1 +1 @@ -3c048787d428ac005188bc2c5153cf71 +82be5440fee696ba8b6a9116e15cc570 diff --git a/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_17.png.md5 b/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_17.png.md5 index ca5b7f6fc7..bec5ec6df4 100644 --- a/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_17.png.md5 +++ b/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_17.png.md5 @@ -1 +1 @@ -11d2216fd034fd9babfa629a935bf9f7 +7b861d9ded7e810b8411ff5bf208bc30 diff --git a/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_18.png.md5 b/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_18.png.md5 new file mode 100644 index 0000000000..f2be463632 --- /dev/null +++ b/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_18.png.md5 @@ -0,0 +1 @@ +9e6bfa920c7579632fd07ae633fde44a diff --git a/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_19.png.md5 b/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_19.png.md5 new file mode 100644 index 0000000000..311f8210fa --- /dev/null +++ b/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_19.png.md5 @@ -0,0 +1 @@ +3c048787d428ac005188bc2c5153cf71 diff --git a/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_20.png.md5 b/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_20.png.md5 new file mode 100644 index 0000000000..ca5b7f6fc7 --- /dev/null +++ b/test_image_data/baseline/AVX2/FromOsprayTesting_TestScenesVolumes_test_scenes_20.png.md5 @@ -0,0 +1 @@ +11d2216fd034fd9babfa629a935bf9f7 diff --git a/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_0.png.md5 b/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_0.png.md5 new file mode 100644 index 0000000000..d0c2e1fd51 --- /dev/null +++ b/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_0.png.md5 @@ -0,0 +1 @@ +f31203eee00bbc6dc439e98aa1f0cdb4 diff --git a/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_1.png.md5 b/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_1.png.md5 new file mode 100644 index 0000000000..469e5abb62 --- /dev/null +++ b/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_1.png.md5 @@ -0,0 +1 @@ +c48599e72fbe1331151cd49ccf8fe854 diff --git a/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_2.png.md5 b/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_2.png.md5 new file mode 100644 index 0000000000..06b4763b77 --- /dev/null +++ b/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_2.png.md5 @@ -0,0 +1 @@ +a4b76a781fcfb6cc911d4cc73f477f5e diff --git a/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_3.png.md5 b/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_3.png.md5 new file mode 100644 index 0000000000..4dff542dc9 --- /dev/null +++ b/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_3.png.md5 @@ -0,0 +1 @@ +4d3a8443c55123c36865c04da7bdd5cb diff --git a/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_4.png.md5 b/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_4.png.md5 new file mode 100644 index 0000000000..b2f11a9599 --- /dev/null +++ b/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_4.png.md5 @@ -0,0 +1 @@ +956f7d5879a1cdba19145548d12d7ad8 diff --git a/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_5.png.md5 b/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_5.png.md5 new file mode 100644 index 0000000000..ad44ea21b1 --- /dev/null +++ b/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_5.png.md5 @@ -0,0 +1 @@ +fab70791d21ecb20d9f838d73027fb53 diff --git a/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_6.png.md5 b/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_6.png.md5 new file mode 100644 index 0000000000..3a58a66b40 --- /dev/null +++ b/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_6.png.md5 @@ -0,0 +1 @@ +e5bb67c6863d440e5284df82ae740966 diff --git a/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_7.png.md5 b/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_7.png.md5 new file mode 100644 index 0000000000..966c303414 --- /dev/null +++ b/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_7.png.md5 @@ -0,0 +1 @@ +1686ff030f2491b5d646bf6590405a58 diff --git a/test_image_data/baseline/AVX2/IDBuffer_Primitive_IDBuffer_0.png.md5 b/test_image_data/baseline/AVX2/IDBuffer_Primitive_IDBuffer_0.png.md5 new file mode 100644 index 0000000000..f076b702ca --- /dev/null +++ b/test_image_data/baseline/AVX2/IDBuffer_Primitive_IDBuffer_0.png.md5 @@ -0,0 +1 @@ +81e05ae014645d86d8b37499eb290484 diff --git a/test_image_data/baseline/AVX2/IDBuffer_Primitive_IDBuffer_1.png.md5 b/test_image_data/baseline/AVX2/IDBuffer_Primitive_IDBuffer_1.png.md5 new file mode 100644 index 0000000000..f714912521 --- /dev/null +++ b/test_image_data/baseline/AVX2/IDBuffer_Primitive_IDBuffer_1.png.md5 @@ -0,0 +1 @@ +abcd7ceac1d7bd3a537e238411df0007 diff --git a/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_0.png.md5 b/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_0.png.md5 new file mode 100644 index 0000000000..ffdee794ce --- /dev/null +++ b/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_0.png.md5 @@ -0,0 +1 @@ +7a8a55271c8e871d8b8cf1f84b867f54 diff --git a/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_1.png.md5 b/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_1.png.md5 new file mode 100644 index 0000000000..02eea40c98 --- /dev/null +++ b/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_1.png.md5 @@ -0,0 +1 @@ +5cccafbdb4b2ac8345e2678609e920de diff --git a/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_2.png.md5 b/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_2.png.md5 new file mode 100644 index 0000000000..740ea7bf5f --- /dev/null +++ b/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_2.png.md5 @@ -0,0 +1 @@ +341333744c238581f14a24bb92263273 diff --git a/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_3.png.md5 b/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_3.png.md5 new file mode 100644 index 0000000000..3e3eb1a3f1 --- /dev/null +++ b/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_3.png.md5 @@ -0,0 +1 @@ +bf6ed62bb1fb6417e84c918a7eb35ab2 diff --git a/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_4.png.md5 b/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_4.png.md5 new file mode 100644 index 0000000000..ffdee794ce --- /dev/null +++ b/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_4.png.md5 @@ -0,0 +1 @@ +7a8a55271c8e871d8b8cf1f84b867f54 diff --git a/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_5.png.md5 b/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_5.png.md5 new file mode 100644 index 0000000000..a81cd36a53 --- /dev/null +++ b/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_5.png.md5 @@ -0,0 +1 @@ +12d81533f45afb9b54769ead45393eea diff --git a/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_6.png.md5 b/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_6.png.md5 new file mode 100644 index 0000000000..740ea7bf5f --- /dev/null +++ b/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_6.png.md5 @@ -0,0 +1 @@ +341333744c238581f14a24bb92263273 diff --git a/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_7.png.md5 b/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_7.png.md5 new file mode 100644 index 0000000000..3e3eb1a3f1 --- /dev/null +++ b/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_7.png.md5 @@ -0,0 +1 @@ +bf6ed62bb1fb6417e84c918a7eb35ab2 diff --git a/test_image_data/baseline/AVX2/Interpolation_Normal_Interpolation_0.png.md5 b/test_image_data/baseline/AVX2/Interpolation_Normal_Interpolation_0.png.md5 new file mode 100644 index 0000000000..23a58129c5 --- /dev/null +++ b/test_image_data/baseline/AVX2/Interpolation_Normal_Interpolation_0.png.md5 @@ -0,0 +1 @@ +9c61a2d99916edb94fb401cbb184eebe diff --git a/test_image_data/baseline/AVX2/Interpolation_Normal_Interpolation_1.png.md5 b/test_image_data/baseline/AVX2/Interpolation_Normal_Interpolation_1.png.md5 new file mode 100644 index 0000000000..1442e18db9 --- /dev/null +++ b/test_image_data/baseline/AVX2/Interpolation_Normal_Interpolation_1.png.md5 @@ -0,0 +1 @@ +73b536d10b031c419a7f3acde81851df diff --git a/test_image_data/baseline/AVX2/Interpolation_Texcoord_Interpolation_0.png.md5 b/test_image_data/baseline/AVX2/Interpolation_Texcoord_Interpolation_0.png.md5 new file mode 100644 index 0000000000..3f0777ca8c --- /dev/null +++ b/test_image_data/baseline/AVX2/Interpolation_Texcoord_Interpolation_0.png.md5 @@ -0,0 +1 @@ +996022b3950c99c071fc893f04468369 diff --git a/test_image_data/baseline/AVX2/Interpolation_Texcoord_Interpolation_1.png.md5 b/test_image_data/baseline/AVX2/Interpolation_Texcoord_Interpolation_1.png.md5 new file mode 100644 index 0000000000..6084007200 --- /dev/null +++ b/test_image_data/baseline/AVX2/Interpolation_Texcoord_Interpolation_1.png.md5 @@ -0,0 +1 @@ +88cf38e9fcc5c30094857c0b7309845d diff --git a/test_image_data/baseline/AVX2/Interpolation_Texcoord_Interpolation_2.png.md5 b/test_image_data/baseline/AVX2/Interpolation_Texcoord_Interpolation_2.png.md5 new file mode 100644 index 0000000000..3f0777ca8c --- /dev/null +++ b/test_image_data/baseline/AVX2/Interpolation_Texcoord_Interpolation_2.png.md5 @@ -0,0 +1 @@ +996022b3950c99c071fc893f04468369 diff --git a/test_image_data/baseline/AVX2/Interpolation_Texcoord_Interpolation_3.png.md5 b/test_image_data/baseline/AVX2/Interpolation_Texcoord_Interpolation_3.png.md5 new file mode 100644 index 0000000000..87ed8586e2 --- /dev/null +++ b/test_image_data/baseline/AVX2/Interpolation_Texcoord_Interpolation_3.png.md5 @@ -0,0 +1 @@ +cedfe1fea5a6074cdb331b5af37087f1 diff --git a/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_0.png.md5 b/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_0.png.md5 index 0138de8625..93b82c6176 100644 --- a/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_0.png.md5 +++ b/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_0.png.md5 @@ -1 +1 @@ -55f2253843b2d288c21bd73e66b89792 +4d5ba0950e2c37a7b9795d5148e4e07e diff --git a/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_1.png.md5 b/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_1.png.md5 index 81c63e2a3b..a7cddf76bb 100644 --- a/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_1.png.md5 +++ b/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_1.png.md5 @@ -1 +1 @@ -2769062866a57a4734f3dd76f3a5865f +c3660300a6162db34b78650ec3f34128 diff --git a/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_2.png.md5 b/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_2.png.md5 index 9d4b93b408..3aab1eaa49 100644 --- a/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_2.png.md5 +++ b/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_2.png.md5 @@ -1 +1 @@ -7be3dc49b3592e7acaea42a1ed06734e +41e5823fd0896fe2cdef622010f7ea7b diff --git a/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_0.png.md5 b/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_0.png.md5 index 2585384572..01d6872576 100644 --- a/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_0.png.md5 +++ b/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_0.png.md5 @@ -1 +1 @@ -33ff070b3d17de5562f2cceeec947100 +32c0271f63f660cbf3aa581576f132d3 diff --git a/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_1.png.md5 b/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_1.png.md5 index 7492687ce1..a7699cb0be 100644 --- a/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_1.png.md5 +++ b/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_1.png.md5 @@ -1 +1 @@ -fcf630625ed9a4645b6937030b802c73 +2038fcbef9d466213bbb66884af965ca diff --git a/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_2.png.md5 b/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_2.png.md5 index 418d020948..0fd504e78f 100644 --- a/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_2.png.md5 +++ b/test_image_data/baseline/AVX2/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_2.png.md5 @@ -1 +1 @@ -01b17a8669d5be94696470962fcd1389 +ac72beda12f155b9b804361b67fe3a41 diff --git a/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_10.png.md5 b/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_10.png.md5 index b2652bd0a0..9a9ae4a8d2 100644 --- a/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_10.png.md5 +++ b/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_10.png.md5 @@ -1 +1 @@ -416eb45986f551488b79ecc92431e3b1 +c464448eed506be63c0a98dfc4d962c9 diff --git a/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_11.png.md5 b/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_11.png.md5 index 3d28ccc5df..9d0e456412 100644 --- a/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_11.png.md5 +++ b/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_11.png.md5 @@ -1 +1 @@ -446cc94c48d63aaf4b626418aeaee11e +f4cf7b9349e8ebb39636607c2032324e diff --git a/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_20.png.md5 b/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_20.png.md5 index 86b96c0573..7b34481b4d 100644 --- a/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_20.png.md5 +++ b/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_20.png.md5 @@ -1 +1 @@ -5767d3984944f3d4e26500c805e3b696 +1b522c0ec5486c81ac67be2427631933 diff --git a/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_21.png.md5 b/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_21.png.md5 index 2b3b376d1b..38e94a984c 100644 --- a/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_21.png.md5 +++ b/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_21.png.md5 @@ -1 +1 @@ -48b00c188dbdba78400090180bfc2f96 +03173bd8ea1371330625722cb04c0dd7 diff --git a/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_22.png.md5 b/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_22.png.md5 index bb13c3cce7..3594dd5edd 100644 --- a/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_22.png.md5 +++ b/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_22.png.md5 @@ -1 +1 @@ -269358b062f803d3c55bf825624c55f6 +1b253c56e183f2c16648bc3a7ff79d5d diff --git a/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_23.png.md5 b/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_23.png.md5 index 87d719a193..61c80e6359 100644 --- a/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_23.png.md5 +++ b/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_23.png.md5 @@ -1 +1 @@ -9ab2be40c3ebc32f9e7b38b73845333c +cdf29d141c8f23127e6f449946a49280 diff --git a/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_8.png.md5 b/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_8.png.md5 index 1e71e6c6de..414df621ff 100644 --- a/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_8.png.md5 +++ b/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_8.png.md5 @@ -1 +1 @@ -a7e84c7412fcf917fe90e63d37f0ae5e +38e6c687c1140e163148541a97cc6bc5 diff --git a/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_9.png.md5 b/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_9.png.md5 index 5c29be2053..2c9853fedd 100644 --- a/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_9.png.md5 +++ b/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_9.png.md5 @@ -1 +1 @@ -458e281f47fa5d0e2ed88392ab97f872 +d2e6547e0fb9c4812b49101204421588 diff --git a/test_image_data/baseline/AVX512SKX/ClippingParallel_planes.png.md5 b/test_image_data/baseline/AVX512SKX/ClippingParallel_planes.png.md5 new file mode 100644 index 0000000000..8e9f0ca4ad --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/ClippingParallel_planes.png.md5 @@ -0,0 +1 @@ +24936b121705fd9cc9fdc59c216a1c53 diff --git a/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_15.png.md5 b/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_15.png.md5 index f2be463632..0a28c4875c 100644 --- a/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_15.png.md5 +++ b/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_15.png.md5 @@ -1 +1 @@ -9e6bfa920c7579632fd07ae633fde44a +e9255f5d5978373819db855bfbaacd6e diff --git a/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_16.png.md5 b/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_16.png.md5 index 311f8210fa..380c97c42a 100644 --- a/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_16.png.md5 +++ b/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_16.png.md5 @@ -1 +1 @@ -3c048787d428ac005188bc2c5153cf71 +d4cdb84bbaed157348a23d6c1c980898 diff --git a/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_17.png.md5 b/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_17.png.md5 index ca5b7f6fc7..bec5ec6df4 100644 --- a/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_17.png.md5 +++ b/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_17.png.md5 @@ -1 +1 @@ -11d2216fd034fd9babfa629a935bf9f7 +7b861d9ded7e810b8411ff5bf208bc30 diff --git a/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_18.png.md5 b/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_18.png.md5 new file mode 100644 index 0000000000..f2be463632 --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_18.png.md5 @@ -0,0 +1 @@ +9e6bfa920c7579632fd07ae633fde44a diff --git a/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_19.png.md5 b/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_19.png.md5 new file mode 100644 index 0000000000..311f8210fa --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_19.png.md5 @@ -0,0 +1 @@ +3c048787d428ac005188bc2c5153cf71 diff --git a/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_20.png.md5 b/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_20.png.md5 new file mode 100644 index 0000000000..ca5b7f6fc7 --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/FromOsprayTesting_TestScenesVolumes_test_scenes_20.png.md5 @@ -0,0 +1 @@ +11d2216fd034fd9babfa629a935bf9f7 diff --git a/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_0.png.md5 b/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_0.png.md5 new file mode 100644 index 0000000000..d0c2e1fd51 --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_0.png.md5 @@ -0,0 +1 @@ +f31203eee00bbc6dc439e98aa1f0cdb4 diff --git a/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_1.png.md5 b/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_1.png.md5 new file mode 100644 index 0000000000..469e5abb62 --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_1.png.md5 @@ -0,0 +1 @@ +c48599e72fbe1331151cd49ccf8fe854 diff --git a/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_2.png.md5 b/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_2.png.md5 new file mode 100644 index 0000000000..06b4763b77 --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_2.png.md5 @@ -0,0 +1 @@ +a4b76a781fcfb6cc911d4cc73f477f5e diff --git a/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_3.png.md5 b/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_3.png.md5 new file mode 100644 index 0000000000..4dff542dc9 --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_3.png.md5 @@ -0,0 +1 @@ +4d3a8443c55123c36865c04da7bdd5cb diff --git a/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_4.png.md5 b/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_4.png.md5 new file mode 100644 index 0000000000..b2f11a9599 --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_4.png.md5 @@ -0,0 +1 @@ +956f7d5879a1cdba19145548d12d7ad8 diff --git a/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_5.png.md5 b/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_5.png.md5 new file mode 100644 index 0000000000..ad44ea21b1 --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_5.png.md5 @@ -0,0 +1 @@ +fab70791d21ecb20d9f838d73027fb53 diff --git a/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_6.png.md5 b/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_6.png.md5 new file mode 100644 index 0000000000..3a58a66b40 --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_6.png.md5 @@ -0,0 +1 @@ +e5bb67c6863d440e5284df82ae740966 diff --git a/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_7.png.md5 b/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_7.png.md5 new file mode 100644 index 0000000000..966c303414 --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/IDBuffer_ObjectInstance_IDBuffer_7.png.md5 @@ -0,0 +1 @@ +1686ff030f2491b5d646bf6590405a58 diff --git a/test_image_data/baseline/AVX512SKX/IDBuffer_Primitive_IDBuffer_0.png.md5 b/test_image_data/baseline/AVX512SKX/IDBuffer_Primitive_IDBuffer_0.png.md5 new file mode 100644 index 0000000000..f076b702ca --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/IDBuffer_Primitive_IDBuffer_0.png.md5 @@ -0,0 +1 @@ +81e05ae014645d86d8b37499eb290484 diff --git a/test_image_data/baseline/AVX512SKX/IDBuffer_Primitive_IDBuffer_1.png.md5 b/test_image_data/baseline/AVX512SKX/IDBuffer_Primitive_IDBuffer_1.png.md5 new file mode 100644 index 0000000000..f714912521 --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/IDBuffer_Primitive_IDBuffer_1.png.md5 @@ -0,0 +1 @@ +abcd7ceac1d7bd3a537e238411df0007 diff --git a/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_0.png.md5 b/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_0.png.md5 new file mode 100644 index 0000000000..ffdee794ce --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_0.png.md5 @@ -0,0 +1 @@ +7a8a55271c8e871d8b8cf1f84b867f54 diff --git a/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_1.png.md5 b/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_1.png.md5 new file mode 100644 index 0000000000..02eea40c98 --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_1.png.md5 @@ -0,0 +1 @@ +5cccafbdb4b2ac8345e2678609e920de diff --git a/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_2.png.md5 b/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_2.png.md5 new file mode 100644 index 0000000000..740ea7bf5f --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_2.png.md5 @@ -0,0 +1 @@ +341333744c238581f14a24bb92263273 diff --git a/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_3.png.md5 b/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_3.png.md5 new file mode 100644 index 0000000000..3e3eb1a3f1 --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_3.png.md5 @@ -0,0 +1 @@ +bf6ed62bb1fb6417e84c918a7eb35ab2 diff --git a/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_4.png.md5 b/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_4.png.md5 new file mode 100644 index 0000000000..ffdee794ce --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_4.png.md5 @@ -0,0 +1 @@ +7a8a55271c8e871d8b8cf1f84b867f54 diff --git a/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_5.png.md5 b/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_5.png.md5 new file mode 100644 index 0000000000..a81cd36a53 --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_5.png.md5 @@ -0,0 +1 @@ +12d81533f45afb9b54769ead45393eea diff --git a/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_6.png.md5 b/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_6.png.md5 new file mode 100644 index 0000000000..740ea7bf5f --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_6.png.md5 @@ -0,0 +1 @@ +341333744c238581f14a24bb92263273 diff --git a/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_7.png.md5 b/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_7.png.md5 new file mode 100644 index 0000000000..3e3eb1a3f1 --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/Interpolation_Color_Interpolation_7.png.md5 @@ -0,0 +1 @@ +bf6ed62bb1fb6417e84c918a7eb35ab2 diff --git a/test_image_data/baseline/AVX512SKX/Interpolation_Normal_Interpolation_0.png.md5 b/test_image_data/baseline/AVX512SKX/Interpolation_Normal_Interpolation_0.png.md5 new file mode 100644 index 0000000000..23a58129c5 --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/Interpolation_Normal_Interpolation_0.png.md5 @@ -0,0 +1 @@ +9c61a2d99916edb94fb401cbb184eebe diff --git a/test_image_data/baseline/AVX512SKX/Interpolation_Normal_Interpolation_1.png.md5 b/test_image_data/baseline/AVX512SKX/Interpolation_Normal_Interpolation_1.png.md5 new file mode 100644 index 0000000000..1442e18db9 --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/Interpolation_Normal_Interpolation_1.png.md5 @@ -0,0 +1 @@ +73b536d10b031c419a7f3acde81851df diff --git a/test_image_data/baseline/AVX512SKX/Interpolation_Texcoord_Interpolation_0.png.md5 b/test_image_data/baseline/AVX512SKX/Interpolation_Texcoord_Interpolation_0.png.md5 new file mode 100644 index 0000000000..3f0777ca8c --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/Interpolation_Texcoord_Interpolation_0.png.md5 @@ -0,0 +1 @@ +996022b3950c99c071fc893f04468369 diff --git a/test_image_data/baseline/AVX512SKX/Interpolation_Texcoord_Interpolation_1.png.md5 b/test_image_data/baseline/AVX512SKX/Interpolation_Texcoord_Interpolation_1.png.md5 new file mode 100644 index 0000000000..6084007200 --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/Interpolation_Texcoord_Interpolation_1.png.md5 @@ -0,0 +1 @@ +88cf38e9fcc5c30094857c0b7309845d diff --git a/test_image_data/baseline/AVX512SKX/Interpolation_Texcoord_Interpolation_2.png.md5 b/test_image_data/baseline/AVX512SKX/Interpolation_Texcoord_Interpolation_2.png.md5 new file mode 100644 index 0000000000..3f0777ca8c --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/Interpolation_Texcoord_Interpolation_2.png.md5 @@ -0,0 +1 @@ +996022b3950c99c071fc893f04468369 diff --git a/test_image_data/baseline/AVX512SKX/Interpolation_Texcoord_Interpolation_3.png.md5 b/test_image_data/baseline/AVX512SKX/Interpolation_Texcoord_Interpolation_3.png.md5 new file mode 100644 index 0000000000..87ed8586e2 --- /dev/null +++ b/test_image_data/baseline/AVX512SKX/Interpolation_Texcoord_Interpolation_3.png.md5 @@ -0,0 +1 @@ +cedfe1fea5a6074cdb331b5af37087f1 diff --git a/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_0.png.md5 b/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_0.png.md5 index 0138de8625..93b82c6176 100644 --- a/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_0.png.md5 +++ b/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_0.png.md5 @@ -1 +1 @@ -55f2253843b2d288c21bd73e66b89792 +4d5ba0950e2c37a7b9795d5148e4e07e diff --git a/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_1.png.md5 b/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_1.png.md5 index 81c63e2a3b..a7cddf76bb 100644 --- a/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_1.png.md5 +++ b/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_1.png.md5 @@ -1 +1 @@ -2769062866a57a4734f3dd76f3a5865f +c3660300a6162db34b78650ec3f34128 diff --git a/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_2.png.md5 b/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_2.png.md5 index 9d4b93b408..3aab1eaa49 100644 --- a/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_2.png.md5 +++ b/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_2.png.md5 @@ -1 +1 @@ -7be3dc49b3592e7acaea42a1ed06734e +41e5823fd0896fe2cdef622010f7ea7b diff --git a/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_0.png.md5 b/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_0.png.md5 index 2585384572..01d6872576 100644 --- a/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_0.png.md5 +++ b/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_0.png.md5 @@ -1 +1 @@ -33ff070b3d17de5562f2cceeec947100 +32c0271f63f660cbf3aa581576f132d3 diff --git a/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_1.png.md5 b/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_1.png.md5 index 7492687ce1..a7699cb0be 100644 --- a/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_1.png.md5 +++ b/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_1.png.md5 @@ -1 +1 @@ -fcf630625ed9a4645b6937030b802c73 +2038fcbef9d466213bbb66884af965ca diff --git a/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_2.png.md5 b/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_2.png.md5 index 418d020948..0fd504e78f 100644 --- a/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_2.png.md5 +++ b/test_image_data/baseline/AVX512SKX/MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_2.png.md5 @@ -1 +1 @@ -01b17a8669d5be94696470962fcd1389 +ac72beda12f155b9b804361b67fe3a41 diff --git a/third-party-programs-OIDN.txt b/third-party-programs-OIDN.txt index 44f06acf3d..79b42ded86 100644 --- a/third-party-programs-OIDN.txt +++ b/third-party-programs-OIDN.txt @@ -15,10 +15,10 @@ terms are listed below. -------------------------------------------------------------------------------- 1. Intel(R) oneAPI Deep Neural Network Library (oneDNN) - Copyright 2016-2020 Intel Corporation + Copyright 2016 Intel Corporation Intel(R) oneAPI Threading Building Blocks (oneTBB) - Copyright 2005-2021 Intel Corporation + Copyright 2005 Intel Corporation Apache License Version 2.0, January 2004 diff --git a/third-party-programs-OpenVKL.txt b/third-party-programs-OpenVKL.txt index ad4959e3fc..af1b375ee8 100644 --- a/third-party-programs-OpenVKL.txt +++ b/third-party-programs-OpenVKL.txt @@ -110,16 +110,16 @@ terms are listed below. -------------------------------------------------------------------------------- 4. Embree - Copyright 2009-2021 Intel Corporation + Copyright 2009 Intel Corporation Google Benchmark Copyright 2014 Google Inc. All rights reserved. OSPRay - Copyright 2009-2021 Intel Corporation + Copyright 2009 Intel Corporation Threading Building Blocks (oneTBB) - Copyright 2005-2021 Intel Corporation + Copyright 2005 Intel Corporation Apache License Version 2.0 January 2004 diff --git a/third-party-programs.txt b/third-party-programs.txt index 41da915ca9..89da546109 100644 --- a/third-party-programs.txt +++ b/third-party-programs.txt @@ -15,19 +15,19 @@ terms are listed below. -------------------------------------------------------------------------------- 1. Intel(R) Embree - Copyright 2009-2021 Intel Corporation + Copyright 2009 Intel Corporation Google Benchmark Copyright 2014 Google Inc. All rights reserved. Intel(R) Open Image Denoise - Copyright 2009-2021 Intel Corporation + Copyright 2009 Intel Corporation Intel(R) Open VKL - Copyright 2019-2021 Intel Corporation + Copyright 2019 Intel Corporation Intel(R) oneAPI Threading Building Blocks (oneTBB) - Copyright 2005-2021 Intel Corporation + Copyright 2005 Intel Corporation Apache License Version 2.0 January 2004