Compare commits
157
Commits
release
...
v1.13.4.0-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71a9310f0b | ||
|
|
5c49a7c6b5 | ||
|
|
abdc966a19 | ||
|
|
374543f040 | ||
|
|
089268b87d | ||
|
|
74b2b30669 | ||
|
|
91699ba7d3 | ||
|
|
4afe9244e8 | ||
|
|
ed9857c416 | ||
|
|
cd22f602a4 | ||
|
|
17d211a3d3 | ||
|
|
20299563ee | ||
|
|
5600d020a0 | ||
|
|
37f4bbc1a2 | ||
|
|
b13b7f08b0 | ||
|
|
7ebfbc4a05 | ||
|
|
e402988611 | ||
|
|
88be276ec1 | ||
|
|
6f1fedb08d | ||
|
|
0bd014cfe2 | ||
|
|
209c672b0b | ||
|
|
49cda0a472 | ||
|
|
787d8ce94e | ||
|
|
89f1e69d88 | ||
|
|
fff0c5985d | ||
|
|
a047c065b7 | ||
|
|
bc735d02cf | ||
|
|
f64f6effc0 | ||
|
|
a620231929 | ||
|
|
df818a7045 | ||
|
|
bee79468e0 | ||
|
|
f8ad0281aa | ||
|
|
b9cb0ae74c | ||
|
|
5879868561 | ||
|
|
c5fe678c9e | ||
|
|
dbe8c214e4 | ||
|
|
fbe141b42b | ||
|
|
a68a972602 | ||
|
|
23edc185a0 | ||
|
|
203dcecafe | ||
|
|
bbbc28d2ff | ||
|
|
649f0b86a3 | ||
|
|
31e92ddc06 | ||
|
|
9ae5b69fd8 | ||
|
|
3bd3778610 | ||
|
|
a8d3ac06e6 | ||
|
|
c0a5998c19 | ||
|
|
5dad5076bc | ||
|
|
317c59ed73 | ||
|
|
66c9b61d72 | ||
|
|
8036e174fb | ||
|
|
b064b25721 | ||
|
|
8d1d9f0cf6 | ||
|
|
1c196d935c | ||
|
|
a878883eeb | ||
|
|
1b3c96603c | ||
|
|
e468ef7595 | ||
|
|
fae61e699f | ||
|
|
7b6854823d | ||
|
|
f84126fb3e | ||
|
|
395e58d6bf | ||
|
|
75401bda4c | ||
|
|
8530aa059a | ||
|
|
bd7fd4cf8c | ||
|
|
61ea4c9a31 | ||
|
|
afec48ebde | ||
|
|
9ef1741056 | ||
|
|
1e8ef316ac | ||
|
|
aafb5cb74e | ||
|
|
d0e49675e5 | ||
|
|
dde0a3451a | ||
|
|
3187864f9b | ||
|
|
66747ac1e6 | ||
|
|
d867d98a50 | ||
|
|
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 |
@@ -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,130 @@
|
||||
# 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-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}}
|
||||
# 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"
|
||||
+152
-85
@@ -20,8 +20,12 @@ on:
|
||||
- '**.rst'
|
||||
- '**.tex'
|
||||
schedule:
|
||||
# Full nightly build
|
||||
# Full nightly build, for the main project repo (not for forks)
|
||||
- cron: "0 6 * * *"
|
||||
if: github.repository == 'AcademySoftwareFoundation/OpenShadingLanguage'
|
||||
|
||||
|
||||
permissions: read-all
|
||||
|
||||
|
||||
jobs:
|
||||
@@ -38,12 +42,12 @@ 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
|
||||
- desc: clang9/C++14 llvm9 oiio-release boost1.66 avx2 exr2.3 py2.7
|
||||
nametag: linux-clang9-llvm9
|
||||
os: ubuntu-18.04
|
||||
os: ubuntu-20.04
|
||||
vfxyear: 2019
|
||||
vfxsuffix: -clang9
|
||||
cc_compiler: clang
|
||||
@@ -64,13 +68,14 @@ jobs:
|
||||
# pybind11_ver: v2.9.0
|
||||
simd: avx2,f16c
|
||||
skip_tests: 1
|
||||
setenvs: export OSL_CMAKE_FLAGS="-DUSE_OPTIX=1" OPTIX_VERSION=7.0
|
||||
setenvs: export OSL_CMAKE_FLAGS="-DUSE_OPTIX=1" OPTIX_VERSION=7.0
|
||||
OPENIMAGEIO_CMAKE_FLAGS=-DBUILD_FMT_VERSION=8.1.1
|
||||
- desc: gcc6/C++14 llvm10 py3.7 boost1.70 exr2.4 oiio2.2 sse4
|
||||
nametag: linux-vfx2020
|
||||
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
|
||||
@@ -81,7 +86,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
|
||||
@@ -109,10 +114,11 @@ jobs:
|
||||
simd: avx2,f16c
|
||||
batched: b8_AVX2,b8_AVX512,b16_AVX512
|
||||
setenvs: USE_OPENVDB=0
|
||||
- desc: icc/C++17 llvm13 py3.9 boost1.76 exr3.1 oiio-master avx2
|
||||
- desc: icc/C++17 llvm14 py3.9 boost1.76 exr3.1 oiio-master avx2
|
||||
nametag: linux-icc
|
||||
os: ubuntu-latest
|
||||
vfxyear: 2022
|
||||
vfxsuffix: -clang13
|
||||
vfxsuffix: -clang14
|
||||
cc_compiler: icc
|
||||
cxx_compiler: icpc
|
||||
cxx_std: 17
|
||||
@@ -125,10 +131,11 @@ jobs:
|
||||
setenvs: export OSL_CMAKE_FLAGS="-DSTOP_ON_WARNING=OFF -DEXTRA_CPP_ARGS=-fp-model=consistent"
|
||||
OPENIMAGEIO_CMAKE_FLAGS=-DBUILD_FMT_VERSION=7.1.3
|
||||
USE_OPENVDB=0
|
||||
- desc: icx/C++17 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
|
||||
- desc: icx/C++17 llvm14 py3.9 boost1.76 exr3.1 oiio2.3 avx2
|
||||
nametag: linux-icx
|
||||
os: ubuntu-latest
|
||||
vfxyear: 2022
|
||||
vfxsuffix: -clang13
|
||||
vfxsuffix: -clang14
|
||||
cc_compiler: icx
|
||||
cxx_compiler: icpx
|
||||
cxx_std: 17
|
||||
@@ -145,12 +152,72 @@ 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 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:
|
||||
image: aswftesting/ci-osl:${{matrix.vfxyear}}${{matrix.vfxsuffix}}
|
||||
@@ -166,13 +233,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}}
|
||||
@@ -198,7 +272,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}}
|
||||
@@ -216,7 +290,7 @@ jobs:
|
||||
include:
|
||||
- desc: Debug gcc7/C++14 llvm9 py2.7 oiio2.3 exr2.4 sse4 boost1.65 exr2.4
|
||||
nametag: linux-debug-gcc7-llvm9
|
||||
os: ubuntu-18.04
|
||||
os: ubuntu-20.04
|
||||
cxx_compiler: g++-7
|
||||
cxx_std: 14
|
||||
openexr_ver: v2.4.3
|
||||
@@ -230,7 +304,7 @@ jobs:
|
||||
CTEST_TEST_TIMEOUT=240
|
||||
- desc: gcc10/C++17 llvm10 oiio-release boost1.65 exr2.5 avx2
|
||||
nametag: linux-2021ish-gcc10-llvm10
|
||||
os: ubuntu-18.04
|
||||
os: ubuntu-20.04
|
||||
cxx_compiler: g++-10
|
||||
cxx_std: 17
|
||||
fmt_ver: 7.0.1
|
||||
@@ -242,32 +316,32 @@ jobs:
|
||||
setenvs: export LLVM_VERSION=10.0.0
|
||||
OPENIMAGEIO_CMAKE_FLAGS="-DBUILD_FMT_VERSION=7.0.1"
|
||||
PUGIXML_VERSION=v1.10
|
||||
- desc: latest releases gcc11/C++17 llvm13 boost1.71 exr3.1 py3.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
|
||||
os: ubuntu-22.04
|
||||
cxx_compiler: g++-11
|
||||
cxx_std: 17
|
||||
fmt_ver: 8.1.1
|
||||
openexr_ver: v3.1.5
|
||||
fmt_ver: 9.1.0
|
||||
openexr_ver: v3.1.7
|
||||
openimageio_ver: master
|
||||
pybind11_ver: v2.9.2
|
||||
python_ver: 3.8
|
||||
pybind11_ver: v2.10.0
|
||||
python_ver: "3.10"
|
||||
simd: avx2,f16c
|
||||
batched: b8_AVX2,b8_AVX512,b16_AVX512
|
||||
setenvs: export LLVM_VERSION=13.0.0
|
||||
LLVM_DISTRO_NAME=ubuntu-20.04
|
||||
OPENCOLORIO_VERSION=v2.1.2
|
||||
PUGIXML_VERSION=v1.11.4
|
||||
- desc: bleeding edge gcc11/C++17 llvm14 oiio/ocio/exr/pybind-master boost1.71 py3.9 avx2 batch-b16avx512
|
||||
OPENCOLORIO_VERSION=v2.2.0
|
||||
PUGIXML_VERSION=v1.13
|
||||
- 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-20.04
|
||||
cxx_compiler: g++-11
|
||||
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.9
|
||||
python_ver: "3.10"
|
||||
simd: avx2,f16c
|
||||
batched: b8_AVX2,b8_AVX512,b16_AVX512
|
||||
setenvs: export LLVM_VERSION=14.0.0
|
||||
@@ -275,13 +349,13 @@ jobs:
|
||||
OPENCOLORIO_VERSION=main
|
||||
PUGIXML_VERSION=master
|
||||
- desc: clang14/C++17 llvm14 boost1.71 exr3.1 py3.8 avx2 batch-b16avx512
|
||||
nametag: linux-latest-releases
|
||||
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
|
||||
openexr_ver: v3.1.7
|
||||
openimageio_ver: master
|
||||
pybind11_ver: v2.9.2
|
||||
python_ver: 3.8
|
||||
@@ -305,13 +379,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}}
|
||||
@@ -329,7 +410,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}}
|
||||
@@ -342,88 +423,74 @@ 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
|
||||
OPENIMAGEIO_VERSION=release
|
||||
QT_BREW_VERSION="@5"
|
||||
- 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
|
||||
OPENIMAGEIO_VERSION=master
|
||||
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: run-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,67 @@
|
||||
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
|
||||
|
||||
# Allow subsequent pushes to the same PR or REF to cancel any previous jobs.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
jobs:
|
||||
analysis:
|
||||
name: Scorecards analysis
|
||||
if: |
|
||||
github.repository == 'AcademySoftwareFoundation/OpenShadingLanguage'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# Needed to upload the results to code-scanning dashboard.
|
||||
security-events: write
|
||||
# Used to receive a badge. (Upcoming feature)
|
||||
id-token: write
|
||||
|
||||
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
|
||||
@@ -9,4 +9,5 @@ build
|
||||
*.pyc
|
||||
*.log
|
||||
.vscode
|
||||
.envrc
|
||||
|
||||
|
||||
@@ -5,13 +5,14 @@ This is a checklist for TSC's to review as part of the intake process. The TSC s
|
||||
- Existing Project Governance
|
||||
- [X] Project License exists ( [LICENSE.md](../LICENSE.md) ) and is OSI-approved
|
||||
- [X] Any third-party components/dependencies included are listed along with their licenses ( [THIRD_PARTY.md](../THIRD_PARTY.md) )
|
||||
- [X] Governance defined, outlining community roles and how decsions are made ( [GOVERNANCE.md](../GOVERNANCE.md] )
|
||||
- [X] Governance defined, outlining community roles and how decisions are made ( [GOVERNANCE.md](../GOVERNANCE.md) )
|
||||
- Closed by https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1137
|
||||
- [X] Contribution Policy defined ( [CONTRIBUTING.md](../CONTRIBUTING.md) )
|
||||
- Closed by https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1137
|
||||
- [X] Code of Conduct defined ( existing or pull from [ASWF Sample Project](https://github.com/AcademySoftwareFoundation/aswf-sample-project/blob/master/CODE_OF_CONDUCT.md) )
|
||||
- Closed by https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1137
|
||||
- [ ] Release methodology defined ( [release.md](process/release.md) )
|
||||
- [X] Release methodology defined ( [RELEASING.md](../docs/RELEASING.md) )
|
||||
- Closed by https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1572
|
||||
- New Project Governance
|
||||
- [X] TSC members identified
|
||||
- [X] First TSC meeting held
|
||||
@@ -41,7 +42,7 @@ This is a checklist for TSC's to review as part of the intake process. The TSC s
|
||||
- [X] New project announcement done ( https://www.aswf.io/osl-joins-aswf/ )
|
||||
- [X] Project added to ASWF website and ASWF landscape
|
||||
- Graduation
|
||||
- [ ] CII Badge achieved
|
||||
- [X] OpenSSF Best Practices Badge achieved
|
||||
- [ ] Committer Diversity established
|
||||
- [ ] Commit/Contribution growth during incubation
|
||||
- [ ] Committers defined in the project ( [COMMITTERS.csv](COMMITTERS.csv) or [COMMITTERS.yml](COMMITTERS.yml) )
|
||||
@@ -50,4 +51,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.
|
||||
|
||||
+180
-8
@@ -1,8 +1,151 @@
|
||||
<!-- 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)
|
||||
* Fix issue with closure keyword parameters. #1620 (1.13.2.0/1.12.8.0)
|
||||
* Fix crash when adding a default initialized closure. #1624
|
||||
(1.13.2.0/1.12.8.0)
|
||||
* Fix support for closures with array types. #1630 (1.13.2.0/1.12.8.0)
|
||||
|
||||
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)
|
||||
* Fix PTX symbol visibility issues. #1609 (1.13.2.0)
|
||||
* Hide more code that is only used for OptiX mode, when OptiX is disabled.
|
||||
#1608 (1.13.2.0)
|
||||
* Remove dependency on OptiX SDK for building core OSL with OptiX support. You
|
||||
can now build OSL with OptiX support enabled even if you don't have the
|
||||
OptiX SDK headers present at build time. But you will still need them to
|
||||
build your OptiX-based application that uses OSL for GPU rendering. #1627
|
||||
(1.13.2.0/1.12.8.0)
|
||||
|
||||
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)
|
||||
- Define OSL::bitcast utility. #1610 (1.13.2.0)
|
||||
* Make sure that std::hash is defined for ustring and ustringhash. #1599
|
||||
(1.13.1.1)
|
||||
* Deprecate LLVMUtil::internalize_module_functions. #1606 (1.13.1.0)
|
||||
* Work toward always representing strings in shaders as ustringhash rather
|
||||
than ustring: phase 1 #1603 phase2 #1612 (1.13.2.0)
|
||||
|
||||
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) Revised again to reduce changes of user error in #1617
|
||||
(1.13.2.0/1.12.7.1)
|
||||
- Add clangSupport library as dependency to fix linker error on some
|
||||
platforms. #1613 (1.13.2.0/1.12.7.1)
|
||||
* Dependency version support:
|
||||
- Fix some issues that came up with the new icx 2022.0 compiler. #1601
|
||||
(1.13.1.0)
|
||||
- Test against OpenColorIO 2.2. #1616 (1.13.2.0/1.12.7.1)
|
||||
* 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)
|
||||
#1607 (1.13.1.0)
|
||||
- Disabling the dso version of testshade for the coverage analysis test.
|
||||
#1604 (1.13.1.0)
|
||||
- Be sure to run pointcloud tests when partio is found. #1611 (1.13.2.0)
|
||||
- testshade: better testing of all closure parameter types. #1621
|
||||
(1.13.2.0/1.12.8.0)
|
||||
* Platform support:
|
||||
- Include `immintrin.h` only when needed. #1605 (1.13.1.0)
|
||||
|
||||
Documentation:
|
||||
* `doc/RELEASING.md` documents our release process and versioning policies.
|
||||
#1572 (1.13.0.2)
|
||||
|
||||
|
||||
Release 1.12.8.0 -- 3 Jan 2023 (compared to 1.12.7.1)
|
||||
-------------------------------------------------------
|
||||
* Remove dependency on OptiX SDK for building core OSL with OptiX support.
|
||||
You can now build OSL with OptiX support enabled even if you don't have the
|
||||
OptiX SDK headers present at build time. But you will still need them to
|
||||
build your OptiX-based application that uses OSL for GPU rendering. #1627
|
||||
* Batch mode: fix issue with closure keyword parameters. #1620
|
||||
* Batch mode: fix crash when adding a default initialized closure. #1624
|
||||
* Batch mode: Fix support for closures with array types. #1630
|
||||
* testshade: better testing of all closure parameter types. #1621
|
||||
* Fix various CI breaks as dependencies shifted. #1629 #1631 #1633
|
||||
|
||||
Release 1.12.7.1 -- 1 Dec 2022 (compared to 1.12.7.0)
|
||||
-------------------------------------------------------
|
||||
* Add clangSupport library as dependency to fix linker error on some
|
||||
platforms. #1613
|
||||
* Test against OpenColorIO 2.2. #1616
|
||||
* Build: Fix how version overrides work to reduce the chance of user mistakes.
|
||||
#1617
|
||||
|
||||
Release 1.12.7.0 -- 1 Nov 2022 (compared to 1.12.6.2)
|
||||
-------------------------------------------------------
|
||||
* Optix: Change naming of certain compiler-generated constants in a way that
|
||||
improves use of the PTX cache. #1570
|
||||
* Batch: Fix uninitialized members in ReadEvent internals. #1575
|
||||
* `testshade --help` now prints TextureSystem options and hardware info. #1584
|
||||
* oslc: Fix memory leak in ASTvariable_declaration. #1576
|
||||
* Fix memory leaks in light path expression code. #1593 #1594
|
||||
* Include the immintrin.h header only when needed. #1605
|
||||
* icx: Improvements to fix problems exposed by new icx 2022.2 compiler. #1601
|
||||
* Testing: CMake cache variables to control the testing timeout length. #1571
|
||||
* CI: Add a dynamic analysis test using address and leak sanitizers. #1581
|
||||
* CI: Now using SonarCloud static analysis. #1551
|
||||
* CI: Many improvements in testing code coverage #1607
|
||||
* CI: Make sure to run pointcloud tests when partio is found. #1611
|
||||
* Developers: platform.h now defines OSL_ALLOCA macro. #1589
|
||||
* Developers: platform.h now defines OSL::bitcast utility. #1610
|
||||
|
||||
Release 1.12 -- 1 Oct 2022 (compared to 1.11)
|
||||
----------------------------------------------
|
||||
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 +176,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
|
||||
@@ -58,7 +203,7 @@ API changes, new options, new ShadingSystem features (for renderer writers):
|
||||
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)
|
||||
@@ -83,8 +228,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)
|
||||
@@ -101,10 +247,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"
|
||||
@@ -142,8 +290,14 @@ Bug fixes and other improvements (internals):
|
||||
* 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)
|
||||
* Fix testrender memory error on teardown. #1499 (1.12.4.6)
|
||||
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.
|
||||
@@ -167,6 +321,12 @@ Internals/developer concerns:
|
||||
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:
|
||||
@@ -208,12 +368,14 @@ 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), 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
|
||||
@@ -232,6 +394,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
|
||||
@@ -240,14 +404,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)
|
||||
@@ -262,6 +427,10 @@ Build & test system improvements:
|
||||
#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)
|
||||
@@ -281,6 +450,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
|
||||
|
||||
|
||||
|
||||
@@ -748,7 +920,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
|
||||
|
||||
+18
-7
@@ -3,7 +3,16 @@
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
cmake_minimum_required (VERSION 3.12)
|
||||
project (OSL VERSION 1.12.5.0
|
||||
|
||||
set (OSL_VERSION "1.13.4.0")
|
||||
set (OSL_VERSION_OVERRIDE "" CACHE STRING
|
||||
"Version override (use with caution)!")
|
||||
mark_as_advanced (OSL_VERSION_OVERRIDE)
|
||||
if (OSL_VERSION_OVERRIDE)
|
||||
set (OSL_VERSION ${OSL_VERSION_OVERRIDE})
|
||||
endif ()
|
||||
|
||||
project (OSL VERSION ${OSL_VERSION}
|
||||
LANGUAGES CXX C
|
||||
HOMEPAGE_URL "https://github.com/AcademySoftwareFoundation/OpenShadingLanguage")
|
||||
set (PROJ_NAME ${PROJECT_NAME}) # short name
|
||||
@@ -89,7 +98,8 @@ else ()
|
||||
endif ()
|
||||
option (OSL_BUILD_PLUGINS "Bool OSL plugins, for example OIIO plugin" ON)
|
||||
option (OSL_BUILD_SHADERS "Build shaders" ON)
|
||||
option (USE_OPTIX "Include OptiX support" OFF)
|
||||
option (OSL_USE_OPTIX "Include OptiX support" OFF)
|
||||
message(STATUS "OSL_USE_OPTIX: ${OSL_USE_OPTIX}")
|
||||
set (OPTIX_EXTRA_LIBS CACHE STRING "Extra lib targets needed for OptiX")
|
||||
set (CUDA_EXTRA_LIBS CACHE STRING "Extra lib targets needed for CUDA")
|
||||
set (CUDA_TARGET_ARCH "sm_60" CACHE STRING "CUDA GPU architecture (e.g. sm_50)")
|
||||
@@ -98,6 +108,7 @@ set (OSL_SHADER_INSTALL_DIR "${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT_NAME}/shade
|
||||
set (OSL_PTX_INSTALL_DIR "${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT_NAME}/ptx"
|
||||
CACHE STRING "Directory where OptiX PTX files will be installed")
|
||||
set (CMAKE_DEBUG_POSTFIX "" CACHE STRING "Library naming postfix for Debug builds (e.g., '_debug')")
|
||||
option (OSL_USTRINGREP_IS_HASH "Always use ustringhash for strings" OFF)
|
||||
|
||||
|
||||
set (OSL_NO_DEFAULT_TEXTURESYSTEM OFF CACHE BOOL "Do not use create a raw OIIO::TextureSystem")
|
||||
@@ -117,14 +128,14 @@ if (OIIO_FMATH_SIMD_FRIENDLY)
|
||||
add_definitions (-DOIIO_FMATH_SIMD_FRIENDLY=1)
|
||||
endif ()
|
||||
|
||||
if (USE_OPTIX)
|
||||
add_definitions ("-DOSL_USE_OPTIX=1")
|
||||
endif ()
|
||||
|
||||
# Define OSL_INTERNAL symbol only when building OSL itself, will not be
|
||||
# defined for downstream projects using OSL.
|
||||
add_definitions (-DOSL_INTERNAL=1)
|
||||
|
||||
# To make sure we aren't relying on deprecated OIIO features, we define
|
||||
# OIIO_DISABLE_DEPRECATED before including any OIIO headers.
|
||||
add_definitions (-DOIIO_DISABLE_DEPRECATED=1)
|
||||
|
||||
# Set the default namespace. For symbol hiding reasons, it's important that
|
||||
# the project name is a subset of the namespace name.
|
||||
set (${PROJ_NAME}_NAMESPACE ${PROJECT_NAME} CACHE STRING
|
||||
@@ -212,7 +223,7 @@ if (OSL_BUILD_PLUGINS)
|
||||
add_subdirectory (src/osl.imageio)
|
||||
endif ()
|
||||
|
||||
if (USE_QT AND Qt5_FOUND)
|
||||
if (USE_QT AND (Qt5_FOUND OR Qt6_FOUND))
|
||||
add_subdirectory (src/osltoy)
|
||||
endif ()
|
||||
|
||||
|
||||
+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;
|
||||
}
|
||||
|
||||
+26
-26
@@ -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.23)
|
||||
* Build system: [CMake](https://cmake.org/) 3.12 or newer (tested through 3.26)
|
||||
|
||||
* 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 14)
|
||||
- Microsoft Visual Studio **2017 or newer**
|
||||
- Intel C++ compiler icc **version 17 or newer** or 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 16)
|
||||
- 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,15 @@ NEW or CHANGED dependencies since the last major release are **bold**.
|
||||
$OpenImageIO_ROOT/lib to be in your LD_LIBRARY_PATH (or
|
||||
DYLD_LIBRARY_PATH on OS X).
|
||||
|
||||
* **[LLVM](http://www.llvm.org) 9, 10, 11, 12, 13, or 14**, including clang
|
||||
libraries.
|
||||
* [LLVM](http://www.llvm.org) 9, 10, 11, 12, 13, 14, or 15, including
|
||||
clang libraries. LLVM 16 doesn't work yet, we need to make changes
|
||||
on the OSL side to be compatible.
|
||||
|
||||
* [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.81)
|
||||
* [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
|
||||
@@ -51,17 +56,17 @@ NEW or CHANGED dependencies since the last major release are **bold**.
|
||||
Note that on some MacOS/xcode releases, the system-installed Bison is too
|
||||
old, and it's better to install a newer Bison (via Homebrew is one way to
|
||||
do this easily).
|
||||
* [PugiXML](http://pugixml.org/)
|
||||
* [PugiXML](http://pugixml.org/) >= 1.8 (we have tested through 1.13).
|
||||
* (optional) [Partio](https://www.disneyanimation.com/technology/partio.html)
|
||||
If it is not found at build time, the OSL `pointcloud` functions will not
|
||||
be operative.
|
||||
* (optional) Python: If you are building the Python bindings or running the
|
||||
testsuite:
|
||||
* Python >= 2.7 (tested against 2.7, 3.7, 3.8, 3.9)
|
||||
* 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.
|
||||
* (optional) Qt5 >= 5.6 or Qt6 (tested Qt5 through 5.15 and Qt6 through 6.4).
|
||||
If not found at build time, the `osltoy` application will be disabled.
|
||||
|
||||
|
||||
|
||||
@@ -93,19 +98,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:
|
||||
|
||||
@@ -209,7 +209,10 @@ ifneq (${BUILD_MISSING_DEPS},)
|
||||
endif
|
||||
|
||||
ifneq (${USE_OPTIX},)
|
||||
MY_CMAKE_FLAGS += -DUSE_OPTIX:BOOL=${USE_OPTIX}
|
||||
MY_CMAKE_FLAGS += -DOSL_USE_OPTIX:BOOL=${USE_OPTIX}
|
||||
endif
|
||||
ifneq (${OSL_USE_OPTIX},)
|
||||
MY_CMAKE_FLAGS += -DOSL_USE_OPTIX:BOOL=${OSL_USE_OPTIX}
|
||||
endif
|
||||
|
||||
ifneq (${USE_PYTHON},)
|
||||
@@ -294,7 +297,7 @@ package_source: install
|
||||
# 'make clang-format' runs clang-format on all source files (if it's installed)
|
||||
clang-format: config
|
||||
@ ( cd ${build_dir} ; \
|
||||
${CMAKE} --build . --target run-clang-format --config ${CMAKE_BUILD_TYPE} \
|
||||
${CMAKE} --build . --target clang-format --config ${CMAKE_BUILD_TYPE} \
|
||||
)
|
||||
|
||||
|
||||
@@ -397,7 +400,7 @@ help:
|
||||
@echo " USE_SIMD=arch Build with SIMD support (comma-separated choices:"
|
||||
@echo " 0, sse2, sse3, ssse3, sse4.1, sse4.2, f16c,"
|
||||
@echo " avx, avx2, avx512f)"
|
||||
@echo " USE_OPTIX=1 Build the OptiX test renderer"
|
||||
@echo " OSL_USE_OPTIX=1 Build the OptiX test renderer"
|
||||
@echo " USE_BATCHED=targets Build batched SIMD execution of shaders for (comma-separated choices:"
|
||||
@echo " 0, b8_AVX, b8_AVX2, b8_AVX2_noFMA,"
|
||||
@echo " b8_AVX512, b8_AVX512_noFMA,"
|
||||
|
||||
@@ -225,8 +225,7 @@ adding OSL support):
|
||||
* [Blender/Cycles](https://docs.blender.org/manual/en/dev/render/shader_nodes/osl.html)
|
||||
* [Chaos Group: V-Ray](https://www.chaosgroup.com/)
|
||||
* [Pixar: PhotoRealistic RenderMan RIS](https://renderman.pixar.com)
|
||||
* [Isotropix: Clarisse](http://www.isotropix.com/clarisse)
|
||||
* [Isotropix: Angie](http://www.isotropix.com/angie)
|
||||
* Isotropix: [Clarisse iFX](https://www.isotropix.com/products/clarisse/ifx) / [Clarisse BUiLDER](https://www.isotropix.com/products/clarisse/builder) / [Angie](https://www.isotropix.com/products/angie)
|
||||
* [Autodesk Beast](http://www.autodesk.com/products/beast/overview)
|
||||
* [Appleseed](http://appleseedhq.net)
|
||||
* [Animal Logic: Glimpse renderer](https://www.fxguide.com/featured/a-glimpse-at-animal-logic/)
|
||||
@@ -390,13 +389,30 @@ Films using OSL (grouped by year of release date):
|
||||
Last Night in Soho,
|
||||
Ghostbusters: Afterlife,
|
||||
Spider-Man 3: No Way Home,
|
||||
Matrix Resurrections
|
||||
* **(2022 / upcoming)**
|
||||
Matrix Resurrections,
|
||||
Sing 2
|
||||
* **(2022)**
|
||||
Hotel Transylvania 4: Transformania,
|
||||
Death on the Nile,
|
||||
Uncharted,
|
||||
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,
|
||||
Minions: Rise of Gru,
|
||||
Bullet Train,
|
||||
Slumberland,
|
||||
Glass Onion
|
||||
* **(2023 / upcoming)**
|
||||
Ant-Man and the Wasp: Quantumania,
|
||||
...
|
||||
|
||||
|
||||
|
||||
Building and Installation
|
||||
-------------------------
|
||||
|
||||
@@ -427,9 +443,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 +473,6 @@ Contacts, Links, and References
|
||||
|
||||
[OSL home page](http://openshadinglanguage.org)
|
||||
|
||||
[Sony Pictures Imageworks main open source page](http://opensource.imageworks.com)
|
||||
|
||||
|
||||
|
||||
@@ -466,19 +485,20 @@ 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,
|
||||
Matthaus G. Chajdas, Clark Chen, Alejandro Conty, Damien Courtois, Dieter De
|
||||
Baets, Thomas Dinges, Daniel Dresser, Mads Drøschler, Peter Ellerington, Luke
|
||||
Emrose, Louis Feng, Mark Final, Henri Fousse, Stephen Friedman, Syoyo Fujita,
|
||||
Tim Grant, Larry Gritz, Nicolas Guiard, Euan Haahr, Derek Haase, Sven-Hendrik
|
||||
Haase, John Haddon, Niklas Harrysson, Daniel Heckenberg, 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.)
|
||||
Haase, John Haddon, Niklas Harrysson, Daniel Heckenberg, Chris Hellmuth,
|
||||
Adrien Herubel, Dan Horák, Thiago Ize, Matt Johnson, Ronan Keryell, Chris
|
||||
Kulla, Elvic Liang, Max Liani, Adam Martinez, John Mertic, Bastien Montagne,
|
||||
Steena Monteiro, Patrick Mours, Alexis Oblet, Erich Ocean, Mikko Ohtamaa, Jino
|
||||
Park, Alexei Pawlow, Jay Reynolds, Declan Russell, Benoit Ruiz, Patrick
|
||||
Scheibe, Alex Schworer, Jonathan Scruggs, Sergey Sharybin, Mark Sisson, Sandip
|
||||
Shukla, Cliff Stein, Stephan Steinbach, Luya Tshimbalanga, Esteban Tovagliari,
|
||||
Brecht Van Lommel, Alexander von Knorring, Alex Wells, Roman Zulak. (Listed
|
||||
alphabetically; if we've left anybody out, it is inadvertent, please let us
|
||||
know.)
|
||||
|
||||
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.
|
||||
|
||||
|
||||
+17
-13
@@ -33,7 +33,7 @@ endif # endif ${SP_OS}
|
||||
|
||||
MY_CMAKE_FLAGS += -DSP_OS=${SP_OS}
|
||||
MY_CMAKE_FLAGS += -DSPI_COMPILER_PLATFORM=${SPI_COMPILER_PLATFORM}
|
||||
MY_CMAKE_FLAGS += -DEXTRA_CPP_ARGS:STRING="-DOSL_SPI=1" -DOSL_SITE:STRING=spi
|
||||
MY_CMAKE_FLAGS += -DOSL_SITE:STRING=spi
|
||||
MY_CMAKE_FLAGS += -DSPI_TESTS=1
|
||||
MY_CMAKE_FLAGS += -DOSL_NAMESPACE_INCLUDE_PATCH=1
|
||||
REZ_PACKAGE_ROOT ?= /shots/spi/home/software/packages
|
||||
@@ -147,14 +147,14 @@ ifeq (${SP_OS}, rhel7)
|
||||
endif
|
||||
|
||||
# Cuda/OptiX
|
||||
USE_OPTIX ?= 1
|
||||
OSL_USE_OPTIX ?= 1
|
||||
CUDA_VERSION ?= 11.1.1
|
||||
OPTIX_VERSION ?= 7.2.0
|
||||
# CUDA_TOOLKIT_ROOT_DIR = $(shell rez-env -b cuda-${CUDA_VERSION} ${SPI_COMPILER_PLATFORM} -c "echo '$CUDA_TOOLKIT_ROOT'")
|
||||
CUDA_TOOLKIT_ROOT_DIR ?= /shots/spi/home/lib/arnold/rhel7/cuda_${CUDA_VERSION}
|
||||
OptiX_ROOT ?= /shots/spi/home/lib/arnold/rhel7/optix_${OPTIX_VERSION}
|
||||
OPTIXHOME = ${OptiX_ROOT}
|
||||
MY_CMAKE_FLAGS += -DUSE_OPTIX=${USE_OPTIX} \
|
||||
MY_CMAKE_FLAGS += -DOSL_USE_OPTIX=${OSL_USE_OPTIX} \
|
||||
-DCUDA_TOOLKIT_ROOT_DIR=${CUDA_TOOLKIT_ROOT_DIR} \
|
||||
-DCUDA_EXTRA_LIBS=${CUDA_EXTRA_LIBS} \
|
||||
-DOPTIXHOME=${OPTIXHOME} -DOPTIX_EXTRA_LIBS=lzma
|
||||
@@ -181,14 +181,18 @@ 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},clang16)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@16/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@16/bin/clang++
|
||||
else ifeq (${COMPILER},clang)
|
||||
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
||||
else ifeq (${COMPILER},gcc)
|
||||
@@ -196,13 +200,13 @@ else ifeq (${platform}, macosx)
|
||||
else ifeq (${COMPILER},)
|
||||
# default compiler is clang, taken from the LLVM directory
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=${LLVM_DIRECTORY}/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=${LLVM_DIRECTORY}/bin/clang++
|
||||
-DCMAKE_C_COMPILER=${LLVM_ROOT}/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=${LLVM_ROOT}/bin/clang++
|
||||
else ifeq (${COMPILER},llvm)
|
||||
# "llvm" means "use the clang from our llvm"
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=${LLVM_DIRECTORY}/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=${LLVM_DIRECTORY}/bin/clang++
|
||||
-DCMAKE_C_COMPILER=${LLVM_ROOT}/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=${LLVM_ROOT}/bin/clang++
|
||||
endif
|
||||
|
||||
# end generic OSX
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# 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
|
||||
@@ -14,7 +14,7 @@ uname
|
||||
|
||||
|
||||
if [[ `uname` == "Linux" ]] ; then
|
||||
LLVM_VERSION=${LLVM_VERSION:=13.0.0}
|
||||
LLVM_VERSION=${LLVM_VERSION:=14.0.0}
|
||||
LLVM_INSTALL_DIR=${LLVM_INSTALL_DIR:=${PWD}/llvm-install}
|
||||
if [[ "$GITHUB_WORKFLOW" != "" ]] ; then
|
||||
LLVM_DISTRO_NAME=${LLVM_DISTRO_NAME:=ubuntu-18.04}
|
||||
|
||||
@@ -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"}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -18,8 +18,8 @@ if [[ "$ASWF_ORG" != "" ]] ; then
|
||||
|
||||
#ls /etc/yum.repos.d
|
||||
|
||||
sudo yum install -y giflib giflib-devel && true
|
||||
# sudo yum install -y ffmpeg ffmpeg-devel && true
|
||||
sudo /usr/bin/yum install -y giflib giflib-devel && true
|
||||
# sudo /usr/bin/yum install -y ffmpeg ffmpeg-devel && true
|
||||
|
||||
if [[ "${CONAN_LLVM_VERSION}" != "" ]] ; then
|
||||
mkdir conan
|
||||
@@ -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 /usr/bin/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
|
||||
@@ -57,22 +61,39 @@ if [[ "$ASWF_ORG" != "" ]] ; then
|
||||
else
|
||||
# Using native Ubuntu runner
|
||||
|
||||
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
|
||||
# sudo add-apt-repository ppa:ubuntu-toolchain-r/test
|
||||
time sudo apt-get update
|
||||
|
||||
time sudo apt-get -q install -y \
|
||||
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
|
||||
|
||||
if [[ "${QT_VERSION:-5}" == "5" ]] ; then
|
||||
time sudo apt-get -q install -y \
|
||||
qt5-default || /bin/true
|
||||
elif [[ "${QT_VERSION}" == "6" ]] ; then
|
||||
time sudo apt-get -q install -y \
|
||||
qt6-base-dev || /bin/true
|
||||
fi
|
||||
|
||||
export CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu:$CMAKE_PREFIX_PATH
|
||||
|
||||
# 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 +106,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 +115,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
|
||||
@@ -164,7 +176,7 @@ if [[ "$OPENIMAGEIO_VERSION" != "" ]] ; then
|
||||
# Don't let warnings in OIIO break OSL's CI run
|
||||
export OPENIMAGEIO_CMAKE_FLAGS+=" -DSTOP_ON_WARNING=OFF"
|
||||
export OPENIMAGEIO_CMAKE_FLAGS+=" -DUSE_OPENGL=0"
|
||||
if [[ $OPENIMAGEIO_VERSION == master ]] ; then
|
||||
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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -19,27 +19,33 @@ if [[ `which brew` == "" ]] ; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -ex
|
||||
|
||||
#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 unlink python@2.7 || true
|
||||
brew unlink python@3.9 || true
|
||||
brew unlink python@3.8 || true
|
||||
brew install --display-times -q python@${PYTHON_VERSION} || true
|
||||
# brew unlink python@2.7 || true
|
||||
# brew unlink python@3.8 || true
|
||||
# brew unlink python@3.9 || true
|
||||
brew unlink python@3.10 || true
|
||||
brew link --overwrite --force python@${PYTHON_VERSION} || true
|
||||
brew upgrade --display-times -q cmake || true
|
||||
brew install --display-times -q ilmbase openexr
|
||||
brew install --display-times -q imath openexr
|
||||
#brew install --display-times -q freetype
|
||||
brew install --display-times -q opencolorio partio pugixml
|
||||
brew install --display-times -q --overwrite --force opencolorio || true
|
||||
brew install --display-times -q partio pugixml
|
||||
brew install --display-times -q pybind11 numpy || true
|
||||
brew install --display-times -q tbb || true
|
||||
brew install --display-times -q flex bison
|
||||
brew install --display-times -q llvm${LLVMBREWVER}
|
||||
brew install --display-times -q qt
|
||||
brew install --display-times -q qt${QT_BREW_VERSION}
|
||||
|
||||
echo ""
|
||||
echo "After brew installs:"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
+12
-50
@@ -121,11 +121,11 @@ endif ()
|
||||
# give more fine-grained control for hiding symbols, because sometimes
|
||||
# dependent libraries may not be well behaved and need extra hiding.
|
||||
#
|
||||
set (CXX_VISIBILITY_PRESET "hidden" CACHE STRING "Symbol visibility (hidden or default")
|
||||
set (CMAKE_CXX_VISIBILITY_PRESET "hidden" CACHE STRING "Symbol visibility (hidden or default")
|
||||
option (VISIBILITY_INLINES_HIDDEN "Hide symbol visibility of inline functions" ON)
|
||||
set (VISIBILITY_MAP_FILE "${PROJECT_SOURCE_DIR}/src/build-scripts/hidesymbols.map" CACHE FILEPATH "Visibility map file")
|
||||
set (C_VISIBILITY_PRESET ${CXX_VISIBILITY_PRESET})
|
||||
if (${CXX_VISIBILITY_PRESET} STREQUAL "hidden" AND VISIBILITY_MAP_FILE AND
|
||||
set (CMAKE_C_VISIBILITY_PRESET ${CMAKE_CXX_VISIBILITY_PRESET})
|
||||
if (${CMAKE_CXX_VISIBILITY_PRESET} STREQUAL "hidden" AND VISIBILITY_MAP_FILE AND
|
||||
(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG) AND
|
||||
(CMAKE_SYSTEM_NAME MATCHES "Linux|kFreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "GNU"))
|
||||
# Linux/FreeBSD/Hurd: also hide all the symbols of dependent libraries
|
||||
@@ -226,7 +226,7 @@ endif ()
|
||||
|
||||
|
||||
|
||||
# We wil use this for ccache and timing
|
||||
# We will use this for ccache and timing
|
||||
set (MY_RULE_LAUNCH "")
|
||||
|
||||
|
||||
@@ -342,17 +342,17 @@ set (USE_BATCHED "" CACHE STRING "Build batched SIMD shader execution for (0, b8
|
||||
option (VEC_REPORT "Enable compiler's reporting system for vectorization" OFF)
|
||||
set (BATCHED_SUPPORT_DEFINES "")
|
||||
set (BATCHED_TARGET_LIBS "")
|
||||
set (BUILD_BATCHED False)
|
||||
set (OSL_BUILD_BATCHED 0)
|
||||
if (NOT USE_BATCHED STREQUAL "")
|
||||
message (STATUS "Compiling with batched SIMD targets ${USE_BATCHED}")
|
||||
if (NOT USE_BATCHED STREQUAL "0")
|
||||
set (BUILD_BATCHED 1)
|
||||
set (OSL_BUILD_BATCHED 1)
|
||||
string (REPLACE "," ";" BATCHED_TARGET_LIST ${USE_BATCHED})
|
||||
foreach (batched_target ${BATCHED_TARGET_LIST})
|
||||
if (VERBOSE)
|
||||
message (STATUS "BATCHED target: ${batched_target}")
|
||||
endif ()
|
||||
set (BATCHED_SUPPORT_DEFINES ${BATCHED_SUPPORT_DEFINES} "__OSL_SUPPORTS_${batched_target}")
|
||||
list (APPEND BATCHED_SUPPORT_DEFINES "__OSL_SUPPORTS_${batched_target}")
|
||||
endforeach()
|
||||
else ()
|
||||
message (STATUS "Compiling with NO batched SIMD targets, USE_BATCHED=0")
|
||||
@@ -376,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 ()
|
||||
|
||||
|
||||
@@ -394,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")
|
||||
@@ -475,29 +460,7 @@ 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/*.cpp"
|
||||
"src/*.h"
|
||||
"src/*.cu"
|
||||
"src/include/*.h"
|
||||
"src/liboslcomp/*.cpp"
|
||||
"src/liboslcomp/*.h"
|
||||
"src/liboslexec/batch*.cpp"
|
||||
"src/liboslexec/wide/*.cpp"
|
||||
"src/liboslexec/wide/*.h"
|
||||
"src/liboslexec/rs_fallback.cpp"
|
||||
"src/liboslquery/*.cpp"
|
||||
"src/liboslnoise/*.cpp"
|
||||
"src/liboslquery/*.h"
|
||||
"src/oslinfo/*.cpp"
|
||||
"src/oslc/*.cpp"
|
||||
"src/osl.imageio/*.cpp"
|
||||
"src/osltoy/*.cpp"
|
||||
"src/osltoy/*.h"
|
||||
"src/testrender/*.h"
|
||||
"src/testrender/*.cpp"
|
||||
"src/testshade/*.h"
|
||||
"src/testshade/*.cpp"
|
||||
"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
|
||||
@@ -508,7 +471,6 @@ if (PROJECT_IS_TOP_LEVEL)
|
||||
"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
|
||||
@@ -529,7 +491,7 @@ if (PROJECT_IS_TOP_LEVEL)
|
||||
# message (STATUS "clang-format file list: ${FILES_TO_FORMAT}")
|
||||
file (COPY ${CMAKE_CURRENT_SOURCE_DIR}/.clang-format
|
||||
DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||
add_custom_target (run-clang-format
|
||||
add_custom_target (clang-format
|
||||
COMMAND "${CLANG_FORMAT_EXE}" -i -style=file ${FILES_TO_FORMAT} )
|
||||
else ()
|
||||
message (STATUS "clang-format not found.")
|
||||
|
||||
@@ -21,6 +21,12 @@ function ( NVCC_COMPILE cuda_src extra_headers ptx_generated extra_nvcc_args )
|
||||
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 ()
|
||||
|
||||
add_custom_command ( OUTPUT ${cuda_ptx}
|
||||
COMMAND ${CUDA_NVCC_EXECUTABLE}
|
||||
"-I${OPTIX_INCLUDES}"
|
||||
|
||||
@@ -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
|
||||
@@ -115,6 +115,7 @@ checked_find_package (pugixml REQUIRED
|
||||
# LLVM library setup
|
||||
checked_find_package (LLVM REQUIRED
|
||||
VERSION_MIN 9.0
|
||||
VERSION_MAX 15.9
|
||||
PRINT LLVM_SYSTEM_LIBRARIES CLANG_LIBRARIES)
|
||||
# ensure include directory is added (in case of non-standard locations
|
||||
include_directories (BEFORE SYSTEM "${LLVM_INCLUDES}")
|
||||
@@ -136,6 +137,27 @@ 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 ()
|
||||
if (LLVM_VERSION VERSION_GREATER_EQUAL 16.0)
|
||||
message (ERROR "${ColorYellow}OSL is not yet compatible with LLVM 16.${ColorReset}\n")
|
||||
if (CMAKE_CXX_STANDARD VERSION_LESS 17)
|
||||
message (WARNING "${ColorYellow}LLVM 16+ requires C++17 or higher. "
|
||||
"Please set CMAKE_CXX_STANDARD to 17 or higher.${ColorReset}\n")
|
||||
endif ()
|
||||
if (CMAKE_COMPILER_IS_GNUCC AND (GCC_VERSION VERSION_LESS 7.0))
|
||||
message (WARNING "${ColorYellow}LLVM 16+ requires gcc 7.0 or higher.${ColorReset}\n")
|
||||
endif ()
|
||||
if (CMAKE_COMPILER_IS_CLANG AND (CLANG_VERSION_STRING VERSION_LESS 5.0))
|
||||
message (WARNING "${ColorYellow}LLVM 16+ requires clang 5.0 or higher.${ColorReset}\n")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
checked_find_package (partio)
|
||||
|
||||
@@ -145,60 +167,63 @@ find_python ()
|
||||
|
||||
|
||||
# Qt -- used for osltoy
|
||||
set (qt5_modules Core Gui Widgets)
|
||||
if (OPENGL_FOUND)
|
||||
list (APPEND qt5_modules OpenGL)
|
||||
endif ()
|
||||
option (USE_QT "Use Qt if found" ON)
|
||||
checked_find_package (Qt5 COMPONENTS ${qt5_modules})
|
||||
if (USE_QT AND NOT Qt5_FOUND AND APPLE)
|
||||
message (STATUS " If you think you installed qt5 with Homebrew and it still doesn't work,")
|
||||
message (STATUS " try: export PATH=/usr/local/opt/qt5/bin:$PATH")
|
||||
if (USE_QT)
|
||||
checked_find_package (Qt6 COMPONENTS Core Gui Widgets OpenGLWidgets)
|
||||
if (NOT Qt6_FOUND)
|
||||
checked_find_package (Qt5 COMPONENTS Core Gui Widgets OpenGL)
|
||||
endif ()
|
||||
if (NOT Qt5_FOUND AND NOT Qt6_FOUND AND APPLE)
|
||||
message (STATUS " If you think you installed qt with Homebrew and it still doesn't work,")
|
||||
message (STATUS " try: export PATH=/usr/local/opt/qt/bin:$PATH")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
|
||||
# CUDA setup
|
||||
if (USE_CUDA OR USE_OPTIX)
|
||||
if (NOT CUDA_TOOLKIT_ROOT_DIR AND NOT $ENV{CUDA_TOOLKIT_ROOT_DIR} STREQUAL "")
|
||||
set (CUDA_TOOLKIT_ROOT_DIR $ENV{CUDA_TOOLKIT_ROOT_DIR})
|
||||
endif ()
|
||||
if (OSL_USE_OPTIX)
|
||||
if (USE_LLVM_BITCODE)
|
||||
if (NOT CUDA_TOOLKIT_ROOT_DIR AND NOT $ENV{CUDA_TOOLKIT_ROOT_DIR} STREQUAL "")
|
||||
set (CUDA_TOOLKIT_ROOT_DIR $ENV{CUDA_TOOLKIT_ROOT_DIR})
|
||||
endif ()
|
||||
|
||||
if (NOT CUDA_FIND_QUIETLY OR NOT OptiX_FIND_QUIETLY)
|
||||
message (STATUS "CUDA_TOOLKIT_ROOT_DIR = ${CUDA_TOOLKIT_ROOT_DIR}")
|
||||
endif ()
|
||||
if (NOT CUDA_FIND_QUIETLY OR NOT OptiX_FIND_QUIETLY)
|
||||
message (STATUS "CUDA_TOOLKIT_ROOT_DIR = ${CUDA_TOOLKIT_ROOT_DIR}")
|
||||
endif ()
|
||||
|
||||
checked_find_package (CUDA REQUIRED
|
||||
VERSION_MIN 8.0
|
||||
PRINT CUDA_INCLUDES)
|
||||
set (CUDA_INCLUDES ${CUDA_TOOLKIT_ROOT_DIR}/include)
|
||||
include_directories (BEFORE "${CUDA_INCLUDES}")
|
||||
checked_find_package (CUDA REQUIRED
|
||||
VERSION_MIN 8.0
|
||||
PRINT CUDA_INCLUDES)
|
||||
set (CUDA_INCLUDES ${CUDA_TOOLKIT_ROOT_DIR}/include)
|
||||
include_directories (BEFORE "${CUDA_INCLUDES}")
|
||||
|
||||
STRING (FIND ${LLVM_TARGETS} "NVPTX" nvptx_index)
|
||||
if (NOT ${nvptx_index} GREATER -1)
|
||||
message (FATAL_ERROR "NVPTX target is not available in the provided LLVM build")
|
||||
endif()
|
||||
STRING (FIND ${LLVM_TARGETS} "NVPTX" nvptx_index)
|
||||
if (NOT ${nvptx_index} GREATER -1)
|
||||
message (FATAL_ERROR "NVPTX target is not available in the provided LLVM build")
|
||||
endif()
|
||||
|
||||
set (CUDA_LIB_FLAGS "--cuda-path=${CUDA_TOOLKIT_ROOT_DIR}")
|
||||
set (CUDA_LIB_FLAGS "--cuda-path=${CUDA_TOOLKIT_ROOT_DIR}")
|
||||
|
||||
find_library(cuda_lib NAMES cudart
|
||||
PATHS "${CUDA_TOOLKIT_ROOT_DIR}/lib64" "${CUDA_TOOLKIT_ROOT_DIR}/x64"
|
||||
REQUIRED)
|
||||
set(CUDA_LIBRARIES ${cuda_lib})
|
||||
find_library(cuda_lib NAMES cudart
|
||||
PATHS "${CUDA_TOOLKIT_ROOT_DIR}/lib64" "${CUDA_TOOLKIT_ROOT_DIR}/x64" "${CUDA_TOOLKIT_ROOT_DIR}/lib/x64"
|
||||
REQUIRED)
|
||||
set(CUDA_LIBRARIES ${cuda_lib})
|
||||
|
||||
# testrender & testshade need libnvrtc
|
||||
if ("${CUDA_VERSION}" VERSION_GREATER_EQUAL "10.0")
|
||||
find_library(nvrtc_lib NAMES nvrtc
|
||||
PATHS "${CUDA_TOOLKIT_ROOT_DIR}/lib64" "${CUDA_TOOLKIT_ROOT_DIR}/x64"
|
||||
REQUIRED)
|
||||
set(CUDA_LIBRARIES ${CUDA_LIBRARIES} ${nvrtc_lib})
|
||||
# testrender & testshade need libnvrtc
|
||||
if ("${CUDA_VERSION}" VERSION_GREATER_EQUAL "10.0")
|
||||
find_library(nvrtc_lib NAMES nvrtc
|
||||
PATHS "${CUDA_TOOLKIT_ROOT_DIR}/lib64" "${CUDA_TOOLKIT_ROOT_DIR}/x64" "${CUDA_TOOLKIT_ROOT_DIR}/lib/x64"
|
||||
REQUIRED)
|
||||
set(CUDA_LIBRARIES ${CUDA_LIBRARIES} ${nvrtc_lib})
|
||||
|
||||
set(CUDA_EXTRA_LIBS ${CUDA_EXTRA_LIBS} dl)
|
||||
set(CUDA_EXTRA_LIBS ${CUDA_EXTRA_LIBS} dl)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# OptiX setup
|
||||
if (USE_OPTIX)
|
||||
if (OSL_USE_OPTIX AND OSL_BUILD_TESTS)
|
||||
checked_find_package (OptiX REQUIRED
|
||||
VERSION_MIN 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")
|
||||
@@ -211,7 +236,6 @@ if (USE_CUDA OR USE_OPTIX)
|
||||
target_compile_definitions (${TARGET} PRIVATE "-DPTX_PATH=\"${OSL_PTX_INSTALL_DIR}\"")
|
||||
target_link_libraries (${TARGET} PRIVATE ${CUDA_LIBRARIES} ${CUDA_EXTRA_LIBS} ${OPTIX_LIBRARIES} ${OPTIX_EXTRA_LIBS})
|
||||
endfunction()
|
||||
|
||||
else ()
|
||||
function (osl_optix_target TARGET)
|
||||
endfunction()
|
||||
|
||||
@@ -82,6 +82,11 @@ function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_
|
||||
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!
|
||||
@@ -103,8 +108,8 @@ function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_
|
||||
-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 dependant on the same source
|
||||
# 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 ()
|
||||
@@ -132,7 +137,7 @@ function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_
|
||||
${exec_headers} ${PROJECT_PUBLIC_HEADERS}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
|
||||
# add generated .cpp with embedded bitcode to the list of soures
|
||||
# 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 ( )
|
||||
|
||||
@@ -23,7 +23,13 @@
|
||||
|
||||
# try to find llvm-config, with a specific version if specified
|
||||
if (LLVM_DIRECTORY)
|
||||
set (LLVM_CONFIG_PATH_HINTS "${LLVM_DIRECTORY}/bin")
|
||||
list (APPEND LLVM_CONFIG_PATH_HINTS "${LLVM_DIRECTORY}/bin")
|
||||
endif ()
|
||||
if (LLVM_ROOT)
|
||||
list (APPEND LLVM_CONFIG_PATH_HINTS "${LLVM_ROOT}/bin")
|
||||
endif ()
|
||||
if (DEFINED ENV{LLVM_ROOT})
|
||||
list (APPEND LLVM_CONFIG_PATH_HINTS "$ENV{LLVM_ROOT}/bin")
|
||||
endif ()
|
||||
list (APPEND LLVM_CONFIG_PATH_HINTS
|
||||
"/usr/local/opt/llvm/${LLVM_VERSION}/bin/"
|
||||
@@ -121,7 +127,7 @@ endif ()
|
||||
|
||||
foreach (COMPONENT clangFrontend clangDriver clangSerialization
|
||||
clangParse clangSema clangAnalysis clangAST clangBasic
|
||||
clangEdit clangLex)
|
||||
clangEdit clangLex clangSupport)
|
||||
find_library ( _CLANG_${COMPONENT}_LIBRARY
|
||||
NAMES ${COMPONENT}
|
||||
PATHS ${LLVM_LIB_DIR})
|
||||
|
||||
@@ -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/
|
||||
|
||||
|
||||
@@ -20,12 +20,9 @@ macro (find_python)
|
||||
|
||||
# Attempt to find the desired version, but fall back to other
|
||||
# additional versions.
|
||||
unset (_req)
|
||||
if (USE_PYTHON)
|
||||
set (_req REQUIRED)
|
||||
if (PYTHON_VERSION)
|
||||
list (APPEND _req EXACT)
|
||||
endif ()
|
||||
set (_req REQUIRED)
|
||||
if (PYTHON_VERSION)
|
||||
list (APPEND _req EXACT)
|
||||
endif ()
|
||||
checked_find_package (Python ${PYTHON_VERSION}
|
||||
${_req}
|
||||
@@ -77,7 +74,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 ()
|
||||
|
||||
+67
-31
@@ -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,11 @@ 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 ()
|
||||
# For debug builds, render tests are very slow, so give them a longer timeout
|
||||
if (${testname} MATCHES "render-" AND ${CMAKE_BUILD_TYPE} STREQUAL Debug)
|
||||
set_tests_properties (${testname} PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
endif ()
|
||||
# Some labeling for fun
|
||||
if (${testname} MATCHES "^texture")
|
||||
@@ -76,7 +95,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 ()
|
||||
|
||||
@@ -107,7 +126,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")
|
||||
@@ -128,7 +147,7 @@ macro ( TESTSUITE )
|
||||
# if there is an OPTIX marker file in the directory.
|
||||
# If an environment variable $TESTSUITE_OPTIX is nonzero, then
|
||||
# run all tests with OptiX, even if there's no OPTIX marker.
|
||||
if (USE_OPTIX
|
||||
if (OSL_USE_OPTIX
|
||||
AND (EXISTS "${_testsrcdir}/OPTIX" OR test_all_optix OR _testname MATCHES "optix")
|
||||
AND NOT EXISTS "${_testsrcdir}/NOOPTIX"
|
||||
AND NOT EXISTS "${_testsrcdir}/NOOPTIX-FIXME"
|
||||
@@ -142,8 +161,8 @@ macro ( TESTSUITE )
|
||||
add_one_testsuite ("${_testname}.optix.opt" "${_testsrcdir}"
|
||||
ENV TESTSHADE_OPT=2 TESTSHADE_OPTIX=1 )
|
||||
endif ()
|
||||
|
||||
if (BUILD_BATCHED)
|
||||
|
||||
if (OSL_BUILD_BATCHED)
|
||||
# When building for Batched support, also run it in Batched mode
|
||||
# if there is an BATCHED marker file in the directory.
|
||||
# If an environment variable $TESTSUITE_BATCHED is nonzero, then
|
||||
@@ -156,7 +175,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"
|
||||
@@ -165,7 +184,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")
|
||||
@@ -211,16 +230,17 @@ 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 colorspace comparison
|
||||
cellnoise closure closure-array closure-parameters closure-zero closure-conditional
|
||||
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
|
||||
@@ -239,7 +259,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
|
||||
@@ -259,7 +281,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
|
||||
@@ -277,6 +299,7 @@ macro (osl_add_all_tests)
|
||||
oslc-err-struct-dup oslc-err-struct-print
|
||||
oslc-err-type-as-variable
|
||||
oslc-err-unknown-ctr
|
||||
oslc-literalfold
|
||||
oslc-pragma-warnerr
|
||||
oslc-warn-commainit
|
||||
oslc-variadic-macro
|
||||
@@ -288,14 +311,25 @@ macro (osl_add_all_tests)
|
||||
pragma-nowarn
|
||||
printf-reg
|
||||
printf-whole-array
|
||||
raytype raytype-reg raytype-specialized regex-reg reparam
|
||||
raytype raytype-reg raytype-specialized regex-reg
|
||||
reparam reparam-arrays
|
||||
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
|
||||
render-raytypes
|
||||
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
|
||||
@@ -319,10 +353,10 @@ 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
|
||||
userdata userdata-custom userdata-passthrough
|
||||
vararray-connect vararray-default
|
||||
vararray-deserialize vararray-param
|
||||
vecctr vector vector-reg
|
||||
@@ -339,10 +373,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 ()
|
||||
|
||||
@@ -354,7 +388,7 @@ macro (osl_add_all_tests)
|
||||
endif()
|
||||
|
||||
# Only run pointcloud tests if Partio is found
|
||||
if (PARTIO_FOUND)
|
||||
if (partio_FOUND)
|
||||
TESTSUITE ( pointcloud pointcloud-fold )
|
||||
endif ()
|
||||
|
||||
@@ -363,11 +397,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
|
||||
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)
|
||||
# Some regression tests have a lot of combinations and may need more time to finish
|
||||
if (OSL_BUILD_BATCHED)
|
||||
set_tests_properties (arithmetic-reg.regress.batched.opt
|
||||
PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
set_tests_properties (transform-reg.regress.batched.opt
|
||||
PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
endif ()
|
||||
set_tests_properties (matrix-reg.regress.rsbitcode.opt PROPERTIES TIMEOUT 800)
|
||||
|
||||
set_tests_properties (matrix-reg.regress.rsbitcode.opt
|
||||
PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
endmacro()
|
||||
|
||||
+773
-111
File diff suppressed because it is too large
Load Diff
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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -82,12 +82,13 @@ public:
|
||||
/// Return a Mask with lanes set to true if ok, false if the named matrix
|
||||
/// is not known.
|
||||
virtual Mask get_matrix(BatchedShaderGlobals* bsg, Masked<Matrix44> wresult,
|
||||
ustring from, Wide<const float> wtime)
|
||||
ustringhash from, Wide<const float> wtime)
|
||||
{
|
||||
return Mask(false);
|
||||
}
|
||||
virtual Mask get_matrix(BatchedShaderGlobals* bsg, Masked<Matrix44> result,
|
||||
Wide<const ustring> wfrom, Wide<const float> wtime);
|
||||
Wide<const ustringhash> wfrom,
|
||||
Wide<const float> wtime);
|
||||
virtual bool is_overridden_get_matrix_WmWsWf() const = 0;
|
||||
|
||||
|
||||
@@ -97,12 +98,12 @@ public:
|
||||
/// particular renderer may have a better technique and overload the
|
||||
/// implementation.
|
||||
virtual Mask get_inverse_matrix(BatchedShaderGlobals* bsg,
|
||||
Masked<Matrix44> wresult, ustring to,
|
||||
Masked<Matrix44> wresult, ustringhash to,
|
||||
Wide<const float> wtime);
|
||||
virtual bool is_overridden_get_inverse_matrix_WmsWf() const = 0;
|
||||
virtual Mask get_inverse_matrix(BatchedShaderGlobals* bsg,
|
||||
Masked<Matrix44> wresult,
|
||||
Wide<const ustring> wto,
|
||||
Wide<const ustringhash> wto,
|
||||
Wide<const float> wtime);
|
||||
virtual bool is_overridden_get_inverse_matrix_WmWsWf() const = 0;
|
||||
|
||||
@@ -124,22 +125,23 @@ public:
|
||||
/// specified (object == ustring()), then the renderer should search *first*
|
||||
/// for the attribute on the currently shaded object, and next, if
|
||||
/// unsuccessful, on the currently shaded "scene".
|
||||
virtual Mask get_attribute(BatchedShaderGlobals* bsg, ustring object,
|
||||
ustring name, MaskedData wval)
|
||||
virtual Mask get_attribute(BatchedShaderGlobals* bsg, ustringhash object,
|
||||
ustringhash name, MaskedData wval)
|
||||
{
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
/// Similar to get_attribute(); this method will fetch the 'index'
|
||||
/// element of an attribute array.
|
||||
virtual Mask get_array_attribute(BatchedShaderGlobals* bsg, ustring object,
|
||||
ustring name, int index, MaskedData wval)
|
||||
virtual Mask get_array_attribute(BatchedShaderGlobals* bsg,
|
||||
ustringhash object, ustringhash name,
|
||||
int index, MaskedData wval)
|
||||
{
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
virtual bool get_attribute_uniform(BatchedShaderGlobals* bsg,
|
||||
ustring object, ustring name,
|
||||
ustringhash object, ustringhash name,
|
||||
RefData val)
|
||||
{
|
||||
return false;
|
||||
@@ -148,8 +150,9 @@ public:
|
||||
/// Similar to get_attribute(); this method will fetch the 'index'
|
||||
/// element of an attribute array.
|
||||
virtual bool get_array_attribute_uniform(BatchedShaderGlobals* bsg,
|
||||
ustring object, ustring name,
|
||||
int index, RefData val)
|
||||
ustringhash object,
|
||||
ustringhash name, int index,
|
||||
RefData val)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -159,7 +162,7 @@ public:
|
||||
/// as well. It is assumed the results are varying and returns Mask
|
||||
// with its bit set to off if no user-data with the given name and type was
|
||||
/// found.
|
||||
virtual Mask get_userdata(ustring name, BatchedShaderGlobals* bsg,
|
||||
virtual Mask get_userdata(ustringhash name, BatchedShaderGlobals* bsg,
|
||||
MaskedData wval)
|
||||
{
|
||||
return Mask(false);
|
||||
@@ -206,7 +209,7 @@ public:
|
||||
/// error.
|
||||
///
|
||||
virtual Mask
|
||||
texture(ustring filename, TextureSystem::TextureHandle* texture_handle,
|
||||
texture(ustringhash filename, TextureSystem::TextureHandle* texture_handle,
|
||||
TextureSystem::Perthread* texture_thread_info,
|
||||
const BatchedTextureOptions& options, BatchedShaderGlobals* bsg,
|
||||
Wide<const float> ws, Wide<const float> wt, Wide<const float> wdsdx,
|
||||
@@ -240,7 +243,7 @@ public:
|
||||
/// messages (in case of failure, when the function returns false) will
|
||||
/// be stored there, leaving it up to the caller/shader to handle the
|
||||
/// error.
|
||||
virtual Mask texture3d(ustring filename,
|
||||
virtual Mask texture3d(ustringhash filename,
|
||||
TextureSystem::TextureHandle* texture_handle,
|
||||
TextureSystem::Perthread* texture_thread_info,
|
||||
const BatchedTextureOptions& options,
|
||||
@@ -273,7 +276,7 @@ public:
|
||||
/// messages (in case of failure, when the function returns false) will
|
||||
/// be stored there, leaving it up to the caller/shader to handle the
|
||||
/// error.
|
||||
virtual Mask environment(ustring filename,
|
||||
virtual Mask environment(ustringhash filename,
|
||||
TextureSystem::TextureHandle* texture_handle,
|
||||
TextureSystem::Perthread* texture_thread_info,
|
||||
const BatchedTextureOptions& options,
|
||||
@@ -300,12 +303,12 @@ public:
|
||||
|
||||
virtual TextureSystem::TextureHandle* resolve_udim_uniform(
|
||||
BatchedShaderGlobals* bsg, TexturePerthread* texture_thread_info,
|
||||
ustring filename, TextureSystem::TextureHandle* texture_handle, float S,
|
||||
float T);
|
||||
ustringhash filename, TextureSystem::TextureHandle* texture_handle,
|
||||
float S, float T);
|
||||
|
||||
virtual void resolve_udim(BatchedShaderGlobals* bsg,
|
||||
TexturePerthread* texture_thread_info,
|
||||
ustring filename,
|
||||
ustringhash filename,
|
||||
TextureSystem::TextureHandle* texture_handle,
|
||||
Wide<const float> wS, Wide<const float> wT,
|
||||
Masked<TextureSystem::TextureHandle*> wresult);
|
||||
@@ -313,8 +316,8 @@ public:
|
||||
// Assumes any UDIM has been resolved already
|
||||
virtual bool get_texture_info_uniform(
|
||||
BatchedShaderGlobals* bsg, TexturePerthread* texture_thread_info,
|
||||
ustring filename, TextureSystem::TextureHandle* texture_handle,
|
||||
int subimage, ustring dataname, RefData val);
|
||||
ustringhash filename, TextureSystem::TextureHandle* texture_handle,
|
||||
int subimage, ustringhash dataname, RefData val);
|
||||
|
||||
|
||||
/// Lookup nearest points in a point cloud. It will search for
|
||||
@@ -407,26 +410,25 @@ public:
|
||||
};
|
||||
|
||||
|
||||
virtual void pointcloud_search(BatchedShaderGlobals* bsg, ustring filename,
|
||||
const void* wcenter,
|
||||
virtual void pointcloud_search(BatchedShaderGlobals* bsg,
|
||||
ustringhash filename, const void* wcenter,
|
||||
Wide<const float> wradius, int max_points,
|
||||
bool sort, PointCloudSearchResults& results);
|
||||
virtual bool is_overridden_pointcloud_search() const = 0;
|
||||
|
||||
|
||||
virtual Mask pointcloud_get(BatchedShaderGlobals* bsg, ustring filename,
|
||||
virtual Mask pointcloud_get(BatchedShaderGlobals* bsg, ustringhash filename,
|
||||
Wide<const int[]> windices,
|
||||
Wide<const int> wnum_points, ustring attr_name,
|
||||
MaskedData wout_data);
|
||||
Wide<const int> wnum_points,
|
||||
ustringhash attr_name, MaskedData wout_data);
|
||||
virtual bool is_overridden_pointcloud_get() const = 0;
|
||||
|
||||
|
||||
virtual Mask pointcloud_write(BatchedShaderGlobals* bsg, ustring filename,
|
||||
Wide<const OSL::Vec3> wpos, int nattribs,
|
||||
const ustring* attr_names,
|
||||
const TypeDesc* attr_types,
|
||||
const void** pointers_to_wide_attr_value,
|
||||
Mask mask);
|
||||
virtual Mask
|
||||
pointcloud_write(BatchedShaderGlobals* bsg, ustringhash filename,
|
||||
Wide<const OSL::Vec3> wpos, int nattribs,
|
||||
const ustring* attr_names, const TypeDesc* attr_types,
|
||||
const void** pointers_to_wide_attr_value, Mask mask);
|
||||
virtual bool is_overridden_pointcloud_write() const = 0;
|
||||
|
||||
/// Options for the trace call.
|
||||
@@ -441,7 +443,8 @@ public:
|
||||
Wide<const Vec3> wdRdy);
|
||||
|
||||
virtual void getmessage(BatchedShaderGlobals* bsg, Masked<int> wresult,
|
||||
ustring source, ustring name, MaskedData wval);
|
||||
ustringhash source, ustringhash name,
|
||||
MaskedData wval);
|
||||
|
||||
// pointcloud_search is T.B.D.
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright Contributors to the Open Shading Language project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
|
||||
/// Wrapper class for holding a "device" pointer -- GPU or whatnot. It
|
||||
/// provides protections so that the pointer cannot easily be accessed on the
|
||||
/// host side, where presumably it would not be valid memory.
|
||||
template<class T> class device_ptr {
|
||||
public:
|
||||
device_ptr() = default;
|
||||
|
||||
// Copy ctr from another device_ptr of the same type
|
||||
device_ptr(const device_ptr& other) = default;
|
||||
|
||||
/// On device, device_ptr can construct from a pointer.
|
||||
/// On host, it must be explicitly constructed -- use with caution.
|
||||
#ifdef __CUDA_ARCH__
|
||||
device_ptr(T* ptr) : m_ptr(ptr) {}
|
||||
#else
|
||||
explicit device_ptr(T* ptr) : m_ptr(ptr) {}
|
||||
#endif
|
||||
|
||||
#ifdef __CUDA_ARCH__
|
||||
/// On device, act as a pointer. None of these things are allowed on the
|
||||
/// host.
|
||||
T* operator->() const
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
T& operator*() const
|
||||
{
|
||||
return *m_ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Extract the raw device-side pointer. Use with caution! On the host,
|
||||
/// this will not point to valid memory.
|
||||
T* d_get() const
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
/// Evaluate as bool is a null pointer check.
|
||||
operator bool() const noexcept
|
||||
{
|
||||
return m_ptr != nullptr;
|
||||
}
|
||||
|
||||
/// Reset the pointer to `dptr`, which must be a device-side raw pointer,
|
||||
/// or null. Since this device_ptr is non-owning, any previous value is
|
||||
/// simply overwritten.
|
||||
void reset(T* dptr = nullptr)
|
||||
{
|
||||
m_ptr = dptr;
|
||||
}
|
||||
|
||||
private:
|
||||
T* m_ptr = nullptr; // underlying pointer, initializes to null
|
||||
};
|
||||
|
||||
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
@@ -6,10 +6,6 @@
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
#ifdef __CUDA_ARCH__
|
||||
# include <optix.h>
|
||||
#endif
|
||||
|
||||
// USAGE NOTES:
|
||||
//
|
||||
// To define a "standard" DeviceString, add a STRDECL to <OSL/strdecls.h>
|
||||
@@ -19,37 +15,26 @@
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
|
||||
// Strings are handled differently in OptiX 6 vs OptiX 7.
|
||||
//
|
||||
// In OptiX 7+:
|
||||
// Strings are not stored on the GPU at all. Strings are represented by
|
||||
// their hash values which are computed at compile-time. Because of this,
|
||||
// we have no access to either the strings' contents or their lengths.
|
||||
//
|
||||
// In OptiX 6:
|
||||
// Strings are stored in a block of CUDA device memory. String variables hold a
|
||||
// pointer to the start of the char array for each string. Each canonical string
|
||||
// has a unique entry in the table, so two strings can be tested for equality by
|
||||
// comparing their addresses.
|
||||
//
|
||||
// As a convenience, the ustring hash and the length of the string are also
|
||||
// stored in the table, in the 16 bytes preceding the characters.
|
||||
|
||||
struct DeviceString {
|
||||
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
|
||||
#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 +43,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,8 +52,11 @@ 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)
|
||||
OSL_HOSTDEVICE const char* c_str() const { return m_chars; }
|
||||
#ifndef __CUDA_ARCH__
|
||||
OSL_HOSTDEVICE const char* c_str() const
|
||||
{
|
||||
return m_chars;
|
||||
}
|
||||
#endif
|
||||
|
||||
OSL_HOSTDEVICE bool operator==(const DeviceString& other) const
|
||||
@@ -81,7 +69,7 @@ struct DeviceString {
|
||||
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
|
||||
{
|
||||
@@ -93,7 +81,10 @@ struct DeviceString {
|
||||
return hash() != other;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE operator size_t() const { return hash(); }
|
||||
OSL_HOSTDEVICE operator size_t() const
|
||||
{
|
||||
return hash();
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
@@ -123,9 +114,6 @@ typedef DeviceString StringParam;
|
||||
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
|
||||
} // namespace DeviceStrings
|
||||
#else
|
||||
@@ -140,10 +128,6 @@ namespace DeviceStrings {
|
||||
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
|
||||
|
||||
+65
-48
@@ -108,6 +108,12 @@ public:
|
||||
void jit_aggressive(bool val) { m_jit_aggressive = val; }
|
||||
bool jit_aggressive() const { return m_jit_aggressive; }
|
||||
|
||||
// Select whether the representation of a ustring is going to be
|
||||
// the character pointer, or the hash.
|
||||
enum class UstringRep { charptr, hash };
|
||||
UstringRep ustring_rep() const { return m_ustring_rep; }
|
||||
void ustring_rep(UstringRep rep);
|
||||
|
||||
/// Return a reference to the current context.
|
||||
llvm::LLVMContext& context() const { return *m_llvm_context; }
|
||||
|
||||
@@ -148,15 +154,6 @@ public:
|
||||
void debug_pop_inlined_function();
|
||||
void debug_set_location(OIIO::ustring sourcefile, int sourceline);
|
||||
|
||||
/// Create a new function (that will later be populated with
|
||||
/// instructions) with up to 4 args.
|
||||
OSL_DEPRECATED("Use make_function flavor that takes a cspan (1.12)")
|
||||
llvm::Function* make_function(const std::string& name, bool fastcall,
|
||||
llvm::Type* rettype, llvm::Type* arg1 = NULL,
|
||||
llvm::Type* arg2 = NULL,
|
||||
llvm::Type* arg3 = NULL,
|
||||
llvm::Type* arg4 = NULL);
|
||||
|
||||
/// Create a new function (that will later be populated with
|
||||
/// instructions) with a cspan of args.
|
||||
llvm::Function* make_function(const std::string& name, bool fastcall,
|
||||
@@ -223,7 +220,7 @@ public:
|
||||
|
||||
// Look up the TargetISA enum by name. Special names: "host" means
|
||||
// figure out what this host is, "none" or "" mean to use the baseline
|
||||
// or no special ops not availabe on all flavors of this family of CPUs.
|
||||
// or no special ops not available on all flavors of this family of CPUs.
|
||||
static TargetISA lookup_isa_by_name(string_view target_name = "");
|
||||
|
||||
// Name for this TargetISA enum.
|
||||
@@ -283,12 +280,7 @@ public:
|
||||
Linkage default_linkage = Linkage::Internal,
|
||||
std::string* out_err = nullptr);
|
||||
|
||||
// OLD, might deprecate later
|
||||
/// Change symbols in the module that are marked as having external
|
||||
/// linkage to an alternate linkage that allows them to be discarded if
|
||||
/// not used within the module. Only do this for functions that start
|
||||
/// with prefix, and that DON'T match anything in the two exceptions
|
||||
/// lists.
|
||||
OSL_DEPRECATED("prune_and_internalize_module is better (1.13)")
|
||||
void internalize_module_functions(
|
||||
const std::string& prefix, const std::vector<std::string>& exceptions,
|
||||
const std::vector<std::string>& moreexceptions);
|
||||
@@ -311,7 +303,7 @@ public:
|
||||
|
||||
/// Create a new LLVM basic block (for the current function) and return
|
||||
/// its handle.
|
||||
llvm::BasicBlock* new_basic_block(const std::string& name = std::string());
|
||||
llvm::BasicBlock* new_basic_block(const std::string& name = {});
|
||||
|
||||
/// Save the return block pointer when entering a function. If
|
||||
/// after==NULL, generate a new basic block for where to go after the
|
||||
@@ -383,13 +375,13 @@ public:
|
||||
// vs. relying on a conditional result already in a register.
|
||||
//
|
||||
// To handle 'continue', we allocate a 'continue mask' that is
|
||||
// initially populated with a 0 representing the deactived lanes by
|
||||
// initially populated with a 0 representing the deactivated lanes by
|
||||
// 'continue' operations. We require a location on the stack for each
|
||||
// 'continue mask' in order for a 'continue' statement to modify it and
|
||||
// cause a subset of the lanes to be deactivated. If an continue was
|
||||
// processed, the 'continue mask' is where it will be stored and pulled
|
||||
// from when applying to the unwinding conditional mask stack. When a
|
||||
// loop's scope is exited, the continue mask is popped so it would't be
|
||||
// loop's scope is exited, the continue mask is popped so it wouldn't be
|
||||
// applied to an outer loop.
|
||||
//
|
||||
// The logic of when and how to actually apply these masks is handled
|
||||
@@ -543,8 +535,8 @@ public:
|
||||
llvm::Type* type_triple() const { return m_llvm_type_triple; }
|
||||
llvm::Type* type_matrix() const { return m_llvm_type_matrix; }
|
||||
llvm::Type* type_typedesc() const { return m_llvm_type_longlong; }
|
||||
llvm::Type* type_ustring() { return m_llvm_type_ustring; }
|
||||
llvm::PointerType* type_void_ptr() const { return m_llvm_type_void_ptr; }
|
||||
llvm::PointerType* type_string() { return m_llvm_type_char_ptr; }
|
||||
llvm::PointerType* type_ustring_ptr() const
|
||||
{
|
||||
return m_llvm_type_ustring_ptr;
|
||||
@@ -579,7 +571,8 @@ public:
|
||||
llvm::Type* type_wide_triple() const { return m_llvm_type_wide_triple; }
|
||||
llvm::Type* type_wide_matrix() const { return m_llvm_type_wide_matrix; }
|
||||
llvm::Type* type_wide_void_ptr() const { return m_llvm_type_wide_void_ptr; }
|
||||
llvm::Type* type_wide_string() const
|
||||
llvm::Type* type_wide_ustring() const { return m_llvm_type_wide_ustring; }
|
||||
llvm::PointerType* type_wide_ustring_ptr() const
|
||||
{
|
||||
return m_llvm_type_wide_ustring_ptr;
|
||||
}
|
||||
@@ -629,7 +622,7 @@ public:
|
||||
bool is_packed = false);
|
||||
|
||||
/// Return the llvm::Type that is a pointer to the given llvm type.
|
||||
llvm::Type* type_ptr(llvm::Type* type);
|
||||
llvm::PointerType* type_ptr(llvm::Type* type);
|
||||
|
||||
/// Return the llvm::Type that is the wide version of the given llvm type
|
||||
llvm::Type* type_wide(llvm::Type* type);
|
||||
@@ -638,6 +631,12 @@ public:
|
||||
/// llvm type.
|
||||
llvm::Type* type_array(llvm::Type* type, int n);
|
||||
|
||||
/// Return the true if the llvm::Type is an array
|
||||
bool is_type_array(llvm::Type* type);
|
||||
|
||||
/// Return the llvm::Type of element that the array_type is made up of
|
||||
llvm::Type* element_type_of(llvm::Type* array_type);
|
||||
|
||||
/// Return an llvm::FunctionType that describes a function with the
|
||||
/// given return types, parameter types (in a cspan), and whether it
|
||||
/// uses varargs conventions.
|
||||
@@ -660,26 +659,26 @@ public:
|
||||
/// Return the human-readable name of the type of the llvm value.
|
||||
std::string llvm_typenameof(llvm::Value* val) const;
|
||||
|
||||
/// Return an llvm::Value holding the given floating point constant.
|
||||
/// Return an llvm::Constant holding the given floating point constant.
|
||||
llvm::Constant* constant(float f);
|
||||
|
||||
/// Return an llvm::Value holding the given integer constant.
|
||||
/// Return an llvm::Constant holding the given integer constant.
|
||||
llvm::Constant* constant(int i);
|
||||
|
||||
/// Return an llvm::Value holding the given integer constant.
|
||||
/// Return an llvm::Constant holding the given integer constant.
|
||||
llvm::Constant* constant8(int i);
|
||||
llvm::Constant* constant16(uint16_t i);
|
||||
llvm::Constant* constant64(uint64_t i);
|
||||
llvm::Constant* constant128(uint64_t i);
|
||||
llvm::Constant* constant128(uint64_t left, uint64_t right);
|
||||
|
||||
// Return an llvm::value holding an explicit signed int64_t constant.
|
||||
// Return an llvm::Constant holding an explicit signed int64_t constant.
|
||||
llvm::Constant* constanti64(int64_t i);
|
||||
|
||||
/// Return an llvm::Value holding the given size_t constant.
|
||||
/// Return an llvm::Constant holding the given size_t constant.
|
||||
llvm::Constant* constant(size_t i);
|
||||
|
||||
/// Return an llvm::Value holding the given bool constant.
|
||||
/// Return an llvm::Constant holding the given bool constant.
|
||||
/// Change the name so it doesn't get mixed up with int.
|
||||
llvm::Constant* constant_bool(bool b);
|
||||
|
||||
@@ -687,7 +686,8 @@ public:
|
||||
/// If the type specified is NULL, it will make a 'void *'.
|
||||
llvm::Value* constant_ptr(void* p, llvm::PointerType* type = NULL);
|
||||
|
||||
/// Return an llvm::Value holding the given string constant.
|
||||
/// Return an llvm::Value holding the given string constant (as
|
||||
/// determined by the ustring_rep).
|
||||
llvm::Value* constant(ustring s);
|
||||
llvm::Value* constant(string_view s) { return constant(ustring(s)); }
|
||||
|
||||
@@ -735,19 +735,23 @@ public:
|
||||
|
||||
/// Cast the pointer variable specified by val to the kind of pointer
|
||||
/// described by type (as an llvm pointer type).
|
||||
llvm::Value* ptr_cast(llvm::Value* val, llvm::Type* type);
|
||||
llvm::Value* ptr_cast(llvm::Value* val, llvm::PointerType* type)
|
||||
llvm::Value* ptr_cast(llvm::Value* val, llvm::Type* type,
|
||||
const std::string& llname = {});
|
||||
llvm::Value* ptr_cast(llvm::Value* val, llvm::PointerType* type,
|
||||
const std::string& llname = {})
|
||||
{
|
||||
return ptr_cast(val, (llvm::Type*)type);
|
||||
return ptr_cast(val, (llvm::Type*)type, llname);
|
||||
}
|
||||
|
||||
/// Cast the pointer variable specified by val to a pointer to the type
|
||||
/// described by type (as an llvm data type).
|
||||
llvm::Value* ptr_to_cast(llvm::Value* val, llvm::Type* type);
|
||||
llvm::Value* ptr_to_cast(llvm::Value* val, llvm::Type* type,
|
||||
const std::string& llname = {});
|
||||
|
||||
/// Cast the pointer variable specified by val to a pointer to the given
|
||||
/// data type, return the llvm::Value of the new pointer.
|
||||
llvm::Value* ptr_cast(llvm::Value* val, const OIIO::TypeDesc& type);
|
||||
llvm::Value* ptr_cast(llvm::Value* val, const OIIO::TypeDesc& type,
|
||||
const std::string& llname = {});
|
||||
|
||||
llvm::Value* wide_ptr_cast(llvm::Value* val, const OIIO::TypeDesc& type);
|
||||
|
||||
@@ -757,7 +761,7 @@ public:
|
||||
|
||||
/// Cast the pointer variable specified by val to a pointer of type
|
||||
/// void* return the llvm::Value of the new pointer.
|
||||
llvm::Value* void_ptr(llvm::Value* val);
|
||||
llvm::Value* void_ptr(llvm::Value* val, const std::string& llname = {});
|
||||
|
||||
/// Generate a pointer that is (ptrtype)((char *)ptr + offset).
|
||||
/// If ptrtype is NULL, just return a void*.
|
||||
@@ -865,9 +869,10 @@ public:
|
||||
|
||||
/// Dereference a pointer: return *ptr
|
||||
/// type is the type of the thing being pointed to.
|
||||
llvm::Value* op_load(llvm::Type* type, llvm::Value* ptr);
|
||||
llvm::Value* op_load(llvm::Type* type, llvm::Value* ptr,
|
||||
const std::string& llname = {});
|
||||
// Blind pointer version that's deprecated as of LLVM13:
|
||||
llvm::Value* op_load(llvm::Value* ptr);
|
||||
llvm::Value* op_load(llvm::Value* ptr, const std::string& llname = {});
|
||||
|
||||
llvm::Value* op_gather(llvm::Value* ptr, llvm::Value* index);
|
||||
|
||||
@@ -898,24 +903,30 @@ public:
|
||||
/// llvm::Value, which can be generated from either a constant or a
|
||||
/// runtime-computed integer element index. `type` is the type of the data
|
||||
/// we're retrieving.
|
||||
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, llvm::Value* elem);
|
||||
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, llvm::Value* elem,
|
||||
const std::string& llname = {});
|
||||
// Blind pointer version that's deprecated as of LLVM13:
|
||||
llvm::Value* GEP(llvm::Value* ptr, llvm::Value* elem);
|
||||
llvm::Value* GEP(llvm::Value* ptr, llvm::Value* elem,
|
||||
const std::string& llname = {});
|
||||
|
||||
/// Generate a GEP (get element pointer) with an integer element
|
||||
/// offset. `type` is the type of the data we're retrieving.
|
||||
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, int elem);
|
||||
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, int elem,
|
||||
const std::string& llname = {});
|
||||
// Blind pointer version that's deprecated as of LLVM13:
|
||||
llvm::Value* GEP(llvm::Value* ptr, int elem);
|
||||
llvm::Value* GEP(llvm::Value* ptr, int elem,
|
||||
const std::string& llname = {});
|
||||
|
||||
/// Generate a GEP (get element pointer) with two integer element
|
||||
/// offsets. This is just a special (and common) case of GEP where
|
||||
/// we have a 2-level hierarchy and we have fixed element indices
|
||||
/// that are known at compile time. `type` is the type of the data we're
|
||||
/// retrieving.
|
||||
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, int elem1, int elem2);
|
||||
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, int elem1, int elem2,
|
||||
const std::string& llname = {});
|
||||
// Blind pointer version that's deprecated as of LLVM13:
|
||||
llvm::Value* GEP(llvm::Value* ptr, int elem1, int elem2);
|
||||
llvm::Value* GEP(llvm::Value* ptr, int elem1, int elem2,
|
||||
const std::string& llname = {});
|
||||
|
||||
// Arithmetic ops. It auto-detects the type (int vs float).
|
||||
// ...
|
||||
@@ -1009,9 +1020,10 @@ private:
|
||||
IRBuilder& builder();
|
||||
|
||||
int m_debug;
|
||||
bool m_dumpasm = false;
|
||||
bool m_jit_fma = false;
|
||||
bool m_jit_aggressive = false;
|
||||
bool m_dumpasm = false;
|
||||
bool m_jit_fma = false;
|
||||
bool m_jit_aggressive = false;
|
||||
UstringRep m_ustring_rep = UstringRep::charptr;
|
||||
PerThreadInfo::Impl* m_thread;
|
||||
llvm::LLVMContext* m_llvm_context;
|
||||
llvm::Module* m_llvm_module;
|
||||
@@ -1027,6 +1039,9 @@ private:
|
||||
std::vector<llvm::BasicBlock*> m_loop_after_block; // stack for break
|
||||
std::vector<llvm::BasicBlock*> m_loop_step_block; // stack for continue
|
||||
|
||||
// Incrementing serial numbers
|
||||
int m_next_serial_bb = 0;
|
||||
|
||||
llvm::Type* m_llvm_type_float;
|
||||
llvm::Type* m_llvm_type_double;
|
||||
llvm::Type* m_llvm_type_int;
|
||||
@@ -1039,8 +1054,8 @@ private:
|
||||
llvm::Type* m_llvm_type_void;
|
||||
llvm::Type* m_llvm_type_triple;
|
||||
llvm::Type* m_llvm_type_matrix;
|
||||
llvm::Type* m_llvm_type_ustring;
|
||||
llvm::PointerType* m_llvm_type_void_ptr;
|
||||
llvm::PointerType* m_llvm_type_ustring_ptr;
|
||||
llvm::PointerType* m_llvm_type_char_ptr;
|
||||
llvm::PointerType* m_llvm_type_bool_ptr;
|
||||
llvm::PointerType* m_llvm_type_int_ptr;
|
||||
@@ -1049,6 +1064,7 @@ private:
|
||||
llvm::PointerType* m_llvm_type_triple_ptr;
|
||||
llvm::PointerType* m_llvm_type_matrix_ptr;
|
||||
llvm::PointerType* m_llvm_type_double_ptr;
|
||||
llvm::PointerType* m_llvm_type_ustring_ptr;
|
||||
|
||||
int m_vector_width;
|
||||
llvm::Type* m_llvm_type_wide_float;
|
||||
@@ -1060,11 +1076,12 @@ private:
|
||||
llvm::Type* m_llvm_type_wide_triple;
|
||||
llvm::Type* m_llvm_type_wide_matrix;
|
||||
llvm::Type* m_llvm_type_wide_void_ptr;
|
||||
llvm::Type* m_llvm_type_wide_ustring_ptr;
|
||||
llvm::Type* m_llvm_type_wide_ustring;
|
||||
llvm::PointerType* m_llvm_type_wide_char_ptr;
|
||||
llvm::PointerType* m_llvm_type_wide_int_ptr;
|
||||
llvm::PointerType* m_llvm_type_wide_bool_ptr;
|
||||
llvm::PointerType* m_llvm_type_wide_float_ptr;
|
||||
llvm::PointerType* m_llvm_type_wide_ustring_ptr;
|
||||
llvm::Type* m_llvm_type_native_mask;
|
||||
|
||||
bool m_supports_masked_stores = false;
|
||||
|
||||
+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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#cmakedefine01 OSL_USE_OPTIX
|
||||
#cmakedefine01 OSL_BUILD_BATCHED
|
||||
#define OSL_USE_BATCHED OSL_BUILD_BATCHED
|
||||
|
||||
|
||||
#include <OSL/export.h>
|
||||
#include <OSL/oslversion.h>
|
||||
#include <OSL/platform.h>
|
||||
@@ -62,8 +67,6 @@
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
#define OSL_USE_BATCHED @BUILD_BATCHED@
|
||||
|
||||
/// Various compile-time defaults are defined here that could, in
|
||||
/// principle, be redefined if you are using OSL in some particular
|
||||
/// renderer that wanted things a different way.
|
||||
@@ -102,7 +105,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;
|
||||
@@ -133,6 +136,101 @@ fmtformat(const Str& fmt, Args&&... args)
|
||||
|
||||
|
||||
|
||||
/// OSL_USTRINGREP_IS_HASH will be 1 if the build-time option was enabled to
|
||||
/// make the ustringrep be a ustringhash, rather than a ustring directly.
|
||||
#cmakedefine01 OSL_USTRINGREP_IS_HASH
|
||||
|
||||
#if OSL_USTRINGREP_IS_HASH
|
||||
/// ustringrep is the class we use to represent strings in the shader.
|
||||
using ustringrep = ustringhash;
|
||||
#else
|
||||
/// ustringrep is the class we use to represent strings in the shader.
|
||||
using ustringrep = ustring;
|
||||
#endif
|
||||
|
||||
#if OSL_USTRINGREP_IS_HASH
|
||||
/// ustring_pod is the type we use to pass string data in llvm function calls.
|
||||
using ustring_pod = size_t;
|
||||
#else
|
||||
/// ustring_pod is the type we use to pass string data in llvm function calls.
|
||||
using ustring_pod = const char*;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/// Convenience function to convert to a ustring.
|
||||
inline ustring
|
||||
ustring_from(ustringhash h)
|
||||
{
|
||||
return ustring::from_hash(h.hash());
|
||||
}
|
||||
|
||||
/// Convenience function to convert to a ustring.
|
||||
inline ustring
|
||||
ustring_from(ustring u)
|
||||
{
|
||||
return u;
|
||||
}
|
||||
|
||||
/// Convenience function to convert to a ustring.
|
||||
inline ustring
|
||||
ustring_from(string_view s)
|
||||
{
|
||||
return ustring(s);
|
||||
}
|
||||
|
||||
|
||||
/// Convenience function to convert to a ustringhash.
|
||||
inline ustringhash
|
||||
ustringhash_from(ustringhash u)
|
||||
{
|
||||
return u;
|
||||
}
|
||||
|
||||
/// Convenience function to convert to a ustringhash.
|
||||
inline ustringhash
|
||||
ustringhash_from(ustring u)
|
||||
{
|
||||
return u.uhash();
|
||||
}
|
||||
|
||||
|
||||
/// Convenience function to convert to a ustringrep.
|
||||
inline ustringrep
|
||||
ustringrep_from(ustringhash h)
|
||||
{
|
||||
#if OSL_USTRINGREP_IS_HASH
|
||||
return h;
|
||||
#else
|
||||
return ustring::from_hash(h.hash());
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Convenience function to convert to a ustringrep.
|
||||
inline ustringrep
|
||||
ustringrep_from(ustring u)
|
||||
{
|
||||
#if OSL_USTRINGREP_IS_HASH
|
||||
return u.hash();
|
||||
#else
|
||||
return u;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Convenience function to convert to a ustringrep.
|
||||
inline ustringrep
|
||||
ustringrep_from(string_view s)
|
||||
{
|
||||
ustring u(s);
|
||||
#if OSL_USTRINGREP_IS_HASH
|
||||
return u.hash();
|
||||
#else
|
||||
return u;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
// N.B. SymArena is not really "configuration", but we cram it here for
|
||||
// lack of a better home.
|
||||
|
||||
@@ -143,6 +241,7 @@ enum class SymArena {
|
||||
Heap, // Belongs to context heap
|
||||
Outputs, // Belongs to output arena
|
||||
UserData, // UserData arena
|
||||
Interactive, // Interactively edited variables
|
||||
// ShaderGlobals, // RESERVED
|
||||
};
|
||||
|
||||
@@ -225,3 +324,50 @@ 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.
|
||||
// This can be removed once OIIO minimum is 2.4.5+ or >=2.5.0.1
|
||||
template<> struct hash<OSL::ustring> {
|
||||
std::size_t operator()(OSL::ustring u) const noexcept { return u.hash(); }
|
||||
};
|
||||
|
||||
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.
|
||||
// This can be removed once OIIO minimum is 2.4.5+ or >=2.5.0.1
|
||||
template<> struct less<OSL::ustringhash> {
|
||||
OSL_HOSTDEVICE constexpr bool operator()(OSL::ustringhash u,
|
||||
OSL::ustringhash v) const noexcept
|
||||
{
|
||||
return u.hash() < v.hash();
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
|
||||
#ifndef OIIO_HAS_USTRINGHASH_FORMATTER
|
||||
// OIIO is too old to have fmt custom formatter for ustringhash.
|
||||
// This can be removed once OIIO minimum is 2.4.5+ or >=2.5.0.1
|
||||
FMT_BEGIN_NAMESPACE
|
||||
template<> struct formatter<OIIO::ustringhash> : formatter<fmt::string_view, char> {
|
||||
template<typename FormatContext>
|
||||
auto format(const OIIO::ustringhash& h, FormatContext& ctx)
|
||||
-> decltype(ctx.out()) const
|
||||
{
|
||||
OIIO::ustring u(h);
|
||||
return formatter<fmt::string_view, char>::format({ u.data(), u.size() },
|
||||
ctx);
|
||||
}
|
||||
};
|
||||
FMT_END_NAMESPACE
|
||||
#endif
|
||||
|
||||
+143
-23
@@ -50,7 +50,7 @@ namespace pvt {
|
||||
class ShadingSystemImpl;
|
||||
}
|
||||
|
||||
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
|
||||
#ifdef __CUDA_ARCH__
|
||||
# define STRING_PARAMS(x) UStringHash::Hash(__OSL_STRINGIFY(x))
|
||||
#else
|
||||
# define STRING_PARAMS(x) StringParams::x
|
||||
@@ -58,11 +58,7 @@ class ShadingSystemImpl;
|
||||
|
||||
namespace Strings {
|
||||
#ifdef __CUDA_ARCH__
|
||||
# if OPTIX_VERSION >= 70000
|
||||
# define STRDECL(str, var_name)
|
||||
# else
|
||||
# define STRDECL(str, var_name) extern __device__ ustring var_name;
|
||||
# endif
|
||||
# define STRDECL(str, var_name)
|
||||
#else
|
||||
// Any strings referenced inside of a libsoslexec/wide/*.cpp
|
||||
// or liboslnoise/wide/*.cpp will need OSLEXECPUBLIC
|
||||
@@ -115,6 +111,67 @@ public:
|
||||
|
||||
|
||||
|
||||
/// Parameter property hint bitflag values. The enum values must be powers of
|
||||
/// two so they can be combined with bitwise operators.
|
||||
enum class ParamHints : uint32_t {
|
||||
/// `none`: No special properties
|
||||
none = 0,
|
||||
/// `interpolated`: This parameter may be an interpolated "user data" or
|
||||
/// "geometric primitive" variable, and so may take on different values at
|
||||
/// different points on the surface or on different objects that share the
|
||||
/// same material. Any optimization of the shader should take this into
|
||||
/// account.
|
||||
interpolated = 1,
|
||||
/// `interactive`: Parameter may have its value interactively modified by
|
||||
/// subsequent ReParameter calls. Any optimization of the shader should
|
||||
/// take this into account.
|
||||
interactive = 2
|
||||
};
|
||||
|
||||
inline constexpr ParamHints
|
||||
operator|(ParamHints a, ParamHints b)
|
||||
{
|
||||
return static_cast<ParamHints>(static_cast<int>(a) | static_cast<int>(b));
|
||||
}
|
||||
|
||||
inline constexpr ParamHints
|
||||
operator&(ParamHints a, ParamHints b)
|
||||
{
|
||||
return static_cast<ParamHints>(static_cast<int>(a) & static_cast<int>(b));
|
||||
}
|
||||
|
||||
inline ParamHints&
|
||||
operator|=(ParamHints& a, ParamHints b)
|
||||
{
|
||||
a = a | b;
|
||||
return a;
|
||||
}
|
||||
|
||||
inline ParamHints&
|
||||
operator&=(ParamHints& a, ParamHints b)
|
||||
{
|
||||
a = a & b;
|
||||
return a;
|
||||
}
|
||||
|
||||
inline constexpr ParamHints
|
||||
operator~(ParamHints a)
|
||||
{
|
||||
return static_cast<ParamHints>(~static_cast<int>(a));
|
||||
}
|
||||
|
||||
inline ParamHints&
|
||||
set(ParamHints& a, ParamHints b, bool on = true)
|
||||
{
|
||||
if (on)
|
||||
a |= b;
|
||||
else
|
||||
a &= ~b;
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class OSLEXECPUBLIC ShadingSystem {
|
||||
public:
|
||||
ShadingSystem(RendererServices* renderer = NULL,
|
||||
@@ -177,7 +234,7 @@ public:
|
||||
/// int lazyerror Run layers lazily even if they have error
|
||||
/// ops after optimization (1).
|
||||
/// int lazy_userdata Retrieve userdata lazily (0).
|
||||
/// int userdata_isconnected Should lockgeom=0 params (that may
|
||||
/// int userdata_isconnected Should interpolated=1 params (that may
|
||||
/// receive userdata) return true from
|
||||
/// isconnected()? (0)
|
||||
/// int greedyjit Optimize and compile all shaders up front,
|
||||
@@ -204,6 +261,7 @@ public:
|
||||
/// that don't specify it (1). Lockgeom
|
||||
/// means a param CANNOT be overridden by
|
||||
/// interpolated geometric parameters.
|
||||
/// This option is slated for deprecation.
|
||||
/// int countlayerexecs Add extra code to count total layers run.
|
||||
/// int allow_shader_replacement Allow shader to be specified more than
|
||||
/// once, replacing former definition.
|
||||
@@ -235,8 +293,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
|
||||
@@ -432,12 +489,15 @@ public:
|
||||
/// ptr attributes_needed Retrieves a pointer to the ustring array
|
||||
/// containing the names of the needed attributes.
|
||||
/// Note that if the same attribute
|
||||
/// is requested in multiple scopes, it will
|
||||
/// is requested in multiple scopes, or with
|
||||
/// multiple different types, it will
|
||||
/// appear in the array multiple times - once for
|
||||
/// each scope in which is is queried.
|
||||
/// each scope/type in which is is queried.
|
||||
/// ptr attribute_scopes Retrieves a pointer to a ustring array containing
|
||||
/// the scopes associated with each attribute query
|
||||
/// in the attributes_needed array.
|
||||
/// ptr attribute_types Retrieves a pointer to the array of
|
||||
/// TypeDesc describing the attributes.
|
||||
/// int unknown_attributes_needed Nonzero if additional attributes may be
|
||||
/// needed, whose names will not be known
|
||||
/// until the shader actually runs.
|
||||
@@ -448,6 +508,15 @@ public:
|
||||
/// string entry_layers[] List of entry point layers.
|
||||
/// string pickle Retrieves a serialized representation
|
||||
/// of the shader group declaration.
|
||||
/// int llvm_groupdata_size Size of the GroupData struct.
|
||||
/// ptr interactive_params Pointer to the memory block containing
|
||||
/// host-side interactive parameter values
|
||||
/// for this shader group.
|
||||
/// ptr device_interactive_params
|
||||
/// Pointer to the memory block containing
|
||||
/// device-side interactive parameter values
|
||||
/// for this shader group.
|
||||
///
|
||||
/// Note: the attributes referred to as "string" are actually on the app
|
||||
/// side as ustring or const char* (they have the same data layout), NOT
|
||||
/// std::string!
|
||||
@@ -535,15 +604,50 @@ public:
|
||||
bool ShaderGroupEnd(ShaderGroup& group);
|
||||
|
||||
/// Set a parameter of the next shader that will be added to the group,
|
||||
/// optionally setting the 'lockgeom' metadata for that parameter
|
||||
/// (despite how it may have been set in the shader). If lockgeom is
|
||||
/// false, it means that this parameter should NOT be considered locked
|
||||
/// against changes by the geometry, and therefore the shader should not
|
||||
/// optimize assuming that the instance value (the 'val' specified by
|
||||
/// this call) is a constant.
|
||||
/// optionally setting or overriding properties with the `hints` argument.
|
||||
/// Individual `hints` bits are defined and documented by the ParamHints
|
||||
/// enum class.
|
||||
bool Parameter(ShaderGroup& group, string_view name, TypeDesc t,
|
||||
const void* val, bool lockgeom = true);
|
||||
const void* val, ParamHints hints = ParamHints::none);
|
||||
|
||||
/// DEPRECATED(1.13) Parameter() call: instead of a full ParamHints
|
||||
/// argument, there is just a bool `lockgeom` that default to true, and
|
||||
/// when set to false is the same thing as setting
|
||||
/// `ParamHints::interpolated`.
|
||||
bool Parameter(ShaderGroup& group, string_view name, TypeDesc t,
|
||||
const void* val, bool lockgeom)
|
||||
{
|
||||
return Parameter(group, name, t, val,
|
||||
lockgeom ? ParamHints::none
|
||||
: ParamHints::interpolated);
|
||||
}
|
||||
|
||||
// Shortcuts for param passing a single int, float, or string.
|
||||
bool Parameter(ShaderGroup& group, string_view name, int val,
|
||||
ParamHints hints = ParamHints::none)
|
||||
{
|
||||
return Parameter(group, name, TypeDesc::INT, &val, hints);
|
||||
}
|
||||
bool Parameter(ShaderGroup& group, string_view name, float val,
|
||||
ParamHints hints = ParamHints::none)
|
||||
{
|
||||
return Parameter(group, name, TypeDesc::FLOAT, &val, hints);
|
||||
}
|
||||
bool Parameter(ShaderGroup& group, string_view name, const std::string& val,
|
||||
ParamHints hints = ParamHints::none)
|
||||
{
|
||||
const char* s = val.c_str();
|
||||
return Parameter(group, name, TypeDesc::STRING, &s, hints);
|
||||
}
|
||||
bool Parameter(ShaderGroup& group, string_view name, ustring val,
|
||||
ParamHints hints = ParamHints::none)
|
||||
{
|
||||
return Parameter(group, name, TypeDesc::STRING, (const char**)&val,
|
||||
hints);
|
||||
}
|
||||
|
||||
// DEPRECATED(1.13): use the version above that takes ParamHints.
|
||||
// This is the old version that takes `bool lockgeom`.
|
||||
bool Parameter(ShaderGroup& group, string_view name, int val,
|
||||
bool lockgeom = true)
|
||||
{
|
||||
@@ -594,10 +698,8 @@ public:
|
||||
/// Replace a parameter value in a previously-declared shader group.
|
||||
/// This is meant to called after the ShaderGroupBegin/End, but will
|
||||
/// fail if the shader has already been irrevocably optimized/compiled,
|
||||
/// unless the particular parameter is marked as lockgeom=0 (which
|
||||
/// indicates that it's a parameter that may be overridden by the
|
||||
/// geometric primitive). This call gives you a way of changing the
|
||||
/// instance value, even if it's not a geometric override.
|
||||
/// unless the particular parameter is marked as either interpolated=1
|
||||
/// or interactive=1.
|
||||
bool ReParameter(ShaderGroup& group, string_view layername,
|
||||
string_view paramname, TypeDesc type, const void* val);
|
||||
// Shortcuts for param passing a single int, float, or string.
|
||||
@@ -633,13 +735,22 @@ public:
|
||||
// above that take an explicit `ShaderGroup&`, which are thread-safe
|
||||
// and re-entrant.
|
||||
bool Parameter(string_view name, TypeDesc t, const void* val,
|
||||
bool lockgeom = true);
|
||||
ParamHints hints = ParamHints::none);
|
||||
bool Shader(string_view shaderusage, string_view shadername,
|
||||
string_view layername);
|
||||
bool ConnectShaders(string_view srclayer, string_view srcparam,
|
||||
string_view dstlayer, string_view dstparam);
|
||||
bool ShaderGroupEnd(void);
|
||||
|
||||
// DEPRECATED(1.13): use the version above that takes ParamHints.
|
||||
// This is the old version that takes `bool lockgeom`.
|
||||
bool Parameter(string_view name, TypeDesc t, const void* val, bool lockgeom)
|
||||
{
|
||||
return Parameter(name, t, val,
|
||||
lockgeom ? ParamHints::none
|
||||
: ParamHints::interpolated);
|
||||
}
|
||||
|
||||
/// Create a per-thread data needed for shader execution. It's very
|
||||
/// important for the app to never use a PerThreadInfo from more than
|
||||
/// one thread (and probably a good idea allocate only one PerThreadInfo
|
||||
@@ -677,6 +788,15 @@ public:
|
||||
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)
|
||||
|
||||
+318
-311
File diff suppressed because it is too large
Load Diff
@@ -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)")
|
||||
|
||||
@@ -18,10 +18,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#include <OSL/oslversion.h>
|
||||
|
||||
#if defined(__x86_64__) && !defined(__CUDA_ARCH__)
|
||||
# include <x86intrin.h>
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Detect which compiler and version we're using
|
||||
@@ -482,15 +486,77 @@
|
||||
# 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
|
||||
|
||||
|
||||
/// Standards-compliant bit cast of two equally sized types. This is used
|
||||
/// equivalently to C++20 std::bit_cast, but it works prior to C++20 and
|
||||
/// it has the right decorators to work with Cuda.
|
||||
/// @version 1.13.2
|
||||
template <typename To, typename From>
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE To bitcast(const From& src) noexcept {
|
||||
// NOTE: this is the only standards compliant way of doing this type of casting,
|
||||
// luckily the compilers we care about know how to optimize away this idiom.
|
||||
static_assert(sizeof(From) == sizeof(To),
|
||||
"bit_cast must be between objects of the same size");
|
||||
To dst;
|
||||
memcpy((void*)&dst, &src, sizeof(From));
|
||||
return dst;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__) && !defined(__CUDA_ARCH__) && \
|
||||
(defined(__INTEL_COMPILER) || defined(__INTEL_LLVM_COMPILER) \
|
||||
|| OSL_CLANG_VERSION >= 100000 || OSL_APPLE_CLANG_VERSION >= 130000)
|
||||
// On x86/x86_64 for certain compilers we can use Intel CPU intrinsics for
|
||||
// some common bitcast cases that might be even more understandable to the
|
||||
// compiler and generate better code without its getting confused about the
|
||||
// memcpy in the general case. We're a bit conservative with the compiler
|
||||
// version checks here, it may be that some earlier versions support these
|
||||
// intrinsics.
|
||||
|
||||
template<> OSL_FORCEINLINE uint32_t bitcast<uint32_t, float>(const float& val) noexcept {
|
||||
return static_cast<uint32_t>(_castf32_u32(val));
|
||||
}
|
||||
template<> OSL_FORCEINLINE int32_t bitcast<int32_t, float>(const float& val) noexcept {
|
||||
return static_cast<int32_t>(_castf32_u32(val));
|
||||
}
|
||||
template<> OSL_FORCEINLINE float bitcast<float, uint32_t>(const uint32_t& val) noexcept {
|
||||
return _castu32_f32(val);
|
||||
}
|
||||
template<> OSL_FORCEINLINE float bitcast<float, int32_t>(const int32_t& val) noexcept {
|
||||
return _castu32_f32(val);
|
||||
}
|
||||
template<> OSL_FORCEINLINE uint64_t bitcast<uint64_t, double>(const double& val) noexcept {
|
||||
return static_cast<uint64_t>(_castf64_u64(val));
|
||||
}
|
||||
template<> OSL_FORCEINLINE int64_t bitcast<int64_t, double>(const double& val) noexcept {
|
||||
return static_cast<int64_t>(_castf64_u64(val));
|
||||
}
|
||||
template<> OSL_FORCEINLINE double bitcast<double, uint64_t>(const uint64_t& val) noexcept {
|
||||
return _castu64_f64(val);
|
||||
}
|
||||
template<> OSL_FORCEINLINE double bitcast<double, int64_t>(const int64_t& val) noexcept {
|
||||
return _castu64_f64(val);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if OSL_CPLUSPLUS_VERSION >= 20
|
||||
using std::assume_aligned;
|
||||
#else
|
||||
|
||||
+150
-133
@@ -2,8 +2,6 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
// clang-format off
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
@@ -13,14 +11,13 @@
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
class RendererServices;
|
||||
template<int WidthT>
|
||||
class BatchedRendererServices;
|
||||
template<int WidthT> class BatchedRendererServices;
|
||||
class ShadingContext;
|
||||
struct ShaderGlobals;
|
||||
|
||||
// Tags for polymorphic dispatch
|
||||
template <int SimdWidthT>
|
||||
class WidthOf {};
|
||||
template<int SimdWidthT> class WidthOf {
|
||||
};
|
||||
|
||||
|
||||
/// Opaque pointer to whatever the renderer uses to represent a
|
||||
@@ -49,7 +46,7 @@ public:
|
||||
|
||||
|
||||
RendererServices(TextureSystem* texsys = NULL);
|
||||
virtual ~RendererServices () { }
|
||||
virtual ~RendererServices() {}
|
||||
|
||||
/// Given the name of a 'feature', return whether this RendererServices
|
||||
/// supports it. Feature names include:
|
||||
@@ -62,28 +59,34 @@ public:
|
||||
/// support it, as long as the OSL runtime only uses that feature if the
|
||||
/// supports("feature") says it's present, thus preserving source
|
||||
/// compatibility.
|
||||
virtual int supports (string_view feature) const { return false; }
|
||||
virtual int supports(string_view feature) const { return false; }
|
||||
|
||||
/// Get the 4x4 matrix that transforms by the specified
|
||||
/// transformation at the given time. Return true if ok, false
|
||||
/// on error.
|
||||
virtual bool get_matrix (ShaderGlobals *sg, Matrix44 &result,
|
||||
TransformationPtr xform, float time) { return false; }
|
||||
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result,
|
||||
TransformationPtr xform, float time)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Get the 4x4 matrix that transforms by the specified
|
||||
/// transformation at the given time. Return true if ok, false on
|
||||
/// error. The default implementation is to use get_matrix and
|
||||
/// invert it, but a particular renderer may have a better technique
|
||||
/// and overload the implementation.
|
||||
virtual bool get_inverse_matrix (ShaderGlobals *sg, Matrix44 &result,
|
||||
TransformationPtr xform, float time);
|
||||
virtual bool get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
|
||||
TransformationPtr xform, float time);
|
||||
|
||||
/// Get the 4x4 matrix that transforms by the specified
|
||||
/// transformation. Return true if ok, false on error. Since no
|
||||
/// time value is given, also return false if the transformation may
|
||||
/// be time-varying.
|
||||
virtual bool get_matrix (ShaderGlobals *sg, Matrix44 &result,
|
||||
TransformationPtr xform) { return false; }
|
||||
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result,
|
||||
TransformationPtr xform)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Get the 4x4 matrix that transforms by the specified
|
||||
/// transformation. Return true if ok, false on error. Since no
|
||||
@@ -91,29 +94,29 @@ public:
|
||||
/// be time-varying. The default implementation is to use
|
||||
/// get_matrix and invert it, but a particular renderer may have a
|
||||
/// better technique and overload the implementation.
|
||||
virtual bool get_inverse_matrix (ShaderGlobals *sg, Matrix44 &result,
|
||||
TransformationPtr xform);
|
||||
virtual bool get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
|
||||
TransformationPtr xform);
|
||||
|
||||
/// Get the 4x4 matrix that transforms points from the named
|
||||
/// 'from' coordinate system to "common" space at the given time.
|
||||
/// Returns true if ok, false if the named matrix is not known.
|
||||
virtual bool get_matrix (ShaderGlobals *sg, Matrix44 &result,
|
||||
ustring from, float time) { return false; }
|
||||
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result,
|
||||
ustringhash from, float time);
|
||||
|
||||
/// Get the 4x4 matrix that transforms points from "common" space to
|
||||
/// the named 'to' coordinate system to at the given time. The
|
||||
/// default implementation is to use get_matrix and invert it, but a
|
||||
/// particular renderer may have a better technique and overload the
|
||||
/// implementation.
|
||||
virtual bool get_inverse_matrix (ShaderGlobals *sg, Matrix44 &result,
|
||||
ustring to, float time);
|
||||
virtual bool get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
|
||||
ustringhash to, float time);
|
||||
|
||||
/// Get the 4x4 matrix that transforms 'from' to "common" space.
|
||||
/// Since there is no time value passed, return false if the
|
||||
/// transformation may be time-varying (as well as if it's not found
|
||||
/// at all).
|
||||
virtual bool get_matrix (ShaderGlobals *sg, Matrix44 &result,
|
||||
ustring from) { return false; }
|
||||
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result,
|
||||
ustringhash from);
|
||||
|
||||
/// Get the 4x4 matrix that transforms points from "common" space to
|
||||
/// the named 'to' coordinate system. Since there is no time value
|
||||
@@ -122,8 +125,8 @@ public:
|
||||
/// implementation is to use get_matrix and invert it, but a
|
||||
/// particular renderer may have a better technique and overload the
|
||||
/// implementation.
|
||||
virtual bool get_inverse_matrix (ShaderGlobals *sg, Matrix44 &result,
|
||||
ustring to);
|
||||
virtual bool get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
|
||||
ustringhash to);
|
||||
|
||||
/// Transform points Pin[0..npoints-1] in named coordinate system
|
||||
/// 'from' into 'to' coordinates, storing the result in Pout[] using
|
||||
@@ -148,11 +151,10 @@ public:
|
||||
/// Note to RendererServices implementations: just return 'false'
|
||||
/// if there isn't a special nonlinear transformation between the
|
||||
/// two spaces.
|
||||
virtual bool transform_points (ShaderGlobals *sg,
|
||||
ustring from, ustring to, float time,
|
||||
const Vec3 *Pin, Vec3 *Pout, int npoints,
|
||||
TypeDesc::VECSEMANTICS vectype)
|
||||
{ return false; }
|
||||
virtual bool transform_points(ShaderGlobals* sg, ustringhash from,
|
||||
ustringhash to, float time, const Vec3* Pin,
|
||||
Vec3* Pout, int npoints,
|
||||
TypeDesc::VECSEMANTICS vectype);
|
||||
|
||||
|
||||
/// Get the named attribute from the renderer and if found then
|
||||
@@ -167,36 +169,39 @@ public:
|
||||
/// run on. Be robust to this situation, return 'true' (retrieve the
|
||||
/// attribute) if you can (known object and attribute name), but
|
||||
/// otherwise just fail by returning 'false'.
|
||||
virtual bool get_attribute (ShaderGlobals *sg, bool derivatives,
|
||||
ustring object, TypeDesc type, ustring name,
|
||||
void *val) { return false; }
|
||||
virtual bool get_attribute(ShaderGlobals* sg, bool derivatives,
|
||||
ustringhash object, TypeDesc type,
|
||||
ustringhash name, void* val);
|
||||
|
||||
/// Similar to get_attribute(); this method will return the 'index'
|
||||
/// element of an attribute array.
|
||||
virtual bool get_array_attribute (ShaderGlobals *sg, bool derivatives,
|
||||
ustring object, TypeDesc type,
|
||||
ustring name, int index, void *val) { return false; }
|
||||
virtual bool get_array_attribute(ShaderGlobals* sg, bool derivatives,
|
||||
ustringhash object, TypeDesc type,
|
||||
ustringhash name, int index, void* val);
|
||||
|
||||
/// Get the named user-data from the current object and write it into
|
||||
/// 'val'. If derivatives is true, the derivatives should be written into val
|
||||
/// as well. Return false if no user-data with the given name and type was
|
||||
/// found.
|
||||
virtual bool get_userdata (bool derivatives, ustring name, TypeDesc type,
|
||||
ShaderGlobals *sg, void *val) { return false; }
|
||||
virtual bool get_userdata(bool derivatives, ustringhash name, TypeDesc type,
|
||||
ShaderGlobals* sg, void* val);
|
||||
|
||||
/// Given the name of a texture, return an opaque handle that can be
|
||||
/// used with texture calls to avoid the name lookups.
|
||||
virtual TextureHandle * get_texture_handle (ustring filename,
|
||||
ShadingContext *context);
|
||||
/// Given the name of a texture, return an opaque handle that can be used
|
||||
/// with texture calls to avoid the name lookups. The `options`, if not
|
||||
/// null, may be used in renderer-specific ways to specialize a handle
|
||||
/// based on certain texture option choices.
|
||||
virtual TextureHandle*
|
||||
get_texture_handle(ustringhash filename, ShadingContext* context,
|
||||
const TextureOpt* options = nullptr);
|
||||
|
||||
/// Return true if the texture handle (previously returned by
|
||||
/// get_texture_handle()) is a valid texture that can be subsequently
|
||||
/// read or sampled.
|
||||
virtual bool good (TextureHandle *texture_handle);
|
||||
virtual bool good(TextureHandle* texture_handle);
|
||||
|
||||
/// Return true if the texture handle (previously returned by
|
||||
/// get_texture_handle()) is udim
|
||||
virtual bool is_udim (TextureHandle *texture_handle);
|
||||
virtual bool is_udim(TextureHandle* texture_handle);
|
||||
|
||||
/// Filtered 2D texture lookup for a single point.
|
||||
///
|
||||
@@ -224,13 +229,13 @@ public:
|
||||
/// messages (in case of failure, when the function returns false) will
|
||||
/// be stored there, leaving it up to the caller/shader to handle the
|
||||
/// error.
|
||||
virtual bool texture (ustring filename, TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
TextureOpt &options, ShaderGlobals *sg,
|
||||
float s, float t, float dsdx, float dtdx,
|
||||
float dsdy, float dtdy, int nchannels,
|
||||
float *result, float *dresultds, float *dresultdt,
|
||||
ustring *errormessage);
|
||||
virtual bool texture(ustringhash filename, TextureHandle* texture_handle,
|
||||
TexturePerthread* texture_thread_info,
|
||||
TextureOpt& options, ShaderGlobals* sg, float s,
|
||||
float t, float dsdx, float dtdx, float dsdy,
|
||||
float dtdy, int nchannels, float* result,
|
||||
float* dresultds, float* dresultdt,
|
||||
ustringhash* errormessage);
|
||||
|
||||
/// Filtered 3D texture lookup for a single point.
|
||||
///
|
||||
@@ -257,14 +262,13 @@ public:
|
||||
/// messages (in case of failure, when the function returns false) will
|
||||
/// be stored there, leaving it up to the caller/shader to handle the
|
||||
/// error.
|
||||
virtual bool texture3d (ustring filename, TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
TextureOpt &options, ShaderGlobals *sg,
|
||||
const Vec3 &P, const Vec3 &dPdx, const Vec3 &dPdy,
|
||||
const Vec3 &dPdz, int nchannels,
|
||||
float *result, float *dresultds,
|
||||
float *dresultdt, float *dresultdr,
|
||||
ustring *errormessage);
|
||||
virtual bool texture3d(ustringhash filename, TextureHandle* texture_handle,
|
||||
TexturePerthread* texture_thread_info,
|
||||
TextureOpt& options, ShaderGlobals* sg,
|
||||
const Vec3& P, const Vec3& dPdx, const Vec3& dPdy,
|
||||
const Vec3& dPdz, int nchannels, float* result,
|
||||
float* dresultds, float* dresultdt, float* dresultdr,
|
||||
ustringhash* errormessage);
|
||||
|
||||
/// Filtered environment lookup for a single point.
|
||||
///
|
||||
@@ -288,13 +292,13 @@ public:
|
||||
/// messages (in case of failure, when the function returns false) will
|
||||
/// be stored there, leaving it up to the caller/shader to handle the
|
||||
/// error.
|
||||
virtual bool environment (ustring filename, TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
TextureOpt &options, ShaderGlobals *sg,
|
||||
const Vec3 &R, const Vec3 &dRdx, const Vec3 &dRdy,
|
||||
int nchannels, float *result,
|
||||
float *dresultds, float *dresultdt,
|
||||
ustring *errormessage);
|
||||
virtual bool environment(ustringhash filename,
|
||||
TextureHandle* texture_handle,
|
||||
TexturePerthread* texture_thread_info,
|
||||
TextureOpt& options, ShaderGlobals* sg,
|
||||
const Vec3& R, const Vec3& dRdx, const Vec3& dRdy,
|
||||
int nchannels, float* result, float* dresultds,
|
||||
float* dresultdt, ustringhash* errormessage);
|
||||
|
||||
/// Get information about the given texture. Return true if found
|
||||
/// and the data has been put in *data. Return false if the texture
|
||||
@@ -315,24 +319,20 @@ public:
|
||||
/// messages (in case of failure, when the function returns false) will
|
||||
/// be stored there, leaving it up to the caller/shader to handle the
|
||||
/// error.
|
||||
virtual bool get_texture_info (ustring filename,
|
||||
TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
ShadingContext *shading_context,
|
||||
int subimage,
|
||||
ustring dataname, TypeDesc datatype,
|
||||
void *data,
|
||||
ustring *errormessage);
|
||||
virtual bool get_texture_info(ustringhash filename,
|
||||
TextureHandle* texture_handle,
|
||||
TexturePerthread* texture_thread_info,
|
||||
ShadingContext* shading_context, int subimage,
|
||||
ustringhash dataname, TypeDesc datatype,
|
||||
void* data, ustringhash* errormessage);
|
||||
|
||||
virtual bool get_texture_info (ustring filename,
|
||||
TextureHandle *texture_handle,
|
||||
float s, float t,
|
||||
TexturePerthread *texture_thread_info,
|
||||
ShadingContext *shading_context,
|
||||
int subimage,
|
||||
ustring dataname, TypeDesc datatype,
|
||||
void *data,
|
||||
ustring *errormessage);
|
||||
virtual bool get_texture_info(ustringhash filename,
|
||||
TextureHandle* texture_handle, float s,
|
||||
float t,
|
||||
TexturePerthread* texture_thread_info,
|
||||
ShadingContext* shading_context, int subimage,
|
||||
ustringhash dataname, TypeDesc datatype,
|
||||
void* data, ustringhash* errormessage);
|
||||
|
||||
|
||||
/// Lookup nearest points in a point cloud. It will search for
|
||||
@@ -343,40 +343,38 @@ public:
|
||||
/// derivatives will be computed for distances (when provided).
|
||||
///
|
||||
/// Return the number of points found, always < max_points
|
||||
virtual int pointcloud_search (ShaderGlobals *sg,
|
||||
ustring filename, const OSL::Vec3 ¢er,
|
||||
float radius, int max_points, bool sort,
|
||||
size_t *out_indices,
|
||||
float *out_distances, int derivs_offset);
|
||||
virtual int pointcloud_search(ShaderGlobals* sg, ustringhash filename,
|
||||
const OSL::Vec3& center, float radius,
|
||||
int max_points, bool sort,
|
||||
size_t* out_indices, float* out_distances,
|
||||
int derivs_offset);
|
||||
|
||||
/// Retrieve an attribute for an index list. The result is another array
|
||||
/// of the requested type stored in out_data.
|
||||
///
|
||||
/// Return 1 if the attribute is found, 0 otherwise.
|
||||
virtual int pointcloud_get (ShaderGlobals *sg,
|
||||
ustring filename, size_t *indices, int count,
|
||||
ustring attr_name, TypeDesc attr_type,
|
||||
void *out_data);
|
||||
virtual int pointcloud_get(ShaderGlobals* sg, ustringhash filename,
|
||||
size_t* indices, int count,
|
||||
ustringhash attr_name, TypeDesc attr_type,
|
||||
void* out_data);
|
||||
|
||||
/// Write a point to the named pointcloud, which will be saved
|
||||
/// at the end of the frame. Return true if everything is ok,
|
||||
/// false if there was an error.
|
||||
virtual bool pointcloud_write (ShaderGlobals *sg,
|
||||
ustring filename, const OSL::Vec3 &pos,
|
||||
int nattribs, const ustring *names,
|
||||
const TypeDesc *types,
|
||||
const void **data);
|
||||
virtual bool pointcloud_write(ShaderGlobals* sg, ustringhash filename,
|
||||
const OSL::Vec3& pos, int nattribs,
|
||||
const ustringrep* names,
|
||||
const TypeDesc* types, const void** data);
|
||||
|
||||
/// Options for the trace call.
|
||||
struct TraceOpt {
|
||||
float mindist; ///< ignore hits closer than this
|
||||
float maxdist; ///< ignore hits farther than this
|
||||
bool shade; ///< whether to shade what is hit
|
||||
ustring traceset; ///< named trace set
|
||||
TraceOpt () : mindist(0.0f), maxdist(1.0e30), shade(false) { }
|
||||
float mindist; ///< ignore hits closer than this
|
||||
float maxdist; ///< ignore hits farther than this
|
||||
bool shade; ///< whether to shade what is hit
|
||||
ustringrep traceset; ///< named trace set
|
||||
TraceOpt() : mindist(0.0f), maxdist(1.0e30), shade(false) {}
|
||||
|
||||
enum class LLVMMemberIndex
|
||||
{
|
||||
enum class LLVMMemberIndex {
|
||||
mindist = 0,
|
||||
maxdist,
|
||||
shade,
|
||||
@@ -387,47 +385,60 @@ public:
|
||||
|
||||
/// Immediately trace a ray from P in the direction R. Return true
|
||||
/// if anything hit, otherwise false.
|
||||
virtual bool trace (TraceOpt &options, ShaderGlobals *sg,
|
||||
const OSL::Vec3 &P, const OSL::Vec3 &dPdx,
|
||||
const OSL::Vec3 &dPdy, const OSL::Vec3 &R,
|
||||
const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy) {
|
||||
return false;
|
||||
}
|
||||
virtual bool trace(TraceOpt& options, ShaderGlobals* sg, const OSL::Vec3& P,
|
||||
const OSL::Vec3& dPdx, const OSL::Vec3& dPdy,
|
||||
const OSL::Vec3& R, const OSL::Vec3& dRdx,
|
||||
const OSL::Vec3& dRdy);
|
||||
|
||||
/// Get the named message from the renderer and if found then
|
||||
/// write it into 'val'. Otherwise, return false. This is only
|
||||
/// called for "sourced" messages, not ordinary intra-group messages.
|
||||
virtual bool getmessage (ShaderGlobals *sg, ustring source, ustring name,
|
||||
TypeDesc type, void *val, bool derivatives) {
|
||||
return false;
|
||||
}
|
||||
virtual bool getmessage(ShaderGlobals* sg, ustringhash source,
|
||||
ustringhash name, TypeDesc type, void* val,
|
||||
bool derivatives);
|
||||
|
||||
/// Return a pointer to the texture system (if available).
|
||||
virtual TextureSystem *texturesys () const;
|
||||
virtual TextureSystem* texturesys() const;
|
||||
|
||||
/// 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)
|
||||
/// Allocate `size` bytes of memory on the device that will execute the
|
||||
/// shaders. (Equivalent to malloc() on the CPU.)
|
||||
virtual void* device_alloc(size_t size)
|
||||
{
|
||||
return 0;
|
||||
return nullptr;
|
||||
// Note: for an OptiX-based renderer, this method should be overriden
|
||||
// with something like:
|
||||
//
|
||||
// void* dptr;
|
||||
// auto r = cudaMalloc(&dptr, size);
|
||||
// return r == cudaSuccess ? dptr : nullptr;
|
||||
}
|
||||
|
||||
virtual uint64_t register_global (const std::string& var_name,
|
||||
uint64_t value)
|
||||
/// Free a previous allocation (by `device_alloc()`) on the device that
|
||||
/// will execute the shaders. (Equivalent to free() on the CPU.)
|
||||
virtual void device_free(void* ptr)
|
||||
{
|
||||
return 0;
|
||||
// Note: for an OptiX-based renderer, this method should be overriden
|
||||
// with something like:
|
||||
//
|
||||
// cudaFree(ptr);
|
||||
}
|
||||
|
||||
virtual bool fetch_global (const std::string& var_name,
|
||||
uint64_t* value)
|
||||
/// Copy `size` bytes from location `src_host` on the host/CPU (the
|
||||
/// machine making this call) into location `dst_device` on the device
|
||||
/// executing shaders. (Equivalent to `memcpy(dst, src, size)` on the
|
||||
/// CPU.)
|
||||
virtual void* copy_to_device(void* dst_device, const void* src_host,
|
||||
size_t size)
|
||||
{
|
||||
return false;
|
||||
return nullptr;
|
||||
// Note: for an OptiX-based renderer, this method should be overriden
|
||||
// with something like:
|
||||
//
|
||||
// auto r = cudaMemcpy(dst_device, src_host, size,
|
||||
// cudaMemcpyHostToDevice);
|
||||
// return dst_device;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Options we use for noise calls.
|
||||
struct NoiseOpt {
|
||||
int anisotropic;
|
||||
@@ -435,19 +446,25 @@ public:
|
||||
Vec3 direction;
|
||||
float bandwidth;
|
||||
float impulses;
|
||||
NoiseOpt () : anisotropic(0), do_filter(true),
|
||||
direction(1.0f,0.0f,0.0f), bandwidth(1.0f), impulses(16.0f) { }
|
||||
NoiseOpt()
|
||||
: anisotropic(0)
|
||||
, do_filter(true)
|
||||
, direction(1.0f, 0.0f, 0.0f)
|
||||
, bandwidth(1.0f)
|
||||
, impulses(16.0f)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/// A renderer may choose to support batched execution by providing pointers
|
||||
/// to objects satisfying the BatchedRendererServices<WidthOf<#>> interface
|
||||
/// for specific batch sizes.
|
||||
/// Unless overridden, a nullptr is returned.
|
||||
virtual BatchedRendererServices<16> * batched(WidthOf<16>);
|
||||
virtual BatchedRendererServices<8> * batched(WidthOf<8>);
|
||||
virtual BatchedRendererServices<16>* batched(WidthOf<16>);
|
||||
virtual BatchedRendererServices<8>* batched(WidthOf<8>);
|
||||
|
||||
protected:
|
||||
TextureSystem *m_texturesys; // A place to hold a TextureSystem
|
||||
TextureSystem* m_texturesys; // A place to hold a TextureSystem
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
+123
-26
@@ -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>
|
||||
@@ -895,6 +895,8 @@ template<int WidthT> struct alignas(VecReg<WidthT>) Block<Matrix44, WidthT> {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Specialization of Block for ustring
|
||||
template<int WidthT> struct alignas(VecReg<WidthT>) Block<ustring, WidthT> {
|
||||
static constexpr int width = WidthT;
|
||||
typedef ustring ValueType;
|
||||
@@ -942,6 +944,58 @@ template<int WidthT> struct alignas(VecReg<WidthT>) Block<ustring, WidthT> {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Specialization of Block for ustringhash
|
||||
template<int WidthT> struct alignas(VecReg<WidthT>) Block<ustringhash, WidthT> {
|
||||
static constexpr int width = WidthT;
|
||||
typedef ustringhash ValueType;
|
||||
|
||||
// To enable vectorization, use uintptr_t to store the ustringhash (const char *)
|
||||
size_t str[WidthT];
|
||||
static_assert(sizeof(ustringhash) == sizeof(size_t),
|
||||
"ustringhash must be size_t");
|
||||
|
||||
OSL_FORCEINLINE Block() = default;
|
||||
// We want to avoid accidentally copying these when the intent was to just pass a reference
|
||||
Block(const Block& other) = delete;
|
||||
|
||||
OSL_FORCEINLINE void set(int lane, const ustringhash& value)
|
||||
{
|
||||
str[lane] = value.hash();
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE void set(int lane, ustring value)
|
||||
{
|
||||
str[lane] = value.hash();
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE void set(int lane, const ustringhash& value, bool laneMask)
|
||||
{
|
||||
if (laneMask)
|
||||
str[lane] = value.hash();
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE ustringhash get(int lane) const
|
||||
{
|
||||
#ifdef OIIO_USTRING_HAS_CTR_FROM_USTRINGHASH
|
||||
return ustringhash::from_hash(str[lane]);
|
||||
#else
|
||||
return OSL::bitcast<ustringhash>(str[lane]);
|
||||
#endif
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE pvt::LaneProxy<ValueType, WidthT> operator[](int lane)
|
||||
{
|
||||
return pvt::LaneProxy<ValueType, WidthT>(*this, lane);
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE pvt::ConstLaneProxy<const ValueType, WidthT>
|
||||
operator[](int lane) const
|
||||
{
|
||||
return pvt::ConstLaneProxy<const ValueType, WidthT>(*this, lane);
|
||||
}
|
||||
};
|
||||
|
||||
template<int WidthT>
|
||||
struct alignas(VecReg<WidthT>) Block<Dual2<float>, WidthT> {
|
||||
typedef Dual2<float> ValueType;
|
||||
@@ -1535,7 +1589,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 +1599,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 +2143,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 +2182,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 +2283,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 +2353,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 +2793,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;
|
||||
@@ -2828,7 +2899,7 @@ public:
|
||||
// Populate all data lanes of the MaskedData by broadcasting the
|
||||
// single instance of data pointed to.
|
||||
// Masked off lanes are not overwritten.
|
||||
// Includes value, as well as Dx and Dy when has_derivs() is true
|
||||
// when has_derivs() is true, Dx and Dy will be zeroed
|
||||
OSL_FORCEINLINE void assign_all_from_scalar(const void* ptr_data) const;
|
||||
|
||||
|
||||
@@ -2846,6 +2917,9 @@ private:
|
||||
template<typename DataT>
|
||||
OSL_NOINLINE void assign_all_from_scalar_type(const void* ptr_data,
|
||||
int deriv_index) const;
|
||||
|
||||
template<typename DataT>
|
||||
OSL_NOINLINE void zero_all_type(int deriv_index) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -3361,6 +3435,33 @@ MaskedData<WidthT>::assign_all_from_scalar_type(const void* ptr_data,
|
||||
}
|
||||
}
|
||||
|
||||
template<int WidthT>
|
||||
template<typename DataT>
|
||||
OSL_NOINLINE void
|
||||
MaskedData<WidthT>::zero_all_type(int deriv_index) const
|
||||
{
|
||||
// We can't just do a memset because some lanes may be masked off
|
||||
// Use a SIMD loop to perform masked assignment.
|
||||
auto* dst_blocks = pvt::block_cast<DataT, WidthT>(m_ptr);
|
||||
int elem_count = static_cast<int>(m_type.numelements());
|
||||
int comp_count = m_type.aggregate;
|
||||
int deriv_offset = deriv_index * elem_count * comp_count;
|
||||
for (int array_index = 0; array_index < elem_count; ++array_index) {
|
||||
int array_offset = array_index * comp_count;
|
||||
for (int comp_index = 0; comp_index < comp_count; ++comp_index) {
|
||||
int combined_index = deriv_offset + array_offset + comp_index;
|
||||
auto& bdst = dst_blocks[combined_index];
|
||||
|
||||
Masked<DataT, WidthT> wdest(bdst, mask());
|
||||
|
||||
OSL_OMP_PRAGMA(omp simd simdlen(WidthT))
|
||||
for (int lane = 0; lane < WidthT; ++lane) {
|
||||
wdest[lane] = DataT {};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<int WidthT>
|
||||
OSL_FORCEINLINE void
|
||||
MaskedData<WidthT>::assign_all_from_scalar(const void* ptr_data) const
|
||||
@@ -3376,16 +3477,12 @@ MaskedData<WidthT>::assign_all_from_scalar(const void* ptr_data) const
|
||||
assign_all_from_scalar_type<ustring>(ptr_data, /*deriv_index*/ 0);
|
||||
}
|
||||
if (has_derivs()) {
|
||||
size_t src_size = type().size();
|
||||
const char* dx_src = reinterpret_cast<const char*>(ptr_data) + src_size;
|
||||
const char* dy_src = dx_src + src_size;
|
||||
|
||||
if (isBase32bit) {
|
||||
assign_all_from_scalar_type<int>(dx_src, /*deriv_index*/ 1);
|
||||
assign_all_from_scalar_type<int>(dy_src, /*deriv_index*/ 2);
|
||||
zero_all_type<int>(/*deriv_index*/ 1);
|
||||
zero_all_type<int>(/*deriv_index*/ 2);
|
||||
} else {
|
||||
assign_all_from_scalar_type<ustring>(dx_src, /*deriv_index*/ 1);
|
||||
assign_all_from_scalar_type<ustring>(dy_src, /*deriv_index*/ 2);
|
||||
zero_all_type<ustring>(/*deriv_index*/ 1);
|
||||
zero_all_type<ustring>(/*deriv_index*/ 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
+20
-10
@@ -5,25 +5,31 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
#include <OSL/oslversion.h>
|
||||
|
||||
#ifdef OSL_USE_OPTIX
|
||||
#if OSL_USE_OPTIX
|
||||
# include <cuda_runtime_api.h>
|
||||
# include <optix.h>
|
||||
# ifdef _WIN32
|
||||
# define NOMINMAX
|
||||
# endif
|
||||
# if (OPTIX_VERSION < 70000)
|
||||
# include <optix_world.h>
|
||||
# endif
|
||||
#else
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <OSL/device_ptr.h>
|
||||
|
||||
#if !OSL_USE_OPTIX && !defined(__CUDA_ARCH__)
|
||||
using CUdeviceptr = void*;
|
||||
using float3 = OSL::Vec3;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
#ifdef OSL_USE_OPTIX
|
||||
#if OSL_USE_OPTIX
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// If OptiX is available, alias everything in optix:: namespace into
|
||||
@@ -31,14 +37,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 +53,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."; }
|
||||
};
|
||||
|
||||
+261
-61
@@ -386,6 +386,7 @@ public:
|
||||
/// vector-like (and match their array-ness and closure-ness), or
|
||||
/// if both are structures with matching fields.
|
||||
friend bool equivalent(const TypeSpec& a, const TypeSpec& b);
|
||||
friend bool relaxed_equivalent(const TypeSpec& a, const TypeSpec& b);
|
||||
|
||||
/// Is type src is assignable to dst? It is if they are the equivalent(),
|
||||
/// or if dst is a float or float-aggregate and src is a float or int.
|
||||
@@ -477,7 +478,9 @@ public:
|
||||
, m_const_initializer(false)
|
||||
, m_connected_down(false)
|
||||
, m_initialized(false)
|
||||
, m_lockgeom(false)
|
||||
, m_interpolated(false)
|
||||
, m_interactive(false)
|
||||
, m_noninteractive(false)
|
||||
, m_allowconnect(true)
|
||||
, m_renderer_output(false)
|
||||
, m_readonly(false)
|
||||
@@ -558,7 +561,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; }
|
||||
|
||||
@@ -629,59 +632,148 @@ public:
|
||||
OSL_ASSERT(arena == SymArena::Absolute);
|
||||
m_arena = static_cast<unsigned int>(arena);
|
||||
m_data = ptr;
|
||||
// m_dataoffset = static_cast<int64_t>((char*)ptr - (char*)0);
|
||||
}
|
||||
|
||||
/// Specify the location of the symbol's data, relative to an arena
|
||||
/// (which for now must be Absolute).
|
||||
void set_dataptr(SymArena arena, void* ptr, int offset)
|
||||
{
|
||||
// OSL_ASSERT(arena == SymArena::Absolute);
|
||||
m_arena = static_cast<unsigned int>(arena);
|
||||
m_data = ptr;
|
||||
m_dataoffset = offset;
|
||||
OSL::print("setting sym {} arena {} offset {}\n", name(), int(m_arena),
|
||||
m_dataoffset);
|
||||
}
|
||||
|
||||
|
||||
void dataoffset(int d) { m_dataoffset = d; }
|
||||
int dataoffset() const { return m_dataoffset; }
|
||||
void dataoffset(int d)
|
||||
{
|
||||
m_dataoffset = d;
|
||||
}
|
||||
int dataoffset() const
|
||||
{
|
||||
return m_dataoffset;
|
||||
}
|
||||
|
||||
void wide_dataoffset(int d) { m_wide_dataoffset = d; }
|
||||
int wide_dataoffset() const { return m_wide_dataoffset; }
|
||||
void wide_dataoffset(int d)
|
||||
{
|
||||
m_wide_dataoffset = d;
|
||||
}
|
||||
int wide_dataoffset() const
|
||||
{
|
||||
return m_wide_dataoffset;
|
||||
}
|
||||
|
||||
SymArena arena() const { return static_cast<SymArena>(m_arena); }
|
||||
SymArena arena() const
|
||||
{
|
||||
return static_cast<SymArena>(m_arena);
|
||||
}
|
||||
|
||||
void initializers(int d) { m_initializers = d; }
|
||||
int initializers() const { return m_initializers; }
|
||||
void initializers(int d)
|
||||
{
|
||||
m_initializers = d;
|
||||
}
|
||||
int initializers() const
|
||||
{
|
||||
return m_initializers;
|
||||
}
|
||||
|
||||
bool has_derivs() const { return m_has_derivs; }
|
||||
void has_derivs(bool new_derivs) { m_has_derivs = new_derivs; }
|
||||
int size() const { return m_size; }
|
||||
void size(size_t newsize) { m_size = (int)newsize; }
|
||||
bool has_derivs() const
|
||||
{
|
||||
return m_has_derivs;
|
||||
}
|
||||
void has_derivs(bool new_derivs)
|
||||
{
|
||||
m_has_derivs = new_derivs;
|
||||
}
|
||||
int size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
void size(size_t newsize)
|
||||
{
|
||||
m_size = (int)newsize;
|
||||
}
|
||||
|
||||
/// Return the size for each point, including derivs.
|
||||
///
|
||||
int derivsize() const { return m_has_derivs ? 3 * m_size : m_size; }
|
||||
int derivsize() const
|
||||
{
|
||||
return m_has_derivs ? 3 * m_size : m_size;
|
||||
}
|
||||
|
||||
bool connected() const { return valuesource() == ConnectedVal; }
|
||||
bool connected_down() const { return m_connected_down; }
|
||||
void connected_down(bool c) { m_connected_down = c; }
|
||||
bool connected() const
|
||||
{
|
||||
return valuesource() == ConnectedVal;
|
||||
}
|
||||
bool connected_down() const
|
||||
{
|
||||
return m_connected_down;
|
||||
}
|
||||
void connected_down(bool c)
|
||||
{
|
||||
m_connected_down = c;
|
||||
}
|
||||
|
||||
/// Where did the symbol's value come from?
|
||||
///
|
||||
enum ValueSource { DefaultVal, InstanceVal, GeomVal, ConnectedVal };
|
||||
|
||||
ValueSource valuesource() const { return (ValueSource)m_valuesource; }
|
||||
void valuesource(ValueSource v) { m_valuesource = v; }
|
||||
ValueSource valuesource() const
|
||||
{
|
||||
return (ValueSource)m_valuesource;
|
||||
}
|
||||
void valuesource(ValueSource v)
|
||||
{
|
||||
m_valuesource = v;
|
||||
}
|
||||
const char* valuesourcename() const;
|
||||
static const char* valuesourcename(ValueSource v);
|
||||
|
||||
int fieldid() const { return m_fieldid; }
|
||||
void fieldid(int id) { m_fieldid = id; }
|
||||
int fieldid() const
|
||||
{
|
||||
return m_fieldid;
|
||||
}
|
||||
void fieldid(int id)
|
||||
{
|
||||
m_fieldid = id;
|
||||
}
|
||||
|
||||
int layer() const { return m_layer; }
|
||||
void layer(int id) { m_layer = id; }
|
||||
int layer() const
|
||||
{
|
||||
return m_layer;
|
||||
}
|
||||
void layer(int id)
|
||||
{
|
||||
m_layer = id;
|
||||
}
|
||||
|
||||
int initbegin() const { return m_initbegin; }
|
||||
void initbegin(int i) { m_initbegin = i; }
|
||||
int initend() const { return m_initend; }
|
||||
void initend(int i) { m_initend = i; }
|
||||
int initbegin() const
|
||||
{
|
||||
return m_initbegin;
|
||||
}
|
||||
void initbegin(int i)
|
||||
{
|
||||
m_initbegin = i;
|
||||
}
|
||||
int initend() const
|
||||
{
|
||||
return m_initend;
|
||||
}
|
||||
void initend(int i)
|
||||
{
|
||||
m_initend = i;
|
||||
}
|
||||
void set_initrange(int b = 0, int e = 0)
|
||||
{
|
||||
m_initbegin = b;
|
||||
m_initend = e;
|
||||
}
|
||||
bool has_init_ops() const { return m_initbegin != m_initend; }
|
||||
bool has_init_ops() const
|
||||
{
|
||||
return m_initbegin != m_initend;
|
||||
}
|
||||
|
||||
/// Clear read/write usage info.
|
||||
///
|
||||
@@ -725,15 +817,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 +873,92 @@ 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
|
||||
{
|
||||
// We can lock a value to a constant (at all places on all pieces of
|
||||
// geometry) if it is neither interpolated nor interactively modified.
|
||||
return !m_interpolated && !m_interactive;
|
||||
}
|
||||
|
||||
bool allowconnect() const { return m_allowconnect; }
|
||||
void allowconnect(bool val) { m_allowconnect = val; }
|
||||
bool interpolated() const
|
||||
{
|
||||
return m_interpolated;
|
||||
}
|
||||
void interpolated(bool val)
|
||||
{
|
||||
m_interpolated = val;
|
||||
}
|
||||
|
||||
int arraylen() const { return m_typespec.arraylength(); }
|
||||
bool interactive() const
|
||||
{
|
||||
return m_interactive;
|
||||
}
|
||||
void interactive(bool val)
|
||||
{
|
||||
m_interactive = val;
|
||||
}
|
||||
|
||||
bool noninteractive() const
|
||||
{
|
||||
return m_noninteractive;
|
||||
}
|
||||
void noninteractive(bool val)
|
||||
{
|
||||
m_noninteractive = val;
|
||||
}
|
||||
|
||||
bool allowconnect() const
|
||||
{
|
||||
return m_allowconnect;
|
||||
}
|
||||
void allowconnect(bool val)
|
||||
{
|
||||
m_allowconnect = val;
|
||||
}
|
||||
|
||||
int arraylen() const
|
||||
{
|
||||
return m_typespec.arraylength();
|
||||
}
|
||||
void arraylen(int len)
|
||||
{
|
||||
m_typespec.make_array(len);
|
||||
m_size = m_typespec.simpletype().size();
|
||||
}
|
||||
|
||||
bool renderer_output() const { return m_renderer_output; }
|
||||
void renderer_output(bool v) { m_renderer_output = v; }
|
||||
bool renderer_output() const
|
||||
{
|
||||
return m_renderer_output;
|
||||
}
|
||||
void renderer_output(bool v)
|
||||
{
|
||||
m_renderer_output = v;
|
||||
}
|
||||
|
||||
// When not uniform a symbol will have a varying value under batched
|
||||
// execution and must use a Wide data type to hold different values
|
||||
// for each data lane executing
|
||||
bool is_uniform() const { return m_is_uniform; }
|
||||
bool is_varying() const { return (m_is_uniform == 0); }
|
||||
void make_varying() { m_is_uniform = false; }
|
||||
bool is_uniform() const
|
||||
{
|
||||
return m_is_uniform;
|
||||
}
|
||||
bool is_varying() const
|
||||
{
|
||||
return (m_is_uniform == 0);
|
||||
}
|
||||
void make_varying()
|
||||
{
|
||||
m_is_uniform = false;
|
||||
}
|
||||
|
||||
// Results of a compare_op and other ops with logically boolean
|
||||
// results under certain conditions could be forced to be represented
|
||||
@@ -792,14 +972,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 +1053,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;
|
||||
@@ -869,10 +1067,12 @@ protected:
|
||||
unsigned m_symtype : 4; ///< Kind of symbol (param, local, etc.)
|
||||
unsigned m_has_derivs : 1; ///< Step to derivs (0 == has no derivs)
|
||||
unsigned m_const_initializer : 1; ///< initializer is a constant expression
|
||||
unsigned m_connected_down : 1; ///< Connected to a later/downstream layer
|
||||
unsigned m_initialized : 1; ///< If a param, has it been initialized?
|
||||
unsigned m_lockgeom : 1; ///< Is the param not overridden by geom?
|
||||
unsigned m_allowconnect : 1; ///< Is the param not overridden by geom?
|
||||
unsigned m_connected_down : 1; ///< Connected to a later/downstream layer
|
||||
unsigned m_initialized : 1; ///< If a param, has it been initialized?
|
||||
unsigned m_interpolated : 1; ///< Is the param overridden by geom?
|
||||
unsigned m_interactive : 1; ///< May the param change interactively?
|
||||
unsigned m_noninteractive : 1; ///< The param def won't modify interactively
|
||||
unsigned m_allowconnect : 1; ///< Is the param allowd to connect?
|
||||
unsigned m_renderer_output : 1; ///< Is this sym a renderer output?
|
||||
unsigned m_readonly : 1; ///< read-only symbol
|
||||
unsigned m_is_uniform : 1; ///< symbol is uniform under batched execution
|
||||
|
||||
+105
-38
@@ -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:
|
||||
@@ -578,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()) {
|
||||
@@ -1110,90 +1116,151 @@ ASTassign_expression::opword() const
|
||||
OSL_ASSERT (0 && "unknown assignment expression");
|
||||
return "assign"; // punt
|
||||
}
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
|
||||
|
||||
ASTunary_expression::ASTunary_expression (OSLCompilerImpl *comp, int op,
|
||||
ASTNode *expr)
|
||||
: ASTNode (unary_expression_node, comp, op, expr)
|
||||
ASTunary_expression::ASTunary_expression(OSLCompilerImpl* comp, int op,
|
||||
ASTNode* expr)
|
||||
: ASTNode(unary_expression_node, comp, op, expr)
|
||||
{
|
||||
// Check for a user-overloaded function for this operator
|
||||
Symbol *sym = comp->symtab().find(ustring::fmtformat("__operator__{}__", opword()));
|
||||
Symbol* sym = comp->symtab().find(
|
||||
ustring::fmtformat("__operator__{}__", opword()));
|
||||
if (sym && sym->symtype() == SymTypeFunction)
|
||||
m_function_overload = (FunctionSymbol *)sym;
|
||||
m_function_overload = (FunctionSymbol*)sym;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *
|
||||
ASTunary_expression::childname (size_t i) const
|
||||
const char*
|
||||
ASTunary_expression::childname(size_t i) const
|
||||
{
|
||||
static const char *name[] = { "expression" };
|
||||
static const char* name[] = { "expression" };
|
||||
return name[i];
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *
|
||||
ASTunary_expression::opname () const
|
||||
const char*
|
||||
ASTunary_expression::opname() const
|
||||
{
|
||||
switch (m_op) {
|
||||
case Add : return "+";
|
||||
case Sub : return "-";
|
||||
case Not : return "!";
|
||||
case Compl : return "~";
|
||||
default:
|
||||
OSL_ASSERT (0 && "unknown unary expression");
|
||||
return "unknown";
|
||||
case Add: return "+";
|
||||
case Sub: return "-";
|
||||
case Not: return "!";
|
||||
case Compl: return "~";
|
||||
default: OSL_ASSERT(0 && "unknown unary expression"); return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *
|
||||
ASTunary_expression::opword () const
|
||||
const char*
|
||||
ASTunary_expression::opword() const
|
||||
{
|
||||
switch (m_op) {
|
||||
case Add : return "add";
|
||||
case Sub : return "neg";
|
||||
case Not : return "not";
|
||||
case Compl : return "compl";
|
||||
default:
|
||||
OSL_ASSERT (0 && "unknown unary expression");
|
||||
return "unknown";
|
||||
case Add: return "add";
|
||||
case Sub: return "neg";
|
||||
case Not: return "not";
|
||||
case Compl: return "compl";
|
||||
default: OSL_ASSERT(0 && "unknown unary expression"); return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
ASTbinary_expression::ASTbinary_expression (OSLCompilerImpl *comp, Operator op,
|
||||
ASTNode *left, ASTNode *right)
|
||||
: ASTNode (binary_expression_node, comp, op, left, right)
|
||||
ASTbinary_expression::ASTbinary_expression(OSLCompilerImpl* comp, Operator op,
|
||||
ASTNode* left, ASTNode* right)
|
||||
: ASTNode(binary_expression_node, comp, op, left, right)
|
||||
{
|
||||
// Check for a user-overloaded function for this operator.
|
||||
// Disallow a few ops from overloading.
|
||||
if (op != And && op != Or) {
|
||||
ustring funcname = ustring::fmtformat("__operator__{}__", opword());
|
||||
Symbol *sym = comp->symtab().find (funcname);
|
||||
Symbol* sym = comp->symtab().find(funcname);
|
||||
if (sym && sym->symtype() == SymTypeFunction)
|
||||
m_function_overload = (FunctionSymbol *)sym;
|
||||
m_function_overload = (FunctionSymbol*)sym;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *
|
||||
ASTbinary_expression::childname (size_t i) const
|
||||
ASTNode*
|
||||
ASTbinary_expression::make(OSLCompilerImpl* comp, Operator op, ASTNode* left,
|
||||
ASTNode* right)
|
||||
{
|
||||
static const char *name[] = { "left", "right" };
|
||||
// If the left and right are both literal constants, fold the expression
|
||||
if (left->nodetype() == literal_node && right->nodetype() == literal_node) {
|
||||
ASTNode* cf = nullptr; // constant-folded result
|
||||
if (left->typespec().is_int() && right->typespec().is_int()) {
|
||||
int lv = dynamic_cast<ASTliteral*>(left)->intval();
|
||||
int rv = dynamic_cast<ASTliteral*>(right)->intval();
|
||||
switch (op) {
|
||||
case Mul: cf = new ASTliteral(comp, lv * rv); break;
|
||||
case Div: cf = new ASTliteral(comp, rv ? lv / rv : 0); break;
|
||||
case Add: cf = new ASTliteral(comp, lv + rv); break;
|
||||
case Sub: cf = new ASTliteral(comp, lv - rv); break;
|
||||
case Mod: cf = new ASTliteral(comp, rv ? lv % rv : 0); break;
|
||||
case Equal: cf = new ASTliteral(comp, lv == rv ? 1 : 0); break;
|
||||
case NotEqual: cf = new ASTliteral(comp, lv != rv ? 1 : 0); break;
|
||||
case Greater: cf = new ASTliteral(comp, lv > rv ? 1 : 0); break;
|
||||
case Less: cf = new ASTliteral(comp, lv < rv ? 1 : 0); break;
|
||||
case GreaterEqual:
|
||||
cf = new ASTliteral(comp, lv >= rv ? 1 : 0);
|
||||
break;
|
||||
case LessEqual: cf = new ASTliteral(comp, lv <= rv ? 1 : 0); break;
|
||||
case BitAnd: cf = new ASTliteral(comp, lv & rv); break;
|
||||
case BitOr: cf = new ASTliteral(comp, lv | rv); break;
|
||||
case Xor: cf = new ASTliteral(comp, lv ^ rv); break;
|
||||
case ShiftLeft: cf = new ASTliteral(comp, lv << rv); break;
|
||||
case ShiftRight: cf = new ASTliteral(comp, lv >> rv); break;
|
||||
default: break;
|
||||
}
|
||||
} else if (left->typespec().is_float()
|
||||
&& right->typespec().is_float()) {
|
||||
float lv = dynamic_cast<ASTliteral*>(left)->floatval();
|
||||
float rv = dynamic_cast<ASTliteral*>(right)->floatval();
|
||||
switch (op) {
|
||||
case Mul: cf = new ASTliteral(comp, lv * rv); break;
|
||||
case Div: cf = new ASTliteral(comp, rv ? lv / rv : 0.0f); break;
|
||||
case Add: cf = new ASTliteral(comp, lv + rv); break;
|
||||
case Sub: cf = new ASTliteral(comp, lv - rv); break;
|
||||
case Equal: cf = new ASTliteral(comp, lv == rv ? 1 : 0); break;
|
||||
case NotEqual: cf = new ASTliteral(comp, lv != rv ? 1 : 0); break;
|
||||
case Greater: cf = new ASTliteral(comp, lv > rv ? 1 : 0); break;
|
||||
case Less: cf = new ASTliteral(comp, lv < rv ? 1 : 0); break;
|
||||
case GreaterEqual:
|
||||
cf = new ASTliteral(comp, lv >= rv ? 1 : 0);
|
||||
break;
|
||||
case LessEqual: cf = new ASTliteral(comp, lv <= rv ? 1 : 0); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if (cf) {
|
||||
delete left;
|
||||
delete right;
|
||||
return cf;
|
||||
}
|
||||
}
|
||||
|
||||
return new ASTbinary_expression(comp, op, left, right);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char*
|
||||
ASTbinary_expression::childname(size_t i) const
|
||||
{
|
||||
static const char* name[] = { "left", "right" };
|
||||
return name[i];
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *
|
||||
ASTbinary_expression::opname () const
|
||||
const char*
|
||||
ASTbinary_expression::opname() const
|
||||
{
|
||||
// clang-format off
|
||||
switch (m_op) {
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -831,6 +832,10 @@ public:
|
||||
ASTbinary_expression(OSLCompilerImpl* comp, Operator op, ASTNode* left,
|
||||
ASTNode* right);
|
||||
|
||||
// Special consructor wrapper that can collapse ops between literals
|
||||
static ASTNode* make(OSLCompilerImpl* comp, Operator op, ASTNode* left,
|
||||
ASTNode* right);
|
||||
|
||||
const char* nodetypename() const { return "binary_expression"; }
|
||||
const char* childname(size_t i) const;
|
||||
const char* opname() const;
|
||||
@@ -949,7 +954,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?
|
||||
|
||||
@@ -918,7 +918,7 @@ 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()) {
|
||||
errorfmt("array of struct are not allowed as parameters");
|
||||
|
||||
@@ -701,11 +701,12 @@ OSLCompilerImpl::write_oso_const_value(const ConstantSymbol* sym) const
|
||||
osofmt("{}{}", sym->get_int(i), nelements > 1 ? " " : "");
|
||||
else if (elemtype == TypeDesc::FLOAT)
|
||||
for (int i = 0; i < nelements; ++i)
|
||||
osofmt("{}{}", sym->floatval(i), nelements > 1 ? " " : "");
|
||||
osofmt("{:.9g}{}", sym->floatval(i), nelements > 1 ? " " : "");
|
||||
else if (equivalent(elemtype, TypeDesc::TypeVector))
|
||||
for (int i = 0; i < nelements; ++i) {
|
||||
Vec3 v = sym->get_vec3(i);
|
||||
osofmt("{} {} {}{}", v.x, v.y, v.z, nelements > 1 ? " " : "");
|
||||
osofmt("{:.9g} {:.9g} {:.9g}{}", v.x, v.y, v.z,
|
||||
nelements > 1 ? " " : "");
|
||||
}
|
||||
else {
|
||||
OSL_ASSERT(0 && "Don't know how to output this constant type");
|
||||
@@ -1305,7 +1306,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
|
||||
|
||||
@@ -490,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
|
||||
|
||||
+22
-18
@@ -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
|
||||
@@ -854,109 +858,109 @@ variable_ref
|
||||
binary_expression
|
||||
: expression OR_OP expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = ASTbinary_expression::make(oslcompiler,
|
||||
ASTNode::Or, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression AND_OP expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = ASTbinary_expression::make(oslcompiler,
|
||||
ASTNode::And, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '|' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = ASTbinary_expression::make(oslcompiler,
|
||||
ASTNode::BitOr, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '^' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = ASTbinary_expression::make(oslcompiler,
|
||||
ASTNode::Xor, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '&' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = ASTbinary_expression::make(oslcompiler,
|
||||
ASTNode::BitAnd, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression EQ_OP expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = ASTbinary_expression::make(oslcompiler,
|
||||
ASTNode::Equal, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression NE_OP expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = ASTbinary_expression::make(oslcompiler,
|
||||
ASTNode::NotEqual, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '>' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = ASTbinary_expression::make(oslcompiler,
|
||||
ASTNode::Greater, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression GE_OP expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = ASTbinary_expression::make(oslcompiler,
|
||||
ASTNode::GreaterEqual, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '<' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = ASTbinary_expression::make(oslcompiler,
|
||||
ASTNode::Less, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression LE_OP expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = ASTbinary_expression::make(oslcompiler,
|
||||
ASTNode::LessEqual, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression SHL_OP expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = ASTbinary_expression::make(oslcompiler,
|
||||
ASTNode::ShiftLeft, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression SHR_OP expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = ASTbinary_expression::make(oslcompiler,
|
||||
ASTNode::ShiftRight, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '+' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = ASTbinary_expression::make(oslcompiler,
|
||||
ASTNode::Add, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '-' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = ASTbinary_expression::make(oslcompiler,
|
||||
ASTNode::Sub, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '*' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = ASTbinary_expression::make(oslcompiler,
|
||||
ASTNode::Mul, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '/' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = ASTbinary_expression::make(oslcompiler,
|
||||
ASTNode::Div, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
| expression '%' expression
|
||||
{
|
||||
$$ = new ASTbinary_expression (oslcompiler,
|
||||
$$ = ASTbinary_expression::make(oslcompiler,
|
||||
ASTNode::Mod, $1, $3);
|
||||
$$->sourceline (@2.first_line);
|
||||
}
|
||||
|
||||
@@ -397,15 +397,6 @@ OSLCompilerImpl::osl_parse_buffer (const std::string &preprocessed_buffer)
|
||||
// Thread safety with the lexer/parser
|
||||
std::lock_guard<std::mutex> lock(oslcompiler_mutex);
|
||||
|
||||
#ifndef OIIO_STRUTIL_HAS_STOF
|
||||
// Force classic "C" locale for correct '.' decimal parsing.
|
||||
// N.B. This is not safe in a multi-threaded program where another
|
||||
// application thread is expecting the native locale to work properly.
|
||||
// This is not necessary for versions of OIIO that have Strutil::stof,
|
||||
// and we can remove it entirely when OIIO 1.9 is the minimum.
|
||||
std::locale oldlocale = std::locale::global (std::locale::classic());
|
||||
#endif
|
||||
|
||||
yyscan_t scanner;
|
||||
yylex_init(&scanner);
|
||||
YY_BUFFER_STATE buffer = yy_scan_string(preprocessed_buffer.c_str(), scanner);
|
||||
@@ -415,9 +406,6 @@ OSLCompilerImpl::osl_parse_buffer (const std::string &preprocessed_buffer)
|
||||
yy_delete_buffer (buffer, scanner);
|
||||
yylex_destroy(scanner);
|
||||
|
||||
#ifndef OIIO_STRUTIL_HAS_STOF
|
||||
std::locale::global (oldlocale); // Restore the original locale.
|
||||
#endif
|
||||
return parseerr;
|
||||
}
|
||||
|
||||
|
||||
@@ -143,6 +143,10 @@ Symbol::print(std::ostream& out, int maxvals) const
|
||||
out << " renderer-output";
|
||||
if (symtype() == SymTypeParam && !lockgeom())
|
||||
out << " lockgeom=0";
|
||||
if (symtype() == SymTypeParam && interactive())
|
||||
out << " interactive=1";
|
||||
if (symtype() == SymTypeParam && noninteractive())
|
||||
out << " interactive=0";
|
||||
}
|
||||
out << "\n";
|
||||
if (symtype() == SymTypeConst) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -478,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;
|
||||
}
|
||||
}
|
||||
@@ -618,7 +618,7 @@ ASTternary_expression::typecheck(TypeSpec expected)
|
||||
errorfmt("Cannot use an array as a condition");
|
||||
|
||||
// No arrays
|
||||
if (t.is_array() || t.is_array()) {
|
||||
if (t.is_array() || f.is_array()) {
|
||||
errorfmt("Not allowed: '{} ? {} : {}'", c, t, f);
|
||||
return TypeSpec();
|
||||
}
|
||||
@@ -678,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()) {
|
||||
@@ -762,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);
|
||||
@@ -992,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
|
||||
@@ -1065,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
|
||||
@@ -1619,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);
|
||||
@@ -1994,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);
|
||||
|
||||
@@ -123,7 +123,7 @@ set (lib_src
|
||||
llvm_gen.cpp llvm_instance.cpp llvm_util.cpp
|
||||
rs_fallback.cpp
|
||||
)
|
||||
if (BUILD_BATCHED)
|
||||
if (OSL_BUILD_BATCHED)
|
||||
list(APPEND lib_src
|
||||
batched_analysis.cpp
|
||||
batched_backendllvm.cpp
|
||||
@@ -209,7 +209,7 @@ macro ( CUDA_SHADEOPS_COMPILE srclist )
|
||||
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_EXECUTABLE} "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py"
|
||||
${linked_shadeops_bc} ${shadeops_bc_cuda_cpp} "osl_llvm_compiled_ops_cuda"
|
||||
@@ -222,14 +222,14 @@ if (USE_LLVM_BITCODE)
|
||||
set (llvm_ops_srcs llvm_ops.cpp)
|
||||
EMBED_LLVM_BITCODE_IN_CPP ( "${llvm_ops_srcs}" "_host" "osl_llvm_compiled_ops" lib_src "")
|
||||
|
||||
set (rs_dependant_ops_srcs
|
||||
set (rs_dependent_ops_srcs
|
||||
opmatrix.cpp
|
||||
)
|
||||
# Achieve the effect of absorbing osl_llvm_compiled_ops by adding its
|
||||
# sources to rs_dependant_ops_srcs which avoids having to do it at runtime.
|
||||
list (APPEND rs_dependant_ops_srcs ${llvm_ops_srcs})
|
||||
# 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_dependant_ops_srcs}" "_host_rs" "osl_llvm_compiled_rs_dependant_ops" lib_src "")
|
||||
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)
|
||||
@@ -352,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")
|
||||
@@ -370,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.
|
||||
@@ -388,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 ()
|
||||
@@ -434,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")
|
||||
|
||||
@@ -23,7 +23,7 @@ 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
|
||||
// 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
|
||||
@@ -88,7 +88,7 @@ simulate(Accumulator& accum, const char** events, size_t testno)
|
||||
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;
|
||||
|
||||
@@ -138,7 +138,7 @@ NdfAutomata::symbolsFrom(const IntSet& states, SymbolSet& out_symbols,
|
||||
{
|
||||
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
|
||||
// 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)
|
||||
|
||||
+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
|
||||
|
||||
+88
-309
@@ -6,10 +6,6 @@
|
||||
#include <OpenImageIO/filesystem.h>
|
||||
#include <OpenImageIO/strutil.h>
|
||||
|
||||
#ifdef OSL_USE_OPTIX
|
||||
# include <optix.h>
|
||||
#endif
|
||||
|
||||
#include "oslexec_pvt.h"
|
||||
#include "backendllvm.h"
|
||||
|
||||
@@ -21,55 +17,6 @@ OSL_NAMESPACE_ENTER
|
||||
namespace pvt {
|
||||
|
||||
|
||||
#ifdef OSL_SPI
|
||||
static void
|
||||
check_cwd(ShadingSystemImpl& shadingsys)
|
||||
{
|
||||
std::string err;
|
||||
char pathname[1024] = { "" };
|
||||
if (!getcwd(pathname, sizeof(pathname) - 1)) {
|
||||
int e = errno;
|
||||
err += fmtformat("Failed getcwd(), errno is {}: {}\n", errno, pathname);
|
||||
if (e == EACCES || e == ENOENT) {
|
||||
err += "Read/search permission problem or dir does not exist.\n";
|
||||
const char* pwdenv = getenv("PWD");
|
||||
if (!pwdenv) {
|
||||
err += "$PWD is not even found in the environment.\n";
|
||||
} else {
|
||||
err += fmtformat("$PWD is \"{}\"\n", pwdenv);
|
||||
err += fmtformat("That {}.\n", OIIO::Filesystem::exists(pwdenv)
|
||||
? "exists"
|
||||
: "does NOT exist");
|
||||
err += fmtformat("That {} a directory.\n",
|
||||
OIIO::Filesystem::is_directory(pwdenv)
|
||||
? "is"
|
||||
: "is NOT");
|
||||
std::vector<std::string> pieces;
|
||||
Strutil::split(pwdenv, pieces, "/");
|
||||
std::string p;
|
||||
for (size_t i = 0; i < pieces.size(); ++i) {
|
||||
if (!pieces[i].size())
|
||||
continue;
|
||||
p += "/";
|
||||
p += pieces[i];
|
||||
err += fmtformat(" {} : {} and is{} a directory.\n", p,
|
||||
OIIO::Filesystem::exists(p)
|
||||
? "exists"
|
||||
: "does NOT exist",
|
||||
OIIO::Filesystem::is_directory(p)
|
||||
? ""
|
||||
: " NOT");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (err.size())
|
||||
shadingsys.error(err);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
BackendLLVM::BackendLLVM(ShadingSystemImpl& shadingsys, ShaderGroup& group,
|
||||
ShadingContext* ctx)
|
||||
: OSOProcessorBase(shadingsys, group, ctx)
|
||||
@@ -80,13 +27,14 @@ BackendLLVM::BackendLLVM(ShadingSystemImpl& shadingsys, ShaderGroup& group,
|
||||
, m_stat_llvm_opt_time(0)
|
||||
, m_stat_llvm_jit_time(0)
|
||||
{
|
||||
#ifdef OSL_SPI
|
||||
// Temporary (I hope) check to diagnose an intermittent failure of
|
||||
// getcwd inside LLVM. Oy.
|
||||
check_cwd(shadingsys);
|
||||
#endif
|
||||
m_use_optix = shadingsys.renderer()->supports("OptiX");
|
||||
m_use_optix = shadingsys.use_optix();
|
||||
m_use_rs_bitcode = !shadingsys.m_rs_bitcode.empty();
|
||||
m_name_llvm_syms = shadingsys.m_llvm_output_bitcode;
|
||||
|
||||
// Select the appropriate ustring representation
|
||||
ll.ustring_rep(m_use_optix ? LLVM_Util::UstringRep::hash
|
||||
: LLVM_Util::UstringRep::charptr);
|
||||
|
||||
ll.dumpasm(shadingsys.m_llvm_dumpasm);
|
||||
ll.jit_fma(shadingsys.m_llvm_jit_fma);
|
||||
ll.jit_aggressive(shadingsys.m_llvm_jit_aggressive);
|
||||
@@ -135,7 +83,7 @@ BackendLLVM::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)
|
||||
@@ -230,6 +178,7 @@ static ustring fields[] = { ustring("P"),
|
||||
ustring("tracedata"),
|
||||
ustring("objdata"),
|
||||
ustring("shadingcontext"),
|
||||
ustring("shadingStateUniform"),
|
||||
ustring("renderer"),
|
||||
ustring("object2common"),
|
||||
ustring("shader2common"),
|
||||
@@ -259,7 +208,8 @@ BackendLLVM::llvm_global_symbol_ptr(ustring name)
|
||||
// the ShaderGlobals struct.
|
||||
int sg_index = ShaderGlobalNameToIndex(name);
|
||||
OSL_ASSERT(sg_index >= 0);
|
||||
return ll.void_ptr(ll.GEP(sg_ptr(), 0, sg_index));
|
||||
return ll.void_ptr(ll.GEP(sg_ptr(), 0, sg_index),
|
||||
llnamefmt("glob_{}_voidptr", name));
|
||||
}
|
||||
|
||||
|
||||
@@ -276,6 +226,15 @@ BackendLLVM::getLLVMSymbolBase(const Symbol& sym)
|
||||
llvm_type(sym.typespec().elementtype()));
|
||||
return result;
|
||||
}
|
||||
if (sym.symtype() == SymTypeParam && sym.interactive()) {
|
||||
// Special case for interactively-edited parameters -- they live in
|
||||
// the interactive data block for the group.
|
||||
// Generate the pointer to this symbol by offsetting into the
|
||||
// interactive data block.
|
||||
int offset = group().interactive_param_offset(layer(), sym.name());
|
||||
return ll.offset_ptr(m_llvm_interactive_params_ptr, offset,
|
||||
llvm_ptr_type(sym.typespec().elementtype()));
|
||||
}
|
||||
|
||||
if (sym.symtype() == SymTypeParam || sym.symtype() == SymTypeOutputParam) {
|
||||
// Special case for params -- they live in the group data
|
||||
@@ -322,7 +281,7 @@ BackendLLVM::getOrAllocateLLVMSymbol(const Symbol& sym)
|
||||
|
||||
if (map_iter == named_values().end()) {
|
||||
llvm::Value* a = llvm_alloca(sym.typespec(), sym.has_derivs(),
|
||||
mangled_name);
|
||||
llnamefmt("{}_mem", mangled_name));
|
||||
named_values()[mangled_name] = a;
|
||||
return a;
|
||||
}
|
||||
@@ -331,9 +290,11 @@ BackendLLVM::getOrAllocateLLVMSymbol(const Symbol& sym)
|
||||
|
||||
|
||||
|
||||
#if OSL_USE_OPTIX
|
||||
llvm::Value*
|
||||
BackendLLVM::addCUDAVariable(const std::string& name, int size, int alignment,
|
||||
const void* data, TypeDesc type)
|
||||
BackendLLVM::addCUDAGlobalVariable(const std::string& name, int size,
|
||||
int alignment, const void* init_data,
|
||||
TypeDesc type)
|
||||
{
|
||||
OSL_ASSERT(use_optix()
|
||||
&& "This function is only supposed to be used with OptiX!");
|
||||
@@ -341,40 +302,16 @@ BackendLLVM::addCUDAVariable(const std::string& name, int size, int alignment,
|
||||
llvm::Constant* constant = nullptr;
|
||||
|
||||
if (type == TypeDesc::TypeFloat) {
|
||||
constant = llvm::ConstantFP::get(llvm::Type::getFloatTy(
|
||||
ll.module()->getContext()),
|
||||
*(float*)data);
|
||||
constant = ll.constant(*(const float*)init_data);
|
||||
} else if (type == TypeDesc::TypeInt) {
|
||||
constant = llvm::ConstantInt::get(llvm::Type::getInt32Ty(
|
||||
ll.module()->getContext()),
|
||||
*(int*)data);
|
||||
constant = ll.constant(*(const int*)init_data);
|
||||
} else if (type == TypeDesc::TypeString) {
|
||||
// Register the string with the OptiX renderer. The renderer will add
|
||||
// the string to a global table and create an OptiX variable to hold the
|
||||
// char*.
|
||||
shadingsys().renderer()->register_string(((ustring*)data)->string(),
|
||||
name);
|
||||
|
||||
#if OPTIX_VERSION < 70000
|
||||
// Leave the variable uninitialized to prevent raw pointers from
|
||||
// appearing in the generated code. The OptiX renderer will set the
|
||||
// variable to the string address before the kernel is launched.
|
||||
constant = llvm::ConstantInt::get(llvm::Type::getInt64Ty(
|
||||
ll.module()->getContext()),
|
||||
0);
|
||||
m_varname_map[name] = ((ustring*)data)->string();
|
||||
#else
|
||||
// DeviceStrings use the ustring hash to identify themselves. These hashes will
|
||||
// match on both the device and host side.
|
||||
constant = llvm::ConstantInt::get(llvm::Type::getInt64Ty(
|
||||
ll.module()->getContext()),
|
||||
((ustring*)data)->hash());
|
||||
m_varname_map[name] = ((ustring*)data)->string();
|
||||
#endif
|
||||
|
||||
constant = ll.constant64(((const ustring*)init_data)->hash());
|
||||
// N.B. Since this is the OptiX side specifically, we will represent
|
||||
// strings as the ustringhash, so we know it as a constant.
|
||||
} else {
|
||||
// Handle unspecified types as generic byte arrays
|
||||
llvm::ArrayRef<uint8_t> arr_ref((uint8_t*)data, size);
|
||||
llvm::ArrayRef<uint8_t> arr_ref((uint8_t*)init_data, size);
|
||||
constant = llvm::ConstantDataArray::get(ll.module()->getContext(),
|
||||
arr_ref);
|
||||
}
|
||||
@@ -384,15 +321,13 @@ BackendLLVM::addCUDAVariable(const std::string& name, int size, int alignment,
|
||||
|
||||
OSL_DASSERT(g_var && "Unable to create GlobalVariable");
|
||||
|
||||
#if OSL_LLVM_VERSION >= 100
|
||||
# if OSL_LLVM_VERSION >= 100
|
||||
g_var->setAlignment(llvm::MaybeAlign(alignment));
|
||||
#else
|
||||
# else
|
||||
g_var->setAlignment(alignment);
|
||||
#endif
|
||||
# endif
|
||||
|
||||
#if (OPTIX_VERSION < 70000)
|
||||
g_var->setLinkage(llvm::GlobalValue::ExternalLinkage);
|
||||
#endif
|
||||
g_var->setLinkage(llvm::GlobalValue::PrivateLinkage);
|
||||
g_var->setVisibility(llvm::GlobalValue::DefaultVisibility);
|
||||
g_var->setInitializer(constant);
|
||||
m_const_map[name] = g_var;
|
||||
@@ -402,156 +337,27 @@ BackendLLVM::addCUDAVariable(const std::string& name, int size, int alignment,
|
||||
|
||||
|
||||
|
||||
void
|
||||
BackendLLVM::createOptixMetadata(const std::string& name, const Symbol& sym)
|
||||
{
|
||||
// Create additional variables with the semantic information needed by OptiX
|
||||
// to access the global variable created above.
|
||||
//
|
||||
// There is no need to retain pointers to these variables, since they are not
|
||||
// accessed during execution. They are only used internally by OptiX.
|
||||
//
|
||||
// Refer to the OptiX API documentation and optix_defines.h in the OptiX SDK
|
||||
// for more information.
|
||||
|
||||
OSL_ASSERT(use_optix()
|
||||
&& "This function is only supported when using OptiX!");
|
||||
|
||||
auto mangle_name = [](const std::string& name, const std::string& prefix) {
|
||||
return fmtformat("_ZN{}rti_internal_{}{}{}E", prefix.size() + 13,
|
||||
prefix, name.size(), name);
|
||||
};
|
||||
|
||||
std::string optix_type;
|
||||
const TypeDesc type = sym.typespec().simpletype();
|
||||
if (!sym.typespec().is_array()) {
|
||||
optix_type =
|
||||
// Documented built-in types
|
||||
(type == TypeDesc::TypeInt) ? "int"
|
||||
: (type == TypeDesc::TypeFloat) ? "float"
|
||||
: (type == TypeDesc::TypePoint) ? "float3"
|
||||
: (type == TypeDesc::TypeVector) ? "float3"
|
||||
: (type == TypeDesc::TypeNormal) ? "float3"
|
||||
: (type == TypeDesc::TypeColor) ? "float3"
|
||||
: (type == TypeDesc::TypeMatrix) ? "matrix"
|
||||
: (type == TypeDesc::TypeString)
|
||||
? "uint64_t"
|
||||
:
|
||||
// Catch-all for types that fall through, if there are any.
|
||||
type.c_str();
|
||||
|
||||
// NB: TypeMatrix is assumed to be 4x4 and will be treated by OptiX as a
|
||||
// user datatype (i.e., a generic struct).
|
||||
} else {
|
||||
// OptiX should handle int and float vectors between 2 and 4 dimensions
|
||||
// with no problem. Larger arrays, or arrays of other element types,
|
||||
// will be treated as a user datatype and will not work natively with
|
||||
// OptiX's variable mechanism.
|
||||
optix_type = fmtformat("{}{}", sym.typespec().elementtype(),
|
||||
sym.typespec().arraylength());
|
||||
}
|
||||
|
||||
struct rti_typeinfo {
|
||||
unsigned int kind = 0x796152; // _OPTIX_VARIABLE
|
||||
unsigned int size;
|
||||
} type_info;
|
||||
type_info.size = sym.size();
|
||||
|
||||
int type_enum = 0x1337; // _OPTIX_TYPE_ENUM_UNKNOWN
|
||||
char zero = 0;
|
||||
|
||||
addCUDAVariable(mangle_name(name, "typeinfo"), 8, 4, &type_info);
|
||||
addCUDAVariable(mangle_name(name, "typename"), optix_type.size() + 1, 16,
|
||||
optix_type.data());
|
||||
addCUDAVariable(mangle_name(name, "typeenum"), 4, 4, &type_enum,
|
||||
TypeDesc::TypeInt);
|
||||
addCUDAVariable(mangle_name(name, "semantic"), 1, 1, &zero);
|
||||
addCUDAVariable(mangle_name(name, "annotation"), 1, 1, &zero);
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BackendLLVM::getOrAllocateCUDAVariable(const Symbol& sym, bool addMetadata)
|
||||
BackendLLVM::getOrAllocateCUDAVariable(const Symbol& sym)
|
||||
{
|
||||
OSL_ASSERT(use_optix()
|
||||
&& "This function is only supported when using OptiX!");
|
||||
|
||||
std::ostringstream ss;
|
||||
ss.imbue(std::locale::classic()); // force C locale
|
||||
if (sym.typespec().is_string()) {
|
||||
// Use the ustring hash to create a name for the symbol that's based on
|
||||
// the string contents
|
||||
//
|
||||
// TODO: Collisions between variable names are unlikely, but still
|
||||
// possible. Using something like a counter to handle collisions
|
||||
// is unattractive because it depends on the order in which
|
||||
// strings are encountered at run time.
|
||||
//
|
||||
// For now I am simply appending the length to the hash, but a
|
||||
// more robust solution may be called for.
|
||||
|
||||
ss << "ds_"
|
||||
#if OPTIX_VERSION >= 70000
|
||||
<< group().name() << "_" << group().id() << "_"
|
||||
#endif
|
||||
<< std::setbase(16) << std::setfill('0') << std::setw(16)
|
||||
<< sym.get_string().hash() << "_" << std::setbase(16)
|
||||
<< std::setfill('0') << std::setw(4) << sym.get_string().length();
|
||||
|
||||
auto it = m_varname_map.find(ss.str());
|
||||
const std::string old_str = (it != m_varname_map.end()) ? it->second
|
||||
: "";
|
||||
|
||||
if (old_str != "" && old_str != sym.get_string().string()) {
|
||||
std::cerr << "Warning: variable name collision between " << old_str
|
||||
<< " and " << sym.get_string() << std::endl;
|
||||
}
|
||||
} else {
|
||||
// We need to sanitize the symbol name for PTX compatibility
|
||||
std::string sym_name = sym.name().c_str();
|
||||
std::replace(sym_name.begin(), sym_name.end(), '.', '_');
|
||||
|
||||
std::string var_name = fmtformat("{}_{}_{}_{}_{}", sym_name,
|
||||
group().name(), group().id(),
|
||||
inst()->layername(), sym.layer());
|
||||
|
||||
// Leading dollar signs are not allowed in PTX variable names,
|
||||
// so prepend an underscore.
|
||||
if (var_name[0] == '$') {
|
||||
ss << '_';
|
||||
}
|
||||
|
||||
ss << var_name;
|
||||
}
|
||||
|
||||
const std::string name = ss.str();
|
||||
std::string name = global_unique_symname(sym);
|
||||
|
||||
// Return the Value if it has already been allocated
|
||||
std::map<std::string, llvm::GlobalVariable*>::iterator it
|
||||
= get_const_map().find(name);
|
||||
|
||||
if (it != get_const_map().end()) {
|
||||
auto it = get_const_map().find(name);
|
||||
if (it != get_const_map().end())
|
||||
return it->second;
|
||||
}
|
||||
|
||||
#if (OPTIX_VERSION < 70000)
|
||||
// Add the extra metadata needed to make the variable visible to OptiX.
|
||||
if (addMetadata || sym.typespec().is_string())
|
||||
createOptixMetadata(name, sym);
|
||||
#endif
|
||||
|
||||
// TODO: Figure out the actual CUDA alignment requirements for the various
|
||||
// OSL types. For now, be somewhat conservative and assume 8 for
|
||||
// non-scalar types.
|
||||
int alignment = (sym.typespec().is_scalarnum()) ? 4 : 8;
|
||||
|
||||
llvm::Value* cuda_var = addCUDAVariable(name, sym.size(), alignment,
|
||||
sym.data(),
|
||||
sym.typespec().simpletype());
|
||||
|
||||
return cuda_var;
|
||||
return addCUDAGlobalVariable(name, sym.size(), alignment, sym.data(),
|
||||
sym.typespec().simpletype());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -568,38 +374,40 @@ BackendLLVM::llvm_get_pointer(const Symbol& sym, int deriv,
|
||||
|
||||
llvm::Value* result = NULL;
|
||||
if (sym.symtype() == SymTypeConst) {
|
||||
TypeSpec elemtype = sym.typespec().elementtype();
|
||||
#if OSL_USE_OPTIX
|
||||
if (use_optix()) {
|
||||
// Check the constant map for the named Symbol; if it's found, then
|
||||
// a GlobalVariable has been created for it
|
||||
llvm::Value* ptr = getOrAllocateCUDAVariable(sym);
|
||||
if (ptr) {
|
||||
llvm::Type* cast_type
|
||||
= (!sym.typespec().is_string())
|
||||
? ll.type_ptr(llvm_type(sym.typespec().elementtype()))
|
||||
: ll.type_void_ptr();
|
||||
|
||||
result = ll.ptr_cast(ptr, cast_type);
|
||||
result = llvm_ptr_cast(ptr, llvm_typedesc(elemtype),
|
||||
llnamefmt("cast_to_{}_", sym.typespec()));
|
||||
// N.B. llvm_typedesc() for a string will know that on OptiX,
|
||||
// strings are actually represented as just the hash.
|
||||
}
|
||||
} else {
|
||||
// For constants, start with *OUR* pointer to the constant values.
|
||||
result = ll.ptr_cast(ll.constant_ptr(sym.data()),
|
||||
ll.type_ptr(
|
||||
llvm_type(sym.typespec().elementtype())));
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// For constants on the CPU side, start with *OUR* pointer to the
|
||||
// constant values.
|
||||
result = ll.constant_ptr(sym.data(),
|
||||
ll.type_ptr(llvm_type(elemtype)));
|
||||
}
|
||||
|
||||
} else {
|
||||
// Start with the initial pointer to the variable's memory location
|
||||
// If the symbol is not a SymTypeConst, then start with the initial
|
||||
// pointer to the variable's memory location.
|
||||
result = getLLVMSymbolBase(sym);
|
||||
}
|
||||
if (!result)
|
||||
return NULL; // Error
|
||||
|
||||
// If it's an array or we're dealing with derivatives, step to the
|
||||
// right element.
|
||||
// If it's an array or we're dealing with derivatives, step to the right
|
||||
// element.
|
||||
TypeDesc t = sym.typespec().simpletype();
|
||||
if (t.arraylen || has_derivs) {
|
||||
int d = deriv * std::max(1, t.arraylen);
|
||||
if (arrayindex)
|
||||
if (arrayindex && d)
|
||||
arrayindex = ll.op_add(arrayindex, ll.constant(d));
|
||||
else
|
||||
arrayindex = ll.constant(d);
|
||||
@@ -645,13 +453,14 @@ BackendLLVM::llvm_load_value(const Symbol& sym, int deriv,
|
||||
return ll.constant(sym.get_float(component));
|
||||
}
|
||||
if (sym.typespec().is_string()) {
|
||||
return ll.constant(sym.get_string());
|
||||
return llvm_load_string(sym.get_string());
|
||||
}
|
||||
OSL_ASSERT(0 && "unhandled constant type");
|
||||
}
|
||||
|
||||
return llvm_load_value(llvm_get_pointer(sym), sym.typespec(), deriv,
|
||||
arrayindex, component, cast);
|
||||
arrayindex, component, cast,
|
||||
llnamefmt("{}_", sym.name()));
|
||||
}
|
||||
|
||||
|
||||
@@ -659,7 +468,7 @@ BackendLLVM::llvm_load_value(const Symbol& sym, int deriv,
|
||||
llvm::Value*
|
||||
BackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type, int deriv,
|
||||
llvm::Value* arrayindex, int component,
|
||||
TypeDesc cast)
|
||||
TypeDesc cast, const std::string& llname)
|
||||
{
|
||||
if (!ptr)
|
||||
return NULL; // Error
|
||||
@@ -681,7 +490,7 @@ BackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type, int deriv,
|
||||
ptr = ll.GEP(ptr, 0, component);
|
||||
|
||||
// Now grab the value
|
||||
llvm::Value* result = ll.op_load(ptr);
|
||||
llvm::Value* result = ll.op_load(ptr, llname);
|
||||
|
||||
if (type.is_closure_based())
|
||||
return result;
|
||||
@@ -691,46 +500,20 @@ BackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type, int deriv,
|
||||
result = ll.op_float_to_int(result);
|
||||
else if (type.is_int() && cast == TypeDesc::TypeFloat)
|
||||
result = ll.op_int_to_float(result);
|
||||
else if (type.is_string() && cast == TypeDesc::LONGLONG)
|
||||
else if (type.is_string() && cast == TypeDesc::LONGLONG) {
|
||||
result = ll.ptr_to_cast(result, ll.type_longlong());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BackendLLVM::llvm_load_device_string(const Symbol& sym, bool follow)
|
||||
{
|
||||
// TODO: need to make this work with arrays of strings
|
||||
OSL_ASSERT(use_optix() && "This is only intended to be used with CUDA");
|
||||
|
||||
// Recover the userdata index for non-constant parameters
|
||||
int userdata_index = find_userdata_index(sym);
|
||||
|
||||
llvm::Value* val = NULL;
|
||||
if (sym.symtype() == SymTypeLocal || sym.symtype() == SymTypeTemp) {
|
||||
// Handle temporary and local variables
|
||||
val = getOrAllocateLLVMSymbol(sym);
|
||||
val = ll.ptr_cast(val, ll.type_longlong_ptr());
|
||||
} else if (userdata_index < 0) {
|
||||
// Handle non-varying variables
|
||||
OSL_DASSERT(sym.data() && "NULL data in non-varying string");
|
||||
val = getOrAllocateCUDAVariable(sym);
|
||||
} else {
|
||||
// Handle potentially varying variables
|
||||
val = ll.ptr_cast(groupdata_field_ptr(2 + userdata_index),
|
||||
ll.type_longlong_ptr());
|
||||
// FIXME -- is this case ever used? Seems strange.
|
||||
}
|
||||
|
||||
// It's preferable to deal with device strings "symbolically" through the
|
||||
// CUDA variable (essentially a char**), which helps keep the code
|
||||
// portable. But sometimes it's necessary to handle the underlying char*
|
||||
// directly, e.g. when printing or writing out a closure param.
|
||||
if (follow)
|
||||
val = ll.int_to_ptr_cast(ll.op_load(val));
|
||||
// We still disguise hashed strings as char*. Ideally, we would only do
|
||||
// that if the rep were a charptr, but we disguise the hashes as char*'s
|
||||
// also to avoid ugliness with function signatures differing between CPU
|
||||
// and GPU. Maybe some day we'll use the hash representation on both
|
||||
// sides?
|
||||
if (type.is_string() && ll.ustring_rep() != LLVM_Util::UstringRep::charptr)
|
||||
result = ll.int_to_ptr_cast(result);
|
||||
|
||||
return val;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -764,13 +547,8 @@ BackendLLVM::llvm_load_constant_value(const Symbol& sym, int arrayindex,
|
||||
int ncomps = (int)sym.typespec().aggregate();
|
||||
return ll.constant(sym.get_float(ncomps * arrayindex + component));
|
||||
}
|
||||
if (sym.typespec().is_string() && use_optix()) {
|
||||
OSL_DASSERT((arrayindex == 0)
|
||||
&& "String arrays are not currently supported in OptiX");
|
||||
return llvm_load_device_string(sym, /*follow*/ false);
|
||||
}
|
||||
if (sym.typespec().is_string()) {
|
||||
return ll.constant(sym.get_string(arrayindex));
|
||||
return llvm_load_string(sym.get_string(arrayindex));
|
||||
}
|
||||
|
||||
OSL_ASSERT(0 && "unhandled constant type");
|
||||
@@ -920,16 +698,20 @@ BackendLLVM::llvm_store_component_value(llvm::Value* new_val, const Symbol& sym,
|
||||
llvm::Value*
|
||||
BackendLLVM::groupdata_field_ref(int fieldnum)
|
||||
{
|
||||
return ll.GEP(groupdata_ptr(), 0, fieldnum);
|
||||
return ll.GEP(groupdata_ptr(), 0, fieldnum,
|
||||
llnamefmt("{}_ref", m_groupdata_field_names[fieldnum]));
|
||||
}
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BackendLLVM::groupdata_field_ptr(int fieldnum, TypeDesc type)
|
||||
{
|
||||
llvm::Value* result = ll.void_ptr(groupdata_field_ref(fieldnum));
|
||||
llvm::Value* result = groupdata_field_ref(fieldnum);
|
||||
std::string llname = llnamefmt("{}_ptr", m_groupdata_field_names[fieldnum]);
|
||||
if (type != TypeDesc::UNKNOWN)
|
||||
result = ll.ptr_to_cast(result, llvm_type(type));
|
||||
result = ll.ptr_to_cast(result, llvm_type(type), llname);
|
||||
else
|
||||
result = ll.void_ptr(result, llname);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -972,8 +754,6 @@ BackendLLVM::llvm_call_function(const char* name, cspan<const Symbol*> args,
|
||||
const Symbol& s = *(args[i]);
|
||||
if (s.typespec().is_closure())
|
||||
valargs[i] = llvm_load_value(s);
|
||||
else if (use_optix() && s.typespec().is_string())
|
||||
valargs[i] = llvm_load_device_string(s, /*follow*/ true);
|
||||
else if (s.typespec().simpletype().aggregate > 1
|
||||
|| (deriv_ptrs && s.has_derivs()))
|
||||
valargs[i] = llvm_void_ptr(s);
|
||||
@@ -983,6 +763,8 @@ BackendLLVM::llvm_call_function(const char* name, cspan<const Symbol*> args,
|
||||
return ll.call_function(name, cspan<llvm::Value*>(valargs, args.size()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BackendLLVM::llvm_test_nonzero(Symbol& val, bool test_derivs)
|
||||
{
|
||||
@@ -1056,8 +838,8 @@ BackendLLVM::llvm_assign_impl(Symbol& Result, Symbol& Src, int arrayindex,
|
||||
// the size difference is intended (by the optimizer).
|
||||
if (result_t.is_array() && src_t.is_array() && arrayindex == -1) {
|
||||
OSL_DASSERT(assignable(result_t.elementtype(), src_t.elementtype()));
|
||||
llvm::Value* resultptr = llvm_void_ptr(Result);
|
||||
llvm::Value* srcptr = llvm_void_ptr(Src);
|
||||
llvm::Value* resultptr = llvm_get_pointer(Result);
|
||||
llvm::Value* srcptr = llvm_get_pointer(Src);
|
||||
int len = std::min(Result.size(), Src.size());
|
||||
int align = result_t.is_closure_based()
|
||||
? (int)sizeof(void*)
|
||||
@@ -1078,10 +860,7 @@ BackendLLVM::llvm_assign_impl(Symbol& Result, Symbol& Src, int arrayindex,
|
||||
TypeDesc basetype = TypeDesc::BASETYPE(rt.basetype);
|
||||
const int num_components = rt.aggregate;
|
||||
const bool singlechan = (srccomp != -1) || (dstcomp != -1);
|
||||
if (use_optix() && Src.typespec().is_string()) {
|
||||
llvm::Value* src = llvm_load_device_string(Src, /*follow*/ true);
|
||||
llvm_store_value(ll.ptr_cast(src, ll.type_void_ptr()), Result);
|
||||
} else if (!singlechan) {
|
||||
if (!singlechan) {
|
||||
for (int i = 0; i < num_components; ++i) {
|
||||
llvm::Value* src_val
|
||||
= Src.is_constant()
|
||||
|
||||
+291
-185
@@ -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,194 @@ 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);
|
||||
|
||||
#if OSL_USE_OPTIX
|
||||
/// Return a globally unique (to the JIT module) name for symbol `sym`,
|
||||
/// assuming it's part of the currently examined layer of the group.
|
||||
std::string global_unique_symname(const Symbol& sym)
|
||||
{
|
||||
// We need to sanitize the symbol name for PTX compatibility. Also, if
|
||||
// the sym name starts with a dollar sign, which are not allowed in
|
||||
// PTX variable names, then prepend another underscore.
|
||||
auto sym_name = Strutil::replace(sym.name(), ".", "_", true);
|
||||
int layer = sym.layer();
|
||||
const ShaderInstance* inst_ = group()[layer];
|
||||
return fmtformat("{}{}_{}_{}_{}", sym_name.front() == '$' ? "_" : "",
|
||||
sym_name, group().name(), inst_->layername(), layer);
|
||||
}
|
||||
|
||||
/// 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);
|
||||
#endif
|
||||
|
||||
/// 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);
|
||||
}
|
||||
|
||||
llvm::Value *llvm_ptr_cast (llvm::Value* val, const TypeSpec &type) {
|
||||
return ll.ptr_cast (val, type.simpletype());
|
||||
/// 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_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 +377,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,133 +425,186 @@ 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 appropriate llvm type definition for a pointer to
|
||||
/// the type specified by the TypeSpec.
|
||||
llvm::Type* llvm_ptr_type(const TypeSpec& typespec)
|
||||
{
|
||||
return ll.type_ptr(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; }
|
||||
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 {
|
||||
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 = fmtformat("{}_{}_exit_", inst()->layername(),
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
void increment_useparam_ops()
|
||||
{
|
||||
shadingsys().m_stat_useparam_ops++;
|
||||
}
|
||||
|
||||
/// 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; }
|
||||
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; }
|
||||
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_interactive_params_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_rs_bitcode; /// To use free function versions of Renderer Service functions.
|
||||
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
|
||||
|
||||
@@ -185,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();
|
||||
@@ -202,13 +202,13 @@ 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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -240,7 +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.
|
||||
@@ -620,6 +620,20 @@ public:
|
||||
}
|
||||
|
||||
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
|
||||
@@ -629,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
|
||||
@@ -644,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
|
||||
@@ -657,29 +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());
|
||||
|
||||
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]())
|
||||
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
|
||||
|
||||
// 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
|
||||
@@ -1053,8 +1091,10 @@ typedef std::vector<WriteEvent> 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_
|
||||
@@ -1077,9 +1117,15 @@ 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
|
||||
};
|
||||
|
||||
@@ -1595,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
|
||||
@@ -1642,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) {
|
||||
@@ -2257,6 +2303,17 @@ struct Analyzer {
|
||||
}
|
||||
}
|
||||
|
||||
void make_closures_varying()
|
||||
{
|
||||
// We assume that closures are always stored as varying pointers
|
||||
FOREACH_PARAM(Symbol & s, inst())
|
||||
{
|
||||
if (s.typespec().is_closure()) {
|
||||
recursively_mark_varying(&s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void push_varying_of_upstream_connections()
|
||||
{
|
||||
OSL_DEV_ONLY(std::cout << "connections to layer begin" << std::endl);
|
||||
@@ -2349,6 +2406,7 @@ BatchedAnalysis::analyze_layer(ShaderInstance* inst)
|
||||
analyzer.push_varying_of_shader_globals();
|
||||
analyzer.make_interpolated_parameters_varying();
|
||||
analyzer.make_renderer_outputs_varying();
|
||||
analyzer.make_closures_varying();
|
||||
analyzer.push_varying_of_upstream_connections();
|
||||
analyzer.push_varying_of_implicitly_varying_ops();
|
||||
|
||||
|
||||
@@ -188,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)
|
||||
@@ -448,6 +448,16 @@ BatchedBackendLLVM::getLLVMSymbolBase(const Symbol& sym)
|
||||
return result;
|
||||
}
|
||||
|
||||
if (sym.symtype() == SymTypeParam && sym.interactive()) {
|
||||
// Special case for interactively-edited parameters -- they live in
|
||||
// the interactive data block for the group.
|
||||
// Generate the pointer to this symbol by offsetting into the
|
||||
// interactive data block.
|
||||
int offset = group().interactive_param_offset(layer(), sym.name());
|
||||
return ll.offset_ptr(m_llvm_interactive_params_ptr, offset,
|
||||
llvm_ptr_type(sym.typespec().elementtype()));
|
||||
}
|
||||
|
||||
if (sym.symtype() == SymTypeParam || sym.symtype() == SymTypeOutputParam) {
|
||||
// Special case for params -- they live in the group data
|
||||
int fieldnum = m_param_order_map[&sym];
|
||||
@@ -867,7 +877,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);
|
||||
@@ -888,7 +898,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()));
|
||||
@@ -1218,7 +1228,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);
|
||||
@@ -1231,7 +1242,7 @@ 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.
|
||||
@@ -1766,7 +1777,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));
|
||||
@@ -1846,7 +1858,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.
|
||||
@@ -1904,7 +1916,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)
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "oslexec_pvt.h"
|
||||
@@ -15,7 +13,7 @@
|
||||
using namespace OSL;
|
||||
using namespace OSL::pvt;
|
||||
|
||||
#include "OSL/llvm_util.h"
|
||||
#include <OSL/llvm_util.h>
|
||||
#include "runtimeoptimize.h"
|
||||
|
||||
#include <llvm/ADT/SmallString.h>
|
||||
@@ -164,7 +162,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 +276,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 +329,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,
|
||||
@@ -489,7 +487,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
|
||||
@@ -533,7 +531,7 @@ public:
|
||||
ArgVector m_args;
|
||||
|
||||
public:
|
||||
FuncSpec(const FuncSpec&) = delete;
|
||||
FuncSpec(const FuncSpec&) = delete;
|
||||
FuncSpec& operator=(const FuncSpec&) = delete;
|
||||
|
||||
FuncSpec(const llvm::Twine& name)
|
||||
@@ -658,6 +656,14 @@ public:
|
||||
return ll.llvm_vector_type(llvm_typedesc(typespec));
|
||||
}
|
||||
|
||||
/// Generate the appropriate llvm type definition for a pointer to
|
||||
/// the type specified by the TypeSpec.
|
||||
llvm::Type* llvm_ptr_type(const TypeSpec& typespec)
|
||||
{
|
||||
return reinterpret_cast<llvm::Type*>(
|
||||
ll.type_ptr(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);
|
||||
@@ -705,6 +711,8 @@ public:
|
||||
shadingsys().m_stat_tex_calls_as_handles += 1;
|
||||
}
|
||||
|
||||
void increment_useparam_ops() { shadingsys().m_stat_useparam_ops++; }
|
||||
|
||||
void llvm_print_mask(const char* title, llvm::Value* mask = nullptr);
|
||||
|
||||
/// Return the userdata index for the given Symbol. Return -1 if the Symbol
|
||||
@@ -781,7 +789,7 @@ private:
|
||||
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_interactive_params_ptr;
|
||||
llvm::Value* m_llvm_wide_shadeindex_ptr;
|
||||
llvm::Value* m_llvm_userdata_base_ptr;
|
||||
llvm::Value* m_llvm_output_base_ptr;
|
||||
|
||||
@@ -92,13 +92,17 @@ BatchedBackendLLVM::llvm_call_layer(int layer, bool unconditional)
|
||||
<< " unconditional=" << unconditional << std::endl);
|
||||
// Make code that looks like:
|
||||
// if (! groupdata->run[parentlayer])
|
||||
// parent_layer (sg, groupdata);
|
||||
// parent_layer (sg, groupdata, wide_shadeindex_ptr,
|
||||
// userdata_base_ptr, output_base_ptr,
|
||||
// execution_mask, interactive_params_ptr);
|
||||
// if it's a conditional call, or
|
||||
// parent_layer (sg, groupdata);
|
||||
// parent_layer (sg, groupdata, wide_shadeindex_ptr,
|
||||
// userdata_base_ptr, output_base_ptr,
|
||||
// execution_mask, interactive_params_ptr);
|
||||
// if it's run unconditionally.
|
||||
// The code in the parent layer itself will set its 'executed' flag.
|
||||
|
||||
llvm::Value* args[6];
|
||||
llvm::Value* args[7];
|
||||
args[0] = sg_ptr();
|
||||
args[1] = groupdata_ptr();
|
||||
args[2] = ll.void_ptr(wide_shadeindex_ptr());
|
||||
@@ -120,13 +124,11 @@ BatchedBackendLLVM::llvm_call_layer(int layer, bool unconditional)
|
||||
llvm::Value* execution_required
|
||||
= ll.op_ne(lanes_requiring_execution_value, ll.constant(0));
|
||||
then_block = ll.new_basic_block(
|
||||
llvm_debug()
|
||||
? std::string("then layer ").append(std::to_string(layer))
|
||||
: std::string());
|
||||
llvm_debug() ? Strutil::fmt::format("then layer {}", layer)
|
||||
: std::string());
|
||||
after_block = ll.new_basic_block(
|
||||
llvm_debug()
|
||||
? std::string("after layer ").append(std::to_string(layer))
|
||||
: std::string());
|
||||
llvm_debug() ? Strutil::fmt::format("after layer {}", layer)
|
||||
: std::string());
|
||||
ll.op_branch(execution_required, then_block, after_block);
|
||||
// insert point is now then_block
|
||||
} else {
|
||||
@@ -134,6 +136,7 @@ BatchedBackendLLVM::llvm_call_layer(int layer, bool unconditional)
|
||||
}
|
||||
|
||||
args[5] = lanes_requiring_execution_value;
|
||||
args[6] = m_llvm_interactive_params_ptr;
|
||||
|
||||
// Before the merge, keeping in case we broke it
|
||||
//std::string name = fmtformat("{}_{}_{}", m_library_selector, parent->layername().c_str(),
|
||||
@@ -149,6 +152,8 @@ BatchedBackendLLVM::llvm_call_layer(int layer, bool unconditional)
|
||||
|
||||
if (!unconditional)
|
||||
ll.op_branch(after_block); // also moves insert point
|
||||
|
||||
shadingsys().m_stat_call_layers_inserted++;
|
||||
}
|
||||
|
||||
|
||||
@@ -199,6 +204,15 @@ BatchedBackendLLVM::llvm_run_connected_layers(const Symbol& sym, int symindex,
|
||||
}
|
||||
}
|
||||
|
||||
if (shadingsys().m_opt_useparam && inmain) {
|
||||
// m_call_layers_inserted tracks if we've already run this layer inside the current basic block
|
||||
const CallLayerKey key = { m_bblockids[opnum], con.srclayer };
|
||||
if (m_call_layers_inserted.count(key)) {
|
||||
continue;
|
||||
}
|
||||
m_call_layers_inserted.insert(key);
|
||||
}
|
||||
|
||||
// If the earlier layer it comes from has not yet been
|
||||
// executed, do so now.
|
||||
llvm_call_layer(con.srclayer);
|
||||
@@ -236,13 +250,16 @@ LLVMGEN(llvm_gen_useparam)
|
||||
// initializing them lazily, now we have to do it.
|
||||
if ((sym.symtype() == SymTypeParam
|
||||
|| sym.symtype() == SymTypeOutputParam)
|
||||
&& !sym.lockgeom() && !sym.typespec().is_closure()
|
||||
&& sym.interpolated() && !sym.typespec().is_closure()
|
||||
&& !sym.connected() && !sym.connected_down()
|
||||
&& rop.shadingsys().lazy_userdata()) {
|
||||
rop.llvm_assign_initial_value(sym, rop.ll.mask_as_int(
|
||||
rop.ll.current_mask()));
|
||||
}
|
||||
}
|
||||
|
||||
rop.increment_useparam_ops();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -557,7 +574,7 @@ LLVMGEN(llvm_gen_arraylength)
|
||||
int len = A.typespec().is_unsized_array() ? A.initializers()
|
||||
: A.typespec().arraylength();
|
||||
|
||||
// Even thought the array's size should be uniform accross all lanes,
|
||||
// Even thought the array's size should be uniform across all lanes,
|
||||
// the symbol its being stored in maybe varying
|
||||
llvm::Value* const_length = Result.is_uniform() ? rop.ll.constant(len)
|
||||
: rop.ll.wide_constant(len);
|
||||
@@ -605,7 +622,7 @@ LLVMGEN(llvm_gen_aref)
|
||||
} else {
|
||||
BatchedBackendLLVM::TempScope temp_scope(rop);
|
||||
|
||||
// We need a copy of the indices incase the range check clamps them
|
||||
// We need a copy of the indices in case the range check clamps them
|
||||
llvm::Value* loc_clamped_wide_index = rop.getOrAllocateTemp(
|
||||
TypeSpec(TypeDesc::INT), false /*derivs*/, false /*is_uniform*/,
|
||||
false /*forceBool*/,
|
||||
@@ -687,7 +704,7 @@ LLVMGEN(llvm_gen_aassign)
|
||||
}
|
||||
} else {
|
||||
BatchedBackendLLVM::TempScope temp_scope(rop);
|
||||
// We need a copy of the indices incase the range check clamps them
|
||||
// We need a copy of the indices in case the range check clamps them
|
||||
llvm::Value* loc_clamped_wide_index = rop.getOrAllocateTemp(
|
||||
TypeSpec(TypeDesc::INT), false /*derivs*/, false /*is_uniform*/,
|
||||
false /*forceBool*/,
|
||||
@@ -1110,10 +1127,10 @@ LLVMGEN(llvm_gen_if)
|
||||
// contain a call to a lower level, those must not be executed
|
||||
// if the mask is all off
|
||||
//#define SKIP_TESTING_IF_ANY_LANES_ACTIVE_TO_AVOID_BRANCH 1
|
||||
// NOTE: if SKIP_TESTING_IF_ANY_LANES_ACTIVE_TO_AVOID_BRANCH is defineed then
|
||||
// NOTE: if SKIP_TESTING_IF_ANY_LANES_ACTIVE_TO_AVOID_BRANCH is defined then
|
||||
// library and layer functions may get called with an entirely empty mask
|
||||
#ifndef SKIP_TESTING_IF_ANY_LANES_ACTIVE_TO_AVOID_BRANCH
|
||||
// We use the combined mask stack + the if condition's mask we aready pushed
|
||||
// We use the combined mask stack + the if condition's mask we already pushed
|
||||
llvm::Value* anyThenLanesActive = rop.ll.test_if_mask_is_non_zero(
|
||||
rop.ll.current_mask());
|
||||
#endif
|
||||
@@ -1263,6 +1280,7 @@ LLVMGEN(llvm_gen_add)
|
||||
OSL_ASSERT(!A.typespec().is_array() && !B.typespec().is_array());
|
||||
if (Result.typespec().is_closure()) {
|
||||
OSL_ASSERT(A.typespec().is_closure() && B.typespec().is_closure());
|
||||
OSL_ASSERT(!A.is_uniform() && !B.is_uniform() && !result_is_uniform);
|
||||
llvm::Value* valargs[] = { rop.sg_void_ptr(), rop.llvm_void_ptr(Result),
|
||||
rop.llvm_void_ptr(A), rop.llvm_void_ptr(B),
|
||||
rop.ll.mask_as_int(rop.ll.current_mask()) };
|
||||
@@ -1676,6 +1694,7 @@ LLVMGEN(llvm_gen_modulus)
|
||||
|
||||
int num_components = type.aggregate;
|
||||
|
||||
#if 0
|
||||
if (is_float && !op_is_uniform) {
|
||||
// llvm 5.0.1 did not do a good job with op_mod when its
|
||||
// parameters were <16xf32>. So we will go ahead
|
||||
@@ -1702,7 +1721,9 @@ LLVMGEN(llvm_gen_modulus)
|
||||
}
|
||||
|
||||
rop.ll.call_function(rop.build_name(func_spec), call_args);
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
for (int i = 0; i < num_components; i++) {
|
||||
llvm::Value* a = rop.loadLLVMValue(A, i, 0, type, op_is_uniform);
|
||||
llvm::Value* b = rop.loadLLVMValue(B, i, 0, type, op_is_uniform);
|
||||
@@ -2302,7 +2323,7 @@ LLVMGEN(llvm_gen_compref)
|
||||
if (rop.inst()->master()->range_checking()) {
|
||||
BatchedBackendLLVM::TempScope temp_scope(rop);
|
||||
|
||||
// We need a copy of the indices incase the range check clamps them
|
||||
// We need a copy of the indices in case the range check clamps them
|
||||
llvm::Value* loc_clamped_wide_index = rop.getOrAllocateTemp(
|
||||
TypeSpec(TypeDesc::INT), false /*derivs*/, false /*is_uniform*/,
|
||||
false /*forceBool*/,
|
||||
@@ -2418,7 +2439,7 @@ LLVMGEN(llvm_gen_compassign)
|
||||
if (rop.inst()->master()->range_checking()) {
|
||||
BatchedBackendLLVM::TempScope temp_scope(rop);
|
||||
|
||||
// We need a copy of the indices incase the range check clamps them
|
||||
// We need a copy of the indices in case the range check clamps them
|
||||
llvm::Value* loc_clamped_wide_index = rop.getOrAllocateTemp(
|
||||
TypeSpec(TypeDesc::INT), false /*derivs*/, false /*is_uniform*/,
|
||||
false /*forceBool*/,
|
||||
@@ -2534,7 +2555,7 @@ LLVMGEN(llvm_gen_mxcompref)
|
||||
}
|
||||
} else {
|
||||
BatchedBackendLLVM::TempScope temp_scope(rop);
|
||||
// We need a copy of the indices incase the range check clamps them
|
||||
// We need a copy of the indices in case the range check clamps them
|
||||
llvm::Value* loc_clamped_wide_index = rop.getOrAllocateTemp(
|
||||
TypeSpec(TypeDesc::INT), false /*derivs*/, false /*is_uniform*/,
|
||||
false /*forceBool*/,
|
||||
@@ -2636,7 +2657,7 @@ LLVMGEN(llvm_gen_mxcompassign)
|
||||
}
|
||||
} else {
|
||||
BatchedBackendLLVM::TempScope temp_scope(rop);
|
||||
// We need a copy of the indices incase the range check clamps them
|
||||
// We need a copy of the indices in case the range check clamps them
|
||||
llvm::Value* loc_clamped_wide_index = rop.getOrAllocateTemp(
|
||||
TypeSpec(TypeDesc::INT), false /*derivs*/, false /*is_uniform*/,
|
||||
false /*forceBool*/,
|
||||
@@ -2955,7 +2976,7 @@ LLVMGEN(llvm_gen_compare_op)
|
||||
if ((typeOfA == rop.ll.type_bool() && typeOfB == rop.ll.type_int())
|
||||
|| (typeOfA == rop.ll.type_wide_bool()
|
||||
&& typeOfB == rop.ll.type_wide_int())) {
|
||||
// TODO: could optimize for contant 0 and 1 and skip the comparison
|
||||
// TODO: could optimize for constant 0 and 1 and skip the comparison
|
||||
a = rop.ll.op_bool_to_int(a);
|
||||
}
|
||||
if ((typeOfB == rop.ll.type_bool() && typeOfA == rop.ll.type_int())
|
||||
@@ -3547,7 +3568,7 @@ LLVMGEN(llvm_gen_transform)
|
||||
|
||||
FuncSpec func_spec("build_transform_matrix");
|
||||
func_spec.arg_varying(TypeDesc::TypeMatrix44);
|
||||
// Ignore derivatives if uneeded or unsupplied
|
||||
// Ignore derivatives if unneeded or unsupplied
|
||||
func_spec.arg(*From, from_is_uniform);
|
||||
func_spec.arg(*To, to_is_uniform);
|
||||
func_spec.mask();
|
||||
@@ -3570,7 +3591,7 @@ LLVMGEN(llvm_gen_transform)
|
||||
FuncSpec func_spec(op.opname().c_str());
|
||||
func_spec.unbatch();
|
||||
//std::string func_name = std::string("osl_") + op.opname().c_str() + "_";
|
||||
// Ignore derivatives if uneeded or unsupplied
|
||||
// Ignore derivatives if unneeded or unsupplied
|
||||
bool has_derivs = (Result->has_derivs() && P->has_derivs());
|
||||
func_spec.arg(*P, has_derivs, P_is_uniform);
|
||||
// The matrix is always varying if we looked it up,
|
||||
@@ -5750,7 +5771,7 @@ llvm_batched_noise_options(BatchedBackendLLVM& rop, int opnum,
|
||||
rop.ll.call_function("osl_noiseparams_set_do_filter", opt,
|
||||
rop.llvm_load_value(Val));
|
||||
} else if (name == Strings::direction && Val.typespec().is_triple()) {
|
||||
// We are not going to bin by varing direction
|
||||
// We are not going to bin by varying direction
|
||||
// instead we will pass a pointer to its wide value
|
||||
// as an extra parameter.
|
||||
// If it is null, then the uniform value from noise options
|
||||
@@ -7064,7 +7085,8 @@ LLVMGEN(llvm_gen_spline)
|
||||
static void
|
||||
llvm_gen_keyword_fill(BatchedBackendLLVM& rop, Opcode& op,
|
||||
const ClosureRegistry::ClosureEntry* clentry,
|
||||
ustring clname, llvm::Value* mem_void_ptr, int argsoffset)
|
||||
ustring clname, llvm::Value* mem_void_ptr, int argsoffset,
|
||||
int lane_index)
|
||||
{
|
||||
OSL_DASSERT(((op.nargs() - argsoffset) % 2) == 0);
|
||||
|
||||
@@ -7088,10 +7110,45 @@ llvm_gen_keyword_fill(BatchedBackendLLVM& rop, Opcode& op,
|
||||
if (equivalent(p.type, ValueType) && !strcmp(key->c_str(), p.key)) {
|
||||
// store data
|
||||
OSL_DASSERT(p.offset + p.field_size <= clentry->struct_size);
|
||||
llvm::Value* dst = rop.ll.offset_ptr(mem_void_ptr, p.offset);
|
||||
llvm::Value* src = rop.llvm_void_ptr(Value);
|
||||
rop.ll.op_memcpy(dst, src, (int)p.type.size(),
|
||||
4 /* use 4 byte alignment for now */);
|
||||
|
||||
bool arg_is_uniform = Value.is_uniform();
|
||||
|
||||
TypeDesc simpletype(Value.typespec().simpletype());
|
||||
|
||||
// We don't currently offer a helper macro in genclosure.h for creating
|
||||
// keyword array parameters, so perhaps we can assume we don't need to
|
||||
// support them
|
||||
OSL_DASSERT(simpletype.arraylen == 0);
|
||||
|
||||
int num_components = simpletype.aggregate;
|
||||
|
||||
llvm::Value* dest_base = rop.ll.offset_ptr(mem_void_ptr,
|
||||
p.offset);
|
||||
dest_base = rop.llvm_ptr_cast(dest_base, p.type);
|
||||
|
||||
for (int c = 0; c < num_components; c++) {
|
||||
llvm::Value* dest_elem;
|
||||
if (num_components > 1)
|
||||
dest_elem = rop.ll.GEP(dest_base, 0, c);
|
||||
else
|
||||
dest_elem = dest_base;
|
||||
|
||||
// NOTE: We don't want any uniform arguments to be
|
||||
// widened, so our typical op_is_uniform doesn't do what we
|
||||
// want for this when loading. So just pass arg_is_uniform
|
||||
// which will avoid widening any uniform arguments.
|
||||
llvm::Value* loaded
|
||||
= rop.llvm_load_value(Value, 0, NULL, c,
|
||||
TypeDesc::UNKNOWN,
|
||||
/*op_is_uniform*/ arg_is_uniform,
|
||||
/*index_is_uniform*/ true);
|
||||
|
||||
if (!arg_is_uniform) {
|
||||
loaded = rop.ll.op_extract(loaded, lane_index);
|
||||
}
|
||||
rop.ll.op_unmasked_store(loaded, dest_elem);
|
||||
}
|
||||
|
||||
legal = true;
|
||||
break;
|
||||
}
|
||||
@@ -7180,8 +7237,9 @@ LLVMGEN(llvm_gen_closure)
|
||||
rop.ll.type_ptr(rop.llvm_type_closure_component_wide_ptr()));
|
||||
llvm::Value* comp_wide_ptr = rop.ll.op_load(comp_wide_ptr_ptr);
|
||||
|
||||
llvm::Value* mask = rop.ll.current_mask();
|
||||
// This is an unrolled vector-width loop. It was unrolled because it's
|
||||
// was more expedient to write the for in C++ than IR, but if compiliation
|
||||
// was more expedient to write the for in C++ than IR, but if compilation
|
||||
// of the extra ops becomes problematic, this choice can be revisited
|
||||
for (int lane_index = 0; lane_index < rop.vector_width(); ++lane_index) {
|
||||
llvm::Value* comp_ptr = rop.ll.op_extract(comp_wide_ptr, lane_index);
|
||||
@@ -7193,14 +7251,16 @@ LLVMGEN(llvm_gen_closure)
|
||||
// For the weighted closures, we need a surrounding "if" so that it's safe
|
||||
// for osl_allocate_weighted_closure_component to return NULL (unless we
|
||||
// know for sure that it's constant weighted and that the weight is
|
||||
// not zero).
|
||||
// not zero). We also need the surrounding "if" to reject writing
|
||||
// to closures that aren't masked.
|
||||
llvm::BasicBlock* next_block = NULL;
|
||||
llvm::BasicBlock* notnull_block = rop.ll.new_basic_block(
|
||||
"non_null_closure");
|
||||
next_block = rop.ll.new_basic_block("");
|
||||
llvm::Value* cond
|
||||
= rop.ll.op_ne(rop.ll.ptr_cast(comp_ptr, rop.ll.type_void_ptr()),
|
||||
rop.ll.void_ptr_null());
|
||||
"non_null_and_masked_closure");
|
||||
next_block = rop.ll.new_basic_block("");
|
||||
llvm::Value* cond = rop.ll.op_and(
|
||||
rop.ll.op_ne(rop.ll.ptr_cast(comp_ptr, rop.ll.type_void_ptr()),
|
||||
rop.ll.void_ptr_null()),
|
||||
rop.ll.test_mask_lane(mask, lane_index));
|
||||
rop.ll.op_branch(cond, notnull_block, next_block);
|
||||
|
||||
// If the closure has a "prepare" method, call
|
||||
@@ -7233,7 +7293,30 @@ LLVMGEN(llvm_gen_closure)
|
||||
int num_components = simpletype.aggregate;
|
||||
|
||||
llvm::Value* dest_base = rop.ll.offset_ptr(mem_void_ptr, p.offset);
|
||||
dest_base = rop.llvm_ptr_cast(dest_base, p.type);
|
||||
llvm::Type* dest_type = rop.ll.llvm_type(
|
||||
static_cast<const TypeSpec&>(p.type).simpletype());
|
||||
dest_base = rop.ll.ptr_to_cast(dest_base, dest_type);
|
||||
|
||||
if (num_elements > 1) {
|
||||
OSL_DASSERT(rop.ll.is_type_array(dest_type));
|
||||
|
||||
// The type is an array type,
|
||||
// which means our pointer is to an array type,
|
||||
// not to &[0] (the address of the 1st element).
|
||||
// IE: typedef int Int5Array[5];
|
||||
// Int5Array *dest_base;
|
||||
// in contrast to what most of use might consider an array pointer
|
||||
// int *dest_base;
|
||||
// So if we dereference Int5Array* to with [4], the 5th element,
|
||||
// we would be really be pointing to ((int *)dest_base)[5*4] which is
|
||||
// out of bounds of our 1 instance of Int5Array.
|
||||
// Thus when dealing with arrays we will just dereference it and get the address to get
|
||||
// the address of the 1st element.
|
||||
|
||||
dest_base = rop.ll.GEP(dest_type, dest_base, 0, 0);
|
||||
llvm::Type* element_type = rop.ll.element_type_of(dest_type);
|
||||
dest_type = element_type;
|
||||
}
|
||||
|
||||
for (int a = 0; a < num_elements; ++a) {
|
||||
llvm::Value* arrind = simpletype.arraylen ? rop.ll.constant(a)
|
||||
@@ -7241,7 +7324,9 @@ LLVMGEN(llvm_gen_closure)
|
||||
for (int c = 0; c < num_components; c++) {
|
||||
llvm::Value* dest_elem;
|
||||
if (num_components > 1)
|
||||
dest_elem = rop.ll.GEP(dest_base, a, c);
|
||||
dest_elem = rop.ll.GEP(dest_type, dest_base, a, c);
|
||||
else if (num_elements > 1)
|
||||
dest_elem = rop.ll.GEP(dest_type, dest_base, a);
|
||||
else
|
||||
dest_elem = dest_base;
|
||||
|
||||
@@ -7275,7 +7360,7 @@ LLVMGEN(llvm_gen_closure)
|
||||
}
|
||||
|
||||
llvm_gen_keyword_fill(rop, op, clentry, closure_name, mem_void_ptr,
|
||||
2 + weighted + clentry->nformal);
|
||||
2 + weighted + clentry->nformal, lane_index);
|
||||
|
||||
if (next_block)
|
||||
rop.ll.op_branch(next_block);
|
||||
@@ -7706,7 +7791,7 @@ LLVMGEN(llvm_gen_pointcloud_write)
|
||||
TypeDesc::NOSEMANTICS, nattrs } };
|
||||
TypeSpec valuesArrayType { TypeDesc { TypeDesc::PTR, TypeDesc::SCALAR,
|
||||
TypeDesc::NOSEMANTICS, nattrs } };
|
||||
llvm::Value* names = rop.ll.op_alloca(rop.ll.type_string(), nattrs);
|
||||
llvm::Value* names = rop.ll.op_alloca(rop.ll.type_ustring(), nattrs);
|
||||
llvm::Value* types = rop.ll.op_alloca(rop.ll.type_typedesc(), nattrs);
|
||||
llvm::Value* values = rop.ll.op_alloca(rop.ll.type_void_ptr(), nattrs);
|
||||
|
||||
@@ -8191,7 +8276,7 @@ LLVMGEN(llvm_gen_split)
|
||||
llvm::Value* wide_sep = rop.ll.wide_constant("");
|
||||
llvm::Value* temp_wide_sep = rop.getOrAllocateTemp(
|
||||
TypeSpec(TypeDesc::STRING), false /*derivs*/,
|
||||
false /*op_is_uniform*/, false /*forceBool*/, "wide seperator");
|
||||
false /*op_is_uniform*/, false /*forceBool*/, "wide separator");
|
||||
rop.ll.op_unmasked_store(wide_sep, temp_wide_sep);
|
||||
args.push_back(rop.ll.void_ptr(temp_wide_sep));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -63,8 +63,19 @@ Schematically, we want to create code that resembles the following:
|
||||
float param_1_bar;
|
||||
};
|
||||
|
||||
// Data for the interactively adjusted parameters of this group -- these
|
||||
// can't be turned into constants because the app may want to modify them
|
||||
// as it runs (such as for user interaction). This block of memory has
|
||||
// one global copy specific each the shader group, managed by OSL.
|
||||
struct InteractiveParams {
|
||||
float iparam_0_baz;
|
||||
};
|
||||
|
||||
// Name of layer entry is $layer_ID
|
||||
void $layer_0 (ShaderGlobals *sg, GroupData_1 *group)
|
||||
void $layer_0(ShaderGlobals *sg, GroupData_1 *group,
|
||||
wide_int* wide_shadeindex_ptr,
|
||||
void* userdatda_base_ptr, void* output_base_ptr,
|
||||
int mask, InteractiveParams* interactive_params)
|
||||
{
|
||||
// Declare locals, temps, constants, params with known values.
|
||||
// Make them all look like stack memory locations:
|
||||
@@ -74,9 +85,14 @@ Schematically, we want to create code that resembles the following:
|
||||
// then run the shader body:
|
||||
*x = sg->u * group->param_0_bar;
|
||||
group->param_1_foo = *x;
|
||||
*x += interactive_params->iparam_0_baz;
|
||||
// ...
|
||||
}
|
||||
|
||||
void $layer_1 (ShaderGlobals *sg, GroupData_1 *group)
|
||||
void $layer_1(ShaderGlobals *sg, GroupData_1 *group,
|
||||
wide_int* wide_shadeindex_ptr,
|
||||
void* userdatda_base_ptr, void* output_base_ptr,
|
||||
int mask, InteractiveParams* interactive_params)
|
||||
{
|
||||
// Because we need the outputs of layer 0 now, we call it if it
|
||||
// hasn't already run:
|
||||
@@ -87,7 +103,10 @@ Schematically, we want to create code that resembles the following:
|
||||
*y = sg->u * group->$param_1_bar;
|
||||
}
|
||||
|
||||
void $group_1 (ShaderGlobals *sg, GroupData_1 *group)
|
||||
void $group_1(ShaderGlobals *sg, GroupData_1 *group,
|
||||
wide_int* wide_shadeindex_ptr,
|
||||
void* userdatda_base_ptr, void* output_base_ptr,
|
||||
int mask, InteractiveParams* interactive_params)
|
||||
{
|
||||
group->layer_run[...] = 0;
|
||||
// Run just the unconditional layers
|
||||
@@ -760,11 +779,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*/);
|
||||
@@ -894,7 +912,7 @@ 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
|
||||
// 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();
|
||||
@@ -902,14 +920,13 @@ BatchedBackendLLVM::llvm_type_groupdata()
|
||||
if (offset & (align - 1))
|
||||
offset += align - (offset & (align - 1));
|
||||
if (llvm_debug() >= 2)
|
||||
std::cout << " " << inst->layername() << " (" << inst->id()
|
||||
<< ") " << sym.mangled() << " " << ts.c_str()
|
||||
<< ", field " << order << ", size "
|
||||
<< derivSize * int(sym.size()) << ", offset "
|
||||
<< offset << std::endl;
|
||||
print(" {} ({}) {} {}, field {}, size {}, offset {}{}{}\n",
|
||||
inst->layername(), inst->id(), sym.mangled(), ts.c_str(),
|
||||
order, derivSize * int(sym.size()), offset,
|
||||
sym.interpolated() ? " (interpolated)" : "",
|
||||
sym.interactive() ? " (interactive)" : "");
|
||||
sym.wide_dataoffset((int)offset);
|
||||
offset += derivSize * int(sym.size()) * m_width;
|
||||
|
||||
m_param_order_map[&sym] = order;
|
||||
++order;
|
||||
}
|
||||
@@ -1042,10 +1059,10 @@ BatchedBackendLLVM::llvm_assign_initial_value(
|
||||
llvm_assign_zero(sym);
|
||||
return; // we're done, the parts below are just for params
|
||||
}
|
||||
ASSERT_MSG(sym.symtype() == SymTypeParam
|
||||
|| sym.symtype() == SymTypeOutputParam,
|
||||
"symtype was %d, data type was %s", (int)sym.symtype(),
|
||||
sym.typespec().c_str());
|
||||
OSL_ASSERT_MSG(sym.symtype() == SymTypeParam
|
||||
|| sym.symtype() == SymTypeOutputParam,
|
||||
"symtype was %d, data type was %s", (int)sym.symtype(),
|
||||
sym.typespec().c_str());
|
||||
|
||||
// Handle interpolated params by calling osl_bind_interpolated_param,
|
||||
// which will check if userdata is already retrieved, if not it will
|
||||
@@ -1060,7 +1077,7 @@ BatchedBackendLLVM::llvm_assign_initial_value(
|
||||
bool partial_userdata_mask_was_pushed = false;
|
||||
const SymLocationDesc* symloc = nullptr;
|
||||
LLVM_Util::ScopedMasking partial_data_masking_scope;
|
||||
if (!sym.lockgeom() && !sym.typespec().is_closure()) {
|
||||
if (sym.interpolated() && !sym.typespec().is_closure()) {
|
||||
ustring symname = sym.name();
|
||||
TypeDesc type = sym.typespec().simpletype();
|
||||
|
||||
@@ -1126,7 +1143,7 @@ BatchedBackendLLVM::llvm_assign_initial_value(
|
||||
// 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.
|
||||
// must be dereferenceable with a shadeindex of 0.
|
||||
llvm::Value* wide_val
|
||||
= ll.op_gather(userdata_sym_base_ptr, wide_index);
|
||||
|
||||
@@ -1218,6 +1235,15 @@ BatchedBackendLLVM::llvm_assign_initial_value(
|
||||
|
||||
// Handle init ops.
|
||||
build_llvm_code(sym.initbegin(), sym.initend());
|
||||
#if 0 /* Is this needed? */
|
||||
} else if (sym.interpolated() && !sym.typespec().is_closure()) {
|
||||
// geometrically-varying param; memcpy its default value
|
||||
TypeDesc t = sym.typespec().simpletype();
|
||||
ll.op_memcpy(llvm_void_ptr(sym), ll.constant_ptr(sym.data()),
|
||||
t.size(), t.basesize() /*align*/);
|
||||
if (sym.has_derivs())
|
||||
llvm_zero_derivs(sym);
|
||||
#endif
|
||||
} else {
|
||||
// We think the non-memcpy route is preferable as it give the compiler
|
||||
// a chance to optimize constant values Also memcpy would ignoring the
|
||||
@@ -1252,8 +1278,7 @@ BatchedBackendLLVM::llvm_assign_initial_value(
|
||||
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());
|
||||
data_type = ll.type_ustring();
|
||||
} else if (elemtype.is_int()) {
|
||||
ptr_type = ll.type_int_ptr();
|
||||
data_type = ll.type_int();
|
||||
@@ -1740,16 +1765,17 @@ BatchedBackendLLVM::build_llvm_init()
|
||||
OSL_ASSERT(m_library_selector);
|
||||
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
|
||||
}));
|
||||
ll.current_function(
|
||||
ll.make_function(unique_name, false,
|
||||
ll.type_void(), // return type
|
||||
{
|
||||
llvm_type_sg_ptr(), llvm_type_groupdata_ptr(),
|
||||
ll.type_void_ptr(), // wide_shader_index
|
||||
ll.type_void_ptr(), // userdata_base_ptr
|
||||
ll.type_void_ptr(), // output_base_ptr
|
||||
ll.type_int(), // mask
|
||||
ll.type_void_ptr(), // FIXME: interactive params
|
||||
}));
|
||||
|
||||
if (ll.debug_is_enabled()) {
|
||||
ustring file_name
|
||||
@@ -1759,14 +1785,20 @@ 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_shaderglobals_ptr = ll.current_function_arg(0); //arg_it++;
|
||||
m_llvm_shaderglobals_ptr->setName("shaderglobals_ptr");
|
||||
m_llvm_groupdata_ptr = ll.current_function_arg(1); //arg_it++;
|
||||
m_llvm_groupdata_ptr->setName("groupdata_ptr");
|
||||
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++;
|
||||
m_llvm_wide_shadeindex_ptr->setName("shadeindex");
|
||||
m_llvm_userdata_base_ptr = ll.current_function_arg(3); //arg_it++;
|
||||
m_llvm_userdata_base_ptr->setName("userdata_base_ptr");
|
||||
m_llvm_output_base_ptr = ll.current_function_arg(4); //arg_it++;
|
||||
m_llvm_output_base_ptr->setName("output_base_ptr");
|
||||
llvm::Value* llvm_initial_shader_mask_value = ll.current_function_arg(5);
|
||||
llvm_initial_shader_mask_value->setName("initial_shader_mask");
|
||||
m_llvm_interactive_params_ptr = ll.current_function_arg(6); //arg_it++;
|
||||
m_llvm_interactive_params_ptr->setName("interactive_params_ptr");
|
||||
|
||||
// New function, reset temp matrix pointer
|
||||
m_llvm_temp_wide_matrix_ptr = nullptr;
|
||||
@@ -1815,6 +1847,7 @@ BatchedBackendLLVM::build_llvm_init()
|
||||
FOREACH_PARAM(Symbol & sym, gi)
|
||||
{
|
||||
if (sym.typespec().is_closure_based()) {
|
||||
OSL_ASSERT(sym.is_varying());
|
||||
int arraylen = std::max(1, sym.typespec().arraylength());
|
||||
llvm::Value* val = ll.constant_ptr(NULL, ll.type_void_ptr());
|
||||
if (!sym.is_uniform())
|
||||
@@ -1876,10 +1909,11 @@ BatchedBackendLLVM::build_llvm_instance(bool groupentry)
|
||||
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.type_void_ptr(), // wide_shader_index
|
||||
ll.type_void_ptr(), // userdata_base_ptr
|
||||
ll.type_void_ptr(), // output_base_ptr
|
||||
ll.type_int(), // mask
|
||||
ll.type_void_ptr(), // FIXME: interactive params
|
||||
}));
|
||||
|
||||
if (ll.debug_is_enabled()) {
|
||||
@@ -1889,14 +1923,20 @@ BatchedBackendLLVM::build_llvm_instance(bool groupentry)
|
||||
}
|
||||
|
||||
// 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_shaderglobals_ptr = ll.current_function_arg(0); //arg_it++;
|
||||
m_llvm_shaderglobals_ptr->setName("shaderglobals_ptr");
|
||||
m_llvm_groupdata_ptr = ll.current_function_arg(1); //arg_it++;
|
||||
m_llvm_groupdata_ptr->setName("groupdata_ptr");
|
||||
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++;
|
||||
m_llvm_wide_shadeindex_ptr->setName("shadeindex");
|
||||
m_llvm_userdata_base_ptr = ll.current_function_arg(3); //arg_it++;
|
||||
m_llvm_userdata_base_ptr->setName("userdata_base_ptr");
|
||||
m_llvm_output_base_ptr = ll.current_function_arg(4); //arg_it++;
|
||||
m_llvm_output_base_ptr->setName("output_base_ptr");
|
||||
llvm::Value* llvm_initial_shader_mask_value = ll.current_function_arg(5);
|
||||
llvm_initial_shader_mask_value->setName("initial_shader_mask");
|
||||
m_llvm_interactive_params_ptr = ll.current_function_arg(6); //arg_it++;
|
||||
m_llvm_interactive_params_ptr->setName("interactive_params_ptr");
|
||||
|
||||
// New function, reset temp matrix pointer
|
||||
m_llvm_temp_wide_matrix_ptr = nullptr;
|
||||
@@ -2071,10 +2111,12 @@ BatchedBackendLLVM::build_llvm_instance(bool groupentry)
|
||||
&& !s.renderer_output())
|
||||
continue;
|
||||
// Skip if it's an interpolated (userdata) parameter and we're
|
||||
// initializing them lazily.
|
||||
if (s.symtype() == SymTypeParam && !s.lockgeom()
|
||||
&& !s.typespec().is_closure() && !s.connected()
|
||||
&& !s.connected_down() && shadingsys().lazy_userdata())
|
||||
// initializing them lazily, or if it's an interactively-adjusted
|
||||
// parameter.
|
||||
if (s.symtype() == SymTypeParam && !s.typespec().is_closure()
|
||||
&& !s.connected() && !s.connected_down()
|
||||
&& (s.interactive()
|
||||
|| (s.interpolated() && shadingsys().lazy_userdata())))
|
||||
continue;
|
||||
// Set initial value for params (may contain init ops)
|
||||
llvm_assign_initial_value(s, llvm_initial_shader_mask_value);
|
||||
@@ -2097,6 +2139,7 @@ BatchedBackendLLVM::build_llvm_instance(bool groupentry)
|
||||
// records for each.
|
||||
find_basic_blocks();
|
||||
find_conditionals();
|
||||
m_call_layers_inserted.clear();
|
||||
|
||||
build_llvm_code(inst()->maincodebegin(), inst()->maincodeend());
|
||||
|
||||
@@ -2693,21 +2736,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.
|
||||
@@ -2716,7 +2747,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()) {
|
||||
|
||||
@@ -41,7 +41,7 @@ template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::get_matrix(BatchedShaderGlobals* bsg,
|
||||
Masked<Matrix44> wresult,
|
||||
Wide<const ustring> wfrom,
|
||||
Wide<const ustringhash> wfrom,
|
||||
Wide<const float> wtime)
|
||||
{
|
||||
OSL_ASSERT(
|
||||
@@ -70,7 +70,7 @@ template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::get_inverse_matrix(BatchedShaderGlobals* bsg,
|
||||
Masked<Matrix44> wresult,
|
||||
ustring to,
|
||||
ustringhash to,
|
||||
Wide<const float> wtime)
|
||||
{
|
||||
OSL_ASSERT(
|
||||
@@ -85,7 +85,7 @@ template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::get_inverse_matrix(BatchedShaderGlobals* bsg,
|
||||
Masked<Matrix44> wresult,
|
||||
Wide<const ustring> wto,
|
||||
Wide<const ustringhash> wto,
|
||||
Wide<const float> wtime)
|
||||
{
|
||||
OSL_ASSERT(
|
||||
@@ -109,15 +109,14 @@ template<int WidthT>
|
||||
TextureSystem::TextureHandle*
|
||||
BatchedRendererServices<WidthT>::resolve_udim_uniform(
|
||||
BatchedShaderGlobals* bsg, TexturePerthread* texture_thread_info,
|
||||
ustring filename, TextureSystem::TextureHandle* texture_handle, float S,
|
||||
ustringhash filename, TextureSystem::TextureHandle* texture_handle, float S,
|
||||
float T)
|
||||
{
|
||||
if (!texture_thread_info)
|
||||
texture_thread_info = bsg->uniform.context->texture_thread_info();
|
||||
if (!texture_handle)
|
||||
texture_handle = texturesys()->get_texture_handle(filename,
|
||||
texture_handle = texturesys()->get_texture_handle(ustring_from(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.
|
||||
@@ -131,9 +130,9 @@ BatchedRendererServices<WidthT>::resolve_udim_uniform(
|
||||
udim_handle = texture_handle;
|
||||
}
|
||||
return udim_handle;
|
||||
} else
|
||||
#endif
|
||||
} else {
|
||||
return texture_handle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -142,16 +141,15 @@ template<int WidthT>
|
||||
void
|
||||
BatchedRendererServices<WidthT>::resolve_udim(
|
||||
BatchedShaderGlobals* bsg, TexturePerthread* texture_thread_info,
|
||||
ustring filename, TextureSystem::TextureHandle* texture_handle,
|
||||
ustringhash filename, TextureSystem::TextureHandle* texture_handle,
|
||||
Wide<const float> wS, Wide<const float> wT,
|
||||
Masked<TextureSystem::TextureHandle*> wresult)
|
||||
{
|
||||
if (!texture_thread_info)
|
||||
texture_thread_info = bsg->uniform.context->texture_thread_info();
|
||||
if (!texture_handle)
|
||||
texture_handle = texturesys()->get_texture_handle(filename,
|
||||
texture_handle = texturesys()->get_texture_handle(ustring_from(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.
|
||||
@@ -167,9 +165,9 @@ BatchedRendererServices<WidthT>::resolve_udim(
|
||||
}
|
||||
wresult[l] = udim_handle;
|
||||
});
|
||||
} else
|
||||
#endif
|
||||
} else {
|
||||
assign_all(wresult, texture_handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -178,17 +176,17 @@ template<int WidthT>
|
||||
bool
|
||||
BatchedRendererServices<WidthT>::get_texture_info_uniform(
|
||||
BatchedShaderGlobals* bsg, TexturePerthread* texture_thread_info,
|
||||
ustring filename, TextureSystem::TextureHandle* texture_handle,
|
||||
int subimage, ustring dataname, RefData val)
|
||||
ustringhash filename, TextureSystem::TextureHandle* texture_handle,
|
||||
int subimage, ustringhash dataname, RefData val)
|
||||
{
|
||||
if (!texture_thread_info)
|
||||
texture_thread_info = bsg->uniform.context->texture_thread_info();
|
||||
if (!texture_handle)
|
||||
texture_handle = texturesys()->get_texture_handle(filename,
|
||||
texture_handle = texturesys()->get_texture_handle(ustring_from(filename),
|
||||
texture_thread_info);
|
||||
bool status = texturesys()->get_texture_info(texture_handle, NULL, subimage,
|
||||
dataname, val.type(),
|
||||
val.ptr());
|
||||
ustring_from(dataname),
|
||||
val.type(), val.ptr());
|
||||
|
||||
if (!status) {
|
||||
std::string err = texturesys()->geterror();
|
||||
@@ -205,7 +203,7 @@ BatchedRendererServices<WidthT>::get_texture_info_uniform(
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::texture(
|
||||
ustring filename, TextureSystem::TextureHandle* texture_handle,
|
||||
ustringhash filename, TextureSystem::TextureHandle* texture_handle,
|
||||
TextureSystem::Perthread* texture_thread_info,
|
||||
const BatchedTextureOptions& options, BatchedShaderGlobals* bsg,
|
||||
Wide<const float> ws, Wide<const float> wt, Wide<const float> wdsdx,
|
||||
@@ -223,7 +221,7 @@ BatchedRendererServices<WidthT>::texture(
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::texture3d(
|
||||
ustring filename, TextureSystem::TextureHandle* texture_handle,
|
||||
ustringhash filename, TextureSystem::TextureHandle* texture_handle,
|
||||
TextureSystem::Perthread* texture_thread_info,
|
||||
const BatchedTextureOptions& options, BatchedShaderGlobals* bsg,
|
||||
Wide<const Vec3> wP, Wide<const Vec3> wdPdx, Wide<const Vec3> wdPdy,
|
||||
@@ -240,7 +238,7 @@ BatchedRendererServices<WidthT>::texture3d(
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::environment(
|
||||
ustring filename, TextureSystem::TextureHandle* texture_handle,
|
||||
ustringhash filename, TextureSystem::TextureHandle* texture_handle,
|
||||
TextureSystem::Perthread* texture_thread_info,
|
||||
const BatchedTextureOptions& options, BatchedShaderGlobals* bsg,
|
||||
Wide<const Vec3> wR, Wide<const Vec3> wdRdx, Wide<const Vec3> wdRdy,
|
||||
@@ -257,7 +255,7 @@ BatchedRendererServices<WidthT>::environment(
|
||||
template<int WidthT>
|
||||
void
|
||||
BatchedRendererServices<WidthT>::pointcloud_search(
|
||||
BatchedShaderGlobals* bsg, ustring filename, const void* wcenter,
|
||||
BatchedShaderGlobals* bsg, ustringhash filename, const void* wcenter,
|
||||
Wide<const float> wradius, int max_points, bool sort,
|
||||
PointCloudSearchResults& results)
|
||||
{
|
||||
@@ -271,8 +269,8 @@ BatchedRendererServices<WidthT>::pointcloud_search(
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::pointcloud_get(
|
||||
BatchedShaderGlobals* bsg, ustring filename, Wide<const int[]> windices,
|
||||
Wide<const int> wnum_points, ustring attr_name, MaskedData wout_data)
|
||||
BatchedShaderGlobals* bsg, ustringhash filename, Wide<const int[]> windices,
|
||||
Wide<const int> wnum_points, ustringhash attr_name, MaskedData wout_data)
|
||||
{
|
||||
OSL_ASSERT(
|
||||
0
|
||||
@@ -285,7 +283,7 @@ BatchedRendererServices<WidthT>::pointcloud_get(
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::pointcloud_write(
|
||||
BatchedShaderGlobals* bsg, ustring filename, Wide<const OSL::Vec3> wpos,
|
||||
BatchedShaderGlobals* bsg, ustringhash filename, Wide<const OSL::Vec3> wpos,
|
||||
int nattribs, const ustring* attr_names, const TypeDesc* attr_types,
|
||||
const void** pointers_to_wide_attr_value, Mask mask)
|
||||
{
|
||||
@@ -314,8 +312,9 @@ BatchedRendererServices<WidthT>::trace(
|
||||
template<int WidthT>
|
||||
void
|
||||
BatchedRendererServices<WidthT>::getmessage(BatchedShaderGlobals* bsg,
|
||||
Masked<int> wresult, ustring source,
|
||||
ustring name, MaskedData wval)
|
||||
Masked<int> wresult,
|
||||
ustringhash source,
|
||||
ustringhash name, MaskedData wval)
|
||||
{
|
||||
// Currently this code path should only be followed when source == "trace"
|
||||
OSL_DASSERT(wresult.mask() == wval.mask());
|
||||
|
||||
+282
-278
@@ -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, "iiisXsisiss")
|
||||
#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, "iiisXsisiss")
|
||||
DECL(osl_naninf_check, "xiXiXsisiis")
|
||||
DECL(osl_uninit_check, "xLXXsisissisisii")
|
||||
DECL(osl_get_attribute, "iXissiiLX")
|
||||
DECL(osl_bind_interpolated_param, "iXsLiXiXiXi")
|
||||
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)
|
||||
@@ -249,142 +248,147 @@ UNARY_OP_IMPL(log10)
|
||||
UNARY_OP_IMPL(exp)
|
||||
UNARY_OP_IMPL(exp2)
|
||||
UNARY_OP_IMPL(expm1)
|
||||
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")
|
||||
BINARY_OP_IMPL(pow)
|
||||
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_fmod_vvf, "xXXf")
|
||||
DECL(osl_fmod_dvdvdf, "xXXX")
|
||||
DECL(osl_fmod_dvvdf, "xXXX")
|
||||
DECL(osl_fmod_dvdvf, "xXXf")
|
||||
|
||||
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, "is");
|
||||
DECL(osl_texture_decode_interpmode, "is");
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -253,7 +253,7 @@ 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.
|
||||
@@ -315,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), "xXsLXisii")
|
||||
DECL(__OSL_MASKED_OP2(setmessage, Ws, WX), "xXXLXisii")
|
||||
|
||||
DECL(__OSL_OP(blackbody_vf), "xXXf")
|
||||
@@ -362,26 +362,26 @@ DECL(__OSL_OP(dict_value), "iXiXLX")
|
||||
DECL(__OSL_MASKED_OP(dict_value), "xXXXXLXi")
|
||||
|
||||
|
||||
DECL(__OSL_OP(raytype_name), "iXX")
|
||||
DECL(__OSL_OP(raytype_name), "iXs")
|
||||
DECL(__OSL_MASKED_OP(raytype_name), "xXXXi")
|
||||
DECL(__OSL_OP(naninf_check), "xiXiXXiXiiX")
|
||||
DECL(__OSL_MASKED_OP1(naninf_check_offset, i), "xiiXiXXiXiiX")
|
||||
DECL(__OSL_MASKED_OP1(naninf_check_offset, Wi), "xiiXiXXiXXiX")
|
||||
DECL(__OSL_OP(range_check), "iiiXXXiXiXX")
|
||||
DECL(__OSL_MASKED_OP(range_check), "xXiiXXXiXiXX")
|
||||
DECL(__OSL_OP2(uninit_check_values_offset, X, i), "xLXXXiXiXXiXiXii")
|
||||
DECL(__OSL_MASKED_OP2(uninit_check_values_offset, X, Wi), "xiLXXXiXiXXiXiXXi")
|
||||
DECL(__OSL_MASKED_OP2(uninit_check_values_offset, WX, i), "xiLXXXiXiXXiXiXii")
|
||||
DECL(__OSL_MASKED_OP2(uninit_check_values_offset, WX, Wi), "xiLXXXiXiXXiXiXXi")
|
||||
DECL(__OSL_OP(naninf_check), "xiXiXsisiis")
|
||||
DECL(__OSL_MASKED_OP1(naninf_check_offset, i), "xiiXiXsisiis")
|
||||
DECL(__OSL_MASKED_OP1(naninf_check_offset, Wi), "xiiXiXsisXis")
|
||||
DECL(__OSL_OP(range_check), "iiisXsisiss")
|
||||
DECL(__OSL_MASKED_OP(range_check), "xXiisXsisiss")
|
||||
DECL(__OSL_OP2(uninit_check_values_offset, X, i), "xLXXsisissisisii")
|
||||
DECL(__OSL_MASKED_OP2(uninit_check_values_offset, X, Wi), "xiLXXsisissisisXi")
|
||||
DECL(__OSL_MASKED_OP2(uninit_check_values_offset, WX, i), "xiLXXsisissisisii")
|
||||
DECL(__OSL_MASKED_OP2(uninit_check_values_offset, WX, Wi), "xiLXXsisissisisXi")
|
||||
|
||||
DECL(__OSL_OP1(get_attribute, s), "iXiXXiiXXi")
|
||||
DECL(__OSL_MASKED_OP1(get_attribute, Ws), "iXiXXiiXXi")
|
||||
DECL(__OSL_OP(get_attribute_uniform), "iXiXXiiXX")
|
||||
DECL(__OSL_OP1(get_attribute, s), "iXissiiXXi")
|
||||
DECL(__OSL_MASKED_OP1(get_attribute, Ws), "iXisXiiXXi")
|
||||
DECL(__OSL_OP(get_attribute_uniform), "iXissiiXX")
|
||||
|
||||
// TODO: shouldn't bind_interpolated_param be MASKED? change name to reflect
|
||||
DECL(__OSL_OP(bind_interpolated_param), "iXXLiXiXiXii")
|
||||
DECL(__OSL_OP(bind_interpolated_param), "iXsLiXiXiXii")
|
||||
|
||||
//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
|
||||
|
||||
@@ -8,9 +8,10 @@
|
||||
|
||||
#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"
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2410,21 +2410,22 @@ DECLFOLDER(constfold_gettextureinfo)
|
||||
ustring filename = Filename.get_string();
|
||||
ustring dataname = Dataname.get_string();
|
||||
TypeDesc t = Data.typespec().simpletype();
|
||||
void* mydata = OIIO_ALLOCA(char, t.size());
|
||||
void* mydata = OSL_ALLOCA(char, t.size());
|
||||
// FIXME(ptex) -- exclude folding of ptex, since these things
|
||||
// can vary per face.
|
||||
ustring errormessage;
|
||||
ustringhash em;
|
||||
int result = rop.renderer()->get_texture_info(
|
||||
filename, nullptr, rop.shadingcontext()->texture_thread_info(),
|
||||
rop.shadingcontext(), 0 /* TODO: subimage? */, dataname, t, mydata,
|
||||
&errormessage);
|
||||
&em);
|
||||
ustring errormessage = ustring_from(em);
|
||||
// Now we turn
|
||||
// gettextureinfo result filename dataname data
|
||||
// into this for success:
|
||||
// assign data [retrieved values]
|
||||
// assign result 1
|
||||
// into this for failure:
|
||||
// error "%s" errormesage
|
||||
// error "%s" errormessage
|
||||
// assign result 0
|
||||
if (result) {
|
||||
int oldresultarg = rop.inst()->args()[op.firstarg() + 0];
|
||||
@@ -2776,7 +2777,7 @@ DECLFOLDER(constfold_pointcloud_get)
|
||||
return 0;
|
||||
|
||||
// Must transfer to size_t array
|
||||
size_t* indices = OIIO_ALLOCA(size_t, count);
|
||||
size_t* indices = OSL_ALLOCA(size_t, count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
indices[i] = Indices.get_int(i);
|
||||
|
||||
|
||||
+13
-10
@@ -128,11 +128,12 @@ ShadingContext::execute_init(ShaderGroup& sgroup, int shadeindex,
|
||||
RunLLVMGroupFunc run_func = sgroup.llvm_compiled_init();
|
||||
if (!run_func)
|
||||
return false;
|
||||
ssg.context = this;
|
||||
ssg.renderer = renderer();
|
||||
ssg.Ci = NULL;
|
||||
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);
|
||||
shadeindex, sgroup.interactive_arena_ptr());
|
||||
}
|
||||
|
||||
if (profile)
|
||||
@@ -159,8 +160,8 @@ ShadingContext::execute_layer(int shadeindex, ShaderGlobals& ssg,
|
||||
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,
|
||||
group()->interactive_arena_ptr());
|
||||
|
||||
if (profile)
|
||||
m_ticks += timer.ticks();
|
||||
@@ -320,7 +321,8 @@ ShadingContext::Batched<WidthT>::execute_init(
|
||||
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());
|
||||
userdata_base_ptr, output_base_ptr, run_mask.value(),
|
||||
sgroup.interactive_arena_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,7 +361,8 @@ ShadingContext::Batched<WidthT>::execute_layer(
|
||||
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());
|
||||
userdata_base_ptr, output_base_ptr, run_mask.value(),
|
||||
group()->interactive_arena_ptr());
|
||||
}
|
||||
|
||||
if (profile)
|
||||
@@ -624,8 +627,8 @@ 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 dest_derivs, ustringhash obj_name,
|
||||
ustringhash attr_name, int array_lookup,
|
||||
int index, TypeDesc attr_type,
|
||||
void* attr_dest)
|
||||
{
|
||||
|
||||
@@ -115,7 +115,7 @@ private:
|
||||
};
|
||||
|
||||
typedef std::unordered_map<Query, QueryResult, QueryHash> QueryMap;
|
||||
typedef std::unordered_map<ustring, int, ustringHash> DocMap;
|
||||
typedef std::unordered_map<ustring, int> DocMap;
|
||||
|
||||
ShadingContext* m_context; // back-pointer to shading context
|
||||
|
||||
|
||||
+84
-57
@@ -182,7 +182,8 @@ compatible_param(const TypeDesc& a, const TypeDesc& b)
|
||||
|
||||
|
||||
void
|
||||
ShaderInstance::parameters(const ParamValueList& params)
|
||||
ShaderInstance::parameters(const ParamValueList& params,
|
||||
cspan<ParamHints> hints)
|
||||
{
|
||||
// Seed the params with the master's defaults
|
||||
m_iparams = m_master->m_idefaults;
|
||||
@@ -195,11 +196,13 @@ ShaderInstance::parameters(const ParamValueList& params)
|
||||
// on the master.
|
||||
for (int i = 0, e = (int)m_instoverrides.size(); i < e; ++i) {
|
||||
Symbol* sym = master()->symbol(i);
|
||||
m_instoverrides[i].lockgeom(sym->lockgeom());
|
||||
m_instoverrides[i].interpolated(sym->interpolated());
|
||||
m_instoverrides[i].interactive(sym->interactive());
|
||||
m_instoverrides[i].dataoffset(sym->dataoffset());
|
||||
}
|
||||
|
||||
for (auto&& p : params) {
|
||||
for (size_t pi = 0; pi < params.size(); ++pi) {
|
||||
const ParamValue& p(params[pi]);
|
||||
if (p.name().size() == 0)
|
||||
continue; // skip empty names
|
||||
int i = findparam(p.name());
|
||||
@@ -244,22 +247,7 @@ ShaderInstance::parameters(const ParamValueList& params)
|
||||
valuetype = TypeDesc::FLOAT;
|
||||
}
|
||||
|
||||
// Relaxed rules just look to see that the types are isomorphic to each other (ie: same number of base values)
|
||||
// Note that:
|
||||
// * basetypes must match exactly (int vs float vs string)
|
||||
// * valuetype cannot be unsized (we must know the concrete number of values)
|
||||
// * if paramtype is sized (or not an array) just check for the total number of entries
|
||||
// * if paramtype is unsized (shader writer is flexible about how many values come in) -- make sure we are a multiple of the target type
|
||||
// * allow a single float setting a vec3 (or equivalent)
|
||||
if (!(valuetype.basetype == paramtype.basetype
|
||||
&& !valuetype.is_unsized_array()
|
||||
&& ((!paramtype.is_unsized_array()
|
||||
&& valuetype.basevalues() == paramtype.basevalues())
|
||||
|| (paramtype.is_unsized_array()
|
||||
&& valuetype.basevalues() % paramtype.aggregate
|
||||
== 0)
|
||||
|| (paramtype.is_vec3()
|
||||
&& valuetype == TypeDesc::FLOAT)))) {
|
||||
if (!relaxed_equivalent(sm_typespec, valuetype)) {
|
||||
// We are being very relaxed in this mode, so if the user _still_ got it wrong
|
||||
// something more serious is at play and we should treat it as an error.
|
||||
shadingsys().errorfmt(
|
||||
@@ -277,13 +265,14 @@ ShaderInstance::parameters(const ParamValueList& params)
|
||||
// Mark that the override as an instance value
|
||||
so->valuesource(Symbol::InstanceVal);
|
||||
|
||||
// Lock the param against geometric primitive overrides if the
|
||||
// master thinks it was so locked, AND the Parameter() call
|
||||
// didn't specify lockgeom=false (which would be indicated by
|
||||
// the parameter's interpolation being non-CONSTANT).
|
||||
bool lockgeom = (sm->lockgeom()
|
||||
&& p.interp() == ParamValue::INTERP_CONSTANT);
|
||||
so->lockgeom(lockgeom);
|
||||
// Pass on any interpolated or interactive hints.
|
||||
auto hint = hints[pi];
|
||||
so->interpolated(sm->interpolated()
|
||||
|| (hint & ParamHints::interpolated)
|
||||
== ParamHints::interpolated);
|
||||
so->interactive((hint & ParamHints::interactive)
|
||||
== ParamHints::interactive);
|
||||
bool lockgeom = !so->interpolated() && !so->interactive();
|
||||
|
||||
OSL_DASSERT(so->dataoffset() == sm->dataoffset());
|
||||
so->dataoffset(sm->dataoffset());
|
||||
@@ -301,7 +290,7 @@ ShaderInstance::parameters(const ParamValueList& params)
|
||||
if (paramtype.arraylen < 0) {
|
||||
// An array of definite size was supplied to a parameter
|
||||
// that was an array of indefinite size. Magic! The trick
|
||||
// here is that we need to allocate paramter space at the
|
||||
// here is that we need to allocate parameter space at the
|
||||
// END of the ordinary param storage, since when we assigned
|
||||
// data offsets to each parameter, we didn't know the length
|
||||
// needed to allocate this param in its proper spot.
|
||||
@@ -330,12 +319,19 @@ ShaderInstance::parameters(const ParamValueList& params)
|
||||
// definite length in subsequent rerenders. Don't do that.
|
||||
} else {
|
||||
// If the instance value is the same as the master's default,
|
||||
// just skip the parameter, let it "keep" the default.
|
||||
// Note that this can't/shouldn't happen for the indefinite-
|
||||
// sized array case, which is why we have it in the 'else'
|
||||
// clause of that test.
|
||||
// just skip the parameter, let it "keep" the default by
|
||||
// marking the source as DefaultVal.
|
||||
//
|
||||
// N.B. Beware the situation where it has init ops, and so the
|
||||
// "default value" slot only coincidentally has the same value
|
||||
// as the instance value. We can't mark it as DefaultVal in
|
||||
// that case, because the init ops need to be run.
|
||||
//
|
||||
// Note that this case also can't/shouldn't happen for the
|
||||
// indefinite- sized array case, which is why we have it in
|
||||
// the 'else' clause of that test.
|
||||
void* defaultdata = m_master->param_default_storage(i);
|
||||
if (lockgeom
|
||||
if (lockgeom && !sm->has_init_ops()
|
||||
&& memcmp(defaultdata, data, valuetype.size()) == 0) {
|
||||
// Must reset valuesource to default, in case the parameter
|
||||
// was set already, and now is being changed back to default.
|
||||
@@ -459,11 +455,9 @@ ShaderInstance::evaluate_writes_globals_and_userdata_params()
|
||||
// userdata_params as accurately as we can based on what we know from
|
||||
// the symbol overrides. This is very important to get instance merging
|
||||
// working correctly.
|
||||
int p = 0;
|
||||
for (auto&& s : m_instoverrides) {
|
||||
if (!s.lockgeom())
|
||||
if (s.interpolated())
|
||||
userdata_params(true);
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -501,7 +495,8 @@ ShaderInstance::copy_code_from_master(ShaderGroup& group)
|
||||
si->arraylen(m_instoverrides[i].arraylen());
|
||||
si->valuesource(m_instoverrides[i].valuesource());
|
||||
si->connected_down(m_instoverrides[i].connected_down());
|
||||
si->lockgeom(m_instoverrides[i].lockgeom());
|
||||
si->interpolated(m_instoverrides[i].interpolated());
|
||||
si->interactive(m_instoverrides[i].interactive());
|
||||
si->dataoffset(m_instoverrides[i].dataoffset());
|
||||
si->set_dataptr(SymArena::Absolute, param_storage(i));
|
||||
}
|
||||
@@ -644,10 +639,12 @@ ShaderInstance::mergeable(const ShaderInstance& b,
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
// But still, if they differ in their lockgeom'edness, we can't
|
||||
// merge the instances.
|
||||
if (m_instoverrides[i].lockgeom()
|
||||
!= b.m_instoverrides[i].lockgeom()) {
|
||||
// But still, if they differ in whether they are interpolated or
|
||||
// interactive, we can't merge the instances.
|
||||
if (m_instoverrides[i].interpolated()
|
||||
!= b.m_instoverrides[i].interpolated()
|
||||
|| m_instoverrides[i].interactive()
|
||||
!= b.m_instoverrides[i].interactive()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -663,10 +660,14 @@ ShaderInstance::mergeable(const ShaderInstance& b,
|
||||
continue;
|
||||
if (sym->typespec().is_closure())
|
||||
continue; // Closures can't have instance override values
|
||||
// Even if the symbols' values match now, they might not in the
|
||||
// future with 'interactive' parameters.
|
||||
const Symbol* b_sym = optimized ? b.symbol(i) : b.mastersymbol(i);
|
||||
if ((sym->valuesource() == Symbol::InstanceVal
|
||||
|| sym->valuesource() == Symbol::DefaultVal)
|
||||
&& memcmp(param_storage(i), b.param_storage(i),
|
||||
sym->typespec().simpletype().size())) {
|
||||
&& (memcmp(param_storage(i), b.param_storage(i),
|
||||
sym->typespec().simpletype().size())
|
||||
|| b_sym->interactive())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -731,7 +732,8 @@ ShaderInstance::mergeable(const ShaderInstance& b,
|
||||
|
||||
|
||||
|
||||
ShaderGroup::ShaderGroup(string_view name)
|
||||
ShaderGroup::ShaderGroup(string_view name, ShadingSystemImpl& shadingsys)
|
||||
: m_shadingsys(shadingsys)
|
||||
{
|
||||
m_id = ++(*(atomic_int*)&next_id);
|
||||
if (name.size()) {
|
||||
@@ -744,15 +746,6 @@ ShaderGroup::ShaderGroup(string_view name)
|
||||
|
||||
|
||||
|
||||
ShaderGroup::ShaderGroup(const ShaderGroup& g, string_view name)
|
||||
: ShaderGroup(name) // delegate most of the work
|
||||
{
|
||||
m_num_entry_layers = g.m_num_entry_layers;
|
||||
m_layers = g.m_layers;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ShaderGroup::~ShaderGroup()
|
||||
{
|
||||
#if 0
|
||||
@@ -767,6 +760,11 @@ ShaderGroup::~ShaderGroup()
|
||||
<< "executed on " << executions() << " points\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
// Free any GPU memory associated with this group
|
||||
if (m_device_interactive_arena)
|
||||
shadingsys().renderer()->device_free(
|
||||
m_device_interactive_arena.d_get());
|
||||
}
|
||||
|
||||
|
||||
@@ -819,6 +817,34 @@ ShaderGroup::mark_entry_layer(int layer)
|
||||
|
||||
|
||||
|
||||
void
|
||||
ShaderGroup::setup_interactive_arena(cspan<uint8_t> paramblock)
|
||||
{
|
||||
if (paramblock.size()) {
|
||||
// CPU side
|
||||
m_interactive_arena_size = paramblock.size();
|
||||
m_interactive_arena.reset(new uint8_t[m_interactive_arena_size]);
|
||||
memcpy(m_interactive_arena.get(), paramblock.data(),
|
||||
m_interactive_arena_size);
|
||||
if (shadingsys().use_optix()) {
|
||||
// GPU side
|
||||
RendererServices* rs = shadingsys().renderer();
|
||||
m_device_interactive_arena.reset(reinterpret_cast<uint8_t*>(
|
||||
rs->device_alloc(m_interactive_arena_size)));
|
||||
rs->copy_to_device(m_device_interactive_arena.d_get(),
|
||||
paramblock.data(), m_interactive_arena_size);
|
||||
// print("group {} has device interactive_params set to {:p}\n",
|
||||
// name(), m_device_interactive_arena.d_get());
|
||||
}
|
||||
} else {
|
||||
m_interactive_arena_size = 0;
|
||||
m_interactive_arena.reset();
|
||||
m_device_interactive_arena.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string
|
||||
ShaderGroup::serialize() const
|
||||
{
|
||||
@@ -871,11 +897,12 @@ ShaderGroup::serialize() const
|
||||
OSL_ASSERT_MSG(0, "unknown type for serialization: %s (%s)",
|
||||
type.c_str(), s->typespec().c_str());
|
||||
}
|
||||
bool lockgeom = dstsyms_exist
|
||||
? s->lockgeom()
|
||||
: inst->instoverride(p)->lockgeom();
|
||||
if (!lockgeom)
|
||||
print(out, " [[int lockgeom={}]]", lockgeom);
|
||||
if (dstsyms_exist ? s->interpolated()
|
||||
: inst->instoverride(p)->interpolated())
|
||||
print(out, " [[int interpolated=1]]");
|
||||
if (dstsyms_exist ? s->interactive()
|
||||
: inst->instoverride(p)->interactive())
|
||||
print(out, " [[int interactive=1]]");
|
||||
out << " ;\n";
|
||||
}
|
||||
}
|
||||
|
||||
+1852
-1827
File diff suppressed because it is too large
Load Diff
+665
-600
File diff suppressed because it is too large
Load Diff
+534
-394
File diff suppressed because it is too large
Load Diff
+159
-85
@@ -6,14 +6,14 @@
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
#include <llvm/Pass.h>
|
||||
#include <llvm/IR/Constants.h>
|
||||
#include <llvm/IR/IRBuilder.h>
|
||||
#include <llvm/IR/Function.h>
|
||||
#include <llvm/IR/Type.h>
|
||||
#include <llvm/IR/DerivedTypes.h>
|
||||
#include <llvm/IR/Function.h>
|
||||
#include <llvm/IR/IRBuilder.h>
|
||||
#include <llvm/IR/Instruction.h>
|
||||
#include <llvm/IR/Instructions.h>
|
||||
#include <llvm/IR/Type.h>
|
||||
#include <llvm/Pass.h>
|
||||
#include <llvm/Support/Casting.h>
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
@@ -37,16 +37,18 @@ namespace {
|
||||
// how instruction lowering happens then this pass may not be necessary.
|
||||
// Also if future LLVM version takes on the work of this optimization pass,
|
||||
// then it may be removed.
|
||||
template <int WidthT>
|
||||
template<int WidthT>
|
||||
class PreventBitMasksFromBeingLiveinsToBasicBlocks final
|
||||
: public llvm::FunctionPass
|
||||
{
|
||||
typedef llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter> IRBuilder;
|
||||
: public llvm::FunctionPass {
|
||||
typedef llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>
|
||||
IRBuilder;
|
||||
llvm::Type* m_llvm_mask_type;
|
||||
llvm::Type* m_native_mask_type;
|
||||
llvm::Constant* m_wide_zero_initializer;
|
||||
std::unordered_map<llvm::Instruction*, llvm::Value*> m_native_mask_by_producing_inst;
|
||||
std::unordered_map<llvm::Value*, llvm::Value*> m_llvm_mask_from_livein_by_native_mask;
|
||||
std::unordered_map<llvm::Instruction*, llvm::Value*>
|
||||
m_native_mask_by_producing_inst;
|
||||
std::unordered_map<llvm::Value*, llvm::Value*>
|
||||
m_llvm_mask_from_livein_by_native_mask;
|
||||
std::vector<llvm::Instruction*> m_phiNodesWithNativeMasks;
|
||||
|
||||
public:
|
||||
@@ -57,11 +59,13 @@ public:
|
||||
, m_llvm_mask_type(nullptr)
|
||||
, m_native_mask_type(nullptr)
|
||||
, m_wide_zero_initializer(nullptr)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
bool doInitialization (llvm::Module &M) override {
|
||||
llvm::Type* llvm_type_bool = llvm::Type::getInt1Ty (M.getContext());
|
||||
llvm::Type* llvm_type_int32 = llvm::Type::getInt32Ty (M.getContext());
|
||||
bool doInitialization(llvm::Module& M) override
|
||||
{
|
||||
llvm::Type* llvm_type_bool = llvm::Type::getInt1Ty(M.getContext());
|
||||
llvm::Type* llvm_type_int32 = llvm::Type::getInt32Ty(M.getContext());
|
||||
|
||||
#if OSL_LLVM_VERSION >= 110
|
||||
m_llvm_mask_type = llvm::FixedVectorType::get(llvm_type_bool, WidthT);
|
||||
@@ -72,39 +76,45 @@ public:
|
||||
// what the native mask type should be. And if necessary maintain a
|
||||
// 16 bit and 32 bit native mask representation to be passed as a
|
||||
// livein.
|
||||
m_native_mask_type = llvm::FixedVectorType::get(llvm_type_int32, WidthT);
|
||||
# if OSL_LLVM_VERSION >= 112
|
||||
m_wide_zero_initializer = llvm::ConstantDataVector::getSplat(WidthT,
|
||||
llvm::ConstantInt::get(M.getContext(), llvm::APInt(32,0)));
|
||||
# else
|
||||
m_native_mask_type = llvm::FixedVectorType::get(llvm_type_int32,
|
||||
WidthT);
|
||||
# if OSL_LLVM_VERSION >= 112
|
||||
m_wide_zero_initializer = llvm::ConstantDataVector::getSplat(
|
||||
WidthT, llvm::ConstantInt::get(M.getContext(), llvm::APInt(32, 0)));
|
||||
# else
|
||||
m_wide_zero_initializer = llvm::ConstantVector::getSplat(
|
||||
llvm::ElementCount(WidthT, false),
|
||||
llvm::ConstantInt::get (M.getContext(), llvm::APInt(32,0)));
|
||||
# endif
|
||||
llvm::ElementCount(WidthT, false),
|
||||
llvm::ConstantInt::get(M.getContext(), llvm::APInt(32, 0)));
|
||||
# endif
|
||||
#else
|
||||
m_llvm_mask_type = llvm::VectorType::get(llvm_type_bool, WidthT);
|
||||
m_llvm_mask_type = llvm::VectorType::get(llvm_type_bool, WidthT);
|
||||
m_native_mask_type = llvm::VectorType::get(llvm_type_int32, WidthT);
|
||||
m_wide_zero_initializer = llvm::ConstantVector::getSplat(WidthT, llvm::ConstantInt::get (M.getContext(), llvm::APInt(32,0)));
|
||||
m_wide_zero_initializer = llvm::ConstantVector::getSplat(
|
||||
WidthT, llvm::ConstantInt::get(M.getContext(), llvm::APInt(32, 0)));
|
||||
#endif
|
||||
return false; // I don't think we modified the module
|
||||
return false; // I don't think we modified the module
|
||||
}
|
||||
|
||||
bool runOnFunction(llvm::Function &F) override {
|
||||
OSL_DEV_ONLY(llvm::errs() << ">>>>>>>>>>>>>>>>>>PreventBitMasksFromBeingLiveinsToBasicBlocks<" << WidthT << ">:");
|
||||
bool runOnFunction(llvm::Function& F) override
|
||||
{
|
||||
OSL_DEV_ONLY(
|
||||
llvm::errs()
|
||||
<< ">>>>>>>>>>>>>>>>>>PreventBitMasksFromBeingLiveinsToBasicBlocks<"
|
||||
<< WidthT << ">:");
|
||||
OSL_DEV_ONLY(llvm::errs().write_escaped(F.getName()) << '\n');
|
||||
|
||||
m_native_mask_by_producing_inst.clear();
|
||||
|
||||
bool changed = false;
|
||||
|
||||
for (llvm::BasicBlock &bb : F) {
|
||||
for (llvm::BasicBlock& bb : F) {
|
||||
OSL_DEV_ONLY(llvm::errs() << ">>>>>>>>>Basic Block: ");
|
||||
OSL_DEV_ONLY(llvm::errs().write_escaped(bb.getName()) << '\n');
|
||||
|
||||
m_phiNodesWithNativeMasks.clear();
|
||||
m_llvm_mask_from_livein_by_native_mask.clear();
|
||||
|
||||
for (llvm::Instruction &inst : bb) {
|
||||
for (llvm::Instruction& inst : bb) {
|
||||
// We could possibly identify all the instruction types that
|
||||
// we "think" could be using a mask, but feel just looking
|
||||
// at the operand types is cheaper.
|
||||
@@ -120,21 +130,24 @@ public:
|
||||
// back to llvm masks.
|
||||
IRBuilder builder(&bb);
|
||||
builder.SetInsertPoint(&inst);
|
||||
for (llvm::Instruction* phiNodeWithNativeMask : m_phiNodesWithNativeMasks) {
|
||||
llvm::Value* llvm_mask = builder.CreateICmpSLT (phiNodeWithNativeMask,m_wide_zero_initializer);
|
||||
for (llvm::Instruction* phiNodeWithNativeMask :
|
||||
m_phiNodesWithNativeMasks) {
|
||||
llvm::Value* llvm_mask
|
||||
= builder.CreateICmpSLT(phiNodeWithNativeMask,
|
||||
m_wide_zero_initializer);
|
||||
// Now we need to replace all uses of phiNodeWithNativeMask with our converted llvm mask
|
||||
auto use_iter = phiNodeWithNativeMask->use_begin(),
|
||||
use_end = phiNodeWithNativeMask->use_end();
|
||||
for (; use_iter != use_end;)
|
||||
{
|
||||
llvm::Use &use = *use_iter;
|
||||
use_end = phiNodeWithNativeMask->use_end();
|
||||
for (; use_iter != use_end;) {
|
||||
llvm::Use& use = *use_iter;
|
||||
++use_iter;
|
||||
auto *user = llvm::dyn_cast<llvm::Instruction>(use.getUser());
|
||||
// We need to skip the use wher the user is our conversion to a llvm_mask
|
||||
auto* user = llvm::dyn_cast<llvm::Instruction>(
|
||||
use.getUser());
|
||||
// We need to skip the use where the user is our conversion to a llvm_mask
|
||||
if (user && user == llvm_mask)
|
||||
continue;
|
||||
use.set(llvm_mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_phiNodesWithNativeMasks.clear();
|
||||
@@ -151,7 +164,8 @@ public:
|
||||
bool phiNodeHadOperandReplacedInLastPassOverOperands;
|
||||
|
||||
OSL_DEV_ONLY(llvm::errs() << ">>>>Op: ");
|
||||
OSL_DEV_ONLY(llvm::errs().write_escaped(inst.getOpcodeName()) << '\n');
|
||||
OSL_DEV_ONLY(llvm::errs().write_escaped(inst.getOpcodeName())
|
||||
<< '\n');
|
||||
|
||||
// As we may have multiple operands that need to be replaced
|
||||
// for a phi node, once we discover a qualifying replacement
|
||||
@@ -167,25 +181,32 @@ public:
|
||||
|
||||
// As we could be replacing operands, but not the number of operands
|
||||
// we use index vs. iterator based loop construct
|
||||
for (unsigned operand_i = 0, num_operands = inst.getNumOperands();
|
||||
operand_i != num_operands;
|
||||
++operand_i) {
|
||||
|
||||
llvm::Value *op_val = inst.getOperand (operand_i);
|
||||
for (unsigned operand_i = 0,
|
||||
num_operands = inst.getNumOperands();
|
||||
operand_i != num_operands; ++operand_i) {
|
||||
llvm::Value* op_val = inst.getOperand(operand_i);
|
||||
if (op_val != nullptr) {
|
||||
llvm::Type* op_type = op_val->getType();
|
||||
llvm::Type* op_type = op_val->getType();
|
||||
if (op_type == m_llvm_mask_type) {
|
||||
// See if the value came from an instruction
|
||||
auto *producing_instr = llvm::dyn_cast<llvm::Instruction>(op_val);
|
||||
auto* producing_instr
|
||||
= llvm::dyn_cast<llvm::Instruction>(op_val);
|
||||
if (producing_instr != nullptr) {
|
||||
llvm::BasicBlock* producing_bb = producing_instr->getParent();
|
||||
llvm::BasicBlock* producing_bb
|
||||
= producing_instr->getParent();
|
||||
|
||||
// If a phi node needs to have one operand promoted,
|
||||
// it will need all operands promoted even if they were
|
||||
// produced in the same basic block, so the types match
|
||||
if (phiNodeHadOperandReplaced || producing_bb != &bb) {
|
||||
OSL_DEV_ONLY(llvm::errs() << "Uses llvm mask <" <<WidthT << "xi1> from different Basic Block: ");
|
||||
OSL_DEV_ONLY(llvm::errs().write_escaped(op_val->getName()) << '\n');
|
||||
if (phiNodeHadOperandReplaced
|
||||
|| producing_bb != &bb) {
|
||||
OSL_DEV_ONLY(
|
||||
llvm::errs()
|
||||
<< "Uses llvm mask <" << WidthT
|
||||
<< "xi1> from different Basic Block: ");
|
||||
OSL_DEV_ONLY(llvm::errs().write_escaped(
|
||||
op_val->getName())
|
||||
<< '\n');
|
||||
changed = true;
|
||||
|
||||
// We can't let an unrepresentable data type of <16xi1>, <8xi1> or <4xi1>
|
||||
@@ -195,37 +216,68 @@ public:
|
||||
llvm::Value* native_mask = nullptr;
|
||||
{
|
||||
// We may have already created a native mask for this instruction
|
||||
auto search_result = m_native_mask_by_producing_inst.find(producing_instr);
|
||||
if (search_result == m_native_mask_by_producing_inst.end()) {
|
||||
|
||||
auto search_result
|
||||
= m_native_mask_by_producing_inst
|
||||
.find(producing_instr);
|
||||
if (search_result
|
||||
== m_native_mask_by_producing_inst
|
||||
.end()) {
|
||||
// Scan producing basic block for an existing sign extend instruction
|
||||
// for the producing_instr. As the existence of a basic block means
|
||||
// we most likely have a branch higher up whose test required a sign extend
|
||||
for (llvm::Instruction &other_inst : *producing_bb) {
|
||||
auto *existing_sign_ext = llvm::dyn_cast<llvm::SExtInst>(&other_inst);
|
||||
for (llvm::Instruction&
|
||||
other_inst :
|
||||
*producing_bb) {
|
||||
auto* existing_sign_ext
|
||||
= llvm::dyn_cast<
|
||||
llvm::SExtInst>(
|
||||
&other_inst);
|
||||
if (existing_sign_ext) {
|
||||
OSL_ASSERT(existing_sign_ext->getNumOperands() == 1);
|
||||
llvm::Value *existing_operand = existing_sign_ext->getOperand (0);
|
||||
if (existing_operand == producing_instr) {
|
||||
OSL_ASSERT(existing_sign_ext->getType() == m_native_mask_type);
|
||||
OSL_DEV_ONLY(llvm::errs() << "Using existing sign ext in producing bb\n");
|
||||
OSL_ASSERT(
|
||||
existing_sign_ext
|
||||
->getNumOperands()
|
||||
== 1);
|
||||
llvm::Value*
|
||||
existing_operand
|
||||
= existing_sign_ext
|
||||
->getOperand(
|
||||
0);
|
||||
if (existing_operand
|
||||
== producing_instr) {
|
||||
OSL_ASSERT(
|
||||
existing_sign_ext
|
||||
->getType()
|
||||
== m_native_mask_type);
|
||||
OSL_DEV_ONLY(
|
||||
llvm::errs()
|
||||
<< "Using existing sign ext in producing bb\n");
|
||||
|
||||
native_mask = existing_sign_ext;
|
||||
native_mask
|
||||
= existing_sign_ext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nullptr == native_mask) {
|
||||
IRBuilder builder(producing_bb);
|
||||
builder.SetInsertPoint(&producing_bb->back());
|
||||
IRBuilder builder(
|
||||
producing_bb);
|
||||
builder.SetInsertPoint(
|
||||
&producing_bb->back());
|
||||
|
||||
native_mask = builder.CreateSExt(producing_instr, m_native_mask_type);
|
||||
native_mask
|
||||
= builder.CreateSExt(
|
||||
producing_instr,
|
||||
m_native_mask_type);
|
||||
// NOTE: we did add instructions, but not to the BB we are currently
|
||||
// iterating over instructions
|
||||
}
|
||||
m_native_mask_by_producing_inst.insert(std::make_pair(producing_instr,native_mask));
|
||||
m_native_mask_by_producing_inst
|
||||
.insert(std::make_pair(
|
||||
producing_instr,
|
||||
native_mask));
|
||||
} else {
|
||||
native_mask = search_result->second;
|
||||
native_mask
|
||||
= search_result->second;
|
||||
}
|
||||
}
|
||||
OSL_ASSERT(native_mask);
|
||||
@@ -239,16 +291,26 @@ public:
|
||||
llvm::Value* llvm_mask = nullptr;
|
||||
{
|
||||
// We may have already created a llvm mask in this basic block for the native mask
|
||||
auto search_result = m_llvm_mask_from_livein_by_native_mask.find(native_mask);
|
||||
if (search_result == m_llvm_mask_from_livein_by_native_mask.end()) {
|
||||
auto search_result
|
||||
= m_llvm_mask_from_livein_by_native_mask
|
||||
.find(native_mask);
|
||||
if (search_result
|
||||
== m_llvm_mask_from_livein_by_native_mask
|
||||
.end()) {
|
||||
// Insert the conversion from native to llvm mask
|
||||
// somewhere before the 1st instruction that needs to use it in this basic block
|
||||
IRBuilder builder(&bb);
|
||||
builder.SetInsertPoint(&inst);
|
||||
builder.SetInsertPoint(
|
||||
&inst);
|
||||
|
||||
llvm_mask = builder.CreateICmpSLT (native_mask,m_wide_zero_initializer);
|
||||
llvm_mask = builder.CreateICmpSLT(
|
||||
native_mask,
|
||||
m_wide_zero_initializer);
|
||||
|
||||
m_llvm_mask_from_livein_by_native_mask.insert(std::make_pair(native_mask,llvm_mask));
|
||||
m_llvm_mask_from_livein_by_native_mask
|
||||
.insert(std::make_pair(
|
||||
native_mask,
|
||||
llvm_mask));
|
||||
|
||||
// NOTE: we did add instructions to this bb,
|
||||
// but the should be inserted before the current inst.
|
||||
@@ -257,12 +319,13 @@ public:
|
||||
// iterator should not invalidate the iterator
|
||||
|
||||
} else {
|
||||
llvm_mask = search_result->second;
|
||||
llvm_mask
|
||||
= search_result->second;
|
||||
}
|
||||
}
|
||||
inst.setOperand (operand_i, llvm_mask);
|
||||
inst.setOperand(operand_i,
|
||||
llvm_mask);
|
||||
} else {
|
||||
|
||||
// Phi nodes have to exist at the top of a basic block which precludes
|
||||
// our basic algorithm from just converting the native mask back to a llvm mask
|
||||
// before the phi node.
|
||||
@@ -270,24 +333,37 @@ public:
|
||||
// and insert an instruction to convert it after the block of phi nodes
|
||||
// However, this now means we will need to find all uses of the phi node's
|
||||
// result and replace them with our converted llvm_mask
|
||||
inst.setOperand (operand_i, native_mask);
|
||||
inst.setOperand(operand_i,
|
||||
native_mask);
|
||||
phiNodeHadOperandReplaced = true;
|
||||
phiNodeHadOperandReplacedInLastPassOverOperands = true;
|
||||
phiNodeHadOperandReplacedInLastPassOverOperands
|
||||
= true;
|
||||
}
|
||||
// We should be able to continue iterating over the rest of the operands
|
||||
}
|
||||
} else if (phiNodeHadOperandReplaced) {
|
||||
auto *constant = llvm::dyn_cast<llvm::Constant>(op_val);
|
||||
auto* constant
|
||||
= llvm::dyn_cast<llvm::Constant>(
|
||||
op_val);
|
||||
if (constant) {
|
||||
OSL_DEV_ONLY(llvm::errs() << "Uses constant llvm mask <" <<WidthT << "xi1> \n");
|
||||
OSL_DEV_ONLY(
|
||||
llvm::errs()
|
||||
<< "Uses constant llvm mask <"
|
||||
<< WidthT << "xi1> \n");
|
||||
|
||||
// Should handle promoting whatever the constant value is (most likely zeroinitializer)
|
||||
llvm::ConstantFolder Folder;
|
||||
auto *signExtConstant = Folder.CreateCast(llvm::Instruction::SExt, constant, m_native_mask_type);
|
||||
auto* signExtConstant
|
||||
= Folder.CreateCast(
|
||||
llvm::Instruction::SExt,
|
||||
constant, m_native_mask_type);
|
||||
|
||||
inst.setOperand (operand_i, signExtConstant);
|
||||
inst.setOperand(operand_i,
|
||||
signExtConstant);
|
||||
} else {
|
||||
OSL_ASSERT(0 && "Unhandled/Unexpected llvm mask type");
|
||||
OSL_ASSERT(
|
||||
0
|
||||
&& "Unhandled/Unexpected llvm mask type");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -321,11 +397,9 @@ public:
|
||||
// including this file will need its own static members defined. LLVM will
|
||||
// assign IDs when they get registered, so this initialization value is not
|
||||
// important.
|
||||
template<>
|
||||
char PreventBitMasksFromBeingLiveinsToBasicBlocks<8>::ID = 0;
|
||||
template<> char PreventBitMasksFromBeingLiveinsToBasicBlocks<8>::ID = 0;
|
||||
|
||||
template<>
|
||||
char PreventBitMasksFromBeingLiveinsToBasicBlocks<16>::ID = 0;
|
||||
template<> char PreventBitMasksFromBeingLiveinsToBasicBlocks<16>::ID = 0;
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
|
||||
+2491
-2231
File diff suppressed because it is too large
Load Diff
@@ -72,7 +72,7 @@ private:
|
||||
int m_oso_major, m_oso_minor; ///< oso file format version
|
||||
int m_sym_default_index; ///< Next sym default value to fill in
|
||||
bool m_errors; ///< Did we hit any errors?
|
||||
typedef std::unordered_map<ustring, int, ustringHash> UstringIntMap;
|
||||
typedef std::unordered_map<ustring, int> UstringIntMap;
|
||||
UstringIntMap m_symmap; ///< map sym name to index
|
||||
};
|
||||
|
||||
@@ -171,7 +171,7 @@ OSOReaderToMaster::symbol(SymType symtype, TypeSpec typespec, const char* name_)
|
||||
sym.dataoffset (m_shadingsys.global_heap_offset (sym.name()));
|
||||
}
|
||||
#endif
|
||||
sym.lockgeom(m_shadingsys.lockgeom_default());
|
||||
sym.interpolated(!m_shadingsys.lockgeom_default());
|
||||
m_master->m_symbols.push_back(sym);
|
||||
m_symmap[name] = int(m_master->m_symbols.size()) - 1;
|
||||
// Start the index at which we add specified defaults
|
||||
@@ -419,7 +419,13 @@ OSOReaderToMaster::hint(string_view hintstring)
|
||||
Symbol& sym(m_master->m_symbols.back());
|
||||
if (type == TypeDesc::TypeInt && ident == "lockgeom"
|
||||
&& Strutil::parse_int(h, ival) && ival >= 0)
|
||||
sym.lockgeom(ival);
|
||||
sym.interpolated(!ival); // soft deprecated
|
||||
else if (type == TypeDesc::TypeInt && ident == "interpolated"
|
||||
&& Strutil::parse_int(h, ival) && ival >= 0)
|
||||
sym.interpolated(ival);
|
||||
else if (type == TypeDesc::TypeInt && ident == "interactive"
|
||||
&& Strutil::parse_int(h, ival) && ival >= 0)
|
||||
sym.interactive(ival);
|
||||
else if (type == TypeDesc::TypeInt && ident == "allowconnect"
|
||||
&& Strutil::parse_int(h, ival) && ival >= 0)
|
||||
sym.allowconnect(ival);
|
||||
|
||||
+141
-125
@@ -12,23 +12,23 @@ OSL_NAMESPACE_ENTER
|
||||
|
||||
static ustring udot(".");
|
||||
|
||||
Parser::Parser(const std::vector<ustring> *user_events,
|
||||
const std::vector<ustring> *user_scatterings)
|
||||
Parser::Parser(const std::vector<ustring>* user_events,
|
||||
const std::vector<ustring>* user_scatterings)
|
||||
{
|
||||
m_ingroup = false;
|
||||
m_error = "";
|
||||
m_error = "";
|
||||
|
||||
m_label_position[Labels::CAMERA] = 0;
|
||||
m_label_position[Labels::LIGHT] = 0;
|
||||
m_label_position[Labels::CAMERA] = 0;
|
||||
m_label_position[Labels::LIGHT] = 0;
|
||||
m_label_position[Labels::BACKGROUND] = 0;
|
||||
m_label_position[Labels::VOLUME] = 0;
|
||||
m_label_position[Labels::TRANSMIT] = 0;
|
||||
m_label_position[Labels::REFLECT] = 0;
|
||||
m_label_position[Labels::OBJECT] = 0;
|
||||
m_label_position[Labels::DIFFUSE] = 1;
|
||||
m_label_position[Labels::GLOSSY] = 1;
|
||||
m_label_position[Labels::SINGULAR] = 1;
|
||||
m_label_position[Labels::STRAIGHT] = 1;
|
||||
m_label_position[Labels::VOLUME] = 0;
|
||||
m_label_position[Labels::TRANSMIT] = 0;
|
||||
m_label_position[Labels::REFLECT] = 0;
|
||||
m_label_position[Labels::OBJECT] = 0;
|
||||
m_label_position[Labels::DIFFUSE] = 1;
|
||||
m_label_position[Labels::GLOSSY] = 1;
|
||||
m_label_position[Labels::SINGULAR] = 1;
|
||||
m_label_position[Labels::STRAIGHT] = 1;
|
||||
|
||||
m_basic_labels.insert(Labels::CAMERA);
|
||||
m_basic_labels.insert(Labels::LIGHT);
|
||||
@@ -47,42 +47,40 @@ Parser::Parser(const std::vector<ustring> *user_events,
|
||||
m_minus_stop.insert(Labels::STOP);
|
||||
|
||||
if (user_events)
|
||||
for (size_t i = 0; i < user_events->size(); ++i)
|
||||
{
|
||||
m_label_position[(*user_events)[i]] = 0;
|
||||
m_basic_labels.insert((*user_events)[i]);
|
||||
}
|
||||
if (user_scatterings)
|
||||
for (size_t i = 0; i < user_scatterings->size(); ++i)
|
||||
{
|
||||
m_label_position[(*user_scatterings)[i]] = 1;
|
||||
m_basic_labels.insert((*user_scatterings)[i]);
|
||||
}
|
||||
for (auto&& e : *user_events) {
|
||||
m_label_position[e] = 0;
|
||||
m_basic_labels.insert(e);
|
||||
}
|
||||
if (user_scatterings)
|
||||
for (auto&& s : *user_scatterings) {
|
||||
m_label_position[s] = 1;
|
||||
m_basic_labels.insert(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LPexp *
|
||||
Parser::buildStop(LPexp *etype, LPexp *scatter, const std::list<LPexp*> &custom)
|
||||
LPexp*
|
||||
Parser::buildStop(LPexp* etype, LPexp* scatter, const std::list<LPexp*>& custom)
|
||||
{
|
||||
lpexp::Cat *cat = new lpexp::Cat();
|
||||
lpexp::Cat* cat = new lpexp::Cat();
|
||||
cat->append(etype);
|
||||
cat->append(scatter);
|
||||
for (std::list<LPexp*>::const_iterator i = custom.begin(); i != custom.end(); ++i)
|
||||
cat->append(*i);
|
||||
for (const auto& p : custom)
|
||||
cat->append(p);
|
||||
|
||||
if (custom.size() < 5)
|
||||
cat->append (new lpexp::Repeat (new lpexp::Wildexp (m_basic_labels)));
|
||||
cat->append(new lpexp::Repeat(new lpexp::Wildexp(m_basic_labels)));
|
||||
cat->append(new lpexp::Symbol(Labels::STOP));
|
||||
return cat;
|
||||
}
|
||||
|
||||
|
||||
|
||||
LPexp *
|
||||
LPexp*
|
||||
Parser::parseSymbol()
|
||||
{
|
||||
bool iscustom = false;
|
||||
ustring sym = parseRawSymbol(iscustom);
|
||||
ustring sym = parseRawSymbol(iscustom);
|
||||
if (m_ingroup) {
|
||||
if (sym == udot)
|
||||
return new lpexp::Wildexp(m_minus_stop);
|
||||
@@ -90,25 +88,26 @@ Parser::parseSymbol()
|
||||
return new lpexp::Symbol(sym);
|
||||
} else {
|
||||
if (iscustom) {
|
||||
std::list<LPexp *> custom;
|
||||
std::list<LPexp*> custom;
|
||||
custom.push_back(new lpexp::Symbol(sym));
|
||||
return buildStop(new lpexp::Wildexp(m_minus_stop), new lpexp::Wildexp(m_minus_stop), custom);
|
||||
return buildStop(new lpexp::Wildexp(m_minus_stop),
|
||||
new lpexp::Wildexp(m_minus_stop), custom);
|
||||
} else {
|
||||
LPexp *basics[2] = {NULL, NULL};
|
||||
LPexp* basics[2] = { NULL, NULL };
|
||||
if (sym != ".") {
|
||||
SymbolToInt::const_iterator i = m_label_position.find(sym);
|
||||
if (i == m_label_position.end()) {
|
||||
m_error = std::string("Unrecognized basic label: ") + sym.c_str();
|
||||
return NULL;
|
||||
m_error = fmtformat("Unrecognized basic label: {}", sym);
|
||||
return nullptr;
|
||||
}
|
||||
int pos = i->second;
|
||||
int pos = i->second;
|
||||
basics[pos] = new lpexp::Symbol(sym);
|
||||
}
|
||||
for (int k = 0; k < 2; ++k)
|
||||
if (!basics[k])
|
||||
basics[k] = new lpexp::Wildexp(m_minus_stop);
|
||||
std::list<LPexp *> empty;
|
||||
return buildStop (basics[0], basics[1], empty);
|
||||
std::list<LPexp*> empty;
|
||||
return buildStop(basics[0], basics[1], empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,7 +115,7 @@ Parser::parseSymbol()
|
||||
|
||||
|
||||
ustring
|
||||
Parser::parseRawSymbol(bool &iscustom)
|
||||
Parser::parseRawSymbol(bool& iscustom)
|
||||
{
|
||||
std::string sym;
|
||||
if (head() == '\'') {
|
||||
@@ -144,47 +143,49 @@ Parser::parseRawSymbol(bool &iscustom)
|
||||
|
||||
|
||||
|
||||
LPexp *
|
||||
LPexp*
|
||||
Parser::parseCat()
|
||||
{
|
||||
//lpexp::Cat *cat = new lpexp::Cat();
|
||||
std::vector<LPexp *> explist;
|
||||
std::vector<LPexp*> explist;
|
||||
char endchar;
|
||||
if (head() == '(') {
|
||||
next();
|
||||
endchar = ')';
|
||||
}
|
||||
else endchar = 0;
|
||||
} else
|
||||
endchar = 0;
|
||||
|
||||
while (hasInput() && head() != endchar) {
|
||||
while (hasInput() && head() != endchar) {
|
||||
if (head() == '|') {
|
||||
if (!explist.size()) {
|
||||
m_error = "No left expression to or with |";
|
||||
for (size_t i=0; i < explist.size(); ++i)
|
||||
delete explist[i];
|
||||
return NULL;
|
||||
for (auto& exp : explist)
|
||||
delete exp;
|
||||
return nullptr;
|
||||
}
|
||||
next();
|
||||
LPexp *e = _parse();
|
||||
LPexp* e = _parse();
|
||||
if (error()) {
|
||||
for (size_t i=0; i < explist.size(); ++i)
|
||||
delete explist[i];
|
||||
return NULL;
|
||||
delete e;
|
||||
for (auto& exp : explist)
|
||||
delete exp;
|
||||
return nullptr;
|
||||
}
|
||||
if (explist.back()->getType() == lpexp::OR)
|
||||
((lpexp::Orlist*)explist.back())->append(e);
|
||||
else {
|
||||
lpexp::Orlist *orexp = new lpexp::Orlist();
|
||||
lpexp::Orlist* orexp = new lpexp::Orlist();
|
||||
orexp->append(explist.back());
|
||||
orexp->append(e);
|
||||
explist[explist.size() - 1] = orexp;
|
||||
}
|
||||
} else {
|
||||
LPexp *e = _parse();
|
||||
LPexp* e = _parse();
|
||||
if (error()) {
|
||||
for (size_t i=0; i < explist.size(); ++i)
|
||||
delete explist[i];
|
||||
return NULL;
|
||||
delete e;
|
||||
for (auto& exp : explist)
|
||||
delete exp;
|
||||
return nullptr;
|
||||
}
|
||||
explist.push_back(e);
|
||||
}
|
||||
@@ -193,41 +194,47 @@ Parser::parseCat()
|
||||
next();
|
||||
else if (endchar != 0) {
|
||||
m_error = "Reached end of line looking for )";
|
||||
for (size_t i=0; i < explist.size(); ++i)
|
||||
delete explist[i];
|
||||
return NULL;
|
||||
for (auto& exp : explist)
|
||||
delete exp;
|
||||
return nullptr;
|
||||
}
|
||||
lpexp::Cat *cat = new lpexp::Cat();
|
||||
for (size_t i=0; i < explist.size(); ++i)
|
||||
cat->append(explist[i]);
|
||||
lpexp::Cat* cat = new lpexp::Cat();
|
||||
for (auto& exp : explist)
|
||||
cat->append(exp);
|
||||
return cat;
|
||||
}
|
||||
|
||||
|
||||
|
||||
LPexp *
|
||||
LPexp*
|
||||
Parser::parseGroup()
|
||||
{
|
||||
OSL_DASSERT(head() == '<');
|
||||
if (m_ingroup) {
|
||||
m_error = "No groups allowed inside of groups";
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
int basicpos = 0;
|
||||
LPexp *basics[2] = {NULL, NULL};
|
||||
std::list<LPexp *> custom;
|
||||
#define THROWAWAY() do{\
|
||||
for (int i=0;i<2;++i) if(basics[i]) delete basics[i];\
|
||||
for (std::list<LPexp *>::iterator i = custom.begin();i!=custom.end();++i) delete *i;\
|
||||
m_ingroup = false;\
|
||||
return NULL;\
|
||||
}while(0)
|
||||
int basicpos = 0;
|
||||
LPexp* basics[2] = { nullptr, nullptr };
|
||||
std::list<LPexp*> custom;
|
||||
#define THROWAWAY() \
|
||||
do { \
|
||||
delete basics[0]; \
|
||||
delete basics[1]; \
|
||||
for (auto& p : custom) \
|
||||
delete p; \
|
||||
m_ingroup = false; \
|
||||
return nullptr; \
|
||||
} while (0)
|
||||
|
||||
m_ingroup = true;
|
||||
next();
|
||||
while (hasInput() && head() != '>') {
|
||||
LPexp *e = _parse();
|
||||
if (error()) THROWAWAY();
|
||||
LPexp* e = _parse();
|
||||
if (error()) {
|
||||
delete e;
|
||||
THROWAWAY();
|
||||
}
|
||||
if (basicpos < 2)
|
||||
basics[basicpos++] = e;
|
||||
else
|
||||
@@ -247,65 +254,69 @@ Parser::parseGroup()
|
||||
|
||||
|
||||
|
||||
LPexp *
|
||||
LPexp*
|
||||
Parser::parseNegor()
|
||||
{
|
||||
OSL_DASSERT (head() == '^');
|
||||
OSL_DASSERT(head() == '^');
|
||||
SymbolSet symlist;
|
||||
symlist.insert(Labels::STOP); // never allowed
|
||||
symlist.insert(Labels::STOP); // never allowed
|
||||
int pos = -1;
|
||||
next();
|
||||
while (hasInput() && head() != ']') {
|
||||
bool iscustom = false;
|
||||
ustring sym = parseRawSymbol(iscustom);
|
||||
if (error()) return NULL;
|
||||
ustring sym = parseRawSymbol(iscustom);
|
||||
if (error())
|
||||
return nullptr;
|
||||
symlist.insert(sym);
|
||||
if (iscustom) {
|
||||
if (symlist.size() > 2 && pos != -1)
|
||||
std::cerr << "[pathexp] you are mixing labels of different type in [...]" << std::endl;
|
||||
if (symlist.size() > 2 && pos != -1)
|
||||
std::cerr
|
||||
<< "[pathexp] you are mixing labels of different type in [...]"
|
||||
<< std::endl;
|
||||
pos = -1;
|
||||
} else {
|
||||
SymbolToInt::const_iterator found = m_label_position.find(sym);
|
||||
if (found == m_label_position.end()) {
|
||||
m_error = "Unrecognized basic label";
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
if (symlist.size() > 2 && found->second != pos)
|
||||
std::cerr << "[pathexp] you are mixing labels of different type in [...]" << std::endl;
|
||||
if (symlist.size() > 2 && found->second != pos)
|
||||
std::cerr
|
||||
<< "[pathexp] you are mixing labels of different type in [...]"
|
||||
<< std::endl;
|
||||
pos = found->second;
|
||||
}
|
||||
}
|
||||
if (!hasInput()) {
|
||||
m_error = "Reached end of line looking for ] to end an negative or list'";
|
||||
return NULL;
|
||||
m_error
|
||||
= "Reached end of line looking for ] to end an negative or list'";
|
||||
return nullptr;
|
||||
}
|
||||
if (symlist.size() < 2) {
|
||||
m_error = "Empty or list [^] not allowed";
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
next();
|
||||
lpexp::Wildexp *wildcard = new lpexp::Wildexp(symlist);
|
||||
lpexp::Wildexp* wildcard = new lpexp::Wildexp(symlist);
|
||||
if (m_ingroup)
|
||||
return wildcard;
|
||||
else {
|
||||
std::list<LPexp *> custom;
|
||||
if (pos < 0) { // is a custom label
|
||||
std::list<LPexp*> custom;
|
||||
if (pos < 0) { // is a custom label
|
||||
custom.push_back(wildcard);
|
||||
return buildStop(new lpexp::Wildexp(m_minus_stop), new lpexp::Wildexp(m_minus_stop), custom);
|
||||
return buildStop(new lpexp::Wildexp(m_minus_stop),
|
||||
new lpexp::Wildexp(m_minus_stop), custom);
|
||||
} else {
|
||||
LPexp *basics[2] = {NULL, NULL};
|
||||
basics[pos] = wildcard;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
if (!basics[i])
|
||||
basics[i] = new lpexp::Wildexp(m_minus_stop);
|
||||
return buildStop(basics[0], basics[1], custom);
|
||||
LPexp* w2 = new lpexp::Wildexp(m_minus_stop);
|
||||
return buildStop(pos == 0 ? wildcard : w2, pos == 0 ? w2 : wildcard,
|
||||
custom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
LPexp *
|
||||
LPexp*
|
||||
Parser::parseOrlist()
|
||||
{
|
||||
OSL_DASSERT(head() == '[');
|
||||
@@ -313,19 +324,20 @@ Parser::parseOrlist()
|
||||
if (hasInput() && head() == '^')
|
||||
return parseNegor();
|
||||
else {
|
||||
lpexp::Orlist *orlist = new lpexp::Orlist();
|
||||
lpexp::Orlist* orlist = new lpexp::Orlist();
|
||||
while (hasInput() && head() != ']') {
|
||||
LPexp *e = _parse();
|
||||
LPexp* e = _parse();
|
||||
if (error()) {
|
||||
delete e;
|
||||
delete orlist;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
orlist->append(e);
|
||||
}
|
||||
if (!hasInput()) {
|
||||
m_error = "Reached end of line looking for ] to end an or list";
|
||||
delete orlist;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
next();
|
||||
return orlist;
|
||||
@@ -360,29 +372,32 @@ Parser::parseRange()
|
||||
}
|
||||
next();
|
||||
if (secondnum.size())
|
||||
return std::pair<int, int>(atoi(firstnum.c_str()), atoi(secondnum.c_str()));
|
||||
return std::pair<int, int>(OIIO::Strutil::stoi(firstnum),
|
||||
OIIO::Strutil::stoi(secondnum));
|
||||
else
|
||||
return std::pair<int, int>(atoi(firstnum.c_str()), atoi(firstnum.c_str()));
|
||||
return std::pair<int, int>(OIIO::Strutil::stoi(firstnum),
|
||||
OIIO::Strutil::stoi(firstnum));
|
||||
}
|
||||
|
||||
|
||||
|
||||
LPexp *
|
||||
Parser::parseModifier(LPexp *e)
|
||||
LPexp*
|
||||
Parser::parseModifier(LPexp* e)
|
||||
{
|
||||
if (hasInput()) {
|
||||
if (m_ingroup && (head() == '*' || head() == '{' || head() == '+')) {
|
||||
m_error = std::string("Repetitions not allowed inside '<...>'");
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
if (head() == '*') {
|
||||
next();
|
||||
return new lpexp::Repeat(e);
|
||||
} else if (head() == '{') {
|
||||
std::pair<int, int> range = parseRange();
|
||||
if (error()) return NULL;
|
||||
if (error())
|
||||
return nullptr;
|
||||
if (range.second < 0) {
|
||||
lpexp::Cat *cat = new lpexp::Cat();
|
||||
lpexp::Cat* cat = new lpexp::Cat();
|
||||
cat->append(new lpexp::NRepeat(e, range.first, range.first));
|
||||
cat->append(new lpexp::Repeat(e->clone()));
|
||||
return cat;
|
||||
@@ -390,23 +405,22 @@ Parser::parseModifier(LPexp *e)
|
||||
return new lpexp::NRepeat(e, range.first, range.second);
|
||||
} else if (head() == '+') {
|
||||
next();
|
||||
lpexp::Cat *cat = new lpexp::Cat();
|
||||
lpexp::Cat* cat = new lpexp::Cat();
|
||||
cat->append(e);
|
||||
cat->append(new lpexp::Repeat(e->clone()));
|
||||
return cat;
|
||||
} else
|
||||
return e;
|
||||
}
|
||||
else
|
||||
} else
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
|
||||
LPexp *
|
||||
LPexp*
|
||||
Parser::_parse()
|
||||
{
|
||||
LPexp *e;
|
||||
LPexp* e = nullptr;
|
||||
if (head() == '(')
|
||||
e = parseCat();
|
||||
else if (head() == '[')
|
||||
@@ -415,24 +429,26 @@ Parser::_parse()
|
||||
e = parseGroup();
|
||||
else
|
||||
e = parseSymbol();
|
||||
if (error())
|
||||
return NULL;
|
||||
if (error()) {
|
||||
delete e;
|
||||
return nullptr;
|
||||
}
|
||||
return parseModifier(e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
LPexp *
|
||||
Parser::parse(const char *text)
|
||||
LPexp*
|
||||
Parser::parse(const char* text)
|
||||
{
|
||||
m_error = "";
|
||||
m_text = text;
|
||||
m_pos = 0;
|
||||
m_error = "";
|
||||
m_text = text;
|
||||
m_pos = 0;
|
||||
m_ingroup = false;
|
||||
if (hasInput())
|
||||
return parseCat();
|
||||
else
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+79
-80
@@ -33,92 +33,91 @@ using lpexp::LPexp;
|
||||
/// exp := wildexp | borexp | sorexp | catexp | group | repeat | repeat+ | mnrepeat
|
||||
/// topexp := exp | topexp exp
|
||||
///
|
||||
class Parser
|
||||
{
|
||||
public:
|
||||
class Parser {
|
||||
public:
|
||||
Parser(const std::vector<ustring>* user_events = NULL,
|
||||
const std::vector<ustring>* user_scatterings = NULL);
|
||||
|
||||
Parser(const std::vector<ustring> *user_events = NULL,
|
||||
const std::vector<ustring> *user_scatterings = NULL);
|
||||
/// Parse a string and return the resulting light path expression tree or NULL if failed
|
||||
LPexp* parse(const char* text);
|
||||
|
||||
/// Parse a string and return the resulting light path expression tree or NULL if failed
|
||||
LPexp *parse(const char *text);
|
||||
/// Check for error in the last parsed string
|
||||
bool error() const { return m_error.size() > 0; };
|
||||
/// Get the error string
|
||||
const char* getErrorMsg() const { return m_error.c_str(); };
|
||||
/// Get the position of the string where the error appeared
|
||||
int getErrorPos() const { return m_pos; };
|
||||
|
||||
/// Check for error in the last parsed string
|
||||
bool error()const { return m_error.size() > 0; };
|
||||
/// Get the error string
|
||||
const char *getErrorMsg()const { return m_error.c_str(); };
|
||||
/// Get the position of the string where the error appeared
|
||||
int getErrorPos()const { return m_pos; };
|
||||
private:
|
||||
/// Current char being parsed
|
||||
char head() const { return m_text[m_pos]; };
|
||||
/// Any input (including head) left?
|
||||
bool hasInput() const { return m_text.size() > m_pos; };
|
||||
/// Go to the next char in the string
|
||||
void next() { m_pos++; };
|
||||
|
||||
private:
|
||||
/// build the complete pattern for a pathtracing stop
|
||||
///
|
||||
/// That means the three basic label match expressions, plus those for the custom labels (if any),
|
||||
/// plus an additional wildcard to eat extra custom labels at the end, and finally the stop mark.
|
||||
/// So you provide the regexps for the basic three labels:
|
||||
///
|
||||
/// \param etype Event type (CFVL)
|
||||
/// \param dir Direction (RD)
|
||||
/// \param scatter Scattering type (DGSs)
|
||||
///
|
||||
/// That of course can be wildcards or any other expression willing to match them. And then you can
|
||||
/// provide extra expressions to match the custom labels:
|
||||
///
|
||||
/// \param custom Custom label regexps
|
||||
///
|
||||
/// And the function will automatically add a "[^stop_mark]*stop_mark" at the end.
|
||||
///
|
||||
LPexp* buildStop(LPexp* etype, LPexp* scatter,
|
||||
const std::list<LPexp*>& custom);
|
||||
/// Given that a symbol is ready in head() to parse, parse it
|
||||
LPexp* parseSymbol();
|
||||
/// Given that a symbol is ready in head() to parse, parse it as a ustring
|
||||
/// and report it was a custom symbol in the iscustom flag
|
||||
ustring parseRawSymbol(bool& iscustom);
|
||||
/// Given that the beginning of a concatenation of regexps is ready to
|
||||
/// parse, parse it and it can be optionally be enclosed in parentheses ()
|
||||
LPexp* parseCat();
|
||||
/// Given that a fully qualified group like <.RD'custom'> is ready to parse, parse it
|
||||
LPexp* parseGroup();
|
||||
/// Given that a ^abcde] (note missing [) is ready to parse, parse it
|
||||
LPexp* parseNegor();
|
||||
/// Given that [abcde] is ready to parse, parse it, but if it finds that it was actually
|
||||
/// [^abcd], fall back to parseNegor
|
||||
LPexp* parseOrlist();
|
||||
/// Given that a range like {5,7} or {2,} or {3} is ready to parse, parse it and return
|
||||
/// the range. Second number being -1 if if was {2,} and equals the first if it was {3}
|
||||
std::pair<int, int> parseRange();
|
||||
/// Take an already parsed lpexp and parse its possible modifier (*={}) if present and
|
||||
/// return the new lpexp
|
||||
LPexp* parseModifier(LPexp* e);
|
||||
/// Generic parse whatever comes next (just one item)
|
||||
LPexp* _parse();
|
||||
|
||||
/// Current char being parsed
|
||||
char head()const { return m_text[m_pos]; };
|
||||
/// Any input (including head) left?
|
||||
bool hasInput()const { return m_text.size() > m_pos; };
|
||||
/// Go to the next char in the string
|
||||
void next() { m_pos++; };
|
||||
// error string
|
||||
std::string m_error;
|
||||
// True if we are actually parsing a group <>, since otherwise everything gets
|
||||
// automatically converted to a group, this prevents that happening
|
||||
bool m_ingroup;
|
||||
// maps each basic label to its expected position in the appearance order,
|
||||
// for instance the direction label can't be in the first pos of a group.
|
||||
// This way we know where to put the expression when the user writes just
|
||||
// S, which translates to <..S>
|
||||
SymbolToInt m_label_position;
|
||||
// The set of the basic labels
|
||||
SymbolSet m_basic_labels;
|
||||
// The black list for our wildcards, that have to exclude always the stop mark
|
||||
SymbolSet m_minus_stop;
|
||||
|
||||
/// build the complete pattern for a pathtracing stop
|
||||
///
|
||||
/// That means the three basic label match expressions, plus those for the custom labels (if any),
|
||||
/// plus an additional wildcard to eat extra custom labels at the end, and finally the stop mark.
|
||||
/// So you provide the regexps for the basic three labels:
|
||||
///
|
||||
/// \param etype Event type (CFVL)
|
||||
/// \param dir Direction (RD)
|
||||
/// \param scatter Scattering type (DGSs)
|
||||
///
|
||||
/// That of course can be wildcards or any other expression willing to match them. And then you can
|
||||
/// provide extra expressions to match the custom labels:
|
||||
///
|
||||
/// \param custom Custom label regexps
|
||||
///
|
||||
/// And the function will automatically add a "[^stop_mark]*stop_mark" at the end.
|
||||
///
|
||||
LPexp *buildStop(LPexp *etype, LPexp *scatter, const std::list<LPexp*> &custom);
|
||||
/// Gicen that a symbol is ready in head() to parse, parse it
|
||||
LPexp *parseSymbol();
|
||||
/// Gicen that a symbol is ready in head() to parse, parse it as a ustring
|
||||
/// and report it was a custom symbol in the iscustom flag
|
||||
ustring parseRawSymbol(bool &iscustom);
|
||||
/// Given that the begining of a concatenation of regexps is ready to parse, parse it
|
||||
/// and it can be optionally be enclosed in parentheses ()
|
||||
LPexp *parseCat();
|
||||
/// Given that a fully qualified group like <.RD'custom'> is ready to parse, parse it
|
||||
LPexp *parseGroup();
|
||||
/// Given that a ^abcde] (note missing [) is ready to parse, parse it
|
||||
LPexp *parseNegor();
|
||||
/// Given that [abcde] is ready to parse, parse it, but if it finds that it was actually
|
||||
/// [^abcd], fall back to parseNegor
|
||||
LPexp *parseOrlist();
|
||||
/// Given that a range like {5,7} or {2,} or {3} is ready to parse, parse it and return
|
||||
/// the range. Second number being -1 if if was {2,} and equals the first if it was {3}
|
||||
std::pair<int, int> parseRange();
|
||||
/// Take an already parsed lpexp and parse its possible modifier (*={}) if present and
|
||||
/// return the new lpexp
|
||||
LPexp *parseModifier(LPexp *e);
|
||||
/// Generic parse whatever comes next (just one item)
|
||||
LPexp *_parse();
|
||||
|
||||
// error string
|
||||
std::string m_error;
|
||||
// True if we are actually parsing a group <>, since otherwise everything gets
|
||||
// automatically converted to a group, this prevents that happening
|
||||
bool m_ingroup;
|
||||
// maps each basic label to its expected possition in the appearance order, for instance
|
||||
// the direction label can't be in the first pos of a group. This way we know where to put the
|
||||
// expression when the user writes just S, which translates to <..S>
|
||||
SymbolToInt m_label_position;
|
||||
// The set of the basic labels
|
||||
SymbolSet m_basic_labels;
|
||||
// The black list for our wildcards, that have to exclude always the stop mark
|
||||
SymbolSet m_minus_stop;
|
||||
|
||||
// Current text being parsed
|
||||
std::string m_text;
|
||||
// Current position in the text for head()
|
||||
size_t m_pos;
|
||||
// Current text being parsed
|
||||
std::string m_text;
|
||||
// Current position in the text for head()
|
||||
size_t m_pos;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ lpexp::Symbol::genAuto(NdfAutomata& automata) const
|
||||
lpexp::FirstLast
|
||||
lpexp::Wildexp::genAuto(NdfAutomata& automata) const
|
||||
{
|
||||
// Same as the Symbol lpexp but with a wildcard insted of a symbol
|
||||
// Same as the Symbol lpexp but with a wildcard instead of a symbol
|
||||
NdfAutomata::State* begin = automata.newState();
|
||||
NdfAutomata::State* end = automata.newState();
|
||||
begin->addWildcardTransition(new Wildcard(m_wildcard), end);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user