Compare commits
193
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0ea2668db | ||
|
|
6ef53ccc64 | ||
|
|
9b5cc9ba18 | ||
|
|
69d5c3e292 | ||
|
|
6343afc07c | ||
|
|
3c957cf4ca | ||
|
|
bc0c58b49f | ||
|
|
bb92d7b8c3 | ||
|
|
096005a6a4 | ||
|
|
14bbc14875 | ||
|
|
fd8ad23e85 | ||
|
|
02b84cfc90 | ||
|
|
7f750c900a | ||
|
|
156103daf2 | ||
|
|
bb89ec0afd | ||
|
|
51ebc17d43 | ||
|
|
a95a987b3a | ||
|
|
18a1ee0e44 | ||
|
|
69851a3159 | ||
|
|
1faae7e25c | ||
|
|
f8dc41c556 | ||
|
|
cc70c2e37b | ||
|
|
be86932223 | ||
|
|
4019fadcb5 | ||
|
|
6d99c3b943 | ||
|
|
befa64183c | ||
|
|
78f8480c07 | ||
|
|
1dfef8bc49 | ||
|
|
6d34914ccc | ||
|
|
99297424d9 | ||
|
|
4678327640 | ||
|
|
d782bcead3 | ||
|
|
e2f20d0a00 | ||
|
|
fa657029cb | ||
|
|
44516d0c4f | ||
|
|
7de8a0f3a4 | ||
|
|
5fed2f2fe7 | ||
|
|
899b1b31cc | ||
|
|
9c2c9b0eb0 | ||
|
|
550096985e | ||
|
|
64c2d66a39 | ||
|
|
53469220b4 | ||
|
|
2332f60ec5 | ||
|
|
31e1f4c6b3 | ||
|
|
e20730af4e | ||
|
|
f51907c205 | ||
|
|
5b246b0d3e | ||
|
|
ccc6d5015b | ||
|
|
b33262f50d | ||
|
|
74eb73a0c8 | ||
|
|
fd3bba1e13 | ||
|
|
93839e1c42 | ||
|
|
158efc4d6c | ||
|
|
9d64eb55f5 | ||
|
|
d25f8d6435 | ||
|
|
7d8b0b2540 | ||
|
|
ab44f553ca | ||
|
|
637fe3e833 | ||
|
|
d76bfeec4b | ||
|
|
524ffe306a | ||
|
|
27266344fb | ||
|
|
c0a4cdea9d | ||
|
|
5e839afa52 | ||
|
|
157e4657fa | ||
|
|
c66ccb6fb5 | ||
|
|
f865b5b252 | ||
|
|
3a080f70b0 | ||
|
|
66f52f8644 | ||
|
|
64dadf9b8f | ||
|
|
d6c375bc29 | ||
|
|
0169ab732e | ||
|
|
ffc58557a3 | ||
|
|
e9191e2440 | ||
|
|
5ec807c081 | ||
|
|
b4843323b0 | ||
|
|
f0bc9a91f3 | ||
|
|
d78dfc146e | ||
|
|
0e4296de4b | ||
|
|
22443fc4e9 | ||
|
|
3e3b528c73 | ||
|
|
7a56abdfb0 | ||
|
|
99ed27a535 | ||
|
|
3c8f214461 | ||
|
|
4d3d0c4804 | ||
|
|
de63270a19 | ||
|
|
585e3dcfba | ||
|
|
addb70fa65 | ||
|
|
18893a8484 | ||
|
|
fb3e125063 | ||
|
|
9d6d30b13c | ||
|
|
388f0370c7 | ||
|
|
182c02b28a | ||
|
|
6fb409d6eb | ||
|
|
ae64eadf48 | ||
|
|
4afb8d4cf0 | ||
|
|
7db5293d96 | ||
|
|
d595393728 | ||
|
|
f4b5846c28 | ||
|
|
0766be6328 | ||
|
|
d8c755bf5a | ||
|
|
d02cbb9b7c | ||
|
|
ad3d40c8df | ||
|
|
3b72f78f66 | ||
|
|
61fd99d06e | ||
|
|
a39f965544 | ||
|
|
edf7d842f7 | ||
|
|
98d71786f8 | ||
|
|
0efbf04f5c | ||
|
|
1e336440d9 | ||
|
|
379107eab3 | ||
|
|
36c714000f | ||
|
|
9a301e8153 | ||
|
|
d67b469898 | ||
|
|
ca1d377056 | ||
|
|
75aeade555 | ||
|
|
4d5eb61328 | ||
|
|
6f611fc009 | ||
|
|
539a5c4f7b | ||
|
|
49add4953c | ||
|
|
75012eb38e | ||
|
|
634c1d30d8 | ||
|
|
803713303a | ||
|
|
89faf72cd0 | ||
|
|
eac82a0087 | ||
|
|
020214b582 | ||
|
|
f19ab7ced8 | ||
|
|
0afc301019 | ||
|
|
db85b9af61 | ||
|
|
b036b11055 | ||
|
|
3fb1ca5eaf | ||
|
|
15b8664336 | ||
|
|
8a3242c1d5 | ||
|
|
b1ed8cc599 | ||
|
|
a271bfc786 | ||
|
|
a157358717 | ||
|
|
4d928f6623 | ||
|
|
926e98b408 | ||
|
|
83159c81b9 | ||
|
|
5a5766f85a | ||
|
|
e410f16a05 | ||
|
|
4cc1f66294 | ||
|
|
ca0738de90 | ||
|
|
2398438c0c | ||
|
|
7a0f6c3ddc | ||
|
|
778624d9fb | ||
|
|
e99fad5c45 | ||
|
|
62c1c3da0c | ||
|
|
6074cd0347 | ||
|
|
b0a680ff4e | ||
|
|
caef3c954a | ||
|
|
320e82ab37 | ||
|
|
cf58c7343d | ||
|
|
c505420eb6 | ||
|
|
b4c8d2850f | ||
|
|
ca0c6df4e0 | ||
|
|
967960dc54 | ||
|
|
2e2e2feb7c | ||
|
|
d0f158a7cd | ||
|
|
597b6b17e2 | ||
|
|
b52b3e673d | ||
|
|
714db4adb7 | ||
|
|
75461a12ae | ||
|
|
df98828efd | ||
|
|
cb9935cdf5 | ||
|
|
0729cca05b | ||
|
|
5f99b5c93d | ||
|
|
5fe0c5bd9a | ||
|
|
5ea1cceb8c | ||
|
|
cd6081e609 | ||
|
|
7f9372f7a2 | ||
|
|
897c20dce6 | ||
|
|
416d443f82 | ||
|
|
848aa8e6d7 | ||
|
|
18c3a0c620 | ||
|
|
d27879a7db | ||
|
|
bd28ff18c5 | ||
|
|
84e9205b5e | ||
|
|
61bb74ee65 | ||
|
|
01167e2a73 | ||
|
|
1bd2d67d88 | ||
|
|
f1ae57c75f | ||
|
|
3bf2494b28 | ||
|
|
43445591e4 | ||
|
|
9568e93d59 | ||
|
|
0647312733 | ||
|
|
c3d062b0ca | ||
|
|
9c83485a4a | ||
|
|
d541d1a113 | ||
|
|
0d058c798e | ||
|
|
86af7c880f | ||
|
|
99b0db748e | ||
|
|
dcb810a109 | ||
|
|
03b10d0d66 |
+148
-56
@@ -1,27 +1,27 @@
|
||||
# .travis.yml for OSL
|
||||
|
||||
language: cpp
|
||||
sudo: false
|
||||
osx_image: xcode7.3
|
||||
osx_image: xcode10
|
||||
dist: trusty
|
||||
|
||||
|
||||
# Add-ons: specify apt packages for Linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- boost-latest
|
||||
- ubuntu-toolchain-r-test
|
||||
- george-edison55-precise-backports
|
||||
packages:
|
||||
- cmake
|
||||
- cmake-data
|
||||
- g++-4.8
|
||||
- g++-5
|
||||
- g++-6
|
||||
- g++-7
|
||||
- libboost1.55-all-dev
|
||||
- libtiff4-dev
|
||||
# Currently, we do this per-matrix-entry so it can be finely customized
|
||||
# so that each entry only get the packages it needs.
|
||||
#addons:
|
||||
# apt:
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
# packages:
|
||||
# - g++-4.8
|
||||
# - g++-6
|
||||
# - g++-7
|
||||
# - libboost-filesystem1.55
|
||||
# - libboost-python1.55
|
||||
# - libboost-regex1.55
|
||||
# - libboost-system1.55
|
||||
# - libboost-thread1.55
|
||||
# - libboost-wave1.55
|
||||
|
||||
cache:
|
||||
ccache: true
|
||||
@@ -55,24 +55,32 @@ install:
|
||||
src/build-scripts/install_homebrew_deps.bash ;
|
||||
elif [ $TRAVIS_OS_NAME == linux ] ; then
|
||||
CXX="ccache $CXX" CCACHE_CPP2=1 src/build-scripts/build_openexr.bash ;
|
||||
export ILMBASE_HOME=$PWD/openexr-install ;
|
||||
export OPENEXR_HOME=$PWD/openexr-install ;
|
||||
if [ "$LLVM_VERSION" == "" ]; then export LLVM_VERSION="3.9.0" ; fi ;
|
||||
wget http://releases.llvm.org/${LLVM_VERSION}/clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-ubuntu-14.04.tar.xz ;
|
||||
tar xf clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-ubuntu-14.04.tar.xz ;
|
||||
rm -f clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-ubuntu-14.04.tar.xz ;
|
||||
export ILMBASE_ROOT_DIR=$PWD/ext/openexr-install ;
|
||||
export OPENEXR_ROOT_DIR=$PWD/ext/openexr-install ;
|
||||
export ILMBASE_HOME=$PWD/ext/openexr-install ;
|
||||
export OPENEXR_HOME=$PWD/ext/openexr-install ;
|
||||
if [ "$LLVM_VERSION" == "" ]; then export LLVM_VERSION="error" ; fi ;
|
||||
if [ "$LLVM_VERSION" == "5.0.0" ]; then export LLVMTAR=clang+llvm-${LLVM_VERSION}-linux-x86_64-ubuntu14.04.tar.xz ; else export LLVMTAR=clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-ubuntu-14.04.tar.xz ; fi;
|
||||
echo LLVMTAR = $LLVMTAR ;
|
||||
wget http://releases.llvm.org/${LLVM_VERSION}/${LLVMTAR} ;
|
||||
tar xf $LLVMTAR ;
|
||||
rm -f $LLVMTAR ;
|
||||
echo "Installed ${LLVM_VERSION}" ;
|
||||
mv clang+llvm* llvm-install ;
|
||||
export LLVM_DIRECTORY=$PWD/llvm-install ;
|
||||
ls -a $LLVM_DIRECTORY ;
|
||||
fi
|
||||
# Note: can remove the ILMBASE_HOME/OPENEXR_HOME when OIIO 2.x is floor
|
||||
- export OIIOMAKEFLAGS="$OIIOMAKEFLAGS -j2 DEBUG= USE_PYTHON=0 OIIO_BUILD_TESTS=0"
|
||||
- export OPENIMAGEIO_SITE=travis
|
||||
- export OSL_SITE=travis
|
||||
- src/build-scripts/build_openimageio.bash
|
||||
- export OPENIMAGEIOHOME=$PWD/OpenImageIO/dist/$OIIOPLATFORM
|
||||
- export PATH=$OPENIMAGEIOHOME/bin:$PATH
|
||||
- export DYLD_LIBRARY_PATH=$OPENIMAGEIOHOME/lib:$DYLD_LIBRARY_PATH
|
||||
- export LD_LIBRARY_PATH=$OPENIMAGEIOHOME/lib:$LD_LIBRARY_PATH
|
||||
- export PYTHONPATH=$OPENIMAGEIOHOME/python:$PYTHONPATH
|
||||
- export OPENIMAGEIO_ROOT_DIR=$PWD/OpenImageIO/dist/$OIIOPLATFORM
|
||||
- export OPENIMAGEIOHOME=$OPENIMAGEIO_ROOT_DIR
|
||||
- export PATH=$OPENIMAGEIO_ROOT_DIR/bin:$PATH
|
||||
- export DYLD_LIBRARY_PATH=$OPENIMAGEIO_ROOT_DIR/lib:$DYLD_LIBRARY_PATH
|
||||
- export LD_LIBRARY_PATH=$OPENIMAGEIO_ROOT_DIR/lib:$LD_LIBRARY_PATH
|
||||
- export PYTHONPATH=$OPENIMAGEIO_ROOT_DIR/python:$PYTHONPATH
|
||||
- if [ $TRAVIS_OS_NAME == linux ] ; then
|
||||
export BUILD_FLAGS="$BUILD_FLAGS LLVM_STATIC=1" ;
|
||||
export TEST_FLAGS="-E broken\|render-cornell\|render-oren-nayar\|render-veachmis\|render-ward" ;
|
||||
@@ -85,8 +93,8 @@ script:
|
||||
- make VERBOSE=1 $BUILD_FLAGS cmakesetup
|
||||
- make -j2 $BUILD_FLAGS
|
||||
- export LSAN_OPTIONS=suppressions=$PWD/src/build-scripts/nosanitize.txt
|
||||
- export OSLHOME=$PWD/dist/$PLATFORM
|
||||
- export OIIO_LIBRARY_PATH=$OSLHOME/lib:${OIIO_LIBRARY_PATH}
|
||||
- export OSL_ROOT_DIR=$PWD/dist/$PLATFORM
|
||||
- export OIIO_LIBRARY_PATH=${OSL_ROOT_DIR}/lib:${OIIO_LIBRARY_PATH}
|
||||
- make $BUILD_FLAGS test
|
||||
|
||||
|
||||
@@ -105,40 +113,124 @@ branches:
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
# Build with C++11, default compiler, optimized build, against OIIO master
|
||||
- os: linux
|
||||
- name: "VFX Platform 2018 (gcc6, c++14), llvm 7, OIIO master, avx/f16c"
|
||||
os: linux
|
||||
compiler: gcc
|
||||
- os: osx
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-6
|
||||
- libboost1.55-dev
|
||||
- libboost-filesystem1.55
|
||||
- libboost-python1.55
|
||||
- libboost-system1.55
|
||||
- libboost-thread1.55
|
||||
- libboost-wave1.55
|
||||
env: WHICHGCC=6 USE_CPP=14 LLVM_VERSION=7.0.0 OIIOBRANCH=master USE_SIMD=avx,f16c
|
||||
- name: "MacOS (latest Apple clang, llvm 7, OIIO master, latest homebrew libs"
|
||||
os: osx
|
||||
compiler: clang
|
||||
# Test against the older release branch of OIIO (all the other tests
|
||||
# are against OIIO master).
|
||||
- os: linux
|
||||
- name: "VFX Platform 2017 (gcc48, c++11), llvm 6, OIIO release, sse4.2"
|
||||
os: linux
|
||||
compiler: gcc
|
||||
env: OIIOBRANCH=release
|
||||
# Test gcc 5, also against higher SSE level
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- libboost1.55-dev
|
||||
- libboost-filesystem1.55
|
||||
- libboost-python1.55
|
||||
- libboost-regex1.55
|
||||
- libboost-system1.55
|
||||
- libboost-thread1.55
|
||||
- libboost-wave1.55
|
||||
env: WHICHGCC=4.8 USE_CPP=11 LLVM_VERSION=6.0.1 USE_SIMD=sse4.2 OIIOBRANCH=release
|
||||
- name: "Older things: release OIIO, llvm 5, OIIO 1.8/oldest, boost 1.55"
|
||||
os: linux
|
||||
compiler: gcc
|
||||
env: WHICHGCC=5 USE_SIMD=sse4.2
|
||||
# Test gcc6, and highest SIMD level supported by Travis.
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- libboost1.55-dev
|
||||
- libboost-filesystem1.55
|
||||
- libboost-python1.55
|
||||
- libboost-regex1.55
|
||||
- libboost-system1.55
|
||||
- libboost-thread1.55
|
||||
- libboost-wave1.55
|
||||
env: WHICHGCC=4.8 USE_CPP=11 LLVM_VERSION=5.0.0 USE_SIMD=sse4.2 OIIOBRANCH=RB-1.9
|
||||
if: branch =~ /(master|RB|travis)/ OR type = pull_request
|
||||
- name: "gcc7, llvm7, C++14"
|
||||
os: linux
|
||||
compiler: gcc
|
||||
env: WHICHGCC=6 USE_SIMD=avx,f16c
|
||||
# Linux only: test gcc 7, also test C++14
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-7
|
||||
- libboost1.55-dev
|
||||
- libboost-filesystem1.55
|
||||
- libboost-python1.55
|
||||
- libboost-system1.55
|
||||
- libboost-thread1.55
|
||||
- libboost-wave1.55
|
||||
env: WHICHGCC=7 USE_CPP=14 LLVM_VERSION=7.0.0
|
||||
if: branch =~ /(master|RB|travis)/ OR type = pull_request
|
||||
- name: "Future: gcc8, C++14, LLVM 7, OIIO master, AVX/f16c"
|
||||
os: linux
|
||||
compiler: gcc
|
||||
env: WHICHGCC=7 USE_CPP=14
|
||||
# Build with C++11, DEBUG build, against OIIO master
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-8
|
||||
- libboost1.55-dev
|
||||
- libboost-filesystem1.55
|
||||
- libboost-python1.55
|
||||
- libboost-system1.55
|
||||
- libboost-thread1.55
|
||||
- libboost-wave1.55
|
||||
env: WHICHGCC=8 USE_CPP=14 LLVM_VERSION=7.0.0 USE_SIMD=avx,f16c
|
||||
- name: "DEBUG build, LLVM 7, OIIO master"
|
||||
os: linux
|
||||
compiler: gcc
|
||||
env: DEBUG=1
|
||||
# Test against older LLVM
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- libboost1.55-dev
|
||||
- libboost-filesystem1.55
|
||||
- libboost-python1.55
|
||||
- libboost-regex1.55
|
||||
- libboost-system1.55
|
||||
- libboost-thread1.55
|
||||
- libboost-wave1.55
|
||||
env: DEBUG=1 LLVM_VERSION=7.0.0 OIIOBRANCH=master
|
||||
- name: "Oldest everything: LLVM 4, OIIO 1.8, no simd"
|
||||
os: linux
|
||||
compiler: gcc
|
||||
env: LLVM_VERSION=3.5.2
|
||||
# One more, just for the heck of it, turn all SIMD off.
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: USE_SIMD=0
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- libboost1.55-dev
|
||||
- libboost-filesystem1.55
|
||||
- libboost-python1.55
|
||||
- libboost-regex1.55
|
||||
- libboost-system1.55
|
||||
- libboost-thread1.55
|
||||
- libboost-wave1.55
|
||||
env: USE_SIMD=0 LLVM_VERSION=4.0.0 OIIOBRANCH=RB-1.8
|
||||
if: branch =~ /(master|RB|travis)/ OR type = pull_request
|
||||
|
||||
notifications:
|
||||
email:
|
||||
|
||||
+408
-15
@@ -1,11 +1,378 @@
|
||||
Release 1.9 -- ?? 2017 (compared to 1.8)
|
||||
Release 1.10.6 -- Jul 4, 2019 (compared to 1.10.5)
|
||||
--------------------------------------------------
|
||||
* Build: Fixes to FindOpenEXR.cmake. #1022
|
||||
* ShadingSystem: when building a shader group from serialized commands,
|
||||
respect the global lockgeom default. #1032
|
||||
|
||||
Release 1.10.5 -- May 1, 2019 (compared to 1.10.4)
|
||||
--------------------------------------------------
|
||||
* Extend linearstep() and smooth_linearstep() to work with color, point,
|
||||
vector, and normal types (previously restricted to float). #994
|
||||
* Improve oslc type error detection for variable declarations with init
|
||||
expressions. Note that this may flag some warnings and errors that went
|
||||
undetected before, involving initialization assignments of incompatible
|
||||
types. #991, #993
|
||||
* Add a build-time option GLIBCXX_USE_CXX11_ABI to force the "new/old string
|
||||
ABI" to something other than the default for your version of gcc. #995
|
||||
|
||||
Release 1.10.4 -- Apr 1, 2019 (compared to 1.10.3)
|
||||
--------------------------------------------------
|
||||
* LPEs: forbid LPE repetitions inside groups. #972
|
||||
* Build process: build script finding of LLVM is now more robust to certain
|
||||
library configurations of llvm, particularly where everything is bundled
|
||||
in just one libLLVM without a separate libLLVMMCJIT. #976
|
||||
* oslc: Improve warnings about ill-advised use of the comma operator. #978
|
||||
* oslc: Fix an assertion/crash when passing initialization-lists as
|
||||
parameters to a function, where the function argument expected was as
|
||||
array. #983
|
||||
* oslc: Fix an assertion/crash for certain type constructors of structs,
|
||||
where the struct name was not declared. (This is an incorrect shader,
|
||||
but of course should have issued an error, not crashed.) #988
|
||||
* Note: The experimental OptiX path is not expected to work in this branch!
|
||||
Development has continued in the 'master' branch. If you are interested in
|
||||
testing the OptiX support while it's under development, please do so with
|
||||
the master branch, because fixes and improvements to the OptiX support
|
||||
are not being backported to the 1.10 branch.
|
||||
* Tested and verified that everything builds and works correctly with
|
||||
Clang 8 and LLVM 8.0.
|
||||
|
||||
Release 1.10.3 -- Feb 1, 2019 (compared to 1.10.2)
|
||||
--------------------------------------------------
|
||||
* oslc: Writing to function parameters not marked as `output` was only
|
||||
recently properly recognized as an error (it was documented as illegal
|
||||
all along). Now we demote to a warning, treating it as a full error was
|
||||
too disruptive. #944 (1.10.3)
|
||||
* testshade: Check that no leftover errors are in the TextureSystem or
|
||||
ImageCache at the end of the test (that would indicate that someplace in
|
||||
OSL we are failing to check texture errors). #939 (1.10.3)
|
||||
* Improve oso output efficiency. #938 (1.10.3)
|
||||
* oslc: Fix bug related to counting the proper number of values used for
|
||||
array default value initialization. #948 (1.10.3)
|
||||
* oslc: Slight modification to the formatting of floating point values in
|
||||
the oso file to ensure full precision preservation for float values.
|
||||
#949 (1.10.3)
|
||||
* oslc: Fix crash when encountering empty-expression `for (;;)`. #951 (1.10.3)
|
||||
* oslc: Fix bug in code generation of certain `while` loops that directly
|
||||
tested a variable as a zero/nonzero test, such as:
|
||||
```
|
||||
i = 3;
|
||||
while (i)
|
||||
--i;
|
||||
```
|
||||
whereas the following had worked (they should have been identical):
|
||||
```
|
||||
i = 3;
|
||||
while (i != 0)
|
||||
--i;
|
||||
```
|
||||
#947 (1.10.3/1.11.0)
|
||||
* Fix bug in implementation of `splineinverse()` when computing with
|
||||
Bezier interpolation. #954 (1.10.3)
|
||||
* Fix bug in implementation of `transformc` when relyin on OpenColorIO for
|
||||
color transformation math, in cases were derivatives were needed (this
|
||||
is a rare case probably nobody ran into). #960 (1.10.3)
|
||||
* Improve thread-safety of the OSLCompiler itself, in case an app wants
|
||||
to be compiling several shaders to oso concurrently by different threads.
|
||||
#953 (1.10.3)
|
||||
|
||||
Release 1.10 -- Dec 1, 2018 (compared to 1.9)
|
||||
--------------------------------------------------
|
||||
Dependency and standards changes:
|
||||
* **LLVM 4.0 / 5.0 / 6.0 / 7.0**: Support has been removed for LLVM 3.x,
|
||||
added for 6.0 and 7.0.
|
||||
* **OpenImageIO 1.8/2.0+**: This release of OSL should build properly against
|
||||
OIIO 1.8 or 2.0. Support has been dropped for OIIO 1.7.
|
||||
|
||||
New back-end targets:
|
||||
* **OptiX** Work in progress: Experimental back end for NVIDIA OptiX GPU ray
|
||||
tracing toolkit. #861, #877, #902
|
||||
- Build with `USE_OPTIX=1`
|
||||
- Requires OptiX 5.1+, Cuda 8.0+, OpenImageIO 1.8.10+, LLVM >= 5.0 with
|
||||
PTX target enabled.
|
||||
- New utility **testoptix** is an example of a simple OptiX renderer
|
||||
that uses OSL for shaders.
|
||||
- Work is in progress to support the majority of OSL, but right now it
|
||||
is restricted to a subset. All the basic math, most of the
|
||||
standard library, noise functions, strings (aside from if you create
|
||||
entirely new strings in the middle of a shader), and closures work.
|
||||
The biggest thing not working yet is textures, but those are coming
|
||||
soon.
|
||||
|
||||
New tools:
|
||||
* **osltoy** : GUI tool for interactive shader editing and pattern
|
||||
visualization (somewhat in the style of [Shadertoy](http://shadertoy.com).
|
||||
#827, #914, #918, #926 (1.10.0)
|
||||
* **docdeep** : This Python script (in src/build-scripts/docdeep.py) is an
|
||||
experimental tool to scrape comments from code and turn them into
|
||||
beautiful Markdeep documentation. (A little like a VERY poor man's
|
||||
Doxygen, but markdeep!) Experimental, caveat emptor. #842 (1.10.0)
|
||||
|
||||
OSL Language and oslc compiler:
|
||||
* In OSL source code, we now encourage the use of the generic "shader" type
|
||||
for all shaders, and it is no longer necessary or encouraged to mark
|
||||
the OSL shader with a specific type, "surface", "displacement", etc.
|
||||
From a source code and/or `oslc` perspective, all shaders are the same
|
||||
generic type. A renderer may, however, have different "uses" or "contexts"
|
||||
and may additional runtime perform error checking to ensure that the
|
||||
shader group you have supplied for a particular "use" does not do things
|
||||
or access globals that are not allowed for that use. #899
|
||||
* C++11 style Initializer lists. (#838) This lets you have constructs like
|
||||
|
||||
// pass a {} list as a triple, matrix, or struct
|
||||
void func (point p);
|
||||
func ({x, y, z});
|
||||
|
||||
// Assign {} to a struct if the types match up
|
||||
struct vec2 { float x, y; };
|
||||
vec2 v = {a,b};
|
||||
|
||||
// Compact 'return' notation, it knows to construct the return type
|
||||
vec2 func (float a, float b)
|
||||
{
|
||||
return {a, b};
|
||||
}
|
||||
|
||||
* osl now warns when it detects duplicate declarations of functions with
|
||||
the exact same argument list, in the same scope. #746
|
||||
* osl now correctly reports the error when you write to a user-function
|
||||
parameter that was not declared as `output` (function params are by
|
||||
default read-only, but a shortcoming in oslc has prevented that error
|
||||
from being issued). #878 (1.10.0)
|
||||
* Fix oslc crash with invalid field selection syntax. #835 (1.10.0/1.9.6)
|
||||
* oslc fix to properly handle command line arguments if the shader file is
|
||||
not the last argument on the command line. #841 (1.10.0/1.9.7)
|
||||
* oslc: when using boost.wave for preprocessing, fix whitespace insertion
|
||||
#840 and windows path separators #849. #841 (1.10.0/1.9.7)
|
||||
* oslc: Fix bug/undefined behavior when trying to format/printf a struct.
|
||||
#849 #841 (1.10.0/1.9.7)
|
||||
* New rules for how polymorphic function variants are chosen: Matches are
|
||||
now ranked in an objective way that no longer depends on declaration
|
||||
order. Type coercions are preferred in the following order of descending
|
||||
score: exact match, int -> float, float -> triple, spatial triple ->
|
||||
spatial triple, any triple -> triple. If there is a tie for passed
|
||||
arguments, return types will break the tie. If there is still a tie or
|
||||
truly ambiguous case, a warning will be printed explaining the choices and
|
||||
which was chosen. #844 (1.10.0)
|
||||
* It is now a warning to define the same function twice in the same scope.
|
||||
#853 (1.10.0)
|
||||
* A shader input parameter marked with metadata `[[ int allowconnect = 0 ]]`
|
||||
will disallow runtime connections via `ConnectShaders()`, resulting in an
|
||||
error. #857 (1.10.0)
|
||||
* oslc command-line argument `-Werror` will treat all warnings as hard
|
||||
errors (failed compilation). #862 (1.10.0)
|
||||
* `#pragma osl nowarn` will suppress any warnings arising from code on the
|
||||
immediately following line of that source file. #864 (1.10.0)
|
||||
* oslc error reporting is improved, many multi-line syntactic constructs
|
||||
will report errors in a more intuitive, easy-to-understand line number.
|
||||
#867 (1.10.0)
|
||||
* Faster parsing of very large constant initializer lists for arrays in OSL.
|
||||
We found an inadvertent O(n^2) behavior when parsing initializer lists.
|
||||
It used to be that a constant table in the form an array of 64k floats
|
||||
took over 10s to compile, now it is 50x faster. #901
|
||||
* Resolution of ambiguous return type functions (such as noise) has been
|
||||
improved when their results are used as arguments to type constructors.
|
||||
#931 (1.10.1)
|
||||
|
||||
OSL Standard library:
|
||||
* There has been a change in the appearance to Cell noise and Gabor noise.
|
||||
This is to fix a bug that made an incorrect pattern for certain negative
|
||||
exact-integer values for cellnoise, and in lots of places for Gabor noise.
|
||||
The only way to fix it was to potentially change the appearance for some
|
||||
shaders. Sorry. If this is a real problem, let us know, perhaps we can
|
||||
make a build-time switch that will let you use the old buggy noise? But
|
||||
since this is a "2.0" release, we figured it was as good a time as ever to
|
||||
let it change to the correct results. #912 (1.10.0)
|
||||
|
||||
Shaders:
|
||||
* Contributed shader library changes:
|
||||
* mandelbrot.osl: computes Mandelbrot and Julia images. #827 (1.10.0)
|
||||
* MaterialX support:
|
||||
* Improved support for MaterialX 1.36: add sin, cos, tan, atan2, ceil,
|
||||
sqrt, exp, determinent, ln, transpose, sign, rotate, transforms,
|
||||
rgb/hsv convert, extract, separate, tiledimage. Rename exponent ->
|
||||
power, pack -> combine, hsvadjust -> hueshift. Add some color2/4
|
||||
mutual conversion operators. Fixes to ramp4, clean up texture mapping
|
||||
nodes, fixes to triplanarprojection weighting. Extend add/sub/mul/div
|
||||
to include matrices. #903, #904, #905, #907, #909 (1.9.10/1.10.0)
|
||||
|
||||
API changes, new options, new ShadingSystem features (for renderer writers):
|
||||
* ShadingSystem API:
|
||||
* It is now permitted to ConnectShaders a single component of a
|
||||
color/point/vector/normal to a float and vice versa. #801 (1.10.0)
|
||||
* An older version of ShadingSystem::execute, which had been marked
|
||||
as deprecated since OSL 1.6, has been fully removed. #832 (1.10.0)
|
||||
* `ShadingSystem::Shader()` now has all three parameters required (none
|
||||
are optional), though the "use" parameter no longer has any meaning.
|
||||
(It will be deprecated and removed in a future release.) #899
|
||||
* `ShadingSystem::optimize_group()` now takes an optional pointer to a
|
||||
`ShadingContext`, which it will use if needed (if passed NULL, one
|
||||
will be internally allocated, used, and freed, as before). #936
|
||||
* ShadingSystem attributes:
|
||||
* New `"allow_shader_replacement"` (int) attribute, when nonzero, allows
|
||||
shaders to be specified more than once, replacing their former
|
||||
definitions. The default, 0, considers that an error, as it always
|
||||
has. #816 (1.10.0).
|
||||
* New developer option `"llvm_output_bitcode"` dumps the bitcode for each
|
||||
group, even if other debug options aren't turned on, and also any
|
||||
dumped bitcode will save as text as well as binary. #831 (1.10.0)
|
||||
* New attribute `"error_repeats"`, if set to non-zero, turns off the
|
||||
suppression of multiple identical errors and warnings. Setting it
|
||||
(even to its existing value) also clears the "already seen" lists.
|
||||
#880, #883 (1.10.0/1.9.9/1.8.14)
|
||||
* Shader group attributes:
|
||||
* New attributes that can be queried with `getattribute()`:
|
||||
`"globals_read"` and `"globals_write"` retrieve an integer bitfield
|
||||
that can reveal which "globals" may be read or written by the shader
|
||||
group. The meaning of the bits is given by the enum class `SGBits`
|
||||
in `oslexec.h`. #899
|
||||
* RendererServices API:
|
||||
* Older versions of RendererServices texture functions, the old ones
|
||||
with no errormessage parameter, which were documented as deprecated
|
||||
since 1.8, are now marked OSL_DEPRECATED. #832 (1.10.0)
|
||||
* OSLCompiler API:
|
||||
* Improved error reporting when compiling from memory buffer. The
|
||||
`OSLCompiler::compile_buffer()` method now takes an optional filename
|
||||
parameter that will make error messages attribute the right "file"
|
||||
(e.g., `Error: foo.osl:5...` rather than `<buffer>:5...`). #937 (1.10.2)
|
||||
* Miscellaneous:
|
||||
* liboslnoise: Properly hide/export symbols. #849 (1.10.0/1.9.7)
|
||||
* The behavior of the "searchpath:shader" attribute, used for finding
|
||||
`.oso` files when shaders is requested, has been modified. If no
|
||||
search path is specified, the current working directory (".") will
|
||||
be searched. But if there is a search path attribute specified, only
|
||||
those directories will be searched, with "." only searched if it is
|
||||
explicitly included in the search path value. #925 (1.10.0)
|
||||
|
||||
Bug fixes and other improvements (internals):
|
||||
* The context's `texture_thread_info` is now properly passed to the
|
||||
RenderServices callbacks instead of passing NULL. (1.10.0)
|
||||
* Symbols are enbled in the JIT, allowing Intel Vtune profiler to correctly
|
||||
report which JITed OSL code is being executed. #830 (1.10.0)
|
||||
* ASTNode and OSLCompilerImpl -- add info() and message() methods to
|
||||
complement the existing error and warning. #854 (1.10.0)
|
||||
* Fix incorrect array length on unbounded arrays specified by relaxed
|
||||
parameter type checking. #900 (1.9.10/1.10.0)
|
||||
* oslc bug fix: the `regex_search()`/`regex_match()` functions did not properly
|
||||
mark their `results` output parameter as write-only. This was never
|
||||
noticed by anyone, but could have resulted in incorrect optimizations.
|
||||
#922 (1.10.0)
|
||||
* When reading `.oso` files, the parser is now more robust for certain ways
|
||||
that the oso file might be corrupted (it's more forgiving, fewer possible
|
||||
ways for it to abort or assert). #923 (1.10.0)
|
||||
* Bug fixes related to incorrect reliance on OIIO's `ustring::operator int()`.
|
||||
It's being removed from OIIO, so wean ourselves off it. #929 (1.10.0)
|
||||
* Certain texture3d lookups with derivatives could crash. #932 (1.10.1)
|
||||
* Fix oslc assertion crash when a struct parameter was initialized with
|
||||
a function call. #934 (1.10.1)
|
||||
|
||||
Build & test system improvements:
|
||||
* Appveyor CI testing for Windows. #849,852,855 (1.10.0/1.9.7)
|
||||
* Our new policy is to disable `STOP_ON_WARNING` for release branches, to
|
||||
minimize build breaks for users when a new compiler warning is hit. We
|
||||
still enable it in development/master branches as well as any CI build
|
||||
in any branch. #850 (1.10.0/1.9.7)
|
||||
* Testsuite is now Python 2/3 agnostic. #873 (1.10.0)
|
||||
* Build the version into the shared library .so names. #876
|
||||
(1.8.13/1.9.8/1.10.0)
|
||||
* Update to fix with OpenImageIO 1.9. #882,#889
|
||||
* Flex/bison fixes on Windows. #891
|
||||
* Fix Windows build break with iso646.h macros. #892
|
||||
* Fix warnings on gcc 6. #896
|
||||
* Fix errors building with MSVC. #898
|
||||
* Fixes to build with clang 7, and to use LLVM 7. #910, #921 (1.10.0)
|
||||
* Fix warnings on gcc 8. #921 (1.10.0)
|
||||
* Build system: the variables containing hints for where to find IlmBase
|
||||
and OpenEXR have been changed to `ILMBASE_ROOT_DIR` and `OPENEXR_ROOT_DIR`
|
||||
(no longer `ILMBASE_HOME`/`OPENEXR_HOME`). Similarly, `OPENIMAGEIO_ROOT_DIR`
|
||||
is the hint for custom OIIO location (no longer OPENIMAGEIOHOME). #928
|
||||
* Eliminated some in-progress MaterialX tests, they weren't in good order,
|
||||
we will do it differently if we want to add MX tests in the future. #928
|
||||
* Build options `OSL_BUILD_SHADERS` and `OSL_BUILD_MATERIALX` (both default
|
||||
to ON) can be used to disable building of all shaders or MX shaders,
|
||||
respectively. #935 (1.10.1)
|
||||
|
||||
Documentation:
|
||||
* `osltoy` documentations in `doc/osltoy.md.html` (1.10.0).
|
||||
|
||||
|
||||
|
||||
Release 1.9.13 -- 1 Dec 2018 (compared to 1.9.12)
|
||||
------------------------------------------------
|
||||
* Fix crash with texture3d lookups with derivatives. #932
|
||||
* Fix oslc crash when a struct parameter is initialized with a function call
|
||||
that returns a structure. #934
|
||||
|
||||
Release 1.9.12 -- 1 Nov 2018 (compared to 1.9.11)
|
||||
------------------------------------------------
|
||||
* Fix oslc read/write error for `regex_search`/`regex_match` #922
|
||||
* Make oso reading more robust to certain broken inputs. #923
|
||||
* Internals: make safe for some changes coming to ustring API in OIIO
|
||||
master. #929
|
||||
* Several docs fixes.
|
||||
|
||||
Release 1.9.11 -- 1 Oct 2018 (compared to 1.9.10)
|
||||
------------------------------------------------
|
||||
* Full support for using LLVM 6.0 and 7.0. #913, #919
|
||||
* Support for building with gcc 8. #921
|
||||
* Fix testrender bug with undefined order of operations (only was a problem
|
||||
with gcc5 and clang7). #916
|
||||
|
||||
Release 1.9.10 -- 1 Sep 2018 (compared to 1.9.9)
|
||||
------------------------------------------------
|
||||
* Fix Windows compile of the flex/bison compiler components. #891
|
||||
* Fix for compatibility with OIIO 1.9.
|
||||
* Fix incorrect array length on unbounded arrays specified by relaxed
|
||||
parameter type checking. #900
|
||||
* Speed up oslc parsing of long constant initializer lists. #901
|
||||
* Add more functions to color2.h, color4.h, vector2.h, vector4.h: ceil,
|
||||
sqrt, exp, log2, log, sign, sin, cos, tan, asin, acos, atan2. #903, #904
|
||||
* Improved support for MaterialX 1.36: add sin, cos, tan, atan2, ceil, sqrt,
|
||||
exp, determinent, ln, transpose, sign, rotate, transforms, rgb/hsv convert,
|
||||
extract, separate, tiledimage. Rename exponent -> power, pack -> combine,
|
||||
hsvadjust -> hueshift. Add some color2/4 mutual conversion operators.
|
||||
Fixes to ramp4, clean up texture mapping nodes, fixes to triplanarprojection
|
||||
weighting. Extend add/sub/muldiv to include matrices. #903, #904, #905
|
||||
|
||||
Release 1.9.9 -- 1 May 2018 (compared to 1.9.8)
|
||||
-----------------------------------------------
|
||||
* New SS attribute `"error_repeats"`, if set to non-zero, turns off the
|
||||
suppression of multiple identical errors and warnings. Setting it (even to
|
||||
its existing value) also clears the "already seen" lists. #880
|
||||
(1.8.14/1.9.9)
|
||||
* Update to fix with some changes in OpenImageIO 1.9. #882
|
||||
|
||||
Release 1.9.8 -- 1 Apr 2018 (compared to 1.9.7)
|
||||
-----------------------------------------------
|
||||
* Build the version into the shared library .so names. #876 (1.8.13/1.9.8)
|
||||
|
||||
Release 1.9.7 -- 1 Feb 2018 (compared to 1.9.6)
|
||||
-----------------------------------------------
|
||||
* oslc fix to properly handle command line arguments if the shader file is
|
||||
not the last argument on the command line. #841
|
||||
* oslc: when using boost.wave for preprocessing, fix whitespace insertion
|
||||
#840 and windows path separators #849.
|
||||
* oslc: Fix bug/undefined behavior when trying to format/printf a struct.
|
||||
#849
|
||||
* liboslnoise: Fix symbol export/hiding. #849
|
||||
* Misc build issue cleanup on Windows. #849
|
||||
* For release branches, we no longer have builds consider every compiler
|
||||
warning to be an error (except in master or for CI builds).
|
||||
|
||||
Release 1.9.6 -- 1 Jan 2018 (compared to 1.9.5)
|
||||
-----------------------------------------------
|
||||
* Fix oslc crash with invalid field selection syntax. #835
|
||||
* Certain texture calls were inadvertently not passing in thread data,
|
||||
forcing the texture system to look it up again redundantly. #829
|
||||
|
||||
|
||||
Release 1.9 -- 4 December 2017 (compared to 1.8)
|
||||
--------------------------------------------------
|
||||
|
||||
Dependency and standards changes:
|
||||
* **C++11 required**: OSL 1.9 requires a minimum standard of C++11. It
|
||||
should also build against C++14 and C++17.
|
||||
* **LLVM 3.5 / 3.9 / 4.0 / 5.0**: Support has been added for LLVM 3.9, 4.0, and
|
||||
5.0. Support has been removed for for LLVM 3.4.
|
||||
* **LLVM 3.5 / 3.9 / 4.0 / 5.0**: Support has been added for LLVM 3.9, 4.0,
|
||||
and 5.0. Support has been removed for for LLVM 3.4.
|
||||
* **OpenImageIO 1.7+**: This release of OSL should build properly against
|
||||
OIIO 1.7 or newer. You may find that 1.6 is still ok, but we are not doing
|
||||
any work to ensure that.
|
||||
@@ -14,14 +381,14 @@ Dependency and standards changes:
|
||||
* **OpenEXR/IlmBase >= 2.0** (recommended: 2.2)
|
||||
|
||||
Language features:
|
||||
* New preprocessor symbols: OSL_VERSION_MAJOR, OSL_VERSION_MINOR,
|
||||
OSL_VERSION_PATCH, and OSL_VERSION (e.g. 10900 for 1.9.0) reveal the
|
||||
* New preprocessor symbols: `OSL_VERSION_MAJOR`, `OSL_VERSION_MINOR`,
|
||||
`OSL_VERSION_PATCH`, and `OSL_VERSION` (e.g. 10900 for 1.9.0) reveal the
|
||||
OSL release at shader compile time. #747 (1.9.0)
|
||||
* Structure constructors: If you have a struct `S` comprising fields with
|
||||
types T1, T2, ..., you may now have an expression `S(T1 v2,T2 v2,...)` that
|
||||
constructs and returns an `S` with those field values, much in the same
|
||||
way that you can say `color(a,b,c)` to construct a color out of components
|
||||
a, b, c. #751 (1.9.0)
|
||||
types T1, T2, ..., you may now have an expression `S(T1 v2, T2 v2,...)`
|
||||
that constructs and returns an `S` with those field values, much in the
|
||||
same way that you can say `color(a,b,c)` to construct a color out of
|
||||
components a, b, c. #751 (1.9.0)
|
||||
* User-defined operator overloading: If you make a new (struct) type, it
|
||||
is possible to define overloaded operators, like this:
|
||||
|
||||
@@ -99,8 +466,8 @@ API changes, new options, new ShadingSystem features (for renderer writers):
|
||||
parameters expecting a float-aggregate or array thereof, and an `int`
|
||||
may be passed to a parameter expecting a `float`, and an `int[1]` may
|
||||
be passed to an `int` parameter. #794,#797 (1.9.1)
|
||||
* Shader group attribute additions/changes:
|
||||
* RendererServices:
|
||||
* Fixed `ClosureComponent` to work with SSE alignment requirements. #810
|
||||
(1.9.3)
|
||||
|
||||
Performance improvements:
|
||||
* Shader JIT time is improved by about 10% as a result of pre-declaring
|
||||
@@ -163,6 +530,15 @@ Bug fixes and other improvements (internals):
|
||||
the `'.'` (dot) character as decimal separator in floating point number,
|
||||
even when running on a computer system configured to use a foreign locale
|
||||
where the comma is traditionally used as the decimal separator. #795 (1.9.1)
|
||||
* Fix param analysis bug for texture or pointcloud functions with optional
|
||||
token/value parameters where the token name wasn't a string literal -- it
|
||||
could fail to recognize that certain parameters would be written to by the
|
||||
call. #812 (1.9.3)
|
||||
* ShadingSystem statistics are now printed if any shaders were
|
||||
declared/loaded, even if no shaders were executed. #815 (1.9.3)
|
||||
* Minor OSLQuery implementation improvements: add move/copy constructors
|
||||
for OSLQuery::Parameter, make the ShadingSystem side of OSLQuery correctly
|
||||
report default parameter values. #821 (1.9.4)
|
||||
|
||||
Build & test system improvements:
|
||||
* C++11 is the new language baseline. #704, #707
|
||||
@@ -220,6 +596,11 @@ Build & test system improvements:
|
||||
#788 (1.9.1)
|
||||
* Improved proper rebuilding of the LLVM bitcode for llvm_ops.cpp when only
|
||||
certain headers change. #802 (1.9.1)
|
||||
* Fix gcc7 warnings about signed vs unsigned compares. #807 (1.9.2)
|
||||
* Simplify the build logic for finding PugiXML and prefer a system install
|
||||
when found, rather than looking to OIIO to supply it. #809 (1.9.2)
|
||||
* MSVS 2015 x64 compilation fixes. #820 (1.9.4)
|
||||
* Fix debug compile against OIIO 1.7. #822 (1.9.4)
|
||||
|
||||
Developer goodies:
|
||||
* The `dual.h` implementation has been completely overhauled. The primary
|
||||
@@ -237,6 +618,22 @@ Documentation:
|
||||
* Full testshade docs in `doc/testshade.md.html` (1.9.0)
|
||||
|
||||
|
||||
|
||||
Release 1.8.15 -- 1 Aug 2018 (compared to 1.8.14)
|
||||
--------------------------------------------------
|
||||
* Fixes for compatibility with OIIO 1.9.
|
||||
|
||||
Release 1.8.14 -- 1 May 2018 (compared to 1.8.13)
|
||||
--------------------------------------------------
|
||||
* New SS attribute "error_repeats", if set to non-zero, turns off the
|
||||
suppression of multiple identical errors and warnings. Setting it (even to
|
||||
its existing value) also clears the "already seen" lists. #880
|
||||
* Update to fix with some changes in OpenImageIO 1.9. #882
|
||||
|
||||
Release 1.8.13 -- 1 Apr 2018 (compared to 1.8.12)
|
||||
--------------------------------------------------
|
||||
* Build the version into the shared library .so names. #876
|
||||
|
||||
Release 1.8.12 -- 1 Nov 2017 (compared to 1.8.11)
|
||||
--------------------------------------------------
|
||||
* Improve type checking error messages with structs. #761
|
||||
@@ -406,10 +803,6 @@ API changes, new options, new ShadingSystem features (for renderer writers):
|
||||
* Attribute "llvm_debug_ops" adds a printf before running each op.
|
||||
This is mostly for debugging OSL itself, not for users. (1.8.3)
|
||||
|
||||
<!--* Shader group attribute additions/changes:
|
||||
* RendererServices:
|
||||
-->
|
||||
|
||||
Performance improvements:
|
||||
* New runtime optimization: better at understanding the initial values of
|
||||
output parameters and what optimizations can be done based on that. #657
|
||||
|
||||
+66
-24
@@ -1,13 +1,13 @@
|
||||
cmake_minimum_required (VERSION 3.2.2)
|
||||
cmake_policy (SET CMP0048 NEW) # Allow VERSION specifier in project()
|
||||
project (OSL
|
||||
VERSION 1.9.1
|
||||
VERSION 1.10.6
|
||||
LANGUAGES CXX C)
|
||||
set (PROJ_NAME ${PROJECT_NAME}) # short name
|
||||
string (TOLOWER ${PROJ_NAME} PROJ_NAME_LOWER) # short name lower case
|
||||
set (PROJECT_VERSION_RELEASE_TYPE "dev") # "dev", "betaX", "RCY", ""
|
||||
set (PROJECT_VERSION_RELEASE_TYPE "") # "dev", "betaX", "RCY", ""
|
||||
set (${PROJECT_NAME}_VERSION_RELEASE_TYPE ${PROJECT_VERSION_RELEASE_TYPE})
|
||||
set (PROJECT_COPYRIGHTYEARS "2008-2017")
|
||||
set (PROJECT_COPYRIGHTYEARS "2008-2019")
|
||||
set (PROJECT_AUTHORS "Sony Pictures Imageworks, et al")
|
||||
set (PROJECT_URL "")
|
||||
|
||||
@@ -55,9 +55,9 @@ endif ()
|
||||
|
||||
include (GNUInstallDirs)
|
||||
|
||||
set (CMAKE_MODULE_PATH
|
||||
"${PROJECT_SOURCE_DIR}/src/cmake/modules"
|
||||
"${PROJECT_SOURCE_DIR}/src/cmake")
|
||||
list (APPEND CMAKE_MODULE_PATH
|
||||
"${PROJECT_SOURCE_DIR}/src/cmake/modules"
|
||||
"${PROJECT_SOURCE_DIR}/src/cmake")
|
||||
|
||||
include (platform)
|
||||
include (compiler) # All the C++ and compiler related options live here
|
||||
@@ -81,6 +81,8 @@ endif()
|
||||
|
||||
option (VERBOSE "Print lots of messages while compiling" OFF)
|
||||
set (${PROJ_NAME}_NAMESPACE ${PROJECT_NAME} CACHE STRING "Customized outer namespace base name (version will be added)")
|
||||
set (SOVERSION ${OSL_VERSION_MAJOR}.${OSL_VERSION_MINOR}
|
||||
CACHE STRING "Set the SO version in the SO name of the output library")
|
||||
option (OSL_BUILD_TESTS "Build the unit tests, testshade, testrender" ON)
|
||||
if (WIN32)
|
||||
option (USE_LLVM_BITCODE "Generate embedded LLVM bitcode" OFF)
|
||||
@@ -89,12 +91,16 @@ else ()
|
||||
endif ()
|
||||
option (USE_PARTIO "Use Partio if found" ON)
|
||||
set (PARTIO_HOME "" CACHE STRING "Search path for Partio components")
|
||||
option (USE_EXTERNAL_PUGIXML "Use an externally built shared library version of the pugixml library" OFF)
|
||||
set (PUGIXML_HOME "" CACHE STRING "Hint about where to find external PugiXML library")
|
||||
option (USE_FAST_MATH "Use fast math approximations (if no, then use system math library)" ON)
|
||||
option (OSL_BUILD_PLUGINS "Bool OSL plugins, for example OIIO plugin" ON)
|
||||
option (OSL_BUILD_SHADERS "Build shaders" ON)
|
||||
option (OSL_BUILD_MATERIALX "Build MaterialX shaders" ON)
|
||||
option (USE_BOOST_WAVE "Use Boost Wave for C preprocessor (alternative is to use clang)" OFF)
|
||||
|
||||
option (USE_QT "Include Qt support" ON)
|
||||
option (USE_OPTIX "Include OptiX support" OFF)
|
||||
set (OPTIX_EXTRA_LIBS CACHE STRING "Extra lib targets needed for OptiX")
|
||||
set (CUDA_TARGET_ARCH "sm_35" CACHE STRING "CUDA GPU architecture (e.g. sm_35)")
|
||||
|
||||
# set (USE_OIIO_STATIC ON CACHE BOOL "If OIIO is built static")
|
||||
# if (USE_OIIO_STATIC)
|
||||
@@ -113,8 +119,13 @@ else ()
|
||||
endif ()
|
||||
|
||||
|
||||
# Set the default namespace
|
||||
# Set the default namespace. For symbol hiding reasons, it's important that
|
||||
# the project name is a subset of the namespace name.
|
||||
set (PROJ_NAMESPACE "${${PROJ_NAME}_NAMESPACE}")
|
||||
string(REGEX MATCH ${PROJECT_NAME} NAMESPACE_HAS_PROJECT_NAME ${PROJ_NAMESPACE})
|
||||
if (NOT NAMESPACE_HAS_PROJECT_NAME)
|
||||
set (PROJ_NAMESPACE ${PROJECT_NAME}_${PROJ_NAMESPACE})
|
||||
endif ()
|
||||
set (PROJ_NAMESPACE_V "${PROJ_NAMESPACE}_v${PROJECT_VERSION_MAJOR}_${PROJECT_VERSION_MINOR}")
|
||||
message(STATUS "Setting Namespace to: ${PROJ_NAMESPACE_V}")
|
||||
|
||||
@@ -156,17 +167,34 @@ add_subdirectory (src/testshade)
|
||||
add_subdirectory (src/testrender)
|
||||
endif ()
|
||||
|
||||
if (OSL_BUILD_TESTS AND USE_OPTIX)
|
||||
add_subdirectory (src/testoptix)
|
||||
endif()
|
||||
|
||||
if (OSL_BUILD_PLUGINS)
|
||||
add_subdirectory (src/osl.imageio)
|
||||
endif ()
|
||||
|
||||
add_subdirectory (src/shaders)
|
||||
add_subdirectory (src/shaders/MaterialX)
|
||||
if (USE_QT AND Qt5_FOUND)
|
||||
add_subdirectory (src/osltoy)
|
||||
endif ()
|
||||
|
||||
if (OSL_BUILD_SHADERS)
|
||||
add_subdirectory (src/shaders)
|
||||
if (OSL_BUILD_MATERIALX)
|
||||
add_subdirectory (src/shaders/MaterialX)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (INSTALL_DOCS)
|
||||
add_subdirectory (src/doc)
|
||||
endif ()
|
||||
|
||||
# Oddball: install the FindOSL.cmake file
|
||||
# install (FILES src/cmake/modules/FindOSL.cmake
|
||||
# DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/Modules
|
||||
# COMPONENT cmake)
|
||||
|
||||
|
||||
|
||||
#########################################################################
|
||||
@@ -212,13 +240,13 @@ macro ( TESTSUITE )
|
||||
NOT _testname MATCHES "^oslinfo" AND
|
||||
NOT _testname MATCHES "^getattribute-shader" AND
|
||||
NOT EXISTS "${_testsrcdir}/OPTIMIZEONLY")
|
||||
set (_env TESTSHADE_OPT=0 OPENIMAGEIOHOME=${OPENIMAGEIOHOME})
|
||||
set (_env TESTSHADE_OPT=0 OPENIMAGEIO_ROOT_DIR=${OPENIMAGEIO_ROOT_DIR})
|
||||
add_test ( NAME ${_testname}
|
||||
COMMAND env ${_env} ${_runtest} )
|
||||
endif ()
|
||||
# Run the same test again with aggressive -O2 runtime
|
||||
# optimization, triggered by setting TESTSHADE_OPT env variable
|
||||
set (_env TESTSHADE_OPT=2 OPENIMAGEIOHOME=${OPENIMAGEIOHOME})
|
||||
set (_env TESTSHADE_OPT=2 OPENIMAGEIO_ROOT_DIR=${OPENIMAGEIO_ROOT_DIR})
|
||||
set (ALL_TEST_LIST "${ALL_TEST_LIST} ${_testname}")
|
||||
add_test ( NAME ${_testname}.opt
|
||||
COMMAND env ${_env} ${_runtest} )
|
||||
@@ -231,24 +259,28 @@ endmacro ()
|
||||
if (OSL_BUILD_TESTS)
|
||||
# List all the individual testsuite tests here, except those that need
|
||||
# special installed tests.
|
||||
TESTSUITE ( and-or-not-synonyms aastep arithmetic array array-derivs array-range
|
||||
TESTSUITE ( aastep allowconnect-err and-or-not-synonyms arithmetic
|
||||
array array-derivs array-range array-aassign
|
||||
blackbody blendmath breakcont
|
||||
bug-array-heapoffsets
|
||||
bug-locallifetime bug-outputinit bug-param-duplicate bug-peep
|
||||
cellnoise closure closure-array color comparison
|
||||
compile-buffer
|
||||
component-range const-array-params const-array-fill
|
||||
component-range
|
||||
connect-components
|
||||
const-array-params const-array-fill
|
||||
debugnan debug-uninit
|
||||
derivs derivs-muldiv-clobber
|
||||
draw_string
|
||||
error-dupes exit exponential
|
||||
fprintf
|
||||
function-earlyreturn function-simple function-outputelem
|
||||
function-overloads function-redef
|
||||
geomath getattribute-camera getattribute-shader
|
||||
getsymbol-nonheap gettextureinfo
|
||||
group-outputs groupstring
|
||||
hash hashnoise hex hyperb
|
||||
ieee_fp if incdec initops intbits isconnected isconstant
|
||||
ieee_fp if incdec initlist initops intbits isconnected isconstant
|
||||
layers layers-Ciassign layers-entry layers-lazy
|
||||
layers-nonlazycopy layers-repeatedoutputs
|
||||
linearstep
|
||||
@@ -257,16 +289,20 @@ TESTSUITE ( and-or-not-synonyms aastep arithmetic array array-derivs array-range
|
||||
metadata-braces miscmath missing-shader
|
||||
noise noise-cell
|
||||
noise-gabor noise-gabor2d-filter noise-gabor3d-filter
|
||||
noise-perlin noise-uperlin noise-simplex noise-usimplex
|
||||
pnoise pnoise-cell pnoise-gabor pnoise-perlin pnoise-uperlin
|
||||
noise-perlin noise-simplex
|
||||
pnoise pnoise-cell pnoise-gabor pnoise-perlin
|
||||
operator-overloading
|
||||
oslc-comma oslc-D
|
||||
oslc-err-arrayindex oslc-err-closuremul
|
||||
oslc-err-format oslc-err-intoverflow
|
||||
oslc-err-arrayindex oslc-err-assignmenttypes
|
||||
oslc-err-closuremul oslc-err-field
|
||||
oslc-err-format oslc-err-funcoverload
|
||||
oslc-err-intoverflow oslc-err-write-nonoutput
|
||||
oslc-err-noreturn oslc-err-notfunc
|
||||
oslc-err-initlist-args oslc-err-initlist-return
|
||||
oslc-err-outputparamvararray oslc-err-paramdefault
|
||||
oslc-err-struct-array-init oslc-err-struct-ctr
|
||||
oslc-err-struct-dup
|
||||
oslc-err-struct-dup oslc-err-struct-print
|
||||
oslc-err-unknown-ctr
|
||||
oslc-warn-commainit
|
||||
oslc-variadic-macro
|
||||
oslc-version
|
||||
@@ -274,12 +310,13 @@ TESTSUITE ( and-or-not-synonyms aastep arithmetic array array-derivs array-range
|
||||
oslinfo-metadata oslinfo-noparams
|
||||
osl-imageio
|
||||
paramval-floatpromotion
|
||||
pragma-nowarn
|
||||
printf-whole-array
|
||||
raytype raytype-specialized reparam
|
||||
render-background render-bumptest
|
||||
render-cornell render-furnace-diffuse
|
||||
render-microfacet render-oren-nayar render-veachmis render-ward
|
||||
select shortcircuit spline splineinverse
|
||||
select shortcircuit spline splineinverse splineinverse-ident
|
||||
spline-boundarybug spline-derivbug
|
||||
string
|
||||
struct struct-array struct-array-mixture
|
||||
@@ -302,10 +339,10 @@ TESTSUITE ( and-or-not-synonyms aastep arithmetic array array-derivs array-range
|
||||
vararray-connect vararray-default
|
||||
vararray-deserialize vararray-param
|
||||
vecctr vector
|
||||
wavelength_color xml )
|
||||
wavelength_color Werror xml )
|
||||
|
||||
# Only run field3d-related tests if the local OIIO was built with f3d support.
|
||||
EXECUTE_PROCESS ( COMMAND ${OPENIMAGEIO_BIN}/oiiotool --help
|
||||
EXECUTE_PROCESS ( COMMAND ${OPENIMAGEIO_BIN} --help
|
||||
OUTPUT_VARIABLE oiiotool_help )
|
||||
if (oiiotool_help MATCHES "field3d")
|
||||
TESTSUITE ( texture-field3d )
|
||||
@@ -316,6 +353,11 @@ if (PARTIO_FOUND)
|
||||
TESTSUITE ( pointcloud pointcloud-fold )
|
||||
endif ()
|
||||
|
||||
# Only run the OptiX tests if OptiX and CUDA are found
|
||||
if (OPTIX_FOUND AND CUDA_FOUND)
|
||||
TESTSUITE ( testoptix testoptix-noise )
|
||||
endif ()
|
||||
|
||||
# FIXME: still working on MaterialX testsuite
|
||||
# add_subdirectory(testsuite/MaterialX)
|
||||
|
||||
|
||||
+15
-9
@@ -9,18 +9,19 @@ Dependencies
|
||||
OSL requires the following dependencies or tools.
|
||||
NEW or CHANGED dependencies since the last major release are **bold**.
|
||||
|
||||
* Build system: **[CMake](https://cmake.org/) 3.2.2 or newer**
|
||||
* Build system: [CMake](https://cmake.org/) 3.2.2 or newer (tested through
|
||||
3.14)
|
||||
|
||||
* A suitable **C++11** compiler to build OSL itself, which may be any of:
|
||||
- GCC 4.8.5 or newer
|
||||
- Clang 3.4 or newer
|
||||
* A suitable C++11 compiler to build OSL itself, which may be any of:
|
||||
- GCC 4.8.5 or newer (through gcc 8)
|
||||
- Clang 3.4 or newer (through clang 8)
|
||||
- Microsoft Visual Studio 2015 or newer
|
||||
- Intel C++ compiler icc version 13 (?) or newer
|
||||
|
||||
OSL should compile also properly with C++14 or C++17, but they are not
|
||||
required.
|
||||
|
||||
* **[OpenImageIO](http://openimageio.org) 1.7 or newer**
|
||||
* **[OpenImageIO](http://openimageio.org) 1.8.5 or newer**
|
||||
|
||||
OSL uses OIIO both for its texture mapping functionality as well as
|
||||
numerous utility classes. If you are integrating OSL into an existing
|
||||
@@ -39,15 +40,15 @@ NEW or CHANGED dependencies since the last major release are **bold**.
|
||||
DYLD_LIBRARY_PATH on OS X) and then OSL's build scripts will be able
|
||||
to find it.
|
||||
|
||||
* **[LLVM](http://www.llvm.org) 3.5, 3.9, 4.0, or 5.0**
|
||||
* **[LLVM](http://www.llvm.org) 4.0, 5.0, 6.0, 7.0, or 8.0**
|
||||
|
||||
Optionally, if Clang libraries are installed alongside LLVM, OSL will
|
||||
in most circumstances use Clang's internals for C-style preprocessing of
|
||||
OSL source. If not found, it will fall back on Boost Wave (but on many
|
||||
platforms, that requires that Boost has been built in C++11 mode).
|
||||
|
||||
* [Boost](www.boost.org) 1.55 or newer.
|
||||
* **[Ilmbase/OpenEXR](http://openexr.com/downloads.html) 2.0 or newer**
|
||||
* [Boost](www.boost.org) 1.55 or newer (tested through 1.69).
|
||||
* [Ilmbase/OpenEXR](http://openexr.com/downloads.html) 2.0 or newer
|
||||
* [Flex](https://github.com/westes/flex) and
|
||||
[GNU Bison](https://www.gnu.org/software/bison/)
|
||||
* [PugiXML](http://pugixml.org/)
|
||||
@@ -79,6 +80,11 @@ Here are the steps to check out, build, and test the OSL distribution:
|
||||
options, and note that 'make nuke' will blow everything away for the
|
||||
freshest possible compile.
|
||||
|
||||
NOTE: If the build breaks due to compiler warnings which have been
|
||||
elevated to errors, you can try "make clean" followed by
|
||||
"make STOP_ON_WARNING=0", that create a build that will only stop for
|
||||
full errors, not warnings.
|
||||
|
||||
3. After compilation, you'll end up with a full OSL distribution in
|
||||
dist/ARCH, where ARCH is the architecture you are building on, one of
|
||||
"linux", "linux64", "macosx", "windows", or "windows64".
|
||||
@@ -92,7 +98,7 @@ Here are the steps to check out, build, and test the OSL distribution:
|
||||
of those files to appropriate directories. Public include files
|
||||
(those needed when building applications that incorporate OSL)
|
||||
can be found in "dist/ARCH/include", and documentation can be found
|
||||
in "dist/ARCH/doc".
|
||||
in "dist/ARCH/share/doc".
|
||||
|
||||
5. After building (and setting your library path), you can run the
|
||||
test suite with:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2009-2017 Sony Pictures Imageworks Inc., et al.
|
||||
Copyright (c) 2009-2019 Sony Pictures Imageworks Inc., et al.
|
||||
All Rights Reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -35,15 +35,10 @@ NINJA ?= ninja
|
||||
CMAKE ?= cmake
|
||||
|
||||
# Site-specific build instructions
|
||||
ifndef OSL_SITE
|
||||
OSL_SITE := ${shell uname -n}
|
||||
endif
|
||||
OSL_SITE ?= ${shell uname -n}
|
||||
ifneq (${shell echo ${OSL_SITE} | grep imageworks.com},)
|
||||
include ${working_dir}/site/spi/Makefile-bits
|
||||
endif
|
||||
ifneq (${shell echo ${OSL_SITE} | grep pixar.com},)
|
||||
include ${working_dir}/site/pixar/Makefile-bits
|
||||
endif
|
||||
|
||||
# Set up variables holding the names of platform-dependent directories --
|
||||
# set these after evaluating site-specific instructions
|
||||
@@ -51,7 +46,7 @@ top_build_dir := build
|
||||
build_dir := ${top_build_dir}/${platform}${variant}
|
||||
top_dist_dir := dist
|
||||
dist_dir := ${top_dist_dir}/${platform}${variant}
|
||||
OSLHOME ?= ${working_dir}/${dist_dir}
|
||||
OSL_ROOT_DIR ?= ${working_dir}/${dist_dir}
|
||||
|
||||
ifndef INSTALL_PREFIX
|
||||
INSTALL_PREFIX := ${working_dir}/${dist_dir}
|
||||
@@ -109,12 +104,20 @@ ifneq (${USE_FAST_MATH},)
|
||||
MY_CMAKE_FLAGS += -DUSE_FAST_MATH:BOOL=${USE_FAST_MATH}
|
||||
endif
|
||||
|
||||
# Old names -- DEPRECATED (1.9)
|
||||
ifneq (${OPENEXR_HOME},)
|
||||
MY_CMAKE_FLAGS += -DOPENEXR_HOME:STRING=${OPENEXR_HOME}
|
||||
MY_CMAKE_FLAGS += -DOPENEXR_ROOT_DIR:STRING=${OPENEXR_HOME}
|
||||
endif
|
||||
ifneq (${ILMBASE_HOME},)
|
||||
MY_CMAKE_FLAGS += -DILMBASE_ROOT_DIR:STRING=${ILMBASE_HOME}
|
||||
endif
|
||||
|
||||
ifneq (${ILMBASE_HOME},)
|
||||
MY_CMAKE_FLAGS += -DILMBASE_HOME:STRING=${ILMBASE_HOME}
|
||||
ifneq (${OPENEXR_ROOT_DIR},)
|
||||
MY_CMAKE_FLAGS += -DOPENEXR_ROOT_DIR:STRING=${OPENEXR_ROOT_DIR}
|
||||
endif
|
||||
|
||||
ifneq (${ILMBASE_ROOT_DIR},)
|
||||
MY_CMAKE_FLAGS += -DILMBASE_ROOT_DIR:STRING=${ILMBASE_ROOT_DIR}
|
||||
endif
|
||||
|
||||
ifneq (${USE_PARTIO},)
|
||||
@@ -129,6 +132,10 @@ ifneq (${BOOST_HOME},)
|
||||
MY_CMAKE_FLAGS += -DBOOST_ROOT:STRING=${BOOST_HOME}
|
||||
endif
|
||||
|
||||
ifneq (${USE_QT},)
|
||||
MY_CMAKE_FLAGS += -DUSE_QT:BOOL=${USE_QT}
|
||||
endif
|
||||
|
||||
ifneq (${STOP_ON_WARNING},)
|
||||
MY_CMAKE_FLAGS += -DSTOP_ON_WARNING:BOOL=${STOP_ON_WARNING}
|
||||
endif
|
||||
@@ -137,6 +144,10 @@ ifneq (${BUILDSTATIC},)
|
||||
MY_CMAKE_FLAGS += -DBUILDSTATIC:BOOL=${BUILDSTATIC}
|
||||
endif
|
||||
|
||||
ifneq (${SOVERSION},)
|
||||
MY_CMAKE_FLAGS += -DSOVERSION:STRING=${SOVERSION}
|
||||
endif
|
||||
|
||||
ifneq (${LINKSTATIC},)
|
||||
MY_CMAKE_FLAGS += -DLINKSTATIC:BOOL=${LINKSTATIC}
|
||||
endif
|
||||
@@ -145,8 +156,12 @@ ifneq (${OSL_BUILD_TESTS},)
|
||||
MY_CMAKE_FLAGS += -DOSL_BUILD_TESTS:BOOL=${OSL_BUILD_TESTS}
|
||||
endif
|
||||
|
||||
ifneq (${USE_EXTERNAL_PUGIXML},)
|
||||
MY_CMAKE_FLAGS += -DUSE_EXTERNAL_PUGIXML:BOOL=${USE_EXTERNAL_PUGIXML} -DPUGIXML_HOME=${PUGIXML_HOME}
|
||||
ifneq (${OSL_BUILD_SHADERS},)
|
||||
MY_CMAKE_FLAGS += -DOSL_BUILD_SHADERS:BOOL=${OSL_BUILD_SHADERS}
|
||||
endif
|
||||
|
||||
ifneq (${OSL_BUILD_MATERIALX},)
|
||||
MY_CMAKE_FLAGS += -DOSL_BUILD_MATERIALX:BOOL=${OSL_BUILD_MATERIALX}
|
||||
endif
|
||||
|
||||
ifdef DEBUG
|
||||
@@ -172,6 +187,10 @@ ifneq (${USE_LIBCPLUSPLUS},)
|
||||
MY_CMAKE_FLAGS += -DUSE_LIBCPLUSPLUS:BOOL=${USE_LIBCPLUSPLUS}
|
||||
endif
|
||||
|
||||
ifneq (${GLIBCXX_USE_CXX11_ABI},)
|
||||
MY_CMAKE_FLAGS += -DGLIBCXX_USE_CXX11_ABI=${GLIBCXX_USE_CXX11_ABI}
|
||||
endif
|
||||
|
||||
ifneq (${EXTRA_CPP_ARGS},)
|
||||
MY_CMAKE_FLAGS += -DEXTRA_CPP_ARGS:STRING="${EXTRA_CPP_ARGS}"
|
||||
endif
|
||||
@@ -216,6 +235,10 @@ ifneq (${CLANG_TIDY_FIX},)
|
||||
# N.B. when fixing, you don't want parallel jobs!
|
||||
endif
|
||||
|
||||
ifneq (${USE_OPTIX},)
|
||||
MY_CMAKE_FLAGS += -DUSE_OPTIX:BOOL=${USE_OPTIX}
|
||||
endif
|
||||
|
||||
#$(info MY_CMAKE_FLAGS = ${MY_CMAKE_FLAGS})
|
||||
#$(info MY_MAKE_FLAGS = ${MY_MAKE_FLAGS})
|
||||
|
||||
@@ -304,7 +327,7 @@ test: cmake
|
||||
@ ${CMAKE} -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests ${TEST_FLAGS}..."
|
||||
@ # if [ "${CODECOV}" == "1" ] ; then lcov -b ${build_dir} -d ${build_dir} -z ; rm -rf ${build_dir}/cov ; fi
|
||||
@ ( cd ${build_dir} ; \
|
||||
OSLHOME=${OSLHOME} \
|
||||
OSL_ROOT_DIR=${OSL_ROOT_DIR} \
|
||||
LD_LIBRARY_PATH=${INSTALL_PREFIX}/lib:${LD_LIBRARY_PATH} \
|
||||
DYLD_LIBRARY_PATH=${INSTALL_PREFIX}/lib:${DYLD_LIBRARY_PATH} \
|
||||
OIIO_LIBRARY_PATH=${INSTALL_PREFIX}/lib:${OIIO_LIBRARY_PATH} \
|
||||
@@ -354,6 +377,7 @@ help:
|
||||
@echo " MYCC=xx MYCXX=yy Use custom compilers"
|
||||
@echo " USE_CPP=14 Compile in C++14 mode (default is C++11)"
|
||||
@echo " USE_LIBCPLUSPLUS=1 Use clang libc++"
|
||||
@echo " GLIBCXX_USE_CXX11_ABI=1 For gcc, use the new string ABI"
|
||||
@echo " EXTRA_CPP_ARGS= Additional args to the C++ command"
|
||||
@echo " USE_NINJA=1 Set up Ninja build (instead of make)"
|
||||
@echo " USE_CCACHE=0 Disable ccache (even if available)"
|
||||
@@ -367,10 +391,10 @@ help:
|
||||
@echo " LINKSTATIC=1 Link with static external libs when possible"
|
||||
@echo " Finding and Using Dependencies:"
|
||||
@echo " BOOST_HOME=path Custom Boost installation"
|
||||
@echo " OPENEXR_HOME=path Custom OpenEXR installation"
|
||||
@echo " ILMBASE_HOME=path Custom Ilmbase installation"
|
||||
@echo " PARTIO_HOME= Use Partio from the given location"
|
||||
@echo " USE_EXTERNAL_PUGIXML=1 Use the system PugiXML, not the one in OIIO"
|
||||
@echo " OPENEXR_ROOT_DIR=path Custom OpenEXR installation"
|
||||
@echo " ILMBASE_ROOT_DIR=path Custom Ilmbase installation"
|
||||
@echo " PARTIO_HOME=path Use Partio from the given location"
|
||||
@echo " USE_QT=0 Skip anything that needs Qt"
|
||||
@echo " LLVM-related options:"
|
||||
@echo " LLVM_VERSION=4.0 Specify which LLVM version to use"
|
||||
@echo " LLVM_DIRECTORY=xx Specify where LLVM lives"
|
||||
@@ -383,9 +407,12 @@ help:
|
||||
@echo " NAMESPACE=name Override namespace base name (default: OSL)"
|
||||
@echo " USE_FAST_MATH=1 Use faster, but less accurate math (set to 0 for libm defaults)"
|
||||
@echo " OSL_BUILD_TESTS=0 Don't build unit tests, testshade, testrender"
|
||||
@echo " OSL_BUILD_SHADERS=0 Don't build any shaders"
|
||||
@echo " OSL_BUILD_MATERIALX=0 Don't build MaterialX shaders"
|
||||
@echo " USE_SIMD=arch Build with SIMD support (choices: 0, sse2, sse3,"
|
||||
@echo " ssse3, sse4.1, sse4.2, f16c, avx, avx2"
|
||||
@echo " comma-separated ok)"
|
||||
@echo " USE_OPTIX=1 Build the OptiX test renderer"
|
||||
@echo " make test, extra options:"
|
||||
@echo " TEST=regex Run only tests matching the regex"
|
||||
@echo ""
|
||||
|
||||
@@ -9,6 +9,7 @@ Open Shading Language
|
||||
Build status:
|
||||
|
||||
[](https://travis-ci.org/imageworks/OpenShadingLanguage)
|
||||
[](https://ci.appveyor.com/project/lgritz/openshadinglanguage)
|
||||
|
||||
**Table of contents**
|
||||
|
||||
@@ -242,6 +243,7 @@ adding OSL support):
|
||||
* [DNA Research: 3Delight](http://www.3delight.com/)
|
||||
* Ubisoft motion picture group's proprietary renderer
|
||||
* [Autodesk/SolidAngle: Arnold](https://www.solidangle.com/arnold/)
|
||||
* [Autodesk: 3DS Max 2019](https://help.autodesk.com/view/3DSMAX/2019/ENU/?guid=__developer_3ds_max_sdk_features_rendering_osl_html)
|
||||
|
||||
Films using OSL (grouped by year of release date):
|
||||
* **(2012)**
|
||||
@@ -275,8 +277,10 @@ Films using OSL (grouped by year of release date):
|
||||
Suicide Squad,
|
||||
Kingsglaive: Final Fantasy XV,
|
||||
Storks,
|
||||
Miss Peregrine's Home for Peculiar Children, Assassin's Creed
|
||||
* **(2017) / upcoming**
|
||||
Miss Peregrine's Home for Peculiar Children,
|
||||
Fantastic Beasts and Where to Find Them,
|
||||
Assassin's Creed
|
||||
* **(2017)**
|
||||
Lego Batman,
|
||||
The Great Wall,
|
||||
A Cure for Wellness,
|
||||
@@ -296,9 +300,50 @@ Films using OSL (grouped by year of release date):
|
||||
The Emoji Movie,
|
||||
Detroit,
|
||||
Kingsman: The Golden Circle,
|
||||
Lega Ninjago Movie,
|
||||
Lego Ninjago Movie,
|
||||
Blade Runner 2049,
|
||||
Geostorm,
|
||||
Coco,
|
||||
Justice League,
|
||||
Thor: Ragnarok
|
||||
* **(2018)**
|
||||
Peter Rabbit,
|
||||
Black Panther,
|
||||
Annnihilation,
|
||||
Red Sparrow,
|
||||
Pacific Rim Uprising,
|
||||
Avengers Infinity War,
|
||||
Deadpool 2,
|
||||
Incredibles 2,
|
||||
Jurassic World: Fallen Kingdom,
|
||||
Hotel Transylvania 3: Summer Vacation,
|
||||
Ant Man and the Wasp,
|
||||
Skyscraper,
|
||||
Mission Impossible: Fallout,
|
||||
The Meg,
|
||||
Kin,
|
||||
Smallfoot,
|
||||
Alpha,
|
||||
Venom,
|
||||
First Man,
|
||||
Bad Times at the El Royale,
|
||||
Fantastic Beasts: The Crimes of Grindelwald,
|
||||
Bohemian Rhapsody,
|
||||
Holmes and Watson,
|
||||
Spider-Man: Into the Spider-Verse
|
||||
* **(2019 / upcoming)**
|
||||
The Kid Who Would Be King,
|
||||
Alita: Battle Angel,
|
||||
Lego Movie 2,
|
||||
Lucky 13,
|
||||
Captain Marvel,
|
||||
Avengers: Endgame,
|
||||
Pokémon Detective Pikachu,
|
||||
Godzilla: King of Monsters,
|
||||
Rim of the World,
|
||||
Men in Black International,
|
||||
Toy Story 4,
|
||||
Spider-Man: Far From Home,
|
||||
...
|
||||
|
||||
|
||||
@@ -339,11 +384,12 @@ Van Lommel.
|
||||
|
||||
Additionally, many others have contributed features, bug fixes, and other
|
||||
changes: Steve Agland, Shane Ambler, Martijn Berger, Farchad Bidgolirad,
|
||||
Nicholas Bishop, Stefan Büttner, Matthaus G. Chajdas, Thomas Dinges, Henri
|
||||
Fousse, Syoyo Fujita, Derek Haase, Sven-Hendrik Haase, John Haddon, Daniel
|
||||
Heckenberg, Ronan Keryell, Elvic Liang, Max Liani, Bastien Montagne, Erich
|
||||
Ocean, Mikko Ohtamaa, Alex Schworer, Sergey Sharybin, Stephan Steinbach,
|
||||
Esteban Tovagliari, Alexander von Knorring, Roman Zulak. (Listed
|
||||
Nicholas Bishop, Stefan Büttner, Matthaus G. Chajdas, Thomas Dinges, Mark
|
||||
Final, Henri Fousse, Syoyo Fujita, Tim Grant, Derek Haase, Sven-Hendrik
|
||||
Haase, John Haddon, Daniel Heckenberg, Matt Johnson, Ronan Keryell, Elvic
|
||||
Liang, Max Liani, Bastien Montagne, Alexis Oblet, Erich Ocean, Mikko
|
||||
Ohtamaa, Alex Schworer, Jonathan Scruggs, Sergey Sharybin, Stephan
|
||||
Steinbach, Esteban Tovagliari, Alexander von Knorring, Roman Zulak. (Listed
|
||||
alphabetically; if we've left anybody out, please let us know.)
|
||||
|
||||
We cannot possibly express sufficient gratitude to the managers at Sony
|
||||
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
clone_depth: 10
|
||||
version: '{branch}-{build}'
|
||||
|
||||
# Disable Appveyor's test discovery which is not used
|
||||
test: off
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- release
|
||||
- appveyor
|
||||
- /RB-/
|
||||
- /lg-/
|
||||
|
||||
skip_tags: true
|
||||
|
||||
build:
|
||||
parallel: true
|
||||
verbosity: detailed
|
||||
|
||||
platform:
|
||||
- x64
|
||||
# - x86
|
||||
|
||||
configuration:
|
||||
#- Debug
|
||||
- Release
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- TOOLSET: msvc14
|
||||
|
||||
os:
|
||||
- Visual Studio 2015
|
||||
|
||||
cache:
|
||||
- C:\projects\OSLdeps -> appveyor.yml
|
||||
# The -> means that the cache dir is discarded if appveyor.yml has changed
|
||||
|
||||
before_build:
|
||||
- ps: |
|
||||
$OSL_INSTALL_BEGIN=Get-Date
|
||||
Write-Output "Configuration: $env:CONFIGURATION"
|
||||
Write-Output "Platform: $env:PLATFORM"
|
||||
ls C:\Libraries\llvm-5.0.0
|
||||
Get-ChildItem Env:
|
||||
|
||||
[Array]$OSL_BUILD_FLAGS = "--", "/nologo", "/verbosity:minimal";
|
||||
|
||||
$DWN_DIR = "C:\projects\OSLdownloads"
|
||||
$DEP_DIR = "C:\projects\OSLdeps"
|
||||
$BOOST_ROOT = "C:\Libraries\boost_1_63_0"
|
||||
$PYTHON_DIR = "C:\Python27"
|
||||
$LLVM_DIR = "C:\Libraries\llvm-5.0.0"
|
||||
#$LLVM_DIR = "$DEP_DIR"
|
||||
$env:Path += ";$DEP_DIR\lib;$DEP_DIR\bin"
|
||||
$OSL_INT_DIR = "build\windows$env:PLATFORM"
|
||||
|
||||
# RDP into the build-bot to try some stuff out
|
||||
# iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
# $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
|
||||
# Choose the VisualStudio generator
|
||||
$GENERATOR = switch ($env:TOOLSET)
|
||||
{
|
||||
"msvc14" {"Visual Studio 14 2015"}
|
||||
"msvc12" {"Visual Studio 12 2013"}
|
||||
"msvc11" {"Visual Studio 11 2012"}
|
||||
"msvc10" {"Visual Studio 10 2010"}
|
||||
}
|
||||
|
||||
# Final setup based on 64 or 32 bit
|
||||
if ($env:PLATFORM -eq "x64") {
|
||||
$GENERATOR = "$GENERATOR Win64"
|
||||
$PYTHON_DIR = "$PYTHON_DIR-x64"
|
||||
$BOOST_LIBRARYDIR = "$BOOST_ROOT\lib64-msvc-14.0"
|
||||
} else {
|
||||
$BOOST_LIBRARYDIR = "$BOOST_ROOT\lib32-msvc-14.0"
|
||||
}
|
||||
|
||||
# Always create the download directory
|
||||
md $DWN_DIR -Force | Out-Null;
|
||||
|
||||
# If the dependency directory exists/cached, use it
|
||||
if(!(Test-Path -Path $DEP_DIR )){
|
||||
md $DEP_DIR -Force | Out-Null; cd $DEP_DIR
|
||||
md $DEP_DIR\include -Force | Out-Null; cd $DEP_DIR
|
||||
md $DEP_DIR\lib -Force | Out-Null; cd $DEP_DIR
|
||||
|
||||
cd $DWN_DIR
|
||||
nuget install libtiff-$env:TOOLSET-$env:PLATFORM-master -Version 4.0.6.85 -Source https://ci.appveyor.com/nuget/libtiff-i3h8tqqy7o7b
|
||||
mv .\libtiff*\*.h $DEP_DIR\include\
|
||||
mv .\libtiff*\*.lib $DEP_DIR\lib\
|
||||
mv .\libtiff*\*.dll $DEP_DIR\lib\
|
||||
|
||||
nuget install libpng-$env:TOOLSET-$env:PLATFORM-master -Version 1.6.18.44 -Source https://ci.appveyor.com/nuget/libpng-7hwq4pmmrc48
|
||||
mv .\libpng*\*.h $DEP_DIR\include\
|
||||
mv .\libpng*\*.lib $DEP_DIR\lib\
|
||||
mv .\libpng*\*.dll $DEP_DIR\lib\
|
||||
|
||||
nuget install libjpeg-$env:TOOLSET-$env:PLATFORM-master -Version 1.4.80.21 -Source https://ci.appveyor.com/nuget/libjpegturbo-o6k4js4y7pjw
|
||||
mv .\libjpeg*\*.h $DEP_DIR\include\
|
||||
mv .\libjpeg*\*.lib $DEP_DIR\lib\
|
||||
mv .\libjpeg*\*.dll $DEP_DIR\lib\
|
||||
|
||||
nuget install freetype
|
||||
mv .\freetype.2.8.0.1\build\native\include\* $DEP_DIR\include\
|
||||
mv .\freetype.2.8.0.1\build\native\lib\$env:PLATFORM\v140\dynamic\$env:CONFIGURATION\*.lib $DEP_DIR\lib\
|
||||
mv .\freetype.redist.2.8.0.1\build\native\bin\$env:PLATFORM\v140\dynamic\$env:CONFIGURATION\*.dll $DEP_DIR\lib\
|
||||
|
||||
# ZLib
|
||||
cd $DWN_DIR
|
||||
Start-FileDownload https://github.com/madler/zlib/archive/v1.2.8.tar.gz
|
||||
tar -xzf v1.2.8.tar.gz; cd zlib-1.2.8; md "$OSL_INT_DIR" -Force | Out-Null; cd "$OSL_INT_DIR"
|
||||
cmake ..\.. -G "$GENERATOR" -DCMAKE_CONFIGURATION_TYPES="$env:CONFIGURATION" -DCMAKE_PREFIX_PATH="$DEP_DIR" -DCMAKE_INSTALL_PREFIX="$DEP_DIR"
|
||||
cmake --build . --config $env:CONFIGURATION --target INSTALL $OSL_BUILD_FLAGS
|
||||
|
||||
# IlmBase
|
||||
cd $DWN_DIR
|
||||
Start-FileDownload http://download.savannah.nongnu.org/releases/openexr/ilmbase-2.2.1.tar.gz
|
||||
tar -xzf ilmbase-2.2.1.tar.gz ; cd ilmbase* ; md "$OSL_INT_DIR" -Force | Out-Null; cd "$OSL_INT_DIR"
|
||||
cmake ..\.. -G "$GENERATOR" -DCMAKE_CONFIGURATION_TYPES="$env:CONFIGURATION" -DCMAKE_PREFIX_PATH="$DEP_DIR" -DCMAKE_INSTALL_PREFIX="$DEP_DIR" -DCMAKE_CXX_FLAGS=" /W1 /EHsc /DWIN32=1 "
|
||||
cmake --build . --config $env:CONFIGURATION --target INSTALL $OSL_BUILD_FLAGS
|
||||
|
||||
# LLVM
|
||||
# This shouldn't be necessary, we use the pre-installed LLVM
|
||||
# cd $DWN_DIR
|
||||
# git clone --depth 10 --branch release_40 https://github.com/llvm-mirror/llvm.git
|
||||
# cd llvm; md "$OSL_INT_DIR" -Force | Out-Null; cd "$OSL_INT_DIR"
|
||||
# cmake ..\.. -G "$GENERATOR" -DCMAKE_CONFIGURATION_TYPES="$env:CONFIGURATION" -DCMAKE_PREFIX_PATH="$DEP_DIR" -DCMAKE_INSTALL_PREFIX="$DEP_DIR" -DLLVM_TARGETS_TO_BUILD="X86"
|
||||
# cmake --build . --config $env:CONFIGURATION --target INSTALL $OSL_BUILD_FLAGS
|
||||
|
||||
# OpenEXR
|
||||
cd $DWN_DIR
|
||||
Start-FileDownload http://download.savannah.nongnu.org/releases/openexr/openexr-2.2.1.tar.gz
|
||||
tar -xzf openexr-2.2.1.tar.gz ; cd openexr* ; md "$OSL_INT_DIR" -Force | Out-Null; cd "$OSL_INT_DIR"
|
||||
cmake ..\.. -G "$GENERATOR" -DCMAKE_CONFIGURATION_TYPES="$env:CONFIGURATION" -DCMAKE_PREFIX_PATH="$DEP_DIR" -DCMAKE_INSTALL_PREFIX="$DEP_DIR" -DILMBASE_PACKAGE_PREFIX="$DEP_DIR" -DCMAKE_CXX_FLAGS=" /W1 /EHsc /DWIN32=1 "
|
||||
cmake --build . --config $env:CONFIGURATION --target INSTALL $OSL_BUILD_FLAGS
|
||||
|
||||
}
|
||||
|
||||
# Always do this
|
||||
cinst winflexbison
|
||||
|
||||
|
||||
build_script:
|
||||
- ps: |
|
||||
# OpenImageIO
|
||||
$env:OPENIMAGEIO_ROOT_DIR = "C:\projects\oiio"
|
||||
$env:FREETYPE_DIR = "$DEP_DIR"
|
||||
$FREETYPE_LIBRARY = "$DEP_DIR\lib\freetype28.lib"
|
||||
cd $DWN_DIR
|
||||
git clone --depth 10 https://github.com/OpenImageIO/oiio.git oiiosrc
|
||||
cd .\oiiosrc; md "$OSL_INT_DIR" -Force | Out-Null; cd "$OSL_INT_DIR"
|
||||
cmake ..\.. -G "$GENERATOR" -DCMAKE_CONFIGURATION_TYPES="$env:CONFIGURATION" -DCMAKE_INSTALL_PREFIX="$env:OPENIMAGEIO_ROOT_DIR" -DCMAKE_PREFIX_PATH="$DEP_DIR;$BOOST_ROOT" -DBOOST_LIBRARYDIR="$BOOST_LIBRARYDIR" -DFREETYPE_LIBRARY="$FREETYPE_LIBRARY" -DUSE_PYTHON=OFF -DOIIO_BUILD_TESTS=OFF -DUSE_NUKE=OFF
|
||||
cmake --build . --config $env:CONFIGURATION --target INSTALL $OSL_BUILD_FLAGS
|
||||
|
||||
# Build OSL
|
||||
cd $env:APPVEYOR_BUILD_FOLDER
|
||||
md "$OSL_INT_DIR" -Force | Out-Null; cd "$OSL_INT_DIR"
|
||||
cmake ..\.. -G "$GENERATOR" -DCMAKE_CONFIGURATION_TYPES="$env:CONFIGURATION" -DCMAKE_PREFIX_PATH="$env:OPENIMAGEIO_ROOT_DIR;$DEP_DIR;$BOOST_ROOT;$LLVM_DIR" -DCMAKE_INSTALL_PREFIX="$DEP_DIR" -DLLVM_DIRECTORY="$LLVM_DIR" -DLLVM_STATIC=ON -DOPENIMAGEIO_ROOT_DIR="$env:OPENIMAGEIO_ROOT_DIR" -DBOOST_LIBRARYDIR="$BOOST_LIBRARYDIR" -DFLEX_EXECUTABLE="C:\ProgramData\chocolatey\lib\winflexbison\tools\win_flex.exe" -DBISON_EXECUTABLE="C:\ProgramData\chocolatey\lib\winflexbison\tools\win_bison.exe" -DUSE_QT=OFF -DBUILDSTATIC=OFF -DLINKSTATIC=OFF
|
||||
|
||||
# OSL's CMake should probably be handling Windows config better...
|
||||
$OSL_BUILD_DIR = "$env:APPVEYOR_BUILD_FOLDER\$OSL_INT_DIR"
|
||||
$env:OSL_ROOT_DIR = "$env:APPVEYOR_BUILD_FOLDER\src"
|
||||
$env:OIIO_LIBRARY_PATH = "$OSL_BUILD_DIR\src\osl.imageio\$env:CONFIGURATION"
|
||||
$env:Path += ";$OSL_BUILD_DIR\src\oslc\$env:CONFIGURATION"
|
||||
$env:Path += ";$OSL_BUILD_DIR\src\oslinfo\$env:CONFIGURATION"
|
||||
$env:Path += ";$OSL_BUILD_DIR\src\liboslcomp\$env:CONFIGURATION"
|
||||
$env:Path += ";$OSL_BUILD_DIR\src\liboslexec\$env:CONFIGURATION"
|
||||
$env:Path += ";$OSL_BUILD_DIR\src\liboslnoise\$env:CONFIGURATION"
|
||||
$env:Path += ";$OSL_BUILD_DIR\src\liboslquery\$env:CONFIGURATION"
|
||||
$env:Path += ";$env:OPENIMAGEIO_ROOT_DIR\lib;$env:OPENIMAGEIO_ROOT_DIR\bin"
|
||||
$env:Path += ";$BOOST_LIBRARYDIR"
|
||||
|
||||
cmake --build . --config $env:CONFIGURATION $OSL_BUILD_FLAGS
|
||||
|
||||
$OSL_BUILD_END=Get-Date
|
||||
if(($OSL_BUILD_END-$OSL_INSTALL_BEGIN).TotalMinutes -gt 50) {
|
||||
# Change to appveyor.yml means the cache needs to be rebuilt leaving
|
||||
# us with not enough time to run the tests.
|
||||
echo "OSL tests skipped in favor of uploading dependency cache"
|
||||
# Echo to build log and Appveyors message page
|
||||
Add-AppveyorMessage -Message "OSL tests skipped in favor of uploading dependency cache" -Category Warning
|
||||
} else {
|
||||
# Test OSL
|
||||
ctest -C $env:CONFIGURATION --output-on-failure
|
||||
}
|
||||
|
||||
|
||||
#init:
|
||||
#- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
|
||||
#on_failure:
|
||||
#- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
# Pixar-specific settings
|
||||
|
||||
ifneq (${VERBOSE},)
|
||||
$(info Including pixar/Makefile-bits)
|
||||
endif
|
||||
|
||||
MY_CMAKE_FLAGS += -DUSE_fPIC:BOOL=1
|
||||
MY_CMAKE_FLAGS += -DENABLERTTI:BOOL=1
|
||||
MY_CMAKE_FLAGS += -DSTOP_ON_WARNING:BOOL=0
|
||||
MY_CMAKE_FLAGS += -DHIDE_SYMBOLS:BOOL=1
|
||||
MY_CMAKE_FLAGS += -DBUILDSTATIC:BOOL=1
|
||||
MY_CMAKE_FLAGS += -DLINKSTATIC:BOOL=1
|
||||
MY_CMAKE_FLAGS += -DUSE_FAST_MATH:BOOL=1
|
||||
MY_CMAKE_FLAGS += -DOPENEXR_CUSTOM_LIB_DIR:STRING=${ILMBASE_HOME}/lib/linux-ix86-64/gcc4.1
|
||||
MY_CMAKE_FLAGS += -DOPENEXR_CUSTOM_LIB_SUFFIX:STRING="-fPIC"
|
||||
|
||||
# Don't build testshade or testrender (mostly because they require the
|
||||
# image-handling parts of OIIO, which Pixar doesn't build)
|
||||
MY_CMAKE_FLAGS += -DOSL_BUILD_TESTS:BOOL=0
|
||||
|
||||
# Don't let OSL create a default OIIO::TextureSystem. If the renderer
|
||||
# doesn't pass in whatever proxy it wants, it will assert.
|
||||
MY_CMAKE_FLAGS += -DOSL_NO_DEFAULT_TEXTURESYSTEM:BOOL=1
|
||||
|
||||
ifneq (${VERBOSE},)
|
||||
$(info MY_CMAKE_FLAGS: $(MY_CMAKE_FLAGS))
|
||||
endif
|
||||
+44
-17
@@ -15,10 +15,12 @@ ifeq ($(SP_OS), rhel7)
|
||||
MY_CMAKE_FLAGS += -DCMAKE_MAKE_PROGRAM=${NINJA}
|
||||
# Override lib64 and use SPI convention of lib
|
||||
MY_CMAKE_FLAGS += -DCMAKE_INSTALL_LIBDIR="${INSTALL_PREFIX}/lib"
|
||||
MY_CMAKE_FLAGS += -DCUDA_TOOLKIT_ROOT_DIR=/net/soft_scratch/apps/arnold/tools/nvidia/cuda8.0 -DOPTIX_EXTRA_LIBS=lzma
|
||||
MY_CMAKE_FLAGS += -DOPTIXHOME=/net/soft_scratch/apps/arnold/tools/nvidia/NVIDIA-OptiX-SDK-5.1.0-linux64
|
||||
|
||||
## If not overridden, here is our preferred LLVM installation
|
||||
## (may be changed as new versions are rolled out to the facility)
|
||||
LLVM_DIRECTORY ?= /shots/spi/home/lib/arnold/rhel7/llvm_5.0.0
|
||||
LLVM_DIRECTORY ?= /shots/spi/home/lib/arnold/rhel7/llvm_7.0.0
|
||||
|
||||
# A variety of tags can be used to try specific versions of gcc or
|
||||
# clang from the site-specific places we have installed them.
|
||||
@@ -28,14 +30,26 @@ ifeq ($(SP_OS), rhel7)
|
||||
-DCMAKE_CXX_COMPILER=/shots/spi/home/lib/arnold/rhel7/llvm_4.0_final/bin/clang++
|
||||
else ifeq (${COMPILER}, clang5)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=/shots/spi/home/lib/arnold/rhel7/llvm_5.0.0/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/shots/spi/home/lib/arnold/rhel7/llvm_5.0.0/bin/clang++
|
||||
-DCMAKE_C_COMPILER=/shots/spi/home/lib/arnold/rhel7/llvm_5.0.1/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/shots/spi/home/lib/arnold/rhel7/llvm_5.0.1/bin/clang++
|
||||
else ifeq (${COMPILER}, clang6)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=/shots/spi/home/lib/arnold/rhel7/llvm_6.0.1/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/shots/spi/home/lib/arnold/rhel7/llvm_6.0.1/bin/clang++
|
||||
else ifeq (${COMPILER}, clang7)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=/shots/spi/home/lib/arnold/rhel7/llvm_7.0.0/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/shots/spi/home/lib/arnold/rhel7/llvm_7.0.0/bin/clang++
|
||||
else ifeq (${COMPILER},clang)
|
||||
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
||||
else ifeq (${COMPILER}, gcc490)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=/net/soft_scratch/apps/arnold/tools/gcc-4.9-20130512-test/bin/gcc \
|
||||
-DCMAKE_CXX_COMPILER=/net/soft_scratch/apps/arnold/tools/gcc-4.9-20130512-test/bin/g++
|
||||
else ifeq (${COMPILER}, gcc6)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=/opt/rh/devtoolset-6/root/usr/bin/gcc \
|
||||
-DCMAKE_CXX_COMPILER=/opt/rh/devtoolset-6/root/usr/bin/g++
|
||||
else ifeq (${COMPILER},gcc)
|
||||
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++
|
||||
else ifeq (${COMPILER},)
|
||||
@@ -43,11 +57,15 @@ ifeq ($(SP_OS), rhel7)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=${LLVM_DIRECTORY}/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=${LLVM_DIRECTORY}/bin/clang++
|
||||
MY_CMAKE_FLAGS += -DCMAKE_C_FLAGS="--gcc-toolchain=/usr" \
|
||||
-DCMAKE_CXX_FLAGS="--gcc-toolchain=/usr" \
|
||||
-DTOOLCHAIN_FLAGS="--gcc-toolchain=/usr"
|
||||
endif
|
||||
|
||||
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DOPENEXR_CUSTOM_INCLUDE_DIR=/usr/include/OpenEXR2 \
|
||||
-DOPENEXR_CUSTOM_LIB_DIR=/usr/lib64/OpenEXR2 \
|
||||
-DOPENEXR_INCLUDE_DIR=/usr/include/OpenEXR2 \
|
||||
-DOPENEXR_LIBRARY_DIR=/usr/lib64/OpenEXR2 \
|
||||
-DPARTIO_HOME="/shots/spi/home/lib/SpComp2/partio/rhel7-gcc48m64/v1" \
|
||||
-DLLVM_STATIC=1 \
|
||||
-DLLVM_VERSION=${LLVM_VERSION} \
|
||||
@@ -56,17 +74,26 @@ ifeq ($(SP_OS), rhel7)
|
||||
ifneq (${SPCOMP2_USE_BOOSTVERS}, 1)
|
||||
BOOSTVERS=1.55
|
||||
endif
|
||||
BOOSTVERSSP=${BOOSTVERS}sp
|
||||
|
||||
BOOSTSPSUFFIX ?=
|
||||
BOOSTVERSSP=${BOOSTVERS}${BOOSTSPSUFFIX}
|
||||
BOOSTVERS_SUFFIX = -${shell echo ${BOOSTVERS} | sed "s/\\./_/"}
|
||||
BOOSTVERS_PREFIX = ${shell echo ${BOOSTVERS} | sed "s/\\./_/"}_0
|
||||
CONSTRUCTED_BOOSTVERS = ${shell echo ${BOOSTVERS} | sed "s/\\./0/"}00
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DBOOST_CUSTOM=1 \
|
||||
-DBoost_VERSION=${CONSTRUCTED_BOOSTVERS} \
|
||||
-DBoost_INCLUDE_DIRS=/usr/include/boost_${BOOSTVERSSP} \
|
||||
-DBoost_LIBRARY_DIRS=/usr/lib64/boost_${BOOSTVERS} \
|
||||
-DBoost_LIBRARIES:STRING="/usr/lib64/boost_${BOOSTVERSSP}/libspboost_${BOOSTVERS_PREFIX}_filesystem-gcc48-mt${BOOSTVERS_SUFFIX}.so;/usr/lib64/boost_${BOOSTVERSSP}/libspboost_${BOOSTVERS_PREFIX}_regex-gcc48-mt${BOOSTVERS_SUFFIX}.so;/usr/lib64/boost_${BOOSTVERSSP}/libspboost_${BOOSTVERS_PREFIX}_system-gcc48-mt${BOOSTVERS_SUFFIX}.so;/usr/lib64/boost_${BOOSTVERSSP}/libspboost_${BOOSTVERS_PREFIX}_thread-gcc48-mt${BOOSTVERS_SUFFIX}.so;/usr/lib64/boost_${BOOSTVERSSP}/libspboost_${BOOSTVERS_PREFIX}_wave-gcc48-mt${BOOSTVERS_SUFFIX}.so"
|
||||
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DBOOST_CUSTOM=1 \
|
||||
-DBoost_VERSION=${CONSTRUCTED_BOOSTVERS} \
|
||||
-DBoost_INCLUDE_DIRS=/usr/include/boost_${BOOSTVERSSP} \
|
||||
-DBoost_LIBRARY_DIRS=/usr/lib64/boost_${BOOSTVERS}
|
||||
|
||||
ifeq (${BOOSTSPSUFFIX}, sp)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DBoost_LIBRARIES:STRING="/usr/lib64/boost_${BOOSTVERSSP}/lib${BOOSTSPSUFFIX}boost_${BOOSTVERS_PREFIX}_regex-gcc48-mt${BOOSTVERS_SUFFIX}.so;/usr/lib64/boost_${BOOSTVERSSP}/lib${BOOSTSPSUFFIX}boost_${BOOSTVERS_PREFIX}_system-gcc48-mt${BOOSTVERS_SUFFIX}.so;/usr/lib64/boost_${BOOSTVERSSP}/lib${BOOSTSPSUFFIX}boost_${BOOSTVERS_PREFIX}_thread-gcc48-mt${BOOSTVERS_SUFFIX}.so"
|
||||
else
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DBoost_LIBRARIES:STRING="/usr/lib64/boost_${BOOSTVERSSP}/lib${BOOSTSPSUFFIX}boost_regex-gcc48-mt${BOOSTVERS_SUFFIX}.so;/usr/lib64/boost_${BOOSTVERSSP}/lib${BOOSTSPSUFFIX}boost_system-gcc48-mt${BOOSTVERS_SUFFIX}.so;/usr/lib64/boost_${BOOSTVERSSP}/lib${BOOSTSPSUFFIX}boost_thread-gcc48-mt${BOOSTVERS_SUFFIX}.so"
|
||||
endif
|
||||
# end rhel7
|
||||
|
||||
## Generic OSX machines (including LG's laptop)
|
||||
@@ -89,10 +116,10 @@ else ifeq (${platform}, macosx)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=gcc-6 -DCMAKE_CXX_COMPILER=g++-6
|
||||
USE_LIBCPLUSPLUS := 0
|
||||
else ifeq (${COMPILER},clang35)
|
||||
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=clang-3.5 -DCMAKE_CXX_COMPILER=clang++-3.5
|
||||
else ifeq (${COMPILER},clang40)
|
||||
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=/usr/local/opt/llvm@4/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@4/bin/clang++
|
||||
else ifeq (${COMPILER},clang7)
|
||||
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=/usr/local/Cellar/llvm/7.0.0rc1/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/Cellar/llvm/7.0.0rc1/bin/clang++
|
||||
else ifeq (${COMPILER},clang)
|
||||
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
||||
else ifeq (${COMPILER},gcc)
|
||||
@@ -112,10 +139,10 @@ endif # endif $(SP_OS)
|
||||
|
||||
|
||||
# set up OpenImageIO distribution environment
|
||||
ifeq (${OPENIMAGEIOHOME},)
|
||||
MY_CMAKE_FLAGS += -DOPENIMAGEIOHOME:STRING=${working_dir}/../OpenImageIO_local/dist/${platform}${variant}/
|
||||
ifeq (${OPENIMAGEIO_ROOT_DIR},)
|
||||
MY_CMAKE_FLAGS += -DOPENIMAGEIO_ROOT_DIR:STRING=${working_dir}/../OpenImageIO_local/dist/${platform}${variant}/
|
||||
else
|
||||
MY_CMAKE_FLAGS += -DOPENIMAGEIOHOME:STRING=${IMAGEIOHOME}
|
||||
MY_CMAKE_FLAGS += -DOPENIMAGEIO_ROOT_DIR:STRING=${OPENIMAGEIO_ROOT_DIR}
|
||||
endif
|
||||
|
||||
|
||||
|
||||
@@ -1,48 +1,62 @@
|
||||
#!/bin/bash
|
||||
|
||||
# The Linux VM used by Travis has OpenEXR 1.x. We really want 2.x.
|
||||
# This script downloads and builds OpenEXR in the ext/ subdirectory.
|
||||
|
||||
EXRREPO=${EXRREPO:=https://github.com/openexr/openexr.git}
|
||||
EXRINSTALLDIR=${EXRINSTALLDIR:=${PWD}/openexr-install}
|
||||
EXRBRANCH=${EXRBRANCH:=v2.2.0}
|
||||
EXRINSTALLDIR=${EXRINSTALLDIR:=${PWD}/ext/openexr-install}
|
||||
EXRBRANCH=${EXRBRANCH:=v2.3.0}
|
||||
EXRCXXFLAGS=${EXRCXXFLAGS:=""}
|
||||
BASEDIR=`pwd`
|
||||
pwd
|
||||
echo "EXR install dir will be: ${EXRINSTALLDIR}"
|
||||
|
||||
if [ ! -e ${EXRINSTALLDIR} ] ; then
|
||||
mkdir ${EXRINSTALLDIR}
|
||||
if [[ ! -e ${EXRINSTALLDIR} ]] ; then
|
||||
mkdir -p ${EXRINSTALLDIR}
|
||||
fi
|
||||
|
||||
# Clone OpenEXR project (including IlmBase) from GitHub and build
|
||||
if [ ! -e ./openexr ] ; then
|
||||
echo "git clone ${EXRREPO} ./openexr"
|
||||
git clone ${EXRREPO} ./openexr
|
||||
if [[ ! -e ./ext/openexr ]] ; then
|
||||
echo "git clone ${EXRREPO} ./ext/openexr"
|
||||
git clone ${EXRREPO} ./ext/openexr
|
||||
fi
|
||||
|
||||
flags=
|
||||
|
||||
if [ ${LINKSTATIC:=0} == 1 ] ; then
|
||||
if [[ ${LINKSTATIC:=0} == 1 ]] ; then
|
||||
flags=${flags} --enable-static --enable-shared=no --with-pic
|
||||
fi
|
||||
|
||||
pushd ./openexr
|
||||
pushd ./ext/openexr
|
||||
echo "git checkout ${EXRBRANCH} --force"
|
||||
git checkout ${EXRBRANCH} --force
|
||||
cd IlmBase
|
||||
mkdir build
|
||||
cd build
|
||||
cmake --config Release -DCMAKE_INSTALL_PREFIX=${EXRINSTALLDIR} -DCMAKE_CXX_FLAGS=${EXRCXXFLAGS} .. && make clean && make -j 4 && make install
|
||||
cd ..
|
||||
cd ../OpenEXR
|
||||
cp ${BASEDIR}/src/build-scripts/OpenEXR-CMakeLists.txt CMakeLists.txt
|
||||
cp ${BASEDIR}/src/build-scripts/OpenEXR-IlmImf-CMakeLists.txt IlmImf/CMakeLists.txt
|
||||
mkdir build
|
||||
mkdir build/IlmImf
|
||||
cd build
|
||||
unzip -d IlmImf ${BASEDIR}/src/build-scripts/b44ExpLogTable.h.zip
|
||||
unzip -d IlmImf ${BASEDIR}/src/build-scripts/dwaLookups.h.zip
|
||||
cmake --config Release -DCMAKE_INSTALL_PREFIX=${EXRINSTALLDIR} -DILMBASE_PACKAGE_PREFIX=${EXRINSTALLDIR} -DBUILD_UTILS=0 -DBUILD_TESTS=0 -DCMAKE_CXX_FLAGS=${EXRCXXFLAGS} .. && make clean && make -j 4 && make install
|
||||
|
||||
if [[ ${EXRBRANCH} == "v2.3.0" ]] ; then
|
||||
# Simplified setup for 2.3+
|
||||
mkdir build
|
||||
cd build
|
||||
mkdir OpenEXR
|
||||
mkdir OpenEXR/IlmImf
|
||||
unzip -d OpenEXR/IlmImf ${BASEDIR}/src/build-scripts/b44ExpLogTable.h.zip
|
||||
unzip -d OpenEXR/IlmImf ${BASEDIR}/src/build-scripts/dwaLookups.h.zip
|
||||
cmake --config Release -DCMAKE_INSTALL_PREFIX=${EXRINSTALLDIR} -DILMBASE_PACKAGE_PREFIX=${EXRINSTALLDIR} -DOPENEXR_BUILD_UTILS=0 -DOPENEXR_BUILD_TESTS=0 -DOPENEXR_BUILD_PYTHON_LIBS=0 -DCMAKE_CXX_FLAGS=${EXRCXXFLAGS} .. && make clean && make -j 4 && make install
|
||||
else
|
||||
cd IlmBase
|
||||
mkdir build
|
||||
cd build
|
||||
cmake --config Release -DCMAKE_INSTALL_PREFIX=${EXRINSTALLDIR} -DCMAKE_CXX_FLAGS=${EXRCXXFLAGS} .. && make clean && make -j 4 && make install
|
||||
cd ..
|
||||
cd ../OpenEXR
|
||||
cp ${BASEDIR}/src/build-scripts/OpenEXR-CMakeLists.txt CMakeLists.txt
|
||||
cp ${BASEDIR}/src/build-scripts/OpenEXR-IlmImf-CMakeLists.txt IlmImf/CMakeLists.txt
|
||||
mkdir build
|
||||
mkdir build/IlmImf
|
||||
cd build
|
||||
unzip -d IlmImf ${BASEDIR}/src/build-scripts/b44ExpLogTable.h.zip
|
||||
unzip -d IlmImf ${BASEDIR}/src/build-scripts/dwaLookups.h.zip
|
||||
cmake --config Release -DCMAKE_INSTALL_PREFIX=${EXRINSTALLDIR} -DILMBASE_PACKAGE_PREFIX=${EXRINSTALLDIR} -DBUILD_UTILS=0 -DBUILD_TESTS=0 -DCMAKE_CXX_FLAGS=${EXRCXXFLAGS} .. && make clean && make -j 4 && make install
|
||||
fi
|
||||
|
||||
popd
|
||||
|
||||
ls -R ${EXRINSTALLDIR}
|
||||
@@ -50,3 +64,11 @@ ls -R ${EXRINSTALLDIR}
|
||||
#echo "listing .."
|
||||
#ls ..
|
||||
|
||||
# Set up paths. These will only affect the caller if this script is
|
||||
# run with 'source' rather than in a separate shell.
|
||||
export ILMBASE_ROOT_DIR=$EXRINSTALLDIR
|
||||
export OPENEXR_ROOT_DIR=$EXRINSTALLDIR
|
||||
export ILMBASE_LIBRARY_DIR=$EXRINSTALLDIR/lib
|
||||
export OPENEXR_LIBRARY_DIR=$EXRINSTALLDIR/lib
|
||||
export LD_LIBRARY_PATH=$OPENEXR_ROOT_DIR/lib:$LD_LIBRARY_PATH
|
||||
|
||||
|
||||
Executable
+443
@@ -0,0 +1,443 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import print_function
|
||||
|
||||
# Copyright (c) 2018 Sony Pictures Imageworks Inc., et al.
|
||||
# BSD 3-clause license.
|
||||
# Distributed as part of Open Shading Language.
|
||||
# https://github.com/imageworks/OpenShadingLanguage
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# To generate docdeep for docdeep, run this:
|
||||
# python3 docdeep.py -d docdeep docdeep.py > docdeep.md.html
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
|
||||
### <doc docdeep>
|
||||
###
|
||||
### **docdeep**
|
||||
###
|
||||
### Introduction
|
||||
### ============
|
||||
###
|
||||
### `docdeep` is a utility that extracts documentation from source code and
|
||||
### turns them into beautiful Markdeep documents.
|
||||
###
|
||||
### [Markdeep](https://casual-effects.com/markdeep) is a package by Morgan
|
||||
### McGuire, an extension of Markdown with a whole bunch of nice features
|
||||
### that make it extra nice for code, math, and diagrams. Read the Markdeep
|
||||
### web page and look at the examples for details.
|
||||
###
|
||||
### `docdeep` is a little like `Doxygen`. A poor person's Doxygen. A very
|
||||
### poor person. But without Doxygen's awkward syntax -- you just write
|
||||
### the comments in Markdeep. And the output is very aesthetically pleasing.
|
||||
### But it doesn't have any bells and whistles, like cross-referencing.
|
||||
###
|
||||
###
|
||||
###
|
||||
### Markup controls
|
||||
### ===============
|
||||
###
|
||||
### ## Documentation lines.
|
||||
###
|
||||
### A line whose first three non-whitespace characters are either `///` or
|
||||
### `###` is called a *doc-line*. Any other line is a *non-doc-line*.
|
||||
###
|
||||
### The `///` or `###` is the *doc-symbol*. Generally speaking, the `///`
|
||||
### doc-symbol is used when doc-marking C or C++, and `###` when doc-marking
|
||||
### Python, shell scripts, or other programs in languages where `#` is the
|
||||
### comment character. For simplicity, in the rest of this document, we will
|
||||
### always use `///` in our examples.
|
||||
###
|
||||
### ## Doc regions
|
||||
###
|
||||
### Doc-lines by themeslves don't do much, unless they are within a
|
||||
### *doc-region*. The beginning of a doc-region is denoted by a doc-line
|
||||
### whose first characters after the doc-symbol is
|
||||
###
|
||||
### <code>
|
||||
### /// <doc region-name>
|
||||
### </code>
|
||||
###
|
||||
### A doc region is ended one of three ways:
|
||||
###
|
||||
### 1. `</doc>` ends the active region.
|
||||
### 2. `<doc newname>` setting a new region name.
|
||||
### 3. The end of the source file.
|
||||
###
|
||||
### When there is an active named region, any other doc lines will be
|
||||
### appended (after stripping off the doc symbol itself) to the current
|
||||
### doc region text.
|
||||
###
|
||||
### You can have multiple regions with the same name, in entirely separate
|
||||
### parts of your source code. They will just be concatenated.
|
||||
###
|
||||
### Only one main doc region will be output by the `docdeep` program,
|
||||
### specified with the `-d` command line argument. Any other doc-regions
|
||||
### will not be included in the documention output of that run.
|
||||
###
|
||||
### However, one doc-region may *include* the text of another doc-region
|
||||
### as follows:
|
||||
###
|
||||
### <code>
|
||||
### /// <inc region-name>
|
||||
### </code>
|
||||
###
|
||||
### ## Doc continuations and code regions
|
||||
###
|
||||
### If three dots follow the `doc` directive, like this:
|
||||
###
|
||||
### <code>
|
||||
### /// <doc... region-name>
|
||||
### </code>
|
||||
###
|
||||
### This causes *all* lines (until the end of the doc region) to be
|
||||
### interpreted as Markdeep documentation, even it if doesn't start with
|
||||
### the doc-symbol.
|
||||
###
|
||||
### Furthermore, denoting any region thusly:
|
||||
### <code>
|
||||
### /// <code>
|
||||
### ...
|
||||
### /// </code>
|
||||
### </code>
|
||||
###
|
||||
### will designate the contents not only as a doc continuation, but also
|
||||
### to be formatted as source code (mono space, syntax highlighted).
|
||||
###
|
||||
### ## API Explanations
|
||||
###
|
||||
### There is a special syntax for a common case: call-by-call explanations
|
||||
### of API methods and their explanations. Of course, this may constitute
|
||||
### the bulk of your auto-generated documentation. The two cases we are
|
||||
### concerned about is *pre-code comments* and *post-code comments*.
|
||||
###
|
||||
### For pre-code comments, the contiguous comment region associated with
|
||||
### a declaration immediately precedes the declaration. Such a comment
|
||||
### set has its first line start with `///>`. For post-code comments,
|
||||
### the documentaiton comments follows the code declaration, and this is
|
||||
### designated by having its first line start with `///<`. I like to
|
||||
### just remember that the `<` or `>` points in the direction of the code
|
||||
### declaration that the comment applies to.
|
||||
###
|
||||
### This is perhaps best explained by example:
|
||||
###
|
||||
### <code>
|
||||
### ///> Do the foo operation. Everybody knows what this is. You can write
|
||||
### /// any comment you want, with full markdeep formatting! It applies
|
||||
### /// to the declaration that will immediately follow this comment.
|
||||
### float foo (float x, float y);
|
||||
###
|
||||
### void bar (int n);
|
||||
### ///< The bar procedure. Note that with post-comments, you explain the
|
||||
### /// function or method *after* the declaration itself.
|
||||
### </code>
|
||||
###
|
||||
### This will generate the following output:
|
||||
###
|
||||
### <code>
|
||||
### float foo (float x, float y);
|
||||
### </code>
|
||||
### Do the foo operation. Everybody knows what this is. You can write
|
||||
### any comment you want, with full markdeep formatting! It applies
|
||||
### to the declaration that will immediately follow this comment.
|
||||
###
|
||||
### <code>
|
||||
### void bar (int n);
|
||||
### </code>
|
||||
### The bar procedure. Note that with post-comments, you explain the
|
||||
### function or method *after* the declaration itself.
|
||||
###
|
||||
### -----------------------
|
||||
###
|
||||
### It is important to keep in mind that **this API explanation is extremely
|
||||
### stupid**. The comment documentation is just a series of doc-lines with
|
||||
### no break between them, whose *first* line starts with `///>' or `///>`
|
||||
### (for pre-code and post-code docs, respectively). And the code that it
|
||||
### documents is just the immediately preceding or following set of non-doc
|
||||
### lines that contain *no* whitespace-only lines. There is no syntax
|
||||
### parsing going on here -- it just takes those non-blank, non-doc lines,
|
||||
### strips off any semicolons and any characters following the semicolon
|
||||
### from each line in the block, and deletes anything in the whole block
|
||||
### at or after the first opening brace (`{`) found in the block. Strangely
|
||||
### enough, this is almost exactly what I want to document.
|
||||
###
|
||||
###
|
||||
### Command line arguments
|
||||
### ======================
|
||||
###
|
||||
### Run from the command line as follows:
|
||||
###
|
||||
### `$ python docdeep.py -d` *region* `-s` *style.css* `input1.h input2.cpp [...] > output.md.html`
|
||||
###
|
||||
### Arguments:
|
||||
###
|
||||
### `-d` *region*
|
||||
### : Specifies the name of the doc-region to generate output for. This is
|
||||
### required.
|
||||
### `-s` *stylesheet*
|
||||
### : This optional argument will specify which CSS style sheet to include a
|
||||
### reference to.
|
||||
###
|
||||
### Any number of filenames may be specified. They will be processed in the
|
||||
### order that they appear on the command line.
|
||||
###
|
||||
|
||||
import sys
|
||||
import re
|
||||
import argparse
|
||||
|
||||
# pattern for beginning of special comment
|
||||
docline_pattern = re.compile ('(^[ \t]*)((///)|(###))[<>]?([ \t]|$)(.*)')
|
||||
doc_begin_pattern = re.compile ('(^[ \t]*)((///)|(###))[ ]*<doc(\.\.\.)?[ ]*(\w*)[ ]*>')
|
||||
docendpattern = re.compile ('(^[ \t]*)((///)|(###))[ ]*</doc>')
|
||||
api_precomment_pattern = re.compile ('(^[ \t]*)((///)|(###))>( )+( )?(.*)')
|
||||
api_postcomment_pattern = re.compile ('(^[ \t]*)((///)|(###))<( )+( )?(.*)')
|
||||
inc_pattern = re.compile ('(^[ \t]*)<inc[ ]+([^>]+)>')
|
||||
code_pattern = re.compile ('(^[ \t]*)((///)|(###))[ ]*<code>')
|
||||
codeend_pattern = re.compile ('(^[ \t]*)((///)|(###))[ ]*</code>')
|
||||
trimbrace_pattern = re.compile ("([^{]*)")
|
||||
trimsemi_pattern = re.compile ("([^;]*)")
|
||||
blankline_pattern = re.compile ("^[ \t]*$")
|
||||
|
||||
region_name = '_'
|
||||
alldocs = { '_' : '' }
|
||||
DEBUG = False
|
||||
|
||||
|
||||
# Utility: blob is a string (possibly containing many "lines" separated by
|
||||
# '\n'). For each line of text in the blob, shave off the first `indent`
|
||||
# characters. Then reassemble and return.
|
||||
def shave_each_line (blob, indent) :
|
||||
r = ''
|
||||
lines = blob.split ('\n')
|
||||
for line in lines :
|
||||
r += line[indent:] + '\n'
|
||||
# strip trailing newline unless the original blob had a trailing newline
|
||||
if len(r) and r[-1] == '\n' and blob[-1] != '\n':
|
||||
r = r[:-1]
|
||||
return r
|
||||
|
||||
# Enumerated type for the state machine.
|
||||
class LineType :
|
||||
BLANK = 0
|
||||
DOC = 2
|
||||
NONDOC = 3
|
||||
|
||||
# Append this doc blob to the current region, and clear the blob
|
||||
def flush_doc_blob (doc_blob) :
|
||||
global alldocs, region_name
|
||||
if len(doc_blob) :
|
||||
alldocs[region_name] += doc_blob + '\n'
|
||||
doc_blob = ''
|
||||
|
||||
def read_input (filename, file) :
|
||||
global region_name, alldocs
|
||||
doc_cont_mode = False
|
||||
post_api_mode = False
|
||||
pre_api_mode = False
|
||||
indent = 0 # Amount of indentation we saw on the liast doc line
|
||||
lines = file.read().splitlines()
|
||||
code_blob = '' # Running set of contiguous non-doc, non-blank lines
|
||||
doc_blob = '' # Running set of contiguous doc lines
|
||||
|
||||
# state machine
|
||||
line_type = LineType.BLANK
|
||||
last_line_type = LineType.BLANK
|
||||
|
||||
for line in lines :
|
||||
|
||||
# Figure out what type of line we're on, and remember what type
|
||||
# of line we saw last.
|
||||
last_line_type = line_type
|
||||
if blankline_pattern.match(line) :
|
||||
line_type = LineType.BLANK
|
||||
elif docline_pattern.match(line) :
|
||||
line_type = LineType.DOC
|
||||
else :
|
||||
line_type = LineType.NONDOC
|
||||
|
||||
# print ('<!-- LINE----- ', line_type, line, ' -->\n')
|
||||
|
||||
# Not a doc line, but we're in "continuation mode": append
|
||||
# (unindented) to the doc blob.
|
||||
if line_type != LineType.DOC and doc_cont_mode :
|
||||
doc_blob += line[indent:] + '\n'
|
||||
if DEBUG :
|
||||
alldocs[region_name] += '<!-- CONT ' + line[:35] + ' -->\n'
|
||||
continue
|
||||
|
||||
# Blank line, not in continuation mode
|
||||
if line_type == LineType.BLANK :
|
||||
if DEBUG and last_line_type != LineType.BLANK :
|
||||
alldocs[region_name] += '<!-- BLANK -->\n'
|
||||
|
||||
# FIXME: does this end a post-declaration API doc?
|
||||
if pre_api_mode : # this blank ends a pre-api comment
|
||||
continue # ...keep reading
|
||||
|
||||
# If this line ends a post-api comment, output the code blob
|
||||
if post_api_mode :
|
||||
if DEBUG :
|
||||
alldocs[region_name] += ' <!-- blank ended post-api -->\n'
|
||||
# Trim everything past the first ; or { from the code blob
|
||||
alllines = code_blob.split('\n')
|
||||
# code_blob = ''
|
||||
new_code_blob = ''
|
||||
for oneline in alllines :
|
||||
m = trimsemi_pattern.search (oneline)
|
||||
oneline = m.group(1)
|
||||
new_code_blob += oneline + '\n'
|
||||
new_code_blob = new_code_blob.rstrip(' \n\r')
|
||||
m = trimbrace_pattern.match(new_code_blob)
|
||||
alldocs[region_name] += ('~~~C\n' +
|
||||
shave_each_line(m.group(1),indent) +
|
||||
'\n~~~\n')
|
||||
post_api_mode = False
|
||||
|
||||
# If this line ends a doc blob, output it
|
||||
if len(doc_blob) :
|
||||
alldocs[region_name] += doc_blob + '\n'
|
||||
doc_blob = ''
|
||||
# Blank lines clear the code blob
|
||||
code_blob = ''
|
||||
continue
|
||||
|
||||
# Non-blank, non-doc line: append to code blob and move on.
|
||||
if line_type == LineType.NONDOC :
|
||||
if DEBUG :
|
||||
alldocs[region_name] += '<!-- NONDOC ' + line[:35] + ' -->\n'
|
||||
code_blob += line + '\n'
|
||||
continue
|
||||
|
||||
# Remaining cases are all doc lines!
|
||||
|
||||
# Any doc line resets the pre-doc-symbol indentation level
|
||||
m = docline_pattern.match(line)
|
||||
indent = len(m.group(1))
|
||||
|
||||
# Handle <doc> and <doc...> : start of new doc section
|
||||
m = doc_begin_pattern.match(line)
|
||||
if m :
|
||||
flush_doc_blob (doc_blob)
|
||||
doc_blob = ''
|
||||
# If it led with <doc...> it also starts continuation mode
|
||||
doc_cont_mode = (m.group(5) == '...')
|
||||
# The <doc> directive gave the region name.
|
||||
r = m.group(6)
|
||||
r.strip()
|
||||
if r == '' :
|
||||
r = '_'
|
||||
if DEBUG :
|
||||
alldocs[region_name] += '<!-- DOCBEGIN ' + r + ' -->\n'
|
||||
region_name = r
|
||||
if not (region_name in alldocs) :
|
||||
alldocs[region_name] = ''
|
||||
continue
|
||||
#
|
||||
# Handle </doc>
|
||||
m = docendpattern.match(line)
|
||||
if m :
|
||||
if DEBUG :
|
||||
alldocs[region_name] += '<!-- DOCEND ' + region_name + '-->\n'
|
||||
flush_doc_blob (doc_blob)
|
||||
doc_blob = ''
|
||||
doc_cont_mode = False
|
||||
region_name = '_'
|
||||
continue
|
||||
#
|
||||
# Handle start of post-declaration API comment
|
||||
m = api_postcomment_pattern.match(line)
|
||||
if m :
|
||||
if DEBUG :
|
||||
alldocs[region_name] += '<!-- start post-decl api ' + line[:35] + '-->\n'
|
||||
flush_doc_blob (doc_blob)
|
||||
doc_blob = ''
|
||||
# Deduce indentation level
|
||||
indent = len(m.group(1))
|
||||
post_api_mode = True
|
||||
remainder = m.group(7)
|
||||
doc_blob += remainder + '\n'
|
||||
continue
|
||||
#
|
||||
# Handle start of pre-declaration API comment
|
||||
m = api_precomment_pattern.match(line)
|
||||
if m :
|
||||
flush_doc_blob (doc_blob)
|
||||
doc_blob = ''
|
||||
indent = len(m.group(1))
|
||||
post_api_mode = True
|
||||
remainder = m.group(7)
|
||||
doc_blob += remainder + '\n'
|
||||
continue
|
||||
#
|
||||
# Handle code section <code> ... </code>
|
||||
m = code_pattern.match(line)
|
||||
if m :
|
||||
flush_doc_blob (doc_blob)
|
||||
doc_blob = ''
|
||||
if DEBUG :
|
||||
doc_blob += '<!-- start code in '+ region_name+ '-->\n'
|
||||
indent = len(m.group(1))
|
||||
doc_blob += '<script type="preformatted">\n~~~C\n'
|
||||
doc_cont_mode = True
|
||||
continue
|
||||
if codeend_pattern.match(line) :
|
||||
doc_cont_mode = False
|
||||
doc_blob += '~~~\n</script>\n'
|
||||
if DEBUG :
|
||||
doc_blob += '<!-- end code in '+ region_name+ '-->\n'
|
||||
flush_doc_blob (doc_blob)
|
||||
doc_blob = ''
|
||||
continue
|
||||
#
|
||||
# Last case: just a continuing doc line
|
||||
m = docline_pattern.match (line)
|
||||
if m :
|
||||
if DEBUG :
|
||||
alldocs[region_name] += '<!-- doc cont ' + line[:35] + ' -->\n'
|
||||
contents = m.group(6)
|
||||
doc_blob += contents + '\n'
|
||||
continue
|
||||
print ('<!-- REMAINING CASE:', line, '-->\n')
|
||||
flush_doc_blob (doc_blob)
|
||||
region_name = '_'
|
||||
|
||||
|
||||
def output_blob (blob) :
|
||||
for line in blob.splitlines() :
|
||||
m = inc_pattern.match (line)
|
||||
if m and (m.group(2) in alldocs) :
|
||||
# print ('Want to include', m.group(2))
|
||||
output_blob (alldocs[m.group(2)])
|
||||
else :
|
||||
print (line)
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser (prog='docdeep',
|
||||
description='Turn source comments into markdeep document')
|
||||
parser.add_argument ('-d', dest='docname', default='main',
|
||||
help='Name of documentation (default: "main")')
|
||||
parser.add_argument ('-s', dest='stylesheet', default='',
|
||||
help='Name of style sheet (default: "")')
|
||||
parser.add_argument ('--debug', dest='DEBUG', action='store_const',
|
||||
const=True, default=False)
|
||||
parser.add_argument ('filenames', nargs='+')
|
||||
# parser.add_argument ('-o', dest='output_filename', nargs=1,
|
||||
# help='Output filename (default: stdout)')
|
||||
args = parser.parse_args()
|
||||
DEBUG = args.DEBUG
|
||||
|
||||
for filename in args.filenames :
|
||||
with open(filename) as file:
|
||||
read_input (filename, file)
|
||||
|
||||
print ('<meta charset="utf-8">\n')
|
||||
if args.docname in alldocs :
|
||||
output_blob (alldocs[args.docname])
|
||||
else :
|
||||
print ("Ick! could not find docs for", args.docname)
|
||||
|
||||
print ('<!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="markdeep.min.js"></script><script src="https://casual-effects.com/markdeep/latest/markdeep.min.js?"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script>')
|
||||
if args.stylesheet :
|
||||
print ('<link rel="stylesheet" href="{}">'.format (args.stylesheet))
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
global: *OSL*; test_shade; *osl*imageio*; *osl_input_extensions;
|
||||
local: osl_*; *;
|
||||
local: osl_*; *pvt*; *;
|
||||
};
|
||||
|
||||
@@ -26,6 +26,7 @@ brew install ilmbase openexr
|
||||
brew install opencolorio partio
|
||||
brew install freetype libpng
|
||||
brew install llvm${LLVMBREWVER}
|
||||
brew install qt
|
||||
#brew install homebrew/science/hdf5 --with-threadsafe
|
||||
#brew install field3d webp ffmpeg openjpeg opencv
|
||||
echo ""
|
||||
|
||||
@@ -21,6 +21,7 @@ option (CLANG_TIDY "Enable clang-tidy" OFF)
|
||||
set (CLANG_TIDY_CHECKS "-*" CACHE STRING "clang-tidy checks to perform")
|
||||
set (CLANG_TIDY_ARGS "" CACHE STRING "clang-tidy args")
|
||||
option (CLANG_TIDY_FIX "Have clang-tidy fix source" OFF)
|
||||
set (GLIBCXX_USE_CXX11_ABI "" CACHE STRING "For gcc, use the new C++11 library ABI (0|1)")
|
||||
|
||||
|
||||
# Figure out which compiler we're using
|
||||
@@ -64,8 +65,11 @@ endif ()
|
||||
# turn on more detailed warnings and consider warnings as errors
|
||||
if (NOT MSVC)
|
||||
add_definitions ("-Wall")
|
||||
if (STOP_ON_WARNING)
|
||||
if (STOP_ON_WARNING OR DEFINED ENV{CI})
|
||||
add_definitions ("-Werror")
|
||||
# N.B. Force CI builds (Travis defines $CI) to use -Werror, even if
|
||||
# STOP_ON_WARNING has been switched off by default, which we may do
|
||||
# in release branches.
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
@@ -193,6 +197,18 @@ if (USE_LIBCPLUSPLUS AND CMAKE_COMPILER_IS_CLANG)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
endif ()
|
||||
|
||||
# GCC 5+: honor build-time option for whether or not to use new string ABI.
|
||||
# FIXME: In theory, this should also be needed for clang, if compiling with
|
||||
# the gcc libstdc++ toolchain. In practice, I could not get things to build
|
||||
# with clang properly when using this option, and I haven't yet seen a case
|
||||
# where it's needed. We can return to this and fix for clang if it becomes a
|
||||
# legit problem later.
|
||||
if (CMAKE_COMPILER_IS_GNUCC AND NOT ${GCC_VERSION} VERSION_LESS 5.0)
|
||||
if (NOT ${GLIBCXX_USE_CXX11_ABI} STREQUAL "")
|
||||
add_definitions ("-D_GLIBCXX_USE_CXX11_ABI=${GLIBCXX_USE_CXX11_ABI}")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
|
||||
# SIMD and machine architecture options
|
||||
set (SIMD_COMPILE_FLAGS "")
|
||||
@@ -340,8 +356,4 @@ endif ()
|
||||
|
||||
if (DEFINED ENV{TRAVIS} OR DEFINED ENV{APPVEYOR} OR DEFINED ENV{CI})
|
||||
add_definitions ("-D${PROJECT_NAME}_CI=1" "-DBUILD_CI=1")
|
||||
if (WIN32)
|
||||
set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
|
||||
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
@@ -15,8 +15,11 @@ if (NOT VERBOSE)
|
||||
set (PugiXML_FIND_QUIETLY TRUE)
|
||||
set (PythonInterp_FIND_QUIETLY true)
|
||||
set (PythonLibs_FIND_QUIETLY true)
|
||||
set (Qt5_FIND_QUIETLY true)
|
||||
set (Threads_FIND_QUIETLY true)
|
||||
set (ZLIB_FIND_QUIETLY true)
|
||||
set (CUDA_FIND_QUIETLY true)
|
||||
set (OptiX_FIND_QUIETLY true)
|
||||
endif ()
|
||||
|
||||
|
||||
@@ -52,7 +55,7 @@ endif ()
|
||||
###########################################################################
|
||||
# OpenImageIO
|
||||
|
||||
find_package (OpenImageIO 1.7 REQUIRED)
|
||||
find_package (OpenImageIO 1.8.5 REQUIRED)
|
||||
include_directories ("${OPENIMAGEIO_INCLUDE_DIR}")
|
||||
link_directories ("${OPENIMAGEIO_LIBRARY_DIRS}")
|
||||
message (STATUS "Using OpenImageIO ${OPENIMAGEIO_VERSION}")
|
||||
@@ -64,7 +67,7 @@ message (STATUS "Using OpenImageIO ${OPENIMAGEIO_VERSION}")
|
||||
###########################################################################
|
||||
# LLVM library setup
|
||||
|
||||
find_package (LLVM 3.5 REQUIRED)
|
||||
find_package (LLVM 4.0 REQUIRED)
|
||||
|
||||
# ensure include directory is added (in case of non-standard locations
|
||||
include_directories (BEFORE SYSTEM "${LLVM_INCLUDES}")
|
||||
@@ -89,10 +92,6 @@ if (NOT Boost_FIND_QUIETLY)
|
||||
message (STATUS "BOOST_ROOT ${BOOST_ROOT}")
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED Boost_ADDITIONAL_VERSIONS)
|
||||
set (Boost_ADDITIONAL_VERSIONS "1.63" "1.62" "1.61" "1.60"
|
||||
"1.59" "1.58" "1.57" "1.56" "1.55")
|
||||
endif ()
|
||||
if (LINKSTATIC)
|
||||
set (Boost_USE_STATIC_LIBS ON)
|
||||
endif ()
|
||||
@@ -101,8 +100,7 @@ set (Boost_COMPONENTS system thread)
|
||||
if (NOT USE_STD_REGEX)
|
||||
list (APPEND Boost_COMPONENTS regex)
|
||||
endif ()
|
||||
if (CMAKE_COMPILER_IS_CLANG OR CMAKE_COMPILER_IS_APPLECLANG OR
|
||||
${LLVM_VERSION} VERSION_LESS 3.6)
|
||||
if (CMAKE_COMPILER_IS_CLANG OR CMAKE_COMPILER_IS_APPLECLANG)
|
||||
set (_CLANG_PREPROCESSOR_CAN_WORK ON)
|
||||
endif ()
|
||||
if (GCC_VERSION)
|
||||
@@ -110,17 +108,6 @@ if (GCC_VERSION)
|
||||
set (_CLANG_PREPROCESSOR_CAN_WORK ON)
|
||||
endif ()
|
||||
endif ()
|
||||
if (${LLVM_VERSION} VERSION_LESS 3.9)
|
||||
# Bug in old LLVM creates some linkage problems we've seen involving
|
||||
# some singleton globals that are duplicated when we include both
|
||||
# the clang libs we need for the preprocessing as well as certain
|
||||
# LLVM support libraries we also need, triggering assertions.
|
||||
# See this for description of the issue:
|
||||
# http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20140203/203968.html
|
||||
# Sweep under the rug by falling back to boost wave when using older
|
||||
# LLVM (it seems fixed and no longer triggers for 3.9+).
|
||||
set (_CLANG_PREPROCESSOR_CAN_WORK OFF)
|
||||
endif ()
|
||||
if (USE_BOOST_WAVE OR (NOT CLANG_LIBRARIES)
|
||||
OR (NOT _CLANG_PREPROCESSOR_CAN_WORK))
|
||||
# N.B. Using clang for preprocessing seems to work when using clang,
|
||||
@@ -186,15 +173,89 @@ endif (USE_PARTIO)
|
||||
|
||||
|
||||
###########################################################################
|
||||
# Pugixml setup. Normally we just use the version bundled with oiio, but
|
||||
# some linux distros are quite particular about having separate packages so we
|
||||
# allow this to be overridden to use the distro-provided package if desired.
|
||||
if (USE_EXTERNAL_PUGIXML)
|
||||
find_package (PugiXML REQUIRED)
|
||||
# insert include path to pugixml first, to ensure that the external
|
||||
# pugixml is found, and not the one in OIIO's include directory.
|
||||
include_directories (BEFORE "${PUGIXML_INCLUDE_DIR}")
|
||||
add_definitions ("-DUSE_EXTERNAL_PUGIXML")
|
||||
endif()
|
||||
# Pugixml setup. Prefer a system install, but note that FindPugiXML.cmake
|
||||
# will look in the OIIO distribution if it's not found on the system.
|
||||
find_package (PugiXML REQUIRED)
|
||||
include_directories (BEFORE "${PUGIXML_INCLUDE_DIR}")
|
||||
# end Pugixml setup
|
||||
###########################################################################
|
||||
|
||||
|
||||
###########################################################################
|
||||
# Qt setup
|
||||
|
||||
if (USE_QT)
|
||||
set (qt5_modules Core Gui Widgets)
|
||||
# if (USE_OPENGL)
|
||||
# list (APPEND qt5_modules OpenGL)
|
||||
# endif ()
|
||||
find_package (Qt5 COMPONENTS ${qt5_modules})
|
||||
endif ()
|
||||
if (USE_QT AND Qt5_FOUND)
|
||||
if (NOT Qt5_FIND_QUIETLY)
|
||||
message (STATUS "Qt5_FOUND=${Qt5_FOUND}")
|
||||
endif ()
|
||||
else ()
|
||||
message (STATUS "No Qt5 -- skipping components that need Qt5.")
|
||||
if (USE_QT AND NOT Qt5_FOUND AND APPLE)
|
||||
message (STATUS "If you think you installed qt5 with Homebrew and it still doesn't work,")
|
||||
message (STATUS "try: export PATH=/usr/local/opt/qt5/bin:$PATH")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# end Qt setup
|
||||
###########################################################################
|
||||
|
||||
###########################################################################
|
||||
# CUDA setup
|
||||
|
||||
if (USE_CUDA OR USE_OPTIX)
|
||||
if (NOT CUDA_TOOLKIT_ROOT_DIR AND NOT $ENV{CUDA_TOOLKIT_ROOT_DIR} STREQUAL "")
|
||||
set (CUDA_TOOLKIT_ROOT_DIR $ENV{CUDA_TOOLKIT_ROOT_DIR})
|
||||
endif ()
|
||||
|
||||
if (NOT CUDA_FIND_QUIETLY OR NOT OptiX_FIND_QUIETLY)
|
||||
message (STATUS "CUDA_TOOLKIT_ROOT_DIR = ${CUDA_TOOLKIT_ROOT_DIR}")
|
||||
endif ()
|
||||
|
||||
find_package (CUDA 8.0 REQUIRED)
|
||||
set (CUDA_INCLUDE_DIR ${CUDA_TOOLKIT_ROOT_DIR}/include)
|
||||
include_directories (BEFORE "${CUDA_INCLUDE_DIR}")
|
||||
|
||||
message (STATUS "CUDA version = ${CUDA_VERSION}")
|
||||
|
||||
if (NOT CUDA_FIND_QUIETLY OR NOT OptiX_FIND_QUIETLY)
|
||||
message (STATUS "CUDA includes = ${CUDA_INCLUDE_DIR}")
|
||||
message (STATUS "CUDA libraries = ${CUDA_LIBRARIES}")
|
||||
endif ()
|
||||
|
||||
STRING (FIND ${LLVM_TARGETS} "NVPTX" nvptx_index)
|
||||
if (NOT ${nvptx_index} GREATER -1)
|
||||
message (FATAL_ERROR "NVTPX target is not available in the provided LLVM build")
|
||||
endif()
|
||||
|
||||
if (${CUDA_VERSION_MAJOR} GREATER 8 AND ${LLVM_VERSION} LESS 6)
|
||||
message (FATAL_ERROR "CUDA ${CUDA_VERSION} requires LLVM 6.0 or greater")
|
||||
endif ()
|
||||
|
||||
set (CUDA_LIB_FLAGS "--cuda-path=${CUDA_TOOLKIT_ROOT_DIR}")
|
||||
endif ()
|
||||
|
||||
# end CUDA setup
|
||||
###########################################################################
|
||||
|
||||
###########################################################################
|
||||
# OptiX setup
|
||||
|
||||
if (USE_OPTIX)
|
||||
find_package (OptiX 5.1 REQUIRED)
|
||||
include_directories (BEFORE "${OPTIX_INCLUDE_DIR}")
|
||||
|
||||
if (NOT USE_LLVM_BITCODE OR NOT USE_FAST_MATH)
|
||||
message (FATAL_ERROR "Enabling OptiX requires USE_LLVM_BITCODE=1 and USE_FAST_MATH=1")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# end OptiX setup
|
||||
###########################################################################
|
||||
|
||||
|
||||
+31
-56
@@ -1,8 +1,7 @@
|
||||
# LG's macros for using flex and bison.
|
||||
# Merely including this file will set FLEX_EXECUTABLE and BISON_EXECUTABLE
|
||||
# to the locations of 'flex' and 'bison' on the system, and leave them
|
||||
# undefined if those programs were not found.
|
||||
# If both are found, there will also be a macro defined:
|
||||
# Merely including this file will require flex and bison to be found.
|
||||
#
|
||||
# The main purpose is to define the macro FLEX_BISON:
|
||||
# FLEX_BISON ( flexsrc bisonsrc srclist compiler_headers )
|
||||
# where
|
||||
# flexsrc = the name of the .l file
|
||||
@@ -14,72 +13,48 @@
|
||||
# for the .y and .l files.
|
||||
|
||||
|
||||
IF (NOT FLEX_EXECUTABLE)
|
||||
if (NOT Flex_FIND_QUIETLY)
|
||||
MESSAGE (STATUS "Looking for flex")
|
||||
endif ()
|
||||
FIND_PROGRAM (FLEX_EXECUTABLE flex)
|
||||
IF (FLEX_EXECUTABLE)
|
||||
if (NOT Flex_FIND_QUIETLY)
|
||||
MESSAGE (STATUS "Looking for flex -- ${FLEX_EXECUTABLE}")
|
||||
endif ()
|
||||
ENDIF (FLEX_EXECUTABLE)
|
||||
ENDIF (NOT FLEX_EXECUTABLE)
|
||||
find_package (BISON REQUIRED)
|
||||
find_package (FLEX REQUIRED)
|
||||
|
||||
IF (NOT BISON_EXECUTABLE)
|
||||
if (NOT Bison_FIND_QUIETLY)
|
||||
MESSAGE (STATUS "Looking for bison")
|
||||
endif ()
|
||||
FIND_PROGRAM (BISON_EXECUTABLE bison)
|
||||
IF (BISON_EXECUTABLE)
|
||||
if (NOT Bison_FIND_QUIETLY)
|
||||
MESSAGE (STATUS "Looking for bison -- ${BISON_EXECUTABLE}")
|
||||
endif ()
|
||||
ENDIF (BISON_EXECUTABLE)
|
||||
ENDIF (NOT BISON_EXECUTABLE)
|
||||
|
||||
|
||||
IF ( FLEX_EXECUTABLE AND BISON_EXECUTABLE )
|
||||
MACRO ( FLEX_BISON flexsrc bisonsrc prefix srclist compiler_headers )
|
||||
if ( FLEX_EXECUTABLE AND BISON_EXECUTABLE )
|
||||
macro ( FLEX_BISON flexsrc bisonsrc prefix srclist compiler_headers )
|
||||
if (VERBOSE)
|
||||
MESSAGE (STATUS "FLEX_BISON flex=${flexsrc} bison=${bisonsrc} prefix=${prefix}")
|
||||
message (STATUS "FLEX_BISON flex=${flexsrc} bison=${bisonsrc} prefix=${prefix}")
|
||||
endif ()
|
||||
#MESSAGE (STATUS " src ${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
#MESSAGE (STATUS " bin ${CMAKE_CURRENT_BINARY_DIR}")
|
||||
GET_FILENAME_COMPONENT ( bisonsrc_we ${bisonsrc} NAME_WE )
|
||||
SET ( bisonoutputcxx "${CMAKE_CURRENT_BINARY_DIR}/${bisonsrc_we}.cpp" )
|
||||
SET ( bisonoutputh "${CMAKE_CURRENT_BINARY_DIR}/${bisonsrc_we}.h" )
|
||||
# MESSAGE (STATUS " bison output ${bisonoutputcxx} ${bisonoutputh}")
|
||||
get_filename_component ( bisonsrc_we ${bisonsrc} NAME_WE )
|
||||
set ( bisonoutputcxx "${CMAKE_CURRENT_BINARY_DIR}/${bisonsrc_we}.cpp" )
|
||||
set ( bisonoutputh "${CMAKE_CURRENT_BINARY_DIR}/${bisonsrc_we}.h" )
|
||||
|
||||
GET_FILENAME_COMPONENT ( flexsrc_we ${flexsrc} NAME_WE )
|
||||
SET ( flexoutputcxx "${CMAKE_CURRENT_BINARY_DIR}/${flexsrc_we}.cpp" )
|
||||
# MESSAGE (STATUS " flex output ${flexoutputcxx}")
|
||||
|
||||
SET ( ${srclist} ${${srclist}} ${bisonoutputcxx} ${flexoutputcxx} )
|
||||
# MESSAGE (STATUS " src list now ${${srclist}}")
|
||||
# MESSAGE (STATUS " compiler headers = ${${compiler_headers}}")
|
||||
get_filename_component ( flexsrc_we ${flexsrc} NAME_WE )
|
||||
set ( flexoutputcxx "${CMAKE_CURRENT_BINARY_DIR}/${flexsrc_we}.cpp" )
|
||||
set ( ${srclist} ${${srclist}} ${bisonoutputcxx} ${flexoutputcxx} )
|
||||
|
||||
# Be really sure that we prefer the FlexLexer.h that comes with
|
||||
# the flex binary we're using, not some other one in the system.
|
||||
GET_FILENAME_COMPONENT ( FLEX_UP ${FLEX_EXECUTABLE} PATH )
|
||||
GET_FILENAME_COMPONENT ( FLEX_UP_UP ${FLEX_UP} PATH )
|
||||
SET ( FLEX_INCLUDE_DIR "${FLEX_UP_UP}/include" )
|
||||
get_filename_component ( FLEX_UP ${FLEX_EXECUTABLE} PATH )
|
||||
get_filename_component ( FLEX_UP_UP ${FLEX_UP} PATH )
|
||||
set ( FLEX_INCLUDE_DIR "${FLEX_UP_UP}/include" )
|
||||
if (VERBOSE)
|
||||
MESSAGE (STATUS "Flex include dir = ${FLEX_INCLUDE_DIR}")
|
||||
message (STATUS "Flex include dir = ${FLEX_INCLUDE_DIR}")
|
||||
endif ()
|
||||
INCLUDE_DIRECTORIES ( ${FLEX_INCLUDE_DIR} )
|
||||
include_directories ( ${FLEX_INCLUDE_DIR} )
|
||||
|
||||
INCLUDE_DIRECTORIES ( ${CMAKE_CURRENT_BINARY_DIR} )
|
||||
INCLUDE_DIRECTORIES ( ${CMAKE_CURRENT_SOURCE_DIR} )
|
||||
ADD_CUSTOM_COMMAND ( OUTPUT ${bisonoutputcxx}
|
||||
# include_directories ( ${CMAKE_CURRENT_BINARY_DIR} )
|
||||
include_directories ( ${CMAKE_CURRENT_SOURCE_DIR} )
|
||||
add_custom_command ( OUTPUT ${bisonoutputcxx}
|
||||
COMMAND ${BISON_EXECUTABLE} -dv -p ${prefix} -o ${bisonoutputcxx} "${CMAKE_CURRENT_SOURCE_DIR}/${bisonsrc}"
|
||||
MAIN_DEPENDENCY ${bisonsrc}
|
||||
DEPENDS ${${compiler_headers}}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
|
||||
ADD_CUSTOM_COMMAND ( OUTPUT ${flexoutputcxx}
|
||||
COMMAND ${FLEX_EXECUTABLE} -o ${flexoutputcxx} "${CMAKE_CURRENT_SOURCE_DIR}/${flexsrc}"
|
||||
if ( WINDOWS )
|
||||
set ( FB_WINCOMPAT --wincompat )
|
||||
else ()
|
||||
set ( FB_WINCOMPAT )
|
||||
endif ()
|
||||
add_custom_command ( OUTPUT ${flexoutputcxx}
|
||||
COMMAND ${FLEX_EXECUTABLE} ${FB_WINCOMPAT} -o ${flexoutputcxx} "${CMAKE_CURRENT_SOURCE_DIR}/${flexsrc}"
|
||||
MAIN_DEPENDENCY ${flexsrc}
|
||||
DEPENDS ${${compiler_headers}}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
|
||||
ENDMACRO ()
|
||||
ENDIF ()
|
||||
endmacro ()
|
||||
endif ()
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
# LLVM_SYSTEM_LIBRARIES - additional libraries needed by LLVM
|
||||
# LLVM_DIRECTORY - If not already set, the root of the LLVM install
|
||||
# LLVM_LIB_DIR - where to find llvm libs
|
||||
# LLVM_TARGETS - List of available LLVM targets
|
||||
# CLANG_LIBRARIES - list of libraries for clang components (optional,
|
||||
# those may not be found)
|
||||
#
|
||||
@@ -48,18 +49,13 @@ execute_process (COMMAND ${LLVM_CONFIG} --libdir
|
||||
execute_process (COMMAND ${LLVM_CONFIG} --includedir
|
||||
OUTPUT_VARIABLE LLVM_INCLUDES
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if (NOT ${LLVM_VERSION} VERSION_LESS 3.8)
|
||||
execute_process (COMMAND ${LLVM_CONFIG} --system-libs
|
||||
OUTPUT_VARIABLE LLVM_SYSTEM_LIBRARIES
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
else ()
|
||||
# Older LLVM did not have llvm-config --system-libs, but we know that
|
||||
# on Linux, we'll need curses.
|
||||
find_package (Curses)
|
||||
if (CURSES_FOUND)
|
||||
list (APPEND LLVM_SYSTEM_LIBRARIES ${CURSES_LIBRARIES})
|
||||
endif ()
|
||||
endif ()
|
||||
execute_process (COMMAND ${LLVM_CONFIG} --targets-built
|
||||
OUTPUT_VARIABLE LLVM_TARGETS
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
execute_process (COMMAND ${LLVM_CONFIG} --system-libs
|
||||
OUTPUT_VARIABLE LLVM_SYSTEM_LIBRARIES
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
string (REPLACE " " ";" LLVM_SYSTEM_LIBRARIES "${LLVM_SYSTEM_LIBRARIES}")
|
||||
|
||||
find_library ( LLVM_LIBRARY
|
||||
NAMES LLVM-${LLVM_VERSION} LLVM
|
||||
@@ -68,7 +64,6 @@ find_library ( LLVM_MCJIT_LIBRARY
|
||||
NAMES LLVMMCJIT
|
||||
PATHS ${LLVM_LIB_DIR})
|
||||
|
||||
|
||||
foreach (COMPONENT clangFrontend clangDriver clangSerialization
|
||||
clangParse clangSema clangAnalysis clangAST clangBasic
|
||||
clangEdit clangLex)
|
||||
@@ -81,12 +76,6 @@ foreach (COMPONENT clangFrontend clangDriver clangSerialization
|
||||
endforeach ()
|
||||
|
||||
|
||||
# if (NOT LLVM_LIBRARY)
|
||||
# execute_process (COMMAND ${LLVM_CONFIG} --libfiles engine
|
||||
# OUTPUT_VARIABLE LLVM_LIBRARIES
|
||||
# OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
# endif ()
|
||||
|
||||
# shared llvm library may not be available, this is not an error if we use LLVM_STATIC.
|
||||
if ((LLVM_LIBRARY OR LLVM_LIBRARIES OR LLVM_STATIC) AND LLVM_INCLUDES AND LLVM_DIRECTORY AND LLVM_LIB_DIR)
|
||||
if (LLVM_STATIC)
|
||||
|
||||
@@ -8,14 +8,9 @@
|
||||
# OPENEXR_VERSION OpenEXR version (accurate for >= 2.0.0,
|
||||
# otherwise will just guess 1.6.1)
|
||||
#
|
||||
# Special inputs:
|
||||
# OPENEXR_CUSTOM_INCLUDE_DIR - custom location of headers
|
||||
# OPENEXR_CUSTOM_LIB_DIR - custom location of libraries
|
||||
# OPENEXR_CUSTOM_LIB_PREFIX - special snowflake library prefix
|
||||
# OPENEXR_CUSTOM_LIB_SUFFIX - special snowflake library suffix
|
||||
#
|
||||
|
||||
# Other standarnd issue macros
|
||||
# Other standard issue macros
|
||||
include (FindPackageHandleStandardArgs)
|
||||
include (SelectLibraryConfigurations)
|
||||
|
||||
@@ -27,17 +22,31 @@ if (CMAKE_USE_PTHREADS_INIT)
|
||||
set (ILMBASE_PTHREADS ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif ()
|
||||
|
||||
# Attempt to find OpenEXR with pkgconfig
|
||||
find_package(PkgConfig)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
if (NOT ILMBASE_ROOT_DIR)
|
||||
pkg_check_modules(_ILMBASE QUIET IlmBase>=2.0.0)
|
||||
endif ()
|
||||
if (NOT OPENEXR_ROOT_DIR)
|
||||
pkg_check_modules(_OPENEXR QUIET OpenEXR>=2.0.0)
|
||||
endif ()
|
||||
endif (PKG_CONFIG_FOUND)
|
||||
|
||||
# List of likely places to find the headers -- note priority override of
|
||||
# OPENEXR_CUSTOM_INCLUDE_DIR and ${OPENEXR_HOME}/include.
|
||||
# ${OPENEXR_ROOT_DIR}/include.
|
||||
# ILMBASE is needed in case ilmbase an openexr are installed in separate
|
||||
# directories, like NixOS does
|
||||
set (GENERIC_INCLUDE_PATHS
|
||||
${OPENEXR_CUSTOM_INCLUDE_DIR}
|
||||
${OPENEXR_HOME}/include
|
||||
${ILMBASE_HOME}/include
|
||||
${OPENEXR_ROOT_DIR}/include
|
||||
$ENV{OPENEXR_ROOT_DIR}/include
|
||||
${ILMBASE_ROOT_DIR}/include
|
||||
$ENV{ILMBASE_ROOT_DIR}/include
|
||||
${_ILMBASE_INCLUDEDIR}
|
||||
${_OPENEXR_INCLUDEDIR}
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
/usr/include/${CMAKE_LIBRARY_ARCHITECTURE}
|
||||
/usr/local/include
|
||||
/sw/include
|
||||
/opt/local/include )
|
||||
|
||||
@@ -46,14 +55,20 @@ set (GENERIC_INCLUDE_PATHS
|
||||
# This seems to be the most robust way I can find to not get confused when
|
||||
# both system and custom libraries are present.
|
||||
find_path (ILMBASE_INCLUDE_PATH OpenEXR/IlmBaseConfig.h
|
||||
PATHS ${GENERIC_INCLUDE_PATHS} NO_DEFAULT_PATH)
|
||||
PATHS ${ILMBASE_INCLUDE_DIR} ${OPENEXR_INCLUDE_DIR}
|
||||
${GENERIC_INCLUDE_PATHS} NO_DEFAULT_PATH)
|
||||
find_path (ILMBASE_INCLUDE_PATH OpenEXR/IlmBaseConfig.h)
|
||||
find_path (OPENEXR_INCLUDE_PATH OpenEXR/OpenEXRConfig.h
|
||||
PATHS ${GENERIC_INCLUDE_PATHS} NO_DEFAULT_PATH)
|
||||
PATHS ${OPENEXR_INCLUDE_DIR}
|
||||
${GENERIC_INCLUDE_PATHS} NO_DEFAULT_PATH)
|
||||
find_path (OPENEXR_INCLUDE_PATH OpenEXR/OpenEXRConfig.h)
|
||||
|
||||
# Try to figure out version number
|
||||
if (EXISTS "${OPENEXR_INCLUDE_PATH}/OpenEXR/ImfMultiPartInputFile.h")
|
||||
if (DEFINED _OPENEXR_VERSION AND NOT "${_OPENEXR_VERSION}" STREQUAL "")
|
||||
set (OPENEXR_VERSION "${_OPENEXR_VERSION}")
|
||||
string (REGEX REPLACE "([0-9]+)\\.[0-9\\.]+" "\\1" OPENEXR_VERSION_MAJOR "${_OPENEXR_VERSION}")
|
||||
string (REGEX REPLACE "[0-9]+\\.([0-9]+)(\\.[0-9]+)?" "\\1" OPENEXR_VERSION_MINOR "${_OPENEXR_VERSION}")
|
||||
elseif (EXISTS "${OPENEXR_INCLUDE_PATH}/OpenEXR/ImfMultiPartInputFile.h")
|
||||
# Must be at least 2.0
|
||||
file(STRINGS "${OPENEXR_INCLUDE_PATH}/OpenEXR/OpenEXRConfig.h" TMP REGEX "^#define OPENEXR_VERSION_STRING .*$")
|
||||
string (REGEX MATCHALL "[0-9]+[.0-9]+" OPENEXR_VERSION ${TMP})
|
||||
@@ -70,21 +85,24 @@ endif ()
|
||||
|
||||
|
||||
# List of likely places to find the libraries -- note priority override of
|
||||
# OPENEXR_CUSTOM_LIB_DIR and ${OPENEXR_HOME}/lib.
|
||||
set (GENERIC_LIBRARY_PATHS
|
||||
${OPENEXR_CUSTOM_LIB_DIR}
|
||||
${OPENEXR_HOME}/lib
|
||||
${ILMBASE_HOME}/lib
|
||||
# ${OPENEXR_ROOT_DIR}/lib.
|
||||
set (GENERIC_LIBRARY_PATHS
|
||||
${OPENEXR_ROOT_DIR}/lib
|
||||
${ILMBASE_ROOT_DIR}/lib
|
||||
${OPENEXR_INCLUDE_PATH}/../lib
|
||||
${ILMBASE_INCLUDE_PATH}/../lib
|
||||
/usr/lib
|
||||
/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}
|
||||
${_ILMBASE_LIBDIR}
|
||||
${_OPENEXR_LIBDIR}
|
||||
/usr/local/lib
|
||||
/usr/local/lib/${CMAKE_LIBRARY_ARCHITECTURE}
|
||||
/usr/lib
|
||||
/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}
|
||||
/sw/lib
|
||||
/opt/local/lib
|
||||
$ENV{PROGRAM_FILES}/OpenEXR/lib/static )
|
||||
|
||||
# message (STATUS "Generic lib paths: ${GENERIC_LIBRARY_PATHS}")
|
||||
|
||||
# Handle request for static libs by altering CMAKE_FIND_LIBRARY_SUFFIXES.
|
||||
# We will restore it at the end of this file.
|
||||
set (_openexr_orig_suffixes ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
@@ -104,24 +122,21 @@ set (_openexr_components IlmThread IlmImf Imath Iex Half)
|
||||
foreach (COMPONENT ${_openexr_components})
|
||||
string (TOUPPER ${COMPONENT} UPPERCOMPONENT)
|
||||
# First try with the version embedded
|
||||
set (FULL_COMPONENT_NAME ${OPENEXR_CUSTOM_LIB_PREFIX}${COMPONENT}-${OPENEXR_VERSION_MAJOR}_${OPENEXR_VERSION_MINOR}${OPENEXR_CUSTOM_LIB_SUFFIX})
|
||||
set (FULL_COMPONENT_NAME ${COMPONENT}-${OPENEXR_VERSION_MAJOR}_${OPENEXR_VERSION_MINOR})
|
||||
find_library (OPENEXR_${UPPERCOMPONENT}_LIBRARY ${FULL_COMPONENT_NAME}
|
||||
PATHS ${GENERIC_LIBRARY_PATHS} NO_DEFAULT_PATH)
|
||||
PATHS ${OPENEXR_LIBRARY_DIR} $ENV{OPENEXR_LIBRARY_DIR}
|
||||
${GENERIC_LIBRARY_PATHS} NO_DEFAULT_PATH)
|
||||
# Again, with no directory restrictions
|
||||
find_library (OPENEXR_${UPPERCOMPONENT}_LIBRARY ${FULL_COMPONENT_NAME})
|
||||
# Try again without the version
|
||||
set (FULL_COMPONENT_NAME ${OPENEXR_CUSTOM_LIB_PREFIX}${COMPONENT}${OPENEXR_CUSTOM_LIB_SUFFIX})
|
||||
set (FULL_COMPONENT_NAME ${COMPONENT})
|
||||
find_library (OPENEXR_${UPPERCOMPONENT}_LIBRARY ${FULL_COMPONENT_NAME}
|
||||
PATHS ${GENERIC_LIBRARY_PATHS} NO_DEFAULT_PATH)
|
||||
PATHS ${OPENEXR_LIBRARY_DIR} $ENV{OPENEXR_LIBRARY_DIR}
|
||||
${GENERIC_LIBRARY_PATHS} NO_DEFAULT_PATH)
|
||||
# One more time, with no restrictions
|
||||
find_library (OPENEXR_${UPPERCOMPONENT}_LIBRARY ${FULL_COMPONENT_NAME})
|
||||
endforeach ()
|
||||
|
||||
#Half usually has no suffix
|
||||
find_library (OPENEXR_HALF_LIBRARY ${OPENEXR_CUSTOM_LIB_PREFIX}Half
|
||||
PATHS ${GENERIC_LIBRARY_PATHS} NO_DEFAULT_PATH)
|
||||
find_library (OPENEXR_HALF_LIBRARY ${OPENEXR_CUSTOM_LIB_PREFIX}Half)
|
||||
|
||||
# Set the FOUND, INCLUDE_DIR, and LIBRARIES variables.
|
||||
if (ILMBASE_INCLUDE_PATH AND OPENEXR_INCLUDE_PATH AND
|
||||
OPENEXR_IMATH_LIBRARY AND OPENEXR_ILMIMF_LIBRARY AND
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
###########################################################################
|
||||
# OpenImageIO https://www.openimageio.org
|
||||
# Copyright 2008-2018 Larry Gritz et al. All rights reserved.
|
||||
# BSD 3-clause license:
|
||||
# https://github.com/OpenImageIO/oiio/blob/master/LICENSE
|
||||
# For an up-to-date version of this file, see:
|
||||
# https://github.com/OpenImageIO/oiio/blob/master/src/cmake/Modules/FindOpenImageIO.cmake
|
||||
#
|
||||
###########################################################################
|
||||
#
|
||||
# CMake module to find OpenImageIO
|
||||
#
|
||||
# This module will set
|
||||
@@ -10,35 +19,38 @@
|
||||
# OPENIMAGEIO_VERSION_MAJOR Version major number
|
||||
# OPENIMAGEIO_VERSION_MINOR Version minor number
|
||||
# OPENIMAGEIO_VERSION_PATCH Version minor patch
|
||||
# OIIOTOOL_BIN Path to oiiotool executable
|
||||
#
|
||||
# Special inputs:
|
||||
# OPENIMAGEIOHOME - custom "prefix" location of OIIO installation
|
||||
# (expecting bin, lib, include subdirectories)
|
||||
# OPENIMAGEIO_ROOT_DIR - custom "prefix" location of OIIO installation
|
||||
# (expecting bin, lib, include subdirectories)
|
||||
# OpenImageIO_FIND_QUIETLY - if set, print minimal console output
|
||||
#
|
||||
###########################################################################
|
||||
|
||||
|
||||
# If 'OPENIMAGEHOME' not set, use the env variable of that name if available
|
||||
if (NOT OPENIMAGEIOHOME AND NOT $ENV{OPENIMAGEIOHOME} STREQUAL "")
|
||||
set (OPENIMAGEIOHOME $ENV{OPENIMAGEIOHOME})
|
||||
# If 'OPENIMAGE_HOME' not set, use the env variable of that name if available
|
||||
if (NOT OPENIMAGEIO_ROOT_DIR AND NOT $ENV{OPENIMAGEIO_ROOT_DIR} STREQUAL "")
|
||||
set (OPENIMAGEIO_ROOT_DIR $ENV{OPENIMAGEIO_ROOT_DIR})
|
||||
endif ()
|
||||
|
||||
|
||||
if (NOT OpenImageIO_FIND_QUIETLY)
|
||||
message ( STATUS "OPENIMAGEIOHOME = ${OPENIMAGEIOHOME}" )
|
||||
message ( STATUS "OPENIMAGEIO_ROOT_DIR = ${OPENIMAGEIO_ROOT_DIR}" )
|
||||
endif ()
|
||||
|
||||
find_library ( OPENIMAGEIO_LIBRARY
|
||||
NAMES OpenImageIO
|
||||
HINTS ${OPENIMAGEIOHOME}/lib
|
||||
HINTS ${OPENIMAGEIO_ROOT_DIR}/lib
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS "${OPENIMAGEIOHOME}/lib" )
|
||||
PATHS "${OPENIMAGEIO_ROOT_DIR}/lib" )
|
||||
find_path ( OPENIMAGEIO_INCLUDE_DIR
|
||||
NAMES OpenImageIO/imageio.h
|
||||
HINTS ${OPENIMAGEIOHOME}/include
|
||||
HINTS ${OPENIMAGEIO_ROOT_DIR}/include
|
||||
PATH_SUFFIXES include )
|
||||
find_program ( OPENIMAGEIO_BIN
|
||||
NAMES oiiotool
|
||||
HINTS ${OPENIMAGEIOHOME}/bin
|
||||
find_program ( OIIOTOOL_BIN
|
||||
NAMES oiiotool oiiotool.exe
|
||||
HINTS ${OPENIMAGEIO_ROOT_DIR}/bin
|
||||
PATH_SUFFIXES bin )
|
||||
|
||||
# Try to figure out version number
|
||||
@@ -60,7 +72,7 @@ if (NOT OpenImageIO_FIND_QUIETLY)
|
||||
message ( STATUS "OpenImageIO includes = ${OPENIMAGEIO_INCLUDE_DIR}" )
|
||||
message ( STATUS "OpenImageIO libraries = ${OPENIMAGEIO_LIBRARIES}" )
|
||||
message ( STATUS "OpenImageIO library_dirs = ${OPENIMAGEIO_LIBRARY_DIRS}" )
|
||||
message ( STATUS "OpenImageIO bin = ${OPENIMAGEIO_BIN}" )
|
||||
message ( STATUS "OpenImageIO oiiiotool = ${OIIOTOOL_BIN}" )
|
||||
endif ()
|
||||
|
||||
include (FindPackageHandleStandardArgs)
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
###########################################################################
|
||||
# CMake module to find OptiX
|
||||
#
|
||||
# This module will set
|
||||
# OPTIX_FOUND True, if OptiX is found
|
||||
# OPTIX_INCLUDE_DIR directory where OptiX headers are found
|
||||
# OPTIX_LIBRARIES libraries for OptiX
|
||||
#
|
||||
# Special inputs:
|
||||
# OPTIXHOME - custom "prefix" location of OptiX installation
|
||||
# (expecting bin, lib, include subdirectories)
|
||||
|
||||
|
||||
# If 'OPTIXHOME' not set, use the env variable of that name if available
|
||||
if (NOT OPTIXHOME)
|
||||
if (NOT $ENV{OPTIXHOME} STREQUAL "")
|
||||
set (OPTIXHOME $ENV{OPTIXHOME})
|
||||
elseif (NOT $ENV{OPTIX_INSTALL_DIR} STREQUAL "")
|
||||
set (OPTIXHOME $ENV{OPTIX_INSTALL_DIR})
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (NOT OptiX_FIND_QUIETLY)
|
||||
message (STATUS "OPTIXHOME = ${OPTIXHOME}")
|
||||
endif ()
|
||||
|
||||
find_path (OPTIX_INCLUDE_DIR
|
||||
NAMES optix.h
|
||||
HINTS ${OPTIXHOME}/include
|
||||
PATH_SUFFIXES include )
|
||||
|
||||
# Macro adapted from https://github.com/nvpro-samples/optix_advanced_samples
|
||||
macro(OPTIX_find_api_library name version)
|
||||
find_library(${name}_LIBRARY
|
||||
NAMES ${name}.${version} ${name}
|
||||
PATHS "${OPTIXHOME}/lib64"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
find_library(${name}_LIBRARY
|
||||
NAMES ${name}.${version} ${name}
|
||||
)
|
||||
endmacro()
|
||||
|
||||
OPTIX_find_api_library(optix 1)
|
||||
OPTIX_find_api_library(optixu 1)
|
||||
OPTIX_find_api_library(optix_prime 1)
|
||||
|
||||
set (OPTIX_LIBRARIES ${optix_LIBRARY} ${optixu_LIBRARY} ${optix_prime_LIBRARY})
|
||||
|
||||
# Pull out the API version from optix.h
|
||||
file(STRINGS ${OPTIX_INCLUDE_DIR}/optix.h OPTIX_VERSION_LINE LIMIT_COUNT 1 REGEX OPTIX_VERSION)
|
||||
string(REGEX MATCH "([0-9]+)" OPTIX_VERSION_STRING "${OPTIX_VERSION_LINE}")
|
||||
math(EXPR OPTIX_VERSION_MAJOR "${OPTIX_VERSION_STRING}/10000")
|
||||
math(EXPR OPTIX_VERSION_MINOR "(${OPTIX_VERSION_STRING}%10000)/100")
|
||||
math(EXPR OPTIX_VERSION_MICRO "${OPTIX_VERSION_STRING}%100")
|
||||
set(OPTIX_VERSION "${OPTIX_VERSION_MAJOR}.${OPTIX_VERSION_MINOR}.${OPTIX_VERSION_MICRO}")
|
||||
|
||||
message (STATUS "OptiX version = ${OPTIX_VERSION}")
|
||||
if (NOT OptiX_FIND_QUIETLY)
|
||||
message (STATUS "OptiX includes = ${OPTIX_INCLUDE_DIR}")
|
||||
message (STATUS "OptiX libraries = ${OPTIX_LIBRARIES}")
|
||||
endif ()
|
||||
|
||||
mark_as_advanced (
|
||||
OPTIX_INCLUDE_DIR
|
||||
OPTIX_LIBRARIES
|
||||
OPTIX_VERSION
|
||||
)
|
||||
|
||||
include (FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args (OptiX
|
||||
FOUND_VAR OPTIX_FOUND
|
||||
REQUIRED_VARS OPTIX_INCLUDE_DIR OPTIX_LIBRARIES OPTIX_VERSION
|
||||
VERSION_VAR OPTIX_VERSION
|
||||
)
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
# PUGIXML_LIBRARIES - library to link against
|
||||
# PUGIXML_FOUND - true if pugixml was found.
|
||||
|
||||
unset (PUGIXML_LIBRARY CACHE)
|
||||
unset (PUGIXML_INCLUDE_DIR CACHE)
|
||||
find_path (PUGIXML_INCLUDE_DIR
|
||||
NAMES pugixml.hpp
|
||||
PATHS ${PUGIXML_HOME}/include
|
||||
@@ -17,6 +19,15 @@ find_library (PUGIXML_LIBRARY
|
||||
/usr/local/lib
|
||||
/usr/local/lib/pugixml-1.8)
|
||||
|
||||
# Second chance -- if not found, look in the OIIO distro
|
||||
if (NOT PUGIXML_INCLUDE_DIR AND OPENIMAGEIO_INCLUDE_DIR)
|
||||
find_path (PUGIXML_INCLUDE_DIR
|
||||
NAMES pugixml.hpp
|
||||
PATHS ${OPENIMAGEIO_INCLUDE_DIR}/OpenImageIO)
|
||||
set (PUGIXML_LIBRARY ${OPENIMAGEIO_LIBRARIES})
|
||||
endif ()
|
||||
|
||||
|
||||
# Support the REQUIRED and QUIET arguments, and set PUGIXML_FOUND if found.
|
||||
include (FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS (PugiXML DEFAULT_MSG PUGIXML_LIBRARY
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
set (public_docs osl-languagespec.pdf
|
||||
testshade.md.html
|
||||
osltoy.md.html
|
||||
markdeep.min.js
|
||||
docs.css
|
||||
)
|
||||
|
||||
install (FILES ${public_docs} DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT documentation)
|
||||
@@ -15,3 +17,65 @@ install ( FILES "${PROJECT_SOURCE_DIR}/LICENSE"
|
||||
file (GLOB testshade_figures "Figures/testshade/*.jpg")
|
||||
install (FILES ${testshade_figures}
|
||||
DESTINATION ${CMAKE_INSTALL_DOCDIR}/Figures/testshade )
|
||||
|
||||
file (GLOB osltoy_figures "Figures/osltoy/*.jpg")
|
||||
install (FILES ${osltoy_figures}
|
||||
DESTINATION ${CMAKE_INSTALL_DOCDIR}/Figures/osltoy )
|
||||
|
||||
|
||||
|
||||
# Macro to compile a shader with oslc. Syntax is:
|
||||
# docdeep_generate (SOURCE osl_source_file
|
||||
# [ NAME doc_name ]
|
||||
# [ DOC_LIST list_to_append_doc_filename ] )
|
||||
# [ SRC_LIST list_to_append_src_filename ] )
|
||||
macro (docdeep_generate)
|
||||
cmake_parse_arguments (_docdeep "" "NAME;DOC_LIST;SRC_LIST" "SOURCE" ${ARGN})
|
||||
# ^^ syntax: prefix options one-arg-keywords multi-arg-keywords args
|
||||
set (oslfile ${_docdeep_SOURCE})
|
||||
set (mdfile "${_docdeep_NAME}.md.html")
|
||||
if (VERBOSE)
|
||||
message (STATUS "docdeep will make '${mdfile}'")
|
||||
endif ()
|
||||
set (docdeep_program ${CMAKE_SOURCE_DIR}/src/build-scripts/docdeep.py)
|
||||
add_custom_command (OUTPUT ${mdfile}
|
||||
COMMAND python ${docdeep_program} -d ${_docdeep_NAME} -s docs.css
|
||||
${_docdeep_SOURCE} > "${CMAKE_CURRENT_BINARY_DIR}/${mdfile}"
|
||||
MAIN_DEPENDENCY ${docdeep_program}
|
||||
DEPENDS ${_docdeep_SOURCE}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "docdeep ${_docdeep_NAME}"
|
||||
)
|
||||
if (_docdeep_DOC_LIST)
|
||||
list (APPEND ${_docdeep_DOC_LIST} "${CMAKE_CURRENT_BINARY_DIR}/${mdfile}")
|
||||
endif ()
|
||||
if (_docdeep_SRC_LIST)
|
||||
list (APPEND ${_docdeep_SRC_LIST} ${_docdeep_SOURCE})
|
||||
endif ()
|
||||
endmacro ()
|
||||
|
||||
|
||||
|
||||
set (all_docdeep_docs "")
|
||||
set (all_docdeep_srcs "")
|
||||
docdeep_generate (NAME OSLQuery
|
||||
SOURCE ${PROJECT_SOURCE_DIR}/src/include/OSL/oslquery.h
|
||||
${PROJECT_SOURCE_DIR}/src/oslinfo/oslinfo.cpp
|
||||
DOC_LIST all_docdeep_docs
|
||||
SRC_LIST all_docdeep_srcs)
|
||||
docdeep_generate (NAME docdeep
|
||||
SOURCE ${PROJECT_SOURCE_DIR}/src/build-scripts/docdeep.py
|
||||
DOC_LIST all_docdeep_docs
|
||||
SRC_LIST all_docdeep_srcs)
|
||||
|
||||
add_custom_target (generated_docs ALL
|
||||
DEPENDS ${all_docdeep_docs} ${all_docdeep_srcs}
|
||||
SOURCES ${all_docdeep_srcs}
|
||||
)
|
||||
|
||||
message (STATUS "All docdeep docs = ${all_docdeep_docs}")
|
||||
|
||||
install (FILES ${all_docdeep_docs}
|
||||
DESTINATION ${CMAKE_INSTALL_DOCDIR}
|
||||
COMPONENT documentation
|
||||
)
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 90 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 108 KiB |
+9
-3
@@ -6,7 +6,7 @@ all: languagespec.pdf
|
||||
|
||||
|
||||
# document making rule: use pdflatex
|
||||
languagespec.pdf: *.tex languagespec.aux macros.aux Figures/*.pdf Figures/*png
|
||||
languagespec.pdf: *.tex Figures/*.pdf Figures/*png
|
||||
pdflatex ${PDFLATEX_FLAGS} languagespec.tex
|
||||
|
||||
|
||||
@@ -15,8 +15,14 @@ languagespec.pdf: *.tex languagespec.aux macros.aux Figures/*.pdf Figures/*png
|
||||
index: languagespec_index
|
||||
|
||||
languagespec_index:
|
||||
pdflatex ${PDFLATEX_FLAGS} languagespec.tex
|
||||
pdflatex ${PDFLATEX_FLAGS} languagespec.tex
|
||||
makeindex languagespec
|
||||
pdflatex ${PDFLATEX_FLAGS} languagespec.tex
|
||||
pdflatex ${PDFLATEX_FLAGS} languagespec.tex languagespec.aux macros.aux
|
||||
pdflatex ${PDFLATEX_FLAGS} languagespec.tex languagespec.aux macros.aux languagespec.toc
|
||||
|
||||
clean:
|
||||
rm -f languagespec.aux languagespec.idx languagespec.ilg languagespec.ind languagespec.log
|
||||
rm -f languagespec.out languagespec.pdf languagespec.toc macros.aux
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
/* Custom stylesheet.
|
||||
* Bits copied from many sources, including those that come with Markdeep.
|
||||
*/
|
||||
|
||||
/* Custom stylesheet for API documentation by Aras Pranckevičius, http://aras-p.info/
|
||||
and tweaked by Morgan McGuire.
|
||||
Licensed as public domain or BSD 2-clause, whichever is more convenient for you.
|
||||
Originally from https://github.com/aras-p/markdeep-docs-style */
|
||||
|
||||
/* Some modifications by Larry Gritz */
|
||||
|
||||
body {
|
||||
max-width: 50em;
|
||||
/* font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; */
|
||||
text-align: left;
|
||||
margin: 1.5em;
|
||||
padding: 0 1em;
|
||||
}
|
||||
|
||||
/* if screen is wide enough, put table of contents on the right side */
|
||||
@media screen and (min-width: 64em) {
|
||||
.md .longTOC, .md .mediumTOC, .md .shortTOC {
|
||||
position: fixed;
|
||||
max-width: 20em;
|
||||
left: 54em;
|
||||
display:block;
|
||||
}
|
||||
}
|
||||
|
||||
/* for narrow screens or print, hide table of contents */
|
||||
@media screen and (max-width: 64em) {
|
||||
.md .longTOC, .md .mediumTOC, .md .shortTOC { display: none; }
|
||||
}
|
||||
|
||||
@media print {
|
||||
.md .longTOC, .md .mediumTOC, .md .shortTOC { display: none; }
|
||||
body { max-width: 100%; }
|
||||
}
|
||||
|
||||
/* reset heading/link fonts to that of body */
|
||||
.md a,
|
||||
.md div.title, contents, .md .tocHeader,
|
||||
.md h1, .md h2, .md h3, .md h4, .md h5, .md h6,
|
||||
.md .nonumberh1, .md .nonumberh2, .md .nonumberh3, .md .nonumberh4, .md .nonumberh5, .md .nonumberh6,
|
||||
.md .shortTOC, .md .mediumTOC, .md .longTOC {
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.md div.title {
|
||||
/*orig margin: 0.4em 0 0 0; */
|
||||
margin: 0.4em 0 2em 0; /* LG */
|
||||
padding: 0;
|
||||
/*orig text-align: inherit; */
|
||||
text-align: center; /* LG */
|
||||
text-decoration: underline; /* LG */
|
||||
}
|
||||
|
||||
.md div.subtitle {
|
||||
/* orig text-align: inherit; */
|
||||
text-align: center; /* LG */
|
||||
}
|
||||
|
||||
/* faint border below headings */
|
||||
.md h1, .md h2, .md h3, .md h4,
|
||||
.md .nonumberh1, .md .nonumberh2, .md .nonumberh3, .md .nonumberh4 {
|
||||
border-bottom: 1px solid rgba(0,0,0,.1);
|
||||
}
|
||||
/* heading font styles */
|
||||
.md h1, .md .nonumberh1, .md div.title {
|
||||
font-size: 150%;
|
||||
font-weight: 600;
|
||||
color: rgba(0,0,0,.7);
|
||||
}
|
||||
.md h2, .md .nonumberh2 {
|
||||
font-size: 120%;
|
||||
font-weight: 400;
|
||||
color: rgba(0,0,0,.9);
|
||||
}
|
||||
.md h3, .md .nonumberh3 {
|
||||
font-size: 110%;
|
||||
font-weight: 400;
|
||||
color: rgba(0,0,0,.7);
|
||||
}
|
||||
/* no numbering of headings */
|
||||
/*.md h1:before, .md h2:before, .md h3:before, .md h4:before { content: none; }*/
|
||||
|
||||
/* link styling */
|
||||
.md a:link, .md a:visited {
|
||||
color: #3f51b5;
|
||||
}
|
||||
|
||||
/* inline and block code */
|
||||
.md code, .md pre.listing {
|
||||
background-color: rgba(0,0,0,.03);
|
||||
padding: 0.1em 0.2em;
|
||||
border-radius: 0.15em;
|
||||
}
|
||||
.md pre.listing code {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* table of contents styling; make all 3 forms of it look the same */
|
||||
.md .longTOC, .md .mediumTOC, .md .shortTOC {
|
||||
font-size: inherit;
|
||||
line-height: 120%;
|
||||
margin: 1em 0;
|
||||
padding: .4rem;
|
||||
border-left: .1rem solid #3f51b5;
|
||||
}
|
||||
.md .tocHeader {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
font-size: inherit;
|
||||
}
|
||||
.md .tocNumber {
|
||||
display: none;
|
||||
}
|
||||
.md .longTOC .level1, .md .mediumTOC .level1, .md .shortTOC .level1 {
|
||||
font-weight: inherit;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.md .longTOC p, .md .mediumTOC p, .md .shortTOC p {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.md .longTOC center, .md .mediumTOC center, .md .shortTOC center {
|
||||
text-align: left;
|
||||
}
|
||||
.md .longTOC b, .md .mediumTOC b, .md .shortTOC b {
|
||||
font-weight: 400;
|
||||
}
|
||||
.md .longTOC a, .md .mediumTOC a, .md .shortTOC a {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.md .longTOC .level1, .md .mediumTOC .level1, .md .shortTOC .level1,
|
||||
.md .longTOC .level2, .md .mediumTOC .level2, .md .shortTOC .level2,
|
||||
.md .longTOC .level3, .md .mediumTOC .level3, .md .shortTOC .level3 {
|
||||
white-space: nowrap;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
/* tables; use fainter colors than regular markdeep style */
|
||||
.md table.table {
|
||||
font-size: 90%;
|
||||
}
|
||||
.md table.table th {
|
||||
border: none;
|
||||
background-color: #ccc;
|
||||
color: rgba(0,0,0,.6);
|
||||
}
|
||||
.md table.table tr, .md table.table td {
|
||||
border-color: #eee;
|
||||
}
|
||||
.md table.table tr:nth-child(even) {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
+60
-37
@@ -43,7 +43,7 @@
|
||||
|
||||
\def\langname{Open Shading Language\xspace}
|
||||
\def\product{{\sffamily Open Shading Language}\xspace}
|
||||
\def\versionnumber{1.9}
|
||||
\def\versionnumber{1.10}
|
||||
\def\productver{\product\ {\sffamily \versionnumber}\xspace}
|
||||
|
||||
|
||||
@@ -52,17 +52,16 @@
|
||||
%\textregistered\
|
||||
{\bf\sffamily \versionnumber} \medskip \\ \huge
|
||||
Language Specification
|
||||
%\\ \large (CONFIDENTIAL --- draft in progress)
|
||||
} \bigskip }
|
||||
\author{
|
||||
\copyright\ Copyright 2009-2017 Sony Pictures Imageworks Inc., et al. All rights reserved.
|
||||
\copyright\ Copyright 2009-2018 Sony Pictures Imageworks Inc., et al. All rights reserved.
|
||||
\bigskip \\
|
||||
\vspace{1in} \\
|
||||
Editor: Larry Gritz \\
|
||||
\emph{lg@imageworks.com}
|
||||
}
|
||||
\date{{\large Date: 30 Jun 2017 \\
|
||||
% (with corrections, 12 May 2017)
|
||||
\date{{\large Date: 31 Mar 2018 \\
|
||||
(with corrections, 12 Apr 2019)
|
||||
}
|
||||
\bigskip
|
||||
\bigskip
|
||||
@@ -539,6 +538,8 @@ source code:
|
||||
\item {\cf source} is a {\cf float} or {\cf int} and {\cf dest} is a
|
||||
\emph{triple} (the scalar value will be replicated for all three components
|
||||
of the triple).
|
||||
\item {\cf source} is a single component of an aggregate type (e.g. one
|
||||
channel of a {\cf color}) and {\cf dest} is a {\cf float} (or vice versa).
|
||||
\end{itemize}
|
||||
|
||||
\subsection*{Geometric primitives}
|
||||
@@ -586,13 +587,6 @@ point-by-point basis, and volume shaders that describe how light is
|
||||
scattered within a region of space. A particular renderer may have
|
||||
additional shader types that it supports.
|
||||
|
||||
%\subsection*{Shader types}
|
||||
%
|
||||
%There are several types of shaders: surface, displacement, light,
|
||||
%volume. The type of shader determines what it's allowed to do (for
|
||||
%example, only displacement shaders can alter the surface position).
|
||||
%There is also a generic kind of shader that can be used for any of the
|
||||
%shader uses.
|
||||
|
||||
\subsection*{Shader execution state: parameter binding and global variables}
|
||||
|
||||
@@ -614,7 +608,7 @@ information about the renderer as a whole (rendering options, etc.).
|
||||
|
||||
Surface shaders (and volume shaders) do not by themselves compute the
|
||||
final color of light emanating from the surface (or along a volume).
|
||||
Rather, the compute a \emph{closure}, which is a symbolic representation
|
||||
Rather, they compute a \emph{closure}, which is a symbolic representation
|
||||
describing the appearance of the surface, that may be more fully
|
||||
evaluated later. This is in effect a parameterized formula, in which
|
||||
some inputs have definite numeric values, but others may depend on
|
||||
@@ -979,7 +973,7 @@ different behaviors or appearances when used on different objects.
|
||||
|
||||
Shader parameters are specified in the shader declaration, in
|
||||
parentheses after the shader's name. This is much like the parameters
|
||||
to a \languagename function (or a function in C or similar languages),
|
||||
to an OSL function (or a function in C or similar languages),
|
||||
except that shader parameters must have an \emph{initializer}, giving a
|
||||
default value for the parameter. Shader parameter default initializers
|
||||
may be expressions (i.e., may be computed rather than restricted to
|
||||
@@ -1865,7 +1859,7 @@ reference to a named space:
|
||||
\end{code}
|
||||
|
||||
\noindent The first form creates the matrix that transforms points from
|
||||
\commonspace to \shaderspace. Transforming points by this matrix
|
||||
\shaderspace to \commonspace. Transforming points by this matrix
|
||||
is identical to calling {\cf transform("shader",...)}.
|
||||
The second form prepends the current-to-world transformation matrix
|
||||
onto the $4 \times 4$ matrix with components $m_{0,0} ... m_{3,3}$.
|
||||
@@ -2060,6 +2054,22 @@ you can construct built-in types like \color or \point:
|
||||
RGBA d = add (c, RGBA(color(.3,.4,.5), 0));
|
||||
\end{code}
|
||||
|
||||
\NEW % 1.10
|
||||
You may also use the \emph{compound initializer list} syntax to construct a
|
||||
type when it can be deduced from context which compound type is required.
|
||||
For example, this is equivalent to the preceding example:
|
||||
|
||||
\begin{code}
|
||||
RGBA c = {col,alpha}; // deduce by what is being assigned to
|
||||
|
||||
RGBA add (RGBA a, RGBA b)
|
||||
{
|
||||
return { a.rgb+b.rgb, a.a+b.a }; // deduce by func return type
|
||||
}
|
||||
|
||||
RGBA d = add (c, {{.3,.4,.5}, 0}); // deduce by expected arg type
|
||||
\end{code}
|
||||
|
||||
It is permitted to have a structure field that is an array, as well as to
|
||||
have an array of structures. But it is not currently permitted to ``nest''
|
||||
arrays (that is, to have an array of structs which contain members that are
|
||||
@@ -2105,7 +2115,7 @@ At present, the only type of \closure supported by \langname is the
|
||||
form a linear combination of \colorclosure's. Additional closure types
|
||||
and operations are reserved for future use.
|
||||
|
||||
Allowable operations on \colorclosure's include:
|
||||
Allowable operations on \colorclosure include:
|
||||
|
||||
\medskip
|
||||
\noindent \begin{tabular}{|p{2.25in}|p{1.25in}|p{1.75in}|}
|
||||
@@ -2653,8 +2663,13 @@ that point, and designates the value that will be returned (if not a
|
||||
|
||||
Functions may be \emph{overloaded}. That is, multiple functions may be
|
||||
defined to have the same name, as long as they have differently-typed
|
||||
parameters, so that when the function is called the list of arguments
|
||||
can disambiguate which version of the function is desired.
|
||||
parameters, so that when the function is called the list of arguments can
|
||||
select which version of the function is desired. When there are multiple
|
||||
potential matches, function versions whose argument types match exactly are
|
||||
favored, followed by those that match with type coercion (for example,
|
||||
passing an {\cf int} when the function expects a {\cf float}, or passing a
|
||||
{\cf float} when the function expects a \color), and finally by trying to
|
||||
match the return value to the type of variable the result is assigned to.
|
||||
|
||||
\subsection{Operator overloading}
|
||||
\label{sec:syntax:operatoroverloading}
|
||||
@@ -3067,16 +3082,6 @@ The {\cf mix} function returns a linear blending :
|
||||
$ x*(1-\alpha) + y*(\alpha) $
|
||||
\apiend
|
||||
|
||||
\apiitem{int {\ce isnan} (float x) \\
|
||||
int {\ce isinf} (float x) \\
|
||||
int {\ce isfinite} (float x)}
|
||||
\indexapi{isnan()} \indexapi{isinf()} \indexapi{isfinite()}
|
||||
The {\cf isnan()} function returns 1 if $x$ is a not-a-number (NaN)
|
||||
value, 0 otherwise. The {\cf isinf()} function returns 1 if $x$ is an
|
||||
infinite (Inf or --Inf) value, 0 otherwise. The {\cf isfinite()}
|
||||
function returns 1 if $x$ is an ordinary number (neither infinite nor
|
||||
NaN), 0 otherwise. \apiend
|
||||
|
||||
\apiitem{\emph{type} {\ce select} (\emph{type} x, \emph{type} y, \emph{type} cond) \\
|
||||
\emph{type} {\ce select} (\emph{type} x, \emph{type} y, float cond) \\
|
||||
\emph{type} {\ce select} (\emph{type} x, \emph{type} y, int cond)}
|
||||
@@ -3242,10 +3247,12 @@ and {\cf eta} is the ratio of refractive index of the medium
|
||||
containing {\cf I} to that on the opposite side of the surface.
|
||||
\apiend
|
||||
|
||||
\apiitem{point {\ce rotate} (point Q, float angle, point P0, point P1)}
|
||||
\apiitem{point {\ce rotate} (point Q, float angle, point P0, point P1) \\
|
||||
point {\ce rotate} (point Q, float angle, vector axis)}
|
||||
\indexapi{rotate()}
|
||||
Returns the point computed by rotating point {\cf Q} by {\cf angle}
|
||||
radians about the axis that passes from point {\cf P0} to {\cf P1}.
|
||||
Returns the point computed by rotating point {\cf Q} by {\cf angle}
|
||||
radians about the axis that passes from point {\cf P0} to {\cf P1},
|
||||
or about the {\cf axis} vector centered on the origin.
|
||||
\apiend
|
||||
|
||||
\apiitem{\emph{ptype} {\ce transform} (string tospace, \emph{ptype} p) \\
|
||||
@@ -3441,11 +3448,15 @@ The \emph{type} may be any of of \float, \color, \point, \vector, or
|
||||
performed component-by-component (separately for $x$, $y$, and $z$).
|
||||
\apiend
|
||||
|
||||
\apiitem{float {\ce linearstep} (float edge0, float edge1, float x)}
|
||||
\apiitem{float {\ce linearstep} (float edge0, float edge1, float x) \\
|
||||
\emph{type} {\ce linearstep} (\emph{type} edge0, \emph{type} edge1, \emph{type} x)}
|
||||
\indexapi{linearstep()}
|
||||
Returns 0 if $x \le {\mathit edge0}$, and 1 if $x \ge {\mathit edge1}$,
|
||||
and performs a linear
|
||||
interpolation between 0 and 1 when ${\mathit edge0} < x < {\mathit edge1}$.
|
||||
This is equivalent to {\cf step(edge0, x)} when {\cf edge0 == edge1}.
|
||||
For \color and \point-like types, the computations are
|
||||
performed component-by-component (separately for $x$, $y$, and $z$).
|
||||
\apiend
|
||||
|
||||
\apiitem{float {\ce smoothstep} (float edge0, float edge1, float x) \\
|
||||
@@ -3459,10 +3470,11 @@ with a smooth transition.
|
||||
|
||||
The \emph{type} may be any of of \float, \color, \point, \vector, or
|
||||
\normal. For \color and \point-like types, the computations are
|
||||
performed component-by-component (separately for $x$, $y$, and $z$).
|
||||
performed component-by-component.
|
||||
\apiend
|
||||
|
||||
\apiitem{float {\ce smooth_linearstep} (float edge0, float edge1, float x, float eps)}
|
||||
\apiitem{float {\ce smooth_linearstep} (float edge0, float edge1, float x, float eps) \\
|
||||
\emph{type} {\ce smooth_linearstep} (\emph{type} edge0, \emph{type} edge1, \emph{type} x, \emph{type} eps)}
|
||||
\indexapi{smooth_linearstep()}
|
||||
This function is strictly linear between ${\mathit edge0}+{\mathit eps}$ and ${\mathit edge1}-{\mathit eps}$
|
||||
but smoothly ramps to 0 between ${\mathit edge0}-{\mathit eps}$ and ${\mathit edge0}+{\mathit eps}$
|
||||
@@ -3470,6 +3482,8 @@ and smoothly ramps to 1 between ${\mathit edge1}-{\mathit eps}$ and ${\mathit ed
|
||||
It is 0 when $x \le {\mathit edge0}-{\mathit eps}$, and 1 if $x \ge {\mathit edge1}+{\mathit eps}$,
|
||||
and performs a linear
|
||||
interpolation between 0 and 1 when ${\mathit edge0} < x < {\mathit edge1}$.
|
||||
For \color and \point-like types, the computations are
|
||||
performed component-by-component.
|
||||
\apiend
|
||||
|
||||
|
||||
@@ -3688,7 +3702,7 @@ animation (provided its input is \emph{precisely} identical).
|
||||
int {\ce hash} (float u, float v) \\
|
||||
int {\ce hash} (point p) \\
|
||||
int {\ce hash} (point p, float t) \\
|
||||
int {\ce hash) (int i)}}
|
||||
int {\ce hash} (int i)}
|
||||
\indexapi{hash()}
|
||||
\NEW % 1.9
|
||||
Returns a deterministic, repeatable integer \emph{hash} of the 1-, 2-, 3-,
|
||||
@@ -4031,7 +4045,7 @@ Identical to {\cf regex_search}, except that it must match the
|
||||
|
||||
Perform a texture lookup of an image file, indexed by 2D coordinates
|
||||
$(s,t)$, antialiased over a region defined by the differentials
|
||||
\emph{dsdx, dtdx, dsty} and \emph{dtdy} (which are computed
|
||||
\emph{dsdx, dtdx, dsdy} and \emph{dtdy} (which are computed
|
||||
automatically from $s$ and $t$, if not supplied). Whether the results
|
||||
are assigned to a \float or a \color (or type cast to one of those)
|
||||
determines whether the texture lookup is a single channel or three
|
||||
@@ -4204,6 +4218,14 @@ The first channel to look up from the texture map (default: 0).
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{"subimage", <int> \\
|
||||
"subimage", <string>}
|
||||
\vspace{12pt}
|
||||
Specify the subimage (by numerical index, or name) of the subimage
|
||||
within a multi-image texture file (default: subimage 0).
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{"fill", <float>}
|
||||
\vspace{12pt}
|
||||
The value to return for any channels that are requested,
|
||||
@@ -4922,7 +4944,7 @@ wish to make queryable.
|
||||
\apiend
|
||||
|
||||
\begin{table}[htbp]
|
||||
\caption{Names of standard attributes that may be retrieved.}\label{tab:cameraattributes}
|
||||
\caption{Names of standard attributes that may be retrieved.}\label{tab:stdattributes}
|
||||
\begin{tabular}{|p{1.8in}|p{0.6in}|p{2.8in}|}
|
||||
\hline
|
||||
{\bf Name} & {\bf Type} & {\bf Description} \\
|
||||
@@ -5435,6 +5457,7 @@ nothing (empty, no token).
|
||||
\alt <ternary-expression>
|
||||
\alt <typecast-expression>
|
||||
\alt <variable-ref>
|
||||
\alt <compound-initializer>
|
||||
|
||||
<compound-expression> ::= <expression> \{ "," <expression> \}
|
||||
|
||||
|
||||
Vendored
+6
-5
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -0,0 +1,243 @@
|
||||
**osltoy**
|
||||
revision date: 30 Nov 2017
|
||||
|
||||
|
||||
|
||||
|
||||
_osltoy_ basics
|
||||
==================================================
|
||||
|
||||
`osltoy` is an interactive editor and realtime visualizer for OSL shaders.
|
||||
It is inspired by [Shadertoy](https://www.shadertoy.com/) by Inigo Quilez.
|
||||
But it uses a real VFX shading language!
|
||||
|
||||

|
||||
|
||||
The basic functionaity of `osltoy` is:
|
||||
|
||||
* Allow you to edit OSL shader source code.
|
||||
* Live and continuous rendering of an "image" that is the result of running
|
||||
your shader on each pixel of the image (pixel color is taken from the
|
||||
shader's parameter `output color Cout`.)
|
||||
|
||||
|
||||
## Command line
|
||||
|
||||
Launch `osltoy` from the command line:
|
||||
|
||||
`osltoy` [*options*]
|
||||
|
||||
Additional command line arguments:
|
||||
|
||||
`--help`
|
||||
: Print command line options and other help.
|
||||
|
||||
`-v`
|
||||
: Verbose mode. (Doesn't really do anything currently.)
|
||||
|
||||
`--res` *xres* *yres*
|
||||
: Specifies the resolution of the render window (default: 512 x 512).
|
||||
|
||||
`--threads` *n*
|
||||
: Specifies the number of simultaneous threads to use for shading. If not
|
||||
specified, it will use all your hardware cores.
|
||||
|
||||
*filename.osl*
|
||||
: If one or more filenames of shader source code are specified, they will
|
||||
be loaded into editor tabs upon startup.
|
||||
|
||||
|
||||
## osltoy Basics
|
||||
|
||||
First, let's launch `osltoy`:
|
||||
|
||||
```
|
||||
$ osltoy
|
||||
```
|
||||
|
||||

|
||||
This will start up a new `osltoy` session.
|
||||
On the right half of the GUI is a code editor window. Below the code editor
|
||||
is an area that will show you any compilation errors. The left half of the
|
||||
GUI will display the results of the shader (a checkerboard if no shader
|
||||
has been compiled yet). Below that is an area that will hold widgets to
|
||||
allow adjustment of shader parameter values.
|
||||
|
||||
At the very bottom of the app window is a status bar showing time, frames
|
||||
per second, and other status messages. At the very top of the app window
|
||||
(or, on MacOS, at the top of the screen) is a menu bar with the usual set of
|
||||
common operations.
|
||||
|
||||
### Loading and saving shaders
|
||||
|
||||
You can load a shader one of three ways:
|
||||
|
||||
1. Specify the filename of an existing shader when you launch the app:
|
||||
```
|
||||
osltoy test.osl
|
||||
```
|
||||
|
||||
2. From a blank window, load an existing shader by selecting the menu
|
||||
bar choice `File` --> `Open`, or hitting the hotkey `Ctrl-O` (on MacOS,
|
||||
⌘`-O`). This will present a file selection dialog.
|
||||
|
||||
3. Just start typing in the editor window.
|
||||
|
||||
You can save the edited shader with the menu bar `File` --> `Save`
|
||||
or the hotkey `Ctrl-S` (⌘`-S` on MacOS). If the file does not yet
|
||||
have a name, you will be presented with a file save dialog (as you will
|
||||
if you use `File` --> `Save As`).
|
||||
|
||||
!!! Note
|
||||
Every time we talk about a `Ctrl-`*key* combination, if you are on MacOS
|
||||
(OSX), that hotkey will be ⌘`-`*key*. This document won't awkwardly
|
||||
repeat this clarification for every command.
|
||||
|
||||
### Compiling shaders
|
||||
|
||||
When you have loaded or edited your OSL source code, you can compile the
|
||||
shader with menu `Tools` --> `Recompile shaders`, or by clicking the
|
||||
`Recompile` button below the source code editor widget, or by using the
|
||||
hotkey `Ctrl-R`.
|
||||
|
||||
!!! Warning
|
||||
`osltoy` won't compile a buffer that doesn't have a filename ending in
|
||||
`.osl`, and if you started with a blank window, it won't have a name at
|
||||
all until you save the first time.
|
||||
|
||||
In the compilation status window below the editor, you will either see
|
||||
an `Ok` message if the compiler succeeded, or the error output from the
|
||||
compiler, as illustrated here:
|
||||
|
||||

|
||||
|
||||
|
||||
!!! Warning
|
||||
`osltoy` appears to let you load or create multiple shaders, appearing
|
||||
in a tabbed editor. We'll get this working eventually (so you can edit
|
||||
whole shader groups and all the shaders that are in them), but currently
|
||||
only the shader in the first tab will be compiled and executed, so don't
|
||||
get confused by the non-functional parts of the interface.
|
||||
|
||||
|
||||
### Executing shaders and interactive changes
|
||||
|
||||
Once you compile the shader successfully, it will execute and display the
|
||||
results of shading a rectangle.
|
||||
|
||||

|
||||
|
||||
As soon as you recompile, the shader will be executed as quickly as possible
|
||||
and displayed as an image on the left, with shader parameter adjustment
|
||||
widgets below it.
|
||||
|
||||
Evey time you change a parameter value through its widget, the shader will
|
||||
automatically recompile and re-execute. If you edit the text of the shader,
|
||||
clicking the `Recompile` button or using the hotkey `Ctrl-R` will recompile
|
||||
and re-execute the shader.
|
||||
|
||||
|
||||
Rules of the game
|
||||
==================
|
||||
|
||||
## Shader inputs and state
|
||||
|
||||
The shader is executed on every pixel of an image (defaulting to a 512x512
|
||||
square, but you can change the resolution via a command line flag).
|
||||
|
||||
The `float u` and `v` global variables vary from 0 to 1 along the rectangle.
|
||||
|
||||
The `point P` global variable will be set to `(x,y,0)`, where `x` is the pixel
|
||||
horizontal coordinate (0 to xres-1 as it goes from left to right) and `y`
|
||||
is the pixel vertical coordinate (0 to yres-1 as it goes from top to bottom
|
||||
of the image).
|
||||
|
||||
The `float time` global variable contains the time (in seconds) since the
|
||||
last time the shader was recompiled. Making your shader change its behavior
|
||||
based on the `time` variable will make an animated shader.
|
||||
|
||||
## Shader outputs
|
||||
|
||||
The color displayed is taken from the shader output parameter that is
|
||||
declared like this:
|
||||
|
||||
```
|
||||
output color Cout = 0
|
||||
```
|
||||
|
||||
Whatever you place in that output will be the color displayed at each pixel
|
||||
of the output image.
|
||||
|
||||
!!! Note
|
||||
Your shader does not need to set `Ci` or deal with closures. The
|
||||
`osltoy` app is just for exploring pattern generation, not illumination.
|
||||
It doesn't actually have any notion of 3D geometry or lights.
|
||||
|
||||
|
||||
## Shader execution
|
||||
|
||||
If your shader does not reference the `time` variable in any way, it will
|
||||
only be executed once each time it recompiles. But if `time` appears in your
|
||||
shader, it will execute repeatedly, as quickly as possible, until you exit
|
||||
or recompile.
|
||||
|
||||
Shader execution will by default use enough threads to keep all your cores
|
||||
busy. The command line option `--threads` can be used to limit the number
|
||||
of cores (or to "over-thread").
|
||||
|
||||
|
||||
Caveats, limitations, and broken stuff
|
||||
========================
|
||||
|
||||
These are current limitations or breakages that we will fix over time.
|
||||
|
||||
* The GUI seems to let you open multiple editor tabs, but currently, the
|
||||
only one that will compile and execute is the *first* (farthest to the left
|
||||
tab that was loaded or saved under a name that ends in `".osl"`.
|
||||
|
||||
* We intend to add "Pause" and "Reset" buttons to control time.
|
||||
|
||||
* I tried to make the parameter adjustment widgets be clever about how
|
||||
quickly to modify the values, depending on their range. But I don't have
|
||||
it quite right. It's still being refined.
|
||||
|
||||
* There isn't yet have a way to get the shader itself to get information about
|
||||
external events such as mouse clicks or key presses, but that would be
|
||||
fun.
|
||||
|
||||
* There isn't yet a way for the shader to have *state* that can be computed,
|
||||
stored, then re-read when the shader executes on the next frame.
|
||||
|
||||
|
||||
Things to try
|
||||
=============
|
||||
|
||||
* Try this:
|
||||
|
||||
` osltoy ` *osl_install_directory*`/shaders/mandelbrot.osl`
|
||||
|
||||
* Use the global `time` variable to make animated patterns.
|
||||
|
||||
* Explore noise functions and other pattern generation interactively.
|
||||
|
||||
* Explore (by keeping an eye on the "FPS" reading at the bottom) what shader
|
||||
operations are fast and what is slow.
|
||||
|
||||
* Don't forget that `texture()` calls work as expected in shadertoy!
|
||||
|
||||
* `osltoy` is a great tool for leaning or *teaching* OSL.
|
||||
|
||||
* The actual "geometry" is just a rectangle, but like with Shadertoy,
|
||||
you can make patterns that *look like* by implementing a simple ray tracer
|
||||
in the shader itself, or using other clever tricks.
|
||||
|
||||
* Look at the many examples on [Shadertoy](https://www.shadertoy.com/)
|
||||
for inspiration!
|
||||
|
||||
* Make crazy stuff and post the shaders to the `osl-dev` mail list!
|
||||
|
||||
|
||||
|
||||
<!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="markdeep.min.js"></script><script src="https://casual-effects.com/markdeep/latest/markdeep.min.js?"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script>
|
||||
<link rel="stylesheet" href="docs.css?">
|
||||
|
||||
@@ -1003,7 +1003,5 @@ tests, you can:
|
||||
|
||||
|
||||
<!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="markdeep.min.js"></script><script src="https://casual-effects.com/markdeep/latest/markdeep.min.js?"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script>
|
||||
<link rel="stylesheet" href="docs.css?">
|
||||
|
||||
<style>
|
||||
h1, .nonumberh1 { page-break-before: always }
|
||||
</style>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
Copyright (c) 2009-2018 Sony Pictures Imageworks Inc., et al.
|
||||
All Rights Reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Sony Pictures Imageworks nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
|
||||
// USAGE NOTES:
|
||||
//
|
||||
// To define a "standard" DeviceString, add a STRDECL to <OSL/strdecls.h>
|
||||
// specifying the string literal and the name to use for the variable.
|
||||
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
// Strings are stored in a block of CUDA device memory. String variables hold a
|
||||
// pointer to the start of the char array for each string. Each canonical string
|
||||
// has a unique entry in the table, so two strings can be tested for equality by
|
||||
// comparing their addresses.
|
||||
//
|
||||
// As a convenience, the ustring hash and the length of the string are also
|
||||
// stored in the table, in the 16 bytes preceding the characters.
|
||||
|
||||
struct DeviceString {
|
||||
const char* m_chars;
|
||||
|
||||
OSL_HOSTDEVICE uint64_t hash()
|
||||
{
|
||||
return *(uint64_t*)(m_chars - sizeof(uint64_t) - sizeof(uint64_t));
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE uint64_t length()
|
||||
{
|
||||
return *(uint64_t*)(m_chars - sizeof(uint64_t));
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE const char* c_str()
|
||||
{
|
||||
return m_chars;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE bool operator== (const DeviceString& other) const
|
||||
{
|
||||
return m_chars == other.m_chars;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE bool operator!= (const DeviceString& other) const
|
||||
{
|
||||
return m_chars != other.m_chars;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Handy re-casting macro
|
||||
#define DEVSTR(cstr) (*(OSL::DeviceString*)&cstr)
|
||||
|
||||
|
||||
#ifdef __CUDA_ARCH__
|
||||
namespace DeviceStrings {
|
||||
#define STRDECL(str,var_name) \
|
||||
extern __device__ DeviceString var_name;
|
||||
#include <OSL/strdecls.h>
|
||||
#undef STRDECL
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
+118
-115
@@ -29,8 +29,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#pragma once
|
||||
|
||||
#include <initializer_list>
|
||||
#include <OSL/oslconfig.h>
|
||||
#include <OSL/oslversion.h>
|
||||
#include <OpenImageIO/fmath.h>
|
||||
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
|
||||
@@ -61,109 +64,109 @@ public:
|
||||
|
||||
/// Default ctr leaves everything uninitialized
|
||||
///
|
||||
constexpr Dual () { }
|
||||
OSL_HOSTDEVICE OIIO_CONSTEXPR14 Dual () { }
|
||||
|
||||
/// Construct a Dual from just a real value (derivs set to 0)
|
||||
///
|
||||
OIIO_CONSTEXPR14 Dual (const T &x) {
|
||||
OSL_HOSTDEVICE OIIO_CONSTEXPR14 Dual (const T &x) {
|
||||
m_data[0] = x;
|
||||
for (int i = 1; i <= PARTIALS; ++i)
|
||||
m_data[i] = T(0.0);
|
||||
}
|
||||
|
||||
/// Copy constructor from another Dual of same type and dimension.
|
||||
OIIO_CONSTEXPR14 Dual (const Dual &x) {
|
||||
OSL_HOSTDEVICE OIIO_CONSTEXPR14 Dual (const Dual &x) {
|
||||
for (int i = 0; i <= PARTIALS; ++i)
|
||||
m_data[i] = T(x.m_data[i]);
|
||||
}
|
||||
|
||||
#if 1
|
||||
/// Copy constructor from another Dual of same dimension and different,
|
||||
/// but castable, data type.
|
||||
template<class F>
|
||||
OIIO_CONSTEXPR14 Dual (const Dual<F,PARTIALS> &x) {
|
||||
OSL_HOSTDEVICE OIIO_CONSTEXPR14 Dual (const Dual<F,PARTIALS> &x) {
|
||||
for (int i = 0; i <= PARTIALS; ++i)
|
||||
m_data[i] = T(x.elem(i));
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Construct a Dual from a real and infinitesimals.
|
||||
///
|
||||
constexpr Dual (const T &x, const T &dx) : m_data{ x, dx } {
|
||||
OSL_HOSTDEVICE constexpr Dual (const T &x, const T &dx) : m_data{ x, dx } {
|
||||
static_assert(PARTIALS==1, "Wrong number of initializers");
|
||||
}
|
||||
constexpr Dual (const T &x, const T &dx, const T &dy)
|
||||
OSL_HOSTDEVICE constexpr Dual (const T &x, const T &dx, const T &dy)
|
||||
: m_data{ x, dx, dy }
|
||||
{
|
||||
static_assert(PARTIALS==2, "Wrong number of initializers");
|
||||
}
|
||||
void set (const T &x, const T &dx) {
|
||||
OSL_HOSTDEVICE void set (const T &x, const T &dx) {
|
||||
static_assert(PARTIALS==1, "Wrong number of initializers");
|
||||
m_data[0] = x;
|
||||
m_data[1] = dx;
|
||||
}
|
||||
void set (const T &x, const T &dx, const T &dy) {
|
||||
OSL_HOSTDEVICE void set (const T &x, const T &dx, const T &dy) {
|
||||
static_assert(PARTIALS==2, "Wrong number of initializers");
|
||||
m_data[0] = x;
|
||||
m_data[1] = dx;
|
||||
m_data[2] = dy;
|
||||
}
|
||||
|
||||
OIIO_CONSTEXPR14 Dual (std::initializer_list<T> vals) {
|
||||
OSL_HOSTDEVICE OIIO_CONSTEXPR14 Dual (std::initializer_list<T> vals) {
|
||||
#if OIIO_CPLUSPLUS_VERSION >= 14
|
||||
static_assert (vals.size() == elements, "Wrong number of initializers");
|
||||
#endif
|
||||
for (int i = 0; i < elements; ++i)
|
||||
m_data[i] = vals.begin()[i];
|
||||
}
|
||||
|
||||
/// Return the real value.
|
||||
constexpr const T& val () const { return m_data[0]; }
|
||||
T& val () { return m_data[0]; }
|
||||
OSL_HOSTDEVICE constexpr const T& val () const { return m_data[0]; }
|
||||
OSL_HOSTDEVICE T& val () { return m_data[0]; }
|
||||
|
||||
/// Return the partial derivative with respect to x.
|
||||
constexpr const T& dx () const { return m_data[1]; }
|
||||
T& dx () { return m_data[1]; }
|
||||
OSL_HOSTDEVICE constexpr const T& dx () const { return m_data[1]; }
|
||||
OSL_HOSTDEVICE T& dx () { return m_data[1]; }
|
||||
|
||||
/// Return the partial derivative with respect to y.
|
||||
/// Only valid if there are at least 2 partial dimensions.
|
||||
constexpr const T& dy () const {
|
||||
OSL_HOSTDEVICE constexpr const T& dy () const {
|
||||
static_assert(PARTIALS>=2, "Cannot call dy without at least 2 partials");
|
||||
return m_data[2];
|
||||
}
|
||||
T& dy () {
|
||||
OSL_HOSTDEVICE T& dy () {
|
||||
static_assert(PARTIALS>=2, "Cannot call dy without at least 2 partials");
|
||||
return m_data[2];
|
||||
}
|
||||
|
||||
/// Return the partial derivative with respect to z.
|
||||
/// Only valid if there are at least 3 partial dimensions.
|
||||
constexpr const T& dz () const {
|
||||
OSL_HOSTDEVICE constexpr const T& dz () const {
|
||||
static_assert(PARTIALS>=3, "Cannot call dz without at least 3 partials");
|
||||
return m_data[3];
|
||||
}
|
||||
T& dz () {
|
||||
OSL_HOSTDEVICE T& dz () {
|
||||
static_assert(PARTIALS>=3, "Cannot call dz without at least 3 partials");
|
||||
return m_data[3];
|
||||
}
|
||||
|
||||
/// Clear the derivatives; leave the value alone.
|
||||
void clear_d () {
|
||||
OSL_HOSTDEVICE void clear_d () {
|
||||
for (int i = 1; i <= PARTIALS; ++i)
|
||||
m_data[i] = T(0.0);
|
||||
}
|
||||
|
||||
/// Return the i-th partial derivative.
|
||||
constexpr const T& partial (int i) const {
|
||||
OSL_HOSTDEVICE constexpr const T& partial (int i) const {
|
||||
return m_data[i+1];
|
||||
}
|
||||
|
||||
/// Return a mutable reference to the i-th partial derivative.
|
||||
/// Use with caution!
|
||||
T& partial (int i) {
|
||||
OSL_HOSTDEVICE T& partial (int i) {
|
||||
return m_data[i+1];
|
||||
}
|
||||
|
||||
/// Assignment of a real (the derivs are implicitly 0).
|
||||
const Dual & operator= (const T &x) {
|
||||
OSL_HOSTDEVICE const Dual & operator= (const T &x) {
|
||||
m_data[0] = x;
|
||||
for (int i = 1; i <= PARTIALS; ++i)
|
||||
m_data[i] = T(0);
|
||||
@@ -172,8 +175,8 @@ public:
|
||||
|
||||
/// Access like an array -- be careful! Element 0 is the main value,
|
||||
/// elements [1..PARTIALS] are the infinitessimals.
|
||||
constexpr const T& elem (int i) const { return m_data[i]; }
|
||||
T& elem (int i) { return m_data[i]; }
|
||||
OSL_HOSTDEVICE constexpr const T& elem (int i) const { return m_data[i]; }
|
||||
OSL_HOSTDEVICE T& elem (int i) { return m_data[i]; }
|
||||
|
||||
/// Stream output. Format as: "val[dx,dy,...]"
|
||||
///
|
||||
@@ -217,7 +220,7 @@ template<class T> using Dual2 = Dual<T,2>;
|
||||
/// Addition of duals.
|
||||
///
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P> operator+ (const Dual<T,P> &a, const Dual<T,P> &b)
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P> operator+ (const Dual<T,P> &a, const Dual<T,P> &b)
|
||||
{
|
||||
Dual<T,P> result = a;
|
||||
for (int i = 0; i <= P; ++i)
|
||||
@@ -227,7 +230,7 @@ inline OIIO_CONSTEXPR14 Dual<T,P> operator+ (const Dual<T,P> &a, const Dual<T,P>
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P> operator+ (const Dual<T,P> &a, const T &b)
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P> operator+ (const Dual<T,P> &a, const T &b)
|
||||
{
|
||||
Dual<T,P> result = a;
|
||||
result.val() += b;
|
||||
@@ -236,7 +239,7 @@ inline OIIO_CONSTEXPR14 Dual<T,P> operator+ (const Dual<T,P> &a, const T &b)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P> operator+ (const T &a, const Dual<T,P> &b)
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P> operator+ (const T &a, const Dual<T,P> &b)
|
||||
{
|
||||
Dual<T,P> result = b;
|
||||
result.val() += a;
|
||||
@@ -245,7 +248,7 @@ inline OIIO_CONSTEXPR14 Dual<T,P> operator+ (const T &a, const Dual<T,P> &b)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P>& operator+= (Dual<T,P> &a, const Dual<T,P> &b)
|
||||
OSL_HOSTDEVICE inline Dual<T,P>& operator+= (Dual<T,P> &a, const Dual<T,P> &b)
|
||||
{
|
||||
for (int i = 0; i <= P; ++i)
|
||||
a.elem(i) += b.elem(i);
|
||||
@@ -254,7 +257,7 @@ inline Dual<T,P>& operator+= (Dual<T,P> &a, const Dual<T,P> &b)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P>& operator+= (Dual<T,P> &a, const T &b)
|
||||
OSL_HOSTDEVICE inline Dual<T,P>& operator+= (Dual<T,P> &a, const T &b)
|
||||
{
|
||||
a.val() += b;
|
||||
return a;
|
||||
@@ -264,7 +267,7 @@ inline Dual<T,P>& operator+= (Dual<T,P> &a, const T &b)
|
||||
/// Subtraction of duals.
|
||||
///
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P> operator- (const Dual<T,P> &a, const Dual<T,P> &b)
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P> operator- (const Dual<T,P> &a, const Dual<T,P> &b)
|
||||
{
|
||||
Dual<T,P> result;
|
||||
for (int i = 0; i <= P; ++i)
|
||||
@@ -274,7 +277,7 @@ inline OIIO_CONSTEXPR14 Dual<T,P> operator- (const Dual<T,P> &a, const Dual<T,P>
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P> operator- (const Dual<T,P> &a, const T &b)
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P> operator- (const Dual<T,P> &a, const T &b)
|
||||
{
|
||||
Dual<T,P> result = a;
|
||||
result.val() -= b;
|
||||
@@ -283,7 +286,7 @@ inline OIIO_CONSTEXPR14 Dual<T,P> operator- (const Dual<T,P> &a, const T &b)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P> operator- (const T &a, const Dual<T,P> &b)
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P> operator- (const T &a, const Dual<T,P> &b)
|
||||
{
|
||||
Dual<T,P> result;
|
||||
result.val() = a - b.val();
|
||||
@@ -294,7 +297,7 @@ inline OIIO_CONSTEXPR14 Dual<T,P> operator- (const T &a, const Dual<T,P> &b)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P>& operator-= (Dual<T,P> &a, const Dual<T,P> &b)
|
||||
OSL_HOSTDEVICE inline Dual<T,P>& operator-= (Dual<T,P> &a, const Dual<T,P> &b)
|
||||
{
|
||||
for (int i = 0; i <= P; ++i)
|
||||
a.elem(i) -= b.elem(i);
|
||||
@@ -303,7 +306,7 @@ inline Dual<T,P>& operator-= (Dual<T,P> &a, const Dual<T,P> &b)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P>& operator-= (Dual<T,P> &a, const T &b)
|
||||
OSL_HOSTDEVICE inline Dual<T,P>& operator-= (Dual<T,P> &a, const T &b)
|
||||
{
|
||||
a.val() -= b.val();
|
||||
return a;
|
||||
@@ -314,7 +317,7 @@ inline Dual<T,P>& operator-= (Dual<T,P> &a, const T &b)
|
||||
/// Negation of duals.
|
||||
///
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P> operator- (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P> operator- (const Dual<T,P> &a)
|
||||
{
|
||||
Dual<T,P> result;
|
||||
for (int i = 0; i <= P; ++i)
|
||||
@@ -326,7 +329,7 @@ inline OIIO_CONSTEXPR14 Dual<T,P> operator- (const Dual<T,P> &a)
|
||||
/// Multiplication of duals. This will work for any Dual<T>*Dual<S>
|
||||
/// where T*S is meaningful.
|
||||
template<class T, int P, class S>
|
||||
inline OIIO_CONSTEXPR14 auto
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 auto
|
||||
operator* (const Dual<T,P> &a, const Dual<S,P> &b) -> Dual<decltype(a.elem(0)*b.elem(0)),P>
|
||||
{
|
||||
// Use the chain rule
|
||||
@@ -342,7 +345,7 @@ operator* (const Dual<T,P> &a, const Dual<S,P> &b) -> Dual<decltype(a.elem(0)*b.
|
||||
/// Dual<T> * S where T*S is meaningful.
|
||||
template<class T, int P, class S,
|
||||
DUAL_REQUIRES(is_Dual<S>::value == false)>
|
||||
inline OIIO_CONSTEXPR14 auto
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 auto
|
||||
operator* (const Dual<T,P> &a, const S &b) -> Dual<decltype(a.elem(0)*b),P>
|
||||
{
|
||||
Dual<decltype(a.elem(0)*b),P> result;
|
||||
@@ -356,7 +359,7 @@ operator* (const Dual<T,P> &a, const S &b) -> Dual<decltype(a.elem(0)*b),P>
|
||||
///
|
||||
template<class T, int P, class S,
|
||||
DUAL_REQUIRES(is_Dual<S>::value == false)>
|
||||
inline const Dual<T,P>& operator*= (Dual<T,P> &a, const S &b)
|
||||
OSL_HOSTDEVICE inline const Dual<T,P>& operator*= (Dual<T,P> &a, const S &b)
|
||||
{
|
||||
for (int i = 0; i <= P; ++i)
|
||||
a.elem(i) *= b;
|
||||
@@ -369,7 +372,7 @@ inline const Dual<T,P>& operator*= (Dual<T,P> &a, const S &b)
|
||||
/// Dual<T> * S where T*S is meaningful.
|
||||
template<class T, int P, class S,
|
||||
DUAL_REQUIRES(is_Dual<S>::value == false)>
|
||||
inline OIIO_CONSTEXPR14 auto
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 auto
|
||||
operator* (const S &b, const Dual<T,P> &a) -> Dual<decltype(a.elem(0)*b),P>
|
||||
{
|
||||
return a*b;
|
||||
@@ -380,7 +383,7 @@ operator* (const S &b, const Dual<T,P> &a) -> Dual<decltype(a.elem(0)*b),P>
|
||||
/// Division of duals.
|
||||
///
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P> operator/ (const Dual<T,P> &a, const Dual<T,P> &b)
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P> operator/ (const Dual<T,P> &a, const Dual<T,P> &b)
|
||||
{
|
||||
T bvalinv = 1.0f / b.val();
|
||||
T aval_bval = a.val() * bvalinv;
|
||||
@@ -395,7 +398,7 @@ inline OIIO_CONSTEXPR14 Dual<T,P> operator/ (const Dual<T,P> &a, const Dual<T,P>
|
||||
/// Division of dual by scalar.
|
||||
///
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P> operator/ (const Dual<T,P> &a, const T &b)
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P> operator/ (const Dual<T,P> &a, const T &b)
|
||||
{
|
||||
T binv = 1.0f / b;
|
||||
return a * binv;
|
||||
@@ -405,7 +408,7 @@ inline OIIO_CONSTEXPR14 Dual<T,P> operator/ (const Dual<T,P> &a, const T &b)
|
||||
/// Division of scalar by dual.
|
||||
///
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P> operator/ (const T &aval, const Dual<T,P> &b)
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P> operator/ (const T &aval, const Dual<T,P> &b)
|
||||
{
|
||||
T bvalinv = 1.0f / b.val();
|
||||
T aval_bval = aval * bvalinv;
|
||||
@@ -420,75 +423,75 @@ inline OIIO_CONSTEXPR14 Dual<T,P> operator/ (const T &aval, const Dual<T,P> &b)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline constexpr bool operator< (const Dual<T,P> &a, const Dual<T,P> &b) {
|
||||
OSL_HOSTDEVICE inline constexpr bool operator< (const Dual<T,P> &a, const Dual<T,P> &b) {
|
||||
return a.val() < b.val();
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline constexpr bool operator< (const Dual<T,P> &a, const T &b) {
|
||||
OSL_HOSTDEVICE inline constexpr bool operator< (const Dual<T,P> &a, const T &b) {
|
||||
return a.val() < b;
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline constexpr bool operator> (const Dual<T,P> &a, const Dual<T,P> &b) {
|
||||
OSL_HOSTDEVICE inline constexpr bool operator> (const Dual<T,P> &a, const Dual<T,P> &b) {
|
||||
return a.val() > b.val();
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline constexpr bool operator> (const Dual<T,P> &a, const T &b) {
|
||||
OSL_HOSTDEVICE inline constexpr bool operator> (const Dual<T,P> &a, const T &b) {
|
||||
return a.val() > b;
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline constexpr bool operator<= (const Dual<T,P> &a, const Dual<T,P> &b) {
|
||||
OSL_HOSTDEVICE inline constexpr bool operator<= (const Dual<T,P> &a, const Dual<T,P> &b) {
|
||||
return a.val() <= b.val();
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline constexpr bool operator<= (const Dual<T,P> &a, const T &b) {
|
||||
OSL_HOSTDEVICE inline constexpr bool operator<= (const Dual<T,P> &a, const T &b) {
|
||||
return a.val() <= b;
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline constexpr bool operator>= (const Dual<T,P> &a, const Dual<T,P> &b) {
|
||||
OSL_HOSTDEVICE inline constexpr bool operator>= (const Dual<T,P> &a, const Dual<T,P> &b) {
|
||||
return a.val() >= b.val();
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline constexpr bool operator>= (const Dual<T,P> &a, const T &b) {
|
||||
OSL_HOSTDEVICE inline constexpr bool operator>= (const Dual<T,P> &a, const T &b) {
|
||||
return a.val() >= b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Eliminate the derivatives of a number, works for scalar as well as Dual.
|
||||
template<class T> inline constexpr const T&
|
||||
template<class T> OSL_HOSTDEVICE inline constexpr const T&
|
||||
removeDerivatives (const T &x) { return x; }
|
||||
|
||||
template<class T, int P> inline constexpr const T&
|
||||
template<class T, int P> OSL_HOSTDEVICE inline constexpr const T&
|
||||
removeDerivatives (const Dual<T,P> &x) { return x.val(); }
|
||||
|
||||
|
||||
// Get the x derivative (or 0 for a non-Dual)
|
||||
template<class T> inline constexpr const T&
|
||||
template<class T> OSL_HOSTDEVICE inline constexpr const T&
|
||||
getXDerivative (const T &x) { return T(0); }
|
||||
|
||||
template<class T, int P> inline constexpr const T&
|
||||
template<class T, int P> OSL_HOSTDEVICE inline constexpr const T&
|
||||
getXDerivative (const Dual<T,P> &x) { return x.partial(0); }
|
||||
|
||||
|
||||
// Get the y derivative (or 0 for a non-Dual)
|
||||
template<class T> inline constexpr const T&
|
||||
template<class T> OSL_HOSTDEVICE inline constexpr const T&
|
||||
getYDerivative (const T &x) { return T(0); }
|
||||
|
||||
template<class T, int P> inline constexpr const T&
|
||||
template<class T, int P> OSL_HOSTDEVICE inline constexpr const T&
|
||||
getYDerivative (const Dual<T,P> &x) { return x.partial(1); }
|
||||
|
||||
|
||||
// Simple templated "copy" function
|
||||
template<class T> inline void
|
||||
template<class T> OSL_HOSTDEVICE inline void
|
||||
assignment (T &a, T &b) { a = b; }
|
||||
template<class T, int P> inline void
|
||||
template<class T, int P> OSL_HOSTDEVICE inline void
|
||||
assignment (T &a, Dual<T,P> &b) { a = b.val(); }
|
||||
|
||||
// Templated value equality. For scalars, it's the same as regular ==.
|
||||
@@ -497,22 +500,22 @@ assignment (T &a, Dual<T,P> &b) { a = b.val(); }
|
||||
// return if just their value is equal or if the whole struct (including
|
||||
// derivs) are equal.
|
||||
template<class T>
|
||||
inline constexpr bool equalVal (const T &x, const T &y) {
|
||||
OSL_HOSTDEVICE inline constexpr bool equalVal (const T &x, const T &y) {
|
||||
return x == y;
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline constexpr bool equalVal (const Dual<T,P> &x, const Dual<T,P> &y) {
|
||||
OSL_HOSTDEVICE inline constexpr bool equalVal (const Dual<T,P> &x, const Dual<T,P> &y) {
|
||||
return x.val() == y.val();
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline constexpr bool equalVal (const Dual<T,P> &x, const T &y) {
|
||||
OSL_HOSTDEVICE inline constexpr bool equalVal (const Dual<T,P> &x, const T &y) {
|
||||
return x.val() == y;
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline constexpr bool equalVal (const T &x, const Dual<T,P> &y) {
|
||||
OSL_HOSTDEVICE inline constexpr bool equalVal (const T &x, const Dual<T,P> &y) {
|
||||
return x == y.val();
|
||||
}
|
||||
|
||||
@@ -523,7 +526,7 @@ inline constexpr bool equalVal (const T &x, const Dual<T,P> &y) {
|
||||
// function f(scalar), then the dual function F(<u,u'>) is defined as:
|
||||
// F(<u,u'>) = < f(u), f'(u)*u' >
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
dualfunc (const Dual<T,P>& u, const T& f_val, const T& df_val)
|
||||
{
|
||||
Dual<T,P> result;
|
||||
@@ -539,7 +542,7 @@ dualfunc (const Dual<T,P>& u, const T& f_val, const T& df_val)
|
||||
// F(<u,u'>, <v,v'>) = < f(u,v), dfdu(u,v)u' + dfdv(u,v)v' >
|
||||
// (from http://en.wikipedia.org/wiki/Automatic_differentiation)
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
dualfunc (const Dual<T,P>& u, const Dual<T,P>& v,
|
||||
const T& f_val, const T& dfdu_val, const T& dfdv_val)
|
||||
{
|
||||
@@ -553,7 +556,7 @@ dualfunc (const Dual<T,P>& u, const Dual<T,P>& v,
|
||||
|
||||
// Helper for construction the result of a Dual function of three variables.
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
dualfunc (const Dual<T,P>& u, const Dual<T,P>& v, const Dual<T,P>& w,
|
||||
const T& f_val, const T& dfdu_val, const T& dfdv_val, const T& dfdw_val)
|
||||
{
|
||||
@@ -568,7 +571,7 @@ dualfunc (const Dual<T,P>& u, const Dual<T,P>& v, const Dual<T,P>& w,
|
||||
|
||||
// f(x) = cos(x), f'(x) = -sin(x)
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> cos (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> cos (const Dual<T,P> &a)
|
||||
{
|
||||
T sina, cosa;
|
||||
OIIO::sincos(a.val(), &sina, &cosa);
|
||||
@@ -576,7 +579,7 @@ inline Dual<T,P> cos (const Dual<T,P> &a)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fast_cos(const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fast_cos(const Dual<T,P> &a)
|
||||
{
|
||||
T sina, cosa;
|
||||
OIIO::fast_sincos (a.val(), &sina, &cosa);
|
||||
@@ -585,7 +588,7 @@ inline Dual<T,P> fast_cos(const Dual<T,P> &a)
|
||||
|
||||
// f(x) = sin(x), f'(x) = cos(x)
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> sin (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> sin (const Dual<T,P> &a)
|
||||
{
|
||||
T sina, cosa;
|
||||
OIIO::sincos(a.val(), &sina, &cosa);
|
||||
@@ -593,7 +596,7 @@ inline Dual<T,P> sin (const Dual<T,P> &a)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fast_sin(const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fast_sin(const Dual<T,P> &a)
|
||||
{
|
||||
T sina, cosa;
|
||||
OIIO::fast_sincos (a.val(), &sina, &cosa);
|
||||
@@ -601,7 +604,7 @@ inline Dual<T,P> fast_sin(const Dual<T,P> &a)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline void sincos(const Dual<T,P> &a, Dual<T,P> *sine, Dual<T,P> *cosine)
|
||||
OSL_HOSTDEVICE inline void sincos(const Dual<T,P> &a, Dual<T,P> *sine, Dual<T,P> *cosine)
|
||||
{
|
||||
T sina, cosa;
|
||||
OIIO::sincos(a.val(), &sina, &cosa);
|
||||
@@ -610,7 +613,7 @@ inline void sincos(const Dual<T,P> &a, Dual<T,P> *sine, Dual<T,P> *cosine)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline void fast_sincos(const Dual<T,P> &a, Dual<T,P> *sine, Dual<T,P> *cosine)
|
||||
OSL_HOSTDEVICE inline void fast_sincos(const Dual<T,P> &a, Dual<T,P> *sine, Dual<T,P> *cosine)
|
||||
{
|
||||
T sina, cosa;
|
||||
OIIO::fast_sincos(a.val(), &sina, &cosa);
|
||||
@@ -620,7 +623,7 @@ inline void fast_sincos(const Dual<T,P> &a, Dual<T,P> *sine, Dual<T,P> *cosine)
|
||||
|
||||
// f(x) = tan(x), f'(x) = sec^2(x)
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> tan (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> tan (const Dual<T,P> &a)
|
||||
{
|
||||
T tana = std::tan (a.val());
|
||||
T cosa = std::cos (a.val());
|
||||
@@ -629,7 +632,7 @@ inline Dual<T,P> tan (const Dual<T,P> &a)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fast_tan(const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fast_tan(const Dual<T,P> &a)
|
||||
{
|
||||
T tana = OIIO::fast_tan (a.val());
|
||||
T cosa = OIIO::fast_cos (a.val());
|
||||
@@ -639,7 +642,7 @@ inline Dual<T,P> fast_tan(const Dual<T,P> &a)
|
||||
|
||||
// f(x) = cosh(x), f'(x) = sinh(x)
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> cosh (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> cosh (const Dual<T,P> &a)
|
||||
{
|
||||
T f = std::cosh(a.val());
|
||||
T df = std::sinh(a.val());
|
||||
@@ -647,7 +650,7 @@ inline Dual<T,P> cosh (const Dual<T,P> &a)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fast_cosh(const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fast_cosh(const Dual<T,P> &a)
|
||||
{
|
||||
T f = OIIO::fast_cosh(a.val());
|
||||
T df = OIIO::fast_sinh(a.val());
|
||||
@@ -657,7 +660,7 @@ inline Dual<T,P> fast_cosh(const Dual<T,P> &a)
|
||||
|
||||
// f(x) = sinh(x), f'(x) = cosh(x)
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> sinh (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> sinh (const Dual<T,P> &a)
|
||||
{
|
||||
T f = std::sinh(a.val());
|
||||
T df = std::cosh(a.val());
|
||||
@@ -665,7 +668,7 @@ inline Dual<T,P> sinh (const Dual<T,P> &a)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fast_sinh(const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fast_sinh(const Dual<T,P> &a)
|
||||
{
|
||||
T f = OIIO::fast_sinh(a.val());
|
||||
T df = OIIO::fast_cosh(a.val());
|
||||
@@ -674,7 +677,7 @@ inline Dual<T,P> fast_sinh(const Dual<T,P> &a)
|
||||
|
||||
// f(x) = tanh(x), f'(x) = sech^2(x)
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> tanh (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> tanh (const Dual<T,P> &a)
|
||||
{
|
||||
T tanha = std::tanh(a.val());
|
||||
T cosha = std::cosh(a.val());
|
||||
@@ -683,7 +686,7 @@ inline Dual<T,P> tanh (const Dual<T,P> &a)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fast_tanh(const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fast_tanh(const Dual<T,P> &a)
|
||||
{
|
||||
T tanha = OIIO::fast_tanh(a.val());
|
||||
T cosha = OIIO::fast_cosh(a.val());
|
||||
@@ -693,7 +696,7 @@ inline Dual<T,P> fast_tanh(const Dual<T,P> &a)
|
||||
|
||||
// f(x) = acos(x), f'(x) = -1/(sqrt(1 - x^2))
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> safe_acos (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> safe_acos (const Dual<T,P> &a)
|
||||
{
|
||||
if (a.val() >= T(1))
|
||||
return Dual<T,P> (T(0));
|
||||
@@ -705,7 +708,7 @@ inline Dual<T,P> safe_acos (const Dual<T,P> &a)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fast_acos(const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fast_acos(const Dual<T,P> &a)
|
||||
{
|
||||
T f = OIIO::fast_acos(a.val());
|
||||
T df = fabsf(a.val()) < 1.0f ? -1.0f / sqrtf(1.0f - a.val() * a.val()) : 0.0f;
|
||||
@@ -714,7 +717,7 @@ inline Dual<T,P> fast_acos(const Dual<T,P> &a)
|
||||
|
||||
// f(x) = asin(x), f'(x) = 1/(sqrt(1 - x^2))
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> safe_asin (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> safe_asin (const Dual<T,P> &a)
|
||||
{
|
||||
if (a.val() >= T(1))
|
||||
return Dual<T,P> (T(M_PI/2));
|
||||
@@ -726,7 +729,7 @@ inline Dual<T,P> safe_asin (const Dual<T,P> &a)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fast_asin(const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fast_asin(const Dual<T,P> &a)
|
||||
{
|
||||
T f = OIIO::fast_asin(a.val());
|
||||
T df = fabsf(a.val()) < 1.0f ? 1.0f / sqrtf(1.0f - a.val() * a.val()) : 0.0f;
|
||||
@@ -736,7 +739,7 @@ inline Dual<T,P> fast_asin(const Dual<T,P> &a)
|
||||
|
||||
// f(x) = atan(x), f'(x) = 1/(1 + x^2)
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> atan (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> atan (const Dual<T,P> &a)
|
||||
{
|
||||
T f = std::atan (a.val());
|
||||
T df = T(1) / (T(1) + a.val()*a.val());
|
||||
@@ -744,7 +747,7 @@ inline Dual<T,P> atan (const Dual<T,P> &a)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fast_atan(const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fast_atan(const Dual<T,P> &a)
|
||||
{
|
||||
T f = OIIO::fast_atan(a.val());
|
||||
T df = 1.0f / (1.0f + a.val() * a.val());
|
||||
@@ -756,7 +759,7 @@ inline Dual<T,P> fast_atan(const Dual<T,P> &a)
|
||||
// reference: http://en.wikipedia.org/wiki/Atan2
|
||||
// (above link has other formulations)
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> atan2 (const Dual<T,P> &y, const Dual<T,P> &x)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> atan2 (const Dual<T,P> &y, const Dual<T,P> &x)
|
||||
{
|
||||
T atan2xy = std::atan2 (y.val(), x.val());
|
||||
T denom = (x.val() == T(0) && y.val() == T(0)) ? T(0) : T(1) / (x.val()*x.val() + y.val()*y.val());
|
||||
@@ -764,7 +767,7 @@ inline Dual<T,P> atan2 (const Dual<T,P> &y, const Dual<T,P> &x)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fast_atan2(const Dual<T,P> &y, const Dual<T,P> &x)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fast_atan2(const Dual<T,P> &y, const Dual<T,P> &x)
|
||||
{
|
||||
T atan2xy = OIIO::fast_atan2(y.val(), x.val());
|
||||
T denom = (x.val() == 0 && y.val() == 0) ? 0.0f : 1.0f / (x.val() * x.val() + y.val() * y.val());
|
||||
@@ -779,7 +782,7 @@ inline Dual<T,P> fast_atan2(const Dual<T,P> &y, const Dual<T,P> &x)
|
||||
// (from http://en.wikipedia.org/wiki/Automatic_differentiation)
|
||||
// so, pow(u,v) = < u^v, vu^(v-1) u' + log(u)u^v v' >
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> safe_pow (const Dual<T,P> &u, const Dual<T,P> &v)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> safe_pow (const Dual<T,P> &u, const Dual<T,P> &v)
|
||||
{
|
||||
// NOTE: this function won't return exactly the same as pow(x,y) because we
|
||||
// use the identity u^v=u * u^(v-1) which does not hold in all cases for our
|
||||
@@ -791,7 +794,7 @@ inline Dual<T,P> safe_pow (const Dual<T,P> &u, const Dual<T,P> &v)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fast_safe_pow(const Dual<T,P> &u, const Dual<T,P> &v)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fast_safe_pow(const Dual<T,P> &u, const Dual<T,P> &v)
|
||||
{
|
||||
// NOTE: same issue as above (fast_safe_pow does even more clamping)
|
||||
T powuvm1 = OIIO::fast_safe_pow (u.val(), v.val() - 1.0f);
|
||||
@@ -803,7 +806,7 @@ inline Dual<T,P> fast_safe_pow(const Dual<T,P> &u, const Dual<T,P> &v)
|
||||
// f(x) = log(a), f'(x) = 1/x
|
||||
// (log base e)
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> safe_log (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> safe_log (const Dual<T,P> &a)
|
||||
{
|
||||
T f = safe_log(a.val());
|
||||
T df = a.val() < std::numeric_limits<T>::min() ? T(0) : T(1) / a.val();
|
||||
@@ -811,7 +814,7 @@ inline Dual<T,P> safe_log (const Dual<T,P> &a)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fast_log(const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fast_log(const Dual<T,P> &a)
|
||||
{
|
||||
T f = OIIO::fast_log(a.val());
|
||||
T df = a.val() < std::numeric_limits<float>::min() ? 0.0f : 1.0f / a.val();
|
||||
@@ -821,7 +824,7 @@ inline Dual<T,P> fast_log(const Dual<T,P> &a)
|
||||
// f(x) = log2(x), f'(x) = 1/(x*log2)
|
||||
// (log base 2)
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> safe_log2 (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> safe_log2 (const Dual<T,P> &a)
|
||||
{
|
||||
T f = safe_log2(a.val());
|
||||
T df = a.val() < std::numeric_limits<T>::min() ? T(0) : T(1) / (a.val() * T(M_LN2));
|
||||
@@ -829,7 +832,7 @@ inline Dual<T,P> safe_log2 (const Dual<T,P> &a)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fast_log2(const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fast_log2(const Dual<T,P> &a)
|
||||
{
|
||||
T f = OIIO::fast_log2(a.val());
|
||||
T aln2 = a.val() * float(M_LN2);
|
||||
@@ -840,7 +843,7 @@ inline Dual<T,P> fast_log2(const Dual<T,P> &a)
|
||||
// f(x) = log10(x), f'(x) = 1/(x*log10)
|
||||
// (log base 10)
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> safe_log10 (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> safe_log10 (const Dual<T,P> &a)
|
||||
{
|
||||
T f = safe_log10(a.val());
|
||||
T df = a.val() < std::numeric_limits<T>::min() ? T(0) : T(1) / (a.val() * T(M_LN10));
|
||||
@@ -848,7 +851,7 @@ inline Dual<T,P> safe_log10 (const Dual<T,P> &a)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fast_log10(const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fast_log10(const Dual<T,P> &a)
|
||||
{
|
||||
T f = OIIO::fast_log10(a.val());
|
||||
T aln10 = a.val() * float(M_LN10);
|
||||
@@ -858,14 +861,14 @@ inline Dual<T,P> fast_log10(const Dual<T,P> &a)
|
||||
|
||||
// f(x) = e^x, f'(x) = e^x
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> exp (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> exp (const Dual<T,P> &a)
|
||||
{
|
||||
T f = std::exp(a.val());
|
||||
return dualfunc (a, f, f);
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fast_exp(const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fast_exp(const Dual<T,P> &a)
|
||||
{
|
||||
T f = OIIO::fast_exp(a.val());
|
||||
return dualfunc (a, f, f);
|
||||
@@ -873,7 +876,7 @@ inline Dual<T,P> fast_exp(const Dual<T,P> &a)
|
||||
|
||||
// f(x) = 2^x, f'(x) = (2^x)*log(2)
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> exp2 (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> exp2 (const Dual<T,P> &a)
|
||||
{
|
||||
using std::exp2;
|
||||
T f = exp2(a.val());
|
||||
@@ -881,7 +884,7 @@ inline Dual<T,P> exp2 (const Dual<T,P> &a)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fast_exp2(const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fast_exp2(const Dual<T,P> &a)
|
||||
{
|
||||
T f = OIIO::fast_exp2(float(a.val()));
|
||||
return dualfunc (a, f, f*T(M_LN2));
|
||||
@@ -890,7 +893,7 @@ inline Dual<T,P> fast_exp2(const Dual<T,P> &a)
|
||||
|
||||
// f(x) = e^x - 1, f'(x) = e^x
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> expm1 (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> expm1 (const Dual<T,P> &a)
|
||||
{
|
||||
using std::expm1;
|
||||
T f = expm1(a.val());
|
||||
@@ -899,7 +902,7 @@ inline Dual<T,P> expm1 (const Dual<T,P> &a)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fast_expm1(const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fast_expm1(const Dual<T,P> &a)
|
||||
{
|
||||
T f = OIIO::fast_expm1(a.val());
|
||||
T df = OIIO::fast_exp (a.val());
|
||||
@@ -908,7 +911,7 @@ inline Dual<T,P> fast_expm1(const Dual<T,P> &a)
|
||||
|
||||
// f(x) = erf(x), f'(x) = (2e^(-x^2))/sqrt(pi)
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> erf (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> erf (const Dual<T,P> &a)
|
||||
{
|
||||
using std::erf;
|
||||
T f = erf (a.val());
|
||||
@@ -918,7 +921,7 @@ inline Dual<T,P> erf (const Dual<T,P> &a)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fast_erf(const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fast_erf(const Dual<T,P> &a)
|
||||
{
|
||||
T f = OIIO::fast_erf (float(a.val())); // float version!
|
||||
const T two_over_sqrt_pi = 1.128379167095512573896158903f;
|
||||
@@ -928,7 +931,7 @@ inline Dual<T,P> fast_erf(const Dual<T,P> &a)
|
||||
|
||||
// f(x) = erfc(x), f'(x) = -(2e^(-x^2))/sqrt(pi)
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> erfc (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> erfc (const Dual<T,P> &a)
|
||||
{
|
||||
using std::erfc;
|
||||
T f = erfc (a.val()); // float version!
|
||||
@@ -938,7 +941,7 @@ inline Dual<T,P> erfc (const Dual<T,P> &a)
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fast_erfc(const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fast_erfc(const Dual<T,P> &a)
|
||||
{
|
||||
T f = OIIO::fast_erfc (float(a.val())); // float version!
|
||||
const T two_over_sqrt_pi = -1.128379167095512573896158903f;
|
||||
@@ -949,7 +952,7 @@ inline Dual<T,P> fast_erfc(const Dual<T,P> &a)
|
||||
|
||||
// f(x) = sqrt(x), f'(x) = 1/(2*sqrt(x))
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P> sqrt (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P> sqrt (const Dual<T,P> &a)
|
||||
{
|
||||
if (a.val() <= T(0))
|
||||
return Dual<T,P> (T(0));
|
||||
@@ -960,7 +963,7 @@ inline OIIO_CONSTEXPR14 Dual<T,P> sqrt (const Dual<T,P> &a)
|
||||
|
||||
// f(x) = 1/sqrt(x), f'(x) = -1/(2*x^(3/2))
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> inversesqrt (const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> inversesqrt (const Dual<T,P> &a)
|
||||
{
|
||||
// do we want to print an error message?
|
||||
if (a.val() <= T(0))
|
||||
@@ -972,21 +975,21 @@ inline Dual<T,P> inversesqrt (const Dual<T,P> &a)
|
||||
|
||||
// (fx) = x*(1-a) + y*a, f'(x) = (1-a)x' + (y - x)*a' + a*y'
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> mix (const Dual<T,P> &x, const Dual<T,P> &y, const Dual<T,P> &a)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> mix (const Dual<T,P> &x, const Dual<T,P> &y, const Dual<T,P> &a)
|
||||
{
|
||||
T mixval = x.val()*(T(1)-a.val()) + y.val()*a.val();
|
||||
return dualfunc (x, y, a, mixval, T(1)-a.val(), a.val(), y.val() - x.val());
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> fabs (const Dual<T,P> &x)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> fabs (const Dual<T,P> &x)
|
||||
{
|
||||
return x.val() >= T(0) ? x : -x;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline float smoothstep(float e0, float e1, float x) {
|
||||
OSL_HOSTDEVICE inline float smoothstep(float e0, float e1, float x) {
|
||||
if (x < e0) return 0.0f;
|
||||
else if (x >= e1) return 1.0f;
|
||||
else {
|
||||
@@ -997,7 +1000,7 @@ inline float smoothstep(float e0, float e1, float x) {
|
||||
|
||||
// f(t) = (3-2t)t^2, t = (x-e0)/(e1-e0)
|
||||
template<class T, int P>
|
||||
inline Dual<T,P> smoothstep (const Dual<T,P> &e0, const Dual<T,P> &e1, const Dual<T,P> &x)
|
||||
OSL_HOSTDEVICE inline Dual<T,P> smoothstep (const Dual<T,P> &e0, const Dual<T,P> &e1, const Dual<T,P> &x)
|
||||
{
|
||||
if (x.val() < e0.val()) {
|
||||
return Dual<T,P> (T(0));
|
||||
@@ -1013,7 +1016,7 @@ inline Dual<T,P> smoothstep (const Dual<T,P> &e0, const Dual<T,P> &e1, const Dua
|
||||
|
||||
// ceil(Dual) loses derivatives
|
||||
template<class T, int P>
|
||||
inline constexpr float ceil (const Dual<T,P> &x)
|
||||
OSL_HOSTDEVICE inline constexpr float ceil (const Dual<T,P> &x)
|
||||
{
|
||||
return std::ceil(x.val());
|
||||
}
|
||||
@@ -1021,7 +1024,7 @@ inline constexpr float ceil (const Dual<T,P> &x)
|
||||
|
||||
// floor(Dual) loses derivatives
|
||||
template<class T, int P>
|
||||
inline constexpr float floor (const Dual<T,P> &x)
|
||||
OSL_HOSTDEVICE inline constexpr float floor (const Dual<T,P> &x)
|
||||
{
|
||||
return std::floor(x.val());
|
||||
}
|
||||
@@ -1029,7 +1032,7 @@ inline constexpr float floor (const Dual<T,P> &x)
|
||||
|
||||
// floor, cast to an int.
|
||||
template<class T, int P>
|
||||
inline constexpr int
|
||||
OSL_HOSTDEVICE inline constexpr int
|
||||
ifloor (const Dual<T,P> &x)
|
||||
{
|
||||
return (int)floor(x);
|
||||
|
||||
+25
-25
@@ -78,14 +78,14 @@ template<> struct ScalarFromVec<Dual2<Color3>> { typedef Dual2<Float> type; };
|
||||
|
||||
/// A uniform way to assemble a Vec3 from float and a Dual<Vec3>
|
||||
/// from Dual<float>.
|
||||
inline Vec3
|
||||
OSL_HOSTDEVICE inline Vec3
|
||||
make_Vec3 (float x, float y, float z)
|
||||
{
|
||||
return Vec3 (x, y, z);
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<Imath::Vec3<T>,P>
|
||||
OSL_HOSTDEVICE inline Dual<Imath::Vec3<T>,P>
|
||||
make_Vec3 (const Dual<T,P> &x, const Dual<T,P> &y, const Dual<T,P> &z)
|
||||
{
|
||||
Dual<Imath::Vec3<T>,P> result;
|
||||
@@ -98,7 +98,7 @@ make_Vec3 (const Dual<T,P> &x, const Dual<T,P> &y, const Dual<T,P> &z)
|
||||
/// Make a Dual<Vec3> from a single Dual<Float> x coordinate, and 0
|
||||
/// for the other components.
|
||||
template<class T, int P>
|
||||
inline Dual<Imath::Vec3<T>,P>
|
||||
OSL_HOSTDEVICE inline Dual<Imath::Vec3<T>,P>
|
||||
make_Vec3 (const Dual<T,P> &x)
|
||||
{
|
||||
Dual<Imath::Vec3<T>,P> result;
|
||||
@@ -109,7 +109,7 @@ make_Vec3 (const Dual<T,P> &x)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<Imath::Vec3<T>,P>
|
||||
OSL_HOSTDEVICE inline Dual<Imath::Vec3<T>,P>
|
||||
make_Vec3 (const Dual<T,P> &x, const Dual<T,P> &y)
|
||||
{
|
||||
Dual<Imath::Vec3<T>,P> result;
|
||||
@@ -122,14 +122,14 @@ make_Vec3 (const Dual<T,P> &x, const Dual<T,P> &y)
|
||||
|
||||
/// A uniform way to assemble a Color3 from float and a Dual<Color3>
|
||||
/// from Dual<float>.
|
||||
inline Color3
|
||||
OSL_HOSTDEVICE inline Color3
|
||||
make_Color3 (float x, float y, float z)
|
||||
{
|
||||
return Color3 (x, y, z);
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<Imath::Color3<T>,P>
|
||||
OSL_HOSTDEVICE inline Dual<Imath::Color3<T>,P>
|
||||
make_Color3 (const Dual<T,P> &x, const Dual<T,P> &y, const Dual<T,P> &z)
|
||||
{
|
||||
Dual<Imath::Color3<T>,P> result;
|
||||
@@ -142,14 +142,14 @@ make_Color3 (const Dual<T,P> &x, const Dual<T,P> &y, const Dual<T,P> &z)
|
||||
|
||||
/// A uniform way to assemble a Vec2 from float and a Dual<Vec2>
|
||||
/// from Dual<float>.
|
||||
inline Vec2
|
||||
OSL_HOSTDEVICE inline Vec2
|
||||
make_Vec2 (float x, float y)
|
||||
{
|
||||
return Vec2 (x, y);
|
||||
}
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<Imath::Vec2<T>,P>
|
||||
OSL_HOSTDEVICE inline Dual<Imath::Vec2<T>,P>
|
||||
make_Vec2 (const Dual<T,P> &x, const Dual<T,P> &y)
|
||||
{
|
||||
Dual<Imath::Vec2<T>,P> result;
|
||||
@@ -167,7 +167,7 @@ make_Vec2 (const Dual<T,P> &x, const Dual<T,P> &y)
|
||||
/// comp(Dual<Vec3>,c) returns a Dual<float> of the c-th component (with
|
||||
/// derivs).
|
||||
|
||||
inline float
|
||||
OSL_HOSTDEVICE inline float
|
||||
comp (const Vec3 &v, int c)
|
||||
{
|
||||
return v[c];
|
||||
@@ -175,7 +175,7 @@ comp (const Vec3 &v, int c)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
comp (const Dual<Imath::Vec3<T>,P> &v, int c)
|
||||
{
|
||||
Dual<T,P> result;
|
||||
@@ -187,7 +187,7 @@ comp (const Dual<Imath::Vec3<T>,P> &v, int c)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
comp (const Dual<Imath::Color3<T>,P> &v, int c)
|
||||
{
|
||||
Dual<T,P> result;
|
||||
@@ -197,7 +197,7 @@ comp (const Dual<Imath::Color3<T>,P> &v, int c)
|
||||
}
|
||||
|
||||
|
||||
inline float
|
||||
OSL_HOSTDEVICE inline float
|
||||
comp (const Vec2 &v, int c)
|
||||
{
|
||||
return v[c];
|
||||
@@ -205,7 +205,7 @@ comp (const Vec2 &v, int c)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
comp (const Dual<Imath::Vec2<T>,P> &v, int c)
|
||||
{
|
||||
Dual<T,P> result;
|
||||
@@ -334,7 +334,7 @@ multDirMatrix (const Imath::Matrix44<S> &M,
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
dot (const Dual<Imath::Vec3<T>,P> &a, const Dual<Imath::Vec3<T>,P> &b)
|
||||
{
|
||||
auto ax = comp (a, 0);
|
||||
@@ -349,7 +349,7 @@ dot (const Dual<Imath::Vec3<T>,P> &a, const Dual<Imath::Vec3<T>,P> &b)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
dot (const Dual<Imath::Vec3<T>,P> &a, const Imath::Vec3<T> &b)
|
||||
{
|
||||
auto ax = comp (a, 0);
|
||||
@@ -364,7 +364,7 @@ dot (const Dual<Imath::Vec3<T>,P> &a, const Imath::Vec3<T> &b)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
dot (const Imath::Vec3<T> &a, const Dual<Imath::Vec3<T>,P> &b)
|
||||
{
|
||||
return dot (b, a);
|
||||
@@ -373,7 +373,7 @@ dot (const Imath::Vec3<T> &a, const Dual<Imath::Vec3<T>,P> &b)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
dot (const Dual<Imath::Vec2<T>,P> &a, const Dual<Imath::Vec2<T>,P> &b)
|
||||
{
|
||||
auto ax = comp (a, 0);
|
||||
@@ -386,7 +386,7 @@ dot (const Dual<Imath::Vec2<T>,P> &a, const Dual<Imath::Vec2<T>,P> &b)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
dot (const Dual<Imath::Vec2<T>,P> &a, const Vec2 &b)
|
||||
{
|
||||
auto ax = comp (a, 0);
|
||||
@@ -399,7 +399,7 @@ dot (const Dual<Imath::Vec2<T>,P> &a, const Vec2 &b)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
dot (const Vec2 &a, const Dual<Imath::Vec2<T>,P> &b)
|
||||
{
|
||||
auto ax = comp (a, 0);
|
||||
@@ -412,7 +412,7 @@ dot (const Vec2 &a, const Dual<Imath::Vec2<T>,P> &b)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<Imath::Vec3<T>,P>
|
||||
OSL_HOSTDEVICE inline Dual<Imath::Vec3<T>,P>
|
||||
cross (const Dual<Imath::Vec3<T>,P> &a, const Dual<Imath::Vec3<T>,P> &b)
|
||||
{
|
||||
auto ax = comp (a, 0);
|
||||
@@ -430,7 +430,7 @@ cross (const Dual<Imath::Vec3<T>,P> &a, const Dual<Imath::Vec3<T>,P> &b)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
OSL_HOSTDEVICE inline OIIO_CONSTEXPR14 Dual<T,P>
|
||||
length (const Dual<Imath::Vec3<T>,P> &a)
|
||||
{
|
||||
auto ax = comp (a, 0);
|
||||
@@ -442,7 +442,7 @@ length (const Dual<Imath::Vec3<T>,P> &a)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<Imath::Vec3<T>,P>
|
||||
OSL_HOSTDEVICE inline Dual<Imath::Vec3<T>,P>
|
||||
normalize (const Dual<Imath::Vec3<T>,P> &a)
|
||||
{
|
||||
auto ax = comp (a, 0);
|
||||
@@ -463,7 +463,7 @@ normalize (const Dual<Imath::Vec3<T>,P> &a)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P>
|
||||
OSL_HOSTDEVICE inline Dual<T,P>
|
||||
distance (const Dual<Imath::Vec3<T>,P> &a, const Dual<Imath::Vec3<T>,P> &b)
|
||||
{
|
||||
return length (a - b);
|
||||
@@ -471,7 +471,7 @@ distance (const Dual<Imath::Vec3<T>,P> &a, const Dual<Imath::Vec3<T>,P> &b)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P>
|
||||
OSL_HOSTDEVICE inline Dual<T,P>
|
||||
distance (const Dual<Imath::Vec3<T>,P> &a, const Imath::Vec3<T> &b)
|
||||
{
|
||||
return length (a - b);
|
||||
@@ -479,7 +479,7 @@ distance (const Dual<Imath::Vec3<T>,P> &a, const Imath::Vec3<T> &b)
|
||||
|
||||
|
||||
template<class T, int P>
|
||||
inline Dual<T,P>
|
||||
OSL_HOSTDEVICE inline Dual<T,P>
|
||||
distance (const Imath::Vec3<T> &a, const Dual<Imath::Vec3<T>,P> &b)
|
||||
{
|
||||
return length (a - b);
|
||||
|
||||
@@ -103,3 +103,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#else
|
||||
# define OSLQUERYPUBLIC OSL_DLL_IMPORT
|
||||
#endif
|
||||
|
||||
#if defined(oslnoise_EXPORTS) || defined(oslexec_EXPORTS)
|
||||
# define OSLNOISEPUBLIC OSL_DLL_EXPORT
|
||||
#else
|
||||
# define OSLNOISEPUBLIC OSL_DLL_IMPORT
|
||||
#endif
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace llvm {
|
||||
class ExecutionEngine;
|
||||
class Function;
|
||||
class FunctionType;
|
||||
class JITMemoryManager;
|
||||
class SectionMemoryManager;
|
||||
class Linker;
|
||||
class LLVMContext;
|
||||
class Module;
|
||||
@@ -322,6 +322,10 @@ public:
|
||||
/// data type, return the llvm::Value of the new pointer.
|
||||
llvm::Value *ptr_cast (llvm::Value* val, const OIIO::TypeDesc &type);
|
||||
|
||||
/// Cast the variable specified by val to a pointer of type void*,
|
||||
/// return the llvm::Value of the new pointer.
|
||||
llvm::Value *int_to_ptr_cast (llvm::Value* val);
|
||||
|
||||
/// Cast the pointer variable specified by val to a pointer of type
|
||||
/// void* return the llvm::Value of the new pointer.
|
||||
llvm::Value *void_ptr (llvm::Value* val);
|
||||
@@ -410,6 +414,10 @@ public:
|
||||
/// Generate code for a memcpy.
|
||||
void op_memcpy (llvm::Value *dst, llvm::Value *src, int len, int align=1);
|
||||
|
||||
/// Generate code for a memcpy.
|
||||
void op_memcpy (llvm::Value *dst, int dstalign,
|
||||
llvm::Value *src, int srcalign, int len);
|
||||
|
||||
/// Dereference a pointer: return *ptr
|
||||
llvm::Value *op_load (llvm::Value *ptr);
|
||||
|
||||
@@ -448,6 +456,7 @@ public:
|
||||
llvm::Value *op_int_to_float (llvm::Value *a);
|
||||
llvm::Value *op_bool_to_int (llvm::Value *a);
|
||||
llvm::Value *op_float_to_double (llvm::Value *a);
|
||||
llvm::Value *op_int_to_longlong (llvm::Value *a);
|
||||
|
||||
llvm::Value *op_and (llvm::Value *a, llvm::Value *b);
|
||||
llvm::Value *op_or (llvm::Value *a, llvm::Value *b);
|
||||
@@ -474,7 +483,14 @@ public:
|
||||
/// file. If err is not NULL, errors will be deposited there.
|
||||
void write_bitcode_file (const char *filename, std::string *err=NULL);
|
||||
|
||||
/// Convert a function's bitcode to a string.
|
||||
/// Generate PTX for the current Module and return it as a string
|
||||
bool ptx_compile_group (llvm::Module* lib_module, const std::string& name,
|
||||
std::string& out);
|
||||
|
||||
/// Convert a whole module's bitcode to a string.
|
||||
std::string bitcode_string (llvm::Module *module);
|
||||
|
||||
/// Convert one function's bitcode to a string.
|
||||
std::string bitcode_string (llvm::Function *func);
|
||||
|
||||
/// Delete the IR for the body of the given function to reclaim its
|
||||
@@ -500,7 +516,7 @@ private:
|
||||
llvm::LLVMContext *m_llvm_context;
|
||||
llvm::Module *m_llvm_module;
|
||||
IRBuilder *m_builder;
|
||||
MemoryManager *m_llvm_jitmm;
|
||||
llvm::SectionMemoryManager *m_llvm_jitmm;
|
||||
llvm::Function *m_current_function;
|
||||
llvm::legacy::PassManager *m_llvm_module_passes;
|
||||
llvm::legacy::FunctionPassManager *m_llvm_func_passes;
|
||||
|
||||
@@ -114,29 +114,26 @@ struct OSLEXECPUBLIC ClosureColor {
|
||||
|
||||
/// ClosureComponent is a subclass of ClosureColor that holds the ID and
|
||||
/// parameter data for a single primitive closure component (such as
|
||||
/// diffuse, translucent, etc.). The declaration leaves 4 bytes for
|
||||
/// parameter data (mem), but it's expected that the structure be
|
||||
/// allocated with enough space to house all the parameter data for
|
||||
/// whatever type of custom primitive component it actually is.
|
||||
struct OSLEXECPUBLIC ClosureComponent : public ClosureColor
|
||||
/// diffuse, translucent, etc.).
|
||||
///
|
||||
/// ClosureComponent itself takes up 16 bytes, and its allocation will be
|
||||
/// scaled to add parameters after the end of the struct. Alignment is
|
||||
/// set to 16 bytes so that 64 bit pointers and 128 bit SSE types in user
|
||||
/// structs have the required alignment.
|
||||
struct OSLEXECPUBLIC OSL_ALIGNAS(16) ClosureComponent : public ClosureColor
|
||||
{
|
||||
Vec3 w; ///< Weight of this component
|
||||
alignas(void*) char mem[8]; ///< Memory for the primitive, 8 is the minimum, allocation will be
|
||||
/// scaled to requirements of the registered closure struct.
|
||||
/// Alignment is forced to a void* to match likely alignement requirements
|
||||
/// of the user's structs.
|
||||
|
||||
/// Handy method for getting the parameter memory as a void*.
|
||||
///
|
||||
void *data () { return &mem; }
|
||||
const void *data () const { return &mem; }
|
||||
void *data () { return (char*)(this + 1); }
|
||||
const void *data () const { return (const char*)(this + 1); }
|
||||
|
||||
/// Handy methods for extracting the underlying parameters as a struct
|
||||
template <typename T>
|
||||
const T* as() const { return reinterpret_cast<const T*>(mem); }
|
||||
const T* as() const { return reinterpret_cast<const T*>(data()); }
|
||||
|
||||
template <typename T>
|
||||
T* as() { return reinterpret_cast<const T*>(mem); }
|
||||
T* as() { return reinterpret_cast<const T*>(data()); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -47,18 +47,24 @@ public:
|
||||
OSLCompiler (ErrorHandler *errhandler=NULL);
|
||||
~OSLCompiler ();
|
||||
|
||||
/// Compile the given file, using the list of command-line options.
|
||||
/// Compile the given file, using the list of command-line options. The
|
||||
/// stdoslpath parameter provides a custom path for finding stdosl.h.
|
||||
/// Return true if ok, false if the compile failed.
|
||||
bool compile (string_view filename,
|
||||
const std::vector<std::string> &options,
|
||||
string_view stdoslpath = string_view());
|
||||
|
||||
/// Compile the given source code buffer, using the list of command-line
|
||||
/// options, placing the resulting "oso" in osobuffer. Return true if
|
||||
/// ok, false if the compile failed.
|
||||
/// options, placing the resulting "oso" in osobuffer. The stdoslpath
|
||||
/// parameter provides a custom path for finding stdosl.h. The filename
|
||||
/// optionally provides a name for the buffer, used for error reporting
|
||||
/// (the compile() from file method would have used the name of the
|
||||
/// actual file for this purpose). Return true if ok, false if the
|
||||
/// compile failed.
|
||||
bool compile_buffer (string_view sourcecode, std::string &osobuffer,
|
||||
const std::vector<std::string> &options,
|
||||
string_view stdoslpath = string_view());
|
||||
string_view stdoslpath = string_view(),
|
||||
string_view filename = string_view());
|
||||
|
||||
/// Return the name of our compiled output (must be called after
|
||||
/// compile()).
|
||||
|
||||
+82
-13
@@ -44,21 +44,56 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
// same if another packages is compiling against OSL and using these headers
|
||||
// (OSL may be C++11 but the client package may be older, or vice versa --
|
||||
// use these two symbols to differentiate these cases, when important).
|
||||
#if (__cplusplus >= 201402L)
|
||||
# define OSL_CPLUSPLUS_VERSION 14
|
||||
#if (__cplusplus >= 201703L)
|
||||
# define OSL_CPLUSPLUS_VERSION 17
|
||||
# define OSL_CONSTEXPR14 constexpr
|
||||
# define OSL_CONSTEXPR17 constexpr
|
||||
# define OSL_CONSTEXPR20 /* not constexpr before C++20 */
|
||||
#elif (__cplusplus >= 201402L)
|
||||
# define OSL_CPLUSPLUS_VERSION 14
|
||||
# define OSL_CONSTEXPR14 constexpr
|
||||
# define OSL_CONSTEXPR17 /* not constexpr before C++17 */
|
||||
# define OSL_CONSTEXPR20 /* not constexpr before C++20 */
|
||||
#elif (__cplusplus >= 201103L) || _MSC_VER >= 1900
|
||||
# define OSL_CPLUSPLUS_VERSION 11
|
||||
# define OSL_CPLUSPLUS_VERSION 11
|
||||
# define OSL_CONSTEXPR14 /* not constexpr before C++14 */
|
||||
# define OSL_CONSTEXPR17 /* not constexpr before C++17 */
|
||||
# define OSL_CONSTEXPR20 /* not constexpr before C++20 */
|
||||
#else
|
||||
# error "This version of OSL requires C++11"
|
||||
# error "This version of OSL requires C++11"
|
||||
#endif
|
||||
|
||||
#ifndef OSL_HOSTDEVICE
|
||||
# ifdef __CUDACC__
|
||||
# define OSL_HOSTDEVICE __host__ __device__
|
||||
# else
|
||||
# define OSL_HOSTDEVICE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef OSL_DEVICE
|
||||
# ifdef __CUDA_ARCH__
|
||||
# define OSL_DEVICE __device__
|
||||
# else
|
||||
# define OSL_DEVICE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Symbol export defines
|
||||
#include "export.h"
|
||||
|
||||
// All the things we need from Imath
|
||||
#include <OpenEXR/ImathVec.h>
|
||||
#ifdef __CUDACC__
|
||||
// When compiling for CUDA, we need to make sure the modified Imath
|
||||
// headers are included before the stock versions.
|
||||
# include <OSL/ImathVec_cuda.h>
|
||||
# include <OSL/ImathMatrix_cuda.h>
|
||||
#else
|
||||
# include <OpenEXR/ImathVec.h>
|
||||
# include <OpenEXR/ImathMatrix.h>
|
||||
#endif
|
||||
|
||||
#include <OpenEXR/ImathColor.h>
|
||||
#include <OpenEXR/ImathMatrix.h>
|
||||
|
||||
// All the things we need from OpenImageIO
|
||||
#include <OpenImageIO/oiioversion.h>
|
||||
@@ -68,6 +103,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <OpenImageIO/ustring.h>
|
||||
#include <OpenImageIO/platform.h>
|
||||
|
||||
// Make sure we can use OIIO::cspan
|
||||
#if OIIO_VERSION >= 10904
|
||||
# include <OpenImageIO/span.h>
|
||||
#else
|
||||
# include <OpenImageIO/array_view.h>
|
||||
#endif
|
||||
|
||||
// Extensions to Imath
|
||||
#include <OSL/matrix22.h>
|
||||
|
||||
@@ -114,21 +156,48 @@ using OIIO::ustring;
|
||||
using OIIO::ustringHash;
|
||||
using OIIO::string_view;
|
||||
|
||||
|
||||
#ifndef __has_attribute
|
||||
# define __has_attribute(x) 0
|
||||
// Make sure we can use OIIO::cspan
|
||||
#if OIIO_VERSION >= 10904
|
||||
using OIIO::cspan;
|
||||
#else
|
||||
template<typename T> using cspan = OIIO::array_view<const T>;
|
||||
#endif
|
||||
|
||||
#if OSL_CPLUSPLUS_VERSION >= 14 && __has_attribute(deprecated)
|
||||
|
||||
// In C++20 (and some compilers before that), __has_cpp_attribute can
|
||||
// test for understand of [[attr]] tests.
|
||||
#ifndef __has_cpp_attribute
|
||||
# define __has_cpp_attribute(x) 0
|
||||
#endif
|
||||
|
||||
// On gcc & clang, __has_attribute can test for __attribute__((attr))
|
||||
#ifndef __has_attribute
|
||||
# define __has_attribute(x) 0
|
||||
#endif
|
||||
|
||||
// In C++17 (and some compilers before that), __has_include("blah.h") or
|
||||
// __has_include(<blah.h>) can test for presence of an include file.
|
||||
#ifndef __has_include
|
||||
# define __has_include(x) 0
|
||||
#endif
|
||||
|
||||
|
||||
#if OSL_CPLUSPLUS_VERSION >= 14 || __has_cpp_attribute(deprecated)
|
||||
# define OSL_DEPRECATED(msg) [[deprecated(msg)]]
|
||||
#elif (defined(__GNUC__) && OIIO_GNUC_VERSION >= 40600) || defined(__clang__)
|
||||
#elif defined(__GNUC__) || defined(__clang__) || __has_attribute(deprecated)
|
||||
# define OSL_DEPRECATED(msg) __attribute__((deprecated(msg)))
|
||||
#elif defined(__GNUC__) /* older gcc -- only the one with no message */
|
||||
# define OSL_DEPRECATED(msg) __attribute__((deprecated))
|
||||
#elif defined(_MSC_VER)
|
||||
# define OSL_DEPRECATED(msg) __declspec(deprecated(msg))
|
||||
#else
|
||||
# define OSL_DEPRECATED(msg)
|
||||
#endif
|
||||
|
||||
/// Work around bug in GCC with mixed __attribute__ and alignas parsing
|
||||
/// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69585
|
||||
#ifdef __GNUC__
|
||||
# define OSL_ALIGNAS(size) __attribute__((aligned(size)))
|
||||
#else
|
||||
# define OSL_ALIGNAS(size) alignas(size)
|
||||
#endif
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
+53
-17
@@ -37,6 +37,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <OpenImageIO/refcnt.h>
|
||||
#include <OpenImageIO/ustring.h>
|
||||
#include <OpenImageIO/array_view.h>
|
||||
#if OPENIMAGEIO_VERSION <= 10902
|
||||
#include <OpenImageIO/imagebufalgo_util.h>
|
||||
#endif
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
@@ -80,6 +83,7 @@ public:
|
||||
/// 1. Attributes that should be exposed to users:
|
||||
/// int statistics:level Automatically print OSL statistics (0).
|
||||
/// string searchpath:shader Colon-separated path to search for .oso
|
||||
/// files ("", meaning test "." only)
|
||||
/// string colorspace Name of RGB color space ("Rec709")
|
||||
/// int range_checking Generate extra code for component & array
|
||||
/// range checking (1)
|
||||
@@ -111,6 +115,9 @@ public:
|
||||
/// fails to find the layer or parameter? (1)
|
||||
/// int strict_messages Issue error if a message is set after
|
||||
/// being queried (1).
|
||||
/// int error_repeats If zero, suppress repeats of errors and
|
||||
/// warnings that are exact duplicates of
|
||||
/// earlier ones. (1)
|
||||
/// int lazylayers Evaluate shader layers only when their
|
||||
/// outputs are first needed (1)
|
||||
/// int lazyglobals Run layers lazily even if they write to
|
||||
@@ -128,6 +135,8 @@ public:
|
||||
/// means a param CANNOT be overridden by
|
||||
/// interpolated geometric parameters.
|
||||
/// int countlayerexecs Add extra code to count total layers run.
|
||||
/// int allow_shader_replacement Allow shader to be specified more than
|
||||
/// once, replacing former definition.
|
||||
/// string archive_groupname Name of a group to pickle and archive.
|
||||
/// string archive_filename Name of file to save the group archive.
|
||||
/// 3. Attributes that that are intended for developers debugging
|
||||
@@ -152,6 +161,8 @@ public:
|
||||
/// layer functions.
|
||||
/// int llvm_debug_ops Extra printfs for each OSL op (helpful
|
||||
/// for devs to find crashes)
|
||||
/// int llvm_output_bitcode Output the full bitcode for each group,
|
||||
/// for debugging. (0)
|
||||
/// int max_local_mem_KB Error if shader group needs more than this
|
||||
/// much local storage to execute (1024K)
|
||||
/// string debug_groupname Name of shader group -- debug only this one
|
||||
@@ -267,6 +278,12 @@ public:
|
||||
/// int unknown_closures_needed Nonzero if additional closures may be
|
||||
/// needed, whose names can't be known
|
||||
/// without actually running the shader.
|
||||
/// int globals_read Bitfield ("or'ed" SGBits values) of
|
||||
/// which ShaderGlobals may be read by
|
||||
/// by the shader group.
|
||||
/// int globals_write Bitfield ("or'ed" SGBits values) of
|
||||
/// which ShaderGlobals may be written by
|
||||
/// by the shader group.
|
||||
/// int num_globals_needed The number of named globals needed.
|
||||
/// ptr globals_needed Retrieves a pointer to the ustring array
|
||||
/// containing all globals needed.
|
||||
@@ -392,14 +409,25 @@ public:
|
||||
bool Parameter (string_view name, TypeDesc t, const void *val,
|
||||
bool lockgeom);
|
||||
|
||||
/// Create a new shader instance, either replacing the one for the
|
||||
/// specified usage (if not within a group) or appending to the
|
||||
/// current group (if a group has been started).
|
||||
/// Create a new shader instance, either replacing the current group (if
|
||||
/// not within a group) or appending to the current group (if a group
|
||||
/// has been started).
|
||||
bool Shader (string_view shaderusage,
|
||||
string_view shadername = string_view(),
|
||||
string_view layername = string_view());
|
||||
string_view shadername,
|
||||
string_view layername);
|
||||
|
||||
/// Connect two shaders within the current group
|
||||
/// Connect two shaders within the current group. The source layer must
|
||||
/// be *upstream* of down destination layer (i.e. source must be
|
||||
/// declared earlier within the shader group). The named parameters must
|
||||
/// be of compatible type -- float to float, color to color, array to
|
||||
/// array of the same length and element type, etc. In general, it is
|
||||
/// permissible to connect type A to type B if and only if it is allowed
|
||||
/// within OSL to assign an A to a B (i.e., if `A = B` is legal). So any
|
||||
/// "triple" may be connected to any other triple, and a float output
|
||||
/// may be connected to a triple input (but not the other way around).
|
||||
/// It is permitted to connect a single component of an aggregate to a
|
||||
/// float and vice versa, for example,
|
||||
/// `ConnectShaders ("lay1", "mycolorout[2]", "lay2", "myfloatinput")`
|
||||
///
|
||||
bool ConnectShaders (string_view srclayer, string_view srcparam,
|
||||
string_view dstlayer, string_view dstparam);
|
||||
@@ -449,9 +477,6 @@ public:
|
||||
/// setup, don't actually run the shader.
|
||||
bool execute (ShadingContext *ctx, ShaderGroup &group,
|
||||
ShaderGlobals &globals, bool run=true);
|
||||
OSL_DEPRECATED("Deprecated since 1.6, pass context pointer, not reference.")
|
||||
bool execute (ShadingContext &ctx, ShaderGroup &group,
|
||||
ShaderGlobals &globals, bool run=true);
|
||||
|
||||
/// Bind a shader group and globals to the context, in preparation to
|
||||
/// execute, including optimization and JIT of the group (if it has not
|
||||
@@ -552,6 +577,13 @@ public:
|
||||
bool query_closure (const char **name, int *id,
|
||||
const ClosureParam **params);
|
||||
|
||||
/// For the proposed shader "global" name, return the corresponding
|
||||
/// SGBits enum.
|
||||
static SGBits globals_bit (ustring name);
|
||||
|
||||
/// For the SGBits value, return the shader "globals" name.
|
||||
static ustring globals_name (SGBits bit);
|
||||
|
||||
/// For the proposed raytype name, return the bit pattern that
|
||||
/// describes it, or 0 for an unrecognized name. (This retrieves
|
||||
/// data passed in via attribute("raytypes")).
|
||||
@@ -564,14 +596,17 @@ public:
|
||||
/// to the optimizer, and will be determined strictly at execution time.
|
||||
void set_raytypes(ShaderGroup *group, int raytypes_on, int raytypes_off);
|
||||
|
||||
/// Ensure that the group has been optimized and JITed.
|
||||
/// Ensure that the group has been optimized and JITed.
|
||||
void optimize_group (ShaderGroup *group);
|
||||
/// Ensure that the group has been optimized and JITed. The ctx pointer
|
||||
/// optionally supplies a ShadingContext to use; if one is not supplied,
|
||||
/// one will be temporarily allocated if needed.
|
||||
void optimize_group (ShaderGroup *group, ShadingContext *ctx = nullptr);
|
||||
|
||||
/// Ensure that the group has been optimized and JITed. This is a
|
||||
/// convenience function that simply calls set_raytypes followed by optimize_group.
|
||||
/// convenience function that simply calls set_raytypes followed by
|
||||
/// optimize_group. The ctx optionally supplies a ShadingContext to use;
|
||||
/// if not supplied, one will be temporarily allocated if needed.
|
||||
void optimize_group (ShaderGroup *group, int raytypes_on,
|
||||
int raytypes_off);
|
||||
int raytypes_off, ShadingContext *ctx = nullptr);
|
||||
|
||||
/// If option "greedyjit" was set, this call will trigger all
|
||||
/// shader groups that have not yet been compiled to do so with the
|
||||
@@ -621,9 +656,9 @@ private:
|
||||
|
||||
|
||||
|
||||
#ifdef OPENIMAGEIO_IMAGEBUF_H
|
||||
#ifdef OPENIMAGEIO_IMAGEBUFALGO_H
|
||||
// To keep from polluting all OSL clients with ImageBuf & ROI, only expose
|
||||
// the following declarations if they have included OpenImageIO/imagebuf.h.
|
||||
// the following declarations if they have included OpenImageIO/imagebufalgo.h.
|
||||
|
||||
// enum describing where shades are located for shade_image().
|
||||
enum ShadeImageLocations {
|
||||
@@ -656,7 +691,8 @@ bool shade_image (ShadingSystem &shadingsys, ShaderGroup &group,
|
||||
const ShaderGlobals *defaultsg,
|
||||
OIIO::ImageBuf &buf, OIIO::array_view<ustring> outputs,
|
||||
ShadeImageLocations shadelocations = ShadePixelCenters,
|
||||
OIIO::ROI roi = OIIO::ROI(), int nthreads = 0);
|
||||
OIIO::ROI roi = OIIO::ROI(),
|
||||
OIIO::ImageBufAlgo::parallel_image_options popt = 0);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+386
-354
File diff suppressed because it is too large
Load Diff
+157
-74
@@ -54,100 +54,152 @@ namespace pvt {
|
||||
|
||||
|
||||
|
||||
/// <doc OSLQuery>
|
||||
/// **OSLQuery Documentation**
|
||||
///
|
||||
///
|
||||
/// Introduction and Tutorial
|
||||
/// =========================
|
||||
///
|
||||
/// `OSLQuery` is a class that lets an application interrogate a
|
||||
/// compiled shader for information about its parameters.
|
||||
///
|
||||
/// The shader may be an already-compiled shader file on disk (i.e. a
|
||||
/// `.oso` file), or the `.oso` equivalent in a string, or the binary
|
||||
/// representation used by the OSL `ShaderSystem` runtime (as a pointer
|
||||
/// to a `ShaderGroup`). For example,
|
||||
///
|
||||
/// ~~~
|
||||
/// OSLQuery oslquery ("polished_oak");
|
||||
/// ~~~
|
||||
///
|
||||
/// It's then easy to retrieve a specific parameter:
|
||||
///
|
||||
/// ~~~
|
||||
/// int nparams = oslquery.nparams(); // number of params
|
||||
///
|
||||
/// const OSLQuery::Parameter *param;
|
||||
/// p = oslquery.getparam (i); // by index (0..nparams-1)
|
||||
/// p = oslquery.getparam ("woodcolor"); // by name
|
||||
/// ~~~
|
||||
///
|
||||
/// And the `Parameter` structure will hold all the information you need
|
||||
/// about that paramter. For example:
|
||||
///
|
||||
/// ~~~
|
||||
/// std::cout << "Parameter " << p->name
|
||||
/// << " is type " << p->type << "\n"
|
||||
/// ~~~
|
||||
///
|
||||
/// You can find out if the parameter is a closure, an output parameter,
|
||||
/// etc. You can also find out its default values, which are stored in
|
||||
/// vector fields `idefault`, `fdefault`, and `sdefault` depending on
|
||||
/// whether the types is based on int, float, or string, respectively.
|
||||
///
|
||||
///
|
||||
/// OSLQuery class API Reference
|
||||
/// ============================
|
||||
|
||||
class OSLQUERYPUBLIC OSLQuery {
|
||||
public:
|
||||
/// Parameter holds all the information about a single shader parameter.
|
||||
///
|
||||
struct Parameter {
|
||||
ustring name; ///< name
|
||||
TypeDesc type; ///< data type
|
||||
bool isoutput; ///< is it an output param?
|
||||
bool validdefault; ///< false if there's no default val
|
||||
bool varlenarray; ///< is it a varying-length array?
|
||||
bool isstruct; ///< is it a structure?
|
||||
bool isclosure; ///< is it a closure?
|
||||
void *data; ///< pointer to data
|
||||
std::vector<int> idefault; ///< default int values
|
||||
std::vector<float> fdefault; ///< default float values
|
||||
std::vector<ustring> sdefault; ///< default string values
|
||||
std::vector<ustring> spacename; ///< space name for matrices and
|
||||
///< triples, for each array elem.
|
||||
std::vector<ustring> fields; ///< Names of this struct's fields
|
||||
ustring structname; ///< Name of the struct
|
||||
std::vector<Parameter> metadata; ///< Meta-data about the param
|
||||
Parameter ()
|
||||
: isoutput(false), validdefault(false), varlenarray(false),
|
||||
isstruct(false), isclosure(false), data(NULL)
|
||||
{ }
|
||||
/// Parameter helper structure
|
||||
/// --------------------------
|
||||
/// `Parameter` holds all the information about a single shader
|
||||
/// parameter.
|
||||
/// <code>
|
||||
struct OSLQUERYPUBLIC Parameter {
|
||||
ustring name; //< name
|
||||
TypeDesc type; //< data type
|
||||
bool isoutput = false; //< is it an output param?
|
||||
bool validdefault = false; //< false if there's no default val
|
||||
bool varlenarray = false; //< is it a varying-length array?
|
||||
bool isstruct = false; //< is it a structure?
|
||||
bool isclosure = false; //< is it a closure?
|
||||
void *data = nullptr; //< pointer to data
|
||||
std::vector<int> idefault; //< default int values
|
||||
std::vector<float> fdefault; //< default float values
|
||||
std::vector<ustring> sdefault; //< default string values
|
||||
std::vector<ustring> spacename; //< space name for matrices and
|
||||
//< triples, for each array elem.
|
||||
std::vector<ustring> fields; //< Names of this struct's fields
|
||||
ustring structname; //< Name of the struct
|
||||
std::vector<Parameter> metadata; //< Meta-data about the param
|
||||
|
||||
Parameter () {}
|
||||
Parameter (const Parameter& src);
|
||||
Parameter (Parameter&& src);
|
||||
const Parameter& operator= (const Parameter &);
|
||||
const Parameter& operator= (Parameter &&);
|
||||
};
|
||||
/// </code>
|
||||
|
||||
/// OSLQuery methods
|
||||
/// ----------------
|
||||
|
||||
OSLQuery ();
|
||||
///< Construct an uninitialized OSLQuery. It will not hold any
|
||||
/// information about a shader until `open()` is called.
|
||||
|
||||
OSLQuery (string_view shadername,
|
||||
string_view searchpath = string_view()) {
|
||||
string_view searchpath = string_view()) {
|
||||
open (shadername, searchpath);
|
||||
}
|
||||
///< Construct an OSLQuery and open a compiled shader from a disk file.
|
||||
/// The `shadername` may be either the name of the `.oso` file, or the
|
||||
/// name of the shader. The optional `searchpath` paramter gives a
|
||||
/// colon-separated list of directories to search for compiled shaders.
|
||||
|
||||
OSLQuery (const ShaderGroup *group, int layernum) {
|
||||
init (group, layernum);
|
||||
}
|
||||
///< Construct an OSLQuery and initialize it with an existing
|
||||
/// `ShaderGroup` (which must have been built using the `ShadingSystem`
|
||||
/// runtime API for OSL.
|
||||
|
||||
~OSLQuery ();
|
||||
///< Clean up and destruct the `OSLQuery`.
|
||||
|
||||
/// Get info on the named shader with optional searcphath. Return
|
||||
/// true for success, false if the shader could not be found or
|
||||
/// opened properly.
|
||||
bool open (string_view shadername,
|
||||
string_view searchpath = string_view());
|
||||
///< For an uninitialized `OSLQuery` object, initialize it with info on
|
||||
/// the named shader with optional searcphath. Return true for success,
|
||||
/// false if the shader could not be found or opened properly.
|
||||
|
||||
/// Get info on the shader from it's compiled bytecode. Return
|
||||
/// true for success, false if the shader could not be found or
|
||||
/// opened properly.
|
||||
/// Meant to be called from an app which caches bytecodes from
|
||||
bool open_bytecode (string_view buffer);
|
||||
///< Get info on the shader from it's compiled bytecode (i.e., like the
|
||||
/// contents of an `.oso` file, but in a string). Return `true` for
|
||||
/// success, false if the shader could not be found or opened properly.
|
||||
///
|
||||
/// This is meant to be called from an app which caches bytecodes from
|
||||
/// it's own side and wants to get shader info on runtime without
|
||||
/// creating a temporary file.
|
||||
bool open_bytecode (string_view buffer);
|
||||
|
||||
/// Meant to be called at runtime from an app with a full ShadingSystem,
|
||||
bool init (const ShaderGroup *group, int layernum);
|
||||
///< Meant to be called at runtime from an app with a full ShadingSystem,
|
||||
/// fill out an OSLQuery structure for the given layer of the group.
|
||||
/// This is much faster than using open() to read it from an oso file on
|
||||
/// disk.
|
||||
bool init (const ShaderGroup *group, int layernum);
|
||||
|
||||
/// Return the shader type: "surface", "displacement", "volume",
|
||||
/// "light", or "shader" (for generic shaders).
|
||||
const ustring shadertype (void) const { return m_shadertypename; }
|
||||
///< Return the shader type: "surface", "displacement", "volume",
|
||||
/// "light", or "shader" (for generic shaders).
|
||||
|
||||
/// Get the name of the shader.
|
||||
///
|
||||
const ustring shadername (void) const { return m_shadername; }
|
||||
///< Get the name of the shader.
|
||||
|
||||
/// How many parameters does the shader have?
|
||||
///
|
||||
size_t nparams (void) const { return (int) m_params.size(); }
|
||||
///< How many parameters does the shader have
|
||||
|
||||
/// Retrieve a parameter, either by index or by name. Return NULL if the
|
||||
/// index is out of range, or if the named parameter is not found.
|
||||
const Parameter *getparam (size_t i) const {
|
||||
if (i >= nparams())
|
||||
return NULL;
|
||||
return &(m_params[i]);
|
||||
}
|
||||
const Parameter *getparam (const std::string &name) const {
|
||||
for (size_t i = 0; i < nparams(); ++i)
|
||||
if (m_params[i].name == name)
|
||||
return &(m_params[i]);
|
||||
return NULL;
|
||||
}
|
||||
const Parameter *getparam (ustring name) const {
|
||||
for (size_t i = 0; i < nparams(); ++i)
|
||||
if (m_params[i].name == name)
|
||||
return &(m_params[i]);
|
||||
return NULL;
|
||||
}
|
||||
const Parameter *getparam (size_t i) const;
|
||||
const Parameter *getparam (const std::string &name) const;
|
||||
const Parameter *getparam (ustring name) const;
|
||||
///< Retrieve a parameter, either by index or by name. Return nullptr if
|
||||
/// the index is out of range, or if the named parameter is not found.
|
||||
|
||||
/// Retrieve a reference to the metadata about the shader.
|
||||
///
|
||||
const std::vector<Parameter> &metadata (void) const { return m_meta; }
|
||||
///< Retrieve a reference to the metadata about the shader.
|
||||
|
||||
/// Return error string, empty if there was no error, and reset the
|
||||
///> Return error string, empty if there was no error, and reset the
|
||||
/// error string.
|
||||
std::string geterror (bool clear_error = true) {
|
||||
std::string e = m_error;
|
||||
@@ -157,24 +209,19 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
ustring m_shadername; ///< Name of shader
|
||||
ustring m_shadertypename; ///< Type of shader
|
||||
mutable std::string m_error; ///< Error message
|
||||
std::vector<Parameter> m_params; ///< Params to the shader
|
||||
std::vector<Parameter> m_meta; ///< Meta-data about the shader
|
||||
ustring m_shadername; //< Name of shader
|
||||
ustring m_shadertypename; //< Type of shader
|
||||
mutable std::string m_error; //< Error message
|
||||
std::vector<Parameter> m_params; //< Params to the shader
|
||||
std::vector<Parameter> m_meta; //< Meta-data about the shader
|
||||
friend class pvt::OSOReaderQuery;
|
||||
|
||||
#if OIIO_VERSION >= 10803
|
||||
/// Internal error reporting routine, with printf-like arguments.
|
||||
// Internal error reporting routine, with printf-like arguments.
|
||||
template<typename... Args>
|
||||
inline void error (string_view fmt, const Args&... args) const {
|
||||
append_error(OIIO::Strutil::format (fmt, args...));
|
||||
}
|
||||
#else
|
||||
// Fallback for older OIIO
|
||||
TINYFORMAT_WRAP_FORMAT (void, error, const,
|
||||
std::ostringstream msg;, msg, append_error(msg.str());)
|
||||
#endif
|
||||
|
||||
void append_error (const std::string& message) const {
|
||||
if (m_error.size())
|
||||
m_error += '\n';
|
||||
@@ -183,4 +230,40 @@ private:
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
////////// Implementation
|
||||
|
||||
inline const OSLQuery::Parameter*
|
||||
OSLQuery::getparam (size_t i) const
|
||||
{
|
||||
if (i >= nparams())
|
||||
return nullptr;
|
||||
return &(m_params[i]);
|
||||
}
|
||||
|
||||
|
||||
inline const OSLQuery::Parameter*
|
||||
OSLQuery::getparam (const std::string &name) const
|
||||
{
|
||||
for (size_t i = 0; i < nparams(); ++i)
|
||||
if (m_params[i].name == name)
|
||||
return &(m_params[i]);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
inline const OSLQuery::Parameter*
|
||||
OSLQuery::getparam (ustring name) const
|
||||
{
|
||||
for (size_t i = 0; i < nparams(); ++i)
|
||||
if (m_params[i].name == name)
|
||||
return &(m_params[i]);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
// more documentation
|
||||
/// <inc oslinfo_source>
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
@@ -67,7 +67,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
OSL_LIBRARY_VERSION_PATCH, \
|
||||
OSL_LIBRARY_VERSION_RELEASE_TYPE)
|
||||
#define OSL_INTRO_STRING "OpenShadingLanguage " OSL_LIBRARY_VERSION_STRING
|
||||
#define OSL_COPYRIGHT_STRING "(c) Copyright 2009-2017 Sony Pictures Imageworks, et al. All rights reserved."
|
||||
#define OSL_COPYRIGHT_STRING "(c) Copyright 2009-2019 Sony Pictures Imageworks, et al. All rights reserved."
|
||||
|
||||
|
||||
// Version numbers for the compiled shader format. The major number
|
||||
@@ -97,5 +97,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#cmakedefine01 OSL_BUILD_CPP14
|
||||
// OSL_BUILD_CPP17 will be 1 if this OSL was built using C++17
|
||||
#cmakedefine01 OSL_BUILD_CPP17
|
||||
// OSL_BUILD_CPP20 will be 1 if this OSL was built using C++20 or higher
|
||||
#cmakedefine01 OSL_BUILD_CPP20
|
||||
|
||||
#endif /* OSLVERSION_H */
|
||||
|
||||
@@ -82,7 +82,7 @@ public:
|
||||
/// transformation at the given time. Return true if ok, false
|
||||
/// on error.
|
||||
virtual bool get_matrix (ShaderGlobals *sg, Matrix44 &result,
|
||||
TransformationPtr xform, float time) = 0;
|
||||
TransformationPtr xform, float time) { return false; }
|
||||
|
||||
/// Get the 4x4 matrix that transforms by the specified
|
||||
/// transformation at the given time. Return true if ok, false on
|
||||
@@ -97,7 +97,7 @@ public:
|
||||
/// time value is given, also return false if the transformation may
|
||||
/// be time-varying.
|
||||
virtual bool get_matrix (ShaderGlobals *sg, Matrix44 &result,
|
||||
TransformationPtr xform) = 0;
|
||||
TransformationPtr xform) { return false; }
|
||||
|
||||
/// Get the 4x4 matrix that transforms by the specified
|
||||
/// transformation. Return true if ok, false on error. Since no
|
||||
@@ -112,7 +112,7 @@ public:
|
||||
/// 'from' coordinate system to "common" space at the given time.
|
||||
/// Returns true if ok, false if the named matrix is not known.
|
||||
virtual bool get_matrix (ShaderGlobals *sg, Matrix44 &result,
|
||||
ustring from, float time) = 0;
|
||||
ustring from, float time) { return false; }
|
||||
|
||||
/// Get the 4x4 matrix that transforms points from "common" space to
|
||||
/// the named 'to' coordinate system to at the given time. The
|
||||
@@ -127,7 +127,7 @@ public:
|
||||
/// transformation may be time-varying (as well as if it's not found
|
||||
/// at all).
|
||||
virtual bool get_matrix (ShaderGlobals *sg, Matrix44 &result,
|
||||
ustring from) = 0;
|
||||
ustring from) { return false; }
|
||||
|
||||
/// Get the 4x4 matrix that transforms points from "common" space to
|
||||
/// the named 'to' coordinate system. Since there is no time value
|
||||
@@ -183,20 +183,20 @@ public:
|
||||
/// otherwise just fail by returning 'false'.
|
||||
virtual bool get_attribute (ShaderGlobals *sg, bool derivatives,
|
||||
ustring object, TypeDesc type, ustring name,
|
||||
void *val ) = 0;
|
||||
void *val) { return false; }
|
||||
|
||||
/// Similar to get_attribute(); this method will return the 'index'
|
||||
/// element of an attribute array.
|
||||
virtual bool get_array_attribute (ShaderGlobals *sg, bool derivatives,
|
||||
ustring object, TypeDesc type,
|
||||
ustring name, int index, void *val ) = 0;
|
||||
ustring name, int index, void *val) { return false; }
|
||||
|
||||
/// Get the named user-data from the current object and write it into
|
||||
/// 'val'. If derivatives is true, the derivatives should be written into val
|
||||
/// as well. Return false if no user-data with the given name and type was
|
||||
/// found.
|
||||
virtual bool get_userdata (bool derivatives, ustring name, TypeDesc type,
|
||||
ShaderGlobals *sg, void *val) = 0;
|
||||
ShaderGlobals *sg, void *val) { return false; }
|
||||
|
||||
/// Given the name of a texture, return an opaque handle that can be
|
||||
/// used with texture calls to avoid the name lookups.
|
||||
@@ -244,8 +244,9 @@ public:
|
||||
float dsdy, float dtdy, int nchannels,
|
||||
float *result, float *dresultds, float *dresultdt,
|
||||
ustring *errormessage);
|
||||
// Deprecated version, with no errormessage parameter. This will
|
||||
// DEPRECATED(1.8) version, with no errormessage parameter. This will
|
||||
// eventually disappear.
|
||||
OSL_DEPRECATED ("Deprecated since 1.8, use the version with an errormessage parameter.")
|
||||
virtual bool texture (ustring filename, TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
TextureOpt &options, ShaderGlobals *sg,
|
||||
@@ -286,8 +287,9 @@ public:
|
||||
float *result, float *dresultds,
|
||||
float *dresultdt, float *dresultdr,
|
||||
ustring *errormessage);
|
||||
// Deprecated version, with no errormessage parameter. This will
|
||||
// DEPRECATED(1.8) version, with no errormessage parameter. This will
|
||||
// eventually disappear.
|
||||
OSL_DEPRECATED ("Deprecated since 1.8, use the version with an errormessage parameter.")
|
||||
virtual bool texture3d (ustring filename, TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
TextureOpt &options, ShaderGlobals *sg,
|
||||
@@ -325,8 +327,9 @@ public:
|
||||
int nchannels, float *result,
|
||||
float *dresultds, float *dresultdt,
|
||||
ustring *errormessage);
|
||||
// Deprecated version, with no errormessage parameter. This will
|
||||
// DEPRECATED(1.8) version, with no errormessage parameter. This will
|
||||
// eventually disappear.
|
||||
OSL_DEPRECATED ("Deprecated since 1.8, use the version with an errormessage parameter.")
|
||||
virtual bool environment (ustring filename, TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
TextureOpt &options, ShaderGlobals *sg,
|
||||
@@ -418,6 +421,15 @@ public:
|
||||
/// Return a pointer to the texture system (if available).
|
||||
virtual TextureSystem *texturesys () const;
|
||||
|
||||
/// Register a string with the renderer, so that the renderer can arrange
|
||||
/// to make the string available in GPU memory as needed. Optionally specify
|
||||
/// a variable name to associate with the string value.
|
||||
virtual uint64_t register_string (const std::string& str,
|
||||
const std::string& var_name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Options we use for noise calls.
|
||||
struct NoiseOpt {
|
||||
int anisotropic;
|
||||
|
||||
@@ -145,4 +145,25 @@ struct ShaderGlobals {
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// Enum giving values that can be 'or'-ed together to make a bitmask
|
||||
/// of which "global" variables are needed or written to by the shader.
|
||||
enum class SGBits {
|
||||
None = 0,
|
||||
P = 1 << 0,
|
||||
I = 1 << 1,
|
||||
N = 1 << 2,
|
||||
Ng = 1 << 3,
|
||||
u = 1 << 4,
|
||||
v = 1 << 5,
|
||||
dPdu = 1 << 6,
|
||||
dPdv = 1 << 7,
|
||||
time = 1 << 8,
|
||||
dtime = 1 << 9,
|
||||
dPdtime = 1 << 10,
|
||||
Ps = 1 << 11,
|
||||
Ci = 1 << 12,
|
||||
last
|
||||
};
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
Copyright (c) 2009-2018 Sony Pictures Imageworks Inc., et al.
|
||||
All Rights Reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Sony Pictures Imageworks nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
// This file contains "declarations" for all the strings that might get used in
|
||||
// JITed shader code or in renderer code. But the declaration itself is
|
||||
// dependent on the STRDECL macro, which should be declared by the outer file
|
||||
// prior to including this file. Thus, this list may be repurposed and included
|
||||
// multiple times, with different STRDECL definitions.
|
||||
|
||||
|
||||
#ifndef STRDECL
|
||||
#error Do not include this file unless STRDECL is defined
|
||||
#endif
|
||||
|
||||
|
||||
STRDECL ("", _emptystring_)
|
||||
STRDECL ("camera", camera)
|
||||
STRDECL ("common", common)
|
||||
STRDECL ("object", object)
|
||||
STRDECL ("shader", shader)
|
||||
STRDECL ("screen", screen)
|
||||
STRDECL ("NDC", NDC)
|
||||
STRDECL ("rgb", rgb)
|
||||
STRDECL ("RGB", RGB)
|
||||
STRDECL ("hsv", hsv)
|
||||
STRDECL ("hsl", hsl)
|
||||
STRDECL ("YIQ", YIQ)
|
||||
STRDECL ("XYZ", XYZ)
|
||||
STRDECL ("xyz", xyz)
|
||||
STRDECL ("xyY", xyY)
|
||||
STRDECL ("null", null)
|
||||
STRDECL ("default", default_)
|
||||
STRDECL ("label", label)
|
||||
STRDECL ("sidedness", sidedness)
|
||||
STRDECL ("front", front)
|
||||
STRDECL ("back", back)
|
||||
STRDECL ("both", both)
|
||||
STRDECL ("P", P)
|
||||
STRDECL ("I", I)
|
||||
STRDECL ("N", N)
|
||||
STRDECL ("Ng", Ng)
|
||||
STRDECL ("dPdu", dPdu)
|
||||
STRDECL ("dPdv", dPdv)
|
||||
STRDECL ("u", u)
|
||||
STRDECL ("v", v)
|
||||
STRDECL ("Ps", Ps)
|
||||
STRDECL ("time", time)
|
||||
STRDECL ("dtime", dtime)
|
||||
STRDECL ("dPdtime", dPdtime)
|
||||
STRDECL ("Ci", Ci)
|
||||
STRDECL ("width", width)
|
||||
STRDECL ("swidth", swidth)
|
||||
STRDECL ("twidth", twidth)
|
||||
STRDECL ("rwidth", rwidth)
|
||||
STRDECL ("blur", blur)
|
||||
STRDECL ("sblur", sblur)
|
||||
STRDECL ("tblur", tblur)
|
||||
STRDECL ("rblur", rblur)
|
||||
STRDECL ("wrap", wrap)
|
||||
STRDECL ("swrap", swrap)
|
||||
STRDECL ("twrap", twrap)
|
||||
STRDECL ("rwrap", rwrap)
|
||||
STRDECL ("black", black)
|
||||
STRDECL ("clamp", clamp)
|
||||
STRDECL ("periodic", periodic)
|
||||
STRDECL ("mirror", mirror)
|
||||
STRDECL ("firstchannel", firstchannel)
|
||||
STRDECL ("fill", fill)
|
||||
STRDECL ("alpha", alpha)
|
||||
STRDECL ("errormessage", errormessage)
|
||||
STRDECL ("interp", interp)
|
||||
STRDECL ("closest", closest)
|
||||
STRDECL ("linear", linear)
|
||||
STRDECL ("cubic", cubic)
|
||||
STRDECL ("smartcubic", smartcubic)
|
||||
STRDECL ("perlin", perlin)
|
||||
STRDECL ("uperlin", uperlin)
|
||||
STRDECL ("noise", noise)
|
||||
STRDECL ("snoise", snoise)
|
||||
STRDECL ("cell", cell)
|
||||
STRDECL ("cellnoise", cellnoise)
|
||||
STRDECL ("pcellnoise", pcellnoise)
|
||||
STRDECL ("hash", hash)
|
||||
STRDECL ("hashnoise", hashnoise)
|
||||
STRDECL ("phashnoise", phashnoise)
|
||||
STRDECL ("pnoise", pnoise)
|
||||
STRDECL ("psnoise", psnoise)
|
||||
STRDECL ("genericnoise", genericnoise)
|
||||
STRDECL ("genericpnoise", genericpnoise)
|
||||
STRDECL ("gabor", gabor)
|
||||
STRDECL ("gabornoise", gabornoise)
|
||||
STRDECL ("gaborpnoise", gaborpnoise)
|
||||
STRDECL ("simplex", simplex)
|
||||
STRDECL ("usimplex", usimplex)
|
||||
STRDECL ("simplexnoise", simplexnoise)
|
||||
STRDECL ("usimplexnoise", usimplexnoise)
|
||||
STRDECL ("anisotropic", anisotropic)
|
||||
STRDECL ("direction", direction)
|
||||
STRDECL ("do_filter", do_filter)
|
||||
STRDECL ("bandwidth", bandwidth)
|
||||
STRDECL ("impulses", impulses)
|
||||
STRDECL ("dowhile", op_dowhile)
|
||||
STRDECL ("for", op_for)
|
||||
STRDECL ("while", op_while)
|
||||
STRDECL ("exit", op_exit)
|
||||
STRDECL ("subimage", subimage)
|
||||
STRDECL ("subimagename", subimagename)
|
||||
STRDECL ("missingcolor", missingcolor)
|
||||
STRDECL ("missingalpha", missingalpha)
|
||||
STRDECL ("end", end)
|
||||
STRDECL ("useparam", useparam)
|
||||
STRDECL ("!!!uninitialized!!!", uninitialized_string)
|
||||
STRDECL ("unull", unull)
|
||||
STRDECL ("raytype", raytype)
|
||||
STRDECL ("color", color)
|
||||
STRDECL ("point", point)
|
||||
STRDECL ("vector", vector)
|
||||
STRDECL ("normal", normal)
|
||||
STRDECL ("matrix", matrix)
|
||||
STRDECL ("unknown", unknown)
|
||||
+19
-28
@@ -43,10 +43,9 @@ class StructSpec;
|
||||
|
||||
/// Kinds of shaders
|
||||
///
|
||||
enum ShaderType {
|
||||
ShadTypeUnknown=0, ShadTypeGeneric, ShadTypeSurface,
|
||||
ShadTypeDisplacement, ShadTypeVolume, ShadTypeLight,
|
||||
ShadTypeLast
|
||||
enum class ShaderType {
|
||||
Unknown=0, Generic, Surface, Displacement, Volume, Light,
|
||||
Last
|
||||
};
|
||||
|
||||
|
||||
@@ -60,24 +59,6 @@ ShaderType shadertype_from_name (string_view name);
|
||||
|
||||
|
||||
|
||||
/// Uses of shaders
|
||||
///
|
||||
enum ShaderUse {
|
||||
ShadUseSurface, ShadUseDisplacement,
|
||||
ShadUseLast, ShadUseUnknown = ShadUseLast
|
||||
};
|
||||
|
||||
|
||||
/// Convert a ShaderUse to a human-readable name ("surface", etc.)
|
||||
///
|
||||
const char *shaderusename (ShaderUse s);
|
||||
|
||||
/// Convert a ShaderUse to a human-readable name ("surface", etc.)
|
||||
///
|
||||
ShaderUse shaderuse_from_name (string_view name);
|
||||
|
||||
|
||||
|
||||
/// Kinds of symbols
|
||||
///
|
||||
enum SymType {
|
||||
@@ -476,7 +457,8 @@ public:
|
||||
m_symtype(symtype),
|
||||
m_has_derivs(false), m_const_initializer(false),
|
||||
m_connected_down(false),
|
||||
m_initialized(false), m_lockgeom(false), m_renderer_output(false),
|
||||
m_initialized(false), m_lockgeom(false), m_allowconnect(true),
|
||||
m_renderer_output(false), m_readonly(false),
|
||||
m_valuesource(DefaultVal), m_free_data(false),
|
||||
m_fieldid(-1), m_layer(-1),
|
||||
m_scope(0), m_dataoffset(-1), m_initializers(0),
|
||||
@@ -496,7 +478,8 @@ public:
|
||||
// since by design we have made this structure hold no unique
|
||||
// pointers and have no elements that aren't safe to memcpy, even
|
||||
// though the compiler probably can't figure that out.
|
||||
if (this != &a) memcpy (this, &a, sizeof(Symbol));
|
||||
// Cast to char* to defeat gcc8 rejecting this.
|
||||
if (this != &a) memcpy ((char *)this, (const char *)&a, sizeof(Symbol));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -686,6 +669,9 @@ public:
|
||||
bool lockgeom () const { return m_lockgeom; }
|
||||
void lockgeom (bool lock) { m_lockgeom = lock; }
|
||||
|
||||
bool allowconnect () const { return m_allowconnect; }
|
||||
void allowconnect (bool val) { m_allowconnect = val; }
|
||||
|
||||
int arraylen () const { return m_typespec.arraylength(); }
|
||||
void arraylen (int len) {
|
||||
m_typespec.make_array(len);
|
||||
@@ -695,25 +681,28 @@ public:
|
||||
bool renderer_output () const { return m_renderer_output; }
|
||||
void renderer_output (bool v) { m_renderer_output = v; }
|
||||
|
||||
bool readonly () const { return m_readonly; }
|
||||
void readonly (bool v) { m_readonly = v; }
|
||||
|
||||
bool is_constant () const { return symtype() == SymTypeConst; }
|
||||
bool is_temp () const { return symtype() == SymTypeTemp; }
|
||||
|
||||
// Retrieve the const float value (will ASSERT if not a const float!)
|
||||
float get_float (int index = 0) {
|
||||
float get_float (int index = 0) const {
|
||||
ASSERT (data() && typespec().is_float_based());
|
||||
return ((const float *)data())[index];
|
||||
}
|
||||
|
||||
// Retrieve the const int value (will ASSERT if not a const int!)
|
||||
int get_int (int index = 0) {
|
||||
int get_int (int index = 0) const {
|
||||
ASSERT (data() && typespec().is_int_based());
|
||||
return ((const int *)data())[index];
|
||||
}
|
||||
|
||||
// Retrieve the const string value (will ASSERT if not a const string!)
|
||||
ustring get_string () {
|
||||
ustring get_string (int index = 0) const {
|
||||
ASSERT (data() && typespec().is_string());
|
||||
return ((const ustring *)data())[0];
|
||||
return ((const ustring *)data())[index];
|
||||
}
|
||||
|
||||
/// Stream output
|
||||
@@ -731,7 +720,9 @@ protected:
|
||||
unsigned m_connected_down:1;///< Connected to a later/downtream layer
|
||||
unsigned m_initialized:1; ///< If a param, has it been initialized?
|
||||
unsigned m_lockgeom:1; ///< Is the param not overridden by geom?
|
||||
unsigned m_allowconnect:1; ///< Is the param not overridden by geom?
|
||||
unsigned m_renderer_output:1; ///< Is this sym a renderer output?
|
||||
unsigned m_readonly:1; ///< read-only symbol
|
||||
char m_valuesource; ///< Where did the value come from?
|
||||
bool m_free_data; ///< Free m_data upon destruction?
|
||||
short m_fieldid; ///< Struct field of this var (or -1)
|
||||
|
||||
@@ -18,6 +18,15 @@ if (BUILDSTATIC)
|
||||
ADD_DEFINITIONS ( -DBUILD_STATIC=1 )
|
||||
else ()
|
||||
ADD_LIBRARY ( oslcomp SHARED ${liboslcomp_srcs} )
|
||||
|
||||
if (VERBOSE)
|
||||
message(STATUS "Setting SOVERSION to: ${SOVERSION}")
|
||||
endif ()
|
||||
set_target_properties( oslcomp
|
||||
PROPERTIES
|
||||
VERSION ${OSL_VERSION_MAJOR}.${OSL_VERSION_MINOR}.${OSL_VERSION_PATCH}
|
||||
SOVERSION ${SOVERSION} )
|
||||
|
||||
endif ()
|
||||
|
||||
TARGET_LINK_LIBRARIES ( oslcomp ${OPENIMAGEIO_LIBRARIES} ${ILMBASE_LIBRARIES}
|
||||
|
||||
+222
-41
@@ -26,10 +26,14 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <functional>
|
||||
#ifndef NDEBUG
|
||||
#include <atomic>
|
||||
#endif
|
||||
|
||||
#include "osl_pvt.h"
|
||||
#include "oslcomp_pvt.h"
|
||||
@@ -73,6 +77,21 @@ ScopeExit print_node_counts ([](){
|
||||
|
||||
|
||||
|
||||
ASTNode::ref
|
||||
reverse (ASTNode::ref list)
|
||||
{
|
||||
ASTNode::ref new_list;
|
||||
while (list) {
|
||||
ASTNode::ref next = list->next();
|
||||
list->m_next = new_list;
|
||||
new_list = list;
|
||||
list = next;
|
||||
}
|
||||
return new_list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ASTNode::ASTNode (NodeType nodetype, OSLCompilerImpl *compiler)
|
||||
: m_nodetype(nodetype), m_compiler(compiler),
|
||||
m_sourcefile(compiler->filename()),
|
||||
@@ -177,12 +196,7 @@ ASTNode::~ASTNode ()
|
||||
void
|
||||
ASTNode::error_impl (string_view msg) const
|
||||
{
|
||||
#if OIIO_VERSION >= 10803
|
||||
m_compiler->error (sourcefile(), sourceline(), "%s", msg);
|
||||
#else
|
||||
// DEPRECATED -- delete when minimum OIIO is at least 1.8
|
||||
m_compiler->error (sourcefile(), sourceline(), "%s", msg.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -190,12 +204,23 @@ ASTNode::error_impl (string_view msg) const
|
||||
void
|
||||
ASTNode::warning_impl (string_view msg) const
|
||||
{
|
||||
#if OIIO_VERSION >= 10803
|
||||
m_compiler->warning (sourcefile(), sourceline(), "%s", msg);
|
||||
#else
|
||||
// DEPRECATED -- delete when minimum OIIO is at least 1.8
|
||||
m_compiler->warning (sourcefile(), sourceline(), "%s", msg.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ASTNode::info_impl (string_view msg) const
|
||||
{
|
||||
m_compiler->info (sourcefile(), sourceline(), "%s", msg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ASTNode::message_impl (string_view msg) const
|
||||
{
|
||||
m_compiler->message (sourcefile(), sourceline(), "%s", msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -243,6 +268,45 @@ ASTNode::type_c_str (const TypeSpec &type) const
|
||||
|
||||
|
||||
|
||||
void
|
||||
ASTNode::list_to_vec (const ref &A, std::vector<ref> &vec)
|
||||
{
|
||||
vec.clear ();
|
||||
for (ref node = A; node; node = node->next())
|
||||
vec.push_back (node);
|
||||
}
|
||||
|
||||
|
||||
|
||||
ASTNode::ref
|
||||
ASTNode::vec_to_list (std::vector<ref> &vec)
|
||||
{
|
||||
if (vec.size()) {
|
||||
for (size_t i = 0; i < vec.size()-1; ++i)
|
||||
vec[i]->m_next = vec[i+1];
|
||||
vec[vec.size()-1]->m_next = NULL;
|
||||
return vec[0];
|
||||
} else {
|
||||
return ref();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string
|
||||
ASTNode::list_to_types_string (const ASTNode *node)
|
||||
{
|
||||
std::ostringstream result;
|
||||
for (int i = 0; node; node = node->nextptr(), ++i) {
|
||||
if (i)
|
||||
result << ", ";
|
||||
result << node->typespec();
|
||||
}
|
||||
return result.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
ASTshader_declaration::ASTshader_declaration (OSLCompilerImpl *comp,
|
||||
int stype, ustring name, ASTNode *form,
|
||||
ASTNode *stmts, ASTNode *meta)
|
||||
@@ -254,11 +318,11 @@ ASTshader_declaration::ASTshader_declaration (OSLCompilerImpl *comp,
|
||||
ASSERT (arg->nodetype() == variable_declaration_node);
|
||||
ASTvariable_declaration *v = (ASTvariable_declaration *)arg;
|
||||
if (! v->init())
|
||||
v->error ("shader parameter '%s' MUST have a default initializer",
|
||||
v->name().c_str());
|
||||
v->error ("shader parameter '%s' requires a default initializer",
|
||||
v->name());
|
||||
if (v->is_output() && v->typespec().is_unsized_array())
|
||||
v->error ("shader output parameter '%s' can't be unsized array",
|
||||
v->name().c_str());
|
||||
v->name());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,29 +360,31 @@ ASTshader_declaration::shadertypename () const
|
||||
|
||||
ASTfunction_declaration::ASTfunction_declaration (OSLCompilerImpl *comp,
|
||||
TypeSpec type, ustring name,
|
||||
ASTNode *form, ASTNode *stmts, ASTNode *meta)
|
||||
ASTNode *form, ASTNode *stmts, ASTNode *meta,
|
||||
int sourceline_start)
|
||||
: ASTNode (function_declaration_node, comp, 0, meta, form, stmts),
|
||||
m_name(name), m_sym(NULL), m_is_builtin(false)
|
||||
{
|
||||
m_typespec = type;
|
||||
Symbol *f = comp->symtab().clash (name);
|
||||
if (f && f->symtype() != SymTypeFunction) {
|
||||
error ("\"%s\" already declared in this scope as a ", name.c_str(),
|
||||
f->typespec().string().c_str());
|
||||
// Some trickery -- the compiler's idea of the "current" source line
|
||||
// is the END of the function body, so if a hint was passed about the
|
||||
// start of the declaration, substitute that.
|
||||
if (sourceline_start >= 0)
|
||||
m_sourceline = sourceline_start;
|
||||
|
||||
if (Strutil::starts_with (name, "___"))
|
||||
error ("\"%s\" : sorry, can't start with three underscores", name);
|
||||
|
||||
// Get a pointer to the first of the existing symbols of that name.
|
||||
Symbol *existing_syms = comp->symtab().clash (name);
|
||||
if (existing_syms && existing_syms->symtype() != SymTypeFunction) {
|
||||
error ("\"%s\" already declared in this scope as a %s",
|
||||
name, existing_syms->typespec());
|
||||
// FIXME -- print the file and line of the other definition
|
||||
f = NULL;
|
||||
existing_syms = NULL;
|
||||
}
|
||||
|
||||
// FIXME -- allow multiple function declarations, but only if they
|
||||
// aren't the same polymorphic type.
|
||||
|
||||
if (name[0] == '_' && name[1] == '_' && name[2] == '_') {
|
||||
error ("\"%s\" : sorry, can't start with three underscores",
|
||||
name.c_str());
|
||||
}
|
||||
|
||||
m_sym = new FunctionSymbol (name, type, this);
|
||||
func()->nextpoly ((FunctionSymbol *)f);
|
||||
// Build up the argument signature for this declared function
|
||||
m_typespec = type;
|
||||
std::string argcodes = oslcompiler->code_from_type (m_typespec);
|
||||
for (ASTNode *arg = form; arg; arg = arg->nextptr()) {
|
||||
const TypeSpec &t (arg->typespec());
|
||||
@@ -333,6 +399,44 @@ ASTfunction_declaration::ASTfunction_declaration (OSLCompilerImpl *comp,
|
||||
v->error ("function parameter '%s' may not have a default initializer.",
|
||||
v->name().c_str());
|
||||
}
|
||||
|
||||
// Allow multiple function declarations, but only if they aren't the
|
||||
// same polymorphic type in the same scope.
|
||||
if (stmts) {
|
||||
std::string err;
|
||||
int current_scope = oslcompiler->symtab().scopeid();
|
||||
for (FunctionSymbol *f = static_cast<FunctionSymbol *>(existing_syms);
|
||||
f; f = f->nextpoly()) {
|
||||
if (f->scope() == current_scope && f->argcodes() == argcodes) {
|
||||
// If the argcodes match, only one should have statements.
|
||||
// If there is no ASTNode for the poly, must be a builtin, and
|
||||
// has 'implicit' statements.
|
||||
auto other = static_cast<ASTfunction_declaration*>(f->node());
|
||||
if (!other || (other->statements() || other->is_builtin())) {
|
||||
if (err.empty()) {
|
||||
err = Strutil::format("Function '%s %s (%s)' redefined "
|
||||
"in the same scope\n"
|
||||
" Previous definitions:", type,
|
||||
name, list_to_types_string(form));
|
||||
}
|
||||
err += "\n ";
|
||||
if (other) {
|
||||
err += Strutil::format("%s:%d",
|
||||
OIIO::Filesystem::filename(other->sourcefile().string()),
|
||||
other->sourceline());
|
||||
} else
|
||||
err += "built-in";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!err.empty())
|
||||
warning ("%s", err);
|
||||
}
|
||||
|
||||
|
||||
m_sym = new FunctionSymbol (name, type, this);
|
||||
func()->nextpoly ((FunctionSymbol *)existing_syms);
|
||||
|
||||
func()->argcodes (ustring (argcodes));
|
||||
oslcompiler->symtab().insert (m_sym);
|
||||
|
||||
@@ -404,12 +508,25 @@ ASTvariable_declaration::ASTvariable_declaration (OSLCompilerImpl *comp,
|
||||
const TypeSpec &type,
|
||||
ustring name, ASTNode *init,
|
||||
bool isparam, bool ismeta,
|
||||
bool isoutput, bool initlist)
|
||||
bool isoutput, bool initlist,
|
||||
int sourceline_start)
|
||||
: ASTNode (variable_declaration_node, comp, 0, init, NULL /* meta */),
|
||||
m_name(name), m_sym(NULL),
|
||||
m_isparam(isparam), m_isoutput(isoutput), m_ismetadata(ismeta),
|
||||
m_initlist(initlist)
|
||||
{
|
||||
// Some trickery -- the compiler's idea of the "current" source line
|
||||
// is the END of the declaration, so if a hint was passed about the
|
||||
// start of the declaration, substitute that.
|
||||
if (sourceline_start >= 0)
|
||||
m_sourceline = sourceline_start;
|
||||
|
||||
if (m_initlist && init) {
|
||||
// Typecheck the init list early.
|
||||
ASSERT (init->nodetype() == compound_initializer_node);
|
||||
static_cast<ASTcompound_initializer*>(init)->typecheck(type);
|
||||
}
|
||||
|
||||
m_typespec = type;
|
||||
Symbol *f = comp->symtab().clash (name);
|
||||
if (f && ! m_ismetadata) {
|
||||
@@ -421,14 +538,13 @@ ASTvariable_declaration::ASTvariable_declaration (OSLCompilerImpl *comp,
|
||||
}
|
||||
if (f->scope() == 0 && f->symtype() == SymTypeFunction && isparam) {
|
||||
// special case: only a warning for param to mask global function
|
||||
warning ("%s", e.c_str());
|
||||
warning ("%s", e);
|
||||
} else {
|
||||
error ("%s", e.c_str());
|
||||
error ("%s", e);
|
||||
}
|
||||
}
|
||||
if (name[0] == '_' && name[1] == '_' && name[2] == '_') {
|
||||
error ("\"%s\" : sorry, can't start with three underscores",
|
||||
name.c_str());
|
||||
if (OIIO::Strutil::starts_with (name, "___")) {
|
||||
error ("\"%s\" : sorry, can't start with three underscores", name);
|
||||
}
|
||||
SymType symtype = isparam ? (isoutput ? SymTypeOutputParam : SymTypeParam)
|
||||
: SymTypeLocal;
|
||||
@@ -520,6 +636,14 @@ ASTvariable_ref::print (std::ostream &out, int indentlevel) const
|
||||
|
||||
|
||||
|
||||
ASTpreincdec::ASTpreincdec (OSLCompilerImpl *comp, int op, ASTNode *expr)
|
||||
: ASTNode (preincdec_node, comp, op, expr)
|
||||
{
|
||||
check_symbol_writeability (expr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *
|
||||
ASTpreincdec::childname (size_t i) const
|
||||
{
|
||||
@@ -529,6 +653,14 @@ ASTpreincdec::childname (size_t i) const
|
||||
|
||||
|
||||
|
||||
ASTpostincdec::ASTpostincdec (OSLCompilerImpl *comp, int op, ASTNode *expr)
|
||||
: ASTNode (postincdec_node, comp, op, expr)
|
||||
{
|
||||
check_symbol_writeability (expr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *
|
||||
ASTpostincdec::childname (size_t i) const
|
||||
{
|
||||
@@ -620,6 +752,8 @@ ASTstructselect::find_fieldsym (int &structid, int &fieldid)
|
||||
{
|
||||
if (! lvalue()->typespec().is_structure() &&
|
||||
! lvalue()->typespec().is_structure_array()) {
|
||||
error ("type '%s' does not have a member '%s'",
|
||||
type_c_str(lvalue()->typespec()), m_field);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -725,6 +859,18 @@ ASTconditional_statement::childname (size_t i) const
|
||||
|
||||
|
||||
|
||||
ASTloop_statement::ASTloop_statement (OSLCompilerImpl *comp, LoopType looptype,
|
||||
ASTNode *init, ASTNode *cond,
|
||||
ASTNode *iter, ASTNode *stmt)
|
||||
: ASTNode (loop_statement_node, comp, looptype, init, cond, iter, stmt)
|
||||
{
|
||||
// Handle empty comparison, for(;;), is same as for(;1;)
|
||||
if (!cond)
|
||||
m_children[1] = new ASTliteral(comp, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *
|
||||
ASTloop_statement::childname (size_t i) const
|
||||
{
|
||||
@@ -778,7 +924,8 @@ ASTreturn_statement::childname (size_t i) const
|
||||
|
||||
ASTcompound_initializer::ASTcompound_initializer (OSLCompilerImpl *comp,
|
||||
ASTNode *exprlist)
|
||||
: ASTNode (compound_initializer_node, comp, Nothing, exprlist)
|
||||
: ASTtype_constructor (compound_initializer_node, comp, TypeSpec(), exprlist),
|
||||
m_ctor(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -787,7 +934,39 @@ ASTcompound_initializer::ASTcompound_initializer (OSLCompilerImpl *comp,
|
||||
const char *
|
||||
ASTcompound_initializer::childname (size_t i) const
|
||||
{
|
||||
return "expression_list";
|
||||
return canconstruct() ? "args" : "expression_list";
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
ASTNode::check_symbol_writeability (ASTNode *var)
|
||||
{
|
||||
if (var->nodetype() == index_node)
|
||||
return check_symbol_writeability (static_cast<ASTindex*>(var)->lvalue().get());
|
||||
if (var->nodetype() == structselect_node)
|
||||
return check_symbol_writeability (static_cast<ASTstructselect*>(var)->lvalue().get());
|
||||
|
||||
Symbol *dest = nullptr;
|
||||
if (var->nodetype() == variable_ref_node)
|
||||
dest = static_cast<ASTvariable_ref*>(var)->sym();
|
||||
else if (var->nodetype() == variable_declaration_node)
|
||||
dest = static_cast<ASTvariable_declaration*>(var)->sym();
|
||||
|
||||
if (dest) {
|
||||
if (dest->readonly()) {
|
||||
warning ("cannot write to non-output parameter \"%s\"", dest->name());
|
||||
// Note: Consider it only a warning to write to a non-output
|
||||
// parameter. Users who want it to be a hard error can use
|
||||
// -Werror. Writing to any other readonly symbols is a full
|
||||
// error.
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// std::cout << "Don't know how to check_symbol_writeability "
|
||||
// << var->nodetypename() << "\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -801,6 +980,8 @@ ASTassign_expression::ASTassign_expression (OSLCompilerImpl *comp, ASTNode *var,
|
||||
m_op = Assign;
|
||||
m_children[1] = new ASTbinary_expression (comp, op, var, expr);
|
||||
}
|
||||
|
||||
check_symbol_writeability (var);
|
||||
}
|
||||
|
||||
|
||||
@@ -1015,14 +1196,14 @@ ASTtype_constructor::childname (size_t i) const
|
||||
ASTfunction_call::ASTfunction_call (OSLCompilerImpl *comp, ustring name,
|
||||
ASTNode *args, FunctionSymbol *funcsym)
|
||||
: ASTNode (function_call_node, comp, 0, args), m_name(name),
|
||||
m_sym(funcsym ? funcsym : comp->symtab().find (name)), // Look it up.
|
||||
m_poly(funcsym), // Default - resolved symbol or null
|
||||
m_argread(~1), // Default - all args are read except the first
|
||||
m_argwrite(1), // Default - first arg only is written by the op
|
||||
m_argtakesderivs(0) // Default - doesn't take derivs
|
||||
{
|
||||
// If we weren't passed a function symbol directly, look it up.
|
||||
m_sym = funcsym ? funcsym : comp->symtab().find (name);
|
||||
if (! m_sym) {
|
||||
error ("function '%s' was not declared in this scope", name.c_str());
|
||||
error ("function '%s' was not declared in this scope", name);
|
||||
// FIXME -- would be fun to troll through the symtab and try to
|
||||
// find the things that almost matched and offer suggestions.
|
||||
return;
|
||||
|
||||
+96
-81
@@ -172,6 +172,9 @@ public:
|
||||
return B;
|
||||
}
|
||||
|
||||
/// Reverse the order of the list.
|
||||
friend ASTNode::ref reverse (ASTNode::ref list);
|
||||
|
||||
/// What source file was this parse node created from?
|
||||
///
|
||||
ustring sourcefile () const { return m_sourcefile; }
|
||||
@@ -186,11 +189,7 @@ public:
|
||||
void error (string_view format, const Args&... args) const
|
||||
{
|
||||
DASSERT (format.size());
|
||||
#if OIIO_VERSION >= 10803
|
||||
error_impl (OIIO::Strutil::format (format, args...));
|
||||
#else /* DEPRECATE when OIIO minimum is at least 1.8 */
|
||||
error_impl (OIIO::Strutil::format (format.c_str(), args...));
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Warning reporting
|
||||
@@ -198,11 +197,23 @@ public:
|
||||
void warning (string_view format, const Args&... args) const
|
||||
{
|
||||
DASSERT (format.size());
|
||||
#if OIIO_VERSION >= 10803
|
||||
warning_impl (OIIO::Strutil::format (format, args...));
|
||||
#else /* DEPRECATE when OIIO minimum is at least 1.8 */
|
||||
warning_impl (OIIO::Strutil::format (format.c_str(), args...));
|
||||
#endif
|
||||
}
|
||||
|
||||
/// info reporting
|
||||
template<typename... Args>
|
||||
void info (string_view format, const Args&... args) const
|
||||
{
|
||||
DASSERT (format.size());
|
||||
info_impl (OIIO::Strutil::format (format, args...));
|
||||
}
|
||||
|
||||
/// message reporting
|
||||
template<typename... Args>
|
||||
void message (string_view format, const Args&... args) const
|
||||
{
|
||||
DASSERT (format.size());
|
||||
message_impl (OIIO::Strutil::format (format, args...));
|
||||
}
|
||||
|
||||
bool is_lvalue () const { return m_is_lvalue; }
|
||||
@@ -248,24 +259,15 @@ protected:
|
||||
|
||||
/// Flatten a list of nodes (headed by A) into a vector of node refs
|
||||
/// (vec).
|
||||
static void list_to_vec (const ref &A, std::vector<ref> &vec) {
|
||||
vec.clear ();
|
||||
for (ref node = A; node; node = node->next())
|
||||
vec.push_back (node);
|
||||
}
|
||||
static void list_to_vec (const ref &A, std::vector<ref> &vec);
|
||||
|
||||
/// Turn a vector of node refs into a list of nodes, returning its
|
||||
/// head.
|
||||
static ref vec_to_list (std::vector<ref> &vec) {
|
||||
if (vec.size()) {
|
||||
for (size_t i = 0; i < vec.size()-1; ++i)
|
||||
vec[i]->m_next = vec[i+1];
|
||||
vec[vec.size()-1]->m_next = NULL;
|
||||
return vec[0];
|
||||
} else {
|
||||
return ref();
|
||||
}
|
||||
}
|
||||
static ref vec_to_list (std::vector<ref> &vec);
|
||||
|
||||
/// Generate a comma-separated string of data types of the list headed
|
||||
/// by node (for example, "float, int, string").
|
||||
static std::string list_to_types_string (const ASTNode *node);
|
||||
|
||||
/// Return the number of child nodes.
|
||||
///
|
||||
@@ -301,7 +303,8 @@ protected:
|
||||
/// Type check a list (whose head is given by 'arg' against the list
|
||||
/// of expected types given in encoded form by 'formals'.
|
||||
bool check_arglist (const char *funcname, ref arg,
|
||||
const char *formals, bool coerce=false);
|
||||
const char *formals, bool coerce=false,
|
||||
bool bind = true);
|
||||
|
||||
/// Follow a list of nodes, generating code for each in turn, and return
|
||||
/// the Symbol* for the last thing generated.
|
||||
@@ -347,25 +350,28 @@ protected:
|
||||
bool copywholearrays, int intindex,
|
||||
bool paraminit);
|
||||
|
||||
// Helper: type check an initializer list -- either a single item to
|
||||
// a scalar, or a list to an array.
|
||||
void typecheck_initlist (ref init, TypeSpec type, string_view name);
|
||||
|
||||
// Helper: generate code for an initializer list -- either a single
|
||||
// item to a scalar, or a list to an array.
|
||||
void codegen_initlist (ref init, TypeSpec type, Symbol *sym);
|
||||
|
||||
// Special type checking for structure member initializers.
|
||||
// It's in the ASTNode base class because it's used from mutiple
|
||||
// subclasses.
|
||||
TypeSpec typecheck_struct_initializers (ref init, TypeSpec type,
|
||||
string_view name);
|
||||
|
||||
// Special code generation for structure initializers.
|
||||
// It's in the ASTNode base class because it's used from mutiple
|
||||
// subclasses.
|
||||
Symbol *codegen_struct_initializers (ref init, Symbol *sym,
|
||||
bool is_constructor=false);
|
||||
bool is_constructor=false,
|
||||
Symbol *arrayindex = nullptr);
|
||||
|
||||
// Codegen an array assignemnt: lval[index] = src
|
||||
// If no index is provided the constant i is used.
|
||||
// Will return either src or a temporary that was codegened.
|
||||
Symbol*
|
||||
codegen_aassign (TypeSpec elemtype, Symbol *src, Symbol *lval,
|
||||
Symbol* index, int i = 0);
|
||||
|
||||
// Check whether the node's symbol destination is ok to write. Return
|
||||
// true if ok, return false and issue error or warning if not. (Used to
|
||||
// check for writing to read-only variables like non-output parameters.)
|
||||
bool check_symbol_writeability (ASTNode *var);
|
||||
|
||||
// Helper for param_default_literals: generate the string that gives
|
||||
// the initialization of the literal value (and/or the default, if
|
||||
@@ -376,6 +382,8 @@ protected:
|
||||
|
||||
void error_impl (string_view msg) const;
|
||||
void warning_impl (string_view msg) const;
|
||||
void info_impl (string_view msg) const;
|
||||
void message_impl (string_view msg) const;
|
||||
|
||||
protected:
|
||||
NodeType m_nodetype; ///< Type of node this is
|
||||
@@ -420,7 +428,8 @@ class ASTfunction_declaration : public ASTNode
|
||||
{
|
||||
public:
|
||||
ASTfunction_declaration (OSLCompilerImpl *comp, TypeSpec type, ustring name,
|
||||
ASTNode *form, ASTNode *stmts, ASTNode *meta=NULL);
|
||||
ASTNode *form, ASTNode *stmts, ASTNode *meta,
|
||||
int sourceline_start=-1);
|
||||
const char *nodetypename () const { return "function_declaration"; }
|
||||
const char *childname (size_t i) const;
|
||||
void print (std::ostream &out, int indentlevel=0) const;
|
||||
@@ -449,9 +458,9 @@ class ASTvariable_declaration : public ASTNode
|
||||
{
|
||||
public:
|
||||
ASTvariable_declaration (OSLCompilerImpl *comp, const TypeSpec &type,
|
||||
ustring name, ASTNode *init, bool isparam=false,
|
||||
bool ismeta=false, bool isoutput=false,
|
||||
bool initlist=false);
|
||||
ustring name, ASTNode *init, bool isparam,
|
||||
bool ismeta, bool isoutput,
|
||||
bool initlist, int sourceline_start=-1);
|
||||
const char *nodetypename () const;
|
||||
const char *childname (size_t i) const;
|
||||
void print (std::ostream &out, int indentlevel=0) const;
|
||||
@@ -522,9 +531,7 @@ private:
|
||||
class ASTpreincdec : public ASTNode
|
||||
{
|
||||
public:
|
||||
ASTpreincdec (OSLCompilerImpl *comp, int op, ASTNode *expr)
|
||||
: ASTNode (preincdec_node, comp, op, expr)
|
||||
{ }
|
||||
ASTpreincdec (OSLCompilerImpl *comp, int op, ASTNode *expr);
|
||||
const char *nodetypename () const { return m_op==Incr ? "preincrement" : "predecrement"; }
|
||||
const char *childname (size_t i) const;
|
||||
TypeSpec typecheck (TypeSpec expected);
|
||||
@@ -538,9 +545,7 @@ public:
|
||||
class ASTpostincdec : public ASTNode
|
||||
{
|
||||
public:
|
||||
ASTpostincdec (OSLCompilerImpl *comp, int op, ASTNode *expr)
|
||||
: ASTNode (postincdec_node, comp, op, expr)
|
||||
{ }
|
||||
ASTpostincdec (OSLCompilerImpl *comp, int op, ASTNode *expr);
|
||||
const char *nodetypename () const { return m_op==Incr ? "postincrement" : "postdecrement"; }
|
||||
const char *childname (size_t i) const;
|
||||
TypeSpec typecheck (TypeSpec expected);
|
||||
@@ -650,9 +655,7 @@ public:
|
||||
};
|
||||
|
||||
ASTloop_statement (OSLCompilerImpl *comp, LoopType looptype, ASTNode *init,
|
||||
ASTNode *cond, ASTNode *iter, ASTNode *stmt)
|
||||
: ASTNode (loop_statement_node, comp, looptype, init, cond, iter, stmt)
|
||||
{ }
|
||||
ASTNode *cond, ASTNode *iter, ASTNode *stmt);
|
||||
|
||||
const char *nodetypename () const { return "loop_statement"; }
|
||||
const char *childname (size_t i) const;
|
||||
@@ -705,8 +708,41 @@ public:
|
||||
|
||||
|
||||
|
||||
class ASTcompound_initializer : public ASTNode
|
||||
class ASTtype_constructor : public ASTNode
|
||||
{
|
||||
protected:
|
||||
ASTtype_constructor (NodeType n, OSLCompilerImpl *c, TypeSpec t, ASTNode *a)
|
||||
: ASTNode (n, c, Nothing, a) { m_typespec = t; }
|
||||
|
||||
public:
|
||||
ASTtype_constructor (OSLCompilerImpl *comp, TypeSpec typespec,
|
||||
ASTNode *args)
|
||||
: ASTtype_constructor (type_constructor_node, comp, typespec, args) {}
|
||||
|
||||
const char *nodetypename () const { return "type_constructor"; }
|
||||
const char *childname (size_t i) const;
|
||||
Symbol *codegen (Symbol *dest = NULL);
|
||||
|
||||
ref args () const { return child (0); }
|
||||
|
||||
// Typecheck construction of expected against args()
|
||||
// Optionally ignoring errors and binding any init-list arguments to the
|
||||
// required type.
|
||||
TypeSpec typecheck (TypeSpec expected, bool error, bool bind = true);
|
||||
|
||||
// Typecheck construction of m_typespec against args()
|
||||
TypeSpec typecheck (TypeSpec expected) {
|
||||
return typecheck (m_typespec, true, true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ASTcompound_initializer : public ASTtype_constructor
|
||||
{
|
||||
bool m_ctor;
|
||||
|
||||
TypeSpec typecheck (TypeSpec expected, unsigned mode);
|
||||
|
||||
public:
|
||||
ASTcompound_initializer (OSLCompilerImpl *comp, ASTNode *exprlist);
|
||||
const char *nodetypename () const { return "compound_initializer"; }
|
||||
@@ -714,6 +750,16 @@ public:
|
||||
Symbol *codegen (Symbol *dest = NULL);
|
||||
|
||||
ref initlist () const { return child (0); }
|
||||
|
||||
bool canconstruct() const { return m_ctor; }
|
||||
void canconstruct(bool b) { m_ctor = b; }
|
||||
|
||||
TypeSpec typecheck (TypeSpec expected) {
|
||||
return typecheck(expected, 0);
|
||||
}
|
||||
|
||||
// Helper for typechecking an initlist or structure.
|
||||
class TypeAdjuster;
|
||||
};
|
||||
|
||||
|
||||
@@ -838,26 +884,6 @@ public:
|
||||
|
||||
|
||||
|
||||
class ASTtype_constructor : public ASTNode
|
||||
{
|
||||
public:
|
||||
ASTtype_constructor (OSLCompilerImpl *comp, TypeSpec typespec,
|
||||
ASTNode *args)
|
||||
: ASTNode (type_constructor_node, comp, 0, args)
|
||||
{
|
||||
m_typespec = typespec;
|
||||
}
|
||||
|
||||
const char *nodetypename () const { return "type_constructor"; }
|
||||
const char *childname (size_t i) const;
|
||||
TypeSpec typecheck (TypeSpec expected);
|
||||
Symbol *codegen (Symbol *dest = NULL);
|
||||
|
||||
ref args () const { return child (0); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ASTfunction_call : public ASTNode
|
||||
{
|
||||
public:
|
||||
@@ -885,21 +911,10 @@ public:
|
||||
/// Pointer to the ASTfunction_declaration node that defines the user
|
||||
/// function, or NULL if it's not a user-defined function.
|
||||
ASTfunction_declaration * user_function () const {
|
||||
return (ASTfunction_declaration *) func()->node();
|
||||
return func() ? (ASTfunction_declaration *) func()->node() : nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Typecheck all polymorphic versions, return UNKNOWN if no match was
|
||||
/// found, or a real type if there was a match. Also, upon matching,
|
||||
/// re-jigger m_sym to point to the specific polymorphic match.
|
||||
/// Allow arguments to be coerced (e.g., substituting a vector where
|
||||
/// a point was expected, or a float where a color was expected) only
|
||||
/// if coerceargs is true. For return values, allow spatial triples to
|
||||
/// mutually match if 'equivreturn' is true, and allow any coercive
|
||||
/// return type if 'expected' is TypeSpec() (i.e., unknown).
|
||||
TypeSpec typecheck_all_poly (TypeSpec expected, bool coerceargs,
|
||||
bool equivreturn);
|
||||
|
||||
/// Handle all the special cases for built-ins. This includes
|
||||
/// irregular patterns of which args are read vs written, special
|
||||
/// checks for printf- and texture-like, etc.
|
||||
|
||||
+183
-63
@@ -461,10 +461,27 @@ ASTreturn_statement::codegen (Symbol *dest)
|
||||
|
||||
|
||||
Symbol *
|
||||
ASTcompound_initializer::codegen (Symbol *dest)
|
||||
ASTcompound_initializer::codegen (Symbol *sym)
|
||||
{
|
||||
ASSERT(0 && "compound codegen");
|
||||
return NULL;
|
||||
if (canconstruct())
|
||||
return ASTtype_constructor::codegen(sym);
|
||||
|
||||
if (m_typespec.is_structure_based()) {
|
||||
if (!sym)
|
||||
sym = m_compiler->make_temporary (m_typespec);
|
||||
return codegen_struct_initializers (initlist(), sym, true /*is_constructor*/);
|
||||
}
|
||||
|
||||
if (m_typespec.is_sized_array()) {
|
||||
if (!sym)
|
||||
sym = m_compiler->make_temporary (m_typespec);
|
||||
codegen_initlist (initlist(), m_typespec, sym);
|
||||
return sym;
|
||||
}
|
||||
|
||||
error("Possible compiler bug: compound_initializer codegen does not "
|
||||
"know how to handle type %s", typespec());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -648,7 +665,7 @@ ASTNode::one_default_literal (const Symbol *sym, ASTNode *init,
|
||||
if (islit && lit->typespec().is_int())
|
||||
out += Strutil::format ("%d", lit->intval());
|
||||
else if (islit && lit->typespec().is_float())
|
||||
out += Strutil::format ("%.8g", lit->floatval());
|
||||
out += Strutil::format ("%.9g", lit->floatval());
|
||||
else {
|
||||
out += "0"; // FIXME?
|
||||
completed = false;
|
||||
@@ -656,12 +673,14 @@ ASTNode::one_default_literal (const Symbol *sym, ASTNode *init,
|
||||
} else if (type.is_triple()) {
|
||||
if (islit && lit->typespec().is_int()) {
|
||||
float f = lit->intval();
|
||||
out += Strutil::format ("%.8g%s%.8g%s%.8g", f, sep, f, sep, f);
|
||||
out += Strutil::format ("%.9g%s%.9g%s%.9g", f, sep, f, sep, f);
|
||||
} else if (islit && lit->typespec().is_float()) {
|
||||
float f = lit->floatval();
|
||||
out += Strutil::format ("%.8g%s%.8g%s%.8g", f, sep, f, sep, f);
|
||||
out += Strutil::format ("%.9g%s%.9g%s%.9g", f, sep, f, sep, f);
|
||||
} else if (init && init->typespec() == type &&
|
||||
init->nodetype() == ASTNode::type_constructor_node) {
|
||||
(init->nodetype() == ASTNode::type_constructor_node ||
|
||||
(init->nodetype() == ASTNode::compound_initializer_node &&
|
||||
static_cast<ASTcompound_initializer*>(init)->canconstruct()))) {
|
||||
ASTtype_constructor *ctr = (ASTtype_constructor *) init;
|
||||
ASTNode::ref val = ctr->args();
|
||||
float f[3];
|
||||
@@ -686,9 +705,9 @@ ASTNode::one_default_literal (const Symbol *sym, ASTNode *init,
|
||||
}
|
||||
}
|
||||
if (nargs == 1)
|
||||
out += Strutil::format ("%.8g%s%.8g%s%.8g", f[0], sep, f[0], sep, f[0]);
|
||||
out += Strutil::format ("%.9g%s%.9g%s%.9g", f[0], sep, f[0], sep, f[0]);
|
||||
else
|
||||
out += Strutil::format ("%.8g%s%.8g%s%.8g", f[0], sep, f[1], sep, f[2]);
|
||||
out += Strutil::format ("%.9g%s%.9g%s%.9g", f[0], sep, f[1], sep, f[2]);
|
||||
} else {
|
||||
out += Strutil::format ("0%s0%s0", sep, sep);
|
||||
completed = false;
|
||||
@@ -697,12 +716,12 @@ ASTNode::one_default_literal (const Symbol *sym, ASTNode *init,
|
||||
if (islit && lit->typespec().is_int()) {
|
||||
float f = lit->intval();
|
||||
for (int c = 0; c < 16; ++c)
|
||||
out += Strutil::format ("%.8g%s", (c/4)==(c%4) ? f : 0.0f,
|
||||
out += Strutil::format ("%.9g%s", (c/4)==(c%4) ? f : 0.0f,
|
||||
c<15 ? sep.c_str() : "");
|
||||
} else if (islit && lit->typespec().is_float()) {
|
||||
float f = lit->floatval();
|
||||
for (int c = 0; c < 16; ++c)
|
||||
out += Strutil::format ("%.8g%s", (c/4)==(c%4) ? f : 0.0f,
|
||||
out += Strutil::format ("%.9g%s", (c/4)==(c%4) ? f : 0.0f,
|
||||
c<15 ? sep.c_str() : "");
|
||||
} else if (init && init->typespec() == type &&
|
||||
init->nodetype() == ASTNode::type_constructor_node) {
|
||||
@@ -730,11 +749,11 @@ ASTNode::one_default_literal (const Symbol *sym, ASTNode *init,
|
||||
}
|
||||
if (nargs == 1) {
|
||||
for (int c = 0; c < 16; ++c)
|
||||
out += Strutil::format ("%.8g%s", (c/4)==(c%4) ? f[0] : 0.0f,
|
||||
out += Strutil::format ("%.9g%s", (c/4)==(c%4) ? f[0] : 0.0f,
|
||||
c<15 ? sep.c_str() : "");
|
||||
} else {
|
||||
for (int c = 0; c < 16; ++c)
|
||||
out += Strutil::format ("%.8g%s", f[c], c<15 ? sep.c_str() : "");
|
||||
out += Strutil::format ("%.9g%s", f[c], c<15 ? sep.c_str() : "");
|
||||
}
|
||||
} else {
|
||||
for (int c = 0; c < 16; ++c)
|
||||
@@ -786,7 +805,9 @@ ASTvariable_declaration::param_default_literals (const Symbol *sym,
|
||||
|
||||
bool compound = (init && init->nodetype() == compound_initializer_node);
|
||||
if (compound) {
|
||||
init = ((ASTcompound_initializer *)init)->initlist().get();
|
||||
compound = !static_cast<ASTcompound_initializer*>(init)->canconstruct();
|
||||
if (compound)
|
||||
init = ((ASTcompound_initializer *)init)->initlist().get();
|
||||
}
|
||||
|
||||
bool completed = true; // have we output the full initialization?
|
||||
@@ -823,13 +844,61 @@ ASTvariable_declaration::codegen_initializer (ref init, Symbol *sym)
|
||||
init = ((ASTcompound_initializer *)init.get())->initlist();
|
||||
codegen_initlist (init, typespec(), sym);
|
||||
} else {
|
||||
if (init->nodetype() == compound_initializer_node)
|
||||
init = ((ASTcompound_initializer *)init.get())->initlist();
|
||||
if (init->nodetype() == compound_initializer_node) {
|
||||
ASTcompound_initializer* cinit = static_cast<ASTcompound_initializer*>(init.get());
|
||||
init = cinit->initlist();
|
||||
if (cinit->canconstruct()) {
|
||||
bool paraminit = (m_compiler->codegen_method() != m_compiler->main_method_name() &&
|
||||
(m_sym->symtype() == SymTypeParam ||
|
||||
m_sym->symtype() == SymTypeOutputParam));
|
||||
if (paraminit) {
|
||||
// For parameter initialization, don't really generate ops if it
|
||||
// can be statically initialized.
|
||||
m_compiler->codegen_method (sym->name());
|
||||
sym->initbegin (m_compiler->next_op_label ());
|
||||
}
|
||||
|
||||
Symbol* dest = cinit->codegen(sym);
|
||||
if (dest != sym)
|
||||
emitcode ("assign", sym, dest);
|
||||
|
||||
if (paraminit)
|
||||
sym->initend (m_compiler->next_op_label ());
|
||||
return;
|
||||
}
|
||||
}
|
||||
codegen_initlist (init, m_typespec, m_sym);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Symbol*
|
||||
ASTNode::codegen_aassign (TypeSpec elemtype, Symbol *src, Symbol *lval,
|
||||
Symbol* ind, int i)
|
||||
{
|
||||
const TypeSpec& srctype = src->typespec();
|
||||
if (! equivalent (elemtype, srctype)) {
|
||||
// Allow floatarray[ind] = int or intarray[ind] = float, but otherwise
|
||||
// A[ind] = x is only allowed if the type of x is equivalent to that of
|
||||
// A's elements.
|
||||
// You can't for example, do colorarray[ind] = int.
|
||||
if (elemtype.is_closure() || !elemtype.is_scalarnum() ||
|
||||
srctype.is_closure() || !srctype.is_scalarnum()) {
|
||||
// Convert through a temp.
|
||||
Symbol *tmp = m_compiler->make_temporary (elemtype);
|
||||
emitcode ("assign", tmp, src);
|
||||
src = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ind)
|
||||
ind = m_compiler->make_constant (i);
|
||||
|
||||
emitcode ("aassign", lval, ind, src);
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ASTNode::codegen_initlist (ref init, TypeSpec type, Symbol *sym)
|
||||
@@ -863,6 +932,12 @@ ASTNode::codegen_initlist (ref init, TypeSpec type, Symbol *sym)
|
||||
}
|
||||
|
||||
if (paraminit) {
|
||||
// Warn early about struct array paramters.
|
||||
// Handling this will likely need changes to oso format.
|
||||
if (type.is_structure_array()) {
|
||||
error ("array of struct are not allowed as parameters");
|
||||
return;
|
||||
}
|
||||
// For parameter initialization, don't really generate ops if it
|
||||
// can be statically initialized.
|
||||
m_compiler->codegen_method (sym->name());
|
||||
@@ -914,10 +989,39 @@ ASTNode::codegen_initlist (ref init, TypeSpec type, Symbol *sym)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (type.is_structure_array()) {
|
||||
for (int i = 0; init && i < type.arraylength(); ++i) {
|
||||
ASTNode* expr = init.get();
|
||||
bool ctor = false;
|
||||
Symbol* dest = sym;
|
||||
switch (expr->nodetype()) {
|
||||
case function_call_node: {
|
||||
ASTfunction_call* fcall = static_cast<ASTfunction_call*>(expr);
|
||||
if ((ctor = fcall->is_struct_ctr())) {
|
||||
expr = fcall->args().get();
|
||||
ASSERT (expr != nullptr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case compound_initializer_node:
|
||||
ctor = static_cast<ASTcompound_initializer*>(expr)->canconstruct();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
codegen_struct_initializers (expr, dest, ctor,
|
||||
m_compiler->make_constant(i));
|
||||
|
||||
init = init->next();
|
||||
}
|
||||
if (paraminit)
|
||||
sym->initend (m_compiler->next_op_label ());
|
||||
return;
|
||||
}
|
||||
else if (init->nodetype() == compound_initializer_node)
|
||||
init = ((ASTcompound_initializer *)init.get())->initlist();
|
||||
|
||||
// Loop over a list of initializers (it's just 1 if not an array)...
|
||||
if (init->nodetype() == compound_initializer_node)
|
||||
init = ((ASTcompound_initializer *)init.get())->initlist();
|
||||
for (int i = 0; init; init = init->next(), ++i) {
|
||||
if (sym->typespec().is_structure() &&
|
||||
init->nodetype() == compound_initializer_node) {
|
||||
@@ -931,17 +1035,8 @@ ASTNode::codegen_initlist (ref init, TypeSpec type, Symbol *sym)
|
||||
if (dest != sym) {
|
||||
if (sym->typespec().is_array()) {
|
||||
// Array variable -- assign to the i-th element
|
||||
TypeSpec elemtype = sym->typespec().elementtype();
|
||||
if (! equivalent (elemtype, dest->typespec())) {
|
||||
// We only allow A[ind] = x if the type of x is
|
||||
// equivalent to that of A's elements. You can't,
|
||||
// for example, do floatarray[ind] = int. So we
|
||||
// convert through a temp.
|
||||
Symbol *tmp = dest;
|
||||
dest = m_compiler->make_temporary (elemtype);
|
||||
emitcode ("assign", dest, tmp);
|
||||
}
|
||||
emitcode ("aassign", sym, m_compiler->make_constant(i), dest);
|
||||
dest = codegen_aassign (sym->typespec().elementtype(), dest,
|
||||
sym, nullptr, i);
|
||||
} else {
|
||||
// Non-array variable, just a simple assignment
|
||||
emitcode ("assign", sym, dest);
|
||||
@@ -959,7 +1054,7 @@ ASTNode::codegen_initlist (ref init, TypeSpec type, Symbol *sym)
|
||||
|
||||
Symbol *
|
||||
ASTNode::codegen_struct_initializers (ref init, Symbol *sym,
|
||||
bool is_constructor)
|
||||
bool is_constructor, Symbol *arrayindex)
|
||||
{
|
||||
// If we're doing this initialization for shader params for their
|
||||
// init ops, we need to take care to set the codegen method names
|
||||
@@ -968,21 +1063,21 @@ ASTNode::codegen_struct_initializers (ref init, Symbol *sym,
|
||||
(sym->symtype() == SymTypeParam ||
|
||||
sym->symtype() == SymTypeOutputParam));
|
||||
|
||||
ASSERT (sym->typespec().is_structure());
|
||||
ASSERT (sym->typespec().is_structure_based());
|
||||
if (init->nodetype() != compound_initializer_node && !is_constructor) {
|
||||
// Just one initializer, it's a whole struct of the right type.
|
||||
Symbol *initsym = init->codegen (sym);
|
||||
if (initsym != sym) {
|
||||
StructSpec *structspec (sym->typespec().structspec());
|
||||
codegen_assign_struct (structspec, ustring(sym->mangled()),
|
||||
ustring(initsym->mangled()), NULL, true, 0,
|
||||
paraminit);
|
||||
ustring(initsym->mangled()), arrayindex,
|
||||
true, 0, paraminit);
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
|
||||
// General case -- per-field initializers
|
||||
if (init->nodetype() == compound_initializer_node) {
|
||||
if (!is_constructor && init->nodetype() == compound_initializer_node) {
|
||||
init = ((ASTcompound_initializer *)init.get())->initlist();
|
||||
}
|
||||
StructSpec *structspec (sym->typespec().structspec());
|
||||
@@ -992,35 +1087,51 @@ ASTNode::codegen_struct_initializers (ref init, Symbol *sym,
|
||||
ustring fieldname = ustring::format ("%s.%s", sym->mangled().c_str(),
|
||||
field.name.c_str());
|
||||
Symbol *fieldsym = m_compiler->symtab().find_exact (fieldname);
|
||||
if (fieldsym->typespec().is_structure()) {
|
||||
if (fieldsym->typespec().is_structure_based() &&
|
||||
(init->nodetype() == type_constructor_node ||
|
||||
init->nodetype() == compound_initializer_node)) {
|
||||
bool ctor = init->nodetype() == type_constructor_node ? true :
|
||||
static_cast<ASTcompound_initializer*>(init.get())->canconstruct();
|
||||
// The field is itself a nested struct, so recurse
|
||||
codegen_struct_initializers (init, fieldsym);
|
||||
codegen_struct_initializers (init, fieldsym, ctor, arrayindex);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (paraminit) {
|
||||
if (paraminit && nodetype() == variable_declaration_node) {
|
||||
// For parameter initialization, don't really generate ops if it
|
||||
// can be statically initialized.
|
||||
std::string out;
|
||||
ASSERT (nodetype() == variable_declaration_node);
|
||||
ASTvariable_declaration *v = (ASTvariable_declaration *)this;
|
||||
if (v->param_default_literals (fieldsym, init.get(), out))
|
||||
continue;
|
||||
|
||||
}
|
||||
if (paraminit) {
|
||||
// Delineate and remember the init ops for this field individually
|
||||
m_compiler->codegen_method (fieldname);
|
||||
fieldsym->initbegin (m_compiler->next_op_label ());
|
||||
}
|
||||
|
||||
if (init->nodetype() == compound_initializer_node) {
|
||||
if (init->nodetype() == compound_initializer_node &&
|
||||
!((ASTcompound_initializer *)init.get())->canconstruct()) {
|
||||
// Initialize the field with a compound initializer
|
||||
codegen_initlist (((ASTcompound_initializer *)init.get())->initlist(),
|
||||
field.type, fieldsym);
|
||||
} else {
|
||||
} else if (init->nodetype() == function_call_node &&
|
||||
static_cast<ASTfunction_call*>(init.get())->is_struct_ctr()) {
|
||||
codegen_struct_initializers (static_cast<ASTfunction_call*>(init.get())->args(),
|
||||
fieldsym, true, arrayindex);
|
||||
}
|
||||
else {
|
||||
// Initialize the field with a scalar initializer
|
||||
Symbol *dest = init->codegen (fieldsym);
|
||||
if (dest != fieldsym)
|
||||
emitcode ("assign", fieldsym, dest);
|
||||
if (dest != fieldsym) {
|
||||
if (!arrayindex)
|
||||
emitcode ("assign", fieldsym, dest);
|
||||
else {
|
||||
dest = codegen_aassign (fieldsym->typespec().elementtype(),
|
||||
dest, fieldsym, arrayindex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (paraminit)
|
||||
@@ -1177,19 +1288,8 @@ ASTindex::codegen_assign (Symbol *src, Symbol *ind,
|
||||
emitcode ("compassign", temp, ind2, src);
|
||||
emitcode ("aassign", lv, ind, temp);
|
||||
}
|
||||
else if (! equivalent (elemtype, src->typespec())) {
|
||||
// Type conversion, e.g., colorarray[i] = float or
|
||||
// floatarray[i] = int
|
||||
// We only allow A[ind] = x if the type of x is equivalent
|
||||
// to that of A's elements. You can't, for example, do
|
||||
// floatarray[ind] = int. So we convert through a temp.
|
||||
Symbol *tmp = src;
|
||||
src = m_compiler->make_temporary (elemtype);
|
||||
emitcode ("assign", src, tmp);
|
||||
emitcode ("aassign", lv, ind, src);
|
||||
} else {
|
||||
// Simple Xarray[i] = X
|
||||
emitcode ("aassign", lv, ind, src);
|
||||
else {
|
||||
src = codegen_aassign (elemtype, src, lv, ind);
|
||||
}
|
||||
} else if (lv->typespec().is_triple()) {
|
||||
emitcode ("compassign", lv, ind, src);
|
||||
@@ -1322,7 +1422,8 @@ ASTloop_statement::codegen (Symbol *)
|
||||
codegen_list (init());
|
||||
|
||||
int condlabel = m_compiler->next_op_label ();
|
||||
Symbol *condvar = cond()->codegen_int ();
|
||||
Symbol *condvar = cond()->codegen_int (/*dest=*/ nullptr,
|
||||
/*boolify=*/ true);
|
||||
|
||||
// Retroactively add the argument
|
||||
size_t argstart = m_compiler->add_op_args (1, &condvar);
|
||||
@@ -1605,11 +1706,19 @@ ASTtype_constructor::codegen (Symbol *dest)
|
||||
// Doesn't fit the pattern, drop to the usual case...
|
||||
}
|
||||
|
||||
// Special case: construct float(float_expr) -- just put it directly
|
||||
// in the dest.
|
||||
Symbol *argevaldest = nullptr;
|
||||
if (dest && typespec().is_float() &&
|
||||
nchildren() == 1 && child(0)->typespec().is_float()) {
|
||||
argevaldest = dest;
|
||||
}
|
||||
|
||||
std::vector<Symbol *> argdest;
|
||||
argdest.push_back (dest);
|
||||
int nargs = 0;
|
||||
for (ref a = args(); a; a = a->next(), ++nargs) {
|
||||
Symbol *argval = a->codegen();
|
||||
Symbol *argval = a->codegen(argevaldest);
|
||||
if (argval->typespec().is_int() && !typespec().is_int()) {
|
||||
// Coerce to float if it's an int
|
||||
if (a->nodetype() == literal_node) {
|
||||
@@ -1625,9 +1734,16 @@ ASTtype_constructor::codegen (Symbol *dest)
|
||||
}
|
||||
argdest.push_back (argval);
|
||||
}
|
||||
if (nargs == 1)
|
||||
if (nargs == 1 && argdest.size() == 2 && argdest[1] == dest) {
|
||||
// Don't have to do anything, we already coaxed the one argument
|
||||
// to show up in the requested destination. This can happen for
|
||||
// foo = float(float_expr)
|
||||
// to avoid the extra needless copy.
|
||||
}
|
||||
else if (nargs == 1) {
|
||||
emitcode ("assign",
|
||||
argdest.size(), (argdest.size())? &argdest[0]: NULL);
|
||||
}
|
||||
else
|
||||
emitcode (typespec().string().c_str(),
|
||||
argdest.size(), (argdest.size())? &argdest[0]: NULL);
|
||||
@@ -1734,6 +1850,7 @@ ASTfunction_call::codegen (Symbol *dest)
|
||||
// alias each of the fields
|
||||
if (a->nodetype() == variable_ref_node ||
|
||||
a->nodetype() == function_call_node ||
|
||||
a->nodetype() == compound_initializer_node ||
|
||||
a->nodetype() == binary_expression_node ||
|
||||
a->nodetype() == unary_expression_node) {
|
||||
// Passed a variable that is a struct ; make the struct
|
||||
@@ -1873,10 +1990,13 @@ ASTfunction_call::codegen_arg (SymbolPtrVec &argdest, SymbolPtrVec &index1,
|
||||
form->typespec().c_str());
|
||||
}
|
||||
}
|
||||
argdest.push_back (thisarg);
|
||||
index1.push_back (ind1);
|
||||
index2.push_back (ind2);
|
||||
index3.push_back (ind3);
|
||||
if (thisarg) {
|
||||
argdest.push_back (thisarg);
|
||||
index1.push_back (ind1);
|
||||
index2.push_back (ind2);
|
||||
index3.push_back (ind3);
|
||||
} else
|
||||
arg->error("Invalid argument to function");
|
||||
}
|
||||
|
||||
|
||||
|
||||
+122
-67
@@ -95,12 +95,12 @@ OSLCompiler::compile (string_view filename,
|
||||
|
||||
|
||||
bool
|
||||
OSLCompiler::compile_buffer (string_view sourcecode,
|
||||
std::string &osobuffer,
|
||||
OSLCompiler::compile_buffer (string_view sourcecode, std::string &osobuffer,
|
||||
const std::vector<std::string> &options,
|
||||
string_view stdoslpath)
|
||||
string_view stdoslpath, string_view filename)
|
||||
{
|
||||
return m_impl->compile_buffer (sourcecode, osobuffer, options, stdoslpath);
|
||||
return m_impl->compile_buffer (sourcecode, osobuffer, options,
|
||||
stdoslpath, filename);
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +116,8 @@ OSLCompiler::output_filename () const
|
||||
namespace pvt { // OSL::pvt
|
||||
|
||||
|
||||
OSLCompilerImpl *oslcompiler = NULL;
|
||||
OSLCompilerImpl *oslcompiler = nullptr;
|
||||
static std::mutex oslcompiler_mutex;
|
||||
|
||||
static ustring op_for("for");
|
||||
static ustring op_while("while");
|
||||
@@ -129,7 +130,8 @@ OSLCompilerImpl::OSLCompilerImpl (ErrorHandler *errhandler)
|
||||
m_err(false), m_symtab(*this),
|
||||
m_current_typespec(TypeDesc::UNKNOWN), m_current_output(false),
|
||||
m_verbose(false), m_quiet(false), m_debug(false),
|
||||
m_preprocess_only(false), m_optimizelevel(1),
|
||||
m_preprocess_only(false), m_err_on_warning(false),
|
||||
m_optimizelevel(1),
|
||||
m_next_temp(0), m_next_const(0),
|
||||
m_osofile(NULL),
|
||||
m_total_nesting(0), m_loop_nesting(0), m_derivsym(NULL),
|
||||
@@ -204,8 +206,10 @@ OSLCompilerImpl::preprocess_buffer (const std::string &buffer,
|
||||
context_type ctx (instring.begin(), instring.end(), filename.c_str());
|
||||
|
||||
// Turn on support of variadic macros, e.g. #define FOO(...) __VA_ARGS__
|
||||
// Turn off whitespace insertion.
|
||||
boost::wave::language_support lang = boost::wave::language_support (
|
||||
ctx.get_language() | boost::wave::support_option_variadics);
|
||||
(ctx.get_language() | boost::wave::support_option_variadics)
|
||||
& ~boost::wave::language_support::support_option_insert_whitespace);
|
||||
ctx.set_language (lang);
|
||||
|
||||
ctx.add_macro_definition (OIIO::Strutil::format("OSL_VERSION_MAJOR=%d",
|
||||
@@ -309,7 +313,7 @@ OSLCompilerImpl::preprocess_buffer (const std::string &buffer,
|
||||
new clang::DiagnosticsEngine(diagIDs, diagOptions, diagPrinter);
|
||||
inst.setDiagnostics(diagEngine);
|
||||
|
||||
const std::shared_ptr<clang::TargetOptions> &targetopts =
|
||||
const std::shared_ptr<clang::TargetOptions> targetopts =
|
||||
std::make_shared<clang::TargetOptions>(inst.getTargetOpts());
|
||||
targetopts->Triple = llvm::sys::getDefaultTargetTriple();
|
||||
clang::TargetInfo *target =
|
||||
@@ -319,16 +323,15 @@ OSLCompilerImpl::preprocess_buffer (const std::string &buffer,
|
||||
|
||||
inst.createFileManager();
|
||||
inst.createSourceManager(inst.getFileManager());
|
||||
#if OSL_LLVM_VERSION <= 35
|
||||
clang::FrontendInputFile inputFile(mbuf.release(), clang::IK_None);
|
||||
inst.InitializeSourceManager(inputFile);
|
||||
#else
|
||||
clang::SourceManager &sm = inst.getSourceManager();
|
||||
sm.setMainFileID (sm.createFileID(std::move(mbuf), clang::SrcMgr::C_User));
|
||||
#endif
|
||||
|
||||
inst.getPreprocessorOutputOpts().ShowCPP = 1;
|
||||
inst.getPreprocessorOutputOpts().ShowMacros = 0;
|
||||
inst.getPreprocessorOutputOpts().ShowComments = 0;
|
||||
inst.getPreprocessorOutputOpts().ShowLineMarkers = 1;
|
||||
inst.getPreprocessorOutputOpts().ShowMacroComments = 0;
|
||||
inst.getPreprocessorOutputOpts().ShowIncludeDirectives = 0;
|
||||
|
||||
clang::HeaderSearchOptions &headerOpts = inst.getHeaderSearchOpts();
|
||||
headerOpts.UseBuiltinIncludes = 0;
|
||||
@@ -412,6 +415,8 @@ OSLCompilerImpl::read_compile_options (const std::vector<std::string> &options,
|
||||
m_optimizelevel = 1;
|
||||
} else if (options[i] == "-O2") {
|
||||
m_optimizelevel = 2;
|
||||
} else if (options[i] == "-Werror") {
|
||||
m_err_on_warning = true;
|
||||
} else if (options[i].c_str()[0] == '-' && options[i].size() > 2) {
|
||||
// options meant for the preprocessor
|
||||
if (options[i].c_str()[1] == 'D' || options[i].c_str()[1] == 'U')
|
||||
@@ -429,10 +434,20 @@ OSLCompilerImpl::read_compile_options (const std::vector<std::string> &options,
|
||||
static string_view
|
||||
find_stdoslpath (const std::vector<std::string>& includepaths)
|
||||
{
|
||||
// first look in $OSLHOME/shaders
|
||||
std::string OSLHOME = OIIO::Sysutil::getenv ("OSLHOME");
|
||||
if (! OSLHOME.empty()) {
|
||||
std::string path = OSLHOME + "/shaders";
|
||||
// first look in $OSL_ROOT_DIR/shaders
|
||||
std::string osl_root_dir = OIIO::Sysutil::getenv ("OSL_ROOT_DIR");
|
||||
if (! osl_root_dir.empty()) {
|
||||
std::string path = osl_root_dir + "/shaders";
|
||||
if (OIIO::Filesystem::is_directory (path)) {
|
||||
path = path + "/stdosl.h";
|
||||
if (OIIO::Filesystem::exists (path))
|
||||
return ustring(path);
|
||||
}
|
||||
}
|
||||
// deprecated name: OSLHOME
|
||||
osl_root_dir = OIIO::Sysutil::getenv ("OSLHOME");
|
||||
if (! osl_root_dir.empty()) {
|
||||
std::string path = osl_root_dir + "/shaders";
|
||||
if (OIIO::Filesystem::is_directory (path)) {
|
||||
path = path + "/stdosl.h";
|
||||
if (OIIO::Filesystem::exists (path))
|
||||
@@ -440,8 +455,8 @@ find_stdoslpath (const std::vector<std::string>& includepaths)
|
||||
}
|
||||
}
|
||||
|
||||
// If no OSLHOME, try looking wherever this program (the one running)
|
||||
// lives, in a shaders or lib/osl/include directory.
|
||||
// If not found in $OSL_ROOT_DIR, try looking wherever this program (the
|
||||
// one running) lives, in a shaders or lib/osl/include directory.
|
||||
std::string program = OIIO::Sysutil::this_program_path ();
|
||||
if (program.size()) {
|
||||
std::string path (program); // our program
|
||||
@@ -521,6 +536,7 @@ OSLCompilerImpl::compile (string_view filename,
|
||||
std::vector<std::string> includepaths;
|
||||
m_cwd = OIIO::Filesystem::current_path();
|
||||
m_main_filename = filename;
|
||||
clear_filecontents_cache();
|
||||
|
||||
read_compile_options (options, defines, includepaths);
|
||||
|
||||
@@ -543,6 +559,9 @@ OSLCompilerImpl::compile (string_view filename,
|
||||
} else if (m_preprocess_only) {
|
||||
std::cout << preprocess_result;
|
||||
} else {
|
||||
// Thread safety with the lexer/parser
|
||||
std::lock_guard<std::mutex> lock (oslcompiler_mutex);
|
||||
oslcompiler = this;
|
||||
bool parseerr = osl_parse_buffer (preprocess_result);
|
||||
if (! parseerr) {
|
||||
if (shader())
|
||||
@@ -575,7 +594,7 @@ OSLCompilerImpl::compile (string_view filename,
|
||||
OIIO::Filesystem::open (oso_output, m_output_filename);
|
||||
if (! oso_output.good()) {
|
||||
error (ustring(), 0, "Could not open \"%s\"",
|
||||
m_output_filename.c_str());
|
||||
m_output_filename);
|
||||
return false;
|
||||
}
|
||||
ASSERT (m_osofile == NULL);
|
||||
@@ -585,7 +604,7 @@ OSLCompilerImpl::compile (string_view filename,
|
||||
ASSERT (m_osofile == NULL);
|
||||
}
|
||||
|
||||
oslcompiler = NULL;
|
||||
oslcompiler = nullptr;
|
||||
}
|
||||
|
||||
return ! error_encountered();
|
||||
@@ -597,9 +616,11 @@ bool
|
||||
OSLCompilerImpl::compile_buffer (string_view sourcecode,
|
||||
std::string &osobuffer,
|
||||
const std::vector<std::string> &options,
|
||||
string_view stdoslpath)
|
||||
string_view stdoslpath,
|
||||
string_view filename)
|
||||
{
|
||||
string_view filename ("<buffer>");
|
||||
if (filename.empty())
|
||||
filename = string_view("<buffer>");
|
||||
|
||||
std::vector<std::string> defines;
|
||||
std::vector<std::string> includepaths;
|
||||
@@ -607,6 +628,7 @@ OSLCompilerImpl::compile_buffer (string_view sourcecode,
|
||||
|
||||
m_cwd = OIIO::Filesystem::current_path();
|
||||
m_main_filename = filename;
|
||||
clear_filecontents_cache();
|
||||
|
||||
// Determine where the installed shader include directory is, and
|
||||
// look for ../shaders/stdosl.h and force it to include.
|
||||
@@ -623,6 +645,9 @@ OSLCompilerImpl::compile_buffer (string_view sourcecode,
|
||||
} else if (m_preprocess_only) {
|
||||
std::cout << preprocess_result;
|
||||
} else {
|
||||
// Thread safety with the lexer/parser
|
||||
std::lock_guard<std::mutex> lock (oslcompiler_mutex);
|
||||
oslcompiler = this;
|
||||
bool parseerr = osl_parse_buffer (preprocess_result);
|
||||
if (! parseerr) {
|
||||
if (shader())
|
||||
@@ -648,7 +673,8 @@ OSLCompilerImpl::compile_buffer (string_view sourcecode,
|
||||
}
|
||||
|
||||
if (! error_encountered()) {
|
||||
m_output_filename = "<buffer>";
|
||||
if (m_output_filename.empty())
|
||||
m_output_filename = default_output_filename ();
|
||||
|
||||
std::ostringstream oso_output;
|
||||
oso_output.imbue (std::locale::classic()); // force C locale
|
||||
@@ -660,7 +686,7 @@ OSLCompilerImpl::compile_buffer (string_view sourcecode,
|
||||
ASSERT (m_osofile == NULL);
|
||||
}
|
||||
|
||||
oslcompiler = NULL;
|
||||
oslcompiler = nullptr;
|
||||
}
|
||||
|
||||
return ! error_encountered();
|
||||
@@ -671,6 +697,10 @@ OSLCompilerImpl::compile_buffer (string_view sourcecode,
|
||||
struct GlobalTable {
|
||||
const char *name;
|
||||
TypeSpec type;
|
||||
bool readonly;
|
||||
|
||||
GlobalTable (const char *name, TypeSpec type, bool readonly=true)
|
||||
: name(name), type(type), readonly(readonly) {}
|
||||
};
|
||||
|
||||
|
||||
@@ -678,34 +708,24 @@ void
|
||||
OSLCompilerImpl::initialize_globals ()
|
||||
{
|
||||
static GlobalTable globals[] = {
|
||||
{ "P", TypeDesc::TypePoint },
|
||||
{ "I", TypeDesc::TypeVector },
|
||||
{ "N", TypeDesc::TypeNormal },
|
||||
{ "P", TypeDesc::TypePoint, false },
|
||||
{ "I", TypeDesc::TypeVector, false },
|
||||
{ "N", TypeDesc::TypeNormal, false },
|
||||
{ "Ng", TypeDesc::TypeNormal },
|
||||
{ "u", TypeDesc::TypeFloat },
|
||||
{ "v", TypeDesc::TypeFloat },
|
||||
{ "dPdu", TypeDesc::TypeVector },
|
||||
{ "dPdv", TypeDesc::TypeVector },
|
||||
#if 0
|
||||
// Light variables -- we don't seem to be on a route to support this
|
||||
// kind of light shader, so comment these out for now.
|
||||
{ "L", TypeDesc::TypeVector },
|
||||
{ "Cl", TypeDesc::TypeColor },
|
||||
{ "Ns", TypeDesc::TypeNormal },
|
||||
{ "Pl", TypeDesc::TypePoint },
|
||||
{ "Nl", TypeDesc::TypeNormal },
|
||||
#endif
|
||||
{ "Ps", TypeDesc::TypePoint },
|
||||
{ "Ci", TypeSpec (TypeDesc::TypeColor, true) },
|
||||
{ "Ci", TypeSpec (TypeDesc::TypeColor, true), false },
|
||||
{ "time", TypeDesc::TypeFloat },
|
||||
{ "dtime", TypeDesc::TypeFloat },
|
||||
{ "dPdtime", TypeDesc::TypeVector },
|
||||
{ NULL }
|
||||
{ "dPdtime", TypeDesc::TypeVector }
|
||||
};
|
||||
|
||||
for (int i = 0; globals[i].name; ++i) {
|
||||
Symbol *s = new Symbol (ustring(globals[i].name), globals[i].type,
|
||||
SymTypeGlobal);
|
||||
for (auto& g : globals) {
|
||||
Symbol *s = new Symbol (ustring(g.name), g.type, SymTypeGlobal);
|
||||
s->readonly (g.readonly);
|
||||
symtab().insert (s);
|
||||
}
|
||||
}
|
||||
@@ -759,10 +779,10 @@ OSLCompilerImpl::write_oso_const_value (const ConstantSymbol *sym) const
|
||||
oso ("%d%s", sym->intval(i), nelements>1 ? " " : "");
|
||||
else if (elemtype == TypeDesc::FLOAT)
|
||||
for (int i = 0; i < nelements; ++i)
|
||||
oso ("%.8g%s", sym->floatval(i), nelements>1 ? " " : "");
|
||||
oso ("%.9g%s", sym->floatval(i), nelements>1 ? " " : "");
|
||||
else if (equivalent (elemtype, TypeDesc::TypeVector))
|
||||
for (int i = 0; i < nelements; ++i)
|
||||
oso ("%.8g %.8g %.8g%s", sym->vecval(i)[0], sym->vecval(i)[1],
|
||||
oso ("%.9g %.9g %.9g%s", sym->vecval(i)[0], sym->vecval(i)[1],
|
||||
sym->vecval(i)[2], nelements>1 ? " " : "");
|
||||
else {
|
||||
ASSERT (0 && "Don't know how to output this constant type");
|
||||
@@ -942,7 +962,7 @@ OSLCompilerImpl::write_oso_file (const std::string &outfilename,
|
||||
lastline = -1;
|
||||
}
|
||||
|
||||
if (/*m_debug &&*/ op.sourcefile()) {
|
||||
if (/*m_debug &&*/ !op.sourcefile().empty()) {
|
||||
ustring file = op.sourcefile();
|
||||
int line = op.sourceline();
|
||||
if (file != lastfile || line != lastline)
|
||||
@@ -975,7 +995,7 @@ OSLCompilerImpl::write_oso_file (const std::string &outfilename,
|
||||
// %filename and %line document the source code file and line that
|
||||
// contained code that generated this op. To avoid clutter, we
|
||||
// only output these hints when they DIFFER from the previous op.
|
||||
if (op.sourcefile()) {
|
||||
if (!op.sourcefile().empty()) {
|
||||
if (op.sourcefile() != lastfile) {
|
||||
lastfile = op.sourcefile();
|
||||
oso ("%c%%filename{\"%s\"}", firsthint ? '\t' : ' ', lastfile);
|
||||
@@ -1004,11 +1024,7 @@ OSLCompilerImpl::write_oso_file (const std::string &outfilename,
|
||||
// %argderivs documents which arguments have derivs taken of
|
||||
// them by the op.
|
||||
if (op.argtakesderivs_all()) {
|
||||
#if OIIO_VERSION >= 10803
|
||||
oso (" %%argderivs{");
|
||||
#else
|
||||
oso (" %cargderivs{", '%'); // trick to work with older OIIO
|
||||
#endif
|
||||
int any = 0;
|
||||
for (int i = 0; i < op.nargs(); ++i)
|
||||
if (op.argtakesderivs(i)) {
|
||||
@@ -1032,29 +1048,70 @@ OSLCompilerImpl::write_oso_file (const std::string &outfilename,
|
||||
|
||||
|
||||
|
||||
std::string
|
||||
void
|
||||
OSLCompilerImpl::clear_filecontents_cache()
|
||||
{
|
||||
m_filecontents_map.clear();
|
||||
m_last_sourcefile.clear();
|
||||
m_last_filecontents = nullptr;
|
||||
m_last_sourceline = 1; // note we call the first line "1" for users
|
||||
m_last_sourceline_offset = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
string_view
|
||||
OSLCompilerImpl::retrieve_source (ustring filename, int line)
|
||||
{
|
||||
// If we don't already have the file open, open it
|
||||
if (filename != m_last_sourcefile) {
|
||||
bool ok = OIIO::Filesystem::read_text_file (filename, m_filecontents);
|
||||
if (ok) {
|
||||
m_last_sourcefile = filename;
|
||||
// If we don't have a valid "last", look it up in the cache.
|
||||
if (filename != m_last_sourcefile || !m_last_filecontents) {
|
||||
m_last_sourceline = 1;
|
||||
m_last_sourceline_offset = 0;
|
||||
auto found = m_filecontents_map.find (filename);
|
||||
if (found == m_filecontents_map.end()) {
|
||||
// If it wasn't in the cache, read the file and add it.
|
||||
std::string contents;
|
||||
bool ok = OIIO::Filesystem::read_text_file (filename, contents);
|
||||
if (ok) {
|
||||
m_last_sourcefile = filename;
|
||||
m_filecontents_map[filename] = std::move(contents);
|
||||
m_last_filecontents = &m_filecontents_map[filename];
|
||||
} else {
|
||||
m_last_sourcefile = ustring();
|
||||
m_last_filecontents = nullptr;
|
||||
return "<file not found>";
|
||||
}
|
||||
} else {
|
||||
m_last_sourcefile = ustring();
|
||||
return "<file not found>";
|
||||
m_last_sourcefile = filename;
|
||||
m_last_filecontents = &found->second;
|
||||
}
|
||||
}
|
||||
|
||||
// Now read lines up to and including the file we want.
|
||||
OIIO::string_view s (m_filecontents);
|
||||
OIIO::string_view s (*m_last_filecontents);
|
||||
int orig_sourceline = line;
|
||||
if (line >= m_last_sourceline) {
|
||||
// Shortcut: the line we want is in the same file as the last read,
|
||||
// and at least as far in the file. Start the search from where we
|
||||
// left off last time.
|
||||
s.remove_prefix (m_last_sourceline_offset);
|
||||
line -= m_last_sourceline - 1;
|
||||
} else {
|
||||
// If we have to backtrack at all, backtrack to the file start.
|
||||
m_last_sourceline_offset = 0;
|
||||
m_last_sourceline = 1;
|
||||
}
|
||||
size_t offset = m_last_sourceline_offset;
|
||||
for ( ; line > 1; --line) {
|
||||
size_t p = s.find_first_of ('\n');
|
||||
if (p == OIIO::string_view::npos)
|
||||
return "<line not found>";
|
||||
s.remove_prefix (p+1);
|
||||
offset += p+1;
|
||||
}
|
||||
s = s.substr (0, s.find_first_of ('\n'));
|
||||
m_last_sourceline_offset = offset;
|
||||
m_last_sourceline = orig_sourceline;
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -1140,8 +1197,9 @@ OSLCompilerImpl::struct_field_pair (const StructSpec *structspec, int fieldnum,
|
||||
|
||||
|
||||
|
||||
/// Verify that the given symbol (written by the given op) is legal to
|
||||
/// be written.
|
||||
/// Verify that the given symbol (written by the given op) is legal to be
|
||||
/// written. If writeable, it's writeable, We don't try to enforce
|
||||
/// differences in policy per shader types.
|
||||
void
|
||||
OSLCompilerImpl::check_write_legality (const Opcode &op, int opnum,
|
||||
const Symbol *sym)
|
||||
@@ -1156,12 +1214,9 @@ OSLCompilerImpl::check_write_legality (const Opcode &op, int opnum,
|
||||
if (sym->symtype() == SymTypeParam &&
|
||||
(opnum < sym->initbegin() || opnum >= sym->initend())) {
|
||||
error (op.sourcefile(), op.sourceline(),
|
||||
"Cannot write to input parameter '%s' (op %d)",
|
||||
sym->name().c_str(), opnum);
|
||||
"cannot write to non-output parameter \"%s\"",
|
||||
sym->name());
|
||||
}
|
||||
|
||||
// FIXME -- check for writing to globals. But it's tricky, depends on
|
||||
// what kind of shader we are.
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -72,7 +72,8 @@ public:
|
||||
bool compile_buffer (string_view sourcecode,
|
||||
std::string &osobuffer,
|
||||
const std::vector<std::string> &options,
|
||||
string_view stdoslpath);
|
||||
string_view stdoslpath,
|
||||
string_view filename);
|
||||
|
||||
bool osl_parse_buffer (const std::string &preprocessed_buffer);
|
||||
|
||||
@@ -100,45 +101,69 @@ public:
|
||||
|
||||
/// Error reporting
|
||||
template<typename... Args>
|
||||
void error (string_view filename, int line,
|
||||
void error (ustring filename, int line,
|
||||
string_view format, const Args&... args) const
|
||||
{
|
||||
ASSERT (format.size());
|
||||
#if OIIO_VERSION >= 10804
|
||||
std::string msg = OIIO::Strutil::format (format, args...);
|
||||
if (msg.size() && msg.back() == '\n') // trim extra newline
|
||||
msg.pop_back();
|
||||
if (filename.size())
|
||||
m_errhandler->error ("%s:%d: error: %s", filename, line, msg);
|
||||
else
|
||||
m_errhandler->error ("error: %s", msg);
|
||||
#else /* Deprecate when the OIIO minimum is 1.8 */
|
||||
std::string msg = OIIO::Strutil::format (format.c_str(), args...);
|
||||
if (filename.size())
|
||||
m_errhandler->error ("%s:%d: error: %s", filename.c_str(), line, msg.c_str());
|
||||
else
|
||||
m_errhandler->error ("error: %s", msg.c_str());
|
||||
#endif
|
||||
m_err = true;
|
||||
}
|
||||
|
||||
/// Warning reporting
|
||||
template<typename... Args>
|
||||
void warning (string_view filename, int line,
|
||||
void warning (ustring filename, int line,
|
||||
string_view format, const Args&... args) const
|
||||
{
|
||||
ASSERT (format.size());
|
||||
#if OIIO_VERSION >= 10804
|
||||
if (nowarn(filename, line))
|
||||
return; // skip if the filename/line is on the nowarn list
|
||||
std::string msg = OIIO::Strutil::format (format, args...);
|
||||
if (msg.size() && msg.back() == '\n') // trim extra newline
|
||||
msg.pop_back();
|
||||
if (m_err_on_warning) {
|
||||
error (filename, line, "%s", msg);
|
||||
return;
|
||||
}
|
||||
if (filename.size())
|
||||
m_errhandler->warning ("%s:%d: warning: %s", filename, line, msg);
|
||||
else
|
||||
m_errhandler->warning ("warning: %s", msg);
|
||||
#else /* Deprecate when the OIIO minimum is 1.8 */
|
||||
std::string msg = OIIO::Strutil::format (format.c_str(), args...);
|
||||
}
|
||||
|
||||
/// Info reporting
|
||||
template<typename... Args>
|
||||
void info (ustring filename, int line,
|
||||
string_view format, const Args&... args) const
|
||||
{
|
||||
ASSERT (format.size());
|
||||
std::string msg = OIIO::Strutil::format (format, args...);
|
||||
if (msg.size() && msg.back() == '\n') // trim extra newline
|
||||
msg.pop_back();
|
||||
if (filename.size())
|
||||
m_errhandler->warning ("%s:%d: warning: %s", filename.c_str(), line, msg.c_str());
|
||||
m_errhandler->info ("%s:%d: info: %s", filename, line, msg);
|
||||
else
|
||||
m_errhandler->warning ("warning: %s", msg.c_str());
|
||||
#endif
|
||||
m_errhandler->info ("info: %s", msg);
|
||||
}
|
||||
|
||||
/// message reporting
|
||||
template<typename... Args>
|
||||
void message (ustring filename, int line,
|
||||
string_view format, const Args&... args) const
|
||||
{
|
||||
ASSERT (format.size());
|
||||
std::string msg = OIIO::Strutil::format (format, args...);
|
||||
if (msg.size() && msg.back() == '\n') // trim extra newline
|
||||
msg.pop_back();
|
||||
if (filename.size())
|
||||
m_errhandler->message ("%s:%d: %s", filename, line, msg);
|
||||
else
|
||||
m_errhandler->message ("%s", msg);
|
||||
}
|
||||
|
||||
/// Have we hit an error?
|
||||
@@ -357,6 +382,16 @@ public:
|
||||
m_func_decls.emplace_back (f);
|
||||
}
|
||||
|
||||
// Add a pragma nowarn for the following line
|
||||
void pragma_nowarn () {
|
||||
m_nowarn_lines.insert ({filename(), lineno()+1});
|
||||
}
|
||||
|
||||
// Is the line amont
|
||||
bool nowarn (ustring filename, int line) const {
|
||||
return m_nowarn_lines.find({filename, line}) != m_nowarn_lines.end();
|
||||
}
|
||||
|
||||
private:
|
||||
void initialize_globals ();
|
||||
void initialize_builtin_funcs ();
|
||||
@@ -366,14 +401,10 @@ private:
|
||||
void write_oso_symbol (const Symbol *sym);
|
||||
void write_oso_metadata (const ASTNode *metanode) const;
|
||||
|
||||
#if OIIO_VERSION >= 10803
|
||||
template<typename... Args>
|
||||
inline void oso (string_view fmt, const Args&... args) const {
|
||||
(*m_osofile) << OIIO::Strutil::format (fmt, args...);
|
||||
}
|
||||
#else
|
||||
TINYFORMAT_WRAP_FORMAT (void, oso, const, , (*m_osofile), )
|
||||
#endif
|
||||
|
||||
void track_variable_lifetimes () {
|
||||
track_variable_lifetimes (m_ircode, m_opargs, symtab().allsyms());
|
||||
@@ -423,7 +454,12 @@ private:
|
||||
return NULL;
|
||||
return static_cast<ASTshader_declaration *>(m_shader.get());
|
||||
}
|
||||
std::string retrieve_source (ustring filename, int line);
|
||||
|
||||
// Retrieve the particular line of a file.
|
||||
string_view retrieve_source (ustring filename, int line);
|
||||
|
||||
// Clear internal caches that speed up retrieve_source().
|
||||
void clear_filecontents_cache();
|
||||
|
||||
ustring m_filename; ///< Current file we're parsing
|
||||
int m_lineno; ///< Current line we're parsing
|
||||
@@ -441,6 +477,7 @@ private:
|
||||
bool m_quiet; ///< Quiet mode
|
||||
bool m_debug; ///< Debug mode
|
||||
bool m_preprocess_only; ///< Preprocess only?
|
||||
bool m_err_on_warning; ///< Treat warnings as errors?
|
||||
int m_optimizelevel; ///< Optimization level
|
||||
OpcodeVec m_ircode; ///< Generated IR code
|
||||
SymbolPtrVec m_opargs; ///< Arguments for all instructions
|
||||
@@ -448,8 +485,6 @@ private:
|
||||
int m_next_const; ///< Next const symbol index
|
||||
std::vector<ConstantSymbol *> m_const_syms; ///< All consts we've made
|
||||
std::ostream *m_osofile; ///< Open .oso stream for output
|
||||
std::string m_filecontents; ///< Contents of source file
|
||||
ustring m_last_sourcefile;///< Last filename for retrieve_source
|
||||
ustring m_codegenmethod; ///< Current method we're generating code for
|
||||
std::stack<FunctionSymbol *> m_function_stack; ///< Stack of called funcs
|
||||
int m_total_nesting; ///< total conditional nesting level (0 == none)
|
||||
@@ -458,6 +493,13 @@ private:
|
||||
Symbol *m_derivsym; ///< Pseudo-symbol to track deriv dependencies
|
||||
int m_main_method_start; ///< Instruction where 'main' starts
|
||||
bool m_declaring_shader_formals; ///< Are we declaring shader formals?
|
||||
std::set<std::pair<ustring,int>> m_nowarn_lines; ///< Lines for 'nowarn'
|
||||
typedef std::unordered_map<ustring,std::string,ustringHash> FCMap;
|
||||
FCMap m_filecontents_map; ///< Contents of source files we've seen
|
||||
ustring m_last_sourcefile;///< Last filename for retrieve_source
|
||||
std::string* m_last_filecontents = nullptr; //< Last file contents
|
||||
int m_last_sourceline;
|
||||
size_t m_last_sourceline_offset;
|
||||
};
|
||||
|
||||
|
||||
|
||||
+206
-89
@@ -107,6 +107,7 @@ static std::stack<TypeSpec> typespec_stack; // just for function_declaration
|
||||
%type <n> variable_declaration def_expressions def_expression
|
||||
%type <n> initializer_opt initializer initializer_list_opt initializer_list
|
||||
%type <n> compound_initializer init_expression_list init_expression
|
||||
%type <n> init_expression_list_rev
|
||||
%type <i> outputspec arrayspec simple_typename
|
||||
%type <i> typespec typespec_or_shadertype
|
||||
%type <n> statement_list statement scoped_statements local_declaration
|
||||
@@ -170,7 +171,7 @@ global_declaration
|
||||
shader_or_function_declaration
|
||||
: typespec_or_shadertype IDENTIFIER
|
||||
{
|
||||
if ($1 == ShadTypeUnknown) {
|
||||
if ($1 == (int)ShaderType::Unknown) {
|
||||
// It's a function declaration, not a shader
|
||||
oslcompiler->symtab().push (); // new scope
|
||||
typespec_stack.push (oslcompiler->current_typespec());
|
||||
@@ -178,7 +179,7 @@ shader_or_function_declaration
|
||||
}
|
||||
metadata_block_opt '('
|
||||
{
|
||||
if ($1 != ShadTypeUnknown)
|
||||
if ($1 != (int)ShaderType::Unknown)
|
||||
oslcompiler->declaring_shader_formals (true);
|
||||
}
|
||||
formal_params_opt ')'
|
||||
@@ -187,18 +188,19 @@ shader_or_function_declaration
|
||||
}
|
||||
metadata_block_opt function_body_or_just_decl
|
||||
{
|
||||
if ($1 == ShadTypeUnknown) {
|
||||
if ($1 == (int)ShaderType::Unknown) {
|
||||
// Function declaration
|
||||
oslcompiler->symtab().pop (); // restore scope
|
||||
ASTfunction_declaration *f;
|
||||
f = new ASTfunction_declaration (oslcompiler,
|
||||
typespec_stack.top(),
|
||||
ustring($2), $7 /*formals*/,
|
||||
$11 /*statements*/);
|
||||
$11 /*statements*/,
|
||||
NULL /*metadata*/,
|
||||
@2.first_line);
|
||||
oslcompiler->remember_function_decl (f);
|
||||
f->add_meta (concat($4, $10));
|
||||
$$ = f;
|
||||
$$->sourceline (@2.first_line);
|
||||
typespec_stack.pop ();
|
||||
} else {
|
||||
// Shader declaration
|
||||
@@ -232,12 +234,17 @@ formal_params
|
||||
formal_param
|
||||
: outputspec typespec IDENTIFIER initializer_opt metadata_block_opt
|
||||
{
|
||||
ASTvariable_declaration *var;
|
||||
TypeSpec t = oslcompiler->current_typespec();
|
||||
var = new ASTvariable_declaration (oslcompiler,
|
||||
bool is_output = $1;
|
||||
auto var = new ASTvariable_declaration (oslcompiler,
|
||||
t, ustring($3), $4 /*init*/,
|
||||
oslcompiler->declaring_shader_formals() /*isparam*/,
|
||||
false /*ismeta*/, $1 /*isoutput*/);
|
||||
false /*ismeta*/, is_output,
|
||||
false /*instlist*/, @3.first_line);
|
||||
if (! oslcompiler->declaring_shader_formals() && !is_output) {
|
||||
// these are function formals, not shader formals,
|
||||
var->sym()->readonly (true);
|
||||
}
|
||||
var->add_meta ($5);
|
||||
$$ = var;
|
||||
}
|
||||
@@ -246,12 +253,11 @@ formal_param
|
||||
// Grab the current declaration type, modify it to be array
|
||||
TypeSpec t = oslcompiler->current_typespec();
|
||||
t.make_array ($4);
|
||||
ASTvariable_declaration *var;
|
||||
var = new ASTvariable_declaration (oslcompiler, t,
|
||||
auto var = new ASTvariable_declaration (oslcompiler, t,
|
||||
ustring($3), $5 /*init*/,
|
||||
oslcompiler->declaring_shader_formals() /*isparam*/,
|
||||
false /*ismeta*/, $1 /*isoutput*/,
|
||||
true /* initializer list */);
|
||||
true /* initlist */, @3.first_line);
|
||||
var->add_meta ($6);
|
||||
$$ = var;
|
||||
}
|
||||
@@ -259,16 +265,18 @@ formal_param
|
||||
{
|
||||
// Grab the current declaration type, modify it to be array
|
||||
TypeSpec t = oslcompiler->current_typespec();
|
||||
if (! t.is_structure())
|
||||
if (! t.is_structure() && ! t.is_triple() && ! t.is_matrix())
|
||||
oslcompiler->error (oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Can't use '= {...}' initializer except with arrays or struct (%s)", $3);
|
||||
ASTvariable_declaration *var;
|
||||
var = new ASTvariable_declaration (oslcompiler, t,
|
||||
"Can't use '= {...}' initializer "
|
||||
"except with arrays, structs, vectors, "
|
||||
"or matrix (%s)", $3);
|
||||
auto var = new ASTvariable_declaration (oslcompiler, t,
|
||||
ustring($3), $4 /*init*/,
|
||||
oslcompiler->declaring_shader_formals() /*isparam*/,
|
||||
false /*ismeta*/, $1 /*isoutput*/,
|
||||
true /* initializer list */);
|
||||
true /* initializer list */,
|
||||
@3.first_line);
|
||||
var->add_meta ($5);
|
||||
$$ = var;
|
||||
}
|
||||
@@ -291,10 +299,12 @@ metadata
|
||||
metadatum
|
||||
: simple_typename IDENTIFIER initializer
|
||||
{
|
||||
ASTvariable_declaration *var;
|
||||
var = new ASTvariable_declaration (oslcompiler, osllextype($1),
|
||||
ustring ($2), $3, false,
|
||||
true /* ismeta */);
|
||||
auto var = new ASTvariable_declaration (oslcompiler, osllextype($1),
|
||||
ustring ($2), $3, false /* isparam */,
|
||||
true /* ismeta */,
|
||||
false /* isoutput */,
|
||||
false /* initlist */,
|
||||
@2.first_line);
|
||||
$$ = var;
|
||||
}
|
||||
| simple_typename IDENTIFIER arrayspec initializer_list
|
||||
@@ -306,11 +316,11 @@ metadatum
|
||||
oslcompiler->lineno(),
|
||||
"Invalid array length for %s", $2);
|
||||
TypeSpec t (simple, false);
|
||||
ASTvariable_declaration *var;
|
||||
var = new ASTvariable_declaration (oslcompiler, t,
|
||||
auto var = new ASTvariable_declaration (oslcompiler, t,
|
||||
ustring ($2), $4, false,
|
||||
true /* ismeata */, false /* output */,
|
||||
true /* initializer list */);
|
||||
true /* initializer list */,
|
||||
@2.first_line);
|
||||
$$ = var;
|
||||
}
|
||||
;
|
||||
@@ -329,10 +339,10 @@ function_declaration
|
||||
'(' formal_params_opt ')' metadata_block_opt function_body_or_just_decl
|
||||
{
|
||||
oslcompiler->symtab().pop (); // restore scope
|
||||
ASTfunction_declaration *f;
|
||||
f = new ASTfunction_declaration (oslcompiler,
|
||||
auto f = new ASTfunction_declaration (oslcompiler,
|
||||
typespec_stack.top(),
|
||||
ustring($2), $5, $8, NULL);
|
||||
ustring($2), $5, $8, NULL,
|
||||
@2.first_line);
|
||||
oslcompiler->remember_function_decl (f);
|
||||
f->add_meta ($7);
|
||||
$$ = f;
|
||||
@@ -346,17 +356,13 @@ struct_declaration
|
||||
ustring name ($2);
|
||||
Symbol *s = oslcompiler->symtab().clash (name);
|
||||
if (s) {
|
||||
oslcompiler->error (oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"\"%s\" already declared in this scope",
|
||||
name.c_str());
|
||||
oslcompiler->error (oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"\"%s\" already declared in this scope", name);
|
||||
// FIXME -- print the file and line of the other definition
|
||||
}
|
||||
if (name[0] == '_' && name[1] == '_' && name[2] == '_') {
|
||||
oslcompiler->error (oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"\"%s\" : sorry, can't start with three underscores",
|
||||
name.c_str());
|
||||
if (OIIO::Strutil::starts_with (name, "___")) {
|
||||
oslcompiler->error (oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"\"%s\" : sorry, can't start with three underscores", name);
|
||||
}
|
||||
oslcompiler->symtab().new_struct (name);
|
||||
}
|
||||
@@ -390,7 +396,7 @@ typed_field
|
||||
oslcompiler->error (oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Field \"%s\" already exists in struct \"%s\"",
|
||||
name.c_str(), s->name().c_str());
|
||||
name, s->name());
|
||||
else
|
||||
oslcompiler->symtab().add_struct_field (t, name);
|
||||
$$ = 0;
|
||||
@@ -404,13 +410,13 @@ typed_field
|
||||
if (t.arraylength() < 1)
|
||||
oslcompiler->error (oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Invalid array length for %s", name.c_str());
|
||||
"Invalid array length for %s", name);
|
||||
StructSpec *s = oslcompiler->symtab().current_struct();
|
||||
if (s->lookup_field (name) >= 0)
|
||||
oslcompiler->error (oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Field \"%s\" already exists in struct \"%s\"",
|
||||
name.c_str(), s->name().c_str());
|
||||
name, s->name());
|
||||
else
|
||||
oslcompiler->symtab().add_struct_field (t, name);
|
||||
$$ = 0;
|
||||
@@ -436,7 +442,9 @@ def_expression
|
||||
{
|
||||
TypeSpec t = oslcompiler->current_typespec();
|
||||
$$ = new ASTvariable_declaration (oslcompiler,
|
||||
t, ustring($1), $2);
|
||||
t, ustring($1), $2, false /*isparam*/,
|
||||
false /*ismeta*/, false /*isoutput*/,
|
||||
false /*initlist*/, @1.first_line);
|
||||
}
|
||||
| IDENTIFIER arrayspec initializer_list_opt
|
||||
{
|
||||
@@ -447,20 +455,22 @@ def_expression
|
||||
oslcompiler->error (oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Invalid array length for %s", $1);
|
||||
$$ = new ASTvariable_declaration (oslcompiler, t,
|
||||
$$ = new ASTvariable_declaration (oslcompiler, t,
|
||||
ustring($1), $3, false, false, false,
|
||||
true /* initializer list */);
|
||||
true /* initlist */, @1.first_line);
|
||||
}
|
||||
| IDENTIFIER initializer_list
|
||||
{
|
||||
TypeSpec t = oslcompiler->current_typespec();
|
||||
if (! t.is_structure())
|
||||
if (! t.is_structure() && ! t.is_triple() && ! t.is_matrix())
|
||||
oslcompiler->error (oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Can't use '= {...}' initializer except with arrays or struct (%s)", $1);
|
||||
"Can't use '= {...}' initializer "
|
||||
"except with arrays, struct, vectors, "
|
||||
"or matrix (%s)", $1);
|
||||
$$ = new ASTvariable_declaration (oslcompiler, t,
|
||||
ustring($1), $2, false, false, false,
|
||||
true /* initializer list */);
|
||||
true /* initlist */, @1.first_line);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -486,14 +496,51 @@ compound_initializer
|
||||
: '{' init_expression_list '}'
|
||||
{
|
||||
$$ = new ASTcompound_initializer (oslcompiler, $2);
|
||||
$$->sourceline (@1.first_line);
|
||||
}
|
||||
;
|
||||
|
||||
init_expression_list
|
||||
: init_expression
|
||||
| init_expression_list ',' init_expression
|
||||
| init_expression_list_rev ',' init_expression
|
||||
{
|
||||
#ifdef OIIO_REFCNT_HAS_RELEASE
|
||||
// Left recursion is much more efficient for Bison, but
|
||||
// concatenating the sole last expression ($3) on the
|
||||
// far end of the running list ($1) leads to an
|
||||
// inadvertently quadratic algorithm, which is very
|
||||
// painful for long initializer lists of thousands of
|
||||
// items (like for a big table). So we use a trick:
|
||||
// accumulate the list in referse order (lets us prepend
|
||||
// as O(1) instead of append with O(n)) and then reverse
|
||||
// it right before we return the list. BUT... note that
|
||||
// we only do this for sufficiently new OIIO that lets
|
||||
// us safely convert the ref-counted pointer to a raw
|
||||
// pointer.
|
||||
ASTNode::ref revlist = concat ($3, $1);
|
||||
revlist = reverse (revlist);
|
||||
$$ = revlist.release ();
|
||||
#else
|
||||
// OIIO too old to support reverse(), so just do it
|
||||
// the old way, normal order.
|
||||
$$ = concat ($1, $3);
|
||||
#endif
|
||||
}
|
||||
;
|
||||
|
||||
init_expression_list_rev
|
||||
: init_expression
|
||||
| init_expression_list_rev ',' init_expression
|
||||
{
|
||||
#ifdef OIIO_REFCNT_HAS_RELEASE
|
||||
$$ = concat ($3, $1);
|
||||
// NOTE: intentionally concat in reverse order!
|
||||
// Because this is init_expression_list_rev!
|
||||
#else
|
||||
// OIIO too old to support reverse(), so just do it
|
||||
// the old way, normal order.
|
||||
$$ = concat ($1, $3);
|
||||
#endif
|
||||
}
|
||||
;
|
||||
|
||||
@@ -577,15 +624,19 @@ typespec_or_shadertype
|
||||
}
|
||||
| IDENTIFIER /* struct name or shader type name */
|
||||
{
|
||||
/* N.B. Shader types are considered obsolete. We are
|
||||
* promoting 'shader' for all, now (OSL 2.0). Some day
|
||||
* we may add a warning for using the old names.
|
||||
*/
|
||||
ustring name ($1);
|
||||
if (name == "shader")
|
||||
$$ = ShadTypeGeneric;
|
||||
$$ = (int)ShaderType::Generic;
|
||||
else if (name == "surface")
|
||||
$$ = ShadTypeSurface;
|
||||
$$ = (int)ShaderType::Surface;
|
||||
else if (name == "displacement")
|
||||
$$ = ShadTypeDisplacement;
|
||||
$$ = (int)ShaderType::Displacement;
|
||||
else if (name == "volume")
|
||||
$$ = ShadTypeVolume;
|
||||
$$ = (int)ShaderType::Volume;
|
||||
else {
|
||||
Symbol *s = oslcompiler->symtab().find (name);
|
||||
if (s && s->is_structure())
|
||||
@@ -596,7 +647,7 @@ typespec_or_shadertype
|
||||
oslcompiler->lineno(),
|
||||
"Unknown struct name: %s", $1);
|
||||
}
|
||||
$$ = ShadTypeUnknown;
|
||||
$$ = (int)ShaderType::Unknown;
|
||||
}
|
||||
}
|
||||
;
|
||||
@@ -687,6 +738,10 @@ return_statement
|
||||
{
|
||||
$$ = new ASTreturn_statement (oslcompiler, $2);
|
||||
}
|
||||
| RETURN compound_initializer ';'
|
||||
{
|
||||
$$ = new ASTreturn_statement (oslcompiler, $2);
|
||||
}
|
||||
;
|
||||
|
||||
for_init_statement
|
||||
@@ -738,9 +793,24 @@ expression
|
||||
$$ = $2;
|
||||
} else {
|
||||
$$ = new ASTunary_expression (oslcompiler, $1, $2);
|
||||
$$->sourceline (@1.first_line);
|
||||
}
|
||||
}
|
||||
| '(' compound_expression ')' { $$ = $2; }
|
||||
| '(' compound_expression ')'
|
||||
{
|
||||
if ($2->nodetype() == ASTNode::comma_operator_node) {
|
||||
// Warning for comma operator ïn parenthesized
|
||||
// expressions, which sometimes happens when somebody
|
||||
// forgets the proper syntax for triple constructors:
|
||||
// color x = Cd * (a, b, c); // same as: x = Cd * c
|
||||
// when they really meant
|
||||
// color x = Cd * color(a, b, c);
|
||||
oslcompiler->warning(oslcompiler->filename(),
|
||||
@1.first_line,
|
||||
"Comma operator inside parenthesis is probably an error -- it is not a vector/color.");
|
||||
}
|
||||
$$ = $2;
|
||||
}
|
||||
| function_call
|
||||
| assign_expression
|
||||
| ternary_expression
|
||||
@@ -753,14 +823,17 @@ variable_lvalue
|
||||
| id_or_field '[' expression ']'
|
||||
{
|
||||
$$ = new ASTindex (oslcompiler, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| id_or_field '[' expression ']' '[' expression ']'
|
||||
{
|
||||
$$ = new ASTindex (oslcompiler, $1, $3, $6);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| id_or_field '[' expression ']' '[' expression ']' '[' expression ']'
|
||||
{
|
||||
$$ = new ASTindex (oslcompiler, $1, $3, $6, $9);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -772,6 +845,7 @@ id_or_field
|
||||
| variable_lvalue '.' IDENTIFIER
|
||||
{
|
||||
$$ = new ASTstructselect (oslcompiler, $1, ustring($3));
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -788,93 +862,111 @@ variable_ref
|
||||
binary_expression
|
||||
: expression OR_OP expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
ASTNode::Or, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression AND_OP expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
ASTNode::And, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '|' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
ASTNode::BitOr, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '^' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
ASTNode::Xor, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '&' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
ASTNode::BitAnd, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression EQ_OP expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
ASTNode::Equal, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression NE_OP expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
ASTNode::NotEqual, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '>' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
ASTNode::Greater, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression GE_OP expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
ASTNode::GreaterEqual, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '<' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
ASTNode::Less, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression LE_OP expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
ASTNode::LessEqual, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression SHL_OP expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
ASTNode::ShiftLeft, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression SHR_OP expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
ASTNode::ShiftRight, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '+' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
ASTNode::Add, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '-' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
ASTNode::Sub, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '*' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
ASTNode::Mul, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '/' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
ASTNode::Div, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '%' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
ASTNode::Mod, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -901,6 +993,7 @@ type_constructor
|
||||
{
|
||||
$$ = new ASTtype_constructor (oslcompiler,
|
||||
TypeSpec (osllextype ($1)), $3);
|
||||
$$->sourceline (@1.first_line);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -908,6 +1001,7 @@ function_call
|
||||
: IDENTIFIER '(' function_args_opt ')'
|
||||
{
|
||||
$$ = new ASTfunction_call (oslcompiler, ustring($1), $3);
|
||||
$$->sourceline (@1.first_line);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -918,46 +1012,69 @@ function_args_opt
|
||||
|
||||
function_args
|
||||
: expression
|
||||
| compound_initializer
|
||||
| function_args ',' expression { $$ = concat ($1, $3); }
|
||||
| function_args ',' compound_initializer { $$ = concat ($1, $3); }
|
||||
;
|
||||
|
||||
assign_expression
|
||||
: variable_lvalue '=' expression
|
||||
{ $$ = new ASTassign_expression (oslcompiler, $1,
|
||||
ASTNode::Assign, $3); }
|
||||
{
|
||||
$$ = new ASTassign_expression (oslcompiler, $1, ASTNode::Assign, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| variable_lvalue MUL_ASSIGN expression
|
||||
{ $$ = new ASTassign_expression (oslcompiler, $1,
|
||||
ASTNode::Mul, $3); }
|
||||
{
|
||||
$$ = new ASTassign_expression (oslcompiler, $1, ASTNode::Mul, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| variable_lvalue DIV_ASSIGN expression
|
||||
{ $$ = new ASTassign_expression (oslcompiler, $1,
|
||||
ASTNode::Div, $3); }
|
||||
{
|
||||
$$ = new ASTassign_expression (oslcompiler, $1, ASTNode::Div, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| variable_lvalue ADD_ASSIGN expression
|
||||
{ $$ = new ASTassign_expression (oslcompiler, $1,
|
||||
ASTNode::Add, $3); }
|
||||
{
|
||||
$$ = new ASTassign_expression (oslcompiler, $1, ASTNode::Add, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| variable_lvalue SUB_ASSIGN expression
|
||||
{ $$ = new ASTassign_expression (oslcompiler, $1,
|
||||
ASTNode::Sub, $3); }
|
||||
{
|
||||
$$ = new ASTassign_expression (oslcompiler, $1, ASTNode::Sub, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| variable_lvalue BIT_AND_ASSIGN expression
|
||||
{ $$ = new ASTassign_expression (oslcompiler, $1,
|
||||
ASTNode::BitAnd, $3); }
|
||||
{
|
||||
$$ = new ASTassign_expression (oslcompiler, $1, ASTNode::BitAnd, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| variable_lvalue BIT_OR_ASSIGN expression
|
||||
{ $$ = new ASTassign_expression (oslcompiler, $1,
|
||||
ASTNode::BitOr, $3); }
|
||||
{
|
||||
$$ = new ASTassign_expression (oslcompiler, $1, ASTNode::BitOr, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| variable_lvalue XOR_ASSIGN expression
|
||||
{ $$ = new ASTassign_expression (oslcompiler, $1,
|
||||
ASTNode::Xor, $3); }
|
||||
{
|
||||
$$ = new ASTassign_expression (oslcompiler, $1, ASTNode::Xor, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| variable_lvalue SHL_ASSIGN expression
|
||||
{ $$ = new ASTassign_expression (oslcompiler, $1,
|
||||
ASTNode::ShiftLeft, $3); }
|
||||
{
|
||||
$$ = new ASTassign_expression (oslcompiler, $1, ASTNode::ShiftLeft, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| variable_lvalue SHR_ASSIGN expression
|
||||
{ $$ = new ASTassign_expression (oslcompiler, $1,
|
||||
ASTNode::ShiftRight, $3); }
|
||||
{
|
||||
$$ = new ASTassign_expression (oslcompiler, $1, ASTNode::ShiftRight, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
;
|
||||
|
||||
ternary_expression
|
||||
: expression '?' expression ':' expression
|
||||
{
|
||||
$$ = new ASTternary_expression (oslcompiler, $1, $3, $5);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
+99
-71
@@ -119,6 +119,12 @@ using namespace OSL::pvt;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// flex itself will generate fatal warnings about signed vs unsigned.
|
||||
// Bypass that nonsense.
|
||||
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 6
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
#endif
|
||||
|
||||
void preprocess (const char *yytext);
|
||||
|
||||
// Macro that sets the yylloc line variables to the current parse line.
|
||||
@@ -134,7 +140,7 @@ void preprocess (const char *yytext);
|
||||
************************************************/
|
||||
|
||||
/* preprocessor symbols */
|
||||
{CPP} { preprocess (yytext); SETLINE; }
|
||||
{CPP} { preprocess (yytext); SETLINE; }
|
||||
|
||||
/* Comments */
|
||||
{CPLUSCOMMENT} { oslcompiler->incr_lineno(); /* skip it */
|
||||
@@ -142,32 +148,32 @@ void preprocess (const char *yytext);
|
||||
}
|
||||
|
||||
/* keywords */
|
||||
"break" { SETLINE; return (yylval.i=BREAK); }
|
||||
"closure" { SETLINE; return (yylval.i=CLOSURE); }
|
||||
"color" { SETLINE; return (yylval.i=COLORTYPE); }
|
||||
"continue" { SETLINE; return (yylval.i=CONTINUE); }
|
||||
"do" { SETLINE; return (yylval.i=DO); }
|
||||
"else" { SETLINE; return (yylval.i=ELSE); }
|
||||
"float" { SETLINE; return (yylval.i=FLOATTYPE); }
|
||||
"for" { SETLINE; return (yylval.i=FOR); }
|
||||
"if" { SETLINE; return (yylval.i=IF_TOKEN); }
|
||||
"illuminance" { SETLINE; return (yylval.i=ILLUMINANCE); }
|
||||
"illuminate" { SETLINE; return (yylval.i=ILLUMINATE); }
|
||||
"int" { SETLINE; return (yylval.i=INTTYPE); }
|
||||
"matrix" { SETLINE; return (yylval.i=MATRIXTYPE); }
|
||||
"normal" { SETLINE; return (yylval.i=NORMALTYPE); }
|
||||
"break" { SETLINE; return (yylval.i=BREAK); }
|
||||
"closure" { SETLINE; return (yylval.i=CLOSURE); }
|
||||
"color" { SETLINE; return (yylval.i=COLORTYPE); }
|
||||
"continue" { SETLINE; return (yylval.i=CONTINUE); }
|
||||
"do" { SETLINE; return (yylval.i=DO); }
|
||||
"else" { SETLINE; return (yylval.i=ELSE); }
|
||||
"float" { SETLINE; return (yylval.i=FLOATTYPE); }
|
||||
"for" { SETLINE; return (yylval.i=FOR); }
|
||||
"if" { SETLINE; return (yylval.i=IF_TOKEN); }
|
||||
"illuminance" { SETLINE; return (yylval.i=ILLUMINANCE); }
|
||||
"illuminate" { SETLINE; return (yylval.i=ILLUMINATE); }
|
||||
"int" { SETLINE; return (yylval.i=INTTYPE); }
|
||||
"matrix" { SETLINE; return (yylval.i=MATRIXTYPE); }
|
||||
"normal" { SETLINE; return (yylval.i=NORMALTYPE); }
|
||||
"output" { SETLINE; return (yylval.i=OUTPUT); }
|
||||
"point" { SETLINE; return (yylval.i=POINTTYPE); }
|
||||
"public" { SETLINE; return (yylval.i=PUBLIC); }
|
||||
"return" { SETLINE; return (yylval.i=RETURN); }
|
||||
"string" { SETLINE; return (yylval.i=STRINGTYPE); }
|
||||
"struct" { SETLINE; return (yylval.i=STRUCT); }
|
||||
"vector" { SETLINE; return (yylval.i=VECTORTYPE); }
|
||||
"void" { SETLINE; return (yylval.i=VOIDTYPE); }
|
||||
"while" { SETLINE; return (yylval.i=WHILE); }
|
||||
"or" { SETLINE; return (yylval.i=OR_OP); }
|
||||
"and" { SETLINE; return (yylval.i=AND_OP); }
|
||||
"not" { SETLINE; return (yylval.i=NOT_OP); }
|
||||
"point" { SETLINE; return (yylval.i=POINTTYPE); }
|
||||
"public" { SETLINE; return (yylval.i=PUBLIC); }
|
||||
"return" { SETLINE; return (yylval.i=RETURN); }
|
||||
"string" { SETLINE; return (yylval.i=STRINGTYPE); }
|
||||
"struct" { SETLINE; return (yylval.i=STRUCT); }
|
||||
"vector" { SETLINE; return (yylval.i=VECTORTYPE); }
|
||||
"void" { SETLINE; return (yylval.i=VOIDTYPE); }
|
||||
"while" { SETLINE; return (yylval.i=WHILE); }
|
||||
"or" { SETLINE; return (yylval.i=OR_OP); }
|
||||
"and" { SETLINE; return (yylval.i=AND_OP); }
|
||||
"not" { SETLINE; return (yylval.i=NOT_OP); }
|
||||
|
||||
/* reserved words */
|
||||
"bool"|"case"|"char"|"class"|"const"|"default"|"double" | \
|
||||
@@ -175,17 +181,17 @@ void preprocess (const char *yytext);
|
||||
"protected"|"short"|"signed"|"sizeof"|"static"|"struct" | \
|
||||
"switch"|"template"|"this"|"true"|"typedef"|"uniform" | \
|
||||
"union"|"unsigned"|"varying"|"virtual" {
|
||||
fprintf (stderr, "Error: \"%s\", line %d:\n"
|
||||
"\t'%s' is a reserved word\n",
|
||||
oslcompiler->filename().c_str(),
|
||||
oslcompiler->lineno(), yytext);
|
||||
oslcompiler->error (oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"'%s' is a reserved word",
|
||||
yytext);
|
||||
SETLINE;
|
||||
return (yylval.i=RESERVED);
|
||||
}
|
||||
|
||||
|
||||
/* Identifiers */
|
||||
{IDENT} {
|
||||
{IDENT} {
|
||||
yylval.s = ustring(yytext).c_str();
|
||||
SETLINE;
|
||||
return IDENTIFIER;
|
||||
@@ -241,23 +247,23 @@ void preprocess (const char *yytext);
|
||||
* catch-all rule, but we need to define the two-character operators
|
||||
* so they are not lexed as '+' and '=' separately, for example.
|
||||
*/
|
||||
"+=" { SETLINE; return (yylval.i=ADD_ASSIGN); }
|
||||
"-=" { SETLINE; return (yylval.i=SUB_ASSIGN); }
|
||||
"*=" { SETLINE; return (yylval.i=MUL_ASSIGN); }
|
||||
"/=" { SETLINE; return (yylval.i=DIV_ASSIGN); }
|
||||
"&=" { SETLINE; return (yylval.i=BIT_AND_ASSIGN); }
|
||||
"|=" { SETLINE; return (yylval.i=BIT_OR_ASSIGN); }
|
||||
"^=" { SETLINE; return (yylval.i=XOR_ASSIGN); }
|
||||
"<<=" { SETLINE; return (yylval.i=SHL_ASSIGN); }
|
||||
">>=" { SETLINE; return (yylval.i=SHR_ASSIGN); }
|
||||
"<<" { SETLINE; return (yylval.i=SHL_OP); }
|
||||
">>" { SETLINE; return (yylval.i=SHR_OP); }
|
||||
"&&" { SETLINE; return (yylval.i=AND_OP); }
|
||||
"||" { SETLINE; return (yylval.i=OR_OP); }
|
||||
"<=" { SETLINE; return (yylval.i=LE_OP); }
|
||||
">=" { SETLINE; return (yylval.i=GE_OP); }
|
||||
"==" { SETLINE; return (yylval.i=EQ_OP); }
|
||||
"!=" { SETLINE; return (yylval.i=NE_OP); }
|
||||
"+=" { SETLINE; return (yylval.i=ADD_ASSIGN); }
|
||||
"-=" { SETLINE; return (yylval.i=SUB_ASSIGN); }
|
||||
"*=" { SETLINE; return (yylval.i=MUL_ASSIGN); }
|
||||
"/=" { SETLINE; return (yylval.i=DIV_ASSIGN); }
|
||||
"&=" { SETLINE; return (yylval.i=BIT_AND_ASSIGN); }
|
||||
"|=" { SETLINE; return (yylval.i=BIT_OR_ASSIGN); }
|
||||
"^=" { SETLINE; return (yylval.i=XOR_ASSIGN); }
|
||||
"<<=" { SETLINE; return (yylval.i=SHL_ASSIGN); }
|
||||
">>=" { SETLINE; return (yylval.i=SHR_ASSIGN); }
|
||||
"<<" { SETLINE; return (yylval.i=SHL_OP); }
|
||||
">>" { SETLINE; return (yylval.i=SHR_OP); }
|
||||
"&&" { SETLINE; return (yylval.i=AND_OP); }
|
||||
"||" { SETLINE; return (yylval.i=OR_OP); }
|
||||
"<=" { SETLINE; return (yylval.i=LE_OP); }
|
||||
">=" { SETLINE; return (yylval.i=GE_OP); }
|
||||
"==" { SETLINE; return (yylval.i=EQ_OP); }
|
||||
"!=" { SETLINE; return (yylval.i=NE_OP); }
|
||||
"++" { SETLINE; return (yylval.i=INCREMENT); }
|
||||
"--" { SETLINE; return (yylval.i=DECREMENT); }
|
||||
|
||||
@@ -265,17 +271,17 @@ void preprocess (const char *yytext);
|
||||
"[[" { SETLINE; return (yylval.i=METADATA_BEGIN); }
|
||||
|
||||
/* End of line */
|
||||
"\\\n" |
|
||||
[\n] { oslcompiler->incr_lineno();
|
||||
"\\\n" |
|
||||
[\n] { oslcompiler->incr_lineno();
|
||||
SETLINE;
|
||||
}
|
||||
|
||||
/* Ignore whitespace */
|
||||
{WHITE} { }
|
||||
{WHITE} { }
|
||||
|
||||
/* catch-all rule for any other single characters */
|
||||
! { SETLINE; return (yylval.i = NOT_OP); }
|
||||
. { SETLINE; return (yylval.i = *yytext); }
|
||||
! { SETLINE; return (yylval.i = NOT_OP); }
|
||||
. { SETLINE; return (yylval.i = *yytext); }
|
||||
|
||||
%%
|
||||
|
||||
@@ -290,29 +296,54 @@ preprocess (const char *yytext)
|
||||
while (*p == ' ' || *p == '\t')
|
||||
p++;
|
||||
if (*p != '#') {
|
||||
fprintf (stderr, "Possible bug in shader preprocess\n");
|
||||
oslcompiler->error (oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"Possible bug in shader preprocess");
|
||||
SETLINE;
|
||||
return;
|
||||
return;
|
||||
}
|
||||
p++;
|
||||
while (*p == ' ' || *p == '\t')
|
||||
p++;
|
||||
if (! strncmp (p, "pragma", 6)) {
|
||||
// pragma
|
||||
fprintf (stderr, "Unknown pragma '%s'\n", p);
|
||||
// pragma
|
||||
OIIO::string_view line (p+6);
|
||||
string_view pragmatype = OIIO::Strutil::parse_word (line);
|
||||
if (OIIO::Strutil::iequals (pragmatype, "osl")) {
|
||||
string_view pragmaname = OIIO::Strutil::parse_word (line);
|
||||
if (pragmaname == "nowarn") {
|
||||
oslcompiler->pragma_nowarn ();
|
||||
} else {
|
||||
oslcompiler->warning (oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"Unknown pragma '%s'", pragmaname);
|
||||
}
|
||||
}
|
||||
// N.B. Pragmas that don't start with "osl" are ignored
|
||||
oslcompiler->incr_lineno(); // the pragma ends with an EOLN
|
||||
} else { /* probably the line number and filename */
|
||||
if (! strncmp (p, "line", 4))
|
||||
p += 4;
|
||||
int line = atoi (p);
|
||||
if (line > 0) {
|
||||
const char *f = strchr (yytext, '\"');
|
||||
if (f) {
|
||||
const char *f = strchr (yytext, '\"');
|
||||
if (f) {
|
||||
++f; // increment to past the quote
|
||||
int len = 0; // count of chars within quotes
|
||||
while (f[len] && f[len] != '\"')
|
||||
++len;
|
||||
int len = 0; // count of chars within quotes
|
||||
while (f[len] && f[len] != '\"')
|
||||
++len;
|
||||
std::string filename (f, len);
|
||||
#if defined(_WIN32) && defined(USE_BOOST_WAVE) && (USE_BOOST_WAVE != 0)
|
||||
// Assuming boost is the culprit and escaping Windows path
|
||||
// separators incorrectly which clang's preprocessor won't do.
|
||||
// Should this just be for Windows CI builds?
|
||||
auto replace_all = [](std::string& str, const std::string& from, const std::string& to) {
|
||||
size_t start = 0;
|
||||
while((start = str.find(from, start)) != std::string::npos) {
|
||||
str.replace(start, from.size(), to);
|
||||
start += to.size();
|
||||
}
|
||||
};
|
||||
replace_all( filename, "\\\\", "\\");
|
||||
#endif
|
||||
// Make it relative to the working directory, so error output
|
||||
// isn't hugely cluttered (and also to make Boost::wave's
|
||||
// error output match the standard cpp.
|
||||
@@ -322,7 +353,7 @@ preprocess (const char *yytext)
|
||||
(filename[0] == '/' || filename[0] == '\\'))
|
||||
filename.erase (0, 1);
|
||||
}
|
||||
oslcompiler->filename (ustring (filename));
|
||||
oslcompiler->filename (ustring (filename));
|
||||
// Spooky workaround for Boost Wave bug: force_include
|
||||
// is broken and doesn't give us the right lines/files, so
|
||||
// instead we forcefully insert a '#include "stdosl.h"' into
|
||||
@@ -333,10 +364,9 @@ preprocess (const char *yytext)
|
||||
--line;
|
||||
}
|
||||
oslcompiler->lineno (line);
|
||||
} else {
|
||||
fprintf (stderr, "Error: \"%s\", line %d:\n"
|
||||
"\tUnrecognized preprocessor command: #%s\n",
|
||||
oslcompiler->filename().c_str(), oslcompiler->lineno(), p);
|
||||
} else {
|
||||
oslcompiler->error (oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"Unrecognized preprocessor command: #%s", p);
|
||||
}
|
||||
}
|
||||
SETLINE;
|
||||
@@ -351,9 +381,8 @@ namespace pvt { // OSL::pvt
|
||||
bool
|
||||
OSLCompilerImpl::osl_parse_buffer (const std::string &preprocessed_buffer)
|
||||
{
|
||||
// Thread safety with the lexer/parser
|
||||
static std::mutex oslcompiler_mutex;
|
||||
std::lock_guard<std::mutex> lock (oslcompiler_mutex);
|
||||
// N.B. This should only be called if oslcompiler_mutex is held.
|
||||
ASSERT (oslcompiler == this);
|
||||
|
||||
#ifndef OIIO_STRUTIL_HAS_STOF
|
||||
// Force classic "C" locale for correct '.' decimal parsing.
|
||||
@@ -365,7 +394,6 @@ OSLCompilerImpl::osl_parse_buffer (const std::string &preprocessed_buffer)
|
||||
#endif
|
||||
|
||||
osl_switch_to_buffer (osl_scan_string (preprocessed_buffer.c_str()));
|
||||
oslcompiler = this;
|
||||
oslparse ();
|
||||
bool parseerr = error_encountered();
|
||||
osl_delete_buffer (YY_CURRENT_BUFFER);
|
||||
|
||||
+1046
-265
File diff suppressed because it is too large
Load Diff
@@ -69,7 +69,7 @@ MACRO ( LLVM_COMPILE llvm_src srclist )
|
||||
foreach (def ${CURRENT_DEFINITIONS})
|
||||
set (LLVM_COMPILE_FLAGS ${LLVM_COMPILE_FLAGS} "-D${def}")
|
||||
endforeach()
|
||||
set (LLVM_COMPILE_FLAGS ${LLVM_COMPILE_FLAGS} ${SIMD_COMPILE_FLAGS} ${CSTD_FLAGS})
|
||||
set (LLVM_COMPILE_FLAGS ${LLVM_COMPILE_FLAGS} ${SIMD_COMPILE_FLAGS} ${CSTD_FLAGS} ${TOOLCHAIN_FLAGS})
|
||||
|
||||
# Figure out what program we will use to make the bitcode.
|
||||
if (NOT LLVM_BC_GENERATOR)
|
||||
@@ -117,15 +117,82 @@ MACRO ( LLVM_COMPILE llvm_src srclist )
|
||||
-Wno-deprecated-register
|
||||
-O3 -fno-math-errno -S -emit-llvm -o ${llvm_asm} ${llvm_src}
|
||||
COMMAND "${LLVM_DIRECTORY}/bin/llvm-as" -f -o ${llvm_bc} ${llvm_asm}
|
||||
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/serialize-bc.bash" ${llvm_bc} ${llvm_bc_cpp}
|
||||
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/serialize-bc.bash" ${llvm_bc} ${llvm_bc_cpp} "osl_llvm_compiled_ops"
|
||||
MAIN_DEPENDENCY ${llvm_src}
|
||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/serialize-bc.bash"
|
||||
${exec_headers} ${PROJECT_PUBLIC_HEADERS}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
|
||||
ENDMACRO ( )
|
||||
|
||||
# Function to compile a C++ source file to CUDA-compatible LLVM bitcode
|
||||
FUNCTION ( MAKE_CUDA_BITCODE src generated_bc )
|
||||
GET_FILENAME_COMPONENT ( src_we ${src} NAME_WE )
|
||||
SET ( asm_cuda "${CMAKE_CURRENT_BINARY_DIR}/${src_we}_cuda.s" )
|
||||
SET ( bc_cuda "${CMAKE_CURRENT_BINARY_DIR}/${src_we}_cuda.bc" )
|
||||
|
||||
ADD_CUSTOM_COMMAND ( OUTPUT ${bc_cuda}
|
||||
COMMAND ${LLVM_BC_GENERATOR}
|
||||
${LLVM_COMPILE_FLAGS}
|
||||
"-I${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
"-I${CMAKE_SOURCE_DIR}/src/include"
|
||||
"-I${CMAKE_BINARY_DIR}/include"
|
||||
"-I${OPENIMAGEIO_INCLUDE_DIR}"
|
||||
"-I${ILMBASE_INCLUDE_DIR}"
|
||||
"-I${Boost_INCLUDE_DIRS}"
|
||||
-D__CUDACC__ -DOSL_COMPILING_TO_BITCODE=1 -DNDEBUG -DOIIO_NO_SSE
|
||||
--language=cuda --cuda-device-only --cuda-gpu-arch=${CUDA_TARGET_ARCH}
|
||||
${CUDA_LIB_FLAGS}
|
||||
-std=c++11 -Wno-deprecated-register
|
||||
-O3 -fno-math-errno -S -emit-llvm -o ${asm_cuda} ${src}
|
||||
COMMAND "${LLVM_DIRECTORY}/bin/llvm-as" -f -o ${bc_cuda} ${asm_cuda}
|
||||
DEPENDS ${exec_headers} ${PROJECT_PUBLIC_HEADERS} ${src}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
|
||||
SET ( ${generated_bc} ${bc_cuda} PARENT_SCOPE )
|
||||
ENDFUNCTION ()
|
||||
|
||||
MACRO ( CUDA_SHADEOPS_COMPILE srclist )
|
||||
# Add all of the "shadeops" sources that need to be compiled to LLVM bitcode for CUDA
|
||||
set ( shadeops_srcs
|
||||
llvm_ops.cpp
|
||||
opnoise.cpp
|
||||
../liboslnoise/simplexnoise.cpp
|
||||
)
|
||||
|
||||
SET ( shadeops_bc_cuda_cpp "${CMAKE_CURRENT_BINARY_DIR}/shadeops_cuda.bc.cpp" )
|
||||
SET ( linked_shadeops_bc "${CMAKE_CURRENT_BINARY_DIR}/linked_shadeops.bc" )
|
||||
|
||||
LIST ( APPEND ${srclist} ${shadeops_bc_cuda_cpp} )
|
||||
|
||||
FOREACH ( shadeops_src ${shadeops_srcs} )
|
||||
MAKE_CUDA_BITCODE ( ${shadeops_src} shadeops_bc )
|
||||
LIST ( APPEND shadeops_bc_list ${shadeops_bc} )
|
||||
ENDFOREACH ()
|
||||
|
||||
# Link all of the individual LLVM bitcode files
|
||||
ADD_CUSTOM_COMMAND ( OUTPUT ${linked_shadeops_bc}
|
||||
COMMAND "${LLVM_DIRECTORY}/bin/llvm-link" -internalize ${shadeops_bc_list} -o ${linked_shadeops_bc}
|
||||
DEPENDS ${shadeops_bc_list} ${exec_headers} ${PROJECT_PUBLIC_HEADERS} ${shadeops_srcs}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
|
||||
# Serialze the linked bitcode into a CPP file and add it to the list of liboslexec soures
|
||||
ADD_CUSTOM_COMMAND ( OUTPUT ${shadeops_bc_cuda_cpp}
|
||||
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/serialize-bc.bash"
|
||||
${linked_shadeops_bc} ${shadeops_bc_cuda_cpp} "osl_llvm_compiled_ops_cuda"
|
||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/serialize-bc.bash" ${linked_shadeops_bc}
|
||||
${exec_headers} ${PROJECT_PUBLIC_HEADERS}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
ENDMACRO ( )
|
||||
|
||||
if (USE_LLVM_BITCODE)
|
||||
LLVM_COMPILE ( llvm_ops.cpp liboslexec_srcs )
|
||||
|
||||
# Optionally repeat the bitcode compilation with CUDA-specific options
|
||||
if (CUDA_FOUND)
|
||||
ADD_DEFINITIONS (-DOSL_LLVM_CUDA_BITCODE)
|
||||
CUDA_SHADEOPS_COMPILE ( liboslexec_srcs )
|
||||
endif ()
|
||||
else ()
|
||||
# With MSVC/Mingw, we don't compile llvm_ops.cpp to LLVM bitcode, due
|
||||
# to clang being unable to compile MSVC C++ header files at this time.
|
||||
@@ -138,6 +205,14 @@ if (BUILDSTATIC)
|
||||
ADD_LIBRARY ( oslexec STATIC ${liboslexec_srcs} )
|
||||
else ()
|
||||
ADD_LIBRARY ( oslexec SHARED ${liboslexec_srcs} )
|
||||
|
||||
if (VERBOSE)
|
||||
message(STATUS "Setting SOVERSION to: ${SOVERSION}")
|
||||
endif ()
|
||||
set_target_properties( oslexec
|
||||
PROPERTIES
|
||||
VERSION ${OSL_VERSION_MAJOR}.${OSL_VERSION_MINOR}.${OSL_VERSION_PATCH}
|
||||
SOVERSION ${SOVERSION} )
|
||||
endif ()
|
||||
|
||||
TARGET_LINK_LIBRARIES ( oslexec
|
||||
@@ -147,7 +222,6 @@ TARGET_LINK_LIBRARIES ( oslexec
|
||||
${PARTIO_LIBRARIES} ${ZLIB_LIBRARIES}
|
||||
${Boost_LIBRARIES} ${CMAKE_DL_LIBS}
|
||||
${CLANG_LIBRARIES}
|
||||
${LLVM_LIBRARY} ${LLVM_MCJIT_LIBRARY}
|
||||
${LLVM_LIBRARIES} ${LLVM_LDFLAGS}
|
||||
${LLVM_SYSTEM_LIBRARIES})
|
||||
ADD_DEPENDENCIES (oslexec "${CMAKE_SOURCE_DIR}/src/build-scripts/hidesymbols.map")
|
||||
|
||||
+314
-16
@@ -97,6 +97,7 @@ BackendLLVM::BackendLLVM (ShadingSystemImpl &shadingsys,
|
||||
// getcwd inside LLVM. Oy.
|
||||
check_cwd (shadingsys);
|
||||
#endif
|
||||
m_use_optix = shadingsys.renderer()->supports ("OptiX");
|
||||
}
|
||||
|
||||
|
||||
@@ -112,10 +113,10 @@ BackendLLVM::llvm_debug() const
|
||||
{
|
||||
if (shadingsys().llvm_debug() == 0)
|
||||
return 0;
|
||||
if (shadingsys().debug_groupname() &&
|
||||
if (!shadingsys().debug_groupname().empty() &&
|
||||
shadingsys().debug_groupname() != group().name())
|
||||
return 0;
|
||||
if (inst() && shadingsys().debug_layername() &&
|
||||
if (inst() && !shadingsys().debug_layername().empty() &&
|
||||
shadingsys().debug_layername() != inst()->layername())
|
||||
return 0;
|
||||
return shadingsys().llvm_debug();
|
||||
@@ -323,6 +324,215 @@ BackendLLVM::getOrAllocateLLVMSymbol (const Symbol& sym)
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BackendLLVM::addCUDAVariable(const std::string& name, int size, int alignment,
|
||||
void* data, const std::string& type)
|
||||
{
|
||||
ASSERT (use_optix() && "This function is only supposed to be used with OptiX!");
|
||||
|
||||
llvm::Constant* constant = nullptr;
|
||||
|
||||
if (type == "float") {
|
||||
constant = llvm::ConstantFP::get (
|
||||
llvm::Type::getFloatTy (ll.module()->getContext()), *(float*) data);
|
||||
}
|
||||
else if (type == "int") {
|
||||
constant = llvm::ConstantInt::get (
|
||||
llvm::Type::getInt32Ty (ll.module()->getContext()), *(int*) data);
|
||||
}
|
||||
else if (type == "string") {
|
||||
// Register the string with the OptiX renderer. The renderer will add
|
||||
// the string to a global table and create an OptiX variable to hold the
|
||||
// char*.
|
||||
shadingsys().renderer()->register_string (((ustring*)data)->string(), name);
|
||||
|
||||
// Add the metadata needed by OptiX to access the variable.
|
||||
createOptixMetadata (name, "string", 8);
|
||||
|
||||
// Leave the variable uninitialized to prevent raw pointers from
|
||||
// appearing in the generated code. The OptiX renderer will set the
|
||||
// variable to the string address before the kernel is launched.
|
||||
constant = llvm::ConstantInt::get (
|
||||
llvm::Type::getInt64Ty (ll.module()->getContext()), 0);
|
||||
|
||||
m_varname_map [name] = ((ustring*)data)->string();
|
||||
}
|
||||
else {
|
||||
// Handle unspecified types as generic byte arrays
|
||||
llvm::ArrayRef<uint8_t> arr_ref ((uint8_t*)data, size);
|
||||
constant = llvm::ConstantDataArray::get (ll.module()->getContext(), arr_ref);
|
||||
}
|
||||
|
||||
llvm::GlobalVariable* g_var = reinterpret_cast<llvm::GlobalVariable*>(
|
||||
ll.module()->getOrInsertGlobal (name, constant->getType()));
|
||||
|
||||
ASSERT (g_var && "Unable to create GlobalVariable");
|
||||
|
||||
g_var->setAlignment (alignment);
|
||||
g_var->setLinkage (llvm::GlobalValue::ExternalLinkage);
|
||||
g_var->setVisibility (llvm::GlobalValue::DefaultVisibility);
|
||||
g_var->setInitializer(constant);
|
||||
|
||||
m_const_map[name] = g_var;
|
||||
|
||||
return g_var;
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BackendLLVM::createOptixVariable (const std::string& name, const std::string& type,
|
||||
int size, void* data)
|
||||
{
|
||||
ASSERT (use_optix() && "This function is only supported when using OptiX!");
|
||||
|
||||
// Return the Value if it has already been allocated
|
||||
std::map<std::string, llvm::GlobalVariable*>::iterator it =
|
||||
get_const_map().find (name);
|
||||
|
||||
if (it != get_const_map().end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
int alignment =
|
||||
(type == "float" ) ? 4 :
|
||||
(type == "int" ) ? 4 :
|
||||
(type == "color" ) ? 8 :
|
||||
(type == "string") ? 8 : 8;
|
||||
|
||||
// Create a global variable with the name, type, and initializer. This is
|
||||
// the value that will be accessed when the shader executes.
|
||||
llvm::Value* g_var = addCUDAVariable (name, size, alignment, data, type);
|
||||
|
||||
if (g_var == nullptr) {
|
||||
ASSERT (0 && "Unable to create OptiX variable");
|
||||
}
|
||||
|
||||
createOptixMetadata (name, type, size);
|
||||
|
||||
return g_var;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BackendLLVM::createOptixMetadata (const std::string& name, const std::string& type,
|
||||
int size)
|
||||
{
|
||||
// Create additional variables with the semantic information needed by OptiX
|
||||
// to access the global variable created above.
|
||||
//
|
||||
// There is no need to retain pointers to these variables, since they are not
|
||||
// accessed during execution. They are only used internally by OptiX.
|
||||
//
|
||||
// Refer to the OptiX API documentation and optix_defines.h in the OptiX SDK
|
||||
// for more information.
|
||||
|
||||
ASSERT (use_optix() && "This function is only supported when using OptiX!");
|
||||
|
||||
auto mangle_name = [](const std::string& name, const std::string& prefix) {
|
||||
return OIIO::Strutil::format ("_ZN%drti_internal_%s%d%sE",
|
||||
prefix.size()+13, prefix, name.size(), name);
|
||||
};
|
||||
|
||||
const std::string optix_type =
|
||||
(type == "color" ) ? "float3" :
|
||||
(type == "string") ? "uint64_t" :
|
||||
type;
|
||||
|
||||
// Copy the OptiX typename contents into a temporary vector
|
||||
std::vector<char> type_name (optix_type.c_str(),
|
||||
optix_type.c_str() + optix_type.size() + 1);
|
||||
|
||||
struct rti_typeinfo {
|
||||
unsigned int kind = 0x796152; // _OPTIX_VARIABLE
|
||||
unsigned int size;
|
||||
} type_info;
|
||||
type_info.size = size;
|
||||
|
||||
int type_enum = 0x1337; // _OPTIX_TYPE_ENUM_UNKNOWN
|
||||
|
||||
char empty = 0;
|
||||
|
||||
addCUDAVariable (mangle_name (name, "typeinfo" ), 8, 4, &type_info, "");
|
||||
addCUDAVariable (mangle_name (name, "typename" ), type_name.size(), 16, type_name.data(), "");
|
||||
addCUDAVariable (mangle_name (name, "typeenum" ), 4, 4, &type_enum, "int");
|
||||
addCUDAVariable (mangle_name (name, "semantic" ), 1, 1, &empty, "");
|
||||
addCUDAVariable (mangle_name (name, "annotation"), 1, 1, &empty, "");
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value *
|
||||
BackendLLVM::getOrAllocateCUDAVariable (const Symbol& sym)
|
||||
{
|
||||
ASSERT (use_optix() && "This function is only supported when using OptiX!");
|
||||
|
||||
std::stringstream ss;
|
||||
if (sym.typespec().is_string()) {
|
||||
// Use the ustring hash to create a name for the symbol that's based on
|
||||
// the string contents
|
||||
//
|
||||
// TODO: Collisions between variable names are unlikely, but stil
|
||||
// possible. Using something like a counter to handle collisions
|
||||
// is unattractive because it depends on the order in which
|
||||
// strings are encountered at run time.
|
||||
//
|
||||
// For now I am simply appending the length to the hash, but a
|
||||
// more robust solution may be called for.
|
||||
|
||||
ss << "ds_"
|
||||
<< std::setbase (16) << std::setfill('0') << std::setw (16)
|
||||
<< (*(ustring *)sym.data()).hash()
|
||||
<< "_"
|
||||
<< std::setbase (16) << std::setfill('0') << std::setw (4)
|
||||
<< (*(ustring *)sym.data()).length();
|
||||
|
||||
auto it = m_varname_map.find(ss.str());
|
||||
const std::string old_str = (it != m_varname_map.end())
|
||||
? it->second : "";
|
||||
|
||||
if (old_str != "" && old_str != (*(ustring *)sym.data()).string()) {
|
||||
std::cerr << "Warning: variable name collision between " << old_str
|
||||
<< " and " << (*(ustring *)sym.data()).string()
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// PTX doesn't like leading dollar signs, so prepend an underscore
|
||||
if (sym.name()[0] == '$') {
|
||||
ss << '_';
|
||||
}
|
||||
|
||||
ss << sym.name();
|
||||
}
|
||||
|
||||
const std::string name = ss.str();
|
||||
|
||||
// Return the Value if it has already been allocated
|
||||
std::map<std::string, llvm::GlobalVariable*>::iterator it =
|
||||
get_const_map().find (name);
|
||||
|
||||
if (it != get_const_map().end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
int alignment =
|
||||
(sym.typespec().is_scalarnum()) ? 4 :
|
||||
(sym.typespec().is_triple() ) ? 8 :
|
||||
(sym.typespec().is_array() ) ? 8 :
|
||||
(sym.typespec().is_string() ) ? 8 : -1;
|
||||
|
||||
if (alignment < 1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return addCUDAVariable (name, sym.size(), alignment, sym.data(),
|
||||
sym.typespec().string());
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value *
|
||||
BackendLLVM::llvm_get_pointer (const Symbol& sym, int deriv,
|
||||
llvm::Value *arrayindex)
|
||||
@@ -336,9 +546,23 @@ BackendLLVM::llvm_get_pointer (const Symbol& sym, int deriv,
|
||||
|
||||
llvm::Value *result = NULL;
|
||||
if (sym.symtype() == SymTypeConst) {
|
||||
// For constants, start with *OUR* pointer to the constant values.
|
||||
result = ll.ptr_cast (ll.constant_ptr (sym.data()),
|
||||
ll.type_ptr (llvm_type(sym.typespec().elementtype())));
|
||||
if (use_optix()) {
|
||||
// Check the constant map for the named Symbol; if it's found, then
|
||||
// a GlobalVariable has been created for it
|
||||
llvm::Value* ptr = getOrAllocateCUDAVariable (sym);
|
||||
if (ptr) {
|
||||
llvm::Type *cast_type = (! sym.typespec().is_string())
|
||||
? ll.type_ptr (llvm_type(sym.typespec().elementtype()))
|
||||
: ll.type_void_ptr();
|
||||
|
||||
result = ll.ptr_cast (ptr, cast_type);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// For constants, start with *OUR* pointer to the constant values.
|
||||
result = ll.ptr_cast (ll.constant_ptr (sym.data()),
|
||||
ll.type_ptr (llvm_type(sym.typespec().elementtype())));
|
||||
}
|
||||
|
||||
} else {
|
||||
// Start with the initial pointer to the variable's memory location
|
||||
@@ -444,12 +668,34 @@ BackendLLVM::llvm_load_value (llvm::Value *ptr, const TypeSpec &type,
|
||||
result = ll.op_float_to_int (result);
|
||||
else if (type.is_int() && cast == TypeDesc::TypeFloat)
|
||||
result = ll.op_int_to_float (result);
|
||||
else if (type.is_string() && cast == TypeDesc::UINT64)
|
||||
result = ll.ptr_to_cast (result, ll.type_longlong());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value *
|
||||
BackendLLVM::llvm_load_device_string (const Symbol& sym, bool follow)
|
||||
{
|
||||
// TODO: need to make this work with arrays of strings
|
||||
ASSERT (use_optix() && "This is only intended to be used with CUDA");
|
||||
|
||||
llvm::Value* val = (sym.is_constant() || sym.data())
|
||||
? getOrAllocateCUDAVariable (sym)
|
||||
: llvm_load_value (sym, 0, nullptr, 0, TypeDesc(TypeDesc::UINT64));
|
||||
|
||||
// Typically, the address of the string is held in a global variable, so we
|
||||
// need to dereference the global to get to the char*.
|
||||
if (follow)
|
||||
val = ll.int_to_ptr_cast (ll.op_load (val));
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value *
|
||||
BackendLLVM::llvm_load_constant_value (const Symbol& sym,
|
||||
int arrayindex, int component,
|
||||
@@ -483,6 +729,10 @@ BackendLLVM::llvm_load_constant_value (const Symbol& sym,
|
||||
int ncomps = (int) sym.typespec().aggregate();
|
||||
return ll.constant (val[ncomps*arrayindex + component]);
|
||||
}
|
||||
if (sym.typespec().is_string() && use_optix()) {
|
||||
// TODO: This ignores arrayindex
|
||||
return llvm_load_device_string (sym);
|
||||
}
|
||||
if (sym.typespec().is_string()) {
|
||||
const ustring *val = (const ustring *)sym.data();
|
||||
return ll.constant (val[arrayindex]);
|
||||
@@ -686,6 +936,8 @@ BackendLLVM::llvm_call_function (const char *name,
|
||||
const Symbol &s = *(symargs[i]);
|
||||
if (s.typespec().is_closure())
|
||||
valargs[i] = llvm_load_value (s);
|
||||
else if (use_optix() && s.typespec().is_string())
|
||||
valargs[i] = llvm_load_device_string (s);
|
||||
else if (s.typespec().simpletype().aggregate > 1 ||
|
||||
(deriv_ptrs && s.has_derivs()))
|
||||
valargs[i] = llvm_void_ptr (s);
|
||||
@@ -767,7 +1019,7 @@ BackendLLVM::llvm_test_nonzero (Symbol &val, bool test_derivs)
|
||||
|
||||
bool
|
||||
BackendLLVM::llvm_assign_impl (Symbol &Result, Symbol &Src,
|
||||
int arrayindex)
|
||||
int arrayindex, int srccomp, int dstcomp)
|
||||
{
|
||||
ASSERT (! Result.typespec().is_structure());
|
||||
ASSERT (! Src.typespec().is_structure());
|
||||
@@ -825,29 +1077,75 @@ BackendLLVM::llvm_assign_impl (Symbol &Result, Symbol &Src,
|
||||
// Remember that llvm_load_value will automatically convert scalar->triple.
|
||||
TypeDesc rt = Result.typespec().simpletype();
|
||||
TypeDesc basetype = TypeDesc::BASETYPE(rt.basetype);
|
||||
int num_components = rt.aggregate;
|
||||
for (int i = 0; i < num_components; ++i) {
|
||||
const int num_components = rt.aggregate;
|
||||
const bool singlechan = (srccomp != -1) || (dstcomp != -1);
|
||||
if (use_optix() && Src.typespec().is_string()) {
|
||||
// We defer the loading of the char* until the assigned value is
|
||||
// actually used, so just pass the value of the global variable.
|
||||
llvm::Value* src = llvm_load_device_string (Src, false);
|
||||
llvm_store_value (ll.ptr_cast (src, ll.type_void_ptr()), Result);
|
||||
}
|
||||
else if (!singlechan) {
|
||||
for (int i = 0; i < num_components; ++i) {
|
||||
llvm::Value* src_val = Src.is_constant()
|
||||
? llvm_load_constant_value (Src, arrayindex, i, basetype)
|
||||
: llvm_load_value (Src, 0, arrind, i, basetype);
|
||||
if (!src_val)
|
||||
return false;
|
||||
llvm_store_value (src_val, Result, 0, arrind, i);
|
||||
}
|
||||
} else {
|
||||
// connect individual component of an aggregate type
|
||||
// set srccomp to 0 for case when src is actually a float
|
||||
if (srccomp == -1) srccomp = 0;
|
||||
llvm::Value* src_val = Src.is_constant()
|
||||
? llvm_load_constant_value (Src, arrayindex, i, basetype)
|
||||
: llvm_load_value (Src, 0, arrind, i, basetype);
|
||||
? llvm_load_constant_value (Src, arrayindex, srccomp, basetype)
|
||||
: llvm_load_value (Src, 0, arrind, srccomp, basetype);
|
||||
if (!src_val)
|
||||
return false;
|
||||
llvm_store_value (src_val, Result, 0, arrind, i);
|
||||
// write source float into all compnents when dstcomp == -1, otherwise
|
||||
// the single element requested.
|
||||
if (dstcomp == -1) {
|
||||
for (int i = 0; i < num_components; ++i)
|
||||
llvm_store_value (src_val, Result, 0, arrind, i);
|
||||
} else
|
||||
llvm_store_value (src_val, Result, 0, arrind, dstcomp);
|
||||
}
|
||||
|
||||
// Handle derivatives
|
||||
if (Result.has_derivs()) {
|
||||
if (Src.has_derivs()) {
|
||||
// src and result both have derivs -- copy them
|
||||
for (int d = 1; d <= 2; ++d) {
|
||||
for (int i = 0; i < num_components; ++i) {
|
||||
llvm::Value* val = llvm_load_value (Src, d, arrind, i);
|
||||
llvm_store_value (val, Result, d, arrind, i);
|
||||
if (!singlechan) {
|
||||
for (int d = 1; d <= 2; ++d) {
|
||||
for (int i = 0; i < num_components; ++i) {
|
||||
llvm::Value* val = llvm_load_value (Src, d, arrind, i);
|
||||
llvm_store_value (val, Result, d, arrind, i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int d = 1; d <= 2; ++d) {
|
||||
llvm::Value* val = llvm_load_value (Src, d, arrind, srccomp);
|
||||
if (dstcomp == -1) {
|
||||
for (int i = 0; i < num_components; ++i)
|
||||
llvm_store_value (val, Result, d, arrind, i);
|
||||
}
|
||||
else
|
||||
llvm_store_value (val, Result, d, arrind, dstcomp);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Result wants derivs but src didn't have them -- zero them
|
||||
llvm_zero_derivs (Result);
|
||||
if (dstcomp != -1) {
|
||||
// memset the single deriv component's to zero
|
||||
if (Result.has_derivs() && Result.typespec().elementtype().is_floatbased()) {
|
||||
// dx
|
||||
ll.op_memset (ll.GEP(llvm_void_ptr(Result,1), dstcomp), 0, 1, rt.basesize());
|
||||
// dy
|
||||
ll.op_memset (ll.GEP(llvm_void_ptr(Result,2), dstcomp), 0, 1, rt.basesize());
|
||||
}
|
||||
} else
|
||||
llvm_zero_derivs (Result);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -38,6 +38,10 @@ using namespace OSL::pvt;
|
||||
#include "runtimeoptimize.h"
|
||||
#include <OSL/llvm_util.h>
|
||||
|
||||
// additional includes for creating global OptiX variables
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/GlobalVariable.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
@@ -85,7 +89,7 @@ public:
|
||||
|
||||
typedef std::map<std::string, llvm::Value*> AllocationMap;
|
||||
|
||||
void llvm_assign_initial_value (const Symbol& sym);
|
||||
void llvm_assign_initial_value (const Symbol& sym, bool force = false);
|
||||
llvm::LLVMContext &llvm_context () const { return ll.context(); }
|
||||
AllocationMap &named_values () { return m_named_values; }
|
||||
|
||||
@@ -142,6 +146,10 @@ public:
|
||||
return llvm_load_value (sym, deriv, NULL, component, cast);
|
||||
}
|
||||
|
||||
/// Load the address of a global device-side string pointer, optionally
|
||||
/// follow the pointer and cast the result to UINT64.
|
||||
llvm::Value *llvm_load_device_string (const Symbol& sym, bool follow=true);
|
||||
|
||||
/// Legacy version
|
||||
///
|
||||
llvm::Value *loadLLVMValue (const Symbol& sym, int component=0,
|
||||
@@ -211,6 +219,26 @@ public:
|
||||
/// map, the symbol is alloca'd and placed in the map.
|
||||
llvm::Value *getOrAllocateLLVMSymbol (const Symbol& sym);
|
||||
|
||||
/// Allocate a CUDA variable for the given OSL symbol and return a pointer
|
||||
/// to the corresponding LLVM GlobalVariable, or return the pointer if it
|
||||
/// has already been allocated.
|
||||
llvm::Value *getOrAllocateCUDAVariable (const Symbol& sym);
|
||||
|
||||
/// Create a CUDA global variable and add it to the current Module
|
||||
llvm::Value *addCUDAVariable (const std::string& name, int size,
|
||||
int alignment, void* data,
|
||||
const std::string& type="");
|
||||
|
||||
/// Create a CUDA variable, along with the extra semantic information needed
|
||||
/// by OptiX.
|
||||
llvm::Value *createOptixVariable (const std::string& name,
|
||||
const std::string& type,
|
||||
int size, void* data );
|
||||
|
||||
/// Create the extra semantic information needed for OptiX variables
|
||||
void createOptixMetadata (const std::string& name,
|
||||
const std::string& type, int size );
|
||||
|
||||
/// Retrieve an llvm::Value that is a pointer holding the start address
|
||||
/// of the specified symbol. This always works for globals and params;
|
||||
/// for stack variables (locals/temps) is succeeds only if the symbol is
|
||||
@@ -229,7 +257,8 @@ public:
|
||||
|
||||
/// Implementaiton of Simple assignment. If arrayindex >= 0, in
|
||||
/// designates a particular array index to assign.
|
||||
bool llvm_assign_impl (Symbol &Result, Symbol &Src, int arrayindex = -1);
|
||||
bool llvm_assign_impl (Symbol &Result, Symbol &Src, int arrayindex = -1,
|
||||
int srcomp = -1, int dstcomp = -1);
|
||||
|
||||
|
||||
/// Convert the name of a global (and its derivative index) into the
|
||||
@@ -403,6 +432,12 @@ public:
|
||||
shadingsys().m_stat_tex_calls_as_handles += 1;
|
||||
}
|
||||
|
||||
/// Return the mapping from symbol names to GlobalVariables.
|
||||
std::map<std::string,llvm::GlobalVariable*>& get_const_map() { return m_const_map; }
|
||||
|
||||
/// Return whether or not we are compiling for an OptiX-based renderer.
|
||||
bool use_optix() { return m_use_optix; }
|
||||
|
||||
LLVM_Util ll;
|
||||
|
||||
private:
|
||||
@@ -429,6 +464,16 @@ private:
|
||||
llvm::PointerType *m_llvm_type_setup_closure_func;
|
||||
int m_llvm_local_mem; // Amount of memory we use for locals
|
||||
|
||||
// A mapping from symbol names to llvm::GlobalVariables
|
||||
std::map<std::string,llvm::GlobalVariable*> m_const_map;
|
||||
|
||||
// A mapping from canonical strings to string variable names, used to
|
||||
// detect collisions that might occur due to using the string hash to
|
||||
// create variable names.
|
||||
std::map<std::string,std::string> m_varname_map;
|
||||
|
||||
bool m_use_optix; ///< Compile for OptiX?
|
||||
|
||||
friend class ShadingSystemImpl;
|
||||
};
|
||||
|
||||
|
||||
@@ -386,7 +386,7 @@ DECL (osl_texture_set_subimagename, "xXs")
|
||||
DECL (osl_texture_set_missingcolor_arena, "xXX")
|
||||
DECL (osl_texture_set_missingcolor_alpha, "xXif")
|
||||
DECL (osl_texture, "iXXXXffffffiXXXXXXX")
|
||||
DECL (osl_texture3d, "iXXXXXXXXiXXXXXXXXX")
|
||||
DECL (osl_texture3d, "iXXXXXXXiXXXXXXX")
|
||||
DECL (osl_environment, "iXXXXXXXiXXXXXXX")
|
||||
DECL (osl_get_textureinfo, "iXXXXiiiX")
|
||||
|
||||
|
||||
@@ -2345,7 +2345,7 @@ DECLFOLDER(constfold_getattribute)
|
||||
ustring obj_name;
|
||||
if (object_lookup)
|
||||
obj_name = *(const ustring *)ObjectName.data();
|
||||
if (! obj_name)
|
||||
if (obj_name.empty())
|
||||
return 0;
|
||||
|
||||
found = array_lookup
|
||||
@@ -2539,9 +2539,18 @@ DECLFOLDER(constfold_texture)
|
||||
#endif
|
||||
CHECK_str (width, float, TypeDesc::FLOAT)
|
||||
else CHECK_str (blur, float, TypeDesc::FLOAT)
|
||||
else CHECK_str (wrap, ustring, TypeDesc::STRING)
|
||||
else CHECK (firstchannel, int, TypeDesc::INT)
|
||||
else CHECK (fill, float, TypeDesc::FLOAT)
|
||||
|
||||
else if ((name == Strings::wrap || name == Strings::swrap ||
|
||||
name == Strings::twrap || name == Strings::rwrap)
|
||||
&& value && valuetype == TypeDesc::STRING) {
|
||||
// Special trick is needed for wrap modes because the input
|
||||
// is a string but the field we're setting is an int enum.
|
||||
OIIO::Tex::Wrap wrapmode = OIIO::Tex::decode_wrapmode (*(ustring *)value);
|
||||
void* value = &wrapmode;
|
||||
CHECK_str (wrap, int, TypeDesc::INT);
|
||||
}
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
@@ -2666,7 +2675,7 @@ DECLFOLDER(constfold_pointcloud_search)
|
||||
for (int i = 0; i < nattrs; ++i) {
|
||||
// We had stashed names, data types, and destinations earlier.
|
||||
// Retrieve them now to build a query.
|
||||
if (! names[i])
|
||||
if (names[i].empty())
|
||||
continue;
|
||||
void *const_data = NULL;
|
||||
TypeDesc const_valtype = value_types[i];
|
||||
|
||||
@@ -325,7 +325,7 @@ ShadingContext::osl_get_attribute (ShaderGlobals *sg, void *objdata,
|
||||
bool ok;
|
||||
|
||||
for (auto& f : m_failed_attribs) {
|
||||
if ((obj_name || f.objdata == objdata) &&
|
||||
if ((!obj_name.empty() || f.objdata == objdata) &&
|
||||
f.attr_name == attr_name && f.obj_name == obj_name &&
|
||||
f.attr_type == attr_type && f.array_lookup == array_lookup &&
|
||||
f.index == index && f.objdata) {
|
||||
|
||||
@@ -36,12 +36,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <OpenImageIO/dassert.h>
|
||||
#include <OpenImageIO/strutil.h>
|
||||
|
||||
#ifdef USE_EXTERNAL_PUGIXML
|
||||
# include <pugixml.hpp>
|
||||
#else
|
||||
# include <OpenImageIO/pugixml.hpp>
|
||||
#include <pugixml.hpp>
|
||||
|
||||
#ifdef USING_OIIO_PUGI
|
||||
namespace pugi = OIIO::pugi;
|
||||
#endif
|
||||
|
||||
|
||||
#include "oslexec_pvt.h"
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
@@ -49,12 +50,6 @@ OSL_NAMESPACE_ENTER
|
||||
namespace pvt { // OSL::pvt
|
||||
|
||||
|
||||
#ifndef USE_EXTERNAL_PUGIXML
|
||||
namespace pugi = OIIO::pugi;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// Helper class to manage the dictionaries.
|
||||
//
|
||||
// Shaders are written as if they parse arbitrary things from whole
|
||||
|
||||
@@ -28,13 +28,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <OpenImageIO/dassert.h>
|
||||
#include <OpenImageIO/unittest.h>
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
#include <OSL/dual.h>
|
||||
#include <OSL/dual_vec.h>
|
||||
|
||||
#include <OpenImageIO/dassert.h>
|
||||
#include <OpenImageIO/unittest.h>
|
||||
|
||||
using namespace OSL;
|
||||
|
||||
// Fix namespace problem with OIIO unit tests in older versions.
|
||||
|
||||
+35
-18
@@ -246,7 +246,7 @@ ShaderInstance::parameters (const ParamValueList ¶ms)
|
||||
|
||||
if (master()->shadingsys().relaxed_param_typecheck()) {
|
||||
// first handle cases where we actually need to modify the data (like setting a float parameter with an int)
|
||||
if ((paramtype == TypeDesc::FLOAT || paramtype.is_vec3()) && valuetype.basetype == TypeDesc::INT && valuetype.basevalues() == 1) {
|
||||
if ((paramtype == TypeDesc::FLOAT || paramtype.is_vec3()) && valuetype.basetype == TypeDesc::INT && valuetype.basevalues() == 1) {
|
||||
int val = *static_cast<const int*>(p.data());
|
||||
float conv = float(val);
|
||||
if (val != int(conv))
|
||||
@@ -313,13 +313,14 @@ ShaderInstance::parameters (const ParamValueList ¶ms)
|
||||
// data offsets to each parameter, we didn't know the length
|
||||
// needed to allocate this param in its proper spot.
|
||||
ASSERT (valuetype.arraylen > 0);
|
||||
int nelements = valuetype.arraylen * valuetype.aggregate;
|
||||
// Store the actual length in the shader instance parameter
|
||||
// override info.
|
||||
so->arraylen (valuetype.arraylen);
|
||||
// override info. Compute the length this way to account for relaxed
|
||||
// parameter checking (for example passing an array of floats to an array of colors)
|
||||
so->arraylen (nelements / paramtype.aggregate);
|
||||
// Allocate space for the new param size at the end of its
|
||||
// usual parameter area, and set the new dataoffset to that
|
||||
// position.
|
||||
int nelements = valuetype.arraylen * valuetype.aggregate;
|
||||
if (paramtype.basetype == TypeDesc::FLOAT) {
|
||||
so->dataoffset((int) m_fparams.size());
|
||||
expand (m_fparams, nelements);
|
||||
@@ -532,6 +533,27 @@ ShaderInstance::copy_code_from_master (ShaderGroup &group)
|
||||
|
||||
|
||||
|
||||
std::string
|
||||
ConnectedParam::str (const ShaderInstance *inst)
|
||||
{
|
||||
const Symbol *s = inst->symbol(param);
|
||||
return Strutil::format ("%s%s%s (%s)", s->name(),
|
||||
arrayindex >= 0 ? Strutil::format("[%d]", arrayindex) : std::string(),
|
||||
channel >= 0 ? Strutil::format("[%d]", channel) : std::string(),
|
||||
type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string
|
||||
Connection::str (const ShaderGroup &group, const ShaderInstance *dstinst)
|
||||
{
|
||||
return Strutil::format ("%s -> %s", src.str (group[srclayer]),
|
||||
dst.str (dstinst));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Are the two vectors equivalent(a[i],b[i]) in each of their members?
|
||||
template<class T>
|
||||
inline bool
|
||||
@@ -709,28 +731,23 @@ ShaderInstance::mergeable (const ShaderInstance &b, const ShaderGroup &g) const
|
||||
|
||||
|
||||
ShaderGroup::ShaderGroup (string_view name)
|
||||
: m_optimized(0), m_does_nothing(false),
|
||||
m_llvm_groupdata_size(0), m_num_entry_layers(0),
|
||||
m_llvm_compiled_version(NULL),
|
||||
m_name(name), m_exec_repeat(1), m_raytype_queries(-1), m_raytypes_on(0), m_raytypes_off(0)
|
||||
{
|
||||
m_executions = 0;
|
||||
m_stat_total_shading_time_ticks = 0;
|
||||
m_id = ++(*(atomic_int *)&next_id);
|
||||
if (name.size()) {
|
||||
m_name = name;
|
||||
} else {
|
||||
// No name -- make one up using the unique
|
||||
m_name = ustring::format ("unnamed_group_%d", m_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
ShaderGroup::ShaderGroup (const ShaderGroup &g, string_view name)
|
||||
: m_optimized(0), m_does_nothing(false),
|
||||
m_llvm_groupdata_size(0), m_num_entry_layers(g.m_num_entry_layers),
|
||||
m_llvm_compiled_version(NULL),
|
||||
m_layers(g.m_layers),
|
||||
m_name(name), m_exec_repeat(1), m_raytype_queries(-1), m_raytypes_on(0), m_raytypes_off(0)
|
||||
: ShaderGroup(name) // delegate most of the work
|
||||
{
|
||||
m_executions = 0;
|
||||
m_stat_total_shading_time_ticks = 0;
|
||||
m_id = ++(*(atomic_int *)&next_id);
|
||||
m_num_entry_layers = g.m_num_entry_layers;
|
||||
m_layers = g.m_layers;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+104
-28
@@ -157,10 +157,8 @@ BackendLLVM::llvm_call_layer (int layer, bool unconditional)
|
||||
// insert point is now then_block
|
||||
}
|
||||
|
||||
std::string name = Strutil::format ("%s_%d", parent->layername().c_str(),
|
||||
parent->id());
|
||||
// Mark the call as a fast call
|
||||
llvm::Value *funccall = ll.call_function (name.c_str(), args, 2);
|
||||
llvm::Value *funccall = ll.call_function (layer_function_name(group(), *parent).c_str(), args, 2);
|
||||
if (!parent->entry_layer())
|
||||
ll.mark_fast_func_call (funccall);
|
||||
|
||||
@@ -323,6 +321,8 @@ LLVMGEN (llvm_gen_printf)
|
||||
std::string ourformat (oldfmt, format); // straddle the format
|
||||
// Doctor it to fix mismatches between format and data
|
||||
Symbol& sym (*rop.opargsym (op, arg));
|
||||
ASSERT (! sym.typespec().is_structure_based());
|
||||
|
||||
TypeDesc simpletype (sym.typespec().simpletype());
|
||||
int num_elements = simpletype.numelements();
|
||||
int num_components = simpletype.aggregate;
|
||||
@@ -358,12 +358,27 @@ LLVMGEN (llvm_gen_printf)
|
||||
s += " ";
|
||||
s += ourformat;
|
||||
|
||||
llvm::Value* loaded = rop.llvm_load_value (sym, 0, arrind, c);
|
||||
llvm::Value* loaded = nullptr;
|
||||
if (rop.use_optix() && simpletype.basetype == TypeDesc::STRING) {
|
||||
// TODO: make this work with arrind
|
||||
// In the OptiX case, we use the device-side string.
|
||||
loaded = rop.llvm_load_device_string (sym);
|
||||
}
|
||||
else {
|
||||
loaded = rop.llvm_load_value (sym, 0, arrind, c);
|
||||
}
|
||||
|
||||
if (simpletype.basetype == TypeDesc::FLOAT) {
|
||||
// C varargs convention upconverts float->double.
|
||||
loaded = rop.ll.op_float_to_double(loaded);
|
||||
}
|
||||
|
||||
if (simpletype.basetype == TypeDesc::INT && rop.use_optix()) {
|
||||
// The printf supported by OptiX expects 8-byte arguments,
|
||||
// so promote int to long long
|
||||
loaded = rop.ll.op_int_to_longlong(loaded);
|
||||
}
|
||||
|
||||
call_args.push_back (loaded);
|
||||
}
|
||||
}
|
||||
@@ -374,6 +389,20 @@ LLVMGEN (llvm_gen_printf)
|
||||
}
|
||||
}
|
||||
|
||||
if (rop.use_optix() && arg > (format_arg + 2)) {
|
||||
std::cerr << "WARNING: "
|
||||
<< "OptiX only supports 0 or 1 printf arguments at this time. "
|
||||
<< "Ignoring printf call in " << op.sourcefile() << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
// In OptiX, printf currently supports 0 or 1 arguments, and the signature
|
||||
// requires 1 argument, so push a null pointer onto the call args if there
|
||||
// is no argument.
|
||||
if (rop.use_optix() && arg == format_arg + 1) {
|
||||
call_args.push_back(rop.ll.void_ptr_null());
|
||||
}
|
||||
|
||||
// Some ops prepend things
|
||||
if (op.opname() == op_error || op.opname() == op_warning) {
|
||||
std::string prefix = Strutil::format ("Shader %s [%s]: ",
|
||||
@@ -383,7 +412,13 @@ LLVMGEN (llvm_gen_printf)
|
||||
}
|
||||
|
||||
// Now go back and put the new format string in its place
|
||||
call_args[new_format_slot] = rop.ll.constant (s.c_str());
|
||||
if (! rop.use_optix()) {
|
||||
call_args[new_format_slot] = rop.ll.constant (s.c_str());
|
||||
}
|
||||
else {
|
||||
// In the OptiX case, we use the pointer to the device-side string
|
||||
call_args[new_format_slot] = rop.llvm_load_device_string (format_sym);
|
||||
}
|
||||
|
||||
// Construct the function name and call it.
|
||||
std::string opname = std::string("osl_") + op.opname().string();
|
||||
@@ -1336,9 +1371,24 @@ LLVMGEN (llvm_gen_aassign)
|
||||
}
|
||||
|
||||
int num_components = Result.typespec().simpletype().aggregate;
|
||||
|
||||
// Allow float <=> int casting
|
||||
TypeDesc cast;
|
||||
if (num_components == 1 && !Result.typespec().is_closure() && !Src.typespec().is_closure() &&
|
||||
(Result.typespec().is_int_based() || Result.typespec().is_float_based()) &&
|
||||
(Src.typespec().is_int_based() || Src.typespec().is_float_based())) {
|
||||
cast = Result.typespec().simpletype();
|
||||
cast.arraylen = 0;
|
||||
} else {
|
||||
// Try to warn before llvm_fatal_error is called which provides little
|
||||
// context as to what went wrong.
|
||||
ASSERT (Result.typespec().simpletype().basetype ==
|
||||
Src.typespec().simpletype().basetype);
|
||||
}
|
||||
|
||||
for (int d = 0; d <= 2; ++d) {
|
||||
for (int c = 0; c < num_components; ++c) {
|
||||
llvm::Value *val = rop.loadLLVMValue (Src, c, d);
|
||||
llvm::Value *val = rop.loadLLVMValue (Src, c, d, cast);
|
||||
rop.llvm_store_value (val, Result, d, index, c);
|
||||
}
|
||||
if (! Result.has_derivs())
|
||||
@@ -1720,6 +1770,27 @@ LLVMGEN (llvm_gen_compare_op)
|
||||
llvm::Value* final_result = 0;
|
||||
ustring opname = op.opname();
|
||||
|
||||
if (rop.use_optix() && A.typespec().is_string()) {
|
||||
ASSERT (B.typespec().is_string() && "Only string-to-string comparison is supported");
|
||||
|
||||
llvm::Value* a = rop.llvm_load_device_string (A);
|
||||
llvm::Value* b = rop.llvm_load_device_string (B);
|
||||
|
||||
if (opname == op_eq) {
|
||||
final_result = rop.ll.op_eq (a, b);
|
||||
} else if (opname == op_neq) {
|
||||
final_result = rop.ll.op_ne (a, b);
|
||||
} else {
|
||||
// Don't know how to handle this.
|
||||
ASSERT (0 && "OptiX only supports equality testing for strings");
|
||||
}
|
||||
ASSERT (final_result);
|
||||
|
||||
final_result = rop.ll.op_bool_to_int (final_result);
|
||||
rop.storeLLVMValue (final_result, Result, 0, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_components; i++) {
|
||||
// Get A&B component i -- note that these correctly handle mixed
|
||||
// scalar/triple comparisons as well as int->float casts as needed.
|
||||
@@ -2093,7 +2164,7 @@ llvm_gen_texture_options (BackendLLVM &rop, int opnum,
|
||||
ustring name = *(ustring *)Name.data();
|
||||
++a; // advance to next argument
|
||||
|
||||
if (! name) // skip empty string param name
|
||||
if (name.empty()) // skip empty string param name
|
||||
continue;
|
||||
|
||||
Symbol &Val (*rop.opargsym(op,a));
|
||||
@@ -2202,7 +2273,7 @@ llvm_gen_texture_options (BackendLLVM &rop, int opnum,
|
||||
if (name == Strings::subimage && valtype == TypeDesc::STRING) {
|
||||
if (Val.is_constant()) {
|
||||
ustring v = *(ustring *)Val.data();
|
||||
if (! v && ! subimage_set) {
|
||||
if (v.empty() && ! subimage_set) {
|
||||
continue; // Ignore nulls unless they are overrides
|
||||
}
|
||||
}
|
||||
@@ -2390,32 +2461,18 @@ LLVMGEN (llvm_gen_texture3d)
|
||||
if (user_derivs) {
|
||||
args.push_back (rop.llvm_void_ptr (*rop.opargsym (op, 3)));
|
||||
args.push_back (rop.llvm_void_ptr (*rop.opargsym (op, 4)));
|
||||
args.push_back (rop.llvm_void_ptr (*rop.opargsym (op, 5)));
|
||||
} else {
|
||||
// Auto derivs of P
|
||||
args.push_back (rop.llvm_void_ptr (P, 1));
|
||||
args.push_back (rop.llvm_void_ptr (P, 2));
|
||||
// dPdz is correct for input P, zero for all else
|
||||
if (&P == rop.inst()->symbol(rop.inst()->Psym())) {
|
||||
args.push_back (rop.llvm_void_ptr (P, 3));
|
||||
} else {
|
||||
// zero for dPdz, for now
|
||||
llvm::Value *fzero = rop.ll.constant (0.0f);
|
||||
llvm::Value *vzero = rop.ll.op_alloca (rop.ll.type_triple());
|
||||
for (int i = 0; i < 3; ++i)
|
||||
rop.ll.op_store (fzero, rop.ll.GEP (vzero, 0, i));
|
||||
args.push_back (rop.ll.void_ptr(vzero));
|
||||
}
|
||||
}
|
||||
args.push_back (rop.ll.constant (nchans));
|
||||
args.push_back (rop.ll.void_ptr (rop.llvm_void_ptr (Result, 0)));
|
||||
args.push_back (rop.ll.void_ptr (rop.llvm_void_ptr (Result, 1)));
|
||||
args.push_back (rop.ll.void_ptr (rop.llvm_void_ptr (Result, 2)));
|
||||
args.push_back (rop.ll.void_ptr_null()); // no dresultdz for now
|
||||
args.push_back (rop.ll.void_ptr (alpha ? alpha : rop.ll.void_ptr_null()));
|
||||
args.push_back (rop.ll.void_ptr (dalphadx ? dalphadx : rop.ll.void_ptr_null()));
|
||||
args.push_back (rop.ll.void_ptr (dalphady ? dalphady : rop.ll.void_ptr_null()));
|
||||
args.push_back (rop.ll.void_ptr_null()); // No dalphadz for now
|
||||
args.push_back (rop.ll.void_ptr (errormessage ? errormessage : rop.ll.void_ptr_null()));
|
||||
rop.ll.call_function ("osl_texture3d", &args[0], (int)args.size());
|
||||
rop.generated_texture_call (texture_handle != NULL);
|
||||
@@ -2591,6 +2648,12 @@ llvm_gen_noise_options (BackendLLVM &rop, int opnum,
|
||||
{
|
||||
llvm::Value* opt = rop.ll.call_function ("osl_get_noise_options",
|
||||
rop.sg_void_ptr());
|
||||
|
||||
// TODO: implement noise options in OptiX
|
||||
if (rop.use_optix()) {
|
||||
return opt;
|
||||
}
|
||||
|
||||
Opcode &op (rop.inst()->ops()[opnum]);
|
||||
for (int a = first_optional_arg; a < op.nargs(); ++a) {
|
||||
Symbol &Name (*rop.opargsym(op,a));
|
||||
@@ -2603,7 +2666,7 @@ llvm_gen_noise_options (BackendLLVM &rop, int opnum,
|
||||
Symbol &Val (*rop.opargsym(op,a));
|
||||
TypeDesc valtype = Val.typespec().simpletype ();
|
||||
|
||||
if (! name) // skip empty string param name
|
||||
if (name.empty()) // skip empty string param name
|
||||
continue;
|
||||
|
||||
if (name == Strings::anisotropic && Val.typespec().is_int()) {
|
||||
@@ -2694,7 +2757,7 @@ LLVMGEN (llvm_gen_noise)
|
||||
derivs &= Result.has_derivs(); // ignore derivs if result doesn't need
|
||||
|
||||
bool pass_name = false, pass_sg = false, pass_options = false;
|
||||
if (! name) {
|
||||
if (name.empty()) {
|
||||
// name is not a constant
|
||||
name = periodic ? Strings::genericpnoise : Strings::genericnoise;
|
||||
pass_name = true;
|
||||
@@ -2758,8 +2821,14 @@ LLVMGEN (llvm_gen_noise)
|
||||
|
||||
std::string funcname = "osl_" + name.string() + "_" + arg_typecode(&Result,derivs);
|
||||
std::vector<llvm::Value *> args;
|
||||
if (pass_name)
|
||||
args.push_back (rop.llvm_load_value(*Name));
|
||||
if (pass_name) {
|
||||
if (! rop.use_optix()) {
|
||||
args.push_back (rop.llvm_load_value(*Name));
|
||||
}
|
||||
else {
|
||||
args.push_back (rop.llvm_load_device_string (*Name));
|
||||
}
|
||||
}
|
||||
llvm::Value *tmpresult = NULL;
|
||||
// triple return, or float return with derivs, passes result pointer
|
||||
if (outdim == 3 || derivs) {
|
||||
@@ -3260,8 +3329,15 @@ LLVMGEN (llvm_gen_closure)
|
||||
DASSERT(p.offset + p.field_size <= clentry->struct_size);
|
||||
Symbol &sym = *rop.opargsym (op, carg + 2 + weighted);
|
||||
TypeDesc t = sym.typespec().simpletype();
|
||||
if (!sym.typespec().is_closure_array() && !sym.typespec().is_structure()
|
||||
&& equivalent(t,p.type)) {
|
||||
|
||||
if (rop.use_optix() && sym.typespec().is_string()) {
|
||||
llvm::Value* dst = rop.ll.offset_ptr (mem_void_ptr, p.offset);
|
||||
llvm::Value* src = rop.llvm_load_device_string (sym);
|
||||
rop.ll.op_memcpy (dst, src, (int)p.type.size(),
|
||||
4 /* use 4 byte alignment for now */);
|
||||
}
|
||||
else if (!sym.typespec().is_closure_array() && !sym.typespec().is_structure()
|
||||
&& equivalent(t,p.type)) {
|
||||
llvm::Value* dst = rop.ll.offset_ptr (mem_void_ptr, p.offset);
|
||||
llvm::Value* src = rop.llvm_void_ptr (sym);
|
||||
rop.ll.op_memcpy (dst, src, (int)p.type.size(),
|
||||
|
||||
@@ -27,7 +27,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <bitset>
|
||||
|
||||
#include <OpenImageIO/timer.h>
|
||||
#include <OpenImageIO/sysutil.h>
|
||||
@@ -111,6 +114,9 @@ Schematically, we want to create code that resembles the following:
|
||||
extern int osl_llvm_compiled_ops_size;
|
||||
extern char osl_llvm_compiled_ops_block[];
|
||||
|
||||
extern int osl_llvm_compiled_ops_cuda_size;
|
||||
extern char osl_llvm_compiled_ops_cuda_block[];
|
||||
|
||||
using namespace OSL::pvt;
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
@@ -267,7 +273,13 @@ BackendLLVM::llvm_type_groupdata ()
|
||||
++order;
|
||||
for (int i = 0; i < nuserdata; ++i) {
|
||||
TypeDesc type = types[i];
|
||||
int n = type.numelements() * 3; // always make deriv room
|
||||
// NB: Userdata derivs are not currently supported in OptiX, since
|
||||
// making room for them in the GroupData struct can result in a
|
||||
// large per-thread memory allocation, which could negatively
|
||||
// impact performance.
|
||||
int n = (! use_optix())
|
||||
? type.numelements() * 3 // make room for derivs by default
|
||||
: type.numelements();
|
||||
type.arraylen = n;
|
||||
fields.push_back (llvm_type (type));
|
||||
// Alignment
|
||||
@@ -364,12 +376,12 @@ BackendLLVM::llvm_type_closure_component_ptr ()
|
||||
|
||||
|
||||
void
|
||||
BackendLLVM::llvm_assign_initial_value (const Symbol& sym)
|
||||
BackendLLVM::llvm_assign_initial_value (const Symbol& sym, bool force)
|
||||
{
|
||||
// Don't write over connections! Connection values are written into
|
||||
// our layer when the earlier layer is run, as part of its code. So
|
||||
// we just don't need to initialize it here at all.
|
||||
if (sym.valuesource() == Symbol::ConnectedVal &&
|
||||
if (!force && sym.valuesource() == Symbol::ConnectedVal &&
|
||||
!sym.typespec().is_closure_based())
|
||||
return;
|
||||
if (sym.typespec().is_closure_based() && sym.symtype() == SymTypeGlobal)
|
||||
@@ -440,9 +452,24 @@ BackendLLVM::llvm_assign_initial_value (const Symbol& sym)
|
||||
}
|
||||
}
|
||||
ASSERT (userdata_index >= 0);
|
||||
|
||||
std::vector<llvm::Value*> args;
|
||||
args.push_back (sg_void_ptr());
|
||||
args.push_back (ll.constant (symname));
|
||||
|
||||
llvm::Value* name_arg = NULL;
|
||||
|
||||
if (use_optix()) {
|
||||
// In the OptiX case, we need to get the pointer to the string
|
||||
// constant for the symbol name.
|
||||
ustring arg_name = ustring::format ("$symname_%s_%d", symname, sym.layer());
|
||||
Symbol symname_const (arg_name, TypeDesc::TypeString, SymTypeConst);
|
||||
symname_const.data (&symname);
|
||||
name_arg = llvm_load_device_string (symname_const);
|
||||
} else {
|
||||
name_arg = ll.constant (symname);
|
||||
}
|
||||
|
||||
args.push_back (name_arg);
|
||||
args.push_back (ll.constant (type));
|
||||
args.push_back (ll.constant ((int) group().m_userdata_derivs[userdata_index]));
|
||||
args.push_back (groupdata_field_ptr (2 + userdata_index)); // userdata data ptr
|
||||
@@ -458,11 +485,11 @@ BackendLLVM::llvm_assign_initial_value (const Symbol& sym)
|
||||
// check for NaN/Inf for float-based types
|
||||
int ncomps = type.numelements() * type.aggregate;
|
||||
llvm::Value *args[] = { ll.constant(ncomps), llvm_void_ptr(sym),
|
||||
ll.constant((int)sym.has_derivs()), sg_void_ptr(),
|
||||
ll.constant(ustring(inst()->shadername())),
|
||||
ll.constant(0), ll.constant(sym.name()),
|
||||
ll.constant(0), ll.constant(ncomps),
|
||||
ll.constant("<get_userdata>")
|
||||
ll.constant((int)sym.has_derivs()), sg_void_ptr(),
|
||||
ll.constant(ustring(inst()->shadername())),
|
||||
ll.constant(0), ll.constant(sym.name()),
|
||||
ll.constant(0), ll.constant(ncomps),
|
||||
ll.constant("<get_userdata>")
|
||||
};
|
||||
ll.call_function ("osl_naninf_check", args, 10);
|
||||
}
|
||||
@@ -478,13 +505,36 @@ BackendLLVM::llvm_assign_initial_value (const Symbol& sym)
|
||||
if (sym.has_init_ops() && sym.valuesource() == Symbol::DefaultVal) {
|
||||
// Handle init ops.
|
||||
build_llvm_code (sym.initbegin(), sym.initend());
|
||||
} else if (! sym.lockgeom() && ! sym.typespec().is_closure()) {
|
||||
} else if (! sym.lockgeom() && ! sym.typespec().is_closure() &&
|
||||
! use_optix()) {
|
||||
// geometrically-varying param; memcpy its default value
|
||||
TypeDesc t = sym.typespec().simpletype();
|
||||
ll.op_memcpy (llvm_void_ptr (sym), ll.constant_ptr (sym.data()),
|
||||
t.size(), t.basesize() /*align*/);
|
||||
if (sym.has_derivs())
|
||||
llvm_zero_derivs (sym);
|
||||
} else if (use_optix() && ! sym.typespec().is_string()) {
|
||||
// If the call to osl_bind_interpolated_param returns 0, the default
|
||||
// value needs to be loaded from a corresponding OptiX variable, which
|
||||
// we are creating here.
|
||||
ustring var_name = ustring::format ("%s_%s_%s_%d", sym.name(),
|
||||
inst()->layername(), group().name(), group().id());
|
||||
|
||||
// TODO: Make sure this works with string variables
|
||||
llvm::Value* ud_var = createOptixVariable (var_name.string(),
|
||||
sym.typespec().simpletype().c_str(),
|
||||
sym.size(),
|
||||
sym.data());
|
||||
|
||||
// memcpy the value from the OptiX variable into the GroupData struct
|
||||
llvm::Value* src = ll.ptr_cast (ll.GEP (ud_var, 0), ll.type_void_ptr());
|
||||
llvm::Value* dst = llvm_void_ptr (sym);
|
||||
|
||||
TypeDesc t = sym.typespec().simpletype();
|
||||
ll.op_memcpy (dst, src, t.size(), t.basesize());
|
||||
} else if (use_optix() && sym.typespec().is_string()) {
|
||||
llvm::Value* src = llvm_load_device_string (sym);
|
||||
ll.op_memcpy (llvm_void_ptr (sym), src, 8, 4);
|
||||
} else {
|
||||
// Use default value
|
||||
int num_components = sym.typespec().simpletype().aggregate;
|
||||
@@ -712,7 +762,9 @@ BackendLLVM::build_llvm_init ()
|
||||
ll.op_memset (ll.void_ptr(layer_run_ref(0)), 0, sz, 4 /*align*/);
|
||||
}
|
||||
int num_userdata = (int) group().m_userdata_names.size();
|
||||
if (num_userdata) {
|
||||
if (num_userdata && ! use_optix()) {
|
||||
// NB: we don't need these flags in the OptiX case because userdata is
|
||||
// accessed through rtVariables, which are guaranteed to be initialized
|
||||
int sz = (num_userdata + 3) & (~3); // round up to 32 bits
|
||||
ll.op_memset (ll.void_ptr(userdata_initialized_ref(0)), 0, sz, 4 /*align*/);
|
||||
}
|
||||
@@ -761,8 +813,7 @@ BackendLLVM::build_llvm_instance (bool groupentry)
|
||||
{
|
||||
// Make a layer function: void layer_func(ShaderGlobals*, GroupData*)
|
||||
// Note that the GroupData* is passed as a void*.
|
||||
std::string unique_layer_name = Strutil::format ("%s_%d", inst()->layername(), inst()->id());
|
||||
|
||||
std::string unique_layer_name = layer_function_name();
|
||||
bool is_entry_layer = group().is_entry_layer(layer());
|
||||
ll.current_function (
|
||||
ll.make_function (unique_layer_name,
|
||||
@@ -896,22 +947,66 @@ BackendLLVM::build_llvm_instance (bool groupentry)
|
||||
if (llvm_has_exit_instance_block())
|
||||
ll.op_branch (m_exit_instance_block); // also sets insert point
|
||||
|
||||
// Track all symbols who needed 'partial' initialization
|
||||
std::unordered_set<Symbol*> initedsyms;
|
||||
|
||||
// Transfer all of this layer's outputs into the downstream shader's
|
||||
// inputs.
|
||||
for (int layer = this->layer()+1; layer < group().nlayers(); ++layer) {
|
||||
ShaderInstance *child = group()[layer];
|
||||
for (int c = 0; c < child->nconnections(); ++c) {
|
||||
for (int c = 0, Nc = child->nconnections(); c < Nc; ++c) {
|
||||
const Connection &con (child->connection (c));
|
||||
if (con.srclayer == this->layer()) {
|
||||
ASSERT (con.src.arrayindex == -1 && con.src.channel == -1 &&
|
||||
con.dst.arrayindex == -1 && con.dst.channel == -1 &&
|
||||
"no support for individual element/channel connection");
|
||||
ASSERT (con.src.arrayindex == -1 && con.dst.arrayindex == -1 &&
|
||||
"no support for individual array element connections");
|
||||
// Validate unsupported connection vecSrc -> vecDst[j]
|
||||
ASSERT ((con.dst.channel == -1 ||
|
||||
con.src.type.aggregate() == TypeDesc::SCALAR ||
|
||||
con.src.channel != -1) &&
|
||||
"no support for vector -> vector[i] connections");
|
||||
|
||||
Symbol *srcsym (inst()->symbol (con.src.param));
|
||||
Symbol *dstsym (child->symbol (con.dst.param));
|
||||
|
||||
// Check remining connections to see if any channels of this
|
||||
// aggregate need to be initialize.
|
||||
if (con.dst.channel != -1 && initedsyms.count(dstsym) == 0) {
|
||||
initedsyms.insert(dstsym);
|
||||
std::bitset<32> inited(0); // Only need to be 16 (matrix4)
|
||||
assert(dstsym->typespec().aggregate() <= inited.size());
|
||||
unsigned ninit = dstsym->typespec().aggregate() - 1;
|
||||
for (int rc = c+1; rc < Nc && ninit; ++rc) {
|
||||
const Connection &next (child->connection (rc));
|
||||
if (next.srclayer == this->layer()) {
|
||||
// Allow redundant/overwriting connections, i.e:
|
||||
// 1. connect layer.value[i] connect layer.value[j]
|
||||
// 2. connect layer.value connect layer.value
|
||||
if (child->symbol (next.dst.param) == dstsym) {
|
||||
if (next.dst.channel != -1) {
|
||||
assert(next.dst.channel < (int)inited.size());
|
||||
if (!inited[next.dst.channel]) {
|
||||
inited[next.dst.channel] = true;
|
||||
--ninit;
|
||||
}
|
||||
} else
|
||||
ninit = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ninit) {
|
||||
// FIXME: Init only components that are not connected
|
||||
llvm_assign_initial_value (*dstsym, true);
|
||||
}
|
||||
}
|
||||
|
||||
// llvm_run_connected_layers tracks layers that have been run,
|
||||
// so no need to do it here as well
|
||||
llvm_run_connected_layers (*srcsym, con.src.param);
|
||||
|
||||
// FIXME -- I'm not sure I understand this. Isn't this
|
||||
// unnecessary if we wrote to the parameter ourself?
|
||||
llvm_assign_impl (*dstsym, *srcsym);
|
||||
llvm_assign_impl (*dstsym, *srcsym, -1,
|
||||
con.src.channel, con.dst.channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -947,7 +1042,10 @@ BackendLLVM::initialize_llvm_group ()
|
||||
m_llvm_type_closure_component = NULL;
|
||||
|
||||
initialize_llvm_helper_function_map();
|
||||
ll.InstallLazyFunctionCreator (helper_function_lookup);
|
||||
|
||||
// Skipping this in the non-JIT OptiX case suppresses an LLVM warning
|
||||
if (! use_optix())
|
||||
ll.InstallLazyFunctionCreator (helper_function_lookup);
|
||||
|
||||
for (HelperFuncMap::iterator i = llvm_helper_function_map.begin(),
|
||||
e = llvm_helper_function_map.end(); i != e; ++i) {
|
||||
@@ -971,7 +1069,10 @@ BackendLLVM::initialize_llvm_group ()
|
||||
types += advance;
|
||||
}
|
||||
llvm::Function *f = ll.make_function (funcname, false, llvm_type(rettype), params, varargs);
|
||||
ll.add_function_mapping (f, (void *)i->second.function);
|
||||
|
||||
// Skipping this in the non-JIT OptiX case suppresses an LLVM warning
|
||||
if (! use_optix())
|
||||
ll.add_function_mapping (f, (void *)i->second.function);
|
||||
}
|
||||
|
||||
// Needed for closure setup
|
||||
@@ -1018,16 +1119,27 @@ BackendLLVM::run ()
|
||||
#ifdef OSL_LLVM_NO_BITCODE
|
||||
ll.module (ll.new_module ("llvm_ops"));
|
||||
#else
|
||||
ll.module (ll.module_from_bitcode (osl_llvm_compiled_ops_block,
|
||||
osl_llvm_compiled_ops_size,
|
||||
"llvm_ops", &err));
|
||||
if (! use_optix()) {
|
||||
ll.module (ll.module_from_bitcode (osl_llvm_compiled_ops_block,
|
||||
osl_llvm_compiled_ops_size,
|
||||
"llvm_ops", &err));
|
||||
} else {
|
||||
#ifdef OSL_LLVM_CUDA_BITCODE
|
||||
ll.module (ll.module_from_bitcode (osl_llvm_compiled_ops_cuda_block,
|
||||
osl_llvm_compiled_ops_cuda_size,
|
||||
"llvm_ops", &err));
|
||||
#else
|
||||
ASSERT (0 && "Must generate LLVM CUDA bitcode for OptiX");
|
||||
#endif
|
||||
}
|
||||
if (err.length())
|
||||
shadingcontext()->error ("ParseBitcodeFile returned '%s'\n", err.c_str());
|
||||
ASSERT (ll.module());
|
||||
#endif
|
||||
|
||||
// Create the ExecutionEngine
|
||||
if (! ll.make_jit_execengine (&err)) {
|
||||
// Create the ExecutionEngine. We don't create an ExecutionEngine in the
|
||||
// OptiX case, because we are using the NVPTX backend and not MCJIT
|
||||
if (! use_optix() && ! ll.make_jit_execengine (&err)) {
|
||||
shadingcontext()->error ("Failed to create engine: %s\n", err.c_str());
|
||||
ASSERT (0);
|
||||
return;
|
||||
@@ -1103,6 +1215,22 @@ BackendLLVM::run ()
|
||||
}
|
||||
ll.internalize_module_functions ("osl_", external_function_names, entry_function_names);
|
||||
|
||||
// Debug code to dump the pre-optimized bitcode to a file
|
||||
if (llvm_debug() >= 2 || shadingsys().llvm_output_bitcode()) {
|
||||
// Make a safe group name that doesn't have "/" in it! Also beware
|
||||
// filename length limits.
|
||||
std::string safegroup = Strutil::replace (group().name(), "/", ".", true);
|
||||
if (safegroup.size() > 235)
|
||||
safegroup = Strutil::format ("TRUNC_%s_%d", safegroup.substr(safegroup.size()-235), group().id());
|
||||
std::string name = Strutil::format ("%s.ll", safegroup);
|
||||
std::ofstream out (name, std::ios_base::out | std::ios_base::trunc);
|
||||
if (out.good()) {
|
||||
out << ll.bitcode_string (ll.module());
|
||||
} else {
|
||||
shadingcontext()->error ("Could not write to '%s'", name);
|
||||
}
|
||||
}
|
||||
|
||||
// Optimize the LLVM IR unless it's a do-nothing group.
|
||||
if (! group().does_nothing())
|
||||
ll.do_optimize();
|
||||
@@ -1116,25 +1244,53 @@ BackendLLVM::run ()
|
||||
std::cout.flush();
|
||||
}
|
||||
|
||||
// Debug code to dump the resulting bitcode to a file
|
||||
if (llvm_debug() >= 2) {
|
||||
std::string name = Strutil::format ("%s_%d.bc", inst()->layername(),
|
||||
inst()->id());
|
||||
ll.write_bitcode_file (name.c_str());
|
||||
// Debug code to dump the post-optimized bitcode to a file
|
||||
if (llvm_debug() >= 2 || shadingsys().llvm_output_bitcode()) {
|
||||
// Make a safe group name that doesn't have "/" in it! Also beware
|
||||
// filename length limits.
|
||||
std::string safegroup = Strutil::replace (group().name(), "/", ".", true);
|
||||
if (safegroup.size() > 235)
|
||||
safegroup = Strutil::format ("TRUNC_%s_%d", safegroup.substr(safegroup.size()-235), group().id());
|
||||
std::string name = Strutil::format ("%s_opt.ll", safegroup);
|
||||
std::ofstream out (name, std::ios_base::out | std::ios_base::trunc);
|
||||
if (out.good()) {
|
||||
out << ll.bitcode_string (ll.module());
|
||||
} else {
|
||||
shadingcontext()->error ("Could not write to '%s'", name);
|
||||
}
|
||||
}
|
||||
|
||||
// Force the JIT to happen now and retrieve the JITed function pointers
|
||||
// for the initialization and all public entry points.
|
||||
group().llvm_compiled_init ((RunLLVMGroupFunc) ll.getPointerToFunction(init_func));
|
||||
for (int layer = 0; layer < nlayers; ++layer) {
|
||||
llvm::Function* f = funcs[layer];
|
||||
if (f && group().is_entry_layer (layer))
|
||||
group().llvm_compiled_layer (layer, (RunLLVMGroupFunc) ll.getPointerToFunction(f));
|
||||
if (use_optix()) {
|
||||
// Create an llvm::Module from the renderer-supplied library bitcode
|
||||
std::vector<char>& bitcode = shadingsys().m_lib_bitcode;
|
||||
ASSERT (bitcode.size() && "Library bitcode is empty");
|
||||
|
||||
// TODO: Is it really necessary to build this Module for every ShaderGroup
|
||||
llvm::Module* lib_module =
|
||||
ll.module_from_bitcode (static_cast<const char*>(bitcode.data()),
|
||||
bitcode.size(), "cuda_lib");
|
||||
|
||||
std::string name = Strutil::format ("%s_%d", group().name(), group().id());
|
||||
ll.ptx_compile_group (lib_module, name, group().m_llvm_ptx_compiled_version);
|
||||
|
||||
if (group().m_llvm_ptx_compiled_version.empty()) {
|
||||
ASSERT (0 && "Unable to generate PTX");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Force the JIT to happen now and retrieve the JITed function pointers
|
||||
// for the initialization and all public entry points.
|
||||
group().llvm_compiled_init ((RunLLVMGroupFunc) ll.getPointerToFunction(init_func));
|
||||
for (int layer = 0; layer < nlayers; ++layer) {
|
||||
llvm::Function* f = funcs[layer];
|
||||
if (f && group().is_entry_layer (layer))
|
||||
group().llvm_compiled_layer (layer, (RunLLVMGroupFunc) ll.getPointerToFunction(f));
|
||||
}
|
||||
if (group().num_entry_layers())
|
||||
group().llvm_compiled_version (NULL);
|
||||
else
|
||||
group().llvm_compiled_version (group().llvm_compiled_layer(nlayers-1));
|
||||
}
|
||||
if (group().num_entry_layers())
|
||||
group().llvm_compiled_version (NULL);
|
||||
else
|
||||
group().llvm_compiled_version (group().llvm_compiled_layer(nlayers-1));
|
||||
|
||||
// Remove the IR for the group layer functions, we've already JITed it
|
||||
// and will never need the IR again. This saves memory, and also saves
|
||||
|
||||
@@ -147,7 +147,11 @@ void * __dso_handle = 0; // necessary to avoid linkage issues in bitcode
|
||||
|
||||
|
||||
#ifndef OSL_SHADEOP
|
||||
#define OSL_SHADEOP extern "C" OSL_LLVM_EXPORT
|
||||
# ifdef __CUDACC__
|
||||
# define OSL_SHADEOP extern "C" __device__ OSL_LLVM_EXPORT
|
||||
# else
|
||||
# define OSL_SHADEOP extern "C" OSL_LLVM_EXPORT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -449,8 +453,8 @@ MAKE_UNARY_PERCOMPONENT_OP (exp2 , OIIO::fast_exp2 , fast_exp2)
|
||||
MAKE_UNARY_PERCOMPONENT_OP (expm1 , OIIO::fast_expm1 , fast_expm1)
|
||||
MAKE_BINARY_PERCOMPONENT_OP (pow , OIIO::fast_safe_pow , fast_safe_pow)
|
||||
MAKE_BINARY_PERCOMPONENT_VF_OP (pow , OIIO::fast_safe_pow , fast_safe_pow)
|
||||
MAKE_UNARY_PERCOMPONENT_OP (erf , OIIO::fast_erf , erf)
|
||||
MAKE_UNARY_PERCOMPONENT_OP (erfc , OIIO::fast_erfc , erfc)
|
||||
MAKE_UNARY_PERCOMPONENT_OP (erf , OIIO::fast_erf , fast_erf)
|
||||
MAKE_UNARY_PERCOMPONENT_OP (erfc , OIIO::fast_erfc , fast_erfc)
|
||||
#else
|
||||
MAKE_UNARY_PERCOMPONENT_OP (log , OIIO::safe_log , safe_log)
|
||||
MAKE_UNARY_PERCOMPONENT_OP (log2 , OIIO::safe_log2 , safe_log2)
|
||||
@@ -463,6 +467,7 @@ MAKE_BINARY_PERCOMPONENT_VF_OP (pow , OIIO::safe_pow , safe_pow)
|
||||
MAKE_UNARY_PERCOMPONENT_OP (erf , erff , erf)
|
||||
MAKE_UNARY_PERCOMPONENT_OP (erfc , erfcf , erfc)
|
||||
#endif
|
||||
|
||||
MAKE_UNARY_PERCOMPONENT_OP (sqrt , OIIO::safe_sqrt , sqrt)
|
||||
MAKE_UNARY_PERCOMPONENT_OP (inversesqrt, OIIO::safe_inversesqrt, inversesqrt)
|
||||
|
||||
@@ -517,7 +522,7 @@ OSL_SHADEOP int osl_isfinite_if (float f) { return OIIO::isfinite (f); }
|
||||
OSL_SHADEOP int osl_abs_ii (int x) { return abs(x); }
|
||||
OSL_SHADEOP int osl_fabs_ii (int x) { return abs(x); }
|
||||
|
||||
inline Dual2<float> fabsf (const Dual2<float> &x) {
|
||||
OSL_HOSTDEVICE inline Dual2<float> fabsf (const Dual2<float> &x) {
|
||||
return x.val() >= 0 ? x : -x;
|
||||
}
|
||||
|
||||
@@ -528,11 +533,11 @@ OSL_SHADEOP int osl_safe_mod_iii (int a, int b) {
|
||||
return (b != 0) ? (a % b) : 0;
|
||||
}
|
||||
|
||||
inline float safe_fmod (float a, float b) {
|
||||
OSL_HOSTDEVICE inline float safe_fmod (float a, float b) {
|
||||
return (b != 0.0f) ? std::fmod (a,b) : 0.0f;
|
||||
}
|
||||
|
||||
inline Dual2<float> safe_fmod (const Dual2<float> &a, const Dual2<float> &b) {
|
||||
OSL_HOSTDEVICE inline Dual2<float> safe_fmod (const Dual2<float> &a, const Dual2<float> &b) {
|
||||
return Dual2<float> (safe_fmod (a.val(), b.val()), a.dx(), a.dy());
|
||||
}
|
||||
|
||||
@@ -725,7 +730,7 @@ osl_normalize_dvdv (void *result, void *a)
|
||||
|
||||
|
||||
|
||||
inline Vec3 calculatenormal(void *P_, bool flipHandedness)
|
||||
OSL_HOSTDEVICE inline Vec3 calculatenormal(void *P_, bool flipHandedness)
|
||||
{
|
||||
Dual2<Vec3> &tmpP (DVEC(P_));
|
||||
if (flipHandedness)
|
||||
@@ -750,7 +755,7 @@ OSL_SHADEOP float osl_area(void *P_)
|
||||
|
||||
|
||||
|
||||
inline float filter_width(float dx, float dy)
|
||||
OSL_HOSTDEVICE inline float filter_width(float dx, float dy)
|
||||
{
|
||||
return sqrtf(dx*dx + dy*dy);
|
||||
}
|
||||
|
||||
+241
-307
@@ -28,20 +28,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
#include <memory>
|
||||
#include <cinttypes>
|
||||
#include <OpenImageIO/thread.h>
|
||||
#include <boost/thread/tss.hpp> /* for thread_specific_ptr */
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
#include <OSL/llvm_util.h>
|
||||
|
||||
#if OSL_LLVM_VERSION < 35 || OSL_CPLUSPLUS_VERSION < 11
|
||||
#error "C++11 and LLVM >= 3.5 are required"
|
||||
#if OSL_LLVM_VERSION < 40
|
||||
#error "LLVM minimum version required for OSL is 4.0"
|
||||
#endif
|
||||
|
||||
// Use MCJIT for LLVM 3.6 and beyind, old JIT for earlier
|
||||
#define USE_MCJIT (OSL_LLVM_VERSION >= 36)
|
||||
#define USE_OLD_JIT (OSL_LLVM_VERSION < 36)
|
||||
|
||||
#include <llvm/IR/Constants.h>
|
||||
#include <llvm/IR/DerivedTypes.h>
|
||||
#include <llvm/IR/Instructions.h>
|
||||
@@ -56,56 +53,72 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <llvm/IR/LegacyPassManager.h>
|
||||
#include <llvm/Support/TargetRegistry.h>
|
||||
|
||||
#if OSL_LLVM_VERSION < 40
|
||||
# include <llvm/Bitcode/ReaderWriter.h>
|
||||
#else
|
||||
# include <llvm/Bitcode/BitcodeReader.h>
|
||||
# include <llvm/Bitcode/BitcodeWriter.h>
|
||||
#endif
|
||||
#include <llvm/Bitcode/BitcodeReader.h>
|
||||
#include <llvm/Bitcode/BitcodeWriter.h>
|
||||
#include <llvm/Support/ManagedStatic.h>
|
||||
#include <llvm/Support/MemoryBuffer.h>
|
||||
#include <llvm/ExecutionEngine/GenericValue.h>
|
||||
#if USE_MCJIT
|
||||
# include <llvm/ExecutionEngine/MCJIT.h>
|
||||
#endif
|
||||
#if USE_OLD_JIT
|
||||
# include <llvm/ExecutionEngine/JIT.h>
|
||||
# include <llvm/ExecutionEngine/JITMemoryManager.h>
|
||||
#endif
|
||||
#include <llvm/ExecutionEngine/JITEventListener.h>
|
||||
#include <llvm/ExecutionEngine/MCJIT.h>
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
#include <llvm/Support/TargetSelect.h>
|
||||
#include <llvm/Support/PrettyStackTrace.h>
|
||||
#include <llvm/IR/Verifier.h>
|
||||
#include <llvm/Target/TargetMachine.h>
|
||||
#include <llvm/Target/TargetOptions.h>
|
||||
#include <llvm/Transforms/Scalar.h>
|
||||
#include <llvm/Transforms/IPO.h>
|
||||
#include <llvm/Transforms/Utils/UnifyFunctionExitNodes.h>
|
||||
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
|
||||
#if OSL_LLVM_VERSION >= 36
|
||||
# include <llvm/ExecutionEngine/SectionMemoryManager.h>
|
||||
#endif
|
||||
#if OSL_LLVM_VERSION >= 39
|
||||
# include <llvm/Transforms/Scalar/GVN.h>
|
||||
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
|
||||
#include <llvm/Transforms/Scalar/GVN.h>
|
||||
|
||||
#if OSL_LLVM_VERSION >= 70
|
||||
#include <llvm/Transforms/Utils.h>
|
||||
#include <llvm/Transforms/InstCombine/InstCombine.h>
|
||||
#endif
|
||||
|
||||
// additional includes for PTX generation
|
||||
#include <llvm/Transforms/Utils/SymbolRewriter.h>
|
||||
#include <llvm/Transforms/Utils/Cloning.h>
|
||||
#include <llvm/Analysis/TargetTransformInfo.h>
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
namespace pvt {
|
||||
|
||||
#if USE_OLD_JIT
|
||||
typedef llvm::JITMemoryManager LLVMMemoryManager;
|
||||
#else
|
||||
typedef llvm::SectionMemoryManager LLVMMemoryManager;
|
||||
#endif
|
||||
typedef llvm::SectionMemoryManager LLVMMemoryManager;
|
||||
|
||||
#if OSL_LLVM_VERSION < 40
|
||||
typedef std::error_code LLVMErr;
|
||||
#else
|
||||
typedef llvm::Error LLVMErr;
|
||||
#endif
|
||||
typedef llvm::Error LLVMErr;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
#if OSL_LLVM_VERSION >= 60
|
||||
// NOTE: This is a COPY of something internal to LLVM, but since we destroy our LLVMMemoryManager
|
||||
// via global variables we can't rely on the LLVM copy sticking around.
|
||||
// Because of this, the variable must be declared _before_ jitmm_hold so that the object stays
|
||||
// valid until after we have destroyed all our memory managers.
|
||||
struct DefaultMMapper final : public llvm::SectionMemoryManager::MemoryMapper {
|
||||
llvm::sys::MemoryBlock
|
||||
allocateMappedMemory(llvm::SectionMemoryManager::AllocationPurpose Purpose,
|
||||
size_t NumBytes, const llvm::sys::MemoryBlock *const NearBlock,
|
||||
unsigned Flags, std::error_code &EC) override {
|
||||
return llvm::sys::Memory::allocateMappedMemory(NumBytes, NearBlock, Flags, EC);
|
||||
}
|
||||
|
||||
std::error_code protectMappedMemory(const llvm::sys::MemoryBlock &Block,
|
||||
unsigned Flags) override {
|
||||
return llvm::sys::Memory::protectMappedMemory(Block, Flags);
|
||||
}
|
||||
|
||||
std::error_code releaseMappedMemory(llvm::sys::MemoryBlock &M) override {
|
||||
return llvm::sys::Memory::releaseMappedMemory(M);
|
||||
}
|
||||
};
|
||||
static DefaultMMapper llvm_default_mapper;
|
||||
#endif
|
||||
|
||||
static OIIO::spin_mutex llvm_global_mutex;
|
||||
static bool setup_done = false;
|
||||
static boost::thread_specific_ptr<LLVM_Util::PerThreadInfo> perthread_infos;
|
||||
@@ -147,15 +160,6 @@ LLVM_Util::total_jit_memory_held ()
|
||||
{
|
||||
size_t jitmem = 0;
|
||||
OIIO::spin_lock lock (llvm_global_mutex);
|
||||
#if USE_OLD_JIT
|
||||
for (size_t i = 0; i < jitmm_hold.size(); ++i) {
|
||||
LLVMMemoryManager *mm = jitmm_hold[i].get();
|
||||
if (mm)
|
||||
jitmem += mm->GetDefaultCodeSlabSize() * mm->GetNumCodeSlabs()
|
||||
+ mm->GetDefaultDataSlabSize() * mm->GetNumDataSlabs()
|
||||
+ mm->GetDefaultStubSlabSize() * mm->GetNumStubSlabs();
|
||||
}
|
||||
#endif
|
||||
return jitmem;
|
||||
}
|
||||
|
||||
@@ -169,69 +173,12 @@ protected:
|
||||
LLVMMemoryManager *mm; // the real one
|
||||
public:
|
||||
|
||||
#if USE_OLD_JIT // llvm::JITMemoryManager
|
||||
MemoryManager(LLVMMemoryManager *realmm) : mm(realmm) { HasGOT = realmm->isManagingGOT(); }
|
||||
|
||||
virtual void setMemoryWritable() { mm->setMemoryWritable(); }
|
||||
virtual void setMemoryExecutable() { mm->setMemoryExecutable(); }
|
||||
virtual void setPoisonMemory(bool poison) { mm->setPoisonMemory(poison); }
|
||||
virtual void AllocateGOT() { ASSERT(HasGOT == false); ASSERT(HasGOT == mm->isManagingGOT()); mm->AllocateGOT(); HasGOT = true; ASSERT(HasGOT == mm->isManagingGOT()); }
|
||||
virtual uint8_t *getGOTBase() const { return mm->getGOTBase(); }
|
||||
virtual uint8_t *startFunctionBody(const llvm::Function *F,
|
||||
uintptr_t &ActualSize) {
|
||||
return mm->startFunctionBody (F, ActualSize);
|
||||
}
|
||||
virtual uint8_t *allocateStub(const llvm::GlobalValue* F, unsigned StubSize,
|
||||
unsigned Alignment) {
|
||||
return mm->allocateStub (F, StubSize, Alignment);
|
||||
}
|
||||
virtual void endFunctionBody(const llvm::Function *F,
|
||||
uint8_t *FunctionStart, uint8_t *FunctionEnd) {
|
||||
mm->endFunctionBody (F, FunctionStart, FunctionEnd);
|
||||
}
|
||||
virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
|
||||
return mm->allocateSpace (Size, Alignment);
|
||||
}
|
||||
virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
|
||||
return mm->allocateGlobal (Size, Alignment);
|
||||
}
|
||||
virtual void deallocateFunctionBody(void *Body) {
|
||||
// DON'T DEALLOCATE mm->deallocateFunctionBody (Body);
|
||||
}
|
||||
virtual bool CheckInvariants(std::string &s) {
|
||||
return mm->CheckInvariants(s);
|
||||
}
|
||||
virtual size_t GetDefaultCodeSlabSize() {
|
||||
return mm->GetDefaultCodeSlabSize();
|
||||
}
|
||||
virtual size_t GetDefaultDataSlabSize() {
|
||||
return mm->GetDefaultDataSlabSize();
|
||||
}
|
||||
virtual size_t GetDefaultStubSlabSize() {
|
||||
return mm->GetDefaultStubSlabSize();
|
||||
}
|
||||
virtual unsigned GetNumCodeSlabs() { return mm->GetNumCodeSlabs(); }
|
||||
virtual unsigned GetNumDataSlabs() { return mm->GetNumDataSlabs(); }
|
||||
virtual unsigned GetNumStubSlabs() { return mm->GetNumStubSlabs(); }
|
||||
|
||||
virtual void notifyObjectLoaded(llvm::ExecutionEngine *EE, const llvm::ObjectImage *oi) {
|
||||
mm->notifyObjectLoaded (EE, oi);
|
||||
}
|
||||
|
||||
#else // MCJITMemoryManager
|
||||
|
||||
MemoryManager(LLVMMemoryManager *realmm) : mm(realmm) {}
|
||||
|
||||
virtual void notifyObjectLoaded(llvm::ExecutionEngine *EE, const llvm::object::ObjectFile &oi) {
|
||||
mm->notifyObjectLoaded (EE, oi);
|
||||
}
|
||||
|
||||
#if OSL_LLVM_VERSION <= 37
|
||||
virtual void reserveAllocationSpace(
|
||||
uintptr_t CodeSize, uintptr_t DataSizeRO, uintptr_t DataSizeRW) {
|
||||
return mm->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW);
|
||||
}
|
||||
#else
|
||||
virtual void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
|
||||
uintptr_t RODataSize,
|
||||
uint32_t RODataAlign,
|
||||
@@ -239,7 +186,6 @@ public:
|
||||
uint32_t RWDataAlign) {
|
||||
return mm->reserveAllocationSpace(CodeSize, CodeAlign, RODataSize, RODataAlign, RWDataSize, RWDataAlign);
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual bool needsToReserveAllocationSpace() {
|
||||
return mm->needsToReserveAllocationSpace();
|
||||
@@ -248,8 +194,6 @@ public:
|
||||
virtual void invalidateInstructionCache() {
|
||||
mm->invalidateInstructionCache();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Common
|
||||
virtual ~MemoryManager() {}
|
||||
@@ -271,14 +215,16 @@ public:
|
||||
virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) {
|
||||
mm->registerEHFrames (Addr, LoadAddr, Size);
|
||||
}
|
||||
virtual void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) {
|
||||
#if OSL_LLVM_VERSION < 50
|
||||
virtual void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) {
|
||||
mm->deregisterEHFrames(Addr, LoadAddr, Size);
|
||||
#else
|
||||
// TODO: verify this is correct
|
||||
mm->deregisterEHFrames();
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
virtual void deregisterEHFrames() {
|
||||
mm->deregisterEHFrames();
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual uint64_t getSymbolAddress(const std::string &Name) {
|
||||
return mm->getSymbolAddress (Name);
|
||||
}
|
||||
@@ -289,15 +235,6 @@ public:
|
||||
|
||||
|
||||
|
||||
#if OSL_LLVM_VERSION <= 38
|
||||
class LLVM_Util::IRBuilder : public llvm::IRBuilder<true,llvm::ConstantFolder,
|
||||
llvm::IRBuilderDefaultInserter<true> > {
|
||||
typedef llvm::IRBuilder<true, llvm::ConstantFolder,
|
||||
llvm::IRBuilderDefaultInserter<true> > Base;
|
||||
public:
|
||||
IRBuilder(llvm::BasicBlock *TheBB) : Base(TheBB) {}
|
||||
};
|
||||
#else
|
||||
class LLVM_Util::IRBuilder : public llvm::IRBuilder<llvm::ConstantFolder,
|
||||
llvm::IRBuilderDefaultInserter> {
|
||||
typedef llvm::IRBuilder<llvm::ConstantFolder,
|
||||
@@ -305,7 +242,6 @@ class LLVM_Util::IRBuilder : public llvm::IRBuilder<llvm::ConstantFolder,
|
||||
public:
|
||||
IRBuilder(llvm::BasicBlock *TheBB) : Base(TheBB) {}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -327,20 +263,16 @@ LLVM_Util::LLVM_Util (int debuglevel)
|
||||
m_thread->llvm_context = new llvm::LLVMContext();
|
||||
|
||||
if (! m_thread->llvm_jitmm) {
|
||||
#if USE_OLD_JIT
|
||||
m_thread->llvm_jitmm = llvm::JITMemoryManager::CreateDefaultMemManager();
|
||||
#if OSL_LLVM_VERSION >= 60
|
||||
m_thread->llvm_jitmm = new LLVMMemoryManager(&llvm_default_mapper);
|
||||
#else
|
||||
m_thread->llvm_jitmm = new LLVMMemoryManager;
|
||||
m_thread->llvm_jitmm = new LLVMMemoryManager();
|
||||
#endif
|
||||
ASSERT (m_thread->llvm_jitmm);
|
||||
jitmm_hold.push_back (std::shared_ptr<LLVMMemoryManager>(m_thread->llvm_jitmm));
|
||||
jitmm_hold.emplace_back (m_thread->llvm_jitmm);
|
||||
}
|
||||
#if USE_OLD_JIT
|
||||
m_llvm_jitmm = new MemoryManager(m_thread->llvm_jitmm);
|
||||
#else
|
||||
// Hold the REAL manager and use it as an argument later
|
||||
m_llvm_jitmm = reinterpret_cast<MemoryManager*>(m_thread->llvm_jitmm);
|
||||
#endif
|
||||
m_llvm_jitmm = m_thread->llvm_jitmm;
|
||||
}
|
||||
|
||||
m_llvm_context = m_thread->llvm_context;
|
||||
@@ -395,31 +327,17 @@ LLVM_Util::SetupLLVM ()
|
||||
return;
|
||||
// Some global LLVM initialization for the first thread that
|
||||
// gets here.
|
||||
|
||||
#if USE_MCJIT
|
||||
LLVMInitializeNativeTarget();
|
||||
LLVMInitializeNativeDisassembler();
|
||||
LLVMInitializeNativeAsmPrinter();
|
||||
LLVMInitializeNativeAsmParser();
|
||||
llvm::InitializeAllTargets();
|
||||
llvm::InitializeAllTargetMCs();
|
||||
llvm::InitializeAllDisassemblers();
|
||||
llvm::InitializeAllAsmPrinters();
|
||||
llvm::InitializeAllAsmParsers();
|
||||
LLVMLinkInMCJIT();
|
||||
#else
|
||||
llvm::InitializeNativeTarget();
|
||||
#endif
|
||||
|
||||
if (debug()) {
|
||||
#if OSL_LLVM_VERSION <= 36
|
||||
# define OSL_TGT_DEF(t) t->
|
||||
for (llvm::TargetRegistry::iterator t = llvm::TargetRegistry::begin();
|
||||
t != llvm::TargetRegistry::end(); ++t)
|
||||
#else
|
||||
# define OSL_TGT_DEF(t) t.
|
||||
for (auto t : llvm::TargetRegistry::targets())
|
||||
#endif
|
||||
{
|
||||
std::cout << "Target: '" << OSL_TGT_DEF(t)getName() << "' "
|
||||
<< OSL_TGT_DEF(t)getShortDescription() << "\n";
|
||||
}
|
||||
#undef OSL_TGT_DEF
|
||||
std::cout << "Target: '" << t.getName() << "' "
|
||||
<< t.getShortDescription() << "\n";
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
@@ -436,15 +354,6 @@ LLVM_Util::new_module (const char *id)
|
||||
|
||||
|
||||
|
||||
#if OSL_LLVM_VERSION < 40
|
||||
inline bool error_string (const std::error_code &err, std::string *str) {
|
||||
if (err) {
|
||||
if (str) *str = err.message();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
inline bool error_string (llvm::Error err, std::string *str) {
|
||||
if (err) {
|
||||
if (str) {
|
||||
@@ -455,7 +364,6 @@ inline bool error_string (llvm::Error err, std::string *str) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -466,32 +374,8 @@ LLVM_Util::module_from_bitcode (const char *bitcode, size_t size,
|
||||
if (err)
|
||||
err->clear();
|
||||
|
||||
#if OSL_LLVM_VERSION <= 35 /* Old JIT vvvvvvvvvvvvvvvvvvvvvvvvvvvv */
|
||||
llvm::MemoryBuffer* buf =
|
||||
llvm::MemoryBuffer::getMemBuffer (llvm::StringRef(bitcode, size), name);
|
||||
|
||||
// Create a lazily deserialized IR module
|
||||
// This can only be done for old JIT
|
||||
llvm::Module *m = llvm::getLazyBitcodeModule (buf, context()).get();
|
||||
// don't delete buf, the module has taken ownership of it
|
||||
|
||||
#if 0
|
||||
// Debugging: print all functions in the module
|
||||
for (llvm::Module::iterator i = m->begin(); i != m->end(); ++i)
|
||||
std::cout << " found " << i->getName().data() << "\n";
|
||||
#endif
|
||||
return m;
|
||||
#endif /* End of LLVM <= 3.5 Old JIT section ^^^^^^^^^^^^^^^^^^^^^ */
|
||||
|
||||
|
||||
#if OSL_LLVM_VERSION >= 36 /* MCJIT vvvvvvvvvvvvvvvvvvvvvvvvvvvvv */
|
||||
# if OSL_LLVM_VERSION >= 40
|
||||
typedef llvm::Expected<std::unique_ptr<llvm::Module> > ErrorOrModule;
|
||||
# else
|
||||
typedef llvm::ErrorOr<std::unique_ptr<llvm::Module> > ErrorOrModule;
|
||||
# endif
|
||||
|
||||
# if OSL_LLVM_VERSION >= 40 || defined(OSL_FORCE_BITCODE_PARSE)
|
||||
llvm::MemoryBufferRef buf =
|
||||
llvm::MemoryBufferRef(llvm::StringRef(bitcode, size), name);
|
||||
# ifdef OSL_FORCE_BITCODE_PARSE
|
||||
@@ -514,18 +398,8 @@ LLVM_Util::module_from_bitcode (const char *bitcode, size_t size,
|
||||
ErrorOrModule ModuleOrErr = llvm::getLazyBitcodeModule(buf, context());
|
||||
# endif
|
||||
|
||||
# else /* !OSL_FORCE_BITCODE_PARSE */
|
||||
std::unique_ptr<llvm::MemoryBuffer> buf (
|
||||
llvm::MemoryBuffer::getMemBuffer (llvm::StringRef(bitcode, size), name, false));
|
||||
ErrorOrModule ModuleOrErr = llvm::getLazyBitcodeModule(std::move(buf), context());
|
||||
# endif
|
||||
|
||||
if (err) {
|
||||
# if OSL_LLVM_VERSION >= 40
|
||||
error_string(ModuleOrErr.takeError(), err);
|
||||
# else
|
||||
error_string(ModuleOrErr.getError(), err);
|
||||
# endif
|
||||
}
|
||||
llvm::Module *m = ModuleOrErr ? ModuleOrErr->release() : nullptr;
|
||||
# if 0
|
||||
@@ -534,8 +408,6 @@ LLVM_Util::module_from_bitcode (const char *bitcode, size_t size,
|
||||
std::cout << " found " << i->getName().data() << "\n";
|
||||
# endif
|
||||
return m;
|
||||
|
||||
#endif /* MCJIT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
|
||||
}
|
||||
|
||||
|
||||
@@ -574,24 +446,14 @@ LLVM_Util::make_jit_execengine (std::string *err)
|
||||
execengine (NULL); // delete and clear any existing engine
|
||||
if (err)
|
||||
err->clear ();
|
||||
# if OSL_LLVM_VERSION >= 36
|
||||
llvm::EngineBuilder engine_builder ((std::unique_ptr<llvm::Module>(module())));
|
||||
# else /* < 36: */
|
||||
llvm::EngineBuilder engine_builder (module());
|
||||
# endif
|
||||
|
||||
engine_builder.setEngineKind (llvm::EngineKind::JIT);
|
||||
engine_builder.setErrorStr (err);
|
||||
|
||||
#if USE_OLD_JIT
|
||||
engine_builder.setJITMemoryManager (m_llvm_jitmm);
|
||||
// N.B. createJIT will take ownership of the the JITMemoryManager!
|
||||
engine_builder.setUseMCJIT (0);
|
||||
#else
|
||||
// We are actually holding a LLVMMemoryManager
|
||||
engine_builder.setMCJITMemoryManager (std::unique_ptr<llvm::RTDyldMemoryManager>
|
||||
(new MemoryManager(reinterpret_cast<LLVMMemoryManager*>(m_llvm_jitmm))));
|
||||
#endif /* USE_OLD_JIT */
|
||||
(new MemoryManager(m_llvm_jitmm)));
|
||||
|
||||
engine_builder.setOptLevel (llvm::CodeGenOpt::Default);
|
||||
|
||||
@@ -599,6 +461,17 @@ LLVM_Util::make_jit_execengine (std::string *err)
|
||||
if (! m_llvm_exec)
|
||||
return NULL;
|
||||
|
||||
// These magic lines will make it so that enough symbol information
|
||||
// is injected so that running vtune will kinda tell you which shaders
|
||||
// you're in, and sometimes which function (only for functions that don't
|
||||
// get inlined. There doesn't seem to be any perf hit from this, either
|
||||
// in code quality or JIT time. It is only enabled, however, if your copy
|
||||
// of LLVM was build with -DLLVM_USE_INTEL_JITEVENTS=ON, otherwise
|
||||
// createIntelJITEventListener() is a stub that just returns nullptr.
|
||||
auto vtuneProfiler = llvm::JITEventListener::createIntelJITEventListener();
|
||||
if (vtuneProfiler)
|
||||
m_llvm_exec->RegisterJITEventListener (vtuneProfiler);
|
||||
|
||||
// Force it to JIT as soon as we ask it for the code pointer,
|
||||
// don't take any chances that it might JIT lazily, since we
|
||||
// will be stealing the JIT code memory from under its nose and
|
||||
@@ -623,8 +496,7 @@ LLVM_Util::getPointerToFunction (llvm::Function *func)
|
||||
{
|
||||
DASSERT (func && "passed NULL to getPointerToFunction");
|
||||
llvm::ExecutionEngine *exec = execengine();
|
||||
if (USE_MCJIT)
|
||||
exec->finalizeObject ();
|
||||
exec->finalizeObject ();
|
||||
void *f = exec->getPointerToFunction (func);
|
||||
ASSERT (f && "could not getPointerToFunction");
|
||||
return f;
|
||||
@@ -648,10 +520,6 @@ LLVM_Util::setup_optimization_passes (int optlevel)
|
||||
|
||||
// Construct the per-function passes and module-wide (interprocedural
|
||||
// optimization) passes.
|
||||
//
|
||||
// LLVM keeps changing names and call sequence. This part is easier to
|
||||
// understand if we explicitly break it into individual LLVM versions.
|
||||
#if OSL_LLVM_VERSION >= 37
|
||||
|
||||
m_llvm_func_passes = new llvm::legacy::FunctionPassManager(module());
|
||||
llvm::legacy::FunctionPassManager &fpm = (*m_llvm_func_passes);
|
||||
@@ -659,28 +527,6 @@ LLVM_Util::setup_optimization_passes (int optlevel)
|
||||
m_llvm_module_passes = new llvm::legacy::PassManager;
|
||||
llvm::legacy::PassManager &mpm = (*m_llvm_module_passes);
|
||||
|
||||
#elif OSL_LLVM_VERSION >= 36
|
||||
|
||||
m_llvm_func_passes = new llvm::legacy::FunctionPassManager(module());
|
||||
llvm::legacy::FunctionPassManager &fpm (*m_llvm_func_passes);
|
||||
fpm.add (new llvm::DataLayoutPass());
|
||||
|
||||
m_llvm_module_passes = new llvm::legacy::PassManager;
|
||||
llvm::legacy::PassManager &mpm (*m_llvm_module_passes);
|
||||
mpm.add (new llvm::DataLayoutPass());
|
||||
|
||||
#elif OSL_LLVM_VERSION == 35
|
||||
|
||||
m_llvm_func_passes = new llvm::legacy::FunctionPassManager(module());
|
||||
llvm::legacy::FunctionPassManager &fpm (*m_llvm_func_passes);
|
||||
fpm.add (new llvm::DataLayoutPass(module()));
|
||||
|
||||
m_llvm_module_passes = new llvm::legacy::PassManager;
|
||||
llvm::legacy::PassManager &mpm (*m_llvm_module_passes);
|
||||
mpm.add (new llvm::DataLayoutPass(module()));
|
||||
|
||||
#endif
|
||||
|
||||
if (optlevel >= 1 && optlevel <= 3) {
|
||||
// For LLVM 3.0 and higher, llvm_optimize 1-3 means to use the
|
||||
// same set of optimizations as clang -O1, -O2, -O3
|
||||
@@ -700,10 +546,7 @@ LLVM_Util::setup_optimization_passes (int optlevel)
|
||||
mpm.add (llvm::createCFGSimplificationPass());
|
||||
// Change memory references to registers
|
||||
// mpm.add (llvm::createPromoteMemoryToRegisterPass());
|
||||
#if OSL_LLVM_VERSION <= 36
|
||||
// Is there a replacement for this in newer LLVM?
|
||||
mpm.add (llvm::createScalarReplAggregatesPass());
|
||||
#endif
|
||||
|
||||
// Combine instructions where possible -- peephole opts & bit-twiddling
|
||||
mpm.add (llvm::createInstructionCombiningPass());
|
||||
// Inline small functions
|
||||
@@ -734,7 +577,7 @@ LLVM_Util::do_optimize (std::string *out_err)
|
||||
{
|
||||
ASSERT(m_llvm_module && "No module to optimize!");
|
||||
|
||||
#if OSL_LLVM_VERSION > 35 && !defined(OSL_FORCE_BITCODE_PARSE)
|
||||
#if !defined(OSL_FORCE_BITCODE_PARSE)
|
||||
LLVMErr err = m_llvm_module->materializeAll();
|
||||
if (error_string(std::move(err), out_err))
|
||||
return;
|
||||
@@ -752,13 +595,8 @@ LLVM_Util::internalize_module_functions (const std::string &prefix,
|
||||
const std::vector<std::string> &exceptions,
|
||||
const std::vector<std::string> &moreexceptions)
|
||||
{
|
||||
#if OSL_LLVM_VERSION < 40
|
||||
for (llvm::Module::iterator iter = module()->begin(); iter != module()->end(); iter++) {
|
||||
llvm::Function *sym = static_cast<llvm::Function*>(iter);
|
||||
#else
|
||||
for (llvm::Function& func : module()->getFunctionList()) {
|
||||
llvm::Function *sym = &func;
|
||||
#endif
|
||||
std::string symname = sym->getName();
|
||||
if (prefix.size() && ! OIIO::Strutil::starts_with(symname, prefix))
|
||||
continue;
|
||||
@@ -874,11 +712,7 @@ LLVM_Util::current_function_arg (int a)
|
||||
llvm::Function::arg_iterator arg_it = current_function()->arg_begin();
|
||||
for (int i = 0; i < a; ++i)
|
||||
++arg_it;
|
||||
#if OSL_LLVM_VERSION <= 36
|
||||
return arg_it;
|
||||
#else
|
||||
return &(*arg_it);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1162,6 +996,14 @@ LLVM_Util::ptr_cast (llvm::Value* val, const TypeDesc &type)
|
||||
|
||||
|
||||
|
||||
llvm::Value *
|
||||
LLVM_Util::int_to_ptr_cast (llvm::Value* val)
|
||||
{
|
||||
return builder().CreateIntToPtr(val,type_void_ptr());
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value *
|
||||
LLVM_Util::void_ptr (llvm::Value* val)
|
||||
{
|
||||
@@ -1313,7 +1155,8 @@ LLVM_Util::op_return (llvm::Value *retval)
|
||||
void
|
||||
LLVM_Util::op_memset (llvm::Value *ptr, int val, int len, int align)
|
||||
{
|
||||
op_memset(ptr, val, constant(len), align);
|
||||
builder().CreateMemSet (ptr, builder().getInt8((unsigned char)val),
|
||||
uint64_t(len), (unsigned)align);
|
||||
}
|
||||
|
||||
|
||||
@@ -1321,35 +1164,8 @@ LLVM_Util::op_memset (llvm::Value *ptr, int val, int len, int align)
|
||||
void
|
||||
LLVM_Util::op_memset (llvm::Value *ptr, int val, llvm::Value *len, int align)
|
||||
{
|
||||
// memset with i32 len
|
||||
// and with an i8 pointer (dst) for LLVM-2.8
|
||||
llvm::Type* types[] = {
|
||||
(llvm::Type *) llvm::PointerType::get(llvm::Type::getInt8Ty(context()), 0),
|
||||
(llvm::Type *) llvm::Type::getInt32Ty(context())
|
||||
};
|
||||
|
||||
llvm::Function* func = llvm::Intrinsic::getDeclaration (module(),
|
||||
llvm::Intrinsic::memset,
|
||||
llvm::ArrayRef<llvm::Type *>(types, sizeof(types)/sizeof(llvm::Type*)));
|
||||
|
||||
// NOTE(boulos): constant(0) would return an i32
|
||||
// version of 0, but we need the i8 version. If we make an
|
||||
// ::constant(char val) though then we'll get ambiguity
|
||||
// everywhere.
|
||||
llvm::Value* fill_val = llvm::ConstantInt::get (context(),
|
||||
llvm::APInt(8, val));
|
||||
// Non-volatile (allow optimizer to move it around as it wishes
|
||||
// and even remove it if it can prove it's useless)
|
||||
#if OSL_LLVM_VERSION <= 36
|
||||
builder().CreateCall5 (func, ptr, fill_val, len, constant(align),
|
||||
constant_bool(false));
|
||||
#else
|
||||
llvm::Value *args[5] = {
|
||||
ptr, fill_val, len, constant(align), constant_bool(false)
|
||||
};
|
||||
builder().CreateCall (func, llvm::ArrayRef<llvm::Value*>(args, 5));
|
||||
|
||||
#endif
|
||||
builder().CreateMemSet (ptr, builder().getInt8((unsigned char)val),
|
||||
len, (unsigned)align);
|
||||
}
|
||||
|
||||
|
||||
@@ -1357,28 +1173,21 @@ LLVM_Util::op_memset (llvm::Value *ptr, int val, llvm::Value *len, int align)
|
||||
void
|
||||
LLVM_Util::op_memcpy (llvm::Value *dst, llvm::Value *src, int len, int align)
|
||||
{
|
||||
// i32 len
|
||||
// and with i8 pointers (dst and src) for LLVM-2.8
|
||||
llvm::Type* types[] = {
|
||||
(llvm::Type *) llvm::PointerType::get(llvm::Type::getInt8Ty(context()), 0),
|
||||
(llvm::Type *) llvm::PointerType::get(llvm::Type::getInt8Ty(context()), 0),
|
||||
(llvm::Type *) llvm::Type::getInt32Ty(context())
|
||||
};
|
||||
op_memcpy (dst, align, src, align, len);
|
||||
}
|
||||
|
||||
llvm::Function* func = llvm::Intrinsic::getDeclaration (module(),
|
||||
llvm::Intrinsic::memcpy,
|
||||
llvm::ArrayRef<llvm::Type *>(types, sizeof(types)/sizeof(llvm::Type*)));
|
||||
|
||||
// Non-volatile (allow optimizer to move it around as it wishes
|
||||
// and even remove it if it can prove it's useless)
|
||||
#if OSL_LLVM_VERSION <= 36
|
||||
builder().CreateCall5 (func, dst, src,
|
||||
constant(len), constant(align), constant_bool(false));
|
||||
|
||||
void
|
||||
LLVM_Util::op_memcpy (llvm::Value *dst, int dstalign,
|
||||
llvm::Value *src, int srcalign, int len)
|
||||
{
|
||||
#if OSL_LLVM_VERSION >= 70
|
||||
builder().CreateMemCpy (dst, (unsigned)dstalign, src, (unsigned)srcalign,
|
||||
uint64_t(len));
|
||||
#else
|
||||
llvm::Value *args[5] = {
|
||||
dst, src, constant(len), constant(align), constant_bool(false)
|
||||
};
|
||||
builder().CreateCall (func, llvm::ArrayRef<llvm::Value*>(args, 5));
|
||||
builder().CreateMemCpy (dst, src, uint64_t(len),
|
||||
std::min ((unsigned)dstalign, (unsigned)srcalign));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1419,11 +1228,7 @@ LLVM_Util::GEP (llvm::Value *ptr, int elem)
|
||||
llvm::Value *
|
||||
LLVM_Util::GEP (llvm::Value *ptr, int elem1, int elem2)
|
||||
{
|
||||
#if OSL_LLVM_VERSION <= 36
|
||||
return builder().CreateConstGEP2_32 (ptr, elem1, elem2);
|
||||
#else
|
||||
return builder().CreateConstGEP2_32 (nullptr, ptr, elem1, elem2);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1521,6 +1326,14 @@ LLVM_Util::op_float_to_double (llvm::Value* a)
|
||||
|
||||
|
||||
|
||||
llvm::Value *
|
||||
LLVM_Util::op_int_to_longlong (llvm::Value* a)
|
||||
{
|
||||
ASSERT (a->getType() == type_int());
|
||||
return builder().CreateSExt(a, llvm::Type::getInt64Ty(context()));
|
||||
}
|
||||
|
||||
|
||||
llvm::Value *
|
||||
LLVM_Util::op_int_to_float (llvm::Value* a)
|
||||
{
|
||||
@@ -1674,19 +1487,126 @@ LLVM_Util::op_le (llvm::Value *a, llvm::Value *b, bool ordered)
|
||||
void
|
||||
LLVM_Util::write_bitcode_file (const char *filename, std::string *err)
|
||||
{
|
||||
#if OSL_LLVM_VERSION >= 36
|
||||
std::error_code local_error;
|
||||
llvm::raw_fd_ostream out (filename, local_error, llvm::sys::fs::F_None);
|
||||
if (! out.has_error()) {
|
||||
#if OSL_LLVM_VERSION >= 70
|
||||
llvm::WriteBitcodeToFile (*module(), out);
|
||||
#else
|
||||
std::string local_error;
|
||||
llvm::raw_fd_ostream out (filename, err ? *err : local_error, llvm::sys::fs::F_None);
|
||||
llvm::WriteBitcodeToFile (module(), out);
|
||||
#endif
|
||||
llvm::WriteBitcodeToFile (module(), out);
|
||||
if (err && local_error)
|
||||
*err = local_error.message ();
|
||||
}
|
||||
}
|
||||
|
||||
#if OSL_LLVM_VERSION >= 36
|
||||
if (err && local_error)
|
||||
*err = local_error.message ();
|
||||
|
||||
|
||||
bool
|
||||
LLVM_Util::ptx_compile_group (llvm::Module* lib_module, const std::string& name,
|
||||
std::string& out)
|
||||
{
|
||||
std::string target_triple = module()->getTargetTriple();
|
||||
ASSERT (lib_module->getTargetTriple() == target_triple &&
|
||||
"PTX compile error: Shader and renderer bitcode library targets do not match");
|
||||
|
||||
// Create a new empty module to hold the linked shadeops and compiled
|
||||
// ShaderGroup
|
||||
llvm::Module* linked_module = new_module (name.c_str());
|
||||
|
||||
// First, link in the cloned ShaderGroup module
|
||||
#if OSL_LLVM_VERSION >= 70
|
||||
std::unique_ptr<llvm::Module> mod_ptr = llvm::CloneModule (*module());
|
||||
#else
|
||||
std::unique_ptr<llvm::Module> mod_ptr = llvm::CloneModule (module());
|
||||
#endif
|
||||
bool failed = llvm::Linker::linkModules (*linked_module, std::move (mod_ptr));
|
||||
if (failed) {
|
||||
ASSERT (0 && "PTX compile error: Unable to link group module");
|
||||
}
|
||||
|
||||
// Second, link in the shadeops library, keeping only the functions that are needed
|
||||
std::unique_ptr<llvm::Module> lib_ptr (lib_module);
|
||||
failed = llvm::Linker::linkModules (*linked_module, std::move (lib_ptr));
|
||||
|
||||
// Internalize the Globals to match code generated by NVCC
|
||||
for (auto& g_var : linked_module->globals()) {
|
||||
g_var.setLinkage(llvm::GlobalValue::InternalLinkage);
|
||||
}
|
||||
|
||||
// Verify that the NVPTX target has been initialized
|
||||
std::string error;
|
||||
const llvm::Target* llvm_target =
|
||||
llvm::TargetRegistry::lookupTarget (target_triple, error);
|
||||
if(! llvm_target) {
|
||||
ASSERT (0 && "PTX compile error: LLVM Target is not initialized");
|
||||
}
|
||||
|
||||
llvm::TargetOptions options;
|
||||
options.AllowFPOpFusion = llvm::FPOpFusion::Standard;
|
||||
options.UnsafeFPMath = 1;
|
||||
options.NoInfsFPMath = 1;
|
||||
options.NoNaNsFPMath = 1;
|
||||
options.HonorSignDependentRoundingFPMathOption = 0;
|
||||
options.FloatABIType = llvm::FloatABI::Default;
|
||||
options.AllowFPOpFusion = llvm::FPOpFusion::Fast;
|
||||
options.NoZerosInBSS = 0;
|
||||
options.GuaranteedTailCallOpt = 0;
|
||||
options.StackAlignmentOverride = 0;
|
||||
options.UseInitArray = 0;
|
||||
|
||||
llvm::TargetMachine* target_machine = llvm_target->createTargetMachine(
|
||||
target_triple, "sm_35", "+ptx50", options,
|
||||
llvm::Reloc::Static, llvm::CodeModel::Small, llvm::CodeGenOpt::Aggressive);
|
||||
if (! target_machine) {
|
||||
ASSERT(0 && "PTX compile error: Unable to create target machine -- is NVPTX enabled in LLVM?");
|
||||
}
|
||||
|
||||
// Setup the optimzation passes
|
||||
llvm::legacy::FunctionPassManager fn_pm (linked_module);
|
||||
fn_pm.add (llvm::createTargetTransformInfoWrapperPass (
|
||||
target_machine->getTargetIRAnalysis()));
|
||||
|
||||
llvm::legacy::PassManager mod_pm;
|
||||
mod_pm.add (new llvm::TargetLibraryInfoWrapperPass (llvm::Triple (target_triple)));
|
||||
mod_pm.add (llvm::createTargetTransformInfoWrapperPass (
|
||||
target_machine->getTargetIRAnalysis()));
|
||||
mod_pm.add (llvm::createRewriteSymbolsPass());
|
||||
|
||||
// Make sure the 'flush-to-zero' instruction variants are used when possible
|
||||
linked_module->addModuleFlag (llvm::Module::Override, "nvvm-reflect-ftz", 1);
|
||||
for (llvm::Function& fn : *linked_module) {
|
||||
fn.addFnAttr ("nvptx-f32ftz", "true");
|
||||
}
|
||||
|
||||
llvm::SmallString<4096> assembly;
|
||||
llvm::raw_svector_ostream assembly_stream (assembly);
|
||||
|
||||
// TODO: Make sure rounding modes, etc., are set correctly
|
||||
#if OSL_LLVM_VERSION >= 70
|
||||
target_machine->addPassesToEmitFile (mod_pm, assembly_stream,
|
||||
nullptr, // FIXME: Correct?
|
||||
llvm::TargetMachine::CGFT_AssemblyFile);
|
||||
#else
|
||||
target_machine->addPassesToEmitFile (mod_pm, assembly_stream,
|
||||
llvm::TargetMachine::CGFT_AssemblyFile);
|
||||
#endif
|
||||
|
||||
// Run the optimization passes on the functions
|
||||
fn_pm.doInitialization();
|
||||
for (llvm::Module::iterator i = linked_module->begin(); i != linked_module->end(); i++) {
|
||||
fn_pm.run (*i);
|
||||
}
|
||||
|
||||
// Run the optimization passes on the module to generate the PTX
|
||||
mod_pm.run (*linked_module);
|
||||
|
||||
// TODO: Minimize string copying
|
||||
out = assembly_stream.str().str();
|
||||
|
||||
delete linked_module;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1702,6 +1622,20 @@ LLVM_Util::bitcode_string (llvm::Function *func)
|
||||
|
||||
|
||||
|
||||
std::string
|
||||
LLVM_Util::bitcode_string (llvm::Module *module)
|
||||
{
|
||||
std::string s;
|
||||
llvm::raw_string_ostream stream (s);
|
||||
|
||||
for (auto&& func : module->getFunctionList())
|
||||
stream << func << '\n';
|
||||
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
LLVM_Util::delete_func_body (llvm::Function *func)
|
||||
{
|
||||
|
||||
@@ -331,129 +331,109 @@ OSOReaderToMaster::parameter_done ()
|
||||
|
||||
|
||||
|
||||
inline bool
|
||||
starts_with (const std::string &source, const std::string &pattern)
|
||||
{
|
||||
return ! strncmp (source.c_str(), pattern.c_str(), pattern.length());
|
||||
}
|
||||
|
||||
|
||||
|
||||
// If the string 'source' begins with 'pattern', erase the pattern from
|
||||
// the start of source and return true. Otherwise, do not alter source
|
||||
// and return false.
|
||||
inline bool
|
||||
extract_prefix (std::string &source, const std::string &pattern)
|
||||
{
|
||||
if (starts_with (source, pattern)) {
|
||||
source.erase (0, pattern.length());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Return the prefix of source that doesn't contain any characters in
|
||||
// 'stop', erase that prefix from source (up to and including the stop
|
||||
// character. Also, the returned string is trimmed of leading and trailing
|
||||
// spaces if 'do_trim' is true.
|
||||
static std::string
|
||||
readuntil (std::string &source, const std::string &stop, bool do_trim=false)
|
||||
{
|
||||
size_t e = source.find_first_of (stop);
|
||||
if (e == source.npos)
|
||||
return std::string ();
|
||||
std::string r (source, 0, e);
|
||||
source.erase (0, e == source.npos ? e : e+1);
|
||||
if (do_trim)
|
||||
r = Strutil::strip (r); // trim whitespace
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
OSOReaderToMaster::hint (string_view hintstring)
|
||||
{
|
||||
std::string h (hintstring); // FIXME -- use string_view ops here
|
||||
if (extract_prefix (h, "%filename{\"")) {
|
||||
m_sourcefile = readuntil (h, "\"");
|
||||
string_view h (hintstring);
|
||||
|
||||
if (Strutil::parse_prefix (h, "%filename{\"")) {
|
||||
m_sourcefile = Strutil::parse_until (h, "\"");
|
||||
return;
|
||||
}
|
||||
if (extract_prefix (h, "%line{")) {
|
||||
m_sourceline = atoi (h.c_str());
|
||||
if (Strutil::parse_prefix (h, "%line{")) {
|
||||
Strutil::parse_int (h, m_sourceline);
|
||||
return;
|
||||
}
|
||||
if (extract_prefix (h, "%structfields{")) {
|
||||
ASSERT (m_master->m_symbols.size() && "structfields hint but no sym");
|
||||
if (Strutil::parse_prefix (h, "%structfields{") && m_master->m_symbols.size()) {
|
||||
Symbol &sym (m_master->m_symbols.back());
|
||||
StructSpec *structspec = sym.typespec().structspec();
|
||||
if (structspec->numfields() == 0) {
|
||||
while (1) {
|
||||
std::string afield = readuntil (h, ",}", true);
|
||||
std::string afield = Strutil::parse_until (h, ",}");
|
||||
Strutil::parse_char (h, ','); // skip the separator
|
||||
if (! afield.length())
|
||||
break;
|
||||
// std::cerr << " struct field " << afield << "\n";
|
||||
structspec->add_field (TypeSpec(), ustring(afield));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (extract_prefix (h, "%mystructfield{")) {
|
||||
ASSERT (m_master->m_symbols.size() && "mystructfield hint but no sym");
|
||||
Symbol &sym (m_master->m_symbols.back());
|
||||
sym.fieldid (atoi(h.c_str()+15));
|
||||
if (Strutil::parse_prefix (h, "%mystructfield{") && m_master->m_symbols.size()) {
|
||||
int ival = -1;
|
||||
if (Strutil::parse_int (h, ival) && ival >= 0)
|
||||
m_master->m_symbols.back().fieldid (ival);
|
||||
return;
|
||||
}
|
||||
if (extract_prefix (h, "%read{")) {
|
||||
ASSERT (m_master->m_symbols.size() && "read hint but no sym");
|
||||
if (Strutil::parse_prefix (h, "%read{") && m_master->m_symbols.size()) {
|
||||
Symbol &sym (m_master->m_symbols.back());
|
||||
int first, last;
|
||||
sscanf (h.c_str(), "%d,%d", &first, &last);
|
||||
sym.set_read (first, last);
|
||||
if (Strutil::parse_int (h, first) && Strutil::parse_char(h, ',')
|
||||
&& Strutil::parse_int (h, last))
|
||||
sym.set_read (first, last);
|
||||
return;
|
||||
}
|
||||
if (extract_prefix (h, "%write{")) {
|
||||
ASSERT (m_master->m_symbols.size() && "write hint but no sym");
|
||||
if (Strutil::parse_prefix (h, "%write{") && m_master->m_symbols.size()) {
|
||||
Symbol &sym (m_master->m_symbols.back());
|
||||
int first, last;
|
||||
sscanf (h.c_str(), "%d,%d", &first, &last);
|
||||
sym.set_write (first, last);
|
||||
if (Strutil::parse_int (h, first) && Strutil::parse_char(h, ',')
|
||||
&& Strutil::parse_int (h, last))
|
||||
sym.set_write (first, last);
|
||||
return;
|
||||
}
|
||||
if (extract_prefix(h, "%argrw{")) {
|
||||
const char* str = h.c_str();
|
||||
ASSERT(*str == '\"');
|
||||
str++; // skip open quote
|
||||
size_t i = 0;
|
||||
for (; *str != '\"'; i++, str++) {
|
||||
ASSERT(*str == 'r' || *str == 'w' || *str == 'W' || *str == '-');
|
||||
m_master->m_ops.back().argwrite(i, *str == 'w' || *str =='W');
|
||||
m_master->m_ops.back().argread(i, *str == 'r' || *str =='W');
|
||||
if (Strutil::parse_prefix(h, "%argrw{") && m_master->m_ops.size()) {
|
||||
Opcode &op (m_master->m_ops.back());
|
||||
string_view str = Strutil::parse_until (h, "}");
|
||||
Strutil::parse_string (str, str, false, Strutil::DeleteQuotes);
|
||||
if (str.size() != m_nargs) {
|
||||
m_shadingsys.error ("Parsing shader %s: malformed hint '%s' on op %s line %d",
|
||||
m_master->shadername(), hintstring,
|
||||
m_master->m_ops.back().opname(), m_sourceline);
|
||||
m_errors = true;
|
||||
}
|
||||
for (size_t i = 0; str.size() && i < m_nargs; i++, str.remove_prefix(1)) {
|
||||
char c = str.front();
|
||||
op.argwrite (i, c == 'w' || c =='W');
|
||||
op.argread (i, c == 'r' || c =='W');
|
||||
}
|
||||
ASSERT(m_nargs == i);
|
||||
// Fix old bug where oslc forgot to mark getmatrix last arg as write
|
||||
ustring opname = m_master->m_ops.back().opname();
|
||||
static ustring getmatrix("getmatrix");
|
||||
if (m_master->m_ops.back().opname() == getmatrix)
|
||||
m_master->m_ops.back().argwrite(m_nargs-1, true);
|
||||
if (opname == getmatrix)
|
||||
m_master->m_ops.back().argwriteonly (m_nargs-1);
|
||||
// Fix old bug where oslc forgot to mark regex results as write.
|
||||
// This was a bug prior to 1.10.
|
||||
static ustring regex_search("regex_search");
|
||||
static ustring regex_match("regex_match");
|
||||
if (opname == regex_search || opname == regex_search)
|
||||
m_master->m_ops.back().argwriteonly (2);
|
||||
return;
|
||||
}
|
||||
if (extract_prefix(h, "%argderivs{")) {
|
||||
if (Strutil::parse_prefix(h, "%argderivs{")) {
|
||||
while (1) {
|
||||
std::string afield = readuntil (h, ",}", true);
|
||||
string_view afield = Strutil::parse_until (h, ",}");
|
||||
Strutil::parse_char (h, ','); // skip the separator
|
||||
if (! afield.length())
|
||||
break;
|
||||
int arg = atoi (afield.c_str());
|
||||
if (arg >= 0)
|
||||
int arg = -1;
|
||||
if (Strutil::parse_int (afield, arg) && arg >= 0)
|
||||
m_master->m_ops.back().argtakesderivs (arg, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (extract_prefix (h, "%meta{") && m_master->m_symbols.size()) {
|
||||
if (Strutil::parse_prefix (h, "%meta{") && m_master->m_symbols.size()) {
|
||||
Symbol &sym (m_master->m_symbols.back());
|
||||
int lockval = -1;
|
||||
int ok = sscanf (h.c_str(), " int , lockgeom , %d", &lockval);
|
||||
if (ok)
|
||||
sym.lockgeom (lockval);
|
||||
int ival = -1;
|
||||
TypeDesc type (Strutil::parse_identifier (h, "", true));
|
||||
Strutil::parse_char (h, ',');
|
||||
string_view ident = Strutil::parse_identifier (h, "", true);
|
||||
Strutil::parse_char (h, ',');
|
||||
if (type == TypeDesc::TypeInt && ident == "lockgeom"
|
||||
&& Strutil::parse_int (h, ival) && ival >= 0)
|
||||
sym.lockgeom (ival);
|
||||
else if (type == TypeDesc::TypeInt && ident == "allowconnect"
|
||||
&& Strutil::parse_int (h, ival) && ival >= 0)
|
||||
sym.allowconnect (ival);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,7 +477,7 @@ OSOReaderToMaster::codeend ()
|
||||
// If we were previously chalking up the code to init ops for a
|
||||
// symbol, mark the end.
|
||||
m_master->symbol(m_codesym)->initend (nextop);
|
||||
} else if (m_codesection && m_codesection == "___main___") {
|
||||
} else if (m_codesection == "___main___") {
|
||||
// If we were previously reading ops for the ___main___ entry
|
||||
// point, mark its end properly.
|
||||
m_master->m_maincodeend = nextop;
|
||||
@@ -585,10 +565,12 @@ ShadingSystemImpl::loadshader (string_view cname)
|
||||
|
||||
// Not found in the map
|
||||
OSOReaderToMaster oso (*this);
|
||||
bool testcwd = m_searchpath_dirs.empty(); // test "." if there's no searchpath
|
||||
std::string filename = OIIO::Filesystem::searchpath_find (name.string() + ".oso",
|
||||
m_searchpath_dirs);
|
||||
m_searchpath_dirs,
|
||||
testcwd);
|
||||
if (filename.empty ()) {
|
||||
error ("No .oso file could be found for shader \"%s\"", name.c_str());
|
||||
error ("No .oso file could be found for shader \"%s\"", name);
|
||||
return NULL;
|
||||
}
|
||||
OIIO::Timer timer;
|
||||
@@ -636,9 +618,9 @@ ShadingSystemImpl::LoadMemoryCompiledShader (string_view shadername,
|
||||
ustring name (shadername);
|
||||
lock_guard guard (m_mutex); // Thread safety
|
||||
ShaderNameMap::const_iterator found = m_shader_masters.find (name);
|
||||
if (found != m_shader_masters.end()) {
|
||||
if (found != m_shader_masters.end() && ! allow_shader_replacement()) {
|
||||
if (debug())
|
||||
info ("Preload shader %s already exists in shader_masters", name.c_str());
|
||||
info ("Preload shader %s already exists in shader_masters", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ Parser::buildStop(LPexp *etype, LPexp *scatter, const std::list<LPexp*> &custom)
|
||||
LPexp *
|
||||
Parser::parseSymbol()
|
||||
{
|
||||
bool iscustom;
|
||||
bool iscustom = false;
|
||||
ustring sym = parseRawSymbol(iscustom);
|
||||
if (m_ingroup) {
|
||||
if (sym == udot)
|
||||
@@ -396,6 +396,10 @@ LPexp *
|
||||
Parser::parseModifier(LPexp *e)
|
||||
{
|
||||
if (hasInput()) {
|
||||
if (m_ingroup && (head() == '*' || head() == '{' || head() == '+')) {
|
||||
m_error = std::string("Repetitions not allowed inside '<...>'");
|
||||
return NULL;
|
||||
}
|
||||
if (head() == '*') {
|
||||
next();
|
||||
return new lpexp::Repeat(e);
|
||||
|
||||
@@ -264,7 +264,7 @@ ShaderMaster::print ()
|
||||
for (size_t j = 0; j < Opcode::max_jumps; ++j)
|
||||
if (m_ops[i].jump(j) >= 0)
|
||||
out << " " << m_ops[i].jump(j);
|
||||
if (m_ops[i].sourcefile())
|
||||
if (!m_ops[i].sourcefile().empty())
|
||||
out << "\t(" << m_ops[i].sourcefile() << ":"
|
||||
<< m_ops[i].sourceline() << ")";
|
||||
out << "\n";
|
||||
|
||||
@@ -539,6 +539,8 @@ ShadingContext::ocio_transform (ustring fromspace, ustring tospace,
|
||||
tospace != m_last_colorproc_tospace) {
|
||||
OIIO::ColorConfig& cc (shadingsys().m_colorconfig);
|
||||
m_last_colorproc = cc.createColorProcessor (fromspace, tospace);
|
||||
m_last_colorproc_fromspace = fromspace;
|
||||
m_last_colorproc_tospace = tospace;
|
||||
}
|
||||
if (m_last_colorproc)
|
||||
m_last_colorproc->apply ((float *)&Cout);
|
||||
@@ -563,13 +565,15 @@ ShadingContext::ocio_transform (ustring fromspace, ustring tospace,
|
||||
tospace != m_last_colorproc_tospace) {
|
||||
OIIO::ColorConfig& cc (shadingsys().m_colorconfig);
|
||||
m_last_colorproc = cc.createColorProcessor (fromspace, tospace);
|
||||
m_last_colorproc_fromspace = fromspace;
|
||||
m_last_colorproc_tospace = tospace;
|
||||
}
|
||||
if (m_last_colorproc) {
|
||||
// Use finite differencing to approximate the derivative. Make 3
|
||||
// color values to convert.
|
||||
const float eps = 0.001f;
|
||||
Color3 CC[3] = { C.val(), C.val() + eps*C.dx(), C.val() + eps*C.dy() };
|
||||
m_last_colorproc->apply ((float *)&CC, 3, 1, 3, sizeof(Color3), 0, 0);
|
||||
m_last_colorproc->apply ((float *)&CC, 3, 1, 3, sizeof(float), sizeof(Color3), 0);
|
||||
Cout.set (CC[0],
|
||||
(CC[1] - CC[0]) * (1.0f / eps),
|
||||
(CC[2] - CC[0]) * (1.0f / eps));
|
||||
|
||||
+101
-96
@@ -94,28 +94,28 @@ void test_perlin(int d) {
|
||||
|
||||
|
||||
#define NOISE_IMPL(opname,implname) \
|
||||
OSL_SHADEOP float osl_ ##opname## _ff (float x) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE float osl_ ##opname## _ff (float x) { \
|
||||
implname impl; \
|
||||
float r; \
|
||||
impl (r, x); \
|
||||
return r; \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP float osl_ ##opname## _fff (float x, float y) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE float osl_ ##opname## _fff (float x, float y) { \
|
||||
implname impl; \
|
||||
float r; \
|
||||
impl (r, x, y); \
|
||||
return r; \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP float osl_ ##opname## _fv (char *x) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE float osl_ ##opname## _fv (char *x) { \
|
||||
implname impl; \
|
||||
float r; \
|
||||
impl (r, VEC(x)); \
|
||||
return r; \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP float osl_ ##opname## _fvf (char *x, float y) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE float osl_ ##opname## _fvf (char *x, float y) { \
|
||||
implname impl; \
|
||||
float r; \
|
||||
impl (r, VEC(x), y); \
|
||||
@@ -123,22 +123,22 @@ OSL_SHADEOP float osl_ ##opname## _fvf (char *x, float y) { \
|
||||
} \
|
||||
\
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _vf (char *r, float x) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _vf (char *r, float x) { \
|
||||
implname impl; \
|
||||
impl (VEC(r), x); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _vff (char *r, float x, float y) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _vff (char *r, float x, float y) { \
|
||||
implname impl; \
|
||||
impl (VEC(r), x, y); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _vv (char *r, char *x) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _vv (char *r, char *x) { \
|
||||
implname impl; \
|
||||
impl (VEC(r), VEC(x)); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _vvf (char *r, char *x, float y) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _vvf (char *r, char *x, float y) { \
|
||||
implname impl; \
|
||||
impl (VEC(r), VEC(x), y); \
|
||||
}
|
||||
@@ -148,83 +148,83 @@ OSL_SHADEOP void osl_ ##opname## _vvf (char *r, char *x, float y) { \
|
||||
|
||||
|
||||
#define NOISE_IMPL_DERIV(opname,implname) \
|
||||
OSL_SHADEOP void osl_ ##opname## _dfdf (char *r, char *x) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdf (char *r, char *x) { \
|
||||
implname impl; \
|
||||
impl (DFLOAT(r), DFLOAT(x)); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dfdfdf (char *r, char *x, char *y) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdfdf (char *r, char *x, char *y) { \
|
||||
implname impl; \
|
||||
impl (DFLOAT(r), DFLOAT(x), DFLOAT(y)); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dfdff (char *r, char *x, float y) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdff (char *r, char *x, float y) { \
|
||||
implname impl; \
|
||||
impl (DFLOAT(r), DFLOAT(x), Dual2<float>(y)); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dffdf (char *r, float x, char *y) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dffdf (char *r, float x, char *y) { \
|
||||
implname impl; \
|
||||
impl (DFLOAT(r), Dual2<float>(x), DFLOAT(y)); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dfdv (char *r, char *x) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdv (char *r, char *x) { \
|
||||
implname impl; \
|
||||
impl (DFLOAT(r), DVEC(x)); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dfdvdf (char *r, char *x, char *y) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdvdf (char *r, char *x, char *y) { \
|
||||
implname impl; \
|
||||
impl (DFLOAT(r), DVEC(x), DFLOAT(y)); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dfdvf (char *r, char *x, float y) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdvf (char *r, char *x, float y) { \
|
||||
implname impl; \
|
||||
impl (DFLOAT(r), DVEC(x), Dual2<float>(y)); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dfvdf (char *r, char *x, char *y) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfvdf (char *r, char *x, char *y) { \
|
||||
implname impl; \
|
||||
impl (DFLOAT(r), Dual2<Vec3>(VEC(x)), DFLOAT(y)); \
|
||||
} \
|
||||
\
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dvdf (char *r, char *x) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdf (char *r, char *x) { \
|
||||
implname impl; \
|
||||
impl (DVEC(r), DFLOAT(x)); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dvdfdf (char *r, char *x, char *y) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdfdf (char *r, char *x, char *y) { \
|
||||
implname impl; \
|
||||
impl (DVEC(r), DFLOAT(x), DFLOAT(y)); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dvdff (char *r, char *x, float y) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdff (char *r, char *x, float y) { \
|
||||
implname impl; \
|
||||
impl (DVEC(r), DFLOAT(x), Dual2<float>(y)); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dvfdf (char *r, float x, char *y) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvfdf (char *r, float x, char *y) { \
|
||||
implname impl; \
|
||||
impl (DVEC(r), Dual2<float>(x), DFLOAT(y)); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dvdv (char *r, char *x) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdv (char *r, char *x) { \
|
||||
implname impl; \
|
||||
impl (DVEC(r), DVEC(x)); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dvdvdf (char *r, char *x, char *y) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdvdf (char *r, char *x, char *y) { \
|
||||
implname impl; \
|
||||
impl (DVEC(r), DVEC(x), DFLOAT(y)); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dvdvf (char *r, char *x, float y) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdvf (char *r, char *x, float y) { \
|
||||
implname impl; \
|
||||
impl (DVEC(r), DVEC(x), Dual2<float>(y)); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dvvdf (char *r, char *x, char *y) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvvdf (char *r, char *x, char *y) { \
|
||||
implname impl; \
|
||||
impl (DVEC(r), Dual2<Vec3>(VEC(x)), DFLOAT(y)); \
|
||||
}
|
||||
@@ -235,43 +235,43 @@ OSL_SHADEOP void osl_ ##opname## _dvvdf (char *r, char *x, char *y) { \
|
||||
#define NOISE_IMPL_DERIV_OPT(opname,implname) \
|
||||
OSL_SHADEOP void osl_ ##opname## _dfdf (char *name, char *r, char *x, char *sg, char *opt) { \
|
||||
implname impl; \
|
||||
impl (USTR(name), DFLOAT(r), DFLOAT(x), (ShaderGlobals *)sg, (NoiseParams *)opt); \
|
||||
impl (USTR(name), DFLOAT(r), DFLOAT(x), (ShaderGlobals *)sg, (NoiseParams *)opt); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dfdfdf (char *name, char *r, char *x, char *y, char *sg, char *opt) { \
|
||||
implname impl; \
|
||||
impl (USTR(name), DFLOAT(r), DFLOAT(x), DFLOAT(y), (ShaderGlobals *)sg, (NoiseParams *)opt); \
|
||||
impl (USTR(name), DFLOAT(r), DFLOAT(x), DFLOAT(y), (ShaderGlobals *)sg, (NoiseParams *)opt); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dfdv (char *name, char *r, char *x, char *sg, char *opt) { \
|
||||
OSL_SHADEOP void osl_ ##opname## _dfdv (char *name, char *r, char *x, char *sg, char *opt) { \
|
||||
implname impl; \
|
||||
impl (USTR(name), DFLOAT(r), DVEC(x), (ShaderGlobals *)sg, (NoiseParams *)opt); \
|
||||
impl (USTR(name), DFLOAT(r), DVEC(x), (ShaderGlobals *)sg, (NoiseParams *)opt); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dfdvdf (char *name, char *r, char *x, char *y, char *sg, char *opt) { \
|
||||
implname impl; \
|
||||
impl (USTR(name), DFLOAT(r), DVEC(x), DFLOAT(y), (ShaderGlobals *)sg, (NoiseParams *)opt); \
|
||||
impl (USTR(name), DFLOAT(r), DVEC(x), DFLOAT(y), (ShaderGlobals *)sg, (NoiseParams *)opt); \
|
||||
} \
|
||||
\
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dvdf (char *name, char *r, char *x, char *sg, char *opt) { \
|
||||
OSL_SHADEOP void osl_ ##opname## _dvdf (char *name, char *r, char *x, char *sg, char *opt) { \
|
||||
implname impl; \
|
||||
impl (USTR(name), DVEC(r), DFLOAT(x), (ShaderGlobals *)sg, (NoiseParams *)opt); \
|
||||
impl (USTR(name), DVEC(r), DFLOAT(x), (ShaderGlobals *)sg, (NoiseParams *)opt); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dvdfdf (char *name, char *r, char *x, char *y, char *sg, char *opt) { \
|
||||
implname impl; \
|
||||
impl (USTR(name), DVEC(r), DFLOAT(x), DFLOAT(y), (ShaderGlobals *)sg, (NoiseParams *)opt); \
|
||||
impl (USTR(name), DVEC(r), DFLOAT(x), DFLOAT(y), (ShaderGlobals *)sg, (NoiseParams *)opt); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dvdv (char *name, char *r, char *x, char *sg, char *opt) { \
|
||||
OSL_SHADEOP void osl_ ##opname## _dvdv (char *name, char *r, char *x, char *sg, char *opt) { \
|
||||
implname impl; \
|
||||
impl (USTR(name), DVEC(r), DVEC(x), (ShaderGlobals *)sg, (NoiseParams *)opt); \
|
||||
impl (USTR(name), DVEC(r), DVEC(x), (ShaderGlobals *)sg, (NoiseParams *)opt); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _dvdvdf (char *name, char *r, char *x, char *y, char *sg, char *opt) { \
|
||||
implname impl; \
|
||||
impl (USTR(name), DVEC(r), DVEC(x), DFLOAT(y), (ShaderGlobals *)sg, (NoiseParams *)opt); \
|
||||
impl (USTR(name), DVEC(r), DVEC(x), DFLOAT(y), (ShaderGlobals *)sg, (NoiseParams *)opt); \
|
||||
}
|
||||
|
||||
|
||||
@@ -291,28 +291,28 @@ NOISE_IMPL_DERIV (usimplexnoise, USimplexNoise)
|
||||
|
||||
|
||||
#define PNOISE_IMPL(opname,implname) \
|
||||
OSL_SHADEOP float osl_ ##opname## _fff (float x, float px) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE float osl_ ##opname## _fff (float x, float px) { \
|
||||
implname impl; \
|
||||
float r; \
|
||||
impl (r, x, px); \
|
||||
return r; \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP float osl_ ##opname## _fffff (float x, float y, float px, float py) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE float osl_ ##opname## _fffff (float x, float y, float px, float py) { \
|
||||
implname impl; \
|
||||
float r; \
|
||||
impl (r, x, y, px, py); \
|
||||
return r; \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP float osl_ ##opname## _fvv (char *x, char *px) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE float osl_ ##opname## _fvv (char *x, char *px) { \
|
||||
implname impl; \
|
||||
float r; \
|
||||
impl (r, VEC(x), VEC(px)); \
|
||||
return r; \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP float osl_ ##opname## _fvfvf (char *x, float y, char *px, float py) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE float osl_ ##opname## _fvfvf (char *x, float y, char *px, float py) { \
|
||||
implname impl; \
|
||||
float r; \
|
||||
impl (r, VEC(x), y, VEC(px), py); \
|
||||
@@ -320,22 +320,22 @@ OSL_SHADEOP float osl_ ##opname## _fvfvf (char *x, float y, char *px, float py)
|
||||
} \
|
||||
\
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _vff (char *r, float x, float px) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _vff (char *r, float x, float px) { \
|
||||
implname impl; \
|
||||
impl (VEC(r), x, px); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _vffff (char *r, float x, float y, float px, float py) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _vffff (char *r, float x, float y, float px, float py) { \
|
||||
implname impl; \
|
||||
impl (VEC(r), x, y, px, py); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _vvv (char *r, char *x, char *px) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _vvv (char *r, char *x, char *px) { \
|
||||
implname impl; \
|
||||
impl (VEC(r), VEC(x), VEC(px)); \
|
||||
} \
|
||||
\
|
||||
OSL_SHADEOP void osl_ ##opname## _vvfvf (char *r, char *x, float y, char *px, float py) { \
|
||||
OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _vvfvf (char *r, char *x, float y, char *px, float py) { \
|
||||
implname impl; \
|
||||
impl (VEC(r), VEC(x), y, VEC(px), py); \
|
||||
}
|
||||
@@ -483,6 +483,11 @@ PNOISE_IMPL_DERIV (psnoise, PeriodicSNoise)
|
||||
|
||||
|
||||
|
||||
// NB: We are excluding noise functions that require (u)string arguments
|
||||
// in the CUDA case, since strings are not currently well-supported
|
||||
// by the PTX backend. We will update this once string support has
|
||||
// been improved.
|
||||
|
||||
struct GaborNoise {
|
||||
GaborNoise () { }
|
||||
|
||||
@@ -609,53 +614,53 @@ PNOISE_IMPL_DERIV_OPT (gaborpnoise, GaborPNoise)
|
||||
|
||||
|
||||
struct NullNoise {
|
||||
NullNoise () { }
|
||||
inline void operator() (float &result, float x) const { result = 0.0f; }
|
||||
inline void operator() (float &result, float x, float y) const { result = 0.0f; }
|
||||
inline void operator() (float &result, const Vec3 &p) const { result = 0.0f; }
|
||||
inline void operator() (float &result, const Vec3 &p, float t) const { result = 0.0f; }
|
||||
inline void operator() (Vec3 &result, float x) const { result = v(); }
|
||||
inline void operator() (Vec3 &result, float x, float y) const { result = v(); }
|
||||
inline void operator() (Vec3 &result, const Vec3 &p) const { result = v(); }
|
||||
inline void operator() (Vec3 &result, const Vec3 &p, float t) const { result = v(); }
|
||||
inline void operator() (Dual2<float> &result, const Dual2<float> &x,
|
||||
int seed=0) const { result.set (0.0f, 0.0f, 0.0f); }
|
||||
inline void operator() (Dual2<float> &result, const Dual2<float> &x,
|
||||
const Dual2<float> &y, int seed=0) const { result.set (0.0f, 0.0f, 0.0f); }
|
||||
inline void operator() (Dual2<float> &result, const Dual2<Vec3> &p,
|
||||
int seed=0) const { result.set (0.0f, 0.0f, 0.0f); }
|
||||
inline void operator() (Dual2<float> &result, const Dual2<Vec3> &p,
|
||||
const Dual2<float> &t, int seed=0) const { result.set (0.0f, 0.0f, 0.0f); }
|
||||
inline void operator() (Dual2<Vec3> &result, const Dual2<float> &x) const { result.set (v(), v(), v()); }
|
||||
inline void operator() (Dual2<Vec3> &result, const Dual2<float> &x, const Dual2<float> &y) const { result.set (v(), v(), v()); }
|
||||
inline void operator() (Dual2<Vec3> &result, const Dual2<Vec3> &p) const { result.set (v(), v(), v()); }
|
||||
inline void operator() (Dual2<Vec3> &result, const Dual2<Vec3> &p, const Dual2<float> &t) const { result.set (v(), v(), v()); }
|
||||
inline Vec3 v () const { return Vec3(0.0f, 0.0f, 0.0f); };
|
||||
OSL_HOSTDEVICE NullNoise () { }
|
||||
OSL_HOSTDEVICE inline void operator() (float &result, float x) const { result = 0.0f; }
|
||||
OSL_HOSTDEVICE inline void operator() (float &result, float x, float y) const { result = 0.0f; }
|
||||
OSL_HOSTDEVICE inline void operator() (float &result, const Vec3 &p) const { result = 0.0f; }
|
||||
OSL_HOSTDEVICE inline void operator() (float &result, const Vec3 &p, float t) const { result = 0.0f; }
|
||||
OSL_HOSTDEVICE inline void operator() (Vec3 &result, float x) const { result = v(); }
|
||||
OSL_HOSTDEVICE inline void operator() (Vec3 &result, float x, float y) const { result = v(); }
|
||||
OSL_HOSTDEVICE inline void operator() (Vec3 &result, const Vec3 &p) const { result = v(); }
|
||||
OSL_HOSTDEVICE inline void operator() (Vec3 &result, const Vec3 &p, float t) const { result = v(); }
|
||||
OSL_HOSTDEVICE inline void operator() (Dual2<float> &result, const Dual2<float> &x,
|
||||
int seed=0) const { result.set (0.0f, 0.0f, 0.0f); }
|
||||
OSL_HOSTDEVICE inline void operator() (Dual2<float> &result, const Dual2<float> &x,
|
||||
const Dual2<float> &y, int seed=0) const { result.set (0.0f, 0.0f, 0.0f); }
|
||||
OSL_HOSTDEVICE inline void operator() (Dual2<float> &result, const Dual2<Vec3> &p,
|
||||
int seed=0) const { result.set (0.0f, 0.0f, 0.0f); }
|
||||
OSL_HOSTDEVICE inline void operator() (Dual2<float> &result, const Dual2<Vec3> &p,
|
||||
const Dual2<float> &t, int seed=0) const { result.set (0.0f, 0.0f, 0.0f); }
|
||||
OSL_HOSTDEVICE inline void operator() (Dual2<Vec3> &result, const Dual2<float> &x) const { result.set (v(), v(), v()); }
|
||||
OSL_HOSTDEVICE inline void operator() (Dual2<Vec3> &result, const Dual2<float> &x, const Dual2<float> &y) const { result.set (v(), v(), v()); }
|
||||
OSL_HOSTDEVICE inline void operator() (Dual2<Vec3> &result, const Dual2<Vec3> &p) const { result.set (v(), v(), v()); }
|
||||
OSL_HOSTDEVICE inline void operator() (Dual2<Vec3> &result, const Dual2<Vec3> &p, const Dual2<float> &t) const { result.set (v(), v(), v()); }
|
||||
OSL_HOSTDEVICE inline Vec3 v () const { return Vec3(0.0f, 0.0f, 0.0f); };
|
||||
};
|
||||
|
||||
struct UNullNoise {
|
||||
UNullNoise () { }
|
||||
inline void operator() (float &result, float x) const { result = 0.5f; }
|
||||
inline void operator() (float &result, float x, float y) const { result = 0.5f; }
|
||||
inline void operator() (float &result, const Vec3 &p) const { result = 0.5f; }
|
||||
inline void operator() (float &result, const Vec3 &p, float t) const { result = 0.5f; }
|
||||
inline void operator() (Vec3 &result, float x) const { result = v(); }
|
||||
inline void operator() (Vec3 &result, float x, float y) const { result = v(); }
|
||||
inline void operator() (Vec3 &result, const Vec3 &p) const { result = v(); }
|
||||
inline void operator() (Vec3 &result, const Vec3 &p, float t) const { result = v(); }
|
||||
inline void operator() (Dual2<float> &result, const Dual2<float> &x,
|
||||
int seed=0) const { result.set (0.5f, 0.5f, 0.5f); }
|
||||
inline void operator() (Dual2<float> &result, const Dual2<float> &x,
|
||||
const Dual2<float> &y, int seed=0) const { result.set (0.5f, 0.5f, 0.5f); }
|
||||
inline void operator() (Dual2<float> &result, const Dual2<Vec3> &p,
|
||||
int seed=0) const { result.set (0.5f, 0.5f, 0.5f); }
|
||||
inline void operator() (Dual2<float> &result, const Dual2<Vec3> &p,
|
||||
const Dual2<float> &t, int seed=0) const { result.set (0.5f, 0.5f, 0.5f); }
|
||||
inline void operator() (Dual2<Vec3> &result, const Dual2<float> &x) const { result.set (v(), v(), v()); }
|
||||
inline void operator() (Dual2<Vec3> &result, const Dual2<float> &x, const Dual2<float> &y) const { result.set (v(), v(), v()); }
|
||||
inline void operator() (Dual2<Vec3> &result, const Dual2<Vec3> &p) const { result.set (v(), v(), v()); }
|
||||
inline void operator() (Dual2<Vec3> &result, const Dual2<Vec3> &p, const Dual2<float> &t) const { result.set (v(), v(), v()); }
|
||||
inline Vec3 v () const { return Vec3(0.5f, 0.5f, 0.5f); };
|
||||
OSL_HOSTDEVICE UNullNoise () { }
|
||||
OSL_HOSTDEVICE inline void operator() (float &result, float x) const { result = 0.5f; }
|
||||
OSL_HOSTDEVICE inline void operator() (float &result, float x, float y) const { result = 0.5f; }
|
||||
OSL_HOSTDEVICE inline void operator() (float &result, const Vec3 &p) const { result = 0.5f; }
|
||||
OSL_HOSTDEVICE inline void operator() (float &result, const Vec3 &p, float t) const { result = 0.5f; }
|
||||
OSL_HOSTDEVICE inline void operator() (Vec3 &result, float x) const { result = v(); }
|
||||
OSL_HOSTDEVICE inline void operator() (Vec3 &result, float x, float y) const { result = v(); }
|
||||
OSL_HOSTDEVICE inline void operator() (Vec3 &result, const Vec3 &p) const { result = v(); }
|
||||
OSL_HOSTDEVICE inline void operator() (Vec3 &result, const Vec3 &p, float t) const { result = v(); }
|
||||
OSL_HOSTDEVICE inline void operator() (Dual2<float> &result, const Dual2<float> &x,
|
||||
int seed=0) const { result.set (0.5f, 0.5f, 0.5f); }
|
||||
OSL_HOSTDEVICE inline void operator() (Dual2<float> &result, const Dual2<float> &x,
|
||||
const Dual2<float> &y, int seed=0) const { result.set (0.5f, 0.5f, 0.5f); }
|
||||
OSL_HOSTDEVICE inline void operator() (Dual2<float> &result, const Dual2<Vec3> &p,
|
||||
int seed=0) const { result.set (0.5f, 0.5f, 0.5f); }
|
||||
OSL_HOSTDEVICE inline void operator() (Dual2<float> &result, const Dual2<Vec3> &p,
|
||||
const Dual2<float> &t, int seed=0) const { result.set (0.5f, 0.5f, 0.5f); }
|
||||
OSL_HOSTDEVICE inline void operator() (Dual2<Vec3> &result, const Dual2<float> &x) const { result.set (v(), v(), v()); }
|
||||
OSL_HOSTDEVICE inline void operator() (Dual2<Vec3> &result, const Dual2<float> &x, const Dual2<float> &y) const { result.set (v(), v(), v()); }
|
||||
OSL_HOSTDEVICE inline void operator() (Dual2<Vec3> &result, const Dual2<Vec3> &p) const { result.set (v(), v(), v()); }
|
||||
OSL_HOSTDEVICE inline void operator() (Dual2<Vec3> &result, const Dual2<Vec3> &p, const Dual2<float> &t) const { result.set (v(), v(), v()); }
|
||||
OSL_HOSTDEVICE inline Vec3 v () const { return Vec3(0.5f, 0.5f, 0.5f); };
|
||||
};
|
||||
|
||||
NOISE_IMPL (nullnoise, NullNoise)
|
||||
@@ -876,36 +881,36 @@ osl_count_noise (void *sg_)
|
||||
|
||||
|
||||
|
||||
OSL_SHADEOP int
|
||||
OSL_SHADEOP OSL_HOSTDEVICE int
|
||||
osl_hash_ii (int x)
|
||||
{
|
||||
return inthashi (x);
|
||||
}
|
||||
|
||||
OSL_SHADEOP int
|
||||
OSL_SHADEOP OSL_HOSTDEVICE int
|
||||
osl_hash_if (float x)
|
||||
{
|
||||
return inthashf (x);
|
||||
}
|
||||
|
||||
OSL_SHADEOP int
|
||||
OSL_SHADEOP OSL_HOSTDEVICE int
|
||||
osl_hash_iff (float x, float y)
|
||||
{
|
||||
return inthashf (x, y);
|
||||
}
|
||||
|
||||
|
||||
OSL_SHADEOP int
|
||||
osl_hash_iv (float *x)
|
||||
OSL_SHADEOP OSL_HOSTDEVICE int
|
||||
osl_hash_iv (void *x)
|
||||
{
|
||||
return inthashf (x);
|
||||
return inthashf (static_cast<float*>(x));
|
||||
}
|
||||
|
||||
|
||||
OSL_SHADEOP int
|
||||
osl_hash_ivf (float *x, float y)
|
||||
OSL_SHADEOP OSL_HOSTDEVICE int
|
||||
osl_hash_ivf (void *x, float y)
|
||||
{
|
||||
return inthashf (x, y);
|
||||
return inthashf (static_cast<float*>(x), y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -259,7 +259,7 @@ osl_texture (void *sg_, const char *name, void *handle,
|
||||
// and ensure that they're being put in aligned memory.
|
||||
OIIO::simd::float4 result_simd, dresultds_simd, dresultdt_simd;
|
||||
bool ok = sg->renderer->texture (USTR(name),
|
||||
(TextureSystem::TextureHandle *)handle, NULL,
|
||||
(TextureSystem::TextureHandle *)handle, sg->context->texture_thread_info(),
|
||||
*opt, sg, s, t, dsdx, dtdx, dsdy, dtdy, 4,
|
||||
(float *)&result_simd,
|
||||
derivs ? (float *)&dresultds_simd : NULL,
|
||||
@@ -294,18 +294,15 @@ osl_texture (void *sg_, const char *name, void *handle,
|
||||
|
||||
OSL_SHADEOP int
|
||||
osl_texture3d (void *sg_, const char *name, void *handle,
|
||||
void *opt_, void *P_,
|
||||
void *dPdx_, void *dPdy_, void *dPdz_, int chans,
|
||||
void *result, void *dresultdx,
|
||||
void *dresultdy, void *dresultdz,
|
||||
void *alpha, void *dalphadx,
|
||||
void *dalphady, void *dalphadz,
|
||||
void *opt_, void *P_, void *dPdx_, void *dPdy_,
|
||||
int chans,
|
||||
void *result, void *dresultdx, void *dresultdy,
|
||||
void *alpha , void *dalphadx , void *dalphady ,
|
||||
ustring *errormessage)
|
||||
{
|
||||
const Vec3 &P (*(Vec3 *)P_);
|
||||
const Vec3 &dPdx (*(Vec3 *)dPdx_);
|
||||
const Vec3 &dPdy (*(Vec3 *)dPdy_);
|
||||
const Vec3 &dPdz (*(Vec3 *)dPdz_);
|
||||
ShaderGlobals *sg = (ShaderGlobals *)sg_;
|
||||
TextureOpt *opt = (TextureOpt *)opt_;
|
||||
bool derivs = (dresultdx != NULL || dalphadx != NULL);
|
||||
@@ -313,12 +310,12 @@ osl_texture3d (void *sg_, const char *name, void *handle,
|
||||
// and ensure that they're being put in aligned memory.
|
||||
OIIO::simd::float4 result_simd, dresultds_simd, dresultdt_simd, dresultdr_simd;
|
||||
bool ok = sg->renderer->texture3d (USTR(name),
|
||||
(TextureSystem::TextureHandle *)handle, NULL,
|
||||
*opt, sg, P, dPdx, dPdy, dPdz,
|
||||
(TextureSystem::TextureHandle *)handle, sg->context->texture_thread_info(),
|
||||
*opt, sg, P, dPdx, dPdy, Vec3(0),
|
||||
4, (float *)&result_simd,
|
||||
derivs ? (float *)&dresultds_simd : NULL,
|
||||
derivs ? (float *)&dresultdt_simd : NULL,
|
||||
derivs ? (float *)&dresultdr_simd : NULL,
|
||||
derivs ? (float *)&dresultds_simd : nullptr,
|
||||
derivs ? (float *)&dresultdt_simd : nullptr,
|
||||
derivs ? (float *)&dresultdr_simd : nullptr,
|
||||
errormessage);
|
||||
|
||||
for (int i = 0; i < chans; ++i)
|
||||
@@ -330,19 +327,15 @@ osl_texture3d (void *sg_, const char *name, void *handle,
|
||||
if (derivs) {
|
||||
OIIO::simd::float4 dresultdx_simd = dresultds_simd * dPdx[0] + dresultdt_simd * dPdx[1] + dresultdr_simd * dPdx[2];
|
||||
OIIO::simd::float4 dresultdy_simd = dresultds_simd * dPdy[0] + dresultdt_simd * dPdy[1] + dresultdr_simd * dPdy[2];
|
||||
OIIO::simd::float4 dresultdz_simd = dresultds_simd * dPdz[0] + dresultdt_simd * dPdz[1] + dresultdr_simd * dPdz[2];
|
||||
if (dresultdx) {
|
||||
for (int i = 0; i < chans; ++i)
|
||||
((float *)dresultdx)[i] = dresultdx_simd[i];
|
||||
for (int i = 0; i < chans; ++i)
|
||||
((float *)dresultdy)[i] = dresultdy_simd[i];
|
||||
for (int i = 0; i < chans; ++i)
|
||||
((float *)dresultdz)[i] = dresultdz_simd[i];
|
||||
}
|
||||
if (dalphadx) {
|
||||
((float *)dalphadx)[0] = dresultdx_simd[chans];
|
||||
((float *)dalphady)[0] = dresultdy_simd[chans];
|
||||
((float *)dalphadz)[0] = dresultdz_simd[chans];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,7 +364,7 @@ osl_environment (void *sg_, const char *name, void *handle,
|
||||
OIIO::simd::float4 local_result;
|
||||
bool ok = sg->renderer->environment (USTR(name),
|
||||
(TextureSystem::TextureHandle *)handle,
|
||||
NULL, *opt, sg, R, dRdx, dRdy, 4,
|
||||
sg->context->texture_thread_info(), *opt, sg, R, dRdx, dRdy, 4,
|
||||
(float *)&local_result, NULL, NULL,
|
||||
errormessage);
|
||||
|
||||
|
||||
+11
-35
@@ -48,11 +48,11 @@ string_view
|
||||
shadertypename (ShaderType s)
|
||||
{
|
||||
switch (s) {
|
||||
case ShadTypeGeneric: return ("shader");
|
||||
case ShadTypeSurface: return ("surface");
|
||||
case ShadTypeDisplacement: return ("displacement");
|
||||
case ShadTypeVolume: return ("volume");
|
||||
case ShadTypeLight: return ("light");
|
||||
case ShaderType::Generic : return ("shader");
|
||||
case ShaderType::Surface : return ("surface");
|
||||
case ShaderType::Displacement : return ("displacement");
|
||||
case ShaderType::Volume : return ("volume");
|
||||
case ShaderType::Light : return ("light");
|
||||
default:
|
||||
ASSERT (0 && "Invalid shader type");
|
||||
}
|
||||
@@ -64,40 +64,16 @@ ShaderType
|
||||
shadertype_from_name (string_view name)
|
||||
{
|
||||
if (name == "shader" || name == "generic")
|
||||
return ShadTypeGeneric;
|
||||
return ShaderType::Generic;
|
||||
if (name == "surface")
|
||||
return ShadTypeSurface;
|
||||
return ShaderType::Surface;
|
||||
if (name == "displacement")
|
||||
return ShadTypeDisplacement;
|
||||
return ShaderType::Displacement;
|
||||
if (name == "volume")
|
||||
return ShadTypeVolume;
|
||||
return ShaderType::Volume;
|
||||
if (name == "light")
|
||||
return ShadTypeLight;
|
||||
return ShadTypeUnknown;
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
shaderusename (ShaderUse s)
|
||||
{
|
||||
switch (s) {
|
||||
case ShadUseSurface: return ("surface");
|
||||
case ShadUseDisplacement: return ("displacement");
|
||||
default:
|
||||
ASSERT (0 && "Invalid shader use");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
ShaderUse
|
||||
shaderuse_from_name (string_view name)
|
||||
{
|
||||
if (name == "surface")
|
||||
return ShadUseSurface;
|
||||
if (name == "displacement")
|
||||
return ShadUseDisplacement;
|
||||
return ShadUseLast;
|
||||
return ShaderType::Light;
|
||||
return ShaderType::Unknown;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,6 +39,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <boost/thread/tss.hpp> /* for thread_specific_ptr */
|
||||
|
||||
// Pull in the modified Imath headers and the OSL_HOSTDEVICE macro
|
||||
#ifdef __CUDACC__
|
||||
#include <OSL/oslconfig.h>
|
||||
#endif
|
||||
|
||||
#include <OpenImageIO/ustring.h>
|
||||
#include <OpenImageIO/thread.h>
|
||||
#include <OpenImageIO/paramlist.h>
|
||||
@@ -191,14 +196,20 @@ expand (std::vector<T> &vec, size_t size)
|
||||
// Struct to hold records about what user data a group needs
|
||||
struct UserDataNeeded {
|
||||
ustring name;
|
||||
int layer_num;
|
||||
TypeDesc type;
|
||||
void* data;
|
||||
bool derivs;
|
||||
|
||||
UserDataNeeded (ustring name, TypeDesc type, bool derivs=false)
|
||||
: name(name), type(type), derivs(derivs) {}
|
||||
UserDataNeeded (ustring name, int layer_num, TypeDesc type, void* data=NULL,
|
||||
bool derivs=false)
|
||||
: name(name), layer_num(layer_num), type(type), data(data),
|
||||
derivs(derivs) {}
|
||||
friend bool operator< (const UserDataNeeded &a, const UserDataNeeded &b) {
|
||||
if (a.name != b.name)
|
||||
return a.name < b.name;
|
||||
if (a.layer_num != b.layer_num )
|
||||
return a.layer_num < b.layer_num;
|
||||
if (a.type.basetype != b.type.basetype)
|
||||
return a.type.basetype < b.type.basetype;
|
||||
if (a.type.aggregate != b.type.aggregate)
|
||||
@@ -506,9 +517,8 @@ public:
|
||||
bool Parameter (string_view name, TypeDesc t, const void *val);
|
||||
bool Parameter (string_view name, TypeDesc t, const void *val,
|
||||
bool lockgeom);
|
||||
bool Shader (string_view shaderusage,
|
||||
string_view shadername = string_view(),
|
||||
string_view layername = string_view());
|
||||
bool Shader (string_view shaderusage, string_view shadername,
|
||||
string_view layername);
|
||||
ShaderGroupRef ShaderGroupBegin (string_view groupname = string_view());
|
||||
bool ShaderGroupEnd (void);
|
||||
bool ConnectShaders (string_view srclayer, string_view srcparam,
|
||||
@@ -522,7 +532,6 @@ public:
|
||||
|
||||
// Internal error, warning, info, and message reporting routines that
|
||||
// take printf-like arguments.
|
||||
#if OIIO_VERSION >= 10803
|
||||
template<typename T1, typename... Args>
|
||||
inline void error (string_view fmt, const T1& v1, const Args&... args) const {
|
||||
error (Strutil::format (fmt, v1, args...));
|
||||
@@ -546,20 +555,6 @@ public:
|
||||
message (Strutil::format (fmt, v1, args...));
|
||||
}
|
||||
void message (const std::string &message) const;
|
||||
#else
|
||||
TINYFORMAT_WRAP_FORMAT (void, error, const,
|
||||
std::ostringstream msg;, msg, error(msg.str());)
|
||||
TINYFORMAT_WRAP_FORMAT (void, warning, const,
|
||||
std::ostringstream msg;, msg, warning(msg.str());)
|
||||
TINYFORMAT_WRAP_FORMAT (void, info, const,
|
||||
std::ostringstream msg;, msg, info(msg.str());)
|
||||
TINYFORMAT_WRAP_FORMAT (void, message, const,
|
||||
std::ostringstream msg;, msg, message(msg.str());)
|
||||
void error (const std::string &message) const;
|
||||
void warning (const std::string &message) const;
|
||||
void info (const std::string &message) const;
|
||||
void message (const std::string &message) const;
|
||||
#endif
|
||||
|
||||
std::string getstats (int level=1) const;
|
||||
|
||||
@@ -609,6 +604,7 @@ public:
|
||||
int llvm_debug () const { return m_llvm_debug; }
|
||||
int llvm_debug_layers () const { return m_llvm_debug_layers; }
|
||||
int llvm_debug_ops () const { return m_llvm_debug_ops; }
|
||||
int llvm_output_bitcode () const { return m_llvm_output_bitcode; }
|
||||
bool fold_getattribute () const { return m_opt_fold_getattribute; }
|
||||
bool opt_texture_handle () const { return m_opt_texture_handle; }
|
||||
int opt_passes() const { return m_opt_passes; }
|
||||
@@ -620,6 +616,7 @@ public:
|
||||
bool no_noise() const { return m_no_noise; }
|
||||
bool no_pointcloud() const { return m_no_pointcloud; }
|
||||
bool force_derivs() const { return m_force_derivs; }
|
||||
bool allow_shader_replacement() const { return m_allow_shader_replacement; }
|
||||
ustring commonspace_synonym () const { return m_commonspace_synonym; }
|
||||
|
||||
ustring debug_groupname() const { return m_debug_groupname; }
|
||||
@@ -633,7 +630,7 @@ public:
|
||||
/// The group is set and won't be changed again; take advantage of
|
||||
/// this by optimizing the code knowing all our instance parameters
|
||||
/// (at least the ones that can't be overridden by the geometry).
|
||||
void optimize_group (ShaderGroup &group);
|
||||
void optimize_group (ShaderGroup &group, ShadingContext *ctx = nullptr);
|
||||
|
||||
/// After doing all optimization and code JIT, we can clean up by
|
||||
/// deleting the instances' code and arguments, and paring their
|
||||
@@ -758,6 +755,9 @@ private:
|
||||
|
||||
OpDescriptorMap m_op_descriptor;
|
||||
|
||||
// Pre-compiled support library
|
||||
std::vector<char> m_lib_bitcode; ///> Container for the pre-compiled library bitcode
|
||||
|
||||
// Options
|
||||
int m_statslevel; ///< Statistics level
|
||||
bool m_lazylayers; ///< Evaluate layers on demand?
|
||||
@@ -770,6 +770,7 @@ private:
|
||||
bool m_debug_uninit; ///< Find use of uninitialized vars?
|
||||
bool m_lockgeom_default; ///< Default value of lockgeom
|
||||
bool m_strict_messages; ///< Strict checking of message passing usage?
|
||||
bool m_error_repeats; ///< Allow repeats of identical err/warn?
|
||||
bool m_range_checking; ///< Range check arrays & components?
|
||||
bool m_unknown_coordsys_error; ///< Error to use unknown xform name?
|
||||
bool m_connection_error; ///< Error for ConnectShaders to fail?
|
||||
@@ -801,6 +802,7 @@ private:
|
||||
int m_llvm_debug; ///< More LLVM debugging output
|
||||
int m_llvm_debug_layers; ///< Add layer enter/exit printfs
|
||||
int m_llvm_debug_ops; ///< Add printfs to every op
|
||||
int m_llvm_output_bitcode; ///< Output bitcode for each group
|
||||
ustring m_debug_groupname; ///< Name of sole group to debug
|
||||
ustring m_debug_layername; ///< Name of sole layer to debug
|
||||
ustring m_opt_layername; ///< Name of sole layer to optimize
|
||||
@@ -819,6 +821,7 @@ private:
|
||||
bool m_no_noise; ///< Substitute trivial noise calls
|
||||
bool m_no_pointcloud; ///< Substitute trivial pointcloud calls
|
||||
bool m_force_derivs; ///< Force derivs on everything
|
||||
bool m_allow_shader_replacement; ///< Allow shader masters to replace
|
||||
int m_exec_repeat; ///< How many times to execute group
|
||||
|
||||
// Derived/cached calculations from options:
|
||||
@@ -832,7 +835,7 @@ private:
|
||||
|
||||
// State
|
||||
bool m_in_group; ///< Are we specifying a group?
|
||||
ShaderUse m_group_use; ///< Use of group
|
||||
std::string m_group_use; ///< "Use" of group
|
||||
ParamValueList m_pending_params; ///< Pending Parameter() values
|
||||
ShaderGroupRef m_curgroup; ///< Current shading attribute state
|
||||
mutable mutex m_mutex; ///< Thread safety
|
||||
@@ -946,6 +949,9 @@ struct ConnectedParam {
|
||||
bool is_complete () const {
|
||||
return arrayindex == -1 && channel == -1;
|
||||
}
|
||||
|
||||
// Debug output of ConnectedParam
|
||||
std::string str (const ShaderInstance *inst);
|
||||
};
|
||||
|
||||
|
||||
@@ -967,6 +973,12 @@ struct Connection {
|
||||
bool operator!= (const Connection &c) const {
|
||||
return srclayer != c.srclayer || src != c.src || dst != c.dst;
|
||||
}
|
||||
|
||||
// Does the connection fully join the source and destination.
|
||||
bool is_complete () const { return src.is_complete() && dst.is_complete(); }
|
||||
|
||||
// Debug output of ConnectedParam
|
||||
std::string str (const ShaderGroup &group, const ShaderInstance *dstinst);
|
||||
};
|
||||
|
||||
|
||||
@@ -1312,6 +1324,13 @@ public:
|
||||
m_current_block = 0;
|
||||
}
|
||||
|
||||
// avoid 'attempting to reference a deleted function' of std::unique_ptr<char>s
|
||||
// in reference to those member variables of ShadingContext
|
||||
SimplePool(const SimplePool &) = delete;
|
||||
SimplePool(SimplePool &&) = delete;
|
||||
SimplePool &operator=(const SimplePool &) = delete;
|
||||
SimplePool &&operator=(SimplePool &&) = delete;
|
||||
|
||||
~SimplePool() {}
|
||||
|
||||
char * alloc(size_t size, size_t alignment=1) {
|
||||
@@ -1543,36 +1562,43 @@ private:
|
||||
// Put all the things that are read-only (after optimization) and
|
||||
// needed on every shade execution at the front of the struct, as much
|
||||
// together on one cache line as possible.
|
||||
volatile int m_optimized; ///< Is it already optimized?
|
||||
bool m_does_nothing; ///< Is the shading group just func() { return; }
|
||||
size_t m_llvm_groupdata_size; ///< Heap size needed for its groupdata
|
||||
volatile int m_optimized = 0; ///< Is it already optimized?
|
||||
bool m_does_nothing = false; ///< Is the shading group just func() { return; }
|
||||
size_t m_llvm_groupdata_size = 0;///< Heap size needed for its groupdata
|
||||
int m_id; ///< Unique ID for the group
|
||||
int m_num_entry_layers; ///< Number of marked entry layers
|
||||
RunLLVMGroupFunc m_llvm_compiled_version;
|
||||
RunLLVMGroupFunc m_llvm_compiled_init;
|
||||
int m_num_entry_layers = 0; ///< Number of marked entry layers
|
||||
RunLLVMGroupFunc m_llvm_compiled_version = nullptr;
|
||||
RunLLVMGroupFunc m_llvm_compiled_init = nullptr;
|
||||
std::vector<RunLLVMGroupFunc> m_llvm_compiled_layers;
|
||||
std::vector<ShaderInstanceRef> m_layers;
|
||||
ustring m_name;
|
||||
int m_exec_repeat; ///< How many times to execute group
|
||||
int m_raytype_queries; ///< Bitmask of raytypes queried
|
||||
int m_raytypes_on; ///< Bitmask of raytypes we assume to be on
|
||||
int m_raytypes_off; ///< Bitmask of raytypes we assume to be off
|
||||
int m_exec_repeat = 1; ///< How many times to execute group
|
||||
int m_raytype_queries = -1; ///< Bitmask of raytypes queried
|
||||
int m_raytypes_on = 0; ///< Bitmask of raytypes we assume to be on
|
||||
int m_raytypes_off = 0; ///< Bitmask of raytypes we assume to be off
|
||||
mutable mutex m_mutex; ///< Thread-safe optimization
|
||||
int m_globals_read = 0;
|
||||
int m_globals_write = 0;
|
||||
std::vector<ustring> m_textures_needed;
|
||||
std::vector<ustring> m_closures_needed;
|
||||
std::vector<ustring> m_globals_needed;
|
||||
std::vector<ustring> m_globals_needed; // semi-deprecated
|
||||
std::vector<ustring> m_userdata_names;
|
||||
std::vector<TypeDesc> m_userdata_types;
|
||||
std::vector<int> m_userdata_offsets;
|
||||
std::vector<char> m_userdata_derivs;
|
||||
std::vector<int> m_userdata_layers;
|
||||
std::vector<void*> m_userdata_init_vals;
|
||||
std::vector<ustring> m_attributes_needed;
|
||||
std::vector<ustring> m_attribute_scopes;
|
||||
std::vector<ustring> m_renderer_outputs; ///< Names of renderer outputs
|
||||
bool m_unknown_textures_needed;
|
||||
bool m_unknown_closures_needed;
|
||||
bool m_unknown_attributes_needed;
|
||||
atomic_ll m_executions; ///< Number of times the group executed
|
||||
atomic_ll m_stat_total_shading_time_ticks; ///< Total shading time (ticks)
|
||||
atomic_ll m_executions {0}; ///< Number of times the group executed
|
||||
atomic_ll m_stat_total_shading_time_ticks {0}; ///< Total shading time (ticks)
|
||||
|
||||
// PTX assembly for compiled ShaderGroup
|
||||
std::string m_llvm_ptx_compiled_version;
|
||||
|
||||
friend class OSL::pvt::ShadingSystemImpl;
|
||||
friend class OSL::pvt::BackendLLVM;
|
||||
@@ -1614,7 +1640,7 @@ public:
|
||||
|
||||
ClosureComponent * closure_component_allot(int id, size_t prim_size, const Color3 &w) {
|
||||
// Allocate the component and the mul back to back
|
||||
size_t needed = sizeof(ClosureComponent) - sizeof(void*) + prim_size;
|
||||
size_t needed = sizeof(ClosureComponent) + prim_size;
|
||||
ClosureComponent *comp = (ClosureComponent *) m_closure_pool.alloc(needed, alignof(ClosureComponent));
|
||||
comp->id = id;
|
||||
comp->w = w;
|
||||
@@ -1687,10 +1713,6 @@ public:
|
||||
/// attribname is "", return the value of the node itself.
|
||||
int dict_value (int nodeID, ustring attribname, TypeDesc type, void *data);
|
||||
|
||||
/// Various setup of the context done by execute(). Return true if
|
||||
/// the function should be executed, otherwise false.
|
||||
bool prepare_execution (ShaderUse use, ShaderGroup &sas);
|
||||
|
||||
bool osl_get_attribute (ShaderGlobals *sg, void *objdata, int dest_derivs,
|
||||
ustring obj_name, ustring attr_name,
|
||||
int array_lookup, int index,
|
||||
@@ -1760,7 +1782,6 @@ public:
|
||||
// Process all the recorded errors, warnings, printfs
|
||||
void process_errors () const;
|
||||
|
||||
#if OIIO_VERSION >= 10803
|
||||
template<typename... Args>
|
||||
inline void error (string_view fmt, const Args&... args) const {
|
||||
record_error(ErrorHandler::EH_ERROR, Strutil::format (fmt, args...));
|
||||
@@ -1780,20 +1801,6 @@ public:
|
||||
inline void message (string_view fmt, const Args&... args) const {
|
||||
record_error(ErrorHandler::EH_MESSAGE, Strutil::format (fmt, args...));
|
||||
}
|
||||
#else
|
||||
TINYFORMAT_WRAP_FORMAT (void, error, const,
|
||||
std::ostringstream msg;, msg,
|
||||
record_error(ErrorHandler::EH_ERROR, msg.str());)
|
||||
TINYFORMAT_WRAP_FORMAT (void, warning, const,
|
||||
std::ostringstream msg;, msg,
|
||||
record_error(ErrorHandler::EH_WARNING, msg.str());)
|
||||
TINYFORMAT_WRAP_FORMAT (void, info, const,
|
||||
std::ostringstream msg;, msg,
|
||||
record_error(ErrorHandler::EH_INFO, msg.str());)
|
||||
TINYFORMAT_WRAP_FORMAT (void, message, const,
|
||||
std::ostringstream msg;, msg,
|
||||
record_error(ErrorHandler::EH_MESSAGE, msg.str());)
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
@@ -1845,14 +1852,6 @@ private:
|
||||
// Buffering of error messages and printfs
|
||||
typedef std::pair<ErrorHandler::ErrCode, std::string> ErrorItem;
|
||||
mutable std::vector<ErrorItem> m_buffered_errors;
|
||||
|
||||
// Calculate offset needed to align ClosureComponent's mem to a given alignment.
|
||||
inline size_t closure_alignment_offset_calc(size_t alignment) {
|
||||
return alignment == 1
|
||||
? 0
|
||||
: alignment - (reckless_offsetof(ClosureComponent, mem) & (alignment - 1));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1996,6 +1995,16 @@ public:
|
||||
return m_bblockids[opnum];
|
||||
}
|
||||
|
||||
// Mangle the group and layer into a unique function name
|
||||
std::string layer_function_name (const ShaderGroup &group,
|
||||
const ShaderInstance &inst) {
|
||||
return Strutil::format ("%s_%s_%d", group.name(),
|
||||
inst.layername(), inst.id());
|
||||
}
|
||||
std::string layer_function_name () {
|
||||
return layer_function_name (group(), *inst());
|
||||
}
|
||||
|
||||
protected:
|
||||
ShadingSystemImpl &m_shadingsys; ///< Backpointer to shading system
|
||||
ShaderGroup &m_group; ///< Group we're processing
|
||||
|
||||
@@ -117,6 +117,12 @@ using namespace OSL::pvt;
|
||||
#define isatty _isatty
|
||||
#endif
|
||||
|
||||
// flex itself will generate fatal warnings about signed vs unsigned.
|
||||
// Bypass that nonsense.
|
||||
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 6
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
#endif
|
||||
|
||||
%}
|
||||
|
||||
/* Declare modes */
|
||||
|
||||
@@ -91,7 +91,7 @@ struct SortedPointCompare {
|
||||
PointCloud *
|
||||
PointCloud::get (ustring filename, bool write)
|
||||
{
|
||||
if (! filename)
|
||||
if (filename.empty())
|
||||
return NULL;
|
||||
spin_lock lock (pointcloudmap_mutex);
|
||||
PointCloudMap::const_iterator found = pointclouds.find(filename);
|
||||
@@ -139,7 +139,7 @@ PointCloud::PointCloud (ustring filename,
|
||||
PointCloud::~PointCloud ()
|
||||
{
|
||||
// Save the file if we wrote to it
|
||||
if (m_write && m_filename)
|
||||
if (m_write && !m_filename.empty())
|
||||
Partio::write (m_filename.c_str(), *m_partio_cloud);
|
||||
if (m_partio_cloud)
|
||||
m_partio_cloud->release ();
|
||||
@@ -238,7 +238,7 @@ RendererServices::pointcloud_search (ShaderGlobals *sg,
|
||||
float *out_distances, int derivs_offset)
|
||||
{
|
||||
#if USE_PARTIO
|
||||
if (! filename)
|
||||
if (filename.empty())
|
||||
return 0;
|
||||
PointCloud *pc = PointCloud::get(filename);
|
||||
if (pc == NULL) { // The file failed to load
|
||||
@@ -408,7 +408,7 @@ RendererServices::pointcloud_write (ShaderGlobals *sg,
|
||||
const void **data)
|
||||
{
|
||||
#if USE_PARTIO
|
||||
if (! filename)
|
||||
if (filename.empty())
|
||||
return false;
|
||||
PointCloud *pc = PointCloud::get(filename, true /* create file to write */);
|
||||
spin_lock lock (pc->m_mutex);
|
||||
|
||||
@@ -184,7 +184,7 @@ RendererServices::texture (ustring filename, TextureHandle *texture_handle,
|
||||
|
||||
|
||||
|
||||
// Deprecated version
|
||||
// Deprecated version (1.8)
|
||||
bool
|
||||
RendererServices::texture (ustring filename, TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
@@ -256,7 +256,7 @@ RendererServices::texture3d (ustring filename, TextureHandle *texture_handle,
|
||||
|
||||
|
||||
|
||||
// Deprecated version
|
||||
// Deprecated version (1.8)
|
||||
bool
|
||||
RendererServices::texture3d (ustring filename, TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
@@ -327,7 +327,7 @@ RendererServices::environment (ustring filename, TextureHandle *texture_handle,
|
||||
|
||||
|
||||
|
||||
// Deprecated version
|
||||
// Deprecated version (1.8)
|
||||
bool
|
||||
RendererServices::environment (ustring filename, TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
|
||||
@@ -125,7 +125,7 @@ RuntimeOptimizer::RuntimeOptimizer (ShadingSystemImpl &shadingsys,
|
||||
m_stop_optimizing(false),
|
||||
m_raytypes_on(group.raytypes_on()), m_raytypes_off(group.raytypes_off())
|
||||
{
|
||||
memset (&m_shaderglobals, 0, sizeof(ShaderGlobals));
|
||||
memset ((char *)&m_shaderglobals, 0, sizeof(ShaderGlobals));
|
||||
m_shaderglobals.context = shadingcontext();
|
||||
}
|
||||
|
||||
@@ -169,15 +169,15 @@ OSOProcessorBase::set_debug ()
|
||||
|
||||
// If either group or layer was specified for debug, surely they want
|
||||
// debugging turned on.
|
||||
if (shadingsys().debug_groupname() || shadingsys().debug_layername())
|
||||
if (!shadingsys().debug_groupname().empty() || !shadingsys().debug_layername().empty())
|
||||
m_debug = std::max (m_debug, 1);
|
||||
|
||||
// Force debugging off if a specific group was selected for debug
|
||||
// and we're not it, or a specific layer was selected for debug and
|
||||
// we're not it.
|
||||
bool wronggroup = (shadingsys().debug_groupname() &&
|
||||
bool wronggroup = (!shadingsys().debug_groupname().empty() &&
|
||||
shadingsys().debug_groupname() != group().name());
|
||||
bool wronglayer = (shadingsys().debug_layername() && inst() &&
|
||||
bool wronglayer = (!shadingsys().debug_layername().empty() && inst() &&
|
||||
shadingsys().debug_layername() != inst()->layername());
|
||||
if (wronggroup || wronglayer)
|
||||
m_debug = 0;
|
||||
@@ -192,7 +192,7 @@ RuntimeOptimizer::set_debug ()
|
||||
|
||||
// If a specific group is isolated for debugging and the
|
||||
// 'optimize_dondebug' flag is on, fully optimize all other groups.
|
||||
if (shadingsys().debug_groupname() &&
|
||||
if (!shadingsys().debug_groupname().empty() &&
|
||||
shadingsys().debug_groupname() != group().name()) {
|
||||
if (shadingsys().m_optimize_nondebug) {
|
||||
// Debugging trick: if user said to only debug one group, turn
|
||||
@@ -921,12 +921,19 @@ RuntimeOptimizer::simplify_params ()
|
||||
// It's connected to an earlier layer. If the output var of
|
||||
// the upstream shader is effectively constant or a global,
|
||||
// then so is this variable.
|
||||
turn_into_nop (s->initbegin(), s->initend(),
|
||||
"connected value doesn't need init ops");
|
||||
for (auto&& c : inst()->connections()) {
|
||||
if (c.dst.param == i) {
|
||||
if (c.dst.param != i)
|
||||
continue;
|
||||
if (c.dst.is_complete()) {
|
||||
/// All components are being set through either
|
||||
/// float->triple or triple->triple
|
||||
/// Get rid of the un-needed init ops.
|
||||
turn_into_nop (s->initbegin(), s->initend(),
|
||||
"connected value doesn't need init ops");
|
||||
}
|
||||
if (c.is_complete()) {
|
||||
// srcsym is the earlier group's output param, which
|
||||
// is connected as the input to the param we're
|
||||
// is fully connected as the input to the param we're
|
||||
// examining.
|
||||
ShaderInstance *uplayer = group()[c.srclayer];
|
||||
Symbol *srcsym = uplayer->symbol(c.src.param);
|
||||
@@ -938,8 +945,7 @@ RuntimeOptimizer::simplify_params ()
|
||||
// If so, make sure the global is in this instance's
|
||||
// symbol table, and alias the parameter to it.
|
||||
ustringmap_t &g (m_params_holding_globals[c.srclayer]);
|
||||
ustringmap_t::const_iterator f;
|
||||
f = g.find (srcsym->name());
|
||||
auto f = g.find (srcsym->name());
|
||||
if (f != g.end()) {
|
||||
if (debug() > 1)
|
||||
debug_opt ("Remapping %s.%s because it's connected to "
|
||||
@@ -972,6 +978,20 @@ RuntimeOptimizer::simplify_params ()
|
||||
}
|
||||
}
|
||||
}
|
||||
// FIXME / N.B.: We only optimize "fully complete" connections,
|
||||
// not those involving individual components or array elements
|
||||
// of the connected parameters, because we sure don't track the
|
||||
// constness or aliasing of individual components/element, only
|
||||
// whole variables. But there are two cases where the logic
|
||||
// above fails to fully exploit the connection propagating a
|
||||
// constant value. (a) Partial-to-whole connections, for example
|
||||
// connecting one component of an upstream triple output to a
|
||||
// downstream float input, should propagate the constant, but we
|
||||
// currently neglect this case. (b) If *multiple* conections
|
||||
// combine to fully propagate values, for example if someone was
|
||||
// foolish enough to connect R, G, and B components of color
|
||||
// parameters *separately*, we sure don't notice that and treat
|
||||
// it as a full connection of the color.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2250,7 +2270,7 @@ void
|
||||
RuntimeOptimizer::optimize_instance ()
|
||||
{
|
||||
// If "opt_layername" attribute is set, only optimize the named layer
|
||||
if (shadingsys().m_opt_layername &&
|
||||
if (!shadingsys().m_opt_layername.empty() &&
|
||||
shadingsys().m_opt_layername != inst()->layername())
|
||||
return;
|
||||
|
||||
@@ -3129,6 +3149,8 @@ RuntimeOptimizer::run ()
|
||||
m_unknown_attributes_needed = false;
|
||||
m_textures_needed.clear();
|
||||
m_closures_needed.clear();
|
||||
m_globals_read = 0;
|
||||
m_globals_write = 0;
|
||||
m_globals_needed.clear();
|
||||
m_userdata_needed.clear();
|
||||
m_attributes_needed.clear();
|
||||
@@ -3143,7 +3165,8 @@ RuntimeOptimizer::run ()
|
||||
// Find interpolated parameters
|
||||
if ((s.symtype() == SymTypeParam || s.symtype() == SymTypeOutputParam)
|
||||
&& ! s.lockgeom()) {
|
||||
UserDataNeeded udn (s.name(), s.typespec().simpletype(), s.has_derivs());
|
||||
UserDataNeeded udn (s.name(), layer, s.typespec().simpletype(),
|
||||
s.data(), s.has_derivs());
|
||||
std::set<UserDataNeeded>::iterator found;
|
||||
found = m_userdata_needed.find (udn);
|
||||
if (found == m_userdata_needed.end())
|
||||
@@ -3156,6 +3179,11 @@ RuntimeOptimizer::run ()
|
||||
// Track which globals the group needs
|
||||
if (s.symtype() == SymTypeGlobal) {
|
||||
m_globals_needed.insert (s.name());
|
||||
int bit = int(ShadingSystem::globals_bit (s.name()));
|
||||
if (s.everread())
|
||||
m_globals_read |= bit;
|
||||
if (s.everwritten())
|
||||
m_globals_write |= bit;
|
||||
}
|
||||
if (s.has_derivs())
|
||||
++new_deriv_syms;
|
||||
|
||||
@@ -154,16 +154,11 @@ public:
|
||||
int turn_into_nop (int begin, int end, string_view why=NULL);
|
||||
|
||||
void debug_opt_impl (string_view message) const;
|
||||
#if OIIO_VERSION >= 10803
|
||||
|
||||
template<typename... Args>
|
||||
inline void debug_opt (string_view fmt, const Args&... args) const {
|
||||
debug_opt_impl (Strutil::format (fmt, args...));
|
||||
}
|
||||
#else
|
||||
TINYFORMAT_WRAP_FORMAT (void, debug_opt, const,
|
||||
std::ostringstream msg;, msg,
|
||||
debug_opt_impl(msg.str());)
|
||||
#endif
|
||||
|
||||
void debug_opt_ops (int opbegin, int opend, string_view message) const;
|
||||
void debug_turn_into (const Opcode &op, int numops,
|
||||
@@ -447,6 +442,8 @@ private:
|
||||
std::set<ustring> m_textures_needed;
|
||||
std::set<ustring> m_closures_needed;
|
||||
std::set<ustring> m_globals_needed;
|
||||
int m_globals_read = 0;
|
||||
int m_globals_write = 0;
|
||||
std::set<AttributeNeeded> m_attributes_needed;
|
||||
bool m_unknown_textures_needed;
|
||||
bool m_unknown_closures_needed;
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Turn an LLVM-compiled bitfile into a C++ source file where the compiled
|
||||
# bitcode is in a huge array.
|
||||
|
||||
in=$1
|
||||
out=$2
|
||||
prefix=$3
|
||||
|
||||
echo "#include <cstddef>" > $out
|
||||
echo "unsigned char osl_llvm_compiled_ops_block[] = {" >> $out
|
||||
echo "unsigned char " ${prefix}"_block[] = {" >> $out
|
||||
hexdump -v -e '"" /1 "0x%02x" ",\n"' $in >> $out
|
||||
echo "0x00 };" >> $out
|
||||
echo "size_t osl_llvm_compiled_ops_size = sizeof(osl_llvm_compiled_ops_block)-1;" >> $out
|
||||
echo "size_t " ${prefix}"_size = sizeof("${prefix}"_block)-1;" >> $out
|
||||
|
||||
|
||||
@@ -26,13 +26,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
|
||||
#include <OpenImageIO/dassert.h>
|
||||
#include <OpenImageIO/thread.h>
|
||||
#include <OpenImageIO/imagebuf.h>
|
||||
@@ -51,16 +44,18 @@ using namespace OSL::pvt;
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
|
||||
|
||||
bool
|
||||
shade_image (ShadingSystem &shadingsys, ShaderGroup &group,
|
||||
const ShaderGlobals *defaultsg,
|
||||
OIIO::ImageBuf &buf, OIIO::array_view<ustring> outputs,
|
||||
ShadeImageLocations shadelocations,
|
||||
OIIO::ROI roi, int nthreads)
|
||||
OIIO::ROI roi, OIIO::ImageBufAlgo::parallel_image_options popt)
|
||||
{
|
||||
using namespace OIIO;
|
||||
using namespace ImageBufAlgo;
|
||||
if (! roi.defined())
|
||||
roi = buf.roi();
|
||||
// std::cout << "shade_image " << roi << "\n";
|
||||
if (buf.spec().format != TypeDesc::FLOAT) {
|
||||
buf.error ("Cannot OSL::shade_image() into a %f buffer, float is required",
|
||||
buf.spec().format);
|
||||
@@ -68,18 +63,7 @@ shade_image (ShadingSystem &shadingsys, ShaderGroup &group,
|
||||
}
|
||||
shadingsys.optimize_group (&group);
|
||||
|
||||
if (nthreads != 1 && roi.npixels() >= 64*64) {
|
||||
// Parallelize
|
||||
OIIO::ImageBufAlgo::parallel_image (
|
||||
std::bind (shade_image, std::ref(shadingsys),
|
||||
std::ref(group), defaultsg,
|
||||
std::ref(buf), outputs, shadelocations,
|
||||
std::placeholders::_1 /*roi*/, 1 /*nthreads*/),
|
||||
roi, nthreads);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Serial case
|
||||
parallel_image (roi, popt, [&](OIIO::ROI roi){
|
||||
|
||||
// Optional: high-performance apps may request this thread-specific
|
||||
// pointer in order to save a bit of time on each shade. Just like
|
||||
@@ -110,7 +94,7 @@ shade_image (ShadingSystem &shadingsys, ShaderGroup &group,
|
||||
const ShaderSymbol **output_sym = OIIO_ALLOCA(const ShaderSymbol*, outputs.size());
|
||||
TypeDesc *output_type = OIIO_ALLOCA(TypeDesc, outputs.size());
|
||||
int *output_nchans = OIIO_ALLOCA(int, outputs.size());
|
||||
for (size_t i = 0; i < outputs.size(); ++i) {
|
||||
for (int i = 0; i < int(outputs.size()); ++i) {
|
||||
output_sym[i] = shadingsys.find_symbol (group, outputs[i]);
|
||||
output_type[i] = shadingsys.symbol_typedesc (output_sym[i]);
|
||||
output_nchans[i] = output_type[i].numelements() * output_type[i].aggregate;
|
||||
@@ -127,10 +111,10 @@ shade_image (ShadingSystem &shadingsys, ShaderGroup &group,
|
||||
if (defaultsg) {
|
||||
// If the caller passed a default SG template, use it to initialize
|
||||
// the sg and in particular to set all the constant fields.
|
||||
memcpy (&sg, defaultsg, sizeof(ShaderGlobals));
|
||||
memcpy ((char *)&sg, (const char*)defaultsg, sizeof(ShaderGlobals));
|
||||
} else {
|
||||
// No SG template was passed, so set up reasonable defaults.
|
||||
memset (&sg, 0, sizeof(ShaderGlobals));
|
||||
memset ((char *)&sg, 0, sizeof(ShaderGlobals));
|
||||
// Set "shader" space to be Mshad. In a real renderer, this may be
|
||||
// different for each shader group.
|
||||
sg.shader2common = OSL::TransformationPtr (&Mshad);
|
||||
@@ -185,7 +169,7 @@ shade_image (ShadingSystem &shadingsys, ShaderGroup &group,
|
||||
|
||||
// Save all the designated outputs.
|
||||
int chan = 0;
|
||||
for (size_t i = 0; i < outputs.size(); ++i) {
|
||||
for (int i = 0; i < int(outputs.size()); ++i) {
|
||||
const void *data = shadingsys.symbol_address (*ctx, output_sym[i]);
|
||||
if (!data)
|
||||
continue; // Skip if symbol isn't found
|
||||
@@ -213,6 +197,7 @@ shade_image (ShadingSystem &shadingsys, ShaderGroup &group,
|
||||
// destroy it when done with it.
|
||||
shadingsys.destroy_thread_info (thread_info);
|
||||
|
||||
}); // end of parallel_image
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+216
-38
@@ -49,9 +49,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
using namespace OSL;
|
||||
using namespace OSL::pvt;
|
||||
|
||||
// avoid naming conflict with MSVC macro
|
||||
#ifdef RGB
|
||||
#undef RGB
|
||||
// avoid naming conflicts with MSVC macros
|
||||
#ifdef _MSC_VER
|
||||
#undef RGB
|
||||
// We use some of the iso646.h macro names later on in this file. For
|
||||
// some compilers (MSVS, I'm looking at you) this is trouble. I don't know
|
||||
// how or why that header would have been included here, but it did for at
|
||||
// least one person, so shut off those macros so they don't cause trouble.
|
||||
#undef and
|
||||
#undef or
|
||||
#undef xor
|
||||
#undef compl
|
||||
#undef bitand
|
||||
#undef bitor
|
||||
#endif
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
@@ -237,15 +247,6 @@ ShadingSystem::execute (ShadingContext *ctx, ShaderGroup &group,
|
||||
|
||||
|
||||
|
||||
bool
|
||||
ShadingSystem::execute (ShadingContext &ctx, ShaderGroup &group,
|
||||
ShaderGlobals &globals, bool run)
|
||||
{
|
||||
return m_impl->execute (&ctx, group, globals, run);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
ShadingSystem::execute_init (ShadingContext &ctx, ShaderGroup &group,
|
||||
ShaderGlobals &globals, bool run)
|
||||
@@ -404,6 +405,53 @@ ShadingSystem::query_closure (const char **name, int *id,
|
||||
|
||||
|
||||
|
||||
static cspan< std::pair<ustring,SGBits> >
|
||||
sgbit_table ()
|
||||
{
|
||||
static const std::pair<ustring,SGBits> table[] = {
|
||||
{ ustring("P"), SGBits::P },
|
||||
{ ustring("I"), SGBits::I },
|
||||
{ ustring("N"), SGBits::N },
|
||||
{ ustring("Ng"), SGBits::Ng },
|
||||
{ ustring("u"), SGBits::u },
|
||||
{ ustring("v"), SGBits::v },
|
||||
{ ustring("dPdu"), SGBits::dPdu },
|
||||
{ ustring("dPdv"), SGBits::dPdv },
|
||||
{ ustring("time"), SGBits::time },
|
||||
{ ustring("dtime"), SGBits::dtime },
|
||||
{ ustring("dPdtime"), SGBits::dPdtime },
|
||||
{ ustring("Ps"), SGBits::Ps },
|
||||
{ ustring("Ci"), SGBits::Ci }
|
||||
};
|
||||
return cspan<std::pair<ustring,SGBits>>(table);
|
||||
}
|
||||
|
||||
|
||||
|
||||
SGBits
|
||||
ShadingSystem::globals_bit (ustring name)
|
||||
{
|
||||
for (auto t : sgbit_table()) {
|
||||
if (name == t.first)
|
||||
return t.second;
|
||||
}
|
||||
return SGBits::None;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ustring
|
||||
ShadingSystem::globals_name (SGBits bit)
|
||||
{
|
||||
for (auto t : sgbit_table()) {
|
||||
if (bit == t.second)
|
||||
return t.first;
|
||||
}
|
||||
return ustring();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
ShadingSystem::raytype_bit (ustring name)
|
||||
{
|
||||
@@ -452,21 +500,22 @@ ShadingSystem::set_raytypes (ShaderGroup *group, int raytypes_on, int raytypes_o
|
||||
|
||||
|
||||
void
|
||||
ShadingSystem::optimize_group (ShaderGroup *group)
|
||||
ShadingSystem::optimize_group (ShaderGroup *group, ShadingContext *ctx)
|
||||
{
|
||||
DASSERT (group);
|
||||
m_impl->optimize_group (*group);
|
||||
m_impl->optimize_group (*group, ctx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ShadingSystem::optimize_group (ShaderGroup *group,
|
||||
int raytypes_on, int raytypes_off)
|
||||
int raytypes_on, int raytypes_off,
|
||||
ShadingContext *ctx)
|
||||
{
|
||||
// convenience function for backwards compatibility
|
||||
set_raytypes (group, raytypes_on, raytypes_off);
|
||||
optimize_group (group);
|
||||
optimize_group (group, ctx);
|
||||
|
||||
}
|
||||
|
||||
@@ -648,6 +697,7 @@ ShadingSystemImpl::ShadingSystemImpl (RendererServices *renderer,
|
||||
m_lazy_userdata(false), m_userdata_isconnected(false),
|
||||
m_clearmemory (false), m_debugnan (false), m_debug_uninit(false),
|
||||
m_lockgeom_default (true), m_strict_messages(true),
|
||||
m_error_repeats(false),
|
||||
m_range_checking(true),
|
||||
m_unknown_coordsys_error(true), m_connection_error(true),
|
||||
m_greedyjit(false), m_countlayerexecs(false),
|
||||
@@ -669,6 +719,7 @@ ShadingSystemImpl::ShadingSystemImpl (RendererServices *renderer,
|
||||
m_llvm_optimize(0),
|
||||
m_debug(0), m_llvm_debug(0),
|
||||
m_llvm_debug_layers(0), m_llvm_debug_ops(0),
|
||||
m_llvm_output_bitcode(0),
|
||||
m_commonspace_synonym("world"),
|
||||
m_colorspace("Rec709"),
|
||||
m_max_local_mem_KB(2048),
|
||||
@@ -677,6 +728,7 @@ ShadingSystemImpl::ShadingSystemImpl (RendererServices *renderer,
|
||||
m_no_noise(false),
|
||||
m_no_pointcloud(false),
|
||||
m_force_derivs(false),
|
||||
m_allow_shader_replacement(false),
|
||||
m_exec_repeat(1),
|
||||
m_in_group (false),
|
||||
m_stat_opt_locking_time(0), m_stat_specialization_time(0),
|
||||
@@ -1091,6 +1143,7 @@ ShadingSystemImpl::attribute (string_view name, TypeDesc type,
|
||||
ATTR_SET ("llvm_debug", int, m_llvm_debug);
|
||||
ATTR_SET ("llvm_debug_layers", int, m_llvm_debug_layers);
|
||||
ATTR_SET ("llvm_debug_ops", int, m_llvm_debug_ops);
|
||||
ATTR_SET ("llvm_output_bitcode", int, m_llvm_output_bitcode);
|
||||
ATTR_SET ("strict_messages", int, m_strict_messages);
|
||||
ATTR_SET ("range_checking", int, m_range_checking);
|
||||
ATTR_SET ("unknown_coordsys_error", int, m_unknown_coordsys_error);
|
||||
@@ -1105,6 +1158,7 @@ ShadingSystemImpl::attribute (string_view name, TypeDesc type,
|
||||
ATTR_SET ("no_noise", int, m_no_noise);
|
||||
ATTR_SET ("no_pointcloud", int, m_no_pointcloud);
|
||||
ATTR_SET ("force_derivs", int, m_force_derivs);
|
||||
ATTR_SET ("allow_shader_replacement", int, m_allow_shader_replacement);
|
||||
ATTR_SET ("exec_repeat", int, m_exec_repeat);
|
||||
ATTR_SET_STRING ("commonspace", m_commonspace_synonym);
|
||||
ATTR_SET_STRING ("debug_groupname", m_debug_groupname);
|
||||
@@ -1142,6 +1196,19 @@ ShadingSystemImpl::attribute (string_view name, TypeDesc type,
|
||||
m_renderer_outputs.emplace_back(((const char **)val)[i]);
|
||||
return true;
|
||||
}
|
||||
if (name == "lib_bitcode" && type.basetype == TypeDesc::UINT8) {
|
||||
m_lib_bitcode.clear();
|
||||
m_lib_bitcode = *static_cast<const std::vector<char>*>(val);
|
||||
return true;
|
||||
}
|
||||
if (name == "error_repeats") {
|
||||
// Special case: setting error_repeats also clears the "previously
|
||||
// seen" error and warning lists.
|
||||
m_errseen.clear();
|
||||
m_warnseen.clear();
|
||||
ATTR_SET ("error_repeats", int, m_error_repeats);
|
||||
}
|
||||
|
||||
return false;
|
||||
#undef ATTR_SET
|
||||
#undef ATTR_SET_STRING
|
||||
@@ -1165,6 +1232,7 @@ ShadingSystemImpl::getattribute (string_view name, TypeDesc type,
|
||||
}
|
||||
|
||||
lock_guard guard (m_mutex); // Thread safety
|
||||
|
||||
ATTR_DECODE_STRING ("searchpath:shader", m_searchpath);
|
||||
ATTR_DECODE ("statistics:level", int, m_statslevel);
|
||||
ATTR_DECODE ("lazylayers", int, m_lazylayers);
|
||||
@@ -1201,7 +1269,9 @@ ShadingSystemImpl::getattribute (string_view name, TypeDesc type,
|
||||
ATTR_DECODE ("llvm_debug", int, m_llvm_debug);
|
||||
ATTR_DECODE ("llvm_debug_layers", int, m_llvm_debug_layers);
|
||||
ATTR_DECODE ("llvm_debug_ops", int, m_llvm_debug_ops);
|
||||
ATTR_DECODE ("llvm_output_bitcode", int, m_llvm_output_bitcode);
|
||||
ATTR_DECODE ("strict_messages", int, m_strict_messages);
|
||||
ATTR_DECODE ("error_repeats", int, m_error_repeats);
|
||||
ATTR_DECODE ("range_checking", int, m_range_checking);
|
||||
ATTR_DECODE ("unknown_coordsys_error", int, m_unknown_coordsys_error);
|
||||
ATTR_DECODE ("connection_error", int, m_connection_error);
|
||||
@@ -1223,6 +1293,7 @@ ShadingSystemImpl::getattribute (string_view name, TypeDesc type,
|
||||
ATTR_DECODE ("no_noise", int, m_no_noise);
|
||||
ATTR_DECODE ("no_pointcloud", int, m_no_pointcloud);
|
||||
ATTR_DECODE ("force_derivs", int, m_force_derivs);
|
||||
ATTR_DECODE ("allow_shader_replacement", int, m_allow_shader_replacement);
|
||||
ATTR_DECODE ("exec_repeat", int, m_exec_repeat);
|
||||
|
||||
ATTR_DECODE ("stat:masters", int, m_stat_shaders_loaded);
|
||||
@@ -1333,6 +1404,7 @@ ShadingSystemImpl::getattribute (ShaderGroup *group, string_view name,
|
||||
{
|
||||
if (! group)
|
||||
return false;
|
||||
|
||||
if (name == "groupname" && type == TypeDesc::TypeString) {
|
||||
*(ustring *)val = group->name();
|
||||
return true;
|
||||
@@ -1379,6 +1451,18 @@ ShadingSystemImpl::getattribute (ShaderGroup *group, string_view name,
|
||||
((ustring *)val)[i] = ustring();
|
||||
return true;
|
||||
}
|
||||
if (name == "group_init_name" && type.basetype == TypeDesc::STRING) {
|
||||
*(ustring *)val = ustring::format ("group_%d_init", group->id());
|
||||
return true;
|
||||
}
|
||||
if (name == "group_entry_name" && type.basetype == TypeDesc::STRING) {
|
||||
int nlayers = group->nlayers ();
|
||||
ShaderInstance *inst = (*group)[nlayers-1];
|
||||
// This formuation mirrors OSOProcessorBase::layer_function_name()
|
||||
*(ustring *)val = ustring::format ("%s_%s_%d", group->name(),
|
||||
inst->layername(), inst->id());
|
||||
return true;
|
||||
}
|
||||
if (name == "num_textures_needed" && type == TypeDesc::TypeInt) {
|
||||
if (! group->optimized())
|
||||
optimize_group (*group);
|
||||
@@ -1432,6 +1516,18 @@ ShadingSystemImpl::getattribute (ShaderGroup *group, string_view name,
|
||||
*(ustring **)val = n ? &group->m_globals_needed[0] : NULL;
|
||||
return true;
|
||||
}
|
||||
if (name == "globals_read" && type.basetype == TypeDesc::INT) {
|
||||
if (! group->optimized())
|
||||
optimize_group (*group);
|
||||
*(int *)val = group->m_globals_read;
|
||||
return true;
|
||||
}
|
||||
if (name == "globals_write" && type.basetype == TypeDesc::INT) {
|
||||
if (! group->optimized())
|
||||
optimize_group (*group);
|
||||
*(int *)val = group->m_globals_write;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (name == "num_userdata" && type == TypeDesc::TypeInt) {
|
||||
if (! group->optimized())
|
||||
@@ -1503,6 +1599,39 @@ ShadingSystemImpl::getattribute (ShaderGroup *group, string_view name,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Additional atttributes useful to OptiX-based renderers
|
||||
if (name == "userdata_layers" && type.basetype == TypeDesc::PTR) {
|
||||
if (! group->optimized())
|
||||
optimize_group (*group);
|
||||
size_t n = group->m_userdata_layers.size();
|
||||
*(int **)val = n ? &group->m_userdata_layers[0] : NULL;
|
||||
return true;
|
||||
}
|
||||
if (name == "userdata_init_vals" && type.basetype == TypeDesc::PTR) {
|
||||
if (! group->optimized())
|
||||
optimize_group (*group);
|
||||
size_t n = group->m_userdata_init_vals.size();
|
||||
*(void **)val = n ? &group->m_userdata_init_vals[0] : NULL;
|
||||
return true;
|
||||
}
|
||||
if (name == "ptx_compiled_version" && type.basetype == TypeDesc::PTR) {
|
||||
bool exists = !group->m_llvm_ptx_compiled_version.empty();
|
||||
*(std::string *)val = exists ? group->m_llvm_ptx_compiled_version : "";
|
||||
return true;
|
||||
}
|
||||
if (name == "group_id" && type == TypeDesc::TypeInt) {
|
||||
if (! group->optimized())
|
||||
optimize_group (*group);
|
||||
*(int *)val = (int) group->id();
|
||||
return true;
|
||||
}
|
||||
if (name == "layer_osofiles" && type.basetype == TypeDesc::STRING) {
|
||||
size_t n = std::min (type.numelements(), (size_t)group->nlayers());
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
((ustring *)val)[i] =(*group)[i]->master()->osofilename();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1514,7 +1643,7 @@ ShadingSystemImpl::error (const std::string &msg) const
|
||||
lock_guard guard (m_errmutex);
|
||||
int n = 0;
|
||||
for (auto&& s : m_errseen) {
|
||||
if (s == msg)
|
||||
if (s == msg && !m_error_repeats)
|
||||
return;
|
||||
++n;
|
||||
}
|
||||
@@ -1532,7 +1661,7 @@ ShadingSystemImpl::warning (const std::string &msg) const
|
||||
lock_guard guard (m_errmutex);
|
||||
int n = 0;
|
||||
for (auto&& s : m_warnseen) {
|
||||
if (s == msg)
|
||||
if (s == msg && !m_error_repeats)
|
||||
return;
|
||||
++n;
|
||||
}
|
||||
@@ -1600,8 +1729,8 @@ ShadingSystemImpl::getstats (int level) const
|
||||
out << "OSL ShadingSystem statistics (" << (void*)this;
|
||||
out << ") ver " << OSL_LIBRARY_VERSION_STRING
|
||||
<< ", LLVM " << OSL_LLVM_FULL_VERSION << "\n";
|
||||
if (m_stat_shaders_requested == 0) {
|
||||
out << " No shaders requested\n";
|
||||
if (m_stat_shaders_requested == 0 && m_stat_shaders_loaded == 0) {
|
||||
out << " No shaders requested or loaded\n";
|
||||
return out.str();
|
||||
}
|
||||
|
||||
@@ -1616,6 +1745,7 @@ ShadingSystemImpl::getstats (int level) const
|
||||
INTOPT (llvm_debug);
|
||||
BOOLOPT (llvm_debug_layers);
|
||||
BOOLOPT (llvm_debug_ops);
|
||||
BOOLOPT (llvm_output_bitcode);
|
||||
BOOLOPT (lazylayers);
|
||||
BOOLOPT (lazyglobals);
|
||||
BOOLOPT (lazyunconnected);
|
||||
@@ -1626,6 +1756,7 @@ ShadingSystemImpl::getstats (int level) const
|
||||
BOOLOPT (debug_uninit);
|
||||
BOOLOPT (lockgeom_default);
|
||||
BOOLOPT (strict_messages);
|
||||
BOOLOPT (error_repeats);
|
||||
BOOLOPT (range_checking);
|
||||
BOOLOPT (greedyjit);
|
||||
BOOLOPT (countlayerexecs);
|
||||
@@ -1648,6 +1779,7 @@ ShadingSystemImpl::getstats (int level) const
|
||||
INTOPT (no_noise);
|
||||
INTOPT (no_pointcloud);
|
||||
INTOPT (force_derivs);
|
||||
INTOPT (allow_shader_replacement);
|
||||
INTOPT (exec_repeat);
|
||||
STROPT (debug_groupname);
|
||||
STROPT (debug_layername);
|
||||
@@ -1867,7 +1999,7 @@ ShadingSystemImpl::ShaderGroupBegin (string_view groupname)
|
||||
return ShaderGroupRef();
|
||||
}
|
||||
m_in_group = true;
|
||||
m_group_use = ShadUseUnknown;
|
||||
m_group_use.clear(); // unknown/unset group
|
||||
m_curgroup.reset (new ShaderGroup(groupname));
|
||||
m_curgroup->m_exec_repeat = m_exec_repeat;
|
||||
return m_curgroup;
|
||||
@@ -1884,7 +2016,7 @@ ShadingSystemImpl::ShaderGroupEnd (void)
|
||||
}
|
||||
|
||||
// Mark the layers that can be run lazily
|
||||
if (m_group_use != ShadUseUnknown) {
|
||||
if (! m_group_use.empty()) {
|
||||
int nlayers = m_curgroup->nlayers ();
|
||||
for (int layer = 0; layer < nlayers; ++layer) {
|
||||
ShaderInstance *inst = (*m_curgroup)[layer];
|
||||
@@ -1917,7 +2049,7 @@ ShadingSystemImpl::ShaderGroupEnd (void)
|
||||
}
|
||||
|
||||
m_in_group = false;
|
||||
m_group_use = ShadUseUnknown;
|
||||
m_group_use.clear(); // Mark use as unset/unknown
|
||||
|
||||
ustring groupname = m_curgroup->name();
|
||||
if (groupname.size() && groupname == m_archive_groupname) {
|
||||
@@ -1947,27 +2079,34 @@ ShadingSystemImpl::Shader (string_view shaderusage,
|
||||
return false;
|
||||
}
|
||||
|
||||
ShaderUse use = shaderuse_from_name (shaderusage);
|
||||
if (use == ShadUseUnknown) {
|
||||
error ("Unknown shader usage \"%s\"", shaderusage);
|
||||
if (shaderusage.empty()) {
|
||||
error ("Shader usage required");
|
||||
return false;
|
||||
}
|
||||
|
||||
// If a layer name was not supplied, make one up.
|
||||
std::string local_layername;
|
||||
if (layername.empty()) {
|
||||
local_layername = OIIO::Strutil::format ("%s_%d", master->shadername(),
|
||||
m_curgroup->nlayers());
|
||||
layername = string_view (local_layername);
|
||||
}
|
||||
|
||||
ShaderInstanceRef instance (new ShaderInstance (master, layername));
|
||||
instance->parameters (m_pending_params);
|
||||
m_pending_params.clear ();
|
||||
|
||||
if (singleton || m_group_use == ShadUseUnknown) {
|
||||
if (singleton || m_group_use.empty()) {
|
||||
// A singleton, or the first in a group
|
||||
m_curgroup->clear ();
|
||||
m_stat_groups += 1;
|
||||
}
|
||||
if (! singleton) {
|
||||
if (m_group_use == ShadUseUnknown) { // First shader in group
|
||||
m_group_use = use;
|
||||
} else if (use != m_group_use) {
|
||||
if (m_group_use.empty()) { // First shader in group
|
||||
m_group_use = shaderusage;
|
||||
} else if (shaderusage != m_group_use) {
|
||||
error ("Shader usage \"%s\" does not match current group (%s)",
|
||||
shaderusage, shaderusename (m_group_use));
|
||||
shaderusage, m_group_use);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -2060,6 +2199,16 @@ ShadingSystemImpl::ConnectShaders (string_view srclayer, string_view srcparam,
|
||||
return false;
|
||||
}
|
||||
|
||||
const Symbol *dstsym = dstinst->mastersymbol(dstcon.param);
|
||||
ASSERT (dstsym);
|
||||
if (dstsym && !dstsym->allowconnect()) {
|
||||
std::string name = dstlayer.size() ? Strutil::format("%s.%s", dstlayer, dstparam)
|
||||
: std::string(dstparam);
|
||||
error ("ConnectShaders: cannot connect to %s because it has metadata allowconnect=0",
|
||||
name);
|
||||
return false;
|
||||
}
|
||||
|
||||
dstinst->add_connection (srcinstindex, srccon, dstcon);
|
||||
dstinst->instoverride(dstcon.param)->valuesource (Symbol::ConnectedVal);
|
||||
srcinst->instoverride(srccon.param)->connected_down (true);
|
||||
@@ -2174,7 +2323,7 @@ ShadingSystemImpl::ShaderGroupBegin (string_view groupname,
|
||||
}
|
||||
}
|
||||
string_view paramname (paramname_string);
|
||||
int lockgeom = true;
|
||||
int lockgeom = m_lockgeom_default;
|
||||
// For speed, reserve space. Note that for "unsized" arrays, we only
|
||||
// preallocate 1 slot and let it grow as needed. That's ok. For
|
||||
// everything else, we will reserve the right amount up front.
|
||||
@@ -2363,8 +2512,13 @@ ShadingSystemImpl::ReParameter (ShaderGroup &group, string_view layername_,
|
||||
int paramindex = layer->findparam (ustring(paramname));
|
||||
if (paramindex < 0)
|
||||
return false; // could not find the named parameter
|
||||
|
||||
Symbol *sym = layer->symbol (paramindex);
|
||||
ASSERT (sym != NULL);
|
||||
if (!sym) {
|
||||
// Can have a paramindex >= 0, but no symbol when it's a master-symbol
|
||||
DASSERT(layer->mastersymbol(paramindex) && "No symbol for paramindex");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for mismatch versus previously-declared type
|
||||
if (!equivalent(sym->typespec(), type))
|
||||
@@ -2461,7 +2615,7 @@ ShadingSystemImpl::find_named_layer_in_group (ustring layername,
|
||||
ShaderInstance * &inst)
|
||||
{
|
||||
inst = NULL;
|
||||
if (m_group_use >= ShadUseUnknown)
|
||||
if (m_group_use.empty())
|
||||
return -1;
|
||||
ShaderGroup &group (*m_curgroup);
|
||||
for (int i = 0; i < group.nlayers(); ++i) {
|
||||
@@ -2646,7 +2800,7 @@ ShadingSystemImpl::group_post_jit_cleanup (ShaderGroup &group)
|
||||
|
||||
|
||||
void
|
||||
ShadingSystemImpl::optimize_group (ShaderGroup &group)
|
||||
ShadingSystemImpl::optimize_group (ShaderGroup &group, ShadingContext *ctx)
|
||||
{
|
||||
if (group.optimized())
|
||||
return; // already optimized
|
||||
@@ -2664,7 +2818,7 @@ ShadingSystemImpl::optimize_group (ShaderGroup &group)
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_only_groupname && m_only_groupname != group.name()) {
|
||||
if (!m_only_groupname.empty() && m_only_groupname != group.name()) {
|
||||
// For debugging purposes, we are requested to compile only one
|
||||
// shader group, and this is not it. Mark it as does_nothing,
|
||||
// and also as optimized so nobody locks on it again, and record
|
||||
@@ -2680,7 +2834,11 @@ ShadingSystemImpl::optimize_group (ShaderGroup &group)
|
||||
|
||||
double locking_time = timer();
|
||||
|
||||
ShadingContext *ctx = get_context ();
|
||||
bool ctx_allocated = false;
|
||||
if (! ctx) {
|
||||
ctx = get_context ();
|
||||
ctx_allocated = true;
|
||||
}
|
||||
RuntimeOptimizer rop (*this, group, ctx);
|
||||
rop.run ();
|
||||
|
||||
@@ -2693,15 +2851,21 @@ ShadingSystemImpl::optimize_group (ShaderGroup &group)
|
||||
group.m_closures_needed.push_back (f);
|
||||
for (auto&& f : rop.m_globals_needed)
|
||||
group.m_globals_needed.push_back (f);
|
||||
group.m_globals_read = rop.m_globals_read;
|
||||
group.m_globals_write = rop.m_globals_write;
|
||||
size_t num_userdata = rop.m_userdata_needed.size();
|
||||
group.m_userdata_names.reserve (num_userdata);
|
||||
group.m_userdata_types.reserve (num_userdata);
|
||||
group.m_userdata_offsets.resize (num_userdata, 0);
|
||||
group.m_userdata_derivs.reserve (num_userdata);
|
||||
group.m_userdata_layers.reserve (num_userdata);
|
||||
group.m_userdata_init_vals.reserve (num_userdata);
|
||||
for (auto&& n : rop.m_userdata_needed) {
|
||||
group.m_userdata_names.push_back (n.name);
|
||||
group.m_userdata_types.push_back (n.type);
|
||||
group.m_userdata_derivs.push_back (n.derivs);
|
||||
group.m_userdata_layers.push_back (n.layer_num);
|
||||
group.m_userdata_init_vals.push_back (n.data);
|
||||
}
|
||||
group.m_unknown_attributes_needed = rop.m_unknown_attributes_needed;
|
||||
for (auto&& f : rop.m_attributes_needed) {
|
||||
@@ -2714,7 +2878,8 @@ ShadingSystemImpl::optimize_group (ShaderGroup &group)
|
||||
|
||||
group_post_jit_cleanup (group);
|
||||
|
||||
release_context (ctx);
|
||||
if (ctx_allocated)
|
||||
release_context (ctx);
|
||||
|
||||
group.m_optimized = true;
|
||||
spin_lock stat_lock (m_stat_mutex);
|
||||
@@ -3098,6 +3263,19 @@ OSL::OSLQuery::init (const ShaderGroup *group, int layernum)
|
||||
p.fdefault.clear();
|
||||
p.sdefault.clear();
|
||||
p.spacename.clear();
|
||||
int n = int (p.type.numelements() * p.type.aggregate);
|
||||
if (p.type.basetype == TypeDesc::INT) {
|
||||
for (int i = 0; i < n; ++i)
|
||||
p.idefault.push_back (sym->get_int(i));
|
||||
}
|
||||
if (p.type.basetype == TypeDesc::FLOAT) {
|
||||
for (int i = 0; i < n; ++i)
|
||||
p.fdefault.push_back (sym->get_float(i));
|
||||
}
|
||||
if (p.type.basetype == TypeDesc::STRING) {
|
||||
for (int i = 0; i < n; ++i)
|
||||
p.sdefault.push_back (sym->get_string(i));
|
||||
}
|
||||
p.fields.clear(); // don't bother filling this out
|
||||
if (StructSpec *ss = ts.structspec()) {
|
||||
p.structname = ss->name().string();
|
||||
|
||||
@@ -178,22 +178,24 @@ void spline_inverse (const SplineBasis *spline,
|
||||
int knot_arraylen)
|
||||
{
|
||||
// account for out-of-range inputs, just clamp to the values we have
|
||||
int lowindex = spline->basis_step == 1 ? 1 : 0;
|
||||
int highindex = spline->basis_step == 1 ? knot_count-2 : knot_count-1;
|
||||
bool increasing = knots[1] < knots[knot_count-2];
|
||||
if (increasing) {
|
||||
if (y <= knots[1]) {
|
||||
if (y <= knots[lowindex]) {
|
||||
x = YTYPE(0);
|
||||
return;
|
||||
}
|
||||
if (y >= knots[knot_count-2]) {
|
||||
if (y >= knots[highindex]) {
|
||||
x = YTYPE(1);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (y >= knots[1]) {
|
||||
if (y >= knots[lowindex]) {
|
||||
x = YTYPE(0);
|
||||
return;
|
||||
}
|
||||
if (y <= knots[knot_count-2]) {
|
||||
if (y <= knots[highindex]) {
|
||||
x = YTYPE(1);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,14 @@ if (BUILDSTATIC)
|
||||
ADD_LIBRARY ( oslnoise STATIC ${liboslnoise_srcs} )
|
||||
else ()
|
||||
ADD_LIBRARY ( oslnoise SHARED ${liboslnoise_srcs} )
|
||||
|
||||
if (VERBOSE)
|
||||
message(STATUS "Setting SOVERSION to: ${SOVERSION}")
|
||||
endif ()
|
||||
set_target_properties( oslnoise
|
||||
PROPERTIES
|
||||
VERSION ${OSL_VERSION_MAJOR}.${OSL_VERSION_MINOR}.${OSL_VERSION_PATCH}
|
||||
SOVERSION ${SOVERSION} )
|
||||
endif ()
|
||||
|
||||
TARGET_LINK_LIBRARIES ( oslnoise ${OPENIMAGEIO_LIBRARIES} ${ILMBASE_LIBRARIES} ${Boost_LIBRARIES} ${CMAKE_DL_LIBS} )
|
||||
|
||||
@@ -60,9 +60,9 @@ public:
|
||||
// seed based on the cell containing P
|
||||
fast_rng (const Vec3 &p, int seed=0) {
|
||||
// Use guts of cellnoise
|
||||
unsigned int pi[4] = { unsigned(quick_floor(p[0])),
|
||||
unsigned(quick_floor(p[1])),
|
||||
unsigned(quick_floor(p[2])),
|
||||
unsigned int pi[4] = { unsigned(OIIO::ifloor(p[0])),
|
||||
unsigned(OIIO::ifloor(p[1])),
|
||||
unsigned(OIIO::ifloor(p[2])),
|
||||
unsigned(seed) };
|
||||
m_seed = inthash<4>(pi);
|
||||
if (! m_seed)
|
||||
|
||||
@@ -29,10 +29,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <OpenImageIO/simd.h>
|
||||
#include <OpenImageIO/unittest.h>
|
||||
#include <OpenImageIO/argparse.h>
|
||||
#include <OpenImageIO/imagebuf.h>
|
||||
#include <OpenImageIO/timer.h>
|
||||
#include <OpenImageIO/benchmark.h>
|
||||
|
||||
#include <OSL/oslnoise.h>
|
||||
|
||||
@@ -98,48 +100,6 @@ inline float abs (const Vec3& a) {
|
||||
|
||||
|
||||
|
||||
template <typename FUNC, typename T>
|
||||
void benchmark1 (string_view funcname, FUNC func, T x)
|
||||
{
|
||||
auto repeat_func = [&](){
|
||||
// Unroll the loop 8 times
|
||||
auto r = func(x); DoNotOptimize (r); clobber_all_memory();
|
||||
r = func(x); DoNotOptimize (r); clobber_all_memory();
|
||||
r = func(x); DoNotOptimize (r); clobber_all_memory();
|
||||
r = func(x); DoNotOptimize (r); clobber_all_memory();
|
||||
r = func(x); DoNotOptimize (r); clobber_all_memory();
|
||||
r = func(x); DoNotOptimize (r); clobber_all_memory();
|
||||
r = func(x); DoNotOptimize (r); clobber_all_memory();
|
||||
r = func(x); DoNotOptimize (r); clobber_all_memory();
|
||||
};
|
||||
float time = time_trial (repeat_func, ntrials, iterations/8);
|
||||
std::cout << Strutil::format (" %s: %7.1f Mcalls/sec\n",
|
||||
funcname, (iterations/1.0e6)/time);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename FUNC, typename S, typename T>
|
||||
void benchmark2 (string_view funcname, FUNC func, S x, T y)
|
||||
{
|
||||
auto repeat_func = [&](){
|
||||
// Unroll the loop 8 times
|
||||
auto r = func(x,y); DoNotOptimize (r); clobber_all_memory();
|
||||
r = func(x,y); DoNotOptimize (r); clobber_all_memory();
|
||||
r = func(x,y); DoNotOptimize (r); clobber_all_memory();
|
||||
r = func(x,y); DoNotOptimize (r); clobber_all_memory();
|
||||
r = func(x,y); DoNotOptimize (r); clobber_all_memory();
|
||||
r = func(x,y); DoNotOptimize (r); clobber_all_memory();
|
||||
r = func(x,y); DoNotOptimize (r); clobber_all_memory();
|
||||
r = func(x,y); DoNotOptimize (r); clobber_all_memory();
|
||||
};
|
||||
float time = time_trial (repeat_func, ntrials, iterations/8);
|
||||
std::cout << Strutil::format (" %s: %7.1f Mcalls/sec\n",
|
||||
funcname, (iterations/1.0e6)/time);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
test_perlin ()
|
||||
{
|
||||
@@ -214,20 +174,35 @@ test_perlin ()
|
||||
OIIO_CHECK_EQUAL_THRESH (vs4, vresults_4d[i], eps);
|
||||
}
|
||||
|
||||
#if OPENIMAGEIO_VERSION >= 10904
|
||||
// Make sure the right thing happens at integer cell boundaries.
|
||||
// Perlin noise should be continuous everywhere.
|
||||
OIIO_CHECK_EQUAL_APPROX (noise( 0.9999f), noise( 1.0f));
|
||||
OIIO_CHECK_EQUAL_APPROX (noise( 1.0001f), noise( 1.0f));
|
||||
OIIO_CHECK_EQUAL_APPROX (noise(-0.0001f), noise( 0.0f));
|
||||
OIIO_CHECK_EQUAL_APPROX (noise( 0.0001f), noise( 0.0f));
|
||||
OIIO_CHECK_EQUAL_APPROX (noise(-1.0001f), noise(-1.0f));
|
||||
OIIO_CHECK_EQUAL_APPROX (noise(-0.9999f), noise(-1.0f));
|
||||
Strutil::printf ("noise around -1: %g %g %g\n",
|
||||
noise(-0.9999f), noise(-1.0f), noise(-1.0001f));
|
||||
#endif
|
||||
|
||||
if (make_images) {
|
||||
MAKE_IMAGE (noise);
|
||||
}
|
||||
|
||||
// Time trials
|
||||
benchmark1 ("snoise(f) ", snoise<float>, 0.5f);
|
||||
benchmark2 ("snoise(f,f) ", snoise<float,float>, 0.5f, 0.5f);
|
||||
benchmark1 ("snoise(v) ", snoise<const Vec3&>, Vec3(0,0,0));
|
||||
benchmark2 ("snoise(v,f) ", snoise<const Vec3&,float>, Vec3(0,0,0), 0.5f);
|
||||
Benchmarker bench;
|
||||
float fval = 0.5f; clobber (fval);
|
||||
Vec3 vval (0,0,0); clobber (vval);
|
||||
bench (" snoise(f)", [&](){ DoNotOptimize (snoise<float>(fval)); });
|
||||
bench (" snoise(f,f)", [&](){ DoNotOptimize (snoise<float,float>(fval, fval)); });
|
||||
bench (" snoise(v)", [&](){ DoNotOptimize (snoise<const Vec3&>(vval)); });
|
||||
bench (" snoise(v,f)", [&](){ DoNotOptimize (snoise<const Vec3&,float>(vval, fval)); });
|
||||
|
||||
benchmark1 ("vsnoise(f) ", vsnoise<float>, 0.5f);
|
||||
benchmark2 ("vsnoise(f,f) ", vsnoise<float,float>, 0.5f, 0.5f);
|
||||
benchmark1 ("vsnoise(v) ", vsnoise<const Vec3&>, Vec3(0,0,0));
|
||||
benchmark2 ("vsnoise(v,f) ", vsnoise<const Vec3&,float>, Vec3(0,0,0), 0.5f);
|
||||
bench (" vsnoise(f)", [&](){ DoNotOptimize (vsnoise<float>(fval)); });
|
||||
bench (" vsnoise(f,f)", [&](){ DoNotOptimize (vsnoise<float,float>(fval, fval)); });
|
||||
bench (" vsnoise(v)", [&](){ DoNotOptimize (vsnoise<const Vec3&>(vval)); });
|
||||
bench (" vsnoise(v,f)", [&](){ DoNotOptimize (vsnoise<const Vec3&,float>(vval, fval)); });
|
||||
}
|
||||
|
||||
|
||||
@@ -287,20 +262,35 @@ test_cell ()
|
||||
OIIO_CHECK_EQUAL_THRESH (vs4, vresults_4d[i], eps);
|
||||
}
|
||||
|
||||
#if OPENIMAGEIO_VERSION >= 10904
|
||||
// Make sure the right thing happens at integer cell boundaries
|
||||
OIIO_CHECK_EQUAL (cellnoise( 1.0001f), cellnoise( 1.0f));
|
||||
OIIO_CHECK_NE (cellnoise( 0.9999f), cellnoise( 1.0f));
|
||||
OIIO_CHECK_EQUAL (cellnoise( 0.9999f), cellnoise( 0.0f));
|
||||
OIIO_CHECK_EQUAL (cellnoise( 0.0001f), cellnoise( 0.0f));
|
||||
OIIO_CHECK_NE (cellnoise(-0.0001f), cellnoise( 0.0f));
|
||||
OIIO_CHECK_EQUAL (cellnoise(-0.0001f), cellnoise(-1.0f));
|
||||
OIIO_CHECK_EQUAL (cellnoise(-0.9999f), cellnoise(-1.0f));
|
||||
OIIO_CHECK_EQUAL (cellnoise(-1.0001f), cellnoise(-2.0f));
|
||||
#endif
|
||||
|
||||
if (make_images) {
|
||||
MAKE_IMAGE (cellnoise);
|
||||
}
|
||||
|
||||
// Time trials
|
||||
benchmark1 ("cellnoise(f) ", cellnoise<float>, 0.5f);
|
||||
benchmark2 ("cellnoise(f,f) ", cellnoise<float,float>, 0.5f, 0.5f);
|
||||
benchmark1 ("cellnoise(v) ", cellnoise<const Vec3&>, Vec3(0,0,0));
|
||||
benchmark2 ("cellnoise(v,f) ", cellnoise<const Vec3&,float>, Vec3(0,0,0), 0.5f);
|
||||
Benchmarker bench;
|
||||
float fval = 0.5f; clobber (fval);
|
||||
Vec3 vval (0,0,0); clobber (vval);
|
||||
bench (" cellnoise(f)", [&](){ DoNotOptimize (cellnoise<float>(fval)); });
|
||||
bench (" cellnoise(f,f)", [&](){ DoNotOptimize (cellnoise<float,float>(fval, fval)); });
|
||||
bench (" cellnoise(v)", [&](){ DoNotOptimize (cellnoise<const Vec3&>(vval)); });
|
||||
bench (" cellnoise(v,f)", [&](){ DoNotOptimize (cellnoise<const Vec3&,float>(vval, fval)); });
|
||||
|
||||
benchmark1 ("vcellnoise(f) ", vcellnoise<float>, 0.5f);
|
||||
benchmark2 ("vcellnoise(f,f)", vcellnoise<float,float>, 0.5f, 0.5f);
|
||||
benchmark1 ("vcellnoise(v) ", vcellnoise<const Vec3&>, Vec3(0,0,0));
|
||||
benchmark2 ("vcellnoise(v,f)", vcellnoise<const Vec3&,float>, Vec3(0,0,0), 0.5f);
|
||||
bench (" vcellnoise(f)", [&](){ DoNotOptimize (vcellnoise<float>(fval)); });
|
||||
bench (" vcellnoise(f,f)", [&](){ DoNotOptimize (vcellnoise<float,float>(fval, fval)); });
|
||||
bench (" vcellnoise(v)", [&](){ DoNotOptimize (vcellnoise<const Vec3&>(vval)); });
|
||||
bench (" vcellnoise(v,f)", [&](){ DoNotOptimize (vcellnoise<const Vec3&,float>(vval, fval)); });
|
||||
}
|
||||
|
||||
|
||||
@@ -360,20 +350,34 @@ test_hash ()
|
||||
OIIO_CHECK_EQUAL_THRESH (vs4, vresults_4d[i], eps);
|
||||
}
|
||||
|
||||
#if OPENIMAGEIO_VERSION >= 10904
|
||||
// Make sure the right thing happens at integer cell boundaries.
|
||||
// hashnoise should be discontinuous everywhere!
|
||||
OIIO_CHECK_NE (hashnoise( 0.9999f), hashnoise( 1.0f));
|
||||
OIIO_CHECK_NE (hashnoise( 1.0001f), hashnoise( 1.0f));
|
||||
OIIO_CHECK_NE (hashnoise(-0.0001f), hashnoise( 0.0f));
|
||||
OIIO_CHECK_NE (hashnoise( 0.0001f), hashnoise( 0.0f));
|
||||
OIIO_CHECK_NE (hashnoise(-1.0001f), hashnoise(-1.0f));
|
||||
OIIO_CHECK_NE (hashnoise(-0.9999f), hashnoise(-1.0f));
|
||||
#endif
|
||||
|
||||
if (make_images) {
|
||||
MAKE_IMAGE (hashnoise);
|
||||
}
|
||||
|
||||
// Time trials
|
||||
benchmark1 ("hashnoise(f) ", hashnoise<float>, 0.5f);
|
||||
benchmark2 ("hashnoise(f,f) ", hashnoise<float,float>, 0.5f, 0.5f);
|
||||
benchmark1 ("hashnoise(v) ", hashnoise<const Vec3&>, Vec3(0,0,0));
|
||||
benchmark2 ("hashnoise(v,f) ", hashnoise<const Vec3&,float>, Vec3(0,0,0), 0.5f);
|
||||
Benchmarker bench;
|
||||
float fval = 0.5f; clobber (fval);
|
||||
Vec3 vval (0,0,0); clobber (vval);
|
||||
bench (" hashnoise(f)", [&](){ DoNotOptimize (hashnoise<float>(fval)); });
|
||||
bench (" hashnoise(f,f)", [&](){ DoNotOptimize (hashnoise<float,float>(fval, fval)); });
|
||||
bench (" hashnoise(v)", [&](){ DoNotOptimize (hashnoise<const Vec3&>(vval)); });
|
||||
bench (" hashnoise(v,f)", [&](){ DoNotOptimize (hashnoise<const Vec3&,float>(vval, fval)); });
|
||||
|
||||
benchmark1 ("vhashnoise(f) ", vhashnoise<float>, 0.5f);
|
||||
benchmark2 ("vhashnoise(f,f)", vhashnoise<float,float>, 0.5f, 0.5f);
|
||||
benchmark1 ("vhashnoise(v) ", vhashnoise<const Vec3&>, Vec3(0,0,0));
|
||||
benchmark2 ("vhashnoise(v,f)", vhashnoise<const Vec3&,float>, Vec3(0,0,0), 0.5f);
|
||||
bench (" vhashnoise(f)", [&](){ DoNotOptimize (vhashnoise<float>(fval)); });
|
||||
bench (" vhashnoise(f,f)", [&](){ DoNotOptimize (vhashnoise<float,float>(fval, fval)); });
|
||||
bench (" vhashnoise(v)", [&](){ DoNotOptimize (vhashnoise<const Vec3&>(vval)); });
|
||||
bench (" vhashnoise(v,f)", [&](){ DoNotOptimize (vhashnoise<const Vec3&,float>(vval, fval)); });
|
||||
}
|
||||
|
||||
|
||||
@@ -409,6 +413,14 @@ getargs (int argc, const char *argv[])
|
||||
int
|
||||
main (int argc, char const *argv[])
|
||||
{
|
||||
#if !defined(NDEBUG) || defined(OIIO_CI) || defined(OIIO_CODE_COVERAGE)
|
||||
// For the sake of test time, reduce the default iterations for DEBUG,
|
||||
// CI, and code coverage builds. Explicit use of --iters or --trials
|
||||
// will override this, since it comes before the getargs() call.
|
||||
iterations /= 10;
|
||||
ntrials = 1;
|
||||
#endif
|
||||
|
||||
getargs (argc, argv);
|
||||
|
||||
test_perlin ();
|
||||
|
||||
@@ -80,7 +80,7 @@ OSL_NAMESPACE_ENTER
|
||||
namespace pvt {
|
||||
|
||||
|
||||
inline uint32_t
|
||||
inline OSL_HOSTDEVICE uint32_t
|
||||
scramble (uint32_t v0, uint32_t v1=0, uint32_t v2=0)
|
||||
{
|
||||
return OIIO::bjhash::bjfinal (v0, v1, v2^0xdeadbeef);
|
||||
@@ -90,11 +90,11 @@ scramble (uint32_t v0, uint32_t v1=0, uint32_t v2=0)
|
||||
|
||||
/* Static data ---------------------- */
|
||||
|
||||
static float zero[] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
static OSL_DEVICE float zero[] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
|
||||
// Gradient table for 2D. These could be programmed the Ken Perlin way with
|
||||
// some clever bit-twiddling, but this is more clear, and not really slower.
|
||||
static float grad2lut[8][2] = {
|
||||
static OSL_DEVICE float grad2lut[8][2] = {
|
||||
{ -1.0f, -1.0f }, { 1.0f, 0.0f }, { -1.0f, 0.0f }, { 1.0f, 1.0f },
|
||||
{ -1.0f, 1.0f }, { 0.0f, -1.0f }, { 0.0f, 1.0f }, { 1.0f, -1.0f }
|
||||
};
|
||||
@@ -105,7 +105,7 @@ static float grad2lut[8][2] = {
|
||||
// but these 12 (including 4 repeats to make the array length a power
|
||||
// of two) work better. They are not random, they are carefully chosen
|
||||
// to represent a small, isotropic set of directions.
|
||||
static float grad3lut[16][3] = {
|
||||
static OSL_DEVICE float grad3lut[16][3] = {
|
||||
{ 1.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f }, // 12 cube edges
|
||||
{ -1.0f, 0.0f, 1.0f }, { 0.0f, -1.0f, 1.0f },
|
||||
{ 1.0f, 0.0f, -1.0f }, { 0.0f, 1.0f, -1.0f },
|
||||
@@ -117,7 +117,7 @@ static float grad3lut[16][3] = {
|
||||
};
|
||||
|
||||
// Gradient directions for 4D
|
||||
static float grad4lut[32][4] = {
|
||||
static OSL_DEVICE float grad4lut[32][4] = {
|
||||
{ 0.0f, 1.0f, 1.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, -1.0f }, { 0.0f, 1.0f, -1.0f, 1.0f }, { 0.0f, 1.0f, -1.0f, -1.0f }, // 32 tesseract edges
|
||||
{ 0.0f, -1.0f, 1.0f, 1.0f }, { 0.0f, -1.0f, 1.0f, -1.0f }, { 0.0f, -1.0f, -1.0f, 1.0f }, { 0.0f, -1.0f, -1.0f, -1.0f },
|
||||
{ 1.0f, 0.0f, 1.0f, 1.0f }, { 1.0f, 0.0f, 1.0f, -1.0f }, { 1.0f, 0.0f, -1.0f, 1.0f }, { 1.0f, 0.0f, -1.0f, -1.0f },
|
||||
@@ -131,7 +131,7 @@ static float grad4lut[32][4] = {
|
||||
// A lookup table to traverse the simplex around a given point in 4D.
|
||||
// Details can be found where this table is used, in the 4D noise method.
|
||||
/* TODO: This should not be required, backport it from Bill's GLSL code! */
|
||||
static unsigned char simplex[64][4] = {
|
||||
static OSL_DEVICE unsigned char simplex[64][4] = {
|
||||
{0,1,2,3},{0,1,3,2},{0,0,0,0},{0,2,3,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,2,3,0},
|
||||
{0,2,1,3},{0,0,0,0},{0,3,1,2},{0,3,2,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,3,2,0},
|
||||
{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},
|
||||
@@ -148,7 +148,7 @@ static unsigned char simplex[64][4] = {
|
||||
* and gradients-dot-residualvectors in 2D to 4D.
|
||||
*/
|
||||
|
||||
inline float grad1 (int i, int seed)
|
||||
inline OSL_HOSTDEVICE float grad1 (int i, int seed)
|
||||
{
|
||||
int h = scramble (i, seed);
|
||||
float g = 1.0f + (h & 7); // Gradient value is one of 1.0, 2.0, ..., 8.0
|
||||
@@ -157,19 +157,19 @@ inline float grad1 (int i, int seed)
|
||||
return g;
|
||||
}
|
||||
|
||||
inline const float * grad2 (int i, int j, int seed)
|
||||
inline OSL_HOSTDEVICE const float * grad2 (int i, int j, int seed)
|
||||
{
|
||||
int h = scramble (i, j, seed);
|
||||
return grad2lut[h & 7];
|
||||
}
|
||||
|
||||
inline const float * grad3 (int i, int j, int k, int seed)
|
||||
inline OSL_HOSTDEVICE const float * grad3 (int i, int j, int k, int seed)
|
||||
{
|
||||
int h = scramble (i, j, scramble (k, seed));
|
||||
return grad3lut[h & 15];
|
||||
}
|
||||
|
||||
inline const float * grad4 (int i, int j, int k, int l, int seed)
|
||||
inline OSL_HOSTDEVICE const float * grad4 (int i, int j, int k, int l, int seed)
|
||||
{
|
||||
int h = scramble (i, j, scramble (k, l, seed));
|
||||
return grad4lut[h & 31];
|
||||
@@ -179,10 +179,10 @@ inline const float * grad4 (int i, int j, int k, int l, int seed)
|
||||
// 1D simplex noise with derivative.
|
||||
// If the last argument is not null, the analytic derivative
|
||||
// is also calculated.
|
||||
float
|
||||
OSL_HOSTDEVICE float
|
||||
simplexnoise1 (float x, int seed, float *dnoise_dx)
|
||||
{
|
||||
int i0 = quick_floor(x);
|
||||
int i0 = OIIO::ifloor(x);
|
||||
int i1 = i0 + 1;
|
||||
float x0 = x - i0;
|
||||
float x1 = x0 - 1.0f;
|
||||
@@ -227,8 +227,8 @@ simplexnoise1 (float x, int seed, float *dnoise_dx)
|
||||
// 2D simplex noise with derivatives.
|
||||
// If the last two arguments are not null, the analytic derivative
|
||||
// (the 2D gradient of the scalar noise field) is also calculated.
|
||||
float simplexnoise2 (float x, float y, int seed,
|
||||
float *dnoise_dx, float *dnoise_dy)
|
||||
OSL_HOSTDEVICE float simplexnoise2 (float x, float y, int seed,
|
||||
float *dnoise_dx, float *dnoise_dy)
|
||||
{
|
||||
// Skewing factors for 2D simplex grid:
|
||||
const float F2 = 0.366025403; // = 0.5*(sqrt(3.0)-1.0)
|
||||
@@ -239,8 +239,8 @@ float simplexnoise2 (float x, float y, int seed,
|
||||
float s = ( x + y ) * F2; /* Hairy factor for 2D */
|
||||
float xs = x + s;
|
||||
float ys = y + s;
|
||||
int i = quick_floor(xs);
|
||||
int j = quick_floor(ys);
|
||||
int i = OIIO::ifloor(xs);
|
||||
int j = OIIO::ifloor(ys);
|
||||
|
||||
float t = (float) (i + j) * G2;
|
||||
float X0 = i - t; /* Unskew the cell origin back to (x,y) space */
|
||||
@@ -338,7 +338,7 @@ float simplexnoise2 (float x, float y, int seed,
|
||||
// 3D simplex noise with derivatives.
|
||||
// If the last tthree arguments are not null, the analytic derivative
|
||||
// (the 3D gradient of the scalar noise field) is also calculated.
|
||||
float
|
||||
OSL_HOSTDEVICE float
|
||||
simplexnoise3 (float x, float y, float z, int seed,
|
||||
float *dnoise_dx, float *dnoise_dy, float *dnoise_dz)
|
||||
{
|
||||
@@ -354,9 +354,9 @@ simplexnoise3 (float x, float y, float z, int seed,
|
||||
float xs = x+s;
|
||||
float ys = y+s;
|
||||
float zs = z+s;
|
||||
int i = quick_floor(xs);
|
||||
int j = quick_floor(ys);
|
||||
int k = quick_floor(zs);
|
||||
int i = OIIO::ifloor(xs);
|
||||
int j = OIIO::ifloor(ys);
|
||||
int k = OIIO::ifloor(zs);
|
||||
|
||||
float t = (float)(i+j+k)*G3;
|
||||
float X0 = i-t; // Unskew the cell origin back to (x,y,z) space
|
||||
@@ -524,7 +524,7 @@ simplexnoise3 (float x, float y, float z, int seed,
|
||||
// 4D simplex noise with derivatives.
|
||||
// If the last four arguments are not null, the analytic derivative
|
||||
// (the 4D gradient of the scalar noise field) is also calculated.
|
||||
float
|
||||
OSL_HOSTDEVICE float
|
||||
simplexnoise4 (float x, float y, float z, float w, int seed,
|
||||
float *dnoise_dx, float *dnoise_dy,
|
||||
float *dnoise_dz, float *dnoise_dw)
|
||||
@@ -547,10 +547,10 @@ simplexnoise4 (float x, float y, float z, float w, int seed,
|
||||
float ys = y + s;
|
||||
float zs = z + s;
|
||||
float ws = w + s;
|
||||
int i = quick_floor(xs);
|
||||
int j = quick_floor(ys);
|
||||
int k = quick_floor(zs);
|
||||
int l = quick_floor(ws);
|
||||
int i = OIIO::ifloor(xs);
|
||||
int j = OIIO::ifloor(ys);
|
||||
int k = OIIO::ifloor(zs);
|
||||
int l = OIIO::ifloor(ws);
|
||||
|
||||
float t = (i + j + k + l) * G4; // Factor for 4D unskewing
|
||||
float X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
|
||||
|
||||
@@ -10,6 +10,14 @@ if (BUILDSTATIC)
|
||||
ADD_LIBRARY ( oslquery STATIC ${liboslquery_srcs} )
|
||||
else ()
|
||||
ADD_LIBRARY ( oslquery SHARED ${liboslquery_srcs} )
|
||||
|
||||
if (VERBOSE)
|
||||
message(STATUS "Setting SOVERSION to: ${SOVERSION}")
|
||||
endif ()
|
||||
set_target_properties( oslquery
|
||||
PROPERTIES
|
||||
VERSION ${OSL_VERSION_MAJOR}.${OSL_VERSION_MINOR}.${OSL_VERSION_PATCH}
|
||||
SOVERSION ${SOVERSION} )
|
||||
endif ()
|
||||
|
||||
TARGET_LINK_LIBRARIES ( oslquery ${OPENIMAGEIO_LIBRARIES} ${ILMBASE_LIBRARIES} ${Boost_LIBRARIES} )
|
||||
|
||||
@@ -267,6 +267,99 @@ OSOReaderQuery::codemarker (const char *name)
|
||||
|
||||
|
||||
|
||||
OSLQuery::Parameter::Parameter (const Parameter& src)
|
||||
: name(src.name), type(src.type), isoutput(src.isoutput),
|
||||
validdefault(src.validdefault), varlenarray(src.varlenarray),
|
||||
isstruct(src.isstruct), isclosure(src.isclosure),
|
||||
idefault(src.idefault), fdefault(src.fdefault),
|
||||
sdefault(src.sdefault), spacename(src.spacename),
|
||||
fields(src.fields), structname(src.structname),
|
||||
metadata(src.metadata)
|
||||
{
|
||||
if (type.basetype == TypeDesc::INT)
|
||||
data = idefault.data();
|
||||
else if (type.basetype == TypeDesc::FLOAT)
|
||||
data = fdefault.data();
|
||||
else if (type.basetype == TypeDesc::STRING)
|
||||
data = sdefault.data();
|
||||
}
|
||||
|
||||
|
||||
|
||||
OSLQuery::Parameter::Parameter (Parameter&& src)
|
||||
: name(src.name), type(src.type), isoutput(src.isoutput),
|
||||
validdefault(src.validdefault), varlenarray(src.varlenarray),
|
||||
isstruct(src.isstruct), isclosure(src.isclosure),
|
||||
idefault(src.idefault), fdefault(src.fdefault),
|
||||
sdefault(src.sdefault), spacename(src.spacename),
|
||||
fields(src.fields), structname(src.structname),
|
||||
metadata(src.metadata)
|
||||
{
|
||||
if (type.basetype == TypeDesc::INT)
|
||||
data = idefault.data();
|
||||
else if (type.basetype == TypeDesc::FLOAT)
|
||||
data = fdefault.data();
|
||||
else if (type.basetype == TypeDesc::STRING)
|
||||
data = sdefault.data();
|
||||
}
|
||||
|
||||
|
||||
|
||||
const OSLQuery::Parameter&
|
||||
OSLQuery::Parameter::operator= (const Parameter& src)
|
||||
{
|
||||
name = src.name;
|
||||
type = src.type;
|
||||
isoutput = src.isoutput;
|
||||
validdefault = src.validdefault;
|
||||
varlenarray = src.varlenarray;
|
||||
isstruct = src.isstruct;
|
||||
isclosure = src.isclosure;
|
||||
idefault = src.idefault;
|
||||
fdefault = src.fdefault;
|
||||
sdefault = src.sdefault;
|
||||
spacename = src.spacename;
|
||||
fields = src.fields;
|
||||
structname = src.structname;
|
||||
metadata = src.metadata;
|
||||
if (type.basetype == TypeDesc::INT)
|
||||
data = idefault.data();
|
||||
else if (type.basetype == TypeDesc::FLOAT)
|
||||
data = fdefault.data();
|
||||
else if (type.basetype == TypeDesc::STRING)
|
||||
data = sdefault.data();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const OSLQuery::Parameter&
|
||||
OSLQuery::Parameter::operator= (Parameter&& src)
|
||||
{
|
||||
name = src.name;
|
||||
type = src.type;
|
||||
isoutput = src.isoutput;
|
||||
validdefault = src.validdefault;
|
||||
varlenarray = src.varlenarray;
|
||||
isstruct = src.isstruct;
|
||||
isclosure = src.isclosure;
|
||||
idefault = std::move(src.idefault);
|
||||
fdefault = std::move(src.fdefault);
|
||||
sdefault = std::move(src.sdefault);
|
||||
spacename = src.spacename;
|
||||
fields = src.fields;
|
||||
structname = src.structname;
|
||||
metadata = std::move(src.metadata);
|
||||
if (type.basetype == TypeDesc::INT)
|
||||
data = idefault.data();
|
||||
else if (type.basetype == TypeDesc::FLOAT)
|
||||
data = fdefault.data();
|
||||
else if (type.basetype == TypeDesc::STRING)
|
||||
data = sdefault.data();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
OSLQuery::OSLQuery ()
|
||||
{
|
||||
|
||||
@@ -20,6 +20,14 @@ macro (add_oiio_plugin)
|
||||
add_library (${_target_name} SHARED ${_plugin_UNPARSED_ARGUMENTS})
|
||||
target_link_libraries (${_target_name} ${OPENIMAGEIO_LIBRARIES} ${_plugin_LINK_LIBRARIES})
|
||||
set_target_properties (${_target_name} PROPERTIES PREFIX "" FOLDER "Plugins")
|
||||
if (VERBOSE)
|
||||
message(STATUS "Setting SOVERSION to: ${SOVERSION}")
|
||||
endif ()
|
||||
set_target_properties( ${_target_name}
|
||||
PROPERTIES
|
||||
VERSION ${OSL_VERSION_MAJOR}.${OSL_VERSION_MINOR}.${OSL_VERSION_PATCH}
|
||||
SOVERSION ${SOVERSION} )
|
||||
|
||||
install_targets (${_target_name})
|
||||
endmacro ()
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <OpenImageIO/strutil.h>
|
||||
#include <OpenImageIO/filesystem.h>
|
||||
#include <OpenImageIO/thread.h>
|
||||
#include <OpenImageIO/imagebuf.h>
|
||||
#include <OpenImageIO/imagebufalgo.h>
|
||||
|
||||
#include <OSL/oslexec.h>
|
||||
#include <OSL/oslcomp.h>
|
||||
@@ -87,15 +87,9 @@ public:
|
||||
OSLInput ();
|
||||
virtual ~OSLInput ();
|
||||
virtual const char * format_name (void) const { return "osl"; }
|
||||
#if OPENIMAGEIO_VERSION >= 10600
|
||||
virtual int supports (string_view feature) const {
|
||||
return (feature == "procedural");
|
||||
}
|
||||
#else /* Remove the following when OIIO <= 1.5 is no longer needed */
|
||||
virtual bool supports (const std::string& feature) const {
|
||||
return (feature == "procedural");
|
||||
}
|
||||
#endif
|
||||
virtual bool valid_file (const std::string &filename) const;
|
||||
virtual bool open (const std::string &name, ImageSpec &newspec);
|
||||
virtual bool open (const std::string &name, ImageSpec &newspec,
|
||||
@@ -103,6 +97,7 @@ public:
|
||||
virtual bool close ();
|
||||
virtual int current_subimage (void) const { return m_subimage; }
|
||||
virtual int current_miplevel (void) const { return m_miplevel; }
|
||||
#if OIIO_PLUGIN_VERSION < 21 /* OIIO < 1.9 */
|
||||
virtual bool seek_subimage (int subimage, int miplevel, ImageSpec &newspec);
|
||||
virtual bool read_native_scanline (int y, int z, void *data);
|
||||
virtual bool read_native_scanlines (int ybegin, int yend, int z,
|
||||
@@ -110,6 +105,19 @@ public:
|
||||
virtual bool read_native_tile (int x, int y, int z, void *data);
|
||||
virtual bool read_native_tiles (int xbegin, int xend, int ybegin, int yend,
|
||||
int zbegin, int zend, void *data);
|
||||
#else
|
||||
virtual bool seek_subimage (int subimage, int miplevel);
|
||||
virtual bool read_native_scanline (int subimage, int miplevel,
|
||||
int y, int z, void *data);
|
||||
virtual bool read_native_scanlines (int subimage, int miplevel,
|
||||
int ybegin, int yend, int z,
|
||||
void *data);
|
||||
virtual bool read_native_tile (int subimage, int miplevel,
|
||||
int x, int y, int z, void *data);
|
||||
virtual bool read_native_tiles (int subimage, int miplevel,
|
||||
int xbegin, int xend, int ybegin, int yend,
|
||||
int zbegin, int zend, void *data);
|
||||
#endif
|
||||
private:
|
||||
std::string m_filename; ///< Stash the filename
|
||||
ShaderGroupRef m_group;
|
||||
@@ -134,6 +142,8 @@ OIIO_PLUGIN_EXPORTS_BEGIN
|
||||
|
||||
OIIO_EXPORT ImageInput *osl_input_imageio_create () { return new OSLInput; }
|
||||
|
||||
OIIO_EXPORT void osl_input_imageio_delete (ImageInput *p) { delete p; }
|
||||
|
||||
OIIO_EXPORT int osl_imageio_version = OIIO_PLUGIN_VERSION;
|
||||
|
||||
OIIO_EXPORT const char * osl_input_extensions[] = {
|
||||
@@ -227,7 +237,7 @@ static ErrorRecorder errhandler;
|
||||
static void
|
||||
setup_shadingsys ()
|
||||
{
|
||||
lock_guard lock (shading_mutex);
|
||||
OIIO::lock_guard lock (shading_mutex);
|
||||
if (! shadingsys) {
|
||||
renderer = new OIIO_RendererServices (TextureSystem::create(true));
|
||||
shadingsys = new ShadingSystem (renderer, NULL, &errhandler);
|
||||
@@ -490,14 +500,14 @@ OSLInput::open (const std::string &name, ImageSpec &newspec,
|
||||
}
|
||||
// std::cout << "Processing group specification:\n---\n"
|
||||
// << groupspec << "\n---\n";
|
||||
lock_guard lock (shading_mutex);
|
||||
OIIO::lock_guard lock (shading_mutex);
|
||||
m_group = shadingsys->ShaderGroupBegin ("", "surface", groupspec);
|
||||
if (! m_group)
|
||||
return false; // Failed
|
||||
shadingsys->ShaderGroupEnd ();
|
||||
}
|
||||
if (Strutil::ends_with (shadername, ".oso")) { // Compiled shader
|
||||
lock_guard lock (shading_mutex);
|
||||
OIIO::lock_guard lock (shading_mutex);
|
||||
shadername.remove_suffix (4);
|
||||
m_group = shadingsys->ShaderGroupBegin ();
|
||||
for (size_t p = 0, np = m_topspec.extra_attribs.size(); p < np; ++p) {
|
||||
@@ -515,7 +525,7 @@ OSLInput::open (const std::string &name, ImageSpec &newspec,
|
||||
if (Strutil::ends_with (shadername, ".osl")) { // shader source
|
||||
}
|
||||
if (Strutil::ends_with (shadername, ".oslbody")) { // shader source
|
||||
lock_guard lock (shading_mutex);
|
||||
OIIO::lock_guard lock (shading_mutex);
|
||||
shadername.remove_suffix (8);
|
||||
static int exprcount = 0;
|
||||
std::string exprname = OIIO::Strutil::format("expr_%d", exprcount++);
|
||||
@@ -554,7 +564,16 @@ OSLInput::open (const std::string &name, ImageSpec &newspec,
|
||||
TypeDesc(TypeDesc::STRING,m_outputs.size()),
|
||||
&m_outputs[0]);
|
||||
|
||||
#if OIIO_PLUGIN_VERSION < 21
|
||||
return ok && seek_subimage (0, 0, newspec);
|
||||
#else
|
||||
ok &= seek_subimage (0, 0);
|
||||
if (ok)
|
||||
newspec = spec();
|
||||
else
|
||||
close ();
|
||||
return ok;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -569,10 +588,16 @@ OSLInput::close ()
|
||||
|
||||
|
||||
bool
|
||||
OSLInput::seek_subimage (int subimage, int miplevel, ImageSpec &newspec)
|
||||
OSLInput::seek_subimage (int subimage, int miplevel
|
||||
#if OIIO_PLUGIN_VERSION < 21
|
||||
, ImageSpec &newspec
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if (subimage == current_subimage() && miplevel == current_miplevel()) {
|
||||
#if OIIO_PLUGIN_VERSION < 21
|
||||
newspec = spec();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -593,15 +618,27 @@ OSLInput::seek_subimage (int subimage, int miplevel, ImageSpec &newspec)
|
||||
m_spec.full_height = m_spec.height;
|
||||
m_spec.full_depth = m_spec.depth;
|
||||
}
|
||||
#if OIIO_PLUGIN_VERSION < 21
|
||||
newspec = spec();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
OSLInput::read_native_scanlines (int ybegin, int yend, int z, void *data)
|
||||
OSLInput::read_native_scanlines (
|
||||
#if OIIO_PLUGIN_VERSION >= 21
|
||||
int subimage, int miplevel,
|
||||
#endif
|
||||
int ybegin, int yend, int z, void *data)
|
||||
{
|
||||
#if OIIO_PLUGIN_VERSION >= 21
|
||||
lock_guard lock (m_mutex);
|
||||
if (! seek_subimage (subimage, miplevel))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
// Create an ImageBuf wrapper of the user's data
|
||||
ImageSpec spec = m_spec; // Make a spec that describes just this scanline
|
||||
spec.y = ybegin;
|
||||
@@ -622,17 +659,35 @@ OSLInput::read_native_scanlines (int ybegin, int yend, int z, void *data)
|
||||
|
||||
|
||||
bool
|
||||
OSLInput::read_native_scanline (int y, int z, void *data)
|
||||
OSLInput::read_native_scanline (
|
||||
#if OIIO_PLUGIN_VERSION >= 21
|
||||
int subimage, int miplevel,
|
||||
#endif
|
||||
int y, int z, void *data)
|
||||
{
|
||||
#if OIIO_PLUGIN_VERSION >= 21
|
||||
return read_native_scanlines (subimage, miplevel, y, y+1, z, data);
|
||||
#else
|
||||
return read_native_scanlines (y, y+1, z, data);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
OSLInput::read_native_tiles (int xbegin, int xend, int ybegin, int yend,
|
||||
OSLInput::read_native_tiles (
|
||||
#if OIIO_PLUGIN_VERSION >= 21
|
||||
int subimage, int miplevel,
|
||||
#endif
|
||||
int xbegin, int xend, int ybegin, int yend,
|
||||
int zbegin, int zend, void *data)
|
||||
{
|
||||
#if OIIO_PLUGIN_VERSION >= 21
|
||||
lock_guard lock (m_mutex);
|
||||
if (! seek_subimage (subimage, miplevel))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
// Create an ImageBuf wrapper of the user's data
|
||||
ImageSpec spec = m_spec; // Make a spec that describes just this scanline
|
||||
spec.x = xbegin;
|
||||
@@ -655,10 +710,24 @@ OSLInput::read_native_tiles (int xbegin, int xend, int ybegin, int yend,
|
||||
|
||||
|
||||
bool
|
||||
OSLInput::read_native_tile (int x, int y, int z, void *data)
|
||||
OSLInput::read_native_tile (
|
||||
#if OIIO_PLUGIN_VERSION >= 21
|
||||
int subimage, int miplevel,
|
||||
#endif
|
||||
int x, int y, int z, void *data)
|
||||
{
|
||||
#if OIIO_PLUGIN_VERSION >= 21
|
||||
lock_guard lock (m_mutex);
|
||||
if (! seek_subimage (subimage, miplevel))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return
|
||||
read_native_tiles (x, std::min (x+m_spec.tile_width, m_spec.x+m_spec.width),
|
||||
read_native_tiles (
|
||||
#if OIIO_PLUGIN_VERSION >= 21
|
||||
subimage, miplevel,
|
||||
#endif
|
||||
x, std::min (x+m_spec.tile_width, m_spec.x+m_spec.width),
|
||||
y, std::min (y+m_spec.tile_height, m_spec.y+m_spec.height),
|
||||
z, std::min (z+m_spec.tile_depth, m_spec.z+m_spec.depth),
|
||||
data);
|
||||
|
||||
+54
-13
@@ -61,6 +61,8 @@ usage ()
|
||||
"\t-O0, -O1, -O2 Set optimization level (default=1)\n"
|
||||
"\t-d Debug mode\n"
|
||||
"\t-E Only preprocess the input and output to stdout\n"
|
||||
"\t-Werror Treat all warnings as errors\n"
|
||||
"\t-buffer (debugging) Force compile from buffer\n"
|
||||
;
|
||||
}
|
||||
|
||||
@@ -108,7 +110,6 @@ static OSLC_ErrorHandler default_oslc_error_handler;
|
||||
|
||||
|
||||
|
||||
|
||||
int
|
||||
main (int argc, const char *argv[])
|
||||
{
|
||||
@@ -118,13 +119,17 @@ main (int argc, const char *argv[])
|
||||
|
||||
OIIO::Filesystem::convert_native_arguments (argc, (const char **)argv);
|
||||
|
||||
std::vector<std::string> args;
|
||||
bool quiet = false;
|
||||
if (argc <= 1) {
|
||||
usage ();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
std::vector<std::string> args;
|
||||
bool quiet = false;
|
||||
bool compile_from_buffer = false;
|
||||
std::string shader_path;
|
||||
|
||||
// Parse arguments from command line
|
||||
for (int a = 1; a < argc; ++a) {
|
||||
if (! strcmp (argv[a], "--help") | ! strcmp (argv[a], "-h")) {
|
||||
usage ();
|
||||
@@ -135,12 +140,15 @@ main (int argc, const char *argv[])
|
||||
! strcmp (argv[a], "-d") ||
|
||||
! strcmp (argv[a], "-E") ||
|
||||
! strcmp (argv[a], "-O") || ! strcmp (argv[a], "-O0") ||
|
||||
! strcmp (argv[a], "-O1") || ! strcmp (argv[a], "-O2")) {
|
||||
! strcmp (argv[a], "-O1") || ! strcmp (argv[a], "-O2") ||
|
||||
! strcmp (argv[a], "-Werror")
|
||||
) {
|
||||
// Valid command-line argument
|
||||
args.emplace_back(argv[a]);
|
||||
quiet |= (strcmp (argv[a], "-q") == 0);
|
||||
}
|
||||
else if (! strcmp (argv[a], "-o") && a < argc-1) {
|
||||
// Output filepath
|
||||
args.emplace_back(argv[a]);
|
||||
++a;
|
||||
args.emplace_back(argv[a]);
|
||||
@@ -149,18 +157,51 @@ main (int argc, const char *argv[])
|
||||
(argv[a][1] == 'D' || argv[a][1] == 'U' || argv[a][1] == 'I')) {
|
||||
args.emplace_back(argv[a]);
|
||||
}
|
||||
else if (!strcmp(argv[a], "-buffer")) {
|
||||
compile_from_buffer = true;
|
||||
}
|
||||
else {
|
||||
OSLCompiler compiler (&default_oslc_error_handler);
|
||||
bool ok = compiler.compile (argv[a], args);
|
||||
if (ok) {
|
||||
if (!quiet)
|
||||
std::cout << "Compiled " << argv[a] << " -> "
|
||||
<< compiler.output_filename() << "\n";
|
||||
} else {
|
||||
std::cout << "FAILED " << argv[a] << "\n";
|
||||
return EXIT_FAILURE;
|
||||
// Shader to compile
|
||||
shader_path = argv[a];
|
||||
}
|
||||
}
|
||||
|
||||
if (shader_path.empty ()) {
|
||||
std::cout << "ERROR: Missing shader path" << "\n\n";
|
||||
usage ();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
OSLCompiler compiler (&default_oslc_error_handler);
|
||||
bool ok = true;
|
||||
if (compile_from_buffer) {
|
||||
// Force a compile-from-buffer for debugging purposes
|
||||
std::string sourcecode;
|
||||
ok = OIIO::Filesystem::read_text_file (shader_path, sourcecode);
|
||||
std::string osobuffer;
|
||||
if (ok)
|
||||
ok = compiler.compile_buffer (sourcecode, osobuffer, args, "",
|
||||
shader_path);
|
||||
if (ok) {
|
||||
std::ofstream file;
|
||||
OIIO::Filesystem::open (file, compiler.output_filename());
|
||||
if (file.good()) {
|
||||
file << osobuffer;
|
||||
file.close ();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Ordinary compile from file
|
||||
ok = compiler.compile (shader_path, args);
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
if (!quiet)
|
||||
std::cout << "Compiled " << shader_path << " -> " << compiler.output_filename() << "\n";
|
||||
}
|
||||
else {
|
||||
std::cout << "FAILED " << shader_path << "\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
+20
-1
@@ -36,7 +36,17 @@ and was distributed under BSD licensing terms identical to the
|
||||
Sony Pictures Imageworks terms, above.
|
||||
*/
|
||||
|
||||
|
||||
/// <doc... oslinfo_source>
|
||||
///
|
||||
/// Example program using OSLQuery
|
||||
/// ==============================
|
||||
///
|
||||
/// This is the full text of `oslinfo`, a command-line utility that
|
||||
/// for any shader, will print out its parameters (name, type, default
|
||||
/// values, and metadata).
|
||||
///
|
||||
/// ~~~~
|
||||
/// <script type="preformatted">
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
@@ -58,6 +68,7 @@ static std::string oneparam;
|
||||
|
||||
|
||||
|
||||
// Print the default values for a paarameter built out of integers.
|
||||
static void
|
||||
print_default_string_vals (const OSLQuery::Parameter *p, bool verbose)
|
||||
{
|
||||
@@ -78,6 +89,8 @@ print_default_string_vals (const OSLQuery::Parameter *p, bool verbose)
|
||||
|
||||
|
||||
|
||||
// Print the default values for a paarameter built out of floats (including
|
||||
// color, point, etc., or arrays thereof).
|
||||
static void
|
||||
print_default_int_vals (const OSLQuery::Parameter *p, bool verbose)
|
||||
{
|
||||
@@ -102,6 +115,7 @@ print_default_int_vals (const OSLQuery::Parameter *p, bool verbose)
|
||||
|
||||
|
||||
|
||||
// Print the default values for a paarameter built out of strings.
|
||||
static void
|
||||
print_default_float_vals (const OSLQuery::Parameter *p, bool verbose)
|
||||
{
|
||||
@@ -128,6 +142,7 @@ print_default_float_vals (const OSLQuery::Parameter *p, bool verbose)
|
||||
|
||||
|
||||
|
||||
// Print all the metadata for a parameter.
|
||||
static void
|
||||
print_metadata (const OSLQuery::Parameter &m)
|
||||
{
|
||||
@@ -264,3 +279,7 @@ main (int argc, char *argv[])
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/// </script>
|
||||
/// ~~~~
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user