Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7394f997db | ||
|
|
f7399cee8e | ||
|
|
5dd94cf83d | ||
|
|
78ba7b8f0d | ||
|
|
2dd1883f95 | ||
|
|
410c04ead8 | ||
|
|
a31fba5505 | ||
|
|
98587dfdf8 | ||
|
|
822518f920 | ||
|
|
442b265940 | ||
|
|
09bfd07da7 | ||
|
|
74a53ff545 | ||
|
|
6ae6aef389 | ||
|
|
4a44416156 | ||
|
|
a30b4f4290 | ||
|
|
f31791b23a | ||
|
|
4a9fc9cc87 | ||
|
|
3e6c52366b | ||
|
|
a014de80fe | ||
|
|
e8bbd79b70 | ||
|
|
b75ce26416 | ||
|
|
c193b0753e | ||
|
|
cf725983de | ||
|
|
fc16c8dde2 | ||
|
|
257ca66afe | ||
|
|
fde2a3e5ee | ||
|
|
6906daebdc | ||
|
|
d80bbaa50a | ||
|
|
a1a77b86ab | ||
|
|
267c93104b | ||
|
|
d08f476b3c | ||
|
|
7e9ddadc0f | ||
|
|
0cdf072c22 | ||
|
|
9f033074fa | ||
|
|
6d9db5a761 | ||
|
|
6cd6849580 | ||
|
|
db1dcc1053 | ||
|
|
af15fb3b3d | ||
|
|
9e9acd1592 | ||
|
|
60975da4e2 | ||
|
|
c25cdd4eab | ||
|
|
01284d3af8 | ||
|
|
c0185c1482 | ||
|
|
93866b7c77 | ||
|
|
d9db605bed | ||
|
|
13d2c1914f | ||
|
|
61d10d6aaf | ||
|
|
3601a3fd1c | ||
|
|
2d6210a893 | ||
|
|
26e8da310b | ||
|
|
07b2d9fb15 | ||
|
|
6c06652cfd | ||
|
|
4ee62cd2ef | ||
|
|
68c67633f5 | ||
|
|
6f65f91b49 | ||
|
|
475a109281 | ||
|
|
91eb43227a | ||
|
|
8c2a10268f | ||
|
|
ec8ec11cfd | ||
|
|
61bb9ac11e | ||
|
|
bd7d138f04 | ||
|
|
38015b6be2 | ||
|
|
d42c5d3e1d | ||
|
|
162b355bc8 | ||
|
|
d383680521 | ||
|
|
95ed032dcd | ||
|
|
0c5544e4dc | ||
|
|
54844fe68d | ||
|
|
760561d74e | ||
|
|
354eb8576c | ||
|
|
a725f2b97e | ||
|
|
29e8d0bf50 | ||
|
|
422c0966a6 | ||
|
|
9b706d30bf | ||
|
|
ceda8c0d23 | ||
|
|
b561a67ad1 | ||
|
|
4e34e8dd20 | ||
|
|
905058ee13 | ||
|
|
d3e443b766 | ||
|
|
d860eae924 | ||
|
|
71a518e9a5 | ||
|
|
2bbd6610c8 | ||
|
|
5bcee23e34 |
@@ -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,120 @@
|
||||
# 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:
|
||||
# - master
|
||||
- '*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
|
||||
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"
|
||||
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}}
|
||||
USE_SIMD: ${{matrix.simd}}
|
||||
FMT_VERSION: ${{matrix.fmt_ver}}
|
||||
OPENEXR_VERSION: ${{matrix.openexr_ver}}
|
||||
PYBIND11_VERSION: ${{matrix.pybind11_ver}}
|
||||
PYTHON_VERSION: ${{matrix.python_ver}}
|
||||
# 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: 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"
|
||||
+133
-70
@@ -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:
|
||||
@@ -110,6 +114,7 @@ jobs:
|
||||
batched: b8_AVX2,b8_AVX512,b16_AVX512
|
||||
setenvs: USE_OPENVDB=0
|
||||
- desc: icc/C++17 llvm13 py3.9 boost1.76 exr3.1 oiio-master avx2
|
||||
nametag: linux-icc
|
||||
os: ubuntu-latest
|
||||
vfxyear: 2022
|
||||
vfxsuffix: -clang13
|
||||
@@ -125,7 +130,8 @@ jobs:
|
||||
setenvs: export OSL_CMAKE_FLAGS="-DSTOP_ON_WARNING=OFF -DEXTRA_CPP_ARGS=-fp-model=consistent"
|
||||
OPENIMAGEIO_CMAKE_FLAGS=-DBUILD_FMT_VERSION=7.1.3
|
||||
USE_OPENVDB=0
|
||||
- desc: icx/C++17 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
|
||||
- desc: icx/C++17 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
|
||||
nametag: linux-icx
|
||||
os: ubuntu-latest
|
||||
vfxyear: 2022
|
||||
vfxsuffix: -clang13
|
||||
@@ -151,6 +157,66 @@ jobs:
|
||||
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 +232,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 +271,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}}
|
||||
@@ -242,32 +315,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
|
||||
cxx_compiler: g++-11
|
||||
cxx_std: 17
|
||||
fmt_ver: 8.1.1
|
||||
fmt_ver: 9.1.0
|
||||
openexr_ver: v3.1.5
|
||||
openimageio_ver: master
|
||||
pybind11_ver: v2.9.2
|
||||
python_ver: 3.8
|
||||
pybind11_ver: v2.10.0
|
||||
python_ver: 3.9
|
||||
simd: avx2,f16c
|
||||
batched: b8_AVX2,b8_AVX512,b16_AVX512
|
||||
setenvs: export LLVM_VERSION=13.0.0
|
||||
LLVM_DISTRO_NAME=ubuntu-20.04
|
||||
OPENCOLORIO_VERSION=v2.1.2
|
||||
OPENCOLORIO_VERSION=v2.2.0
|
||||
PUGIXML_VERSION=v1.11.4
|
||||
- desc: bleeding edge gcc11/C++17 llvm14 oiio/ocio/exr/pybind-master boost1.71 py3.9 avx2 batch-b16avx512
|
||||
- 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,7 +348,7 @@ 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
|
||||
@@ -305,13 +378,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 +409,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 +422,71 @@ jobs:
|
||||
macos:
|
||||
name: "${{matrix.os}} appleclang${{matrix.aclang}}/C++${{matrix.cxx_std}} py${{matrix.python_ver}} ${{matrix.desc}}"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- desc: llvm11
|
||||
os: macos-10.15
|
||||
nametag: macos10-py39
|
||||
cxx_std: 14
|
||||
python_ver: 3.9
|
||||
aclang: 12
|
||||
- desc: llvm11
|
||||
- desc: MacOS-11
|
||||
os: macos-11
|
||||
nametag: macos11-py39
|
||||
cc_compiler: /usr/local/opt/llvm@14/bin/clang
|
||||
cxx_compiler: /usr/local/opt/llvm@14/bin/clang++
|
||||
cxx_std: 17
|
||||
python_ver: 3.9
|
||||
python_ver: "3.10"
|
||||
aclang: 13
|
||||
setenvs: export LLVMBREWVER="@14" DO_BREW_UPDATE=1
|
||||
- desc: MacOS-12
|
||||
os: macos-12
|
||||
nametag: macos11-p310
|
||||
cc_compiler: /usr/local/opt/llvm@15/bin/clang
|
||||
cxx_compiler: /usr/local/opt/llvm@15/bin/clang++
|
||||
cxx_std: 17
|
||||
python_ver: "3.10"
|
||||
aclang: 13
|
||||
setenvs: export LLVMBREWVER="@15" DO_BREW_UPDATE=1
|
||||
runs-on: ${{matrix.os}}
|
||||
env:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
CXX: ${{matrix.cxx_compiler}}
|
||||
CC: ${{matrix.cc_compiler}}
|
||||
CMAKE_CXX_STANDARD: ${{matrix.cxx_std}}
|
||||
PYTHON_VERSION: ${{matrix.python_ver}}
|
||||
OPENIMAGEIO_VERSION: ${{matrix.openimageio_ver}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
|
||||
- name: Prepare ccache timestamp
|
||||
id: ccache_cache_keys
|
||||
run: echo "::set-output name=date::`date -u +'%Y-%m-%dT%H:%M:%SZ'`"
|
||||
- name: ccache
|
||||
id: ccache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@c3f1317a9e7b1ef106c153ac8c0f00fed3ddbc0d # v3.0.4
|
||||
with:
|
||||
path: /Users/runner/.ccache
|
||||
key: ${{github.job}}-${{matrix.os}}-${{steps.ccache_cache_keys.outputs.date}}
|
||||
restore-keys: ${{github.job}}-${{matrix.os}}-
|
||||
key: ${{github.job}}-${{matrix.nametag}}-${{steps.ccache_cache_keys.outputs.date}}
|
||||
restore-keys: ${{github.job}}-${{matrix.nametag}}-
|
||||
- name: Build setup
|
||||
run: src/build-scripts/ci-startup.bash
|
||||
run: |
|
||||
${{matrix.setenvs}}
|
||||
src/build-scripts/ci-startup.bash
|
||||
- name: Dependencies
|
||||
run: |
|
||||
source src/build-scripts/install_homebrew_deps.bash
|
||||
# OPENIMAGEIO_CMAKE_FLAGS="-DOIIO_BUILD_TESTS=0 -DUSE_OPENGL=0"
|
||||
# source src/build-scripts/build_openimageio.bash
|
||||
brew install --display-times -q openimageio
|
||||
PYTHONPATH=$PYTHONPATH:/usr/local/python${PYTHON_VERSION}/site-packages
|
||||
if [[ "$OPENIMAGEIO_VERSION" != "" ]] ; then \
|
||||
OPENIMAGEIO_CMAKE_FLAGS="-DOIIO_BUILD_TESTS=0 -DUSE_OPENGL=0" ; \
|
||||
source src/build-scripts/build_openimageio.bash ; \
|
||||
else \
|
||||
brew install --display-times -q openimageio ; \
|
||||
PYTHONPATH=$PYTHONPATH:/usr/local/python${PYTHON_VERSION}/site-packages ; \
|
||||
fi
|
||||
src/build-scripts/save-env.bash
|
||||
- name: Build
|
||||
run: |
|
||||
src/build-scripts/ci-build.bash
|
||||
- name: Testsuite
|
||||
run: src/build-scripts/ci-test.bash
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
|
||||
if: failure()
|
||||
with:
|
||||
name: osl-${{github.job}}
|
||||
name: osl-${{github.job}}-${{matrix.nametag}}
|
||||
path: |
|
||||
build/*.cmake
|
||||
build/CMake*
|
||||
build/testsuite/*/*.*
|
||||
|
||||
|
||||
clang-format:
|
||||
# Test formatting. This test entry doesn't do a full build, it just runs
|
||||
# clang-format on everything, and passes if nothing is misformatted.
|
||||
# Upon failure, the build artifact will be the full source code with the
|
||||
# formatting fixed (diffs will also appear in the console output).
|
||||
name: "clang-format verification"
|
||||
runs-on: ubuntu-18.04
|
||||
container:
|
||||
image: aswf/ci-osl:2021-clang11
|
||||
env:
|
||||
BUILDTARGET: 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
|
||||
|
||||
|
||||
@@ -50,4 +50,4 @@ This is a checklist for TSC's to review as part of the intake process. The TSC s
|
||||
- [X] License scan completed and no issues found
|
||||
- Minor issues were found but already fixed in PR https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1145
|
||||
- [X] Code repository imported to ASWF GitHub organization
|
||||
- [ ] Developer Certificate of Origin past commit signoff done and DCO Probot enabled.
|
||||
- [X] Developer Certificate of Origin post commit signoff done and DCO Probot enabled.
|
||||
|
||||
+81
-9
@@ -1,8 +1,46 @@
|
||||
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
||||
<!-- Copyright Contributors to the Open Shading Language Project. -->
|
||||
|
||||
Release 1.12 -- ?? (compared to 1.11)
|
||||
--------------------------------------------------
|
||||
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 +71,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 +98,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 +123,11 @@ 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
|
||||
* Fix overrunning allocation region in debug common_ancestor_between. #1577
|
||||
(1.12.6.1)
|
||||
|
||||
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 +144,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 +187,16 @@ 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)
|
||||
* Fix bug where assigning an init-op param its default value as an instance
|
||||
value would get lost. #1578 (1.12.6.1)
|
||||
|
||||
Internals/developer concerns:
|
||||
* Use the `final` keyword in certain internal classes where applicable.
|
||||
@@ -167,6 +220,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:
|
||||
@@ -206,14 +265,17 @@ Build & test system improvements:
|
||||
(1.12.4.1)
|
||||
- Make exported cmake configs relocatable by using relative paths. #1466
|
||||
(1.12.4.4)
|
||||
- Make the version number be a cmake cache variable. #1579 (1.12.6.1)
|
||||
* 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 +294,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 +304,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 +327,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 +350,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 +820,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
|
||||
|
||||
+12
-3
@@ -3,18 +3,27 @@
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
cmake_minimum_required (VERSION 3.12)
|
||||
project (OSL VERSION 1.12.5.0
|
||||
|
||||
set (OSL_VERSION "1.12.7.1")
|
||||
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
|
||||
string (TOLOWER ${PROJ_NAME} PROJ_NAME_LOWER) # short name lower case
|
||||
string (TOUPPER ${PROJ_NAME} PROJ_NAME_UPPER) # short name upper case
|
||||
set (PROJECT_VERSION_RELEASE_TYPE "dev" CACHE STRING
|
||||
set (PROJECT_VERSION_RELEASE_TYPE "" CACHE STRING
|
||||
"Build type, for example: dev, beta2, RC1 (empty string for normal release)")
|
||||
set (${PROJECT_NAME}_VERSION_RELEASE_TYPE ${PROJECT_VERSION_RELEASE_TYPE})
|
||||
set (PROJECT_AUTHORS "Contributors to the Open Shading Language project")
|
||||
option (${PROJECT_NAME}_SUPPORTED_RELEASE
|
||||
"Set ON for supported release branch, OFF for master" OFF)
|
||||
"Set ON for supported release branch, OFF for master" ON)
|
||||
if (${PROJECT_NAME}_SUPPORTED_RELEASE)
|
||||
set (${PROJECT_NAME}_DEV_RELEASE OFF)
|
||||
else ()
|
||||
|
||||
+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;
|
||||
}
|
||||
|
||||
+19
-19
@@ -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.24)
|
||||
|
||||
* A suitable **C++14 or C++17** compiler to build OSL itself, which may be any of:
|
||||
- **GCC 6.1 or newer** (tested through gcc 11.2)
|
||||
- Clang 3.4 or newer (tested through clang 14)
|
||||
- **GCC 6.1 or newer** (tested through gcc 12.1)
|
||||
- Clang 3.4 or newer (tested through clang 15)
|
||||
- Microsoft Visual Studio **2017 or newer**
|
||||
- Intel C++ compiler icc **version 17 or newer** or LLVM-based icx compiler
|
||||
**version 2022 or newer**.
|
||||
|
||||
* **[OpenImageIO](http://openimageio.org) 2.2 or newer** (tested through 2.3)
|
||||
* **[OpenImageIO](http://openimageio.org) 2.2 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.
|
||||
|
||||
* [Boost](https://www.boost.org) 1.55 or newer (tested through boost 1.78)
|
||||
* (optional) For GPU rendering on NVIDIA GPUs:
|
||||
* [Cuda](https://developer.nvidia.com/cuda-downloads) 8.0 or higher.
|
||||
* [OptiX](https://developer.nvidia.com/rtx/ray-tracing/optix) 5.1 or higher
|
||||
(though 7.0+ is highly recommended).
|
||||
|
||||
* [Boost](https://www.boost.org) 1.55 or newer (tested through boost 1.80)
|
||||
* [Ilmbase or Imath](https://github.com/AcademySoftwareFoundation/openexr) 2.3
|
||||
or newer (recommended: 2.4 or higher; tested through 3.1)
|
||||
* [Flex](https://github.com/westes/flex) 2.5.35 or newer and
|
||||
@@ -57,8 +62,8 @@ NEW or CHANGED dependencies since the last major release are **bold**.
|
||||
be operative.
|
||||
* (optional) Python: If you are building the Python bindings or running the
|
||||
testsuite:
|
||||
* Python >= 2.7 (tested against 2.7, 3.7, 3.8, 3.9)
|
||||
* pybind11 >= 2.4.2 (Tested through 2.9)
|
||||
* Python >= 2.7 (tested against 2.7, 3.7, 3.8, 3.9, 3.10)
|
||||
* pybind11 >= 2.4.2 (Tested through 2.10)
|
||||
* NumPy
|
||||
* (optional) Qt >= 5.6 (tested through 5.15). If not found at build time,
|
||||
the `osltoy` application will be disabled.
|
||||
@@ -93,19 +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:
|
||||
|
||||
@@ -294,7 +294,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} \
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -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/)
|
||||
@@ -393,6 +392,18 @@ Films using OSL (grouped by year of release date):
|
||||
Matrix Resurrections
|
||||
* **(2022 / upcoming)**
|
||||
Hotel Transylvania 4: Transformania,
|
||||
Death on the Nile,
|
||||
Uncharted,
|
||||
Turning Red,
|
||||
The Adam Project,
|
||||
Doctor Strange in the Multiverse of Madness,
|
||||
Love, Death, and Robots: In Vaulted Halls Entombed,
|
||||
Jurassic World: Dominion,
|
||||
Lightyear,
|
||||
Thor: Love and Thunder,
|
||||
The Sea Beast,
|
||||
DC League of Super Pets,
|
||||
Bullet Train,
|
||||
...
|
||||
|
||||
|
||||
@@ -427,9 +438,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 +468,6 @@ Contacts, Links, and References
|
||||
|
||||
[OSL home page](http://openshadinglanguage.org)
|
||||
|
||||
[Sony Pictures Imageworks main open source page](http://opensource.imageworks.com)
|
||||
|
||||
|
||||
|
||||
@@ -466,19 +480,19 @@ The current project leadership is documented in the
|
||||
Many people have contributed features, bug fixes, and other changes to OSL
|
||||
over the years: Steve Agland, Shane Ambler, Martijn Berger, Farchad
|
||||
Bidgolirad, Nicholas Bishop, Solomon Boulos, Stefan Bruens, Stefan Büttner,
|
||||
Matthaus G. Chajdas, Clark Chen, Alejandro Conty,
|
||||
Dieter De Baets, Thomas Dinges, Mads Drøschler,
|
||||
Luke Emrose, Louis Feng, Mark Final, Henri Fousse, Syoyo Fujita,
|
||||
Tim Grant, Larry Gritz, Nicolas Guiard, Euan Haahr, Derek Haase, Sven-Hendrik
|
||||
Haase, John Haddon, Niklas Harrysson, Daniel Heckenberg, Thiago Ize, Matt
|
||||
Johnson, Ronan Keryell, Chris Kulla, Elvic Liang, Max Liani, Adam Martinez,
|
||||
John Mertic, Bastien Montagne, Steena Monteiro, Alexis Oblet, Erich Ocean,
|
||||
Mikko Ohtamaa, Jino Park, Alexei Pawlow, Jay Reynolds, Declan Russell, Benoit
|
||||
Ruiz, Patrick Scheibe, Alex Schworer, Jonathan Scruggs, Sergey Sharybin,
|
||||
Sandip Shukla, Cliff Stein, Stephan Steinbach, Luya Tshimbalanga, Esteban
|
||||
Tovagliari, Brecht Van Lommel, Alexander von Knorring, Alex Wells, Roman
|
||||
Zulak. (Listed alphabetically; if we've left anybody out, it is inadvertent,
|
||||
please let us know.)
|
||||
Matthaus G. Chajdas, Clark Chen, Alejandro Conty, Damien Courtois, Dieter De
|
||||
Baets, Thomas Dinges, Mads Drøschler, Luke Emrose, Louis Feng, Mark Final,
|
||||
Henri Fousse, Stephen Friedman, Syoyo Fujita, Tim Grant, Larry Gritz, Nicolas
|
||||
Guiard, Euan Haahr, Derek Haase, Sven-Hendrik Haase, John Haddon, Niklas
|
||||
Harrysson, Daniel Heckenberg, 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, 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, Mark Sisson, 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,346 @@
|
||||
<!-- 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.) Also at this stage, the main branch's CHANGES.md should
|
||||
have a heading added at the top for the *next* version.
|
||||
|
||||
|
||||
### 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.
|
||||
|
||||
- Edit the top-level CMakeList.txt to update the version to the *next*
|
||||
anticipated release on the branch, in order to ensure that anybody building
|
||||
from subsequent patches won't get a release number that advertises itself
|
||||
incorrectly as a prior tagged release. Also edit CHANGES.md to add a new
|
||||
(blank) heading for the next patch or release.
|
||||
@@ -181,14 +181,14 @@ else ifeq (${platform}, macosx)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=gcc-9 -DCMAKE_CXX_COMPILER=g++-9
|
||||
USE_LIBCPLUSPLUS := 0
|
||||
else ifeq (${COMPILER},clang11)
|
||||
else ifeq (${COMPILER},clang14)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@11/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@11/bin/clang++
|
||||
else ifeq (${COMPILER},clang12)
|
||||
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@14/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@14/bin/clang++
|
||||
else ifeq (${COMPILER},clang15)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@12/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@12/bin/clang++
|
||||
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@15/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@15/bin/clang++
|
||||
else ifeq (${COMPILER},clang)
|
||||
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
||||
else ifeq (${COMPILER},gcc)
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# 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
|
||||
|
||||
# C/C++ analyzer properties
|
||||
sonar.cfamily.build-wrapper-output=build/bw_output
|
||||
sonar.cfamily.gcov.reportsPath=_coverage
|
||||
|
||||
sonar.cfamily.cache.enabled=true
|
||||
sonar.cfamily.cache.path=/tmp/sonarcache
|
||||
@@ -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
+25
@@ -0,0 +1,25 @@
|
||||
#!/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/
|
||||
|
||||
# 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.
|
||||
|
||||
@@ -42,8 +42,12 @@ if [[ "$ASWF_ORG" != "" ]] ; then
|
||||
|
||||
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" || "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
|
||||
sudo cp src/build-scripts/oneAPI.repo /etc/yum.repos.d
|
||||
sudo yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic
|
||||
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
||||
sudo yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic-2022.1.0-3768
|
||||
# Because multiple (possibly newer) versions of oneAPI may be installed,
|
||||
# use a config file to specify compiler and tbb versions
|
||||
# NOTE: oneAPI components have independent version numbering.
|
||||
set +e; source /opt/intel/oneapi/setvars.sh --config oneapi_2022.1.0.cfg; set -e
|
||||
|
||||
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" ]] ; then
|
||||
echo "Verifying installation of Intel(r) C++ Compiler:"
|
||||
icpc --version
|
||||
@@ -57,22 +61,34 @@ 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
|
||||
|
||||
time sudo apt-get -q install -y \
|
||||
qt5-default || /bin/true
|
||||
|
||||
export CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu:$CMAKE_PREFIX_PATH
|
||||
|
||||
# Nonstandard python versions
|
||||
if [[ "${PYTHON_VERSION}" == "3.9" ]] ; then
|
||||
time sudo apt-get -q install -y python3.9-dev python3-numpy
|
||||
pip3 --version
|
||||
pip3 install numpy
|
||||
elif [[ "$PYTHON_VERSION" == "2.7" ]] ; then
|
||||
time sudo apt-get -q install -y python-dev python-numpy
|
||||
else
|
||||
pip3 install numpy
|
||||
fi
|
||||
|
||||
if [[ "$CXX" == "g++-6" ]] ; then
|
||||
time sudo apt-get install -y g++-6
|
||||
elif [[ "$CXX" == "g++-7" ]] ; then
|
||||
@@ -85,6 +101,8 @@ else
|
||||
time sudo apt-get install -y g++-10
|
||||
elif [[ "$CXX" == "g++-11" ]] ; then
|
||||
time sudo apt-get install -y g++-11
|
||||
elif [[ "$CXX" == "g++-12" ]] ; then
|
||||
time sudo apt-get install -y g++-12
|
||||
fi
|
||||
|
||||
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" || "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
|
||||
@@ -92,22 +110,11 @@ else
|
||||
sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB
|
||||
echo "deb https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list
|
||||
time sudo apt-get update
|
||||
time sudo apt-get install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic
|
||||
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
||||
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" ]] ; then
|
||||
icpc --version
|
||||
fi
|
||||
if [[ "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
|
||||
icpx --version
|
||||
fi
|
||||
fi
|
||||
|
||||
# Nonstandard python versions
|
||||
if [[ "${PYTHON_VERSION}" == "3.8" ]] ; then
|
||||
#time sudo apt-get -q install -y python3.8-dev python3-numpy
|
||||
echo "skip?"
|
||||
elif [[ "${PYTHON_VERSION}" == "3.9" ]] ; then
|
||||
time sudo apt-get -q install -y python3.9-dev python3-numpy
|
||||
time sudo apt-get install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic=2022.1.0-3768
|
||||
# Because multiple (possibly newer) versions of oneAPI may be installed,
|
||||
# use a config file to specify compiler and tbb versions
|
||||
# NOTE: oneAPI components have independent version numbering.
|
||||
set +e; source /opt/intel/oneapi/setvars.sh --config oneapi_2022.1.0.cfg; set -e
|
||||
fi
|
||||
|
||||
source src/build-scripts/build_llvm.bash
|
||||
@@ -164,7 +171,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,22 +19,28 @@ 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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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 "")
|
||||
|
||||
|
||||
@@ -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.")
|
||||
|
||||
@@ -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})
|
||||
@@ -136,6 +136,14 @@ if (APPLE AND LLVM_VERSION VERSION_EQUAL 10.0.1 AND EXISTS "/usr/local/Cellar/ll
|
||||
" brew upgrade llvm \n"
|
||||
"${ColorReset}\n")
|
||||
endif ()
|
||||
if (LLVM_VERSION VERSION_GREATER_EQUAL 15.0
|
||||
AND ( (CMAKE_COMPILER_IS_APPLECLANG AND APPLECLANG_VERSION_STRING VERSION_LESS 15.0)
|
||||
OR (CMAKE_COMPILER_IS_CLANG AND CLANG_VERSION_STRING VERSION_LESS 15.0)))
|
||||
message (WARNING
|
||||
"${ColorYellow}"
|
||||
"If you are using LLVM 15 or higher, you should also use clang version "
|
||||
"15 or higher, or you may get build errors.${ColorReset}\n")
|
||||
endif ()
|
||||
|
||||
checked_find_package (partio)
|
||||
|
||||
|
||||
@@ -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 ( )
|
||||
|
||||
@@ -121,7 +121,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/
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ macro (setup_python_module)
|
||||
PRIVATE
|
||||
pybind11::pybind11
|
||||
Python::Python
|
||||
${lib_LIBS} ${SANITIZE_LIBRARIES})
|
||||
${lib_LIBS})
|
||||
if (APPLE)
|
||||
set_target_properties (${target_name} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
|
||||
endif ()
|
||||
|
||||
+56
-25
@@ -1,4 +1,4 @@
|
||||
# Copyright Contributors to the Open Shading Languge project.
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/
|
||||
|
||||
@@ -16,6 +16,10 @@ add_custom_command (OUTPUT "${CMAKE_BINARY_DIR}/testsuite/runtest.py"
|
||||
MAIN_DEPENDENCY "${CMAKE_SOURCE_DIR}/testsuite/runtest.py")
|
||||
add_custom_target ( CopyFiles ALL DEPENDS "${CMAKE_BINARY_DIR}/testsuite/runtest.py" )
|
||||
|
||||
|
||||
set (OSL_TEST_BIG_TIMEOUT 800 CACHE STRING "Timeout for tests that take a long time")
|
||||
|
||||
|
||||
# add_one_testsuite() - set up one testsuite entry
|
||||
#
|
||||
# Usage:
|
||||
@@ -26,10 +30,12 @@ add_custom_target ( CopyFiles ALL DEPENDS "${CMAKE_BINARY_DIR}/testsuite/runtest
|
||||
# [COMMAND cmd...] - optional override of launch command
|
||||
# )
|
||||
#
|
||||
|
||||
macro (add_one_testsuite testname testsrcdir)
|
||||
cmake_parse_arguments (_tst "" "" "ENV;COMMAND" ${ARGN})
|
||||
set (testsuite "${CMAKE_SOURCE_DIR}/testsuite")
|
||||
set (testdir "${CMAKE_BINARY_DIR}/testsuite/${testname}")
|
||||
file (MAKE_DIRECTORY "${testdir}")
|
||||
if (NOT _tst_COMMAND)
|
||||
set (_tst_COMMAND ${Python_EXECUTABLE} "${testsuite}/runtest.py" ${testdir})
|
||||
if (MSVC_IDE)
|
||||
@@ -45,7 +51,17 @@ macro (add_one_testsuite testname testsrcdir)
|
||||
OSL_TESTSUITE_SRC=${testsrcdir}
|
||||
OSL_TESTSUITE_CUR=${testdir}
|
||||
)
|
||||
file (MAKE_DIRECTORY "${testdir}")
|
||||
|
||||
# We need to suppress the leak sanitizer for "texture" tests, because of a
|
||||
# minor leak inside OIIO (140 bytes! -- inconsequential) but which we
|
||||
# can't use the suppressions list becuase the leaks come from calls made
|
||||
# inside JITed code for which there is not a good stack trace. Any real
|
||||
# leaks from OIIO or its dependencies we assume will be caught by lsan on
|
||||
# the OIIO side, where there is no JIT to complicate things.
|
||||
if (${testname} MATCHES "^texture" OR ${testname} MATCHES "gettextureinfo")
|
||||
list (APPEND _tst_ENV ASAN_OPTIONS=detect_leaks=0:$ENV{ASAN_OPTIONS})
|
||||
endif ()
|
||||
|
||||
add_test ( NAME ${testname} COMMAND ${_tst_COMMAND} )
|
||||
# message ("Test -- env ${_tst_ENV} cmd ${_tst_COMMAND}")
|
||||
set_tests_properties (${testname} PROPERTIES ENVIRONMENT "${_tst_ENV}" )
|
||||
@@ -53,8 +69,7 @@ macro (add_one_testsuite testname testsrcdir)
|
||||
# from piling up together, allocate a few cores each.
|
||||
if (${testname} MATCHES "^render-")
|
||||
set_tests_properties (${testname} PROPERTIES LABELS render
|
||||
TIMEOUT 240
|
||||
PROCESSORS 4 COST 10 TIMEOUT 240)
|
||||
PROCESSORS 4 COST 10 TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
endif ()
|
||||
# Some labeling for fun
|
||||
if (${testname} MATCHES "^texture")
|
||||
@@ -76,7 +91,7 @@ macro (add_one_testsuite testname testsrcdir)
|
||||
# These are batched shading regression tests. Some are quite
|
||||
# long, so give them a higher cost and timeout.
|
||||
set_tests_properties (${testname} PROPERTIES LABELS batchregression
|
||||
COST 15 TIMEOUT 300)
|
||||
COST 15 TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
endif ()
|
||||
endmacro ()
|
||||
|
||||
@@ -107,7 +122,7 @@ macro ( TESTSUITE )
|
||||
|
||||
# Run the test unoptimized, unless it matches a few patterns that
|
||||
# we don't test unoptimized (or has an OPTIMIZEONLY marker file).
|
||||
if (NOT _testname MATCHES "optix"
|
||||
if (NOT _testname MATCHES "optix"
|
||||
AND NOT EXISTS "${_testsrcdir}/NOSCALAR"
|
||||
AND NOT EXISTS "${_testsrcdir}/BATCHED_REGRESSION"
|
||||
AND NOT EXISTS "${_testsrcdir}/OPTIMIZEONLY")
|
||||
@@ -124,6 +139,9 @@ macro ( TESTSUITE )
|
||||
add_one_testsuite ("${_testname}.opt" "${_testsrcdir}"
|
||||
ENV TESTSHADE_OPT=2 )
|
||||
endif ()
|
||||
if (_testname MATCHES "render-" AND ${CMAKE_BUILD_TYPE} STREQUAL Debug)
|
||||
set_tests_properties (${_testname} PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
endif ()
|
||||
# When building for OptiX support, also run it in OptiX mode
|
||||
# if there is an OPTIX marker file in the directory.
|
||||
# If an environment variable $TESTSUITE_OPTIX is nonzero, then
|
||||
@@ -142,7 +160,7 @@ macro ( TESTSUITE )
|
||||
add_one_testsuite ("${_testname}.optix.opt" "${_testsrcdir}"
|
||||
ENV TESTSHADE_OPT=2 TESTSHADE_OPTIX=1 )
|
||||
endif ()
|
||||
|
||||
|
||||
if (BUILD_BATCHED)
|
||||
# When building for Batched support, also run it in Batched mode
|
||||
# if there is an BATCHED marker file in the directory.
|
||||
@@ -156,7 +174,7 @@ macro ( TESTSUITE )
|
||||
add_one_testsuite ("${_testname}.batched" "${_testsrcdir}"
|
||||
ENV TESTSHADE_OPT=0 TESTSHADE_BATCHED=1 )
|
||||
endif ()
|
||||
|
||||
|
||||
if ((EXISTS "${_testsrcdir}/BATCHED" OR test_all_batched OR _testname MATCHES "batched")
|
||||
AND NOT EXISTS "${_testsrcdir}/BATCHED_REGRESSION"
|
||||
AND NOT EXISTS "${_testsrcdir}/NOBATCHED"
|
||||
@@ -165,7 +183,7 @@ macro ( TESTSUITE )
|
||||
add_one_testsuite ("${_testname}.batched.opt" "${_testsrcdir}"
|
||||
ENV TESTSHADE_OPT=2 TESTSHADE_BATCHED=1 )
|
||||
endif ()
|
||||
|
||||
|
||||
# When building for Batched support, optionally run a regression test
|
||||
# if there is an BATCHED_REGRESSION marker file in the directory.
|
||||
if ((EXISTS "${_testsrcdir}/BATCHED_REGRESSION")
|
||||
@@ -211,7 +229,7 @@ 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
|
||||
@@ -220,7 +238,7 @@ macro (osl_add_all_tests)
|
||||
calculatenormal-reg
|
||||
cellnoise closure closure-array color color-reg colorspace comparison
|
||||
complement-reg compile-buffer compassign-reg
|
||||
component-range
|
||||
component-range
|
||||
control-flow-reg connect-components
|
||||
const-array-params const-array-fill
|
||||
debugnan debug-uninit
|
||||
@@ -239,7 +257,9 @@ macro (osl_add_all_tests)
|
||||
globals-needed
|
||||
group-outputs groupstring
|
||||
hash hashnoise hex hyperb
|
||||
ieee_fp ieee_fp-reg if if-reg incdec initlist initops intbits isconnected
|
||||
ieee_fp ieee_fp-reg if if-reg incdec initlist
|
||||
initops initops-instance-clash
|
||||
intbits isconnected
|
||||
isconstant
|
||||
layers layers-Ciassign layers-entry layers-lazy layers-lazyerror
|
||||
layers-nonlazycopy layers-repeatedoutputs
|
||||
@@ -259,7 +279,7 @@ macro (osl_add_all_tests)
|
||||
noise-perlin noise-simplex
|
||||
noise-reg
|
||||
normalize-reg
|
||||
pnoise pnoise-cell pnoise-gabor
|
||||
pnoise pnoise-cell pnoise-gabor
|
||||
pnoise-generic pnoise-perlin
|
||||
pnoise-reg
|
||||
operator-overloading
|
||||
@@ -291,11 +311,20 @@ macro (osl_add_all_tests)
|
||||
raytype raytype-reg raytype-specialized regex-reg reparam
|
||||
render-background render-bumptest
|
||||
render-cornell render-furnace-diffuse
|
||||
render-mx-furnace-burley-diffuse
|
||||
render-mx-furnace-oren-nayar
|
||||
render-mx-furnace-sheen
|
||||
render-mx-burley-diffuse
|
||||
render-mx-dielectric render-mx-dielectric-glass
|
||||
render-mx-conductor
|
||||
render-mx-generalized-schlick render-mx-generalized-schlick-glass
|
||||
render-mx-layer
|
||||
render-mx-sheen
|
||||
render-microfacet render-oren-nayar
|
||||
render-uv render-veachmis render-ward
|
||||
select select-reg shaderglobals shortcircuit
|
||||
smoothstep-reg
|
||||
spline spline-reg splineinverse splineinverse-ident
|
||||
smoothstep-reg
|
||||
spline spline-reg splineinverse splineinverse-ident
|
||||
splineinverse-knots-ascend-reg splineinverse-knots-descend-reg
|
||||
spline-boundarybug spline-derivbug
|
||||
split-reg
|
||||
@@ -319,7 +348,7 @@ macro (osl_add_all_tests)
|
||||
trailing-commas
|
||||
transcendental-reg
|
||||
transitive-assign
|
||||
transform transform-reg transformc transformc-reg trig trig-reg
|
||||
transform transform-reg transformc transformc-reg trig trig-reg
|
||||
typecast
|
||||
unknown-instruction
|
||||
userdata userdata-passthrough
|
||||
@@ -339,10 +368,10 @@ macro (osl_add_all_tests)
|
||||
endif ()
|
||||
|
||||
# Add tests that require the Python bindings if we built them.
|
||||
# We also exclude these tests if this is a sanitizer build on Linux,
|
||||
# because the Python interpreter itself won't be linked with the right asan
|
||||
# We also exclude these tests if this is a sanitizer build, because the
|
||||
# Python interpreter itself won't be linked with the right asan
|
||||
# libraries to run correctly.
|
||||
if (USE_PYTHON AND NOT SANITIZE_ON_LINUX)
|
||||
if (USE_PYTHON AND NOT SANITIZE)
|
||||
TESTSUITE ( python-oslquery )
|
||||
endif ()
|
||||
|
||||
@@ -354,7 +383,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 +392,13 @@ macro (osl_add_all_tests)
|
||||
TESTSUITE ( testoptix testoptix-noise example-cuda)
|
||||
endif ()
|
||||
|
||||
# Some regression tests have alot of combinations and may need more time to finish
|
||||
# Some regression tests have a lot of combinations and may need more time to finish
|
||||
if (BUILD_BATCHED)
|
||||
set_tests_properties (arithmetic-reg.regress.batched.opt PROPERTIES TIMEOUT 800)
|
||||
set_tests_properties (transform-reg.regress.batched.opt PROPERTIES TIMEOUT 800)
|
||||
set_tests_properties (arithmetic-reg.regress.batched.opt
|
||||
PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
set_tests_properties (transform-reg.regress.batched.opt
|
||||
PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
endif ()
|
||||
set_tests_properties (matrix-reg.regress.rsbitcode.opt PROPERTIES TIMEOUT 800)
|
||||
|
||||
set_tests_properties (matrix-reg.regress.rsbitcode.opt
|
||||
PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
endmacro()
|
||||
|
||||
+710
-77
@@ -66,7 +66,7 @@ All rights reserved.
|
||||
Editor: Larry Gritz \\
|
||||
\emph{lg@imageworks.com}
|
||||
}
|
||||
\date{{\large Date: 24 Nov 2021 \\
|
||||
\date{{\large Date: 27 Aug 2022 \\
|
||||
% (with corrections, 24 Nov 2021)
|
||||
}
|
||||
\bigskip
|
||||
@@ -1431,7 +1431,7 @@ least 32 bits.
|
||||
|
||||
Integer constants are constructed the same way as in C. The following
|
||||
are examples of {\cf int} constants: {\cf 1}, {\cf -32}, etc. Integer
|
||||
constants may be specified as hexidecimal, for example: {\cf 0x01cf}.
|
||||
constants may be specified as hexadecimal, for example: {\cf 0x01cf}.
|
||||
|
||||
Unlike C, no unsigned, bool, char, short, or long types are supplied.
|
||||
This is to simplify the process of writing shaders (as well as
|
||||
@@ -3778,7 +3778,7 @@ Computes the \emph{inverse} of the {\cf spline()} function, i.e., returns
|
||||
the value $x$ for which \\
|
||||
\spc {\cf spline (basis, x, y...)}\\
|
||||
would return value
|
||||
$v$. Results are undefined if the knots do not specifiy a monotonic
|
||||
$v$. Results are undefined if the knots do not specify a monotonic
|
||||
(only increasing or only decreasing) set of values.
|
||||
|
||||
Note that the combination of {\cf spline} and {\cf splineinverse} makes
|
||||
@@ -3905,7 +3905,7 @@ multi-component types such as \color, the format will be applied to each
|
||||
of the components). The {\cf \%s} expects a {\cf string} or
|
||||
{\cf closure} argument.
|
||||
|
||||
All of the substition commands follow the usual C/C++ formatting rules,
|
||||
All of the substitution commands follow the usual C/C++ formatting rules,
|
||||
so format commands such as {\cf "\%6.2f"}, etc., should work as
|
||||
expected.
|
||||
\apiend
|
||||
@@ -3930,7 +3930,7 @@ and other diagnostic information.
|
||||
\indexapi{fprintf()}
|
||||
The {\cf fprintf()} function works similarly to {\cf printf}, but rather
|
||||
than printing to the default text output stream, the results will be
|
||||
concatentated onto the end of the text file named by {\cf filename}.
|
||||
concatenated onto the end of the text file named by {\cf filename}.
|
||||
\apiend
|
||||
|
||||
\apiitem{string {\ce concat} (string s1, ..., string sN)}
|
||||
@@ -4404,7 +4404,7 @@ will not be modified and {\cf gettextureinfo} will return {\cf 0}.
|
||||
The version of {\cf gettextureinfo} that takes {\cf s} and {\cf t} parameters
|
||||
retrieves information about the texture file that will be used for those
|
||||
texture coordinates. This can be useful for UDIM textures that may use
|
||||
different texture files for different regions, based on the coodinates. For
|
||||
different texture files for different regions, based on the corodinates. For
|
||||
regular, non-UDIM textures, the coordinates, if supplied, will be ignored.
|
||||
When UDIM textures are queried without coordinates supplied, it will succeed
|
||||
and return the texture info only if that parameter is found and has the same
|
||||
@@ -4611,7 +4611,7 @@ Example:
|
||||
\index{material closure functions}
|
||||
\index{functions!closures}
|
||||
|
||||
For \closurecolor functions, the return ``value'' is symbolic and is may
|
||||
For \closurecolor functions, the return ``value'' is symbolic and may
|
||||
be passed to an output variable or assigned to \Ci, to be evaluated at a
|
||||
later time convenient to the renderer in order to compute the exitant
|
||||
radiance in the direction {\cf -I}. But the shader itself cannot
|
||||
@@ -4620,15 +4620,695 @@ examine the numeric values of the \colorclosure.
|
||||
The intent of this specification is to give a minimal but useful set of
|
||||
material closures that you can expect any renderer implementation to
|
||||
provide. Individual renderers may supply additional closures that are
|
||||
specific to the workings of that renderer. Additionally, invidual
|
||||
specific to the workings of that renderer. Additionally, individual
|
||||
renderers may allow additional parameters or controls on the standard
|
||||
closures, passed as token/value pairs following the required arguments
|
||||
(much like the optional arguments to the {\cf texture()} function).
|
||||
Consult the documentation for your specific renderer for details.
|
||||
|
||||
OSL's standard material closures are by synchronized to match the names and
|
||||
properties of the physically-based shading nodes of MaterialX v1.38
|
||||
(\url{https://www.materialx.org/}).
|
||||
|
||||
\subsection{Surface BSDF closures}
|
||||
|
||||
\apiitem{\closurecolor\ {\ce oren_nayar_diffuse_bsdf}(normal N, color albedo, float roughness)}
|
||||
\indexapi{oren_nayar_diffuse_bsdf()}
|
||||
|
||||
Constructs a diffuse reflection BSDF based on the Oren-Nayar reflectance
|
||||
model.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Surface albedo.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness}
|
||||
\vspace{12pt}
|
||||
Surface roughness [0,1]. A value of 0.0 gives Lambertian reflectance.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
The Oren-Nayar reflection model is described in M.\ Oren and S.\ K.\
|
||||
Nayar, ``Generalization of Lambert's Reflectance Model,'' Proceedings of
|
||||
SIGGRAPH 1994, pp.239-246 (July, 1994).
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Surface material closures}
|
||||
\apiitem{\colorclosure\ {\ce burley_diffuse_bsdf} (normal N, color albedo, float roughness)}
|
||||
\indexapi{burley_diffuse_bsdf()}
|
||||
|
||||
Constructs a diffuse reflection BSDF based on the corresponding component of
|
||||
the Disney Principled shading model.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Surface albedo.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness}
|
||||
\vspace{12pt}
|
||||
Surface roughness [0,1]. A value of 0.0 gives Lambertian reflectance.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce dielectric_bsdf} (normal N, vector U, color reflection_tint, \\
|
||||
\spc\spc color transmission_tint, float roughness_x, float roughness_y, \\
|
||||
\spc\spc float ior, string distribution)}
|
||||
\indexapi{dielectric_bsdf()}
|
||||
|
||||
Constructs a reflection and/or transmission BSDF based on a microfacet
|
||||
reflectance model and a Fresnel curve for dielectrics. The two tint parameters
|
||||
control the contribution of each reflection/transmission lobe. The tints
|
||||
should remain 100\% white for a physically correct dielectric, but can be
|
||||
tweaked for artistic control or set to 0.0 for disabling a lobe.
|
||||
|
||||
The closure may be vertically layered over a base BSDF for the surface beneath
|
||||
the dielectric layer. This is done using the {\cf layer()} closure. By
|
||||
chaining multiple {\cf dielectric_bsdf} closures you can describe a surface
|
||||
with multiple specular lobes. If transmission is enabled (transmission_tint
|
||||
$>$ 0.0) the closure may be layered over a VDF closure describing the surface
|
||||
interior to handle absorption and scattering inside the medium.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{U}
|
||||
\vspace{12pt}
|
||||
Tangent vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{reflection_tint}
|
||||
\vspace{12pt}
|
||||
Weight per color channel for the reflection lobe. Should be (1,1,1) for a physically-correct dielectric surface, but can be tweaked for artistic control. Set to (0,0,0) to disable reflection.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{transmission_tint}
|
||||
\vspace{12pt}
|
||||
Weight per color channel for the transmission lobe. Should be (1,1,1) for a physically-correct dielectric surface, but can be tweaked for artistic control. Set to (0,0,0) to disable transmission.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness_x}
|
||||
\vspace{12pt}
|
||||
Surface roughness in the U direction with a perceptually linear response over its range.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness_y}
|
||||
\vspace{12pt}
|
||||
Surface roughness in the V direction with a perceptually linear response
|
||||
over its range.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{ior}
|
||||
\vspace{12pt}
|
||||
Refraction index.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{distribution}
|
||||
\vspace{12pt}
|
||||
Microfacet distribution. An implementation is expected to support the
|
||||
following distributions: \qkw{ggx}
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{thinfilm_thickness}
|
||||
\vspace{12pt}
|
||||
Optional float parameter for thickness of an iridescent thin film layer on
|
||||
top of this BSDF. Given in nanometers.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{thinfilm_ior}
|
||||
\vspace{12pt}
|
||||
Optional float parameter for refraction index of the thin film layer.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce conductor_bsdf} (normal N, vector U, float roughness_x, \\
|
||||
\spc\spc float roughness_y, color ior, color extinction, string distribution)}
|
||||
\indexapi{conductor_bsdf()}
|
||||
|
||||
Constructs a reflection BSDF based on a microfacet reflectance model. Uses a
|
||||
Fresnel curve with complex refraction index for conductors/metals. If an
|
||||
artistic parametrization is preferred the {\cf artistic_ior()} utility
|
||||
function can be used to convert from artistic to physical parameters.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{U}
|
||||
\vspace{12pt}
|
||||
Tangent vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness_x}
|
||||
\vspace{12pt}
|
||||
Surface roughness in the U direction with a perceptually linear response over its range.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness_y}
|
||||
\vspace{12pt}
|
||||
Surface roughness in the V direction with a perceptually linear response over its range.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{ior}
|
||||
\vspace{12pt}
|
||||
Refraction index.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{extinction}
|
||||
\vspace{12pt}
|
||||
Extinction coefficient.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{distribution}
|
||||
\vspace{12pt}
|
||||
Microfacet distribution. An implementation is expected to support the
|
||||
following distributions: \qkw{ggx}
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{thinfilm_thickness}
|
||||
\vspace{12pt}
|
||||
Optional float parameter for thickness of an iridescent thin film layer on
|
||||
top of this BSDF. Given in nanometers.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{thinfilm_ior}
|
||||
\vspace{12pt}
|
||||
Optional float parameter for refraction index of the thin film layer.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce generalized_schlick_bsdf} (normal N, vector U, \\
|
||||
\spc\spc color reflection_tint, color transmission_tint, \\
|
||||
\spc\spc float roughness_x, float roughness_y, color f0, color f90, \\
|
||||
\spc\spc float exponent, string distribution)}
|
||||
\indexapi{generalized_schlick_bsdf()}
|
||||
|
||||
Constructs a reflection and/or transmission BSDF based on a microfacet
|
||||
reflectance model and a generalized Schlick Fresnel curve. The two tint
|
||||
parameters control the contribution of each reflection/transmission lobe.
|
||||
|
||||
The closure may be vertically layered over a base BSDF for the surface beneath
|
||||
the dielectric layer. This is done using the layer() closure. By chaining
|
||||
multiple {\cf dielectric_bsdf} closures you can describe a surface with multiple
|
||||
specular lobes. If transmission is enabled (transmission_tint $>$ 0.0) the
|
||||
closure may be layered over a VDF closure describing the surface interior to
|
||||
handle absorption and scattering inside the medium.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{U}
|
||||
\vspace{12pt}
|
||||
Tangent vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{reflection_tint}
|
||||
\vspace{12pt}
|
||||
Weight per color channel for the reflection lobe. Set to (0,0,0) to disable
|
||||
reflection.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{transmission_tint}
|
||||
\vspace{12pt}
|
||||
Weight per color channel for the transmission lobe. Set to (0,0,0) to
|
||||
disable transmission.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness_x}
|
||||
\vspace{12pt}
|
||||
Surface roughness in the U direction with a perceptually linear response
|
||||
over its range.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness_y}
|
||||
\vspace{12pt}
|
||||
Surface roughness in the V direction with a perceptually linear response
|
||||
over its range.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{f0}
|
||||
\vspace{12pt}
|
||||
Reflectivity per color channel at facing angles.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{f90}
|
||||
\vspace{12pt}
|
||||
Reflectivity per color channel at grazing angles.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{exponent}
|
||||
\vspace{12pt}
|
||||
Variable exponent for the Schlick Fresnel curve, the default value should be
|
||||
5.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{distribution}
|
||||
\vspace{12pt}
|
||||
Microfacet distribution. An implementation is expected to support the
|
||||
following distributions: \qkw{ggx}
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{thinfilm_thickness}
|
||||
\vspace{12pt}
|
||||
Optional float parameter for thickness of an iridescent thin film layer on
|
||||
top of this BSDF. Given in nanometers.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{thinfilm_ior}
|
||||
\vspace{12pt}
|
||||
Optional float parameter for refraction index of the thin film layer.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce translucent_bsdf} (normal N, color albedo)}
|
||||
\indexapi{translucent_bsdf()}
|
||||
|
||||
Constructs a translucent (diffuse transmission) BSDF based on the Lambert
|
||||
reflectance model.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Surface albedo.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness}
|
||||
\vspace{12pt}
|
||||
Surface roughness [0,1]. A value of 0.0 gives Lambertian reflectance.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce transparent_bsdf} ( )}
|
||||
\indexapi{transparent_bsdf()}
|
||||
|
||||
Constructs a closure that represents straight transmission through a surface.
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce subsurface_bssrdf} ( )}
|
||||
\indexapi{subsurface_bssrdf}
|
||||
Constructs a BSSRDF for subsurface scattering within a homogeneous medium.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Single-scattering albedo of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{transmission_depth}
|
||||
\vspace{12pt}
|
||||
Distance travelled inside the medium by white light before its color becomes
|
||||
transmission_color by Beer's law. Given in scene length units, range
|
||||
[0,infinity). Together with transmission_color this determines the
|
||||
extinction coefficient of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{transmission_color}
|
||||
\vspace{12pt}
|
||||
Desired color resulting from white light transmitted a distance of
|
||||
'transmission_depth' through the medium. Together with transmission_depth
|
||||
this determines the extinction coefficient of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{anisotropy}
|
||||
\vspace{12pt}
|
||||
Scattering anisotropy [-1,1]. Negative values give backwards scattering,
|
||||
positive values give forward scattering, and 0.0 gives uniform scattering.
|
||||
\apiend
|
||||
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce sheen_bsdf} (normal N, color albedo, float roughness)}
|
||||
\indexapi{sheen_bsdf()}
|
||||
|
||||
Constructs a microfacet BSDF for the back-scattering properties of cloth-like
|
||||
materials. This closure may be vertically layered over a base BSDF, where
|
||||
energy that is not reflected will be transmitted to the base closure.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Surface albedo.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness}
|
||||
\vspace{12pt}
|
||||
Surface roughness [0,1].
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
|
||||
\subsection{Volumetric material closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce anisotropic_vdf} (color albedo, color extinction, float anisotropy)}
|
||||
\indexapi{anisotropic_vdf}
|
||||
|
||||
Constructs a VDF scattering light for a general participating medium, based on
|
||||
the Henyey-Greenstein phase function. Forward, backward and uniform scattering
|
||||
is supported and controlled by the anisotropy input.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Single-scattering albedo of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{extinction}
|
||||
\vspace{12pt}
|
||||
Volume extinction coefficient.
|
||||
\apiend
|
||||
|
||||
\apiitem{anisotropy}
|
||||
\vspace{12pt}
|
||||
Scattering anisotropy [-1,1]. Negative values give backwards scattering,
|
||||
positive values give forward scattering, and 0.0 gives uniform scattering.
|
||||
\apiend
|
||||
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce medium_vdf} (color albedo, float transmission_depth, \\
|
||||
\spc\spc color transmission_color, float anisotropy, float ior, int priority)}
|
||||
\indexapi{medium_vdf}
|
||||
|
||||
Constructs a VDF for light passing through a dielectric homogeneous medium,
|
||||
such as glass or liquids. The parameters {\cf transmission_depth} and
|
||||
{\cf transmission_color} control the extinction coefficient of the medium in an
|
||||
artist-friendly way. A priority can be set to determine the ordering of
|
||||
overlapping media.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Single-scattering albedo of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{transmission_depth}
|
||||
\vspace{12pt}
|
||||
Distance travelled inside the medium by white light before its color becomes
|
||||
transmission_color by Beer's law. Given in scene length units, range
|
||||
[0,infinity). Together with transmission_color this determines the
|
||||
extinction coefficient of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{transmission_color}
|
||||
\vspace{12pt}
|
||||
Desired color resulting from white light transmitted a distance of
|
||||
'transmission_depth' through the medium. Together with transmission_depth
|
||||
this determines the extinction coefficient of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{anisotropy}
|
||||
\vspace{12pt}
|
||||
Scattering anisotropy [-1,1]. Negative values give backwards scattering,
|
||||
positive values give forward scattering, and 0.0 gives uniform scattering.
|
||||
\apiend
|
||||
|
||||
\apiitem{ior}
|
||||
\vspace{12pt}
|
||||
Refraction index of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{priority}
|
||||
\vspace{12pt}
|
||||
Priority of this medium (for nested dielectrics).
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Light emission closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce uniform_edf} (color emittance)}
|
||||
\indexapi{uniform_edf}
|
||||
Constructs an EDF emitting light uniformly in all directions.
|
||||
This is used to represent a glowing/emissive material.
|
||||
When called in the context of a surface shader group, it implies that
|
||||
light is emitted in a full hemisphere centered around the surface
|
||||
normal. When called in the context of a volume shader group, it implies
|
||||
that light is emitted evenly in all directions around the point being
|
||||
shaded.
|
||||
|
||||
The {\cf emittance} parameter is the amount of emission and
|
||||
has units of radiance (e.g.,
|
||||
$\mathrm{W}\cdot\mathrm{sr}^{-1}\cdot\mathrm{m}^{-2}$). This means that a surface
|
||||
directly seen by the camera will directly reproduce the closure weight in the
|
||||
final pixel, regardless of being a surface or a volume.
|
||||
|
||||
For an emissive surface, if you divide the return value of {\cf uniform_edf()} by
|
||||
{\cf surfacearea() * M_PI}, then you can easily specify the total emissive
|
||||
power of the light (e.g., $\mathrm{W}$), regardless of its physical size.
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Layering and Signaling closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce layer} (closure color top, closure color base)}
|
||||
\indexapi{layer()}
|
||||
Vertically layer a layerable BSDF such as {\cf dielectric_bsdf},
|
||||
{\cf generalized_schlick_bsdf} or {\cf sheen_bsdf} over a BSDF or VDF. The
|
||||
implementation is target specific, but a standard way of handling this is by
|
||||
albedo scaling, using {\cf base*(1-reflectance(top)) + top}, where
|
||||
reflectance() calculates the directional albedo of a given top BSDF.
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce holdout} ( )}
|
||||
\indexapi{holdout()}
|
||||
Returns a \colorclosure that does not represent any additional light
|
||||
reflection from the surface, but does signal to the renderer that
|
||||
the surface is a \emph{holdout object} (appears transparent in
|
||||
the final output yet hides objects behind it). ``Partial holdouts''
|
||||
may be designated by weighting the {\cf holdout()} closure by a
|
||||
weight that is less than 1.0.
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce debug} (string outputname)}
|
||||
\indexapi{debug()}
|
||||
Returns a \colorclosure that does not represent any additional light
|
||||
reflection from the surface, but does signal to the renderer to add
|
||||
the weight of the closure (which may be a {\cf float} or a \color)
|
||||
to the named output (i.e., AOV).
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Material utility functions}
|
||||
|
||||
\apiitem{void {\ce artistic_ior} (color reflectivity, color edge_tint, \\
|
||||
\spc\spc output color ior, output color extinction)}
|
||||
\indexapi{artistic_ior()}
|
||||
Converts the artistic parameterization reflectivity and edge_tint to complex IOR values.
|
||||
To be used with the conductor_bsdf() closure.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{reflectivity}
|
||||
\vspace{12pt}
|
||||
Reflectivity per color channel at facing angles (\emph{r} parameter in [OG14])
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{edge_tint}
|
||||
\vspace{12pt}
|
||||
Color bias for grazing angles (\emph{g} parameter in [OG14]).
|
||||
NOTE: This is not equal to 'f90' in a Schlick Fresnel parameterization.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{ior}
|
||||
\vspace{12pt}
|
||||
Output refraction index.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{extinction}
|
||||
\vspace{12pt}
|
||||
Output extinction coefficient.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
Reference: [OG14] Ole Gulbrandsen, "Artist Friendly Metallic Fresnel", Journal
|
||||
of Computer Graphics Tools 3(4), 2014.
|
||||
\url{http://jcgt.org/published/0003/04/03/paper.pdf}
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Deprecated closures}
|
||||
|
||||
These were described in the original OSL language specification, but
|
||||
beginning with OSL 1.12, these are considered deprecated. Support for
|
||||
them will be removed entirely in OSL 2.0.
|
||||
|
||||
\subsubsection{Deprecated Surface closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce diffuse} (normal N)}
|
||||
\indexapi{diffuse()}
|
||||
@@ -4664,7 +5344,7 @@ Nayar, ``Generalization of Lambert's Reflectance Model,'' Proceedings of
|
||||
SIGGRAPH 1994, pp.239-246 (July, 1994).
|
||||
|
||||
\begin{comment}
|
||||
Like all \closurecolors, the return ``value'' is symbolic and is may be
|
||||
Like all \closurecolors, the return ``value'' is symbolic and may be
|
||||
evaluated at a later time convenient to the renderer in order to compute
|
||||
the exitant radiance in the direction {\cf -I}. But aside from the
|
||||
fact that the shader cannot examine the numeric values of the
|
||||
@@ -4745,33 +5425,6 @@ implemented as follows:
|
||||
\end{comment}
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce microfacet} (string distribution, normal N, vector
|
||||
U, \\ \bigspc\bigspc float xalpha, float yalpha, float eta, int refract)}
|
||||
\indexapi{microfacet()}
|
||||
|
||||
Returns a \colorclosure that represents scattering on the
|
||||
surface using some microfacet distribution such as \qkw{beckmann} or \qkw{ggx} (as
|
||||
described in Walter et al., ``Microfacet Models for Refraction through Rough
|
||||
Surfaces,'' Eurographics Symposium on Rendering, 2007).
|
||||
Both {\cf xalpha} and {\cf yalpha} control how rough the microstructure of the
|
||||
surface is, possibly in an anisotropic way if they are different. In the
|
||||
anisotropic case {\cf U} must be a vector orthogonal to {\cf N} to specify the
|
||||
direction. These values are expected to be the alpha values of the distribution
|
||||
as it appears in the literature, not a universal roughness measure.
|
||||
The {\cf eta} parameter is the index of refraction of the material, and
|
||||
{\cf refract} is a enumeration flag that controls if the BSDF is reflective ({\cf 0}),
|
||||
refractive ({\cf 1}) or both at once ({\cf 2}). The implementation must not rely on
|
||||
{\cf U} when the roughness is isotropic or the given vector is zero.
|
||||
|
||||
The list of supported distributions will change from renderer to renderer, and
|
||||
also the behavior when an unsupported distribution is requested. It is up to the
|
||||
implementation to issue an error or to default to a supported one. Also it is
|
||||
expected that the alias \qkw{default} must work as a distribution in any renderer.
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce microfacet} (string distribution, normal N,
|
||||
\\ \bigspc\bigspc float alpha, float eta, int refract)}
|
||||
\indexapi{microfacet()}
|
||||
@@ -4823,7 +5476,6 @@ implemented as follows:
|
||||
\end{code}
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce transparent} ( )}
|
||||
\indexapi{transparent()}
|
||||
|
||||
@@ -4867,8 +5519,7 @@ scattering} exhibited by the surface.
|
||||
\apiend
|
||||
\end{comment}
|
||||
|
||||
|
||||
\subsection{Volumetric material closures}
|
||||
\subsubsection{Deprecated Volumetric closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce isotropic} ( )}
|
||||
\indexapi{isotropic}
|
||||
@@ -4877,18 +5528,16 @@ volumetric material, scattering light evenly in all directions,
|
||||
regardless of its original direction.
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce henyey_greenstein} (float g)}
|
||||
\indexapi{henyey_greenstein}
|
||||
Returns a \colorclosure that represents the directional volumetric
|
||||
scattering by small suspended particles. The {\cf g} parameter is the
|
||||
anisotropy factor, ranging from $-1$ to $1$), with positive values
|
||||
anisotropy factor, in the range $(-1, 1)$, with positive values
|
||||
indicating predominantly forward-scattering, negative values indicating
|
||||
predominantly back-scattering, and value of $g=0$ resulting in isotropic
|
||||
scattering.
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce absorption} ( )}
|
||||
\indexapi{absorption}
|
||||
Returns a \colorclosure that does not represent any additional
|
||||
@@ -4898,8 +5547,7 @@ volumetric material, scattering light evenly in all directions,
|
||||
regardless of its original direction.
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Light emission closures}
|
||||
\subsubsection{Deprecated Emission closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce emission} ( )}
|
||||
\indexapi{emission}
|
||||
@@ -4915,7 +5563,7 @@ $\mathrm{W}\cdot\mathrm{sr}^{-1}\cdot\mathrm{m}^{-2}$). This means that a surfac
|
||||
directly seen by the camera will directly reproduce the closure weight in the
|
||||
final pixel, regardless of being a surface or a volume.
|
||||
|
||||
For surface emission, If you divide {\cf emission()} by
|
||||
For an emissive surface, if you divide the return value of {\cf emission()} by
|
||||
{\cf surfacearea() * M_PI}, then you can easily specify the total emissive
|
||||
power of the light (e.g., $\mathrm{W}$), regardless of its physical size.
|
||||
\apiend
|
||||
@@ -4930,30 +5578,6 @@ up from an HDRI environment map.
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Signaling closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce holdout} ( )}
|
||||
\indexapi{holdout()}
|
||||
Returns a \colorclosure that does not represent any additional light
|
||||
reflection from the surface, but does signal to the renderer that
|
||||
the surface is a \emph{holdout object} (appears transparent in
|
||||
the final output yet hides objects behind it). ``Partial holdouts''
|
||||
may be designated by weighting the {\cf holdout()} closure by a
|
||||
weight that is less than 1.0.
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce debug} (string outputname)}
|
||||
\indexapi{debug()}
|
||||
Returns a \colorclosure that does not represent any additional light
|
||||
reflection from the surface, but does signal to the renderer to add
|
||||
the weight of the closure (which may be a {\cf float} or a \color)
|
||||
to the named output (i.e., AOV).
|
||||
\apiend
|
||||
|
||||
|
||||
|
||||
|
||||
\newpage
|
||||
\section{Renderer state and message passing}
|
||||
\label{sec:stdlib:state}
|
||||
@@ -5750,7 +6374,7 @@ programming language design)?
|
||||
|
||||
This spec is written assuming that \color should explicitly be
|
||||
3-component RGB. Alternately, we could add global \inttype\ {\cf ncomps} that gives the
|
||||
numer of components in a \color, and eliminate any built-in operations
|
||||
number of components in a \color, and eliminate any built-in operations
|
||||
and library functions that seem to require or imply a 3-component color
|
||||
model (including type casting between \color and the 3-component
|
||||
\point-like types).
|
||||
@@ -5862,7 +6486,7 @@ anybody want to argue for any of the following to be included?
|
||||
|
||||
We have defined structures as being allowed to consist only of basic
|
||||
types and arrays thereof --- not structures of structures. This
|
||||
restriction makes for a simpler grammar and implementation, simplier
|
||||
restriction makes for a simpler grammar and implementation, simpler
|
||||
renderer-side APIs for passing data to shaders, and simpler APIs for
|
||||
libraries that query parameters of compiled shaders. But if people
|
||||
strongly feel like structures-of-structures is an important feature, we
|
||||
@@ -5948,7 +6572,7 @@ about it.
|
||||
|
||||
\subsection{Nomenclature}
|
||||
|
||||
Does anybody have a perference for \dPdu and \dPdv (borrowing the
|
||||
Does anybody have a preference for \dPdu and \dPdv (borrowing the
|
||||
RenderMan names, but awkward for primitives without a consistent $u,v$
|
||||
parameterization?), versus something more generic such as {\cf T} and
|
||||
{\cf B} (tangent and bitangent, without explicitly saying how they are
|
||||
@@ -6134,6 +6758,9 @@ full control in the shader.
|
||||
may be shared among multiple geometric primitives. Also sometimes
|
||||
called \emph{graphics state}.
|
||||
|
||||
\item[BSDF.] Bidirectional scattering distribution function, a
|
||||
function that describes light scattering properties of a surface.
|
||||
|
||||
\item[Built-in function.] A function callable from within a shader, where
|
||||
the implementation of the function is provided by the renderer (as
|
||||
opposed to a function that the shader author writes in \langname
|
||||
@@ -6144,7 +6771,7 @@ full control in the shader.
|
||||
at a later time to yield a final numeric value.
|
||||
|
||||
\item[Connection.] A routing of the value of an \emph{output parameter}
|
||||
of one \emph{shader layer} to an \emph{input paramter} of another
|
||||
of one \emph{shader layer} to an \emph{input parameter} of another
|
||||
shader layer within the same \emph{shader group}.
|
||||
|
||||
\item[Default parameter value.] The initial value of a \emph{shader
|
||||
@@ -6155,6 +6782,9 @@ full control in the shader.
|
||||
is explicitly given in the code for that shader, and may either be
|
||||
a constant or a computed expression.
|
||||
|
||||
\item[EDF.] Emission distribution function, a function that describes
|
||||
the distribution of light emitted by a light source.
|
||||
|
||||
\item[Geometric primitive.] A single shape, such as a NURBS patch, a
|
||||
polygon or subdivision mesh, a hair primitive, etc.
|
||||
|
||||
@@ -6190,7 +6820,7 @@ full control in the shader.
|
||||
|
||||
\item[Primitive variable.] A named variable, and values, attached to an
|
||||
individual geometric primitive. Primitive variables may have one of
|
||||
serveral \emph{interpolation methods} --- such as a single value for
|
||||
several \emph{interpolation methods} --- such as a single value for
|
||||
the whole primitive, a value for each piece or face of the primitive,
|
||||
or per-vertex values that are smoothly interpolated across the
|
||||
surface.
|
||||
@@ -6199,12 +6829,12 @@ full control in the shader.
|
||||
that is visible and directly callable by the renderer, as opposed to
|
||||
merely being called from other code within the shader. Public methods
|
||||
must be \emph{top-level} (not defined within other functions) and must
|
||||
be preceeded by the {\cf public} keyword.
|
||||
be preceded by the {\cf public} keyword.
|
||||
|
||||
\item[Shader.] A small self-contained program written in \langname, used
|
||||
to extend the functionality of a renderer with custom behavior of
|
||||
materials and lights. A particular shader may have multiple
|
||||
\emph{shader instances} within a scene, each of which has ts unique
|
||||
\emph{shader instances} within a scene, each of which has its unique
|
||||
\emph{instance parameters}, transformation, etc.
|
||||
|
||||
\item[Shader function.] A function written in \langname that may be
|
||||
@@ -6239,6 +6869,9 @@ full control in the shader.
|
||||
\item[Shading.] The computations within a renderer that implement the
|
||||
behavior and visual appearance of materials and lights.
|
||||
|
||||
\item[VDF.] Volumetric distribution function, a function that describes
|
||||
the scattering properties of a volume.
|
||||
|
||||
\end{description}
|
||||
|
||||
\end{appendix}
|
||||
|
||||
Binary file not shown.
@@ -11,7 +11,7 @@
|
||||
_testshade_ basics
|
||||
==================================================
|
||||
|
||||
The OSL software distribution inculdes `testshade`, a command-line utility
|
||||
The OSL software distribution includes `testshade`, a command-line utility
|
||||
that was written for OSL unit tests, and for a "test harness" in which we
|
||||
can execute shaders for debugging (the shaders or OSL itself) in isolation
|
||||
from any particular rendering system.
|
||||
@@ -28,7 +28,7 @@ itself, it has a number of potential uses in a production studio, including:
|
||||
* Baking procedural patterns into textures.
|
||||
|
||||
* Benchmarking shaders and evaluating their performance, including
|
||||
comparitive tests such as "is it faster to code it this way or that way?"
|
||||
comparative tests such as "is it faster to code it this way or that way?"
|
||||
|
||||
* Exploring the inner workings of OSL's runtime optimizer, to answer
|
||||
questions like: "will this idiom optimize away at runtime when I use
|
||||
@@ -176,7 +176,7 @@ Helpful command line arguments:
|
||||
|
||||
For the sake of simplicity, this document presents almost all examples as if
|
||||
they consisted of just a single shader node. But `testshade` is able to
|
||||
specify and execut entire shader groups (networks of shader nodes). The
|
||||
specify and execute entire shader groups (networks of shader nodes). The
|
||||
remainder of this section will explain how this can be done.
|
||||
|
||||
Let's make a simple shader network as an example.
|
||||
@@ -582,7 +582,7 @@ single texture lookup.
|
||||
|
||||
|
||||
|
||||
## Controling optimization
|
||||
## Controlling optimization
|
||||
|
||||
You can control the optimization level overall:
|
||||
|
||||
@@ -638,7 +638,7 @@ that they are not optimized away so as to lead you to an inaccurate
|
||||
reflection of what optimizations would really happen at render time. At the
|
||||
same time, be careful not to inadvertently set `lockgeom=0` for parameters
|
||||
that will typically be set to default values, instance values, or
|
||||
connections from layers that are likely to be analized and found to emit
|
||||
connections from layers that are likely to be analyzed and found to emit
|
||||
constants for theor outputs -- you also don't want your benchmarks to
|
||||
incorrectly disable optimizations what would typically happen at render
|
||||
time.
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -68,7 +68,10 @@ 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; }
|
||||
OSL_HOSTDEVICE const char* c_str() const
|
||||
{
|
||||
return m_chars;
|
||||
}
|
||||
#endif
|
||||
|
||||
OSL_HOSTDEVICE bool operator==(const DeviceString& other) const
|
||||
@@ -93,7 +96,10 @@ struct DeviceString {
|
||||
return hash() != other;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE operator size_t() const { return hash(); }
|
||||
OSL_HOSTDEVICE operator size_t() const
|
||||
{
|
||||
return hash();
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
+34
-23
@@ -223,7 +223,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.
|
||||
@@ -383,13 +383,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
|
||||
@@ -660,26 +660,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);
|
||||
|
||||
@@ -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).
|
||||
// ...
|
||||
|
||||
+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
|
||||
|
||||
+32
-20
@@ -141,6 +141,19 @@ inline OSL_HOSTDEVICE float bits_to_01 (unsigned int bits) {
|
||||
}
|
||||
|
||||
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE int
|
||||
bitcast_to_uint (float x)
|
||||
{
|
||||
#if OPENIMAGEIO_VERSION >= 20500
|
||||
return OIIO::bitcast<unsigned int, float>(x);
|
||||
#else
|
||||
// obsolete call
|
||||
return OIIO::bit_cast<float, unsigned int>(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef __CUDA_ARCH__
|
||||
// Perform a bjmix (see OpenImageIO/hash.h) on 4 sets of values at once.
|
||||
OSL_FORCEINLINE void
|
||||
@@ -231,7 +244,7 @@ reference_inthash (const unsigned int k[N]) {
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE unsigned int
|
||||
inthash (const unsigned int k0, const unsigned int k1) {
|
||||
// now hash the data!
|
||||
unsigned int start_val = 0xdeadbeef + (2 << 2) + 13;
|
||||
unsigned int start_val = 0xdeadbeef + (2 << 2) + 13; //NOSONAR
|
||||
|
||||
unsigned int a = start_val + k0;
|
||||
unsigned int b = start_val + k1;
|
||||
@@ -467,7 +480,7 @@ struct HashNoise: public IntHashNoiseBase<HashNoise> {
|
||||
static OSL_FORCEINLINE OSL_HOSTDEVICE unsigned int
|
||||
transformToUint(float val)
|
||||
{
|
||||
return OIIO::bit_cast<float,unsigned int>(val);
|
||||
return bitcast_to_uint(val);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -544,7 +557,6 @@ using PeriodicHashNoise = PeriodicAdaptionOf<HashNoise>;
|
||||
|
||||
|
||||
|
||||
|
||||
inline OSL_HOSTDEVICE int
|
||||
inthashi (int x)
|
||||
{
|
||||
@@ -557,7 +569,7 @@ inline OSL_HOSTDEVICE int
|
||||
inthashf (float x)
|
||||
{
|
||||
return static_cast<int>(
|
||||
inthash(OIIO::bit_cast<float,unsigned int>(x))
|
||||
inthash(bitcast_to_uint(x))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -566,8 +578,8 @@ inthashf (float x, float y)
|
||||
{
|
||||
return static_cast<int>(
|
||||
inthash(
|
||||
OIIO::bit_cast<float,unsigned int>(x),
|
||||
OIIO::bit_cast<float,unsigned int>(y)
|
||||
bitcast_to_uint(x),
|
||||
bitcast_to_uint(y)
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -578,9 +590,9 @@ inthashf (const float *x)
|
||||
{
|
||||
return static_cast<int>(
|
||||
inthash(
|
||||
OIIO::bit_cast<float,unsigned int>(x[0]),
|
||||
OIIO::bit_cast<float,unsigned int>(x[1]),
|
||||
OIIO::bit_cast<float,unsigned int>(x[2])
|
||||
bitcast_to_uint(x[0]),
|
||||
bitcast_to_uint(x[1]),
|
||||
bitcast_to_uint(x[2])
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -591,10 +603,10 @@ inthashf (const float *x, float y)
|
||||
{
|
||||
return static_cast<int>(
|
||||
inthash(
|
||||
OIIO::bit_cast<float,unsigned int>(x[0]),
|
||||
OIIO::bit_cast<float,unsigned int>(x[1]),
|
||||
OIIO::bit_cast<float,unsigned int>(x[2]),
|
||||
OIIO::bit_cast<float,unsigned int>(y)
|
||||
bitcast_to_uint(x[0]),
|
||||
bitcast_to_uint(x[1]),
|
||||
bitcast_to_uint(x[2]),
|
||||
bitcast_to_uint(y)
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -1154,16 +1166,16 @@ private:
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE HashScalarPeriodic () {}
|
||||
public:
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE HashScalarPeriodic (float px) {
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1;
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1; //NOSONAR
|
||||
}
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE HashScalarPeriodic (float px, float py) {
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1;
|
||||
m_py = OIIO::ifloor(py); if (m_py < 1) m_py = 1;
|
||||
m_py = OIIO::ifloor(py); if (m_py < 1) m_py = 1; //NOSONAR
|
||||
}
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE HashScalarPeriodic (float px, float py, float pz) {
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1;
|
||||
m_py = OIIO::ifloor(py); if (m_py < 1) m_py = 1;
|
||||
m_pz = OIIO::ifloor(pz); if (m_pz < 1) m_pz = 1;
|
||||
m_pz = OIIO::ifloor(pz); if (m_pz < 1) m_pz = 1; //NOSONAR
|
||||
}
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE HashScalarPeriodic (float px, float py, float pz, float pw) {
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1;
|
||||
@@ -1225,16 +1237,16 @@ public:
|
||||
|
||||
struct HashVectorPeriodic {
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE HashVectorPeriodic (float px) {
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1;
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1; //NOSONAR
|
||||
}
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE HashVectorPeriodic (float px, float py) {
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1;
|
||||
m_py = OIIO::ifloor(py); if (m_py < 1) m_py = 1;
|
||||
m_py = OIIO::ifloor(py); if (m_py < 1) m_py = 1; //NOSONAR
|
||||
}
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE HashVectorPeriodic (float px, float py, float pz) {
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1;
|
||||
m_py = OIIO::ifloor(py); if (m_py < 1) m_py = 1;
|
||||
m_pz = OIIO::ifloor(pz); if (m_pz < 1) m_pz = 1;
|
||||
m_pz = OIIO::ifloor(pz); if (m_pz < 1) m_pz = 1; //NOSONAR
|
||||
}
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE HashVectorPeriodic (float px, float py, float pz, float pw) {
|
||||
m_px = OIIO::ifloor(px); if (m_px < 1) m_px = 1;
|
||||
@@ -1881,7 +1893,7 @@ OSL_FORCEINLINE OSL_HOSTDEVICE void perlin (Vec3 &result, const H &hash,
|
||||
u, v, w);
|
||||
result = scale3 (result);
|
||||
#else
|
||||
static_assert(std::is_same<Vec3i, decltype(hash(X, Y, Z))>::value, "This re-implementation was developed for Hashs returning a vector type only");
|
||||
static_assert(std::is_same<Vec3i, decltype(hash(X, Y, Z))>::value, "This re-implementation was developed for hashes returning a vector type only");
|
||||
// Want to avoid repeating the same hash work 3 times in a row
|
||||
// so rather than executing the vector version, we will use HashScalar
|
||||
// and directly mask its results on a per component basis
|
||||
|
||||
@@ -61,7 +61,7 @@ class OSOReaderQuery; // Just so OSLQuery can friend OSLReaderQuery
|
||||
/// ~~~
|
||||
///
|
||||
/// And the `Parameter` structure will hold all the information you need
|
||||
/// about that paramter. For example:
|
||||
/// about that parameter. For example:
|
||||
///
|
||||
/// ~~~
|
||||
/// std::cout << "Parameter " << p->name
|
||||
@@ -123,7 +123,7 @@ public:
|
||||
}
|
||||
///< Construct an OSLQuery and open a compiled shader from a disk file.
|
||||
/// The `shadername` may be either the name of the `.oso` file, or the
|
||||
/// name of the shader. The optional `searchpath` paramter gives a
|
||||
/// name of the shader. The optional `searchpath` parameter gives a
|
||||
/// colon-separated list of directories to search for compiled shaders.
|
||||
|
||||
OSL_DEPRECATED("Use ShadingSystem::oslquery(group,layernum)")
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#include <OSL/oslversion.h>
|
||||
@@ -482,15 +483,41 @@
|
||||
# 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 OSL_CPLUSPLUS_VERSION >= 20
|
||||
using std::assume_aligned;
|
||||
#else
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+34
-17
@@ -194,17 +194,17 @@ template<int WidthT> struct alignas(WidthT * sizeof(float)) VecReg {
|
||||
};
|
||||
|
||||
static_assert(std::alignment_of<VecReg<16>>::value == 64,
|
||||
"Unexepected alignment");
|
||||
"Unexpected alignment");
|
||||
static_assert(std::alignment_of<VecReg<8>>::value == 32,
|
||||
"Unexepected alignment");
|
||||
"Unexpected alignment");
|
||||
static_assert(std::alignment_of<VecReg<4>>::value == 16,
|
||||
"Unexepected alignment");
|
||||
"Unexpected alignment");
|
||||
static_assert(std::alignment_of<VecReg<16>>::value == VecReg<16>::alignment,
|
||||
"Unexepected alignment");
|
||||
"Unexpected alignment");
|
||||
static_assert(std::alignment_of<VecReg<8>>::value == VecReg<8>::alignment,
|
||||
"Unexepected alignment");
|
||||
"Unexpected alignment");
|
||||
static_assert(std::alignment_of<VecReg<4>>::value == VecReg<4>::alignment,
|
||||
"Unexepected alignment");
|
||||
"Unexpected alignment");
|
||||
|
||||
|
||||
template<typename BuiltinT, int WidthT>
|
||||
@@ -1535,7 +1535,7 @@ assume_aligned(Block<DataT, WidthT>* block_ptr)
|
||||
{
|
||||
static_assert(std::alignment_of<Block<DataT, WidthT>>::value
|
||||
== std::alignment_of<VecReg<WidthT>>::value,
|
||||
"Unexepected alignment");
|
||||
"Unexpected alignment");
|
||||
return assume_aligned<VecReg<WidthT>::alignment>(block_ptr);
|
||||
}
|
||||
|
||||
@@ -1545,7 +1545,7 @@ assume_aligned(const Block<DataT, WidthT>* block_ptr)
|
||||
{
|
||||
static_assert(std::alignment_of<Block<DataT, WidthT>>::value
|
||||
== std::alignment_of<VecReg<WidthT>>::value,
|
||||
"Unexepected alignment");
|
||||
"Unexpected alignment");
|
||||
return assume_aligned<VecReg<WidthT>::alignment>(block_ptr);
|
||||
}
|
||||
|
||||
@@ -2089,7 +2089,7 @@ struct UniformAsWide : public pvt::UniformAsWideImpl<DataT, WidthT> {
|
||||
template<typename DataT>
|
||||
struct WideTraits; // undefined, all types used should be specialized
|
||||
//{
|
||||
//static bool mathes(const TypeDesc &) { return false; }
|
||||
//static bool matches(const TypeDesc &) { return false; }
|
||||
//};
|
||||
|
||||
template<> struct WideTraits<float> {
|
||||
@@ -2128,7 +2128,7 @@ template<> struct WideTraits<ustring> {
|
||||
}
|
||||
};
|
||||
|
||||
// We let Vec3 match any vector semantics as we don't have a seperate Point or Normal classes
|
||||
// We let Vec3 match any vector semantics as we don't have a separate Point or Normal classes
|
||||
template<> struct WideTraits<Vec3> {
|
||||
static bool matches(const TypeDesc& type_desc)
|
||||
{
|
||||
@@ -2229,9 +2229,15 @@ template<typename DataT, int WidthT> struct MaskedLaneProxy {
|
||||
// visibility to end user whose IDE
|
||||
// might display these methods vs. free
|
||||
// functions
|
||||
OSL_FORCEINLINE bool is_on() const { return m_mask.is_on(m_lane); }
|
||||
OSL_FORCEINLINE bool is_on() const
|
||||
{
|
||||
return m_mask.is_on(m_lane);
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE bool is_off() const { return m_mask.is_off(m_lane); }
|
||||
OSL_FORCEINLINE bool is_off() const
|
||||
{
|
||||
return m_mask.is_off(m_lane);
|
||||
}
|
||||
|
||||
private:
|
||||
Block<DataT, WidthT>& m_ref_wide_data;
|
||||
@@ -2293,9 +2299,15 @@ struct MaskedArrayLaneProxy {
|
||||
// visibility to end user whose IDE
|
||||
// might display these methods vs. free
|
||||
// functions
|
||||
OSL_FORCEINLINE bool is_on() const { return m_mask.is_on(m_lane); }
|
||||
OSL_FORCEINLINE bool is_on() const
|
||||
{
|
||||
return m_mask.is_on(m_lane);
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE bool is_off() const { return m_mask.is_off(m_lane); }
|
||||
OSL_FORCEINLINE bool is_off() const
|
||||
{
|
||||
return m_mask.is_off(m_lane);
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE MaskedLaneProxy<DataT, WidthT>
|
||||
operator[](int array_index) const
|
||||
@@ -2727,19 +2739,24 @@ foreach_unique(Wide<DataT, WidthT> wdata, Mask<WidthT> data_mask, FunctorT f)
|
||||
do {
|
||||
ActiveLane lead_lane(remaining_mask.first_on());
|
||||
DataT lead_data = wdata[lead_lane];
|
||||
Mask<WidthT> matching_lanes(false);
|
||||
// Use int instead of Mask<> to allow reduction clause in openmp simd declaration
|
||||
int matching_lanes_bits { 0 };
|
||||
OSL_FORCEINLINE_BLOCK
|
||||
{
|
||||
OSL_OMP_PRAGMA(omp simd simdlen(WidthT))
|
||||
OSL_OMP_PRAGMA(omp simd simdlen(WidthT)
|
||||
reduction(|
|
||||
: matching_lanes_bits))
|
||||
for (int lane = 0; lane < WidthT; ++lane) {
|
||||
// NOTE: the comparison ignores the remaining_mask
|
||||
bool lane_matches = (lead_data == wdata[lane]);
|
||||
// NOTE: using bitwise & to avoid branches
|
||||
if (lane_matches & remaining_mask[lane]) {
|
||||
matching_lanes.set_on(lane);
|
||||
// inline of Mask::set_on(lane)
|
||||
matching_lanes_bits |= 1 << lane;
|
||||
}
|
||||
}
|
||||
}
|
||||
Mask<WidthT> matching_lanes { matching_lanes_bits };
|
||||
|
||||
f(lead_data, matching_lanes);
|
||||
remaining_mask &= ~matching_lanes;
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace __OSL_WIDE_PVT {
|
||||
|
||||
OSL_USING_DATA_WIDTH(__OSL_WIDTH)
|
||||
|
||||
// Foward declaration, implementation is in liboslnoise/wide_gabornoise.h
|
||||
// Forward declaration, implementation is in liboslnoise/wide_gabornoise.h
|
||||
struct DisabledFilterPolicy {
|
||||
static constexpr bool active = false;
|
||||
};
|
||||
@@ -34,7 +34,7 @@ OSL_NOINLINE void
|
||||
wide_gabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
|
||||
NoiseParams const* opt, Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_gabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
|
||||
@@ -46,20 +46,20 @@ OSL_NOINLINE void
|
||||
wide_gabor(Masked<Dual2<float>> wResult, Wide<const Dual2<Vec3>> wP,
|
||||
NoiseParams const* opt, Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_gabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
|
||||
NoiseParams const* opt, Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_gabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
|
||||
Wide<const Dual2<float>> wY, NoiseParams const* opt,
|
||||
Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_gabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<Vec3>> wP,
|
||||
@@ -71,14 +71,14 @@ wide_gabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<Vec3>> wP,
|
||||
// Periodic gabor(s)
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
|
||||
Wide<const float> wXp, NoiseParams const* opt,
|
||||
Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
|
||||
@@ -86,7 +86,7 @@ wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
|
||||
Wide<const float> wYp, NoiseParams const* opt,
|
||||
Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<Vec3>> wP,
|
||||
@@ -95,14 +95,14 @@ wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<Vec3>> wP,
|
||||
|
||||
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_pgabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
|
||||
Wide<const float> wXp, NoiseParams const* opt,
|
||||
Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_pgabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
|
||||
@@ -110,7 +110,7 @@ wide_pgabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
|
||||
Wide<const float> wYp, NoiseParams const* opt,
|
||||
Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_pgabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<Vec3>> wP,
|
||||
|
||||
+214
-55
@@ -558,7 +558,7 @@ public:
|
||||
///
|
||||
void scope(int s) { m_scope = s; }
|
||||
|
||||
/// Return teh AST node containing the declaration of this symbol.
|
||||
/// Return the AST node containing the declaration of this symbol.
|
||||
/// Use with care!
|
||||
ASTNode* node() const { return m_node; }
|
||||
|
||||
@@ -633,55 +633,133 @@ public:
|
||||
}
|
||||
|
||||
|
||||
void dataoffset(int d) { m_dataoffset = d; }
|
||||
int dataoffset() const { return m_dataoffset; }
|
||||
void dataoffset(int d)
|
||||
{
|
||||
m_dataoffset = d;
|
||||
}
|
||||
int dataoffset() const
|
||||
{
|
||||
return m_dataoffset;
|
||||
}
|
||||
|
||||
void wide_dataoffset(int d) { m_wide_dataoffset = d; }
|
||||
int wide_dataoffset() const { return m_wide_dataoffset; }
|
||||
void wide_dataoffset(int d)
|
||||
{
|
||||
m_wide_dataoffset = d;
|
||||
}
|
||||
int wide_dataoffset() const
|
||||
{
|
||||
return m_wide_dataoffset;
|
||||
}
|
||||
|
||||
SymArena arena() const { return static_cast<SymArena>(m_arena); }
|
||||
SymArena arena() const
|
||||
{
|
||||
return static_cast<SymArena>(m_arena);
|
||||
}
|
||||
|
||||
void initializers(int d) { m_initializers = d; }
|
||||
int initializers() const { return m_initializers; }
|
||||
void initializers(int d)
|
||||
{
|
||||
m_initializers = d;
|
||||
}
|
||||
int initializers() const
|
||||
{
|
||||
return m_initializers;
|
||||
}
|
||||
|
||||
bool has_derivs() const { return m_has_derivs; }
|
||||
void has_derivs(bool new_derivs) { m_has_derivs = new_derivs; }
|
||||
int size() const { return m_size; }
|
||||
void size(size_t newsize) { m_size = (int)newsize; }
|
||||
bool has_derivs() const
|
||||
{
|
||||
return m_has_derivs;
|
||||
}
|
||||
void has_derivs(bool new_derivs)
|
||||
{
|
||||
m_has_derivs = new_derivs;
|
||||
}
|
||||
int size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
void size(size_t newsize)
|
||||
{
|
||||
m_size = (int)newsize;
|
||||
}
|
||||
|
||||
/// Return the size for each point, including derivs.
|
||||
///
|
||||
int derivsize() const { return m_has_derivs ? 3 * m_size : m_size; }
|
||||
int derivsize() const
|
||||
{
|
||||
return m_has_derivs ? 3 * m_size : m_size;
|
||||
}
|
||||
|
||||
bool connected() const { return valuesource() == ConnectedVal; }
|
||||
bool connected_down() const { return m_connected_down; }
|
||||
void connected_down(bool c) { m_connected_down = c; }
|
||||
bool connected() const
|
||||
{
|
||||
return valuesource() == ConnectedVal;
|
||||
}
|
||||
bool connected_down() const
|
||||
{
|
||||
return m_connected_down;
|
||||
}
|
||||
void connected_down(bool c)
|
||||
{
|
||||
m_connected_down = c;
|
||||
}
|
||||
|
||||
/// Where did the symbol's value come from?
|
||||
///
|
||||
enum ValueSource { DefaultVal, InstanceVal, GeomVal, ConnectedVal };
|
||||
|
||||
ValueSource valuesource() const { return (ValueSource)m_valuesource; }
|
||||
void valuesource(ValueSource v) { m_valuesource = v; }
|
||||
ValueSource valuesource() const
|
||||
{
|
||||
return (ValueSource)m_valuesource;
|
||||
}
|
||||
void valuesource(ValueSource v)
|
||||
{
|
||||
m_valuesource = v;
|
||||
}
|
||||
const char* valuesourcename() const;
|
||||
static const char* valuesourcename(ValueSource v);
|
||||
|
||||
int fieldid() const { return m_fieldid; }
|
||||
void fieldid(int id) { m_fieldid = id; }
|
||||
int fieldid() const
|
||||
{
|
||||
return m_fieldid;
|
||||
}
|
||||
void fieldid(int id)
|
||||
{
|
||||
m_fieldid = id;
|
||||
}
|
||||
|
||||
int layer() const { return m_layer; }
|
||||
void layer(int id) { m_layer = id; }
|
||||
int layer() const
|
||||
{
|
||||
return m_layer;
|
||||
}
|
||||
void layer(int id)
|
||||
{
|
||||
m_layer = id;
|
||||
}
|
||||
|
||||
int initbegin() const { return m_initbegin; }
|
||||
void initbegin(int i) { m_initbegin = i; }
|
||||
int initend() const { return m_initend; }
|
||||
void initend(int i) { m_initend = i; }
|
||||
int initbegin() const
|
||||
{
|
||||
return m_initbegin;
|
||||
}
|
||||
void initbegin(int i)
|
||||
{
|
||||
m_initbegin = i;
|
||||
}
|
||||
int initend() const
|
||||
{
|
||||
return m_initend;
|
||||
}
|
||||
void initend(int i)
|
||||
{
|
||||
m_initend = i;
|
||||
}
|
||||
void set_initrange(int b = 0, int e = 0)
|
||||
{
|
||||
m_initbegin = b;
|
||||
m_initend = e;
|
||||
}
|
||||
bool has_init_ops() const { return m_initbegin != m_initend; }
|
||||
bool has_init_ops() const
|
||||
{
|
||||
return m_initbegin != m_initend;
|
||||
}
|
||||
|
||||
/// Clear read/write usage info.
|
||||
///
|
||||
@@ -725,15 +803,42 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
int firstread() const { return m_firstread; }
|
||||
int lastread() const { return m_lastread; }
|
||||
int firstwrite() const { return m_firstwrite; }
|
||||
int lastwrite() const { return m_lastwrite; }
|
||||
int firstuse() const { return std::min(firstread(), firstwrite()); }
|
||||
int lastuse() const { return std::max(lastread(), lastwrite()); }
|
||||
bool everread() const { return lastread() >= 0; }
|
||||
bool everwritten() const { return lastwrite() >= 0; }
|
||||
bool everused() const { return everread() || everwritten(); }
|
||||
int firstread() const
|
||||
{
|
||||
return m_firstread;
|
||||
}
|
||||
int lastread() const
|
||||
{
|
||||
return m_lastread;
|
||||
}
|
||||
int firstwrite() const
|
||||
{
|
||||
return m_firstwrite;
|
||||
}
|
||||
int lastwrite() const
|
||||
{
|
||||
return m_lastwrite;
|
||||
}
|
||||
int firstuse() const
|
||||
{
|
||||
return std::min(firstread(), firstwrite());
|
||||
}
|
||||
int lastuse() const
|
||||
{
|
||||
return std::max(lastread(), lastwrite());
|
||||
}
|
||||
bool everread() const
|
||||
{
|
||||
return lastread() >= 0;
|
||||
}
|
||||
bool everwritten() const
|
||||
{
|
||||
return lastwrite() >= 0;
|
||||
}
|
||||
bool everused() const
|
||||
{
|
||||
return everread() || everwritten();
|
||||
}
|
||||
// everused_in_group is an even more stringent test -- not only must
|
||||
// the symbol not be used within the shader but it also must not be
|
||||
// used elsewhere in the group, by being connected to something downstream
|
||||
@@ -754,31 +859,67 @@ public:
|
||||
m_lastwrite = last;
|
||||
}
|
||||
|
||||
bool initialized() const { return m_initialized; }
|
||||
void initialized(bool init) { m_initialized = init; }
|
||||
bool initialized() const
|
||||
{
|
||||
return m_initialized;
|
||||
}
|
||||
void initialized(bool init)
|
||||
{
|
||||
m_initialized = init;
|
||||
}
|
||||
|
||||
bool lockgeom() const { return m_lockgeom; }
|
||||
void lockgeom(bool lock) { m_lockgeom = lock; }
|
||||
bool lockgeom() const
|
||||
{
|
||||
return m_lockgeom;
|
||||
}
|
||||
void lockgeom(bool lock)
|
||||
{
|
||||
m_lockgeom = lock;
|
||||
}
|
||||
|
||||
bool allowconnect() const { return m_allowconnect; }
|
||||
void allowconnect(bool val) { m_allowconnect = val; }
|
||||
bool allowconnect() const
|
||||
{
|
||||
return m_allowconnect;
|
||||
}
|
||||
void allowconnect(bool val)
|
||||
{
|
||||
m_allowconnect = val;
|
||||
}
|
||||
|
||||
int arraylen() const { return m_typespec.arraylength(); }
|
||||
int arraylen() const
|
||||
{
|
||||
return m_typespec.arraylength();
|
||||
}
|
||||
void arraylen(int len)
|
||||
{
|
||||
m_typespec.make_array(len);
|
||||
m_size = m_typespec.simpletype().size();
|
||||
}
|
||||
|
||||
bool renderer_output() const { return m_renderer_output; }
|
||||
void renderer_output(bool v) { m_renderer_output = v; }
|
||||
bool renderer_output() const
|
||||
{
|
||||
return m_renderer_output;
|
||||
}
|
||||
void renderer_output(bool v)
|
||||
{
|
||||
m_renderer_output = v;
|
||||
}
|
||||
|
||||
// When not uniform a symbol will have a varying value under batched
|
||||
// execution and must use a Wide data type to hold different values
|
||||
// for each data lane executing
|
||||
bool is_uniform() const { return m_is_uniform; }
|
||||
bool is_varying() const { return (m_is_uniform == 0); }
|
||||
void make_varying() { m_is_uniform = false; }
|
||||
bool is_uniform() const
|
||||
{
|
||||
return m_is_uniform;
|
||||
}
|
||||
bool is_varying() const
|
||||
{
|
||||
return (m_is_uniform == 0);
|
||||
}
|
||||
void make_varying()
|
||||
{
|
||||
m_is_uniform = false;
|
||||
}
|
||||
|
||||
// Results of a compare_op and other ops with logically boolean
|
||||
// results under certain conditions could be forced to be represented
|
||||
@@ -792,14 +933,32 @@ public:
|
||||
// The value of forced_llvm_bool() is currently only respected during
|
||||
// batched execution. Forced bools should not be coalesced with regular
|
||||
// ints, only other forced bools.
|
||||
bool forced_llvm_bool() const { return m_forced_llvm_bool; }
|
||||
void forced_llvm_bool(bool v) { m_forced_llvm_bool = v; }
|
||||
bool forced_llvm_bool() const
|
||||
{
|
||||
return m_forced_llvm_bool;
|
||||
}
|
||||
void forced_llvm_bool(bool v)
|
||||
{
|
||||
m_forced_llvm_bool = v;
|
||||
}
|
||||
|
||||
bool readonly() const { return m_readonly; }
|
||||
void readonly(bool v) { m_readonly = v; }
|
||||
bool readonly() const
|
||||
{
|
||||
return m_readonly;
|
||||
}
|
||||
void readonly(bool v)
|
||||
{
|
||||
m_readonly = v;
|
||||
}
|
||||
|
||||
bool is_constant() const { return symtype() == SymTypeConst; }
|
||||
bool is_temp() const { return symtype() == SymTypeTemp; }
|
||||
bool is_constant() const
|
||||
{
|
||||
return symtype() == SymTypeConst;
|
||||
}
|
||||
bool is_temp() const
|
||||
{
|
||||
return symtype() == SymTypeTemp;
|
||||
}
|
||||
|
||||
// Retrieve the const float value (must be a const float!)
|
||||
float get_float(int index = 0) const
|
||||
@@ -855,7 +1014,7 @@ public:
|
||||
|
||||
// Stream output. Note that print/print_vals assume that any string
|
||||
// values are "raw" and they will be converted to C source code "escaped
|
||||
// string" notation for printing. For example, a newline characer will
|
||||
// string" notation for printing. For example, a newline character will
|
||||
// be rendered into the stream as the two character sequence '\n'.
|
||||
std::ostream& print(std::ostream& out, int maxvals = 100000000) const;
|
||||
std::ostream& print_vals(std::ostream& out, int maxvals = 100000000) const;
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -375,7 +375,7 @@ protected:
|
||||
void codegen_initlist(ref init, TypeSpec type, Symbol* sym);
|
||||
|
||||
// Special code generation for structure initializers.
|
||||
// It's in the ASTNode base class because it's used from mutiple
|
||||
// It's in the ASTNode base class because it's used from multiple
|
||||
// subclasses.
|
||||
Symbol* codegen_struct_initializers(ref init, Symbol* sym,
|
||||
bool is_constructor = false,
|
||||
@@ -520,7 +520,7 @@ public:
|
||||
|
||||
private:
|
||||
ustring m_name; ///< Name of the symbol (unmangled)
|
||||
Symbol* m_sym; ///< Ptr to the symbol this declares
|
||||
Symbol* m_sym; ///< Ptr to the symbol this declares (non-owning)
|
||||
bool m_isparam; ///< Is this a parameter?
|
||||
bool m_isoutput; ///< Is this an output parameter?
|
||||
bool m_ismetadata; ///< Is this declaration a piece of metadata?
|
||||
@@ -529,6 +529,7 @@ private:
|
||||
// specific initializers.
|
||||
typedef std::pair<ustring, ASTNode*> NamedInit;
|
||||
std::vector<NamedInit> m_struct_field_inits;
|
||||
std::unique_ptr<Symbol> m_sym_owned; // if we own the symbol
|
||||
};
|
||||
|
||||
|
||||
@@ -949,7 +950,7 @@ private:
|
||||
/// return false and call an appropriate error().
|
||||
bool typecheck_printf_args(const char* format, ASTNode* arg);
|
||||
|
||||
/// Handle "funcion calls" that are really struct ctrs.
|
||||
/// Handle "function calls" that are really struct ctrs.
|
||||
TypeSpec typecheck_struct_constructor();
|
||||
|
||||
/// Is the argument number 'arg' read by the op?
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -1305,7 +1305,7 @@ OSLCompilerImpl::track_variable_dependencies()
|
||||
// This naivite will never miss a dependency, but it may
|
||||
// overestimate dependencies. (Hence we call this "conservative"
|
||||
// rather than "wrong.") We deem this acceptable for now, since
|
||||
// it's so much easer to implement the conservative dependency
|
||||
// it's so much easier to implement the conservative dependency
|
||||
// analysis, and it's not yet clear that getting it closer to
|
||||
// optimal will have any performance impact on final shaders. Also
|
||||
// because this is probably no worse than the "dependency slop" that
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
+199
-195
@@ -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,7 +20,8 @@ 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;
|
||||
// This is for the transition table used in DfAutomata::State
|
||||
@@ -33,7 +34,7 @@ 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
|
||||
|
||||
@@ -259,7 +259,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),
|
||||
fmtformat("glob_{}_voidptr", name));
|
||||
}
|
||||
|
||||
|
||||
@@ -651,7 +652,7 @@ BackendLLVM::llvm_load_value(const Symbol& sym, int deriv,
|
||||
}
|
||||
|
||||
return llvm_load_value(llvm_get_pointer(sym), sym.typespec(), deriv,
|
||||
arrayindex, component, cast);
|
||||
arrayindex, component, cast, sym.name().string());
|
||||
}
|
||||
|
||||
|
||||
@@ -659,7 +660,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 +682,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;
|
||||
|
||||
+199
-173
@@ -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,68 @@ 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 (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);
|
||||
}
|
||||
|
||||
/// 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);
|
||||
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 use_optix() ? llvm_load_device_string(sym, /*follow*/ true)
|
||||
: llvm_load_value(sym);
|
||||
}
|
||||
|
||||
/// 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);
|
||||
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 +167,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 +176,156 @@ public:
|
||||
/// and the symbol doesn't have a deriv, it's a nop. If the
|
||||
/// component >0 and it's a scalar, set the scalar. Returns true if
|
||||
/// ok, false upon failure.
|
||||
bool llvm_store_value (llvm::Value* new_val, llvm::Value* dst_ptr,
|
||||
const TypeSpec &type, int deriv,
|
||||
llvm::Value* arrayindex, int component);
|
||||
bool llvm_store_value(llvm::Value* new_val, llvm::Value* dst_ptr,
|
||||
const TypeSpec& type, int deriv,
|
||||
llvm::Value* arrayindex, int component);
|
||||
|
||||
/// Non-array version of llvm_store_value, with default deriv &
|
||||
/// component.
|
||||
bool llvm_store_value (llvm::Value *new_val, const Symbol& sym,
|
||||
int deriv=0, int component=0) {
|
||||
return llvm_store_value (new_val, sym, deriv, NULL, component);
|
||||
bool llvm_store_value(llvm::Value* new_val, const Symbol& sym,
|
||||
int deriv = 0, int component = 0)
|
||||
{
|
||||
return llvm_store_value(new_val, sym, deriv, NULL, component);
|
||||
}
|
||||
|
||||
/// llvm_store_value with non-constant component designation. Does
|
||||
/// not work with arrays or do type casts!
|
||||
bool llvm_store_component_value (llvm::Value *new_val, const Symbol& sym,
|
||||
int deriv, llvm::Value *component);
|
||||
bool llvm_store_component_value(llvm::Value* new_val, const Symbol& sym,
|
||||
int deriv, llvm::Value* component);
|
||||
|
||||
/// Legacy version
|
||||
///
|
||||
bool storeLLVMValue (llvm::Value* new_val, const Symbol& sym,
|
||||
int component=0, int deriv=0) {
|
||||
return llvm_store_value (new_val, sym, deriv, component);
|
||||
bool storeLLVMValue(llvm::Value* new_val, const Symbol& sym,
|
||||
int component = 0, int deriv = 0)
|
||||
{
|
||||
return llvm_store_value(new_val, sym, deriv, component);
|
||||
}
|
||||
|
||||
/// Generate an alloca instruction to allocate space for the given
|
||||
/// type, with derivs if derivs==true, and return the its pointer.
|
||||
llvm::Value *llvm_alloca (const TypeSpec &type, bool derivs,
|
||||
const std::string &name="", int align=0);
|
||||
llvm::Value* llvm_alloca(const TypeSpec& type, bool derivs,
|
||||
const std::string& name = "", int align = 0);
|
||||
|
||||
/// Given the OSL symbol, return the llvm::Value* corresponding to the
|
||||
/// address of the start of that symbol (first element, first component,
|
||||
/// and just the plain value if it has derivatives). This is retrieved
|
||||
/// from the allocation map if already there; and if not yet in the
|
||||
/// map, the symbol is alloca'd and placed in the map.
|
||||
llvm::Value *getOrAllocateLLVMSymbol (const Symbol& sym);
|
||||
llvm::Value* getOrAllocateLLVMSymbol(const Symbol& sym);
|
||||
|
||||
/// Allocate a CUDA variable for the given OSL symbol and return a pointer
|
||||
/// to the corresponding LLVM GlobalVariable, or return the pointer if it
|
||||
/// has already been allocated.
|
||||
llvm::Value *getOrAllocateCUDAVariable (const Symbol& sym, bool addMetadata=false);
|
||||
llvm::Value* getOrAllocateCUDAVariable(const Symbol& sym,
|
||||
bool addMetadata = false);
|
||||
|
||||
/// 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);
|
||||
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 );
|
||||
void createOptixMetadata(const std::string& name, const Symbol& sym);
|
||||
|
||||
/// 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());
|
||||
}
|
||||
|
||||
llvm::Value *llvm_ptr_cast (llvm::Value* val, const TypeSpec &type) {
|
||||
return ll.ptr_cast (val, type.simpletype());
|
||||
}
|
||||
|
||||
llvm::Value *llvm_void_ptr (const Symbol &sym, int deriv=0) {
|
||||
return ll.void_ptr (llvm_get_pointer(sym, deriv));
|
||||
llvm::Value* llvm_void_ptr(const Symbol& sym, int deriv = 0)
|
||||
{
|
||||
return ll.void_ptr(llvm_get_pointer(sym, deriv));
|
||||
}
|
||||
|
||||
/// 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 +336,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 +384,147 @@ 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) {
|
||||
TypeDesc llvm_typedesc(const TypeSpec& typespec)
|
||||
{
|
||||
return typespec.is_closure_based()
|
||||
? TypeDesc(TypeDesc::PTR, typespec.arraylength())
|
||||
: typespec.simpletype();
|
||||
? TypeDesc(TypeDesc::PTR, typespec.arraylength())
|
||||
: typespec.simpletype();
|
||||
}
|
||||
|
||||
/// Generate the appropriate llvm type definition for a TypeSpec
|
||||
/// (this is the actual type, for example when we allocate it).
|
||||
/// Allocates ptrs for closures.
|
||||
llvm::Type *llvm_type (const TypeSpec &typespec) {
|
||||
return ll.llvm_type (llvm_typedesc(typespec));
|
||||
llvm::Type* llvm_type(const TypeSpec& typespec)
|
||||
{
|
||||
return ll.llvm_type(llvm_typedesc(typespec));
|
||||
}
|
||||
|
||||
/// Generate the parameter-passing llvm type definition for an OSL
|
||||
/// TypeSpec.
|
||||
llvm::Type *llvm_pass_type (const TypeSpec &typespec);
|
||||
llvm::Type* llvm_pass_type(const TypeSpec& typespec);
|
||||
|
||||
llvm::PointerType *llvm_type_prepare_closure_func() { return m_llvm_type_prepare_closure_func; }
|
||||
llvm::PointerType *llvm_type_setup_closure_func() { return m_llvm_type_setup_closure_func; }
|
||||
|
||||
/// Return the basic block of the exit for the whole instance.
|
||||
///
|
||||
bool llvm_has_exit_instance_block () const {
|
||||
return m_exit_instance_block;
|
||||
llvm::PointerType* llvm_type_prepare_closure_func()
|
||||
{
|
||||
return m_llvm_type_prepare_closure_func;
|
||||
}
|
||||
llvm::PointerType* llvm_type_setup_closure_func()
|
||||
{
|
||||
return m_llvm_type_setup_closure_func;
|
||||
}
|
||||
|
||||
/// Return the basic block of the exit for the whole instance.
|
||||
///
|
||||
llvm::BasicBlock *llvm_exit_instance_block () {
|
||||
if (! m_exit_instance_block) {
|
||||
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(),
|
||||
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;
|
||||
}
|
||||
|
||||
/// Return the mapping from symbol names to GlobalVariables.
|
||||
std::map<std::string,llvm::GlobalVariable*>& get_const_map() { return m_const_map; }
|
||||
std::map<std::string, llvm::GlobalVariable*>& get_const_map()
|
||||
{
|
||||
return m_const_map;
|
||||
}
|
||||
|
||||
/// Return whether or not we are compiling for an OptiX-based renderer.
|
||||
bool use_optix() { return m_use_optix; }
|
||||
|
||||
/// Return if we should compile against free function versions of Renderer Service.
|
||||
bool use_rs_bitcode() {return m_use_rs_bitcode; }
|
||||
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
|
||||
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
|
||||
double m_stat_total_llvm_time; ///< total time spent on LLVM
|
||||
double m_stat_llvm_setup_time; ///< llvm setup time
|
||||
double m_stat_llvm_irgen_time; ///< llvm IR generation time
|
||||
double m_stat_llvm_opt_time; ///< llvm IR optimization time
|
||||
double m_stat_llvm_jit_time; ///< llvm JIT time
|
||||
|
||||
// LLVM stuff
|
||||
AllocationMap m_named_values;
|
||||
std::map<const Symbol*,int> m_param_order_map;
|
||||
llvm::Value *m_llvm_shaderglobals_ptr;
|
||||
llvm::Value *m_llvm_groupdata_ptr;
|
||||
llvm::Value *m_llvm_userdata_base_ptr;
|
||||
llvm::Value *m_llvm_output_base_ptr;
|
||||
llvm::Value *m_llvm_shadeindex;
|
||||
llvm::BasicBlock * m_exit_instance_block; // exit point for the instance
|
||||
llvm::Type *m_llvm_type_sg; // LLVM type of ShaderGlobals struct
|
||||
llvm::Type *m_llvm_type_groupdata; // LLVM type of group data
|
||||
llvm::Type *m_llvm_type_closure_component; // LLVM type for ClosureComponent
|
||||
llvm::PointerType *m_llvm_type_prepare_closure_func;
|
||||
llvm::PointerType *m_llvm_type_setup_closure_func;
|
||||
int m_llvm_local_mem; // Amount of memory we use for locals
|
||||
std::map<const Symbol*, int> m_param_order_map;
|
||||
llvm::Value* m_llvm_shaderglobals_ptr;
|
||||
llvm::Value* m_llvm_groupdata_ptr;
|
||||
llvm::Value* m_llvm_userdata_base_ptr;
|
||||
llvm::Value* m_llvm_output_base_ptr;
|
||||
llvm::Value* m_llvm_shadeindex;
|
||||
llvm::BasicBlock* m_exit_instance_block; // exit point for the instance
|
||||
llvm::Type* m_llvm_type_sg; // LLVM type of ShaderGlobals struct
|
||||
llvm::Type* m_llvm_type_groupdata; // LLVM type of group data
|
||||
llvm::Type* m_llvm_type_closure_component; // LLVM type for ClosureComponent
|
||||
llvm::PointerType* m_llvm_type_prepare_closure_func;
|
||||
llvm::PointerType* m_llvm_type_setup_closure_func;
|
||||
int m_llvm_local_mem; // Amount of memory we use for locals
|
||||
|
||||
// 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;
|
||||
std::map<std::string, std::string> m_varname_map;
|
||||
|
||||
bool m_use_optix; ///< Compile for OptiX?
|
||||
bool m_use_optix; ///< Compile for OptiX?
|
||||
|
||||
bool m_use_rs_bitcode; /// To use free function versions of Renderer Service functions.
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -1846,7 +1846,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 +1904,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)
|
||||
|
||||
@@ -164,7 +164,7 @@ public:
|
||||
llvm::Value* llvm_load_mask(const Symbol& cond);
|
||||
|
||||
/// Return an llvm::Value* that is either a scalar and derivs is
|
||||
/// false, or a pointer to sym's values (if sym is an aggreate or
|
||||
/// false, or a pointer to sym's values (if sym is an aggregate or
|
||||
/// derivs == true). Furthermore, if deriv == true and sym doesn't
|
||||
/// have derivs, coerce it into a variable with zero derivs.
|
||||
llvm::Value* llvm_load_arg(const Symbol& sym, bool derivs,
|
||||
@@ -278,9 +278,9 @@ public:
|
||||
|
||||
public:
|
||||
TempScope(BatchedBackendLLVM& backend);
|
||||
TempScope(const TempScope& other) = delete;
|
||||
TempScope(const TempScope&& other) = delete;
|
||||
TempScope& operator=(const TempScope& other) = delete;
|
||||
TempScope(const TempScope& other) = delete;
|
||||
TempScope(const TempScope&& other) = delete;
|
||||
TempScope& operator=(const TempScope& other) = delete;
|
||||
TempScope& operator=(const TempScope&& other) = delete;
|
||||
~TempScope();
|
||||
};
|
||||
@@ -331,7 +331,7 @@ public:
|
||||
/// derivs are zero.
|
||||
llvm::Value* llvm_test_nonzero(const Symbol& val, bool test_derivs = false);
|
||||
|
||||
/// Implementaiton of Simple assignment. If arrayindex >= 0, in
|
||||
/// Implementation of Simple assignment. If arrayindex >= 0, in
|
||||
/// designates a particular array index to assign.
|
||||
bool llvm_assign_impl(const Symbol& Result, const Symbol& Src,
|
||||
int arrayindex = -1, int srccomp = -1,
|
||||
@@ -489,7 +489,7 @@ public:
|
||||
|
||||
// Encapsulate creation of function names that encode parameter types,
|
||||
// including if each is varying or uniform, and if a mask is required.
|
||||
// Utilize llvm::Twine to efficently combine multiple strings
|
||||
// Utilize llvm::Twine to efficiently combine multiple strings
|
||||
// Usage is to start with the function name then append arguments,
|
||||
// and at any point masking can be turned on/off as well as batching.
|
||||
// The effect of disabling batching would be the function name is
|
||||
@@ -533,7 +533,7 @@ public:
|
||||
ArgVector m_args;
|
||||
|
||||
public:
|
||||
FuncSpec(const FuncSpec&) = delete;
|
||||
FuncSpec(const FuncSpec&) = delete;
|
||||
FuncSpec& operator=(const FuncSpec&) = delete;
|
||||
|
||||
FuncSpec(const llvm::Twine& name)
|
||||
|
||||
@@ -557,7 +557,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 +605,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 +687,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 +1110,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
|
||||
@@ -2302,7 +2302,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 +2418,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 +2534,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 +2636,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 +2955,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 +3547,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 +3570,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 +5750,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
|
||||
@@ -7181,7 +7181,7 @@ LLVMGEN(llvm_gen_closure)
|
||||
llvm::Value* comp_wide_ptr = rop.ll.op_load(comp_wide_ptr_ptr);
|
||||
|
||||
// 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);
|
||||
@@ -8191,7 +8191,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
|
||||
@@ -894,7 +894,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();
|
||||
@@ -1126,7 +1126,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);
|
||||
|
||||
|
||||
+276
-277
@@ -11,119 +11,118 @@
|
||||
|
||||
|
||||
#ifndef DECL
|
||||
#error Do not include this file unless DECL is defined
|
||||
# error Do not include this file unless DECL is defined
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define NOISE_IMPL(name) \
|
||||
DECL (osl_ ## name ## _ff, "ff") \
|
||||
DECL (osl_ ## name ## _fff, "fff") \
|
||||
DECL (osl_ ## name ## _fv, "fv") \
|
||||
DECL (osl_ ## name ## _fvf, "fvf") \
|
||||
DECL (osl_ ## name ## _vf, "xvf") \
|
||||
DECL (osl_ ## name ## _vff, "xvff") \
|
||||
DECL (osl_ ## name ## _vv, "xvv") \
|
||||
DECL (osl_ ## name ## _vvf, "xvvf")
|
||||
#define NOISE_IMPL(name) \
|
||||
DECL(osl_##name##_ff, "ff") \
|
||||
DECL(osl_##name##_fff, "fff") \
|
||||
DECL(osl_##name##_fv, "fv") \
|
||||
DECL(osl_##name##_fvf, "fvf") \
|
||||
DECL(osl_##name##_vf, "xvf") \
|
||||
DECL(osl_##name##_vff, "xvff") \
|
||||
DECL(osl_##name##_vv, "xvv") \
|
||||
DECL(osl_##name##_vvf, "xvvf")
|
||||
|
||||
#define NOISE_DERIV_IMPL(name) \
|
||||
DECL (osl_ ## name ## _dfdf, "xXX") \
|
||||
DECL (osl_ ## name ## _dfdff, "xXXf") \
|
||||
DECL (osl_ ## name ## _dffdf, "xXfX") \
|
||||
DECL (osl_ ## name ## _dfdfdf, "xXXX") \
|
||||
DECL (osl_ ## name ## _dfdv, "xXv") \
|
||||
DECL (osl_ ## name ## _dfdvf, "xXvf") \
|
||||
DECL (osl_ ## name ## _dfvdf, "xXvX") \
|
||||
DECL (osl_ ## name ## _dfdvdf, "xXvX") \
|
||||
DECL (osl_ ## name ## _dvdf, "xvX") \
|
||||
DECL (osl_ ## name ## _dvdff, "xvXf") \
|
||||
DECL (osl_ ## name ## _dvfdf, "xvfX") \
|
||||
DECL (osl_ ## name ## _dvdfdf, "xvXX") \
|
||||
DECL (osl_ ## name ## _dvdv, "xvv") \
|
||||
DECL (osl_ ## name ## _dvdvf, "xvvf") \
|
||||
DECL (osl_ ## name ## _dvvdf, "xvvX") \
|
||||
DECL (osl_ ## name ## _dvdvdf, "xvvX")
|
||||
#define NOISE_DERIV_IMPL(name) \
|
||||
DECL(osl_##name##_dfdf, "xXX") \
|
||||
DECL(osl_##name##_dfdff, "xXXf") \
|
||||
DECL(osl_##name##_dffdf, "xXfX") \
|
||||
DECL(osl_##name##_dfdfdf, "xXXX") \
|
||||
DECL(osl_##name##_dfdv, "xXv") \
|
||||
DECL(osl_##name##_dfdvf, "xXvf") \
|
||||
DECL(osl_##name##_dfvdf, "xXvX") \
|
||||
DECL(osl_##name##_dfdvdf, "xXvX") \
|
||||
DECL(osl_##name##_dvdf, "xvX") \
|
||||
DECL(osl_##name##_dvdff, "xvXf") \
|
||||
DECL(osl_##name##_dvfdf, "xvfX") \
|
||||
DECL(osl_##name##_dvdfdf, "xvXX") \
|
||||
DECL(osl_##name##_dvdv, "xvv") \
|
||||
DECL(osl_##name##_dvdvf, "xvvf") \
|
||||
DECL(osl_##name##_dvvdf, "xvvX") \
|
||||
DECL(osl_##name##_dvdvdf, "xvvX")
|
||||
|
||||
#define GENERIC_NOISE_DERIV_IMPL(name) \
|
||||
DECL (osl_ ## name ## _dfdf, "xsXXXX") \
|
||||
DECL (osl_ ## name ## _dfdfdf, "xsXXXXX") \
|
||||
DECL (osl_ ## name ## _dfdv, "xsXXXX") \
|
||||
DECL (osl_ ## name ## _dfdvdf, "xsXXXXX") \
|
||||
DECL (osl_ ## name ## _dvdf, "xsXXXX") \
|
||||
DECL (osl_ ## name ## _dvdfdf, "xsXXXXX") \
|
||||
DECL (osl_ ## name ## _dvdv, "xsXXXX") \
|
||||
DECL (osl_ ## name ## _dvdvdf, "xsXXXXX")
|
||||
#define GENERIC_NOISE_DERIV_IMPL(name) \
|
||||
DECL(osl_##name##_dfdf, "xsXXXX") \
|
||||
DECL(osl_##name##_dfdfdf, "xsXXXXX") \
|
||||
DECL(osl_##name##_dfdv, "xsXXXX") \
|
||||
DECL(osl_##name##_dfdvdf, "xsXXXXX") \
|
||||
DECL(osl_##name##_dvdf, "xsXXXX") \
|
||||
DECL(osl_##name##_dvdfdf, "xsXXXXX") \
|
||||
DECL(osl_##name##_dvdv, "xsXXXX") \
|
||||
DECL(osl_##name##_dvdvdf, "xsXXXXX")
|
||||
|
||||
#define PNOISE_IMPL(name) \
|
||||
DECL (osl_ ## name ## _fff, "fff") \
|
||||
DECL (osl_ ## name ## _fffff, "fffff") \
|
||||
DECL (osl_ ## name ## _fvv, "fvv") \
|
||||
DECL (osl_ ## name ## _fvfvf, "fvfvf") \
|
||||
DECL (osl_ ## name ## _vff, "xvff") \
|
||||
DECL (osl_ ## name ## _vffff, "xvffff") \
|
||||
DECL (osl_ ## name ## _vvv, "xvvv") \
|
||||
DECL (osl_ ## name ## _vvfvf, "xvvfvf")
|
||||
#define PNOISE_IMPL(name) \
|
||||
DECL(osl_##name##_fff, "fff") \
|
||||
DECL(osl_##name##_fffff, "fffff") \
|
||||
DECL(osl_##name##_fvv, "fvv") \
|
||||
DECL(osl_##name##_fvfvf, "fvfvf") \
|
||||
DECL(osl_##name##_vff, "xvff") \
|
||||
DECL(osl_##name##_vffff, "xvffff") \
|
||||
DECL(osl_##name##_vvv, "xvvv") \
|
||||
DECL(osl_##name##_vvfvf, "xvvfvf")
|
||||
|
||||
#define PNOISE_DERIV_IMPL(name) \
|
||||
DECL (osl_ ## name ## _dfdff, "xXXf") \
|
||||
DECL (osl_ ## name ## _dfdffff, "xXXfff") \
|
||||
DECL (osl_ ## name ## _dffdfff, "xXfXff") \
|
||||
DECL (osl_ ## name ## _dfdfdfff, "xXXXff") \
|
||||
DECL (osl_ ## name ## _dfdvv, "xXXv") \
|
||||
DECL (osl_ ## name ## _dfdvfvf, "xXvfvf") \
|
||||
DECL (osl_ ## name ## _dfvdfvf, "xXvXvf") \
|
||||
DECL (osl_ ## name ## _dfdvdfvf, "xXvXvf") \
|
||||
DECL (osl_ ## name ## _dvdff, "xvXf") \
|
||||
DECL (osl_ ## name ## _dvdffff, "xvXfff") \
|
||||
DECL (osl_ ## name ## _dvfdfff, "xvfXff") \
|
||||
DECL (osl_ ## name ## _dvdfdfff, "xvXXff") \
|
||||
DECL (osl_ ## name ## _dvdvv, "xvvv") \
|
||||
DECL (osl_ ## name ## _dvdvfvf, "xvvfvf") \
|
||||
DECL (osl_ ## name ## _dvvdfvf, "xvvXvf") \
|
||||
DECL (osl_ ## name ## _dvdvdfvf, "xvvXvf")
|
||||
#define PNOISE_DERIV_IMPL(name) \
|
||||
DECL(osl_##name##_dfdff, "xXXf") \
|
||||
DECL(osl_##name##_dfdffff, "xXXfff") \
|
||||
DECL(osl_##name##_dffdfff, "xXfXff") \
|
||||
DECL(osl_##name##_dfdfdfff, "xXXXff") \
|
||||
DECL(osl_##name##_dfdvv, "xXXv") \
|
||||
DECL(osl_##name##_dfdvfvf, "xXvfvf") \
|
||||
DECL(osl_##name##_dfvdfvf, "xXvXvf") \
|
||||
DECL(osl_##name##_dfdvdfvf, "xXvXvf") \
|
||||
DECL(osl_##name##_dvdff, "xvXf") \
|
||||
DECL(osl_##name##_dvdffff, "xvXfff") \
|
||||
DECL(osl_##name##_dvfdfff, "xvfXff") \
|
||||
DECL(osl_##name##_dvdfdfff, "xvXXff") \
|
||||
DECL(osl_##name##_dvdvv, "xvvv") \
|
||||
DECL(osl_##name##_dvdvfvf, "xvvfvf") \
|
||||
DECL(osl_##name##_dvvdfvf, "xvvXvf") \
|
||||
DECL(osl_##name##_dvdvdfvf, "xvvXvf")
|
||||
|
||||
#define GENERIC_PNOISE_DERIV_IMPL(name) \
|
||||
DECL (osl_ ## name ## _dfdff, "xsXXfXX") \
|
||||
DECL (osl_ ## name ## _dfdfdfff, "xsXXXffXX") \
|
||||
DECL (osl_ ## name ## _dfdvv, "xsXXvXX") \
|
||||
DECL (osl_ ## name ## _dfdvdfvf, "xsXvXvfXX") \
|
||||
DECL (osl_ ## name ## _dvdff, "xsvXfXX") \
|
||||
DECL (osl_ ## name ## _dvdfdfff, "xsvXXffXX") \
|
||||
DECL (osl_ ## name ## _dvdvv, "xsvvvXX") \
|
||||
DECL (osl_ ## name ## _dvdvdfvf, "xsvvXvfXX")
|
||||
#define GENERIC_PNOISE_DERIV_IMPL(name) \
|
||||
DECL(osl_##name##_dfdff, "xsXXfXX") \
|
||||
DECL(osl_##name##_dfdfdfff, "xsXXXffXX") \
|
||||
DECL(osl_##name##_dfdvv, "xsXXvXX") \
|
||||
DECL(osl_##name##_dfdvdfvf, "xsXvXvfXX") \
|
||||
DECL(osl_##name##_dvdff, "xsvXfXX") \
|
||||
DECL(osl_##name##_dvdfdfff, "xsvXXffXX") \
|
||||
DECL(osl_##name##_dvdvv, "xsvvvXX") \
|
||||
DECL(osl_##name##_dvdvdfvf, "xsvvXvfXX")
|
||||
|
||||
#define UNARY_OP_IMPL(name) \
|
||||
DECL (osl_ ## name ## _ff, "ff") \
|
||||
DECL (osl_ ## name ## _dfdf, "xXX") \
|
||||
DECL (osl_ ## name ## _vv, "xXX") \
|
||||
DECL (osl_ ## name ## _dvdv, "xXX")
|
||||
#define UNARY_OP_IMPL(name) \
|
||||
DECL(osl_##name##_ff, "ff") \
|
||||
DECL(osl_##name##_dfdf, "xXX") \
|
||||
DECL(osl_##name##_vv, "xXX") \
|
||||
DECL(osl_##name##_dvdv, "xXX")
|
||||
|
||||
#define BINARY_OP_IMPL(name) \
|
||||
DECL (osl_ ## name ## _fff, "fff") \
|
||||
DECL (osl_ ## name ## _dfdfdf, "xXXX") \
|
||||
DECL (osl_ ## name ## _dffdf, "xXfX") \
|
||||
DECL (osl_ ## name ## _dfdff, "xXXf") \
|
||||
DECL (osl_ ## name ## _vvv, "xXXX") \
|
||||
DECL (osl_ ## name ## _dvdvdv, "xXXX") \
|
||||
DECL (osl_ ## name ## _dvvdv, "xXXX") \
|
||||
DECL (osl_ ## name ## _dvdvv, "xXXX")
|
||||
#define BINARY_OP_IMPL(name) \
|
||||
DECL(osl_##name##_fff, "fff") \
|
||||
DECL(osl_##name##_dfdfdf, "xXXX") \
|
||||
DECL(osl_##name##_dffdf, "xXfX") \
|
||||
DECL(osl_##name##_dfdff, "xXXf") \
|
||||
DECL(osl_##name##_vvv, "xXXX") \
|
||||
DECL(osl_##name##_dvdvdv, "xXXX") \
|
||||
DECL(osl_##name##_dvvdv, "xXXX") \
|
||||
DECL(osl_##name##_dvdvv, "xXXX")
|
||||
|
||||
|
||||
|
||||
|
||||
DECL (osl_add_closure_closure, "CXCC")
|
||||
DECL (osl_mul_closure_float, "CXCf")
|
||||
DECL (osl_mul_closure_color, "CXCc")
|
||||
DECL (osl_allocate_closure_component, "CXii")
|
||||
DECL (osl_allocate_weighted_closure_component, "CXiiX")
|
||||
DECL (osl_closure_to_string, "sXC")
|
||||
DECL (osl_format, "ss*")
|
||||
DECL (osl_printf, "xXs*")
|
||||
DECL (osl_fprintf, "xXss*")
|
||||
DECL (osl_error, "xXs*")
|
||||
DECL (osl_warning, "xXs*")
|
||||
DECL (osl_split, "isXsii")
|
||||
DECL (osl_incr_layers_executed, "xX")
|
||||
DECL(osl_add_closure_closure, "CXCC")
|
||||
DECL(osl_mul_closure_float, "CXCf")
|
||||
DECL(osl_mul_closure_color, "CXCc")
|
||||
DECL(osl_allocate_closure_component, "CXii")
|
||||
DECL(osl_allocate_weighted_closure_component, "CXiiX")
|
||||
DECL(osl_closure_to_string, "sXC")
|
||||
DECL(osl_format, "ss*")
|
||||
DECL(osl_printf, "xXs*")
|
||||
DECL(osl_fprintf, "xXss*")
|
||||
DECL(osl_error, "xXs*")
|
||||
DECL(osl_warning, "xXs*")
|
||||
DECL(osl_split, "isXsii")
|
||||
DECL(osl_incr_layers_executed, "xX")
|
||||
|
||||
NOISE_IMPL(cellnoise)
|
||||
//NOISE_DERIV_IMPL(cellnoise)
|
||||
@@ -151,70 +150,70 @@ PNOISE_IMPL(psnoise)
|
||||
PNOISE_DERIV_IMPL(psnoise)
|
||||
GENERIC_PNOISE_DERIV_IMPL(gaborpnoise)
|
||||
GENERIC_PNOISE_DERIV_IMPL(genericpnoise)
|
||||
DECL (osl_noiseparams_set_anisotropic, "xXi")
|
||||
DECL (osl_noiseparams_set_do_filter, "xXi")
|
||||
DECL (osl_noiseparams_set_direction, "xXv")
|
||||
DECL (osl_noiseparams_set_bandwidth, "xXf")
|
||||
DECL (osl_noiseparams_set_impulses, "xXf")
|
||||
DECL (osl_count_noise, "xX")
|
||||
DECL (osl_hash_ii, "ii")
|
||||
DECL (osl_hash_if, "if")
|
||||
DECL (osl_hash_iff, "iff")
|
||||
DECL (osl_hash_iv, "iX")
|
||||
DECL (osl_hash_ivf, "iXf")
|
||||
DECL(osl_noiseparams_set_anisotropic, "xXi")
|
||||
DECL(osl_noiseparams_set_do_filter, "xXi")
|
||||
DECL(osl_noiseparams_set_direction, "xXv")
|
||||
DECL(osl_noiseparams_set_bandwidth, "xXf")
|
||||
DECL(osl_noiseparams_set_impulses, "xXf")
|
||||
DECL(osl_count_noise, "xX")
|
||||
DECL(osl_hash_ii, "ii")
|
||||
DECL(osl_hash_if, "if")
|
||||
DECL(osl_hash_iff, "iff")
|
||||
DECL(osl_hash_iv, "iX")
|
||||
DECL(osl_hash_ivf, "iXf")
|
||||
|
||||
DECL (osl_spline_fff, "xXXXXii")
|
||||
DECL (osl_spline_dfdfdf, "xXXXXii")
|
||||
DECL (osl_spline_dfdff, "xXXXXii")
|
||||
DECL (osl_spline_dffdf, "xXXXXii")
|
||||
DECL (osl_spline_vfv, "xXXXXii")
|
||||
DECL (osl_spline_dvdfdv, "xXXXXii")
|
||||
DECL (osl_spline_dvdfv, "xXXXXii")
|
||||
DECL (osl_spline_dvfdv, "xXXXXii")
|
||||
DECL (osl_splineinverse_fff, "xXXXXii")
|
||||
DECL (osl_splineinverse_dfdfdf, "xXXXXii")
|
||||
DECL (osl_splineinverse_dfdff, "xXXXXii")
|
||||
DECL (osl_splineinverse_dffdf, "xXXXXii")
|
||||
DECL (osl_setmessage, "xXsLXisi")
|
||||
DECL (osl_getmessage, "iXssLXiisi")
|
||||
DECL (osl_pointcloud_search, "iXsXfiiXXii*")
|
||||
DECL (osl_pointcloud_get, "iXsXisLX")
|
||||
DECL (osl_pointcloud_write, "iXsXiXXX")
|
||||
DECL (osl_pointcloud_write_helper, "xXXXisLX")
|
||||
DECL (osl_blackbody_vf, "xXXf")
|
||||
DECL (osl_wavelength_color_vf, "xXXf")
|
||||
DECL (osl_luminance_fv, "xXXX")
|
||||
DECL (osl_luminance_dfdv, "xXXX")
|
||||
DECL (osl_prepend_color_from, "xXXs")
|
||||
DECL (osl_prepend_matrix_from, "iXXs")
|
||||
DECL (osl_get_matrix, "iXXs")
|
||||
DECL (osl_get_inverse_matrix, "iXXs")
|
||||
DECL (osl_transform_triple, "iXXiXiXXi")
|
||||
DECL (osl_transform_triple_nonlinear, "iXXiXiXXi")
|
||||
DECL (osl_transform_vmv, "xXXX")
|
||||
DECL (osl_transform_dvmdv, "xXXX")
|
||||
DECL (osl_transformv_vmv, "xXXX")
|
||||
DECL (osl_transformv_dvmdv, "xXXX")
|
||||
DECL (osl_transformn_vmv, "xXXX")
|
||||
DECL (osl_transformn_dvmdv, "xXXX")
|
||||
DECL (osl_transformc, "iXXiXiXX")
|
||||
DECL(osl_spline_fff, "xXXXXii")
|
||||
DECL(osl_spline_dfdfdf, "xXXXXii")
|
||||
DECL(osl_spline_dfdff, "xXXXXii")
|
||||
DECL(osl_spline_dffdf, "xXXXXii")
|
||||
DECL(osl_spline_vfv, "xXXXXii")
|
||||
DECL(osl_spline_dvdfdv, "xXXXXii")
|
||||
DECL(osl_spline_dvdfv, "xXXXXii")
|
||||
DECL(osl_spline_dvfdv, "xXXXXii")
|
||||
DECL(osl_splineinverse_fff, "xXXXXii")
|
||||
DECL(osl_splineinverse_dfdfdf, "xXXXXii")
|
||||
DECL(osl_splineinverse_dfdff, "xXXXXii")
|
||||
DECL(osl_splineinverse_dffdf, "xXXXXii")
|
||||
DECL(osl_setmessage, "xXsLXisi")
|
||||
DECL(osl_getmessage, "iXssLXiisi")
|
||||
DECL(osl_pointcloud_search, "iXsXfiiXXii*")
|
||||
DECL(osl_pointcloud_get, "iXsXisLX")
|
||||
DECL(osl_pointcloud_write, "iXsXiXXX")
|
||||
DECL(osl_pointcloud_write_helper, "xXXXisLX")
|
||||
DECL(osl_blackbody_vf, "xXXf")
|
||||
DECL(osl_wavelength_color_vf, "xXXf")
|
||||
DECL(osl_luminance_fv, "xXXX")
|
||||
DECL(osl_luminance_dfdv, "xXXX")
|
||||
DECL(osl_prepend_color_from, "xXXs")
|
||||
DECL(osl_prepend_matrix_from, "iXXs")
|
||||
DECL(osl_get_matrix, "iXXs")
|
||||
DECL(osl_get_inverse_matrix, "iXXs")
|
||||
DECL(osl_transform_triple, "iXXiXiXXi")
|
||||
DECL(osl_transform_triple_nonlinear, "iXXiXiXXi")
|
||||
DECL(osl_transform_vmv, "xXXX")
|
||||
DECL(osl_transform_dvmdv, "xXXX")
|
||||
DECL(osl_transformv_vmv, "xXXX")
|
||||
DECL(osl_transformv_dvmdv, "xXXX")
|
||||
DECL(osl_transformn_vmv, "xXXX")
|
||||
DECL(osl_transformn_dvmdv, "xXXX")
|
||||
DECL(osl_transformc, "iXXiXiXX")
|
||||
|
||||
DECL (osl_dict_find_iis, "iXiX")
|
||||
DECL (osl_dict_find_iss, "iXXX")
|
||||
DECL (osl_dict_next, "iXi")
|
||||
DECL (osl_dict_value, "iXiXLX")
|
||||
DECL (osl_raytype_name, "iXs")
|
||||
DECL(osl_dict_find_iis, "iXiX")
|
||||
DECL(osl_dict_find_iss, "iXXX")
|
||||
DECL(osl_dict_next, "iXi")
|
||||
DECL(osl_dict_value, "iXiXLX")
|
||||
DECL(osl_raytype_name, "iXs")
|
||||
#ifdef OSL_LLVM_NO_BITCODE
|
||||
DECL (osl_range_check, "iiiXXXiXiXX")
|
||||
DECL(osl_range_check, "iiiXXXiXiXX")
|
||||
#endif
|
||||
DECL (osl_range_check_err, "iiiXXXiXiXX")
|
||||
DECL (osl_naninf_check, "xiXiXXiXiiX")
|
||||
DECL (osl_uninit_check, "xLXXXiXiXXiXiXii")
|
||||
DECL (osl_get_attribute, "iXiXXiiLX")
|
||||
DECL (osl_bind_interpolated_param, "iXXLiXiXiXi")
|
||||
DECL (osl_get_texture_options, "XX");
|
||||
DECL (osl_get_noise_options, "XX");
|
||||
DECL (osl_get_trace_options, "XX");
|
||||
DECL(osl_range_check_err, "iiiXXXiXiXX")
|
||||
DECL(osl_naninf_check, "xiXiXXiXiiX")
|
||||
DECL(osl_uninit_check, "xLXXXiXiXXiXiXii")
|
||||
DECL(osl_get_attribute, "iXiXXiiLX")
|
||||
DECL(osl_bind_interpolated_param, "iXXLiXiXiXi")
|
||||
DECL(osl_get_texture_options, "XX");
|
||||
DECL(osl_get_noise_options, "XX");
|
||||
DECL(osl_get_trace_options, "XX");
|
||||
|
||||
|
||||
// The following are defined inside llvm_ops.cpp. Only include these
|
||||
@@ -231,17 +230,17 @@ UNARY_OP_IMPL(sinh)
|
||||
UNARY_OP_IMPL(cosh)
|
||||
UNARY_OP_IMPL(tanh)
|
||||
|
||||
DECL (osl_safe_div_iii, "iii")
|
||||
DECL (osl_safe_div_fff, "fff")
|
||||
DECL (osl_safe_mod_iii, "iii")
|
||||
DECL (osl_sincos_fff, "xfXX")
|
||||
DECL (osl_sincos_dfdff, "xXXX")
|
||||
DECL (osl_sincos_dffdf, "xXXX")
|
||||
DECL (osl_sincos_dfdfdf, "xXXX")
|
||||
DECL (osl_sincos_vvv, "xXXX")
|
||||
DECL (osl_sincos_dvdvv, "xXXX")
|
||||
DECL (osl_sincos_dvvdv, "xXXX")
|
||||
DECL (osl_sincos_dvdvdv, "xXXX")
|
||||
DECL(osl_safe_div_iii, "iii")
|
||||
DECL(osl_safe_div_fff, "fff")
|
||||
DECL(osl_safe_mod_iii, "iii")
|
||||
DECL(osl_sincos_fff, "xfXX")
|
||||
DECL(osl_sincos_dfdff, "xXXX")
|
||||
DECL(osl_sincos_dffdf, "xXXX")
|
||||
DECL(osl_sincos_dfdfdf, "xXXX")
|
||||
DECL(osl_sincos_vvv, "xXXX")
|
||||
DECL(osl_sincos_dvdvv, "xXXX")
|
||||
DECL(osl_sincos_dvvdv, "xXXX")
|
||||
DECL(osl_sincos_dvdvdv, "xXXX")
|
||||
|
||||
UNARY_OP_IMPL(log)
|
||||
UNARY_OP_IMPL(log2)
|
||||
@@ -253,138 +252,138 @@ BINARY_OP_IMPL(pow)
|
||||
UNARY_OP_IMPL(erf)
|
||||
UNARY_OP_IMPL(erfc)
|
||||
|
||||
DECL (osl_pow_vvf, "xXXf")
|
||||
DECL (osl_pow_dvdvdf, "xXXX")
|
||||
DECL (osl_pow_dvvdf, "xXXX")
|
||||
DECL (osl_pow_dvdvf, "xXXf")
|
||||
DECL(osl_pow_vvf, "xXXf")
|
||||
DECL(osl_pow_dvdvdf, "xXXX")
|
||||
DECL(osl_pow_dvvdf, "xXXX")
|
||||
DECL(osl_pow_dvdvf, "xXXf")
|
||||
|
||||
UNARY_OP_IMPL(sqrt)
|
||||
UNARY_OP_IMPL(inversesqrt)
|
||||
UNARY_OP_IMPL(cbrt)
|
||||
|
||||
DECL (osl_logb_ff, "ff")
|
||||
DECL (osl_logb_vv, "xXX")
|
||||
DECL(osl_logb_ff, "ff")
|
||||
DECL(osl_logb_vv, "xXX")
|
||||
|
||||
DECL (osl_floor_ff, "ff")
|
||||
DECL (osl_floor_vv, "xXX")
|
||||
DECL (osl_ceil_ff, "ff")
|
||||
DECL (osl_ceil_vv, "xXX")
|
||||
DECL (osl_round_ff, "ff")
|
||||
DECL (osl_round_vv, "xXX")
|
||||
DECL (osl_trunc_ff, "ff")
|
||||
DECL (osl_trunc_vv, "xXX")
|
||||
DECL (osl_sign_ff, "ff")
|
||||
DECL (osl_sign_vv, "xXX")
|
||||
DECL (osl_step_fff, "fff")
|
||||
DECL (osl_step_vvv, "xXXX")
|
||||
DECL(osl_floor_ff, "ff")
|
||||
DECL(osl_floor_vv, "xXX")
|
||||
DECL(osl_ceil_ff, "ff")
|
||||
DECL(osl_ceil_vv, "xXX")
|
||||
DECL(osl_round_ff, "ff")
|
||||
DECL(osl_round_vv, "xXX")
|
||||
DECL(osl_trunc_ff, "ff")
|
||||
DECL(osl_trunc_vv, "xXX")
|
||||
DECL(osl_sign_ff, "ff")
|
||||
DECL(osl_sign_vv, "xXX")
|
||||
DECL(osl_step_fff, "fff")
|
||||
DECL(osl_step_vvv, "xXXX")
|
||||
|
||||
DECL (osl_isnan_if, "if")
|
||||
DECL (osl_isinf_if, "if")
|
||||
DECL (osl_isfinite_if, "if")
|
||||
DECL (osl_abs_ii, "ii")
|
||||
DECL (osl_fabs_ii, "ii")
|
||||
DECL(osl_isnan_if, "if")
|
||||
DECL(osl_isinf_if, "if")
|
||||
DECL(osl_isfinite_if, "if")
|
||||
DECL(osl_abs_ii, "ii")
|
||||
DECL(osl_fabs_ii, "ii")
|
||||
|
||||
UNARY_OP_IMPL(abs)
|
||||
UNARY_OP_IMPL(fabs)
|
||||
BINARY_OP_IMPL(fmod)
|
||||
|
||||
DECL (osl_smoothstep_ffff, "ffff")
|
||||
DECL (osl_smoothstep_dfffdf, "xXffX")
|
||||
DECL (osl_smoothstep_dffdff, "xXfXf")
|
||||
DECL (osl_smoothstep_dffdfdf, "xXfXX")
|
||||
DECL (osl_smoothstep_dfdfff, "xXXff")
|
||||
DECL (osl_smoothstep_dfdffdf, "xXXfX")
|
||||
DECL (osl_smoothstep_dfdfdff, "xXXXf")
|
||||
DECL (osl_smoothstep_dfdfdfdf, "xXXXX")
|
||||
DECL(osl_smoothstep_ffff, "ffff")
|
||||
DECL(osl_smoothstep_dfffdf, "xXffX")
|
||||
DECL(osl_smoothstep_dffdff, "xXfXf")
|
||||
DECL(osl_smoothstep_dffdfdf, "xXfXX")
|
||||
DECL(osl_smoothstep_dfdfff, "xXXff")
|
||||
DECL(osl_smoothstep_dfdffdf, "xXXfX")
|
||||
DECL(osl_smoothstep_dfdfdff, "xXXXf")
|
||||
DECL(osl_smoothstep_dfdfdfdf, "xXXXX")
|
||||
|
||||
DECL (osl_dot_fvv, "fXX")
|
||||
DECL (osl_dot_dfdvdv, "xXXX")
|
||||
DECL (osl_dot_dfdvv, "xXXX")
|
||||
DECL (osl_dot_dfvdv, "xXXX")
|
||||
DECL (osl_cross_vvv, "xXXX")
|
||||
DECL (osl_cross_dvdvdv, "xXXX")
|
||||
DECL (osl_cross_dvdvv, "xXXX")
|
||||
DECL (osl_cross_dvvdv, "xXXX")
|
||||
DECL (osl_length_fv, "fX")
|
||||
DECL (osl_length_dfdv, "xXX")
|
||||
DECL (osl_distance_fvv, "fXX")
|
||||
DECL (osl_distance_dfdvdv, "xXXX")
|
||||
DECL (osl_distance_dfdvv, "xXXX")
|
||||
DECL (osl_distance_dfvdv, "xXXX")
|
||||
DECL (osl_normalize_vv, "xXX")
|
||||
DECL (osl_normalize_dvdv, "xXX")
|
||||
DECL(osl_dot_fvv, "fXX")
|
||||
DECL(osl_dot_dfdvdv, "xXXX")
|
||||
DECL(osl_dot_dfdvv, "xXXX")
|
||||
DECL(osl_dot_dfvdv, "xXXX")
|
||||
DECL(osl_cross_vvv, "xXXX")
|
||||
DECL(osl_cross_dvdvdv, "xXXX")
|
||||
DECL(osl_cross_dvdvv, "xXXX")
|
||||
DECL(osl_cross_dvvdv, "xXXX")
|
||||
DECL(osl_length_fv, "fX")
|
||||
DECL(osl_length_dfdv, "xXX")
|
||||
DECL(osl_distance_fvv, "fXX")
|
||||
DECL(osl_distance_dfdvdv, "xXXX")
|
||||
DECL(osl_distance_dfdvv, "xXXX")
|
||||
DECL(osl_distance_dfvdv, "xXXX")
|
||||
DECL(osl_normalize_vv, "xXX")
|
||||
DECL(osl_normalize_dvdv, "xXX")
|
||||
#endif
|
||||
|
||||
|
||||
DECL (osl_mul_mmm, "xXXX")
|
||||
DECL (osl_mul_mmf, "xXXf")
|
||||
DECL(osl_mul_mmm, "xXXX")
|
||||
DECL(osl_mul_mmf, "xXXf")
|
||||
|
||||
DECL (osl_div_mmm, "xXXX")
|
||||
DECL (osl_div_mmf, "xXXf")
|
||||
DECL (osl_div_mfm, "xXfX")
|
||||
DECL(osl_div_mmm, "xXXX")
|
||||
DECL(osl_div_mmf, "xXXf")
|
||||
DECL(osl_div_mfm, "xXfX")
|
||||
|
||||
DECL (osl_get_from_to_matrix, "iXXss")
|
||||
DECL (osl_transpose_mm, "xXX")
|
||||
DECL (osl_determinant_fm, "fX")
|
||||
DECL(osl_get_from_to_matrix, "iXXss")
|
||||
DECL(osl_transpose_mm, "xXX")
|
||||
DECL(osl_determinant_fm, "fX")
|
||||
|
||||
DECL (osl_concat_sss, "sss")
|
||||
DECL (osl_strlen_is, "is")
|
||||
DECL (osl_hash_is, "is")
|
||||
DECL (osl_getchar_isi, "isi");
|
||||
DECL (osl_startswith_iss, "iss")
|
||||
DECL (osl_endswith_iss, "iss")
|
||||
DECL (osl_stoi_is, "is")
|
||||
DECL (osl_stof_fs, "fs")
|
||||
DECL (osl_substr_ssii, "ssii")
|
||||
DECL (osl_regex_impl, "iXsXisi")
|
||||
DECL(osl_concat_sss, "sss")
|
||||
DECL(osl_strlen_is, "is")
|
||||
DECL(osl_hash_is, "is")
|
||||
DECL(osl_getchar_isi, "isi");
|
||||
DECL(osl_startswith_iss, "iss")
|
||||
DECL(osl_endswith_iss, "iss")
|
||||
DECL(osl_stoi_is, "is")
|
||||
DECL(osl_stof_fs, "fs")
|
||||
DECL(osl_substr_ssii, "ssii")
|
||||
DECL(osl_regex_impl, "iXsXisi")
|
||||
|
||||
// Used by wide code generator, but are uniform calls
|
||||
DECL (osl_texture_decode_wrapmode, "iX");
|
||||
DECL (osl_texture_decode_interpmode, "iX");
|
||||
DECL(osl_texture_decode_wrapmode, "iX");
|
||||
DECL(osl_texture_decode_interpmode, "iX");
|
||||
|
||||
DECL (osl_texture_set_firstchannel, "xXi")
|
||||
DECL (osl_texture_set_swrap, "xXs")
|
||||
DECL (osl_texture_set_twrap, "xXs")
|
||||
DECL (osl_texture_set_rwrap, "xXs")
|
||||
DECL (osl_texture_set_stwrap, "xXs")
|
||||
DECL (osl_texture_set_swrap_code, "xXi")
|
||||
DECL (osl_texture_set_twrap_code, "xXi")
|
||||
DECL (osl_texture_set_rwrap_code, "xXi")
|
||||
DECL (osl_texture_set_stwrap_code, "xXi")
|
||||
DECL (osl_texture_set_sblur, "xXf")
|
||||
DECL (osl_texture_set_tblur, "xXf")
|
||||
DECL (osl_texture_set_rblur, "xXf")
|
||||
DECL (osl_texture_set_stblur, "xXf")
|
||||
DECL (osl_texture_set_swidth, "xXf")
|
||||
DECL (osl_texture_set_twidth, "xXf")
|
||||
DECL (osl_texture_set_rwidth, "xXf")
|
||||
DECL (osl_texture_set_stwidth, "xXf")
|
||||
DECL (osl_texture_set_fill, "xXf")
|
||||
DECL (osl_texture_set_time, "xXf")
|
||||
DECL (osl_texture_set_interp, "xXs")
|
||||
DECL (osl_texture_set_interp_code, "xXi")
|
||||
DECL (osl_texture_set_subimage, "xXi")
|
||||
DECL (osl_texture_set_subimagename, "xXs")
|
||||
DECL (osl_texture_set_missingcolor_arena, "xXX")
|
||||
DECL (osl_texture_set_missingcolor_alpha, "xXif")
|
||||
DECL (osl_texture, "iXXXXffffffiXXXXXXX")
|
||||
DECL (osl_texture3d, "iXXXXXXXXiXXXXXXX")
|
||||
DECL (osl_environment, "iXXXXXXXiXXXXXXX")
|
||||
DECL (osl_get_textureinfo, "iXXXXiiiXX")
|
||||
DECL (osl_get_textureinfo_st, "iXXXffXiiiXX")
|
||||
DECL(osl_texture_set_firstchannel, "xXi")
|
||||
DECL(osl_texture_set_swrap, "xXs")
|
||||
DECL(osl_texture_set_twrap, "xXs")
|
||||
DECL(osl_texture_set_rwrap, "xXs")
|
||||
DECL(osl_texture_set_stwrap, "xXs")
|
||||
DECL(osl_texture_set_swrap_code, "xXi")
|
||||
DECL(osl_texture_set_twrap_code, "xXi")
|
||||
DECL(osl_texture_set_rwrap_code, "xXi")
|
||||
DECL(osl_texture_set_stwrap_code, "xXi")
|
||||
DECL(osl_texture_set_sblur, "xXf")
|
||||
DECL(osl_texture_set_tblur, "xXf")
|
||||
DECL(osl_texture_set_rblur, "xXf")
|
||||
DECL(osl_texture_set_stblur, "xXf")
|
||||
DECL(osl_texture_set_swidth, "xXf")
|
||||
DECL(osl_texture_set_twidth, "xXf")
|
||||
DECL(osl_texture_set_rwidth, "xXf")
|
||||
DECL(osl_texture_set_stwidth, "xXf")
|
||||
DECL(osl_texture_set_fill, "xXf")
|
||||
DECL(osl_texture_set_time, "xXf")
|
||||
DECL(osl_texture_set_interp, "xXs")
|
||||
DECL(osl_texture_set_interp_code, "xXi")
|
||||
DECL(osl_texture_set_subimage, "xXi")
|
||||
DECL(osl_texture_set_subimagename, "xXs")
|
||||
DECL(osl_texture_set_missingcolor_arena, "xXX")
|
||||
DECL(osl_texture_set_missingcolor_alpha, "xXif")
|
||||
DECL(osl_texture, "iXXXXffffffiXXXXXXX")
|
||||
DECL(osl_texture3d, "iXXXXXXXXiXXXXXXX")
|
||||
DECL(osl_environment, "iXXXXXXXiXXXXXXX")
|
||||
DECL(osl_get_textureinfo, "iXXXXiiiXX")
|
||||
DECL(osl_get_textureinfo_st, "iXXXffXiiiXX")
|
||||
|
||||
DECL (osl_trace_set_mindist, "xXf")
|
||||
DECL (osl_trace_set_maxdist, "xXf")
|
||||
DECL (osl_trace_set_shade, "xXi")
|
||||
DECL (osl_trace_set_traceset, "xXs")
|
||||
DECL (osl_trace, "iXXXXXXXX")
|
||||
DECL(osl_trace_set_mindist, "xXf")
|
||||
DECL(osl_trace_set_maxdist, "xXf")
|
||||
DECL(osl_trace_set_shade, "xXi")
|
||||
DECL(osl_trace_set_traceset, "xXs")
|
||||
DECL(osl_trace, "iXXXXXXXX")
|
||||
|
||||
#ifdef OSL_LLVM_NO_BITCODE
|
||||
DECL (osl_calculatenormal, "xXXX")
|
||||
DECL (osl_area, "fX")
|
||||
DECL (osl_filterwidth_fdf, "fX")
|
||||
DECL (osl_filterwidth_vdv, "xXX")
|
||||
DECL (osl_raytype_bit, "iXi")
|
||||
DECL(osl_calculatenormal, "xXXX")
|
||||
DECL(osl_area, "fX")
|
||||
DECL(osl_filterwidth_fdf, "fX")
|
||||
DECL(osl_filterwidth_vdv, "xXX")
|
||||
DECL(osl_raytype_bit, "iXi")
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -381,7 +381,7 @@ DECL(__OSL_OP(get_attribute_uniform), "iXiXXiiXX")
|
||||
// TODO: shouldn't bind_interpolated_param be MASKED? change name to reflect
|
||||
DECL(__OSL_OP(bind_interpolated_param), "iXXLiXiXiXii")
|
||||
|
||||
//DECL (osl_get_texture_options, "XX") // uneeded
|
||||
//DECL (osl_get_texture_options, "XX") // unneeded
|
||||
DECL(__OSL_OP(get_noise_options), "XX")
|
||||
|
||||
// The following are defined inside llvm_ops.cpp. Only include these
|
||||
|
||||
@@ -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,7 +2410,7 @@ 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;
|
||||
@@ -2424,7 +2424,7 @@ DECLFOLDER(constfold_gettextureinfo)
|
||||
// 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 +2776,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);
|
||||
|
||||
|
||||
@@ -301,7 +301,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 +330,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 +466,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())
|
||||
userdata_params(true);
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1854
-1748
File diff suppressed because it is too large
Load Diff
+602
-536
File diff suppressed because it is too large
Load Diff
+522
-391
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
|
||||
|
||||
|
||||
+2432
-2135
File diff suppressed because it is too large
Load Diff
+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);
|
||||
|
||||
+84
-88
@@ -13,17 +13,10 @@ namespace lpexp {
|
||||
|
||||
// This is just a pair of states, see the use of the function genAuto in LPexp
|
||||
// for a justification of this type that we use throughout all the regexp code
|
||||
typedef std::pair<NdfAutomata::State *, NdfAutomata::State *> FirstLast;
|
||||
typedef std::pair<NdfAutomata::State*, NdfAutomata::State*> FirstLast;
|
||||
|
||||
/// LPexp atom type for the getType method
|
||||
typedef enum {
|
||||
CAT,
|
||||
OR,
|
||||
SYMBOL,
|
||||
WILDCARD,
|
||||
REPEAT,
|
||||
NREPEAT
|
||||
}Regtype;
|
||||
typedef enum { CAT, OR, SYMBOL, WILDCARD, REPEAT, NREPEAT } Regtype;
|
||||
|
||||
|
||||
|
||||
@@ -42,56 +35,56 @@ typedef enum {
|
||||
/// NREPEAT Bounded repetition of the child expression like (exp){n,m}
|
||||
///
|
||||
class LPexp {
|
||||
public:
|
||||
virtual ~LPexp() {};
|
||||
public:
|
||||
virtual ~LPexp() {};
|
||||
|
||||
/// Generate automata states for this subtree
|
||||
///
|
||||
/// This method recursively builds all the needed automata states of
|
||||
/// the tree rooted by this node and returns the begin and end states
|
||||
/// for it. That means that if it were the only thing in the automata,
|
||||
/// making retvalue.first initial state and retvalue.second final state,
|
||||
/// would be the right thing to do.
|
||||
///
|
||||
virtual FirstLast genAuto(NdfAutomata &automata)const = 0;
|
||||
/// Get the type for this node
|
||||
virtual Regtype getType()const = 0;
|
||||
/// For the parser's convenience. It is easy to implement things like a+
|
||||
/// as aa*. So the amount of regexp classes gets reduced. For doing that
|
||||
/// it needs an abstract clone function
|
||||
virtual LPexp * clone()const = 0;
|
||||
/// Generate automata states for this subtree
|
||||
///
|
||||
/// This method recursively builds all the needed automata states of
|
||||
/// the tree rooted by this node and returns the begin and end states
|
||||
/// for it. That means that if it were the only thing in the automata,
|
||||
/// making retvalue.first initial state and retvalue.second final state,
|
||||
/// would be the right thing to do.
|
||||
///
|
||||
virtual FirstLast genAuto(NdfAutomata& automata) const = 0;
|
||||
/// Get the type for this node
|
||||
virtual Regtype getType() const = 0;
|
||||
/// For the parser's convenience. It is easy to implement things like a+
|
||||
/// as aa*. So the amount of regexp classes gets reduced. For doing that
|
||||
/// it needs an abstract clone function
|
||||
virtual LPexp* clone() const = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// LPexp concatenation
|
||||
class Cat final : public LPexp {
|
||||
public:
|
||||
virtual ~Cat();
|
||||
void append(LPexp *regexp);
|
||||
virtual FirstLast genAuto(NdfAutomata &automata)const;
|
||||
virtual Regtype getType()const { return CAT; };
|
||||
virtual LPexp * clone()const;
|
||||
public:
|
||||
virtual ~Cat();
|
||||
void append(LPexp* regexp);
|
||||
virtual FirstLast genAuto(NdfAutomata& automata) const;
|
||||
virtual Regtype getType() const { return CAT; };
|
||||
virtual LPexp* clone() const;
|
||||
|
||||
protected:
|
||||
std::list<LPexp *> m_children;
|
||||
protected:
|
||||
std::list<LPexp*> m_children;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// Basic symbol like G or 'customlabel'
|
||||
class Symbol final : public LPexp {
|
||||
public:
|
||||
Symbol(ustring sym) { m_sym = sym; };
|
||||
virtual ~Symbol() {};
|
||||
public:
|
||||
Symbol(ustring sym) { m_sym = sym; };
|
||||
virtual ~Symbol() {};
|
||||
|
||||
virtual FirstLast genAuto(NdfAutomata &automata)const;
|
||||
virtual Regtype getType()const { return SYMBOL; };
|
||||
virtual LPexp * clone()const { return new Symbol(*this); };
|
||||
virtual FirstLast genAuto(NdfAutomata& automata) const;
|
||||
virtual Regtype getType() const { return SYMBOL; };
|
||||
virtual LPexp* clone() const { return new Symbol(*this); };
|
||||
|
||||
protected:
|
||||
// All symbols are unique ustrings
|
||||
ustring m_sym;
|
||||
protected:
|
||||
// All symbols are unique ustrings
|
||||
ustring m_sym;
|
||||
};
|
||||
|
||||
|
||||
@@ -100,63 +93,67 @@ class Symbol final : public LPexp {
|
||||
///
|
||||
/// Named like this to avoid confusion with the automata Wildcard class
|
||||
class Wildexp final : public LPexp {
|
||||
public:
|
||||
Wildexp(SymbolSet &minus):m_wildcard(minus) {};
|
||||
virtual ~Wildexp() {};
|
||||
public:
|
||||
Wildexp(SymbolSet& minus) : m_wildcard(minus) {};
|
||||
virtual ~Wildexp() {};
|
||||
|
||||
virtual FirstLast genAuto(NdfAutomata &automata)const;
|
||||
virtual Regtype getType()const { return WILDCARD; };
|
||||
virtual LPexp * clone()const { return new Wildexp(*this); };
|
||||
virtual FirstLast genAuto(NdfAutomata& automata) const;
|
||||
virtual Regtype getType() const { return WILDCARD; };
|
||||
virtual LPexp* clone() const { return new Wildexp(*this); };
|
||||
|
||||
protected:
|
||||
// And internally we use the automata's Wildcard type
|
||||
Wildcard m_wildcard;
|
||||
protected:
|
||||
// And internally we use the automata's Wildcard type
|
||||
Wildcard m_wildcard;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// Ored list of expressions
|
||||
class Orlist final : public LPexp {
|
||||
public:
|
||||
virtual ~Orlist();
|
||||
void append(LPexp *regexp);
|
||||
virtual FirstLast genAuto(NdfAutomata &automata)const;
|
||||
virtual Regtype getType()const { return OR; };
|
||||
virtual LPexp * clone()const;
|
||||
public:
|
||||
virtual ~Orlist();
|
||||
void append(LPexp* regexp);
|
||||
virtual FirstLast genAuto(NdfAutomata& automata) const;
|
||||
virtual Regtype getType() const { return OR; };
|
||||
virtual LPexp* clone() const;
|
||||
|
||||
protected:
|
||||
std::list<LPexp *> m_children;
|
||||
protected:
|
||||
std::list<LPexp*> m_children;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Unlimited repeat: (exp)*
|
||||
class Repeat final : public LPexp {
|
||||
public:
|
||||
Repeat(LPexp *child):m_child(child) {};
|
||||
virtual ~Repeat() { delete m_child; };
|
||||
virtual FirstLast genAuto(NdfAutomata &automata)const;
|
||||
virtual Regtype getType()const { return REPEAT; };
|
||||
virtual LPexp * clone()const { return new Repeat(m_child->clone()); };
|
||||
public:
|
||||
Repeat(LPexp* child) : m_child(child) {};
|
||||
virtual ~Repeat() { delete m_child; };
|
||||
virtual FirstLast genAuto(NdfAutomata& automata) const;
|
||||
virtual Regtype getType() const { return REPEAT; };
|
||||
virtual LPexp* clone() const { return new Repeat(m_child->clone()); };
|
||||
|
||||
protected:
|
||||
LPexp *m_child;
|
||||
protected:
|
||||
LPexp* m_child;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Bounded repeat: (exp){m,n}
|
||||
class NRepeat final : public LPexp {
|
||||
public:
|
||||
NRepeat(LPexp *child, int min, int max):m_child(child),m_min(min),m_max(max) {};
|
||||
virtual ~NRepeat() { delete m_child; };
|
||||
virtual FirstLast genAuto(NdfAutomata &automata)const;
|
||||
virtual Regtype getType()const { return NREPEAT; };
|
||||
virtual LPexp * clone()const { return new NRepeat(m_child->clone(), m_min, m_max); };
|
||||
public:
|
||||
NRepeat(LPexp* child, int min, int max)
|
||||
: m_child(child), m_min(min), m_max(max) {};
|
||||
virtual ~NRepeat() { delete m_child; };
|
||||
virtual FirstLast genAuto(NdfAutomata& automata) const;
|
||||
virtual Regtype getType() const { return NREPEAT; };
|
||||
virtual LPexp* clone() const
|
||||
{
|
||||
return new NRepeat(m_child->clone(), m_min, m_max);
|
||||
};
|
||||
|
||||
protected:
|
||||
LPexp *m_child;
|
||||
int m_min, m_max;
|
||||
protected:
|
||||
LPexp* m_child;
|
||||
int m_min, m_max;
|
||||
};
|
||||
|
||||
|
||||
@@ -167,19 +164,18 @@ class NRepeat final : public LPexp {
|
||||
/// a LPexp. It actually binds a light path expression to a certain rule.
|
||||
/// Making the begin state initial and the end state final. It can't be
|
||||
/// nested in other light path expressions, it is the root of the tree.
|
||||
class Rule
|
||||
{
|
||||
public:
|
||||
Rule(LPexp *child, void *rule):m_child(child), m_rule(rule) {};
|
||||
virtual ~Rule() { delete m_child; };
|
||||
void genAuto(NdfAutomata &automata)const;
|
||||
class Rule {
|
||||
public:
|
||||
Rule(LPexp* child, void* rule) : m_child(child), m_rule(rule) {};
|
||||
virtual ~Rule() { delete m_child; };
|
||||
void genAuto(NdfAutomata& automata) const;
|
||||
|
||||
protected:
|
||||
LPexp *m_child;
|
||||
// Anonymous pointer to the associated object for this rule
|
||||
void *m_rule;
|
||||
protected:
|
||||
LPexp* m_child;
|
||||
// Anonymous pointer to the associated object for this rule
|
||||
void* m_rule;
|
||||
};
|
||||
|
||||
} // namespace regexp
|
||||
} // namespace lpexp
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
@@ -38,6 +38,7 @@ namespace pvt {
|
||||
#define IlluminantE 0.33333333, 0.33333333 /* CIE equal-energy illuminant */
|
||||
#define IlluminantACES 0.32168, 0.33767 /* For ACES, approximate D60 */
|
||||
|
||||
namespace { // anon namespace to avoid duplicate OptiX symbols
|
||||
OSL_CONSTANT_DATA const static ColorSystem::Chroma k_color_systems[13] = {
|
||||
// Index, Name xRed yRed xGreen yGreen xBlue yBlue White point
|
||||
/* 0 Rec709 */ { 0.64, 0.33, 0.30, 0.60, 0.15, 0.06, IlluminantD65 },
|
||||
@@ -54,6 +55,7 @@ OSL_CONSTANT_DATA const static ColorSystem::Chroma k_color_systems[13] = {
|
||||
/* 11 ACES2065-1 */ { 0.7347, 0.2653, 0.0, 1.0, 0.0001, -0.077, IlluminantACES },
|
||||
/* 12 ACEScg */ { 0.713, 0.293, 0.165, 0.83, 0.128, 0.044, IlluminantACES },
|
||||
};
|
||||
} // namespace
|
||||
|
||||
// clang-format on
|
||||
|
||||
|
||||
+64
-52
@@ -11,10 +11,10 @@
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <OSL/dual.h>
|
||||
#include <OSL/dual_vec.h>
|
||||
#include <OSL/Imathx/Imathx.h>
|
||||
#include <OSL/device_string.h>
|
||||
#include <OSL/dual.h>
|
||||
#include <OSL/dual_vec.h>
|
||||
|
||||
#include <OpenImageIO/color.h>
|
||||
|
||||
@@ -37,96 +37,107 @@ public:
|
||||
// A colour system is defined by the CIE x and y coordinates of its
|
||||
// three primary illuminants and its white point.
|
||||
struct Chroma {
|
||||
float xRed, yRed,
|
||||
xGreen, yGreen,
|
||||
xBlue, yBlue,
|
||||
xWhite, yWhite;
|
||||
float xRed, yRed, xGreen, yGreen, xBlue, yBlue, xWhite, yWhite;
|
||||
};
|
||||
|
||||
OSL_HOSTDEVICE static const Chroma* fromString(StringParam colorspace);
|
||||
|
||||
/// Convert an XYZ color to RGB in our preferred color space.
|
||||
template <typename T> OSL_HOSTDEVICE T
|
||||
XYZ_to_RGB (const T &XYZ) const { return XYZ * m_XYZ2RGB; }
|
||||
template<typename T> OSL_HOSTDEVICE T XYZ_to_RGB(const T& XYZ) const
|
||||
{
|
||||
return XYZ * m_XYZ2RGB;
|
||||
}
|
||||
|
||||
/// Convert an RGB color in our preferred color space to XYZ.
|
||||
template <typename T> OSL_HOSTDEVICE T
|
||||
RGB_to_XYZ (const T &RGB) const { return RGB * m_RGB2XYZ; }
|
||||
template<typename T> OSL_HOSTDEVICE T RGB_to_XYZ(const T& RGB) const
|
||||
{
|
||||
return RGB * m_RGB2XYZ;
|
||||
}
|
||||
|
||||
/// Return the luminance of an RGB color in the current color space.
|
||||
OSL_HOSTDEVICE float
|
||||
luminance (const Color3 &RGB) const { return RGB.dot(m_luminance_scale); }
|
||||
OSL_HOSTDEVICE float luminance(const Color3& RGB) const
|
||||
{
|
||||
return RGB.dot(m_luminance_scale);
|
||||
}
|
||||
|
||||
/// Return the luminance scale of the current color space.
|
||||
const Color3 & luminance_scale() const { return m_luminance_scale; }
|
||||
const Color3& luminance_scale() const
|
||||
{
|
||||
return m_luminance_scale;
|
||||
}
|
||||
|
||||
/// Return the RGB in the current color space for blackbody radiation
|
||||
/// at temperature T (in Kelvin).
|
||||
OSL_HOSTDEVICE inline Color3
|
||||
blackbody_rgb (float T /*Kelvin*/) const;
|
||||
OSL_HOSTDEVICE inline Color3 blackbody_rgb(float T /*Kelvin*/) const;
|
||||
|
||||
// Interface to access underlying optimized lookup table for blackbody
|
||||
// When can_lookup_blackbody() returns true,
|
||||
// then lookup_blackbody_rgb can be safely called,
|
||||
// otherwise the compute_blackbody_rgb is required.
|
||||
OSL_HOSTDEVICE inline bool
|
||||
can_lookup_blackbody(float T /*Kelvin*/) const;
|
||||
OSL_HOSTDEVICE inline bool can_lookup_blackbody(float T /*Kelvin*/) const;
|
||||
|
||||
OSL_HOSTDEVICE inline Color3
|
||||
lookup_blackbody_rgb (float T /*Kelvin*/) const;
|
||||
OSL_HOSTDEVICE inline Color3 lookup_blackbody_rgb(float T /*Kelvin*/) const;
|
||||
|
||||
// Expensive real computation without lookup table
|
||||
OSL_HOSTDEVICE inline Color3
|
||||
compute_blackbody_rgb (float T /*Kelvin*/) const;
|
||||
OSL_HOSTDEVICE inline Color3 compute_blackbody_rgb(float T /*Kelvin*/) const;
|
||||
|
||||
|
||||
/// Set the current color space.
|
||||
OSL_HOSTDEVICE bool
|
||||
set_colorspace (StringParam colorspace);
|
||||
OSL_HOSTDEVICE bool set_colorspace(StringParam colorspace);
|
||||
|
||||
OSL_HOSTDEVICE Color3
|
||||
to_rgb (StringParam fromspace, const Color3& C, Context) const;
|
||||
OSL_HOSTDEVICE Color3 to_rgb(StringParam fromspace, const Color3& C,
|
||||
Context) const;
|
||||
|
||||
OSL_HOSTDEVICE Color3
|
||||
from_rgb (StringParam fromspace, const Color3& C, Context) const;
|
||||
OSL_HOSTDEVICE Color3 from_rgb(StringParam fromspace, const Color3& C,
|
||||
Context) const;
|
||||
|
||||
OSL_HOSTDEVICE Dual2<Color3>
|
||||
transformc (StringParam fromspace, StringParam tospace,
|
||||
const Dual2<Color3>& color, Context ctx) const;
|
||||
OSL_HOSTDEVICE Dual2<Color3> transformc(StringParam fromspace,
|
||||
StringParam tospace,
|
||||
const Dual2<Color3>& color,
|
||||
Context ctx) const;
|
||||
|
||||
OSL_HOSTDEVICE Color3
|
||||
transformc (StringParam fromspace, StringParam tospace,
|
||||
const Color3& color, Context ctx) const;
|
||||
OSL_HOSTDEVICE Color3 transformc(StringParam fromspace, StringParam tospace,
|
||||
const Color3& color, Context ctx) const;
|
||||
|
||||
OSL_HOSTDEVICE Dual2<Color3>
|
||||
ocio_transform (StringParam fromspace, StringParam tospace, const Dual2<Color3>& C, Context) const;
|
||||
OSL_HOSTDEVICE Dual2<Color3> ocio_transform(StringParam fromspace,
|
||||
StringParam tospace,
|
||||
const Dual2<Color3>& C,
|
||||
Context) const;
|
||||
|
||||
OSL_HOSTDEVICE Color3
|
||||
ocio_transform (StringParam fromspace, StringParam tospace, const Color3& C, Context) const;
|
||||
OSL_HOSTDEVICE Color3 ocio_transform(StringParam fromspace,
|
||||
StringParam tospace, const Color3& C,
|
||||
Context) const;
|
||||
|
||||
|
||||
OSL_HOSTDEVICE const StringParam& colorspace() const { return m_colorspace; }
|
||||
OSL_HOSTDEVICE const StringParam& colorspace() const
|
||||
{
|
||||
return m_colorspace;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE void error(StringParam src, StringParam dst, Context) const;
|
||||
|
||||
private:
|
||||
template <typename Color> OSL_HOSTDEVICE inline Color
|
||||
transformc (StringParam fromspace, StringParam tospace, const Color& C, Context) const;
|
||||
template<typename Color>
|
||||
OSL_HOSTDEVICE inline Color transformc(StringParam fromspace,
|
||||
StringParam tospace, const Color& C,
|
||||
Context) const;
|
||||
|
||||
template <typename Color> OSL_HOSTDEVICE inline Color
|
||||
ocio_transform (StringParam fromspace, StringParam tospace, const Color& C, Context) const;
|
||||
template<typename Color>
|
||||
OSL_HOSTDEVICE inline Color ocio_transform(StringParam fromspace,
|
||||
StringParam tospace,
|
||||
const Color& C, Context) const;
|
||||
|
||||
|
||||
// Derived/cached calculations from options:
|
||||
Color3 m_Red, m_Green, m_Blue; ///< Color primaries (xyY)
|
||||
Color3 m_White; ///< White point (xyY)
|
||||
Matrix33 m_XYZ2RGB; ///< XYZ to RGB conversion matrix
|
||||
Matrix33 m_RGB2XYZ; ///< RGB to XYZ conversion matrix
|
||||
Color3 m_luminance_scale; ///< Scaling for RGB->luma
|
||||
Color3 m_blackbody_table[317]; ///< Precomputed blackbody table
|
||||
Color3 m_Red, m_Green, m_Blue; ///< Color primaries (xyY)
|
||||
Color3 m_White; ///< White point (xyY)
|
||||
Matrix33 m_XYZ2RGB; ///< XYZ to RGB conversion matrix
|
||||
Matrix33 m_RGB2XYZ; ///< RGB to XYZ conversion matrix
|
||||
Color3 m_luminance_scale; ///< Scaling for RGB->luma
|
||||
Color3 m_blackbody_table[317]; ///< Precomputed blackbody table
|
||||
|
||||
// Keep this last so the CUDA device string can be easily set
|
||||
StringParam m_colorspace; ///< What RGB colors mean
|
||||
StringParam m_colorspace; ///< What RGB colors mean
|
||||
};
|
||||
|
||||
|
||||
@@ -138,9 +149,10 @@ public:
|
||||
ShadingSystemImpl* shadingsys);
|
||||
|
||||
private:
|
||||
const OIIO::ColorConfig& colorconfig (ShadingSystemImpl* shadingsys);
|
||||
const OIIO::ColorConfig& colorconfig(ShadingSystemImpl* shadingsys);
|
||||
|
||||
std::shared_ptr<OIIO::ColorConfig> m_colorconfig; ///< OIIO/OCIO color configuration
|
||||
std::shared_ptr<OIIO::ColorConfig>
|
||||
m_colorconfig; ///< OIIO/OCIO color configuration
|
||||
|
||||
// 1-item cache for the last requested custom color conversion processor
|
||||
OIIO::ColorProcessorHandle m_last_colorproc;
|
||||
@@ -149,7 +161,7 @@ private:
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace pvt
|
||||
} // namespace pvt
|
||||
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
+201
-174
@@ -22,15 +22,16 @@
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
#ifdef __OSL_WIDE_PVT
|
||||
namespace __OSL_WIDE_PVT {
|
||||
namespace __OSL_WIDE_PVT {
|
||||
#else
|
||||
namespace pvt {
|
||||
namespace pvt {
|
||||
#endif
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
OSL_HOSTDEVICE inline void clamp_zero (Color3 &c)
|
||||
OSL_HOSTDEVICE inline void
|
||||
clamp_zero(Color3& c)
|
||||
{
|
||||
if (c.x < 0.0f)
|
||||
c.x = 0.0f;
|
||||
@@ -48,8 +49,9 @@ OSL_HOSTDEVICE inline void clamp_zero (Color3 &c)
|
||||
// cie_colour_match[(lambda - 380) / 5][2] = zBar
|
||||
//OSL_CONSTANT_DATA const float cie_colour_match[81][3] =
|
||||
// Choose to access 1d array vs 2d to allow better code generation of gathers
|
||||
OSL_CONSTANT_DATA const float cie_colour_match[81*3] OSL_ALIGNAS(64) =
|
||||
{
|
||||
namespace { // anon namespace to avoid duplicate OptiX symbols
|
||||
static OSL_CONSTANT_DATA const float cie_colour_match[81 * 3] OSL_ALIGNAS(64) = {
|
||||
// clang-format off
|
||||
0.0014,0.0000,0.0065, 0.0022,0.0001,0.0105, 0.0042,0.0001,0.0201,
|
||||
0.0076,0.0002,0.0362, 0.0143,0.0004,0.0679, 0.0232,0.0006,0.1102,
|
||||
0.0435,0.0012,0.2074, 0.0776,0.0022,0.3713, 0.1344,0.0040,0.6456,
|
||||
@@ -77,22 +79,23 @@ OSL_CONSTANT_DATA const float cie_colour_match[81*3] OSL_ALIGNAS(64) =
|
||||
0.0007,0.0002,0.0000, 0.0005,0.0002,0.0000, 0.0003,0.0001,0.0000,
|
||||
0.0002,0.0001,0.0000, 0.0002,0.0001,0.0000, 0.0001,0.0000,0.0000,
|
||||
0.0001,0.0000,0.0000, 0.0001,0.0000,0.0000, 0.0000,0.0000,0.0000
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
// For a given wavelength lambda (in nm), return the XYZ triple giving the
|
||||
// XYZ color corresponding to that single wavelength;
|
||||
OSL_HOSTDEVICE static Color3
|
||||
wavelength_color_XYZ (float lambda_nm)
|
||||
wavelength_color_XYZ(float lambda_nm)
|
||||
{
|
||||
float ii = (lambda_nm-380.0f) / 5.0f; // scaled 0..80
|
||||
int i = (int) ii;
|
||||
float ii = (lambda_nm - 380.0f) / 5.0f; // scaled 0..80
|
||||
int i = (int)ii;
|
||||
// NOTE: bitwise OR to avoid branchiness logical OR introduces.
|
||||
// Also when left as logical OR, vectorizing with clang 11 did not
|
||||
// mask off gathering of out of range index values causing segfaults
|
||||
if ((i < 0) | (i >= 80))
|
||||
return Color3(0.0f,0.0f,0.0f);
|
||||
return Color3(0.0f, 0.0f, 0.0f);
|
||||
float remainder = ii - i;
|
||||
// Do not separate address calculation so that compiler can see that the
|
||||
// base pointer is uniform for all data lanes and 32bit indices can be
|
||||
@@ -101,10 +104,15 @@ wavelength_color_XYZ (float lambda_nm)
|
||||
// Furthermore, have all gathers use the same indices by having different
|
||||
// base registers for each of the 6 components to avoid need to manipulate
|
||||
// indices between gathers.
|
||||
constexpr int stride = sizeof(Color3)/sizeof(float);
|
||||
const int si = stride*i;
|
||||
Color3 XYZ = OIIO::lerp (Color3((cie_colour_match+0)[si], (cie_colour_match+1)[si], (cie_colour_match+2)[si]),
|
||||
Color3((cie_colour_match+3)[si], (cie_colour_match+4)[si], (cie_colour_match+5)[si]), remainder);
|
||||
constexpr int stride = sizeof(Color3) / sizeof(float);
|
||||
const int si = stride * i;
|
||||
Color3 XYZ = OIIO::lerp(Color3((cie_colour_match + 0)[si],
|
||||
(cie_colour_match + 1)[si],
|
||||
(cie_colour_match + 2)[si]),
|
||||
Color3((cie_colour_match + 3)[si],
|
||||
(cie_colour_match + 4)[si],
|
||||
(cie_colour_match + 5)[si]),
|
||||
remainder);
|
||||
#if 0
|
||||
float n = (XYZ.x + XYZ.y + XYZ.z);
|
||||
float n_inv = (n >= 1.0e-6f ? 1.0f/n : 0.0f);
|
||||
@@ -130,27 +138,32 @@ wavelength_color_XYZ (float lambda_nm)
|
||||
// I tuned this a bit, and with the current values we can have all
|
||||
// blackbody results accurate to within 0.1% with a table size of 317
|
||||
// (about 5 KB of data).
|
||||
#define BB_DRAPER 800.0f /* really 798K, below this visible BB is negligible */
|
||||
#define BB_DRAPER 800.0f /* really 798K, below this visible BB is negligible */
|
||||
#define BB_MAX_TABLE_RANGE 12000.0f /* max temp for which we use the table */
|
||||
#define BB_TABLE_XPOWER 1.5f // NOTE: not used, hardcoded into expressions below
|
||||
#define BB_TABLE_YPOWER 5.0f // NOTE: decode is hardcoded
|
||||
#define BB_TABLE_XPOWER \
|
||||
1.5f // NOTE: not used, hardcoded into expressions below
|
||||
#define BB_TABLE_YPOWER 5.0f // NOTE: decode is hardcoded
|
||||
#define BB_TABLE_SPACING 2.0f
|
||||
|
||||
OSL_HOSTDEVICE inline float BB_TABLE_MAP(float i) {
|
||||
OSL_HOSTDEVICE inline float
|
||||
BB_TABLE_MAP(float i)
|
||||
{
|
||||
// return powf (i, BB_TABLE_XPOWER) * BB_TABLE_SPACING + BB_DRAPER;
|
||||
float is = sqrtf(i);
|
||||
float ip = is * is * is; // ^3/2
|
||||
float ip = is * is * is; // ^3/2
|
||||
return ip * BB_TABLE_SPACING + BB_DRAPER;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE inline float BB_TABLE_UNMAP(float T) {
|
||||
OSL_HOSTDEVICE inline float
|
||||
BB_TABLE_UNMAP(float T)
|
||||
{
|
||||
// return powf ((T - BB_DRAPER) / BB_TABLE_SPACING, 1.0f/BB_TABLE_XPOWER);
|
||||
float t = (T - BB_DRAPER) / BB_TABLE_SPACING;
|
||||
float t = (T - BB_DRAPER) / BB_TABLE_SPACING;
|
||||
// Clang doesn't have vectorizing version of cbrtf,
|
||||
// so use OIIO's instead
|
||||
float ic = OIIO::fast_cbrt(t);
|
||||
|
||||
return ic * ic; // ^2/3
|
||||
return ic * ic; // ^2/3
|
||||
}
|
||||
|
||||
|
||||
@@ -173,26 +186,31 @@ OSL_HOSTDEVICE inline float BB_TABLE_UNMAP(float T) {
|
||||
// W/m^2 in the range [wavelength,wavelength+dwavelength].
|
||||
class bb_spectrum {
|
||||
public:
|
||||
OSL_HOSTDEVICE bb_spectrum (float temperature=5000) : m_temp(temperature) { }
|
||||
OSL_HOSTDEVICE bb_spectrum(float temperature = 5000) : m_temp(temperature)
|
||||
{
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE float operator() (float wavelength_nm) const {
|
||||
OSL_HOSTDEVICE float operator()(float wavelength_nm) const
|
||||
{
|
||||
// Testing showed < .0000534058f differences between single and double
|
||||
// precision. So choose to perform math using single precision.
|
||||
float wlm = wavelength_nm * 1e-9f; // Wavelength in meters
|
||||
const float c1 = 3.74183e-16f; // 2*pi*h*c^2, W*m^2
|
||||
const float c2 = 1.4388e-2f; // h*c/k, m*K
|
||||
// h is Planck's const, k is Boltzmann's
|
||||
float wlm = wavelength_nm * 1e-9f; // Wavelength in meters
|
||||
const float c1 = 3.74183e-16f; // 2*pi*h*c^2, W*m^2
|
||||
const float c2 = 1.4388e-2f; // h*c/k, m*K
|
||||
// h is Planck's const, k is Boltzmann's
|
||||
//const float inverse_of_wlm5 = std::pow(wlm,-5.0f);
|
||||
// Rather than calling powf, just implement exact power and inverse
|
||||
// directly here. Confirmed with ICC that identical optimized assembly
|
||||
// is produced to std::powf and more SIMD friendly to other compilers.
|
||||
const float wlm2 = wlm*wlm;
|
||||
const float wlm4 = wlm2*wlm2;
|
||||
const float wlm5 = wlm4*wlm;
|
||||
const float inverse_of_wlm5 = 1.0f/wlm5;
|
||||
const float wlm2 = wlm * wlm;
|
||||
const float wlm4 = wlm2 * wlm2;
|
||||
const float wlm5 = wlm4 * wlm;
|
||||
const float inverse_of_wlm5 = 1.0f / wlm5;
|
||||
// Clang doesn't have vectorizing version of expm1, so use OIIO::fast_expm1
|
||||
return float((c1 * inverse_of_wlm5) / OIIO::fast_expm1(c2 / (wlm * m_temp)));
|
||||
return float((c1 * inverse_of_wlm5)
|
||||
/ OIIO::fast_expm1(c2 / (wlm * m_temp)));
|
||||
}
|
||||
|
||||
private:
|
||||
float m_temp;
|
||||
};
|
||||
@@ -200,9 +218,9 @@ private:
|
||||
|
||||
// Integrate the CIE color matching values, weighted by function
|
||||
// spec_intens(lambda_nm), returning the aggregate XYZ color.
|
||||
template<class SPECTRUM> OSL_HOSTDEVICE
|
||||
static Color3
|
||||
spectrum_to_XYZ (const SPECTRUM &spec_intens)
|
||||
template<class SPECTRUM>
|
||||
OSL_HOSTDEVICE static Color3
|
||||
spectrum_to_XYZ(const SPECTRUM& spec_intens)
|
||||
{
|
||||
float X = 0, Y = 0, Z = 0;
|
||||
const float dlambda = 5.0f * 1e-9; // in meters
|
||||
@@ -210,80 +228,81 @@ spectrum_to_XYZ (const SPECTRUM &spec_intens)
|
||||
float lambda = 380.0f + 5.0f * i;
|
||||
// N.B. spec_intens returns result in W/m^2 but it's a differential,
|
||||
// needs to be scaled by dlambda!
|
||||
float Me = spec_intens(lambda) * dlambda;
|
||||
constexpr int stride = sizeof(Color3)/sizeof(float);
|
||||
const int si = stride*i;
|
||||
float Me = spec_intens(lambda) * dlambda;
|
||||
constexpr int stride = sizeof(Color3) / sizeof(float);
|
||||
const int si = stride * i;
|
||||
X += Me * (cie_colour_match + 0)[si];
|
||||
Y += Me * (cie_colour_match + 1)[si];
|
||||
Z += Me * (cie_colour_match + 2)[si];
|
||||
}
|
||||
return Color3 (X, Y, Z);
|
||||
return Color3(X, Y, Z);
|
||||
}
|
||||
|
||||
|
||||
template <typename COLOR3> OSL_HOSTDEVICE
|
||||
static COLOR3
|
||||
hsv_to_rgb (const COLOR3& hsv)
|
||||
template<typename COLOR3>
|
||||
OSL_HOSTDEVICE static COLOR3
|
||||
hsv_to_rgb(const COLOR3& hsv)
|
||||
{
|
||||
// Reference for this technique: Foley & van Dam
|
||||
using FLOAT = typename ScalarFromVec<COLOR3>::type;
|
||||
FLOAT h = comp_x(hsv), s = comp_y(hsv), v = comp_z(hsv);
|
||||
if (s < 0.0001f) {
|
||||
return make_Color3 (v, v, v);
|
||||
return make_Color3(v, v, v);
|
||||
} else {
|
||||
using std::floor; // to pick up the float one
|
||||
using OIIO::ifloor;
|
||||
h = 6.0f * (h - floor(h)); // expand to [0..6)
|
||||
int hi = ifloor(h);
|
||||
using std::floor; // to pick up the float one
|
||||
h = 6.0f * (h - floor(h)); // expand to [0..6)
|
||||
int hi = ifloor(h);
|
||||
FLOAT f = h - FLOAT(hi);
|
||||
FLOAT p = v * (1.0f-s);
|
||||
FLOAT q = v * (1.0f-s*f);
|
||||
FLOAT t = v * (1.0f-s*(1.0f-f));
|
||||
FLOAT p = v * (1.0f - s);
|
||||
FLOAT q = v * (1.0f - s * f);
|
||||
FLOAT t = v * (1.0f - s * (1.0f - f));
|
||||
#ifdef __OSL_WIDE_PVT
|
||||
// Avoid switch statement vectorizor doesn't like
|
||||
// Also avoid if/else nest which some optimizers might
|
||||
// convert back into a switch statement
|
||||
# if OSL_ANY_CLANG && !OSL_INTEL_CLASSIC_COMPILER_VERSION && !OSL_INTEL_LLVM_COMPILER_VERSION
|
||||
# if OSL_ANY_CLANG && !OSL_INTEL_CLASSIC_COMPILER_VERSION \
|
||||
&& !OSL_INTEL_LLVM_COMPILER_VERSION
|
||||
// Clang was still transforming series of if's back into a switch.
|
||||
// Alternate between == and <= comparisons to avoid
|
||||
# define __OSL_ASC_EQ <=
|
||||
# else
|
||||
# define __OSL_ASC_EQ ==
|
||||
# endif
|
||||
# define __OSL_ASC_EQ <=
|
||||
# else
|
||||
# define __OSL_ASC_EQ ==
|
||||
# endif
|
||||
if (hi == 0) {
|
||||
return make_Color3 (v, t, p);
|
||||
return make_Color3(v, t, p);
|
||||
}
|
||||
if (hi __OSL_ASC_EQ 1) {
|
||||
return make_Color3 (q, v, p);
|
||||
return make_Color3(q, v, p);
|
||||
}
|
||||
if (hi == 2) {
|
||||
return make_Color3 (p, v, t);
|
||||
return make_Color3(p, v, t);
|
||||
}
|
||||
if (hi __OSL_ASC_EQ 3) {
|
||||
return make_Color3 (p, q, v);
|
||||
return make_Color3(p, q, v);
|
||||
}
|
||||
if (hi == 4) {
|
||||
return make_Color3 (t, p, v);
|
||||
return make_Color3(t, p, v);
|
||||
}
|
||||
return make_Color3 (v, p, q);
|
||||
return make_Color3(v, p, q);
|
||||
# undef __OSL_ASC_EQ
|
||||
#else
|
||||
// serial execution might be faster with switch
|
||||
switch (hi) {
|
||||
case 0 : return make_Color3 (v, t, p);
|
||||
case 1 : return make_Color3 (q, v, p);
|
||||
case 2 : return make_Color3 (p, v, t);
|
||||
case 3 : return make_Color3 (p, q, v);
|
||||
case 4 : return make_Color3 (t, p, v);
|
||||
default: return make_Color3 (v, p, q);
|
||||
case 0: return make_Color3(v, t, p);
|
||||
case 1: return make_Color3(q, v, p);
|
||||
case 2: return make_Color3(p, v, t);
|
||||
case 3: return make_Color3(p, q, v);
|
||||
case 4: return make_Color3(t, p, v);
|
||||
default: return make_Color3(v, p, q);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
template <typename COLOR3> OSL_HOSTDEVICE
|
||||
static inline COLOR3
|
||||
rgb_to_hsv (const COLOR3& rgb)
|
||||
template<typename COLOR3>
|
||||
OSL_HOSTDEVICE static inline COLOR3
|
||||
rgb_to_hsv(const COLOR3& rgb)
|
||||
{
|
||||
// See Foley & van Dam
|
||||
using FLOAT = typename ScalarFromVec<COLOR3>::type;
|
||||
@@ -291,17 +310,16 @@ rgb_to_hsv (const COLOR3& rgb)
|
||||
// NOTE: use sfm::min_val and sfm::max_val instead of std::min and
|
||||
// std::max which return references
|
||||
// that can interfere with vectorization
|
||||
FLOAT mincomp = sfm::min_val (r, sfm::min_val (g, b));
|
||||
FLOAT maxcomp = sfm::max_val (r, sfm::max_val (g, b));
|
||||
FLOAT delta = maxcomp - mincomp; // chroma
|
||||
FLOAT v = maxcomp;
|
||||
FLOAT s = 0.0f;
|
||||
FLOAT mincomp = sfm::min_val(r, sfm::min_val(g, b));
|
||||
FLOAT maxcomp = sfm::max_val(r, sfm::max_val(g, b));
|
||||
FLOAT delta = maxcomp - mincomp; // chroma
|
||||
FLOAT v = maxcomp;
|
||||
FLOAT s = 0.0f;
|
||||
if (maxcomp > 0.0f)
|
||||
s = delta / maxcomp;
|
||||
FLOAT h = 0.0f;
|
||||
if (s > 0.0f)
|
||||
{
|
||||
#if 0 // Reference version
|
||||
if (s > 0.0f) {
|
||||
#if 0 // Reference version
|
||||
if (r >= maxcomp) h = (g-b) / delta;
|
||||
else if (g >= maxcomp) h = 2.0f + (b-r) / delta;
|
||||
else h = 4.0f + (r-g) / delta;
|
||||
@@ -314,57 +332,67 @@ rgb_to_hsv (const COLOR3& rgb)
|
||||
// which was already going to be a divisor.
|
||||
float k;
|
||||
FLOAT x, y;
|
||||
if (r >= maxcomp) { k = 0.0f/6.0f; x = g; y = b; }
|
||||
else if (g >= maxcomp) { k = 2.0f/6.0f; x = b; y = r; }
|
||||
else { k = 4.0f/6.0f; x = r; y = g; }
|
||||
h = k + (x-y) / (6.0f*delta);
|
||||
if (r >= maxcomp) {
|
||||
k = 0.0f / 6.0f;
|
||||
x = g;
|
||||
y = b;
|
||||
} else if (g >= maxcomp) {
|
||||
k = 2.0f / 6.0f;
|
||||
x = b;
|
||||
y = r;
|
||||
} else {
|
||||
k = 4.0f / 6.0f;
|
||||
x = r;
|
||||
y = g;
|
||||
}
|
||||
h = k + (x - y) / (6.0f * delta);
|
||||
#endif
|
||||
if (h < 0.0f)
|
||||
h += 1.0f;
|
||||
}
|
||||
return make_Color3 (h, s, v);
|
||||
return make_Color3(h, s, v);
|
||||
}
|
||||
|
||||
template <typename COLOR3> OSL_HOSTDEVICE
|
||||
static COLOR3
|
||||
hsl_to_rgb (const COLOR3& hsl)
|
||||
template<typename COLOR3>
|
||||
OSL_HOSTDEVICE static COLOR3
|
||||
hsl_to_rgb(const COLOR3& hsl)
|
||||
{
|
||||
using FLOAT = typename ScalarFromVec<COLOR3>::type;
|
||||
FLOAT h = comp_x(hsl), s = comp_y(hsl), l = comp_z(hsl);
|
||||
// Easiest to convert hsl -> hsv, then hsv -> RGB (per Foley & van Dam)
|
||||
FLOAT v = (l <= 0.5f) ? (l * (1.0f + s)) : (l * (1.0f - s) + s);
|
||||
if (v <= 0.0f) {
|
||||
return make_Color3 (0.0f, 0.0f, 0.0f);
|
||||
return make_Color3(0.0f, 0.0f, 0.0f);
|
||||
} else {
|
||||
FLOAT min = 2.0f * l - v;
|
||||
s = (v - min) / v;
|
||||
return hsv_to_rgb (make_Color3(h, s, v));
|
||||
s = (v - min) / v;
|
||||
return hsv_to_rgb(make_Color3(h, s, v));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename COLOR3> OSL_HOSTDEVICE
|
||||
static COLOR3
|
||||
rgb_to_hsl (const COLOR3& rgb)
|
||||
template<typename COLOR3>
|
||||
OSL_HOSTDEVICE static COLOR3
|
||||
rgb_to_hsl(const COLOR3& rgb)
|
||||
{
|
||||
// See Foley & van Dam
|
||||
// First convert rgb to hsv, then to hsl
|
||||
using FLOAT = typename ScalarFromVec<COLOR3>::type;
|
||||
// NOTE: use sfm::min_val instead of std::min which returns references
|
||||
// that can interfere with vectorization
|
||||
FLOAT minval = sfm::min_val (comp_x(rgb), sfm::min_val (comp_y(rgb), comp_z(rgb)));
|
||||
COLOR3 hsv = rgb_to_hsv (rgb);
|
||||
FLOAT maxval = comp_z(hsv); // v == maxval
|
||||
FLOAT h = comp_x(hsv), s, l = (minval+maxval) / 2.0f;
|
||||
if (equalVal (minval, maxval))
|
||||
FLOAT minval = sfm::min_val(comp_x(rgb),
|
||||
sfm::min_val(comp_y(rgb), comp_z(rgb)));
|
||||
COLOR3 hsv = rgb_to_hsv(rgb);
|
||||
FLOAT maxval = comp_z(hsv); // v == maxval
|
||||
FLOAT h = comp_x(hsv), s, l = (minval + maxval) / 2.0f;
|
||||
if (equalVal(minval, maxval))
|
||||
s = 0.0f; // special 'achromatic' case, hue is 0
|
||||
#if 0 // reference version
|
||||
#if 0 // reference version
|
||||
else if (l <= 0.5f)
|
||||
s = (maxval - minval) / (maxval + minval);
|
||||
else
|
||||
s = (maxval - minval) / (2.0f - maxval - minval)
|
||||
#else
|
||||
else
|
||||
{
|
||||
else {
|
||||
// Share computation of min2max and divide vs. repeating in 2 branches
|
||||
// which both could execute masked
|
||||
FLOAT min2max = (maxval - minval);
|
||||
@@ -376,90 +404,90 @@ rgb_to_hsl (const COLOR3& rgb)
|
||||
s = min2max / divisor;
|
||||
}
|
||||
#endif
|
||||
return make_Color3 (h, s, l);
|
||||
return make_Color3(h, s, l);
|
||||
}
|
||||
|
||||
template <typename COLOR3> OSL_HOSTDEVICE
|
||||
static COLOR3
|
||||
YIQ_to_rgb (const COLOR3& YIQ)
|
||||
template<typename COLOR3>
|
||||
OSL_HOSTDEVICE static COLOR3
|
||||
YIQ_to_rgb(const COLOR3& YIQ)
|
||||
{
|
||||
return YIQ * Matrix33(1.0000, 1.0000, 1.0000,
|
||||
0.9557, -0.2716, -1.1082,
|
||||
0.6199, -0.6469, 1.7051);
|
||||
return YIQ
|
||||
* Matrix33(1.0000, 1.0000, 1.0000, 0.9557, -0.2716, -1.1082, 0.6199,
|
||||
-0.6469, 1.7051);
|
||||
}
|
||||
|
||||
template <typename COLOR3> OSL_HOSTDEVICE
|
||||
static COLOR3
|
||||
rgb_to_YIQ (const COLOR3& rgb)
|
||||
template<typename COLOR3>
|
||||
OSL_HOSTDEVICE static COLOR3
|
||||
rgb_to_YIQ(const COLOR3& rgb)
|
||||
{
|
||||
return rgb * Matrix33(0.299, 0.596, 0.212,
|
||||
0.587, -0.275, -0.523,
|
||||
0.114, -0.321, 0.311);
|
||||
return rgb
|
||||
* Matrix33(0.299, 0.596, 0.212, 0.587, -0.275, -0.523, 0.114, -0.321,
|
||||
0.311);
|
||||
}
|
||||
|
||||
template <typename COLOR3> OSL_HOSTDEVICE
|
||||
static COLOR3
|
||||
XYZ_to_xyY (const COLOR3 &XYZ)
|
||||
template<typename COLOR3>
|
||||
OSL_HOSTDEVICE static COLOR3
|
||||
XYZ_to_xyY(const COLOR3& XYZ)
|
||||
{
|
||||
using FLOAT = typename ScalarFromVec<COLOR3>::type;
|
||||
FLOAT n = (comp_x(XYZ) + comp_y(XYZ) + comp_z(XYZ));
|
||||
FLOAT n_inv = (n >= 1.0e-6f ? 1.0f/n : 0.0f);
|
||||
return make_Color3 (comp_x(XYZ)*n_inv, comp_y(XYZ)*n_inv, comp_y(XYZ));
|
||||
FLOAT n = (comp_x(XYZ) + comp_y(XYZ) + comp_z(XYZ));
|
||||
FLOAT n_inv = (n >= 1.0e-6f ? 1.0f / n : 0.0f);
|
||||
return make_Color3(comp_x(XYZ) * n_inv, comp_y(XYZ) * n_inv, comp_y(XYZ));
|
||||
// N.B. http://brucelindbloom.com/ suggests returning xy of the
|
||||
// reference white in the X+Y+Z==0 case.
|
||||
}
|
||||
|
||||
template <typename COLOR3> OSL_HOSTDEVICE
|
||||
static COLOR3
|
||||
xyY_to_XYZ (const COLOR3 &xyY)
|
||||
template<typename COLOR3>
|
||||
OSL_HOSTDEVICE static COLOR3
|
||||
xyY_to_XYZ(const COLOR3& xyY)
|
||||
{
|
||||
using FLOAT = typename ScalarFromVec<COLOR3>::type;
|
||||
FLOAT Y = comp_z(xyY);
|
||||
FLOAT Y_y = (comp_y(xyY) > 1.0e-6f ? Y/comp_y(xyY) : 0.0f);
|
||||
FLOAT X = Y_y * comp_x(xyY);
|
||||
FLOAT Z = Y_y * (1.0f - comp_x(xyY) - comp_y(xyY));
|
||||
return make_Color3 (X, Y, Z);
|
||||
FLOAT Y = comp_z(xyY);
|
||||
FLOAT Y_y = (comp_y(xyY) > 1.0e-6f ? Y / comp_y(xyY) : 0.0f);
|
||||
FLOAT X = Y_y * comp_x(xyY);
|
||||
FLOAT Z = Y_y * (1.0f - comp_x(xyY) - comp_y(xyY));
|
||||
return make_Color3(X, Y, Z);
|
||||
}
|
||||
|
||||
template <typename COLOR3> OSL_HOSTDEVICE
|
||||
static COLOR3
|
||||
sRGB_to_linear (const COLOR3& srgb)
|
||||
template<typename COLOR3>
|
||||
OSL_HOSTDEVICE static COLOR3
|
||||
sRGB_to_linear(const COLOR3& srgb)
|
||||
{
|
||||
// See Foley & van Dam
|
||||
using FLOAT = typename ScalarFromVec<COLOR3>::type;
|
||||
using namespace OIIO;
|
||||
//using safe_pow = std::conditional<is_Dual<COLOR3>::value, OSL::safe_pow, OIIO::safe_pow>::type;
|
||||
FLOAT r = comp_x(srgb), g = comp_y(srgb), b = comp_z(srgb);
|
||||
auto convert = [] (FLOAT x) -> FLOAT {
|
||||
return (x <= 0.04045f) ?
|
||||
(x * (1.0f / 12.92f)) :
|
||||
safe_pow((x + 0.055f) * (1.0f / 1.055f), FLOAT(2.4f));
|
||||
auto convert = [](FLOAT x) -> FLOAT {
|
||||
return (x <= 0.04045f)
|
||||
? (x * (1.0f / 12.92f))
|
||||
: safe_pow((x + 0.055f) * (1.0f / 1.055f), FLOAT(2.4f));
|
||||
};
|
||||
return make_Color3 (convert(r), convert(g), convert(b));
|
||||
return make_Color3(convert(r), convert(g), convert(b));
|
||||
}
|
||||
|
||||
template <typename COLOR3> OSL_HOSTDEVICE
|
||||
static COLOR3
|
||||
linear_to_sRGB (const COLOR3& rgb)
|
||||
template<typename COLOR3>
|
||||
OSL_HOSTDEVICE static COLOR3
|
||||
linear_to_sRGB(const COLOR3& rgb)
|
||||
{
|
||||
// See Foley & van Dam
|
||||
using FLOAT = typename ScalarFromVec<COLOR3>::type;
|
||||
using namespace OIIO;
|
||||
//using safe_pow = std::conditional<is_Dual<COLOR3>::value, OSL::safe_pow, OIIO::safe_pow>::type;
|
||||
FLOAT r = comp_x(rgb), g = comp_y(rgb), b = comp_z(rgb);
|
||||
auto convert = [] (FLOAT x) -> FLOAT {
|
||||
return (x <= 0.0031308f) ?
|
||||
(12.92f * x) :
|
||||
(1.055f * safe_pow(x, FLOAT(1.f / 2.4f)) - 0.055f);
|
||||
auto convert = [](FLOAT x) -> FLOAT {
|
||||
return (x <= 0.0031308f)
|
||||
? (12.92f * x)
|
||||
: (1.055f * safe_pow(x, FLOAT(1.f / 2.4f)) - 0.055f);
|
||||
};
|
||||
|
||||
return make_Color3 (convert(r), convert(g), convert(b));
|
||||
return make_Color3(convert(r), convert(g), convert(b));
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE inline Color3
|
||||
colpow (const Color3 &c, float p)
|
||||
colpow(const Color3& c, float p)
|
||||
{
|
||||
return Color3 (powf(c.x,p), powf(c.y,p), powf(c.z,p));
|
||||
return Color3(powf(c.x, p), powf(c.y, p), powf(c.z, p));
|
||||
}
|
||||
|
||||
} // namespace __OSL_WIDE_PVT or pvt
|
||||
@@ -468,11 +496,11 @@ namespace pvt {
|
||||
|
||||
|
||||
#ifdef __OSL_WIDE_PVT
|
||||
using __OSL_WIDE_PVT::clamp_zero;
|
||||
using __OSL_WIDE_PVT::bb_spectrum;
|
||||
using __OSL_WIDE_PVT::spectrum_to_XYZ;
|
||||
using __OSL_WIDE_PVT::BB_TABLE_MAP;
|
||||
using __OSL_WIDE_PVT::BB_TABLE_UNMAP;
|
||||
using __OSL_WIDE_PVT::bb_spectrum;
|
||||
using __OSL_WIDE_PVT::BB_TABLE_MAP;
|
||||
using __OSL_WIDE_PVT::BB_TABLE_UNMAP;
|
||||
using __OSL_WIDE_PVT::clamp_zero;
|
||||
using __OSL_WIDE_PVT::spectrum_to_XYZ;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -483,15 +511,15 @@ ColorSystem::can_lookup_blackbody(float T /*Kelvin*/) const
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE Color3
|
||||
ColorSystem::lookup_blackbody_rgb (float T /*Kelvin*/) const
|
||||
ColorSystem::lookup_blackbody_rgb(float T /*Kelvin*/) const
|
||||
{
|
||||
if (T < BB_DRAPER)
|
||||
return Color3(1.0e-6f,0.0f,0.0f); // very very dim red
|
||||
return Color3(1.0e-6f, 0.0f, 0.0f); // very very dim red
|
||||
|
||||
// can_lookup_blackbody() should have checked before now
|
||||
OSL_DASSERT(T < BB_MAX_TABLE_RANGE);
|
||||
float t = BB_TABLE_UNMAP(T);
|
||||
int ti = static_cast<int>(t);
|
||||
float t = BB_TABLE_UNMAP(T);
|
||||
int ti = static_cast<int>(t);
|
||||
float remainder = t - ti;
|
||||
#ifdef __OSL_WIDE_PVT
|
||||
// Choose to access Color3 lookup table as 3 float components.
|
||||
@@ -500,40 +528,40 @@ ColorSystem::lookup_blackbody_rgb (float T /*Kelvin*/) const
|
||||
// dereferencing Color3 which was using 64bit gathers which can take
|
||||
// multiple registers to hold the 64bit offsets and multiple gather
|
||||
// instructions who's results need to be merged into a single register.
|
||||
const float *blackbody_components = reinterpret_cast<const float *>(m_blackbody_table);
|
||||
constexpr int stride = sizeof(Color3)/sizeof(float);
|
||||
int sti = stride*ti;
|
||||
Color3 rgb = OIIO::lerp (
|
||||
// Have all gathers use the same indices by having different base registers
|
||||
const float* blackbody_components = reinterpret_cast<const float*>(
|
||||
m_blackbody_table);
|
||||
constexpr int stride = sizeof(Color3) / sizeof(float);
|
||||
int sti = stride * ti;
|
||||
Color3 rgb = OIIO::lerp(
|
||||
// Have all gathers use the same indices by having different base registers
|
||||
// for each of the 6 components
|
||||
Color3((blackbody_components+0)[sti],
|
||||
(blackbody_components+1)[sti],
|
||||
(blackbody_components+2)[sti]),
|
||||
Color3((blackbody_components+3)[sti],
|
||||
(blackbody_components+4)[sti],
|
||||
(blackbody_components+5)[sti]),
|
||||
remainder);
|
||||
Color3((blackbody_components + 0)[sti], (blackbody_components + 1)[sti],
|
||||
(blackbody_components + 2)[sti]),
|
||||
Color3((blackbody_components + 3)[sti], (blackbody_components + 4)[sti],
|
||||
(blackbody_components + 5)[sti]),
|
||||
remainder);
|
||||
#else
|
||||
Color3 rgb = OIIO::lerp (m_blackbody_table[ti], m_blackbody_table[ti+1], remainder);
|
||||
Color3 rgb = OIIO::lerp(m_blackbody_table[ti], m_blackbody_table[ti + 1],
|
||||
remainder);
|
||||
#endif
|
||||
//return colpow(rgb, BB_TABLE_YPOWER);
|
||||
Color3 rgb2 = rgb * rgb;
|
||||
Color3 rgb4 = rgb2 * rgb2;
|
||||
return rgb4 * rgb; // ^5
|
||||
return rgb4 * rgb; // ^5
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE Color3
|
||||
ColorSystem::compute_blackbody_rgb (float T /*Kelvin*/) const
|
||||
ColorSystem::compute_blackbody_rgb(float T /*Kelvin*/) const
|
||||
{
|
||||
// compute for real
|
||||
bb_spectrum spec (T);
|
||||
Color3 rgb = XYZ_to_RGB (spectrum_to_XYZ (spec));
|
||||
clamp_zero (rgb);
|
||||
bb_spectrum spec(T);
|
||||
Color3 rgb = XYZ_to_RGB(spectrum_to_XYZ(spec));
|
||||
clamp_zero(rgb);
|
||||
return rgb;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE Color3
|
||||
ColorSystem::blackbody_rgb (float T) const
|
||||
ColorSystem::blackbody_rgb(float T) const
|
||||
{
|
||||
if (can_lookup_blackbody(T)) {
|
||||
return lookup_blackbody_rgb(T);
|
||||
@@ -544,4 +572,3 @@ ColorSystem::blackbody_rgb (float T) const
|
||||
|
||||
} // namespace pvt
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ osl_getmessage(ShaderGlobals* sg, const char* source_, const char* name_,
|
||||
sg->context->errorfmt(
|
||||
"message \"{}\" was set by layer #{} ({}:{})"
|
||||
" but is being queried by layer #{} ({}:{})"
|
||||
" - messages may only be transfered from nodes "
|
||||
" - messages may only be transferred from nodes "
|
||||
"that appear earlier in the shading network",
|
||||
name, m->layeridx, m->sourcefile, m->sourceline, layeridx,
|
||||
sourcefile, sourceline);
|
||||
|
||||
+1223
-945
File diff suppressed because it is too large
Load Diff
@@ -27,6 +27,10 @@
|
||||
#pragma clang diagnostic ignored "-Wparentheses-equality"
|
||||
#endif
|
||||
|
||||
#if OSL_CLANG_VERSION >= 150000
|
||||
#pragma clang diagnostic ignored "-Wunused-but-set-variable"
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC visibility push(hidden)
|
||||
#endif
|
||||
|
||||
+33
-33
@@ -4,11 +4,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <OSL/platform.h>
|
||||
#include "osl_pvt.h"
|
||||
#include <OSL/platform.h>
|
||||
|
||||
#include <OpenImageIO/thread.h>
|
||||
#include <OpenImageIO/string_view.h>
|
||||
#include <OpenImageIO/thread.h>
|
||||
|
||||
|
||||
|
||||
@@ -26,107 +26,107 @@ OSL_GCC_PRAGMA(GCC diagnostic ignored "-Wunused-parameter")
|
||||
///
|
||||
class OSOReader {
|
||||
public:
|
||||
OSOReader (ErrorHandler *errhandler = NULL)
|
||||
: m_err (errhandler ? *errhandler : ErrorHandler::default_handler()),
|
||||
m_lineno(1)
|
||||
{ }
|
||||
virtual ~OSOReader () { }
|
||||
OSOReader(ErrorHandler* errhandler = NULL)
|
||||
: m_err(errhandler ? *errhandler : ErrorHandler::default_handler())
|
||||
, m_lineno(1)
|
||||
{
|
||||
}
|
||||
virtual ~OSOReader() {}
|
||||
|
||||
/// Read in the oso file, parse it, call the various callbacks.
|
||||
/// Return true if the file was correctly parsed, false if there was
|
||||
/// an unrecoverable error reading the file.
|
||||
virtual bool parse_file (const std::string &filename);
|
||||
virtual bool parse_file(const std::string& filename);
|
||||
|
||||
/// Read in OSO from memory, parse, call the various callbacks.
|
||||
/// Return true if the OSO code was correctly parsed, false if there was
|
||||
/// an unrecoverable error reading.
|
||||
virtual bool parse_memory (const std::string &buffer);
|
||||
virtual bool parse_memory(const std::string& buffer);
|
||||
|
||||
/// Declare the shader version.
|
||||
///
|
||||
virtual void version (const char *specid, int major, int minor) { }
|
||||
virtual void version(const char* specid, int major, int minor) {}
|
||||
|
||||
/// Set the name and type of the shader
|
||||
///
|
||||
virtual void shader (const char *shadertype, const char *name) { }
|
||||
virtual void shader(const char* shadertype, const char* name) {}
|
||||
|
||||
/// Register a new symbol.
|
||||
///
|
||||
virtual void symbol (SymType symtype, TypeSpec typespec, const char *name)
|
||||
{ }
|
||||
virtual void symbol(SymType symtype, TypeSpec typespec, const char* name) {}
|
||||
|
||||
/// Add a default integer value to the last declared symbol.
|
||||
///
|
||||
virtual void symdefault (int def) { }
|
||||
virtual void symdefault(int def) {}
|
||||
|
||||
/// Add a default float value to the last declared symbol.
|
||||
///
|
||||
virtual void symdefault (float def) { }
|
||||
virtual void symdefault(float def) {}
|
||||
|
||||
/// Add a default string value to the last declared symbol.
|
||||
///
|
||||
virtual void symdefault (const char *def) { }
|
||||
virtual void symdefault(const char* def) {}
|
||||
|
||||
/// Called when we're done with all information related to a parameter
|
||||
/// symbol.
|
||||
virtual void parameter_done () { }
|
||||
virtual void parameter_done() {}
|
||||
|
||||
/// Return true for parsers whose only purpose is to read the header up
|
||||
/// to params, to stop parsing as soon as we start encountering temps in
|
||||
/// the symbol table.
|
||||
virtual bool stop_parsing_at_temp_symbols () { return false; }
|
||||
virtual bool stop_parsing_at_temp_symbols() { return false; }
|
||||
|
||||
/// Add a hint.
|
||||
///
|
||||
virtual void hint (string_view hintstring) { }
|
||||
virtual void hint(string_view hintstring) {}
|
||||
|
||||
/// Return true if this parser cares about the code, false if parsing
|
||||
/// of oso may terminate once the symbol table has been parsed.
|
||||
virtual bool parse_code_section () { return true; }
|
||||
virtual bool parse_code_section() { return true; }
|
||||
|
||||
/// New code section marker designating subsequent instructions.
|
||||
///
|
||||
virtual void codemarker (const char *name) { }
|
||||
virtual void codemarker(const char* name) {}
|
||||
|
||||
/// Mark the end of the code section
|
||||
///
|
||||
virtual void codeend () { }
|
||||
virtual void codeend() {}
|
||||
|
||||
/// Add an instruction.
|
||||
///
|
||||
virtual void instruction (int label, const char *opcode) { }
|
||||
virtual void instruction(int label, const char* opcode) {}
|
||||
|
||||
/// Add an argument to the last instruction.
|
||||
///
|
||||
virtual void instruction_arg (const char *name) { }
|
||||
virtual void instruction_arg(const char* name) {}
|
||||
|
||||
/// Add a jump target to the last instruction.
|
||||
///
|
||||
virtual void instruction_jump (int target) { }
|
||||
virtual void instruction_jump(int target) {}
|
||||
|
||||
/// Called after an instruction (after args and hints)
|
||||
///
|
||||
virtual void instruction_end () { }
|
||||
virtual void instruction_end() {}
|
||||
|
||||
/// Increment the line number (for error reporting). Should only
|
||||
/// be called by the lexer.
|
||||
void incr_lineno () { ++m_lineno; }
|
||||
void incr_lineno() { ++m_lineno; }
|
||||
|
||||
/// Return the line number (for error reporting). Should only
|
||||
/// be called by the lexer.
|
||||
int lineno () const { return m_lineno; }
|
||||
int lineno() const { return m_lineno; }
|
||||
|
||||
/// Return a reference to the error handler
|
||||
ErrorHandler& errhandler () { return m_err; }
|
||||
ErrorHandler& errhandler() { return m_err; }
|
||||
|
||||
/// Store and retrieve the current typespec
|
||||
///
|
||||
void current_typespec (TypeSpec t) { m_current_typespec = std::move(t); }
|
||||
TypeSpec current_typespec () const { return m_current_typespec; }
|
||||
void current_typespec(TypeSpec t) { m_current_typespec = std::move(t); }
|
||||
TypeSpec current_typespec() const { return m_current_typespec; }
|
||||
|
||||
private:
|
||||
class Scope;
|
||||
ErrorHandler &m_err;
|
||||
ErrorHandler& m_err;
|
||||
int m_lineno;
|
||||
TypeSpec m_current_typespec;
|
||||
};
|
||||
@@ -134,5 +134,5 @@ private:
|
||||
OSL_PRAGMA_WARNING_POP
|
||||
|
||||
|
||||
}; // namespace pvt
|
||||
}; // namespace pvt
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
@@ -255,7 +255,7 @@ RendererServices::pointcloud_get(ShaderGlobals* sg, ustring filename,
|
||||
// Actual data query
|
||||
if (partio_type == TypeString) {
|
||||
// strings are special cases because they are stored as int index
|
||||
int* strindices = OIIO_ALLOCA(int, count);
|
||||
int* strindices = OSL_ALLOCA(int, count);
|
||||
const_cast<Partio::ParticlesData*>(cloud)->data(
|
||||
*attr, count, (const Partio::ParticleIndex*)indices,
|
||||
/*sorted=*/false, (void*)strindices);
|
||||
@@ -385,7 +385,7 @@ osl_pointcloud_search(ShaderGlobals* sg, const char* filename, void* center,
|
||||
if (sizeof(int) == sizeof(size_t) && out_indices)
|
||||
indices = (size_t*)out_indices;
|
||||
else
|
||||
indices = OIIO_ALLOCA(size_t, max_points);
|
||||
indices = OSL_ALLOCA(size_t, max_points);
|
||||
|
||||
int count
|
||||
= sg->renderer->pointcloud_search(sg, USTR(filename), *((Vec3*)center),
|
||||
@@ -425,7 +425,7 @@ osl_pointcloud_get(ShaderGlobals* sg, const char* filename, void* in_indices,
|
||||
if (shadingsys.no_pointcloud()) // Debug mode to skip pointcloud expense
|
||||
return 0;
|
||||
|
||||
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] = ((int*)in_indices)[i];
|
||||
|
||||
|
||||
+40
-33
@@ -3,9 +3,9 @@
|
||||
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
#ifdef USE_PARTIO
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <Partio.h>
|
||||
# include <Partio.h>
|
||||
# include <memory>
|
||||
# include <unordered_map>
|
||||
#endif
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
@@ -17,41 +17,54 @@ namespace pvt {
|
||||
|
||||
class PointCloud {
|
||||
public:
|
||||
PointCloud (ustring filename, Partio::ParticlesDataMutable *partio_cloud, bool write);
|
||||
~PointCloud ();
|
||||
static PointCloud *get (ustring filename, bool write = false);
|
||||
PointCloud(ustring filename, Partio::ParticlesDataMutable* partio_cloud,
|
||||
bool write);
|
||||
~PointCloud();
|
||||
static PointCloud* get(ustring filename, bool write = false);
|
||||
|
||||
typedef std::unordered_map<ustring, std::unique_ptr<Partio::ParticleAttribute>, ustringHash> AttributeMap;
|
||||
typedef std::unordered_map<
|
||||
ustring, std::unique_ptr<Partio::ParticleAttribute>, ustringHash>
|
||||
AttributeMap;
|
||||
|
||||
const Partio::ParticlesData* read_access() const { OSL_DASSERT(!m_write); return m_partio_cloud; }
|
||||
Partio::ParticlesDataMutable* write_access() const { OSL_DASSERT(m_write); return m_partio_cloud; }
|
||||
const Partio::ParticlesData* read_access() const
|
||||
{
|
||||
OSL_DASSERT(!m_write);
|
||||
return m_partio_cloud;
|
||||
}
|
||||
Partio::ParticlesDataMutable* write_access() const
|
||||
{
|
||||
OSL_DASSERT(m_write);
|
||||
return m_partio_cloud;
|
||||
}
|
||||
|
||||
ustring m_filename;
|
||||
|
||||
private:
|
||||
// hide just this field, because we want to control how it is accessed
|
||||
Partio::ParticlesDataMutable *m_partio_cloud;
|
||||
public:
|
||||
Partio::ParticlesDataMutable* m_partio_cloud;
|
||||
|
||||
public:
|
||||
AttributeMap m_attributes;
|
||||
bool m_write;
|
||||
Partio::ParticleAttribute m_position_attribute;
|
||||
OIIO::spin_mutex m_mutex;
|
||||
};
|
||||
|
||||
namespace { // anon
|
||||
namespace { // anon
|
||||
|
||||
static ustring u_position ("position");
|
||||
static ustring u_position("position");
|
||||
|
||||
// some helper classes to make the sort easy
|
||||
typedef std::pair<float,int> SortedPointRecord; // dist,index
|
||||
typedef std::pair<float, int> SortedPointRecord; // dist,index
|
||||
struct SortedPointCompare {
|
||||
bool operator() (const SortedPointRecord &a, const SortedPointRecord &b) {
|
||||
bool operator()(const SortedPointRecord& a, const SortedPointRecord& b)
|
||||
{
|
||||
return a.first < b.first;
|
||||
}
|
||||
};
|
||||
|
||||
inline Partio::ParticleAttributeType
|
||||
PartioType (TypeDesc t)
|
||||
PartioType(TypeDesc t)
|
||||
{
|
||||
if (t == TypeDesc::TypeFloat)
|
||||
return Partio::FLOAT;
|
||||
@@ -68,7 +81,7 @@ PartioType (TypeDesc t)
|
||||
|
||||
// Helper: number of base values
|
||||
inline int
|
||||
basevals (TypeDesc t)
|
||||
basevals(TypeDesc t)
|
||||
{
|
||||
return t.numelements() * int(t.aggregate);
|
||||
}
|
||||
@@ -76,16 +89,16 @@ basevals (TypeDesc t)
|
||||
|
||||
|
||||
bool
|
||||
compatiblePartioType (TypeDesc partio_type, TypeDesc osl_element_type)
|
||||
compatiblePartioType(TypeDesc partio_type, TypeDesc osl_element_type)
|
||||
{
|
||||
// Matching types (treating all VEC3 aggregates as equivalent)...
|
||||
if (equivalent (partio_type, osl_element_type))
|
||||
if (equivalent(partio_type, osl_element_type))
|
||||
return true;
|
||||
|
||||
// Consider arrays and aggregates as interchangeable, as long as the
|
||||
// totals are the same.
|
||||
if (partio_type.basetype == osl_element_type.basetype &&
|
||||
basevals(partio_type) == basevals(osl_element_type))
|
||||
if (partio_type.basetype == osl_element_type.basetype
|
||||
&& basevals(partio_type) == basevals(osl_element_type))
|
||||
return true;
|
||||
|
||||
// The Partio file may contain an array size that OSL can't exactly
|
||||
@@ -102,7 +115,7 @@ compatiblePartioType (TypeDesc partio_type, TypeDesc osl_element_type)
|
||||
|
||||
|
||||
TypeDesc
|
||||
TypeDescOfPartioType (const Partio::ParticleAttribute *ptype)
|
||||
TypeDescOfPartioType(const Partio::ParticleAttribute* ptype)
|
||||
{
|
||||
TypeDesc type; // default to UNKNOWN
|
||||
switch (ptype->type) {
|
||||
@@ -117,25 +130,19 @@ TypeDescOfPartioType (const Partio::ParticleAttribute *ptype)
|
||||
type.arraylen = ptype->count;
|
||||
break;
|
||||
case Partio::VECTOR:
|
||||
type = TypeDesc (TypeDesc::FLOAT, TypeDesc::VEC3, TypeDesc::NOSEMANTICS);
|
||||
type = TypeDesc(TypeDesc::FLOAT, TypeDesc::VEC3, TypeDesc::NOSEMANTICS);
|
||||
if (ptype->count != 3)
|
||||
type = TypeDesc::UNKNOWN; // Must be 3: punt
|
||||
break;
|
||||
case Partio::INDEXEDSTR:
|
||||
type = TypeDesc::STRING;
|
||||
break;
|
||||
default:
|
||||
break; // Any other future types -- return UNKNOWN
|
||||
case Partio::INDEXEDSTR: type = TypeDesc::STRING; break;
|
||||
default: break; // Any other future types -- return UNKNOWN
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
} // anon namespace
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace pvt
|
||||
} // namespace pvt
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
|
||||
|
||||
|
||||
+1232
-1129
File diff suppressed because it is too large
Load Diff
+195
-162
@@ -4,9 +4,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/container/flat_map.hpp>
|
||||
#include <boost/container/flat_set.hpp>
|
||||
@@ -19,13 +19,13 @@ using namespace OSL::pvt;
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
namespace pvt { // OSL::pvt
|
||||
namespace pvt { // OSL::pvt
|
||||
|
||||
#if USE_FLAT_MAP
|
||||
typedef boost::container::flat_map<int,int> FastIntMap;
|
||||
typedef boost::container::flat_map<int, int> FastIntMap;
|
||||
typedef boost::container::flat_set<int> FastIntSet;
|
||||
#else
|
||||
typedef std::map<int,int> FastIntMap;
|
||||
typedef std::map<int, int> FastIntMap;
|
||||
typedef std::set<int> FastIntSet;
|
||||
#endif
|
||||
|
||||
@@ -34,185 +34,204 @@ typedef std::set<int> FastIntSet;
|
||||
/// OSOProcessor that does runtime optimization on shaders.
|
||||
class RuntimeOptimizer final : public OSOProcessorBase {
|
||||
public:
|
||||
RuntimeOptimizer (ShadingSystemImpl &shadingsys, ShaderGroup &group,
|
||||
ShadingContext *context);
|
||||
RuntimeOptimizer(ShadingSystemImpl& shadingsys, ShaderGroup& group,
|
||||
ShadingContext* context);
|
||||
|
||||
virtual ~RuntimeOptimizer ();
|
||||
virtual ~RuntimeOptimizer();
|
||||
|
||||
virtual void run ();
|
||||
virtual void run();
|
||||
|
||||
virtual void set_inst (int layer);
|
||||
virtual void set_inst(int layer);
|
||||
|
||||
virtual void set_debug ();
|
||||
virtual void set_debug();
|
||||
|
||||
/// Optionally set which ray types are known to be on or off (0 means
|
||||
/// not known at optimize time).
|
||||
void set_raytypes (int raytypes_on, int raytypes_off) {
|
||||
void set_raytypes(int raytypes_on, int raytypes_off)
|
||||
{
|
||||
m_raytypes_on = raytypes_on;
|
||||
m_raytypes_off = raytypes_off;
|
||||
}
|
||||
int raytypes_on () const { return m_raytypes_on; }
|
||||
int raytypes_off () const { return m_raytypes_off; }
|
||||
int raytypes_on() const { return m_raytypes_on; }
|
||||
int raytypes_off() const { return m_raytypes_off; }
|
||||
|
||||
/// Optimize one layer of a group, given what we know about its
|
||||
/// instance variables and connections.
|
||||
void optimize_instance ();
|
||||
void optimize_instance();
|
||||
|
||||
/// One optimization pass over a range of instructions [begin, end).
|
||||
/// Return the number of changes made. If seed_block_aliases is not
|
||||
/// NULL, use that as the initial set of block_aliases.
|
||||
int optimize_ops (int beginop, int endop,
|
||||
FastIntMap *seed_block_aliases = NULL);
|
||||
int optimize_ops(int beginop, int endop,
|
||||
FastIntMap* seed_block_aliases = NULL);
|
||||
|
||||
/// Post-optimization cleanup of a layer: add 'useparam' instructions,
|
||||
/// track variable lifetimes, coalesce temporaries.
|
||||
void post_optimize_instance ();
|
||||
void post_optimize_instance();
|
||||
|
||||
/// What's our current optimization level?
|
||||
int optimize() const { return m_optimize; }
|
||||
|
||||
/// Search the instance for a constant whose type and value match
|
||||
/// type and data[...]. Return -1 if no matching const is found.
|
||||
int find_constant (const TypeSpec &type, const void *data);
|
||||
int find_constant(const TypeSpec& type, const void* data);
|
||||
|
||||
/// Search for a constant whose type and value match type and data[...],
|
||||
/// returning its index if one exists, or else creating a new constant
|
||||
/// and returning its index.
|
||||
int add_constant (const TypeSpec &type, const void *data,
|
||||
TypeDesc datatype=TypeDesc::UNKNOWN);
|
||||
int add_constant (float c) { return add_constant(TypeDesc::TypeFloat, &c); }
|
||||
int add_constant (int c) { return add_constant(TypeDesc::TypeInt, &c); }
|
||||
int add_constant (ustring s) { return add_constant(TypeDesc::TypeString, &s); }
|
||||
int add_constant (const Matrix44 &c) { return add_constant(TypeDesc::TypeMatrix, &c); }
|
||||
int add_constantc (const Color3 &c) { return add_constant(TypeDesc::TypeColor, &c); }
|
||||
int add_constantv (const Vec3 &c, const TypeSpec& vectype) {
|
||||
int add_constant(const TypeSpec& type, const void* data,
|
||||
TypeDesc datatype = TypeDesc::UNKNOWN);
|
||||
int add_constant(float c) { return add_constant(TypeDesc::TypeFloat, &c); }
|
||||
int add_constant(int c) { return add_constant(TypeDesc::TypeInt, &c); }
|
||||
int add_constant(ustring s)
|
||||
{
|
||||
return add_constant(TypeDesc::TypeString, &s);
|
||||
}
|
||||
int add_constant(const Matrix44& c)
|
||||
{
|
||||
return add_constant(TypeDesc::TypeMatrix, &c);
|
||||
}
|
||||
int add_constantc(const Color3& c)
|
||||
{
|
||||
return add_constant(TypeDesc::TypeColor, &c);
|
||||
}
|
||||
int add_constantv(const Vec3& c, const TypeSpec& vectype)
|
||||
{
|
||||
return add_constant(vectype, &c);
|
||||
}
|
||||
int add_constant (string_view s) {
|
||||
int add_constant(string_view s)
|
||||
{
|
||||
ustring u(s);
|
||||
return add_constant(TypeDesc::TypeString, &s);
|
||||
}
|
||||
|
||||
/// Create a new temporary variable of the given type, return its index.
|
||||
int add_temp (const TypeSpec &type);
|
||||
int add_temp(const TypeSpec& type);
|
||||
|
||||
/// Search for the given global, adding it to the symbol table if
|
||||
/// necessary, and returning its index.
|
||||
int add_global (ustring name, const TypeSpec &type);
|
||||
int add_global(ustring name, const TypeSpec& type);
|
||||
|
||||
/// Add a new symbol to the current instance's symbol list. Don't push
|
||||
/// onto the symbol table yourself during optimization; this does some
|
||||
/// other essential housekeeping.
|
||||
int add_symbol (const Symbol &sym);
|
||||
int add_symbol(const Symbol& sym);
|
||||
|
||||
/// Turn the op into a simple assignment of the new symbol index to the
|
||||
/// previous first argument of the op. That is, changes "OP arg0 arg1..."
|
||||
/// into "assign arg0 newarg".
|
||||
void turn_into_assign (Opcode &op, int newarg, string_view why=NULL);
|
||||
void turn_into_assign(Opcode& op, int newarg, string_view why = NULL);
|
||||
|
||||
/// Turn the op into a simple assignment of zero to the previous
|
||||
/// first argument of the op. That is, changes "OP arg0 arg1 ..."
|
||||
/// into "assign arg0 zero".
|
||||
void turn_into_assign_zero (Opcode &op, string_view why=NULL);
|
||||
void turn_into_assign_zero(Opcode& op, string_view why = NULL);
|
||||
|
||||
/// Turn the op into a simple assignment of one to the previous
|
||||
/// first argument of the op. That is, changes "OP arg0 arg1 ..."
|
||||
/// into "assign arg0 one".
|
||||
void turn_into_assign_one (Opcode &op, string_view why=NULL);
|
||||
void turn_into_assign_one(Opcode& op, string_view why = NULL);
|
||||
|
||||
/// Turn the op into a new simple unary or binary op with arguments
|
||||
/// newarg0 (the result, newarg1, and newarg2. If newarg2 < 0, then
|
||||
/// it's a unary op, otherwise a binary op. The original arg list must
|
||||
/// have at least as many operands as the new one, since no new arg
|
||||
/// space is allocated.
|
||||
void turn_into_new_op (Opcode &op, ustring newop, int newarg0,
|
||||
int newarg1, int newarg2, string_view why=NULL);
|
||||
void turn_into_new_op(Opcode& op, ustring newop, int newarg0, int newarg1,
|
||||
int newarg2, string_view why = NULL);
|
||||
|
||||
/// Turn the op into a no-op. Return 1 if it changed, 0 if it was
|
||||
/// already a nop.
|
||||
int turn_into_nop (Opcode &op, string_view why=NULL);
|
||||
int turn_into_nop(Opcode& op, string_view why = NULL);
|
||||
|
||||
/// Turn the whole range [begin,end) into no-ops. Return the number
|
||||
/// of instructions that were altered.
|
||||
int turn_into_nop (int begin, int end, string_view why=NULL);
|
||||
int turn_into_nop(int begin, int end, string_view why = NULL);
|
||||
|
||||
|
||||
/// Transmute regular function call into a 'no return' function call
|
||||
/// The funcationcall_nr is useful to generate debug info for the inlined
|
||||
/// function call. Its existence shouldn't otherwise modify resulting
|
||||
/// code generation.
|
||||
int turn_into_functioncall_nr (Opcode &op, string_view why=nullptr);
|
||||
int turn_into_functioncall_nr(Opcode& op, string_view why = nullptr);
|
||||
|
||||
void debug_opt_impl (string_view message) const;
|
||||
void debug_opt_impl(string_view message) const;
|
||||
|
||||
template<typename... Args>
|
||||
inline void debug_optf (const char* fmt, const Args&... args) const {
|
||||
debug_opt_impl (OIIO::Strutil::sprintf (fmt, args...));
|
||||
inline void debug_optf(const char* fmt, const Args&... args) const
|
||||
{
|
||||
debug_opt_impl(OIIO::Strutil::sprintf(fmt, args...));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
inline void debug_optfmt (const char* fmt, const Args&... args) const {
|
||||
debug_opt_impl (OIIO::Strutil::fmt::format(fmt, args...));
|
||||
inline void debug_optfmt(const char* fmt, const Args&... args) const
|
||||
{
|
||||
debug_opt_impl(OIIO::Strutil::fmt::format(fmt, args...));
|
||||
}
|
||||
|
||||
void debug_opt_ops (int opbegin, int opend, string_view message) const;
|
||||
void debug_turn_into (const Opcode &op, int numops,
|
||||
string_view newop, int newarg0,
|
||||
int newarg1, int newarg2, string_view why);
|
||||
void debug_opt_ops(int opbegin, int opend, string_view message) const;
|
||||
void debug_turn_into(const Opcode& op, int numops, string_view newop,
|
||||
int newarg0, int newarg1, int newarg2,
|
||||
string_view why);
|
||||
|
||||
void simplify_params ();
|
||||
void simplify_params();
|
||||
|
||||
void find_params_holding_globals ();
|
||||
void find_params_holding_globals();
|
||||
|
||||
bool coerce_assigned_constant (Opcode &op);
|
||||
bool coerce_assigned_constant(Opcode& op);
|
||||
|
||||
void make_param_use_instanceval (Symbol *R, string_view why=NULL);
|
||||
void make_param_use_instanceval(Symbol* R, string_view why = NULL);
|
||||
|
||||
/// Return the index of the symbol ultimately de-aliases to (it may be
|
||||
/// itself, if it doesn't alias to anything else). Local block aliases
|
||||
/// are considered higher precedent than global aliases.
|
||||
int dealias_symbol (int symindex, int opnum=-1);
|
||||
int dealias_symbol(int symindex, int opnum = -1);
|
||||
|
||||
/// Return the index of the symbol that 'symindex' aliases to, locally,
|
||||
/// or -1 if it has no block-local alias.
|
||||
int block_alias (int symindex) const {
|
||||
FastIntMap::const_iterator i = m_block_aliases.find (symindex);
|
||||
int block_alias(int symindex) const
|
||||
{
|
||||
FastIntMap::const_iterator i = m_block_aliases.find(symindex);
|
||||
return (i == m_block_aliases.end()) ? -1 : i->second;
|
||||
}
|
||||
|
||||
/// Set the new block-local alias of 'symindex' to 'alias'.
|
||||
///
|
||||
void block_alias (int symindex, int alias) {
|
||||
void block_alias(int symindex, int alias)
|
||||
{
|
||||
m_block_aliases[symindex] = alias;
|
||||
}
|
||||
|
||||
/// Reset the block-local alias of 'symindex' so it doesn't alias to
|
||||
/// anything. Also will unalias from any saved alias lists on the
|
||||
/// m_block_aliases_stack.
|
||||
void block_unalias (int symindex);
|
||||
void block_unalias(int symindex);
|
||||
|
||||
/// Clear local block aliases for any args that are written by this op.
|
||||
void block_unalias_written_args (Opcode &op) {
|
||||
for (int i = 0, e = op.nargs(); i < e; ++i)
|
||||
void block_unalias_written_args(Opcode& op)
|
||||
{
|
||||
for (int i = 0, e = op.nargs(); i < e; ++i)
|
||||
if (op.argwrite(i))
|
||||
block_unalias (inst()->arg(op.firstarg()+i));
|
||||
block_unalias(inst()->arg(op.firstarg() + i));
|
||||
}
|
||||
|
||||
/// Reset all block-local aliases (done when we enter a new basic
|
||||
/// block). If new_block_aliases is non-NULL, copy its contents to the
|
||||
/// current block aliases.
|
||||
void clear_block_aliases (FastIntMap *new_block_aliases=NULL) {
|
||||
void clear_block_aliases(FastIntMap* new_block_aliases = NULL)
|
||||
{
|
||||
if (new_block_aliases) {
|
||||
if (new_block_aliases != &m_block_aliases)
|
||||
m_block_aliases = *new_block_aliases;
|
||||
} else {
|
||||
m_block_aliases.clear ();
|
||||
m_block_aliases.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the new global alias of 'symindex' to 'alias'.
|
||||
///
|
||||
void global_alias (int symindex, int alias) {
|
||||
void global_alias(int symindex, int alias)
|
||||
{
|
||||
m_symbol_aliases[symindex] = alias;
|
||||
}
|
||||
|
||||
@@ -221,48 +240,53 @@ public:
|
||||
/// (by a single op with no other side effects), but not yet used.
|
||||
/// The point is that if they are simply assigned again before being
|
||||
/// used, that first assignment can be turned into a no-op.
|
||||
bool sym_is_stale (int sym) {
|
||||
bool sym_is_stale(int sym)
|
||||
{
|
||||
return m_stale_syms.find(sym) != m_stale_syms.end();
|
||||
}
|
||||
|
||||
/// Clear the stale symbol list -- we do this when entering a new
|
||||
/// basic block.
|
||||
void clear_stale_syms ();
|
||||
void clear_stale_syms();
|
||||
|
||||
/// Take a symbol out of the stale list -- we do this when a symbol
|
||||
/// is used in any way.
|
||||
void use_stale_sym (int sym);
|
||||
void use_stale_sym(int sym);
|
||||
|
||||
/// Is the op a "simple" assignment (arg 0 completely overwritten,
|
||||
/// no side effects or funny business)?
|
||||
/// Optional OpDescriptor is passed to save an extra lookup.
|
||||
bool is_simple_assign (Opcode &op, const OpDescriptor *opd=NULL);
|
||||
bool is_simple_assign(Opcode& op, const OpDescriptor* opd = NULL);
|
||||
|
||||
/// Called when symbol sym is "simply" assigned at the given op. An
|
||||
/// assignment is considered simple if it completely overwrites the
|
||||
/// symbol in a single op and has no side effects. When this
|
||||
/// happens, we mark the symbol as "stale", meaning it's got a value
|
||||
/// that hasn't been read yet. If it's wholy assigned again before
|
||||
/// that hasn't been read yet. If it's wholly assigned again before
|
||||
/// it's read, we can go back and remove the earlier assignment.
|
||||
void simple_sym_assign (int sym, int op);
|
||||
void simple_sym_assign(int sym, int op);
|
||||
|
||||
/// Return true if assignments to A on this op have no effect because
|
||||
/// they will not be subsequently used.
|
||||
bool unread_after (const Symbol *A, int opnum);
|
||||
bool unread_after(const Symbol* A, int opnum);
|
||||
|
||||
/// Replace R's instance value with new data.
|
||||
///
|
||||
void replace_param_value (Symbol *R, const void *newdata,
|
||||
const TypeSpec &newdata_type);
|
||||
void replace_param_value(Symbol* R, const void* newdata,
|
||||
const TypeSpec& newdata_type);
|
||||
|
||||
bool outparam_assign_elision (int opnum, Opcode &op);
|
||||
bool outparam_assign_elision(int opnum, Opcode& op);
|
||||
|
||||
bool useless_op_elision (Opcode &op, int opnum);
|
||||
bool useless_op_elision(Opcode& op, int opnum);
|
||||
|
||||
void make_symbol_room (int howmany=1);
|
||||
void make_symbol_room(int howmany = 1);
|
||||
|
||||
enum RecomputeRWRangesOption { DontRecomputeRWRanges, RecomputeRWRanges };
|
||||
enum InsertRelation { NoRelation=0, GroupWithPrevious=-1, GroupWithNext=1 };
|
||||
enum InsertRelation {
|
||||
NoRelation = 0,
|
||||
GroupWithPrevious = -1,
|
||||
GroupWithNext = 1
|
||||
};
|
||||
/// Insert instruction 'opname' with arguments 'args_to_add' into
|
||||
/// the code at instruction 'opnum'. The existing code and
|
||||
/// concatenated argument lists can be found in code and opargs,
|
||||
@@ -274,142 +298,148 @@ public:
|
||||
/// take the new instruction into consideration. Relation indicates
|
||||
/// its relation to surrounding instructions: GroupWithPrevious
|
||||
/// means it should have the same method, sourcefile, and sourceline
|
||||
/// as the preceeding instruction; GroupWithNext means it should
|
||||
/// as the preceding instruction; GroupWithNext means it should
|
||||
/// have the same method, sourcefile, and sourceline as the
|
||||
/// subsequent instruction; NoRelation means we have no information,
|
||||
/// so don't copy that info from anywhere.
|
||||
void insert_code (int opnum, ustring opname,
|
||||
const cspan<int> args_to_add,
|
||||
RecomputeRWRangesOption recompute_rw_ranges,
|
||||
InsertRelation relation=GroupWithNext);
|
||||
void insert_code(int opnum, ustring opname, const cspan<int> args_to_add,
|
||||
RecomputeRWRangesOption recompute_rw_ranges,
|
||||
InsertRelation relation = GroupWithNext);
|
||||
/// insert_code with explicit arguments (up to 4, a value of -1 means
|
||||
/// the arg isn't used). Presume recompute_rw_ranges is true.
|
||||
void insert_code (int opnum, ustring opname, InsertRelation relation,
|
||||
int arg0=-1, int arg1=-1, int arg2=-1, int arg3=-1);
|
||||
void insert_code(int opnum, ustring opname, InsertRelation relation,
|
||||
int arg0 = -1, int arg1 = -1, int arg2 = -1,
|
||||
int arg3 = -1);
|
||||
|
||||
void insert_useparam (size_t opnum, const std::vector<int> ¶ms_to_use);
|
||||
void insert_useparam(size_t opnum, const std::vector<int>& params_to_use);
|
||||
|
||||
/// Add a 'useparam' before any op that reads parameters. This is what
|
||||
/// tells the runtime that it needs to run the layer it came from, if
|
||||
/// not already done.
|
||||
void add_useparam (SymbolPtrVec &allsyms);
|
||||
void add_useparam(SymbolPtrVec& allsyms);
|
||||
|
||||
void coalesce_temporaries ();
|
||||
void coalesce_temporaries();
|
||||
|
||||
/// Track variable lifetimes for all the symbols of the instance.
|
||||
///
|
||||
void track_variable_lifetimes ();
|
||||
void track_variable_lifetimes (const SymbolPtrVec &allsymptrs);
|
||||
void track_variable_lifetimes();
|
||||
void track_variable_lifetimes(const SymbolPtrVec& allsymptrs);
|
||||
|
||||
/// For each symbol, have a list of the symbols it depends on (or that
|
||||
/// depends on it).
|
||||
typedef std::set<int> SymIntSet;
|
||||
typedef std::map<int, SymIntSet> SymDependency;
|
||||
|
||||
void syms_used_in_op (Opcode &op,
|
||||
std::vector<int> &rsyms, std::vector<int> &wsyms);
|
||||
void syms_used_in_op(Opcode& op, std::vector<int>& rsyms,
|
||||
std::vector<int>& wsyms);
|
||||
|
||||
void track_variable_dependencies ();
|
||||
void track_variable_dependencies();
|
||||
|
||||
void add_dependency (SymDependency &dmap, int A, int B);
|
||||
void add_dependency(SymDependency& dmap, int A, int B);
|
||||
|
||||
void mark_symbol_derivatives (SymDependency &symdeps, SymIntSet &visited, int d);
|
||||
void mark_symbol_derivatives(SymDependency& symdeps, SymIntSet& visited,
|
||||
int d);
|
||||
|
||||
void mark_outgoing_connections ();
|
||||
void mark_outgoing_connections();
|
||||
|
||||
int remove_unused_params ();
|
||||
int remove_unused_params();
|
||||
|
||||
/// Turn isconnected() calls into constant assignments
|
||||
void resolve_isconnected ();
|
||||
void resolve_isconnected();
|
||||
|
||||
int eliminate_middleman ();
|
||||
int eliminate_middleman();
|
||||
|
||||
/// Squeeze out unused symbols from an instance that has been
|
||||
/// optimized.
|
||||
void collapse_syms ();
|
||||
void collapse_syms();
|
||||
|
||||
/// Squeeze out nop instructions from an instance that has been
|
||||
/// optimized.
|
||||
void collapse_ops ();
|
||||
void collapse_ops();
|
||||
|
||||
/// Let the optimizer know that this (known, constant) message was
|
||||
/// set by the current instance.
|
||||
void register_message (ustring name);
|
||||
void register_message(ustring name);
|
||||
|
||||
/// Let the optimizer know that an unknown message (i.e., we
|
||||
/// couldn't reduce the message name to a constant) was set by the
|
||||
/// current instance.
|
||||
void register_unknown_message ();
|
||||
void register_unknown_message();
|
||||
|
||||
/// Is it possible that the message with the given name was set?
|
||||
///
|
||||
bool message_possibly_set (ustring name) const;
|
||||
bool message_possibly_set(ustring name) const;
|
||||
|
||||
/// Return the index of the next instruction within the same basic
|
||||
/// block that isn't a NOP. If there are no more non-NOP
|
||||
/// instructions in the same basic block as opnum, return 0.
|
||||
int next_block_instruction (int opnum);
|
||||
int next_block_instruction(int opnum);
|
||||
|
||||
/// Perform peephole optimization on pairs of adjacent instructions
|
||||
/// within the same basic block.
|
||||
int peephole2 (int opnum, int op2num);
|
||||
int peephole2(int opnum, int op2num);
|
||||
|
||||
/// Perform various optimizations specific to assignments.
|
||||
int optimize_assignment (Opcode &op, int opnum);
|
||||
int optimize_assignment(Opcode& op, int opnum);
|
||||
|
||||
bool opt_elide_unconnected_outputs () const {
|
||||
bool opt_elide_unconnected_outputs() const
|
||||
{
|
||||
return m_opt_elide_unconnected_outputs;
|
||||
}
|
||||
|
||||
/// Are special optimizations to 'mix' requested?
|
||||
bool opt_mix () const { return m_opt_mix; }
|
||||
bool opt_mix() const { return m_opt_mix; }
|
||||
|
||||
/// Should no return function calls be kept in order to
|
||||
/// generate correct inline function debug info
|
||||
bool keep_no_return_function_calls() const { return m_keep_no_return_function_calls; }
|
||||
bool keep_no_return_function_calls() const
|
||||
{
|
||||
return m_keep_no_return_function_calls;
|
||||
}
|
||||
|
||||
/// Which optimization pass are we on?
|
||||
int optimization_pass () const { return m_pass; }
|
||||
int optimization_pass() const { return m_pass; }
|
||||
|
||||
/// Retrieve ptr to the dummy shader globals
|
||||
ShaderGlobals *shaderglobals () { return &m_shaderglobals; }
|
||||
ShaderGlobals* shaderglobals() { return &m_shaderglobals; }
|
||||
|
||||
// Maximum number of new constant symbols that a constant-folding
|
||||
// function is able to add.
|
||||
static const int max_new_consts_per_fold = 10;
|
||||
|
||||
void stop_optimizing () { m_stop_optimizing = true; }
|
||||
void stop_optimizing() { m_stop_optimizing = true; }
|
||||
|
||||
std::string op_string (const Opcode &op) {
|
||||
std::string op_string(const Opcode& op)
|
||||
{
|
||||
std::string s = op.opname().string();
|
||||
for (int a = 0; a < op.nargs(); ++a)
|
||||
s = s + ' ' + opargsym(op,a)->name().string();
|
||||
for (int a = 0; a < op.nargs(); ++a)
|
||||
s = s + ' ' + opargsym(op, a)->name().string();
|
||||
return s;
|
||||
}
|
||||
|
||||
std::ostream & printinst (std::ostream &out) const;
|
||||
std::ostream& printinst(std::ostream& out) const;
|
||||
|
||||
/// Add to syms the indices of all symbols that may be written by
|
||||
/// instructions in the half-closed range [opbegin, opend).
|
||||
void catalog_symbol_writes (int opbegin, int opend, FastIntSet &syms);
|
||||
void catalog_symbol_writes(int opbegin, int opend, FastIntSet& syms);
|
||||
|
||||
/// Copy block_aliases from old to new, except any aliases involving
|
||||
/// symbols in the excluded list (which may be NULL if there no
|
||||
/// exclusions). If copy_temps is false, aliases involving temp symbols
|
||||
/// will not be copied.
|
||||
void copy_block_aliases (const FastIntMap &old_block_aliases,
|
||||
FastIntMap &new_block_aliases,
|
||||
const FastIntSet *excluded=NULL,
|
||||
bool copy_temps=false);
|
||||
void copy_block_aliases(const FastIntMap& old_block_aliases,
|
||||
FastIntMap& new_block_aliases,
|
||||
const FastIntSet* excluded = NULL,
|
||||
bool copy_temps = false);
|
||||
|
||||
// Check for any error() calls, mark has_error_op if found and if
|
||||
// lazyerrors == 0. If `warn` is true, presumably only after
|
||||
// optimization is finished, warn if any error messages are left.
|
||||
bool check_for_error_calls (bool warn = false);
|
||||
bool check_for_error_calls(bool warn = false);
|
||||
|
||||
/// After optimization, check for things that should not be left
|
||||
/// unoptimized.
|
||||
bool police_failed_optimizations ();
|
||||
bool police_failed_optimizations();
|
||||
enum { // bit field
|
||||
police_opt_warn = 1,
|
||||
police_gpu_err_only = 2,
|
||||
@@ -422,67 +452,70 @@ public:
|
||||
bool police_(int type, const Opcode& op, string_view msg);
|
||||
|
||||
template<typename Str, typename... Args>
|
||||
bool police(int type, const Opcode& op, const Str& fmt, Args&&... args) {
|
||||
bool police(int type, const Opcode& op, const Str& fmt, Args&&... args)
|
||||
{
|
||||
return police_(type, op, fmtformat(fmt, std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<typename Str, typename... Args>
|
||||
bool police(const Opcode& op, const Str& fmt, Args&&... args) {
|
||||
bool police(const Opcode& op, const Str& fmt, Args&&... args)
|
||||
{
|
||||
return police_(police_opt_warn, op,
|
||||
fmtformat(fmt, std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
private:
|
||||
int m_optimize; ///< Current optimization level
|
||||
bool m_opt_simplify_param; ///< Turn instance params into const?
|
||||
bool m_opt_constant_fold; ///< Allow constant folding?
|
||||
bool m_opt_stale_assign; ///< Optimize stale assignments?
|
||||
bool m_opt_elide_useless_ops; ///< Optimize away useless ops?
|
||||
bool m_opt_elide_unconnected_outputs; ///< Optimize unconnected outputs?
|
||||
bool m_opt_peephole; ///< Do some peephole optimizations?
|
||||
bool m_opt_coalesce_temps; ///< Coalesce temporary variables?
|
||||
bool m_opt_assign; ///< Do various assign optimizations?
|
||||
bool m_opt_mix; ///< Do mix optimizations?
|
||||
bool m_opt_middleman; ///< Do middleman optimizations?
|
||||
bool m_opt_batched_analysis; ///< Perform extra analysis required for batched execution?
|
||||
bool m_keep_no_return_function_calls; ///< To generate debug info, keep no return function calls
|
||||
ShaderGlobals m_shaderglobals; ///< Dummy ShaderGlobals
|
||||
int m_optimize; ///< Current optimization level
|
||||
bool m_opt_simplify_param; ///< Turn instance params into const?
|
||||
bool m_opt_constant_fold; ///< Allow constant folding?
|
||||
bool m_opt_stale_assign; ///< Optimize stale assignments?
|
||||
bool m_opt_elide_useless_ops; ///< Optimize away useless ops?
|
||||
bool m_opt_elide_unconnected_outputs; ///< Optimize unconnected outputs?
|
||||
bool m_opt_peephole; ///< Do some peephole optimizations?
|
||||
bool m_opt_coalesce_temps; ///< Coalesce temporary variables?
|
||||
bool m_opt_assign; ///< Do various assign optimizations?
|
||||
bool m_opt_mix; ///< Do mix optimizations?
|
||||
bool m_opt_middleman; ///< Do middleman optimizations?
|
||||
bool m_opt_batched_analysis; ///< Perform extra analysis required for batched execution?
|
||||
bool m_keep_no_return_function_calls; ///< To generate debug info, keep no return function calls
|
||||
ShaderGlobals m_shaderglobals; ///< Dummy ShaderGlobals
|
||||
|
||||
// Keep track of some things for the whole shader group:
|
||||
typedef std::unordered_map<ustring,ustring,ustringHash> ustringmap_t;
|
||||
typedef std::unordered_map<ustring, ustring, ustringHash> ustringmap_t;
|
||||
std::vector<ustringmap_t> m_params_holding_globals;
|
||||
///< Which params of each layer really just hold globals
|
||||
///< Which params of each layer really just hold globals
|
||||
|
||||
// All below is just for the one inst we're optimizing at the moment:
|
||||
int m_pass; ///< Optimization pass we're on now
|
||||
std::vector<int> m_all_consts; ///< All const symbol indices for inst
|
||||
int m_next_newconst; ///< Unique ID for next new const we add
|
||||
int m_next_newtemp; ///< Unique ID for next new temp we add
|
||||
FastIntMap m_symbol_aliases; ///< Global symbol aliases
|
||||
FastIntMap m_block_aliases; ///< Local block aliases
|
||||
std::vector<FastIntMap *> m_block_aliases_stack; ///< Stack of saved local block aliases
|
||||
FastIntMap m_param_aliases; ///< Params aliasing to params/globals
|
||||
FastIntMap m_stale_syms; ///< Stale symbols for this block
|
||||
int m_local_unknown_message_sent; ///< Non-const setmessage in this inst
|
||||
std::vector<ustring> m_local_messages_sent; ///< Messages set in this inst
|
||||
int m_pass; ///< Optimization pass we're on now
|
||||
std::vector<int> m_all_consts; ///< All const symbol indices for inst
|
||||
int m_next_newconst; ///< Unique ID for next new const we add
|
||||
int m_next_newtemp; ///< Unique ID for next new temp we add
|
||||
FastIntMap m_symbol_aliases; ///< Global symbol aliases
|
||||
FastIntMap m_block_aliases; ///< Local block aliases
|
||||
std::vector<FastIntMap*>
|
||||
m_block_aliases_stack; ///< Stack of saved local block aliases
|
||||
FastIntMap m_param_aliases; ///< Params aliasing to params/globals
|
||||
FastIntMap m_stale_syms; ///< Stale symbols for this block
|
||||
int m_local_unknown_message_sent; ///< Non-const setmessage in this inst
|
||||
std::vector<ustring> m_local_messages_sent; ///< Messages set in this inst
|
||||
std::set<ustring> m_textures_needed;
|
||||
std::set<ustring> m_closures_needed;
|
||||
std::set<ustring> m_globals_needed;
|
||||
int m_globals_read = 0;
|
||||
int m_globals_read = 0;
|
||||
int m_globals_write = 0;
|
||||
std::set<AttributeNeeded> m_attributes_needed;
|
||||
bool m_unknown_textures_needed;
|
||||
bool m_unknown_closures_needed;
|
||||
bool m_unknown_attributes_needed;
|
||||
std::set<UserDataNeeded> m_userdata_needed;
|
||||
double m_stat_opt_locking_time; ///< locking time
|
||||
double m_stat_specialization_time; ///< specialization time
|
||||
bool m_stop_optimizing; ///< for debugging
|
||||
int m_raytypes_on; ///< Ray types known to be on
|
||||
int m_raytypes_off; ///< Ray types known to be off
|
||||
double m_stat_opt_locking_time; ///< locking time
|
||||
double m_stat_specialization_time; ///< specialization time
|
||||
bool m_stop_optimizing; ///< for debugging
|
||||
int m_raytypes_on; ///< Ray types known to be on
|
||||
int m_raytypes_off; ///< Ray types known to be off
|
||||
|
||||
// Persistant data shared between layers
|
||||
bool m_unknown_message_sent; ///< Somebody did a non-const setmessage
|
||||
// Persistent data shared between layers
|
||||
bool m_unknown_message_sent; ///< Somebody did a non-const setmessage
|
||||
std::vector<ustring> m_messages_sent; ///< Names of messages set
|
||||
|
||||
friend class ShadingSystemImpl;
|
||||
@@ -492,13 +525,13 @@ private:
|
||||
|
||||
/// Macro that defines the arguments to constant-folding routines
|
||||
///
|
||||
#define FOLDARGSDECL RuntimeOptimizer &rop, int opnum
|
||||
#define FOLDARGSDECL RuntimeOptimizer &rop, int opnum
|
||||
|
||||
/// Macro that defines the full declaration of a shadeop constant-folder.
|
||||
///
|
||||
#define DECLFOLDER(name) int name (FOLDARGSDECL)
|
||||
///
|
||||
#define DECLFOLDER(name) int name(FOLDARGSDECL)
|
||||
|
||||
|
||||
|
||||
}; // namespace pvt
|
||||
}; // namespace pvt
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
@@ -66,10 +66,10 @@ shade_image(ShadingSystem& shadingsys, ShaderGroup& group,
|
||||
|
||||
// Gather some information about the outputs once, rather than for
|
||||
// each pixel.
|
||||
const ShaderSymbol** output_sym = OIIO_ALLOCA(const ShaderSymbol*,
|
||||
outputs.size());
|
||||
TypeDesc* output_type = OIIO_ALLOCA(TypeDesc, outputs.size());
|
||||
int* output_nchans = OIIO_ALLOCA(int, outputs.size());
|
||||
const ShaderSymbol** output_sym = OSL_ALLOCA(const ShaderSymbol*,
|
||||
outputs.size());
|
||||
TypeDesc* output_type = OSL_ALLOCA(TypeDesc, outputs.size());
|
||||
int* output_nchans = OSL_ALLOCA(int, outputs.size());
|
||||
for (int i = 0; i < int(outputs.size()); ++i) {
|
||||
output_sym[i] = shadingsys.find_symbol(group, outputs[i]);
|
||||
output_type[i] = shadingsys.symbol_typedesc(output_sym[i]);
|
||||
|
||||
@@ -646,8 +646,8 @@ ShadingSystem::query_closure(const char** name, int* id,
|
||||
|
||||
|
||||
|
||||
static cspan< std::pair<ustring,SGBits> >
|
||||
sgbit_table ()
|
||||
static cspan<std::pair<ustring, SGBits>>
|
||||
sgbit_table()
|
||||
{
|
||||
// clang-format off
|
||||
static const std::pair<ustring,SGBits> table[] = {
|
||||
@@ -666,7 +666,7 @@ sgbit_table ()
|
||||
{ ustring("Ci"), SGBits::Ci }
|
||||
};
|
||||
// clang-format on
|
||||
return cspan<std::pair<ustring,SGBits>>(table);
|
||||
return cspan<std::pair<ustring, SGBits>>(table);
|
||||
}
|
||||
|
||||
|
||||
@@ -1168,7 +1168,8 @@ ShadingSystemImpl::ShadingSystemImpl(RendererServices* renderer,
|
||||
|
||||
|
||||
static void
|
||||
shading_system_setup_op_descriptors (ShadingSystemImpl::OpDescriptorMap& op_descriptor)
|
||||
shading_system_setup_op_descriptors(
|
||||
ShadingSystemImpl::OpDescriptorMap& op_descriptor)
|
||||
{
|
||||
// clang-format off
|
||||
#if OSL_USE_BATCHED
|
||||
@@ -2110,7 +2111,7 @@ ShadingSystemImpl::getattribute(ShaderGroup* group, string_view name,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Additional atttributes useful to OptiX-based renderers
|
||||
// Additional attributes useful to OptiX-based renderers
|
||||
if (name == "userdata_layers" && type.basetype == TypeDesc::PTR) {
|
||||
size_t n = group->m_userdata_layers.size();
|
||||
*(int**)val = n ? &group->m_userdata_layers[0] : NULL;
|
||||
|
||||
@@ -41,6 +41,7 @@ enum {
|
||||
|
||||
|
||||
// clang-format off
|
||||
namespace { // anon namespace to avoid duplicate OptiX symbols
|
||||
OSL_CONSTANT_DATA const static SplineBasis gBasisSet[kNumSplineTypes] = {
|
||||
//
|
||||
// catmullrom
|
||||
@@ -48,7 +49,7 @@ OSL_CONSTANT_DATA const static SplineBasis gBasisSet[kNumSplineTypes] = {
|
||||
{ 1, { {(-1.0f/2.0f), ( 3.0f/2.0f), (-3.0f/2.0f), ( 1.0f/2.0f)},
|
||||
{( 2.0f/2.0f), (-5.0f/2.0f), ( 4.0f/2.0f), (-1.0f/2.0f)},
|
||||
{(-1.0f/2.0f), ( 0.0f/2.0f), ( 1.0f/2.0f), ( 0.0f/2.0f)},
|
||||
{( 0.0f/2.0f), ( 2.0f/2.0f), ( 0.0f/2.0f), ( 0.0f/2.0f)} } },
|
||||
{( 0.0f/2.0f), ( 2.0f/2.0f), ( 0.0f/2.0f), ( 0.0f/2.0f)} } }, // NOSONAR
|
||||
//
|
||||
// bezier
|
||||
//
|
||||
@@ -85,11 +86,13 @@ OSL_CONSTANT_DATA const static SplineBasis gBasisSet[kNumSplineTypes] = {
|
||||
{0, 0, 0, 0},
|
||||
{0, 0, 0, 0} } }
|
||||
};
|
||||
} // namespace
|
||||
// clang-format on
|
||||
|
||||
|
||||
|
||||
OSL_HOSTDEVICE static int basis_type_of(StringParam basis_name)
|
||||
OSL_HOSTDEVICE static int
|
||||
basis_type_of(StringParam basis_name)
|
||||
{
|
||||
if (basis_name == STRING_PARAMS(catmullrom))
|
||||
return kCatmullRom;
|
||||
|
||||
@@ -4,29 +4,30 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <OpenImageIO/oiioversion.h>
|
||||
#include <OpenImageIO/detail/farmhash.h>
|
||||
#include <OpenImageIO/oiioversion.h>
|
||||
|
||||
namespace pvt {
|
||||
|
||||
OIIO_CONSTEXPR14 inline size_t pvtstrlen(const char *s) {
|
||||
OIIO_CONSTEXPR14 inline size_t
|
||||
pvtstrlen(const char* s)
|
||||
{
|
||||
if (s == nullptr)
|
||||
return 0;
|
||||
size_t len = 0;
|
||||
size_t len = 0;
|
||||
while (s[len] != 0)
|
||||
len++;
|
||||
return len;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace pvt
|
||||
|
||||
namespace UStringHash {
|
||||
OIIO_CONSTEXPR14 inline size_t Hash(const char* s)
|
||||
OIIO_CONSTEXPR14 inline size_t
|
||||
Hash(const char* s)
|
||||
{
|
||||
size_t len = pvt::pvtstrlen(s);
|
||||
size_t len = pvt::pvtstrlen(s);
|
||||
|
||||
return len ? OIIO::farmhash::inlined::Hash(s, len)
|
||||
: 0;
|
||||
return len ? OIIO::farmhash::inlined::Hash(s, len) : 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace UStringHash
|
||||
|
||||
@@ -25,15 +25,26 @@ OSL_USING_DATA_WIDTH(__OSL_WIDTH)
|
||||
|
||||
namespace {
|
||||
|
||||
OSL_FORCEINLINE OSL_HOSTDEVICE int
|
||||
bitcast_to_uint(float x)
|
||||
{
|
||||
#if OPENIMAGEIO_VERSION >= 20500
|
||||
return OIIO::bitcast<unsigned int, float>(x);
|
||||
#else
|
||||
// obsolete call
|
||||
return OIIO::bit_cast<float, unsigned int>(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// TODO: to avoid ansi aliasing issues,
|
||||
// suggest replacing inthashf (const float *x) with inthashv
|
||||
inline OSL_HOSTDEVICE int
|
||||
inthashv(const Vec3& v)
|
||||
{
|
||||
return static_cast<int>(
|
||||
pvt::inthash(OIIO::bit_cast<float, unsigned int>(v.x),
|
||||
OIIO::bit_cast<float, unsigned int>(v.y),
|
||||
OIIO::bit_cast<float, unsigned int>(v.z)));
|
||||
return static_cast<int>(pvt::inthash(bitcast_to_uint(v.x),
|
||||
bitcast_to_uint(v.y),
|
||||
bitcast_to_uint(v.z)));
|
||||
}
|
||||
|
||||
|
||||
@@ -43,10 +54,8 @@ inline OSL_HOSTDEVICE int
|
||||
inthashvf(const Vec3& v, float y)
|
||||
{
|
||||
return static_cast<int>(
|
||||
pvt::inthash(OIIO::bit_cast<float, unsigned int>(v.x),
|
||||
OIIO::bit_cast<float, unsigned int>(v.y),
|
||||
OIIO::bit_cast<float, unsigned int>(v.z),
|
||||
OIIO::bit_cast<float, unsigned int>(y)));
|
||||
pvt::inthash(bitcast_to_uint(v.x), bitcast_to_uint(v.y),
|
||||
bitcast_to_uint(v.z), bitcast_to_uint(y)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user