Compare commits
135
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4db549061 | ||
|
|
4debd96adc | ||
|
|
30a4a95b7e | ||
|
|
a38aa58c0e | ||
|
|
e126a20df7 | ||
|
|
52cf2ee418 | ||
|
|
83a1e7e74b | ||
|
|
6069b7cfc0 | ||
|
|
41cc6d78db | ||
|
|
8561a817ea | ||
|
|
cfaf643d0e | ||
|
|
c505c4ca5f | ||
|
|
318f0e488e | ||
|
|
b22c9b7c84 | ||
|
|
bd491d025e | ||
|
|
6140c72aa6 | ||
|
|
7fcdc3f71c | ||
|
|
22feb208c2 | ||
|
|
ab65bbad4b | ||
|
|
64c66949e7 | ||
|
|
2fe18079a3 | ||
|
|
e0a66c7bc6 | ||
|
|
e4e5088ed6 | ||
|
|
aea281dcad | ||
|
|
b5aba16147 | ||
|
|
4ba1678561 | ||
|
|
8417f8eb04 | ||
|
|
55029e388f | ||
|
|
89c033bda9 | ||
|
|
0b57ae6b03 | ||
|
|
6588caafa6 | ||
|
|
b11fb97626 | ||
|
|
7a885c68b6 | ||
|
|
32278d3f77 | ||
|
|
c8dd33f5a3 | ||
|
|
1a7670600c | ||
|
|
a6ff40b0b2 | ||
|
|
54cf8b209c | ||
|
|
2e941e612f | ||
|
|
051f2bfe2f | ||
|
|
f13463e6b6 | ||
|
|
cd2fa1650d | ||
|
|
c23da3df34 | ||
|
|
95c1408d27 | ||
|
|
e278f4c24a | ||
|
|
365f2c4b2b | ||
|
|
ac59af9bd1 | ||
|
|
9d5d6203b9 | ||
|
|
1a66a2b8dd | ||
|
|
3b97ecef47 | ||
|
|
ed5b5a2a0c | ||
|
|
37cbab5bad | ||
|
|
11127b72b5 | ||
|
|
d5d87f1e64 | ||
|
|
fa6f228b87 | ||
|
|
21f1a2f47e | ||
|
|
5be7c6bd4e | ||
|
|
9f8e92ce93 | ||
|
|
4bbaca7fe5 | ||
|
|
cf1b4ef3e6 | ||
|
|
c3e36affa8 | ||
|
|
e9a614ba53 | ||
|
|
d57a462462 | ||
|
|
ac114aded4 | ||
|
|
74fc27de12 | ||
|
|
826b6767c9 | ||
|
|
89d5db2b5c | ||
|
|
1dd33050da | ||
|
|
0879638dda | ||
|
|
8a7b9b96ba | ||
|
|
23ea0644f8 | ||
|
|
bd6d856b0e | ||
|
|
6424177e3a | ||
|
|
0b92d2b03b | ||
|
|
bf04610296 | ||
|
|
ff9560f401 | ||
|
|
e0d6a21438 | ||
|
|
da794de6fd | ||
|
|
a1e941c43b | ||
|
|
3bb41960fd | ||
|
|
95fa78d3fd | ||
|
|
eff3dede3a | ||
|
|
7b4c7cffd7 | ||
|
|
8281721bde | ||
|
|
2ece55aa97 | ||
|
|
88c471a315 | ||
|
|
11afddc8da | ||
|
|
f7cac87979 | ||
|
|
5401e8417b | ||
|
|
c61a85e217 | ||
|
|
08cda36387 | ||
|
|
caa8a2d252 | ||
|
|
21eac9d921 | ||
|
|
d75384da6d | ||
|
|
008907161d | ||
|
|
102430c835 | ||
|
|
ce0e6e1d4f | ||
|
|
8c6ffdd911 | ||
|
|
a5a8f9d745 | ||
|
|
1c715483b4 | ||
|
|
08706b7cba | ||
|
|
c1045f2c28 | ||
|
|
46d451ce74 | ||
|
|
1c57fc61d8 | ||
|
|
e56851056d | ||
|
|
28399fefc8 | ||
|
|
7f2e83794e | ||
|
|
1f73b075c9 | ||
|
|
b4026fd169 | ||
|
|
efeb577933 | ||
|
|
fdd8ff04a3 | ||
|
|
89cc2374c7 | ||
|
|
5fc4ee50f6 | ||
|
|
d8a9993f63 | ||
|
|
96fe1eff44 | ||
|
|
033dae3772 | ||
|
|
5efe15a79e | ||
|
|
3d00dbcd55 | ||
|
|
10b72648a8 | ||
|
|
e5dd190874 | ||
|
|
880b44620a | ||
|
|
0a55421f34 | ||
|
|
b7a87285a1 | ||
|
|
b0d8cb82a2 | ||
|
|
9cfca9397b | ||
|
|
a056e181c2 | ||
|
|
d8000dfc2c | ||
|
|
8feaff41fe | ||
|
|
97d5337283 | ||
|
|
87913529e1 | ||
|
|
4e96ab13dd | ||
|
|
2e1c0a95c2 | ||
|
|
096fab8da7 | ||
|
|
aeba1f2db4 | ||
|
|
7e34ce27c7 |
@@ -6,3 +6,40 @@ bdb473cbdb119f3d9060d48f75f965cbd45f6d7a
|
||||
|
||||
# More clang-format: liboslquery, oslinfo, oslc, osl.imageio, osltoy (#1220)
|
||||
bf366d7a90c46599b82071dac6dbef7c5e3ca157
|
||||
|
||||
# Turn on clang-format for cpp files in testsuite (#1269)
|
||||
00c895fc642eb89685797c292048bdff15d675e7
|
||||
5e848fb761261521a3ee7cd8a4f6814f32fe4a47
|
||||
|
||||
# CI: Change our clang-format standard to clang11 (#1372)
|
||||
91d22ebe2f65d4ed0599e421172a15d99fe0e1b4
|
||||
|
||||
# More clang-format (this time, testrender and liboslnoise) (#1511)
|
||||
08706b7cbac781b6a9389780428016be985d9d89
|
||||
|
||||
# clang-format #1509
|
||||
b4026fd1695c08532557b3ba1c2142323087ccf9
|
||||
1f73b075c99861afa42fac44567b37f797bc72f2
|
||||
7f2e83794e6fa63d5180653cffb77be2cc38b32b
|
||||
28399fefc890442b5ac020e7a90cee0d5bf9f03c
|
||||
e56851056d33233b0bb8324faac251907099961a
|
||||
1c57fc61d8ab7c3f309be4335e4c71c26399edd4
|
||||
46d451ce74d00e904874df476ebeca19bb119ea9
|
||||
c1045f2c2845a98e661c7181932a031eb3c76063
|
||||
|
||||
# More clang-format (#1512)
|
||||
8c6ffdd911b9eb7db4adf41ab88891360452d7c5
|
||||
|
||||
# style: more clang-format (#1515)
|
||||
102430c83554fe7e328cd8c3317db00507bcfaba
|
||||
|
||||
# Revert some formatting (#1518)
|
||||
21eac9d9215d071b0a7b9ce2c32f189ed0c62c4a
|
||||
|
||||
# Another round of clang-format (#1540)
|
||||
38015b6be28643254aea530154b7860136cf5e15
|
||||
89d5db2b5c5fda79184d8245d903e580fc6a4e9c
|
||||
|
||||
# clang-format: the very last piece of the puzzle (#1555)
|
||||
4ee62cd2ef05543f818f4d95a19efc1d684a7381
|
||||
5be7c6bd4e7bd2e560cb6be8c06f11985384a87a
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
# Copyright 2008-present Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
name: Analysis
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Run nightly while we're still working our way through the warnings
|
||||
- cron: "0 8 * * *"
|
||||
# Run unconditionally once weekly
|
||||
# - cron: "0 0 * * 0"
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- '*analysis*'
|
||||
# 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:
|
||||
|
||||
aswf:
|
||||
name: "SonarCloud Analysis"
|
||||
if: |
|
||||
github.repository == 'AcademySoftwareFoundation/OpenShadingLanguage'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- desc: sonar gcc9/C++14 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
|
||||
nametag: static-analysis-sonar
|
||||
os: ubuntu-20.04-8c-32g-300h
|
||||
# os: ubuntu-latest
|
||||
vfxyear: 2022
|
||||
vfxsuffix: -clang13
|
||||
cxx_std: 14
|
||||
openimageio_ver: master
|
||||
python_ver: 3.9
|
||||
pybind11_ver: v2.9.0
|
||||
simd: avx2,f16c
|
||||
batched: b8_AVX2,b16_AVX512
|
||||
coverage: 1
|
||||
# skip_tests: 1
|
||||
sonar: 1
|
||||
setenvs: export SONAR_SCANNER_VERSION=4.7.0.2747
|
||||
SONAR_SERVER_URL="https://sonarcloud.io"
|
||||
BUILD_WRAPPER_OUT_DIR=bw_output
|
||||
OSL_CMAKE_BUILD_WRAPPER="build-wrapper-linux-x86-64 --out-dir bw_output"
|
||||
CMAKE_BUILD_TYPE=Debug
|
||||
CMAKE_UNITY_BUILD=OFF
|
||||
CODECOV=1
|
||||
TESTRENDER_AA=1
|
||||
OSL_TESTSUITE_SKIP_DIFF=1
|
||||
CTEST_TEST_TIMEOUT=1200
|
||||
OSL_CMAKE_FLAGS="-DOSL_TEST_BIG_TIMEOUT=1200 -DUSE_QT=0"
|
||||
CTEST_EXCLUSIONS="broken|noise-reg.regress|noise-gabor-reg.regress"
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
container:
|
||||
image: aswf/ci-osl:${{matrix.vfxyear}}${{matrix.vfxsuffix}}
|
||||
env:
|
||||
CXX: ${{matrix.cxx_compiler}}
|
||||
CC: ${{matrix.cc_compiler}}
|
||||
CMAKE_CXX_STANDARD: ${{matrix.cxx_std}}
|
||||
FMT_VERSION: ${{matrix.fmt_ver}}
|
||||
OPENEXR_VERSION: ${{matrix.openexr_ver}}
|
||||
OPENIMAGEIO_VERSION: ${{matrix.openimageio_ver}}
|
||||
PYBIND11_VERSION: ${{matrix.pybind11_ver}}
|
||||
PYTHON_VERSION: ${{matrix.python_ver}}
|
||||
USE_BATCHED: ${{matrix.batched}}
|
||||
USE_SIMD: ${{matrix.simd}}
|
||||
PARALLEL: 24
|
||||
# DEBUG_CI: 1
|
||||
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
|
||||
# on CI runs where we are producing artifacts that users might rely on.
|
||||
# - name: Harden Runner
|
||||
# uses: step-security/harden-runner@248ae51c2e8cc9622ecf50685c8bf7150c6e8813 # v1.4.3
|
||||
# with:
|
||||
# egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
|
||||
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
|
||||
with:
|
||||
fetch-depth: '0'
|
||||
- name: Prepare ccache timestamp
|
||||
id: ccache_cache_keys
|
||||
run: echo "::set-output name=date::`date -u +'%Y-%m-%dT%H:%M:%SZ'`"
|
||||
- name: ccache
|
||||
id: ccache
|
||||
uses: actions/cache@c3f1317a9e7b1ef106c153ac8c0f00fed3ddbc0d # v3.0.4
|
||||
with:
|
||||
path: /tmp/ccache
|
||||
key: ${{github.job}}-${{matrix.nametag}}-${{steps.ccache_cache_keys.outputs.date}}
|
||||
restore-keys: ${{github.job}}-
|
||||
- name: Build setup
|
||||
run: |
|
||||
${{matrix.setenvs}}
|
||||
src/build-scripts/ci-startup.bash
|
||||
- name: Remove existing OIIO
|
||||
if: matrix.openimageio_ver != ''
|
||||
run: |
|
||||
sudo rm -rf /usr/local/include/OpenImageIO
|
||||
sudo rm -rf /usr/local/lib*/cmake/OpenImageIO
|
||||
sudo rm -rf /usr/local/lib*/libOpenImageIO*
|
||||
sudo rm -rf /usr/local/lib*/python3.9/site-packages/OpenImageIO*
|
||||
- name: Dependencies
|
||||
run: |
|
||||
${{matrix.depcmds}}
|
||||
src/build-scripts/gh-installdeps.bash
|
||||
- name: Build
|
||||
run: src/build-scripts/ci-build.bash
|
||||
- name: Testsuite
|
||||
if: matrix.skip_tests != '1'
|
||||
run: src/build-scripts/ci-test.bash
|
||||
- name: Code coverage
|
||||
if: matrix.coverage == '1'
|
||||
run: src/build-scripts/ci-coverage.bash
|
||||
- name: Sonar-scanner
|
||||
if: matrix.sonar == 1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
run: |
|
||||
sonar-scanner -X --define sonar.host.url="${{ env.SONAR_SERVER_URL }}" --define sonar.cfamily.build-wrapper-output="build/bw_output" --define sonar.cfamily.gcov.reportsPath="_coverage"
|
||||
+167
-85
@@ -23,6 +23,13 @@ on:
|
||||
# Full nightly build
|
||||
- cron: "0 6 * * *"
|
||||
|
||||
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:
|
||||
|
||||
@@ -38,10 +45,9 @@ jobs:
|
||||
vfxyear: 2019
|
||||
vfxsuffix: -clang9
|
||||
cxx_std: 14
|
||||
openimageio_ver: v2.2.17.0
|
||||
openimageio_ver: v2.3.17.0
|
||||
python_ver: 2.7
|
||||
pybind11_ver: v2.4.2
|
||||
setenvs: export xUSE_PYTHON=0
|
||||
- desc: clang9/C++14 llvm9 oiio-release boost1.66 avx2 exr2.3 py2.7
|
||||
nametag: linux-clang9-llvm9
|
||||
os: ubuntu-18.04
|
||||
@@ -71,7 +77,7 @@ jobs:
|
||||
os: ubuntu-latest
|
||||
vfxyear: 2020
|
||||
cxx_std: 14
|
||||
openimageio_ver: v2.2.17.0
|
||||
openimageio_ver: v2.3.17.0
|
||||
python_ver: 3.7
|
||||
pybind11_ver: v2.5.0
|
||||
simd: sse4.2
|
||||
@@ -82,7 +88,7 @@ jobs:
|
||||
vfxyear: 2021
|
||||
vfxsuffix: -clang11
|
||||
cxx_std: 17
|
||||
openimageio_ver: dev-2.2
|
||||
openimageio_ver: dev-2.3
|
||||
python_ver: 3.7
|
||||
pybind11_ver: v2.7.0
|
||||
simd: avx2,f16c
|
||||
@@ -111,6 +117,7 @@ jobs:
|
||||
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
|
||||
nametag: linux-icc
|
||||
os: ubuntu-latest
|
||||
vfxyear: 2022
|
||||
vfxsuffix: -clang13
|
||||
@@ -126,7 +133,8 @@ 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 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
|
||||
nametag: linux-icx
|
||||
os: ubuntu-latest
|
||||
vfxyear: 2022
|
||||
vfxsuffix: -clang13
|
||||
@@ -146,11 +154,71 @@ jobs:
|
||||
vfxyear: 2019
|
||||
vfxsuffix: -clang9
|
||||
cxx_std: 14
|
||||
openimageio_ver: v2.2.17.0
|
||||
openimageio_ver: v2.3.17.0
|
||||
python_ver: 2.7
|
||||
pybind11_ver: v2.6.2
|
||||
simd: 0
|
||||
setenvs: export USE_PYTHON=0 PUGIXML_VERSION=v1.8
|
||||
setenvs: export PUGIXML_VERSION=v1.8
|
||||
|
||||
# Address and leak sanitizers
|
||||
- desc: sanitizers
|
||||
nametag: sanitizer
|
||||
os: ubuntu-latest
|
||||
vfxyear: 2022
|
||||
vfxsuffix: -clang13
|
||||
cc_compiler: clang
|
||||
cxx_compiler: clang++
|
||||
cxx_std: 17
|
||||
openimageio_ver: master
|
||||
python_ver: 3.9
|
||||
pybind11_ver: v2.9.0
|
||||
simd: avx2,f16c
|
||||
batched: b8_AVX2
|
||||
setenvs: export OSL_CMAKE_FLAGS="-DSANITIZE=address -DOSL_TEST_BIG_TIMEOUT=1200"
|
||||
CMAKE_BUILD_TYPE=Debug
|
||||
CTEST_TEST_TIMEOUT=1200
|
||||
CTEST_EXCLUSIONS="broken|noise-reg.regress|noise-gabor-reg.regress|example-.*deformer|spline-reg.regress.batched|osl-imageio"
|
||||
OSL_OPTIONS=llvm_debugging_symbols=1
|
||||
TESTRENDER_AA=1
|
||||
OSL_TESTSUITE_SKIP_DIFF=1
|
||||
# Sanitizer notes:
|
||||
# - There are a handful of tests we disable entirely with
|
||||
# CTEST_EXCLUSIONS because they are irrelevant or just cannot be
|
||||
# made to be clean (and that's ok).
|
||||
# - Tests with sanitizers run slow, so we increase timeouts, and
|
||||
# also set AA to 1 for render tests to speed them up.
|
||||
# OSL_TESTSUITE_SKIP_DIFF prevents making the AA=1 image result
|
||||
# fail, but that's ok because every other CI test is checking
|
||||
# the results; here we have no reason to believe results will
|
||||
# differ from other tests, we just need to run with sanitizers
|
||||
# turned on.
|
||||
# - In testing.cmake, we rig texture tests to disable the leak
|
||||
# sanitizer, because we can't eliminate some completely benign
|
||||
# leaks from the texture system, and because they are called
|
||||
# from JITed code, we don't get a clean stack trace of things
|
||||
# that happen in OIIO and therefore we just can't enumerate the
|
||||
# allowed exceptions. So we trust that OIIO itself tests the
|
||||
# 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
|
||||
cxx_std: 17
|
||||
openimageio_ver: release
|
||||
python_ver: 3.9
|
||||
simd: avx2,f16c
|
||||
batched: b8_AVX2
|
||||
skip_tests: 1
|
||||
setenvs: export BUILDTARGET=clang-format
|
||||
OPENIMAGEIO_CMAKE_FLAGS=-DUSE_PYTHON=0
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
container:
|
||||
@@ -167,13 +235,20 @@ jobs:
|
||||
USE_BATCHED: ${{matrix.batched}}
|
||||
USE_SIMD: ${{matrix.simd}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
# 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
|
||||
# on CI runs where we are producing artifacts that users might rely on.
|
||||
# - name: Harden Runner
|
||||
# uses: step-security/harden-runner@248ae51c2e8cc9622ecf50685c8bf7150c6e8813 # v1.4.3
|
||||
# with:
|
||||
# egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
|
||||
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
|
||||
- name: Prepare ccache timestamp
|
||||
id: ccache_cache_keys
|
||||
run: echo "::set-output name=date::`date -u +'%Y-%m-%dT%H:%M:%SZ'`"
|
||||
- name: ccache
|
||||
id: ccache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@c3f1317a9e7b1ef106c153ac8c0f00fed3ddbc0d # v3.0.4
|
||||
with:
|
||||
path: /tmp/ccache
|
||||
key: ${{github.job}}-${{matrix.nametag}}-${{steps.ccache_cache_keys.outputs.date}}
|
||||
@@ -199,7 +274,7 @@ jobs:
|
||||
- name: Testsuite
|
||||
if: matrix.skip_tests != '1'
|
||||
run: src/build-scripts/ci-test.bash
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
|
||||
if: failure()
|
||||
with:
|
||||
name: osl-${{github.job}}-${{matrix.nametag}}
|
||||
@@ -243,38 +318,55 @@ 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 llvm12 boost1.71 exr3.1 py3.8 avx2 batch-b16avx512
|
||||
- desc: latest releases gcc11/C++17 llvm13 boost1.71 exr3.1 py3.9 avx2 batch-b16avx512
|
||||
nametag: linux-latest-releases
|
||||
os: ubuntu-20.04
|
||||
cxx_compiler: g++-11
|
||||
cxx_std: 17
|
||||
fmt_ver: 8.1.1
|
||||
openexr_ver: v3.1.4
|
||||
fmt_ver: 9.1.0
|
||||
openexr_ver: v3.1.5
|
||||
openimageio_ver: master
|
||||
pybind11_ver: v2.9.1
|
||||
python_ver: 3.8
|
||||
simd: avx2,f16c
|
||||
batched: b8_AVX2,b8_AVX512,b16_AVX512
|
||||
setenvs: export LLVM_VERSION=12.0.0
|
||||
LLVM_DISTRO_NAME=ubuntu-20.04
|
||||
OPENCOLORIO_VERSION=v2.1.1
|
||||
PUGIXML_VERSION=v1.11.4
|
||||
- desc: bleeding edge gcc11/C++17 llvm13 oiio/ocio/exr/pybind-master boost1.71 py3.9 avx2 batch-b16avx512
|
||||
nametag: linux-bleeding-edge
|
||||
os: ubuntu-20.04
|
||||
cxx_compiler: g++-11
|
||||
cxx_std: 17
|
||||
fmt_ver: master
|
||||
openexr_ver: main
|
||||
openimageio_ver: master
|
||||
pybind11_ver: master
|
||||
pybind11_ver: v2.10.0
|
||||
python_ver: 3.9
|
||||
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
|
||||
nametag: linux-bleeding-edge
|
||||
os: ubuntu-22.04
|
||||
cxx_compiler: g++-12
|
||||
cxx_std: 17
|
||||
fmt_ver: master
|
||||
openexr_ver: main
|
||||
openimageio_ver: master
|
||||
pybind11_ver: master
|
||||
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
|
||||
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
|
||||
cxx_compiler: clang++
|
||||
cc_compiler: clang
|
||||
cxx_std: 17
|
||||
fmt_ver: 8.1.1
|
||||
openexr_ver: v3.1.5
|
||||
openimageio_ver: master
|
||||
pybind11_ver: v2.9.2
|
||||
python_ver: 3.8
|
||||
simd: avx2,f16c
|
||||
batched: b8_AVX2,b8_AVX512,b16_AVX512
|
||||
setenvs: export LLVM_VERSION=14.0.0
|
||||
LLVM_DISTRO_NAME=ubuntu-18.04
|
||||
OPENCOLORIO_VERSION=v2.1.2
|
||||
PUGIXML_VERSION=v1.11.4
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
env:
|
||||
@@ -289,13 +381,20 @@ jobs:
|
||||
USE_BATCHED: ${{matrix.batched}}
|
||||
USE_SIMD: ${{matrix.simd}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
# 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
|
||||
# on CI runs where we are producing artifacts that users might rely on.
|
||||
# - name: Harden Runner
|
||||
# uses: step-security/harden-runner@248ae51c2e8cc9622ecf50685c8bf7150c6e8813 # v1.4.3
|
||||
# with:
|
||||
# egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
|
||||
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
|
||||
- name: Prepare ccache timestamp
|
||||
id: ccache_cache_keys
|
||||
run: echo "::set-output name=date::`date -u +'%Y-%m-%dT%H:%M:%SZ'`"
|
||||
- name: ccache
|
||||
id: ccache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@c3f1317a9e7b1ef106c153ac8c0f00fed3ddbc0d # v3.0.4
|
||||
with:
|
||||
path: /tmp/ccache
|
||||
key: ${{github.job}}-${{matrix.nametag}}-${{steps.ccache_cache_keys.outputs.date}}
|
||||
@@ -313,7 +412,7 @@ jobs:
|
||||
- name: Testsuite
|
||||
if: matrix.skip_tests != '1'
|
||||
run: src/build-scripts/ci-test.bash
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
|
||||
if: failure()
|
||||
with:
|
||||
name: osl-${{github.job}}-${{matrix.nametag}}
|
||||
@@ -326,88 +425,71 @@ jobs:
|
||||
macos:
|
||||
name: "${{matrix.os}} appleclang${{matrix.aclang}}/C++${{matrix.cxx_std}} py${{matrix.python_ver}} ${{matrix.desc}}"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- desc: llvm11
|
||||
os: macos-10.15
|
||||
nametag: macos10-py39
|
||||
cxx_std: 14
|
||||
python_ver: 3.9
|
||||
aclang: 12
|
||||
- desc: llvm11
|
||||
- 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++
|
||||
cxx_std: 17
|
||||
python_ver: 3.9
|
||||
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++
|
||||
cxx_std: 17
|
||||
python_ver: "3.10"
|
||||
aclang: 13
|
||||
setenvs: export LLVMBREWVER="@15" DO_BREW_UPDATE=1
|
||||
runs-on: ${{matrix.os}}
|
||||
env:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
CXX: ${{matrix.cxx_compiler}}
|
||||
CC: ${{matrix.cc_compiler}}
|
||||
CMAKE_CXX_STANDARD: ${{matrix.cxx_std}}
|
||||
PYTHON_VERSION: ${{matrix.python_ver}}
|
||||
OPENIMAGEIO_VERSION: ${{matrix.openimageio_ver}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
|
||||
- name: Prepare ccache timestamp
|
||||
id: ccache_cache_keys
|
||||
run: echo "::set-output name=date::`date -u +'%Y-%m-%dT%H:%M:%SZ'`"
|
||||
- name: ccache
|
||||
id: ccache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@c3f1317a9e7b1ef106c153ac8c0f00fed3ddbc0d # v3.0.4
|
||||
with:
|
||||
path: /Users/runner/.ccache
|
||||
key: ${{github.job}}-${{matrix.os}}-${{steps.ccache_cache_keys.outputs.date}}
|
||||
restore-keys: ${{github.job}}-${{matrix.os}}-
|
||||
key: ${{github.job}}-${{matrix.nametag}}-${{steps.ccache_cache_keys.outputs.date}}
|
||||
restore-keys: ${{github.job}}-${{matrix.nametag}}-
|
||||
- name: Build setup
|
||||
run: src/build-scripts/ci-startup.bash
|
||||
run: |
|
||||
${{matrix.setenvs}}
|
||||
src/build-scripts/ci-startup.bash
|
||||
- name: Dependencies
|
||||
run: |
|
||||
source src/build-scripts/install_homebrew_deps.bash
|
||||
# OPENIMAGEIO_CMAKE_FLAGS="-DOIIO_BUILD_TESTS=0 -DUSE_OPENGL=0"
|
||||
# source src/build-scripts/build_openimageio.bash
|
||||
brew install --display-times -q openimageio
|
||||
PYTHONPATH=$PYTHONPATH:/usr/local/python${PYTHON_VERSION}/site-packages
|
||||
if [[ "$OPENIMAGEIO_VERSION" != "" ]] ; then \
|
||||
OPENIMAGEIO_CMAKE_FLAGS="-DOIIO_BUILD_TESTS=0 -DUSE_OPENGL=0" ; \
|
||||
source src/build-scripts/build_openimageio.bash ; \
|
||||
else \
|
||||
brew install --display-times -q openimageio ; \
|
||||
PYTHONPATH=$PYTHONPATH:/usr/local/python${PYTHON_VERSION}/site-packages ; \
|
||||
fi
|
||||
src/build-scripts/save-env.bash
|
||||
- name: Build
|
||||
run: |
|
||||
src/build-scripts/ci-build.bash
|
||||
- name: Testsuite
|
||||
run: src/build-scripts/ci-test.bash
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
|
||||
if: failure()
|
||||
with:
|
||||
name: osl-${{github.job}}
|
||||
name: osl-${{github.job}}-${{matrix.nametag}}
|
||||
path: |
|
||||
build/*.cmake
|
||||
build/CMake*
|
||||
build/testsuite/*/*.*
|
||||
|
||||
|
||||
clang-format:
|
||||
# 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).
|
||||
name: "clang-format verification"
|
||||
runs-on: ubuntu-18.04
|
||||
container:
|
||||
image: aswf/ci-osl:2021-clang11
|
||||
env:
|
||||
BUILDTARGET: clang-format
|
||||
CMAKE_CXX_STANDARD: 17
|
||||
PYTHON_VERSION: 3.7
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build setup
|
||||
run: |
|
||||
src/build-scripts/ci-startup.bash
|
||||
- name: Dependencies
|
||||
run: |
|
||||
src/build-scripts/gh-installdeps.bash
|
||||
- name: Build
|
||||
run: |
|
||||
src/build-scripts/ci-build.bash
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: failure()
|
||||
with:
|
||||
name: osl-${{github.job}}
|
||||
path: src/*/*.{cpp,h}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
name: Scorecards supply-chain security
|
||||
on:
|
||||
# Only the default branch is supported.
|
||||
branch_protection_rule:
|
||||
schedule:
|
||||
- cron: '44 20 * * 6'
|
||||
push:
|
||||
branches: [ "main", "scorecard" ]
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
analysis:
|
||||
name: Scorecards analysis
|
||||
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"
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@3e15ea8318eee9b333819ec77a36aca8d39df13e # v1.1.1
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
# (Optional) Read-only PAT token. Uncomment the `repo_token` line below if:
|
||||
# - you want to enable the Branch-Protection check on a *public* repository, or
|
||||
# - you are installing Scorecards on a *private* repository
|
||||
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
|
||||
# repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}
|
||||
|
||||
# Publish the results for public repositories to enable scorecard badges. For more details, see
|
||||
# https://github.com/ossf/scorecard-action#publishing-results.
|
||||
# For private repositories, `publish_results` will automatically be set to `false`, regardless
|
||||
# of the value entered here.
|
||||
publish_results: true
|
||||
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@5f532563584d71fdef14ee64d17bafb34f751ce5 # v1.0.26
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
@@ -8,3 +8,6 @@ build
|
||||
\#*\#
|
||||
*.pyc
|
||||
*.log
|
||||
.vscode
|
||||
.envrc
|
||||
|
||||
|
||||
@@ -50,4 +50,4 @@ This is a checklist for TSC's to review as part of the intake process. The TSC s
|
||||
- [X] License scan completed and no issues found
|
||||
- Minor issues were found but already fixed in PR https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1145
|
||||
- [X] Code repository imported to ASWF GitHub organization
|
||||
- [ ] Developer Certificate of Origin past commit signoff done and DCO Probot enabled.
|
||||
- [X] Developer Certificate of Origin post commit signoff done and DCO Probot enabled.
|
||||
|
||||
+135
-9
@@ -1,8 +1,84 @@
|
||||
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
||||
<!-- Copyright Contributors to the Open Shading Language Project. -->
|
||||
|
||||
Release 1.12 -- ?? (compared to 1.11)
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
OSL Standard library:
|
||||
|
||||
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)
|
||||
|
||||
SIMD batched shading mode:
|
||||
* Fix some array overruns (asymptomatic, but still potentially buggy) in
|
||||
common_ancestor_between. #1577 (1.13.0.2)
|
||||
|
||||
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
|
||||
extra level of indirection to global variables is removed, and strings are
|
||||
simply represented in ordinary variables as the hash of their characters.
|
||||
#1531 (1.13.0.0) #1553 (1.13.0.1)
|
||||
* 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)
|
||||
|
||||
Performance improvements:
|
||||
|
||||
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:
|
||||
* platform.h:
|
||||
- New `OSL_ALLOCA` macro to allocate on the stack. #1589 (1.13.0.3)
|
||||
|
||||
Build & test system improvements:
|
||||
* CMake build system and scripts:
|
||||
- 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)
|
||||
* Dependency version support:
|
||||
- Fix some issues that came up with the new icx 2022.0 compiler. #1601
|
||||
(1.13.1.0)
|
||||
* 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
|
||||
information. #1584 (1.13.0.3)
|
||||
- Improvements to SonarCloud and coverage analysis. #1596 (1.13.0.3)
|
||||
* Platform support:
|
||||
|
||||
Documentation:
|
||||
* `doc/RELEASING.md` documents our release process and versioning policies.
|
||||
#1572 (1.13.0.2)
|
||||
|
||||
|
||||
Release 1.12 -- 1 Oct 2022 (compared to 1.11)
|
||||
----------------------------------------------
|
||||
Big Deal Changes:
|
||||
* **Batch shading**: A fully operational "batch shading" support when using
|
||||
CPUs supporting the Intel AVX2 or AVX512 instruction set architectures,
|
||||
allows shading 8 or 16 points at a time, accelerated by using SIMD
|
||||
instructions. (Changes contributed by Intel.)
|
||||
* **OptiX**: A reasonable subset of the OSL language can run on NVIDIA GPUs
|
||||
for Cuda or OptiX-based renderers.
|
||||
* **Standardized material closures**: Synchronize with MaterialX on a minimum
|
||||
standard set of material closures. This is reflected in both the OSL spec as
|
||||
well as reference implementations of those closures in testrender. #1533
|
||||
#1536 #1537 #1538 #1539 #1541 #1542 #1547 #1557
|
||||
|
||||
Dependency and standards requirements changes:
|
||||
* The minimum (and default) compilation mode is now C++14. C++17 and 20 are
|
||||
also supported. #1362 #1369 (1.12.2)
|
||||
@@ -33,6 +109,8 @@ OSL Standard library:
|
||||
* Fix previously-broken color conversions from RGB to xyY. #1410 (1.12.3)
|
||||
* Fully removed MaterialX shaders (get those from the MaterialX project).
|
||||
#1450 (1.12.3)
|
||||
* Fix incorrect implementation of `matrix4 * vector4` in vector4.h #1513
|
||||
(1.12.5.0)
|
||||
|
||||
API changes, new options, new ShadingSystem features (for renderer writers):
|
||||
* Custom experimental llvm optimization levels 10, 11, 12, and 13. These
|
||||
@@ -49,8 +127,16 @@ API changes, new options, new ShadingSystem features (for renderer writers):
|
||||
* Userdata input placement -- now you can designate where interpolated
|
||||
userdata should be copied from directly, rather then via callbacks to
|
||||
RendererServices::get_userdata(). #1391 (1.12.3)
|
||||
* Better hiding of the Matrix22 class, which was never actually part of the
|
||||
public APIs. #1480 (1.12.4.5)
|
||||
* Add ACES2065-1 and ACEScg as shading system color spaces (#1486) (1.12.4.6)
|
||||
* Expanded warnings (via enabling the "opt_warnings" attribute of the
|
||||
ShadingSystem) for operations that try to create new strings mid-shader, or
|
||||
that need to access the characters of strings mid-shader. These are only
|
||||
triggered for those cases that cannot be resolved by the end of the "runtime
|
||||
optimization" phase. #1497 (1.12.4.6)
|
||||
|
||||
Continued work on experimental SIMD batched shading mode:
|
||||
SIMD batched shading mode:
|
||||
* Added support for masked operations to LLVMUtil. #1248 #1250 (1.12.0.0)
|
||||
* Add interface to ShadingSystem for batched execution. #1272 (1.12.0.1)
|
||||
* Add interface to batched RendererServices. #1276 (1.12.0.1)
|
||||
@@ -63,7 +149,7 @@ Continued work on experimental SIMD batched shading mode:
|
||||
* ISA-specific modules. #1345 (1.12.2)
|
||||
* Introduction of CI testing of batched mode. #1357 #1367 (1.12.2)
|
||||
* Control flow and string ops. #1372 (1.12.2)
|
||||
* Matrix operations. #1378 (1.12.2)
|
||||
* Matrix operations. #1378 (1.12.2) #1485 (1.12.4.6)
|
||||
* Batched algebraic, trig, and transcendental functions. #1385 (1.12.2)
|
||||
* Batched noise. #1394 (1.12.3)
|
||||
* Batched implementation of all color operations. #1408 (1.12.3)
|
||||
@@ -75,8 +161,9 @@ Continued work on experimental SIMD batched shading mode:
|
||||
* Batched isnan, isinf, isfinite. #1456 (1.12.4.2)
|
||||
* Batched userdata and output placement. #1455 (1.12.4.2)
|
||||
* Batched pointcloud functions. #1464 (1.12.4.4)
|
||||
* Batched closures (#1500)
|
||||
|
||||
Continued work on experimental OptiX rendering:
|
||||
OptiX rendering:
|
||||
* Explicitly set the OptiX pipeline stack size. #1254 (1.12.0.0)
|
||||
* CI tests now at least compile and build with USE_OPTIX=1 (though not yet
|
||||
run the tests). #1281 (1.12.0.1)
|
||||
@@ -93,10 +180,12 @@ Continued work on experimental OptiX rendering:
|
||||
* Fix race conditions when compiling for OptiX 7. #1411 (1.12.3)
|
||||
* osl_get_attribute() uses device strings when compiling for OptiX.
|
||||
#1435 (1.12.3)
|
||||
* Fix issue with OptiX + clang 14 with duplicate symbols. #1561 (1.12.6.0)
|
||||
|
||||
Performance improvements:
|
||||
* Less mutex locking around use and retrieval of ColorSystem related to
|
||||
doing color transforms. #1405 (1.12.3)
|
||||
* Constant folding of `startswith()`. #1507 (1.12.5.0)
|
||||
|
||||
Bug fixes and other improvements (internals):
|
||||
* Fix derivatives of texture calls when only derivatives of the "alpha"
|
||||
@@ -133,6 +222,15 @@ Bug fixes and other improvements (internals):
|
||||
globals. #1462 (1.12.4.4)
|
||||
* Print all 4 levels of version numbers in help messages. #1477 (1.12.4.4)
|
||||
* Fix GPU code generation crash. #1479 (1.12.4.4)
|
||||
* Work to transition internals to use modern std::format notation for
|
||||
formatted output. #1487 #1490 (1.12.4.6) #1504 #1506 (1.12.5.0)
|
||||
* testrender improvements:
|
||||
* Fix testrender memory error on teardown. #1499 (1.12.4.6)
|
||||
* Modernize the sampler in testrender, improving quality and performance.
|
||||
#1534 (1.12.6.0)
|
||||
* Switch to cone tracing for derivatives. #1543 (1.12.6.0)
|
||||
* Fix error that prevented correct typecheck of ternary operator. #1552
|
||||
(1.12.6.0)
|
||||
|
||||
Internals/developer concerns:
|
||||
* Use the `final` keyword in certain internal classes where applicable.
|
||||
@@ -150,6 +248,18 @@ Internals/developer concerns:
|
||||
whenever we need to parse strings. #1432 (1.12.3)
|
||||
* Avoid use of OIIO::string_view::str() which is not corresponding to the
|
||||
official C++17 std::string_view. #1467 (1.12.4.4)
|
||||
* Prototype of "free function" approach that will someday mostly supplant
|
||||
the way we use RendererServices, and will help to unlock feature completion
|
||||
for GPU and other back ends. This experimental feature is not expected
|
||||
to be used in OSL 1.12. #1494 (1.12.5.0)
|
||||
* Work on gradually converting printf-style formatted strings to fmt /
|
||||
std::format style. #1493 (1.12.5.0)
|
||||
* LLVM_Util: allow naming of llvm symbols to help with IR debugging. #1530
|
||||
(1.12.6.0)
|
||||
* clang-format the code base. #1508 #1509 #1511 #1512 #1515 #1518 #1540
|
||||
(1.12.5.0) #1555 #1562 #1568 (1.12.6.0)
|
||||
* A round of spell-checking all the comments in the code base. #1550
|
||||
(1.12.5.0)
|
||||
|
||||
Build & test system improvements:
|
||||
* CMake build system and scripts:
|
||||
@@ -191,17 +301,19 @@ Build & test system improvements:
|
||||
(1.12.4.4)
|
||||
* Dependency version support:
|
||||
- Build properly against Cuda 11 and OptiX 7.1. #1232 (1.12.0.1)
|
||||
and up to OptiX 7.4 #1559 (1.12.6.0)
|
||||
- PugiXML build fixes on some systems. #1262 (1.12.0.1/1.11.8)
|
||||
- Cuda/OptiX back end: Add `__CUDADEVRT_INTERNAL__` define to bitcode
|
||||
generation, needed to avoid duplicate cudaMalloc symbols with CUDA9+
|
||||
#1271 (1.12.0.1)
|
||||
- Build against LLVM 11 #1274 (1.12.0.1), LLVM 12 #1351 (1.12.1.0)
|
||||
#1412 (1.12.3), LLVM 13 #1420 (1.12.3)
|
||||
#1412 (1.12.3), LLVM 13 #1420 (1.12.3), LLVM 14 #1492 (1.12.4.6)
|
||||
LLVM 15 #1592 (1.12.6.2)
|
||||
- Fix build break against recent OIIO master change where m_mutex field
|
||||
was removed from ImageInput. #1281 (1.12.0.1/1.11.9)
|
||||
- Work to ensure that OIIO will build correctly against the upcoming
|
||||
Imath 3.0 and OpenEXR 3.0. #1299 (1.11.10/1.12.1) #1332 (1.11.11/1.12.1)
|
||||
#1341 (1.11.12/1.12.1) #1356 #1368 (1.11.13/1.12.2)
|
||||
#1341 (1.11.12/1.12.1) #1356 #1368 (1.11.13/1.12.2) #1489 (1.12.4.6)
|
||||
- Improved finding of llvm components when using static libraries. #1375
|
||||
(1.12.2)
|
||||
- No longer use boost regex, completely rely on std::regex now that OSL
|
||||
@@ -215,6 +327,8 @@ Build & test system improvements:
|
||||
compilers. #1459 #1473 #1475. (1.12.4.4)
|
||||
- Fixes for recent OIIO TextureSystem changes that hide Imath types.
|
||||
#1476 (1.12.4.4)
|
||||
- Changes to work correctly with OpenImageIO 2.4 and its master being
|
||||
the start of 2.5. #1569 (1.12.6.0)
|
||||
* Testing and Continuous integration (CI) systems:
|
||||
- Eliminate the old Travis CI and Appveyor. #1334 #1338 (1.12.1)
|
||||
- Use ccache + GitHub 'cache' action to greatly speed up CI runs. #1335
|
||||
@@ -223,14 +337,15 @@ Build & test system improvements:
|
||||
scripts for CentOS and Ubuntu ito a single script. #1338 (1.12.1)
|
||||
- CI tests clang11, also batched shading with clang. #1379 (1.12.2)
|
||||
- CI speeds up OIIO builds by not building its tests. #1380 (1.12.2)
|
||||
- CI tests gcc11. #1381 (1.12.2)
|
||||
- CI tests gcc11 #1381 (1.12.2) and gcc12 #1565 (1.12.6)
|
||||
- Deal with OpenColorIO changing its master branch to "main". #1429
|
||||
(1.12.3)
|
||||
- Fix tests for texture3d now that OIIO has dropped support for Field3D.
|
||||
#1437 (1.12.3)
|
||||
- Test against LLVM13/clang13 for the VFX Platform 2022 tests. #1434
|
||||
(1.12.3)
|
||||
- Test against MacOS-11. #1434 (1.12.3)
|
||||
- CI test against MacOS-11 #1434 (1.12.3) and MacOS-12 #1554 (1.12.6)
|
||||
#1522 (1.12.5)
|
||||
- Add testsuite coverage of environment(). #1438 (1.12.3)
|
||||
- Use a project-specific environment variable `OSL_CI` instead of the more
|
||||
generic `CI` to avoid clashes with other systems. #1446 (1.12.3)
|
||||
@@ -242,10 +357,18 @@ Build & test system improvements:
|
||||
#1472 (1.12.4.4)
|
||||
- Allow `-Werror` to be disabled even on CI branches. #1471 (1.12.4.4)
|
||||
- CI Tests against the Intel icc and icx compilers! #1459 #1473 (1.12.4.4)
|
||||
#1501 (1.12.5.0)
|
||||
- Overhaul of GHA ci.yml to use strategy matrix. #1474 (1.12.4.4)
|
||||
- Test against clang 14 and fix new warnings. #1498 (1.12.5.0)
|
||||
- Test against clang 15 and fix new warnings. #1586 (1.12.6.2)
|
||||
- A scorecards workflow guards against a variety of security issues of
|
||||
the CI system itself. #1529 (1.12.6.0)
|
||||
- Enable SonarCloud static analysis. #1551 #1556 #1563 (1.12.6.0)
|
||||
* Platform support:
|
||||
- Various Windows compile fixes. #1263 #1285 (1.12.0.1)
|
||||
- Windows+Cuda build fixes. #1292 (1.12.0.1)
|
||||
- Fix warnings about pointer casts on Windows. #1484 (1.12.4.5)
|
||||
- Various Windows build fixes. #1502 (1.12.5.0)
|
||||
* The oso and osl lexers/parsers are now given internal symbol names that
|
||||
are fully versioned, to avoid possible clash if multiple OSL releases are
|
||||
both linked into the same application. #1255 (1.12.0.0)
|
||||
@@ -260,6 +383,9 @@ Documentation:
|
||||
#1326 (1.12.1)
|
||||
* Fix missing explanation of the optional "errormessage" parameter to
|
||||
environment() and texture3d(). #1442 (1.12.3/1.11.17)
|
||||
* A SECURITY.md file explains how to confidentially report vulnerabilities.
|
||||
#1529 (1.12.6)
|
||||
* Document all the new MaterialX closures. #1564
|
||||
|
||||
|
||||
|
||||
@@ -727,7 +853,7 @@ Build & test system improvements:
|
||||
use clang library components for preprocessing. #1089 (1.11.3)
|
||||
* Add an optional build-time `EXTRA_WARNINGS` option (default: OFF) that
|
||||
enables even more picky than usual warnings. Fix many warnings that cropped
|
||||
up during testing, mostly related to unused function paramters. #1106 (1.11.3)
|
||||
up during testing, mostly related to unused function parameters. #1106 (1.11.3)
|
||||
* The testsuite can run in parallel, with a number of threads set by the
|
||||
environment variable `CTEST_PARALLEL_LEVEL`. #1119 (1.11.4)
|
||||
* oslconfig.h is now generated by a cmake configure_file step, from
|
||||
|
||||
+7
-1
@@ -3,7 +3,9 @@
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
cmake_minimum_required (VERSION 3.12)
|
||||
project (OSL VERSION 1.12.4.4
|
||||
|
||||
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
|
||||
@@ -121,6 +123,9 @@ 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)
|
||||
|
||||
# Set the default namespace. For symbol hiding reasons, it's important that
|
||||
# the project name is a subset of the namespace name.
|
||||
@@ -158,6 +163,7 @@ include (pythonutils)
|
||||
include (externalpackages)
|
||||
include (flexbison)
|
||||
include (cuda_macros)
|
||||
include (llvm_macros)
|
||||
|
||||
# Include all our testing apparatus and utils, but not if it's a subproject
|
||||
if (${PROJECT_NAME}_BUILD_TESTS AND PROJECT_IS_TOP_LEVEL)
|
||||
|
||||
+13
-9
@@ -173,9 +173,16 @@ it really only applies to the particular file in which it appears.
|
||||
|
||||
#### Formatting
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
@@ -217,13 +224,10 @@ 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, this is always ok
|
||||
x = foo(a, b); // Yes
|
||||
|
||||
x = foo ( a, b ); // No
|
||||
x = foo (a,b); // No
|
||||
x = foo(a, b); // No
|
||||
x = foo(a); // Occasionally, this just looks better, when the function name is short,
|
||||
// and there's just one very short argument. What can I say, I do it too.
|
||||
|
||||
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
|
||||
@@ -233,7 +237,7 @@ 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)
|
||||
function(int a, int b)
|
||||
{
|
||||
int x = a + b;
|
||||
if (a == 0 || b == 0) {
|
||||
@@ -244,7 +248,7 @@ Here is a short code fragment that shows some of these rules in action:
|
||||
}
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
x += a * i;
|
||||
x *= foo (i); // function call
|
||||
x *= foo(i); // function call
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
+22
-23
@@ -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.22)
|
||||
* Build system: [CMake](https://cmake.org/) 3.12 or newer (tested through 3.24)
|
||||
|
||||
* 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 11.2)
|
||||
- Clang 3.4 or newer (tested through clang 13)
|
||||
- Microsoft Visual Studio **2017 or newer**
|
||||
- Intel C++ compiler icc **version 17 or newer** and LLVM-based icx compiler
|
||||
**version 2022 or newer**.
|
||||
* 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)
|
||||
- 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.2 or newer** (tested through 2.3)
|
||||
* **[OpenImageIO](http://openimageio.org) 2.3 or newer** (tested through 2.4)
|
||||
|
||||
OSL uses OIIO both for its texture mapping functionality as well as
|
||||
numerous utility classes. If you are integrating OSL into an existing
|
||||
@@ -40,10 +40,14 @@ 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, or 13**, including clang
|
||||
libraries.
|
||||
* [LLVM](http://www.llvm.org) 9, 10, 11, 12, 13, 14, or 15, including
|
||||
clang libraries.
|
||||
|
||||
* [Boost](https://www.boost.org) 1.55 or newer (tested through boost 1.78)
|
||||
* (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.
|
||||
|
||||
* [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)
|
||||
* [Flex](https://github.com/westes/flex) 2.5.35 or newer and
|
||||
@@ -57,8 +61,8 @@ NEW or CHANGED dependencies since the last major release are **bold**.
|
||||
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)
|
||||
* pybind11 >= 2.4.2 (Tested through 2.9)
|
||||
* Python >= 2.7 (tested against 2.7, 3.7, 3.8, 3.9, 3.10)
|
||||
* pybind11 >= 2.4.2 (Tested through 2.10)
|
||||
* NumPy
|
||||
* (optional) Qt >= 5.6 (tested through 5.15). If not found at build time,
|
||||
the `osltoy` application will be disabled.
|
||||
@@ -93,19 +97,14 @@ Here are the steps to check out, build, and test the OSL distribution:
|
||||
full errors, not warnings.
|
||||
|
||||
4. After compilation, you'll end up with a full OSL distribution in
|
||||
dist/ARCH, where ARCH is the architecture you are building on, one of
|
||||
"linux", "linux64", "macosx", "windows", or "windows64".
|
||||
dist/
|
||||
|
||||
Note: The default is to make an optimized "release" build. If
|
||||
instead type 'make debug' at the top level, you will end up with
|
||||
a debug build (no optimization, full symbols) in "dist/ARCH.debug".
|
||||
|
||||
5. Add the "dist/ARCH/bin" to your $PATH, and "dist/ARCH/lib" to your
|
||||
$LD_LIBRAY_PATH (or $DYLD_LIBRARY_PATH on OS X), or copy the contents
|
||||
5. Add the "dist/bin" to your $PATH, and "dist/lib" to your
|
||||
$LD_LIBRAY_PATH (or $DYLD_LIBRARY_PATH on MacOS), or copy the contents
|
||||
of those files to appropriate directories. Public include files
|
||||
(those needed when building applications that incorporate OSL)
|
||||
can be found in "dist/ARCH/include", and documentation can be found
|
||||
in "dist/ARCH/share/doc".
|
||||
can be found in "dist/include", and documentation can be found
|
||||
in "dist/share/doc".
|
||||
|
||||
6. After building (and setting your library path), you can run the
|
||||
test suite with:
|
||||
|
||||
@@ -393,6 +393,18 @@ Films using OSL (grouped by year of release date):
|
||||
Matrix Resurrections
|
||||
* **(2022 / upcoming)**
|
||||
Hotel Transylvania 4: Transformania,
|
||||
Death on the Nile,
|
||||
Uncharted,
|
||||
Turning Red,
|
||||
The Adam Project,
|
||||
Doctor Strange in the Multiverse of Madness,
|
||||
Love, Death, and Robots: In Vaulted Halls Entombed,
|
||||
Jurassic World: Dominion,
|
||||
Lightyear,
|
||||
Thor: Love and Thunder,
|
||||
The Sea Beast,
|
||||
DC League of Super Pets,
|
||||
Bullet Train,
|
||||
...
|
||||
|
||||
|
||||
@@ -427,9 +439,13 @@ certain is a legit problem in the code, and for which you can give clear
|
||||
instructions for how to reproduce, should be [reported as
|
||||
issues](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/issues).
|
||||
|
||||
If confidentiality precludes a public question or issue, you may contact the
|
||||
project administrator privately at [lg@imageworks.com](lg@imageworks.com),
|
||||
including for security-related issues.
|
||||
If you think you've found a potential vulnerability in OSL, please
|
||||
confidentially report it by emailing the project administrators at
|
||||
[security@openshadinglanguage.org](security@openshadinglanguage.org).
|
||||
|
||||
If any other issue requires confidentiality that precludes a public question
|
||||
or issue, you may contact the project administrator privately at
|
||||
[lg@larrygritz.com](lg@larrygritz.com).
|
||||
|
||||
|
||||
Contributing
|
||||
@@ -453,7 +469,6 @@ Contacts, Links, and References
|
||||
|
||||
[OSL home page](http://openshadinglanguage.org)
|
||||
|
||||
[Sony Pictures Imageworks main open source page](http://opensource.imageworks.com)
|
||||
|
||||
|
||||
|
||||
@@ -466,19 +481,18 @@ 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, Syoyo Fujita,
|
||||
Tim Grant, Larry Gritz, Nicolas Guiard, Euan Haahr, Derek Haase, Sven-Hendrik
|
||||
Haase, John Haddon, Niklas Harrysson, Daniel Heckenberg, 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, 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.)
|
||||
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,
|
||||
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.)
|
||||
|
||||
We cannot possibly express sufficient gratitude to the managers at Sony
|
||||
Pictures Imageworks who allowed this project to proceed, supported it
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
This gives guidance about which branches are supported with patches to
|
||||
security vulnerabilities.
|
||||
|
||||
| Version / branch | Supported |
|
||||
| --------- | ---------------------------------------------------- |
|
||||
| main | :white_check_mark: :construction: ALL fixes immediately, but this is a branch under development with a frequently unstable ABI and occasionally unstable API. |
|
||||
| 1.12.x | :white_check_mark: All fixes that can be backported without breaking ABI compatibility. New tagged releases monthly. |
|
||||
| 1.11.x | :warning: Only the most critical fixes, only if they can be easily backported. |
|
||||
| <= 1.10.x | :x: No longer receiving patches of any kind. |
|
||||
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you think you've found a potential vulnerability in OSL, please report it
|
||||
by emailing the project administrators at
|
||||
[security@openshadinglanguage.org](security@openshadinglanguage.org). Only the
|
||||
project administrators have access to these messages. Include detailed steps to
|
||||
reproduce the issue, and any other information that could aid an
|
||||
investigation. Our policy is to respond to vulnerability reports within 14
|
||||
days.
|
||||
|
||||
Our policy is to address critical security vulnerabilities rapidly and post
|
||||
patches as quickly as possible.
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
The OSL Documentation Project is a work in progress.
|
||||
|
||||
The plan is to adopt the OCIO Documentation Project's methodology for maintaining and building documention of various kinds as it becomes the blueprint for the ASWF.
|
||||
The plan is to adopt the OCIO Documentation Project's methodology for maintaining and building documentation of various kinds as it becomes the blueprint for the ASWF.
|
||||
|
||||
There is much work to be done here.
|
||||
|
||||
|
||||
@@ -0,0 +1,341 @@
|
||||
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
||||
<!-- Copyright Contributors to the Open Shading Language Project. -->
|
||||
|
||||
# Release Procedures for Open Shading Language
|
||||
|
||||
## Version nomenclature and release cadence
|
||||
|
||||
### The meaning of the version parts
|
||||
|
||||
Our release numbers are of the form `MAJOR.MINOR.PATCH.TWEAK`, and we follow
|
||||
an almost-semantic-versioning scheme.
|
||||
|
||||
MAJOR changes are those that break backward-compatibility of the public APIs,
|
||||
requiring existing application code to change their source code where it calls
|
||||
OSL API functions in order to compile and work correctly.
|
||||
|
||||
MINOR changes guarantee API backward-compatibility with prior releases that
|
||||
have the same major number, but can introduce ABI or link incompatibilities.
|
||||
Applications using OSL need to be recompiled to move to a new minor release,
|
||||
but should not need to change their source code. Minor releases are allowed
|
||||
to drop support for sufficiently old compilers and dependencies.
|
||||
|
||||
PATCH changes guarantee both API and ABI/link backward-compatibility with
|
||||
prior releases that have the same minor number. Features and new public API
|
||||
calls may be added (thus deviating from strict semantic versioning), but only
|
||||
if they preserve ABI/link compatibility. This means that standalone functions
|
||||
or static methods may be added, but existing functions will not change their
|
||||
parameters, and no new virtual methods or struct data layouts change for patch
|
||||
releases (for classes in public header files). Application code can be
|
||||
re-linked to a new patch release without needing to be recompiled. We also
|
||||
guarantee that any compilers or dependencies supported for the first release
|
||||
of a minor series will continue to be supported for all patches to that minor
|
||||
series.
|
||||
|
||||
TWEAK changes are restricted to critical bug fixes or build breaks that do
|
||||
not alter public APIs in any way.
|
||||
|
||||
### Cadence of releases
|
||||
|
||||
Major (arbitrarily incompatible) releases happen rarely, usually with multiple
|
||||
years between them.
|
||||
|
||||
Minor (API backward-compatible) releases are scheduled annually, targeted at
|
||||
late summer (SIGGRAPH time) to be in beta, and early autumn for a full
|
||||
release.
|
||||
|
||||
Patch (API and ABI backward-compatible) releases are scheduled monthly,
|
||||
usually aiming for the first day of each month.
|
||||
|
||||
Tweak (fully forward and backward compatible) releases are not regularly
|
||||
scheduled, and only happen sporadically, when a critical fix is needed in
|
||||
between scheduled patch releases.
|
||||
|
||||
### Things are different in "main"
|
||||
|
||||
The "main" branch is where ongoing development occurs without any
|
||||
compatibility guarantees. We don't always know if the next year's release from
|
||||
main will turn out to be major (API breaking) or minor (only ABI breaking).
|
||||
|
||||
Some studios or products need the most up-to-date enhancements, and thus tend
|
||||
to build OSL from the "main" branch rather than using tagged releases. For
|
||||
these users, we try to set version numbers and occasionally tag in main, to
|
||||
send a signal about which points in main seem safe to rely on various
|
||||
compatibility levels. However, the rules are slightly different than we use
|
||||
for releases.
|
||||
|
||||
In the "main" branch:
|
||||
|
||||
- TWEAK changes within "main" only guarantee ABI back-compatibility, but may
|
||||
have additions or non-bug-fix behavior changes (akin to patch releases
|
||||
within a release branch).
|
||||
- PATCH changes within "main" are allowed to break ABI or API (changes that
|
||||
would require minor or major releases, if they were not in "main").
|
||||
- Beware of unmarked breaks in compatibility of commits in main that are
|
||||
in between developer preview tags.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Branch and tag names
|
||||
|
||||
**Branches** are places where commits containing new development may be added
|
||||
(and thus the branch markers will move over time). Branch names obey the
|
||||
following conventions:
|
||||
|
||||
- `main` is the area for arbitrary changes intended for the next year's major
|
||||
or minor release.
|
||||
- `dev-1.2` are the areas for staging additions to the next month's patch
|
||||
release for the designated minor version series.
|
||||
- `release` is a special branch marker that is always set to the latest tag of
|
||||
the currently supported, stable release family. People can count on
|
||||
"release" always being the latest stable release, whatever that may be at
|
||||
the time.
|
||||
|
||||
**Tags** indicate releases or developer previews, and once a commit is
|
||||
tagged, it is permanent and will never be moved. Tag names obey the following
|
||||
conventions:
|
||||
|
||||
- `v1.2.3.4` is a specific public stable release, corresponding to official
|
||||
major, minor, public, or tweak releases.
|
||||
- `v1.2.3.4-alpha`, `v1.2.3.4-beta`, or `v1.2.3.4-RC1` are pre-releases for an
|
||||
upcoming public stable release, at the alpha, beta, or release candidate
|
||||
stages, respectively.
|
||||
- `v1.2.3.4-dev` is a "developer preview" within "main." It is not an official
|
||||
supported release, and while the numbering may indicate compatibility versus
|
||||
other recent developer previews, they should not be assumed to be compatible
|
||||
with any prior official stable releases.
|
||||
|
||||
*Very* occasionally, other branch or tag names (with custom suffixes or
|
||||
different naming schemes) may be used for special purposes by particular
|
||||
developers or users, but should not be considered reliable or permanent, and
|
||||
in general should be ignored by anyone who didn't make the tag or branch.
|
||||
|
||||
---
|
||||
|
||||
## Release Procedures
|
||||
|
||||
### Soft freeze for monthly tweak releases:
|
||||
|
||||
We freely backport *safe*, non-ABI-breaking changes by cherry-picking them
|
||||
from main to the supported branch continually throughout most of the month.
|
||||
|
||||
In the seven days before the new month, we do a "soft freeze" where only
|
||||
important bug fixes are backported. Hold on to any other patches you wish to
|
||||
backport until after the monthly patch release (i.e., save them for the next
|
||||
month's release so you never have a release that contains changes that are
|
||||
only a few days old, and therefore not as well tested). You may, of course,
|
||||
continue to backport fixes to documentation or other non-code parts of the
|
||||
project during this soft freeze.
|
||||
|
||||
### Branching for annual major/minor releases
|
||||
|
||||
By mid-June (about 1-2 months before the beta of a new annual big release),
|
||||
you should branch and mark it as an alpha.
|
||||
|
||||
At the tip of "main," create a new branch named `dev-MAJOR.MINOR` that will be
|
||||
the staging area for the next release.
|
||||
|
||||
Customarily, at that point we add a commit to main (but not to the new
|
||||
dev-MAJ.MIN branch) that bumps main's version to the next minor level, to
|
||||
avoid any confusion between builds from main versus what will be the next
|
||||
release branch. This starts the divergence between main and the release
|
||||
branch, and henceforth, any big or compatibility-breaking changes will only be
|
||||
committed to main and not backported to the release branch. (Though we are
|
||||
loose about this rule during the alpha period and allow continued breaking
|
||||
changes in the alpha, but by the time we call it beta, we allow no more
|
||||
breaking changes.)
|
||||
|
||||
|
||||
### Prior to a release
|
||||
|
||||
1. Update CI dependencies: Ensure that the "latest" CI test specifies the
|
||||
current releases of the dependencies and compilers (check their home
|
||||
pages), and that the [INSTALL.md](../INSTALL.md) file correctly documents
|
||||
the version ranges that we expect to work and that we actively test.
|
||||
|
||||
2. Release notes: [CHANGES.md](../CHANGES.md) should be updated to reflect
|
||||
all the new features and fixes. Looking at the notes from older releases
|
||||
should provide a good example of what we're aiming for.
|
||||
|
||||
- Patch and tweak releases can be brief one-line descriptions (often the
|
||||
first line of the commit messages involved), presented in a single
|
||||
section in either chronological or any other order that seems right.
|
||||
- Minor or major releases have a much more extensive, prose-based
|
||||
description of all changes since the last minor release, broken into
|
||||
sections (dependency changes, major new features, enhancements and fixes,
|
||||
internals and developer goodies, testing/CI/ports, etc.) and ordered for
|
||||
readability and relevance.
|
||||
|
||||
3. Ensure docs are up to date:
|
||||
|
||||
- Actually read the [README.md](../README.md), [INSTALL.md](../INSTALL.md),
|
||||
and other repository docs and make sure all the information is up to
|
||||
date. Check the "contributor credits" in the README against the recent
|
||||
repo history to be sure new contributors are listed. Also check the
|
||||
list of films and make sure it includes any recent productions that are
|
||||
known to have used OSL.
|
||||
- Skim the primary user documentation to look for any obvious errors,
|
||||
especially the parts that describe new features. In the case of PDF docs
|
||||
(such as osl-languagespec.pdf), make sure that a new PDF book is built if
|
||||
the documentation source has been changed since the last release.
|
||||
- If we are using any online docs (like readthedocs), make sure it is
|
||||
building and looks correct on the web site.
|
||||
|
||||
4. Make sure the the top-level CMakeLists.txt file is updated:
|
||||
|
||||
- The version on the `project()` call should be correct.
|
||||
- The `PROJECT_VERSION_RELEASE_TYPE` variable should be set to "alpha" or
|
||||
"beta" if appropriate, "RC" for release candidate, or empty string `""`
|
||||
for most supported releases, and "dev" only for the main branch or
|
||||
developer previews.
|
||||
- The `${PROJECT_NAME}_SUPPORTED_RELEASE` variable should be `ON` for any
|
||||
release branch, `OFF` for main.
|
||||
|
||||
5. Make sure everything passes the usual CI workflow. Also check the daily or
|
||||
weekly "analysis" workflows to make sure there aren't any important
|
||||
warnings that should be fixed.
|
||||
|
||||
|
||||
### Staging alpha / beta / release candidate (annual minor/major releases only)
|
||||
|
||||
For monthly patch releases, we don't have any formal alpha/beta/RC stages.
|
||||
|
||||
For the annual minor or major releases we have a staged release:
|
||||
|
||||
- `alpha` is everything after we have branched, in which we think all the big
|
||||
new features have been added, and while we will make continued changes and
|
||||
fixes, we are aiming for increased stability and to minimize additional
|
||||
breaking changes prior to the release.
|
||||
- `beta` should be about one month prior to the final release date. We create
|
||||
a tag `v1.2.3.4-beta` and announce the beta (see below "Making the
|
||||
release"). Once we tag a beta, we try very hard not to allow any further
|
||||
changes that change the API or are not ABI-compatible (i.e., safe fixes
|
||||
only).
|
||||
- `RC` or release candidates around one week prior to the final release date.
|
||||
This is a trial run, hopefully identical to the final release (except for
|
||||
removing the RC label and making a new tag). The only changes allowed after
|
||||
RC are fixes to the most critical bugs or build breaks that would be bad for
|
||||
users to encounter. If critical problems are found with RC1, they should be
|
||||
fixed and immediately re-tagged as RC2, etc. All other fixes should be
|
||||
postponed until the next month's patch release.
|
||||
|
||||
### Making the release
|
||||
|
||||
A final release is made on the scheduled date, provided the latest RC has
|
||||
survived for at least a few days of testing without finding any critical
|
||||
problems. Don't make the release final until you are sure there are no
|
||||
truly critical bugs or build breaks that users will encounter.
|
||||
|
||||
The following are the steps for making the release:
|
||||
|
||||
1. Edit the top-level CMakeLists.txt to remove any RC designation
|
||||
(i.e., `PROJECT_VERSION_RELEASE_TYPE` should be set to `""`).
|
||||
|
||||
2. Edit CHANGES.md to reflect the correct date of the release and ensure it
|
||||
includes any last-minute changes that were made during beta or release
|
||||
candidate stages.
|
||||
|
||||
3. Push it to **your** GitHub, make sure it passes CI.
|
||||
|
||||
4. Tag the release: `git tag v1.2.3.4` (no more beta, RC, or dev suffix).
|
||||
|
||||
5. If this will now be the recommended stable release, move the `release`
|
||||
branch marker to the same position.
|
||||
|
||||
6. Push it to GitHub: `git push aswf release --tags`
|
||||
|
||||
(This example assumes "aswf" is the name of the remote for the GitHub
|
||||
`AcademySoftwareFoundation/OpenShadingLanguage` repo.)
|
||||
|
||||
7. Draft a release on GitHub: On
|
||||
https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/releases
|
||||
select "Draft a new release." Choose the new tag you just pushed. Make the
|
||||
release title "Open Shading Language v1.2.3.4" (and beta, etc., designation
|
||||
if applicable). In the description, paste the release notes for this
|
||||
release (from Changes.md). If this is a beta or release candidate, check
|
||||
"this is a pre-release" box at the bottom.
|
||||
|
||||
8. Announce the release on the [osl-dev mail list](https://lists.aswf.io/g/osl-dev)
|
||||
with the subject "Release: OSL v1.2.3.4" and using one of these templates
|
||||
for the body of the email.
|
||||
|
||||
For a monthly patch release:
|
||||
|
||||
> We have tagged v1.2.3.4 as the latest production release and moved the
|
||||
> "release" branch marker to that point. This is guaranteed to be API,
|
||||
> ABI, and link back-compatible with prior 1.2 releases. Release notes
|
||||
> are below.
|
||||
>
|
||||
> (Paste the full set of 1.2 changes here, just copy the appropriate
|
||||
> part of CHANGES.md)
|
||||
|
||||
For an annual major/minor release:
|
||||
|
||||
> OSL version 1.2 has been released! Officially tagged as "v1.2.3.4", we
|
||||
> have also moved the "release" branch tag to this position. Henceforth,
|
||||
> 1.2 is the supported production release family. The API is now frozen --
|
||||
> we promise that subsequent 1.2.x releases (which should happen monthly)
|
||||
> will not break back-compatibility of API, ABI, or linkage, compared to
|
||||
> this release. Please note that this release is *not* ABI or link
|
||||
> compatible with 1.1 or older releases.
|
||||
>
|
||||
> Release notes for 1.2 outlining all the changes since last year's
|
||||
> release are below.
|
||||
>
|
||||
> Please note that a few of the build and runtime dependencies have
|
||||
> changed their minimum supported versions. (List here any important
|
||||
> changes to dependencies, compilers, or C++ standard that users should be
|
||||
> aware of.)
|
||||
>
|
||||
> (List here anything else that people should know about this release
|
||||
> family that may be surprising if they haven't followed the last year of
|
||||
> development closely, or that they must know even if they are too lazy to
|
||||
> read the release notes. If this is a major release that is not
|
||||
> backward-compatible with prior versions, warn about that here.)
|
||||
>
|
||||
> Enjoy, and please report any problems. We will continue to make patch
|
||||
> releases to the 1.2 family roughly monthly, which will contain bug fixes
|
||||
> and non-breaking enhancements.
|
||||
>
|
||||
> The older 1.1 series of releases is now considered obsolete. We will
|
||||
> continue for now to make 1.1 patch releases, but over time, these will
|
||||
> become less frequent and be reserved for only the most critical bug
|
||||
> fixes.
|
||||
>
|
||||
> The "main" branch is now progressing toward an eventual 1.3 release next
|
||||
> summer. As usual, you are welcome to use main for real work, but we do
|
||||
> not make any compatibility guarantees and don't guarantee continuing API
|
||||
> compatibility in main.
|
||||
>
|
||||
> (Paste the full set of 1.2 changes here, just copy the appropriate
|
||||
> part of CHANGES.md)
|
||||
|
||||
For a beta leading up to the annual major/minor release:
|
||||
|
||||
> OSL version 1.2 is now in beta, tagged as "v1.2.3.4-beta". We
|
||||
> will try very hard not to make any further API or ABI changes between
|
||||
> now and the final release (unless it is absolutely necessary to fix
|
||||
> an important problem identified during beta testing). The final 1.2
|
||||
> release is scheduled for [DATE GOES HERE], so please try building and
|
||||
> testing the beta so we are sure to find any problems.
|
||||
>
|
||||
> Release notes for 1.2 outlining all the changes since last year's
|
||||
> release are below.
|
||||
>
|
||||
> (Paste the full set of 1.2 changes here, just copy the appropriate
|
||||
> part of CHANGES.md)
|
||||
|
||||
|
||||
### After the release
|
||||
|
||||
Odds and ends to do after the tag is pushed and the announcements are sent:
|
||||
|
||||
- Re-read RELEASING.md and ensure that the instructions match what you
|
||||
have done. Update as necessary.
|
||||
|
||||
- For annual beta releases, post a short message to the "Open Shading
|
||||
Language" channel of the ASWF slack. It can be a one-line announcement and
|
||||
then just a link to the GitHub release page for this version.
|
||||
|
||||
|
||||
@@ -181,14 +181,14 @@ else ifeq (${platform}, macosx)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=gcc-9 -DCMAKE_CXX_COMPILER=g++-9
|
||||
USE_LIBCPLUSPLUS := 0
|
||||
else ifeq (${COMPILER},clang11)
|
||||
else ifeq (${COMPILER},clang14)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@11/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@11/bin/clang++
|
||||
else ifeq (${COMPILER},clang12)
|
||||
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@14/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@14/bin/clang++
|
||||
else ifeq (${COMPILER},clang15)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@12/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@12/bin/clang++
|
||||
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@15/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@15/bin/clang++
|
||||
else ifeq (${COMPILER},clang)
|
||||
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
||||
else ifeq (${COMPILER},gcc)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright Contributors to the Open Shading Language Project.
|
||||
|
||||
sonar.host.url=https://sonarcloud.io
|
||||
|
||||
# Required metadata
|
||||
sonar.organization=academysoftwarefoundation
|
||||
sonar.projectName=OpenShadingLanguage
|
||||
sonar.projectVersion=1.12
|
||||
sonar.projectKey=AcademySoftwareFoundation_OpenShadingLanguage
|
||||
|
||||
# Project links
|
||||
sonar.links.homepage=https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
sonar.links.ci=https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/actions
|
||||
sonar.links.scm=https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
sonar.links.issue=https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/issues
|
||||
|
||||
# Source properties
|
||||
sonar.sources=src
|
||||
sonar.sourceEncoding=UTF-8
|
||||
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
|
||||
@@ -29,7 +29,10 @@ if [[ `uname` == "Linux" ]] ; then
|
||||
fi
|
||||
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" ]] ; then
|
||||
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" ]] ;
|
||||
then
|
||||
# new
|
||||
curl --location https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/${LLVMTAR} -o $LLVMTAR
|
||||
else
|
||||
|
||||
@@ -12,6 +12,10 @@ if [[ "$USE_SIMD" != "" ]] ; then
|
||||
OSL_CMAKE_FLAGS="$OSL_CMAKE_FLAGS -DUSE_SIMD=$USE_SIMD"
|
||||
fi
|
||||
|
||||
if [[ -n "$CODECOV" ]] ; then
|
||||
OSL_CMAKE_FLAGS="$OSL_CMAKE_FLAGS -DCODECOV=${CODECOV}"
|
||||
fi
|
||||
|
||||
pushd build
|
||||
cmake .. -G "$CMAKE_GENERATOR" \
|
||||
-DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" \
|
||||
@@ -23,7 +27,16 @@ cmake .. -G "$CMAKE_GENERATOR" \
|
||||
-DCMAKE_INSTALL_LIBDIR="$OSL_ROOT/lib" \
|
||||
-DCMAKE_CXX_STANDARD="$CMAKE_CXX_STANDARD" \
|
||||
$OSL_CMAKE_FLAGS -DVERBOSE=1
|
||||
time cmake --build . --target ${BUILDTARGET:=install} --config ${CMAKE_BUILD_TYPE}
|
||||
|
||||
# Save a copy of the generated files for debugging broken CI builds.
|
||||
mkdir cmake-save || /bin/true
|
||||
cp -r CMake* *.cmake cmake-save
|
||||
|
||||
: ${BUILDTARGET:=install}
|
||||
if [[ "$BUILDTARGET" != "none" ]] ; then
|
||||
echo "Parallel build ${CMAKE_BUILD_PARALLEL_LEVEL} of target ${BUILDTARGET}"
|
||||
time ${OSL_CMAKE_BUILD_WRAPPER} cmake --build . --target ${BUILDTARGET} --config ${CMAKE_BUILD_TYPE}
|
||||
fi
|
||||
popd
|
||||
|
||||
if [[ "${DEBUG_CI:=0}" != "0" ]] ; then
|
||||
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Run code coverage analysis
|
||||
# This assumes that the build occurred with CODECOV=1 andtests have already
|
||||
# fully run.
|
||||
|
||||
set -ex
|
||||
|
||||
echo "Performing code coverage analysis"
|
||||
mkdir _coverage
|
||||
pushd _coverage
|
||||
|
||||
ls -R ../build/src/
|
||||
|
||||
# Remove files or directories we want to exclude from code coverage analysis,
|
||||
# generally because we don't expect to execute any of their code during our
|
||||
# CI. (Because it's only used interactively, or is fallback code only used
|
||||
# when certain dependencies are not found.) Including these when we know we
|
||||
# won't be calling them during coverage gathering will just make our coverage
|
||||
# percentage look artifically low.
|
||||
rm -f ../build/src/osltoy/CMakeFiles/osltoy.dir/*.cpp.{gcno,gcda}
|
||||
|
||||
|
||||
# The sed command below converts from:
|
||||
# ../build/src/liboslexec/CMakeFiles/oslexec.dir/foo.gcno
|
||||
# to:
|
||||
# ../src/liboslexec/foo.cpp
|
||||
|
||||
for g in $(find ../build -name "*.gcno" -type f); do
|
||||
echo "Processing $g"
|
||||
echo "dirname $g = $(dirname $g) to " `$(echo "$g" | sed -e 's/\/build\//\//' -e 's/\.gcno/\.cpp/' -e 's/\.cpp\.cpp/\.cpp/' -e 's/\/CMakeFiles.*\.dir\//\//')`
|
||||
gcov -l -p -o $(dirname "$g") $(echo "$g" | sed -e 's/\/build\//\//' -e 's/\.gcno/\.cpp/' -e 's/\/CMakeFiles.*\.dir\//\//')
|
||||
done
|
||||
popd
|
||||
@@ -23,7 +23,7 @@ export DYLD_LIBRARY_PATH=$OSL_ROOT/lib:$DYLD_LIBRARY_PATH
|
||||
export LD_LIBRARY_PATH=$OSL_ROOT/lib:$LD_LIBRARY_PATH
|
||||
export OIIO_LIBRARY_PATH=$OSL_ROOT/lib:${OIIO_LIBRARY_PATH}
|
||||
export LSAN_OPTIONS=suppressions=$PWD/src/build-scripts/nosanitize.txt
|
||||
export ASAN_OPTIONS=print_suppressions=0
|
||||
export ASAN_OPTIONS=print_suppressions=0:detect_odr_violation=1
|
||||
|
||||
export USE_PYTHON=${USE_PYTHON:=1}
|
||||
export PYTHON_VERSION=${PYTHON_VERSION:="2.7"}
|
||||
@@ -61,6 +61,7 @@ echo "uname -a: " `uname -a`
|
||||
echo "uname -m: " `uname -m`
|
||||
echo "uname -s: " `uname -s`
|
||||
echo "uname -n: " `uname -n`
|
||||
echo "nproc " `nproc`
|
||||
pwd
|
||||
ls
|
||||
env | sort
|
||||
|
||||
@@ -8,12 +8,26 @@
|
||||
# any command in it fails. This is crucial for CI tests.
|
||||
set -ex
|
||||
|
||||
: ${CTEST_EXCLUSIONS:="broken"}
|
||||
: ${CTEST_TEST_TIMEOUT:=60}
|
||||
|
||||
$OSL_ROOT/bin/testshade --help
|
||||
|
||||
echo "Parallel test " ${CTEST_PARALLEL_LEVEL}
|
||||
echo "Parallel test ${CTEST_PARALLEL_LEVEL}"
|
||||
echo "Default timeout ${CTEST_TEST_TIMEOUT}"
|
||||
echo "Test exclusions '${CTEST_EXCLUSIONS}'"
|
||||
echo "CTEST_ARGS '${CTEST_ARGS}'"
|
||||
|
||||
pushd build
|
||||
time ctest -C ${CMAKE_BUILD_TYPE} -E broken --force-new-ctest-process \
|
||||
--output-on-failure --timeout ${CTEST_TEST_TIMEOUT:=60} ${CTEST_ARGS}
|
||||
|
||||
ctest -C ${CMAKE_BUILD_TYPE} --force-new-ctest-process --output-on-failure \
|
||||
--timeout ${CTEST_TEST_TIMEOUT} -E "${CTEST_EXCLUSIONS}" ${CTEST_ARGS} \
|
||||
|| \
|
||||
ctest -C ${CMAKE_BUILD_TYPE} --force-new-ctest-process \
|
||||
--rerun-failed --repeat until-pass:5 -R render --output-on-failure \
|
||||
--timeout ${CTEST_TEST_TIMEOUT} -E "${CTEST_EXCLUSIONS}" ${CTEST_ARGS}
|
||||
# The weird construct above allows the render-* tests to run multiple times
|
||||
|
||||
popd
|
||||
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ from __future__ import print_function, absolute_import
|
||||
###
|
||||
### Only one main doc region will be output by the `docdeep` program,
|
||||
### specified with the `-d` command line argument. Any other doc-regions
|
||||
### will not be included in the documention output of that run.
|
||||
### will not be included in the documentation output of that run.
|
||||
###
|
||||
### However, one doc-region may *include* the text of another doc-region
|
||||
### as follows:
|
||||
@@ -114,7 +114,7 @@ from __future__ import print_function, absolute_import
|
||||
### For pre-code comments, the contiguous comment region associated with
|
||||
### a declaration immediately precedes the declaration. Such a comment
|
||||
### set has its first line start with `///>`. For post-code comments,
|
||||
### the documentaiton comments follows the code declaration, and this is
|
||||
### the documentation comments follows the code declaration, and this is
|
||||
### designated by having its first line start with `///<`. I like to
|
||||
### just remember that the `<` or `>` points in the direction of the code
|
||||
### declaration that the comment applies to.
|
||||
|
||||
@@ -42,8 +42,12 @@ if [[ "$ASWF_ORG" != "" ]] ; then
|
||||
|
||||
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" || "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
|
||||
sudo cp src/build-scripts/oneAPI.repo /etc/yum.repos.d
|
||||
sudo yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic
|
||||
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
||||
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.
|
||||
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
|
||||
@@ -64,15 +68,27 @@ else
|
||||
git cmake ninja-build ccache g++ \
|
||||
libboost-dev libboost-thread-dev libboost-filesystem-dev \
|
||||
libilmbase-dev libopenexr-dev \
|
||||
python-dev python-numpy \
|
||||
libtiff-dev libgif-dev libpng-dev \
|
||||
flex bison libbison-dev \
|
||||
libpugixml-dev \
|
||||
libopencolorio-dev \
|
||||
qt5-default
|
||||
libopencolorio-dev
|
||||
|
||||
time sudo apt-get -q install -y \
|
||||
qt5-default || /bin/true
|
||||
|
||||
export CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu:$CMAKE_PREFIX_PATH
|
||||
|
||||
# Nonstandard python versions
|
||||
if [[ "${PYTHON_VERSION}" == "3.9" ]] ; then
|
||||
time sudo apt-get -q install -y python3.9-dev python3-numpy
|
||||
pip3 --version
|
||||
pip3 install numpy
|
||||
elif [[ "$PYTHON_VERSION" == "2.7" ]] ; then
|
||||
time sudo apt-get -q install -y python-dev python-numpy
|
||||
else
|
||||
pip3 install numpy
|
||||
fi
|
||||
|
||||
if [[ "$CXX" == "g++-6" ]] ; then
|
||||
time sudo apt-get install -y g++-6
|
||||
elif [[ "$CXX" == "g++-7" ]] ; then
|
||||
@@ -85,6 +101,8 @@ else
|
||||
time sudo apt-get install -y g++-10
|
||||
elif [[ "$CXX" == "g++-11" ]] ; then
|
||||
time sudo apt-get install -y g++-11
|
||||
elif [[ "$CXX" == "g++-12" ]] ; then
|
||||
time sudo apt-get install -y g++-12
|
||||
fi
|
||||
|
||||
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" || "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
|
||||
@@ -92,22 +110,11 @@ else
|
||||
sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB
|
||||
echo "deb https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list
|
||||
time sudo apt-get update
|
||||
time sudo apt-get install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic
|
||||
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
||||
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" ]] ; then
|
||||
icpc --version
|
||||
fi
|
||||
if [[ "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
|
||||
icpx --version
|
||||
fi
|
||||
fi
|
||||
|
||||
# Nonstandard python versions
|
||||
if [[ "${PYTHON_VERSION}" == "3.8" ]] ; then
|
||||
#time sudo apt-get -q install -y python3.8-dev python3-numpy
|
||||
echo "skip?"
|
||||
elif [[ "${PYTHON_VERSION}" == "3.9" ]] ; then
|
||||
time sudo apt-get -q install -y python3.9-dev python3-numpy
|
||||
time sudo apt-get 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.
|
||||
set +e; source /opt/intel/oneapi/setvars.sh --config oneapi_2022.1.0.cfg; set -e
|
||||
fi
|
||||
|
||||
source src/build-scripts/build_llvm.bash
|
||||
@@ -150,14 +157,26 @@ if [[ "$OPENCOLORIO_VERSION" != "" ]] ; then
|
||||
fi
|
||||
|
||||
if [[ "$OPENIMAGEIO_VERSION" != "" ]] ; then
|
||||
# There are many parts of OIIO we don't need to build
|
||||
# There are many parts of OIIO we don't need to build for OSL's tests
|
||||
export ENABLE_iinfo=0 ENABLE_iv=0 ENABLE_igrep=0
|
||||
export ENABLE_iconvert=0 ENABLE_testtex=0
|
||||
# For speed of compiling OIIO, disable the file formats that we don't
|
||||
# need for OSL's tests
|
||||
export ENABLE_BMP=0 ENABLE_cineon=0 ENABLE_DDS=0 ENABLE_DPX=0 ENABLE_FITS=0
|
||||
export ENABLE_ICO=0 ENABLE_iff=0 ENABLE_jpeg2000=0 ENABLE_PNM=0 ENABLE_PSD=0
|
||||
export ENABLE_RLA=0 ENABLE_SGI=0 ENABLE_SOCKET=0 ENABLE_SOFTIMAGE=0
|
||||
export ENABLE_TARGA=0 ENABLE_WEBP=0
|
||||
export OPENIMAGEIO_CMAKE_FLAGS+=" -DOIIO_BUILD_TESTS=0 -DUSE_OPENGL=0"
|
||||
# We don't need to run OIIO's tests
|
||||
export OPENIMAGEIO_CMAKE_FLAGS+=" -DOIIO_BUILD_TESTING=OFF -DOIIO_BUILD_TESTS=0"
|
||||
# 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
|
||||
# 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)
|
||||
export OPENIMAGEIO_CMAKE_FLAGS+=" -DCMAKE_UNITY_BUILD=ON -DCMAKE_UNITY_BUILD_MODE=BATCH"
|
||||
fi
|
||||
source src/build-scripts/build_openimageio.bash
|
||||
fi
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
# This script, which assumes it is runnign on a Mac OSX with Homebrew
|
||||
# This script, which assumes it is running on a Mac OSX with Homebrew
|
||||
# installed, does a "brew install" in all packages reasonably needed by
|
||||
# OSL and its dependencies.
|
||||
|
||||
@@ -20,16 +20,20 @@ if [[ `which brew` == "" ]] ; then
|
||||
fi
|
||||
|
||||
|
||||
#brew update >/dev/null
|
||||
if [[ "$DO_BREW_UPDATE" != "" ]] ; then
|
||||
brew update >/dev/null
|
||||
fi
|
||||
echo ""
|
||||
echo "Before my brew installs:"
|
||||
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.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
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
leak:Imf_2_2
|
||||
leak:Imf_2_3
|
||||
leak:Imf_2_4
|
||||
leak:libIlmImf
|
||||
leak:oslgram.y
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
default=exclude
|
||||
compiler=2022.1.0
|
||||
tbb=2021.6.0
|
||||
Regular → Executable
+1
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
@@ -8,7 +8,7 @@ include(CMakeFindDependencyMacro)
|
||||
|
||||
# add here all the find_dependency() whenever switching to config based dependencies
|
||||
if (@OpenEXR_VERSION@ VERSION_GREATER_EQUAL 3.0)
|
||||
find_dependency(Imath @OpenEXR_VERSION@)
|
||||
find_dependency(Imath @Imath_VERSION@)
|
||||
elseif (@OpenEXR_VERSION@ VERSION_GREATER_EQUAL 2.4 AND @FOUND_OPENEXR_WITH_CONFIG@)
|
||||
find_dependency(IlmBase @OpenEXR_VERSION@)
|
||||
find_dependency(OpenEXR @OpenEXR_VERSION@)
|
||||
@@ -22,7 +22,7 @@ find_dependency(OpenImageIO @OpenImageIO_VERSION@ REQUIRED)
|
||||
# Compute the installation prefix relative to this file
|
||||
get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE)
|
||||
|
||||
# There's no guarantee that CMAKE_INSTALL_XXXDIR is a relative path so we extract the final component to handle asbolute paths
|
||||
# There's no guarantee that CMAKE_INSTALL_XXXDIR is a relative path so we extract the final component to handle absolute paths
|
||||
get_filename_component(_INCLUDE_DIR_NAME "@CMAKE_INSTALL_INCLUDEDIR@" NAME)
|
||||
get_filename_component(_LIB_DIR_NAME "@CMAKE_INSTALL_LIBDIR@" NAME)
|
||||
|
||||
|
||||
@@ -3,10 +3,27 @@
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
|
||||
set (REQUIED_DEPS "" CACHE STRING
|
||||
set (REQUIRED_DEPS "" CACHE STRING
|
||||
"Additional dependencies to consider required (semicolon-separated list, or ALL)")
|
||||
set (OPTIONAL_DEPS "" CACHE STRING
|
||||
"Additional dependencies to consider optional (semicolon-separated list, or ALL)")
|
||||
option (ALWAYS_PREFER_CONFIG "Prefer a dependency's exported config file if it's available" OFF)
|
||||
|
||||
|
||||
# Utility function to list the names and values of all variables matching
|
||||
# the pattern (case-insensitive)
|
||||
function (dump_matching_variables pattern)
|
||||
string (TOLOWER ${pattern} _pattern_lower)
|
||||
get_cmake_property(_allvars VARIABLES)
|
||||
list (SORT _allvars)
|
||||
foreach (_var IN LISTS _allvars)
|
||||
string (TOLOWER ${_var} _var_lower)
|
||||
if (_var_lower MATCHES ${_pattern_lower})
|
||||
message (STATUS " ${_var} = ${${_var}}")
|
||||
endif ()
|
||||
endforeach ()
|
||||
endfunction ()
|
||||
|
||||
|
||||
|
||||
# checked_find_package(Pkgname ...) is a wrapper for find_package, with the
|
||||
@@ -20,8 +37,11 @@ set (OPTIONAL_DEPS "" CACHE STRING
|
||||
# turned off explicitly from one of these sources.
|
||||
# * Print a message if the package is enabled but not found. This is based
|
||||
# on ${Pkgname}_FOUND or $PKGNAME_FOUND.
|
||||
# * Optional DEFINITIONS <string> are passed to add_definitions if the
|
||||
# * Optional DEFINITIONS <string>... are passed to add_definitions if the
|
||||
# package is found.
|
||||
# * Optional SETVARIABLES <id>... is a list of CMake variables to set to
|
||||
# TRUE if the package is found (they will not be set or changed if the
|
||||
# package is not found).
|
||||
# * Optional PRINT <list> is a list of variables that will be printed
|
||||
# if the package is found, if VERBOSE is on.
|
||||
# * Optional DEPS <list> is a list of hard dependencies; for each one, if
|
||||
@@ -42,6 +62,10 @@ set (OPTIONAL_DEPS "" CACHE STRING
|
||||
# version, accepting but warning if it is below this number (even
|
||||
# if above the true minimum version accepted). The warning message
|
||||
# can give an optional explanation, passed as RECOMMEND_MIN_REASON.
|
||||
# * Optional PREFER_CONFIG, if supplied, tries to use an exported config
|
||||
# file from the package before using a FindPackage.cmake module.
|
||||
# * Optional DEBUG turns on extra debugging information related to how
|
||||
# this package is found.
|
||||
#
|
||||
# N.B. This needs to be a macro, not a function, because the find modules
|
||||
# will set(blah val PARENT_SCOPE) and we need that to be the global scope,
|
||||
@@ -49,16 +73,20 @@ set (OPTIONAL_DEPS "" CACHE STRING
|
||||
macro (checked_find_package pkgname)
|
||||
cmake_parse_arguments(_pkg # prefix
|
||||
# noValueKeywords:
|
||||
"REQUIRED"
|
||||
"REQUIRED;PREFER_CONFIG;DEBUG"
|
||||
# singleValueKeywords:
|
||||
"ENABLE;ISDEPOF;VERSION_MIN;VERSION_MAX;RECOMMEND_MIN;RECOMMEND_MIN_REASON"
|
||||
# multiValueKeywords:
|
||||
"DEFINITIONS;PRINT;DEPS"
|
||||
"DEFINITIONS;PRINT;DEPS;SETVARIABLES"
|
||||
# argsToParse:
|
||||
${ARGN})
|
||||
string (TOLOWER ${pkgname} pkgname_lower)
|
||||
string (TOUPPER ${pkgname} pkgname_upper)
|
||||
if (NOT VERBOSE)
|
||||
set (_pkg_VERBOSE ${VERBOSE})
|
||||
if (_pkg_DEBUG)
|
||||
set (_pkg_VERBOSE ON)
|
||||
endif ()
|
||||
if (NOT _pkg_VERBOSE)
|
||||
set (${pkgname}_FIND_QUIETLY true)
|
||||
set (${pkgname_upper}_FIND_QUIETLY true)
|
||||
endif ()
|
||||
@@ -85,8 +113,19 @@ macro (checked_find_package pkgname)
|
||||
set (_quietskip true)
|
||||
endif ()
|
||||
endif ()
|
||||
set (_config_status "")
|
||||
if (_enable OR _pkg_REQUIRED)
|
||||
find_package (${pkgname} ${_pkg_UNPARSED_ARGUMENTS})
|
||||
if (${pkgname}_FOUND OR ${pkgname_upper}_FOUND)
|
||||
# was already found
|
||||
elseif (_pkg_PREFER_CONFIG OR ALWAYS_PREFER_CONFIG)
|
||||
find_package (${pkgname} CONFIG ${_pkg_UNPARSED_ARGUMENTS})
|
||||
if (${pkgname}_FOUND OR ${pkgname_upper}_FOUND)
|
||||
set (_config_status "from CONFIG")
|
||||
endif ()
|
||||
endif ()
|
||||
if (NOT (${pkgname}_FOUND OR ${pkgname_upper}_FOUND))
|
||||
find_package (${pkgname} ${_pkg_UNPARSED_ARGUMENTS})
|
||||
endif()
|
||||
if ((${pkgname}_FOUND OR ${pkgname_upper}_FOUND)
|
||||
AND ${pkgname}_VERSION
|
||||
AND (_pkg_VERSION_MIN OR _pkg_VERSION_MAX))
|
||||
@@ -106,21 +145,11 @@ macro (checked_find_package pkgname)
|
||||
set (${pkgname}_VERSION ${${_vervar}})
|
||||
endif ()
|
||||
endforeach ()
|
||||
message (STATUS "${ColorGreen}Found ${pkgname} ${${pkgname}_VERSION} ${ColorReset}")
|
||||
if (VERBOSE)
|
||||
set (_vars_to_print ${pkgname}_INCLUDES ${pkgname_upper}_INCLUDES
|
||||
${pkgname}_INCLUDE_DIR ${pkgname_upper}_INCLUDE_DIR
|
||||
${pkgname}_INCLUDE_DIRS ${pkgname_upper}_INCLUDE_DIRS
|
||||
${pkgname}_LIBRARIES ${pkgname_upper}_LIBRARIES
|
||||
${_pkg_PRINT})
|
||||
list (REMOVE_DUPLICATES _vars_to_print)
|
||||
foreach (_v IN LISTS _vars_to_print)
|
||||
if (NOT "${${_v}}" STREQUAL "")
|
||||
message (STATUS " ${_v} = ${${_v}}")
|
||||
endif ()
|
||||
endforeach ()
|
||||
endif ()
|
||||
message (STATUS "${ColorGreen}Found ${pkgname} ${${pkgname}_VERSION} ${_config_status}${ColorReset}")
|
||||
add_definitions (${_pkg_DEFINITIONS})
|
||||
foreach (_v IN LISTS _pkg_SETVARIABLES)
|
||||
set (${_v} TRUE)
|
||||
endforeach ()
|
||||
if (_pkg_RECOMMEND_MIN)
|
||||
if (${${pkgname}_VERSION} VERSION_LESS ${_pkg_RECOMMEND_MIN})
|
||||
message (STATUS "${ColorYellow}Recommend ${pkgname} >= ${_pkg_RECOMMEND_MIN} ${_pkg_RECOMMEND_MIN_REASON} ${ColorReset}")
|
||||
@@ -148,6 +177,22 @@ macro (checked_find_package pkgname)
|
||||
message (FATAL_ERROR "${ColorRed}${pkgname} is required, aborting.${ColorReset}")
|
||||
endif ()
|
||||
endif()
|
||||
if (_pkg_VERBOSE AND (${pkgname}_FOUND OR ${pkgname_upper}_FOUND OR _pkg_DEBUG))
|
||||
if (_pkg_DEBUG)
|
||||
dump_matching_variables (${pkgname})
|
||||
endif ()
|
||||
set (_vars_to_print ${pkgname}_INCLUDES ${pkgname_upper}_INCLUDES
|
||||
${pkgname}_INCLUDE_DIR ${pkgname_upper}_INCLUDE_DIR
|
||||
${pkgname}_INCLUDE_DIRS ${pkgname_upper}_INCLUDE_DIRS
|
||||
${pkgname}_LIBRARIES ${pkgname_upper}_LIBRARIES
|
||||
${_pkg_PRINT})
|
||||
list (REMOVE_DUPLICATES _vars_to_print)
|
||||
foreach (_v IN LISTS _vars_to_print)
|
||||
if (NOT "${${_v}}" STREQUAL "")
|
||||
message (STATUS " ${_v} = ${${_v}}")
|
||||
endif ()
|
||||
endforeach ()
|
||||
endif ()
|
||||
else ()
|
||||
if (NOT _quietskip)
|
||||
message (STATUS "${ColorRed}Not using ${pkgname} -- disabled ${_disablereason} ${ColorReset}")
|
||||
|
||||
+21
-48
@@ -68,9 +68,9 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER MATCHES "[Cc]lan
|
||||
endif ()
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "IntelLLVM")
|
||||
set (CMAKE_COMPILER_IS_INTELCLANG 1)
|
||||
string (REGEX REPLACE ".* version ([0-9]+\\.[0-9]+).*" "\\1" CLANG_VERSION_STRING ${clang_full_version_string})
|
||||
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 ${CLANG_VERSION_STRING}")
|
||||
message (STATUS "The compiler is Intel Clang: ${CMAKE_CXX_COMPILER_ID} version ${INTELCLANG_VERSION_STRING}")
|
||||
endif ()
|
||||
else ()
|
||||
string (REGEX REPLACE ".* version ([0-9]+\\.[0-9]+).*" "\\1" CLANG_VERSION_STRING ${clang_full_version_string})
|
||||
@@ -162,6 +162,13 @@ if (CMAKE_COMPILER_IS_CLANG OR CMAKE_COMPILER_IS_APPLECLANG)
|
||||
# Don't warn about using unknown preprocessor symbols in `#if`
|
||||
add_compile_options ("-Wno-expansion-to-defined")
|
||||
endif ()
|
||||
# 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 INTELCLANG_VERSION_STRING VERSION_GREATER_EQUAL 14.0)
|
||||
add_compile_options ("-Wno-bitwise-instead-of-logical")
|
||||
endif ()
|
||||
|
||||
# disable warning in flex-generated code
|
||||
add_compile_options ("-Wno-null-conversion")
|
||||
add_compile_options ("-Wno-error=strict-overflow")
|
||||
@@ -189,6 +196,11 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
|
||||
add_compile_options ("-fno-math-errno")
|
||||
endif ()
|
||||
|
||||
if (INTELCLANG_VERSION_STRING VERSION_GREATER_EQUAL 2022.1.0)
|
||||
# New versions of icx warn about changing certain floating point options
|
||||
add_compile_options ("-Wno-overriding-t-option")
|
||||
endif ()
|
||||
|
||||
if (MSVC)
|
||||
# Microsoft specific options
|
||||
string (REGEX REPLACE "/W[1-4]" "/W1" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
@@ -214,7 +226,7 @@ endif ()
|
||||
|
||||
|
||||
|
||||
# We wil use this for ccache and timing
|
||||
# We will use this for ccache and timing
|
||||
set (MY_RULE_LAUNCH "")
|
||||
|
||||
|
||||
@@ -364,11 +376,9 @@ include (CheckCXXSourceRuns)
|
||||
option (CODECOV "Build code coverage tests" OFF)
|
||||
if (CODECOV AND (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG))
|
||||
message (STATUS "Compiling for code coverage analysis")
|
||||
add_compile_options ("-ftest-coverage -fprofile-arcs -O0")
|
||||
add_compile_options (-ftest-coverage -fprofile-arcs)
|
||||
add_definitions ("-D${PROJ_NAME}_CODE_COVERAGE=1")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ftest-coverage -fprofile-arcs")
|
||||
set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -ftest-coverage -fprofile-arcs")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -ftest-coverage -fprofile-arcs")
|
||||
link_libraries(gcov)
|
||||
endif ()
|
||||
|
||||
|
||||
@@ -382,22 +392,9 @@ if (SANITIZE AND (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG))
|
||||
foreach (feature ${SANITIZE_FEATURE_LIST})
|
||||
message (STATUS " sanitize feature: ${feature}")
|
||||
add_compile_options (-fsanitize=${feature})
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=${feature}")
|
||||
set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fsanitize=${feature}")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=${feature}")
|
||||
add_link_options (-fsanitize=${feature})
|
||||
endforeach()
|
||||
add_compile_options (-g -fno-omit-frame-pointer)
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
set (SANITIZE_ON_LINUX 1)
|
||||
endif ()
|
||||
if (CMAKE_COMPILER_IS_GNUCC AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
add_compile_options ("-fuse-ld=gold")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
|
||||
set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fuse-ld=gold")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=gold")
|
||||
set (SANITIZE_LIBRARIES "asan;pthread")
|
||||
# set (SANITIZE_LIBRARIES "asan" "ubsan")
|
||||
endif()
|
||||
if (CMAKE_COMPILER_IS_GNUCC)
|
||||
# turn on glibcxx extra annotations to find vector writes past end
|
||||
add_definitions ("-D_GLIBCXX_SANITIZE_VECTOR=1")
|
||||
@@ -463,41 +460,17 @@ endif ()
|
||||
# is being built as a subproject.
|
||||
if (PROJECT_IS_TOP_LEVEL)
|
||||
set (CLANG_FORMAT_EXE_HINT "" CACHE PATH "clang-format executable's directory (will search if not specified")
|
||||
set (CLANG_FORMAT_INCLUDES # "src/*.h" "src/*.cpp"
|
||||
"src/include/*.h"
|
||||
"src/liboslcomp/*.cpp"
|
||||
"src/liboslcomp/*.h"
|
||||
"src/liboslexec/batched_rendservices.cpp"
|
||||
"src/liboslquery/*.cpp"
|
||||
"src/liboslquery/*.h"
|
||||
"src/oslinfo/*.cpp"
|
||||
"src/oslc/*.cpp"
|
||||
"src/osl.imageio/*.cpp"
|
||||
"src/osltoy/*.cpp"
|
||||
"src/osltoy/*.h"
|
||||
"testsuite/*.cpp"
|
||||
set (CLANG_FORMAT_INCLUDES "src/*.cpp" "src/*.h" "src/*.cu"
|
||||
CACHE STRING "Glob patterns to include for clang-format")
|
||||
set (CLANG_FORMAT_EXCLUDES
|
||||
# Files "imported and modified" that we don't want to reformat, so
|
||||
# they continue to match their upstream versions.
|
||||
"src/include/OSL/Imathx/*"
|
||||
"src/include/OSL/matrix22.h"
|
||||
# Files that are currently being modified with the SIMD batch
|
||||
# shading -- we'll reformat those only after that project work is
|
||||
# completed, to avoid nasty merge conflicts.
|
||||
"src/include/OSL/rendererservices.h"
|
||||
"src/include/OSL/*llvm*"
|
||||
"src/liboslexec/*llvm*"
|
||||
"src/liboslexec/oslexec_pvt.h"
|
||||
# Files that are currently being modified with the OptiX work --
|
||||
# we'll reformat those only after that project work is completed, to
|
||||
# avoid nasty merge conflicts.
|
||||
"src/include/OSL/device_string.h"
|
||||
"src/include/OSL/oslexec.h"
|
||||
"src/testrender/cuda/*"
|
||||
# Header files in testsuite are almost certainly osl headers, not C++
|
||||
"testsuite/*.h"
|
||||
""
|
||||
# Header files in shaders are OSL, not C++
|
||||
"src/shaders/*.h"
|
||||
CACHE STRING "Glob patterns to exclude for clang-format")
|
||||
find_program (CLANG_FORMAT_EXE
|
||||
NAMES clang-format bin/clang-format
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
set ($OSL_EXTRA_NVCC_ARGS "" CACHE STRING "Custom args passed to nvcc when compiling CUDA code")
|
||||
|
||||
# Compile a CUDA file to PTX using NVCC
|
||||
function ( NVCC_COMPILE cuda_src ptx_generated extra_nvcc_args )
|
||||
function ( NVCC_COMPILE cuda_src extra_headers ptx_generated extra_nvcc_args )
|
||||
get_filename_component ( cuda_src_we ${cuda_src} NAME_WE )
|
||||
get_filename_component ( cuda_src_dir ${cuda_src} DIRECTORY )
|
||||
set (cuda_ptx "${CMAKE_CURRENT_BINARY_DIR}/${cuda_src_we}.ptx" )
|
||||
set (${ptxlist} ${${ptxlist}} ${cuda_ptx} )
|
||||
set (${ptx_generated} ${cuda_ptx} PARENT_SCOPE)
|
||||
file ( GLOB cuda_headers "${cuda_src_dir}/*.h" )
|
||||
list (APPEND cuda_headers ${extra_headers})
|
||||
|
||||
list (TRANSFORM IMATH_INCLUDES PREPEND -I
|
||||
OUTPUT_VARIABLE ALL_IMATH_INCLUDES)
|
||||
@@ -79,6 +80,20 @@ function ( MAKE_CUDA_BITCODE src suffix generated_bc extra_clang_args )
|
||||
message (STATUS "Using LLVM_BC_GENERATOR ${LLVM_BC_GENERATOR} to generate bitcode.")
|
||||
endif()
|
||||
|
||||
if (NOT LLVM_AS_TOOL)
|
||||
find_program (LLVM_AS_TOOL NAMES "llvm-as"
|
||||
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_LINK_TOOL)
|
||||
find_program (LLVM_LINK_TOOL NAMES "llvm-link"
|
||||
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")
|
||||
@@ -114,7 +129,7 @@ function ( MAKE_CUDA_BITCODE src suffix generated_bc extra_clang_args )
|
||||
-Wno-deprecated-register -Wno-format-security
|
||||
-O3 -fno-math-errno -ffast-math -S -emit-llvm ${extra_clang_args}
|
||||
${src} -o ${asm_cuda}
|
||||
COMMAND "${LLVM_DIRECTORY}/bin/llvm-as" -f -o ${bc_cuda} ${asm_cuda}
|
||||
COMMAND ${LLVM_AS_TOOL} -f -o ${bc_cuda} ${asm_cuda}
|
||||
DEPENDS ${exec_headers} ${PROJECT_PUBLIC_HEADERS} ${src}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
endfunction ()
|
||||
@@ -129,8 +144,8 @@ function ( LLVM_COMPILE_CUDA llvm_src headers prefix llvm_bc_cpp_generated extra
|
||||
MAKE_CUDA_BITCODE (${llvm_src} "" llvm_bc "${extra_clang_args}")
|
||||
|
||||
add_custom_command (OUTPUT ${llvm_bc_cpp}
|
||||
COMMAND python "${CMAKE_SOURCE_DIR}/src/liboslexec/serialize-bc.py" ${llvm_bc} ${llvm_bc_cpp} ${prefix}
|
||||
COMMAND ${Python_EXECUTABLE} "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py" ${llvm_bc} ${llvm_bc_cpp} ${prefix}
|
||||
MAIN_DEPENDENCY ${llvm_src}
|
||||
DEPENDS "${CMAKE_SOURCE_DIR}/src/liboslexec/serialize-bc.py" ${llvm_src} ${headers} ${llvm_bc}
|
||||
DEPENDS "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py" ${llvm_src} ${headers} ${llvm_bc}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
endfunction ()
|
||||
|
||||
@@ -88,7 +88,7 @@ checked_find_package (OpenEXR REQUIRED
|
||||
)
|
||||
# Force Imath includes to be before everything else to ensure that we have
|
||||
# the right Imath/OpenEXR version, not some older version in the system
|
||||
# library. This shoudn't be necessary, except for the common case of people
|
||||
# library. This shouldn't be necessary, except for the common case of people
|
||||
# building against Imath/OpenEXR 3.x when there is still a system-level
|
||||
# install version of 2.x.
|
||||
include_directories(BEFORE ${IMATH_INCLUDES})
|
||||
@@ -105,7 +105,7 @@ endif ()
|
||||
|
||||
# OpenImageIO
|
||||
checked_find_package (OpenImageIO REQUIRED
|
||||
VERSION_MIN 2.2.6
|
||||
VERSION_MIN 2.3.17
|
||||
DEFINITIONS -DOIIO_HIDE_FORMAT=1)
|
||||
|
||||
checked_find_package (pugixml REQUIRED
|
||||
@@ -136,6 +136,14 @@ if (APPLE AND LLVM_VERSION VERSION_EQUAL 10.0.1 AND EXISTS "/usr/local/Cellar/ll
|
||||
" brew upgrade llvm \n"
|
||||
"${ColorReset}\n")
|
||||
endif ()
|
||||
if (LLVM_VERSION VERSION_GREATER_EQUAL 15.0
|
||||
AND ( (CMAKE_COMPILER_IS_APPLECLANG AND APPLECLANG_VERSION_STRING VERSION_LESS 15.0)
|
||||
OR (CMAKE_COMPILER_IS_CLANG AND CLANG_VERSION_STRING VERSION_LESS 15.0)))
|
||||
message (WARNING
|
||||
"${ColorYellow}"
|
||||
"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 ()
|
||||
|
||||
checked_find_package (partio)
|
||||
|
||||
@@ -198,7 +206,7 @@ if (USE_CUDA OR USE_OPTIX)
|
||||
# OptiX setup
|
||||
if (USE_OPTIX)
|
||||
checked_find_package (OptiX REQUIRED
|
||||
VERSION_MIN 5.1)
|
||||
VERSION_MIN 7.0)
|
||||
include_directories (BEFORE "${OPTIX_INCLUDES}")
|
||||
if (NOT USE_LLVM_BITCODE OR NOT USE_FAST_MATH)
|
||||
message (FATAL_ERROR "Enabling OptiX requires USE_LLVM_BITCODE=1 and USE_FAST_MATH=1")
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
# The executable may be disabled individually using any of the usual
|
||||
# check_is_enabled() conventions (e.g. -DENABLE_<executable>=OFF).
|
||||
#
|
||||
# If -DENABLE_INSTALL_<executable>=OFF was specified, the target will be built
|
||||
# (in the build area) but will not be installed.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# fancy_add_executable ([ NAME targetname ... ]
|
||||
@@ -42,13 +45,16 @@ macro (fancy_add_executable)
|
||||
target_include_directories (${_target_NAME} SYSTEM PRIVATE ${_target_SYSTEM_INCLUDE_DIRS})
|
||||
endif ()
|
||||
if (_target_DEFINITIONS)
|
||||
target_compile_definitions (${_target_name} PRIVATE ${_target_DEFINITIONS})
|
||||
target_compile_definitions (${_target_NAME} PRIVATE ${_target_DEFINITIONS})
|
||||
endif ()
|
||||
if (_target_LINK_LIBRARIES)
|
||||
target_link_libraries (${_target_NAME} PRIVATE ${_target_LINK_LIBRARIES})
|
||||
endif ()
|
||||
set_target_properties (${_target_NAME} PROPERTIES FOLDER "Tools")
|
||||
install_targets (${_target_NAME})
|
||||
check_is_enabled (INSTALL_${_target_NAME} _target_NAME_INSTALL_enabled)
|
||||
if (_target_NAME_INSTALL_enabled)
|
||||
install_targets (${_target_NAME})
|
||||
endif ()
|
||||
else ()
|
||||
message (STATUS "${ColorRed}Disabling ${_target_NAME} ${ColorReset}")
|
||||
endif ()
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
|
||||
function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_cpp extra_clang_args)
|
||||
|
||||
if (VERBOSE)
|
||||
message (STATUS "EMBED_LLVM_BITCODE_IN_CPP src_list=${src_list}")
|
||||
endif ()
|
||||
|
||||
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 ()
|
||||
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 ()
|
||||
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} ${TOOLCHAIN_FLAGS})
|
||||
# Avoid generating __dso_handle external global
|
||||
set (LLVM_COMPILE_FLAGS ${LLVM_COMPILE_FLAGS} "-fno-use-cxa-atexit")
|
||||
|
||||
# Figure out what program we will use to make the bitcode.
|
||||
if (NOT LLVM_BC_GENERATOR)
|
||||
find_program (LLVM_BC_GENERATOR NAMES "clang++"
|
||||
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_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()
|
||||
|
||||
if (NOT LLVM_AS_TOOL)
|
||||
find_program (LLVM_AS_TOOL NAMES "llvm-as"
|
||||
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_LINK_TOOL)
|
||||
find_program (LLVM_LINK_TOOL NAMES "llvm-link"
|
||||
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 ()
|
||||
|
||||
|
||||
# Fix specific problem I had on new Apple systems (e.g. Mavericks) with
|
||||
# LLVM/libc++ installed -- for some reason, LLVM 3.4 wasn't finding it,
|
||||
# so in that specific case, append another -I to point it in the right
|
||||
# direction.
|
||||
#if (APPLE AND ${LLVM_BC_GENERATOR} MATCHES ".*clang.*")
|
||||
# exec_program ( "${LLVM_BC_GENERATOR}" ARGS --version OUTPUT_VARIABLE MY_CLANG_VERSION )
|
||||
# string (REGEX REPLACE "clang version ([0-9][.][0-9]+).*" "\\1" MY_CLANG_VERSION "${MY_CLANG_VERSION}")
|
||||
# if ((${MY_CLANG_VERSION} VERSION_GREATER "3.3")
|
||||
# AND (EXISTS "/usr/lib/libc++.dylib")
|
||||
# AND (EXISTS "/Library/Developer/CommandLineTools/usr/lib/c++/v1"))
|
||||
# set (LLVM_COMPILE_FLAGS ${LLVM_COMPILE_FLAGS} "-I/Library/Developer/CommandLineTools/usr/lib/c++/v1")
|
||||
# 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)
|
||||
|
||||
if (${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 ()
|
||||
|
||||
# Command to turn the .cpp file into LLVM assembly language .s, into
|
||||
# LLVM bitcode .bc, then back into a C++ file with the bc embedded!
|
||||
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}"
|
||||
-DOSL_COMPILING_TO_BITCODE=1
|
||||
-Wno-deprecated-register
|
||||
# the following 2 warnings can be restored when all 3rd parties have fixed their export macros
|
||||
# (dllimport attribute is not supported when compiling for Cuda and triggers a ton of warnings)
|
||||
-Wno-ignored-attributes -Wno-unknown-attributes
|
||||
-O3 -fno-math-errno -S -emit-llvm ${extra_clang_args}
|
||||
-o ${src_asm} ${src}
|
||||
COMMAND ${LLVM_AS_TOOL} -f -o ${src_bc} ${src_asm}
|
||||
# Do NOT setup a MAIN_DEPENDENCY because only 1 may exist
|
||||
# and we may have the several outputs dependent on the same source
|
||||
DEPENDS ${src} ${exec_headers} ${PROJECT_PUBLIC_HEADERS}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
endforeach ()
|
||||
|
||||
|
||||
if (VERBOSE)
|
||||
message ( STATUS "^^^^^^^^^^^^^^^^^^^^^^^^^^" )
|
||||
message ( STATUS "src_bc_list: ${src_bc_list} ")
|
||||
message ( STATUS "^^^^^^^^^^^^^^^^^^^^^^^^^^" )
|
||||
endif()
|
||||
|
||||
# Link all of the individual LLVM bitcode files
|
||||
set ( linked_src_bc "${CMAKE_CURRENT_BINARY_DIR}/${output_name}.bc" )
|
||||
add_custom_command ( OUTPUT ${linked_src_bc}
|
||||
COMMAND ${LLVM_LINK_TOOL} -internalize ${src_bc_list} -o ${linked_src_bc}
|
||||
DEPENDS ${src_bc_list} ${exec_headers} ${PROJECT_PUBLIC_HEADERS} ${src_list}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" )
|
||||
|
||||
# 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"
|
||||
${linked_src_bc} ${src_bc_cpp} ${output_name}
|
||||
DEPENDS "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py" ${linked_src_bc}
|
||||
${exec_headers} ${PROJECT_PUBLIC_HEADERS}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
|
||||
# add generated .cpp with embedded bitcode to the list of sources
|
||||
set ( ${list_to_append_cpp} ${${list_to_append_cpp}} ${src_bc_cpp} PARENT_SCOPE )
|
||||
|
||||
endfunction ( )
|
||||
@@ -10,7 +10,7 @@
|
||||
# PARTIO_LIBRARIES - library to link against
|
||||
# PARTIO_FOUND - true if Partio was found.
|
||||
|
||||
# Hack! perfer a config if it can be found
|
||||
# Hack! prefer a config if it can be found
|
||||
find_package(partio CONFIG)
|
||||
if (PARTIO_FOUND OR partio_FOUND)
|
||||
if (VERBOSE)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright Contributors to the Open Shading Languge project.
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ macro (setup_python_module)
|
||||
PRIVATE
|
||||
pybind11::pybind11
|
||||
Python::Python
|
||||
${lib_LIBS} ${SANITIZE_LIBRARIES})
|
||||
${lib_LIBS})
|
||||
if (APPLE)
|
||||
set_target_properties (${target_name} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
|
||||
endif ()
|
||||
|
||||
+76
-24
@@ -1,4 +1,4 @@
|
||||
# Copyright Contributors to the Open Shading Languge project.
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/
|
||||
|
||||
@@ -16,6 +16,10 @@ add_custom_command (OUTPUT "${CMAKE_BINARY_DIR}/testsuite/runtest.py"
|
||||
MAIN_DEPENDENCY "${CMAKE_SOURCE_DIR}/testsuite/runtest.py")
|
||||
add_custom_target ( CopyFiles ALL DEPENDS "${CMAKE_BINARY_DIR}/testsuite/runtest.py" )
|
||||
|
||||
|
||||
set (OSL_TEST_BIG_TIMEOUT 800 CACHE STRING "Timeout for tests that take a long time")
|
||||
|
||||
|
||||
# add_one_testsuite() - set up one testsuite entry
|
||||
#
|
||||
# Usage:
|
||||
@@ -26,10 +30,12 @@ add_custom_target ( CopyFiles ALL DEPENDS "${CMAKE_BINARY_DIR}/testsuite/runtest
|
||||
# [COMMAND cmd...] - optional override of launch command
|
||||
# )
|
||||
#
|
||||
|
||||
macro (add_one_testsuite testname testsrcdir)
|
||||
cmake_parse_arguments (_tst "" "" "ENV;COMMAND" ${ARGN})
|
||||
set (testsuite "${CMAKE_SOURCE_DIR}/testsuite")
|
||||
set (testdir "${CMAKE_BINARY_DIR}/testsuite/${testname}")
|
||||
file (MAKE_DIRECTORY "${testdir}")
|
||||
if (NOT _tst_COMMAND)
|
||||
set (_tst_COMMAND ${Python_EXECUTABLE} "${testsuite}/runtest.py" ${testdir})
|
||||
if (MSVC_IDE)
|
||||
@@ -45,7 +51,17 @@ macro (add_one_testsuite testname testsrcdir)
|
||||
OSL_TESTSUITE_SRC=${testsrcdir}
|
||||
OSL_TESTSUITE_CUR=${testdir}
|
||||
)
|
||||
file (MAKE_DIRECTORY "${testdir}")
|
||||
|
||||
# We need to suppress the leak sanitizer for "texture" tests, because of a
|
||||
# minor leak inside OIIO (140 bytes! -- inconsequential) but which we
|
||||
# can't use the suppressions list becuase the leaks come from calls made
|
||||
# inside JITed code for which there is not a good stack trace. Any real
|
||||
# leaks from OIIO or its dependencies we assume will be caught by lsan on
|
||||
# the OIIO side, where there is no JIT to complicate things.
|
||||
if (${testname} MATCHES "^texture" OR ${testname} MATCHES "gettextureinfo")
|
||||
list (APPEND _tst_ENV ASAN_OPTIONS=detect_leaks=0:$ENV{ASAN_OPTIONS})
|
||||
endif ()
|
||||
|
||||
add_test ( NAME ${testname} COMMAND ${_tst_COMMAND} )
|
||||
# message ("Test -- env ${_tst_ENV} cmd ${_tst_COMMAND}")
|
||||
set_tests_properties (${testname} PROPERTIES ENVIRONMENT "${_tst_ENV}" )
|
||||
@@ -53,8 +69,7 @@ macro (add_one_testsuite testname testsrcdir)
|
||||
# from piling up together, allocate a few cores each.
|
||||
if (${testname} MATCHES "^render-")
|
||||
set_tests_properties (${testname} PROPERTIES LABELS render
|
||||
TIMEOUT 240
|
||||
PROCESSORS 4 COST 10 TIMEOUT 240)
|
||||
PROCESSORS 4 COST 10 TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
endif ()
|
||||
# Some labeling for fun
|
||||
if (${testname} MATCHES "^texture")
|
||||
@@ -76,7 +91,7 @@ macro (add_one_testsuite testname testsrcdir)
|
||||
# These are batched shading regression tests. Some are quite
|
||||
# long, so give them a higher cost and timeout.
|
||||
set_tests_properties (${testname} PROPERTIES LABELS batchregression
|
||||
COST 15 TIMEOUT 300)
|
||||
COST 15 TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
endif ()
|
||||
endmacro ()
|
||||
|
||||
@@ -90,6 +105,7 @@ macro ( TESTSUITE )
|
||||
endif ()
|
||||
set (test_all_optix $ENV{TESTSUITE_OPTIX})
|
||||
set (test_all_batched $ENV{TESTSUITE_BATCHED})
|
||||
set (test_all_rs_bitcode $ENV{TESTSUITE_RS_BITCODE})
|
||||
# Add the tests if all is well.
|
||||
set (ALL_TEST_LIST "")
|
||||
set (_testsuite "${CMAKE_SOURCE_DIR}/testsuite")
|
||||
@@ -106,7 +122,7 @@ macro ( TESTSUITE )
|
||||
|
||||
# Run the test unoptimized, unless it matches a few patterns that
|
||||
# we don't test unoptimized (or has an OPTIMIZEONLY marker file).
|
||||
if (NOT _testname MATCHES "optix"
|
||||
if (NOT _testname MATCHES "optix"
|
||||
AND NOT EXISTS "${_testsrcdir}/NOSCALAR"
|
||||
AND NOT EXISTS "${_testsrcdir}/BATCHED_REGRESSION"
|
||||
AND NOT EXISTS "${_testsrcdir}/OPTIMIZEONLY")
|
||||
@@ -123,6 +139,9 @@ 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})
|
||||
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
|
||||
@@ -141,7 +160,7 @@ macro ( TESTSUITE )
|
||||
add_one_testsuite ("${_testname}.optix.opt" "${_testsrcdir}"
|
||||
ENV TESTSHADE_OPT=2 TESTSHADE_OPTIX=1 )
|
||||
endif ()
|
||||
|
||||
|
||||
if (BUILD_BATCHED)
|
||||
# When building for Batched support, also run it in Batched mode
|
||||
# if there is an BATCHED marker file in the directory.
|
||||
@@ -155,7 +174,7 @@ macro ( TESTSUITE )
|
||||
add_one_testsuite ("${_testname}.batched" "${_testsrcdir}"
|
||||
ENV TESTSHADE_OPT=0 TESTSHADE_BATCHED=1 )
|
||||
endif ()
|
||||
|
||||
|
||||
if ((EXISTS "${_testsrcdir}/BATCHED" OR test_all_batched OR _testname MATCHES "batched")
|
||||
AND NOT EXISTS "${_testsrcdir}/BATCHED_REGRESSION"
|
||||
AND NOT EXISTS "${_testsrcdir}/NOBATCHED"
|
||||
@@ -164,7 +183,7 @@ macro ( TESTSUITE )
|
||||
add_one_testsuite ("${_testname}.batched.opt" "${_testsrcdir}"
|
||||
ENV TESTSHADE_OPT=2 TESTSHADE_BATCHED=1 )
|
||||
endif ()
|
||||
|
||||
|
||||
# When building for Batched support, optionally run a regression test
|
||||
# if there is an BATCHED_REGRESSION marker file in the directory.
|
||||
if ((EXISTS "${_testsrcdir}/BATCHED_REGRESSION")
|
||||
@@ -180,6 +199,25 @@ macro ( TESTSUITE )
|
||||
ENV TESTSHADE_OPT=0 OSL_REGRESSION_TEST=BATCHED )
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# if there is an RS_BITCODE marker file in the directory.
|
||||
if ((EXISTS "${_testsrcdir}/RS_BITCODE" OR test_all_rs_bitcode)
|
||||
AND NOT EXISTS "${_testsrcdir}/BATCHED_REGRESSION"
|
||||
AND NOT EXISTS "${_testsrcdir}/RS_BITCODE_REGRESSION"
|
||||
AND NOT EXISTS "${_testsrcdir}/NOOPTIMIZE")
|
||||
add_one_testsuite ("${_testname}.rsbitcode.opt" "${_testsrcdir}"
|
||||
ENV TESTSHADE_OPT=2 TESTSHADE_RS_BITCODE=1 )
|
||||
endif ()
|
||||
|
||||
# if there is an RS_BITCODE_REGRESSION marker file in the directory.
|
||||
if (EXISTS "${_testsrcdir}/RS_BITCODE_REGRESSION" OR (
|
||||
test_all_rs_bitcode AND EXISTS "${_testsrcdir}/BATCHED_REGRESSION")
|
||||
AND NOT EXISTS "${_testsrcdir}/NOOPTIMIZE")
|
||||
# optimized for right now
|
||||
add_one_testsuite ("${_testname}.regress.rsbitcode.opt" "${_testsrcdir}"
|
||||
ENV TESTSHADE_OPT=2 OSL_REGRESSION_TEST=RS_BITCODE )
|
||||
endif ()
|
||||
|
||||
endforeach ()
|
||||
if (VERBOSE)
|
||||
message (STATUS "Added tests: ${ALL_TEST_LIST}")
|
||||
@@ -191,16 +229,16 @@ macro (osl_add_all_tests)
|
||||
# special installed tests.
|
||||
TESTSUITE ( aastep allowconnect-err andor-reg and-or-not-synonyms
|
||||
arithmetic area-reg arithmetic-reg
|
||||
array array-reg array-copy-reg array-derivs array-range
|
||||
array array-reg array-copy-reg array-derivs array-range
|
||||
array-aassign array-assign-reg array-length-reg
|
||||
bitwise-and-reg bitwise-or-reg bitwise-shl-reg bitwise-shr-reg bitwise-xor-reg
|
||||
blackbody blackbody-reg blendmath breakcont breakcont-reg
|
||||
bug-array-heapoffsets bug-locallifetime bug-outputinit
|
||||
bug-param-duplicate bug-peep bug-return
|
||||
calculatenormal-reg
|
||||
cellnoise closure closure-array color color-reg comparison
|
||||
cellnoise closure closure-array color color-reg colorspace comparison
|
||||
complement-reg compile-buffer compassign-reg
|
||||
component-range
|
||||
component-range
|
||||
control-flow-reg connect-components
|
||||
const-array-params const-array-fill
|
||||
debugnan debug-uninit
|
||||
@@ -219,7 +257,9 @@ macro (osl_add_all_tests)
|
||||
globals-needed
|
||||
group-outputs groupstring
|
||||
hash hashnoise hex hyperb
|
||||
ieee_fp ieee_fp-reg if if-reg incdec initlist initops intbits isconnected
|
||||
ieee_fp ieee_fp-reg if if-reg incdec initlist
|
||||
initops initops-instance-clash
|
||||
intbits isconnected
|
||||
isconstant
|
||||
layers layers-Ciassign layers-entry layers-lazy layers-lazyerror
|
||||
layers-nonlazycopy layers-repeatedoutputs
|
||||
@@ -239,7 +279,7 @@ macro (osl_add_all_tests)
|
||||
noise-perlin noise-simplex
|
||||
noise-reg
|
||||
normalize-reg
|
||||
pnoise pnoise-cell pnoise-gabor
|
||||
pnoise pnoise-cell pnoise-gabor
|
||||
pnoise-generic pnoise-perlin
|
||||
pnoise-reg
|
||||
operator-overloading
|
||||
@@ -271,11 +311,20 @@ macro (osl_add_all_tests)
|
||||
raytype raytype-reg raytype-specialized regex-reg reparam
|
||||
render-background render-bumptest
|
||||
render-cornell render-furnace-diffuse
|
||||
render-mx-furnace-burley-diffuse
|
||||
render-mx-furnace-oren-nayar
|
||||
render-mx-furnace-sheen
|
||||
render-mx-burley-diffuse
|
||||
render-mx-dielectric render-mx-dielectric-glass
|
||||
render-mx-conductor
|
||||
render-mx-generalized-schlick render-mx-generalized-schlick-glass
|
||||
render-mx-layer
|
||||
render-mx-sheen
|
||||
render-microfacet render-oren-nayar
|
||||
render-uv render-veachmis render-ward
|
||||
select select-reg shaderglobals shortcircuit
|
||||
smoothstep-reg
|
||||
spline spline-reg splineinverse splineinverse-ident
|
||||
smoothstep-reg
|
||||
spline spline-reg splineinverse splineinverse-ident
|
||||
splineinverse-knots-ascend-reg splineinverse-knots-descend-reg
|
||||
spline-boundarybug spline-derivbug
|
||||
split-reg
|
||||
@@ -299,7 +348,7 @@ macro (osl_add_all_tests)
|
||||
trailing-commas
|
||||
transcendental-reg
|
||||
transitive-assign
|
||||
transform transform-reg transformc transformc-reg trig trig-reg
|
||||
transform transform-reg transformc transformc-reg trig trig-reg
|
||||
typecast
|
||||
unknown-instruction
|
||||
userdata userdata-passthrough
|
||||
@@ -319,10 +368,10 @@ macro (osl_add_all_tests)
|
||||
endif ()
|
||||
|
||||
# Add tests that require the Python bindings if we built them.
|
||||
# We also exclude these tests if this is a sanitizer build on Linux,
|
||||
# because the Python interpreter itself won't be linked with the right asan
|
||||
# We also exclude these tests if this is a sanitizer build, because the
|
||||
# Python interpreter itself won't be linked with the right asan
|
||||
# libraries to run correctly.
|
||||
if (USE_PYTHON AND NOT SANITIZE_ON_LINUX)
|
||||
if (USE_PYTHON AND NOT SANITIZE)
|
||||
TESTSUITE ( python-oslquery )
|
||||
endif ()
|
||||
|
||||
@@ -343,10 +392,13 @@ macro (osl_add_all_tests)
|
||||
TESTSUITE ( testoptix testoptix-noise example-cuda)
|
||||
endif ()
|
||||
|
||||
# Some regression tests have alot of combinations and may need more time to finish
|
||||
# Some regression tests have a lot of combinations and may need more time to finish
|
||||
if (BUILD_BATCHED)
|
||||
set_tests_properties (arithmetic-reg.regress.batched.opt PROPERTIES TIMEOUT 800)
|
||||
set_tests_properties (transform-reg.regress.batched.opt PROPERTIES TIMEOUT 800)
|
||||
set_tests_properties (arithmetic-reg.regress.batched.opt
|
||||
PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
set_tests_properties (transform-reg.regress.batched.opt
|
||||
PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
endif ()
|
||||
|
||||
set_tests_properties (matrix-reg.regress.rsbitcode.opt
|
||||
PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
endmacro()
|
||||
|
||||
+710
-77
@@ -66,7 +66,7 @@ All rights reserved.
|
||||
Editor: Larry Gritz \\
|
||||
\emph{lg@imageworks.com}
|
||||
}
|
||||
\date{{\large Date: 24 Nov 2021 \\
|
||||
\date{{\large Date: 27 Aug 2022 \\
|
||||
% (with corrections, 24 Nov 2021)
|
||||
}
|
||||
\bigskip
|
||||
@@ -1431,7 +1431,7 @@ least 32 bits.
|
||||
|
||||
Integer constants are constructed the same way as in C. The following
|
||||
are examples of {\cf int} constants: {\cf 1}, {\cf -32}, etc. Integer
|
||||
constants may be specified as hexidecimal, for example: {\cf 0x01cf}.
|
||||
constants may be specified as hexadecimal, for example: {\cf 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
|
||||
@@ -3778,7 +3778,7 @@ Computes the \emph{inverse} of the {\cf spline()} function, i.e., returns
|
||||
the value $x$ for which \\
|
||||
\spc {\cf spline (basis, x, y...)}\\
|
||||
would return value
|
||||
$v$. Results are undefined if the knots do not specifiy a monotonic
|
||||
$v$. Results are undefined if the knots do not specify a monotonic
|
||||
(only increasing or only decreasing) set of values.
|
||||
|
||||
Note that the combination of {\cf spline} and {\cf splineinverse} makes
|
||||
@@ -3905,7 +3905,7 @@ multi-component types such as \color, the format will be applied to each
|
||||
of the components). The {\cf \%s} expects a {\cf string} or
|
||||
{\cf closure} argument.
|
||||
|
||||
All of the substition commands follow the usual C/C++ formatting rules,
|
||||
All of the substitution commands follow the usual C/C++ formatting rules,
|
||||
so format commands such as {\cf "\%6.2f"}, etc., should work as
|
||||
expected.
|
||||
\apiend
|
||||
@@ -3930,7 +3930,7 @@ and other diagnostic information.
|
||||
\indexapi{fprintf()}
|
||||
The {\cf fprintf()} function works similarly to {\cf printf}, but rather
|
||||
than printing to the default text output stream, the results will be
|
||||
concatentated onto the end of the text file named by {\cf filename}.
|
||||
concatenated onto the end of the text file named by {\cf filename}.
|
||||
\apiend
|
||||
|
||||
\apiitem{string {\ce concat} (string s1, ..., string sN)}
|
||||
@@ -4404,7 +4404,7 @@ will not be modified and {\cf gettextureinfo} will return {\cf 0}.
|
||||
The version of {\cf gettextureinfo} that takes {\cf s} and {\cf t} parameters
|
||||
retrieves information about the texture file that will be used for those
|
||||
texture coordinates. This can be useful for UDIM textures that may use
|
||||
different texture files for different regions, based on the coodinates. For
|
||||
different texture files for different regions, based on the corodinates. For
|
||||
regular, non-UDIM textures, the coordinates, if supplied, will be ignored.
|
||||
When UDIM textures are queried without coordinates supplied, it will succeed
|
||||
and return the texture info only if that parameter is found and has the same
|
||||
@@ -4611,7 +4611,7 @@ Example:
|
||||
\index{material closure functions}
|
||||
\index{functions!closures}
|
||||
|
||||
For \closurecolor functions, the return ``value'' is symbolic and is may
|
||||
For \closurecolor functions, the return ``value'' is symbolic and may
|
||||
be passed to an output variable or assigned to \Ci, to be evaluated at a
|
||||
later time convenient to the renderer in order to compute the exitant
|
||||
radiance in the direction {\cf -I}. But the shader itself cannot
|
||||
@@ -4620,15 +4620,695 @@ examine the numeric values of the \colorclosure.
|
||||
The intent of this specification is to give a minimal but useful set of
|
||||
material closures that you can expect any renderer implementation to
|
||||
provide. Individual renderers may supply additional closures that are
|
||||
specific to the workings of that renderer. Additionally, invidual
|
||||
specific to the workings of that renderer. Additionally, individual
|
||||
renderers may allow additional parameters or controls on the standard
|
||||
closures, passed as token/value pairs following the required arguments
|
||||
(much like the optional arguments to the {\cf texture()} function).
|
||||
Consult the documentation for your specific renderer for details.
|
||||
|
||||
OSL's standard material closures are by synchronized to match the names and
|
||||
properties of the physically-based shading nodes of MaterialX v1.38
|
||||
(\url{https://www.materialx.org/}).
|
||||
|
||||
\subsection{Surface BSDF closures}
|
||||
|
||||
\apiitem{\closurecolor\ {\ce oren_nayar_diffuse_bsdf}(normal N, color albedo, float roughness)}
|
||||
\indexapi{oren_nayar_diffuse_bsdf()}
|
||||
|
||||
Constructs a diffuse reflection BSDF based on the Oren-Nayar reflectance
|
||||
model.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Surface albedo.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness}
|
||||
\vspace{12pt}
|
||||
Surface roughness [0,1]. A value of 0.0 gives Lambertian reflectance.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
The Oren-Nayar reflection model is described in M.\ Oren and S.\ K.\
|
||||
Nayar, ``Generalization of Lambert's Reflectance Model,'' Proceedings of
|
||||
SIGGRAPH 1994, pp.239-246 (July, 1994).
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Surface material closures}
|
||||
\apiitem{\colorclosure\ {\ce burley_diffuse_bsdf} (normal N, color albedo, float roughness)}
|
||||
\indexapi{burley_diffuse_bsdf()}
|
||||
|
||||
Constructs a diffuse reflection BSDF based on the corresponding component of
|
||||
the Disney Principled shading model.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Surface albedo.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness}
|
||||
\vspace{12pt}
|
||||
Surface roughness [0,1]. A value of 0.0 gives Lambertian reflectance.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce dielectric_bsdf} (normal N, vector U, color reflection_tint, \\
|
||||
\spc\spc color transmission_tint, float roughness_x, float roughness_y, \\
|
||||
\spc\spc float ior, string distribution)}
|
||||
\indexapi{dielectric_bsdf()}
|
||||
|
||||
Constructs a reflection and/or transmission BSDF based on a microfacet
|
||||
reflectance model and a Fresnel curve for dielectrics. The two tint parameters
|
||||
control the contribution of each reflection/transmission lobe. The tints
|
||||
should remain 100\% white for a physically correct dielectric, but can be
|
||||
tweaked for artistic control or set to 0.0 for disabling a lobe.
|
||||
|
||||
The closure may be vertically layered over a base BSDF for the surface beneath
|
||||
the dielectric layer. This is done using the {\cf layer()} closure. By
|
||||
chaining multiple {\cf dielectric_bsdf} closures you can describe a surface
|
||||
with multiple specular lobes. If transmission is enabled (transmission_tint
|
||||
$>$ 0.0) the closure may be layered over a VDF closure describing the surface
|
||||
interior to handle absorption and scattering inside the medium.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{U}
|
||||
\vspace{12pt}
|
||||
Tangent vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{reflection_tint}
|
||||
\vspace{12pt}
|
||||
Weight per color channel for the reflection lobe. Should be (1,1,1) for a physically-correct dielectric surface, but can be tweaked for artistic control. Set to (0,0,0) to disable reflection.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{transmission_tint}
|
||||
\vspace{12pt}
|
||||
Weight per color channel for the transmission lobe. Should be (1,1,1) for a physically-correct dielectric surface, but can be tweaked for artistic control. Set to (0,0,0) to disable transmission.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness_x}
|
||||
\vspace{12pt}
|
||||
Surface roughness in the U direction with a perceptually linear response over its range.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness_y}
|
||||
\vspace{12pt}
|
||||
Surface roughness in the V direction with a perceptually linear response
|
||||
over its range.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{ior}
|
||||
\vspace{12pt}
|
||||
Refraction index.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{distribution}
|
||||
\vspace{12pt}
|
||||
Microfacet distribution. An implementation is expected to support the
|
||||
following distributions: \qkw{ggx}
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{thinfilm_thickness}
|
||||
\vspace{12pt}
|
||||
Optional float parameter for thickness of an iridescent thin film layer on
|
||||
top of this BSDF. Given in nanometers.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{thinfilm_ior}
|
||||
\vspace{12pt}
|
||||
Optional float parameter for refraction index of the thin film layer.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce conductor_bsdf} (normal N, vector U, float roughness_x, \\
|
||||
\spc\spc float roughness_y, color ior, color extinction, string distribution)}
|
||||
\indexapi{conductor_bsdf()}
|
||||
|
||||
Constructs a reflection BSDF based on a microfacet reflectance model. Uses a
|
||||
Fresnel curve with complex refraction index for conductors/metals. If an
|
||||
artistic parametrization is preferred the {\cf artistic_ior()} utility
|
||||
function can be used to convert from artistic to physical parameters.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{U}
|
||||
\vspace{12pt}
|
||||
Tangent vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness_x}
|
||||
\vspace{12pt}
|
||||
Surface roughness in the U direction with a perceptually linear response over its range.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness_y}
|
||||
\vspace{12pt}
|
||||
Surface roughness in the V direction with a perceptually linear response over its range.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{ior}
|
||||
\vspace{12pt}
|
||||
Refraction index.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{extinction}
|
||||
\vspace{12pt}
|
||||
Extinction coefficient.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{distribution}
|
||||
\vspace{12pt}
|
||||
Microfacet distribution. An implementation is expected to support the
|
||||
following distributions: \qkw{ggx}
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{thinfilm_thickness}
|
||||
\vspace{12pt}
|
||||
Optional float parameter for thickness of an iridescent thin film layer on
|
||||
top of this BSDF. Given in nanometers.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{thinfilm_ior}
|
||||
\vspace{12pt}
|
||||
Optional float parameter for refraction index of the thin film layer.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce generalized_schlick_bsdf} (normal N, vector U, \\
|
||||
\spc\spc color reflection_tint, color transmission_tint, \\
|
||||
\spc\spc float roughness_x, float roughness_y, color f0, color f90, \\
|
||||
\spc\spc float exponent, string distribution)}
|
||||
\indexapi{generalized_schlick_bsdf()}
|
||||
|
||||
Constructs a reflection and/or transmission BSDF based on a microfacet
|
||||
reflectance model and a generalized Schlick Fresnel curve. The two tint
|
||||
parameters control the contribution of each reflection/transmission lobe.
|
||||
|
||||
The closure may be vertically layered over a base BSDF for the surface beneath
|
||||
the dielectric layer. This is done using the layer() closure. By chaining
|
||||
multiple {\cf dielectric_bsdf} closures you can describe a surface with multiple
|
||||
specular lobes. If transmission is enabled (transmission_tint $>$ 0.0) the
|
||||
closure may be layered over a VDF closure describing the surface interior to
|
||||
handle absorption and scattering inside the medium.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{U}
|
||||
\vspace{12pt}
|
||||
Tangent vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{reflection_tint}
|
||||
\vspace{12pt}
|
||||
Weight per color channel for the reflection lobe. Set to (0,0,0) to disable
|
||||
reflection.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{transmission_tint}
|
||||
\vspace{12pt}
|
||||
Weight per color channel for the transmission lobe. Set to (0,0,0) to
|
||||
disable transmission.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness_x}
|
||||
\vspace{12pt}
|
||||
Surface roughness in the U direction with a perceptually linear response
|
||||
over its range.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness_y}
|
||||
\vspace{12pt}
|
||||
Surface roughness in the V direction with a perceptually linear response
|
||||
over its range.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{f0}
|
||||
\vspace{12pt}
|
||||
Reflectivity per color channel at facing angles.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{f90}
|
||||
\vspace{12pt}
|
||||
Reflectivity per color channel at grazing angles.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{exponent}
|
||||
\vspace{12pt}
|
||||
Variable exponent for the Schlick Fresnel curve, the default value should be
|
||||
5.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{distribution}
|
||||
\vspace{12pt}
|
||||
Microfacet distribution. An implementation is expected to support the
|
||||
following distributions: \qkw{ggx}
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{thinfilm_thickness}
|
||||
\vspace{12pt}
|
||||
Optional float parameter for thickness of an iridescent thin film layer on
|
||||
top of this BSDF. Given in nanometers.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{thinfilm_ior}
|
||||
\vspace{12pt}
|
||||
Optional float parameter for refraction index of the thin film layer.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce translucent_bsdf} (normal N, color albedo)}
|
||||
\indexapi{translucent_bsdf()}
|
||||
|
||||
Constructs a translucent (diffuse transmission) BSDF based on the Lambert
|
||||
reflectance model.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Surface albedo.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness}
|
||||
\vspace{12pt}
|
||||
Surface roughness [0,1]. A value of 0.0 gives Lambertian reflectance.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce transparent_bsdf} ( )}
|
||||
\indexapi{transparent_bsdf()}
|
||||
|
||||
Constructs a closure that represents straight transmission through a surface.
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce subsurface_bssrdf} ( )}
|
||||
\indexapi{subsurface_bssrdf}
|
||||
Constructs a BSSRDF for subsurface scattering within a homogeneous medium.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Single-scattering albedo of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{transmission_depth}
|
||||
\vspace{12pt}
|
||||
Distance travelled inside the medium by white light before its color becomes
|
||||
transmission_color by Beer's law. Given in scene length units, range
|
||||
[0,infinity). Together with transmission_color this determines the
|
||||
extinction coefficient of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{transmission_color}
|
||||
\vspace{12pt}
|
||||
Desired color resulting from white light transmitted a distance of
|
||||
'transmission_depth' through the medium. Together with transmission_depth
|
||||
this determines the extinction coefficient of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{anisotropy}
|
||||
\vspace{12pt}
|
||||
Scattering anisotropy [-1,1]. Negative values give backwards scattering,
|
||||
positive values give forward scattering, and 0.0 gives uniform scattering.
|
||||
\apiend
|
||||
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce sheen_bsdf} (normal N, color albedo, float roughness)}
|
||||
\indexapi{sheen_bsdf()}
|
||||
|
||||
Constructs a microfacet BSDF for the back-scattering properties of cloth-like
|
||||
materials. This closure may be vertically layered over a base BSDF, where
|
||||
energy that is not reflected will be transmitted to the base closure.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Surface albedo.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness}
|
||||
\vspace{12pt}
|
||||
Surface roughness [0,1].
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
|
||||
\subsection{Volumetric material closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce anisotropic_vdf} (color albedo, color extinction, float anisotropy)}
|
||||
\indexapi{anisotropic_vdf}
|
||||
|
||||
Constructs a VDF scattering light for a general participating medium, based on
|
||||
the Henyey-Greenstein phase function. Forward, backward and uniform scattering
|
||||
is supported and controlled by the anisotropy input.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Single-scattering albedo of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{extinction}
|
||||
\vspace{12pt}
|
||||
Volume extinction coefficient.
|
||||
\apiend
|
||||
|
||||
\apiitem{anisotropy}
|
||||
\vspace{12pt}
|
||||
Scattering anisotropy [-1,1]. Negative values give backwards scattering,
|
||||
positive values give forward scattering, and 0.0 gives uniform scattering.
|
||||
\apiend
|
||||
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce medium_vdf} (color albedo, float transmission_depth, \\
|
||||
\spc\spc color transmission_color, float anisotropy, float ior, int priority)}
|
||||
\indexapi{medium_vdf}
|
||||
|
||||
Constructs a VDF for light passing through a dielectric homogeneous medium,
|
||||
such as glass or liquids. The parameters {\cf transmission_depth} and
|
||||
{\cf transmission_color} control the extinction coefficient of the medium in an
|
||||
artist-friendly way. A priority can be set to determine the ordering of
|
||||
overlapping media.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Single-scattering albedo of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{transmission_depth}
|
||||
\vspace{12pt}
|
||||
Distance travelled inside the medium by white light before its color becomes
|
||||
transmission_color by Beer's law. Given in scene length units, range
|
||||
[0,infinity). Together with transmission_color this determines the
|
||||
extinction coefficient of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{transmission_color}
|
||||
\vspace{12pt}
|
||||
Desired color resulting from white light transmitted a distance of
|
||||
'transmission_depth' through the medium. Together with transmission_depth
|
||||
this determines the extinction coefficient of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{anisotropy}
|
||||
\vspace{12pt}
|
||||
Scattering anisotropy [-1,1]. Negative values give backwards scattering,
|
||||
positive values give forward scattering, and 0.0 gives uniform scattering.
|
||||
\apiend
|
||||
|
||||
\apiitem{ior}
|
||||
\vspace{12pt}
|
||||
Refraction index of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{priority}
|
||||
\vspace{12pt}
|
||||
Priority of this medium (for nested dielectrics).
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Light emission closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce uniform_edf} (color emittance)}
|
||||
\indexapi{uniform_edf}
|
||||
Constructs an EDF emitting light uniformly in all directions.
|
||||
This is used to represent a glowing/emissive material.
|
||||
When called in the context of a surface shader group, it implies that
|
||||
light is emitted in a full hemisphere centered around the surface
|
||||
normal. When called in the context of a volume shader group, it implies
|
||||
that light is emitted evenly in all directions around the point being
|
||||
shaded.
|
||||
|
||||
The {\cf emittance} parameter is the amount of emission and
|
||||
has units of radiance (e.g.,
|
||||
$\mathrm{W}\cdot\mathrm{sr}^{-1}\cdot\mathrm{m}^{-2}$). This means that a surface
|
||||
directly seen by the camera will directly reproduce the closure weight in the
|
||||
final pixel, regardless of being a surface or a volume.
|
||||
|
||||
For an emissive surface, if you divide the return value of {\cf uniform_edf()} by
|
||||
{\cf surfacearea() * M_PI}, then you can easily specify the total emissive
|
||||
power of the light (e.g., $\mathrm{W}$), regardless of its physical size.
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Layering and Signaling closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce layer} (closure color top, closure color base)}
|
||||
\indexapi{layer()}
|
||||
Vertically layer a layerable BSDF such as {\cf dielectric_bsdf},
|
||||
{\cf generalized_schlick_bsdf} or {\cf sheen_bsdf} over a BSDF or VDF. The
|
||||
implementation is target specific, but a standard way of handling this is by
|
||||
albedo scaling, using {\cf base*(1-reflectance(top)) + top}, where
|
||||
reflectance() calculates the directional albedo of a given top BSDF.
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce holdout} ( )}
|
||||
\indexapi{holdout()}
|
||||
Returns a \colorclosure that does not represent any additional light
|
||||
reflection from the surface, but does signal to the renderer that
|
||||
the surface is a \emph{holdout object} (appears transparent in
|
||||
the final output yet hides objects behind it). ``Partial holdouts''
|
||||
may be designated by weighting the {\cf holdout()} closure by a
|
||||
weight that is less than 1.0.
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce debug} (string outputname)}
|
||||
\indexapi{debug()}
|
||||
Returns a \colorclosure that does not represent any additional light
|
||||
reflection from the surface, but does signal to the renderer to add
|
||||
the weight of the closure (which may be a {\cf float} or a \color)
|
||||
to the named output (i.e., AOV).
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Material utility functions}
|
||||
|
||||
\apiitem{void {\ce artistic_ior} (color reflectivity, color edge_tint, \\
|
||||
\spc\spc output color ior, output color extinction)}
|
||||
\indexapi{artistic_ior()}
|
||||
Converts the artistic parameterization reflectivity and edge_tint to complex IOR values.
|
||||
To be used with the conductor_bsdf() closure.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{reflectivity}
|
||||
\vspace{12pt}
|
||||
Reflectivity per color channel at facing angles (\emph{r} parameter in [OG14])
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{edge_tint}
|
||||
\vspace{12pt}
|
||||
Color bias for grazing angles (\emph{g} parameter in [OG14]).
|
||||
NOTE: This is not equal to 'f90' in a Schlick Fresnel parameterization.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{ior}
|
||||
\vspace{12pt}
|
||||
Output refraction index.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{extinction}
|
||||
\vspace{12pt}
|
||||
Output extinction coefficient.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
Reference: [OG14] Ole Gulbrandsen, "Artist Friendly Metallic Fresnel", Journal
|
||||
of Computer Graphics Tools 3(4), 2014.
|
||||
\url{http://jcgt.org/published/0003/04/03/paper.pdf}
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Deprecated closures}
|
||||
|
||||
These were described in the original OSL language specification, but
|
||||
beginning with OSL 1.12, these are considered deprecated. Support for
|
||||
them will be removed entirely in OSL 2.0.
|
||||
|
||||
\subsubsection{Deprecated Surface closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce diffuse} (normal N)}
|
||||
\indexapi{diffuse()}
|
||||
@@ -4664,7 +5344,7 @@ Nayar, ``Generalization of Lambert's Reflectance Model,'' Proceedings of
|
||||
SIGGRAPH 1994, pp.239-246 (July, 1994).
|
||||
|
||||
\begin{comment}
|
||||
Like all \closurecolors, the return ``value'' is symbolic and is may be
|
||||
Like all \closurecolors, the return ``value'' is symbolic and may be
|
||||
evaluated at a later time convenient to the renderer in order to compute
|
||||
the exitant radiance in the direction {\cf -I}. But aside from the
|
||||
fact that the shader cannot examine the numeric values of the
|
||||
@@ -4745,33 +5425,6 @@ implemented as follows:
|
||||
\end{comment}
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce microfacet} (string distribution, normal N, vector
|
||||
U, \\ \bigspc\bigspc float xalpha, float yalpha, float eta, int refract)}
|
||||
\indexapi{microfacet()}
|
||||
|
||||
Returns a \colorclosure that represents scattering on the
|
||||
surface using some microfacet distribution such as \qkw{beckmann} or \qkw{ggx} (as
|
||||
described in Walter et al., ``Microfacet Models for Refraction through Rough
|
||||
Surfaces,'' Eurographics Symposium on Rendering, 2007).
|
||||
Both {\cf xalpha} and {\cf yalpha} control how rough the microstructure of the
|
||||
surface is, possibly in an anisotropic way if they are different. In the
|
||||
anisotropic case {\cf U} must be a vector orthogonal to {\cf N} to specify the
|
||||
direction. These values are expected to be the alpha values of the distribution
|
||||
as it appears in the literature, not a universal roughness measure.
|
||||
The {\cf eta} parameter is the index of refraction of the material, and
|
||||
{\cf refract} is a enumeration flag that controls if the BSDF is reflective ({\cf 0}),
|
||||
refractive ({\cf 1}) or both at once ({\cf 2}). The implementation must not rely on
|
||||
{\cf U} when the roughness is isotropic or the given vector is zero.
|
||||
|
||||
The list of supported distributions will change from renderer to renderer, and
|
||||
also the behavior when an unsupported distribution is requested. It is up to the
|
||||
implementation to issue an error or to default to a supported one. Also it is
|
||||
expected that the alias \qkw{default} must work as a distribution in any renderer.
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce microfacet} (string distribution, normal N,
|
||||
\\ \bigspc\bigspc float alpha, float eta, int refract)}
|
||||
\indexapi{microfacet()}
|
||||
@@ -4823,7 +5476,6 @@ implemented as follows:
|
||||
\end{code}
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce transparent} ( )}
|
||||
\indexapi{transparent()}
|
||||
|
||||
@@ -4867,8 +5519,7 @@ scattering} exhibited by the surface.
|
||||
\apiend
|
||||
\end{comment}
|
||||
|
||||
|
||||
\subsection{Volumetric material closures}
|
||||
\subsubsection{Deprecated Volumetric closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce isotropic} ( )}
|
||||
\indexapi{isotropic}
|
||||
@@ -4877,18 +5528,16 @@ volumetric material, scattering light evenly in all directions,
|
||||
regardless of its original direction.
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce henyey_greenstein} (float g)}
|
||||
\indexapi{henyey_greenstein}
|
||||
Returns a \colorclosure that represents the directional volumetric
|
||||
scattering by small suspended particles. The {\cf g} parameter is the
|
||||
anisotropy factor, ranging from $-1$ to $1$), with positive values
|
||||
anisotropy factor, in the range $(-1, 1)$, with positive values
|
||||
indicating predominantly forward-scattering, negative values indicating
|
||||
predominantly back-scattering, and value of $g=0$ resulting in isotropic
|
||||
scattering.
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce absorption} ( )}
|
||||
\indexapi{absorption}
|
||||
Returns a \colorclosure that does not represent any additional
|
||||
@@ -4898,8 +5547,7 @@ volumetric material, scattering light evenly in all directions,
|
||||
regardless of its original direction.
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Light emission closures}
|
||||
\subsubsection{Deprecated Emission closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce emission} ( )}
|
||||
\indexapi{emission}
|
||||
@@ -4915,7 +5563,7 @@ $\mathrm{W}\cdot\mathrm{sr}^{-1}\cdot\mathrm{m}^{-2}$). This means that a surfac
|
||||
directly seen by the camera will directly reproduce the closure weight in the
|
||||
final pixel, regardless of being a surface or a volume.
|
||||
|
||||
For surface emission, If you divide {\cf emission()} by
|
||||
For an emissive surface, if you divide the return value of {\cf emission()} by
|
||||
{\cf surfacearea() * M_PI}, then you can easily specify the total emissive
|
||||
power of the light (e.g., $\mathrm{W}$), regardless of its physical size.
|
||||
\apiend
|
||||
@@ -4930,30 +5578,6 @@ up from an HDRI environment map.
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Signaling closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce holdout} ( )}
|
||||
\indexapi{holdout()}
|
||||
Returns a \colorclosure that does not represent any additional light
|
||||
reflection from the surface, but does signal to the renderer that
|
||||
the surface is a \emph{holdout object} (appears transparent in
|
||||
the final output yet hides objects behind it). ``Partial holdouts''
|
||||
may be designated by weighting the {\cf holdout()} closure by a
|
||||
weight that is less than 1.0.
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce debug} (string outputname)}
|
||||
\indexapi{debug()}
|
||||
Returns a \colorclosure that does not represent any additional light
|
||||
reflection from the surface, but does signal to the renderer to add
|
||||
the weight of the closure (which may be a {\cf float} or a \color)
|
||||
to the named output (i.e., AOV).
|
||||
\apiend
|
||||
|
||||
|
||||
|
||||
|
||||
\newpage
|
||||
\section{Renderer state and message passing}
|
||||
\label{sec:stdlib:state}
|
||||
@@ -5750,7 +6374,7 @@ programming language design)?
|
||||
|
||||
This spec is written assuming that \color should explicitly be
|
||||
3-component RGB. Alternately, we could add global \inttype\ {\cf ncomps} that gives the
|
||||
numer of components in a \color, and eliminate any built-in operations
|
||||
number of components in a \color, and eliminate any built-in operations
|
||||
and library functions that seem to require or imply a 3-component color
|
||||
model (including type casting between \color and the 3-component
|
||||
\point-like types).
|
||||
@@ -5862,7 +6486,7 @@ anybody want to argue for any of the following to be included?
|
||||
|
||||
We have defined structures as being allowed to consist only of basic
|
||||
types and arrays thereof --- not structures of structures. This
|
||||
restriction makes for a simpler grammar and implementation, simplier
|
||||
restriction makes for a simpler grammar and implementation, simpler
|
||||
renderer-side APIs for passing data to shaders, and simpler APIs for
|
||||
libraries that query parameters of compiled shaders. But if people
|
||||
strongly feel like structures-of-structures is an important feature, we
|
||||
@@ -5948,7 +6572,7 @@ about it.
|
||||
|
||||
\subsection{Nomenclature}
|
||||
|
||||
Does anybody have a perference for \dPdu and \dPdv (borrowing the
|
||||
Does anybody have a preference for \dPdu and \dPdv (borrowing the
|
||||
RenderMan names, but awkward for primitives without a consistent $u,v$
|
||||
parameterization?), versus something more generic such as {\cf T} and
|
||||
{\cf B} (tangent and bitangent, without explicitly saying how they are
|
||||
@@ -6134,6 +6758,9 @@ full control in the shader.
|
||||
may be shared among multiple geometric primitives. Also sometimes
|
||||
called \emph{graphics state}.
|
||||
|
||||
\item[BSDF.] Bidirectional scattering distribution function, a
|
||||
function that describes light scattering properties of a surface.
|
||||
|
||||
\item[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 \langname
|
||||
@@ -6144,7 +6771,7 @@ full control in the shader.
|
||||
at a later time to yield a final numeric value.
|
||||
|
||||
\item[Connection.] A routing of the value of an \emph{output parameter}
|
||||
of one \emph{shader layer} to an \emph{input paramter} of another
|
||||
of one \emph{shader layer} to an \emph{input parameter} of another
|
||||
shader layer within the same \emph{shader group}.
|
||||
|
||||
\item[Default parameter value.] The initial value of a \emph{shader
|
||||
@@ -6155,6 +6782,9 @@ full control in the shader.
|
||||
is explicitly given in the code for that shader, and may either be
|
||||
a constant or a computed expression.
|
||||
|
||||
\item[EDF.] Emission distribution function, a function that describes
|
||||
the distribution of light emitted by a light source.
|
||||
|
||||
\item[Geometric primitive.] A single shape, such as a NURBS patch, a
|
||||
polygon or subdivision mesh, a hair primitive, etc.
|
||||
|
||||
@@ -6190,7 +6820,7 @@ full control in the shader.
|
||||
|
||||
\item[Primitive variable.] A named variable, and values, attached to an
|
||||
individual geometric primitive. Primitive variables may have one of
|
||||
serveral \emph{interpolation methods} --- such as a single value for
|
||||
several \emph{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.
|
||||
@@ -6199,12 +6829,12 @@ full control in the shader.
|
||||
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 \emph{top-level} (not defined within other functions) and must
|
||||
be preceeded by the {\cf public} keyword.
|
||||
be preceded by the {\cf public} keyword.
|
||||
|
||||
\item[Shader.] A small self-contained program written in \langname, used
|
||||
to extend the functionality of a renderer with custom behavior of
|
||||
materials and lights. A particular shader may have multiple
|
||||
\emph{shader instances} within a scene, each of which has ts unique
|
||||
\emph{shader instances} within a scene, each of which has its unique
|
||||
\emph{instance parameters}, transformation, etc.
|
||||
|
||||
\item[Shader function.] A function written in \langname that may be
|
||||
@@ -6239,6 +6869,9 @@ full control in the shader.
|
||||
\item[Shading.] The computations within a renderer that implement the
|
||||
behavior and visual appearance of materials and lights.
|
||||
|
||||
\item[VDF.] Volumetric distribution function, a function that describes
|
||||
the scattering properties of a volume.
|
||||
|
||||
\end{description}
|
||||
|
||||
\end{appendix}
|
||||
|
||||
Binary file not shown.
@@ -11,7 +11,7 @@
|
||||
_testshade_ basics
|
||||
==================================================
|
||||
|
||||
The OSL software distribution inculdes `testshade`, a command-line utility
|
||||
The OSL software distribution includes `testshade`, a command-line utility
|
||||
that was written for OSL unit tests, and for a "test harness" in which we
|
||||
can execute shaders for debugging (the shaders or OSL itself) in isolation
|
||||
from any particular rendering system.
|
||||
@@ -28,7 +28,7 @@ itself, it has a number of potential uses in a production studio, including:
|
||||
* Baking procedural patterns into textures.
|
||||
|
||||
* Benchmarking shaders and evaluating their performance, including
|
||||
comparitive tests such as "is it faster to code it this way or that way?"
|
||||
comparative tests such as "is it faster to code it this way or that way?"
|
||||
|
||||
* Exploring the inner workings of OSL's runtime optimizer, to answer
|
||||
questions like: "will this idiom optimize away at runtime when I use
|
||||
@@ -176,7 +176,7 @@ Helpful command line arguments:
|
||||
|
||||
For the sake of simplicity, this document presents almost all examples as if
|
||||
they consisted of just a single shader node. But `testshade` is able to
|
||||
specify and execut entire shader groups (networks of shader nodes). The
|
||||
specify and execute entire shader groups (networks of shader nodes). The
|
||||
remainder of this section will explain how this can be done.
|
||||
|
||||
Let's make a simple shader network as an example.
|
||||
@@ -582,7 +582,7 @@ single texture lookup.
|
||||
|
||||
|
||||
|
||||
## Controling optimization
|
||||
## Controlling optimization
|
||||
|
||||
You can control the optimization level overall:
|
||||
|
||||
@@ -638,7 +638,7 @@ that they are not optimized away so as to lead you to an inaccurate
|
||||
reflection of what optimizations would really happen at render time. At the
|
||||
same time, be careful not to inadvertently set `lockgeom=0` for parameters
|
||||
that will typically be set to default values, instance values, or
|
||||
connections from layers that are likely to be analized and found to emit
|
||||
connections from layers that are likely to be analyzed and found to emit
|
||||
constants for theor outputs -- you also don't want your benchmarks to
|
||||
incorrectly disable optimizations what would typically happen at render
|
||||
time.
|
||||
|
||||
@@ -16,9 +16,21 @@
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
#if OSL_USING_IMATH < 3
|
||||
# include <OSL/matrix22.h>
|
||||
#endif
|
||||
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
|
||||
#if OSL_USING_IMATH >= 3
|
||||
using Matrix22 = Imath::Matrix22<Float>;
|
||||
#else
|
||||
using Matrix22 = Imathx::Matrix22<Float>;
|
||||
#endif
|
||||
|
||||
|
||||
// Choose to treat helper functions as static
|
||||
// so their symbols don't escape and possibly collide
|
||||
// with other compilation units who might be compiled with
|
||||
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
AccumRule(int outidx, bool toalpha)
|
||||
: m_outidx(outidx), m_save_to_alpha(toalpha) {};
|
||||
|
||||
/// Called to accumulate from AccumAutomata. It will select the right ouput from
|
||||
/// Called to accumulate from AccumAutomata. It will select the right output from
|
||||
/// the given vector based in the AOV index number (they are guaranteed to match)
|
||||
void accum(const Color3& color, std::vector<AovOutput>& outputs) const;
|
||||
|
||||
|
||||
@@ -43,13 +43,6 @@ struct UniformShaderGlobals {
|
||||
/// way back to the renderer for callbacks.
|
||||
RendererServices* renderer;
|
||||
|
||||
/// The output closure will be placed here. The rendererer should
|
||||
/// initialize this to NULL before shading execution, and this is where
|
||||
/// it can retrieve the output closure from after shader execution has
|
||||
/// completed.
|
||||
/// DESIGN DECISION: NOT CURRENTLY SUPPORTING CLOSURES IN BATCH MODE
|
||||
ClosureColor* Ci;
|
||||
|
||||
/// Bit field of ray type flags.
|
||||
int raytype;
|
||||
|
||||
@@ -59,6 +52,8 @@ struct UniformShaderGlobals {
|
||||
int pad0;
|
||||
int pad1;
|
||||
int pad2;
|
||||
int pad3;
|
||||
int pad4;
|
||||
|
||||
void dump()
|
||||
{
|
||||
@@ -70,7 +65,6 @@ struct UniformShaderGlobals {
|
||||
__OSL_DUMP(objdata);
|
||||
__OSL_DUMP(context);
|
||||
__OSL_DUMP(renderer);
|
||||
__OSL_DUMP(Ci);
|
||||
__OSL_DUMP(raytype);
|
||||
|
||||
std::cout << "};" << std::endl;
|
||||
@@ -129,6 +123,12 @@ template<int WidthT> struct alignas(64) VaryingShaderGlobals {
|
||||
Block<TransformationPtr> object2common;
|
||||
Block<TransformationPtr> shader2common;
|
||||
|
||||
/// The output closure will be placed here. The rendererer should
|
||||
/// initialize this to NULL before shading execution, and this is where
|
||||
/// it can retrieve the output closure from after shader execution has
|
||||
/// completed.
|
||||
Block<ClosureColor*> Ci;
|
||||
|
||||
/// Surface area of the emissive object (used by light shaders for
|
||||
/// energy normalization).
|
||||
Block<float> surfacearea;
|
||||
@@ -168,6 +168,7 @@ template<int WidthT> struct alignas(64) VaryingShaderGlobals {
|
||||
__OSL_DUMP(dPsdy);
|
||||
__OSL_DUMP(object2common);
|
||||
__OSL_DUMP(shader2common);
|
||||
__OSL_DUMP(Ci);
|
||||
__OSL_DUMP(surfacearea);
|
||||
__OSL_DUMP(flipHandedness);
|
||||
__OSL_DUMP(backfacing);
|
||||
|
||||
@@ -135,77 +135,77 @@ static_assert(sizeof(OIIO::TextureOptBatch)
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, sblur)
|
||||
== varying_offset + offsetof(VTO, sblur),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, tblur)
|
||||
== varying_offset + offsetof(VTO, tblur),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, rblur)
|
||||
== varying_offset + offsetof(VTO, rblur),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, swidth)
|
||||
== varying_offset + offsetof(VTO, swidth),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, twidth)
|
||||
== varying_offset + offsetof(VTO, twidth),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, rwidth)
|
||||
== varying_offset + offsetof(VTO, rwidth),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, firstchannel)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, firstchannel),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, subimage)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, subimage),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, subimagename)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, subimagename),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, swrap)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, swrap),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, twrap)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, twrap),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, rwrap)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, rwrap),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, mipmode)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, mipmode),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, interpmode)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, interpmode),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, anisotropic)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, anisotropic),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, conservative_filter)
|
||||
== uniform_offset
|
||||
+ offsetof(UniformTextureOptions, conservative_filter),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, fill)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, fill),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, missingcolor)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, missingcolor),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
|
||||
OSL_PRAGMA_WARNING_POP
|
||||
} // namespace validate_offsets
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
#ifdef __CUDA_ARCH__
|
||||
#include <optix.h>
|
||||
# include <optix.h>
|
||||
#endif
|
||||
|
||||
// USAGE NOTES:
|
||||
@@ -36,20 +36,20 @@ OSL_NAMESPACE_ENTER
|
||||
// stored in the table, in the 16 bytes preceding the characters.
|
||||
|
||||
struct DeviceString {
|
||||
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
|
||||
size_t m_chars;
|
||||
#ifdef __CUDA_ARCH__
|
||||
size_t m_chars;
|
||||
#else
|
||||
const char* m_chars;
|
||||
#endif
|
||||
|
||||
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
|
||||
#ifdef __CUDA_ARCH__
|
||||
OSL_HOSTDEVICE DeviceString() {}
|
||||
OSL_HOSTDEVICE DeviceString(uint64_t i) : m_chars(i) {}
|
||||
#endif
|
||||
|
||||
OSL_HOSTDEVICE uint64_t hash() const
|
||||
{
|
||||
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
|
||||
#ifdef __CUDA_ARCH__
|
||||
return m_chars;
|
||||
#else
|
||||
return *(uint64_t*)(m_chars - sizeof(uint64_t) - sizeof(uint64_t));
|
||||
@@ -58,7 +58,7 @@ struct DeviceString {
|
||||
|
||||
// In OptiX 7 we don't store the string's length. Make this a compile
|
||||
// time error.
|
||||
#if ! (defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000)
|
||||
#ifndef __CUDA_ARCH__
|
||||
OSL_HOSTDEVICE uint64_t length() const
|
||||
{
|
||||
return *(uint64_t*)(m_chars - sizeof(uint64_t));
|
||||
@@ -67,36 +67,39 @@ struct DeviceString {
|
||||
|
||||
// In OptiX 7 we can't return the string's contents. Make this a compile
|
||||
// time error.
|
||||
#if ! (defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000)
|
||||
#ifndef __CUDA_ARCH__
|
||||
OSL_HOSTDEVICE const char* c_str() const
|
||||
{
|
||||
return m_chars;
|
||||
}
|
||||
#endif
|
||||
|
||||
OSL_HOSTDEVICE bool operator== (const DeviceString& other) const
|
||||
OSL_HOSTDEVICE bool operator==(const DeviceString& other) const
|
||||
{
|
||||
return m_chars == other.m_chars;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE bool operator!= (const DeviceString& other) const
|
||||
OSL_HOSTDEVICE bool operator!=(const DeviceString& other) const
|
||||
{
|
||||
return m_chars != other.m_chars;
|
||||
}
|
||||
|
||||
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
|
||||
#ifdef __CUDA_ARCH__
|
||||
|
||||
OSL_HOSTDEVICE bool operator== (const size_t other) const
|
||||
OSL_HOSTDEVICE bool operator==(const size_t other) const
|
||||
{
|
||||
return hash() == other;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE bool operator!= (const size_t other) const
|
||||
OSL_HOSTDEVICE bool operator!=(const size_t other) const
|
||||
{
|
||||
return hash() != other;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE operator size_t() const { return hash(); }
|
||||
OSL_HOSTDEVICE operator size_t() const
|
||||
{
|
||||
return hash();
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
@@ -106,9 +109,9 @@ struct DeviceString {
|
||||
// macro is the same as the USTR macro defined in oslexec_pvt.h when compiling
|
||||
// for the host.
|
||||
#ifndef __CUDA_ARCH__
|
||||
# define HDSTR(cstr) (*((ustring *)&cstr))
|
||||
# define HDSTR(cstr) (*((ustring*)&cstr))
|
||||
#else
|
||||
#define HDSTR(cstr) (*((OSL::DeviceString*)&cstr))
|
||||
# define HDSTR(cstr) (*((OSL::DeviceString*)&cstr))
|
||||
#endif
|
||||
|
||||
|
||||
@@ -124,25 +127,22 @@ typedef DeviceString StringParam;
|
||||
|
||||
#ifdef __CUDA_ARCH__
|
||||
namespace DeviceStrings {
|
||||
#define STRDECL(str,var_name) \
|
||||
extern __device__ OSL_NAMESPACE::DeviceString var_name;
|
||||
#if OPTIX_VERSION < 70000
|
||||
# include <OSL/strdecls.h>
|
||||
#endif
|
||||
#undef STRDECL
|
||||
}
|
||||
# define STRDECL(str, var_name) \
|
||||
extern __device__ OSL_NAMESPACE::DeviceString var_name;
|
||||
# undef STRDECL
|
||||
} // namespace DeviceStrings
|
||||
#else
|
||||
# define STRING_PARAMS(x) StringParams::x
|
||||
# ifdef OSL_HOST_RS_BITCODE
|
||||
# define STRING_PARAMS(x) RS_##x
|
||||
# else
|
||||
# define STRING_PARAMS(x) StringParams::x
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
|
||||
#ifdef __CUDA_ARCH__
|
||||
#if OPTIX_VERSION < 70000
|
||||
namespace StringParams = OSL_NAMESPACE::DeviceStrings;
|
||||
#endif
|
||||
#else
|
||||
#ifndef __CUDA_ARCH__
|
||||
namespace StringParams = OSL_NAMESPACE::Strings;
|
||||
#endif
|
||||
|
||||
@@ -223,7 +223,7 @@ public:
|
||||
// delegating access to element storage to the DualStorage base class
|
||||
template<
|
||||
class T, // Base data type
|
||||
int PARTIALS=1 // Number of dimentions of partial derivs
|
||||
int PARTIALS=1 // Number of dimensions of partial derivs
|
||||
>
|
||||
class Dual : public DualStorage<T, PARTIALS> {
|
||||
static const int elements = PARTIALS+1; // main value + partials
|
||||
|
||||
+497
-406
File diff suppressed because it is too large
Load Diff
+38
-10
@@ -4,7 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <immintrin.h>
|
||||
#include <type_traits>
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
@@ -23,6 +22,8 @@ using std::countr_zero;
|
||||
|
||||
#elif OSL_INTEL_CLASSIC_COMPILER_VERSION
|
||||
|
||||
#include <immintrin.h>
|
||||
|
||||
OSL_FORCEINLINE int popcount(uint32_t x) noexcept { return _mm_popcnt_u32(x);}
|
||||
OSL_FORCEINLINE int popcount(uint64_t x) noexcept { return _mm_popcnt_u64(x); }
|
||||
OSL_FORCEINLINE int countr_zero(uint32_t x) noexcept { return _bit_scan_forward(x); }
|
||||
@@ -170,13 +171,22 @@ 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
|
||||
{
|
||||
@@ -229,7 +239,10 @@ 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
|
||||
{
|
||||
@@ -244,27 +257,39 @@ 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
|
||||
{
|
||||
@@ -298,7 +323,10 @@ 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>
|
||||
|
||||
@@ -959,7 +959,7 @@ Matrix22<T>::inverse (bool singExc) const
|
||||
{
|
||||
#ifndef __CUDA_ARCH__
|
||||
if (singExc)
|
||||
throw Imath::SingMatrixExc ("Cannot invert "
|
||||
throw std::invalid_argument ("Cannot invert "
|
||||
"singular matrix.");
|
||||
#endif
|
||||
return Matrix22();
|
||||
|
||||
@@ -109,8 +109,14 @@ 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
|
||||
@@ -140,4 +146,10 @@ struct OSLEXECPUBLIC ClosureAdd : public ClosureColor {
|
||||
const ClosureColor* closureB;
|
||||
};
|
||||
|
||||
/// Type for pointers to closures
|
||||
typedef ClosureColor* ClosureColorPtr;
|
||||
typedef ClosureComponent* ClosureComponentPtr;
|
||||
typedef ClosureAdd* ClosureAddPtr;
|
||||
typedef ClosureMul* ClosureMulPtr;
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
# include <OSL/Imathx/ImathVec.h>
|
||||
# include <OSL/Imathx/ImathMatrix.h>
|
||||
# include <OSL/Imathx/ImathColor.h>
|
||||
# include <OSL/matrix22.h>
|
||||
#endif
|
||||
|
||||
// We included the Imath files we needed, so set the OIIO_IMATH_H_INCLUDED
|
||||
@@ -32,16 +31,25 @@
|
||||
#define OIIO_IMATH_H_INCLUDED 1
|
||||
|
||||
|
||||
// The fmt library causes trouble for Cuda. Work around by disabling it from
|
||||
// oiio headers (OIIO <= 2.1) or telling fmt not to use the troublesome
|
||||
// int128 that Cuda doesn't understand (OIIO >= 2.2).
|
||||
// The fmt library causes trouble for Cuda. Work around by telling fmt not to
|
||||
// use the troublesome int128 that Cuda doesn't understand.
|
||||
#ifdef __CUDA_ARCH__
|
||||
# define OIIO_USE_FMT 0
|
||||
# ifndef FMT_USE_INT128
|
||||
# define FMT_USE_INT128 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// For OSL internal compilation only, get deprecation warnings if we call OIIO
|
||||
// methods that use the old printf style interface.
|
||||
#ifdef OSL_INTERNAL
|
||||
# ifdef OIIO_ERRORHANDLER_HIDE_PRINTF
|
||||
# define OIIO_ERRORHANDLER_HIDE_PRINTF 1
|
||||
# endif
|
||||
# ifdef OIIO_HIDE_FORMAT
|
||||
# define OIIO_HIDE_FORMAT 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// All the things we need from OpenImageIO
|
||||
#include <OpenImageIO/oiioversion.h>
|
||||
#include <OpenImageIO/errorhandler.h>
|
||||
@@ -82,11 +90,6 @@ using Color3 = Imath::Color3<Float>;
|
||||
using Matrix33 = Imath::Matrix33<Float>;
|
||||
using Matrix44 = Imath::Matrix44<Float>;
|
||||
|
||||
#if OSL_USING_IMATH >= 3
|
||||
using Matrix22 = Imath::Matrix22<Float>;
|
||||
#else
|
||||
using Matrix22 = Imathx::Matrix22<Float>;
|
||||
#endif
|
||||
|
||||
|
||||
/// Assume that we are dealing with OpenImageIO's texture system. It
|
||||
@@ -99,7 +102,7 @@ using OIIO::TextureOpt;
|
||||
// And some other things we borrow from OIIO...
|
||||
using OIIO::ErrorHandler;
|
||||
using OIIO::ustring;
|
||||
using OIIO::ustringHash;
|
||||
using OIIO::ustringhash;
|
||||
using OIIO::string_view;
|
||||
using OIIO::span;
|
||||
using OIIO::cspan;
|
||||
@@ -119,6 +122,16 @@ using OIIO::TypeFloat2;
|
||||
using OIIO::TypeVector2;
|
||||
using OIIO::TypeVector4;
|
||||
|
||||
using OIIO::Strutil::print;
|
||||
|
||||
template<typename Str, typename... Args>
|
||||
OSL_NODISCARD inline std::string
|
||||
fmtformat(const Str& fmt, Args&&... args)
|
||||
{
|
||||
return OIIO::Strutil::fmt::format(fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// N.B. SymArena is not really "configuration", but we cram it here for
|
||||
// lack of a better home.
|
||||
@@ -212,3 +225,30 @@ using ConstIndex = std::integral_constant<int, N>;
|
||||
|
||||
|
||||
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
|
||||
template<> struct hash<OSL::ustring> {
|
||||
std::size_t operator()(OSL::ustring u) const noexcept { return u.hash(); }
|
||||
};
|
||||
|
||||
template<> struct hash<OSL::ustringhash> {
|
||||
OSL_HOSTDEVICE constexpr std::size_t
|
||||
operator()(OSL::ustringhash u) const noexcept
|
||||
{
|
||||
return u.hash();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
// Not necessary once minimum OIIO defines operator< for ustringhash
|
||||
template<> struct less<OSL::ustringhash> {
|
||||
OSL_HOSTDEVICE constexpr bool operator()(OSL::ustringhash u,
|
||||
OSL::ustringhash v) const noexcept
|
||||
{
|
||||
return u.hash() < v.hash();
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
+291
-241
@@ -29,6 +29,12 @@ template<typename DataT, int WidthT> struct Wide;
|
||||
#endif
|
||||
|
||||
|
||||
/// RendererServices free function bitcode may reference global variables that
|
||||
/// only exist in the renderer's program space and won't automatically be
|
||||
/// found when referenced in JIT'd code inside OSL. A renderer may register
|
||||
/// the addresses of these global variables to allow valid JIT to occur.
|
||||
void OSLEXECPUBLIC
|
||||
register_JIT_Global(const char* global_var_name, void* global_var_addr);
|
||||
|
||||
/// Opaque pointer to whatever the renderer uses to represent a
|
||||
/// (potentially motion-blurred) coordinate transformation.
|
||||
@@ -44,73 +50,73 @@ namespace pvt {
|
||||
class ShadingSystemImpl;
|
||||
}
|
||||
|
||||
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
|
||||
# define STRINGIFY(x) XSTR(x)
|
||||
# define XSTR(x) #x
|
||||
# define STRING_PARAMS(x) UStringHash::Hash(STRINGIFY(x))
|
||||
#ifdef __CUDA_ARCH__
|
||||
# define STRING_PARAMS(x) UStringHash::Hash(__OSL_STRINGIFY(x))
|
||||
#else
|
||||
# define STRING_PARAMS(x) StringParams::x
|
||||
# define STRING_PARAMS(x) StringParams::x
|
||||
#endif
|
||||
|
||||
namespace Strings {
|
||||
#ifdef __CUDA_ARCH__
|
||||
# if OPTIX_VERSION >= 70000
|
||||
# define STRDECL(str,var_name)
|
||||
# define STRDECL(str, var_name)
|
||||
#else
|
||||
# define STRDECL(str,var_name) extern __device__ ustring var_name;
|
||||
#endif
|
||||
#else
|
||||
// Any strings referenced inside of a libsoslexec/wide/*.cpp
|
||||
// or liboslnoise/wide/*.cpp will need OSLEXECPUBLIC
|
||||
#define STRDECL(str,var_name) OSLEXECPUBLIC extern const ustring var_name;
|
||||
// Any strings referenced inside of a libsoslexec/wide/*.cpp
|
||||
// or liboslnoise/wide/*.cpp will need OSLEXECPUBLIC
|
||||
# define STRDECL(str, var_name) OSLEXECPUBLIC extern const ustring var_name;
|
||||
#endif
|
||||
#include <OSL/strdecls.h>
|
||||
#undef STRDECL
|
||||
}; // namespace Strings
|
||||
}; // namespace Strings
|
||||
|
||||
|
||||
|
||||
/// Description of where a symbol is located on the app side.
|
||||
struct SymLocationDesc {
|
||||
public:
|
||||
using offset_t = int64_t;
|
||||
using stride_t = int64_t;
|
||||
using offset_t = int64_t;
|
||||
using stride_t = int64_t;
|
||||
static const int64_t AutoStride = std::numeric_limits<stride_t>::min();
|
||||
|
||||
SymLocationDesc() {}
|
||||
SymLocationDesc(string_view name, TypeDesc type, bool derivs = false,
|
||||
SymArena arena = SymArena::Heap, offset_t offset = -1,
|
||||
stride_t stride = AutoStride)
|
||||
: name(name), type(type), offset(offset),
|
||||
stride(stride == AutoStride ? type.size() : stride),
|
||||
arena(arena), derivs(derivs)
|
||||
{}
|
||||
: name(name)
|
||||
, type(type)
|
||||
, offset(offset)
|
||||
, stride(stride == AutoStride ? type.size() : stride)
|
||||
, arena(arena)
|
||||
, derivs(derivs)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(ustring n) const { return name == n; }
|
||||
friend bool operator<(ustring n, const SymLocationDesc& sld) {
|
||||
friend bool operator<(ustring n, const SymLocationDesc& sld)
|
||||
{
|
||||
return n < sld.name;
|
||||
}
|
||||
friend bool operator<(const SymLocationDesc& sld, ustring n) {
|
||||
friend bool operator<(const SymLocationDesc& sld, ustring n)
|
||||
{
|
||||
return sld.name < n;
|
||||
}
|
||||
|
||||
ustring name; ///< Name of the symbol
|
||||
TypeDesc type; ///< Data type of the symbol
|
||||
offset_t offset = -1; ///< Offset from arena base for point 0 (batched mode assumes userdata at point 0 is readable)
|
||||
stride_t stride = AutoStride; ///< Stride in bytes between shade points
|
||||
SymArena arena = SymArena::Heap; ///< Memory arena type for the symbol
|
||||
bool derivs = false; ///< Space allocated for derivs also
|
||||
ustring name; ///< Name of the symbol
|
||||
TypeDesc type; ///< Data type of the symbol
|
||||
offset_t offset
|
||||
= -1; ///< Offset from arena base for point 0 (batched mode assumes userdata at point 0 is readable)
|
||||
stride_t stride = AutoStride; ///< Stride in bytes between shade points
|
||||
SymArena arena = SymArena::Heap; ///< Memory arena type for the symbol
|
||||
bool derivs = false; ///< Space allocated for derivs also
|
||||
};
|
||||
|
||||
|
||||
|
||||
class OSLEXECPUBLIC ShadingSystem
|
||||
{
|
||||
class OSLEXECPUBLIC ShadingSystem {
|
||||
public:
|
||||
ShadingSystem (RendererServices *renderer=NULL,
|
||||
TextureSystem *texturesystem=NULL,
|
||||
ErrorHandler *err=NULL);
|
||||
~ShadingSystem ();
|
||||
ShadingSystem(RendererServices* renderer = NULL,
|
||||
TextureSystem* texturesystem = NULL,
|
||||
ErrorHandler* err = NULL);
|
||||
~ShadingSystem();
|
||||
|
||||
/// Set an attribute controlling the shading system. Return true
|
||||
/// if the name and type were recognized and the attrib was set.
|
||||
@@ -137,10 +143,11 @@ public:
|
||||
/// int no_noise Replace noise with constant value. (0)
|
||||
/// int no_pointcloud Skip pointcloud lookups. (0)
|
||||
/// int exec_repeat How many times to run each group (1).
|
||||
/// int opt_warnings Warn on certain failure to runtime-optimize
|
||||
/// certain shader constructs. (0)
|
||||
/// int gpu_opt_error Consider a hard error if certain shader
|
||||
/// constructs cannot be optimized away. (0)
|
||||
/// int opt_warnings Warn on failure to runtime-optimize certain
|
||||
/// shader constructs. (0)
|
||||
/// int gpu_opt_error Issue a hard error if certain shader
|
||||
/// constructs cannot be optimized away, which
|
||||
/// have no way to run on GPU. (0)
|
||||
/// 2. Attributes that should be set by applications/renderers that
|
||||
/// incorporate OSL:
|
||||
/// string commonspace Name of "common" coord system ("world")
|
||||
@@ -224,8 +231,7 @@ public:
|
||||
/// for debugging. (0)
|
||||
/// int llvm_dumpasm Print the CPU assembly code from the JIT (0)
|
||||
/// string llvm_prune_ir_strategy Strategy for pruning unnecessary
|
||||
/// IR (choices: "prune" [default],
|
||||
/// "internalize", or "none").
|
||||
/// IR (choices: "prune" [default], or "none").
|
||||
/// int max_local_mem_KB Error if shader group needs more than this
|
||||
/// much local storage to execute (1024K)
|
||||
/// string debug_groupname Name of shader group -- debug only this one
|
||||
@@ -240,23 +246,27 @@ public:
|
||||
/// 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!
|
||||
bool attribute (string_view name, TypeDesc type, const void *val);
|
||||
bool attribute(string_view name, TypeDesc type, const void* val);
|
||||
|
||||
// Shortcuts for common types
|
||||
bool attribute (string_view name, int val) {
|
||||
return attribute (name, TypeDesc::INT, &val);
|
||||
bool attribute(string_view name, int val)
|
||||
{
|
||||
return attribute(name, TypeDesc::INT, &val);
|
||||
}
|
||||
bool attribute (string_view name, float val) {
|
||||
return attribute (name, TypeDesc::FLOAT, &val);
|
||||
bool attribute(string_view name, float val)
|
||||
{
|
||||
return attribute(name, TypeDesc::FLOAT, &val);
|
||||
}
|
||||
bool attribute (string_view name, double val) {
|
||||
float f = (float) val;
|
||||
return attribute (name, TypeDesc::FLOAT, &f);
|
||||
bool attribute(string_view name, double val)
|
||||
{
|
||||
float f = (float)val;
|
||||
return attribute(name, TypeDesc::FLOAT, &f);
|
||||
}
|
||||
bool attribute (string_view name, string_view val) {
|
||||
bool attribute(string_view name, string_view val)
|
||||
{
|
||||
std::string valstr(val);
|
||||
const char *s = valstr.c_str();
|
||||
return attribute (name, TypeDesc::STRING, &s);
|
||||
const char* s = valstr.c_str();
|
||||
return attribute(name, TypeDesc::STRING, &s);
|
||||
}
|
||||
|
||||
|
||||
@@ -272,22 +282,26 @@ public:
|
||||
/// called unconditionally.
|
||||
/// int exec_repeat How many times to run the group (1).
|
||||
///
|
||||
bool attribute (ShaderGroup *group, string_view name,
|
||||
TypeDesc type, const void *val);
|
||||
bool attribute (ShaderGroup *group, string_view name, int val) {
|
||||
return attribute (group, name, TypeDesc::INT, &val);
|
||||
bool attribute(ShaderGroup* group, string_view name, TypeDesc type,
|
||||
const void* val);
|
||||
bool attribute(ShaderGroup* group, string_view name, int val)
|
||||
{
|
||||
return attribute(group, name, TypeDesc::INT, &val);
|
||||
}
|
||||
bool attribute (ShaderGroup *group, string_view name, float val) {
|
||||
return attribute (group, name, TypeDesc::FLOAT, &val);
|
||||
bool attribute(ShaderGroup* group, string_view name, float val)
|
||||
{
|
||||
return attribute(group, name, TypeDesc::FLOAT, &val);
|
||||
}
|
||||
bool attribute (ShaderGroup *group, string_view name, double val) {
|
||||
float f = (float) val;
|
||||
return attribute (group, name, TypeDesc::FLOAT, &f);
|
||||
bool attribute(ShaderGroup* group, string_view name, double val)
|
||||
{
|
||||
float f = (float)val;
|
||||
return attribute(group, name, TypeDesc::FLOAT, &f);
|
||||
}
|
||||
bool attribute (ShaderGroup *group, string_view name, string_view val) {
|
||||
bool attribute(ShaderGroup* group, string_view name, string_view val)
|
||||
{
|
||||
std::string valstr(val);
|
||||
const char *s = valstr.c_str();
|
||||
return attribute (group, name, TypeDesc::STRING, &s);
|
||||
const char* s = valstr.c_str();
|
||||
return attribute(group, name, TypeDesc::STRING, &s);
|
||||
}
|
||||
|
||||
/// Get the named attribute of the ShadingSystem, store it in `*val`.
|
||||
@@ -317,23 +331,26 @@ public:
|
||||
/// library build dependencies and their versions (for example,
|
||||
/// "OIIO-2.3.0,LLVM-10.0.0,OpenEXR-2.5.0").
|
||||
///
|
||||
bool getattribute (string_view name, TypeDesc type, void *val);
|
||||
bool getattribute(string_view name, TypeDesc type, void* val);
|
||||
|
||||
/// Shortcut getattribute() for retrieving a single integer.
|
||||
/// The value is placed in `val`, and the function returns `true` if the
|
||||
/// attribute was found and was legally convertible to an int.
|
||||
bool getattribute (string_view name, int &val) {
|
||||
return getattribute (name, TypeDesc::INT, &val);
|
||||
bool getattribute(string_view name, int& val)
|
||||
{
|
||||
return getattribute(name, TypeDesc::INT, &val);
|
||||
}
|
||||
/// Shortcut getattribute() for retrieving a single float.
|
||||
/// The value is placed in `val`, and the function returns `true` if the
|
||||
/// attribute was found and was legally convertible to a float.
|
||||
bool getattribute (string_view name, float &val) {
|
||||
return getattribute (name, TypeDesc::FLOAT, &val);
|
||||
bool getattribute(string_view name, float& val)
|
||||
{
|
||||
return getattribute(name, TypeDesc::FLOAT, &val);
|
||||
}
|
||||
bool getattribute (string_view name, double &val) {
|
||||
bool getattribute(string_view name, double& val)
|
||||
{
|
||||
float f;
|
||||
bool ok = getattribute (name, TypeDesc::FLOAT, &f);
|
||||
bool ok = getattribute(name, TypeDesc::FLOAT, &f);
|
||||
if (ok)
|
||||
val = f;
|
||||
return ok;
|
||||
@@ -341,21 +358,24 @@ public:
|
||||
/// Shortcut getattribute() for retrieving a single string as a
|
||||
/// `const char*`. The value is placed in `val`, and the function
|
||||
/// returns `true` if the attribute was found.
|
||||
bool getattribute (string_view name, char **val) {
|
||||
return getattribute (name, TypeDesc::STRING, val);
|
||||
bool getattribute(string_view name, char** val)
|
||||
{
|
||||
return getattribute(name, TypeDesc::STRING, val);
|
||||
}
|
||||
/// Shortcut getattribute() for retrieving a single string as a
|
||||
/// `ustring`. The value is placed in `val`, and the function returns
|
||||
/// `true` if the attribute was found.
|
||||
bool getattribute (string_view name, ustring &val) {
|
||||
return getattribute (name, TypeDesc::STRING, (char **)&val);
|
||||
bool getattribute(string_view name, ustring& val)
|
||||
{
|
||||
return getattribute(name, TypeDesc::STRING, (char**)&val);
|
||||
}
|
||||
/// Shortcut getattribute() for retrieving a single string as a
|
||||
/// `std::string`. The value is placed in `val`, and the function
|
||||
/// returns `true` if the attribute was found.
|
||||
bool getattribute (string_view name, std::string &val) {
|
||||
const char *s = NULL;
|
||||
bool ok = getattribute (name, TypeDesc::STRING, &s);
|
||||
bool getattribute(string_view name, std::string& val)
|
||||
{
|
||||
const char* s = NULL;
|
||||
bool ok = getattribute(name, TypeDesc::STRING, &s);
|
||||
if (ok)
|
||||
val = s;
|
||||
return ok;
|
||||
@@ -426,31 +446,37 @@ public:
|
||||
/// 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!
|
||||
bool getattribute (ShaderGroup *group, string_view name,
|
||||
TypeDesc type, void *val);
|
||||
bool getattribute(ShaderGroup* group, string_view name, TypeDesc type,
|
||||
void* val);
|
||||
// Shortcuts for common types
|
||||
bool getattribute (ShaderGroup *group, string_view name, int &val) {
|
||||
return getattribute (group, name, TypeDesc::INT, &val);
|
||||
bool getattribute(ShaderGroup* group, string_view name, int& val)
|
||||
{
|
||||
return getattribute(group, name, TypeDesc::INT, &val);
|
||||
}
|
||||
bool getattribute (ShaderGroup *group, string_view name, float &val) {
|
||||
return getattribute (group, name, TypeDesc::FLOAT, &val);
|
||||
bool getattribute(ShaderGroup* group, string_view name, float& val)
|
||||
{
|
||||
return getattribute(group, name, TypeDesc::FLOAT, &val);
|
||||
}
|
||||
bool getattribute (ShaderGroup *group, string_view name, double &val) {
|
||||
bool getattribute(ShaderGroup* group, string_view name, double& val)
|
||||
{
|
||||
float f;
|
||||
bool ok = getattribute (group, name, TypeDesc::FLOAT, &f);
|
||||
bool ok = getattribute(group, name, TypeDesc::FLOAT, &f);
|
||||
if (ok)
|
||||
val = f;
|
||||
return ok;
|
||||
}
|
||||
bool getattribute (ShaderGroup *group, string_view name, char **val) {
|
||||
return getattribute (group, name, TypeDesc::STRING, val);
|
||||
bool getattribute(ShaderGroup* group, string_view name, char** val)
|
||||
{
|
||||
return getattribute(group, name, TypeDesc::STRING, val);
|
||||
}
|
||||
bool getattribute (ShaderGroup *group, string_view name, ustring &val) {
|
||||
return getattribute (group, name, TypeDesc::STRING, (char **)&val);
|
||||
bool getattribute(ShaderGroup* group, string_view name, ustring& val)
|
||||
{
|
||||
return getattribute(group, name, TypeDesc::STRING, (char**)&val);
|
||||
}
|
||||
bool getattribute (ShaderGroup *group, string_view name, std::string &val) {
|
||||
const char *s = NULL;
|
||||
bool ok = getattribute (group, name, TypeDesc::STRING, &s);
|
||||
bool getattribute(ShaderGroup* group, string_view name, std::string& val)
|
||||
{
|
||||
const char* s = NULL;
|
||||
bool ok = getattribute(group, name, TypeDesc::STRING, &s);
|
||||
if (ok)
|
||||
val = s;
|
||||
return ok;
|
||||
@@ -459,8 +485,7 @@ public:
|
||||
|
||||
/// Load compiled shader (oso) from a memory buffer, overriding
|
||||
/// shader lookups in the shader search path
|
||||
bool LoadMemoryCompiledShader (string_view shadername,
|
||||
string_view buffer);
|
||||
bool LoadMemoryCompiledShader(string_view shadername, string_view buffer);
|
||||
|
||||
// The basic sequence for declaring a shader group looks like this:
|
||||
// ShadingSystem *ss = ...;
|
||||
@@ -486,7 +511,7 @@ public:
|
||||
|
||||
/// Signal the start of a new shader group. The return value is a
|
||||
/// reference-counted opaque handle to the ShaderGroup.
|
||||
ShaderGroupRef ShaderGroupBegin (string_view groupname = string_view());
|
||||
ShaderGroupRef ShaderGroupBegin(string_view groupname = string_view());
|
||||
|
||||
/// Alternate way to specify a shader group. The group specification
|
||||
/// syntax looks like this: (as a string, all whitespace is equivalent):
|
||||
@@ -496,13 +521,13 @@ public:
|
||||
/// For the sake of easy assembling on command lines, a comma ',' may
|
||||
/// substitute for the semicolon as a separator, and the last separator
|
||||
/// before the end of the string is optional.
|
||||
ShaderGroupRef ShaderGroupBegin (string_view groupname,
|
||||
string_view shaderusage,
|
||||
string_view groupspec = string_view());
|
||||
ShaderGroupRef ShaderGroupBegin(string_view groupname,
|
||||
string_view shaderusage,
|
||||
string_view groupspec = string_view());
|
||||
|
||||
/// Signal the end of a new shader group.
|
||||
///
|
||||
bool ShaderGroupEnd (ShaderGroup& group);
|
||||
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
|
||||
@@ -511,32 +536,37 @@ public:
|
||||
/// 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.
|
||||
bool Parameter (ShaderGroup& group, string_view name, TypeDesc t,
|
||||
const void *val, bool lockgeom=true);
|
||||
bool Parameter(ShaderGroup& group, string_view name, TypeDesc t,
|
||||
const void* val, bool lockgeom = true);
|
||||
// Shortcuts for param passing a single int, float, or string.
|
||||
bool Parameter (ShaderGroup& group, string_view name,
|
||||
int val, bool lockgeom=true) {
|
||||
return Parameter (group, name, TypeDesc::INT, &val, lockgeom);
|
||||
bool Parameter(ShaderGroup& group, string_view name, int val,
|
||||
bool lockgeom = true)
|
||||
{
|
||||
return Parameter(group, name, TypeDesc::INT, &val, lockgeom);
|
||||
}
|
||||
bool Parameter (ShaderGroup& group, string_view name,
|
||||
float val, bool lockgeom=true) {
|
||||
return Parameter (group, name, TypeDesc::FLOAT, &val, lockgeom);
|
||||
bool Parameter(ShaderGroup& group, string_view name, float val,
|
||||
bool lockgeom = true)
|
||||
{
|
||||
return Parameter(group, name, TypeDesc::FLOAT, &val, lockgeom);
|
||||
}
|
||||
bool Parameter (ShaderGroup& group, string_view name,
|
||||
const std::string& val, bool lockgeom=true) {
|
||||
const char *s = val.c_str();
|
||||
return Parameter (group, name, TypeDesc::STRING, &s, lockgeom);
|
||||
bool Parameter(ShaderGroup& group, string_view name, const std::string& val,
|
||||
bool lockgeom = true)
|
||||
{
|
||||
const char* s = val.c_str();
|
||||
return Parameter(group, name, TypeDesc::STRING, &s, lockgeom);
|
||||
}
|
||||
bool Parameter (ShaderGroup& group, string_view name,
|
||||
ustring val, bool lockgeom=true) {
|
||||
return Parameter (group, name, TypeDesc::STRING, (const char**)&val, lockgeom);
|
||||
bool Parameter(ShaderGroup& group, string_view name, ustring val,
|
||||
bool lockgeom = true)
|
||||
{
|
||||
return Parameter(group, name, TypeDesc::STRING, (const char**)&val,
|
||||
lockgeom);
|
||||
}
|
||||
|
||||
/// Append a new shader instance onto the specified group. The shader
|
||||
/// instance will get any pending parameters that were set by
|
||||
/// Parameter() calls since the last Shader() call for the group.
|
||||
bool Shader (ShaderGroup& group, string_view shaderusage,
|
||||
string_view shadername, string_view layername);
|
||||
bool Shader(ShaderGroup& group, string_view shaderusage,
|
||||
string_view shadername, string_view layername);
|
||||
|
||||
/// Connect two shaders within the specified group. The source layer
|
||||
/// must be *upstream* of down destination layer (i.e. source must be
|
||||
@@ -552,9 +582,9 @@ public:
|
||||
/// `ConnectShaders (group, "lay1", "mycolorout[2]",
|
||||
/// "lay2", "myfloatinput")`
|
||||
///
|
||||
bool ConnectShaders (ShaderGroup &group,
|
||||
string_view srclayer, string_view srcparam,
|
||||
string_view dstlayer, string_view dstparam);
|
||||
bool ConnectShaders(ShaderGroup& group, string_view srclayer,
|
||||
string_view srcparam, string_view dstlayer,
|
||||
string_view dstparam);
|
||||
|
||||
/// Replace a parameter value in a previously-declared shader group.
|
||||
/// This is meant to called after the ShaderGroupBegin/End, but will
|
||||
@@ -563,27 +593,30 @@ public:
|
||||
/// 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.
|
||||
bool ReParameter (ShaderGroup &group,
|
||||
string_view layername, string_view paramname,
|
||||
TypeDesc type, const void *val);
|
||||
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.
|
||||
bool ReParameter (ShaderGroup &group, string_view layername,
|
||||
string_view paramname, int val) {
|
||||
return ReParameter (group, layername, paramname, TypeDesc::INT, &val);
|
||||
bool ReParameter(ShaderGroup& group, string_view layername,
|
||||
string_view paramname, int val)
|
||||
{
|
||||
return ReParameter(group, layername, paramname, TypeDesc::INT, &val);
|
||||
}
|
||||
bool ReParameter (ShaderGroup &group, string_view layername,
|
||||
string_view paramname, float val) {
|
||||
return ReParameter (group, layername, paramname, TypeDesc::FLOAT, &val);
|
||||
bool ReParameter(ShaderGroup& group, string_view layername,
|
||||
string_view paramname, float val)
|
||||
{
|
||||
return ReParameter(group, layername, paramname, TypeDesc::FLOAT, &val);
|
||||
}
|
||||
bool ReParameter (ShaderGroup &group, string_view layername,
|
||||
string_view paramname, const std::string& val) {
|
||||
const char *s = val.c_str();
|
||||
return ReParameter (group, layername, paramname, TypeDesc::STRING, &s);
|
||||
bool ReParameter(ShaderGroup& group, string_view layername,
|
||||
string_view paramname, const std::string& val)
|
||||
{
|
||||
const char* s = val.c_str();
|
||||
return ReParameter(group, layername, paramname, TypeDesc::STRING, &s);
|
||||
}
|
||||
bool ReParameter (ShaderGroup &group, string_view layername,
|
||||
string_view paramname, ustring val) {
|
||||
return ReParameter (group, layername, paramname, TypeDesc::STRING,
|
||||
(const char**)&val);
|
||||
bool ReParameter(ShaderGroup& group, string_view layername,
|
||||
string_view paramname, ustring val)
|
||||
{
|
||||
return ReParameter(group, layername, paramname, TypeDesc::STRING,
|
||||
(const char**)&val);
|
||||
}
|
||||
|
||||
// Non-threadsafe versions of Parameter, Shader, ConnectShaders, and
|
||||
@@ -594,13 +627,13 @@ public:
|
||||
// concurrently). If there is any doubt about that, use the versions
|
||||
// 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);
|
||||
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);
|
||||
bool Parameter(string_view name, TypeDesc t, const void* val,
|
||||
bool lockgeom = true);
|
||||
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);
|
||||
|
||||
/// Create a per-thread data needed for shader execution. It's very
|
||||
/// important for the app to never use a PerThreadInfo from more than
|
||||
@@ -608,11 +641,11 @@ public:
|
||||
/// for each renderer thread), and destroy it with destroy_thread_info
|
||||
/// when the thread terminates (and before the ShadingSystem is
|
||||
/// destroyed).
|
||||
PerThreadInfo * create_thread_info();
|
||||
PerThreadInfo* create_thread_info();
|
||||
|
||||
/// Destroy a PerThreadInfo that was allocated by
|
||||
/// create_thread_info().
|
||||
void destroy_thread_info (PerThreadInfo *threadinfo);
|
||||
void destroy_thread_info(PerThreadInfo* threadinfo);
|
||||
|
||||
/// Get a ShadingContext that we can use. The context is specific to a
|
||||
/// renderer thread, and should never be passed between or shared by
|
||||
@@ -620,12 +653,13 @@ public:
|
||||
/// thread-specific pointer created by create_thread_info. The context
|
||||
/// can be used to shade many points; a typical usage is to allocate
|
||||
/// just one context per thread and use it for the whole run.
|
||||
ShadingContext *get_context (PerThreadInfo *threadinfo,
|
||||
TextureSystem::Perthread *texture_threadinfo=NULL);
|
||||
ShadingContext*
|
||||
get_context(PerThreadInfo* threadinfo,
|
||||
TextureSystem::Perthread* texture_threadinfo = NULL);
|
||||
|
||||
/// Return a ShadingContext to the pool.
|
||||
///
|
||||
void release_context (ShadingContext *ctx);
|
||||
void release_context(ShadingContext* ctx);
|
||||
|
||||
/// Execute the shader group in this context on shading point
|
||||
/// `shadeindex`. If ctx is nullptr, then execute will request one
|
||||
@@ -634,19 +668,30 @@ 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,
|
||||
bool execute(ShadingContext& ctx, ShaderGroup& group, 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.
|
||||
#if 0 // TODO in future PR
|
||||
bool execute(ShadingContext& ctx, ShaderGroup& group, OpaqueShadingStateUniformPtr ssu,
|
||||
int shadeindex_begin_at, int shadeindex_end_before
|
||||
void* userdata_base_ptr,
|
||||
void* output_base_ptr, bool run = true);
|
||||
#endif
|
||||
|
||||
// DEPRECATED(2.0): no shadeindex or base pointers
|
||||
bool execute (ShadingContext &ctx, ShaderGroup &group,
|
||||
ShaderGlobals &globals, bool run=true) {
|
||||
bool execute(ShadingContext& ctx, ShaderGroup& group,
|
||||
ShaderGlobals& globals, bool run = true)
|
||||
{
|
||||
return execute(ctx, group, 0, globals, nullptr, nullptr, run);
|
||||
}
|
||||
|
||||
// DEPRECATED(2.0): ctx pointer
|
||||
bool execute (ShadingContext *ctx, ShaderGroup &group,
|
||||
ShaderGlobals &globals, bool run=true) {
|
||||
bool execute(ShadingContext* ctx, ShaderGroup& group,
|
||||
ShaderGlobals& globals, bool run = true)
|
||||
{
|
||||
return execute(*ctx, group, globals, run);
|
||||
}
|
||||
|
||||
@@ -658,12 +703,13 @@ 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 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) {
|
||||
bool execute_init(ShadingContext& ctx, ShaderGroup& group,
|
||||
ShaderGlobals& globals, bool run = true)
|
||||
{
|
||||
return execute_init(ctx, group, 0, globals, nullptr, nullptr, run);
|
||||
}
|
||||
|
||||
@@ -672,41 +718,44 @@ 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, ShaderGlobals &globals,
|
||||
void* userdata_base_ptr, void* output_base_ptr,
|
||||
int layernumber);
|
||||
bool execute_layer(ShadingContext& ctx, 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, ShaderGlobals &globals,
|
||||
void* userdata_base_ptr, void* output_base_ptr,
|
||||
ustring layername);
|
||||
bool execute_layer(ShadingContext& ctx, 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, ShaderGlobals &globals,
|
||||
void* userdata_base_ptr, void* output_base_ptr,
|
||||
const ShaderSymbol *symbol);
|
||||
bool execute_layer(ShadingContext& ctx, int shadeindex,
|
||||
ShaderGlobals& globals, void* userdata_base_ptr,
|
||||
void* output_base_ptr, const ShaderSymbol* symbol);
|
||||
|
||||
// DEPRECATED(2.0): no shadeindex or base pointers
|
||||
bool execute_layer (ShadingContext &ctx, ShaderGlobals &globals,
|
||||
int layernumber) {
|
||||
bool execute_layer(ShadingContext& ctx, ShaderGlobals& globals,
|
||||
int layernumber)
|
||||
{
|
||||
return execute_layer(ctx, 0, globals, nullptr, nullptr, layernumber);
|
||||
}
|
||||
bool execute_layer (ShadingContext &ctx, ShaderGlobals &globals,
|
||||
ustring layername) {
|
||||
bool execute_layer(ShadingContext& ctx, ShaderGlobals& globals,
|
||||
ustring layername)
|
||||
{
|
||||
return execute_layer(ctx, 0, globals, nullptr, nullptr, layername);
|
||||
}
|
||||
bool execute_layer (ShadingContext &ctx, ShaderGlobals &globals,
|
||||
const ShaderSymbol *symbol) {
|
||||
bool execute_layer(ShadingContext& ctx, ShaderGlobals& globals,
|
||||
const ShaderSymbol* symbol)
|
||||
{
|
||||
return execute_layer(ctx, 0, globals, nullptr, nullptr, symbol);
|
||||
}
|
||||
|
||||
/// Signify that the context is done with the current execution of the
|
||||
/// group that was kicked off by execute_init and one or more calls to
|
||||
/// execute_layer.
|
||||
bool execute_cleanup (ShadingContext &ctx);
|
||||
bool execute_cleanup(ShadingContext& ctx);
|
||||
|
||||
/// Find the named layer within a group and return its index, or -1
|
||||
/// if no such named layer exists.
|
||||
int find_layer (const ShaderGroup &group, ustring layername) const;
|
||||
int find_layer(const ShaderGroup& group, ustring layername) const;
|
||||
|
||||
/// Get a raw pointer to a named symbol (such as you'd need to pull
|
||||
/// out the value of an output parameter). ctx is the shading
|
||||
@@ -723,10 +772,10 @@ public:
|
||||
///
|
||||
/// These are considered somewhat deprecated, in favor of using
|
||||
/// find_symbol(), symbol_typedesc(), and symbol_address().
|
||||
const void* get_symbol (const ShadingContext &ctx, ustring layername,
|
||||
ustring symbolname, TypeDesc &type) const;
|
||||
const void* get_symbol (const ShadingContext &ctx, ustring symbolname,
|
||||
TypeDesc &type) const;
|
||||
const void* get_symbol(const ShadingContext& ctx, ustring layername,
|
||||
ustring symbolname, TypeDesc& type) const;
|
||||
const void* get_symbol(const ShadingContext& ctx, ustring symbolname,
|
||||
TypeDesc& type) const;
|
||||
|
||||
/// Search for an output symbol by name (and optionally, layer) within
|
||||
/// the optimized shader group. If the symbol is found, return an opaque
|
||||
@@ -740,22 +789,22 @@ public:
|
||||
/// separately, or by concatenating "layername.symbolname", but note
|
||||
/// that the latter will involve string manipulation inside find_symbol
|
||||
/// and is much more expensive than specifying them separately.
|
||||
const ShaderSymbol* find_symbol (const ShaderGroup &group,
|
||||
ustring layername, ustring symbolname) const;
|
||||
const ShaderSymbol* find_symbol (const ShaderGroup &group,
|
||||
ustring symbolname) const;
|
||||
const ShaderSymbol* find_symbol(const ShaderGroup& group, ustring layername,
|
||||
ustring symbolname) const;
|
||||
const ShaderSymbol* find_symbol(const ShaderGroup& group,
|
||||
ustring symbolname) const;
|
||||
|
||||
/// Given an opaque ShaderSymbol*, return the TypeDesc describing it.
|
||||
/// Note that a closure will end up with a TypeDesc::UNKNOWN value.
|
||||
TypeDesc symbol_typedesc (const ShaderSymbol *sym) const;
|
||||
TypeDesc symbol_typedesc(const ShaderSymbol* sym) const;
|
||||
|
||||
/// Given a context (that has executed a shader) and an opaque
|
||||
/// ShaderSymbol*, return the actual memory address where the value of
|
||||
/// the symbol resides within the heap memory of the context. This
|
||||
/// is only valid for the shader execution that had happened immediately
|
||||
/// prior for this context, but it is a very inexpensive operation.
|
||||
const void* symbol_address (const ShadingContext &ctx,
|
||||
const ShaderSymbol *sym) const;
|
||||
const void* symbol_address(const ShadingContext& ctx,
|
||||
const ShaderSymbol* sym) const;
|
||||
|
||||
#if OSL_USE_BATCHED
|
||||
/// Based on currently set attributes for llvm_jit_target and
|
||||
@@ -766,54 +815,56 @@ public:
|
||||
/// Returns true if supported, false otherwise
|
||||
bool configure_batch_execution_at(int width);
|
||||
|
||||
template<int WidthT>
|
||||
class OSLEXECPUBLIC BatchedExecutor {
|
||||
ShadingSystem & m_shading_system;
|
||||
template<int WidthT> class OSLEXECPUBLIC BatchedExecutor {
|
||||
ShadingSystem& m_shading_system;
|
||||
|
||||
public:
|
||||
explicit OSL_FORCEINLINE BatchedExecutor(ShadingSystem & ss)
|
||||
:m_shading_system(ss)
|
||||
{}
|
||||
explicit OSL_FORCEINLINE BatchedExecutor(ShadingSystem& ss)
|
||||
: m_shading_system(ss)
|
||||
{
|
||||
}
|
||||
OSL_FORCEINLINE BatchedExecutor(const BatchedExecutor&) = default;
|
||||
|
||||
/// Ensure that the group has been JITed.
|
||||
void jit_group (ShaderGroup *group, ShadingContext *ctx);
|
||||
void jit_group(ShaderGroup* group, ShadingContext* ctx);
|
||||
|
||||
/// If option "greedyjit" was set, this call will trigger all
|
||||
/// shader groups that have not yet been compiled to do so with the
|
||||
/// specified number of threads (0 means use all available HW cores).
|
||||
void jit_all_groups (int nthreads=0);
|
||||
void jit_all_groups(int nthreads = 0);
|
||||
|
||||
bool execute (ShadingContext &ctx, ShaderGroup &group, int batch_size,
|
||||
Wide<const int, WidthT> wide_shadeindex,
|
||||
BatchedShaderGlobals<WidthT> &globals_batch,
|
||||
void* userdata_base_ptr,
|
||||
void* output_base_ptr, bool run=true);
|
||||
bool execute(ShadingContext& ctx, ShaderGroup& group, int batch_size,
|
||||
Wide<const int, WidthT> wide_shadeindex,
|
||||
BatchedShaderGlobals<WidthT>& globals_batch,
|
||||
void* userdata_base_ptr, void* output_base_ptr,
|
||||
bool run = true);
|
||||
|
||||
bool execute_init (ShadingContext &ctx, ShaderGroup &group, int batch_size,
|
||||
bool execute_init(ShadingContext& ctx, ShaderGroup& group,
|
||||
int batch_size,
|
||||
Wide<const int, WidthT> wide_shadeindex,
|
||||
BatchedShaderGlobals<WidthT>& globals_batch,
|
||||
void* userdata_base_ptr, void* output_base_ptr,
|
||||
bool run = true);
|
||||
|
||||
bool execute_layer(ShadingContext& ctx, int batch_size,
|
||||
Wide<const int, WidthT> wide_shadeindex,
|
||||
BatchedShaderGlobals<WidthT> &globals_batch,
|
||||
void* userdata_base_ptr,
|
||||
void* output_base_ptr, bool run=true);
|
||||
|
||||
bool execute_layer (ShadingContext &ctx, int batch_size,
|
||||
Wide<const int, WidthT> wide_shadeindex,
|
||||
BatchedShaderGlobals<WidthT> &globals_batch,
|
||||
void* userdata_base_ptr,
|
||||
void* output_base_ptr, int layernumber);
|
||||
bool execute_layer (ShadingContext &ctx, int batch_size,
|
||||
Wide<const int, WidthT> wide_shadeindex,
|
||||
BatchedShaderGlobals<WidthT> &globals_batch,
|
||||
void* userdata_base_ptr,
|
||||
void* output_base_ptr, ustring layername);
|
||||
bool execute_layer (ShadingContext &ctx, int batch_size,
|
||||
Wide<const int, WidthT> wide_shadeindex,
|
||||
BatchedShaderGlobals<WidthT> &globals_batch,
|
||||
void* userdata_base_ptr,
|
||||
void* output_base_ptr, const ShaderSymbol *symbol);
|
||||
BatchedShaderGlobals<WidthT>& globals_batch,
|
||||
void* userdata_base_ptr, void* output_base_ptr,
|
||||
int layernumber);
|
||||
bool execute_layer(ShadingContext& ctx, int batch_size,
|
||||
Wide<const int, WidthT> wide_shadeindex,
|
||||
BatchedShaderGlobals<WidthT>& globals_batch,
|
||||
void* userdata_base_ptr, void* output_base_ptr,
|
||||
ustring layername);
|
||||
bool execute_layer(ShadingContext& ctx, int batch_size,
|
||||
Wide<const int, WidthT> wide_shadeindex,
|
||||
BatchedShaderGlobals<WidthT>& globals_batch,
|
||||
void* userdata_base_ptr, void* output_base_ptr,
|
||||
const ShaderSymbol* symbol);
|
||||
};
|
||||
|
||||
template<int WidthT>
|
||||
OSL_FORCEINLINE BatchedExecutor<WidthT> batched() {
|
||||
template<int WidthT> OSL_FORCEINLINE BatchedExecutor<WidthT> batched()
|
||||
{
|
||||
return BatchedExecutor<WidthT>(*this);
|
||||
}
|
||||
#endif
|
||||
@@ -821,37 +872,36 @@ public:
|
||||
|
||||
/// Return the statistics output as a huge string.
|
||||
///
|
||||
std::string getstats (int level=1) const;
|
||||
std::string getstats(int level = 1) const;
|
||||
|
||||
void register_closure (string_view name, int id, const ClosureParam *params,
|
||||
PrepareClosureFunc prepare, SetupClosureFunc setup);
|
||||
void register_closure(string_view name, int id, const ClosureParam* params,
|
||||
PrepareClosureFunc prepare, SetupClosureFunc setup);
|
||||
|
||||
/// Query either by name or id an existing closure. If name is non
|
||||
/// NULL it will use it for the search, otherwise id would be used
|
||||
/// and the name will be placed in name if successful. Also return
|
||||
/// pointer to the params array in the last argument. All args are
|
||||
/// optional but at least one of name or id must non NULL.
|
||||
bool query_closure (const char **name, int *id,
|
||||
const ClosureParam **params);
|
||||
bool query_closure(const char** name, int* id, const ClosureParam** params);
|
||||
|
||||
/// For the proposed shader "global" name, return the corresponding
|
||||
/// SGBits enum.
|
||||
static SGBits globals_bit (ustring name);
|
||||
static SGBits globals_bit(ustring name);
|
||||
|
||||
/// For the SGBits value, return the shader "globals" name.
|
||||
static ustring globals_name (SGBits bit);
|
||||
static ustring globals_name(SGBits bit);
|
||||
|
||||
/// For the proposed raytype name, return the bit pattern that
|
||||
/// describes it, or 0 for an unrecognized name. (This retrieves
|
||||
/// data passed in via attribute("raytypes")).
|
||||
int raytype_bit (ustring name);
|
||||
int raytype_bit(ustring name);
|
||||
|
||||
/// Configure the default raytypes to assume to be on (or off) at optimization
|
||||
/// time for the given group. The raytypes_on gives a bitfield describing which
|
||||
/// ray flags are known to be 1, and raytypes_off describes which ray flags are
|
||||
/// known to be 0. Bits that are not set in either set of flags are not known
|
||||
/// to the optimizer, and will be determined strictly at execution time.
|
||||
void set_raytypes(ShaderGroup *group, int raytypes_on, int raytypes_off);
|
||||
void set_raytypes(ShaderGroup* group, int raytypes_on, int raytypes_off);
|
||||
|
||||
/// Clear any known mappings of symbol locations.
|
||||
void clear_symlocs();
|
||||
@@ -863,31 +913,32 @@ public:
|
||||
|
||||
/// 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, bool do_jit = true);
|
||||
void optimize_group(ShaderGroup* group, ShadingContext* ctx,
|
||||
bool do_jit = true);
|
||||
|
||||
/// Ensure that the group has been optimized and optionally JITed. This is a
|
||||
/// convenience function that simply calls set_raytypes followed by
|
||||
/// optimize_group. The ctx supplies a ShadingContext to use.
|
||||
void optimize_group (ShaderGroup *group, int raytypes_on,
|
||||
int raytypes_off, ShadingContext *ctx, bool do_jit = true);
|
||||
void optimize_group(ShaderGroup* group, int raytypes_on, int raytypes_off,
|
||||
ShadingContext* ctx, bool do_jit = true);
|
||||
|
||||
/// If option "greedyjit" was set, this call will trigger all
|
||||
/// shader groups that have not yet been compiled to do so with the
|
||||
/// specified number of threads (0 means use all available HW cores).
|
||||
void optimize_all_groups (int nthreads=0, bool do_jit = true);
|
||||
void optimize_all_groups(int nthreads = 0, bool do_jit = true);
|
||||
|
||||
/// Return a pointer to the TextureSystem being used.
|
||||
TextureSystem * texturesys () const;
|
||||
TextureSystem* texturesys() const;
|
||||
|
||||
/// Return a pointer to the RendererServices being used.
|
||||
RendererServices * renderer () const;
|
||||
RendererServices* renderer() const;
|
||||
|
||||
/// Archive the entire shader group so that it can be reconstituted
|
||||
/// later.
|
||||
bool archive_shadergroup (ShaderGroup &group, string_view filename);
|
||||
bool archive_shadergroup(ShaderGroup& group, string_view filename);
|
||||
|
||||
// DEPRECATED(2.0)
|
||||
bool archive_shadergroup (ShaderGroup *group, string_view filename);
|
||||
bool archive_shadergroup(ShaderGroup* group, string_view filename);
|
||||
|
||||
/// Construct and return an OSLQuery initialized with an existing
|
||||
/// ShaderGroup. For a shader group already loaded by the ShadingSystem,
|
||||
@@ -966,9 +1017,8 @@ bool
|
||||
shade_image(ShadingSystem& shadingsys, ShaderGroup& group,
|
||||
const ShaderGlobals* defaultsg, OIIO::ImageBuf& buf,
|
||||
cspan<ustring> outputs,
|
||||
ShadeImageLocations shadelocations = ShadePixelCenters,
|
||||
OIIO::ROI roi = OIIO::ROI(),
|
||||
OIIO::parallel_options popt = 0);
|
||||
ShadeImageLocations shadelocations = ShadePixelCenters,
|
||||
OIIO::ROI roi = OIIO::ROI(), OIIO::parallel_options popt = 0);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+32
-20
@@ -141,6 +141,19 @@ inline OSL_HOSTDEVICE float bits_to_01 (unsigned int bits) {
|
||||
}
|
||||
|
||||
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE int
|
||||
bitcast_to_uint (float x)
|
||||
{
|
||||
#if OPENIMAGEIO_VERSION >= 20500
|
||||
return OIIO::bitcast<unsigned int, float>(x);
|
||||
#else
|
||||
// obsolete call
|
||||
return OIIO::bit_cast<float, unsigned int>(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef __CUDA_ARCH__
|
||||
// Perform a bjmix (see OpenImageIO/hash.h) on 4 sets of values at once.
|
||||
OSL_FORCEINLINE void
|
||||
@@ -231,7 +244,7 @@ reference_inthash (const unsigned int k[N]) {
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE unsigned int
|
||||
inthash (const unsigned int k0, const unsigned int k1) {
|
||||
// now hash the data!
|
||||
unsigned int start_val = 0xdeadbeef + (2 << 2) + 13;
|
||||
unsigned int start_val = 0xdeadbeef + (2 << 2) + 13; //NOSONAR
|
||||
|
||||
unsigned int a = start_val + k0;
|
||||
unsigned int b = start_val + k1;
|
||||
@@ -467,7 +480,7 @@ struct HashNoise: public IntHashNoiseBase<HashNoise> {
|
||||
static OSL_FORCEINLINE OSL_HOSTDEVICE unsigned int
|
||||
transformToUint(float val)
|
||||
{
|
||||
return OIIO::bit_cast<float,unsigned int>(val);
|
||||
return bitcast_to_uint(val);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -544,7 +557,6 @@ using PeriodicHashNoise = PeriodicAdaptionOf<HashNoise>;
|
||||
|
||||
|
||||
|
||||
|
||||
inline OSL_HOSTDEVICE int
|
||||
inthashi (int x)
|
||||
{
|
||||
@@ -557,7 +569,7 @@ inline OSL_HOSTDEVICE int
|
||||
inthashf (float x)
|
||||
{
|
||||
return static_cast<int>(
|
||||
inthash(OIIO::bit_cast<float,unsigned int>(x))
|
||||
inthash(bitcast_to_uint(x))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -566,8 +578,8 @@ inthashf (float x, float y)
|
||||
{
|
||||
return static_cast<int>(
|
||||
inthash(
|
||||
OIIO::bit_cast<float,unsigned int>(x),
|
||||
OIIO::bit_cast<float,unsigned int>(y)
|
||||
bitcast_to_uint(x),
|
||||
bitcast_to_uint(y)
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -578,9 +590,9 @@ inthashf (const float *x)
|
||||
{
|
||||
return static_cast<int>(
|
||||
inthash(
|
||||
OIIO::bit_cast<float,unsigned int>(x[0]),
|
||||
OIIO::bit_cast<float,unsigned int>(x[1]),
|
||||
OIIO::bit_cast<float,unsigned int>(x[2])
|
||||
bitcast_to_uint(x[0]),
|
||||
bitcast_to_uint(x[1]),
|
||||
bitcast_to_uint(x[2])
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -591,10 +603,10 @@ inthashf (const float *x, float y)
|
||||
{
|
||||
return static_cast<int>(
|
||||
inthash(
|
||||
OIIO::bit_cast<float,unsigned int>(x[0]),
|
||||
OIIO::bit_cast<float,unsigned int>(x[1]),
|
||||
OIIO::bit_cast<float,unsigned int>(x[2]),
|
||||
OIIO::bit_cast<float,unsigned int>(y)
|
||||
bitcast_to_uint(x[0]),
|
||||
bitcast_to_uint(x[1]),
|
||||
bitcast_to_uint(x[2]),
|
||||
bitcast_to_uint(y)
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -1154,16 +1166,16 @@ private:
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE HashScalarPeriodic () {}
|
||||
public:
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE HashScalarPeriodic (float px) {
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1;
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1; //NOSONAR
|
||||
}
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE HashScalarPeriodic (float px, float py) {
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1;
|
||||
m_py = OIIO::ifloor(py); if (m_py < 1) m_py = 1;
|
||||
m_py = OIIO::ifloor(py); if (m_py < 1) m_py = 1; //NOSONAR
|
||||
}
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE HashScalarPeriodic (float px, float py, float pz) {
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1;
|
||||
m_py = OIIO::ifloor(py); if (m_py < 1) m_py = 1;
|
||||
m_pz = OIIO::ifloor(pz); if (m_pz < 1) m_pz = 1;
|
||||
m_pz = OIIO::ifloor(pz); if (m_pz < 1) m_pz = 1; //NOSONAR
|
||||
}
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE HashScalarPeriodic (float px, float py, float pz, float pw) {
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1;
|
||||
@@ -1225,16 +1237,16 @@ public:
|
||||
|
||||
struct HashVectorPeriodic {
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE HashVectorPeriodic (float px) {
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1;
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1; //NOSONAR
|
||||
}
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE HashVectorPeriodic (float px, float py) {
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1;
|
||||
m_py = OIIO::ifloor(py); if (m_py < 1) m_py = 1;
|
||||
m_py = OIIO::ifloor(py); if (m_py < 1) m_py = 1; //NOSONAR
|
||||
}
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE HashVectorPeriodic (float px, float py, float pz) {
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1;
|
||||
m_py = OIIO::ifloor(py); if (m_py < 1) m_py = 1;
|
||||
m_pz = OIIO::ifloor(pz); if (m_pz < 1) m_pz = 1;
|
||||
m_pz = OIIO::ifloor(pz); if (m_pz < 1) m_pz = 1; //NOSONAR
|
||||
}
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE HashVectorPeriodic (float px, float py, float pz, float pw) {
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1;
|
||||
@@ -1881,7 +1893,7 @@ OSL_FORCEINLINE OSL_HOSTDEVICE void perlin (Vec3 &result, const H &hash,
|
||||
u, v, w);
|
||||
result = scale3 (result);
|
||||
#else
|
||||
static_assert(std::is_same<Vec3i, decltype(hash(X, Y, Z))>::value, "This re-implementation was developed for Hashs returning a vector type only");
|
||||
static_assert(std::is_same<Vec3i, decltype(hash(X, Y, Z))>::value, "This re-implementation was developed for hashes returning a vector type only");
|
||||
// Want to avoid repeating the same hash work 3 times in a row
|
||||
// so rather than executing the vector version, we will use HashScalar
|
||||
// and directly mask its results on a per component basis
|
||||
|
||||
@@ -61,7 +61,7 @@ class OSOReaderQuery; // Just so OSLQuery can friend OSLReaderQuery
|
||||
/// ~~~
|
||||
///
|
||||
/// And the `Parameter` structure will hold all the information you need
|
||||
/// about that paramter. For example:
|
||||
/// about that parameter. For example:
|
||||
///
|
||||
/// ~~~
|
||||
/// std::cout << "Parameter " << p->name
|
||||
@@ -123,7 +123,7 @@ public:
|
||||
}
|
||||
///< Construct an OSLQuery and open a compiled shader from a disk file.
|
||||
/// The `shadername` may be either the name of the `.oso` file, or the
|
||||
/// name of the shader. The optional `searchpath` paramter gives a
|
||||
/// name of the shader. The optional `searchpath` parameter gives a
|
||||
/// colon-separated list of directories to search for compiled shaders.
|
||||
|
||||
OSL_DEPRECATED("Use ShadingSystem::oslquery(group,layernum)")
|
||||
|
||||
@@ -103,4 +103,7 @@ namespace @PROJ_NAME@ = @PROJ_NAMESPACE_V@;
|
||||
#define __OSL_WIDE_PVT __OSL_CONCAT5(b,__OSL_WIDTH,_,__OSL_TARGET_ISA,_pvt)
|
||||
#endif
|
||||
|
||||
#define __OSL_INDIRECT_STRINGIFY(x) #x
|
||||
#define __OSL_STRINGIFY(x) __OSL_INDIRECT_STRINGIFY(x)
|
||||
|
||||
#endif /* OSLVERSION_H */
|
||||
|
||||
@@ -102,6 +102,7 @@
|
||||
|
||||
// Tests for MSVS versions, always 0 if not MSVS at all.
|
||||
#if defined(_MSC_VER)
|
||||
# define OSL_MSVS_VERSION _MSC_VER
|
||||
# define OSL_MSVS_AT_LEAST_2013 (_MSC_VER >= 1800)
|
||||
# define OSL_MSVS_BEFORE_2013 (_MSC_VER < 1800)
|
||||
# define OSL_MSVS_AT_LEAST_2015 (_MSC_VER >= 1900)
|
||||
@@ -112,6 +113,7 @@
|
||||
# error "This version of OSL is meant to work only with Visual Studio 2017 or later"
|
||||
# endif
|
||||
#else
|
||||
# define OSL_MSVS_VERSION 0
|
||||
# define OSL_MSVS_AT_LEAST_2013 0
|
||||
# define OSL_MSVS_BEFORE_2013 0
|
||||
# define OSL_MSVS_AT_LEAST_2015 0
|
||||
@@ -263,6 +265,7 @@
|
||||
#endif
|
||||
|
||||
#define OSL_OMP_SIMD_LOOP(...) OSL_OMP_PRAGMA(omp simd __VA_ARGS__)
|
||||
|
||||
#if (OSL_GCCVERSION || OSL_INTEL_CLASSIC_COMPILER_VERSION || OSL_INTEL_LLVM_COMPILER_VERSION)
|
||||
# define OSL_OMP_COMPLEX_SIMD_LOOP(...) OSL_OMP_SIMD_LOOP(__VA_ARGS__)
|
||||
#else
|
||||
@@ -479,11 +482,19 @@
|
||||
# define OSL_DASSERT_MSG(x, ...) ((void)sizeof(x)) /*NOLINT*/
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
|
||||
#define OSL_STACK_ARRAY(TYPE, NAME, DYNAMIC_COUNT) TYPE * NAME = reinterpret_cast<TYPE *>(alloca(sizeof(TYPE)*(DYNAMIC_COUNT)))
|
||||
|
||||
/// OSL_ALLOCA is used to allocate smallish amount of memory on the stack,
|
||||
/// equivalent of C99 type var_name[size].
|
||||
///
|
||||
/// NOTE: in a debug build, this will assert for allocations >= 1MB, which is
|
||||
/// much too big. Hopefully this will keep us from abusing alloca and having
|
||||
/// stack overflows. The rule of thumb is that it's ok to use alloca for small
|
||||
/// things of bounded size, but not for anything that could be arbitrarily
|
||||
/// big, which should instead use heap allocation.
|
||||
#if defined(__GNUC__)
|
||||
# define OSL_ALLOCA(type, size) (assert(size < (1<<20)), (size) != 0 ? (reinterpret_cast<type*>(__builtin_alloca((size) * sizeof(type)))) : nullptr)
|
||||
#else
|
||||
// Utilize variable length array compiler extension when available
|
||||
#define OSL_STACK_ARRAY(TYPE, NAME, DYNAMIC_COUNT) TYPE NAME[DYNAMIC_COUNT]
|
||||
# define OSL_ALLOCA(type, size) (assert(size < (1<<20)), (size) != 0 ? (reinterpret_cast<type*>(alloca((size) * sizeof(type)))) : nullptr)
|
||||
#endif
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
@@ -42,6 +42,7 @@ OSL_GCC_PRAGMA(GCC diagnostic ignored "-Wunused-parameter")
|
||||
/// RendererServices defines an abstract interface through which a
|
||||
/// renderer may provide callback to the ShadingSystem.
|
||||
class OSLEXECPUBLIC RendererServices {
|
||||
// Keep interface in sync with rs_free_function.h
|
||||
public:
|
||||
typedef TextureSystem::TextureHandle TextureHandle;
|
||||
typedef TextureSystem::Perthread TexturePerthread;
|
||||
@@ -404,15 +405,6 @@ public:
|
||||
/// Return a pointer to the texture system (if available).
|
||||
virtual TextureSystem *texturesys () const;
|
||||
|
||||
/// Register a string with the renderer, so that the renderer can arrange
|
||||
/// to make the string available in GPU memory as needed. Optionally specify
|
||||
/// a variable name to associate with the string value.
|
||||
virtual uint64_t register_string (const std::string& str,
|
||||
const std::string& var_name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual uint64_t register_global (const std::string& var_name,
|
||||
uint64_t value)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
// Copyright Contributors to the Open Shading Language project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
// Make all the strings defined in OSL
|
||||
// available to the renderer services free functions
|
||||
OSL_NAMESPACE_ENTER
|
||||
namespace Strings {
|
||||
#define STRDECL(str, var_name) OSLEXECPUBLIC extern const ustring var_name;
|
||||
#include <OSL/strdecls.h>
|
||||
#undef STRDECL
|
||||
}; // namespace Strings
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
#ifdef OSL_HOST_RS_BITCODE
|
||||
extern "C" {
|
||||
# define STRDECL(str, var_name) \
|
||||
const OSL::ustring& RS_##var_name = OSL::Strings::var_name;
|
||||
# include <OSL/strdecls.h>
|
||||
# undef STRDECL
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <OSL/device_string.h>
|
||||
#include <OSL/shaderglobals.h>
|
||||
|
||||
// Prefix for OSL shade op declarations.
|
||||
// "C" linkage (no C++ name mangling) and local visibility
|
||||
#define OSL_RSOP extern "C"
|
||||
|
||||
// We are choosing to use unique names encoding parameters directly
|
||||
// as opposed to using overloaded functions.
|
||||
|
||||
// Keep free functions in sync with virtual function based RendererServices.
|
||||
|
||||
/// 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,
|
||||
OSL::TransformationPtr from, float time);
|
||||
|
||||
/// Get the 4x4 matrix that transforms by the specified
|
||||
/// transformation at the given time. Return true if ok, false on
|
||||
/// 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,
|
||||
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,
|
||||
OSL::StringParam from, float time);
|
||||
|
||||
/// Get the 4x4 matrix that transforms points from "common" space to
|
||||
/// the named 'to' coordinate system to at the given time. Suggested
|
||||
/// 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);
|
||||
|
||||
/// 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,
|
||||
OSL::TransformationPtr xform);
|
||||
|
||||
/// 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. Suggested implementation is to use
|
||||
/// 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,
|
||||
OSL::TransformationPtr xform);
|
||||
|
||||
/// 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).
|
||||
OSL_RSOP bool
|
||||
rs_get_matrix_space(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
OSL::StringParam from);
|
||||
|
||||
/// Get the 4x4 matrix that transforms points from "common" space to
|
||||
/// the named 'to' coordinate system. 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). Suggested
|
||||
/// 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);
|
||||
|
||||
/// Transform points Pin[0..npoints-1] in named coordinate system
|
||||
/// 'from' into 'to' coordinates, storing the result in Pout[] using
|
||||
/// the specified vector semantic (POINT, VECTOR, NORMAL). The
|
||||
/// function returns true if the renderer correctly transformed the
|
||||
/// points, false if it failed (for example, because it did not know
|
||||
/// the name of one of the coordinate systems). Suggested implementation
|
||||
/// is simply to make appropriate calls to rs_get_matrix_space and
|
||||
/// get_inverse_matrix_space. The existence of this function is to allow
|
||||
/// some renderers to provide transformations that cannot be
|
||||
/// expressed by a 4x4 matrix.
|
||||
///
|
||||
/// Note, the virtual function based RendererServices::transform_points
|
||||
/// provides additional functionality/modes that are only used during
|
||||
/// code generation to detect if it required to even call rs_transform_points
|
||||
/// during evaluation of the shader. There is no need for the free
|
||||
/// function version to handle these additional modes.
|
||||
///
|
||||
/// Note to implementations: just return 'false'
|
||||
/// if there isn't a special nonlinear transformation between the
|
||||
/// two spaces.
|
||||
OSL_RSOP bool
|
||||
rs_transform_points(OSL::ShaderGlobals* sg, OSL::StringParam from,
|
||||
OSL::StringParam to, float time, const OSL::Vec3* Pin,
|
||||
OSL::Vec3* Pout, int npoints,
|
||||
OSL::TypeDesc::VECSEMANTICS vectype);
|
||||
@@ -145,7 +145,7 @@ namespace sfm
|
||||
//return static_cast<int>(rintf(x));
|
||||
return rintf(x);
|
||||
#else
|
||||
// emulate rounding by adding/substracting 0.5
|
||||
// emulate rounding by adding/subtracting 0.5
|
||||
return static_cast<int>(x + copysignf(0.5f, x));
|
||||
|
||||
// Other possible factorings
|
||||
@@ -441,7 +441,7 @@ namespace sfm
|
||||
|
||||
// Considering having functionally equivalent versions of Vec3, Color3, Matrix44
|
||||
// with slight modifications to inlining and implementation to avoid aliasing and
|
||||
// improve likelyhood of proper privation of local variables within a SIMD loop
|
||||
// improve likelihood of proper privation of local variables within a SIMD loop
|
||||
|
||||
} // namespace sfm
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@ class RendererServices;
|
||||
/// coordinate transformation.
|
||||
typedef const void* TransformationPtr;
|
||||
|
||||
/// Type for an opaque pointer to whatever the Shading System uses to represent
|
||||
/// Uniform State.
|
||||
typedef const void* OpaqueShadingStateUniformPtr;
|
||||
|
||||
|
||||
/// The ShaderGlobals structure represents the state describing a particular
|
||||
@@ -83,6 +86,7 @@ struct ShaderGlobals {
|
||||
/// Back-pointer to the ShadingContext (set and used by OSL itself --
|
||||
/// renderers shouldn't mess with this at all).
|
||||
ShadingContext* context;
|
||||
OpaqueShadingStateUniformPtr shadingStateUniform;
|
||||
|
||||
/// Pointer to the RendererServices object. This is how OSL finds its
|
||||
/// way back to the renderer for callbacks.
|
||||
|
||||
@@ -139,6 +139,8 @@ STRDECL("SMPTE", SMPTE)
|
||||
STRDECL("HDTV", HDTV)
|
||||
STRDECL("CIE", CIE)
|
||||
STRDECL("AdobeRGB", AdobeRGB)
|
||||
STRDECL("ACES2065-1", ACES2065_1)
|
||||
STRDECL("ACEScg", ACEScg)
|
||||
STRDECL("colorsystem", colorsystem)
|
||||
STRDECL("arraylength", arraylength)
|
||||
STRDECL("unknown", unknown)
|
||||
|
||||
+34
-17
@@ -194,17 +194,17 @@ template<int WidthT> struct alignas(WidthT * sizeof(float)) VecReg {
|
||||
};
|
||||
|
||||
static_assert(std::alignment_of<VecReg<16>>::value == 64,
|
||||
"Unexepected alignment");
|
||||
"Unexpected alignment");
|
||||
static_assert(std::alignment_of<VecReg<8>>::value == 32,
|
||||
"Unexepected alignment");
|
||||
"Unexpected alignment");
|
||||
static_assert(std::alignment_of<VecReg<4>>::value == 16,
|
||||
"Unexepected alignment");
|
||||
"Unexpected alignment");
|
||||
static_assert(std::alignment_of<VecReg<16>>::value == VecReg<16>::alignment,
|
||||
"Unexepected alignment");
|
||||
"Unexpected alignment");
|
||||
static_assert(std::alignment_of<VecReg<8>>::value == VecReg<8>::alignment,
|
||||
"Unexepected alignment");
|
||||
"Unexpected alignment");
|
||||
static_assert(std::alignment_of<VecReg<4>>::value == VecReg<4>::alignment,
|
||||
"Unexepected alignment");
|
||||
"Unexpected alignment");
|
||||
|
||||
|
||||
template<typename BuiltinT, int WidthT>
|
||||
@@ -1535,7 +1535,7 @@ assume_aligned(Block<DataT, WidthT>* block_ptr)
|
||||
{
|
||||
static_assert(std::alignment_of<Block<DataT, WidthT>>::value
|
||||
== std::alignment_of<VecReg<WidthT>>::value,
|
||||
"Unexepected alignment");
|
||||
"Unexpected alignment");
|
||||
return assume_aligned<VecReg<WidthT>::alignment>(block_ptr);
|
||||
}
|
||||
|
||||
@@ -1545,7 +1545,7 @@ assume_aligned(const Block<DataT, WidthT>* block_ptr)
|
||||
{
|
||||
static_assert(std::alignment_of<Block<DataT, WidthT>>::value
|
||||
== std::alignment_of<VecReg<WidthT>>::value,
|
||||
"Unexepected alignment");
|
||||
"Unexpected alignment");
|
||||
return assume_aligned<VecReg<WidthT>::alignment>(block_ptr);
|
||||
}
|
||||
|
||||
@@ -2089,7 +2089,7 @@ struct UniformAsWide : public pvt::UniformAsWideImpl<DataT, WidthT> {
|
||||
template<typename DataT>
|
||||
struct WideTraits; // undefined, all types used should be specialized
|
||||
//{
|
||||
//static bool mathes(const TypeDesc &) { return false; }
|
||||
//static bool matches(const TypeDesc &) { return false; }
|
||||
//};
|
||||
|
||||
template<> struct WideTraits<float> {
|
||||
@@ -2128,7 +2128,7 @@ template<> struct WideTraits<ustring> {
|
||||
}
|
||||
};
|
||||
|
||||
// We let Vec3 match any vector semantics as we don't have a seperate Point or Normal classes
|
||||
// We let Vec3 match any vector semantics as we don't have a separate Point or Normal classes
|
||||
template<> struct WideTraits<Vec3> {
|
||||
static bool matches(const TypeDesc& type_desc)
|
||||
{
|
||||
@@ -2229,9 +2229,15 @@ 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;
|
||||
@@ -2293,9 +2299,15 @@ 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
|
||||
@@ -2727,19 +2739,24 @@ foreach_unique(Wide<DataT, WidthT> wdata, Mask<WidthT> data_mask, FunctorT f)
|
||||
do {
|
||||
ActiveLane lead_lane(remaining_mask.first_on());
|
||||
DataT lead_data = wdata[lead_lane];
|
||||
Mask<WidthT> matching_lanes(false);
|
||||
// Use int instead of Mask<> to allow reduction clause in openmp simd declaration
|
||||
int matching_lanes_bits { 0 };
|
||||
OSL_FORCEINLINE_BLOCK
|
||||
{
|
||||
OSL_OMP_PRAGMA(omp simd simdlen(WidthT))
|
||||
OSL_OMP_PRAGMA(omp simd simdlen(WidthT)
|
||||
reduction(|
|
||||
: matching_lanes_bits))
|
||||
for (int lane = 0; lane < WidthT; ++lane) {
|
||||
// NOTE: the comparison ignores the remaining_mask
|
||||
bool lane_matches = (lead_data == wdata[lane]);
|
||||
// NOTE: using bitwise & to avoid branches
|
||||
if (lane_matches & remaining_mask[lane]) {
|
||||
matching_lanes.set_on(lane);
|
||||
// inline of Mask::set_on(lane)
|
||||
matching_lanes_bits |= 1 << lane;
|
||||
}
|
||||
}
|
||||
}
|
||||
Mask<WidthT> matching_lanes { matching_lanes_bits };
|
||||
|
||||
f(lead_data, matching_lanes);
|
||||
remaining_mask &= ~matching_lanes;
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace __OSL_WIDE_PVT {
|
||||
|
||||
OSL_USING_DATA_WIDTH(__OSL_WIDTH)
|
||||
|
||||
// Foward declaration, implementation is in liboslnoise/wide_gabornoise.h
|
||||
// Forward declaration, implementation is in liboslnoise/wide_gabornoise.h
|
||||
struct DisabledFilterPolicy {
|
||||
static constexpr bool active = false;
|
||||
};
|
||||
@@ -34,7 +34,7 @@ OSL_NOINLINE void
|
||||
wide_gabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
|
||||
NoiseParams const* opt, Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_gabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
|
||||
@@ -46,20 +46,20 @@ OSL_NOINLINE void
|
||||
wide_gabor(Masked<Dual2<float>> wResult, Wide<const Dual2<Vec3>> wP,
|
||||
NoiseParams const* opt, Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_gabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
|
||||
NoiseParams const* opt, Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_gabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
|
||||
Wide<const Dual2<float>> wY, NoiseParams const* opt,
|
||||
Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_gabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<Vec3>> wP,
|
||||
@@ -71,14 +71,14 @@ wide_gabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<Vec3>> wP,
|
||||
// Periodic gabor(s)
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
|
||||
Wide<const float> wXp, NoiseParams const* opt,
|
||||
Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
|
||||
@@ -86,7 +86,7 @@ wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
|
||||
Wide<const float> wYp, NoiseParams const* opt,
|
||||
Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<Vec3>> wP,
|
||||
@@ -95,14 +95,14 @@ wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<Vec3>> wP,
|
||||
|
||||
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_pgabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
|
||||
Wide<const float> wXp, NoiseParams const* opt,
|
||||
Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_pgabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
|
||||
@@ -110,7 +110,7 @@ wide_pgabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
|
||||
Wide<const float> wYp, NoiseParams const* opt,
|
||||
Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_pgabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<Vec3>> wP,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
#include <OSL/oslversion.h>
|
||||
|
||||
#ifdef OSL_USE_OPTIX
|
||||
@@ -13,14 +14,18 @@
|
||||
# ifdef _WIN32
|
||||
# define NOMINMAX
|
||||
# endif
|
||||
# if (OPTIX_VERSION < 70000)
|
||||
# include <optix_world.h>
|
||||
# endif
|
||||
#else
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(OSL_USE_OPTIX) && !defined(__CUDA_ARCH__)
|
||||
using CUdeviceptr = void*;
|
||||
using float3 = OSL::Vec3;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
#ifdef OSL_USE_OPTIX
|
||||
@@ -31,14 +36,12 @@ OSL_NAMESPACE_ENTER
|
||||
|
||||
|
||||
// TODO clean this up once OptiX6 support is dropped
|
||||
# if (OPTIX_VERSION < 70000)
|
||||
namespace optix = ::optix;
|
||||
# else
|
||||
namespace optix {
|
||||
typedef OptixDeviceContext Context;
|
||||
typedef cudaTextureObject_t TextureSampler;
|
||||
using ::CUdeviceptr;
|
||||
using ::float3;
|
||||
} // namespace optix
|
||||
# endif
|
||||
|
||||
using ::cudaFree;
|
||||
using ::cudaMalloc;
|
||||
@@ -49,13 +52,19 @@ using ::cudaMalloc;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// If OptiX is not available, make reasonable proxies just so that we
|
||||
// don't have to litter the code with quite as many #ifdef's.
|
||||
// OSL::optix::
|
||||
// Mostly under OSL::optix::
|
||||
|
||||
|
||||
|
||||
namespace optix {
|
||||
|
||||
typedef void* Context;
|
||||
typedef void* Program;
|
||||
typedef void* TextureSampler;
|
||||
typedef void* CUdeviceptr;
|
||||
using float3 = OSL::Vec3;
|
||||
|
||||
|
||||
struct Exception {
|
||||
static const char* what() { return "OSL compiled without Optix."; }
|
||||
};
|
||||
|
||||
+214
-55
@@ -558,7 +558,7 @@ public:
|
||||
///
|
||||
void scope(int s) { m_scope = s; }
|
||||
|
||||
/// Return teh AST node containing the declaration of this symbol.
|
||||
/// Return the AST node containing the declaration of this symbol.
|
||||
/// Use with care!
|
||||
ASTNode* node() const { return m_node; }
|
||||
|
||||
@@ -633,55 +633,133 @@ public:
|
||||
}
|
||||
|
||||
|
||||
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.
|
||||
///
|
||||
@@ -725,15 +803,42 @@ 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
|
||||
@@ -754,31 +859,67 @@ 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; }
|
||||
bool lockgeom() const
|
||||
{
|
||||
return m_lockgeom;
|
||||
}
|
||||
void lockgeom(bool lock)
|
||||
{
|
||||
m_lockgeom = lock;
|
||||
}
|
||||
|
||||
bool allowconnect() const { return m_allowconnect; }
|
||||
void allowconnect(bool val) { m_allowconnect = val; }
|
||||
bool allowconnect() const
|
||||
{
|
||||
return m_allowconnect;
|
||||
}
|
||||
void allowconnect(bool val)
|
||||
{
|
||||
m_allowconnect = val;
|
||||
}
|
||||
|
||||
int arraylen() const { return m_typespec.arraylength(); }
|
||||
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
|
||||
@@ -792,14 +933,32 @@ 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
|
||||
@@ -855,7 +1014,7 @@ public:
|
||||
|
||||
// Stream output. Note that print/print_vals assume that any string
|
||||
// values are "raw" and they will be converted to C source code "escaped
|
||||
// string" notation for printing. For example, a newline characer will
|
||||
// string" notation for printing. For example, a newline character will
|
||||
// be rendered into the stream as the two character sequence '\n'.
|
||||
std::ostream& print(std::ostream& out, int maxvals = 100000000) const;
|
||||
std::ostream& print_vals(std::ostream& out, int maxvals = 100000000) const;
|
||||
|
||||
+95
-91
@@ -35,7 +35,7 @@ std::atomic<int> node_counts_peak[ASTNode::_last_node];
|
||||
class ScopeExit {
|
||||
public:
|
||||
typedef std::function<void()> Task;
|
||||
explicit ScopeExit(Task&& task) : m_task(std::forward<Task>(task)) {}
|
||||
explicit ScopeExit(Task&& task) : m_task(std::move(task)) {}
|
||||
~ScopeExit() { m_task(); }
|
||||
|
||||
private:
|
||||
@@ -45,8 +45,8 @@ private:
|
||||
ScopeExit print_node_counts([]() {
|
||||
for (int i = 0; i < ASTNode::_last_node; ++i)
|
||||
if (node_counts[i] > 0)
|
||||
Strutil::printf("ASTNode type %2d: %5d (peak %5d)\n", i,
|
||||
node_counts[i], node_counts_peak[i]);
|
||||
Strutil::print("ASTNode type {:2}: {:5} (peak {:5})\n", i,
|
||||
node_counts[i], node_counts_peak[i]);
|
||||
});
|
||||
} // namespace
|
||||
#endif
|
||||
@@ -213,7 +213,7 @@ ASTNode::~ASTNode()
|
||||
void
|
||||
ASTNode::error_impl(string_view msg) const
|
||||
{
|
||||
m_compiler->errorf(sourcefile(), sourceline(), "%s", msg);
|
||||
m_compiler->errorfmt(sourcefile(), sourceline(), "{}", msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -221,7 +221,7 @@ ASTNode::error_impl(string_view msg) const
|
||||
void
|
||||
ASTNode::warning_impl(string_view msg) const
|
||||
{
|
||||
m_compiler->warningf(sourcefile(), sourceline(), "%s", msg);
|
||||
m_compiler->warningfmt(sourcefile(), sourceline(), "{}", msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -229,7 +229,7 @@ ASTNode::warning_impl(string_view msg) const
|
||||
void
|
||||
ASTNode::info_impl(string_view msg) const
|
||||
{
|
||||
m_compiler->infof(sourcefile(), sourceline(), "%s", msg);
|
||||
m_compiler->infofmt(sourcefile(), sourceline(), "{}", msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -237,7 +237,7 @@ ASTNode::info_impl(string_view msg) const
|
||||
void
|
||||
ASTNode::message_impl(string_view msg) const
|
||||
{
|
||||
m_compiler->messagef(sourcefile(), sourceline(), "%s", msg);
|
||||
m_compiler->messagefmt(sourcefile(), sourceline(), "{}", msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -246,12 +246,11 @@ void
|
||||
ASTNode::print(std::ostream& out, int indentlevel) const
|
||||
{
|
||||
indent(out, indentlevel);
|
||||
out << "(" << nodetypename() << " : "
|
||||
<< " (type: " << typespec().string() << ") "
|
||||
<< (opname() ? opname() : "") << "\n";
|
||||
OSL::print(out, "({} : (type: {}) {}\n", nodetypename(), typespec(),
|
||||
(opname() ? opname() : ""));
|
||||
printchildren(out, indentlevel);
|
||||
indent(out, indentlevel);
|
||||
out << ")\n";
|
||||
OSL::print(out, ")\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -264,13 +263,13 @@ ASTNode::printchildren(std::ostream& out, int indentlevel) const
|
||||
continue;
|
||||
indent(out, indentlevel);
|
||||
if (childname(i))
|
||||
out << " " << childname(i);
|
||||
OSL::print(out, " {}", childname(i));
|
||||
else
|
||||
out << " child" << i;
|
||||
out << ": ";
|
||||
OSL::print(out, " child{}", i);
|
||||
OSL::print(out, ": ");
|
||||
if (typespec() != TypeSpec() && !child(i)->next())
|
||||
out << " (type: " << typespec().string() << ")";
|
||||
out << "\n";
|
||||
OSL::print(out, " (type: {})", typespec());
|
||||
OSL::print(out, "\n");
|
||||
printlist(out, child(i), indentlevel + 1);
|
||||
}
|
||||
}
|
||||
@@ -314,11 +313,8 @@ std::string
|
||||
ASTNode::list_to_types_string(const ASTNode* node)
|
||||
{
|
||||
std::ostringstream result;
|
||||
for (int i = 0; node; node = node->nextptr(), ++i) {
|
||||
if (i)
|
||||
result << ", ";
|
||||
result << node->typespec();
|
||||
}
|
||||
for (int i = 0; node; node = node->nextptr(), ++i)
|
||||
OSL::print(result, "{}{}", i ? ", " : "", node->typespec());
|
||||
return result.str();
|
||||
}
|
||||
|
||||
@@ -335,11 +331,11 @@ ASTshader_declaration::ASTshader_declaration(OSLCompilerImpl* comp, int stype,
|
||||
OSL_ASSERT(arg->nodetype() == variable_declaration_node);
|
||||
ASTvariable_declaration* v = (ASTvariable_declaration*)arg;
|
||||
if (!v->init())
|
||||
v->errorf("shader parameter '%s' requires a default initializer",
|
||||
v->name());
|
||||
v->errorfmt("shader parameter '{}' requires a default initializer",
|
||||
v->name());
|
||||
if (v->is_output() && v->typespec().is_unsized_array())
|
||||
v->errorf("shader output parameter '%s' can't be unsized array",
|
||||
v->name());
|
||||
v->errorfmt("shader output parameter '{}' can't be unsized array",
|
||||
v->name());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,11 +354,11 @@ void
|
||||
ASTshader_declaration::print(std::ostream& out, int indentlevel) const
|
||||
{
|
||||
indent(out, indentlevel);
|
||||
out << "(" << nodetypename() << " " << shadertypename() << " \""
|
||||
<< m_shadername << "\"\n";
|
||||
OSL::print(out, "({} {} \"{}\"\n", nodetypename(), shadertypename(),
|
||||
m_shadername);
|
||||
printchildren(out, indentlevel);
|
||||
indent(out, indentlevel);
|
||||
out << ")\n";
|
||||
OSL::print(out, ")\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -392,13 +388,13 @@ ASTfunction_declaration::ASTfunction_declaration(OSLCompilerImpl* comp,
|
||||
m_sourceline = sourceline_start;
|
||||
|
||||
if (Strutil::starts_with(name, "___"))
|
||||
errorf("\"%s\" : sorry, can't start with three underscores", name);
|
||||
errorfmt("\"{}\" : sorry, can't start with three underscores", name);
|
||||
|
||||
// Get a pointer to the first of the existing symbols of that name.
|
||||
Symbol* existing_syms = comp->symtab().clash(name);
|
||||
if (existing_syms && existing_syms->symtype() != SymTypeFunction) {
|
||||
errorf("\"%s\" already declared in this scope as a %s", name,
|
||||
existing_syms->typespec());
|
||||
errorfmt("\"{}\" already declared in this scope as a {}", name,
|
||||
existing_syms->typespec());
|
||||
// FIXME -- print the file and line of the other definition
|
||||
existing_syms = NULL;
|
||||
}
|
||||
@@ -416,8 +412,8 @@ ASTfunction_declaration::ASTfunction_declaration(OSLCompilerImpl* comp,
|
||||
OSL_ASSERT(arg->nodetype() == variable_declaration_node);
|
||||
ASTvariable_declaration* v = (ASTvariable_declaration*)arg;
|
||||
if (v->init())
|
||||
v->errorf(
|
||||
"function parameter '%s' may not have a default initializer.",
|
||||
v->errorfmt(
|
||||
"function parameter '{}' may not have a default initializer.",
|
||||
v->name());
|
||||
}
|
||||
|
||||
@@ -435,16 +431,15 @@ ASTfunction_declaration::ASTfunction_declaration(OSLCompilerImpl* comp,
|
||||
auto other = static_cast<ASTfunction_declaration*>(f->node());
|
||||
if (!other || (other->statements() || other->is_builtin())) {
|
||||
if (err.empty()) {
|
||||
err = Strutil::sprintf("Function '%s %s (%s)' redefined "
|
||||
"in the same scope\n"
|
||||
" Previous definitions:",
|
||||
type, name,
|
||||
list_to_types_string(form));
|
||||
err = Strutil::fmt::format(
|
||||
"Function '{} {} ({})' redefined in the same scope\n"
|
||||
" Previous definitions:",
|
||||
type, name, list_to_types_string(form));
|
||||
}
|
||||
err += "\n ";
|
||||
if (other) {
|
||||
err += Strutil::sprintf(
|
||||
"%s:%d",
|
||||
err += Strutil::fmt::format(
|
||||
"{}:{}",
|
||||
OIIO::Filesystem::filename(
|
||||
other->sourcefile().string()),
|
||||
other->sourceline());
|
||||
@@ -454,7 +449,7 @@ ASTfunction_declaration::ASTfunction_declaration(OSLCompilerImpl* comp,
|
||||
}
|
||||
}
|
||||
if (!err.empty())
|
||||
warningf("%s", err);
|
||||
warningfmt("{}", err);
|
||||
}
|
||||
|
||||
|
||||
@@ -519,10 +514,10 @@ void
|
||||
ASTfunction_declaration::print(std::ostream& out, int indentlevel) const
|
||||
{
|
||||
indent(out, indentlevel);
|
||||
out << nodetypename() << " " << m_sym->mangled();
|
||||
OSL::print(out, "{} {}", nodetypename(), m_sym->mangled());
|
||||
if (m_sym->scope())
|
||||
out << " (" << m_sym->name() << " in scope " << m_sym->scope() << ")";
|
||||
out << "\n";
|
||||
OSL::print(out, " ({} in scope {})", m_sym->name(), m_sym->scope());
|
||||
OSL::print(out, "\n");
|
||||
printchildren(out, indentlevel);
|
||||
}
|
||||
|
||||
@@ -557,23 +552,24 @@ ASTvariable_declaration::ASTvariable_declaration(OSLCompilerImpl* comp,
|
||||
m_typespec = type;
|
||||
Symbol* f = comp->symtab().clash(name);
|
||||
if (f && !m_ismetadata) {
|
||||
std::string e = Strutil::sprintf("\"%s\" already declared in this scope",
|
||||
name.c_str());
|
||||
std::string e
|
||||
= Strutil::fmt::format("\"{}\" already declared in this scope",
|
||||
name);
|
||||
if (f->node()) {
|
||||
std::string filename = OIIO::Filesystem::filename(
|
||||
f->node()->sourcefile().string());
|
||||
e += Strutil::sprintf("\n\t\tprevious declaration was at %s:%d",
|
||||
filename, f->node()->sourceline());
|
||||
e += Strutil::fmt::format("\n\t\tprevious declaration was at {}:{}",
|
||||
filename, f->node()->sourceline());
|
||||
}
|
||||
if (f->scope() == 0 && f->symtype() == SymTypeFunction && isparam) {
|
||||
// special case: only a warning for param to mask global function
|
||||
warningf("%s", e);
|
||||
warningfmt("{}", e);
|
||||
} else {
|
||||
errorf("%s", e);
|
||||
errorfmt("{}", e);
|
||||
}
|
||||
}
|
||||
if (OIIO::Strutil::starts_with(name, "___")) {
|
||||
errorf("\"%s\" : sorry, can't start with three underscores", name);
|
||||
errorfmt("\"{}\" : sorry, can't start with three underscores", name);
|
||||
}
|
||||
SymType symtype = isparam ? (isoutput ? SymTypeOutputParam : SymTypeParam)
|
||||
: SymTypeLocal;
|
||||
@@ -582,8 +578,14 @@ ASTvariable_declaration::ASTvariable_declaration(OSLCompilerImpl* comp,
|
||||
if (symtype == SymTypeLocal && Strutil::starts_with(name, "__debug_tmp__"))
|
||||
symtype = SymTypeTemp;
|
||||
m_sym = new Symbol(name, type, symtype, this);
|
||||
if (!m_ismetadata)
|
||||
if (m_ismetadata) {
|
||||
// Metadata doesn't go in the symbol table, so we need to retain
|
||||
// an owning pointer so it doesn't leak.
|
||||
m_sym_owned.reset(m_sym);
|
||||
} else {
|
||||
// Put in the symbol table, after which symtab is the owner
|
||||
m_compiler->symtab().insert(m_sym);
|
||||
}
|
||||
|
||||
// A struct really makes several subvariables
|
||||
if (type.is_structure() || type.is_structure_array()) {
|
||||
@@ -620,17 +622,15 @@ void
|
||||
ASTvariable_declaration::print(std::ostream& out, int indentlevel) const
|
||||
{
|
||||
indent(out, indentlevel);
|
||||
out << "(" << nodetypename() << " " << m_sym->typespec().string() << " "
|
||||
<< m_sym->mangled();
|
||||
OSL::print(out, "({} {}", nodetypename(), m_sym->mangled());
|
||||
#if 0
|
||||
if (m_sym->scope())
|
||||
out << " (" << m_sym->name()
|
||||
<< " in scope " << m_sym->scope() << ")";
|
||||
OSL::print(out, " ({} in scope {})", m_sym->name(), m_sym->scope());
|
||||
#endif
|
||||
out << "\n";
|
||||
OSL::print(out, "\n");
|
||||
printchildren(out, indentlevel);
|
||||
indent(out, indentlevel);
|
||||
out << ")\n";
|
||||
OSL::print(out, ")\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -640,17 +640,17 @@ ASTvariable_ref::ASTvariable_ref(OSLCompilerImpl* comp, ustring name)
|
||||
{
|
||||
m_sym = comp->symtab().find(name);
|
||||
if (!m_sym) {
|
||||
errorf("'%s' was not declared in this scope", name);
|
||||
errorfmt("'{}' was not declared in this scope", name);
|
||||
// FIXME -- would be fun to troll through the symtab and try to
|
||||
// find the things that almost matched and offer suggestions.
|
||||
return;
|
||||
}
|
||||
if (m_sym->symtype() == SymTypeFunction) {
|
||||
errorf("function '%s' can't be used as a variable", name);
|
||||
errorfmt("function '{}' can't be used as a variable", name);
|
||||
return;
|
||||
}
|
||||
if (m_sym->symtype() == SymTypeType) {
|
||||
errorf("type name '%s' can't be used as a variable", name);
|
||||
errorfmt("type name '{}' can't be used as a variable", name);
|
||||
return;
|
||||
}
|
||||
m_typespec = m_sym->typespec();
|
||||
@@ -662,9 +662,9 @@ void
|
||||
ASTvariable_ref::print(std::ostream& out, int indentlevel) const
|
||||
{
|
||||
indent(out, indentlevel);
|
||||
out << "(" << nodetypename()
|
||||
<< " (type: " << (m_sym ? m_sym->typespec().string() : "unknown")
|
||||
<< ") " << (m_sym ? m_sym->mangled() : m_name.string()) << ")\n";
|
||||
OSL::print(out, "({} (type: {}) {})\n", nodetypename(),
|
||||
m_sym ? m_sym->typespec().string() : "unknown",
|
||||
m_sym ? m_sym->mangled() : m_name.string());
|
||||
OSL_DASSERT(nchildren() == 0);
|
||||
}
|
||||
|
||||
@@ -762,7 +762,7 @@ ASTindex::ASTindex(OSLCompilerImpl* comp, ASTNode* expr, ASTNode* index,
|
||||
}
|
||||
|
||||
if (m_typespec.is_unknown()) {
|
||||
errorf("indexing into non-array or non-component type");
|
||||
errorfmt("indexing into non-array or non-component type");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -827,7 +827,7 @@ ASTstructselect::find_fieldsym(int& structid, int& fieldid)
|
||||
}
|
||||
|
||||
if (!lvtype.is_structure() && !lvtype.is_structure_array()) {
|
||||
errorf("type '%s' does not have a member '%s'", lvtype, m_field);
|
||||
errorfmt("type '{}' does not have a member '{}'", lvtype, m_field);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -846,14 +846,14 @@ ASTstructselect::find_fieldsym(int& structid, int& fieldid)
|
||||
}
|
||||
|
||||
if (fieldid < 0) {
|
||||
errorf("struct type '%s' does not have a member '%s'",
|
||||
structspec->name(), m_field);
|
||||
errorfmt("struct type '{}' does not have a member '{}'",
|
||||
structspec->name(), m_field);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const StructSpec::FieldSpec& fieldrec(structspec->field(fieldid));
|
||||
ustring fieldsymname = ustring::sprintf("%s.%s", structsymname,
|
||||
fieldrec.name);
|
||||
ustring fieldsymname = ustring::fmtformat("{}.{}", structsymname,
|
||||
fieldrec.name);
|
||||
Symbol* sym = m_compiler->symtab().find(fieldsymname);
|
||||
return sym;
|
||||
}
|
||||
@@ -914,7 +914,7 @@ ASTstructselect::print(std::ostream& out, int indentlevel) const
|
||||
{
|
||||
ASTNode::print(out, indentlevel);
|
||||
indent(out, indentlevel + 1);
|
||||
out << "select " << field() << "\n";
|
||||
OSL::print(out, "select {}\n", field());
|
||||
}
|
||||
|
||||
|
||||
@@ -964,7 +964,8 @@ ASTloop_statement::opname() const
|
||||
|
||||
|
||||
|
||||
const char* ASTloopmod_statement::childname(size_t /*i*/) const
|
||||
const char*
|
||||
ASTloopmod_statement::childname(size_t /*i*/) const
|
||||
{
|
||||
return NULL; // no children
|
||||
}
|
||||
@@ -983,7 +984,8 @@ ASTloopmod_statement::opname() const
|
||||
|
||||
|
||||
|
||||
const char* ASTreturn_statement::childname(size_t /*i*/) const
|
||||
const char*
|
||||
ASTreturn_statement::childname(size_t /*i*/) const
|
||||
{
|
||||
return "expression"; // only child
|
||||
}
|
||||
@@ -999,7 +1001,8 @@ ASTcompound_initializer::ASTcompound_initializer(OSLCompilerImpl* comp,
|
||||
|
||||
|
||||
|
||||
const char* ASTcompound_initializer::childname(size_t /*i*/) const
|
||||
const char*
|
||||
ASTcompound_initializer::childname(size_t /*i*/) const
|
||||
{
|
||||
return canconstruct() ? "args" : "expression_list";
|
||||
}
|
||||
@@ -1029,8 +1032,8 @@ ASTNode::check_symbol_writeability(ASTNode* var, bool quiet, Symbol** dest_sym)
|
||||
*dest_sym = dest;
|
||||
if (dest->readonly()) {
|
||||
if (!quiet)
|
||||
warningf("cannot write to non-output parameter \"%s\"",
|
||||
dest->name());
|
||||
warningfmt("cannot write to non-output parameter \"{}\"",
|
||||
dest->name());
|
||||
// Note: Consider it only a warning to write to a non-output
|
||||
// parameter. Users who want it to be a hard error can use
|
||||
// -Werror. Writing to any other readonly symbols is a full
|
||||
@@ -1038,8 +1041,8 @@ ASTNode::check_symbol_writeability(ASTNode* var, bool quiet, Symbol** dest_sym)
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// std::cout << "Don't know how to check_symbol_writeability "
|
||||
// << var->nodetypename() << "\n";
|
||||
// OSL::print("Don't know how to check_symbol_writeability {}\n",
|
||||
// var->nodetypename());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1122,7 +1125,7 @@ ASTunary_expression::ASTunary_expression (OSLCompilerImpl *comp, int op,
|
||||
: ASTNode (unary_expression_node, comp, op, expr)
|
||||
{
|
||||
// Check for a user-overloaded function for this operator
|
||||
Symbol *sym = comp->symtab().find (ustring::sprintf ("__operator__%s__", opword()));
|
||||
Symbol *sym = comp->symtab().find(ustring::fmtformat("__operator__{}__", opword()));
|
||||
if (sym && sym->symtype() == SymTypeFunction)
|
||||
m_function_overload = (FunctionSymbol *)sym;
|
||||
}
|
||||
@@ -1177,7 +1180,7 @@ ASTbinary_expression::ASTbinary_expression (OSLCompilerImpl *comp, Operator op,
|
||||
// Check for a user-overloaded function for this operator.
|
||||
// Disallow a few ops from overloading.
|
||||
if (op != And && op != Or) {
|
||||
ustring funcname = ustring::sprintf ("__operator__%s__", opword());
|
||||
ustring funcname = ustring::fmtformat("__operator__{}__", opword());
|
||||
Symbol *sym = comp->symtab().find (funcname);
|
||||
if (sym && sym->symtype() == SymTypeFunction)
|
||||
m_function_overload = (FunctionSymbol *)sym;
|
||||
@@ -1298,7 +1301,7 @@ ASTfunction_call::ASTfunction_call(OSLCompilerImpl* comp, ustring name,
|
||||
, m_argtakesderivs(0) // Default - doesn't take derivs
|
||||
{
|
||||
if (!m_sym) {
|
||||
errorf("function '%s' was not declared in this scope", name);
|
||||
errorfmt("function '{}' was not declared in this scope", name);
|
||||
// FIXME -- would be fun to troll through the symtab and try to
|
||||
// find the things that almost matched and offer suggestions.
|
||||
return;
|
||||
@@ -1307,7 +1310,7 @@ ASTfunction_call::ASTfunction_call(OSLCompilerImpl* comp, ustring name,
|
||||
return; // It's a struct constructor
|
||||
}
|
||||
if (m_sym->symtype() != SymTypeFunction) {
|
||||
errorf("'%s' is not a function", name);
|
||||
errorfmt("'{}' is not a function", name);
|
||||
m_sym = NULL;
|
||||
return;
|
||||
}
|
||||
@@ -1318,7 +1321,7 @@ ASTfunction_call::ASTfunction_call(OSLCompilerImpl* comp, ustring name,
|
||||
const char*
|
||||
ASTfunction_call::childname(size_t i) const
|
||||
{
|
||||
return ustring::sprintf("param%d", (int)i).c_str();
|
||||
return ustring::fmtformat("param{}", (int)i).c_str();
|
||||
}
|
||||
|
||||
|
||||
@@ -1337,16 +1340,17 @@ ASTfunction_call::print(std::ostream& out, int indentlevel) const
|
||||
ASTNode::print(out, indentlevel);
|
||||
#if 0
|
||||
if (is_user_function()) {
|
||||
out << "\n";
|
||||
OSL::print(out, "\n");
|
||||
user_function()->print (out, indentlevel+1);
|
||||
out << "\n";
|
||||
OSL::print(out, "\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char* ASTliteral::childname(size_t /*i*/) const
|
||||
const char*
|
||||
ASTliteral::childname(size_t /*i*/) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -1357,14 +1361,14 @@ void
|
||||
ASTliteral::print(std::ostream& out, int indentlevel) const
|
||||
{
|
||||
indent(out, indentlevel);
|
||||
out << "(" << nodetypename() << " (type: " << m_typespec.string() << ") ";
|
||||
OSL::print(out, "({} (type: {}) ", nodetypename(), m_typespec);
|
||||
if (m_typespec.is_int())
|
||||
out << m_i;
|
||||
OSL::print(out, "{}", m_i);
|
||||
else if (m_typespec.is_float())
|
||||
out << m_f;
|
||||
OSL::print(out, "{}", m_f);
|
||||
else if (m_typespec.is_string())
|
||||
out << "\"" << m_s << "\"";
|
||||
out << ")\n";
|
||||
OSL::print(out, "\"{}\"", m_s);
|
||||
OSL::print(out, ")\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
+12
-11
@@ -202,34 +202,34 @@ public:
|
||||
void sourceline(int line) { m_sourceline = line; }
|
||||
|
||||
template<typename... Args>
|
||||
void errorf(const char* format, const Args&... args) const
|
||||
void errorfmt(const char* format, const Args&... args) const
|
||||
{
|
||||
OSL_DASSERT(format && format[0]);
|
||||
error_impl(OIIO::Strutil::sprintf(format, args...));
|
||||
error_impl(OIIO::Strutil::fmt::format(format, args...));
|
||||
}
|
||||
|
||||
/// Warning reporting
|
||||
template<typename... Args>
|
||||
void warningf(const char* format, const Args&... args) const
|
||||
void warningfmt(const char* format, const Args&... args) const
|
||||
{
|
||||
OSL_DASSERT(format && format[0]);
|
||||
warning_impl(OIIO::Strutil::sprintf(format, args...));
|
||||
warning_impl(OIIO::Strutil::fmt::format(format, args...));
|
||||
}
|
||||
|
||||
/// info reporting
|
||||
template<typename... Args>
|
||||
void infof(const char* format, const Args&... args) const
|
||||
void infofmt(const char* format, const Args&... args) const
|
||||
{
|
||||
OSL_DASSERT(format && format[0]);
|
||||
info_impl(OIIO::Strutil::sprintf(format, args...));
|
||||
info_impl(OIIO::Strutil::fmt::format(format, args...));
|
||||
}
|
||||
|
||||
/// message reporting
|
||||
template<typename... Args>
|
||||
void messagef(const char* format, const Args&... args) const
|
||||
void messagefmt(const char* format, const Args&... args) const
|
||||
{
|
||||
OSL_DASSERT(format && format[0]);
|
||||
message_impl(OIIO::Strutil::sprintf(format, args...));
|
||||
message_impl(OIIO::Strutil::fmt::format(format, args...));
|
||||
}
|
||||
|
||||
bool is_lvalue() const { return m_is_lvalue; }
|
||||
@@ -375,7 +375,7 @@ protected:
|
||||
void codegen_initlist(ref init, TypeSpec type, Symbol* sym);
|
||||
|
||||
// Special code generation for structure initializers.
|
||||
// It's in the ASTNode base class because it's used from mutiple
|
||||
// It's in the ASTNode base class because it's used from multiple
|
||||
// subclasses.
|
||||
Symbol* codegen_struct_initializers(ref init, Symbol* sym,
|
||||
bool is_constructor = false,
|
||||
@@ -520,7 +520,7 @@ public:
|
||||
|
||||
private:
|
||||
ustring m_name; ///< Name of the symbol (unmangled)
|
||||
Symbol* m_sym; ///< Ptr to the symbol this declares
|
||||
Symbol* m_sym; ///< Ptr to the symbol this declares (non-owning)
|
||||
bool m_isparam; ///< Is this a parameter?
|
||||
bool m_isoutput; ///< Is this an output parameter?
|
||||
bool m_ismetadata; ///< Is this declaration a piece of metadata?
|
||||
@@ -529,6 +529,7 @@ private:
|
||||
// specific initializers.
|
||||
typedef std::pair<ustring, ASTNode*> NamedInit;
|
||||
std::vector<NamedInit> m_struct_field_inits;
|
||||
std::unique_ptr<Symbol> m_sym_owned; // if we own the symbol
|
||||
};
|
||||
|
||||
|
||||
@@ -949,7 +950,7 @@ private:
|
||||
/// return false and call an appropriate error().
|
||||
bool typecheck_printf_args(const char* format, ASTNode* arg);
|
||||
|
||||
/// Handle "funcion calls" that are really struct ctrs.
|
||||
/// Handle "function calls" that are really struct ctrs.
|
||||
TypeSpec typecheck_struct_constructor();
|
||||
|
||||
/// Is the argument number 'arg' read by the op?
|
||||
|
||||
+58
-58
@@ -101,7 +101,7 @@ OSLCompilerImpl::insert_code(int opnum, const char* opname, size_t nargs,
|
||||
Symbol*
|
||||
OSLCompilerImpl::make_temporary(const TypeSpec& type)
|
||||
{
|
||||
ustring name = ustring::sprintf("$tmp%d", ++m_next_temp);
|
||||
ustring name = ustring::fmtformat("$tmp{}", ++m_next_temp);
|
||||
Symbol* s = new Symbol(name, type, SymTypeTemp);
|
||||
symtab().insert(s);
|
||||
|
||||
@@ -131,14 +131,15 @@ OSLCompilerImpl::add_struct_fields(StructSpec* structspec, ustring basename,
|
||||
// arraylen is the length of the array of the surrounding data type
|
||||
for (int i = 0; i < (int)structspec->numfields(); ++i) {
|
||||
const StructSpec::FieldSpec& field(structspec->field(i));
|
||||
ustring fieldname = ustring::sprintf("%s.%s", basename, field.name);
|
||||
ustring fieldname = ustring::fmtformat("{}.{}", basename, field.name);
|
||||
TypeSpec type = field.type;
|
||||
int arr = type.arraylength();
|
||||
if (arr && arraylen) {
|
||||
errorf(node ? node->sourcefile() : ustring(),
|
||||
node ? node->sourceline() : 1,
|
||||
"Nested structs with >1 levels of arrays are not allowed: %s",
|
||||
structspec->name());
|
||||
errorfmt(
|
||||
node ? node->sourcefile() : ustring(),
|
||||
node ? node->sourceline() : 1,
|
||||
"Nested structs with >1 levels of arrays are not allowed: {}",
|
||||
structspec->name());
|
||||
}
|
||||
if (arraylen || arr) {
|
||||
// Translate an outer array into an inner array
|
||||
@@ -174,7 +175,7 @@ OSLCompilerImpl::make_constant(ustring val)
|
||||
return sym;
|
||||
}
|
||||
// It's not a constant we've added before
|
||||
ustring name = ustring::sprintf("$const%d", ++m_next_const);
|
||||
ustring name = ustring::fmtformat("$const{}", ++m_next_const);
|
||||
ConstantSymbol* s = new ConstantSymbol(name, val);
|
||||
symtab().insert(s);
|
||||
m_const_syms.push_back(s);
|
||||
@@ -193,7 +194,7 @@ OSLCompilerImpl::make_constant(TypeDesc type, const void* val)
|
||||
return sym;
|
||||
}
|
||||
// It's not a constant we've added before
|
||||
ustring name = ustring::sprintf("$const%d", ++m_next_const);
|
||||
ustring name = ustring::fmtformat("$const{}", ++m_next_const);
|
||||
ConstantSymbol* s = new ConstantSymbol(name, type);
|
||||
memcpy(s->dataptr(), val, typesize);
|
||||
symtab().insert(s);
|
||||
@@ -211,7 +212,7 @@ OSLCompilerImpl::make_constant(int val)
|
||||
return sym;
|
||||
}
|
||||
// It's not a constant we've added before
|
||||
ustring name = ustring::sprintf("$const%d", ++m_next_const);
|
||||
ustring name = ustring::fmtformat("$const{}", ++m_next_const);
|
||||
ConstantSymbol* s = new ConstantSymbol(name, val);
|
||||
symtab().insert(s);
|
||||
m_const_syms.push_back(s);
|
||||
@@ -228,7 +229,7 @@ OSLCompilerImpl::make_constant(float val)
|
||||
return sym;
|
||||
}
|
||||
// It's not a constant we've added before
|
||||
ustring name = ustring::sprintf("$const%d", ++m_next_const);
|
||||
ustring name = ustring::fmtformat("$const{}", ++m_next_const);
|
||||
ConstantSymbol* s = new ConstantSymbol(name, val);
|
||||
symtab().insert(s);
|
||||
m_const_syms.push_back(s);
|
||||
@@ -246,7 +247,7 @@ OSLCompilerImpl::make_constant(TypeDesc type, float x, float y, float z)
|
||||
return sym;
|
||||
}
|
||||
// It's not a constant we've added before
|
||||
ustring name = ustring::sprintf("$const%d", ++m_next_const);
|
||||
ustring name = ustring::fmtformat("$const{}", ++m_next_const);
|
||||
ConstantSymbol* s = new ConstantSymbol(name, type, x, y, z);
|
||||
symtab().insert(s);
|
||||
m_const_syms.push_back(s);
|
||||
@@ -453,9 +454,9 @@ ASTcompound_initializer::codegen(Symbol* sym)
|
||||
return sym;
|
||||
}
|
||||
|
||||
errorf("Possible compiler bug: compound_initializer codegen does not "
|
||||
"know how to handle type %s",
|
||||
typespec());
|
||||
errorfmt("Possible compiler bug: compound_initializer codegen does not "
|
||||
"know how to handle type {}",
|
||||
typespec());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -549,8 +550,8 @@ ASTNode::codegen_assign_struct(StructSpec* structspec, ustring dstsym,
|
||||
// struct within struct -- recurse
|
||||
ustring fieldname(structspec->field(i).name);
|
||||
codegen_assign_struct(fieldtype.structspec(),
|
||||
ustring::sprintf("%s.%s", dstsym, fieldname),
|
||||
ustring::sprintf("%s.%s", srcsym, fieldname),
|
||||
ustring::fmtformat("{}.{}", dstsym, fieldname),
|
||||
ustring::fmtformat("{}.{}", srcsym, fieldname),
|
||||
arrayindex, copywholearrays, 0, paraminit);
|
||||
continue;
|
||||
}
|
||||
@@ -559,8 +560,8 @@ ASTNode::codegen_assign_struct(StructSpec* structspec, ustring dstsym,
|
||||
// struct array within struct -- loop over indices and recurse
|
||||
OSL_ASSERT(!arrayindex && "two levels of arrays not allowed");
|
||||
ustring fieldname(structspec->field(i).name);
|
||||
ustring dstfield = ustring::sprintf("%s.%s", dstsym, fieldname);
|
||||
ustring srcfield = ustring::sprintf("%s.%s", srcsym, fieldname);
|
||||
ustring dstfield = ustring::fmtformat("{}.{}", dstsym, fieldname);
|
||||
ustring srcfield = ustring::fmtformat("{}.{}", srcsym, fieldname);
|
||||
for (int i = 0; i < fieldtype.arraylength(); ++i) {
|
||||
codegen_assign_struct(fieldtype.structspec(), dstfield,
|
||||
srcfield, m_compiler->make_constant(i),
|
||||
@@ -631,16 +632,16 @@ ASTNode::one_default_literal(const Symbol* sym, ASTNode* init, std::string& out,
|
||||
completed = false;
|
||||
} else if (type.is_int()) {
|
||||
if (islit && lit->typespec().is_int())
|
||||
out += Strutil::sprintf("%d", lit->intval());
|
||||
out += fmtformat("{}", lit->intval());
|
||||
else {
|
||||
out += "0"; // FIXME?
|
||||
completed = false;
|
||||
}
|
||||
} else if (type.is_float()) {
|
||||
if (islit && lit->typespec().is_int())
|
||||
out += Strutil::sprintf("%d", lit->intval());
|
||||
out += fmtformat("{}", lit->intval());
|
||||
else if (islit && lit->typespec().is_float())
|
||||
out += Strutil::sprintf("%.9g", lit->floatval());
|
||||
out += fmtformat("{:.9g}", lit->floatval());
|
||||
else {
|
||||
out += "0"; // FIXME?
|
||||
completed = false;
|
||||
@@ -648,10 +649,10 @@ ASTNode::one_default_literal(const Symbol* sym, ASTNode* init, std::string& out,
|
||||
} else if (type.is_triple()) {
|
||||
if (islit && lit->typespec().is_int()) {
|
||||
float f = lit->intval();
|
||||
out += Strutil::sprintf("%.9g%s%.9g%s%.9g", f, sep, f, sep, f);
|
||||
out += fmtformat("{:.9g}{}{:.9g}{}{:.9g}", f, sep, f, sep, f);
|
||||
} else if (islit && lit->typespec().is_float()) {
|
||||
float f = lit->floatval();
|
||||
out += Strutil::sprintf("%.9g%s%.9g%s%.9g", f, sep, f, sep, f);
|
||||
out += fmtformat("{:.9g}{}{:.9g}{}{:.9g}", f, sep, f, sep, f);
|
||||
} else if (init && init->typespec() == type
|
||||
&& (init->nodetype() == ASTNode::type_constructor_node
|
||||
|| (init->nodetype() == ASTNode::compound_initializer_node
|
||||
@@ -681,26 +682,26 @@ ASTNode::one_default_literal(const Symbol* sym, ASTNode* init, std::string& out,
|
||||
}
|
||||
}
|
||||
if (nargs == 1)
|
||||
out += Strutil::sprintf("%.9g%s%.9g%s%.9g", f[0], sep, f[0],
|
||||
sep, f[0]);
|
||||
out += fmtformat("{:.9g}{}{:.9g}{}{:.9g}", f[0], sep, f[0], sep,
|
||||
f[0]);
|
||||
else
|
||||
out += Strutil::sprintf("%.9g%s%.9g%s%.9g", f[0], sep, f[1],
|
||||
sep, f[2]);
|
||||
out += fmtformat("{:.9g}{}{:.9g}{}{:.9g}", f[0], sep, f[1], sep,
|
||||
f[2]);
|
||||
} else {
|
||||
out += Strutil::sprintf("0%s0%s0", sep, sep);
|
||||
out += fmtformat("0{}0{}0", sep, sep);
|
||||
completed = false;
|
||||
}
|
||||
} else if (type.is_matrix()) {
|
||||
if (islit && lit->typespec().is_int()) {
|
||||
float f = lit->intval();
|
||||
for (int c = 0; c < 16; ++c)
|
||||
out += Strutil::sprintf("%.9g%s", (c / 4) == (c % 4) ? f : 0.0f,
|
||||
c < 15 ? sep : "");
|
||||
out += fmtformat("{:.9g}{}", (c / 4) == (c % 4) ? f : 0.0f,
|
||||
c < 15 ? sep : "");
|
||||
} else if (islit && lit->typespec().is_float()) {
|
||||
float f = lit->floatval();
|
||||
for (int c = 0; c < 16; ++c)
|
||||
out += Strutil::sprintf("%.9g%s", (c / 4) == (c % 4) ? f : 0.0f,
|
||||
c < 15 ? sep : "");
|
||||
out += fmtformat("{:.9g}{}", (c / 4) == (c % 4) ? f : 0.0f,
|
||||
c < 15 ? sep : "");
|
||||
} else if (init && init->typespec() == type
|
||||
&& init->nodetype() == ASTNode::type_constructor_node) {
|
||||
ASTtype_constructor* ctr = (ASTtype_constructor*)init;
|
||||
@@ -728,22 +729,21 @@ ASTNode::one_default_literal(const Symbol* sym, ASTNode* init, std::string& out,
|
||||
}
|
||||
if (nargs == 1) {
|
||||
for (int c = 0; c < 16; ++c)
|
||||
out += Strutil::sprintf("%.9g%s",
|
||||
(c / 4) == (c % 4) ? f[0] : 0.0f,
|
||||
c < 15 ? sep : "");
|
||||
out += fmtformat("{:.9g}{}",
|
||||
(c / 4) == (c % 4) ? f[0] : 0.0f,
|
||||
c < 15 ? sep : "");
|
||||
} else {
|
||||
for (int c = 0; c < 16; ++c)
|
||||
out += Strutil::sprintf("%.9g%s", f[c], c < 15 ? sep : "");
|
||||
out += fmtformat("{:.9g}{}", f[c], c < 15 ? sep : "");
|
||||
}
|
||||
} else {
|
||||
for (int c = 0; c < 16; ++c)
|
||||
out += Strutil::sprintf("0%s", c < 15 ? sep : "");
|
||||
out += fmtformat("0{}", c < 15 ? sep : "");
|
||||
completed = false;
|
||||
}
|
||||
} else if (type.is_string()) {
|
||||
if (islit && lit->typespec().is_string())
|
||||
out += Strutil::sprintf("\"%s\"",
|
||||
Strutil::escape_chars(lit->strval()));
|
||||
out += fmtformat("\"{}\"", Strutil::escape_chars(lit->strval()));
|
||||
else {
|
||||
out += "\"\""; // FIXME?
|
||||
completed = false;
|
||||
@@ -902,8 +902,8 @@ ASTNode::codegen_initlist(ref init, TypeSpec type, Symbol* sym)
|
||||
for (int i = 0; init && i < structspec->numfields();
|
||||
init = init->next(), ++i) {
|
||||
const StructSpec::FieldSpec& field(structspec->field(i));
|
||||
ustring fieldname = ustring::sprintf("%s.%s", sym->mangled(),
|
||||
field.name);
|
||||
ustring fieldname = ustring::fmtformat("{}.{}", sym->mangled(),
|
||||
field.name);
|
||||
Symbol* fieldsym = m_compiler->symtab().find_exact(fieldname);
|
||||
if (paraminit) {
|
||||
OSL_DASSERT(nodetype() == variable_declaration_node);
|
||||
@@ -918,10 +918,10 @@ ASTNode::codegen_initlist(ref init, TypeSpec type, Symbol* sym)
|
||||
}
|
||||
|
||||
if (paraminit) {
|
||||
// Warn early about struct array paramters.
|
||||
// Warn early about struct array parameters.
|
||||
// Handling this will likely need changes to oso format.
|
||||
if (type.is_structure_array()) {
|
||||
errorf("array of struct are not allowed as parameters");
|
||||
errorfmt("array of struct are not allowed as parameters");
|
||||
return;
|
||||
}
|
||||
// For parameter initialization, don't really generate ops if it
|
||||
@@ -1072,8 +1072,8 @@ ASTNode::codegen_struct_initializers(ref init, Symbol* sym, bool is_constructor,
|
||||
init = init->next(), ++i) {
|
||||
// Structure element -- assign to the i-th member field
|
||||
const StructSpec::FieldSpec& field(structspec->field(i));
|
||||
ustring fieldname = ustring::sprintf("%s.%s", sym->mangled(),
|
||||
field.name);
|
||||
ustring fieldname = ustring::fmtformat("{}.{}", sym->mangled(),
|
||||
field.name);
|
||||
Symbol* fieldsym = m_compiler->symtab().find_exact(fieldname);
|
||||
if (fieldsym->typespec().is_structure_based()
|
||||
&& (init->nodetype() == type_constructor_node
|
||||
@@ -1239,8 +1239,8 @@ ASTindex::codegen_copy_struct_array_element(StructSpec* structspec,
|
||||
// struct within struct -- recurse!
|
||||
codegen_copy_struct_array_element(
|
||||
type.structspec(),
|
||||
ustring::sprintf("%s.%s", destname, field.name),
|
||||
ustring::sprintf("%s.%s", srcname, field.name), index);
|
||||
ustring::fmtformat("{}.{}", destname, field.name),
|
||||
ustring::fmtformat("{}.{}", srcname, field.name), index);
|
||||
} else {
|
||||
OSL_ASSERT(!type.is_array());
|
||||
Symbol *dfield, *sfield;
|
||||
@@ -1463,7 +1463,7 @@ ASTunary_expression::codegen(Symbol* dest)
|
||||
if (m_function_overload) {
|
||||
// A little crazy, but we temporarily construct an ASTfunction_call
|
||||
// in order to codegen this overloaded operator.
|
||||
ustring funcname = ustring::sprintf("__operator__%s__", opword());
|
||||
ustring funcname = ustring::fmtformat("__operator__{}__", opword());
|
||||
ASTfunction_call fc(m_compiler, funcname, expr().get(),
|
||||
m_function_overload);
|
||||
fc.typecheck(typespec());
|
||||
@@ -1511,10 +1511,10 @@ ASTbinary_expression::codegen(Symbol* dest)
|
||||
// in order to codegen this overloaded operator. Slightly tricky
|
||||
// is that we need to concatenate our left and right arguments into
|
||||
// an arg list.
|
||||
ustring funcname = ustring::sprintf("__operator__%s__", opword());
|
||||
ustring funcname = ustring::fmtformat("__operator__{}__", opword());
|
||||
if (left()->nextptr() || right()->nextptr()) {
|
||||
errorf("Overloaded %s cannot be passed arguments %s and %s",
|
||||
funcname, left()->nodetypename(), right()->nodetypename());
|
||||
errorfmt("Overloaded %s cannot be passed arguments {} and {}",
|
||||
funcname, left()->nodetypename(), right()->nodetypename());
|
||||
return dest;
|
||||
}
|
||||
ref args = left();
|
||||
@@ -1994,10 +1994,10 @@ ASTfunction_call::codegen_arg(SymbolPtrVec& argdest, SymbolPtrVec& index1,
|
||||
&& !equivalent(origarg->typespec(), form->typespec())
|
||||
&& form->nodetype() == variable_declaration_node
|
||||
&& ((ASTvariable_declaration*)form)->is_output()) {
|
||||
errorf("Cannot pass '%s %s' as argument %d to %s\n\t"
|
||||
"because it is an output parameter that must be a %s",
|
||||
origarg->typespec(), origarg->name(), argnum + 1,
|
||||
user_function()->func()->name(), form->typespec());
|
||||
errorfmt("Cannot pass '{} {}' as argument {} to {}\n\t"
|
||||
"because it is an output parameter that must be a %s",
|
||||
origarg->typespec(), origarg->name(), argnum + 1,
|
||||
user_function()->func()->name(), form->typespec());
|
||||
}
|
||||
}
|
||||
if (thisarg) {
|
||||
@@ -2006,7 +2006,7 @@ ASTfunction_call::codegen_arg(SymbolPtrVec& argdest, SymbolPtrVec& index1,
|
||||
index2.push_back(ind2);
|
||||
index3.push_back(ind3);
|
||||
} else
|
||||
arg->errorf("Invalid argument to function");
|
||||
arg->errorfmt("Invalid argument to function");
|
||||
}
|
||||
|
||||
|
||||
@@ -2022,8 +2022,8 @@ ASTfunction_call::struct_pair_all_fields(StructSpec* structspec, ustring formal,
|
||||
// struct within struct -- recurse!
|
||||
struct_pair_all_fields(
|
||||
type.structspec(),
|
||||
ustring::sprintf("%s.%s", formal, field.name),
|
||||
ustring::sprintf("%s.%s", actual, field.name), arrayindex);
|
||||
ustring::fmtformat("{}.{}", formal, field.name),
|
||||
ustring::fmtformat("{}.{}", actual, field.name), arrayindex);
|
||||
} else {
|
||||
Symbol *fsym, *asym;
|
||||
m_compiler->struct_field_pair(structspec, fi, formal, actual, fsym,
|
||||
|
||||
+42
-41
@@ -131,7 +131,7 @@ OSLCompilerImpl::preprocess_file(const std::string& filename,
|
||||
// Read file contents into a string
|
||||
std::string instring;
|
||||
if (!OIIO::Filesystem::read_text_file(filename, instring)) {
|
||||
errorf(ustring(filename), 0, "Could not open \"%s\"\n", filename);
|
||||
errorfmt(ustring(filename), 0, "Could not open \"{}\"\n", filename);
|
||||
return false;
|
||||
}
|
||||
return preprocess_buffer(instring, filename, stdoslpath, defines,
|
||||
@@ -148,11 +148,11 @@ OSLCompilerImpl::preprocess_buffer(const std::string& buffer,
|
||||
const std::vector<std::string>& includepaths,
|
||||
std::string& result)
|
||||
{
|
||||
using OIIO::Strutil::fmt::format;
|
||||
std::string instring;
|
||||
if (!stdoslpath.empty()) {
|
||||
instring
|
||||
= OIIO::Strutil::sprintf("#include \"%s\"\n",
|
||||
OIIO::Strutil::escape_chars(stdoslpath));
|
||||
instring = format("#include \"{}\"\n",
|
||||
OIIO::Strutil::escape_chars(stdoslpath));
|
||||
// Note: because we're turning this from a regular string into a
|
||||
// double-quoted string injected into the OSL parse stream, we need
|
||||
// to fully escape any backslashes used in Windows file paths. We
|
||||
@@ -217,14 +217,13 @@ OSLCompilerImpl::preprocess_buffer(const std::string& buffer,
|
||||
|
||||
clang::PreprocessorOptions& preprocOpts = inst.getPreprocessorOpts();
|
||||
preprocOpts.UsePredefines = 0;
|
||||
preprocOpts.addMacroDef(OIIO::Strutil::sprintf("OSL_VERSION_MAJOR=%d",
|
||||
OSL_LIBRARY_VERSION_MAJOR));
|
||||
preprocOpts.addMacroDef(OIIO::Strutil::sprintf("OSL_VERSION_MINOR=%d",
|
||||
OSL_LIBRARY_VERSION_MINOR));
|
||||
preprocOpts.addMacroDef(OIIO::Strutil::sprintf("OSL_VERSION_PATCH=%d",
|
||||
OSL_LIBRARY_VERSION_PATCH));
|
||||
preprocOpts.addMacroDef(
|
||||
OIIO::Strutil::sprintf("OSL_VERSION=%d", OSL_LIBRARY_VERSION_CODE));
|
||||
format("OSL_VERSION_MAJOR={}", OSL_LIBRARY_VERSION_MAJOR));
|
||||
preprocOpts.addMacroDef(
|
||||
format("OSL_VERSION_MINOR={}", OSL_LIBRARY_VERSION_MINOR));
|
||||
preprocOpts.addMacroDef(
|
||||
format("OSL_VERSION_PATCH={}", OSL_LIBRARY_VERSION_PATCH));
|
||||
preprocOpts.addMacroDef(format("OSL_VERSION={}", OSL_LIBRARY_VERSION_CODE));
|
||||
for (auto&& d : defines) {
|
||||
if (d[1] == 'D')
|
||||
preprocOpts.addMacroDef(d.c_str() + 2);
|
||||
@@ -245,7 +244,7 @@ OSLCompilerImpl::preprocess_buffer(const std::string& buffer,
|
||||
while (preproc_errors.size()
|
||||
&& preproc_errors[preproc_errors.size() - 1] == '\n')
|
||||
preproc_errors.erase(preproc_errors.size() - 1);
|
||||
errorf(ustring(), -1, "%s", preproc_errors);
|
||||
errorfmt(ustring(), -1, "{}", preproc_errors);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -342,8 +341,8 @@ find_stdoslpath(const std::vector<std::string>& includepaths)
|
||||
|
||||
// If that doesn't work, look in a bunch of likely places.
|
||||
|
||||
std::string install_loc = OIIO::Strutil::sprintf("%s/stdosl.h",
|
||||
OSL_SHADER_INSTALL_DIR);
|
||||
std::string install_loc
|
||||
= OIIO::Strutil::fmt::format("{}/stdosl.h", OSL_SHADER_INSTALL_DIR);
|
||||
if (OIIO::Filesystem::exists(install_loc))
|
||||
return ustring(install_loc);
|
||||
|
||||
@@ -407,7 +406,7 @@ OSLCompilerImpl::compile(string_view filename,
|
||||
string_view stdoslpath)
|
||||
{
|
||||
if (!OIIO::Filesystem::exists(filename)) {
|
||||
errorf(ustring(), 0, "Input file \"%s\" not found", filename);
|
||||
errorfmt(ustring(), 0, "Input file \"{}\" not found", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -425,7 +424,7 @@ OSLCompilerImpl::compile(string_view filename,
|
||||
stdoslpath = find_stdoslpath(includepaths);
|
||||
}
|
||||
if (stdoslpath.empty() || !OIIO::Filesystem::exists(stdoslpath))
|
||||
warningf(ustring(filename), 0, "Unable to find \"stdosl.h\"");
|
||||
warningfmt(ustring(filename), 0, "Unable to find \"stdosl.h\"");
|
||||
else {
|
||||
// Add the directory of stdosl.h to the include paths
|
||||
includepaths.push_back(OIIO::Filesystem::parent_path(stdoslpath));
|
||||
@@ -445,7 +444,7 @@ OSLCompilerImpl::compile(string_view filename,
|
||||
if (shader())
|
||||
shader()->typecheck();
|
||||
else
|
||||
errorf(ustring(), 0, "No shader function defined");
|
||||
errorfmt(ustring(), 0, "No shader function defined");
|
||||
}
|
||||
|
||||
// Print the parse tree if there were no errors
|
||||
@@ -474,8 +473,8 @@ OSLCompilerImpl::compile(string_view filename,
|
||||
OIIO::ofstream oso_output;
|
||||
OIIO::Filesystem::open(oso_output, m_output_filename);
|
||||
if (!oso_output.good()) {
|
||||
errorf(ustring(), 0, "Could not open \"%s\"",
|
||||
m_output_filename);
|
||||
errorfmt(ustring(), 0, "Could not open \"{}\"",
|
||||
m_output_filename);
|
||||
return false;
|
||||
}
|
||||
OSL_DASSERT(m_osofile == nullptr);
|
||||
@@ -487,8 +486,8 @@ OSLCompilerImpl::compile(string_view filename,
|
||||
|
||||
oso_output.close();
|
||||
if (!oso_output.good()) {
|
||||
errorf(ustring(), 0, "Failed to write to \"%s\"",
|
||||
m_output_filename);
|
||||
errorfmt(ustring(), 0, "Failed to write to \"{}\"",
|
||||
m_output_filename);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -521,7 +520,7 @@ OSLCompilerImpl::compile_buffer(string_view sourcecode, std::string& osobuffer,
|
||||
stdoslpath = find_stdoslpath(includepaths);
|
||||
}
|
||||
if (stdoslpath.empty() || !OIIO::Filesystem::exists(stdoslpath))
|
||||
warningf(ustring(filename), 0, "Unable to find \"stdosl.h\"");
|
||||
warningfmt(ustring(filename), 0, "Unable to find \"stdosl.h\"");
|
||||
|
||||
std::string preprocess_result;
|
||||
if (!preprocess_buffer(sourcecode, filename, stdoslpath, defines,
|
||||
@@ -537,7 +536,7 @@ OSLCompilerImpl::compile_buffer(string_view sourcecode, std::string& osobuffer,
|
||||
if (shader())
|
||||
shader()->typecheck();
|
||||
else
|
||||
errorf(ustring(), 0, "No shader function defined");
|
||||
errorfmt(ustring(), 0, "No shader function defined");
|
||||
}
|
||||
|
||||
// Print the parse tree if there were no errors
|
||||
@@ -591,7 +590,7 @@ OSLCompilerImpl::write_dependency_file(string_view filename)
|
||||
? stdout
|
||||
: OIIO::Filesystem::fopen(m_deps_filename, "w"));
|
||||
if (depfile) {
|
||||
OIIO::Strutil::fprintf(depfile, "%s: %s", target, filename);
|
||||
OSL::print(depfile, "{}: {}", target, filename);
|
||||
for (const auto& dep : m_file_dependencies) {
|
||||
if (OIIO::Strutil::ends_with(dep, "stdosl.h")
|
||||
&& !m_generate_system_deps)
|
||||
@@ -600,14 +599,15 @@ OSLCompilerImpl::write_dependency_file(string_view filename)
|
||||
continue; // skip pseudo files
|
||||
if (dep == filename)
|
||||
continue; // skip this file, since we already put it first
|
||||
OIIO::Strutil::fprintf(depfile, " \\\n %s", dep);
|
||||
OSL::print(depfile, " \\\n {}", dep);
|
||||
}
|
||||
OIIO::Strutil::fprintf(depfile, "\n");
|
||||
OSL::print(depfile, "\n");
|
||||
if (depfile != stdout)
|
||||
fclose(depfile);
|
||||
} else {
|
||||
errorf(ustring(), 0, "Could not open dependency file '%s' for writing",
|
||||
m_deps_filename);
|
||||
errorfmt(ustring(), 0,
|
||||
"Could not open dependency file '{}' for writing",
|
||||
m_deps_filename);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -677,9 +677,9 @@ OSLCompilerImpl::write_oso_metadata(const ASTNode* metanode) const
|
||||
if (ok) {
|
||||
osofmt("%meta{{{},{},{}}} ", ts, metasym->name(), pdl);
|
||||
} else {
|
||||
errorf(metanode->sourcefile(), metanode->sourceline(),
|
||||
"Don't know how to print metadata %s (%s) with node type %s",
|
||||
metasym->name(), ts, metavar->init()->nodetypename());
|
||||
errorfmt(metanode->sourcefile(), metanode->sourceline(),
|
||||
"Don't know how to print metadata {} ({}) with node type {}",
|
||||
metasym->name(), ts, metavar->init()->nodetypename());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1073,7 +1073,8 @@ const char*
|
||||
OSLCompilerImpl::type_c_str(const TypeSpec& type) const
|
||||
{
|
||||
if (type.is_structure())
|
||||
return ustring::sprintf("struct %s", type.structspec()->name()).c_str();
|
||||
return ustring::fmtformat("struct {}", type.structspec()->name())
|
||||
.c_str();
|
||||
else
|
||||
return type.c_str();
|
||||
}
|
||||
@@ -1094,8 +1095,8 @@ OSLCompilerImpl::struct_field_pair(Symbol* sym1, Symbol* sym2, int fieldnum,
|
||||
const StructSpec::FieldSpec& field(structspec->field(fieldnum));
|
||||
// Construct mangled names that describe the symbols for the
|
||||
// individual fields
|
||||
ustring name1 = ustring::sprintf("%s.%s", sym1->mangled(), field.name);
|
||||
ustring name2 = ustring::sprintf("%s.%s", sym2->mangled(), field.name);
|
||||
ustring name1 = ustring::fmtformat("{}.{}", sym1->mangled(), field.name);
|
||||
ustring name2 = ustring::fmtformat("{}.{}", sym2->mangled(), field.name);
|
||||
// Retrieve the symbols
|
||||
field1 = symtab().find_exact(name1);
|
||||
field2 = symtab().find_exact(name2);
|
||||
@@ -1111,8 +1112,8 @@ OSLCompilerImpl::struct_field_pair(const StructSpec* structspec, int fieldnum,
|
||||
{
|
||||
// Find the FieldSpec for the field we are interested in
|
||||
const StructSpec::FieldSpec& field(structspec->field(fieldnum));
|
||||
ustring name1 = ustring::sprintf("%s.%s", sym1, field.name);
|
||||
ustring name2 = ustring::sprintf("%s.%s", sym2, field.name);
|
||||
ustring name1 = ustring::fmtformat("{}.{}", sym1, field.name);
|
||||
ustring name2 = ustring::fmtformat("{}.{}", sym2, field.name);
|
||||
// Retrieve the symbols
|
||||
field1 = symtab().find_exact(name1);
|
||||
field2 = symtab().find_exact(name2);
|
||||
@@ -1130,15 +1131,15 @@ OSLCompilerImpl::check_write_legality(const Opcode& op, int opnum,
|
||||
{
|
||||
// We can never write to constant symbols
|
||||
if (sym->symtype() == SymTypeConst) {
|
||||
errorf(op.sourcefile(), op.sourceline(),
|
||||
"Attempted to write to a constant value");
|
||||
errorfmt(op.sourcefile(), op.sourceline(),
|
||||
"Attempted to write to a constant value");
|
||||
}
|
||||
|
||||
// Params can only write if it's part of their initialization
|
||||
if (sym->symtype() == SymTypeParam
|
||||
&& (opnum < sym->initbegin() || opnum >= sym->initend())) {
|
||||
errorf(op.sourcefile(), op.sourceline(),
|
||||
"cannot write to non-output parameter \"%s\"", sym->name());
|
||||
errorfmt(op.sourcefile(), op.sourceline(),
|
||||
"cannot write to non-output parameter \"{}\"", sym->name());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1304,7 +1305,7 @@ OSLCompilerImpl::track_variable_dependencies()
|
||||
// This naivite will never miss a dependency, but it may
|
||||
// overestimate dependencies. (Hence we call this "conservative"
|
||||
// rather than "wrong.") We deem this acceptable for now, since
|
||||
// it's so much easer to implement the conservative dependency
|
||||
// it's so much easier to implement the conservative dependency
|
||||
// analysis, and it's not yet clear that getting it closer to
|
||||
// optimal will have any performance impact on final shaders. Also
|
||||
// because this is probably no worse than the "dependency slop" that
|
||||
|
||||
@@ -77,69 +77,69 @@ public:
|
||||
|
||||
/// Error reporting
|
||||
template<typename... Args>
|
||||
void errorf(ustring filename, int line, const char* format,
|
||||
const Args&... args) const
|
||||
void errorfmt(ustring filename, int line, const char* format,
|
||||
const Args&... args) const
|
||||
{
|
||||
OSL_DASSERT(format && format[0]);
|
||||
std::string msg = OIIO::Strutil::sprintf(format, args...);
|
||||
std::string msg = OIIO::Strutil::fmt::format(format, args...);
|
||||
if (msg.size() && msg.back() == '\n') // trim extra newline
|
||||
msg.pop_back();
|
||||
if (filename.size())
|
||||
m_errhandler->errorf("%s:%d: error: %s", filename, line, msg);
|
||||
m_errhandler->errorfmt("{}:{}: error: {}", filename, line, msg);
|
||||
else
|
||||
m_errhandler->errorf("error: %s", msg);
|
||||
m_errhandler->errorfmt("error: {}", msg);
|
||||
m_err = true;
|
||||
}
|
||||
|
||||
/// Warning reporting
|
||||
template<typename... Args>
|
||||
void warningf(ustring filename, int line, const char* format,
|
||||
const Args&... args) const
|
||||
void warningfmt(ustring filename, int line, const char* format,
|
||||
const Args&... args) const
|
||||
{
|
||||
OSL_DASSERT(format && format[0]);
|
||||
if (nowarn(filename, line))
|
||||
return; // skip if the filename/line is on the nowarn list
|
||||
std::string msg = OIIO::Strutil::sprintf(format, args...);
|
||||
std::string msg = OIIO::Strutil::fmt::format(format, args...);
|
||||
if (msg.size() && msg.back() == '\n') // trim extra newline
|
||||
msg.pop_back();
|
||||
if (m_err_on_warning) {
|
||||
errorf(filename, line, "%s", msg);
|
||||
errorfmt(filename, line, "{}", msg);
|
||||
return;
|
||||
}
|
||||
if (filename.size())
|
||||
m_errhandler->warningf("%s:%d: warning: %s", filename, line, msg);
|
||||
m_errhandler->warningfmt("{}:{}: warning: {}", filename, line, msg);
|
||||
else
|
||||
m_errhandler->warningf("warning: %s", msg);
|
||||
m_errhandler->warningfmt("warning: {}", msg);
|
||||
}
|
||||
|
||||
/// Info reporting
|
||||
template<typename... Args>
|
||||
void infof(ustring filename, int line, const char* format,
|
||||
const Args&... args) const
|
||||
void infofmt(ustring filename, int line, const char* format,
|
||||
const Args&... args) const
|
||||
{
|
||||
OSL_DASSERT(format && format[0]);
|
||||
std::string msg = OIIO::Strutil::sprintf(format, args...);
|
||||
std::string msg = OIIO::Strutil::fmt::format(format, args...);
|
||||
if (msg.size() && msg.back() == '\n') // trim extra newline
|
||||
msg.pop_back();
|
||||
if (filename.size())
|
||||
m_errhandler->infof("%s:%d: info: %s", filename, line, msg);
|
||||
m_errhandler->infofmt("{}:{}: info: {}", filename, line, msg);
|
||||
else
|
||||
m_errhandler->infof("info: %s", msg);
|
||||
m_errhandler->infofmt("info: {}", msg);
|
||||
}
|
||||
|
||||
/// message reporting
|
||||
template<typename... Args>
|
||||
void messagef(ustring filename, int line, const char* format,
|
||||
const Args&... args) const
|
||||
void messagefmt(ustring filename, int line, const char* format,
|
||||
const Args&... args) const
|
||||
{
|
||||
OSL_DASSERT(format && format[0]);
|
||||
std::string msg = OIIO::Strutil::sprintf(format, args...);
|
||||
std::string msg = OIIO::Strutil::fmt::format(format, args...);
|
||||
if (msg.size() && msg.back() == '\n') // trim extra newline
|
||||
msg.pop_back();
|
||||
if (filename.size())
|
||||
m_errhandler->messagef("%s:%d: %s", filename, line, msg);
|
||||
m_errhandler->messagefmt("{}:{}: {}", filename, line, msg);
|
||||
else
|
||||
m_errhandler->messagef("%s", msg);
|
||||
m_errhandler->messagefmt("{}", msg);
|
||||
}
|
||||
|
||||
/// Have we hit an error?
|
||||
@@ -390,13 +390,6 @@ private:
|
||||
void write_oso_metadata(const ASTNode* metanode) const;
|
||||
void write_dependency_file(string_view filename);
|
||||
|
||||
template<typename... Args>
|
||||
OSL_DEPRECATED("Use osofmt with std::format conventions")
|
||||
inline void osof(const char* fmt, const Args&... args) const
|
||||
{
|
||||
(*m_osofile) << OIIO::Strutil::sprintf(fmt, args...);
|
||||
}
|
||||
|
||||
// Output text to the osofile, using std::format formatting conventions.
|
||||
template<typename... Args>
|
||||
inline void osofmt(const char* fmt, const Args&... args) const
|
||||
@@ -497,7 +490,7 @@ private:
|
||||
int m_main_method_start; ///< Instruction where 'main' starts
|
||||
bool m_declaring_shader_formals; ///< Are we declaring shader formals?
|
||||
std::set<std::pair<ustring, int>> m_nowarn_lines; ///< Lines for 'nowarn'
|
||||
typedef std::unordered_map<ustring, std::string, ustringHash> FCMap;
|
||||
typedef std::unordered_map<ustring, std::string> FCMap;
|
||||
FCMap m_filecontents_map; ///< Contents of source files we've seen
|
||||
ustring m_last_sourcefile; ///< Last filename for retrieve_source
|
||||
std::string* m_last_filecontents = nullptr; //< Last file contents
|
||||
|
||||
+53
-49
@@ -28,6 +28,10 @@
|
||||
#pragma clang diagnostic ignored "-Wparentheses-equality"
|
||||
#endif
|
||||
|
||||
#if (OSL_CLANG_VERSION >= 150000) || (OSL_INTEL_CLANG_VERSION >= 140000)
|
||||
#pragma clang diagnostic ignored "-Wunused-but-set-variable"
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC visibility push(hidden)
|
||||
#endif
|
||||
@@ -248,11 +252,11 @@ formal_param
|
||||
// Grab the current declaration type, modify it to be array
|
||||
TypeSpec t = oslcompiler->current_typespec();
|
||||
if (! t.is_structure() && ! t.is_triple() && ! t.is_matrix())
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Can't use '= {...}' initializer "
|
||||
"except with arrays, structs, vectors, "
|
||||
"or matrix (%s)", $3);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Can't use '= {{...}}' initializer "
|
||||
"except with arrays, structs, vectors, "
|
||||
"or matrix ({})", $3);
|
||||
auto var = new ASTvariable_declaration (oslcompiler, t,
|
||||
ustring($3), $4 /*init*/,
|
||||
oslcompiler->declaring_shader_formals() /*isparam*/,
|
||||
@@ -294,9 +298,9 @@ metadatum
|
||||
TypeDesc simple = osllextype ($1);
|
||||
simple.arraylen = $3;
|
||||
if (simple.arraylen < 1)
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Invalid array length for %s", $2);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Invalid array length for {}", $2);
|
||||
TypeSpec t (simple, false);
|
||||
auto var = new ASTvariable_declaration (oslcompiler, t,
|
||||
ustring ($2), $4, false,
|
||||
@@ -338,13 +342,13 @@ struct_declaration
|
||||
ustring name ($2);
|
||||
Symbol *s = oslcompiler->symtab().clash (name);
|
||||
if (s) {
|
||||
oslcompiler->errorf(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"\"%s\" already declared in this scope", name);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"\"{}\" already declared in this scope", name);
|
||||
// FIXME -- print the file and line of the other definition
|
||||
}
|
||||
if (OIIO::Strutil::starts_with (name, "___")) {
|
||||
oslcompiler->errorf(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"\"%s\" : sorry, can't start with three underscores", name);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"\"{}\" : sorry, can't start with three underscores", name);
|
||||
}
|
||||
oslcompiler->symtab().new_struct (name);
|
||||
}
|
||||
@@ -375,10 +379,10 @@ typed_field
|
||||
TypeSpec t = oslcompiler->current_typespec();
|
||||
StructSpec *s = oslcompiler->symtab().current_struct();
|
||||
if (s->lookup_field (name) >= 0)
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Field \"%s\" already exists in struct \"%s\"",
|
||||
name, s->name());
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Field \"{}\" already exists in struct \"{}\"",
|
||||
name, s->name());
|
||||
else
|
||||
oslcompiler->symtab().add_struct_field (t, name);
|
||||
$$ = 0;
|
||||
@@ -390,15 +394,15 @@ typed_field
|
||||
TypeSpec t = oslcompiler->current_typespec();
|
||||
t.make_array ($2);
|
||||
if (t.arraylength() < 1)
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Invalid array length for %s", name);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Invalid array length for {}", name);
|
||||
StructSpec *s = oslcompiler->symtab().current_struct();
|
||||
if (s->lookup_field (name) >= 0)
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Field \"%s\" already exists in struct \"%s\"",
|
||||
name, s->name());
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Field \"{}\" already exists in struct \"{}\"",
|
||||
name, s->name());
|
||||
else
|
||||
oslcompiler->symtab().add_struct_field (t, name);
|
||||
$$ = 0;
|
||||
@@ -434,9 +438,9 @@ def_expression
|
||||
TypeSpec t = oslcompiler->current_typespec();
|
||||
t.make_array ($2);
|
||||
if ($2 < 1)
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Invalid array length for %s", $1);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Invalid array length for {}", $1);
|
||||
$$ = new ASTvariable_declaration (oslcompiler, t,
|
||||
ustring($1), $3, false, false, false,
|
||||
true /* initlist */, @1.first_line);
|
||||
@@ -445,11 +449,11 @@ def_expression
|
||||
{
|
||||
TypeSpec t = oslcompiler->current_typespec();
|
||||
if (! t.is_structure() && ! t.is_triple() && ! t.is_matrix())
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Can't use '= {...}' initializer "
|
||||
"except with arrays, struct, vectors, "
|
||||
"or matrix (%s)", $1);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Can't use '= {{...}}' initializer "
|
||||
"except with arrays, struct, vectors, "
|
||||
"or matrix ({})", $1);
|
||||
$$ = new ASTvariable_declaration (oslcompiler, t,
|
||||
ustring($1), $2, false, false, false,
|
||||
true /* initlist */, @1.first_line);
|
||||
@@ -483,10 +487,10 @@ compound_initializer
|
||||
| '{' '}'
|
||||
{
|
||||
if (!oslcompiler->declaring_shader_formals())
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Empty compound initializers '{ }' "
|
||||
"only allowed for shader parameters.");
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Empty compound initializers '{{ }}' "
|
||||
"only allowed for shader parameters.");
|
||||
$$ = new ASTcompound_initializer (oslcompiler, nullptr);
|
||||
$$->sourceline (@1.first_line);
|
||||
}
|
||||
@@ -566,9 +570,9 @@ arrayspec
|
||||
: '[' INT_LITERAL ']'
|
||||
{
|
||||
if ($2 < 1)
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Invalid array length (%d)", $2);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Invalid array length ({})", $2);
|
||||
$$ = $2;
|
||||
}
|
||||
| '[' ']' { $$ = -1; }
|
||||
@@ -594,9 +598,9 @@ typespec
|
||||
oslcompiler->current_typespec (TypeSpec ("", s->typespec().structure()));
|
||||
else {
|
||||
oslcompiler->current_typespec (TypeSpec (TypeDesc::UNKNOWN));
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Unknown struct name: %s", $1);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Unknown struct name: {}", $1);
|
||||
}
|
||||
$$ = 0;
|
||||
}
|
||||
@@ -635,9 +639,9 @@ typespec_or_shadertype
|
||||
oslcompiler->current_typespec (TypeSpec ("", s->typespec().structure()));
|
||||
else {
|
||||
oslcompiler->current_typespec (TypeSpec (TypeDesc::UNKNOWN));
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Unknown struct name: %s", $1);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Unknown struct name: {}", $1);
|
||||
}
|
||||
$$ = (int)ShaderType::Unknown;
|
||||
}
|
||||
@@ -797,9 +801,9 @@ expression
|
||||
// color x = Cd * (a, b, c); // same as: x = Cd * c
|
||||
// when they really meant
|
||||
// color x = Cd * color(a, b, c);
|
||||
oslcompiler->warningf(oslcompiler->filename(),
|
||||
@1.first_line,
|
||||
"Comma operator inside parenthesis is probably an error -- it is not a vector/color.");
|
||||
oslcompiler->warningfmt(oslcompiler->filename(),
|
||||
@1.first_line,
|
||||
"Comma operator inside parenthesis is probably an error -- it is not a vector/color.");
|
||||
}
|
||||
$$ = $2;
|
||||
}
|
||||
@@ -1094,8 +1098,8 @@ string_literal_group
|
||||
void
|
||||
OSL::pvt::yyerror (YYLTYPE* yylloc_param, void* yyscanner, OSLCompilerImpl* oslcompiler, const char* err)
|
||||
{
|
||||
oslcompiler->errorf(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"Syntax error: %s", err);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"Syntax error: {}", err);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+33
-28
@@ -7,6 +7,11 @@
|
||||
/** Lexical scanner for Open Shading Language
|
||||
**/
|
||||
|
||||
%top{
|
||||
/* Include this first to avoid warnings about re-definitions on windows */
|
||||
#include <stdint.h>
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
* Definitions section
|
||||
************************************************************/
|
||||
@@ -176,10 +181,10 @@ OSL_NAMESPACE_EXIT
|
||||
"protected"|"short"|"signed"|"sizeof"|"static"|"struct" | \
|
||||
"switch"|"template"|"this"|"true"|"typedef"|"uniform" | \
|
||||
"union"|"unsigned"|"varying"|"virtual" {
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"'%s' is a reserved word",
|
||||
yytext);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"'{}' is a reserved word",
|
||||
yytext);
|
||||
SETLINE;
|
||||
return (yylval->i=RESERVED);
|
||||
}
|
||||
@@ -198,10 +203,10 @@ OSL_NAMESPACE_EXIT
|
||||
// we do not detect overflow when the value is INT_MAX+1,
|
||||
// because negation happens later and -(INT_MAX+1) == INT_MIN
|
||||
if (llval > ((long long)INT_MAX)+1) {
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"integer overflow, value must be between %d and %d.",
|
||||
INT_MIN, INT_MAX);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"integer overflow, value must be between {} and {}.",
|
||||
INT_MIN, INT_MAX);
|
||||
}
|
||||
yylval->i = (int)llval;
|
||||
SETLINE;
|
||||
@@ -212,10 +217,10 @@ OSL_NAMESPACE_EXIT
|
||||
// we do not detect overflow when the value is INT_MAX+1,
|
||||
// because negation happens later and -(INT_MAX+1) == INT_MIN
|
||||
if (llval > ((long long)UINT_MAX)+1) {
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"integer overflow, value must be between %d and %d.",
|
||||
INT_MIN, INT_MAX);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"integer overflow, value must be between {} and {}.",
|
||||
INT_MIN, INT_MAX);
|
||||
}
|
||||
yylval->i = (int)llval;
|
||||
SETLINE;
|
||||
@@ -300,8 +305,8 @@ preprocess (const char *str, OSLCompilerImpl* oslcompiler, YYLTYPE* yyloc_param)
|
||||
while (*p == ' ' || *p == '\t')
|
||||
p++;
|
||||
if (*p != '#') {
|
||||
oslcompiler->errorf(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"Possible bug in shader preprocess");
|
||||
oslcompiler->errorfmt(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"Possible bug in shader preprocess");
|
||||
SETLINE;
|
||||
return;
|
||||
}
|
||||
@@ -315,30 +320,30 @@ preprocess (const char *str, OSLCompilerImpl* oslcompiler, YYLTYPE* yyloc_param)
|
||||
if (pragmatype == "error") {
|
||||
string_view msg;
|
||||
if (OIIO::Strutil::parse_string(line, msg))
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(), "%s", msg);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(), "{}", msg);
|
||||
else
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"<unknown error>");
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"<unknown error>");
|
||||
}
|
||||
else if (pragmatype == "warning") {
|
||||
string_view msg;
|
||||
if (OIIO::Strutil::parse_string(line, msg))
|
||||
oslcompiler->warningf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(), "%s", msg);
|
||||
oslcompiler->warningfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(), "{}", msg);
|
||||
else
|
||||
oslcompiler->warningf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"<unknown warning>");
|
||||
oslcompiler->warningfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"<unknown warning>");
|
||||
}
|
||||
else if (OIIO::Strutil::iequals (pragmatype, "osl")) {
|
||||
string_view pragmaname = OIIO::Strutil::parse_word (line);
|
||||
if (pragmaname == "nowarn") {
|
||||
oslcompiler->pragma_nowarn ();
|
||||
} else {
|
||||
oslcompiler->warningf(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"Unknown pragma '%s'", pragmaname);
|
||||
oslcompiler->warningfmt(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"Unknown pragma '{}'", pragmaname);
|
||||
}
|
||||
}
|
||||
// N.B. Any other pragmas that don't start with "osl" are ignored
|
||||
@@ -377,8 +382,8 @@ preprocess (const char *str, OSLCompilerImpl* oslcompiler, YYLTYPE* yyloc_param)
|
||||
}
|
||||
oslcompiler->lineno (line);
|
||||
} else {
|
||||
oslcompiler->errorf(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"Unrecognized preprocessor command: #%s", p);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"Unrecognized preprocessor command: #{}", p);
|
||||
}
|
||||
}
|
||||
SETLINE;
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace pvt { // OSL::pvt
|
||||
std::string
|
||||
Symbol::mangled() const
|
||||
{
|
||||
std::string result = scope() ? Strutil::sprintf("___%d_%s", scope(), m_name)
|
||||
std::string result = scope() ? fmtformat("___{}_{}", scope(), m_name)
|
||||
: m_name.string();
|
||||
return result; // Force NRVO (named value return optimization)
|
||||
}
|
||||
@@ -54,8 +54,7 @@ Symbol::symtype_shortname(SymType s)
|
||||
std::string
|
||||
StructSpec::mangled() const
|
||||
{
|
||||
return scope() ? Strutil::sprintf("___%d_%s", scope(), m_name)
|
||||
: m_name.string();
|
||||
return scope() ? fmtformat("___{}_{}", scope(), m_name) : m_name.string();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ private:
|
||||
///
|
||||
class SymbolTable {
|
||||
public:
|
||||
typedef std::unordered_map<ustring, Symbol*, ustringHash> ScopeTable;
|
||||
typedef std::unordered_map<ustring, Symbol*> ScopeTable;
|
||||
typedef std::vector<ScopeTable> ScopeTableStack;
|
||||
typedef SymbolPtrVec::iterator iterator;
|
||||
typedef SymbolPtrVec::const_iterator const_iterator;
|
||||
|
||||
+134
-120
@@ -65,7 +65,8 @@ ASTfunction_declaration::typecheck(TypeSpec expected)
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTvariable_declaration::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTvariable_declaration::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
typecheck_children(m_typespec);
|
||||
ASTNode* init = this->init().get();
|
||||
@@ -79,7 +80,7 @@ TypeSpec ASTvariable_declaration::typecheck(TypeSpec /*expected*/)
|
||||
if (m_typespec.is_structure() && !m_initlist
|
||||
&& et.structure() != vt.structure()) {
|
||||
// Can't do: struct foo = 1
|
||||
errorf("Cannot initialize %s %s = %s", vt, name(), et);
|
||||
errorfmt("Cannot initialize {} {} = {}", vt, name(), et);
|
||||
return m_typespec;
|
||||
}
|
||||
|
||||
@@ -88,7 +89,7 @@ TypeSpec ASTvariable_declaration::typecheck(TypeSpec /*expected*/)
|
||||
// typecheck method.
|
||||
if (init->nodetype() == compound_initializer_node) {
|
||||
if (init->nextptr())
|
||||
errorf("compound_initializer should be the only initializer");
|
||||
errorfmt("compound_initializer should be the only initializer");
|
||||
init = ((ASTcompound_initializer*)init)->initlist().get();
|
||||
if (!init)
|
||||
return m_typespec;
|
||||
@@ -106,10 +107,10 @@ TypeSpec ASTvariable_declaration::typecheck(TypeSpec /*expected*/)
|
||||
if (!assignable(vt, et)) {
|
||||
// Special case: for int=float, it's just a warning.
|
||||
if (vt.is_int() && et.is_float())
|
||||
warningf("Assignment may lose precision: %s %s = %s", vt, name(),
|
||||
et);
|
||||
warningfmt("Assignment may lose precision: {} {} = {}", vt, name(),
|
||||
et);
|
||||
else
|
||||
errorf("Cannot assign %s %s = %s", vt, name(), et);
|
||||
errorfmt("Cannot assign {} {} = {}", vt, name(), et);
|
||||
return m_typespec;
|
||||
}
|
||||
|
||||
@@ -118,7 +119,8 @@ TypeSpec ASTvariable_declaration::typecheck(TypeSpec /*expected*/)
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTvariable_ref::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTvariable_ref::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
m_is_lvalue = true; // A var ref is an lvalue
|
||||
return m_typespec;
|
||||
@@ -126,7 +128,8 @@ TypeSpec ASTvariable_ref::typecheck(TypeSpec /*expected*/)
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTpreincdec::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTpreincdec::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
typecheck_children();
|
||||
m_is_lvalue = var()->is_lvalue();
|
||||
@@ -136,11 +139,12 @@ TypeSpec ASTpreincdec::typecheck(TypeSpec /*expected*/)
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTpostincdec::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTpostincdec::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
typecheck_children();
|
||||
if (!var()->is_lvalue())
|
||||
errorf("%s can only be applied to an lvalue", nodetypename());
|
||||
errorfmt("{} can only be applied to an lvalue", nodetypename());
|
||||
m_is_lvalue = false;
|
||||
m_typespec = var()->typespec();
|
||||
return m_typespec;
|
||||
@@ -148,29 +152,30 @@ TypeSpec ASTpostincdec::typecheck(TypeSpec /*expected*/)
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTindex::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTindex::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
typecheck_children();
|
||||
const char* indextype = "";
|
||||
TypeSpec t = lvalue()->typespec();
|
||||
if (t.is_structure()) {
|
||||
errorf("Cannot use [] indexing on a struct");
|
||||
errorfmt("Cannot use [] indexing on a struct");
|
||||
return TypeSpec();
|
||||
}
|
||||
if (t.is_closure()) {
|
||||
errorf("Cannot use [] indexing on a closure");
|
||||
errorfmt("Cannot use [] indexing on a closure");
|
||||
return TypeSpec();
|
||||
}
|
||||
if (index3()) {
|
||||
if (!t.is_array() && !t.elementtype().is_matrix())
|
||||
errorf("[][][] only valid for a matrix array");
|
||||
errorfmt("[][][] only valid for a matrix array");
|
||||
m_typespec = TypeDesc::FLOAT;
|
||||
} else if (t.is_array()) {
|
||||
indextype = "array";
|
||||
m_typespec = t.elementtype();
|
||||
if (index2()) {
|
||||
if (t.aggregate() == TypeDesc::SCALAR)
|
||||
errorf("can't use [][] on a simple array");
|
||||
errorfmt("can't use [][] on a simple array");
|
||||
m_typespec = TypeDesc::FLOAT;
|
||||
}
|
||||
} else if (t.aggregate() == TypeDesc::VEC3) {
|
||||
@@ -180,7 +185,7 @@ TypeSpec ASTindex::typecheck(TypeSpec /*expected*/)
|
||||
tnew.vecsemantics = TypeDesc::NOXFORM;
|
||||
m_typespec = tnew;
|
||||
if (index2())
|
||||
errorf("can't use [][] on a %s", t);
|
||||
errorfmt("can't use [][] on a {}", t);
|
||||
} else if (t.aggregate() == TypeDesc::MATRIX44) {
|
||||
indextype = "component";
|
||||
TypeDesc tnew = t.simpletype();
|
||||
@@ -188,17 +193,18 @@ TypeSpec ASTindex::typecheck(TypeSpec /*expected*/)
|
||||
tnew.vecsemantics = TypeDesc::NOXFORM;
|
||||
m_typespec = tnew;
|
||||
if (!index2())
|
||||
errorf("must use [][] on a matrix, not just []");
|
||||
errorfmt("must use [][] on a matrix, not just []");
|
||||
} else {
|
||||
errorf("can only use [] indexing for arrays or multi-component types");
|
||||
errorfmt(
|
||||
"can only use [] indexing for arrays or multi-component types");
|
||||
return TypeSpec();
|
||||
}
|
||||
|
||||
// Make sure the indices (children 1+) are integers
|
||||
for (size_t c = 1; c < nchildren(); ++c)
|
||||
if (!child(c)->typespec().is_int())
|
||||
errorf("%s index must be an integer, not a %s", indextype,
|
||||
index()->typespec());
|
||||
errorfmt("{} index must be an integer, not a {}", indextype,
|
||||
index()->typespec());
|
||||
|
||||
// If the thing we're indexing is an lvalue, so is the indexed element
|
||||
m_is_lvalue = lvalue()->is_lvalue();
|
||||
@@ -230,7 +236,8 @@ ASTstructselect::typecheck(TypeSpec expected)
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTconditional_statement::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTconditional_statement::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
typecheck_list(cond());
|
||||
m_compiler->push_nesting(false);
|
||||
@@ -240,15 +247,16 @@ TypeSpec ASTconditional_statement::typecheck(TypeSpec /*expected*/)
|
||||
|
||||
TypeSpec c = cond()->typespec();
|
||||
if (c.is_structure())
|
||||
errorf("Cannot use a struct as an 'if' condition");
|
||||
errorfmt("Cannot use a struct as an 'if' condition");
|
||||
if (c.is_array())
|
||||
errorf("Cannot use an array as an 'if' condition");
|
||||
errorfmt("Cannot use an array as an 'if' condition");
|
||||
return m_typespec = TypeDesc(TypeDesc::NONE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTloop_statement::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTloop_statement::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
typecheck_list(init());
|
||||
m_compiler->push_nesting(true);
|
||||
@@ -259,34 +267,36 @@ TypeSpec ASTloop_statement::typecheck(TypeSpec /*expected*/)
|
||||
|
||||
TypeSpec c = cond()->typespec();
|
||||
if (c.is_closure())
|
||||
errorf("Cannot use a closure as an '%s' condition", opname());
|
||||
errorfmt("Cannot use a closure as an '{}' condition", opname());
|
||||
if (c.is_structure())
|
||||
errorf("Cannot use a struct as an '%s' condition", opname());
|
||||
errorfmt("Cannot use a struct as an '{}' condition", opname());
|
||||
if (c.is_array())
|
||||
errorf("Cannot use an array as an '%s' condition", opname());
|
||||
errorfmt("Cannot use an array as an '{}' condition", opname());
|
||||
return m_typespec = TypeDesc(TypeDesc::NONE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTloopmod_statement::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTloopmod_statement::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
if (m_compiler->nesting_level(true /*loops*/) < 1)
|
||||
errorf("Cannot '%s' here -- not inside a loop.", opname());
|
||||
errorfmt("Cannot '{}' here -- not inside a loop.", opname());
|
||||
return m_typespec = TypeDesc(TypeDesc::NONE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTassign_expression::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTassign_expression::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
TypeSpec vt = var()->typecheck(); // Type of the variable
|
||||
TypeSpec et = expr()->typecheck(vt); // Type of the expression assigned
|
||||
m_typespec = vt;
|
||||
|
||||
if (!var()->is_lvalue()) {
|
||||
errorf("Can't assign via %s to something that isn't an lvalue",
|
||||
opname());
|
||||
errorfmt("Can't assign via {} to something that isn't an lvalue",
|
||||
opname());
|
||||
return TypeSpec();
|
||||
}
|
||||
|
||||
@@ -307,7 +317,7 @@ TypeSpec ASTassign_expression::typecheck(TypeSpec /*expected*/)
|
||||
return m_typespec;
|
||||
}
|
||||
}
|
||||
errorf("Cannot assign %s %s = %s", vt, varname, et);
|
||||
errorfmt("Cannot assign {} {} = {}", vt, varname, et);
|
||||
return m_typespec;
|
||||
}
|
||||
|
||||
@@ -326,7 +336,7 @@ TypeSpec ASTassign_expression::typecheck(TypeSpec /*expected*/)
|
||||
if (vts == ets)
|
||||
return m_typespec = vt;
|
||||
// Otherwise, a structure mismatch
|
||||
errorf("Cannot assign %s %s = %s", vt, varname, et);
|
||||
errorfmt("Cannot assign {} {} = {}", vt, varname, et);
|
||||
return m_typespec;
|
||||
}
|
||||
|
||||
@@ -334,10 +344,10 @@ TypeSpec ASTassign_expression::typecheck(TypeSpec /*expected*/)
|
||||
if (!assignable(vt, et)) {
|
||||
// Special case: for int=float, it's just a warning.
|
||||
if (vt.is_int() && et.is_float())
|
||||
warningf("Assignment may lose precision: %s %s = %s", vt, varname,
|
||||
et);
|
||||
warningfmt("Assignment may lose precision: {} {} = {}", vt, varname,
|
||||
et);
|
||||
else
|
||||
errorf("Cannot assign %s %s = %s", vt, varname, et);
|
||||
errorfmt("Cannot assign {} {} = {}", vt, varname, et);
|
||||
return m_typespec;
|
||||
}
|
||||
|
||||
@@ -346,7 +356,8 @@ TypeSpec ASTassign_expression::typecheck(TypeSpec /*expected*/)
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTreturn_statement::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTreturn_statement::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
FunctionSymbol* myfunc = m_compiler->current_function();
|
||||
if (myfunc) {
|
||||
@@ -357,14 +368,14 @@ TypeSpec ASTreturn_statement::typecheck(TypeSpec /*expected*/)
|
||||
// will also catch returning a value from a void function.
|
||||
TypeSpec et = expr()->typecheck(myfunc->typespec());
|
||||
if (!assignable(myfunc->typespec(), et)) {
|
||||
errorf("Cannot return a '%s' from '%s %s()'", et,
|
||||
myfunc->typespec(), myfunc->name());
|
||||
errorfmt("Cannot return a '{}' from '{} {}()'", et,
|
||||
myfunc->typespec(), myfunc->name());
|
||||
}
|
||||
} else {
|
||||
// If we are not returning a value, it must be a void function.
|
||||
if (!myfunc->typespec().is_void())
|
||||
errorf("You must return a '%s' from function '%s'",
|
||||
myfunc->typespec(), myfunc->name());
|
||||
errorfmt("You must return a '{}' from function '{}'",
|
||||
myfunc->typespec(), myfunc->name());
|
||||
}
|
||||
myfunc->encountered_return();
|
||||
} else {
|
||||
@@ -372,7 +383,7 @@ TypeSpec ASTreturn_statement::typecheck(TypeSpec /*expected*/)
|
||||
// be from the main shader body. That's fine (it's equivalent
|
||||
// to calling exit()), but it can't return a value.
|
||||
if (expr())
|
||||
errorf("Cannot return a value from a shader body");
|
||||
errorfmt("Cannot return a value from a shader body");
|
||||
}
|
||||
return TypeSpec(); // TODO: what should be returned here?
|
||||
}
|
||||
@@ -402,14 +413,14 @@ ASTunary_expression::typecheck(TypeSpec expected)
|
||||
}
|
||||
|
||||
if (t.is_structure() || t.is_array()) {
|
||||
errorf("Can't do '%s' to a %s.", opname(), t);
|
||||
errorfmt("Can't do '{}' to a {}.", opname(), t);
|
||||
return TypeSpec();
|
||||
}
|
||||
switch (m_op) {
|
||||
case Sub:
|
||||
case Add:
|
||||
if (!(t.is_closure() || t.is_numeric())) {
|
||||
errorf("Can't do '%s' to a %s.", opname(), t);
|
||||
errorfmt("Can't do '{}' to a {}.", opname(), t);
|
||||
return TypeSpec();
|
||||
}
|
||||
m_typespec = t;
|
||||
@@ -419,12 +430,12 @@ ASTunary_expression::typecheck(TypeSpec expected)
|
||||
break;
|
||||
case Compl:
|
||||
if (!t.is_int()) {
|
||||
errorf("Operator '~' can only be done to an int");
|
||||
errorfmt("Operator '~' can only be done to an int");
|
||||
return TypeSpec();
|
||||
}
|
||||
m_typespec = t;
|
||||
break;
|
||||
default: errorf("unknown unary operator");
|
||||
default: errorfmt("unknown unary operator");
|
||||
}
|
||||
return m_typespec;
|
||||
}
|
||||
@@ -467,7 +478,7 @@ ASTbinary_expression::typecheck(TypeSpec expected)
|
||||
TypeSpec returntype = m_compiler->type_from_code(code, &advance);
|
||||
code += advance;
|
||||
if (code[0] && check_simple_arg(l, code, true) && code[0]
|
||||
&& check_simple_arg(r, code, true) && !code[0]) {
|
||||
&& check_simple_arg(r, code, true) && !code[0]) { // NOSONAR
|
||||
return m_typespec = returntype;
|
||||
}
|
||||
}
|
||||
@@ -477,7 +488,7 @@ ASTbinary_expression::typecheck(TypeSpec expected)
|
||||
|
||||
// No binary ops work on structs or arrays
|
||||
if (l.is_structure() || r.is_structure() || l.is_array() || r.is_array()) {
|
||||
errorf("Not allowed: '%s %s %s'", l, opname(), r);
|
||||
errorfmt("Not allowed: '{} {} {}'", l, opname(), r);
|
||||
return TypeSpec();
|
||||
}
|
||||
|
||||
@@ -507,7 +518,7 @@ ASTbinary_expression::typecheck(TypeSpec expected)
|
||||
return m_typespec = TypeDesc::TypeInt;
|
||||
}
|
||||
// If we got this far, it's an op that's not allowed
|
||||
errorf("Not allowed: '%s %s %s'", l, opname(), r);
|
||||
errorfmt("Not allowed: '{} {} {}'", l, opname(), r);
|
||||
return TypeSpec();
|
||||
}
|
||||
|
||||
@@ -581,11 +592,11 @@ ASTbinary_expression::typecheck(TypeSpec expected)
|
||||
// nonzeroness), but always return int.
|
||||
return m_typespec = TypeDesc::TypeInt;
|
||||
|
||||
default: errorf("unknown binary operator");
|
||||
default: errorfmt("unknown binary operator");
|
||||
}
|
||||
|
||||
// If we got this far, it's an op that's not allowed
|
||||
errorf("Not allowed: '%s %s %s'", l, opname(), r);
|
||||
errorfmt("Not allowed: '{} {} {}'", l, opname(), r);
|
||||
return TypeSpec();
|
||||
}
|
||||
|
||||
@@ -600,15 +611,15 @@ ASTternary_expression::typecheck(TypeSpec expected)
|
||||
TypeSpec f = typecheck_list(falseexpr(), expected);
|
||||
|
||||
if (c.is_closure())
|
||||
errorf("Cannot use a closure as a condition");
|
||||
errorfmt("Cannot use a closure as a condition");
|
||||
if (c.is_structure())
|
||||
errorf("Cannot use a struct as a condition");
|
||||
errorfmt("Cannot use a struct as a condition");
|
||||
if (c.is_array())
|
||||
errorf("Cannot use an array as a condition");
|
||||
errorfmt("Cannot use an array as a condition");
|
||||
|
||||
// No arrays
|
||||
if (t.is_array() || t.is_array()) {
|
||||
errorf("Not allowed: '%s ? %s : %s'", c, t, f);
|
||||
if (t.is_array() || f.is_array()) {
|
||||
errorfmt("Not allowed: '{} ? {} : {}'", c, t, f);
|
||||
return TypeSpec();
|
||||
}
|
||||
|
||||
@@ -617,7 +628,7 @@ ASTternary_expression::typecheck(TypeSpec expected)
|
||||
if (assignable(t, f) || assignable(f, t))
|
||||
m_typespec = higherprecision(t.simpletype(), f.simpletype());
|
||||
else
|
||||
errorf("Not allowed: '%s ? %s : %s'", c, t, f);
|
||||
errorfmt("Not allowed: '{} ? {} : {}'", c, t, f);
|
||||
|
||||
return m_typespec;
|
||||
}
|
||||
@@ -634,7 +645,8 @@ ASTcomma_operator::typecheck(TypeSpec expected)
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTtypecast_expression::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTtypecast_expression::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
// FIXME - closures
|
||||
typecheck_children(m_typespec);
|
||||
@@ -642,7 +654,7 @@ TypeSpec ASTtypecast_expression::typecheck(TypeSpec /*expected*/)
|
||||
if (!assignable(m_typespec, t) && !(m_typespec.is_int() && t.is_float())
|
||||
&& // (int)float is ok
|
||||
!(m_typespec.is_triple() && t.is_triple()))
|
||||
errorf("Cannot cast '%s' to '%s'", t, m_typespec);
|
||||
errorfmt("Cannot cast '{}' to '{}'", t, m_typespec);
|
||||
return m_typespec;
|
||||
}
|
||||
|
||||
@@ -666,7 +678,7 @@ ASTtype_constructor::typecheck(TypeSpec expected, bool report, bool bind)
|
||||
if (expected.is_float()) {
|
||||
patterns = float_patterns;
|
||||
argexpected = TypeDesc::FLOAT;
|
||||
// ^^^ Since simetimes tht constructor `float(expr)` is used as a
|
||||
// ^^^ Since sometimes the constructor `float(expr)` is used as a
|
||||
// synonym for a cast `(float)expr`, we know that ambiguously typed
|
||||
// expressions should favor disambiguating to a float.
|
||||
} else if (expected.is_triple()) {
|
||||
@@ -686,7 +698,7 @@ ASTtype_constructor::typecheck(TypeSpec expected, bool report, bool bind)
|
||||
patterns = int_patterns;
|
||||
} else {
|
||||
if (report)
|
||||
errorf("Cannot construct type '%s'", expected);
|
||||
errorfmt("Cannot construct type '{}'", expected);
|
||||
return TypeSpec();
|
||||
}
|
||||
|
||||
@@ -706,15 +718,15 @@ ASTtype_constructor::typecheck(TypeSpec expected, bool report, bool bind)
|
||||
|
||||
// If we made it this far, no match could be found.
|
||||
if (report) {
|
||||
std::string err = OIIO::Strutil::sprintf("Cannot construct %s (",
|
||||
expected);
|
||||
std::string err = OIIO::Strutil::fmt::format("Cannot construct {} (",
|
||||
expected);
|
||||
for (ref a = args(); a; a = a->next()) {
|
||||
err += a->typespec().string();
|
||||
if (a->next())
|
||||
err += ", ";
|
||||
}
|
||||
err += ")";
|
||||
errorf("%s", err);
|
||||
errorfmt("{}", err);
|
||||
// FIXME -- it might be nice here to enumerate for the user all the
|
||||
// valid combinations.
|
||||
}
|
||||
@@ -750,7 +762,7 @@ public:
|
||||
|
||||
~TypeAdjuster()
|
||||
{
|
||||
// Commit infered types of all ASTcompound_initializers scanned.
|
||||
// Commit inferred types of all ASTcompound_initializers scanned.
|
||||
if (m_success) {
|
||||
for (auto&& initer : m_adjust) {
|
||||
ASTcompound_initializer* ciptr = std::get<0>(initer);
|
||||
@@ -775,9 +787,9 @@ public:
|
||||
if (m_mode & must_init_all) {
|
||||
m_success = false;
|
||||
if (errors()) {
|
||||
cinit->errorf("Empty initializer list not allowed to"
|
||||
"represent '%' here",
|
||||
to);
|
||||
cinit->errorfmt("Empty initializer list not allowed to "
|
||||
"represent '{}' here",
|
||||
to);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -840,9 +852,9 @@ public:
|
||||
|
||||
m_success = false;
|
||||
if (errors()) {
|
||||
init->errorf("Too %s initializers for a '%s'",
|
||||
nelem < expected.arraylength() ? "few" : "many",
|
||||
expected);
|
||||
init->errorfmt("Too {} initializers for a '{}'",
|
||||
nelem < expected.arraylength() ? "few" : "many",
|
||||
expected);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -888,9 +900,9 @@ public:
|
||||
|
||||
m_success = false;
|
||||
if (errors() && (arg || nfields > ninits)) {
|
||||
parent->errorf("Too %s initializers for struct '%s'",
|
||||
ninits < nfields ? "few" : "many",
|
||||
structspec->name());
|
||||
parent->errorfmt("Too {} initializers for struct '{}'",
|
||||
ninits < nfields ? "few" : "many",
|
||||
structspec->name());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -980,9 +992,9 @@ private:
|
||||
const StructSpec::FieldSpec* field = nullptr)
|
||||
{
|
||||
if (node->typecheck(expected) != expected &&
|
||||
// Alllow assignment with comparable type
|
||||
// Allow assignment with comparable type
|
||||
!assignable(expected, node->typespec()) &&
|
||||
// Alllow closure assignments to '0'
|
||||
// Allow closure assignments to '0'
|
||||
!(expected.is_closure() && !node->typespec().is_closure()
|
||||
&& node->typespec().is_int_or_float()
|
||||
&& node->nodetype() == literal_node
|
||||
@@ -992,11 +1004,11 @@ private:
|
||||
return false;
|
||||
|
||||
OSL_DASSERT(!spec || field);
|
||||
node->errorf("Can't assign '%s' to '%s%s'", node->typespec(),
|
||||
expected,
|
||||
!spec ? ""
|
||||
: Strutil::sprintf(" %s.%s", spec->name(),
|
||||
field->name));
|
||||
node->errorfmt("Can't assign '{}' to '{}{}'", node->typespec(),
|
||||
expected,
|
||||
!spec ? ""
|
||||
: Strutil::fmt::format(" {}.{}", spec->name(),
|
||||
field->name));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1010,7 +1022,7 @@ ASTcompound_initializer::typecheck(TypeSpec expected, unsigned mode)
|
||||
if (m_ctor || m_typespec.is_structure_based()
|
||||
|| m_typespec.simpletype().basetype != TypeDesc::UNKNOWN) {
|
||||
if (m_typespec != expected)
|
||||
errorf("Cannot construct type '%s'", expected);
|
||||
errorfmt("Cannot construct type '{}'", expected);
|
||||
return m_typespec;
|
||||
}
|
||||
|
||||
@@ -1053,6 +1065,8 @@ bool
|
||||
ASTNode::check_arglist(const char* /*funcname*/, ASTNode::ref arg,
|
||||
const char* formals, bool coerce, bool bind)
|
||||
{
|
||||
if (!formals)
|
||||
return false;
|
||||
// std::cerr << "ca " << funcname << " formals='" << formals << "\n";
|
||||
for (; arg; arg = arg->next()) {
|
||||
if (!*formals) // More formal args, but no more actual args
|
||||
@@ -1188,14 +1202,14 @@ ASTfunction_call::typecheck_printf_args(const char* format, ASTNode* arg)
|
||||
++format;
|
||||
char formatchar = *format++; // Also eat the format char
|
||||
if (!arg) {
|
||||
errorf(
|
||||
"%s has mismatched format string and arguments (not enough args)",
|
||||
errorfmt(
|
||||
"{} has mismatched format string and arguments (not enough args)",
|
||||
m_name);
|
||||
return false;
|
||||
}
|
||||
if (arg->typespec().is_structure_based()) {
|
||||
errorf("struct '%s' is not a valid argument",
|
||||
arg->typespec().structspec()->name());
|
||||
errorfmt("struct '{}' is not a valid argument",
|
||||
arg->typespec().structspec()->name());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1205,16 +1219,16 @@ ASTfunction_call::typecheck_printf_args(const char* format, ASTNode* arg)
|
||||
if ((arg->typespec().is_closure_based()
|
||||
|| simpletype.basetype == TypeDesc::STRING)
|
||||
&& formatchar != 's') {
|
||||
errorf(
|
||||
"%s has mismatched format string and arguments (arg %d needs %%s)",
|
||||
errorfmt(
|
||||
"{} has mismatched format string and arguments (arg {} needs %s)",
|
||||
m_name);
|
||||
return false;
|
||||
}
|
||||
if (simpletype.basetype == TypeDesc::INT && formatchar != 'd'
|
||||
&& formatchar != 'i' && formatchar != 'o' && formatchar != 'x'
|
||||
&& formatchar != 'X') {
|
||||
errorf(
|
||||
"%s has mismatched format string and arguments (arg %d needs %%d, %%i, %%o, %%x, or %%X)",
|
||||
errorfmt(
|
||||
"{} has mismatched format string and arguments (arg {} needs %d, %i, %o, %x, or %X)",
|
||||
m_name, argnum);
|
||||
return false;
|
||||
}
|
||||
@@ -1222,8 +1236,8 @@ ASTfunction_call::typecheck_printf_args(const char* format, ASTNode* arg)
|
||||
&& formatchar != 'g' && formatchar != 'c' && formatchar != 'e'
|
||||
&& formatchar != 'm' && formatchar != 'n' && formatchar != 'p'
|
||||
&& formatchar != 'v') {
|
||||
errorf(
|
||||
"%s has mismatched format string and arguments (arg %d needs %%f, %%g, or %%e)",
|
||||
errorfmt(
|
||||
"{} has mismatched format string and arguments (arg {} needs %f, %g, or %e)",
|
||||
m_name, argnum);
|
||||
return false;
|
||||
}
|
||||
@@ -1236,8 +1250,8 @@ ASTfunction_call::typecheck_printf_args(const char* format, ASTNode* arg)
|
||||
}
|
||||
}
|
||||
if (arg) {
|
||||
errorf("%s has mismatched format string and arguments (too many args)",
|
||||
m_name);
|
||||
errorfmt("{} has mismatched format string and arguments (too many args)",
|
||||
m_name);
|
||||
return false;
|
||||
}
|
||||
return true; // all ok
|
||||
@@ -1303,8 +1317,8 @@ ASTfunction_call::typecheck_builtin_specialcase()
|
||||
arg = arg->nextptr();
|
||||
typecheck_printf_args(format, arg);
|
||||
} else {
|
||||
warningf("%s() uses a format string that is not a constant.",
|
||||
m_name);
|
||||
warningfmt("{}() uses a format string that is not a constant.",
|
||||
m_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1379,8 +1393,8 @@ ASTfunction_call::typecheck_struct_constructor()
|
||||
m_typespec = m_sym->typespec();
|
||||
if (structspec->numfields() != (int)listlength(args())) {
|
||||
// Support a single argument which is an init-list of proper type?
|
||||
errorf(
|
||||
"Constructor for '%s' has the wrong number of arguments (expected %d, got %d)",
|
||||
errorfmt(
|
||||
"Constructor for '{}' has the wrong number of arguments (expected {}, got {})",
|
||||
structspec->name(), structspec->numfields(), listlength(args()));
|
||||
}
|
||||
|
||||
@@ -1607,7 +1621,7 @@ class CandidateFunctions {
|
||||
|
||||
default:
|
||||
// TODO: Scoring default function arguments would go here
|
||||
// Curently an unused formal argument, so no match at all.
|
||||
// Currently an unused formal argument, so no match at all.
|
||||
return kNoMatch;
|
||||
}
|
||||
OSL_DASSERT(*formals == 0);
|
||||
@@ -1672,8 +1686,8 @@ public:
|
||||
comma = ", ";
|
||||
}
|
||||
argstr += ")";
|
||||
return Strutil::sprintf("%s '%s'%s\n", msg, argstr,
|
||||
candidateMsg ? "\n Candidates are:" : "");
|
||||
return Strutil::fmt::format("{} '{}'{}\n", msg, argstr,
|
||||
candidateMsg ? "\n Candidates are:" : "");
|
||||
}
|
||||
|
||||
std::string reportFunction(FunctionSymbol* sym) const
|
||||
@@ -1684,10 +1698,10 @@ public:
|
||||
formals += advance;
|
||||
std::string msg = " ";
|
||||
if (ASTNode* decl = sym->node())
|
||||
msg += Strutil::sprintf("%s:%d\t", decl->sourcefile(),
|
||||
decl->sourceline());
|
||||
msg += Strutil::sprintf("%s %s (%s)\n", returntype, sym->name(),
|
||||
m_compiler->typelist_from_code(formals));
|
||||
msg += Strutil::fmt::format("{}:{}\t", decl->sourcefile(),
|
||||
decl->sourceline());
|
||||
msg += Strutil::fmt::format("{} {} ({})\n", returntype, sym->name(),
|
||||
m_compiler->typelist_from_code(formals));
|
||||
return msg;
|
||||
}
|
||||
|
||||
@@ -1715,7 +1729,7 @@ public:
|
||||
"No matching function call to");
|
||||
for (FunctionSymbol* f = m_called; f; f = f->nextpoly())
|
||||
errmsg += reportFunction(f);
|
||||
caller->errorf("%s", errmsg);
|
||||
caller->errorfmt("{}", errmsg);
|
||||
return { nullptr, TypeSpec() };
|
||||
|
||||
case 1: // Success
|
||||
@@ -1840,17 +1854,17 @@ public:
|
||||
= reportAmbiguity(funcname, !warn /* "Candidates are" msg*/,
|
||||
"Ambiguous call to");
|
||||
if (warn) {
|
||||
errmsg += Strutil::sprintf(" Chosen function is:\n%s",
|
||||
reportFunction(c.first->sym));
|
||||
errmsg += Strutil::fmt::format(" Chosen function is:\n{}",
|
||||
reportFunction(c.first->sym));
|
||||
errmsg += " Other candidates are:\n";
|
||||
for (auto& candidate : m_candidates)
|
||||
if (candidate.sym != c.first->sym)
|
||||
errmsg += reportFunction(candidate.sym);
|
||||
caller->warningf("%s", errmsg);
|
||||
caller->warningfmt("{}", errmsg);
|
||||
} else {
|
||||
for (auto& candidate : m_candidates)
|
||||
errmsg += reportFunction(candidate.sym);
|
||||
caller->errorf("%s", errmsg);
|
||||
caller->errorfmt("{}", errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1982,7 +1996,7 @@ ASTfunction_call::typecheck(TypeSpec expected)
|
||||
any_args_are_compound_initializers = true;
|
||||
}
|
||||
|
||||
// Save the currently choosen symbol for error reporting later
|
||||
// Save the currently chosen symbol for error reporting later
|
||||
FunctionSymbol* poly = func();
|
||||
|
||||
CandidateFunctions candidates(m_compiler, expected, args(), poly);
|
||||
@@ -2013,9 +2027,9 @@ ASTfunction_call::typecheck(TypeSpec expected)
|
||||
if (Strutil::iequals(OSL_LEGACY, "use"))
|
||||
m_sym = legacy;
|
||||
if (as_warning)
|
||||
warningf("overload chosen differs from OSL 1.9\n%s", errmsg);
|
||||
warningfmt("overload chosen differs from OSL 1.9\n{}", errmsg);
|
||||
else
|
||||
errorf("overload chosen differs from OSL 1.9\n%s", errmsg);
|
||||
errorfmt("overload chosen differs from OSL 1.9\n{}", errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2053,8 +2067,8 @@ ASTfunction_call::typecheck(TypeSpec expected)
|
||||
if (formal->is_output()
|
||||
&& !check_symbol_writeability(a, true, &dest_sym)) {
|
||||
OSL_DASSERT(dest_sym);
|
||||
warningf(
|
||||
"cannot write to non-output parameter \"%s\", as passed to function %s() as arg %d (output parameter \"%s\")",
|
||||
warningfmt(
|
||||
"cannot write to non-output parameter \"{}\", as passed to function {}() as arg {} (output parameter \"{}\")",
|
||||
dest_sym->name(), func()->name(), i + 1, formal->name());
|
||||
}
|
||||
}
|
||||
@@ -2062,8 +2076,8 @@ ASTfunction_call::typecheck(TypeSpec expected)
|
||||
|
||||
if (is_user_function()) {
|
||||
if (func()->number_of_returns() == 0 && !func()->typespec().is_void()) {
|
||||
errorf("non-void function \"%s\" had no 'return' statement.",
|
||||
func()->name());
|
||||
errorfmt("non-void function \"{}\" had no 'return' statement.",
|
||||
func()->name());
|
||||
}
|
||||
} else {
|
||||
// built-in
|
||||
@@ -2318,7 +2332,7 @@ OSLCompilerImpl::code_from_type(TypeSpec type) const
|
||||
std::string out;
|
||||
TypeDesc elem = type.elementtype().simpletype();
|
||||
if (type.is_structure() || type.is_structure_array()) {
|
||||
out = Strutil::sprintf("S%d", type.structure());
|
||||
out = Strutil::fmt::format("S{}", type.structure());
|
||||
} else if (type.is_closure() || type.is_closure_array()) {
|
||||
out = 'C';
|
||||
} else {
|
||||
@@ -2352,7 +2366,7 @@ OSLCompilerImpl::code_from_type(TypeSpec type) const
|
||||
if (type.is_unsized_array())
|
||||
out += "[]";
|
||||
else
|
||||
out += Strutil::sprintf("[%d]", type.arraylength());
|
||||
out += Strutil::fmt::format("[{}]", type.arraylength());
|
||||
}
|
||||
|
||||
return out;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
set ( liboslexec_target_srcs
|
||||
wide/wide_opalgebraic
|
||||
wide/wide_opcolor
|
||||
wide/wide_opclosure
|
||||
wide/wide_opdictionary
|
||||
wide/wide_ophash
|
||||
wide/wide_opmatrix
|
||||
@@ -120,6 +121,7 @@ set (lib_src
|
||||
shadeimage.cpp
|
||||
backendllvm.cpp
|
||||
llvm_gen.cpp llvm_instance.cpp llvm_util.cpp
|
||||
rs_fallback.cpp
|
||||
)
|
||||
if (BUILD_BATCHED)
|
||||
list(APPEND lib_src
|
||||
@@ -179,94 +181,6 @@ foreach(src ${lib_src})
|
||||
endif()
|
||||
endforeach(src)
|
||||
|
||||
macro ( LLVM_COMPILE llvm_src srclist )
|
||||
get_filename_component ( llvmsrc_we ${llvm_src} NAME_WE )
|
||||
set ( llvm_asm "${CMAKE_CURRENT_BINARY_DIR}/${llvmsrc_we}.s" )
|
||||
set ( llvm_bc "${CMAKE_CURRENT_BINARY_DIR}/${llvmsrc_we}.bc" )
|
||||
set ( llvm_bc_cpp "${CMAKE_CURRENT_BINARY_DIR}/${llvmsrc_we}.bc.cpp" )
|
||||
if (VERBOSE)
|
||||
message (STATUS "LLVM_COMPILE in=${llvm_src}")
|
||||
message (STATUS "LLVM_COMPILE asm=${llvm_asm}")
|
||||
message (STATUS "LLVM_COMPILE bc=${llvm_bc}")
|
||||
message (STATUS "LLVM_COMPILE cpp=${llvm_bc_cpp}")
|
||||
endif ()
|
||||
set ( ${srclist} ${${srclist}} ${llvm_bc_cpp} )
|
||||
get_property (CURRENT_DEFINITIONS DIRECTORY PROPERTY COMPILE_DEFINITIONS)
|
||||
if (VERBOSE)
|
||||
message (STATUS "Current #defines are ${CURRENT_DEFINITIONS}")
|
||||
endif ()
|
||||
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} ${TOOLCHAIN_FLAGS})
|
||||
|
||||
# Figure out what program we will use to make the bitcode.
|
||||
if (NOT LLVM_BC_GENERATOR)
|
||||
find_program (LLVM_BC_GENERATOR NAMES "clang++"
|
||||
PATHS "${LLVM_DIRECTORY}/bin"
|
||||
NO_CMAKE_PATH NO_DEFAULT_PATH NO_CMAKE_SYSTEM_PATH
|
||||
NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_ENVIRONMENT_PATH)
|
||||
endif ()
|
||||
# If that didn't work, look anywhere
|
||||
if (NOT LLVM_BC_GENERATOR)
|
||||
# Wasn't in their build, look anywhere
|
||||
find_program (LLVM_BC_GENERATOR NAMES clang++ llvm-g++)
|
||||
endif ()
|
||||
|
||||
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()
|
||||
|
||||
# Fix specific problem I had on new Apple systems (e.g. Mavericks) with
|
||||
# LLVM/libc++ installed -- for some reason, LLVM 3.4 wasn't finding it,
|
||||
# so in that specific case, append another -I to point it in the right
|
||||
# direction.
|
||||
#if (APPLE AND ${LLVM_BC_GENERATOR} MATCHES ".*clang.*")
|
||||
# exec_program ( "${LLVM_BC_GENERATOR}" ARGS --version OUTPUT_VARIABLE MY_CLANG_VERSION )
|
||||
# string (REGEX REPLACE "clang version ([0-9][.][0-9]+).*" "\\1" MY_CLANG_VERSION "${MY_CLANG_VERSION}")
|
||||
# if ((${MY_CLANG_VERSION} VERSION_GREATER "3.3")
|
||||
# AND (EXISTS "/usr/lib/libc++.dylib")
|
||||
# AND (EXISTS "/Library/Developer/CommandLineTools/usr/lib/c++/v1"))
|
||||
# set (LLVM_COMPILE_FLAGS ${LLVM_COMPILE_FLAGS} "-I/Library/Developer/CommandLineTools/usr/lib/c++/v1")
|
||||
# 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)
|
||||
|
||||
# Command to turn the .cpp file into LLVM assembly language .s, into
|
||||
# LLVM bitcode .bc, then back into a C++ file with the bc embedded!
|
||||
add_custom_command ( OUTPUT ${llvm_bc_cpp}
|
||||
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}"
|
||||
-DOSL_COMPILING_TO_BITCODE=1
|
||||
-Wno-deprecated-register
|
||||
# the following 2 warnings can be restored when all 3rd parties have fixed their export macros
|
||||
# (dllimport attribute is not supported when compiling for Cuda and triggers a ton of warnings)
|
||||
-Wno-ignored-attributes -Wno-unknown-attributes
|
||||
-O3 -fno-math-errno -S -emit-llvm -o ${llvm_asm} ${llvm_src}
|
||||
COMMAND "${LLVM_DIRECTORY}/bin/llvm-as" -f -o ${llvm_bc} ${llvm_asm}
|
||||
COMMAND python "${CMAKE_CURRENT_SOURCE_DIR}/serialize-bc.py" ${llvm_bc} ${llvm_bc_cpp} "osl_llvm_compiled_ops"
|
||||
MAIN_DEPENDENCY ${llvm_src}
|
||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/serialize-bc.py"
|
||||
${exec_headers} ${PROJECT_PUBLIC_HEADERS}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
endmacro ( )
|
||||
|
||||
|
||||
macro ( CUDA_SHADEOPS_COMPILE srclist )
|
||||
# Add all of the "shadeops" sources that need to be compiled to LLVM bitcode for CUDA
|
||||
set ( shadeops_srcs
|
||||
@@ -291,21 +205,31 @@ macro ( CUDA_SHADEOPS_COMPILE srclist )
|
||||
|
||||
# Link all of the individual LLVM bitcode files
|
||||
add_custom_command ( OUTPUT ${linked_shadeops_bc}
|
||||
COMMAND "${LLVM_DIRECTORY}/bin/llvm-link" -internalize ${shadeops_bc_list} -o ${linked_shadeops_bc}
|
||||
COMMAND ${LLVM_LINK_TOOL} -internalize ${shadeops_bc_list} -o ${linked_shadeops_bc}
|
||||
DEPENDS ${shadeops_bc_list} ${exec_headers} ${PROJECT_PUBLIC_HEADERS} ${shadeops_srcs}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
|
||||
# Serialize the linked bitcode into a CPP file and add it to the list of liboslexec soures
|
||||
# Serialize the linked bitcode into a CPP file and add it to the list of liboslexec sources
|
||||
add_custom_command ( OUTPUT ${shadeops_bc_cuda_cpp}
|
||||
COMMAND python "${CMAKE_CURRENT_SOURCE_DIR}/serialize-bc.py"
|
||||
COMMAND ${Python_EXECUTABLE} "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py"
|
||||
${linked_shadeops_bc} ${shadeops_bc_cuda_cpp} "osl_llvm_compiled_ops_cuda"
|
||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/serialize-bc.py" ${linked_shadeops_bc}
|
||||
DEPENDS "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py" ${linked_shadeops_bc}
|
||||
${exec_headers} ${PROJECT_PUBLIC_HEADERS}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
endmacro ( )
|
||||
|
||||
if (USE_LLVM_BITCODE)
|
||||
LLVM_COMPILE ( llvm_ops.cpp lib_src )
|
||||
set (llvm_ops_srcs llvm_ops.cpp)
|
||||
EMBED_LLVM_BITCODE_IN_CPP ( "${llvm_ops_srcs}" "_host" "osl_llvm_compiled_ops" lib_src "")
|
||||
|
||||
set (rs_dependent_ops_srcs
|
||||
opmatrix.cpp
|
||||
)
|
||||
# Achieve the effect of absorbing osl_llvm_compiled_ops by adding its
|
||||
# sources to rs_dependent_ops_srcs which avoids having to do it at runtime.
|
||||
list (APPEND rs_dependent_ops_srcs ${llvm_ops_srcs})
|
||||
|
||||
EMBED_LLVM_BITCODE_IN_CPP ( "${rs_dependent_ops_srcs}" "_host_rs" "osl_llvm_compiled_rs_dependent_ops" lib_src "")
|
||||
|
||||
# Optionally repeat the bitcode compilation with CUDA-specific options
|
||||
if (CUDA_FOUND)
|
||||
@@ -428,7 +352,7 @@ foreach(batched_target ${BATCHED_TARGET_LIST})
|
||||
endif ()
|
||||
|
||||
if (CMAKE_COMPILER_IS_CLANG OR CMAKE_COMPILER_IS_APPLECLANG)
|
||||
# REQUIRES CLANG 7+ to use sucessfully vectorize with OpenMP simd
|
||||
# REQUIRES CLANG 7+ to use successfully vectorize with OpenMP simd
|
||||
|
||||
if (${TARGET_OPT_ISA} STREQUAL "AVX512")
|
||||
list (APPEND TARGET_CXX_OPTS "-march=skylake-avx512")
|
||||
@@ -446,7 +370,13 @@ foreach(batched_target ${BATCHED_TARGET_LIST})
|
||||
endif ()
|
||||
|
||||
if (${TARGET_OPT_FMA} STREQUAL "noFMA")
|
||||
list (APPEND TARGET_CXX_OPTS "-mno-fma")
|
||||
# Do NOT use "-mno-fma" as it may lower ISA to one without any FMA
|
||||
# instructions (AVX512->AVX2). Our intent is to not generate
|
||||
# FMA's but still use the available instructions and register
|
||||
# width. However math library calls may use still end up using
|
||||
# FMA's, but lets try turning of fused math ops because many OSL
|
||||
# math functions are from OIIO/IMath headers generate non FMA
|
||||
list (APPEND TARGET_CXX_OPTS "-ffp-contract=off")
|
||||
endif ()
|
||||
|
||||
# large SIMD function loops will exceed llvm's -inline-threshold default of 225.
|
||||
@@ -464,7 +394,8 @@ foreach(batched_target ${BATCHED_TARGET_LIST})
|
||||
list (APPEND TARGET_CXX_OPTS "-fno-unroll-loops")
|
||||
|
||||
if (CMAKE_COMPILER_IS_INTELCLANG)
|
||||
list (APPEND TARGET_CXX_OPTS "-qopenmp-simd")
|
||||
# utilize Intel compiler's optimized openmp simd generation vs. open source "-qopenmp-simd"
|
||||
list (APPEND TARGET_CXX_OPTS "-fiopenmp-simd")
|
||||
else ()
|
||||
list (APPEND TARGET_CXX_OPTS "-fopenmp")
|
||||
endif ()
|
||||
@@ -510,7 +441,13 @@ foreach(batched_target ${BATCHED_TARGET_LIST})
|
||||
endif ()
|
||||
|
||||
if (${TARGET_OPT_FMA} STREQUAL "noFMA")
|
||||
list (APPEND TARGET_CXX_OPTS "-mno-fma")
|
||||
# Do NOT use "-mno-fma" as it may lower ISA to one without any FMA
|
||||
# instructions (AVX512->AVX2). Our intent is to not generate
|
||||
# FMA's but still use the available instructions and register
|
||||
# width. However math library calls may use still end up using
|
||||
# FMA's, but lets try turning of fused math ops because many OSL
|
||||
# math functions are from OIIO/IMath headers generate non FMA
|
||||
list (APPEND TARGET_CXX_OPTS "-ffp-contract=off")
|
||||
endif ()
|
||||
|
||||
list (APPEND TARGET_CXX_OPTS "-fopenmp-simd")
|
||||
|
||||
+28
-26
@@ -12,7 +12,7 @@ OSL_NAMESPACE_ENTER
|
||||
|
||||
|
||||
void
|
||||
AovOutput::flush(void *flush_data)
|
||||
AovOutput::flush(void* flush_data)
|
||||
{
|
||||
if (!aov)
|
||||
return;
|
||||
@@ -21,7 +21,7 @@ AovOutput::flush(void *flush_data)
|
||||
has_color = true;
|
||||
}
|
||||
if (neg_alpha) {
|
||||
alpha = 1.0f - alpha;
|
||||
alpha = 1.0f - alpha;
|
||||
has_alpha = true;
|
||||
}
|
||||
|
||||
@@ -31,10 +31,10 @@ AovOutput::flush(void *flush_data)
|
||||
|
||||
|
||||
void
|
||||
AccumRule::accum(const Color3 &color, std::vector<AovOutput> &outputs)const
|
||||
AccumRule::accum(const Color3& color, std::vector<AovOutput>& outputs) const
|
||||
{
|
||||
if (m_save_to_alpha) {
|
||||
outputs[m_outidx].alpha += (color.x + color.y + color.z) * 1.0f/3.0f;
|
||||
outputs[m_outidx].alpha += (color.x + color.y + color.z) * 1.0f / 3.0f;
|
||||
outputs[m_outidx].has_alpha = true;
|
||||
} else {
|
||||
outputs[m_outidx].color += color;
|
||||
@@ -44,7 +44,6 @@ AccumRule::accum(const Color3 &color, std::vector<AovOutput> &outputs)const
|
||||
|
||||
|
||||
|
||||
|
||||
AccumAutomata::~AccumAutomata()
|
||||
{
|
||||
for (auto& r : m_rules)
|
||||
@@ -53,21 +52,22 @@ AccumAutomata::~AccumAutomata()
|
||||
|
||||
|
||||
|
||||
AccumRule *
|
||||
AccumAutomata::addRule(const char *pattern, int outidx, bool toalpha)
|
||||
AccumRule*
|
||||
AccumAutomata::addRule(const char* pattern, int outidx, bool toalpha)
|
||||
{
|
||||
// First parse the lpexp and see if it fails
|
||||
Parser parser(&m_user_events, &m_user_scatterings);
|
||||
LPexp *e = parser.parse(pattern);
|
||||
LPexp* e = parser.parse(pattern);
|
||||
if (parser.error()) {
|
||||
std::cerr << "[pathexp] Parse error" << parser.getErrorMsg() << " at char " << parser.getErrorPos() << std::endl;
|
||||
std::cerr << "[pathexp] Parse error" << parser.getErrorMsg()
|
||||
<< " at char " << parser.getErrorPos() << std::endl;
|
||||
delete e;
|
||||
return NULL;
|
||||
}
|
||||
m_accumrules.emplace_back(outidx, toalpha);
|
||||
// it is a list, so as long as we don't remove it from there, the pointer is valid
|
||||
void *rule = (void *)&(m_accumrules.back());
|
||||
m_rules.push_back (new lpexp::Rule (e, rule));
|
||||
void* rule = (void*)&(m_accumrules.back());
|
||||
m_rules.push_back(new lpexp::Rule(e, rule));
|
||||
return &(m_accumrules.back());
|
||||
}
|
||||
|
||||
@@ -91,28 +91,29 @@ AccumAutomata::compile()
|
||||
|
||||
|
||||
void
|
||||
AccumAutomata::accum(int state, const Color3 &color, std::vector<AovOutput> &outputs)const
|
||||
AccumAutomata::accum(int state, const Color3& color,
|
||||
std::vector<AovOutput>& outputs) const
|
||||
{
|
||||
// get the rules field, the underlying type is a std::vector
|
||||
int nrules = 0;
|
||||
void * const * rules = getRulesInState(state, nrules);
|
||||
int nrules = 0;
|
||||
void* const* rules = getRulesInState(state, nrules);
|
||||
// Iterate the vector
|
||||
for (int i = 0; i < nrules; ++i)
|
||||
// Let the accumulator rule do its job
|
||||
((AccumRule *)(rules[i]))->accum(color, outputs);
|
||||
((AccumRule*)(rules[i]))->accum(color, outputs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Accumulator::Accumulator(const AccumAutomata *accauto)
|
||||
Accumulator::Accumulator(const AccumAutomata* accauto)
|
||||
: m_accum_automata(accauto)
|
||||
{
|
||||
const auto &rules = m_accum_automata->getRuleList();
|
||||
const auto& rules = m_accum_automata->getRuleList();
|
||||
// Make sure we have as many outputs as the rules need
|
||||
int maxouts = 0;
|
||||
for (const auto& i : rules)
|
||||
maxouts = std::max(i.getOutputIndex(), maxouts);
|
||||
m_outputs.resize(maxouts+1);
|
||||
m_outputs.resize(maxouts + 1);
|
||||
|
||||
// 0 is our initial state always
|
||||
m_state = 0;
|
||||
@@ -121,10 +122,10 @@ Accumulator::Accumulator(const AccumAutomata *accauto)
|
||||
|
||||
|
||||
void
|
||||
Accumulator::setAov(int outidx, Aov *aov, bool neg_color, bool neg_alpha)
|
||||
Accumulator::setAov(int outidx, Aov* aov, bool neg_color, bool neg_alpha)
|
||||
{
|
||||
OSL_ASSERT (0 <= outidx && outidx < (int) m_outputs.size());
|
||||
m_outputs[outidx].aov = aov;
|
||||
OSL_ASSERT(0 <= outidx && outidx < (int)m_outputs.size());
|
||||
m_outputs[outidx].aov = aov;
|
||||
m_outputs[outidx].neg_color = neg_color;
|
||||
m_outputs[outidx].neg_alpha = neg_alpha;
|
||||
}
|
||||
@@ -134,7 +135,7 @@ Accumulator::setAov(int outidx, Aov *aov, bool neg_color, bool neg_alpha)
|
||||
void
|
||||
Accumulator::pushState()
|
||||
{
|
||||
OSL_ASSERT (m_state >= 0);
|
||||
OSL_ASSERT(m_state >= 0);
|
||||
m_stack.push(m_state);
|
||||
}
|
||||
|
||||
@@ -143,7 +144,7 @@ Accumulator::pushState()
|
||||
void
|
||||
Accumulator::popState()
|
||||
{
|
||||
OSL_ASSERT (m_stack.size());
|
||||
OSL_ASSERT(m_stack.size());
|
||||
m_state = m_stack.top();
|
||||
m_stack.pop();
|
||||
}
|
||||
@@ -160,7 +161,7 @@ Accumulator::move(ustring symbol)
|
||||
|
||||
|
||||
void
|
||||
Accumulator::move(const ustring *symbols)
|
||||
Accumulator::move(const ustring* symbols)
|
||||
{
|
||||
while (m_state >= 0 && symbols && *symbols != Labels::NONE)
|
||||
m_state = m_accum_automata->getTransition(m_state, *(symbols++));
|
||||
@@ -169,7 +170,8 @@ Accumulator::move(const ustring *symbols)
|
||||
|
||||
|
||||
void
|
||||
Accumulator::move(ustring event, ustring scatt, const ustring *custom, ustring stop)
|
||||
Accumulator::move(ustring event, ustring scatt, const ustring* custom,
|
||||
ustring stop)
|
||||
{
|
||||
if (m_state >= 0)
|
||||
m_state = m_accum_automata->getTransition(m_state, event);
|
||||
@@ -193,7 +195,7 @@ Accumulator::begin()
|
||||
|
||||
|
||||
void
|
||||
Accumulator::end(void *flush_data)
|
||||
Accumulator::end(void* flush_data)
|
||||
{
|
||||
for (size_t i = 0; i < m_outputs.size(); ++i)
|
||||
m_outputs[i].flush(flush_data);
|
||||
|
||||
@@ -10,67 +10,63 @@ using namespace OSL;
|
||||
|
||||
#define END_AOV 65535
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *path[16];
|
||||
typedef struct {
|
||||
const char* path[16];
|
||||
int expected[8];
|
||||
} TestPath;
|
||||
|
||||
|
||||
// This is a fake AOV implementation. It will just keep track
|
||||
// of what test cases wrote to it
|
||||
class MyAov final : public Aov
|
||||
{
|
||||
public:
|
||||
MyAov(const TestPath *test, int id)
|
||||
{
|
||||
// Init for the test case array. For each test case set a bool
|
||||
// in m_expected marking wether this AOV should get some color
|
||||
// from that test or not.
|
||||
for (int i = 0; test[i].path[0]; ++i) { // iterate test cases
|
||||
m_expected.push_back(false); // false by default
|
||||
for (const int *expected = test[i].expected; *expected != END_AOV; ++expected)
|
||||
if (*expected == id)
|
||||
// if the AOV id is on the test's expected list, set it to true
|
||||
m_expected[i] = true;
|
||||
}
|
||||
m_received.resize(m_expected.size());
|
||||
class MyAov final : public Aov {
|
||||
public:
|
||||
MyAov(const TestPath* test, int id)
|
||||
{
|
||||
// Init for the test case array. For each test case set a bool
|
||||
// in m_expected marking whether this AOV should get some color
|
||||
// from that test or not.
|
||||
for (int i = 0; test[i].path[0]; ++i) { // iterate test cases
|
||||
m_expected.push_back(false); // false by default
|
||||
for (const int* expected = test[i].expected; *expected != END_AOV;
|
||||
++expected)
|
||||
if (*expected == id)
|
||||
// if the AOV id is on the test's expected list, set it to true
|
||||
m_expected[i] = true;
|
||||
}
|
||||
virtual ~MyAov() {}
|
||||
m_received.resize(m_expected.size());
|
||||
}
|
||||
virtual ~MyAov() {}
|
||||
|
||||
virtual void write(void *flush_data, Color3 &color, float /*alpha*/,
|
||||
bool has_color, bool /*has_alpha*/)
|
||||
{
|
||||
// our custom argument to write is the rule's number so we
|
||||
// can check what. But you normally would pass information
|
||||
// about the pixel.
|
||||
long int testno = (long int)flush_data;
|
||||
if (has_color && color.x > 0)
|
||||
// only mrk with true if there is a positive color present
|
||||
m_received[testno] = true;
|
||||
else
|
||||
m_received[testno] = false;
|
||||
}
|
||||
virtual void write(void* flush_data, Color3& color, float /*alpha*/,
|
||||
bool has_color, bool /*has_alpha*/)
|
||||
{
|
||||
// our custom argument to write is the rule's number so we
|
||||
// can check what. But you normally would pass information
|
||||
// about the pixel.
|
||||
size_t testno = reinterpret_cast<size_t>(flush_data);
|
||||
if (has_color && color.x > 0)
|
||||
// only mrk with true if there is a positive color present
|
||||
m_received[testno] = true;
|
||||
else
|
||||
m_received[testno] = false;
|
||||
}
|
||||
|
||||
bool check()
|
||||
{
|
||||
return m_expected == m_received;
|
||||
}
|
||||
bool check() { return m_expected == m_received; }
|
||||
|
||||
protected:
|
||||
|
||||
std::vector<bool> m_expected;
|
||||
std::vector<bool> m_received;
|
||||
protected:
|
||||
std::vector<bool> m_expected;
|
||||
std::vector<bool> m_received;
|
||||
};
|
||||
|
||||
// Simulate the tracing of a path with the accumulator
|
||||
void simulate(Accumulator &accum, const char **events, int testno)
|
||||
void
|
||||
simulate(Accumulator& accum, const char** events, size_t testno)
|
||||
{
|
||||
accum.begin();
|
||||
accum.pushState();
|
||||
// for each ray stop in the path (see test cases) ...
|
||||
while (*events) {
|
||||
const char *e = *events;
|
||||
const char* e = *events;
|
||||
// for each label in this hit
|
||||
while (*e) {
|
||||
ustring sym(e, 1);
|
||||
@@ -86,12 +82,13 @@ void simulate(Accumulator &accum, const char **events, int testno)
|
||||
accum.accum(Color3(1, 1, 1));
|
||||
// Restore state and flush
|
||||
accum.popState();
|
||||
accum.end((void *)(long int)testno);
|
||||
accum.end(reinterpret_cast<void*>(testno));
|
||||
}
|
||||
|
||||
int main()
|
||||
int
|
||||
main()
|
||||
{
|
||||
// Some constants to avoid refering to AOV's by number
|
||||
// Some constants to avoid referring to AOV's by number
|
||||
const int beauty = 0;
|
||||
const int diffuse2_3 = 1;
|
||||
const int light3 = 2;
|
||||
@@ -107,20 +104,29 @@ int main()
|
||||
// The actual test cases. Each one is a list of ray hits with some labels.
|
||||
// We use 1 char labels for convenience. They will be converted to ustrings
|
||||
// by simulate. And then a list of expected AOV's for each.
|
||||
TestPath test[] = { { { "C_", "TS", "TS", "RD", "L_", NULL }, { beauty, specular, nocaustic, END_AOV} },
|
||||
{ { "C_", "TS", "TS", "RD", "RG", "L_", NULL }, { END_AOV } },
|
||||
{ { "C_", "TS", "TS", "RD", "RD", "L_", NULL }, { beauty, specular, diffuse2_3, nocaustic, END_AOV } },
|
||||
{ { "C_", "RG", "RD", "RG", "RD", "RG", "RD", "L_", NULL }, { END_AOV } },
|
||||
{ { "C_", "RG", "RD", "RG", "RD", "L_", NULL }, { nocaustic, END_AOV } },
|
||||
{ { "C_", "RD", "RD", "L_", NULL }, { beauty, diffuse, diffuse2_3, nocaustic, END_AOV } },
|
||||
{ { "C_", "RD", "RS", "RD", "L_", NULL }, { nocaustic, END_AOV } },
|
||||
{ { "C_", "RD", "Ts", "L_", NULL }, { transpshadow, END_AOV } },
|
||||
{ { "C_", "TS", "TS", "RD", "L_3", NULL }, { beauty, specular, light3, nocaustic, END_AOV } },
|
||||
{ { "C_", "RD1", "RD", "L_", NULL }, { beauty, diffuse, diffuse2_3, object_1, nocaustic, END_AOV } },
|
||||
{ { "C_", "RS", "RD", "RG", "L_", NULL }, { END_AOV } },
|
||||
{ { "C_", "RS", "RD", "L_", NULL }, { beauty, specular, reflections, nocaustic, END_AOV } },
|
||||
{ { "C_", "RD", "RY", "RD", "U_", NULL }, { custom, END_AOV } },
|
||||
{ { NULL }, { END_AOV } } };
|
||||
TestPath test[]
|
||||
= { { { "C_", "TS", "TS", "RD", "L_", NULL },
|
||||
{ beauty, specular, nocaustic, END_AOV } },
|
||||
{ { "C_", "TS", "TS", "RD", "RG", "L_", NULL }, { END_AOV } },
|
||||
{ { "C_", "TS", "TS", "RD", "RD", "L_", NULL },
|
||||
{ beauty, specular, diffuse2_3, nocaustic, END_AOV } },
|
||||
{ { "C_", "RG", "RD", "RG", "RD", "RG", "RD", "L_", NULL },
|
||||
{ END_AOV } },
|
||||
{ { "C_", "RG", "RD", "RG", "RD", "L_", NULL },
|
||||
{ nocaustic, END_AOV } },
|
||||
{ { "C_", "RD", "RD", "L_", NULL },
|
||||
{ beauty, diffuse, diffuse2_3, nocaustic, END_AOV } },
|
||||
{ { "C_", "RD", "RS", "RD", "L_", NULL }, { nocaustic, END_AOV } },
|
||||
{ { "C_", "RD", "Ts", "L_", NULL }, { transpshadow, END_AOV } },
|
||||
{ { "C_", "TS", "TS", "RD", "L_3", NULL },
|
||||
{ beauty, specular, light3, nocaustic, END_AOV } },
|
||||
{ { "C_", "RD1", "RD", "L_", NULL },
|
||||
{ beauty, diffuse, diffuse2_3, object_1, nocaustic, END_AOV } },
|
||||
{ { "C_", "RS", "RD", "RG", "L_", NULL }, { END_AOV } },
|
||||
{ { "C_", "RS", "RD", "L_", NULL },
|
||||
{ beauty, specular, reflections, nocaustic, END_AOV } },
|
||||
{ { "C_", "RD", "RY", "RD", "U_", NULL }, { custom, END_AOV } },
|
||||
{ { NULL }, { END_AOV } } };
|
||||
|
||||
// Create our fake testing AOV's
|
||||
std::vector<MyAov> aovs;
|
||||
@@ -133,21 +139,21 @@ int main()
|
||||
automata.addEventType(ustring("U"));
|
||||
automata.addScatteringType(ustring("Y"));
|
||||
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C[SG]*D*L", beauty));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C[SG]*D{2,3}L", diffuse2_3));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C[SG]*D*<L.'3'>", light3));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C[SG]*D*L", beauty));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C[SG]*D{2,3}L", diffuse2_3));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C[SG]*D*<L.'3'>", light3));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C[SG]*<.D'1'>D*L", object_1));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C<.[SG]>+D*L", specular));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("CD+L", diffuse));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("CD+<Ts>L", transpshadow));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C<R[^D]>+D*L", reflections));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C([SG]*D){1,2}L", nocaustic));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("CDY+U", custom));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C<.[SG]>+D*L", specular));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("CD+L", diffuse));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("CD+<Ts>L", transpshadow));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C<R[^D]>+D*L", reflections));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C([SG]*D){1,2}L", nocaustic));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("CDY+U", custom));
|
||||
|
||||
automata.compile();
|
||||
|
||||
// now create the accumulator
|
||||
Accumulator accum (&automata);
|
||||
Accumulator accum(&automata);
|
||||
|
||||
// and set the AOV's for each id (beauty, diffuse2_3, etc ...)
|
||||
for (int i = 0; i < naovs; ++i)
|
||||
@@ -159,15 +165,15 @@ int main()
|
||||
|
||||
// And check. We unroll this loop for boost to give us a useful
|
||||
// error in case they fail
|
||||
OIIO_CHECK_ASSERT(aovs[beauty ].check());
|
||||
OIIO_CHECK_ASSERT(aovs[diffuse2_3 ].check());
|
||||
OIIO_CHECK_ASSERT(aovs[light3 ].check());
|
||||
OIIO_CHECK_ASSERT(aovs[object_1 ].check());
|
||||
OIIO_CHECK_ASSERT(aovs[specular ].check());
|
||||
OIIO_CHECK_ASSERT(aovs[diffuse ].check());
|
||||
OIIO_CHECK_ASSERT(aovs[beauty].check());
|
||||
OIIO_CHECK_ASSERT(aovs[diffuse2_3].check());
|
||||
OIIO_CHECK_ASSERT(aovs[light3].check());
|
||||
OIIO_CHECK_ASSERT(aovs[object_1].check());
|
||||
OIIO_CHECK_ASSERT(aovs[specular].check());
|
||||
OIIO_CHECK_ASSERT(aovs[diffuse].check());
|
||||
OIIO_CHECK_ASSERT(aovs[transpshadow].check());
|
||||
OIIO_CHECK_ASSERT(aovs[reflections ].check());
|
||||
OIIO_CHECK_ASSERT(aovs[nocaustic ].check());
|
||||
OIIO_CHECK_ASSERT(aovs[reflections].check());
|
||||
OIIO_CHECK_ASSERT(aovs[nocaustic].check());
|
||||
|
||||
std::cout << "Light expressions check OK" << std::endl;
|
||||
return unit_test_failures;
|
||||
|
||||
+153
-100
@@ -13,17 +13,18 @@ OSL_NAMESPACE_ENTER
|
||||
namespace Strutil = OIIO::Strutil;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf sprintf_s
|
||||
# define snprintf sprintf_s
|
||||
#endif
|
||||
|
||||
ustring lambda("__lambda__");
|
||||
|
||||
void
|
||||
NdfAutomata::State::getTransitions(ustring symbol, IntSet &out_states)const
|
||||
NdfAutomata::State::getTransitions(ustring symbol, IntSet& out_states) const
|
||||
{
|
||||
SymbolToIntList::const_iterator s = m_symbol_trans.find(symbol);
|
||||
if (s != m_symbol_trans.end())
|
||||
for (IntSet::const_iterator i = s->second.begin(); i != s->second.end(); ++i)
|
||||
for (IntSet::const_iterator i = s->second.begin(); i != s->second.end();
|
||||
++i)
|
||||
out_states.insert(*i);
|
||||
if (m_wildcard && m_wildcard->matches(symbol))
|
||||
out_states.insert(m_wildcard_trans);
|
||||
@@ -32,16 +33,15 @@ NdfAutomata::State::getTransitions(ustring symbol, IntSet &out_states)const
|
||||
|
||||
static IntSet _emptyset;
|
||||
|
||||
std::pair <IntSet::const_iterator, IntSet::const_iterator>
|
||||
NdfAutomata::State::getLambdaTransitions ()const
|
||||
std::pair<IntSet::const_iterator, IntSet::const_iterator>
|
||||
NdfAutomata::State::getLambdaTransitions() const
|
||||
{
|
||||
std::pair <IntSet::const_iterator, IntSet::const_iterator> res;
|
||||
std::pair<IntSet::const_iterator, IntSet::const_iterator> res;
|
||||
SymbolToIntList::const_iterator s = m_symbol_trans.find(lambda);
|
||||
if (s != m_symbol_trans.end()) {
|
||||
res.first = s->second.begin();
|
||||
res.first = s->second.begin();
|
||||
res.second = s->second.end();
|
||||
}
|
||||
else
|
||||
} else
|
||||
// We use a static empty list to return an empty range
|
||||
res.first = res.second = _emptyset.end();
|
||||
return res;
|
||||
@@ -50,7 +50,7 @@ NdfAutomata::State::getLambdaTransitions ()const
|
||||
|
||||
|
||||
void
|
||||
NdfAutomata::State::addTransition(ustring symbol, NdfAutomata::State *state)
|
||||
NdfAutomata::State::addTransition(ustring symbol, NdfAutomata::State* state)
|
||||
{
|
||||
m_symbol_trans[symbol].insert(state->m_id);
|
||||
}
|
||||
@@ -58,24 +58,26 @@ NdfAutomata::State::addTransition(ustring symbol, NdfAutomata::State *state)
|
||||
|
||||
|
||||
void
|
||||
NdfAutomata::State::addWildcardTransition(Wildcard *wildcard, NdfAutomata::State *state)
|
||||
NdfAutomata::State::addWildcardTransition(Wildcard* wildcard,
|
||||
NdfAutomata::State* state)
|
||||
{
|
||||
if (m_wildcard)
|
||||
std::cerr << "[pathexp] redefining wildcard transition" << std::endl;
|
||||
m_wildcard = wildcard;
|
||||
m_wildcard = wildcard;
|
||||
m_wildcard_trans = state->m_id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string
|
||||
NdfAutomata::State::tostr()const
|
||||
NdfAutomata::State::tostr() const
|
||||
{
|
||||
std::string s = "";
|
||||
// output the transitions
|
||||
for (SymbolToIntList::const_iterator i = m_symbol_trans.begin(); i != m_symbol_trans.end(); ++i) {
|
||||
ustring sym = i->first;
|
||||
const IntSet &dest = i->second;
|
||||
for (SymbolToIntList::const_iterator i = m_symbol_trans.begin();
|
||||
i != m_symbol_trans.end(); ++i) {
|
||||
ustring sym = i->first;
|
||||
const IntSet& dest = i->second;
|
||||
if (s.size())
|
||||
s += " ";
|
||||
if (sym == lambda)
|
||||
@@ -84,9 +86,9 @@ NdfAutomata::State::tostr()const
|
||||
s += sym.c_str();
|
||||
s += ":{";
|
||||
for (IntSet::const_iterator j = dest.begin(); j != dest.end(); ++j) {
|
||||
if (s[s.size()-1] != '{')
|
||||
if (s[s.size() - 1] != '{')
|
||||
s += ", ";
|
||||
s += Strutil::sprintf("%d", *j);
|
||||
s += Strutil::to_string(*j);
|
||||
}
|
||||
s += "}";
|
||||
}
|
||||
@@ -100,7 +102,8 @@ NdfAutomata::State::tostr()const
|
||||
else {
|
||||
// Standard regexp notation [^abcd]
|
||||
s += "[^";
|
||||
for (SymbolSet::const_iterator i = m_wildcard->m_minus.begin(); i != m_wildcard->m_minus.end(); ++i) {
|
||||
for (SymbolSet::const_iterator i = m_wildcard->m_minus.begin();
|
||||
i != m_wildcard->m_minus.end(); ++i) {
|
||||
if (!i->c_str())
|
||||
s += "_";
|
||||
else
|
||||
@@ -108,19 +111,19 @@ NdfAutomata::State::tostr()const
|
||||
}
|
||||
s += "]:";
|
||||
}
|
||||
s += Strutil::sprintf("%d", m_wildcard_trans);
|
||||
s += Strutil::to_string(m_wildcard_trans);
|
||||
}
|
||||
// and finally the rule if we have it
|
||||
if (m_rule) {
|
||||
s += " | ";
|
||||
s += Strutil::sprintf("%lx", (long unsigned int)m_rule);
|
||||
s += Strutil::fmt::format("{:p}", m_rule);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NdfAutomata::State *
|
||||
NdfAutomata::State*
|
||||
NdfAutomata::newState()
|
||||
{
|
||||
m_states.push_back(new State(m_states.size()));
|
||||
@@ -130,13 +133,15 @@ NdfAutomata::newState()
|
||||
|
||||
|
||||
void
|
||||
NdfAutomata::symbolsFrom(const IntSet &states, SymbolSet &out_symbols, Wildcard *&wildcard)const
|
||||
NdfAutomata::symbolsFrom(const IntSet& states, SymbolSet& out_symbols,
|
||||
Wildcard*& wildcard) const
|
||||
{
|
||||
for (IntSet::const_iterator i = states.begin(); i != states.end(); ++i) {
|
||||
const State *state = m_states[*i];
|
||||
// For every state we have to go thorugh all the symbols in the transition table
|
||||
const State* state = m_states[*i];
|
||||
// For every state we have to go through all the symbols in the transition table
|
||||
// m_symbol_trans and add them to the output
|
||||
for (SymbolToIntList::const_iterator j = state->m_symbol_trans.begin(); j != state->m_symbol_trans.end(); ++j)
|
||||
for (SymbolToIntList::const_iterator j = state->m_symbol_trans.begin();
|
||||
j != state->m_symbol_trans.end(); ++j)
|
||||
if (j->first != lambda)
|
||||
out_symbols.insert(j->first);
|
||||
if (state->m_wildcard) {
|
||||
@@ -145,16 +150,19 @@ NdfAutomata::symbolsFrom(const IntSet &states, SymbolSet &out_symbols, Wildcard
|
||||
// And if the state has a wildcard movement, we need to add its exclusion list
|
||||
// to our new computed exclusion list. So we guarantee that the returned wildcard
|
||||
// matches will be contained in all the wildcards out of this set
|
||||
wildcard->m_minus.insert(state->m_wildcard->m_minus.begin(), state->m_wildcard->m_minus.end());
|
||||
wildcard->m_minus.insert(state->m_wildcard->m_minus.begin(),
|
||||
state->m_wildcard->m_minus.end());
|
||||
}
|
||||
}
|
||||
if (wildcard) {
|
||||
// We have to make sure that all the symbols covered by the wildcards
|
||||
// are either covered by our wildcard or in out_symbols set
|
||||
for (IntSet::const_iterator i = states.begin(); i != states.end(); ++i) {
|
||||
const State *state = m_states[*i];
|
||||
for (IntSet::const_iterator i = states.begin(); i != states.end();
|
||||
++i) {
|
||||
const State* state = m_states[*i];
|
||||
if (state->m_wildcard)
|
||||
for (SymbolSet::const_iterator j = wildcard->m_minus.begin(); j != wildcard->m_minus.end(); ++j)
|
||||
for (SymbolSet::const_iterator j = wildcard->m_minus.begin();
|
||||
j != wildcard->m_minus.end(); ++j)
|
||||
if (state->m_wildcard->matches(*j))
|
||||
out_symbols.insert(*j);
|
||||
}
|
||||
@@ -166,7 +174,8 @@ NdfAutomata::symbolsFrom(const IntSet &states, SymbolSet &out_symbols, Wildcard
|
||||
|
||||
|
||||
void
|
||||
NdfAutomata::transitionsFrom(const IntSet &states, ustring symbol, IntSet &out_states)const
|
||||
NdfAutomata::transitionsFrom(const IntSet& states, ustring symbol,
|
||||
IntSet& out_states) const
|
||||
{
|
||||
for (IntSet::const_iterator i = states.begin(); i != states.end(); ++i)
|
||||
// remember getTransitions is not destructive with out_states, it just adds stuff
|
||||
@@ -178,10 +187,11 @@ NdfAutomata::transitionsFrom(const IntSet &states, ustring symbol, IntSet &out_s
|
||||
|
||||
|
||||
void
|
||||
NdfAutomata::wildcardTransitionsFrom(const IntSet &states, IntSet &out_states)const
|
||||
NdfAutomata::wildcardTransitionsFrom(const IntSet& states,
|
||||
IntSet& out_states) const
|
||||
{
|
||||
for (IntSet::const_iterator i = states.begin(); i != states.end(); ++i) {
|
||||
const State *state = m_states[*i];
|
||||
const State* state = m_states[*i];
|
||||
if (state->m_wildcard)
|
||||
out_states.insert(state->m_wildcard_trans);
|
||||
}
|
||||
@@ -191,7 +201,7 @@ NdfAutomata::wildcardTransitionsFrom(const IntSet &states, IntSet &out_states)co
|
||||
|
||||
|
||||
void
|
||||
NdfAutomata::lambdaClosure(IntSet &states)const
|
||||
NdfAutomata::lambdaClosure(IntSet& states) const
|
||||
{
|
||||
// This algorithm basically keeps expanding the set until no new states appear
|
||||
// to avoid checking over and over the same states we keep a frontier pair of sets
|
||||
@@ -200,40 +210,42 @@ NdfAutomata::lambdaClosure(IntSet &states)const
|
||||
// First iterate all the states in the given set
|
||||
// and see what lambda transitions are there
|
||||
for (IntSet::const_iterator i = states.begin(); i != states.end(); ++i) {
|
||||
const State *state = m_states[*i];
|
||||
std::pair <IntSet::const_iterator, IntSet::const_iterator> lr;
|
||||
const State* state = m_states[*i];
|
||||
std::pair<IntSet::const_iterator, IntSet::const_iterator> lr;
|
||||
// iterate all lambda transitions for this state
|
||||
for (lr = state->getLambdaTransitions(); lr.first != lr.second; lr.first++) {
|
||||
for (lr = state->getLambdaTransitions(); lr.first != lr.second;
|
||||
lr.first++) {
|
||||
// Add them to the set, and if they were not already there add to the
|
||||
// frontier
|
||||
std::pair<IntSet::iterator, bool> rec = states.insert(*(lr.first));
|
||||
if (rec.second) // newly added
|
||||
if (rec.second) // newly added
|
||||
frontier.push_back(*(lr.first));
|
||||
}
|
||||
}
|
||||
// frontier becomes last discovered
|
||||
frontier.swap(discovered); // swap discovered and frontier
|
||||
while (discovered.size()) { // as long as there are new found states
|
||||
frontier.swap(discovered); // swap discovered and frontier
|
||||
while (discovered.size()) { // as long as there are new found states
|
||||
frontier.clear();
|
||||
// we do the same as in the above loop but with discovered instead of states
|
||||
for (auto i : discovered) {
|
||||
const State *state = m_states[i];
|
||||
for (auto lr = state->getLambdaTransitions(); lr.first != lr.second; lr.first++) {
|
||||
std::pair<IntSet::iterator, bool> rec = states.insert(*(lr.first));
|
||||
const State* state = m_states[i];
|
||||
for (auto lr = state->getLambdaTransitions(); lr.first != lr.second;
|
||||
lr.first++) {
|
||||
std::pair<IntSet::iterator, bool> rec = states.insert(
|
||||
*(lr.first));
|
||||
if (rec.second)
|
||||
frontier.push_back(*(lr.first));
|
||||
}
|
||||
|
||||
}
|
||||
// again frontier becomes last discovered
|
||||
frontier.swap(discovered); // swap discovered and frontier
|
||||
frontier.swap(discovered); // swap discovered and frontier
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string
|
||||
NdfAutomata::tostr()const
|
||||
NdfAutomata::tostr() const
|
||||
{
|
||||
std::string s;
|
||||
for (size_t i = 0; i < m_states.size(); ++i) {
|
||||
@@ -254,9 +266,10 @@ NdfAutomata::~NdfAutomata()
|
||||
|
||||
|
||||
|
||||
void keyFromStateSet(const IntSet &states, StateSetKey &out_key)
|
||||
void
|
||||
keyFromStateSet(const IntSet& states, StateSetKey& out_key)
|
||||
{
|
||||
out_key.clear(); // just in case
|
||||
out_key.clear(); // just in case
|
||||
for (IntSet::const_iterator i = states.begin(); i != states.end(); ++i)
|
||||
out_key.push_back(*i);
|
||||
// Sort the ids so we make sure the vector is unique for each set
|
||||
@@ -266,7 +279,7 @@ void keyFromStateSet(const IntSet &states, StateSetKey &out_key)
|
||||
|
||||
|
||||
int
|
||||
DfAutomata::State::getTransition(ustring symbol)const
|
||||
DfAutomata::State::getTransition(ustring symbol) const
|
||||
{
|
||||
SymbolToInt::const_iterator i = m_symbol_trans.find(symbol);
|
||||
if (i == m_symbol_trans.end())
|
||||
@@ -281,20 +294,23 @@ DfAutomata::State::getTransition(ustring symbol)const
|
||||
|
||||
|
||||
void
|
||||
DfAutomata::State::addTransition(ustring symbol, DfAutomata::State *state)
|
||||
DfAutomata::State::addTransition(ustring symbol, DfAutomata::State* state)
|
||||
{
|
||||
SymbolToInt::value_type value(symbol, state->m_id);
|
||||
std::pair<SymbolToInt::iterator, bool> place = m_symbol_trans.insert(value);
|
||||
if (!place.second)
|
||||
std::cerr << "[pathexp] overwriting a transition in a DF automata" << std::endl;
|
||||
std::cerr << "[pathexp] overwriting a transition in a DF automata"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
DfAutomata::State::addWildcardTransition(Wildcard *wildcard, DfAutomata::State *state)
|
||||
DfAutomata::State::addWildcardTransition(Wildcard* wildcard,
|
||||
DfAutomata::State* state)
|
||||
{
|
||||
for (SymbolSet::const_iterator i = wildcard->m_minus.begin(); i != wildcard->m_minus.end(); ++i)
|
||||
for (SymbolSet::const_iterator i = wildcard->m_minus.begin();
|
||||
i != wildcard->m_minus.end(); ++i)
|
||||
// optimized storage, if it is not already in the transition table, tag it with -1
|
||||
if (m_symbol_trans.find(*i) == m_symbol_trans.end())
|
||||
m_symbol_trans[*i] = -1;
|
||||
@@ -309,7 +325,8 @@ DfAutomata::State::removeUselessTransitions()
|
||||
{
|
||||
if (m_wildcard_trans >= 0) {
|
||||
std::list<SymbolToInt::iterator> toremove;
|
||||
for (SymbolToInt::iterator i = m_symbol_trans.begin(); i != m_symbol_trans.end(); ++i)
|
||||
for (SymbolToInt::iterator i = m_symbol_trans.begin();
|
||||
i != m_symbol_trans.end(); ++i)
|
||||
// If there is a transition to the same state as the wildcard, we better nuke it
|
||||
// and just add that symbol to the wildcard be removing it from the map itself
|
||||
if (i->second == m_wildcard_trans)
|
||||
@@ -322,13 +339,14 @@ DfAutomata::State::removeUselessTransitions()
|
||||
|
||||
|
||||
std::string
|
||||
DfAutomata::State::tostr()const
|
||||
DfAutomata::State::tostr() const
|
||||
{
|
||||
std::string s = "";
|
||||
// normal transitions
|
||||
for (SymbolToInt::const_iterator i = m_symbol_trans.begin(); i != m_symbol_trans.end(); ++i) {
|
||||
for (SymbolToInt::const_iterator i = m_symbol_trans.begin();
|
||||
i != m_symbol_trans.end(); ++i) {
|
||||
ustring sym = i->first;
|
||||
int dest = i->second;
|
||||
int dest = i->second;
|
||||
if (s.size())
|
||||
s += " ";
|
||||
if (sym == lambda)
|
||||
@@ -336,7 +354,7 @@ DfAutomata::State::tostr()const
|
||||
else
|
||||
s += sym.c_str();
|
||||
s += ":";
|
||||
s += Strutil::sprintf("%d", dest);
|
||||
s += Strutil::to_string(dest);
|
||||
}
|
||||
// wildcard
|
||||
if (m_wildcard_trans >= 0) {
|
||||
@@ -346,7 +364,8 @@ DfAutomata::State::tostr()const
|
||||
s += ".:";
|
||||
else {
|
||||
s += "[^";
|
||||
for (SymbolToInt::const_iterator i = m_symbol_trans.begin(); i != m_symbol_trans.end(); ++i) {
|
||||
for (SymbolToInt::const_iterator i = m_symbol_trans.begin();
|
||||
i != m_symbol_trans.end(); ++i) {
|
||||
if (!i->first.c_str())
|
||||
s += "_";
|
||||
else
|
||||
@@ -354,15 +373,16 @@ DfAutomata::State::tostr()const
|
||||
}
|
||||
s += "}:";
|
||||
}
|
||||
s += Strutil::sprintf("%d", m_wildcard_trans);
|
||||
s += Strutil::to_string(m_wildcard_trans);
|
||||
}
|
||||
// and the rules
|
||||
if (m_rules.size()) {
|
||||
s += " | [";
|
||||
for (RuleSet::const_iterator i = m_rules.begin(); i != m_rules.end(); ++i) {
|
||||
if (s[s.size()-1] != '[')
|
||||
for (RuleSet::const_iterator i = m_rules.begin(); i != m_rules.end();
|
||||
++i) {
|
||||
if (s[s.size() - 1] != '[')
|
||||
s += ", ";
|
||||
s += Strutil::sprintf("%lx", (long unsigned int)*i);
|
||||
s += Strutil::fmt::format("{:p}", *i);
|
||||
}
|
||||
s += "]";
|
||||
}
|
||||
@@ -371,7 +391,7 @@ DfAutomata::State::tostr()const
|
||||
|
||||
|
||||
|
||||
DfAutomata::State *
|
||||
DfAutomata::State*
|
||||
DfAutomata::newState()
|
||||
{
|
||||
m_states.push_back(new State(m_states.size()));
|
||||
@@ -381,7 +401,7 @@ DfAutomata::newState()
|
||||
|
||||
|
||||
std::string
|
||||
DfAutomata::tostr()const
|
||||
DfAutomata::tostr() const
|
||||
{
|
||||
std::string s;
|
||||
for (size_t i = 0; i < m_states.size(); ++i) {
|
||||
@@ -395,26 +415,40 @@ DfAutomata::tostr()const
|
||||
|
||||
|
||||
bool
|
||||
DfAutomata::equivalent(const State *dfstateA, const State *dfstateB)
|
||||
DfAutomata::equivalent(const State* dfstateA, const State* dfstateB)
|
||||
{
|
||||
// early exit if the size of the tables is different
|
||||
if (dfstateA->m_symbol_trans.size() != dfstateB->m_symbol_trans.size())
|
||||
return false;
|
||||
// The pointed state by both transitions have to be the same or any of dfstateA and dfstateB
|
||||
int destA = (dfstateA->m_wildcard_trans == dfstateA->getId() || dfstateA->m_wildcard_trans == dfstateB->getId()) ? -2 : dfstateA->m_wildcard_trans;
|
||||
int destB = (dfstateB->m_wildcard_trans == dfstateA->getId() || dfstateB->m_wildcard_trans == dfstateB->getId()) ? -2 : dfstateB->m_wildcard_trans;
|
||||
int destA = (dfstateA->m_wildcard_trans == dfstateA->getId()
|
||||
|| dfstateA->m_wildcard_trans == dfstateB->getId())
|
||||
? -2
|
||||
: dfstateA->m_wildcard_trans;
|
||||
int destB = (dfstateB->m_wildcard_trans == dfstateA->getId()
|
||||
|| dfstateB->m_wildcard_trans == dfstateB->getId())
|
||||
? -2
|
||||
: dfstateB->m_wildcard_trans;
|
||||
if (destA != destB)
|
||||
return false;
|
||||
// Rules have to be the same
|
||||
if (dfstateA->m_rules != dfstateB->m_rules)
|
||||
return false;
|
||||
for (SymbolToInt::const_iterator i = dfstateA->m_symbol_trans.begin(); i != dfstateA->m_symbol_trans.end(); ++i) {
|
||||
SymbolToInt::const_iterator other = dfstateB->m_symbol_trans.find(i->first);
|
||||
for (SymbolToInt::const_iterator i = dfstateA->m_symbol_trans.begin();
|
||||
i != dfstateA->m_symbol_trans.end(); ++i) {
|
||||
SymbolToInt::const_iterator other = dfstateB->m_symbol_trans.find(
|
||||
i->first);
|
||||
if (other == dfstateB->m_symbol_trans.end())
|
||||
return false;
|
||||
// The pointed state by both transitions have to be the same or any of dfstateA and dfstateB
|
||||
int destA = (i->second == dfstateA->getId() || i->second == dfstateB->getId()) ? -2 : i->second;
|
||||
int destB = (other->second == dfstateA->getId() || other->second == dfstateB->getId()) ? -2 : other->second;
|
||||
int destA = (i->second == dfstateA->getId()
|
||||
|| i->second == dfstateB->getId())
|
||||
? -2
|
||||
: i->second;
|
||||
int destB = (other->second == dfstateA->getId()
|
||||
|| other->second == dfstateB->getId())
|
||||
? -2
|
||||
: other->second;
|
||||
// when they are -1 is because they are in the wildcard black list, anyway they have to match so ...
|
||||
if (destA != destB)
|
||||
return false;
|
||||
@@ -428,13 +462,13 @@ DfAutomata::equivalent(const State *dfstateA, const State *dfstateB)
|
||||
void
|
||||
DfAutomata::removeEquivalentStates()
|
||||
{
|
||||
std::vector<State *> newstatelist;
|
||||
std::vector<State*> newstatelist;
|
||||
HashIntInt newfromold;
|
||||
|
||||
// First go through all states and delete all those
|
||||
// that are equivalent with a previous one
|
||||
for (size_t i = 0; i < m_states.size(); ++i) {
|
||||
if (!m_states[i]) // it has already been removed
|
||||
if (!m_states[i]) // it has already been removed
|
||||
continue;
|
||||
// create a new state id from newstatelist.size()
|
||||
// move the pointer there and register the translation
|
||||
@@ -452,24 +486,30 @@ DfAutomata::removeEquivalentStates()
|
||||
// Everything has been moved now, but we still have to fix the
|
||||
// transitions so they point to the right states!
|
||||
for (size_t i = 0; i < newstatelist.size(); ++i) {
|
||||
State *state = newstatelist[i];
|
||||
for (SymbolToInt::iterator j = state->m_symbol_trans.begin(); j != state->m_symbol_trans.end(); ++j) {
|
||||
if (j->second != -1) { // if it is -1 it is just in the wildcards black list
|
||||
State* state = newstatelist[i];
|
||||
for (SymbolToInt::iterator j = state->m_symbol_trans.begin();
|
||||
j != state->m_symbol_trans.end(); ++j) {
|
||||
if (j->second
|
||||
!= -1) { // if it is -1 it is just in the wildcards black list
|
||||
// Get the new state that maps to the oldstate pointed by the transition
|
||||
HashIntInt::const_iterator trans = newfromold.find(j->second);
|
||||
if (trans != newfromold.end())
|
||||
j->second = trans->second;
|
||||
else
|
||||
std::cerr << "[pathexp] broken translation list between states" << std::endl;
|
||||
std::cerr
|
||||
<< "[pathexp] broken translation list between states"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
// Do the same with the wildcard
|
||||
if (state->m_wildcard_trans >=0) {
|
||||
HashIntInt::const_iterator trans = newfromold.find(state->m_wildcard_trans);
|
||||
if (state->m_wildcard_trans >= 0) {
|
||||
HashIntInt::const_iterator trans = newfromold.find(
|
||||
state->m_wildcard_trans);
|
||||
if (trans != newfromold.end())
|
||||
state->m_wildcard_trans = trans->second;
|
||||
else
|
||||
std::cerr << "[pathexp] broken translation list between states" << std::endl;
|
||||
std::cerr << "[pathexp] broken translation list between states"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
// switch to the new hopefully reduced state vector
|
||||
@@ -504,8 +544,9 @@ DfAutomata::~DfAutomata()
|
||||
|
||||
|
||||
|
||||
DfAutomata::State *
|
||||
StateSetRecord::ensureState(const IntSet &newstates, std::list<StateSetRecord::Discovery> &discovered)
|
||||
DfAutomata::State*
|
||||
StateSetRecord::ensureState(const IntSet& newstates,
|
||||
std::list<StateSetRecord::Discovery>& discovered)
|
||||
{
|
||||
// create the key
|
||||
StateSetKey newkey;
|
||||
@@ -516,7 +557,7 @@ StateSetRecord::ensureState(const IntSet &newstates, std::list<StateSetRecord::D
|
||||
return i->second;
|
||||
else {
|
||||
// if not in our records create a new DF state
|
||||
DfAutomata::State *tstate = m_dfautomata.newState();
|
||||
DfAutomata::State* tstate = m_dfautomata.newState();
|
||||
getRulesFromSet(tstate, m_ndfautomata, newstates);
|
||||
m_key_to_dfstate[newkey] = tstate;
|
||||
// Add the discovery to the list so it will be explored
|
||||
@@ -528,10 +569,13 @@ StateSetRecord::ensureState(const IntSet &newstates, std::list<StateSetRecord::D
|
||||
|
||||
|
||||
void
|
||||
StateSetRecord::getRulesFromSet(DfAutomata::State *dfstate, const NdfAutomata &ndfautomata, const IntSet &ndfstates)
|
||||
StateSetRecord::getRulesFromSet(DfAutomata::State* dfstate,
|
||||
const NdfAutomata& ndfautomata,
|
||||
const IntSet& ndfstates)
|
||||
{
|
||||
for (IntSet::const_iterator i = ndfstates.begin(); i != ndfstates.end(); ++i) {
|
||||
const NdfAutomata::State *ndfstate = ndfautomata.getState(*i);
|
||||
for (IntSet::const_iterator i = ndfstates.begin(); i != ndfstates.end();
|
||||
++i) {
|
||||
const NdfAutomata::State* ndfstate = ndfautomata.getState(*i);
|
||||
if (ndfstate->getRule())
|
||||
dfstate->addRule(ndfstate->getRule());
|
||||
}
|
||||
@@ -540,7 +584,7 @@ StateSetRecord::getRulesFromSet(DfAutomata::State *dfstate, const NdfAutomata &n
|
||||
|
||||
|
||||
void
|
||||
ndfautoToDfauto(const NdfAutomata &ndfautomata, DfAutomata &dfautomata)
|
||||
ndfautoToDfauto(const NdfAutomata& ndfautomata, DfAutomata& dfautomata)
|
||||
{
|
||||
std::list<StateSetRecord::Discovery> toexplore, discovered;
|
||||
// our initial state is the lambda closure
|
||||
@@ -561,14 +605,16 @@ ndfautoToDfauto(const NdfAutomata &ndfautomata, DfAutomata &dfautomata)
|
||||
// a wildcard movement that is guaranteed to match all
|
||||
// the wildcard transitions in the set (if any)
|
||||
SymbolSet symbols;
|
||||
Wildcard *wildcard = NULL;
|
||||
Wildcard* wildcard = NULL;
|
||||
ndfautomata.symbolsFrom(i.second, symbols, wildcard);
|
||||
for (SymbolSet::iterator j = symbols.begin(); j != symbols.end(); ++j) {
|
||||
for (SymbolSet::iterator j = symbols.begin(); j != symbols.end();
|
||||
++j) {
|
||||
IntSet newstates;
|
||||
// get all the states reachable with this symbol
|
||||
ndfautomata.transitionsFrom(i.second, *j, newstates);
|
||||
// build or recover the associated DF state
|
||||
DfAutomata::State *next_state = record.ensureState(newstates, discovered);
|
||||
DfAutomata::State* next_state = record.ensureState(newstates,
|
||||
discovered);
|
||||
// and store a transition
|
||||
i.first->addTransition(*j, next_state);
|
||||
}
|
||||
@@ -577,7 +623,8 @@ ndfautoToDfauto(const NdfAutomata &ndfautomata, DfAutomata &dfautomata)
|
||||
// we know they all match whatever ours match
|
||||
ndfautomata.wildcardTransitionsFrom(i.second, newstates);
|
||||
// build or recover the associated DF state
|
||||
DfAutomata::State *next_state = record.ensureState(newstates, discovered);
|
||||
DfAutomata::State* next_state = record.ensureState(newstates,
|
||||
discovered);
|
||||
// and store a transition
|
||||
i.first->addWildcardTransition(wildcard, next_state);
|
||||
}
|
||||
@@ -593,7 +640,9 @@ ndfautoToDfauto(const NdfAutomata &ndfautomata, DfAutomata &dfautomata)
|
||||
|
||||
|
||||
bool
|
||||
DfOptimizedAutomata::Transition::trans_comp (const DfOptimizedAutomata::Transition &a, const DfOptimizedAutomata::Transition &b)
|
||||
DfOptimizedAutomata::Transition::trans_comp(
|
||||
const DfOptimizedAutomata::Transition& a,
|
||||
const DfOptimizedAutomata::Transition& b)
|
||||
{
|
||||
return a.symbol.data() < b.symbol.data();
|
||||
}
|
||||
@@ -601,7 +650,7 @@ DfOptimizedAutomata::Transition::trans_comp (const DfOptimizedAutomata::Transiti
|
||||
|
||||
|
||||
void
|
||||
DfOptimizedAutomata::compileFrom(const DfAutomata &dfautomata)
|
||||
DfOptimizedAutomata::compileFrom(const DfAutomata& dfautomata)
|
||||
{
|
||||
m_states.resize(dfautomata.m_states.size());
|
||||
size_t totaltrans = 0;
|
||||
@@ -617,18 +666,22 @@ DfOptimizedAutomata::compileFrom(const DfAutomata &dfautomata)
|
||||
for (size_t s = 0; s < m_states.size(); ++s) {
|
||||
m_states[s].begin_trans = trans_offset;
|
||||
m_states[s].begin_rules = rules_offset;
|
||||
for (SymbolToInt::const_iterator i = dfautomata.m_states[s]->m_symbol_trans.begin();
|
||||
i != dfautomata.m_states[s]->m_symbol_trans.end(); ++i, ++trans_offset) {
|
||||
for (SymbolToInt::const_iterator i
|
||||
= dfautomata.m_states[s]->m_symbol_trans.begin();
|
||||
i != dfautomata.m_states[s]->m_symbol_trans.end();
|
||||
++i, ++trans_offset) {
|
||||
m_trans[trans_offset].symbol = i->first;
|
||||
m_trans[trans_offset].state = i->second;
|
||||
m_trans[trans_offset].state = i->second;
|
||||
}
|
||||
for (RuleSet::const_iterator i = dfautomata.m_states[s]->m_rules.begin();
|
||||
i != dfautomata.m_states[s]->m_rules.end(); ++i, ++rules_offset)
|
||||
i != dfautomata.m_states[s]->m_rules.end(); ++i, ++rules_offset)
|
||||
m_rules[rules_offset] = *i;
|
||||
m_states[s].ntrans = dfautomata.m_states[s]->m_symbol_trans.size();
|
||||
m_states[s].nrules = dfautomata.m_states[s]->m_rules.size();
|
||||
std::sort(m_trans.begin() + m_states[s].begin_trans, m_trans.begin() + m_states[s].begin_trans + m_states[s].ntrans,
|
||||
DfOptimizedAutomata::Transition::trans_comp);
|
||||
std::sort(m_trans.begin() + m_states[s].begin_trans,
|
||||
m_trans.begin() + m_states[s].begin_trans
|
||||
+ m_states[s].ntrans,
|
||||
DfOptimizedAutomata::Transition::trans_comp);
|
||||
m_states[s].wildcard_trans = dfautomata.m_states[s]->m_wildcard_trans;
|
||||
}
|
||||
}
|
||||
|
||||
+202
-198
@@ -4,12 +4,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
@@ -20,20 +20,21 @@ OSL_NAMESPACE_ENTER
|
||||
// General container for all symbol sets
|
||||
|
||||
// General container for integer sets
|
||||
typedef std::set<int> IntSet; // probably faster to test for equality, unions and so
|
||||
typedef std::set<int>
|
||||
IntSet; // probably faster to test for equality, unions and so
|
||||
|
||||
typedef std::unordered_set<ustring, ustringHash> SymbolSet;
|
||||
typedef std::unordered_set<ustring> SymbolSet;
|
||||
// This is for the transition table used in DfAutomata::State
|
||||
typedef std::unordered_map<ustring, int, ustringHash> SymbolToInt;
|
||||
typedef std::unordered_map<ustring, int> SymbolToInt;
|
||||
// And this is for the transition table in NdfAutomata which
|
||||
// has several movements for each symbol
|
||||
typedef std::unordered_map<ustring, IntSet, ustringHash> SymbolToIntList;
|
||||
typedef std::unordered_map<ustring, IntSet> SymbolToIntList;
|
||||
typedef std::unordered_map<int, int> HashIntInt;
|
||||
|
||||
// For the rules in the deterministic states, we don't need a real set
|
||||
// cause when converting from the NDF automata we will never find the same
|
||||
// rule twice
|
||||
typedef std::vector<void *> RuleSet;
|
||||
typedef std::vector<void*> RuleSet;
|
||||
|
||||
// The lambda symbol (empty word)
|
||||
extern ustring lambda;
|
||||
@@ -45,9 +46,9 @@ extern ustring lambda;
|
||||
/// any symbol which is not listed in its black list (m_minus).
|
||||
struct Wildcard {
|
||||
Wildcard() {};
|
||||
Wildcard(SymbolSet &minus):m_minus(minus) {};
|
||||
Wildcard(SymbolSet& minus) : m_minus(minus) {};
|
||||
|
||||
bool matches(ustring symbol)const
|
||||
bool matches(ustring symbol) const
|
||||
{
|
||||
// true if the given symbol is not in m_minus
|
||||
return (m_minus.find(symbol) == m_minus.end());
|
||||
@@ -63,109 +64,110 @@ struct Wildcard {
|
||||
/// symbol and allowed lambda transitions too. Light path expressions
|
||||
/// build this automata easily. It is later converted to a DF automata.
|
||||
class NdfAutomata {
|
||||
public:
|
||||
// Basic state for NDF automata
|
||||
class State {
|
||||
friend class NdfAutomata;
|
||||
|
||||
public:
|
||||
|
||||
// Basic state for NDF automata
|
||||
class State {
|
||||
friend class NdfAutomata;
|
||||
public:
|
||||
|
||||
State(int id)
|
||||
{
|
||||
m_id = id;
|
||||
m_wildcard_trans = -1;
|
||||
m_wildcard = NULL;
|
||||
m_rule = NULL;
|
||||
};
|
||||
~State() { delete m_wildcard; };
|
||||
|
||||
/// Get the set of state id's reachable by the given symbol
|
||||
///
|
||||
/// It doesn't clean the given result set, so you can use this
|
||||
/// function to accumulate states.
|
||||
void getTransitions (ustring symbol, IntSet &out_states)const;
|
||||
|
||||
/// Get all the lambda transitions
|
||||
///
|
||||
/// Returns the state collection as a pair of iterators [begin, end)
|
||||
std::pair <IntSet::const_iterator, IntSet::const_iterator>
|
||||
getLambdaTransitions ()const;
|
||||
|
||||
/// Add a standar transition (also valid for lambda)
|
||||
void addTransition (ustring symbol, State *state);
|
||||
/// Add a wildcard transition
|
||||
///
|
||||
/// Note that the state is going to take ownership of the wildcard
|
||||
/// pointer. So it should be newly allocated on heap and you don't
|
||||
/// have to delete ir
|
||||
void addWildcardTransition(Wildcard *wildcard, State *state);
|
||||
|
||||
/// For final states, this sets the associated rule. Which
|
||||
/// can be any kind of pointer
|
||||
void setRule(void *rule) { m_rule = rule; };
|
||||
|
||||
void *getRule()const { return m_rule; };
|
||||
int getId()const { return m_id; };
|
||||
|
||||
/// For debuging purposes
|
||||
std::string tostr()const;
|
||||
|
||||
protected:
|
||||
|
||||
// State id (i.e index in the states vector)
|
||||
int m_id;
|
||||
// Transitions by single symbols
|
||||
SymbolToIntList m_symbol_trans;
|
||||
// In case m_wildcard is not NULL this holds the destination
|
||||
// of the wildcard transition
|
||||
int m_wildcard_trans;
|
||||
// Wildcard (NULL if no wildcard transition present)
|
||||
Wildcard *m_wildcard;
|
||||
// Associated rule for final states, NULL if not final
|
||||
void *m_rule;
|
||||
State(int id)
|
||||
{
|
||||
m_id = id;
|
||||
m_wildcard_trans = -1;
|
||||
m_wildcard = NULL;
|
||||
m_rule = NULL;
|
||||
};
|
||||
~State() { delete m_wildcard; };
|
||||
|
||||
|
||||
|
||||
NdfAutomata() { newState(); };
|
||||
~NdfAutomata();
|
||||
|
||||
const State *getInitial()const { return m_states[0]; };
|
||||
State *getInitial() { return m_states[0]; };
|
||||
|
||||
/// Creates a new state qith a valid id
|
||||
State *newState();
|
||||
|
||||
const State *getState(int i)const { return m_states[i]; };
|
||||
size_t size()const { return m_states.size(); };
|
||||
|
||||
/// return all the symbols that lead to other states starting
|
||||
/// in any of the states in the given set. Also if there are
|
||||
/// wildcard transitions, give back a new wildcard that guarantees
|
||||
/// that its matches match all the wildcards in the set.
|
||||
/// So the symbols returned in out_symbols do NOT overlap those that
|
||||
/// match the returned wildcard (if present). And the union of out_symbols
|
||||
/// and those matched by the wildcard, are all the valid transitions from
|
||||
/// the given state set
|
||||
void symbolsFrom(const IntSet &states, SymbolSet &out_symbols, Wildcard *&wildcard)const;
|
||||
|
||||
/// Get the set of states that are reachable from the given state set using the given symbol
|
||||
void transitionsFrom(const IntSet &states, ustring symbol, IntSet &out_states)const;
|
||||
/// Get the set of states that are reachable from the given state set by wildcard
|
||||
void wildcardTransitionsFrom(const IntSet &states, IntSet &out_states)const;
|
||||
|
||||
/// Perform a lambda closure of a state set
|
||||
/// Get the set of state id's reachable by the given symbol
|
||||
///
|
||||
/// In other words, complete the given set so it includes all the additional
|
||||
/// states that are reachable by the lambda symbol
|
||||
void lambdaClosure(IntSet &states)const;
|
||||
/// It doesn't clean the given result set, so you can use this
|
||||
/// function to accumulate states.
|
||||
void getTransitions(ustring symbol, IntSet& out_states) const;
|
||||
|
||||
/// for debuging purposes
|
||||
std::string tostr()const;
|
||||
/// Get all the lambda transitions
|
||||
///
|
||||
/// Returns the state collection as a pair of iterators [begin, end)
|
||||
std::pair<IntSet::const_iterator, IntSet::const_iterator>
|
||||
getLambdaTransitions() const;
|
||||
|
||||
/// Add a standard transition (also valid for lambda)
|
||||
void addTransition(ustring symbol, State* state);
|
||||
/// Add a wildcard transition
|
||||
///
|
||||
/// Note that the state is going to take ownership of the wildcard
|
||||
/// pointer. So it should be newly allocated on heap and you don't
|
||||
/// have to delete ir
|
||||
void addWildcardTransition(Wildcard* wildcard, State* state);
|
||||
|
||||
/// For final states, this sets the associated rule. Which
|
||||
/// can be any kind of pointer
|
||||
void setRule(void* rule) { m_rule = rule; };
|
||||
|
||||
void* getRule() const { return m_rule; };
|
||||
int getId() const { return m_id; };
|
||||
|
||||
/// For debugging purposes
|
||||
std::string tostr() const;
|
||||
|
||||
protected:
|
||||
/// Vector of states
|
||||
std::vector<State *> m_states;
|
||||
// State id (i.e index in the states vector)
|
||||
int m_id;
|
||||
// Transitions by single symbols
|
||||
SymbolToIntList m_symbol_trans;
|
||||
// In case m_wildcard is not NULL this holds the destination
|
||||
// of the wildcard transition
|
||||
int m_wildcard_trans;
|
||||
// Wildcard (NULL if no wildcard transition present)
|
||||
Wildcard* m_wildcard;
|
||||
// Associated rule for final states, NULL if not final
|
||||
void* m_rule;
|
||||
};
|
||||
|
||||
|
||||
|
||||
NdfAutomata() { newState(); };
|
||||
~NdfAutomata();
|
||||
|
||||
const State* getInitial() const { return m_states[0]; };
|
||||
State* getInitial() { return m_states[0]; };
|
||||
|
||||
/// Creates a new state with a valid id
|
||||
State* newState();
|
||||
|
||||
const State* getState(int i) const { return m_states[i]; };
|
||||
size_t size() const { return m_states.size(); };
|
||||
|
||||
/// return all the symbols that lead to other states starting
|
||||
/// in any of the states in the given set. Also if there are
|
||||
/// wildcard transitions, give back a new wildcard that guarantees
|
||||
/// that its matches match all the wildcards in the set.
|
||||
/// So the symbols returned in out_symbols do NOT overlap those that
|
||||
/// match the returned wildcard (if present). And the union of out_symbols
|
||||
/// and those matched by the wildcard, are all the valid transitions from
|
||||
/// the given state set
|
||||
void symbolsFrom(const IntSet& states, SymbolSet& out_symbols,
|
||||
Wildcard*& wildcard) const;
|
||||
|
||||
/// Get the set of states that are reachable from the given state set using the given symbol
|
||||
void transitionsFrom(const IntSet& states, ustring symbol,
|
||||
IntSet& out_states) const;
|
||||
/// Get the set of states that are reachable from the given state set by wildcard
|
||||
void wildcardTransitionsFrom(const IntSet& states,
|
||||
IntSet& out_states) const;
|
||||
|
||||
/// Perform a lambda closure of a state set
|
||||
///
|
||||
/// In other words, complete the given set so it includes all the additional
|
||||
/// states that are reachable by the lambda symbol
|
||||
void lambdaClosure(IntSet& states) const;
|
||||
|
||||
/// for debugging purposes
|
||||
std::string tostr() const;
|
||||
|
||||
protected:
|
||||
/// Vector of states
|
||||
std::vector<State*> m_states;
|
||||
};
|
||||
|
||||
|
||||
@@ -177,7 +179,8 @@ class NdfAutomata {
|
||||
typedef std::vector<int> StateSetKey;
|
||||
|
||||
// Compute the unique key for the given set of states
|
||||
void keyFromStateSet(const IntSet &states, StateSetKey &out_key);
|
||||
void
|
||||
keyFromStateSet(const IntSet& states, StateSetKey& out_key);
|
||||
|
||||
|
||||
|
||||
@@ -188,84 +191,83 @@ void keyFromStateSet(const IntSet &states, StateSetKey &out_key);
|
||||
/// time parsing of light path expressions
|
||||
class DfAutomata {
|
||||
friend class DfOptimizedAutomata;
|
||||
|
||||
public:
|
||||
/// Simple state for a deterministic automata
|
||||
class State {
|
||||
friend class DfAutomata;
|
||||
friend class DfOptimizedAutomata;
|
||||
|
||||
public:
|
||||
/// Simple state for a deterministic automata
|
||||
class State {
|
||||
friend class DfAutomata;
|
||||
friend class DfOptimizedAutomata;
|
||||
public:
|
||||
State(int id)
|
||||
{
|
||||
m_id = id;
|
||||
m_wildcard_trans = -1;
|
||||
}
|
||||
|
||||
State(int id)
|
||||
{
|
||||
m_id = id;
|
||||
m_wildcard_trans = -1;
|
||||
}
|
||||
/// Get the transition for a symbol
|
||||
//
|
||||
/// Returns -1 if no transitions with that symbol. That means the
|
||||
/// symbol is not recognized at this point of the automata
|
||||
int getTransition(ustring symbol) const;
|
||||
|
||||
/// Get the transition for a symbol
|
||||
//
|
||||
/// Returns -1 if no transitions with that symbol. That means the
|
||||
/// symbol is not recognized at this point of the automata
|
||||
int getTransition(ustring symbol)const;
|
||||
// Same semantics as in NdfAutomata::State
|
||||
void addTransition(ustring symbol, State* state);
|
||||
// WARNING: this has an optimized representation and has to be called
|
||||
// always AFTER all the normal transitions have been added
|
||||
void addWildcardTransition(Wildcard* wildcard, State* state);
|
||||
|
||||
// Same semantics as in NdfAutomata::State
|
||||
void addTransition(ustring symbol, State *state);
|
||||
// WARNING: this has an optimized representation and has to be called
|
||||
// always AFTER all the normal transitions have been added
|
||||
void addWildcardTransition(Wildcard *wildcard, State *state);
|
||||
|
||||
/// Optimize transitions
|
||||
///
|
||||
/// Sometimes the existing wildcard can be extended to wrap some of
|
||||
/// the single symbol transitions. This function performs that optimization
|
||||
void removeUselessTransitions();
|
||||
|
||||
void addRule(void *rule) { m_rules.push_back(rule); };
|
||||
const RuleSet &getRules()const { return m_rules; };
|
||||
int getId()const { return m_id; };
|
||||
std::string tostr()const;
|
||||
|
||||
protected:
|
||||
|
||||
int m_id;
|
||||
// Only one transition per symbol here
|
||||
SymbolToInt m_symbol_trans;
|
||||
int m_wildcard_trans;
|
||||
// A final state here might contain several final states
|
||||
// from the original NDF automata. Therefore, we need a list
|
||||
// of rules here
|
||||
RuleSet m_rules;
|
||||
};
|
||||
|
||||
|
||||
DfAutomata() {};
|
||||
~DfAutomata();
|
||||
|
||||
State *newState();
|
||||
const State *getState(int i)const { return m_states[i]; };
|
||||
size_t size()const { return m_states.size(); };
|
||||
// In case somebody wants to reuse the same object and recreate
|
||||
// an automata, we provide this method
|
||||
void clear();
|
||||
|
||||
/// Colapse all the equivalent states into single ones
|
||||
void removeEquivalentStates();
|
||||
/// Go through all the states and perform removeUselessTransitions
|
||||
/// method call on them
|
||||
/// Optimize transitions
|
||||
///
|
||||
/// Sometimes the existing wildcard can be extended to wrap some of
|
||||
/// the single symbol transitions. This function performs that optimization
|
||||
void removeUselessTransitions();
|
||||
|
||||
/// For debuging purposes
|
||||
std::string tostr()const;
|
||||
void addRule(void* rule) { m_rules.push_back(rule); };
|
||||
const RuleSet& getRules() const { return m_rules; };
|
||||
int getId() const { return m_id; };
|
||||
std::string tostr() const;
|
||||
|
||||
protected:
|
||||
int m_id;
|
||||
// Only one transition per symbol here
|
||||
SymbolToInt m_symbol_trans;
|
||||
int m_wildcard_trans;
|
||||
// A final state here might contain several final states
|
||||
// from the original NDF automata. Therefore, we need a list
|
||||
// of rules here
|
||||
RuleSet m_rules;
|
||||
};
|
||||
|
||||
/// Return true if two states are equivalent
|
||||
///
|
||||
/// Two states are equivalent if their transition tables lead
|
||||
/// to the same states for the same symbols
|
||||
bool equivalent(const State *dfstateA, const State *dfstateB);
|
||||
|
||||
// State vector with the automata
|
||||
std::vector<State *> m_states;
|
||||
DfAutomata() {};
|
||||
~DfAutomata();
|
||||
|
||||
State* newState();
|
||||
const State* getState(int i) const { return m_states[i]; };
|
||||
size_t size() const { return m_states.size(); };
|
||||
// In case somebody wants to reuse the same object and recreate
|
||||
// an automata, we provide this method
|
||||
void clear();
|
||||
|
||||
/// Colapse all the equivalent states into single ones
|
||||
void removeEquivalentStates();
|
||||
/// Go through all the states and perform removeUselessTransitions
|
||||
/// method call on them
|
||||
void removeUselessTransitions();
|
||||
|
||||
/// For debugging purposes
|
||||
std::string tostr() const;
|
||||
|
||||
protected:
|
||||
/// Return true if two states are equivalent
|
||||
///
|
||||
/// Two states are equivalent if their transition tables lead
|
||||
/// to the same states for the same symbols
|
||||
bool equivalent(const State* dfstateA, const State* dfstateB);
|
||||
|
||||
// State vector with the automata
|
||||
std::vector<State*> m_states;
|
||||
};
|
||||
|
||||
|
||||
@@ -274,40 +276,42 @@ class DfAutomata {
|
||||
/// of state sets that have already been found to be new states of the
|
||||
/// deterministic automata
|
||||
class StateSetRecord {
|
||||
public:
|
||||
StateSetRecord(const NdfAutomata &ndfautomata, DfAutomata &dfautomata):
|
||||
m_ndfautomata(ndfautomata), m_dfautomata(dfautomata)
|
||||
{};
|
||||
public:
|
||||
StateSetRecord(const NdfAutomata& ndfautomata, DfAutomata& dfautomata)
|
||||
: m_ndfautomata(ndfautomata), m_dfautomata(dfautomata) {};
|
||||
|
||||
// A new found state is defined by the deterministic state created
|
||||
// for it and the state(int) set in the original automata
|
||||
typedef std::pair<DfAutomata::State *, IntSet> Discovery;
|
||||
// The type that will index our new created states indexed by the set key
|
||||
typedef std::map<StateSetKey, DfAutomata::State *> StateSetMap;
|
||||
// A new found state is defined by the deterministic state created
|
||||
// for it and the state(int) set in the original automata
|
||||
typedef std::pair<DfAutomata::State*, IntSet> Discovery;
|
||||
// The type that will index our new created states indexed by the set key
|
||||
typedef std::map<StateSetKey, DfAutomata::State*> StateSetMap;
|
||||
|
||||
/// Take a state set and build a new df state (or return existing one)
|
||||
/// Also, if it was newly created, append it to the discovered list so we
|
||||
/// can iterate over it later
|
||||
DfAutomata::State *ensureState(const IntSet &newstates, std::list<Discovery> &discovered);
|
||||
/// Take a state set and build a new df state (or return existing one)
|
||||
/// Also, if it was newly created, append it to the discovered list so we
|
||||
/// can iterate over it later
|
||||
DfAutomata::State* ensureState(const IntSet& newstates,
|
||||
std::list<Discovery>& discovered);
|
||||
|
||||
private:
|
||||
private:
|
||||
/// Gather all the rules from the original automata in the given sets (if any)
|
||||
/// and put them in the dfstate rule set
|
||||
void getRulesFromSet(DfAutomata::State* dfstate,
|
||||
const NdfAutomata& ndfautomata,
|
||||
const IntSet& ndfstates);
|
||||
|
||||
/// Gather all the rules from the original automata in the given sets (if any)
|
||||
/// and put them in the dfstate rule set
|
||||
void getRulesFromSet(DfAutomata::State *dfstate, const NdfAutomata &ndfautomata, const IntSet &ndfstates);
|
||||
|
||||
const NdfAutomata &m_ndfautomata;
|
||||
DfAutomata &m_dfautomata;
|
||||
StateSetMap m_key_to_dfstate;
|
||||
const NdfAutomata& m_ndfautomata;
|
||||
DfAutomata& m_dfautomata;
|
||||
StateSetMap m_key_to_dfstate;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// NDF to DF automata convertion
|
||||
/// NDF to DF automata conversion
|
||||
///
|
||||
/// This function is the most important pice of the whole process. It takes
|
||||
/// a non-deterministic finite automata and computes an equivalent deterministic
|
||||
/// one. It is equivalente in the sense that they both recognize the same language
|
||||
void ndfautoToDfauto(const NdfAutomata &ndfautomata, DfAutomata &dfautomata);
|
||||
void
|
||||
ndfautoToDfauto(const NdfAutomata& ndfautomata, DfAutomata& dfautomata);
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
+426
-565
File diff suppressed because it is too large
Load Diff
+240
-187
@@ -4,15 +4,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "oslexec_pvt.h"
|
||||
using namespace OSL;
|
||||
using namespace OSL::pvt;
|
||||
|
||||
#include "runtimeoptimize.h"
|
||||
#include <OSL/llvm_util.h>
|
||||
#include "runtimeoptimize.h"
|
||||
|
||||
// additional includes for creating global OptiX variables
|
||||
#include "llvm/IR/Constants.h"
|
||||
@@ -22,7 +22,7 @@ using namespace OSL::pvt;
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
namespace pvt { // OSL::pvt
|
||||
namespace pvt { // OSL::pvt
|
||||
|
||||
|
||||
|
||||
@@ -30,16 +30,16 @@ namespace pvt { // OSL::pvt
|
||||
/// code to implement a shader group.
|
||||
class BackendLLVM final : public OSOProcessorBase {
|
||||
public:
|
||||
BackendLLVM (ShadingSystemImpl &shadingsys, ShaderGroup &group,
|
||||
ShadingContext *context);
|
||||
BackendLLVM(ShadingSystemImpl& shadingsys, ShaderGroup& group,
|
||||
ShadingContext* context);
|
||||
|
||||
virtual ~BackendLLVM ();
|
||||
virtual ~BackendLLVM();
|
||||
|
||||
virtual void set_inst (int layer);
|
||||
virtual void set_inst(int layer);
|
||||
|
||||
/// Create an llvm function for the whole shader group, JIT it,
|
||||
/// and store the llvm::Function* handle to it with the ShaderGroup.
|
||||
virtual void run ();
|
||||
virtual void run();
|
||||
|
||||
|
||||
/// What LLVM debug level are we at?
|
||||
@@ -47,33 +47,33 @@ public:
|
||||
|
||||
/// Set up a bunch of static things we'll need for the whole group.
|
||||
///
|
||||
void initialize_llvm_group ();
|
||||
void initialize_llvm_group();
|
||||
|
||||
int layer_remap (int origlayer) const { return m_layer_remap[origlayer]; }
|
||||
int layer_remap(int origlayer) const { return m_layer_remap[origlayer]; }
|
||||
|
||||
/// Create an llvm function for the current shader instance.
|
||||
/// This will end up being the group entry if 'groupentry' is true.
|
||||
llvm::Function* build_llvm_instance (bool groupentry);
|
||||
llvm::Function* build_llvm_instance(bool groupentry);
|
||||
|
||||
/// Create an llvm function for group initialization code.
|
||||
llvm::Function* build_llvm_init ();
|
||||
llvm::Function* build_llvm_init();
|
||||
|
||||
/// Build up LLVM IR code for the given range [begin,end) or
|
||||
/// opcodes, putting them (initially) into basic block bb (or the
|
||||
/// current basic block if bb==NULL).
|
||||
bool build_llvm_code (int beginop, int endop, llvm::BasicBlock *bb=NULL);
|
||||
bool build_llvm_code(int beginop, int endop, llvm::BasicBlock* bb = NULL);
|
||||
|
||||
typedef std::map<std::string, llvm::Value*> AllocationMap;
|
||||
|
||||
void llvm_assign_initial_value (const Symbol& sym, bool force = false);
|
||||
llvm::LLVMContext &llvm_context () const { return ll.context(); }
|
||||
AllocationMap &named_values () { return m_named_values; }
|
||||
void llvm_assign_initial_value(const Symbol& sym, bool force = false);
|
||||
llvm::LLVMContext& llvm_context() const { return ll.context(); }
|
||||
AllocationMap& named_values() { return m_named_values; }
|
||||
|
||||
/// Return an llvm::Value* corresponding to the address of the given
|
||||
/// symbol element, with derivative (0=value, 1=dx, 2=dy) and array
|
||||
/// index (NULL if it's not an array).
|
||||
llvm::Value *llvm_get_pointer (const Symbol& sym, int deriv=0,
|
||||
llvm::Value *arrayindex=NULL);
|
||||
llvm::Value* llvm_get_pointer(const Symbol& sym, int deriv = 0,
|
||||
llvm::Value* arrayindex = NULL);
|
||||
|
||||
/// Return the llvm::Value* corresponding to the given element
|
||||
/// value, with derivative (0=value, 1=dx, 2=dy), array index (NULL
|
||||
@@ -83,9 +83,9 @@ public:
|
||||
/// return the scalar -- this allows automatic casting to triples.
|
||||
/// Finally, auto-cast int<->float if requested (no conversion is
|
||||
/// performed if cast is the default of UNKNOWN).
|
||||
llvm::Value *llvm_load_value (const Symbol& sym, int deriv,
|
||||
llvm::Value *arrayindex, int component,
|
||||
TypeDesc cast=TypeDesc::UNKNOWN);
|
||||
llvm::Value* llvm_load_value(const Symbol& sym, int deriv,
|
||||
llvm::Value* arrayindex, int component,
|
||||
TypeDesc cast = TypeDesc::UNKNOWN);
|
||||
|
||||
|
||||
/// Given an llvm::Value* of a pointer (and the type of the data
|
||||
@@ -97,62 +97,71 @@ public:
|
||||
/// and it's a scalar, return the scalar -- this allows automatic
|
||||
/// casting to triples. Finally, auto-cast int<->float if requested
|
||||
/// (no conversion is performed if cast is the default of UNKNOWN).
|
||||
llvm::Value *llvm_load_value (llvm::Value *ptr, const TypeSpec &type,
|
||||
int deriv, llvm::Value *arrayindex,
|
||||
int component, TypeDesc cast=TypeDesc::UNKNOWN);
|
||||
llvm::Value* llvm_load_value(llvm::Value* ptr, const TypeSpec& type,
|
||||
int deriv, llvm::Value* arrayindex,
|
||||
int component,
|
||||
TypeDesc cast = TypeDesc::UNKNOWN,
|
||||
const std::string& llname = {});
|
||||
|
||||
/// Just like llvm_load_value, but when both the symbol and the
|
||||
/// array index are known to be constants. This can even handle
|
||||
/// pulling constant-indexed elements out of constant arrays. Use
|
||||
/// arrayindex==-1 to indicate that it's not an array dereference.
|
||||
llvm::Value *llvm_load_constant_value (const Symbol& sym,
|
||||
int arrayindex, int component,
|
||||
TypeDesc cast=TypeDesc::UNKNOWN);
|
||||
llvm::Value* llvm_load_constant_value(const Symbol& sym, int arrayindex,
|
||||
int component,
|
||||
TypeDesc cast = TypeDesc::UNKNOWN);
|
||||
|
||||
/// llvm_load_value with non-constant component designation. Does
|
||||
/// not work with arrays or do type casts!
|
||||
llvm::Value *llvm_load_component_value (const Symbol& sym, int deriv,
|
||||
llvm::Value *component);
|
||||
llvm::Value* llvm_load_component_value(const Symbol& sym, int deriv,
|
||||
llvm::Value* component);
|
||||
|
||||
/// Non-array version of llvm_load_value, with default deriv &
|
||||
/// component.
|
||||
llvm::Value *llvm_load_value (const Symbol& sym, int deriv = 0,
|
||||
int component = 0,
|
||||
TypeDesc cast=TypeDesc::UNKNOWN) {
|
||||
return (use_optix() && ! sym.typespec().is_closure() && sym.typespec().is_string())
|
||||
? llvm_load_device_string (sym, /*follow*/ true)
|
||||
: llvm_load_value (sym, deriv, NULL, component, cast);
|
||||
llvm::Value* llvm_load_value(const Symbol& sym, int deriv = 0,
|
||||
int component = 0,
|
||||
TypeDesc cast = TypeDesc::UNKNOWN)
|
||||
{
|
||||
return llvm_load_value(sym, deriv, NULL, component, cast);
|
||||
}
|
||||
|
||||
/// Load the address of a global device-side string pointer, which may
|
||||
/// reside in a global variable, the groupdata struct, or a local value.
|
||||
llvm::Value *llvm_load_device_string (const Symbol& sym, bool follow);
|
||||
|
||||
/// Convenience function to load a string for CPU or GPU device
|
||||
llvm::Value *llvm_load_string (const Symbol& sym) {
|
||||
llvm::Value* llvm_load_string(const Symbol& sym)
|
||||
{
|
||||
OSL_DASSERT(sym.typespec().is_string());
|
||||
return use_optix()
|
||||
? llvm_load_device_string(sym, /*follow*/ true)
|
||||
: llvm_load_value(sym);
|
||||
return llvm_load_value(sym);
|
||||
}
|
||||
|
||||
/// Convenience function to load a constant string for CPU or GPU device.
|
||||
/// On the GPU, we use the ustring hash, not the character pointer.
|
||||
llvm::Value* llvm_load_string(ustring str) { return ll.constant(str); }
|
||||
|
||||
llvm::Value* llvm_load_string(string_view str)
|
||||
{
|
||||
return llvm_load_string(ustring(str));
|
||||
}
|
||||
|
||||
/// Legacy version
|
||||
///
|
||||
llvm::Value *loadLLVMValue (const Symbol& sym, int component=0,
|
||||
int deriv=0, TypeDesc cast=TypeDesc::UNKNOWN) {
|
||||
return llvm_load_value (sym, deriv, NULL, component, cast);
|
||||
llvm::Value* loadLLVMValue(const Symbol& sym, int component = 0,
|
||||
int deriv = 0, TypeDesc cast = TypeDesc::UNKNOWN)
|
||||
{
|
||||
return llvm_load_value(sym, deriv, NULL, component, cast);
|
||||
}
|
||||
|
||||
/// Return an llvm::Value* that is either a scalar and derivs is
|
||||
/// false, or a pointer to sym's values (if sym is an aggregate or
|
||||
/// derivs == true). Furthermore, if deriv == true and sym doesn't
|
||||
/// have derivs, coerce it into a variable with zero derivs.
|
||||
llvm::Value *llvm_load_arg (const Symbol& sym, bool derivs);
|
||||
/// Return an llvm::Value* in the form that we will pass a float-based
|
||||
/// symbol as a function argument to any "built-in" OSL function -- as a
|
||||
/// simple value if the symbol is a scalar and no derivs are needed, or as
|
||||
/// a pointer to the data in all other cases (aggregates, arrays, or
|
||||
/// derivs needed). If deriv == true and sym doesn't have derivs, coerce
|
||||
/// it into a variable having derivatives set to 0.0.
|
||||
llvm::Value* llvm_load_arg(const Symbol& sym, bool derivs);
|
||||
|
||||
/// Just like llvm_load_arg(sym,deriv), except use use sym's derivs
|
||||
/// as-is, no coercion.
|
||||
llvm::Value *llvm_load_arg (const Symbol& sym) {
|
||||
return llvm_load_arg (sym, sym.has_derivs());
|
||||
llvm::Value* llvm_load_arg(const Symbol& sym)
|
||||
{
|
||||
return llvm_load_arg(sym, sym.has_derivs());
|
||||
}
|
||||
|
||||
/// Store new_val into the given symbol, given the derivative
|
||||
@@ -161,8 +170,8 @@ public:
|
||||
/// symbol doesn't have a deriv, it's a nop. If the component >0
|
||||
/// and it's a scalar, set the scalar. Returns true if ok, false
|
||||
/// upon failure.
|
||||
bool llvm_store_value (llvm::Value *new_val, const Symbol& sym, int deriv,
|
||||
llvm::Value *arrayindex, int component);
|
||||
bool llvm_store_value(llvm::Value* new_val, const Symbol& sym, int deriv,
|
||||
llvm::Value* arrayindex, int component);
|
||||
|
||||
/// Store new_val into the memory pointed to by dst_ptr, given the
|
||||
/// derivative (0=value, 1=dx, 2=dy), array index (NULL if it's not
|
||||
@@ -170,150 +179,160 @@ public:
|
||||
/// and the symbol doesn't have a deriv, it's a nop. If the
|
||||
/// component >0 and it's a scalar, set the scalar. Returns true if
|
||||
/// ok, false upon failure.
|
||||
bool llvm_store_value (llvm::Value* new_val, llvm::Value* dst_ptr,
|
||||
const TypeSpec &type, int deriv,
|
||||
llvm::Value* arrayindex, int component);
|
||||
bool llvm_store_value(llvm::Value* new_val, llvm::Value* dst_ptr,
|
||||
const TypeSpec& type, int deriv,
|
||||
llvm::Value* arrayindex, int component);
|
||||
|
||||
/// Non-array version of llvm_store_value, with default deriv &
|
||||
/// component.
|
||||
bool llvm_store_value (llvm::Value *new_val, const Symbol& sym,
|
||||
int deriv=0, int component=0) {
|
||||
return llvm_store_value (new_val, sym, deriv, NULL, component);
|
||||
bool llvm_store_value(llvm::Value* new_val, const Symbol& sym,
|
||||
int deriv = 0, int component = 0)
|
||||
{
|
||||
return llvm_store_value(new_val, sym, deriv, NULL, component);
|
||||
}
|
||||
|
||||
/// llvm_store_value with non-constant component designation. Does
|
||||
/// not work with arrays or do type casts!
|
||||
bool llvm_store_component_value (llvm::Value *new_val, const Symbol& sym,
|
||||
int deriv, llvm::Value *component);
|
||||
bool llvm_store_component_value(llvm::Value* new_val, const Symbol& sym,
|
||||
int deriv, llvm::Value* component);
|
||||
|
||||
/// Legacy version
|
||||
///
|
||||
bool storeLLVMValue (llvm::Value* new_val, const Symbol& sym,
|
||||
int component=0, int deriv=0) {
|
||||
return llvm_store_value (new_val, sym, deriv, component);
|
||||
bool storeLLVMValue(llvm::Value* new_val, const Symbol& sym,
|
||||
int component = 0, int deriv = 0)
|
||||
{
|
||||
return llvm_store_value(new_val, sym, deriv, component);
|
||||
}
|
||||
|
||||
/// Generate an alloca instruction to allocate space for the given
|
||||
/// type, with derivs if derivs==true, and return the its pointer.
|
||||
llvm::Value *llvm_alloca (const TypeSpec &type, bool derivs,
|
||||
const std::string &name="", int align=0);
|
||||
llvm::Value* llvm_alloca(const TypeSpec& type, bool derivs,
|
||||
const std::string& name = "", int align = 0);
|
||||
|
||||
/// Given the OSL symbol, return the llvm::Value* corresponding to the
|
||||
/// address of the start of that symbol (first element, first component,
|
||||
/// and just the plain value if it has derivatives). This is retrieved
|
||||
/// from the allocation map if already there; and if not yet in the
|
||||
/// map, the symbol is alloca'd and placed in the map.
|
||||
llvm::Value *getOrAllocateLLVMSymbol (const Symbol& sym);
|
||||
llvm::Value* getOrAllocateLLVMSymbol(const Symbol& sym);
|
||||
|
||||
/// Allocate a CUDA variable for the given OSL symbol and return a pointer
|
||||
/// to the corresponding LLVM GlobalVariable, or return the pointer if it
|
||||
/// has already been allocated.
|
||||
llvm::Value *getOrAllocateCUDAVariable (const Symbol& sym, bool addMetadata=false);
|
||||
llvm::Value* getOrAllocateCUDAVariable(const Symbol& sym);
|
||||
|
||||
/// Create a CUDA global variable and add it to the current Module
|
||||
llvm::Value *addCUDAVariable (const std::string& name, int size, int alignment,
|
||||
const void* data, TypeDesc type=TypeDesc::UNKNOWN);
|
||||
|
||||
/// Create the extra semantic information needed for OptiX variables
|
||||
void createOptixMetadata (const std::string& name, const Symbol& sym );
|
||||
/// Create a named CUDA global variable with the given type, size, and
|
||||
/// alignment, and add it to the current Module. It will be initialized
|
||||
/// with data pointed to by init_data. A record will be also added to
|
||||
/// m_const_map, and will be retrieved by subsequent calls to
|
||||
/// getOrAllocateCUDAVariable().
|
||||
llvm::Value* addCUDAGlobalVariable(const std::string& name, int size,
|
||||
int alignment, const void* init_data,
|
||||
TypeDesc type = TypeDesc::UNKNOWN);
|
||||
|
||||
/// Retrieve an llvm::Value that is a pointer holding the start address
|
||||
/// of the specified symbol. This always works for globals and params;
|
||||
/// for stack variables (locals/temps) is succeeds only if the symbol is
|
||||
/// already in the allocation table (will fail otherwise). This method
|
||||
/// is not designed to retrieve constants.
|
||||
llvm::Value *getLLVMSymbolBase (const Symbol &sym);
|
||||
llvm::Value* getLLVMSymbolBase(const Symbol& sym);
|
||||
|
||||
/// Retrieve the named global ("P", "N", etc.).
|
||||
llvm::Value *llvm_global_symbol_ptr (ustring name);
|
||||
llvm::Value* llvm_global_symbol_ptr(ustring name);
|
||||
|
||||
/// Test whether val is nonzero, return the llvm::Value* that's the
|
||||
/// result of a CreateICmpNE or CreateFCmpUNE (depending on the
|
||||
/// type). If test_derivs is true, it it also tests whether the
|
||||
/// derivs are zero.
|
||||
llvm::Value *llvm_test_nonzero (Symbol &val, bool test_derivs = false);
|
||||
llvm::Value* llvm_test_nonzero(Symbol& val, bool test_derivs = false);
|
||||
|
||||
/// Implementaiton of Simple assignment. If arrayindex >= 0, in
|
||||
/// Implementation of Simple assignment. If arrayindex >= 0, in
|
||||
/// designates a particular array index to assign.
|
||||
bool llvm_assign_impl (Symbol &Result, Symbol &Src, int arrayindex = -1,
|
||||
int srccomp = -1, int dstcomp = -1);
|
||||
bool llvm_assign_impl(Symbol& Result, Symbol& Src, int arrayindex = -1,
|
||||
int srccomp = -1, int dstcomp = -1);
|
||||
|
||||
|
||||
/// Convert the name of a global (and its derivative index) into the
|
||||
/// field number of the ShaderGlobals struct.
|
||||
int ShaderGlobalNameToIndex (ustring name);
|
||||
int ShaderGlobalNameToIndex(ustring name);
|
||||
|
||||
/// Return the LLVM type handle for the ShaderGlobals struct.
|
||||
///
|
||||
llvm::Type *llvm_type_sg ();
|
||||
llvm::Type* llvm_type_sg();
|
||||
|
||||
/// Return the LLVM type handle for a pointer to a
|
||||
/// ShaderGlobals struct.
|
||||
llvm::Type *llvm_type_sg_ptr ();
|
||||
llvm::Type* llvm_type_sg_ptr();
|
||||
|
||||
/// Return the ShaderGlobals pointer.
|
||||
///
|
||||
llvm::Value *sg_ptr () const { return m_llvm_shaderglobals_ptr; }
|
||||
llvm::Value* sg_ptr() const { return m_llvm_shaderglobals_ptr; }
|
||||
|
||||
llvm::Type *llvm_type_closure_component ();
|
||||
llvm::Type *llvm_type_closure_component_ptr ();
|
||||
llvm::Type* llvm_type_closure_component();
|
||||
llvm::Type* llvm_type_closure_component_ptr();
|
||||
|
||||
/// Return the ShaderGlobals pointer cast as a void*.
|
||||
///
|
||||
llvm::Value *sg_void_ptr () {
|
||||
return ll.void_ptr (m_llvm_shaderglobals_ptr);
|
||||
llvm::Value* sg_void_ptr() { return ll.void_ptr(m_llvm_shaderglobals_ptr); }
|
||||
|
||||
/// Cast the pointer variable specified by val to a pointer to the
|
||||
/// basic type comprising `type`.
|
||||
llvm::Value* llvm_ptr_cast(llvm::Value* val, const TypeSpec& type,
|
||||
const std::string& llname = {})
|
||||
{
|
||||
return ll.ptr_cast(val, type.simpletype(), llname);
|
||||
}
|
||||
|
||||
llvm::Value *llvm_ptr_cast (llvm::Value* val, const TypeSpec &type) {
|
||||
return ll.ptr_cast (val, type.simpletype());
|
||||
}
|
||||
|
||||
llvm::Value *llvm_void_ptr (const Symbol &sym, int deriv=0) {
|
||||
return ll.void_ptr (llvm_get_pointer(sym, deriv));
|
||||
llvm::Value* llvm_void_ptr(const Symbol& sym, int deriv = 0)
|
||||
{
|
||||
return ll.void_ptr(llvm_get_pointer(sym, deriv),
|
||||
llnamefmt("{}_voidptr", sym.mangled()));
|
||||
}
|
||||
|
||||
/// Return the LLVM type handle for a structure of the common group
|
||||
/// data that holds all the shader params.
|
||||
llvm::Type *llvm_type_groupdata ();
|
||||
llvm::Type* llvm_type_groupdata();
|
||||
|
||||
/// Return the LLVM type handle for a pointer to the common group
|
||||
/// data that holds all the shader params.
|
||||
llvm::Type *llvm_type_groupdata_ptr ();
|
||||
llvm::Type* llvm_type_groupdata_ptr();
|
||||
|
||||
/// Return the group data pointer.
|
||||
///
|
||||
llvm::Value *groupdata_ptr () const { return m_llvm_groupdata_ptr; }
|
||||
llvm::Value* groupdata_ptr() const { return m_llvm_groupdata_ptr; }
|
||||
|
||||
/// Return the group data pointer cast as a void*.
|
||||
///
|
||||
llvm::Value *groupdata_void_ptr () {
|
||||
return ll.void_ptr (m_llvm_groupdata_ptr);
|
||||
llvm::Value* groupdata_void_ptr()
|
||||
{
|
||||
return ll.void_ptr(m_llvm_groupdata_ptr);
|
||||
}
|
||||
|
||||
/// Return a reference to the specified field within the group data.
|
||||
llvm::Value *groupdata_field_ref (int fieldnum);
|
||||
llvm::Value* groupdata_field_ref(int fieldnum);
|
||||
|
||||
/// Return a pointer to the specified field within the group data,
|
||||
/// optionally cast to pointer to a particular data type.
|
||||
llvm::Value *groupdata_field_ptr (int fieldnum,
|
||||
TypeDesc type = TypeDesc::UNKNOWN);
|
||||
llvm::Value* groupdata_field_ptr(int fieldnum,
|
||||
TypeDesc type = TypeDesc::UNKNOWN);
|
||||
|
||||
/// Return the userdata base pointer.
|
||||
llvm::Value *userdata_base_ptr () const { return m_llvm_userdata_base_ptr; }
|
||||
llvm::Value* userdata_base_ptr() const { return m_llvm_userdata_base_ptr; }
|
||||
|
||||
/// Return the output base pointer.
|
||||
llvm::Value *output_base_ptr () const { return m_llvm_output_base_ptr; }
|
||||
llvm::Value* output_base_ptr() const { return m_llvm_output_base_ptr; }
|
||||
|
||||
/// Return the shade index
|
||||
llvm::Value *shadeindex () const { return m_llvm_shadeindex; }
|
||||
llvm::Value* shadeindex() const { return m_llvm_shadeindex; }
|
||||
|
||||
// For a symloc, compute the llvm::Value of the pointer to its true,
|
||||
// offset location from the base pointer for shade index `sindex`
|
||||
// (which should already be a i64, or if nullptr, then use
|
||||
// m_llvm_shadeindex and convert it to i64).
|
||||
llvm::Value *symloc_ptr(const SymLocationDesc* symloc,
|
||||
llvm::Value* symloc_ptr(const SymLocationDesc* symloc,
|
||||
llvm::Value* base_ptr,
|
||||
llvm::Value* sindex = nullptr) {
|
||||
llvm::Value* sindex = nullptr)
|
||||
{
|
||||
llvm::Value* offset = ll.constanti64(symloc->offset);
|
||||
llvm::Value* stride = ll.constanti64(symloc->stride);
|
||||
if (!sindex)
|
||||
@@ -324,47 +343,47 @@ public:
|
||||
|
||||
/// Return a ref to the bool where the "layer_run" flag is stored for
|
||||
/// the specified layer.
|
||||
llvm::Value *layer_run_ref (int layer);
|
||||
llvm::Value* layer_run_ref(int layer);
|
||||
|
||||
/// Return a ref to the bool where the "userdata_initialized" flag is
|
||||
/// stored for the specified userdata index.
|
||||
llvm::Value *userdata_initialized_ref (int userdata_index=0);
|
||||
llvm::Value* userdata_initialized_ref(int userdata_index = 0);
|
||||
|
||||
/// Generate LLVM code to zero out the variable (including derivs)
|
||||
///
|
||||
void llvm_assign_zero (const Symbol &sym);
|
||||
void llvm_assign_zero(const Symbol& sym);
|
||||
|
||||
/// Generate LLVM code to zero out the derivatives of sym.
|
||||
///
|
||||
void llvm_zero_derivs (const Symbol &sym);
|
||||
void llvm_zero_derivs(const Symbol& sym);
|
||||
|
||||
/// Generate LLVM code to zero out the derivatives of an array
|
||||
/// only for the first count elements of it.
|
||||
///
|
||||
void llvm_zero_derivs (const Symbol &sym, llvm::Value *count);
|
||||
void llvm_zero_derivs(const Symbol& sym, llvm::Value* count);
|
||||
|
||||
/// Generate a debugging printf at shader execution time.
|
||||
void llvm_gen_debug_printf (string_view message);
|
||||
void llvm_gen_debug_printf(string_view message);
|
||||
|
||||
/// Generate a warning message at shader execution time.
|
||||
void llvm_gen_warning (string_view message);
|
||||
void llvm_gen_warning(string_view message);
|
||||
|
||||
/// Generate an error message at shader execution time.
|
||||
void llvm_gen_error (string_view message);
|
||||
void llvm_gen_error(string_view message);
|
||||
|
||||
/// Generate code to call the given layer. If 'unconditional' is
|
||||
/// true, call it without even testing if the layer has already been
|
||||
/// called.
|
||||
void llvm_call_layer (int layer, bool unconditional = false);
|
||||
void llvm_call_layer(int layer, bool unconditional = false);
|
||||
|
||||
/// Execute the upstream connection (if any, and if not yet run) that
|
||||
/// establishes the value of symbol sym, which has index 'symindex'
|
||||
/// within the current layer rop.inst(). If already_run is not NULL,
|
||||
/// it points to a vector of layer indices that are known to have been
|
||||
/// it points to a vector of layer indices that are known to have been
|
||||
/// run -- those can be skipped without dynamically checking their
|
||||
/// execution status.
|
||||
void llvm_run_connected_layers (Symbol &sym, int symindex, int opnum = -1,
|
||||
std::set<int> *already_run = NULL);
|
||||
void llvm_run_connected_layers(Symbol& sym, int symindex, int opnum = -1,
|
||||
std::set<int>* already_run = NULL);
|
||||
|
||||
/// Generate code for a call to the named function with the given
|
||||
/// arg list as symbols -- float & ints will be passed by value,
|
||||
@@ -372,127 +391,161 @@ public:
|
||||
/// is true, pass pointers even for floats if they have derivs.
|
||||
/// Return an llvm::Value* corresponding to the return value of the
|
||||
/// function, if any.
|
||||
llvm::Value *llvm_call_function (const char *name, cspan<const Symbol *> args,
|
||||
bool deriv_ptrs=false);
|
||||
llvm::Value *llvm_call_function (const char *name, const Symbol &A,
|
||||
bool deriv_ptrs=false) {
|
||||
return llvm_call_function (name, { &A }, deriv_ptrs);
|
||||
llvm::Value* llvm_call_function(const char* name, cspan<const Symbol*> args,
|
||||
bool deriv_ptrs = false);
|
||||
llvm::Value* llvm_call_function(const char* name, const Symbol& A,
|
||||
bool deriv_ptrs = false)
|
||||
{
|
||||
return llvm_call_function(name, { &A }, deriv_ptrs);
|
||||
}
|
||||
llvm::Value *llvm_call_function (const char *name, const Symbol &A,
|
||||
const Symbol &B, bool deriv_ptrs=false) {
|
||||
return llvm_call_function (name, { &A, &B }, deriv_ptrs);
|
||||
llvm::Value* llvm_call_function(const char* name, const Symbol& A,
|
||||
const Symbol& B, bool deriv_ptrs = false)
|
||||
{
|
||||
return llvm_call_function(name, { &A, &B }, deriv_ptrs);
|
||||
}
|
||||
llvm::Value *llvm_call_function (const char *name, const Symbol &A,
|
||||
const Symbol &B, const Symbol &C,
|
||||
bool deriv_ptrs=false) {
|
||||
return llvm_call_function (name, { &A, &B, &C }, deriv_ptrs);
|
||||
llvm::Value* llvm_call_function(const char* name, const Symbol& A,
|
||||
const Symbol& B, const Symbol& C,
|
||||
bool deriv_ptrs = false)
|
||||
{
|
||||
return llvm_call_function(name, { &A, &B, &C }, deriv_ptrs);
|
||||
}
|
||||
|
||||
TypeDesc llvm_typedesc (const TypeSpec &typespec) {
|
||||
return typespec.is_closure_based()
|
||||
? TypeDesc(TypeDesc::PTR, typespec.arraylength())
|
||||
: typespec.simpletype();
|
||||
TypeDesc llvm_typedesc(const TypeSpec& typespec)
|
||||
{
|
||||
if (typespec.is_closure_based())
|
||||
return TypeDesc(TypeDesc::PTR, typespec.arraylength());
|
||||
else if (use_optix() && typespec.is_string_based()) {
|
||||
// On the OptiX side, we use the uint64 hash to represent a string
|
||||
return TypeDesc(TypeDesc::UINT64, typespec.arraylength());
|
||||
} else
|
||||
return typespec.simpletype();
|
||||
}
|
||||
|
||||
/// Generate the appropriate llvm type definition for a TypeSpec
|
||||
/// (this is the actual type, for example when we allocate it).
|
||||
/// Allocates ptrs for closures.
|
||||
llvm::Type *llvm_type (const TypeSpec &typespec) {
|
||||
return ll.llvm_type (llvm_typedesc(typespec));
|
||||
llvm::Type* llvm_type(const TypeSpec& typespec)
|
||||
{
|
||||
return ll.llvm_type(llvm_typedesc(typespec));
|
||||
}
|
||||
|
||||
/// Generate the parameter-passing llvm type definition for an OSL
|
||||
/// TypeSpec.
|
||||
llvm::Type *llvm_pass_type (const TypeSpec &typespec);
|
||||
llvm::Type* llvm_pass_type(const TypeSpec& typespec);
|
||||
|
||||
llvm::PointerType *llvm_type_prepare_closure_func() { return m_llvm_type_prepare_closure_func; }
|
||||
llvm::PointerType *llvm_type_setup_closure_func() { return m_llvm_type_setup_closure_func; }
|
||||
|
||||
/// Return the basic block of the exit for the whole instance.
|
||||
///
|
||||
bool llvm_has_exit_instance_block () const {
|
||||
return m_exit_instance_block;
|
||||
llvm::PointerType* llvm_type_prepare_closure_func()
|
||||
{
|
||||
return m_llvm_type_prepare_closure_func;
|
||||
}
|
||||
llvm::PointerType* llvm_type_setup_closure_func()
|
||||
{
|
||||
return m_llvm_type_setup_closure_func;
|
||||
}
|
||||
|
||||
/// Return the basic block of the exit for the whole instance.
|
||||
///
|
||||
llvm::BasicBlock *llvm_exit_instance_block () {
|
||||
if (! m_exit_instance_block) {
|
||||
std::string name = Strutil::sprintf ("%s_%d_exit_", inst()->layername(), inst()->id());
|
||||
m_exit_instance_block = ll.new_basic_block (name);
|
||||
bool llvm_has_exit_instance_block() const { return m_exit_instance_block; }
|
||||
|
||||
/// Return the basic block of the exit for the whole instance.
|
||||
///
|
||||
llvm::BasicBlock* llvm_exit_instance_block()
|
||||
{
|
||||
if (!m_exit_instance_block) {
|
||||
std::string name = llnamefmt("{}_{}_exit_", inst()->layername(),
|
||||
inst()->id());
|
||||
m_exit_instance_block = ll.new_basic_block(name);
|
||||
}
|
||||
return m_exit_instance_block;
|
||||
}
|
||||
|
||||
/// Check for inf/nan in all written-to arguments of the op
|
||||
void llvm_generate_debugnan (const Opcode &op);
|
||||
void llvm_generate_debugnan(const Opcode& op);
|
||||
/// Check for uninitialized values in all read-from arguments to the op
|
||||
void llvm_generate_debug_uninit (const Opcode &op);
|
||||
void llvm_generate_debug_uninit(const Opcode& op);
|
||||
/// Print debugging line for the op
|
||||
void llvm_generate_debug_op_printf (const Opcode &op);
|
||||
void llvm_generate_debug_op_printf(const Opcode& op);
|
||||
|
||||
llvm::Function *layer_func () const { return ll.current_function(); }
|
||||
llvm::Function* layer_func() const { return ll.current_function(); }
|
||||
|
||||
/// Call this when JITing a texture-like call, to track how many.
|
||||
void generated_texture_call (bool handle) {
|
||||
void generated_texture_call(bool handle)
|
||||
{
|
||||
shadingsys().m_stat_tex_calls_codegened += 1;
|
||||
if (handle)
|
||||
shadingsys().m_stat_tex_calls_as_handles += 1;
|
||||
}
|
||||
|
||||
/// Return the mapping from symbol names to GlobalVariables.
|
||||
std::map<std::string,llvm::GlobalVariable*>& get_const_map() { return m_const_map; }
|
||||
std::map<std::string, llvm::GlobalVariable*>& get_const_map()
|
||||
{
|
||||
return m_const_map;
|
||||
}
|
||||
|
||||
/// Return whether or not we are compiling for an OptiX-based renderer.
|
||||
bool use_optix() { return m_use_optix; }
|
||||
|
||||
/// Return if we should compile against free function versions of Renderer Service.
|
||||
bool use_rs_bitcode() { return m_use_rs_bitcode; }
|
||||
|
||||
/// Return the userdata index for the given Symbol. Return -1 if the Symbol
|
||||
/// is not an input parameter or is constant and therefore doesn't have an
|
||||
/// entry in the groupdata struct.
|
||||
int find_userdata_index (const Symbol& sym);
|
||||
int find_userdata_index(const Symbol& sym);
|
||||
|
||||
LLVM_Util ll;
|
||||
|
||||
private:
|
||||
std::vector<int> m_layer_remap; ///< Remapping of layer ordering
|
||||
std::set<int> m_layers_already_run; ///< List of layers run
|
||||
int m_num_used_layers; ///< Number of layers actually used
|
||||
// Utility for constructing names for llvm symbols. It creates a formatted
|
||||
// string if the shading system's "llvm_output_bitcode" option is set,
|
||||
// otherwise it takes a shortcut and returns an empty string (since nobody
|
||||
// is going to see the pretty bitcode anyway).
|
||||
template<typename Str, typename... Args>
|
||||
OSL_NODISCARD inline std::string llnamefmt(const Str& fmt,
|
||||
Args&&... args) const
|
||||
{
|
||||
return m_name_llvm_syms ? fmtformat(fmt, std::forward<Args>(args)...)
|
||||
: std::string();
|
||||
}
|
||||
|
||||
double m_stat_total_llvm_time; ///< total time spent on LLVM
|
||||
double m_stat_llvm_setup_time; ///< llvm setup time
|
||||
double m_stat_llvm_irgen_time; ///< llvm IR generation time
|
||||
double m_stat_llvm_opt_time; ///< llvm IR optimization time
|
||||
double m_stat_llvm_jit_time; ///< llvm JIT time
|
||||
private:
|
||||
std::vector<int> m_layer_remap; ///< Remapping of layer ordering
|
||||
std::set<int> m_layers_already_run; ///< List of layers run
|
||||
int m_num_used_layers; ///< Number of layers actually used
|
||||
|
||||
double m_stat_total_llvm_time; ///< total time spent on LLVM
|
||||
double m_stat_llvm_setup_time; ///< llvm setup time
|
||||
double m_stat_llvm_irgen_time; ///< llvm IR generation time
|
||||
double m_stat_llvm_opt_time; ///< llvm IR optimization time
|
||||
double m_stat_llvm_jit_time; ///< llvm JIT time
|
||||
|
||||
// LLVM stuff
|
||||
AllocationMap m_named_values;
|
||||
std::map<const Symbol*,int> m_param_order_map;
|
||||
llvm::Value *m_llvm_shaderglobals_ptr;
|
||||
llvm::Value *m_llvm_groupdata_ptr;
|
||||
llvm::Value *m_llvm_userdata_base_ptr;
|
||||
llvm::Value *m_llvm_output_base_ptr;
|
||||
llvm::Value *m_llvm_shadeindex;
|
||||
llvm::BasicBlock * m_exit_instance_block; // exit point for the instance
|
||||
llvm::Type *m_llvm_type_sg; // LLVM type of ShaderGlobals struct
|
||||
llvm::Type *m_llvm_type_groupdata; // LLVM type of group data
|
||||
llvm::Type *m_llvm_type_closure_component; // LLVM type for ClosureComponent
|
||||
llvm::PointerType *m_llvm_type_prepare_closure_func;
|
||||
llvm::PointerType *m_llvm_type_setup_closure_func;
|
||||
int m_llvm_local_mem; // Amount of memory we use for locals
|
||||
std::map<const Symbol*, int> m_param_order_map;
|
||||
llvm::Value* m_llvm_shaderglobals_ptr;
|
||||
llvm::Value* m_llvm_groupdata_ptr;
|
||||
llvm::Value* m_llvm_userdata_base_ptr;
|
||||
llvm::Value* m_llvm_output_base_ptr;
|
||||
llvm::Value* m_llvm_shadeindex;
|
||||
llvm::BasicBlock* m_exit_instance_block; // exit point for the instance
|
||||
llvm::Type* m_llvm_type_sg; // LLVM type of ShaderGlobals struct
|
||||
llvm::Type* m_llvm_type_groupdata; // LLVM type of group data
|
||||
llvm::Type* m_llvm_type_closure_component; // LLVM type for ClosureComponent
|
||||
llvm::PointerType* m_llvm_type_prepare_closure_func;
|
||||
llvm::PointerType* m_llvm_type_setup_closure_func;
|
||||
int m_llvm_local_mem; // Amount of memory we use for locals
|
||||
bool m_name_llvm_syms; // Whether to name LLVM symbols
|
||||
|
||||
// A mapping from symbol names to llvm::GlobalVariables
|
||||
std::map<std::string,llvm::GlobalVariable*> m_const_map;
|
||||
std::map<std::string, llvm::GlobalVariable*> m_const_map;
|
||||
|
||||
// A mapping from canonical strings to string variable names, used to
|
||||
// detect collisions that might occur due to using the string hash to
|
||||
// create variable names.
|
||||
std::map<std::string,std::string> m_varname_map;
|
||||
// Name of each indexed field in the groupdata, mostly for debugging.
|
||||
std::vector<std::string> m_groupdata_field_names;
|
||||
|
||||
bool m_use_optix; ///< Compile for OptiX?
|
||||
bool m_use_optix; ///< Compile for OptiX?
|
||||
bool m_use_rs_bitcode; /// To use free function versions of Renderer Service functions.
|
||||
|
||||
friend class ShadingSystemImpl;
|
||||
};
|
||||
|
||||
|
||||
}; // namespace pvt
|
||||
}; // namespace pvt
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
@@ -35,6 +35,7 @@ static ustring op_and("and");
|
||||
static ustring op_backfacing("backfacing");
|
||||
static ustring op_break("break");
|
||||
static ustring op_calculatenormal("calculatenormal");
|
||||
static ustring op_closure("closure");
|
||||
static ustring op_compl("compl");
|
||||
static ustring op_concat("concat");
|
||||
static ustring op_continue("continue");
|
||||
@@ -101,23 +102,25 @@ is_shader_global_uniform_by_name(ustring name);
|
||||
|
||||
namespace // Unnamed
|
||||
{
|
||||
|
||||
// Even when all inputs to an operation are uniform,
|
||||
// the results written to output symbols maybe varying.
|
||||
bool
|
||||
are_op_results_always_implicitly_varying(ustring opname)
|
||||
{
|
||||
return (opname == Strings::op_getmessage) | (opname == Strings::op_trace)
|
||||
| (opname == Strings::op_texture)
|
||||
| (opname == Strings::op_texture3d)
|
||||
| (opname == Strings::op_texture) | (opname == Strings::op_texture3d)
|
||||
| (opname == Strings::op_pointcloud_search)
|
||||
| (opname == Strings::op_pointcloud_get)
|
||||
| (opname == Strings::op_pointcloud_write);
|
||||
| (opname == Strings::op_pointcloud_write)
|
||||
| (opname == Strings::op_closure);
|
||||
// Renderer might identify result of getattribute as always uniform
|
||||
// depending on the attribute itself, so it cannot
|
||||
// be "always" implicitly varying based solely on the opname.
|
||||
// We consider getattribute during discovery.
|
||||
}
|
||||
|
||||
|
||||
// Even when all inputs to an operation are varying,
|
||||
// the results written to output symbols maybe uniform.
|
||||
bool
|
||||
@@ -166,6 +169,8 @@ does_op_implementation_require_masking(ustring opname)
|
||||
return lazy_lookup.find(opname) != lazy_lookup.end();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Create some placeholder symbols for shader globals that have don't
|
||||
// normally have symbols.
|
||||
// Purpose is to allow our data structures to use Symbol * as a key
|
||||
@@ -180,7 +185,7 @@ struct Symbols4ProtectedShaderGlobals {
|
||||
|
||||
SymbolPtrVec varying_symbols;
|
||||
|
||||
void check_if_varing(Symbol& s)
|
||||
void check_if_varying(Symbol& s)
|
||||
{
|
||||
if (!is_shader_global_uniform_by_name(s.name())) {
|
||||
s.make_varying();
|
||||
@@ -197,16 +202,18 @@ struct Symbols4ProtectedShaderGlobals {
|
||||
, surfacearea(Strings::op_surfacearea, TypeSpec(), SymTypeGlobal)
|
||||
, time(Strings::time, TypeSpec(), SymTypeGlobal)
|
||||
{
|
||||
check_if_varing(shader2common);
|
||||
check_if_varing(object2common);
|
||||
check_if_varing(flipHandedness);
|
||||
check_if_varing(raytype);
|
||||
check_if_varing(backfacing);
|
||||
check_if_varing(surfacearea);
|
||||
check_if_varing(time);
|
||||
check_if_varying(shader2common);
|
||||
check_if_varying(object2common);
|
||||
check_if_varying(flipHandedness);
|
||||
check_if_varying(raytype);
|
||||
check_if_varying(backfacing);
|
||||
check_if_varying(surfacearea);
|
||||
check_if_varying(time);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
Symbols4ProtectedShaderGlobals&
|
||||
psg()
|
||||
{
|
||||
@@ -233,8 +240,7 @@ private:
|
||||
static constexpr OpcodeTest no_test = nullptr;
|
||||
|
||||
// Map opcode names to a Dependency info
|
||||
std::unordered_map<ustring, Dependency, ustringHash> m_lookup;
|
||||
|
||||
std::unordered_map<ustring, Dependency> m_lookup;
|
||||
|
||||
/// Return the ptr to the symbol that is the argnum-th argument to the
|
||||
/// given op in the instance.
|
||||
@@ -259,8 +265,8 @@ private:
|
||||
// We can know all the space names at this time
|
||||
ustring from = From ? *((ustring*)From->data())
|
||||
: Strings::common;
|
||||
ustring to = *((ustring*)To->data());
|
||||
ustring syn = inst.shadingsys().commonspace_synonym();
|
||||
ustring to = *((ustring*)To->data());
|
||||
ustring syn = inst.shadingsys().commonspace_synonym();
|
||||
if (from == syn)
|
||||
from = Strings::common;
|
||||
if (to == syn)
|
||||
@@ -355,6 +361,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
static SymbolPtrVec*
|
||||
protected_shader_globals_op_implicitly_depends_on(ShaderInstance& inst,
|
||||
Opcode& opcode)
|
||||
@@ -363,17 +371,20 @@ protected_shader_globals_op_implicitly_depends_on(ShaderInstance& inst,
|
||||
return lazyDependencies.lookup(inst, opcode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
is_op_result_always_logically_boolean(ustring opname)
|
||||
{
|
||||
// Test if explicit comparison is faster or not
|
||||
static boost::container::flat_set<ustring> lazy_lookup(
|
||||
{ Strings::op_getattribute, Strings::op_eq,
|
||||
Strings::op_ge, Strings::op_gt, Strings::op_le, Strings::op_lt,
|
||||
Strings::op_neq, Strings::op_and, Strings::op_or });
|
||||
{ Strings::op_getattribute, Strings::op_eq, Strings::op_ge,
|
||||
Strings::op_gt, Strings::op_le, Strings::op_lt, Strings::op_neq,
|
||||
Strings::op_and, Strings::op_or });
|
||||
return lazy_lookup.find(opname) != lazy_lookup.end();
|
||||
}
|
||||
|
||||
|
||||
// TODO: Add more analysis to identify boolean results from the class of
|
||||
// operations who would produce a boolean result if given boolean inputs.
|
||||
// For example complement (~) would have a boolean result when passed a
|
||||
@@ -383,7 +394,8 @@ is_op_result_always_logically_boolean(ustring opname)
|
||||
// comparison operators even if the are not "currently"
|
||||
// being referenced. May need to disable some warnings
|
||||
// error #177: function "..." was declared but never referenced
|
||||
OSL_INTEL_PRAGMA(warning ( disable:177 ))
|
||||
OSL_INTEL_PRAGMA(warning(disable : 177))
|
||||
|
||||
|
||||
// The Position returned by top_pos changes and symbols are pushed and popped.
|
||||
// However any given position is invariant as scopes change, and one
|
||||
@@ -443,7 +455,6 @@ public:
|
||||
|
||||
DependencyTreeTracker(const DependencyTreeTracker&) = delete;
|
||||
|
||||
|
||||
class Iterator {
|
||||
Position m_pos;
|
||||
const DependencyTreeTracker* m_dtt;
|
||||
@@ -608,8 +619,21 @@ public:
|
||||
--m_current_depth;
|
||||
}
|
||||
|
||||
|
||||
Position common_ancestor_between(Position read_pos, Position write_pos)
|
||||
{
|
||||
// Early out when read and write are at the same position
|
||||
if (read_pos == write_pos)
|
||||
return read_pos;
|
||||
// Early out if either position is the root of the dependency tree
|
||||
if (read_pos == end_pos() || write_pos == end_pos())
|
||||
return end_pos();
|
||||
return search_for_common_ancestor_between(read_pos, write_pos);
|
||||
}
|
||||
|
||||
// Because this function makes use of stack arrays, ensure is NOT inlined
|
||||
// inside a loop to avoid repeatedly reserve stack space each iteration
|
||||
OSL_NOINLINE Position search_for_common_ancestor_between(Position read_pos,
|
||||
Position write_pos)
|
||||
{
|
||||
// To find common anscenstor
|
||||
// Walk up both paths building 2 stacks of positions
|
||||
@@ -619,8 +643,8 @@ public:
|
||||
auto write_iter = begin_at(write_pos);
|
||||
|
||||
const int read_count = read_iter.depth() + 1;
|
||||
OSL_STACK_ARRAY(Position, read_path, read_count);
|
||||
int read_depth = 0;
|
||||
Position* read_path = OSL_ALLOCA(Position, read_count);
|
||||
int read_depth = 0;
|
||||
{
|
||||
// Loop structure is to allow
|
||||
// writing the end position into the read path
|
||||
@@ -634,8 +658,8 @@ public:
|
||||
}
|
||||
|
||||
const int writeCount = write_iter.depth() + 1;
|
||||
OSL_STACK_ARRAY(Position, write_path, writeCount);
|
||||
int write_depth = 0;
|
||||
Position* write_path = OSL_ALLOCA(Position, writeCount);
|
||||
int write_depth = 0;
|
||||
{
|
||||
// Loop structure is to allow
|
||||
// writing the end position into the write path
|
||||
@@ -647,31 +671,53 @@ public:
|
||||
++write_iter;
|
||||
}
|
||||
}
|
||||
const int levelCount = std::min(read_depth, write_depth);
|
||||
const int read_level = read_depth - 1;
|
||||
const int write_level = write_depth - 1;
|
||||
OSL_ASSERT(write_path[write_level] == end_pos());
|
||||
OSL_ASSERT(read_path[read_level] == end_pos());
|
||||
|
||||
const int walkCount = std::min(read_depth, write_depth);
|
||||
const int read_top = read_depth - 1;
|
||||
const int write_top = write_depth - 1;
|
||||
OSL_DASSERT(write_top < writeCount);
|
||||
OSL_DASSERT(write_path[write_top] == end_pos());
|
||||
OSL_DASSERT(read_top < read_count);
|
||||
OSL_DASSERT(read_path[read_top] == end_pos());
|
||||
|
||||
int walkDepth = 0;
|
||||
// Verify top of read and write stacks match positions
|
||||
OSL_DASSERT((read_top - walkDepth) >= 0);
|
||||
OSL_DASSERT((read_top - walkDepth) < read_count);
|
||||
OSL_DASSERT((write_top - walkDepth) >= 0);
|
||||
OSL_DASSERT((write_top - walkDepth) < writeCount);
|
||||
OSL_DASSERT(read_path[read_top - walkDepth]
|
||||
== write_path[write_top - walkDepth]);
|
||||
// That position should technically be the root (no conditions in the dependency tree)
|
||||
OSL_DASSERT(read_path[read_top - walkDepth] == end_pos());
|
||||
// Because we know walkDepth 0 never differs, we can start iterating
|
||||
// at walkDepth 1
|
||||
|
||||
int level = 0;
|
||||
OSL_ASSERT(read_path[read_level - level]
|
||||
== write_path[write_level - level]);
|
||||
do {
|
||||
++level;
|
||||
if (read_path[read_level - level]()
|
||||
!= write_path[write_level - level]())
|
||||
// Walk down the read and write paths until they differ
|
||||
for (walkDepth = 1; walkDepth < walkCount; ++walkDepth) {
|
||||
OSL_DASSERT((read_top - walkDepth) >= 0);
|
||||
OSL_DASSERT((read_top - walkDepth) < read_count);
|
||||
OSL_DASSERT((write_top - walkDepth) >= 0);
|
||||
OSL_DASSERT((write_top - walkDepth) < writeCount);
|
||||
if (read_path[read_top - walkDepth]()
|
||||
!= write_path[write_top - walkDepth]()) {
|
||||
break;
|
||||
} while (level < levelCount);
|
||||
--level;
|
||||
OSL_ASSERT(read_path[read_level - level]
|
||||
== write_path[write_level - level]);
|
||||
OSL_ASSERT(read_level - level >= 0);
|
||||
return read_path[read_level - level];
|
||||
}
|
||||
}
|
||||
// The previous walk depth's position was the common ancestor
|
||||
--walkDepth;
|
||||
OSL_DASSERT((read_top - walkDepth) >= 0);
|
||||
OSL_DASSERT((read_top - walkDepth) < read_count);
|
||||
OSL_DASSERT((write_top - walkDepth) >= 0);
|
||||
OSL_DASSERT((write_top - walkDepth) < writeCount);
|
||||
OSL_DASSERT(read_path[read_top - walkDepth]
|
||||
== write_path[write_top - walkDepth]);
|
||||
return read_path[read_top - walkDepth];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Historically tracks stack of functions
|
||||
// The Position returned by top_pos changes and function scopes are pushed and popped.
|
||||
// However any given position is invariant as scopes change
|
||||
@@ -747,7 +793,6 @@ public:
|
||||
|
||||
FunctionTreeTracker(const FunctionTreeTracker&) = delete;
|
||||
|
||||
|
||||
class Iterator {
|
||||
Position m_pos;
|
||||
const FunctionTreeTracker* m_ftt;
|
||||
@@ -961,7 +1006,6 @@ public:
|
||||
m_nodes.push_back(node);
|
||||
}
|
||||
|
||||
|
||||
OSL_FORCEINLINE Position top_pos() const { return m_top_of_stack; }
|
||||
|
||||
OSL_FORCEINLINE void pop_function_call()
|
||||
@@ -995,6 +1039,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class WriteEvent {
|
||||
DependencyTreeTracker::Position m_pos_in_tree;
|
||||
int m_op_num;
|
||||
@@ -1034,18 +1080,22 @@ public:
|
||||
return m_op_num;
|
||||
}
|
||||
|
||||
|
||||
OSL_FORCEINLINE int loop_op_index() const { return m_loop_op_index; }
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector<WriteEvent> WriteChronology;
|
||||
//typedef llvm::SmallVector<WriteEvent, 8> WriteChronology;
|
||||
|
||||
|
||||
|
||||
class ReadEvent {
|
||||
DependencyTreeTracker::Position m_pos_in_tree;
|
||||
#ifdef OSL_DEV
|
||||
int m_op_num;
|
||||
int m_loop_op_index;
|
||||
#endif
|
||||
|
||||
public:
|
||||
ReadEvent(DependencyTreeTracker::Position pos_in_tree_
|
||||
#ifdef OSL_DEV
|
||||
@@ -1067,16 +1117,25 @@ public:
|
||||
}
|
||||
|
||||
#ifdef OSL_DEV
|
||||
OSL_FORCEINLINE int op_num() const { return m_op_num; }
|
||||
OSL_FORCEINLINE int op_num() const
|
||||
{
|
||||
return m_op_num;
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE int loop_op_index() const { return m_loop_op_index; }
|
||||
OSL_FORCEINLINE int loop_op_index() const
|
||||
{
|
||||
return m_loop_op_index;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector<ReadEvent> ReadChronology;
|
||||
// Testing showed 6 read events a typically max
|
||||
//typedef llvm::SmallVector<ReadEvent, 6> ReadChronology;
|
||||
|
||||
|
||||
|
||||
class LoopStack {
|
||||
std::vector<int> m_conditions_op_index_stack;
|
||||
std::vector<const Symbol*> m_conditions_symbol_stack;
|
||||
@@ -1156,6 +1215,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct ReadBranch {
|
||||
DependencyTreeTracker::Position pos;
|
||||
int depth; // how deep in the m_conditional_symbol_stack did the read occur
|
||||
@@ -1167,6 +1228,8 @@ struct ReadBranch {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct Analyzer {
|
||||
BatchedAnalysis& m_ba;
|
||||
ShaderInstance* m_inst;
|
||||
@@ -1202,7 +1265,6 @@ struct Analyzer {
|
||||
|
||||
std::unordered_set<Symbol*> m_symbols_written_to_by_implicitly_varying_ops;
|
||||
|
||||
|
||||
// Remember which symbols we've force to be boolean so we can
|
||||
// reverse that decision if we see them used by any boolean operations
|
||||
std::unordered_set<Symbol*> m_symbols_logically_bool;
|
||||
@@ -1363,7 +1425,8 @@ struct Analyzer {
|
||||
op(write_op_num).requires_masking(true);
|
||||
OSL_DEV_ONLY(
|
||||
std::cout
|
||||
<< "cyclic read of " << symbol_to_check->unmangled().c_str()
|
||||
<< "cyclic read of "
|
||||
<< symbol_to_check->unmangled().c_str()
|
||||
<< " from loop [" << read_iter->loop_op_index()
|
||||
<< "] op(" << write_op_num << ").requires_masking()="
|
||||
<< op(write_op_num).requires_masking() << std::endl);
|
||||
@@ -1490,11 +1553,12 @@ struct Analyzer {
|
||||
for (auto cond_iter = m_conditional_symbol_stack.begin();
|
||||
*cond_iter != loop_condition; ++cond_iter) {
|
||||
auto conditionContinueDependsOn = *cond_iter;
|
||||
OSL_DEV_ONLY(std::cout << ">>>Loop Conditional "
|
||||
<< loop_condition->unmangled().c_str()
|
||||
<< " needs to depend on conditional "
|
||||
<< conditionContinueDependsOn->unmangled().c_str()
|
||||
<< std::endl);
|
||||
OSL_DEV_ONLY(std::cout
|
||||
<< ">>>Loop Conditional "
|
||||
<< loop_condition->unmangled().c_str()
|
||||
<< " needs to depend on conditional "
|
||||
<< conditionContinueDependsOn->unmangled().c_str()
|
||||
<< std::endl);
|
||||
m_symbols_dependent_upon.insert(
|
||||
std::make_pair(conditionContinueDependsOn, loop_condition));
|
||||
}
|
||||
@@ -1577,7 +1641,7 @@ struct Analyzer {
|
||||
// Process arguments written to to handle early outs, cyclical reads,
|
||||
// and record a WriteEvent to a potentially unmasked operations remembering
|
||||
// the exact stack of conditional dependencies at that point.
|
||||
// When we processed reads (above), we ensured that any reads occuring at a higher that on the stoCheck for
|
||||
// When we processed reads (above), we ensured that any reads occurring at a higher that on the stoCheck for
|
||||
for (int write_index = 0; write_index < write_count;
|
||||
++write_index) {
|
||||
const Symbol* symbolWrittenTo
|
||||
@@ -1624,7 +1688,7 @@ struct Analyzer {
|
||||
}
|
||||
}
|
||||
|
||||
// Special case for op_getattribute which normaly would be
|
||||
// Special case for op_getattribute which normally would be
|
||||
// implicitly varying unless BatchedRendererServices says it
|
||||
// is uniform.
|
||||
if (opcode.opname() == Strings::op_getattribute) {
|
||||
@@ -1718,7 +1782,6 @@ struct Analyzer {
|
||||
m_deferred_op_indices_to_be_masked.push_back(op_index);
|
||||
}
|
||||
|
||||
|
||||
// Track dependencies between symbols written to in this basic block
|
||||
// to the set of symbols the code blocks where dependent upon to be executed
|
||||
m_pos_in_dependent_sym_stack_by_op_index[op_index]
|
||||
@@ -1788,7 +1851,6 @@ struct Analyzer {
|
||||
OSL_ASSERT(read_count == 1);
|
||||
m_loop_stack.push_loop(op_index, symbols_read_by_op[0]);
|
||||
|
||||
|
||||
// Body block
|
||||
OSL_DEV_ONLY(std::cout << " FOR BODY BLOCK BEGIN"
|
||||
<< std::endl);
|
||||
@@ -1809,7 +1871,6 @@ struct Analyzer {
|
||||
OSL_ASSERT(m_conditional_symbol_stack.top() == condition);
|
||||
m_conditional_symbol_stack.pop();
|
||||
|
||||
|
||||
// Condition block
|
||||
// NOTE: Processing condition like it was a do/while
|
||||
// Although the first execution of the condition doesn't depend on the for loops conditions
|
||||
@@ -1837,7 +1898,6 @@ struct Analyzer {
|
||||
m_conditional_symbol_stack.pop();
|
||||
m_loop_stack.pop_loop(op_index);
|
||||
|
||||
|
||||
} else if (opcode.opname() == Strings::op_functioncall) {
|
||||
// Function call itself operates on the same symbol dependencies
|
||||
// as the current block, there was no conditionals involved
|
||||
@@ -2006,9 +2066,9 @@ struct Analyzer {
|
||||
continue;
|
||||
// Skip if it's an interpolated (userdata) parameter and we're
|
||||
// initializing them lazily.
|
||||
if ((s.symtype() == SymTypeParam || s.symtype() == SymTypeOutputParam)
|
||||
&& !s.lockgeom()
|
||||
&& !s.typespec().is_closure() && !s.connected()
|
||||
if ((s.symtype() == SymTypeParam
|
||||
|| s.symtype() == SymTypeOutputParam)
|
||||
&& !s.lockgeom() && !s.typespec().is_closure() && !s.connected()
|
||||
&& !s.connected_down() && m_ba.shadingsys().lazy_userdata())
|
||||
continue;
|
||||
// Set initial value for params (may contain init ops)
|
||||
@@ -2118,7 +2178,8 @@ struct Analyzer {
|
||||
OSL_DEV_ONLY(
|
||||
std::cout
|
||||
<< "Mapping "
|
||||
<< sym_mask_depends_on->unmangled().c_str()
|
||||
<< sym_mask_depends_on->unmangled()
|
||||
.c_str()
|
||||
<< std::endl);
|
||||
m_symbols_dependent_upon.insert(
|
||||
std::make_pair(sym_mask_depends_on,
|
||||
@@ -2140,7 +2201,7 @@ struct Analyzer {
|
||||
#endif
|
||||
const auto& early_out = *earlyOutIter;
|
||||
auto begin_dep_iter = m_conditional_symbol_stack.begin_at(
|
||||
early_out.dtt_pos);
|
||||
early_out.dtt_pos);
|
||||
auto end_dep_iter = m_conditional_symbol_stack.end();
|
||||
|
||||
const Opcode& opcode = m_opcodes[op_index];
|
||||
@@ -2166,7 +2227,8 @@ struct Analyzer {
|
||||
OSL_DEV_ONLY(
|
||||
std::cout
|
||||
<< "Mapping "
|
||||
<< sym_mask_depends_on->unmangled().c_str()
|
||||
<< sym_mask_depends_on->unmangled()
|
||||
.c_str()
|
||||
<< std::endl);
|
||||
m_symbols_dependent_upon.insert(
|
||||
std::make_pair(sym_mask_depends_on,
|
||||
@@ -2297,12 +2359,16 @@ struct Analyzer {
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
BatchedAnalysis::BatchedAnalysis(ShadingSystemImpl& shadingsys,
|
||||
ShaderGroup& group)
|
||||
: m_shadingsys(shadingsys), m_group(group)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedAnalysis::analyze_layer(ShaderInstance* inst)
|
||||
{
|
||||
@@ -2339,6 +2405,8 @@ BatchedAnalysis::analyze_layer(ShaderInstance* inst)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedAnalysis::dump_symbol_uniformity(ShaderInstance* inst)
|
||||
{
|
||||
@@ -2355,6 +2423,8 @@ BatchedAnalysis::dump_symbol_uniformity(ShaderInstance* inst)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedAnalysis::dump_layer(ShaderInstance* inst)
|
||||
{
|
||||
|
||||
@@ -45,11 +45,12 @@ static ustring fields[] = {
|
||||
ustring("objdata"), //
|
||||
ustring("shadingcontext"), //
|
||||
ustring("renderer"), //
|
||||
Strings::Ci, //
|
||||
Strings::raytype, //
|
||||
ustring("pad0"), //
|
||||
ustring("pad1"), //
|
||||
ustring("pad2"), //
|
||||
ustring("pad3"), //
|
||||
ustring("pad4"), //
|
||||
// Varying
|
||||
Strings::P, //
|
||||
ustring("dPdz"), //
|
||||
@@ -66,6 +67,7 @@ static ustring fields[] = {
|
||||
Strings::Ps, //
|
||||
Strings::object2common, //
|
||||
Strings::shader2common, //
|
||||
Strings::Ci, //
|
||||
Strings::surfacearea, //
|
||||
Strings::flipHandedness, //
|
||||
Strings::backfacing
|
||||
@@ -78,11 +80,12 @@ static bool field_is_uniform[] = {
|
||||
true, // objdata
|
||||
true, // shadingcontext
|
||||
true, // renderer
|
||||
true, // Ci
|
||||
true, // raytype
|
||||
true, // pad0
|
||||
true, // pad1
|
||||
true, // pad2
|
||||
true, // pad3
|
||||
true, // pad4
|
||||
// Varying
|
||||
false, // P
|
||||
false, // dPdz
|
||||
@@ -99,6 +102,7 @@ static bool field_is_uniform[] = {
|
||||
false, // Ps
|
||||
false, // object2common
|
||||
false, // shader2common
|
||||
false, // Ci,
|
||||
false, // surfacearea
|
||||
false, // flipHandedness
|
||||
false, // backfacing
|
||||
@@ -184,7 +188,7 @@ BatchedBackendLLVM::llvm_pass_type(const TypeSpec& typespec)
|
||||
else if (t == TypeDesc::INT)
|
||||
lt = ll.type_int();
|
||||
else if (t == TypeDesc::STRING)
|
||||
lt = (llvm::Type*)ll.type_string();
|
||||
lt = (llvm::Type*)ll.type_ustring();
|
||||
else if (t.aggregate == TypeDesc::VEC3)
|
||||
lt = (llvm::Type*)ll.type_void_ptr(); //llvm_type_triple_ptr();
|
||||
else if (t.aggregate == TypeDesc::MATRIX44)
|
||||
@@ -205,6 +209,8 @@ BatchedBackendLLVM::llvm_pass_type(const TypeSpec& typespec)
|
||||
return lt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Type*
|
||||
BatchedBackendLLVM::llvm_pass_wide_type(const TypeSpec& typespec)
|
||||
{
|
||||
@@ -263,6 +269,11 @@ BatchedBackendLLVM::llvm_assign_zero(const Symbol& sym)
|
||||
zero = ll.constant(ustring());
|
||||
else
|
||||
zero = ll.wide_constant(ustring());
|
||||
} else if (elemtype.is_closure_based()) {
|
||||
if (sym.is_uniform())
|
||||
zero = ll.void_ptr_null();
|
||||
else
|
||||
zero = ll.widen_value(ll.void_ptr_null());
|
||||
} else {
|
||||
OSL_ASSERT(0 && "Unsupported element type");
|
||||
zero = nullptr;
|
||||
@@ -270,9 +281,8 @@ BatchedBackendLLVM::llvm_assign_zero(const Symbol& sym)
|
||||
|
||||
int num_elements = t.numelements();
|
||||
for (int a = 0; a < num_elements; ++a) {
|
||||
int numDeriv = sym.has_derivs() ? 3 : 1;
|
||||
llvm::Value* arrind = t.simpletype().arraylen ? ll.constant(a)
|
||||
: NULL;
|
||||
int numDeriv = sym.has_derivs() ? 3 : 1;
|
||||
llvm::Value* arrind = t.simpletype().arraylen ? ll.constant(a) : NULL;
|
||||
for (int d = 0; d < numDeriv; ++d) {
|
||||
for (int c = 0; c < t.aggregate(); ++c) {
|
||||
llvm_store_value(zero, sym, d, arrind, c);
|
||||
@@ -312,7 +322,6 @@ BatchedBackendLLVM::llvm_zero_derivs(const Symbol& sym)
|
||||
++arrayindex) {
|
||||
llvm::Value* arrind = arrayindex >= 0 ? ll.constant(arrayindex)
|
||||
: NULL;
|
||||
|
||||
for (int c = 0; c < t.aggregate(); ++c)
|
||||
llvm_store_value(zero, sym, 1, arrind, c);
|
||||
for (int c = 0; c < t.aggregate(); ++c)
|
||||
@@ -322,15 +331,15 @@ BatchedBackendLLVM::llvm_zero_derivs(const Symbol& sym)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedBackendLLVM::llvm_zero_derivs(const Symbol& sym, llvm::Value* count)
|
||||
{
|
||||
// Same thing as the above version but with just the first count derivs
|
||||
const TypeSpec& t = sym.typespec();
|
||||
|
||||
OSL_ASSERT((count->getType() == ll.type_int()) ||
|
||||
(count->getType() == ll.type_wide_int()));
|
||||
|
||||
OSL_ASSERT((count->getType() == ll.type_int())
|
||||
|| (count->getType() == ll.type_wide_int()));
|
||||
|
||||
if (t.is_closure_based())
|
||||
return; // Closures don't have derivs
|
||||
@@ -343,7 +352,7 @@ BatchedBackendLLVM::llvm_zero_derivs(const Symbol& sym, llvm::Value* count)
|
||||
else
|
||||
zero = ll.wide_constant(0.0f);
|
||||
|
||||
if(!t.is_array()) {
|
||||
if (!t.is_array()) {
|
||||
// Not an array, probably shouldn't have called this method
|
||||
// just fallback to non-count based version
|
||||
llvm_zero_derivs(sym);
|
||||
@@ -352,40 +361,45 @@ BatchedBackendLLVM::llvm_zero_derivs(const Symbol& sym, llvm::Value* count)
|
||||
|
||||
llvm::Value* pre_condition_mask = ll.current_mask();
|
||||
|
||||
llvm::Value * index_loc = ll.op_alloca(ll.type_int(), 1);
|
||||
llvm::Value* index_loc = ll.op_alloca(ll.type_int(), 1);
|
||||
ll.op_store(ll.constant(0), index_loc);
|
||||
|
||||
llvm::BasicBlock* cond_block = ll.new_basic_block ("zero deriv cond");
|
||||
llvm::BasicBlock* body_block = ll.new_basic_block ("zero deriv body");
|
||||
llvm::BasicBlock* step_block = ll.new_basic_block ("zero deriv step");
|
||||
llvm::BasicBlock* after_block = ll.new_basic_block ("zero deriv after");
|
||||
llvm::BasicBlock* cond_block = ll.new_basic_block("zero deriv cond");
|
||||
llvm::BasicBlock* body_block = ll.new_basic_block("zero deriv body");
|
||||
llvm::BasicBlock* step_block = ll.new_basic_block("zero deriv step");
|
||||
llvm::BasicBlock* after_block = ll.new_basic_block("zero deriv after");
|
||||
|
||||
ll.op_branch (cond_block);
|
||||
llvm::Value * index_val = ll.op_load(index_loc);
|
||||
llvm::Value * windex_val = ll.widen_value(index_val);
|
||||
llvm::Value * condition_mask = ll.op_lt(windex_val, count);
|
||||
llvm::Value * post_condition_mask = ll.op_and(condition_mask, pre_condition_mask);
|
||||
llvm::Value* cond_val = ll.test_if_mask_is_non_zero(post_condition_mask);
|
||||
ll.op_branch(cond_block);
|
||||
llvm::Value* index_val = ll.op_load(index_loc);
|
||||
llvm::Value* windex_val = ll.widen_value(index_val);
|
||||
llvm::Value* condition_mask = ll.op_lt(windex_val, count);
|
||||
llvm::Value* post_condition_mask = ll.op_and(condition_mask,
|
||||
pre_condition_mask);
|
||||
llvm::Value* cond_val = ll.test_if_mask_is_non_zero(
|
||||
post_condition_mask);
|
||||
|
||||
// Jump to either LoopBody or AfterLoop
|
||||
ll.op_branch (cond_val, body_block, after_block);
|
||||
ll.push_mask(post_condition_mask, false /* negate */, true /* absolute */);
|
||||
ll.op_branch(cond_val, body_block, after_block);
|
||||
ll.push_mask(post_condition_mask, false /* negate */,
|
||||
true /* absolute */);
|
||||
for (int c = 0; c < t.aggregate(); ++c)
|
||||
llvm_store_value(zero, sym, 1, index_val, c);
|
||||
for (int c = 0; c < t.aggregate(); ++c)
|
||||
llvm_store_value(zero, sym, 2, index_val, c);
|
||||
ll.pop_mask();
|
||||
|
||||
ll.op_branch (step_block);
|
||||
ll.op_branch(step_block);
|
||||
index_val = ll.op_add(index_val, ll.constant(1));
|
||||
ll.op_store(index_val, index_loc);
|
||||
ll.op_branch (cond_block);
|
||||
ll.op_branch(cond_block);
|
||||
|
||||
// Continue on with the previous flow
|
||||
ll.set_insert_point (after_block);
|
||||
ll.set_insert_point(after_block);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
BatchedBackendLLVM::ShaderGlobalNameToIndex(ustring name, bool& is_uniform)
|
||||
{
|
||||
@@ -399,6 +413,8 @@ BatchedBackendLLVM::ShaderGlobalNameToIndex(ustring name, bool& is_uniform)
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::llvm_global_symbol_ptr(ustring name, bool& is_uniform)
|
||||
{
|
||||
@@ -410,6 +426,8 @@ BatchedBackendLLVM::llvm_global_symbol_ptr(ustring name, bool& is_uniform)
|
||||
return ll.void_ptr(ll.GEP(sg_ptr(), 0, sg_index));
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::getLLVMSymbolBase(const Symbol& sym)
|
||||
{
|
||||
@@ -441,14 +459,16 @@ BatchedBackendLLVM::getLLVMSymbolBase(const Symbol& sym)
|
||||
std::string mangled_name = dealiased->mangled();
|
||||
AllocationMap::iterator map_iter = named_values().find(mangled_name);
|
||||
if (map_iter == named_values().end()) {
|
||||
shadingcontext()->errorf(
|
||||
"Couldn't find symbol '%s' (unmangled = '%s'). Did you forget to allocate it?",
|
||||
mangled_name.c_str(), dealiased->unmangled());
|
||||
shadingcontext()->errorfmt(
|
||||
"Couldn't find symbol '{}' (unmangled = '{}'). Did you forget to allocate it?",
|
||||
mangled_name, dealiased->unmangled());
|
||||
return 0;
|
||||
}
|
||||
return (llvm::Value*)map_iter->second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::llvm_alloca(const TypeSpec& type, bool derivs,
|
||||
bool is_uniform, bool forceBool,
|
||||
@@ -476,12 +496,16 @@ BatchedBackendLLVM::llvm_alloca(const TypeSpec& type, bool derivs,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
BatchedBackendLLVM::TempScope::TempScope(BatchedBackendLLVM& backend)
|
||||
: m_backend(backend)
|
||||
{
|
||||
m_backend.m_temp_scopes.push_back(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
BatchedBackendLLVM::TempScope::~TempScope()
|
||||
{
|
||||
OSL_ASSERT(!m_backend.m_temp_scopes.empty()
|
||||
@@ -497,6 +521,8 @@ BatchedBackendLLVM::TempScope::~TempScope()
|
||||
m_backend.m_temp_scopes.pop_back();
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::getOrAllocateTemp(const TypeSpec& type, bool derivs,
|
||||
bool is_uniform, bool forceBool,
|
||||
@@ -537,6 +563,8 @@ BatchedBackendLLVM::getOrAllocateTemp(const TypeSpec& type, bool derivs,
|
||||
return allocation;
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::getOrAllocateLLVMSymbol(const Symbol& sym)
|
||||
{
|
||||
@@ -620,6 +648,8 @@ BatchedBackendLLVM::llvm_get_pointer(const Symbol& sym, int deriv,
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::llvm_widen_value_into_temp(const Symbol& sym, int deriv)
|
||||
{
|
||||
@@ -633,7 +663,7 @@ BatchedBackendLLVM::llvm_widen_value_into_temp(const Symbol& sym, int deriv)
|
||||
OSL_ASSERT(symType.is_unknown() == false);
|
||||
|
||||
llvm::Value* widePtr = getOrAllocateTemp(t, false /*derivs*/,
|
||||
false /*is_uniform*/);
|
||||
false /*is_uniform*/);
|
||||
auto disable_masked_stores = ll.create_masking_scope(false);
|
||||
for (int c = 0; c < t.aggregate(); ++c) {
|
||||
// NOTE: we use the passed deriv to load, but store to value (deriv==0)
|
||||
@@ -644,6 +674,8 @@ BatchedBackendLLVM::llvm_widen_value_into_temp(const Symbol& sym, int deriv)
|
||||
return ll.void_ptr(widePtr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::llvm_load_value(const Symbol& sym, int deriv,
|
||||
llvm::Value* arrayindex, int component,
|
||||
@@ -729,6 +761,7 @@ BatchedBackendLLVM::llvm_load_value(const Symbol& sym, int deriv,
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::llvm_load_mask(const Symbol& cond)
|
||||
{
|
||||
@@ -751,6 +784,7 @@ BatchedBackendLLVM::llvm_load_mask(const Symbol& cond)
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type,
|
||||
int deriv, llvm::Value* arrayindex,
|
||||
@@ -833,7 +867,7 @@ BatchedBackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type,
|
||||
|| (ll.llvm_typeof(result) == ll.type_float())
|
||||
|| (ll.llvm_typeof(result) == ll.type_triple())
|
||||
|| (ll.llvm_typeof(result) == ll.type_int())
|
||||
|| (ll.llvm_typeof(result) == (llvm::Type*)ll.type_string())
|
||||
|| (ll.llvm_typeof(result) == ll.type_ustring())
|
||||
|| (ll.llvm_typeof(result) == ll.type_matrix())
|
||||
|| (ll.llvm_typeof(result) == ll.type_longlong())) {
|
||||
result = ll.widen_value(result);
|
||||
@@ -854,7 +888,7 @@ BatchedBackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type,
|
||||
(ll.llvm_typeof(result) == ll.type_wide_float())
|
||||
|| (ll.llvm_typeof(result) == ll.type_wide_int())
|
||||
|| (ll.llvm_typeof(result) == ll.type_wide_triple())
|
||||
|| (ll.llvm_typeof(result) == ll.type_wide_string())
|
||||
|| (ll.llvm_typeof(result) == ll.type_wide_ustring())
|
||||
|| (ll.llvm_typeof(result) == ll.type_wide_bool())
|
||||
|| (ll.llvm_typeof(result) == ll.type_wide_matrix())
|
||||
|| (ll.llvm_typeof(result) == ll.type_wide_longlong()));
|
||||
@@ -888,7 +922,6 @@ BatchedBackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type,
|
||||
// vs. the hardcoded 4 and avoid the multiplication above
|
||||
}
|
||||
|
||||
|
||||
// Now grab the value
|
||||
llvm::Value* result;
|
||||
result = ll.op_gather(ptr, arrayindex);
|
||||
@@ -932,7 +965,6 @@ BatchedBackendLLVM::llvm_load_constant_value(const Symbol& sym, int arrayindex,
|
||||
OSL_ASSERT(arrayindex >= 0
|
||||
&& "Called llvm_load_constant_value with negative array index");
|
||||
|
||||
|
||||
// TODO: might want to take this fix for array types back to the non-wide backend
|
||||
TypeSpec elementType = sym.typespec();
|
||||
// The symbol we are creating a constant for might be an array
|
||||
@@ -971,7 +1003,7 @@ BatchedBackendLLVM::llvm_load_constant_value(const Symbol& sym, int arrayindex,
|
||||
}
|
||||
if (elementType.is_triple() || elementType.is_matrix()) {
|
||||
int ncomps = (int)sym.typespec().aggregate();
|
||||
float float_elem = sym.get_float(ncomps*arrayindex + component);
|
||||
float float_elem = sym.get_float(ncomps * arrayindex + component);
|
||||
if (op_is_uniform) {
|
||||
return ll.constant(float_elem);
|
||||
} else {
|
||||
@@ -1109,14 +1141,14 @@ BatchedBackendLLVM::llvm_load_arg(const Symbol& sym, bool derivs,
|
||||
int copy_deriv_count = (derivs && sym.has_derivs()) ? 3 : 1;
|
||||
|
||||
int copy_elem_count = t.numelements();
|
||||
bool is_array = t.is_array();
|
||||
bool is_array = t.is_array();
|
||||
for (int d = 0; d < copy_deriv_count; ++d) {
|
||||
for(int ai=0; ai < copy_elem_count; ++ai) {
|
||||
llvm::Value * arrayIndex = is_array ? ll.constant(ai) : nullptr;
|
||||
for (int ai = 0; ai < copy_elem_count; ++ai) {
|
||||
llvm::Value* arrayIndex = is_array ? ll.constant(ai) : nullptr;
|
||||
for (int c = 0; c < t.aggregate(); ++c) {
|
||||
|
||||
// Will automatically widen value if needed
|
||||
llvm::Value* v = llvm_load_value(sym, d, arrayIndex, c, TypeDesc::UNKNOWN,
|
||||
llvm::Value* v = llvm_load_value(sym, d, arrayIndex, c,
|
||||
TypeDesc::UNKNOWN,
|
||||
op_is_uniform);
|
||||
llvm_store_value(v, tmpptr, t, d, arrayIndex, c);
|
||||
}
|
||||
@@ -1186,7 +1218,8 @@ BatchedBackendLLVM::llvm_store_value(llvm::Value* new_val, llvm::Value* dst_ptr,
|
||||
if (!type.is_closure_based() && t.aggregate > 1)
|
||||
dst_ptr = ll.GEP(dst_ptr, 0, component);
|
||||
|
||||
if (ll.type_ptr(ll.llvm_typeof(new_val)) != ll.llvm_typeof(dst_ptr)) {
|
||||
if ((const llvm::Type*)ll.type_ptr(ll.llvm_typeof(new_val))
|
||||
!= ll.llvm_typeof(dst_ptr)) {
|
||||
std::cerr << " new_val type=";
|
||||
{
|
||||
llvm::raw_os_ostream os_cerr(std::cerr);
|
||||
@@ -1199,10 +1232,9 @@ BatchedBackendLLVM::llvm_store_value(llvm::Value* new_val, llvm::Value* dst_ptr,
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
OSL_ASSERT(ll.type_ptr(ll.llvm_typeof(new_val))
|
||||
OSL_ASSERT((const llvm::Type*)ll.type_ptr(ll.llvm_typeof(new_val))
|
||||
== ll.llvm_typeof(dst_ptr));
|
||||
|
||||
|
||||
// Finally, store the value.
|
||||
ll.op_store(new_val, dst_ptr);
|
||||
return true;
|
||||
@@ -1245,6 +1277,7 @@ BatchedBackendLLVM::llvm_store_value(llvm::Value* new_val, llvm::Value* dst_ptr,
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
BatchedBackendLLVM::llvm_store_mask(llvm::Value* new_mask, const Symbol& cond)
|
||||
{
|
||||
@@ -1259,6 +1292,7 @@ BatchedBackendLLVM::llvm_store_mask(llvm::Value* new_mask, const Symbol& cond)
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
BatchedBackendLLVM::llvm_store_component_value(llvm::Value* new_val,
|
||||
const Symbol& sym, int deriv,
|
||||
@@ -1302,6 +1336,8 @@ BatchedBackendLLVM::llvm_store_component_value(llvm::Value* new_val,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedBackendLLVM::llvm_broadcast_uniform_value_from_mem(
|
||||
llvm::Value* pointerTotempUniform, const Symbol& Destination,
|
||||
@@ -1349,6 +1385,8 @@ BatchedBackendLLVM::llvm_broadcast_uniform_value_from_mem(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedBackendLLVM::llvm_broadcast_uniform_value(llvm::Value* tempUniform,
|
||||
const Symbol& Destination,
|
||||
@@ -1361,6 +1399,8 @@ BatchedBackendLLVM::llvm_broadcast_uniform_value(llvm::Value* tempUniform,
|
||||
llvm_store_value(wide_value, Destination, derivs, nullptr, component);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedBackendLLVM::llvm_conversion_store_masked_status(llvm::Value* val,
|
||||
const Symbol& Status)
|
||||
@@ -1383,6 +1423,8 @@ BatchedBackendLLVM::llvm_conversion_store_masked_status(llvm::Value* val,
|
||||
llvm_store_value(mask, Status);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedBackendLLVM::llvm_conversion_store_uniform_status(llvm::Value* val,
|
||||
const Symbol& Status)
|
||||
@@ -1409,6 +1451,8 @@ BatchedBackendLLVM::llvm_conversion_store_uniform_status(llvm::Value* val,
|
||||
llvm_store_value(val, Status);
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::groupdata_field_ref(int fieldnum)
|
||||
{
|
||||
@@ -1416,6 +1460,7 @@ BatchedBackendLLVM::groupdata_field_ref(int fieldnum)
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::groupdata_field_ptr(int fieldnum, TypeDesc type,
|
||||
bool is_uniform)
|
||||
@@ -1431,6 +1476,8 @@ BatchedBackendLLVM::groupdata_field_ptr(int fieldnum, TypeDesc type,
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::temp_wide_matrix_ptr()
|
||||
{
|
||||
@@ -1444,6 +1491,7 @@ BatchedBackendLLVM::temp_wide_matrix_ptr()
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::temp_batched_texture_options_ptr()
|
||||
{
|
||||
@@ -1457,6 +1505,8 @@ BatchedBackendLLVM::temp_batched_texture_options_ptr()
|
||||
return m_llvm_temp_batched_texture_options_ptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::temp_batched_trace_options_ptr()
|
||||
{
|
||||
@@ -1471,6 +1521,7 @@ BatchedBackendLLVM::temp_batched_trace_options_ptr()
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::layer_run_ref(int layer)
|
||||
{
|
||||
@@ -1615,7 +1666,6 @@ BatchedBackendLLVM::llvm_call_function(const FuncSpec& name,
|
||||
valargs[i] = ll.void_ptr(tmpptr);
|
||||
}
|
||||
|
||||
|
||||
OSL_DEV_ONLY(std::cout << "....pushing " << s.name().c_str()
|
||||
<< " as void_ptr" << std::endl);
|
||||
} else {
|
||||
@@ -1717,7 +1767,8 @@ BatchedBackendLLVM::llvm_test_nonzero(const Symbol& val, bool test_derivs)
|
||||
llvm::Value* llvmValue = llvm_get_pointer(val);
|
||||
//OSL_DEV_ONLY(std::cout << "llvmValue type=" << ll.llvm_typenameof(llvmValue) << std::endl);
|
||||
|
||||
if (ll.llvm_typeof(llvmValue) == ll.type_ptr(ll.type_bool())) {
|
||||
if (ll.llvm_typeof(llvmValue)
|
||||
== (const llvm::Type*)ll.type_ptr(ll.type_bool())) {
|
||||
return ll.op_ne(llvm_load_value(val), ll.constant_bool(0));
|
||||
} else {
|
||||
return ll.op_ne(llvm_load_value(val), ll.constant(0));
|
||||
@@ -1763,14 +1814,16 @@ BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,
|
||||
llvm::Value* arrind = arrayindex >= 0 ? ll.constant(arrayindex) : NULL;
|
||||
|
||||
if (Result.typespec().is_closure() || Src.typespec().is_closure()) {
|
||||
OSL_ASSERT(0 && "unhandled case"); // TODO: implement
|
||||
|
||||
if (Src.typespec().is_closure()) {
|
||||
llvm::Value* srcval = llvm_load_value(Src, 0, arrind, 0);
|
||||
llvm::Value* srcval = llvm_load_value(Src, 0, arrind, 0,
|
||||
TypeDesc::UNKNOWN,
|
||||
op_is_uniform);
|
||||
llvm_store_value(srcval, Result, 0, arrind, 0);
|
||||
} else {
|
||||
llvm::Value* null = ll.constant_ptr(NULL, ll.type_void_ptr());
|
||||
llvm_store_value(null, Result, 0, arrind, 0);
|
||||
llvm::Value* null_value = ll.constant_ptr(NULL, ll.type_void_ptr());
|
||||
if (!op_is_uniform)
|
||||
null_value = ll.widen_value(null_value);
|
||||
llvm_store_value(null_value, Result, 0, arrind, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1795,7 +1848,7 @@ BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,
|
||||
return true;
|
||||
}
|
||||
|
||||
// memcpy complicated by promotion of uniform to wide during assignment, dissallow
|
||||
// memcpy complicated by promotion of uniform to wide during assignment, disallow
|
||||
|
||||
// The following code handles f=f, f=i, v=v, v=f, v=i, m=m, s=s.
|
||||
// Remember that llvm_load_value will automatically convert scalar->triple.
|
||||
@@ -1812,7 +1865,7 @@ BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,
|
||||
if (result_t.is_array() && src_t.is_array()) {
|
||||
start_array_index = 0;
|
||||
end_array_index = std::min(result_t.arraylength(),
|
||||
src_t.arraylength());
|
||||
src_t.arraylength());
|
||||
}
|
||||
}
|
||||
for (arrayindex = start_array_index; arrayindex < end_array_index;
|
||||
@@ -1853,7 +1906,7 @@ BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,
|
||||
// The llvm_load_value above should have handled bool to int conversions
|
||||
// when the basetype == Typedesc::INT
|
||||
|
||||
// write source float into all compnents when dstcomp == -1, otherwise
|
||||
// write source float into all components when dstcomp == -1, otherwise
|
||||
// the single element requested.
|
||||
if (dstcomp == -1) {
|
||||
for (int i = 0; i < num_components; ++i)
|
||||
@@ -1905,6 +1958,8 @@ BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
BatchedBackendLLVM::find_userdata_index(const Symbol& sym)
|
||||
{
|
||||
@@ -1921,6 +1976,7 @@ BatchedBackendLLVM::find_userdata_index(const Symbol& sym)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedBackendLLVM::append_arg_to(llvm::raw_svector_ostream& OS,
|
||||
const FuncSpec::Arg& arg)
|
||||
@@ -1949,6 +2005,8 @@ BatchedBackendLLVM::append_arg_to(llvm::raw_svector_ostream& OS,
|
||||
OS << name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char*
|
||||
BatchedBackendLLVM::build_name(const FuncSpec& fs)
|
||||
{
|
||||
|
||||
@@ -164,7 +164,7 @@ public:
|
||||
llvm::Value* llvm_load_mask(const Symbol& cond);
|
||||
|
||||
/// Return an llvm::Value* that is either a scalar and derivs is
|
||||
/// false, or a pointer to sym's values (if sym is an aggreate or
|
||||
/// false, or a pointer to sym's values (if sym is an aggregate or
|
||||
/// derivs == true). Furthermore, if deriv == true and sym doesn't
|
||||
/// have derivs, coerce it into a variable with zero derivs.
|
||||
llvm::Value* llvm_load_arg(const Symbol& sym, bool derivs,
|
||||
@@ -278,9 +278,9 @@ public:
|
||||
|
||||
public:
|
||||
TempScope(BatchedBackendLLVM& backend);
|
||||
TempScope(const TempScope& other) = delete;
|
||||
TempScope(const TempScope&& other) = delete;
|
||||
TempScope& operator=(const TempScope& other) = delete;
|
||||
TempScope(const TempScope& other) = delete;
|
||||
TempScope(const TempScope&& other) = delete;
|
||||
TempScope& operator=(const TempScope& other) = delete;
|
||||
TempScope& operator=(const TempScope&& other) = delete;
|
||||
~TempScope();
|
||||
};
|
||||
@@ -331,7 +331,7 @@ public:
|
||||
/// derivs are zero.
|
||||
llvm::Value* llvm_test_nonzero(const Symbol& val, bool test_derivs = false);
|
||||
|
||||
/// Implementaiton of Simple assignment. If arrayindex >= 0, in
|
||||
/// Implementation of Simple assignment. If arrayindex >= 0, in
|
||||
/// designates a particular array index to assign.
|
||||
bool llvm_assign_impl(const Symbol& Result, const Symbol& Src,
|
||||
int arrayindex = -1, int srccomp = -1,
|
||||
@@ -364,6 +364,7 @@ public:
|
||||
|
||||
llvm::Type* llvm_type_closure_component();
|
||||
llvm::Type* llvm_type_closure_component_ptr();
|
||||
llvm::Type* llvm_type_closure_component_wide_ptr();
|
||||
|
||||
/// Return the ShaderGlobals pointer cast as a void*.
|
||||
///
|
||||
@@ -415,13 +416,16 @@ public:
|
||||
|
||||
|
||||
/// Return the pointer to the block of shadeindices.
|
||||
llvm::Value *wide_shadeindex_ptr () const { return m_llvm_wide_shadeindex_ptr; }
|
||||
llvm::Value* wide_shadeindex_ptr() const
|
||||
{
|
||||
return m_llvm_wide_shadeindex_ptr;
|
||||
}
|
||||
|
||||
/// Return the userdata base pointer.
|
||||
llvm::Value *userdata_base_ptr () const { return m_llvm_userdata_base_ptr; }
|
||||
llvm::Value* userdata_base_ptr() const { return m_llvm_userdata_base_ptr; }
|
||||
|
||||
/// Return the output base pointer.
|
||||
llvm::Value *output_base_ptr () const { return m_llvm_output_base_ptr; }
|
||||
llvm::Value* output_base_ptr() const { return m_llvm_output_base_ptr; }
|
||||
|
||||
/// Return a pointer to an WideMatrix that was previously alloca
|
||||
/// on the stack, meant for generator to reuse as a temporary
|
||||
@@ -485,7 +489,7 @@ public:
|
||||
|
||||
// Encapsulate creation of function names that encode parameter types,
|
||||
// including if each is varying or uniform, and if a mask is required.
|
||||
// Utilize llvm::Twine to efficently combine multiple strings
|
||||
// Utilize llvm::Twine to efficiently combine multiple strings
|
||||
// Usage is to start with the function name then append arguments,
|
||||
// and at any point masking can be turned on/off as well as batching.
|
||||
// The effect of disabling batching would be the function name is
|
||||
@@ -529,7 +533,7 @@ public:
|
||||
ArgVector m_args;
|
||||
|
||||
public:
|
||||
FuncSpec(const FuncSpec&) = delete;
|
||||
FuncSpec(const FuncSpec&) = delete;
|
||||
FuncSpec& operator=(const FuncSpec&) = delete;
|
||||
|
||||
FuncSpec(const llvm::Twine& name)
|
||||
@@ -677,9 +681,8 @@ public:
|
||||
llvm::BasicBlock* llvm_exit_instance_block()
|
||||
{
|
||||
if (!m_exit_instance_block) {
|
||||
std::string name = Strutil::sprintf("%s_%d_exit_",
|
||||
inst()->layername(),
|
||||
inst()->id());
|
||||
std::string name = fmtformat("{}_{}_exit_", inst()->layername(),
|
||||
inst()->id());
|
||||
m_exit_instance_block = ll.new_basic_block(name);
|
||||
}
|
||||
return m_exit_instance_block;
|
||||
@@ -750,12 +753,11 @@ private:
|
||||
virtual const char* library_selector() const = 0;
|
||||
virtual void init_function_map(ShadingSystemImpl& shadingsys) const = 0;
|
||||
|
||||
static std::unique_ptr<TargetLibraryHelper> build(ShadingContext* context,
|
||||
int vector_width,
|
||||
TargetISA target_isa);
|
||||
static std::unique_ptr<TargetLibraryHelper>
|
||||
build(ShadingContext* context, int vector_width, TargetISA target_isa);
|
||||
};
|
||||
// TargetLibraryHelper is private, so need to be friend with Concrete
|
||||
template <int WidthT, TargetISA IsaT>
|
||||
template<int WidthT, TargetISA IsaT>
|
||||
friend class ConcreteTargetLibraryHelper;
|
||||
|
||||
std::unique_ptr<TargetLibraryHelper> m_target_lib_helper;
|
||||
@@ -780,9 +782,9 @@ private:
|
||||
llvm::Value* m_llvm_shaderglobals_ptr;
|
||||
llvm::Value* m_llvm_groupdata_ptr;
|
||||
|
||||
llvm::Value *m_llvm_wide_shadeindex_ptr;
|
||||
llvm::Value *m_llvm_userdata_base_ptr;
|
||||
llvm::Value *m_llvm_output_base_ptr;
|
||||
llvm::Value* m_llvm_wide_shadeindex_ptr;
|
||||
llvm::Value* m_llvm_userdata_base_ptr;
|
||||
llvm::Value* m_llvm_output_base_ptr;
|
||||
|
||||
// Reused allocas for temps used to pass options or intermediates
|
||||
llvm::Value* m_llvm_temp_wide_matrix_ptr; // for gen_tranform
|
||||
|
||||
+3981
-3090
File diff suppressed because it is too large
Load Diff
@@ -31,7 +31,7 @@
|
||||
#include "batched_backendllvm.h"
|
||||
#include "oslexec_pvt.h"
|
||||
|
||||
// Create extrenal declarations for all built-in funcs we may call from LLVM
|
||||
// Create external declarations for all built-in funcs we may call from LLVM
|
||||
#define DECL(name, signature) extern "C" void name();
|
||||
#include "builtindecl.h"
|
||||
#undef DECL
|
||||
@@ -142,6 +142,8 @@ possibly_wide_type_from_code(const char* code, int* advance, bool& is_uniform)
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct HelperFuncRecord {
|
||||
const char* argtypes;
|
||||
void (*function)();
|
||||
@@ -168,6 +170,8 @@ struct HelperFuncRecord {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// As we will be using compile time const char * to populate the HelperFuncMap
|
||||
// We avoid std::string (which would create a copy), and instead just store
|
||||
// the const char *, however we must supply our own hashing and equality
|
||||
@@ -188,6 +192,8 @@ struct CStrHash {
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CStrEquality {
|
||||
OSL_FORCEINLINE bool operator()(const char* lhs, const char* rhs) const
|
||||
{
|
||||
@@ -195,12 +201,15 @@ struct CStrEquality {
|
||||
return is_equal;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef std::unordered_map<const char*, HelperFuncRecord, CStrHash, CStrEquality>
|
||||
HelperFuncMap;
|
||||
static HelperFuncMap llvm_helper_function_map;
|
||||
static atomic_int llvm_helper_function_map_initialized(0);
|
||||
static spin_mutex llvm_helper_function_map_mutex;
|
||||
|
||||
|
||||
static void
|
||||
initialize_llvm_helper_function_map()
|
||||
{
|
||||
@@ -217,11 +226,14 @@ initialize_llvm_helper_function_map()
|
||||
llvm_helper_function_map_initialized = 1;
|
||||
}
|
||||
|
||||
|
||||
struct NameAndSignature {
|
||||
const char* name;
|
||||
const char* signature;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// As we don't now the sizeof ConcreteT::library_functions until specialization,
|
||||
// we need a helper template function to defer its resolution
|
||||
template<typename ConcreteT>
|
||||
@@ -254,7 +266,6 @@ init_wide_function_map(const ConcreteT&, ShadingSystemImpl& shadingsys)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
auto shared_lib = OIIO::Plugin::open(filename, /*global=*/false);
|
||||
if (shared_lib == 0) {
|
||||
shadingsys.errorfmt("{} could not be loaded with error \"{}\"",
|
||||
@@ -287,6 +298,8 @@ init_wide_function_map(const ConcreteT&, ShadingSystemImpl& shadingsys)
|
||||
is_initialized = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT, TargetISA IsaT>
|
||||
class ConcreteTargetLibraryHelper final
|
||||
: public BatchedBackendLLVM::TargetLibraryHelper {
|
||||
@@ -312,6 +325,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Specialize ConcreteTargetLibraryHelper<>::library_functions and
|
||||
// ConcreteTargetLibraryHelper<>::library_selector_string for each
|
||||
// WidthT and TargetISA that we are building a shared library for.
|
||||
@@ -511,6 +526,8 @@ const char*
|
||||
= "b8_AVX_";
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
std::unique_ptr<BatchedBackendLLVM::TargetLibraryHelper>
|
||||
BatchedBackendLLVM::TargetLibraryHelper::build(ShadingContext* context,
|
||||
int vector_width,
|
||||
@@ -531,8 +548,7 @@ BatchedBackendLLVM::TargetLibraryHelper::build(ShadingContext* context,
|
||||
return RetType(
|
||||
new ConcreteTargetLibraryHelper<16, TargetISA::AVX512_noFMA>());
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
@@ -562,18 +578,20 @@ BatchedBackendLLVM::TargetLibraryHelper::build(ShadingContext* context,
|
||||
return RetType(
|
||||
new ConcreteTargetLibraryHelper<8, TargetISA::AVX>());
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
default: OSL_ASSERT(0 && "unsupported vector width");
|
||||
}
|
||||
std::cerr << "Build is not configured to support TargetISA of " <<
|
||||
LLVM_Util::target_isa_name(target_isa) << " and batch_size of " << vector_width << std::endl << std::flush;
|
||||
std::cerr << "Build is not configured to support TargetISA of "
|
||||
<< LLVM_Util::target_isa_name(target_isa) << " and batch_size of "
|
||||
<< vector_width << std::endl
|
||||
<< std::flush;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void*
|
||||
helper_function_lookup(const std::string& name)
|
||||
{
|
||||
@@ -619,12 +637,12 @@ BatchedBackendLLVM::llvm_type_sg()
|
||||
sg_types.push_back(vp); // opaque objdata*
|
||||
sg_types.push_back(vp); // ShadingContext*
|
||||
sg_types.push_back(vp); // RendererServices*
|
||||
sg_types.push_back(vp); // Ci
|
||||
sg_types.push_back(ll.type_int()); // raytype
|
||||
sg_types.push_back(ll.type_int()); // pad0
|
||||
sg_types.push_back(ll.type_int()); // pad1
|
||||
sg_types.push_back(ll.type_int()); // pad2
|
||||
|
||||
sg_types.push_back(ll.type_int()); // pad3
|
||||
sg_types.push_back(ll.type_int()); // pad4
|
||||
|
||||
// VaryingShaderGlobals of the batch
|
||||
sg_types.push_back(wide_triple_deriv); // P, dPdx, dPdy
|
||||
@@ -644,6 +662,8 @@ BatchedBackendLLVM::llvm_type_sg()
|
||||
sg_types.push_back(wide_vp); // object2common
|
||||
sg_types.push_back(wide_vp); // shader2common
|
||||
|
||||
sg_types.push_back(wide_vp); // Ci
|
||||
|
||||
sg_types.push_back(ll.type_wide_float()); // surfacearea
|
||||
sg_types.push_back(ll.type_wide_int()); // flipHandedness
|
||||
sg_types.push_back(ll.type_wide_int()); // backfacing
|
||||
@@ -653,6 +673,7 @@ BatchedBackendLLVM::llvm_type_sg()
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Type*
|
||||
BatchedBackendLLVM::llvm_type_batched_texture_options()
|
||||
{
|
||||
@@ -697,7 +718,6 @@ BatchedBackendLLVM::llvm_type_batched_texture_options()
|
||||
= ll.type_struct(sg_types, "BatchedTextureOptions",
|
||||
false /*is_packed*/);
|
||||
|
||||
|
||||
#if 0 && defined(OSL_DEV)
|
||||
std::cout << std::endl << std::endl << "llvm's data layout of BatchedTextureOptions" << std::endl;
|
||||
ll.dump_struct_data_layout(llvm_type_batched_texture_options());
|
||||
@@ -728,6 +748,7 @@ BatchedBackendLLVM::llvm_type_batched_texture_options()
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Type*
|
||||
BatchedBackendLLVM::llvm_type_batched_trace_options()
|
||||
{
|
||||
@@ -739,11 +760,10 @@ BatchedBackendLLVM::llvm_type_batched_trace_options()
|
||||
std::vector<llvm::Type*> sg_types;
|
||||
|
||||
// Uniform values of the batch
|
||||
sg_types.push_back(ll.type_float()); // mindist
|
||||
sg_types.push_back(ll.type_float()); // maxdist
|
||||
sg_types.push_back(ll.type_int()); // shade
|
||||
sg_types.push_back(
|
||||
reinterpret_cast<llvm::Type*>(ll.type_string())); // traceset
|
||||
sg_types.push_back(ll.type_float()); // mindist
|
||||
sg_types.push_back(ll.type_float()); // maxdist
|
||||
sg_types.push_back(ll.type_int()); // shade
|
||||
sg_types.push_back(ll.type_ustring()); // traceset
|
||||
|
||||
m_llvm_type_batched_trace_options = ll.type_struct(sg_types, "TraceOptions",
|
||||
false /*is_packed*/);
|
||||
@@ -773,6 +793,7 @@ BatchedBackendLLVM::llvm_type_batched_trace_options()
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Type*
|
||||
BatchedBackendLLVM::llvm_type_sg_ptr()
|
||||
{
|
||||
@@ -872,11 +893,11 @@ BatchedBackendLLVM::llvm_type_groupdata()
|
||||
fields.push_back(llvm_wide_type(ts));
|
||||
|
||||
// Alignment
|
||||
// TODO: this isn't quite right, cant rely on batch size to == ISA SIMD requirements
|
||||
size_t align = sym.typespec().is_closure_based()
|
||||
? sizeof(void*)
|
||||
: sym.typespec().simpletype().basesize()
|
||||
* m_width;
|
||||
// TODO: this isn't quite right, can't rely on batch size to == ISA SIMD requirements
|
||||
size_t base_size = sym.typespec().is_closure_based()
|
||||
? sizeof(void*)
|
||||
: sym.typespec().simpletype().basesize();
|
||||
size_t align = base_size * m_width;
|
||||
if (offset & (align - 1))
|
||||
offset += align - (offset & (align - 1));
|
||||
if (llvm_debug() >= 2)
|
||||
@@ -894,14 +915,13 @@ BatchedBackendLLVM::llvm_type_groupdata()
|
||||
}
|
||||
group().llvm_groupdata_wide_size(offset);
|
||||
if (llvm_debug() >= 2)
|
||||
std::cout << " Group struct had " << order << " fields, total size "
|
||||
<< offset << "\n\n";
|
||||
OSL::print(" Group struct had {} fields, total size {}\n\n", order,
|
||||
offset);
|
||||
|
||||
std::string groupdataname
|
||||
= Strutil::sprintf("Groupdata_%llu",
|
||||
(long long unsigned int)group().name().hash());
|
||||
m_llvm_type_groupdata = ll.type_struct(fields, groupdataname,
|
||||
false /*is_packed*/);
|
||||
std::string groupdataname = fmtformat("Groupdata_{}",
|
||||
group().name().hash());
|
||||
m_llvm_type_groupdata = ll.type_struct(fields, groupdataname,
|
||||
false /*is_packed*/);
|
||||
|
||||
return m_llvm_type_groupdata;
|
||||
}
|
||||
@@ -940,6 +960,13 @@ BatchedBackendLLVM::llvm_type_closure_component_ptr()
|
||||
}
|
||||
|
||||
|
||||
llvm::Type*
|
||||
BatchedBackendLLVM::llvm_type_closure_component_wide_ptr()
|
||||
{
|
||||
return ll.type_wide(llvm_type_closure_component_ptr());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedBackendLLVM::llvm_assign_initial_value(
|
||||
@@ -965,7 +992,7 @@ BatchedBackendLLVM::llvm_assign_initial_value(
|
||||
return;
|
||||
}
|
||||
|
||||
bool isarray = sym.typespec().is_array();
|
||||
bool isarray = sym.typespec().is_array();
|
||||
if ((sym.symtype() == SymTypeLocal || sym.symtype() == SymTypeTemp)
|
||||
&& shadingsys().debug_uninit()) {
|
||||
// Handle the "debug uninitialized values" case
|
||||
@@ -1030,7 +1057,7 @@ BatchedBackendLLVM::llvm_assign_initial_value(
|
||||
// generating the get_userdata callback?
|
||||
llvm::BasicBlock* after_userdata_block = nullptr;
|
||||
bool partial_userdata_mask_was_pushed = false;
|
||||
const SymLocationDesc* symloc = nullptr;
|
||||
const SymLocationDesc* symloc = nullptr;
|
||||
LLVM_Util::ScopedMasking partial_data_masking_scope;
|
||||
if (!sym.lockgeom() && !sym.typespec().is_closure()) {
|
||||
ustring symname = sym.name();
|
||||
@@ -1045,57 +1072,66 @@ BatchedBackendLLVM::llvm_assign_initial_value(
|
||||
llvm::Value* got_userdata = nullptr;
|
||||
// See if userdata input placement has been used for this symbol
|
||||
ustring layersym = ustring::fmtformat("{}.{}", inst()->layername(),
|
||||
sym.name());
|
||||
symloc = group().find_symloc(layersym, SymArena::UserData);
|
||||
if (! symloc)
|
||||
sym.name());
|
||||
symloc = group().find_symloc(layersym, SymArena::UserData);
|
||||
if (!symloc)
|
||||
symloc = group().find_symloc(sym.name(), SymArena::UserData);
|
||||
if (symloc) {
|
||||
// We had a userdata pre-placement record for this variable.
|
||||
// Just copy from the correct offset location!
|
||||
|
||||
// Strutil::print("GEN found placeable userdata input {} -> {} {} size={}\n",
|
||||
// sym.name(), symloc->name, sym.typespec(),
|
||||
// symloc->type.size());
|
||||
const int deriv_count = (symloc->derivs && sym.has_derivs()) ? 3 : 1;
|
||||
// OSL::print("GEN found placeable userdata input {} -> {} {} size={}\n",
|
||||
// sym.name(), symloc->name, sym.typespec(),
|
||||
// symloc->type.size());
|
||||
const int deriv_count = (symloc->derivs && sym.has_derivs()) ? 3
|
||||
: 1;
|
||||
|
||||
llvm::Value* sym_offset = ll.constanti64(symloc->offset);
|
||||
llvm::Value* userdata_sym_base_ptr = ll.ptr_cast(ll.offset_ptr(m_llvm_userdata_base_ptr, sym_offset), type.scalartype());
|
||||
llvm::Value* userdata_sym_base_ptr
|
||||
= ll.ptr_cast(ll.offset_ptr(m_llvm_userdata_base_ptr,
|
||||
sym_offset),
|
||||
type.scalartype());
|
||||
bool isBase32bit = (symloc->type != TypeDesc::STRING);
|
||||
int bytesPerElem = isBase32bit ? 4 : 8;
|
||||
// TODO: could move assert inside SymLocation
|
||||
OSL_ASSERT((symloc->stride % bytesPerElem) == 0);
|
||||
|
||||
llvm::Value* wide_shadeindex = ll.op_load(ll.type_wide_int(), m_llvm_wide_shadeindex_ptr);
|
||||
const int elem_stride = static_cast<int>(symloc->stride/bytesPerElem);
|
||||
llvm::Value* wide_shadeindex
|
||||
= ll.op_load(ll.type_wide_int(), m_llvm_wide_shadeindex_ptr);
|
||||
const int elem_stride = static_cast<int>(symloc->stride
|
||||
/ bytesPerElem);
|
||||
llvm::Value* wide_index_for_userdata = nullptr;
|
||||
if (elem_stride == 1) {
|
||||
wide_index_for_userdata = wide_shadeindex;
|
||||
} else {
|
||||
llvm::Value* element_stride = ll.wide_constant(elem_stride);
|
||||
wide_index_for_userdata = ll.op_mul(element_stride, wide_shadeindex);
|
||||
wide_index_for_userdata = ll.op_mul(element_stride,
|
||||
wide_shadeindex);
|
||||
}
|
||||
|
||||
const int elem_count = static_cast<int>(type.numelements());
|
||||
const int comp_count = type.aggregate;
|
||||
const int elem_count = static_cast<int>(type.numelements());
|
||||
const int comp_count = type.aggregate;
|
||||
|
||||
int c = 0;
|
||||
for (int d = 0; d < deriv_count; ++d) {
|
||||
for (int a = 0; a < elem_count; ++a) {
|
||||
llvm::Value* arrind = isarray ? ll.constant(a)
|
||||
: nullptr;
|
||||
llvm::Value* arrind = isarray ? ll.constant(a) : nullptr;
|
||||
for (int i = 0; i < comp_count; ++i, ++c) {
|
||||
llvm::Value* wide_index = wide_index_for_userdata;
|
||||
if (c != 0) {
|
||||
wide_index = ll.op_add(wide_index_for_userdata, ll.wide_constant(c));
|
||||
wide_index = ll.op_add(wide_index_for_userdata,
|
||||
ll.wide_constant(c));
|
||||
}
|
||||
// For ISA without a native mask (AVX & AVX2), this gather op will
|
||||
// clamp the indices of masked off lanes to 0.
|
||||
// This means the user data base pointer + sym_offset
|
||||
// must be dereferencable with a shadeindex of 0.
|
||||
llvm::Value *wide_val = ll.op_gather(userdata_sym_base_ptr, wide_index);
|
||||
// must be dereferenceable with a shadeindex of 0.
|
||||
llvm::Value* wide_val
|
||||
= ll.op_gather(userdata_sym_base_ptr, wide_index);
|
||||
|
||||
llvm_store_value(wide_val, sym, d, arrind,
|
||||
/*component*/i, /*index_is_uniform*/true);
|
||||
/*component*/ i,
|
||||
/*index_is_uniform*/ true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1148,11 +1184,12 @@ BatchedBackendLLVM::llvm_assign_initial_value(
|
||||
// happen if the userdata was retrieved.
|
||||
llvm::BasicBlock* partial_userdata_block = ll.new_basic_block(
|
||||
"partial_userdata");
|
||||
after_userdata_block = ll.new_basic_block();
|
||||
after_userdata_block = ll.new_basic_block();
|
||||
OSL_ASSERT(got_userdata != nullptr);
|
||||
llvm::Value* cond_val = ll.op_ne(got_userdata,
|
||||
llvm_initial_shader_mask_value);
|
||||
ll.op_branch(cond_val, partial_userdata_block, after_userdata_block);
|
||||
ll.op_branch(cond_val, partial_userdata_block,
|
||||
after_userdata_block);
|
||||
|
||||
// If we got no or partial user data, we need to mask out the lanes
|
||||
// that successfully got user data from the initops or default value
|
||||
@@ -1161,7 +1198,8 @@ BatchedBackendLLVM::llvm_assign_initial_value(
|
||||
ll.push_mask(
|
||||
got_userdata_mask, /* negate */
|
||||
true /*, absolute = false (not sure how it wouldn't be an absolute mask) */);
|
||||
partial_data_masking_scope = ll.create_masking_scope(/*enabled=*/true);
|
||||
partial_data_masking_scope = ll.create_masking_scope(
|
||||
/*enabled=*/true);
|
||||
partial_userdata_mask_was_pushed = true;
|
||||
}
|
||||
}
|
||||
@@ -1203,25 +1241,28 @@ BatchedBackendLLVM::llvm_assign_initial_value(
|
||||
continue;
|
||||
for (int i = 0; i < num_components; ++i, ++c) {
|
||||
llvm::Value* init_val = nullptr;
|
||||
if(! sym.lockgeom() && ! sym.typespec().is_closure()) {
|
||||
if (!sym.lockgeom() && !sym.typespec().is_closure()) {
|
||||
// Reload value from symbol memory as reparam
|
||||
// may have changed it
|
||||
llvm::PointerType * ptr_type = nullptr;
|
||||
llvm::Type * data_type = nullptr;
|
||||
llvm::PointerType* ptr_type = nullptr;
|
||||
llvm::Type* data_type = nullptr;
|
||||
if (elemtype.is_float_based()) {
|
||||
ptr_type = ll.type_float_ptr();
|
||||
ptr_type = ll.type_float_ptr();
|
||||
data_type = ll.type_float();
|
||||
} else if (elemtype.is_string()) {
|
||||
ptr_type = ll.type_ustring_ptr();
|
||||
data_type = static_cast<llvm::Type *>(ll.type_string());
|
||||
ptr_type = ll.type_ustring_ptr();
|
||||
data_type = ll.type_ustring();
|
||||
} else if (elemtype.is_int()) {
|
||||
ptr_type = ll.type_int_ptr();
|
||||
ptr_type = ll.type_int_ptr();
|
||||
data_type = ll.type_int();
|
||||
}
|
||||
OSL_ASSERT(ptr_type && data_type);
|
||||
|
||||
llvm::Value * sym_data_src = ll.GEP(data_type, ll.constant_ptr (sym.dataptr(), ptr_type), c);
|
||||
init_val = ll.op_load (data_type, sym_data_src);
|
||||
llvm::Value* sym_data_src
|
||||
= ll.GEP(data_type,
|
||||
ll.constant_ptr(sym.dataptr(), ptr_type),
|
||||
c);
|
||||
init_val = ll.op_load(data_type, sym_data_src);
|
||||
OSL_ASSERT(init_val);
|
||||
if (sym.is_varying()) {
|
||||
init_val = ll.widen_value(init_val);
|
||||
@@ -1263,8 +1304,7 @@ BatchedBackendLLVM::llvm_assign_initial_value(
|
||||
// next basic block now.
|
||||
ll.op_branch(after_userdata_block);
|
||||
// NOTE: we must be in the after block to apply the exit mask
|
||||
if (ll.masked_exit_count() > exit_count_before_init_ops)
|
||||
{
|
||||
if (ll.masked_exit_count() > exit_count_before_init_ops) {
|
||||
// At some point one or more calls to exit have been made
|
||||
// we need to apply that exit mask the the current function scope's mask
|
||||
ll.apply_exit_to_mask_stack();
|
||||
@@ -1296,11 +1336,11 @@ BatchedBackendLLVM::llvm_generate_debugnan(const Opcode& op)
|
||||
if (op.opname() == op_aassign) {
|
||||
// Special case -- array assignment -- only check one element
|
||||
OSL_ASSERT(i == 0 && "only arg 0 is written for aassign");
|
||||
Symbol& index_sym = *opargsym(op, 1);
|
||||
llvm::Value* ind = llvm_load_value(index_sym);
|
||||
llvm::Value* agg = index_sym.is_uniform()
|
||||
? ll.constant(t.aggregate)
|
||||
: ll.wide_constant(t.aggregate);
|
||||
Symbol& index_sym = *opargsym(op, 1);
|
||||
llvm::Value* ind = llvm_load_value(index_sym);
|
||||
llvm::Value* agg = index_sym.is_uniform()
|
||||
? ll.constant(t.aggregate)
|
||||
: ll.wide_constant(t.aggregate);
|
||||
llvm::Value* scaled_offset = t.aggregate == 1 ? ind
|
||||
: ll.op_mul(ind, agg);
|
||||
if (index_sym.is_uniform()) {
|
||||
@@ -1471,9 +1511,9 @@ BatchedBackendLLVM::llvm_generate_debug_uninit(const Opcode& op)
|
||||
Symbol& index_sym = *opargsym(op, 2);
|
||||
llvm::Value* ind = llvm_load_value(index_sym);
|
||||
|
||||
llvm::Value* agg = index_sym.is_uniform()
|
||||
? ll.constant(t.aggregate)
|
||||
: ll.wide_constant(t.aggregate);
|
||||
llvm::Value* agg = index_sym.is_uniform()
|
||||
? ll.constant(t.aggregate)
|
||||
: ll.wide_constant(t.aggregate);
|
||||
llvm::Value* scaled_offset = t.aggregate == 1 ? ind
|
||||
: ll.op_mul(ind, agg);
|
||||
if (index_sym.is_uniform()) {
|
||||
@@ -1616,6 +1656,7 @@ BatchedBackendLLVM::llvm_generate_debug_uninit(const Opcode& op)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedBackendLLVM::llvm_generate_debug_op_printf(const Opcode& op)
|
||||
{
|
||||
@@ -1627,6 +1668,7 @@ BatchedBackendLLVM::llvm_generate_debug_op_printf(const Opcode& op)
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
BatchedBackendLLVM::build_llvm_code(int beginop, int endop,
|
||||
llvm::BasicBlock* bb)
|
||||
@@ -1670,8 +1712,9 @@ BatchedBackendLLVM::build_llvm_code(int beginop, int endop,
|
||||
} else if (op.opname() == op_nop || op.opname() == op_end) {
|
||||
// Skip this op, it does nothing...
|
||||
} else {
|
||||
shadingcontext()->errorfmt("LLVMOSL: Unsupported op {} in layer {}\n",
|
||||
op.opname(), inst()->layername());
|
||||
shadingcontext()->errorfmt(
|
||||
"LLVMOSL: Unsupported op {} in layer {}\n", op.opname(),
|
||||
inst()->layername());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1693,18 +1736,18 @@ BatchedBackendLLVM::build_llvm_init()
|
||||
// Make a group init function: void group_init(ShaderGlobals*, GroupData*)
|
||||
// Note that the GroupData* is passed as a void*.
|
||||
OSL_ASSERT(m_library_selector);
|
||||
std::string unique_name = Strutil::sprintf("%s_group_%d_init",
|
||||
m_library_selector,
|
||||
group().id());
|
||||
ll.current_function(ll.make_function(unique_name, false,
|
||||
ll.type_void(), // return type
|
||||
{ llvm_type_sg_ptr(),
|
||||
llvm_type_groupdata_ptr(),
|
||||
static_cast<llvm::Type *>(ll.type_void_ptr()), // wide_shader_index
|
||||
static_cast<llvm::Type *>(ll.type_void_ptr()), // userdata_base_ptr
|
||||
static_cast<llvm::Type *>(ll.type_void_ptr()), // output_base_ptr
|
||||
ll.type_int() // mask
|
||||
}));
|
||||
std::string unique_name = fmtformat("{}_group_{}_init", m_library_selector,
|
||||
group().id());
|
||||
ll.current_function(ll.make_function(
|
||||
unique_name, false,
|
||||
ll.type_void(), // return type
|
||||
{
|
||||
llvm_type_sg_ptr(), llvm_type_groupdata_ptr(),
|
||||
static_cast<llvm::Type*>(ll.type_void_ptr()), // wide_shader_index
|
||||
static_cast<llvm::Type*>(ll.type_void_ptr()), // userdata_base_ptr
|
||||
static_cast<llvm::Type*>(ll.type_void_ptr()), // output_base_ptr
|
||||
ll.type_int() // mask
|
||||
}));
|
||||
|
||||
if (ll.debug_is_enabled()) {
|
||||
ustring file_name
|
||||
@@ -1714,11 +1757,11 @@ BatchedBackendLLVM::build_llvm_init()
|
||||
}
|
||||
|
||||
// Get shader globals and groupdata pointers
|
||||
m_llvm_shaderglobals_ptr = ll.current_function_arg(0); //arg_it++;
|
||||
m_llvm_groupdata_ptr = ll.current_function_arg(1); //arg_it++;
|
||||
m_llvm_wide_shadeindex_ptr = ll.current_function_arg(2); //arg_it++;
|
||||
m_llvm_userdata_base_ptr = ll.current_function_arg(3); //arg_it++;
|
||||
m_llvm_output_base_ptr = ll.current_function_arg(4); //arg_it++;
|
||||
m_llvm_shaderglobals_ptr = ll.current_function_arg(0); //arg_it++;
|
||||
m_llvm_groupdata_ptr = ll.current_function_arg(1); //arg_it++;
|
||||
m_llvm_wide_shadeindex_ptr = ll.current_function_arg(2); //arg_it++;
|
||||
m_llvm_userdata_base_ptr = ll.current_function_arg(3); //arg_it++;
|
||||
m_llvm_output_base_ptr = ll.current_function_arg(4); //arg_it++;
|
||||
|
||||
// TODO: do we need to utilize the shader mask in the init function?
|
||||
//llvm::Value * llvm_initial_shader_mask_value = ll.current_function_arg(5); //arg_it++;
|
||||
@@ -1733,14 +1776,16 @@ BatchedBackendLLVM::build_llvm_init()
|
||||
ll.new_builder(entry_bb);
|
||||
|
||||
// Fixup type of wide shadeindex, we had to wait until we were in a basic block
|
||||
m_llvm_wide_shadeindex_ptr = ll.ptr_cast(m_llvm_wide_shadeindex_ptr, ll.type_wide_int_ptr()); //arg_it++;
|
||||
m_llvm_wide_shadeindex_ptr
|
||||
= ll.ptr_cast(m_llvm_wide_shadeindex_ptr,
|
||||
ll.type_wide_int_ptr()); //arg_it++;
|
||||
|
||||
ll.assume_ptr_is_aligned(m_llvm_shaderglobals_ptr, 64);
|
||||
ll.assume_ptr_is_aligned(m_llvm_groupdata_ptr, 64);
|
||||
|
||||
#if 0 /* helpful for debugging */
|
||||
if (llvm_debug()) {
|
||||
llvm_gen_debug_printf (Strutil::sprintf("\n\n\n\nGROUP! %s",group().name()));
|
||||
llvm_gen_debug_printf (fmtformat("\n\n\n\nGROUP! {}",group().name()));
|
||||
llvm_gen_debug_printf ("enter group initlayer %d %s %s"); this->layer(), inst()->layername(), inst()->shadername()));
|
||||
}
|
||||
#endif
|
||||
@@ -1770,6 +1815,8 @@ BatchedBackendLLVM::build_llvm_init()
|
||||
if (sym.typespec().is_closure_based()) {
|
||||
int arraylen = std::max(1, sym.typespec().arraylength());
|
||||
llvm::Value* val = ll.constant_ptr(NULL, ll.type_void_ptr());
|
||||
if (!sym.is_uniform())
|
||||
val = ll.widen_value(val);
|
||||
for (int a = 0; a < arraylen; ++a) {
|
||||
llvm::Value* arrind = sym.typespec().is_array()
|
||||
? ll.constant(a)
|
||||
@@ -1780,19 +1827,16 @@ BatchedBackendLLVM::build_llvm_init()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// All done
|
||||
#if 0 /* helpful for debugging */
|
||||
if (llvm_debug())
|
||||
llvm_gen_debug_printf (Strutil::sprintf("exit group init %s",
|
||||
group().name());
|
||||
llvm_gen_debug_printf(fmtformat("exit group init {}", group().name());
|
||||
#endif
|
||||
ll.op_return();
|
||||
|
||||
if (llvm_debug())
|
||||
std::cout << "group init func (" << unique_name << ") "
|
||||
<< " after llvm = "
|
||||
<< ll.bitcode_string(ll.current_function()) << "\n";
|
||||
OSL::print("group init func ({}) after llvm = {}\n", unique_name,
|
||||
ll.bitcode_string(ll.current_function()));
|
||||
|
||||
if (ll.debug_is_enabled()) {
|
||||
ll.debug_pop_function();
|
||||
@@ -1811,6 +1855,7 @@ BatchedBackendLLVM::build_llvm_init()
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Function*
|
||||
BatchedBackendLLVM::build_llvm_instance(bool groupentry)
|
||||
{
|
||||
@@ -1818,35 +1863,35 @@ BatchedBackendLLVM::build_llvm_instance(bool groupentry)
|
||||
// Note that the GroupData* is passed as a void*.
|
||||
OSL_ASSERT(m_library_selector);
|
||||
std::string unique_layer_name
|
||||
= Strutil::sprintf("%s_%s%s", m_library_selector,
|
||||
(groupentry ? "__direct_callable__" : ""),
|
||||
layer_function_name().c_str());
|
||||
= fmtformat("{}_{}{}", m_library_selector,
|
||||
(groupentry ? "__direct_callable__" : ""),
|
||||
layer_function_name());
|
||||
|
||||
bool is_entry_layer = group().is_entry_layer(layer());
|
||||
ll.current_function(
|
||||
ll.make_function(unique_layer_name,
|
||||
!is_entry_layer, // fastcall for non-entry layer functions
|
||||
ll.type_void(), // return type
|
||||
{ llvm_type_sg_ptr(), llvm_type_groupdata_ptr(),
|
||||
static_cast<llvm::Type *>(ll.type_void_ptr()), // wide_shader_index
|
||||
static_cast<llvm::Type *>(ll.type_void_ptr()), // userdata_base_ptr
|
||||
static_cast<llvm::Type *>(ll.type_void_ptr()), // output_base_ptr
|
||||
ll.type_int() // mask
|
||||
}));
|
||||
ll.current_function(ll.make_function(
|
||||
unique_layer_name,
|
||||
!is_entry_layer, // fastcall for non-entry layer functions
|
||||
ll.type_void(), // return type
|
||||
{
|
||||
llvm_type_sg_ptr(), llvm_type_groupdata_ptr(),
|
||||
static_cast<llvm::Type*>(ll.type_void_ptr()), // wide_shader_index
|
||||
static_cast<llvm::Type*>(ll.type_void_ptr()), // userdata_base_ptr
|
||||
static_cast<llvm::Type*>(ll.type_void_ptr()), // output_base_ptr
|
||||
ll.type_int() // mask
|
||||
}));
|
||||
|
||||
if (ll.debug_is_enabled()) {
|
||||
const Opcode& mainbegin (inst()->op(inst()->maincodebegin()));
|
||||
const Opcode& mainbegin(inst()->op(inst()->maincodebegin()));
|
||||
ll.debug_push_function(unique_layer_name, mainbegin.sourcefile(),
|
||||
mainbegin.sourceline());
|
||||
}
|
||||
|
||||
|
||||
// Get shader globals and groupdata pointers
|
||||
m_llvm_shaderglobals_ptr = ll.current_function_arg(0); //arg_it++;
|
||||
m_llvm_groupdata_ptr = ll.current_function_arg(1); //arg_it++;
|
||||
m_llvm_wide_shadeindex_ptr = ll.current_function_arg(2); //arg_it++;
|
||||
m_llvm_userdata_base_ptr = ll.current_function_arg(3); //arg_it++;
|
||||
m_llvm_output_base_ptr = ll.current_function_arg(4); //arg_it++;
|
||||
m_llvm_shaderglobals_ptr = ll.current_function_arg(0); //arg_it++;
|
||||
m_llvm_groupdata_ptr = ll.current_function_arg(1); //arg_it++;
|
||||
m_llvm_wide_shadeindex_ptr = ll.current_function_arg(2); //arg_it++;
|
||||
m_llvm_userdata_base_ptr = ll.current_function_arg(3); //arg_it++;
|
||||
m_llvm_output_base_ptr = ll.current_function_arg(4); //arg_it++;
|
||||
|
||||
llvm::Value* llvm_initial_shader_mask_value = ll.current_function_arg(
|
||||
5); //arg_it++;
|
||||
@@ -1863,7 +1908,9 @@ BatchedBackendLLVM::build_llvm_instance(bool groupentry)
|
||||
ll.new_builder(entry_bb);
|
||||
|
||||
// Fixup type of wide shadeindex, we had to wait until we were in a basic block
|
||||
m_llvm_wide_shadeindex_ptr = ll.ptr_cast(m_llvm_wide_shadeindex_ptr, ll.type_wide_int_ptr()); //arg_it++;
|
||||
m_llvm_wide_shadeindex_ptr
|
||||
= ll.ptr_cast(m_llvm_wide_shadeindex_ptr,
|
||||
ll.type_wide_int_ptr()); //arg_it++;
|
||||
|
||||
ll.assume_ptr_is_aligned(m_llvm_shaderglobals_ptr, 64);
|
||||
ll.assume_ptr_is_aligned(m_llvm_groupdata_ptr, 64);
|
||||
@@ -1898,16 +1945,17 @@ BatchedBackendLLVM::build_llvm_instance(bool groupentry)
|
||||
// and then run the layer.
|
||||
if (shadingsys().llvm_debug_layers())
|
||||
llvm_gen_debug_printf(
|
||||
Strutil::sprintf("checking for already-run layer %d %s %s",
|
||||
this->layer(), inst()->layername(),
|
||||
inst()->shadername()));
|
||||
fmtformat("checking for already-run layer {} {} {}",
|
||||
this->layer(), inst()->layername(),
|
||||
inst()->shadername()));
|
||||
llvm::Value* previously_executed = ll.int_as_mask(
|
||||
previously_executed_value);
|
||||
llvm::Value* required_lanes_executed
|
||||
= ll.op_select(initial_shader_mask, previously_executed,
|
||||
ll.wide_constant_bool(false));
|
||||
llvm::Value* all_required_lanes_already_executed
|
||||
= ll.op_eq(ll.mask_as_int(initial_shader_mask), ll.mask_as_int(required_lanes_executed));
|
||||
= ll.op_eq(ll.mask_as_int(initial_shader_mask),
|
||||
ll.mask_as_int(required_lanes_executed));
|
||||
|
||||
llvm::BasicBlock* then_block = ll.new_basic_block();
|
||||
llvm::BasicBlock* after_block = ll.new_basic_block();
|
||||
@@ -1916,17 +1964,17 @@ BatchedBackendLLVM::build_llvm_instance(bool groupentry)
|
||||
// insert point is now then_block
|
||||
// we've already executed, so return early
|
||||
if (shadingsys().llvm_debug_layers())
|
||||
llvm_gen_debug_printf(Strutil::sprintf(
|
||||
" taking early exit, already executed layer %d %s %s",
|
||||
llvm_gen_debug_printf(fmtformat(
|
||||
" taking early exit, already executed layer {} {} {}",
|
||||
this->layer(), inst()->layername(), inst()->shadername()));
|
||||
ll.op_return();
|
||||
ll.set_insert_point(after_block);
|
||||
}
|
||||
|
||||
if (shadingsys().llvm_debug_layers())
|
||||
llvm_gen_debug_printf(
|
||||
Strutil::sprintf("enter layer %d %s %s", this->layer(),
|
||||
inst()->layername(), inst()->shadername()));
|
||||
llvm_gen_debug_printf(fmtformat("enter layer {} {} {}", this->layer(),
|
||||
inst()->layername(),
|
||||
inst()->shadername()));
|
||||
// Mark this layer as executed
|
||||
if (!group().is_last_layer(layer())) {
|
||||
// Caller may only be asking for a subset of the lanes to be executed
|
||||
@@ -1970,8 +2018,8 @@ BatchedBackendLLVM::build_llvm_instance(bool groupentry)
|
||||
// If debugnan is turned on, globals check that their values are ok
|
||||
if (s.symtype() == SymTypeGlobal && shadingsys().debug_nan()) {
|
||||
TypeDesc t = s.typespec().simpletype();
|
||||
if (t.basetype
|
||||
== TypeDesc::FLOAT) { // just check float-based types
|
||||
if (t.basetype == TypeDesc::FLOAT) {
|
||||
// just check float-based types
|
||||
int ncomps = t.numelements() * t.aggregate;
|
||||
if (s.is_uniform()) {
|
||||
llvm::Value* args[]
|
||||
@@ -2112,8 +2160,8 @@ BatchedBackendLLVM::build_llvm_instance(bool groupentry)
|
||||
if (child->symbol(next.dst.param)
|
||||
== dstsym) {
|
||||
if (next.dst.channel != -1) {
|
||||
OSL_DASSERT(next.dst.channel
|
||||
< (int)inited.size());
|
||||
OSL_DASSERT(next.dst.channel
|
||||
< (int)inited.size());
|
||||
if (!inited[next.dst.channel]) {
|
||||
inited[next.dst.channel] = true;
|
||||
--ninit;
|
||||
@@ -2147,52 +2195,54 @@ BatchedBackendLLVM::build_llvm_instance(bool groupentry)
|
||||
// llvm_gen_debug_printf ("done copying connections");
|
||||
}
|
||||
|
||||
|
||||
// Copy results to renderer outputs
|
||||
// The current mask could be altered by early returns or exit
|
||||
// But for copying output parameters to output locations,
|
||||
// we want to use the shader mask
|
||||
ll.push_mask(initial_shader_mask, /*negate=*/false,
|
||||
/*absolute = */ true);
|
||||
FOREACH_PARAM(Symbol& s, inst()) {
|
||||
if (! s.renderer_output()) // Skip if not a renderer output
|
||||
FOREACH_PARAM(Symbol & s, inst())
|
||||
{
|
||||
if (!s.renderer_output()) // Skip if not a renderer output
|
||||
continue;
|
||||
// Try to look up the sym among the outputs with the full layer.name
|
||||
// specification first. If that fails, look for name only.
|
||||
ustring layersym = ustring::fmtformat("{}.{}", inst()->layername(),
|
||||
s.name());
|
||||
auto symloc = group().find_symloc(layersym, SymArena::Outputs);
|
||||
if (! symloc)
|
||||
auto symloc = group().find_symloc(layersym, SymArena::Outputs);
|
||||
if (!symloc)
|
||||
symloc = group().find_symloc(s.name(), SymArena::Outputs);
|
||||
if (! symloc) {
|
||||
if (!symloc) {
|
||||
// std::cout << "No output copy for " << s.name()
|
||||
// << " because no symloc was found\n";
|
||||
continue; // not found in either place
|
||||
continue; // not found in either place
|
||||
}
|
||||
|
||||
if (! equivalent(s.typespec(), symloc->type)
|
||||
if (!equivalent(s.typespec(), symloc->type)
|
||||
|| s.typespec().is_closure()) {
|
||||
std::cout << "No output copy for " << s.typespec() << ' ' << s.name()
|
||||
<< " because of type mismatch vs symloc=" << symloc->type
|
||||
<< "\n";
|
||||
// print("No output copy for {} {} because of type mismatch vs symloc={}\n",
|
||||
// s.typespec(), s.name(), symloc->type);
|
||||
continue; // types didn't match
|
||||
}
|
||||
auto type = s.typespec().simpletype();
|
||||
|
||||
//const int deriv_count = (symloc->derivs && s.has_derivs()) ? 3 : 1;
|
||||
const int output_deriv_count = symloc->derivs ? 3 : 1;
|
||||
const int s_deriv_count = s.has_derivs() ? 3 : 1;
|
||||
const int s_deriv_count = s.has_derivs() ? 3 : 1;
|
||||
|
||||
llvm::Value* sym_offset = ll.constanti64(symloc->offset);
|
||||
llvm::Value* output_sym_base_ptr = ll.ptr_cast(ll.offset_ptr(m_llvm_output_base_ptr, sym_offset), type.scalartype());
|
||||
llvm::Value* output_sym_base_ptr
|
||||
= ll.ptr_cast(ll.offset_ptr(m_llvm_output_base_ptr, sym_offset),
|
||||
type.scalartype());
|
||||
bool isBase32bit = (symloc->type != TypeDesc::STRING);
|
||||
int bytesPerElem = isBase32bit ? 4 : 8;
|
||||
// TODO: could move assert inside SymLocation
|
||||
OSL_ASSERT((symloc->stride % bytesPerElem) == 0);
|
||||
|
||||
|
||||
llvm::Value* wide_shadeindex = ll.op_load(ll.type_wide_int(), m_llvm_wide_shadeindex_ptr);
|
||||
const int elem_stride = static_cast<int>(symloc->stride/bytesPerElem);
|
||||
llvm::Value* wide_shadeindex = ll.op_load(ll.type_wide_int(),
|
||||
m_llvm_wide_shadeindex_ptr);
|
||||
const int elem_stride = static_cast<int>(symloc->stride / bytesPerElem);
|
||||
llvm::Value* wide_index_to_output = nullptr;
|
||||
if (elem_stride == 1) {
|
||||
wide_index_to_output = wide_shadeindex;
|
||||
@@ -2201,8 +2251,8 @@ BatchedBackendLLVM::build_llvm_instance(bool groupentry)
|
||||
wide_index_to_output = ll.op_mul(element_stride, wide_shadeindex);
|
||||
}
|
||||
|
||||
const int elem_count = static_cast<int>(type.numelements());
|
||||
const int comp_count = type.aggregate;
|
||||
const int elem_count = static_cast<int>(type.numelements());
|
||||
const int comp_count = type.aggregate;
|
||||
|
||||
int c = 0;
|
||||
for (int d = 0; d < output_deriv_count; ++d) {
|
||||
@@ -2213,16 +2263,17 @@ BatchedBackendLLVM::build_llvm_instance(bool groupentry)
|
||||
for (int i = 0; i < comp_count; ++i, ++c) {
|
||||
// It is fine if the symbol is uniform, it will get broadcast
|
||||
// to a wide value for use in the scatter.
|
||||
llvm::Value *wide_val = s_deriv_exists
|
||||
? llvm_load_value(s, d,
|
||||
arrind, /*component*/i,
|
||||
TypeDesc::UNKNOWN,
|
||||
/*op_is_uniform*/false)
|
||||
: ll.wide_constant(0.0f);
|
||||
llvm::Value* wide_val
|
||||
= s_deriv_exists
|
||||
? llvm_load_value(s, d, arrind, /*component*/ i,
|
||||
TypeDesc::UNKNOWN,
|
||||
/*op_is_uniform*/ false)
|
||||
: ll.wide_constant(0.0f);
|
||||
|
||||
llvm::Value* wide_index = wide_index_to_output;
|
||||
if (c != 0) {
|
||||
wide_index = ll.op_add(wide_index_to_output, ll.wide_constant(c));
|
||||
wide_index = ll.op_add(wide_index_to_output,
|
||||
ll.wide_constant(c));
|
||||
}
|
||||
ll.op_scatter(wide_val, output_sym_base_ptr, wide_index);
|
||||
}
|
||||
@@ -2233,9 +2284,9 @@ BatchedBackendLLVM::build_llvm_instance(bool groupentry)
|
||||
|
||||
// All done
|
||||
if (shadingsys().llvm_debug_layers())
|
||||
llvm_gen_debug_printf(
|
||||
Strutil::sprintf("exit layer %d %s %s", this->layer(),
|
||||
inst()->layername(), inst()->shadername()));
|
||||
llvm_gen_debug_printf(fmtformat("exit layer {} {} {}", this->layer(),
|
||||
inst()->layername(),
|
||||
inst()->shadername()));
|
||||
ll.op_return();
|
||||
|
||||
if (llvm_debug())
|
||||
@@ -2269,7 +2320,6 @@ BatchedBackendLLVM::initialize_llvm_group()
|
||||
const char* compile_unit_name = m_group.m_name.empty()
|
||||
? unknown_shader_group_name.c_str()
|
||||
: m_group.m_name.c_str();
|
||||
|
||||
ll.debug_setup_compilation_unit(compile_unit_name);
|
||||
}
|
||||
|
||||
@@ -2355,6 +2405,8 @@ BatchedBackendLLVM::initialize_llvm_group()
|
||||
m_llvm_type_setup_closure_func = m_llvm_type_prepare_closure_func;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
void
|
||||
BatchedBackendLLVM::build_offsets_of_BatchedShaderGlobals(
|
||||
@@ -2373,8 +2425,6 @@ BatchedBackendLLVM::build_offsets_of_BatchedShaderGlobals(
|
||||
+ offsetof(UniformShaderGlobals, context));
|
||||
offset_by_index.push_back(uniform_offset
|
||||
+ offsetof(UniformShaderGlobals, renderer));
|
||||
offset_by_index.push_back(uniform_offset
|
||||
+ offsetof(UniformShaderGlobals, Ci));
|
||||
offset_by_index.push_back(uniform_offset
|
||||
+ offsetof(UniformShaderGlobals, raytype));
|
||||
offset_by_index.push_back(uniform_offset
|
||||
@@ -2383,6 +2433,10 @@ BatchedBackendLLVM::build_offsets_of_BatchedShaderGlobals(
|
||||
+ offsetof(UniformShaderGlobals, pad1));
|
||||
offset_by_index.push_back(uniform_offset
|
||||
+ offsetof(UniformShaderGlobals, pad2));
|
||||
offset_by_index.push_back(uniform_offset
|
||||
+ offsetof(UniformShaderGlobals, pad3));
|
||||
offset_by_index.push_back(uniform_offset
|
||||
+ offsetof(UniformShaderGlobals, pad4));
|
||||
|
||||
offset_by_index.push_back(varying_offset
|
||||
+ offsetof(VaryingShaderGlobals<WidthT>, P));
|
||||
@@ -2429,6 +2483,8 @@ BatchedBackendLLVM::build_offsets_of_BatchedShaderGlobals(
|
||||
varying_offset + offsetof(VaryingShaderGlobals<WidthT>, object2common));
|
||||
offset_by_index.push_back(
|
||||
varying_offset + offsetof(VaryingShaderGlobals<WidthT>, shader2common));
|
||||
offset_by_index.push_back(varying_offset
|
||||
+ offsetof(VaryingShaderGlobals<WidthT>, Ci));
|
||||
offset_by_index.push_back(
|
||||
varying_offset + offsetof(VaryingShaderGlobals<WidthT>, surfacearea));
|
||||
offset_by_index.push_back(
|
||||
@@ -2439,6 +2495,7 @@ BatchedBackendLLVM::build_offsets_of_BatchedShaderGlobals(
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
void
|
||||
BatchedBackendLLVM::build_offsets_of_BatchedTextureOptions(
|
||||
@@ -2459,8 +2516,8 @@ BatchedBackendLLVM::build_offsets_of_BatchedTextureOptions(
|
||||
offset_by_index.push_back(
|
||||
varying_offset + offsetof(VaryingTextureOptions<WidthT>, rwidth));
|
||||
#if OIIO_VERSION_GREATER_EQUAL(2, 4, 0)
|
||||
offset_by_index.push_back(
|
||||
varying_offset + offsetof(VaryingTextureOptions<WidthT>, rnd));
|
||||
offset_by_index.push_back(varying_offset
|
||||
+ offsetof(VaryingTextureOptions<WidthT>, rnd));
|
||||
#endif
|
||||
offset_by_index.push_back(uniform_offset
|
||||
+ offsetof(UniformTextureOptions, firstchannel));
|
||||
@@ -2490,6 +2547,8 @@ BatchedBackendLLVM::build_offsets_of_BatchedTextureOptions(
|
||||
offsetof(BatchedTextureOptions<WidthT>, private_envlayout));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedBackendLLVM::run()
|
||||
{
|
||||
@@ -2600,7 +2659,6 @@ BatchedBackendLLVM::run()
|
||||
ll.validate_struct_data_layout(m_llvm_type_sg, offset_by_index);
|
||||
}
|
||||
|
||||
|
||||
std::vector<llvm::Function*> funcs(nlayers, NULL);
|
||||
for (int layer = 0; layer < nlayers; ++layer) {
|
||||
set_inst(layer);
|
||||
@@ -2633,21 +2691,9 @@ BatchedBackendLLVM::run()
|
||||
// entry points, as well as for all the external functions that are
|
||||
// just declarations (not definitions) in the module (which we have
|
||||
// conveniently stashed in external_function_names).
|
||||
#if 0
|
||||
std::vector<std::string> entry_function_names;
|
||||
entry_function_names.push_back (ll.func_name(init_func));
|
||||
for (int layer = 0; layer < nlayers; ++layer) {
|
||||
// set_inst (layer);
|
||||
llvm::Function* f = funcs[layer];
|
||||
if (f && group().is_entry_layer(layer))
|
||||
entry_function_names.push_back (ll.func_name(f));
|
||||
}
|
||||
ll.internalize_module_functions ("osl_", external_function_names, entry_function_names);
|
||||
#else
|
||||
std::unordered_set<llvm::Function*> external_functions;
|
||||
external_functions.insert(init_func);
|
||||
for (int layer = 0; layer < nlayers; ++layer) {
|
||||
// set_inst (layer);
|
||||
llvm::Function* f = funcs[layer];
|
||||
// If we plan to call bitcode_string of a layer's function after optimization
|
||||
// it may not exist after optimization unless we treat it as external.
|
||||
@@ -2656,7 +2702,6 @@ BatchedBackendLLVM::run()
|
||||
}
|
||||
}
|
||||
ll.prune_and_internalize_module(external_functions);
|
||||
#endif
|
||||
|
||||
// Debug code to dump the pre-optimized bitcode to a file
|
||||
if (llvm_debug() >= 2 || shadingsys().llvm_output_bitcode()) {
|
||||
@@ -2665,11 +2710,10 @@ BatchedBackendLLVM::run()
|
||||
std::string safegroup = Strutil::replace(group().name(), "/", ".",
|
||||
true);
|
||||
if (safegroup.size() > 235)
|
||||
safegroup
|
||||
= Strutil::sprintf("TRUNC_%s_%d",
|
||||
safegroup.substr(safegroup.size() - 235),
|
||||
group().id());
|
||||
std::string name = Strutil::sprintf("%s.ll", safegroup);
|
||||
safegroup = fmtformat("TRUNC_{}_{}",
|
||||
safegroup.substr(safegroup.size() - 235),
|
||||
group().id());
|
||||
std::string name = fmtformat("{}.ll", safegroup);
|
||||
std::ofstream out(name, std::ios_base::out | std::ios_base::trunc);
|
||||
if (out.good()) {
|
||||
out << ll.bitcode_string(ll.module());
|
||||
@@ -2711,11 +2755,10 @@ BatchedBackendLLVM::run()
|
||||
std::string safegroup = Strutil::replace(group().name(), "/", ".",
|
||||
true);
|
||||
if (safegroup.size() > 235)
|
||||
safegroup
|
||||
= Strutil::sprintf("TRUNC_%s_%d",
|
||||
safegroup.substr(safegroup.size() - 235),
|
||||
group().id());
|
||||
std::string name = Strutil::sprintf("%s_opt.ll", safegroup);
|
||||
safegroup = fmtformat("TRUNC_{}_{}",
|
||||
safegroup.substr(safegroup.size() - 235),
|
||||
group().id());
|
||||
std::string name = fmtformat("{}_opt.ll", safegroup);
|
||||
std::ofstream out(name, std::ios_base::out | std::ios_base::trunc);
|
||||
if (out.good()) {
|
||||
out << ll.bitcode_string(ll.module());
|
||||
@@ -2755,9 +2798,9 @@ BatchedBackendLLVM::run()
|
||||
m_stat_total_llvm_time = timer();
|
||||
|
||||
if (shadingsys().m_compile_report) {
|
||||
shadingcontext()->infof("JITed shader group %s:", group().name());
|
||||
shadingcontext()->infof(
|
||||
" (%1.2fs = %1.2f setup, %1.2f ir, %1.2f opt, %1.2f jit; local mem %dKB)",
|
||||
shadingcontext()->infofmt("JITed shader group {}:", group().name());
|
||||
shadingcontext()->infofmt(
|
||||
" ({:1.2f}s = {:1.2f} setup, {:1.2f} ir, {:1.2f} opt, {:1.2f} jit; local mem {}KB)",
|
||||
m_stat_total_llvm_time, m_stat_llvm_setup_time,
|
||||
m_stat_llvm_irgen_time, m_stat_llvm_opt_time, m_stat_llvm_jit_time,
|
||||
m_llvm_local_mem / 1024);
|
||||
@@ -2765,6 +2808,5 @@ BatchedBackendLLVM::run()
|
||||
}
|
||||
|
||||
|
||||
|
||||
}; // namespace pvt
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
@@ -13,6 +13,7 @@ using namespace OSL::pvt;
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
BatchedRendererServices<WidthT>::BatchedRendererServices(TextureSystem* texsys)
|
||||
: m_texturesys(texsys)
|
||||
@@ -35,6 +36,7 @@ BatchedRendererServices<WidthT>::BatchedRendererServices(TextureSystem* texsys)
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::get_matrix(BatchedShaderGlobals* bsg,
|
||||
@@ -49,6 +51,7 @@ BatchedRendererServices<WidthT>::get_matrix(BatchedShaderGlobals* bsg,
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::get_inverse_matrix(
|
||||
@@ -62,6 +65,7 @@ BatchedRendererServices<WidthT>::get_inverse_matrix(
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::get_inverse_matrix(BatchedShaderGlobals* bsg,
|
||||
@@ -75,6 +79,8 @@ BatchedRendererServices<WidthT>::get_inverse_matrix(BatchedShaderGlobals* bsg,
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::get_inverse_matrix(BatchedShaderGlobals* bsg,
|
||||
@@ -88,6 +94,8 @@ BatchedRendererServices<WidthT>::get_inverse_matrix(BatchedShaderGlobals* bsg,
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
TextureSystem*
|
||||
BatchedRendererServices<WidthT>::texturesys() const
|
||||
@@ -95,6 +103,8 @@ BatchedRendererServices<WidthT>::texturesys() const
|
||||
return m_texturesys;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
TextureSystem::TextureHandle*
|
||||
BatchedRendererServices<WidthT>::resolve_udim_uniform(
|
||||
@@ -107,7 +117,6 @@ BatchedRendererServices<WidthT>::resolve_udim_uniform(
|
||||
if (!texture_handle)
|
||||
texture_handle = texturesys()->get_texture_handle(filename,
|
||||
texture_thread_info);
|
||||
#if OPENIMAGEIO_VERSION >= 20307
|
||||
if (texturesys()->is_udim(texture_handle)) {
|
||||
// Newer versions of the TextureSystem interface are able to determine the
|
||||
// specific UDIM tile we're using.
|
||||
@@ -121,11 +130,13 @@ BatchedRendererServices<WidthT>::resolve_udim_uniform(
|
||||
udim_handle = texture_handle;
|
||||
}
|
||||
return udim_handle;
|
||||
} else
|
||||
#endif
|
||||
} else {
|
||||
return texture_handle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
void
|
||||
BatchedRendererServices<WidthT>::resolve_udim(
|
||||
@@ -139,7 +150,6 @@ BatchedRendererServices<WidthT>::resolve_udim(
|
||||
if (!texture_handle)
|
||||
texture_handle = texturesys()->get_texture_handle(filename,
|
||||
texture_thread_info);
|
||||
#if OPENIMAGEIO_VERSION >= 20307
|
||||
if (texturesys()->is_udim(texture_handle)) {
|
||||
// Newer versions of the TextureSystem interface are able to determine the
|
||||
// specific UDIM tile we're using.
|
||||
@@ -155,12 +165,13 @@ BatchedRendererServices<WidthT>::resolve_udim(
|
||||
}
|
||||
wresult[l] = udim_handle;
|
||||
});
|
||||
} else
|
||||
#endif
|
||||
} else {
|
||||
assign_all(wresult, texture_handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
bool
|
||||
BatchedRendererServices<WidthT>::get_texture_info_uniform(
|
||||
@@ -180,13 +191,15 @@ BatchedRendererServices<WidthT>::get_texture_info_uniform(
|
||||
if (!status) {
|
||||
std::string err = texturesys()->geterror();
|
||||
if (err.size() && bsg) {
|
||||
bsg->uniform.context->errorf(
|
||||
"[RendererServices::get_texture_info] %s", err);
|
||||
bsg->uniform.context->errorfmt(
|
||||
"[RendererServices::get_texture_info] {}", err);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::texture(
|
||||
@@ -203,6 +216,8 @@ BatchedRendererServices<WidthT>::texture(
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::texture3d(
|
||||
@@ -218,6 +233,8 @@ BatchedRendererServices<WidthT>::texture3d(
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::environment(
|
||||
@@ -233,6 +250,8 @@ BatchedRendererServices<WidthT>::environment(
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
void
|
||||
BatchedRendererServices<WidthT>::pointcloud_search(
|
||||
@@ -245,6 +264,8 @@ BatchedRendererServices<WidthT>::pointcloud_search(
|
||||
&& "UNREACHABLE: BatchedRendererServices<WidthT>::pointcloud_search calls should be overridden or the target specific version in wide_oppointcloud.cpp should be called");
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::pointcloud_get(
|
||||
@@ -258,6 +279,7 @@ BatchedRendererServices<WidthT>::pointcloud_get(
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::pointcloud_write(
|
||||
@@ -271,6 +293,8 @@ BatchedRendererServices<WidthT>::pointcloud_write(
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
void
|
||||
BatchedRendererServices<WidthT>::trace(
|
||||
@@ -283,6 +307,8 @@ BatchedRendererServices<WidthT>::trace(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
void
|
||||
BatchedRendererServices<WidthT>::getmessage(BatchedShaderGlobals* bsg,
|
||||
@@ -296,6 +322,8 @@ BatchedRendererServices<WidthT>::getmessage(BatchedShaderGlobals* bsg,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Explicitly instantiate BatchedRendererServices template
|
||||
template class OSLEXECPUBLIC BatchedRendererServices<16>;
|
||||
template class OSLEXECPUBLIC BatchedRendererServices<8>;
|
||||
|
||||
+276
-277
@@ -11,119 +11,118 @@
|
||||
|
||||
|
||||
#ifndef DECL
|
||||
#error Do not include this file unless DECL is defined
|
||||
# error Do not include this file unless DECL is defined
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define NOISE_IMPL(name) \
|
||||
DECL (osl_ ## name ## _ff, "ff") \
|
||||
DECL (osl_ ## name ## _fff, "fff") \
|
||||
DECL (osl_ ## name ## _fv, "fv") \
|
||||
DECL (osl_ ## name ## _fvf, "fvf") \
|
||||
DECL (osl_ ## name ## _vf, "xvf") \
|
||||
DECL (osl_ ## name ## _vff, "xvff") \
|
||||
DECL (osl_ ## name ## _vv, "xvv") \
|
||||
DECL (osl_ ## name ## _vvf, "xvvf")
|
||||
#define NOISE_IMPL(name) \
|
||||
DECL(osl_##name##_ff, "ff") \
|
||||
DECL(osl_##name##_fff, "fff") \
|
||||
DECL(osl_##name##_fv, "fv") \
|
||||
DECL(osl_##name##_fvf, "fvf") \
|
||||
DECL(osl_##name##_vf, "xvf") \
|
||||
DECL(osl_##name##_vff, "xvff") \
|
||||
DECL(osl_##name##_vv, "xvv") \
|
||||
DECL(osl_##name##_vvf, "xvvf")
|
||||
|
||||
#define NOISE_DERIV_IMPL(name) \
|
||||
DECL (osl_ ## name ## _dfdf, "xXX") \
|
||||
DECL (osl_ ## name ## _dfdff, "xXXf") \
|
||||
DECL (osl_ ## name ## _dffdf, "xXfX") \
|
||||
DECL (osl_ ## name ## _dfdfdf, "xXXX") \
|
||||
DECL (osl_ ## name ## _dfdv, "xXv") \
|
||||
DECL (osl_ ## name ## _dfdvf, "xXvf") \
|
||||
DECL (osl_ ## name ## _dfvdf, "xXvX") \
|
||||
DECL (osl_ ## name ## _dfdvdf, "xXvX") \
|
||||
DECL (osl_ ## name ## _dvdf, "xvX") \
|
||||
DECL (osl_ ## name ## _dvdff, "xvXf") \
|
||||
DECL (osl_ ## name ## _dvfdf, "xvfX") \
|
||||
DECL (osl_ ## name ## _dvdfdf, "xvXX") \
|
||||
DECL (osl_ ## name ## _dvdv, "xvv") \
|
||||
DECL (osl_ ## name ## _dvdvf, "xvvf") \
|
||||
DECL (osl_ ## name ## _dvvdf, "xvvX") \
|
||||
DECL (osl_ ## name ## _dvdvdf, "xvvX")
|
||||
#define NOISE_DERIV_IMPL(name) \
|
||||
DECL(osl_##name##_dfdf, "xXX") \
|
||||
DECL(osl_##name##_dfdff, "xXXf") \
|
||||
DECL(osl_##name##_dffdf, "xXfX") \
|
||||
DECL(osl_##name##_dfdfdf, "xXXX") \
|
||||
DECL(osl_##name##_dfdv, "xXv") \
|
||||
DECL(osl_##name##_dfdvf, "xXvf") \
|
||||
DECL(osl_##name##_dfvdf, "xXvX") \
|
||||
DECL(osl_##name##_dfdvdf, "xXvX") \
|
||||
DECL(osl_##name##_dvdf, "xvX") \
|
||||
DECL(osl_##name##_dvdff, "xvXf") \
|
||||
DECL(osl_##name##_dvfdf, "xvfX") \
|
||||
DECL(osl_##name##_dvdfdf, "xvXX") \
|
||||
DECL(osl_##name##_dvdv, "xvv") \
|
||||
DECL(osl_##name##_dvdvf, "xvvf") \
|
||||
DECL(osl_##name##_dvvdf, "xvvX") \
|
||||
DECL(osl_##name##_dvdvdf, "xvvX")
|
||||
|
||||
#define GENERIC_NOISE_DERIV_IMPL(name) \
|
||||
DECL (osl_ ## name ## _dfdf, "xsXXXX") \
|
||||
DECL (osl_ ## name ## _dfdfdf, "xsXXXXX") \
|
||||
DECL (osl_ ## name ## _dfdv, "xsXXXX") \
|
||||
DECL (osl_ ## name ## _dfdvdf, "xsXXXXX") \
|
||||
DECL (osl_ ## name ## _dvdf, "xsXXXX") \
|
||||
DECL (osl_ ## name ## _dvdfdf, "xsXXXXX") \
|
||||
DECL (osl_ ## name ## _dvdv, "xsXXXX") \
|
||||
DECL (osl_ ## name ## _dvdvdf, "xsXXXXX")
|
||||
#define GENERIC_NOISE_DERIV_IMPL(name) \
|
||||
DECL(osl_##name##_dfdf, "xsXXXX") \
|
||||
DECL(osl_##name##_dfdfdf, "xsXXXXX") \
|
||||
DECL(osl_##name##_dfdv, "xsXXXX") \
|
||||
DECL(osl_##name##_dfdvdf, "xsXXXXX") \
|
||||
DECL(osl_##name##_dvdf, "xsXXXX") \
|
||||
DECL(osl_##name##_dvdfdf, "xsXXXXX") \
|
||||
DECL(osl_##name##_dvdv, "xsXXXX") \
|
||||
DECL(osl_##name##_dvdvdf, "xsXXXXX")
|
||||
|
||||
#define PNOISE_IMPL(name) \
|
||||
DECL (osl_ ## name ## _fff, "fff") \
|
||||
DECL (osl_ ## name ## _fffff, "fffff") \
|
||||
DECL (osl_ ## name ## _fvv, "fvv") \
|
||||
DECL (osl_ ## name ## _fvfvf, "fvfvf") \
|
||||
DECL (osl_ ## name ## _vff, "xvff") \
|
||||
DECL (osl_ ## name ## _vffff, "xvffff") \
|
||||
DECL (osl_ ## name ## _vvv, "xvvv") \
|
||||
DECL (osl_ ## name ## _vvfvf, "xvvfvf")
|
||||
#define PNOISE_IMPL(name) \
|
||||
DECL(osl_##name##_fff, "fff") \
|
||||
DECL(osl_##name##_fffff, "fffff") \
|
||||
DECL(osl_##name##_fvv, "fvv") \
|
||||
DECL(osl_##name##_fvfvf, "fvfvf") \
|
||||
DECL(osl_##name##_vff, "xvff") \
|
||||
DECL(osl_##name##_vffff, "xvffff") \
|
||||
DECL(osl_##name##_vvv, "xvvv") \
|
||||
DECL(osl_##name##_vvfvf, "xvvfvf")
|
||||
|
||||
#define PNOISE_DERIV_IMPL(name) \
|
||||
DECL (osl_ ## name ## _dfdff, "xXXf") \
|
||||
DECL (osl_ ## name ## _dfdffff, "xXXfff") \
|
||||
DECL (osl_ ## name ## _dffdfff, "xXfXff") \
|
||||
DECL (osl_ ## name ## _dfdfdfff, "xXXXff") \
|
||||
DECL (osl_ ## name ## _dfdvv, "xXXv") \
|
||||
DECL (osl_ ## name ## _dfdvfvf, "xXvfvf") \
|
||||
DECL (osl_ ## name ## _dfvdfvf, "xXvXvf") \
|
||||
DECL (osl_ ## name ## _dfdvdfvf, "xXvXvf") \
|
||||
DECL (osl_ ## name ## _dvdff, "xvXf") \
|
||||
DECL (osl_ ## name ## _dvdffff, "xvXfff") \
|
||||
DECL (osl_ ## name ## _dvfdfff, "xvfXff") \
|
||||
DECL (osl_ ## name ## _dvdfdfff, "xvXXff") \
|
||||
DECL (osl_ ## name ## _dvdvv, "xvvv") \
|
||||
DECL (osl_ ## name ## _dvdvfvf, "xvvfvf") \
|
||||
DECL (osl_ ## name ## _dvvdfvf, "xvvXvf") \
|
||||
DECL (osl_ ## name ## _dvdvdfvf, "xvvXvf")
|
||||
#define PNOISE_DERIV_IMPL(name) \
|
||||
DECL(osl_##name##_dfdff, "xXXf") \
|
||||
DECL(osl_##name##_dfdffff, "xXXfff") \
|
||||
DECL(osl_##name##_dffdfff, "xXfXff") \
|
||||
DECL(osl_##name##_dfdfdfff, "xXXXff") \
|
||||
DECL(osl_##name##_dfdvv, "xXXv") \
|
||||
DECL(osl_##name##_dfdvfvf, "xXvfvf") \
|
||||
DECL(osl_##name##_dfvdfvf, "xXvXvf") \
|
||||
DECL(osl_##name##_dfdvdfvf, "xXvXvf") \
|
||||
DECL(osl_##name##_dvdff, "xvXf") \
|
||||
DECL(osl_##name##_dvdffff, "xvXfff") \
|
||||
DECL(osl_##name##_dvfdfff, "xvfXff") \
|
||||
DECL(osl_##name##_dvdfdfff, "xvXXff") \
|
||||
DECL(osl_##name##_dvdvv, "xvvv") \
|
||||
DECL(osl_##name##_dvdvfvf, "xvvfvf") \
|
||||
DECL(osl_##name##_dvvdfvf, "xvvXvf") \
|
||||
DECL(osl_##name##_dvdvdfvf, "xvvXvf")
|
||||
|
||||
#define GENERIC_PNOISE_DERIV_IMPL(name) \
|
||||
DECL (osl_ ## name ## _dfdff, "xsXXfXX") \
|
||||
DECL (osl_ ## name ## _dfdfdfff, "xsXXXffXX") \
|
||||
DECL (osl_ ## name ## _dfdvv, "xsXXvXX") \
|
||||
DECL (osl_ ## name ## _dfdvdfvf, "xsXvXvfXX") \
|
||||
DECL (osl_ ## name ## _dvdff, "xsvXfXX") \
|
||||
DECL (osl_ ## name ## _dvdfdfff, "xsvXXffXX") \
|
||||
DECL (osl_ ## name ## _dvdvv, "xsvvvXX") \
|
||||
DECL (osl_ ## name ## _dvdvdfvf, "xsvvXvfXX")
|
||||
#define GENERIC_PNOISE_DERIV_IMPL(name) \
|
||||
DECL(osl_##name##_dfdff, "xsXXfXX") \
|
||||
DECL(osl_##name##_dfdfdfff, "xsXXXffXX") \
|
||||
DECL(osl_##name##_dfdvv, "xsXXvXX") \
|
||||
DECL(osl_##name##_dfdvdfvf, "xsXvXvfXX") \
|
||||
DECL(osl_##name##_dvdff, "xsvXfXX") \
|
||||
DECL(osl_##name##_dvdfdfff, "xsvXXffXX") \
|
||||
DECL(osl_##name##_dvdvv, "xsvvvXX") \
|
||||
DECL(osl_##name##_dvdvdfvf, "xsvvXvfXX")
|
||||
|
||||
#define UNARY_OP_IMPL(name) \
|
||||
DECL (osl_ ## name ## _ff, "ff") \
|
||||
DECL (osl_ ## name ## _dfdf, "xXX") \
|
||||
DECL (osl_ ## name ## _vv, "xXX") \
|
||||
DECL (osl_ ## name ## _dvdv, "xXX")
|
||||
#define UNARY_OP_IMPL(name) \
|
||||
DECL(osl_##name##_ff, "ff") \
|
||||
DECL(osl_##name##_dfdf, "xXX") \
|
||||
DECL(osl_##name##_vv, "xXX") \
|
||||
DECL(osl_##name##_dvdv, "xXX")
|
||||
|
||||
#define BINARY_OP_IMPL(name) \
|
||||
DECL (osl_ ## name ## _fff, "fff") \
|
||||
DECL (osl_ ## name ## _dfdfdf, "xXXX") \
|
||||
DECL (osl_ ## name ## _dffdf, "xXfX") \
|
||||
DECL (osl_ ## name ## _dfdff, "xXXf") \
|
||||
DECL (osl_ ## name ## _vvv, "xXXX") \
|
||||
DECL (osl_ ## name ## _dvdvdv, "xXXX") \
|
||||
DECL (osl_ ## name ## _dvvdv, "xXXX") \
|
||||
DECL (osl_ ## name ## _dvdvv, "xXXX")
|
||||
#define BINARY_OP_IMPL(name) \
|
||||
DECL(osl_##name##_fff, "fff") \
|
||||
DECL(osl_##name##_dfdfdf, "xXXX") \
|
||||
DECL(osl_##name##_dffdf, "xXfX") \
|
||||
DECL(osl_##name##_dfdff, "xXXf") \
|
||||
DECL(osl_##name##_vvv, "xXXX") \
|
||||
DECL(osl_##name##_dvdvdv, "xXXX") \
|
||||
DECL(osl_##name##_dvvdv, "xXXX") \
|
||||
DECL(osl_##name##_dvdvv, "xXXX")
|
||||
|
||||
|
||||
|
||||
|
||||
DECL (osl_add_closure_closure, "CXCC")
|
||||
DECL (osl_mul_closure_float, "CXCf")
|
||||
DECL (osl_mul_closure_color, "CXCc")
|
||||
DECL (osl_allocate_closure_component, "CXii")
|
||||
DECL (osl_allocate_weighted_closure_component, "CXiiX")
|
||||
DECL (osl_closure_to_string, "sXC")
|
||||
DECL (osl_format, "ss*")
|
||||
DECL (osl_printf, "xXs*")
|
||||
DECL (osl_fprintf, "xXss*")
|
||||
DECL (osl_error, "xXs*")
|
||||
DECL (osl_warning, "xXs*")
|
||||
DECL (osl_split, "isXsii")
|
||||
DECL (osl_incr_layers_executed, "xX")
|
||||
DECL(osl_add_closure_closure, "CXCC")
|
||||
DECL(osl_mul_closure_float, "CXCf")
|
||||
DECL(osl_mul_closure_color, "CXCc")
|
||||
DECL(osl_allocate_closure_component, "CXii")
|
||||
DECL(osl_allocate_weighted_closure_component, "CXiiX")
|
||||
DECL(osl_closure_to_string, "sXC")
|
||||
DECL(osl_format, "ss*")
|
||||
DECL(osl_printf, "xXs*")
|
||||
DECL(osl_fprintf, "xXss*")
|
||||
DECL(osl_error, "xXs*")
|
||||
DECL(osl_warning, "xXs*")
|
||||
DECL(osl_split, "isXsii")
|
||||
DECL(osl_incr_layers_executed, "xX")
|
||||
|
||||
NOISE_IMPL(cellnoise)
|
||||
//NOISE_DERIV_IMPL(cellnoise)
|
||||
@@ -151,70 +150,70 @@ PNOISE_IMPL(psnoise)
|
||||
PNOISE_DERIV_IMPL(psnoise)
|
||||
GENERIC_PNOISE_DERIV_IMPL(gaborpnoise)
|
||||
GENERIC_PNOISE_DERIV_IMPL(genericpnoise)
|
||||
DECL (osl_noiseparams_set_anisotropic, "xXi")
|
||||
DECL (osl_noiseparams_set_do_filter, "xXi")
|
||||
DECL (osl_noiseparams_set_direction, "xXv")
|
||||
DECL (osl_noiseparams_set_bandwidth, "xXf")
|
||||
DECL (osl_noiseparams_set_impulses, "xXf")
|
||||
DECL (osl_count_noise, "xX")
|
||||
DECL (osl_hash_ii, "ii")
|
||||
DECL (osl_hash_if, "if")
|
||||
DECL (osl_hash_iff, "iff")
|
||||
DECL (osl_hash_iv, "iX")
|
||||
DECL (osl_hash_ivf, "iXf")
|
||||
DECL(osl_noiseparams_set_anisotropic, "xXi")
|
||||
DECL(osl_noiseparams_set_do_filter, "xXi")
|
||||
DECL(osl_noiseparams_set_direction, "xXv")
|
||||
DECL(osl_noiseparams_set_bandwidth, "xXf")
|
||||
DECL(osl_noiseparams_set_impulses, "xXf")
|
||||
DECL(osl_count_noise, "xX")
|
||||
DECL(osl_hash_ii, "ii")
|
||||
DECL(osl_hash_if, "if")
|
||||
DECL(osl_hash_iff, "iff")
|
||||
DECL(osl_hash_iv, "iX")
|
||||
DECL(osl_hash_ivf, "iXf")
|
||||
|
||||
DECL (osl_spline_fff, "xXXXXii")
|
||||
DECL (osl_spline_dfdfdf, "xXXXXii")
|
||||
DECL (osl_spline_dfdff, "xXXXXii")
|
||||
DECL (osl_spline_dffdf, "xXXXXii")
|
||||
DECL (osl_spline_vfv, "xXXXXii")
|
||||
DECL (osl_spline_dvdfdv, "xXXXXii")
|
||||
DECL (osl_spline_dvdfv, "xXXXXii")
|
||||
DECL (osl_spline_dvfdv, "xXXXXii")
|
||||
DECL (osl_splineinverse_fff, "xXXXXii")
|
||||
DECL (osl_splineinverse_dfdfdf, "xXXXXii")
|
||||
DECL (osl_splineinverse_dfdff, "xXXXXii")
|
||||
DECL (osl_splineinverse_dffdf, "xXXXXii")
|
||||
DECL (osl_setmessage, "xXsLXisi")
|
||||
DECL (osl_getmessage, "iXssLXiisi")
|
||||
DECL (osl_pointcloud_search, "iXsXfiiXXii*")
|
||||
DECL (osl_pointcloud_get, "iXsXisLX")
|
||||
DECL (osl_pointcloud_write, "iXsXiXXX")
|
||||
DECL (osl_pointcloud_write_helper, "xXXXisLX")
|
||||
DECL (osl_blackbody_vf, "xXXf")
|
||||
DECL (osl_wavelength_color_vf, "xXXf")
|
||||
DECL (osl_luminance_fv, "xXXX")
|
||||
DECL (osl_luminance_dfdv, "xXXX")
|
||||
DECL (osl_prepend_color_from, "xXXs")
|
||||
DECL (osl_prepend_matrix_from, "iXXs")
|
||||
DECL (osl_get_matrix, "iXXs")
|
||||
DECL (osl_get_inverse_matrix, "iXXs")
|
||||
DECL (osl_transform_triple, "iXXiXiXXi")
|
||||
DECL (osl_transform_triple_nonlinear, "iXXiXiXXi")
|
||||
DECL (osl_transform_vmv, "xXXX")
|
||||
DECL (osl_transform_dvmdv, "xXXX")
|
||||
DECL (osl_transformv_vmv, "xXXX")
|
||||
DECL (osl_transformv_dvmdv, "xXXX")
|
||||
DECL (osl_transformn_vmv, "xXXX")
|
||||
DECL (osl_transformn_dvmdv, "xXXX")
|
||||
DECL (osl_transformc, "iXXiXiXX")
|
||||
DECL(osl_spline_fff, "xXXXXii")
|
||||
DECL(osl_spline_dfdfdf, "xXXXXii")
|
||||
DECL(osl_spline_dfdff, "xXXXXii")
|
||||
DECL(osl_spline_dffdf, "xXXXXii")
|
||||
DECL(osl_spline_vfv, "xXXXXii")
|
||||
DECL(osl_spline_dvdfdv, "xXXXXii")
|
||||
DECL(osl_spline_dvdfv, "xXXXXii")
|
||||
DECL(osl_spline_dvfdv, "xXXXXii")
|
||||
DECL(osl_splineinverse_fff, "xXXXXii")
|
||||
DECL(osl_splineinverse_dfdfdf, "xXXXXii")
|
||||
DECL(osl_splineinverse_dfdff, "xXXXXii")
|
||||
DECL(osl_splineinverse_dffdf, "xXXXXii")
|
||||
DECL(osl_setmessage, "xXsLXisi")
|
||||
DECL(osl_getmessage, "iXssLXiisi")
|
||||
DECL(osl_pointcloud_search, "iXsXfiiXXii*")
|
||||
DECL(osl_pointcloud_get, "iXsXisLX")
|
||||
DECL(osl_pointcloud_write, "iXsXiXXX")
|
||||
DECL(osl_pointcloud_write_helper, "xXXXisLX")
|
||||
DECL(osl_blackbody_vf, "xXXf")
|
||||
DECL(osl_wavelength_color_vf, "xXXf")
|
||||
DECL(osl_luminance_fv, "xXXX")
|
||||
DECL(osl_luminance_dfdv, "xXXX")
|
||||
DECL(osl_prepend_color_from, "xXXs")
|
||||
DECL(osl_prepend_matrix_from, "iXXs")
|
||||
DECL(osl_get_matrix, "iXXs")
|
||||
DECL(osl_get_inverse_matrix, "iXXs")
|
||||
DECL(osl_transform_triple, "iXXiXiXXi")
|
||||
DECL(osl_transform_triple_nonlinear, "iXXiXiXXi")
|
||||
DECL(osl_transform_vmv, "xXXX")
|
||||
DECL(osl_transform_dvmdv, "xXXX")
|
||||
DECL(osl_transformv_vmv, "xXXX")
|
||||
DECL(osl_transformv_dvmdv, "xXXX")
|
||||
DECL(osl_transformn_vmv, "xXXX")
|
||||
DECL(osl_transformn_dvmdv, "xXXX")
|
||||
DECL(osl_transformc, "iXXiXiXX")
|
||||
|
||||
DECL (osl_dict_find_iis, "iXiX")
|
||||
DECL (osl_dict_find_iss, "iXXX")
|
||||
DECL (osl_dict_next, "iXi")
|
||||
DECL (osl_dict_value, "iXiXLX")
|
||||
DECL (osl_raytype_name, "iXs")
|
||||
DECL(osl_dict_find_iis, "iXiX")
|
||||
DECL(osl_dict_find_iss, "iXXX")
|
||||
DECL(osl_dict_next, "iXi")
|
||||
DECL(osl_dict_value, "iXiXLX")
|
||||
DECL(osl_raytype_name, "iXs")
|
||||
#ifdef OSL_LLVM_NO_BITCODE
|
||||
DECL (osl_range_check, "iiiXXXiXiXX")
|
||||
DECL(osl_range_check, "iiiXXXiXiXX")
|
||||
#endif
|
||||
DECL (osl_range_check_err, "iiiXXXiXiXX")
|
||||
DECL (osl_naninf_check, "xiXiXXiXiiX")
|
||||
DECL (osl_uninit_check, "xLXXXiXiXXiXiXii")
|
||||
DECL (osl_get_attribute, "iXiXXiiLX")
|
||||
DECL (osl_bind_interpolated_param, "iXXLiXiXiXi")
|
||||
DECL (osl_get_texture_options, "XX");
|
||||
DECL (osl_get_noise_options, "XX");
|
||||
DECL (osl_get_trace_options, "XX");
|
||||
DECL(osl_range_check_err, "iiiXXXiXiXX")
|
||||
DECL(osl_naninf_check, "xiXiXXiXiiX")
|
||||
DECL(osl_uninit_check, "xLXXXiXiXXiXiXii")
|
||||
DECL(osl_get_attribute, "iXiXXiiLX")
|
||||
DECL(osl_bind_interpolated_param, "iXXLiXiXiXi")
|
||||
DECL(osl_get_texture_options, "XX");
|
||||
DECL(osl_get_noise_options, "XX");
|
||||
DECL(osl_get_trace_options, "XX");
|
||||
|
||||
|
||||
// The following are defined inside llvm_ops.cpp. Only include these
|
||||
@@ -231,17 +230,17 @@ UNARY_OP_IMPL(sinh)
|
||||
UNARY_OP_IMPL(cosh)
|
||||
UNARY_OP_IMPL(tanh)
|
||||
|
||||
DECL (osl_safe_div_iii, "iii")
|
||||
DECL (osl_safe_div_fff, "fff")
|
||||
DECL (osl_safe_mod_iii, "iii")
|
||||
DECL (osl_sincos_fff, "xfXX")
|
||||
DECL (osl_sincos_dfdff, "xXXX")
|
||||
DECL (osl_sincos_dffdf, "xXXX")
|
||||
DECL (osl_sincos_dfdfdf, "xXXX")
|
||||
DECL (osl_sincos_vvv, "xXXX")
|
||||
DECL (osl_sincos_dvdvv, "xXXX")
|
||||
DECL (osl_sincos_dvvdv, "xXXX")
|
||||
DECL (osl_sincos_dvdvdv, "xXXX")
|
||||
DECL(osl_safe_div_iii, "iii")
|
||||
DECL(osl_safe_div_fff, "fff")
|
||||
DECL(osl_safe_mod_iii, "iii")
|
||||
DECL(osl_sincos_fff, "xfXX")
|
||||
DECL(osl_sincos_dfdff, "xXXX")
|
||||
DECL(osl_sincos_dffdf, "xXXX")
|
||||
DECL(osl_sincos_dfdfdf, "xXXX")
|
||||
DECL(osl_sincos_vvv, "xXXX")
|
||||
DECL(osl_sincos_dvdvv, "xXXX")
|
||||
DECL(osl_sincos_dvvdv, "xXXX")
|
||||
DECL(osl_sincos_dvdvdv, "xXXX")
|
||||
|
||||
UNARY_OP_IMPL(log)
|
||||
UNARY_OP_IMPL(log2)
|
||||
@@ -253,138 +252,138 @@ BINARY_OP_IMPL(pow)
|
||||
UNARY_OP_IMPL(erf)
|
||||
UNARY_OP_IMPL(erfc)
|
||||
|
||||
DECL (osl_pow_vvf, "xXXf")
|
||||
DECL (osl_pow_dvdvdf, "xXXX")
|
||||
DECL (osl_pow_dvvdf, "xXXX")
|
||||
DECL (osl_pow_dvdvf, "xXXf")
|
||||
DECL(osl_pow_vvf, "xXXf")
|
||||
DECL(osl_pow_dvdvdf, "xXXX")
|
||||
DECL(osl_pow_dvvdf, "xXXX")
|
||||
DECL(osl_pow_dvdvf, "xXXf")
|
||||
|
||||
UNARY_OP_IMPL(sqrt)
|
||||
UNARY_OP_IMPL(inversesqrt)
|
||||
UNARY_OP_IMPL(cbrt)
|
||||
|
||||
DECL (osl_logb_ff, "ff")
|
||||
DECL (osl_logb_vv, "xXX")
|
||||
DECL(osl_logb_ff, "ff")
|
||||
DECL(osl_logb_vv, "xXX")
|
||||
|
||||
DECL (osl_floor_ff, "ff")
|
||||
DECL (osl_floor_vv, "xXX")
|
||||
DECL (osl_ceil_ff, "ff")
|
||||
DECL (osl_ceil_vv, "xXX")
|
||||
DECL (osl_round_ff, "ff")
|
||||
DECL (osl_round_vv, "xXX")
|
||||
DECL (osl_trunc_ff, "ff")
|
||||
DECL (osl_trunc_vv, "xXX")
|
||||
DECL (osl_sign_ff, "ff")
|
||||
DECL (osl_sign_vv, "xXX")
|
||||
DECL (osl_step_fff, "fff")
|
||||
DECL (osl_step_vvv, "xXXX")
|
||||
DECL(osl_floor_ff, "ff")
|
||||
DECL(osl_floor_vv, "xXX")
|
||||
DECL(osl_ceil_ff, "ff")
|
||||
DECL(osl_ceil_vv, "xXX")
|
||||
DECL(osl_round_ff, "ff")
|
||||
DECL(osl_round_vv, "xXX")
|
||||
DECL(osl_trunc_ff, "ff")
|
||||
DECL(osl_trunc_vv, "xXX")
|
||||
DECL(osl_sign_ff, "ff")
|
||||
DECL(osl_sign_vv, "xXX")
|
||||
DECL(osl_step_fff, "fff")
|
||||
DECL(osl_step_vvv, "xXXX")
|
||||
|
||||
DECL (osl_isnan_if, "if")
|
||||
DECL (osl_isinf_if, "if")
|
||||
DECL (osl_isfinite_if, "if")
|
||||
DECL (osl_abs_ii, "ii")
|
||||
DECL (osl_fabs_ii, "ii")
|
||||
DECL(osl_isnan_if, "if")
|
||||
DECL(osl_isinf_if, "if")
|
||||
DECL(osl_isfinite_if, "if")
|
||||
DECL(osl_abs_ii, "ii")
|
||||
DECL(osl_fabs_ii, "ii")
|
||||
|
||||
UNARY_OP_IMPL(abs)
|
||||
UNARY_OP_IMPL(fabs)
|
||||
BINARY_OP_IMPL(fmod)
|
||||
|
||||
DECL (osl_smoothstep_ffff, "ffff")
|
||||
DECL (osl_smoothstep_dfffdf, "xXffX")
|
||||
DECL (osl_smoothstep_dffdff, "xXfXf")
|
||||
DECL (osl_smoothstep_dffdfdf, "xXfXX")
|
||||
DECL (osl_smoothstep_dfdfff, "xXXff")
|
||||
DECL (osl_smoothstep_dfdffdf, "xXXfX")
|
||||
DECL (osl_smoothstep_dfdfdff, "xXXXf")
|
||||
DECL (osl_smoothstep_dfdfdfdf, "xXXXX")
|
||||
DECL(osl_smoothstep_ffff, "ffff")
|
||||
DECL(osl_smoothstep_dfffdf, "xXffX")
|
||||
DECL(osl_smoothstep_dffdff, "xXfXf")
|
||||
DECL(osl_smoothstep_dffdfdf, "xXfXX")
|
||||
DECL(osl_smoothstep_dfdfff, "xXXff")
|
||||
DECL(osl_smoothstep_dfdffdf, "xXXfX")
|
||||
DECL(osl_smoothstep_dfdfdff, "xXXXf")
|
||||
DECL(osl_smoothstep_dfdfdfdf, "xXXXX")
|
||||
|
||||
DECL (osl_dot_fvv, "fXX")
|
||||
DECL (osl_dot_dfdvdv, "xXXX")
|
||||
DECL (osl_dot_dfdvv, "xXXX")
|
||||
DECL (osl_dot_dfvdv, "xXXX")
|
||||
DECL (osl_cross_vvv, "xXXX")
|
||||
DECL (osl_cross_dvdvdv, "xXXX")
|
||||
DECL (osl_cross_dvdvv, "xXXX")
|
||||
DECL (osl_cross_dvvdv, "xXXX")
|
||||
DECL (osl_length_fv, "fX")
|
||||
DECL (osl_length_dfdv, "xXX")
|
||||
DECL (osl_distance_fvv, "fXX")
|
||||
DECL (osl_distance_dfdvdv, "xXXX")
|
||||
DECL (osl_distance_dfdvv, "xXXX")
|
||||
DECL (osl_distance_dfvdv, "xXXX")
|
||||
DECL (osl_normalize_vv, "xXX")
|
||||
DECL (osl_normalize_dvdv, "xXX")
|
||||
DECL(osl_dot_fvv, "fXX")
|
||||
DECL(osl_dot_dfdvdv, "xXXX")
|
||||
DECL(osl_dot_dfdvv, "xXXX")
|
||||
DECL(osl_dot_dfvdv, "xXXX")
|
||||
DECL(osl_cross_vvv, "xXXX")
|
||||
DECL(osl_cross_dvdvdv, "xXXX")
|
||||
DECL(osl_cross_dvdvv, "xXXX")
|
||||
DECL(osl_cross_dvvdv, "xXXX")
|
||||
DECL(osl_length_fv, "fX")
|
||||
DECL(osl_length_dfdv, "xXX")
|
||||
DECL(osl_distance_fvv, "fXX")
|
||||
DECL(osl_distance_dfdvdv, "xXXX")
|
||||
DECL(osl_distance_dfdvv, "xXXX")
|
||||
DECL(osl_distance_dfvdv, "xXXX")
|
||||
DECL(osl_normalize_vv, "xXX")
|
||||
DECL(osl_normalize_dvdv, "xXX")
|
||||
#endif
|
||||
|
||||
|
||||
DECL (osl_mul_mmm, "xXXX")
|
||||
DECL (osl_mul_mmf, "xXXf")
|
||||
DECL(osl_mul_mmm, "xXXX")
|
||||
DECL(osl_mul_mmf, "xXXf")
|
||||
|
||||
DECL (osl_div_mmm, "xXXX")
|
||||
DECL (osl_div_mmf, "xXXf")
|
||||
DECL (osl_div_mfm, "xXfX")
|
||||
DECL(osl_div_mmm, "xXXX")
|
||||
DECL(osl_div_mmf, "xXXf")
|
||||
DECL(osl_div_mfm, "xXfX")
|
||||
|
||||
DECL (osl_get_from_to_matrix, "iXXss")
|
||||
DECL (osl_transpose_mm, "xXX")
|
||||
DECL (osl_determinant_fm, "fX")
|
||||
DECL(osl_get_from_to_matrix, "iXXss")
|
||||
DECL(osl_transpose_mm, "xXX")
|
||||
DECL(osl_determinant_fm, "fX")
|
||||
|
||||
DECL (osl_concat_sss, "sss")
|
||||
DECL (osl_strlen_is, "is")
|
||||
DECL (osl_hash_is, "is")
|
||||
DECL (osl_getchar_isi, "isi");
|
||||
DECL (osl_startswith_iss, "iss")
|
||||
DECL (osl_endswith_iss, "iss")
|
||||
DECL (osl_stoi_is, "is")
|
||||
DECL (osl_stof_fs, "fs")
|
||||
DECL (osl_substr_ssii, "ssii")
|
||||
DECL (osl_regex_impl, "iXsXisi")
|
||||
DECL(osl_concat_sss, "sss")
|
||||
DECL(osl_strlen_is, "is")
|
||||
DECL(osl_hash_is, "is")
|
||||
DECL(osl_getchar_isi, "isi");
|
||||
DECL(osl_startswith_iss, "iss")
|
||||
DECL(osl_endswith_iss, "iss")
|
||||
DECL(osl_stoi_is, "is")
|
||||
DECL(osl_stof_fs, "fs")
|
||||
DECL(osl_substr_ssii, "ssii")
|
||||
DECL(osl_regex_impl, "iXsXisi")
|
||||
|
||||
// Used by wide code generator, but are uniform calls
|
||||
DECL (osl_texture_decode_wrapmode, "iX");
|
||||
DECL (osl_texture_decode_interpmode, "iX");
|
||||
DECL(osl_texture_decode_wrapmode, "iX");
|
||||
DECL(osl_texture_decode_interpmode, "iX");
|
||||
|
||||
DECL (osl_texture_set_firstchannel, "xXi")
|
||||
DECL (osl_texture_set_swrap, "xXs")
|
||||
DECL (osl_texture_set_twrap, "xXs")
|
||||
DECL (osl_texture_set_rwrap, "xXs")
|
||||
DECL (osl_texture_set_stwrap, "xXs")
|
||||
DECL (osl_texture_set_swrap_code, "xXi")
|
||||
DECL (osl_texture_set_twrap_code, "xXi")
|
||||
DECL (osl_texture_set_rwrap_code, "xXi")
|
||||
DECL (osl_texture_set_stwrap_code, "xXi")
|
||||
DECL (osl_texture_set_sblur, "xXf")
|
||||
DECL (osl_texture_set_tblur, "xXf")
|
||||
DECL (osl_texture_set_rblur, "xXf")
|
||||
DECL (osl_texture_set_stblur, "xXf")
|
||||
DECL (osl_texture_set_swidth, "xXf")
|
||||
DECL (osl_texture_set_twidth, "xXf")
|
||||
DECL (osl_texture_set_rwidth, "xXf")
|
||||
DECL (osl_texture_set_stwidth, "xXf")
|
||||
DECL (osl_texture_set_fill, "xXf")
|
||||
DECL (osl_texture_set_time, "xXf")
|
||||
DECL (osl_texture_set_interp, "xXs")
|
||||
DECL (osl_texture_set_interp_code, "xXi")
|
||||
DECL (osl_texture_set_subimage, "xXi")
|
||||
DECL (osl_texture_set_subimagename, "xXs")
|
||||
DECL (osl_texture_set_missingcolor_arena, "xXX")
|
||||
DECL (osl_texture_set_missingcolor_alpha, "xXif")
|
||||
DECL (osl_texture, "iXXXXffffffiXXXXXXX")
|
||||
DECL (osl_texture3d, "iXXXXXXXXiXXXXXXX")
|
||||
DECL (osl_environment, "iXXXXXXXiXXXXXXX")
|
||||
DECL (osl_get_textureinfo, "iXXXXiiiXX")
|
||||
DECL (osl_get_textureinfo_st, "iXXXffXiiiXX")
|
||||
DECL(osl_texture_set_firstchannel, "xXi")
|
||||
DECL(osl_texture_set_swrap, "xXs")
|
||||
DECL(osl_texture_set_twrap, "xXs")
|
||||
DECL(osl_texture_set_rwrap, "xXs")
|
||||
DECL(osl_texture_set_stwrap, "xXs")
|
||||
DECL(osl_texture_set_swrap_code, "xXi")
|
||||
DECL(osl_texture_set_twrap_code, "xXi")
|
||||
DECL(osl_texture_set_rwrap_code, "xXi")
|
||||
DECL(osl_texture_set_stwrap_code, "xXi")
|
||||
DECL(osl_texture_set_sblur, "xXf")
|
||||
DECL(osl_texture_set_tblur, "xXf")
|
||||
DECL(osl_texture_set_rblur, "xXf")
|
||||
DECL(osl_texture_set_stblur, "xXf")
|
||||
DECL(osl_texture_set_swidth, "xXf")
|
||||
DECL(osl_texture_set_twidth, "xXf")
|
||||
DECL(osl_texture_set_rwidth, "xXf")
|
||||
DECL(osl_texture_set_stwidth, "xXf")
|
||||
DECL(osl_texture_set_fill, "xXf")
|
||||
DECL(osl_texture_set_time, "xXf")
|
||||
DECL(osl_texture_set_interp, "xXs")
|
||||
DECL(osl_texture_set_interp_code, "xXi")
|
||||
DECL(osl_texture_set_subimage, "xXi")
|
||||
DECL(osl_texture_set_subimagename, "xXs")
|
||||
DECL(osl_texture_set_missingcolor_arena, "xXX")
|
||||
DECL(osl_texture_set_missingcolor_alpha, "xXif")
|
||||
DECL(osl_texture, "iXXXXffffffiXXXXXXX")
|
||||
DECL(osl_texture3d, "iXXXXXXXXiXXXXXXX")
|
||||
DECL(osl_environment, "iXXXXXXXiXXXXXXX")
|
||||
DECL(osl_get_textureinfo, "iXXXXiiiXX")
|
||||
DECL(osl_get_textureinfo_st, "iXXXffXiiiXX")
|
||||
|
||||
DECL (osl_trace_set_mindist, "xXf")
|
||||
DECL (osl_trace_set_maxdist, "xXf")
|
||||
DECL (osl_trace_set_shade, "xXi")
|
||||
DECL (osl_trace_set_traceset, "xXs")
|
||||
DECL (osl_trace, "iXXXXXXXX")
|
||||
DECL(osl_trace_set_mindist, "xXf")
|
||||
DECL(osl_trace_set_maxdist, "xXf")
|
||||
DECL(osl_trace_set_shade, "xXi")
|
||||
DECL(osl_trace_set_traceset, "xXs")
|
||||
DECL(osl_trace, "iXXXXXXXX")
|
||||
|
||||
#ifdef OSL_LLVM_NO_BITCODE
|
||||
DECL (osl_calculatenormal, "xXXX")
|
||||
DECL (osl_area, "fX")
|
||||
DECL (osl_filterwidth_fdf, "fX")
|
||||
DECL (osl_filterwidth_vdv, "xXX")
|
||||
DECL (osl_raytype_bit, "iXi")
|
||||
DECL(osl_calculatenormal, "xXXX")
|
||||
DECL(osl_area, "fX")
|
||||
DECL(osl_filterwidth_fdf, "fX")
|
||||
DECL(osl_filterwidth_vdv, "xXX")
|
||||
DECL(osl_raytype_bit, "iXi")
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -143,15 +143,15 @@
|
||||
DECL(__OSL_MASKED_OP3(name, Wdv, Wv, Wdv), "xXXXi") \
|
||||
DECL(__OSL_MASKED_OP3(name, Wdv, Wdv, Wv), "xXXXi")
|
||||
|
||||
#define WIDE_BINARY_OP_IMPL(name) \
|
||||
DECL(__OSL_OP3(name, Wf, Wf, Wf), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdf, Wdf, Wdf), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdf, Wf, Wdf), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdf, Wdf, Wf), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wv, Wv, Wv), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdv, Wdv, Wdv), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdv, Wv, Wdv), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdv, Wdv, Wv), "xXXX") \
|
||||
#define WIDE_BINARY_OP_IMPL(name) \
|
||||
DECL(__OSL_OP3(name, Wf, Wf, Wf), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdf, Wdf, Wdf), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdf, Wf, Wdf), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdf, Wdf, Wf), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wv, Wv, Wv), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdv, Wdv, Wdv), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdv, Wv, Wdv), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdv, Wdv, Wv), "xXXX") \
|
||||
WIDE_BINARY_OP_MASKED_IMPL(name)
|
||||
|
||||
|
||||
@@ -168,14 +168,12 @@
|
||||
DECL(__OSL_OP3(name, Wv, Wv, Wv), "xXXX") \
|
||||
DECL(__OSL_MASKED_OP3(name, Wv, Wv, Wv), "xXXXi")
|
||||
|
||||
#if 0 // incomplete closure support
|
||||
DECL (osl_add_closure_closure, "CXCC")
|
||||
DECL (osl_mul_closure_float, "CXCf")
|
||||
DECL (osl_mul_closure_color, "CXCc")
|
||||
DECL (osl_allocate_closure_component, "CXii")
|
||||
DECL (osl_allocate_weighted_closure_component, "CXiiX")
|
||||
DECL (osl_closure_to_string, "sXC")
|
||||
#endif
|
||||
DECL(__OSL_MASKED_OP(allocate_closure_component), "xXXiii")
|
||||
DECL(__OSL_MASKED_OP(allocate_weighted_closure_component), "xXXiiXi")
|
||||
DECL(__OSL_MASKED_OP(add_closure_closure), "xXXXXi")
|
||||
DECL(__OSL_MASKED_OP(mul_closure_float), "xXXXXi")
|
||||
DECL(__OSL_MASKED_OP(mul_closure_color), "xXXXXi")
|
||||
DECL(__OSL_OP(closure_to_string), "sXX")
|
||||
|
||||
DECL(__OSL_OP(format), "xXis*")
|
||||
DECL(__OSL_OP(printf), "xXis*")
|
||||
@@ -243,19 +241,19 @@ WIDE_NOISE_DERIV_IMPL(unullnoise)
|
||||
|
||||
DECL(__OSL_MASKED_OP(count_noise), "xXi")
|
||||
|
||||
DECL (__OSL_OP2(hash,Wi,Wi), "xXX")
|
||||
DECL (__OSL_OP2(hash,Wi,Wf), "xXX")
|
||||
DECL (__OSL_OP3(hash,Wi,Wf,Wf), "xXXX")
|
||||
DECL (__OSL_OP2(hash,Wi,Wv), "xXX")
|
||||
DECL (__OSL_OP3(hash,Wi,Wv,Wf), "xXXX")
|
||||
DECL (__OSL_MASKED_OP2(hash,Wi,Wi), "xXXi")
|
||||
DECL (__OSL_MASKED_OP2(hash,Wi,Wf), "xXXi")
|
||||
DECL (__OSL_MASKED_OP3(hash,Wi,Wf,Wf), "xXXXi")
|
||||
DECL (__OSL_MASKED_OP2(hash,Wi,Wv), "xXXi")
|
||||
DECL (__OSL_MASKED_OP3(hash,Wi,Wv,Wf), "xXXXi")
|
||||
DECL(__OSL_OP2(hash, Wi, Wi), "xXX")
|
||||
DECL(__OSL_OP2(hash, Wi, Wf), "xXX")
|
||||
DECL(__OSL_OP3(hash, Wi, Wf, Wf), "xXXX")
|
||||
DECL(__OSL_OP2(hash, Wi, Wv), "xXX")
|
||||
DECL(__OSL_OP3(hash, Wi, Wv, Wf), "xXXX")
|
||||
DECL(__OSL_MASKED_OP2(hash, Wi, Wi), "xXXi")
|
||||
DECL(__OSL_MASKED_OP2(hash, Wi, Wf), "xXXi")
|
||||
DECL(__OSL_MASKED_OP3(hash, Wi, Wf, Wf), "xXXXi")
|
||||
DECL(__OSL_MASKED_OP2(hash, Wi, Wv), "xXXi")
|
||||
DECL(__OSL_MASKED_OP3(hash, Wi, Wv, Wf), "xXXXi")
|
||||
|
||||
// Need wide for combinations of the 3 parameters allowed to be uniform
|
||||
// caveat, some combos are unreachable/uneeded
|
||||
// caveat, some combos are unreachable/unneeded
|
||||
// When result has a derivative, there is
|
||||
// no "easy" have a input parameter be non-derivative based on code
|
||||
// analysis promoting all inputs to be derivative base.
|
||||
@@ -317,7 +315,7 @@ DECL(__OSL_MASKED_OP(pointcloud_get), "iXsXiXsLXi")
|
||||
DECL(__OSL_MASKED_OP(pointcloud_write), "iXsXiXXXi")
|
||||
|
||||
DECL(__OSL_MASKED_OP(getmessage), "xXXssLXiisii")
|
||||
DECL(__OSL_MASKED_OP2(setmessage, s, WX), "xXXLXisii")
|
||||
DECL(__OSL_MASKED_OP2(setmessage, s, WX), "xXXLXisii")
|
||||
DECL(__OSL_MASKED_OP2(setmessage, Ws, WX), "xXXLXisii")
|
||||
|
||||
DECL(__OSL_OP(blackbody_vf), "xXXf")
|
||||
@@ -383,7 +381,7 @@ DECL(__OSL_OP(get_attribute_uniform), "iXiXXiiXX")
|
||||
// TODO: shouldn't bind_interpolated_param be MASKED? change name to reflect
|
||||
DECL(__OSL_OP(bind_interpolated_param), "iXXLiXiXiXii")
|
||||
|
||||
//DECL (osl_get_texture_options, "XX") // uneeded
|
||||
//DECL (osl_get_texture_options, "XX") // unneeded
|
||||
DECL(__OSL_OP(get_noise_options), "XX")
|
||||
|
||||
// The following are defined inside llvm_ops.cpp. Only include these
|
||||
|
||||
+49
-37
@@ -2,15 +2,16 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <OpenImageIO/sysutil.h>
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
#include <OSL/oslclosure.h>
|
||||
#include <OSL/genclosure.h>
|
||||
#include <OSL/oslclosure.h>
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
#include "oslexec_pvt.h"
|
||||
|
||||
|
||||
@@ -38,46 +39,54 @@ namespace pvt {
|
||||
|
||||
|
||||
static void
|
||||
print_component_value(std::ostream &out, ShadingSystemImpl *ss,
|
||||
TypeDesc type, const void *data)
|
||||
print_component_value(std::ostream& out, ShadingSystemImpl* ss, TypeDesc type,
|
||||
const void* data)
|
||||
|
||||
{
|
||||
if (type == TypeDesc::TypeInt)
|
||||
out << *(int *)data;
|
||||
out << *(int*)data;
|
||||
else if (type == TypeDesc::TypeFloat)
|
||||
out << *(float *)data;
|
||||
out << *(float*)data;
|
||||
else if (type == TypeDesc::TypeColor)
|
||||
out << "(" << ((Color3 *)data)->x << ", " << ((Color3 *)data)->y << ", " << ((Color3 *)data)->z << ")";
|
||||
out << "(" << ((Color3*)data)->x << ", " << ((Color3*)data)->y << ", "
|
||||
<< ((Color3*)data)->z << ")";
|
||||
else if (type == TypeDesc::TypeVector)
|
||||
out << "(" << ((Vec3 *)data)->x << ", " << ((Vec3 *)data)->y << ", " << ((Vec3 *)data)->z << ")";
|
||||
out << "(" << ((Vec3*)data)->x << ", " << ((Vec3*)data)->y << ", "
|
||||
<< ((Vec3*)data)->z << ")";
|
||||
else if (type == TypeDesc::TypeString)
|
||||
out << "\"" << *((ustring *)data) << "\"";
|
||||
out << "\"" << *((ustring*)data) << "\"";
|
||||
else if (type == TypeDesc::PTR) // this only happens for closures
|
||||
print_closure (out, *(const ClosureColor **)data, ss);
|
||||
print_closure(out, *(const ClosureColor**)data, ss);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
print_component (std::ostream &out, const ClosureComponent *comp, ShadingSystemImpl *ss, const Color3 &weight)
|
||||
print_component(std::ostream& out, const ClosureComponent* comp,
|
||||
ShadingSystemImpl* ss, const Color3& weight)
|
||||
{
|
||||
const ClosureRegistry::ClosureEntry *clentry = ss->find_closure(comp->id);
|
||||
const ClosureRegistry::ClosureEntry* clentry = ss->find_closure(comp->id);
|
||||
OSL_ASSERT(clentry);
|
||||
out << "(" << weight.x*comp->w.x << ", " << weight.y*comp->w.y << ", " << weight.z*comp->w.z << ") * ";
|
||||
out << "(" << weight.x * comp->w.x << ", " << weight.y * comp->w.y << ", "
|
||||
<< weight.z * comp->w.z << ") * ";
|
||||
out << clentry->name.c_str() << " (";
|
||||
for (int i = 0, nparams = clentry->params.size() - 1; i < nparams; ++i) {
|
||||
if (i) out << ", ";
|
||||
if (i)
|
||||
out << ", ";
|
||||
const ClosureParam& param = clentry->params[i];
|
||||
if (param.key != 0)
|
||||
out << "\"" << param.key << "\", ";
|
||||
if (param.type.numelements() > 1) out << "[";
|
||||
if (param.type.numelements() > 1)
|
||||
out << "[";
|
||||
for (size_t j = 0; j < param.type.numelements(); ++j) {
|
||||
if (j) out << ", ";
|
||||
if (j)
|
||||
out << ", ";
|
||||
print_component_value(out, ss, param.type.elementtype(),
|
||||
(const char *)comp->data() + param.offset
|
||||
+ param.type.elementsize() * j);
|
||||
(const char*)comp->data() + param.offset
|
||||
+ param.type.elementsize() * j);
|
||||
}
|
||||
if (clentry->params[i].type.numelements() > 1) out << "]";
|
||||
if (clentry->params[i].type.numelements() > 1)
|
||||
out << "]";
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
@@ -85,32 +94,35 @@ print_component (std::ostream &out, const ClosureComponent *comp, ShadingSystemI
|
||||
|
||||
|
||||
static void
|
||||
print_closure (std::ostream &out, const ClosureColor *closure, ShadingSystemImpl *ss, const Color3 &w, bool &first)
|
||||
print_closure(std::ostream& out, const ClosureColor* closure,
|
||||
ShadingSystemImpl* ss, const Color3& w, bool& first)
|
||||
{
|
||||
if (closure == NULL)
|
||||
return;
|
||||
|
||||
switch (closure->id) {
|
||||
case ClosureColor::MUL:
|
||||
print_closure(out, closure->as_mul()->closure, ss, closure->as_mul()->weight * w, first);
|
||||
break;
|
||||
case ClosureColor::ADD:
|
||||
print_closure(out, closure->as_add()->closureA, ss, w, first);
|
||||
print_closure(out, closure->as_add()->closureB, ss, w, first);
|
||||
break;
|
||||
default:
|
||||
if (!first)
|
||||
out << "\n\t+ ";
|
||||
print_component (out, closure->as_comp(), ss, w);
|
||||
first = false;
|
||||
break;
|
||||
case ClosureColor::MUL:
|
||||
print_closure(out, closure->as_mul()->closure, ss,
|
||||
closure->as_mul()->weight * w, first);
|
||||
break;
|
||||
case ClosureColor::ADD:
|
||||
print_closure(out, closure->as_add()->closureA, ss, w, first);
|
||||
print_closure(out, closure->as_add()->closureB, ss, w, first);
|
||||
break;
|
||||
default:
|
||||
if (!first)
|
||||
out << "\n\t+ ";
|
||||
print_component(out, closure->as_comp(), ss, w);
|
||||
first = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
print_closure (std::ostream &out, const ClosureColor *closure, ShadingSystemImpl *ss)
|
||||
print_closure(std::ostream& out, const ClosureColor* closure,
|
||||
ShadingSystemImpl* ss)
|
||||
{
|
||||
bool first = true;
|
||||
print_closure(out, closure, ss, Color3(1, 1, 1), first);
|
||||
@@ -118,7 +130,7 @@ print_closure (std::ostream &out, const ClosureColor *closure, ShadingSystemImpl
|
||||
|
||||
|
||||
|
||||
} // namespace pvt
|
||||
} // namespace pvt
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#include <OpenImageIO/thread.h>
|
||||
|
||||
@@ -27,48 +27,48 @@ namespace pvt {
|
||||
/// a new allocation tries to fit it in one of the allocated blocks, but
|
||||
/// if it won't fit anywhere, it makes a new block and adds it to the
|
||||
/// head of the list.
|
||||
template<class T>
|
||||
class ConstantPool {
|
||||
template<class T> class ConstantPool {
|
||||
public:
|
||||
/// Allocate a new pool of T's. The quanta, if supplied, is the
|
||||
/// number of T's to malloc at a time.
|
||||
ConstantPool (size_t quanta = 1000000) : m_quanta(quanta), m_total(0) { }
|
||||
ConstantPool(size_t quanta = 1000000) : m_quanta(quanta), m_total(0) {}
|
||||
|
||||
~ConstantPool () { }
|
||||
~ConstantPool() {}
|
||||
|
||||
/// Allocate space enough for n T's, and return a pointer to the
|
||||
/// start of that space.
|
||||
T * alloc (size_t n) {
|
||||
OIIO::lock_guard lock (m_mutex);
|
||||
T* alloc(size_t n)
|
||||
{
|
||||
OIIO::lock_guard lock(m_mutex);
|
||||
// Check each block in the block list to see if it has enough space
|
||||
for (auto&& block : m_block_list) {
|
||||
size_t s = block.size();
|
||||
if ((s+n) <= block.capacity()) {
|
||||
if ((s + n) <= block.capacity()) {
|
||||
// Enough space in this block. Use it.
|
||||
block.resize (s+n);
|
||||
block.resize(s + n);
|
||||
return &block[s];
|
||||
}
|
||||
}
|
||||
// If we got here, there were no mini-blocks in the list with enough
|
||||
// space. Make a new one.
|
||||
m_block_list.push_front (block_t());
|
||||
block_t &block (m_block_list.front());
|
||||
size_t s = std::max (m_quanta, n);
|
||||
block.reserve (s);
|
||||
m_block_list.push_front(block_t());
|
||||
block_t& block(m_block_list.front());
|
||||
size_t s = std::max(m_quanta, n);
|
||||
block.reserve(s);
|
||||
m_total += s * sizeof(T);
|
||||
block.resize (n);
|
||||
block.resize(n);
|
||||
return &block[0];
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::vector<T> block_t; ///< Type of block
|
||||
std::list<block_t> m_block_list; ///< List of memory blocks
|
||||
size_t m_quanta; ///< How big each memory block is (in T's, not bytes)
|
||||
size_t m_total; ///< Total memory allocated (bytes!)
|
||||
size_t m_quanta; ///< How big each memory block is (in T's, not bytes)
|
||||
size_t m_total; ///< Total memory allocated (bytes!)
|
||||
OIIO::mutex m_mutex; ///< Thread-safe lock
|
||||
};
|
||||
|
||||
|
||||
|
||||
}; // namespace OSL::pvt
|
||||
}; // namespace pvt
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
+1206
-1133
File diff suppressed because it is too large
Load Diff
+210
-195
@@ -2,19 +2,19 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <OpenImageIO/sysutil.h>
|
||||
#include <OpenImageIO/timer.h>
|
||||
#include <OpenImageIO/thread.h>
|
||||
#include <OpenImageIO/timer.h>
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
#if OSL_USE_BATCHED
|
||||
#include <OSL/batched_shaderglobals.h>
|
||||
# include <OSL/batched_shaderglobals.h>
|
||||
#endif
|
||||
|
||||
#include <OSL/mask.h>
|
||||
@@ -32,36 +32,40 @@ static mutex buffered_file_output_mutex;
|
||||
|
||||
namespace pvt {
|
||||
|
||||
template <size_t ByteAlignmentT, typename T>
|
||||
inline bool is_aligned(const T *pointer)
|
||||
template<size_t ByteAlignmentT, typename T>
|
||||
inline bool
|
||||
is_aligned(const T* pointer)
|
||||
{
|
||||
std::uintptr_t ptrAsUint = reinterpret_cast<std::uintptr_t>(pointer);
|
||||
return (ptrAsUint%ByteAlignmentT==0);
|
||||
return (ptrAsUint % ByteAlignmentT == 0);
|
||||
}
|
||||
|
||||
} // namespace pvt
|
||||
} // namespace pvt
|
||||
|
||||
ShadingContext::ShadingContext (ShadingSystemImpl &shadingsys,
|
||||
PerThreadInfo *threadinfo)
|
||||
: m_shadingsys(shadingsys), m_renderer(m_shadingsys.renderer()),
|
||||
m_group(NULL), m_max_warnings(shadingsys.max_warnings_per_thread()),
|
||||
m_dictionary(NULL), batch_size_executed(0)
|
||||
ShadingContext::ShadingContext(ShadingSystemImpl& shadingsys,
|
||||
PerThreadInfo* threadinfo)
|
||||
: m_shadingsys(shadingsys)
|
||||
, m_renderer(m_shadingsys.renderer())
|
||||
, m_group(NULL)
|
||||
, m_max_warnings(shadingsys.max_warnings_per_thread())
|
||||
, m_dictionary(NULL)
|
||||
, batch_size_executed(0)
|
||||
{
|
||||
m_shadingsys.m_stat_contexts += 1;
|
||||
m_threadinfo = threadinfo ? threadinfo : shadingsys.get_perthread_info ();
|
||||
m_threadinfo = threadinfo ? threadinfo : shadingsys.get_perthread_info();
|
||||
m_texture_thread_info = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ShadingContext::~ShadingContext ()
|
||||
ShadingContext::~ShadingContext()
|
||||
{
|
||||
process_errors ();
|
||||
process_errors();
|
||||
#if OSL_USE_BATCHED
|
||||
process_file_output();
|
||||
#endif
|
||||
m_shadingsys.m_stat_contexts -= 1;
|
||||
free_dict_resources ();
|
||||
free_dict_resources();
|
||||
}
|
||||
|
||||
|
||||
@@ -72,61 +76,64 @@ ShadingContext::execute_init(ShaderGroup& sgroup, int shadeindex,
|
||||
void* output_base_ptr, bool run)
|
||||
{
|
||||
if (m_group)
|
||||
execute_cleanup ();
|
||||
execute_cleanup();
|
||||
batch_size_executed = 0;
|
||||
m_group = &sgroup;
|
||||
m_ticks = 0;
|
||||
m_group = &sgroup;
|
||||
m_ticks = 0;
|
||||
|
||||
// Optimize if we haven't already
|
||||
if (sgroup.nlayers()) {
|
||||
sgroup.start_running ();
|
||||
if (! sgroup.jitted()) {
|
||||
sgroup.start_running();
|
||||
if (!sgroup.jitted()) {
|
||||
auto ctx = shadingsys().get_context(thread_info());
|
||||
shadingsys().optimize_group (sgroup, ctx, true /*do_jit*/);
|
||||
if (shadingsys().m_greedyjit && shadingsys().m_groups_to_compile_count) {
|
||||
shadingsys().optimize_group(sgroup, ctx, true /*do_jit*/);
|
||||
if (shadingsys().m_greedyjit
|
||||
&& shadingsys().m_groups_to_compile_count) {
|
||||
// If we are greedily JITing, optimize/JIT everything now
|
||||
shadingsys().optimize_all_groups ();
|
||||
shadingsys().optimize_all_groups();
|
||||
}
|
||||
shadingsys().release_context(ctx);
|
||||
}
|
||||
if (sgroup.does_nothing())
|
||||
return false;
|
||||
} else {
|
||||
// empty shader - nothing to do!
|
||||
return false;
|
||||
// empty shader - nothing to do!
|
||||
return false;
|
||||
}
|
||||
|
||||
int profile = shadingsys().m_profile;
|
||||
OIIO::Timer timer (profile ? OIIO::Timer::StartNow : OIIO::Timer::DontStartNow);
|
||||
OIIO::Timer timer(profile ? OIIO::Timer::StartNow
|
||||
: OIIO::Timer::DontStartNow);
|
||||
|
||||
// Allocate enough space on the heap
|
||||
size_t heap_size_needed = sgroup.llvm_groupdata_size();
|
||||
reserve_heap(heap_size_needed);
|
||||
// Zero out the heap memory we will be using
|
||||
if (shadingsys().m_clearmemory)
|
||||
memset (m_heap.get(), 0, heap_size_needed);
|
||||
memset(m_heap.get(), 0, heap_size_needed);
|
||||
|
||||
// Set up closure storage
|
||||
m_closure_pool.clear();
|
||||
|
||||
// Clear the message blackboard
|
||||
m_messages.clear ();
|
||||
m_messages.clear();
|
||||
|
||||
// Clear miscellaneous scratch space
|
||||
m_scratch_pool.clear ();
|
||||
m_scratch_pool.clear();
|
||||
|
||||
// Zero out stats for this execution
|
||||
clear_runtime_stats ();
|
||||
clear_runtime_stats();
|
||||
|
||||
if (run) {
|
||||
RunLLVMGroupFunc run_func = sgroup.llvm_compiled_init();
|
||||
if (!run_func)
|
||||
return false;
|
||||
ssg.context = this;
|
||||
ssg.renderer = renderer();
|
||||
ssg.Ci = NULL;
|
||||
run_func (&ssg, m_heap.get(), userdata_base_ptr, output_base_ptr,
|
||||
shadeindex);
|
||||
ssg.context = this;
|
||||
ssg.shadingStateUniform = &(shadingsys().m_shading_state_uniform);
|
||||
ssg.renderer = renderer();
|
||||
ssg.Ci = NULL;
|
||||
run_func(&ssg, m_heap.get(), userdata_base_ptr, output_base_ptr,
|
||||
shadeindex);
|
||||
}
|
||||
|
||||
if (profile)
|
||||
@@ -146,14 +153,15 @@ ShadingContext::execute_layer(int shadeindex, ShaderGlobals& ssg,
|
||||
OSL_DASSERT(ssg.context == this && ssg.renderer == renderer());
|
||||
|
||||
int profile = shadingsys().m_profile;
|
||||
OIIO::Timer timer (profile ? OIIO::Timer::StartNow : OIIO::Timer::DontStartNow);
|
||||
OIIO::Timer timer(profile ? OIIO::Timer::StartNow
|
||||
: OIIO::Timer::DontStartNow);
|
||||
|
||||
RunLLVMGroupFunc run_func = group()->llvm_compiled_layer (layernumber);
|
||||
if (! run_func)
|
||||
RunLLVMGroupFunc run_func = group()->llvm_compiled_layer(layernumber);
|
||||
if (!run_func)
|
||||
return false;
|
||||
|
||||
run_func (&ssg, m_heap.get(), userdata_base_ptr, output_base_ptr,
|
||||
shadeindex);
|
||||
run_func(&ssg, m_heap.get(), userdata_base_ptr, output_base_ptr,
|
||||
shadeindex);
|
||||
|
||||
if (profile)
|
||||
m_ticks += timer.ticks();
|
||||
@@ -164,21 +172,21 @@ ShadingContext::execute_layer(int shadeindex, ShaderGlobals& ssg,
|
||||
|
||||
|
||||
bool
|
||||
ShadingContext::execute_cleanup ()
|
||||
ShadingContext::execute_cleanup()
|
||||
{
|
||||
if (! group()) {
|
||||
errorf("execute_cleanup called again on a cleaned-up context");
|
||||
if (!group()) {
|
||||
errorfmt("execute_cleanup called again on a cleaned-up context");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Process any queued up error messages, warnings, printfs from shaders
|
||||
process_errors ();
|
||||
process_errors();
|
||||
#if OSL_USE_BATCHED
|
||||
process_file_output();
|
||||
#endif
|
||||
|
||||
if (shadingsys().m_profile) {
|
||||
record_runtime_stats (); // Transfer runtime stats to the shadingsys
|
||||
record_runtime_stats(); // Transfer runtime stats to the shadingsys
|
||||
shadingsys().m_stat_total_shading_time_ticks += m_ticks;
|
||||
group()->m_stat_total_shading_time_ticks += m_ticks;
|
||||
}
|
||||
@@ -189,38 +197,38 @@ ShadingContext::execute_cleanup ()
|
||||
|
||||
|
||||
bool
|
||||
ShadingContext::execute (ShaderGroup &sgroup, int shadeindex,
|
||||
ShaderGlobals &ssg, void* userdata_base_ptr,
|
||||
void* output_base_ptr, bool run)
|
||||
ShadingContext::execute(ShaderGroup& sgroup, int shadeindex, ShaderGlobals& ssg,
|
||||
void* userdata_base_ptr, void* output_base_ptr,
|
||||
bool run)
|
||||
{
|
||||
int n = sgroup.m_exec_repeat;
|
||||
Vec3 Psave, Nsave; // for repeats
|
||||
Vec3 Psave, Nsave; // for repeats
|
||||
bool repeat = (n > 1);
|
||||
if (repeat) {
|
||||
// If we're going to repeat more than once, we need to save any
|
||||
// globals that might get modified.
|
||||
Psave = ssg.P;
|
||||
Nsave = ssg.N;
|
||||
if (! run)
|
||||
if (!run)
|
||||
n = 1;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
while (1) {
|
||||
if (! execute_init (sgroup, shadeindex, ssg, userdata_base_ptr,
|
||||
output_base_ptr, run))
|
||||
if (!execute_init(sgroup, shadeindex, ssg, userdata_base_ptr,
|
||||
output_base_ptr, run))
|
||||
return false;
|
||||
if (run && n)
|
||||
execute_layer (shadeindex, ssg, userdata_base_ptr, output_base_ptr,
|
||||
group()->nlayers() - 1);
|
||||
result = execute_cleanup ();
|
||||
execute_layer(shadeindex, ssg, userdata_base_ptr, output_base_ptr,
|
||||
group()->nlayers() - 1);
|
||||
result = execute_cleanup();
|
||||
if (--n < 1)
|
||||
break; // done
|
||||
break; // done
|
||||
if (repeat) {
|
||||
// Going around for another pass... restore things as best as we
|
||||
// can.
|
||||
ssg.P = Psave;
|
||||
ssg.N = Nsave;
|
||||
ssg.P = Psave;
|
||||
ssg.N = Nsave;
|
||||
ssg.Ci = NULL;
|
||||
}
|
||||
}
|
||||
@@ -232,24 +240,22 @@ ShadingContext::execute (ShaderGroup &sgroup, int shadeindex,
|
||||
|
||||
template<int WidthT>
|
||||
bool
|
||||
ShadingContext::Batched<WidthT>::execute_init( ShaderGroup &sgroup,
|
||||
int batch_size,
|
||||
Wide<const int, WidthT> wide_shadeindex,
|
||||
BatchedShaderGlobals<WidthT> &bsg,
|
||||
void* userdata_base_ptr,
|
||||
void* output_base_ptr, bool run)
|
||||
ShadingContext::Batched<WidthT>::execute_init(
|
||||
ShaderGroup& sgroup, int batch_size,
|
||||
Wide<const int, WidthT> wide_shadeindex, BatchedShaderGlobals<WidthT>& bsg,
|
||||
void* userdata_base_ptr, void* output_base_ptr, bool run)
|
||||
{
|
||||
if (context().m_group)
|
||||
context().execute_cleanup ();
|
||||
context().execute_cleanup();
|
||||
|
||||
context().batch_size_executed = batch_size;
|
||||
context().m_group = &sgroup;
|
||||
context().m_ticks = 0;
|
||||
context().m_group = &sgroup;
|
||||
context().m_ticks = 0;
|
||||
|
||||
// Optimize if we haven't already
|
||||
if (sgroup.nlayers()) {
|
||||
sgroup.start_running ();
|
||||
if (! sgroup.batch_jitted()) {
|
||||
sgroup.start_running();
|
||||
if (!sgroup.batch_jitted()) {
|
||||
// Matching ShadingContext::execute_init behavior
|
||||
// of grabbing another context.
|
||||
// TODO: Is this necessary, why can't we just use the
|
||||
@@ -257,7 +263,8 @@ ShadingContext::Batched<WidthT>::execute_init( ShaderGroup &sgroup,
|
||||
//shadingsys().template batched<WidthT>().jit_group(sgroup, &context());
|
||||
auto ctx = shadingsys().get_context(context().thread_info());
|
||||
shadingsys().template batched<WidthT>().jit_group(sgroup, ctx);
|
||||
if (shadingsys().m_greedyjit && shadingsys().m_groups_to_compile_count) {
|
||||
if (shadingsys().m_greedyjit
|
||||
&& shadingsys().m_groups_to_compile_count) {
|
||||
// If we are greedily JITing, optimize/JIT everything now
|
||||
shadingsys().template batched<WidthT>().jit_all_groups();
|
||||
}
|
||||
@@ -273,47 +280,48 @@ ShadingContext::Batched<WidthT>::execute_init( ShaderGroup &sgroup,
|
||||
// default value ourselves
|
||||
|
||||
} else {
|
||||
// empty shader - nothing to do!
|
||||
return false;
|
||||
// empty shader - nothing to do!
|
||||
return false;
|
||||
}
|
||||
|
||||
int profile = shadingsys().m_profile;
|
||||
OIIO::Timer timer (profile ? OIIO::Timer::StartNow : OIIO::Timer::DontStartNow);
|
||||
OIIO::Timer timer(profile ? OIIO::Timer::StartNow
|
||||
: OIIO::Timer::DontStartNow);
|
||||
|
||||
// Allocate enough space on the heap
|
||||
size_t heap_size_needed = sgroup.llvm_groupdata_wide_size();
|
||||
context().reserve_heap(heap_size_needed);
|
||||
// Zero out the heap memory we will be using
|
||||
if (shadingsys().m_clearmemory)
|
||||
memset (context().m_heap.get(), 0, heap_size_needed);
|
||||
memset(context().m_heap.get(), 0, heap_size_needed);
|
||||
|
||||
// Set up closure storage
|
||||
context().m_closure_pool.clear();
|
||||
|
||||
// Clear the message blackboard
|
||||
context().m_messages.clear ();
|
||||
context().batched_messages_buffer().clear ();
|
||||
context().m_messages.clear();
|
||||
context().batched_messages_buffer().clear();
|
||||
|
||||
// Clear miscellaneous scratch space
|
||||
context().m_scratch_pool.clear ();
|
||||
context().m_scratch_pool.clear();
|
||||
|
||||
// Zero out stats for this execution
|
||||
context().clear_runtime_stats ();
|
||||
context().clear_runtime_stats();
|
||||
|
||||
if (run) {
|
||||
bsg.uniform.context = &context();
|
||||
bsg.uniform.context = &context();
|
||||
bsg.uniform.renderer = context().renderer();
|
||||
bsg.uniform.Ci = NULL;
|
||||
assign_all(bsg.varying.Ci, (ClosureColor*)nullptr);
|
||||
RunLLVMGroupFuncWide run_func = sgroup.llvm_compiled_wide_init();
|
||||
OSL_DASSERT (run_func);
|
||||
OSL_DASSERT (sgroup.llvm_groupdata_wide_size() <= context().m_heapsize);
|
||||
OSL_DASSERT(run_func);
|
||||
OSL_DASSERT(sgroup.llvm_groupdata_wide_size() <= context().m_heapsize);
|
||||
|
||||
if(batch_size > 0) {
|
||||
if (batch_size > 0) {
|
||||
Mask<WidthT> run_mask(false);
|
||||
run_mask.set_count_on(batch_size);
|
||||
|
||||
run_func (&bsg, context().m_heap.get(), &wide_shadeindex.data(),
|
||||
userdata_base_ptr, output_base_ptr, run_mask.value());
|
||||
run_func(&bsg, context().m_heap.get(), &wide_shadeindex.data(),
|
||||
userdata_base_ptr, output_base_ptr, run_mask.value());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,22 +332,24 @@ ShadingContext::Batched<WidthT>::execute_init( ShaderGroup &sgroup,
|
||||
|
||||
template<int WidthT>
|
||||
bool
|
||||
ShadingContext::Batched<WidthT>::execute_layer (int batch_size,
|
||||
Wide<const int, WidthT> wide_shadeindex,
|
||||
BatchedShaderGlobals<WidthT> &bsg,
|
||||
void* userdata_base_ptr,
|
||||
void* output_base_ptr,
|
||||
int layernumber)
|
||||
ShadingContext::Batched<WidthT>::execute_layer(
|
||||
int batch_size, Wide<const int, WidthT> wide_shadeindex,
|
||||
BatchedShaderGlobals<WidthT>& bsg, void* userdata_base_ptr,
|
||||
void* output_base_ptr, int layernumber)
|
||||
{
|
||||
if (!group() || group()->nlayers() == 0 || group()->does_nothing() || (context().batch_size_executed != batch_size))
|
||||
if (!group() || group()->nlayers() == 0 || group()->does_nothing()
|
||||
|| (context().batch_size_executed != batch_size))
|
||||
return false;
|
||||
OSL_DASSERT (bsg.uniform.context == &context() && bsg.uniform.renderer == context().renderer());
|
||||
OSL_DASSERT(bsg.uniform.context == &context()
|
||||
&& bsg.uniform.renderer == context().renderer());
|
||||
|
||||
int profile = shadingsys().m_profile;
|
||||
OIIO::Timer timer (profile ? OIIO::Timer::StartNow : OIIO::Timer::DontStartNow);
|
||||
OIIO::Timer timer(profile ? OIIO::Timer::StartNow
|
||||
: OIIO::Timer::DontStartNow);
|
||||
|
||||
RunLLVMGroupFuncWide run_func = group()->llvm_compiled_wide_layer (layernumber);
|
||||
if (! run_func)
|
||||
RunLLVMGroupFuncWide run_func = group()->llvm_compiled_wide_layer(
|
||||
layernumber);
|
||||
if (!run_func)
|
||||
return false;
|
||||
|
||||
OSL_ASSERT(pvt::is_aligned<64>(&bsg));
|
||||
@@ -349,8 +359,8 @@ ShadingContext::Batched<WidthT>::execute_layer (int batch_size,
|
||||
Mask<WidthT> run_mask(false);
|
||||
run_mask.set_count_on(batch_size);
|
||||
|
||||
run_func (&bsg, context().m_heap.get(), &wide_shadeindex.data(),
|
||||
userdata_base_ptr, output_base_ptr, run_mask.value());
|
||||
run_func(&bsg, context().m_heap.get(), &wide_shadeindex.data(),
|
||||
userdata_base_ptr, output_base_ptr, run_mask.value());
|
||||
}
|
||||
|
||||
if (profile)
|
||||
@@ -362,83 +372,85 @@ ShadingContext::Batched<WidthT>::execute_layer (int batch_size,
|
||||
|
||||
template<int WidthT>
|
||||
bool
|
||||
ShadingContext::Batched<WidthT>::execute(ShaderGroup &sgroup, int batch_size,
|
||||
Wide<const int, WidthT> wide_shadeindex,
|
||||
BatchedShaderGlobals<WidthT> &bsg,
|
||||
void* userdata_base_ptr,
|
||||
void* output_base_ptr, bool run)
|
||||
ShadingContext::Batched<WidthT>::execute(
|
||||
ShaderGroup& sgroup, int batch_size,
|
||||
Wide<const int, WidthT> wide_shadeindex, BatchedShaderGlobals<WidthT>& bsg,
|
||||
void* userdata_base_ptr, void* output_base_ptr, bool run)
|
||||
{
|
||||
OSL_ASSERT(is_aligned<64>(&bsg));
|
||||
int n = sgroup.m_exec_repeat;
|
||||
|
||||
Block<Vec3,WidthT> Psave, Nsave; // for repeats
|
||||
Block<Vec3, WidthT> Psave, Nsave; // for repeats
|
||||
bool repeat = (n > 1);
|
||||
if (repeat) {
|
||||
// If we're going to repeat more than once, we need to save any
|
||||
// globals that might get modified.
|
||||
Psave = bsg.varying.P;
|
||||
Nsave = bsg.varying.N;
|
||||
if (! run)
|
||||
if (!run)
|
||||
n = 1;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
while (1) {
|
||||
if (! execute_init (sgroup, batch_size, wide_shadeindex, bsg,
|
||||
userdata_base_ptr, output_base_ptr, run))
|
||||
if (!execute_init(sgroup, batch_size, wide_shadeindex, bsg,
|
||||
userdata_base_ptr, output_base_ptr, run))
|
||||
return false;
|
||||
if (run && n)
|
||||
execute_layer (batch_size, wide_shadeindex, bsg,
|
||||
userdata_base_ptr, output_base_ptr,
|
||||
group()->nlayers()-1);
|
||||
result = context().execute_cleanup ();
|
||||
execute_layer(batch_size, wide_shadeindex, bsg, userdata_base_ptr,
|
||||
output_base_ptr, group()->nlayers() - 1);
|
||||
result = context().execute_cleanup();
|
||||
if (--n < 1)
|
||||
break; // done
|
||||
break; // done
|
||||
if (repeat) {
|
||||
// Going around for another pass... restore things as best as we
|
||||
// can.
|
||||
bsg.varying.P = Psave;
|
||||
bsg.varying.N = Nsave;
|
||||
bsg.uniform.Ci = NULL;
|
||||
assign_all(bsg.varying.Ci, (ClosureColor*)nullptr);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
ShadingContext::record_error (ErrorHandler::ErrCode code,
|
||||
const std::string &text, Mask<MaxSupportedSimdLaneCount> mask) const
|
||||
ShadingContext::record_error(ErrorHandler::ErrCode code,
|
||||
const std::string& text,
|
||||
Mask<MaxSupportedSimdLaneCount> mask) const
|
||||
{
|
||||
m_buffered_errors.emplace_back (code,text, mask);
|
||||
m_buffered_errors.emplace_back(code, text, mask);
|
||||
// If we aren't buffering, just process immediately
|
||||
if (! shadingsys().m_buffer_printf)
|
||||
process_errors ();
|
||||
if (!shadingsys().m_buffer_printf)
|
||||
process_errors();
|
||||
}
|
||||
|
||||
void
|
||||
ShadingContext::record_to_file (ustring filename,
|
||||
const std::string &text, Mask<MaxSupportedSimdLaneCount> mask) const
|
||||
ShadingContext::record_to_file(ustring filename, const std::string& text,
|
||||
Mask<MaxSupportedSimdLaneCount> mask) const
|
||||
{
|
||||
m_buffered_file_output.emplace_back (filename,text, mask);
|
||||
m_buffered_file_output.emplace_back(filename, text, mask);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
ShadingContext::record_error (ErrorHandler::ErrCode code,
|
||||
const std::string &text) const
|
||||
ShadingContext::record_error(ErrorHandler::ErrCode code,
|
||||
const std::string& text) const
|
||||
{
|
||||
m_buffered_errors.emplace_back(code,text);
|
||||
m_buffered_errors.emplace_back(code, text);
|
||||
// If we aren't buffering, just process immediately
|
||||
if (! shadingsys().m_buffer_printf)
|
||||
process_errors ();
|
||||
if (!shadingsys().m_buffer_printf)
|
||||
process_errors();
|
||||
}
|
||||
|
||||
|
||||
// separate declaration from definition of template function
|
||||
// to ensure noinline is respected
|
||||
template<typename ErrorsT, typename TestFunctorT>
|
||||
static OSL_NOINLINE void process_errors_helper (ShadingSystemImpl &shading_sys, const ErrorsT &errors, int startAtError, int endBeforeError, const TestFunctorT & test_func);
|
||||
static OSL_NOINLINE void
|
||||
process_errors_helper(ShadingSystemImpl& shading_sys, const ErrorsT& errors,
|
||||
int startAtError, int endBeforeError,
|
||||
const TestFunctorT& test_func);
|
||||
|
||||
// Given array of ErrorItems emit errors within the range startAtError to
|
||||
// endBeforeError if and only if the test_func passed each ErrorItem's mask
|
||||
@@ -446,55 +458,57 @@ static OSL_NOINLINE void process_errors_helper (ShadingSystemImpl &shading_sys,
|
||||
// each data lane separately effectively serializing emission of errors,
|
||||
// warnings, info, and messages
|
||||
template<typename ErrorsT, typename TestFunctorT>
|
||||
void process_errors_helper (ShadingSystemImpl &shading_sys, const ErrorsT &errors, int startAtError, int endBeforeError, const TestFunctorT & test_func)
|
||||
void
|
||||
process_errors_helper(ShadingSystemImpl& shading_sys, const ErrorsT& errors,
|
||||
int startAtError, int endBeforeError,
|
||||
const TestFunctorT& test_func)
|
||||
{
|
||||
for (int i = startAtError; i < endBeforeError; ++i) {
|
||||
const auto & error_item = errors[i];
|
||||
for (int i = startAtError; i < endBeforeError; ++i) {
|
||||
const auto& error_item = errors[i];
|
||||
if (test_func(error_item.mask)) {
|
||||
switch (errors[i].err_code) {
|
||||
case ErrorHandler::EH_MESSAGE :
|
||||
case ErrorHandler::EH_DEBUG :
|
||||
shading_sys.message (error_item.msgString);
|
||||
case ErrorHandler::EH_MESSAGE:
|
||||
case ErrorHandler::EH_DEBUG:
|
||||
shading_sys.message(error_item.msgString);
|
||||
break;
|
||||
case ErrorHandler::EH_INFO :
|
||||
shading_sys.info (error_item.msgString);
|
||||
case ErrorHandler::EH_INFO:
|
||||
shading_sys.info(error_item.msgString);
|
||||
break;
|
||||
case ErrorHandler::EH_WARNING :
|
||||
shading_sys.warning (error_item.msgString);
|
||||
case ErrorHandler::EH_WARNING:
|
||||
shading_sys.warning(error_item.msgString);
|
||||
break;
|
||||
case ErrorHandler::EH_ERROR :
|
||||
case ErrorHandler::EH_SEVERE :
|
||||
shading_sys.error (error_item.msgString);
|
||||
break;
|
||||
default:
|
||||
case ErrorHandler::EH_ERROR:
|
||||
case ErrorHandler::EH_SEVERE:
|
||||
shading_sys.error(error_item.msgString);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ShadingContext::process_errors () const
|
||||
ShadingContext::process_errors() const
|
||||
{
|
||||
int nerrors(m_buffered_errors.size());
|
||||
if (! nerrors)
|
||||
if (!nerrors)
|
||||
return;
|
||||
|
||||
// Use a mutex to make sure output from different threads stays
|
||||
// together, at least for one shader invocation, rather than being
|
||||
// interleaved with other threads.
|
||||
lock_guard lock (buffered_errors_mutex);
|
||||
lock_guard lock(buffered_errors_mutex);
|
||||
|
||||
#if OSL_USE_BATCHED
|
||||
if (execution_is_batched()) {
|
||||
OSL_DASSERT(batch_size_executed <= MaxSupportedSimdLaneCount);
|
||||
// Process each data lane separately and in the correct order
|
||||
for(int lane=0; lane < batch_size_executed; ++lane) {
|
||||
for (int lane = 0; lane < batch_size_executed; ++lane) {
|
||||
OSL_INTEL_PRAGMA(noinline)
|
||||
process_errors_helper(shadingsys(), m_buffered_errors, 0, nerrors,
|
||||
process_errors_helper(
|
||||
shadingsys(), m_buffered_errors, 0, nerrors,
|
||||
// Test Function returns true to process the ErrorItem
|
||||
[=](Mask<MaxSupportedSimdLaneCount> mask)->bool
|
||||
{
|
||||
[=](Mask<MaxSupportedSimdLaneCount> mask) -> bool {
|
||||
return mask.is_on(lane);
|
||||
});
|
||||
}
|
||||
@@ -503,10 +517,10 @@ ShadingContext::process_errors () const
|
||||
{
|
||||
// Non-batch errors: ignore the mask, just print them out once
|
||||
OSL_INTEL_PRAGMA(noinline)
|
||||
process_errors_helper(shadingsys(), m_buffered_errors, 0, nerrors,
|
||||
process_errors_helper(
|
||||
shadingsys(), m_buffered_errors, 0, nerrors,
|
||||
// Test Function returns true to process the ErrorItem
|
||||
[=](Mask<MaxSupportedSimdLaneCount> /*mask*/)->bool
|
||||
{
|
||||
[=](Mask<MaxSupportedSimdLaneCount> /*mask*/) -> bool {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@@ -515,29 +529,29 @@ ShadingContext::process_errors () const
|
||||
|
||||
#if OSL_USE_BATCHED
|
||||
void
|
||||
ShadingContext::process_file_output () const
|
||||
ShadingContext::process_file_output() const
|
||||
{
|
||||
int nerrors(m_buffered_file_output.size());
|
||||
if (! nerrors)
|
||||
if (!nerrors)
|
||||
return;
|
||||
|
||||
// Use a mutex to make sure output from different threads stays
|
||||
// together, at least for one shader invocation, rather than being
|
||||
// interleaved with other threads.
|
||||
lock_guard lock (buffered_file_output_mutex);
|
||||
lock_guard lock(buffered_file_output_mutex);
|
||||
|
||||
OSL_ASSERT(execution_is_batched());
|
||||
OSL_DASSERT(batch_size_executed <= MaxSupportedSimdLaneCount);
|
||||
// Process each data lane separately and in the correct order
|
||||
for(int lane=0; lane < batch_size_executed; ++lane) {
|
||||
for (int i = 0; i < nerrors; ++i) {
|
||||
const auto & item = m_buffered_file_output[i];
|
||||
if (item.mask.is_on(lane)){
|
||||
for (int lane = 0; lane < batch_size_executed; ++lane) {
|
||||
for (int i = 0; i < nerrors; ++i) {
|
||||
const auto& item = m_buffered_file_output[i];
|
||||
if (item.mask.is_on(lane)) {
|
||||
// TODO: if performance critical, one could keep a cache of
|
||||
// open files instead of closing and reopening
|
||||
FILE *file = fopen (item.filename.c_str(), "a");
|
||||
fputs (item.msgString.c_str(), file);
|
||||
fclose (file);
|
||||
FILE* file = fopen(item.filename.c_str(), "a");
|
||||
fputs(item.msgString.c_str(), file);
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -545,32 +559,33 @@ ShadingContext::process_file_output () const
|
||||
}
|
||||
#endif
|
||||
|
||||
const Symbol *
|
||||
ShadingContext::symbol (ustring layername, ustring symbolname) const
|
||||
const Symbol*
|
||||
ShadingContext::symbol(ustring layername, ustring symbolname) const
|
||||
{
|
||||
return group()->find_symbol (layername, symbolname);
|
||||
return group()->find_symbol(layername, symbolname);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const void *
|
||||
ShadingContext::symbol_data (const Symbol &sym) const
|
||||
const void*
|
||||
ShadingContext::symbol_data(const Symbol& sym) const
|
||||
{
|
||||
const ShaderGroup &sgroup (*group());
|
||||
const ShaderGroup& sgroup(*group());
|
||||
#if OSL_USE_BATCHED
|
||||
if (execution_is_batched()) {
|
||||
if (! sgroup.batch_jitted())
|
||||
return NULL; // can't retrieve symbol if we didn't optimize & batched jit
|
||||
if (!sgroup.batch_jitted())
|
||||
return NULL; // can't retrieve symbol if we didn't optimize & batched jit
|
||||
|
||||
if (sym.wide_dataoffset() >= 0 && (int)m_heapsize > sym.wide_dataoffset()) {
|
||||
if (sym.wide_dataoffset() >= 0
|
||||
&& (int)m_heapsize > sym.wide_dataoffset()) {
|
||||
// lives on the heap
|
||||
return m_heap.get() + sym.wide_dataoffset();
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (! sgroup.jitted())
|
||||
return NULL; // can't retrieve symbol if we didn't optimize & jit
|
||||
if (!sgroup.jitted())
|
||||
return NULL; // can't retrieve symbol if we didn't optimize & jit
|
||||
|
||||
if (sym.dataoffset() >= 0 && (int)m_heapsize > sym.dataoffset()) {
|
||||
// lives on the heap
|
||||
@@ -581,8 +596,9 @@ ShadingContext::symbol_data (const Symbol &sym) const
|
||||
}
|
||||
|
||||
// doesn't live on the heap
|
||||
if ((sym.symtype() == SymTypeParam || sym.symtype() == SymTypeOutputParam) &&
|
||||
(sym.valuesource() == Symbol::DefaultVal || sym.valuesource() == Symbol::InstanceVal)) {
|
||||
if ((sym.symtype() == SymTypeParam || sym.symtype() == SymTypeOutputParam)
|
||||
&& (sym.valuesource() == Symbol::DefaultVal
|
||||
|| sym.valuesource() == Symbol::InstanceVal)) {
|
||||
// TODO(arenas): OSL_ASSERT(sym.arena() == SymArena::Absolute);
|
||||
return sym.dataptr();
|
||||
}
|
||||
@@ -593,9 +609,9 @@ ShadingContext::symbol_data (const Symbol &sym) const
|
||||
|
||||
|
||||
const std::regex&
|
||||
ShadingContext::find_regex (ustring r)
|
||||
ShadingContext::find_regex(ustring r)
|
||||
{
|
||||
RegexMap::const_iterator found = m_regex_map.find (r);
|
||||
RegexMap::const_iterator found = m_regex_map.find(r);
|
||||
if (found != m_regex_map.end())
|
||||
return *found->second;
|
||||
// otherwise, it wasn't found, add it
|
||||
@@ -608,11 +624,11 @@ ShadingContext::find_regex (ustring r)
|
||||
|
||||
|
||||
bool
|
||||
ShadingContext::osl_get_attribute (ShaderGlobals *sg, void *objdata,
|
||||
int dest_derivs,
|
||||
ustring obj_name, ustring attr_name,
|
||||
int array_lookup, int index,
|
||||
TypeDesc attr_type, void *attr_dest)
|
||||
ShadingContext::osl_get_attribute(ShaderGlobals* sg, void* objdata,
|
||||
int dest_derivs, ustring obj_name,
|
||||
ustring attr_name, int array_lookup,
|
||||
int index, TypeDesc attr_type,
|
||||
void* attr_dest)
|
||||
{
|
||||
#if 0
|
||||
// Change the #if's below if you want to
|
||||
@@ -621,13 +637,12 @@ ShadingContext::osl_get_attribute (ShaderGlobals *sg, void *objdata,
|
||||
bool ok;
|
||||
|
||||
if (array_lookup)
|
||||
ok = renderer()->get_array_attribute (sg, dest_derivs,
|
||||
obj_name, attr_type,
|
||||
attr_name, index, attr_dest);
|
||||
ok = renderer()->get_array_attribute(sg, dest_derivs, obj_name,
|
||||
attr_type, attr_name, index,
|
||||
attr_dest);
|
||||
else
|
||||
ok = renderer()->get_attribute (sg, dest_derivs,
|
||||
obj_name, attr_type,
|
||||
attr_name, attr_dest);
|
||||
ok = renderer()->get_attribute(sg, dest_derivs, obj_name, attr_type,
|
||||
attr_name, attr_dest);
|
||||
|
||||
#if 0
|
||||
double time = timer();
|
||||
@@ -636,17 +651,17 @@ ShadingContext::osl_get_attribute (ShaderGlobals *sg, void *objdata,
|
||||
shadingsys().m_stat_getattribute_fail_time += time;
|
||||
shadingsys().m_stat_getattribute_calls += 1;
|
||||
#endif
|
||||
// std::cout << "getattribute! '" << obj_name << "' " << attr_name << ' ' << attr_type.c_str() << " ok=" << ok << ", objdata was " << objdata << "\n";
|
||||
// std::cout << "getattribute! '" << obj_name << "' " << attr_name << ' ' << attr_type.c_str() << " ok=" << ok << ", objdata was " << objdata << "\n";
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
|
||||
OSL_SHADEOP void
|
||||
osl_incr_layers_executed (ShaderGlobals *sg)
|
||||
osl_incr_layers_executed(ShaderGlobals* sg)
|
||||
{
|
||||
ShadingContext *ctx = (ShadingContext *)sg->context;
|
||||
ctx->incr_layers_executed ();
|
||||
ShadingContext* ctx = (ShadingContext*)sg->context;
|
||||
ctx->incr_layers_executed();
|
||||
}
|
||||
|
||||
#if OSL_USE_BATCHED
|
||||
|
||||
+146
-137
@@ -2,12 +2,12 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cctype>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <OpenImageIO/strutil.h>
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace pugi = OIIO::pugi;
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
namespace pvt { // OSL::pvt
|
||||
namespace pvt { // OSL::pvt
|
||||
|
||||
|
||||
// Helper class to manage the dictionaries.
|
||||
@@ -46,21 +46,22 @@ namespace pvt { // OSL::pvt
|
||||
//
|
||||
class Dictionary {
|
||||
public:
|
||||
Dictionary (ShadingContext *ctx) : m_context(ctx)
|
||||
Dictionary(ShadingContext* ctx) : m_context(ctx)
|
||||
{
|
||||
// Create placeholder element 0 == 'not found'
|
||||
m_nodes.emplace_back(0, pugi::xml_node());
|
||||
}
|
||||
~Dictionary () {
|
||||
~Dictionary()
|
||||
{
|
||||
// Free all the documents.
|
||||
for (auto& doc : m_documents)
|
||||
delete doc;
|
||||
}
|
||||
|
||||
int dict_find (ustring dictionaryname, ustring query);
|
||||
int dict_find (int nodeID, ustring query);
|
||||
int dict_next (int nodeID);
|
||||
int dict_value (int nodeID, ustring attribname, TypeDesc type, void *data);
|
||||
int dict_find(ustring dictionaryname, ustring query);
|
||||
int dict_find(int nodeID, ustring query);
|
||||
int dict_next(int nodeID);
|
||||
int dict_value(int nodeID, ustring attribname, TypeDesc type, void* data);
|
||||
|
||||
private:
|
||||
// We cache individual queries with a key that is a tuple of the
|
||||
@@ -70,19 +71,23 @@ private:
|
||||
int node; // root node for the search
|
||||
ustring name; // name for the the search
|
||||
TypeDesc type; // UNKNOWN signifies a node, versus an attribute value
|
||||
Query (int doc_, int node_, ustring name_,
|
||||
TypeDesc type_=TypeDesc::UNKNOWN) :
|
||||
document(doc_), node(node_), name(name_), type(type_) { }
|
||||
bool operator== (const Query &q) const {
|
||||
return document == q.document && node == q.node &&
|
||||
name == q.name && type == q.type;
|
||||
Query(int doc_, int node_, ustring name_,
|
||||
TypeDesc type_ = TypeDesc::UNKNOWN)
|
||||
: document(doc_), node(node_), name(name_), type(type_)
|
||||
{
|
||||
}
|
||||
bool operator==(const Query& q) const
|
||||
{
|
||||
return document == q.document && node == q.node && name == q.name
|
||||
&& type == q.type;
|
||||
}
|
||||
};
|
||||
|
||||
// Must define a hash operation to build the unordered_map.
|
||||
struct QueryHash {
|
||||
size_t operator() (const Query &key) const {
|
||||
return key.name.hash() + 17*key.node + 79*key.document;
|
||||
size_t operator()(const Query& key) const
|
||||
{
|
||||
return key.name.hash() + 17 * key.node + 79 * key.document;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -93,9 +98,11 @@ private:
|
||||
struct QueryResult {
|
||||
int valueoffset; // Offset into one of the 'data' vectors, or nodeID
|
||||
bool is_valid; // true: query found
|
||||
QueryResult (bool valid=true) : valueoffset(0), is_valid(valid) { }
|
||||
QueryResult (bool /*isnode*/, int value)
|
||||
: valueoffset(value), is_valid(true) { }
|
||||
QueryResult(bool valid = true) : valueoffset(0), is_valid(valid) {}
|
||||
QueryResult(bool /*isnode*/, int value)
|
||||
: valueoffset(value), is_valid(true)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// Nodes we've looked up. Includes a 'next' index of the matching node
|
||||
@@ -104,17 +111,16 @@ private:
|
||||
int document; // which document the node belongs to
|
||||
pugi::xml_node node; // which node within the dictionary
|
||||
int next; // next node for the same query
|
||||
Node (int d, const pugi::xml_node &n)
|
||||
: document(d), node(n), next(0) { }
|
||||
Node(int d, const pugi::xml_node& n) : document(d), node(n), next(0) {}
|
||||
};
|
||||
|
||||
typedef std::unordered_map <Query, QueryResult, QueryHash> QueryMap;
|
||||
typedef std::unordered_map<ustring, int, ustringHash> DocMap;
|
||||
typedef std::unordered_map<Query, QueryResult, QueryHash> QueryMap;
|
||||
typedef std::unordered_map<ustring, int> DocMap;
|
||||
|
||||
ShadingContext *m_context; // back-pointer to shading context
|
||||
ShadingContext* m_context; // back-pointer to shading context
|
||||
|
||||
// List of XML documents we've read in.
|
||||
std::vector<pugi::xml_document *> m_documents;
|
||||
std::vector<pugi::xml_document*> m_documents;
|
||||
|
||||
// Map xml strings and/or filename to indices in m_documents.
|
||||
DocMap m_document_map;
|
||||
@@ -127,38 +133,38 @@ private:
|
||||
|
||||
// m_floatdata, m_intdata, and m_stringdata hold the decoded data
|
||||
// results (including type conversion) of cached queries.
|
||||
std::vector<float> m_floatdata;
|
||||
std::vector<int> m_intdata;
|
||||
std::vector<float> m_floatdata;
|
||||
std::vector<int> m_intdata;
|
||||
std::vector<ustring> m_stringdata;
|
||||
|
||||
// Helper function: return the document index given dictionary name.
|
||||
int get_document_index (ustring dictionaryname);
|
||||
int get_document_index(ustring dictionaryname);
|
||||
};
|
||||
|
||||
|
||||
|
||||
int
|
||||
Dictionary::get_document_index (ustring dictionaryname)
|
||||
Dictionary::get_document_index(ustring dictionaryname)
|
||||
{
|
||||
DocMap::iterator dm = m_document_map.find(dictionaryname);
|
||||
int dindex;
|
||||
if (dm == m_document_map.end()) {
|
||||
dindex = m_documents.size();
|
||||
dindex = m_documents.size();
|
||||
m_document_map[dictionaryname] = dindex;
|
||||
pugi::xml_document *doc = new pugi::xml_document;
|
||||
m_documents.push_back (doc);
|
||||
pugi::xml_document* doc = new pugi::xml_document;
|
||||
m_documents.push_back(doc);
|
||||
pugi::xml_parse_result parse_result;
|
||||
if (Strutil::ends_with(dictionaryname, ".xml")) {
|
||||
// xml file -- read it
|
||||
parse_result = doc->load_file (dictionaryname.c_str());
|
||||
parse_result = doc->load_file(dictionaryname.c_str());
|
||||
} else {
|
||||
// load xml directly from the string
|
||||
parse_result = doc->load_string(dictionaryname.c_str());
|
||||
}
|
||||
if (! parse_result) {
|
||||
m_context->errorf("XML parsed with errors: %s, at offset %d",
|
||||
parse_result.description(),
|
||||
parse_result.offset);
|
||||
if (!parse_result) {
|
||||
m_context->errorfmt("XML parsed with errors: {}, at offset {}",
|
||||
parse_result.description(),
|
||||
parse_result.offset);
|
||||
m_document_map[dictionaryname] = -1;
|
||||
return -1;
|
||||
}
|
||||
@@ -173,44 +179,43 @@ Dictionary::get_document_index (ustring dictionaryname)
|
||||
|
||||
|
||||
int
|
||||
Dictionary::dict_find (ustring dictionaryname, ustring query)
|
||||
Dictionary::dict_find(ustring dictionaryname, ustring query)
|
||||
{
|
||||
int dindex = get_document_index (dictionaryname);
|
||||
int dindex = get_document_index(dictionaryname);
|
||||
if (dindex < 0)
|
||||
return dindex;
|
||||
|
||||
Query q (dindex, 0, query);
|
||||
QueryMap::iterator qfound = m_cache.find (q);
|
||||
Query q(dindex, 0, query);
|
||||
QueryMap::iterator qfound = m_cache.find(q);
|
||||
if (qfound != m_cache.end()) {
|
||||
return qfound->second.valueoffset;
|
||||
}
|
||||
|
||||
pugi::xml_document *doc = m_documents[dindex];
|
||||
pugi::xml_document* doc = m_documents[dindex];
|
||||
|
||||
// Query was not found. Do the expensive lookup and cache it
|
||||
pugi::xpath_node_set matches;
|
||||
|
||||
try {
|
||||
matches = doc->select_nodes (query.c_str());
|
||||
}
|
||||
catch (const pugi::xpath_exception& e) {
|
||||
m_context->errorf("Invalid dict_find query '%s': %s",
|
||||
query.c_str(), e.what());
|
||||
matches = doc->select_nodes(query.c_str());
|
||||
} catch (const pugi::xpath_exception& e) {
|
||||
m_context->errorfmt("Invalid dict_find query '{}': {}", query,
|
||||
e.what());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (matches.empty()) {
|
||||
m_cache[q] = QueryResult (false); // mark invalid
|
||||
return 0; // Not found
|
||||
m_cache[q] = QueryResult(false); // mark invalid
|
||||
return 0; // Not found
|
||||
}
|
||||
int firstmatch = (int) m_nodes.size();
|
||||
int last = -1;
|
||||
int firstmatch = (int)m_nodes.size();
|
||||
int last = -1;
|
||||
for (auto&& m : matches) {
|
||||
m_nodes.emplace_back(dindex, m.node());
|
||||
int nodeid = (int) m_nodes.size()-1;
|
||||
int nodeid = (int)m_nodes.size() - 1;
|
||||
if (last < 0) {
|
||||
// If this is the first match, add a cache entry for it
|
||||
m_cache[q] = QueryResult (true /* it's a node */, nodeid);
|
||||
m_cache[q] = QueryResult(true /* it's a node */, nodeid);
|
||||
} else {
|
||||
// If this is a subsequent match, set the last match's 'next'
|
||||
m_nodes[last].next = nodeid;
|
||||
@@ -223,14 +228,14 @@ Dictionary::dict_find (ustring dictionaryname, ustring query)
|
||||
|
||||
|
||||
int
|
||||
Dictionary::dict_find (int nodeID, ustring query)
|
||||
Dictionary::dict_find(int nodeID, ustring query)
|
||||
{
|
||||
if (nodeID <= 0 || nodeID >= (int)m_nodes.size())
|
||||
return 0; // invalid node ID
|
||||
return 0; // invalid node ID
|
||||
|
||||
int document = m_nodes[nodeID].document;
|
||||
Query q (document, nodeID, query);
|
||||
QueryMap::iterator qfound = m_cache.find (q);
|
||||
Query q(document, nodeID, query);
|
||||
QueryMap::iterator qfound = m_cache.find(q);
|
||||
if (qfound != m_cache.end()) {
|
||||
return qfound->second.valueoffset;
|
||||
}
|
||||
@@ -238,26 +243,25 @@ Dictionary::dict_find (int nodeID, ustring query)
|
||||
// Query was not found. Do the expensive lookup and cache it
|
||||
pugi::xpath_node_set matches;
|
||||
try {
|
||||
matches = m_nodes[nodeID].node.select_nodes (query.c_str());
|
||||
}
|
||||
catch (const pugi::xpath_exception& e) {
|
||||
m_context->errorf("Invalid dict_find query '%s': %s",
|
||||
query.c_str(), e.what());
|
||||
matches = m_nodes[nodeID].node.select_nodes(query.c_str());
|
||||
} catch (const pugi::xpath_exception& e) {
|
||||
m_context->errorfmt("Invalid dict_find query '{}': {}", query,
|
||||
e.what());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (matches.empty()) {
|
||||
m_cache[q] = QueryResult (false); // mark invalid
|
||||
return 0; // Not found
|
||||
m_cache[q] = QueryResult(false); // mark invalid
|
||||
return 0; // Not found
|
||||
}
|
||||
int firstmatch = (int) m_nodes.size();
|
||||
int last = -1;
|
||||
int firstmatch = (int)m_nodes.size();
|
||||
int last = -1;
|
||||
for (auto&& m : matches) {
|
||||
m_nodes.emplace_back(document, m.node());
|
||||
int nodeid = (int) m_nodes.size()-1;
|
||||
int nodeid = (int)m_nodes.size() - 1;
|
||||
if (last < 0) {
|
||||
// If this is the first match, add a cache entry for it
|
||||
m_cache[q] = QueryResult (true /* it's a node */, nodeid);
|
||||
m_cache[q] = QueryResult(true /* it's a node */, nodeid);
|
||||
} else {
|
||||
// If this is a subsequent match, set the last match's 'next'
|
||||
m_nodes[last].next = nodeid;
|
||||
@@ -270,42 +274,42 @@ Dictionary::dict_find (int nodeID, ustring query)
|
||||
|
||||
|
||||
int
|
||||
Dictionary::dict_next (int nodeID)
|
||||
Dictionary::dict_next(int nodeID)
|
||||
{
|
||||
if (nodeID <= 0 || nodeID >= (int)m_nodes.size())
|
||||
return 0; // invalid node ID
|
||||
return 0; // invalid node ID
|
||||
return m_nodes[nodeID].next;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
Dictionary::dict_value (int nodeID, ustring attribname,
|
||||
TypeDesc type, void *data)
|
||||
Dictionary::dict_value(int nodeID, ustring attribname, TypeDesc type,
|
||||
void* data)
|
||||
{
|
||||
if (nodeID <= 0 || nodeID >= (int)m_nodes.size())
|
||||
return 0; // invalid node ID
|
||||
return 0; // invalid node ID
|
||||
|
||||
const Dictionary::Node &node (m_nodes[nodeID]);
|
||||
Dictionary::Query q (node.document, nodeID, attribname, type);
|
||||
Dictionary::QueryMap::iterator qfound = m_cache.find (q);
|
||||
const Dictionary::Node& node(m_nodes[nodeID]);
|
||||
Dictionary::Query q(node.document, nodeID, attribname, type);
|
||||
Dictionary::QueryMap::iterator qfound = m_cache.find(q);
|
||||
if (qfound != m_cache.end()) {
|
||||
// previously found
|
||||
int offset = qfound->second.valueoffset;
|
||||
int n = type.numelements() * type.aggregate;
|
||||
int n = type.numelements() * type.aggregate;
|
||||
if (type.basetype == TypeDesc::STRING) {
|
||||
OSL_DASSERT (n == 1 && "no string arrays in XML");
|
||||
((ustring *)data)[0] = m_stringdata[offset];
|
||||
OSL_DASSERT(n == 1 && "no string arrays in XML");
|
||||
((ustring*)data)[0] = m_stringdata[offset];
|
||||
return 1;
|
||||
}
|
||||
if (type.basetype == TypeDesc::INT) {
|
||||
for (int i = 0; i < n; ++i)
|
||||
((int *)data)[i] = m_intdata[offset++];
|
||||
for (int i = 0; i < n; ++i)
|
||||
((int*)data)[i] = m_intdata[offset++];
|
||||
return 1;
|
||||
}
|
||||
if (type.basetype == TypeDesc::FLOAT) {
|
||||
for (int i = 0; i < n; ++i)
|
||||
((float *)data)[i] = m_floatdata[offset++];
|
||||
for (int i = 0; i < n; ++i)
|
||||
((float*)data)[i] = m_floatdata[offset++];
|
||||
return 1;
|
||||
}
|
||||
return 0; // Unknown type
|
||||
@@ -313,7 +317,7 @@ Dictionary::dict_value (int nodeID, ustring attribname,
|
||||
|
||||
// OK, the entry wasn't in the cache, we need to decode it and cache it.
|
||||
|
||||
const char *val = NULL;
|
||||
const char* val = NULL;
|
||||
if (attribname.empty()) {
|
||||
val = node.node.value();
|
||||
} else {
|
||||
@@ -326,40 +330,40 @@ Dictionary::dict_value (int nodeID, ustring attribname,
|
||||
}
|
||||
}
|
||||
if (val == NULL)
|
||||
return 0; // not found
|
||||
return 0; // not found
|
||||
|
||||
Dictionary::QueryResult r (false, 0);
|
||||
Dictionary::QueryResult r(false, 0);
|
||||
int n = type.numelements() * type.aggregate;
|
||||
if (type.basetype == TypeDesc::STRING && n == 1) {
|
||||
r.valueoffset = (int) m_stringdata.size();
|
||||
ustring s (val);
|
||||
m_stringdata.push_back (s);
|
||||
((ustring *)data)[0] = s;
|
||||
m_cache[q] = r;
|
||||
r.valueoffset = (int)m_stringdata.size();
|
||||
ustring s(val);
|
||||
m_stringdata.push_back(s);
|
||||
((ustring*)data)[0] = s;
|
||||
m_cache[q] = r;
|
||||
return 1;
|
||||
}
|
||||
if (type.basetype == TypeDesc::INT) {
|
||||
r.valueoffset = (int) m_intdata.size();
|
||||
string_view valstr (val);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
r.valueoffset = (int)m_intdata.size();
|
||||
string_view valstr(val);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
int v;
|
||||
OIIO::Strutil::parse_int (valstr, v);
|
||||
OIIO::Strutil::parse_char (valstr, ',');
|
||||
m_intdata.push_back (v);
|
||||
((int *)data)[i] = v;
|
||||
OIIO::Strutil::parse_int(valstr, v);
|
||||
OIIO::Strutil::parse_char(valstr, ',');
|
||||
m_intdata.push_back(v);
|
||||
((int*)data)[i] = v;
|
||||
}
|
||||
m_cache[q] = r;
|
||||
return 1;
|
||||
}
|
||||
if (type.basetype == TypeDesc::FLOAT) {
|
||||
r.valueoffset = (int) m_floatdata.size();
|
||||
string_view valstr (val);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
r.valueoffset = (int)m_floatdata.size();
|
||||
string_view valstr(val);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
float v;
|
||||
OIIO::Strutil::parse_float (valstr, v);
|
||||
OIIO::Strutil::parse_char (valstr, ',');
|
||||
m_floatdata.push_back (v);
|
||||
((float *)data)[i] = v;
|
||||
OIIO::Strutil::parse_float(valstr, v);
|
||||
OIIO::Strutil::parse_char(valstr, ',');
|
||||
m_floatdata.push_back(v);
|
||||
((float*)data)[i] = v;
|
||||
}
|
||||
m_cache[q] = r;
|
||||
return 1;
|
||||
@@ -370,90 +374,95 @@ Dictionary::dict_value (int nodeID, ustring attribname,
|
||||
}
|
||||
|
||||
|
||||
}; // namespace pvt
|
||||
}; // namespace pvt
|
||||
|
||||
|
||||
|
||||
int
|
||||
ShadingContext::dict_find (ustring dictionaryname, ustring query)
|
||||
ShadingContext::dict_find(ustring dictionaryname, ustring query)
|
||||
{
|
||||
if (! m_dictionary) {
|
||||
m_dictionary = new Dictionary (this);
|
||||
if (!m_dictionary) {
|
||||
m_dictionary = new Dictionary(this);
|
||||
}
|
||||
return m_dictionary->dict_find (dictionaryname, query);
|
||||
return m_dictionary->dict_find(dictionaryname, query);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
ShadingContext::dict_find (int nodeID, ustring query)
|
||||
ShadingContext::dict_find(int nodeID, ustring query)
|
||||
{
|
||||
if (! m_dictionary) {
|
||||
m_dictionary = new Dictionary (this);
|
||||
if (!m_dictionary) {
|
||||
m_dictionary = new Dictionary(this);
|
||||
}
|
||||
return m_dictionary->dict_find (nodeID, query);
|
||||
return m_dictionary->dict_find(nodeID, query);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
ShadingContext::dict_next (int nodeID)
|
||||
ShadingContext::dict_next(int nodeID)
|
||||
{
|
||||
if (! m_dictionary)
|
||||
if (!m_dictionary)
|
||||
return 0;
|
||||
return m_dictionary->dict_next (nodeID);
|
||||
return m_dictionary->dict_next(nodeID);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
ShadingContext::dict_value (int nodeID, ustring attribname,
|
||||
TypeDesc type, void *data)
|
||||
ShadingContext::dict_value(int nodeID, ustring attribname, TypeDesc type,
|
||||
void* data)
|
||||
{
|
||||
if (! m_dictionary)
|
||||
if (!m_dictionary)
|
||||
return 0;
|
||||
return m_dictionary->dict_value (nodeID, attribname, type, data);
|
||||
return m_dictionary->dict_value(nodeID, attribname, type, data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ShadingContext::free_dict_resources ()
|
||||
ShadingContext::free_dict_resources()
|
||||
{
|
||||
delete m_dictionary;
|
||||
}
|
||||
|
||||
|
||||
|
||||
OSL_SHADEOP int osl_dict_find_iis (void *sg_, int nodeID, void *query)
|
||||
OSL_SHADEOP int
|
||||
osl_dict_find_iis(void* sg_, int nodeID, void* query)
|
||||
{
|
||||
ShaderGlobals *sg = (ShaderGlobals *)sg_;
|
||||
return sg->context->dict_find (nodeID, USTR(query));
|
||||
ShaderGlobals* sg = (ShaderGlobals*)sg_;
|
||||
return sg->context->dict_find(nodeID, USTR(query));
|
||||
}
|
||||
|
||||
|
||||
|
||||
OSL_SHADEOP int osl_dict_find_iss (void *sg_, void *dictionary, void *query)
|
||||
OSL_SHADEOP int
|
||||
osl_dict_find_iss(void* sg_, void* dictionary, void* query)
|
||||
{
|
||||
ShaderGlobals *sg = (ShaderGlobals *)sg_;
|
||||
return sg->context->dict_find (USTR(dictionary), USTR(query));
|
||||
ShaderGlobals* sg = (ShaderGlobals*)sg_;
|
||||
return sg->context->dict_find(USTR(dictionary), USTR(query));
|
||||
}
|
||||
|
||||
|
||||
|
||||
OSL_SHADEOP int osl_dict_next (void *sg_, int nodeID)
|
||||
OSL_SHADEOP int
|
||||
osl_dict_next(void* sg_, int nodeID)
|
||||
{
|
||||
ShaderGlobals *sg = (ShaderGlobals *)sg_;
|
||||
return sg->context->dict_next (nodeID);
|
||||
ShaderGlobals* sg = (ShaderGlobals*)sg_;
|
||||
return sg->context->dict_next(nodeID);
|
||||
}
|
||||
|
||||
|
||||
|
||||
OSL_SHADEOP int osl_dict_value (void *sg_, int nodeID, void *attribname,
|
||||
long long type, void *data)
|
||||
OSL_SHADEOP int
|
||||
osl_dict_value(void* sg_, int nodeID, void* attribname, long long type,
|
||||
void* data)
|
||||
{
|
||||
ShaderGlobals *sg = (ShaderGlobals *)sg_;
|
||||
return sg->context->dict_value (nodeID, USTR(attribname), TYPEDESC(type), data);
|
||||
ShaderGlobals* sg = (ShaderGlobals*)sg_;
|
||||
return sg->context->dict_value(nodeID, USTR(attribname), TYPEDESC(type),
|
||||
data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,22 +4,23 @@
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
#include <OSL/dual.h>
|
||||
#include <OSL/dual_vec.h>
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
#include <OpenImageIO/benchmark.h>
|
||||
#include <OpenImageIO/unittest.h>
|
||||
|
||||
using namespace OSL;
|
||||
|
||||
typedef Dual<float,1> Dualf;
|
||||
typedef Dual<float, 1> Dualf;
|
||||
typedef Dual2<float> Dual2f;
|
||||
|
||||
|
||||
|
||||
template<class T>
|
||||
T crazy (const T& x)
|
||||
T
|
||||
crazy(const T& x)
|
||||
{
|
||||
using namespace std;
|
||||
using namespace OSL;
|
||||
@@ -29,11 +30,12 @@ T crazy (const T& x)
|
||||
|
||||
|
||||
template<class T>
|
||||
T crazy (const T& x, const T& y)
|
||||
T
|
||||
crazy(const T& x, const T& y)
|
||||
{
|
||||
using namespace std;
|
||||
using namespace OSL;
|
||||
return x * y * exp(x+y);
|
||||
return x * y * exp(x + y);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,19 +43,21 @@ T crazy (const T& x, const T& y)
|
||||
// Compare 1D derivs with Duals to numerical differentiation. This sure
|
||||
// isn't comprehensive, but it tests the general scheme.
|
||||
void
|
||||
test_derivs1 () {
|
||||
const float eps = 1e-3;
|
||||
test_derivs1()
|
||||
{
|
||||
const float eps = 1e-3;
|
||||
static float domain[] = { 0, 0.1, 0.25, 0.333333, 0.91 };
|
||||
for (auto x : domain) {
|
||||
float f = crazy(x);
|
||||
float df_numeric = (crazy(x+eps) - crazy(x-eps)) / (2.0f*eps);
|
||||
Dual<float> xd (x, 1.0f);
|
||||
Dual<float> fd = crazy (xd);
|
||||
std::cout << "crazy(" << x << ")=" << f << ", numeric derivs ~= "
|
||||
<< df_numeric << ", Dual f = " << fd << "\n";
|
||||
float f = crazy(x);
|
||||
float df_numeric = (crazy(x + eps) - crazy(x - eps)) / (2.0f * eps);
|
||||
Dual<float> xd(x, 1.0f);
|
||||
Dual<float> fd = crazy(xd);
|
||||
std::cout << "crazy(" << x << ")=" << f
|
||||
<< ", numeric derivs ~= " << df_numeric << ", Dual f = " << fd
|
||||
<< "\n";
|
||||
|
||||
OIIO_CHECK_EQUAL_THRESH (f, fd.val(), eps);
|
||||
OIIO_CHECK_EQUAL_THRESH (df_numeric, fd.dx(), eps);
|
||||
OIIO_CHECK_EQUAL_THRESH(f, fd.val(), eps);
|
||||
OIIO_CHECK_EQUAL_THRESH(df_numeric, fd.dx(), eps);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,25 +66,28 @@ test_derivs1 () {
|
||||
// Compare 2D derivs with Duals to numerical differentiation. This sure
|
||||
// isn't comprehensive, but it tests the general scheme.
|
||||
void
|
||||
test_derivs2 () {
|
||||
const float eps = 1e-3;
|
||||
test_derivs2()
|
||||
{
|
||||
const float eps = 1e-3;
|
||||
static float domain[] = { 0, 0.1, 0.25, 0.333333, 0.91 };
|
||||
for (auto x : domain) {
|
||||
for (auto y : domain) {
|
||||
float f = crazy(x,y);
|
||||
float df_dx_numeric = (crazy(x+eps,y) - crazy(x-eps,y)) / (2.0f*eps);
|
||||
float df_dy_numeric = (crazy(x,y+eps) - crazy(x,y-eps)) / (2.0f*eps);
|
||||
Dual<float,2> xd (x, 1.0f, 0.0f);
|
||||
Dual<float,2> yd (y, 0.0f, 1.0f);
|
||||
Dual<float,2> fd = crazy (xd, yd);
|
||||
float f = crazy(x, y);
|
||||
float df_dx_numeric = (crazy(x + eps, y) - crazy(x - eps, y))
|
||||
/ (2.0f * eps);
|
||||
float df_dy_numeric = (crazy(x, y + eps) - crazy(x, y - eps))
|
||||
/ (2.0f * eps);
|
||||
Dual<float, 2> xd(x, 1.0f, 0.0f);
|
||||
Dual<float, 2> yd(y, 0.0f, 1.0f);
|
||||
Dual<float, 2> fd = crazy(xd, yd);
|
||||
std::cout << "crazy(" << x << "," << y << ")=" << f
|
||||
<< ", numeric derivs df/dx ~= "
|
||||
<< df_dx_numeric << ", df/dy ~= " << df_dy_numeric
|
||||
<< ", Dual f = " << fd << "\n";
|
||||
<< ", numeric derivs df/dx ~= " << df_dx_numeric
|
||||
<< ", df/dy ~= " << df_dy_numeric << ", Dual f = " << fd
|
||||
<< "\n";
|
||||
|
||||
OIIO_CHECK_EQUAL_THRESH (f, fd.val(), eps);
|
||||
OIIO_CHECK_EQUAL_THRESH (df_dx_numeric, fd.dx(), eps);
|
||||
OIIO_CHECK_EQUAL_THRESH (df_dy_numeric, fd.dy(), eps);
|
||||
OIIO_CHECK_EQUAL_THRESH(f, fd.val(), eps);
|
||||
OIIO_CHECK_EQUAL_THRESH(df_dx_numeric, fd.dx(), eps);
|
||||
OIIO_CHECK_EQUAL_THRESH(df_dy_numeric, fd.dy(), eps);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,33 +95,34 @@ test_derivs2 () {
|
||||
|
||||
|
||||
void
|
||||
test_metaprogramming ()
|
||||
test_metaprogramming()
|
||||
{
|
||||
// Does is_Dual<> correctly discern duals from non-duals?
|
||||
OIIO_CHECK_ASSERT (is_Dual<Dualf>());
|
||||
OIIO_CHECK_ASSERT (is_Dual<Dual2f>());
|
||||
OIIO_CHECK_ASSERT (! is_Dual<float>());
|
||||
OIIO_CHECK_ASSERT (! is_Dual<Vec3>());
|
||||
OIIO_CHECK_ASSERT(is_Dual<Dualf>());
|
||||
OIIO_CHECK_ASSERT(is_Dual<Dual2f>());
|
||||
OIIO_CHECK_ASSERT(!is_Dual<float>());
|
||||
OIIO_CHECK_ASSERT(!is_Dual<Vec3>());
|
||||
|
||||
// Does Dualify<> correctly turn a scalar into a dual?
|
||||
OIIO_CHECK_ASSERT ((std::is_same<Dualify<float>::type, Dualf>::value));
|
||||
OIIO_CHECK_ASSERT ((std::is_same<Dualify<float,2>::type, Dual2f>::value));
|
||||
OIIO_CHECK_ASSERT ((std::is_same<Dualify<Dualf,1>::type, Dualf>::value));
|
||||
OIIO_CHECK_ASSERT ((std::is_same<Dualify<Dual2f,2>::type, Dual2f>::value));
|
||||
OIIO_CHECK_ASSERT((std::is_same<Dualify<float>::type, Dualf>::value));
|
||||
OIIO_CHECK_ASSERT((std::is_same<Dualify<float, 2>::type, Dual2f>::value));
|
||||
OIIO_CHECK_ASSERT((std::is_same<Dualify<Dualf, 1>::type, Dualf>::value));
|
||||
OIIO_CHECK_ASSERT((std::is_same<Dualify<Dual2f, 2>::type, Dual2f>::value));
|
||||
|
||||
OIIO_CHECK_ASSERT ((std::is_same<UnDual<float >::type, float>::value));
|
||||
OIIO_CHECK_ASSERT ((std::is_same<UnDual<Vec3 >::type, Vec3> ::value));
|
||||
OIIO_CHECK_ASSERT ((std::is_same<UnDual<Dualf >::type, float>::value));
|
||||
OIIO_CHECK_ASSERT ((std::is_same<UnDual<Dual2f>::type, float>::value));
|
||||
OIIO_CHECK_ASSERT((std::is_same<UnDual<float>::type, float>::value));
|
||||
OIIO_CHECK_ASSERT((std::is_same<UnDual<Vec3>::type, Vec3>::value));
|
||||
OIIO_CHECK_ASSERT((std::is_same<UnDual<Dualf>::type, float>::value));
|
||||
OIIO_CHECK_ASSERT((std::is_same<UnDual<Dual2f>::type, float>::value));
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int /*argc*/, char * /*argv*/[])
|
||||
int
|
||||
main(int /*argc*/, char* /*argv*/[])
|
||||
{
|
||||
test_metaprogramming ();
|
||||
test_derivs1 ();
|
||||
test_derivs2 ();
|
||||
test_metaprogramming();
|
||||
test_derivs1();
|
||||
test_derivs2();
|
||||
|
||||
// Some benchmarking
|
||||
std::cout << "\nBenchmarks:\n";
|
||||
@@ -122,9 +130,14 @@ int main(int /*argc*/, char * /*argv*/[])
|
||||
Benchmarker bench;
|
||||
Dual2f v(1.5f, 0.01f, 0.01f);
|
||||
clobber(v);
|
||||
bench("-Dual2f", [&](const Dual2f& v) { return DoNotOptimize(-v); }, v);
|
||||
bench("fast_neg(Dual2f)", [&](const Dual2f& v) { return DoNotOptimize(fast_neg(v)); }, v);
|
||||
bench("log2(Dual2f)", [&](const Dual2f& v) { return DoNotOptimize(fast_log2(v)); }, v);
|
||||
bench(
|
||||
"-Dual2f", [&](const Dual2f& v) { return DoNotOptimize(-v); }, v);
|
||||
bench(
|
||||
"fast_neg(Dual2f)",
|
||||
[&](const Dual2f& v) { return DoNotOptimize(fast_neg(v)); }, v);
|
||||
bench(
|
||||
"log2(Dual2f)",
|
||||
[&](const Dual2f& v) { return DoNotOptimize(fast_log2(v)); }, v);
|
||||
|
||||
// FIXME: Some day, expand to more exhaustive tests of Dual
|
||||
|
||||
|
||||
+321
-287
File diff suppressed because it is too large
Load Diff
+1861
-1836
File diff suppressed because it is too large
Load Diff
+662
-577
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user