Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e47ef444e | ||
|
|
e94b0fec1e | ||
|
|
ee3403a916 | ||
|
|
da77f89205 | ||
|
|
5fede29c6e | ||
|
|
434914e7ee | ||
|
|
726dc3ff0c | ||
|
|
a88d708bc8 | ||
|
|
90d94caecb | ||
|
|
5da8e8c8bb | ||
|
|
9ceac106fa | ||
|
|
726049ad49 | ||
|
|
710d1154b3 | ||
|
|
04645499ab | ||
|
|
0d9ab3c495 | ||
|
|
3d52f3906b | ||
|
|
e154a220b6 | ||
|
|
da8f2be156 | ||
|
|
bc864771df | ||
|
|
b38487532d | ||
|
|
7985893a76 | ||
|
|
58ae6a1551 | ||
|
|
9320db9f2a | ||
|
|
4d39f8099f | ||
|
|
41a45b68ea | ||
|
|
8374278a07 | ||
|
|
78b861f34a | ||
|
|
7710b1be46 | ||
|
|
0e55efbd99 | ||
|
|
0d4c343759 | ||
|
|
9636c8c66c | ||
|
|
784bf53e88 | ||
|
|
cdfec4f31d | ||
|
|
3567aac515 | ||
|
|
00ea8a80fd | ||
|
|
a95116f793 | ||
|
|
b8a100e427 | ||
|
|
0210c88374 | ||
|
|
baca4c2de6 | ||
|
|
e4766b4516 | ||
|
|
f00da4f788 | ||
|
|
e327241a30 | ||
|
|
a569d4f0be | ||
|
|
46250b4c10 | ||
|
|
e235661479 | ||
|
|
fdc0579931 | ||
|
|
d4faecd79d | ||
|
|
f449749f24 | ||
|
|
8c2d8c03b4 | ||
|
|
373e359b49 | ||
|
|
7afd948737 | ||
|
|
473bbfcdbd | ||
|
|
05f4acee5b | ||
|
|
a4e779c44f | ||
|
|
271f8bc30e | ||
|
|
9e30a4e6df | ||
|
|
3df1aa2f98 | ||
|
|
afc44289fc | ||
|
|
3bf59982e5 | ||
|
|
cce40c38b8 | ||
|
|
1863d04edc | ||
|
|
06c42d5c18 | ||
|
|
8dae508b4f | ||
|
|
b4f0517f0c | ||
|
|
5e10537608 | ||
|
|
4962ac2a1b | ||
|
|
1956e83954 | ||
|
|
50ccc8736f | ||
|
|
6a5c50e3f3 | ||
|
|
49aac8740d | ||
|
|
c06df65331 | ||
|
|
4e9e640e5b | ||
|
|
b76a53a779 | ||
|
|
4e958e92c1 | ||
|
|
188ec977a5 | ||
|
|
417088e91a | ||
|
|
16d217a21f | ||
|
|
6a2e2960ef | ||
|
|
606beade27 | ||
|
|
71a9310f0b | ||
|
|
5c49a7c6b5 | ||
|
|
abdc966a19 | ||
|
|
374543f040 | ||
|
|
089268b87d | ||
|
|
74b2b30669 | ||
|
|
91699ba7d3 | ||
|
|
4afe9244e8 | ||
|
|
ed9857c416 | ||
|
|
cd22f602a4 | ||
|
|
17d211a3d3 | ||
|
|
20299563ee | ||
|
|
5600d020a0 | ||
|
|
37f4bbc1a2 | ||
|
|
b13b7f08b0 | ||
|
|
7ebfbc4a05 | ||
|
|
e402988611 | ||
|
|
88be276ec1 | ||
|
|
6f1fedb08d | ||
|
|
0bd014cfe2 | ||
|
|
209c672b0b | ||
|
|
49cda0a472 | ||
|
|
787d8ce94e | ||
|
|
89f1e69d88 | ||
|
|
fff0c5985d | ||
|
|
a047c065b7 | ||
|
|
bc735d02cf | ||
|
|
f64f6effc0 | ||
|
|
a620231929 | ||
|
|
df818a7045 | ||
|
|
bee79468e0 | ||
|
|
f8ad0281aa | ||
|
|
b9cb0ae74c | ||
|
|
5879868561 | ||
|
|
c5fe678c9e | ||
|
|
dbe8c214e4 | ||
|
|
fbe141b42b | ||
|
|
a68a972602 | ||
|
|
23edc185a0 | ||
|
|
203dcecafe | ||
|
|
bbbc28d2ff | ||
|
|
649f0b86a3 | ||
|
|
31e92ddc06 | ||
|
|
9ae5b69fd8 | ||
|
|
3bd3778610 | ||
|
|
a8d3ac06e6 | ||
|
|
c0a5998c19 | ||
|
|
5dad5076bc | ||
|
|
317c59ed73 | ||
|
|
66c9b61d72 | ||
|
|
8036e174fb | ||
|
|
b064b25721 | ||
|
|
8d1d9f0cf6 | ||
|
|
1c196d935c | ||
|
|
a878883eeb | ||
|
|
1b3c96603c | ||
|
|
e468ef7595 | ||
|
|
fae61e699f | ||
|
|
7b6854823d | ||
|
|
f84126fb3e | ||
|
|
395e58d6bf | ||
|
|
75401bda4c | ||
|
|
8530aa059a | ||
|
|
bd7fd4cf8c | ||
|
|
61ea4c9a31 | ||
|
|
afec48ebde | ||
|
|
9ef1741056 | ||
|
|
1e8ef316ac | ||
|
|
aafb5cb74e | ||
|
|
d0e49675e5 | ||
|
|
dde0a3451a | ||
|
|
3187864f9b | ||
|
|
66747ac1e6 | ||
|
|
d867d98a50 |
@@ -4,7 +4,6 @@
|
||||
|
||||
Language: Cpp
|
||||
BasedOnStyle: WebKit
|
||||
SpaceBeforeParens: ControlStatements
|
||||
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
|
||||
@@ -43,3 +43,7 @@ c1045f2c2845a98e661c7181932a031eb3c76063
|
||||
# clang-format: the very last piece of the puzzle (#1555)
|
||||
4ee62cd2ef05543f818f4d95a19efc1d684a7381
|
||||
5be7c6bd4e7bd2e560cb6be8c06f11985384a87a
|
||||
|
||||
# Raise CI formatting standard to clang-format 17
|
||||
a9ce35135e6c022d538a4a184fee1b5ce908aed8
|
||||
90d94caecbb97141c9df63abc634be6e8394b6c3
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
<!-- Put an 'x' in the boxes as you complete the checklist items -->
|
||||
|
||||
- [ ] I have read the [contribution guidelines](../CONTRIBUTING.md).
|
||||
- [ ] I have previously submitted a [Contributor License Agreement](http://opensource.imageworks.com/cla/).
|
||||
- [ ] I have updated the documentation, if applicable.
|
||||
- [ ] I have ensured that the change is tested somewhere in the testsuite (adding new test cases if necessary).
|
||||
- [ ] My code follows the prevailing code style of this project.
|
||||
|
||||
- [ ] My code follows the prevailing code style of this project. If I haven't
|
||||
already run clang-format v17 before submitting, I definitely will look at
|
||||
the CI test that runs clang-format and fix anything that it highlights as
|
||||
being nonconforming.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2008-present Contributors to the Open Shading Language project.
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
@@ -14,11 +14,20 @@ on:
|
||||
branches:
|
||||
- main
|
||||
- '*analysis*'
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- '**.rst'
|
||||
- '**.tex'
|
||||
# Allow manual kicking off of the workflow from github.com
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: read-all
|
||||
|
||||
# Allow subsequent pushes to the same PR or REF to cancel any previous jobs.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -30,7 +39,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- desc: sonary gcc9/C++14 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
|
||||
- desc: sonar gcc9/C++14 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
|
||||
nametag: static-analysis-sonar
|
||||
os: ubuntu-latest
|
||||
vfxyear: 2022
|
||||
@@ -40,7 +49,7 @@ jobs:
|
||||
python_ver: 3.9
|
||||
pybind11_ver: v2.9.0
|
||||
simd: avx2,f16c
|
||||
batched: b8_AVX2
|
||||
batched: b8_AVX2,b16_AVX512
|
||||
coverage: 1
|
||||
# skip_tests: 1
|
||||
sonar: 1
|
||||
|
||||
@@ -20,8 +20,10 @@ on:
|
||||
- '**.rst'
|
||||
- '**.tex'
|
||||
schedule:
|
||||
# Full nightly build
|
||||
# Full nightly build, for the main project repo (not for forks)
|
||||
- cron: "0 6 * * *"
|
||||
if: github.repository == 'AcademySoftwareFoundation/OpenShadingLanguage'
|
||||
|
||||
|
||||
permissions: read-all
|
||||
|
||||
@@ -34,65 +36,58 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- desc: gcc6/C++14 llvm9 py2.7 boost1.66 exr2.3 oiio2.2 sse2
|
||||
nametag: linux-vfx2019
|
||||
os: ubuntu-latest
|
||||
- desc: gcc6/C++14 llvm9 py2.7 boost1.66 exr2.4 oiio2.3 sse2
|
||||
nametag: linux-vfx2020
|
||||
runner: ubuntu-latest
|
||||
container: aswftesting/ci-osl:2019-clang9
|
||||
vfxyear: 2019
|
||||
vfxsuffix: -clang9
|
||||
cxx_std: 14
|
||||
openimageio_ver: v2.3.17.0
|
||||
openexr_ver: v2.4.3
|
||||
openimageio_ver: v2.4.13.0
|
||||
python_ver: 2.7
|
||||
pybind11_ver: v2.4.2
|
||||
- desc: clang9/C++14 llvm9 oiio-release boost1.66 avx2 exr2.3 py2.7
|
||||
setenvs: export CMAKE_VERSION=3.15.5
|
||||
- desc: clang9/C++14 llvm9 oiio-release boost1.66 avx2 exr2.4 py2.7
|
||||
nametag: linux-clang9-llvm9
|
||||
os: ubuntu-18.04
|
||||
runner: ubuntu-20.04
|
||||
container: aswftesting/ci-osl:2019-clang9
|
||||
vfxyear: 2019
|
||||
vfxsuffix: -clang9
|
||||
cc_compiler: clang
|
||||
cxx_compiler: clang++
|
||||
cxx_std: 14
|
||||
openexr_ver: v2.4.3
|
||||
openimageio_ver: release
|
||||
python_ver: 2.7
|
||||
# pybind11_ver: v2.9.0
|
||||
simd: avx
|
||||
- desc: GPU Cuda10 gcc6/C++14 llvm10 py2.7 boost-1.70 exr-2.3 OIIO-master avx2
|
||||
nametag: linux-optix7-2019
|
||||
os: ubuntu-latest
|
||||
vfxyear: 2019
|
||||
vfxsuffix: -clang10
|
||||
cxx_std: 14
|
||||
openimageio_ver: master
|
||||
python_ver: 2.7
|
||||
# pybind11_ver: v2.9.0
|
||||
simd: avx2,f16c
|
||||
skip_tests: 1
|
||||
setenvs: export OSL_CMAKE_FLAGS="-DUSE_OPTIX=1" OPTIX_VERSION=7.0
|
||||
setenvs: export CMAKE_VERSION=3.15.5
|
||||
- desc: gcc6/C++14 llvm10 py3.7 boost1.70 exr2.4 oiio2.2 sse4
|
||||
nametag: linux-vfx2020
|
||||
os: ubuntu-latest
|
||||
runner: ubuntu-latest
|
||||
container: aswftesting/ci-osl:2020
|
||||
vfxyear: 2020
|
||||
cxx_std: 14
|
||||
openimageio_ver: v2.3.17.0
|
||||
openimageio_ver: v2.4.13.0
|
||||
python_ver: 3.7
|
||||
pybind11_ver: v2.5.0
|
||||
simd: sse4.2
|
||||
setenvs: export CONAN_LLVM_VERSION=10.0.1
|
||||
- desc: gcc9/C++17 llvm11 py3.7 boost1.73 exr2.5 oiio2.2 avx2 batch-b8avx2
|
||||
- desc: gcc9/C++17 llvm11 py3.7 boost1.73 exr2.5 oiio2.3 avx2 batch-b8avx2
|
||||
nametag: linux-vfx2021
|
||||
os: ubuntu-latest
|
||||
runner: ubuntu-latest
|
||||
container: aswftesting/ci-osl:2021-clang11
|
||||
vfxyear: 2021
|
||||
vfxsuffix: -clang11
|
||||
cxx_std: 17
|
||||
openimageio_ver: dev-2.3
|
||||
openimageio_ver: v2.4.13.0
|
||||
python_ver: 3.7
|
||||
pybind11_ver: v2.7.0
|
||||
simd: avx2,f16c
|
||||
batched: b8_AVX2_noFMA
|
||||
- desc: gcc9/C++17 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
|
||||
- desc: gcc9/C++17 llvm13 py3.9 boost1.76 exr3.1 oiio-rel avx2
|
||||
nametag: linux-vfx2022
|
||||
os: ubuntu-latest
|
||||
runner: ubuntu-latest
|
||||
container: aswftesting/ci-osl:2022-clang13
|
||||
vfxyear: 2022
|
||||
vfxsuffix: -clang13
|
||||
cxx_std: 17
|
||||
openimageio_ver: release
|
||||
python_ver: 3.9
|
||||
@@ -101,9 +96,9 @@ jobs:
|
||||
batched: b8_AVX2
|
||||
- desc: clang12/C++17 llvm12 oiio-master boost1.73 exr3.1 py3.9 avx2 batch-avx512
|
||||
nametag: linux-clang12-llvm12-batch
|
||||
os: ubuntu-latest
|
||||
runner: ubuntu-latest
|
||||
container: aswftesting/ci-osl:2022-clang12
|
||||
vfxyear: 2022
|
||||
vfxsuffix: -clang12
|
||||
cxx_std: 17
|
||||
openimageio_ver: master
|
||||
python_ver: 3.9
|
||||
@@ -111,11 +106,11 @@ jobs:
|
||||
simd: avx2,f16c
|
||||
batched: b8_AVX2,b8_AVX512,b16_AVX512
|
||||
setenvs: USE_OPENVDB=0
|
||||
- desc: icc/C++17 llvm13 py3.9 boost1.76 exr3.1 oiio-master avx2
|
||||
- desc: icc/C++17 llvm14 py3.9 boost1.76 exr3.1 oiio-master avx2
|
||||
nametag: linux-icc
|
||||
os: ubuntu-latest
|
||||
runner: ubuntu-latest
|
||||
container: aswftesting/ci-osl:2022-clang14
|
||||
vfxyear: 2022
|
||||
vfxsuffix: -clang13
|
||||
cc_compiler: icc
|
||||
cxx_compiler: icpc
|
||||
cxx_std: 17
|
||||
@@ -128,11 +123,11 @@ jobs:
|
||||
setenvs: export OSL_CMAKE_FLAGS="-DSTOP_ON_WARNING=OFF -DEXTRA_CPP_ARGS=-fp-model=consistent"
|
||||
OPENIMAGEIO_CMAKE_FLAGS=-DBUILD_FMT_VERSION=7.1.3
|
||||
USE_OPENVDB=0
|
||||
- desc: icx/C++17 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
|
||||
- desc: icx/C++17 llvm14 py3.9 boost1.76 exr3.1 oiio2.3 avx2
|
||||
nametag: linux-icx
|
||||
os: ubuntu-latest
|
||||
runner: ubuntu-latest
|
||||
container: aswftesting/ci-osl:2022-clang14
|
||||
vfxyear: 2022
|
||||
vfxsuffix: -clang13
|
||||
cc_compiler: icx
|
||||
cxx_compiler: icpx
|
||||
cxx_std: 17
|
||||
@@ -143,24 +138,50 @@ jobs:
|
||||
simd: avx2,f16c
|
||||
batched: b8_AVX2_noFMA
|
||||
setenvs: export OSL_CMAKE_FLAGS="-DSTOP_ON_WARNING=OFF" USE_OPENVDB=0
|
||||
- desc: oldest everything gcc6/C++14 llvm9 py2.7 boost1.66 oiio2.2 no-simd exr2.3
|
||||
- desc: gcc11/C++17 llvm15 py3.10 boost1.80 exr3.1 oiio-rel avx2
|
||||
nametag: linux-vfx2023
|
||||
runner: ubuntu-latest
|
||||
container: aswftesting/ci-osl:2023-clang15
|
||||
vfxyear: 2023
|
||||
cxx_std: 17
|
||||
openimageio_ver: release
|
||||
python_ver: "3.10"
|
||||
pybind11_ver: v2.9.0
|
||||
simd: avx2,f16c
|
||||
batched: b8_AVX2
|
||||
- desc: GPU Cuda11 gcc11/C++17 llvm15 py3.10 boost1.80 exr3.1 OIIO-master avx2
|
||||
nametag: linux-optix7-2023
|
||||
runner: ubuntu-latest
|
||||
container: aswftesting/ci-osl:2023-clang15
|
||||
vfxyear: 2023
|
||||
cxx_std: 17
|
||||
openimageio_ver: master
|
||||
python_ver: "3.10"
|
||||
pybind11_ver: v2.10.0
|
||||
simd: avx2,f16c
|
||||
skip_tests: 1
|
||||
setenvs: export OSL_CMAKE_FLAGS="-DOSL_USE_OPTIX=1" OPTIX_VERSION=7.0
|
||||
OPENIMAGEIO_CMAKE_FLAGS=-DBUILD_FMT_VERSION=9.1.0
|
||||
- desc: oldest everything gcc6/C++14 llvm9 py2.7 boost1.66 oiio2.3 no-simd exr2.4
|
||||
nametag: linux-oldest
|
||||
os: ubuntu-latest
|
||||
runner: ubuntu-latest
|
||||
container: aswftesting/ci-osl:2019-clang9
|
||||
vfxyear: 2019
|
||||
vfxsuffix: -clang9
|
||||
cxx_std: 14
|
||||
openimageio_ver: v2.3.17.0
|
||||
openexr_ver: v2.4.3
|
||||
openimageio_ver: v2.4.13.0
|
||||
python_ver: 2.7
|
||||
pybind11_ver: v2.6.2
|
||||
simd: 0
|
||||
setenvs: export PUGIXML_VERSION=v1.8
|
||||
CMAKE_VERSION=3.15.5
|
||||
|
||||
# Address and leak sanitizers
|
||||
- desc: sanitizers
|
||||
nametag: sanitizer
|
||||
os: ubuntu-latest
|
||||
runner: ubuntu-latest
|
||||
container: aswftesting/ci-osl:2022-clang13
|
||||
vfxyear: 2022
|
||||
vfxsuffix: -clang13
|
||||
cc_compiler: clang
|
||||
cxx_compiler: clang++
|
||||
cxx_std: 17
|
||||
@@ -196,28 +217,33 @@ jobs:
|
||||
# texture system adequately and is able to ignore the benign
|
||||
# "leaks."
|
||||
|
||||
# Test formatting. This test entry doesn't do a full build, it
|
||||
# just runs clang-format on everything, and passes if nothing is
|
||||
# misformatted. Upon failure, the build artifact will be the full
|
||||
# source code with the formatting fixed (diffs will also appear in
|
||||
# the console output).
|
||||
- desc: "clang-format"
|
||||
nametag: clang-format
|
||||
os: ubuntu-latest
|
||||
vfxyear: 2022
|
||||
vfxsuffix: -clang14
|
||||
# Test ABI stability. `abi_check` is the version or commit that we
|
||||
# believe is the current standard against which we don't want to
|
||||
# break the ABI. Basically, we will build that version as well as
|
||||
# the current one, and compare the resulting libraries.
|
||||
- desc: abi check
|
||||
nametag: linux-vfx2023
|
||||
runner: ubuntu-latest
|
||||
container: aswftesting/ci-osl:2023-clang15
|
||||
vfxyear: 2023
|
||||
cc_compiler: gcc
|
||||
cxx_compiler: g++
|
||||
cxx_std: 17
|
||||
openimageio_ver: release
|
||||
python_ver: 3.9
|
||||
simd: avx2,f16c
|
||||
# openimageio_ver: release
|
||||
python_ver: "3.10"
|
||||
simd: "avx2,f16c"
|
||||
batched: b8_AVX2
|
||||
fmt_ver: 10.1.1
|
||||
pybind11_ver: v2.10.0
|
||||
skip_tests: 1
|
||||
setenvs: export BUILDTARGET=clang-format
|
||||
OPENIMAGEIO_CMAKE_FLAGS=-DUSE_PYTHON=0
|
||||
abi_check: 1726df72a9841df93bc74a5184d78cacb44b585d
|
||||
setenvs: export OSL_CMAKE_FLAGS="-DOSL_BUILD_TESTS=0 -DBUILD_TESTING=OFF -DUSE_QT=0"
|
||||
OPENIMAGEIO_CMAKE_FLAGS="-DUSE_PYTHON=0"
|
||||
CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
runs-on: ${{matrix.runner}}
|
||||
container:
|
||||
image: aswftesting/ci-osl:${{matrix.vfxyear}}${{matrix.vfxsuffix}}
|
||||
image: ${{ matrix.container }}
|
||||
env:
|
||||
CXX: ${{matrix.cxx_compiler}}
|
||||
CC: ${{matrix.cc_compiler}}
|
||||
@@ -229,6 +255,7 @@ jobs:
|
||||
PYTHON_VERSION: ${{matrix.python_ver}}
|
||||
USE_BATCHED: ${{matrix.batched}}
|
||||
USE_SIMD: ${{matrix.simd}}
|
||||
ABI_CHECK: ${{matrix.abi_check}}
|
||||
steps:
|
||||
# We would like to use harden-runner, but it flags too many false
|
||||
# positives, every time we download a dependency. We should use it only
|
||||
@@ -269,11 +296,32 @@ jobs:
|
||||
- name: Testsuite
|
||||
if: matrix.skip_tests != '1'
|
||||
run: src/build-scripts/ci-test.bash
|
||||
- name: Check out ABI standard
|
||||
if: matrix.abi_check != ''
|
||||
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
|
||||
with:
|
||||
ref: ${{matrix.abi_check}}
|
||||
path: abi_standard
|
||||
- name: Build ABI standard
|
||||
if: matrix.abi_check != ''
|
||||
run: |
|
||||
mkdir -p abi_standard/build
|
||||
pushd abi_standard
|
||||
export LD_LIBRARY_PATH="${PWD}/build/lib:${LD_LIBRARY_PATH}"
|
||||
src/build-scripts/ci-build.bash
|
||||
popd
|
||||
- name: Check ABI
|
||||
if: matrix.abi_check != ''
|
||||
run: |
|
||||
src/build-scripts/ci-abicheck.bash ./build abi_standard/build \
|
||||
liboslexec liboslcomp liboslquery liboslnoise
|
||||
- uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
|
||||
if: failure()
|
||||
with:
|
||||
name: osl-${{github.job}}-${{matrix.nametag}}
|
||||
path: |
|
||||
build/cmake-save
|
||||
build/compat_reports
|
||||
build/*.cmake
|
||||
build/CMake*
|
||||
build/testsuite/*/*.*
|
||||
@@ -287,11 +335,11 @@ jobs:
|
||||
include:
|
||||
- desc: Debug gcc7/C++14 llvm9 py2.7 oiio2.3 exr2.4 sse4 boost1.65 exr2.4
|
||||
nametag: linux-debug-gcc7-llvm9
|
||||
os: ubuntu-18.04
|
||||
runner: ubuntu-20.04
|
||||
cxx_compiler: g++-7
|
||||
cxx_std: 14
|
||||
openexr_ver: v2.4.3
|
||||
openimageio_ver: dev-2.3
|
||||
openimageio_ver: v2.4.13.0
|
||||
pybind11_ver: v2.6.2
|
||||
python_ver: 2.7
|
||||
simd: sse4.2
|
||||
@@ -301,7 +349,7 @@ jobs:
|
||||
CTEST_TEST_TIMEOUT=240
|
||||
- desc: gcc10/C++17 llvm10 oiio-release boost1.65 exr2.5 avx2
|
||||
nametag: linux-2021ish-gcc10-llvm10
|
||||
os: ubuntu-18.04
|
||||
runner: ubuntu-20.04
|
||||
cxx_compiler: g++-10
|
||||
cxx_std: 17
|
||||
fmt_ver: 7.0.1
|
||||
@@ -313,25 +361,25 @@ jobs:
|
||||
setenvs: export LLVM_VERSION=10.0.0
|
||||
OPENIMAGEIO_CMAKE_FLAGS="-DBUILD_FMT_VERSION=7.0.1"
|
||||
PUGIXML_VERSION=v1.10
|
||||
- desc: latest releases gcc11/C++17 llvm13 boost1.71 exr3.1 py3.9 avx2 batch-b16avx512
|
||||
- desc: latest releases gcc11/C++17 llvm16 boost1.71 exr3.2 py3.9 avx2 batch-b16avx512
|
||||
nametag: linux-latest-releases
|
||||
os: ubuntu-20.04
|
||||
runner: ubuntu-22.04
|
||||
cxx_compiler: g++-11
|
||||
cxx_std: 17
|
||||
fmt_ver: 9.1.0
|
||||
openexr_ver: v3.1.5
|
||||
fmt_ver: 10.1.0
|
||||
openexr_ver: v3.2.1
|
||||
openimageio_ver: master
|
||||
pybind11_ver: v2.10.0
|
||||
python_ver: 3.9
|
||||
python_ver: "3.10"
|
||||
simd: avx2,f16c
|
||||
batched: b8_AVX2,b8_AVX512,b16_AVX512
|
||||
setenvs: export LLVM_VERSION=13.0.0
|
||||
LLVM_DISTRO_NAME=ubuntu-20.04
|
||||
OPENCOLORIO_VERSION=v2.1.2
|
||||
PUGIXML_VERSION=v1.11.4
|
||||
- desc: bleeding edge gcc12/C++17 llvm14 oiio/ocio/exr/pybind-master boost1.71 py3.10 avx2 batch-b16avx512
|
||||
setenvs: export LLVM_VERSION=16.0.4
|
||||
LLVM_DISTRO_NAME=ubuntu-22.04
|
||||
OPENCOLORIO_VERSION=v2.2.0
|
||||
PUGIXML_VERSION=v1.13
|
||||
- desc: bleeding edge gcc12/C++17 llvm17 oiio/ocio/exr/pybind-master boost1.71 py3.10 avx2 batch-b16avx512
|
||||
nametag: linux-bleeding-edge
|
||||
os: ubuntu-22.04
|
||||
runner: ubuntu-22.04
|
||||
cxx_compiler: g++-12
|
||||
cxx_std: 17
|
||||
fmt_ver: master
|
||||
@@ -341,18 +389,18 @@ jobs:
|
||||
python_ver: "3.10"
|
||||
simd: avx2,f16c
|
||||
batched: b8_AVX2,b8_AVX512,b16_AVX512
|
||||
setenvs: export LLVM_VERSION=14.0.0
|
||||
LLVM_DISTRO_NAME=ubuntu-18.04
|
||||
setenvs: export LLVM_VERSION=17.0.6
|
||||
LLVM_DISTRO_NAME=ubuntu-22.04
|
||||
OPENCOLORIO_VERSION=main
|
||||
PUGIXML_VERSION=master
|
||||
- desc: clang14/C++17 llvm14 boost1.71 exr3.1 py3.8 avx2 batch-b16avx512
|
||||
nametag: linux-latest-releases-clang
|
||||
os: ubuntu-20.04
|
||||
runner: ubuntu-20.04
|
||||
cxx_compiler: clang++
|
||||
cc_compiler: clang
|
||||
cxx_std: 17
|
||||
fmt_ver: 8.1.1
|
||||
openexr_ver: v3.1.5
|
||||
openexr_ver: v3.1.7
|
||||
openimageio_ver: master
|
||||
pybind11_ver: v2.9.2
|
||||
python_ver: 3.8
|
||||
@@ -362,8 +410,29 @@ jobs:
|
||||
LLVM_DISTRO_NAME=ubuntu-18.04
|
||||
OPENCOLORIO_VERSION=v2.1.2
|
||||
PUGIXML_VERSION=v1.11.4
|
||||
# Test formatting. This test entry doesn't do a full build, it
|
||||
# just runs clang-format on everything, and passes if nothing is
|
||||
# misformatted. Upon failure, the build artifact will be the full
|
||||
# source code with the formatting fixed (diffs will also appear in
|
||||
# the console output).
|
||||
- desc: "clang-format"
|
||||
nametag: clang-format
|
||||
runner: ubuntu-latest
|
||||
container: aswftesting/ci-osl:2022-clang14
|
||||
cxx_std: 17
|
||||
extra_artifacts: "src/*.*"
|
||||
openimageio_ver: release
|
||||
python_ver: "3.10"
|
||||
simd: avx2,f16c
|
||||
batched: b8_AVX2
|
||||
skip_tests: 1
|
||||
setenvs: export BUILDTARGET=clang-format
|
||||
LLVM_VERSION=17.0.6
|
||||
LLVM_DISTRO_NAME=ubuntu-22.04
|
||||
OPENIMAGEIO_CMAKE_FLAGS=-DUSE_PYTHON=0
|
||||
QT_VERSION=0
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
runs-on: ${{matrix.runner}}
|
||||
env:
|
||||
CXX: ${{matrix.cxx_compiler}}
|
||||
CC: ${{matrix.cc_compiler}}
|
||||
@@ -412,36 +481,43 @@ jobs:
|
||||
with:
|
||||
name: osl-${{github.job}}-${{matrix.nametag}}
|
||||
path: |
|
||||
build/cmake-save
|
||||
build/*.cmake
|
||||
build/CMake*
|
||||
build/testsuite/*/*.*
|
||||
${{ matrix.extra_artifacts }}
|
||||
|
||||
|
||||
macos:
|
||||
name: "${{matrix.os}} appleclang${{matrix.aclang}}/C++${{matrix.cxx_std}} py${{matrix.python_ver}} ${{matrix.desc}}"
|
||||
name: "${{matrix.runner}} C++${{matrix.cxx_std}} py${{matrix.python_ver}} ${{matrix.desc}}"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- desc: MacOS-11
|
||||
os: macos-11
|
||||
nametag: macos11-py39
|
||||
cc_compiler: /usr/local/opt/llvm@14/bin/clang
|
||||
cxx_compiler: /usr/local/opt/llvm@14/bin/clang++
|
||||
- desc: MacOS-13 llvm17
|
||||
runner: macos-13
|
||||
nametag: macos13-p311
|
||||
cc_compiler: /usr/local/opt/llvm/bin/clang
|
||||
cxx_compiler: /usr/local/opt/llvm/bin/clang++
|
||||
cxx_std: 17
|
||||
python_ver: "3.10"
|
||||
aclang: 13
|
||||
setenvs: export LLVMBREWVER="@14" DO_BREW_UPDATE=1
|
||||
- desc: MacOS-12
|
||||
os: macos-12
|
||||
nametag: macos11-p310
|
||||
cc_compiler: /usr/local/opt/llvm@15/bin/clang
|
||||
cxx_compiler: /usr/local/opt/llvm@15/bin/clang++
|
||||
openimageio_ver: master
|
||||
python_ver: "3.11"
|
||||
aclang: 14
|
||||
setenvs: export DO_BREW_UPDATE=1 CTEST_TEST_TIMEOUT=120
|
||||
- desc: MacOS-14-ARM llvm17
|
||||
runner: macos-14
|
||||
nametag: macos14-arm-p311
|
||||
cc_compiler: clang
|
||||
cxx_compiler: clang++
|
||||
Xcc_compiler: /usr/local/opt/llvm/bin/clang
|
||||
Xcxx_compiler: /usr/local/opt/llvm/bin/clang++
|
||||
cxx_std: 17
|
||||
python_ver: "3.10"
|
||||
aclang: 13
|
||||
setenvs: export LLVMBREWVER="@15" DO_BREW_UPDATE=1
|
||||
runs-on: ${{matrix.os}}
|
||||
openimageio_ver: master
|
||||
python_ver: "3.11"
|
||||
aclang: 15
|
||||
setenvs: export DO_BREW_UPDATE=1
|
||||
|
||||
runs-on: ${{matrix.runner}}
|
||||
env:
|
||||
CXX: ${{matrix.cxx_compiler}}
|
||||
CC: ${{matrix.cc_compiler}}
|
||||
@@ -468,7 +544,7 @@ jobs:
|
||||
run: |
|
||||
source src/build-scripts/install_homebrew_deps.bash
|
||||
if [[ "$OPENIMAGEIO_VERSION" != "" ]] ; then \
|
||||
OPENIMAGEIO_CMAKE_FLAGS="-DOIIO_BUILD_TESTS=0 -DUSE_OPENGL=0" ; \
|
||||
OPENIMAGEIO_CMAKE_FLAGS="-DOIIO_BUILD_TESTS=0 -DUSE_OPENGL=0 -DCMAKE_UNITY_BUILD=ON" ; \
|
||||
source src/build-scripts/build_openimageio.bash ; \
|
||||
else \
|
||||
brew install --display-times -q openimageio ; \
|
||||
@@ -485,6 +561,7 @@ jobs:
|
||||
with:
|
||||
name: osl-${{github.job}}-${{matrix.nametag}}
|
||||
path: |
|
||||
build/cmake-save
|
||||
build/*.cmake
|
||||
build/CMake*
|
||||
build/testsuite/*/*.*
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenshadingLanguage
|
||||
|
||||
|
||||
name: Publish Release Notice to ASWF Slack
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
# published should cover both 'released' and 'prereleased'
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Notify Slack
|
||||
id: slack
|
||||
with:
|
||||
project_name: "Open Shading Language"
|
||||
slack_bot_token: ${{ secrets.SLACK_BOT_TOKEN }}
|
||||
slack_channel: "#release-announcements"
|
||||
project_logo: "https://artwork.aswf.io/projects/openshadinglanguage/AcronymStack/Shaded/openshadinglanguage-AcronymStack-Shaded.png"
|
||||
uses: jmertic/slack-release-notifier@main
|
||||
@@ -1,3 +1,7 @@
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
name: Scorecards supply-chain security
|
||||
on:
|
||||
# Only the default branch is supported.
|
||||
@@ -6,22 +10,31 @@ on:
|
||||
- cron: '44 20 * * 6'
|
||||
push:
|
||||
branches: [ "main", "scorecard" ]
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- '**.rst'
|
||||
- '**.tex'
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
# Allow subsequent pushes to the same PR or REF to cancel any previous jobs.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
jobs:
|
||||
analysis:
|
||||
name: Scorecards analysis
|
||||
if: |
|
||||
github.repository == 'AcademySoftwareFoundation/OpenShadingLanguage'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# Needed to upload the results to code-scanning dashboard.
|
||||
security-events: write
|
||||
# Used to receive a badge. (Upcoming feature)
|
||||
id-token: write
|
||||
# Needs for private repositories.
|
||||
contents: read
|
||||
actions: read
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
# This file establishes email equivalences so we can resolve what look like
|
||||
# multiple authors, but actually are the same author who has used multiple
|
||||
# emails over the course of their involvement with the project.
|
||||
#
|
||||
# The format is any of the following:
|
||||
# <CANONICAL-EMAIL> <alternate-email>
|
||||
# CANONICAL-NAME <CANONICAL-EMAIL> <alternate-email>
|
||||
# CANONICAL-NAME <CANONICAL-EMAIL> alternate-name <alternate-email>
|
||||
#
|
||||
# You can check for duplicates with this command:
|
||||
# git shortlog -sne --all
|
||||
# That command (and others) will use this file to collapse the duplicates.
|
||||
#
|
||||
# If you see any duplicates we don't account for here, or if you look at your
|
||||
# own entry here and want a different name or email to be your canonical one
|
||||
# (we may not have guessed correctly and matched your preferences), please
|
||||
# file a PR with the edits to this file.
|
||||
|
||||
Adam Martinez <amartinez.cg@gmail.com> amartinez-cg <amartinez.cg@gmail.com>
|
||||
Alejandro Conty <aconty@imageworks.com> aconty <aconty@gmail.com>
|
||||
Alejandro Conty <aconty@imageworks.com> Alejandro Conty <aconty@gmail.com>
|
||||
Alex M. Wells <alex.m.wells@intel.com> <alex.m.wells@intel.com>
|
||||
Alex M. Wells <alex.m.wells@intel.com> <AlexMWells@users.noreply.github.com>
|
||||
Alex M. Wells <alex.m.wells@intel.com> <awells-np@argon.sea.pixar.com>
|
||||
Alexis Oblet <alob@mikrosimage.eu> Alexis Oblet <aoblet@users.noreply.github.com>
|
||||
Brecht Van Lommel <brecht@blender.org> <brecht@solidangle.com>
|
||||
Brecht Van Lommel <brecht@blender.org> Brecht Van Lommel <brechtvanlommel@gmail.com>
|
||||
Chris Kulla <ckulla@gmail.com> <ckulla@imageworks.com>
|
||||
Chris Kulla <ckulla@gmail.com> <fpsunflower@users.noreply.github.com>
|
||||
Chris Kulla <ckulla@gmail.com> Christopher Kulla <ckulla@gmail.com>
|
||||
Chris Kulla <ckulla@gmail.com> fpsunflower <ckulla@gmail.com>
|
||||
Clifford Stein <cstein@imageworks.com> Cliff Stein <clifford.stein@gmail.com>
|
||||
Clifford Stein <cstein@imageworks.com> cmstein <cstein@imageworks.com>
|
||||
Declan Russell <declan.russell@autodesk.com> Declan Russell <i7709212@bournemouth.ac.uk>
|
||||
Derek Haase <derekhaase@gmail.com> Derek Haase <dhaase@imageworks.com>
|
||||
Esteban Tovagliari <ramenhdr@gmail.com> est77 <ramenhdr@gmail.com>
|
||||
Henri Fousse <henri.fousse@free.fr> darkhorse64 <henri.fousse@free.fr>
|
||||
Larry Gritz <lg@imageworks.com> <larrygritz@gmail.com>
|
||||
Larry Gritz <lg@imageworks.com> <lg@larrygritz.com>
|
||||
Roman Zulak <marsupial@users.noreply.github.com> <rzulak@imageworks.com>
|
||||
Roman Zulak <marsupial@users.noreply.github.com> Frederich Munch <marsupial@users.noreply.github.com>
|
||||
Roman Zulak <marsupial@users.noreply.github.com> marsupial <marsupial@users.noreply.github.com>
|
||||
Ronan Keryell <Ronan.Keryell@amd.com> Ronan Keryell <Ronan.Keryell@silkan.com>
|
||||
Steena Monteiro <steena.monteiro@intel.com> steena.monteiro <smonteir@ortce-sklaw.jf.intel.com>
|
||||
Sven-Hendrik Haase <sh@lutzhaase.com> Sven-Hendrik Haase <svenstaro@gmail.com>
|
||||
Tim Grant <tgrant@nvidia.com> Tim Grant <87798327+tgrant-nv@users.noreply.github.com>
|
||||
Tim Grant <tgrant@nvidia.com> timgrant <timgrant@users.noreply.github.com>
|
||||
@@ -0,0 +1,29 @@
|
||||
# .readthedocs.yml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Set the OS, Python version and other tools you might need
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3.11"
|
||||
|
||||
|
||||
# Build documentation with Sphinx
|
||||
sphinx:
|
||||
configuration: src/doc/conf.py
|
||||
|
||||
|
||||
# Optionally build your docs in additional formats such as PDF and ePub
|
||||
formats:
|
||||
- pdf
|
||||
- htmlzip
|
||||
|
||||
|
||||
# Optionally set the version of Python and requirements required to build your docs
|
||||
python:
|
||||
install:
|
||||
- requirements: src/doc/requirements.txt
|
||||
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 121 KiB |
|
After Width: | Height: | Size: 92 KiB |
@@ -5,13 +5,14 @@ This is a checklist for TSC's to review as part of the intake process. The TSC s
|
||||
- Existing Project Governance
|
||||
- [X] Project License exists ( [LICENSE.md](../LICENSE.md) ) and is OSI-approved
|
||||
- [X] Any third-party components/dependencies included are listed along with their licenses ( [THIRD_PARTY.md](../THIRD_PARTY.md) )
|
||||
- [X] Governance defined, outlining community roles and how decsions are made ( [GOVERNANCE.md](../GOVERNANCE.md] )
|
||||
- [X] Governance defined, outlining community roles and how decisions are made ( [GOVERNANCE.md](../GOVERNANCE.md) )
|
||||
- Closed by https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1137
|
||||
- [X] Contribution Policy defined ( [CONTRIBUTING.md](../CONTRIBUTING.md) )
|
||||
- Closed by https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1137
|
||||
- [X] Code of Conduct defined ( existing or pull from [ASWF Sample Project](https://github.com/AcademySoftwareFoundation/aswf-sample-project/blob/master/CODE_OF_CONDUCT.md) )
|
||||
- Closed by https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1137
|
||||
- [ ] Release methodology defined ( [release.md](process/release.md) )
|
||||
- [X] Release methodology defined ( [RELEASING.md](../docs/RELEASING.md) )
|
||||
- Closed by https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1572
|
||||
- New Project Governance
|
||||
- [X] TSC members identified
|
||||
- [X] First TSC meeting held
|
||||
@@ -41,7 +42,7 @@ This is a checklist for TSC's to review as part of the intake process. The TSC s
|
||||
- [X] New project announcement done ( https://www.aswf.io/osl-joins-aswf/ )
|
||||
- [X] Project added to ASWF website and ASWF landscape
|
||||
- Graduation
|
||||
- [ ] CII Badge achieved
|
||||
- [X] OpenSSF Best Practices Badge achieved
|
||||
- [ ] Committer Diversity established
|
||||
- [ ] Commit/Contribution growth during incubation
|
||||
- [ ] Committers defined in the project ( [COMMITTERS.csv](COMMITTERS.csv) or [COMMITTERS.yml](COMMITTERS.yml) )
|
||||
|
||||
@@ -1,30 +1,78 @@
|
||||
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
||||
<!-- Copyright Contributors to the Open Shading Language Project. -->
|
||||
|
||||
Release 1.13 -- ?? 2023 ?? (compared to 1.12)
|
||||
--------------------------------------------------
|
||||
Dependency and standards requirements changes:
|
||||
* OptiX 6.0 support has been removed. For GPU rendering with OptiX, a minimum
|
||||
of OptiX 7.0 is required.
|
||||
* The minimum version OpenImageIO has been raised from 2.2 to 2.3. #1591
|
||||
(1.13.0.3)
|
||||
Release 1.13.7.0 -- 1 Mar 2024 (compared to 1.13.6.1)
|
||||
--------------------------------------------------------
|
||||
- *fix*: Mute partio error prints [#1774](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1774) (by olegul)
|
||||
- *ci*: Test with Mac ARM runner [#1770](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1770)
|
||||
- *docs*: Fix links to RTD docs from github landing page [#1768](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1768)
|
||||
- *admin*: Switch release announcement workflow to jmertic's awesome action [#1766](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1766)
|
||||
|
||||
OSL Language and oslc compiler:
|
||||
* Bug fix: shader params whose default values involve "init ops" could be
|
||||
incorrectly initialized if their values came from instance parameters set to
|
||||
zero. #1578 (1.13.0.2)
|
||||
<br>
|
||||
|
||||
OSL Standard library:
|
||||
|
||||
API changes, new options, new ShadingSystem features (for renderer writers):
|
||||
Release 1.13 -- Feb 1, 2024 (compared to 1.12)
|
||||
===============================================
|
||||
- beta 1: December 20, 2023
|
||||
- release v1.13.6.1: Feb 1, 2024
|
||||
|
||||
### New minimum dependencies and compatibility changes:
|
||||
|
||||
* For GPU/OptiX mode, OptiX 6.0 support has been removed. For GPU rendering
|
||||
with OptiX, a minimum of OptiX 7.0 is required, and the Cuda minimum has
|
||||
been raised to 9.0 [#1737](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1737)
|
||||
* The minimum version OpenImageIO has been raised from 2.2 to 2.4. [#1591](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1591) [#1722](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1722)
|
||||
* The minimum CMake dependency has been raised from 3.12 to 3.15
|
||||
[#1724](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1724) (1.13.5.0)
|
||||
* The minimum Imath/OpenEXR has been raised from 2.3 to 2.4. (Note: OSL 1.13
|
||||
is probably the last major release family that will support Imath/OpenEXR
|
||||
2.x.)
|
||||
|
||||
### OSL Language and oslc compiler:
|
||||
|
||||
* There have been no substantive changes to the OSL language in this release.
|
||||
|
||||
### ⛰️ API changes, new options, new ShadingSystem features (for renderer writers):
|
||||
|
||||
* A new `shadingStateUniform` pointer field was added to ShaderGlobals for
|
||||
planned future expansion and improved GPU support. #1585 (1.13.1.0)
|
||||
* Adding relaxed type-equivalency to ReParameter() [#1639](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1639) (by cmstein) (1.13.2.1)
|
||||
* Expose llvm groupdata size as a shadergroup attribute
|
||||
[#1642](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1642) (by Chris Hellmuth) (1.13.4.0)
|
||||
* RendererServices API for letting get_texture_handle consider colorspace
|
||||
[#1641](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1641) (1.13.4.0)
|
||||
* Make "compile_report" attribute an int instead of just 0/1. Passing 1 makes
|
||||
a brief report, values >1 are more verbose. (Zero still prints no report.)
|
||||
[#1654](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1654) (1.13.4.0)
|
||||
* Switch `lockgeom` to `interpolated` and `interactive`. The `lockgeom=0`
|
||||
was confusing. Now we use `interpolated=1` to mean "don't optimize it away
|
||||
because it might be interpolated across the geometry and thus won't have
|
||||
the same value at all points being shaded," and the subtly different
|
||||
`interactive=1` to mean "don't optimize it away because although it will
|
||||
always take on the same value at all points at the same time, the user
|
||||
might want to interactively adjust the value and we don't want to have
|
||||
to recompile the shader group if that happens."
|
||||
[#1662](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1662) (1.13.4.0)
|
||||
* Add type information for needed attributes. [#1650](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1650) (by Curtis Black) (1.13.4.0)
|
||||
* Add API for building attribute getter free functions.
|
||||
[#1704](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1704) (by Curtis Black) (1.13.5.0)
|
||||
* Rs fmt specification - Journaling Algorithm for error, warning, fprintf
|
||||
[#1702](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1702) (by Steena Monteiro) [#1711](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1711) [#1715](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1715) (1.13.5.0)
|
||||
|
||||
### 🚀 SIMD batched shading mode
|
||||
|
||||
SIMD batched shading mode:
|
||||
* Fix some array overruns (asymptomatic, but still potentially buggy) in
|
||||
common_ancestor_between. #1577 (1.13.0.2)
|
||||
* Fix issue with closure keyword parameters. #1620 (1.13.2.0/1.12.8.0)
|
||||
* Fix crash when adding a default initialized closure. #1624
|
||||
(1.13.2.0/1.12.8.0)
|
||||
* Fix support for closures with array types. #1630 (1.13.2.0/1.12.8.0)
|
||||
* Fix bug with masked wide llvm_gen_closure() [#1637](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1637) (by danieldresser-ie) (1.13.2.1)
|
||||
* Fix Force LLVM Boolean [#1717](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1717) (by Alex Wells)
|
||||
* Batched pointcloud if "index" is not passed [#1753](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1753) (by Alex Wells)
|
||||
|
||||
### 🚀 OptiX GPU rendering
|
||||
|
||||
OptiX rendering:
|
||||
* OptiX 6.0 support has been removed. For GPU rendering with OptiX, a minimum
|
||||
of OptiX 7.0 is required.
|
||||
* Big overhaul/simplification of how strings are represented on the GPU: the
|
||||
@@ -34,36 +82,268 @@ OptiX rendering:
|
||||
* Better PTX cache hit rate by eliminating several sources of not being
|
||||
strictly deterministic in the PTX text we were generating. #1566 #1570
|
||||
(1.13.0.1)
|
||||
* Fix PTX symbol visibility issues. #1609 (1.13.2.0)
|
||||
* Hide more code that is only used for OptiX mode, when OptiX is disabled.
|
||||
#1608 (1.13.2.0)
|
||||
* Remove dependency on OptiX SDK for building core OSL with OptiX support. You
|
||||
can now build OSL with OptiX support enabled even if you don't have the
|
||||
OptiX SDK headers present at build time. But you will still need them to
|
||||
build your OptiX-based application that uses OSL for GPU rendering. #1627
|
||||
(1.13.2.0/1.12.8.0)
|
||||
* GPU/OptiX support of ReParameter [#1686](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1686) (1.13.4.0)
|
||||
* Fix userdata derivatives for interpolated params on GPU [#1685](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1685) (by Pascal Lecocq) (1.13.4.0)
|
||||
* Enable userdata derivatives for interpolated params on GPU
|
||||
[#1657](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1657) (by Chris Hellmuth) (1.13.4.0)
|
||||
* Move qualifying GroupData params onto stack for higher performance.
|
||||
[#1710](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1710) (by Chris Hellmuth) (1.13.5.0)
|
||||
* Handle mixed string casting that plagues optix codegen [#1718](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1718) (1.13.5.0)
|
||||
* Add missing members to ShaderGlobals in rend_lib.h [#1721](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1721) (by Tim Grant) (1.13.5.0)
|
||||
* OptiX direct callable API that owns groupdata buffer
|
||||
[#1683](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1683) (by Chris Hellmuth) (1.13.5.0)
|
||||
* OptiX PTX pipeline overhaul [#1680](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1680) (by Tim Grant) (1.13.5.0)
|
||||
* Perf: Don't insert redundant run layer calls inside a basic block
|
||||
[#1665](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1665) [#1669](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1669) [#1672](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1672) (by Chris Hellmuth) (1.13.4.0)
|
||||
* Fix NVPTX TargetMachine leak, etc. [#1763](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1763) (by Tim Grant)
|
||||
|
||||
Performance improvements:
|
||||
### 🐛/🔧 Internals: fixes, improvements, and developer concerns
|
||||
|
||||
Bug fixes and other improvements (internals):
|
||||
* Fix memory leak in oslc ASTvariable_declaration. #1576 (1.13.0.2)
|
||||
* Fix memory leaks in LPE code in error conditions. #1593 #1594 (1.13.0.3)
|
||||
|
||||
Internals/developer concerns:
|
||||
* Fix mismatched strides when calling OCIO for transformc with derivs [#1646](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1646) (1.13.4.0)
|
||||
* Set up ray types for testrender [#1648](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1648) (1.13.4.0)
|
||||
* Fix userdata binding corner case [#1673](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1673) (by Alejandro Conty) (1.13.4.0)
|
||||
* Fix constant float values being converted to ints [#1674](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1674) (by Declan Russell) (1.13.4.0)
|
||||
* Don't try to ReParameter symbols not in the group [#1693](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1693) (by Alejandro Conty) (1.13.5.0)
|
||||
* Have ReParameter only copy data when it changes [#1698](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1698) (1.13.5.0)
|
||||
* Avoid deprecated OSLQuery ctr in test example [#1699](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1699) (1.13.5.0)
|
||||
* Zero derivs for interactive params when needed [#1700](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1700) (by Alejandro Conty) (1.13.5.0)
|
||||
* oslc bug fix: shader params whose default values involve "init ops" could be
|
||||
incorrectly initialized if their values came from instance parameters set to
|
||||
zero. #1578 (1.13.0.2)
|
||||
* oslc: Add missing `fmod()` variants [#1643](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1643) (1.13.4.0)
|
||||
* Simple constant folding of binary expressions now happen on the oslc side
|
||||
[#1653](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1653) (1.13.4.0)
|
||||
* platform.h:
|
||||
- New `OSL_ALLOCA` macro to allocate on the stack. #1589 (1.13.0.3)
|
||||
* New `OSL_ALLOCA` macro to allocate on the stack. #1589 (1.13.0.3)
|
||||
* Define OSL::bitcast utility. #1610 (1.13.2.0)
|
||||
* Make sure that std::hash is defined for ustring and ustringhash. #1599
|
||||
(1.13.1.1)
|
||||
* Deprecate LLVMUtil::internalize_module_functions. #1606 (1.13.1.0)
|
||||
* Work toward always representing strings in shaders as ustringhash rather
|
||||
than ustring: phase 1 #1603 phase2 #1612 (1.13.2.0) [#1726](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1726) (1.13.5.0)
|
||||
* Remove unnecessary setting of locale::global [#1636](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1636) (by danieldresser-ie) (1.13.2.1)
|
||||
* Fully define bitcast template [#1635](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1635) (1.13.2.1)
|
||||
* Fix for ReParameter corner case [#1670](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1670) (by cmstein) (1.13.4.0)
|
||||
* Switch deprecated oiio simd names to modern [#1679](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1679) (1.13.4.0)
|
||||
* Give ShadingSystemImpl a handy use_optix() method [#1682](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1682) (1.13.4.0)
|
||||
* Fix default fmt logic changing in latest openimageio release [#1725](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1725) (1.13.5.0)
|
||||
* The recently added SS::find_symloc can have const args [#1723](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1723) (1.13.5.0)
|
||||
* SymOverrideInfo bitfields should be the same type [#1745](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1745)
|
||||
* Fix wrong offset of MxSheen param [#1751](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1751) (by Rasmus Bonnedal)
|
||||
* Make get_texture_info robust to empty shaderglobals param [#1731](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1731)
|
||||
|
||||
### 🏗 Build/test/CI and platform ports
|
||||
|
||||
Build & test system improvements:
|
||||
* CMake build system and scripts:
|
||||
- The version number is now a cache variable, and so can be overridden at
|
||||
* The version number is now a cache variable, and so can be overridden at
|
||||
build time using `-DOSL_VERSION=...`. Use with extreme caution! #1579
|
||||
(1.13.0.2)
|
||||
(1.13.0.2) Revised again to reduce changes of user error in #1617
|
||||
(1.13.2.0/1.12.7.1)
|
||||
* Add clangSupport library as dependency to fix linker error on some
|
||||
platforms. #1613 (1.13.2.0/1.12.7.1)
|
||||
* Fix incorrect CMake variable name to control symbol visibility
|
||||
[#1681](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1681) (1.13.4.0)
|
||||
* Change cmake option `USE_OPTIX` -> `OSL_USE_OPTIX` [#1668](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1668) (1.13.4.0)
|
||||
* Fix duplicate osl lexing symbols when building as static libraries
|
||||
[#1709](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1709) (by Brecht Van Lommel) (1.13.5.0)
|
||||
* Better cmake verbose behavior [#1752](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1752)
|
||||
* Dependency version support:
|
||||
- Fix some issues that came up with the new icx 2022.0 compiler. #1601
|
||||
* Fix some issues that came up with the new icx 2022.0 compiler. #1601
|
||||
(1.13.1.0)
|
||||
* Test against OpenColorIO 2.2. #1616 (1.13.2.0/1.12.7.1)
|
||||
* Proper warnings about LLVM 16 [#1658](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1658) (1.13.4.0)
|
||||
* Fix cuda compilation flags for LLVM 15 [#1659](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1659) (1.13.4.0)
|
||||
* Verify that OSL can build with clang16 [#1664](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1664) (1.13.4.0)
|
||||
* Be more careful about paths to look for llvm [#1656](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1656) (1.13.4.0)
|
||||
* Qt6 compatibility [#1655](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1655) (1.13.4.0)
|
||||
* Fix warnings about Qt compilation and enums [#1661](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1661) (1.13.4.0)
|
||||
* Changes to support fmt 10.0 [#1691](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1691) (1.13.5.0)
|
||||
* Raise OpenEXR minimum to 2.4 [#1734](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1734)
|
||||
* Fix Partio build errors on pointcloud functions for MSVC [#1757](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1757) (by Alex Wells)
|
||||
* Bump Cuda minimum to 9.0 [#1737](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1737)
|
||||
* LLVM 16 and 17 support: LLVM opaque pointers support [#1728](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1728),
|
||||
LLVM new pass manager support [#1729](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1729),
|
||||
finish LLVM 16 and 17 support [#1730](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1730) (all by Brecht Van Lommel)
|
||||
* Testing and Continuous integration (CI) systems:
|
||||
- Dynamic analysis using address and leak sanitizers. #1581 (1.13.0.3)
|
||||
- `testshade --help` now prints TextureSystem options and all hardware
|
||||
* Dynamic analysis using address and leak sanitizers. #1581 (1.13.0.3)
|
||||
* `testshade --help` now prints TextureSystem options and all hardware
|
||||
information. #1584 (1.13.0.3)
|
||||
- Improvements to SonarCloud and coverage analysis. #1596 (1.13.0.3)
|
||||
* Improvements to SonarCloud and coverage analysis. #1596 (1.13.0.3)
|
||||
#1607 (1.13.1.0)
|
||||
* Disabling the dso version of testshade for the coverage analysis test.
|
||||
#1604 (1.13.1.0)
|
||||
* Be sure to run pointcloud tests when partio is found. #1611 (1.13.2.0)
|
||||
* testshade: better testing of all closure parameter types. #1621
|
||||
(1.13.2.0/1.12.8.0)
|
||||
* Don't use the cached background map on the first bounce
|
||||
[#1649](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1649) (by Christopher Kulla) (1.13.4.0)
|
||||
* Fix builds when USE_PYTHON=OFF [#1675](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1675) (by Declan Russell) (1.13.4.0)
|
||||
* Remove SonarCloud cache setup as it is now offered by default
|
||||
[#1660](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1660) (by Massimo Paladin) (1.13.4.0)
|
||||
* *ci*: Simplify build_llvm.bash script [#1703](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1703) (1.13.5.0)
|
||||
* Test interactive parameter initialization in optix testrender [#1687](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1687) (by Chris Hellmuth) (1.13.5.0)
|
||||
* Fix GPU job not actually enabling OptiX [#1738](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1738) (by Brecht Van Lommel)
|
||||
* Fix python-oslquery test failure on macOS [#1739](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1739) (by Brecht Van Lommel)
|
||||
* Disable MacOS-11 CI [#1746](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1746)
|
||||
* Skip analysis and scorecard workflows on push if only docs changed [#1744](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1744)
|
||||
* For clarity, use the term 'runner' instead of 'os' [#1743](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1743)
|
||||
* Test ABI compliance [#1748](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1748)
|
||||
* Fix tests passing when test commands fail [#1733](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1733) (by Brecht Van Lommel)
|
||||
* *ci*: Test against LLVM 17 [#1760](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1760)
|
||||
* Platform support:
|
||||
* Include `immintrin.h` only when needed. #1605 (1.13.1.0)
|
||||
* Changed snprintf formatting to satisfy some compilers.
|
||||
[#1640](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1640) (by pellerington) (1.13.4.0)
|
||||
* Fix some windows GPU build errors [#1638](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1638) (by Declan Russell) (1.13.4.0)
|
||||
* Fix for Apple clang 14+ warnings [#1697](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1697) (1.13.5.0)
|
||||
* Fix struct align/pack for MSVC [#1754](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1754) (by Rasmus Bonnedal)
|
||||
* Refactor icc/icx specific pragma macros [#1756](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1756) (by Alex Wells)
|
||||
|
||||
Documentation:
|
||||
### 📚 Documentation
|
||||
|
||||
* First stab at ReadTheDocs -- new [Experimental OSL Documentation on
|
||||
ReadTheDocs](https://open-shading-language.readthedocs.io/)
|
||||
is still a little rough, but eventually will be our primary documentation.
|
||||
[#1736](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1736)
|
||||
* `doc/RELEASING.md` documents our release process and versioning policies.
|
||||
#1572 (1.13.0.2)
|
||||
* Improve documentation of `trace` function [#1671](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1671) (by AidanWelch) (1.13.4.0)
|
||||
* Update CONTRIBUTING [#1689](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1689) (1.13.5.0)
|
||||
* Update logos [#1705](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1705), Move logos and add an icon-only logo [#1707](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1707) (1.13.5.0)
|
||||
|
||||
### 🏢 Project Administration
|
||||
|
||||
* Alert slack "release-announcements" channel upon OSL release [#1740](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1740) [#1749](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1749)
|
||||
* Update pull request template [#1741](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1741)
|
||||
* Account for duplicate emails in the .mailmap [#1759](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1759)
|
||||
|
||||
|
||||
---
|
||||
---
|
||||
---
|
||||
|
||||
|
||||
Release 1.12.13.0 -- 1 July 2023 (compared to 1.12.12.0)
|
||||
--------------------------------------------------------
|
||||
- *fix*: Fix constant float values being converted to ints
|
||||
[#1674](https://github.com/OpenImageIO/oiio/pull/1674) (by Declan Russell)
|
||||
- *build*: Fix builds when USE_PYTHON=OFF
|
||||
[#1675](https://github.com/OpenImageIO/oiio/pull/1675) (by Declan Russell)
|
||||
- *build*: Changes to support fmt 10.0
|
||||
[#1691](https://github.com/OpenImageIO/oiio/pull/1691)
|
||||
- *cleanup*: Switch deprecated oiio simd names to modern
|
||||
[#1679](https://github.com/OpenImageIO/oiio/pull/1679)
|
||||
- *testing*: Avoid deprecated OSLQuery ctr in test example
|
||||
[#1699](https://github.com/OpenImageIO/oiio/pull/1699)
|
||||
- *ci*: Fix package name for icc
|
||||
[#1690](https://github.com/OpenImageIO/oiio/pull/1690)
|
||||
- *ci*: Add VFX Platform 2023 tests using new ASWF containers
|
||||
[#1696](https://github.com/OpenImageIO/oiio/pull/1696)
|
||||
- *ci*: Switch oiio obsolete branch names to immutable tags
|
||||
[#1701](https://github.com/OpenImageIO/oiio/pull/1701)
|
||||
- *docs*: Improve documentation of `trace` function
|
||||
[#1671](https://github.com/OpenImageIO/oiio/pull/1671) (by AidanWelch)
|
||||
- *docs*: README.md: added filmography and Siggraph OSL course info.
|
||||
[#1692](https://github.com/OpenImageIO/oiio/pull/1692)
|
||||
[#1694](https://github.com/OpenImageIO/oiio/pull/1694) (by Mitch Prater)
|
||||
- *docs*: Amend the filmography
|
||||
[#1695](https://github.com/OpenImageIO/oiio/pull/1695)
|
||||
- *docs*: Fix incorrect links in CONTRIBUTING
|
||||
[#1688](https://github.com/OpenImageIO/oiio/pull/1688)
|
||||
|
||||
Release 1.12.12.0 -- 1 May 2023 (compared to 1.12.11.0)
|
||||
--------------------------------------------------------
|
||||
* New ShadingSystem getattribute query for shader groups: "attribute_types"
|
||||
retrieves a pointer to the array of TypeDesc values describing the
|
||||
attributes retrieved by existing "attributes_needed" and "attribute_scopes".
|
||||
#1650
|
||||
* Fix a bug with binding userdata when it's used by more than one shader
|
||||
within the group and they disagree about whether derivatives are needed when
|
||||
retrieving the attribute. #1673
|
||||
|
||||
Release 1.12.11.0 -- 5 Apr 2023 (compared to 1.12.10.0)
|
||||
--------------------------------------------------------
|
||||
* Build: Add Qt 6.x compatibility (Qt is only used for `osltoy`). #1655
|
||||
* Build: more careful about paths to look for LLVM. #1656
|
||||
* Build: Fix Cuda compilation flags for LLVM 15. #1659
|
||||
* Notice: OSL does not yet build properly against the newly release LLVM 16.
|
||||
You must use LLVM 9-15. For Mac users who get their llvm from Homebrew,
|
||||
please be aware that Homebrew has changed its default llvm to 16, so you'll
|
||||
need to `brew install llvm@14` and make your OSL CMake define:
|
||||
`-DLLVM_ROOT=/usr/local/opt/llvm@14`
|
||||
|
||||
Release 1.12.10.0 -- 1 Mar 2023 (compared to 1.12.9.0)
|
||||
--------------------------------------------------------
|
||||
* feat(testrender): Modify testrender so that it correctly sets raytype to
|
||||
"camera" for camera rays, "shadow" for shadow rays, and "diffuse" for all
|
||||
secondary rays. Also rerun the shades for background shader group on the
|
||||
camera rays rather than use the cached map. This helps the MaterialX project
|
||||
use testrender for certain unit tests and verification. #1648 #1649
|
||||
* feat: Expose llvm groupdata size as a shadergroup attribute
|
||||
"llvm_groupdata_size". #1642
|
||||
* fix: Crash could result from uncaught exception in OpenColorIO when calling
|
||||
transformc with derivatives for color spaces that require OCIO. #1646
|
||||
* fix: certain uses of fmod() in shaders could fail to generate LLVM code
|
||||
correctly, due to a missing implementation for the fmod(triple,float)
|
||||
varieties. #1643
|
||||
* build: Change snprintf formatting to satisfy some compilers. #1640
|
||||
* CI: Fix broken Mac ci. #1647
|
||||
|
||||
Release 1.12.9.0 -- 1 Feb 2023 (compared to 1.12.8.0)
|
||||
-------------------------------------------------------
|
||||
* Remove unnecessary setting of locale::global. #1630
|
||||
* Batch shading: Fix bug with masked wide closure generation. #1637
|
||||
* Make sure ReParameter() has the same relaxed type checking rules as
|
||||
Parameter(). Before, it was stricter about type conversion. #1639
|
||||
* Windows: Fix some GPU build errors. #1638
|
||||
|
||||
Release 1.12.8.0 -- 3 Jan 2023 (compared to 1.12.7.1)
|
||||
-------------------------------------------------------
|
||||
* Remove dependency on OptiX SDK for building core OSL with OptiX support.
|
||||
You can now build OSL with OptiX support enabled even if you don't have the
|
||||
OptiX SDK headers present at build time. But you will still need them to
|
||||
build your OptiX-based application that uses OSL for GPU rendering. #1627
|
||||
* Batch mode: fix issue with closure keyword parameters. #1620
|
||||
* Batch mode: fix crash when adding a default initialized closure. #1624
|
||||
* Batch mode: Fix support for closures with array types. #1630
|
||||
* testshade: better testing of all closure parameter types. #1621
|
||||
* Fix various CI breaks as dependencies shifted. #1629 #1631 #1633
|
||||
|
||||
Release 1.12.7.1 -- 1 Dec 2022 (compared to 1.12.7.0)
|
||||
-------------------------------------------------------
|
||||
* Add clangSupport library as dependency to fix linker error on some
|
||||
platforms. #1613
|
||||
* Test against OpenColorIO 2.2. #1616
|
||||
* Build: Fix how version overrides work to reduce the chance of user mistakes.
|
||||
#1617
|
||||
|
||||
Release 1.12.7.0 -- 1 Nov 2022 (compared to 1.12.6.2)
|
||||
-------------------------------------------------------
|
||||
* Optix: Change naming of certain compiler-generated constants in a way that
|
||||
improves use of the PTX cache. #1570
|
||||
* Batch: Fix uninitialized members in ReadEvent internals. #1575
|
||||
* `testshade --help` now prints TextureSystem options and hardware info. #1584
|
||||
* oslc: Fix memory leak in ASTvariable_declaration. #1576
|
||||
* Fix memory leaks in light path expression code. #1593 #1594
|
||||
* Include the immintrin.h header only when needed. #1605
|
||||
* icx: Improvements to fix problems exposed by new icx 2022.2 compiler. #1601
|
||||
* Testing: CMake cache variables to control the testing timeout length. #1571
|
||||
* CI: Add a dynamic analysis test using address and leak sanitizers. #1581
|
||||
* CI: Now using SonarCloud static analysis. #1551
|
||||
* CI: Many improvements in testing code coverage #1607
|
||||
* CI: Make sure to run pointcloud tests when partio is found. #1611
|
||||
* Developers: platform.h now defines OSL_ALLOCA macro. #1589
|
||||
* Developers: platform.h now defines OSL::bitcast utility. #1610
|
||||
|
||||
Release 1.12 -- 1 Oct 2022 (compared to 1.11)
|
||||
----------------------------------------------
|
||||
|
||||
@@ -2,21 +2,28 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
cmake_minimum_required (VERSION 3.12)
|
||||
cmake_minimum_required (VERSION 3.15)
|
||||
|
||||
set (OSL_VERSION "1.13.7.0")
|
||||
set (OSL_VERSION_OVERRIDE "" CACHE STRING
|
||||
"Version override (use with caution)!")
|
||||
mark_as_advanced (OSL_VERSION_OVERRIDE)
|
||||
if (OSL_VERSION_OVERRIDE)
|
||||
set (OSL_VERSION ${OSL_VERSION_OVERRIDE})
|
||||
endif ()
|
||||
|
||||
set (OSL_VERSION "1.13.1.0" CACHE STRING "Version")
|
||||
project (OSL VERSION ${OSL_VERSION}
|
||||
LANGUAGES CXX C
|
||||
HOMEPAGE_URL "https://github.com/AcademySoftwareFoundation/OpenShadingLanguage")
|
||||
set (PROJ_NAME ${PROJECT_NAME}) # short name
|
||||
string (TOLOWER ${PROJ_NAME} PROJ_NAME_LOWER) # short name lower case
|
||||
string (TOUPPER ${PROJ_NAME} PROJ_NAME_UPPER) # short name upper case
|
||||
set (PROJECT_VERSION_RELEASE_TYPE "dev" CACHE STRING
|
||||
set (PROJECT_VERSION_RELEASE_TYPE "" CACHE STRING
|
||||
"Build type, for example: dev, beta2, RC1 (empty string for normal release)")
|
||||
set (${PROJECT_NAME}_VERSION_RELEASE_TYPE ${PROJECT_VERSION_RELEASE_TYPE})
|
||||
set (PROJECT_AUTHORS "Contributors to the Open Shading Language project")
|
||||
option (${PROJECT_NAME}_SUPPORTED_RELEASE
|
||||
"Set ON for supported release branch, OFF for master" OFF)
|
||||
"Set ON for supported release branch, OFF for master" ON)
|
||||
if (${PROJECT_NAME}_SUPPORTED_RELEASE)
|
||||
set (${PROJECT_NAME}_DEV_RELEASE OFF)
|
||||
else ()
|
||||
@@ -81,6 +88,11 @@ include (GNUInstallDirs)
|
||||
|
||||
|
||||
option (VERBOSE "Print lots of messages while compiling" OFF)
|
||||
if (VERBOSE)
|
||||
set (CMAKE_MESSAGE_LOG_LEVEL "VERBOSE" CACHE STRING "CMake log level to display")
|
||||
else ()
|
||||
set (CMAKE_MESSAGE_LOG_LEVEL "STATUS" CACHE STRING "CMake log level to display")
|
||||
endif ()
|
||||
set (OSL_LIBNAME_SUFFIX "" CACHE STRING
|
||||
"Optional name appended to ${PROJECT_NAME} libraries that are built")
|
||||
option (OSL_BUILD_TESTS "Build the unit tests, testshade, testrender" ON)
|
||||
@@ -91,7 +103,8 @@ else ()
|
||||
endif ()
|
||||
option (OSL_BUILD_PLUGINS "Bool OSL plugins, for example OIIO plugin" ON)
|
||||
option (OSL_BUILD_SHADERS "Build shaders" ON)
|
||||
option (USE_OPTIX "Include OptiX support" OFF)
|
||||
option (OSL_USE_OPTIX "Include OptiX support" OFF)
|
||||
message(STATUS "OSL_USE_OPTIX: ${OSL_USE_OPTIX}")
|
||||
set (OPTIX_EXTRA_LIBS CACHE STRING "Extra lib targets needed for OptiX")
|
||||
set (CUDA_EXTRA_LIBS CACHE STRING "Extra lib targets needed for CUDA")
|
||||
set (CUDA_TARGET_ARCH "sm_60" CACHE STRING "CUDA GPU architecture (e.g. sm_50)")
|
||||
@@ -100,6 +113,7 @@ set (OSL_SHADER_INSTALL_DIR "${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT_NAME}/shade
|
||||
set (OSL_PTX_INSTALL_DIR "${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT_NAME}/ptx"
|
||||
CACHE STRING "Directory where OptiX PTX files will be installed")
|
||||
set (CMAKE_DEBUG_POSTFIX "" CACHE STRING "Library naming postfix for Debug builds (e.g., '_debug')")
|
||||
option (OSL_USTRINGREP_IS_HASH "Always use ustringhash for strings" OFF)
|
||||
|
||||
|
||||
set (OSL_NO_DEFAULT_TEXTURESYSTEM OFF CACHE BOOL "Do not use create a raw OIIO::TextureSystem")
|
||||
@@ -119,14 +133,14 @@ if (OIIO_FMATH_SIMD_FRIENDLY)
|
||||
add_definitions (-DOIIO_FMATH_SIMD_FRIENDLY=1)
|
||||
endif ()
|
||||
|
||||
if (USE_OPTIX)
|
||||
add_definitions ("-DOSL_USE_OPTIX=1")
|
||||
endif ()
|
||||
|
||||
# Define OSL_INTERNAL symbol only when building OSL itself, will not be
|
||||
# defined for downstream projects using OSL.
|
||||
add_definitions (-DOSL_INTERNAL=1)
|
||||
|
||||
# To make sure we aren't relying on deprecated OIIO features, we define
|
||||
# OIIO_DISABLE_DEPRECATED before including any OIIO headers.
|
||||
add_definitions (-DOIIO_DISABLE_DEPRECATED=1)
|
||||
|
||||
# Set the default namespace. For symbol hiding reasons, it's important that
|
||||
# the project name is a subset of the namespace name.
|
||||
set (${PROJ_NAME}_NAMESPACE ${PROJECT_NAME} CACHE STRING
|
||||
@@ -205,7 +219,7 @@ add_subdirectory (src/liboslnoise)
|
||||
add_subdirectory (src/oslc)
|
||||
add_subdirectory (src/oslinfo)
|
||||
|
||||
if (OSL_BUILD_TESTS)
|
||||
if (OSL_BUILD_TESTS AND BUILD_TESTING)
|
||||
add_subdirectory (src/testshade)
|
||||
add_subdirectory (src/testrender)
|
||||
endif ()
|
||||
@@ -214,7 +228,7 @@ if (OSL_BUILD_PLUGINS)
|
||||
add_subdirectory (src/osl.imageio)
|
||||
endif ()
|
||||
|
||||
if (USE_QT AND Qt5_FOUND)
|
||||
if (USE_QT AND (Qt5_FOUND OR Qt6_FOUND) AND NOT DISABLE_OSLTOY)
|
||||
add_subdirectory (src/osltoy)
|
||||
endif ()
|
||||
|
||||
@@ -280,13 +294,22 @@ configure_package_config_file ("${PROJECT_SOURCE_DIR}/src/cmake/Config.cmake.in"
|
||||
install (FILES "${OSL_PROJECT_CONFIG}" "${OSL_VERSION_CONFIG}"
|
||||
DESTINATION "${OSL_CONFIG_INSTALL_DIR}")
|
||||
|
||||
install (FILES src/cmake/llvm_macros.cmake DESTINATION cmake)
|
||||
|
||||
set (PERMISSION_FLAGS OWNER_EXECUTE OWNER_READ OWNER_WRITE
|
||||
GROUP_EXECUTE GROUP_READ
|
||||
WORLD_EXECUTE WORLD_READ)
|
||||
install (FILES src/build-scripts/serialize-bc.py
|
||||
DESTINATION build-scripts
|
||||
PERMISSIONS ${PERMISSION_FLAGS})
|
||||
|
||||
# install targets files
|
||||
install (EXPORT OSL_EXPORTED_TARGETS
|
||||
DESTINATION ${OSL_CONFIG_INSTALL_DIR}
|
||||
FILE ${OSL_TARGETS_EXPORT_NAME}
|
||||
NAMESPACE ${PROJECT_NAME}::)
|
||||
|
||||
if (${PROJECT_NAME}_BUILD_TESTS AND PROJECT_IS_TOP_LEVEL)
|
||||
if (PROJECT_IS_TOP_LEVEL AND BUILD_TESTING AND ${PROJECT_NAME}_BUILD_TESTS)
|
||||
osl_add_all_tests()
|
||||
endif ()
|
||||
|
||||
|
||||
@@ -19,11 +19,10 @@ Contributors should be reading the osl-dev mail list:
|
||||
|
||||
You can sign up for the mail list on your own using the link above.
|
||||
|
||||
We also have an `openshadinglanguage` channel on the
|
||||
[ASWF Slack](https://slack.aswf.io/). But note that the Slack channel is
|
||||
not archived, so while it's ok for fleeting comments, it is unreliable as
|
||||
a permanent repository of useful information. Serious discussions that are
|
||||
we would want to refer to over time should be sent to the mail list instead.
|
||||
The [ASWF Slack](https://slack.aswf.io/) has an `openshadinglanguage` channel.
|
||||
Sign up for the Slack on your own, then under "channels", select "browse
|
||||
channels" and you should see the openshadinglanguage channel (among those of
|
||||
the other projects and working groups).
|
||||
|
||||
|
||||
Bug Reports and Issue Tracking
|
||||
@@ -55,15 +54,16 @@ Contributor License Agreement (CLA) and Intellectual Property
|
||||
To protect the project -- and the contributors! -- we do require a
|
||||
Contributor License Agreement (CLA) for anybody submitting changes.
|
||||
|
||||
* [Corporate CLA](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/ASWF/OSL-CLA-corporate.md)
|
||||
* [Corporate CLA](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/blob/main/ASWF/CLA-corporate.md) :
|
||||
If you are writing the code as part of your job, or if there is any
|
||||
possibility that your employers might think they own any intellectual
|
||||
property you create. This needs to be executed by someone who has
|
||||
signatory power for the company.
|
||||
|
||||
* [Individual]((https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/ASWF/OSL-CLA-individual.md)).
|
||||
If you are an individual writing the code on your own time and you're SURE
|
||||
you are the sole owner of any intellectual property you contribute.
|
||||
* [Individual CLA](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/blob/main/ASWF/CLA-individual.md) :
|
||||
If you are an individual writing the code on your own time, using your own
|
||||
equipment, and you're SURE you are the sole owner of any intellectual
|
||||
property you contribute.
|
||||
|
||||
The easiest way to sign CLAs is digitally [using EasyCLA](https://corporate.v1.easycla.lfx.linuxfoundation.org).
|
||||
Companies who prefer not to use the online tools may sign, scan, and email
|
||||
@@ -79,8 +79,7 @@ Please note that these CLAs are based on the Apache 2.0 CLAs, and differ
|
||||
minimally, only as much as was required to correctly describe the EasyCLA
|
||||
process and our use of a CLA manager.
|
||||
|
||||
|
||||
** Contribution sign off
|
||||
**Contribution sign off**
|
||||
|
||||
ASWF requires the use of the [Developer’s Certificate of Origin 1.1
|
||||
(DCO)](https://developercertificate.org/), which is the same mechanism that
|
||||
@@ -115,7 +114,9 @@ repository. The protocol is like this:
|
||||
own repository on GitHub, and then clone it to get a repository on your
|
||||
local machine.
|
||||
|
||||
2. Edit, compile, and test your changes.
|
||||
2. Edit, compile, and test your changes. Run clang-format (see the
|
||||
instructions on coding style below). Our current formatting standard,
|
||||
as checked by our CI, uses clang-format 17.0.
|
||||
|
||||
3. Push your changes to your fork (each unrelated pull request to a separate
|
||||
"topic branch", please).
|
||||
@@ -127,30 +128,26 @@ component that deserves extended discussion or debate among the wider OSL
|
||||
community, then it may be prudent to email osl-dev pointing everybody to
|
||||
the pull request URL and discussing any issues you think are important.
|
||||
|
||||
6. The reviewer will look over the code and critique on the "comments" area,
|
||||
6. All pull requests automatically launch CI jobs on GitHub Actions to
|
||||
ensure that the build completes and that the tests suite runs correctly, for
|
||||
a variety of platform, compiler, library, and flag combinations. The status
|
||||
of the CI tests for your PR will be displayed on the GitHub PR page. We will
|
||||
not accept PRs that don't build cleanly or pass the existing testsuite.
|
||||
|
||||
7. The reviewer will look over the code and critique on the "comments" area,
|
||||
or discuss in email. Reviewers may ask for changes, explain problems they
|
||||
found, congratulate the author on a clever solution, etc. But until somebody
|
||||
says "LGTM" (looks good to me), the code should not be committed. Sometimes
|
||||
this takes a few rounds of give and take. Please don't take it hard if your
|
||||
first try is not accepted. It happens to all of us.
|
||||
|
||||
7. After approval, one of the senior developers (with commit approval to the
|
||||
8. After approval, one of the senior developers (with commit approval to the
|
||||
official main repository) will merge your fixes into the master branch.
|
||||
|
||||
|
||||
Coding Style
|
||||
------------
|
||||
|
||||
There are two overarching rules:
|
||||
|
||||
1. When making changes, conform to the style and conventions of the surrounding code.
|
||||
|
||||
2. Strive for clarity, even if that means occasionally breaking the
|
||||
guidelines. Use your head and ask for advice if your common sense seems to
|
||||
disagree with the conventions.
|
||||
|
||||
Below we try to enumerate the guidelines embodied in the code.
|
||||
|
||||
#### File conventions
|
||||
|
||||
C++ implementation should be named `*.cpp`. Headers should be named `.h`.
|
||||
@@ -158,115 +155,73 @@ All headers should contain
|
||||
|
||||
#pragma once
|
||||
|
||||
All source files should begin with these three lines:
|
||||
|
||||
All source files should begin with the copyright and license, which can be
|
||||
found in the [LICENSE](LICENSE) file (or cut and pasted from any other other source
|
||||
file). Two notes on this:
|
||||
// Copyright Contributors to the Open Shading Language project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
* For NEW source files, please change the copyright year to the present. DO
|
||||
NOT edit existing files only to update the copyright year, it just creates
|
||||
pointless deltas and offers no increased protection.
|
||||
as a comment in the syntax of whatever source code is used in that file (for
|
||||
example, for python or shell files, use `#` rather than `//`).
|
||||
|
||||
* Occasionally a file contains substantial code from another project
|
||||
and will also list its copyright. Do NOT copy that notice to any new files,
|
||||
it really only applies to the particular file in which it appears.
|
||||
Occasionally a file may contain substantial code from another project and will
|
||||
also list its original copyright and license information. Do NOT alter that
|
||||
notice or copy it to any new files, it really only applies to the particular
|
||||
file in which it appears.
|
||||
|
||||
#### Formatting
|
||||
|
||||
We use clang-format to enforce formatting rules for the vast majority of the
|
||||
code base. It is automatically run during CI and is a CI failure if the code
|
||||
does not conform. There are, however, parts of the code base that are not
|
||||
clang-formatted, either because we have not yet put them under the
|
||||
clang-format regime, or because individual modules were deemed to be less
|
||||
clear with clang-format than with hand formatting.
|
||||
We use [clang-format](https://clang.llvm.org/docs/ClangFormat.html) v17
|
||||
to uniformly format our source code prior to PR submission. Make sure that
|
||||
clang-format is installed on your local machine, and just run
|
||||
|
||||
For non-clang-format regions of code, NEVER alter somebody else's code to
|
||||
reformat just because you found something that violates the rules. Let the
|
||||
group/author/leader know, and resist the temptation to change it yourself.
|
||||
make clang-format
|
||||
|
||||
Each line of text in your code should be at most 80 characters long.
|
||||
Exceptions are allowed for those rare cases where letting a line be longer
|
||||
(and wrapping on an 80-character window) is actually a better and clearer
|
||||
alternative than trying to split it into two lines. Sometimes this happens,
|
||||
but it's extremely rare.
|
||||
and it will automatically reformat your code according to the configuration
|
||||
file found in the `.clang-format` file at the root directory of the OSL
|
||||
source code checkout.
|
||||
|
||||
Indent 4 spaces at a time, and use actual spaces, not tabs. For files that
|
||||
must use tabs for some reason, tabs should always be on 8's. Most editors
|
||||
have a setting that forces indentations to be spaces. With emacs, you can do
|
||||
this:
|
||||
One of the CI test matrix entries runs clang-format and fails if any
|
||||
diffs were generated (that is, if any of your code did not 100% conform to
|
||||
the `.clang-format` formatting configuration). If it fails, clicking on that
|
||||
test log will show you the diffs generated, so that you can easily correct
|
||||
it on your end and update the PR with the formatting fixes.
|
||||
|
||||
(setq c-default-style "bsd")
|
||||
(setq-default indent-tabs-mode nil)
|
||||
If you don't have clang-format set up on your machine, and your patch is not
|
||||
very long, you may find that it's more convenient to just submit it and hope
|
||||
for the best, and if it doesn't pass the CI test, look at the diffs in the log
|
||||
for the "clang-format" CI run and make the corrections by hand and then submit
|
||||
an update to the patch (i.e. relying on CI to run clang-format for you).
|
||||
|
||||
Opening brace on the same line as the condition or loop.
|
||||
Because the basic formatting is automated by clang-format, we won't
|
||||
enumerate the rules here.
|
||||
|
||||
One statement per line, except in rare cases where violating this rule makes
|
||||
the code more clear.
|
||||
For the occasional non-clang-format regions of code, NEVER alter somebody
|
||||
else's code to reformat just because you found something that violates the
|
||||
rules. Let the group/author/leader know, and resist the temptation to change
|
||||
it yourself.
|
||||
|
||||
Three (3) consecutive empty lines between function or class method
|
||||
implementations, one blank line between method declarations within a class
|
||||
definition. Put a single blank line within a function if it helps to
|
||||
visually separate different sequential tasks. Don't put multiple blank lines
|
||||
in a row within a function, or blank lines right after an opening brace or
|
||||
right before a closing brace. The goal is to use just enough white space to
|
||||
help developers visually parse the code (for example, spotting at a glance
|
||||
where new functions begin), but not so much as to spread it out or be
|
||||
confusing.
|
||||
Each line of text in your code, including comments, should be at most 80
|
||||
characters long. Exceptions are allowed for those rare cases where letting a
|
||||
line be longer (and wrapping on an 80-character window) is actually a better
|
||||
and clearer alternative than trying to split it into two lines. Sometimes this
|
||||
happens, but it's extremely rare.
|
||||
|
||||
For if, for, while, etc., put a space before the paren, but NOT inside the parens. For example:
|
||||
We prefer three (3) consecutive empty lines between freestanding functions or
|
||||
class definitions, one blank line between method declarations within a class
|
||||
definition. Put a single blank line within a function if it helps to visually
|
||||
separate different sequential tasks, but don't put multiple blank lines in a
|
||||
row within a function, or blank lines right after an opening brace or right
|
||||
before a closing brace. The goal is to use just enough white space to help
|
||||
developers visually parse the code (for example, spotting at a glance where
|
||||
new functions begin), but not so much as to spread it out or be confusing.
|
||||
|
||||
if (foo) // Yes
|
||||
|
||||
if(foo) // No
|
||||
if ( foo ) // No
|
||||
|
||||
Function calls should have a space between the function name and the opening
|
||||
parenthesis, NO space inside the parenthesis, except for a single blank
|
||||
space between each argument. For example:
|
||||
|
||||
x = foo(a, b); // Yes
|
||||
|
||||
x = foo ( a, b ); // No
|
||||
x = foo (a,b); // No
|
||||
|
||||
Function declarations: function names should begin at column 0 for a full
|
||||
function definition. (It's ok to violate this rule for very short inline
|
||||
functions within class definitions.)
|
||||
|
||||
|
||||
Here is a short code fragment that shows some of these rules in action:
|
||||
|
||||
static int
|
||||
function(int a, int b)
|
||||
{
|
||||
int x = a + b;
|
||||
if (a == 0 || b == 0) {
|
||||
x += 1;
|
||||
x *= 4;
|
||||
} else {
|
||||
x -= 3;
|
||||
}
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
x += a * i;
|
||||
x *= foo(i); // function call
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
Don't ever reformat, re-indent, change whitespace, or make any other such
|
||||
changes to working code. If you're adding just a few lines or fixing a bug
|
||||
in existing code, stick to the style of the surrounding code. In very rare
|
||||
circumstances, and with consensus of the group, reformatting is sometimes
|
||||
helpful to improve code readability, but it should be done as a separate
|
||||
formatting-only checkin.
|
||||
|
||||
#### Identifiers
|
||||
|
||||
In general, classes and templates should start with upper case and capitalize new words:
|
||||
|
||||
class CustomerList;
|
||||
|
||||
In general, local variables should start with lower case.
|
||||
In general, classes and templates should start with upper case and
|
||||
capitalize new words: `class CustomerList;` In general, local variables
|
||||
should start with lower case. Macros should be `ALL_CAPS`, if used at all.
|
||||
|
||||
If your class is extremely similar to, or modeled after, something in the
|
||||
standard library, Boost, or something else we interoperate with, it's ok to
|
||||
@@ -278,8 +233,6 @@ were standards.
|
||||
template <class T> shared_ptr;
|
||||
class scoped_mutex;
|
||||
|
||||
Macros should be ALL_CAPS, if used at all.
|
||||
|
||||
Names of data should generally be nouns. Functions/methods are trickier: a
|
||||
the name of a function that returns a value but has no side effects should
|
||||
be a noun, but a procedure that performs an action should be a verb.
|
||||
@@ -310,7 +263,7 @@ Prefer C++11 `std` rather than Boost or other third party libraries, where
|
||||
both can do the same task.
|
||||
|
||||
If you see a third party library already used as a dependency (such as OIIO,
|
||||
Boost, Ilmbase, or LLVM), feel free to any of its public features in OSL
|
||||
Boost, Imath, or LLVM), feel free to any of its public features in OSL
|
||||
internals (provided those features are present in the minimum version of
|
||||
that library that we support).
|
||||
|
||||
@@ -334,9 +287,6 @@ protected members of classes), please use Doxygen-style comments. They looks
|
||||
like this:
|
||||
|
||||
/// Explanation of a class. Note THREE slashes!
|
||||
/// Also, you need at least two lines like this. If you don't have enough
|
||||
/// for two lines, make one line blank like this:
|
||||
///
|
||||
class myclass {
|
||||
....
|
||||
float foo; ///< Doxygen comments on same line look like this
|
||||
|
||||
@@ -12,16 +12,16 @@ 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.12 or newer (tested through 3.24)
|
||||
* Build system: [CMake](https://cmake.org/) **3.15 or newer** (tested through 3.27)
|
||||
|
||||
* A suitable C++14 or C++17 compiler to build OSL itself, which may be any of:
|
||||
- GCC 6.1 or newer (tested through gcc 12.1)
|
||||
- Clang 3.4 or newer (tested through clang 15)
|
||||
- Clang 3.4 or newer (tested through clang 17)
|
||||
- Microsoft Visual Studio 2017 or newer
|
||||
- Intel C++ compiler icc version 17 or newer or LLVM-based icx compiler
|
||||
version 2022 or newer.
|
||||
|
||||
* **[OpenImageIO](http://openimageio.org) 2.3 or newer** (tested through 2.4)
|
||||
* **[OpenImageIO](http://openimageio.org) 2.4 or newer** (tested through 2.5 and master)
|
||||
|
||||
OSL uses OIIO both for its texture mapping functionality as well as
|
||||
numerous utility classes. If you are integrating OSL into an existing
|
||||
@@ -40,32 +40,38 @@ NEW or CHANGED dependencies since the last major release are **bold**.
|
||||
$OpenImageIO_ROOT/lib to be in your LD_LIBRARY_PATH (or
|
||||
DYLD_LIBRARY_PATH on OS X).
|
||||
|
||||
* [LLVM](http://www.llvm.org) 9, 10, 11, 12, 13, 14, or 15, including
|
||||
* [LLVM](http://www.llvm.org) 9, 10, 11, 12, 13, 14, 15, 16, or 17, including
|
||||
clang libraries.
|
||||
|
||||
* (optional) For GPU rendering on NVIDIA GPUs:
|
||||
* [OptiX](https://developer.nvidia.com/rtx/ray-tracing/optix) 7.0 or higher.
|
||||
* [Cuda](https://developer.nvidia.com/cuda-downloads) 8.0 or higher.
|
||||
* [Cuda](https://developer.nvidia.com/cuda-downloads) 9.0 or higher. It is
|
||||
recommended that you use 11.0 or higher.
|
||||
|
||||
* [Boost](https://www.boost.org) 1.55 or newer (tested through boost 1.80)
|
||||
* [Ilmbase or Imath](https://github.com/AcademySoftwareFoundation/openexr) 2.3
|
||||
or newer (recommended: 2.4 or higher; tested through 3.1)
|
||||
* [Boost](https://www.boost.org) 1.55 or newer (tested through boost 1.84)
|
||||
* [Ilmbase or Imath](https://github.com/AcademySoftwareFoundation/Imath) 2.4
|
||||
or newer (recommended: 3.1 or higher; tested through 3.2)
|
||||
NOTE: It is likely that 1.13 is the last release that will support
|
||||
Imath/OpenEXR 2.x.
|
||||
* [Flex](https://github.com/westes/flex) 2.5.35 or newer and
|
||||
[GNU Bison](https://www.gnu.org/software/bison/) 2.7 or newer.
|
||||
Note that on some MacOS/xcode releases, the system-installed Bison is too
|
||||
old, and it's better to install a newer Bison (via Homebrew is one way to
|
||||
do this easily).
|
||||
* [PugiXML](http://pugixml.org/)
|
||||
* [PugiXML](http://pugixml.org/) >= 1.8 (we have tested through 1.13).
|
||||
* (optional) [Partio](https://www.disneyanimation.com/technology/partio.html)
|
||||
If it is not found at build time, the OSL `pointcloud` functions will not
|
||||
be operative.
|
||||
* (optional) Python: If you are building the Python bindings or running the
|
||||
testsuite:
|
||||
* Python >= 2.7 (tested against 2.7, 3.7, 3.8, 3.9, 3.10)
|
||||
* pybind11 >= 2.4.2 (Tested through 2.10)
|
||||
* Python >= 2.7 (tested against 2.7, 3.7, 3.8, 3.9, 3.10, 3.11)
|
||||
NOTE: It is likely that 1.13 is the last release that will support
|
||||
Python 2.7.
|
||||
* pybind11 >= 2.4.2 (Tested through 2.11. Note that pybind11 v2.10+ does
|
||||
not support Python < 3.6.)
|
||||
* NumPy
|
||||
* (optional) Qt >= 5.6 (tested through 5.15). If not found at build time,
|
||||
the `osltoy` application will be disabled.
|
||||
* (optional) Qt5 >= 5.6 or Qt6 (tested Qt5 through 5.15 and Qt6 through 6.6).
|
||||
If not found at build time, the `osltoy` application will be disabled.
|
||||
|
||||
|
||||
|
||||
@@ -91,9 +97,16 @@ 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
|
||||
You can also ignore the top level Makefile wrapper, and instead use
|
||||
CMake directly:
|
||||
|
||||
cmake -B build -S .
|
||||
cmake --build build --target install
|
||||
|
||||
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",
|
||||
or if using cmake directly, add `-DSTOP_ON_WARNING=0` to the cmake
|
||||
configuration command. That will create a build that will only stop for
|
||||
full errors, not warnings.
|
||||
|
||||
4. After compilation, you'll end up with a full OSL distribution in
|
||||
|
||||
@@ -46,7 +46,7 @@ INSTALL_PREFIX ?= ${working_dir}/${dist_dir}
|
||||
VERBOSE ?= ${SHOWCOMMANDS}
|
||||
ifneq (${VERBOSE},)
|
||||
MY_MAKE_FLAGS += VERBOSE=${VERBOSE}
|
||||
MY_CMAKE_FLAGS += -DVERBOSE:BOOL=${VERBOSE}
|
||||
MY_CMAKE_FLAGS += -DVERBOSE:BOOL=${VERBOSE} --log-level=VERBOSE
|
||||
ifneq (${VERBOSE},0)
|
||||
MY_NINJA_FLAGS += -v
|
||||
TEST_FLAGS += -V
|
||||
@@ -209,7 +209,10 @@ ifneq (${BUILD_MISSING_DEPS},)
|
||||
endif
|
||||
|
||||
ifneq (${USE_OPTIX},)
|
||||
MY_CMAKE_FLAGS += -DUSE_OPTIX:BOOL=${USE_OPTIX}
|
||||
MY_CMAKE_FLAGS += -DOSL_USE_OPTIX:BOOL=${USE_OPTIX}
|
||||
endif
|
||||
ifneq (${OSL_USE_OPTIX},)
|
||||
MY_CMAKE_FLAGS += -DOSL_USE_OPTIX:BOOL=${OSL_USE_OPTIX}
|
||||
endif
|
||||
|
||||
ifneq (${USE_PYTHON},)
|
||||
@@ -397,7 +400,7 @@ help:
|
||||
@echo " USE_SIMD=arch Build with SIMD support (comma-separated choices:"
|
||||
@echo " 0, sse2, sse3, ssse3, sse4.1, sse4.2, f16c,"
|
||||
@echo " avx, avx2, avx512f)"
|
||||
@echo " USE_OPTIX=1 Build the OptiX test renderer"
|
||||
@echo " OSL_USE_OPTIX=1 Build the OptiX test renderer"
|
||||
@echo " USE_BATCHED=targets Build batched SIMD execution of shaders for (comma-separated choices:"
|
||||
@echo " 0, b8_AVX, b8_AVX2, b8_AVX2_noFMA,"
|
||||
@echo " b8_AVX512, b8_AVX512_noFMA,"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div align="center">
|
||||
<img src="https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/blob/main/src/doc/Figures/osl-short.png" width=256 height=128>
|
||||
<img src="ASWF/logos/openshadinglanguage-stacked-Shaded.png">
|
||||
|
||||
<H1>Open Shading Language</H1>
|
||||
<!-- <H1>Open Shading Language</H1> -->
|
||||
</div>
|
||||
|
||||
[](https://www.youtube.com/watch?v=nmwMz1YnGPA "Open Shading Language Reel 2020")
|
||||
@@ -9,7 +9,7 @@
|
||||
[](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/actions)
|
||||
[](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/LICENSE.md)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/3061)
|
||||
|
||||
[](https://open-shading-language.readthedocs.io/en/main/?badge=main)
|
||||
|
||||
|
||||
Introduction
|
||||
@@ -219,14 +219,15 @@ inferred from public sources, or that we've been told is ok to list here. If
|
||||
an OSL-using project is missing and it's not a secret, just email the OSL
|
||||
project leader or submit a PR with edits to this file.*
|
||||
|
||||
Renderers and other tools with OSL support (in approximate order of
|
||||
adding OSL support):
|
||||
* Sony Pictures Imageworks: in-house "Arnold" renderer
|
||||
### Renderers and other production tools with OSL support
|
||||
|
||||
(In approximate order of adding OSL support)
|
||||
|
||||
* [Sony Pictures Imageworks: in-house "Arnold" renderer](https://dl.acm.org/doi/10.1145/3180495)
|
||||
* [Blender/Cycles](https://docs.blender.org/manual/en/dev/render/shader_nodes/osl.html)
|
||||
* [Chaos Group: V-Ray](https://www.chaosgroup.com/)
|
||||
* [Pixar: PhotoRealistic RenderMan RIS](https://renderman.pixar.com)
|
||||
* [Isotropix: Clarisse](http://www.isotropix.com/clarisse)
|
||||
* [Isotropix: Angie](http://www.isotropix.com/angie)
|
||||
* Isotropix: [Clarisse iFX](https://www.isotropix.com/products/clarisse/ifx) / [Clarisse BUiLDER](https://www.isotropix.com/products/clarisse/builder) / [Angie](https://www.isotropix.com/products/angie)
|
||||
* [Autodesk Beast](http://www.autodesk.com/products/beast/overview)
|
||||
* [Appleseed](http://appleseedhq.net)
|
||||
* [Animal Logic: Glimpse renderer](https://www.fxguide.com/featured/a-glimpse-at-animal-logic/)
|
||||
@@ -237,7 +238,13 @@ adding OSL support):
|
||||
* [Autodesk: 3DS Max 2019](https://help.autodesk.com/view/3DSMAX/2019/ENU/?guid=__developer_3ds_max_sdk_features_rendering_osl_html)
|
||||
* [Maxon: Redshift](https://www.maxon.net/en/redshift)
|
||||
|
||||
Films using OSL (grouped by year of release date):
|
||||
### Significant work using OSL, grouped by year of release date:
|
||||
|
||||
(Here we are considering "significant work" to mean a feature film released
|
||||
theatrically or on a major streaming platform, TV/streaming series heavily
|
||||
featuring visual effects or animation, or short films that have won or been
|
||||
nominated for major awards.)
|
||||
|
||||
* **(2012)**
|
||||
Men in Black 3, The Amazing Spider-Man, Hotel Transylvania
|
||||
* **(2013)**
|
||||
@@ -272,6 +279,7 @@ Films using OSL (grouped by year of release date):
|
||||
Ghostbusters,
|
||||
Star Trek Beyond,
|
||||
Suicide Squad,
|
||||
Kubo and the Two Strings,
|
||||
Kingsglaive: Final Fantasy XV,
|
||||
Storks,
|
||||
Miss Peregrine's Home for Peculiar Children,
|
||||
@@ -306,7 +314,7 @@ Films using OSL (grouped by year of release date):
|
||||
* **(2018)**
|
||||
Peter Rabbit,
|
||||
Black Panther,
|
||||
Annnihilation,
|
||||
Annihilation,
|
||||
Red Sparrow,
|
||||
Pacific Rim Uprising,
|
||||
Avengers Infinity War,
|
||||
@@ -354,7 +362,8 @@ Films using OSL (grouped by year of release date):
|
||||
Richard Jewell,
|
||||
Game of Thrones (S8),
|
||||
Lost in Space (S1),
|
||||
Togo
|
||||
Togo,
|
||||
Missing Link
|
||||
* **(2020)**
|
||||
Underwater,
|
||||
Birds of Prey,
|
||||
@@ -370,7 +379,9 @@ Films using OSL (grouped by year of release date):
|
||||
Over the Moon,
|
||||
Wonder Woman 1984,
|
||||
Soul,
|
||||
The Mandalorian (S2)
|
||||
The Mandalorian (S2),
|
||||
The Boys (S2),
|
||||
Umbrella Academy (S2)
|
||||
* **(2021)**
|
||||
Chaos Walking,
|
||||
Peter Rabbit 2: The Runaway,
|
||||
@@ -383,6 +394,7 @@ Films using OSL (grouped by year of release date):
|
||||
F9,
|
||||
Vivo,
|
||||
Jungle Cruise,
|
||||
Cinderella,
|
||||
Dune,
|
||||
No Time To Die,
|
||||
Ron's Gone Wrong,
|
||||
@@ -390,8 +402,9 @@ Films using OSL (grouped by year of release date):
|
||||
Last Night in Soho,
|
||||
Ghostbusters: Afterlife,
|
||||
Spider-Man 3: No Way Home,
|
||||
Matrix Resurrections
|
||||
* **(2022 / upcoming)**
|
||||
Matrix Resurrections,
|
||||
Sing 2
|
||||
* **(2022)**
|
||||
Hotel Transylvania 4: Transformania,
|
||||
Death on the Nile,
|
||||
Uncharted,
|
||||
@@ -404,11 +417,26 @@ Films using OSL (grouped by year of release date):
|
||||
Thor: Love and Thunder,
|
||||
The Sea Beast,
|
||||
DC League of Super Pets,
|
||||
Minions: Rise of Gru,
|
||||
Bullet Train,
|
||||
Slumberland,
|
||||
Glass Onion,
|
||||
Archive 81 (series),
|
||||
Moon Night (series),
|
||||
Obi-Wan Kenobi (series),
|
||||
The Boys (S3),
|
||||
Andor (S1)
|
||||
* **(2023 / upcoming)**
|
||||
Ant-Man and the Wasp: Quantumania,
|
||||
The Mandalorian S3,
|
||||
The Magician's Elephant,
|
||||
Super Mario Bros Film,
|
||||
Guardians of the Galaxy 3,
|
||||
Spider-Man: Across the Spider-Verse,
|
||||
Elemental,
|
||||
...
|
||||
|
||||
|
||||
|
||||
Building and Installation
|
||||
-------------------------
|
||||
|
||||
@@ -424,6 +452,24 @@ The OSL language specification can be found at
|
||||
distribution) or in the share/doc/OSL/osl-languagespec.pdf file of an
|
||||
installed binary distribution.
|
||||
|
||||
[Experimental OSL Documentation on ReadTheDocs](https://open-shading-language.readthedocs.io/)
|
||||
This will be the future documentation. It's probably as complete as the PDF,
|
||||
but it needs some proofreading, so the PDF is still considered the
|
||||
authoritative source for now. But some time soon, the old PDF specification
|
||||
will be deprecated in favor of
|
||||
this online documentation.
|
||||
<!-- is the best place to start if you are interested in how to use OSL,
|
||||
its APIs. -->
|
||||
There is also a [PDF
|
||||
version](https://readthedocs.org/projects/open-shading-language/downloads/pdf/latest/).
|
||||
|
||||
For those interested in learning to program shaders in OSL, there is the
|
||||
[Siggraph 2022 Educator's Forum](https://dl.acm.org/doi/proceedings/10.1145/3532724)
|
||||
[OSL Shaders for RenderMan](https://dl.acm.org/doi/abs/10.1145/3532724.3535604) course,
|
||||
which uses RenderMan in the examples and
|
||||
[Supplementary Materials](https://github.com/LaikaStudios/OSLShadersForRenderMan),
|
||||
but which is primarily about shader writing in OSL.
|
||||
|
||||
|
||||
Contact & reporting problems
|
||||
----------------------------
|
||||
@@ -480,19 +526,22 @@ The current project leadership is documented in the
|
||||
|
||||
Many people have contributed features, bug fixes, and other changes to OSL
|
||||
over the years: Steve Agland, Shane Ambler, Martijn Berger, Farchad
|
||||
Bidgolirad, Nicholas Bishop, Solomon Boulos, Stefan Bruens, Stefan Büttner,
|
||||
Matthaus G. Chajdas, Clark Chen, Alejandro Conty, Dieter De Baets, Thomas
|
||||
Dinges, Mads Drøschler, Luke Emrose, Louis Feng, Mark Final, Henri Fousse,
|
||||
Stephen Friedman, Syoyo Fujita, Tim Grant, Larry Gritz, Nicolas Guiard, Euan
|
||||
Haahr, Derek Haase, Sven-Hendrik Haase, John Haddon, Niklas Harrysson, Daniel
|
||||
Heckenberg, Adrien Herubel, Thiago Ize, Matt Johnson, Ronan Keryell, Chris
|
||||
Kulla, Elvic Liang, Max Liani, Adam Martinez, John Mertic, Bastien Montagne,
|
||||
Steena Monteiro, Alexis Oblet, Erich Ocean, Mikko Ohtamaa, Jino Park, Alexei
|
||||
Pawlow, Jay Reynolds, Declan Russell, Benoit Ruiz, Patrick Scheibe, Alex
|
||||
Schworer, Jonathan Scruggs, Sergey Sharybin, Sandip Shukla, Cliff Stein,
|
||||
Bidgolirad, Nicholas Bishop, Curtis Black, Rasmus Bonnedal, Solomon Boulos,
|
||||
Stefan Bruens, Stefan Büttner, Matthaus G. Chajdas, Clark Chen, Alejandro
|
||||
Conty, Damien Courtois, Dieter De Baets, Thomas Dinges, Daniel Dresser, Mads
|
||||
Drøschler, Peter Ellerington, Luke Emrose, Louis Feng, Mark Final, Henri
|
||||
Fousse, Stephen Friedman, Syoyo Fujita, Tim Grant, Larry Gritz, Nicolas
|
||||
Guiard, Euan Haahr, Derek Haase, Sven-Hendrik Haase, John Haddon, Niklas
|
||||
Harrysson, Daniel Heckenberg, Chris Hellmuth, Adrien Herubel, Dan Horák,
|
||||
Thiago Ize, Matt Johnson, Ronan Keryell, Chris Kulla, Elvic Liang, Max Liani,
|
||||
Adam Martinez, John Mertic, Bastien Montagne, Steena Monteiro, Patrick Mours,
|
||||
Alexis Oblet, Erich Ocean, Mikko Ohtamaa, Jino Park, Alexei Pawlow, Jay
|
||||
Reynolds, Declan Russell, Benoit Ruiz, Patrick Scheibe, Alex Schworer,
|
||||
Jonathan Scruggs, Sergey Sharybin, Mark Sisson, Sandip Shukla, Cliff Stein,
|
||||
Stephan Steinbach, Luya Tshimbalanga, Esteban Tovagliari, Brecht Van Lommel,
|
||||
Alexander von Knorring, Alex Wells, Roman Zulak. (Listed alphabetically; if
|
||||
we've left anybody out, it is inadvertent, please let us know.)
|
||||
Alexander von Knorring, Aidan Welch, Alex Wells, Roman Zulak. (Listed
|
||||
alphabetically; if we've left anybody out, it is inadvertent, please let us
|
||||
know.)
|
||||
|
||||
We cannot possibly express sufficient gratitude to the managers at Sony
|
||||
Pictures Imageworks who allowed this project to proceed, supported it
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
||||
<!-- Copyright Contributors to the Open Shading Language Project. -->
|
||||
|
||||
Inlining Options for OptiX and CUDA
|
||||
===================================
|
||||
|
||||
When compiling shaders for OptiX and CUDA (and in general), there is a tradeoff
|
||||
between compile speed and shade-time performance. The LLVM optimizer generally
|
||||
does a good job of balancing these concerns, but there might be cases where a
|
||||
renderer can give additional hints to the optimizer to tip the balance one way
|
||||
or the other.
|
||||
|
||||
Aggressive inlining can increase the run-time performance, but can negatively
|
||||
impact the compile speed. Inlining can be very helpful with small functions
|
||||
where the function call overhead tends to dwarf the useful instructions, so it
|
||||
is important to inline such functions when possible.
|
||||
|
||||
Choosing to __not__ inline certain functions (e.g., very large noise functions)
|
||||
allows them to be excluded from the module prior to running the LLVM optimizer
|
||||
and JIT engine, which can greatly improve the compile time. This is particularly
|
||||
beneficial when a function is not likely to be inlined anyway; removing such
|
||||
large functions from the module prior to optimization can speed up compilation
|
||||
considerably without affecting the generated PTX.
|
||||
|
||||
ShadingSystem Attributes
|
||||
------------------------
|
||||
|
||||
There are a number of `ShadingSystem` attributes to help control the inlining
|
||||
behavior. The default settings should work well in most circumstances, but they
|
||||
can be adjusted to favor compile speed over shade-time performance, or vice
|
||||
versa.
|
||||
|
||||
* `optix_no_inline_thresh`: Don't inline functions greater-than or equal-to the
|
||||
threshold. This allows them to be excluded from the module prior to
|
||||
optimization, which reduces the size of module and can greatly speed up the
|
||||
optimization and JIT stages.
|
||||
|
||||
* `optix_force_inline_thresh`: Force inline functions less-than or equal-to the
|
||||
threshold. This tends to be most helpful with relatively low values, < 30.
|
||||
|
||||
* `optix_no_inline`: Don't inline any functions. Offers the best compile times
|
||||
at the expense of shade-time performance. This option is not recommended, but is
|
||||
included for benchmarking and tuning purposes.
|
||||
|
||||
* `optix_no_inline_layer_funcs`: Don't inline the shader layer functions. This
|
||||
can moderately improve compile times at the expense of shade-time performance.
|
||||
|
||||
* `optix_merge_layer_funcs`: Allow layer functions that are only called once to
|
||||
be merged into their caller, even if `optix_no_inline_layer_funcs` is set. This
|
||||
can help restore some of the shade-time performance lost by enabling
|
||||
`optix_no_inline_layer_funcs`.
|
||||
|
||||
* `optix_no_inline_rend_lib`: Don't inline any functions defined in the
|
||||
renderer-supplied `rend_lib` module. As an alternative, the renderer can simply
|
||||
not supply the LLVM bitcode for the `rend_lib` module to the `ShadingSystem`.
|
||||
|
||||
Inline/Noinline Function Registration
|
||||
-------------------------------------
|
||||
|
||||
In addition to the `ShadingSystem` attributes, individual functions can be
|
||||
registered with the `ShadingSystem` as `inline` or `noinline`. Functions can
|
||||
be unregistered to restore the default inlining behavior. This registration
|
||||
takes precedence over the `ShadingSystem` inlining attributes, which allows
|
||||
very fine-grained control when needed.
|
||||
|
||||
```C++
|
||||
// Register
|
||||
shadingsys->register_inline_function(ustring("osl_abs_ff"));
|
||||
shadingsys->register_noinline_function(ustring("osl_gabornoise_dfdfdf"));
|
||||
|
||||
// Unregister
|
||||
shadingsys->unregister_inline_function(ustring("osl_abs_ff"));
|
||||
shadingsys->unregister_noinline_function(ustring("osl_gabornoise_dfdfdf"));
|
||||
```
|
||||
|
||||
It might be best to prefer the `ShadingSystem` attributes to control the inlining
|
||||
behavior, and to strategically register functions when it is known to be
|
||||
beneficial through benchmarking and profiling.
|
||||
|
||||
Tuning and Analysis
|
||||
-------------------
|
||||
|
||||
We have added a Python script (`src/build-scripts/analyze-ptx.py`) to help
|
||||
identify functions that might be good candidates for inlining/noinling. This
|
||||
script will generate a summary of the functions in the input PTX file, with a
|
||||
list of all functions and their sizes in CSV format. It will also generate a
|
||||
graphical reprensentation of the callgraph in DOT and PDF format.
|
||||
|
||||
An example tuning workflow might include the following steps:
|
||||
|
||||
1. Run `analyze-ptx.py` on the "shadeops" and "rend_lib" PTX files to generate
|
||||
a list of the functions contained in those modules.
|
||||
|
||||
```bash
|
||||
$ analyze_ptx.py shadeop_cuda.ptx
|
||||
$ analyze_ptx.py rend_lib_myrender.ptx
|
||||
```
|
||||
|
||||
2. Run `analyze-ptx.py` on the generated PTX for a representative shader:
|
||||
|
||||
```bash
|
||||
$ analyze_ptx.py myshader.ptx
|
||||
```
|
||||
|
||||
3. View the summary file (`myshader-summary.txt`) and the callgraph
|
||||
(`myshader-callgraph.gv`) to deterimine which library functions were _not_
|
||||
inlined. They will appear as boxes with a dashed outline in the callgraph.
|
||||
|
||||
In particular, be on the lookout for trivial functions (e.g., `osl_floor_ff`)
|
||||
which have not been inlined. If such functions appear, that might be a sign
|
||||
that the inline thresholds need to be adjusted, or that it might be
|
||||
beneficial to register specific functions.
|
||||
@@ -33,7 +33,7 @@ endif # endif ${SP_OS}
|
||||
|
||||
MY_CMAKE_FLAGS += -DSP_OS=${SP_OS}
|
||||
MY_CMAKE_FLAGS += -DSPI_COMPILER_PLATFORM=${SPI_COMPILER_PLATFORM}
|
||||
MY_CMAKE_FLAGS += -DEXTRA_CPP_ARGS:STRING="-DOSL_SPI=1" -DOSL_SITE:STRING=spi
|
||||
MY_CMAKE_FLAGS += -DOSL_SITE:STRING=spi
|
||||
MY_CMAKE_FLAGS += -DSPI_TESTS=1
|
||||
MY_CMAKE_FLAGS += -DOSL_NAMESPACE_INCLUDE_PATCH=1
|
||||
REZ_PACKAGE_ROOT ?= /shots/spi/home/software/packages
|
||||
@@ -147,14 +147,14 @@ ifeq (${SP_OS}, rhel7)
|
||||
endif
|
||||
|
||||
# Cuda/OptiX
|
||||
USE_OPTIX ?= 1
|
||||
OSL_USE_OPTIX ?= 1
|
||||
CUDA_VERSION ?= 11.1.1
|
||||
OPTIX_VERSION ?= 7.2.0
|
||||
# CUDA_TOOLKIT_ROOT_DIR = $(shell rez-env -b cuda-${CUDA_VERSION} ${SPI_COMPILER_PLATFORM} -c "echo '$CUDA_TOOLKIT_ROOT'")
|
||||
CUDA_TOOLKIT_ROOT_DIR ?= /shots/spi/home/lib/arnold/rhel7/cuda_${CUDA_VERSION}
|
||||
OptiX_ROOT ?= /shots/spi/home/lib/arnold/rhel7/optix_${OPTIX_VERSION}
|
||||
OPTIXHOME = ${OptiX_ROOT}
|
||||
MY_CMAKE_FLAGS += -DUSE_OPTIX=${USE_OPTIX} \
|
||||
MY_CMAKE_FLAGS += -DOSL_USE_OPTIX=${OSL_USE_OPTIX} \
|
||||
-DCUDA_TOOLKIT_ROOT_DIR=${CUDA_TOOLKIT_ROOT_DIR} \
|
||||
-DCUDA_EXTRA_LIBS=${CUDA_EXTRA_LIBS} \
|
||||
-DOPTIXHOME=${OPTIXHOME} -DOPTIX_EXTRA_LIBS=lzma
|
||||
@@ -189,6 +189,10 @@ else ifeq (${platform}, macosx)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@15/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@15/bin/clang++
|
||||
else ifeq (${COMPILER},clang16)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@16/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@16/bin/clang++
|
||||
else ifeq (${COMPILER},clang)
|
||||
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
||||
else ifeq (${COMPILER},gcc)
|
||||
@@ -196,13 +200,13 @@ else ifeq (${platform}, macosx)
|
||||
else ifeq (${COMPILER},)
|
||||
# default compiler is clang, taken from the LLVM directory
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=${LLVM_DIRECTORY}/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=${LLVM_DIRECTORY}/bin/clang++
|
||||
-DCMAKE_C_COMPILER=${LLVM_ROOT}/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=${LLVM_ROOT}/bin/clang++
|
||||
else ifeq (${COMPILER},llvm)
|
||||
# "llvm" means "use the clang from our llvm"
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=${LLVM_DIRECTORY}/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=${LLVM_DIRECTORY}/bin/clang++
|
||||
-DCMAKE_C_COMPILER=${LLVM_ROOT}/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=${LLVM_ROOT}/bin/clang++
|
||||
endif
|
||||
|
||||
# end generic OSX
|
||||
|
||||
@@ -23,6 +23,3 @@ sonar.exclusions=src/include/OSL/Imath/*.h,src/build-scripts/*
|
||||
# C/C++ analyzer properties
|
||||
sonar.cfamily.build-wrapper-output=build/bw_output
|
||||
sonar.cfamily.gcov.reportsPath=_coverage
|
||||
|
||||
sonar.cfamily.cache.enabled=true
|
||||
sonar.cfamily.cache.path=/tmp/sonarcache
|
||||
|
||||
@@ -0,0 +1,413 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
|
||||
import getopt
|
||||
import graphviz
|
||||
import itertools
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
from collections import OrderedDict
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Dict
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# PTX parsing helpers
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
# pre-compile some regex patterns to speed up parsing
|
||||
call_ptn = re.compile(r"^\s*(call\.uni).*$")
|
||||
dec_ptn = re.compile(r"^\s*(\.pragma|\.extern|\.visible|\.func|\.local|\.global|\.reg|\.param|LBB[0-9_]+\:)(.*)$")
|
||||
fn_ptn = re.compile(r"^(\.visible \.func|\.visible \.entry|\.weak \.func|\.func).*[\s]+([a-zA-Z0-9_]+)[\(\)]*$")
|
||||
inst_ptn = re.compile(r"^\s*([@!%p0-9 ]*)([a-zA-Z0-9\.]+)\s*([a-zA-Z0-9\$\.,% _\[\]{}+-]+);.*$")
|
||||
mem_ptn = re.compile(r"^\s*(st|ld).*;$")
|
||||
ret_ptn = re.compile(r"^\s*(ret);.*$")
|
||||
|
||||
def get_func_name(line):
|
||||
match = fn_ptn.match(line)
|
||||
if match:
|
||||
return match.group(2)
|
||||
else:
|
||||
return ""
|
||||
|
||||
def is_func_or_decl(line):
|
||||
match = fn_ptn.match(line)
|
||||
if match:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def is_call_start(line):
|
||||
if line.find("call.uni") != -1:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def is_instruction(line):
|
||||
match = call_ptn.match(line)
|
||||
if match:
|
||||
return True
|
||||
if len(line) < 4:
|
||||
return False
|
||||
if not line.endswith(';'):
|
||||
return False
|
||||
|
||||
match = dec_ptn.match(line)
|
||||
if not match:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def is_mem_inst(line):
|
||||
match = mem_ptn.match(line)
|
||||
if match:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def parse_inst(line):
|
||||
if not is_instruction(line):
|
||||
return "", "", ""
|
||||
match = call_ptn.match(line)
|
||||
if match:
|
||||
return "", "call.uni", ""
|
||||
match = ret_ptn.match(line)
|
||||
if match:
|
||||
return "", "ret", ""
|
||||
match = inst_ptn.match(line)
|
||||
if match:
|
||||
return match.group(1), match.group(2), match.group(3)
|
||||
else:
|
||||
return "", "", ""
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
@dataclass
|
||||
class FuncStats:
|
||||
func_name: str = ""
|
||||
inst_count: int = 0
|
||||
call_count: int = 0
|
||||
mem_count: int = 0
|
||||
call_dict: Dict[str, int] = field(default_factory=dict) # func name, count
|
||||
inst_dict: Dict[str, int] = field(default_factory=dict) # inst, count
|
||||
|
||||
@dataclass
|
||||
class FileStats:
|
||||
total_funcs: int = 0
|
||||
total_insts: int = 0
|
||||
total_mem_insts: int = 0
|
||||
total_calls: int = 0
|
||||
extern_funcs: Dict[str, int] = field(default_factory=dict) # func name, count
|
||||
func_calls: Dict[str, int] = field(default_factory=dict) # func name, count
|
||||
summary_dict: Dict[str, str] = field(default_factory=dict) # func name, summary
|
||||
inst_dict: Dict[str, int] = field(default_factory=dict) # inst, count
|
||||
largest_function: str = ""
|
||||
largest_size: int = 0
|
||||
csv_string: str = ""
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
def parse_ptx(ptx_filename):
|
||||
# read the raw PTX into a string
|
||||
raw_ptx = ""
|
||||
with open(ptx_filename, 'r') as ptx_file:
|
||||
raw_ptx = ptx_file.read()
|
||||
|
||||
# variables to keep track of the parsing state
|
||||
begin_func_or_decl = False
|
||||
begin_call = False
|
||||
in_func = False
|
||||
brace_count = 0
|
||||
|
||||
func_stats = FuncStats()
|
||||
func_dict = {}
|
||||
|
||||
for line in raw_ptx.splitlines():
|
||||
# strip off comments
|
||||
if line.find("//") != -1:
|
||||
line = line[:line.find("//")]
|
||||
|
||||
# trim whitespace and trailing commas
|
||||
line = line.strip(" \t\n\r,")
|
||||
|
||||
# keep track of when we hit a function declaration or definition
|
||||
if is_func_or_decl(line):
|
||||
begin_func_or_decl = True
|
||||
func_stats.func_name = get_func_name(line)
|
||||
|
||||
# keep track of braces so we can have some picture of nesting
|
||||
brace_count = brace_count + line.count('{')
|
||||
brace_count = brace_count - line.count('}')
|
||||
|
||||
# if we hit a call.uni, we need to look for the name of the callee
|
||||
# on the next pass
|
||||
if is_call_start(line):
|
||||
begin_call = True
|
||||
func_stats.call_count = func_stats.call_count + 1
|
||||
elif begin_call:
|
||||
begin_call = False
|
||||
func_stats.call_dict[line] = func_stats.call_dict.get(line, 0) + 1
|
||||
|
||||
pred, opcode, args = parse_inst(line)
|
||||
if in_func and opcode != "":
|
||||
func_stats.inst_count = func_stats.inst_count + 1
|
||||
func_stats.mem_count = func_stats.mem_count + is_mem_inst(line)
|
||||
inst = opcode
|
||||
func_stats.inst_dict[inst] = func_stats.inst_dict.get((inst), 0) + 1
|
||||
|
||||
if begin_func_or_decl and brace_count == 1:
|
||||
in_func = True
|
||||
begin_func_or_decl = False
|
||||
|
||||
# exiting the function -- save off the stats
|
||||
if in_func and brace_count == 0:
|
||||
func_dict[func_stats.func_name] = func_stats
|
||||
|
||||
# prepare for the next iteration
|
||||
func_stats = FuncStats()
|
||||
begin_func_or_decl = False
|
||||
begin_call = False
|
||||
in_func = False
|
||||
brace_count = 0
|
||||
|
||||
return func_dict
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
def gather_file_stats(func_dict):
|
||||
file_stats = FileStats()
|
||||
file_stats.total_funcs = len(func_dict)
|
||||
file_stats.csv_string = "Function Name, Total Instructions, Memory Instructions, Function Calls\n"
|
||||
|
||||
# print the function statistics
|
||||
for key, entry in sorted(func_dict.items()):
|
||||
func_name = entry.func_name
|
||||
file_stats.total_insts += entry.inst_count
|
||||
file_stats.total_mem_insts += entry.mem_count
|
||||
file_stats.total_calls += entry.call_count
|
||||
|
||||
# keep track of the largest function
|
||||
if entry.inst_count > file_stats.largest_size:
|
||||
file_stats.largest_function = func_name
|
||||
file_stats.largest_size = entry.inst_count
|
||||
|
||||
# clamp the counts to prevent divide-by-zero
|
||||
inst_count = max(1, entry.inst_count)
|
||||
mem_count = max(1, entry.mem_count)
|
||||
call_count = max(1, entry.call_count)
|
||||
|
||||
summary_string = ""
|
||||
summary_string += " Function: {}\n".format(func_name)
|
||||
summary_string += " Total Instructions: {}\n".format(inst_count)
|
||||
summary_string += " Memory Instructions: {} ({:.2f}%)\n".format(mem_count, 100 * float(mem_count)/inst_count)
|
||||
summary_string += " Total Calls: {}\n".format(entry.call_count)
|
||||
|
||||
summary_string += "\n"
|
||||
summary_string += "Top 10 Function Calls (name, count, %):\n"
|
||||
for name, count in itertools.islice(sorted(entry.call_dict.items(), key=lambda item: -item[1]), 0, 11):
|
||||
summary_string += " {}, {}, {:.2f}%\n".format(name, count, 100 * float(count)/max(1,file_stats.total_calls))
|
||||
|
||||
# print the instruction mix
|
||||
summary_string += "\n"
|
||||
summary_string += "Instruction Mix (name, count, %):\n"
|
||||
for inst, count in sorted(entry.inst_dict.items()):
|
||||
summary_string += " {}, {}, {:.2f}%\n".format(inst, count, 100 * float(count)/inst_count)
|
||||
file_stats.inst_dict[inst] = file_stats.inst_dict.get((inst), 0) + count
|
||||
|
||||
# print the call mix
|
||||
summary_string += "\n"
|
||||
summary_string += "Function Calls (name, count, %):\n"
|
||||
for name, count in sorted(entry.call_dict.items()):
|
||||
file_stats.func_calls[name] = file_stats.func_calls.get((name), 0) + count
|
||||
summary_string += " {}, {}, {:.2f}%\n".format(name, count, 100 * float(count)/call_count)
|
||||
if not name in func_dict:
|
||||
file_stats.extern_funcs[name] = 1
|
||||
|
||||
file_stats.summary_dict[func_name] = summary_string
|
||||
|
||||
file_stats.csv_string += "{},{},{},{}\n".format(func_name, entry.inst_count, entry.mem_count, entry.call_count)
|
||||
|
||||
return file_stats
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
def generate_summary(func_dict, file_stats, out_name):
|
||||
summary_string = "Overall Stats\n"
|
||||
summary_string += " Total Functions: {}\n".format(file_stats.total_funcs)
|
||||
summary_string += " Total Instructions: {}\n".format(file_stats.total_insts)
|
||||
summary_string += " Memory Instructions: {} ({:.2f}%)\n".format(file_stats.total_mem_insts, 100 * float(file_stats.total_mem_insts)/max(1, file_stats.total_insts))
|
||||
summary_string += " Total Calls: {}\n".format(file_stats.total_calls)
|
||||
summary_string += " Biggest Function: {} ({} instructions)\n".format(file_stats.largest_function, file_stats.largest_size)
|
||||
|
||||
summary_string += "\n"
|
||||
summary_string += "Top 10 Function Calls (name, count, %):\n"
|
||||
for name, count in itertools.islice(sorted(file_stats.func_calls.items(), key=lambda item: -item[1]), 0, 11):
|
||||
summary_string += " {}, {}, {:.2f}%\n".format(name, count, 100 * float(count)/max(1,file_stats.total_calls))
|
||||
|
||||
summary_string += "\n"
|
||||
summary_string += "Function Call Counts (name, count, %):\n"
|
||||
for name, count in sorted(file_stats.func_calls.items()):
|
||||
summary_string += " {}, {}, {:.2f}%\n".format(name, count, 100 * float(count)/max(1,file_stats.total_calls))
|
||||
|
||||
summary_string += "\n"
|
||||
summary_string += "Instruction Mix (name, count, %):\n"
|
||||
for name, count in sorted(file_stats.inst_dict.items()):
|
||||
summary_string += " {}, {}, {:.2f}%\n".format(name, count, 100 * float(count)/max(1,file_stats.total_insts))
|
||||
|
||||
summary_string += "\n"
|
||||
summary_string += "Uncalled Functions:\n"
|
||||
for name, count in sorted(func_dict.items()):
|
||||
if not name in file_stats.func_calls:
|
||||
summary_string += " {}\n".format(name)
|
||||
|
||||
summary_string += "\n"
|
||||
summary_string += "Extern Functions:\n"
|
||||
for name, val in sorted(file_stats.extern_funcs.items()):
|
||||
summary_string += " {}\n".format(name)
|
||||
|
||||
with open("{}-summary.txt".format(out_name), "w") as summary_file:
|
||||
summary_file.write(summary_string)
|
||||
for func_name, summary in sorted(file_stats.summary_dict.items()):
|
||||
summary_file.write("\n#---------------------------------------\n")
|
||||
summary_file.write(summary)
|
||||
|
||||
with open("{}.csv".format(out_name), "w") as csv_file:
|
||||
csv_file.write(file_stats.csv_string)
|
||||
|
||||
return summary_string
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
def wrap_name(name):
|
||||
wrapped_name = ""
|
||||
cur_line = ""
|
||||
last_char = ''
|
||||
wrap_len = 20
|
||||
split_pos = 0
|
||||
line_pos = 0
|
||||
|
||||
for cur_char in name:
|
||||
cur_line = cur_line + cur_char
|
||||
line_pos = line_pos + 1
|
||||
|
||||
if not cur_char.isalpha():
|
||||
# prefer to split at non-alphabetic characters
|
||||
split_pos = line_pos
|
||||
elif last_char.isupper() and not cur_char.isupper():
|
||||
# otherwise, prefer to split at the first capitalized letter
|
||||
# of some group
|
||||
split_pos = line_pos - 2
|
||||
|
||||
if line_pos == wrap_len:
|
||||
wrapped_name = wrapped_name + cur_line[:split_pos] + '\n'
|
||||
cur_line = cur_line[split_pos:]
|
||||
line_pos = len(cur_line)
|
||||
|
||||
last_char = cur_char
|
||||
|
||||
wrapped_name = wrapped_name + cur_line + '\n'
|
||||
return wrapped_name.strip(" \t\n\r,")
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
def generate_callgraph(func_dict, file_stats, out_name):
|
||||
callgraph = graphviz.Digraph("{} Call Graph".format(out_name),
|
||||
filename="{}-callgraph.gv".format(out_name),
|
||||
engine="dot")
|
||||
|
||||
callgraph.attr("graph", rankdir="TB")
|
||||
callgraph.attr("graph", splines="true")
|
||||
callgraph.attr("graph", concentrate="false")
|
||||
callgraph.attr("graph", clusterrank="none")
|
||||
callgraph.attr("node", fontname="Courier New")
|
||||
callgraph.attr("node", shape="square")
|
||||
callgraph.attr("node", nojustify="true")
|
||||
callgraph.attr("node", width="2.5")
|
||||
callgraph.attr("node", height="2.5")
|
||||
callgraph.attr("edge", penwidth="3")
|
||||
callgraph.attr("edge", constrain="false")
|
||||
|
||||
# create a summary node
|
||||
with callgraph.subgraph(name="Summary") as c:
|
||||
c.attr("graph", rankdir="TB")
|
||||
c.attr("graph", splines="true")
|
||||
c.attr("graph", concentrate="false")
|
||||
c.attr("graph", clusterrank="none")
|
||||
c.attr("node", fontname="Courier New")
|
||||
c.attr("node", shape="square")
|
||||
c.attr("node", nojustify="false")
|
||||
c.attr("node", width="2.5")
|
||||
c.attr("node", height="2.5")
|
||||
c.attr("edge", penwidth="3")
|
||||
c.attr("edge", constrain="false")
|
||||
c.node(name="SUMMARY",
|
||||
label="Summary\linsts: {}\lfuncs: {}\lcalls: {}\l".format
|
||||
(file_stats.total_insts, file_stats.total_funcs, file_stats.total_calls))
|
||||
|
||||
# create the nodes
|
||||
for func_name, entry in sorted(func_dict.items()):
|
||||
num_calls_to = 0
|
||||
if func_name in file_stats.func_calls:
|
||||
num_calls_to = file_stats.func_calls[func_name]
|
||||
label = "{}\n\ninsts: {}\lcalls from: {}\lcalls to: {}\l".format(
|
||||
wrap_name(func_name),
|
||||
entry.inst_count,
|
||||
entry.call_count,
|
||||
num_calls_to)
|
||||
callgraph.node(name=wrap_name(func_name), label=label)
|
||||
|
||||
# create nodes for the extern functions
|
||||
callgraph.attr("node", style="dashed")
|
||||
for key, entry in sorted(file_stats.extern_funcs.items()):
|
||||
func_name = key
|
||||
callgraph.node(wrap_name(func_name))
|
||||
|
||||
# cycle through a handful of edge colors to add a little eye candy
|
||||
color_idx = 0
|
||||
edge_colors = [ "#FF000080", # red
|
||||
"#00800F80", # green
|
||||
"#FFAF0080", # orange
|
||||
"#0000FF80", # blue
|
||||
"#40404080" ] # gray
|
||||
|
||||
# create the edges
|
||||
for key, entry in sorted(func_dict.items()):
|
||||
func_name = entry.func_name
|
||||
callgraph.attr("edge", color=edge_colors[color_idx])
|
||||
for calleeName, count in sorted(entry.call_dict.items()):
|
||||
callgraph.attr("edge", tooltip="{} -> {}".format(func_name, calleeName))
|
||||
callgraph.edge(wrap_name(func_name), wrap_name(calleeName))
|
||||
color_idx = (color_idx + 1) % len(edge_colors)
|
||||
|
||||
callgraph.render()
|
||||
|
||||
return
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2:
|
||||
sys.exit("Wrong number of arguments\nUsage: $ parse-ptx.py <path-to-PTX-file>")
|
||||
|
||||
in_name = sys.argv[1]
|
||||
if not os.path.isfile(in_name):
|
||||
sys.exit("Unable to open PTX file")
|
||||
|
||||
out_name = os.path.splitext(os.path.basename(in_name))[0]
|
||||
func_dict = parse_ptx(in_name)
|
||||
file_stats = gather_file_stats(func_dict)
|
||||
|
||||
generate_summary(func_dict, file_stats, out_name)
|
||||
generate_callgraph(func_dict, file_stats, out_name)
|
||||
|
||||
return
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Utility script to download and build abi checking tools
|
||||
#
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
# Exit the whole script if any command fails.
|
||||
set -ex
|
||||
|
||||
# Where to install the final results
|
||||
: ${LOCAL_DEPS_DIR:=${PWD}/ext}
|
||||
: ${ABITOOLS_INSTALL_DIR:=${LOCAL_DEPS_DIR}/dist}
|
||||
|
||||
mkdir -p ${LOCAL_DEPS_DIR}
|
||||
pushd ${LOCAL_DEPS_DIR}
|
||||
|
||||
git clone https://github.com/lvc/vtable-dumper
|
||||
pushd vtable-dumper ; make install prefix=${ABITOOLS_INSTALL_DIR} ; popd
|
||||
|
||||
git clone https://github.com/lvc/abi-dumper
|
||||
pushd abi-dumper ; make install prefix=${ABITOOLS_INSTALL_DIR} ; popd
|
||||
|
||||
git clone https://github.com/lvc/abi-compliance-checker
|
||||
pushd abi-compliance-checker ; make install prefix=${ABITOOLS_INSTALL_DIR} ; popd
|
||||
|
||||
popd
|
||||
|
||||
# ls -R ${LOCAL_DEPS_DIR}
|
||||
export PATH=${PATH}:${ABITOOLS_INSTALL_DIR}/bin
|
||||
@@ -12,7 +12,7 @@ set -ex
|
||||
echo "Building cmake"
|
||||
uname
|
||||
|
||||
CMAKE_VERSION=${CMAKE_VERSION:=3.12.4}
|
||||
CMAKE_VERSION=${CMAKE_VERSION:=3.18.5}
|
||||
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
|
||||
CMAKE_INSTALL_DIR=${CMAKE_INSTALL_DIR:=${LOCAL_DEPS_DIR}/cmake}
|
||||
|
||||
|
||||
@@ -14,29 +14,18 @@ uname
|
||||
|
||||
|
||||
if [[ `uname` == "Linux" ]] ; then
|
||||
LLVM_VERSION=${LLVM_VERSION:=13.0.0}
|
||||
LLVM_INSTALL_DIR=${LLVM_INSTALL_DIR:=${PWD}/llvm-install}
|
||||
if [[ "$GITHUB_WORKFLOW" != "" ]] ; then
|
||||
LLVM_DISTRO_NAME=${LLVM_DISTRO_NAME:=ubuntu-18.04}
|
||||
elif [[ "$TRAVIS_DIST" == "trusty" ]] ; then
|
||||
LLVM_DISTRO_NAME=${LLVM_DISTRO_NAME:=ubuntu-14.04}
|
||||
elif [[ "$TRAVIS_DIST" == "xenial" ]] ; then
|
||||
LLVM_DISTRO_NAME=${LLVM_DISTRO_NAME:=ubuntu-16.04}
|
||||
elif [[ "$TRAVIS_DIST" == "bionic" ]] ; then
|
||||
LLVM_DISTRO_NAME=${LLVM_DISTRO_NAME:=ubuntu-18.04}
|
||||
else
|
||||
LLVM_DISTRO_NAME=${LLVM_DISTRO_NAME:=error}
|
||||
fi
|
||||
: ${LLVM_VERSION:=14.0.0}
|
||||
: ${LLVM_INSTALL_DIR:=${PWD}/llvm-install}
|
||||
: ${LLVM_DISTRO_NAME:=ubuntu-18.04}
|
||||
LLVMTAR=clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-${LLVM_DISTRO_NAME}.tar.xz
|
||||
echo LLVMTAR = $LLVMTAR
|
||||
if [[ "$LLVM_VERSION" == "10.0.0" ]] || [[ "$LLVM_VERSION" == "11.0.0" ]] \
|
||||
|| [[ "$LLVM_VERSION" == "11.1.0" ]] || [[ "$LLVM_VERSION" == "12.0.0" ]] \
|
||||
|| [[ "$LLVM_VERSION" == "13.0.0" ]] || [[ "$LLVM_VERSION" == "14.0.0" ]] ;
|
||||
if [[ "$LLVM_VERSION" == "9.0.0" ]] || [[ "$LLVM_VERSION" == "9.0.1" ]] ;
|
||||
then
|
||||
# old -- get rid of this when LLVM 10 is the newest we allow
|
||||
curl --location http://releases.llvm.org/${LLVM_VERSION}/${LLVMTAR} -o $LLVMTAR
|
||||
else
|
||||
# new
|
||||
curl --location https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/${LLVMTAR} -o $LLVMTAR
|
||||
else
|
||||
curl --location http://releases.llvm.org/${LLVM_VERSION}/${LLVMTAR} -o $LLVMTAR
|
||||
fi
|
||||
ls -l $LLVMTAR
|
||||
tar xf $LLVMTAR
|
||||
|
||||
@@ -11,13 +11,14 @@ set -ex
|
||||
|
||||
# Which OCIO to retrieve, how to build it
|
||||
OPENCOLORIO_REPO=${OPENCOLORIO_REPO:=https://github.com/AcademySoftwareFoundation/OpenColorIO.git}
|
||||
OPENCOLORIO_VERSION=${OPENCOLORIO_VERSION:=v1.1.1}
|
||||
OPENCOLORIO_VERSION=${OPENCOLORIO_VERSION:=v2.2.1}
|
||||
|
||||
# Where to install the final results
|
||||
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
|
||||
OPENCOLORIO_SOURCE_DIR=${OPENCOLORIO_SOURCE_DIR:=${LOCAL_DEPS_DIR}/OpenColorIO}
|
||||
OPENCOLORIO_BUILD_DIR=${OPENCOLORIO_BUILD_DIR:=${LOCAL_DEPS_DIR}/OpenColorIO-build}
|
||||
OPENCOLORIO_INSTALL_DIR=${OPENCOLORIO_INSTALL_DIR:=${LOCAL_DEPS_DIR}/dist}
|
||||
OPENCOLORIO_BUILD_TYPE=${OPENCOLORIO_BUILD_TYPE:=Release}
|
||||
OPENCOLORIO_CXX_FLAGS=${OPENCOLORIO_CXX_FLAGS:="-Wno-unused-function -Wno-deprecated-declarations -Wno-cast-qual -Wno-write-strings"}
|
||||
# Just need libs:
|
||||
OPENCOLORIO_BUILDOPTS="-DOCIO_BUILD_APPS=OFF -DOCIO_BUILD_NUKE=OFF \
|
||||
@@ -42,13 +43,12 @@ cd ${OPENCOLORIO_SOURCE_DIR}
|
||||
|
||||
echo "git checkout ${OPENCOLORIO_VERSION} --force"
|
||||
git checkout ${OPENCOLORIO_VERSION} --force
|
||||
mkdir -p ${OPENCOLORIO_BUILD_DIR}
|
||||
cd ${OPENCOLORIO_BUILD_DIR}
|
||||
time cmake -DCMAKE_BUILD_TYPE=Release \
|
||||
time cmake -S . -B ${OPENCOLORIO_BUILD_DIR} \
|
||||
-DCMAKE_BUILD_TYPE=${OPENCOLORIO_BUILD_TYPE} \
|
||||
-DCMAKE_INSTALL_PREFIX=${OPENCOLORIO_INSTALL_DIR} \
|
||||
-DCMAKE_CXX_FLAGS="${OPENCOLORIO_CXX_FLAGS}" \
|
||||
${OPENCOLORIO_BUILDOPTS} ${OPENCOLORIO_SOURCE_DIR}
|
||||
time cmake --build . --config Release --target install
|
||||
${OPENCOLORIO_BUILDOPTS}
|
||||
time cmake --build ${OPENCOLORIO_BUILD_DIR} --config Release --target install
|
||||
popd
|
||||
|
||||
# ls -R ${OPENCOLORIO_INSTALL_DIR}
|
||||
|
||||
@@ -12,7 +12,7 @@ set -ex
|
||||
|
||||
# Which OpenEXR to retrieve, how to build it
|
||||
OPENEXR_REPO=${OPENEXR_REPO:=https://github.com/AcademySoftwareFoundation/openexr.git}
|
||||
OPENEXR_VERSION=${OPENEXR_VERSION:=v3.1.1}
|
||||
OPENEXR_VERSION=${OPENEXR_VERSION:=v3.1.11}
|
||||
|
||||
# Where to install the final results
|
||||
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
|
||||
@@ -37,42 +37,25 @@ if [[ ! -e ${OPENEXR_SOURCE_DIR} ]] ; then
|
||||
git clone ${OPENEXR_REPO} ${OPENEXR_SOURCE_DIR}
|
||||
fi
|
||||
mkdir -p ${OPENEXR_INSTALL_DIR} && true
|
||||
mkdir -p ${OPENEXR_BUILD_DIR} && true
|
||||
|
||||
pushd ${OPENEXR_SOURCE_DIR}
|
||||
git checkout ${OPENEXR_VERSION} --force
|
||||
|
||||
if [[ ${OPENEXR_VERSION} == "v2.3.0" ]] ; then
|
||||
# Simplified setup for 2.3+
|
||||
cd ${OPENEXR_BUILD_DIR}
|
||||
cmake -DCMAKE_BUILD_TYPE=${OPENEXR_BUILD_TYPE} \
|
||||
-DCMAKE_INSTALL_PREFIX="${OPENEXR_INSTALL_DIR}" \
|
||||
-DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}" \
|
||||
-DILMBASE_PACKAGE_PREFIX="${OPENEXR_INSTALL_DIR}" \
|
||||
-DOPENEXR_BUILD_UTILS=0 \
|
||||
-DOPENEXR_BUILD_TESTS=0 \
|
||||
-DOPENEXR_BUILD_PYTHON_LIBS=0 \
|
||||
-DCMAKE_CXX_FLAGS="${OPENEXR_CXX_FLAGS}" \
|
||||
${OPENEXR_CMAKE_FLAGS} ${OPENEXR_SOURCE_DIR}
|
||||
time cmake --build . --target install --config ${OPENEXR_BUILD_TYPE}
|
||||
else
|
||||
# Simplified setup for 2.4+
|
||||
cd ${OPENEXR_BUILD_DIR}
|
||||
cmake -DCMAKE_BUILD_TYPE=${OPENEXR_BUILD_TYPE} \
|
||||
-DCMAKE_INSTALL_PREFIX="${OPENEXR_INSTALL_DIR}" \
|
||||
-DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}" \
|
||||
-DILMBASE_PACKAGE_PREFIX="${OPENEXR_INSTALL_DIR}" \
|
||||
-DOPENEXR_BUILD_UTILS=0 \
|
||||
-DBUILD_TESTING=0 \
|
||||
-DPYILMBASE_ENABLE=0 \
|
||||
-DOPENEXR_VIEWERS_ENABLE=0 \
|
||||
-DINSTALL_OPENEXR_EXAMPLES=0 \
|
||||
-DOPENEXR_INSTALL_EXAMPLES=0 \
|
||||
-DCMAKE_INSTALL_LIBDIR=lib \
|
||||
-DCMAKE_CXX_FLAGS="${OPENEXR_CXX_FLAGS}" \
|
||||
${OPENEXR_CMAKE_FLAGS} ${OPENEXR_SOURCE_DIR}
|
||||
time cmake --build . --target install --config ${OPENEXR_BUILD_TYPE}
|
||||
fi
|
||||
cmake -S . -B ${OPENEXR_BUILD_DIR} \
|
||||
-DCMAKE_BUILD_TYPE=${OPENEXR_BUILD_TYPE} \
|
||||
-DCMAKE_INSTALL_PREFIX="${OPENEXR_INSTALL_DIR}" \
|
||||
-DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}" \
|
||||
-DILMBASE_PACKAGE_PREFIX="${OPENEXR_INSTALL_DIR}" \
|
||||
-DOPENEXR_BUILD_UTILS=0 \
|
||||
-DBUILD_TESTING=0 \
|
||||
-DPYILMBASE_ENABLE=0 \
|
||||
-DOPENEXR_VIEWERS_ENABLE=0 \
|
||||
-DINSTALL_OPENEXR_EXAMPLES=0 \
|
||||
-DOPENEXR_INSTALL_EXAMPLES=0 \
|
||||
-DCMAKE_INSTALL_LIBDIR=lib \
|
||||
-DCMAKE_CXX_FLAGS="${OPENEXR_CXX_FLAGS}" \
|
||||
${OPENEXR_CMAKE_FLAGS}
|
||||
time cmake --build ${OPENEXR_BUILD_DIR} --target install --config ${OPENEXR_BUILD_TYPE}
|
||||
|
||||
popd
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ set -ex
|
||||
|
||||
# Repo and branch/tag/commit of pugixml to download if we don't have it yet
|
||||
PUGIXML_REPO=${PUGIXML_REPO:=https://github.com/zeux/pugixml.git}
|
||||
PUGIXML_VERSION=${PUGIXML_VERSION:=v1.10}
|
||||
PUGIXML_VERSION=${PUGIXML_VERSION:=v1.11.4}
|
||||
|
||||
# Where to put pugixml repo source (default to the ext area)
|
||||
PUGIXML_SRC_DIR=${PUGIXML_SRC_DIR:=${PWD}/ext/pugixml}
|
||||
@@ -34,17 +34,18 @@ if [[ ! -e ${PUGIXML_SRC_DIR} ]] ; then
|
||||
git clone ${PUGIXML_REPO} ${PUGIXML_SRC_DIR}
|
||||
fi
|
||||
cd ${PUGIXML_SRC_DIR}
|
||||
|
||||
echo "git checkout ${PUGIXML_VERSION} --force"
|
||||
git checkout ${PUGIXML_VERSION} --force
|
||||
|
||||
mkdir -p ${PUGIXML_BUILD_DIR}
|
||||
cd ${PUGIXML_BUILD_DIR}
|
||||
time cmake -DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX=${PUGIXML_INSTALL_DIR} \
|
||||
-DBUILD_SHARED_LIBS=ON \
|
||||
-DBUILD_TESTS=OFF \
|
||||
${PUGIXML_BUILD_OPTS} ..
|
||||
time cmake --build . --config Release --target install
|
||||
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
|
||||
time cmake -S . -B ${PUGIXML_BUILD_DIR} -DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX=${PUGIXML_INSTALL_DIR} \
|
||||
-DBUILD_SHARED_LIBS=ON \
|
||||
-DBUILD_TESTS=OFF \
|
||||
${PUGIXML_BUILD_OPTS} ..
|
||||
time cmake --build ${PUGIXML_BUILD_DIR} --config Release --target install
|
||||
fi
|
||||
|
||||
# ls -R ${PUGIXML_INSTALL_DIR}
|
||||
popd
|
||||
|
||||
@@ -42,15 +42,12 @@ cd ${PYBIND11_SRC_DIR}
|
||||
echo "git checkout ${PYBIND11_VERSION} --force"
|
||||
git checkout ${PYBIND11_VERSION} --force
|
||||
|
||||
mkdir -p ${PYBIND11_BUILD_DIR}
|
||||
cd ${PYBIND11_BUILD_DIR}
|
||||
|
||||
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
|
||||
time cmake -DCMAKE_BUILD_TYPE=Release \
|
||||
time cmake -S . -B ${PYBIND11_BUILD_DIR} -DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX=${PYBIND11_INSTALL_DIR} \
|
||||
-DPYBIND11_TEST=OFF \
|
||||
${PYBIND11_BUILD_OPTS} ..
|
||||
time cmake --build . --config Release --target install
|
||||
${PYBIND11_BUILD_OPTS}
|
||||
time cmake --build ${PYBIND11_BUILD_DIR} --config Release --target install
|
||||
fi
|
||||
|
||||
# ls -R ${PYBIND11_INSTALL_DIR}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
# Important: set -ex causes this whole script to terminate with error if
|
||||
# any command in it fails. This is crucial for CI tests.
|
||||
set -e
|
||||
|
||||
# Arguments to this script are:
|
||||
# BUILDDIR_NEW BUILDDIR_OLD LIBRARIES...
|
||||
|
||||
BUILDDIR_NEW=$1
|
||||
shift
|
||||
BUILDDIR_OLD=$1
|
||||
shift
|
||||
LIBS=$*
|
||||
|
||||
#
|
||||
# First, create ABI dumps from both builds
|
||||
#
|
||||
ABI_ARGS="-bin-only -skip-cxx -public-headers $PWD/dist/include/OSL "
|
||||
echo "ABI_CHECK: PWD=${PWD} "
|
||||
ls -l $BUILDDIR_NEW
|
||||
ls -l $BUILDDIR_OLD
|
||||
for dir in $BUILDDIR_NEW $BUILDDIR_OLD ; do
|
||||
for lib in $LIBS ; do
|
||||
abi-dumper $ABI_ARGS ${dir}/lib/${lib}.so -o ${dir}/abi-${lib}.dump
|
||||
done
|
||||
done
|
||||
echo "Saved ABI dumps"
|
||||
|
||||
#
|
||||
# Run the ABI compliance checker, saving the outputs to files
|
||||
#
|
||||
for lib in $LIBS ; do
|
||||
abi-compliance-checker -l $lib -old $BUILDDIR_OLD/abi-$lib.dump -new $BUILDDIR_NEW/abi-$lib.dump | tee ${lib}-abi-results.txt || true
|
||||
echo -e "\x1b[33;1m"
|
||||
echo -e "$lib"
|
||||
fgrep "Binary compatibility:" ${lib}-abi-results.txt
|
||||
echo -e "\x1b[33;0m"
|
||||
done
|
||||
|
||||
#
|
||||
# If the "Binary compatibility" summary results say anything other than 100%,
|
||||
# we fail!
|
||||
#
|
||||
for lib in $LIBS ; do
|
||||
if [[ `fgrep "Binary compatibility:" ${lib}-abi-results.txt | grep -v 100\%` != "" ]] ; then
|
||||
cp -r compat_reports ${BUILDDIR_NEW}/compat_reports
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
@@ -1,5 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
# Run code coverage analysis
|
||||
# This assumes that the build occurred with CODECOV=1 andtests have already
|
||||
# fully run.
|
||||
|
||||
@@ -39,11 +39,6 @@ export CMAKE_GENERATOR=${CMAKE_GENERATOR:=Ninja}
|
||||
export CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE:=Release}
|
||||
export CMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD:=11}
|
||||
|
||||
export PARALLEL=${PARALLEL:=4}
|
||||
export PAR_MAKEFLAGS=-j${PARALLEL}
|
||||
export CMAKE_BUILD_PARALLEL_LEVEL=${CMAKE_BUILD_PARALLEL_LEVEL:=${PARALLEL}}
|
||||
export CTEST_PARALLEL_LEVEL=${CTEST_PARALLEL_LEVEL:=${PARALLEL}}
|
||||
|
||||
export LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=$HOME/ext}
|
||||
export CMAKE_PREFIX_PATH=${LOCAL_DEPS_DIR}/dist:${CMAKE_PREFIX_PATH}
|
||||
export LD_LIBRARY_PATH=${LOCAL_DEPS_DIR}/dist/lib:$LD_LIBRARY_PATH
|
||||
@@ -52,6 +47,25 @@ export DYLD_LIBRARY_PATH=${LOCAL_DEPS_DIR}/dist/lib:$DYLD_LIBRARY_PATH
|
||||
|
||||
export TESTSUITE_CLEANUP_ON_SUCCESS=${TESTSUITE_CLEANUP_ON_SUCCESS:=1}
|
||||
|
||||
# Parallel builds
|
||||
if [[ `uname -s` == "Linux" ]] ; then
|
||||
echo "procs: " `nproc`
|
||||
head -40 /proc/cpuinfo
|
||||
export PARALLEL=${PARALLEL:=$((2 + `nproc`))}
|
||||
elif [[ "${RUNNER_OS}" == "macOS" ]] ; then
|
||||
echo "procs: " `sysctl -n hw.ncpu`
|
||||
sysctl machdep.cpu.features
|
||||
export PARALLEL=${PARALLEL:=$((2 + `sysctl -n hw.ncpu`))}
|
||||
elif [[ "${RUNNER_OS}" == "Windows" ]] ; then
|
||||
# Presumably Windows
|
||||
export PARALLEL=${PARALLEL:=$((2 + ${NUMBER_OF_PROCESSORS}))}
|
||||
else
|
||||
export PARALLEL=${PARALLEL:=6}
|
||||
fi
|
||||
export PAR_MAKEFLAGS=-j${PARALLEL}
|
||||
export CMAKE_BUILD_PARALLEL_LEVEL=${CMAKE_BUILD_PARALLEL_LEVEL:=${PARALLEL}}
|
||||
export CTEST_PARALLEL_LEVEL=${CTEST_PARALLEL_LEVEL:=${PARALLEL}}
|
||||
|
||||
mkdir -p build dist
|
||||
|
||||
echo "HOME = $HOME"
|
||||
|
||||
@@ -18,8 +18,8 @@ if [[ "$ASWF_ORG" != "" ]] ; then
|
||||
|
||||
#ls /etc/yum.repos.d
|
||||
|
||||
sudo yum install -y giflib giflib-devel && true
|
||||
# sudo yum install -y ffmpeg ffmpeg-devel && true
|
||||
sudo /usr/bin/yum install -y giflib giflib-devel && true
|
||||
# sudo /usr/bin/yum install -y ffmpeg ffmpeg-devel && true
|
||||
|
||||
if [[ "${CONAN_LLVM_VERSION}" != "" ]] ; then
|
||||
mkdir conan
|
||||
@@ -40,28 +40,29 @@ if [[ "$ASWF_ORG" != "" ]] ; then
|
||||
popd
|
||||
fi
|
||||
|
||||
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" || "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
|
||||
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" ]] ; then
|
||||
# Lock down icc to 2022.1 because newer versions hosted on the Intel
|
||||
# repo require a glibc too new for the ASWF CentOS7-based containers
|
||||
# we run CI on.
|
||||
sudo cp src/build-scripts/oneAPI.repo /etc/yum.repos.d
|
||||
sudo yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic-2022.1.0-3768
|
||||
# Because multiple (possibly newer) versions of oneAPI may be installed,
|
||||
# use a config file to specify compiler and tbb versions
|
||||
# NOTE: oneAPI components have independent version numbering.
|
||||
sudo /usr/bin/yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic-2022.1.0.x86_64
|
||||
set +e; source /opt/intel/oneapi/setvars.sh --config oneapi_2022.1.0.cfg; set -e
|
||||
|
||||
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" ]] ; then
|
||||
echo "Verifying installation of Intel(r) C++ Compiler:"
|
||||
icpc --version
|
||||
fi
|
||||
if [[ "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
|
||||
echo "Verifying installation of Intel(r) oneAPI DPC++/C++ Compiler:"
|
||||
icpx --version
|
||||
fi
|
||||
elif [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" || "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
|
||||
# Lock down icx to 2023.1 because newer versions hosted on the Intel
|
||||
# repo require a libstd++ too new for the ASWF containers we run CI on
|
||||
# because their default install of gcc 9 based toolchain.
|
||||
sudo cp src/build-scripts/oneAPI.repo /etc/yum.repos.d
|
||||
sudo yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic-2023.1.0.x86_64
|
||||
# sudo yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic
|
||||
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
||||
echo "Verifying installation of Intel(r) oneAPI DPC++/C++ Compiler:"
|
||||
icpx --version
|
||||
fi
|
||||
|
||||
else
|
||||
# Using native Ubuntu runner
|
||||
|
||||
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
|
||||
# sudo add-apt-repository ppa:ubuntu-toolchain-r/test
|
||||
time sudo apt-get update
|
||||
|
||||
time sudo apt-get -q install -y \
|
||||
@@ -73,8 +74,13 @@ else
|
||||
libpugixml-dev \
|
||||
libopencolorio-dev
|
||||
|
||||
time sudo apt-get -q install -y \
|
||||
qt5-default || /bin/true
|
||||
if [[ "${QT_VERSION:-5}" == "5" ]] ; then
|
||||
time sudo apt-get -q install -y \
|
||||
qt5-default || /bin/true
|
||||
elif [[ "${QT_VERSION}" == "6" ]] ; then
|
||||
time sudo apt-get -q install -y \
|
||||
qt6-base-dev || /bin/true
|
||||
fi
|
||||
|
||||
export CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu:$CMAKE_PREFIX_PATH
|
||||
|
||||
@@ -120,6 +126,10 @@ else
|
||||
source src/build-scripts/build_llvm.bash
|
||||
fi
|
||||
|
||||
if [[ "$CMAKE_VERSION" != "" ]] ; then
|
||||
source src/build-scripts/build_cmake.bash
|
||||
fi
|
||||
cmake --version
|
||||
|
||||
|
||||
if [[ "$OPTIX_VERSION" != "" ]] ; then
|
||||
@@ -141,6 +151,11 @@ if [[ "$OPTIX_VERSION" != "" ]] ; then
|
||||
fi
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Packages we need to build from scratch.
|
||||
#
|
||||
|
||||
source src/build-scripts/build_pybind11.bash
|
||||
|
||||
if [[ "$OPENEXR_VERSION" != "" ]] ; then
|
||||
@@ -171,14 +186,18 @@ if [[ "$OPENIMAGEIO_VERSION" != "" ]] ; then
|
||||
# Don't let warnings in OIIO break OSL's CI run
|
||||
export OPENIMAGEIO_CMAKE_FLAGS+=" -DSTOP_ON_WARNING=OFF"
|
||||
export OPENIMAGEIO_CMAKE_FLAGS+=" -DUSE_OPENGL=0"
|
||||
if [[ $OPENIMAGEIO_VERSION == master && "${OPENIMAGEIO_UNITY:-1}" != "0" ]] ; then
|
||||
export OPENIMAGEIO_CMAKE_FLAGS+=" -DUSE_OPENCV=0 -DUSE_FFMPEG=0 -DUSE_QT=0"
|
||||
if [[ "${OPENIMAGEIO_UNITY:-1}" != "0" ]] ; then
|
||||
# Speed up the OIIO build by doing a "unity" build. (Note: this is
|
||||
# only a savings in CI where there are only 1-2 cores available, and
|
||||
# is only supported for OIIO 2.3.14 and later)
|
||||
# only a savings in CI where there are only 1-2 cores available.)
|
||||
export OPENIMAGEIO_CMAKE_FLAGS+=" -DCMAKE_UNITY_BUILD=ON -DCMAKE_UNITY_BUILD_MODE=BATCH"
|
||||
fi
|
||||
source src/build-scripts/build_openimageio.bash
|
||||
fi
|
||||
|
||||
if [[ "$ABI_CHECK" != "" ]] ; then
|
||||
source src/build-scripts/build_abi_tools.bash
|
||||
fi
|
||||
|
||||
# Save the env for use by other stages
|
||||
src/build-scripts/save-env.bash
|
||||
|
||||
@@ -19,6 +19,7 @@ if [[ `which brew` == "" ]] ; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -ex
|
||||
|
||||
if [[ "$DO_BREW_UPDATE" != "" ]] ; then
|
||||
brew update >/dev/null
|
||||
@@ -30,41 +31,41 @@ brew list --versions
|
||||
brew install --display-times -q gcc ccache cmake ninja boost || true
|
||||
brew link --overwrite gcc
|
||||
brew install --display-times -q python@${PYTHON_VERSION} || true
|
||||
brew unlink python@2.7 || true
|
||||
brew unlink python@3.8 || true
|
||||
brew unlink python@3.9 || true
|
||||
# brew unlink python@3.8 || true
|
||||
# brew unlink python@3.9 || true
|
||||
brew unlink python@3.10 || true
|
||||
brew link --overwrite --force python@${PYTHON_VERSION} || true
|
||||
brew upgrade --display-times -q cmake || true
|
||||
brew install --display-times -q ilmbase openexr
|
||||
brew install --display-times -q imath openexr
|
||||
#brew install --display-times -q freetype
|
||||
brew install --display-times -q opencolorio partio pugixml
|
||||
brew install --display-times -q --overwrite --force opencolorio || true
|
||||
brew install --display-times -q partio pugixml
|
||||
brew install --display-times -q pybind11 numpy || true
|
||||
brew install --display-times -q tbb || true
|
||||
brew install --display-times -q openvdb || true
|
||||
brew install --display-times -q flex bison
|
||||
brew install --display-times -q fmt
|
||||
brew install --display-times -q llvm${LLVMBREWVER}
|
||||
brew install --display-times -q qt
|
||||
if [[ "${USE_QT}" != "0" ]] ; then
|
||||
brew install --display-times -q qt${QT_VERSION}
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "After brew installs:"
|
||||
brew list --versions
|
||||
|
||||
# Needed on some systems
|
||||
if [[ $PYTHON_VERSION != "2.7" ]] ; then
|
||||
pip3 install numpy
|
||||
else
|
||||
pip install numpy
|
||||
fi
|
||||
pip${PYTHON_VERSION} install numpy
|
||||
|
||||
# Set up paths. These will only affect the caller if this script is
|
||||
# run with 'source' rather than in a separate shell.
|
||||
export PATH=/usr/local/opt/qt5/bin:$PATH
|
||||
export PATH=/usr/local/opt/python/libexec/bin:$PATH
|
||||
export PYTHONPATH=/usr/local/lib/python${PYTHON_VERSION}/site-packages:$PYTHONPATH
|
||||
# export PATH=/usr/local/opt/llvm${LLVMBREWVER}/bin:$PATH
|
||||
export LLVM_DIRECTORY=/usr/local/opt/llvm${LLVMBREWVER}
|
||||
export LLVM_ROOT=/usr/local/opt/llvm${LLVMBREWVER}
|
||||
export PATH=/usr/local/opt/flex/bin:/usr/local/opt/bison/bin:$PATH
|
||||
export PATH=${HOMEBREW_PREFIX}/opt/qt5/bin:$PATH
|
||||
export PATH=${HOMEBREW_PREFIX}/opt/python/libexec/bin:$PATH
|
||||
export PYTHONPATH=${HOMEBREW_PREFIX}/lib/python${PYTHON_VERSION}/site-packages:$PYTHONPATH
|
||||
# export PATH=${HOMEBREW_PREFIX}/opt/llvm${LLVMBREWVER}/bin:$PATH
|
||||
export LLVM_DIRECTORY=${HOMEBREW_PREFIX}/opt/llvm${LLVMBREWVER}
|
||||
export LLVM_ROOT=${HOMEBREW_PREFIX}/opt/llvm${LLVMBREWVER}
|
||||
export PATH=${HOMEBREW_PREFIX}/opt/flex/bin:${HOMEBREW_PREFIX}/opt/bison/bin:$PATH
|
||||
|
||||
# Save the env for use by other stages
|
||||
src/build-scripts/save-env.bash
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# Small leaks that make CI fail, suppress until cause is identified.
|
||||
leak:__cxa_thread_atexit
|
||||
leak:std::string::_Rep::_S_create
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
# Open a PTX file and:
|
||||
# * add the `.visible` directive to all functions
|
||||
# * add the `.visible` directive to global/constant variables
|
||||
|
||||
from __future__ import print_function, absolute_import
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
in_name = sys.argv[1]
|
||||
out_name = sys.argv[2]
|
||||
ptx = ""
|
||||
with open(in_name, 'r') as ptx_in:
|
||||
ptx = ptx_in.read()
|
||||
ptx = re.sub(r'(?m)^(\.const .align)', ".visible .const .align", ptx)
|
||||
ptx = re.sub(r'(?m)^(\.global .align)', ".visible .global .align", ptx)
|
||||
ptx = re.sub(r'(?m)^(\.func)', ".visible .func", ptx)
|
||||
with open(out_name, 'w') as ptx_out:
|
||||
ptx_out.write(ptx)
|
||||
@@ -1,5 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
# Save the env for use by other stages. Exclude things that we know aren't
|
||||
# needed.
|
||||
printenv \
|
||||
|
||||
@@ -15,13 +15,11 @@
|
||||
###########################################################################
|
||||
# Print some basic status about the system and compiler
|
||||
#
|
||||
if (VERBOSE)
|
||||
message (STATUS "CMAKE_SYSTEM_NAME = ${CMAKE_SYSTEM_NAME}")
|
||||
message (STATUS "CMAKE_SYSTEM_VERSION = ${CMAKE_SYSTEM_VERSION}")
|
||||
message (STATUS "CMAKE_SYSTEM_PROCESSOR = ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
endif ()
|
||||
message (STATUS "CMAKE_CXX_COMPILER = ${CMAKE_CXX_COMPILER}")
|
||||
message (STATUS "CMAKE_CXX_COMPILER_ID = ${CMAKE_CXX_COMPILER_ID}")
|
||||
message (VERBOSE "CMAKE_SYSTEM_NAME = ${CMAKE_SYSTEM_NAME}")
|
||||
message (VERBOSE "CMAKE_SYSTEM_VERSION = ${CMAKE_SYSTEM_VERSION}")
|
||||
message (VERBOSE "CMAKE_SYSTEM_PROCESSOR = ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
message (STATUS "CMAKE_CXX_COMPILER = ${CMAKE_CXX_COMPILER}")
|
||||
message (STATUS "CMAKE_CXX_COMPILER_ID = ${CMAKE_CXX_COMPILER_ID}")
|
||||
|
||||
|
||||
###########################################################################
|
||||
@@ -44,9 +42,7 @@ if (CMAKE_COMPILER_IS_GNUCC)
|
||||
execute_process (COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
|
||||
OUTPUT_VARIABLE GCC_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if (VERBOSE)
|
||||
message (STATUS "Using gcc ${GCC_VERSION} as the compiler")
|
||||
endif ()
|
||||
message (VERBOSE "Using gcc ${GCC_VERSION} as the compiler")
|
||||
else ()
|
||||
set (GCC_VERSION 0)
|
||||
endif ()
|
||||
@@ -63,26 +59,18 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER MATCHES "[Cc]lan
|
||||
set (CMAKE_CXX_COMPILER_ID "AppleClang")
|
||||
set (CMAKE_COMPILER_IS_APPLECLANG 1)
|
||||
string (REGEX REPLACE ".* version ([0-9]+\\.[0-9]+).*" "\\1" APPLECLANG_VERSION_STRING ${clang_full_version_string})
|
||||
if (VERBOSE)
|
||||
message (STATUS "The compiler is Clang: ${CMAKE_CXX_COMPILER_ID} version ${APPLECLANG_VERSION_STRING}")
|
||||
endif ()
|
||||
message (VERBOSE "The compiler is Clang: ${CMAKE_CXX_COMPILER_ID} version ${APPLECLANG_VERSION_STRING}")
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "IntelLLVM")
|
||||
set (CMAKE_COMPILER_IS_INTELCLANG 1)
|
||||
string (REGEX MATCH "[0-9]+(\\.[0-9]+)+" INTELCLANG_VERSION_STRING ${clang_full_version_string})
|
||||
if (VERBOSE)
|
||||
message (STATUS "The compiler is Intel Clang: ${CMAKE_CXX_COMPILER_ID} version ${INTELCLANG_VERSION_STRING}")
|
||||
endif ()
|
||||
message (VERBOSE "The compiler is Intel Clang: ${CMAKE_CXX_COMPILER_ID} version ${INTELCLANG_VERSION_STRING}")
|
||||
else ()
|
||||
string (REGEX REPLACE ".* version ([0-9]+\\.[0-9]+).*" "\\1" CLANG_VERSION_STRING ${clang_full_version_string})
|
||||
if (VERBOSE)
|
||||
message (STATUS "The compiler is Clang: ${CMAKE_CXX_COMPILER_ID} version ${CLANG_VERSION_STRING}")
|
||||
endif ()
|
||||
message (VERBOSE "The compiler is Clang: ${CMAKE_CXX_COMPILER_ID} version ${CLANG_VERSION_STRING}")
|
||||
endif ()
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Intel")
|
||||
set (CMAKE_COMPILER_IS_INTEL 1)
|
||||
if (VERBOSE)
|
||||
message (STATUS "Using Intel as the compiler")
|
||||
endif ()
|
||||
message (VERBOSE "Using Intel as the compiler")
|
||||
endif ()
|
||||
|
||||
|
||||
@@ -121,11 +109,11 @@ endif ()
|
||||
# give more fine-grained control for hiding symbols, because sometimes
|
||||
# dependent libraries may not be well behaved and need extra hiding.
|
||||
#
|
||||
set (CXX_VISIBILITY_PRESET "hidden" CACHE STRING "Symbol visibility (hidden or default")
|
||||
set (CMAKE_CXX_VISIBILITY_PRESET "hidden" CACHE STRING "Symbol visibility (hidden or default")
|
||||
option (VISIBILITY_INLINES_HIDDEN "Hide symbol visibility of inline functions" ON)
|
||||
set (VISIBILITY_MAP_FILE "${PROJECT_SOURCE_DIR}/src/build-scripts/hidesymbols.map" CACHE FILEPATH "Visibility map file")
|
||||
set (C_VISIBILITY_PRESET ${CXX_VISIBILITY_PRESET})
|
||||
if (${CXX_VISIBILITY_PRESET} STREQUAL "hidden" AND VISIBILITY_MAP_FILE AND
|
||||
set (CMAKE_C_VISIBILITY_PRESET ${CMAKE_CXX_VISIBILITY_PRESET})
|
||||
if (${CMAKE_CXX_VISIBILITY_PRESET} STREQUAL "hidden" AND VISIBILITY_MAP_FILE AND
|
||||
(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG) AND
|
||||
(CMAKE_SYSTEM_NAME MATCHES "Linux|kFreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "GNU"))
|
||||
# Linux/FreeBSD/Hurd: also hide all the symbols of dependent libraries
|
||||
@@ -165,6 +153,7 @@ if (CMAKE_COMPILER_IS_CLANG OR CMAKE_COMPILER_IS_APPLECLANG)
|
||||
# Suppress warnings about our strategic use of bitwise operations in place
|
||||
# of logical operators to produce branchless code in some places.
|
||||
if (CLANG_VERSION_STRING VERSION_GREATER_EQUAL 14.0
|
||||
OR APPLECLANG_VERSION_STRING VERSION_GREATER_EQUAL 14.0
|
||||
OR INTELCLANG_VERSION_STRING VERSION_GREATER_EQUAL 14.0)
|
||||
add_compile_options ("-Wno-bitwise-instead-of-logical")
|
||||
endif ()
|
||||
@@ -313,9 +302,7 @@ if (NOT USE_SIMD STREQUAL "")
|
||||
else ()
|
||||
string (REPLACE "," ";" SIMD_FEATURE_LIST ${USE_SIMD})
|
||||
foreach (feature ${SIMD_FEATURE_LIST})
|
||||
if (VERBOSE)
|
||||
message (STATUS "SIMD feature: ${feature}")
|
||||
endif ()
|
||||
message (VERBOSE "SIMD feature: ${feature}")
|
||||
if (MSVC OR CMAKE_COMPILER_IS_INTEL)
|
||||
set (SIMD_COMPILE_FLAGS ${SIMD_COMPILE_FLAGS} "/arch:${feature}")
|
||||
else ()
|
||||
@@ -342,17 +329,17 @@ set (USE_BATCHED "" CACHE STRING "Build batched SIMD shader execution for (0, b8
|
||||
option (VEC_REPORT "Enable compiler's reporting system for vectorization" OFF)
|
||||
set (BATCHED_SUPPORT_DEFINES "")
|
||||
set (BATCHED_TARGET_LIBS "")
|
||||
set (BUILD_BATCHED False)
|
||||
set (OSL_BUILD_BATCHED 0)
|
||||
if (NOT USE_BATCHED STREQUAL "")
|
||||
message (STATUS "Compiling with batched SIMD targets ${USE_BATCHED}")
|
||||
if (NOT USE_BATCHED STREQUAL "0")
|
||||
set (BUILD_BATCHED 1)
|
||||
set (OSL_BUILD_BATCHED 1)
|
||||
string (REPLACE "," ";" BATCHED_TARGET_LIST ${USE_BATCHED})
|
||||
foreach (batched_target ${BATCHED_TARGET_LIST})
|
||||
if (VERBOSE)
|
||||
message (STATUS "BATCHED target: ${batched_target}")
|
||||
endif ()
|
||||
set (BATCHED_SUPPORT_DEFINES ${BATCHED_SUPPORT_DEFINES} "__OSL_SUPPORTS_${batched_target}")
|
||||
list (APPEND BATCHED_SUPPORT_DEFINES "__OSL_SUPPORTS_${batched_target}")
|
||||
endforeach()
|
||||
else ()
|
||||
message (STATUS "Compiling with NO batched SIMD targets, USE_BATCHED=0")
|
||||
@@ -422,7 +409,7 @@ if (CLANG_TIDY)
|
||||
find_program(CLANG_TIDY_EXE NAMES "clang-tidy"
|
||||
DOC "Path to clang-tidy executable")
|
||||
message (STATUS "CLANG_TIDY_EXE ${CLANG_TIDY_EXE}")
|
||||
if (CLANG_TIDY_EXE AND NOT ${CMAKE_VERSION} VERSION_LESS 3.6)
|
||||
if (CLANG_TIDY_EXE)
|
||||
set (CMAKE_CXX_CLANG_TIDY
|
||||
"${CLANG_TIDY_EXE}"
|
||||
)
|
||||
@@ -524,9 +511,7 @@ else ()
|
||||
set (SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}
|
||||
CACHE STRING "Set the SO version for dynamic libraries")
|
||||
endif ()
|
||||
if (VERBOSE)
|
||||
message(STATUS "Setting SOVERSION to: ${SOVERSION}")
|
||||
endif ()
|
||||
message(VERBOSE "Setting SOVERSION to: ${SOVERSION}")
|
||||
|
||||
|
||||
###########################################################################
|
||||
@@ -588,9 +573,7 @@ else ()
|
||||
# add the automatically determined parts of the RPATH that
|
||||
# point to directories outside the build tree to the install RPATH
|
||||
set (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
if (VERBOSE)
|
||||
message (STATUS "CMAKE_INSTALL_RPATH = ${CMAKE_INSTALL_RPATH}")
|
||||
endif ()
|
||||
message (VERBOSE "CMAKE_INSTALL_RPATH = ${CMAKE_INSTALL_RPATH}")
|
||||
endif ()
|
||||
# OSL considerations because we run oslc in the course of building:
|
||||
# Use (i.e. don't skip) the full RPATH for the build tree
|
||||
|
||||
@@ -3,6 +3,16 @@
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
set ($OSL_EXTRA_NVCC_ARGS "" CACHE STRING "Custom args passed to nvcc when compiling CUDA code")
|
||||
set (CUDA_OPT_FLAG_NVCC "-O3" CACHE STRING "The optimization level to use when compiling CUDA/C++ files with nvcc")
|
||||
set (CUDA_OPT_FLAG_CLANG "-O3" CACHE STRING "The optimization level to use when compiling CUDA/C++ files with clang")
|
||||
|
||||
# FTZ is enabled by default since it offers the best performance,
|
||||
# but it may be disabled to debug numerical issues, to better match
|
||||
# host behavior, etc.
|
||||
set (CUDA_NO_FTZ OFF CACHE BOOL "Do not enable force-to-zero when compiling for CUDA")
|
||||
if (CUDA_NO_FTZ)
|
||||
add_definitions ("-DOSL_CUDA_NO_FTZ=1")
|
||||
endif ()
|
||||
|
||||
# Compile a CUDA file to PTX using NVCC
|
||||
function ( NVCC_COMPILE cuda_src extra_headers ptx_generated extra_nvcc_args )
|
||||
@@ -21,6 +31,10 @@ function ( NVCC_COMPILE cuda_src extra_headers ptx_generated extra_nvcc_args )
|
||||
list (TRANSFORM OpenImageIO_INCLUDES PREPEND -I
|
||||
OUTPUT_VARIABLE ALL_OpenImageIO_INCLUDES)
|
||||
|
||||
if (NOT CUDA_NO_FTZ)
|
||||
set (NVCC_FTZ_FLAG "--ftz=true")
|
||||
endif ()
|
||||
|
||||
add_custom_command ( OUTPUT ${cuda_ptx}
|
||||
COMMAND ${CUDA_NVCC_EXECUTABLE}
|
||||
"-I${OPTIX_INCLUDES}"
|
||||
@@ -37,7 +51,7 @@ function ( NVCC_COMPILE cuda_src extra_headers ptx_generated extra_nvcc_args )
|
||||
${LLVM_COMPILE_FLAGS}
|
||||
-DOSL_USE_FAST_MATH=1
|
||||
-m64 -arch ${CUDA_TARGET_ARCH} -ptx
|
||||
--std=c++14 -dc -O3 --use_fast_math --expt-relaxed-constexpr
|
||||
--std=c++14 -dc --use_fast_math ${CUDA_OPT_FLAG_NVCC} ${NVCC_FTZ_FLAG} --expt-relaxed-constexpr
|
||||
${extra_nvcc_args}
|
||||
${OSL_EXTRA_NVCC_ARGS}
|
||||
${cuda_src} -o ${cuda_ptx}
|
||||
@@ -55,13 +69,11 @@ function ( MAKE_CUDA_BITCODE src suffix generated_bc extra_clang_args )
|
||||
|
||||
# Setup the compile flags
|
||||
get_property (CURRENT_DEFINITIONS DIRECTORY PROPERTY COMPILE_DEFINITIONS)
|
||||
if (VERBOSE)
|
||||
message (STATUS "Current #defines are ${CURRENT_DEFINITIONS}")
|
||||
endif ()
|
||||
message (VERBOSE "Current #defines are ${CURRENT_DEFINITIONS}")
|
||||
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} ${CSTD_FLAGS})
|
||||
|
||||
# Setup the bitcode generator
|
||||
if (NOT LLVM_BC_GENERATOR)
|
||||
@@ -76,9 +88,7 @@ function ( MAKE_CUDA_BITCODE src suffix generated_bc extra_clang_args )
|
||||
if (NOT LLVM_BC_GENERATOR)
|
||||
message (FATAL_ERROR "You must have a valid llvm bitcode generator (clang++) somewhere.")
|
||||
endif ()
|
||||
if (VERBOSE)
|
||||
message (STATUS "Using LLVM_BC_GENERATOR ${LLVM_BC_GENERATOR} to generate bitcode.")
|
||||
endif()
|
||||
message (VERBOSE "Using LLVM_BC_GENERATOR ${LLVM_BC_GENERATOR} to generate bitcode.")
|
||||
|
||||
if (NOT LLVM_AS_TOOL)
|
||||
find_program (LLVM_AS_TOOL NAMES "llvm-as"
|
||||
@@ -94,6 +104,20 @@ function ( MAKE_CUDA_BITCODE src suffix generated_bc extra_clang_args )
|
||||
NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_ENVIRONMENT_PATH)
|
||||
endif ()
|
||||
|
||||
if (NOT LLVM_LLC_TOOL)
|
||||
find_program (LLVM_LLC_TOOL NAMES "llc"
|
||||
PATHS "${LLVM_DIRECTORY}/bin" "${LLVM_DIRECTORY}/tools/llvm"
|
||||
NO_CMAKE_PATH NO_DEFAULT_PATH NO_CMAKE_SYSTEM_PATH
|
||||
NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_ENVIRONMENT_PATH)
|
||||
endif ()
|
||||
|
||||
if (NOT LLVM_OPT_TOOL)
|
||||
find_program (LLVM_OPT_TOOL NAMES "opt"
|
||||
PATHS "${LLVM_DIRECTORY}/bin" "${LLVM_DIRECTORY}/tools/llvm"
|
||||
NO_CMAKE_PATH NO_DEFAULT_PATH NO_CMAKE_SYSTEM_PATH
|
||||
NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_ENVIRONMENT_PATH)
|
||||
endif ()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
# fix compilation error when using MSVC
|
||||
set (CLANG_MSVC_FIX "-DBOOST_CONFIG_REQUIRES_THREADS_HPP")
|
||||
@@ -104,6 +128,26 @@ function ( MAKE_CUDA_BITCODE src suffix generated_bc extra_clang_args )
|
||||
set (CLANG_MSVC_FIX "${CLANG_MSVC_FIX} -Wno-ignored-attributes -Wno-unknown-attributes")
|
||||
endif ()
|
||||
|
||||
if (NOT LLVM_OPAQUE_POINTERS AND ${LLVM_VERSION} VERSION_GREATER_EQUAL 15.0)
|
||||
# Until we fully support opaque pointers, we need to disable
|
||||
# them when using LLVM 15.
|
||||
list (APPEND LLVM_COMPILE_FLAGS -Xclang -no-opaque-pointers)
|
||||
endif ()
|
||||
|
||||
if (NOT CUDA_NO_FTZ)
|
||||
set (CLANG_FTZ_FLAG "-fcuda-flush-denormals-to-zero")
|
||||
endif ()
|
||||
|
||||
if ("${CUDA_VERSION}" VERSION_GREATER_EQUAL "12.0")
|
||||
# The textureReference API was removed in CUDA 12.0, but it's still referenced
|
||||
# in the clang headers, so compilation will fail with 12.0 and newer toolkits
|
||||
# due to the missing definitions.
|
||||
#
|
||||
# We don't actually require any of the clang CUDA texture intrinsics, so we can
|
||||
# side-step the issue by preventing them from being included by the preprocessor.
|
||||
set (CUDA_TEXREF_FIX "-D__CLANG_CUDA_TEXTURE_INTRINSICS_H__")
|
||||
endif()
|
||||
|
||||
list (TRANSFORM IMATH_INCLUDES PREPEND -I
|
||||
OUTPUT_VARIABLE ALL_IMATH_INCLUDES)
|
||||
list (TRANSFORM OPENEXR_INCLUDES PREPEND -I
|
||||
@@ -116,6 +160,7 @@ function ( MAKE_CUDA_BITCODE src suffix generated_bc extra_clang_args )
|
||||
"-I${OPTIX_INCLUDES}"
|
||||
"-I${CUDA_INCLUDES}"
|
||||
"-I${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
"-I${CMAKE_SOURCE_DIR}/src/liboslexec"
|
||||
"-I${CMAKE_BINARY_DIR}/include"
|
||||
"-I${PROJECT_SOURCE_DIR}/src/include"
|
||||
"-I${PROJECT_SOURCE_DIR}/src/cuda_common"
|
||||
@@ -123,11 +168,11 @@ function ( MAKE_CUDA_BITCODE src suffix generated_bc extra_clang_args )
|
||||
${ALL_IMATH_INCLUDES}
|
||||
${ALL_OPENEXR_INCLUDES}
|
||||
"-I${Boost_INCLUDE_DIRS}"
|
||||
${LLVM_COMPILE_FLAGS} ${CUDA_LIB_FLAGS} ${CLANG_MSVC_FIX}
|
||||
${LLVM_COMPILE_FLAGS} ${CUDA_LIB_FLAGS} ${CLANG_MSVC_FIX} ${CUDA_TEXREF_FIX}
|
||||
-D__CUDACC__ -DOSL_COMPILING_TO_BITCODE=1 -DNDEBUG -DOIIO_NO_SSE -D__CUDADEVRT_INTERNAL__
|
||||
--language=cuda --cuda-device-only --cuda-gpu-arch=${CUDA_TARGET_ARCH}
|
||||
-Wno-deprecated-register -Wno-format-security
|
||||
-O3 -fno-math-errno -ffast-math -S -emit-llvm ${extra_clang_args}
|
||||
-fno-math-errno -ffast-math ${CUDA_OPT_FLAG_CLANG} ${CLANG_FTZ_FLAG} -S -emit-llvm ${extra_clang_args}
|
||||
${src} -o ${asm_cuda}
|
||||
COMMAND ${LLVM_AS_TOOL} -f -o ${bc_cuda} ${asm_cuda}
|
||||
DEPENDS ${exec_headers} ${PROJECT_PUBLIC_HEADERS} ${src}
|
||||
@@ -149,3 +194,46 @@ function ( LLVM_COMPILE_CUDA llvm_src headers prefix llvm_bc_cpp_generated extra
|
||||
DEPENDS "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py" ${llvm_src} ${headers} ${llvm_bc}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
endfunction ()
|
||||
|
||||
function ( MAKE_EMBEDDED_CPP symbol_name output_cpp input_file )
|
||||
add_custom_command ( OUTPUT ${output_cpp}
|
||||
COMMAND ${Python_EXECUTABLE} "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py"
|
||||
${input_file} ${output_cpp} "${symbol_name}"
|
||||
|
||||
DEPENDS "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py" ${linked_bc}
|
||||
${input_file} ${exec_headers} ${PROJECT_PUBLIC_HEADERS}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
endfunction ()
|
||||
|
||||
function ( CUDA_SHADEOPS_COMPILE prefix output_bc output_ptx input_srcs headers )
|
||||
set (linked_bc "${CMAKE_CURRENT_BINARY_DIR}/linked_${prefix}.bc")
|
||||
set (linked_ptx "${CMAKE_CURRENT_BINARY_DIR}/${prefix}.ptx")
|
||||
set (${output_bc} ${linked_bc} PARENT_SCOPE )
|
||||
set (${output_ptx} ${linked_ptx} PARENT_SCOPE )
|
||||
|
||||
foreach ( shadeops_src ${input_srcs} )
|
||||
MAKE_CUDA_BITCODE ( ${shadeops_src} "_cuda" shadeops_bc "" )
|
||||
list ( APPEND shadeops_bc_list ${shadeops_bc} )
|
||||
endforeach ()
|
||||
|
||||
if (LLVM_NEW_PASS_MANAGER)
|
||||
# There is no --nvptx-assign-valid-global-names flag for the new
|
||||
# pass manager, but it appears to run this pass by default.
|
||||
string(REPLACE "-O" "O" opt_tool_flags ${CUDA_OPT_FLAG_CLANG})
|
||||
set (opt_tool_flags -passes="default<${opt_tool_flags}>")
|
||||
else()
|
||||
set (opt_tool_flags ${CUDA_OPT_FLAG_CLANG} --nvptx-assign-valid-global-names)
|
||||
endif ()
|
||||
|
||||
# Link all of the individual LLVM bitcode files, and emit PTX for the linked bitcode
|
||||
add_custom_command ( OUTPUT ${linked_bc} ${linked_ptx}
|
||||
COMMAND ${LLVM_LINK_TOOL} ${shadeops_bc_list} -o ${linked_bc}
|
||||
COMMAND ${LLVM_OPT_TOOL} ${opt_tool_flags} ${linked_bc} -o ${linked_bc}
|
||||
COMMAND ${LLVM_LLC_TOOL} --march=nvptx64 -mcpu=${CUDA_TARGET_ARCH} ${linked_bc} -o ${linked_ptx}
|
||||
# This script converts all of the .weak functions defined in the PTX into .visible functions.
|
||||
COMMAND ${Python_EXECUTABLE} "${CMAKE_SOURCE_DIR}/src/build-scripts/process-ptx.py"
|
||||
${linked_ptx} ${linked_ptx}
|
||||
DEPENDS ${shadeops_bc_list} ${exec_headers} ${PROJECT_PUBLIC_HEADERS} ${input_srcs} ${headers}
|
||||
"${CMAKE_SOURCE_DIR}/src/build-scripts/process-ptx.py"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
endfunction ()
|
||||
|
||||
@@ -53,7 +53,9 @@ else ()
|
||||
# cmake output (e.g. boost 1.70.0, cmake <= 3.14). Specifically it fails
|
||||
# to set the expected variables printed below. So until that's fixed
|
||||
# force FindBoost.cmake to use the original brute force path.
|
||||
set (Boost_NO_BOOST_CMAKE ON)
|
||||
if (NOT DEFINED Boost_NO_BOOST_CMAKE)
|
||||
set (Boost_NO_BOOST_CMAKE ON)
|
||||
endif ()
|
||||
checked_find_package (Boost REQUIRED
|
||||
VERSION_MIN 1.55
|
||||
COMPONENTS ${Boost_COMPONENTS}
|
||||
@@ -80,10 +82,10 @@ checked_find_package (ZLIB REQUIRED) # Needed by several packages
|
||||
|
||||
# IlmBase & OpenEXR
|
||||
checked_find_package (OpenEXR REQUIRED
|
||||
VERSION_MIN 2.3
|
||||
RECOMMEND_MIN 2.4
|
||||
VERSION_MIN 2.4
|
||||
RECOMMEND_MIN 2.5
|
||||
RECOMMEND_MIN_REASON
|
||||
"Even extremely critical patches are no longer supplied to < 2.4"
|
||||
"Even extremely critical patches are no longer supplied to < 2.5"
|
||||
PRINT IMATH_INCLUDES
|
||||
)
|
||||
# Force Imath includes to be before everything else to ensure that we have
|
||||
@@ -105,7 +107,7 @@ endif ()
|
||||
|
||||
# OpenImageIO
|
||||
checked_find_package (OpenImageIO REQUIRED
|
||||
VERSION_MIN 2.3.17
|
||||
VERSION_MIN 2.4
|
||||
DEFINITIONS -DOIIO_HIDE_FORMAT=1)
|
||||
|
||||
checked_find_package (pugixml REQUIRED
|
||||
@@ -115,6 +117,7 @@ checked_find_package (pugixml REQUIRED
|
||||
# LLVM library setup
|
||||
checked_find_package (LLVM REQUIRED
|
||||
VERSION_MIN 9.0
|
||||
VERSION_MAX 17.9
|
||||
PRINT LLVM_SYSTEM_LIBRARIES CLANG_LIBRARIES)
|
||||
# ensure include directory is added (in case of non-standard locations
|
||||
include_directories (BEFORE SYSTEM "${LLVM_INCLUDES}")
|
||||
@@ -144,6 +147,35 @@ if (LLVM_VERSION VERSION_GREATER_EQUAL 15.0
|
||||
"If you are using LLVM 15 or higher, you should also use clang version "
|
||||
"15 or higher, or you may get build errors.${ColorReset}\n")
|
||||
endif ()
|
||||
if (LLVM_VERSION VERSION_GREATER_EQUAL 16.0)
|
||||
if (CMAKE_CXX_STANDARD VERSION_LESS 17)
|
||||
message (WARNING "${ColorYellow}LLVM 16+ requires C++17 or higher. "
|
||||
"Please set CMAKE_CXX_STANDARD to 17 or higher.${ColorReset}\n")
|
||||
endif ()
|
||||
if (CMAKE_COMPILER_IS_GNUCC AND (GCC_VERSION VERSION_LESS 7.0))
|
||||
message (WARNING "${ColorYellow}LLVM 16+ requires gcc 7.0 or higher.${ColorReset}\n")
|
||||
endif ()
|
||||
if (CMAKE_COMPILER_IS_CLANG AND (CLANG_VERSION_STRING VERSION_LESS 5.0))
|
||||
message (WARNING "${ColorYellow}LLVM 16+ requires clang 5.0 or higher.${ColorReset}\n")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Use opaque pointers starting with LLVM 16
|
||||
if (${LLVM_VERSION} VERSION_GREATER_EQUAL 16.0)
|
||||
set(LLVM_OPAQUE_POINTERS ON)
|
||||
add_definitions (-DOSL_LLVM_OPAQUE_POINTERS)
|
||||
else()
|
||||
set(LLVM_OPAQUE_POINTERS OFF)
|
||||
endif()
|
||||
|
||||
# Enable new pass manager for LLVM 16+
|
||||
if (${LLVM_VERSION} VERSION_GREATER_EQUAL 16.0)
|
||||
set(LLVM_NEW_PASS_MANAGER ON)
|
||||
add_definitions (-DOSL_LLVM_NEW_PASS_MANAGER)
|
||||
else()
|
||||
set(LLVM_NEW_PASS_MANAGER OFF)
|
||||
endif()
|
||||
|
||||
|
||||
checked_find_package (partio)
|
||||
|
||||
@@ -153,58 +185,64 @@ find_python ()
|
||||
|
||||
|
||||
# Qt -- used for osltoy
|
||||
set (qt5_modules Core Gui Widgets)
|
||||
if (OPENGL_FOUND)
|
||||
list (APPEND qt5_modules OpenGL)
|
||||
endif ()
|
||||
option (USE_QT "Use Qt if found" ON)
|
||||
checked_find_package (Qt5 COMPONENTS ${qt5_modules})
|
||||
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")
|
||||
if (USE_QT)
|
||||
checked_find_package (Qt6 COMPONENTS Core Gui Widgets OpenGLWidgets)
|
||||
if (NOT Qt6_FOUND)
|
||||
checked_find_package (Qt5 COMPONENTS Core Gui Widgets OpenGL)
|
||||
endif ()
|
||||
if (NOT Qt5_FOUND AND NOT Qt6_FOUND AND APPLE)
|
||||
message (STATUS " If you think you installed qt with Homebrew and it still doesn't work,")
|
||||
message (STATUS " try: export PATH=/usr/local/opt/qt/bin:$PATH")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
|
||||
# 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 (OSL_USE_OPTIX)
|
||||
if (USE_LLVM_BITCODE)
|
||||
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 ()
|
||||
if (NOT CUDA_FIND_QUIETLY OR NOT OptiX_FIND_QUIETLY)
|
||||
message (STATUS "CUDA_TOOLKIT_ROOT_DIR = ${CUDA_TOOLKIT_ROOT_DIR}")
|
||||
endif ()
|
||||
|
||||
checked_find_package (CUDA REQUIRED
|
||||
VERSION_MIN 8.0
|
||||
PRINT CUDA_INCLUDES)
|
||||
set (CUDA_INCLUDES ${CUDA_TOOLKIT_ROOT_DIR}/include)
|
||||
include_directories (BEFORE "${CUDA_INCLUDES}")
|
||||
checked_find_package (CUDA REQUIRED
|
||||
VERSION_MIN 9.0
|
||||
RECOMMEND_MIN 11.0
|
||||
RECOMMEND_MIN_REASON
|
||||
"We don't actively test CUDA older than 11"
|
||||
PRINT CUDA_INCLUDES)
|
||||
set (CUDA_INCLUDES ${CUDA_TOOLKIT_ROOT_DIR}/include)
|
||||
include_directories (BEFORE "${CUDA_INCLUDES}")
|
||||
|
||||
STRING (FIND ${LLVM_TARGETS} "NVPTX" nvptx_index)
|
||||
if (NOT ${nvptx_index} GREATER -1)
|
||||
message (FATAL_ERROR "NVPTX target is not available in the provided LLVM build")
|
||||
endif()
|
||||
STRING (FIND ${LLVM_TARGETS} "NVPTX" nvptx_index)
|
||||
if (NOT ${nvptx_index} GREATER -1)
|
||||
message (FATAL_ERROR "NVPTX target is not available in the provided LLVM build")
|
||||
endif()
|
||||
|
||||
set (CUDA_LIB_FLAGS "--cuda-path=${CUDA_TOOLKIT_ROOT_DIR}")
|
||||
set (CUDA_LIB_FLAGS "--cuda-path=${CUDA_TOOLKIT_ROOT_DIR}")
|
||||
|
||||
find_library(cuda_lib NAMES cudart
|
||||
PATHS "${CUDA_TOOLKIT_ROOT_DIR}/lib64" "${CUDA_TOOLKIT_ROOT_DIR}/x64"
|
||||
REQUIRED)
|
||||
set(CUDA_LIBRARIES ${cuda_lib})
|
||||
find_library(cuda_lib NAMES cudart
|
||||
PATHS "${CUDA_TOOLKIT_ROOT_DIR}/lib64" "${CUDA_TOOLKIT_ROOT_DIR}/x64" "${CUDA_TOOLKIT_ROOT_DIR}/lib/x64"
|
||||
REQUIRED)
|
||||
set(CUDA_LIBRARIES ${cuda_lib})
|
||||
|
||||
# testrender & testshade need libnvrtc
|
||||
if ("${CUDA_VERSION}" VERSION_GREATER_EQUAL "10.0")
|
||||
find_library(nvrtc_lib NAMES nvrtc
|
||||
PATHS "${CUDA_TOOLKIT_ROOT_DIR}/lib64" "${CUDA_TOOLKIT_ROOT_DIR}/x64"
|
||||
REQUIRED)
|
||||
set(CUDA_LIBRARIES ${CUDA_LIBRARIES} ${nvrtc_lib})
|
||||
# testrender & testshade need libnvrtc
|
||||
if ("${CUDA_VERSION}" VERSION_GREATER_EQUAL "10.0")
|
||||
find_library(nvrtc_lib NAMES nvrtc
|
||||
PATHS "${CUDA_TOOLKIT_ROOT_DIR}/lib64" "${CUDA_TOOLKIT_ROOT_DIR}/x64" "${CUDA_TOOLKIT_ROOT_DIR}/lib/x64"
|
||||
REQUIRED)
|
||||
set(CUDA_LIBRARIES ${CUDA_LIBRARIES} ${nvrtc_lib})
|
||||
|
||||
set(CUDA_EXTRA_LIBS ${CUDA_EXTRA_LIBS} dl)
|
||||
set(CUDA_EXTRA_LIBS ${CUDA_EXTRA_LIBS} dl)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# OptiX setup
|
||||
if (USE_OPTIX)
|
||||
if (OSL_USE_OPTIX AND OSL_BUILD_TESTS)
|
||||
checked_find_package (OptiX REQUIRED
|
||||
VERSION_MIN 7.0)
|
||||
include_directories (BEFORE "${OPTIX_INCLUDES}")
|
||||
@@ -219,7 +257,6 @@ if (USE_CUDA OR USE_OPTIX)
|
||||
target_compile_definitions (${TARGET} PRIVATE "-DPTX_PATH=\"${OSL_PTX_INSTALL_DIR}\"")
|
||||
target_link_libraries (${TARGET} PRIVATE ${CUDA_LIBRARIES} ${CUDA_EXTRA_LIBS} ${OPTIX_LIBRARIES} ${OPTIX_EXTRA_LIBS})
|
||||
endfunction()
|
||||
|
||||
else ()
|
||||
function (osl_optix_target TARGET)
|
||||
endfunction()
|
||||
|
||||
@@ -38,9 +38,7 @@ if ( FLEX_EXECUTABLE AND BISON_EXECUTABLE )
|
||||
# XXX: This may be excessive now that OSL::pvt::ExtraArg is mangled into the function signature
|
||||
add_definitions(-D${prefix}parse=${PROJ_NAMESPACE_V}_${prefix}parse)
|
||||
|
||||
if (VERBOSE)
|
||||
message (STATUS "FLEX_BISON flex=${flexsrc} bison=${bisonsrc} prefix=${prefix}")
|
||||
endif ()
|
||||
message (VERBOSE "FLEX_BISON flex=${flexsrc} bison=${bisonsrc} prefix=${prefix}")
|
||||
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" )
|
||||
@@ -54,9 +52,7 @@ if ( FLEX_EXECUTABLE AND BISON_EXECUTABLE )
|
||||
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}")
|
||||
endif ()
|
||||
message (VERBOSE "Flex include dir = ${FLEX_INCLUDE_DIR}")
|
||||
include_directories ( ${FLEX_INCLUDE_DIR} )
|
||||
|
||||
# include_directories ( ${CMAKE_CURRENT_BINARY_DIR} )
|
||||
|
||||
@@ -2,28 +2,24 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
# TODO: Use CMAKE_CURRENT_FUNCTION_LIST_DIR in cmake-3.17
|
||||
set(_THIS_MODULE_BASE_DIR "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_cpp extra_clang_args)
|
||||
function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_cpp extra_clang_args include_dirs)
|
||||
|
||||
if (VERBOSE)
|
||||
message (STATUS "EMBED_LLVM_BITCODE_IN_CPP src_list=${src_list}")
|
||||
endif ()
|
||||
message (VERBOSE "EMBED_LLVM_BITCODE_IN_CPP src_list=${src_list}")
|
||||
|
||||
foreach ( src ${src_list} )
|
||||
get_filename_component ( src_we ${src} NAME_WE )
|
||||
set ( src_asm "${CMAKE_CURRENT_BINARY_DIR}/${src_we}${suffix}.s" )
|
||||
set ( src_bc "${CMAKE_CURRENT_BINARY_DIR}/${src_we}${suffix}.bc" )
|
||||
if (VERBOSE)
|
||||
message (STATUS "EMBED_LLVM_BITCODE_IN_CPP in=${src}")
|
||||
message (STATUS "EMBED_LLVM_BITCODE_IN_CPP asm=${src_asm}")
|
||||
message (STATUS "EMBED_LLVM_BITCODE_IN_CPP bc=${src_bc}")
|
||||
endif ()
|
||||
message (VERBOSE "EMBED_LLVM_BITCODE_IN_CPP in=${src}")
|
||||
message (VERBOSE "EMBED_LLVM_BITCODE_IN_CPP asm=${src_asm}")
|
||||
message (VERBOSE "EMBED_LLVM_BITCODE_IN_CPP bc=${src_bc}")
|
||||
list ( APPEND src_bc_list ${src_bc} )
|
||||
|
||||
get_property (CURRENT_DEFINITIONS DIRECTORY PROPERTY COMPILE_DEFINITIONS)
|
||||
if (VERBOSE)
|
||||
message (STATUS "Current #defines are ${CURRENT_DEFINITIONS}")
|
||||
endif ()
|
||||
message (VERBOSE "Current #defines are ${CURRENT_DEFINITIONS}")
|
||||
foreach (def ${CURRENT_DEFINITIONS})
|
||||
set (LLVM_COMPILE_FLAGS ${LLVM_COMPILE_FLAGS} "-D${def}")
|
||||
endforeach()
|
||||
@@ -42,9 +38,7 @@ function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_
|
||||
if (NOT LLVM_BC_GENERATOR)
|
||||
message (FATAL_ERROR "You must have a valid llvm bitcode generator (clang++) somewhere.")
|
||||
endif ()
|
||||
if (VERBOSE)
|
||||
message (STATUS "Using LLVM_BC_GENERATOR ${LLVM_BC_GENERATOR} to generate bitcode.")
|
||||
endif()
|
||||
message (VERBOSE "Using LLVM_BC_GENERATOR ${LLVM_BC_GENERATOR} to generate bitcode.")
|
||||
|
||||
if (NOT LLVM_AS_TOOL)
|
||||
find_program (LLVM_AS_TOOL NAMES "llvm-as"
|
||||
@@ -75,14 +69,10 @@ function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_
|
||||
# endif ()
|
||||
#endif ()
|
||||
|
||||
list (TRANSFORM IMATH_INCLUDES PREPEND -I
|
||||
OUTPUT_VARIABLE ALL_IMATH_INCLUDES)
|
||||
list (TRANSFORM OPENEXR_INCLUDES PREPEND -I
|
||||
OUTPUT_VARIABLE ALL_OPENEXR_INCLUDES)
|
||||
list (TRANSFORM OpenImageIO_INCLUDES PREPEND -I
|
||||
OUTPUT_VARIABLE ALL_OpenImageIO_INCLUDES)
|
||||
list (TRANSFORM include_dirs PREPEND -I
|
||||
OUTPUT_VARIABLE ALL_INCLUDE_DIRS)
|
||||
|
||||
if (${LLVM_VERSION} VERSION_GREATER_EQUAL 15.0)
|
||||
if (NOT LLVM_OPAQUE_POINTERS AND ${LLVM_VERSION} VERSION_GREATER_EQUAL 15.0)
|
||||
# Until we fully support opaque pointers, we need to disable
|
||||
# them when using LLVM 15.
|
||||
list (APPEND LLVM_COMPILE_FLAGS -Xclang -no-opaque-pointers)
|
||||
@@ -93,13 +83,7 @@ function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_
|
||||
add_custom_command ( OUTPUT ${src_bc}
|
||||
COMMAND ${LLVM_BC_GENERATOR}
|
||||
${LLVM_COMPILE_FLAGS}
|
||||
"-I${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
"-I${CMAKE_SOURCE_DIR}/src/include"
|
||||
"-I${CMAKE_BINARY_DIR}/include"
|
||||
${ALL_OpenImageIO_INCLUDES}
|
||||
${ALL_IMATH_INCLUDES}
|
||||
#"-isystem ${Boost_INCLUDE_DIRS}" #Does not pick up usr installed boost/thread/tss.hpp for oslexec_pvt.h
|
||||
"-I${Boost_INCLUDE_DIRS}"
|
||||
${ALL_INCLUDE_DIRS}
|
||||
-DOSL_COMPILING_TO_BITCODE=1
|
||||
-Wno-deprecated-register
|
||||
# the following 2 warnings can be restored when all 3rd parties have fixed their export macros
|
||||
@@ -114,12 +98,9 @@ function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
endforeach ()
|
||||
|
||||
|
||||
if (VERBOSE)
|
||||
message ( STATUS "^^^^^^^^^^^^^^^^^^^^^^^^^^" )
|
||||
message ( STATUS "src_bc_list: ${src_bc_list} ")
|
||||
message ( STATUS "^^^^^^^^^^^^^^^^^^^^^^^^^^" )
|
||||
endif()
|
||||
message (VERBOSE "^^^^^^^^^^^^^^^^^^^^^^^^^^" )
|
||||
message (VERBOSE "src_bc_list: ${src_bc_list} ")
|
||||
message (VERBOSE "^^^^^^^^^^^^^^^^^^^^^^^^^^" )
|
||||
|
||||
# Link all of the individual LLVM bitcode files
|
||||
set ( linked_src_bc "${CMAKE_CURRENT_BINARY_DIR}/${output_name}.bc" )
|
||||
@@ -131,9 +112,9 @@ function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_
|
||||
# Serialize the linked bitcode into a CPP file
|
||||
set ( src_bc_cpp "${CMAKE_CURRENT_BINARY_DIR}/${output_name}.bc.cpp" )
|
||||
add_custom_command ( OUTPUT ${src_bc_cpp}
|
||||
COMMAND ${Python_EXECUTABLE} "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py"
|
||||
COMMAND ${Python_EXECUTABLE} "${_THIS_MODULE_BASE_DIR}/../build-scripts/serialize-bc.py"
|
||||
${linked_src_bc} ${src_bc_cpp} ${output_name}
|
||||
DEPENDS "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py" ${linked_src_bc}
|
||||
DEPENDS "${_THIS_MODULE_BASE_DIR}/../build-scripts/serialize-bc.py" ${linked_src_bc}
|
||||
${exec_headers} ${PROJECT_PUBLIC_HEADERS}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
|
||||
|
||||
@@ -23,7 +23,13 @@
|
||||
|
||||
# try to find llvm-config, with a specific version if specified
|
||||
if (LLVM_DIRECTORY)
|
||||
set (LLVM_CONFIG_PATH_HINTS "${LLVM_DIRECTORY}/bin")
|
||||
list (APPEND LLVM_CONFIG_PATH_HINTS "${LLVM_DIRECTORY}/bin")
|
||||
endif ()
|
||||
if (LLVM_ROOT)
|
||||
list (APPEND LLVM_CONFIG_PATH_HINTS "${LLVM_ROOT}/bin")
|
||||
endif ()
|
||||
if (DEFINED ENV{LLVM_ROOT})
|
||||
list (APPEND LLVM_CONFIG_PATH_HINTS "$ENV{LLVM_ROOT}/bin")
|
||||
endif ()
|
||||
list (APPEND LLVM_CONFIG_PATH_HINTS
|
||||
"/usr/local/opt/llvm/${LLVM_VERSION}/bin/"
|
||||
@@ -120,8 +126,9 @@ if (LLVM_VERSION VERSION_GREATER_EQUAL 9.0 AND (LLVM_SHARED_MODE STREQUAL "share
|
||||
endif ()
|
||||
|
||||
foreach (COMPONENT clangFrontend clangDriver clangSerialization
|
||||
clangParse clangSema clangAnalysis clangAST clangBasic
|
||||
clangEdit clangLex)
|
||||
clangParse clangSema clangAnalysis clangAST
|
||||
clangASTMatchers clangBasic clangEdit clangLex
|
||||
clangSupport)
|
||||
find_library ( _CLANG_${COMPONENT}_LIBRARY
|
||||
NAMES ${COMPONENT}
|
||||
PATHS ${LLVM_LIB_DIR})
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# I'm afraid this is a mess, due to needing to support a wide range of
|
||||
# OpenEXR versions.
|
||||
#
|
||||
# For OpenEXR & Imath 3.0, this will establish the following imported
|
||||
# For OpenEXR & Imath 3.x, this will establish the following imported
|
||||
# targets:
|
||||
#
|
||||
# Imath::Imath
|
||||
@@ -24,14 +24,12 @@
|
||||
# IlmBase::IlmThread
|
||||
# OpenEXR::IlmImf
|
||||
#
|
||||
# For all versions -- but for OpenEXR < 2.4 the only thing this sets --
|
||||
# are the following CMake variables:
|
||||
# For all version, the following CMake variables:
|
||||
#
|
||||
# OPENEXR_FOUND true, if found
|
||||
# OPENEXR_INCLUDES directory where OpenEXR headers are found
|
||||
# OPENEXR_LIBRARIES libraries for OpenEXR + IlmBase
|
||||
# OPENEXR_VERSION OpenEXR version (accurate for >= 2.0.0,
|
||||
# otherwise will just guess 1.6.1)
|
||||
# OPENEXR_VERSION OpenEXR version
|
||||
# IMATH_INCLUDES directory where Imath headers are found
|
||||
# ILMBASE_INCLUDES directory where IlmBase headers are found
|
||||
# ILMBASE_LIBRARIES libraries just IlmBase
|
||||
@@ -50,7 +48,7 @@ if (TARGET OpenEXR::OpenEXR AND TARGET Imath::Imath)
|
||||
# OpenEXR 3.x if both of these targets are found
|
||||
set (FOUND_OPENEXR_WITH_CONFIG 1)
|
||||
if (NOT OpenEXR_FIND_QUIETLY)
|
||||
message (STATUS "Found CONFIG for OpenEXR 3 (OPENEXR_VERSION=${OpenEXR_VERSION})")
|
||||
message (STATUS "Found CONFIG for OpenEXR 3 (OpenEXR_VERSION=${OpenEXR_VERSION})")
|
||||
endif ()
|
||||
|
||||
# Mimic old style variables
|
||||
@@ -80,7 +78,7 @@ elseif (TARGET OpenEXR::IlmImf AND TARGET IlmBase::Imath AND
|
||||
# OpenEXR 2.4 or 2.5 with exported config
|
||||
set (FOUND_OPENEXR_WITH_CONFIG 1)
|
||||
if (NOT OpenEXR_FIND_QUIETLY)
|
||||
message (STATUS "Found CONFIG for OpenEXR 2 (OPENEXR_VERSION=${OpenEXR_VERSION})")
|
||||
message (STATUS "Found CONFIG for OpenEXR 2 (OpenEXR_VERSION=${OpenEXR_VERSION})")
|
||||
endif ()
|
||||
|
||||
# Mimic old style variables
|
||||
@@ -111,157 +109,4 @@ elseif (TARGET OpenEXR::IlmImf AND TARGET IlmBase::Imath AND
|
||||
string(REGEX REPLACE "include/OpenEXR$" "include" IMATH_INCLUDES "${IMATH_INCLUDES}")
|
||||
string(REGEX REPLACE "include/OpenEXR$" "include" OPENEXR_INCLUDES "${OPENEXR_INCLUDES}")
|
||||
|
||||
else ()
|
||||
# OpenEXR 2.x older versions without a config or whose configs we don't
|
||||
# trust.
|
||||
|
||||
set (FOUND_OPENEXR_WITH_CONFIG 0)
|
||||
|
||||
# Other standard issue macros
|
||||
include (FindPackageHandleStandardArgs)
|
||||
include (SelectLibraryConfigurations)
|
||||
|
||||
find_package (ZLIB REQUIRED)
|
||||
|
||||
# Link with pthreads if required
|
||||
find_package (Threads)
|
||||
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 AND NOT ILMBASE_ROOT
|
||||
AND NOT DEFINED ENV{Ilmbase_ROOT} AND NOT DEFINED ENV{ILMBASE_ROOT})
|
||||
pkg_check_modules(_ILMBASE QUIET IlmBase>=2.0.0)
|
||||
endif ()
|
||||
if (NOT OpenEXR_ROOT AND NOT OPENEXR_ROOT
|
||||
AND NOT DEFINED ENV{OpenEXR_ROOT} AND NOT DEFINED ENV{OPENEXR_ROOT})
|
||||
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_ROOT}/include.
|
||||
# ILMBASE is needed in case ilmbase an openexr are installed in separate
|
||||
# directories, like NixOS does
|
||||
set (GENERIC_INCLUDE_PATHS
|
||||
${OPENEXR_ROOT}/include
|
||||
$ENV{OPENEXR_ROOT}/include
|
||||
${ILMBASE_ROOT}/include
|
||||
$ENV{ILMBASE_ROOT}/include
|
||||
${_ILMBASE_INCLUDEDIR}
|
||||
${_OPENEXR_INCLUDEDIR}
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
/usr/include/${CMAKE_LIBRARY_ARCHITECTURE}
|
||||
/sw/include
|
||||
/opt/local/include )
|
||||
|
||||
# Find the include file locations.
|
||||
find_path (ILMBASE_INCLUDE_PATH OpenEXR/IlmBaseConfig.h
|
||||
HINTS ${ILMBASE_INCLUDE_DIR} ${OPENEXR_INCLUDE_DIR}
|
||||
${GENERIC_INCLUDE_PATHS} )
|
||||
find_path (OPENEXR_INCLUDE_PATH OpenEXR/OpenEXRConfig.h
|
||||
HINTS ${OPENEXR_INCLUDE_DIR}
|
||||
${GENERIC_INCLUDE_PATHS} )
|
||||
|
||||
# Try to figure out version number
|
||||
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})
|
||||
file(STRINGS "${OPENEXR_INCLUDE_PATH}/OpenEXR/OpenEXRConfig.h" TMP REGEX "^#define OPENEXR_VERSION_MAJOR .*$")
|
||||
string (REGEX MATCHALL "[0-9]+" OPENEXR_VERSION_MAJOR ${TMP})
|
||||
file(STRINGS "${OPENEXR_INCLUDE_PATH}/OpenEXR/OpenEXRConfig.h" TMP REGEX "^#define OPENEXR_VERSION_MINOR .*$")
|
||||
string (REGEX MATCHALL "[0-9]+" OPENEXR_VERSION_MINOR ${TMP})
|
||||
else ()
|
||||
# Assume an old one, predates 2.x that had versions
|
||||
set (OPENEXR_VERSION 1.6.1)
|
||||
set (OPENEXR_MAJOR 1)
|
||||
set (OPENEXR_MINOR 6)
|
||||
endif ()
|
||||
|
||||
|
||||
# List of likely places to find the libraries -- note priority override of
|
||||
# ${OPENEXR_ROOT}/lib.
|
||||
set (GENERIC_LIBRARY_PATHS
|
||||
${OPENEXR_ROOT}/lib
|
||||
${ILMBASE_ROOT}/lib
|
||||
${OPENEXR_INCLUDE_PATH}/../lib
|
||||
${ILMBASE_INCLUDE_PATH}/../lib
|
||||
${_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})
|
||||
if (OpenEXR_USE_STATIC_LIBS)
|
||||
if (WIN32)
|
||||
set (CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
else ()
|
||||
set (CMAKE_FIND_LIBRARY_SUFFIXES .a)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Look for the libraries themselves, for all the components.
|
||||
# This is complicated because the OpenEXR libraries may or may not be
|
||||
# built with version numbers embedded.
|
||||
set (_openexr_components IlmThread IlmImf Imath Iex Half)
|
||||
foreach (COMPONENT ${_openexr_components})
|
||||
string (TOUPPER ${COMPONENT} UPPERCOMPONENT)
|
||||
# First try with the version embedded
|
||||
find_library (OPENEXR_${UPPERCOMPONENT}_LIBRARY
|
||||
NAMES ${COMPONENT}-${OPENEXR_VERSION_MAJOR}_${OPENEXR_VERSION_MINOR}
|
||||
${COMPONENT}
|
||||
${COMPONENT}-${OPENEXR_VERSION_MAJOR}_${OPENEXR_VERSION_MINOR}_d
|
||||
${COMPONENT}_d
|
||||
HINTS ${OPENEXR_LIBRARY_DIR} $ENV{OPENEXR_LIBRARY_DIR}
|
||||
${GENERIC_LIBRARY_PATHS} )
|
||||
endforeach ()
|
||||
|
||||
find_package_handle_standard_args (OpenEXR
|
||||
REQUIRED_VARS ILMBASE_INCLUDE_PATH OPENEXR_INCLUDE_PATH
|
||||
OPENEXR_IMATH_LIBRARY OPENEXR_ILMIMF_LIBRARY
|
||||
OPENEXR_IEX_LIBRARY OPENEXR_HALF_LIBRARY
|
||||
)
|
||||
|
||||
if (OPENEXR_FOUND)
|
||||
set (OpenEXR_VERSION ${OPENEXR_VERSION})
|
||||
set (ILMBASE_FOUND TRUE)
|
||||
set (ILMBASE_INCLUDES ${ILMBASE_INCLUDE_PATH})
|
||||
set (IMATH_INCLUDES ${ILMBASE_INCLUDE_PATH})
|
||||
set (OPENEXR_INCLUDES ${OPENEXR_INCLUDE_PATH})
|
||||
set (ILMBASE_INCLUDE_DIR ${ILMBASE_INCLUDE_PATH})
|
||||
set (IMATH_INCLUDE_DIR ${ILMBASE_INCLUDE_PATH})
|
||||
set (OPENEXR_INCLUDE_DIR ${OPENEXR_INCLUDE_PATH})
|
||||
set (ILMBASE_LIBRARIES ${OPENEXR_IMATH_LIBRARY} ${OPENEXR_IEX_LIBRARY} ${OPENEXR_HALF_LIBRARY} ${OPENEXR_ILMTHREAD_LIBRARY} ${ILMBASE_PTHREADS} CACHE STRING "The libraries needed to use IlmBase")
|
||||
set (OPENEXR_LIBRARIES ${OPENEXR_ILMIMF_LIBRARY} ${ILMBASE_LIBRARIES} ${ZLIB_LIBRARIES} CACHE STRING "The libraries needed to use OpenEXR")
|
||||
set (FINDOPENEXR_FALLBACK TRUE)
|
||||
endif ()
|
||||
|
||||
mark_as_advanced(
|
||||
OPENEXR_ILMIMF_LIBRARY
|
||||
OPENEXR_IMATH_LIBRARY
|
||||
OPENEXR_IEX_LIBRARY
|
||||
OPENEXR_HALF_LIBRARY
|
||||
OPENEXR_VERSION)
|
||||
|
||||
# Restore the original CMAKE_FIND_LIBRARY_SUFFIXES
|
||||
set (CMAKE_FIND_LIBRARY_SUFFIXES ${_openexr_orig_suffixes})
|
||||
|
||||
endif ()
|
||||
|
||||
@@ -13,13 +13,9 @@
|
||||
# Hack! prefer a config if it can be found
|
||||
find_package(partio CONFIG)
|
||||
if (PARTIO_FOUND OR partio_FOUND)
|
||||
if (VERBOSE)
|
||||
message (STATUS "partio found via config")
|
||||
endif ()
|
||||
message (VERBOSE "partio found via config")
|
||||
else ()
|
||||
if (VERBOSE)
|
||||
message (STATUS "partio falling back to FindPartio.cmake")
|
||||
endif ()
|
||||
message (VERBOSE "partio falling back to FindPartio.cmake")
|
||||
|
||||
|
||||
find_path (PARTIO_INCLUDE_DIR NAMES Partio.h)
|
||||
|
||||
@@ -16,7 +16,7 @@ find_package (pugixml CONFIG)
|
||||
if (TARGET pugixml::pugixml)
|
||||
# New pugixml (>= 1.11) has nice config files we can rely on and makes a
|
||||
# pugixml::pugixml target.
|
||||
message (STATUS "Found CONFIG for pugixml (>=1.11)")
|
||||
message (VERBOSE "Found CONFIG for pugixml (>=1.11)")
|
||||
|
||||
set (PUGIXML_FOUND true)
|
||||
set (pugixml_FOUND true)
|
||||
|
||||
@@ -20,12 +20,9 @@ macro (find_python)
|
||||
|
||||
# Attempt to find the desired version, but fall back to other
|
||||
# additional versions.
|
||||
unset (_req)
|
||||
if (USE_PYTHON)
|
||||
set (_req REQUIRED)
|
||||
if (PYTHON_VERSION)
|
||||
list (APPEND _req EXACT)
|
||||
endif ()
|
||||
set (_req REQUIRED)
|
||||
if (PYTHON_VERSION)
|
||||
list (APPEND _req EXACT)
|
||||
endif ()
|
||||
checked_find_package (Python ${PYTHON_VERSION}
|
||||
${_req}
|
||||
@@ -46,11 +43,9 @@ macro (find_python)
|
||||
if (NOT DEFINED PYTHON_SITE_DIR)
|
||||
set (PYTHON_SITE_DIR "${CMAKE_INSTALL_LIBDIR}/python${PYTHON_VERSION_FOUND}/site-packages")
|
||||
endif ()
|
||||
if (VERBOSE)
|
||||
message (STATUS " Python site packages dir ${PYTHON_SITE_DIR}")
|
||||
message (STATUS " Python to include 'lib' prefix: ${PYLIB_LIB_PREFIX}")
|
||||
message (STATUS " Python to include SO version: ${PYLIB_INCLUDE_SONAME}")
|
||||
endif ()
|
||||
message (VERBOSE " Python site packages dir ${PYTHON_SITE_DIR}")
|
||||
message (VERBOSE " Python to include 'lib' prefix: ${PYLIB_LIB_PREFIX}")
|
||||
message (VERBOSE " Python to include SO version: ${PYLIB_INCLUDE_SONAME}")
|
||||
endmacro()
|
||||
|
||||
|
||||
@@ -98,9 +93,7 @@ macro (setup_python_module)
|
||||
endif ()
|
||||
|
||||
if (PYLIB_INCLUDE_SONAME)
|
||||
if (VERBOSE)
|
||||
message(STATUS "Setting Py${lib_MODULE} SOVERSION to: ${SOVERSION}")
|
||||
endif ()
|
||||
message(VERBOSE "Setting Py${lib_MODULE} SOVERSION to: ${SOVERSION}")
|
||||
set_target_properties(${target_name} PROPERTIES
|
||||
VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
SOVERSION ${SOVERSION} )
|
||||
|
||||
@@ -71,6 +71,10 @@ macro (add_one_testsuite testname testsrcdir)
|
||||
set_tests_properties (${testname} PROPERTIES LABELS render
|
||||
PROCESSORS 4 COST 10 TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
endif ()
|
||||
# For debug builds, render tests are very slow, so give them a longer timeout
|
||||
if (${testname} MATCHES "render-" AND ${CMAKE_BUILD_TYPE} STREQUAL Debug)
|
||||
set_tests_properties (${testname} PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
endif ()
|
||||
# Some labeling for fun
|
||||
if (${testname} MATCHES "^texture")
|
||||
set_tests_properties (${testname} PROPERTIES LABELS texture
|
||||
@@ -139,14 +143,22 @@ macro ( TESTSUITE )
|
||||
add_one_testsuite ("${_testname}.opt" "${_testsrcdir}"
|
||||
ENV TESTSHADE_OPT=2 )
|
||||
endif ()
|
||||
if (_testname MATCHES "render-" AND ${CMAKE_BUILD_TYPE} STREQUAL Debug)
|
||||
set_tests_properties (${_testname} PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
# Run the same test again with aggressive -O2 runtime
|
||||
# optimization, triggered by setting TESTSHADE_OPT env variable.
|
||||
# Skip OptiX-only tests and those with a NOOPTIMIZE marker file.
|
||||
if (NOT _testname MATCHES "optix"
|
||||
AND NOT EXISTS "${_testsrcdir}/NOSCALAR"
|
||||
AND NOT EXISTS "${_testsrcdir}/BATCHED_REGRESSION"
|
||||
AND NOT EXISTS "${_testsrcdir}/NOOPTIMIZE"
|
||||
AND NOT EXISTS "${_testsrcdir}/NORSBITCODE")
|
||||
add_one_testsuite ("${_testname}.opt.rs_bitcode" "${_testsrcdir}"
|
||||
ENV TESTSHADE_OPT=2 TESTSHADE_RS_BITCODE=1)
|
||||
endif ()
|
||||
# When building for OptiX support, also run it in OptiX mode
|
||||
# if there is an OPTIX marker file in the directory.
|
||||
# If an environment variable $TESTSUITE_OPTIX is nonzero, then
|
||||
# run all tests with OptiX, even if there's no OPTIX marker.
|
||||
if (USE_OPTIX
|
||||
if (OSL_USE_OPTIX
|
||||
AND (EXISTS "${_testsrcdir}/OPTIX" OR test_all_optix OR _testname MATCHES "optix")
|
||||
AND NOT EXISTS "${_testsrcdir}/NOOPTIX"
|
||||
AND NOT EXISTS "${_testsrcdir}/NOOPTIX-FIXME"
|
||||
@@ -159,9 +171,14 @@ macro ( TESTSUITE )
|
||||
# and optimized
|
||||
add_one_testsuite ("${_testname}.optix.opt" "${_testsrcdir}"
|
||||
ENV TESTSHADE_OPT=2 TESTSHADE_OPTIX=1 )
|
||||
if (NOT EXISTS "${_testsrcdir}/NOFUSED")
|
||||
# and fused
|
||||
add_one_testsuite ("${_testname}.optix.fused" "${_testsrcdir}"
|
||||
ENV TESTSHADE_OPT=2 TESTSHADE_OPTIX=1 TESTSHADE_FUSED=1 )
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if (BUILD_BATCHED)
|
||||
if (OSL_BUILD_BATCHED)
|
||||
# When building for Batched support, also run it in Batched mode
|
||||
# if there is an BATCHED marker file in the directory.
|
||||
# If an environment variable $TESTSUITE_BATCHED is nonzero, then
|
||||
@@ -219,9 +236,7 @@ macro ( TESTSUITE )
|
||||
endif ()
|
||||
|
||||
endforeach ()
|
||||
if (VERBOSE)
|
||||
message (STATUS "Added tests: ${ALL_TEST_LIST}")
|
||||
endif ()
|
||||
message (VERBOSE "Added tests: ${ALL_TEST_LIST}")
|
||||
endmacro ()
|
||||
|
||||
macro (osl_add_all_tests)
|
||||
@@ -236,8 +251,9 @@ macro (osl_add_all_tests)
|
||||
bug-array-heapoffsets bug-locallifetime bug-outputinit
|
||||
bug-param-duplicate bug-peep bug-return
|
||||
calculatenormal-reg
|
||||
cellnoise closure closure-array color color-reg colorspace comparison
|
||||
complement-reg compile-buffer compassign-reg
|
||||
cellnoise closure closure-array closure-layered closure-parameters closure-zero closure-conditional
|
||||
color color-reg colorspace comparison
|
||||
complement-reg compile-buffer compassign-bool compassign-reg
|
||||
component-range
|
||||
control-flow-reg connect-components
|
||||
const-array-params const-array-fill
|
||||
@@ -252,10 +268,11 @@ macro (osl_add_all_tests)
|
||||
for-reg format-reg fprintf
|
||||
function-earlyreturn function-simple function-outputelem
|
||||
function-overloads function-redef
|
||||
geomath getattribute-camera getattribute-shader
|
||||
geomath getattribute-camera getattribute-shader getattribute-shading
|
||||
getsymbol-nonheap gettextureinfo gettextureinfo-reg
|
||||
gettextureinfo-udim gettextureinfo-udim-reg
|
||||
globals-needed
|
||||
group-outputs groupstring
|
||||
group-outputs groupdata-opt groupstring
|
||||
hash hashnoise hex hyperb
|
||||
ieee_fp ieee_fp-reg if if-reg incdec initlist
|
||||
initops initops-instance-clash
|
||||
@@ -297,6 +314,7 @@ macro (osl_add_all_tests)
|
||||
oslc-err-struct-dup oslc-err-struct-print
|
||||
oslc-err-type-as-variable
|
||||
oslc-err-unknown-ctr
|
||||
oslc-literalfold
|
||||
oslc-pragma-warnerr
|
||||
oslc-warn-commainit
|
||||
oslc-variadic-macro
|
||||
@@ -308,7 +326,8 @@ macro (osl_add_all_tests)
|
||||
pragma-nowarn
|
||||
printf-reg
|
||||
printf-whole-array
|
||||
raytype raytype-reg raytype-specialized regex-reg reparam
|
||||
raytype raytype-reg raytype-specialized regex-reg
|
||||
reparam reparam-arrays testoptix-reparam
|
||||
render-background render-bumptest
|
||||
render-cornell render-furnace-diffuse
|
||||
render-mx-furnace-burley-diffuse
|
||||
@@ -322,6 +341,7 @@ macro (osl_add_all_tests)
|
||||
render-mx-sheen
|
||||
render-microfacet render-oren-nayar
|
||||
render-uv render-veachmis render-ward
|
||||
render-raytypes
|
||||
select select-reg shaderglobals shortcircuit
|
||||
smoothstep-reg
|
||||
spline spline-reg splineinverse splineinverse-ident
|
||||
@@ -336,6 +356,9 @@ macro (osl_add_all_tests)
|
||||
struct-nested struct-nested-assign struct-nested-deep
|
||||
ternary
|
||||
testshade-expr
|
||||
test-fmt-arrays test-fmt-fileprint
|
||||
test-fmt-cxpf test-fmt-noise test-fmt-matrixcolor
|
||||
test-fmt-stpf test-fmt-errorwarning test-fmt-errorwarning-repeats
|
||||
texture-alpha texture-alpha-derivs
|
||||
texture-blur texture-connected-options
|
||||
texture-derivs texture-environment texture-errormsg
|
||||
@@ -351,17 +374,12 @@ macro (osl_add_all_tests)
|
||||
transform transform-reg transformc transformc-reg trig trig-reg
|
||||
typecast
|
||||
unknown-instruction
|
||||
userdata userdata-passthrough
|
||||
userdata userdata-partial userdata-custom userdata-passthrough
|
||||
vararray-connect vararray-default
|
||||
vararray-deserialize vararray-param
|
||||
vecctr vector vector-reg
|
||||
wavelength_color wavelength_color-reg Werror xml xml-reg )
|
||||
|
||||
# Coordinate-aware gettextureinfo only works for TextureSystem >= 2.3.7
|
||||
if (OpenImageIO_VERSION VERSION_GREATER_EQUAL 2.3.7)
|
||||
TESTSUITE ( gettextureinfo-udim gettextureinfo-udim-reg )
|
||||
endif ()
|
||||
|
||||
# Only run the ocio test if the OIIO we are using has OCIO support
|
||||
if (OpenImageIO_HAS_OpenColorIO)
|
||||
TESTSUITE ( ocio )
|
||||
@@ -383,7 +401,7 @@ macro (osl_add_all_tests)
|
||||
endif()
|
||||
|
||||
# Only run pointcloud tests if Partio is found
|
||||
if (PARTIO_FOUND)
|
||||
if (partio_FOUND)
|
||||
TESTSUITE ( pointcloud pointcloud-fold )
|
||||
endif ()
|
||||
|
||||
@@ -393,7 +411,7 @@ macro (osl_add_all_tests)
|
||||
endif ()
|
||||
|
||||
# Some regression tests have a lot of combinations and may need more time to finish
|
||||
if (BUILD_BATCHED)
|
||||
if (OSL_BUILD_BATCHED)
|
||||
set_tests_properties (arithmetic-reg.regress.batched.opt
|
||||
PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
set_tests_properties (transform-reg.regress.batched.opt
|
||||
|
||||
@@ -38,9 +38,7 @@ macro (docdeep_generate)
|
||||
# ^^ 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 ()
|
||||
message (VERBOSE "docdeep will make '${mdfile}'")
|
||||
set (docdeep_program ${CMAKE_SOURCE_DIR}/src/build-scripts/docdeep.py)
|
||||
add_custom_command (OUTPUT ${mdfile}
|
||||
COMMAND ${Python_EXECUTABLE} ${docdeep_program} -d ${_docdeep_NAME} -s docs.css
|
||||
|
||||
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 16 KiB |
@@ -30,3 +30,35 @@ clean:
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
|
||||
doxygen:
|
||||
echo "make doxygen TBD"
|
||||
doxygen Doxyfile
|
||||
touch doxygen.turd
|
||||
|
||||
doxygen.turd: doxygen
|
||||
|
||||
doxygenclean:
|
||||
cmake -E remove_directory ../../build/doxygen
|
||||
cmake -E remove doxygen.turd
|
||||
cmake -E remove_directory ../../build/sphinx
|
||||
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
SOURCEDIR = .
|
||||
SPHINXBUILDDIR = ../../build/sphinx
|
||||
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
sphinx : Makefile conf.py
|
||||
# @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(SPHINXBUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
$(SPHINXBUILD) -b html "$(SOURCEDIR)" "$(SPHINXBUILDDIR)" $(SPHINXOPTS)
|
||||
|
||||
sphinxpdf : Makefile conf.py
|
||||
# @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(SPHINXBUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
$(SPHINXBUILD) -b latex "$(SOURCEDIR)" "$(SPHINXBUILDDIR)/latex" $(SPHINXOPTS)
|
||||
$(MAKE) -C $(SPHINXBUILDDIR)/latex all-pdf
|
||||
# $(SPHINXBUILD) -b latexpdf "$(SOURCEDIR)" "$(SPHINXBUILDDIR)/latex" $(SPHINXOPTS)
|
||||
|
||||
@@ -0,0 +1,307 @@
|
||||
<!--
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
-->
|
||||
|
||||
|
||||
(chap-bigpicture=)
|
||||
# The Big Picture
|
||||
|
||||
|
||||
This chapter attempts to lay out the major concepts of OSL,
|
||||
define key nomenclature, and sketch out how individual shaders fit
|
||||
together in the context of a renderer as a whole.
|
||||
|
||||
<!--
|
||||
Other than the background material of this chapter, the rest of this
|
||||
specification deals strictly with the language itself. In the future,
|
||||
there will be separate (shorter) documents explaining in detail the use
|
||||
of the language compiler, the renderer-side issues, the library and APIs
|
||||
for how a renderer actually causes shaders to be evaluated, and so on.
|
||||
-->
|
||||
|
||||
#### A shader is code that performs a discrete task
|
||||
|
||||
A shader is a program, with inputs and outputs, that performs a specific
|
||||
task when rendering a scene, such as determining the appearance behavior
|
||||
of a material or light. The program code is written in OSL, the
|
||||
specification of which comprises this document.
|
||||
|
||||
For example, here is a simple `gamma` shader that performs
|
||||
simple gamma correction on is `Cin` input, storing the result
|
||||
in its output `Cout`:
|
||||
|
||||
```{image} Figures/shaderschematic.png
|
||||
:width: 6.0in
|
||||
```
|
||||
|
||||
The shader's inputs and outputs are called *shader parameters*.
|
||||
Parameters have default values, specified in the shader code, but may
|
||||
also be given new values by the renderer at runtime.
|
||||
|
||||
#### Shader instances
|
||||
|
||||
A particular shader may be used many times in a scene, on different
|
||||
objects or as different layers in a shader group. Each separate use of
|
||||
a shader is called a *shader instance*. Although all instances of
|
||||
a shader are comprised of the same program code, each instance may
|
||||
override any or all of its default parameter values with its own set of
|
||||
*instance values*.
|
||||
|
||||
Below is a schematic showing a `gamma` instance with the `gam` parameter
|
||||
overridden with an instance-specific value of `2.2`.
|
||||
|
||||
```{image} Figures/instanceschematic.png
|
||||
:width: 200px
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### Shader groups, layers, and connections
|
||||
|
||||
A *shader group* is an ordered sequence of individual shaders called *layers*
|
||||
that are executed in turn. Output parameters of an earlier-executed layer may
|
||||
be *connected* to an input parameter of a later-executed layer. This connected
|
||||
network of layers is sometimes called a *shader network* or a *shader DAG*
|
||||
(directed acyclic graph). Of course, it is fine for the shader group to
|
||||
consist of a single shader layer.
|
||||
|
||||
Below is a schematic showing how several shader instances may be
|
||||
connected to form a shader group.
|
||||
|
||||
|
||||
|
||||
```{image} Figures/groupschematic.png
|
||||
:width: 6.0in
|
||||
```
|
||||
|
||||
|
||||
|
||||
And here is sample pseudo-code shows how the above network may be assembled
|
||||
using an API in the renderer [^rendererapi]:
|
||||
|
||||
```
|
||||
ShaderGroupBegin ()
|
||||
Shader ("texturemap", /* shader name */
|
||||
"tex1", /* layer name */
|
||||
"string name", "rings.tx") /* instance variable */
|
||||
Shader ("texturemap", "tex2", "string name", "grain.tx")
|
||||
Shader ("gamma", "gam1", "float gam", 2.2)
|
||||
Shader ("gamma", "gam2", "float gam", 1)
|
||||
Shader ("wood", "wood1")
|
||||
ConnectShaders ("tex1", /* layer name A */
|
||||
"Cout", /* an output parameter of A */
|
||||
"gam1", /* layer name B */
|
||||
"Cin") /* Connect this layer of B to A's Cout */
|
||||
ConnectShaders ("tex2", "Cout", "gam2", "Cin")
|
||||
ConnectShaders ("gam1", "Cout", "wood1", "rings")
|
||||
ConnectShaders ("gam2", "Cout", "wood1", "grain")
|
||||
ShaderGroupEnd ()
|
||||
```
|
||||
|
||||
Or, expressed as serialized text (as detailed in Chapter [](chap-shader-groups):
|
||||
|
||||
param string name "rings.tx" ;
|
||||
shader "texturemap" "tex1" ;
|
||||
param string name "grain.tx" ;
|
||||
shader "texturemap" "tex2" ;
|
||||
param float gam 2.2 ;
|
||||
shader "gamma" "gam1" ;
|
||||
param float gam 1.0 ;
|
||||
shader "gamma" "gam2" ;
|
||||
shader "wood" "wood1" ;
|
||||
connect tex1.Cout gam1.Cin ;
|
||||
connect tex2.Cout gam2.Cin ;
|
||||
connect gam1.Cout wood1.rings ;
|
||||
connect gam2.Cout wood1.grain ;
|
||||
|
||||
The rules for which data types may be connected are generally the same as
|
||||
the rules determining which variables may be assigned to each other in OSL
|
||||
source code:
|
||||
|
||||
* `source` and `dest` are the same data type.
|
||||
* `source` and `dest` are both *triples* (`color`, `point`,
|
||||
`vector`, or `normal`), even if they are not the same kind of triple.
|
||||
* `source` is an `int` and `dest` is a `float`.
|
||||
* `source` is a `float` or `int` and `dest` is a
|
||||
*triple* (the scalar value will be replicated for all three components
|
||||
of the triple).
|
||||
* `source` is a single component of an aggregate type (e.g. one
|
||||
channel of a `color`) and `dest` is a `float` (or vice versa).
|
||||
|
||||
#### Geometric primitives
|
||||
|
||||
The *scene* consists of primarily of geometric primitives,
|
||||
light sources, and cameras.
|
||||
|
||||
*Geometric primitives* are shapes such as NURBS, subdivision surfaces,
|
||||
polygons, and curves. The exact set of supported primitives may vary
|
||||
from renderer to renderer.
|
||||
|
||||
Each geometric primitive carries around a set of named *primitive
|
||||
variables* (also sometimes called *interpolated values* or
|
||||
*user data*). Nearly all shape types will have, among their primitive
|
||||
variables, control point positions that, when interpolated, actually
|
||||
designate the shape. Some shapes will also allow the specification of
|
||||
normals or other shape-specific data. Arbitrary user data may also be
|
||||
attached to a shape as primitive variables. Primitive variables may be
|
||||
interpolated in a variety of ways: one constant value per primitive, one
|
||||
constant value per face, or per-vertex values that are interpolated
|
||||
across faces in various ways.
|
||||
|
||||
If a shader input parameter's name and type match the name and type
|
||||
of a primitive variable on the object (and that input parameters is
|
||||
not already explicitly connected to another layer's output), the
|
||||
interpolated primitive variable will override the instance value or
|
||||
default.
|
||||
|
||||
|
||||
#### Attribute state and shader assignments
|
||||
|
||||
Every geometric primitive has a collection of *attributes* (sometimes
|
||||
called the *graphics state*) that includes its transformation
|
||||
matrix, the list of which lights illuminate it, whether it is one-sided
|
||||
or two-sided, shader assignments, etc. There may also be a long list of
|
||||
renderer-specific or user-designated attributes associated with each
|
||||
object. A particular attribute state may be shared among many geometric
|
||||
primitives.
|
||||
|
||||
The attribute state also includes shader assignments --- the shaders or
|
||||
shader groups for each of several *shader uses*, such as surface
|
||||
shaders that designate how light reflects or emits from each point on a shape,
|
||||
displacement shaders that can add fine detail to the shape on a
|
||||
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.
|
||||
|
||||
|
||||
#### Shader execution state: parameter binding and global variables
|
||||
|
||||
When the body of code of an individual shader is about to execute, all
|
||||
its parameters are *bound* --- that is, take on specific values
|
||||
(from connections from other layers, interpolated primitive variables,
|
||||
instance values, or defaults, in that order).
|
||||
|
||||
Certain state about the position on the surface where the shading is
|
||||
being run is stored in so-called *global variables*. This includes
|
||||
such useful data as the 3D coordinates of the point being shaded, the
|
||||
surface normal and tangents at that point, etc.
|
||||
|
||||
Additionally, the shader may query other information about other
|
||||
elements of the attribute state attached to the primitive, and
|
||||
information about the renderer as a whole (rendering options, etc.).
|
||||
|
||||
#### Surface and volume shaders compute closures
|
||||
|
||||
Surface shaders (and volume shaders) do not by themselves compute the
|
||||
final color of light emanating from the surface (or along a volume).
|
||||
Rather, they compute a *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
|
||||
quantities not yet known (such as the direction from which the surface
|
||||
is being viewed, and the amount of light from each source that is
|
||||
arriving at the surface).
|
||||
|
||||
For example, a surface shader may compute its result like this:
|
||||
|
||||
color paint = texture ("file.tx", u, v);
|
||||
Ci = paint * diffuse (N);
|
||||
|
||||
In this example, the variable `paint` will take on a specific numeric
|
||||
value (by looking up from a texture map). But the `diffuse()` function
|
||||
returns a `color closure`, not a definite numeric `color`. The output
|
||||
variable `Ci` that represents the appearance of the surface is also a `color
|
||||
closure`, whose numeric value is not known yet, except that it will be the
|
||||
product of `paint`` and a Lambertian reflectance.
|
||||
|
||||
|
||||
|
||||
```{image} Figures/shaderexecschematic.png
|
||||
```
|
||||
|
||||
The closures output by surface and volume shaders can do a number of
|
||||
interesting things that a mere number cannot:
|
||||
|
||||
* Evaluate: given input and output light directions, compute the
|
||||
proportion of light propagating from input to output.
|
||||
* Sample: given just an input (or output) direction, choose a
|
||||
scattering direction with a probability distribution that is
|
||||
proportional to the amount of light that will end up going in various
|
||||
directions.
|
||||
* Integrate: given all lights and a view direction, compute
|
||||
the total amount of light leaving the surface in the view direction.
|
||||
* Recompute: given changes only to lights (or only to one light),
|
||||
recompute the integrated result without recomputing other lights or
|
||||
any of the calculations that went into assembling constants in the
|
||||
closure (such as texture lookups, noise functions, etc.).
|
||||
|
||||
<!--
|
||||
At present, we are assuming that the primitive closure functions (such
|
||||
as `diffuse`, `ward`, `cooktorrance`, etc.) are all built
|
||||
into the renderer, or implemented as renderer plugins. At a later time,
|
||||
possibly in a later draft or maybe not until a truly later version of
|
||||
the spec, we will fully spec it out so that closure primitive functions
|
||||
may be written in OSL. But I fear that if we do it too soon,
|
||||
we'll screw it up. But, yes, the eventual goal is for you to be able to
|
||||
write these primitive functions in the language itself.
|
||||
-->
|
||||
|
||||
|
||||
#### Integrators
|
||||
|
||||
The renderer contains a number of *integrators* (selectable via the
|
||||
renderer's API) which will combine the color closures computed by
|
||||
surfaces and volumes with the light sources and view-dependent
|
||||
information, to yield the amount of light visible to the camera.
|
||||
|
||||
```{image} Figures/integratorschematic.png
|
||||
:width: 6.0in
|
||||
```
|
||||
|
||||
<!--
|
||||
At present, this document is written as if the integrators are built
|
||||
into the renderer itself (or implemented as renderer plug-ins). At a
|
||||
later time, we intend to make it possible for integrators themselves
|
||||
to be written in OSL.
|
||||
-->
|
||||
|
||||
|
||||
#### Units
|
||||
|
||||
You can tell the renderer (through a global option) what units the scene
|
||||
is using for distance and time. Then the shader has a built-in function
|
||||
called `transformu()` that works a lot like `transform()`, but
|
||||
instead of converting between coordinate systems, it converts among
|
||||
units. For example,
|
||||
|
||||
```
|
||||
displacement bumpy (float bumpdist = 1,
|
||||
string bumpunits = "cm")
|
||||
{
|
||||
// convert bumpdist to common units
|
||||
float spacing = transformu (bumpunits, "common", bumpdist);
|
||||
float n = noise (P / spacing);
|
||||
displace (n);
|
||||
}
|
||||
```
|
||||
|
||||
So you can write a shader to achieve some effect in real world units,
|
||||
and that shader is totally reusable on another show that used different
|
||||
modeling units.
|
||||
|
||||
It knows all the standard names like `cm`, `in`, `km`,
|
||||
etc., and can convert among any of those, as well as between named
|
||||
coordinate systems. For example,
|
||||
|
||||
```
|
||||
float x = transformu ("object", "mm", 1);
|
||||
```
|
||||
|
||||
now `x` is the number of millimeters per unit of "object" space on
|
||||
that primitive.
|
||||
|
||||
[^rendererapi]: This document does not dictate a specific renderer API for
|
||||
declaring shader instances, groups, and connections; the code above is just
|
||||
an example of how it might be done.
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# http://www.sphinx-doc.org/en/master/config
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
from __future__ import absolute_import
|
||||
import sys
|
||||
import os
|
||||
import shlex
|
||||
import subprocess
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
default_role = 'code'
|
||||
|
||||
project = 'Open Shading Language'
|
||||
copyright = 'Contributors to the Open Shading Language project'
|
||||
author = 'Larry Gritz, editor'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
|
||||
# LG addition: we search for it in the CMakeLists.txt so we don't need to
|
||||
# keep modifying this file:
|
||||
version = '0.0'
|
||||
release = '0.0.0'
|
||||
import re
|
||||
version_regex = re.compile(r'set \(OSL_VERSION \"?((\d+\.\d+)\.\d+)\.\d+\"?\)')
|
||||
f = open('../../CMakeLists.txt')
|
||||
for l in f:
|
||||
aa=re.search(version_regex, l)
|
||||
if aa is not None:
|
||||
release = aa.group(1)
|
||||
version = aa.group(2)
|
||||
break
|
||||
f.close()
|
||||
print ("OSL docs version = {}, release = {}".format(version, release))
|
||||
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
|
||||
# add custom extensions directory to python path
|
||||
sys.path.insert(0, os.path.join(os.path.abspath(os.path.dirname(__file__)), 'extensions/sphinxtr'))
|
||||
sys.path.insert(0, os.path.join(os.path.abspath(os.path.dirname(__file__)), '../../ext/breathe'))
|
||||
#import html_mods
|
||||
#import latex_mods
|
||||
|
||||
extensions = [
|
||||
'breathe',
|
||||
'myst_parser',
|
||||
'sphinx_tabs.tabs',
|
||||
]
|
||||
|
||||
myst_enable_extensions = [
|
||||
# "amsmath",
|
||||
"attrs_inline",
|
||||
"colon_fence",
|
||||
"deflist",
|
||||
"dollarmath",
|
||||
"fieldlist",
|
||||
# "html_admonition",
|
||||
# "html_image",
|
||||
# "linkify",
|
||||
# "replacements",
|
||||
# "smartquotes",
|
||||
# "strikethrough",
|
||||
# "substitution",
|
||||
# "tasklist",
|
||||
]
|
||||
myst_heading_anchors = 3
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['templates']
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = []
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
#html_theme = 'alabaster'
|
||||
#html_theme = 'astropy-sphinx-theme'
|
||||
# html_theme = 'sphinx_rtd_theme'
|
||||
html_theme = 'furo'
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
|
||||
# Breathe options
|
||||
breathe_projects = { "osl": "../../build/doxygen/xml" }
|
||||
breathe_default_project = "osl"
|
||||
breathe_domain_by_extension = {'h': 'cpp'}
|
||||
breathe_default_members = ()
|
||||
primary_domain = 'cpp'
|
||||
highlight_language = 'cpp'
|
||||
|
||||
|
||||
read_the_docs_build = os.getenv('READTHEDOCS') == 'True'
|
||||
|
||||
if read_the_docs_build:
|
||||
print ("cwd =", os.getcwd())
|
||||
print ("checkpoint -- rtd build")
|
||||
if not os.path.exists('../../build/doxygen') :
|
||||
os.makedirs ('../../build/doxygen')
|
||||
print ("checkpoint 2 -- rtd build")
|
||||
subprocess.call('echo "Calling Doxygen"', shell=True)
|
||||
subprocess.call(['doxygen'], shell=True)
|
||||
subprocess.call('echo "Ran Doxygen"', shell=True)
|
||||
@@ -0,0 +1,31 @@
|
||||
<!--
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
-->
|
||||
|
||||
|
||||
# Copyright Notice
|
||||
|
||||
|
||||
The code that implements Open Shading Language is licensed under the BSD
|
||||
3-clause (also sometimes known as "new BSD" or "modified BSD") license.
|
||||
|
||||
```{include} ../../LICENSE.md
|
||||
```
|
||||
|
||||
|
||||
This manual and other text documentation about OSL are licensed under the
|
||||
Creative Commons Attribution 4.0 International License.
|
||||
|
||||
```{image} figures/CC-BY.png
|
||||
:alt: Beautiful Sunset
|
||||
:width: 200px
|
||||
:align: center
|
||||
```
|
||||
|
||||
http://creativecommons.org/licenses/by/4.0/
|
||||
|
||||
|
||||
OSL incorporates code from several other software packages with
|
||||
compatible licenses. Copies of their licenses are reproduced here:
|
||||
https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/blob/master/THIRD-PARTY.md
|
||||
@@ -0,0 +1,709 @@
|
||||
---
|
||||
numbering:
|
||||
heading_1: true
|
||||
heading_2: true
|
||||
heading_3: true
|
||||
---
|
||||
|
||||
<!--
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
-->
|
||||
|
||||
|
||||
(chap-types)=
|
||||
# Data types
|
||||
|
||||
OSL provides several built-in simple data types for performing
|
||||
computations inside your shader:
|
||||
|
||||
Type | Explanation
|
||||
:---------- | :-----------
|
||||
`int` | Integer data
|
||||
`float` | Scalar floating-point data (numbers)
|
||||
`point`, `vector`, `normal` | Three-dimensional positions, directions, and face orientations
|
||||
`color` | Spectral reflectivities and light energy values
|
||||
`matrix` | $4 \times 4$ transformation matrices
|
||||
`string` | Character strings (such as filenames)
|
||||
`void` | Indicates functions that do not return a value
|
||||
|
||||
In addition, you may create arrays and structures (much like C), and
|
||||
OSL has a new type of data structure called a *closure*.
|
||||
|
||||
The remainder of this chapter will describe the simple and aggregate
|
||||
data types available in OSL.
|
||||
|
||||
(sec-datatypes-int)=
|
||||
## `int`
|
||||
|
||||
The basic type for discrete numeric values is `int`. The size of
|
||||
the `int` type is renderer-dependent, but is guaranteed to be at
|
||||
least 32 bits.
|
||||
|
||||
Integer constants are constructed the same way as in C. The following
|
||||
are examples of `int` constants: `1`, `-2`, etc. Integer
|
||||
constants may be specified as hexadecimal, for example: `0x01cf`.
|
||||
|
||||
Unlike C, no unsigned, bool, char, short, or long types are supplied.
|
||||
This is to simplify the process of writing shaders (as well as
|
||||
implementing shading systems).
|
||||
|
||||
The following operators may be used with `int` values (in order of
|
||||
decreasing precedence, with each box holding operators of the same
|
||||
precedence):
|
||||
|
||||
|
||||
Operation | Result | Explanation
|
||||
:--------- | :------ | :---
|
||||
*int* `++` | `int` | post-increment by 1
|
||||
*int* `--` | `int` | post-decrement by 1
|
||||
| |
|
||||
| |
|
||||
`++` *int* | `int` | pre-increment by 1
|
||||
`--` *int* | `int` | pre-decrement by 1
|
||||
`-` *int* | `int` | unary negation
|
||||
`~` *int* | `int` | bitwise complement (1 and 0 bits flipped)
|
||||
`!` *int* | `int` | boolean `not' (1 if operand is zero, otherwise 0)
|
||||
| |
|
||||
| |
|
||||
*int* `*` *int* | `int` | multiplication
|
||||
*int* `/` *int* | `int` | division
|
||||
*int* `%` *int* | `int` | modulus
|
||||
| |
|
||||
| |
|
||||
*int* `+` *int* | `int` | addition
|
||||
*int* `-` *int* | `int` | subtraction
|
||||
| |
|
||||
| |
|
||||
*int* `<<` *int* | `int` | shift left
|
||||
*int* `>>` *int* | `int` | shift right
|
||||
| |
|
||||
| |
|
||||
*int* `<` *int* | `int` | 1 if the first value is less than the second, else 0
|
||||
*int* `<=` *int* | `int` | 1 if the first value is less or equal to the second, else 0
|
||||
*int* `>` *int* | `int` | 1 if the first value is greater than the second, else 0
|
||||
*int* `>=` *int* | `int` | 1 if the first value is greater than or equal to the second, else 0
|
||||
| |
|
||||
| |
|
||||
*int* `==` *int* | `int` | 1 if the two values are equal, else 0
|
||||
*int* `!=` *int* | `int` | 1 if the two values are different, else 0
|
||||
| |
|
||||
| |
|
||||
*int* `&` *int* | `int` | bitwise and
|
||||
| |
|
||||
| |
|
||||
*int* `^` *int* | `int` | bitwise exclusive or
|
||||
| |
|
||||
| |
|
||||
*int* `\|` *int* | `int` | bitwise or
|
||||
| |
|
||||
| |
|
||||
*int* `&&` *int* | `int` | boolean and (1 if both operands are nonzero, otherwise 0)
|
||||
| |
|
||||
| |
|
||||
*int* `\|\|` *int* | `int` | boolean or (1 if either operand is nonzero, otherwise 0)
|
||||
|
||||
|
||||
Note that the `not`, `and`, and `or` keywords are synonyms for `!`, `&&`, and
|
||||
`||`, respectively.
|
||||
|
||||
|
||||
|
||||
## `float`
|
||||
|
||||
The basic type for scalar floating-point numeric values is `float`. The
|
||||
size of the `float` type is renderer-dependent, but is guaranteed to
|
||||
be at least IEEE 32-bit float (the standard C `float` data type).
|
||||
Individual renderer implementations may choose to implement `float` with
|
||||
even more precision (such as using the C `double` as the underlying
|
||||
representation).
|
||||
|
||||
Floating-point constants are constructed the same way as in C. The following
|
||||
are examples of `float` constants: `1.0`, `2.48`, `-4.3e2`.
|
||||
|
||||
An `int` may be used in place of a `float` when used with any valid
|
||||
`float` operator. In such cases, the `int` will be promoted to a
|
||||
`float` and the resulting expression will be `float`. An `int` may
|
||||
also be passed to a function that expects a `float` parameters, with the
|
||||
`int` automatically promoted to `float`.
|
||||
|
||||
The following operators may be used with `float` values (in order of
|
||||
decreasing precedence, with each box holding operators of the same
|
||||
precedence):
|
||||
|
||||
|
||||
Operation | Result | Explanation
|
||||
:--------- | :------ | :---
|
||||
*float* `++` | `float` | post-increment by 1
|
||||
*float* `--` | `float` | post-decrement by 1
|
||||
| |
|
||||
| |
|
||||
`++` *float* | `float` | pre-increment by 1
|
||||
`--` *float* | `float` | pre-decrement by 1
|
||||
`-` *float* | `float` | unary negation
|
||||
| |
|
||||
| |
|
||||
*float* `*` *float* | `float` | multiplication
|
||||
*float* `/` *float* | `float` | division
|
||||
| |
|
||||
| |
|
||||
*float* `+` *float* | `float` | addition
|
||||
*float* `-` *float* | `float` | subtraction
|
||||
| |
|
||||
| |
|
||||
*float* `<` *float* | `int` | 1 if the first value is less than the second, else 0
|
||||
*float* `<=` *float* | `int` | 1 if the first value is less or equal to the second, else 0
|
||||
*float* `>` *float* | `int` | 1 if the first value is greater than the second, else 0
|
||||
*float* `>=` *float* | `int` | 1 if the first value is greater than or equal to the second, else 0
|
||||
| |
|
||||
| |
|
||||
*float* `==` *float* | `int` | 1 if the two values are equal, else 0
|
||||
*float* `!=` *float* | `int` | 1 if the two values are different, else 0
|
||||
|
||||
|
||||
|
||||
## `color`
|
||||
|
||||
The `color` type is used to represent 3-component (RGB) spectral
|
||||
reflectivities and light energies. You can assemble a
|
||||
color out of three floats, either representing an RGB triple or some
|
||||
other color space known to the renderer, as well as from a single
|
||||
float (replicated for all three channels). Following are some examples:
|
||||
|
||||
```
|
||||
color (0, 0, 0) // black
|
||||
color ("rgb", .75, .5, .5) // pinkish
|
||||
color ("hsv", .2, .5, .63) // specify in "hsv" space
|
||||
color (0.5) // same as color (0.5, 0.5, 0.5)
|
||||
```
|
||||
|
||||
All these expressions above return colors in "rgb" space. Even the third
|
||||
example returns a color in "rgb" space --- specifically, the RGB value of the
|
||||
color that is equivalent to hue 0.2, saturation 0.5, and value 0.63. In other
|
||||
words, when assembling a color from components given relative to a specific
|
||||
color space in this manner, there is an implied transformation to "rgb" space.
|
||||
The following table lists the built-in color spaces.
|
||||
|
||||
% \caption{Names of color spaces.}\label{tab:colorspacenames}
|
||||
|
||||
| | |
|
||||
:--------- | :------
|
||||
`"rgb"` | The coordinate system that all colors start out in, and in which the renderer expects to find colors that are set by your shader.
|
||||
`"hsv"` | hue, saturation, and value.
|
||||
`"hsl"` | hue, saturation, and lightness.
|
||||
`"YIQ"` | the color space used for the NTSC television standard.
|
||||
`"XYZ"` | CIE *XYZ* coordinates.
|
||||
`"xyY"` | CIE *xyY* coordinates.
|
||||
|
||||
Colors may be assigned another color or a `float` value (which sets
|
||||
all three components to the value). For example:
|
||||
|
||||
```
|
||||
color C;
|
||||
C = color (0, 0.3, 0.3);
|
||||
C = 0.5; // same as C = color (0.5, 0.5, 0.5)
|
||||
```
|
||||
|
||||
Colors can have their individual components examined and set using the
|
||||
`[]` array access notation. For example:
|
||||
|
||||
```
|
||||
color C;
|
||||
float g = C[1]; // get the green component
|
||||
C[0] = 0.5; // set the red component
|
||||
```
|
||||
|
||||
Components 0, 1, and 2 are red, green, and blue, respectively.
|
||||
It is an error to access a color component with an index outside the
|
||||
$[0...2]$ range.
|
||||
|
||||
Color variables may also have their components referenced using "named
|
||||
components" that look like accessing structure fields named `r`, `g`, and `b`,
|
||||
as synonyms for `[0]`, `[1]`, and `[2]`, respectively:
|
||||
|
||||
```
|
||||
float green = C.g; // get the green component
|
||||
C.r = 0.5; // set the red component
|
||||
```
|
||||
|
||||
The following operators may be used with `color` values (in order of
|
||||
decreasing precedence, with each box holding operators of the same
|
||||
precedence):
|
||||
|
||||
|
||||
Operation | Result | Explanation
|
||||
:--------- | :------ | :---
|
||||
*color* `[` *int* `]` | `float` | component access
|
||||
| |
|
||||
| |
|
||||
`-` *color* | `color` | unary negation
|
||||
| |
|
||||
| |
|
||||
*color* `*` *color* | `color` | component-wise multiplication
|
||||
*color* `*` *float* | `color` | scaling
|
||||
*float* `*` *color* | `color` | scaling
|
||||
*color* `/` *color* | `color` | component-wise division
|
||||
*color* `/` *float* | `color` | scaling
|
||||
*float* `/` *color* | `color` | scaling
|
||||
| |
|
||||
| |
|
||||
*color* `+` *color* | `color` | component-wise addition
|
||||
*color* `-` *color* | `color` | component-wise subtraction
|
||||
| |
|
||||
| |
|
||||
*color* `==` *color* | `int` | 1 if the two values are equal, else 0
|
||||
*color* `!=` *color* | `int` | 1 if the two values are different, else 0
|
||||
|
||||
All of the binary operators may combine a scalar value (`float` or
|
||||
`int`) with a `color`, treating the scalar if it were a `color` with
|
||||
three identical components.
|
||||
|
||||
|
||||
## Point-like types: `point`, `vector`, `normal`
|
||||
|
||||
Points, vectors, and normals are similar data types with identical
|
||||
structures but subtly different semantics. We will frequently refer to
|
||||
them collectively as the "point-like" data types when making
|
||||
statements that apply to all three types.
|
||||
|
||||
A `point` is a position in 3D space. A `vector` has a length and
|
||||
direction, but does not exist in a particular location. A `normal` is a
|
||||
special type of vector that is *perpendicular* to a surface, and
|
||||
thus describes the surface's orientation. Such a perpendicular vector
|
||||
uses different transformation rules than ordinary vectors, as we will
|
||||
describe below.
|
||||
|
||||
All of these point-like types are internally represented by three
|
||||
floating-point numbers that uniquely describe a position or
|
||||
direction relative to the three axes of some coordinate system.
|
||||
|
||||
All points, vectors, and normals are described relative to some
|
||||
coordinate system. All data provided to a shader (surface information,
|
||||
graphics state, parameters, and vertex data) are relative to one
|
||||
particular coordinate system that we call the `"common"` coordinate
|
||||
system. The `"common"` coordinate system is one that is convenient
|
||||
for the renderer's shading calculations.
|
||||
|
||||
You can "assemble" a point-like type out of three floats using a
|
||||
constructor:
|
||||
|
||||
```
|
||||
point (0, 2.3, 1)
|
||||
vector (a, b, c)
|
||||
normal (0, 0, 1)
|
||||
```
|
||||
|
||||
These expressions are interpreted as a point, vector, and normal
|
||||
whose three components are the floats given, relative to "common" space .
|
||||
|
||||
As with colors, you may also specify the coordinates relative to some other
|
||||
coordinate system:
|
||||
|
||||
```
|
||||
Q = point ("object", 0, 0, 0);
|
||||
```
|
||||
|
||||
This example assigns to `Q` the point at the origin of "object" space.
|
||||
However, this statement does *not* set the components of `Q` to (0,0,0)!
|
||||
Rather, `Q` will contain the "common" space coordinates of the point that is
|
||||
at the same location as the origin of "object" space. In other words, the
|
||||
point constructor that specifies a space name implicitly specifies a
|
||||
transformation to "common" space. This type of constructor also can be used
|
||||
for vectors and normals.
|
||||
|
||||
The choice of "common" space is renderer-dependent, though will usually
|
||||
be equivalent to either "camera" space or "world" space.
|
||||
|
||||
Some computations may be easier in a coordinate system other than
|
||||
"common" space. For example, it is much more convenient to apply a
|
||||
"solid texture" to a moving object in its "object" space than in
|
||||
"common" space. For these reasons, OSL provides a built-in
|
||||
`transform()` function that
|
||||
allows you to transform points, vectors, and normals
|
||||
among different coordinate systems (see Section [](#sec-stdlib-geom)). Note,
|
||||
however, that OSL does not keep track of which point variables are
|
||||
in which coordinate systems. It is the responsibility of the shader
|
||||
programmer to keep track of this and ensure that, for example, lighting
|
||||
computations are performed using quantities in "common" space.
|
||||
|
||||
Several coordinate systems are predefined by name, listed in the following
|
||||
table. Additionally, a renderer will probably allow for additional coordinate
|
||||
systems to be named in the scene description, and these names may also be
|
||||
referenced inside your shader to designate transformations.
|
||||
|
||||
% \caption{Names of predeclared geometric spaces.\label{tab:spacenames}}
|
||||
|
||||
`"common"`
|
||||
: The coordinate system that all spatial values start out in and the one in
|
||||
which all lighting calculations are carried out. Note that the choice of
|
||||
`"common"` space may be different on each renderer.
|
||||
|
||||
`"object"`
|
||||
: The local coordinate system of the graphics primitive (sphere, patch, etc.)
|
||||
that we are shading.
|
||||
|
||||
`"shader"`
|
||||
: The local coordinate system active at the time that the shader was
|
||||
instanced.
|
||||
|
||||
`"world"`
|
||||
: The world coordinate system designated in the scene.
|
||||
|
||||
`"camera"`
|
||||
: The coordinate system with its origin at the center of the camera lens,
|
||||
$x$-axis pointing right, $y$-axis pointing up, and $z$-axis pointing into
|
||||
the screen.
|
||||
|
||||
`"screen"`
|
||||
: The coordinate system of the camera's image plane (after perspective
|
||||
transformation, if any). Coordinate (0,0) of `"screen"` space is looking
|
||||
along the $z$-axis of "camera" space.
|
||||
|
||||
`"raster"`
|
||||
: 2D pixel coordinates, with (0,0) as the upper-left
|
||||
corner of the image and (xres, yres) as the lower-right corner.
|
||||
|
||||
`"NDC"`
|
||||
: 2D Normalized Device Coordinates --- like raster space, but normalized so
|
||||
that $x$ and $y$ both run from 0 to 1 across the whole image, with (0,0)
|
||||
being at the upper left of the image, and (1,1) being at the lower right.
|
||||
|
||||
|
||||
Point types can have their individual components examined and set using
|
||||
the `[]` array access notation. For example:
|
||||
|
||||
```
|
||||
point P;
|
||||
float y = P[1]; // get the y component
|
||||
P[0] = 0.5; // set the x component
|
||||
```
|
||||
|
||||
Components 0, 1, and 2 are $x$, $y$, and $z$, respectively.
|
||||
It is an error to access a point component with an index outside the
|
||||
$[0...2]$ range.
|
||||
|
||||
Point-like variables may also have their components referenced using "named
|
||||
components" that look like accessing structure fields named `x`, `y`, and `z`,
|
||||
as synonyms for `[0]`, `[1]`, and `[2]`, respectively:
|
||||
|
||||
```
|
||||
float yval = P.y; // get the [1] or y component
|
||||
P.x = 0.5; // set the [0] or x component
|
||||
```
|
||||
|
||||
The following operators may be used with point-like values (in order of
|
||||
decreasing precedence, with each box holding operators of the same
|
||||
precedence):
|
||||
|
||||
|
||||
Operation | Result | Explanation
|
||||
:--------- | :------ | :---
|
||||
*ptype* `[` `int` `]` | `float` | component access
|
||||
| |
|
||||
| |
|
||||
`-` *ptype* | `vector` | component-wise unary negation
|
||||
| |
|
||||
| |
|
||||
*ptype* `*` *ptype* | *ptype* | component-wise multiplication
|
||||
`float` `*` *ptype* | *ptype* | scaling of all components
|
||||
*ptype* `*` `float` | *ptype* | scaling of all components
|
||||
*ptype* `/` *ptype* | *ptype* | component-wise division
|
||||
*ptype* `/` `float` | *ptype* | division of all components
|
||||
`float` `/` *ptype* | *ptype* | division by all components
|
||||
| |
|
||||
| |
|
||||
*ptype* `+` *ptype* | *ptype* | component-wise addition
|
||||
*ptype* `-` *ptype* | `vector` | component-wise subtraction
|
||||
| |
|
||||
| |
|
||||
*ptype* `==` *ptype* | `int` | 1 if the two values are equal, else 0
|
||||
*ptype* `!=` *ptype* | `int` | 1 if the two values are different, else 0
|
||||
|
||||
|
||||
The generic *ptype* is listed in places where any of `point`, `vector`, or
|
||||
`normal` may be used.
|
||||
|
||||
All of the binary operators may combine a scalar value (`float` or `int`) with
|
||||
a point-like type, treating the scalar if it were point-like with three
|
||||
identical components.
|
||||
|
||||
|
||||
## `matrix`
|
||||
|
||||
OSL has a `matrix` type that represents the transformation matrix required to
|
||||
transform points and vectors between one coordinate system and another.
|
||||
Matrices are represented internally by 16 floats (a $4 \times 4$ homogeneous
|
||||
transformation matrix).
|
||||
|
||||
A `matrix` can be constructed from a single float or 16 floats. For example:
|
||||
|
||||
```
|
||||
matrix zero = 0; // makes a matrix with all 0 components
|
||||
matrix ident = 1; // makes the identity matrix
|
||||
|
||||
// Construct a matrix from 16 floats
|
||||
matrix m = matrix (m00, m01, m02, m03, m10, m11, m12, m13,
|
||||
m20, m21, m22, m23, m30, m31, m32, m33);
|
||||
```
|
||||
|
||||
Assigning a single floating-point number $x$ to a matrix will result
|
||||
in a matrix with diagonal components all being $x$ and other
|
||||
components being zero (i.e., $x$ times the identity matrix).
|
||||
Constructing a matrix with 16 floats will create the matrix whose
|
||||
components are those floats, in row-major order.
|
||||
|
||||
Similar to point-like types, a `matrix` may be constructed in
|
||||
reference to a named space:
|
||||
|
||||
```
|
||||
// Construct matrices relative to something other than "common"
|
||||
matrix q = matrix ("shader", 1);
|
||||
matrix m = matrix ("world", m00, m01, m02, m03, m10, m11, m12, m13,
|
||||
m20, m21, m22, m23, m30, m31, m32, m33);
|
||||
```
|
||||
|
||||
The first form creates the matrix that transforms points from "shader" space
|
||||
to "common" space. Transforming points by this matrix is identical to calling
|
||||
`transform("shader", "common", ...)`. The second form prepends the
|
||||
current-to-world transformation matrix onto the $4 \times 4$ matrix with
|
||||
components $m_{0,0} ... m_{3,3}$. Note that although we have used `"shader"`
|
||||
and `"world"` space in our examples, any named space is acceptable.
|
||||
|
||||
A matrix may also be constructed from the names of two coordinate
|
||||
systems, yielding the matrix that transforms coordinates from the
|
||||
first named space to the second named space:
|
||||
|
||||
```
|
||||
matrix m = matrix ("object", "world");
|
||||
```
|
||||
|
||||
The example returns the *object-to-world* transformation matrix.
|
||||
|
||||
Matrix variables can be tested for equality and inequality with the `==` and
|
||||
`!=` boolean operators. Also, the `*` operator between matrices denotes
|
||||
matrix multiplication, while `m1 / m2` denotes multiplying `m1` by the inverse
|
||||
of matrix `m2`. Thus, a matrix can be inverted by writing `1/m`. In
|
||||
addition, some functions will accept matrix variables as arguments, as
|
||||
described in Section [](#chap-stdlibrary).
|
||||
|
||||
Individual components of a matrix variable may be set or accessed using array
|
||||
notation, for example,
|
||||
|
||||
```
|
||||
matrix M;
|
||||
float x = M[row][col];
|
||||
M[row][col] = 1;
|
||||
```
|
||||
|
||||
Valid component indices are integers on $[0...3]$. It is an error to access a
|
||||
matrix component with either a row or column outside this range.
|
||||
|
||||
The following operators may be used with matrices (in order of decreasing
|
||||
precedence, with each box holding operators of the same precedence):
|
||||
|
||||
Operation | Result | Explanation
|
||||
:--------- | :------ | :---
|
||||
*matrix* `[` *int* `][` *int* `]` | `float` | component access (row, column)
|
||||
| |
|
||||
| |
|
||||
`-` *matrix* | `matrix` | unary negation
|
||||
| |
|
||||
| |
|
||||
*matrix* `*` *matrix* | `matrix` | matrix multiplication
|
||||
*matrix* `*` *float* | `matrix` | component-wise scaling
|
||||
*float* `*` *matrix* | `matrix` | component-wise scaling
|
||||
*matrix* `/` *matrix* | `matrix` | multiply the first matrix by the *inverse of the second
|
||||
*matrix* `/` *float* | `matrix` | component-wise division
|
||||
*float* `/` *matrix* | `matrix` | multiply the *float* by the *inverse of the matrix
|
||||
| |
|
||||
| |
|
||||
*matrix* `==` *matrix* | *int* | 1 if the two values are equal, else 0
|
||||
*matrix* `!=` *matrix* | *int* | 1 if the two values are different, else 0
|
||||
|
||||
|
||||
## `string`
|
||||
|
||||
The `string` type may hold character strings. The main application
|
||||
of strings is to provide the names of files where textures may be
|
||||
found. Strings can be compared using `==` and `!=`.
|
||||
|
||||
String constants are denoted by surrounding the characters with double
|
||||
quotes, as in `"I am a string literal"`. As in C programs, string
|
||||
literals may contain escape sequences such as `\n` (newline),
|
||||
`\r` (carriage return), `\t` (tab), `\"` (double quote),
|
||||
`\\` (backslash).
|
||||
|
||||
Two quote-quoted string literals that are separated only by whitespace
|
||||
(spaces, tabs, or newlines) will be automatically concatenated into a
|
||||
single string literal. In other words,
|
||||
|
||||
```text
|
||||
"foo" "bar"
|
||||
```
|
||||
|
||||
is exactly equivalent to `"foobar"`.
|
||||
|
||||
## `void`
|
||||
|
||||
The `void` type is used to designate a function that does not return a value.
|
||||
No variable may have type `void`.
|
||||
|
||||
## Arrays
|
||||
|
||||
Arrays of any of the basic types are supported, provided that they
|
||||
are 1D and statically sized, using the usual syntax for C-like languages:
|
||||
|
||||
```
|
||||
float d[10]; // Declare an uninitialized array
|
||||
float c[3] = { 0.1, 0.2, 3.14 }; // Initialize the array
|
||||
|
||||
float f = c[1]; // Access one element
|
||||
```
|
||||
|
||||
The built-in function `arraylength()` returns the number of elements in an
|
||||
array. For example:
|
||||
|
||||
```
|
||||
float c[3];
|
||||
int clen = arraylength(c); // should return 3
|
||||
```
|
||||
|
||||
There are two circumstances when arrays do not need to have a declared
|
||||
length --- an array parameter to a function, and a shader parameter that
|
||||
is an array. This is indicated by empty array brackets, as shown in the
|
||||
following example:
|
||||
|
||||
```
|
||||
float sum (float x[])
|
||||
{
|
||||
float s = 0;
|
||||
for (int i = 0; i < arraylength(x); ++i)
|
||||
s += x[i];
|
||||
return s;
|
||||
}
|
||||
```
|
||||
|
||||
It is allowed in OSL to copy an entire array at once using the `=` operator,
|
||||
provided that the arrays contain elements of the same type and that the
|
||||
destination array is at least as long as the source array. For example:
|
||||
|
||||
```
|
||||
float array[4], anotherarray[4];
|
||||
...
|
||||
anotherarray = array;
|
||||
```
|
||||
|
||||
|
||||
## Structures
|
||||
|
||||
Structures are used to group several fields of potentially different types
|
||||
into a single object that can be referred to by name. You may then use the
|
||||
structure type name to declare structure variables as you would for any of the
|
||||
built-in types. Structure elements are accessed using the `.` ("dot")
|
||||
operator. The syntax for declaring and using structures is similar to C or
|
||||
C++:
|
||||
|
||||
```
|
||||
struct RGBA { // Define a structure type
|
||||
color rgb;
|
||||
float alpha;
|
||||
};
|
||||
|
||||
RGBA col; // Declare a structure
|
||||
r.rgb = color (1, 0, 0); // Assign to one field
|
||||
color c = r.rgb; // Read from a structure field
|
||||
|
||||
RGBA b = { color(.1,.2,.3), 1 }; // Member-by-member initialization
|
||||
```
|
||||
|
||||
You can use "constructor expressions" for a your struct types much like
|
||||
you can construct built-in types like `color` or `point`:
|
||||
|
||||
> *struct_name* `(` *first_member_value*, ... `}`
|
||||
|
||||
For example,
|
||||
|
||||
```
|
||||
RGBA c = RGBA(col,alpha); // Constructor syntax
|
||||
|
||||
RGBA add (RGBA a, RGBA b)
|
||||
{
|
||||
return RGBA (a.rgb+b.rgb, a.a+b.a); // return expression
|
||||
}
|
||||
|
||||
// pass constructor expression as a parameter:
|
||||
RGBA d = add (c, RGBA(color(.3,.4,.5), 0));
|
||||
```
|
||||
|
||||
You may also use the *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:
|
||||
|
||||
```
|
||||
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
|
||||
```
|
||||
|
||||
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 arrays).
|
||||
|
||||
```
|
||||
struct A {
|
||||
color a;
|
||||
float b[4]; // Ok: struct may contain an array
|
||||
};
|
||||
|
||||
RGBA vals[4]; // Ok: Array of structures
|
||||
vals[0].a = 0;
|
||||
|
||||
A d[5]; // NO: Array of structures that contain arrays
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Closures
|
||||
|
||||
A `closure`is an expression or function call that will be stored, along
|
||||
with necessary contextual information, to be evaluated at a later time.
|
||||
|
||||
In general, the type "`closure` *gentype*" behaves exactly like a
|
||||
*gentype*, except that its numeric values may not be examined or
|
||||
used for the duration of the shader's execution. For example, a
|
||||
`color closure` behaves mostly like a color --- you can multiply it by a
|
||||
scalar, assign it to a `color closure` variable, etc. --- but you may not
|
||||
assign it to an ordinary `color` or examine its individual component's
|
||||
numeric values.
|
||||
|
||||
It is legal to assign `0` to a closure, which is understood to mean setting it
|
||||
to a *null closure* (even though in all other circumstances, assigning a
|
||||
`float` to a `closure`would not be allowed).
|
||||
|
||||
At present, the only type of `closure`supported by OSL is the `color closure`,
|
||||
and the only allowed operations are those that let you form a linear
|
||||
combination of `color closure`'s. Additional closure types and operations are
|
||||
reserved for future use.
|
||||
|
||||
Allowable operations on `color closure` include:
|
||||
|
||||
Operation | Result | Explanation
|
||||
:--------- | :------ | :---
|
||||
`-` *colorclosure* | `color closure` | unary negation
|
||||
| |
|
||||
| |
|
||||
*color* `*` *colorclosure* | `color closure` | component-wise scaling
|
||||
*colorclosure* `*` *color* | `color closure` | component-wise scaling
|
||||
*float* `*` *colorclosure* | `color closure` | scaling
|
||||
*colorclosure* `*` *float* | `color closure` | scaling
|
||||
| |
|
||||
| |
|
||||
*colorclosure* `+` *colorclosure* | `color closure` | component-wise addition
|
||||
% *colorclosure* `-` *colorclosure* | `color closure` | component-wise subtraction
|
||||
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
<!--
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
-->
|
||||
|
||||
|
||||
(chap-glossary)=
|
||||
# Glossary
|
||||
|
||||
Attribute state
|
||||
|
||||
: The set of variables that determines all the properties (other than shape)
|
||||
of a *geometric primitive* --- such as its local transformation matrix,
|
||||
the surface, displacement, and volume shaders to be used, which light
|
||||
sources illuminate objects that share the attribute state, whether
|
||||
surfaces are one-sided or two-sided, etc. Basically all of the options
|
||||
that determine the behavior and appearance of the primitives, that are not
|
||||
determined by the shape itself or the code of the shaders. A single
|
||||
attribute state may be shared among multiple geometric primitives. Also
|
||||
sometimes called *graphics state*.
|
||||
|
||||
BSDF
|
||||
|
||||
: Bidirectional scattering distribution function, a function that describes
|
||||
light scattering properties of a surface.
|
||||
|
||||
Built-in function
|
||||
|
||||
: A function callable from within a shader, where the implementation of the
|
||||
function is provided by the renderer (as opposed to a function that the
|
||||
shader author writes in OSL itself).
|
||||
|
||||
Closure
|
||||
|
||||
: A symbolic representation of a function to be called, and values for its
|
||||
parameters, that are packaged up to be evaluated at a later time to yield
|
||||
a final numeric value.
|
||||
|
||||
Connection
|
||||
|
||||
: A routing of the value of an *output parameter* of one *shader layer* to
|
||||
an *input parameter* of another shader layer within the same *shader
|
||||
group*.
|
||||
|
||||
Default parameter value
|
||||
|
||||
: The initial value of a *shader parameter*, if the renderer does not
|
||||
override it with an *instance value*, an interpolated *primitive
|
||||
variable*, or a *connection* to an output parameter of another *layer*
|
||||
within the *group*. The default value of a shader parameter is explicitly
|
||||
given in the code for that shader, and may either be a constant or a
|
||||
computed expression.
|
||||
|
||||
EDF
|
||||
|
||||
: Emission distribution function, a function that describes the distribution
|
||||
of light emitted by a light source.
|
||||
|
||||
Geometric primitive
|
||||
|
||||
: A single shape, such as a NURBS patch, a polygon or subdivision mesh, a
|
||||
hair primitive, etc.
|
||||
|
||||
Global variables
|
||||
|
||||
: The set of "built-in" variables describing the common renderer inputs to
|
||||
all shaders (as opposed to shader-specific parameters). These include
|
||||
position (`P`), surface normal (`N`), surface tangents (`dPdu`, `dPdv`),
|
||||
as well as standard radiance output (`Ci`). Different *shader types*
|
||||
support different subsets of the global variables.
|
||||
|
||||
Graphics state
|
||||
|
||||
: See *attribute state*.
|
||||
|
||||
Group
|
||||
|
||||
: See *shader group*.
|
||||
|
||||
Input parameter
|
||||
|
||||
: A read-only *shader parameter* that provides a value to control a
|
||||
shader's behavior. Can also refer to a read-only parameter to a
|
||||
*shader function*.
|
||||
|
||||
Instance value
|
||||
|
||||
: A constant value that overrides a default parameter value for a
|
||||
particular *shader instance*. Each instance of a shader may have a
|
||||
completely different set of instance values for its parameters.
|
||||
|
||||
Layer
|
||||
|
||||
: See *shader layer*.
|
||||
|
||||
Output parameter
|
||||
|
||||
: A read/write *shader parameter* allows a shader to provide outputs beyond
|
||||
the *global variables* such as `Ci`. Can also refer to a read/write
|
||||
parameter to a *shader function*, allowing a function to provide more
|
||||
outputs than a simple return value.
|
||||
|
||||
Primitive
|
||||
|
||||
: Usually refers to a *geometric primitive*.
|
||||
|
||||
Primitive variable
|
||||
|
||||
: A named variable, and values, attached to an individual geometric
|
||||
primitive. Primitive variables may have one of several *interpolation
|
||||
methods* --- such as a single value for the whole primitive, a value for
|
||||
each piece or face of the primitive, or per-vertex values that are
|
||||
smoothly interpolated across the surface.
|
||||
|
||||
% Public method
|
||||
%
|
||||
% : A function within a shader that has an entry point that is visible and
|
||||
% directly callable by the renderer, as opposed to merely being called from
|
||||
% other code within the shader. Public methods must be *top-level* (not
|
||||
% defined within other functions) and must be preceded by the `public`
|
||||
% keyword.
|
||||
|
||||
Shader
|
||||
|
||||
: A small self-contained program written in OSL, used to extend the
|
||||
functionality of a renderer with custom behavior of materials and lights.
|
||||
A particular shader may have multiple *shader instances* within a scene,
|
||||
each of which has its unique *instance parameters*, transformation, etc.
|
||||
|
||||
Shader function
|
||||
|
||||
: A function written in OSL that may be called from within a shader.
|
||||
|
||||
Shader group
|
||||
|
||||
: An ordered collection of *shader instances* (individually called the
|
||||
*layers* of a group) that are executed to collectively determine material
|
||||
properties or displacement of a geometric primitive, emission of a light
|
||||
source, or scattering properties of a volume. In addition to executing
|
||||
sequentially, layers within a group may optionally have any of their input
|
||||
parameters explicitly connected to output parameters of other layers
|
||||
within the group in an acyclic manner (thus, sometimes being referred to
|
||||
as a *shader network*).
|
||||
|
||||
Shader instance
|
||||
|
||||
: A particular reference to a *shader*, with a unique set of *instance
|
||||
values*, transformation, and potentially other attributes. Each shader
|
||||
instance is a separate entity, despite their sharing executable code.
|
||||
|
||||
Shader network
|
||||
|
||||
: See *shader group*.
|
||||
|
||||
Shader layer
|
||||
|
||||
: An individual *shader instance* within a *shader group*.
|
||||
|
||||
Shader parameter
|
||||
|
||||
: A named input or output variable of a shader. *Input parameters* provide
|
||||
"knobs" that control the behavior of a shader; *output parameters*
|
||||
additional provide a way for shaders to produce additional output beyond
|
||||
the usual *global variables*.
|
||||
|
||||
Shading
|
||||
|
||||
: The computations within a renderer that implement the behavior and visual
|
||||
appearance of materials and lights.
|
||||
|
||||
VDF
|
||||
|
||||
: Volumetric distribution function, a function that describes the scattering
|
||||
properties of a volume.
|
||||
@@ -0,0 +1,239 @@
|
||||
---
|
||||
numbering:
|
||||
heading_1: true
|
||||
heading_2: true
|
||||
heading_3: true
|
||||
---
|
||||
|
||||
<!--
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
-->
|
||||
|
||||
|
||||
(chap-grammar)=
|
||||
# Formal Language Grammar
|
||||
|
||||
This section gives the complete syntax of OSL. Syntactic structures that have
|
||||
a name ending in `-opt` are optional. Structures surrounded by curly braces
|
||||
`{ }` may be repeated 0 or more times. Text in `typewriter` face indicates
|
||||
literal text. The $\epsilon$ character is used to indicate that it is
|
||||
acceptable for there to be nothing (empty, no token).
|
||||
|
||||
#### Lexical elements
|
||||
|
||||
|
||||
\<digit\> ::= "`0`" | "`1`" | "`2`" | "`3`" | "`4`" | "`5`" | "`6`" | "`7`" | "`8`" | "`9`"
|
||||
|
||||
\<digit-sequence\> ::= \<digit\> { \<digit\> }
|
||||
|
||||
\<hexdigit\> ::= \<digit\> | "`a`" | "`A`" | "`b`" | "`B`" | "`c`" | "`C`" | "`d`" | "`D`" | "`e`" | "`E`" | "`f`" | "`F`"
|
||||
|
||||
\<hexdigit-sequence\> ::= \<hexdigit\> { \<hexdigit\> }
|
||||
|
||||
\<integer\> ::= \<sign\> \<digit-sequence\>
|
||||
<br>$~~~~~~~~~~$ | \<sign\> "`0x`" \<hexdigit-sequence\>
|
||||
|
||||
\<floating-point\> ::= \<digit-sequence\> \<decimal-part-opt\> \<exponent-opt\>
|
||||
<br>$~~~~~~~~~~$ | \<decimal-part\> \<exponent-opt\>
|
||||
|
||||
\<decimal-part\> ::= '`.`' { \<digit\> }
|
||||
|
||||
\<exponent\> ::= '`e`' \<sign\> \<digit-sequence\>
|
||||
|
||||
\<sign\> ::= '`-`' | '`+`' | $\epsilon$
|
||||
|
||||
\<number\> ::= \<integer\>
|
||||
<br>$~~~~~~~~~~$ | \<floating-point\>
|
||||
|
||||
\<char-sequence\> ::= { \<any-char\> }
|
||||
|
||||
\<stringliteral> ::= `"` \<char-sequence\> `"`
|
||||
|
||||
\<identifier\> ::= \<letter-or-underscore\> { \<letter-or-underscore-or-digit\> }
|
||||
|
||||
|
||||
#### Overall structure
|
||||
|
||||
\<shader-file\> ::= { \<global-declaration\> }
|
||||
|
||||
\<global-declaration\> ::= \<function-declaration\>
|
||||
<br>$~~~~~~~~~~$ | \<struct-declaration\>
|
||||
<br>$~~~~~~~~~~$ | \<shader-declaration\>
|
||||
|
||||
\<shader-declaration\> ::= <br>$~~~~~~~~~~~~$ $~~~~~~~~~~$
|
||||
\<shadertype\> \<identifier\> \<metadata-block-opt\>
|
||||
"(" \<shader-formal-params-opt\> ")" "{" \<statement-list\> "}"
|
||||
|
||||
\<shadertype\> ::= "displacement" | "shader" | "surface" | "volume"
|
||||
|
||||
\<shader-formal-params\> ::= \<shader-formal-param\> { "," \<shader-formal-param\> }
|
||||
|
||||
\<shader-formal-param\> ::= \<outputspec\> \<typespec\> \<identifier\>
|
||||
\<initializer\> \<metadata-block-opt\>
|
||||
<br>$~~~~~~~~~~$ | \<outputspec\> \<typespec\> \<identifier\> \<arrayspec\>
|
||||
\<initializer-list\> \<metadata-block-opt\>
|
||||
|
||||
\<metadata-block> ::= "[[" \<metadata\> { "," \<metadata\> } "]]"
|
||||
|
||||
\<metadata\> ::= \<simple-typespec\> \<identifier\> \<initializer\>
|
||||
|
||||
|
||||
|
||||
#### Declarations
|
||||
|
||||
\<function-declaration\> ::= <br>$~~~~~~~~~~~~$ \<typespec\> \<identifier\>
|
||||
"(" \<function-formal-params-opt\> ")" "{" \<statement-list\> "}"
|
||||
|
||||
\<function-formal-params\> ::= \<function-formal-param\> { "," \<function-formal-param\> }
|
||||
|
||||
\<function-formal-param\> ::= \<outputspec\> \<typespec\> \<identifier\> \<arrayspec-opt\>
|
||||
|
||||
\<outputspec> ::= "output" | $\epsilon$
|
||||
|
||||
\<struct-declaration\> ::= "struct" \<identifier\> "{" \<field-declarations> "}" ";"
|
||||
|
||||
\<field-declarations\> ::= \<field-declaration\> { \<field-declaration\> }
|
||||
|
||||
\<field-declaration\> ::= \<typespec\> \<typed-field-list\> ";"
|
||||
|
||||
\<typed-field-list\> ::= \<typed-field\> { "," \<typed-field\> }
|
||||
|
||||
\<typed-field\> ::= \<identifier\> \<arrayspec-opt\>
|
||||
|
||||
\<local-declaration\> ::= \<function-declaration\>
|
||||
<br>$~~~~~~~~~~$ | \<variable-declaration\>
|
||||
|
||||
\<arrayspec> ::= "[" \<integer\> "]"
|
||||
<br>$~~~~~~~~~~$ | "[" "]"
|
||||
|
||||
\<variable-declaration\> ::= \<typespec\> \<def-expressions> ";"
|
||||
|
||||
\<def-expressions\> ::= \<def-expression\> { "," <def-expression\> }
|
||||
|
||||
\<def-expression\> ::= \<identifier\> \<initializer-opt\>
|
||||
<br>$~~~~~~~~~~$ | \<identifier\> \<arrayspec\> \<initializer-list-opt\>
|
||||
|
||||
\<initializer\> ::= "=" \<expression\>
|
||||
|
||||
\<initializer-list\> ::= "=" \<compound-initializer\>
|
||||
|
||||
\<compound-initializer\> ::= "{" \<init-expression-list\> "}"
|
||||
|
||||
\<init-expression-list\> ::= \<init-expression\> { "," \<init-expression\> }
|
||||
|
||||
\<init-expression\> ::= \<expression\> | \<compound-initializer\>
|
||||
|
||||
\<typespec\> ::= \<simple-typename>
|
||||
<br>$~~~~~~~~~~$ | "closure" \<simple-typename\>
|
||||
<br>$~~~~~~~~~~$ | \<identifier-structname\>
|
||||
|
||||
\<simple-typename\> ::=
|
||||
"color"
|
||||
| "float"
|
||||
| "matrix"
|
||||
| "normal"
|
||||
| "point"
|
||||
| "string"
|
||||
| "vector"
|
||||
| "void"
|
||||
|
||||
|
||||
|
||||
#### Statements
|
||||
|
||||
\<statement-list\> ::= \<statement\> { \<statement\> }
|
||||
|
||||
\<statement\> ::=
|
||||
\<compound-expression-opt\> ";"
|
||||
<br>$~~~~~~~~~~$ | \<scoped-statements\>
|
||||
<br>$~~~~~~~~~~$ | \<local-declaration\>
|
||||
<br>$~~~~~~~~~~$ | \<conditional-statement\>
|
||||
<br>$~~~~~~~~~~$ | \<loop-statement\>
|
||||
<br>$~~~~~~~~~~$ | \<loopmod-statement\>
|
||||
<br>$~~~~~~~~~~$ | \<return-statement\>
|
||||
|
||||
\<scoped-statements> ::= "{" \<statement-list-opt\> "}"
|
||||
|
||||
\<conditional-statement\> ::= <br>$~~~~~~~~~~~~$ "if" "(" \<compound-expression\> ")" \<statement\>
|
||||
<br>$~~~~~~~~~~$ | "if" "(" \<compound-expression\> ")" \<statement\> "else" \<statement\>
|
||||
|
||||
\<loop-statement\> ::= <br>$~~~~~~~~~~~~$ "while" "(" \<compound-expression\> ")" \<statement\>
|
||||
<br>$~~~~~~~~~~$ | "do" \<statement\> "while" "(" \<compound-expression\> ")" ";"
|
||||
<br>$~~~~~~~~~~$ | "for" "(" \<for-init-statement-opt\> \<compound-expression-opt\> ";"
|
||||
\<compound-expression-opt\> ")" \<statement\>
|
||||
|
||||
\<for-init-statement\> ::= <br>$~~~~~~~~~~~~$ \<expression-opt\> ";"
|
||||
<br>$~~~~~~~~~~$ | \<variable-declaration\>
|
||||
|
||||
\<loopmod-statement\> ::= "break" ";"
|
||||
<br>$~~~~~~~~~~$ | "continue" ";"
|
||||
|
||||
|
||||
\<return-statement\> ::= "return" \<expression-opt\> ";"
|
||||
|
||||
|
||||
|
||||
#### Expressions
|
||||
|
||||
\<expression-list\> ::= \<expression\> { "," \<expression\> }
|
||||
|
||||
\<expression\> ::= \<number\>
|
||||
<br>$~~~~~~~~~~$ | \<stringliteral\>
|
||||
<br>$~~~~~~~~~~$ | \<type-constructor\>
|
||||
<br>$~~~~~~~~~~$ | \<incdec-op\> \<variable-ref\>
|
||||
<br>$~~~~~~~~~~$ | \<expression\> \<binary-op\> \<expression\>
|
||||
<br>$~~~~~~~~~~$ | \<unary-op\> \<expression\>
|
||||
<br>$~~~~~~~~~~$ | "(" \<compound-expression\> ")"
|
||||
<br>$~~~~~~~~~~$ | \<function-call\>
|
||||
<br>$~~~~~~~~~~$ | \<assign-expression\>
|
||||
<br>$~~~~~~~~~~$ | \<ternary-expression\>
|
||||
<br>$~~~~~~~~~~$ | \<typecast-expression\>
|
||||
<br>$~~~~~~~~~~$ | \<variable-ref\>
|
||||
<br>$~~~~~~~~~~$ | \<compound-initializer\>
|
||||
|
||||
\<compound-expression\> ::= \<expression\> { "," \<expression\> }
|
||||
|
||||
\<variable-lvalue\> ::= \<identifier\> \<array-deref-opt\> \<component-deref-opt\>
|
||||
<br>$~~~~~~~~~~$ | \<variable_lvalue> "[" \<expression\> "]"
|
||||
<br>$~~~~~~~~~~$ | \<variable_lvalue> "." \<identifier\>
|
||||
|
||||
\<variable-ref\> ::= \<identifier\> \<array-deref-opt\>
|
||||
|
||||
\<array-deref> ::= "[" \<expression\> "]"
|
||||
|
||||
\<component-deref> ::= "[" \<expression\> "]"
|
||||
<br>$~~~~~~~~~~$ | "." \<component-field\>
|
||||
|
||||
\<component-field\> ::= "x" | "y" | "z" | "r" | "g" | "b"
|
||||
|
||||
\<binary-op> ::= "*" | "/" | "\%"
|
||||
<br>$~~~~~~~~~~$ | "+" | "-"
|
||||
<br>$~~~~~~~~~~$ | "<<" | ">>"
|
||||
<br>$~~~~~~~~~~$ | "<" | "<=" | ">" | ">="
|
||||
<br>$~~~~~~~~~~$ | "==" | "!="
|
||||
<br>$~~~~~~~~~~$ | "&"
|
||||
<br>$~~~~~~~~~~$ | "^"
|
||||
<br>$~~~~~~~~~~$ | "|"
|
||||
<br>$~~~~~~~~~~$ | "&&" | "and"
|
||||
<br>$~~~~~~~~~~$ | "||" | "or"
|
||||
|
||||
\<unary-op> ::= "-" | "~" | "!" | "not"
|
||||
|
||||
\<incdec-op> ::= "++" | "--"
|
||||
|
||||
\<type-constructor\> ::= \<typespec> "(" \<expression-list\> ")"
|
||||
|
||||
\<function-call\> ::= \<identifier\> "(" \<function-args-opt\> ")"
|
||||
|
||||
\<function-args\> ::= \<expression\> { "," \<expression\> }
|
||||
|
||||
\<assign-expression\> ::= \<variable-lvalue\> \<assign-op\> \<expression\>
|
||||
|
||||
\<assign-op> ::= "=" | "*=" | "/=" | "+=" | "-=" | "&=" | "|=" | "^=" |
|
||||
"<<=" | ">>="
|
||||
|
||||
\<ternary-expression\> ::= \<expression\> "?" \<expression\> ":" \<expression\>
|
||||
|
||||
\<typecast-expression\> ::= "(" \<simple-typename> ")" \<expression\>
|
||||
|
||||
@@ -0,0 +1,403 @@
|
||||
<!--
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
-->
|
||||
|
||||
# Gross syntax, shader types, parameters
|
||||
|
||||
The overall structure of a shader is as follows:
|
||||
|
||||
> *optional-function-or-struct-declarations* \
|
||||
\
|
||||
shader-type shader-name `(` optional-parameters `)` \
|
||||
`{` \
|
||||
*statements* \
|
||||
`}`
|
||||
|
||||
Note that *statements* may include function or structure definitions, local
|
||||
variable declarations, or public methods, as well as ordinary execution
|
||||
instructions (such as assignments, etc.).
|
||||
|
||||
## Shader types
|
||||
|
||||
Shader types include the following: `surface`, `displacement`, `light`,
|
||||
`volume`, and generic `shader`. Some operations may only be performed from
|
||||
within certain types of shaders (e.g., one may only call `displace()` or alter
|
||||
`P` in a displacement shader), and some global variables may only be accessed
|
||||
from within certain types of shaders (e.g., `dPdu` is not defined inside a
|
||||
volume shader).
|
||||
|
||||
Following are brief descriptions of the basic types of shaders:
|
||||
|
||||
|
||||
`surface` shaders
|
||||
|
||||
: Surface shaders determine the basic material properties of a surface and
|
||||
how it reacts to light. They are responsible for computing a
|
||||
`color closure` that describes the material, and optionally setting
|
||||
other user-defined output variables. They may not alter
|
||||
the position of the surface.
|
||||
|
||||
Surface shaders are written as if they describe the behavior of a single
|
||||
point on the primitive, and the renderer will choose the positions
|
||||
surface at which the shader must be evaluated.
|
||||
|
||||
Surface shaders also are used to describe emissive objects, i.e., light
|
||||
sources. OSL does not need a separate shader type to describe lights.
|
||||
|
||||
`displacement` shaders
|
||||
|
||||
: Displacement shaders alter the position and shading normal (or,
|
||||
optionally, just the shading normal) to make a piece of geometry appear
|
||||
deformed, wrinkled, or bumpy. They are the only kind of shader that
|
||||
is allowed to alter a primitive's position.
|
||||
|
||||
`volume` shaders
|
||||
|
||||
: Volume shaders describe how a participating medium (air, smoke, glass,
|
||||
etc.) reacts to light and affects the appearance of objects on the other
|
||||
side of the medium. They are similar to `surface` shaders, except
|
||||
that they may be called from positions that do not lie upon (and are not
|
||||
necessarily associated with) any particular primitive.
|
||||
|
||||
`shader` generic shaders
|
||||
|
||||
: Generic shaders are used for utility code, generic routines that may be
|
||||
called as individual layers in a shader group. Generic shaders need not
|
||||
specify a shader type, and therefore may be reused from inside surface,
|
||||
displacement, or volume shader groups. But as a result, they may
|
||||
not contain any functionality that cannot be performed from inside all
|
||||
shader types (for example, they may not alter `P`, which can only be done
|
||||
from within a displacement shader).
|
||||
|
||||
|
||||
## Shader parameters
|
||||
|
||||
An individual shader has (optionally) many *parameters* whose
|
||||
values may be set in a number of ways so that a single shader may have
|
||||
different behaviors or appearances when used on different objects.
|
||||
|
||||
### Shader parameter syntax
|
||||
|
||||
Shader parameters are specified in the shader declaration, in
|
||||
parentheses after the shader's name. This is much like the parameters
|
||||
to an OSL function (or a function in C or similar languages),
|
||||
except that shader parameters must have an *initializer*, giving a
|
||||
default value for the parameter. Shader parameter default initializers
|
||||
may be expressions (i.e., may be computed rather than restricted to
|
||||
numeric constants), and are evaluated in the order that the parameters
|
||||
are declared, and may include references to previously-declared
|
||||
parameters. Formally, the grammar for a simple parameter
|
||||
declaration looks like this:
|
||||
|
||||
> *type parametername* `=` *default-expression*
|
||||
|
||||
where *type* is one of the data types described in Chapter [](#chap-types),
|
||||
*parametername* is the name of the parameter, and *default-expression* is a
|
||||
valid expression (see Section [](#sec-expressions)). Multiple parameters are
|
||||
simply separated by commas:
|
||||
|
||||
> *type1 parameter1* `=` *expr1* `,` *type2 parameter2* `=` *expr2* `,` ...
|
||||
|
||||
Fixed-length, one-dimensional array parameters are declared as follows:
|
||||
|
||||
> *type parametername* `[` *array-length* `] = {` *expr0* `,` *expr1* ... `}`
|
||||
|
||||
where *array-length* is a positive integer constant giving the length of the
|
||||
array, and the initializer is a series of initializing expressions listed
|
||||
between curly braces. The first initializing expression provides the
|
||||
initializer for the first element of the array, the second expression provides
|
||||
the initializer for the second element of the array, and so on. If the number
|
||||
of initializing expressions is less than the length of the array, any
|
||||
additional array elements will have undefined values.
|
||||
|
||||
Arrays may also be declared without a set length:
|
||||
|
||||
> *type parametername* `[ ] = {` *expr0* `,` *expr1* ... `}`
|
||||
|
||||
where no array length is found between the square brackets.
|
||||
This indicates that the array's length will be determined based on
|
||||
whatever is passed in --- a connection from the output of another shader
|
||||
in the group (take on the length of that output), an instance value
|
||||
(take on the length specified by the declaration of the instance value),
|
||||
or a primitive variable (length determined by its declaration on the
|
||||
primitive). If no instance value, primitive value, or connection is
|
||||
supplied, then the number of initializing expressions will determine the
|
||||
length, as well as the default values, of the array.
|
||||
|
||||
Structure parameters are also straightforward to declare:
|
||||
|
||||
> *structure-type parametername* `= {` *expr0* `,` *expr1* ... `}`
|
||||
|
||||
where *structure-type* is the name of a previously-declared `struct` type, and
|
||||
the *expr* initializers correspond to each respective field within the
|
||||
structure. An initializer of appropriate type is required for every field of
|
||||
the structure.
|
||||
|
||||
### Shader output parameters
|
||||
|
||||
Shader parameters are, by default, read-only in the body of the
|
||||
shader. However, special \emph{output parameters} may be altered
|
||||
by execution of the shader. Parameters may be designated outputs
|
||||
by use of the {\cf output} keyword immediately prior to the
|
||||
type declaration of the parameter:
|
||||
|
||||
> `output` *type parametername* `=` *expr*
|
||||
|
||||
(Output parameters may be arrays and structures, but we will omit spelling out
|
||||
the obvious syntax here.)
|
||||
|
||||
Output parameters may be connected to inputs of later-run shader layers in the
|
||||
shader group, may be queried by later-run shaders in the group via message
|
||||
passing (i.e., `getmessage()` calls), or used by the renderer as an output
|
||||
image channel (in a manner described through the renderer's API).
|
||||
|
||||
### Shader parameter example
|
||||
|
||||
Here is an example of a shader declaration, with several parameters:
|
||||
|
||||
```
|
||||
surface wood (
|
||||
/* Simple params with constant initializers */
|
||||
float Kd = 0.5,
|
||||
color woodcolor = color (.7, .5, .3),
|
||||
string texturename = "wood.tx",
|
||||
/* Computed from an earlier parameter */
|
||||
color ringcolor = 0.25 * woodcolor,
|
||||
/* Fixed-length array */
|
||||
color paintcolors[3] = { color(0,.25,0.7), color(1,1,1),
|
||||
color(0.75,0.5,0.2) },
|
||||
/* variable-length array */
|
||||
int pattern[] = { 2, 4, 2, 1 },
|
||||
/* output parameter */
|
||||
output color Cunlit = 0
|
||||
)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### How shader parameters get their values
|
||||
|
||||
Shader parameters get their values in the following manner,
|
||||
in order of decreasing priority:
|
||||
|
||||
1. If the parameter has been designated by the renderer to be connected to an
|
||||
output parameter of a previously-executed shader layer within the shader
|
||||
group, that is the value it will get.
|
||||
2. If the parameter matches the name and type of a per-primitive, per-face, or
|
||||
per-vertex *primitive variable* on the particular piece of geometry
|
||||
being shaded, the parameter's value will be computed by interpolating the
|
||||
primitive variable for each position that must be shaded.
|
||||
3. If there is no connection or primitive variable, the parameter may will
|
||||
take on an *instance value*, if that parameter was given an explicit
|
||||
per-instance value at the time that the renderer referenced the shader
|
||||
(associating it with an object or set of objects).
|
||||
4. If none of these overrides is present, the parameter's value will be
|
||||
determined by executing the parameter initialization code in the shader.
|
||||
|
||||
This triage is performed per parameter, in order of declaration. So, for
|
||||
example, in the code sample above where the default value for `ringcolor1 is a
|
||||
scaled version of `woodcolor`, this relationship would hold whether
|
||||
`woodcolor` was the default, an instance value, an interpolated primitive
|
||||
value, or was connected to another layer's output. Unless `ringcolor` itself
|
||||
was given an instance, primitive, or connection value, in which case that's
|
||||
what would be used.
|
||||
|
||||
|
||||
|
||||
## Shader metadata
|
||||
|
||||
A shader may optionally include *metadata* (data *about* the
|
||||
shader, as opposed to data *used by* the shader). Metadata may be
|
||||
used to annotate the shader or any of its individual parameters with
|
||||
additional hints or information that will be compiled into the shader
|
||||
and may be queried by applications. A common use of metadata is to
|
||||
specify user interface hints about shader parameters --- for example,
|
||||
that a particular parameter should only take on integer values, should
|
||||
have an on/off checkbox, is intended to be a filename, etc.
|
||||
|
||||
Metadata is specified inside double brackets `[[` and `]]` enclosing a
|
||||
comma-separated list of metadata items. Each metadatum looks like a parameter
|
||||
declaration --- having a data type, name, and initializer. However, metadata
|
||||
may only be simple types or arrays of simple types (not structs or closures)
|
||||
and their value initializers must be numeric or string constants (not computed
|
||||
expressions).
|
||||
|
||||
Metadata about the shader as a whole is placed between the shader name
|
||||
and the parameter list. Metadata about shader parameters are placed
|
||||
immediately after the parameter's initializing expression, but before
|
||||
the comma or closing parentheses that terminates the parameter
|
||||
description.
|
||||
|
||||
Below is an example shader declaration showing the use of shader and
|
||||
parameter metadata:
|
||||
|
||||
```
|
||||
surface wood
|
||||
[[ string help = "Realistic wood shader" ]]
|
||||
(
|
||||
float Kd = 0.5
|
||||
[[ string help = "Diffuse reflectivity",
|
||||
float min = 0, float max = 1 ]] ,
|
||||
color woodcolor = color (.7, .5, .3)
|
||||
[[ string help = "Base color of the wood" ]],
|
||||
color ringcolor = 0.25 * woodcolor
|
||||
[[ string help = "Color of the dark rings" ]],
|
||||
string texturename = "wood.tx"
|
||||
[[ string help = "Texture map for the grain",
|
||||
string widget = "filename" ]],
|
||||
int pattern = 0
|
||||
[[ string widget = "mapper",
|
||||
string options = "oak:0|elm:1|walnut:2" ]]
|
||||
)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
The metadata are not semantically meaningful; that is, the metadata does
|
||||
not affect the actual execution of the shader. Most metadata exist only
|
||||
to be embedded in the compiled shader and able to be queried by other
|
||||
applications, such as to construct user interfaces for shader assignment
|
||||
that allow usage tips, appropriate kinds of widgets for setting each
|
||||
parameter, etc.
|
||||
|
||||
The choice of metadata and their meaning is completely up to the shader
|
||||
writer and/or modeling system. However, we propose some conventions
|
||||
below. These conventions are not intended to be comprehensive, nor to
|
||||
meet all your needs --- merely to establish a common nomenclature for
|
||||
the most common metadata uses.
|
||||
|
||||
The use of metadata is entirely optional on the part of the shader
|
||||
writer, and any application that queries shader metadata is free to
|
||||
honor or ignore any metadata it finds.
|
||||
|
||||
string label
|
||||
: A short label to be displayed in the UI for this parameter. If not
|
||||
present, the parameter name itself should be used as the widget label.
|
||||
|
||||
string help
|
||||
: Help text that describes the purpose and use of the shader or parameter.
|
||||
|
||||
string page
|
||||
: Helps to group related widgets by ``page.''
|
||||
|
||||
string widget
|
||||
: The type of widget that should be used to adjust this parameter.
|
||||
Suggested widget types:
|
||||
|
||||
"number"
|
||||
: Provide a slider and/or numeric input. This is the default widget type for
|
||||
`float` or `int` parameters. Numeric inputs also may be influenced by the
|
||||
following metadata: `min`, `max`, `sensitivity`, `digits`, `slider`,
|
||||
`slidermin`, `slidermax`, `slidercenter`, `sliderexponent`.
|
||||
|
||||
"string"
|
||||
: Provide a text entry widget. This is the default widget type for
|
||||
{\cf string} parameters.
|
||||
|
||||
"boolean"
|
||||
: Provide a pop-up menu with "Yes" and "No" options. Works on strings
|
||||
or numbers. With strings, "Yes" and "No" values are used, with
|
||||
numbers, 0 and 1 are used.
|
||||
|
||||
"checkBox"
|
||||
: A boolean widget displayed as a checkbox. Works on strings or
|
||||
numbers. With strings, "Yes" and "No" values are used, with numbers,
|
||||
0 and 1 are used.
|
||||
|
||||
"popup"
|
||||
: A pop-up menu of literal choices. This widget further requires
|
||||
parameter metadata `options` (a string listing the supported
|
||||
menu items, delimited by the `|` character), and optionally `editable`
|
||||
(an integer, which if nonzero means the widget should allow the
|
||||
text field should be directly editable). For example:
|
||||
```
|
||||
string wrap = "default"
|
||||
[[ string widget = "popup",
|
||||
string options = "default|black|clamp|periodic|mirror" ]]
|
||||
```
|
||||
|
||||
"mapper"
|
||||
: A pop-up with associative choices (an enumerated type, if the values are
|
||||
integers). This widget further requires parameter metadata `options`, a
|
||||
`|`-delimited string with "key:value" pairs. For example:
|
||||
```
|
||||
int pattern = 0
|
||||
[[ string widget = "mapper",
|
||||
string options = "oak:0|elm:1|walnut:2" ]]
|
||||
```
|
||||
|
||||
"filename"
|
||||
: A file selection dialog.
|
||||
|
||||
"null"
|
||||
: A hidden widget.
|
||||
|
||||
|
||||
float min, float max, int min, int max
|
||||
: The minimum and/or maximum value that the parameter may take on.
|
||||
|
||||
float sensitivity, int sensitivity
|
||||
: The precision or step size for incrementing or decrementing the value
|
||||
(within the appropriate min/max range).
|
||||
|
||||
int digits
|
||||
: The number of digits to show (-1 for full precision).
|
||||
|
||||
int slider
|
||||
: If nonzero, enables display of a slider sub-widget. This also respects the
|
||||
following additional metadata that control the slider specifically:
|
||||
`slidermin` (minimum value for the slider, `slidermax` (maximum value for
|
||||
the slider), `slidercenter` (origin value for the slider), `sliderexponent`
|
||||
(nonlinear slider options).
|
||||
|
||||
string URL
|
||||
: Provides a URL for full documentation of the shader or parameter.
|
||||
|
||||
string units
|
||||
: Gives the assumed units, if any, for the parameter (e.g., `cm`, `sec`,
|
||||
`degrees`). The compiler or renderer may issue a warning if it detects that
|
||||
this assumption is being violated (for example, the compiler can warn if a
|
||||
`degrees` variable is passed as the argument to `cos`).
|
||||
|
||||
|
||||
% We never implemented this:
|
||||
% ## Public methods
|
||||
%
|
||||
% Ordinary (non-public) functions inside a shader may be called only from
|
||||
% within the shader; they do not generate entry points that the renderer
|
||||
% is aware of.
|
||||
%
|
||||
% A *public method* is a function that may be directly called by the
|
||||
% renderer. Only top-level local functions of a shader --- that is,
|
||||
% declared within the braces that define the local scope of the shader,
|
||||
% but not within any other such function --- may be public methods. A
|
||||
% function may be designated a public method by using the `public`
|
||||
% keyword immediately before the function declaration:
|
||||
%
|
||||
% > *shader-type shader-name* `(` *params* `)` \
|
||||
% > `{` \
|
||||
% >
|
||||
% > `public` *return-type* *function-name* `(` *optional-parameters* `)` \
|
||||
% > `{` \
|
||||
% > *statements* \
|
||||
% > `}` \
|
||||
% >
|
||||
% > ...\\
|
||||
% > `}`
|
||||
|
||||
|
||||
% A given renderer will publish a list of public methods (names, arguments
|
||||
% expected, and return value) that has particular meaning for that
|
||||
% renderer. For example, a renderer may honor a public method
|
||||
% ```
|
||||
% public float maxdisplacement ()
|
||||
% ```
|
||||
% that computes and returns the maximum distance
|
||||
% that a displacement shader will move any surface points.
|
||||
|
||||
% At some later point, this spec will recommend several ``standard''
|
||||
% public methods that should be honored by most renderers.
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
..
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
|
||||
|
||||
.. image::
|
||||
../../ASWF/logos/openshadinglanguage-stacked-Shaded.png
|
||||
|
||||
|
||||
=============================================
|
||||
Open Shading Language |version| Documentation
|
||||
=============================================
|
||||
|
||||
.. only:: not latex
|
||||
|
||||
|
||||
|
||||
Editor: Larry Gritz, OSL Chief Architect
|
||||
|
||||
Open Shading Language (OSL) is a small but rich language for programmable
|
||||
shading in advanced renderers and other applications, ideal for describing
|
||||
materials, lights, displacement, and pattern generation.
|
||||
|
||||
Quick Links:
|
||||
`GitHub repository <https://github.com/AcademySoftwareFoundation/OpenShadingLanguage>`_ /
|
||||
`Developer mail list <https://lists.aswf.io/g/osl-dev>`_ /
|
||||
`BSD License <https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/blob/master/LICENSE.md>`_
|
||||
|
||||
|
||||
------------
|
||||
|
||||
.. default-role:: code
|
||||
|
||||
|
||||
.. only:: not latex
|
||||
|
||||
Contents
|
||||
--------
|
||||
|
||||
.. toctree::
|
||||
:caption: Introduction
|
||||
|
||||
copyr
|
||||
|
||||
.. toctree::
|
||||
:caption: The OSL Language Specification
|
||||
:maxdepth: 2
|
||||
:numbered: 2
|
||||
|
||||
intro
|
||||
bigpicture
|
||||
lexical
|
||||
grosssyntax
|
||||
datatypes
|
||||
syntax
|
||||
stdlib
|
||||
grammar
|
||||
shadergroups
|
||||
glossary
|
||||
|
||||
|
||||
.. comment
|
||||
This is where we would put additional documentation sections
|
||||
in the future.
|
||||
|
||||
|
||||
.. comment
|
||||
Helpful links when writing documentation:
|
||||
|
||||
Doxygen docs:
|
||||
http://www.doxygen.nl/manual/index.html
|
||||
Sphinx docs:
|
||||
http://www.sphinx-doc.org/en/master/contents.html
|
||||
http://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#cpp-domain
|
||||
Breathe docs:
|
||||
https://github.com/michaeljones/breathe
|
||||
https://breathe.readthedocs.io/en/latest/directives.html
|
||||
RST:
|
||||
|
||||
sphinx-tabs plugin for Sphinx:
|
||||
https://pypi.org/project/sphinx-tabs/
|
||||
https://sphinx-tabs.readthedocs.io/en/latest/#
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
<!--
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
-->
|
||||
|
||||
|
||||
(chap-introduction=)
|
||||
# Introduction
|
||||
|
||||
Welcome to Open Shading Language!
|
||||
|
||||
|
||||
Open Shading Language (OSL) is a small but rich language for
|
||||
programmable shading in advanced renderers and other applications, ideal
|
||||
for describing materials, lights, displacement, and pattern generation.
|
||||
|
||||
OSL was developed by Sony Pictures Imageworks for use in its in-house
|
||||
renderer used for feature film animation and visual effects. The
|
||||
language specification was developed with input by other visual effects
|
||||
and animation studios who also wish to use it.
|
||||
|
||||
OSL is distributed under the "New BSD" license. In short, you are free
|
||||
to use it in your own applications, whether they are free or commercial,
|
||||
open or proprietary, as well as to modify the OSL code as you desire,
|
||||
provided that you retain the original copyright notices as described in
|
||||
the license.
|
||||
|
||||
|
||||
#### How OSL is different from other shading languages
|
||||
|
||||
OSL has syntax similar to C, as well as other shading languages.
|
||||
However, it is specifically designed for advanced rendering algorithms
|
||||
and has features such as radiance closures, BSDFs, and deferred ray
|
||||
tracing as first-class concepts.
|
||||
|
||||
OSL has several unique characteristics not found in other shading
|
||||
languages (certainly not all together). Here are some things you will
|
||||
find are different in OSL compared to other languages:
|
||||
|
||||
* **Surface and volume shaders compute radiance closures, not final colors.**
|
||||
|
||||
OSL's surface and volume shaders compute an explicit symbolic
|
||||
description, called a "closure," of the way a surface or volume
|
||||
scatters light, in units of radiance. These radiance closures may be
|
||||
evaluated in particular directions, sampled to find important
|
||||
directions, or saved for later evaluation and re-evaluation.
|
||||
This new approach is ideal for a physically-based renderer that
|
||||
supports ray tracing and global illumination.
|
||||
|
||||
In contrast, other shading languages usually compute just a surface
|
||||
color as visible from a particular direction. These old shaders are
|
||||
"black boxes" that a renderer can do little with but execute to for
|
||||
this once piece of information (for example, there is no effective way
|
||||
to discover from them which directions are important to sample).
|
||||
Furthermore, the physical units of lights and surfaces are often
|
||||
underspecified, making it very difficult to ensure that shaders are
|
||||
behaving in a physically correct manner.
|
||||
|
||||
* **Surface and volume shaders do not loop over lights or shoot rays.**
|
||||
|
||||
There are no "light loops" or explicitly traced rays in OSL surface
|
||||
shaders. Instead, surface shaders compute a radiance closure
|
||||
describing how the surface scatters light, and a part of the renderer
|
||||
called an "integrator" evaluates the closures for a particular set of
|
||||
light sources and determines in which directions rays should be
|
||||
traced. Effects that would ordinarily require explicit ray tracing,
|
||||
such as reflection and refraction, are simply part of the radiance
|
||||
closure and look like any other BSDF.
|
||||
|
||||
Advantages of this approach include that integration and sampling may
|
||||
be batched or re-ordered to increase ray coherence; a "ray budget" can
|
||||
be allocated to optimally sample the BSDF; the closures may be used by
|
||||
for bidirectional ray tracing or Metropolis light transport; and the
|
||||
closures may be rapidly re-evaluated with new lighting without having
|
||||
to re-run the shaders.
|
||||
|
||||
* **Surface and light shaders are the same thing.**
|
||||
|
||||
OSL does not have a separate kind of shader for light sources. Lights
|
||||
are simply surfaces that are emissive, and all lights are area lights.
|
||||
|
||||
* **Transparency is just another kind of illumination.**
|
||||
|
||||
You don't need to explicitly set transparency/opacity variables in the
|
||||
shader. Transparency is just another way for light to interact with a
|
||||
surface, and is included in the main radiance closure computed by a
|
||||
surface shader.
|
||||
|
||||
* **Renderer outputs (AOV's) are specified using "light path expressions."**
|
||||
|
||||
Sometimes it is desirable to output images containing individual
|
||||
lighting components such as specular, diffuse, reflection, individual
|
||||
lights, etc. In other languages, this is usually accomplished by
|
||||
adding a plethora of "output variables" to the shaders that collect
|
||||
these individual quantities.
|
||||
|
||||
OSL shaders need not be cluttered with any code or output variables to
|
||||
accomplish this. Instead, there is a regular-expression-based
|
||||
notation for describing which light paths should contribute to which
|
||||
outputs. This is all done on the renderer side (though supported by
|
||||
the OSL implementation). If you desire a new output, there is no need
|
||||
to modify the shaders at all; you only need to tell the renderer the
|
||||
new light path expression.
|
||||
|
||||
* **Shaders are organized into networks.**
|
||||
|
||||
OSL shaders are not monolithic, but rather can be organized into
|
||||
networks of shaders (sometimes called a shader group, graph, or DAG),
|
||||
with named outputs of some nodes being connected to named inputs of
|
||||
other nodes within the network. These connections may be done
|
||||
dynamically at render time, and do not affect compilation of
|
||||
individual shader nodes. Furthermore, the individual nodes are
|
||||
evaluated lazily, only their outputs are "pulled" from the later nodes
|
||||
that depend on them (shader writers may remain blissfully unaware of
|
||||
these details, and write shaders as if everything is evaluated
|
||||
normally).
|
||||
|
||||
* **No "uniform" and "varying" keywords in the language.**
|
||||
|
||||
OSL shaders are evaluated in SIMD fashion, executing shaders on many
|
||||
points at once, but there is no need to burden shader writers with
|
||||
declaring which variables need to be uniform or varying.
|
||||
|
||||
In the open source OSL implementation, this is done both automatically
|
||||
and dynamically, meaning that a variable can switch back and forth
|
||||
between uniform and varying, on an instruction-by-instruction basis,
|
||||
depending on what is assigned to it.
|
||||
|
||||
* **Arbitrary derivatives without grids or extra shading points.**
|
||||
|
||||
In OSL, you can take derivatives of any computed quantity in a shader,
|
||||
and use arbitrary quantities as texture coordinates and expect correct
|
||||
filtering. This does not require that shaded points be arranged in a
|
||||
rectangular grid, or have any particular connectivity, or that any
|
||||
"extra points" be shaded.
|
||||
|
||||
In the open source OSL implementation, this is possible because
|
||||
derivatives are not computed by finite differences with neighboring
|
||||
points, but rather by "automatic differentiation," computing partial
|
||||
differentials for the variables that lead to derivatives, without any
|
||||
intervention required by the shader writer.
|
||||
|
||||
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
The original designer and project leader of OSL is Larry Gritz. Other early
|
||||
developers of OSL are (in order of joining the project): Cliff Stein, Chris
|
||||
Kulla, Alejandro Conty, Jay Reynolds, Solomon Boulos, Adam Martinez, Brecht
|
||||
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
|
||||
alphabetically; if we've left anybody out, please let us know.)
|
||||
|
||||
We cannot possibly express sufficient gratitude to the managers at Sony
|
||||
Pictures Imageworks who allowed this project to proceed, supported it
|
||||
wholeheartedly, and permitted us to release the source, especially Rob
|
||||
Bredow, Brian Keeney, Barbara Ford, Rene Limberger, and Erik Strauss.
|
||||
|
||||
Huge thanks also go to the crack shading team at SPI, and the brave
|
||||
lookdev TDs and CG supes willing to use OSL on their shows. They served
|
||||
as our guinea pigs, inspiration, testers, and a fantastic source of
|
||||
feedback. Thank you, and we hope we've been responsive to your needs.
|
||||
|
||||
OSL was not developed in isolation. We owe a debt to the individuals
|
||||
and studios who patiently read early drafts of the language
|
||||
specification and gave us very helpful feedback and additional ideas,
|
||||
and especially to those at other companies who have taken the risk of
|
||||
incorporating OSL into their products and pipelines.
|
||||
|
||||
The open source OSL implementation incorporates or depends upon several
|
||||
other open source packages:
|
||||
|
||||
- **OpenImageIO** Copyright Contributors to OpenImageIO.
|
||||
http://openimageio.org
|
||||
- **Imath** Copyright Contributors to Imath.
|
||||
http://www.openexr.com
|
||||
- **Boost** Copyright various authors. http://www.boost.org
|
||||
- **LLVM** Copyright 2003-2010 University of Illinois at
|
||||
Urbana-Champaign. http://llvm.org
|
||||
|
||||
These other packages are all distributed under licenses that allow them
|
||||
to be used by and distributed with OSL.
|
||||
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
|
||||
\def\langname{Open Shading Language\xspace}
|
||||
\def\product{{\sffamily Open Shading Language}\xspace}
|
||||
\def\versionnumber{1.12}
|
||||
\def\versionnumber{1.13}
|
||||
\def\productver{\product\ {\sffamily \versionnumber}\xspace}
|
||||
|
||||
|
||||
@@ -59,14 +59,14 @@
|
||||
Language Specification
|
||||
} \bigskip }
|
||||
\author{
|
||||
\copyright\ Copyright 2009-present Contributors to the Open Shading Language project. \\
|
||||
\copyright\ Copyright Contributors to the Open Shading Language project. \\
|
||||
All rights reserved.
|
||||
\bigskip \\
|
||||
\vspace{1in} \\
|
||||
Editor: Larry Gritz \\
|
||||
\emph{lg@imageworks.com}
|
||||
}
|
||||
\date{{\large Date: 27 Aug 2022 \\
|
||||
\date{{\large Date: 27 Oct 2023 \\
|
||||
% (with corrections, 24 Nov 2021)
|
||||
}
|
||||
\bigskip
|
||||
@@ -135,7 +135,7 @@ documentation are:
|
||||
|
||||
\vspace*{0.2in}
|
||||
|
||||
Copyright \textcopyright\ 2009-present, Contributors to the Open Shading
|
||||
Copyright \textcopyright\ Contributors to the Open Shading
|
||||
Language project. All Rights Reserved.
|
||||
|
||||
\vspace{0.5in}
|
||||
@@ -380,9 +380,9 @@ The open source OSL implementation incorporates or depends upon several
|
||||
other open source packages:
|
||||
|
||||
\begin{itemize}
|
||||
\item {\cf OpenImageIO} \copyright\ 2008 Larry Gritz et al.
|
||||
\item {\cf OpenImageIO} \copyright\ Contributors to OpenImageIO
|
||||
\url{http://openimageio.org}
|
||||
\item Ilmbase \copyright\ 2006, Industrial Light \& Magic.
|
||||
\item Imath \copyright\ Contributors to Imath.
|
||||
\url{http://www.openexr.com}
|
||||
\item Boost \copyright\ various authors. \url{http://www.boost.org}
|
||||
\item LLVM \copyright\ 2003-2010 University of Illinois at
|
||||
@@ -2631,27 +2631,6 @@ and proceeds to the next iteration of the loop.
|
||||
\section{Functions}
|
||||
\label{sec:functions}
|
||||
|
||||
\subsection{Function calls}
|
||||
\label{sec:syntax:functioncalls}
|
||||
\index{function calls}
|
||||
|
||||
Function calls are very similar to C and related programming languages:
|
||||
|
||||
\begin{tabbing}
|
||||
\hspace{0.5in} \= \hspace{0.3in} \= \kill
|
||||
\> \emph{functionname} {\cf (} \emph{arg1} {\cf ,} ... {\cf ,} \emph{argn} {\cf )} \\
|
||||
\end{tabbing}
|
||||
|
||||
If the function returns a value (not \void), you may use its value as
|
||||
an expression. It is fine to completely ignore the value of even
|
||||
a non-\void function.
|
||||
|
||||
In \langname, all arguments are passed by reference. This generally
|
||||
will not be noticeably different from C-style ``pass by value''
|
||||
semantics, except if you pass the same variable as two separate
|
||||
arguments to a function that modifies an argument's value.
|
||||
|
||||
|
||||
\subsection{Function definitions}
|
||||
\label{sec:syntax:functiondefinitions}
|
||||
\index{functions!definitions}
|
||||
@@ -2699,6 +2678,35 @@ 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{Function calls}
|
||||
\label{sec:syntax:functioncalls}
|
||||
\index{function calls}
|
||||
|
||||
Function calls are very similar to C and related programming languages:
|
||||
|
||||
\begin{tabbing}
|
||||
\hspace{0.5in} \= \hspace{0.3in} \= \kill
|
||||
\> \emph{functionname} {\cf (} \emph{arg1} {\cf ,} ... {\cf ,} \emph{argn} {\cf )} \\
|
||||
\end{tabbing}
|
||||
|
||||
If the function returns a value (not \void), you may use its value as
|
||||
an expression. It is fine to completely ignore the value of even
|
||||
a non-\void function.
|
||||
|
||||
In \langname, all arguments are passed by reference. This generally
|
||||
will not be noticeably different from C-style ``pass by value''
|
||||
semantics, except if you pass the same variable as two separate
|
||||
arguments to a function that modifies an argument's value.
|
||||
|
||||
Certain functions allow optional arguments to be passed.
|
||||
Optional arguments are key-value pairs with the key passed as an
|
||||
argument and the associated value passed as the subsequent argument:
|
||||
|
||||
\begin{tabbing}
|
||||
\hspace{0.5in} \= \hspace{0.3in} \= \kill
|
||||
\> \emph{functionname} {\cf (} \emph{arg1} {\cf ,} ... {\cf ,} \emph{argn} {\cf ,} \emph{"optionalkey"} {\cf ,} \emph{optionalvalue} {\cf ,} ... {\cf )} \\
|
||||
\end{tabbing}
|
||||
|
||||
\subsection{Operator overloading}
|
||||
\label{sec:syntax:operatoroverloading}
|
||||
\index{operator overloading}
|
||||
@@ -4083,8 +4091,8 @@ 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
|
||||
channels.
|
||||
|
||||
The 2D lookup coordinate(s) may be followed by optional token/value
|
||||
arguments that control the behavior of {\cf texture()}:
|
||||
The 2D lookup coordinate(s) may be followed by optional key-value
|
||||
arguments (see Section~\ref{sec:syntax:functioncalls}) that control the behavior of {\cf texture()}:
|
||||
|
||||
\apiitem{"blur", <float>}
|
||||
\vspace{12pt}
|
||||
@@ -5599,7 +5607,7 @@ forms of the function with no object name, or if the object name is the
|
||||
empty string \qkw{}, the renderer will first search
|
||||
per-object attributes on the current object (or interpolated variables
|
||||
with that name attached to the object), then if not found it will search
|
||||
searching global scene-wide attributes.
|
||||
global scene-wide attributes.
|
||||
|
||||
If the attribute is found and can be converted to the type of
|
||||
\emph{destination}, the attribute's value will be stored in
|
||||
@@ -5901,17 +5909,38 @@ view-dependence into shaders.
|
||||
The return value is 0 if the ray missed all geometry, 1 if it hit
|
||||
anything within the distance range.
|
||||
|
||||
Optional parameters include:
|
||||
The following optional key-value arguments
|
||||
(see Section~\ref{sec:syntax:functioncalls}) can be passed:
|
||||
|
||||
\begin{tabular}{p{1.2in} p{0.5in} p{3.2in}}
|
||||
\qkw{mindist} & {\cf float} & Minimum hit distance (default: zero) \\
|
||||
\qkw{maxdist} & {\cf float} & Maximum hit distance (default: infinite) \\
|
||||
\qkw{shade} & {\cf int} & Whether objects hit will be shaded
|
||||
(default: 0) \\
|
||||
\qkw{traceset} & {\cf string} & An optional named set of objects to
|
||||
ray trace (if preceded by a `{\cf -}'
|
||||
character, it means to exclude that set).
|
||||
\end{tabular}
|
||||
\apiitem{"mindist", <float>}
|
||||
\vspace{12pt}
|
||||
The minimum hit distance (default: 0).
|
||||
|
||||
The units of the {\cf "mindist"} and {\cf "maxdist"} are determined by the renderer
|
||||
and are sometimes defined by the dir vector, which can lead to unexpected
|
||||
behavior. So, generally, clearly written and portable shaders should pass
|
||||
a unit length (see Section~\ref{sec:stdlib:geom}) dir vector.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{"mindist", <float>}
|
||||
\vspace{12pt}
|
||||
The maximum hit distance (default: infinite).
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{"shade", <int>}
|
||||
\vspace{12pt}
|
||||
Defines whether objects hit will be shaded (default: 0).
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{"traceset", <string>}
|
||||
\vspace{12pt}
|
||||
An optional named set of objects to ray trace (if preceded by a `{\cf -}'
|
||||
character, it means to exclude that set).
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
Information about the closest object hit by the ray may be retrieved
|
||||
using \\ {\cf getmessage("trace",...)} (see Section~\ref{sec:getmessage}).
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
# Lexical structure
|
||||
|
||||
## Characters
|
||||
|
||||
Source code for OSL consists of ASCII or UTF-8 characters.
|
||||
|
||||
The characters for space, tab, carriage return, and linefeed are
|
||||
collectively referred to as *whitespace*. Whitespace characters
|
||||
delimit identifiers, keywords, or other symbols, but other than that
|
||||
have no syntactic meaning. Multiple whitespace characters in a row
|
||||
are equivalent to a single whitespace character.
|
||||
|
||||
Source code may be split into multiple lines, separated by end-of-line
|
||||
markers (carriage return and/or linefeed). Lines may be of any length
|
||||
and end-of-line markers carry no significant difference from other
|
||||
whitespace, except that they terminate `//` comments and delimit
|
||||
preprocessor directives.
|
||||
|
||||
## Identifiers
|
||||
|
||||
*Identifiers* are the names of variables, parameters, functions, and shaders.
|
||||
In OSL, identifiers consist of one or more characters. The first character
|
||||
may be a letter (`A`-`Z` or `a`-`z`) or underscore (`_`), and subsequent
|
||||
characters may be letters, underscore, or numerals (`0`-`9`). Examples of
|
||||
valid and invalid identifiers are:
|
||||
|
||||
```
|
||||
opacity // valid
|
||||
Long_name42 // valid - letters, underscores, numbers are ok
|
||||
_foo // valid - ok to start with an underscore
|
||||
|
||||
2smart // invalid - starts with a numeral
|
||||
bigbuck$ // invalid - $ is an illegal character
|
||||
```
|
||||
|
||||
|
||||
## Comments
|
||||
|
||||
*Comments* are text that are for the human reader of programs, and
|
||||
are ignored entirely by the OSL compiler. Just like in C++, there
|
||||
are two ways to designate comments in OSL:
|
||||
|
||||
1. Any text enclosed by `/*` and `*/` will be considered a comment, even if
|
||||
the comment spans several lines.
|
||||
|
||||
```
|
||||
/* this is a comment */
|
||||
|
||||
/* this is also
|
||||
a comment, spanning
|
||||
several lines */
|
||||
```
|
||||
|
||||
2. Any text following `//`, up to the end of the current line, will be
|
||||
considered a comment.
|
||||
|
||||
```
|
||||
// This is a comment
|
||||
a = 3; // another comment
|
||||
```
|
||||
|
||||
|
||||
## Keywords and reserved words
|
||||
|
||||
There are two sets of names that you may not use as identifiers:
|
||||
keywords and reserved words.
|
||||
|
||||
The following are *keywords* that have special meaning in OSL:
|
||||
|
||||
and break closure color continue do else emit float for if illuminance
|
||||
illuminate int matrix normal not or output point public return string
|
||||
struct vector void while
|
||||
|
||||
The following are *reserved words* that currently have no special meaning in
|
||||
OSL, but we reserve them for possible future use, or because they are
|
||||
confusingly similar to keywords in related programming languages:
|
||||
|
||||
bool case catch char class const delete default double
|
||||
enum extern false friend
|
||||
goto inline long new operator private protected
|
||||
short signed sizeof static
|
||||
switch template this throw true try typedef
|
||||
uniform union unsigned varying virtual volatile
|
||||
|
||||
|
||||
## Preprocessor
|
||||
|
||||
Shader source code is passed through a standard C preprocessor as a
|
||||
first step in parsing.
|
||||
|
||||
Preprocessor directives are designated by a hash mark `#` as the first
|
||||
character on a line, followed by a preprocessor directive name. Whitespace may
|
||||
optionally appear between the hash and the directive name.
|
||||
|
||||
OSL compilers support the full complement of C/C++ preprocessing directives,
|
||||
including:
|
||||
|
||||
```
|
||||
#define
|
||||
#undef
|
||||
#if
|
||||
#ifdef
|
||||
#ifndef
|
||||
#elif
|
||||
#else
|
||||
#endif
|
||||
#include
|
||||
#pragma error "message"
|
||||
#pragma once
|
||||
#pragma osl ...
|
||||
#pragma warning "message"
|
||||
```
|
||||
|
||||
Additionally, the following preprocessor symbols will already be
|
||||
defined by the compiler:
|
||||
|
||||
| | |
|
||||
| ------ | :------- |
|
||||
| `OSL_VERSION_MAJOR` | Major version (e.g., 1) |
|
||||
| `OSL_VERSION_MINOR` | Minor version (e.g., 9) |
|
||||
| `OSL_VERSION_PATCH` | Patch version (e.g., 3) |
|
||||
| `OSL_VERSION` | Combined version number = `10000*major + 100*minor + patch` (e.g., 10903 for version 1.9.3) |
|
||||
@@ -0,0 +1,6 @@
|
||||
sphinx >= 5.0
|
||||
breathe == 4.34.0
|
||||
sphinx-tabs
|
||||
furo==2022.6.21
|
||||
myst-parser
|
||||
linkify
|
||||
@@ -0,0 +1,100 @@
|
||||
---
|
||||
numbering:
|
||||
heading_1: true
|
||||
heading_2: true
|
||||
heading_3: true
|
||||
---
|
||||
|
||||
<!--
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
-->
|
||||
|
||||
|
||||
(chap-shader-groups)=
|
||||
# Describing shader groups
|
||||
|
||||
Below, we propose a simple grammar giving a standard way to serialize (i.e.,
|
||||
express as text) a full shader group, including instance values and
|
||||
connectivity of the shader layers. There are only three statements/operations:
|
||||
set an instance value, make a shader instance, and connect two instances.
|
||||
|
||||
**`param`** *`type paramname value`*... **`;`** <br> **`param`** *`type paramname value`*... **`[[`** *`metadata`*... **`]] ;`**
|
||||
|
||||
: Declare an instance value of a shader parameter to be applied to the next
|
||||
`shader` statement. We refer to the parameter values set, which have not
|
||||
yet had their shader declared, as *pending parameters*.
|
||||
|
||||
The *`paramname`* is the name of the parameter whose instance values are
|
||||
being specified.
|
||||
|
||||
The *`type`* is one of the basic numeric or string data types described in
|
||||
Chapter [](#chap-types) (`int`, `float`,`color`, `point`, `vector`, `normal`,
|
||||
`matrix`, or `string`), or an array thereof (indicated by the usual notation
|
||||
of `[size]`). The *`type`* must match the declared type of the parameter in
|
||||
the shader.
|
||||
|
||||
The actual values are listed individually, with multiple values (in the
|
||||
case of an array or an aggregate such as a `color`) simply separated by
|
||||
whitespace. If fewer values are supplied than the total number of array
|
||||
elements or aggregate components, the remainder will be understood to be
|
||||
filled with 0 values. String values must be enclosed in double quotes
|
||||
(`"like this"`).
|
||||
|
||||
The `param` statement is terminated by a semicolon (`;`).
|
||||
|
||||
Optionally, metadata hints may be supplied enclosed by double brackets,
|
||||
immediately before the semicolon.
|
||||
|
||||
|
||||
**`shader`** *`shadername layername`* **`;`**
|
||||
|
||||
: Declares a shader instance, which will receive any pending parameters that
|
||||
were declared since the previous `shader` statement (and in the process,
|
||||
clear the list of pending parameters).
|
||||
|
||||
The `shadername` is an identifier that specifies the name of the shader
|
||||
to use as the master for this instance. The `layername` is an identifier
|
||||
that names the layer (e.g., to subsequently specify it as a source or
|
||||
destination for connections).
|
||||
|
||||
The `shader` statement is terminated by a semicolon (`;`).
|
||||
|
||||
|
||||
**`connect`** *`source_layername`* **`.`** *`paramname`* $~~$ *` destination_layername`* **`.`** *`paramname`* **`;`**
|
||||
|
||||
: Establish a connection between an output parameter of a source layer and an
|
||||
input parameter of a destination layer, both of which have been previously
|
||||
declared within this group. The source layer must have preceded the
|
||||
destination layer when they were declared, and the parameters must exist and
|
||||
be of a compatible type so that it is meaningful to establish a connection
|
||||
(for example, you may connect a `color` to a `color`, but you may not connect
|
||||
a `color` to a `matrix`).
|
||||
|
||||
If the named parameters are structures, the two structures must have
|
||||
identical data layout, and establishing the connection will connect each
|
||||
corresponding data member. It is also possible to make a connection of just
|
||||
a single member of a structure by using the usual ``dot'' syntax, for
|
||||
example, for layers `A` and `B`, `connect A.c.x B.y` might
|
||||
connect A's parameter `c`, member `x`, to B's parameter `y` (the
|
||||
types of `c.x` in A and `y` in B must match).
|
||||
|
||||
The `connect` statement is terminated by a semicolon (`;`).
|
||||
|
||||
**Example**
|
||||
|
||||
param string name "rings.tx" ; # set pending `name'
|
||||
param float scale 3.5 ; # set pending `scale'
|
||||
shader "texturemap" "tex1" ; # tex1 layer, picks up `name', `scale'
|
||||
param string name "grain.tx" ;
|
||||
shader "texturemap" "tex2" ;
|
||||
param float gam 2.2 ;
|
||||
shader "gamma" "gam1" ;
|
||||
param float gam 1.0 ;
|
||||
shader "gamma" "gam2" ;
|
||||
param color woodcolor 0.42 0.38 0.22 ; # example of a color param
|
||||
shader "wood" "wood1" ;
|
||||
connect tex1.Cout gam1.Cin ; # connect tex1's Cout to gam1's Cin
|
||||
connect tex2.Cout gam2.Cin ;
|
||||
connect gam1.Cout wood1.rings ;
|
||||
connect gam2.Cout wood1.grain ;
|
||||
@@ -0,0 +1,566 @@
|
||||
---
|
||||
numbering:
|
||||
heading_1: true
|
||||
heading_2: true
|
||||
heading_3: true
|
||||
---
|
||||
|
||||
<!--
|
||||
Copyright Contributors to the Open Shading Language project.
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
-->
|
||||
|
||||
|
||||
(chap-syntax)=
|
||||
# Language Syntax
|
||||
|
||||
The body of a shader is a sequence of individual *statements*.
|
||||
This chapter describes the types of statements and control-flow patterns
|
||||
in OSL.
|
||||
|
||||
Statements in OSL include the following types of constructs:
|
||||
|
||||
* Scoped statements.
|
||||
* Variable declarations.
|
||||
* Expressions.
|
||||
* Assignments.
|
||||
* Control flow: `if`, `else`, `while`, `do`, `for`, `break`, `continue`
|
||||
* Function declarations.
|
||||
|
||||
#### Scoping
|
||||
|
||||
Any place where it is legal to have a statement, it is legal to have multiple
|
||||
statements enclosed by curly braces `{ }`. This is called a *scope*. Any
|
||||
variables or functions declared within a scope are only visible within that
|
||||
scope, and only may be used after their declaration. Variables or functions
|
||||
that are referenced will always resolve to the matching name in the innermost
|
||||
scope relative to its use. For example
|
||||
|
||||
```
|
||||
float a = 1; // Call this the "outer" 'a'
|
||||
float b = 2;
|
||||
{
|
||||
float a = 3; // Call this the "inner" 'a'
|
||||
float c = 1;
|
||||
b = a; // b gets 3, because a is resolved to the inner scope
|
||||
}
|
||||
b += c; // ERROR -- c was only in the inner scope
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Variable declarations and assignments
|
||||
|
||||
### Variable declarations
|
||||
|
||||
The syntax for declaring a variable in OSL is:
|
||||
|
||||
> *type* *name*
|
||||
>
|
||||
> *type* *name* `=` *value*
|
||||
|
||||
where
|
||||
|
||||
* *type* is one of the basic data types, described earlier.
|
||||
* *name* is the name of the variable you are declaring.
|
||||
* If you wish to initialize your variable an initial value, you may
|
||||
immediately assign it a *value*, which may be any valid expression.
|
||||
|
||||
You may declare several variables of the same type in a single
|
||||
declaration by separating multiple variable names by commas:
|
||||
|
||||
> *type* *name1* `,` *name2* ...
|
||||
>
|
||||
> *type* *name1* [ = *value1*] `,` *name2* [ `=` *value2* ] ...
|
||||
|
||||
|
||||
Some examples of variable declarations are
|
||||
|
||||
```
|
||||
float a; // Declare; current value is undefined
|
||||
float b = 1; // Declare and assign a constant initializer
|
||||
float c = a*b; // Computed initializer
|
||||
float d, e = 2, f; // Declare several variables of the same type
|
||||
```
|
||||
|
||||
### Arrays
|
||||
|
||||
Arrays are also supported, declared as follows:
|
||||
|
||||
> *type variablename* `[` *arraylen* `}`
|
||||
>
|
||||
> *type variablename* `[` *arraylen* `}` `=` `{` *init0 `,` *init1* ... `}`
|
||||
|
||||
Array variables in OSL must have a constant length (though function parameters
|
||||
and shader parameters may have undetermined length). Some examples of array
|
||||
variable declarations are:
|
||||
|
||||
```
|
||||
float d[10]; // Declare an uninitialized array
|
||||
float c[3] = { 0.1, 0.2, 3.14 }; // Initialize the array
|
||||
```
|
||||
|
||||
### Structures
|
||||
|
||||
Structures are used to group several fields of potentially different
|
||||
types into a single object that can be referred to by name. The syntax
|
||||
for declaring a structure type is:
|
||||
|
||||
\spc `struct` *structname* {\cf \{}
|
||||
|
||||
\spc\spc *type1* *fieldname1* `;`
|
||||
|
||||
\spc\spc ...
|
||||
|
||||
\spc\spc *typeN* *fieldnameN* `;`
|
||||
|
||||
\spc `) ;`
|
||||
|
||||
You may then use the structure type name to declare structure variables
|
||||
as you would for any of the built-in types:
|
||||
|
||||
\spc *structname* *variablename* `;`
|
||||
|
||||
\spc *structname* *variablename* {\cf = \{ }
|
||||
*initializer1* `,` ... *initializerN* `) ;`
|
||||
|
||||
If initializers are supplied, each field of the structure will be
|
||||
initialized with the initializer in the corresponding position, which
|
||||
is expected to be of the appropriate type.
|
||||
|
||||
Structure elements are accessed in the same way as other C-like
|
||||
languages, using the `dot' operator:
|
||||
|
||||
\spc *variablename*{\cf .} *fieldname*
|
||||
|
||||
Examples of declaration and use of structures:
|
||||
|
||||
```
|
||||
struct ray {
|
||||
point pos;
|
||||
vector dir;
|
||||
};
|
||||
|
||||
ray r; // Declare a structure
|
||||
ray s = { point(0,0,0), vector(0,0,1) }; // declare and initialize
|
||||
r.pos = point (1, 0, 0); // Assign to one field
|
||||
```
|
||||
|
||||
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 permitted for one
|
||||
structure to have a field that is another structure.
|
||||
|
||||
Please refer to Section~\ref{sec:types:struct} for more information
|
||||
on using `struct`.
|
||||
|
||||
|
||||
(sec-expressions)=
|
||||
## Expressions
|
||||
|
||||
The expressions available in OSL include the following:
|
||||
|
||||
* Constants: integer (e.g., `1`, `42`), floating-point (e.g. `1.0`, `3`,
|
||||
`-2.35e4`), or string literals (e.g., `"hello"`)
|
||||
|
||||
* point, vector, normal, or matrix constructors, for example:
|
||||
|
||||
```
|
||||
color (1, 0.75, 0.5)
|
||||
point ("object", 1, 2, 3)
|
||||
```
|
||||
|
||||
If all the arguments to a constructor are themselves constants, the
|
||||
constructed point is treated like a constant and has no runtime cost.
|
||||
That is, `color(1,2,3)` is treated as a single constant entity, not
|
||||
assembled bit by bit at runtime.
|
||||
|
||||
* Variable or parameter references
|
||||
|
||||
* An individual element of an array (using `[ ]`)
|
||||
|
||||
* An individual component of a `color`, `point`, `vector`, `normal` (using
|
||||
`[ ]`), or of a `matrix` (using `[][]`)
|
||||
|
||||
* prefix and postfix increment and decrement operators:
|
||||
|
||||
Operator | Meaning
|
||||
:-- | :--
|
||||
*varref* `++` | post-increment
|
||||
*varref* `--` | post-decrement
|
||||
`++` *varref* | pre-increment
|
||||
`--` *varref* | pre-decrement
|
||||
|
||||
The post-increment and post-decrement (e.g., {\cf a++}) returns the old
|
||||
value, then increments or decrements the variable; the pre-increment and
|
||||
pre-decrement ({\cf ++a}) will first increment or decrement the
|
||||
variable, then return the new value.
|
||||
|
||||
* Unary and binary arithmetic operators on other expressions:
|
||||
|
||||
Operator | Meaning
|
||||
:-- | :--
|
||||
`-` *expr* | negation
|
||||
`~` *expr* | bitwise complement
|
||||
*expr* `*` *expr* | multiplication
|
||||
*expr* `/` *expr* | division
|
||||
*expr* `+` *expr* | addition
|
||||
*expr* `-` *expr* | subtraction
|
||||
*expr* `%` *expr* | integer modulus
|
||||
*expr* `<<` *expr* | integer shift left
|
||||
*expr* `>>` *expr* | integer shift right
|
||||
*expr* `&` *expr* | bitwise and
|
||||
*expr* `\|` *expr* | bitwise or
|
||||
*expr* `^` *expr* | bitwise exclusive or
|
||||
|
||||
The operators `+`, `-`, `*`, `/`, and the unary `-` (negation) may be used
|
||||
on most of the numeric types. For multicomponent types (`color`, `point`,
|
||||
`vector`, `normal`, `matrix`), these operators combine their arguments on a
|
||||
component-by-component basis. The only operators that may be applied to the
|
||||
`matrix` type are `*` and `/`, which respectively denote matrix-matrix
|
||||
multiplication and matrix multiplication by the inverse of another matrix.
|
||||
|
||||
The integer and bit-wise operators `%`, `<<`, `>>`, `&`, `|`, `^`, and `~`
|
||||
may only be used with expressions of type `int`.
|
||||
|
||||
For details on which operators are allowed, please consult the operator
|
||||
tables for each individual type in Chapter [](#chap-types).
|
||||
|
||||
* Relational operators (all lower precedence than the arithmetic operators):
|
||||
|
||||
Operator | Meaning
|
||||
:-- | :--
|
||||
*expr* `==` *expr* | equal to
|
||||
*expr* `!=` *expr* | not equal to
|
||||
*expr* `<` *expr* | less then
|
||||
*expr* `<=` *expr* | less than or equal to
|
||||
*expr* `>` *expr* | greater than
|
||||
*expr* `>=` *expr* | greater than or equal
|
||||
|
||||
The `==` and `!=` operators may be performed between any two values of equal
|
||||
type, and are performed component-by-component for multi-component types.
|
||||
The `<`, `<=`, `>`, `>=` may not be used to compare multi-component types.
|
||||
|
||||
An `int` expression may be compared to a `float` (and is treated as if
|
||||
they are both `float`). A `float` expression may be compared to a
|
||||
multi-component type (and is treated as a multi-component type as if
|
||||
constructed from a single float).
|
||||
|
||||
Relation comparisons produce Boolean (true/false) values. These
|
||||
are implemented as `int` values, 0 if false and 1 if true.
|
||||
|
||||
* Logical unary and binary operators:
|
||||
|
||||
> `!` *expr*
|
||||
> *expr1* `&&` *expr2*
|
||||
> *expr1* `\|\|` *expr2*
|
||||
|
||||
Note that the `not`, `and`, and `or` keywords are synonyms for `!`, `&&`,
|
||||
and `||`, respectively.
|
||||
|
||||
For the logical operators, numeric expressions (`int` or `float`) are
|
||||
considered *true* if nonzero, *false* if zero. Multi-component types (such
|
||||
as `color`) are considered *true* any component is nonzero, *false* all
|
||||
components are zero. Strings are considered *true* if they are nonempty,
|
||||
*false* if they are the empty string (`""`).
|
||||
|
||||
* another expression enclosed in parentheses: `( )`. Parentheses may be used
|
||||
to guarantee associativity of operations.
|
||||
|
||||
* Type casts, specified either by having the type name in parentheses in front
|
||||
of the value to cast (C-style typecasts) or the type name called as a
|
||||
constructor (C++-style type constructors):
|
||||
|
||||
```
|
||||
(vector) P /* cast a point to a vector */
|
||||
(point) f /* cast a float to a point */
|
||||
(color) P /* cast a point to a color! */
|
||||
|
||||
vector (P) /* Means the same thing */
|
||||
point (f)
|
||||
color (P)
|
||||
```
|
||||
|
||||
The three-component types (`color`, `point`, `vector`, `normal`) may be cast
|
||||
to other three-component types. A `float` may be cast to any of the
|
||||
three-component types (by placing the float in all three components) or to a
|
||||
`matrix` (which makes a matrix with all diagonal components being the
|
||||
`float`). Obviously, there are some type casts that are not allowed because
|
||||
they make no sense, like casting a `point` to a `float`, or casting a
|
||||
`string` to a numerical type.
|
||||
|
||||
* function calls
|
||||
|
||||
* assignment expressions:
|
||||
|
||||
same thing as `var = var OP expr` :
|
||||
|
||||
Operator | Meaning
|
||||
:-- | :--
|
||||
*var* `=` *expr* | assign
|
||||
*var* `+=` *expr* | add
|
||||
*var* `-=` *expr* | subtract
|
||||
*var* `*=` *expr* | multiply
|
||||
*var* `/=` *expr* | divide
|
||||
*int-var* `&=` *int-expr* | bitwise and
|
||||
*int-var* `\|=` *int-expr* | bitwise or
|
||||
*int-var* `^=` *int-expr* | bitwise exclusive or
|
||||
*int-var* `<<=` *int-expr* | integer shift left
|
||||
*int-var* `>>=` *int-expr* | integer shift right
|
||||
|
||||
Note that the integer and bit-wise operators are only allowed with `int`
|
||||
variables and expressions. In general, `var OP= expr` is allowed only if
|
||||
`var = var OP expr` is allowed, and means exactly the same thing. Please
|
||||
consult the operator tables for each individual type in Chapter
|
||||
[](#chap-types).
|
||||
|
||||
* ternary operator, just like C:
|
||||
|
||||
> *condition* `?` *expr1* `:` *expr2*
|
||||
|
||||
This expression takes on the value of *expr1* if *condition* is true
|
||||
(nonzero), or *expr2* if *condition* is false (zero).
|
||||
|
||||
|
||||
Please refer to Chapter [](#chap-types), where the section describing each
|
||||
data type describes the full complement of operators that may be used with the
|
||||
type. Operator precedence in OSL is identical to that of C.
|
||||
|
||||
|
||||
## Control flow: `if`, `while`, `do`, `for`
|
||||
|
||||
Conditionals in OSL just like in C or C++:
|
||||
|
||||
\begin{tabbing}
|
||||
\hspace{0.5in} \= \hspace{0.3in} \= \kill
|
||||
\> {\cf if (} *condition* {\cf )} \\
|
||||
\> \> *truestatement*
|
||||
\end{tabbing}
|
||||
|
||||
and
|
||||
|
||||
\begin{tabbing}
|
||||
\hspace{0.5in} \= \hspace{0.3in} \= \kill
|
||||
\> {\cf if (} *condition* {\cf )} \\
|
||||
\> \> *truestatement* \\
|
||||
\> {\cf else} \\
|
||||
\> \> *falsestatement*
|
||||
\end{tabbing}
|
||||
|
||||
The statements can also be entire blocks, surrounded by curly
|
||||
braces. For example,
|
||||
|
||||
```
|
||||
if (s > 0.5) {
|
||||
x = s;
|
||||
y = 1;
|
||||
} else {
|
||||
x = s+t;
|
||||
}
|
||||
```
|
||||
|
||||
The *condition* may be any valid expression, including:
|
||||
|
||||
* The result of any comparison operator (such as `<`, `==`, etc.).
|
||||
* Any numeric expression (`int`, `color`, `point`, `vector`, `normal`,
|
||||
`matrix`), which is considered "true" if nonzero and "false" if zero.
|
||||
* Any string expression, which is considered "true" if it is a nonempty
|
||||
string, "false" if it is the empty string (`""`).
|
||||
* A closure, which is considered "true" if it's empty (not assigned, or
|
||||
initialized with {\cf =0}), and "false" if anything else has been assigned
|
||||
to it.
|
||||
* A logical combination of expressions using the operators `!` (not), `&&`
|
||||
(logical "and"), or `||` (logical "or"). Note that `&&` and `\|\|`
|
||||
*short circuit* as in C, i.e. `A && B` will only evaluate B if A
|
||||
is true, and `A || B` will only evaluate B if A is false.
|
||||
|
||||
Repeated execution of statements for as long as a condition is true is
|
||||
possible with a `while` statement:
|
||||
|
||||
> `while (` *condition* `)` *statements*
|
||||
|
||||
Or the test may happen after the body of the loop, with a `do/while` loop:
|
||||
|
||||
> `do` *statement* `while (` *condition* `)`
|
||||
|
||||
Also, `for` loops are also allowed:
|
||||
|
||||
> `for (` *initialization-statement* `;` *condition* `;` *iteration-statement* `)` \
|
||||
> *body-statements*
|
||||
|
||||
As in C++, a `for` loop's initialization may contain variable declarations and
|
||||
initializations, which are scoped locally to the `for` loop itself. For
|
||||
example,
|
||||
|
||||
```
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
As with `if` statements, loop conditions may be relations or numerical
|
||||
quantities (which are considered "true" if nonzero, "false" if zero), or
|
||||
strings (considered "true" if nonempty, "false" if the empty string `""`.
|
||||
|
||||
Inside the body of a loop, the `break` statement terminates the loop
|
||||
altogether, and the `continue` statement skip to the end of the body and
|
||||
proceeds to the next iteration of the loop.
|
||||
|
||||
## Functions
|
||||
|
||||
### Function definitions
|
||||
|
||||
You may define functions much like in C or C++.
|
||||
|
||||
> *return-type* *function-name* `(` *optional-parameters* `)` \
|
||||
> `{` \
|
||||
> *statements* \
|
||||
> `}`
|
||||
|
||||
Parameters to functions are similar to shader parameters, except that they do
|
||||
not permit initializers. A function call must pass values for all formal
|
||||
parameters. Function parameters in OSL are all *passed by reference*, and are
|
||||
read-only within the body of the function unless they are also designated as
|
||||
`output` (in the same manner as output shader parameters).
|
||||
|
||||
Like for shaders, statements inside functions may be actual executions
|
||||
(assignments, function call, etc.), local variable declarations (visible
|
||||
only from within the body of the function), or local function
|
||||
declarations (callable only from within the body of the function).
|
||||
|
||||
The return type may be any simple data type, a `struct`, or a
|
||||
`closure`. Functions may not return arrays. The return type may be
|
||||
`void`, indicating that the function does not return a value (and
|
||||
should not contain a `return` statement). A `return` statement
|
||||
inside the body of the function will halt execution of the function at
|
||||
that point, and designates the value that will be returned (if not a
|
||||
`void` function).
|
||||
|
||||
Functions may be *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
|
||||
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 `int` when the function expects a `float`, or passing a
|
||||
`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.
|
||||
|
||||
(sec-syntax-functioncalls)=
|
||||
### Function calls
|
||||
|
||||
Function calls are very similar to C and related programming languages:
|
||||
|
||||
> *functionname* `(` *arg1* `,` ... `,` *argn* `)`
|
||||
|
||||
If the function returns a value (not `void`), you may use its value as an
|
||||
expression. It is fine to completely ignore the value of even a non-`void`
|
||||
function.
|
||||
|
||||
In OSL, all arguments are passed by reference. This generally will not be
|
||||
noticeably different from C-style "pass by value" semantics, except if you
|
||||
pass the same variable as two separate arguments to a function that modifies
|
||||
an argument's value.
|
||||
|
||||
Certain functions allow optional arguments to be passed.
|
||||
Optional arguments are key-value pairs with the key passed as an argument and
|
||||
the associated value passed as the subsequent argument:
|
||||
|
||||
> *functionname* `(` *arg1* `,` ... `,` *argn* `,` *"optionalkey"* `,` *optionalvalue* `,` ... `)`
|
||||
|
||||
|
||||
### Operator overloading
|
||||
|
||||
OSL permits \emph{operator overloading}, which is the practice of providing a
|
||||
function that will be called when you use an operator like `+` or `*`. This is
|
||||
especially handy when you use `struct` to define mathematical types and wish
|
||||
for the usual math operators to work with them. Here is a typical example,
|
||||
which also shows the special naming convention that allows operator
|
||||
overloading:
|
||||
|
||||
```
|
||||
struct vector4 {
|
||||
float x, y, z, w;
|
||||
};
|
||||
|
||||
vector4 __operator__add__ (vector4 a, vector4 b) {
|
||||
return vector4 (a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w);
|
||||
}
|
||||
|
||||
shader test ()
|
||||
{
|
||||
vector4 a = vector4 (.2, .3, .4, .5);
|
||||
vector4 b = vector4 (1, 2, 3, 4);
|
||||
|
||||
vector4 c = a + b; // Will call __operator__add__(vector4,vector4)
|
||||
printf ("a+b = %g %g %g %g\n", c.x, c.y, c.z, c.w);
|
||||
}
|
||||
```
|
||||
|
||||
The full list of these special function names is as follows (in order of
|
||||
decreasing operator precedence):
|
||||
|
||||
|
||||
Operator | Overload function name | notes
|
||||
:---------- | :----------- | :------
|
||||
`-` | `__operator__neg__` | unary negation
|
||||
`~` | `__operator__compl__` | unary bitwise
|
||||
`!` | `__operator__not__` | unary boolean 'not'
|
||||
`*` | `__operator__mul__` |
|
||||
`/` | `__operator__div__` |
|
||||
`\%` | `__operator__mod__` |
|
||||
`+` | `__operator__add__` |
|
||||
`-` | `__operator__sub__` |
|
||||
`<<` | `__operator__shl__` |
|
||||
`>>` | `__operator__shr__` |
|
||||
`<` | `__operator__lt__` |
|
||||
`<=` | `__operator__le__` |
|
||||
`>` | `__operator__gt__` |
|
||||
`>=` | `__operator__ge__` |
|
||||
`==` | `__operator__eq__` |
|
||||
`!=` | `__operator__ne__` |
|
||||
`\&` | `__operator__bitand__` |
|
||||
`^` | `__operator__xor__` |
|
||||
`\|` | `__operator__bitor__` |
|
||||
|
||||
|
||||
## Global variables
|
||||
|
||||
*Global variables* (sometimes called *graphics state variables*) contain the
|
||||
basic information that the renderer knows about the point being shaded, such
|
||||
as position, surface orientation, and default surface color. You need not
|
||||
declare these variables; they are simply available by default in your shader.
|
||||
Global variables available in shaders are listed in the following table:
|
||||
|
||||
Variable | Description
|
||||
:---------- | :-----------
|
||||
`point P` | Position of the point you are shading. In a displacement shader, changing this variable displaces the surface.
|
||||
`vector I` | The *incident* ray direction, pointing from the viewing position to the shading position `P`.
|
||||
`normal N` | The surface "Shading" "normal of the surface at `P`. Changing `N` yields bump mapping.
|
||||
`normal Ng` | The true surface normal at `P`. This can differ from `N`; `N` can be overridden in various ways including bump mapping and user-provided vertex normals, but `Ng` is always the true surface geometric normal of the surface at `P`.
|
||||
`float u, v` | The 2D parametric coordinates of \P (on the particular geometric primitive you are shading).
|
||||
`vector dPdu, dPdv` | Partial derivatives $\partial P/\partial u$ and $\partial P/\partial v$ tangent to the surface at `P`.
|
||||
`point Ps` | Position at which the light is being queried (currently only used for light attenuation shaders)
|
||||
`float time` | Current shutter time for the point being shaded.
|
||||
`float dtime` | The amount of time covered by this shading sample.
|
||||
`vector dPdtime` | How the surface position \P is moving per unit time
|
||||
`closure color Ci` | Incident radiance --- a closure representing the color of the light leaving the surface from `P` in the direction `-I`.
|
||||
|
||||
|
||||
Accessibility of variables by shader type:
|
||||
|
||||
Variable | surface | displacement | volume
|
||||
:---------- | ----- | -- | --
|
||||
`P` | R | RW | R
|
||||
`I` | R | | R
|
||||
`N` | RW | RW |
|
||||
`Ng` | R | R |
|
||||
`dPdu` | R | R |
|
||||
`dPdv` | R | R |
|
||||
`Ps` | | | R
|
||||
`u, v` | R | R | R
|
||||
`time` | R | R | R
|
||||
`dtime` | R | R | R
|
||||
`dPdtime` | R | R | R
|
||||
`Ci` | RW | | RW
|
||||
|
||||
@@ -28,16 +28,12 @@ endif()
|
||||
|
||||
|
||||
set (versionfile oslversion.h)
|
||||
if (VERBOSE)
|
||||
message (STATUS "Create ${versionfile} from ${versionfile}.in")
|
||||
endif ()
|
||||
message (VERBOSE "Create ${versionfile} from ${versionfile}.in")
|
||||
configure_file (${PROJECT_NAME}/${versionfile}.in "${CMAKE_BINARY_DIR}/include/${PROJECT_NAME}/${versionfile}" @ONLY)
|
||||
list (APPEND public_headers "${CMAKE_BINARY_DIR}/include/${PROJECT_NAME}/${versionfile}")
|
||||
|
||||
set (oslconfighfile oslconfig.h)
|
||||
if (VERBOSE)
|
||||
message (STATUS "Create ${oslconfighfile} from ${oslconfighfile}.in")
|
||||
endif ()
|
||||
message (VERBOSE "Create ${oslconfighfile} from ${oslconfighfile}.in")
|
||||
configure_file (${PROJECT_NAME}/${oslconfighfile}.in "${CMAKE_BINARY_DIR}/include/${PROJECT_NAME}/${oslconfighfile}" @ONLY)
|
||||
list (APPEND public_headers "${CMAKE_BINARY_DIR}/include/${PROJECT_NAME}/${oslconfighfile}")
|
||||
|
||||
|
||||
@@ -265,7 +265,7 @@ nonAffineInverse(const Matrix44 &source);
|
||||
|
||||
Matrix44 OSL_HOSTDEVICE nonAffineInverse(const Matrix44 &source)
|
||||
{
|
||||
OSL_INTEL_PRAGMA(float_control(strict,on,push))
|
||||
OSL_INTEL_CLASSIC_PRAGMA(float_control(strict,on,push))
|
||||
OSL_CLANG_PRAGMA(clang fp contract(off))
|
||||
|
||||
using ScalarT = typename Matrix44::BaseType;
|
||||
|
||||
@@ -82,12 +82,13 @@ public:
|
||||
/// Return a Mask with lanes set to true if ok, false if the named matrix
|
||||
/// is not known.
|
||||
virtual Mask get_matrix(BatchedShaderGlobals* bsg, Masked<Matrix44> wresult,
|
||||
ustring from, Wide<const float> wtime)
|
||||
ustringhash from, Wide<const float> wtime)
|
||||
{
|
||||
return Mask(false);
|
||||
}
|
||||
virtual Mask get_matrix(BatchedShaderGlobals* bsg, Masked<Matrix44> result,
|
||||
Wide<const ustring> wfrom, Wide<const float> wtime);
|
||||
Wide<const ustringhash> wfrom,
|
||||
Wide<const float> wtime);
|
||||
virtual bool is_overridden_get_matrix_WmWsWf() const = 0;
|
||||
|
||||
|
||||
@@ -97,12 +98,12 @@ public:
|
||||
/// particular renderer may have a better technique and overload the
|
||||
/// implementation.
|
||||
virtual Mask get_inverse_matrix(BatchedShaderGlobals* bsg,
|
||||
Masked<Matrix44> wresult, ustring to,
|
||||
Masked<Matrix44> wresult, ustringhash to,
|
||||
Wide<const float> wtime);
|
||||
virtual bool is_overridden_get_inverse_matrix_WmsWf() const = 0;
|
||||
virtual Mask get_inverse_matrix(BatchedShaderGlobals* bsg,
|
||||
Masked<Matrix44> wresult,
|
||||
Wide<const ustring> wto,
|
||||
Wide<const ustringhash> wto,
|
||||
Wide<const float> wtime);
|
||||
virtual bool is_overridden_get_inverse_matrix_WmWsWf() const = 0;
|
||||
|
||||
@@ -124,22 +125,23 @@ public:
|
||||
/// specified (object == ustring()), then the renderer should search *first*
|
||||
/// for the attribute on the currently shaded object, and next, if
|
||||
/// unsuccessful, on the currently shaded "scene".
|
||||
virtual Mask get_attribute(BatchedShaderGlobals* bsg, ustring object,
|
||||
ustring name, MaskedData wval)
|
||||
virtual Mask get_attribute(BatchedShaderGlobals* bsg, ustringhash object,
|
||||
ustringhash name, MaskedData wval)
|
||||
{
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
/// Similar to get_attribute(); this method will fetch the 'index'
|
||||
/// element of an attribute array.
|
||||
virtual Mask get_array_attribute(BatchedShaderGlobals* bsg, ustring object,
|
||||
ustring name, int index, MaskedData wval)
|
||||
virtual Mask get_array_attribute(BatchedShaderGlobals* bsg,
|
||||
ustringhash object, ustringhash name,
|
||||
int index, MaskedData wval)
|
||||
{
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
virtual bool get_attribute_uniform(BatchedShaderGlobals* bsg,
|
||||
ustring object, ustring name,
|
||||
ustringhash object, ustringhash name,
|
||||
RefData val)
|
||||
{
|
||||
return false;
|
||||
@@ -148,8 +150,9 @@ public:
|
||||
/// Similar to get_attribute(); this method will fetch the 'index'
|
||||
/// element of an attribute array.
|
||||
virtual bool get_array_attribute_uniform(BatchedShaderGlobals* bsg,
|
||||
ustring object, ustring name,
|
||||
int index, RefData val)
|
||||
ustringhash object,
|
||||
ustringhash name, int index,
|
||||
RefData val)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -159,7 +162,7 @@ public:
|
||||
/// as well. It is assumed the results are varying and returns Mask
|
||||
// with its bit set to off if no user-data with the given name and type was
|
||||
/// found.
|
||||
virtual Mask get_userdata(ustring name, BatchedShaderGlobals* bsg,
|
||||
virtual Mask get_userdata(ustringhash name, BatchedShaderGlobals* bsg,
|
||||
MaskedData wval)
|
||||
{
|
||||
return Mask(false);
|
||||
@@ -206,7 +209,7 @@ public:
|
||||
/// error.
|
||||
///
|
||||
virtual Mask
|
||||
texture(ustring filename, TextureSystem::TextureHandle* texture_handle,
|
||||
texture(ustringhash filename, TextureSystem::TextureHandle* texture_handle,
|
||||
TextureSystem::Perthread* texture_thread_info,
|
||||
const BatchedTextureOptions& options, BatchedShaderGlobals* bsg,
|
||||
Wide<const float> ws, Wide<const float> wt, Wide<const float> wdsdx,
|
||||
@@ -240,7 +243,7 @@ public:
|
||||
/// messages (in case of failure, when the function returns false) will
|
||||
/// be stored there, leaving it up to the caller/shader to handle the
|
||||
/// error.
|
||||
virtual Mask texture3d(ustring filename,
|
||||
virtual Mask texture3d(ustringhash filename,
|
||||
TextureSystem::TextureHandle* texture_handle,
|
||||
TextureSystem::Perthread* texture_thread_info,
|
||||
const BatchedTextureOptions& options,
|
||||
@@ -273,7 +276,7 @@ public:
|
||||
/// messages (in case of failure, when the function returns false) will
|
||||
/// be stored there, leaving it up to the caller/shader to handle the
|
||||
/// error.
|
||||
virtual Mask environment(ustring filename,
|
||||
virtual Mask environment(ustringhash filename,
|
||||
TextureSystem::TextureHandle* texture_handle,
|
||||
TextureSystem::Perthread* texture_thread_info,
|
||||
const BatchedTextureOptions& options,
|
||||
@@ -300,12 +303,12 @@ public:
|
||||
|
||||
virtual TextureSystem::TextureHandle* resolve_udim_uniform(
|
||||
BatchedShaderGlobals* bsg, TexturePerthread* texture_thread_info,
|
||||
ustring filename, TextureSystem::TextureHandle* texture_handle, float S,
|
||||
float T);
|
||||
ustringhash filename, TextureSystem::TextureHandle* texture_handle,
|
||||
float S, float T);
|
||||
|
||||
virtual void resolve_udim(BatchedShaderGlobals* bsg,
|
||||
TexturePerthread* texture_thread_info,
|
||||
ustring filename,
|
||||
ustringhash filename,
|
||||
TextureSystem::TextureHandle* texture_handle,
|
||||
Wide<const float> wS, Wide<const float> wT,
|
||||
Masked<TextureSystem::TextureHandle*> wresult);
|
||||
@@ -313,8 +316,8 @@ public:
|
||||
// Assumes any UDIM has been resolved already
|
||||
virtual bool get_texture_info_uniform(
|
||||
BatchedShaderGlobals* bsg, TexturePerthread* texture_thread_info,
|
||||
ustring filename, TextureSystem::TextureHandle* texture_handle,
|
||||
int subimage, ustring dataname, RefData val);
|
||||
ustringhash filename, TextureSystem::TextureHandle* texture_handle,
|
||||
int subimage, ustringhash dataname, RefData val);
|
||||
|
||||
|
||||
/// Lookup nearest points in a point cloud. It will search for
|
||||
@@ -407,26 +410,25 @@ public:
|
||||
};
|
||||
|
||||
|
||||
virtual void pointcloud_search(BatchedShaderGlobals* bsg, ustring filename,
|
||||
const void* wcenter,
|
||||
virtual void pointcloud_search(BatchedShaderGlobals* bsg,
|
||||
ustringhash filename, const void* wcenter,
|
||||
Wide<const float> wradius, int max_points,
|
||||
bool sort, PointCloudSearchResults& results);
|
||||
virtual bool is_overridden_pointcloud_search() const = 0;
|
||||
|
||||
|
||||
virtual Mask pointcloud_get(BatchedShaderGlobals* bsg, ustring filename,
|
||||
virtual Mask pointcloud_get(BatchedShaderGlobals* bsg, ustringhash filename,
|
||||
Wide<const int[]> windices,
|
||||
Wide<const int> wnum_points, ustring attr_name,
|
||||
MaskedData wout_data);
|
||||
Wide<const int> wnum_points,
|
||||
ustringhash attr_name, MaskedData wout_data);
|
||||
virtual bool is_overridden_pointcloud_get() const = 0;
|
||||
|
||||
|
||||
virtual Mask pointcloud_write(BatchedShaderGlobals* bsg, ustring filename,
|
||||
Wide<const OSL::Vec3> wpos, int nattribs,
|
||||
const ustring* attr_names,
|
||||
const TypeDesc* attr_types,
|
||||
const void** pointers_to_wide_attr_value,
|
||||
Mask mask);
|
||||
virtual Mask
|
||||
pointcloud_write(BatchedShaderGlobals* bsg, ustringhash filename,
|
||||
Wide<const OSL::Vec3> wpos, int nattribs,
|
||||
const ustring* attr_names, const TypeDesc* attr_types,
|
||||
const void** pointers_to_wide_attr_value, Mask mask);
|
||||
virtual bool is_overridden_pointcloud_write() const = 0;
|
||||
|
||||
/// Options for the trace call.
|
||||
@@ -441,7 +443,8 @@ public:
|
||||
Wide<const Vec3> wdRdy);
|
||||
|
||||
virtual void getmessage(BatchedShaderGlobals* bsg, Masked<int> wresult,
|
||||
ustring source, ustring name, MaskedData wval);
|
||||
ustringhash source, ustringhash name,
|
||||
MaskedData wval);
|
||||
|
||||
// pointcloud_search is T.B.D.
|
||||
|
||||
|
||||
@@ -41,9 +41,7 @@ template<int WidthT> struct VaryingTextureOptions {
|
||||
Block<float, WidthT> swidth; ///< Multiplier for derivatives
|
||||
Block<float, WidthT> twidth;
|
||||
Block<float, WidthT> rwidth; // For 3D volume texture lookups only:
|
||||
#if OIIO_VERSION_GREATER_EQUAL(2, 4, 0)
|
||||
Block<float, WidthT> rnd; // For stochastic sampling
|
||||
#endif
|
||||
Block<float, WidthT> rnd; // For stochastic sampling
|
||||
};
|
||||
static_assert(std::alignment_of<VaryingTextureOptions<16>>::value
|
||||
== VecReg<16>::alignment,
|
||||
@@ -69,9 +67,7 @@ template<int WidthT> struct BatchedTextureOptions {
|
||||
swidth,
|
||||
twidth,
|
||||
rwidth,
|
||||
#if OIIO_VERSION_GREATER_EQUAL(2, 4, 0)
|
||||
rnd,
|
||||
#endif
|
||||
firstchannel,
|
||||
subimage,
|
||||
subimagename,
|
||||
@@ -123,10 +119,8 @@ static_assert(offsetof(OIIO::TextureOptBatch, twidth) % 64 == 0,
|
||||
"oops unaligned wide variable");
|
||||
static_assert(offsetof(OIIO::TextureOptBatch, rwidth) % 64 == 0,
|
||||
"oops unaligned wide variable");
|
||||
# if OIIO_VERSION_GREATER_EQUAL(2, 4, 0)
|
||||
static_assert(offsetof(OIIO::TextureOptBatch, rnd) % 64 == 0,
|
||||
"oops unaligned wide variable");
|
||||
# endif
|
||||
|
||||
static_assert(sizeof(OIIO::TextureOptBatch)
|
||||
== sizeof(BatchedTextureOptions<16>),
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
// Copyright Contributors to the Open Shading Language project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
|
||||
/// Wrapper class for holding a "device" pointer -- GPU or whatnot. It
|
||||
/// provides protections so that the pointer cannot easily be accessed on the
|
||||
/// host side, where presumably it would not be valid memory.
|
||||
template<class T> class device_ptr {
|
||||
public:
|
||||
device_ptr() = default;
|
||||
|
||||
// Copy ctr from another device_ptr of the same type
|
||||
device_ptr(const device_ptr& other) = default;
|
||||
|
||||
/// On device, device_ptr can construct from a pointer.
|
||||
/// On host, it must be explicitly constructed -- use with caution.
|
||||
#ifdef __CUDA_ARCH__
|
||||
device_ptr(T* ptr) : m_ptr(ptr) {}
|
||||
#else
|
||||
explicit device_ptr(T* ptr) : m_ptr(ptr) {}
|
||||
#endif
|
||||
|
||||
#ifdef __CUDA_ARCH__
|
||||
/// On device, act as a pointer. None of these things are allowed on the
|
||||
/// host.
|
||||
T* operator->() const { return m_ptr; }
|
||||
T& operator*() const { return *m_ptr; }
|
||||
#endif
|
||||
|
||||
/// Extract the raw device-side pointer. Use with caution! On the host,
|
||||
/// this will not point to valid memory.
|
||||
T* d_get() const { return m_ptr; }
|
||||
|
||||
/// Evaluate as bool is a null pointer check.
|
||||
operator bool() const noexcept { return m_ptr != nullptr; }
|
||||
|
||||
/// Reset the pointer to `dptr`, which must be a device-side raw pointer,
|
||||
/// or null. Since this device_ptr is non-owning, any previous value is
|
||||
/// simply overwritten.
|
||||
void reset(T* dptr = nullptr) { m_ptr = dptr; }
|
||||
|
||||
private:
|
||||
T* m_ptr = nullptr; // underlying pointer, initializes to null
|
||||
};
|
||||
|
||||
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
@@ -6,10 +6,6 @@
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
#ifdef __CUDA_ARCH__
|
||||
# include <optix.h>
|
||||
#endif
|
||||
|
||||
// USAGE NOTES:
|
||||
//
|
||||
// To define a "standard" DeviceString, add a STRDECL to <OSL/strdecls.h>
|
||||
@@ -19,21 +15,10 @@
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
|
||||
// Strings are handled differently in OptiX 6 vs OptiX 7.
|
||||
//
|
||||
// In OptiX 7+:
|
||||
// Strings are not stored on the GPU at all. Strings are represented by
|
||||
// their hash values which are computed at compile-time. Because of this,
|
||||
// we have no access to either the strings' contents or their lengths.
|
||||
//
|
||||
// In OptiX 6:
|
||||
// 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 {
|
||||
#ifdef __CUDA_ARCH__
|
||||
@@ -68,10 +53,7 @@ struct DeviceString {
|
||||
// In OptiX 7 we can't return the string's contents. Make this a compile
|
||||
// time error.
|
||||
#ifndef __CUDA_ARCH__
|
||||
OSL_HOSTDEVICE const char* c_str() const
|
||||
{
|
||||
return m_chars;
|
||||
}
|
||||
OSL_HOSTDEVICE const char* c_str() const { return m_chars; }
|
||||
#endif
|
||||
|
||||
OSL_HOSTDEVICE bool operator==(const DeviceString& other) const
|
||||
@@ -96,10 +78,7 @@ struct DeviceString {
|
||||
return hash() != other;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE operator size_t() const
|
||||
{
|
||||
return hash();
|
||||
}
|
||||
OSL_HOSTDEVICE operator size_t() const { return hash(); }
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
// Copyright Contributors to the Open Shading Language project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
|
||||
// Substitute for variable argument list, which is traditionally used with a printf, with arrays
|
||||
// of EncodedTypes to identify types contained in a blind payload of values.
|
||||
enum class EncodedType : uint8_t {
|
||||
// OSL Shaders could encode these types
|
||||
kUstringHash = 0,
|
||||
kInt32,
|
||||
kFloat,
|
||||
|
||||
// OSL library functions or renderer services encode additional native types
|
||||
kInt64,
|
||||
kDouble,
|
||||
kUInt32,
|
||||
kUInt64,
|
||||
kPointer,
|
||||
kTypeDesc,
|
||||
kCount
|
||||
};
|
||||
|
||||
// Decode will use each EncodedType in the array to interpret the contents of the arg_values
|
||||
// parameter alongwith a fmtlib specifier identified by the ustring that the format_hash represents.
|
||||
// Contents of decoded_str are written over (not appended).
|
||||
// Returns # of bytes read from arg_values
|
||||
int
|
||||
decode_message(uint64_t format_hash, int32_t arg_count,
|
||||
const EncodedType* arg_types, const uint8_t* arg_values,
|
||||
std::string& decoded_str);
|
||||
|
||||
namespace pvt {
|
||||
|
||||
constexpr inline uint32_t
|
||||
size_of_encoded_type(EncodedType et)
|
||||
{
|
||||
constexpr uint32_t SizeByEncodedType[] = {
|
||||
sizeof(OSL::ustringhash), sizeof(int32_t), sizeof(float),
|
||||
sizeof(int64_t), sizeof(double), sizeof(uint32_t),
|
||||
sizeof(uint64_t), sizeof(void*), sizeof(OSL::TypeDesc),
|
||||
};
|
||||
static_assert(sizeof(SizeByEncodedType) / sizeof(SizeByEncodedType[0])
|
||||
== size_t(EncodedType::kCount),
|
||||
"Keep array contents lined up with enum");
|
||||
return SizeByEncodedType[static_cast<int>(et)];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct TypeEncoder; //Undefined on purpose; all types must have a specialization
|
||||
|
||||
template<> struct TypeEncoder<OSL::ustringhash> {
|
||||
using DataType = ustringhash_pod;
|
||||
static constexpr EncodedType value = EncodedType::kUstringHash;
|
||||
static_assert(size_of_encoded_type(value) == sizeof(DataType),
|
||||
"unexpected");
|
||||
static DataType Encode(const OSL::ustringhash& val) { return val.hash(); }
|
||||
};
|
||||
|
||||
template<> struct TypeEncoder<OSL::ustring> {
|
||||
using DataType = ustringhash_pod;
|
||||
static constexpr EncodedType value = EncodedType::kUstringHash;
|
||||
static_assert(size_of_encoded_type(value) == sizeof(DataType),
|
||||
"unexpected");
|
||||
static DataType Encode(const OSL::ustring& val) { return val.hash(); }
|
||||
};
|
||||
|
||||
template<> struct TypeEncoder<const char*> {
|
||||
using DataType = ustringhash_pod;
|
||||
static constexpr EncodedType value = EncodedType::kUstringHash;
|
||||
static_assert(size_of_encoded_type(value) == sizeof(DataType),
|
||||
"unexpected");
|
||||
static DataType Encode(const char* val) { return ustring(val).hash(); }
|
||||
};
|
||||
|
||||
template<> struct TypeEncoder<std::string> {
|
||||
using DataType = ustringhash_pod;
|
||||
static constexpr EncodedType value = EncodedType::kUstringHash;
|
||||
static_assert(size_of_encoded_type(value) == sizeof(DataType),
|
||||
"unexpected");
|
||||
static DataType Encode(const std::string& val)
|
||||
{
|
||||
return ustring(val).hash();
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct TypeEncoder<int32_t> {
|
||||
using DataType = int32_t;
|
||||
static constexpr EncodedType value = EncodedType::kInt32;
|
||||
static_assert(size_of_encoded_type(value) == sizeof(DataType),
|
||||
"unexpected");
|
||||
static DataType Encode(const int32_t val) { return val; }
|
||||
};
|
||||
|
||||
template<> struct TypeEncoder<float> {
|
||||
using DataType = float;
|
||||
static constexpr EncodedType value = EncodedType::kFloat;
|
||||
static_assert(size_of_encoded_type(value) == sizeof(DataType),
|
||||
"unexpected");
|
||||
static DataType Encode(const float val) { return val; }
|
||||
};
|
||||
|
||||
|
||||
template<> struct TypeEncoder<int64_t> {
|
||||
using DataType = int64_t;
|
||||
static constexpr EncodedType value = EncodedType::kInt64;
|
||||
static_assert(size_of_encoded_type(value) == sizeof(DataType),
|
||||
"unexpected");
|
||||
static DataType Encode(const int64_t val) { return val; }
|
||||
};
|
||||
|
||||
// On macOS 10.+ ptrdiff_t is a long, but on linux this
|
||||
// specialization would conflict with int64_t
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
template<> struct TypeEncoder<ptrdiff_t> {
|
||||
using DataType = int64_t;
|
||||
static constexpr EncodedType value = EncodedType::kInt64;
|
||||
static_assert(size_of_encoded_type(value) == sizeof(DataType),
|
||||
"unexpected");
|
||||
static DataType Encode(const ptrdiff_t val) { return val; }
|
||||
};
|
||||
#endif
|
||||
|
||||
template<> struct TypeEncoder<double> {
|
||||
using DataType = double;
|
||||
static constexpr EncodedType value = EncodedType::kDouble;
|
||||
static_assert(size_of_encoded_type(value) == sizeof(DataType),
|
||||
"unexpected");
|
||||
static DataType Encode(const double val) { return val; }
|
||||
};
|
||||
|
||||
template<> struct TypeEncoder<uint64_t> {
|
||||
using DataType = uint64_t;
|
||||
static constexpr EncodedType value = EncodedType::kUInt64;
|
||||
static_assert(size_of_encoded_type(value) == sizeof(DataType),
|
||||
"unexpected");
|
||||
static DataType Encode(const uint64_t val) { return val; }
|
||||
};
|
||||
|
||||
template<> struct TypeEncoder<uint32_t> {
|
||||
using DataType = uint32_t;
|
||||
static constexpr EncodedType value = EncodedType::kUInt32;
|
||||
static_assert(size_of_encoded_type(value) == sizeof(DataType),
|
||||
"unexpected");
|
||||
static DataType Encode(const uint32_t val) { return val; }
|
||||
};
|
||||
|
||||
template<typename T> struct TypeEncoder<T*> {
|
||||
// fmtlib only supports const void *, all other pointers must be
|
||||
// converted with a cast or helper like fmt::ptr(p)
|
||||
static_assert(
|
||||
(std::is_same<void*, T*>::value || std::is_same<const void*, T*>::value),
|
||||
"formatting of non-void pointers is disallowed, wrap with fmt::ptr");
|
||||
|
||||
using DataType = const T*;
|
||||
static constexpr EncodedType value = EncodedType::kPointer;
|
||||
static_assert(size_of_encoded_type(value) == sizeof(DataType),
|
||||
"unexpected");
|
||||
static DataType Encode(const T* val) { return val; }
|
||||
};
|
||||
|
||||
template<> struct TypeEncoder<OSL::TypeDesc> {
|
||||
// To avoid warnings about non-pod types when we PackArgs
|
||||
// we will encode into builtin type
|
||||
using DataType = uint64_t;
|
||||
static_assert(sizeof(OSL::TypeDesc) == sizeof(DataType), "unexpected");
|
||||
static constexpr EncodedType value = EncodedType::kTypeDesc;
|
||||
static_assert(size_of_encoded_type(value) == sizeof(DataType),
|
||||
"unexpected");
|
||||
static DataType Encode(const OSL::TypeDesc& val)
|
||||
{
|
||||
return OSL::bitcast<DataType>(val);
|
||||
}
|
||||
};
|
||||
|
||||
// Promote thinner types
|
||||
template<> struct TypeEncoder<int16_t> {
|
||||
using DataType = int32_t;
|
||||
static constexpr EncodedType value = EncodedType::kInt32;
|
||||
static_assert(size_of_encoded_type(value) == sizeof(DataType),
|
||||
"unexpected");
|
||||
static DataType Encode(const int16_t val) { return DataType(val); }
|
||||
};
|
||||
|
||||
template<> struct TypeEncoder<int8_t> {
|
||||
using DataType = int32_t;
|
||||
static constexpr EncodedType value = EncodedType::kInt32;
|
||||
static_assert(size_of_encoded_type(value) == sizeof(DataType),
|
||||
"unexpected");
|
||||
static DataType Encode(const int8_t val) { return DataType(val); }
|
||||
};
|
||||
|
||||
template<> struct TypeEncoder<uint16_t> {
|
||||
using DataType = uint32_t;
|
||||
static constexpr EncodedType value = EncodedType::kUInt32;
|
||||
static_assert(size_of_encoded_type(value) == sizeof(DataType),
|
||||
"unexpected");
|
||||
static DataType Encode(const uint16_t val) { return DataType(val); }
|
||||
};
|
||||
|
||||
template<> struct TypeEncoder<uint8_t> {
|
||||
using DataType = uint32_t;
|
||||
static constexpr EncodedType value = EncodedType::kUInt32;
|
||||
static_assert(size_of_encoded_type(value) == sizeof(DataType),
|
||||
"unexpected");
|
||||
static DataType Encode(const uint8_t val) { return DataType(val); }
|
||||
};
|
||||
} // namespace pvt
|
||||
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
@@ -0,0 +1,146 @@
|
||||
// Copyright Contributors to the Open Shading Language project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <OSL/rs_free_function.h>
|
||||
|
||||
// OSL library functions as well as Renderer Service free functions
|
||||
// can utilize OSL::filefmt, OSL::printfmt, OSL::errorfmt, and
|
||||
// OSL::warningfmt wrappers to accept variable arguments to be
|
||||
// encoded into a EncodeType array and PackedArgument buffer
|
||||
// that underlying render service free functions require.
|
||||
// NOTE: All strings arguments to the underlying render service free
|
||||
// functions must be ustringhash. To make this easier, these wrappers
|
||||
// automatically convert ustring and const char * to ustringhash.
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
namespace pvt {
|
||||
// PackedArgs is similar to tuple but packs its data back to back
|
||||
// in memory layout, which is what we need to build up payload
|
||||
// to the fmt reporting system
|
||||
OSL_PACK_STRUCTS_BEGIN
|
||||
template<int IndexT, typename TypeT> struct alignas(1) PackedArg {
|
||||
explicit PackedArg(const TypeT& a_value) : m_value(a_value) {}
|
||||
TypeT m_value;
|
||||
};
|
||||
OSL_PACK_STRUCTS_END
|
||||
|
||||
template<typename IntSequenceT, typename... TypeListT> struct PackedArgsBase;
|
||||
// Specialize to extract a parameter pack of the IntegerSquence
|
||||
// so it can be expanded alongside the TypeListT parameter pack
|
||||
OSL_PACK_STRUCTS_BEGIN
|
||||
template<int... IntegerListT, typename... TypeListT>
|
||||
struct alignas(1)
|
||||
PackedArgsBase<std::integer_sequence<int, IntegerListT...>, TypeListT...>
|
||||
: public PackedArg<IntegerListT, TypeListT>... {
|
||||
explicit PackedArgsBase(const TypeListT&... a_values)
|
||||
// multiple inheritance of individual components
|
||||
// uniquely identified by the <Integer,Type> combo
|
||||
: PackedArg<IntegerListT, TypeListT>(a_values)...
|
||||
{
|
||||
}
|
||||
};
|
||||
OSL_PACK_STRUCTS_END
|
||||
|
||||
template<typename... TypeListT> struct PackedArgs {
|
||||
typedef std::make_integer_sequence<int, sizeof...(TypeListT)>
|
||||
IndexSequenceType;
|
||||
PackedArgsBase<IndexSequenceType, TypeListT...> m_components;
|
||||
|
||||
explicit PackedArgs(const TypeListT&... a_values)
|
||||
: m_components(a_values...)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(PackedArgs<int, char, int>)
|
||||
== sizeof(int) + sizeof(char) + sizeof(int),
|
||||
"PackedArgs<> type is not packed");
|
||||
static_assert(alignof(PackedArgs<int, char, int>) == 1,
|
||||
"PackedArgs<> type is not aligned to 1");
|
||||
|
||||
} // namespace pvt
|
||||
|
||||
|
||||
|
||||
template<typename FilenameT, typename SpecifierT, typename... ArgListT>
|
||||
void
|
||||
filefmt(OpaqueExecContextPtr oec, const FilenameT& filename_hash,
|
||||
const SpecifierT& fmt_specification, ArgListT... args)
|
||||
{
|
||||
constexpr int32_t count = sizeof...(args);
|
||||
constexpr OSL::EncodedType argTypes[]
|
||||
= { pvt::TypeEncoder<ArgListT>::value... };
|
||||
pvt::PackedArgs<typename pvt::TypeEncoder<ArgListT>::DataType...> argValues {
|
||||
pvt::TypeEncoder<ArgListT>::Encode(args)...
|
||||
};
|
||||
|
||||
rs_filefmt(oec, OSL::ustringhash { filename_hash },
|
||||
OSL::ustringhash { fmt_specification }, count,
|
||||
(count == 0) ? nullptr : argTypes,
|
||||
static_cast<uint32_t>((count == 0) ? 0 : sizeof(argValues)),
|
||||
(count == 0) ? nullptr : reinterpret_cast<uint8_t*>(&argValues));
|
||||
}
|
||||
|
||||
template<typename SpecifierT, typename... ArgListT>
|
||||
void
|
||||
printfmt(OpaqueExecContextPtr oec, const SpecifierT& fmt_specification,
|
||||
ArgListT... args)
|
||||
{
|
||||
constexpr int32_t count = sizeof...(args);
|
||||
constexpr OSL::EncodedType argTypes[]
|
||||
= { pvt::TypeEncoder<ArgListT>::value... };
|
||||
pvt::PackedArgs<typename pvt::TypeEncoder<ArgListT>::DataType...> argValues {
|
||||
pvt::TypeEncoder<ArgListT>::Encode(args)...
|
||||
};
|
||||
|
||||
rs_printfmt(oec, OSL::ustringhash { fmt_specification }, count,
|
||||
(count == 0) ? nullptr : argTypes,
|
||||
static_cast<uint32_t>((count == 0) ? 0 : sizeof(argValues)),
|
||||
(count == 0) ? nullptr
|
||||
: reinterpret_cast<uint8_t*>(&argValues));
|
||||
}
|
||||
|
||||
template<typename SpecifierT, typename... ArgListT>
|
||||
void
|
||||
errorfmt(OpaqueExecContextPtr oec, const SpecifierT& fmt_specification,
|
||||
ArgListT... args)
|
||||
{
|
||||
constexpr int32_t count = sizeof...(args);
|
||||
constexpr OSL::EncodedType argTypes[]
|
||||
= { pvt::TypeEncoder<ArgListT>::value... };
|
||||
pvt::PackedArgs<typename pvt::TypeEncoder<ArgListT>::DataType...> argValues {
|
||||
pvt::TypeEncoder<ArgListT>::Encode(args)...
|
||||
};
|
||||
|
||||
rs_errorfmt(oec, OSL::ustringhash { fmt_specification }, count,
|
||||
(count == 0) ? nullptr : argTypes,
|
||||
static_cast<uint32_t>((count == 0) ? 0 : sizeof(argValues)),
|
||||
(count == 0) ? nullptr
|
||||
: reinterpret_cast<uint8_t*>(&argValues));
|
||||
}
|
||||
|
||||
template<typename SpecifierT, typename... ArgListT>
|
||||
void
|
||||
warningfmt(OpaqueExecContextPtr oec, const SpecifierT& fmt_specification,
|
||||
ArgListT... args)
|
||||
{
|
||||
constexpr int32_t count = sizeof...(args);
|
||||
constexpr OSL::EncodedType argTypes[]
|
||||
= { pvt::TypeEncoder<ArgListT>::value... };
|
||||
pvt::PackedArgs<typename pvt::TypeEncoder<ArgListT>::DataType...> argValues {
|
||||
pvt::TypeEncoder<ArgListT>::Encode(args)...
|
||||
};
|
||||
|
||||
rs_warningfmt(oec, OSL::ustringhash { fmt_specification }, count,
|
||||
(count == 0) ? nullptr : argTypes,
|
||||
static_cast<uint32_t>((count == 0) ? 0 : sizeof(argValues)),
|
||||
(count == 0) ? nullptr
|
||||
: reinterpret_cast<uint8_t*>(&argValues));
|
||||
}
|
||||
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
@@ -0,0 +1,364 @@
|
||||
// Copyright Contributors to the Open Shading Language project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#ifdef __CUDACC__
|
||||
# include <cuda/atomic>
|
||||
#endif
|
||||
|
||||
#include <OSL/encodedtypes.h>
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
/// Journal Buffer approach: each thread gets its own chain of pages within
|
||||
/// the shared journal buffer for recording errors, warnings, etc.
|
||||
/// By maintaining a separate chain per thread we can record errors (etc.) in a
|
||||
/// non-blocking fashion. Shade index is recorded for use by error reporter to
|
||||
/// sort messages but it is not used at present.
|
||||
/// Using a Journal buffer is up to a Renderer. The Renderer use the new
|
||||
/// customization points (rs_errorfmt, rs_filefmt, rs_printfmt, rs_warningfmt
|
||||
/// or their virtual function equivalents) to interact with a journal::Writer
|
||||
/// and journal buffer owned by its RenderState. The Renderer would of have to
|
||||
/// allocate and initialized the journal buffer with the requested page size
|
||||
/// and number of threads before executing a shader. After a shader is done
|
||||
/// executing, the contents of the journal buffer can be transfered back to the
|
||||
/// host and processed with a journal::Reader, which reports them through a
|
||||
/// journal::Reporter's virtual interface. Intent is for Renderers's to use the
|
||||
/// Journal buffer and provide their own overriden version of the
|
||||
/// journal::Reporter. Testshade provides example usage.
|
||||
/// For legacy purposes, the default virtual RendererServices will route errors
|
||||
/// to ShadingSystem's OSL::ErrorHandler, but intent is for Renderer's to
|
||||
/// switch over to using a Journal buffer or their own custom logging.
|
||||
|
||||
namespace journal {
|
||||
|
||||
namespace pvt {
|
||||
//Per thread information for its page
|
||||
struct alignas(64) PageInfo {
|
||||
uint32_t pos;
|
||||
uint32_t remaining;
|
||||
uint32_t warning_count;
|
||||
};
|
||||
|
||||
struct Organization //Initial bookkeeping
|
||||
{
|
||||
int thread_count;
|
||||
uint32_t buf_size;
|
||||
uint32_t page_size;
|
||||
|
||||
// rename free_pos bytes_used;
|
||||
#ifdef __CUDACC__
|
||||
using AtomicUint32 = cuda::std::atomic<std::uint32_t>;
|
||||
#else
|
||||
using AtomicUint32 = std::atomic<std::uint32_t>;
|
||||
#endif
|
||||
alignas(64)
|
||||
AtomicUint32 free_pos; // cache line alignment to avoid false sharing
|
||||
alignas(64) AtomicUint32
|
||||
additional_bytes_required; // when the journal is full, how many more bytes would of been needed
|
||||
alignas(64) AtomicUint32
|
||||
exceeded_page_size; // when the a single entry exceeds the page size, we can't record it, but we can track how space it needed
|
||||
|
||||
uint32_t calc_end_of_page_infos() const
|
||||
{
|
||||
return sizeof(PageInfo) * thread_count + sizeof(Organization);
|
||||
}
|
||||
uint32_t calc_head_pos(int thread_index) const
|
||||
{
|
||||
return calc_end_of_page_infos() + (thread_index * page_size);
|
||||
}
|
||||
|
||||
PageInfo& get_pageinfo(int thread_index)
|
||||
{
|
||||
return reinterpret_cast<PageInfo*>(
|
||||
reinterpret_cast<uint8_t*>(this)
|
||||
+ sizeof(Organization))[thread_index];
|
||||
}
|
||||
};
|
||||
|
||||
enum class Content : uint8_t {
|
||||
PageTransition,
|
||||
// Shader Language generated
|
||||
Error,
|
||||
Warning,
|
||||
Print,
|
||||
FilePrint
|
||||
};
|
||||
|
||||
static_assert(sizeof(PageInfo) % 64 == 0, "PageInfo needs to be cache aligned");
|
||||
} // namespace pvt
|
||||
|
||||
|
||||
/// Call before launching shaders or after processing
|
||||
/// returns: true for success,
|
||||
/// false if buf_size can not accomadate at least 1 page per thread
|
||||
OSLEXECPUBLIC bool
|
||||
initialize_buffer(uint8_t* const buffer, uint32_t buf_size_,
|
||||
uint32_t page_size_, int thread_count_);
|
||||
|
||||
/// Abstract base class intended for Renders to override and handle messages
|
||||
/// decoded from a journal buffer
|
||||
class OSLEXECPUBLIC Reporter {
|
||||
//Methods will NOT be called by multiple threads (no synchronization needed)
|
||||
public:
|
||||
virtual ~Reporter() {}
|
||||
virtual void report_error(int thread_index, int shade_index,
|
||||
const OSL::string_view& message)
|
||||
= 0;
|
||||
virtual void report_warning(int thread_index, int shade_index,
|
||||
const OSL::string_view& message)
|
||||
= 0;
|
||||
virtual void report_print(int thread_index, int shade_index,
|
||||
const OSL::string_view& message)
|
||||
= 0;
|
||||
virtual void report_file_print(int thread_index, int shade_index,
|
||||
const OSL::string_view& filename,
|
||||
const OSL::string_view& message)
|
||||
= 0;
|
||||
};
|
||||
|
||||
/// Utility class to look for repeated errors or warnings over
|
||||
/// a limited history window
|
||||
class OSLEXECPUBLIC TrackRecentlyReported {
|
||||
public:
|
||||
TrackRecentlyReported(bool limit_errors = true,
|
||||
int error_history_capacity = 32,
|
||||
bool limit_warnings = true,
|
||||
int warning_history_capacity = 32);
|
||||
|
||||
bool shouldReportError(const OSL::string_view& message);
|
||||
bool shouldReportWarning(const OSL::string_view& message);
|
||||
|
||||
protected:
|
||||
const bool m_limit_errors;
|
||||
const int m_error_history_capacity;
|
||||
const bool m_limit_warnings;
|
||||
const int m_warning_history_capacity;
|
||||
std::list<std::string> m_errseen, m_warnseen;
|
||||
};
|
||||
|
||||
/// Concrete Reporter that utilizes a TrackRecentlyReported to filter and
|
||||
/// forwards to a legacy OSL::ErrorHandler
|
||||
class OSLEXECPUBLIC Report2ErrorHandler : public Reporter {
|
||||
public:
|
||||
Report2ErrorHandler(OSL::ErrorHandler* eh, TrackRecentlyReported& tracker);
|
||||
void report_error(int thread_index, int shade_index,
|
||||
const OSL::string_view& message) override;
|
||||
void report_warning(int thread_index, int shade_index,
|
||||
const OSL::string_view& message) override;
|
||||
void report_print(int thread_index, int shade_index,
|
||||
const OSL::string_view& message) override;
|
||||
void report_file_print(int thread_index, int shade_index,
|
||||
const OSL::string_view& filename,
|
||||
const OSL::string_view& message) override;
|
||||
|
||||
protected:
|
||||
OSL::ErrorHandler* m_eh;
|
||||
TrackRecentlyReported& m_tracker;
|
||||
};
|
||||
|
||||
/// Reader is a lightweight class meant to be constructed as a local variable
|
||||
/// with an already initalized (and populated) journal buffer and a concreate
|
||||
/// Reporter. Calling process will decode all of the messages in the journal
|
||||
/// calling the appropriate methods on the provided Reportor.
|
||||
/// NOTE: Renderer is expected to call initialize_buffer after Reader::process
|
||||
/// before reusing the buffer for additional shading.
|
||||
class OSLEXECPUBLIC Reader {
|
||||
public:
|
||||
Reader(const uint8_t* buffer_, Reporter& reporter);
|
||||
void process();
|
||||
|
||||
private:
|
||||
void process_entries_for_thread(int thread_index);
|
||||
|
||||
const uint8_t* const m_buffer; //Read from this?
|
||||
const pvt::Organization& m_org; //
|
||||
const pvt::PageInfo* m_pageinfo_by_thread_index;
|
||||
Reporter& m_reporter;
|
||||
};
|
||||
|
||||
/// Writer is a lightweight class meant to be constructed as a local variable
|
||||
/// with an already initalized journal buffer and used to record error,
|
||||
/// warnings, prints, or fprints into the buffer and then go out of scope.
|
||||
/// Writer implementation entirely inlinable and intended for use on devices.
|
||||
class OSLEXECPUBLIC Writer {
|
||||
public:
|
||||
Writer(void* buffer)
|
||||
: m_buffer(static_cast<uint8_t*>(buffer))
|
||||
, m_org(*(reinterpret_cast<pvt::Organization*>(buffer)))
|
||||
, m_pageinfo_by_thread_index(reinterpret_cast<pvt::PageInfo*>(
|
||||
m_buffer + sizeof(pvt::Organization)))
|
||||
{
|
||||
}
|
||||
|
||||
bool record_errorfmt(int thread_index, int shade_index,
|
||||
OSL::ustringhash fmt_specification, int32_t arg_count,
|
||||
const EncodedType* arg_types, uint32_t arg_values_size,
|
||||
uint8_t* arg_values)
|
||||
{
|
||||
return write_entry(thread_index, shade_index, pvt::Content::Error,
|
||||
fmt_specification, OSL::ustringhash {} /*filename*/,
|
||||
arg_count, arg_types, arg_values_size, arg_values);
|
||||
}
|
||||
|
||||
bool record_warningfmt(int max_warnings_per_thread, int thread_index,
|
||||
int shade_index, OSL::ustringhash fmt_specification,
|
||||
int32_t arg_count, const EncodedType* arg_types,
|
||||
uint32_t arg_values_size, uint8_t* arg_values)
|
||||
{
|
||||
auto& info = m_pageinfo_by_thread_index[thread_index];
|
||||
|
||||
if (static_cast<int>(info.warning_count) >= max_warnings_per_thread) {
|
||||
return false;
|
||||
}
|
||||
++info.warning_count;
|
||||
return write_entry(thread_index, shade_index, pvt::Content::Warning,
|
||||
fmt_specification, OSL::ustringhash {} /*filename*/,
|
||||
arg_count, arg_types, arg_values_size, arg_values);
|
||||
}
|
||||
|
||||
bool record_printfmt(int thread_index, int shade_index,
|
||||
OSL::ustringhash fmt_specification, int32_t arg_count,
|
||||
const EncodedType* arg_types, uint32_t arg_values_size,
|
||||
uint8_t* arg_values)
|
||||
{
|
||||
return write_entry(thread_index, shade_index, pvt::Content::Print,
|
||||
fmt_specification, OSL::ustringhash {} /*filename*/,
|
||||
arg_count, arg_types, arg_values_size, arg_values);
|
||||
}
|
||||
|
||||
bool record_filefmt(int thread_index, int shade_index,
|
||||
OSL::ustringhash filename_hash,
|
||||
OSL::ustringhash fmt_specification, int32_t arg_count,
|
||||
const EncodedType* arg_types, uint32_t arg_values_size,
|
||||
uint8_t* arg_values)
|
||||
{
|
||||
return write_entry(thread_index, shade_index, pvt::Content::FilePrint,
|
||||
fmt_specification, filename_hash, arg_count,
|
||||
arg_types, arg_values_size, arg_values);
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr size_t requiredForPageTransition()
|
||||
{
|
||||
return sizeof(pvt::Content::PageTransition) + sizeof(uint32_t);
|
||||
}
|
||||
bool allocatePage(int thread_index)
|
||||
{
|
||||
using pvt::Content;
|
||||
auto& info = m_pageinfo_by_thread_index[thread_index];
|
||||
|
||||
OSL_ASSERT(info.remaining >= requiredForPageTransition());
|
||||
|
||||
// pre check if next_pos >= buf_size to prevent continuing to
|
||||
// increment free_pos once its already past the end of a page
|
||||
if ((m_org.free_pos.load() + m_org.page_size) >= m_org.buf_size)
|
||||
return false;
|
||||
|
||||
uint32_t next_pos = m_org.free_pos.fetch_add(m_org.page_size);
|
||||
// post check if next_pos >= buf_size because another thread could
|
||||
// have bumped free_pos
|
||||
if (next_pos >= m_org.buf_size)
|
||||
return false;
|
||||
|
||||
// write page transition
|
||||
uint8_t* dest_ptr = m_buffer + info.pos;
|
||||
constexpr Content content = Content::PageTransition;
|
||||
memcpy(dest_ptr, &content, sizeof(content));
|
||||
memcpy(dest_ptr + sizeof(content), &next_pos, sizeof(next_pos));
|
||||
// Don't bother update page info for the memory used by the transition
|
||||
// because we are about to overwrite it.
|
||||
|
||||
// Update page info to point to newly allocated page
|
||||
info.pos = next_pos;
|
||||
info.remaining = m_org.page_size;
|
||||
info.warning_count = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool write_entry(int thread_index, int shade_index, pvt::Content content,
|
||||
OSL::ustringhash fmt_specification,
|
||||
OSL::ustringhash filename, int32_t arg_count,
|
||||
const EncodedType* arg_types, uint32_t arg_values_size,
|
||||
uint8_t* arg_values)
|
||||
{
|
||||
using pvt::Content;
|
||||
|
||||
uint64_t fname_hash;
|
||||
// calc required size for this entry
|
||||
uint64_t fmt_spec_hash = fmt_specification.hash();
|
||||
uint32_t required_bytes = sizeof(Content) + sizeof(int)
|
||||
+ sizeof(fmt_spec_hash) + sizeof(arg_count)
|
||||
+ sizeof(EncodedType) * arg_count
|
||||
+ arg_values_size;
|
||||
|
||||
if (filename.hash()) {
|
||||
fname_hash = filename.hash();
|
||||
required_bytes += sizeof(fname_hash);
|
||||
}
|
||||
|
||||
|
||||
if (required_bytes > m_org.page_size) {
|
||||
uint32_t exceeded = m_org.exceeded_page_size;
|
||||
while (required_bytes > exceeded) {
|
||||
if (m_org.exceeded_page_size.compare_exchange_weak(
|
||||
exceeded, required_bytes)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& info = m_pageinfo_by_thread_index[thread_index];
|
||||
|
||||
if ((info.remaining - requiredForPageTransition()) < required_bytes) {
|
||||
// TODO (extra credit): get fancy spanning entry over multiple pages
|
||||
if (!allocatePage(thread_index)) {
|
||||
m_org.additional_bytes_required += required_bytes;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
OSL_ASSERT(info.remaining >= required_bytes);
|
||||
uint8_t* dest_ptr = m_buffer + info.pos;
|
||||
|
||||
memcpy(dest_ptr, &content, sizeof(content));
|
||||
memcpy(dest_ptr + sizeof(content), &shade_index, sizeof(shade_index));
|
||||
memcpy(dest_ptr + sizeof(content) + sizeof(shade_index), &fmt_spec_hash,
|
||||
sizeof(fmt_spec_hash));
|
||||
memcpy(dest_ptr + sizeof(content) + sizeof(shade_index)
|
||||
+ sizeof(fmt_spec_hash),
|
||||
&arg_count, sizeof(arg_count));
|
||||
memcpy(dest_ptr + sizeof(content) + sizeof(shade_index)
|
||||
+ sizeof(fmt_spec_hash) + sizeof(arg_count),
|
||||
arg_types, sizeof(EncodedType) * arg_count);
|
||||
memcpy(dest_ptr + sizeof(content) + sizeof(shade_index)
|
||||
+ sizeof(fmt_spec_hash) + sizeof(arg_count)
|
||||
+ sizeof(EncodedType) * arg_count,
|
||||
arg_values, arg_values_size);
|
||||
if (content == Content::FilePrint) {
|
||||
uint64_t filename_hash = filename.hash();
|
||||
memcpy(dest_ptr + sizeof(content) + sizeof(shade_index)
|
||||
+ sizeof(fmt_spec_hash) + sizeof(arg_count)
|
||||
+ sizeof(EncodedType) * arg_count + arg_values_size,
|
||||
&filename_hash, sizeof(filename_hash));
|
||||
}
|
||||
|
||||
info.remaining -= required_bytes;
|
||||
info.pos += required_bytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t* m_buffer;
|
||||
pvt::Organization& m_org;
|
||||
pvt::PageInfo* m_pageinfo_by_thread_index;
|
||||
};
|
||||
|
||||
} // namespace journal
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
@@ -34,6 +34,7 @@ class LLVMContext;
|
||||
class Module;
|
||||
class PointerType;
|
||||
class StringRef;
|
||||
class TargetMachine;
|
||||
class Type;
|
||||
class Value;
|
||||
class VectorType;
|
||||
@@ -62,6 +63,7 @@ enum class TargetISA {
|
||||
AVX512,
|
||||
AVX512_noFMA,
|
||||
HOST,
|
||||
NVPTX,
|
||||
COUNT
|
||||
};
|
||||
|
||||
@@ -154,15 +156,6 @@ public:
|
||||
void debug_pop_inlined_function();
|
||||
void debug_set_location(OIIO::ustring sourcefile, int sourceline);
|
||||
|
||||
/// Create a new function (that will later be populated with
|
||||
/// instructions) with up to 4 args.
|
||||
OSL_DEPRECATED("Use make_function flavor that takes a cspan (1.12)")
|
||||
llvm::Function* make_function(const std::string& name, bool fastcall,
|
||||
llvm::Type* rettype, llvm::Type* arg1 = NULL,
|
||||
llvm::Type* arg2 = NULL,
|
||||
llvm::Type* arg3 = NULL,
|
||||
llvm::Type* arg4 = NULL);
|
||||
|
||||
/// Create a new function (that will later be populated with
|
||||
/// instructions) with a cspan of args.
|
||||
llvm::Function* make_function(const std::string& name, bool fastcall,
|
||||
@@ -212,6 +205,9 @@ public:
|
||||
/// target_isa() unless one of those has previously been called.
|
||||
TargetISA target_isa() const { return m_target_isa; }
|
||||
|
||||
/// Set the TargetISA to be used during codegen.
|
||||
void set_target_isa(TargetISA requestedISA) { m_target_isa = requestedISA; }
|
||||
|
||||
// Check support for certain CPU ISA features. These are only valid
|
||||
// after detect_cpu_features() (or make_jit_execengine()) has been
|
||||
// called.
|
||||
@@ -272,6 +268,10 @@ public:
|
||||
/// current one).
|
||||
void execengine(llvm::ExecutionEngine* exec);
|
||||
|
||||
/// Return a pointer to the TargetMachine for NVPTX. Create the TargetMachine
|
||||
/// if it has not yet been created.
|
||||
llvm::TargetMachine* nvptx_target_machine();
|
||||
|
||||
enum class Linkage {
|
||||
External, // Externally visible
|
||||
LinkOnceODR, // One Definition Rule: Inline version, but allow replacement by equivalent.
|
||||
@@ -536,6 +536,7 @@ public:
|
||||
llvm::Type* type_int() const { return m_llvm_type_int; }
|
||||
llvm::Type* type_int8() const { return m_llvm_type_int8; }
|
||||
llvm::Type* type_int16() const { return m_llvm_type_int16; }
|
||||
llvm::Type* type_int64() const { return m_llvm_type_int64; }
|
||||
llvm::Type* type_addrint() const { return m_llvm_type_addrint; }
|
||||
llvm::Type* type_bool() const { return m_llvm_type_bool; }
|
||||
llvm::Type* type_char() const { return m_llvm_type_char; }
|
||||
@@ -553,6 +554,8 @@ public:
|
||||
llvm::PointerType* type_char_ptr() const { return m_llvm_type_char_ptr; }
|
||||
llvm::PointerType* type_bool_ptr() const { return m_llvm_type_bool_ptr; }
|
||||
llvm::PointerType* type_int_ptr() const { return m_llvm_type_int_ptr; }
|
||||
llvm::PointerType* type_int8_ptr() const { return m_llvm_type_int8_ptr; }
|
||||
llvm::PointerType* type_int64_ptr() const { return m_llvm_type_int64_ptr; }
|
||||
llvm::PointerType* type_float_ptr() const { return m_llvm_type_float_ptr; }
|
||||
llvm::PointerType* type_longlong_ptr() const
|
||||
{
|
||||
@@ -630,6 +633,9 @@ public:
|
||||
const std::string& name = "",
|
||||
bool is_packed = false);
|
||||
|
||||
// Return type of field at given index in a struct type.
|
||||
llvm::Type* type_struct_field_at_index(llvm::Type* type, int index);
|
||||
|
||||
/// Return the llvm::Type that is a pointer to the given llvm type.
|
||||
llvm::PointerType* type_ptr(llvm::Type* type);
|
||||
|
||||
@@ -640,6 +646,12 @@ public:
|
||||
/// llvm type.
|
||||
llvm::Type* type_array(llvm::Type* type, int n);
|
||||
|
||||
/// Return the true if the llvm::Type is an array
|
||||
bool is_type_array(llvm::Type* type);
|
||||
|
||||
/// Return the llvm::Type of element that the array_type is made up of
|
||||
llvm::Type* element_type_of(llvm::Type* array_type);
|
||||
|
||||
/// Return an llvm::FunctionType that describes a function with the
|
||||
/// given return types, parameter types (in a cspan), and whether it
|
||||
/// uses varargs conventions.
|
||||
@@ -659,17 +671,29 @@ public:
|
||||
/// Return the llvm::Type of the llvm value.
|
||||
llvm::Type* llvm_typeof(llvm::Value* val) const;
|
||||
|
||||
/// Return number of bytes used to store the type
|
||||
size_t llvm_sizeof(llvm::Type* type) const;
|
||||
|
||||
/// Return preferred byte alignment for a type
|
||||
size_t llvm_alignmentof(llvm::Type* type) const;
|
||||
|
||||
/// Return the human-readable name of the type of the llvm value.
|
||||
std::string llvm_typenameof(llvm::Value* val) const;
|
||||
|
||||
/// Return an llvm::Constant holding the given floating point constant.
|
||||
llvm::Constant* constant(float f);
|
||||
|
||||
/// Return an llvm::Constant holding the given integer constant.
|
||||
llvm::Constant* constant(int i);
|
||||
/// Return an llvm::Constant holding the given floating point constant.
|
||||
llvm::Constant* constant64(double f);
|
||||
|
||||
/// Return an llvm::Constant holding the given integer constant.
|
||||
llvm::Constant* constant8(int i);
|
||||
llvm::Constant* constant(int32_t i);
|
||||
llvm::Constant* constant(uint32_t i);
|
||||
|
||||
/// Return an llvm::Constant holding the given integer constant.
|
||||
llvm::Constant* constant8(int8_t i);
|
||||
llvm::Constant* constant8(uint8_t i);
|
||||
llvm::Constant* constant16(int16_t i);
|
||||
llvm::Constant* constant16(uint16_t i);
|
||||
llvm::Constant* constant64(uint64_t i);
|
||||
llvm::Constant* constant128(uint64_t i);
|
||||
@@ -762,6 +786,10 @@ public:
|
||||
/// return the llvm::Value of the new pointer.
|
||||
llvm::Value* int_to_ptr_cast(llvm::Value* val);
|
||||
|
||||
/// Cast the pointer specified by ptr to an int64, return the llvm::Value
|
||||
/// of the new value.
|
||||
llvm::Value* ptr_to_int64_cast(llvm::Value* ptr);
|
||||
|
||||
/// 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, const std::string& llname = {});
|
||||
@@ -874,10 +902,9 @@ public:
|
||||
/// type is the type of the thing being pointed to.
|
||||
llvm::Value* op_load(llvm::Type* type, llvm::Value* ptr,
|
||||
const std::string& llname = {});
|
||||
// Blind pointer version that's deprecated as of LLVM13:
|
||||
llvm::Value* op_load(llvm::Value* ptr, const std::string& llname = {});
|
||||
|
||||
llvm::Value* op_gather(llvm::Value* ptr, llvm::Value* index);
|
||||
llvm::Value* op_gather(llvm::Type* src_type, llvm::Value* src_ptr,
|
||||
llvm::Value* wide_index);
|
||||
|
||||
/// Store to a dereferenced pointer
|
||||
/// respecting the current mask & masking_enabled flag: *ptr = val
|
||||
@@ -894,8 +921,8 @@ public:
|
||||
/// converting it to the native mask type for storage: *ptr = llvm_mask_to_native(val);
|
||||
void op_store_mask(llvm::Value* llvm_mask, llvm::Value* native_mask_ptr);
|
||||
|
||||
void op_scatter(llvm::Value* wide_val, llvm::Value* ptr,
|
||||
llvm::Value* wide_index);
|
||||
void op_scatter(llvm::Value* wide_val, llvm::Type* src_type,
|
||||
llvm::Value* src_ptr, llvm::Value* wide_index);
|
||||
|
||||
// N.B. "GEP" -- GetElementPointer -- is a particular LLVM-ism that is
|
||||
// the means for retrieving elements from some kind of aggregate: the
|
||||
@@ -908,17 +935,11 @@ public:
|
||||
/// we're retrieving.
|
||||
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, llvm::Value* elem,
|
||||
const std::string& llname = {});
|
||||
// Blind pointer version that's deprecated as of LLVM13:
|
||||
llvm::Value* GEP(llvm::Value* ptr, llvm::Value* elem,
|
||||
const std::string& llname = {});
|
||||
|
||||
/// Generate a GEP (get element pointer) with an integer element
|
||||
/// offset. `type` is the type of the data we're retrieving.
|
||||
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, int elem,
|
||||
const std::string& llname = {});
|
||||
// Blind pointer version that's deprecated as of LLVM13:
|
||||
llvm::Value* GEP(llvm::Value* ptr, int elem,
|
||||
const std::string& llname = {});
|
||||
|
||||
/// Generate a GEP (get element pointer) with two integer element
|
||||
/// offsets. This is just a special (and common) case of GEP where
|
||||
@@ -927,9 +948,14 @@ public:
|
||||
/// retrieving.
|
||||
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, int elem1, int elem2,
|
||||
const std::string& llname = {});
|
||||
// Blind pointer version that's deprecated as of LLVM13:
|
||||
llvm::Value* GEP(llvm::Value* ptr, int elem1, int elem2,
|
||||
const std::string& llname = {});
|
||||
|
||||
/// Generate a GEP (get element pointer) with three integer element
|
||||
/// offsets. This is just a special (and common) case of GEP where
|
||||
/// we have a 3-level hierarchy and we have fixed element indices
|
||||
/// that are known at compile time. `type` is the type of the data we're
|
||||
/// retrieving.
|
||||
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, int elem1, int elem2,
|
||||
int elem3, const std::string& llname = {});
|
||||
|
||||
// Arithmetic ops. It auto-detects the type (int vs float).
|
||||
// ...
|
||||
@@ -1018,6 +1044,7 @@ public:
|
||||
private:
|
||||
class MemoryManager;
|
||||
class IRBuilder;
|
||||
struct NewPassManager;
|
||||
|
||||
void SetupLLVM();
|
||||
IRBuilder& builder();
|
||||
@@ -1035,8 +1062,10 @@ private:
|
||||
llvm::Function* m_current_function;
|
||||
llvm::legacy::PassManager* m_llvm_module_passes;
|
||||
llvm::legacy::FunctionPassManager* m_llvm_func_passes;
|
||||
NewPassManager* m_new_pass_manager;
|
||||
llvm::ExecutionEngine* m_llvm_exec;
|
||||
TargetISA m_target_isa = TargetISA::UNKNOWN;
|
||||
llvm::TargetMachine* m_nvptx_target_machine;
|
||||
|
||||
std::vector<llvm::BasicBlock*> m_return_block; // stack for func call
|
||||
std::vector<llvm::BasicBlock*> m_loop_after_block; // stack for break
|
||||
@@ -1050,6 +1079,7 @@ private:
|
||||
llvm::Type* m_llvm_type_int;
|
||||
llvm::Type* m_llvm_type_int8;
|
||||
llvm::Type* m_llvm_type_int16;
|
||||
llvm::Type* m_llvm_type_int64;
|
||||
llvm::Type* m_llvm_type_addrint;
|
||||
llvm::Type* m_llvm_type_bool;
|
||||
llvm::Type* m_llvm_type_char;
|
||||
@@ -1062,6 +1092,8 @@ private:
|
||||
llvm::PointerType* m_llvm_type_char_ptr;
|
||||
llvm::PointerType* m_llvm_type_bool_ptr;
|
||||
llvm::PointerType* m_llvm_type_int_ptr;
|
||||
llvm::PointerType* m_llvm_type_int8_ptr;
|
||||
llvm::PointerType* m_llvm_type_int64_ptr;
|
||||
llvm::PointerType* m_llvm_type_float_ptr;
|
||||
llvm::PointerType* m_llvm_type_longlong_ptr;
|
||||
llvm::PointerType* m_llvm_type_triple_ptr;
|
||||
@@ -1194,6 +1226,9 @@ private:
|
||||
llvm::Value* half_vec_2);
|
||||
llvm::Value* op_combine_4x_vectors(llvm::Value* half_vec_1,
|
||||
llvm::Value* half_vec_2);
|
||||
|
||||
void setup_legacy_optimization_passes(int optlevel, bool target_host);
|
||||
void setup_new_optimization_passes(int optlevel, bool target_host);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -171,22 +171,13 @@ public:
|
||||
}
|
||||
|
||||
|
||||
OSL_FORCEINLINE ValueType value() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
OSL_FORCEINLINE ValueType value() const { return m_value; }
|
||||
|
||||
// count number of active bits
|
||||
OSL_FORCEINLINE int count() const
|
||||
{
|
||||
return OSL::popcount(m_value);
|
||||
}
|
||||
OSL_FORCEINLINE int count() const { return OSL::popcount(m_value); }
|
||||
|
||||
// NOTE: undefined result if no bits are on
|
||||
OSL_FORCEINLINE int first_on() const
|
||||
{
|
||||
return OSL::countr_zero(m_value);
|
||||
}
|
||||
OSL_FORCEINLINE int first_on() const { return OSL::countr_zero(m_value); }
|
||||
|
||||
OSL_FORCEINLINE Mask invert() const
|
||||
{
|
||||
@@ -239,10 +230,7 @@ public:
|
||||
return (m_value != static_cast<ValueType>(0));
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE bool any_off() const
|
||||
{
|
||||
return (m_value < valid_bits);
|
||||
}
|
||||
OSL_FORCEINLINE bool any_off() const { return (m_value < valid_bits); }
|
||||
|
||||
OSL_FORCEINLINE bool any_off(const Mask& mask) const
|
||||
{
|
||||
@@ -257,39 +245,27 @@ public:
|
||||
// So really only set_on or set_off is required
|
||||
// Choose to not provide a generic set(int lane, bool flag)
|
||||
|
||||
OSL_FORCEINLINE void set_on(int lane)
|
||||
{
|
||||
m_value |= (1 << lane);
|
||||
}
|
||||
OSL_FORCEINLINE void set_on(int lane) { m_value |= (1 << lane); }
|
||||
|
||||
OSL_FORCEINLINE void set_on_if(int lane, bool cond)
|
||||
{
|
||||
m_value |= (cond << lane);
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE void set_all_on()
|
||||
{
|
||||
m_value = valid_bits;
|
||||
}
|
||||
OSL_FORCEINLINE void set_all_on() { m_value = valid_bits; }
|
||||
OSL_FORCEINLINE void set_count_on(int count)
|
||||
{
|
||||
m_value = valid_bits >> (width - count);
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE void set_off(int lane)
|
||||
{
|
||||
m_value &= (~(1 << lane));
|
||||
}
|
||||
OSL_FORCEINLINE void set_off(int lane) { m_value &= (~(1 << lane)); }
|
||||
|
||||
OSL_FORCEINLINE void set_off_if(int lane, bool cond)
|
||||
{
|
||||
m_value &= (~(cond << lane));
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE void set_all_off()
|
||||
{
|
||||
m_value = static_cast<ValueType>(0);
|
||||
}
|
||||
OSL_FORCEINLINE void set_all_off() { m_value = static_cast<ValueType>(0); }
|
||||
|
||||
OSL_FORCEINLINE bool operator==(const Mask& other) const
|
||||
{
|
||||
@@ -323,10 +299,7 @@ public:
|
||||
return Mask(m_value | other.m_value);
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE Mask operator~() const
|
||||
{
|
||||
return invert();
|
||||
}
|
||||
OSL_FORCEINLINE Mask operator~() const { return invert(); }
|
||||
|
||||
|
||||
template<int MinOccupancyT, int MaxOccupancyT = width, typename FunctorT>
|
||||
|
||||
@@ -109,14 +109,8 @@ OSL_ALIGNAS(16) ClosureComponent : public ClosureColor
|
||||
Vec3 w; ///< Weight of this component
|
||||
|
||||
/// Handy method for getting the parameter memory as a void*.
|
||||
OSL_HOSTDEVICE void* data()
|
||||
{
|
||||
return (char*)(this + 1);
|
||||
}
|
||||
OSL_HOSTDEVICE const void* data() const
|
||||
{
|
||||
return (const char*)(this + 1);
|
||||
}
|
||||
OSL_HOSTDEVICE void* data() { return (char*)(this + 1); }
|
||||
OSL_HOSTDEVICE const void* data() const { return (const char*)(this + 1); }
|
||||
|
||||
/// Handy methods for extracting the underlying parameters as a struct
|
||||
template<typename T> OSL_HOSTDEVICE const T* as() const
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#cmakedefine01 OSL_USE_OPTIX
|
||||
#cmakedefine01 OSL_BUILD_BATCHED
|
||||
#define OSL_USE_BATCHED OSL_BUILD_BATCHED
|
||||
|
||||
|
||||
#include <OSL/export.h>
|
||||
#include <OSL/oslversion.h>
|
||||
#include <OSL/platform.h>
|
||||
@@ -62,8 +67,6 @@
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
#define OSL_USE_BATCHED @BUILD_BATCHED@
|
||||
|
||||
/// Various compile-time defaults are defined here that could, in
|
||||
/// principle, be redefined if you are using OSL in some particular
|
||||
/// renderer that wanted things a different way.
|
||||
@@ -121,6 +124,7 @@ using OIIO::TypeInt;
|
||||
using OIIO::TypeFloat2;
|
||||
using OIIO::TypeVector2;
|
||||
using OIIO::TypeVector4;
|
||||
using OIIO::TypeUInt64;
|
||||
|
||||
using OIIO::Strutil::print;
|
||||
|
||||
@@ -131,6 +135,149 @@ fmtformat(const Str& fmt, Args&&... args)
|
||||
return OIIO::Strutil::fmt::format(fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// TODO: notice the fmt argument is not templatised, this is because
|
||||
// no implicit conversion exists betwen OSL::string_view and ::fmt::string_view
|
||||
// so we choose to only accept OSL::string_view and explicitly convert to ::fmt::string_view
|
||||
// OIIO should fix this if possible.
|
||||
template<typename OutIt, typename... Args>
|
||||
OSL_NODISCARD inline auto
|
||||
fmtformat_to_n(OutIt &out, size_t n, const string_view& fmt, Args&&... args)
|
||||
{
|
||||
// DOES NOT EXIST AS PUBLIC API
|
||||
//return OIIO::Strutil::fmt::format_to_n(out, n, fmt, std::forward<Args>(args)...);
|
||||
// So call directly into underlying fmt library OIIO is using
|
||||
// TODO: Add format_to_n as a public API in OIIO
|
||||
return ::fmt::format_to_n(out, n, ::fmt::string_view{fmt.begin(), fmt.length()}, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
/// OSL_USTRINGREP_IS_HASH will be 1 if the build-time option was enabled to
|
||||
/// make the ustringrep be a ustringhash, rather than a ustring directly.
|
||||
#cmakedefine01 OSL_USTRINGREP_IS_HASH
|
||||
|
||||
#if OSL_USTRINGREP_IS_HASH
|
||||
/// ustringrep is the class we use to represent strings in the shader.
|
||||
using ustringrep = ustringhash;
|
||||
#else
|
||||
/// ustringrep is the class we use to represent strings in the shader.
|
||||
using ustringrep = ustring;
|
||||
#endif
|
||||
|
||||
/// ustringhash_pod is the type we use to pass hash data in llvm function calls.
|
||||
using ustringhash_pod = size_t;
|
||||
|
||||
#if OSL_USTRINGREP_IS_HASH
|
||||
/// ustring_pod is the type we use to pass string data in llvm function calls.
|
||||
using ustring_pod = ustringhash_pod;
|
||||
#else
|
||||
/// ustring_pod is the type we use to pass string data in llvm function calls.
|
||||
using ustring_pod = const char*;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/// Convenience function to convert to a ustring.
|
||||
inline ustring
|
||||
ustring_from(ustringhash h)
|
||||
{
|
||||
return ustring::from_hash(h.hash());
|
||||
}
|
||||
|
||||
/// Convenience function to convert to a ustring.
|
||||
inline ustring
|
||||
ustring_from(ustring u)
|
||||
{
|
||||
return u;
|
||||
}
|
||||
|
||||
/// Convenience function to convert to a ustring.
|
||||
inline ustring
|
||||
ustring_from(string_view s)
|
||||
{
|
||||
return ustring(s);
|
||||
}
|
||||
|
||||
|
||||
/// Convenience function to convert to a ustringhash.
|
||||
inline ustringhash
|
||||
ustringhash_from(ustringhash u)
|
||||
{
|
||||
return u;
|
||||
}
|
||||
|
||||
/// Convenience function to convert USTRINGHASH_POD to a ustringhash.
|
||||
inline ustringhash
|
||||
ustringhash_from(ustringhash_pod u)
|
||||
{
|
||||
#if OIIO_VERSION_GREATER_EQUAL(2, 4, 10)
|
||||
return ustringhash{u};
|
||||
#else
|
||||
// No constructor taking the pod type existed previously
|
||||
// so bitcast it.
|
||||
return OSL::bitcast<ustringhash>(u);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Convenience function to convert to a ustringhash.
|
||||
inline ustringhash
|
||||
ustringhash_from(ustring u)
|
||||
{
|
||||
ustringhash ret;
|
||||
// Not legal to call uhash on an empty ustring
|
||||
if(!u.empty())
|
||||
ret = u.uhash();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/// Convenience function to convert to a ustringrep.
|
||||
inline ustringrep
|
||||
ustringrep_from(ustringhash h)
|
||||
{
|
||||
#if OSL_USTRINGREP_IS_HASH
|
||||
return h;
|
||||
#else
|
||||
return ustring::from_hash(h.hash());
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Convenience function to convert to a ustringrep.
|
||||
inline ustringrep
|
||||
ustringrep_from(ustring u)
|
||||
{
|
||||
#if OSL_USTRINGREP_IS_HASH
|
||||
return u.hash();
|
||||
#else
|
||||
return u;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Convenience function to convert to a ustringrep.
|
||||
inline ustringrep
|
||||
ustringrep_from(string_view s)
|
||||
{
|
||||
ustring u(s);
|
||||
#if OSL_USTRINGREP_IS_HASH
|
||||
return u.hash();
|
||||
#else
|
||||
return u;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
using TypeDesc_pod = int64_t;
|
||||
|
||||
static_assert(sizeof(TypeDesc_pod) == sizeof(TypeDesc),
|
||||
"TypeDesc size differs from its POD counterpart");
|
||||
|
||||
/// Convenience function to convert to a TypeDesc.
|
||||
inline TypeDesc
|
||||
TypeDesc_from(TypeDesc_pod type)
|
||||
{
|
||||
return OSL::bitcast<OSL::TypeDesc>(type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// N.B. SymArena is not really "configuration", but we cram it here for
|
||||
@@ -143,6 +290,7 @@ enum class SymArena {
|
||||
Heap, // Belongs to context heap
|
||||
Outputs, // Belongs to output arena
|
||||
UserData, // UserData arena
|
||||
Interactive, // Interactively edited variables
|
||||
// ShaderGlobals, // RESERVED
|
||||
};
|
||||
|
||||
@@ -229,7 +377,8 @@ OSL_NAMESPACE_EXIT
|
||||
|
||||
namespace std { // not necessary in C++17, then we can just say std::hash
|
||||
#ifndef OIIO_USTRING_HAS_STDHASH
|
||||
// Not a new enough OIIO to define std::hash<ustring>, so we'll do it
|
||||
// Not a new enough OIIO to define std::hash<ustring>, so we'll do it.
|
||||
// This can be removed once OIIO minimum is 2.4.5+ or >=2.5.0.1
|
||||
template<> struct hash<OSL::ustring> {
|
||||
std::size_t operator()(OSL::ustring u) const noexcept { return u.hash(); }
|
||||
};
|
||||
@@ -243,7 +392,8 @@ template<> struct hash<OSL::ustringhash> {
|
||||
};
|
||||
#endif
|
||||
|
||||
// Not necessary once minimum OIIO defines operator< for ustringhash
|
||||
// Not necessary once minimum OIIO defines operator< for ustringhash.
|
||||
// This can be removed once OIIO minimum is 2.4.5+ or >=2.5.0.1
|
||||
template<> struct less<OSL::ustringhash> {
|
||||
OSL_HOSTDEVICE constexpr bool operator()(OSL::ustringhash u,
|
||||
OSL::ustringhash v) const noexcept
|
||||
@@ -252,3 +402,21 @@ template<> struct less<OSL::ustringhash> {
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
|
||||
#ifndef OIIO_HAS_USTRINGHASH_FORMATTER
|
||||
// OIIO is too old to have fmt custom formatter for ustringhash.
|
||||
// This can be removed once OIIO minimum is 2.4.5+ or >=2.5.0.1
|
||||
FMT_BEGIN_NAMESPACE
|
||||
template<> struct formatter<OIIO::ustringhash> : formatter<fmt::string_view, char> {
|
||||
template<typename FormatContext>
|
||||
auto format(const OIIO::ustringhash& h, FormatContext& ctx)
|
||||
-> decltype(ctx.out()) const
|
||||
{
|
||||
OIIO::ustring u(h);
|
||||
return formatter<fmt::string_view, char>::format({ u.data(), u.size() },
|
||||
ctx);
|
||||
}
|
||||
};
|
||||
FMT_END_NAMESPACE
|
||||
#endif
|
||||
|
||||
@@ -51,7 +51,8 @@ class ShadingSystemImpl;
|
||||
}
|
||||
|
||||
#ifdef __CUDA_ARCH__
|
||||
# define STRING_PARAMS(x) UStringHash::Hash(__OSL_STRINGIFY(x))
|
||||
# define STRING_PARAMS(x) \
|
||||
UStringHash::HashConstEval<UStringHash::Hash(__OSL_STRINGIFY(x))>
|
||||
#else
|
||||
# define STRING_PARAMS(x) StringParams::x
|
||||
#endif
|
||||
@@ -111,6 +112,67 @@ public:
|
||||
|
||||
|
||||
|
||||
/// Parameter property hint bitflag values. The enum values must be powers of
|
||||
/// two so they can be combined with bitwise operators.
|
||||
enum class ParamHints : uint32_t {
|
||||
/// `none`: No special properties
|
||||
none = 0,
|
||||
/// `interpolated`: This parameter may be an interpolated "user data" or
|
||||
/// "geometric primitive" variable, and so may take on different values at
|
||||
/// different points on the surface or on different objects that share the
|
||||
/// same material. Any optimization of the shader should take this into
|
||||
/// account.
|
||||
interpolated = 1,
|
||||
/// `interactive`: Parameter may have its value interactively modified by
|
||||
/// subsequent ReParameter calls. Any optimization of the shader should
|
||||
/// take this into account.
|
||||
interactive = 2
|
||||
};
|
||||
|
||||
inline constexpr ParamHints
|
||||
operator|(ParamHints a, ParamHints b)
|
||||
{
|
||||
return static_cast<ParamHints>(static_cast<int>(a) | static_cast<int>(b));
|
||||
}
|
||||
|
||||
inline constexpr ParamHints
|
||||
operator&(ParamHints a, ParamHints b)
|
||||
{
|
||||
return static_cast<ParamHints>(static_cast<int>(a) & static_cast<int>(b));
|
||||
}
|
||||
|
||||
inline ParamHints&
|
||||
operator|=(ParamHints& a, ParamHints b)
|
||||
{
|
||||
a = a | b;
|
||||
return a;
|
||||
}
|
||||
|
||||
inline ParamHints&
|
||||
operator&=(ParamHints& a, ParamHints b)
|
||||
{
|
||||
a = a & b;
|
||||
return a;
|
||||
}
|
||||
|
||||
inline constexpr ParamHints
|
||||
operator~(ParamHints a)
|
||||
{
|
||||
return static_cast<ParamHints>(~static_cast<int>(a));
|
||||
}
|
||||
|
||||
inline ParamHints&
|
||||
set(ParamHints& a, ParamHints b, bool on = true)
|
||||
{
|
||||
if (on)
|
||||
a |= b;
|
||||
else
|
||||
a &= ~b;
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class OSLEXECPUBLIC ShadingSystem {
|
||||
public:
|
||||
ShadingSystem(RendererServices* renderer = NULL,
|
||||
@@ -173,7 +235,7 @@ public:
|
||||
/// int lazyerror Run layers lazily even if they have error
|
||||
/// ops after optimization (1).
|
||||
/// int lazy_userdata Retrieve userdata lazily (0).
|
||||
/// int userdata_isconnected Should lockgeom=0 params (that may
|
||||
/// int userdata_isconnected Should interpolated=1 params (that may
|
||||
/// receive userdata) return true from
|
||||
/// isconnected()? (0)
|
||||
/// int greedyjit Optimize and compile all shaders up front,
|
||||
@@ -200,11 +262,16 @@ public:
|
||||
/// that don't specify it (1). Lockgeom
|
||||
/// means a param CANNOT be overridden by
|
||||
/// interpolated geometric parameters.
|
||||
/// This option is slated for deprecation.
|
||||
/// 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.
|
||||
/// int max_optix_groupdata_alloc Maximum stack size for an OSL-managed
|
||||
/// groupdata buffer when targeting OptiX (0).
|
||||
/// OSL expects a pointer to a buffer when
|
||||
/// requirements exceed max allocation.
|
||||
/// 3. Attributes that that are intended for developers debugging
|
||||
/// liboslexec itself:
|
||||
/// These attributes may be helpful for liboslexec developers or
|
||||
@@ -219,7 +286,7 @@ public:
|
||||
/// opt_peephole, opt_coalesce_temps, opt_assign, opt_mix
|
||||
/// opt_merge_instances, opt_merge_instance_with_userdata,
|
||||
/// opt_fold_getattribute, opt_middleman, opt_texture_handle
|
||||
/// opt_seed_bblock_aliases
|
||||
/// opt_seed_bblock_aliases, opt_groupdata
|
||||
/// int opt_passes Number of optimization passes per layer (10)
|
||||
/// int llvm_optimize Which of several LLVM optimize strategies (1)
|
||||
/// int llvm_debug Set LLVM extra debug level (0)
|
||||
@@ -427,12 +494,15 @@ public:
|
||||
/// ptr attributes_needed Retrieves a pointer to the ustring array
|
||||
/// containing the names of the needed attributes.
|
||||
/// Note that if the same attribute
|
||||
/// is requested in multiple scopes, it will
|
||||
/// is requested in multiple scopes, or with
|
||||
/// multiple different types, it will
|
||||
/// appear in the array multiple times - once for
|
||||
/// each scope in which is is queried.
|
||||
/// each scope/type in which is is queried.
|
||||
/// ptr attribute_scopes Retrieves a pointer to a ustring array containing
|
||||
/// the scopes associated with each attribute query
|
||||
/// in the attributes_needed array.
|
||||
/// ptr attribute_types Retrieves a pointer to the array of
|
||||
/// TypeDesc describing the attributes.
|
||||
/// int unknown_attributes_needed Nonzero if additional attributes may be
|
||||
/// needed, whose names will not be known
|
||||
/// until the shader actually runs.
|
||||
@@ -443,6 +513,15 @@ public:
|
||||
/// string entry_layers[] List of entry point layers.
|
||||
/// string pickle Retrieves a serialized representation
|
||||
/// of the shader group declaration.
|
||||
/// int llvm_groupdata_size Size of the GroupData struct.
|
||||
/// ptr interactive_params Pointer to the memory block containing
|
||||
/// host-side interactive parameter values
|
||||
/// for this shader group.
|
||||
/// ptr device_interactive_params
|
||||
/// Pointer to the memory block containing
|
||||
/// device-side interactive parameter values
|
||||
/// for this shader group.
|
||||
///
|
||||
/// Note: the attributes referred to as "string" are actually on the app
|
||||
/// side as ustring or const char* (they have the same data layout), NOT
|
||||
/// std::string!
|
||||
@@ -530,15 +609,50 @@ public:
|
||||
bool ShaderGroupEnd(ShaderGroup& group);
|
||||
|
||||
/// Set a parameter of the next shader that will be added to the group,
|
||||
/// optionally setting the 'lockgeom' metadata for that parameter
|
||||
/// (despite how it may have been set in the shader). If lockgeom is
|
||||
/// false, it means that this parameter should NOT be considered locked
|
||||
/// against changes by the geometry, and therefore the shader should not
|
||||
/// optimize assuming that the instance value (the 'val' specified by
|
||||
/// this call) is a constant.
|
||||
/// optionally setting or overriding properties with the `hints` argument.
|
||||
/// Individual `hints` bits are defined and documented by the ParamHints
|
||||
/// enum class.
|
||||
bool Parameter(ShaderGroup& group, string_view name, TypeDesc t,
|
||||
const void* val, bool lockgeom = true);
|
||||
const void* val, ParamHints hints = ParamHints::none);
|
||||
|
||||
/// DEPRECATED(1.13) Parameter() call: instead of a full ParamHints
|
||||
/// argument, there is just a bool `lockgeom` that default to true, and
|
||||
/// when set to false is the same thing as setting
|
||||
/// `ParamHints::interpolated`.
|
||||
bool Parameter(ShaderGroup& group, string_view name, TypeDesc t,
|
||||
const void* val, bool lockgeom)
|
||||
{
|
||||
return Parameter(group, name, t, val,
|
||||
lockgeom ? ParamHints::none
|
||||
: ParamHints::interpolated);
|
||||
}
|
||||
|
||||
// Shortcuts for param passing a single int, float, or string.
|
||||
bool Parameter(ShaderGroup& group, string_view name, int val,
|
||||
ParamHints hints = ParamHints::none)
|
||||
{
|
||||
return Parameter(group, name, TypeDesc::INT, &val, hints);
|
||||
}
|
||||
bool Parameter(ShaderGroup& group, string_view name, float val,
|
||||
ParamHints hints = ParamHints::none)
|
||||
{
|
||||
return Parameter(group, name, TypeDesc::FLOAT, &val, hints);
|
||||
}
|
||||
bool Parameter(ShaderGroup& group, string_view name, const std::string& val,
|
||||
ParamHints hints = ParamHints::none)
|
||||
{
|
||||
const char* s = val.c_str();
|
||||
return Parameter(group, name, TypeDesc::STRING, &s, hints);
|
||||
}
|
||||
bool Parameter(ShaderGroup& group, string_view name, ustring val,
|
||||
ParamHints hints = ParamHints::none)
|
||||
{
|
||||
return Parameter(group, name, TypeDesc::STRING, (const char**)&val,
|
||||
hints);
|
||||
}
|
||||
|
||||
// DEPRECATED(1.13): use the version above that takes ParamHints.
|
||||
// This is the old version that takes `bool lockgeom`.
|
||||
bool Parameter(ShaderGroup& group, string_view name, int val,
|
||||
bool lockgeom = true)
|
||||
{
|
||||
@@ -589,10 +703,8 @@ public:
|
||||
/// Replace a parameter value in a previously-declared shader group.
|
||||
/// This is meant to called after the ShaderGroupBegin/End, but will
|
||||
/// fail if the shader has already been irrevocably optimized/compiled,
|
||||
/// unless the particular parameter is marked as lockgeom=0 (which
|
||||
/// indicates that it's a parameter that may be overridden by the
|
||||
/// geometric primitive). This call gives you a way of changing the
|
||||
/// instance value, even if it's not a geometric override.
|
||||
/// unless the particular parameter is marked as either interpolated=1
|
||||
/// or interactive=1.
|
||||
bool ReParameter(ShaderGroup& group, string_view layername,
|
||||
string_view paramname, TypeDesc type, const void* val);
|
||||
// Shortcuts for param passing a single int, float, or string.
|
||||
@@ -628,13 +740,22 @@ public:
|
||||
// above that take an explicit `ShaderGroup&`, which are thread-safe
|
||||
// and re-entrant.
|
||||
bool Parameter(string_view name, TypeDesc t, const void* val,
|
||||
bool lockgeom = true);
|
||||
ParamHints hints = ParamHints::none);
|
||||
bool Shader(string_view shaderusage, string_view shadername,
|
||||
string_view layername);
|
||||
bool ConnectShaders(string_view srclayer, string_view srcparam,
|
||||
string_view dstlayer, string_view dstparam);
|
||||
bool ShaderGroupEnd(void);
|
||||
|
||||
// DEPRECATED(1.13): use the version above that takes ParamHints.
|
||||
// This is the old version that takes `bool lockgeom`.
|
||||
bool Parameter(string_view name, TypeDesc t, const void* val, bool lockgeom)
|
||||
{
|
||||
return Parameter(name, t, val,
|
||||
lockgeom ? ParamHints::none
|
||||
: ParamHints::interpolated);
|
||||
}
|
||||
|
||||
/// Create a per-thread data needed for shader execution. It's very
|
||||
/// important for the app to never use a PerThreadInfo from more than
|
||||
/// one thread (and probably a good idea allocate only one PerThreadInfo
|
||||
@@ -668,9 +789,10 @@ public:
|
||||
/// execute_layer of the last (presumably group entry) layer, and
|
||||
/// execute_cleanup. If run==false, just do the binding and setup, don't
|
||||
/// actually run the shader.
|
||||
bool execute(ShadingContext& ctx, ShaderGroup& group, int shadeindex,
|
||||
ShaderGlobals& globals, void* userdata_base_ptr,
|
||||
void* output_base_ptr, bool run = true);
|
||||
bool execute(ShadingContext& ctx, ShaderGroup& group, int thread_index,
|
||||
int shadeindex, ShaderGlobals& globals,
|
||||
void* userdata_base_ptr, void* output_base_ptr,
|
||||
bool run = true);
|
||||
|
||||
/// Future execute signature that will be range based. Shader globals will be
|
||||
/// obtained from renderer services.
|
||||
@@ -685,7 +807,7 @@ public:
|
||||
bool execute(ShadingContext& ctx, ShaderGroup& group,
|
||||
ShaderGlobals& globals, bool run = true)
|
||||
{
|
||||
return execute(ctx, group, 0, globals, nullptr, nullptr, run);
|
||||
return execute(ctx, group, 0, 0, globals, nullptr, nullptr, run);
|
||||
}
|
||||
|
||||
// DEPRECATED(2.0): ctx pointer
|
||||
@@ -703,14 +825,15 @@ public:
|
||||
/// preparation, but don't actually run the shader. Return true if the
|
||||
/// shader executed, false if it did not (including if the shader itself
|
||||
/// was empty).
|
||||
bool execute_init(ShadingContext& ctx, ShaderGroup& group, int shadeindex,
|
||||
ShaderGlobals& globals, void* userdata_base_ptr,
|
||||
void* output_base_ptr, bool run = true);
|
||||
bool execute_init(ShadingContext& ctx, ShaderGroup& group, int threadindex,
|
||||
int shadeindex, ShaderGlobals& globals,
|
||||
void* userdata_base_ptr, void* output_base_ptr,
|
||||
bool run = true);
|
||||
// DEPRECATED(2.0): no shadeindex or base pointers
|
||||
bool execute_init(ShadingContext& ctx, ShaderGroup& group,
|
||||
ShaderGlobals& globals, bool run = true)
|
||||
{
|
||||
return execute_init(ctx, group, 0, globals, nullptr, nullptr, run);
|
||||
return execute_init(ctx, group, 0, 0, globals, nullptr, nullptr, run);
|
||||
}
|
||||
|
||||
/// Execute the layer whose layernumber is specified, in this context.
|
||||
@@ -718,16 +841,16 @@ public:
|
||||
/// run==true, and that the call to execute_init() returned true. (One
|
||||
/// reason why it might have returned false is if the shader group
|
||||
/// turned out, after optimization, to do nothing.)
|
||||
bool execute_layer(ShadingContext& ctx, int shadeindex,
|
||||
bool execute_layer(ShadingContext& ctx, int threadindex, int shadeindex,
|
||||
ShaderGlobals& globals, void* userdata_base_ptr,
|
||||
void* output_base_ptr, int layernumber);
|
||||
/// Execute the layer by name.
|
||||
bool execute_layer(ShadingContext& ctx, int shadeindex,
|
||||
bool execute_layer(ShadingContext& ctx, int threadindex, int shadeindex,
|
||||
ShaderGlobals& globals, void* userdata_base_ptr,
|
||||
void* output_base_ptr, ustring layername);
|
||||
/// Execute the layer that has the given ShaderSymbol as an output.
|
||||
/// (The symbol is one returned by find_symbol()).
|
||||
bool execute_layer(ShadingContext& ctx, int shadeindex,
|
||||
bool execute_layer(ShadingContext& ctx, int threadindex, int shadeindex,
|
||||
ShaderGlobals& globals, void* userdata_base_ptr,
|
||||
void* output_base_ptr, const ShaderSymbol* symbol);
|
||||
|
||||
@@ -735,17 +858,17 @@ public:
|
||||
bool execute_layer(ShadingContext& ctx, ShaderGlobals& globals,
|
||||
int layernumber)
|
||||
{
|
||||
return execute_layer(ctx, 0, globals, nullptr, nullptr, layernumber);
|
||||
return execute_layer(ctx, 0, 0, globals, nullptr, nullptr, layernumber);
|
||||
}
|
||||
bool execute_layer(ShadingContext& ctx, ShaderGlobals& globals,
|
||||
ustring layername)
|
||||
{
|
||||
return execute_layer(ctx, 0, globals, nullptr, nullptr, layername);
|
||||
return execute_layer(ctx, 0, 0, globals, nullptr, nullptr, layername);
|
||||
}
|
||||
bool execute_layer(ShadingContext& ctx, ShaderGlobals& globals,
|
||||
const ShaderSymbol* symbol)
|
||||
{
|
||||
return execute_layer(ctx, 0, globals, nullptr, nullptr, symbol);
|
||||
return execute_layer(ctx, 0, 0, globals, nullptr, nullptr, symbol);
|
||||
}
|
||||
|
||||
/// Signify that the context is done with the current execution of the
|
||||
@@ -911,6 +1034,19 @@ public:
|
||||
void add_symlocs(cspan<SymLocationDesc> symlocs);
|
||||
void add_symlocs(ShaderGroup* group, cspan<SymLocationDesc> symlocs);
|
||||
|
||||
// Find the SymLocationDesc for this named param, returning its pointer
|
||||
// or nullptr if that name is not found.
|
||||
const SymLocationDesc* find_symloc(ustring name) const;
|
||||
const SymLocationDesc* find_symloc(const ShaderGroup* group,
|
||||
ustring name) const;
|
||||
|
||||
// Find the SymLocationDesc for this named param but only if it matches
|
||||
// the arena type, returning its pointer or nullptr if that name is not
|
||||
// found.
|
||||
const SymLocationDesc* find_symloc(ustring name, SymArena arena) const;
|
||||
const SymLocationDesc* find_symloc(const ShaderGroup* group, ustring name,
|
||||
SymArena arena) const;
|
||||
|
||||
/// Ensure that the group has been optimized and optionally JITed. The ctx pointer
|
||||
/// supplies a ShadingContext to use.
|
||||
void optimize_group(ShaderGroup* group, ShadingContext* ctx,
|
||||
@@ -976,6 +1112,15 @@ public:
|
||||
static bool convert_value(void* dst, TypeDesc dsttype, const void* src,
|
||||
TypeDesc srctype);
|
||||
|
||||
/// Tell the ShadingSystem if there are functions that should or should not
|
||||
/// be inlined during LLVM optimization. Functions that are not registered
|
||||
/// will not receive any special treatment, and may or may not be inlined.
|
||||
void register_inline_function(ustring name);
|
||||
void unregister_inline_function(ustring name);
|
||||
void register_noinline_function(ustring name);
|
||||
void unregister_noinline_function(ustring name);
|
||||
|
||||
|
||||
private:
|
||||
pvt::ShadingSystemImpl* m_impl;
|
||||
};
|
||||
|
||||
@@ -18,10 +18,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#include <OSL/oslversion.h>
|
||||
|
||||
#if defined(__x86_64__) && !defined(__CUDA_ARCH__)
|
||||
# include <x86intrin.h>
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Detect which compiler and version we're using
|
||||
@@ -202,9 +206,14 @@
|
||||
# define OSL_CLANG_PRAGMA(UnQuotedPragma)
|
||||
# endif
|
||||
# if defined(__INTEL_COMPILER)
|
||||
# define OSL_INTEL_PRAGMA(UnQuotedPragma) OSL_PRAGMA(UnQuotedPragma)
|
||||
# define OSL_INTEL_CLASSIC_PRAGMA(UnQuotedPragma) OSL_PRAGMA(UnQuotedPragma)
|
||||
# else
|
||||
# define OSL_INTEL_PRAGMA(UnQuotedPragma)
|
||||
# define OSL_INTEL_CLASSIC_PRAGMA(UnQuotedPragma)
|
||||
# endif
|
||||
# if defined(__INTEL_LLVM_COMPILER)
|
||||
# define OSL_INTEL_LLVM_PRAGMA(UnQuotedPragma) OSL_PRAGMA(UnQuotedPragma)
|
||||
# else
|
||||
# define OSL_INTEL_LLVM_PRAGMA(UnQuotedPragma)
|
||||
# endif
|
||||
# define OSL_MSVS_PRAGMA(UnQuotedPragma)
|
||||
#elif defined(_MSC_VER)
|
||||
@@ -214,7 +223,8 @@
|
||||
# define OSL_PRAGMA_VISIBILITY_POP /* N/A on MSVS */
|
||||
# define OSL_GCC_PRAGMA(UnQuotedPragma)
|
||||
# define OSL_CLANG_PRAGMA(UnQuotedPragma)
|
||||
# define OSL_INTEL_PRAGMA(UnQuotedPragma)
|
||||
# define OSL_INTEL_CLASSIC_PRAGMA(UnQuotedPragma)
|
||||
# define OSL_INTEL_LLVM_PRAGMA(UnQuotedPragma)
|
||||
# define OSL_MSVS_PRAGMA(UnQuotedPragma) OSL_PRAGMA(UnQuotedPragma)
|
||||
#else
|
||||
# define OSL_PRAGMA_WARNING_PUSH
|
||||
@@ -223,10 +233,14 @@
|
||||
# define OSL_PRAGMA_VISIBILITY_POP
|
||||
# define OSL_GCC_PRAGMA(UnQuotedPragma)
|
||||
# define OSL_CLANG_PRAGMA(UnQuotedPragma)
|
||||
# define OSL_INTEL_PRAGMA(UnQuotedPragma)
|
||||
# define OSL_INTEL_CLASSIC_PRAGMA(UnQuotedPragma)
|
||||
# define OSL_INTEL_LLVM_PRAGMA(UnQuotedPragma)
|
||||
# define OSL_MSVS_PRAGMA(UnQuotedPragma)
|
||||
#endif
|
||||
|
||||
// A pragma that applies to both icc and icx
|
||||
#define OSL_INTEL_PRAGMA(UnQuotedPragma) OSL_INTEL_CLASSIC_PRAGMA(UnQuotedPragma) OSL_INTEL_LLVM_PRAGMA(UnQuotedPragma)
|
||||
|
||||
#ifdef __clang__
|
||||
#define OSL_CLANG_ATTRIBUTE(value) __attribute__((value))
|
||||
#else
|
||||
@@ -499,6 +513,72 @@
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
|
||||
/// Standards-compliant bit cast of two equally sized types. This is used
|
||||
/// equivalently to C++20 std::bit_cast, but it works prior to C++20 and
|
||||
/// it has the right decorators to work with Cuda.
|
||||
/// @version 1.13.2
|
||||
template <typename To, typename From>
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE To bitcast(const From& src) noexcept {
|
||||
// NOTE: this is the only standards compliant way of doing this type of casting,
|
||||
// luckily the compilers we care about know how to optimize away this idiom.
|
||||
static_assert(sizeof(From) == sizeof(To),
|
||||
"bit_cast must be between objects of the same size");
|
||||
To dst;
|
||||
memcpy((void*)&dst, &src, sizeof(From));
|
||||
return dst;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__) && !defined(__CUDA_ARCH__) && \
|
||||
(defined(__INTEL_COMPILER) || defined(__INTEL_LLVM_COMPILER) \
|
||||
|| OSL_CLANG_VERSION >= 100000 || OSL_APPLE_CLANG_VERSION >= 130000)
|
||||
// On x86/x86_64 for certain compilers we can use Intel CPU intrinsics for
|
||||
// some common bitcast cases that might be even more understandable to the
|
||||
// compiler and generate better code without its getting confused about the
|
||||
// memcpy in the general case. We're a bit conservative with the compiler
|
||||
// version checks here, it may be that some earlier versions support these
|
||||
// intrinsics.
|
||||
|
||||
template<> OSL_FORCEINLINE uint32_t bitcast<uint32_t, float>(const float& val) noexcept {
|
||||
return static_cast<uint32_t>(_castf32_u32(val));
|
||||
}
|
||||
template<> OSL_FORCEINLINE int32_t bitcast<int32_t, float>(const float& val) noexcept {
|
||||
return static_cast<int32_t>(_castf32_u32(val));
|
||||
}
|
||||
template<> OSL_FORCEINLINE float bitcast<float, uint32_t>(const uint32_t& val) noexcept {
|
||||
return _castu32_f32(val);
|
||||
}
|
||||
template<> OSL_FORCEINLINE float bitcast<float, int32_t>(const int32_t& val) noexcept {
|
||||
return _castu32_f32(val);
|
||||
}
|
||||
template<> OSL_FORCEINLINE uint64_t bitcast<uint64_t, double>(const double& val) noexcept {
|
||||
return static_cast<uint64_t>(_castf64_u64(val));
|
||||
}
|
||||
template<> OSL_FORCEINLINE int64_t bitcast<int64_t, double>(const double& val) noexcept {
|
||||
return static_cast<int64_t>(_castf64_u64(val));
|
||||
}
|
||||
template<> OSL_FORCEINLINE double bitcast<double, uint64_t>(const uint64_t& val) noexcept {
|
||||
return _castu64_f64(val);
|
||||
}
|
||||
template<> OSL_FORCEINLINE double bitcast<double, int64_t>(const int64_t& val) noexcept {
|
||||
return _castu64_f64(val);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/// OSL_PACK_STRUCTS_* is used to pack a struct or class tightly. Use it like
|
||||
/// the following example. To set the alignment of the struct use the
|
||||
/// alignas(x) directive.
|
||||
///
|
||||
/// OSL_PACK_STRUCTS_BEGIN
|
||||
/// struct alignas(1) Foo {
|
||||
/// char x, y, z;
|
||||
/// };
|
||||
/// OSL_PACK_STRUCTS_END
|
||||
#define OSL_PACK_STRUCTS_BEGIN OSL_PRAGMA(pack(push, 1))
|
||||
#define OSL_PACK_STRUCTS_END OSL_PRAGMA(pack(pop))
|
||||
|
||||
|
||||
#if OSL_CPLUSPLUS_VERSION >= 20
|
||||
using std::assume_aligned;
|
||||
#else
|
||||
|
||||
@@ -2,25 +2,24 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
// clang-format off
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <OSL/encodedtypes.h>
|
||||
#include <OSL/oslconfig.h>
|
||||
#include <OSL/variant.h>
|
||||
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
class RendererServices;
|
||||
template<int WidthT>
|
||||
class BatchedRendererServices;
|
||||
template<int WidthT> class BatchedRendererServices;
|
||||
class ShadingContext;
|
||||
struct ShaderGlobals;
|
||||
class ShaderGroup;
|
||||
|
||||
// Tags for polymorphic dispatch
|
||||
template <int SimdWidthT>
|
||||
class WidthOf {};
|
||||
template<int SimdWidthT> class WidthOf {};
|
||||
|
||||
|
||||
/// Opaque pointer to whatever the renderer uses to represent a
|
||||
@@ -32,6 +31,20 @@ typedef const void* TransformationPtr;
|
||||
typedef void (*PrepareClosureFunc)(RendererServices*, int id, void* data);
|
||||
typedef void (*SetupClosureFunc)(RendererServices*, int id, void* data);
|
||||
|
||||
enum class AttributeSpecBuiltinArg {
|
||||
ShaderGlobalsPointer, // void* (TODO: ideally ShaderGlobals*)
|
||||
ShadeIndex, // int
|
||||
Derivatives, // bool
|
||||
Type, // TypeDesc_pod
|
||||
ArrayIndex, // int, Always zero for non-indexed array lookups.
|
||||
IsArrayLookup, // bool
|
||||
ObjectName, // const char* (TODO: change to ustringhash)
|
||||
AttributeName, // const char* (TODO: change to ustringhash)
|
||||
};
|
||||
|
||||
using AttributeSpecArg = ArgVariant<AttributeSpecBuiltinArg>;
|
||||
using AttributeGetterSpec = FunctionSpec<AttributeSpecArg>;
|
||||
|
||||
// Turn off warnings about unused params for this file, since we have lots
|
||||
// of declarations with stub function bodies.
|
||||
OSL_PRAGMA_WARNING_PUSH
|
||||
@@ -49,11 +62,12 @@ public:
|
||||
|
||||
|
||||
RendererServices(TextureSystem* texsys = NULL);
|
||||
virtual ~RendererServices () { }
|
||||
virtual ~RendererServices() {}
|
||||
|
||||
/// Given the name of a 'feature', return whether this RendererServices
|
||||
/// supports it. Feature names include:
|
||||
/// <none>
|
||||
/// "OptiX"
|
||||
/// "build_attribute_getter"
|
||||
///
|
||||
/// This allows some customization of JIT generated code based on the
|
||||
/// facilities and features of a particular renderer. It also allows
|
||||
@@ -62,28 +76,34 @@ public:
|
||||
/// support it, as long as the OSL runtime only uses that feature if the
|
||||
/// supports("feature") says it's present, thus preserving source
|
||||
/// compatibility.
|
||||
virtual int supports (string_view feature) const { return false; }
|
||||
virtual int supports(string_view feature) const { return false; }
|
||||
|
||||
/// Get the 4x4 matrix that transforms by the specified
|
||||
/// transformation at the given time. Return true if ok, false
|
||||
/// on error.
|
||||
virtual bool get_matrix (ShaderGlobals *sg, Matrix44 &result,
|
||||
TransformationPtr xform, float time) { return false; }
|
||||
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result,
|
||||
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
|
||||
/// error. The default implementation is to use get_matrix and
|
||||
/// invert it, but a particular renderer may have a better technique
|
||||
/// and overload the implementation.
|
||||
virtual bool get_inverse_matrix (ShaderGlobals *sg, Matrix44 &result,
|
||||
TransformationPtr xform, float time);
|
||||
virtual bool get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
|
||||
TransformationPtr xform, float time);
|
||||
|
||||
/// Get the 4x4 matrix that transforms by the specified
|
||||
/// transformation. Return true if ok, false on error. Since no
|
||||
/// time value is given, also return false if the transformation may
|
||||
/// be time-varying.
|
||||
virtual bool get_matrix (ShaderGlobals *sg, Matrix44 &result,
|
||||
TransformationPtr xform) { return false; }
|
||||
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result,
|
||||
TransformationPtr xform)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Get the 4x4 matrix that transforms by the specified
|
||||
/// transformation. Return true if ok, false on error. Since no
|
||||
@@ -91,29 +111,29 @@ public:
|
||||
/// be time-varying. The default implementation is to use
|
||||
/// get_matrix and invert it, but a particular renderer may have a
|
||||
/// better technique and overload the implementation.
|
||||
virtual bool get_inverse_matrix (ShaderGlobals *sg, Matrix44 &result,
|
||||
TransformationPtr xform);
|
||||
virtual bool get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
|
||||
TransformationPtr xform);
|
||||
|
||||
/// Get the 4x4 matrix that transforms points from the named
|
||||
/// '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) { return false; }
|
||||
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result,
|
||||
ustringhash from, float time);
|
||||
|
||||
/// Get the 4x4 matrix that transforms points from "common" space to
|
||||
/// the named 'to' coordinate system to at the given time. The
|
||||
/// default implementation is to use get_matrix and invert it, but a
|
||||
/// particular renderer may have a better technique and overload the
|
||||
/// implementation.
|
||||
virtual bool get_inverse_matrix (ShaderGlobals *sg, Matrix44 &result,
|
||||
ustring to, float time);
|
||||
virtual bool get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
|
||||
ustringhash to, float time);
|
||||
|
||||
/// Get the 4x4 matrix that transforms 'from' to "common" space.
|
||||
/// Since there is no time value passed, return false if the
|
||||
/// 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) { return false; }
|
||||
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result,
|
||||
ustringhash from);
|
||||
|
||||
/// Get the 4x4 matrix that transforms points from "common" space to
|
||||
/// the named 'to' coordinate system. Since there is no time value
|
||||
@@ -122,8 +142,8 @@ public:
|
||||
/// implementation is to use get_matrix and invert it, but a
|
||||
/// particular renderer may have a better technique and overload the
|
||||
/// implementation.
|
||||
virtual bool get_inverse_matrix (ShaderGlobals *sg, Matrix44 &result,
|
||||
ustring to);
|
||||
virtual bool get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
|
||||
ustringhash to);
|
||||
|
||||
/// Transform points Pin[0..npoints-1] in named coordinate system
|
||||
/// 'from' into 'to' coordinates, storing the result in Pout[] using
|
||||
@@ -148,12 +168,84 @@ public:
|
||||
/// Note to RendererServices implementations: just return 'false'
|
||||
/// if there isn't a special nonlinear transformation between the
|
||||
/// two spaces.
|
||||
virtual bool transform_points (ShaderGlobals *sg,
|
||||
ustring from, ustring to, float time,
|
||||
const Vec3 *Pin, Vec3 *Pout, int npoints,
|
||||
TypeDesc::VECSEMANTICS vectype)
|
||||
{ return false; }
|
||||
virtual bool transform_points(ShaderGlobals* sg, ustringhash from,
|
||||
ustringhash to, float time, const Vec3* Pin,
|
||||
Vec3* Pout, int npoints,
|
||||
TypeDesc::VECSEMANTICS vectype);
|
||||
|
||||
/// Report errors, warnings, printf, and fprintf.
|
||||
/// Fmtlib style format specifier is used (vs. printf style)
|
||||
/// Arguments are represented as EncodedTypes (encodedtypes.h) and
|
||||
/// packed into an arg_values buffer. OSL::decode_message converts these
|
||||
/// arguments into a std::string for renderer's handle to use as they please.
|
||||
/// For device compatibility, the format specifier and any string arguments
|
||||
/// are passed as ustringhash's.
|
||||
/// Default implementation decodes the messages and fowards them to the
|
||||
/// ShadingContext onto the ShadyingSystem's ErrorHandler.
|
||||
/// It is recomended to override and make use of the
|
||||
/// journal buffer to record everything to a buffer than can be post
|
||||
/// processed as needed vs. going through the ShadingSystem ErrorHandler.
|
||||
virtual void errorfmt(OSL::ShaderGlobals* sg,
|
||||
OSL::ustringhash fmt_specification, int32_t arg_count,
|
||||
const EncodedType* arg_types,
|
||||
uint32_t arg_values_size, uint8_t* arg_values);
|
||||
|
||||
virtual void warningfmt(OSL::ShaderGlobals* sg,
|
||||
OSL::ustringhash fmt_specification,
|
||||
int32_t arg_count, const EncodedType* arg_types,
|
||||
uint32_t arg_values_size, uint8_t* arg_values);
|
||||
|
||||
virtual void printfmt(OSL::ShaderGlobals* sg,
|
||||
OSL::ustringhash fmt_specification, int32_t arg_count,
|
||||
const EncodedType* arg_types,
|
||||
uint32_t arg_values_size, uint8_t* arg_values);
|
||||
|
||||
virtual void filefmt(OSL::ShaderGlobals* sg, OSL::ustringhash filename_hash,
|
||||
OSL::ustringhash fmt_specification, int32_t arg_count,
|
||||
const EncodedType* arg_types, uint32_t arg_values_size,
|
||||
uint8_t* arg_values);
|
||||
|
||||
/// Builds a free function to provide a value for a given attribute.
|
||||
/// This occurs at shader compile time, not at execution time.
|
||||
///
|
||||
/// @param group
|
||||
/// The shader group currently requesting the attribute.
|
||||
///
|
||||
/// @param is_object_lookup
|
||||
/// True if an object name was specified, even if the value is not
|
||||
/// known at compile time.
|
||||
///
|
||||
/// @param object_name
|
||||
/// The object name, or nullptr if the value is not specified or it
|
||||
/// is not known at compile time.
|
||||
///
|
||||
/// @param attribute_name
|
||||
/// The attribute name, or nullptr if the value is not known at
|
||||
/// compile time.
|
||||
///
|
||||
/// @param is_array_lookup
|
||||
/// True if the attribute lookup provides an index.
|
||||
///
|
||||
/// @param array_index
|
||||
/// The array index, or nullptr if the value is not specified or it
|
||||
/// is not known at compile time.
|
||||
///
|
||||
/// @param type
|
||||
/// The type of the value being requested.
|
||||
///
|
||||
/// @param derivatives
|
||||
/// True if derivatives are also being requested.
|
||||
///
|
||||
/// @param spec
|
||||
/// The built attribute getter. An empty function name is interpreted
|
||||
/// as a missing attribute.
|
||||
///
|
||||
virtual void
|
||||
build_attribute_getter(const ShaderGroup& group, bool is_object_lookup,
|
||||
const ustring* object_name,
|
||||
const ustring* attribute_name, bool is_array_lookup,
|
||||
const int* array_index, TypeDesc type,
|
||||
bool derivatives, AttributeGetterSpec& spec);
|
||||
|
||||
/// Get the named attribute from the renderer and if found then
|
||||
/// write it into 'val'. Otherwise, return false. If no object is
|
||||
@@ -167,36 +259,42 @@ public:
|
||||
/// run on. Be robust to this situation, return 'true' (retrieve the
|
||||
/// attribute) if you can (known object and attribute name), but
|
||||
/// otherwise just fail by returning 'false'.
|
||||
virtual bool get_attribute (ShaderGlobals *sg, bool derivatives,
|
||||
ustring object, TypeDesc type, ustring name,
|
||||
void *val) { return false; }
|
||||
virtual bool get_attribute(ShaderGlobals* sg, bool derivatives,
|
||||
ustringhash object, TypeDesc type,
|
||||
ustringhash name, void* val);
|
||||
|
||||
/// 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) { return false; }
|
||||
virtual bool get_array_attribute(ShaderGlobals* sg, bool derivatives,
|
||||
ustringhash object, TypeDesc type,
|
||||
ustringhash name, int index, void* val);
|
||||
|
||||
/// 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) { return false; }
|
||||
virtual bool get_userdata(bool derivatives, ustringhash name, TypeDesc type,
|
||||
ShaderGlobals* sg, void* val);
|
||||
|
||||
/// Given the name of a texture, return an opaque handle that can be
|
||||
/// used with texture calls to avoid the name lookups.
|
||||
virtual TextureHandle * get_texture_handle (ustring filename,
|
||||
ShadingContext *context);
|
||||
/// Given the name of a texture, return an opaque handle that can be used
|
||||
/// with texture calls to avoid the name lookups. The `options`, if not
|
||||
/// null, may be used in renderer-specific ways to specialize a handle
|
||||
/// based on certain texture option choices.
|
||||
virtual TextureHandle*
|
||||
get_texture_handle(ustring filename, ShadingContext* context,
|
||||
const TextureOpt* options = nullptr);
|
||||
virtual TextureHandle*
|
||||
get_texture_handle(ustringhash filename, ShadingContext* context,
|
||||
const TextureOpt* options = nullptr);
|
||||
|
||||
/// Return true if the texture handle (previously returned by
|
||||
/// get_texture_handle()) is a valid texture that can be subsequently
|
||||
/// read or sampled.
|
||||
virtual bool good (TextureHandle *texture_handle);
|
||||
virtual bool good(TextureHandle* texture_handle);
|
||||
|
||||
/// Return true if the texture handle (previously returned by
|
||||
/// get_texture_handle()) is udim
|
||||
virtual bool is_udim (TextureHandle *texture_handle);
|
||||
virtual bool is_udim(TextureHandle* texture_handle);
|
||||
|
||||
/// Filtered 2D texture lookup for a single point.
|
||||
///
|
||||
@@ -224,13 +322,13 @@ public:
|
||||
/// messages (in case of failure, when the function returns false) will
|
||||
/// be stored there, leaving it up to the caller/shader to handle the
|
||||
/// error.
|
||||
virtual bool texture (ustring filename, TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
TextureOpt &options, ShaderGlobals *sg,
|
||||
float s, float t, float dsdx, float dtdx,
|
||||
float dsdy, float dtdy, int nchannels,
|
||||
float *result, float *dresultds, float *dresultdt,
|
||||
ustring *errormessage);
|
||||
virtual bool texture(ustringhash filename, TextureHandle* texture_handle,
|
||||
TexturePerthread* texture_thread_info,
|
||||
TextureOpt& options, ShaderGlobals* sg, float s,
|
||||
float t, float dsdx, float dtdx, float dsdy,
|
||||
float dtdy, int nchannels, float* result,
|
||||
float* dresultds, float* dresultdt,
|
||||
ustringhash* errormessage);
|
||||
|
||||
/// Filtered 3D texture lookup for a single point.
|
||||
///
|
||||
@@ -257,14 +355,13 @@ public:
|
||||
/// messages (in case of failure, when the function returns false) will
|
||||
/// be stored there, leaving it up to the caller/shader to handle the
|
||||
/// error.
|
||||
virtual bool texture3d (ustring filename, TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
TextureOpt &options, ShaderGlobals *sg,
|
||||
const Vec3 &P, const Vec3 &dPdx, const Vec3 &dPdy,
|
||||
const Vec3 &dPdz, int nchannels,
|
||||
float *result, float *dresultds,
|
||||
float *dresultdt, float *dresultdr,
|
||||
ustring *errormessage);
|
||||
virtual bool texture3d(ustringhash filename, TextureHandle* texture_handle,
|
||||
TexturePerthread* texture_thread_info,
|
||||
TextureOpt& options, ShaderGlobals* sg,
|
||||
const Vec3& P, const Vec3& dPdx, const Vec3& dPdy,
|
||||
const Vec3& dPdz, int nchannels, float* result,
|
||||
float* dresultds, float* dresultdt, float* dresultdr,
|
||||
ustringhash* errormessage);
|
||||
|
||||
/// Filtered environment lookup for a single point.
|
||||
///
|
||||
@@ -288,13 +385,13 @@ public:
|
||||
/// messages (in case of failure, when the function returns false) will
|
||||
/// be stored there, leaving it up to the caller/shader to handle the
|
||||
/// error.
|
||||
virtual bool environment (ustring filename, TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
TextureOpt &options, ShaderGlobals *sg,
|
||||
const Vec3 &R, const Vec3 &dRdx, const Vec3 &dRdy,
|
||||
int nchannels, float *result,
|
||||
float *dresultds, float *dresultdt,
|
||||
ustring *errormessage);
|
||||
virtual bool environment(ustringhash filename,
|
||||
TextureHandle* texture_handle,
|
||||
TexturePerthread* texture_thread_info,
|
||||
TextureOpt& options, ShaderGlobals* sg,
|
||||
const Vec3& R, const Vec3& dRdx, const Vec3& dRdy,
|
||||
int nchannels, float* result, float* dresultds,
|
||||
float* dresultdt, ustringhash* errormessage);
|
||||
|
||||
/// Get information about the given texture. Return true if found
|
||||
/// and the data has been put in *data. Return false if the texture
|
||||
@@ -315,24 +412,18 @@ public:
|
||||
/// messages (in case of failure, when the function returns false) will
|
||||
/// be stored there, leaving it up to the caller/shader to handle the
|
||||
/// error.
|
||||
virtual bool get_texture_info (ustring filename,
|
||||
TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
ShadingContext *shading_context,
|
||||
int subimage,
|
||||
ustring dataname, TypeDesc datatype,
|
||||
void *data,
|
||||
ustring *errormessage);
|
||||
virtual bool get_texture_info(ustringhash filename,
|
||||
TextureHandle* texture_handle,
|
||||
TexturePerthread* texture_thread_info,
|
||||
ShaderGlobals* sg, int subimage,
|
||||
ustringhash dataname, TypeDesc datatype,
|
||||
void* data, ustringhash* errormessage);
|
||||
|
||||
virtual bool get_texture_info (ustring filename,
|
||||
TextureHandle *texture_handle,
|
||||
float s, float t,
|
||||
TexturePerthread *texture_thread_info,
|
||||
ShadingContext *shading_context,
|
||||
int subimage,
|
||||
ustring dataname, TypeDesc datatype,
|
||||
void *data,
|
||||
ustring *errormessage);
|
||||
virtual bool
|
||||
get_texture_info(ustringhash filename, TextureHandle* texture_handle,
|
||||
float s, float t, TexturePerthread* texture_thread_info,
|
||||
ShaderGlobals* sg, int subimage, ustringhash dataname,
|
||||
TypeDesc datatype, void* data, ustringhash* errormessage);
|
||||
|
||||
|
||||
/// Lookup nearest points in a point cloud. It will search for
|
||||
@@ -343,40 +434,38 @@ public:
|
||||
/// derivatives will be computed for distances (when provided).
|
||||
///
|
||||
/// Return the number of points found, always < max_points
|
||||
virtual int pointcloud_search (ShaderGlobals *sg,
|
||||
ustring filename, const OSL::Vec3 ¢er,
|
||||
float radius, int max_points, bool sort,
|
||||
size_t *out_indices,
|
||||
float *out_distances, int derivs_offset);
|
||||
virtual int pointcloud_search(ShaderGlobals* sg, ustringhash filename,
|
||||
const OSL::Vec3& center, float radius,
|
||||
int max_points, bool sort,
|
||||
size_t* out_indices, float* out_distances,
|
||||
int derivs_offset);
|
||||
|
||||
/// Retrieve an attribute for an index list. The result is another array
|
||||
/// of the requested type stored in out_data.
|
||||
///
|
||||
/// Return 1 if the attribute is found, 0 otherwise.
|
||||
virtual int pointcloud_get (ShaderGlobals *sg,
|
||||
ustring filename, size_t *indices, int count,
|
||||
ustring attr_name, TypeDesc attr_type,
|
||||
void *out_data);
|
||||
virtual int pointcloud_get(ShaderGlobals* sg, ustringhash filename,
|
||||
size_t* indices, int count,
|
||||
ustringhash attr_name, TypeDesc attr_type,
|
||||
void* out_data);
|
||||
|
||||
/// Write a point to the named pointcloud, which will be saved
|
||||
/// at the end of the frame. Return true if everything is ok,
|
||||
/// false if there was an error.
|
||||
virtual bool pointcloud_write (ShaderGlobals *sg,
|
||||
ustring filename, const OSL::Vec3 &pos,
|
||||
int nattribs, const ustring *names,
|
||||
const TypeDesc *types,
|
||||
const void **data);
|
||||
virtual bool pointcloud_write(ShaderGlobals* sg, ustringhash filename,
|
||||
const OSL::Vec3& pos, int nattribs,
|
||||
const ustringrep* names,
|
||||
const TypeDesc* types, const void** data);
|
||||
|
||||
/// Options for the trace call.
|
||||
struct TraceOpt {
|
||||
float mindist; ///< ignore hits closer than this
|
||||
float maxdist; ///< ignore hits farther than this
|
||||
bool shade; ///< whether to shade what is hit
|
||||
ustring traceset; ///< named trace set
|
||||
TraceOpt () : mindist(0.0f), maxdist(1.0e30), shade(false) { }
|
||||
float mindist; ///< ignore hits closer than this
|
||||
float maxdist; ///< ignore hits farther than this
|
||||
bool shade; ///< whether to shade what is hit
|
||||
ustringrep traceset; ///< named trace set
|
||||
TraceOpt() : mindist(0.0f), maxdist(1.0e30), shade(false) {}
|
||||
|
||||
enum class LLVMMemberIndex
|
||||
{
|
||||
enum class LLVMMemberIndex {
|
||||
mindist = 0,
|
||||
maxdist,
|
||||
shade,
|
||||
@@ -387,37 +476,59 @@ public:
|
||||
|
||||
/// Immediately trace a ray from P in the direction R. Return true
|
||||
/// if anything hit, otherwise false.
|
||||
virtual bool trace (TraceOpt &options, ShaderGlobals *sg,
|
||||
const OSL::Vec3 &P, const OSL::Vec3 &dPdx,
|
||||
const OSL::Vec3 &dPdy, const OSL::Vec3 &R,
|
||||
const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy) {
|
||||
return false;
|
||||
}
|
||||
virtual bool trace(TraceOpt& options, ShaderGlobals* sg, const OSL::Vec3& P,
|
||||
const OSL::Vec3& dPdx, const OSL::Vec3& dPdy,
|
||||
const OSL::Vec3& R, const OSL::Vec3& dRdx,
|
||||
const OSL::Vec3& dRdy);
|
||||
|
||||
/// Get the named message from the renderer and if found then
|
||||
/// write it into 'val'. Otherwise, return false. This is only
|
||||
/// called for "sourced" messages, not ordinary intra-group messages.
|
||||
virtual bool getmessage (ShaderGlobals *sg, ustring source, ustring name,
|
||||
TypeDesc type, void *val, bool derivatives) {
|
||||
return false;
|
||||
}
|
||||
virtual bool getmessage(ShaderGlobals* sg, ustringhash source,
|
||||
ustringhash name, TypeDesc type, void* val,
|
||||
bool derivatives);
|
||||
|
||||
/// Return a pointer to the texture system (if available).
|
||||
virtual TextureSystem *texturesys () const;
|
||||
virtual TextureSystem* texturesys() const;
|
||||
|
||||
virtual uint64_t register_global (const std::string& var_name,
|
||||
uint64_t value)
|
||||
/// Allocate `size` bytes of memory on the device that will execute the
|
||||
/// shaders. (Equivalent to malloc() on the CPU.)
|
||||
virtual void* device_alloc(size_t size)
|
||||
{
|
||||
return 0;
|
||||
return nullptr;
|
||||
// Note: for an OptiX-based renderer, this method should be overriden
|
||||
// with something like:
|
||||
//
|
||||
// void* dptr;
|
||||
// auto r = cudaMalloc(&dptr, size);
|
||||
// return r == cudaSuccess ? dptr : nullptr;
|
||||
}
|
||||
|
||||
virtual bool fetch_global (const std::string& var_name,
|
||||
uint64_t* value)
|
||||
/// Free a previous allocation (by `device_alloc()`) on the device that
|
||||
/// will execute the shaders. (Equivalent to free() on the CPU.)
|
||||
virtual void device_free(void* ptr)
|
||||
{
|
||||
return false;
|
||||
// Note: for an OptiX-based renderer, this method should be overriden
|
||||
// with something like:
|
||||
//
|
||||
// cudaFree(ptr);
|
||||
}
|
||||
|
||||
|
||||
/// Copy `size` bytes from location `src_host` on the host/CPU (the
|
||||
/// machine making this call) into location `dst_device` on the device
|
||||
/// executing shaders. (Equivalent to `memcpy(dst, src, size)` on the
|
||||
/// CPU.)
|
||||
virtual void* copy_to_device(void* dst_device, const void* src_host,
|
||||
size_t size)
|
||||
{
|
||||
return nullptr;
|
||||
// Note: for an OptiX-based renderer, this method should be overriden
|
||||
// with something like:
|
||||
//
|
||||
// auto r = cudaMemcpy(dst_device, src_host, size,
|
||||
// cudaMemcpyHostToDevice);
|
||||
// return dst_device;
|
||||
}
|
||||
|
||||
/// Options we use for noise calls.
|
||||
struct NoiseOpt {
|
||||
@@ -426,19 +537,25 @@ public:
|
||||
Vec3 direction;
|
||||
float bandwidth;
|
||||
float impulses;
|
||||
NoiseOpt () : anisotropic(0), do_filter(true),
|
||||
direction(1.0f,0.0f,0.0f), bandwidth(1.0f), impulses(16.0f) { }
|
||||
NoiseOpt()
|
||||
: anisotropic(0)
|
||||
, do_filter(true)
|
||||
, direction(1.0f, 0.0f, 0.0f)
|
||||
, bandwidth(1.0f)
|
||||
, impulses(16.0f)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/// A renderer may choose to support batched execution by providing pointers
|
||||
/// to objects satisfying the BatchedRendererServices<WidthOf<#>> interface
|
||||
/// for specific batch sizes.
|
||||
/// Unless overridden, a nullptr is returned.
|
||||
virtual BatchedRendererServices<16> * batched(WidthOf<16>);
|
||||
virtual BatchedRendererServices<8> * batched(WidthOf<8>);
|
||||
virtual BatchedRendererServices<16>* batched(WidthOf<16>);
|
||||
virtual BatchedRendererServices<8>* batched(WidthOf<8>);
|
||||
|
||||
protected:
|
||||
TextureSystem *m_texturesys; // A place to hold a TextureSystem
|
||||
TextureSystem* m_texturesys; // A place to hold a TextureSystem
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <OSL/encodedtypes.h>
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
// Make all the strings defined in OSL
|
||||
@@ -34,12 +37,13 @@ extern "C" {
|
||||
// as opposed to using overloaded functions.
|
||||
|
||||
// Keep free functions in sync with virtual function based RendererServices.
|
||||
// Must be re-enterant; Expect to be called from multiple threads
|
||||
|
||||
/// Get the 4x4 matrix that transforms by the specified
|
||||
/// transformation at the given time. Return true if ok, false
|
||||
/// on error.
|
||||
OSL_RSOP bool
|
||||
rs_get_matrix_xform_time(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
rs_get_matrix_xform_time(OSL::OpaqueExecContextPtr oec, OSL::Matrix44& result,
|
||||
OSL::TransformationPtr from, float time);
|
||||
|
||||
/// Get the 4x4 matrix that transforms by the specified
|
||||
@@ -47,14 +51,15 @@ rs_get_matrix_xform_time(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
/// error. Suggested implementation is to use rs_get_matrix_xform_time and
|
||||
/// invert it, but a particular renderer may have a better technique.
|
||||
OSL_RSOP bool
|
||||
rs_get_inverse_matrix_xform_time(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
rs_get_inverse_matrix_xform_time(OSL::OpaqueExecContextPtr oec,
|
||||
OSL::Matrix44& result,
|
||||
OSL::TransformationPtr xform, float time);
|
||||
|
||||
/// Get the 4x4 matrix that transforms points from the named
|
||||
/// 'from' coordinate system to "common" space at the given time.
|
||||
/// Returns true if ok, false if the named matrix is not known.
|
||||
OSL_RSOP bool
|
||||
rs_get_matrix_space_time(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
rs_get_matrix_space_time(OSL::OpaqueExecContextPtr oec, OSL::Matrix44& result,
|
||||
OSL::StringParam from, float time);
|
||||
|
||||
/// Get the 4x4 matrix that transforms points from "common" space to
|
||||
@@ -62,15 +67,16 @@ rs_get_matrix_space_time(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
/// implementation is to use rs_get_matrix_space_time and invert it, but a
|
||||
/// particular renderer may have a better technique.
|
||||
OSL_RSOP bool
|
||||
rs_get_inverse_matrix_space_time(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
OSL::StringParam to, float time);
|
||||
rs_get_inverse_matrix_space_time(OSL::OpaqueExecContextPtr oec,
|
||||
OSL::Matrix44& result, OSL::StringParam to,
|
||||
float time);
|
||||
|
||||
/// Get the 4x4 matrix that transforms by the specified
|
||||
/// transformation. Return true if ok, false on error. Since no
|
||||
/// time value is given, also return false if the transformation may
|
||||
/// be time-varying.
|
||||
OSL_RSOP bool
|
||||
rs_get_matrix_xform(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
rs_get_matrix_xform(OSL::OpaqueExecContextPtr oec, OSL::Matrix44& result,
|
||||
OSL::TransformationPtr xform);
|
||||
|
||||
/// Get the 4x4 matrix that transforms by the specified
|
||||
@@ -80,7 +86,8 @@ rs_get_matrix_xform(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
/// rs_get_matrix_xform and invert it, but a particular renderer may have a
|
||||
/// better technique.
|
||||
OSL_RSOP bool
|
||||
rs_get_inverse_matrix_xform(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
rs_get_inverse_matrix_xform(OSL::OpaqueExecContextPtr oec,
|
||||
OSL::Matrix44& result,
|
||||
OSL::TransformationPtr xform);
|
||||
|
||||
/// Get the 4x4 matrix that transforms 'from' to "common" space.
|
||||
@@ -88,7 +95,7 @@ rs_get_inverse_matrix_xform(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
/// transformation may be time-varying (as well as if it's not found
|
||||
/// at all).
|
||||
OSL_RSOP bool
|
||||
rs_get_matrix_space(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
rs_get_matrix_space(OSL::OpaqueExecContextPtr oec, OSL::Matrix44& result,
|
||||
OSL::StringParam from);
|
||||
|
||||
/// Get the 4x4 matrix that transforms points from "common" space to
|
||||
@@ -98,8 +105,8 @@ rs_get_matrix_space(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
/// implementation is to use rs_get_matrix_space and invert it, but a
|
||||
/// particular renderer may have a better technique.
|
||||
OSL_RSOP bool
|
||||
rs_get_inverse_matrix_space(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
OSL::StringParam to);
|
||||
rs_get_inverse_matrix_space(OSL::OpaqueExecContextPtr oec,
|
||||
OSL::Matrix44& result, OSL::StringParam to);
|
||||
|
||||
/// Transform points Pin[0..npoints-1] in named coordinate system
|
||||
/// 'from' into 'to' coordinates, storing the result in Pout[] using
|
||||
@@ -122,7 +129,162 @@ rs_get_inverse_matrix_space(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
/// if there isn't a special nonlinear transformation between the
|
||||
/// two spaces.
|
||||
OSL_RSOP bool
|
||||
rs_transform_points(OSL::ShaderGlobals* sg, OSL::StringParam from,
|
||||
rs_transform_points(OSL::OpaqueExecContextPtr oec, OSL::StringParam from,
|
||||
OSL::StringParam to, float time, const OSL::Vec3* Pin,
|
||||
OSL::Vec3* Pout, int npoints,
|
||||
OSL::TypeDesc::VECSEMANTICS vectype);
|
||||
OSL::TypeDesc::VECSEMANTICS vectype);
|
||||
|
||||
|
||||
/// Report errors, warnings, printf, and fprintf.
|
||||
/// Fmtlib style format specifier is used (vs. printf style)
|
||||
/// Arguments are represented as EncodedTypes (encodedtypes.h) and
|
||||
/// packed into an arg_values buffer. OSL::decode_message converts these
|
||||
/// arguments into a std::string for renderer's handle to use as they please.
|
||||
/// For device compatibility, the format specifier and any string arguments
|
||||
/// are passed as ustringhash's.
|
||||
/// It is recomended to override and make use of the journal buffer to record
|
||||
/// everything to a buffer than can be post processed as needed.
|
||||
OSL_RSOP void
|
||||
rs_errorfmt(OSL::OpaqueExecContextPtr oec, OSL::ustringhash fmt_specification,
|
||||
int32_t count, const OSL::EncodedType* argTypes,
|
||||
uint32_t argValuesSize, uint8_t* argValues);
|
||||
|
||||
OSL_RSOP void
|
||||
rs_filefmt(OSL::OpaqueExecContextPtr oec, OSL::ustringhash filname_hash,
|
||||
OSL::ustringhash fmt_specification, int32_t count,
|
||||
const OSL::EncodedType* argTypes, uint32_t argValuesSize,
|
||||
uint8_t* argValues);
|
||||
|
||||
OSL_RSOP void
|
||||
rs_printfmt(OSL::OpaqueExecContextPtr oec, OSL::ustringhash fmt_specification,
|
||||
int32_t count, const OSL::EncodedType* argTypes,
|
||||
uint32_t argValuesSize, uint8_t* argValues);
|
||||
|
||||
|
||||
OSL_RSOP void
|
||||
rs_warningfmt(OSL::OpaqueExecContextPtr oec, OSL::ustringhash fmt_specification,
|
||||
int32_t count, const OSL::EncodedType* argTypes,
|
||||
uint32_t argValuesSize, uint8_t* argValues);
|
||||
|
||||
|
||||
#if 0
|
||||
// C++ helpers to accept variable arguements and encode messages to be sent
|
||||
// through renderer service free functions
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
namespace pvt {
|
||||
// PackedArgs is similar to tuple but packs its data back to back
|
||||
// in memory layout, which is what we need to build up payload
|
||||
// to the fmt reporting system
|
||||
template<int IndexT, typename TypeT> struct PackedArg {
|
||||
explicit PackedArg(const TypeT& a_value) : m_value(a_value) {}
|
||||
TypeT m_value;
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
template<typename IntSequenceT, typename... TypeListT> struct PackedArgsBase;
|
||||
// Specialize to extract a parameter pack of the IntegerSquence
|
||||
// so it can be expanded alongside the TypeListT parameter pack
|
||||
template<int... IntegerListT, typename... TypeListT>
|
||||
struct PackedArgsBase<std::integer_sequence<int, IntegerListT...>, TypeListT...>
|
||||
: public PackedArg<IntegerListT, TypeListT>... {
|
||||
explicit PackedArgsBase(const TypeListT&... a_values)
|
||||
// multiple inheritance of individual components
|
||||
// uniquely identified by the <Integer,Type> combo
|
||||
: PackedArg<IntegerListT, TypeListT>(a_values)...
|
||||
{
|
||||
}
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
template<typename... TypeListT> struct PackedArgs {
|
||||
typedef std::make_integer_sequence<int, sizeof...(TypeListT)>
|
||||
IndexSequenceType;
|
||||
PackedArgsBase<IndexSequenceType, TypeListT...> m_components;
|
||||
|
||||
explicit PackedArgs(const TypeListT&... a_values)
|
||||
: m_components(a_values...)
|
||||
{
|
||||
}
|
||||
};
|
||||
} // namespace pvt
|
||||
|
||||
|
||||
|
||||
template<typename FilenameT, typename SpecifierT, typename... ArgListT>
|
||||
void
|
||||
filefmt(OpaqueExecContextPtr oec, const FilenameT& filename_hash,
|
||||
const SpecifierT& fmt_specification, ArgListT... args)
|
||||
{
|
||||
constexpr int32_t count = sizeof...(args);
|
||||
constexpr OSL::EncodedType argTypes[]
|
||||
= { pvt::TypeEncoder<ArgListT>::value... };
|
||||
pvt::PackedArgs<typename pvt::TypeEncoder<ArgListT>::DataType...> argValues {
|
||||
pvt::TypeEncoder<ArgListT>::Encode(args)...
|
||||
};
|
||||
|
||||
rs_filefmt(oec, OSL::ustringhash { filename_hash },
|
||||
OSL::ustringhash { fmt_specification }, count,
|
||||
(count == 0) ? nullptr : argTypes,
|
||||
static_cast<uint32_t>((count == 0) ? 0 : sizeof(argValues)),
|
||||
(count == 0) ? nullptr : reinterpret_cast<uint8_t*>(&argValues));
|
||||
}
|
||||
|
||||
template<typename SpecifierT, typename... ArgListT>
|
||||
void
|
||||
printfmt(OpaqueExecContextPtr oec, const SpecifierT& fmt_specification,
|
||||
ArgListT... args)
|
||||
{
|
||||
constexpr int32_t count = sizeof...(args);
|
||||
constexpr OSL::EncodedType argTypes[]
|
||||
= { pvt::TypeEncoder<ArgListT>::value... };
|
||||
pvt::PackedArgs<typename pvt::TypeEncoder<ArgListT>::DataType...> argValues {
|
||||
pvt::TypeEncoder<ArgListT>::Encode(args)...
|
||||
};
|
||||
|
||||
rs_printfmt(oec, OSL::ustringhash { fmt_specification }, count,
|
||||
(count == 0) ? nullptr : argTypes,
|
||||
static_cast<uint32_t>((count == 0) ? 0 : sizeof(argValues)),
|
||||
(count == 0) ? nullptr
|
||||
: reinterpret_cast<uint8_t*>(&argValues));
|
||||
}
|
||||
|
||||
template<typename SpecifierT, typename... ArgListT>
|
||||
void
|
||||
errorfmt(OpaqueExecContextPtr oec, const SpecifierT& fmt_specification,
|
||||
ArgListT... args)
|
||||
{
|
||||
constexpr int32_t count = sizeof...(args);
|
||||
constexpr OSL::EncodedType argTypes[]
|
||||
= { pvt::TypeEncoder<ArgListT>::value... };
|
||||
pvt::PackedArgs<typename pvt::TypeEncoder<ArgListT>::DataType...> argValues {
|
||||
pvt::TypeEncoder<ArgListT>::Encode(args)...
|
||||
};
|
||||
|
||||
rs_errorfmt(oec, OSL::ustringhash { fmt_specification }, count,
|
||||
(count == 0) ? nullptr : argTypes,
|
||||
static_cast<uint32_t>((count == 0) ? 0 : sizeof(argValues)),
|
||||
(count == 0) ? nullptr
|
||||
: reinterpret_cast<uint8_t*>(&argValues));
|
||||
}
|
||||
|
||||
template<typename SpecifierT, typename... ArgListT>
|
||||
void
|
||||
warningfmt(OpaqueExecContextPtr oec, const SpecifierT& fmt_specification,
|
||||
ArgListT... args)
|
||||
{
|
||||
constexpr int32_t count = sizeof...(args);
|
||||
constexpr OSL::EncodedType argTypes[]
|
||||
= { pvt::TypeEncoder<ArgListT>::value... };
|
||||
pvt::PackedArgs<typename pvt::TypeEncoder<ArgListT>::DataType...> argValues {
|
||||
pvt::TypeEncoder<ArgListT>::Encode(args)...
|
||||
};
|
||||
|
||||
rs_warningfmt(oec, OSL::ustringhash { fmt_specification }, count,
|
||||
(count == 0) ? nullptr : argTypes,
|
||||
static_cast<uint32_t>((count == 0) ? 0 : sizeof(argValues)),
|
||||
(count == 0) ? nullptr
|
||||
: reinterpret_cast<uint8_t*>(&argValues));
|
||||
}
|
||||
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
#endif
|
||||
@@ -36,6 +36,22 @@ typedef const void* OpaqueShadingStateUniformPtr;
|
||||
///
|
||||
/// All points, vectors and normals are given in "common" space.
|
||||
///
|
||||
|
||||
/// We are working towards making ShaderGlobals a private implementation
|
||||
/// detail. Preference is given to utilizing an Opaque Execution Context
|
||||
/// Pointer with accessor functions (setter/getters) to access shader global
|
||||
/// values or any context for the currently executing shade. These accessors
|
||||
/// are at the bottom of this file following the form:
|
||||
/// const Vec3& get_P(const OpaqueExecContextPtr oec);
|
||||
/// const Vec3& get_N(const OpaqueExecContextPtr oec);
|
||||
/// float get_time(const OpaqueExecContextPtr oec);
|
||||
/// int get_shade_index(const OpaqueExecContextPtr oec);
|
||||
/// Currently ExecutionContext is a ShaderGlobals and can be used
|
||||
/// interchangably. After inlining we don't expect worse performance.
|
||||
/// Users should transition to the new accessor function API. Once transition
|
||||
/// is complete, where the values are stored and how they are populated is
|
||||
/// expected to change and the new API will provide a layer of encapsulation
|
||||
/// that the raw ShaderGlobals struct doesn't allow.
|
||||
struct ShaderGlobals {
|
||||
/// Surface position (and its x & y differentials).
|
||||
Vec3 P, dPdx, dPdy;
|
||||
@@ -88,6 +104,13 @@ struct ShaderGlobals {
|
||||
ShadingContext* context;
|
||||
OpaqueShadingStateUniformPtr shadingStateUniform;
|
||||
|
||||
/// Shading System responsible for setting
|
||||
/// 0 based thread index, required by journaling mechanism
|
||||
int thread_index;
|
||||
|
||||
/// Shading System responsible for setting
|
||||
int shade_index;
|
||||
|
||||
/// Pointer to the RendererServices object. This is how OSL finds its
|
||||
/// way back to the renderer for callbacks.
|
||||
RendererServices* renderer;
|
||||
@@ -144,4 +167,317 @@ enum class SGBits {
|
||||
last
|
||||
};
|
||||
|
||||
typedef void* OpaqueExecContextPtr;
|
||||
namespace pvt {
|
||||
// As the concrete ExecutionContext is an implementation detail,
|
||||
// it is placed in the pvt namespace.
|
||||
// New accessor functions are provided below in the form
|
||||
// OSL::get_???(const OpaqueExecContextPtr)
|
||||
// Renderer's should use the accessor functions, and not attempt to cast or
|
||||
// directly use the underlying ExecutionContext. This will allow the
|
||||
// implemenation to change and possibly have accessors generated in llvm if
|
||||
// needed. OSL library function implementions may directly use the
|
||||
// ExecutionContext.
|
||||
typedef ShaderGlobals ExecContext;
|
||||
typedef ExecContext* ExecContextPtr;
|
||||
|
||||
OSL_HOSTDEVICE inline ExecContextPtr
|
||||
get_ec(OSL::OpaqueExecContextPtr oec)
|
||||
{
|
||||
return reinterpret_cast<ExecContextPtr>(oec);
|
||||
}
|
||||
}; // namespace pvt
|
||||
|
||||
|
||||
|
||||
template<typename RenderStateT>
|
||||
OSL_HOSTDEVICE inline RenderStateT*
|
||||
get_rs(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
auto rs = reinterpret_cast<RenderStateT*>(ec->renderstate);
|
||||
return rs;
|
||||
}
|
||||
|
||||
template<typename TraceDataT>
|
||||
OSL_HOSTDEVICE inline TraceDataT*
|
||||
get_tracedata(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
auto tracedata = reinterpret_cast<TraceDataT*>(ec->tracedata);
|
||||
return tracedata;
|
||||
}
|
||||
|
||||
template<typename ObjectT>
|
||||
OSL_HOSTDEVICE inline ObjectT*
|
||||
get_objdata(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
auto objdata = reinterpret_cast<ObjectT*>(ec->objdata);
|
||||
return objdata;
|
||||
}
|
||||
|
||||
// TODO: not sure ci should be exposed via a getter or not
|
||||
// its presence here maybe temporary
|
||||
OSL_HOSTDEVICE inline ClosureColor*
|
||||
get_Ci(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->Ci;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE inline TransformationPtr
|
||||
get_object2common(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->object2common;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE inline TransformationPtr
|
||||
get_shader2common(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->shader2common;
|
||||
}
|
||||
|
||||
///Required by free function renderer services to process fmt specification calls; set by Shading System, and not by user
|
||||
OSL_HOSTDEVICE inline int
|
||||
get_shade_index(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->shade_index;
|
||||
}
|
||||
|
||||
///Required for memory allocation on a per thread basis for journaling fmt specification calls; set by Shading System, and not by user
|
||||
OSL_HOSTDEVICE inline int
|
||||
get_thread_index(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->thread_index;
|
||||
}
|
||||
|
||||
/// Surface position (and its x & y differentials).
|
||||
OSL_HOSTDEVICE inline const Vec3&
|
||||
get_P(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->P;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE inline const Vec3&
|
||||
get_dPdx(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->dPdx;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE inline const Vec3&
|
||||
get_dPdy(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->dPdy;
|
||||
}
|
||||
|
||||
|
||||
/// P's z differential, used for volume shading only.
|
||||
OSL_HOSTDEVICE inline const Vec3&
|
||||
get_dPdz(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->dPdz;
|
||||
}
|
||||
|
||||
/// Incident ray, and its x and y derivatives.
|
||||
OSL_HOSTDEVICE inline const Vec3&
|
||||
get_I(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->I;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE inline const Vec3&
|
||||
get_dIdx(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->dIdx;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE inline const Vec3&
|
||||
get_dIdy(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->dIdy;
|
||||
}
|
||||
|
||||
|
||||
/// Shading normal, already front-facing.
|
||||
OSL_HOSTDEVICE inline const Vec3&
|
||||
get_N(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->N;
|
||||
}
|
||||
|
||||
/// True geometric normal.
|
||||
OSL_HOSTDEVICE inline const Vec3&
|
||||
get_Ng(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->Ng;
|
||||
}
|
||||
|
||||
/// 2D surface parameter u, and its differentials.
|
||||
OSL_HOSTDEVICE inline float
|
||||
get_u(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->u;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE inline float
|
||||
get_dudx(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->dudx;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE inline float
|
||||
get_dudy(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->dudy;
|
||||
}
|
||||
|
||||
/// 2D surface parameter v, and its differentials.
|
||||
OSL_HOSTDEVICE inline float
|
||||
get_v(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->v;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE inline float
|
||||
get_dvdx(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->dvdx;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE inline float
|
||||
get_dvdy(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->dvdy;
|
||||
}
|
||||
|
||||
/// Surface tangents: derivative of P with respect to surface u and v.
|
||||
OSL_HOSTDEVICE inline const Vec3&
|
||||
get_dPdu(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->dPdu;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE inline const Vec3&
|
||||
get_dPdv(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->dPdv;
|
||||
}
|
||||
|
||||
/// Time for this shading sample.
|
||||
OSL_HOSTDEVICE inline float
|
||||
get_time(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->time;
|
||||
}
|
||||
|
||||
/// Time interval for the frame (or shading sample).
|
||||
OSL_HOSTDEVICE inline float
|
||||
get_dtime(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = reinterpret_cast<OSL::ShaderGlobals*>(oec);
|
||||
return ec->dtime;
|
||||
}
|
||||
|
||||
/// Velocity vector: derivative of position P with respect to time.
|
||||
OSL_HOSTDEVICE inline const Vec3&
|
||||
get_dPdtime(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->dPdtime;
|
||||
}
|
||||
|
||||
/// For lights or light attenuation shaders: the point being illuminated
|
||||
/// (Ps), and its differentials.
|
||||
OSL_HOSTDEVICE inline const Vec3&
|
||||
get_Ps(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->Ps;
|
||||
}
|
||||
OSL_HOSTDEVICE inline const Vec3&
|
||||
get_dPsdx(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->dPsdx;
|
||||
}
|
||||
OSL_HOSTDEVICE inline const Vec3&
|
||||
get_dPsdy(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->dPsdy;
|
||||
}
|
||||
|
||||
|
||||
/// If nonzero, we are shading the back side of a surface.
|
||||
OSL_HOSTDEVICE inline int
|
||||
get_backfacing(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->backfacing;
|
||||
}
|
||||
|
||||
/// If nonzero, will flip the result of calculatenormal().
|
||||
OSL_HOSTDEVICE inline int
|
||||
get_flipHandedness(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->flipHandedness;
|
||||
}
|
||||
|
||||
/// Bit field of ray type flags.
|
||||
OSL_HOSTDEVICE inline int
|
||||
get_raytype(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->raytype;
|
||||
}
|
||||
|
||||
/// Surface area of the emissive object (used by light shaders for
|
||||
/// energy normalization).
|
||||
OSL_HOSTDEVICE inline float
|
||||
get_surfacearea(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
auto ec = pvt::get_ec(oec);
|
||||
return ec->surfacearea;
|
||||
}
|
||||
|
||||
namespace pvt {
|
||||
// defined in opfmt.cpp
|
||||
OSLEXECPUBLIC int
|
||||
get_max_warnings_per_thread(const OSL::OpaqueExecContextPtr cptr);
|
||||
} // namespace pvt
|
||||
|
||||
|
||||
// Useful to pass to OSL::journal::Writer::record_warningfmt
|
||||
inline int
|
||||
get_max_warnings_per_thread(const OpaqueExecContextPtr oec)
|
||||
{
|
||||
return pvt::get_max_warnings_per_thread(oec);
|
||||
}
|
||||
|
||||
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
// Copyright Contributors to the Open Shading Language project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
// TODO: When minimum required C++ reaches C++17, replace with std::variant.
|
||||
template<typename TBuiltinArg> class ArgVariant {
|
||||
public:
|
||||
enum class Type {
|
||||
Unspecified = 0,
|
||||
Builtin,
|
||||
Bool,
|
||||
Int8,
|
||||
Int16,
|
||||
Int32,
|
||||
Int64,
|
||||
UInt8,
|
||||
UInt16,
|
||||
UInt32,
|
||||
UInt64,
|
||||
Float,
|
||||
Double,
|
||||
Pointer,
|
||||
UString,
|
||||
UStringHash,
|
||||
};
|
||||
|
||||
private:
|
||||
union {
|
||||
TBuiltinArg m_builtin;
|
||||
bool m_bool;
|
||||
int8_t m_int8;
|
||||
int16_t m_int16;
|
||||
int32_t m_int32;
|
||||
int64_t m_int64;
|
||||
uint8_t m_uint8;
|
||||
uint16_t m_uint16;
|
||||
uint32_t m_uint32;
|
||||
uint64_t m_uint64;
|
||||
float m_float;
|
||||
double m_double;
|
||||
void* m_ptr;
|
||||
ustring m_ustring;
|
||||
ustringhash m_ustringhash;
|
||||
};
|
||||
Type m_type;
|
||||
|
||||
public:
|
||||
ArgVariant() : m_type(Type::Unspecified) {}
|
||||
ArgVariant(TBuiltinArg arg) : m_builtin(arg), m_type(Type::Builtin) {}
|
||||
ArgVariant(bool arg) : m_bool(arg), m_type(Type::Bool) {}
|
||||
ArgVariant(int8_t arg) : m_int8(arg), m_type(Type::Int8) {}
|
||||
ArgVariant(int16_t arg) : m_int16(arg), m_type(Type::Int16) {}
|
||||
ArgVariant(int32_t arg) : m_int32(arg), m_type(Type::Int32) {}
|
||||
ArgVariant(int64_t arg) : m_int64(arg), m_type(Type::Int64) {}
|
||||
ArgVariant(uint8_t arg) : m_uint8(arg), m_type(Type::UInt8) {}
|
||||
ArgVariant(uint16_t arg) : m_uint16(arg), m_type(Type::UInt16) {}
|
||||
ArgVariant(uint32_t arg) : m_uint32(arg), m_type(Type::UInt32) {}
|
||||
ArgVariant(uint64_t arg) : m_uint64(arg), m_type(Type::UInt64) {}
|
||||
ArgVariant(float arg) : m_float(arg), m_type(Type::Float) {}
|
||||
ArgVariant(double arg) : m_double(arg), m_type(Type::Double) {}
|
||||
ArgVariant(void* arg) : m_ptr(arg), m_type(Type::Pointer) {}
|
||||
ArgVariant(ustring arg) : m_ustring(arg), m_type(Type::UString) {}
|
||||
ArgVariant(ustringhash arg) : m_ustringhash(arg), m_type(Type::UStringHash)
|
||||
{
|
||||
}
|
||||
|
||||
ArgVariant(const ArgVariant& other)
|
||||
{
|
||||
memcpy((void*)this, &other, sizeof(ArgVariant));
|
||||
}
|
||||
ArgVariant(ArgVariant&& other)
|
||||
{
|
||||
memcpy((void*)this, &other, sizeof(ArgVariant));
|
||||
}
|
||||
|
||||
~ArgVariant() {}
|
||||
|
||||
ArgVariant& operator=(const ArgVariant& other)
|
||||
{
|
||||
memcpy((void*)this, &other, sizeof(ArgVariant));
|
||||
return *this;
|
||||
}
|
||||
ArgVariant& operator=(ArgVariant&& other)
|
||||
{
|
||||
memcpy((void*)this, &other, sizeof(ArgVariant));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Type type() const { return m_type; }
|
||||
|
||||
template<typename T> bool is_holding() const
|
||||
{
|
||||
if (std::is_same<T, TBuiltinArg>::value)
|
||||
return m_type == Type::Builtin;
|
||||
if (std::is_same<T, bool>::value)
|
||||
return m_type == Type::Bool;
|
||||
if (std::is_same<T, int8_t>::value)
|
||||
return m_type == Type::Int8;
|
||||
if (std::is_same<T, int16_t>::value)
|
||||
return m_type == Type::Int16;
|
||||
if (std::is_same<T, int32_t>::value)
|
||||
return m_type == Type::Int32;
|
||||
if (std::is_same<T, int64_t>::value)
|
||||
return m_type == Type::Int64;
|
||||
if (std::is_same<T, uint8_t>::value)
|
||||
return m_type == Type::UInt8;
|
||||
if (std::is_same<T, uint16_t>::value)
|
||||
return m_type == Type::UInt16;
|
||||
if (std::is_same<T, uint32_t>::value)
|
||||
return m_type == Type::UInt32;
|
||||
if (std::is_same<T, uint64_t>::value)
|
||||
return m_type == Type::UInt64;
|
||||
if (std::is_same<T, float>::value)
|
||||
return m_type == Type::Float;
|
||||
if (std::is_same<T, double>::value)
|
||||
return m_type == Type::Double;
|
||||
if (std::is_same<T, void*>::value)
|
||||
return m_type == Type::Pointer;
|
||||
if (std::is_same<T, ustring>::value)
|
||||
return m_type == Type::UString;
|
||||
if (std::is_same<T, ustringhash>::value)
|
||||
return m_type == Type::UStringHash;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
TBuiltinArg get_builtin() const
|
||||
{
|
||||
OSL_DASSERT(is_holding<TBuiltinArg>());
|
||||
return m_builtin;
|
||||
}
|
||||
|
||||
bool get_bool() const
|
||||
{
|
||||
OSL_DASSERT(is_holding<bool>());
|
||||
return m_bool;
|
||||
}
|
||||
|
||||
int8_t get_int8() const
|
||||
{
|
||||
OSL_DASSERT(is_holding<int8_t>());
|
||||
return m_int8;
|
||||
}
|
||||
|
||||
int16_t get_int16() const
|
||||
{
|
||||
OSL_DASSERT(is_holding<int16_t>());
|
||||
return m_int16;
|
||||
}
|
||||
|
||||
int32_t get_int32() const
|
||||
{
|
||||
OSL_DASSERT(is_holding<int32_t>());
|
||||
return m_int32;
|
||||
}
|
||||
|
||||
int64_t get_int64() const
|
||||
{
|
||||
OSL_DASSERT(is_holding<int64_t>());
|
||||
return m_int64;
|
||||
}
|
||||
|
||||
uint8_t get_uint8() const
|
||||
{
|
||||
OSL_DASSERT(is_holding<uint8_t>());
|
||||
return m_uint8;
|
||||
}
|
||||
|
||||
uint16_t get_uint16() const
|
||||
{
|
||||
OSL_DASSERT(is_holding<uint16_t>());
|
||||
return m_uint16;
|
||||
}
|
||||
|
||||
uint32_t get_uint32() const
|
||||
{
|
||||
OSL_DASSERT(is_holding<uint32_t>());
|
||||
return m_uint32;
|
||||
}
|
||||
|
||||
uint64_t get_uint64() const
|
||||
{
|
||||
OSL_DASSERT(is_holding<uint64_t>());
|
||||
return m_uint64;
|
||||
}
|
||||
|
||||
float get_float() const
|
||||
{
|
||||
OSL_DASSERT(is_holding<float>());
|
||||
return m_float;
|
||||
}
|
||||
|
||||
double get_double() const
|
||||
{
|
||||
OSL_DASSERT(is_holding<double>());
|
||||
return m_double;
|
||||
}
|
||||
|
||||
void* get_ptr() const
|
||||
{
|
||||
OSL_DASSERT(is_holding<void*>());
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
ustring get_ustring() const
|
||||
{
|
||||
OSL_DASSERT(is_holding<ustring>());
|
||||
return m_ustring;
|
||||
}
|
||||
|
||||
ustringhash get_ustringhash() const
|
||||
{
|
||||
OSL_DASSERT(is_holding<ustringhash>());
|
||||
return m_ustringhash;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// The FunctionSpec is never in device code, so it can be a bit more
|
||||
// complex and have dynamic allocations. Although we do want to
|
||||
// use an interface and not allow direct data member access
|
||||
template<typename TArg> class FunctionSpec {
|
||||
ustring m_function_name;
|
||||
std::vector<TArg> m_args;
|
||||
|
||||
public:
|
||||
template<typename... ArgListT>
|
||||
void set(ustring function_name, ArgListT... args)
|
||||
{
|
||||
m_function_name = function_name;
|
||||
m_args.clear();
|
||||
m_args.insert(m_args.end(),
|
||||
std::initializer_list<TArg> { TArg { args }... });
|
||||
}
|
||||
|
||||
const ustring& function_name() const { return m_function_name; }
|
||||
size_t arg_count() const { return m_args.size(); }
|
||||
const TArg& arg(size_t i) const
|
||||
{
|
||||
OSL_DASSERT(i < m_args.size());
|
||||
return m_args[i];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
@@ -299,16 +299,13 @@ public:
|
||||
|
||||
// Specializations
|
||||
template<int WidthT>
|
||||
struct Block<float, WidthT> : public BlockOfBuiltin<float, WidthT> {
|
||||
};
|
||||
struct Block<float, WidthT> : public BlockOfBuiltin<float, WidthT> {};
|
||||
|
||||
template<int WidthT>
|
||||
struct Block<int, WidthT> : public BlockOfBuiltin<int, WidthT> {
|
||||
};
|
||||
struct Block<int, WidthT> : public BlockOfBuiltin<int, WidthT> {};
|
||||
|
||||
template<typename DataT, int WidthT>
|
||||
struct Block<DataT*, WidthT> : public BlockOfBuiltin<DataT*, WidthT> {
|
||||
};
|
||||
struct Block<DataT*, WidthT> : public BlockOfBuiltin<DataT*, WidthT> {};
|
||||
|
||||
|
||||
// Vec4 isn't used by external interfaces, but some internal
|
||||
@@ -895,6 +892,8 @@ template<int WidthT> struct alignas(VecReg<WidthT>) Block<Matrix44, WidthT> {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Specialization of Block for ustring
|
||||
template<int WidthT> struct alignas(VecReg<WidthT>) Block<ustring, WidthT> {
|
||||
static constexpr int width = WidthT;
|
||||
typedef ustring ValueType;
|
||||
@@ -942,6 +941,58 @@ template<int WidthT> struct alignas(VecReg<WidthT>) Block<ustring, WidthT> {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Specialization of Block for ustringhash
|
||||
template<int WidthT> struct alignas(VecReg<WidthT>) Block<ustringhash, WidthT> {
|
||||
static constexpr int width = WidthT;
|
||||
typedef ustringhash ValueType;
|
||||
|
||||
// To enable vectorization, use uintptr_t to store the ustringhash (const char *)
|
||||
size_t str[WidthT];
|
||||
static_assert(sizeof(ustringhash) == sizeof(size_t),
|
||||
"ustringhash must be size_t");
|
||||
|
||||
OSL_FORCEINLINE Block() = default;
|
||||
// We want to avoid accidentally copying these when the intent was to just pass a reference
|
||||
Block(const Block& other) = delete;
|
||||
|
||||
OSL_FORCEINLINE void set(int lane, const ustringhash& value)
|
||||
{
|
||||
str[lane] = value.hash();
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE void set(int lane, ustring value)
|
||||
{
|
||||
str[lane] = value.hash();
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE void set(int lane, const ustringhash& value, bool laneMask)
|
||||
{
|
||||
if (laneMask)
|
||||
str[lane] = value.hash();
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE ustringhash get(int lane) const
|
||||
{
|
||||
#ifdef OIIO_USTRING_HAS_CTR_FROM_USTRINGHASH
|
||||
return ustringhash::from_hash(str[lane]);
|
||||
#else
|
||||
return OSL::bitcast<ustringhash>(str[lane]);
|
||||
#endif
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE pvt::LaneProxy<ValueType, WidthT> operator[](int lane)
|
||||
{
|
||||
return pvt::LaneProxy<ValueType, WidthT>(*this, lane);
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE pvt::ConstLaneProxy<const ValueType, WidthT>
|
||||
operator[](int lane) const
|
||||
{
|
||||
return pvt::ConstLaneProxy<const ValueType, WidthT>(*this, lane);
|
||||
}
|
||||
};
|
||||
|
||||
template<int WidthT>
|
||||
struct alignas(VecReg<WidthT>) Block<Dual2<float>, WidthT> {
|
||||
typedef Dual2<float> ValueType;
|
||||
@@ -2229,15 +2280,9 @@ template<typename DataT, int WidthT> struct MaskedLaneProxy {
|
||||
// visibility to end user whose IDE
|
||||
// might display these methods vs. free
|
||||
// functions
|
||||
OSL_FORCEINLINE bool is_on() const
|
||||
{
|
||||
return m_mask.is_on(m_lane);
|
||||
}
|
||||
OSL_FORCEINLINE bool is_on() const { return m_mask.is_on(m_lane); }
|
||||
|
||||
OSL_FORCEINLINE bool is_off() const
|
||||
{
|
||||
return m_mask.is_off(m_lane);
|
||||
}
|
||||
OSL_FORCEINLINE bool is_off() const { return m_mask.is_off(m_lane); }
|
||||
|
||||
private:
|
||||
Block<DataT, WidthT>& m_ref_wide_data;
|
||||
@@ -2299,15 +2344,9 @@ struct MaskedArrayLaneProxy {
|
||||
// visibility to end user whose IDE
|
||||
// might display these methods vs. free
|
||||
// functions
|
||||
OSL_FORCEINLINE bool is_on() const
|
||||
{
|
||||
return m_mask.is_on(m_lane);
|
||||
}
|
||||
OSL_FORCEINLINE bool is_on() const { return m_mask.is_on(m_lane); }
|
||||
|
||||
OSL_FORCEINLINE bool is_off() const
|
||||
{
|
||||
return m_mask.is_off(m_lane);
|
||||
}
|
||||
OSL_FORCEINLINE bool is_off() const { return m_mask.is_off(m_lane); }
|
||||
|
||||
OSL_FORCEINLINE MaskedLaneProxy<DataT, WidthT>
|
||||
operator[](int array_index) const
|
||||
@@ -2672,7 +2711,8 @@ struct MaskedDeriv : public Masked<DataT, WidthT> {
|
||||
template<typename FirstT, typename... ListT,
|
||||
std::enable_if_t<std::is_same<typename std::decay<FirstT>::type,
|
||||
MaskedDeriv>::value,
|
||||
bool> = true>
|
||||
bool>
|
||||
= true>
|
||||
OSL_FORCEINLINE MaskedDeriv(FirstT&& first, ListT&&... argList)
|
||||
: Masked<DataT, WidthT>(std::forward<FirstT>(first),
|
||||
std::forward<ListT>(argList)...)
|
||||
@@ -2683,7 +2723,8 @@ struct MaskedDeriv : public Masked<DataT, WidthT> {
|
||||
template<typename FirstT, typename... ListT,
|
||||
std::enable_if_t<!std::is_same<typename std::decay<FirstT>::type,
|
||||
MaskedDeriv>::value,
|
||||
bool> = true>
|
||||
bool>
|
||||
= true>
|
||||
OSL_FORCEINLINE MaskedDeriv(FirstT&& first, ListT&&... argList)
|
||||
: Masked<DataT, WidthT>(std::forward<FirstT>(first),
|
||||
std::forward<ListT>(argList)...,
|
||||
@@ -2845,7 +2886,7 @@ public:
|
||||
// Populate all data lanes of the MaskedData by broadcasting the
|
||||
// single instance of data pointed to.
|
||||
// Masked off lanes are not overwritten.
|
||||
// Includes value, as well as Dx and Dy when has_derivs() is true
|
||||
// when has_derivs() is true, Dx and Dy will be zeroed
|
||||
OSL_FORCEINLINE void assign_all_from_scalar(const void* ptr_data) const;
|
||||
|
||||
|
||||
@@ -2863,6 +2904,9 @@ private:
|
||||
template<typename DataT>
|
||||
OSL_NOINLINE void assign_all_from_scalar_type(const void* ptr_data,
|
||||
int deriv_index) const;
|
||||
|
||||
template<typename DataT>
|
||||
OSL_NOINLINE void zero_all_type(int deriv_index) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -3131,7 +3175,8 @@ template<typename DataT, int DerivIndexT> struct RefDeriv : public Ref<DataT> {
|
||||
template<typename FirstT, typename... ListT,
|
||||
std::enable_if_t<!std::is_same<typename std::decay<FirstT>::type,
|
||||
RefDeriv>::value,
|
||||
bool> = true>
|
||||
bool>
|
||||
= true>
|
||||
explicit OSL_FORCEINLINE RefDeriv(FirstT&& first, ListT&&... argList)
|
||||
: Ref<DataT>(std::forward<FirstT>(first),
|
||||
std::forward<ListT>(argList)...,
|
||||
@@ -3378,6 +3423,33 @@ MaskedData<WidthT>::assign_all_from_scalar_type(const void* ptr_data,
|
||||
}
|
||||
}
|
||||
|
||||
template<int WidthT>
|
||||
template<typename DataT>
|
||||
OSL_NOINLINE void
|
||||
MaskedData<WidthT>::zero_all_type(int deriv_index) const
|
||||
{
|
||||
// We can't just do a memset because some lanes may be masked off
|
||||
// Use a SIMD loop to perform masked assignment.
|
||||
auto* dst_blocks = pvt::block_cast<DataT, WidthT>(m_ptr);
|
||||
int elem_count = static_cast<int>(m_type.numelements());
|
||||
int comp_count = m_type.aggregate;
|
||||
int deriv_offset = deriv_index * elem_count * comp_count;
|
||||
for (int array_index = 0; array_index < elem_count; ++array_index) {
|
||||
int array_offset = array_index * comp_count;
|
||||
for (int comp_index = 0; comp_index < comp_count; ++comp_index) {
|
||||
int combined_index = deriv_offset + array_offset + comp_index;
|
||||
auto& bdst = dst_blocks[combined_index];
|
||||
|
||||
Masked<DataT, WidthT> wdest(bdst, mask());
|
||||
|
||||
OSL_OMP_PRAGMA(omp simd simdlen(WidthT))
|
||||
for (int lane = 0; lane < WidthT; ++lane) {
|
||||
wdest[lane] = DataT {};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<int WidthT>
|
||||
OSL_FORCEINLINE void
|
||||
MaskedData<WidthT>::assign_all_from_scalar(const void* ptr_data) const
|
||||
@@ -3393,16 +3465,12 @@ MaskedData<WidthT>::assign_all_from_scalar(const void* ptr_data) const
|
||||
assign_all_from_scalar_type<ustring>(ptr_data, /*deriv_index*/ 0);
|
||||
}
|
||||
if (has_derivs()) {
|
||||
size_t src_size = type().size();
|
||||
const char* dx_src = reinterpret_cast<const char*>(ptr_data) + src_size;
|
||||
const char* dy_src = dx_src + src_size;
|
||||
|
||||
if (isBase32bit) {
|
||||
assign_all_from_scalar_type<int>(dx_src, /*deriv_index*/ 1);
|
||||
assign_all_from_scalar_type<int>(dy_src, /*deriv_index*/ 2);
|
||||
zero_all_type<int>(/*deriv_index*/ 1);
|
||||
zero_all_type<int>(/*deriv_index*/ 2);
|
||||
} else {
|
||||
assign_all_from_scalar_type<ustring>(dx_src, /*deriv_index*/ 1);
|
||||
assign_all_from_scalar_type<ustring>(dy_src, /*deriv_index*/ 2);
|
||||
zero_all_type<ustring>(/*deriv_index*/ 1);
|
||||
zero_all_type<ustring>(/*deriv_index*/ 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <OSL/oslconfig.h>
|
||||
#include <OSL/oslversion.h>
|
||||
|
||||
#ifdef OSL_USE_OPTIX
|
||||
#if OSL_USE_OPTIX
|
||||
# include <cuda_runtime_api.h>
|
||||
# include <optix.h>
|
||||
# ifdef _WIN32
|
||||
@@ -18,8 +18,9 @@
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <OSL/device_ptr.h>
|
||||
|
||||
#if !defined(OSL_USE_OPTIX) && !defined(__CUDA_ARCH__)
|
||||
#if !OSL_USE_OPTIX && !defined(__CUDA_ARCH__)
|
||||
using CUdeviceptr = void*;
|
||||
using float3 = OSL::Vec3;
|
||||
#endif
|
||||
@@ -28,7 +29,7 @@ using float3 = OSL::Vec3;
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
#ifdef OSL_USE_OPTIX
|
||||
#if OSL_USE_OPTIX
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// If OptiX is available, alias everything in optix:: namespace into
|
||||
|
||||
@@ -386,6 +386,7 @@ public:
|
||||
/// vector-like (and match their array-ness and closure-ness), or
|
||||
/// if both are structures with matching fields.
|
||||
friend bool equivalent(const TypeSpec& a, const TypeSpec& b);
|
||||
friend bool relaxed_equivalent(const TypeSpec& a, const TypeSpec& b);
|
||||
|
||||
/// Is type src is assignable to dst? It is if they are the equivalent(),
|
||||
/// or if dst is a float or float-aggregate and src is a float or int.
|
||||
@@ -477,7 +478,9 @@ public:
|
||||
, m_const_initializer(false)
|
||||
, m_connected_down(false)
|
||||
, m_initialized(false)
|
||||
, m_lockgeom(false)
|
||||
, m_interpolated(false)
|
||||
, m_interactive(false)
|
||||
, m_noninteractive(false)
|
||||
, m_allowconnect(true)
|
||||
, m_renderer_output(false)
|
||||
, m_readonly(false)
|
||||
@@ -629,137 +632,70 @@ public:
|
||||
OSL_ASSERT(arena == SymArena::Absolute);
|
||||
m_arena = static_cast<unsigned int>(arena);
|
||||
m_data = ptr;
|
||||
// m_dataoffset = static_cast<int64_t>((char*)ptr - (char*)0);
|
||||
}
|
||||
|
||||
/// Specify the location of the symbol's data, relative to an arena
|
||||
/// (which for now must be Absolute).
|
||||
void set_dataptr(SymArena arena, void* ptr, int offset)
|
||||
{
|
||||
// OSL_ASSERT(arena == SymArena::Absolute);
|
||||
m_arena = static_cast<unsigned int>(arena);
|
||||
m_data = ptr;
|
||||
m_dataoffset = offset;
|
||||
OSL::print("setting sym {} arena {} offset {}\n", name(), int(m_arena),
|
||||
m_dataoffset);
|
||||
}
|
||||
|
||||
|
||||
void dataoffset(int d)
|
||||
{
|
||||
m_dataoffset = d;
|
||||
}
|
||||
int dataoffset() const
|
||||
{
|
||||
return m_dataoffset;
|
||||
}
|
||||
void dataoffset(int d) { m_dataoffset = d; }
|
||||
int dataoffset() const { return m_dataoffset; }
|
||||
|
||||
void wide_dataoffset(int d)
|
||||
{
|
||||
m_wide_dataoffset = d;
|
||||
}
|
||||
int wide_dataoffset() const
|
||||
{
|
||||
return m_wide_dataoffset;
|
||||
}
|
||||
void wide_dataoffset(int d) { m_wide_dataoffset = d; }
|
||||
int wide_dataoffset() const { return m_wide_dataoffset; }
|
||||
|
||||
SymArena arena() const
|
||||
{
|
||||
return static_cast<SymArena>(m_arena);
|
||||
}
|
||||
SymArena arena() const { return static_cast<SymArena>(m_arena); }
|
||||
|
||||
void initializers(int d)
|
||||
{
|
||||
m_initializers = d;
|
||||
}
|
||||
int initializers() const
|
||||
{
|
||||
return m_initializers;
|
||||
}
|
||||
void initializers(int d) { m_initializers = d; }
|
||||
int initializers() const { return m_initializers; }
|
||||
|
||||
bool has_derivs() const
|
||||
{
|
||||
return m_has_derivs;
|
||||
}
|
||||
void has_derivs(bool new_derivs)
|
||||
{
|
||||
m_has_derivs = new_derivs;
|
||||
}
|
||||
int size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
void size(size_t newsize)
|
||||
{
|
||||
m_size = (int)newsize;
|
||||
}
|
||||
bool has_derivs() const { return m_has_derivs; }
|
||||
void has_derivs(bool new_derivs) { m_has_derivs = new_derivs; }
|
||||
int size() const { return m_size; }
|
||||
void size(size_t newsize) { m_size = (int)newsize; }
|
||||
|
||||
/// Return the size for each point, including derivs.
|
||||
///
|
||||
int derivsize() const
|
||||
{
|
||||
return m_has_derivs ? 3 * m_size : m_size;
|
||||
}
|
||||
int derivsize() const { return m_has_derivs ? 3 * m_size : m_size; }
|
||||
|
||||
bool connected() const
|
||||
{
|
||||
return valuesource() == ConnectedVal;
|
||||
}
|
||||
bool connected_down() const
|
||||
{
|
||||
return m_connected_down;
|
||||
}
|
||||
void connected_down(bool c)
|
||||
{
|
||||
m_connected_down = c;
|
||||
}
|
||||
bool connected() const { return valuesource() == ConnectedVal; }
|
||||
bool connected_down() const { return m_connected_down; }
|
||||
void connected_down(bool c) { m_connected_down = c; }
|
||||
|
||||
/// Where did the symbol's value come from?
|
||||
///
|
||||
enum ValueSource { DefaultVal, InstanceVal, GeomVal, ConnectedVal };
|
||||
|
||||
ValueSource valuesource() const
|
||||
{
|
||||
return (ValueSource)m_valuesource;
|
||||
}
|
||||
void valuesource(ValueSource v)
|
||||
{
|
||||
m_valuesource = v;
|
||||
}
|
||||
ValueSource valuesource() const { return (ValueSource)m_valuesource; }
|
||||
void valuesource(ValueSource v) { m_valuesource = v; }
|
||||
const char* valuesourcename() const;
|
||||
static const char* valuesourcename(ValueSource v);
|
||||
|
||||
int fieldid() const
|
||||
{
|
||||
return m_fieldid;
|
||||
}
|
||||
void fieldid(int id)
|
||||
{
|
||||
m_fieldid = id;
|
||||
}
|
||||
int fieldid() const { return m_fieldid; }
|
||||
void fieldid(int id) { m_fieldid = id; }
|
||||
|
||||
int layer() const
|
||||
{
|
||||
return m_layer;
|
||||
}
|
||||
void layer(int id)
|
||||
{
|
||||
m_layer = id;
|
||||
}
|
||||
int layer() const { return m_layer; }
|
||||
void layer(int id) { m_layer = id; }
|
||||
|
||||
int initbegin() const
|
||||
{
|
||||
return m_initbegin;
|
||||
}
|
||||
void initbegin(int i)
|
||||
{
|
||||
m_initbegin = i;
|
||||
}
|
||||
int initend() const
|
||||
{
|
||||
return m_initend;
|
||||
}
|
||||
void initend(int i)
|
||||
{
|
||||
m_initend = i;
|
||||
}
|
||||
int initbegin() const { return m_initbegin; }
|
||||
void initbegin(int i) { m_initbegin = i; }
|
||||
int initend() const { return m_initend; }
|
||||
void initend(int i) { m_initend = i; }
|
||||
void set_initrange(int b = 0, int e = 0)
|
||||
{
|
||||
m_initbegin = b;
|
||||
m_initend = e;
|
||||
}
|
||||
bool has_init_ops() const
|
||||
{
|
||||
return m_initbegin != m_initend;
|
||||
}
|
||||
bool has_init_ops() const { return m_initbegin != m_initend; }
|
||||
|
||||
/// Clear read/write usage info.
|
||||
///
|
||||
@@ -803,42 +739,15 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
int firstread() const
|
||||
{
|
||||
return m_firstread;
|
||||
}
|
||||
int lastread() const
|
||||
{
|
||||
return m_lastread;
|
||||
}
|
||||
int firstwrite() const
|
||||
{
|
||||
return m_firstwrite;
|
||||
}
|
||||
int lastwrite() const
|
||||
{
|
||||
return m_lastwrite;
|
||||
}
|
||||
int firstuse() const
|
||||
{
|
||||
return std::min(firstread(), firstwrite());
|
||||
}
|
||||
int lastuse() const
|
||||
{
|
||||
return std::max(lastread(), lastwrite());
|
||||
}
|
||||
bool everread() const
|
||||
{
|
||||
return lastread() >= 0;
|
||||
}
|
||||
bool everwritten() const
|
||||
{
|
||||
return lastwrite() >= 0;
|
||||
}
|
||||
bool everused() const
|
||||
{
|
||||
return everread() || everwritten();
|
||||
}
|
||||
int firstread() const { return m_firstread; }
|
||||
int lastread() const { return m_lastread; }
|
||||
int firstwrite() const { return m_firstwrite; }
|
||||
int lastwrite() const { return m_lastwrite; }
|
||||
int firstuse() const { return std::min(firstread(), firstwrite()); }
|
||||
int lastuse() const { return std::max(lastread(), lastwrite()); }
|
||||
bool everread() const { return lastread() >= 0; }
|
||||
bool everwritten() const { return lastwrite() >= 0; }
|
||||
bool everused() const { return everread() || everwritten(); }
|
||||
// everused_in_group is an even more stringent test -- not only must
|
||||
// the symbol not be used within the shader but it also must not be
|
||||
// used elsewhere in the group, by being connected to something downstream
|
||||
@@ -859,67 +768,44 @@ public:
|
||||
m_lastwrite = last;
|
||||
}
|
||||
|
||||
bool initialized() const
|
||||
{
|
||||
return m_initialized;
|
||||
}
|
||||
void initialized(bool init)
|
||||
{
|
||||
m_initialized = init;
|
||||
}
|
||||
bool initialized() const { return m_initialized; }
|
||||
void initialized(bool init) { m_initialized = init; }
|
||||
|
||||
bool lockgeom() const
|
||||
{
|
||||
return m_lockgeom;
|
||||
}
|
||||
void lockgeom(bool lock)
|
||||
{
|
||||
m_lockgeom = lock;
|
||||
// We can lock a value to a constant (at all places on all pieces of
|
||||
// geometry) if it is neither interpolated nor interactively modified.
|
||||
return !m_interpolated && !m_interactive;
|
||||
}
|
||||
|
||||
bool allowconnect() const
|
||||
{
|
||||
return m_allowconnect;
|
||||
}
|
||||
void allowconnect(bool val)
|
||||
{
|
||||
m_allowconnect = val;
|
||||
}
|
||||
bool interpolated() const { return m_interpolated; }
|
||||
void interpolated(bool val) { m_interpolated = val; }
|
||||
|
||||
int arraylen() const
|
||||
{
|
||||
return m_typespec.arraylength();
|
||||
}
|
||||
bool interactive() const { return m_interactive; }
|
||||
void interactive(bool val) { m_interactive = val; }
|
||||
|
||||
bool noninteractive() const { return m_noninteractive; }
|
||||
void noninteractive(bool val) { m_noninteractive = val; }
|
||||
|
||||
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);
|
||||
m_size = m_typespec.simpletype().size();
|
||||
}
|
||||
|
||||
bool renderer_output() const
|
||||
{
|
||||
return m_renderer_output;
|
||||
}
|
||||
void renderer_output(bool v)
|
||||
{
|
||||
m_renderer_output = v;
|
||||
}
|
||||
bool renderer_output() const { return m_renderer_output; }
|
||||
void renderer_output(bool v) { m_renderer_output = v; }
|
||||
|
||||
// When not uniform a symbol will have a varying value under batched
|
||||
// execution and must use a Wide data type to hold different values
|
||||
// for each data lane executing
|
||||
bool is_uniform() const
|
||||
{
|
||||
return m_is_uniform;
|
||||
}
|
||||
bool is_varying() const
|
||||
{
|
||||
return (m_is_uniform == 0);
|
||||
}
|
||||
void make_varying()
|
||||
{
|
||||
m_is_uniform = false;
|
||||
}
|
||||
bool is_uniform() const { return m_is_uniform; }
|
||||
bool is_varying() const { return (m_is_uniform == 0); }
|
||||
void make_varying() { m_is_uniform = false; }
|
||||
|
||||
// Results of a compare_op and other ops with logically boolean
|
||||
// results under certain conditions could be forced to be represented
|
||||
@@ -933,32 +819,14 @@ public:
|
||||
// The value of forced_llvm_bool() is currently only respected during
|
||||
// batched execution. Forced bools should not be coalesced with regular
|
||||
// ints, only other forced bools.
|
||||
bool forced_llvm_bool() const
|
||||
{
|
||||
return m_forced_llvm_bool;
|
||||
}
|
||||
void forced_llvm_bool(bool v)
|
||||
{
|
||||
m_forced_llvm_bool = v;
|
||||
}
|
||||
bool forced_llvm_bool() const { return m_forced_llvm_bool; }
|
||||
void forced_llvm_bool(bool v) { m_forced_llvm_bool = v; }
|
||||
|
||||
bool readonly() const
|
||||
{
|
||||
return m_readonly;
|
||||
}
|
||||
void readonly(bool v)
|
||||
{
|
||||
m_readonly = 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;
|
||||
}
|
||||
bool is_constant() const { return symtype() == SymTypeConst; }
|
||||
bool is_temp() const { return symtype() == SymTypeTemp; }
|
||||
|
||||
// Retrieve the const float value (must be a const float!)
|
||||
float get_float(int index = 0) const
|
||||
@@ -1028,10 +896,12 @@ protected:
|
||||
unsigned m_symtype : 4; ///< Kind of symbol (param, local, etc.)
|
||||
unsigned m_has_derivs : 1; ///< Step to derivs (0 == has no derivs)
|
||||
unsigned m_const_initializer : 1; ///< initializer is a constant expression
|
||||
unsigned m_connected_down : 1; ///< Connected to a later/downstream 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_connected_down : 1; ///< Connected to a later/downstream layer
|
||||
unsigned m_initialized : 1; ///< If a param, has it been initialized?
|
||||
unsigned m_interpolated : 1; ///< Is the param overridden by geom?
|
||||
unsigned m_interactive : 1; ///< May the param change interactively?
|
||||
unsigned m_noninteractive : 1; ///< The param def won't modify interactively
|
||||
unsigned m_allowconnect : 1; ///< Is the param allowd to connect?
|
||||
unsigned m_renderer_output : 1; ///< Is this sym a renderer output?
|
||||
unsigned m_readonly : 1; ///< read-only symbol
|
||||
unsigned m_is_uniform : 1; ///< symbol is uniform under batched execution
|
||||
@@ -1285,3 +1155,12 @@ typedef std::vector<Opcode> OpcodeVec;
|
||||
|
||||
}; // namespace pvt
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
|
||||
|
||||
// Supply a fmtlib compatible custom formatter for TypeSpec.
|
||||
#if FMT_VERSION >= 100000
|
||||
FMT_BEGIN_NAMESPACE
|
||||
template<> struct formatter<OSL::pvt::TypeSpec> : ostream_formatter {};
|
||||
FMT_END_NAMESPACE
|
||||
#endif
|
||||
|
||||
@@ -46,7 +46,7 @@ ScopeExit print_node_counts([]() {
|
||||
for (int i = 0; i < ASTNode::_last_node; ++i)
|
||||
if (node_counts[i] > 0)
|
||||
Strutil::print("ASTNode type {:2}: {:5} (peak {:5})\n", i,
|
||||
node_counts[i], node_counts_peak[i]);
|
||||
node_counts[i].load(), node_counts_peak[i].load());
|
||||
});
|
||||
} // namespace
|
||||
#endif
|
||||
@@ -1116,90 +1116,151 @@ ASTassign_expression::opword() const
|
||||
OSL_ASSERT (0 && "unknown assignment expression");
|
||||
return "assign"; // punt
|
||||
}
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
|
||||
|
||||
ASTunary_expression::ASTunary_expression (OSLCompilerImpl *comp, int op,
|
||||
ASTNode *expr)
|
||||
: ASTNode (unary_expression_node, comp, op, expr)
|
||||
ASTunary_expression::ASTunary_expression(OSLCompilerImpl* comp, int op,
|
||||
ASTNode* expr)
|
||||
: ASTNode(unary_expression_node, comp, op, expr)
|
||||
{
|
||||
// Check for a user-overloaded function for this operator
|
||||
Symbol *sym = comp->symtab().find(ustring::fmtformat("__operator__{}__", opword()));
|
||||
Symbol* sym = comp->symtab().find(
|
||||
ustring::fmtformat("__operator__{}__", opword()));
|
||||
if (sym && sym->symtype() == SymTypeFunction)
|
||||
m_function_overload = (FunctionSymbol *)sym;
|
||||
m_function_overload = (FunctionSymbol*)sym;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *
|
||||
ASTunary_expression::childname (size_t i) const
|
||||
const char*
|
||||
ASTunary_expression::childname(size_t i) const
|
||||
{
|
||||
static const char *name[] = { "expression" };
|
||||
static const char* name[] = { "expression" };
|
||||
return name[i];
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *
|
||||
ASTunary_expression::opname () const
|
||||
const char*
|
||||
ASTunary_expression::opname() const
|
||||
{
|
||||
switch (m_op) {
|
||||
case Add : return "+";
|
||||
case Sub : return "-";
|
||||
case Not : return "!";
|
||||
case Compl : return "~";
|
||||
default:
|
||||
OSL_ASSERT (0 && "unknown unary expression");
|
||||
return "unknown";
|
||||
case Add: return "+";
|
||||
case Sub: return "-";
|
||||
case Not: return "!";
|
||||
case Compl: return "~";
|
||||
default: OSL_ASSERT(0 && "unknown unary expression"); return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *
|
||||
ASTunary_expression::opword () const
|
||||
const char*
|
||||
ASTunary_expression::opword() const
|
||||
{
|
||||
switch (m_op) {
|
||||
case Add : return "add";
|
||||
case Sub : return "neg";
|
||||
case Not : return "not";
|
||||
case Compl : return "compl";
|
||||
default:
|
||||
OSL_ASSERT (0 && "unknown unary expression");
|
||||
return "unknown";
|
||||
case Add: return "add";
|
||||
case Sub: return "neg";
|
||||
case Not: return "not";
|
||||
case Compl: return "compl";
|
||||
default: OSL_ASSERT(0 && "unknown unary expression"); return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
ASTbinary_expression::ASTbinary_expression (OSLCompilerImpl *comp, Operator op,
|
||||
ASTNode *left, ASTNode *right)
|
||||
: ASTNode (binary_expression_node, comp, op, left, right)
|
||||
ASTbinary_expression::ASTbinary_expression(OSLCompilerImpl* comp, Operator op,
|
||||
ASTNode* left, ASTNode* right)
|
||||
: ASTNode(binary_expression_node, comp, op, left, right)
|
||||
{
|
||||
// Check for a user-overloaded function for this operator.
|
||||
// Disallow a few ops from overloading.
|
||||
if (op != And && op != Or) {
|
||||
ustring funcname = ustring::fmtformat("__operator__{}__", opword());
|
||||
Symbol *sym = comp->symtab().find (funcname);
|
||||
Symbol* sym = comp->symtab().find(funcname);
|
||||
if (sym && sym->symtype() == SymTypeFunction)
|
||||
m_function_overload = (FunctionSymbol *)sym;
|
||||
m_function_overload = (FunctionSymbol*)sym;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *
|
||||
ASTbinary_expression::childname (size_t i) const
|
||||
ASTNode*
|
||||
ASTbinary_expression::make(OSLCompilerImpl* comp, Operator op, ASTNode* left,
|
||||
ASTNode* right)
|
||||
{
|
||||
static const char *name[] = { "left", "right" };
|
||||
// If the left and right are both literal constants, fold the expression
|
||||
if (left->nodetype() == literal_node && right->nodetype() == literal_node) {
|
||||
ASTNode* cf = nullptr; // constant-folded result
|
||||
if (left->typespec().is_int() && right->typespec().is_int()) {
|
||||
int lv = dynamic_cast<ASTliteral*>(left)->intval();
|
||||
int rv = dynamic_cast<ASTliteral*>(right)->intval();
|
||||
switch (op) {
|
||||
case Mul: cf = new ASTliteral(comp, lv * rv); break;
|
||||
case Div: cf = new ASTliteral(comp, rv ? lv / rv : 0); break;
|
||||
case Add: cf = new ASTliteral(comp, lv + rv); break;
|
||||
case Sub: cf = new ASTliteral(comp, lv - rv); break;
|
||||
case Mod: cf = new ASTliteral(comp, rv ? lv % rv : 0); break;
|
||||
case Equal: cf = new ASTliteral(comp, lv == rv ? 1 : 0); break;
|
||||
case NotEqual: cf = new ASTliteral(comp, lv != rv ? 1 : 0); break;
|
||||
case Greater: cf = new ASTliteral(comp, lv > rv ? 1 : 0); break;
|
||||
case Less: cf = new ASTliteral(comp, lv < rv ? 1 : 0); break;
|
||||
case GreaterEqual:
|
||||
cf = new ASTliteral(comp, lv >= rv ? 1 : 0);
|
||||
break;
|
||||
case LessEqual: cf = new ASTliteral(comp, lv <= rv ? 1 : 0); break;
|
||||
case BitAnd: cf = new ASTliteral(comp, lv & rv); break;
|
||||
case BitOr: cf = new ASTliteral(comp, lv | rv); break;
|
||||
case Xor: cf = new ASTliteral(comp, lv ^ rv); break;
|
||||
case ShiftLeft: cf = new ASTliteral(comp, lv << rv); break;
|
||||
case ShiftRight: cf = new ASTliteral(comp, lv >> rv); break;
|
||||
default: break;
|
||||
}
|
||||
} else if (left->typespec().is_float()
|
||||
&& right->typespec().is_float()) {
|
||||
float lv = dynamic_cast<ASTliteral*>(left)->floatval();
|
||||
float rv = dynamic_cast<ASTliteral*>(right)->floatval();
|
||||
switch (op) {
|
||||
case Mul: cf = new ASTliteral(comp, lv * rv); break;
|
||||
case Div: cf = new ASTliteral(comp, rv ? lv / rv : 0.0f); break;
|
||||
case Add: cf = new ASTliteral(comp, lv + rv); break;
|
||||
case Sub: cf = new ASTliteral(comp, lv - rv); break;
|
||||
case Equal: cf = new ASTliteral(comp, lv == rv ? 1 : 0); break;
|
||||
case NotEqual: cf = new ASTliteral(comp, lv != rv ? 1 : 0); break;
|
||||
case Greater: cf = new ASTliteral(comp, lv > rv ? 1 : 0); break;
|
||||
case Less: cf = new ASTliteral(comp, lv < rv ? 1 : 0); break;
|
||||
case GreaterEqual:
|
||||
cf = new ASTliteral(comp, lv >= rv ? 1 : 0);
|
||||
break;
|
||||
case LessEqual: cf = new ASTliteral(comp, lv <= rv ? 1 : 0); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if (cf) {
|
||||
delete left;
|
||||
delete right;
|
||||
return cf;
|
||||
}
|
||||
}
|
||||
|
||||
return new ASTbinary_expression(comp, op, left, right);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char*
|
||||
ASTbinary_expression::childname(size_t i) const
|
||||
{
|
||||
static const char* name[] = { "left", "right" };
|
||||
return name[i];
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *
|
||||
ASTbinary_expression::opname () const
|
||||
const char*
|
||||
ASTbinary_expression::opname() const
|
||||
{
|
||||
// clang-format off
|
||||
switch (m_op) {
|
||||
|
||||
@@ -832,6 +832,10 @@ public:
|
||||
ASTbinary_expression(OSLCompilerImpl* comp, Operator op, ASTNode* left,
|
||||
ASTNode* right);
|
||||
|
||||
// Special consructor wrapper that can collapse ops between literals
|
||||
static ASTNode* make(OSLCompilerImpl* comp, Operator op, ASTNode* left,
|
||||
ASTNode* right);
|
||||
|
||||
const char* nodetypename() const { return "binary_expression"; }
|
||||
const char* childname(size_t i) const;
|
||||
const char* opname() const;
|
||||
|
||||