Compare commits
167
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4db549061 | ||
|
|
4debd96adc | ||
|
|
30a4a95b7e | ||
|
|
a38aa58c0e | ||
|
|
e126a20df7 | ||
|
|
52cf2ee418 | ||
|
|
83a1e7e74b | ||
|
|
6069b7cfc0 | ||
|
|
41cc6d78db | ||
|
|
8561a817ea | ||
|
|
cfaf643d0e | ||
|
|
c505c4ca5f | ||
|
|
318f0e488e | ||
|
|
b22c9b7c84 | ||
|
|
bd491d025e | ||
|
|
6140c72aa6 | ||
|
|
7fcdc3f71c | ||
|
|
22feb208c2 | ||
|
|
ab65bbad4b | ||
|
|
64c66949e7 | ||
|
|
2fe18079a3 | ||
|
|
e0a66c7bc6 | ||
|
|
e4e5088ed6 | ||
|
|
aea281dcad | ||
|
|
b5aba16147 | ||
|
|
4ba1678561 | ||
|
|
8417f8eb04 | ||
|
|
55029e388f | ||
|
|
89c033bda9 | ||
|
|
0b57ae6b03 | ||
|
|
6588caafa6 | ||
|
|
b11fb97626 | ||
|
|
7a885c68b6 | ||
|
|
32278d3f77 | ||
|
|
c8dd33f5a3 | ||
|
|
1a7670600c | ||
|
|
a6ff40b0b2 | ||
|
|
54cf8b209c | ||
|
|
2e941e612f | ||
|
|
051f2bfe2f | ||
|
|
f13463e6b6 | ||
|
|
cd2fa1650d | ||
|
|
c23da3df34 | ||
|
|
95c1408d27 | ||
|
|
e278f4c24a | ||
|
|
365f2c4b2b | ||
|
|
ac59af9bd1 | ||
|
|
9d5d6203b9 | ||
|
|
1a66a2b8dd | ||
|
|
3b97ecef47 | ||
|
|
ed5b5a2a0c | ||
|
|
37cbab5bad | ||
|
|
11127b72b5 | ||
|
|
d5d87f1e64 | ||
|
|
fa6f228b87 | ||
|
|
21f1a2f47e | ||
|
|
5be7c6bd4e | ||
|
|
9f8e92ce93 | ||
|
|
4bbaca7fe5 | ||
|
|
cf1b4ef3e6 | ||
|
|
c3e36affa8 | ||
|
|
e9a614ba53 | ||
|
|
d57a462462 | ||
|
|
ac114aded4 | ||
|
|
74fc27de12 | ||
|
|
826b6767c9 | ||
|
|
89d5db2b5c | ||
|
|
1dd33050da | ||
|
|
0879638dda | ||
|
|
8a7b9b96ba | ||
|
|
23ea0644f8 | ||
|
|
bd6d856b0e | ||
|
|
6424177e3a | ||
|
|
0b92d2b03b | ||
|
|
bf04610296 | ||
|
|
ff9560f401 | ||
|
|
e0d6a21438 | ||
|
|
da794de6fd | ||
|
|
a1e941c43b | ||
|
|
3bb41960fd | ||
|
|
95fa78d3fd | ||
|
|
eff3dede3a | ||
|
|
7b4c7cffd7 | ||
|
|
8281721bde | ||
|
|
2ece55aa97 | ||
|
|
88c471a315 | ||
|
|
11afddc8da | ||
|
|
f7cac87979 | ||
|
|
5401e8417b | ||
|
|
c61a85e217 | ||
|
|
08cda36387 | ||
|
|
caa8a2d252 | ||
|
|
21eac9d921 | ||
|
|
d75384da6d | ||
|
|
008907161d | ||
|
|
102430c835 | ||
|
|
ce0e6e1d4f | ||
|
|
8c6ffdd911 | ||
|
|
a5a8f9d745 | ||
|
|
1c715483b4 | ||
|
|
08706b7cba | ||
|
|
c1045f2c28 | ||
|
|
46d451ce74 | ||
|
|
1c57fc61d8 | ||
|
|
e56851056d | ||
|
|
28399fefc8 | ||
|
|
7f2e83794e | ||
|
|
1f73b075c9 | ||
|
|
b4026fd169 | ||
|
|
efeb577933 | ||
|
|
fdd8ff04a3 | ||
|
|
89cc2374c7 | ||
|
|
5fc4ee50f6 | ||
|
|
d8a9993f63 | ||
|
|
96fe1eff44 | ||
|
|
033dae3772 | ||
|
|
5efe15a79e | ||
|
|
3d00dbcd55 | ||
|
|
10b72648a8 | ||
|
|
e5dd190874 | ||
|
|
880b44620a | ||
|
|
0a55421f34 | ||
|
|
b7a87285a1 | ||
|
|
b0d8cb82a2 | ||
|
|
9cfca9397b | ||
|
|
a056e181c2 | ||
|
|
d8000dfc2c | ||
|
|
8feaff41fe | ||
|
|
97d5337283 | ||
|
|
87913529e1 | ||
|
|
4e96ab13dd | ||
|
|
2e1c0a95c2 | ||
|
|
096fab8da7 | ||
|
|
aeba1f2db4 | ||
|
|
7e34ce27c7 | ||
|
|
8589d4dd7b | ||
|
|
20bcc714b9 | ||
|
|
a1dc6d7c87 | ||
|
|
e493510d81 | ||
|
|
9b3f15b170 | ||
|
|
8c52d48965 | ||
|
|
9b33a7af3b | ||
|
|
2a186f8bc4 | ||
|
|
2ab1c5e322 | ||
|
|
7366046f47 | ||
|
|
1773995dbc | ||
|
|
2bdd9b567a | ||
|
|
9ee6b08f76 | ||
|
|
77df61003c | ||
|
|
701dcab948 | ||
|
|
97a4ac8338 | ||
|
|
c2b1d86c69 | ||
|
|
0392aea57e | ||
|
|
89207ef83a | ||
|
|
d34c3f584c | ||
|
|
72d530702e | ||
|
|
bf185d1245 | ||
|
|
58a25f1bea | ||
|
|
b816c21b19 | ||
|
|
c476b4727d | ||
|
|
f7fccf6a3a | ||
|
|
72acb7caf1 | ||
|
|
40223e513b | ||
|
|
e71dfec941 | ||
|
|
0e4a7e6f90 | ||
|
|
7baa2937b0 | ||
|
|
c79e4a7a4b |
@@ -6,3 +6,40 @@ bdb473cbdb119f3d9060d48f75f965cbd45f6d7a
|
||||
|
||||
# More clang-format: liboslquery, oslinfo, oslc, osl.imageio, osltoy (#1220)
|
||||
bf366d7a90c46599b82071dac6dbef7c5e3ca157
|
||||
|
||||
# Turn on clang-format for cpp files in testsuite (#1269)
|
||||
00c895fc642eb89685797c292048bdff15d675e7
|
||||
5e848fb761261521a3ee7cd8a4f6814f32fe4a47
|
||||
|
||||
# CI: Change our clang-format standard to clang11 (#1372)
|
||||
91d22ebe2f65d4ed0599e421172a15d99fe0e1b4
|
||||
|
||||
# More clang-format (this time, testrender and liboslnoise) (#1511)
|
||||
08706b7cbac781b6a9389780428016be985d9d89
|
||||
|
||||
# clang-format #1509
|
||||
b4026fd1695c08532557b3ba1c2142323087ccf9
|
||||
1f73b075c99861afa42fac44567b37f797bc72f2
|
||||
7f2e83794e6fa63d5180653cffb77be2cc38b32b
|
||||
28399fefc890442b5ac020e7a90cee0d5bf9f03c
|
||||
e56851056d33233b0bb8324faac251907099961a
|
||||
1c57fc61d8ab7c3f309be4335e4c71c26399edd4
|
||||
46d451ce74d00e904874df476ebeca19bb119ea9
|
||||
c1045f2c2845a98e661c7181932a031eb3c76063
|
||||
|
||||
# More clang-format (#1512)
|
||||
8c6ffdd911b9eb7db4adf41ab88891360452d7c5
|
||||
|
||||
# style: more clang-format (#1515)
|
||||
102430c83554fe7e328cd8c3317db00507bcfaba
|
||||
|
||||
# Revert some formatting (#1518)
|
||||
21eac9d9215d071b0a7b9ce2c32f189ed0c62c4a
|
||||
|
||||
# Another round of clang-format (#1540)
|
||||
38015b6be28643254aea530154b7860136cf5e15
|
||||
89d5db2b5c5fda79184d8245d903e580fc6a4e9c
|
||||
|
||||
# clang-format: the very last piece of the puzzle (#1555)
|
||||
4ee62cd2ef05543f818f4d95a19efc1d684a7381
|
||||
5be7c6bd4e7bd2e560cb6be8c06f11985384a87a
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
# Copyright 2008-present Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
name: Analysis
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Run nightly while we're still working our way through the warnings
|
||||
- cron: "0 8 * * *"
|
||||
# Run unconditionally once weekly
|
||||
# - cron: "0 0 * * 0"
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- '*analysis*'
|
||||
# Allow manual kicking off of the workflow from github.com
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: read-all
|
||||
|
||||
# Allow subsequent pushes to the same PR or REF to cancel any previous jobs.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
jobs:
|
||||
|
||||
aswf:
|
||||
name: "SonarCloud Analysis"
|
||||
if: |
|
||||
github.repository == 'AcademySoftwareFoundation/OpenShadingLanguage'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- desc: sonar gcc9/C++14 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
|
||||
nametag: static-analysis-sonar
|
||||
os: ubuntu-20.04-8c-32g-300h
|
||||
# os: ubuntu-latest
|
||||
vfxyear: 2022
|
||||
vfxsuffix: -clang13
|
||||
cxx_std: 14
|
||||
openimageio_ver: master
|
||||
python_ver: 3.9
|
||||
pybind11_ver: v2.9.0
|
||||
simd: avx2,f16c
|
||||
batched: b8_AVX2,b16_AVX512
|
||||
coverage: 1
|
||||
# skip_tests: 1
|
||||
sonar: 1
|
||||
setenvs: export SONAR_SCANNER_VERSION=4.7.0.2747
|
||||
SONAR_SERVER_URL="https://sonarcloud.io"
|
||||
BUILD_WRAPPER_OUT_DIR=bw_output
|
||||
OSL_CMAKE_BUILD_WRAPPER="build-wrapper-linux-x86-64 --out-dir bw_output"
|
||||
CMAKE_BUILD_TYPE=Debug
|
||||
CMAKE_UNITY_BUILD=OFF
|
||||
CODECOV=1
|
||||
TESTRENDER_AA=1
|
||||
OSL_TESTSUITE_SKIP_DIFF=1
|
||||
CTEST_TEST_TIMEOUT=1200
|
||||
OSL_CMAKE_FLAGS="-DOSL_TEST_BIG_TIMEOUT=1200 -DUSE_QT=0"
|
||||
CTEST_EXCLUSIONS="broken|noise-reg.regress|noise-gabor-reg.regress"
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
container:
|
||||
image: aswf/ci-osl:${{matrix.vfxyear}}${{matrix.vfxsuffix}}
|
||||
env:
|
||||
CXX: ${{matrix.cxx_compiler}}
|
||||
CC: ${{matrix.cc_compiler}}
|
||||
CMAKE_CXX_STANDARD: ${{matrix.cxx_std}}
|
||||
FMT_VERSION: ${{matrix.fmt_ver}}
|
||||
OPENEXR_VERSION: ${{matrix.openexr_ver}}
|
||||
OPENIMAGEIO_VERSION: ${{matrix.openimageio_ver}}
|
||||
PYBIND11_VERSION: ${{matrix.pybind11_ver}}
|
||||
PYTHON_VERSION: ${{matrix.python_ver}}
|
||||
USE_BATCHED: ${{matrix.batched}}
|
||||
USE_SIMD: ${{matrix.simd}}
|
||||
PARALLEL: 24
|
||||
# DEBUG_CI: 1
|
||||
steps:
|
||||
# We would like to use harden-runner, but it flags too many false
|
||||
# positives, every time we download a dependency. We should use it only
|
||||
# on CI runs where we are producing artifacts that users might rely on.
|
||||
# - name: Harden Runner
|
||||
# uses: step-security/harden-runner@248ae51c2e8cc9622ecf50685c8bf7150c6e8813 # v1.4.3
|
||||
# with:
|
||||
# egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
|
||||
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
|
||||
with:
|
||||
fetch-depth: '0'
|
||||
- name: Prepare ccache timestamp
|
||||
id: ccache_cache_keys
|
||||
run: echo "::set-output name=date::`date -u +'%Y-%m-%dT%H:%M:%SZ'`"
|
||||
- name: ccache
|
||||
id: ccache
|
||||
uses: actions/cache@c3f1317a9e7b1ef106c153ac8c0f00fed3ddbc0d # v3.0.4
|
||||
with:
|
||||
path: /tmp/ccache
|
||||
key: ${{github.job}}-${{matrix.nametag}}-${{steps.ccache_cache_keys.outputs.date}}
|
||||
restore-keys: ${{github.job}}-
|
||||
- name: Build setup
|
||||
run: |
|
||||
${{matrix.setenvs}}
|
||||
src/build-scripts/ci-startup.bash
|
||||
- name: Remove existing OIIO
|
||||
if: matrix.openimageio_ver != ''
|
||||
run: |
|
||||
sudo rm -rf /usr/local/include/OpenImageIO
|
||||
sudo rm -rf /usr/local/lib*/cmake/OpenImageIO
|
||||
sudo rm -rf /usr/local/lib*/libOpenImageIO*
|
||||
sudo rm -rf /usr/local/lib*/python3.9/site-packages/OpenImageIO*
|
||||
- name: Dependencies
|
||||
run: |
|
||||
${{matrix.depcmds}}
|
||||
src/build-scripts/gh-installdeps.bash
|
||||
- name: Build
|
||||
run: src/build-scripts/ci-build.bash
|
||||
- name: Testsuite
|
||||
if: matrix.skip_tests != '1'
|
||||
run: src/build-scripts/ci-test.bash
|
||||
- name: Code coverage
|
||||
if: matrix.coverage == '1'
|
||||
run: src/build-scripts/ci-coverage.bash
|
||||
- name: Sonar-scanner
|
||||
if: matrix.sonar == 1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
run: |
|
||||
sonar-scanner -X --define sonar.host.url="${{ env.SONAR_SERVER_URL }}" --define sonar.cfamily.build-wrapper-output="build/bw_output" --define sonar.cfamily.gcov.reportsPath="_coverage"
|
||||
+402
-664
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,62 @@
|
||||
name: Scorecards supply-chain security
|
||||
on:
|
||||
# Only the default branch is supported.
|
||||
branch_protection_rule:
|
||||
schedule:
|
||||
- cron: '44 20 * * 6'
|
||||
push:
|
||||
branches: [ "main", "scorecard" ]
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
analysis:
|
||||
name: Scorecards analysis
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# Needed to upload the results to code-scanning dashboard.
|
||||
security-events: write
|
||||
# Used to receive a badge. (Upcoming feature)
|
||||
id-token: write
|
||||
# Needs for private repositories.
|
||||
contents: read
|
||||
actions: read
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@3e15ea8318eee9b333819ec77a36aca8d39df13e # v1.1.1
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
# (Optional) Read-only PAT token. Uncomment the `repo_token` line below if:
|
||||
# - you want to enable the Branch-Protection check on a *public* repository, or
|
||||
# - you are installing Scorecards on a *private* repository
|
||||
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
|
||||
# repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}
|
||||
|
||||
# Publish the results for public repositories to enable scorecard badges. For more details, see
|
||||
# https://github.com/ossf/scorecard-action#publishing-results.
|
||||
# For private repositories, `publish_results` will automatically be set to `false`, regardless
|
||||
# of the value entered here.
|
||||
publish_results: true
|
||||
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@5f532563584d71fdef14ee64d17bafb34f751ce5 # v1.0.26
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
@@ -8,3 +8,6 @@ build
|
||||
\#*\#
|
||||
*.pyc
|
||||
*.log
|
||||
.vscode
|
||||
.envrc
|
||||
|
||||
|
||||
@@ -50,4 +50,4 @@ This is a checklist for TSC's to review as part of the intake process. The TSC s
|
||||
- [X] License scan completed and no issues found
|
||||
- Minor issues were found but already fixed in PR https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1145
|
||||
- [X] Code repository imported to ASWF GitHub organization
|
||||
- [ ] Developer Certificate of Origin past commit signoff done and DCO Probot enabled.
|
||||
- [X] Developer Certificate of Origin post commit signoff done and DCO Probot enabled.
|
||||
|
||||
+174
-9
@@ -1,8 +1,84 @@
|
||||
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
||||
<!-- Copyright Contributors to the Open Shading Language Project. -->
|
||||
|
||||
Release 1.12 -- ?? (compared to 1.11)
|
||||
Release 1.13 -- ?? 2023 ?? (compared to 1.12)
|
||||
--------------------------------------------------
|
||||
Dependency and standards requirements changes:
|
||||
* OptiX 6.0 support has been removed. For GPU rendering with OptiX, a minimum
|
||||
of OptiX 7.0 is required.
|
||||
* The minimum version OpenImageIO has been raised from 2.2 to 2.3. #1591
|
||||
(1.13.0.3)
|
||||
|
||||
OSL Language and oslc compiler:
|
||||
* Bug fix: shader params whose default values involve "init ops" could be
|
||||
incorrectly initialized if their values came from instance parameters set to
|
||||
zero. #1578 (1.13.0.2)
|
||||
|
||||
OSL Standard library:
|
||||
|
||||
API changes, new options, new ShadingSystem features (for renderer writers):
|
||||
* A new `shadingStateUniform` pointer field was added to ShaderGlobals for
|
||||
planned future expansion and improved GPU support. #1585 (1.13.1.0)
|
||||
|
||||
SIMD batched shading mode:
|
||||
* Fix some array overruns (asymptomatic, but still potentially buggy) in
|
||||
common_ancestor_between. #1577 (1.13.0.2)
|
||||
|
||||
OptiX rendering:
|
||||
* OptiX 6.0 support has been removed. For GPU rendering with OptiX, a minimum
|
||||
of OptiX 7.0 is required.
|
||||
* Big overhaul/simplification of how strings are represented on the GPU: the
|
||||
extra level of indirection to global variables is removed, and strings are
|
||||
simply represented in ordinary variables as the hash of their characters.
|
||||
#1531 (1.13.0.0) #1553 (1.13.0.1)
|
||||
* Better PTX cache hit rate by eliminating several sources of not being
|
||||
strictly deterministic in the PTX text we were generating. #1566 #1570
|
||||
(1.13.0.1)
|
||||
|
||||
Performance improvements:
|
||||
|
||||
Bug fixes and other improvements (internals):
|
||||
* Fix memory leak in oslc ASTvariable_declaration. #1576 (1.13.0.2)
|
||||
* Fix memory leaks in LPE code in error conditions. #1593 #1594 (1.13.0.3)
|
||||
|
||||
Internals/developer concerns:
|
||||
* platform.h:
|
||||
- New `OSL_ALLOCA` macro to allocate on the stack. #1589 (1.13.0.3)
|
||||
|
||||
Build & test system improvements:
|
||||
* CMake build system and scripts:
|
||||
- The version number is now a cache variable, and so can be overridden at
|
||||
build time using `-DOSL_VERSION=...`. Use with extreme caution! #1579
|
||||
(1.13.0.2)
|
||||
* Dependency version support:
|
||||
- Fix some issues that came up with the new icx 2022.0 compiler. #1601
|
||||
(1.13.1.0)
|
||||
* Testing and Continuous integration (CI) systems:
|
||||
- Dynamic analysis using address and leak sanitizers. #1581 (1.13.0.3)
|
||||
- `testshade --help` now prints TextureSystem options and all hardware
|
||||
information. #1584 (1.13.0.3)
|
||||
- Improvements to SonarCloud and coverage analysis. #1596 (1.13.0.3)
|
||||
* Platform support:
|
||||
|
||||
Documentation:
|
||||
* `doc/RELEASING.md` documents our release process and versioning policies.
|
||||
#1572 (1.13.0.2)
|
||||
|
||||
|
||||
Release 1.12 -- 1 Oct 2022 (compared to 1.11)
|
||||
----------------------------------------------
|
||||
Big Deal Changes:
|
||||
* **Batch shading**: A fully operational "batch shading" support when using
|
||||
CPUs supporting the Intel AVX2 or AVX512 instruction set architectures,
|
||||
allows shading 8 or 16 points at a time, accelerated by using SIMD
|
||||
instructions. (Changes contributed by Intel.)
|
||||
* **OptiX**: A reasonable subset of the OSL language can run on NVIDIA GPUs
|
||||
for Cuda or OptiX-based renderers.
|
||||
* **Standardized material closures**: Synchronize with MaterialX on a minimum
|
||||
standard set of material closures. This is reflected in both the OSL spec as
|
||||
well as reference implementations of those closures in testrender. #1533
|
||||
#1536 #1537 #1538 #1539 #1541 #1542 #1547 #1557
|
||||
|
||||
Dependency and standards requirements changes:
|
||||
* The minimum (and default) compilation mode is now C++14. C++17 and 20 are
|
||||
also supported. #1362 #1369 (1.12.2)
|
||||
@@ -24,6 +100,8 @@ OSL Language and oslc compiler:
|
||||
that will be used for particular (s,t) texture coordinates. #1398 (1.12.3)
|
||||
* Better error detection when OSL user functions write to function parameters
|
||||
that are not marked as output. #1417 (1.12.3)
|
||||
* Detect and better error message when using a type name where a variable
|
||||
identifier should be. #1457 (1.12.4.2)
|
||||
|
||||
OSL Standard library:
|
||||
* vector2.h is updated with a mod() function for vector2. #1312 (1.12.1/1.11.12)
|
||||
@@ -31,6 +109,8 @@ OSL Standard library:
|
||||
* Fix previously-broken color conversions from RGB to xyY. #1410 (1.12.3)
|
||||
* Fully removed MaterialX shaders (get those from the MaterialX project).
|
||||
#1450 (1.12.3)
|
||||
* Fix incorrect implementation of `matrix4 * vector4` in vector4.h #1513
|
||||
(1.12.5.0)
|
||||
|
||||
API changes, new options, new ShadingSystem features (for renderer writers):
|
||||
* Custom experimental llvm optimization levels 10, 11, 12, and 13. These
|
||||
@@ -47,8 +127,16 @@ API changes, new options, new ShadingSystem features (for renderer writers):
|
||||
* Userdata input placement -- now you can designate where interpolated
|
||||
userdata should be copied from directly, rather then via callbacks to
|
||||
RendererServices::get_userdata(). #1391 (1.12.3)
|
||||
* Better hiding of the Matrix22 class, which was never actually part of the
|
||||
public APIs. #1480 (1.12.4.5)
|
||||
* Add ACES2065-1 and ACEScg as shading system color spaces (#1486) (1.12.4.6)
|
||||
* Expanded warnings (via enabling the "opt_warnings" attribute of the
|
||||
ShadingSystem) for operations that try to create new strings mid-shader, or
|
||||
that need to access the characters of strings mid-shader. These are only
|
||||
triggered for those cases that cannot be resolved by the end of the "runtime
|
||||
optimization" phase. #1497 (1.12.4.6)
|
||||
|
||||
Continued work on experimental SIMD batched shading mode:
|
||||
SIMD batched shading mode:
|
||||
* Added support for masked operations to LLVMUtil. #1248 #1250 (1.12.0.0)
|
||||
* Add interface to ShadingSystem for batched execution. #1272 (1.12.0.1)
|
||||
* Add interface to batched RendererServices. #1276 (1.12.0.1)
|
||||
@@ -61,7 +149,7 @@ Continued work on experimental SIMD batched shading mode:
|
||||
* ISA-specific modules. #1345 (1.12.2)
|
||||
* Introduction of CI testing of batched mode. #1357 #1367 (1.12.2)
|
||||
* Control flow and string ops. #1372 (1.12.2)
|
||||
* Matrix operations. #1378 (1.12.2)
|
||||
* Matrix operations. #1378 (1.12.2) #1485 (1.12.4.6)
|
||||
* Batched algebraic, trig, and transcendental functions. #1385 (1.12.2)
|
||||
* Batched noise. #1394 (1.12.3)
|
||||
* Batched implementation of all color operations. #1408 (1.12.3)
|
||||
@@ -69,8 +157,13 @@ Continued work on experimental SIMD batched shading mode:
|
||||
* Batched spline and spline inverse. #1422 (1.12.3)
|
||||
* Batched texture, gettextureinfo, texture3d, environment. #1436 (1.12.3)
|
||||
* Batched dictionary functionality (dict_find, etc.) #1445 (1.12.3)
|
||||
* Enable batched execution of most testsuite. #1453 (1.12.4.1)
|
||||
* Batched isnan, isinf, isfinite. #1456 (1.12.4.2)
|
||||
* Batched userdata and output placement. #1455 (1.12.4.2)
|
||||
* Batched pointcloud functions. #1464 (1.12.4.4)
|
||||
* Batched closures (#1500)
|
||||
|
||||
Continued work on experimental OptiX rendering:
|
||||
OptiX rendering:
|
||||
* Explicitly set the OptiX pipeline stack size. #1254 (1.12.0.0)
|
||||
* CI tests now at least compile and build with USE_OPTIX=1 (though not yet
|
||||
run the tests). #1281 (1.12.0.1)
|
||||
@@ -87,10 +180,12 @@ Continued work on experimental OptiX rendering:
|
||||
* Fix race conditions when compiling for OptiX 7. #1411 (1.12.3)
|
||||
* osl_get_attribute() uses device strings when compiling for OptiX.
|
||||
#1435 (1.12.3)
|
||||
* Fix issue with OptiX + clang 14 with duplicate symbols. #1561 (1.12.6.0)
|
||||
|
||||
Performance improvements:
|
||||
* Less mutex locking around use and retrieval of ColorSystem related to
|
||||
doing color transforms. #1405 (1.12.3)
|
||||
* Constant folding of `startswith()`. #1507 (1.12.5.0)
|
||||
|
||||
Bug fixes and other improvements (internals):
|
||||
* Fix derivatives of texture calls when only derivatives of the "alpha"
|
||||
@@ -121,6 +216,21 @@ Bug fixes and other improvements (internals):
|
||||
the Symbol class having no virtual destructor. #1397 (1.12.3)
|
||||
* Fix in runtime optimizer where tracking of messages and unknown messages
|
||||
relied on uninitialized variables. #1447 (1.11.17/1.12.3)
|
||||
* Stop internally using OIIO::string_view::c_str(), which will someday be
|
||||
removed. #1458 (1.12.4.2)
|
||||
* Correctly track that the backfacing() function requires N and I shader
|
||||
globals. #1462 (1.12.4.4)
|
||||
* Print all 4 levels of version numbers in help messages. #1477 (1.12.4.4)
|
||||
* Fix GPU code generation crash. #1479 (1.12.4.4)
|
||||
* Work to transition internals to use modern std::format notation for
|
||||
formatted output. #1487 #1490 (1.12.4.6) #1504 #1506 (1.12.5.0)
|
||||
* testrender improvements:
|
||||
* Fix testrender memory error on teardown. #1499 (1.12.4.6)
|
||||
* Modernize the sampler in testrender, improving quality and performance.
|
||||
#1534 (1.12.6.0)
|
||||
* Switch to cone tracing for derivatives. #1543 (1.12.6.0)
|
||||
* Fix error that prevented correct typecheck of ternary operator. #1552
|
||||
(1.12.6.0)
|
||||
|
||||
Internals/developer concerns:
|
||||
* Use the `final` keyword in certain internal classes where applicable.
|
||||
@@ -131,10 +241,25 @@ Internals/developer concerns:
|
||||
* The "archive_groupname" handling is now careful to sanitize the filenames
|
||||
it deals with, closing some security and safety holes. #1383 (1.12.2)
|
||||
* More migration of string formatting to new std::format style. #1389 (1.12.3)
|
||||
#1469 #1470 (1.12.4.4)
|
||||
* llvm_util: Switch some uses of ptr+len to span. #1390 (1.12.3)
|
||||
* OSL no longer uses sscanf internally (which has icky locale-dependent
|
||||
behavior), and instead use locale-independent OIIO::Strutil utilities
|
||||
whenever we need to parse strings. #1432 (1.12.3)
|
||||
* Avoid use of OIIO::string_view::str() which is not corresponding to the
|
||||
official C++17 std::string_view. #1467 (1.12.4.4)
|
||||
* Prototype of "free function" approach that will someday mostly supplant
|
||||
the way we use RendererServices, and will help to unlock feature completion
|
||||
for GPU and other back ends. This experimental feature is not expected
|
||||
to be used in OSL 1.12. #1494 (1.12.5.0)
|
||||
* Work on gradually converting printf-style formatted strings to fmt /
|
||||
std::format style. #1493 (1.12.5.0)
|
||||
* LLVM_Util: allow naming of llvm symbols to help with IR debugging. #1530
|
||||
(1.12.6.0)
|
||||
* clang-format the code base. #1508 #1509 #1511 #1512 #1515 #1518 #1540
|
||||
(1.12.5.0) #1555 #1562 #1568 (1.12.6.0)
|
||||
* A round of spell-checking all the comments in the code base. #1550
|
||||
(1.12.5.0)
|
||||
|
||||
Build & test system improvements:
|
||||
* CMake build system and scripts:
|
||||
@@ -167,24 +292,43 @@ Build & test system improvements:
|
||||
CMake 21 conventions. #1443 (1.12.3)
|
||||
- New TIME_COMMANDS option, when enabled, can help debug performance of
|
||||
the build. #1443 (1.12.3)
|
||||
- New CMake variable `DOWNSTREAM_CXX_STANDARD` sets the downstream
|
||||
minimum C++ requirement, separately from `CMAKE_CXX_STANDARD` which sets
|
||||
what we build OSL itself with. Clarify that currently, OSL can be used
|
||||
downstream by C++14, even if it is built with C++17 or higher. #1454
|
||||
(1.12.4.1)
|
||||
- Make exported cmake configs relocatable by using relative paths. #1466
|
||||
(1.12.4.4)
|
||||
* Dependency version support:
|
||||
- Build properly against Cuda 11 and OptiX 7.1. #1232 (1.12.0.1)
|
||||
and up to OptiX 7.4 #1559 (1.12.6.0)
|
||||
- PugiXML build fixes on some systems. #1262 (1.12.0.1/1.11.8)
|
||||
- Cuda/OptiX back end: Add `__CUDADEVRT_INTERNAL__` define to bitcode
|
||||
generation, needed to avoid duplicate cudaMalloc symbols with CUDA9+
|
||||
#1271 (1.12.0.1)
|
||||
- Build against LLVM 11 #1274 (1.12.0.1), LLVM 12 #1351 (1.12.1.0)
|
||||
#1412 (1.12.3), LLVM 13 #1420 (1.12.3)
|
||||
#1412 (1.12.3), LLVM 13 #1420 (1.12.3), LLVM 14 #1492 (1.12.4.6)
|
||||
LLVM 15 #1592 (1.12.6.2)
|
||||
- Fix build break against recent OIIO master change where m_mutex field
|
||||
was removed from ImageInput. #1281 (1.12.0.1/1.11.9)
|
||||
- Work to ensure that OIIO will build correctly against the upcoming
|
||||
Imath 3.0 and OpenEXR 3.0. #1299 (1.11.10/1.12.1) #1332 (1.11.11/1.12.1)
|
||||
#1341 (1.11.12/1.12.1) #1356 #1368 (1.11.13/1.12.2)
|
||||
#1341 (1.11.12/1.12.1) #1356 #1368 (1.11.13/1.12.2) #1489 (1.12.4.6)
|
||||
- Improved finding of llvm components when using static libraries. #1375
|
||||
(1.12.2)
|
||||
- No longer use boost regex, completely rely on std::regex now that OSL
|
||||
is C++14 minimum. #1377. (1.12.2)
|
||||
- Support for OpenImageIO 2.3 changes. #1393 (1.12.3)
|
||||
- Some rearrangement of `#include` and other trickery ensures that OSL
|
||||
always includes headers from its favored version of Imath, rather than
|
||||
the ones that OIIO prefers (in cases where OIIO and OSL were each based
|
||||
on different Imath versions). #1460 (1.12.4.2)
|
||||
- Various fixes for functionality and warnings for Intel icc and icx
|
||||
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
|
||||
@@ -193,20 +337,38 @@ 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)
|
||||
- Deal with OpenEXR and Imath changing its master branch to "main". #1463
|
||||
(1.12.4.4)
|
||||
- testrender fix sphere tangents, per MaterialX suggestion. #1465
|
||||
(1.12.4.4)
|
||||
- Allow testsuite tests to use oiiotool for image diffs instead of idiff.
|
||||
#1472 (1.12.4.4)
|
||||
- Allow `-Werror` to be disabled even on CI branches. #1471 (1.12.4.4)
|
||||
- CI Tests against the Intel icc and icx compilers! #1459 #1473 (1.12.4.4)
|
||||
#1501 (1.12.5.0)
|
||||
- Overhaul of GHA ci.yml to use strategy matrix. #1474 (1.12.4.4)
|
||||
- Test against clang 14 and fix new warnings. #1498 (1.12.5.0)
|
||||
- Test against clang 15 and fix new warnings. #1586 (1.12.6.2)
|
||||
- A scorecards workflow guards against a variety of security issues of
|
||||
the CI system itself. #1529 (1.12.6.0)
|
||||
- Enable SonarCloud static analysis. #1551 #1556 #1563 (1.12.6.0)
|
||||
* Platform support:
|
||||
- Various Windows compile fixes. #1263 #1285 (1.12.0.1)
|
||||
- Windows+Cuda build fixes. #1292 (1.12.0.1)
|
||||
- Fix warnings about pointer casts on Windows. #1484 (1.12.4.5)
|
||||
- Various Windows build fixes. #1502 (1.12.5.0)
|
||||
* The oso and osl lexers/parsers are now given internal symbol names that
|
||||
are fully versioned, to avoid possible clash if multiple OSL releases are
|
||||
both linked into the same application. #1255 (1.12.0.0)
|
||||
@@ -221,6 +383,9 @@ Documentation:
|
||||
#1326 (1.12.1)
|
||||
* Fix missing explanation of the optional "errormessage" parameter to
|
||||
environment() and texture3d(). #1442 (1.12.3/1.11.17)
|
||||
* A SECURITY.md file explains how to confidentially report vulnerabilities.
|
||||
#1529 (1.12.6)
|
||||
* Document all the new MaterialX closures. #1564
|
||||
|
||||
|
||||
|
||||
@@ -688,7 +853,7 @@ Build & test system improvements:
|
||||
use clang library components for preprocessing. #1089 (1.11.3)
|
||||
* Add an optional build-time `EXTRA_WARNINGS` option (default: OFF) that
|
||||
enables even more picky than usual warnings. Fix many warnings that cropped
|
||||
up during testing, mostly related to unused function paramters. #1106 (1.11.3)
|
||||
up during testing, mostly related to unused function parameters. #1106 (1.11.3)
|
||||
* The testsuite can run in parallel, with a number of threads set by the
|
||||
environment variable `CTEST_PARALLEL_LEVEL`. #1119 (1.11.4)
|
||||
* oslconfig.h is now generated by a cmake configure_file step, from
|
||||
|
||||
+22
-1
@@ -3,7 +3,9 @@
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
cmake_minimum_required (VERSION 3.12)
|
||||
project (OSL VERSION 1.12.3.0
|
||||
|
||||
set (OSL_VERSION "1.13.1.0" CACHE STRING "Version")
|
||||
project (OSL VERSION ${OSL_VERSION}
|
||||
LANGUAGES CXX C
|
||||
HOMEPAGE_URL "https://github.com/AcademySoftwareFoundation/OpenShadingLanguage")
|
||||
set (PROJ_NAME ${PROJECT_NAME}) # short name
|
||||
@@ -121,6 +123,9 @@ if (USE_OPTIX)
|
||||
add_definitions ("-DOSL_USE_OPTIX=1")
|
||||
endif ()
|
||||
|
||||
# Define OSL_INTERNAL symbol only when building OSL itself, will not be
|
||||
# defined for downstream projects using OSL.
|
||||
add_definitions (-DOSL_INTERNAL=1)
|
||||
|
||||
# Set the default namespace. For symbol hiding reasons, it's important that
|
||||
# the project name is a subset of the namespace name.
|
||||
@@ -158,6 +163,7 @@ include (pythonutils)
|
||||
include (externalpackages)
|
||||
include (flexbison)
|
||||
include (cuda_macros)
|
||||
include (llvm_macros)
|
||||
|
||||
# Include all our testing apparatus and utils, but not if it's a subproject
|
||||
if (${PROJECT_NAME}_BUILD_TESTS AND PROJECT_IS_TOP_LEVEL)
|
||||
@@ -175,6 +181,21 @@ include_directories (
|
||||
)
|
||||
|
||||
|
||||
# Make sure our math calculations are consistent,
|
||||
# especially division. Different compilers may have choose to use
|
||||
# reciprocal division losing precision causing slightly different
|
||||
# results which can lead to aliasing differences when running the testsuite
|
||||
# Disable reciprocal division
|
||||
if (CMAKE_COMPILER_IS_INTEL)
|
||||
if (MSVC)
|
||||
add_compile_options("/Qprec-div")
|
||||
else ()
|
||||
add_compile_options("-prec-div")
|
||||
endif ()
|
||||
elseif (CMAKE_COMPILER_IS_CLANG OR CMAKE_COMPILER_IS_APPLECLANG OR CMAKE_COMPILER_IS_INTELCLANG)
|
||||
add_compile_options("-fno-reciprocal-math")
|
||||
endif ()
|
||||
|
||||
# Tell CMake to process the sub-directories
|
||||
add_subdirectory (src/include)
|
||||
add_subdirectory (src/liboslcomp)
|
||||
|
||||
+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;
|
||||
}
|
||||
|
||||
@@ -139,6 +139,7 @@ Current voting members of the TSC are:
|
||||
* Lee Kerley - Sony Pictures Imageworks
|
||||
* Mitch Prater - Laika
|
||||
* Brecht Van Lommel - Blender
|
||||
* Alex Wells - Intel
|
||||
|
||||
### TSC Nomination and Succession
|
||||
|
||||
|
||||
+22
-22
@@ -12,15 +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.21)
|
||||
* Build system: [CMake](https://cmake.org/) 3.12 or newer (tested through 3.24)
|
||||
|
||||
* A suitable **C++14 or C++17** compiler to build OSL itself, which may be any of:
|
||||
- **GCC 6.1 or newer** (tested through gcc 11.2)
|
||||
- Clang 3.4 or newer (tested through clang 13)
|
||||
- Microsoft Visual Studio **2017 or newer**
|
||||
- Intel C++ compiler icc **version 17 or newer**
|
||||
* A suitable C++14 or C++17 compiler to build OSL itself, which may be any of:
|
||||
- GCC 6.1 or newer (tested through gcc 12.1)
|
||||
- Clang 3.4 or newer (tested through clang 15)
|
||||
- Microsoft Visual Studio 2017 or newer
|
||||
- Intel C++ compiler icc version 17 or newer or LLVM-based icx compiler
|
||||
version 2022 or newer.
|
||||
|
||||
* **[OpenImageIO](http://openimageio.org) 2.2 or newer** (tested through 2.3)
|
||||
* **[OpenImageIO](http://openimageio.org) 2.3 or newer** (tested through 2.4)
|
||||
|
||||
OSL uses OIIO both for its texture mapping functionality as well as
|
||||
numerous utility classes. If you are integrating OSL into an existing
|
||||
@@ -39,10 +40,14 @@ NEW or CHANGED dependencies since the last major release are **bold**.
|
||||
$OpenImageIO_ROOT/lib to be in your LD_LIBRARY_PATH (or
|
||||
DYLD_LIBRARY_PATH on OS X).
|
||||
|
||||
* **[LLVM](http://www.llvm.org) 9, 10, 11, 12, or 13**, including clang
|
||||
libraries.
|
||||
* [LLVM](http://www.llvm.org) 9, 10, 11, 12, 13, 14, or 15, including
|
||||
clang libraries.
|
||||
|
||||
* [Boost](https://www.boost.org) 1.55 or newer (tested through boost 1.77)
|
||||
* (optional) For GPU rendering on NVIDIA GPUs:
|
||||
* [OptiX](https://developer.nvidia.com/rtx/ray-tracing/optix) 7.0 or higher.
|
||||
* [Cuda](https://developer.nvidia.com/cuda-downloads) 8.0 or higher.
|
||||
|
||||
* [Boost](https://www.boost.org) 1.55 or newer (tested through boost 1.80)
|
||||
* [Ilmbase or Imath](https://github.com/AcademySoftwareFoundation/openexr) 2.3
|
||||
or newer (recommended: 2.4 or higher; tested through 3.1)
|
||||
* [Flex](https://github.com/westes/flex) 2.5.35 or newer and
|
||||
@@ -56,8 +61,8 @@ NEW or CHANGED dependencies since the last major release are **bold**.
|
||||
be operative.
|
||||
* (optional) Python: If you are building the Python bindings or running the
|
||||
testsuite:
|
||||
* Python >= 2.7 (tested against 2.7, 3.7, 3.8, 3.9)
|
||||
* pybind11 >= 2.4.2 (Tested through 2.9)
|
||||
* Python >= 2.7 (tested against 2.7, 3.7, 3.8, 3.9, 3.10)
|
||||
* pybind11 >= 2.4.2 (Tested through 2.10)
|
||||
* NumPy
|
||||
* (optional) Qt >= 5.6 (tested through 5.15). If not found at build time,
|
||||
the `osltoy` application will be disabled.
|
||||
@@ -92,19 +97,14 @@ Here are the steps to check out, build, and test the OSL distribution:
|
||||
full errors, not warnings.
|
||||
|
||||
4. After compilation, you'll end up with a full OSL distribution in
|
||||
dist/ARCH, where ARCH is the architecture you are building on, one of
|
||||
"linux", "linux64", "macosx", "windows", or "windows64".
|
||||
dist/
|
||||
|
||||
Note: The default is to make an optimized "release" build. If
|
||||
instead type 'make debug' at the top level, you will end up with
|
||||
a debug build (no optimization, full symbols) in "dist/ARCH.debug".
|
||||
|
||||
5. Add the "dist/ARCH/bin" to your $PATH, and "dist/ARCH/lib" to your
|
||||
$LD_LIBRAY_PATH (or $DYLD_LIBRARY_PATH on OS X), or copy the contents
|
||||
5. Add the "dist/bin" to your $PATH, and "dist/lib" to your
|
||||
$LD_LIBRAY_PATH (or $DYLD_LIBRARY_PATH on MacOS), or copy the contents
|
||||
of those files to appropriate directories. Public include files
|
||||
(those needed when building applications that incorporate OSL)
|
||||
can be found in "dist/ARCH/include", and documentation can be found
|
||||
in "dist/ARCH/share/doc".
|
||||
can be found in "dist/include", and documentation can be found
|
||||
in "dist/share/doc".
|
||||
|
||||
6. After building (and setting your library path), you can run the
|
||||
test suite with:
|
||||
|
||||
@@ -156,6 +156,10 @@ ifneq (${USE_BATCHED},)
|
||||
MY_CMAKE_FLAGS += -DUSE_BATCHED:STRING="${USE_BATCHED}"
|
||||
endif
|
||||
|
||||
ifneq (${VEC_REPORT},)
|
||||
MY_CMAKE_FLAGS += -DVEC_REPORT:BOOL="${VEC_REPORT}"
|
||||
endif
|
||||
|
||||
ifneq (${TEST},)
|
||||
TEST_FLAGS += -R ${TEST}
|
||||
endif
|
||||
@@ -356,7 +360,7 @@ help:
|
||||
@echo " STOP_ON_WARNING=0 Do not stop building if compiler warns"
|
||||
@echo " OSL_SITE=xx Use custom site build mods"
|
||||
@echo " MYCC=xx MYCXX=yy Use custom compilers"
|
||||
@echo " CMAKE_CXX_STANDARD=14 Compile in C++14 mode (default is C++11)"
|
||||
@echo " CMAKE_CXX_STANDARD=14 C++ standard to build with (default is 14)"
|
||||
@echo " USE_LIBCPLUSPLUS=1 For clang, use libc++"
|
||||
@echo " GLIBCXX_USE_CXX11_ABI=1 For gcc, use the new string ABI"
|
||||
@echo " EXTRA_CPP_ARGS= Additional args to the C++ command"
|
||||
@@ -398,6 +402,7 @@ help:
|
||||
@echo " 0, b8_AVX, b8_AVX2, b8_AVX2_noFMA,"
|
||||
@echo " b8_AVX512, b8_AVX512_noFMA,"
|
||||
@echo " b16_AVX512, b16_AVX512_noFMA)"
|
||||
@echo " VEC_REPORT=0 Generate compiler vectorization reports"
|
||||
@echo " make test, extra options:"
|
||||
@echo " TEST=regex Run only tests matching the regex"
|
||||
@echo ""
|
||||
|
||||
@@ -393,6 +393,18 @@ Films using OSL (grouped by year of release date):
|
||||
Matrix Resurrections
|
||||
* **(2022 / upcoming)**
|
||||
Hotel Transylvania 4: Transformania,
|
||||
Death on the Nile,
|
||||
Uncharted,
|
||||
Turning Red,
|
||||
The Adam Project,
|
||||
Doctor Strange in the Multiverse of Madness,
|
||||
Love, Death, and Robots: In Vaulted Halls Entombed,
|
||||
Jurassic World: Dominion,
|
||||
Lightyear,
|
||||
Thor: Love and Thunder,
|
||||
The Sea Beast,
|
||||
DC League of Super Pets,
|
||||
Bullet Train,
|
||||
...
|
||||
|
||||
|
||||
@@ -427,9 +439,13 @@ certain is a legit problem in the code, and for which you can give clear
|
||||
instructions for how to reproduce, should be [reported as
|
||||
issues](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/issues).
|
||||
|
||||
If confidentiality precludes a public question or issue, you may contact the
|
||||
project administrator privately at [lg@imageworks.com](lg@imageworks.com),
|
||||
including for security-related issues.
|
||||
If you think you've found a potential vulnerability in OSL, please
|
||||
confidentially report it by emailing the project administrators at
|
||||
[security@openshadinglanguage.org](security@openshadinglanguage.org).
|
||||
|
||||
If any other issue requires confidentiality that precludes a public question
|
||||
or issue, you may contact the project administrator privately at
|
||||
[lg@larrygritz.com](lg@larrygritz.com).
|
||||
|
||||
|
||||
Contributing
|
||||
@@ -453,7 +469,6 @@ Contacts, Links, and References
|
||||
|
||||
[OSL home page](http://openshadinglanguage.org)
|
||||
|
||||
[Sony Pictures Imageworks main open source page](http://opensource.imageworks.com)
|
||||
|
||||
|
||||
|
||||
@@ -466,18 +481,18 @@ The current project leadership is documented in the
|
||||
Many people have contributed features, bug fixes, and other changes to OSL
|
||||
over the years: Steve Agland, Shane Ambler, Martijn Berger, Farchad
|
||||
Bidgolirad, Nicholas Bishop, Solomon Boulos, Stefan Bruens, Stefan Büttner,
|
||||
Matthaus G. Chajdas, Clark Chen, Alejandro Conty, Thomas Dinges, Mads
|
||||
Drøschler, Luke Emrose, Louis Feng, Mark Final, Henri Fousse, Syoyo Fujita,
|
||||
Tim Grant, Larry Gritz, Nicolas Guiard, Euan Haahr, Derek Haase, Sven-Hendrik
|
||||
Haase, John Haddon, Niklas Harrysson, Daniel Heckenberg, Thiago Ize, Matt
|
||||
Johnson, Ronan Keryell, Chris Kulla, Elvic Liang, Max Liani, Adam Martinez,
|
||||
John Mertic, Bastien Montagne, Steena Monteiro, Alexis Oblet, Erich Ocean,
|
||||
Mikko Ohtamaa, Jino Park, Alexei Pawlow, Jay Reynolds, Declan Russell, Benoit
|
||||
Ruiz, Patrick Scheibe, Alex Schworer, Jonathan Scruggs, Sergey Sharybin,
|
||||
Sandip Shukla, Cliff Stein, Stephan Steinbach, Luya Tshimbalanga, Esteban
|
||||
Tovagliari, Brecht Van Lommel, Alexander von Knorring, Alex Wells, Roman
|
||||
Zulak. (Listed alphabetically; if we've left anybody out, it is inadvertent,
|
||||
please let us know.)
|
||||
Matthaus G. Chajdas, Clark Chen, Alejandro Conty, Dieter De Baets, Thomas
|
||||
Dinges, Mads Drøschler, Luke Emrose, Louis Feng, Mark Final, Henri Fousse,
|
||||
Stephen Friedman, Syoyo Fujita, Tim Grant, Larry Gritz, Nicolas Guiard, Euan
|
||||
Haahr, Derek Haase, Sven-Hendrik Haase, John Haddon, Niklas Harrysson, Daniel
|
||||
Heckenberg, Adrien Herubel, Thiago Ize, Matt Johnson, Ronan Keryell, Chris
|
||||
Kulla, Elvic Liang, Max Liani, Adam Martinez, John Mertic, Bastien Montagne,
|
||||
Steena Monteiro, Alexis Oblet, Erich Ocean, Mikko Ohtamaa, Jino Park, Alexei
|
||||
Pawlow, Jay Reynolds, Declan Russell, Benoit Ruiz, Patrick Scheibe, Alex
|
||||
Schworer, Jonathan Scruggs, Sergey Sharybin, Sandip Shukla, Cliff Stein,
|
||||
Stephan Steinbach, Luya Tshimbalanga, Esteban Tovagliari, Brecht Van Lommel,
|
||||
Alexander von Knorring, Alex Wells, Roman Zulak. (Listed alphabetically; if
|
||||
we've left anybody out, it is inadvertent, please let us know.)
|
||||
|
||||
We cannot possibly express sufficient gratitude to the managers at Sony
|
||||
Pictures Imageworks who allowed this project to proceed, supported it
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
This gives guidance about which branches are supported with patches to
|
||||
security vulnerabilities.
|
||||
|
||||
| Version / branch | Supported |
|
||||
| --------- | ---------------------------------------------------- |
|
||||
| main | :white_check_mark: :construction: ALL fixes immediately, but this is a branch under development with a frequently unstable ABI and occasionally unstable API. |
|
||||
| 1.12.x | :white_check_mark: All fixes that can be backported without breaking ABI compatibility. New tagged releases monthly. |
|
||||
| 1.11.x | :warning: Only the most critical fixes, only if they can be easily backported. |
|
||||
| <= 1.10.x | :x: No longer receiving patches of any kind. |
|
||||
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you think you've found a potential vulnerability in OSL, please report it
|
||||
by emailing the project administrators at
|
||||
[security@openshadinglanguage.org](security@openshadinglanguage.org). Only the
|
||||
project administrators have access to these messages. Include detailed steps to
|
||||
reproduce the issue, and any other information that could aid an
|
||||
investigation. Our policy is to respond to vulnerability reports within 14
|
||||
days.
|
||||
|
||||
Our policy is to address critical security vulnerabilities rapidly and post
|
||||
patches as quickly as possible.
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
The OSL Documentation Project is a work in progress.
|
||||
|
||||
The plan is to adopt the OCIO Documentation Project's methodology for maintaining and building documention of various kinds as it becomes the blueprint for the ASWF.
|
||||
The plan is to adopt the OCIO Documentation Project's methodology for maintaining and building documentation of various kinds as it becomes the blueprint for the ASWF.
|
||||
|
||||
There is much work to be done here.
|
||||
|
||||
|
||||
@@ -0,0 +1,341 @@
|
||||
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
||||
<!-- Copyright Contributors to the Open Shading Language Project. -->
|
||||
|
||||
# Release Procedures for Open Shading Language
|
||||
|
||||
## Version nomenclature and release cadence
|
||||
|
||||
### The meaning of the version parts
|
||||
|
||||
Our release numbers are of the form `MAJOR.MINOR.PATCH.TWEAK`, and we follow
|
||||
an almost-semantic-versioning scheme.
|
||||
|
||||
MAJOR changes are those that break backward-compatibility of the public APIs,
|
||||
requiring existing application code to change their source code where it calls
|
||||
OSL API functions in order to compile and work correctly.
|
||||
|
||||
MINOR changes guarantee API backward-compatibility with prior releases that
|
||||
have the same major number, but can introduce ABI or link incompatibilities.
|
||||
Applications using OSL need to be recompiled to move to a new minor release,
|
||||
but should not need to change their source code. Minor releases are allowed
|
||||
to drop support for sufficiently old compilers and dependencies.
|
||||
|
||||
PATCH changes guarantee both API and ABI/link backward-compatibility with
|
||||
prior releases that have the same minor number. Features and new public API
|
||||
calls may be added (thus deviating from strict semantic versioning), but only
|
||||
if they preserve ABI/link compatibility. This means that standalone functions
|
||||
or static methods may be added, but existing functions will not change their
|
||||
parameters, and no new virtual methods or struct data layouts change for patch
|
||||
releases (for classes in public header files). Application code can be
|
||||
re-linked to a new patch release without needing to be recompiled. We also
|
||||
guarantee that any compilers or dependencies supported for the first release
|
||||
of a minor series will continue to be supported for all patches to that minor
|
||||
series.
|
||||
|
||||
TWEAK changes are restricted to critical bug fixes or build breaks that do
|
||||
not alter public APIs in any way.
|
||||
|
||||
### Cadence of releases
|
||||
|
||||
Major (arbitrarily incompatible) releases happen rarely, usually with multiple
|
||||
years between them.
|
||||
|
||||
Minor (API backward-compatible) releases are scheduled annually, targeted at
|
||||
late summer (SIGGRAPH time) to be in beta, and early autumn for a full
|
||||
release.
|
||||
|
||||
Patch (API and ABI backward-compatible) releases are scheduled monthly,
|
||||
usually aiming for the first day of each month.
|
||||
|
||||
Tweak (fully forward and backward compatible) releases are not regularly
|
||||
scheduled, and only happen sporadically, when a critical fix is needed in
|
||||
between scheduled patch releases.
|
||||
|
||||
### Things are different in "main"
|
||||
|
||||
The "main" branch is where ongoing development occurs without any
|
||||
compatibility guarantees. We don't always know if the next year's release from
|
||||
main will turn out to be major (API breaking) or minor (only ABI breaking).
|
||||
|
||||
Some studios or products need the most up-to-date enhancements, and thus tend
|
||||
to build OSL from the "main" branch rather than using tagged releases. For
|
||||
these users, we try to set version numbers and occasionally tag in main, to
|
||||
send a signal about which points in main seem safe to rely on various
|
||||
compatibility levels. However, the rules are slightly different than we use
|
||||
for releases.
|
||||
|
||||
In the "main" branch:
|
||||
|
||||
- TWEAK changes within "main" only guarantee ABI back-compatibility, but may
|
||||
have additions or non-bug-fix behavior changes (akin to patch releases
|
||||
within a release branch).
|
||||
- PATCH changes within "main" are allowed to break ABI or API (changes that
|
||||
would require minor or major releases, if they were not in "main").
|
||||
- Beware of unmarked breaks in compatibility of commits in main that are
|
||||
in between developer preview tags.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Branch and tag names
|
||||
|
||||
**Branches** are places where commits containing new development may be added
|
||||
(and thus the branch markers will move over time). Branch names obey the
|
||||
following conventions:
|
||||
|
||||
- `main` is the area for arbitrary changes intended for the next year's major
|
||||
or minor release.
|
||||
- `dev-1.2` are the areas for staging additions to the next month's patch
|
||||
release for the designated minor version series.
|
||||
- `release` is a special branch marker that is always set to the latest tag of
|
||||
the currently supported, stable release family. People can count on
|
||||
"release" always being the latest stable release, whatever that may be at
|
||||
the time.
|
||||
|
||||
**Tags** indicate releases or developer previews, and once a commit is
|
||||
tagged, it is permanent and will never be moved. Tag names obey the following
|
||||
conventions:
|
||||
|
||||
- `v1.2.3.4` is a specific public stable release, corresponding to official
|
||||
major, minor, public, or tweak releases.
|
||||
- `v1.2.3.4-alpha`, `v1.2.3.4-beta`, or `v1.2.3.4-RC1` are pre-releases for an
|
||||
upcoming public stable release, at the alpha, beta, or release candidate
|
||||
stages, respectively.
|
||||
- `v1.2.3.4-dev` is a "developer preview" within "main." It is not an official
|
||||
supported release, and while the numbering may indicate compatibility versus
|
||||
other recent developer previews, they should not be assumed to be compatible
|
||||
with any prior official stable releases.
|
||||
|
||||
*Very* occasionally, other branch or tag names (with custom suffixes or
|
||||
different naming schemes) may be used for special purposes by particular
|
||||
developers or users, but should not be considered reliable or permanent, and
|
||||
in general should be ignored by anyone who didn't make the tag or branch.
|
||||
|
||||
---
|
||||
|
||||
## Release Procedures
|
||||
|
||||
### Soft freeze for monthly tweak releases:
|
||||
|
||||
We freely backport *safe*, non-ABI-breaking changes by cherry-picking them
|
||||
from main to the supported branch continually throughout most of the month.
|
||||
|
||||
In the seven days before the new month, we do a "soft freeze" where only
|
||||
important bug fixes are backported. Hold on to any other patches you wish to
|
||||
backport until after the monthly patch release (i.e., save them for the next
|
||||
month's release so you never have a release that contains changes that are
|
||||
only a few days old, and therefore not as well tested). You may, of course,
|
||||
continue to backport fixes to documentation or other non-code parts of the
|
||||
project during this soft freeze.
|
||||
|
||||
### Branching for annual major/minor releases
|
||||
|
||||
By mid-June (about 1-2 months before the beta of a new annual big release),
|
||||
you should branch and mark it as an alpha.
|
||||
|
||||
At the tip of "main," create a new branch named `dev-MAJOR.MINOR` that will be
|
||||
the staging area for the next release.
|
||||
|
||||
Customarily, at that point we add a commit to main (but not to the new
|
||||
dev-MAJ.MIN branch) that bumps main's version to the next minor level, to
|
||||
avoid any confusion between builds from main versus what will be the next
|
||||
release branch. This starts the divergence between main and the release
|
||||
branch, and henceforth, any big or compatibility-breaking changes will only be
|
||||
committed to main and not backported to the release branch. (Though we are
|
||||
loose about this rule during the alpha period and allow continued breaking
|
||||
changes in the alpha, but by the time we call it beta, we allow no more
|
||||
breaking changes.)
|
||||
|
||||
|
||||
### Prior to a release
|
||||
|
||||
1. Update CI dependencies: Ensure that the "latest" CI test specifies the
|
||||
current releases of the dependencies and compilers (check their home
|
||||
pages), and that the [INSTALL.md](../INSTALL.md) file correctly documents
|
||||
the version ranges that we expect to work and that we actively test.
|
||||
|
||||
2. Release notes: [CHANGES.md](../CHANGES.md) should be updated to reflect
|
||||
all the new features and fixes. Looking at the notes from older releases
|
||||
should provide a good example of what we're aiming for.
|
||||
|
||||
- Patch and tweak releases can be brief one-line descriptions (often the
|
||||
first line of the commit messages involved), presented in a single
|
||||
section in either chronological or any other order that seems right.
|
||||
- Minor or major releases have a much more extensive, prose-based
|
||||
description of all changes since the last minor release, broken into
|
||||
sections (dependency changes, major new features, enhancements and fixes,
|
||||
internals and developer goodies, testing/CI/ports, etc.) and ordered for
|
||||
readability and relevance.
|
||||
|
||||
3. Ensure docs are up to date:
|
||||
|
||||
- Actually read the [README.md](../README.md), [INSTALL.md](../INSTALL.md),
|
||||
and other repository docs and make sure all the information is up to
|
||||
date. Check the "contributor credits" in the README against the recent
|
||||
repo history to be sure new contributors are listed. Also check the
|
||||
list of films and make sure it includes any recent productions that are
|
||||
known to have used OSL.
|
||||
- Skim the primary user documentation to look for any obvious errors,
|
||||
especially the parts that describe new features. In the case of PDF docs
|
||||
(such as osl-languagespec.pdf), make sure that a new PDF book is built if
|
||||
the documentation source has been changed since the last release.
|
||||
- If we are using any online docs (like readthedocs), make sure it is
|
||||
building and looks correct on the web site.
|
||||
|
||||
4. Make sure the the top-level CMakeLists.txt file is updated:
|
||||
|
||||
- The version on the `project()` call should be correct.
|
||||
- The `PROJECT_VERSION_RELEASE_TYPE` variable should be set to "alpha" or
|
||||
"beta" if appropriate, "RC" for release candidate, or empty string `""`
|
||||
for most supported releases, and "dev" only for the main branch or
|
||||
developer previews.
|
||||
- The `${PROJECT_NAME}_SUPPORTED_RELEASE` variable should be `ON` for any
|
||||
release branch, `OFF` for main.
|
||||
|
||||
5. Make sure everything passes the usual CI workflow. Also check the daily or
|
||||
weekly "analysis" workflows to make sure there aren't any important
|
||||
warnings that should be fixed.
|
||||
|
||||
|
||||
### Staging alpha / beta / release candidate (annual minor/major releases only)
|
||||
|
||||
For monthly patch releases, we don't have any formal alpha/beta/RC stages.
|
||||
|
||||
For the annual minor or major releases we have a staged release:
|
||||
|
||||
- `alpha` is everything after we have branched, in which we think all the big
|
||||
new features have been added, and while we will make continued changes and
|
||||
fixes, we are aiming for increased stability and to minimize additional
|
||||
breaking changes prior to the release.
|
||||
- `beta` should be about one month prior to the final release date. We create
|
||||
a tag `v1.2.3.4-beta` and announce the beta (see below "Making the
|
||||
release"). Once we tag a beta, we try very hard not to allow any further
|
||||
changes that change the API or are not ABI-compatible (i.e., safe fixes
|
||||
only).
|
||||
- `RC` or release candidates around one week prior to the final release date.
|
||||
This is a trial run, hopefully identical to the final release (except for
|
||||
removing the RC label and making a new tag). The only changes allowed after
|
||||
RC are fixes to the most critical bugs or build breaks that would be bad for
|
||||
users to encounter. If critical problems are found with RC1, they should be
|
||||
fixed and immediately re-tagged as RC2, etc. All other fixes should be
|
||||
postponed until the next month's patch release.
|
||||
|
||||
### Making the release
|
||||
|
||||
A final release is made on the scheduled date, provided the latest RC has
|
||||
survived for at least a few days of testing without finding any critical
|
||||
problems. Don't make the release final until you are sure there are no
|
||||
truly critical bugs or build breaks that users will encounter.
|
||||
|
||||
The following are the steps for making the release:
|
||||
|
||||
1. Edit the top-level CMakeLists.txt to remove any RC designation
|
||||
(i.e., `PROJECT_VERSION_RELEASE_TYPE` should be set to `""`).
|
||||
|
||||
2. Edit CHANGES.md to reflect the correct date of the release and ensure it
|
||||
includes any last-minute changes that were made during beta or release
|
||||
candidate stages.
|
||||
|
||||
3. Push it to **your** GitHub, make sure it passes CI.
|
||||
|
||||
4. Tag the release: `git tag v1.2.3.4` (no more beta, RC, or dev suffix).
|
||||
|
||||
5. If this will now be the recommended stable release, move the `release`
|
||||
branch marker to the same position.
|
||||
|
||||
6. Push it to GitHub: `git push aswf release --tags`
|
||||
|
||||
(This example assumes "aswf" is the name of the remote for the GitHub
|
||||
`AcademySoftwareFoundation/OpenShadingLanguage` repo.)
|
||||
|
||||
7. Draft a release on GitHub: On
|
||||
https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/releases
|
||||
select "Draft a new release." Choose the new tag you just pushed. Make the
|
||||
release title "Open Shading Language v1.2.3.4" (and beta, etc., designation
|
||||
if applicable). In the description, paste the release notes for this
|
||||
release (from Changes.md). If this is a beta or release candidate, check
|
||||
"this is a pre-release" box at the bottom.
|
||||
|
||||
8. Announce the release on the [osl-dev mail list](https://lists.aswf.io/g/osl-dev)
|
||||
with the subject "Release: OSL v1.2.3.4" and using one of these templates
|
||||
for the body of the email.
|
||||
|
||||
For a monthly patch release:
|
||||
|
||||
> We have tagged v1.2.3.4 as the latest production release and moved the
|
||||
> "release" branch marker to that point. This is guaranteed to be API,
|
||||
> ABI, and link back-compatible with prior 1.2 releases. Release notes
|
||||
> are below.
|
||||
>
|
||||
> (Paste the full set of 1.2 changes here, just copy the appropriate
|
||||
> part of CHANGES.md)
|
||||
|
||||
For an annual major/minor release:
|
||||
|
||||
> OSL version 1.2 has been released! Officially tagged as "v1.2.3.4", we
|
||||
> have also moved the "release" branch tag to this position. Henceforth,
|
||||
> 1.2 is the supported production release family. The API is now frozen --
|
||||
> we promise that subsequent 1.2.x releases (which should happen monthly)
|
||||
> will not break back-compatibility of API, ABI, or linkage, compared to
|
||||
> this release. Please note that this release is *not* ABI or link
|
||||
> compatible with 1.1 or older releases.
|
||||
>
|
||||
> Release notes for 1.2 outlining all the changes since last year's
|
||||
> release are below.
|
||||
>
|
||||
> Please note that a few of the build and runtime dependencies have
|
||||
> changed their minimum supported versions. (List here any important
|
||||
> changes to dependencies, compilers, or C++ standard that users should be
|
||||
> aware of.)
|
||||
>
|
||||
> (List here anything else that people should know about this release
|
||||
> family that may be surprising if they haven't followed the last year of
|
||||
> development closely, or that they must know even if they are too lazy to
|
||||
> read the release notes. If this is a major release that is not
|
||||
> backward-compatible with prior versions, warn about that here.)
|
||||
>
|
||||
> Enjoy, and please report any problems. We will continue to make patch
|
||||
> releases to the 1.2 family roughly monthly, which will contain bug fixes
|
||||
> and non-breaking enhancements.
|
||||
>
|
||||
> The older 1.1 series of releases is now considered obsolete. We will
|
||||
> continue for now to make 1.1 patch releases, but over time, these will
|
||||
> become less frequent and be reserved for only the most critical bug
|
||||
> fixes.
|
||||
>
|
||||
> The "main" branch is now progressing toward an eventual 1.3 release next
|
||||
> summer. As usual, you are welcome to use main for real work, but we do
|
||||
> not make any compatibility guarantees and don't guarantee continuing API
|
||||
> compatibility in main.
|
||||
>
|
||||
> (Paste the full set of 1.2 changes here, just copy the appropriate
|
||||
> part of CHANGES.md)
|
||||
|
||||
For a beta leading up to the annual major/minor release:
|
||||
|
||||
> OSL version 1.2 is now in beta, tagged as "v1.2.3.4-beta". We
|
||||
> will try very hard not to make any further API or ABI changes between
|
||||
> now and the final release (unless it is absolutely necessary to fix
|
||||
> an important problem identified during beta testing). The final 1.2
|
||||
> release is scheduled for [DATE GOES HERE], so please try building and
|
||||
> testing the beta so we are sure to find any problems.
|
||||
>
|
||||
> Release notes for 1.2 outlining all the changes since last year's
|
||||
> release are below.
|
||||
>
|
||||
> (Paste the full set of 1.2 changes here, just copy the appropriate
|
||||
> part of CHANGES.md)
|
||||
|
||||
|
||||
### After the release
|
||||
|
||||
Odds and ends to do after the tag is pushed and the announcements are sent:
|
||||
|
||||
- Re-read RELEASING.md and ensure that the instructions match what you
|
||||
have done. Update as necessary.
|
||||
|
||||
- For annual beta releases, post a short message to the "Open Shading
|
||||
Language" channel of the ASWF slack. It can be a one-line announcement and
|
||||
then just a link to the GitHub release page for this version.
|
||||
|
||||
|
||||
@@ -181,14 +181,14 @@ else ifeq (${platform}, macosx)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=gcc-9 -DCMAKE_CXX_COMPILER=g++-9
|
||||
USE_LIBCPLUSPLUS := 0
|
||||
else ifeq (${COMPILER},clang11)
|
||||
else ifeq (${COMPILER},clang14)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@11/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@11/bin/clang++
|
||||
else ifeq (${COMPILER},clang12)
|
||||
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@14/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@14/bin/clang++
|
||||
else ifeq (${COMPILER},clang15)
|
||||
MY_CMAKE_FLAGS += \
|
||||
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@12/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@12/bin/clang++
|
||||
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@15/bin/clang \
|
||||
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@15/bin/clang++
|
||||
else ifeq (${COMPILER},clang)
|
||||
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
||||
else ifeq (${COMPILER},gcc)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright Contributors to the Open Shading Language Project.
|
||||
|
||||
sonar.host.url=https://sonarcloud.io
|
||||
|
||||
# Required metadata
|
||||
sonar.organization=academysoftwarefoundation
|
||||
sonar.projectName=OpenShadingLanguage
|
||||
sonar.projectVersion=1.12
|
||||
sonar.projectKey=AcademySoftwareFoundation_OpenShadingLanguage
|
||||
|
||||
# Project links
|
||||
sonar.links.homepage=https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
sonar.links.ci=https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/actions
|
||||
sonar.links.scm=https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
sonar.links.issue=https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/issues
|
||||
|
||||
# Source properties
|
||||
sonar.sources=src
|
||||
sonar.sourceEncoding=UTF-8
|
||||
sonar.exclusions=src/include/OSL/Imath/*.h,src/build-scripts/*
|
||||
|
||||
# C/C++ analyzer properties
|
||||
sonar.cfamily.build-wrapper-output=build/bw_output
|
||||
sonar.cfamily.gcov.reportsPath=_coverage
|
||||
|
||||
sonar.cfamily.cache.enabled=true
|
||||
sonar.cfamily.cache.path=/tmp/sonarcache
|
||||
@@ -29,7 +29,10 @@ if [[ `uname` == "Linux" ]] ; then
|
||||
fi
|
||||
LLVMTAR=clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-${LLVM_DISTRO_NAME}.tar.xz
|
||||
echo LLVMTAR = $LLVMTAR
|
||||
if [[ "$LLVM_VERSION" == "10.0.0" ]] || [[ "$LLVM_VERSION" == "11.0.0" ]] || [[ "$LLVM_VERSION" == "11.1.0" ]] || [[ "$LLVM_VERSION" == "12.0.0" ]] || [[ "$LLVM_VERSION" == "13.0.0" ]] ; then
|
||||
if [[ "$LLVM_VERSION" == "10.0.0" ]] || [[ "$LLVM_VERSION" == "11.0.0" ]] \
|
||||
|| [[ "$LLVM_VERSION" == "11.1.0" ]] || [[ "$LLVM_VERSION" == "12.0.0" ]] \
|
||||
|| [[ "$LLVM_VERSION" == "13.0.0" ]] || [[ "$LLVM_VERSION" == "14.0.0" ]] ;
|
||||
then
|
||||
# new
|
||||
curl --location https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/${LLVMTAR} -o $LLVMTAR
|
||||
else
|
||||
|
||||
@@ -15,7 +15,7 @@ OPENCOLORIO_VERSION=${OPENCOLORIO_VERSION:=v1.1.1}
|
||||
|
||||
# Where to install the final results
|
||||
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
|
||||
OPENCOLORIO_SOURCE_DIR=${OPENCOLORIO_BUILD_DIR:=${LOCAL_DEPS_DIR}/OpenColorIO}
|
||||
OPENCOLORIO_SOURCE_DIR=${OPENCOLORIO_SOURCE_DIR:=${LOCAL_DEPS_DIR}/OpenColorIO}
|
||||
OPENCOLORIO_BUILD_DIR=${OPENCOLORIO_BUILD_DIR:=${LOCAL_DEPS_DIR}/OpenColorIO-build}
|
||||
OPENCOLORIO_INSTALL_DIR=${OPENCOLORIO_INSTALL_DIR:=${LOCAL_DEPS_DIR}/dist}
|
||||
OPENCOLORIO_CXX_FLAGS=${OPENCOLORIO_CXX_FLAGS:="-Wno-unused-function -Wno-deprecated-declarations -Wno-cast-qual -Wno-write-strings"}
|
||||
@@ -25,7 +25,7 @@ OPENCOLORIO_BUILDOPTS="-DOCIO_BUILD_APPS=OFF -DOCIO_BUILD_NUKE=OFF \
|
||||
-DOCIO_BUILD_GPU_TESTS=OFF \
|
||||
-DOCIO_BUILD_PYTHON=OFF -DOCIO_BUILD_PYGLUE=OFF \
|
||||
-DOCIO_BUILD_JAVA=OFF \
|
||||
-DOCIO_BUILD_STATIC=${OCIO_BUILD_STATIC:=OFF}"
|
||||
-DBUILD_SHARED_LIBS=${OPENCOLORIO_BUILD_SHARED_LIBS:=ON}"
|
||||
BASEDIR=`pwd`
|
||||
pwd
|
||||
echo "OpenColorIO install dir will be: ${OPENCOLORIO_INSTALL_DIR}"
|
||||
@@ -34,20 +34,20 @@ mkdir -p ${LOCAL_DEPS_DIR}
|
||||
pushd ${LOCAL_DEPS_DIR}
|
||||
|
||||
# Clone OpenColorIO project from GitHub and build
|
||||
if [[ ! -e OpenColorIO ]] ; then
|
||||
echo "git clone ${OPENCOLORIO_REPO} OpenColorIO"
|
||||
git clone ${OPENCOLORIO_REPO} OpenColorIO
|
||||
if [[ ! -e ${OPENCOLORIO_SOURCE_DIR} ]] ; then
|
||||
echo "git clone ${OPENCOLORIO_REPO} ${OPENCOLORIO_SOURCE_DIR}"
|
||||
git clone ${OPENCOLORIO_REPO} ${OPENCOLORIO_SOURCE_DIR}
|
||||
fi
|
||||
cd OpenColorIO
|
||||
cd ${OPENCOLORIO_SOURCE_DIR}
|
||||
|
||||
echo "git checkout ${OPENCOLORIO_VERSION} --force"
|
||||
git checkout ${OPENCOLORIO_VERSION} --force
|
||||
mkdir -p build
|
||||
cd build
|
||||
mkdir -p ${OPENCOLORIO_BUILD_DIR}
|
||||
cd ${OPENCOLORIO_BUILD_DIR}
|
||||
time cmake -DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX=${OPENCOLORIO_INSTALL_DIR} \
|
||||
-DCMAKE_CXX_FLAGS="${OPENCOLORIO_CXX_FLAGS}" \
|
||||
${OPENCOLORIO_BUILDOPTS} ..
|
||||
${OPENCOLORIO_BUILDOPTS} ${OPENCOLORIO_SOURCE_DIR}
|
||||
time cmake --build . --config Release --target install
|
||||
popd
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ OPENEXR_SOURCE_DIR=${OPENEXR_SOURCE_DIR:=${LOCAL_DEPS_DIR}/openexr}
|
||||
OPENEXR_BUILD_DIR=${OPENEXR_BUILD_DIR:=${LOCAL_DEPS_DIR}/openexr-build}
|
||||
OPENEXR_INSTALL_DIR=${OPENEXR_INSTALL_DIR:=${LOCAL_DEPS_DIR}/dist}
|
||||
OPENEXR_BUILD_TYPE=${OPENEXR_BUILD_TYPE:=Release}
|
||||
CMAKE_GENERATOR=${CMAKE_GENERATOR:="Unix Makefiles"}
|
||||
OPENEXR_CMAKE_FLAGS=${OPENEXR_CMAKE_FLAGS:=""}
|
||||
OPENEXR_CXX_FLAGS=${OPENEXR_CXX_FLAGS:=""}
|
||||
BASEDIR=$PWD
|
||||
@@ -29,19 +28,14 @@ pwd
|
||||
echo "Building OpenEXR ${OPENEXR_VERSION}"
|
||||
echo "OpenEXR build dir will be: ${OPENEXR_BUILD_DIR}"
|
||||
echo "OpenEXR install dir will be: ${OPENEXR_INSTALL_DIR}"
|
||||
echo "CMAKE_PREFIX_PATH is ${CMAKE_PREFIX_PATH}"
|
||||
echo "OpenEXR Build type is ${OPENEXR_BUILD_TYPE}"
|
||||
|
||||
if [[ "$CMAKE_GENERATOR" == "" ]] ; then
|
||||
OPENEXR_GENERATOR_CMD="-G \"$CMAKE_GENERATOR\""
|
||||
fi
|
||||
echo "CMAKE_PREFIX_PATH is ${CMAKE_PREFIX_PATH}"
|
||||
|
||||
# Clone OpenEXR project (including IlmBase) from GitHub and build
|
||||
if [[ ! -e ${OPENEXR_SOURCE_DIR} ]] ; then
|
||||
echo "git clone ${OPENEXR_REPO} ${OPENEXR_SOURCE_DIR}"
|
||||
git clone ${OPENEXR_REPO} ${OPENEXR_SOURCE_DIR}
|
||||
fi
|
||||
|
||||
mkdir -p ${OPENEXR_INSTALL_DIR} && true
|
||||
mkdir -p ${OPENEXR_BUILD_DIR} && true
|
||||
|
||||
@@ -51,7 +45,7 @@ git checkout ${OPENEXR_VERSION} --force
|
||||
if [[ ${OPENEXR_VERSION} == "v2.3.0" ]] ; then
|
||||
# Simplified setup for 2.3+
|
||||
cd ${OPENEXR_BUILD_DIR}
|
||||
cmake -DCMAKE_BUILD_TYPE=${OPENEXR_BUILD_TYPE} -G "$CMAKE_GENERATOR" \
|
||||
cmake -DCMAKE_BUILD_TYPE=${OPENEXR_BUILD_TYPE} \
|
||||
-DCMAKE_INSTALL_PREFIX="${OPENEXR_INSTALL_DIR}" \
|
||||
-DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}" \
|
||||
-DILMBASE_PACKAGE_PREFIX="${OPENEXR_INSTALL_DIR}" \
|
||||
@@ -64,7 +58,7 @@ if [[ ${OPENEXR_VERSION} == "v2.3.0" ]] ; then
|
||||
else
|
||||
# Simplified setup for 2.4+
|
||||
cd ${OPENEXR_BUILD_DIR}
|
||||
cmake -DCMAKE_BUILD_TYPE=${OPENEXR_BUILD_TYPE} -G "$CMAKE_GENERATOR" \
|
||||
cmake -DCMAKE_BUILD_TYPE=${OPENEXR_BUILD_TYPE} \
|
||||
-DCMAKE_INSTALL_PREFIX="${OPENEXR_INSTALL_DIR}" \
|
||||
-DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}" \
|
||||
-DILMBASE_PACKAGE_PREFIX="${OPENEXR_INSTALL_DIR}" \
|
||||
@@ -92,5 +86,3 @@ export ILMBASE_LIBRARY_DIR=$OPENEXR_INSTALL_DIR/lib
|
||||
export OPENEXR_LIBRARY_DIR=$OPENEXR_INSTALL_DIR/lib
|
||||
export LD_LIBRARY_PATH=$OPENEXR_ROOT/lib:$LD_LIBRARY_PATH
|
||||
|
||||
export ILMBASE_ROOT_DIR=$OPENEXR_INSTALL_DIR
|
||||
export OPENEXR_ROOT_DIR=$OPENEXR_INSTALL_DIR
|
||||
|
||||
@@ -12,6 +12,10 @@ if [[ "$USE_SIMD" != "" ]] ; then
|
||||
OSL_CMAKE_FLAGS="$OSL_CMAKE_FLAGS -DUSE_SIMD=$USE_SIMD"
|
||||
fi
|
||||
|
||||
if [[ -n "$CODECOV" ]] ; then
|
||||
OSL_CMAKE_FLAGS="$OSL_CMAKE_FLAGS -DCODECOV=${CODECOV}"
|
||||
fi
|
||||
|
||||
pushd build
|
||||
cmake .. -G "$CMAKE_GENERATOR" \
|
||||
-DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" \
|
||||
@@ -23,7 +27,16 @@ cmake .. -G "$CMAKE_GENERATOR" \
|
||||
-DCMAKE_INSTALL_LIBDIR="$OSL_ROOT/lib" \
|
||||
-DCMAKE_CXX_STANDARD="$CMAKE_CXX_STANDARD" \
|
||||
$OSL_CMAKE_FLAGS -DVERBOSE=1
|
||||
time cmake --build . --target ${BUILDTARGET:=install} --config ${CMAKE_BUILD_TYPE}
|
||||
|
||||
# Save a copy of the generated files for debugging broken CI builds.
|
||||
mkdir cmake-save || /bin/true
|
||||
cp -r CMake* *.cmake cmake-save
|
||||
|
||||
: ${BUILDTARGET:=install}
|
||||
if [[ "$BUILDTARGET" != "none" ]] ; then
|
||||
echo "Parallel build ${CMAKE_BUILD_PARALLEL_LEVEL} of target ${BUILDTARGET}"
|
||||
time ${OSL_CMAKE_BUILD_WRAPPER} cmake --build . --target ${BUILDTARGET} --config ${CMAKE_BUILD_TYPE}
|
||||
fi
|
||||
popd
|
||||
|
||||
if [[ "${DEBUG_CI:=0}" != "0" ]] ; then
|
||||
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Run code coverage analysis
|
||||
# This assumes that the build occurred with CODECOV=1 andtests have already
|
||||
# fully run.
|
||||
|
||||
set -ex
|
||||
|
||||
echo "Performing code coverage analysis"
|
||||
mkdir _coverage
|
||||
pushd _coverage
|
||||
|
||||
ls -R ../build/src/
|
||||
|
||||
# Remove files or directories we want to exclude from code coverage analysis,
|
||||
# generally because we don't expect to execute any of their code during our
|
||||
# CI. (Because it's only used interactively, or is fallback code only used
|
||||
# when certain dependencies are not found.) Including these when we know we
|
||||
# won't be calling them during coverage gathering will just make our coverage
|
||||
# percentage look artifically low.
|
||||
rm -f ../build/src/osltoy/CMakeFiles/osltoy.dir/*.cpp.{gcno,gcda}
|
||||
|
||||
|
||||
# The sed command below converts from:
|
||||
# ../build/src/liboslexec/CMakeFiles/oslexec.dir/foo.gcno
|
||||
# to:
|
||||
# ../src/liboslexec/foo.cpp
|
||||
|
||||
for g in $(find ../build -name "*.gcno" -type f); do
|
||||
echo "Processing $g"
|
||||
echo "dirname $g = $(dirname $g) to " `$(echo "$g" | sed -e 's/\/build\//\//' -e 's/\.gcno/\.cpp/' -e 's/\.cpp\.cpp/\.cpp/' -e 's/\/CMakeFiles.*\.dir\//\//')`
|
||||
gcov -l -p -o $(dirname "$g") $(echo "$g" | sed -e 's/\/build\//\//' -e 's/\.gcno/\.cpp/' -e 's/\/CMakeFiles.*\.dir\//\//')
|
||||
done
|
||||
popd
|
||||
@@ -23,7 +23,7 @@ export DYLD_LIBRARY_PATH=$OSL_ROOT/lib:$DYLD_LIBRARY_PATH
|
||||
export LD_LIBRARY_PATH=$OSL_ROOT/lib:$LD_LIBRARY_PATH
|
||||
export OIIO_LIBRARY_PATH=$OSL_ROOT/lib:${OIIO_LIBRARY_PATH}
|
||||
export LSAN_OPTIONS=suppressions=$PWD/src/build-scripts/nosanitize.txt
|
||||
export ASAN_OPTIONS=print_suppressions=0
|
||||
export ASAN_OPTIONS=print_suppressions=0:detect_odr_violation=1
|
||||
|
||||
export USE_PYTHON=${USE_PYTHON:=1}
|
||||
export PYTHON_VERSION=${PYTHON_VERSION:="2.7"}
|
||||
@@ -61,6 +61,7 @@ echo "uname -a: " `uname -a`
|
||||
echo "uname -m: " `uname -m`
|
||||
echo "uname -s: " `uname -s`
|
||||
echo "uname -n: " `uname -n`
|
||||
echo "nproc " `nproc`
|
||||
pwd
|
||||
ls
|
||||
env | sort
|
||||
|
||||
@@ -8,12 +8,26 @@
|
||||
# any command in it fails. This is crucial for CI tests.
|
||||
set -ex
|
||||
|
||||
: ${CTEST_EXCLUSIONS:="broken"}
|
||||
: ${CTEST_TEST_TIMEOUT:=60}
|
||||
|
||||
$OSL_ROOT/bin/testshade --help
|
||||
|
||||
echo "Parallel test " ${CTEST_PARALLEL_LEVEL}
|
||||
echo "Parallel test ${CTEST_PARALLEL_LEVEL}"
|
||||
echo "Default timeout ${CTEST_TEST_TIMEOUT}"
|
||||
echo "Test exclusions '${CTEST_EXCLUSIONS}'"
|
||||
echo "CTEST_ARGS '${CTEST_ARGS}'"
|
||||
|
||||
pushd build
|
||||
time ctest -C ${CMAKE_BUILD_TYPE} -E broken --force-new-ctest-process \
|
||||
--output-on-failure --timeout ${CTEST_TEST_TIMEOUT:=60} ${CTEST_ARGS}
|
||||
|
||||
ctest -C ${CMAKE_BUILD_TYPE} --force-new-ctest-process --output-on-failure \
|
||||
--timeout ${CTEST_TEST_TIMEOUT} -E "${CTEST_EXCLUSIONS}" ${CTEST_ARGS} \
|
||||
|| \
|
||||
ctest -C ${CMAKE_BUILD_TYPE} --force-new-ctest-process \
|
||||
--rerun-failed --repeat until-pass:5 -R render --output-on-failure \
|
||||
--timeout ${CTEST_TEST_TIMEOUT} -E "${CTEST_EXCLUSIONS}" ${CTEST_ARGS}
|
||||
# The weird construct above allows the render-* tests to run multiple times
|
||||
|
||||
popd
|
||||
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ from __future__ import print_function, absolute_import
|
||||
###
|
||||
### Only one main doc region will be output by the `docdeep` program,
|
||||
### specified with the `-d` command line argument. Any other doc-regions
|
||||
### will not be included in the documention output of that run.
|
||||
### will not be included in the documentation output of that run.
|
||||
###
|
||||
### However, one doc-region may *include* the text of another doc-region
|
||||
### as follows:
|
||||
@@ -114,7 +114,7 @@ from __future__ import print_function, absolute_import
|
||||
### For pre-code comments, the contiguous comment region associated with
|
||||
### a declaration immediately precedes the declaration. Such a comment
|
||||
### set has its first line start with `///>`. For post-code comments,
|
||||
### the documentaiton comments follows the code declaration, and this is
|
||||
### the documentation comments follows the code declaration, and this is
|
||||
### designated by having its first line start with `///<`. I like to
|
||||
### just remember that the `<` or `>` points in the direction of the code
|
||||
### declaration that the comment applies to.
|
||||
|
||||
@@ -19,9 +19,7 @@ if [[ "$ASWF_ORG" != "" ]] ; then
|
||||
#ls /etc/yum.repos.d
|
||||
|
||||
sudo yum install -y giflib giflib-devel && true
|
||||
sudo yum install -y opencv opencv-devel && true
|
||||
sudo yum install -y Field3D Field3D-devel && true
|
||||
sudo yum install -y ffmpeg ffmpeg-devel && true
|
||||
# sudo yum install -y ffmpeg ffmpeg-devel && true
|
||||
|
||||
if [[ "${CONAN_LLVM_VERSION}" != "" ]] ; then
|
||||
mkdir conan
|
||||
@@ -41,6 +39,25 @@ if [[ "$ASWF_ORG" != "" ]] ; then
|
||||
export LLVM_ROOT=$PWD
|
||||
popd
|
||||
fi
|
||||
|
||||
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-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
|
||||
fi
|
||||
if [[ "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
|
||||
echo "Verifying installation of Intel(r) oneAPI DPC++/C++ Compiler:"
|
||||
icpx --version
|
||||
fi
|
||||
fi
|
||||
|
||||
else
|
||||
# Using native Ubuntu runner
|
||||
|
||||
@@ -51,15 +68,27 @@ else
|
||||
git cmake ninja-build ccache g++ \
|
||||
libboost-dev libboost-thread-dev libboost-filesystem-dev \
|
||||
libilmbase-dev libopenexr-dev \
|
||||
python-dev python-numpy \
|
||||
libtiff-dev libgif-dev libpng-dev \
|
||||
flex bison libbison-dev \
|
||||
libpugixml-dev \
|
||||
libopencolorio-dev \
|
||||
qt5-default
|
||||
libopencolorio-dev
|
||||
|
||||
time sudo apt-get -q install -y \
|
||||
qt5-default || /bin/true
|
||||
|
||||
export CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu:$CMAKE_PREFIX_PATH
|
||||
|
||||
# Nonstandard python versions
|
||||
if [[ "${PYTHON_VERSION}" == "3.9" ]] ; then
|
||||
time sudo apt-get -q install -y python3.9-dev python3-numpy
|
||||
pip3 --version
|
||||
pip3 install numpy
|
||||
elif [[ "$PYTHON_VERSION" == "2.7" ]] ; then
|
||||
time sudo apt-get -q install -y python-dev python-numpy
|
||||
else
|
||||
pip3 install numpy
|
||||
fi
|
||||
|
||||
if [[ "$CXX" == "g++-6" ]] ; then
|
||||
time sudo apt-get install -y g++-6
|
||||
elif [[ "$CXX" == "g++-7" ]] ; then
|
||||
@@ -72,14 +101,20 @@ 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
|
||||
|
||||
# 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
|
||||
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" || "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
|
||||
wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB
|
||||
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=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
|
||||
@@ -118,20 +153,30 @@ fi
|
||||
# fi
|
||||
|
||||
if [[ "$OPENCOLORIO_VERSION" != "" ]] ; then
|
||||
# Temporary (?) fix: GH ninja having problems, fall back to make
|
||||
CMAKE_GENERATOR="Unix Makefiles" \
|
||||
source src/build-scripts/build_opencolorio.bash
|
||||
fi
|
||||
|
||||
if [[ "$OPENIMAGEIO_VERSION" != "" ]] ; then
|
||||
# There are many parts of OIIO we don't need to build
|
||||
# There are many parts of OIIO we don't need to build for OSL's tests
|
||||
export ENABLE_iinfo=0 ENABLE_iv=0 ENABLE_igrep=0
|
||||
export ENABLE_iconvert=0 ENABLE_testtex=0
|
||||
# For speed of compiling OIIO, disable the file formats that we don't
|
||||
# need for OSL's tests
|
||||
export ENABLE_BMP=0 ENABLE_cineon=0 ENABLE_DDS=0 ENABLE_DPX=0 ENABLE_FITS=0
|
||||
export ENABLE_ICO=0 ENABLE_iff=0 ENABLE_jpeg2000=0 ENABLE_PNM=0 ENABLE_PSD=0
|
||||
export ENABLE_RLA=0 ENABLE_SGI=0 ENABLE_SOCKET=0 ENABLE_SOFTIMAGE=0
|
||||
export ENABLE_TARGA=0 ENABLE_WEBP=0
|
||||
export OPENIMAGEIO_CMAKE_FLAGS="-DOIIO_BUILD_TESTS=0 -DUSE_OPENGL=0"
|
||||
# We don't need to run OIIO's tests
|
||||
export OPENIMAGEIO_CMAKE_FLAGS+=" -DOIIO_BUILD_TESTING=OFF -DOIIO_BUILD_TESTS=0"
|
||||
# Don't let warnings in OIIO break OSL's CI run
|
||||
export OPENIMAGEIO_CMAKE_FLAGS+=" -DSTOP_ON_WARNING=OFF"
|
||||
export OPENIMAGEIO_CMAKE_FLAGS+=" -DUSE_OPENGL=0"
|
||||
if [[ $OPENIMAGEIO_VERSION == master && "${OPENIMAGEIO_UNITY:-1}" != "0" ]] ; then
|
||||
# Speed up the OIIO build by doing a "unity" build. (Note: this is
|
||||
# only a savings in CI where there are only 1-2 cores available, and
|
||||
# is only supported for OIIO 2.3.14 and later)
|
||||
export OPENIMAGEIO_CMAKE_FLAGS+=" -DCMAKE_UNITY_BUILD=ON -DCMAKE_UNITY_BUILD_MODE=BATCH"
|
||||
fi
|
||||
source src/build-scripts/build_openimageio.bash
|
||||
fi
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
# This script, which assumes it is runnign on a Mac OSX with Homebrew
|
||||
# This script, which assumes it is running on a Mac OSX with Homebrew
|
||||
# installed, does a "brew install" in all packages reasonably needed by
|
||||
# OSL and its dependencies.
|
||||
|
||||
@@ -20,16 +20,20 @@ if [[ `which brew` == "" ]] ; then
|
||||
fi
|
||||
|
||||
|
||||
#brew update >/dev/null
|
||||
if [[ "$DO_BREW_UPDATE" != "" ]] ; then
|
||||
brew update >/dev/null
|
||||
fi
|
||||
echo ""
|
||||
echo "Before my brew installs:"
|
||||
brew list --versions
|
||||
|
||||
brew install --display-times -q gcc ccache cmake ninja boost || true
|
||||
brew link --overwrite gcc
|
||||
brew install --display-times -q python@${PYTHON_VERSION} || true
|
||||
brew unlink python@2.7 || true
|
||||
brew unlink python@3.9 || true
|
||||
brew unlink python@3.8 || true
|
||||
brew unlink python@3.9 || true
|
||||
brew unlink python@3.10 || true
|
||||
brew link --overwrite --force python@${PYTHON_VERSION} || true
|
||||
brew upgrade --display-times -q cmake || true
|
||||
brew install --display-times -q ilmbase openexr
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
leak:Imf_2_2
|
||||
leak:Imf_2_3
|
||||
leak:Imf_2_4
|
||||
leak:libIlmImf
|
||||
leak:oslgram.y
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
[oneAPI]
|
||||
name=Intel® oneAPI repository
|
||||
baseurl=https://yum.repos.intel.com/oneapi
|
||||
enabled=1
|
||||
gpgcheck=1
|
||||
repo_gpgcheck=1
|
||||
gpgkey=https://yum.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB
|
||||
@@ -0,0 +1,3 @@
|
||||
default=exclude
|
||||
compiler=2022.1.0
|
||||
tbb=2021.6.0
|
||||
Regular → Executable
+1
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
@@ -8,7 +8,7 @@ include(CMakeFindDependencyMacro)
|
||||
|
||||
# add here all the find_dependency() whenever switching to config based dependencies
|
||||
if (@OpenEXR_VERSION@ VERSION_GREATER_EQUAL 3.0)
|
||||
find_dependency(Imath @OpenEXR_VERSION@)
|
||||
find_dependency(Imath @Imath_VERSION@)
|
||||
elseif (@OpenEXR_VERSION@ VERSION_GREATER_EQUAL 2.4 AND @FOUND_OPENEXR_WITH_CONFIG@)
|
||||
find_dependency(IlmBase @OpenEXR_VERSION@)
|
||||
find_dependency(OpenEXR @OpenEXR_VERSION@)
|
||||
@@ -19,9 +19,16 @@ endif ()
|
||||
|
||||
find_dependency(OpenImageIO @OpenImageIO_VERSION@ REQUIRED)
|
||||
|
||||
set_and_check (@PROJECT_NAME@_INCLUDE_DIR "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
|
||||
set_and_check (@PROJECT_NAME@_INCLUDES "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
|
||||
set_and_check (@PROJECT_NAME@_LIB_DIR "@CMAKE_INSTALL_FULL_LIBDIR@")
|
||||
# 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 absolute paths
|
||||
get_filename_component(_INCLUDE_DIR_NAME "@CMAKE_INSTALL_INCLUDEDIR@" NAME)
|
||||
get_filename_component(_LIB_DIR_NAME "@CMAKE_INSTALL_LIBDIR@" NAME)
|
||||
|
||||
set_and_check (@PROJECT_NAME@_INCLUDE_DIR "${_IMPORT_PREFIX}/${_INCLUDE_DIR_NAME}")
|
||||
set_and_check (@PROJECT_NAME@_INCLUDES "${_IMPORT_PREFIX}/${_INCLUDE_DIR_NAME}")
|
||||
set_and_check (@PROJECT_NAME@_LIB_DIR "${_IMPORT_PREFIX}/${_LIB_DIR_NAME}")
|
||||
|
||||
#...logic to determine installedPrefix from the own location...
|
||||
#set (@PROJECT_NAME@_CONFIG_DIR "${installedPrefix}/@CONFIG_INSTALL_DIR@")
|
||||
|
||||
@@ -3,10 +3,27 @@
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
|
||||
set (REQUIED_DEPS "" CACHE STRING
|
||||
set (REQUIRED_DEPS "" CACHE STRING
|
||||
"Additional dependencies to consider required (semicolon-separated list, or ALL)")
|
||||
set (OPTIONAL_DEPS "" CACHE STRING
|
||||
"Additional dependencies to consider optional (semicolon-separated list, or ALL)")
|
||||
option (ALWAYS_PREFER_CONFIG "Prefer a dependency's exported config file if it's available" OFF)
|
||||
|
||||
|
||||
# Utility function to list the names and values of all variables matching
|
||||
# the pattern (case-insensitive)
|
||||
function (dump_matching_variables pattern)
|
||||
string (TOLOWER ${pattern} _pattern_lower)
|
||||
get_cmake_property(_allvars VARIABLES)
|
||||
list (SORT _allvars)
|
||||
foreach (_var IN LISTS _allvars)
|
||||
string (TOLOWER ${_var} _var_lower)
|
||||
if (_var_lower MATCHES ${_pattern_lower})
|
||||
message (STATUS " ${_var} = ${${_var}}")
|
||||
endif ()
|
||||
endforeach ()
|
||||
endfunction ()
|
||||
|
||||
|
||||
|
||||
# checked_find_package(Pkgname ...) is a wrapper for find_package, with the
|
||||
@@ -20,8 +37,11 @@ set (OPTIONAL_DEPS "" CACHE STRING
|
||||
# turned off explicitly from one of these sources.
|
||||
# * Print a message if the package is enabled but not found. This is based
|
||||
# on ${Pkgname}_FOUND or $PKGNAME_FOUND.
|
||||
# * Optional DEFINITIONS <string> are passed to add_definitions if the
|
||||
# * Optional DEFINITIONS <string>... are passed to add_definitions if the
|
||||
# package is found.
|
||||
# * Optional SETVARIABLES <id>... is a list of CMake variables to set to
|
||||
# TRUE if the package is found (they will not be set or changed if the
|
||||
# package is not found).
|
||||
# * Optional PRINT <list> is a list of variables that will be printed
|
||||
# if the package is found, if VERBOSE is on.
|
||||
# * Optional DEPS <list> is a list of hard dependencies; for each one, if
|
||||
@@ -42,6 +62,10 @@ set (OPTIONAL_DEPS "" CACHE STRING
|
||||
# version, accepting but warning if it is below this number (even
|
||||
# if above the true minimum version accepted). The warning message
|
||||
# can give an optional explanation, passed as RECOMMEND_MIN_REASON.
|
||||
# * Optional PREFER_CONFIG, if supplied, tries to use an exported config
|
||||
# file from the package before using a FindPackage.cmake module.
|
||||
# * Optional DEBUG turns on extra debugging information related to how
|
||||
# this package is found.
|
||||
#
|
||||
# N.B. This needs to be a macro, not a function, because the find modules
|
||||
# will set(blah val PARENT_SCOPE) and we need that to be the global scope,
|
||||
@@ -49,16 +73,20 @@ set (OPTIONAL_DEPS "" CACHE STRING
|
||||
macro (checked_find_package pkgname)
|
||||
cmake_parse_arguments(_pkg # prefix
|
||||
# noValueKeywords:
|
||||
"REQUIRED"
|
||||
"REQUIRED;PREFER_CONFIG;DEBUG"
|
||||
# singleValueKeywords:
|
||||
"ENABLE;ISDEPOF;VERSION_MIN;VERSION_MAX;RECOMMEND_MIN;RECOMMEND_MIN_REASON"
|
||||
# multiValueKeywords:
|
||||
"DEFINITIONS;PRINT;DEPS"
|
||||
"DEFINITIONS;PRINT;DEPS;SETVARIABLES"
|
||||
# argsToParse:
|
||||
${ARGN})
|
||||
string (TOLOWER ${pkgname} pkgname_lower)
|
||||
string (TOUPPER ${pkgname} pkgname_upper)
|
||||
if (NOT VERBOSE)
|
||||
set (_pkg_VERBOSE ${VERBOSE})
|
||||
if (_pkg_DEBUG)
|
||||
set (_pkg_VERBOSE ON)
|
||||
endif ()
|
||||
if (NOT _pkg_VERBOSE)
|
||||
set (${pkgname}_FIND_QUIETLY true)
|
||||
set (${pkgname_upper}_FIND_QUIETLY true)
|
||||
endif ()
|
||||
@@ -85,8 +113,19 @@ macro (checked_find_package pkgname)
|
||||
set (_quietskip true)
|
||||
endif ()
|
||||
endif ()
|
||||
set (_config_status "")
|
||||
if (_enable OR _pkg_REQUIRED)
|
||||
find_package (${pkgname} ${_pkg_UNPARSED_ARGUMENTS})
|
||||
if (${pkgname}_FOUND OR ${pkgname_upper}_FOUND)
|
||||
# was already found
|
||||
elseif (_pkg_PREFER_CONFIG OR ALWAYS_PREFER_CONFIG)
|
||||
find_package (${pkgname} CONFIG ${_pkg_UNPARSED_ARGUMENTS})
|
||||
if (${pkgname}_FOUND OR ${pkgname_upper}_FOUND)
|
||||
set (_config_status "from CONFIG")
|
||||
endif ()
|
||||
endif ()
|
||||
if (NOT (${pkgname}_FOUND OR ${pkgname_upper}_FOUND))
|
||||
find_package (${pkgname} ${_pkg_UNPARSED_ARGUMENTS})
|
||||
endif()
|
||||
if ((${pkgname}_FOUND OR ${pkgname_upper}_FOUND)
|
||||
AND ${pkgname}_VERSION
|
||||
AND (_pkg_VERSION_MIN OR _pkg_VERSION_MAX))
|
||||
@@ -106,21 +145,11 @@ macro (checked_find_package pkgname)
|
||||
set (${pkgname}_VERSION ${${_vervar}})
|
||||
endif ()
|
||||
endforeach ()
|
||||
message (STATUS "${ColorGreen}Found ${pkgname} ${${pkgname}_VERSION} ${ColorReset}")
|
||||
if (VERBOSE)
|
||||
set (_vars_to_print ${pkgname}_INCLUDES ${pkgname_upper}_INCLUDES
|
||||
${pkgname}_INCLUDE_DIR ${pkgname_upper}_INCLUDE_DIR
|
||||
${pkgname}_INCLUDE_DIRS ${pkgname_upper}_INCLUDE_DIRS
|
||||
${pkgname}_LIBRARIES ${pkgname_upper}_LIBRARIES
|
||||
${_pkg_PRINT})
|
||||
list (REMOVE_DUPLICATES _vars_to_print)
|
||||
foreach (_v IN LISTS _vars_to_print)
|
||||
if (NOT "${${_v}}" STREQUAL "")
|
||||
message (STATUS " ${_v} = ${${_v}}")
|
||||
endif ()
|
||||
endforeach ()
|
||||
endif ()
|
||||
message (STATUS "${ColorGreen}Found ${pkgname} ${${pkgname}_VERSION} ${_config_status}${ColorReset}")
|
||||
add_definitions (${_pkg_DEFINITIONS})
|
||||
foreach (_v IN LISTS _pkg_SETVARIABLES)
|
||||
set (${_v} TRUE)
|
||||
endforeach ()
|
||||
if (_pkg_RECOMMEND_MIN)
|
||||
if (${${pkgname}_VERSION} VERSION_LESS ${_pkg_RECOMMEND_MIN})
|
||||
message (STATUS "${ColorYellow}Recommend ${pkgname} >= ${_pkg_RECOMMEND_MIN} ${_pkg_RECOMMEND_MIN_REASON} ${ColorReset}")
|
||||
@@ -148,6 +177,22 @@ macro (checked_find_package pkgname)
|
||||
message (FATAL_ERROR "${ColorRed}${pkgname} is required, aborting.${ColorReset}")
|
||||
endif ()
|
||||
endif()
|
||||
if (_pkg_VERBOSE AND (${pkgname}_FOUND OR ${pkgname_upper}_FOUND OR _pkg_DEBUG))
|
||||
if (_pkg_DEBUG)
|
||||
dump_matching_variables (${pkgname})
|
||||
endif ()
|
||||
set (_vars_to_print ${pkgname}_INCLUDES ${pkgname_upper}_INCLUDES
|
||||
${pkgname}_INCLUDE_DIR ${pkgname_upper}_INCLUDE_DIR
|
||||
${pkgname}_INCLUDE_DIRS ${pkgname_upper}_INCLUDE_DIRS
|
||||
${pkgname}_LIBRARIES ${pkgname_upper}_LIBRARIES
|
||||
${_pkg_PRINT})
|
||||
list (REMOVE_DUPLICATES _vars_to_print)
|
||||
foreach (_v IN LISTS _vars_to_print)
|
||||
if (NOT "${${_v}}" STREQUAL "")
|
||||
message (STATUS " ${_v} = ${${_v}}")
|
||||
endif ()
|
||||
endforeach ()
|
||||
endif ()
|
||||
else ()
|
||||
if (NOT _quietskip)
|
||||
message (STATUS "${ColorRed}Not using ${pkgname} -- disabled ${_disablereason} ${ColorReset}")
|
||||
|
||||
+46
-56
@@ -28,10 +28,12 @@ message (STATUS "CMAKE_CXX_COMPILER_ID = ${CMAKE_CXX_COMPILER_ID}")
|
||||
# C++ language standard
|
||||
#
|
||||
set (CMAKE_CXX_STANDARD 14 CACHE STRING
|
||||
"C++ standard to prefer (14, 17, 20, etc.)")
|
||||
"C++ standard to build with (14, 17, 20, etc.)")
|
||||
set (DOWNSTREAM_CXX_STANDARD 14 CACHE STRING
|
||||
"C++ minimum standard to impose on downstream clients")
|
||||
set (CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set (CMAKE_CXX_EXTENSIONS OFF)
|
||||
message (STATUS "Building for C++${CMAKE_CXX_STANDARD}")
|
||||
message (STATUS "Building with C++${CMAKE_CXX_STANDARD}, downstream minimum C++${DOWNSTREAM_CXX_STANDARD}")
|
||||
|
||||
|
||||
###########################################################################
|
||||
@@ -49,7 +51,8 @@ else ()
|
||||
set (GCC_VERSION 0)
|
||||
endif ()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER MATCHES "[Cc]lang")
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER MATCHES "[Cc]lang"
|
||||
OR CMAKE_CXX_COMPILER_ID MATCHES "IntelLLVM")
|
||||
# If using any flavor of clang, set CMAKE_COMPILER_IS_CLANG. If it's
|
||||
# Apple's variety, set CMAKE_COMPILER_IS_APPLECLANG and
|
||||
# APPLECLANG_VERSION_STRING, otherwise for generic clang set
|
||||
@@ -63,6 +66,12 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER MATCHES "[Cc]lan
|
||||
if (VERBOSE)
|
||||
message (STATUS "The compiler is Clang: ${CMAKE_CXX_COMPILER_ID} version ${APPLECLANG_VERSION_STRING}")
|
||||
endif ()
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "IntelLLVM")
|
||||
set (CMAKE_COMPILER_IS_INTELCLANG 1)
|
||||
string (REGEX MATCH "[0-9]+(\\.[0-9]+)+" INTELCLANG_VERSION_STRING ${clang_full_version_string})
|
||||
if (VERBOSE)
|
||||
message (STATUS "The compiler is Intel Clang: ${CMAKE_CXX_COMPILER_ID} version ${INTELCLANG_VERSION_STRING}")
|
||||
endif ()
|
||||
else ()
|
||||
string (REGEX REPLACE ".* version ([0-9]+\\.[0-9]+).*" "\\1" CLANG_VERSION_STRING ${clang_full_version_string})
|
||||
if (VERBOSE)
|
||||
@@ -80,10 +89,14 @@ endif ()
|
||||
###########################################################################
|
||||
# Turn on more detailed warnings and optionally consider warnings as errors
|
||||
#
|
||||
if (${PROJECT_NAME}_SUPPORTED_RELEASE)
|
||||
option (STOP_ON_WARNING "Stop building if there are any compiler warnings" OFF)
|
||||
else ()
|
||||
if (NOT ${PROJECT_NAME}_SUPPORTED_RELEASE OR DEFINED ENV{${PROJECT_NAME}_CI})
|
||||
# For development branches (i.e., not a supported release), or when
|
||||
# running CI, default to treating all warnings as errors.
|
||||
option (STOP_ON_WARNING "Stop building if there are any compiler warnings" ON)
|
||||
else ()
|
||||
# For release branches not doing a CI build default to just printing
|
||||
# warnings but not letting them stop the build.
|
||||
option (STOP_ON_WARNING "Stop building if there are any compiler warnings" OFF)
|
||||
endif()
|
||||
option (EXTRA_WARNINGS "Enable lots of extra pedantic warnings" OFF)
|
||||
if (NOT MSVC)
|
||||
@@ -91,10 +104,8 @@ if (NOT MSVC)
|
||||
if (EXTRA_WARNINGS)
|
||||
add_compile_options ("-Wextra")
|
||||
endif ()
|
||||
if (STOP_ON_WARNING OR DEFINED ENV{${PROJECT_NAME}_CI})
|
||||
if (STOP_ON_WARNING)
|
||||
add_compile_options ("-Werror")
|
||||
# N.B. Force CI builds to use -Werror, even if STOP_ON_WARNING has
|
||||
# been switched off by default, which we may do in release branches.
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
@@ -114,7 +125,7 @@ set (CXX_VISIBILITY_PRESET "hidden" CACHE STRING "Symbol visibility (hidden or d
|
||||
option (VISIBILITY_INLINES_HIDDEN "Hide symbol visibility of inline functions" ON)
|
||||
set (VISIBILITY_MAP_FILE "${PROJECT_SOURCE_DIR}/src/build-scripts/hidesymbols.map" CACHE FILEPATH "Visibility map file")
|
||||
set (C_VISIBILITY_PRESET ${CXX_VISIBILITY_PRESET})
|
||||
if (${CXX_VISIBILITY_PRESET} STREQUAL "hidden" AND
|
||||
if (${CXX_VISIBILITY_PRESET} STREQUAL "hidden" AND VISIBILITY_MAP_FILE AND
|
||||
(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG) AND
|
||||
(CMAKE_SYSTEM_NAME MATCHES "Linux|kFreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "GNU"))
|
||||
# Linux/FreeBSD/Hurd: also hide all the symbols of dependent libraries
|
||||
@@ -148,9 +159,16 @@ if (CMAKE_COMPILER_IS_CLANG OR CMAKE_COMPILER_IS_APPLECLANG)
|
||||
add_compile_options ("-Wno-unused-local-typedefs")
|
||||
endif ()
|
||||
if (CLANG_VERSION_STRING VERSION_GREATER_EQUAL 3.9)
|
||||
# Don't warn about using unknown preprocessor symbols in #if'set
|
||||
# Don't warn about using unknown preprocessor symbols in `#if`
|
||||
add_compile_options ("-Wno-expansion-to-defined")
|
||||
endif ()
|
||||
# Suppress warnings about our strategic use of bitwise operations in place
|
||||
# of logical operators to produce branchless code in some places.
|
||||
if (CLANG_VERSION_STRING VERSION_GREATER_EQUAL 14.0
|
||||
OR INTELCLANG_VERSION_STRING VERSION_GREATER_EQUAL 14.0)
|
||||
add_compile_options ("-Wno-bitwise-instead-of-logical")
|
||||
endif ()
|
||||
|
||||
# disable warning in flex-generated code
|
||||
add_compile_options ("-Wno-null-conversion")
|
||||
add_compile_options ("-Wno-error=strict-overflow")
|
||||
@@ -178,6 +196,11 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
|
||||
add_compile_options ("-fno-math-errno")
|
||||
endif ()
|
||||
|
||||
if (INTELCLANG_VERSION_STRING VERSION_GREATER_EQUAL 2022.1.0)
|
||||
# New versions of icx warn about changing certain floating point options
|
||||
add_compile_options ("-Wno-overriding-t-option")
|
||||
endif ()
|
||||
|
||||
if (MSVC)
|
||||
# Microsoft specific options
|
||||
string (REGEX REPLACE "/W[1-4]" "/W1" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
@@ -195,6 +218,7 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD"
|
||||
endif ()
|
||||
|
||||
|
||||
# Remember the -std flags we need will be used later for custom Cuda builds
|
||||
set (CSTD_FLAGS "")
|
||||
if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG OR CMAKE_COMPILER_IS_INTEL)
|
||||
set (CSTD_FLAGS "-std=c++${CMAKE_CXX_STANDARD}")
|
||||
@@ -202,6 +226,10 @@ endif ()
|
||||
|
||||
|
||||
|
||||
# We will use this for ccache and timing
|
||||
set (MY_RULE_LAUNCH "")
|
||||
|
||||
|
||||
###########################################################################
|
||||
# Use ccache if found
|
||||
#
|
||||
@@ -311,6 +339,7 @@ endif ()
|
||||
# The USE_BATCHED option may be set to indicate that support for batched
|
||||
# SIMD shader execution be compiled along with targe specific libraries
|
||||
set (USE_BATCHED "" CACHE STRING "Build batched SIMD shader execution for (0, b8_AVX, b8_AVX2, b8_AVX2_noFMA, b8_AVX512, b8_AVX512_noFMA, b16_AVX512, b16_AVX512_noFMA)")
|
||||
option (VEC_REPORT "Enable compiler's reporting system for vectorization" OFF)
|
||||
set (BATCHED_SUPPORT_DEFINES "")
|
||||
set (BATCHED_TARGET_LIBS "")
|
||||
set (BUILD_BATCHED False)
|
||||
@@ -347,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 ()
|
||||
|
||||
|
||||
@@ -365,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")
|
||||
@@ -446,41 +460,17 @@ endif ()
|
||||
# is being built as a subproject.
|
||||
if (PROJECT_IS_TOP_LEVEL)
|
||||
set (CLANG_FORMAT_EXE_HINT "" CACHE PATH "clang-format executable's directory (will search if not specified")
|
||||
set (CLANG_FORMAT_INCLUDES # "src/*.h" "src/*.cpp"
|
||||
"src/include/*.h"
|
||||
"src/liboslcomp/*.cpp"
|
||||
"src/liboslcomp/*.h"
|
||||
"src/liboslexec/batched_rendservices.cpp"
|
||||
"src/liboslquery/*.cpp"
|
||||
"src/liboslquery/*.h"
|
||||
"src/oslinfo/*.cpp"
|
||||
"src/oslc/*.cpp"
|
||||
"src/osl.imageio/*.cpp"
|
||||
"src/osltoy/*.cpp"
|
||||
"src/osltoy/*.h"
|
||||
"testsuite/*.cpp"
|
||||
set (CLANG_FORMAT_INCLUDES "src/*.cpp" "src/*.h" "src/*.cu"
|
||||
CACHE STRING "Glob patterns to include for clang-format")
|
||||
set (CLANG_FORMAT_EXCLUDES
|
||||
# Files "imported and modified" that we don't want to reformat, so
|
||||
# they continue to match their upstream versions.
|
||||
"src/include/OSL/Imathx/*"
|
||||
"src/include/OSL/matrix22.h"
|
||||
# Files that are currently being modified with the SIMD batch
|
||||
# shading -- we'll reformat those only after that project work is
|
||||
# completed, to avoid nasty merge conflicts.
|
||||
"src/include/OSL/rendererservices.h"
|
||||
"src/include/OSL/*llvm*"
|
||||
"src/liboslexec/*llvm*"
|
||||
"src/liboslexec/oslexec_pvt.h"
|
||||
# Files that are currently being modified with the OptiX work --
|
||||
# we'll reformat those only after that project work is completed, to
|
||||
# avoid nasty merge conflicts.
|
||||
"src/include/OSL/device_string.h"
|
||||
"src/include/OSL/oslexec.h"
|
||||
"src/testrender/cuda/*"
|
||||
# Header files in testsuite are almost certainly osl headers, not C++
|
||||
"testsuite/*.h"
|
||||
""
|
||||
# Header files in shaders are OSL, not C++
|
||||
"src/shaders/*.h"
|
||||
CACHE STRING "Glob patterns to exclude for clang-format")
|
||||
find_program (CLANG_FORMAT_EXE
|
||||
NAMES clang-format bin/clang-format
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
set ($OSL_EXTRA_NVCC_ARGS "" CACHE STRING "Custom args passed to nvcc when compiling CUDA code")
|
||||
|
||||
# Compile a CUDA file to PTX using NVCC
|
||||
function ( NVCC_COMPILE cuda_src ptx_generated extra_nvcc_args )
|
||||
function ( NVCC_COMPILE cuda_src extra_headers ptx_generated extra_nvcc_args )
|
||||
get_filename_component ( cuda_src_we ${cuda_src} NAME_WE )
|
||||
get_filename_component ( cuda_src_dir ${cuda_src} DIRECTORY )
|
||||
set (cuda_ptx "${CMAKE_CURRENT_BINARY_DIR}/${cuda_src_we}.ptx" )
|
||||
set (${ptxlist} ${${ptxlist}} ${cuda_ptx} )
|
||||
set (${ptx_generated} ${cuda_ptx} PARENT_SCOPE)
|
||||
file ( GLOB cuda_headers "${cuda_src_dir}/*.h" )
|
||||
list (APPEND cuda_headers ${extra_headers})
|
||||
|
||||
list (TRANSFORM IMATH_INCLUDES PREPEND -I
|
||||
OUTPUT_VARIABLE ALL_IMATH_INCLUDES)
|
||||
@@ -79,6 +80,20 @@ function ( MAKE_CUDA_BITCODE src suffix generated_bc extra_clang_args )
|
||||
message (STATUS "Using LLVM_BC_GENERATOR ${LLVM_BC_GENERATOR} to generate bitcode.")
|
||||
endif()
|
||||
|
||||
if (NOT LLVM_AS_TOOL)
|
||||
find_program (LLVM_AS_TOOL NAMES "llvm-as"
|
||||
PATHS "${LLVM_DIRECTORY}/bin" "${LLVM_DIRECTORY}/tools/llvm"
|
||||
NO_CMAKE_PATH NO_DEFAULT_PATH NO_CMAKE_SYSTEM_PATH
|
||||
NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_ENVIRONMENT_PATH)
|
||||
endif ()
|
||||
|
||||
if (NOT LLVM_LINK_TOOL)
|
||||
find_program (LLVM_LINK_TOOL NAMES "llvm-link"
|
||||
PATHS "${LLVM_DIRECTORY}/bin" "${LLVM_DIRECTORY}/tools/llvm"
|
||||
NO_CMAKE_PATH NO_DEFAULT_PATH NO_CMAKE_SYSTEM_PATH
|
||||
NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_ENVIRONMENT_PATH)
|
||||
endif ()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
# fix compilation error when using MSVC
|
||||
set (CLANG_MSVC_FIX "-DBOOST_CONFIG_REQUIRES_THREADS_HPP")
|
||||
@@ -114,7 +129,7 @@ function ( MAKE_CUDA_BITCODE src suffix generated_bc extra_clang_args )
|
||||
-Wno-deprecated-register -Wno-format-security
|
||||
-O3 -fno-math-errno -ffast-math -S -emit-llvm ${extra_clang_args}
|
||||
${src} -o ${asm_cuda}
|
||||
COMMAND "${LLVM_DIRECTORY}/bin/llvm-as" -f -o ${bc_cuda} ${asm_cuda}
|
||||
COMMAND ${LLVM_AS_TOOL} -f -o ${bc_cuda} ${asm_cuda}
|
||||
DEPENDS ${exec_headers} ${PROJECT_PUBLIC_HEADERS} ${src}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
endfunction ()
|
||||
@@ -129,8 +144,8 @@ function ( LLVM_COMPILE_CUDA llvm_src headers prefix llvm_bc_cpp_generated extra
|
||||
MAKE_CUDA_BITCODE (${llvm_src} "" llvm_bc "${extra_clang_args}")
|
||||
|
||||
add_custom_command (OUTPUT ${llvm_bc_cpp}
|
||||
COMMAND python "${CMAKE_SOURCE_DIR}/src/liboslexec/serialize-bc.py" ${llvm_bc} ${llvm_bc_cpp} ${prefix}
|
||||
COMMAND ${Python_EXECUTABLE} "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py" ${llvm_bc} ${llvm_bc_cpp} ${prefix}
|
||||
MAIN_DEPENDENCY ${llvm_src}
|
||||
DEPENDS "${CMAKE_SOURCE_DIR}/src/liboslexec/serialize-bc.py" ${llvm_src} ${headers} ${llvm_bc}
|
||||
DEPENDS "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py" ${llvm_src} ${headers} ${llvm_bc}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
endfunction ()
|
||||
|
||||
@@ -88,7 +88,7 @@ checked_find_package (OpenEXR REQUIRED
|
||||
)
|
||||
# Force Imath includes to be before everything else to ensure that we have
|
||||
# the right Imath/OpenEXR version, not some older version in the system
|
||||
# library. This shoudn't be necessary, except for the common case of people
|
||||
# library. This shouldn't be necessary, except for the common case of people
|
||||
# building against Imath/OpenEXR 3.x when there is still a system-level
|
||||
# install version of 2.x.
|
||||
include_directories(BEFORE ${IMATH_INCLUDES})
|
||||
@@ -105,8 +105,8 @@ endif ()
|
||||
|
||||
# OpenImageIO
|
||||
checked_find_package (OpenImageIO REQUIRED
|
||||
VERSION_MIN 2.2.6)
|
||||
|
||||
VERSION_MIN 2.3.17
|
||||
DEFINITIONS -DOIIO_HIDE_FORMAT=1)
|
||||
|
||||
checked_find_package (pugixml REQUIRED
|
||||
VERSION_MIN 1.8)
|
||||
@@ -136,6 +136,14 @@ if (APPLE AND LLVM_VERSION VERSION_EQUAL 10.0.1 AND EXISTS "/usr/local/Cellar/ll
|
||||
" brew upgrade llvm \n"
|
||||
"${ColorReset}\n")
|
||||
endif ()
|
||||
if (LLVM_VERSION VERSION_GREATER_EQUAL 15.0
|
||||
AND ( (CMAKE_COMPILER_IS_APPLECLANG AND APPLECLANG_VERSION_STRING VERSION_LESS 15.0)
|
||||
OR (CMAKE_COMPILER_IS_CLANG AND CLANG_VERSION_STRING VERSION_LESS 15.0)))
|
||||
message (WARNING
|
||||
"${ColorYellow}"
|
||||
"If you are using LLVM 15 or higher, you should also use clang version "
|
||||
"15 or higher, or you may get build errors.${ColorReset}\n")
|
||||
endif ()
|
||||
|
||||
checked_find_package (partio)
|
||||
|
||||
@@ -198,7 +206,7 @@ if (USE_CUDA OR USE_OPTIX)
|
||||
# OptiX setup
|
||||
if (USE_OPTIX)
|
||||
checked_find_package (OptiX REQUIRED
|
||||
VERSION_MIN 5.1)
|
||||
VERSION_MIN 7.0)
|
||||
include_directories (BEFORE "${OPTIX_INCLUDES}")
|
||||
if (NOT USE_LLVM_BITCODE OR NOT USE_FAST_MATH)
|
||||
message (FATAL_ERROR "Enabling OptiX requires USE_LLVM_BITCODE=1 and USE_FAST_MATH=1")
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
# The executable may be disabled individually using any of the usual
|
||||
# check_is_enabled() conventions (e.g. -DENABLE_<executable>=OFF).
|
||||
#
|
||||
# If -DENABLE_INSTALL_<executable>=OFF was specified, the target will be built
|
||||
# (in the build area) but will not be installed.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# fancy_add_executable ([ NAME targetname ... ]
|
||||
@@ -42,13 +45,16 @@ macro (fancy_add_executable)
|
||||
target_include_directories (${_target_NAME} SYSTEM PRIVATE ${_target_SYSTEM_INCLUDE_DIRS})
|
||||
endif ()
|
||||
if (_target_DEFINITIONS)
|
||||
target_compile_definitions (${_target_name} PRIVATE ${_target_DEFINITIONS})
|
||||
target_compile_definitions (${_target_NAME} PRIVATE ${_target_DEFINITIONS})
|
||||
endif ()
|
||||
if (_target_LINK_LIBRARIES)
|
||||
target_link_libraries (${_target_NAME} PRIVATE ${_target_LINK_LIBRARIES})
|
||||
endif ()
|
||||
set_target_properties (${_target_NAME} PROPERTIES FOLDER "Tools")
|
||||
install_targets (${_target_NAME})
|
||||
check_is_enabled (INSTALL_${_target_NAME} _target_NAME_INSTALL_enabled)
|
||||
if (_target_NAME_INSTALL_enabled)
|
||||
install_targets (${_target_NAME})
|
||||
endif ()
|
||||
else ()
|
||||
message (STATUS "${ColorRed}Disabling ${_target_NAME} ${ColorReset}")
|
||||
endif ()
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
|
||||
function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_cpp extra_clang_args)
|
||||
|
||||
if (VERBOSE)
|
||||
message (STATUS "EMBED_LLVM_BITCODE_IN_CPP src_list=${src_list}")
|
||||
endif ()
|
||||
|
||||
foreach ( src ${src_list} )
|
||||
get_filename_component ( src_we ${src} NAME_WE )
|
||||
set ( src_asm "${CMAKE_CURRENT_BINARY_DIR}/${src_we}${suffix}.s" )
|
||||
set ( src_bc "${CMAKE_CURRENT_BINARY_DIR}/${src_we}${suffix}.bc" )
|
||||
if (VERBOSE)
|
||||
message (STATUS "EMBED_LLVM_BITCODE_IN_CPP in=${src}")
|
||||
message (STATUS "EMBED_LLVM_BITCODE_IN_CPP asm=${src_asm}")
|
||||
message (STATUS "EMBED_LLVM_BITCODE_IN_CPP bc=${src_bc}")
|
||||
endif ()
|
||||
list ( APPEND src_bc_list ${src_bc} )
|
||||
|
||||
get_property (CURRENT_DEFINITIONS DIRECTORY PROPERTY COMPILE_DEFINITIONS)
|
||||
if (VERBOSE)
|
||||
message (STATUS "Current #defines are ${CURRENT_DEFINITIONS}")
|
||||
endif ()
|
||||
foreach (def ${CURRENT_DEFINITIONS})
|
||||
set (LLVM_COMPILE_FLAGS ${LLVM_COMPILE_FLAGS} "-D${def}")
|
||||
endforeach()
|
||||
set (LLVM_COMPILE_FLAGS ${LLVM_COMPILE_FLAGS} ${SIMD_COMPILE_FLAGS} ${CSTD_FLAGS} ${TOOLCHAIN_FLAGS})
|
||||
# Avoid generating __dso_handle external global
|
||||
set (LLVM_COMPILE_FLAGS ${LLVM_COMPILE_FLAGS} "-fno-use-cxa-atexit")
|
||||
|
||||
# Figure out what program we will use to make the bitcode.
|
||||
if (NOT LLVM_BC_GENERATOR)
|
||||
find_program (LLVM_BC_GENERATOR NAMES "clang++"
|
||||
PATHS "${LLVM_DIRECTORY}/bin" "${LLVM_DIRECTORY}/tools/llvm"
|
||||
NO_CMAKE_PATH NO_DEFAULT_PATH NO_CMAKE_SYSTEM_PATH
|
||||
NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_ENVIRONMENT_PATH)
|
||||
endif ()
|
||||
|
||||
if (NOT LLVM_BC_GENERATOR)
|
||||
message (FATAL_ERROR "You must have a valid llvm bitcode generator (clang++) somewhere.")
|
||||
endif ()
|
||||
if (VERBOSE)
|
||||
message (STATUS "Using LLVM_BC_GENERATOR ${LLVM_BC_GENERATOR} to generate bitcode.")
|
||||
endif()
|
||||
|
||||
if (NOT LLVM_AS_TOOL)
|
||||
find_program (LLVM_AS_TOOL NAMES "llvm-as"
|
||||
PATHS "${LLVM_DIRECTORY}/bin" "${LLVM_DIRECTORY}/tools/llvm"
|
||||
NO_CMAKE_PATH NO_DEFAULT_PATH NO_CMAKE_SYSTEM_PATH
|
||||
NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_ENVIRONMENT_PATH)
|
||||
endif ()
|
||||
|
||||
if (NOT LLVM_LINK_TOOL)
|
||||
find_program (LLVM_LINK_TOOL NAMES "llvm-link"
|
||||
PATHS "${LLVM_DIRECTORY}/bin" "${LLVM_DIRECTORY}/tools/llvm"
|
||||
NO_CMAKE_PATH NO_DEFAULT_PATH NO_CMAKE_SYSTEM_PATH
|
||||
NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_ENVIRONMENT_PATH)
|
||||
endif ()
|
||||
|
||||
|
||||
# Fix specific problem I had on new Apple systems (e.g. Mavericks) with
|
||||
# LLVM/libc++ installed -- for some reason, LLVM 3.4 wasn't finding it,
|
||||
# so in that specific case, append another -I to point it in the right
|
||||
# direction.
|
||||
#if (APPLE AND ${LLVM_BC_GENERATOR} MATCHES ".*clang.*")
|
||||
# exec_program ( "${LLVM_BC_GENERATOR}" ARGS --version OUTPUT_VARIABLE MY_CLANG_VERSION )
|
||||
# string (REGEX REPLACE "clang version ([0-9][.][0-9]+).*" "\\1" MY_CLANG_VERSION "${MY_CLANG_VERSION}")
|
||||
# if ((${MY_CLANG_VERSION} VERSION_GREATER "3.3")
|
||||
# AND (EXISTS "/usr/lib/libc++.dylib")
|
||||
# AND (EXISTS "/Library/Developer/CommandLineTools/usr/lib/c++/v1"))
|
||||
# set (LLVM_COMPILE_FLAGS ${LLVM_COMPILE_FLAGS} "-I/Library/Developer/CommandLineTools/usr/lib/c++/v1")
|
||||
# endif ()
|
||||
#endif ()
|
||||
|
||||
list (TRANSFORM IMATH_INCLUDES PREPEND -I
|
||||
OUTPUT_VARIABLE ALL_IMATH_INCLUDES)
|
||||
list (TRANSFORM OPENEXR_INCLUDES PREPEND -I
|
||||
OUTPUT_VARIABLE ALL_OPENEXR_INCLUDES)
|
||||
list (TRANSFORM OpenImageIO_INCLUDES PREPEND -I
|
||||
OUTPUT_VARIABLE ALL_OpenImageIO_INCLUDES)
|
||||
|
||||
if (${LLVM_VERSION} VERSION_GREATER_EQUAL 15.0)
|
||||
# Until we fully support opaque pointers, we need to disable
|
||||
# them when using LLVM 15.
|
||||
list (APPEND LLVM_COMPILE_FLAGS -Xclang -no-opaque-pointers)
|
||||
endif ()
|
||||
|
||||
# Command to turn the .cpp file into LLVM assembly language .s, into
|
||||
# LLVM bitcode .bc, then back into a C++ file with the bc embedded!
|
||||
add_custom_command ( OUTPUT ${src_bc}
|
||||
COMMAND ${LLVM_BC_GENERATOR}
|
||||
${LLVM_COMPILE_FLAGS}
|
||||
"-I${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
"-I${CMAKE_SOURCE_DIR}/src/include"
|
||||
"-I${CMAKE_BINARY_DIR}/include"
|
||||
${ALL_OpenImageIO_INCLUDES}
|
||||
${ALL_IMATH_INCLUDES}
|
||||
#"-isystem ${Boost_INCLUDE_DIRS}" #Does not pick up usr installed boost/thread/tss.hpp for oslexec_pvt.h
|
||||
"-I${Boost_INCLUDE_DIRS}"
|
||||
-DOSL_COMPILING_TO_BITCODE=1
|
||||
-Wno-deprecated-register
|
||||
# the following 2 warnings can be restored when all 3rd parties have fixed their export macros
|
||||
# (dllimport attribute is not supported when compiling for Cuda and triggers a ton of warnings)
|
||||
-Wno-ignored-attributes -Wno-unknown-attributes
|
||||
-O3 -fno-math-errno -S -emit-llvm ${extra_clang_args}
|
||||
-o ${src_asm} ${src}
|
||||
COMMAND ${LLVM_AS_TOOL} -f -o ${src_bc} ${src_asm}
|
||||
# Do NOT setup a MAIN_DEPENDENCY because only 1 may exist
|
||||
# and we may have the several outputs dependent on the same source
|
||||
DEPENDS ${src} ${exec_headers} ${PROJECT_PUBLIC_HEADERS}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
endforeach ()
|
||||
|
||||
|
||||
if (VERBOSE)
|
||||
message ( STATUS "^^^^^^^^^^^^^^^^^^^^^^^^^^" )
|
||||
message ( STATUS "src_bc_list: ${src_bc_list} ")
|
||||
message ( STATUS "^^^^^^^^^^^^^^^^^^^^^^^^^^" )
|
||||
endif()
|
||||
|
||||
# Link all of the individual LLVM bitcode files
|
||||
set ( linked_src_bc "${CMAKE_CURRENT_BINARY_DIR}/${output_name}.bc" )
|
||||
add_custom_command ( OUTPUT ${linked_src_bc}
|
||||
COMMAND ${LLVM_LINK_TOOL} -internalize ${src_bc_list} -o ${linked_src_bc}
|
||||
DEPENDS ${src_bc_list} ${exec_headers} ${PROJECT_PUBLIC_HEADERS} ${src_list}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" )
|
||||
|
||||
# Serialize the linked bitcode into a CPP file
|
||||
set ( src_bc_cpp "${CMAKE_CURRENT_BINARY_DIR}/${output_name}.bc.cpp" )
|
||||
add_custom_command ( OUTPUT ${src_bc_cpp}
|
||||
COMMAND ${Python_EXECUTABLE} "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py"
|
||||
${linked_src_bc} ${src_bc_cpp} ${output_name}
|
||||
DEPENDS "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py" ${linked_src_bc}
|
||||
${exec_headers} ${PROJECT_PUBLIC_HEADERS}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
|
||||
# add generated .cpp with embedded bitcode to the list of sources
|
||||
set ( ${list_to_append_cpp} ${${list_to_append_cpp}} ${src_bc_cpp} PARENT_SCOPE )
|
||||
|
||||
endfunction ( )
|
||||
@@ -10,7 +10,7 @@
|
||||
# PARTIO_LIBRARIES - library to link against
|
||||
# PARTIO_FOUND - true if Partio was found.
|
||||
|
||||
# Hack! perfer a config if it can be found
|
||||
# Hack! prefer a config if it can be found
|
||||
find_package(partio CONFIG)
|
||||
if (PARTIO_FOUND OR partio_FOUND)
|
||||
if (VERBOSE)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright Contributors to the Open Shading Languge project.
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ macro (setup_python_module)
|
||||
|
||||
set (target_name ${lib_TARGET})
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND NOT ${CMAKE_COMPILER_ID} STREQUAL "Intel")
|
||||
# Seems to be a problem on some systems, with pybind11 and python headers
|
||||
set_property (SOURCE ${lib_SOURCES} APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-macro-redefined ")
|
||||
endif ()
|
||||
@@ -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 ()
|
||||
|
||||
+93
-28
@@ -1,4 +1,4 @@
|
||||
# Copyright Contributors to the Open Shading Languge project.
|
||||
# Copyright Contributors to the Open Shading Language project.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/
|
||||
|
||||
@@ -16,6 +16,10 @@ add_custom_command (OUTPUT "${CMAKE_BINARY_DIR}/testsuite/runtest.py"
|
||||
MAIN_DEPENDENCY "${CMAKE_SOURCE_DIR}/testsuite/runtest.py")
|
||||
add_custom_target ( CopyFiles ALL DEPENDS "${CMAKE_BINARY_DIR}/testsuite/runtest.py" )
|
||||
|
||||
|
||||
set (OSL_TEST_BIG_TIMEOUT 800 CACHE STRING "Timeout for tests that take a long time")
|
||||
|
||||
|
||||
# add_one_testsuite() - set up one testsuite entry
|
||||
#
|
||||
# Usage:
|
||||
@@ -26,10 +30,12 @@ add_custom_target ( CopyFiles ALL DEPENDS "${CMAKE_BINARY_DIR}/testsuite/runtest
|
||||
# [COMMAND cmd...] - optional override of launch command
|
||||
# )
|
||||
#
|
||||
|
||||
macro (add_one_testsuite testname testsrcdir)
|
||||
cmake_parse_arguments (_tst "" "" "ENV;COMMAND" ${ARGN})
|
||||
set (testsuite "${CMAKE_SOURCE_DIR}/testsuite")
|
||||
set (testdir "${CMAKE_BINARY_DIR}/testsuite/${testname}")
|
||||
file (MAKE_DIRECTORY "${testdir}")
|
||||
if (NOT _tst_COMMAND)
|
||||
set (_tst_COMMAND ${Python_EXECUTABLE} "${testsuite}/runtest.py" ${testdir})
|
||||
if (MSVC_IDE)
|
||||
@@ -45,7 +51,17 @@ macro (add_one_testsuite testname testsrcdir)
|
||||
OSL_TESTSUITE_SRC=${testsrcdir}
|
||||
OSL_TESTSUITE_CUR=${testdir}
|
||||
)
|
||||
file (MAKE_DIRECTORY "${testdir}")
|
||||
|
||||
# We need to suppress the leak sanitizer for "texture" tests, because of a
|
||||
# minor leak inside OIIO (140 bytes! -- inconsequential) but which we
|
||||
# can't use the suppressions list becuase the leaks come from calls made
|
||||
# inside JITed code for which there is not a good stack trace. Any real
|
||||
# leaks from OIIO or its dependencies we assume will be caught by lsan on
|
||||
# the OIIO side, where there is no JIT to complicate things.
|
||||
if (${testname} MATCHES "^texture" OR ${testname} MATCHES "gettextureinfo")
|
||||
list (APPEND _tst_ENV ASAN_OPTIONS=detect_leaks=0:$ENV{ASAN_OPTIONS})
|
||||
endif ()
|
||||
|
||||
add_test ( NAME ${testname} COMMAND ${_tst_COMMAND} )
|
||||
# message ("Test -- env ${_tst_ENV} cmd ${_tst_COMMAND}")
|
||||
set_tests_properties (${testname} PROPERTIES ENVIRONMENT "${_tst_ENV}" )
|
||||
@@ -53,8 +69,7 @@ macro (add_one_testsuite testname testsrcdir)
|
||||
# from piling up together, allocate a few cores each.
|
||||
if (${testname} MATCHES "^render-")
|
||||
set_tests_properties (${testname} PROPERTIES LABELS render
|
||||
TIMEOUT 240
|
||||
PROCESSORS 4 COST 10 TIMEOUT 240)
|
||||
PROCESSORS 4 COST 10 TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
endif ()
|
||||
# Some labeling for fun
|
||||
if (${testname} MATCHES "^texture")
|
||||
@@ -76,7 +91,7 @@ macro (add_one_testsuite testname testsrcdir)
|
||||
# These are batched shading regression tests. Some are quite
|
||||
# long, so give them a higher cost and timeout.
|
||||
set_tests_properties (${testname} PROPERTIES LABELS batchregression
|
||||
COST 15 TIMEOUT 300)
|
||||
COST 15 TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
endif ()
|
||||
endmacro ()
|
||||
|
||||
@@ -90,6 +105,7 @@ macro ( TESTSUITE )
|
||||
endif ()
|
||||
set (test_all_optix $ENV{TESTSUITE_OPTIX})
|
||||
set (test_all_batched $ENV{TESTSUITE_BATCHED})
|
||||
set (test_all_rs_bitcode $ENV{TESTSUITE_RS_BITCODE})
|
||||
# Add the tests if all is well.
|
||||
set (ALL_TEST_LIST "")
|
||||
set (_testsuite "${CMAKE_SOURCE_DIR}/testsuite")
|
||||
@@ -106,9 +122,10 @@ 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" AND
|
||||
NOT EXISTS "${_testsrcdir}/BATCHED_REGRESSION" AND
|
||||
NOT EXISTS "${_testsrcdir}/OPTIMIZEONLY")
|
||||
if (NOT _testname MATCHES "optix"
|
||||
AND NOT EXISTS "${_testsrcdir}/NOSCALAR"
|
||||
AND NOT EXISTS "${_testsrcdir}/BATCHED_REGRESSION"
|
||||
AND NOT EXISTS "${_testsrcdir}/OPTIMIZEONLY")
|
||||
add_one_testsuite ("${_testname}" "${_testsrcdir}"
|
||||
ENV TESTSHADE_OPT=0 )
|
||||
endif ()
|
||||
@@ -116,11 +133,15 @@ macro ( TESTSUITE )
|
||||
# optimization, triggered by setting TESTSHADE_OPT env variable.
|
||||
# Skip OptiX-only tests and those with a NOOPTIMIZE marker file.
|
||||
if (NOT _testname MATCHES "optix"
|
||||
AND NOT EXISTS "${_testsrcdir}/NOSCALAR"
|
||||
AND NOT EXISTS "${_testsrcdir}/BATCHED_REGRESSION"
|
||||
AND NOT EXISTS "${_testsrcdir}/NOOPTIMIZE")
|
||||
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
|
||||
@@ -139,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.
|
||||
@@ -153,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"
|
||||
@@ -162,15 +183,41 @@ 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")
|
||||
if ((EXISTS "${_testsrcdir}/BATCHED_REGRESSION")
|
||||
AND NOT EXISTS "${_testsrcdir}/NOOPTIMIZE")
|
||||
# optimized for right now
|
||||
add_one_testsuite ("${_testname}.regress.batched.opt" "${_testsrcdir}"
|
||||
ENV TESTSHADE_OPT=2 OSL_REGRESSION_TEST=BATCHED )
|
||||
endif ()
|
||||
if ((EXISTS "${_testsrcdir}/BATCHED_REGRESSION")
|
||||
AND EXISTS "${_testsrcdir}/NOOPTIMIZE")
|
||||
# not optimized
|
||||
add_one_testsuite ("${_testname}.regress.batched" "${_testsrcdir}"
|
||||
ENV TESTSHADE_OPT=0 OSL_REGRESSION_TEST=BATCHED )
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# if there is an RS_BITCODE marker file in the directory.
|
||||
if ((EXISTS "${_testsrcdir}/RS_BITCODE" OR test_all_rs_bitcode)
|
||||
AND NOT EXISTS "${_testsrcdir}/BATCHED_REGRESSION"
|
||||
AND NOT EXISTS "${_testsrcdir}/RS_BITCODE_REGRESSION"
|
||||
AND NOT EXISTS "${_testsrcdir}/NOOPTIMIZE")
|
||||
add_one_testsuite ("${_testname}.rsbitcode.opt" "${_testsrcdir}"
|
||||
ENV TESTSHADE_OPT=2 TESTSHADE_RS_BITCODE=1 )
|
||||
endif ()
|
||||
|
||||
# if there is an RS_BITCODE_REGRESSION marker file in the directory.
|
||||
if (EXISTS "${_testsrcdir}/RS_BITCODE_REGRESSION" OR (
|
||||
test_all_rs_bitcode AND EXISTS "${_testsrcdir}/BATCHED_REGRESSION")
|
||||
AND NOT EXISTS "${_testsrcdir}/NOOPTIMIZE")
|
||||
# optimized for right now
|
||||
add_one_testsuite ("${_testname}.regress.rsbitcode.opt" "${_testsrcdir}"
|
||||
ENV TESTSHADE_OPT=2 OSL_REGRESSION_TEST=RS_BITCODE )
|
||||
endif ()
|
||||
|
||||
endforeach ()
|
||||
if (VERBOSE)
|
||||
message (STATUS "Added tests: ${ALL_TEST_LIST}")
|
||||
@@ -182,16 +229,16 @@ macro (osl_add_all_tests)
|
||||
# special installed tests.
|
||||
TESTSUITE ( aastep allowconnect-err andor-reg and-or-not-synonyms
|
||||
arithmetic area-reg arithmetic-reg
|
||||
array array-reg array-copy-reg array-derivs array-range
|
||||
array array-reg array-copy-reg array-derivs array-range
|
||||
array-aassign array-assign-reg array-length-reg
|
||||
bitwise-and-reg bitwise-or-reg bitwise-shl-reg bitwise-shr-reg bitwise-xor-reg
|
||||
blackbody blackbody-reg blendmath breakcont breakcont-reg
|
||||
bug-array-heapoffsets bug-locallifetime bug-outputinit
|
||||
bug-param-duplicate bug-peep bug-return
|
||||
calculatenormal-reg
|
||||
cellnoise closure closure-array color color-reg comparison
|
||||
cellnoise closure closure-array color color-reg colorspace comparison
|
||||
complement-reg compile-buffer compassign-reg
|
||||
component-range
|
||||
component-range
|
||||
control-flow-reg connect-components
|
||||
const-array-params const-array-fill
|
||||
debugnan debug-uninit
|
||||
@@ -199,6 +246,7 @@ macro (osl_add_all_tests)
|
||||
draw_string
|
||||
error-dupes error-serialized
|
||||
example-deformer
|
||||
example-batched-deformer
|
||||
exit exponential
|
||||
filterwidth-reg
|
||||
for-reg format-reg fprintf
|
||||
@@ -206,9 +254,12 @@ macro (osl_add_all_tests)
|
||||
function-overloads function-redef
|
||||
geomath getattribute-camera getattribute-shader
|
||||
getsymbol-nonheap gettextureinfo gettextureinfo-reg
|
||||
globals-needed
|
||||
group-outputs groupstring
|
||||
hash hashnoise hex hyperb
|
||||
ieee_fp 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
|
||||
@@ -228,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
|
||||
@@ -244,6 +295,7 @@ macro (osl_add_all_tests)
|
||||
oslc-err-outputparamvararray oslc-err-paramdefault
|
||||
oslc-err-struct-array-init oslc-err-struct-ctr
|
||||
oslc-err-struct-dup oslc-err-struct-print
|
||||
oslc-err-type-as-variable
|
||||
oslc-err-unknown-ctr
|
||||
oslc-pragma-warnerr
|
||||
oslc-warn-commainit
|
||||
@@ -259,10 +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-microfacet render-oren-nayar render-veachmis render-ward
|
||||
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
|
||||
@@ -286,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
|
||||
@@ -306,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 ()
|
||||
|
||||
@@ -330,10 +392,13 @@ macro (osl_add_all_tests)
|
||||
TESTSUITE ( testoptix testoptix-noise example-cuda)
|
||||
endif ()
|
||||
|
||||
# Some regression tests have alot of combinations and may need more time to finish
|
||||
# Some regression tests have a lot of combinations and may need more time to finish
|
||||
if (BUILD_BATCHED)
|
||||
set_tests_properties (arithmetic-reg.regress.batched.opt PROPERTIES TIMEOUT 800)
|
||||
set_tests_properties (transform-reg.regress.batched.opt PROPERTIES TIMEOUT 800)
|
||||
set_tests_properties (arithmetic-reg.regress.batched.opt
|
||||
PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
set_tests_properties (transform-reg.regress.batched.opt
|
||||
PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
endif ()
|
||||
|
||||
set_tests_properties (matrix-reg.regress.rsbitcode.opt
|
||||
PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
|
||||
endmacro()
|
||||
|
||||
+710
-77
@@ -66,7 +66,7 @@ All rights reserved.
|
||||
Editor: Larry Gritz \\
|
||||
\emph{lg@imageworks.com}
|
||||
}
|
||||
\date{{\large Date: 24 Nov 2021 \\
|
||||
\date{{\large Date: 27 Aug 2022 \\
|
||||
% (with corrections, 24 Nov 2021)
|
||||
}
|
||||
\bigskip
|
||||
@@ -1431,7 +1431,7 @@ least 32 bits.
|
||||
|
||||
Integer constants are constructed the same way as in C. The following
|
||||
are examples of {\cf int} constants: {\cf 1}, {\cf -32}, etc. Integer
|
||||
constants may be specified as hexidecimal, for example: {\cf 0x01cf}.
|
||||
constants may be specified as hexadecimal, for example: {\cf 0x01cf}.
|
||||
|
||||
Unlike C, no unsigned, bool, char, short, or long types are supplied.
|
||||
This is to simplify the process of writing shaders (as well as
|
||||
@@ -3778,7 +3778,7 @@ Computes the \emph{inverse} of the {\cf spline()} function, i.e., returns
|
||||
the value $x$ for which \\
|
||||
\spc {\cf spline (basis, x, y...)}\\
|
||||
would return value
|
||||
$v$. Results are undefined if the knots do not specifiy a monotonic
|
||||
$v$. Results are undefined if the knots do not specify a monotonic
|
||||
(only increasing or only decreasing) set of values.
|
||||
|
||||
Note that the combination of {\cf spline} and {\cf splineinverse} makes
|
||||
@@ -3905,7 +3905,7 @@ multi-component types such as \color, the format will be applied to each
|
||||
of the components). The {\cf \%s} expects a {\cf string} or
|
||||
{\cf closure} argument.
|
||||
|
||||
All of the substition commands follow the usual C/C++ formatting rules,
|
||||
All of the substitution commands follow the usual C/C++ formatting rules,
|
||||
so format commands such as {\cf "\%6.2f"}, etc., should work as
|
||||
expected.
|
||||
\apiend
|
||||
@@ -3930,7 +3930,7 @@ and other diagnostic information.
|
||||
\indexapi{fprintf()}
|
||||
The {\cf fprintf()} function works similarly to {\cf printf}, but rather
|
||||
than printing to the default text output stream, the results will be
|
||||
concatentated onto the end of the text file named by {\cf filename}.
|
||||
concatenated onto the end of the text file named by {\cf filename}.
|
||||
\apiend
|
||||
|
||||
\apiitem{string {\ce concat} (string s1, ..., string sN)}
|
||||
@@ -4404,7 +4404,7 @@ will not be modified and {\cf gettextureinfo} will return {\cf 0}.
|
||||
The version of {\cf gettextureinfo} that takes {\cf s} and {\cf t} parameters
|
||||
retrieves information about the texture file that will be used for those
|
||||
texture coordinates. This can be useful for UDIM textures that may use
|
||||
different texture files for different regions, based on the coodinates. For
|
||||
different texture files for different regions, based on the corodinates. For
|
||||
regular, non-UDIM textures, the coordinates, if supplied, will be ignored.
|
||||
When UDIM textures are queried without coordinates supplied, it will succeed
|
||||
and return the texture info only if that parameter is found and has the same
|
||||
@@ -4611,7 +4611,7 @@ Example:
|
||||
\index{material closure functions}
|
||||
\index{functions!closures}
|
||||
|
||||
For \closurecolor functions, the return ``value'' is symbolic and is may
|
||||
For \closurecolor functions, the return ``value'' is symbolic and may
|
||||
be passed to an output variable or assigned to \Ci, to be evaluated at a
|
||||
later time convenient to the renderer in order to compute the exitant
|
||||
radiance in the direction {\cf -I}. But the shader itself cannot
|
||||
@@ -4620,15 +4620,695 @@ examine the numeric values of the \colorclosure.
|
||||
The intent of this specification is to give a minimal but useful set of
|
||||
material closures that you can expect any renderer implementation to
|
||||
provide. Individual renderers may supply additional closures that are
|
||||
specific to the workings of that renderer. Additionally, invidual
|
||||
specific to the workings of that renderer. Additionally, individual
|
||||
renderers may allow additional parameters or controls on the standard
|
||||
closures, passed as token/value pairs following the required arguments
|
||||
(much like the optional arguments to the {\cf texture()} function).
|
||||
Consult the documentation for your specific renderer for details.
|
||||
|
||||
OSL's standard material closures are by synchronized to match the names and
|
||||
properties of the physically-based shading nodes of MaterialX v1.38
|
||||
(\url{https://www.materialx.org/}).
|
||||
|
||||
\subsection{Surface BSDF closures}
|
||||
|
||||
\apiitem{\closurecolor\ {\ce oren_nayar_diffuse_bsdf}(normal N, color albedo, float roughness)}
|
||||
\indexapi{oren_nayar_diffuse_bsdf()}
|
||||
|
||||
Constructs a diffuse reflection BSDF based on the Oren-Nayar reflectance
|
||||
model.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Surface albedo.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness}
|
||||
\vspace{12pt}
|
||||
Surface roughness [0,1]. A value of 0.0 gives Lambertian reflectance.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
The Oren-Nayar reflection model is described in M.\ Oren and S.\ K.\
|
||||
Nayar, ``Generalization of Lambert's Reflectance Model,'' Proceedings of
|
||||
SIGGRAPH 1994, pp.239-246 (July, 1994).
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Surface material closures}
|
||||
\apiitem{\colorclosure\ {\ce burley_diffuse_bsdf} (normal N, color albedo, float roughness)}
|
||||
\indexapi{burley_diffuse_bsdf()}
|
||||
|
||||
Constructs a diffuse reflection BSDF based on the corresponding component of
|
||||
the Disney Principled shading model.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Surface albedo.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness}
|
||||
\vspace{12pt}
|
||||
Surface roughness [0,1]. A value of 0.0 gives Lambertian reflectance.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce dielectric_bsdf} (normal N, vector U, color reflection_tint, \\
|
||||
\spc\spc color transmission_tint, float roughness_x, float roughness_y, \\
|
||||
\spc\spc float ior, string distribution)}
|
||||
\indexapi{dielectric_bsdf()}
|
||||
|
||||
Constructs a reflection and/or transmission BSDF based on a microfacet
|
||||
reflectance model and a Fresnel curve for dielectrics. The two tint parameters
|
||||
control the contribution of each reflection/transmission lobe. The tints
|
||||
should remain 100\% white for a physically correct dielectric, but can be
|
||||
tweaked for artistic control or set to 0.0 for disabling a lobe.
|
||||
|
||||
The closure may be vertically layered over a base BSDF for the surface beneath
|
||||
the dielectric layer. This is done using the {\cf layer()} closure. By
|
||||
chaining multiple {\cf dielectric_bsdf} closures you can describe a surface
|
||||
with multiple specular lobes. If transmission is enabled (transmission_tint
|
||||
$>$ 0.0) the closure may be layered over a VDF closure describing the surface
|
||||
interior to handle absorption and scattering inside the medium.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{U}
|
||||
\vspace{12pt}
|
||||
Tangent vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{reflection_tint}
|
||||
\vspace{12pt}
|
||||
Weight per color channel for the reflection lobe. Should be (1,1,1) for a physically-correct dielectric surface, but can be tweaked for artistic control. Set to (0,0,0) to disable reflection.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{transmission_tint}
|
||||
\vspace{12pt}
|
||||
Weight per color channel for the transmission lobe. Should be (1,1,1) for a physically-correct dielectric surface, but can be tweaked for artistic control. Set to (0,0,0) to disable transmission.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness_x}
|
||||
\vspace{12pt}
|
||||
Surface roughness in the U direction with a perceptually linear response over its range.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness_y}
|
||||
\vspace{12pt}
|
||||
Surface roughness in the V direction with a perceptually linear response
|
||||
over its range.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{ior}
|
||||
\vspace{12pt}
|
||||
Refraction index.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{distribution}
|
||||
\vspace{12pt}
|
||||
Microfacet distribution. An implementation is expected to support the
|
||||
following distributions: \qkw{ggx}
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{thinfilm_thickness}
|
||||
\vspace{12pt}
|
||||
Optional float parameter for thickness of an iridescent thin film layer on
|
||||
top of this BSDF. Given in nanometers.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{thinfilm_ior}
|
||||
\vspace{12pt}
|
||||
Optional float parameter for refraction index of the thin film layer.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce conductor_bsdf} (normal N, vector U, float roughness_x, \\
|
||||
\spc\spc float roughness_y, color ior, color extinction, string distribution)}
|
||||
\indexapi{conductor_bsdf()}
|
||||
|
||||
Constructs a reflection BSDF based on a microfacet reflectance model. Uses a
|
||||
Fresnel curve with complex refraction index for conductors/metals. If an
|
||||
artistic parametrization is preferred the {\cf artistic_ior()} utility
|
||||
function can be used to convert from artistic to physical parameters.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{U}
|
||||
\vspace{12pt}
|
||||
Tangent vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness_x}
|
||||
\vspace{12pt}
|
||||
Surface roughness in the U direction with a perceptually linear response over its range.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness_y}
|
||||
\vspace{12pt}
|
||||
Surface roughness in the V direction with a perceptually linear response over its range.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{ior}
|
||||
\vspace{12pt}
|
||||
Refraction index.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{extinction}
|
||||
\vspace{12pt}
|
||||
Extinction coefficient.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{distribution}
|
||||
\vspace{12pt}
|
||||
Microfacet distribution. An implementation is expected to support the
|
||||
following distributions: \qkw{ggx}
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{thinfilm_thickness}
|
||||
\vspace{12pt}
|
||||
Optional float parameter for thickness of an iridescent thin film layer on
|
||||
top of this BSDF. Given in nanometers.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{thinfilm_ior}
|
||||
\vspace{12pt}
|
||||
Optional float parameter for refraction index of the thin film layer.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce generalized_schlick_bsdf} (normal N, vector U, \\
|
||||
\spc\spc color reflection_tint, color transmission_tint, \\
|
||||
\spc\spc float roughness_x, float roughness_y, color f0, color f90, \\
|
||||
\spc\spc float exponent, string distribution)}
|
||||
\indexapi{generalized_schlick_bsdf()}
|
||||
|
||||
Constructs a reflection and/or transmission BSDF based on a microfacet
|
||||
reflectance model and a generalized Schlick Fresnel curve. The two tint
|
||||
parameters control the contribution of each reflection/transmission lobe.
|
||||
|
||||
The closure may be vertically layered over a base BSDF for the surface beneath
|
||||
the dielectric layer. This is done using the layer() closure. By chaining
|
||||
multiple {\cf dielectric_bsdf} closures you can describe a surface with multiple
|
||||
specular lobes. If transmission is enabled (transmission_tint $>$ 0.0) the
|
||||
closure may be layered over a VDF closure describing the surface interior to
|
||||
handle absorption and scattering inside the medium.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{U}
|
||||
\vspace{12pt}
|
||||
Tangent vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{reflection_tint}
|
||||
\vspace{12pt}
|
||||
Weight per color channel for the reflection lobe. Set to (0,0,0) to disable
|
||||
reflection.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{transmission_tint}
|
||||
\vspace{12pt}
|
||||
Weight per color channel for the transmission lobe. Set to (0,0,0) to
|
||||
disable transmission.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness_x}
|
||||
\vspace{12pt}
|
||||
Surface roughness in the U direction with a perceptually linear response
|
||||
over its range.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness_y}
|
||||
\vspace{12pt}
|
||||
Surface roughness in the V direction with a perceptually linear response
|
||||
over its range.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{f0}
|
||||
\vspace{12pt}
|
||||
Reflectivity per color channel at facing angles.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{f90}
|
||||
\vspace{12pt}
|
||||
Reflectivity per color channel at grazing angles.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{exponent}
|
||||
\vspace{12pt}
|
||||
Variable exponent for the Schlick Fresnel curve, the default value should be
|
||||
5.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{distribution}
|
||||
\vspace{12pt}
|
||||
Microfacet distribution. An implementation is expected to support the
|
||||
following distributions: \qkw{ggx}
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{thinfilm_thickness}
|
||||
\vspace{12pt}
|
||||
Optional float parameter for thickness of an iridescent thin film layer on
|
||||
top of this BSDF. Given in nanometers.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{thinfilm_ior}
|
||||
\vspace{12pt}
|
||||
Optional float parameter for refraction index of the thin film layer.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce translucent_bsdf} (normal N, color albedo)}
|
||||
\indexapi{translucent_bsdf()}
|
||||
|
||||
Constructs a translucent (diffuse transmission) BSDF based on the Lambert
|
||||
reflectance model.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Surface albedo.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness}
|
||||
\vspace{12pt}
|
||||
Surface roughness [0,1]. A value of 0.0 gives Lambertian reflectance.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce transparent_bsdf} ( )}
|
||||
\indexapi{transparent_bsdf()}
|
||||
|
||||
Constructs a closure that represents straight transmission through a surface.
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce subsurface_bssrdf} ( )}
|
||||
\indexapi{subsurface_bssrdf}
|
||||
Constructs a BSSRDF for subsurface scattering within a homogeneous medium.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Single-scattering albedo of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{transmission_depth}
|
||||
\vspace{12pt}
|
||||
Distance travelled inside the medium by white light before its color becomes
|
||||
transmission_color by Beer's law. Given in scene length units, range
|
||||
[0,infinity). Together with transmission_color this determines the
|
||||
extinction coefficient of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{transmission_color}
|
||||
\vspace{12pt}
|
||||
Desired color resulting from white light transmitted a distance of
|
||||
'transmission_depth' through the medium. Together with transmission_depth
|
||||
this determines the extinction coefficient of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{anisotropy}
|
||||
\vspace{12pt}
|
||||
Scattering anisotropy [-1,1]. Negative values give backwards scattering,
|
||||
positive values give forward scattering, and 0.0 gives uniform scattering.
|
||||
\apiend
|
||||
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce sheen_bsdf} (normal N, color albedo, float roughness)}
|
||||
\indexapi{sheen_bsdf()}
|
||||
|
||||
Constructs a microfacet BSDF for the back-scattering properties of cloth-like
|
||||
materials. This closure may be vertically layered over a base BSDF, where
|
||||
energy that is not reflected will be transmitted to the base closure.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{N}
|
||||
\vspace{12pt}
|
||||
Normal vector of the surface point being shaded.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Surface albedo.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{roughness}
|
||||
\vspace{12pt}
|
||||
Surface roughness [0,1].
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
|
||||
\subsection{Volumetric material closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce anisotropic_vdf} (color albedo, color extinction, float anisotropy)}
|
||||
\indexapi{anisotropic_vdf}
|
||||
|
||||
Constructs a VDF scattering light for a general participating medium, based on
|
||||
the Henyey-Greenstein phase function. Forward, backward and uniform scattering
|
||||
is supported and controlled by the anisotropy input.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Single-scattering albedo of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{extinction}
|
||||
\vspace{12pt}
|
||||
Volume extinction coefficient.
|
||||
\apiend
|
||||
|
||||
\apiitem{anisotropy}
|
||||
\vspace{12pt}
|
||||
Scattering anisotropy [-1,1]. Negative values give backwards scattering,
|
||||
positive values give forward scattering, and 0.0 gives uniform scattering.
|
||||
\apiend
|
||||
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce medium_vdf} (color albedo, float transmission_depth, \\
|
||||
\spc\spc color transmission_color, float anisotropy, float ior, int priority)}
|
||||
\indexapi{medium_vdf}
|
||||
|
||||
Constructs a VDF for light passing through a dielectric homogeneous medium,
|
||||
such as glass or liquids. The parameters {\cf transmission_depth} and
|
||||
{\cf transmission_color} control the extinction coefficient of the medium in an
|
||||
artist-friendly way. A priority can be set to determine the ordering of
|
||||
overlapping media.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{albedo}
|
||||
\vspace{12pt}
|
||||
Single-scattering albedo of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{transmission_depth}
|
||||
\vspace{12pt}
|
||||
Distance travelled inside the medium by white light before its color becomes
|
||||
transmission_color by Beer's law. Given in scene length units, range
|
||||
[0,infinity). Together with transmission_color this determines the
|
||||
extinction coefficient of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{transmission_color}
|
||||
\vspace{12pt}
|
||||
Desired color resulting from white light transmitted a distance of
|
||||
'transmission_depth' through the medium. Together with transmission_depth
|
||||
this determines the extinction coefficient of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{anisotropy}
|
||||
\vspace{12pt}
|
||||
Scattering anisotropy [-1,1]. Negative values give backwards scattering,
|
||||
positive values give forward scattering, and 0.0 gives uniform scattering.
|
||||
\apiend
|
||||
|
||||
\apiitem{ior}
|
||||
\vspace{12pt}
|
||||
Refraction index of the medium.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{priority}
|
||||
\vspace{12pt}
|
||||
Priority of this medium (for nested dielectrics).
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
% \vspace{-16pt}
|
||||
|
||||
% \apiitem{label}
|
||||
% \vspace{12pt}
|
||||
% Optional string parameter to name this component. For use in AOVs / LPEs.
|
||||
% \apiend
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Light emission closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce uniform_edf} (color emittance)}
|
||||
\indexapi{uniform_edf}
|
||||
Constructs an EDF emitting light uniformly in all directions.
|
||||
This is used to represent a glowing/emissive material.
|
||||
When called in the context of a surface shader group, it implies that
|
||||
light is emitted in a full hemisphere centered around the surface
|
||||
normal. When called in the context of a volume shader group, it implies
|
||||
that light is emitted evenly in all directions around the point being
|
||||
shaded.
|
||||
|
||||
The {\cf emittance} parameter is the amount of emission and
|
||||
has units of radiance (e.g.,
|
||||
$\mathrm{W}\cdot\mathrm{sr}^{-1}\cdot\mathrm{m}^{-2}$). This means that a surface
|
||||
directly seen by the camera will directly reproduce the closure weight in the
|
||||
final pixel, regardless of being a surface or a volume.
|
||||
|
||||
For an emissive surface, if you divide the return value of {\cf uniform_edf()} by
|
||||
{\cf surfacearea() * M_PI}, then you can easily specify the total emissive
|
||||
power of the light (e.g., $\mathrm{W}$), regardless of its physical size.
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Layering and Signaling closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce layer} (closure color top, closure color base)}
|
||||
\indexapi{layer()}
|
||||
Vertically layer a layerable BSDF such as {\cf dielectric_bsdf},
|
||||
{\cf generalized_schlick_bsdf} or {\cf sheen_bsdf} over a BSDF or VDF. The
|
||||
implementation is target specific, but a standard way of handling this is by
|
||||
albedo scaling, using {\cf base*(1-reflectance(top)) + top}, where
|
||||
reflectance() calculates the directional albedo of a given top BSDF.
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce holdout} ( )}
|
||||
\indexapi{holdout()}
|
||||
Returns a \colorclosure that does not represent any additional light
|
||||
reflection from the surface, but does signal to the renderer that
|
||||
the surface is a \emph{holdout object} (appears transparent in
|
||||
the final output yet hides objects behind it). ``Partial holdouts''
|
||||
may be designated by weighting the {\cf holdout()} closure by a
|
||||
weight that is less than 1.0.
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce debug} (string outputname)}
|
||||
\indexapi{debug()}
|
||||
Returns a \colorclosure that does not represent any additional light
|
||||
reflection from the surface, but does signal to the renderer to add
|
||||
the weight of the closure (which may be a {\cf float} or a \color)
|
||||
to the named output (i.e., AOV).
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Material utility functions}
|
||||
|
||||
\apiitem{void {\ce artistic_ior} (color reflectivity, color edge_tint, \\
|
||||
\spc\spc output color ior, output color extinction)}
|
||||
\indexapi{artistic_ior()}
|
||||
Converts the artistic parameterization reflectivity and edge_tint to complex IOR values.
|
||||
To be used with the conductor_bsdf() closure.
|
||||
|
||||
\noindent Parameters include:
|
||||
|
||||
\apiitem{reflectivity}
|
||||
\vspace{12pt}
|
||||
Reflectivity per color channel at facing angles (\emph{r} parameter in [OG14])
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{edge_tint}
|
||||
\vspace{12pt}
|
||||
Color bias for grazing angles (\emph{g} parameter in [OG14]).
|
||||
NOTE: This is not equal to 'f90' in a Schlick Fresnel parameterization.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{ior}
|
||||
\vspace{12pt}
|
||||
Output refraction index.
|
||||
\apiend
|
||||
\vspace{-16pt}
|
||||
|
||||
\apiitem{extinction}
|
||||
\vspace{12pt}
|
||||
Output extinction coefficient.
|
||||
\apiend
|
||||
% \vspace{-16pt}
|
||||
|
||||
Reference: [OG14] Ole Gulbrandsen, "Artist Friendly Metallic Fresnel", Journal
|
||||
of Computer Graphics Tools 3(4), 2014.
|
||||
\url{http://jcgt.org/published/0003/04/03/paper.pdf}
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Deprecated closures}
|
||||
|
||||
These were described in the original OSL language specification, but
|
||||
beginning with OSL 1.12, these are considered deprecated. Support for
|
||||
them will be removed entirely in OSL 2.0.
|
||||
|
||||
\subsubsection{Deprecated Surface closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce diffuse} (normal N)}
|
||||
\indexapi{diffuse()}
|
||||
@@ -4664,7 +5344,7 @@ Nayar, ``Generalization of Lambert's Reflectance Model,'' Proceedings of
|
||||
SIGGRAPH 1994, pp.239-246 (July, 1994).
|
||||
|
||||
\begin{comment}
|
||||
Like all \closurecolors, the return ``value'' is symbolic and is may be
|
||||
Like all \closurecolors, the return ``value'' is symbolic and may be
|
||||
evaluated at a later time convenient to the renderer in order to compute
|
||||
the exitant radiance in the direction {\cf -I}. But aside from the
|
||||
fact that the shader cannot examine the numeric values of the
|
||||
@@ -4745,33 +5425,6 @@ implemented as follows:
|
||||
\end{comment}
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce microfacet} (string distribution, normal N, vector
|
||||
U, \\ \bigspc\bigspc float xalpha, float yalpha, float eta, int refract)}
|
||||
\indexapi{microfacet()}
|
||||
|
||||
Returns a \colorclosure that represents scattering on the
|
||||
surface using some microfacet distribution such as \qkw{beckmann} or \qkw{ggx} (as
|
||||
described in Walter et al., ``Microfacet Models for Refraction through Rough
|
||||
Surfaces,'' Eurographics Symposium on Rendering, 2007).
|
||||
Both {\cf xalpha} and {\cf yalpha} control how rough the microstructure of the
|
||||
surface is, possibly in an anisotropic way if they are different. In the
|
||||
anisotropic case {\cf U} must be a vector orthogonal to {\cf N} to specify the
|
||||
direction. These values are expected to be the alpha values of the distribution
|
||||
as it appears in the literature, not a universal roughness measure.
|
||||
The {\cf eta} parameter is the index of refraction of the material, and
|
||||
{\cf refract} is a enumeration flag that controls if the BSDF is reflective ({\cf 0}),
|
||||
refractive ({\cf 1}) or both at once ({\cf 2}). The implementation must not rely on
|
||||
{\cf U} when the roughness is isotropic or the given vector is zero.
|
||||
|
||||
The list of supported distributions will change from renderer to renderer, and
|
||||
also the behavior when an unsupported distribution is requested. It is up to the
|
||||
implementation to issue an error or to default to a supported one. Also it is
|
||||
expected that the alias \qkw{default} must work as a distribution in any renderer.
|
||||
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce microfacet} (string distribution, normal N,
|
||||
\\ \bigspc\bigspc float alpha, float eta, int refract)}
|
||||
\indexapi{microfacet()}
|
||||
@@ -4823,7 +5476,6 @@ implemented as follows:
|
||||
\end{code}
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce transparent} ( )}
|
||||
\indexapi{transparent()}
|
||||
|
||||
@@ -4867,8 +5519,7 @@ scattering} exhibited by the surface.
|
||||
\apiend
|
||||
\end{comment}
|
||||
|
||||
|
||||
\subsection{Volumetric material closures}
|
||||
\subsubsection{Deprecated Volumetric closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce isotropic} ( )}
|
||||
\indexapi{isotropic}
|
||||
@@ -4877,18 +5528,16 @@ volumetric material, scattering light evenly in all directions,
|
||||
regardless of its original direction.
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce henyey_greenstein} (float g)}
|
||||
\indexapi{henyey_greenstein}
|
||||
Returns a \colorclosure that represents the directional volumetric
|
||||
scattering by small suspended particles. The {\cf g} parameter is the
|
||||
anisotropy factor, ranging from $-1$ to $1$), with positive values
|
||||
anisotropy factor, in the range $(-1, 1)$, with positive values
|
||||
indicating predominantly forward-scattering, negative values indicating
|
||||
predominantly back-scattering, and value of $g=0$ resulting in isotropic
|
||||
scattering.
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce absorption} ( )}
|
||||
\indexapi{absorption}
|
||||
Returns a \colorclosure that does not represent any additional
|
||||
@@ -4898,8 +5547,7 @@ volumetric material, scattering light evenly in all directions,
|
||||
regardless of its original direction.
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Light emission closures}
|
||||
\subsubsection{Deprecated Emission closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce emission} ( )}
|
||||
\indexapi{emission}
|
||||
@@ -4915,7 +5563,7 @@ $\mathrm{W}\cdot\mathrm{sr}^{-1}\cdot\mathrm{m}^{-2}$). This means that a surfac
|
||||
directly seen by the camera will directly reproduce the closure weight in the
|
||||
final pixel, regardless of being a surface or a volume.
|
||||
|
||||
For surface emission, If you divide {\cf emission()} by
|
||||
For an emissive surface, if you divide the return value of {\cf emission()} by
|
||||
{\cf surfacearea() * M_PI}, then you can easily specify the total emissive
|
||||
power of the light (e.g., $\mathrm{W}$), regardless of its physical size.
|
||||
\apiend
|
||||
@@ -4930,30 +5578,6 @@ up from an HDRI environment map.
|
||||
\apiend
|
||||
|
||||
|
||||
\subsection{Signaling closures}
|
||||
|
||||
\apiitem{\colorclosure\ {\ce holdout} ( )}
|
||||
\indexapi{holdout()}
|
||||
Returns a \colorclosure that does not represent any additional light
|
||||
reflection from the surface, but does signal to the renderer that
|
||||
the surface is a \emph{holdout object} (appears transparent in
|
||||
the final output yet hides objects behind it). ``Partial holdouts''
|
||||
may be designated by weighting the {\cf holdout()} closure by a
|
||||
weight that is less than 1.0.
|
||||
\apiend
|
||||
|
||||
|
||||
\apiitem{\colorclosure\ {\ce debug} (string outputname)}
|
||||
\indexapi{debug()}
|
||||
Returns a \colorclosure that does not represent any additional light
|
||||
reflection from the surface, but does signal to the renderer to add
|
||||
the weight of the closure (which may be a {\cf float} or a \color)
|
||||
to the named output (i.e., AOV).
|
||||
\apiend
|
||||
|
||||
|
||||
|
||||
|
||||
\newpage
|
||||
\section{Renderer state and message passing}
|
||||
\label{sec:stdlib:state}
|
||||
@@ -5750,7 +6374,7 @@ programming language design)?
|
||||
|
||||
This spec is written assuming that \color should explicitly be
|
||||
3-component RGB. Alternately, we could add global \inttype\ {\cf ncomps} that gives the
|
||||
numer of components in a \color, and eliminate any built-in operations
|
||||
number of components in a \color, and eliminate any built-in operations
|
||||
and library functions that seem to require or imply a 3-component color
|
||||
model (including type casting between \color and the 3-component
|
||||
\point-like types).
|
||||
@@ -5862,7 +6486,7 @@ anybody want to argue for any of the following to be included?
|
||||
|
||||
We have defined structures as being allowed to consist only of basic
|
||||
types and arrays thereof --- not structures of structures. This
|
||||
restriction makes for a simpler grammar and implementation, simplier
|
||||
restriction makes for a simpler grammar and implementation, simpler
|
||||
renderer-side APIs for passing data to shaders, and simpler APIs for
|
||||
libraries that query parameters of compiled shaders. But if people
|
||||
strongly feel like structures-of-structures is an important feature, we
|
||||
@@ -5948,7 +6572,7 @@ about it.
|
||||
|
||||
\subsection{Nomenclature}
|
||||
|
||||
Does anybody have a perference for \dPdu and \dPdv (borrowing the
|
||||
Does anybody have a preference for \dPdu and \dPdv (borrowing the
|
||||
RenderMan names, but awkward for primitives without a consistent $u,v$
|
||||
parameterization?), versus something more generic such as {\cf T} and
|
||||
{\cf B} (tangent and bitangent, without explicitly saying how they are
|
||||
@@ -6134,6 +6758,9 @@ full control in the shader.
|
||||
may be shared among multiple geometric primitives. Also sometimes
|
||||
called \emph{graphics state}.
|
||||
|
||||
\item[BSDF.] Bidirectional scattering distribution function, a
|
||||
function that describes light scattering properties of a surface.
|
||||
|
||||
\item[Built-in function.] A function callable from within a shader, where
|
||||
the implementation of the function is provided by the renderer (as
|
||||
opposed to a function that the shader author writes in \langname
|
||||
@@ -6144,7 +6771,7 @@ full control in the shader.
|
||||
at a later time to yield a final numeric value.
|
||||
|
||||
\item[Connection.] A routing of the value of an \emph{output parameter}
|
||||
of one \emph{shader layer} to an \emph{input paramter} of another
|
||||
of one \emph{shader layer} to an \emph{input parameter} of another
|
||||
shader layer within the same \emph{shader group}.
|
||||
|
||||
\item[Default parameter value.] The initial value of a \emph{shader
|
||||
@@ -6155,6 +6782,9 @@ full control in the shader.
|
||||
is explicitly given in the code for that shader, and may either be
|
||||
a constant or a computed expression.
|
||||
|
||||
\item[EDF.] Emission distribution function, a function that describes
|
||||
the distribution of light emitted by a light source.
|
||||
|
||||
\item[Geometric primitive.] A single shape, such as a NURBS patch, a
|
||||
polygon or subdivision mesh, a hair primitive, etc.
|
||||
|
||||
@@ -6190,7 +6820,7 @@ full control in the shader.
|
||||
|
||||
\item[Primitive variable.] A named variable, and values, attached to an
|
||||
individual geometric primitive. Primitive variables may have one of
|
||||
serveral \emph{interpolation methods} --- such as a single value for
|
||||
several \emph{interpolation methods} --- such as a single value for
|
||||
the whole primitive, a value for each piece or face of the primitive,
|
||||
or per-vertex values that are smoothly interpolated across the
|
||||
surface.
|
||||
@@ -6199,12 +6829,12 @@ full control in the shader.
|
||||
that is visible and directly callable by the renderer, as opposed to
|
||||
merely being called from other code within the shader. Public methods
|
||||
must be \emph{top-level} (not defined within other functions) and must
|
||||
be preceeded by the {\cf public} keyword.
|
||||
be preceded by the {\cf public} keyword.
|
||||
|
||||
\item[Shader.] A small self-contained program written in \langname, used
|
||||
to extend the functionality of a renderer with custom behavior of
|
||||
materials and lights. A particular shader may have multiple
|
||||
\emph{shader instances} within a scene, each of which has ts unique
|
||||
\emph{shader instances} within a scene, each of which has its unique
|
||||
\emph{instance parameters}, transformation, etc.
|
||||
|
||||
\item[Shader function.] A function written in \langname that may be
|
||||
@@ -6239,6 +6869,9 @@ full control in the shader.
|
||||
\item[Shading.] The computations within a renderer that implement the
|
||||
behavior and visual appearance of materials and lights.
|
||||
|
||||
\item[VDF.] Volumetric distribution function, a function that describes
|
||||
the scattering properties of a volume.
|
||||
|
||||
\end{description}
|
||||
|
||||
\end{appendix}
|
||||
|
||||
Binary file not shown.
@@ -11,7 +11,7 @@
|
||||
_testshade_ basics
|
||||
==================================================
|
||||
|
||||
The OSL software distribution inculdes `testshade`, a command-line utility
|
||||
The OSL software distribution includes `testshade`, a command-line utility
|
||||
that was written for OSL unit tests, and for a "test harness" in which we
|
||||
can execute shaders for debugging (the shaders or OSL itself) in isolation
|
||||
from any particular rendering system.
|
||||
@@ -28,7 +28,7 @@ itself, it has a number of potential uses in a production studio, including:
|
||||
* Baking procedural patterns into textures.
|
||||
|
||||
* Benchmarking shaders and evaluating their performance, including
|
||||
comparitive tests such as "is it faster to code it this way or that way?"
|
||||
comparative tests such as "is it faster to code it this way or that way?"
|
||||
|
||||
* Exploring the inner workings of OSL's runtime optimizer, to answer
|
||||
questions like: "will this idiom optimize away at runtime when I use
|
||||
@@ -176,7 +176,7 @@ Helpful command line arguments:
|
||||
|
||||
For the sake of simplicity, this document presents almost all examples as if
|
||||
they consisted of just a single shader node. But `testshade` is able to
|
||||
specify and execut entire shader groups (networks of shader nodes). The
|
||||
specify and execute entire shader groups (networks of shader nodes). The
|
||||
remainder of this section will explain how this can be done.
|
||||
|
||||
Let's make a simple shader network as an example.
|
||||
@@ -582,7 +582,7 @@ single texture lookup.
|
||||
|
||||
|
||||
|
||||
## Controling optimization
|
||||
## Controlling optimization
|
||||
|
||||
You can control the optimization level overall:
|
||||
|
||||
@@ -638,7 +638,7 @@ that they are not optimized away so as to lead you to an inaccurate
|
||||
reflection of what optimizations would really happen at render time. At the
|
||||
same time, be careful not to inadvertently set `lockgeom=0` for parameters
|
||||
that will typically be set to default values, instance values, or
|
||||
connections from layers that are likely to be analized and found to emit
|
||||
connections from layers that are likely to be analyzed and found to emit
|
||||
constants for theor outputs -- you also don't want your benchmarks to
|
||||
incorrectly disable optimizations what would typically happen at render
|
||||
time.
|
||||
|
||||
@@ -16,9 +16,21 @@
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
#if OSL_USING_IMATH < 3
|
||||
# include <OSL/matrix22.h>
|
||||
#endif
|
||||
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
|
||||
#if OSL_USING_IMATH >= 3
|
||||
using Matrix22 = Imath::Matrix22<Float>;
|
||||
#else
|
||||
using Matrix22 = Imathx::Matrix22<Float>;
|
||||
#endif
|
||||
|
||||
|
||||
// Choose to treat helper functions as static
|
||||
// so their symbols don't escape and possibly collide
|
||||
// with other compilation units who might be compiled with
|
||||
@@ -246,7 +258,7 @@ affineInverse(const Matrix44 &m)
|
||||
// differently than the LLVM IR version.
|
||||
// NOTE: only using "inline" to get ODR (One Definition Rule) behavior
|
||||
static inline OSL_HOSTDEVICE Matrix44
|
||||
#if !OSL_INTEL_COMPILER
|
||||
#if !OSL_INTEL_CLASSIC_COMPILER_VERSION
|
||||
OSL_GNUC_ATTRIBUTE(optimize("fp-contract=off"))
|
||||
#endif
|
||||
nonAffineInverse(const Matrix44 &source);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -62,7 +62,9 @@ public:
|
||||
virtual Mask get_matrix(BatchedShaderGlobals* bsg, Masked<Matrix44> wresult,
|
||||
Wide<const TransformationPtr> wxform,
|
||||
Wide<const float> wtime)
|
||||
= 0;
|
||||
{
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
/// Get the 4x4 matrix that transforms by the specified
|
||||
/// transformation at the given time. Return a Mask with lanes set to true
|
||||
@@ -81,7 +83,9 @@ public:
|
||||
/// is not known.
|
||||
virtual Mask get_matrix(BatchedShaderGlobals* bsg, Masked<Matrix44> wresult,
|
||||
ustring from, Wide<const float> wtime)
|
||||
= 0;
|
||||
{
|
||||
return Mask(false);
|
||||
}
|
||||
virtual Mask get_matrix(BatchedShaderGlobals* bsg, Masked<Matrix44> result,
|
||||
Wide<const ustring> wfrom, Wide<const float> wtime);
|
||||
virtual bool is_overridden_get_matrix_WmWsWf() const = 0;
|
||||
@@ -108,8 +112,12 @@ public:
|
||||
/// Identify if the the named attribute from the renderer can be treated as uniform
|
||||
/// across all batches to the shader. We assume all attributes are varying unless
|
||||
/// identified as uniform by the renderer. NOTE: To enable constant folding of
|
||||
// an attribute value, it must be uniform and retrievable with a NULL BatchedShaderGlobals
|
||||
virtual bool is_attribute_uniform(ustring object, ustring name) = 0;
|
||||
/// an attribute value, it must be uniform and retrievable with
|
||||
/// a NULL BatchedShaderGlobals
|
||||
virtual bool is_attribute_uniform(ustring object, ustring name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Get the named attribute from the renderer and if found then
|
||||
/// write it into 'val'. Otherwise, return false. If no object is
|
||||
@@ -118,25 +126,33 @@ public:
|
||||
/// unsuccessful, on the currently shaded "scene".
|
||||
virtual Mask get_attribute(BatchedShaderGlobals* bsg, ustring object,
|
||||
ustring name, MaskedData wval)
|
||||
= 0;
|
||||
{
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
/// Similar to get_attribute(); this method will fetch the 'index'
|
||||
/// element of an attribute array.
|
||||
virtual Mask get_array_attribute(BatchedShaderGlobals* bsg, ustring object,
|
||||
ustring name, int index, MaskedData wval)
|
||||
= 0;
|
||||
{
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
virtual bool get_attribute_uniform(BatchedShaderGlobals* bsg,
|
||||
ustring object, ustring name,
|
||||
RefData val)
|
||||
= 0;
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Similar to get_attribute(); this method will fetch the 'index'
|
||||
/// element of an attribute array.
|
||||
virtual bool get_array_attribute_uniform(BatchedShaderGlobals* bsg,
|
||||
ustring object, ustring name,
|
||||
int index, RefData val)
|
||||
= 0;
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Get multiple named user-data from the current object and write them into
|
||||
/// 'val'. If derivatives is true, the derivatives should be written into val
|
||||
@@ -145,7 +161,9 @@ public:
|
||||
/// found.
|
||||
virtual Mask get_userdata(ustring name, BatchedShaderGlobals* bsg,
|
||||
MaskedData wval)
|
||||
= 0;
|
||||
{
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
// Currently texture handles are serviced by the non-batched
|
||||
// RendererServices interface. If necessary, customized ones could
|
||||
@@ -298,6 +316,119 @@ public:
|
||||
ustring filename, TextureSystem::TextureHandle* texture_handle,
|
||||
int subimage, ustring dataname, RefData val);
|
||||
|
||||
|
||||
/// Lookup nearest points in a point cloud. It will search for
|
||||
/// points around the given center within the specified radius. A
|
||||
/// list of indices is returned so the programmer can later retrieve
|
||||
/// attributes with pointcloud_get. The indices array is mandatory,
|
||||
/// but distances MaskedData can be invalid (empty), may or may not
|
||||
/// have derivs, will always be float[], and contains the mask to use
|
||||
/// for the operations.
|
||||
///
|
||||
/// out_num_points will contain the number of points found, always < max_points
|
||||
|
||||
// To enable sharing of single mask with multiple outputs we use
|
||||
// a class to encapsulate multiple wide pointers with a single mask.
|
||||
// Because the Masked accessors will be constructed by the helper methods
|
||||
// once inlined compilers will see the same mask_value is used for both.
|
||||
class PointCloudSearchResults {
|
||||
void* m_wnum_points;
|
||||
void* m_windices;
|
||||
int m_indices_array_length;
|
||||
void* m_wdistances;
|
||||
int m_distances_array_length;
|
||||
bool m_distances_have_derivs;
|
||||
Mask m_mask;
|
||||
|
||||
public:
|
||||
PointCloudSearchResults(void* wnum_points, void* windices,
|
||||
int indices_array_length, void* wdistances,
|
||||
int distances_array_length,
|
||||
int distances_have_derivs, int mask_value)
|
||||
: m_wnum_points(wnum_points)
|
||||
, m_windices(windices)
|
||||
, m_indices_array_length(indices_array_length)
|
||||
, m_wdistances(wdistances)
|
||||
, m_distances_array_length(distances_array_length)
|
||||
, m_distances_have_derivs(distances_have_derivs)
|
||||
, m_mask(mask_value)
|
||||
{
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE Mask mask() const { return m_mask; }
|
||||
|
||||
// NOTE: Always assign to a local object before calling an
|
||||
// array subscript operator []. Bugs can occur if the []
|
||||
// is called on a temporary object as a reference to a
|
||||
// temporary object would be created.
|
||||
// DO NOT DO THIS:
|
||||
// auto out_num_points = results.wnum_points()[lane];
|
||||
// instead
|
||||
// auto wnum_points = results.wnum_points();
|
||||
// auto out_num_points = wnum_points[lane];
|
||||
|
||||
OSL_FORCEINLINE Masked<int> wnum_points() const
|
||||
{
|
||||
return Masked<int>(m_wnum_points, m_mask);
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE Masked<int[]> windices() const
|
||||
{
|
||||
return Masked<int[]>(m_windices, m_indices_array_length, m_mask);
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE bool has_distances() const
|
||||
{
|
||||
return m_wdistances != nullptr;
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE Masked<float[]> wdistances() const
|
||||
{
|
||||
return Masked<float[]>(m_wdistances, m_distances_array_length,
|
||||
m_mask);
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE bool distances_have_derivs() const
|
||||
{
|
||||
return m_distances_have_derivs;
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE MaskedDx<float[]> wdistancesDx() const
|
||||
{
|
||||
return MaskedDx<float[]>(m_wdistances, m_distances_array_length,
|
||||
m_mask);
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE MaskedDy<float[]> wdistancesDy() const
|
||||
{
|
||||
return MaskedDy<float[]>(m_wdistances, m_distances_array_length,
|
||||
m_mask);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
virtual void pointcloud_search(BatchedShaderGlobals* bsg, ustring filename,
|
||||
const void* wcenter,
|
||||
Wide<const float> wradius, int max_points,
|
||||
bool sort, PointCloudSearchResults& results);
|
||||
virtual bool is_overridden_pointcloud_search() const = 0;
|
||||
|
||||
|
||||
virtual Mask pointcloud_get(BatchedShaderGlobals* bsg, ustring filename,
|
||||
Wide<const int[]> windices,
|
||||
Wide<const int> wnum_points, ustring attr_name,
|
||||
MaskedData wout_data);
|
||||
virtual bool is_overridden_pointcloud_get() const = 0;
|
||||
|
||||
|
||||
virtual Mask pointcloud_write(BatchedShaderGlobals* bsg, ustring filename,
|
||||
Wide<const OSL::Vec3> wpos, int nattribs,
|
||||
const ustring* attr_names,
|
||||
const TypeDesc* attr_types,
|
||||
const void** pointers_to_wide_attr_value,
|
||||
Mask mask);
|
||||
virtual bool is_overridden_pointcloud_write() const = 0;
|
||||
|
||||
/// Options for the trace call.
|
||||
using TraceOpt = RendererServices::TraceOpt;
|
||||
|
||||
|
||||
@@ -43,13 +43,6 @@ struct UniformShaderGlobals {
|
||||
/// way back to the renderer for callbacks.
|
||||
RendererServices* renderer;
|
||||
|
||||
/// The output closure will be placed here. The rendererer should
|
||||
/// initialize this to NULL before shading execution, and this is where
|
||||
/// it can retrieve the output closure from after shader execution has
|
||||
/// completed.
|
||||
/// DESIGN DECISION: NOT CURRENTLY SUPPORTING CLOSURES IN BATCH MODE
|
||||
ClosureColor* Ci;
|
||||
|
||||
/// Bit field of ray type flags.
|
||||
int raytype;
|
||||
|
||||
@@ -59,6 +52,8 @@ struct UniformShaderGlobals {
|
||||
int pad0;
|
||||
int pad1;
|
||||
int pad2;
|
||||
int pad3;
|
||||
int pad4;
|
||||
|
||||
void dump()
|
||||
{
|
||||
@@ -70,7 +65,6 @@ struct UniformShaderGlobals {
|
||||
__OSL_DUMP(objdata);
|
||||
__OSL_DUMP(context);
|
||||
__OSL_DUMP(renderer);
|
||||
__OSL_DUMP(Ci);
|
||||
__OSL_DUMP(raytype);
|
||||
|
||||
std::cout << "};" << std::endl;
|
||||
@@ -129,6 +123,12 @@ template<int WidthT> struct alignas(64) VaryingShaderGlobals {
|
||||
Block<TransformationPtr> object2common;
|
||||
Block<TransformationPtr> shader2common;
|
||||
|
||||
/// The output closure will be placed here. The rendererer should
|
||||
/// initialize this to NULL before shading execution, and this is where
|
||||
/// it can retrieve the output closure from after shader execution has
|
||||
/// completed.
|
||||
Block<ClosureColor*> Ci;
|
||||
|
||||
/// Surface area of the emissive object (used by light shaders for
|
||||
/// energy normalization).
|
||||
Block<float> surfacearea;
|
||||
@@ -168,6 +168,7 @@ template<int WidthT> struct alignas(64) VaryingShaderGlobals {
|
||||
__OSL_DUMP(dPsdy);
|
||||
__OSL_DUMP(object2common);
|
||||
__OSL_DUMP(shader2common);
|
||||
__OSL_DUMP(Ci);
|
||||
__OSL_DUMP(surfacearea);
|
||||
__OSL_DUMP(flipHandedness);
|
||||
__OSL_DUMP(backfacing);
|
||||
|
||||
@@ -135,77 +135,77 @@ static_assert(sizeof(OIIO::TextureOptBatch)
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, sblur)
|
||||
== varying_offset + offsetof(VTO, sblur),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, tblur)
|
||||
== varying_offset + offsetof(VTO, tblur),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, rblur)
|
||||
== varying_offset + offsetof(VTO, rblur),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, swidth)
|
||||
== varying_offset + offsetof(VTO, swidth),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, twidth)
|
||||
== varying_offset + offsetof(VTO, twidth),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, rwidth)
|
||||
== varying_offset + offsetof(VTO, rwidth),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, firstchannel)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, firstchannel),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, subimage)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, subimage),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, subimagename)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, subimagename),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, swrap)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, swrap),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, twrap)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, twrap),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, rwrap)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, rwrap),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, mipmode)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, mipmode),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, interpmode)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, interpmode),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, anisotropic)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, anisotropic),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, conservative_filter)
|
||||
== uniform_offset
|
||||
+ offsetof(UniformTextureOptions, conservative_filter),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, fill)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, fill),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
static_assert(
|
||||
offsetof(OIIO::TextureOptBatch, missingcolor)
|
||||
== uniform_offset + offsetof(UniformTextureOptions, missingcolor),
|
||||
"BatchedTextureOptions members offset different that OIIO::TextureOptBatch");
|
||||
"BatchedTextureOptions members offset different than OIIO::TextureOptBatch");
|
||||
|
||||
OSL_PRAGMA_WARNING_POP
|
||||
} // namespace validate_offsets
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
#ifdef __CUDA_ARCH__
|
||||
#include <optix.h>
|
||||
# include <optix.h>
|
||||
#endif
|
||||
|
||||
// USAGE NOTES:
|
||||
@@ -36,20 +36,20 @@ OSL_NAMESPACE_ENTER
|
||||
// stored in the table, in the 16 bytes preceding the characters.
|
||||
|
||||
struct DeviceString {
|
||||
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
|
||||
size_t m_chars;
|
||||
#ifdef __CUDA_ARCH__
|
||||
size_t m_chars;
|
||||
#else
|
||||
const char* m_chars;
|
||||
#endif
|
||||
|
||||
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
|
||||
#ifdef __CUDA_ARCH__
|
||||
OSL_HOSTDEVICE DeviceString() {}
|
||||
OSL_HOSTDEVICE DeviceString(uint64_t i) : m_chars(i) {}
|
||||
#endif
|
||||
|
||||
OSL_HOSTDEVICE uint64_t hash() const
|
||||
{
|
||||
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
|
||||
#ifdef __CUDA_ARCH__
|
||||
return m_chars;
|
||||
#else
|
||||
return *(uint64_t*)(m_chars - sizeof(uint64_t) - sizeof(uint64_t));
|
||||
@@ -58,7 +58,7 @@ struct DeviceString {
|
||||
|
||||
// In OptiX 7 we don't store the string's length. Make this a compile
|
||||
// time error.
|
||||
#if ! (defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000)
|
||||
#ifndef __CUDA_ARCH__
|
||||
OSL_HOSTDEVICE uint64_t length() const
|
||||
{
|
||||
return *(uint64_t*)(m_chars - sizeof(uint64_t));
|
||||
@@ -67,36 +67,39 @@ struct DeviceString {
|
||||
|
||||
// In OptiX 7 we can't return the string's contents. Make this a compile
|
||||
// time error.
|
||||
#if ! (defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000)
|
||||
#ifndef __CUDA_ARCH__
|
||||
OSL_HOSTDEVICE const char* c_str() const
|
||||
{
|
||||
return m_chars;
|
||||
}
|
||||
#endif
|
||||
|
||||
OSL_HOSTDEVICE bool operator== (const DeviceString& other) const
|
||||
OSL_HOSTDEVICE bool operator==(const DeviceString& other) const
|
||||
{
|
||||
return m_chars == other.m_chars;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE bool operator!= (const DeviceString& other) const
|
||||
OSL_HOSTDEVICE bool operator!=(const DeviceString& other) const
|
||||
{
|
||||
return m_chars != other.m_chars;
|
||||
}
|
||||
|
||||
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
|
||||
#ifdef __CUDA_ARCH__
|
||||
|
||||
OSL_HOSTDEVICE bool operator== (const size_t other) const
|
||||
OSL_HOSTDEVICE bool operator==(const size_t other) const
|
||||
{
|
||||
return hash() == other;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE bool operator!= (const size_t other) const
|
||||
OSL_HOSTDEVICE bool operator!=(const size_t other) const
|
||||
{
|
||||
return hash() != other;
|
||||
}
|
||||
|
||||
OSL_HOSTDEVICE operator size_t() const { return hash(); }
|
||||
OSL_HOSTDEVICE operator size_t() const
|
||||
{
|
||||
return hash();
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
@@ -106,9 +109,9 @@ struct DeviceString {
|
||||
// macro is the same as the USTR macro defined in oslexec_pvt.h when compiling
|
||||
// for the host.
|
||||
#ifndef __CUDA_ARCH__
|
||||
# define HDSTR(cstr) (*((ustring *)&cstr))
|
||||
# define HDSTR(cstr) (*((ustring*)&cstr))
|
||||
#else
|
||||
#define HDSTR(cstr) (*((OSL::DeviceString*)&cstr))
|
||||
# define HDSTR(cstr) (*((OSL::DeviceString*)&cstr))
|
||||
#endif
|
||||
|
||||
|
||||
@@ -124,25 +127,22 @@ typedef DeviceString StringParam;
|
||||
|
||||
#ifdef __CUDA_ARCH__
|
||||
namespace DeviceStrings {
|
||||
#define STRDECL(str,var_name) \
|
||||
extern __device__ OSL_NAMESPACE::DeviceString var_name;
|
||||
#if OPTIX_VERSION < 70000
|
||||
# include <OSL/strdecls.h>
|
||||
#endif
|
||||
#undef STRDECL
|
||||
}
|
||||
# define STRDECL(str, var_name) \
|
||||
extern __device__ OSL_NAMESPACE::DeviceString var_name;
|
||||
# undef STRDECL
|
||||
} // namespace DeviceStrings
|
||||
#else
|
||||
# define STRING_PARAMS(x) StringParams::x
|
||||
# ifdef OSL_HOST_RS_BITCODE
|
||||
# define STRING_PARAMS(x) RS_##x
|
||||
# else
|
||||
# define STRING_PARAMS(x) StringParams::x
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
|
||||
#ifdef __CUDA_ARCH__
|
||||
#if OPTIX_VERSION < 70000
|
||||
namespace StringParams = OSL_NAMESPACE::DeviceStrings;
|
||||
#endif
|
||||
#else
|
||||
#ifndef __CUDA_ARCH__
|
||||
namespace StringParams = OSL_NAMESPACE::Strings;
|
||||
#endif
|
||||
|
||||
@@ -223,7 +223,7 @@ public:
|
||||
// delegating access to element storage to the DualStorage base class
|
||||
template<
|
||||
class T, // Base data type
|
||||
int PARTIALS=1 // Number of dimentions of partial derivs
|
||||
int PARTIALS=1 // Number of dimensions of partial derivs
|
||||
>
|
||||
class Dual : public DualStorage<T, PARTIALS> {
|
||||
static const int elements = PARTIALS+1; // main value + partials
|
||||
|
||||
+497
-406
File diff suppressed because it is too large
Load Diff
+39
-11
@@ -4,7 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <immintrin.h>
|
||||
#include <type_traits>
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
@@ -21,7 +20,9 @@ OSL_NAMESPACE_ENTER
|
||||
using std::popcount;
|
||||
using std::countr_zero;
|
||||
|
||||
#elif OSL_INTEL_COMPILER
|
||||
#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); }
|
||||
@@ -170,13 +171,22 @@ public:
|
||||
}
|
||||
|
||||
|
||||
OSL_FORCEINLINE ValueType value() const { return m_value; }
|
||||
OSL_FORCEINLINE ValueType value() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
// count number of active bits
|
||||
OSL_FORCEINLINE int count() const { return OSL::popcount(m_value); }
|
||||
OSL_FORCEINLINE int count() const
|
||||
{
|
||||
return OSL::popcount(m_value);
|
||||
}
|
||||
|
||||
// NOTE: undefined result if no bits are on
|
||||
OSL_FORCEINLINE int first_on() const { return OSL::countr_zero(m_value); }
|
||||
OSL_FORCEINLINE int first_on() const
|
||||
{
|
||||
return OSL::countr_zero(m_value);
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE Mask invert() const
|
||||
{
|
||||
@@ -229,7 +239,10 @@ public:
|
||||
return (m_value != static_cast<ValueType>(0));
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE bool any_off() const { return (m_value < valid_bits); }
|
||||
OSL_FORCEINLINE bool any_off() const
|
||||
{
|
||||
return (m_value < valid_bits);
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE bool any_off(const Mask& mask) const
|
||||
{
|
||||
@@ -244,27 +257,39 @@ public:
|
||||
// So really only set_on or set_off is required
|
||||
// Choose to not provide a generic set(int lane, bool flag)
|
||||
|
||||
OSL_FORCEINLINE void set_on(int lane) { m_value |= (1 << lane); }
|
||||
OSL_FORCEINLINE void set_on(int lane)
|
||||
{
|
||||
m_value |= (1 << lane);
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE void set_on_if(int lane, bool cond)
|
||||
{
|
||||
m_value |= (cond << lane);
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE void set_all_on() { m_value = valid_bits; }
|
||||
OSL_FORCEINLINE void set_all_on()
|
||||
{
|
||||
m_value = valid_bits;
|
||||
}
|
||||
OSL_FORCEINLINE void set_count_on(int count)
|
||||
{
|
||||
m_value = valid_bits >> (width - count);
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE void set_off(int lane) { m_value &= (~(1 << lane)); }
|
||||
OSL_FORCEINLINE void set_off(int lane)
|
||||
{
|
||||
m_value &= (~(1 << lane));
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE void set_off_if(int lane, bool cond)
|
||||
{
|
||||
m_value &= (~(cond << lane));
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE void set_all_off() { m_value = static_cast<ValueType>(0); }
|
||||
OSL_FORCEINLINE void set_all_off()
|
||||
{
|
||||
m_value = static_cast<ValueType>(0);
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE bool operator==(const Mask& other) const
|
||||
{
|
||||
@@ -298,7 +323,10 @@ public:
|
||||
return Mask(m_value | other.m_value);
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE Mask operator~() const { return invert(); }
|
||||
OSL_FORCEINLINE Mask operator~() const
|
||||
{
|
||||
return invert();
|
||||
}
|
||||
|
||||
|
||||
template<int MinOccupancyT, int MaxOccupancyT = width, typename FunctorT>
|
||||
|
||||
@@ -959,7 +959,7 @@ Matrix22<T>::inverse (bool singExc) const
|
||||
{
|
||||
#ifndef __CUDA_ARCH__
|
||||
if (singExc)
|
||||
throw Imath::SingMatrixExc ("Cannot invert "
|
||||
throw std::invalid_argument ("Cannot invert "
|
||||
"singular matrix.");
|
||||
#endif
|
||||
return Matrix22();
|
||||
|
||||
@@ -109,8 +109,14 @@ OSL_ALIGNAS(16) ClosureComponent : public ClosureColor
|
||||
Vec3 w; ///< Weight of this component
|
||||
|
||||
/// Handy method for getting the parameter memory as a void*.
|
||||
OSL_HOSTDEVICE void* data() { return (char*)(this + 1); }
|
||||
OSL_HOSTDEVICE const void* data() const { return (const char*)(this + 1); }
|
||||
OSL_HOSTDEVICE void* data()
|
||||
{
|
||||
return (char*)(this + 1);
|
||||
}
|
||||
OSL_HOSTDEVICE const void* data() const
|
||||
{
|
||||
return (const char*)(this + 1);
|
||||
}
|
||||
|
||||
/// Handy methods for extracting the underlying parameters as a struct
|
||||
template<typename T> OSL_HOSTDEVICE const T* as() const
|
||||
@@ -140,4 +146,10 @@ struct OSLEXECPUBLIC ClosureAdd : public ClosureColor {
|
||||
const ClosureColor* closureB;
|
||||
};
|
||||
|
||||
/// Type for pointers to closures
|
||||
typedef ClosureColor* ClosureColorPtr;
|
||||
typedef ClosureComponent* ClosureComponentPtr;
|
||||
typedef ClosureAdd* ClosureAddPtr;
|
||||
typedef ClosureMul* ClosureMulPtr;
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <OSL/platform.h>
|
||||
#include <OSL/export.h>
|
||||
#include <OSL/oslversion.h>
|
||||
#include <OSL/platform.h>
|
||||
|
||||
|
||||
// All the things we need from Imath.
|
||||
@@ -23,19 +23,33 @@
|
||||
# include <OSL/Imathx/ImathVec.h>
|
||||
# include <OSL/Imathx/ImathMatrix.h>
|
||||
# include <OSL/Imathx/ImathColor.h>
|
||||
# include <OSL/matrix22.h>
|
||||
#endif
|
||||
|
||||
// The fmt library causes trouble for Cuda. Work around by disabling it from
|
||||
// oiio headers (OIIO <= 2.1) or telling fmt not to use the troublesome
|
||||
// int128 that Cuda doesn't understand (OIIO >= 2.2).
|
||||
// We included the Imath files we needed, so set the OIIO_IMATH_H_INCLUDED
|
||||
// symbol to prevent OpenImageIO/Imath.h from including them again (or
|
||||
// before), which is critical if they turn out to be different versions.
|
||||
#define OIIO_IMATH_H_INCLUDED 1
|
||||
|
||||
|
||||
// The fmt library causes trouble for Cuda. Work around by telling fmt not to
|
||||
// use the troublesome int128 that Cuda doesn't understand.
|
||||
#ifdef __CUDA_ARCH__
|
||||
# define OIIO_USE_FMT 0
|
||||
# ifndef FMT_USE_INT128
|
||||
# define FMT_USE_INT128 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// For OSL internal compilation only, get deprecation warnings if we call OIIO
|
||||
// methods that use the old printf style interface.
|
||||
#ifdef OSL_INTERNAL
|
||||
# ifdef OIIO_ERRORHANDLER_HIDE_PRINTF
|
||||
# define OIIO_ERRORHANDLER_HIDE_PRINTF 1
|
||||
# endif
|
||||
# ifdef OIIO_HIDE_FORMAT
|
||||
# define OIIO_HIDE_FORMAT 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// All the things we need from OpenImageIO
|
||||
#include <OpenImageIO/oiioversion.h>
|
||||
#include <OpenImageIO/errorhandler.h>
|
||||
@@ -76,11 +90,6 @@ using Color3 = Imath::Color3<Float>;
|
||||
using Matrix33 = Imath::Matrix33<Float>;
|
||||
using Matrix44 = Imath::Matrix44<Float>;
|
||||
|
||||
#if OSL_USING_IMATH >= 3
|
||||
using Matrix22 = Imath::Matrix22<Float>;
|
||||
#else
|
||||
using Matrix22 = Imathx::Matrix22<Float>;
|
||||
#endif
|
||||
|
||||
|
||||
/// Assume that we are dealing with OpenImageIO's texture system. It
|
||||
@@ -93,7 +102,7 @@ using OIIO::TextureOpt;
|
||||
// And some other things we borrow from OIIO...
|
||||
using OIIO::ErrorHandler;
|
||||
using OIIO::ustring;
|
||||
using OIIO::ustringHash;
|
||||
using OIIO::ustringhash;
|
||||
using OIIO::string_view;
|
||||
using OIIO::span;
|
||||
using OIIO::cspan;
|
||||
@@ -113,6 +122,16 @@ using OIIO::TypeFloat2;
|
||||
using OIIO::TypeVector2;
|
||||
using OIIO::TypeVector4;
|
||||
|
||||
using OIIO::Strutil::print;
|
||||
|
||||
template<typename Str, typename... Args>
|
||||
OSL_NODISCARD inline std::string
|
||||
fmtformat(const Str& fmt, Args&&... args)
|
||||
{
|
||||
return OIIO::Strutil::fmt::format(fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// N.B. SymArena is not really "configuration", but we cram it here for
|
||||
// lack of a better home.
|
||||
@@ -206,3 +225,30 @@ using ConstIndex = std::integral_constant<int, N>;
|
||||
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
|
||||
namespace std { // not necessary in C++17, then we can just say std::hash
|
||||
#ifndef OIIO_USTRING_HAS_STDHASH
|
||||
// Not a new enough OIIO to define std::hash<ustring>, so we'll do it
|
||||
template<> struct hash<OSL::ustring> {
|
||||
std::size_t operator()(OSL::ustring u) const noexcept { return u.hash(); }
|
||||
};
|
||||
|
||||
template<> struct hash<OSL::ustringhash> {
|
||||
OSL_HOSTDEVICE constexpr std::size_t
|
||||
operator()(OSL::ustringhash u) const noexcept
|
||||
{
|
||||
return u.hash();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
// Not necessary once minimum OIIO defines operator< for ustringhash
|
||||
template<> struct less<OSL::ustringhash> {
|
||||
OSL_HOSTDEVICE constexpr bool operator()(OSL::ustringhash u,
|
||||
OSL::ustringhash v) const noexcept
|
||||
{
|
||||
return u.hash() < v.hash();
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
+294
-226
@@ -25,9 +25,16 @@ class ShaderSymbol;
|
||||
class OSLQuery;
|
||||
#if OSL_USE_BATCHED
|
||||
template<int WidthT> struct alignas(64) BatchedShaderGlobals;
|
||||
template<typename DataT, int WidthT> struct Wide;
|
||||
#endif
|
||||
|
||||
|
||||
/// RendererServices free function bitcode may reference global variables that
|
||||
/// only exist in the renderer's program space and won't automatically be
|
||||
/// found when referenced in JIT'd code inside OSL. A renderer may register
|
||||
/// the addresses of these global variables to allow valid JIT to occur.
|
||||
void OSLEXECPUBLIC
|
||||
register_JIT_Global(const char* global_var_name, void* global_var_addr);
|
||||
|
||||
/// Opaque pointer to whatever the renderer uses to represent a
|
||||
/// (potentially motion-blurred) coordinate transformation.
|
||||
@@ -43,73 +50,73 @@ namespace pvt {
|
||||
class ShadingSystemImpl;
|
||||
}
|
||||
|
||||
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
|
||||
# define STRINGIFY(x) XSTR(x)
|
||||
# define XSTR(x) #x
|
||||
# define STRING_PARAMS(x) UStringHash::Hash(STRINGIFY(x))
|
||||
#ifdef __CUDA_ARCH__
|
||||
# define STRING_PARAMS(x) UStringHash::Hash(__OSL_STRINGIFY(x))
|
||||
#else
|
||||
# define STRING_PARAMS(x) StringParams::x
|
||||
# define STRING_PARAMS(x) StringParams::x
|
||||
#endif
|
||||
|
||||
namespace Strings {
|
||||
#ifdef __CUDA_ARCH__
|
||||
# if OPTIX_VERSION >= 70000
|
||||
# define STRDECL(str,var_name)
|
||||
# define STRDECL(str, var_name)
|
||||
#else
|
||||
# define STRDECL(str,var_name) extern __device__ ustring var_name;
|
||||
#endif
|
||||
#else
|
||||
// Any strings referenced inside of a libsoslexec/wide/*.cpp
|
||||
// or liboslnoise/wide/*.cpp will need OSLEXECPUBLIC
|
||||
#define STRDECL(str,var_name) OSLEXECPUBLIC extern const ustring var_name;
|
||||
// Any strings referenced inside of a libsoslexec/wide/*.cpp
|
||||
// or liboslnoise/wide/*.cpp will need OSLEXECPUBLIC
|
||||
# define STRDECL(str, var_name) OSLEXECPUBLIC extern const ustring var_name;
|
||||
#endif
|
||||
#include <OSL/strdecls.h>
|
||||
#undef STRDECL
|
||||
}; // namespace Strings
|
||||
}; // namespace Strings
|
||||
|
||||
|
||||
|
||||
/// Description of where a symbol is located on the app side.
|
||||
struct SymLocationDesc {
|
||||
public:
|
||||
using offset_t = int64_t;
|
||||
using stride_t = int64_t;
|
||||
using offset_t = int64_t;
|
||||
using stride_t = int64_t;
|
||||
static const int64_t AutoStride = std::numeric_limits<stride_t>::min();
|
||||
|
||||
SymLocationDesc() {}
|
||||
SymLocationDesc(string_view name, TypeDesc type, bool derivs = false,
|
||||
SymArena arena = SymArena::Heap, offset_t offset = -1,
|
||||
stride_t stride = AutoStride)
|
||||
: name(name), type(type), offset(offset),
|
||||
stride(stride == AutoStride ? type.size() : stride),
|
||||
arena(arena), derivs(derivs)
|
||||
{}
|
||||
: name(name)
|
||||
, type(type)
|
||||
, offset(offset)
|
||||
, stride(stride == AutoStride ? type.size() : stride)
|
||||
, arena(arena)
|
||||
, derivs(derivs)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(ustring n) const { return name == n; }
|
||||
friend bool operator<(ustring n, const SymLocationDesc& sld) {
|
||||
friend bool operator<(ustring n, const SymLocationDesc& sld)
|
||||
{
|
||||
return n < sld.name;
|
||||
}
|
||||
friend bool operator<(const SymLocationDesc& sld, ustring n) {
|
||||
friend bool operator<(const SymLocationDesc& sld, ustring n)
|
||||
{
|
||||
return sld.name < n;
|
||||
}
|
||||
|
||||
ustring name; ///< Name of the symbol
|
||||
TypeDesc type; ///< Data type of the symbol
|
||||
offset_t offset = -1; ///< Offset from arena base for point 0
|
||||
stride_t stride = AutoStride; ///< Stride in bytes between shade points
|
||||
SymArena arena = SymArena::Heap; ///< Memory arena type for the symbol
|
||||
bool derivs = false; ///< Space allocated for derivs also
|
||||
ustring name; ///< Name of the symbol
|
||||
TypeDesc type; ///< Data type of the symbol
|
||||
offset_t offset
|
||||
= -1; ///< Offset from arena base for point 0 (batched mode assumes userdata at point 0 is readable)
|
||||
stride_t stride = AutoStride; ///< Stride in bytes between shade points
|
||||
SymArena arena = SymArena::Heap; ///< Memory arena type for the symbol
|
||||
bool derivs = false; ///< Space allocated for derivs also
|
||||
};
|
||||
|
||||
|
||||
|
||||
class OSLEXECPUBLIC ShadingSystem
|
||||
{
|
||||
class OSLEXECPUBLIC ShadingSystem {
|
||||
public:
|
||||
ShadingSystem (RendererServices *renderer=NULL,
|
||||
TextureSystem *texturesystem=NULL,
|
||||
ErrorHandler *err=NULL);
|
||||
~ShadingSystem ();
|
||||
ShadingSystem(RendererServices* renderer = NULL,
|
||||
TextureSystem* texturesystem = NULL,
|
||||
ErrorHandler* err = NULL);
|
||||
~ShadingSystem();
|
||||
|
||||
/// Set an attribute controlling the shading system. Return true
|
||||
/// if the name and type were recognized and the attrib was set.
|
||||
@@ -136,10 +143,11 @@ public:
|
||||
/// int no_noise Replace noise with constant value. (0)
|
||||
/// int no_pointcloud Skip pointcloud lookups. (0)
|
||||
/// int exec_repeat How many times to run each group (1).
|
||||
/// int opt_warnings Warn on certain failure to runtime-optimize
|
||||
/// certain shader constructs. (0)
|
||||
/// int gpu_opt_error Consider a hard error if certain shader
|
||||
/// constructs cannot be optimized away. (0)
|
||||
/// int opt_warnings Warn on failure to runtime-optimize certain
|
||||
/// shader constructs. (0)
|
||||
/// int gpu_opt_error Issue a hard error if certain shader
|
||||
/// constructs cannot be optimized away, which
|
||||
/// have no way to run on GPU. (0)
|
||||
/// 2. Attributes that should be set by applications/renderers that
|
||||
/// incorporate OSL:
|
||||
/// string commonspace Name of "common" coord system ("world")
|
||||
@@ -223,8 +231,7 @@ public:
|
||||
/// for debugging. (0)
|
||||
/// int llvm_dumpasm Print the CPU assembly code from the JIT (0)
|
||||
/// string llvm_prune_ir_strategy Strategy for pruning unnecessary
|
||||
/// IR (choices: "prune" [default],
|
||||
/// "internalize", or "none").
|
||||
/// IR (choices: "prune" [default], or "none").
|
||||
/// int max_local_mem_KB Error if shader group needs more than this
|
||||
/// much local storage to execute (1024K)
|
||||
/// string debug_groupname Name of shader group -- debug only this one
|
||||
@@ -239,22 +246,27 @@ public:
|
||||
/// Note: the attributes referred to as "string" are actually on the app
|
||||
/// side as ustring or const char* (they have the same data layout), NOT
|
||||
/// std::string!
|
||||
bool attribute (string_view name, TypeDesc type, const void *val);
|
||||
bool attribute(string_view name, TypeDesc type, const void* val);
|
||||
|
||||
// Shortcuts for common types
|
||||
bool attribute (string_view name, int val) {
|
||||
return attribute (name, TypeDesc::INT, &val);
|
||||
bool attribute(string_view name, int val)
|
||||
{
|
||||
return attribute(name, TypeDesc::INT, &val);
|
||||
}
|
||||
bool attribute (string_view name, float val) {
|
||||
return attribute (name, TypeDesc::FLOAT, &val);
|
||||
bool attribute(string_view name, float val)
|
||||
{
|
||||
return attribute(name, TypeDesc::FLOAT, &val);
|
||||
}
|
||||
bool attribute (string_view name, double val) {
|
||||
float f = (float) val;
|
||||
return attribute (name, TypeDesc::FLOAT, &f);
|
||||
bool attribute(string_view name, double val)
|
||||
{
|
||||
float f = (float)val;
|
||||
return attribute(name, TypeDesc::FLOAT, &f);
|
||||
}
|
||||
bool attribute (string_view name, string_view val) {
|
||||
const char *s = val.c_str();
|
||||
return attribute (name, TypeDesc::STRING, &s);
|
||||
bool attribute(string_view name, string_view val)
|
||||
{
|
||||
std::string valstr(val);
|
||||
const char* s = valstr.c_str();
|
||||
return attribute(name, TypeDesc::STRING, &s);
|
||||
}
|
||||
|
||||
|
||||
@@ -270,21 +282,26 @@ public:
|
||||
/// called unconditionally.
|
||||
/// int exec_repeat How many times to run the group (1).
|
||||
///
|
||||
bool attribute (ShaderGroup *group, string_view name,
|
||||
TypeDesc type, const void *val);
|
||||
bool attribute (ShaderGroup *group, string_view name, int val) {
|
||||
return attribute (group, name, TypeDesc::INT, &val);
|
||||
bool attribute(ShaderGroup* group, string_view name, TypeDesc type,
|
||||
const void* val);
|
||||
bool attribute(ShaderGroup* group, string_view name, int val)
|
||||
{
|
||||
return attribute(group, name, TypeDesc::INT, &val);
|
||||
}
|
||||
bool attribute (ShaderGroup *group, string_view name, float val) {
|
||||
return attribute (group, name, TypeDesc::FLOAT, &val);
|
||||
bool attribute(ShaderGroup* group, string_view name, float val)
|
||||
{
|
||||
return attribute(group, name, TypeDesc::FLOAT, &val);
|
||||
}
|
||||
bool attribute (ShaderGroup *group, string_view name, double val) {
|
||||
float f = (float) val;
|
||||
return attribute (group, name, TypeDesc::FLOAT, &f);
|
||||
bool attribute(ShaderGroup* group, string_view name, double val)
|
||||
{
|
||||
float f = (float)val;
|
||||
return attribute(group, name, TypeDesc::FLOAT, &f);
|
||||
}
|
||||
bool attribute (ShaderGroup *group, string_view name, string_view val) {
|
||||
const char *s = val.c_str();
|
||||
return attribute (group, name, TypeDesc::STRING, &s);
|
||||
bool attribute(ShaderGroup* group, string_view name, string_view val)
|
||||
{
|
||||
std::string valstr(val);
|
||||
const char* s = valstr.c_str();
|
||||
return attribute(group, name, TypeDesc::STRING, &s);
|
||||
}
|
||||
|
||||
/// Get the named attribute of the ShadingSystem, store it in `*val`.
|
||||
@@ -314,23 +331,26 @@ public:
|
||||
/// library build dependencies and their versions (for example,
|
||||
/// "OIIO-2.3.0,LLVM-10.0.0,OpenEXR-2.5.0").
|
||||
///
|
||||
bool getattribute (string_view name, TypeDesc type, void *val);
|
||||
bool getattribute(string_view name, TypeDesc type, void* val);
|
||||
|
||||
/// Shortcut getattribute() for retrieving a single integer.
|
||||
/// The value is placed in `val`, and the function returns `true` if the
|
||||
/// attribute was found and was legally convertible to an int.
|
||||
bool getattribute (string_view name, int &val) {
|
||||
return getattribute (name, TypeDesc::INT, &val);
|
||||
bool getattribute(string_view name, int& val)
|
||||
{
|
||||
return getattribute(name, TypeDesc::INT, &val);
|
||||
}
|
||||
/// Shortcut getattribute() for retrieving a single float.
|
||||
/// The value is placed in `val`, and the function returns `true` if the
|
||||
/// attribute was found and was legally convertible to a float.
|
||||
bool getattribute (string_view name, float &val) {
|
||||
return getattribute (name, TypeDesc::FLOAT, &val);
|
||||
bool getattribute(string_view name, float& val)
|
||||
{
|
||||
return getattribute(name, TypeDesc::FLOAT, &val);
|
||||
}
|
||||
bool getattribute (string_view name, double &val) {
|
||||
bool getattribute(string_view name, double& val)
|
||||
{
|
||||
float f;
|
||||
bool ok = getattribute (name, TypeDesc::FLOAT, &f);
|
||||
bool ok = getattribute(name, TypeDesc::FLOAT, &f);
|
||||
if (ok)
|
||||
val = f;
|
||||
return ok;
|
||||
@@ -338,21 +358,24 @@ public:
|
||||
/// Shortcut getattribute() for retrieving a single string as a
|
||||
/// `const char*`. The value is placed in `val`, and the function
|
||||
/// returns `true` if the attribute was found.
|
||||
bool getattribute (string_view name, char **val) {
|
||||
return getattribute (name, TypeDesc::STRING, val);
|
||||
bool getattribute(string_view name, char** val)
|
||||
{
|
||||
return getattribute(name, TypeDesc::STRING, val);
|
||||
}
|
||||
/// Shortcut getattribute() for retrieving a single string as a
|
||||
/// `ustring`. The value is placed in `val`, and the function returns
|
||||
/// `true` if the attribute was found.
|
||||
bool getattribute (string_view name, ustring &val) {
|
||||
return getattribute (name, TypeDesc::STRING, (char **)&val);
|
||||
bool getattribute(string_view name, ustring& val)
|
||||
{
|
||||
return getattribute(name, TypeDesc::STRING, (char**)&val);
|
||||
}
|
||||
/// Shortcut getattribute() for retrieving a single string as a
|
||||
/// `std::string`. The value is placed in `val`, and the function
|
||||
/// returns `true` if the attribute was found.
|
||||
bool getattribute (string_view name, std::string &val) {
|
||||
const char *s = NULL;
|
||||
bool ok = getattribute (name, TypeDesc::STRING, &s);
|
||||
bool getattribute(string_view name, std::string& val)
|
||||
{
|
||||
const char* s = NULL;
|
||||
bool ok = getattribute(name, TypeDesc::STRING, &s);
|
||||
if (ok)
|
||||
val = s;
|
||||
return ok;
|
||||
@@ -423,31 +446,37 @@ public:
|
||||
/// Note: the attributes referred to as "string" are actually on the app
|
||||
/// side as ustring or const char* (they have the same data layout), NOT
|
||||
/// std::string!
|
||||
bool getattribute (ShaderGroup *group, string_view name,
|
||||
TypeDesc type, void *val);
|
||||
bool getattribute(ShaderGroup* group, string_view name, TypeDesc type,
|
||||
void* val);
|
||||
// Shortcuts for common types
|
||||
bool getattribute (ShaderGroup *group, string_view name, int &val) {
|
||||
return getattribute (group, name, TypeDesc::INT, &val);
|
||||
bool getattribute(ShaderGroup* group, string_view name, int& val)
|
||||
{
|
||||
return getattribute(group, name, TypeDesc::INT, &val);
|
||||
}
|
||||
bool getattribute (ShaderGroup *group, string_view name, float &val) {
|
||||
return getattribute (group, name, TypeDesc::FLOAT, &val);
|
||||
bool getattribute(ShaderGroup* group, string_view name, float& val)
|
||||
{
|
||||
return getattribute(group, name, TypeDesc::FLOAT, &val);
|
||||
}
|
||||
bool getattribute (ShaderGroup *group, string_view name, double &val) {
|
||||
bool getattribute(ShaderGroup* group, string_view name, double& val)
|
||||
{
|
||||
float f;
|
||||
bool ok = getattribute (group, name, TypeDesc::FLOAT, &f);
|
||||
bool ok = getattribute(group, name, TypeDesc::FLOAT, &f);
|
||||
if (ok)
|
||||
val = f;
|
||||
return ok;
|
||||
}
|
||||
bool getattribute (ShaderGroup *group, string_view name, char **val) {
|
||||
return getattribute (group, name, TypeDesc::STRING, val);
|
||||
bool getattribute(ShaderGroup* group, string_view name, char** val)
|
||||
{
|
||||
return getattribute(group, name, TypeDesc::STRING, val);
|
||||
}
|
||||
bool getattribute (ShaderGroup *group, string_view name, ustring &val) {
|
||||
return getattribute (group, name, TypeDesc::STRING, (char **)&val);
|
||||
bool getattribute(ShaderGroup* group, string_view name, ustring& val)
|
||||
{
|
||||
return getattribute(group, name, TypeDesc::STRING, (char**)&val);
|
||||
}
|
||||
bool getattribute (ShaderGroup *group, string_view name, std::string &val) {
|
||||
const char *s = NULL;
|
||||
bool ok = getattribute (group, name, TypeDesc::STRING, &s);
|
||||
bool getattribute(ShaderGroup* group, string_view name, std::string& val)
|
||||
{
|
||||
const char* s = NULL;
|
||||
bool ok = getattribute(group, name, TypeDesc::STRING, &s);
|
||||
if (ok)
|
||||
val = s;
|
||||
return ok;
|
||||
@@ -456,8 +485,7 @@ public:
|
||||
|
||||
/// Load compiled shader (oso) from a memory buffer, overriding
|
||||
/// shader lookups in the shader search path
|
||||
bool LoadMemoryCompiledShader (string_view shadername,
|
||||
string_view buffer);
|
||||
bool LoadMemoryCompiledShader(string_view shadername, string_view buffer);
|
||||
|
||||
// The basic sequence for declaring a shader group looks like this:
|
||||
// ShadingSystem *ss = ...;
|
||||
@@ -483,7 +511,7 @@ public:
|
||||
|
||||
/// Signal the start of a new shader group. The return value is a
|
||||
/// reference-counted opaque handle to the ShaderGroup.
|
||||
ShaderGroupRef ShaderGroupBegin (string_view groupname = string_view());
|
||||
ShaderGroupRef ShaderGroupBegin(string_view groupname = string_view());
|
||||
|
||||
/// Alternate way to specify a shader group. The group specification
|
||||
/// syntax looks like this: (as a string, all whitespace is equivalent):
|
||||
@@ -493,13 +521,13 @@ public:
|
||||
/// For the sake of easy assembling on command lines, a comma ',' may
|
||||
/// substitute for the semicolon as a separator, and the last separator
|
||||
/// before the end of the string is optional.
|
||||
ShaderGroupRef ShaderGroupBegin (string_view groupname,
|
||||
string_view shaderusage,
|
||||
string_view groupspec = string_view());
|
||||
ShaderGroupRef ShaderGroupBegin(string_view groupname,
|
||||
string_view shaderusage,
|
||||
string_view groupspec = string_view());
|
||||
|
||||
/// Signal the end of a new shader group.
|
||||
///
|
||||
bool ShaderGroupEnd (ShaderGroup& group);
|
||||
bool ShaderGroupEnd(ShaderGroup& group);
|
||||
|
||||
/// Set a parameter of the next shader that will be added to the group,
|
||||
/// optionally setting the 'lockgeom' metadata for that parameter
|
||||
@@ -508,32 +536,37 @@ public:
|
||||
/// against changes by the geometry, and therefore the shader should not
|
||||
/// optimize assuming that the instance value (the 'val' specified by
|
||||
/// this call) is a constant.
|
||||
bool Parameter (ShaderGroup& group, string_view name, TypeDesc t,
|
||||
const void *val, bool lockgeom=true);
|
||||
bool Parameter(ShaderGroup& group, string_view name, TypeDesc t,
|
||||
const void* val, bool lockgeom = true);
|
||||
// Shortcuts for param passing a single int, float, or string.
|
||||
bool Parameter (ShaderGroup& group, string_view name,
|
||||
int val, bool lockgeom=true) {
|
||||
return Parameter (group, name, TypeDesc::INT, &val, lockgeom);
|
||||
bool Parameter(ShaderGroup& group, string_view name, int val,
|
||||
bool lockgeom = true)
|
||||
{
|
||||
return Parameter(group, name, TypeDesc::INT, &val, lockgeom);
|
||||
}
|
||||
bool Parameter (ShaderGroup& group, string_view name,
|
||||
float val, bool lockgeom=true) {
|
||||
return Parameter (group, name, TypeDesc::FLOAT, &val, lockgeom);
|
||||
bool Parameter(ShaderGroup& group, string_view name, float val,
|
||||
bool lockgeom = true)
|
||||
{
|
||||
return Parameter(group, name, TypeDesc::FLOAT, &val, lockgeom);
|
||||
}
|
||||
bool Parameter (ShaderGroup& group, string_view name,
|
||||
const std::string& val, bool lockgeom=true) {
|
||||
const char *s = val.c_str();
|
||||
return Parameter (group, name, TypeDesc::STRING, &s, lockgeom);
|
||||
bool Parameter(ShaderGroup& group, string_view name, const std::string& val,
|
||||
bool lockgeom = true)
|
||||
{
|
||||
const char* s = val.c_str();
|
||||
return Parameter(group, name, TypeDesc::STRING, &s, lockgeom);
|
||||
}
|
||||
bool Parameter (ShaderGroup& group, string_view name,
|
||||
ustring val, bool lockgeom=true) {
|
||||
return Parameter (group, name, TypeDesc::STRING, (const char**)&val, lockgeom);
|
||||
bool Parameter(ShaderGroup& group, string_view name, ustring val,
|
||||
bool lockgeom = true)
|
||||
{
|
||||
return Parameter(group, name, TypeDesc::STRING, (const char**)&val,
|
||||
lockgeom);
|
||||
}
|
||||
|
||||
/// Append a new shader instance onto the specified group. The shader
|
||||
/// instance will get any pending parameters that were set by
|
||||
/// Parameter() calls since the last Shader() call for the group.
|
||||
bool Shader (ShaderGroup& group, string_view shaderusage,
|
||||
string_view shadername, string_view layername);
|
||||
bool Shader(ShaderGroup& group, string_view shaderusage,
|
||||
string_view shadername, string_view layername);
|
||||
|
||||
/// Connect two shaders within the specified group. The source layer
|
||||
/// must be *upstream* of down destination layer (i.e. source must be
|
||||
@@ -549,9 +582,9 @@ public:
|
||||
/// `ConnectShaders (group, "lay1", "mycolorout[2]",
|
||||
/// "lay2", "myfloatinput")`
|
||||
///
|
||||
bool ConnectShaders (ShaderGroup &group,
|
||||
string_view srclayer, string_view srcparam,
|
||||
string_view dstlayer, string_view dstparam);
|
||||
bool ConnectShaders(ShaderGroup& group, string_view srclayer,
|
||||
string_view srcparam, string_view dstlayer,
|
||||
string_view dstparam);
|
||||
|
||||
/// Replace a parameter value in a previously-declared shader group.
|
||||
/// This is meant to called after the ShaderGroupBegin/End, but will
|
||||
@@ -560,27 +593,30 @@ public:
|
||||
/// indicates that it's a parameter that may be overridden by the
|
||||
/// geometric primitive). This call gives you a way of changing the
|
||||
/// instance value, even if it's not a geometric override.
|
||||
bool ReParameter (ShaderGroup &group,
|
||||
string_view layername, string_view paramname,
|
||||
TypeDesc type, const void *val);
|
||||
bool ReParameter(ShaderGroup& group, string_view layername,
|
||||
string_view paramname, TypeDesc type, const void* val);
|
||||
// Shortcuts for param passing a single int, float, or string.
|
||||
bool ReParameter (ShaderGroup &group, string_view layername,
|
||||
string_view paramname, int val) {
|
||||
return ReParameter (group, layername, paramname, TypeDesc::INT, &val);
|
||||
bool ReParameter(ShaderGroup& group, string_view layername,
|
||||
string_view paramname, int val)
|
||||
{
|
||||
return ReParameter(group, layername, paramname, TypeDesc::INT, &val);
|
||||
}
|
||||
bool ReParameter (ShaderGroup &group, string_view layername,
|
||||
string_view paramname, float val) {
|
||||
return ReParameter (group, layername, paramname, TypeDesc::FLOAT, &val);
|
||||
bool ReParameter(ShaderGroup& group, string_view layername,
|
||||
string_view paramname, float val)
|
||||
{
|
||||
return ReParameter(group, layername, paramname, TypeDesc::FLOAT, &val);
|
||||
}
|
||||
bool ReParameter (ShaderGroup &group, string_view layername,
|
||||
string_view paramname, const std::string& val) {
|
||||
const char *s = val.c_str();
|
||||
return ReParameter (group, layername, paramname, TypeDesc::STRING, &s);
|
||||
bool ReParameter(ShaderGroup& group, string_view layername,
|
||||
string_view paramname, const std::string& val)
|
||||
{
|
||||
const char* s = val.c_str();
|
||||
return ReParameter(group, layername, paramname, TypeDesc::STRING, &s);
|
||||
}
|
||||
bool ReParameter (ShaderGroup &group, string_view layername,
|
||||
string_view paramname, ustring val) {
|
||||
return ReParameter (group, layername, paramname, TypeDesc::STRING,
|
||||
(const char**)&val);
|
||||
bool ReParameter(ShaderGroup& group, string_view layername,
|
||||
string_view paramname, ustring val)
|
||||
{
|
||||
return ReParameter(group, layername, paramname, TypeDesc::STRING,
|
||||
(const char**)&val);
|
||||
}
|
||||
|
||||
// Non-threadsafe versions of Parameter, Shader, ConnectShaders, and
|
||||
@@ -591,13 +627,13 @@ public:
|
||||
// concurrently). If there is any doubt about that, use the versions
|
||||
// above that take an explicit `ShaderGroup&`, which are thread-safe
|
||||
// and re-entrant.
|
||||
bool Parameter (string_view name, TypeDesc t, const void *val,
|
||||
bool lockgeom=true);
|
||||
bool Shader (string_view shaderusage, string_view shadername,
|
||||
string_view layername);
|
||||
bool ConnectShaders (string_view srclayer, string_view srcparam,
|
||||
string_view dstlayer, string_view dstparam);
|
||||
bool ShaderGroupEnd (void);
|
||||
bool Parameter(string_view name, TypeDesc t, const void* val,
|
||||
bool lockgeom = true);
|
||||
bool Shader(string_view shaderusage, string_view shadername,
|
||||
string_view layername);
|
||||
bool ConnectShaders(string_view srclayer, string_view srcparam,
|
||||
string_view dstlayer, string_view dstparam);
|
||||
bool ShaderGroupEnd(void);
|
||||
|
||||
/// Create a per-thread data needed for shader execution. It's very
|
||||
/// important for the app to never use a PerThreadInfo from more than
|
||||
@@ -605,11 +641,11 @@ public:
|
||||
/// for each renderer thread), and destroy it with destroy_thread_info
|
||||
/// when the thread terminates (and before the ShadingSystem is
|
||||
/// destroyed).
|
||||
PerThreadInfo * create_thread_info();
|
||||
PerThreadInfo* create_thread_info();
|
||||
|
||||
/// Destroy a PerThreadInfo that was allocated by
|
||||
/// create_thread_info().
|
||||
void destroy_thread_info (PerThreadInfo *threadinfo);
|
||||
void destroy_thread_info(PerThreadInfo* threadinfo);
|
||||
|
||||
/// Get a ShadingContext that we can use. The context is specific to a
|
||||
/// renderer thread, and should never be passed between or shared by
|
||||
@@ -617,12 +653,13 @@ public:
|
||||
/// thread-specific pointer created by create_thread_info. The context
|
||||
/// can be used to shade many points; a typical usage is to allocate
|
||||
/// just one context per thread and use it for the whole run.
|
||||
ShadingContext *get_context (PerThreadInfo *threadinfo,
|
||||
TextureSystem::Perthread *texture_threadinfo=NULL);
|
||||
ShadingContext*
|
||||
get_context(PerThreadInfo* threadinfo,
|
||||
TextureSystem::Perthread* texture_threadinfo = NULL);
|
||||
|
||||
/// Return a ShadingContext to the pool.
|
||||
///
|
||||
void release_context (ShadingContext *ctx);
|
||||
void release_context(ShadingContext* ctx);
|
||||
|
||||
/// Execute the shader group in this context on shading point
|
||||
/// `shadeindex`. If ctx is nullptr, then execute will request one
|
||||
@@ -631,19 +668,30 @@ public:
|
||||
/// execute_layer of the last (presumably group entry) layer, and
|
||||
/// execute_cleanup. If run==false, just do the binding and setup, don't
|
||||
/// actually run the shader.
|
||||
bool execute(ShadingContext &ctx, ShaderGroup &group, int shadeindex,
|
||||
bool execute(ShadingContext& ctx, ShaderGroup& group, int shadeindex,
|
||||
ShaderGlobals& globals, void* userdata_base_ptr,
|
||||
void* output_base_ptr, bool run = true);
|
||||
|
||||
/// Future execute signature that will be range based. Shader globals will be
|
||||
/// obtained from renderer services.
|
||||
#if 0 // TODO in future PR
|
||||
bool execute(ShadingContext& ctx, ShaderGroup& group, OpaqueShadingStateUniformPtr ssu,
|
||||
int shadeindex_begin_at, int shadeindex_end_before
|
||||
void* userdata_base_ptr,
|
||||
void* output_base_ptr, bool run = true);
|
||||
#endif
|
||||
|
||||
// DEPRECATED(2.0): no shadeindex or base pointers
|
||||
bool execute (ShadingContext &ctx, ShaderGroup &group,
|
||||
ShaderGlobals &globals, bool run=true) {
|
||||
bool execute(ShadingContext& ctx, ShaderGroup& group,
|
||||
ShaderGlobals& globals, bool run = true)
|
||||
{
|
||||
return execute(ctx, group, 0, globals, nullptr, nullptr, run);
|
||||
}
|
||||
|
||||
// DEPRECATED(2.0): ctx pointer
|
||||
bool execute (ShadingContext *ctx, ShaderGroup &group,
|
||||
ShaderGlobals &globals, bool run=true) {
|
||||
bool execute(ShadingContext* ctx, ShaderGroup& group,
|
||||
ShaderGlobals& globals, bool run = true)
|
||||
{
|
||||
return execute(*ctx, group, globals, run);
|
||||
}
|
||||
|
||||
@@ -655,12 +703,13 @@ public:
|
||||
/// preparation, but don't actually run the shader. Return true if the
|
||||
/// shader executed, false if it did not (including if the shader itself
|
||||
/// was empty).
|
||||
bool execute_init(ShadingContext &ctx, ShaderGroup &group, int shadeindex,
|
||||
ShaderGlobals &globals, void* userdata_base_ptr,
|
||||
void* output_base_ptr, bool run=true);
|
||||
bool execute_init(ShadingContext& ctx, ShaderGroup& group, int shadeindex,
|
||||
ShaderGlobals& globals, void* userdata_base_ptr,
|
||||
void* output_base_ptr, bool run = true);
|
||||
// DEPRECATED(2.0): no shadeindex or base pointers
|
||||
bool execute_init (ShadingContext &ctx, ShaderGroup &group,
|
||||
ShaderGlobals &globals, bool run=true) {
|
||||
bool execute_init(ShadingContext& ctx, ShaderGroup& group,
|
||||
ShaderGlobals& globals, bool run = true)
|
||||
{
|
||||
return execute_init(ctx, group, 0, globals, nullptr, nullptr, run);
|
||||
}
|
||||
|
||||
@@ -669,41 +718,44 @@ public:
|
||||
/// run==true, and that the call to execute_init() returned true. (One
|
||||
/// reason why it might have returned false is if the shader group
|
||||
/// turned out, after optimization, to do nothing.)
|
||||
bool execute_layer(ShadingContext &ctx, int shadeindex, ShaderGlobals &globals,
|
||||
void* userdata_base_ptr, void* output_base_ptr,
|
||||
int layernumber);
|
||||
bool execute_layer(ShadingContext& ctx, int shadeindex,
|
||||
ShaderGlobals& globals, void* userdata_base_ptr,
|
||||
void* output_base_ptr, int layernumber);
|
||||
/// Execute the layer by name.
|
||||
bool execute_layer(ShadingContext &ctx, int shadeindex, ShaderGlobals &globals,
|
||||
void* userdata_base_ptr, void* output_base_ptr,
|
||||
ustring layername);
|
||||
bool execute_layer(ShadingContext& ctx, int shadeindex,
|
||||
ShaderGlobals& globals, void* userdata_base_ptr,
|
||||
void* output_base_ptr, ustring layername);
|
||||
/// Execute the layer that has the given ShaderSymbol as an output.
|
||||
/// (The symbol is one returned by find_symbol()).
|
||||
bool execute_layer(ShadingContext &ctx, int shadeindex, ShaderGlobals &globals,
|
||||
void* userdata_base_ptr, void* output_base_ptr,
|
||||
const ShaderSymbol *symbol);
|
||||
bool execute_layer(ShadingContext& ctx, int shadeindex,
|
||||
ShaderGlobals& globals, void* userdata_base_ptr,
|
||||
void* output_base_ptr, const ShaderSymbol* symbol);
|
||||
|
||||
// DEPRECATED(2.0): no shadeindex or base pointers
|
||||
bool execute_layer (ShadingContext &ctx, ShaderGlobals &globals,
|
||||
int layernumber) {
|
||||
bool execute_layer(ShadingContext& ctx, ShaderGlobals& globals,
|
||||
int layernumber)
|
||||
{
|
||||
return execute_layer(ctx, 0, globals, nullptr, nullptr, layernumber);
|
||||
}
|
||||
bool execute_layer (ShadingContext &ctx, ShaderGlobals &globals,
|
||||
ustring layername) {
|
||||
bool execute_layer(ShadingContext& ctx, ShaderGlobals& globals,
|
||||
ustring layername)
|
||||
{
|
||||
return execute_layer(ctx, 0, globals, nullptr, nullptr, layername);
|
||||
}
|
||||
bool execute_layer (ShadingContext &ctx, ShaderGlobals &globals,
|
||||
const ShaderSymbol *symbol) {
|
||||
bool execute_layer(ShadingContext& ctx, ShaderGlobals& globals,
|
||||
const ShaderSymbol* symbol)
|
||||
{
|
||||
return execute_layer(ctx, 0, globals, nullptr, nullptr, symbol);
|
||||
}
|
||||
|
||||
/// Signify that the context is done with the current execution of the
|
||||
/// group that was kicked off by execute_init and one or more calls to
|
||||
/// execute_layer.
|
||||
bool execute_cleanup (ShadingContext &ctx);
|
||||
bool execute_cleanup(ShadingContext& ctx);
|
||||
|
||||
/// Find the named layer within a group and return its index, or -1
|
||||
/// if no such named layer exists.
|
||||
int find_layer (const ShaderGroup &group, ustring layername) const;
|
||||
int find_layer(const ShaderGroup& group, ustring layername) const;
|
||||
|
||||
/// Get a raw pointer to a named symbol (such as you'd need to pull
|
||||
/// out the value of an output parameter). ctx is the shading
|
||||
@@ -720,10 +772,10 @@ public:
|
||||
///
|
||||
/// These are considered somewhat deprecated, in favor of using
|
||||
/// find_symbol(), symbol_typedesc(), and symbol_address().
|
||||
const void* get_symbol (const ShadingContext &ctx, ustring layername,
|
||||
ustring symbolname, TypeDesc &type) const;
|
||||
const void* get_symbol (const ShadingContext &ctx, ustring symbolname,
|
||||
TypeDesc &type) const;
|
||||
const void* get_symbol(const ShadingContext& ctx, ustring layername,
|
||||
ustring symbolname, TypeDesc& type) const;
|
||||
const void* get_symbol(const ShadingContext& ctx, ustring symbolname,
|
||||
TypeDesc& type) const;
|
||||
|
||||
/// Search for an output symbol by name (and optionally, layer) within
|
||||
/// the optimized shader group. If the symbol is found, return an opaque
|
||||
@@ -737,22 +789,22 @@ public:
|
||||
/// separately, or by concatenating "layername.symbolname", but note
|
||||
/// that the latter will involve string manipulation inside find_symbol
|
||||
/// and is much more expensive than specifying them separately.
|
||||
const ShaderSymbol* find_symbol (const ShaderGroup &group,
|
||||
ustring layername, ustring symbolname) const;
|
||||
const ShaderSymbol* find_symbol (const ShaderGroup &group,
|
||||
ustring symbolname) const;
|
||||
const ShaderSymbol* find_symbol(const ShaderGroup& group, ustring layername,
|
||||
ustring symbolname) const;
|
||||
const ShaderSymbol* find_symbol(const ShaderGroup& group,
|
||||
ustring symbolname) const;
|
||||
|
||||
/// Given an opaque ShaderSymbol*, return the TypeDesc describing it.
|
||||
/// Note that a closure will end up with a TypeDesc::UNKNOWN value.
|
||||
TypeDesc symbol_typedesc (const ShaderSymbol *sym) const;
|
||||
TypeDesc symbol_typedesc(const ShaderSymbol* sym) const;
|
||||
|
||||
/// Given a context (that has executed a shader) and an opaque
|
||||
/// ShaderSymbol*, return the actual memory address where the value of
|
||||
/// the symbol resides within the heap memory of the context. This
|
||||
/// is only valid for the shader execution that had happened immediately
|
||||
/// prior for this context, but it is a very inexpensive operation.
|
||||
const void* symbol_address (const ShadingContext &ctx,
|
||||
const ShaderSymbol *sym) const;
|
||||
const void* symbol_address(const ShadingContext& ctx,
|
||||
const ShaderSymbol* sym) const;
|
||||
|
||||
#if OSL_USE_BATCHED
|
||||
/// Based on currently set attributes for llvm_jit_target and
|
||||
@@ -763,39 +815,56 @@ public:
|
||||
/// Returns true if supported, false otherwise
|
||||
bool configure_batch_execution_at(int width);
|
||||
|
||||
template<int WidthT>
|
||||
class OSLEXECPUBLIC BatchedExecutor {
|
||||
ShadingSystem & m_shading_system;
|
||||
template<int WidthT> class OSLEXECPUBLIC BatchedExecutor {
|
||||
ShadingSystem& m_shading_system;
|
||||
|
||||
public:
|
||||
explicit OSL_FORCEINLINE BatchedExecutor(ShadingSystem & ss)
|
||||
:m_shading_system(ss)
|
||||
{}
|
||||
explicit OSL_FORCEINLINE BatchedExecutor(ShadingSystem& ss)
|
||||
: m_shading_system(ss)
|
||||
{
|
||||
}
|
||||
OSL_FORCEINLINE BatchedExecutor(const BatchedExecutor&) = default;
|
||||
|
||||
/// Ensure that the group has been JITed.
|
||||
void jit_group (ShaderGroup *group, ShadingContext *ctx);
|
||||
void jit_group(ShaderGroup* group, ShadingContext* ctx);
|
||||
|
||||
/// If option "greedyjit" was set, this call will trigger all
|
||||
/// shader groups that have not yet been compiled to do so with the
|
||||
/// specified number of threads (0 means use all available HW cores).
|
||||
void jit_all_groups (int nthreads=0);
|
||||
void jit_all_groups(int nthreads = 0);
|
||||
|
||||
bool execute(ShadingContext &ctx, ShaderGroup &group, int batch_size,
|
||||
BatchedShaderGlobals<WidthT> &globals_batch, bool run=true);
|
||||
bool execute(ShadingContext& ctx, ShaderGroup& group, int batch_size,
|
||||
Wide<const int, WidthT> wide_shadeindex,
|
||||
BatchedShaderGlobals<WidthT>& globals_batch,
|
||||
void* userdata_base_ptr, void* output_base_ptr,
|
||||
bool run = true);
|
||||
|
||||
bool execute_init (ShadingContext &ctx, ShaderGroup &group, int batch_size,
|
||||
BatchedShaderGlobals<WidthT> &globals_batch, bool run=true);
|
||||
bool execute_init(ShadingContext& ctx, ShaderGroup& group,
|
||||
int batch_size,
|
||||
Wide<const int, WidthT> wide_shadeindex,
|
||||
BatchedShaderGlobals<WidthT>& globals_batch,
|
||||
void* userdata_base_ptr, void* output_base_ptr,
|
||||
bool run = true);
|
||||
|
||||
bool execute_layer (ShadingContext &ctx, int batch_size, BatchedShaderGlobals<WidthT> &globals_batch,
|
||||
int layernumber);
|
||||
bool execute_layer (ShadingContext &ctx, int batch_size, BatchedShaderGlobals<WidthT> &globals_batch,
|
||||
ustring layername);
|
||||
bool execute_layer (ShadingContext &ctx, int batch_size, BatchedShaderGlobals<WidthT> &globals_batch,
|
||||
const ShaderSymbol *symbol);
|
||||
bool execute_layer(ShadingContext& ctx, int batch_size,
|
||||
Wide<const int, WidthT> wide_shadeindex,
|
||||
BatchedShaderGlobals<WidthT>& globals_batch,
|
||||
void* userdata_base_ptr, void* output_base_ptr,
|
||||
int layernumber);
|
||||
bool execute_layer(ShadingContext& ctx, int batch_size,
|
||||
Wide<const int, WidthT> wide_shadeindex,
|
||||
BatchedShaderGlobals<WidthT>& globals_batch,
|
||||
void* userdata_base_ptr, void* output_base_ptr,
|
||||
ustring layername);
|
||||
bool execute_layer(ShadingContext& ctx, int batch_size,
|
||||
Wide<const int, WidthT> wide_shadeindex,
|
||||
BatchedShaderGlobals<WidthT>& globals_batch,
|
||||
void* userdata_base_ptr, void* output_base_ptr,
|
||||
const ShaderSymbol* symbol);
|
||||
};
|
||||
|
||||
template<int WidthT>
|
||||
OSL_FORCEINLINE BatchedExecutor<WidthT> batched() {
|
||||
template<int WidthT> OSL_FORCEINLINE BatchedExecutor<WidthT> batched()
|
||||
{
|
||||
return BatchedExecutor<WidthT>(*this);
|
||||
}
|
||||
#endif
|
||||
@@ -803,37 +872,36 @@ public:
|
||||
|
||||
/// Return the statistics output as a huge string.
|
||||
///
|
||||
std::string getstats (int level=1) const;
|
||||
std::string getstats(int level = 1) const;
|
||||
|
||||
void register_closure (string_view name, int id, const ClosureParam *params,
|
||||
PrepareClosureFunc prepare, SetupClosureFunc setup);
|
||||
void register_closure(string_view name, int id, const ClosureParam* params,
|
||||
PrepareClosureFunc prepare, SetupClosureFunc setup);
|
||||
|
||||
/// Query either by name or id an existing closure. If name is non
|
||||
/// NULL it will use it for the search, otherwise id would be used
|
||||
/// and the name will be placed in name if successful. Also return
|
||||
/// pointer to the params array in the last argument. All args are
|
||||
/// optional but at least one of name or id must non NULL.
|
||||
bool query_closure (const char **name, int *id,
|
||||
const ClosureParam **params);
|
||||
bool query_closure(const char** name, int* id, const ClosureParam** params);
|
||||
|
||||
/// For the proposed shader "global" name, return the corresponding
|
||||
/// SGBits enum.
|
||||
static SGBits globals_bit (ustring name);
|
||||
static SGBits globals_bit(ustring name);
|
||||
|
||||
/// For the SGBits value, return the shader "globals" name.
|
||||
static ustring globals_name (SGBits bit);
|
||||
static ustring globals_name(SGBits bit);
|
||||
|
||||
/// For the proposed raytype name, return the bit pattern that
|
||||
/// describes it, or 0 for an unrecognized name. (This retrieves
|
||||
/// data passed in via attribute("raytypes")).
|
||||
int raytype_bit (ustring name);
|
||||
int raytype_bit(ustring name);
|
||||
|
||||
/// Configure the default raytypes to assume to be on (or off) at optimization
|
||||
/// time for the given group. The raytypes_on gives a bitfield describing which
|
||||
/// ray flags are known to be 1, and raytypes_off describes which ray flags are
|
||||
/// known to be 0. Bits that are not set in either set of flags are not known
|
||||
/// to the optimizer, and will be determined strictly at execution time.
|
||||
void set_raytypes(ShaderGroup *group, int raytypes_on, int raytypes_off);
|
||||
void set_raytypes(ShaderGroup* group, int raytypes_on, int raytypes_off);
|
||||
|
||||
/// Clear any known mappings of symbol locations.
|
||||
void clear_symlocs();
|
||||
@@ -845,31 +913,32 @@ public:
|
||||
|
||||
/// Ensure that the group has been optimized and optionally JITed. The ctx pointer
|
||||
/// supplies a ShadingContext to use.
|
||||
void optimize_group (ShaderGroup *group, ShadingContext *ctx, bool do_jit = true);
|
||||
void optimize_group(ShaderGroup* group, ShadingContext* ctx,
|
||||
bool do_jit = true);
|
||||
|
||||
/// Ensure that the group has been optimized and optionally JITed. This is a
|
||||
/// convenience function that simply calls set_raytypes followed by
|
||||
/// optimize_group. The ctx supplies a ShadingContext to use.
|
||||
void optimize_group (ShaderGroup *group, int raytypes_on,
|
||||
int raytypes_off, ShadingContext *ctx, bool do_jit = true);
|
||||
void optimize_group(ShaderGroup* group, int raytypes_on, int raytypes_off,
|
||||
ShadingContext* ctx, bool do_jit = true);
|
||||
|
||||
/// If option "greedyjit" was set, this call will trigger all
|
||||
/// shader groups that have not yet been compiled to do so with the
|
||||
/// specified number of threads (0 means use all available HW cores).
|
||||
void optimize_all_groups (int nthreads=0, bool do_jit = true);
|
||||
void optimize_all_groups(int nthreads = 0, bool do_jit = true);
|
||||
|
||||
/// Return a pointer to the TextureSystem being used.
|
||||
TextureSystem * texturesys () const;
|
||||
TextureSystem* texturesys() const;
|
||||
|
||||
/// Return a pointer to the RendererServices being used.
|
||||
RendererServices * renderer () const;
|
||||
RendererServices* renderer() const;
|
||||
|
||||
/// Archive the entire shader group so that it can be reconstituted
|
||||
/// later.
|
||||
bool archive_shadergroup (ShaderGroup &group, string_view filename);
|
||||
bool archive_shadergroup(ShaderGroup& group, string_view filename);
|
||||
|
||||
// DEPRECATED(2.0)
|
||||
bool archive_shadergroup (ShaderGroup *group, string_view filename);
|
||||
bool archive_shadergroup(ShaderGroup* group, string_view filename);
|
||||
|
||||
/// Construct and return an OSLQuery initialized with an existing
|
||||
/// ShaderGroup. For a shader group already loaded by the ShadingSystem,
|
||||
@@ -948,9 +1017,8 @@ bool
|
||||
shade_image(ShadingSystem& shadingsys, ShaderGroup& group,
|
||||
const ShaderGlobals* defaultsg, OIIO::ImageBuf& buf,
|
||||
cspan<ustring> outputs,
|
||||
ShadeImageLocations shadelocations = ShadePixelCenters,
|
||||
OIIO::ROI roi = OIIO::ROI(),
|
||||
OIIO::parallel_options popt = 0);
|
||||
ShadeImageLocations shadelocations = ShadePixelCenters,
|
||||
OIIO::ROI roi = OIIO::ROI(), OIIO::parallel_options popt = 0);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+36
-22
@@ -9,6 +9,8 @@
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
#include <OpenImageIO/fmath.h>
|
||||
#include <OpenImageIO/hash.h>
|
||||
#include <OpenImageIO/simd.h>
|
||||
@@ -139,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
|
||||
@@ -229,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;
|
||||
@@ -465,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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -542,7 +557,6 @@ using PeriodicHashNoise = PeriodicAdaptionOf<HashNoise>;
|
||||
|
||||
|
||||
|
||||
|
||||
inline OSL_HOSTDEVICE int
|
||||
inthashi (int x)
|
||||
{
|
||||
@@ -555,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))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -564,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)
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -576,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])
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -589,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)
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -638,7 +652,7 @@ OSL_FORCEINLINE OSL_HOSTDEVICE Dual2<float> select(const bool b, const Dual2<flo
|
||||
// versus requiring a stack location.
|
||||
// Without this work per component, gathers & scatters were being emitted
|
||||
// when used inside SIMD loops.
|
||||
#if OSL_NON_INTEL_CLANG
|
||||
#if OSL_ANY_CLANG && !OSL_INTEL_CLASSIC_COMPILER_VERSION && !OSL_INTEL_LLVM_COMPILER_VERSION
|
||||
// Clang's vectorizor was really insistent that a select operation could not be replaced
|
||||
// with control flow, so had to re-introduce the ? operator to make it happy
|
||||
return Dual2<float> (
|
||||
@@ -1152,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;
|
||||
@@ -1223,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;
|
||||
@@ -1879,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
|
||||
@@ -2245,7 +2259,7 @@ OSL_FORCEINLINE OSL_HOSTDEVICE void perlin (Dual2<Vec3> &result, const H &hash,
|
||||
|
||||
// With Dual2<Vec3> data types, a lot of code is generated below
|
||||
// which caused some runaway compiler memory consumption when vectorizing
|
||||
#if !OSL_INTEL_COMPILER
|
||||
#if !OSL_INTEL_CLASSIC_COMPILER_VERSION
|
||||
auto l_result = OIIO::lerp (
|
||||
OIIO::trilerp (grad (hash (X , Y , Z , W ), fx , fy , fz , fw ),
|
||||
grad (hash (X+1, Y , Z , W ), fx-1.0f, fy , fz , fw ),
|
||||
|
||||
@@ -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)")
|
||||
|
||||
@@ -36,13 +36,14 @@
|
||||
100 * OSL_VERSION_MINOR + \
|
||||
OSL_VERSION_PATCH)
|
||||
|
||||
// Magic macros to make OSL_LIBRARY_VERSION_STRING that looks like "1.2.3"
|
||||
#define OSL_MAKE_VERSION_STRING2(a,b,c,d) #a "." #b "." #c #d
|
||||
#define OSL_MAKE_VERSION_STRING(a,b,c,d) OSL_MAKE_VERSION_STRING2(a,b,c,d)
|
||||
// Magic macros to make OSL_LIBRARY_VERSION_STRING that looks like "1.2.3.0"
|
||||
#define OSL_MAKE_VERSION_STRING2(a,b,c,d,e) #a "." #b "." #c "." #d #e
|
||||
#define OSL_MAKE_VERSION_STRING(a,b,c,d,e) OSL_MAKE_VERSION_STRING2(a,b,c,d,e)
|
||||
#define OSL_LIBRARY_VERSION_STRING \
|
||||
OSL_MAKE_VERSION_STRING(OSL_LIBRARY_VERSION_MAJOR, \
|
||||
OSL_LIBRARY_VERSION_MINOR, \
|
||||
OSL_LIBRARY_VERSION_PATCH, \
|
||||
OSL_LIBRARY_VERSION_TWEAK, \
|
||||
OSL_LIBRARY_VERSION_RELEASE_TYPE)
|
||||
#define OSL_INTRO_STRING "Open Shading Language " OSL_LIBRARY_VERSION_STRING
|
||||
#define OSL_COPYRIGHT_STRING "Copyright Contributors to the Open Shading Language project."
|
||||
@@ -102,4 +103,7 @@ namespace @PROJ_NAME@ = @PROJ_NAMESPACE_V@;
|
||||
#define __OSL_WIDE_PVT __OSL_CONCAT5(b,__OSL_WIDTH,_,__OSL_TARGET_ISA,_pvt)
|
||||
#endif
|
||||
|
||||
#define __OSL_INDIRECT_STRINGIFY(x) #x
|
||||
#define __OSL_STRINGIFY(x) __OSL_INDIRECT_STRINGIFY(x)
|
||||
|
||||
#endif /* OSLVERSION_H */
|
||||
|
||||
+65
-22
@@ -26,6 +26,19 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Detect which compiler and version we're using
|
||||
|
||||
// Notes:
|
||||
// __GNUC__ is defined for gcc and all clang varieties
|
||||
// __clang__ is defined for all clang varieties (generic, Apple, and Intel)
|
||||
// __apple_build_version__ is only defined for Apple clang
|
||||
// __INTEL_COMPILER is defined only for icc
|
||||
// __INTEL_LLVM_COMPILER is defined only for icx
|
||||
// _MSC_VER is defined for MSVS compiler (not gcc/clang/icc even on Windows)
|
||||
// _WIN32 is defined on Windows regardless of compiler
|
||||
// __CUDACC__ is defined any time we are compiling a module for Cuda
|
||||
// (both for the host pass and the device pass). "Do this
|
||||
// when using nvcc or clang with ptx target."
|
||||
// __CUDA_ARCH__ is only defined when doing the device pass. "Do this only
|
||||
// for code that will actually run on the GPU."
|
||||
|
||||
// Define OSL_GNUC_VERSION to hold an encoded gcc version (e.g. 40802 for
|
||||
// 4.8.2), or 0 if not a GCC release. N.B.: This will be 0 for clang.
|
||||
@@ -39,7 +52,7 @@
|
||||
// 30402 for clang 3.4.2), or 0 if not a generic Clang release.
|
||||
// N.B. This will be 0 for the clang Apple distributes (which has different
|
||||
// version numbers entirely).
|
||||
#if defined(__clang__) && !defined(__apple_build_version__)
|
||||
#if defined(__clang__) && !defined(__apple_build_version__) && !defined(__INTEL_LLVM_COMPILER)
|
||||
# define OSL_CLANG_VERSION (10000*__clang_major__ + 100*__clang_minor__ + __clang_patchlevel__)
|
||||
#else
|
||||
# define OSL_CLANG_VERSION 0
|
||||
@@ -48,29 +61,48 @@
|
||||
// Define OSL_APPLE_CLANG_VERSION to hold an encoded Apple Clang version
|
||||
// (e.g. 70002 for clang 7.0.2), or 0 if not an Apple Clang release.
|
||||
#if defined(__clang__) && defined(__apple_build_version__)
|
||||
# if defined(__INTEL_LLVM_COMPILER)
|
||||
# error Not expected for __INTEL_LLVM_COMPILER to be defined with an __apple_build_version__
|
||||
# endif
|
||||
# define OSL_APPLE_CLANG_VERSION (10000*__clang_major__ + 100*__clang_minor__ + __clang_patchlevel__)
|
||||
#else
|
||||
# define OSL_APPLE_CLANG_VERSION 0
|
||||
#endif
|
||||
// The classic Intel(r) C++ Compiler on OSX may still define __clang__
|
||||
// combine with testing OSL_INTEL_CLASSIC_COMPILER_VERSION to further differentiate if needed.
|
||||
|
||||
// Define OSL_INTEL_COMPILER to hold an encoded Intel compiler version
|
||||
// (e.g. 1900), or 0 if not an Intel compiler.
|
||||
// Define OSL_INTEL_CLASSIC_COMPILER_VERSION to hold an encoded Intel(r) C++ Compiler version
|
||||
// (e.g. 1900), or 0 if not an Intel(r) C++ Compiler.
|
||||
#if defined(__INTEL_COMPILER)
|
||||
# define OSL_INTEL_COMPILER __INTEL_COMPILER
|
||||
# define OSL_INTEL_CLASSIC_COMPILER_VERSION __INTEL_COMPILER
|
||||
#else
|
||||
# define OSL_INTEL_COMPILER 0
|
||||
# define OSL_INTEL_CLASSIC_COMPILER_VERSION 0
|
||||
#endif
|
||||
|
||||
// Intel's compiler on OSX may still define __clang__
|
||||
// and we have need to know when using a true clang compiler
|
||||
#if !defined(__INTEL_COMPILER) && defined(__clang__)
|
||||
#define OSL_NON_INTEL_CLANG __clang__
|
||||
// Define OSL_INTEL_LLVM_COMPILER_VERSION to hold an encoded Intel(r) LLVM Compiler version
|
||||
// (e.g. 20220000), or 0 if not an Intel(r) LLVM Compiler.
|
||||
// Define OSL_INTEL_CLANG_VERSION to hold the encoded Clang version the
|
||||
// Intel(r) LLVM Compiler is based on (e.g. 140000),
|
||||
// or 0 if not an Intel(r) LLVM compiler.
|
||||
#if defined(__INTEL_LLVM_COMPILER)
|
||||
# define OSL_INTEL_LLVM_COMPILER_VERSION __INTEL_LLVM_COMPILER
|
||||
# define OSL_INTEL_CLANG_VERSION (10000*__clang_major__ + 100*__clang_minor__ + __clang_patchlevel__)
|
||||
#else
|
||||
#define OSL_NON_INTEL_CLANG 0
|
||||
# define OSL_INTEL_LLVM_COMPILER_VERSION 0
|
||||
# define OSL_INTEL_CLANG_VERSION 0
|
||||
#endif
|
||||
|
||||
// Define OSL_ANY_CLANG to 0 or 1 to indicate if any Clang based compiler is in use
|
||||
#if defined(__clang__)
|
||||
# define OSL_ANY_CLANG 1
|
||||
#else
|
||||
# define OSL_ANY_CLANG 0
|
||||
#endif
|
||||
|
||||
|
||||
// Tests for MSVS versions, always 0 if not MSVS at all.
|
||||
#if defined(_MSC_VER)
|
||||
# define OSL_MSVS_VERSION _MSC_VER
|
||||
# define OSL_MSVS_AT_LEAST_2013 (_MSC_VER >= 1800)
|
||||
# define OSL_MSVS_BEFORE_2013 (_MSC_VER < 1800)
|
||||
# define OSL_MSVS_AT_LEAST_2015 (_MSC_VER >= 1900)
|
||||
@@ -81,6 +113,7 @@
|
||||
# error "This version of OSL is meant to work only with Visual Studio 2017 or later"
|
||||
# endif
|
||||
#else
|
||||
# define OSL_MSVS_VERSION 0
|
||||
# define OSL_MSVS_AT_LEAST_2013 0
|
||||
# define OSL_MSVS_BEFORE_2013 0
|
||||
# define OSL_MSVS_AT_LEAST_2015 0
|
||||
@@ -90,14 +123,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
// Note about __CUDACC__ versus __CUDA_ARCH__:
|
||||
//
|
||||
// __CUDACC__ defined any time we are compiling a module for Cuda
|
||||
// (both for the host pass and the device pass). "Do this
|
||||
// when using nvcc or clang with ptx target."
|
||||
// __CUDA_ARCH__ is only defined when doing the device pass. "Do this only
|
||||
// for code that will actually run on the GPU."
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Detect which C++ standard we're using, and handy macros.
|
||||
@@ -239,6 +264,16 @@
|
||||
#define OSL_OMP_PRAGMA(aUnQuotedPragma)
|
||||
#endif
|
||||
|
||||
#define OSL_OMP_SIMD_LOOP(...) OSL_OMP_PRAGMA(omp simd __VA_ARGS__)
|
||||
|
||||
#if (OSL_GCCVERSION || OSL_INTEL_CLASSIC_COMPILER_VERSION || OSL_INTEL_LLVM_COMPILER_VERSION)
|
||||
# define OSL_OMP_COMPLEX_SIMD_LOOP(...) OSL_OMP_SIMD_LOOP(__VA_ARGS__)
|
||||
#else
|
||||
// Ignore requests to vectorize complex/nested SIMD loops for certain
|
||||
// compilers/versions that are not currently vectorizing complex loops.
|
||||
# define OSL_OMP_COMPLEX_SIMD_LOOP(...)
|
||||
#endif
|
||||
|
||||
// OSL_FORCEINLINE is a function attribute that attempts to make the
|
||||
// function always inline. On many compilers regular 'inline' is only
|
||||
// advisory. Put this attribute before the function return type, just like
|
||||
@@ -447,11 +482,19 @@
|
||||
# define OSL_DASSERT_MSG(x, ...) ((void)sizeof(x)) /*NOLINT*/
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
|
||||
#define OSL_STACK_ARRAY(TYPE, NAME, DYNAMIC_COUNT) TYPE * NAME = reinterpret_cast<TYPE *>(alloca(sizeof(TYPE)*(DYNAMIC_COUNT)))
|
||||
|
||||
/// OSL_ALLOCA is used to allocate smallish amount of memory on the stack,
|
||||
/// equivalent of C99 type var_name[size].
|
||||
///
|
||||
/// NOTE: in a debug build, this will assert for allocations >= 1MB, which is
|
||||
/// much too big. Hopefully this will keep us from abusing alloca and having
|
||||
/// stack overflows. The rule of thumb is that it's ok to use alloca for small
|
||||
/// things of bounded size, but not for anything that could be arbitrarily
|
||||
/// big, which should instead use heap allocation.
|
||||
#if defined(__GNUC__)
|
||||
# define OSL_ALLOCA(type, size) (assert(size < (1<<20)), (size) != 0 ? (reinterpret_cast<type*>(__builtin_alloca((size) * sizeof(type)))) : nullptr)
|
||||
#else
|
||||
// Utilize variable length array compiler extension when available
|
||||
#define OSL_STACK_ARRAY(TYPE, NAME, DYNAMIC_COUNT) TYPE NAME[DYNAMIC_COUNT]
|
||||
# define OSL_ALLOCA(type, size) (assert(size < (1<<20)), (size) != 0 ? (reinterpret_cast<type*>(alloca((size) * sizeof(type)))) : nullptr)
|
||||
#endif
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
@@ -42,6 +42,7 @@ OSL_GCC_PRAGMA(GCC diagnostic ignored "-Wunused-parameter")
|
||||
/// RendererServices defines an abstract interface through which a
|
||||
/// renderer may provide callback to the ShadingSystem.
|
||||
class OSLEXECPUBLIC RendererServices {
|
||||
// Keep interface in sync with rs_free_function.h
|
||||
public:
|
||||
typedef TextureSystem::TextureHandle TextureHandle;
|
||||
typedef TextureSystem::Perthread TexturePerthread;
|
||||
@@ -404,15 +405,6 @@ public:
|
||||
/// Return a pointer to the texture system (if available).
|
||||
virtual TextureSystem *texturesys () const;
|
||||
|
||||
/// Register a string with the renderer, so that the renderer can arrange
|
||||
/// to make the string available in GPU memory as needed. Optionally specify
|
||||
/// a variable name to associate with the string value.
|
||||
virtual uint64_t register_string (const std::string& str,
|
||||
const std::string& var_name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual uint64_t register_global (const std::string& var_name,
|
||||
uint64_t value)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
// Copyright Contributors to the Open Shading Language project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
// Make all the strings defined in OSL
|
||||
// available to the renderer services free functions
|
||||
OSL_NAMESPACE_ENTER
|
||||
namespace Strings {
|
||||
#define STRDECL(str, var_name) OSLEXECPUBLIC extern const ustring var_name;
|
||||
#include <OSL/strdecls.h>
|
||||
#undef STRDECL
|
||||
}; // namespace Strings
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
#ifdef OSL_HOST_RS_BITCODE
|
||||
extern "C" {
|
||||
# define STRDECL(str, var_name) \
|
||||
const OSL::ustring& RS_##var_name = OSL::Strings::var_name;
|
||||
# include <OSL/strdecls.h>
|
||||
# undef STRDECL
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <OSL/device_string.h>
|
||||
#include <OSL/shaderglobals.h>
|
||||
|
||||
// Prefix for OSL shade op declarations.
|
||||
// "C" linkage (no C++ name mangling) and local visibility
|
||||
#define OSL_RSOP extern "C"
|
||||
|
||||
// We are choosing to use unique names encoding parameters directly
|
||||
// as opposed to using overloaded functions.
|
||||
|
||||
// Keep free functions in sync with virtual function based RendererServices.
|
||||
|
||||
/// Get the 4x4 matrix that transforms by the specified
|
||||
/// transformation at the given time. Return true if ok, false
|
||||
/// on error.
|
||||
OSL_RSOP bool
|
||||
rs_get_matrix_xform_time(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
OSL::TransformationPtr from, float time);
|
||||
|
||||
/// Get the 4x4 matrix that transforms by the specified
|
||||
/// transformation at the given time. Return true if ok, false on
|
||||
/// error. Suggested implementation is to use rs_get_matrix_xform_time and
|
||||
/// invert it, but a particular renderer may have a better technique.
|
||||
OSL_RSOP bool
|
||||
rs_get_inverse_matrix_xform_time(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
OSL::TransformationPtr xform, float time);
|
||||
|
||||
/// Get the 4x4 matrix that transforms points from the named
|
||||
/// 'from' coordinate system to "common" space at the given time.
|
||||
/// Returns true if ok, false if the named matrix is not known.
|
||||
OSL_RSOP bool
|
||||
rs_get_matrix_space_time(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
OSL::StringParam from, float time);
|
||||
|
||||
/// Get the 4x4 matrix that transforms points from "common" space to
|
||||
/// the named 'to' coordinate system to at the given time. Suggested
|
||||
/// implementation is to use rs_get_matrix_space_time and invert it, but a
|
||||
/// particular renderer may have a better technique.
|
||||
OSL_RSOP bool
|
||||
rs_get_inverse_matrix_space_time(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
OSL::StringParam to, float time);
|
||||
|
||||
/// Get the 4x4 matrix that transforms by the specified
|
||||
/// transformation. Return true if ok, false on error. Since no
|
||||
/// time value is given, also return false if the transformation may
|
||||
/// be time-varying.
|
||||
OSL_RSOP bool
|
||||
rs_get_matrix_xform(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
OSL::TransformationPtr xform);
|
||||
|
||||
/// Get the 4x4 matrix that transforms by the specified
|
||||
/// transformation. Return true if ok, false on error. Since no
|
||||
/// time value is given, also return false if the transformation may
|
||||
/// be time-varying. Suggested implementation is to use
|
||||
/// rs_get_matrix_xform and invert it, but a particular renderer may have a
|
||||
/// better technique.
|
||||
OSL_RSOP bool
|
||||
rs_get_inverse_matrix_xform(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
OSL::TransformationPtr xform);
|
||||
|
||||
/// Get the 4x4 matrix that transforms 'from' to "common" space.
|
||||
/// Since there is no time value passed, return false if the
|
||||
/// transformation may be time-varying (as well as if it's not found
|
||||
/// at all).
|
||||
OSL_RSOP bool
|
||||
rs_get_matrix_space(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
OSL::StringParam from);
|
||||
|
||||
/// Get the 4x4 matrix that transforms points from "common" space to
|
||||
/// the named 'to' coordinate system. Since there is no time value
|
||||
/// passed, return false if the transformation may be time-varying
|
||||
/// (as well as if it's not found at all). Suggested
|
||||
/// implementation is to use rs_get_matrix_space and invert it, but a
|
||||
/// particular renderer may have a better technique.
|
||||
OSL_RSOP bool
|
||||
rs_get_inverse_matrix_space(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
|
||||
OSL::StringParam to);
|
||||
|
||||
/// Transform points Pin[0..npoints-1] in named coordinate system
|
||||
/// 'from' into 'to' coordinates, storing the result in Pout[] using
|
||||
/// the specified vector semantic (POINT, VECTOR, NORMAL). The
|
||||
/// function returns true if the renderer correctly transformed the
|
||||
/// points, false if it failed (for example, because it did not know
|
||||
/// the name of one of the coordinate systems). Suggested implementation
|
||||
/// is simply to make appropriate calls to rs_get_matrix_space and
|
||||
/// get_inverse_matrix_space. The existence of this function is to allow
|
||||
/// some renderers to provide transformations that cannot be
|
||||
/// expressed by a 4x4 matrix.
|
||||
///
|
||||
/// Note, the virtual function based RendererServices::transform_points
|
||||
/// provides additional functionality/modes that are only used during
|
||||
/// code generation to detect if it required to even call rs_transform_points
|
||||
/// during evaluation of the shader. There is no need for the free
|
||||
/// function version to handle these additional modes.
|
||||
///
|
||||
/// Note to implementations: just return 'false'
|
||||
/// if there isn't a special nonlinear transformation between the
|
||||
/// two spaces.
|
||||
OSL_RSOP bool
|
||||
rs_transform_points(OSL::ShaderGlobals* sg, OSL::StringParam from,
|
||||
OSL::StringParam to, float time, const OSL::Vec3* Pin,
|
||||
OSL::Vec3* Pout, int npoints,
|
||||
OSL::TypeDesc::VECSEMANTICS vectype);
|
||||
@@ -68,7 +68,7 @@ namespace sfm
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if OSL_INTEL_COMPILER
|
||||
#if OSL_INTEL_CLASSIC_COMPILER_VERSION
|
||||
// std::isinf wasn't vectorizing and was branchy. This slightly
|
||||
// perturbed version fairs better and is branch free when vectorized
|
||||
// with the Intel compiler.
|
||||
@@ -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
|
||||
@@ -263,7 +263,7 @@ namespace sfm
|
||||
}
|
||||
}
|
||||
|
||||
#if OSL_CLANG_VERSION && !OSL_INTEL_COMPILER
|
||||
#if OSL_ANY_CLANG && !OSL_INTEL_CLASSIC_COMPILER_VERSION && !OSL_INTEL_LLVM_COMPILER_VERSION
|
||||
|
||||
// To make clang's loop vectorizor happy
|
||||
// we need to make sure result of min and max
|
||||
@@ -441,7 +441,7 @@ namespace sfm
|
||||
|
||||
// Considering having functionally equivalent versions of Vec3, Color3, Matrix44
|
||||
// with slight modifications to inlining and implementation to avoid aliasing and
|
||||
// improve likelyhood of proper privation of local variables within a SIMD loop
|
||||
// improve likelihood of proper privation of local variables within a SIMD loop
|
||||
|
||||
} // namespace sfm
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@ class RendererServices;
|
||||
/// coordinate transformation.
|
||||
typedef const void* TransformationPtr;
|
||||
|
||||
/// Type for an opaque pointer to whatever the Shading System uses to represent
|
||||
/// Uniform State.
|
||||
typedef const void* OpaqueShadingStateUniformPtr;
|
||||
|
||||
|
||||
/// The ShaderGlobals structure represents the state describing a particular
|
||||
@@ -83,6 +86,7 @@ struct ShaderGlobals {
|
||||
/// Back-pointer to the ShadingContext (set and used by OSL itself --
|
||||
/// renderers shouldn't mess with this at all).
|
||||
ShadingContext* context;
|
||||
OpaqueShadingStateUniformPtr shadingStateUniform;
|
||||
|
||||
/// Pointer to the RendererServices object. This is how OSL finds its
|
||||
/// way back to the renderer for callbacks.
|
||||
|
||||
@@ -139,6 +139,8 @@ STRDECL("SMPTE", SMPTE)
|
||||
STRDECL("HDTV", HDTV)
|
||||
STRDECL("CIE", CIE)
|
||||
STRDECL("AdobeRGB", AdobeRGB)
|
||||
STRDECL("ACES2065-1", ACES2065_1)
|
||||
STRDECL("ACEScg", ACEScg)
|
||||
STRDECL("colorsystem", colorsystem)
|
||||
STRDECL("arraylength", arraylength)
|
||||
STRDECL("unknown", unknown)
|
||||
|
||||
+672
-495
File diff suppressed because it is too large
Load Diff
@@ -19,7 +19,7 @@ namespace __OSL_WIDE_PVT {
|
||||
|
||||
OSL_USING_DATA_WIDTH(__OSL_WIDTH)
|
||||
|
||||
// Foward declaration, implementation is in liboslnoise/wide_gabornoise.h
|
||||
// Forward declaration, implementation is in liboslnoise/wide_gabornoise.h
|
||||
struct DisabledFilterPolicy {
|
||||
static constexpr bool active = false;
|
||||
};
|
||||
@@ -34,7 +34,7 @@ OSL_NOINLINE void
|
||||
wide_gabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
|
||||
NoiseParams const* opt, Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_gabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
|
||||
@@ -46,20 +46,20 @@ OSL_NOINLINE void
|
||||
wide_gabor(Masked<Dual2<float>> wResult, Wide<const Dual2<Vec3>> wP,
|
||||
NoiseParams const* opt, Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_gabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
|
||||
NoiseParams const* opt, Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_gabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
|
||||
Wide<const Dual2<float>> wY, NoiseParams const* opt,
|
||||
Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_gabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<Vec3>> wP,
|
||||
@@ -71,14 +71,14 @@ wide_gabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<Vec3>> wP,
|
||||
// Periodic gabor(s)
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
|
||||
Wide<const float> wXp, NoiseParams const* opt,
|
||||
Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
|
||||
@@ -86,7 +86,7 @@ wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
|
||||
Wide<const float> wYp, NoiseParams const* opt,
|
||||
Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<Vec3>> wP,
|
||||
@@ -95,14 +95,14 @@ wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<Vec3>> wP,
|
||||
|
||||
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_pgabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
|
||||
Wide<const float> wXp, NoiseParams const* opt,
|
||||
Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_pgabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
|
||||
@@ -110,7 +110,7 @@ wide_pgabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
|
||||
Wide<const float> wYp, NoiseParams const* opt,
|
||||
Block<Vec3>* opt_varying_direction);
|
||||
|
||||
// Foward declaration, implementation is in wide_gabor.h
|
||||
// Forward declaration, implementation is in wide_gabor.h
|
||||
template<int AnisotropicT, typename FilterPolicyT>
|
||||
OSL_NOINLINE void
|
||||
wide_pgabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<Vec3>> wP,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
#include <OSL/oslversion.h>
|
||||
|
||||
#ifdef OSL_USE_OPTIX
|
||||
@@ -13,14 +14,18 @@
|
||||
# ifdef _WIN32
|
||||
# define NOMINMAX
|
||||
# endif
|
||||
# if (OPTIX_VERSION < 70000)
|
||||
# include <optix_world.h>
|
||||
# endif
|
||||
#else
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(OSL_USE_OPTIX) && !defined(__CUDA_ARCH__)
|
||||
using CUdeviceptr = void*;
|
||||
using float3 = OSL::Vec3;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
#ifdef OSL_USE_OPTIX
|
||||
@@ -31,14 +36,12 @@ OSL_NAMESPACE_ENTER
|
||||
|
||||
|
||||
// TODO clean this up once OptiX6 support is dropped
|
||||
# if (OPTIX_VERSION < 70000)
|
||||
namespace optix = ::optix;
|
||||
# else
|
||||
namespace optix {
|
||||
typedef OptixDeviceContext Context;
|
||||
typedef cudaTextureObject_t TextureSampler;
|
||||
using ::CUdeviceptr;
|
||||
using ::float3;
|
||||
} // namespace optix
|
||||
# endif
|
||||
|
||||
using ::cudaFree;
|
||||
using ::cudaMalloc;
|
||||
@@ -49,13 +52,19 @@ using ::cudaMalloc;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// If OptiX is not available, make reasonable proxies just so that we
|
||||
// don't have to litter the code with quite as many #ifdef's.
|
||||
// OSL::optix::
|
||||
// Mostly under OSL::optix::
|
||||
|
||||
|
||||
|
||||
namespace optix {
|
||||
|
||||
typedef void* Context;
|
||||
typedef void* Program;
|
||||
typedef void* TextureSampler;
|
||||
typedef void* CUdeviceptr;
|
||||
using float3 = OSL::Vec3;
|
||||
|
||||
|
||||
struct Exception {
|
||||
static const char* what() { return "OSL compiled without Optix."; }
|
||||
};
|
||||
|
||||
+216
-56
@@ -51,7 +51,8 @@ enum SymType {
|
||||
SymTypeGlobal,
|
||||
SymTypeConst,
|
||||
SymTypeFunction,
|
||||
SymTypeType
|
||||
SymTypeType,
|
||||
SymTypeLast
|
||||
};
|
||||
|
||||
|
||||
@@ -557,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; }
|
||||
|
||||
@@ -632,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.
|
||||
///
|
||||
@@ -724,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
|
||||
@@ -753,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
|
||||
@@ -791,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
|
||||
@@ -854,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;
|
||||
|
||||
@@ -45,22 +45,23 @@ if (MSVC)
|
||||
target_link_libraries (${local_lib} PRIVATE "Version.lib")
|
||||
endif()
|
||||
|
||||
set (link_flags "${VISIBILITY_MAP_COMMAND} ${EXTRA_DSO_LINK_ARGS}")
|
||||
if (UNIX AND NOT APPLE)
|
||||
# Hide symbols from any static dependent libraries embedded here.
|
||||
set (link_flags "${link_flags} -Wl,--exclude-libs,ALL")
|
||||
endif ()
|
||||
|
||||
target_compile_features (${local_lib}
|
||||
PUBLIC cxx_std_${CMAKE_CXX_STANDARD})
|
||||
INTERFACE cxx_std_${DOWNSTREAM_CXX_STANDARD})
|
||||
|
||||
set_target_properties (${local_lib}
|
||||
PROPERTIES
|
||||
VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}
|
||||
SOVERSION ${SOVERSION}
|
||||
OUTPUT_NAME ${local_lib}${OSL_LIBNAME_SUFFIX}
|
||||
LINK_FLAGS ${link_flags}
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
)
|
||||
|
||||
|
||||
if (VISIBILITY_MAP_COMMAND)
|
||||
set_property (TARGET ${local_lib}
|
||||
APPEND PROPERTY LINK_FLAGS ${VISIBILITY_MAP_COMMAND})
|
||||
endif ()
|
||||
|
||||
install_targets (${local_lib})
|
||||
|
||||
|
||||
+98
-90
@@ -35,7 +35,7 @@ std::atomic<int> node_counts_peak[ASTNode::_last_node];
|
||||
class ScopeExit {
|
||||
public:
|
||||
typedef std::function<void()> Task;
|
||||
explicit ScopeExit(Task&& task) : m_task(std::forward<Task>(task)) {}
|
||||
explicit ScopeExit(Task&& task) : m_task(std::move(task)) {}
|
||||
~ScopeExit() { m_task(); }
|
||||
|
||||
private:
|
||||
@@ -45,8 +45,8 @@ private:
|
||||
ScopeExit print_node_counts([]() {
|
||||
for (int i = 0; i < ASTNode::_last_node; ++i)
|
||||
if (node_counts[i] > 0)
|
||||
Strutil::printf("ASTNode type %2d: %5d (peak %5d)\n", i,
|
||||
node_counts[i], node_counts_peak[i]);
|
||||
Strutil::print("ASTNode type {:2}: {:5} (peak {:5})\n", i,
|
||||
node_counts[i], node_counts_peak[i]);
|
||||
});
|
||||
} // namespace
|
||||
#endif
|
||||
@@ -213,7 +213,7 @@ ASTNode::~ASTNode()
|
||||
void
|
||||
ASTNode::error_impl(string_view msg) const
|
||||
{
|
||||
m_compiler->errorf(sourcefile(), sourceline(), "%s", msg);
|
||||
m_compiler->errorfmt(sourcefile(), sourceline(), "{}", msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -221,7 +221,7 @@ ASTNode::error_impl(string_view msg) const
|
||||
void
|
||||
ASTNode::warning_impl(string_view msg) const
|
||||
{
|
||||
m_compiler->warningf(sourcefile(), sourceline(), "%s", msg);
|
||||
m_compiler->warningfmt(sourcefile(), sourceline(), "{}", msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -229,7 +229,7 @@ ASTNode::warning_impl(string_view msg) const
|
||||
void
|
||||
ASTNode::info_impl(string_view msg) const
|
||||
{
|
||||
m_compiler->infof(sourcefile(), sourceline(), "%s", msg);
|
||||
m_compiler->infofmt(sourcefile(), sourceline(), "{}", msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -237,7 +237,7 @@ ASTNode::info_impl(string_view msg) const
|
||||
void
|
||||
ASTNode::message_impl(string_view msg) const
|
||||
{
|
||||
m_compiler->messagef(sourcefile(), sourceline(), "%s", msg);
|
||||
m_compiler->messagefmt(sourcefile(), sourceline(), "{}", msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -246,12 +246,11 @@ void
|
||||
ASTNode::print(std::ostream& out, int indentlevel) const
|
||||
{
|
||||
indent(out, indentlevel);
|
||||
out << "(" << nodetypename() << " : "
|
||||
<< " (type: " << typespec().string() << ") "
|
||||
<< (opname() ? opname() : "") << "\n";
|
||||
OSL::print(out, "({} : (type: {}) {}\n", nodetypename(), typespec(),
|
||||
(opname() ? opname() : ""));
|
||||
printchildren(out, indentlevel);
|
||||
indent(out, indentlevel);
|
||||
out << ")\n";
|
||||
OSL::print(out, ")\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -264,13 +263,13 @@ ASTNode::printchildren(std::ostream& out, int indentlevel) const
|
||||
continue;
|
||||
indent(out, indentlevel);
|
||||
if (childname(i))
|
||||
out << " " << childname(i);
|
||||
OSL::print(out, " {}", childname(i));
|
||||
else
|
||||
out << " child" << i;
|
||||
out << ": ";
|
||||
OSL::print(out, " child{}", i);
|
||||
OSL::print(out, ": ");
|
||||
if (typespec() != TypeSpec() && !child(i)->next())
|
||||
out << " (type: " << typespec().string() << ")";
|
||||
out << "\n";
|
||||
OSL::print(out, " (type: {})", typespec());
|
||||
OSL::print(out, "\n");
|
||||
printlist(out, child(i), indentlevel + 1);
|
||||
}
|
||||
}
|
||||
@@ -314,11 +313,8 @@ std::string
|
||||
ASTNode::list_to_types_string(const ASTNode* node)
|
||||
{
|
||||
std::ostringstream result;
|
||||
for (int i = 0; node; node = node->nextptr(), ++i) {
|
||||
if (i)
|
||||
result << ", ";
|
||||
result << node->typespec();
|
||||
}
|
||||
for (int i = 0; node; node = node->nextptr(), ++i)
|
||||
OSL::print(result, "{}{}", i ? ", " : "", node->typespec());
|
||||
return result.str();
|
||||
}
|
||||
|
||||
@@ -335,11 +331,11 @@ ASTshader_declaration::ASTshader_declaration(OSLCompilerImpl* comp, int stype,
|
||||
OSL_ASSERT(arg->nodetype() == variable_declaration_node);
|
||||
ASTvariable_declaration* v = (ASTvariable_declaration*)arg;
|
||||
if (!v->init())
|
||||
v->errorf("shader parameter '%s' requires a default initializer",
|
||||
v->name());
|
||||
v->errorfmt("shader parameter '{}' requires a default initializer",
|
||||
v->name());
|
||||
if (v->is_output() && v->typespec().is_unsized_array())
|
||||
v->errorf("shader output parameter '%s' can't be unsized array",
|
||||
v->name());
|
||||
v->errorfmt("shader output parameter '{}' can't be unsized array",
|
||||
v->name());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,11 +354,11 @@ void
|
||||
ASTshader_declaration::print(std::ostream& out, int indentlevel) const
|
||||
{
|
||||
indent(out, indentlevel);
|
||||
out << "(" << nodetypename() << " " << shadertypename() << " \""
|
||||
<< m_shadername << "\"\n";
|
||||
OSL::print(out, "({} {} \"{}\"\n", nodetypename(), shadertypename(),
|
||||
m_shadername);
|
||||
printchildren(out, indentlevel);
|
||||
indent(out, indentlevel);
|
||||
out << ")\n";
|
||||
OSL::print(out, ")\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -392,13 +388,13 @@ ASTfunction_declaration::ASTfunction_declaration(OSLCompilerImpl* comp,
|
||||
m_sourceline = sourceline_start;
|
||||
|
||||
if (Strutil::starts_with(name, "___"))
|
||||
errorf("\"%s\" : sorry, can't start with three underscores", name);
|
||||
errorfmt("\"{}\" : sorry, can't start with three underscores", name);
|
||||
|
||||
// Get a pointer to the first of the existing symbols of that name.
|
||||
Symbol* existing_syms = comp->symtab().clash(name);
|
||||
if (existing_syms && existing_syms->symtype() != SymTypeFunction) {
|
||||
errorf("\"%s\" already declared in this scope as a %s", name,
|
||||
existing_syms->typespec());
|
||||
errorfmt("\"{}\" already declared in this scope as a {}", name,
|
||||
existing_syms->typespec());
|
||||
// FIXME -- print the file and line of the other definition
|
||||
existing_syms = NULL;
|
||||
}
|
||||
@@ -416,8 +412,8 @@ ASTfunction_declaration::ASTfunction_declaration(OSLCompilerImpl* comp,
|
||||
OSL_ASSERT(arg->nodetype() == variable_declaration_node);
|
||||
ASTvariable_declaration* v = (ASTvariable_declaration*)arg;
|
||||
if (v->init())
|
||||
v->errorf(
|
||||
"function parameter '%s' may not have a default initializer.",
|
||||
v->errorfmt(
|
||||
"function parameter '{}' may not have a default initializer.",
|
||||
v->name());
|
||||
}
|
||||
|
||||
@@ -435,16 +431,15 @@ ASTfunction_declaration::ASTfunction_declaration(OSLCompilerImpl* comp,
|
||||
auto other = static_cast<ASTfunction_declaration*>(f->node());
|
||||
if (!other || (other->statements() || other->is_builtin())) {
|
||||
if (err.empty()) {
|
||||
err = Strutil::sprintf("Function '%s %s (%s)' redefined "
|
||||
"in the same scope\n"
|
||||
" Previous definitions:",
|
||||
type, name,
|
||||
list_to_types_string(form));
|
||||
err = Strutil::fmt::format(
|
||||
"Function '{} {} ({})' redefined in the same scope\n"
|
||||
" Previous definitions:",
|
||||
type, name, list_to_types_string(form));
|
||||
}
|
||||
err += "\n ";
|
||||
if (other) {
|
||||
err += Strutil::sprintf(
|
||||
"%s:%d",
|
||||
err += Strutil::fmt::format(
|
||||
"{}:{}",
|
||||
OIIO::Filesystem::filename(
|
||||
other->sourcefile().string()),
|
||||
other->sourceline());
|
||||
@@ -454,7 +449,7 @@ ASTfunction_declaration::ASTfunction_declaration(OSLCompilerImpl* comp,
|
||||
}
|
||||
}
|
||||
if (!err.empty())
|
||||
warningf("%s", err);
|
||||
warningfmt("{}", err);
|
||||
}
|
||||
|
||||
|
||||
@@ -519,10 +514,10 @@ void
|
||||
ASTfunction_declaration::print(std::ostream& out, int indentlevel) const
|
||||
{
|
||||
indent(out, indentlevel);
|
||||
out << nodetypename() << " " << m_sym->mangled();
|
||||
OSL::print(out, "{} {}", nodetypename(), m_sym->mangled());
|
||||
if (m_sym->scope())
|
||||
out << " (" << m_sym->name() << " in scope " << m_sym->scope() << ")";
|
||||
out << "\n";
|
||||
OSL::print(out, " ({} in scope {})", m_sym->name(), m_sym->scope());
|
||||
OSL::print(out, "\n");
|
||||
printchildren(out, indentlevel);
|
||||
}
|
||||
|
||||
@@ -557,23 +552,24 @@ ASTvariable_declaration::ASTvariable_declaration(OSLCompilerImpl* comp,
|
||||
m_typespec = type;
|
||||
Symbol* f = comp->symtab().clash(name);
|
||||
if (f && !m_ismetadata) {
|
||||
std::string e = Strutil::sprintf("\"%s\" already declared in this scope",
|
||||
name.c_str());
|
||||
std::string e
|
||||
= Strutil::fmt::format("\"{}\" already declared in this scope",
|
||||
name);
|
||||
if (f->node()) {
|
||||
std::string filename = OIIO::Filesystem::filename(
|
||||
f->node()->sourcefile().string());
|
||||
e += Strutil::sprintf("\n\t\tprevious declaration was at %s:%d",
|
||||
filename, f->node()->sourceline());
|
||||
e += Strutil::fmt::format("\n\t\tprevious declaration was at {}:{}",
|
||||
filename, f->node()->sourceline());
|
||||
}
|
||||
if (f->scope() == 0 && f->symtype() == SymTypeFunction && isparam) {
|
||||
// special case: only a warning for param to mask global function
|
||||
warningf("%s", e);
|
||||
warningfmt("{}", e);
|
||||
} else {
|
||||
errorf("%s", e);
|
||||
errorfmt("{}", e);
|
||||
}
|
||||
}
|
||||
if (OIIO::Strutil::starts_with(name, "___")) {
|
||||
errorf("\"%s\" : sorry, can't start with three underscores", name);
|
||||
errorfmt("\"{}\" : sorry, can't start with three underscores", name);
|
||||
}
|
||||
SymType symtype = isparam ? (isoutput ? SymTypeOutputParam : SymTypeParam)
|
||||
: SymTypeLocal;
|
||||
@@ -582,8 +578,14 @@ ASTvariable_declaration::ASTvariable_declaration(OSLCompilerImpl* comp,
|
||||
if (symtype == SymTypeLocal && Strutil::starts_with(name, "__debug_tmp__"))
|
||||
symtype = SymTypeTemp;
|
||||
m_sym = new Symbol(name, type, symtype, this);
|
||||
if (!m_ismetadata)
|
||||
if (m_ismetadata) {
|
||||
// Metadata doesn't go in the symbol table, so we need to retain
|
||||
// an owning pointer so it doesn't leak.
|
||||
m_sym_owned.reset(m_sym);
|
||||
} else {
|
||||
// Put in the symbol table, after which symtab is the owner
|
||||
m_compiler->symtab().insert(m_sym);
|
||||
}
|
||||
|
||||
// A struct really makes several subvariables
|
||||
if (type.is_structure() || type.is_structure_array()) {
|
||||
@@ -620,17 +622,15 @@ void
|
||||
ASTvariable_declaration::print(std::ostream& out, int indentlevel) const
|
||||
{
|
||||
indent(out, indentlevel);
|
||||
out << "(" << nodetypename() << " " << m_sym->typespec().string() << " "
|
||||
<< m_sym->mangled();
|
||||
OSL::print(out, "({} {}", nodetypename(), m_sym->mangled());
|
||||
#if 0
|
||||
if (m_sym->scope())
|
||||
out << " (" << m_sym->name()
|
||||
<< " in scope " << m_sym->scope() << ")";
|
||||
OSL::print(out, " ({} in scope {})", m_sym->name(), m_sym->scope());
|
||||
#endif
|
||||
out << "\n";
|
||||
OSL::print(out, "\n");
|
||||
printchildren(out, indentlevel);
|
||||
indent(out, indentlevel);
|
||||
out << ")\n";
|
||||
OSL::print(out, ")\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -640,13 +640,17 @@ ASTvariable_ref::ASTvariable_ref(OSLCompilerImpl* comp, ustring name)
|
||||
{
|
||||
m_sym = comp->symtab().find(name);
|
||||
if (!m_sym) {
|
||||
errorf("'%s' was not declared in this scope", name);
|
||||
errorfmt("'{}' was not declared in this scope", name);
|
||||
// FIXME -- would be fun to troll through the symtab and try to
|
||||
// find the things that almost matched and offer suggestions.
|
||||
return;
|
||||
}
|
||||
if (m_sym->symtype() == SymTypeFunction) {
|
||||
errorf("function '%s' can't be used as a variable", name);
|
||||
errorfmt("function '{}' can't be used as a variable", name);
|
||||
return;
|
||||
}
|
||||
if (m_sym->symtype() == SymTypeType) {
|
||||
errorfmt("type name '{}' can't be used as a variable", name);
|
||||
return;
|
||||
}
|
||||
m_typespec = m_sym->typespec();
|
||||
@@ -658,9 +662,9 @@ void
|
||||
ASTvariable_ref::print(std::ostream& out, int indentlevel) const
|
||||
{
|
||||
indent(out, indentlevel);
|
||||
out << "(" << nodetypename()
|
||||
<< " (type: " << (m_sym ? m_sym->typespec().string() : "unknown")
|
||||
<< ") " << (m_sym ? m_sym->mangled() : m_name.string()) << ")\n";
|
||||
OSL::print(out, "({} (type: {}) {})\n", nodetypename(),
|
||||
m_sym ? m_sym->typespec().string() : "unknown",
|
||||
m_sym ? m_sym->mangled() : m_name.string());
|
||||
OSL_DASSERT(nchildren() == 0);
|
||||
}
|
||||
|
||||
@@ -758,7 +762,7 @@ ASTindex::ASTindex(OSLCompilerImpl* comp, ASTNode* expr, ASTNode* index,
|
||||
}
|
||||
|
||||
if (m_typespec.is_unknown()) {
|
||||
errorf("indexing into non-array or non-component type");
|
||||
errorfmt("indexing into non-array or non-component type");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -823,7 +827,7 @@ ASTstructselect::find_fieldsym(int& structid, int& fieldid)
|
||||
}
|
||||
|
||||
if (!lvtype.is_structure() && !lvtype.is_structure_array()) {
|
||||
errorf("type '%s' does not have a member '%s'", lvtype, m_field);
|
||||
errorfmt("type '{}' does not have a member '{}'", lvtype, m_field);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -842,14 +846,14 @@ ASTstructselect::find_fieldsym(int& structid, int& fieldid)
|
||||
}
|
||||
|
||||
if (fieldid < 0) {
|
||||
errorf("struct type '%s' does not have a member '%s'",
|
||||
structspec->name(), m_field);
|
||||
errorfmt("struct type '{}' does not have a member '{}'",
|
||||
structspec->name(), m_field);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const StructSpec::FieldSpec& fieldrec(structspec->field(fieldid));
|
||||
ustring fieldsymname = ustring::sprintf("%s.%s", structsymname,
|
||||
fieldrec.name);
|
||||
ustring fieldsymname = ustring::fmtformat("{}.{}", structsymname,
|
||||
fieldrec.name);
|
||||
Symbol* sym = m_compiler->symtab().find(fieldsymname);
|
||||
return sym;
|
||||
}
|
||||
@@ -910,7 +914,7 @@ ASTstructselect::print(std::ostream& out, int indentlevel) const
|
||||
{
|
||||
ASTNode::print(out, indentlevel);
|
||||
indent(out, indentlevel + 1);
|
||||
out << "select " << field() << "\n";
|
||||
OSL::print(out, "select {}\n", field());
|
||||
}
|
||||
|
||||
|
||||
@@ -960,7 +964,8 @@ ASTloop_statement::opname() const
|
||||
|
||||
|
||||
|
||||
const char* ASTloopmod_statement::childname(size_t /*i*/) const
|
||||
const char*
|
||||
ASTloopmod_statement::childname(size_t /*i*/) const
|
||||
{
|
||||
return NULL; // no children
|
||||
}
|
||||
@@ -979,7 +984,8 @@ ASTloopmod_statement::opname() const
|
||||
|
||||
|
||||
|
||||
const char* ASTreturn_statement::childname(size_t /*i*/) const
|
||||
const char*
|
||||
ASTreturn_statement::childname(size_t /*i*/) const
|
||||
{
|
||||
return "expression"; // only child
|
||||
}
|
||||
@@ -995,7 +1001,8 @@ ASTcompound_initializer::ASTcompound_initializer(OSLCompilerImpl* comp,
|
||||
|
||||
|
||||
|
||||
const char* ASTcompound_initializer::childname(size_t /*i*/) const
|
||||
const char*
|
||||
ASTcompound_initializer::childname(size_t /*i*/) const
|
||||
{
|
||||
return canconstruct() ? "args" : "expression_list";
|
||||
}
|
||||
@@ -1025,8 +1032,8 @@ ASTNode::check_symbol_writeability(ASTNode* var, bool quiet, Symbol** dest_sym)
|
||||
*dest_sym = dest;
|
||||
if (dest->readonly()) {
|
||||
if (!quiet)
|
||||
warningf("cannot write to non-output parameter \"%s\"",
|
||||
dest->name());
|
||||
warningfmt("cannot write to non-output parameter \"{}\"",
|
||||
dest->name());
|
||||
// Note: Consider it only a warning to write to a non-output
|
||||
// parameter. Users who want it to be a hard error can use
|
||||
// -Werror. Writing to any other readonly symbols is a full
|
||||
@@ -1034,8 +1041,8 @@ ASTNode::check_symbol_writeability(ASTNode* var, bool quiet, Symbol** dest_sym)
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// std::cout << "Don't know how to check_symbol_writeability "
|
||||
// << var->nodetypename() << "\n";
|
||||
// OSL::print("Don't know how to check_symbol_writeability {}\n",
|
||||
// var->nodetypename());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1118,7 +1125,7 @@ ASTunary_expression::ASTunary_expression (OSLCompilerImpl *comp, int op,
|
||||
: ASTNode (unary_expression_node, comp, op, expr)
|
||||
{
|
||||
// Check for a user-overloaded function for this operator
|
||||
Symbol *sym = comp->symtab().find (ustring::sprintf ("__operator__%s__", opword()));
|
||||
Symbol *sym = comp->symtab().find(ustring::fmtformat("__operator__{}__", opword()));
|
||||
if (sym && sym->symtype() == SymTypeFunction)
|
||||
m_function_overload = (FunctionSymbol *)sym;
|
||||
}
|
||||
@@ -1173,7 +1180,7 @@ ASTbinary_expression::ASTbinary_expression (OSLCompilerImpl *comp, Operator op,
|
||||
// Check for a user-overloaded function for this operator.
|
||||
// Disallow a few ops from overloading.
|
||||
if (op != And && op != Or) {
|
||||
ustring funcname = ustring::sprintf ("__operator__%s__", opword());
|
||||
ustring funcname = ustring::fmtformat("__operator__{}__", opword());
|
||||
Symbol *sym = comp->symtab().find (funcname);
|
||||
if (sym && sym->symtype() == SymTypeFunction)
|
||||
m_function_overload = (FunctionSymbol *)sym;
|
||||
@@ -1294,7 +1301,7 @@ ASTfunction_call::ASTfunction_call(OSLCompilerImpl* comp, ustring name,
|
||||
, m_argtakesderivs(0) // Default - doesn't take derivs
|
||||
{
|
||||
if (!m_sym) {
|
||||
errorf("function '%s' was not declared in this scope", name);
|
||||
errorfmt("function '{}' was not declared in this scope", name);
|
||||
// FIXME -- would be fun to troll through the symtab and try to
|
||||
// find the things that almost matched and offer suggestions.
|
||||
return;
|
||||
@@ -1303,7 +1310,7 @@ ASTfunction_call::ASTfunction_call(OSLCompilerImpl* comp, ustring name,
|
||||
return; // It's a struct constructor
|
||||
}
|
||||
if (m_sym->symtype() != SymTypeFunction) {
|
||||
errorf("'%s' is not a function", name);
|
||||
errorfmt("'{}' is not a function", name);
|
||||
m_sym = NULL;
|
||||
return;
|
||||
}
|
||||
@@ -1314,7 +1321,7 @@ ASTfunction_call::ASTfunction_call(OSLCompilerImpl* comp, ustring name,
|
||||
const char*
|
||||
ASTfunction_call::childname(size_t i) const
|
||||
{
|
||||
return ustring::sprintf("param%d", (int)i).c_str();
|
||||
return ustring::fmtformat("param{}", (int)i).c_str();
|
||||
}
|
||||
|
||||
|
||||
@@ -1333,16 +1340,17 @@ ASTfunction_call::print(std::ostream& out, int indentlevel) const
|
||||
ASTNode::print(out, indentlevel);
|
||||
#if 0
|
||||
if (is_user_function()) {
|
||||
out << "\n";
|
||||
OSL::print(out, "\n");
|
||||
user_function()->print (out, indentlevel+1);
|
||||
out << "\n";
|
||||
OSL::print(out, "\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char* ASTliteral::childname(size_t /*i*/) const
|
||||
const char*
|
||||
ASTliteral::childname(size_t /*i*/) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -1353,14 +1361,14 @@ void
|
||||
ASTliteral::print(std::ostream& out, int indentlevel) const
|
||||
{
|
||||
indent(out, indentlevel);
|
||||
out << "(" << nodetypename() << " (type: " << m_typespec.string() << ") ";
|
||||
OSL::print(out, "({} (type: {}) ", nodetypename(), m_typespec);
|
||||
if (m_typespec.is_int())
|
||||
out << m_i;
|
||||
OSL::print(out, "{}", m_i);
|
||||
else if (m_typespec.is_float())
|
||||
out << m_f;
|
||||
OSL::print(out, "{}", m_f);
|
||||
else if (m_typespec.is_string())
|
||||
out << "\"" << m_s << "\"";
|
||||
out << ")\n";
|
||||
OSL::print(out, "\"{}\"", m_s);
|
||||
OSL::print(out, ")\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
+12
-11
@@ -202,34 +202,34 @@ public:
|
||||
void sourceline(int line) { m_sourceline = line; }
|
||||
|
||||
template<typename... Args>
|
||||
void errorf(const char* format, const Args&... args) const
|
||||
void errorfmt(const char* format, const Args&... args) const
|
||||
{
|
||||
OSL_DASSERT(format && format[0]);
|
||||
error_impl(OIIO::Strutil::sprintf(format, args...));
|
||||
error_impl(OIIO::Strutil::fmt::format(format, args...));
|
||||
}
|
||||
|
||||
/// Warning reporting
|
||||
template<typename... Args>
|
||||
void warningf(const char* format, const Args&... args) const
|
||||
void warningfmt(const char* format, const Args&... args) const
|
||||
{
|
||||
OSL_DASSERT(format && format[0]);
|
||||
warning_impl(OIIO::Strutil::sprintf(format, args...));
|
||||
warning_impl(OIIO::Strutil::fmt::format(format, args...));
|
||||
}
|
||||
|
||||
/// info reporting
|
||||
template<typename... Args>
|
||||
void infof(const char* format, const Args&... args) const
|
||||
void infofmt(const char* format, const Args&... args) const
|
||||
{
|
||||
OSL_DASSERT(format && format[0]);
|
||||
info_impl(OIIO::Strutil::sprintf(format, args...));
|
||||
info_impl(OIIO::Strutil::fmt::format(format, args...));
|
||||
}
|
||||
|
||||
/// message reporting
|
||||
template<typename... Args>
|
||||
void messagef(const char* format, const Args&... args) const
|
||||
void messagefmt(const char* format, const Args&... args) const
|
||||
{
|
||||
OSL_DASSERT(format && format[0]);
|
||||
message_impl(OIIO::Strutil::sprintf(format, args...));
|
||||
message_impl(OIIO::Strutil::fmt::format(format, args...));
|
||||
}
|
||||
|
||||
bool is_lvalue() const { return m_is_lvalue; }
|
||||
@@ -375,7 +375,7 @@ protected:
|
||||
void codegen_initlist(ref init, TypeSpec type, Symbol* sym);
|
||||
|
||||
// Special code generation for structure initializers.
|
||||
// It's in the ASTNode base class because it's used from mutiple
|
||||
// It's in the ASTNode base class because it's used from multiple
|
||||
// subclasses.
|
||||
Symbol* codegen_struct_initializers(ref init, Symbol* sym,
|
||||
bool is_constructor = false,
|
||||
@@ -520,7 +520,7 @@ public:
|
||||
|
||||
private:
|
||||
ustring m_name; ///< Name of the symbol (unmangled)
|
||||
Symbol* m_sym; ///< Ptr to the symbol this declares
|
||||
Symbol* m_sym; ///< Ptr to the symbol this declares (non-owning)
|
||||
bool m_isparam; ///< Is this a parameter?
|
||||
bool m_isoutput; ///< Is this an output parameter?
|
||||
bool m_ismetadata; ///< Is this declaration a piece of metadata?
|
||||
@@ -529,6 +529,7 @@ private:
|
||||
// specific initializers.
|
||||
typedef std::pair<ustring, ASTNode*> NamedInit;
|
||||
std::vector<NamedInit> m_struct_field_inits;
|
||||
std::unique_ptr<Symbol> m_sym_owned; // if we own the symbol
|
||||
};
|
||||
|
||||
|
||||
@@ -949,7 +950,7 @@ private:
|
||||
/// return false and call an appropriate error().
|
||||
bool typecheck_printf_args(const char* format, ASTNode* arg);
|
||||
|
||||
/// Handle "funcion calls" that are really struct ctrs.
|
||||
/// Handle "function calls" that are really struct ctrs.
|
||||
TypeSpec typecheck_struct_constructor();
|
||||
|
||||
/// Is the argument number 'arg' read by the op?
|
||||
|
||||
+58
-59
@@ -101,7 +101,7 @@ OSLCompilerImpl::insert_code(int opnum, const char* opname, size_t nargs,
|
||||
Symbol*
|
||||
OSLCompilerImpl::make_temporary(const TypeSpec& type)
|
||||
{
|
||||
ustring name = ustring::sprintf("$tmp%d", ++m_next_temp);
|
||||
ustring name = ustring::fmtformat("$tmp{}", ++m_next_temp);
|
||||
Symbol* s = new Symbol(name, type, SymTypeTemp);
|
||||
symtab().insert(s);
|
||||
|
||||
@@ -131,14 +131,15 @@ OSLCompilerImpl::add_struct_fields(StructSpec* structspec, ustring basename,
|
||||
// arraylen is the length of the array of the surrounding data type
|
||||
for (int i = 0; i < (int)structspec->numfields(); ++i) {
|
||||
const StructSpec::FieldSpec& field(structspec->field(i));
|
||||
ustring fieldname = ustring::sprintf("%s.%s", basename, field.name);
|
||||
ustring fieldname = ustring::fmtformat("{}.{}", basename, field.name);
|
||||
TypeSpec type = field.type;
|
||||
int arr = type.arraylength();
|
||||
if (arr && arraylen) {
|
||||
errorf(node ? node->sourcefile() : ustring(),
|
||||
node ? node->sourceline() : 1,
|
||||
"Nested structs with >1 levels of arrays are not allowed: %s",
|
||||
structspec->name());
|
||||
errorfmt(
|
||||
node ? node->sourcefile() : ustring(),
|
||||
node ? node->sourceline() : 1,
|
||||
"Nested structs with >1 levels of arrays are not allowed: {}",
|
||||
structspec->name());
|
||||
}
|
||||
if (arraylen || arr) {
|
||||
// Translate an outer array into an inner array
|
||||
@@ -174,7 +175,7 @@ OSLCompilerImpl::make_constant(ustring val)
|
||||
return sym;
|
||||
}
|
||||
// It's not a constant we've added before
|
||||
ustring name = ustring::sprintf("$const%d", ++m_next_const);
|
||||
ustring name = ustring::fmtformat("$const{}", ++m_next_const);
|
||||
ConstantSymbol* s = new ConstantSymbol(name, val);
|
||||
symtab().insert(s);
|
||||
m_const_syms.push_back(s);
|
||||
@@ -193,7 +194,7 @@ OSLCompilerImpl::make_constant(TypeDesc type, const void* val)
|
||||
return sym;
|
||||
}
|
||||
// It's not a constant we've added before
|
||||
ustring name = ustring::sprintf("$const%d", ++m_next_const);
|
||||
ustring name = ustring::fmtformat("$const{}", ++m_next_const);
|
||||
ConstantSymbol* s = new ConstantSymbol(name, type);
|
||||
memcpy(s->dataptr(), val, typesize);
|
||||
symtab().insert(s);
|
||||
@@ -211,7 +212,7 @@ OSLCompilerImpl::make_constant(int val)
|
||||
return sym;
|
||||
}
|
||||
// It's not a constant we've added before
|
||||
ustring name = ustring::sprintf("$const%d", ++m_next_const);
|
||||
ustring name = ustring::fmtformat("$const{}", ++m_next_const);
|
||||
ConstantSymbol* s = new ConstantSymbol(name, val);
|
||||
symtab().insert(s);
|
||||
m_const_syms.push_back(s);
|
||||
@@ -228,7 +229,7 @@ OSLCompilerImpl::make_constant(float val)
|
||||
return sym;
|
||||
}
|
||||
// It's not a constant we've added before
|
||||
ustring name = ustring::sprintf("$const%d", ++m_next_const);
|
||||
ustring name = ustring::fmtformat("$const{}", ++m_next_const);
|
||||
ConstantSymbol* s = new ConstantSymbol(name, val);
|
||||
symtab().insert(s);
|
||||
m_const_syms.push_back(s);
|
||||
@@ -246,7 +247,7 @@ OSLCompilerImpl::make_constant(TypeDesc type, float x, float y, float z)
|
||||
return sym;
|
||||
}
|
||||
// It's not a constant we've added before
|
||||
ustring name = ustring::sprintf("$const%d", ++m_next_const);
|
||||
ustring name = ustring::fmtformat("$const{}", ++m_next_const);
|
||||
ConstantSymbol* s = new ConstantSymbol(name, type, x, y, z);
|
||||
symtab().insert(s);
|
||||
m_const_syms.push_back(s);
|
||||
@@ -453,9 +454,9 @@ ASTcompound_initializer::codegen(Symbol* sym)
|
||||
return sym;
|
||||
}
|
||||
|
||||
errorf("Possible compiler bug: compound_initializer codegen does not "
|
||||
"know how to handle type %s",
|
||||
typespec());
|
||||
errorfmt("Possible compiler bug: compound_initializer codegen does not "
|
||||
"know how to handle type {}",
|
||||
typespec());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -549,8 +550,8 @@ ASTNode::codegen_assign_struct(StructSpec* structspec, ustring dstsym,
|
||||
// struct within struct -- recurse
|
||||
ustring fieldname(structspec->field(i).name);
|
||||
codegen_assign_struct(fieldtype.structspec(),
|
||||
ustring::sprintf("%s.%s", dstsym, fieldname),
|
||||
ustring::sprintf("%s.%s", srcsym, fieldname),
|
||||
ustring::fmtformat("{}.{}", dstsym, fieldname),
|
||||
ustring::fmtformat("{}.{}", srcsym, fieldname),
|
||||
arrayindex, copywholearrays, 0, paraminit);
|
||||
continue;
|
||||
}
|
||||
@@ -559,8 +560,8 @@ ASTNode::codegen_assign_struct(StructSpec* structspec, ustring dstsym,
|
||||
// struct array within struct -- loop over indices and recurse
|
||||
OSL_ASSERT(!arrayindex && "two levels of arrays not allowed");
|
||||
ustring fieldname(structspec->field(i).name);
|
||||
ustring dstfield = ustring::sprintf("%s.%s", dstsym, fieldname);
|
||||
ustring srcfield = ustring::sprintf("%s.%s", srcsym, fieldname);
|
||||
ustring dstfield = ustring::fmtformat("{}.{}", dstsym, fieldname);
|
||||
ustring srcfield = ustring::fmtformat("{}.{}", srcsym, fieldname);
|
||||
for (int i = 0; i < fieldtype.arraylength(); ++i) {
|
||||
codegen_assign_struct(fieldtype.structspec(), dstfield,
|
||||
srcfield, m_compiler->make_constant(i),
|
||||
@@ -631,16 +632,16 @@ ASTNode::one_default_literal(const Symbol* sym, ASTNode* init, std::string& out,
|
||||
completed = false;
|
||||
} else if (type.is_int()) {
|
||||
if (islit && lit->typespec().is_int())
|
||||
out += Strutil::sprintf("%d", lit->intval());
|
||||
out += fmtformat("{}", lit->intval());
|
||||
else {
|
||||
out += "0"; // FIXME?
|
||||
completed = false;
|
||||
}
|
||||
} else if (type.is_float()) {
|
||||
if (islit && lit->typespec().is_int())
|
||||
out += Strutil::sprintf("%d", lit->intval());
|
||||
out += fmtformat("{}", lit->intval());
|
||||
else if (islit && lit->typespec().is_float())
|
||||
out += Strutil::sprintf("%.9g", lit->floatval());
|
||||
out += fmtformat("{:.9g}", lit->floatval());
|
||||
else {
|
||||
out += "0"; // FIXME?
|
||||
completed = false;
|
||||
@@ -648,10 +649,10 @@ ASTNode::one_default_literal(const Symbol* sym, ASTNode* init, std::string& out,
|
||||
} else if (type.is_triple()) {
|
||||
if (islit && lit->typespec().is_int()) {
|
||||
float f = lit->intval();
|
||||
out += Strutil::sprintf("%.9g%s%.9g%s%.9g", f, sep, f, sep, f);
|
||||
out += fmtformat("{:.9g}{}{:.9g}{}{:.9g}", f, sep, f, sep, f);
|
||||
} else if (islit && lit->typespec().is_float()) {
|
||||
float f = lit->floatval();
|
||||
out += Strutil::sprintf("%.9g%s%.9g%s%.9g", f, sep, f, sep, f);
|
||||
out += fmtformat("{:.9g}{}{:.9g}{}{:.9g}", f, sep, f, sep, f);
|
||||
} else if (init && init->typespec() == type
|
||||
&& (init->nodetype() == ASTNode::type_constructor_node
|
||||
|| (init->nodetype() == ASTNode::compound_initializer_node
|
||||
@@ -681,26 +682,26 @@ ASTNode::one_default_literal(const Symbol* sym, ASTNode* init, std::string& out,
|
||||
}
|
||||
}
|
||||
if (nargs == 1)
|
||||
out += Strutil::sprintf("%.9g%s%.9g%s%.9g", f[0], sep, f[0],
|
||||
sep, f[0]);
|
||||
out += fmtformat("{:.9g}{}{:.9g}{}{:.9g}", f[0], sep, f[0], sep,
|
||||
f[0]);
|
||||
else
|
||||
out += Strutil::sprintf("%.9g%s%.9g%s%.9g", f[0], sep, f[1],
|
||||
sep, f[2]);
|
||||
out += fmtformat("{:.9g}{}{:.9g}{}{:.9g}", f[0], sep, f[1], sep,
|
||||
f[2]);
|
||||
} else {
|
||||
out += Strutil::sprintf("0%s0%s0", sep, sep);
|
||||
out += fmtformat("0{}0{}0", sep, sep);
|
||||
completed = false;
|
||||
}
|
||||
} else if (type.is_matrix()) {
|
||||
if (islit && lit->typespec().is_int()) {
|
||||
float f = lit->intval();
|
||||
for (int c = 0; c < 16; ++c)
|
||||
out += Strutil::sprintf("%.9g%s", (c / 4) == (c % 4) ? f : 0.0f,
|
||||
c < 15 ? sep.c_str() : "");
|
||||
out += fmtformat("{:.9g}{}", (c / 4) == (c % 4) ? f : 0.0f,
|
||||
c < 15 ? sep : "");
|
||||
} else if (islit && lit->typespec().is_float()) {
|
||||
float f = lit->floatval();
|
||||
for (int c = 0; c < 16; ++c)
|
||||
out += Strutil::sprintf("%.9g%s", (c / 4) == (c % 4) ? f : 0.0f,
|
||||
c < 15 ? sep.c_str() : "");
|
||||
out += fmtformat("{:.9g}{}", (c / 4) == (c % 4) ? f : 0.0f,
|
||||
c < 15 ? sep : "");
|
||||
} else if (init && init->typespec() == type
|
||||
&& init->nodetype() == ASTNode::type_constructor_node) {
|
||||
ASTtype_constructor* ctr = (ASTtype_constructor*)init;
|
||||
@@ -728,23 +729,21 @@ ASTNode::one_default_literal(const Symbol* sym, ASTNode* init, std::string& out,
|
||||
}
|
||||
if (nargs == 1) {
|
||||
for (int c = 0; c < 16; ++c)
|
||||
out += Strutil::sprintf("%.9g%s",
|
||||
(c / 4) == (c % 4) ? f[0] : 0.0f,
|
||||
c < 15 ? sep.c_str() : "");
|
||||
out += fmtformat("{:.9g}{}",
|
||||
(c / 4) == (c % 4) ? f[0] : 0.0f,
|
||||
c < 15 ? sep : "");
|
||||
} else {
|
||||
for (int c = 0; c < 16; ++c)
|
||||
out += Strutil::sprintf("%.9g%s", f[c],
|
||||
c < 15 ? sep.c_str() : "");
|
||||
out += fmtformat("{:.9g}{}", f[c], c < 15 ? sep : "");
|
||||
}
|
||||
} else {
|
||||
for (int c = 0; c < 16; ++c)
|
||||
out += Strutil::sprintf("0%s", c < 15 ? sep.c_str() : "");
|
||||
out += fmtformat("0{}", c < 15 ? sep : "");
|
||||
completed = false;
|
||||
}
|
||||
} else if (type.is_string()) {
|
||||
if (islit && lit->typespec().is_string())
|
||||
out += Strutil::sprintf("\"%s\"",
|
||||
Strutil::escape_chars(lit->strval()));
|
||||
out += fmtformat("\"{}\"", Strutil::escape_chars(lit->strval()));
|
||||
else {
|
||||
out += "\"\""; // FIXME?
|
||||
completed = false;
|
||||
@@ -903,8 +902,8 @@ ASTNode::codegen_initlist(ref init, TypeSpec type, Symbol* sym)
|
||||
for (int i = 0; init && i < structspec->numfields();
|
||||
init = init->next(), ++i) {
|
||||
const StructSpec::FieldSpec& field(structspec->field(i));
|
||||
ustring fieldname = ustring::sprintf("%s.%s", sym->mangled(),
|
||||
field.name);
|
||||
ustring fieldname = ustring::fmtformat("{}.{}", sym->mangled(),
|
||||
field.name);
|
||||
Symbol* fieldsym = m_compiler->symtab().find_exact(fieldname);
|
||||
if (paraminit) {
|
||||
OSL_DASSERT(nodetype() == variable_declaration_node);
|
||||
@@ -919,10 +918,10 @@ ASTNode::codegen_initlist(ref init, TypeSpec type, Symbol* sym)
|
||||
}
|
||||
|
||||
if (paraminit) {
|
||||
// Warn early about struct array paramters.
|
||||
// Warn early about struct array parameters.
|
||||
// Handling this will likely need changes to oso format.
|
||||
if (type.is_structure_array()) {
|
||||
errorf("array of struct are not allowed as parameters");
|
||||
errorfmt("array of struct are not allowed as parameters");
|
||||
return;
|
||||
}
|
||||
// For parameter initialization, don't really generate ops if it
|
||||
@@ -1073,8 +1072,8 @@ ASTNode::codegen_struct_initializers(ref init, Symbol* sym, bool is_constructor,
|
||||
init = init->next(), ++i) {
|
||||
// Structure element -- assign to the i-th member field
|
||||
const StructSpec::FieldSpec& field(structspec->field(i));
|
||||
ustring fieldname = ustring::sprintf("%s.%s", sym->mangled(),
|
||||
field.name);
|
||||
ustring fieldname = ustring::fmtformat("{}.{}", sym->mangled(),
|
||||
field.name);
|
||||
Symbol* fieldsym = m_compiler->symtab().find_exact(fieldname);
|
||||
if (fieldsym->typespec().is_structure_based()
|
||||
&& (init->nodetype() == type_constructor_node
|
||||
@@ -1240,8 +1239,8 @@ ASTindex::codegen_copy_struct_array_element(StructSpec* structspec,
|
||||
// struct within struct -- recurse!
|
||||
codegen_copy_struct_array_element(
|
||||
type.structspec(),
|
||||
ustring::sprintf("%s.%s", destname, field.name),
|
||||
ustring::sprintf("%s.%s", srcname, field.name), index);
|
||||
ustring::fmtformat("{}.{}", destname, field.name),
|
||||
ustring::fmtformat("{}.{}", srcname, field.name), index);
|
||||
} else {
|
||||
OSL_ASSERT(!type.is_array());
|
||||
Symbol *dfield, *sfield;
|
||||
@@ -1464,7 +1463,7 @@ ASTunary_expression::codegen(Symbol* dest)
|
||||
if (m_function_overload) {
|
||||
// A little crazy, but we temporarily construct an ASTfunction_call
|
||||
// in order to codegen this overloaded operator.
|
||||
ustring funcname = ustring::sprintf("__operator__%s__", opword());
|
||||
ustring funcname = ustring::fmtformat("__operator__{}__", opword());
|
||||
ASTfunction_call fc(m_compiler, funcname, expr().get(),
|
||||
m_function_overload);
|
||||
fc.typecheck(typespec());
|
||||
@@ -1512,10 +1511,10 @@ ASTbinary_expression::codegen(Symbol* dest)
|
||||
// in order to codegen this overloaded operator. Slightly tricky
|
||||
// is that we need to concatenate our left and right arguments into
|
||||
// an arg list.
|
||||
ustring funcname = ustring::sprintf("__operator__%s__", opword());
|
||||
ustring funcname = ustring::fmtformat("__operator__{}__", opword());
|
||||
if (left()->nextptr() || right()->nextptr()) {
|
||||
errorf("Overloaded %s cannot be passed arguments %s and %s",
|
||||
funcname, left()->nodetypename(), right()->nodetypename());
|
||||
errorfmt("Overloaded %s cannot be passed arguments {} and {}",
|
||||
funcname, left()->nodetypename(), right()->nodetypename());
|
||||
return dest;
|
||||
}
|
||||
ref args = left();
|
||||
@@ -1995,10 +1994,10 @@ ASTfunction_call::codegen_arg(SymbolPtrVec& argdest, SymbolPtrVec& index1,
|
||||
&& !equivalent(origarg->typespec(), form->typespec())
|
||||
&& form->nodetype() == variable_declaration_node
|
||||
&& ((ASTvariable_declaration*)form)->is_output()) {
|
||||
errorf("Cannot pass '%s %s' as argument %d to %s\n\t"
|
||||
"because it is an output parameter that must be a %s",
|
||||
origarg->typespec(), origarg->name(), argnum + 1,
|
||||
user_function()->func()->name(), form->typespec());
|
||||
errorfmt("Cannot pass '{} {}' as argument {} to {}\n\t"
|
||||
"because it is an output parameter that must be a %s",
|
||||
origarg->typespec(), origarg->name(), argnum + 1,
|
||||
user_function()->func()->name(), form->typespec());
|
||||
}
|
||||
}
|
||||
if (thisarg) {
|
||||
@@ -2007,7 +2006,7 @@ ASTfunction_call::codegen_arg(SymbolPtrVec& argdest, SymbolPtrVec& index1,
|
||||
index2.push_back(ind2);
|
||||
index3.push_back(ind3);
|
||||
} else
|
||||
arg->errorf("Invalid argument to function");
|
||||
arg->errorfmt("Invalid argument to function");
|
||||
}
|
||||
|
||||
|
||||
@@ -2023,8 +2022,8 @@ ASTfunction_call::struct_pair_all_fields(StructSpec* structspec, ustring formal,
|
||||
// struct within struct -- recurse!
|
||||
struct_pair_all_fields(
|
||||
type.structspec(),
|
||||
ustring::sprintf("%s.%s", formal, field.name),
|
||||
ustring::sprintf("%s.%s", actual, field.name), arrayindex);
|
||||
ustring::fmtformat("{}.{}", formal, field.name),
|
||||
ustring::fmtformat("{}.{}", actual, field.name), arrayindex);
|
||||
} else {
|
||||
Symbol *fsym, *asym;
|
||||
m_compiler->struct_field_pair(structspec, fi, formal, actual, fsym,
|
||||
|
||||
+100
-97
@@ -131,7 +131,7 @@ OSLCompilerImpl::preprocess_file(const std::string& filename,
|
||||
// Read file contents into a string
|
||||
std::string instring;
|
||||
if (!OIIO::Filesystem::read_text_file(filename, instring)) {
|
||||
errorf(ustring(filename), 0, "Could not open \"%s\"\n", filename);
|
||||
errorfmt(ustring(filename), 0, "Could not open \"{}\"\n", filename);
|
||||
return false;
|
||||
}
|
||||
return preprocess_buffer(instring, filename, stdoslpath, defines,
|
||||
@@ -148,11 +148,11 @@ OSLCompilerImpl::preprocess_buffer(const std::string& buffer,
|
||||
const std::vector<std::string>& includepaths,
|
||||
std::string& result)
|
||||
{
|
||||
using OIIO::Strutil::fmt::format;
|
||||
std::string instring;
|
||||
if (!stdoslpath.empty()) {
|
||||
instring
|
||||
= OIIO::Strutil::sprintf("#include \"%s\"\n",
|
||||
OIIO::Strutil::escape_chars(stdoslpath));
|
||||
instring = format("#include \"{}\"\n",
|
||||
OIIO::Strutil::escape_chars(stdoslpath));
|
||||
// Note: because we're turning this from a regular string into a
|
||||
// double-quoted string injected into the OSL parse stream, we need
|
||||
// to fully escape any backslashes used in Windows file paths. We
|
||||
@@ -217,14 +217,13 @@ OSLCompilerImpl::preprocess_buffer(const std::string& buffer,
|
||||
|
||||
clang::PreprocessorOptions& preprocOpts = inst.getPreprocessorOpts();
|
||||
preprocOpts.UsePredefines = 0;
|
||||
preprocOpts.addMacroDef(OIIO::Strutil::sprintf("OSL_VERSION_MAJOR=%d",
|
||||
OSL_LIBRARY_VERSION_MAJOR));
|
||||
preprocOpts.addMacroDef(OIIO::Strutil::sprintf("OSL_VERSION_MINOR=%d",
|
||||
OSL_LIBRARY_VERSION_MINOR));
|
||||
preprocOpts.addMacroDef(OIIO::Strutil::sprintf("OSL_VERSION_PATCH=%d",
|
||||
OSL_LIBRARY_VERSION_PATCH));
|
||||
preprocOpts.addMacroDef(
|
||||
OIIO::Strutil::sprintf("OSL_VERSION=%d", OSL_LIBRARY_VERSION_CODE));
|
||||
format("OSL_VERSION_MAJOR={}", OSL_LIBRARY_VERSION_MAJOR));
|
||||
preprocOpts.addMacroDef(
|
||||
format("OSL_VERSION_MINOR={}", OSL_LIBRARY_VERSION_MINOR));
|
||||
preprocOpts.addMacroDef(
|
||||
format("OSL_VERSION_PATCH={}", OSL_LIBRARY_VERSION_PATCH));
|
||||
preprocOpts.addMacroDef(format("OSL_VERSION={}", OSL_LIBRARY_VERSION_CODE));
|
||||
for (auto&& d : defines) {
|
||||
if (d[1] == 'D')
|
||||
preprocOpts.addMacroDef(d.c_str() + 2);
|
||||
@@ -245,7 +244,7 @@ OSLCompilerImpl::preprocess_buffer(const std::string& buffer,
|
||||
while (preproc_errors.size()
|
||||
&& preproc_errors[preproc_errors.size() - 1] == '\n')
|
||||
preproc_errors.erase(preproc_errors.size() - 1);
|
||||
errorf(ustring(), -1, "%s", preproc_errors);
|
||||
errorfmt(ustring(), -1, "{}", preproc_errors);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -342,8 +341,8 @@ find_stdoslpath(const std::vector<std::string>& includepaths)
|
||||
|
||||
// If that doesn't work, look in a bunch of likely places.
|
||||
|
||||
std::string install_loc = OIIO::Strutil::sprintf("%s/stdosl.h",
|
||||
OSL_SHADER_INSTALL_DIR);
|
||||
std::string install_loc
|
||||
= OIIO::Strutil::fmt::format("{}/stdosl.h", OSL_SHADER_INSTALL_DIR);
|
||||
if (OIIO::Filesystem::exists(install_loc))
|
||||
return ustring(install_loc);
|
||||
|
||||
@@ -407,7 +406,7 @@ OSLCompilerImpl::compile(string_view filename,
|
||||
string_view stdoslpath)
|
||||
{
|
||||
if (!OIIO::Filesystem::exists(filename)) {
|
||||
errorf(ustring(), 0, "Input file \"%s\" not found", filename);
|
||||
errorfmt(ustring(), 0, "Input file \"{}\" not found", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -425,7 +424,7 @@ OSLCompilerImpl::compile(string_view filename,
|
||||
stdoslpath = find_stdoslpath(includepaths);
|
||||
}
|
||||
if (stdoslpath.empty() || !OIIO::Filesystem::exists(stdoslpath))
|
||||
warningf(ustring(filename), 0, "Unable to find \"stdosl.h\"");
|
||||
warningfmt(ustring(filename), 0, "Unable to find \"stdosl.h\"");
|
||||
else {
|
||||
// Add the directory of stdosl.h to the include paths
|
||||
includepaths.push_back(OIIO::Filesystem::parent_path(stdoslpath));
|
||||
@@ -445,7 +444,7 @@ OSLCompilerImpl::compile(string_view filename,
|
||||
if (shader())
|
||||
shader()->typecheck();
|
||||
else
|
||||
errorf(ustring(), 0, "No shader function defined");
|
||||
errorfmt(ustring(), 0, "No shader function defined");
|
||||
}
|
||||
|
||||
// Print the parse tree if there were no errors
|
||||
@@ -474,8 +473,8 @@ OSLCompilerImpl::compile(string_view filename,
|
||||
OIIO::ofstream oso_output;
|
||||
OIIO::Filesystem::open(oso_output, m_output_filename);
|
||||
if (!oso_output.good()) {
|
||||
errorf(ustring(), 0, "Could not open \"%s\"",
|
||||
m_output_filename);
|
||||
errorfmt(ustring(), 0, "Could not open \"{}\"",
|
||||
m_output_filename);
|
||||
return false;
|
||||
}
|
||||
OSL_DASSERT(m_osofile == nullptr);
|
||||
@@ -487,8 +486,8 @@ OSLCompilerImpl::compile(string_view filename,
|
||||
|
||||
oso_output.close();
|
||||
if (!oso_output.good()) {
|
||||
errorf(ustring(), 0, "Failed to write to \"%s\"",
|
||||
m_output_filename);
|
||||
errorfmt(ustring(), 0, "Failed to write to \"{}\"",
|
||||
m_output_filename);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -521,7 +520,7 @@ OSLCompilerImpl::compile_buffer(string_view sourcecode, std::string& osobuffer,
|
||||
stdoslpath = find_stdoslpath(includepaths);
|
||||
}
|
||||
if (stdoslpath.empty() || !OIIO::Filesystem::exists(stdoslpath))
|
||||
warningf(ustring(filename), 0, "Unable to find \"stdosl.h\"");
|
||||
warningfmt(ustring(filename), 0, "Unable to find \"stdosl.h\"");
|
||||
|
||||
std::string preprocess_result;
|
||||
if (!preprocess_buffer(sourcecode, filename, stdoslpath, defines,
|
||||
@@ -537,7 +536,7 @@ OSLCompilerImpl::compile_buffer(string_view sourcecode, std::string& osobuffer,
|
||||
if (shader())
|
||||
shader()->typecheck();
|
||||
else
|
||||
errorf(ustring(), 0, "No shader function defined");
|
||||
errorfmt(ustring(), 0, "No shader function defined");
|
||||
}
|
||||
|
||||
// Print the parse tree if there were no errors
|
||||
@@ -591,7 +590,7 @@ OSLCompilerImpl::write_dependency_file(string_view filename)
|
||||
? stdout
|
||||
: OIIO::Filesystem::fopen(m_deps_filename, "w"));
|
||||
if (depfile) {
|
||||
OIIO::Strutil::fprintf(depfile, "%s: %s", target, filename);
|
||||
OSL::print(depfile, "{}: {}", target, filename);
|
||||
for (const auto& dep : m_file_dependencies) {
|
||||
if (OIIO::Strutil::ends_with(dep, "stdosl.h")
|
||||
&& !m_generate_system_deps)
|
||||
@@ -600,14 +599,15 @@ OSLCompilerImpl::write_dependency_file(string_view filename)
|
||||
continue; // skip pseudo files
|
||||
if (dep == filename)
|
||||
continue; // skip this file, since we already put it first
|
||||
OIIO::Strutil::fprintf(depfile, " \\\n %s", dep);
|
||||
OSL::print(depfile, " \\\n {}", dep);
|
||||
}
|
||||
OIIO::Strutil::fprintf(depfile, "\n");
|
||||
OSL::print(depfile, "\n");
|
||||
if (depfile != stdout)
|
||||
fclose(depfile);
|
||||
} else {
|
||||
errorf(ustring(), 0, "Could not open dependency file '%s' for writing",
|
||||
m_deps_filename);
|
||||
errorfmt(ustring(), 0,
|
||||
"Could not open dependency file '{}' for writing",
|
||||
m_deps_filename);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -675,11 +675,11 @@ OSLCompilerImpl::write_oso_metadata(const ASTNode* metanode) const
|
||||
bool ok = metavar->param_default_literals(metasym, metavar->init().get(),
|
||||
pdl, ",");
|
||||
if (ok) {
|
||||
osof("%%meta{%s,%s,%s} ", ts, metasym->name(), pdl);
|
||||
osofmt("%meta{{{},{},{}}} ", ts, metasym->name(), pdl);
|
||||
} else {
|
||||
errorf(metanode->sourcefile(), metanode->sourceline(),
|
||||
"Don't know how to print metadata %s (%s) with node type %s",
|
||||
metasym->name(), ts, metavar->init()->nodetypename());
|
||||
errorfmt(metanode->sourcefile(), metanode->sourceline(),
|
||||
"Don't know how to print metadata {} ({}) with node type {}",
|
||||
metasym->name(), ts, metavar->init()->nodetypename());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -694,18 +694,18 @@ OSLCompilerImpl::write_oso_const_value(const ConstantSymbol* sym) const
|
||||
int nelements = std::max(1, type.arraylen);
|
||||
if (elemtype == TypeDesc::STRING)
|
||||
for (int i = 0; i < nelements; ++i)
|
||||
osof("\"%s\"%s", OIIO::Strutil::escape_chars(sym->get_string(i)),
|
||||
nelements > 1 ? " " : "");
|
||||
osofmt("\"{}\"{}", OIIO::Strutil::escape_chars(sym->get_string(i)),
|
||||
nelements > 1 ? " " : "");
|
||||
else if (elemtype == TypeDesc::INT)
|
||||
for (int i = 0; i < nelements; ++i)
|
||||
osof("%d%s", sym->get_int(i), nelements > 1 ? " " : "");
|
||||
osofmt("{}{}", sym->get_int(i), nelements > 1 ? " " : "");
|
||||
else if (elemtype == TypeDesc::FLOAT)
|
||||
for (int i = 0; i < nelements; ++i)
|
||||
osof("%.9g%s", sym->floatval(i), nelements > 1 ? " " : "");
|
||||
osofmt("{}{}", sym->floatval(i), nelements > 1 ? " " : "");
|
||||
else if (equivalent(elemtype, TypeDesc::TypeVector))
|
||||
for (int i = 0; i < nelements; ++i) {
|
||||
Vec3 v = sym->get_vec3(i);
|
||||
osof("%.9g %.9g %.9g%s", v.x, v.y, v.z, nelements > 1 ? " " : "");
|
||||
osofmt("{} {} {}{}", v.x, v.y, v.z, nelements > 1 ? " " : "");
|
||||
}
|
||||
else {
|
||||
OSL_ASSERT(0 && "Don't know how to output this constant type");
|
||||
@@ -718,8 +718,8 @@ void
|
||||
OSLCompilerImpl::write_oso_symbol(const Symbol* sym)
|
||||
{
|
||||
// symtype / datatype / name
|
||||
osof("%s\t%s\t%s", sym->symtype_shortname(), sym->typespec(),
|
||||
sym->mangled());
|
||||
osofmt("{}\t{}\t{}", sym->symtype_shortname(), sym->typespec(),
|
||||
sym->mangled());
|
||||
|
||||
ASTvariable_declaration* v = NULL;
|
||||
if (sym->node()
|
||||
@@ -730,13 +730,13 @@ OSLCompilerImpl::write_oso_symbol(const Symbol* sym)
|
||||
bool isparam = (sym->symtype() == SymTypeParam
|
||||
|| sym->symtype() == SymTypeOutputParam);
|
||||
if (sym->symtype() == SymTypeConst) {
|
||||
osof("\t");
|
||||
osofmt("\t");
|
||||
write_oso_const_value(static_cast<const ConstantSymbol*>(sym));
|
||||
osof("\t");
|
||||
osofmt("\t");
|
||||
} else if (v && isparam) {
|
||||
std::string out;
|
||||
v->param_default_literals(sym, v->init().get(), out);
|
||||
osof("\t%s\t", out);
|
||||
osofmt("\t{}\t", out);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -749,15 +749,15 @@ OSLCompilerImpl::write_oso_symbol(const Symbol* sym)
|
||||
if (v) {
|
||||
for (ASTNode::ref m = v->meta(); m; m = m->next()) {
|
||||
if (hints++ == 0)
|
||||
osof("\t");
|
||||
osofmt("\t");
|
||||
write_oso_metadata(m.get());
|
||||
}
|
||||
}
|
||||
|
||||
// %read and %write give the range of ops over which a symbol is used.
|
||||
osof("%c%%read{%d,%d} %%write{%d,%d}", hints++ ? ' ' : '\t',
|
||||
sym->firstread(), sym->lastread(), sym->firstwrite(),
|
||||
sym->lastwrite());
|
||||
osofmt("{}%read{{{},{}}} %write{{{},{}}}", hints++ ? ' ' : '\t',
|
||||
sym->firstread(), sym->lastread(), sym->firstwrite(),
|
||||
sym->lastwrite());
|
||||
|
||||
// %struct, %structfields, and %structfieldtypes document the
|
||||
// definition of a structure and which other symbols comprise the
|
||||
@@ -771,28 +771,29 @@ OSLCompilerImpl::write_oso_symbol(const Symbol* sym)
|
||||
fieldlist += structspec->field(i).name.string();
|
||||
signature += code_from_type(structspec->field(i).type);
|
||||
}
|
||||
osof("%c%%struct{\"%s\"} %%structfields{%s} %%structfieldtypes{\"%s\"} %%structnfields{%d}",
|
||||
hints++ ? ' ' : '\t', structspec->mangled(), fieldlist, signature,
|
||||
structspec->numfields());
|
||||
osofmt(
|
||||
"{}%struct{{\"{}\"}} %structfields{{{}}} %structfieldtypes{{\"{}\"}} %structnfields{{{}}}",
|
||||
hints++ ? ' ' : '\t', structspec->mangled(), fieldlist, signature,
|
||||
structspec->numfields());
|
||||
}
|
||||
// %mystruct and %mystructfield document the symbols holding structure
|
||||
// fields, linking them back to the structures they are part of.
|
||||
if (sym->fieldid() >= 0) {
|
||||
ASTvariable_declaration* vd = (ASTvariable_declaration*)sym->node();
|
||||
if (vd)
|
||||
osof("%c%%mystruct{%s} %%mystructfield{%d}", hints++ ? ' ' : '\t',
|
||||
vd->sym()->mangled(), sym->fieldid());
|
||||
osofmt("{}%mystruct{{{}}} %mystructfield{{{}}}",
|
||||
hints++ ? ' ' : '\t', vd->sym()->mangled(), sym->fieldid());
|
||||
}
|
||||
|
||||
// %derivs hint marks symbols that need to carry derivatives
|
||||
if (sym->has_derivs())
|
||||
osof("%c%%derivs", hints++ ? ' ' : '\t');
|
||||
osofmt("{}%derivs", hints++ ? ' ' : '\t');
|
||||
|
||||
// %initexpr hint marks parameters whose default is the result of code
|
||||
// that must be executed (an expression, like =noise(P) or =u), rather
|
||||
// than a true default value that is statically known (like =3.14).
|
||||
if (isparam && sym->has_init_ops())
|
||||
osof("%c%%initexpr", hints++ ? ' ' : '\t');
|
||||
osofmt("{}%initexpr", hints++ ? ' ' : '\t');
|
||||
|
||||
#if 0 // this is recomputed by the runtime optimizer, no need to bloat the .oso with these
|
||||
|
||||
@@ -812,22 +813,22 @@ OSLCompilerImpl::write_oso_symbol(const Symbol* sym)
|
||||
inputdeps.push_back (d);
|
||||
if (inputdeps.size()) {
|
||||
if (hints++ == 0)
|
||||
osof("\t");
|
||||
osof(" %%depends{");
|
||||
osofmt("\t");
|
||||
osofmt(" %depends{{");
|
||||
int deps = 0;
|
||||
for (size_t i = 0; i < inputdeps.size(); ++i) {
|
||||
if (inputdeps[i]->symtype() == SymTypeTemp &&
|
||||
inputdeps[i]->dealias() != inputdeps[i])
|
||||
continue; // Skip aliased temporaries
|
||||
if (deps++)
|
||||
osof(",");
|
||||
osof("%s", inputdeps[i]->mangled());
|
||||
osofmt(",");
|
||||
osofmt("{}", inputdeps[i]->mangled());
|
||||
}
|
||||
osof("}");
|
||||
osofmt("}}");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
osof("\n");
|
||||
osofmt("\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -837,23 +838,23 @@ OSLCompilerImpl::write_oso_file(string_view options,
|
||||
string_view preprocessed_source)
|
||||
{
|
||||
OSL_DASSERT(m_osofile && m_osofile->good());
|
||||
osof("OpenShadingLanguage %d.%02d\n", OSO_FILE_VERSION_MAJOR,
|
||||
OSO_FILE_VERSION_MINOR);
|
||||
osof("# Compiled by oslc %s\n", OSL_LIBRARY_VERSION_STRING);
|
||||
osof("# options: %s\n", options);
|
||||
osofmt("OpenShadingLanguage {}.{:02d}\n", OSO_FILE_VERSION_MAJOR,
|
||||
OSO_FILE_VERSION_MINOR);
|
||||
osofmt("# Compiled by oslc {}\n", OSL_LIBRARY_VERSION_STRING);
|
||||
osofmt("# options: {}\n", options);
|
||||
|
||||
ASTshader_declaration* shaderdecl = shader_decl();
|
||||
osof("%s %s", shaderdecl->shadertypename(), shaderdecl->shadername());
|
||||
osofmt("{} {}", shaderdecl->shadertypename(), shaderdecl->shadername());
|
||||
|
||||
// output global hints and metadata
|
||||
int hints = 0;
|
||||
for (ASTNode::ref m = shaderdecl->metadata(); m; m = m->next()) {
|
||||
if (hints++ == 0)
|
||||
osof("\t");
|
||||
osofmt("\t");
|
||||
write_oso_metadata(m.get());
|
||||
}
|
||||
|
||||
osof("\n");
|
||||
osofmt("\n");
|
||||
|
||||
// Output params, so they are first
|
||||
for (auto&& s : symtab()) {
|
||||
@@ -877,7 +878,7 @@ OSLCompilerImpl::write_oso_file(string_view options,
|
||||
ustring lastmethod("___uninitialized___");
|
||||
for (auto& op : m_ircode) {
|
||||
if (lastmethod != op.method()) {
|
||||
osof("code %s\n", op.method());
|
||||
osofmt("code {}\n", op.method());
|
||||
lastmethod = op.method();
|
||||
lastfile = ustring();
|
||||
lastline = -1;
|
||||
@@ -887,25 +888,25 @@ OSLCompilerImpl::write_oso_file(string_view options,
|
||||
ustring file = op.sourcefile();
|
||||
int line = op.sourceline();
|
||||
if (file != lastfile || line != lastline)
|
||||
osof("# %s:%d\n# %s\n", file, line,
|
||||
retrieve_source(file, line));
|
||||
osofmt("# {}:{}\n# {}\n", file, line,
|
||||
retrieve_source(file, line));
|
||||
}
|
||||
|
||||
// Op name
|
||||
osof("\t%s", op.opname());
|
||||
osofmt("\t{}", op.opname());
|
||||
|
||||
// Register arguments
|
||||
if (op.nargs())
|
||||
osof(op.opname().length() < 8 ? "\t\t" : "\t");
|
||||
osofmt(op.opname().length() < 8 ? "\t\t" : "\t");
|
||||
for (int i = 0; i < op.nargs(); ++i) {
|
||||
int arg = op.firstarg() + i;
|
||||
osof("%s ", m_opargs[arg]->dealias()->mangled());
|
||||
osofmt("{} ", m_opargs[arg]->dealias()->mangled());
|
||||
}
|
||||
|
||||
// Jump targets
|
||||
for (size_t i = 0; i < Opcode::max_jumps; ++i)
|
||||
if (op.jump(i) >= 0)
|
||||
osof("%d ", op.jump(i));
|
||||
osofmt("{} ", op.jump(i));
|
||||
|
||||
//
|
||||
// Opcode Hints
|
||||
@@ -919,55 +920,56 @@ OSLCompilerImpl::write_oso_file(string_view options,
|
||||
if (!op.sourcefile().empty()) {
|
||||
if (op.sourcefile() != lastfile) {
|
||||
lastfile = op.sourcefile();
|
||||
osof("%c%%filename{\"%s\"}", firsthint ? '\t' : ' ', lastfile);
|
||||
osofmt("{}%filename{{\"{}\"}}", firsthint ? '\t' : ' ',
|
||||
lastfile);
|
||||
firsthint = false;
|
||||
}
|
||||
if (op.sourceline() != lastline) {
|
||||
lastline = op.sourceline();
|
||||
osof("%c%%line{%d}", firsthint ? '\t' : ' ', lastline);
|
||||
osofmt("{}%line{{{}}}", firsthint ? '\t' : ' ', lastline);
|
||||
firsthint = false;
|
||||
}
|
||||
}
|
||||
|
||||
// %argrw documents which arguments are read, written, or both (rwW).
|
||||
if (op.nargs()) {
|
||||
osof("%c%%argrw{\"", firsthint ? '\t' : ' ');
|
||||
osofmt("{}%argrw{{\"", firsthint ? '\t' : ' ');
|
||||
for (int i = 0; i < op.nargs(); ++i) {
|
||||
if (op.argwrite(i))
|
||||
osof(op.argread(i) ? "W" : "w");
|
||||
osofmt(op.argread(i) ? "W" : "w");
|
||||
else
|
||||
osof(op.argread(i) ? "r" : "-");
|
||||
osofmt(op.argread(i) ? "r" : "-");
|
||||
}
|
||||
osof("\"}");
|
||||
osofmt("\"}}");
|
||||
firsthint = false;
|
||||
}
|
||||
|
||||
// %argderivs documents which arguments have derivs taken of
|
||||
// them by the op.
|
||||
if (op.argtakesderivs_all()) {
|
||||
osof(" %%argderivs{");
|
||||
osofmt(" %argderivs{{");
|
||||
int any = 0;
|
||||
for (int i = 0; i < op.nargs(); ++i)
|
||||
if (op.argtakesderivs(i)) {
|
||||
if (any++)
|
||||
osof(",");
|
||||
osof("%d", i);
|
||||
osofmt(",");
|
||||
osofmt("{}", i);
|
||||
}
|
||||
osof("}");
|
||||
osofmt("}}");
|
||||
firsthint = false;
|
||||
}
|
||||
|
||||
osof("\n");
|
||||
osofmt("\n");
|
||||
}
|
||||
|
||||
// If no code, still need a code marker
|
||||
if (lastmethod != main_method_name())
|
||||
osof("code %s\n", main_method_name());
|
||||
osofmt("code {}\n", main_method_name());
|
||||
|
||||
osof("\tend\n");
|
||||
osofmt("\tend\n");
|
||||
|
||||
if (m_embed_source)
|
||||
osof("%%preprocessed_source\n%s\n", preprocessed_source);
|
||||
osofmt("%preprocessed_source\n{}\n", preprocessed_source);
|
||||
|
||||
m_osofile = NULL;
|
||||
}
|
||||
@@ -1071,7 +1073,8 @@ const char*
|
||||
OSLCompilerImpl::type_c_str(const TypeSpec& type) const
|
||||
{
|
||||
if (type.is_structure())
|
||||
return ustring::sprintf("struct %s", type.structspec()->name()).c_str();
|
||||
return ustring::fmtformat("struct {}", type.structspec()->name())
|
||||
.c_str();
|
||||
else
|
||||
return type.c_str();
|
||||
}
|
||||
@@ -1092,8 +1095,8 @@ OSLCompilerImpl::struct_field_pair(Symbol* sym1, Symbol* sym2, int fieldnum,
|
||||
const StructSpec::FieldSpec& field(structspec->field(fieldnum));
|
||||
// Construct mangled names that describe the symbols for the
|
||||
// individual fields
|
||||
ustring name1 = ustring::sprintf("%s.%s", sym1->mangled(), field.name);
|
||||
ustring name2 = ustring::sprintf("%s.%s", sym2->mangled(), field.name);
|
||||
ustring name1 = ustring::fmtformat("{}.{}", sym1->mangled(), field.name);
|
||||
ustring name2 = ustring::fmtformat("{}.{}", sym2->mangled(), field.name);
|
||||
// Retrieve the symbols
|
||||
field1 = symtab().find_exact(name1);
|
||||
field2 = symtab().find_exact(name2);
|
||||
@@ -1109,8 +1112,8 @@ OSLCompilerImpl::struct_field_pair(const StructSpec* structspec, int fieldnum,
|
||||
{
|
||||
// Find the FieldSpec for the field we are interested in
|
||||
const StructSpec::FieldSpec& field(structspec->field(fieldnum));
|
||||
ustring name1 = ustring::sprintf("%s.%s", sym1, field.name);
|
||||
ustring name2 = ustring::sprintf("%s.%s", sym2, field.name);
|
||||
ustring name1 = ustring::fmtformat("{}.{}", sym1, field.name);
|
||||
ustring name2 = ustring::fmtformat("{}.{}", sym2, field.name);
|
||||
// Retrieve the symbols
|
||||
field1 = symtab().find_exact(name1);
|
||||
field2 = symtab().find_exact(name2);
|
||||
@@ -1128,15 +1131,15 @@ OSLCompilerImpl::check_write_legality(const Opcode& op, int opnum,
|
||||
{
|
||||
// We can never write to constant symbols
|
||||
if (sym->symtype() == SymTypeConst) {
|
||||
errorf(op.sourcefile(), op.sourceline(),
|
||||
"Attempted to write to a constant value");
|
||||
errorfmt(op.sourcefile(), op.sourceline(),
|
||||
"Attempted to write to a constant value");
|
||||
}
|
||||
|
||||
// Params can only write if it's part of their initialization
|
||||
if (sym->symtype() == SymTypeParam
|
||||
&& (opnum < sym->initbegin() || opnum >= sym->initend())) {
|
||||
errorf(op.sourcefile(), op.sourceline(),
|
||||
"cannot write to non-output parameter \"%s\"", sym->name());
|
||||
errorfmt(op.sourcefile(), op.sourceline(),
|
||||
"cannot write to non-output parameter \"{}\"", sym->name());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1302,7 +1305,7 @@ OSLCompilerImpl::track_variable_dependencies()
|
||||
// This naivite will never miss a dependency, but it may
|
||||
// overestimate dependencies. (Hence we call this "conservative"
|
||||
// rather than "wrong.") We deem this acceptable for now, since
|
||||
// it's so much easer to implement the conservative dependency
|
||||
// it's so much easier to implement the conservative dependency
|
||||
// analysis, and it's not yet clear that getting it closer to
|
||||
// optimal will have any performance impact on final shaders. Also
|
||||
// because this is probably no worse than the "dependency slop" that
|
||||
|
||||
@@ -77,69 +77,69 @@ public:
|
||||
|
||||
/// Error reporting
|
||||
template<typename... Args>
|
||||
void errorf(ustring filename, int line, const char* format,
|
||||
const Args&... args) const
|
||||
void errorfmt(ustring filename, int line, const char* format,
|
||||
const Args&... args) const
|
||||
{
|
||||
OSL_DASSERT(format && format[0]);
|
||||
std::string msg = OIIO::Strutil::sprintf(format, args...);
|
||||
std::string msg = OIIO::Strutil::fmt::format(format, args...);
|
||||
if (msg.size() && msg.back() == '\n') // trim extra newline
|
||||
msg.pop_back();
|
||||
if (filename.size())
|
||||
m_errhandler->errorf("%s:%d: error: %s", filename, line, msg);
|
||||
m_errhandler->errorfmt("{}:{}: error: {}", filename, line, msg);
|
||||
else
|
||||
m_errhandler->errorf("error: %s", msg);
|
||||
m_errhandler->errorfmt("error: {}", msg);
|
||||
m_err = true;
|
||||
}
|
||||
|
||||
/// Warning reporting
|
||||
template<typename... Args>
|
||||
void warningf(ustring filename, int line, const char* format,
|
||||
const Args&... args) const
|
||||
void warningfmt(ustring filename, int line, const char* format,
|
||||
const Args&... args) const
|
||||
{
|
||||
OSL_DASSERT(format && format[0]);
|
||||
if (nowarn(filename, line))
|
||||
return; // skip if the filename/line is on the nowarn list
|
||||
std::string msg = OIIO::Strutil::sprintf(format, args...);
|
||||
std::string msg = OIIO::Strutil::fmt::format(format, args...);
|
||||
if (msg.size() && msg.back() == '\n') // trim extra newline
|
||||
msg.pop_back();
|
||||
if (m_err_on_warning) {
|
||||
errorf(filename, line, "%s", msg);
|
||||
errorfmt(filename, line, "{}", msg);
|
||||
return;
|
||||
}
|
||||
if (filename.size())
|
||||
m_errhandler->warningf("%s:%d: warning: %s", filename, line, msg);
|
||||
m_errhandler->warningfmt("{}:{}: warning: {}", filename, line, msg);
|
||||
else
|
||||
m_errhandler->warningf("warning: %s", msg);
|
||||
m_errhandler->warningfmt("warning: {}", msg);
|
||||
}
|
||||
|
||||
/// Info reporting
|
||||
template<typename... Args>
|
||||
void infof(ustring filename, int line, const char* format,
|
||||
const Args&... args) const
|
||||
void infofmt(ustring filename, int line, const char* format,
|
||||
const Args&... args) const
|
||||
{
|
||||
OSL_DASSERT(format && format[0]);
|
||||
std::string msg = OIIO::Strutil::sprintf(format, args...);
|
||||
std::string msg = OIIO::Strutil::fmt::format(format, args...);
|
||||
if (msg.size() && msg.back() == '\n') // trim extra newline
|
||||
msg.pop_back();
|
||||
if (filename.size())
|
||||
m_errhandler->infof("%s:%d: info: %s", filename, line, msg);
|
||||
m_errhandler->infofmt("{}:{}: info: {}", filename, line, msg);
|
||||
else
|
||||
m_errhandler->infof("info: %s", msg);
|
||||
m_errhandler->infofmt("info: {}", msg);
|
||||
}
|
||||
|
||||
/// message reporting
|
||||
template<typename... Args>
|
||||
void messagef(ustring filename, int line, const char* format,
|
||||
const Args&... args) const
|
||||
void messagefmt(ustring filename, int line, const char* format,
|
||||
const Args&... args) const
|
||||
{
|
||||
OSL_DASSERT(format && format[0]);
|
||||
std::string msg = OIIO::Strutil::sprintf(format, args...);
|
||||
std::string msg = OIIO::Strutil::fmt::format(format, args...);
|
||||
if (msg.size() && msg.back() == '\n') // trim extra newline
|
||||
msg.pop_back();
|
||||
if (filename.size())
|
||||
m_errhandler->messagef("%s:%d: %s", filename, line, msg);
|
||||
m_errhandler->messagefmt("{}:{}: {}", filename, line, msg);
|
||||
else
|
||||
m_errhandler->messagef("%s", msg);
|
||||
m_errhandler->messagefmt("{}", msg);
|
||||
}
|
||||
|
||||
/// Have we hit an error?
|
||||
@@ -390,10 +390,11 @@ private:
|
||||
void write_oso_metadata(const ASTNode* metanode) const;
|
||||
void write_dependency_file(string_view filename);
|
||||
|
||||
// Output text to the osofile, using std::format formatting conventions.
|
||||
template<typename... Args>
|
||||
inline void osof(const char* fmt, const Args&... args) const
|
||||
inline void osofmt(const char* fmt, const Args&... args) const
|
||||
{
|
||||
(*m_osofile) << OIIO::Strutil::sprintf(fmt, args...);
|
||||
fmt::print(*m_osofile, fmt, args...);
|
||||
}
|
||||
|
||||
void track_variable_lifetimes()
|
||||
@@ -489,7 +490,7 @@ private:
|
||||
int m_main_method_start; ///< Instruction where 'main' starts
|
||||
bool m_declaring_shader_formals; ///< Are we declaring shader formals?
|
||||
std::set<std::pair<ustring, int>> m_nowarn_lines; ///< Lines for 'nowarn'
|
||||
typedef std::unordered_map<ustring, std::string, ustringHash> FCMap;
|
||||
typedef std::unordered_map<ustring, std::string> FCMap;
|
||||
FCMap m_filecontents_map; ///< Contents of source files we've seen
|
||||
ustring m_last_sourcefile; ///< Last filename for retrieve_source
|
||||
std::string* m_last_filecontents = nullptr; //< Last file contents
|
||||
|
||||
+53
-49
@@ -28,6 +28,10 @@
|
||||
#pragma clang diagnostic ignored "-Wparentheses-equality"
|
||||
#endif
|
||||
|
||||
#if (OSL_CLANG_VERSION >= 150000) || (OSL_INTEL_CLANG_VERSION >= 140000)
|
||||
#pragma clang diagnostic ignored "-Wunused-but-set-variable"
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC visibility push(hidden)
|
||||
#endif
|
||||
@@ -248,11 +252,11 @@ formal_param
|
||||
// Grab the current declaration type, modify it to be array
|
||||
TypeSpec t = oslcompiler->current_typespec();
|
||||
if (! t.is_structure() && ! t.is_triple() && ! t.is_matrix())
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Can't use '= {...}' initializer "
|
||||
"except with arrays, structs, vectors, "
|
||||
"or matrix (%s)", $3);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Can't use '= {{...}}' initializer "
|
||||
"except with arrays, structs, vectors, "
|
||||
"or matrix ({})", $3);
|
||||
auto var = new ASTvariable_declaration (oslcompiler, t,
|
||||
ustring($3), $4 /*init*/,
|
||||
oslcompiler->declaring_shader_formals() /*isparam*/,
|
||||
@@ -294,9 +298,9 @@ metadatum
|
||||
TypeDesc simple = osllextype ($1);
|
||||
simple.arraylen = $3;
|
||||
if (simple.arraylen < 1)
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Invalid array length for %s", $2);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Invalid array length for {}", $2);
|
||||
TypeSpec t (simple, false);
|
||||
auto var = new ASTvariable_declaration (oslcompiler, t,
|
||||
ustring ($2), $4, false,
|
||||
@@ -338,13 +342,13 @@ struct_declaration
|
||||
ustring name ($2);
|
||||
Symbol *s = oslcompiler->symtab().clash (name);
|
||||
if (s) {
|
||||
oslcompiler->errorf(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"\"%s\" already declared in this scope", name);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"\"{}\" already declared in this scope", name);
|
||||
// FIXME -- print the file and line of the other definition
|
||||
}
|
||||
if (OIIO::Strutil::starts_with (name, "___")) {
|
||||
oslcompiler->errorf(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"\"%s\" : sorry, can't start with three underscores", name);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"\"{}\" : sorry, can't start with three underscores", name);
|
||||
}
|
||||
oslcompiler->symtab().new_struct (name);
|
||||
}
|
||||
@@ -375,10 +379,10 @@ typed_field
|
||||
TypeSpec t = oslcompiler->current_typespec();
|
||||
StructSpec *s = oslcompiler->symtab().current_struct();
|
||||
if (s->lookup_field (name) >= 0)
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Field \"%s\" already exists in struct \"%s\"",
|
||||
name, s->name());
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Field \"{}\" already exists in struct \"{}\"",
|
||||
name, s->name());
|
||||
else
|
||||
oslcompiler->symtab().add_struct_field (t, name);
|
||||
$$ = 0;
|
||||
@@ -390,15 +394,15 @@ typed_field
|
||||
TypeSpec t = oslcompiler->current_typespec();
|
||||
t.make_array ($2);
|
||||
if (t.arraylength() < 1)
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Invalid array length for %s", name);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Invalid array length for {}", name);
|
||||
StructSpec *s = oslcompiler->symtab().current_struct();
|
||||
if (s->lookup_field (name) >= 0)
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Field \"%s\" already exists in struct \"%s\"",
|
||||
name, s->name());
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Field \"{}\" already exists in struct \"{}\"",
|
||||
name, s->name());
|
||||
else
|
||||
oslcompiler->symtab().add_struct_field (t, name);
|
||||
$$ = 0;
|
||||
@@ -434,9 +438,9 @@ def_expression
|
||||
TypeSpec t = oslcompiler->current_typespec();
|
||||
t.make_array ($2);
|
||||
if ($2 < 1)
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Invalid array length for %s", $1);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Invalid array length for {}", $1);
|
||||
$$ = new ASTvariable_declaration (oslcompiler, t,
|
||||
ustring($1), $3, false, false, false,
|
||||
true /* initlist */, @1.first_line);
|
||||
@@ -445,11 +449,11 @@ def_expression
|
||||
{
|
||||
TypeSpec t = oslcompiler->current_typespec();
|
||||
if (! t.is_structure() && ! t.is_triple() && ! t.is_matrix())
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Can't use '= {...}' initializer "
|
||||
"except with arrays, struct, vectors, "
|
||||
"or matrix (%s)", $1);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Can't use '= {{...}}' initializer "
|
||||
"except with arrays, struct, vectors, "
|
||||
"or matrix ({})", $1);
|
||||
$$ = new ASTvariable_declaration (oslcompiler, t,
|
||||
ustring($1), $2, false, false, false,
|
||||
true /* initlist */, @1.first_line);
|
||||
@@ -483,10 +487,10 @@ compound_initializer
|
||||
| '{' '}'
|
||||
{
|
||||
if (!oslcompiler->declaring_shader_formals())
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Empty compound initializers '{ }' "
|
||||
"only allowed for shader parameters.");
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Empty compound initializers '{{ }}' "
|
||||
"only allowed for shader parameters.");
|
||||
$$ = new ASTcompound_initializer (oslcompiler, nullptr);
|
||||
$$->sourceline (@1.first_line);
|
||||
}
|
||||
@@ -566,9 +570,9 @@ arrayspec
|
||||
: '[' INT_LITERAL ']'
|
||||
{
|
||||
if ($2 < 1)
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Invalid array length (%d)", $2);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Invalid array length ({})", $2);
|
||||
$$ = $2;
|
||||
}
|
||||
| '[' ']' { $$ = -1; }
|
||||
@@ -594,9 +598,9 @@ typespec
|
||||
oslcompiler->current_typespec (TypeSpec ("", s->typespec().structure()));
|
||||
else {
|
||||
oslcompiler->current_typespec (TypeSpec (TypeDesc::UNKNOWN));
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Unknown struct name: %s", $1);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Unknown struct name: {}", $1);
|
||||
}
|
||||
$$ = 0;
|
||||
}
|
||||
@@ -635,9 +639,9 @@ typespec_or_shadertype
|
||||
oslcompiler->current_typespec (TypeSpec ("", s->typespec().structure()));
|
||||
else {
|
||||
oslcompiler->current_typespec (TypeSpec (TypeDesc::UNKNOWN));
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Unknown struct name: %s", $1);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"Unknown struct name: {}", $1);
|
||||
}
|
||||
$$ = (int)ShaderType::Unknown;
|
||||
}
|
||||
@@ -797,9 +801,9 @@ expression
|
||||
// color x = Cd * (a, b, c); // same as: x = Cd * c
|
||||
// when they really meant
|
||||
// color x = Cd * color(a, b, c);
|
||||
oslcompiler->warningf(oslcompiler->filename(),
|
||||
@1.first_line,
|
||||
"Comma operator inside parenthesis is probably an error -- it is not a vector/color.");
|
||||
oslcompiler->warningfmt(oslcompiler->filename(),
|
||||
@1.first_line,
|
||||
"Comma operator inside parenthesis is probably an error -- it is not a vector/color.");
|
||||
}
|
||||
$$ = $2;
|
||||
}
|
||||
@@ -1094,8 +1098,8 @@ string_literal_group
|
||||
void
|
||||
OSL::pvt::yyerror (YYLTYPE* yylloc_param, void* yyscanner, OSLCompilerImpl* oslcompiler, const char* err)
|
||||
{
|
||||
oslcompiler->errorf(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"Syntax error: %s", err);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"Syntax error: {}", err);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+33
-28
@@ -7,6 +7,11 @@
|
||||
/** Lexical scanner for Open Shading Language
|
||||
**/
|
||||
|
||||
%top{
|
||||
/* Include this first to avoid warnings about re-definitions on windows */
|
||||
#include <stdint.h>
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
* Definitions section
|
||||
************************************************************/
|
||||
@@ -176,10 +181,10 @@ OSL_NAMESPACE_EXIT
|
||||
"protected"|"short"|"signed"|"sizeof"|"static"|"struct" | \
|
||||
"switch"|"template"|"this"|"true"|"typedef"|"uniform" | \
|
||||
"union"|"unsigned"|"varying"|"virtual" {
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"'%s' is a reserved word",
|
||||
yytext);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"'{}' is a reserved word",
|
||||
yytext);
|
||||
SETLINE;
|
||||
return (yylval->i=RESERVED);
|
||||
}
|
||||
@@ -198,10 +203,10 @@ OSL_NAMESPACE_EXIT
|
||||
// we do not detect overflow when the value is INT_MAX+1,
|
||||
// because negation happens later and -(INT_MAX+1) == INT_MIN
|
||||
if (llval > ((long long)INT_MAX)+1) {
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"integer overflow, value must be between %d and %d.",
|
||||
INT_MIN, INT_MAX);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"integer overflow, value must be between {} and {}.",
|
||||
INT_MIN, INT_MAX);
|
||||
}
|
||||
yylval->i = (int)llval;
|
||||
SETLINE;
|
||||
@@ -212,10 +217,10 @@ OSL_NAMESPACE_EXIT
|
||||
// we do not detect overflow when the value is INT_MAX+1,
|
||||
// because negation happens later and -(INT_MAX+1) == INT_MIN
|
||||
if (llval > ((long long)UINT_MAX)+1) {
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"integer overflow, value must be between %d and %d.",
|
||||
INT_MIN, INT_MAX);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"integer overflow, value must be between {} and {}.",
|
||||
INT_MIN, INT_MAX);
|
||||
}
|
||||
yylval->i = (int)llval;
|
||||
SETLINE;
|
||||
@@ -300,8 +305,8 @@ preprocess (const char *str, OSLCompilerImpl* oslcompiler, YYLTYPE* yyloc_param)
|
||||
while (*p == ' ' || *p == '\t')
|
||||
p++;
|
||||
if (*p != '#') {
|
||||
oslcompiler->errorf(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"Possible bug in shader preprocess");
|
||||
oslcompiler->errorfmt(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"Possible bug in shader preprocess");
|
||||
SETLINE;
|
||||
return;
|
||||
}
|
||||
@@ -315,30 +320,30 @@ preprocess (const char *str, OSLCompilerImpl* oslcompiler, YYLTYPE* yyloc_param)
|
||||
if (pragmatype == "error") {
|
||||
string_view msg;
|
||||
if (OIIO::Strutil::parse_string(line, msg))
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(), "%s", msg);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(), "{}", msg);
|
||||
else
|
||||
oslcompiler->errorf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"<unknown error>");
|
||||
oslcompiler->errorfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"<unknown error>");
|
||||
}
|
||||
else if (pragmatype == "warning") {
|
||||
string_view msg;
|
||||
if (OIIO::Strutil::parse_string(line, msg))
|
||||
oslcompiler->warningf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(), "%s", msg);
|
||||
oslcompiler->warningfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(), "{}", msg);
|
||||
else
|
||||
oslcompiler->warningf(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"<unknown warning>");
|
||||
oslcompiler->warningfmt(oslcompiler->filename(),
|
||||
oslcompiler->lineno(),
|
||||
"<unknown warning>");
|
||||
}
|
||||
else if (OIIO::Strutil::iequals (pragmatype, "osl")) {
|
||||
string_view pragmaname = OIIO::Strutil::parse_word (line);
|
||||
if (pragmaname == "nowarn") {
|
||||
oslcompiler->pragma_nowarn ();
|
||||
} else {
|
||||
oslcompiler->warningf(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"Unknown pragma '%s'", pragmaname);
|
||||
oslcompiler->warningfmt(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"Unknown pragma '{}'", pragmaname);
|
||||
}
|
||||
}
|
||||
// N.B. Any other pragmas that don't start with "osl" are ignored
|
||||
@@ -377,8 +382,8 @@ preprocess (const char *str, OSLCompilerImpl* oslcompiler, YYLTYPE* yyloc_param)
|
||||
}
|
||||
oslcompiler->lineno (line);
|
||||
} else {
|
||||
oslcompiler->errorf(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"Unrecognized preprocessor command: #%s", p);
|
||||
oslcompiler->errorfmt(oslcompiler->filename(), oslcompiler->lineno(),
|
||||
"Unrecognized preprocessor command: #{}", p);
|
||||
}
|
||||
}
|
||||
SETLINE;
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace pvt { // OSL::pvt
|
||||
std::string
|
||||
Symbol::mangled() const
|
||||
{
|
||||
std::string result = scope() ? Strutil::sprintf("___%d_%s", scope(), m_name)
|
||||
std::string result = scope() ? fmtformat("___{}_{}", scope(), m_name)
|
||||
: m_name.string();
|
||||
return result; // Force NRVO (named value return optimization)
|
||||
}
|
||||
@@ -43,9 +43,9 @@ Symbol::unmangled() const
|
||||
const char*
|
||||
Symbol::symtype_shortname(SymType s)
|
||||
{
|
||||
OSL_DASSERT((int)s >= 0 && (int)s < (int)SymTypeType);
|
||||
OSL_DASSERT((int)s >= 0 && (int)s < (int)SymTypeLast);
|
||||
static const char* names[] = { "param", "oparam", "local", "temp",
|
||||
"global", "const", "func" };
|
||||
"global", "const", "func", "typename" };
|
||||
return names[(int)s];
|
||||
}
|
||||
|
||||
@@ -54,8 +54,7 @@ Symbol::symtype_shortname(SymType s)
|
||||
std::string
|
||||
StructSpec::mangled() const
|
||||
{
|
||||
return scope() ? Strutil::sprintf("___%d_%s", scope(), m_name)
|
||||
: m_name.string();
|
||||
return scope() ? fmtformat("___{}_{}", scope(), m_name) : m_name.string();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ private:
|
||||
///
|
||||
class SymbolTable {
|
||||
public:
|
||||
typedef std::unordered_map<ustring, Symbol*, ustringHash> ScopeTable;
|
||||
typedef std::unordered_map<ustring, Symbol*> ScopeTable;
|
||||
typedef std::vector<ScopeTable> ScopeTableStack;
|
||||
typedef SymbolPtrVec::iterator iterator;
|
||||
typedef SymbolPtrVec::const_iterator const_iterator;
|
||||
|
||||
+134
-120
@@ -65,7 +65,8 @@ ASTfunction_declaration::typecheck(TypeSpec expected)
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTvariable_declaration::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTvariable_declaration::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
typecheck_children(m_typespec);
|
||||
ASTNode* init = this->init().get();
|
||||
@@ -79,7 +80,7 @@ TypeSpec ASTvariable_declaration::typecheck(TypeSpec /*expected*/)
|
||||
if (m_typespec.is_structure() && !m_initlist
|
||||
&& et.structure() != vt.structure()) {
|
||||
// Can't do: struct foo = 1
|
||||
errorf("Cannot initialize %s %s = %s", vt, name(), et);
|
||||
errorfmt("Cannot initialize {} {} = {}", vt, name(), et);
|
||||
return m_typespec;
|
||||
}
|
||||
|
||||
@@ -88,7 +89,7 @@ TypeSpec ASTvariable_declaration::typecheck(TypeSpec /*expected*/)
|
||||
// typecheck method.
|
||||
if (init->nodetype() == compound_initializer_node) {
|
||||
if (init->nextptr())
|
||||
errorf("compound_initializer should be the only initializer");
|
||||
errorfmt("compound_initializer should be the only initializer");
|
||||
init = ((ASTcompound_initializer*)init)->initlist().get();
|
||||
if (!init)
|
||||
return m_typespec;
|
||||
@@ -106,10 +107,10 @@ TypeSpec ASTvariable_declaration::typecheck(TypeSpec /*expected*/)
|
||||
if (!assignable(vt, et)) {
|
||||
// Special case: for int=float, it's just a warning.
|
||||
if (vt.is_int() && et.is_float())
|
||||
warningf("Assignment may lose precision: %s %s = %s", vt, name(),
|
||||
et);
|
||||
warningfmt("Assignment may lose precision: {} {} = {}", vt, name(),
|
||||
et);
|
||||
else
|
||||
errorf("Cannot assign %s %s = %s", vt, name(), et);
|
||||
errorfmt("Cannot assign {} {} = {}", vt, name(), et);
|
||||
return m_typespec;
|
||||
}
|
||||
|
||||
@@ -118,7 +119,8 @@ TypeSpec ASTvariable_declaration::typecheck(TypeSpec /*expected*/)
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTvariable_ref::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTvariable_ref::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
m_is_lvalue = true; // A var ref is an lvalue
|
||||
return m_typespec;
|
||||
@@ -126,7 +128,8 @@ TypeSpec ASTvariable_ref::typecheck(TypeSpec /*expected*/)
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTpreincdec::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTpreincdec::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
typecheck_children();
|
||||
m_is_lvalue = var()->is_lvalue();
|
||||
@@ -136,11 +139,12 @@ TypeSpec ASTpreincdec::typecheck(TypeSpec /*expected*/)
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTpostincdec::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTpostincdec::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
typecheck_children();
|
||||
if (!var()->is_lvalue())
|
||||
errorf("%s can only be applied to an lvalue", nodetypename());
|
||||
errorfmt("{} can only be applied to an lvalue", nodetypename());
|
||||
m_is_lvalue = false;
|
||||
m_typespec = var()->typespec();
|
||||
return m_typespec;
|
||||
@@ -148,29 +152,30 @@ TypeSpec ASTpostincdec::typecheck(TypeSpec /*expected*/)
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTindex::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTindex::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
typecheck_children();
|
||||
const char* indextype = "";
|
||||
TypeSpec t = lvalue()->typespec();
|
||||
if (t.is_structure()) {
|
||||
errorf("Cannot use [] indexing on a struct");
|
||||
errorfmt("Cannot use [] indexing on a struct");
|
||||
return TypeSpec();
|
||||
}
|
||||
if (t.is_closure()) {
|
||||
errorf("Cannot use [] indexing on a closure");
|
||||
errorfmt("Cannot use [] indexing on a closure");
|
||||
return TypeSpec();
|
||||
}
|
||||
if (index3()) {
|
||||
if (!t.is_array() && !t.elementtype().is_matrix())
|
||||
errorf("[][][] only valid for a matrix array");
|
||||
errorfmt("[][][] only valid for a matrix array");
|
||||
m_typespec = TypeDesc::FLOAT;
|
||||
} else if (t.is_array()) {
|
||||
indextype = "array";
|
||||
m_typespec = t.elementtype();
|
||||
if (index2()) {
|
||||
if (t.aggregate() == TypeDesc::SCALAR)
|
||||
errorf("can't use [][] on a simple array");
|
||||
errorfmt("can't use [][] on a simple array");
|
||||
m_typespec = TypeDesc::FLOAT;
|
||||
}
|
||||
} else if (t.aggregate() == TypeDesc::VEC3) {
|
||||
@@ -180,7 +185,7 @@ TypeSpec ASTindex::typecheck(TypeSpec /*expected*/)
|
||||
tnew.vecsemantics = TypeDesc::NOXFORM;
|
||||
m_typespec = tnew;
|
||||
if (index2())
|
||||
errorf("can't use [][] on a %s", t);
|
||||
errorfmt("can't use [][] on a {}", t);
|
||||
} else if (t.aggregate() == TypeDesc::MATRIX44) {
|
||||
indextype = "component";
|
||||
TypeDesc tnew = t.simpletype();
|
||||
@@ -188,17 +193,18 @@ TypeSpec ASTindex::typecheck(TypeSpec /*expected*/)
|
||||
tnew.vecsemantics = TypeDesc::NOXFORM;
|
||||
m_typespec = tnew;
|
||||
if (!index2())
|
||||
errorf("must use [][] on a matrix, not just []");
|
||||
errorfmt("must use [][] on a matrix, not just []");
|
||||
} else {
|
||||
errorf("can only use [] indexing for arrays or multi-component types");
|
||||
errorfmt(
|
||||
"can only use [] indexing for arrays or multi-component types");
|
||||
return TypeSpec();
|
||||
}
|
||||
|
||||
// Make sure the indices (children 1+) are integers
|
||||
for (size_t c = 1; c < nchildren(); ++c)
|
||||
if (!child(c)->typespec().is_int())
|
||||
errorf("%s index must be an integer, not a %s", indextype,
|
||||
index()->typespec());
|
||||
errorfmt("{} index must be an integer, not a {}", indextype,
|
||||
index()->typespec());
|
||||
|
||||
// If the thing we're indexing is an lvalue, so is the indexed element
|
||||
m_is_lvalue = lvalue()->is_lvalue();
|
||||
@@ -230,7 +236,8 @@ ASTstructselect::typecheck(TypeSpec expected)
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTconditional_statement::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTconditional_statement::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
typecheck_list(cond());
|
||||
m_compiler->push_nesting(false);
|
||||
@@ -240,15 +247,16 @@ TypeSpec ASTconditional_statement::typecheck(TypeSpec /*expected*/)
|
||||
|
||||
TypeSpec c = cond()->typespec();
|
||||
if (c.is_structure())
|
||||
errorf("Cannot use a struct as an 'if' condition");
|
||||
errorfmt("Cannot use a struct as an 'if' condition");
|
||||
if (c.is_array())
|
||||
errorf("Cannot use an array as an 'if' condition");
|
||||
errorfmt("Cannot use an array as an 'if' condition");
|
||||
return m_typespec = TypeDesc(TypeDesc::NONE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTloop_statement::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTloop_statement::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
typecheck_list(init());
|
||||
m_compiler->push_nesting(true);
|
||||
@@ -259,34 +267,36 @@ TypeSpec ASTloop_statement::typecheck(TypeSpec /*expected*/)
|
||||
|
||||
TypeSpec c = cond()->typespec();
|
||||
if (c.is_closure())
|
||||
errorf("Cannot use a closure as an '%s' condition", opname());
|
||||
errorfmt("Cannot use a closure as an '{}' condition", opname());
|
||||
if (c.is_structure())
|
||||
errorf("Cannot use a struct as an '%s' condition", opname());
|
||||
errorfmt("Cannot use a struct as an '{}' condition", opname());
|
||||
if (c.is_array())
|
||||
errorf("Cannot use an array as an '%s' condition", opname());
|
||||
errorfmt("Cannot use an array as an '{}' condition", opname());
|
||||
return m_typespec = TypeDesc(TypeDesc::NONE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTloopmod_statement::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTloopmod_statement::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
if (m_compiler->nesting_level(true /*loops*/) < 1)
|
||||
errorf("Cannot '%s' here -- not inside a loop.", opname());
|
||||
errorfmt("Cannot '{}' here -- not inside a loop.", opname());
|
||||
return m_typespec = TypeDesc(TypeDesc::NONE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTassign_expression::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTassign_expression::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
TypeSpec vt = var()->typecheck(); // Type of the variable
|
||||
TypeSpec et = expr()->typecheck(vt); // Type of the expression assigned
|
||||
m_typespec = vt;
|
||||
|
||||
if (!var()->is_lvalue()) {
|
||||
errorf("Can't assign via %s to something that isn't an lvalue",
|
||||
opname());
|
||||
errorfmt("Can't assign via {} to something that isn't an lvalue",
|
||||
opname());
|
||||
return TypeSpec();
|
||||
}
|
||||
|
||||
@@ -307,7 +317,7 @@ TypeSpec ASTassign_expression::typecheck(TypeSpec /*expected*/)
|
||||
return m_typespec;
|
||||
}
|
||||
}
|
||||
errorf("Cannot assign %s %s = %s", vt, varname, et);
|
||||
errorfmt("Cannot assign {} {} = {}", vt, varname, et);
|
||||
return m_typespec;
|
||||
}
|
||||
|
||||
@@ -326,7 +336,7 @@ TypeSpec ASTassign_expression::typecheck(TypeSpec /*expected*/)
|
||||
if (vts == ets)
|
||||
return m_typespec = vt;
|
||||
// Otherwise, a structure mismatch
|
||||
errorf("Cannot assign %s %s = %s", vt, varname, et);
|
||||
errorfmt("Cannot assign {} {} = {}", vt, varname, et);
|
||||
return m_typespec;
|
||||
}
|
||||
|
||||
@@ -334,10 +344,10 @@ TypeSpec ASTassign_expression::typecheck(TypeSpec /*expected*/)
|
||||
if (!assignable(vt, et)) {
|
||||
// Special case: for int=float, it's just a warning.
|
||||
if (vt.is_int() && et.is_float())
|
||||
warningf("Assignment may lose precision: %s %s = %s", vt, varname,
|
||||
et);
|
||||
warningfmt("Assignment may lose precision: {} {} = {}", vt, varname,
|
||||
et);
|
||||
else
|
||||
errorf("Cannot assign %s %s = %s", vt, varname, et);
|
||||
errorfmt("Cannot assign {} {} = {}", vt, varname, et);
|
||||
return m_typespec;
|
||||
}
|
||||
|
||||
@@ -346,7 +356,8 @@ TypeSpec ASTassign_expression::typecheck(TypeSpec /*expected*/)
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTreturn_statement::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTreturn_statement::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
FunctionSymbol* myfunc = m_compiler->current_function();
|
||||
if (myfunc) {
|
||||
@@ -357,14 +368,14 @@ TypeSpec ASTreturn_statement::typecheck(TypeSpec /*expected*/)
|
||||
// will also catch returning a value from a void function.
|
||||
TypeSpec et = expr()->typecheck(myfunc->typespec());
|
||||
if (!assignable(myfunc->typespec(), et)) {
|
||||
errorf("Cannot return a '%s' from '%s %s()'", et,
|
||||
myfunc->typespec(), myfunc->name());
|
||||
errorfmt("Cannot return a '{}' from '{} {}()'", et,
|
||||
myfunc->typespec(), myfunc->name());
|
||||
}
|
||||
} else {
|
||||
// If we are not returning a value, it must be a void function.
|
||||
if (!myfunc->typespec().is_void())
|
||||
errorf("You must return a '%s' from function '%s'",
|
||||
myfunc->typespec(), myfunc->name());
|
||||
errorfmt("You must return a '{}' from function '{}'",
|
||||
myfunc->typespec(), myfunc->name());
|
||||
}
|
||||
myfunc->encountered_return();
|
||||
} else {
|
||||
@@ -372,7 +383,7 @@ TypeSpec ASTreturn_statement::typecheck(TypeSpec /*expected*/)
|
||||
// be from the main shader body. That's fine (it's equivalent
|
||||
// to calling exit()), but it can't return a value.
|
||||
if (expr())
|
||||
errorf("Cannot return a value from a shader body");
|
||||
errorfmt("Cannot return a value from a shader body");
|
||||
}
|
||||
return TypeSpec(); // TODO: what should be returned here?
|
||||
}
|
||||
@@ -402,14 +413,14 @@ ASTunary_expression::typecheck(TypeSpec expected)
|
||||
}
|
||||
|
||||
if (t.is_structure() || t.is_array()) {
|
||||
errorf("Can't do '%s' to a %s.", opname(), t);
|
||||
errorfmt("Can't do '{}' to a {}.", opname(), t);
|
||||
return TypeSpec();
|
||||
}
|
||||
switch (m_op) {
|
||||
case Sub:
|
||||
case Add:
|
||||
if (!(t.is_closure() || t.is_numeric())) {
|
||||
errorf("Can't do '%s' to a %s.", opname(), t);
|
||||
errorfmt("Can't do '{}' to a {}.", opname(), t);
|
||||
return TypeSpec();
|
||||
}
|
||||
m_typespec = t;
|
||||
@@ -419,12 +430,12 @@ ASTunary_expression::typecheck(TypeSpec expected)
|
||||
break;
|
||||
case Compl:
|
||||
if (!t.is_int()) {
|
||||
errorf("Operator '~' can only be done to an int");
|
||||
errorfmt("Operator '~' can only be done to an int");
|
||||
return TypeSpec();
|
||||
}
|
||||
m_typespec = t;
|
||||
break;
|
||||
default: errorf("unknown unary operator");
|
||||
default: errorfmt("unknown unary operator");
|
||||
}
|
||||
return m_typespec;
|
||||
}
|
||||
@@ -467,7 +478,7 @@ ASTbinary_expression::typecheck(TypeSpec expected)
|
||||
TypeSpec returntype = m_compiler->type_from_code(code, &advance);
|
||||
code += advance;
|
||||
if (code[0] && check_simple_arg(l, code, true) && code[0]
|
||||
&& check_simple_arg(r, code, true) && !code[0]) {
|
||||
&& check_simple_arg(r, code, true) && !code[0]) { // NOSONAR
|
||||
return m_typespec = returntype;
|
||||
}
|
||||
}
|
||||
@@ -477,7 +488,7 @@ ASTbinary_expression::typecheck(TypeSpec expected)
|
||||
|
||||
// No binary ops work on structs or arrays
|
||||
if (l.is_structure() || r.is_structure() || l.is_array() || r.is_array()) {
|
||||
errorf("Not allowed: '%s %s %s'", l, opname(), r);
|
||||
errorfmt("Not allowed: '{} {} {}'", l, opname(), r);
|
||||
return TypeSpec();
|
||||
}
|
||||
|
||||
@@ -507,7 +518,7 @@ ASTbinary_expression::typecheck(TypeSpec expected)
|
||||
return m_typespec = TypeDesc::TypeInt;
|
||||
}
|
||||
// If we got this far, it's an op that's not allowed
|
||||
errorf("Not allowed: '%s %s %s'", l, opname(), r);
|
||||
errorfmt("Not allowed: '{} {} {}'", l, opname(), r);
|
||||
return TypeSpec();
|
||||
}
|
||||
|
||||
@@ -581,11 +592,11 @@ ASTbinary_expression::typecheck(TypeSpec expected)
|
||||
// nonzeroness), but always return int.
|
||||
return m_typespec = TypeDesc::TypeInt;
|
||||
|
||||
default: errorf("unknown binary operator");
|
||||
default: errorfmt("unknown binary operator");
|
||||
}
|
||||
|
||||
// If we got this far, it's an op that's not allowed
|
||||
errorf("Not allowed: '%s %s %s'", l, opname(), r);
|
||||
errorfmt("Not allowed: '{} {} {}'", l, opname(), r);
|
||||
return TypeSpec();
|
||||
}
|
||||
|
||||
@@ -600,15 +611,15 @@ ASTternary_expression::typecheck(TypeSpec expected)
|
||||
TypeSpec f = typecheck_list(falseexpr(), expected);
|
||||
|
||||
if (c.is_closure())
|
||||
errorf("Cannot use a closure as a condition");
|
||||
errorfmt("Cannot use a closure as a condition");
|
||||
if (c.is_structure())
|
||||
errorf("Cannot use a struct as a condition");
|
||||
errorfmt("Cannot use a struct as a condition");
|
||||
if (c.is_array())
|
||||
errorf("Cannot use an array as a condition");
|
||||
errorfmt("Cannot use an array as a condition");
|
||||
|
||||
// No arrays
|
||||
if (t.is_array() || t.is_array()) {
|
||||
errorf("Not allowed: '%s ? %s : %s'", c, t, f);
|
||||
if (t.is_array() || f.is_array()) {
|
||||
errorfmt("Not allowed: '{} ? {} : {}'", c, t, f);
|
||||
return TypeSpec();
|
||||
}
|
||||
|
||||
@@ -617,7 +628,7 @@ ASTternary_expression::typecheck(TypeSpec expected)
|
||||
if (assignable(t, f) || assignable(f, t))
|
||||
m_typespec = higherprecision(t.simpletype(), f.simpletype());
|
||||
else
|
||||
errorf("Not allowed: '%s ? %s : %s'", c, t, f);
|
||||
errorfmt("Not allowed: '{} ? {} : {}'", c, t, f);
|
||||
|
||||
return m_typespec;
|
||||
}
|
||||
@@ -634,7 +645,8 @@ ASTcomma_operator::typecheck(TypeSpec expected)
|
||||
|
||||
|
||||
|
||||
TypeSpec ASTtypecast_expression::typecheck(TypeSpec /*expected*/)
|
||||
TypeSpec
|
||||
ASTtypecast_expression::typecheck(TypeSpec /*expected*/)
|
||||
{
|
||||
// FIXME - closures
|
||||
typecheck_children(m_typespec);
|
||||
@@ -642,7 +654,7 @@ TypeSpec ASTtypecast_expression::typecheck(TypeSpec /*expected*/)
|
||||
if (!assignable(m_typespec, t) && !(m_typespec.is_int() && t.is_float())
|
||||
&& // (int)float is ok
|
||||
!(m_typespec.is_triple() && t.is_triple()))
|
||||
errorf("Cannot cast '%s' to '%s'", t, m_typespec);
|
||||
errorfmt("Cannot cast '{}' to '{}'", t, m_typespec);
|
||||
return m_typespec;
|
||||
}
|
||||
|
||||
@@ -666,7 +678,7 @@ ASTtype_constructor::typecheck(TypeSpec expected, bool report, bool bind)
|
||||
if (expected.is_float()) {
|
||||
patterns = float_patterns;
|
||||
argexpected = TypeDesc::FLOAT;
|
||||
// ^^^ Since simetimes tht constructor `float(expr)` is used as a
|
||||
// ^^^ Since sometimes the constructor `float(expr)` is used as a
|
||||
// synonym for a cast `(float)expr`, we know that ambiguously typed
|
||||
// expressions should favor disambiguating to a float.
|
||||
} else if (expected.is_triple()) {
|
||||
@@ -686,7 +698,7 @@ ASTtype_constructor::typecheck(TypeSpec expected, bool report, bool bind)
|
||||
patterns = int_patterns;
|
||||
} else {
|
||||
if (report)
|
||||
errorf("Cannot construct type '%s'", expected);
|
||||
errorfmt("Cannot construct type '{}'", expected);
|
||||
return TypeSpec();
|
||||
}
|
||||
|
||||
@@ -706,15 +718,15 @@ ASTtype_constructor::typecheck(TypeSpec expected, bool report, bool bind)
|
||||
|
||||
// If we made it this far, no match could be found.
|
||||
if (report) {
|
||||
std::string err = OIIO::Strutil::sprintf("Cannot construct %s (",
|
||||
expected);
|
||||
std::string err = OIIO::Strutil::fmt::format("Cannot construct {} (",
|
||||
expected);
|
||||
for (ref a = args(); a; a = a->next()) {
|
||||
err += a->typespec().string();
|
||||
if (a->next())
|
||||
err += ", ";
|
||||
}
|
||||
err += ")";
|
||||
errorf("%s", err);
|
||||
errorfmt("{}", err);
|
||||
// FIXME -- it might be nice here to enumerate for the user all the
|
||||
// valid combinations.
|
||||
}
|
||||
@@ -750,7 +762,7 @@ public:
|
||||
|
||||
~TypeAdjuster()
|
||||
{
|
||||
// Commit infered types of all ASTcompound_initializers scanned.
|
||||
// Commit inferred types of all ASTcompound_initializers scanned.
|
||||
if (m_success) {
|
||||
for (auto&& initer : m_adjust) {
|
||||
ASTcompound_initializer* ciptr = std::get<0>(initer);
|
||||
@@ -775,9 +787,9 @@ public:
|
||||
if (m_mode & must_init_all) {
|
||||
m_success = false;
|
||||
if (errors()) {
|
||||
cinit->errorf("Empty initializer list not allowed to"
|
||||
"represent '%' here",
|
||||
to);
|
||||
cinit->errorfmt("Empty initializer list not allowed to "
|
||||
"represent '{}' here",
|
||||
to);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -840,9 +852,9 @@ public:
|
||||
|
||||
m_success = false;
|
||||
if (errors()) {
|
||||
init->errorf("Too %s initializers for a '%s'",
|
||||
nelem < expected.arraylength() ? "few" : "many",
|
||||
expected);
|
||||
init->errorfmt("Too {} initializers for a '{}'",
|
||||
nelem < expected.arraylength() ? "few" : "many",
|
||||
expected);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -888,9 +900,9 @@ public:
|
||||
|
||||
m_success = false;
|
||||
if (errors() && (arg || nfields > ninits)) {
|
||||
parent->errorf("Too %s initializers for struct '%s'",
|
||||
ninits < nfields ? "few" : "many",
|
||||
structspec->name());
|
||||
parent->errorfmt("Too {} initializers for struct '{}'",
|
||||
ninits < nfields ? "few" : "many",
|
||||
structspec->name());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -980,9 +992,9 @@ private:
|
||||
const StructSpec::FieldSpec* field = nullptr)
|
||||
{
|
||||
if (node->typecheck(expected) != expected &&
|
||||
// Alllow assignment with comparable type
|
||||
// Allow assignment with comparable type
|
||||
!assignable(expected, node->typespec()) &&
|
||||
// Alllow closure assignments to '0'
|
||||
// Allow closure assignments to '0'
|
||||
!(expected.is_closure() && !node->typespec().is_closure()
|
||||
&& node->typespec().is_int_or_float()
|
||||
&& node->nodetype() == literal_node
|
||||
@@ -992,11 +1004,11 @@ private:
|
||||
return false;
|
||||
|
||||
OSL_DASSERT(!spec || field);
|
||||
node->errorf("Can't assign '%s' to '%s%s'", node->typespec(),
|
||||
expected,
|
||||
!spec ? ""
|
||||
: Strutil::sprintf(" %s.%s", spec->name(),
|
||||
field->name));
|
||||
node->errorfmt("Can't assign '{}' to '{}{}'", node->typespec(),
|
||||
expected,
|
||||
!spec ? ""
|
||||
: Strutil::fmt::format(" {}.{}", spec->name(),
|
||||
field->name));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1010,7 +1022,7 @@ ASTcompound_initializer::typecheck(TypeSpec expected, unsigned mode)
|
||||
if (m_ctor || m_typespec.is_structure_based()
|
||||
|| m_typespec.simpletype().basetype != TypeDesc::UNKNOWN) {
|
||||
if (m_typespec != expected)
|
||||
errorf("Cannot construct type '%s'", expected);
|
||||
errorfmt("Cannot construct type '{}'", expected);
|
||||
return m_typespec;
|
||||
}
|
||||
|
||||
@@ -1053,6 +1065,8 @@ bool
|
||||
ASTNode::check_arglist(const char* /*funcname*/, ASTNode::ref arg,
|
||||
const char* formals, bool coerce, bool bind)
|
||||
{
|
||||
if (!formals)
|
||||
return false;
|
||||
// std::cerr << "ca " << funcname << " formals='" << formals << "\n";
|
||||
for (; arg; arg = arg->next()) {
|
||||
if (!*formals) // More formal args, but no more actual args
|
||||
@@ -1188,14 +1202,14 @@ ASTfunction_call::typecheck_printf_args(const char* format, ASTNode* arg)
|
||||
++format;
|
||||
char formatchar = *format++; // Also eat the format char
|
||||
if (!arg) {
|
||||
errorf(
|
||||
"%s has mismatched format string and arguments (not enough args)",
|
||||
errorfmt(
|
||||
"{} has mismatched format string and arguments (not enough args)",
|
||||
m_name);
|
||||
return false;
|
||||
}
|
||||
if (arg->typespec().is_structure_based()) {
|
||||
errorf("struct '%s' is not a valid argument",
|
||||
arg->typespec().structspec()->name());
|
||||
errorfmt("struct '{}' is not a valid argument",
|
||||
arg->typespec().structspec()->name());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1205,16 +1219,16 @@ ASTfunction_call::typecheck_printf_args(const char* format, ASTNode* arg)
|
||||
if ((arg->typespec().is_closure_based()
|
||||
|| simpletype.basetype == TypeDesc::STRING)
|
||||
&& formatchar != 's') {
|
||||
errorf(
|
||||
"%s has mismatched format string and arguments (arg %d needs %%s)",
|
||||
errorfmt(
|
||||
"{} has mismatched format string and arguments (arg {} needs %s)",
|
||||
m_name);
|
||||
return false;
|
||||
}
|
||||
if (simpletype.basetype == TypeDesc::INT && formatchar != 'd'
|
||||
&& formatchar != 'i' && formatchar != 'o' && formatchar != 'x'
|
||||
&& formatchar != 'X') {
|
||||
errorf(
|
||||
"%s has mismatched format string and arguments (arg %d needs %%d, %%i, %%o, %%x, or %%X)",
|
||||
errorfmt(
|
||||
"{} has mismatched format string and arguments (arg {} needs %d, %i, %o, %x, or %X)",
|
||||
m_name, argnum);
|
||||
return false;
|
||||
}
|
||||
@@ -1222,8 +1236,8 @@ ASTfunction_call::typecheck_printf_args(const char* format, ASTNode* arg)
|
||||
&& formatchar != 'g' && formatchar != 'c' && formatchar != 'e'
|
||||
&& formatchar != 'm' && formatchar != 'n' && formatchar != 'p'
|
||||
&& formatchar != 'v') {
|
||||
errorf(
|
||||
"%s has mismatched format string and arguments (arg %d needs %%f, %%g, or %%e)",
|
||||
errorfmt(
|
||||
"{} has mismatched format string and arguments (arg {} needs %f, %g, or %e)",
|
||||
m_name, argnum);
|
||||
return false;
|
||||
}
|
||||
@@ -1236,8 +1250,8 @@ ASTfunction_call::typecheck_printf_args(const char* format, ASTNode* arg)
|
||||
}
|
||||
}
|
||||
if (arg) {
|
||||
errorf("%s has mismatched format string and arguments (too many args)",
|
||||
m_name);
|
||||
errorfmt("{} has mismatched format string and arguments (too many args)",
|
||||
m_name);
|
||||
return false;
|
||||
}
|
||||
return true; // all ok
|
||||
@@ -1303,8 +1317,8 @@ ASTfunction_call::typecheck_builtin_specialcase()
|
||||
arg = arg->nextptr();
|
||||
typecheck_printf_args(format, arg);
|
||||
} else {
|
||||
warningf("%s() uses a format string that is not a constant.",
|
||||
m_name);
|
||||
warningfmt("{}() uses a format string that is not a constant.",
|
||||
m_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1379,8 +1393,8 @@ ASTfunction_call::typecheck_struct_constructor()
|
||||
m_typespec = m_sym->typespec();
|
||||
if (structspec->numfields() != (int)listlength(args())) {
|
||||
// Support a single argument which is an init-list of proper type?
|
||||
errorf(
|
||||
"Constructor for '%s' has the wrong number of arguments (expected %d, got %d)",
|
||||
errorfmt(
|
||||
"Constructor for '{}' has the wrong number of arguments (expected {}, got {})",
|
||||
structspec->name(), structspec->numfields(), listlength(args()));
|
||||
}
|
||||
|
||||
@@ -1607,7 +1621,7 @@ class CandidateFunctions {
|
||||
|
||||
default:
|
||||
// TODO: Scoring default function arguments would go here
|
||||
// Curently an unused formal argument, so no match at all.
|
||||
// Currently an unused formal argument, so no match at all.
|
||||
return kNoMatch;
|
||||
}
|
||||
OSL_DASSERT(*formals == 0);
|
||||
@@ -1672,8 +1686,8 @@ public:
|
||||
comma = ", ";
|
||||
}
|
||||
argstr += ")";
|
||||
return Strutil::sprintf("%s '%s'%s\n", msg, argstr,
|
||||
candidateMsg ? "\n Candidates are:" : "");
|
||||
return Strutil::fmt::format("{} '{}'{}\n", msg, argstr,
|
||||
candidateMsg ? "\n Candidates are:" : "");
|
||||
}
|
||||
|
||||
std::string reportFunction(FunctionSymbol* sym) const
|
||||
@@ -1684,10 +1698,10 @@ public:
|
||||
formals += advance;
|
||||
std::string msg = " ";
|
||||
if (ASTNode* decl = sym->node())
|
||||
msg += Strutil::sprintf("%s:%d\t", decl->sourcefile(),
|
||||
decl->sourceline());
|
||||
msg += Strutil::sprintf("%s %s (%s)\n", returntype, sym->name(),
|
||||
m_compiler->typelist_from_code(formals));
|
||||
msg += Strutil::fmt::format("{}:{}\t", decl->sourcefile(),
|
||||
decl->sourceline());
|
||||
msg += Strutil::fmt::format("{} {} ({})\n", returntype, sym->name(),
|
||||
m_compiler->typelist_from_code(formals));
|
||||
return msg;
|
||||
}
|
||||
|
||||
@@ -1715,7 +1729,7 @@ public:
|
||||
"No matching function call to");
|
||||
for (FunctionSymbol* f = m_called; f; f = f->nextpoly())
|
||||
errmsg += reportFunction(f);
|
||||
caller->errorf("%s", errmsg);
|
||||
caller->errorfmt("{}", errmsg);
|
||||
return { nullptr, TypeSpec() };
|
||||
|
||||
case 1: // Success
|
||||
@@ -1840,17 +1854,17 @@ public:
|
||||
= reportAmbiguity(funcname, !warn /* "Candidates are" msg*/,
|
||||
"Ambiguous call to");
|
||||
if (warn) {
|
||||
errmsg += Strutil::sprintf(" Chosen function is:\n%s",
|
||||
reportFunction(c.first->sym));
|
||||
errmsg += Strutil::fmt::format(" Chosen function is:\n{}",
|
||||
reportFunction(c.first->sym));
|
||||
errmsg += " Other candidates are:\n";
|
||||
for (auto& candidate : m_candidates)
|
||||
if (candidate.sym != c.first->sym)
|
||||
errmsg += reportFunction(candidate.sym);
|
||||
caller->warningf("%s", errmsg);
|
||||
caller->warningfmt("{}", errmsg);
|
||||
} else {
|
||||
for (auto& candidate : m_candidates)
|
||||
errmsg += reportFunction(candidate.sym);
|
||||
caller->errorf("%s", errmsg);
|
||||
caller->errorfmt("{}", errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1982,7 +1996,7 @@ ASTfunction_call::typecheck(TypeSpec expected)
|
||||
any_args_are_compound_initializers = true;
|
||||
}
|
||||
|
||||
// Save the currently choosen symbol for error reporting later
|
||||
// Save the currently chosen symbol for error reporting later
|
||||
FunctionSymbol* poly = func();
|
||||
|
||||
CandidateFunctions candidates(m_compiler, expected, args(), poly);
|
||||
@@ -2013,9 +2027,9 @@ ASTfunction_call::typecheck(TypeSpec expected)
|
||||
if (Strutil::iequals(OSL_LEGACY, "use"))
|
||||
m_sym = legacy;
|
||||
if (as_warning)
|
||||
warningf("overload chosen differs from OSL 1.9\n%s", errmsg);
|
||||
warningfmt("overload chosen differs from OSL 1.9\n{}", errmsg);
|
||||
else
|
||||
errorf("overload chosen differs from OSL 1.9\n%s", errmsg);
|
||||
errorfmt("overload chosen differs from OSL 1.9\n{}", errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2053,8 +2067,8 @@ ASTfunction_call::typecheck(TypeSpec expected)
|
||||
if (formal->is_output()
|
||||
&& !check_symbol_writeability(a, true, &dest_sym)) {
|
||||
OSL_DASSERT(dest_sym);
|
||||
warningf(
|
||||
"cannot write to non-output parameter \"%s\", as passed to function %s() as arg %d (output parameter \"%s\")",
|
||||
warningfmt(
|
||||
"cannot write to non-output parameter \"{}\", as passed to function {}() as arg {} (output parameter \"{}\")",
|
||||
dest_sym->name(), func()->name(), i + 1, formal->name());
|
||||
}
|
||||
}
|
||||
@@ -2062,8 +2076,8 @@ ASTfunction_call::typecheck(TypeSpec expected)
|
||||
|
||||
if (is_user_function()) {
|
||||
if (func()->number_of_returns() == 0 && !func()->typespec().is_void()) {
|
||||
errorf("non-void function \"%s\" had no 'return' statement.",
|
||||
func()->name());
|
||||
errorfmt("non-void function \"{}\" had no 'return' statement.",
|
||||
func()->name());
|
||||
}
|
||||
} else {
|
||||
// built-in
|
||||
@@ -2318,7 +2332,7 @@ OSLCompilerImpl::code_from_type(TypeSpec type) const
|
||||
std::string out;
|
||||
TypeDesc elem = type.elementtype().simpletype();
|
||||
if (type.is_structure() || type.is_structure_array()) {
|
||||
out = Strutil::sprintf("S%d", type.structure());
|
||||
out = Strutil::fmt::format("S{}", type.structure());
|
||||
} else if (type.is_closure() || type.is_closure_array()) {
|
||||
out = 'C';
|
||||
} else {
|
||||
@@ -2352,7 +2366,7 @@ OSLCompilerImpl::code_from_type(TypeSpec type) const
|
||||
if (type.is_unsized_array())
|
||||
out += "[]";
|
||||
else
|
||||
out += Strutil::sprintf("[%d]", type.arraylength());
|
||||
out += Strutil::fmt::format("[{}]", type.arraylength());
|
||||
}
|
||||
|
||||
return out;
|
||||
|
||||
+112
-107
@@ -7,7 +7,9 @@
|
||||
set ( liboslexec_target_srcs
|
||||
wide/wide_opalgebraic
|
||||
wide/wide_opcolor
|
||||
wide/wide_opclosure
|
||||
wide/wide_opdictionary
|
||||
wide/wide_ophash
|
||||
wide/wide_opmatrix
|
||||
wide/wide_opmessage
|
||||
wide/wide_opnoise
|
||||
@@ -47,8 +49,10 @@ set ( liboslexec_target_srcs
|
||||
wide/wide_opnoise_usimplex_deriv_float
|
||||
wide/wide_opnoise_usimplex_Vec3
|
||||
wide/wide_opnoise_usimplex_deriv_Vec3
|
||||
wide/wide_oppointcloud
|
||||
wide/wide_opspline
|
||||
wide/wide_opstring
|
||||
wide/wide_optest_float
|
||||
wide/wide_optexture
|
||||
wide/wide_optranscendental
|
||||
wide/wide_optrigonometric
|
||||
@@ -94,6 +98,12 @@ set ( liboslexec_override_limits
|
||||
../liboslnoise/wide/wide_gabor3_isotropic_enabled
|
||||
)
|
||||
|
||||
set ( liboslexec_require_INF_NaN
|
||||
shadingsys.cpp
|
||||
wide/wide_shadingsys
|
||||
wide/wide_optest_float
|
||||
)
|
||||
|
||||
set (local_lib oslexec)
|
||||
set (lib_src
|
||||
shadingsys.cpp closure.cpp
|
||||
@@ -111,6 +121,7 @@ set (lib_src
|
||||
shadeimage.cpp
|
||||
backendllvm.cpp
|
||||
llvm_gen.cpp llvm_instance.cpp llvm_util.cpp
|
||||
rs_fallback.cpp
|
||||
)
|
||||
if (BUILD_BATCHED)
|
||||
list(APPEND lib_src
|
||||
@@ -141,93 +152,34 @@ FLEX_BISON ( ../liboslcomp/osllex.l ../liboslcomp/oslgram.y osl lib_src compiler
|
||||
|
||||
set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS" )
|
||||
|
||||
macro ( LLVM_COMPILE llvm_src srclist )
|
||||
get_filename_component ( llvmsrc_we ${llvm_src} NAME_WE )
|
||||
set ( llvm_asm "${CMAKE_CURRENT_BINARY_DIR}/${llvmsrc_we}.s" )
|
||||
set ( llvm_bc "${CMAKE_CURRENT_BINARY_DIR}/${llvmsrc_we}.bc" )
|
||||
set ( llvm_bc_cpp "${CMAKE_CURRENT_BINARY_DIR}/${llvmsrc_we}.bc.cpp" )
|
||||
if (VERBOSE)
|
||||
message (STATUS "LLVM_COMPILE in=${llvm_src}")
|
||||
message (STATUS "LLVM_COMPILE asm=${llvm_asm}")
|
||||
message (STATUS "LLVM_COMPILE bc=${llvm_bc}")
|
||||
message (STATUS "LLVM_COMPILE cpp=${llvm_bc_cpp}")
|
||||
endif ()
|
||||
set ( ${srclist} ${${srclist}} ${llvm_bc_cpp} )
|
||||
get_property (CURRENT_DEFINITIONS DIRECTORY PROPERTY COMPILE_DEFINITIONS)
|
||||
if (VERBOSE)
|
||||
message (STATUS "Current #defines are ${CURRENT_DEFINITIONS}")
|
||||
endif ()
|
||||
foreach (def ${CURRENT_DEFINITIONS})
|
||||
set (LLVM_COMPILE_FLAGS ${LLVM_COMPILE_FLAGS} "-D${def}")
|
||||
endforeach()
|
||||
set (LLVM_COMPILE_FLAGS ${LLVM_COMPILE_FLAGS} ${SIMD_COMPILE_FLAGS} ${CSTD_FLAGS} ${TOOLCHAIN_FLAGS})
|
||||
|
||||
# Figure out what program we will use to make the bitcode.
|
||||
if (NOT LLVM_BC_GENERATOR)
|
||||
find_program (LLVM_BC_GENERATOR NAMES "clang++"
|
||||
PATHS "${LLVM_DIRECTORY}/bin"
|
||||
NO_CMAKE_PATH NO_DEFAULT_PATH NO_CMAKE_SYSTEM_PATH
|
||||
NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_ENVIRONMENT_PATH)
|
||||
endif ()
|
||||
# If that didn't work, look anywhere
|
||||
if (NOT LLVM_BC_GENERATOR)
|
||||
# Wasn't in their build, look anywhere
|
||||
find_program (LLVM_BC_GENERATOR NAMES clang++ llvm-g++)
|
||||
endif ()
|
||||
|
||||
if (NOT LLVM_BC_GENERATOR)
|
||||
message (FATAL_ERROR "You must have a valid llvm bitcode generator (clang++) somewhere.")
|
||||
endif ()
|
||||
if (VERBOSE)
|
||||
message (STATUS "Using LLVM_BC_GENERATOR ${LLVM_BC_GENERATOR} to generate bitcode.")
|
||||
macro ( REQUIRE_INF_NAN SRC )
|
||||
if (CMAKE_COMPILER_IS_INTELCLANG)
|
||||
# if -ffast-math is enabled to to the underlying compiler,
|
||||
# inf's and NaN's may not be handled properly (by design)
|
||||
if (MSVC)
|
||||
set_property(SOURCE ${SRC} APPEND PROPERTY COMPILE_OPTIONS "/fp:precise")
|
||||
#message (STATUS "SOURCE ${SRC} APPEND PROPERTY COMPILE_OPTIONS /fp:precise")
|
||||
else ()
|
||||
#set_property(SOURCE $SRC} APPEND PROPERTY COMPILE_OPTIONS "-fp-model=precise")
|
||||
# Disabling fast-math should be enough to enable proper support of INF and NaN
|
||||
#set_property(SOURCE ${SRC} APPEND PROPERTY COMPILE_OPTIONS "-fno-fast-math")
|
||||
# We can explicitly honor inf, nans, and signed 0's
|
||||
set_property(SOURCE ${SRC} APPEND PROPERTY COMPILE_OPTIONS
|
||||
"-fhonor-infinities"
|
||||
"-fhonor-nans"
|
||||
"-fsigned-zeros")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Fix specific problem I had on new Apple systems (e.g. Mavericks) with
|
||||
# LLVM/libc++ installed -- for some reason, LLVM 3.4 wasn't finding it,
|
||||
# so in that specific case, append another -I to point it in the right
|
||||
# direction.
|
||||
#if (APPLE AND ${LLVM_BC_GENERATOR} MATCHES ".*clang.*")
|
||||
# exec_program ( "${LLVM_BC_GENERATOR}" ARGS --version OUTPUT_VARIABLE MY_CLANG_VERSION )
|
||||
# string (REGEX REPLACE "clang version ([0-9][.][0-9]+).*" "\\1" MY_CLANG_VERSION "${MY_CLANG_VERSION}")
|
||||
# if ((${MY_CLANG_VERSION} VERSION_GREATER "3.3")
|
||||
# AND (EXISTS "/usr/lib/libc++.dylib")
|
||||
# AND (EXISTS "/Library/Developer/CommandLineTools/usr/lib/c++/v1"))
|
||||
# set (LLVM_COMPILE_FLAGS ${LLVM_COMPILE_FLAGS} "-I/Library/Developer/CommandLineTools/usr/lib/c++/v1")
|
||||
# endif ()
|
||||
#endif ()
|
||||
|
||||
list (TRANSFORM IMATH_INCLUDES PREPEND -I
|
||||
OUTPUT_VARIABLE ALL_IMATH_INCLUDES)
|
||||
list (TRANSFORM OPENEXR_INCLUDES PREPEND -I
|
||||
OUTPUT_VARIABLE ALL_OPENEXR_INCLUDES)
|
||||
list (TRANSFORM OpenImageIO_INCLUDES PREPEND -I
|
||||
OUTPUT_VARIABLE ALL_OpenImageIO_INCLUDES)
|
||||
|
||||
# Command to turn the .cpp file into LLVM assembly language .s, into
|
||||
# LLVM bitcode .bc, then back into a C++ file with the bc embedded!
|
||||
add_custom_command ( OUTPUT ${llvm_bc_cpp}
|
||||
COMMAND ${LLVM_BC_GENERATOR}
|
||||
${LLVM_COMPILE_FLAGS}
|
||||
"-I${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
"-I${CMAKE_SOURCE_DIR}/src/include"
|
||||
"-I${CMAKE_BINARY_DIR}/include"
|
||||
${ALL_OpenImageIO_INCLUDES}
|
||||
${ALL_IMATH_INCLUDES}
|
||||
"-isystem ${Boost_INCLUDE_DIRS}"
|
||||
-DOSL_COMPILING_TO_BITCODE=1
|
||||
-Wno-deprecated-register
|
||||
# the following 2 warnings can be restored when all 3rd parties have fixed their export macros
|
||||
# (dllimport attribute is not supported when compiling for Cuda and triggers a ton of warnings)
|
||||
-Wno-ignored-attributes -Wno-unknown-attributes
|
||||
-O3 -fno-math-errno -S -emit-llvm -o ${llvm_asm} ${llvm_src}
|
||||
COMMAND "${LLVM_DIRECTORY}/bin/llvm-as" -f -o ${llvm_bc} ${llvm_asm}
|
||||
COMMAND python "${CMAKE_CURRENT_SOURCE_DIR}/serialize-bc.py" ${llvm_bc} ${llvm_bc_cpp} "osl_llvm_compiled_ops"
|
||||
MAIN_DEPENDENCY ${llvm_src}
|
||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/serialize-bc.py"
|
||||
${exec_headers} ${PROJECT_PUBLIC_HEADERS}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
endmacro ( )
|
||||
|
||||
# Apply complilation options as needed
|
||||
foreach(src ${lib_src})
|
||||
if (${src} IN_LIST liboslexec_require_INF_NaN)
|
||||
set(SRC "${CMAKE_CURRENT_SOURCE_DIR}/${src}")
|
||||
REQUIRE_INF_NAN ( ${SRC} )
|
||||
endif()
|
||||
endforeach(src)
|
||||
|
||||
macro ( CUDA_SHADEOPS_COMPILE srclist )
|
||||
# Add all of the "shadeops" sources that need to be compiled to LLVM bitcode for CUDA
|
||||
@@ -253,21 +205,31 @@ macro ( CUDA_SHADEOPS_COMPILE srclist )
|
||||
|
||||
# Link all of the individual LLVM bitcode files
|
||||
add_custom_command ( OUTPUT ${linked_shadeops_bc}
|
||||
COMMAND "${LLVM_DIRECTORY}/bin/llvm-link" -internalize ${shadeops_bc_list} -o ${linked_shadeops_bc}
|
||||
COMMAND ${LLVM_LINK_TOOL} -internalize ${shadeops_bc_list} -o ${linked_shadeops_bc}
|
||||
DEPENDS ${shadeops_bc_list} ${exec_headers} ${PROJECT_PUBLIC_HEADERS} ${shadeops_srcs}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
|
||||
# Serialize the linked bitcode into a CPP file and add it to the list of liboslexec soures
|
||||
# Serialize the linked bitcode into a CPP file and add it to the list of liboslexec sources
|
||||
add_custom_command ( OUTPUT ${shadeops_bc_cuda_cpp}
|
||||
COMMAND python "${CMAKE_CURRENT_SOURCE_DIR}/serialize-bc.py"
|
||||
COMMAND ${Python_EXECUTABLE} "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py"
|
||||
${linked_shadeops_bc} ${shadeops_bc_cuda_cpp} "osl_llvm_compiled_ops_cuda"
|
||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/serialize-bc.py" ${linked_shadeops_bc}
|
||||
DEPENDS "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py" ${linked_shadeops_bc}
|
||||
${exec_headers} ${PROJECT_PUBLIC_HEADERS}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||
endmacro ( )
|
||||
|
||||
if (USE_LLVM_BITCODE)
|
||||
LLVM_COMPILE ( llvm_ops.cpp lib_src )
|
||||
set (llvm_ops_srcs llvm_ops.cpp)
|
||||
EMBED_LLVM_BITCODE_IN_CPP ( "${llvm_ops_srcs}" "_host" "osl_llvm_compiled_ops" lib_src "")
|
||||
|
||||
set (rs_dependent_ops_srcs
|
||||
opmatrix.cpp
|
||||
)
|
||||
# Achieve the effect of absorbing osl_llvm_compiled_ops by adding its
|
||||
# sources to rs_dependent_ops_srcs which avoids having to do it at runtime.
|
||||
list (APPEND rs_dependent_ops_srcs ${llvm_ops_srcs})
|
||||
|
||||
EMBED_LLVM_BITCODE_IN_CPP ( "${rs_dependent_ops_srcs}" "_host_rs" "osl_llvm_compiled_rs_dependent_ops" lib_src "")
|
||||
|
||||
# Optionally repeat the bitcode compilation with CUDA-specific options
|
||||
if (CUDA_FOUND)
|
||||
@@ -349,9 +311,12 @@ foreach(batched_target ${BATCHED_TARGET_LIST})
|
||||
|
||||
list (APPEND TARGET_CXX_OPTS
|
||||
"/Qprec-div"
|
||||
"/Qopt-report:5"
|
||||
"/Qopenmp-simd"
|
||||
)
|
||||
if (VEC_REPORT)
|
||||
list (APPEND TARGET_CXX_OPTS "/Qopt-report:5")
|
||||
endif ()
|
||||
|
||||
|
||||
else ()
|
||||
if (${TARGET_OPT_ISA} STREQUAL "AVX512")
|
||||
@@ -375,16 +340,19 @@ foreach(batched_target ${BATCHED_TARGET_LIST})
|
||||
|
||||
list (APPEND TARGET_CXX_OPTS
|
||||
"-prec-div"
|
||||
"-qopt-report=5"
|
||||
"-qopenmp-simd"
|
||||
"-qno-opt-multiple-gather-scatter-by-shuffles"
|
||||
)
|
||||
|
||||
if (VEC_REPORT)
|
||||
list (APPEND TARGET_CXX_OPTS "-qopt-report=5")
|
||||
endif ()
|
||||
|
||||
endif ()
|
||||
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")
|
||||
@@ -402,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.
|
||||
@@ -419,14 +393,27 @@ foreach(batched_target ${BATCHED_TARGET_LIST})
|
||||
# it as soon as clang addresses this issue.
|
||||
list (APPEND TARGET_CXX_OPTS "-fno-unroll-loops")
|
||||
|
||||
list (APPEND TARGET_CXX_OPTS "-fopenmp")
|
||||
if (CMAKE_COMPILER_IS_INTELCLANG)
|
||||
# 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 ()
|
||||
|
||||
# Uncomment next section to investigate failures in vectorization
|
||||
#list (APPEND TARGET_CXX_OPTS
|
||||
# "-Rpass=loop-vectorize"
|
||||
# "-Rpass-analysis=loop-vectorize"
|
||||
# "-Rpass-missed=loop-vectorize"
|
||||
# )
|
||||
if (VEC_REPORT)
|
||||
if (CMAKE_COMPILER_IS_INTELCLANG)
|
||||
list (APPEND TARGET_CXX_OPTS
|
||||
"-qopt-report=3"
|
||||
)
|
||||
else ()
|
||||
list (APPEND TARGET_CXX_OPTS
|
||||
"-Rpass=loop-vectorize"
|
||||
"-Rpass-analysis=loop-vectorize"
|
||||
# Uncomment next section to investigate failures in vectorization
|
||||
#"-Rpass-missed=loop-vectorize"
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
|
||||
@@ -454,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")
|
||||
@@ -481,6 +474,11 @@ foreach(batched_target ${BATCHED_TARGET_LIST})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (${target_src} IN_LIST liboslexec_require_INF_NaN)
|
||||
REQUIRE_INF_NAN ( ${TARGET_SRC} )
|
||||
endif()
|
||||
|
||||
endforeach(target_src)
|
||||
|
||||
add_library ( ${batched_target_lib} MODULE ${TARGET_LIB_SOURCES} )
|
||||
@@ -494,6 +492,11 @@ foreach(batched_target ${BATCHED_TARGET_LIST})
|
||||
PUBLIC
|
||||
OpenImageIO::OpenImageIO
|
||||
)
|
||||
if (partio_FOUND)
|
||||
target_link_libraries(${batched_target_lib} PRIVATE partio::partio)
|
||||
target_compile_definitions (${batched_target_lib} PRIVATE USE_PARTIO=1)
|
||||
endif ()
|
||||
|
||||
endforeach(batched_target)
|
||||
|
||||
add_library (${local_lib} ${lib_src})
|
||||
@@ -553,20 +556,22 @@ target_link_libraries (${local_lib}
|
||||
)
|
||||
|
||||
target_compile_features (${local_lib}
|
||||
PUBLIC cxx_std_${CMAKE_CXX_STANDARD})
|
||||
INTERFACE cxx_std_${DOWNSTREAM_CXX_STANDARD})
|
||||
|
||||
set (link_flags "${VISIBILITY_MAP_COMMAND} ${EXTRA_DSO_LINK_ARGS}")
|
||||
if (UNIX AND NOT APPLE)
|
||||
# Hide symbols from any static dependent libraries embedded here.
|
||||
set (link_flags "${link_flags} -Wl,--exclude-libs,ALL")
|
||||
endif ()
|
||||
|
||||
set_target_properties (${local_lib}
|
||||
PROPERTIES
|
||||
VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}
|
||||
SOVERSION ${SOVERSION}
|
||||
SOVERSION ${SOVERSION}
|
||||
OUTPUT_NAME ${local_lib}${OSL_LIBNAME_SUFFIX}
|
||||
LINK_FLAGS ${link_flags}
|
||||
)
|
||||
|
||||
if (VISIBILITY_MAP_COMMAND)
|
||||
set_property (TARGET ${local_lib}
|
||||
APPEND PROPERTY LINK_FLAGS ${VISIBILITY_MAP_COMMAND})
|
||||
endif ()
|
||||
|
||||
# add_dependencies (${local_lib} "${CMAKE_SOURCE_DIR}/src/build-scripts/hidesymbols.map")
|
||||
|
||||
foreach(batched_target_lib ${BATCHED_TARGET_LIBS})
|
||||
|
||||
+28
-26
@@ -12,7 +12,7 @@ OSL_NAMESPACE_ENTER
|
||||
|
||||
|
||||
void
|
||||
AovOutput::flush(void *flush_data)
|
||||
AovOutput::flush(void* flush_data)
|
||||
{
|
||||
if (!aov)
|
||||
return;
|
||||
@@ -21,7 +21,7 @@ AovOutput::flush(void *flush_data)
|
||||
has_color = true;
|
||||
}
|
||||
if (neg_alpha) {
|
||||
alpha = 1.0f - alpha;
|
||||
alpha = 1.0f - alpha;
|
||||
has_alpha = true;
|
||||
}
|
||||
|
||||
@@ -31,10 +31,10 @@ AovOutput::flush(void *flush_data)
|
||||
|
||||
|
||||
void
|
||||
AccumRule::accum(const Color3 &color, std::vector<AovOutput> &outputs)const
|
||||
AccumRule::accum(const Color3& color, std::vector<AovOutput>& outputs) const
|
||||
{
|
||||
if (m_save_to_alpha) {
|
||||
outputs[m_outidx].alpha += (color.x + color.y + color.z) * 1.0f/3.0f;
|
||||
outputs[m_outidx].alpha += (color.x + color.y + color.z) * 1.0f / 3.0f;
|
||||
outputs[m_outidx].has_alpha = true;
|
||||
} else {
|
||||
outputs[m_outidx].color += color;
|
||||
@@ -44,7 +44,6 @@ AccumRule::accum(const Color3 &color, std::vector<AovOutput> &outputs)const
|
||||
|
||||
|
||||
|
||||
|
||||
AccumAutomata::~AccumAutomata()
|
||||
{
|
||||
for (auto& r : m_rules)
|
||||
@@ -53,21 +52,22 @@ AccumAutomata::~AccumAutomata()
|
||||
|
||||
|
||||
|
||||
AccumRule *
|
||||
AccumAutomata::addRule(const char *pattern, int outidx, bool toalpha)
|
||||
AccumRule*
|
||||
AccumAutomata::addRule(const char* pattern, int outidx, bool toalpha)
|
||||
{
|
||||
// First parse the lpexp and see if it fails
|
||||
Parser parser(&m_user_events, &m_user_scatterings);
|
||||
LPexp *e = parser.parse(pattern);
|
||||
LPexp* e = parser.parse(pattern);
|
||||
if (parser.error()) {
|
||||
std::cerr << "[pathexp] Parse error" << parser.getErrorMsg() << " at char " << parser.getErrorPos() << std::endl;
|
||||
std::cerr << "[pathexp] Parse error" << parser.getErrorMsg()
|
||||
<< " at char " << parser.getErrorPos() << std::endl;
|
||||
delete e;
|
||||
return NULL;
|
||||
}
|
||||
m_accumrules.emplace_back(outidx, toalpha);
|
||||
// it is a list, so as long as we don't remove it from there, the pointer is valid
|
||||
void *rule = (void *)&(m_accumrules.back());
|
||||
m_rules.push_back (new lpexp::Rule (e, rule));
|
||||
void* rule = (void*)&(m_accumrules.back());
|
||||
m_rules.push_back(new lpexp::Rule(e, rule));
|
||||
return &(m_accumrules.back());
|
||||
}
|
||||
|
||||
@@ -91,28 +91,29 @@ AccumAutomata::compile()
|
||||
|
||||
|
||||
void
|
||||
AccumAutomata::accum(int state, const Color3 &color, std::vector<AovOutput> &outputs)const
|
||||
AccumAutomata::accum(int state, const Color3& color,
|
||||
std::vector<AovOutput>& outputs) const
|
||||
{
|
||||
// get the rules field, the underlying type is a std::vector
|
||||
int nrules = 0;
|
||||
void * const * rules = getRulesInState(state, nrules);
|
||||
int nrules = 0;
|
||||
void* const* rules = getRulesInState(state, nrules);
|
||||
// Iterate the vector
|
||||
for (int i = 0; i < nrules; ++i)
|
||||
// Let the accumulator rule do its job
|
||||
((AccumRule *)(rules[i]))->accum(color, outputs);
|
||||
((AccumRule*)(rules[i]))->accum(color, outputs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Accumulator::Accumulator(const AccumAutomata *accauto)
|
||||
Accumulator::Accumulator(const AccumAutomata* accauto)
|
||||
: m_accum_automata(accauto)
|
||||
{
|
||||
const auto &rules = m_accum_automata->getRuleList();
|
||||
const auto& rules = m_accum_automata->getRuleList();
|
||||
// Make sure we have as many outputs as the rules need
|
||||
int maxouts = 0;
|
||||
for (const auto& i : rules)
|
||||
maxouts = std::max(i.getOutputIndex(), maxouts);
|
||||
m_outputs.resize(maxouts+1);
|
||||
m_outputs.resize(maxouts + 1);
|
||||
|
||||
// 0 is our initial state always
|
||||
m_state = 0;
|
||||
@@ -121,10 +122,10 @@ Accumulator::Accumulator(const AccumAutomata *accauto)
|
||||
|
||||
|
||||
void
|
||||
Accumulator::setAov(int outidx, Aov *aov, bool neg_color, bool neg_alpha)
|
||||
Accumulator::setAov(int outidx, Aov* aov, bool neg_color, bool neg_alpha)
|
||||
{
|
||||
OSL_ASSERT (0 <= outidx && outidx < (int) m_outputs.size());
|
||||
m_outputs[outidx].aov = aov;
|
||||
OSL_ASSERT(0 <= outidx && outidx < (int)m_outputs.size());
|
||||
m_outputs[outidx].aov = aov;
|
||||
m_outputs[outidx].neg_color = neg_color;
|
||||
m_outputs[outidx].neg_alpha = neg_alpha;
|
||||
}
|
||||
@@ -134,7 +135,7 @@ Accumulator::setAov(int outidx, Aov *aov, bool neg_color, bool neg_alpha)
|
||||
void
|
||||
Accumulator::pushState()
|
||||
{
|
||||
OSL_ASSERT (m_state >= 0);
|
||||
OSL_ASSERT(m_state >= 0);
|
||||
m_stack.push(m_state);
|
||||
}
|
||||
|
||||
@@ -143,7 +144,7 @@ Accumulator::pushState()
|
||||
void
|
||||
Accumulator::popState()
|
||||
{
|
||||
OSL_ASSERT (m_stack.size());
|
||||
OSL_ASSERT(m_stack.size());
|
||||
m_state = m_stack.top();
|
||||
m_stack.pop();
|
||||
}
|
||||
@@ -160,7 +161,7 @@ Accumulator::move(ustring symbol)
|
||||
|
||||
|
||||
void
|
||||
Accumulator::move(const ustring *symbols)
|
||||
Accumulator::move(const ustring* symbols)
|
||||
{
|
||||
while (m_state >= 0 && symbols && *symbols != Labels::NONE)
|
||||
m_state = m_accum_automata->getTransition(m_state, *(symbols++));
|
||||
@@ -169,7 +170,8 @@ Accumulator::move(const ustring *symbols)
|
||||
|
||||
|
||||
void
|
||||
Accumulator::move(ustring event, ustring scatt, const ustring *custom, ustring stop)
|
||||
Accumulator::move(ustring event, ustring scatt, const ustring* custom,
|
||||
ustring stop)
|
||||
{
|
||||
if (m_state >= 0)
|
||||
m_state = m_accum_automata->getTransition(m_state, event);
|
||||
@@ -193,7 +195,7 @@ Accumulator::begin()
|
||||
|
||||
|
||||
void
|
||||
Accumulator::end(void *flush_data)
|
||||
Accumulator::end(void* flush_data)
|
||||
{
|
||||
for (size_t i = 0; i < m_outputs.size(); ++i)
|
||||
m_outputs[i].flush(flush_data);
|
||||
|
||||
@@ -10,67 +10,63 @@ using namespace OSL;
|
||||
|
||||
#define END_AOV 65535
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *path[16];
|
||||
typedef struct {
|
||||
const char* path[16];
|
||||
int expected[8];
|
||||
} TestPath;
|
||||
|
||||
|
||||
// This is a fake AOV implementation. It will just keep track
|
||||
// of what test cases wrote to it
|
||||
class MyAov final : public Aov
|
||||
{
|
||||
public:
|
||||
MyAov(const TestPath *test, int id)
|
||||
{
|
||||
// Init for the test case array. For each test case set a bool
|
||||
// in m_expected marking wether this AOV should get some color
|
||||
// from that test or not.
|
||||
for (int i = 0; test[i].path[0]; ++i) { // iterate test cases
|
||||
m_expected.push_back(false); // false by default
|
||||
for (const int *expected = test[i].expected; *expected != END_AOV; ++expected)
|
||||
if (*expected == id)
|
||||
// if the AOV id is on the test's expected list, set it to true
|
||||
m_expected[i] = true;
|
||||
}
|
||||
m_received.resize(m_expected.size());
|
||||
class MyAov final : public Aov {
|
||||
public:
|
||||
MyAov(const TestPath* test, int id)
|
||||
{
|
||||
// Init for the test case array. For each test case set a bool
|
||||
// in m_expected marking whether this AOV should get some color
|
||||
// from that test or not.
|
||||
for (int i = 0; test[i].path[0]; ++i) { // iterate test cases
|
||||
m_expected.push_back(false); // false by default
|
||||
for (const int* expected = test[i].expected; *expected != END_AOV;
|
||||
++expected)
|
||||
if (*expected == id)
|
||||
// if the AOV id is on the test's expected list, set it to true
|
||||
m_expected[i] = true;
|
||||
}
|
||||
virtual ~MyAov() {}
|
||||
m_received.resize(m_expected.size());
|
||||
}
|
||||
virtual ~MyAov() {}
|
||||
|
||||
virtual void write(void *flush_data, Color3 &color, float /*alpha*/,
|
||||
bool has_color, bool /*has_alpha*/)
|
||||
{
|
||||
// our custom argument to write is the rule's number so we
|
||||
// can check what. But you normally would pass information
|
||||
// about the pixel.
|
||||
long int testno = (long int)flush_data;
|
||||
if (has_color && color.x > 0)
|
||||
// only mrk with true if there is a positive color present
|
||||
m_received[testno] = true;
|
||||
else
|
||||
m_received[testno] = false;
|
||||
}
|
||||
virtual void write(void* flush_data, Color3& color, float /*alpha*/,
|
||||
bool has_color, bool /*has_alpha*/)
|
||||
{
|
||||
// our custom argument to write is the rule's number so we
|
||||
// can check what. But you normally would pass information
|
||||
// about the pixel.
|
||||
size_t testno = reinterpret_cast<size_t>(flush_data);
|
||||
if (has_color && color.x > 0)
|
||||
// only mrk with true if there is a positive color present
|
||||
m_received[testno] = true;
|
||||
else
|
||||
m_received[testno] = false;
|
||||
}
|
||||
|
||||
bool check()
|
||||
{
|
||||
return m_expected == m_received;
|
||||
}
|
||||
bool check() { return m_expected == m_received; }
|
||||
|
||||
protected:
|
||||
|
||||
std::vector<bool> m_expected;
|
||||
std::vector<bool> m_received;
|
||||
protected:
|
||||
std::vector<bool> m_expected;
|
||||
std::vector<bool> m_received;
|
||||
};
|
||||
|
||||
// Simulate the tracing of a path with the accumulator
|
||||
void simulate(Accumulator &accum, const char **events, int testno)
|
||||
void
|
||||
simulate(Accumulator& accum, const char** events, size_t testno)
|
||||
{
|
||||
accum.begin();
|
||||
accum.pushState();
|
||||
// for each ray stop in the path (see test cases) ...
|
||||
while (*events) {
|
||||
const char *e = *events;
|
||||
const char* e = *events;
|
||||
// for each label in this hit
|
||||
while (*e) {
|
||||
ustring sym(e, 1);
|
||||
@@ -86,12 +82,13 @@ void simulate(Accumulator &accum, const char **events, int testno)
|
||||
accum.accum(Color3(1, 1, 1));
|
||||
// Restore state and flush
|
||||
accum.popState();
|
||||
accum.end((void *)(long int)testno);
|
||||
accum.end(reinterpret_cast<void*>(testno));
|
||||
}
|
||||
|
||||
int main()
|
||||
int
|
||||
main()
|
||||
{
|
||||
// Some constants to avoid refering to AOV's by number
|
||||
// Some constants to avoid referring to AOV's by number
|
||||
const int beauty = 0;
|
||||
const int diffuse2_3 = 1;
|
||||
const int light3 = 2;
|
||||
@@ -107,20 +104,29 @@ int main()
|
||||
// The actual test cases. Each one is a list of ray hits with some labels.
|
||||
// We use 1 char labels for convenience. They will be converted to ustrings
|
||||
// by simulate. And then a list of expected AOV's for each.
|
||||
TestPath test[] = { { { "C_", "TS", "TS", "RD", "L_", NULL }, { beauty, specular, nocaustic, END_AOV} },
|
||||
{ { "C_", "TS", "TS", "RD", "RG", "L_", NULL }, { END_AOV } },
|
||||
{ { "C_", "TS", "TS", "RD", "RD", "L_", NULL }, { beauty, specular, diffuse2_3, nocaustic, END_AOV } },
|
||||
{ { "C_", "RG", "RD", "RG", "RD", "RG", "RD", "L_", NULL }, { END_AOV } },
|
||||
{ { "C_", "RG", "RD", "RG", "RD", "L_", NULL }, { nocaustic, END_AOV } },
|
||||
{ { "C_", "RD", "RD", "L_", NULL }, { beauty, diffuse, diffuse2_3, nocaustic, END_AOV } },
|
||||
{ { "C_", "RD", "RS", "RD", "L_", NULL }, { nocaustic, END_AOV } },
|
||||
{ { "C_", "RD", "Ts", "L_", NULL }, { transpshadow, END_AOV } },
|
||||
{ { "C_", "TS", "TS", "RD", "L_3", NULL }, { beauty, specular, light3, nocaustic, END_AOV } },
|
||||
{ { "C_", "RD1", "RD", "L_", NULL }, { beauty, diffuse, diffuse2_3, object_1, nocaustic, END_AOV } },
|
||||
{ { "C_", "RS", "RD", "RG", "L_", NULL }, { END_AOV } },
|
||||
{ { "C_", "RS", "RD", "L_", NULL }, { beauty, specular, reflections, nocaustic, END_AOV } },
|
||||
{ { "C_", "RD", "RY", "RD", "U_", NULL }, { custom, END_AOV } },
|
||||
{ { NULL }, { END_AOV } } };
|
||||
TestPath test[]
|
||||
= { { { "C_", "TS", "TS", "RD", "L_", NULL },
|
||||
{ beauty, specular, nocaustic, END_AOV } },
|
||||
{ { "C_", "TS", "TS", "RD", "RG", "L_", NULL }, { END_AOV } },
|
||||
{ { "C_", "TS", "TS", "RD", "RD", "L_", NULL },
|
||||
{ beauty, specular, diffuse2_3, nocaustic, END_AOV } },
|
||||
{ { "C_", "RG", "RD", "RG", "RD", "RG", "RD", "L_", NULL },
|
||||
{ END_AOV } },
|
||||
{ { "C_", "RG", "RD", "RG", "RD", "L_", NULL },
|
||||
{ nocaustic, END_AOV } },
|
||||
{ { "C_", "RD", "RD", "L_", NULL },
|
||||
{ beauty, diffuse, diffuse2_3, nocaustic, END_AOV } },
|
||||
{ { "C_", "RD", "RS", "RD", "L_", NULL }, { nocaustic, END_AOV } },
|
||||
{ { "C_", "RD", "Ts", "L_", NULL }, { transpshadow, END_AOV } },
|
||||
{ { "C_", "TS", "TS", "RD", "L_3", NULL },
|
||||
{ beauty, specular, light3, nocaustic, END_AOV } },
|
||||
{ { "C_", "RD1", "RD", "L_", NULL },
|
||||
{ beauty, diffuse, diffuse2_3, object_1, nocaustic, END_AOV } },
|
||||
{ { "C_", "RS", "RD", "RG", "L_", NULL }, { END_AOV } },
|
||||
{ { "C_", "RS", "RD", "L_", NULL },
|
||||
{ beauty, specular, reflections, nocaustic, END_AOV } },
|
||||
{ { "C_", "RD", "RY", "RD", "U_", NULL }, { custom, END_AOV } },
|
||||
{ { NULL }, { END_AOV } } };
|
||||
|
||||
// Create our fake testing AOV's
|
||||
std::vector<MyAov> aovs;
|
||||
@@ -133,21 +139,21 @@ int main()
|
||||
automata.addEventType(ustring("U"));
|
||||
automata.addScatteringType(ustring("Y"));
|
||||
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C[SG]*D*L", beauty));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C[SG]*D{2,3}L", diffuse2_3));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C[SG]*D*<L.'3'>", light3));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C[SG]*D*L", beauty));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C[SG]*D{2,3}L", diffuse2_3));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C[SG]*D*<L.'3'>", light3));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C[SG]*<.D'1'>D*L", object_1));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C<.[SG]>+D*L", specular));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("CD+L", diffuse));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("CD+<Ts>L", transpshadow));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C<R[^D]>+D*L", reflections));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C([SG]*D){1,2}L", nocaustic));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("CDY+U", custom));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C<.[SG]>+D*L", specular));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("CD+L", diffuse));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("CD+<Ts>L", transpshadow));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C<R[^D]>+D*L", reflections));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("C([SG]*D){1,2}L", nocaustic));
|
||||
OIIO_CHECK_ASSERT(automata.addRule("CDY+U", custom));
|
||||
|
||||
automata.compile();
|
||||
|
||||
// now create the accumulator
|
||||
Accumulator accum (&automata);
|
||||
Accumulator accum(&automata);
|
||||
|
||||
// and set the AOV's for each id (beauty, diffuse2_3, etc ...)
|
||||
for (int i = 0; i < naovs; ++i)
|
||||
@@ -159,15 +165,15 @@ int main()
|
||||
|
||||
// And check. We unroll this loop for boost to give us a useful
|
||||
// error in case they fail
|
||||
OIIO_CHECK_ASSERT(aovs[beauty ].check());
|
||||
OIIO_CHECK_ASSERT(aovs[diffuse2_3 ].check());
|
||||
OIIO_CHECK_ASSERT(aovs[light3 ].check());
|
||||
OIIO_CHECK_ASSERT(aovs[object_1 ].check());
|
||||
OIIO_CHECK_ASSERT(aovs[specular ].check());
|
||||
OIIO_CHECK_ASSERT(aovs[diffuse ].check());
|
||||
OIIO_CHECK_ASSERT(aovs[beauty].check());
|
||||
OIIO_CHECK_ASSERT(aovs[diffuse2_3].check());
|
||||
OIIO_CHECK_ASSERT(aovs[light3].check());
|
||||
OIIO_CHECK_ASSERT(aovs[object_1].check());
|
||||
OIIO_CHECK_ASSERT(aovs[specular].check());
|
||||
OIIO_CHECK_ASSERT(aovs[diffuse].check());
|
||||
OIIO_CHECK_ASSERT(aovs[transpshadow].check());
|
||||
OIIO_CHECK_ASSERT(aovs[reflections ].check());
|
||||
OIIO_CHECK_ASSERT(aovs[nocaustic ].check());
|
||||
OIIO_CHECK_ASSERT(aovs[reflections].check());
|
||||
OIIO_CHECK_ASSERT(aovs[nocaustic].check());
|
||||
|
||||
std::cout << "Light expressions check OK" << std::endl;
|
||||
return unit_test_failures;
|
||||
|
||||
+153
-100
@@ -13,17 +13,18 @@ OSL_NAMESPACE_ENTER
|
||||
namespace Strutil = OIIO::Strutil;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf sprintf_s
|
||||
# define snprintf sprintf_s
|
||||
#endif
|
||||
|
||||
ustring lambda("__lambda__");
|
||||
|
||||
void
|
||||
NdfAutomata::State::getTransitions(ustring symbol, IntSet &out_states)const
|
||||
NdfAutomata::State::getTransitions(ustring symbol, IntSet& out_states) const
|
||||
{
|
||||
SymbolToIntList::const_iterator s = m_symbol_trans.find(symbol);
|
||||
if (s != m_symbol_trans.end())
|
||||
for (IntSet::const_iterator i = s->second.begin(); i != s->second.end(); ++i)
|
||||
for (IntSet::const_iterator i = s->second.begin(); i != s->second.end();
|
||||
++i)
|
||||
out_states.insert(*i);
|
||||
if (m_wildcard && m_wildcard->matches(symbol))
|
||||
out_states.insert(m_wildcard_trans);
|
||||
@@ -32,16 +33,15 @@ NdfAutomata::State::getTransitions(ustring symbol, IntSet &out_states)const
|
||||
|
||||
static IntSet _emptyset;
|
||||
|
||||
std::pair <IntSet::const_iterator, IntSet::const_iterator>
|
||||
NdfAutomata::State::getLambdaTransitions ()const
|
||||
std::pair<IntSet::const_iterator, IntSet::const_iterator>
|
||||
NdfAutomata::State::getLambdaTransitions() const
|
||||
{
|
||||
std::pair <IntSet::const_iterator, IntSet::const_iterator> res;
|
||||
std::pair<IntSet::const_iterator, IntSet::const_iterator> res;
|
||||
SymbolToIntList::const_iterator s = m_symbol_trans.find(lambda);
|
||||
if (s != m_symbol_trans.end()) {
|
||||
res.first = s->second.begin();
|
||||
res.first = s->second.begin();
|
||||
res.second = s->second.end();
|
||||
}
|
||||
else
|
||||
} else
|
||||
// We use a static empty list to return an empty range
|
||||
res.first = res.second = _emptyset.end();
|
||||
return res;
|
||||
@@ -50,7 +50,7 @@ NdfAutomata::State::getLambdaTransitions ()const
|
||||
|
||||
|
||||
void
|
||||
NdfAutomata::State::addTransition(ustring symbol, NdfAutomata::State *state)
|
||||
NdfAutomata::State::addTransition(ustring symbol, NdfAutomata::State* state)
|
||||
{
|
||||
m_symbol_trans[symbol].insert(state->m_id);
|
||||
}
|
||||
@@ -58,24 +58,26 @@ NdfAutomata::State::addTransition(ustring symbol, NdfAutomata::State *state)
|
||||
|
||||
|
||||
void
|
||||
NdfAutomata::State::addWildcardTransition(Wildcard *wildcard, NdfAutomata::State *state)
|
||||
NdfAutomata::State::addWildcardTransition(Wildcard* wildcard,
|
||||
NdfAutomata::State* state)
|
||||
{
|
||||
if (m_wildcard)
|
||||
std::cerr << "[pathexp] redefining wildcard transition" << std::endl;
|
||||
m_wildcard = wildcard;
|
||||
m_wildcard = wildcard;
|
||||
m_wildcard_trans = state->m_id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string
|
||||
NdfAutomata::State::tostr()const
|
||||
NdfAutomata::State::tostr() const
|
||||
{
|
||||
std::string s = "";
|
||||
// output the transitions
|
||||
for (SymbolToIntList::const_iterator i = m_symbol_trans.begin(); i != m_symbol_trans.end(); ++i) {
|
||||
ustring sym = i->first;
|
||||
const IntSet &dest = i->second;
|
||||
for (SymbolToIntList::const_iterator i = m_symbol_trans.begin();
|
||||
i != m_symbol_trans.end(); ++i) {
|
||||
ustring sym = i->first;
|
||||
const IntSet& dest = i->second;
|
||||
if (s.size())
|
||||
s += " ";
|
||||
if (sym == lambda)
|
||||
@@ -84,9 +86,9 @@ NdfAutomata::State::tostr()const
|
||||
s += sym.c_str();
|
||||
s += ":{";
|
||||
for (IntSet::const_iterator j = dest.begin(); j != dest.end(); ++j) {
|
||||
if (s[s.size()-1] != '{')
|
||||
if (s[s.size() - 1] != '{')
|
||||
s += ", ";
|
||||
s += Strutil::sprintf("%d", *j);
|
||||
s += Strutil::to_string(*j);
|
||||
}
|
||||
s += "}";
|
||||
}
|
||||
@@ -100,7 +102,8 @@ NdfAutomata::State::tostr()const
|
||||
else {
|
||||
// Standard regexp notation [^abcd]
|
||||
s += "[^";
|
||||
for (SymbolSet::const_iterator i = m_wildcard->m_minus.begin(); i != m_wildcard->m_minus.end(); ++i) {
|
||||
for (SymbolSet::const_iterator i = m_wildcard->m_minus.begin();
|
||||
i != m_wildcard->m_minus.end(); ++i) {
|
||||
if (!i->c_str())
|
||||
s += "_";
|
||||
else
|
||||
@@ -108,19 +111,19 @@ NdfAutomata::State::tostr()const
|
||||
}
|
||||
s += "]:";
|
||||
}
|
||||
s += Strutil::sprintf("%d", m_wildcard_trans);
|
||||
s += Strutil::to_string(m_wildcard_trans);
|
||||
}
|
||||
// and finally the rule if we have it
|
||||
if (m_rule) {
|
||||
s += " | ";
|
||||
s += Strutil::sprintf("%lx", (long unsigned int)m_rule);
|
||||
s += Strutil::fmt::format("{:p}", m_rule);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NdfAutomata::State *
|
||||
NdfAutomata::State*
|
||||
NdfAutomata::newState()
|
||||
{
|
||||
m_states.push_back(new State(m_states.size()));
|
||||
@@ -130,13 +133,15 @@ NdfAutomata::newState()
|
||||
|
||||
|
||||
void
|
||||
NdfAutomata::symbolsFrom(const IntSet &states, SymbolSet &out_symbols, Wildcard *&wildcard)const
|
||||
NdfAutomata::symbolsFrom(const IntSet& states, SymbolSet& out_symbols,
|
||||
Wildcard*& wildcard) const
|
||||
{
|
||||
for (IntSet::const_iterator i = states.begin(); i != states.end(); ++i) {
|
||||
const State *state = m_states[*i];
|
||||
// For every state we have to go thorugh all the symbols in the transition table
|
||||
const State* state = m_states[*i];
|
||||
// For every state we have to go through all the symbols in the transition table
|
||||
// m_symbol_trans and add them to the output
|
||||
for (SymbolToIntList::const_iterator j = state->m_symbol_trans.begin(); j != state->m_symbol_trans.end(); ++j)
|
||||
for (SymbolToIntList::const_iterator j = state->m_symbol_trans.begin();
|
||||
j != state->m_symbol_trans.end(); ++j)
|
||||
if (j->first != lambda)
|
||||
out_symbols.insert(j->first);
|
||||
if (state->m_wildcard) {
|
||||
@@ -145,16 +150,19 @@ NdfAutomata::symbolsFrom(const IntSet &states, SymbolSet &out_symbols, Wildcard
|
||||
// And if the state has a wildcard movement, we need to add its exclusion list
|
||||
// to our new computed exclusion list. So we guarantee that the returned wildcard
|
||||
// matches will be contained in all the wildcards out of this set
|
||||
wildcard->m_minus.insert(state->m_wildcard->m_minus.begin(), state->m_wildcard->m_minus.end());
|
||||
wildcard->m_minus.insert(state->m_wildcard->m_minus.begin(),
|
||||
state->m_wildcard->m_minus.end());
|
||||
}
|
||||
}
|
||||
if (wildcard) {
|
||||
// We have to make sure that all the symbols covered by the wildcards
|
||||
// are either covered by our wildcard or in out_symbols set
|
||||
for (IntSet::const_iterator i = states.begin(); i != states.end(); ++i) {
|
||||
const State *state = m_states[*i];
|
||||
for (IntSet::const_iterator i = states.begin(); i != states.end();
|
||||
++i) {
|
||||
const State* state = m_states[*i];
|
||||
if (state->m_wildcard)
|
||||
for (SymbolSet::const_iterator j = wildcard->m_minus.begin(); j != wildcard->m_minus.end(); ++j)
|
||||
for (SymbolSet::const_iterator j = wildcard->m_minus.begin();
|
||||
j != wildcard->m_minus.end(); ++j)
|
||||
if (state->m_wildcard->matches(*j))
|
||||
out_symbols.insert(*j);
|
||||
}
|
||||
@@ -166,7 +174,8 @@ NdfAutomata::symbolsFrom(const IntSet &states, SymbolSet &out_symbols, Wildcard
|
||||
|
||||
|
||||
void
|
||||
NdfAutomata::transitionsFrom(const IntSet &states, ustring symbol, IntSet &out_states)const
|
||||
NdfAutomata::transitionsFrom(const IntSet& states, ustring symbol,
|
||||
IntSet& out_states) const
|
||||
{
|
||||
for (IntSet::const_iterator i = states.begin(); i != states.end(); ++i)
|
||||
// remember getTransitions is not destructive with out_states, it just adds stuff
|
||||
@@ -178,10 +187,11 @@ NdfAutomata::transitionsFrom(const IntSet &states, ustring symbol, IntSet &out_s
|
||||
|
||||
|
||||
void
|
||||
NdfAutomata::wildcardTransitionsFrom(const IntSet &states, IntSet &out_states)const
|
||||
NdfAutomata::wildcardTransitionsFrom(const IntSet& states,
|
||||
IntSet& out_states) const
|
||||
{
|
||||
for (IntSet::const_iterator i = states.begin(); i != states.end(); ++i) {
|
||||
const State *state = m_states[*i];
|
||||
const State* state = m_states[*i];
|
||||
if (state->m_wildcard)
|
||||
out_states.insert(state->m_wildcard_trans);
|
||||
}
|
||||
@@ -191,7 +201,7 @@ NdfAutomata::wildcardTransitionsFrom(const IntSet &states, IntSet &out_states)co
|
||||
|
||||
|
||||
void
|
||||
NdfAutomata::lambdaClosure(IntSet &states)const
|
||||
NdfAutomata::lambdaClosure(IntSet& states) const
|
||||
{
|
||||
// This algorithm basically keeps expanding the set until no new states appear
|
||||
// to avoid checking over and over the same states we keep a frontier pair of sets
|
||||
@@ -200,40 +210,42 @@ NdfAutomata::lambdaClosure(IntSet &states)const
|
||||
// First iterate all the states in the given set
|
||||
// and see what lambda transitions are there
|
||||
for (IntSet::const_iterator i = states.begin(); i != states.end(); ++i) {
|
||||
const State *state = m_states[*i];
|
||||
std::pair <IntSet::const_iterator, IntSet::const_iterator> lr;
|
||||
const State* state = m_states[*i];
|
||||
std::pair<IntSet::const_iterator, IntSet::const_iterator> lr;
|
||||
// iterate all lambda transitions for this state
|
||||
for (lr = state->getLambdaTransitions(); lr.first != lr.second; lr.first++) {
|
||||
for (lr = state->getLambdaTransitions(); lr.first != lr.second;
|
||||
lr.first++) {
|
||||
// Add them to the set, and if they were not already there add to the
|
||||
// frontier
|
||||
std::pair<IntSet::iterator, bool> rec = states.insert(*(lr.first));
|
||||
if (rec.second) // newly added
|
||||
if (rec.second) // newly added
|
||||
frontier.push_back(*(lr.first));
|
||||
}
|
||||
}
|
||||
// frontier becomes last discovered
|
||||
frontier.swap(discovered); // swap discovered and frontier
|
||||
while (discovered.size()) { // as long as there are new found states
|
||||
frontier.swap(discovered); // swap discovered and frontier
|
||||
while (discovered.size()) { // as long as there are new found states
|
||||
frontier.clear();
|
||||
// we do the same as in the above loop but with discovered instead of states
|
||||
for (auto i : discovered) {
|
||||
const State *state = m_states[i];
|
||||
for (auto lr = state->getLambdaTransitions(); lr.first != lr.second; lr.first++) {
|
||||
std::pair<IntSet::iterator, bool> rec = states.insert(*(lr.first));
|
||||
const State* state = m_states[i];
|
||||
for (auto lr = state->getLambdaTransitions(); lr.first != lr.second;
|
||||
lr.first++) {
|
||||
std::pair<IntSet::iterator, bool> rec = states.insert(
|
||||
*(lr.first));
|
||||
if (rec.second)
|
||||
frontier.push_back(*(lr.first));
|
||||
}
|
||||
|
||||
}
|
||||
// again frontier becomes last discovered
|
||||
frontier.swap(discovered); // swap discovered and frontier
|
||||
frontier.swap(discovered); // swap discovered and frontier
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string
|
||||
NdfAutomata::tostr()const
|
||||
NdfAutomata::tostr() const
|
||||
{
|
||||
std::string s;
|
||||
for (size_t i = 0; i < m_states.size(); ++i) {
|
||||
@@ -254,9 +266,10 @@ NdfAutomata::~NdfAutomata()
|
||||
|
||||
|
||||
|
||||
void keyFromStateSet(const IntSet &states, StateSetKey &out_key)
|
||||
void
|
||||
keyFromStateSet(const IntSet& states, StateSetKey& out_key)
|
||||
{
|
||||
out_key.clear(); // just in case
|
||||
out_key.clear(); // just in case
|
||||
for (IntSet::const_iterator i = states.begin(); i != states.end(); ++i)
|
||||
out_key.push_back(*i);
|
||||
// Sort the ids so we make sure the vector is unique for each set
|
||||
@@ -266,7 +279,7 @@ void keyFromStateSet(const IntSet &states, StateSetKey &out_key)
|
||||
|
||||
|
||||
int
|
||||
DfAutomata::State::getTransition(ustring symbol)const
|
||||
DfAutomata::State::getTransition(ustring symbol) const
|
||||
{
|
||||
SymbolToInt::const_iterator i = m_symbol_trans.find(symbol);
|
||||
if (i == m_symbol_trans.end())
|
||||
@@ -281,20 +294,23 @@ DfAutomata::State::getTransition(ustring symbol)const
|
||||
|
||||
|
||||
void
|
||||
DfAutomata::State::addTransition(ustring symbol, DfAutomata::State *state)
|
||||
DfAutomata::State::addTransition(ustring symbol, DfAutomata::State* state)
|
||||
{
|
||||
SymbolToInt::value_type value(symbol, state->m_id);
|
||||
std::pair<SymbolToInt::iterator, bool> place = m_symbol_trans.insert(value);
|
||||
if (!place.second)
|
||||
std::cerr << "[pathexp] overwriting a transition in a DF automata" << std::endl;
|
||||
std::cerr << "[pathexp] overwriting a transition in a DF automata"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
DfAutomata::State::addWildcardTransition(Wildcard *wildcard, DfAutomata::State *state)
|
||||
DfAutomata::State::addWildcardTransition(Wildcard* wildcard,
|
||||
DfAutomata::State* state)
|
||||
{
|
||||
for (SymbolSet::const_iterator i = wildcard->m_minus.begin(); i != wildcard->m_minus.end(); ++i)
|
||||
for (SymbolSet::const_iterator i = wildcard->m_minus.begin();
|
||||
i != wildcard->m_minus.end(); ++i)
|
||||
// optimized storage, if it is not already in the transition table, tag it with -1
|
||||
if (m_symbol_trans.find(*i) == m_symbol_trans.end())
|
||||
m_symbol_trans[*i] = -1;
|
||||
@@ -309,7 +325,8 @@ DfAutomata::State::removeUselessTransitions()
|
||||
{
|
||||
if (m_wildcard_trans >= 0) {
|
||||
std::list<SymbolToInt::iterator> toremove;
|
||||
for (SymbolToInt::iterator i = m_symbol_trans.begin(); i != m_symbol_trans.end(); ++i)
|
||||
for (SymbolToInt::iterator i = m_symbol_trans.begin();
|
||||
i != m_symbol_trans.end(); ++i)
|
||||
// If there is a transition to the same state as the wildcard, we better nuke it
|
||||
// and just add that symbol to the wildcard be removing it from the map itself
|
||||
if (i->second == m_wildcard_trans)
|
||||
@@ -322,13 +339,14 @@ DfAutomata::State::removeUselessTransitions()
|
||||
|
||||
|
||||
std::string
|
||||
DfAutomata::State::tostr()const
|
||||
DfAutomata::State::tostr() const
|
||||
{
|
||||
std::string s = "";
|
||||
// normal transitions
|
||||
for (SymbolToInt::const_iterator i = m_symbol_trans.begin(); i != m_symbol_trans.end(); ++i) {
|
||||
for (SymbolToInt::const_iterator i = m_symbol_trans.begin();
|
||||
i != m_symbol_trans.end(); ++i) {
|
||||
ustring sym = i->first;
|
||||
int dest = i->second;
|
||||
int dest = i->second;
|
||||
if (s.size())
|
||||
s += " ";
|
||||
if (sym == lambda)
|
||||
@@ -336,7 +354,7 @@ DfAutomata::State::tostr()const
|
||||
else
|
||||
s += sym.c_str();
|
||||
s += ":";
|
||||
s += Strutil::sprintf("%d", dest);
|
||||
s += Strutil::to_string(dest);
|
||||
}
|
||||
// wildcard
|
||||
if (m_wildcard_trans >= 0) {
|
||||
@@ -346,7 +364,8 @@ DfAutomata::State::tostr()const
|
||||
s += ".:";
|
||||
else {
|
||||
s += "[^";
|
||||
for (SymbolToInt::const_iterator i = m_symbol_trans.begin(); i != m_symbol_trans.end(); ++i) {
|
||||
for (SymbolToInt::const_iterator i = m_symbol_trans.begin();
|
||||
i != m_symbol_trans.end(); ++i) {
|
||||
if (!i->first.c_str())
|
||||
s += "_";
|
||||
else
|
||||
@@ -354,15 +373,16 @@ DfAutomata::State::tostr()const
|
||||
}
|
||||
s += "}:";
|
||||
}
|
||||
s += Strutil::sprintf("%d", m_wildcard_trans);
|
||||
s += Strutil::to_string(m_wildcard_trans);
|
||||
}
|
||||
// and the rules
|
||||
if (m_rules.size()) {
|
||||
s += " | [";
|
||||
for (RuleSet::const_iterator i = m_rules.begin(); i != m_rules.end(); ++i) {
|
||||
if (s[s.size()-1] != '[')
|
||||
for (RuleSet::const_iterator i = m_rules.begin(); i != m_rules.end();
|
||||
++i) {
|
||||
if (s[s.size() - 1] != '[')
|
||||
s += ", ";
|
||||
s += Strutil::sprintf("%lx", (long unsigned int)*i);
|
||||
s += Strutil::fmt::format("{:p}", *i);
|
||||
}
|
||||
s += "]";
|
||||
}
|
||||
@@ -371,7 +391,7 @@ DfAutomata::State::tostr()const
|
||||
|
||||
|
||||
|
||||
DfAutomata::State *
|
||||
DfAutomata::State*
|
||||
DfAutomata::newState()
|
||||
{
|
||||
m_states.push_back(new State(m_states.size()));
|
||||
@@ -381,7 +401,7 @@ DfAutomata::newState()
|
||||
|
||||
|
||||
std::string
|
||||
DfAutomata::tostr()const
|
||||
DfAutomata::tostr() const
|
||||
{
|
||||
std::string s;
|
||||
for (size_t i = 0; i < m_states.size(); ++i) {
|
||||
@@ -395,26 +415,40 @@ DfAutomata::tostr()const
|
||||
|
||||
|
||||
bool
|
||||
DfAutomata::equivalent(const State *dfstateA, const State *dfstateB)
|
||||
DfAutomata::equivalent(const State* dfstateA, const State* dfstateB)
|
||||
{
|
||||
// early exit if the size of the tables is different
|
||||
if (dfstateA->m_symbol_trans.size() != dfstateB->m_symbol_trans.size())
|
||||
return false;
|
||||
// The pointed state by both transitions have to be the same or any of dfstateA and dfstateB
|
||||
int destA = (dfstateA->m_wildcard_trans == dfstateA->getId() || dfstateA->m_wildcard_trans == dfstateB->getId()) ? -2 : dfstateA->m_wildcard_trans;
|
||||
int destB = (dfstateB->m_wildcard_trans == dfstateA->getId() || dfstateB->m_wildcard_trans == dfstateB->getId()) ? -2 : dfstateB->m_wildcard_trans;
|
||||
int destA = (dfstateA->m_wildcard_trans == dfstateA->getId()
|
||||
|| dfstateA->m_wildcard_trans == dfstateB->getId())
|
||||
? -2
|
||||
: dfstateA->m_wildcard_trans;
|
||||
int destB = (dfstateB->m_wildcard_trans == dfstateA->getId()
|
||||
|| dfstateB->m_wildcard_trans == dfstateB->getId())
|
||||
? -2
|
||||
: dfstateB->m_wildcard_trans;
|
||||
if (destA != destB)
|
||||
return false;
|
||||
// Rules have to be the same
|
||||
if (dfstateA->m_rules != dfstateB->m_rules)
|
||||
return false;
|
||||
for (SymbolToInt::const_iterator i = dfstateA->m_symbol_trans.begin(); i != dfstateA->m_symbol_trans.end(); ++i) {
|
||||
SymbolToInt::const_iterator other = dfstateB->m_symbol_trans.find(i->first);
|
||||
for (SymbolToInt::const_iterator i = dfstateA->m_symbol_trans.begin();
|
||||
i != dfstateA->m_symbol_trans.end(); ++i) {
|
||||
SymbolToInt::const_iterator other = dfstateB->m_symbol_trans.find(
|
||||
i->first);
|
||||
if (other == dfstateB->m_symbol_trans.end())
|
||||
return false;
|
||||
// The pointed state by both transitions have to be the same or any of dfstateA and dfstateB
|
||||
int destA = (i->second == dfstateA->getId() || i->second == dfstateB->getId()) ? -2 : i->second;
|
||||
int destB = (other->second == dfstateA->getId() || other->second == dfstateB->getId()) ? -2 : other->second;
|
||||
int destA = (i->second == dfstateA->getId()
|
||||
|| i->second == dfstateB->getId())
|
||||
? -2
|
||||
: i->second;
|
||||
int destB = (other->second == dfstateA->getId()
|
||||
|| other->second == dfstateB->getId())
|
||||
? -2
|
||||
: other->second;
|
||||
// when they are -1 is because they are in the wildcard black list, anyway they have to match so ...
|
||||
if (destA != destB)
|
||||
return false;
|
||||
@@ -428,13 +462,13 @@ DfAutomata::equivalent(const State *dfstateA, const State *dfstateB)
|
||||
void
|
||||
DfAutomata::removeEquivalentStates()
|
||||
{
|
||||
std::vector<State *> newstatelist;
|
||||
std::vector<State*> newstatelist;
|
||||
HashIntInt newfromold;
|
||||
|
||||
// First go through all states and delete all those
|
||||
// that are equivalent with a previous one
|
||||
for (size_t i = 0; i < m_states.size(); ++i) {
|
||||
if (!m_states[i]) // it has already been removed
|
||||
if (!m_states[i]) // it has already been removed
|
||||
continue;
|
||||
// create a new state id from newstatelist.size()
|
||||
// move the pointer there and register the translation
|
||||
@@ -452,24 +486,30 @@ DfAutomata::removeEquivalentStates()
|
||||
// Everything has been moved now, but we still have to fix the
|
||||
// transitions so they point to the right states!
|
||||
for (size_t i = 0; i < newstatelist.size(); ++i) {
|
||||
State *state = newstatelist[i];
|
||||
for (SymbolToInt::iterator j = state->m_symbol_trans.begin(); j != state->m_symbol_trans.end(); ++j) {
|
||||
if (j->second != -1) { // if it is -1 it is just in the wildcards black list
|
||||
State* state = newstatelist[i];
|
||||
for (SymbolToInt::iterator j = state->m_symbol_trans.begin();
|
||||
j != state->m_symbol_trans.end(); ++j) {
|
||||
if (j->second
|
||||
!= -1) { // if it is -1 it is just in the wildcards black list
|
||||
// Get the new state that maps to the oldstate pointed by the transition
|
||||
HashIntInt::const_iterator trans = newfromold.find(j->second);
|
||||
if (trans != newfromold.end())
|
||||
j->second = trans->second;
|
||||
else
|
||||
std::cerr << "[pathexp] broken translation list between states" << std::endl;
|
||||
std::cerr
|
||||
<< "[pathexp] broken translation list between states"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
// Do the same with the wildcard
|
||||
if (state->m_wildcard_trans >=0) {
|
||||
HashIntInt::const_iterator trans = newfromold.find(state->m_wildcard_trans);
|
||||
if (state->m_wildcard_trans >= 0) {
|
||||
HashIntInt::const_iterator trans = newfromold.find(
|
||||
state->m_wildcard_trans);
|
||||
if (trans != newfromold.end())
|
||||
state->m_wildcard_trans = trans->second;
|
||||
else
|
||||
std::cerr << "[pathexp] broken translation list between states" << std::endl;
|
||||
std::cerr << "[pathexp] broken translation list between states"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
// switch to the new hopefully reduced state vector
|
||||
@@ -504,8 +544,9 @@ DfAutomata::~DfAutomata()
|
||||
|
||||
|
||||
|
||||
DfAutomata::State *
|
||||
StateSetRecord::ensureState(const IntSet &newstates, std::list<StateSetRecord::Discovery> &discovered)
|
||||
DfAutomata::State*
|
||||
StateSetRecord::ensureState(const IntSet& newstates,
|
||||
std::list<StateSetRecord::Discovery>& discovered)
|
||||
{
|
||||
// create the key
|
||||
StateSetKey newkey;
|
||||
@@ -516,7 +557,7 @@ StateSetRecord::ensureState(const IntSet &newstates, std::list<StateSetRecord::D
|
||||
return i->second;
|
||||
else {
|
||||
// if not in our records create a new DF state
|
||||
DfAutomata::State *tstate = m_dfautomata.newState();
|
||||
DfAutomata::State* tstate = m_dfautomata.newState();
|
||||
getRulesFromSet(tstate, m_ndfautomata, newstates);
|
||||
m_key_to_dfstate[newkey] = tstate;
|
||||
// Add the discovery to the list so it will be explored
|
||||
@@ -528,10 +569,13 @@ StateSetRecord::ensureState(const IntSet &newstates, std::list<StateSetRecord::D
|
||||
|
||||
|
||||
void
|
||||
StateSetRecord::getRulesFromSet(DfAutomata::State *dfstate, const NdfAutomata &ndfautomata, const IntSet &ndfstates)
|
||||
StateSetRecord::getRulesFromSet(DfAutomata::State* dfstate,
|
||||
const NdfAutomata& ndfautomata,
|
||||
const IntSet& ndfstates)
|
||||
{
|
||||
for (IntSet::const_iterator i = ndfstates.begin(); i != ndfstates.end(); ++i) {
|
||||
const NdfAutomata::State *ndfstate = ndfautomata.getState(*i);
|
||||
for (IntSet::const_iterator i = ndfstates.begin(); i != ndfstates.end();
|
||||
++i) {
|
||||
const NdfAutomata::State* ndfstate = ndfautomata.getState(*i);
|
||||
if (ndfstate->getRule())
|
||||
dfstate->addRule(ndfstate->getRule());
|
||||
}
|
||||
@@ -540,7 +584,7 @@ StateSetRecord::getRulesFromSet(DfAutomata::State *dfstate, const NdfAutomata &n
|
||||
|
||||
|
||||
void
|
||||
ndfautoToDfauto(const NdfAutomata &ndfautomata, DfAutomata &dfautomata)
|
||||
ndfautoToDfauto(const NdfAutomata& ndfautomata, DfAutomata& dfautomata)
|
||||
{
|
||||
std::list<StateSetRecord::Discovery> toexplore, discovered;
|
||||
// our initial state is the lambda closure
|
||||
@@ -561,14 +605,16 @@ ndfautoToDfauto(const NdfAutomata &ndfautomata, DfAutomata &dfautomata)
|
||||
// a wildcard movement that is guaranteed to match all
|
||||
// the wildcard transitions in the set (if any)
|
||||
SymbolSet symbols;
|
||||
Wildcard *wildcard = NULL;
|
||||
Wildcard* wildcard = NULL;
|
||||
ndfautomata.symbolsFrom(i.second, symbols, wildcard);
|
||||
for (SymbolSet::iterator j = symbols.begin(); j != symbols.end(); ++j) {
|
||||
for (SymbolSet::iterator j = symbols.begin(); j != symbols.end();
|
||||
++j) {
|
||||
IntSet newstates;
|
||||
// get all the states reachable with this symbol
|
||||
ndfautomata.transitionsFrom(i.second, *j, newstates);
|
||||
// build or recover the associated DF state
|
||||
DfAutomata::State *next_state = record.ensureState(newstates, discovered);
|
||||
DfAutomata::State* next_state = record.ensureState(newstates,
|
||||
discovered);
|
||||
// and store a transition
|
||||
i.first->addTransition(*j, next_state);
|
||||
}
|
||||
@@ -577,7 +623,8 @@ ndfautoToDfauto(const NdfAutomata &ndfautomata, DfAutomata &dfautomata)
|
||||
// we know they all match whatever ours match
|
||||
ndfautomata.wildcardTransitionsFrom(i.second, newstates);
|
||||
// build or recover the associated DF state
|
||||
DfAutomata::State *next_state = record.ensureState(newstates, discovered);
|
||||
DfAutomata::State* next_state = record.ensureState(newstates,
|
||||
discovered);
|
||||
// and store a transition
|
||||
i.first->addWildcardTransition(wildcard, next_state);
|
||||
}
|
||||
@@ -593,7 +640,9 @@ ndfautoToDfauto(const NdfAutomata &ndfautomata, DfAutomata &dfautomata)
|
||||
|
||||
|
||||
bool
|
||||
DfOptimizedAutomata::Transition::trans_comp (const DfOptimizedAutomata::Transition &a, const DfOptimizedAutomata::Transition &b)
|
||||
DfOptimizedAutomata::Transition::trans_comp(
|
||||
const DfOptimizedAutomata::Transition& a,
|
||||
const DfOptimizedAutomata::Transition& b)
|
||||
{
|
||||
return a.symbol.data() < b.symbol.data();
|
||||
}
|
||||
@@ -601,7 +650,7 @@ DfOptimizedAutomata::Transition::trans_comp (const DfOptimizedAutomata::Transiti
|
||||
|
||||
|
||||
void
|
||||
DfOptimizedAutomata::compileFrom(const DfAutomata &dfautomata)
|
||||
DfOptimizedAutomata::compileFrom(const DfAutomata& dfautomata)
|
||||
{
|
||||
m_states.resize(dfautomata.m_states.size());
|
||||
size_t totaltrans = 0;
|
||||
@@ -617,18 +666,22 @@ DfOptimizedAutomata::compileFrom(const DfAutomata &dfautomata)
|
||||
for (size_t s = 0; s < m_states.size(); ++s) {
|
||||
m_states[s].begin_trans = trans_offset;
|
||||
m_states[s].begin_rules = rules_offset;
|
||||
for (SymbolToInt::const_iterator i = dfautomata.m_states[s]->m_symbol_trans.begin();
|
||||
i != dfautomata.m_states[s]->m_symbol_trans.end(); ++i, ++trans_offset) {
|
||||
for (SymbolToInt::const_iterator i
|
||||
= dfautomata.m_states[s]->m_symbol_trans.begin();
|
||||
i != dfautomata.m_states[s]->m_symbol_trans.end();
|
||||
++i, ++trans_offset) {
|
||||
m_trans[trans_offset].symbol = i->first;
|
||||
m_trans[trans_offset].state = i->second;
|
||||
m_trans[trans_offset].state = i->second;
|
||||
}
|
||||
for (RuleSet::const_iterator i = dfautomata.m_states[s]->m_rules.begin();
|
||||
i != dfautomata.m_states[s]->m_rules.end(); ++i, ++rules_offset)
|
||||
i != dfautomata.m_states[s]->m_rules.end(); ++i, ++rules_offset)
|
||||
m_rules[rules_offset] = *i;
|
||||
m_states[s].ntrans = dfautomata.m_states[s]->m_symbol_trans.size();
|
||||
m_states[s].nrules = dfautomata.m_states[s]->m_rules.size();
|
||||
std::sort(m_trans.begin() + m_states[s].begin_trans, m_trans.begin() + m_states[s].begin_trans + m_states[s].ntrans,
|
||||
DfOptimizedAutomata::Transition::trans_comp);
|
||||
std::sort(m_trans.begin() + m_states[s].begin_trans,
|
||||
m_trans.begin() + m_states[s].begin_trans
|
||||
+ m_states[s].ntrans,
|
||||
DfOptimizedAutomata::Transition::trans_comp);
|
||||
m_states[s].wildcard_trans = dfautomata.m_states[s]->m_wildcard_trans;
|
||||
}
|
||||
}
|
||||
|
||||
+202
-198
@@ -4,12 +4,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
@@ -20,20 +20,21 @@ OSL_NAMESPACE_ENTER
|
||||
// General container for all symbol sets
|
||||
|
||||
// General container for integer sets
|
||||
typedef std::set<int> IntSet; // probably faster to test for equality, unions and so
|
||||
typedef std::set<int>
|
||||
IntSet; // probably faster to test for equality, unions and so
|
||||
|
||||
typedef std::unordered_set<ustring, ustringHash> SymbolSet;
|
||||
typedef std::unordered_set<ustring> SymbolSet;
|
||||
// This is for the transition table used in DfAutomata::State
|
||||
typedef std::unordered_map<ustring, int, ustringHash> SymbolToInt;
|
||||
typedef std::unordered_map<ustring, int> SymbolToInt;
|
||||
// And this is for the transition table in NdfAutomata which
|
||||
// has several movements for each symbol
|
||||
typedef std::unordered_map<ustring, IntSet, ustringHash> SymbolToIntList;
|
||||
typedef std::unordered_map<ustring, IntSet> SymbolToIntList;
|
||||
typedef std::unordered_map<int, int> HashIntInt;
|
||||
|
||||
// For the rules in the deterministic states, we don't need a real set
|
||||
// cause when converting from the NDF automata we will never find the same
|
||||
// rule twice
|
||||
typedef std::vector<void *> RuleSet;
|
||||
typedef std::vector<void*> RuleSet;
|
||||
|
||||
// The lambda symbol (empty word)
|
||||
extern ustring lambda;
|
||||
@@ -45,9 +46,9 @@ extern ustring lambda;
|
||||
/// any symbol which is not listed in its black list (m_minus).
|
||||
struct Wildcard {
|
||||
Wildcard() {};
|
||||
Wildcard(SymbolSet &minus):m_minus(minus) {};
|
||||
Wildcard(SymbolSet& minus) : m_minus(minus) {};
|
||||
|
||||
bool matches(ustring symbol)const
|
||||
bool matches(ustring symbol) const
|
||||
{
|
||||
// true if the given symbol is not in m_minus
|
||||
return (m_minus.find(symbol) == m_minus.end());
|
||||
@@ -63,109 +64,110 @@ struct Wildcard {
|
||||
/// symbol and allowed lambda transitions too. Light path expressions
|
||||
/// build this automata easily. It is later converted to a DF automata.
|
||||
class NdfAutomata {
|
||||
public:
|
||||
// Basic state for NDF automata
|
||||
class State {
|
||||
friend class NdfAutomata;
|
||||
|
||||
public:
|
||||
|
||||
// Basic state for NDF automata
|
||||
class State {
|
||||
friend class NdfAutomata;
|
||||
public:
|
||||
|
||||
State(int id)
|
||||
{
|
||||
m_id = id;
|
||||
m_wildcard_trans = -1;
|
||||
m_wildcard = NULL;
|
||||
m_rule = NULL;
|
||||
};
|
||||
~State() { delete m_wildcard; };
|
||||
|
||||
/// Get the set of state id's reachable by the given symbol
|
||||
///
|
||||
/// It doesn't clean the given result set, so you can use this
|
||||
/// function to accumulate states.
|
||||
void getTransitions (ustring symbol, IntSet &out_states)const;
|
||||
|
||||
/// Get all the lambda transitions
|
||||
///
|
||||
/// Returns the state collection as a pair of iterators [begin, end)
|
||||
std::pair <IntSet::const_iterator, IntSet::const_iterator>
|
||||
getLambdaTransitions ()const;
|
||||
|
||||
/// Add a standar transition (also valid for lambda)
|
||||
void addTransition (ustring symbol, State *state);
|
||||
/// Add a wildcard transition
|
||||
///
|
||||
/// Note that the state is going to take ownership of the wildcard
|
||||
/// pointer. So it should be newly allocated on heap and you don't
|
||||
/// have to delete ir
|
||||
void addWildcardTransition(Wildcard *wildcard, State *state);
|
||||
|
||||
/// For final states, this sets the associated rule. Which
|
||||
/// can be any kind of pointer
|
||||
void setRule(void *rule) { m_rule = rule; };
|
||||
|
||||
void *getRule()const { return m_rule; };
|
||||
int getId()const { return m_id; };
|
||||
|
||||
/// For debuging purposes
|
||||
std::string tostr()const;
|
||||
|
||||
protected:
|
||||
|
||||
// State id (i.e index in the states vector)
|
||||
int m_id;
|
||||
// Transitions by single symbols
|
||||
SymbolToIntList m_symbol_trans;
|
||||
// In case m_wildcard is not NULL this holds the destination
|
||||
// of the wildcard transition
|
||||
int m_wildcard_trans;
|
||||
// Wildcard (NULL if no wildcard transition present)
|
||||
Wildcard *m_wildcard;
|
||||
// Associated rule for final states, NULL if not final
|
||||
void *m_rule;
|
||||
State(int id)
|
||||
{
|
||||
m_id = id;
|
||||
m_wildcard_trans = -1;
|
||||
m_wildcard = NULL;
|
||||
m_rule = NULL;
|
||||
};
|
||||
~State() { delete m_wildcard; };
|
||||
|
||||
|
||||
|
||||
NdfAutomata() { newState(); };
|
||||
~NdfAutomata();
|
||||
|
||||
const State *getInitial()const { return m_states[0]; };
|
||||
State *getInitial() { return m_states[0]; };
|
||||
|
||||
/// Creates a new state qith a valid id
|
||||
State *newState();
|
||||
|
||||
const State *getState(int i)const { return m_states[i]; };
|
||||
size_t size()const { return m_states.size(); };
|
||||
|
||||
/// return all the symbols that lead to other states starting
|
||||
/// in any of the states in the given set. Also if there are
|
||||
/// wildcard transitions, give back a new wildcard that guarantees
|
||||
/// that its matches match all the wildcards in the set.
|
||||
/// So the symbols returned in out_symbols do NOT overlap those that
|
||||
/// match the returned wildcard (if present). And the union of out_symbols
|
||||
/// and those matched by the wildcard, are all the valid transitions from
|
||||
/// the given state set
|
||||
void symbolsFrom(const IntSet &states, SymbolSet &out_symbols, Wildcard *&wildcard)const;
|
||||
|
||||
/// Get the set of states that are reachable from the given state set using the given symbol
|
||||
void transitionsFrom(const IntSet &states, ustring symbol, IntSet &out_states)const;
|
||||
/// Get the set of states that are reachable from the given state set by wildcard
|
||||
void wildcardTransitionsFrom(const IntSet &states, IntSet &out_states)const;
|
||||
|
||||
/// Perform a lambda closure of a state set
|
||||
/// Get the set of state id's reachable by the given symbol
|
||||
///
|
||||
/// In other words, complete the given set so it includes all the additional
|
||||
/// states that are reachable by the lambda symbol
|
||||
void lambdaClosure(IntSet &states)const;
|
||||
/// It doesn't clean the given result set, so you can use this
|
||||
/// function to accumulate states.
|
||||
void getTransitions(ustring symbol, IntSet& out_states) const;
|
||||
|
||||
/// for debuging purposes
|
||||
std::string tostr()const;
|
||||
/// Get all the lambda transitions
|
||||
///
|
||||
/// Returns the state collection as a pair of iterators [begin, end)
|
||||
std::pair<IntSet::const_iterator, IntSet::const_iterator>
|
||||
getLambdaTransitions() const;
|
||||
|
||||
/// Add a standard transition (also valid for lambda)
|
||||
void addTransition(ustring symbol, State* state);
|
||||
/// Add a wildcard transition
|
||||
///
|
||||
/// Note that the state is going to take ownership of the wildcard
|
||||
/// pointer. So it should be newly allocated on heap and you don't
|
||||
/// have to delete ir
|
||||
void addWildcardTransition(Wildcard* wildcard, State* state);
|
||||
|
||||
/// For final states, this sets the associated rule. Which
|
||||
/// can be any kind of pointer
|
||||
void setRule(void* rule) { m_rule = rule; };
|
||||
|
||||
void* getRule() const { return m_rule; };
|
||||
int getId() const { return m_id; };
|
||||
|
||||
/// For debugging purposes
|
||||
std::string tostr() const;
|
||||
|
||||
protected:
|
||||
/// Vector of states
|
||||
std::vector<State *> m_states;
|
||||
// State id (i.e index in the states vector)
|
||||
int m_id;
|
||||
// Transitions by single symbols
|
||||
SymbolToIntList m_symbol_trans;
|
||||
// In case m_wildcard is not NULL this holds the destination
|
||||
// of the wildcard transition
|
||||
int m_wildcard_trans;
|
||||
// Wildcard (NULL if no wildcard transition present)
|
||||
Wildcard* m_wildcard;
|
||||
// Associated rule for final states, NULL if not final
|
||||
void* m_rule;
|
||||
};
|
||||
|
||||
|
||||
|
||||
NdfAutomata() { newState(); };
|
||||
~NdfAutomata();
|
||||
|
||||
const State* getInitial() const { return m_states[0]; };
|
||||
State* getInitial() { return m_states[0]; };
|
||||
|
||||
/// Creates a new state with a valid id
|
||||
State* newState();
|
||||
|
||||
const State* getState(int i) const { return m_states[i]; };
|
||||
size_t size() const { return m_states.size(); };
|
||||
|
||||
/// return all the symbols that lead to other states starting
|
||||
/// in any of the states in the given set. Also if there are
|
||||
/// wildcard transitions, give back a new wildcard that guarantees
|
||||
/// that its matches match all the wildcards in the set.
|
||||
/// So the symbols returned in out_symbols do NOT overlap those that
|
||||
/// match the returned wildcard (if present). And the union of out_symbols
|
||||
/// and those matched by the wildcard, are all the valid transitions from
|
||||
/// the given state set
|
||||
void symbolsFrom(const IntSet& states, SymbolSet& out_symbols,
|
||||
Wildcard*& wildcard) const;
|
||||
|
||||
/// Get the set of states that are reachable from the given state set using the given symbol
|
||||
void transitionsFrom(const IntSet& states, ustring symbol,
|
||||
IntSet& out_states) const;
|
||||
/// Get the set of states that are reachable from the given state set by wildcard
|
||||
void wildcardTransitionsFrom(const IntSet& states,
|
||||
IntSet& out_states) const;
|
||||
|
||||
/// Perform a lambda closure of a state set
|
||||
///
|
||||
/// In other words, complete the given set so it includes all the additional
|
||||
/// states that are reachable by the lambda symbol
|
||||
void lambdaClosure(IntSet& states) const;
|
||||
|
||||
/// for debugging purposes
|
||||
std::string tostr() const;
|
||||
|
||||
protected:
|
||||
/// Vector of states
|
||||
std::vector<State*> m_states;
|
||||
};
|
||||
|
||||
|
||||
@@ -177,7 +179,8 @@ class NdfAutomata {
|
||||
typedef std::vector<int> StateSetKey;
|
||||
|
||||
// Compute the unique key for the given set of states
|
||||
void keyFromStateSet(const IntSet &states, StateSetKey &out_key);
|
||||
void
|
||||
keyFromStateSet(const IntSet& states, StateSetKey& out_key);
|
||||
|
||||
|
||||
|
||||
@@ -188,84 +191,83 @@ void keyFromStateSet(const IntSet &states, StateSetKey &out_key);
|
||||
/// time parsing of light path expressions
|
||||
class DfAutomata {
|
||||
friend class DfOptimizedAutomata;
|
||||
|
||||
public:
|
||||
/// Simple state for a deterministic automata
|
||||
class State {
|
||||
friend class DfAutomata;
|
||||
friend class DfOptimizedAutomata;
|
||||
|
||||
public:
|
||||
/// Simple state for a deterministic automata
|
||||
class State {
|
||||
friend class DfAutomata;
|
||||
friend class DfOptimizedAutomata;
|
||||
public:
|
||||
State(int id)
|
||||
{
|
||||
m_id = id;
|
||||
m_wildcard_trans = -1;
|
||||
}
|
||||
|
||||
State(int id)
|
||||
{
|
||||
m_id = id;
|
||||
m_wildcard_trans = -1;
|
||||
}
|
||||
/// Get the transition for a symbol
|
||||
//
|
||||
/// Returns -1 if no transitions with that symbol. That means the
|
||||
/// symbol is not recognized at this point of the automata
|
||||
int getTransition(ustring symbol) const;
|
||||
|
||||
/// Get the transition for a symbol
|
||||
//
|
||||
/// Returns -1 if no transitions with that symbol. That means the
|
||||
/// symbol is not recognized at this point of the automata
|
||||
int getTransition(ustring symbol)const;
|
||||
// Same semantics as in NdfAutomata::State
|
||||
void addTransition(ustring symbol, State* state);
|
||||
// WARNING: this has an optimized representation and has to be called
|
||||
// always AFTER all the normal transitions have been added
|
||||
void addWildcardTransition(Wildcard* wildcard, State* state);
|
||||
|
||||
// Same semantics as in NdfAutomata::State
|
||||
void addTransition(ustring symbol, State *state);
|
||||
// WARNING: this has an optimized representation and has to be called
|
||||
// always AFTER all the normal transitions have been added
|
||||
void addWildcardTransition(Wildcard *wildcard, State *state);
|
||||
|
||||
/// Optimize transitions
|
||||
///
|
||||
/// Sometimes the existing wildcard can be extended to wrap some of
|
||||
/// the single symbol transitions. This function performs that optimization
|
||||
void removeUselessTransitions();
|
||||
|
||||
void addRule(void *rule) { m_rules.push_back(rule); };
|
||||
const RuleSet &getRules()const { return m_rules; };
|
||||
int getId()const { return m_id; };
|
||||
std::string tostr()const;
|
||||
|
||||
protected:
|
||||
|
||||
int m_id;
|
||||
// Only one transition per symbol here
|
||||
SymbolToInt m_symbol_trans;
|
||||
int m_wildcard_trans;
|
||||
// A final state here might contain several final states
|
||||
// from the original NDF automata. Therefore, we need a list
|
||||
// of rules here
|
||||
RuleSet m_rules;
|
||||
};
|
||||
|
||||
|
||||
DfAutomata() {};
|
||||
~DfAutomata();
|
||||
|
||||
State *newState();
|
||||
const State *getState(int i)const { return m_states[i]; };
|
||||
size_t size()const { return m_states.size(); };
|
||||
// In case somebody wants to reuse the same object and recreate
|
||||
// an automata, we provide this method
|
||||
void clear();
|
||||
|
||||
/// Colapse all the equivalent states into single ones
|
||||
void removeEquivalentStates();
|
||||
/// Go through all the states and perform removeUselessTransitions
|
||||
/// method call on them
|
||||
/// Optimize transitions
|
||||
///
|
||||
/// Sometimes the existing wildcard can be extended to wrap some of
|
||||
/// the single symbol transitions. This function performs that optimization
|
||||
void removeUselessTransitions();
|
||||
|
||||
/// For debuging purposes
|
||||
std::string tostr()const;
|
||||
void addRule(void* rule) { m_rules.push_back(rule); };
|
||||
const RuleSet& getRules() const { return m_rules; };
|
||||
int getId() const { return m_id; };
|
||||
std::string tostr() const;
|
||||
|
||||
protected:
|
||||
int m_id;
|
||||
// Only one transition per symbol here
|
||||
SymbolToInt m_symbol_trans;
|
||||
int m_wildcard_trans;
|
||||
// A final state here might contain several final states
|
||||
// from the original NDF automata. Therefore, we need a list
|
||||
// of rules here
|
||||
RuleSet m_rules;
|
||||
};
|
||||
|
||||
/// Return true if two states are equivalent
|
||||
///
|
||||
/// Two states are equivalent if their transition tables lead
|
||||
/// to the same states for the same symbols
|
||||
bool equivalent(const State *dfstateA, const State *dfstateB);
|
||||
|
||||
// State vector with the automata
|
||||
std::vector<State *> m_states;
|
||||
DfAutomata() {};
|
||||
~DfAutomata();
|
||||
|
||||
State* newState();
|
||||
const State* getState(int i) const { return m_states[i]; };
|
||||
size_t size() const { return m_states.size(); };
|
||||
// In case somebody wants to reuse the same object and recreate
|
||||
// an automata, we provide this method
|
||||
void clear();
|
||||
|
||||
/// Colapse all the equivalent states into single ones
|
||||
void removeEquivalentStates();
|
||||
/// Go through all the states and perform removeUselessTransitions
|
||||
/// method call on them
|
||||
void removeUselessTransitions();
|
||||
|
||||
/// For debugging purposes
|
||||
std::string tostr() const;
|
||||
|
||||
protected:
|
||||
/// Return true if two states are equivalent
|
||||
///
|
||||
/// Two states are equivalent if their transition tables lead
|
||||
/// to the same states for the same symbols
|
||||
bool equivalent(const State* dfstateA, const State* dfstateB);
|
||||
|
||||
// State vector with the automata
|
||||
std::vector<State*> m_states;
|
||||
};
|
||||
|
||||
|
||||
@@ -274,40 +276,42 @@ class DfAutomata {
|
||||
/// of state sets that have already been found to be new states of the
|
||||
/// deterministic automata
|
||||
class StateSetRecord {
|
||||
public:
|
||||
StateSetRecord(const NdfAutomata &ndfautomata, DfAutomata &dfautomata):
|
||||
m_ndfautomata(ndfautomata), m_dfautomata(dfautomata)
|
||||
{};
|
||||
public:
|
||||
StateSetRecord(const NdfAutomata& ndfautomata, DfAutomata& dfautomata)
|
||||
: m_ndfautomata(ndfautomata), m_dfautomata(dfautomata) {};
|
||||
|
||||
// A new found state is defined by the deterministic state created
|
||||
// for it and the state(int) set in the original automata
|
||||
typedef std::pair<DfAutomata::State *, IntSet> Discovery;
|
||||
// The type that will index our new created states indexed by the set key
|
||||
typedef std::map<StateSetKey, DfAutomata::State *> StateSetMap;
|
||||
// A new found state is defined by the deterministic state created
|
||||
// for it and the state(int) set in the original automata
|
||||
typedef std::pair<DfAutomata::State*, IntSet> Discovery;
|
||||
// The type that will index our new created states indexed by the set key
|
||||
typedef std::map<StateSetKey, DfAutomata::State*> StateSetMap;
|
||||
|
||||
/// Take a state set and build a new df state (or return existing one)
|
||||
/// Also, if it was newly created, append it to the discovered list so we
|
||||
/// can iterate over it later
|
||||
DfAutomata::State *ensureState(const IntSet &newstates, std::list<Discovery> &discovered);
|
||||
/// Take a state set and build a new df state (or return existing one)
|
||||
/// Also, if it was newly created, append it to the discovered list so we
|
||||
/// can iterate over it later
|
||||
DfAutomata::State* ensureState(const IntSet& newstates,
|
||||
std::list<Discovery>& discovered);
|
||||
|
||||
private:
|
||||
private:
|
||||
/// Gather all the rules from the original automata in the given sets (if any)
|
||||
/// and put them in the dfstate rule set
|
||||
void getRulesFromSet(DfAutomata::State* dfstate,
|
||||
const NdfAutomata& ndfautomata,
|
||||
const IntSet& ndfstates);
|
||||
|
||||
/// Gather all the rules from the original automata in the given sets (if any)
|
||||
/// and put them in the dfstate rule set
|
||||
void getRulesFromSet(DfAutomata::State *dfstate, const NdfAutomata &ndfautomata, const IntSet &ndfstates);
|
||||
|
||||
const NdfAutomata &m_ndfautomata;
|
||||
DfAutomata &m_dfautomata;
|
||||
StateSetMap m_key_to_dfstate;
|
||||
const NdfAutomata& m_ndfautomata;
|
||||
DfAutomata& m_dfautomata;
|
||||
StateSetMap m_key_to_dfstate;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// NDF to DF automata convertion
|
||||
/// NDF to DF automata conversion
|
||||
///
|
||||
/// This function is the most important pice of the whole process. It takes
|
||||
/// a non-deterministic finite automata and computes an equivalent deterministic
|
||||
/// one. It is equivalente in the sense that they both recognize the same language
|
||||
void ndfautoToDfauto(const NdfAutomata &ndfautomata, DfAutomata &dfautomata);
|
||||
void
|
||||
ndfautoToDfauto(const NdfAutomata& ndfautomata, DfAutomata& dfautomata);
|
||||
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
+426
-565
File diff suppressed because it is too large
Load Diff
+240
-187
@@ -4,15 +4,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "oslexec_pvt.h"
|
||||
using namespace OSL;
|
||||
using namespace OSL::pvt;
|
||||
|
||||
#include "runtimeoptimize.h"
|
||||
#include <OSL/llvm_util.h>
|
||||
#include "runtimeoptimize.h"
|
||||
|
||||
// additional includes for creating global OptiX variables
|
||||
#include "llvm/IR/Constants.h"
|
||||
@@ -22,7 +22,7 @@ using namespace OSL::pvt;
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
namespace pvt { // OSL::pvt
|
||||
namespace pvt { // OSL::pvt
|
||||
|
||||
|
||||
|
||||
@@ -30,16 +30,16 @@ namespace pvt { // OSL::pvt
|
||||
/// code to implement a shader group.
|
||||
class BackendLLVM final : public OSOProcessorBase {
|
||||
public:
|
||||
BackendLLVM (ShadingSystemImpl &shadingsys, ShaderGroup &group,
|
||||
ShadingContext *context);
|
||||
BackendLLVM(ShadingSystemImpl& shadingsys, ShaderGroup& group,
|
||||
ShadingContext* context);
|
||||
|
||||
virtual ~BackendLLVM ();
|
||||
virtual ~BackendLLVM();
|
||||
|
||||
virtual void set_inst (int layer);
|
||||
virtual void set_inst(int layer);
|
||||
|
||||
/// Create an llvm function for the whole shader group, JIT it,
|
||||
/// and store the llvm::Function* handle to it with the ShaderGroup.
|
||||
virtual void run ();
|
||||
virtual void run();
|
||||
|
||||
|
||||
/// What LLVM debug level are we at?
|
||||
@@ -47,33 +47,33 @@ public:
|
||||
|
||||
/// Set up a bunch of static things we'll need for the whole group.
|
||||
///
|
||||
void initialize_llvm_group ();
|
||||
void initialize_llvm_group();
|
||||
|
||||
int layer_remap (int origlayer) const { return m_layer_remap[origlayer]; }
|
||||
int layer_remap(int origlayer) const { return m_layer_remap[origlayer]; }
|
||||
|
||||
/// Create an llvm function for the current shader instance.
|
||||
/// This will end up being the group entry if 'groupentry' is true.
|
||||
llvm::Function* build_llvm_instance (bool groupentry);
|
||||
llvm::Function* build_llvm_instance(bool groupentry);
|
||||
|
||||
/// Create an llvm function for group initialization code.
|
||||
llvm::Function* build_llvm_init ();
|
||||
llvm::Function* build_llvm_init();
|
||||
|
||||
/// Build up LLVM IR code for the given range [begin,end) or
|
||||
/// opcodes, putting them (initially) into basic block bb (or the
|
||||
/// current basic block if bb==NULL).
|
||||
bool build_llvm_code (int beginop, int endop, llvm::BasicBlock *bb=NULL);
|
||||
bool build_llvm_code(int beginop, int endop, llvm::BasicBlock* bb = NULL);
|
||||
|
||||
typedef std::map<std::string, llvm::Value*> AllocationMap;
|
||||
|
||||
void llvm_assign_initial_value (const Symbol& sym, bool force = false);
|
||||
llvm::LLVMContext &llvm_context () const { return ll.context(); }
|
||||
AllocationMap &named_values () { return m_named_values; }
|
||||
void llvm_assign_initial_value(const Symbol& sym, bool force = false);
|
||||
llvm::LLVMContext& llvm_context() const { return ll.context(); }
|
||||
AllocationMap& named_values() { return m_named_values; }
|
||||
|
||||
/// Return an llvm::Value* corresponding to the address of the given
|
||||
/// symbol element, with derivative (0=value, 1=dx, 2=dy) and array
|
||||
/// index (NULL if it's not an array).
|
||||
llvm::Value *llvm_get_pointer (const Symbol& sym, int deriv=0,
|
||||
llvm::Value *arrayindex=NULL);
|
||||
llvm::Value* llvm_get_pointer(const Symbol& sym, int deriv = 0,
|
||||
llvm::Value* arrayindex = NULL);
|
||||
|
||||
/// Return the llvm::Value* corresponding to the given element
|
||||
/// value, with derivative (0=value, 1=dx, 2=dy), array index (NULL
|
||||
@@ -83,9 +83,9 @@ public:
|
||||
/// return the scalar -- this allows automatic casting to triples.
|
||||
/// Finally, auto-cast int<->float if requested (no conversion is
|
||||
/// performed if cast is the default of UNKNOWN).
|
||||
llvm::Value *llvm_load_value (const Symbol& sym, int deriv,
|
||||
llvm::Value *arrayindex, int component,
|
||||
TypeDesc cast=TypeDesc::UNKNOWN);
|
||||
llvm::Value* llvm_load_value(const Symbol& sym, int deriv,
|
||||
llvm::Value* arrayindex, int component,
|
||||
TypeDesc cast = TypeDesc::UNKNOWN);
|
||||
|
||||
|
||||
/// Given an llvm::Value* of a pointer (and the type of the data
|
||||
@@ -97,62 +97,71 @@ public:
|
||||
/// and it's a scalar, return the scalar -- this allows automatic
|
||||
/// casting to triples. Finally, auto-cast int<->float if requested
|
||||
/// (no conversion is performed if cast is the default of UNKNOWN).
|
||||
llvm::Value *llvm_load_value (llvm::Value *ptr, const TypeSpec &type,
|
||||
int deriv, llvm::Value *arrayindex,
|
||||
int component, TypeDesc cast=TypeDesc::UNKNOWN);
|
||||
llvm::Value* llvm_load_value(llvm::Value* ptr, const TypeSpec& type,
|
||||
int deriv, llvm::Value* arrayindex,
|
||||
int component,
|
||||
TypeDesc cast = TypeDesc::UNKNOWN,
|
||||
const std::string& llname = {});
|
||||
|
||||
/// Just like llvm_load_value, but when both the symbol and the
|
||||
/// array index are known to be constants. This can even handle
|
||||
/// pulling constant-indexed elements out of constant arrays. Use
|
||||
/// arrayindex==-1 to indicate that it's not an array dereference.
|
||||
llvm::Value *llvm_load_constant_value (const Symbol& sym,
|
||||
int arrayindex, int component,
|
||||
TypeDesc cast=TypeDesc::UNKNOWN);
|
||||
llvm::Value* llvm_load_constant_value(const Symbol& sym, int arrayindex,
|
||||
int component,
|
||||
TypeDesc cast = TypeDesc::UNKNOWN);
|
||||
|
||||
/// llvm_load_value with non-constant component designation. Does
|
||||
/// not work with arrays or do type casts!
|
||||
llvm::Value *llvm_load_component_value (const Symbol& sym, int deriv,
|
||||
llvm::Value *component);
|
||||
llvm::Value* llvm_load_component_value(const Symbol& sym, int deriv,
|
||||
llvm::Value* component);
|
||||
|
||||
/// Non-array version of llvm_load_value, with default deriv &
|
||||
/// component.
|
||||
llvm::Value *llvm_load_value (const Symbol& sym, int deriv = 0,
|
||||
int component = 0,
|
||||
TypeDesc cast=TypeDesc::UNKNOWN) {
|
||||
return (use_optix() && ! sym.typespec().is_closure() && sym.typespec().is_string())
|
||||
? llvm_load_device_string (sym, /*follow*/ true)
|
||||
: llvm_load_value (sym, deriv, NULL, component, cast);
|
||||
llvm::Value* llvm_load_value(const Symbol& sym, int deriv = 0,
|
||||
int component = 0,
|
||||
TypeDesc cast = TypeDesc::UNKNOWN)
|
||||
{
|
||||
return llvm_load_value(sym, deriv, NULL, component, cast);
|
||||
}
|
||||
|
||||
/// Load the address of a global device-side string pointer, which may
|
||||
/// reside in a global variable, the groupdata struct, or a local value.
|
||||
llvm::Value *llvm_load_device_string (const Symbol& sym, bool follow);
|
||||
|
||||
/// Convenience function to load a string for CPU or GPU device
|
||||
llvm::Value *llvm_load_string (const Symbol& sym) {
|
||||
llvm::Value* llvm_load_string(const Symbol& sym)
|
||||
{
|
||||
OSL_DASSERT(sym.typespec().is_string());
|
||||
return use_optix()
|
||||
? llvm_load_device_string(sym, /*follow*/ true)
|
||||
: llvm_load_value(sym);
|
||||
return llvm_load_value(sym);
|
||||
}
|
||||
|
||||
/// Convenience function to load a constant string for CPU or GPU device.
|
||||
/// On the GPU, we use the ustring hash, not the character pointer.
|
||||
llvm::Value* llvm_load_string(ustring str) { return ll.constant(str); }
|
||||
|
||||
llvm::Value* llvm_load_string(string_view str)
|
||||
{
|
||||
return llvm_load_string(ustring(str));
|
||||
}
|
||||
|
||||
/// Legacy version
|
||||
///
|
||||
llvm::Value *loadLLVMValue (const Symbol& sym, int component=0,
|
||||
int deriv=0, TypeDesc cast=TypeDesc::UNKNOWN) {
|
||||
return llvm_load_value (sym, deriv, NULL, component, cast);
|
||||
llvm::Value* loadLLVMValue(const Symbol& sym, int component = 0,
|
||||
int deriv = 0, TypeDesc cast = TypeDesc::UNKNOWN)
|
||||
{
|
||||
return llvm_load_value(sym, deriv, NULL, component, cast);
|
||||
}
|
||||
|
||||
/// Return an llvm::Value* that is either a scalar and derivs is
|
||||
/// false, or a pointer to sym's values (if sym is an aggregate or
|
||||
/// derivs == true). Furthermore, if deriv == true and sym doesn't
|
||||
/// have derivs, coerce it into a variable with zero derivs.
|
||||
llvm::Value *llvm_load_arg (const Symbol& sym, bool derivs);
|
||||
/// Return an llvm::Value* in the form that we will pass a float-based
|
||||
/// symbol as a function argument to any "built-in" OSL function -- as a
|
||||
/// simple value if the symbol is a scalar and no derivs are needed, or as
|
||||
/// a pointer to the data in all other cases (aggregates, arrays, or
|
||||
/// derivs needed). If deriv == true and sym doesn't have derivs, coerce
|
||||
/// it into a variable having derivatives set to 0.0.
|
||||
llvm::Value* llvm_load_arg(const Symbol& sym, bool derivs);
|
||||
|
||||
/// Just like llvm_load_arg(sym,deriv), except use use sym's derivs
|
||||
/// as-is, no coercion.
|
||||
llvm::Value *llvm_load_arg (const Symbol& sym) {
|
||||
return llvm_load_arg (sym, sym.has_derivs());
|
||||
llvm::Value* llvm_load_arg(const Symbol& sym)
|
||||
{
|
||||
return llvm_load_arg(sym, sym.has_derivs());
|
||||
}
|
||||
|
||||
/// Store new_val into the given symbol, given the derivative
|
||||
@@ -161,8 +170,8 @@ public:
|
||||
/// symbol doesn't have a deriv, it's a nop. If the component >0
|
||||
/// and it's a scalar, set the scalar. Returns true if ok, false
|
||||
/// upon failure.
|
||||
bool llvm_store_value (llvm::Value *new_val, const Symbol& sym, int deriv,
|
||||
llvm::Value *arrayindex, int component);
|
||||
bool llvm_store_value(llvm::Value* new_val, const Symbol& sym, int deriv,
|
||||
llvm::Value* arrayindex, int component);
|
||||
|
||||
/// Store new_val into the memory pointed to by dst_ptr, given the
|
||||
/// derivative (0=value, 1=dx, 2=dy), array index (NULL if it's not
|
||||
@@ -170,150 +179,160 @@ public:
|
||||
/// and the symbol doesn't have a deriv, it's a nop. If the
|
||||
/// component >0 and it's a scalar, set the scalar. Returns true if
|
||||
/// ok, false upon failure.
|
||||
bool llvm_store_value (llvm::Value* new_val, llvm::Value* dst_ptr,
|
||||
const TypeSpec &type, int deriv,
|
||||
llvm::Value* arrayindex, int component);
|
||||
bool llvm_store_value(llvm::Value* new_val, llvm::Value* dst_ptr,
|
||||
const TypeSpec& type, int deriv,
|
||||
llvm::Value* arrayindex, int component);
|
||||
|
||||
/// Non-array version of llvm_store_value, with default deriv &
|
||||
/// component.
|
||||
bool llvm_store_value (llvm::Value *new_val, const Symbol& sym,
|
||||
int deriv=0, int component=0) {
|
||||
return llvm_store_value (new_val, sym, deriv, NULL, component);
|
||||
bool llvm_store_value(llvm::Value* new_val, const Symbol& sym,
|
||||
int deriv = 0, int component = 0)
|
||||
{
|
||||
return llvm_store_value(new_val, sym, deriv, NULL, component);
|
||||
}
|
||||
|
||||
/// llvm_store_value with non-constant component designation. Does
|
||||
/// not work with arrays or do type casts!
|
||||
bool llvm_store_component_value (llvm::Value *new_val, const Symbol& sym,
|
||||
int deriv, llvm::Value *component);
|
||||
bool llvm_store_component_value(llvm::Value* new_val, const Symbol& sym,
|
||||
int deriv, llvm::Value* component);
|
||||
|
||||
/// Legacy version
|
||||
///
|
||||
bool storeLLVMValue (llvm::Value* new_val, const Symbol& sym,
|
||||
int component=0, int deriv=0) {
|
||||
return llvm_store_value (new_val, sym, deriv, component);
|
||||
bool storeLLVMValue(llvm::Value* new_val, const Symbol& sym,
|
||||
int component = 0, int deriv = 0)
|
||||
{
|
||||
return llvm_store_value(new_val, sym, deriv, component);
|
||||
}
|
||||
|
||||
/// Generate an alloca instruction to allocate space for the given
|
||||
/// type, with derivs if derivs==true, and return the its pointer.
|
||||
llvm::Value *llvm_alloca (const TypeSpec &type, bool derivs,
|
||||
const std::string &name="", int align=0);
|
||||
llvm::Value* llvm_alloca(const TypeSpec& type, bool derivs,
|
||||
const std::string& name = "", int align = 0);
|
||||
|
||||
/// Given the OSL symbol, return the llvm::Value* corresponding to the
|
||||
/// address of the start of that symbol (first element, first component,
|
||||
/// and just the plain value if it has derivatives). This is retrieved
|
||||
/// from the allocation map if already there; and if not yet in the
|
||||
/// map, the symbol is alloca'd and placed in the map.
|
||||
llvm::Value *getOrAllocateLLVMSymbol (const Symbol& sym);
|
||||
llvm::Value* getOrAllocateLLVMSymbol(const Symbol& sym);
|
||||
|
||||
/// Allocate a CUDA variable for the given OSL symbol and return a pointer
|
||||
/// to the corresponding LLVM GlobalVariable, or return the pointer if it
|
||||
/// has already been allocated.
|
||||
llvm::Value *getOrAllocateCUDAVariable (const Symbol& sym, bool addMetadata=false);
|
||||
llvm::Value* getOrAllocateCUDAVariable(const Symbol& sym);
|
||||
|
||||
/// Create a CUDA global variable and add it to the current Module
|
||||
llvm::Value *addCUDAVariable (const std::string& name, int size, int alignment,
|
||||
const void* data, TypeDesc type=TypeDesc::UNKNOWN);
|
||||
|
||||
/// Create the extra semantic information needed for OptiX variables
|
||||
void createOptixMetadata (const std::string& name, const Symbol& sym );
|
||||
/// Create a named CUDA global variable with the given type, size, and
|
||||
/// alignment, and add it to the current Module. It will be initialized
|
||||
/// with data pointed to by init_data. A record will be also added to
|
||||
/// m_const_map, and will be retrieved by subsequent calls to
|
||||
/// getOrAllocateCUDAVariable().
|
||||
llvm::Value* addCUDAGlobalVariable(const std::string& name, int size,
|
||||
int alignment, const void* init_data,
|
||||
TypeDesc type = TypeDesc::UNKNOWN);
|
||||
|
||||
/// Retrieve an llvm::Value that is a pointer holding the start address
|
||||
/// of the specified symbol. This always works for globals and params;
|
||||
/// for stack variables (locals/temps) is succeeds only if the symbol is
|
||||
/// already in the allocation table (will fail otherwise). This method
|
||||
/// is not designed to retrieve constants.
|
||||
llvm::Value *getLLVMSymbolBase (const Symbol &sym);
|
||||
llvm::Value* getLLVMSymbolBase(const Symbol& sym);
|
||||
|
||||
/// Retrieve the named global ("P", "N", etc.).
|
||||
llvm::Value *llvm_global_symbol_ptr (ustring name);
|
||||
llvm::Value* llvm_global_symbol_ptr(ustring name);
|
||||
|
||||
/// Test whether val is nonzero, return the llvm::Value* that's the
|
||||
/// result of a CreateICmpNE or CreateFCmpUNE (depending on the
|
||||
/// type). If test_derivs is true, it it also tests whether the
|
||||
/// derivs are zero.
|
||||
llvm::Value *llvm_test_nonzero (Symbol &val, bool test_derivs = false);
|
||||
llvm::Value* llvm_test_nonzero(Symbol& val, bool test_derivs = false);
|
||||
|
||||
/// Implementaiton of Simple assignment. If arrayindex >= 0, in
|
||||
/// Implementation of Simple assignment. If arrayindex >= 0, in
|
||||
/// designates a particular array index to assign.
|
||||
bool llvm_assign_impl (Symbol &Result, Symbol &Src, int arrayindex = -1,
|
||||
int srccomp = -1, int dstcomp = -1);
|
||||
bool llvm_assign_impl(Symbol& Result, Symbol& Src, int arrayindex = -1,
|
||||
int srccomp = -1, int dstcomp = -1);
|
||||
|
||||
|
||||
/// Convert the name of a global (and its derivative index) into the
|
||||
/// field number of the ShaderGlobals struct.
|
||||
int ShaderGlobalNameToIndex (ustring name);
|
||||
int ShaderGlobalNameToIndex(ustring name);
|
||||
|
||||
/// Return the LLVM type handle for the ShaderGlobals struct.
|
||||
///
|
||||
llvm::Type *llvm_type_sg ();
|
||||
llvm::Type* llvm_type_sg();
|
||||
|
||||
/// Return the LLVM type handle for a pointer to a
|
||||
/// ShaderGlobals struct.
|
||||
llvm::Type *llvm_type_sg_ptr ();
|
||||
llvm::Type* llvm_type_sg_ptr();
|
||||
|
||||
/// Return the ShaderGlobals pointer.
|
||||
///
|
||||
llvm::Value *sg_ptr () const { return m_llvm_shaderglobals_ptr; }
|
||||
llvm::Value* sg_ptr() const { return m_llvm_shaderglobals_ptr; }
|
||||
|
||||
llvm::Type *llvm_type_closure_component ();
|
||||
llvm::Type *llvm_type_closure_component_ptr ();
|
||||
llvm::Type* llvm_type_closure_component();
|
||||
llvm::Type* llvm_type_closure_component_ptr();
|
||||
|
||||
/// Return the ShaderGlobals pointer cast as a void*.
|
||||
///
|
||||
llvm::Value *sg_void_ptr () {
|
||||
return ll.void_ptr (m_llvm_shaderglobals_ptr);
|
||||
llvm::Value* sg_void_ptr() { return ll.void_ptr(m_llvm_shaderglobals_ptr); }
|
||||
|
||||
/// Cast the pointer variable specified by val to a pointer to the
|
||||
/// basic type comprising `type`.
|
||||
llvm::Value* llvm_ptr_cast(llvm::Value* val, const TypeSpec& type,
|
||||
const std::string& llname = {})
|
||||
{
|
||||
return ll.ptr_cast(val, type.simpletype(), llname);
|
||||
}
|
||||
|
||||
llvm::Value *llvm_ptr_cast (llvm::Value* val, const TypeSpec &type) {
|
||||
return ll.ptr_cast (val, type.simpletype());
|
||||
}
|
||||
|
||||
llvm::Value *llvm_void_ptr (const Symbol &sym, int deriv=0) {
|
||||
return ll.void_ptr (llvm_get_pointer(sym, deriv));
|
||||
llvm::Value* llvm_void_ptr(const Symbol& sym, int deriv = 0)
|
||||
{
|
||||
return ll.void_ptr(llvm_get_pointer(sym, deriv),
|
||||
llnamefmt("{}_voidptr", sym.mangled()));
|
||||
}
|
||||
|
||||
/// Return the LLVM type handle for a structure of the common group
|
||||
/// data that holds all the shader params.
|
||||
llvm::Type *llvm_type_groupdata ();
|
||||
llvm::Type* llvm_type_groupdata();
|
||||
|
||||
/// Return the LLVM type handle for a pointer to the common group
|
||||
/// data that holds all the shader params.
|
||||
llvm::Type *llvm_type_groupdata_ptr ();
|
||||
llvm::Type* llvm_type_groupdata_ptr();
|
||||
|
||||
/// Return the group data pointer.
|
||||
///
|
||||
llvm::Value *groupdata_ptr () const { return m_llvm_groupdata_ptr; }
|
||||
llvm::Value* groupdata_ptr() const { return m_llvm_groupdata_ptr; }
|
||||
|
||||
/// Return the group data pointer cast as a void*.
|
||||
///
|
||||
llvm::Value *groupdata_void_ptr () {
|
||||
return ll.void_ptr (m_llvm_groupdata_ptr);
|
||||
llvm::Value* groupdata_void_ptr()
|
||||
{
|
||||
return ll.void_ptr(m_llvm_groupdata_ptr);
|
||||
}
|
||||
|
||||
/// Return a reference to the specified field within the group data.
|
||||
llvm::Value *groupdata_field_ref (int fieldnum);
|
||||
llvm::Value* groupdata_field_ref(int fieldnum);
|
||||
|
||||
/// Return a pointer to the specified field within the group data,
|
||||
/// optionally cast to pointer to a particular data type.
|
||||
llvm::Value *groupdata_field_ptr (int fieldnum,
|
||||
TypeDesc type = TypeDesc::UNKNOWN);
|
||||
llvm::Value* groupdata_field_ptr(int fieldnum,
|
||||
TypeDesc type = TypeDesc::UNKNOWN);
|
||||
|
||||
/// Return the userdata base pointer.
|
||||
llvm::Value *userdata_base_ptr () const { return m_llvm_userdata_base_ptr; }
|
||||
llvm::Value* userdata_base_ptr() const { return m_llvm_userdata_base_ptr; }
|
||||
|
||||
/// Return the output base pointer.
|
||||
llvm::Value *output_base_ptr () const { return m_llvm_output_base_ptr; }
|
||||
llvm::Value* output_base_ptr() const { return m_llvm_output_base_ptr; }
|
||||
|
||||
/// Return the shade index
|
||||
llvm::Value *shadeindex () const { return m_llvm_shadeindex; }
|
||||
llvm::Value* shadeindex() const { return m_llvm_shadeindex; }
|
||||
|
||||
// For a symloc, compute the llvm::Value of the pointer to its true,
|
||||
// offset location from the base pointer for shade index `sindex`
|
||||
// (which should already be a i64, or if nullptr, then use
|
||||
// m_llvm_shadeindex and convert it to i64).
|
||||
llvm::Value *symloc_ptr(const SymLocationDesc* symloc,
|
||||
llvm::Value* symloc_ptr(const SymLocationDesc* symloc,
|
||||
llvm::Value* base_ptr,
|
||||
llvm::Value* sindex = nullptr) {
|
||||
llvm::Value* sindex = nullptr)
|
||||
{
|
||||
llvm::Value* offset = ll.constanti64(symloc->offset);
|
||||
llvm::Value* stride = ll.constanti64(symloc->stride);
|
||||
if (!sindex)
|
||||
@@ -324,47 +343,47 @@ public:
|
||||
|
||||
/// Return a ref to the bool where the "layer_run" flag is stored for
|
||||
/// the specified layer.
|
||||
llvm::Value *layer_run_ref (int layer);
|
||||
llvm::Value* layer_run_ref(int layer);
|
||||
|
||||
/// Return a ref to the bool where the "userdata_initialized" flag is
|
||||
/// stored for the specified userdata index.
|
||||
llvm::Value *userdata_initialized_ref (int userdata_index=0);
|
||||
llvm::Value* userdata_initialized_ref(int userdata_index = 0);
|
||||
|
||||
/// Generate LLVM code to zero out the variable (including derivs)
|
||||
///
|
||||
void llvm_assign_zero (const Symbol &sym);
|
||||
void llvm_assign_zero(const Symbol& sym);
|
||||
|
||||
/// Generate LLVM code to zero out the derivatives of sym.
|
||||
///
|
||||
void llvm_zero_derivs (const Symbol &sym);
|
||||
void llvm_zero_derivs(const Symbol& sym);
|
||||
|
||||
/// Generate LLVM code to zero out the derivatives of an array
|
||||
/// only for the first count elements of it.
|
||||
///
|
||||
void llvm_zero_derivs (const Symbol &sym, llvm::Value *count);
|
||||
void llvm_zero_derivs(const Symbol& sym, llvm::Value* count);
|
||||
|
||||
/// Generate a debugging printf at shader execution time.
|
||||
void llvm_gen_debug_printf (string_view message);
|
||||
void llvm_gen_debug_printf(string_view message);
|
||||
|
||||
/// Generate a warning message at shader execution time.
|
||||
void llvm_gen_warning (string_view message);
|
||||
void llvm_gen_warning(string_view message);
|
||||
|
||||
/// Generate an error message at shader execution time.
|
||||
void llvm_gen_error (string_view message);
|
||||
void llvm_gen_error(string_view message);
|
||||
|
||||
/// Generate code to call the given layer. If 'unconditional' is
|
||||
/// true, call it without even testing if the layer has already been
|
||||
/// called.
|
||||
void llvm_call_layer (int layer, bool unconditional = false);
|
||||
void llvm_call_layer(int layer, bool unconditional = false);
|
||||
|
||||
/// Execute the upstream connection (if any, and if not yet run) that
|
||||
/// establishes the value of symbol sym, which has index 'symindex'
|
||||
/// within the current layer rop.inst(). If already_run is not NULL,
|
||||
/// it points to a vector of layer indices that are known to have been
|
||||
/// it points to a vector of layer indices that are known to have been
|
||||
/// run -- those can be skipped without dynamically checking their
|
||||
/// execution status.
|
||||
void llvm_run_connected_layers (Symbol &sym, int symindex, int opnum = -1,
|
||||
std::set<int> *already_run = NULL);
|
||||
void llvm_run_connected_layers(Symbol& sym, int symindex, int opnum = -1,
|
||||
std::set<int>* already_run = NULL);
|
||||
|
||||
/// Generate code for a call to the named function with the given
|
||||
/// arg list as symbols -- float & ints will be passed by value,
|
||||
@@ -372,127 +391,161 @@ public:
|
||||
/// is true, pass pointers even for floats if they have derivs.
|
||||
/// Return an llvm::Value* corresponding to the return value of the
|
||||
/// function, if any.
|
||||
llvm::Value *llvm_call_function (const char *name, cspan<const Symbol *> args,
|
||||
bool deriv_ptrs=false);
|
||||
llvm::Value *llvm_call_function (const char *name, const Symbol &A,
|
||||
bool deriv_ptrs=false) {
|
||||
return llvm_call_function (name, { &A }, deriv_ptrs);
|
||||
llvm::Value* llvm_call_function(const char* name, cspan<const Symbol*> args,
|
||||
bool deriv_ptrs = false);
|
||||
llvm::Value* llvm_call_function(const char* name, const Symbol& A,
|
||||
bool deriv_ptrs = false)
|
||||
{
|
||||
return llvm_call_function(name, { &A }, deriv_ptrs);
|
||||
}
|
||||
llvm::Value *llvm_call_function (const char *name, const Symbol &A,
|
||||
const Symbol &B, bool deriv_ptrs=false) {
|
||||
return llvm_call_function (name, { &A, &B }, deriv_ptrs);
|
||||
llvm::Value* llvm_call_function(const char* name, const Symbol& A,
|
||||
const Symbol& B, bool deriv_ptrs = false)
|
||||
{
|
||||
return llvm_call_function(name, { &A, &B }, deriv_ptrs);
|
||||
}
|
||||
llvm::Value *llvm_call_function (const char *name, const Symbol &A,
|
||||
const Symbol &B, const Symbol &C,
|
||||
bool deriv_ptrs=false) {
|
||||
return llvm_call_function (name, { &A, &B, &C }, deriv_ptrs);
|
||||
llvm::Value* llvm_call_function(const char* name, const Symbol& A,
|
||||
const Symbol& B, const Symbol& C,
|
||||
bool deriv_ptrs = false)
|
||||
{
|
||||
return llvm_call_function(name, { &A, &B, &C }, deriv_ptrs);
|
||||
}
|
||||
|
||||
TypeDesc llvm_typedesc (const TypeSpec &typespec) {
|
||||
return typespec.is_closure_based()
|
||||
? TypeDesc(TypeDesc::PTR, typespec.arraylength())
|
||||
: typespec.simpletype();
|
||||
TypeDesc llvm_typedesc(const TypeSpec& typespec)
|
||||
{
|
||||
if (typespec.is_closure_based())
|
||||
return TypeDesc(TypeDesc::PTR, typespec.arraylength());
|
||||
else if (use_optix() && typespec.is_string_based()) {
|
||||
// On the OptiX side, we use the uint64 hash to represent a string
|
||||
return TypeDesc(TypeDesc::UINT64, typespec.arraylength());
|
||||
} else
|
||||
return typespec.simpletype();
|
||||
}
|
||||
|
||||
/// Generate the appropriate llvm type definition for a TypeSpec
|
||||
/// (this is the actual type, for example when we allocate it).
|
||||
/// Allocates ptrs for closures.
|
||||
llvm::Type *llvm_type (const TypeSpec &typespec) {
|
||||
return ll.llvm_type (llvm_typedesc(typespec));
|
||||
llvm::Type* llvm_type(const TypeSpec& typespec)
|
||||
{
|
||||
return ll.llvm_type(llvm_typedesc(typespec));
|
||||
}
|
||||
|
||||
/// Generate the parameter-passing llvm type definition for an OSL
|
||||
/// TypeSpec.
|
||||
llvm::Type *llvm_pass_type (const TypeSpec &typespec);
|
||||
llvm::Type* llvm_pass_type(const TypeSpec& typespec);
|
||||
|
||||
llvm::PointerType *llvm_type_prepare_closure_func() { return m_llvm_type_prepare_closure_func; }
|
||||
llvm::PointerType *llvm_type_setup_closure_func() { return m_llvm_type_setup_closure_func; }
|
||||
|
||||
/// Return the basic block of the exit for the whole instance.
|
||||
///
|
||||
bool llvm_has_exit_instance_block () const {
|
||||
return m_exit_instance_block;
|
||||
llvm::PointerType* llvm_type_prepare_closure_func()
|
||||
{
|
||||
return m_llvm_type_prepare_closure_func;
|
||||
}
|
||||
llvm::PointerType* llvm_type_setup_closure_func()
|
||||
{
|
||||
return m_llvm_type_setup_closure_func;
|
||||
}
|
||||
|
||||
/// Return the basic block of the exit for the whole instance.
|
||||
///
|
||||
llvm::BasicBlock *llvm_exit_instance_block () {
|
||||
if (! m_exit_instance_block) {
|
||||
std::string name = Strutil::sprintf ("%s_%d_exit_", inst()->layername(), inst()->id());
|
||||
m_exit_instance_block = ll.new_basic_block (name);
|
||||
bool llvm_has_exit_instance_block() const { return m_exit_instance_block; }
|
||||
|
||||
/// Return the basic block of the exit for the whole instance.
|
||||
///
|
||||
llvm::BasicBlock* llvm_exit_instance_block()
|
||||
{
|
||||
if (!m_exit_instance_block) {
|
||||
std::string name = llnamefmt("{}_{}_exit_", inst()->layername(),
|
||||
inst()->id());
|
||||
m_exit_instance_block = ll.new_basic_block(name);
|
||||
}
|
||||
return m_exit_instance_block;
|
||||
}
|
||||
|
||||
/// Check for inf/nan in all written-to arguments of the op
|
||||
void llvm_generate_debugnan (const Opcode &op);
|
||||
void llvm_generate_debugnan(const Opcode& op);
|
||||
/// Check for uninitialized values in all read-from arguments to the op
|
||||
void llvm_generate_debug_uninit (const Opcode &op);
|
||||
void llvm_generate_debug_uninit(const Opcode& op);
|
||||
/// Print debugging line for the op
|
||||
void llvm_generate_debug_op_printf (const Opcode &op);
|
||||
void llvm_generate_debug_op_printf(const Opcode& op);
|
||||
|
||||
llvm::Function *layer_func () const { return ll.current_function(); }
|
||||
llvm::Function* layer_func() const { return ll.current_function(); }
|
||||
|
||||
/// Call this when JITing a texture-like call, to track how many.
|
||||
void generated_texture_call (bool handle) {
|
||||
void generated_texture_call(bool handle)
|
||||
{
|
||||
shadingsys().m_stat_tex_calls_codegened += 1;
|
||||
if (handle)
|
||||
shadingsys().m_stat_tex_calls_as_handles += 1;
|
||||
}
|
||||
|
||||
/// Return the mapping from symbol names to GlobalVariables.
|
||||
std::map<std::string,llvm::GlobalVariable*>& get_const_map() { return m_const_map; }
|
||||
std::map<std::string, llvm::GlobalVariable*>& get_const_map()
|
||||
{
|
||||
return m_const_map;
|
||||
}
|
||||
|
||||
/// Return whether or not we are compiling for an OptiX-based renderer.
|
||||
bool use_optix() { return m_use_optix; }
|
||||
|
||||
/// Return if we should compile against free function versions of Renderer Service.
|
||||
bool use_rs_bitcode() { return m_use_rs_bitcode; }
|
||||
|
||||
/// Return the userdata index for the given Symbol. Return -1 if the Symbol
|
||||
/// is not an input parameter or is constant and therefore doesn't have an
|
||||
/// entry in the groupdata struct.
|
||||
int find_userdata_index (const Symbol& sym);
|
||||
int find_userdata_index(const Symbol& sym);
|
||||
|
||||
LLVM_Util ll;
|
||||
|
||||
private:
|
||||
std::vector<int> m_layer_remap; ///< Remapping of layer ordering
|
||||
std::set<int> m_layers_already_run; ///< List of layers run
|
||||
int m_num_used_layers; ///< Number of layers actually used
|
||||
// Utility for constructing names for llvm symbols. It creates a formatted
|
||||
// string if the shading system's "llvm_output_bitcode" option is set,
|
||||
// otherwise it takes a shortcut and returns an empty string (since nobody
|
||||
// is going to see the pretty bitcode anyway).
|
||||
template<typename Str, typename... Args>
|
||||
OSL_NODISCARD inline std::string llnamefmt(const Str& fmt,
|
||||
Args&&... args) const
|
||||
{
|
||||
return m_name_llvm_syms ? fmtformat(fmt, std::forward<Args>(args)...)
|
||||
: std::string();
|
||||
}
|
||||
|
||||
double m_stat_total_llvm_time; ///< total time spent on LLVM
|
||||
double m_stat_llvm_setup_time; ///< llvm setup time
|
||||
double m_stat_llvm_irgen_time; ///< llvm IR generation time
|
||||
double m_stat_llvm_opt_time; ///< llvm IR optimization time
|
||||
double m_stat_llvm_jit_time; ///< llvm JIT time
|
||||
private:
|
||||
std::vector<int> m_layer_remap; ///< Remapping of layer ordering
|
||||
std::set<int> m_layers_already_run; ///< List of layers run
|
||||
int m_num_used_layers; ///< Number of layers actually used
|
||||
|
||||
double m_stat_total_llvm_time; ///< total time spent on LLVM
|
||||
double m_stat_llvm_setup_time; ///< llvm setup time
|
||||
double m_stat_llvm_irgen_time; ///< llvm IR generation time
|
||||
double m_stat_llvm_opt_time; ///< llvm IR optimization time
|
||||
double m_stat_llvm_jit_time; ///< llvm JIT time
|
||||
|
||||
// LLVM stuff
|
||||
AllocationMap m_named_values;
|
||||
std::map<const Symbol*,int> m_param_order_map;
|
||||
llvm::Value *m_llvm_shaderglobals_ptr;
|
||||
llvm::Value *m_llvm_groupdata_ptr;
|
||||
llvm::Value *m_llvm_userdata_base_ptr;
|
||||
llvm::Value *m_llvm_output_base_ptr;
|
||||
llvm::Value *m_llvm_shadeindex;
|
||||
llvm::BasicBlock * m_exit_instance_block; // exit point for the instance
|
||||
llvm::Type *m_llvm_type_sg; // LLVM type of ShaderGlobals struct
|
||||
llvm::Type *m_llvm_type_groupdata; // LLVM type of group data
|
||||
llvm::Type *m_llvm_type_closure_component; // LLVM type for ClosureComponent
|
||||
llvm::PointerType *m_llvm_type_prepare_closure_func;
|
||||
llvm::PointerType *m_llvm_type_setup_closure_func;
|
||||
int m_llvm_local_mem; // Amount of memory we use for locals
|
||||
std::map<const Symbol*, int> m_param_order_map;
|
||||
llvm::Value* m_llvm_shaderglobals_ptr;
|
||||
llvm::Value* m_llvm_groupdata_ptr;
|
||||
llvm::Value* m_llvm_userdata_base_ptr;
|
||||
llvm::Value* m_llvm_output_base_ptr;
|
||||
llvm::Value* m_llvm_shadeindex;
|
||||
llvm::BasicBlock* m_exit_instance_block; // exit point for the instance
|
||||
llvm::Type* m_llvm_type_sg; // LLVM type of ShaderGlobals struct
|
||||
llvm::Type* m_llvm_type_groupdata; // LLVM type of group data
|
||||
llvm::Type* m_llvm_type_closure_component; // LLVM type for ClosureComponent
|
||||
llvm::PointerType* m_llvm_type_prepare_closure_func;
|
||||
llvm::PointerType* m_llvm_type_setup_closure_func;
|
||||
int m_llvm_local_mem; // Amount of memory we use for locals
|
||||
bool m_name_llvm_syms; // Whether to name LLVM symbols
|
||||
|
||||
// A mapping from symbol names to llvm::GlobalVariables
|
||||
std::map<std::string,llvm::GlobalVariable*> m_const_map;
|
||||
std::map<std::string, llvm::GlobalVariable*> m_const_map;
|
||||
|
||||
// A mapping from canonical strings to string variable names, used to
|
||||
// detect collisions that might occur due to using the string hash to
|
||||
// create variable names.
|
||||
std::map<std::string,std::string> m_varname_map;
|
||||
// Name of each indexed field in the groupdata, mostly for debugging.
|
||||
std::vector<std::string> m_groupdata_field_names;
|
||||
|
||||
bool m_use_optix; ///< Compile for OptiX?
|
||||
bool m_use_optix; ///< Compile for OptiX?
|
||||
bool m_use_rs_bitcode; /// To use free function versions of Renderer Service functions.
|
||||
|
||||
friend class ShadingSystemImpl;
|
||||
};
|
||||
|
||||
|
||||
}; // namespace pvt
|
||||
}; // namespace pvt
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
@@ -35,6 +35,7 @@ static ustring op_and("and");
|
||||
static ustring op_backfacing("backfacing");
|
||||
static ustring op_break("break");
|
||||
static ustring op_calculatenormal("calculatenormal");
|
||||
static ustring op_closure("closure");
|
||||
static ustring op_compl("compl");
|
||||
static ustring op_concat("concat");
|
||||
static ustring op_continue("continue");
|
||||
@@ -68,6 +69,9 @@ static ustring op_transformv("transformv");
|
||||
static ustring op_transformn("transformn");
|
||||
static ustring op_texture("texture");
|
||||
static ustring op_texture3d("texture3d");
|
||||
static ustring op_pointcloud_search("pointcloud_search");
|
||||
static ustring op_pointcloud_get("pointcloud_get");
|
||||
static ustring op_pointcloud_write("pointcloud_write");
|
||||
|
||||
// Shader global strings
|
||||
static ustring object2common("object2common");
|
||||
@@ -98,20 +102,25 @@ is_shader_global_uniform_by_name(ustring name);
|
||||
|
||||
namespace // Unnamed
|
||||
{
|
||||
|
||||
// Even when all inputs to an operation are uniform,
|
||||
// the results written to output symbols maybe varying.
|
||||
bool
|
||||
are_op_results_always_implicitly_varying(ustring opname)
|
||||
{
|
||||
return (opname == Strings::op_getmessage) | (opname == Strings::op_trace)
|
||||
| (opname == Strings::op_texture)
|
||||
| (opname == Strings::op_texture3d);
|
||||
| (opname == Strings::op_texture) | (opname == Strings::op_texture3d)
|
||||
| (opname == Strings::op_pointcloud_search)
|
||||
| (opname == Strings::op_pointcloud_get)
|
||||
| (opname == Strings::op_pointcloud_write)
|
||||
| (opname == Strings::op_closure);
|
||||
// Renderer might identify result of getattribute as always uniform
|
||||
// depending on the attribute itself, so it cannot
|
||||
// be "always" implicitly varying based solely on the opname.
|
||||
// We consider getattribute during discovery.
|
||||
}
|
||||
|
||||
|
||||
// Even when all inputs to an operation are varying,
|
||||
// the results written to output symbols maybe uniform.
|
||||
bool
|
||||
@@ -160,6 +169,8 @@ does_op_implementation_require_masking(ustring opname)
|
||||
return lazy_lookup.find(opname) != lazy_lookup.end();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Create some placeholder symbols for shader globals that have don't
|
||||
// normally have symbols.
|
||||
// Purpose is to allow our data structures to use Symbol * as a key
|
||||
@@ -174,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();
|
||||
@@ -191,16 +202,18 @@ struct Symbols4ProtectedShaderGlobals {
|
||||
, surfacearea(Strings::op_surfacearea, TypeSpec(), SymTypeGlobal)
|
||||
, time(Strings::time, TypeSpec(), SymTypeGlobal)
|
||||
{
|
||||
check_if_varing(shader2common);
|
||||
check_if_varing(object2common);
|
||||
check_if_varing(flipHandedness);
|
||||
check_if_varing(raytype);
|
||||
check_if_varing(backfacing);
|
||||
check_if_varing(surfacearea);
|
||||
check_if_varing(time);
|
||||
check_if_varying(shader2common);
|
||||
check_if_varying(object2common);
|
||||
check_if_varying(flipHandedness);
|
||||
check_if_varying(raytype);
|
||||
check_if_varying(backfacing);
|
||||
check_if_varying(surfacearea);
|
||||
check_if_varying(time);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
Symbols4ProtectedShaderGlobals&
|
||||
psg()
|
||||
{
|
||||
@@ -227,8 +240,7 @@ private:
|
||||
static constexpr OpcodeTest no_test = nullptr;
|
||||
|
||||
// Map opcode names to a Dependency info
|
||||
std::unordered_map<ustring, Dependency, ustringHash> m_lookup;
|
||||
|
||||
std::unordered_map<ustring, Dependency> m_lookup;
|
||||
|
||||
/// Return the ptr to the symbol that is the argnum-th argument to the
|
||||
/// given op in the instance.
|
||||
@@ -253,8 +265,8 @@ private:
|
||||
// We can know all the space names at this time
|
||||
ustring from = From ? *((ustring*)From->data())
|
||||
: Strings::common;
|
||||
ustring to = *((ustring*)To->data());
|
||||
ustring syn = inst.shadingsys().commonspace_synonym();
|
||||
ustring to = *((ustring*)To->data());
|
||||
ustring syn = inst.shadingsys().commonspace_synonym();
|
||||
if (from == syn)
|
||||
from = Strings::common;
|
||||
if (to == syn)
|
||||
@@ -349,6 +361,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
static SymbolPtrVec*
|
||||
protected_shader_globals_op_implicitly_depends_on(ShaderInstance& inst,
|
||||
Opcode& opcode)
|
||||
@@ -357,17 +371,20 @@ protected_shader_globals_op_implicitly_depends_on(ShaderInstance& inst,
|
||||
return lazyDependencies.lookup(inst, opcode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
is_op_result_always_logically_boolean(ustring opname)
|
||||
{
|
||||
// Test if explicit comparison is faster or not
|
||||
static boost::container::flat_set<ustring> lazy_lookup(
|
||||
{ Strings::op_getattribute, Strings::op_eq,
|
||||
Strings::op_ge, Strings::op_gt, Strings::op_le, Strings::op_lt,
|
||||
Strings::op_neq, Strings::op_and, Strings::op_or });
|
||||
{ Strings::op_getattribute, Strings::op_eq, Strings::op_ge,
|
||||
Strings::op_gt, Strings::op_le, Strings::op_lt, Strings::op_neq,
|
||||
Strings::op_and, Strings::op_or });
|
||||
return lazy_lookup.find(opname) != lazy_lookup.end();
|
||||
}
|
||||
|
||||
|
||||
// TODO: Add more analysis to identify boolean results from the class of
|
||||
// operations who would produce a boolean result if given boolean inputs.
|
||||
// For example complement (~) would have a boolean result when passed a
|
||||
@@ -377,7 +394,8 @@ is_op_result_always_logically_boolean(ustring opname)
|
||||
// comparison operators even if the are not "currently"
|
||||
// being referenced. May need to disable some warnings
|
||||
// error #177: function "..." was declared but never referenced
|
||||
OSL_INTEL_PRAGMA(warning ( disable:177 ))
|
||||
OSL_INTEL_PRAGMA(warning(disable : 177))
|
||||
|
||||
|
||||
// The Position returned by top_pos changes and symbols are pushed and popped.
|
||||
// However any given position is invariant as scopes change, and one
|
||||
@@ -437,7 +455,6 @@ public:
|
||||
|
||||
DependencyTreeTracker(const DependencyTreeTracker&) = delete;
|
||||
|
||||
|
||||
class Iterator {
|
||||
Position m_pos;
|
||||
const DependencyTreeTracker* m_dtt;
|
||||
@@ -602,8 +619,21 @@ public:
|
||||
--m_current_depth;
|
||||
}
|
||||
|
||||
|
||||
Position common_ancestor_between(Position read_pos, Position write_pos)
|
||||
{
|
||||
// Early out when read and write are at the same position
|
||||
if (read_pos == write_pos)
|
||||
return read_pos;
|
||||
// Early out if either position is the root of the dependency tree
|
||||
if (read_pos == end_pos() || write_pos == end_pos())
|
||||
return end_pos();
|
||||
return search_for_common_ancestor_between(read_pos, write_pos);
|
||||
}
|
||||
|
||||
// Because this function makes use of stack arrays, ensure is NOT inlined
|
||||
// inside a loop to avoid repeatedly reserve stack space each iteration
|
||||
OSL_NOINLINE Position search_for_common_ancestor_between(Position read_pos,
|
||||
Position write_pos)
|
||||
{
|
||||
// To find common anscenstor
|
||||
// Walk up both paths building 2 stacks of positions
|
||||
@@ -613,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
|
||||
@@ -628,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
|
||||
@@ -641,31 +671,53 @@ public:
|
||||
++write_iter;
|
||||
}
|
||||
}
|
||||
const int levelCount = std::min(read_depth, write_depth);
|
||||
const int read_level = read_depth - 1;
|
||||
const int write_level = write_depth - 1;
|
||||
OSL_ASSERT(write_path[write_level] == end_pos());
|
||||
OSL_ASSERT(read_path[read_level] == end_pos());
|
||||
|
||||
const int walkCount = std::min(read_depth, write_depth);
|
||||
const int read_top = read_depth - 1;
|
||||
const int write_top = write_depth - 1;
|
||||
OSL_DASSERT(write_top < writeCount);
|
||||
OSL_DASSERT(write_path[write_top] == end_pos());
|
||||
OSL_DASSERT(read_top < read_count);
|
||||
OSL_DASSERT(read_path[read_top] == end_pos());
|
||||
|
||||
int walkDepth = 0;
|
||||
// Verify top of read and write stacks match positions
|
||||
OSL_DASSERT((read_top - walkDepth) >= 0);
|
||||
OSL_DASSERT((read_top - walkDepth) < read_count);
|
||||
OSL_DASSERT((write_top - walkDepth) >= 0);
|
||||
OSL_DASSERT((write_top - walkDepth) < writeCount);
|
||||
OSL_DASSERT(read_path[read_top - walkDepth]
|
||||
== write_path[write_top - walkDepth]);
|
||||
// That position should technically be the root (no conditions in the dependency tree)
|
||||
OSL_DASSERT(read_path[read_top - walkDepth] == end_pos());
|
||||
// Because we know walkDepth 0 never differs, we can start iterating
|
||||
// at walkDepth 1
|
||||
|
||||
int level = 0;
|
||||
OSL_ASSERT(read_path[read_level - level]
|
||||
== write_path[write_level - level]);
|
||||
do {
|
||||
++level;
|
||||
if (read_path[read_level - level]()
|
||||
!= write_path[write_level - level]())
|
||||
// Walk down the read and write paths until they differ
|
||||
for (walkDepth = 1; walkDepth < walkCount; ++walkDepth) {
|
||||
OSL_DASSERT((read_top - walkDepth) >= 0);
|
||||
OSL_DASSERT((read_top - walkDepth) < read_count);
|
||||
OSL_DASSERT((write_top - walkDepth) >= 0);
|
||||
OSL_DASSERT((write_top - walkDepth) < writeCount);
|
||||
if (read_path[read_top - walkDepth]()
|
||||
!= write_path[write_top - walkDepth]()) {
|
||||
break;
|
||||
} while (level < levelCount);
|
||||
--level;
|
||||
OSL_ASSERT(read_path[read_level - level]
|
||||
== write_path[write_level - level]);
|
||||
OSL_ASSERT(read_level - level >= 0);
|
||||
return read_path[read_level - level];
|
||||
}
|
||||
}
|
||||
// The previous walk depth's position was the common ancestor
|
||||
--walkDepth;
|
||||
OSL_DASSERT((read_top - walkDepth) >= 0);
|
||||
OSL_DASSERT((read_top - walkDepth) < read_count);
|
||||
OSL_DASSERT((write_top - walkDepth) >= 0);
|
||||
OSL_DASSERT((write_top - walkDepth) < writeCount);
|
||||
OSL_DASSERT(read_path[read_top - walkDepth]
|
||||
== write_path[write_top - walkDepth]);
|
||||
return read_path[read_top - walkDepth];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Historically tracks stack of functions
|
||||
// The Position returned by top_pos changes and function scopes are pushed and popped.
|
||||
// However any given position is invariant as scopes change
|
||||
@@ -741,7 +793,6 @@ public:
|
||||
|
||||
FunctionTreeTracker(const FunctionTreeTracker&) = delete;
|
||||
|
||||
|
||||
class Iterator {
|
||||
Position m_pos;
|
||||
const FunctionTreeTracker* m_ftt;
|
||||
@@ -955,7 +1006,6 @@ public:
|
||||
m_nodes.push_back(node);
|
||||
}
|
||||
|
||||
|
||||
OSL_FORCEINLINE Position top_pos() const { return m_top_of_stack; }
|
||||
|
||||
OSL_FORCEINLINE void pop_function_call()
|
||||
@@ -989,6 +1039,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class WriteEvent {
|
||||
DependencyTreeTracker::Position m_pos_in_tree;
|
||||
int m_op_num;
|
||||
@@ -1028,18 +1080,22 @@ public:
|
||||
return m_op_num;
|
||||
}
|
||||
|
||||
|
||||
OSL_FORCEINLINE int loop_op_index() const { return m_loop_op_index; }
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector<WriteEvent> WriteChronology;
|
||||
//typedef llvm::SmallVector<WriteEvent, 8> WriteChronology;
|
||||
|
||||
|
||||
|
||||
class ReadEvent {
|
||||
DependencyTreeTracker::Position m_pos_in_tree;
|
||||
#ifdef OSL_DEV
|
||||
int m_op_num;
|
||||
int m_loop_op_index;
|
||||
#endif
|
||||
|
||||
public:
|
||||
ReadEvent(DependencyTreeTracker::Position pos_in_tree_
|
||||
#ifdef OSL_DEV
|
||||
@@ -1061,16 +1117,25 @@ public:
|
||||
}
|
||||
|
||||
#ifdef OSL_DEV
|
||||
OSL_FORCEINLINE int op_num() const { return m_op_num; }
|
||||
OSL_FORCEINLINE int op_num() const
|
||||
{
|
||||
return m_op_num;
|
||||
}
|
||||
|
||||
OSL_FORCEINLINE int loop_op_index() const { return m_loop_op_index; }
|
||||
OSL_FORCEINLINE int loop_op_index() const
|
||||
{
|
||||
return m_loop_op_index;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector<ReadEvent> ReadChronology;
|
||||
// Testing showed 6 read events a typically max
|
||||
//typedef llvm::SmallVector<ReadEvent, 6> ReadChronology;
|
||||
|
||||
|
||||
|
||||
class LoopStack {
|
||||
std::vector<int> m_conditions_op_index_stack;
|
||||
std::vector<const Symbol*> m_conditions_symbol_stack;
|
||||
@@ -1150,6 +1215,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct ReadBranch {
|
||||
DependencyTreeTracker::Position pos;
|
||||
int depth; // how deep in the m_conditional_symbol_stack did the read occur
|
||||
@@ -1161,6 +1228,8 @@ struct ReadBranch {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct Analyzer {
|
||||
BatchedAnalysis& m_ba;
|
||||
ShaderInstance* m_inst;
|
||||
@@ -1196,7 +1265,6 @@ struct Analyzer {
|
||||
|
||||
std::unordered_set<Symbol*> m_symbols_written_to_by_implicitly_varying_ops;
|
||||
|
||||
|
||||
// Remember which symbols we've force to be boolean so we can
|
||||
// reverse that decision if we see them used by any boolean operations
|
||||
std::unordered_set<Symbol*> m_symbols_logically_bool;
|
||||
@@ -1357,7 +1425,8 @@ struct Analyzer {
|
||||
op(write_op_num).requires_masking(true);
|
||||
OSL_DEV_ONLY(
|
||||
std::cout
|
||||
<< "cyclic read of " << symbol_to_check->name().c_str()
|
||||
<< "cyclic read of "
|
||||
<< symbol_to_check->unmangled().c_str()
|
||||
<< " from loop [" << read_iter->loop_op_index()
|
||||
<< "] op(" << write_op_num << ").requires_masking()="
|
||||
<< op(write_op_num).requires_masking() << std::endl);
|
||||
@@ -1378,7 +1447,7 @@ struct Analyzer {
|
||||
#ifdef OSL_DEV
|
||||
else {
|
||||
std::cout << "rejected cyclic read of "
|
||||
<< symbol_to_check->name().c_str()
|
||||
<< symbol_to_check->unmangled().c_str()
|
||||
<< " from loop [" << read_iter->loop_op_index()
|
||||
<< "] for opnum[" << write_op_num << "]"
|
||||
<< std::endl;
|
||||
@@ -1433,8 +1502,8 @@ struct Analyzer {
|
||||
<< m_execution_scope_stack.end_pos()()
|
||||
<< " write_scope_pos()="
|
||||
<< write_scope_pos()
|
||||
<< " symbol_to_check->name()="
|
||||
<< symbol_to_check->name().c_str()
|
||||
<< " symbol_to_check->unmangled()="
|
||||
<< symbol_to_check->unmangled().c_str()
|
||||
<< std::endl);
|
||||
}
|
||||
} else {
|
||||
@@ -1454,8 +1523,8 @@ struct Analyzer {
|
||||
[write_iter->op_num()]()
|
||||
<< " write_scope_pos()="
|
||||
<< write_scope_pos()
|
||||
<< " symbol_to_check->name()="
|
||||
<< symbol_to_check->name().c_str()
|
||||
<< " symbol_to_check->unmangled()="
|
||||
<< symbol_to_check->unmangled().c_str()
|
||||
<< std::endl);
|
||||
}
|
||||
}
|
||||
@@ -1484,11 +1553,12 @@ struct Analyzer {
|
||||
for (auto cond_iter = m_conditional_symbol_stack.begin();
|
||||
*cond_iter != loop_condition; ++cond_iter) {
|
||||
auto conditionContinueDependsOn = *cond_iter;
|
||||
OSL_DEV_ONLY(std::cout << ">>>Loop Conditional "
|
||||
<< loop_condition->name().c_str()
|
||||
<< " needs to depend on conditional "
|
||||
<< conditionContinueDependsOn->name().c_str()
|
||||
<< std::endl);
|
||||
OSL_DEV_ONLY(std::cout
|
||||
<< ">>>Loop Conditional "
|
||||
<< loop_condition->unmangled().c_str()
|
||||
<< " needs to depend on conditional "
|
||||
<< conditionContinueDependsOn->unmangled().c_str()
|
||||
<< std::endl);
|
||||
m_symbols_dependent_upon.insert(
|
||||
std::make_pair(conditionContinueDependsOn, loop_condition));
|
||||
}
|
||||
@@ -1522,9 +1592,9 @@ struct Analyzer {
|
||||
symbols_read_by_op[read_count++] = sym;
|
||||
OSL_DEV_ONLY(std::cout << " read from ");
|
||||
}
|
||||
OSL_DEV_ONLY(std::cout << " " << sym->name());
|
||||
OSL_DEV_ONLY(std::cout << " " << sym->unmangled());
|
||||
|
||||
OSL_DEV_ONLY(std::cout << " discovery " << sym->name()
|
||||
OSL_DEV_ONLY(std::cout << " discovery " << sym->unmangled()
|
||||
<< std::endl);
|
||||
}
|
||||
OSL_DEV_ONLY(std::cout << std::endl);
|
||||
@@ -1571,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
|
||||
@@ -1618,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) {
|
||||
@@ -1712,7 +1782,6 @@ struct Analyzer {
|
||||
m_deferred_op_indices_to_be_masked.push_back(op_index);
|
||||
}
|
||||
|
||||
|
||||
// Track dependencies between symbols written to in this basic block
|
||||
// to the set of symbols the code blocks where dependent upon to be executed
|
||||
m_pos_in_dependent_sym_stack_by_op_index[op_index]
|
||||
@@ -1782,7 +1851,6 @@ struct Analyzer {
|
||||
OSL_ASSERT(read_count == 1);
|
||||
m_loop_stack.push_loop(op_index, symbols_read_by_op[0]);
|
||||
|
||||
|
||||
// Body block
|
||||
OSL_DEV_ONLY(std::cout << " FOR BODY BLOCK BEGIN"
|
||||
<< std::endl);
|
||||
@@ -1803,7 +1871,6 @@ struct Analyzer {
|
||||
OSL_ASSERT(m_conditional_symbol_stack.top() == condition);
|
||||
m_conditional_symbol_stack.pop();
|
||||
|
||||
|
||||
// Condition block
|
||||
// NOTE: Processing condition like it was a do/while
|
||||
// Although the first execution of the condition doesn't depend on the for loops conditions
|
||||
@@ -1831,7 +1898,6 @@ struct Analyzer {
|
||||
m_conditional_symbol_stack.pop();
|
||||
m_loop_stack.pop_loop(op_index);
|
||||
|
||||
|
||||
} else if (opcode.opname() == Strings::op_functioncall) {
|
||||
// Function call itself operates on the same symbol dependencies
|
||||
// as the current block, there was no conditionals involved
|
||||
@@ -2000,8 +2066,9 @@ struct Analyzer {
|
||||
continue;
|
||||
// Skip if it's an interpolated (userdata) parameter and we're
|
||||
// initializing them lazily.
|
||||
if (s.symtype() == SymTypeParam && !s.lockgeom()
|
||||
&& !s.typespec().is_closure() && !s.connected()
|
||||
if ((s.symtype() == SymTypeParam
|
||||
|| s.symtype() == SymTypeOutputParam)
|
||||
&& !s.lockgeom() && !s.typespec().is_closure() && !s.connected()
|
||||
&& !s.connected_down() && m_ba.shadingsys().lazy_userdata())
|
||||
continue;
|
||||
// Set initial value for params (may contain init ops)
|
||||
@@ -2096,7 +2163,7 @@ struct Analyzer {
|
||||
auto sym_written_to = opargsym(opcode, arg_index);
|
||||
#ifdef OSL_DEV
|
||||
std::cout << "Symbol written to "
|
||||
<< sym_written_to->name().c_str()
|
||||
<< sym_written_to->unmangled().c_str()
|
||||
<< std::endl;
|
||||
std::cout << "begin_dep_iter "
|
||||
<< begin_dep_iter.pos()() << std::endl;
|
||||
@@ -2111,7 +2178,8 @@ struct Analyzer {
|
||||
OSL_DEV_ONLY(
|
||||
std::cout
|
||||
<< "Mapping "
|
||||
<< sym_mask_depends_on->name().c_str()
|
||||
<< sym_mask_depends_on->unmangled()
|
||||
.c_str()
|
||||
<< std::endl);
|
||||
m_symbols_dependent_upon.insert(
|
||||
std::make_pair(sym_mask_depends_on,
|
||||
@@ -2133,7 +2201,7 @@ struct Analyzer {
|
||||
#endif
|
||||
const auto& early_out = *earlyOutIter;
|
||||
auto begin_dep_iter = m_conditional_symbol_stack.begin_at(
|
||||
early_out.dtt_pos);
|
||||
early_out.dtt_pos);
|
||||
auto end_dep_iter = m_conditional_symbol_stack.end();
|
||||
|
||||
const Opcode& opcode = m_opcodes[op_index];
|
||||
@@ -2144,7 +2212,7 @@ struct Analyzer {
|
||||
auto sym_written_to = opargsym(opcode, arg_index);
|
||||
#ifdef OSL_DEV
|
||||
std::cout << "Symbol written to "
|
||||
<< sym_written_to->name().c_str()
|
||||
<< sym_written_to->unmangled().c_str()
|
||||
<< std::endl;
|
||||
std::cout << "begin_dep_iter "
|
||||
<< begin_dep_iter.pos()() << std::endl;
|
||||
@@ -2159,7 +2227,8 @@ struct Analyzer {
|
||||
OSL_DEV_ONLY(
|
||||
std::cout
|
||||
<< "Mapping "
|
||||
<< sym_mask_depends_on->name().c_str()
|
||||
<< sym_mask_depends_on->unmangled()
|
||||
.c_str()
|
||||
<< std::endl);
|
||||
m_symbols_dependent_upon.insert(
|
||||
std::make_pair(sym_mask_depends_on,
|
||||
@@ -2228,8 +2297,7 @@ struct Analyzer {
|
||||
// our symbols appropriately!
|
||||
FOREACH_PARAM(Symbol & s, inst())
|
||||
{
|
||||
if (s.everread() && !s.lockgeom() && !s.typespec().is_closure()
|
||||
&& !(s.symtype() == SymTypeOutputParam)) {
|
||||
if (s.everread() && !s.lockgeom() && !s.typespec().is_closure()) {
|
||||
recursively_mark_varying(&s);
|
||||
}
|
||||
}
|
||||
@@ -2257,10 +2325,10 @@ struct Analyzer {
|
||||
// then the dest must be made varying as well
|
||||
if (srcsym->is_varying()) {
|
||||
OSL_DEV_ONLY(std::cout
|
||||
<< "symbol " << srcsym->name().c_str()
|
||||
<< "symbol " << srcsym->unmangled().c_str()
|
||||
<< " from layer " << con.srclayer
|
||||
<< " is varying and connected to symbol "
|
||||
<< dstsym->name().c_str() << std::endl);
|
||||
<< dstsym->unmangled().c_str() << std::endl);
|
||||
recursively_mark_varying(dstsym);
|
||||
}
|
||||
}
|
||||
@@ -2273,7 +2341,7 @@ struct Analyzer {
|
||||
OSL_DEV_ONLY(std::cout << "symbolsWrittenToByImplicitlyVaryingOps begin"
|
||||
<< std::endl);
|
||||
for (auto s : m_symbols_written_to_by_implicitly_varying_ops) {
|
||||
OSL_DEV_ONLY(std::cout << s->name() << std::endl);
|
||||
OSL_DEV_ONLY(std::cout << s->unmangled() << std::endl);
|
||||
recursively_mark_varying(s);
|
||||
}
|
||||
OSL_DEV_ONLY(std::cout << "symbolsWrittenToByImplicitlyVaryingOps end"
|
||||
@@ -2291,12 +2359,16 @@ struct Analyzer {
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
BatchedAnalysis::BatchedAnalysis(ShadingSystemImpl& shadingsys,
|
||||
ShaderGroup& group)
|
||||
: m_shadingsys(shadingsys), m_group(group)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedAnalysis::analyze_layer(ShaderInstance* inst)
|
||||
{
|
||||
@@ -2333,6 +2405,8 @@ BatchedAnalysis::analyze_layer(ShaderInstance* inst)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedAnalysis::dump_symbol_uniformity(ShaderInstance* inst)
|
||||
{
|
||||
@@ -2341,7 +2415,7 @@ BatchedAnalysis::dump_symbol_uniformity(ShaderInstance* inst)
|
||||
|
||||
FOREACH_SYM(Symbol & s, inst)
|
||||
{
|
||||
std::cout << "--->" << &s << " " << s.name() << " is "
|
||||
std::cout << "--->" << &s << " " << s.unmangled() << " is "
|
||||
<< (s.is_uniform() ? "UNIFORM" : "VARYING") << std::endl;
|
||||
}
|
||||
std::cout << std::flush;
|
||||
@@ -2349,6 +2423,8 @@ BatchedAnalysis::dump_symbol_uniformity(ShaderInstance* inst)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedAnalysis::dump_layer(ShaderInstance* inst)
|
||||
{
|
||||
@@ -2412,7 +2488,7 @@ BatchedAnalysis::dump_layer(ShaderInstance* inst)
|
||||
FOREACH_SYM(Symbol & s, inst)
|
||||
{
|
||||
if (s.forced_llvm_bool()) {
|
||||
std::cout << "--->" << &s << " " << s.name()
|
||||
std::cout << "--->" << &s << " " << s.unmangled()
|
||||
<< " is forced_llvm_bool" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,11 +45,12 @@ static ustring fields[] = {
|
||||
ustring("objdata"), //
|
||||
ustring("shadingcontext"), //
|
||||
ustring("renderer"), //
|
||||
Strings::Ci, //
|
||||
Strings::raytype, //
|
||||
ustring("pad0"), //
|
||||
ustring("pad1"), //
|
||||
ustring("pad2"), //
|
||||
ustring("pad3"), //
|
||||
ustring("pad4"), //
|
||||
// Varying
|
||||
Strings::P, //
|
||||
ustring("dPdz"), //
|
||||
@@ -66,6 +67,7 @@ static ustring fields[] = {
|
||||
Strings::Ps, //
|
||||
Strings::object2common, //
|
||||
Strings::shader2common, //
|
||||
Strings::Ci, //
|
||||
Strings::surfacearea, //
|
||||
Strings::flipHandedness, //
|
||||
Strings::backfacing
|
||||
@@ -78,11 +80,12 @@ static bool field_is_uniform[] = {
|
||||
true, // objdata
|
||||
true, // shadingcontext
|
||||
true, // renderer
|
||||
true, // Ci
|
||||
true, // raytype
|
||||
true, // pad0
|
||||
true, // pad1
|
||||
true, // pad2
|
||||
true, // pad3
|
||||
true, // pad4
|
||||
// Varying
|
||||
false, // P
|
||||
false, // dPdz
|
||||
@@ -99,6 +102,7 @@ static bool field_is_uniform[] = {
|
||||
false, // Ps
|
||||
false, // object2common
|
||||
false, // shader2common
|
||||
false, // Ci,
|
||||
false, // surfacearea
|
||||
false, // flipHandedness
|
||||
false, // backfacing
|
||||
@@ -184,7 +188,7 @@ BatchedBackendLLVM::llvm_pass_type(const TypeSpec& typespec)
|
||||
else if (t == TypeDesc::INT)
|
||||
lt = ll.type_int();
|
||||
else if (t == TypeDesc::STRING)
|
||||
lt = (llvm::Type*)ll.type_string();
|
||||
lt = (llvm::Type*)ll.type_ustring();
|
||||
else if (t.aggregate == TypeDesc::VEC3)
|
||||
lt = (llvm::Type*)ll.type_void_ptr(); //llvm_type_triple_ptr();
|
||||
else if (t.aggregate == TypeDesc::MATRIX44)
|
||||
@@ -205,6 +209,8 @@ BatchedBackendLLVM::llvm_pass_type(const TypeSpec& typespec)
|
||||
return lt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Type*
|
||||
BatchedBackendLLVM::llvm_pass_wide_type(const TypeSpec& typespec)
|
||||
{
|
||||
@@ -263,6 +269,11 @@ BatchedBackendLLVM::llvm_assign_zero(const Symbol& sym)
|
||||
zero = ll.constant(ustring());
|
||||
else
|
||||
zero = ll.wide_constant(ustring());
|
||||
} else if (elemtype.is_closure_based()) {
|
||||
if (sym.is_uniform())
|
||||
zero = ll.void_ptr_null();
|
||||
else
|
||||
zero = ll.widen_value(ll.void_ptr_null());
|
||||
} else {
|
||||
OSL_ASSERT(0 && "Unsupported element type");
|
||||
zero = nullptr;
|
||||
@@ -270,9 +281,8 @@ BatchedBackendLLVM::llvm_assign_zero(const Symbol& sym)
|
||||
|
||||
int num_elements = t.numelements();
|
||||
for (int a = 0; a < num_elements; ++a) {
|
||||
int numDeriv = sym.has_derivs() ? 3 : 1;
|
||||
llvm::Value* arrind = t.simpletype().arraylen ? ll.constant(a)
|
||||
: NULL;
|
||||
int numDeriv = sym.has_derivs() ? 3 : 1;
|
||||
llvm::Value* arrind = t.simpletype().arraylen ? ll.constant(a) : NULL;
|
||||
for (int d = 0; d < numDeriv; ++d) {
|
||||
for (int c = 0; c < t.aggregate(); ++c) {
|
||||
llvm_store_value(zero, sym, d, arrind, c);
|
||||
@@ -312,7 +322,6 @@ BatchedBackendLLVM::llvm_zero_derivs(const Symbol& sym)
|
||||
++arrayindex) {
|
||||
llvm::Value* arrind = arrayindex >= 0 ? ll.constant(arrayindex)
|
||||
: NULL;
|
||||
|
||||
for (int c = 0; c < t.aggregate(); ++c)
|
||||
llvm_store_value(zero, sym, 1, arrind, c);
|
||||
for (int c = 0; c < t.aggregate(); ++c)
|
||||
@@ -326,21 +335,71 @@ BatchedBackendLLVM::llvm_zero_derivs(const Symbol& sym)
|
||||
void
|
||||
BatchedBackendLLVM::llvm_zero_derivs(const Symbol& sym, llvm::Value* count)
|
||||
{
|
||||
if (sym.typespec().is_closure_based())
|
||||
return; // Closures don't have derivs
|
||||
// Same thing as the above version but with just the first count derivs
|
||||
TypeSpec elemtype = sym.typespec().elementtype();
|
||||
const TypeSpec& t = sym.typespec();
|
||||
|
||||
OSL_ASSERT((count->getType() == ll.type_int())
|
||||
|| (count->getType() == ll.type_wide_int()));
|
||||
|
||||
if (t.is_closure_based())
|
||||
return; // Closures don't have derivs
|
||||
|
||||
TypeSpec elemtype = t.elementtype();
|
||||
if (sym.has_derivs() && elemtype.is_float_based()) {
|
||||
OSL_ASSERT(
|
||||
sym.is_uniform()); // TODO: handle varying case and remove OSL_ASSERT
|
||||
size_t esize = sym.typespec().simpletype().elementsize();
|
||||
size_t align = sym.typespec().simpletype().basesize();
|
||||
count = ll.op_mul(count, ll.constant((int)esize));
|
||||
ll.op_memset(llvm_void_ptr(sym, 1), 0, count, (int)align); // X derivs
|
||||
ll.op_memset(llvm_void_ptr(sym, 2), 0, count, (int)align); // Y derivs
|
||||
llvm::Value* zero;
|
||||
if (sym.is_uniform())
|
||||
zero = ll.constant(0.0f);
|
||||
else
|
||||
zero = ll.wide_constant(0.0f);
|
||||
|
||||
if (!t.is_array()) {
|
||||
// Not an array, probably shouldn't have called this method
|
||||
// just fallback to non-count based version
|
||||
llvm_zero_derivs(sym);
|
||||
return;
|
||||
}
|
||||
|
||||
llvm::Value* pre_condition_mask = ll.current_mask();
|
||||
|
||||
llvm::Value* index_loc = ll.op_alloca(ll.type_int(), 1);
|
||||
ll.op_store(ll.constant(0), index_loc);
|
||||
|
||||
llvm::BasicBlock* cond_block = ll.new_basic_block("zero deriv cond");
|
||||
llvm::BasicBlock* body_block = ll.new_basic_block("zero deriv body");
|
||||
llvm::BasicBlock* step_block = ll.new_basic_block("zero deriv step");
|
||||
llvm::BasicBlock* after_block = ll.new_basic_block("zero deriv after");
|
||||
|
||||
ll.op_branch(cond_block);
|
||||
llvm::Value* index_val = ll.op_load(index_loc);
|
||||
llvm::Value* windex_val = ll.widen_value(index_val);
|
||||
llvm::Value* condition_mask = ll.op_lt(windex_val, count);
|
||||
llvm::Value* post_condition_mask = ll.op_and(condition_mask,
|
||||
pre_condition_mask);
|
||||
llvm::Value* cond_val = ll.test_if_mask_is_non_zero(
|
||||
post_condition_mask);
|
||||
|
||||
// Jump to either LoopBody or AfterLoop
|
||||
ll.op_branch(cond_val, body_block, after_block);
|
||||
ll.push_mask(post_condition_mask, false /* negate */,
|
||||
true /* absolute */);
|
||||
for (int c = 0; c < t.aggregate(); ++c)
|
||||
llvm_store_value(zero, sym, 1, index_val, c);
|
||||
for (int c = 0; c < t.aggregate(); ++c)
|
||||
llvm_store_value(zero, sym, 2, index_val, c);
|
||||
ll.pop_mask();
|
||||
|
||||
ll.op_branch(step_block);
|
||||
index_val = ll.op_add(index_val, ll.constant(1));
|
||||
ll.op_store(index_val, index_loc);
|
||||
ll.op_branch(cond_block);
|
||||
|
||||
// Continue on with the previous flow
|
||||
ll.set_insert_point(after_block);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
BatchedBackendLLVM::ShaderGlobalNameToIndex(ustring name, bool& is_uniform)
|
||||
{
|
||||
@@ -354,6 +413,8 @@ BatchedBackendLLVM::ShaderGlobalNameToIndex(ustring name, bool& is_uniform)
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::llvm_global_symbol_ptr(ustring name, bool& is_uniform)
|
||||
{
|
||||
@@ -365,6 +426,8 @@ BatchedBackendLLVM::llvm_global_symbol_ptr(ustring name, bool& is_uniform)
|
||||
return ll.void_ptr(ll.GEP(sg_ptr(), 0, sg_index));
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::getLLVMSymbolBase(const Symbol& sym)
|
||||
{
|
||||
@@ -396,14 +459,16 @@ BatchedBackendLLVM::getLLVMSymbolBase(const Symbol& sym)
|
||||
std::string mangled_name = dealiased->mangled();
|
||||
AllocationMap::iterator map_iter = named_values().find(mangled_name);
|
||||
if (map_iter == named_values().end()) {
|
||||
shadingcontext()->errorf(
|
||||
"Couldn't find symbol '%s' (unmangled = '%s'). Did you forget to allocate it?",
|
||||
mangled_name.c_str(), dealiased->name().c_str());
|
||||
shadingcontext()->errorfmt(
|
||||
"Couldn't find symbol '{}' (unmangled = '{}'). Did you forget to allocate it?",
|
||||
mangled_name, dealiased->unmangled());
|
||||
return 0;
|
||||
}
|
||||
return (llvm::Value*)map_iter->second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::llvm_alloca(const TypeSpec& type, bool derivs,
|
||||
bool is_uniform, bool forceBool,
|
||||
@@ -431,12 +496,16 @@ BatchedBackendLLVM::llvm_alloca(const TypeSpec& type, bool derivs,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
BatchedBackendLLVM::TempScope::TempScope(BatchedBackendLLVM& backend)
|
||||
: m_backend(backend)
|
||||
{
|
||||
m_backend.m_temp_scopes.push_back(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
BatchedBackendLLVM::TempScope::~TempScope()
|
||||
{
|
||||
OSL_ASSERT(!m_backend.m_temp_scopes.empty()
|
||||
@@ -452,6 +521,8 @@ BatchedBackendLLVM::TempScope::~TempScope()
|
||||
m_backend.m_temp_scopes.pop_back();
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::getOrAllocateTemp(const TypeSpec& type, bool derivs,
|
||||
bool is_uniform, bool forceBool,
|
||||
@@ -492,6 +563,8 @@ BatchedBackendLLVM::getOrAllocateTemp(const TypeSpec& type, bool derivs,
|
||||
return allocation;
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::getOrAllocateLLVMSymbol(const Symbol& sym)
|
||||
{
|
||||
@@ -575,6 +648,8 @@ BatchedBackendLLVM::llvm_get_pointer(const Symbol& sym, int deriv,
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::llvm_widen_value_into_temp(const Symbol& sym, int deriv)
|
||||
{
|
||||
@@ -588,7 +663,7 @@ BatchedBackendLLVM::llvm_widen_value_into_temp(const Symbol& sym, int deriv)
|
||||
OSL_ASSERT(symType.is_unknown() == false);
|
||||
|
||||
llvm::Value* widePtr = getOrAllocateTemp(t, false /*derivs*/,
|
||||
false /*is_uniform*/);
|
||||
false /*is_uniform*/);
|
||||
auto disable_masked_stores = ll.create_masking_scope(false);
|
||||
for (int c = 0; c < t.aggregate(); ++c) {
|
||||
// NOTE: we use the passed deriv to load, but store to value (deriv==0)
|
||||
@@ -599,6 +674,8 @@ BatchedBackendLLVM::llvm_widen_value_into_temp(const Symbol& sym, int deriv)
|
||||
return ll.void_ptr(widePtr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::llvm_load_value(const Symbol& sym, int deriv,
|
||||
llvm::Value* arrayindex, int component,
|
||||
@@ -626,45 +703,51 @@ BatchedBackendLLVM::llvm_load_value(const Symbol& sym, int deriv,
|
||||
if (sym.is_constant() && !sym.typespec().is_array() && !arrayindex) {
|
||||
// Shortcut for simple constants
|
||||
if (sym.typespec().is_float()) {
|
||||
if (cast == TypeDesc::TypeInt)
|
||||
float float_val = sym.get_float();
|
||||
if (cast == TypeDesc::TypeInt) {
|
||||
int int_val = static_cast<int>(float_val);
|
||||
if (op_is_uniform) {
|
||||
return ll.constant((int)*(float*)sym.data());
|
||||
return ll.constant(int_val);
|
||||
} else {
|
||||
return ll.wide_constant((int)*(float*)sym.data());
|
||||
return ll.wide_constant(int_val);
|
||||
}
|
||||
else if (op_is_uniform) {
|
||||
return ll.constant(*(float*)sym.data());
|
||||
} else if (op_is_uniform) {
|
||||
return ll.constant(float_val);
|
||||
} else {
|
||||
return ll.wide_constant(*(float*)sym.data());
|
||||
return ll.wide_constant(float_val);
|
||||
}
|
||||
}
|
||||
if (sym.typespec().is_int()) {
|
||||
if (cast == TypeDesc::TypeFloat)
|
||||
int int_val = sym.get_int();
|
||||
if (cast == TypeDesc::TypeFloat) {
|
||||
float float_val = static_cast<float>(int_val);
|
||||
if (op_is_uniform) {
|
||||
return ll.constant((float)*(int*)sym.data());
|
||||
return ll.constant(float_val);
|
||||
} else {
|
||||
return ll.wide_constant((float)*(int*)sym.data());
|
||||
return ll.wide_constant(float_val);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (op_is_uniform) {
|
||||
return ll.constant(*(int*)sym.data());
|
||||
return ll.constant(int_val);
|
||||
} else {
|
||||
return ll.wide_constant(*(int*)sym.data());
|
||||
return ll.wide_constant(int_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sym.typespec().is_triple() || sym.typespec().is_matrix()) {
|
||||
float float_val = sym.get_float(component);
|
||||
if (op_is_uniform) {
|
||||
return ll.constant(((float*)sym.data())[component]);
|
||||
return ll.constant(float_val);
|
||||
} else {
|
||||
return ll.wide_constant(((float*)sym.data())[component]);
|
||||
return ll.wide_constant(float_val);
|
||||
}
|
||||
}
|
||||
if (sym.typespec().is_string()) {
|
||||
ustring string_val = sym.get_string();
|
||||
if (op_is_uniform) {
|
||||
return ll.constant(*(ustring*)sym.data());
|
||||
return ll.constant(string_val);
|
||||
} else {
|
||||
return ll.wide_constant(*(ustring*)sym.data());
|
||||
return ll.wide_constant(string_val);
|
||||
}
|
||||
}
|
||||
OSL_ASSERT(0 && "unhandled constant type");
|
||||
@@ -678,6 +761,7 @@ BatchedBackendLLVM::llvm_load_value(const Symbol& sym, int deriv,
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::llvm_load_mask(const Symbol& cond)
|
||||
{
|
||||
@@ -700,6 +784,7 @@ BatchedBackendLLVM::llvm_load_mask(const Symbol& cond)
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type,
|
||||
int deriv, llvm::Value* arrayindex,
|
||||
@@ -782,7 +867,7 @@ BatchedBackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type,
|
||||
|| (ll.llvm_typeof(result) == ll.type_float())
|
||||
|| (ll.llvm_typeof(result) == ll.type_triple())
|
||||
|| (ll.llvm_typeof(result) == ll.type_int())
|
||||
|| (ll.llvm_typeof(result) == (llvm::Type*)ll.type_string())
|
||||
|| (ll.llvm_typeof(result) == ll.type_ustring())
|
||||
|| (ll.llvm_typeof(result) == ll.type_matrix())
|
||||
|| (ll.llvm_typeof(result) == ll.type_longlong())) {
|
||||
result = ll.widen_value(result);
|
||||
@@ -803,7 +888,7 @@ BatchedBackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type,
|
||||
(ll.llvm_typeof(result) == ll.type_wide_float())
|
||||
|| (ll.llvm_typeof(result) == ll.type_wide_int())
|
||||
|| (ll.llvm_typeof(result) == ll.type_wide_triple())
|
||||
|| (ll.llvm_typeof(result) == ll.type_wide_string())
|
||||
|| (ll.llvm_typeof(result) == ll.type_wide_ustring())
|
||||
|| (ll.llvm_typeof(result) == ll.type_wide_bool())
|
||||
|| (ll.llvm_typeof(result) == ll.type_wide_matrix())
|
||||
|| (ll.llvm_typeof(result) == ll.type_wide_longlong()));
|
||||
@@ -837,7 +922,6 @@ BatchedBackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type,
|
||||
// vs. the hardcoded 4 and avoid the multiplication above
|
||||
}
|
||||
|
||||
|
||||
// Now grab the value
|
||||
llvm::Value* result;
|
||||
result = ll.op_gather(ptr, arrayindex);
|
||||
@@ -881,7 +965,6 @@ BatchedBackendLLVM::llvm_load_constant_value(const Symbol& sym, int arrayindex,
|
||||
OSL_ASSERT(arrayindex >= 0
|
||||
&& "Called llvm_load_constant_value with negative array index");
|
||||
|
||||
|
||||
// TODO: might want to take this fix for array types back to the non-wide backend
|
||||
TypeSpec elementType = sym.typespec();
|
||||
// The symbol we are creating a constant for might be an array
|
||||
@@ -889,53 +972,53 @@ BatchedBackendLLVM::llvm_load_constant_value(const Symbol& sym, int arrayindex,
|
||||
elementType.make_array(0);
|
||||
|
||||
if (elementType.is_float()) {
|
||||
const float* val = (const float*)sym.data();
|
||||
if (cast == TypeDesc::TypeInt)
|
||||
float float_elem = sym.get_float(arrayindex);
|
||||
if (cast == TypeDesc::TypeInt) {
|
||||
int int_elem = static_cast<int>(float_elem);
|
||||
if (op_is_uniform) {
|
||||
return ll.constant((int)val[arrayindex]);
|
||||
return ll.constant(int_elem);
|
||||
} else {
|
||||
return ll.wide_constant((int)val[arrayindex]);
|
||||
return ll.wide_constant(int_elem);
|
||||
}
|
||||
else if (op_is_uniform) {
|
||||
return ll.constant(val[arrayindex]);
|
||||
} else if (op_is_uniform) {
|
||||
return ll.constant(float_elem);
|
||||
} else {
|
||||
return ll.wide_constant(val[arrayindex]);
|
||||
return ll.wide_constant(float_elem);
|
||||
}
|
||||
}
|
||||
if (elementType.is_int()) {
|
||||
const int* val = (const int*)sym.data();
|
||||
if (cast == TypeDesc::TypeFloat)
|
||||
int int_elem = sym.get_int(arrayindex);
|
||||
if (cast == TypeDesc::TypeFloat) {
|
||||
float float_elem = static_cast<float>(int_elem);
|
||||
if (op_is_uniform) {
|
||||
return ll.constant((float)val[arrayindex]);
|
||||
return ll.constant(float_elem);
|
||||
} else {
|
||||
return ll.wide_constant((float)val[arrayindex]);
|
||||
return ll.wide_constant(float_elem);
|
||||
}
|
||||
else if (op_is_uniform) {
|
||||
return ll.constant(val[arrayindex]);
|
||||
} else if (op_is_uniform) {
|
||||
return ll.constant(int_elem);
|
||||
} else {
|
||||
return ll.wide_constant(val[arrayindex]);
|
||||
return ll.wide_constant(int_elem);
|
||||
}
|
||||
}
|
||||
if (elementType.is_triple() || elementType.is_matrix()) {
|
||||
const float* val = (const float*)sym.data();
|
||||
int ncomps = (int)sym.typespec().aggregate();
|
||||
float float_elem = sym.get_float(ncomps * arrayindex + component);
|
||||
if (op_is_uniform) {
|
||||
return ll.constant(val[ncomps * arrayindex + component]);
|
||||
return ll.constant(float_elem);
|
||||
} else {
|
||||
return ll.wide_constant(val[ncomps * arrayindex + component]);
|
||||
return ll.wide_constant(float_elem);
|
||||
}
|
||||
}
|
||||
if (elementType.is_string()) {
|
||||
const ustring* val = (const ustring*)sym.data();
|
||||
ustring string_elem = sym.get_string(arrayindex);
|
||||
if (op_is_uniform) {
|
||||
return ll.constant(val[arrayindex]);
|
||||
return ll.constant(string_elem);
|
||||
} else {
|
||||
return ll.wide_constant(val[arrayindex]);
|
||||
return ll.wide_constant(string_elem);
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "SYMBOL " << sym.name().c_str() << " type=" << sym.typespec()
|
||||
<< std::endl;
|
||||
OSL_ASSERT(0 && "unhandled constant type");
|
||||
return NULL;
|
||||
}
|
||||
@@ -1058,14 +1141,14 @@ BatchedBackendLLVM::llvm_load_arg(const Symbol& sym, bool derivs,
|
||||
int copy_deriv_count = (derivs && sym.has_derivs()) ? 3 : 1;
|
||||
|
||||
int copy_elem_count = t.numelements();
|
||||
bool is_array = t.is_array();
|
||||
bool is_array = t.is_array();
|
||||
for (int d = 0; d < copy_deriv_count; ++d) {
|
||||
for(int ai=0; ai < copy_elem_count; ++ai) {
|
||||
llvm::Value * arrayIndex = is_array ? ll.constant(ai) : nullptr;
|
||||
for (int ai = 0; ai < copy_elem_count; ++ai) {
|
||||
llvm::Value* arrayIndex = is_array ? ll.constant(ai) : nullptr;
|
||||
for (int c = 0; c < t.aggregate(); ++c) {
|
||||
|
||||
// Will automatically widen value if needed
|
||||
llvm::Value* v = llvm_load_value(sym, d, arrayIndex, c, TypeDesc::UNKNOWN,
|
||||
llvm::Value* v = llvm_load_value(sym, d, arrayIndex, c,
|
||||
TypeDesc::UNKNOWN,
|
||||
op_is_uniform);
|
||||
llvm_store_value(v, tmpptr, t, d, arrayIndex, c);
|
||||
}
|
||||
@@ -1135,7 +1218,8 @@ BatchedBackendLLVM::llvm_store_value(llvm::Value* new_val, llvm::Value* dst_ptr,
|
||||
if (!type.is_closure_based() && t.aggregate > 1)
|
||||
dst_ptr = ll.GEP(dst_ptr, 0, component);
|
||||
|
||||
if (ll.type_ptr(ll.llvm_typeof(new_val)) != ll.llvm_typeof(dst_ptr)) {
|
||||
if ((const llvm::Type*)ll.type_ptr(ll.llvm_typeof(new_val))
|
||||
!= ll.llvm_typeof(dst_ptr)) {
|
||||
std::cerr << " new_val type=";
|
||||
{
|
||||
llvm::raw_os_ostream os_cerr(std::cerr);
|
||||
@@ -1148,10 +1232,9 @@ BatchedBackendLLVM::llvm_store_value(llvm::Value* new_val, llvm::Value* dst_ptr,
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
OSL_ASSERT(ll.type_ptr(ll.llvm_typeof(new_val))
|
||||
OSL_ASSERT((const llvm::Type*)ll.type_ptr(ll.llvm_typeof(new_val))
|
||||
== ll.llvm_typeof(dst_ptr));
|
||||
|
||||
|
||||
// Finally, store the value.
|
||||
ll.op_store(new_val, dst_ptr);
|
||||
return true;
|
||||
@@ -1194,6 +1277,7 @@ BatchedBackendLLVM::llvm_store_value(llvm::Value* new_val, llvm::Value* dst_ptr,
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
BatchedBackendLLVM::llvm_store_mask(llvm::Value* new_mask, const Symbol& cond)
|
||||
{
|
||||
@@ -1208,6 +1292,7 @@ BatchedBackendLLVM::llvm_store_mask(llvm::Value* new_mask, const Symbol& cond)
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
BatchedBackendLLVM::llvm_store_component_value(llvm::Value* new_val,
|
||||
const Symbol& sym, int deriv,
|
||||
@@ -1251,6 +1336,8 @@ BatchedBackendLLVM::llvm_store_component_value(llvm::Value* new_val,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedBackendLLVM::llvm_broadcast_uniform_value_from_mem(
|
||||
llvm::Value* pointerTotempUniform, const Symbol& Destination,
|
||||
@@ -1298,6 +1385,8 @@ BatchedBackendLLVM::llvm_broadcast_uniform_value_from_mem(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedBackendLLVM::llvm_broadcast_uniform_value(llvm::Value* tempUniform,
|
||||
const Symbol& Destination,
|
||||
@@ -1310,6 +1399,8 @@ BatchedBackendLLVM::llvm_broadcast_uniform_value(llvm::Value* tempUniform,
|
||||
llvm_store_value(wide_value, Destination, derivs, nullptr, component);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedBackendLLVM::llvm_conversion_store_masked_status(llvm::Value* val,
|
||||
const Symbol& Status)
|
||||
@@ -1332,6 +1423,8 @@ BatchedBackendLLVM::llvm_conversion_store_masked_status(llvm::Value* val,
|
||||
llvm_store_value(mask, Status);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedBackendLLVM::llvm_conversion_store_uniform_status(llvm::Value* val,
|
||||
const Symbol& Status)
|
||||
@@ -1358,6 +1451,8 @@ BatchedBackendLLVM::llvm_conversion_store_uniform_status(llvm::Value* val,
|
||||
llvm_store_value(val, Status);
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::groupdata_field_ref(int fieldnum)
|
||||
{
|
||||
@@ -1365,6 +1460,7 @@ BatchedBackendLLVM::groupdata_field_ref(int fieldnum)
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::groupdata_field_ptr(int fieldnum, TypeDesc type,
|
||||
bool is_uniform)
|
||||
@@ -1380,6 +1476,8 @@ BatchedBackendLLVM::groupdata_field_ptr(int fieldnum, TypeDesc type,
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::temp_wide_matrix_ptr()
|
||||
{
|
||||
@@ -1393,6 +1491,7 @@ BatchedBackendLLVM::temp_wide_matrix_ptr()
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::temp_batched_texture_options_ptr()
|
||||
{
|
||||
@@ -1406,6 +1505,8 @@ BatchedBackendLLVM::temp_batched_texture_options_ptr()
|
||||
return m_llvm_temp_batched_texture_options_ptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::temp_batched_trace_options_ptr()
|
||||
{
|
||||
@@ -1420,6 +1521,7 @@ BatchedBackendLLVM::temp_batched_trace_options_ptr()
|
||||
}
|
||||
|
||||
|
||||
|
||||
llvm::Value*
|
||||
BatchedBackendLLVM::layer_run_ref(int layer)
|
||||
{
|
||||
@@ -1564,7 +1666,6 @@ BatchedBackendLLVM::llvm_call_function(const FuncSpec& name,
|
||||
valargs[i] = ll.void_ptr(tmpptr);
|
||||
}
|
||||
|
||||
|
||||
OSL_DEV_ONLY(std::cout << "....pushing " << s.name().c_str()
|
||||
<< " as void_ptr" << std::endl);
|
||||
} else {
|
||||
@@ -1666,7 +1767,8 @@ BatchedBackendLLVM::llvm_test_nonzero(const Symbol& val, bool test_derivs)
|
||||
llvm::Value* llvmValue = llvm_get_pointer(val);
|
||||
//OSL_DEV_ONLY(std::cout << "llvmValue type=" << ll.llvm_typenameof(llvmValue) << std::endl);
|
||||
|
||||
if (ll.llvm_typeof(llvmValue) == ll.type_ptr(ll.type_bool())) {
|
||||
if (ll.llvm_typeof(llvmValue)
|
||||
== (const llvm::Type*)ll.type_ptr(ll.type_bool())) {
|
||||
return ll.op_ne(llvm_load_value(val), ll.constant_bool(0));
|
||||
} else {
|
||||
return ll.op_ne(llvm_load_value(val), ll.constant(0));
|
||||
@@ -1712,14 +1814,16 @@ BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,
|
||||
llvm::Value* arrind = arrayindex >= 0 ? ll.constant(arrayindex) : NULL;
|
||||
|
||||
if (Result.typespec().is_closure() || Src.typespec().is_closure()) {
|
||||
OSL_ASSERT(0 && "unhandled case"); // TODO: implement
|
||||
|
||||
if (Src.typespec().is_closure()) {
|
||||
llvm::Value* srcval = llvm_load_value(Src, 0, arrind, 0);
|
||||
llvm::Value* srcval = llvm_load_value(Src, 0, arrind, 0,
|
||||
TypeDesc::UNKNOWN,
|
||||
op_is_uniform);
|
||||
llvm_store_value(srcval, Result, 0, arrind, 0);
|
||||
} else {
|
||||
llvm::Value* null = ll.constant_ptr(NULL, ll.type_void_ptr());
|
||||
llvm_store_value(null, Result, 0, arrind, 0);
|
||||
llvm::Value* null_value = ll.constant_ptr(NULL, ll.type_void_ptr());
|
||||
if (!op_is_uniform)
|
||||
null_value = ll.widen_value(null_value);
|
||||
llvm_store_value(null_value, Result, 0, arrind, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1744,7 +1848,7 @@ BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,
|
||||
return true;
|
||||
}
|
||||
|
||||
// memcpy complicated by promotion of uniform to wide during assignment, dissallow
|
||||
// memcpy complicated by promotion of uniform to wide during assignment, disallow
|
||||
|
||||
// The following code handles f=f, f=i, v=v, v=f, v=i, m=m, s=s.
|
||||
// Remember that llvm_load_value will automatically convert scalar->triple.
|
||||
@@ -1761,7 +1865,7 @@ BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,
|
||||
if (result_t.is_array() && src_t.is_array()) {
|
||||
start_array_index = 0;
|
||||
end_array_index = std::min(result_t.arraylength(),
|
||||
src_t.arraylength());
|
||||
src_t.arraylength());
|
||||
}
|
||||
}
|
||||
for (arrayindex = start_array_index; arrayindex < end_array_index;
|
||||
@@ -1802,7 +1906,7 @@ BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,
|
||||
// The llvm_load_value above should have handled bool to int conversions
|
||||
// when the basetype == Typedesc::INT
|
||||
|
||||
// write source float into all compnents when dstcomp == -1, otherwise
|
||||
// write source float into all components when dstcomp == -1, otherwise
|
||||
// the single element requested.
|
||||
if (dstcomp == -1) {
|
||||
for (int i = 0; i < num_components; ++i)
|
||||
@@ -1854,6 +1958,8 @@ BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
BatchedBackendLLVM::find_userdata_index(const Symbol& sym)
|
||||
{
|
||||
@@ -1870,6 +1976,7 @@ BatchedBackendLLVM::find_userdata_index(const Symbol& sym)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BatchedBackendLLVM::append_arg_to(llvm::raw_svector_ostream& OS,
|
||||
const FuncSpec::Arg& arg)
|
||||
@@ -1898,6 +2005,8 @@ BatchedBackendLLVM::append_arg_to(llvm::raw_svector_ostream& OS,
|
||||
OS << name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char*
|
||||
BatchedBackendLLVM::build_name(const FuncSpec& fs)
|
||||
{
|
||||
|
||||
@@ -164,7 +164,7 @@ public:
|
||||
llvm::Value* llvm_load_mask(const Symbol& cond);
|
||||
|
||||
/// Return an llvm::Value* that is either a scalar and derivs is
|
||||
/// false, or a pointer to sym's values (if sym is an aggreate or
|
||||
/// false, or a pointer to sym's values (if sym is an aggregate or
|
||||
/// derivs == true). Furthermore, if deriv == true and sym doesn't
|
||||
/// have derivs, coerce it into a variable with zero derivs.
|
||||
llvm::Value* llvm_load_arg(const Symbol& sym, bool derivs,
|
||||
@@ -278,9 +278,9 @@ public:
|
||||
|
||||
public:
|
||||
TempScope(BatchedBackendLLVM& backend);
|
||||
TempScope(const TempScope& other) = delete;
|
||||
TempScope(const TempScope&& other) = delete;
|
||||
TempScope& operator=(const TempScope& other) = delete;
|
||||
TempScope(const TempScope& other) = delete;
|
||||
TempScope(const TempScope&& other) = delete;
|
||||
TempScope& operator=(const TempScope& other) = delete;
|
||||
TempScope& operator=(const TempScope&& other) = delete;
|
||||
~TempScope();
|
||||
};
|
||||
@@ -331,7 +331,7 @@ public:
|
||||
/// derivs are zero.
|
||||
llvm::Value* llvm_test_nonzero(const Symbol& val, bool test_derivs = false);
|
||||
|
||||
/// Implementaiton of Simple assignment. If arrayindex >= 0, in
|
||||
/// Implementation of Simple assignment. If arrayindex >= 0, in
|
||||
/// designates a particular array index to assign.
|
||||
bool llvm_assign_impl(const Symbol& Result, const Symbol& Src,
|
||||
int arrayindex = -1, int srccomp = -1,
|
||||
@@ -364,6 +364,7 @@ public:
|
||||
|
||||
llvm::Type* llvm_type_closure_component();
|
||||
llvm::Type* llvm_type_closure_component_ptr();
|
||||
llvm::Type* llvm_type_closure_component_wide_ptr();
|
||||
|
||||
/// Return the ShaderGlobals pointer cast as a void*.
|
||||
///
|
||||
@@ -414,6 +415,18 @@ public:
|
||||
bool is_uniform = true);
|
||||
|
||||
|
||||
/// Return the pointer to the block of shadeindices.
|
||||
llvm::Value* wide_shadeindex_ptr() const
|
||||
{
|
||||
return m_llvm_wide_shadeindex_ptr;
|
||||
}
|
||||
|
||||
/// Return the userdata base pointer.
|
||||
llvm::Value* userdata_base_ptr() const { return m_llvm_userdata_base_ptr; }
|
||||
|
||||
/// Return the output base pointer.
|
||||
llvm::Value* output_base_ptr() const { return m_llvm_output_base_ptr; }
|
||||
|
||||
/// Return a pointer to an WideMatrix that was previously alloca
|
||||
/// on the stack, meant for generator to reuse as a temporary
|
||||
llvm::Value* temp_wide_matrix_ptr();
|
||||
@@ -476,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
|
||||
@@ -520,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)
|
||||
@@ -668,9 +681,8 @@ public:
|
||||
llvm::BasicBlock* llvm_exit_instance_block()
|
||||
{
|
||||
if (!m_exit_instance_block) {
|
||||
std::string name = Strutil::sprintf("%s_%d_exit_",
|
||||
inst()->layername(),
|
||||
inst()->id());
|
||||
std::string name = fmtformat("{}_{}_exit_", inst()->layername(),
|
||||
inst()->id());
|
||||
m_exit_instance_block = ll.new_basic_block(name);
|
||||
}
|
||||
return m_exit_instance_block;
|
||||
@@ -741,12 +753,11 @@ private:
|
||||
virtual const char* library_selector() const = 0;
|
||||
virtual void init_function_map(ShadingSystemImpl& shadingsys) const = 0;
|
||||
|
||||
static std::unique_ptr<TargetLibraryHelper> build(ShadingContext* context,
|
||||
int vector_width,
|
||||
TargetISA target_isa);
|
||||
static std::unique_ptr<TargetLibraryHelper>
|
||||
build(ShadingContext* context, int vector_width, TargetISA target_isa);
|
||||
};
|
||||
// TargetLibraryHelper is private, so need to be friend with Concrete
|
||||
template <int WidthT, TargetISA IsaT>
|
||||
template<int WidthT, TargetISA IsaT>
|
||||
friend class ConcreteTargetLibraryHelper;
|
||||
|
||||
std::unique_ptr<TargetLibraryHelper> m_target_lib_helper;
|
||||
@@ -771,6 +782,10 @@ private:
|
||||
llvm::Value* m_llvm_shaderglobals_ptr;
|
||||
llvm::Value* m_llvm_groupdata_ptr;
|
||||
|
||||
llvm::Value* m_llvm_wide_shadeindex_ptr;
|
||||
llvm::Value* m_llvm_userdata_base_ptr;
|
||||
llvm::Value* m_llvm_output_base_ptr;
|
||||
|
||||
// Reused allocas for temps used to pass options or intermediates
|
||||
llvm::Value* m_llvm_temp_wide_matrix_ptr; // for gen_tranform
|
||||
llvm::Value* m_llvm_temp_batched_texture_options_ptr;
|
||||
|
||||
+4301
-2903
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,7 @@ using namespace OSL::pvt;
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
BatchedRendererServices<WidthT>::BatchedRendererServices(TextureSystem* texsys)
|
||||
: m_texturesys(texsys)
|
||||
@@ -35,6 +36,7 @@ BatchedRendererServices<WidthT>::BatchedRendererServices(TextureSystem* texsys)
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::get_matrix(BatchedShaderGlobals* bsg,
|
||||
@@ -49,6 +51,7 @@ BatchedRendererServices<WidthT>::get_matrix(BatchedShaderGlobals* bsg,
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::get_inverse_matrix(
|
||||
@@ -62,6 +65,7 @@ BatchedRendererServices<WidthT>::get_inverse_matrix(
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::get_inverse_matrix(BatchedShaderGlobals* bsg,
|
||||
@@ -75,6 +79,8 @@ BatchedRendererServices<WidthT>::get_inverse_matrix(BatchedShaderGlobals* bsg,
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::get_inverse_matrix(BatchedShaderGlobals* bsg,
|
||||
@@ -88,6 +94,8 @@ BatchedRendererServices<WidthT>::get_inverse_matrix(BatchedShaderGlobals* bsg,
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
TextureSystem*
|
||||
BatchedRendererServices<WidthT>::texturesys() const
|
||||
@@ -95,6 +103,8 @@ BatchedRendererServices<WidthT>::texturesys() const
|
||||
return m_texturesys;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
TextureSystem::TextureHandle*
|
||||
BatchedRendererServices<WidthT>::resolve_udim_uniform(
|
||||
@@ -107,7 +117,6 @@ BatchedRendererServices<WidthT>::resolve_udim_uniform(
|
||||
if (!texture_handle)
|
||||
texture_handle = texturesys()->get_texture_handle(filename,
|
||||
texture_thread_info);
|
||||
#if OPENIMAGEIO_VERSION >= 20307
|
||||
if (texturesys()->is_udim(texture_handle)) {
|
||||
// Newer versions of the TextureSystem interface are able to determine the
|
||||
// specific UDIM tile we're using.
|
||||
@@ -121,11 +130,13 @@ BatchedRendererServices<WidthT>::resolve_udim_uniform(
|
||||
udim_handle = texture_handle;
|
||||
}
|
||||
return udim_handle;
|
||||
} else
|
||||
#endif
|
||||
} else {
|
||||
return texture_handle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
void
|
||||
BatchedRendererServices<WidthT>::resolve_udim(
|
||||
@@ -139,7 +150,6 @@ BatchedRendererServices<WidthT>::resolve_udim(
|
||||
if (!texture_handle)
|
||||
texture_handle = texturesys()->get_texture_handle(filename,
|
||||
texture_thread_info);
|
||||
#if OPENIMAGEIO_VERSION >= 20307
|
||||
if (texturesys()->is_udim(texture_handle)) {
|
||||
// Newer versions of the TextureSystem interface are able to determine the
|
||||
// specific UDIM tile we're using.
|
||||
@@ -155,12 +165,13 @@ BatchedRendererServices<WidthT>::resolve_udim(
|
||||
}
|
||||
wresult[l] = udim_handle;
|
||||
});
|
||||
} else
|
||||
#endif
|
||||
} else {
|
||||
assign_all(wresult, texture_handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
bool
|
||||
BatchedRendererServices<WidthT>::get_texture_info_uniform(
|
||||
@@ -180,13 +191,15 @@ BatchedRendererServices<WidthT>::get_texture_info_uniform(
|
||||
if (!status) {
|
||||
std::string err = texturesys()->geterror();
|
||||
if (err.size() && bsg) {
|
||||
bsg->uniform.context->errorf(
|
||||
"[RendererServices::get_texture_info] %s", err);
|
||||
bsg->uniform.context->errorfmt(
|
||||
"[RendererServices::get_texture_info] {}", err);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::texture(
|
||||
@@ -203,6 +216,8 @@ BatchedRendererServices<WidthT>::texture(
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::texture3d(
|
||||
@@ -218,6 +233,8 @@ BatchedRendererServices<WidthT>::texture3d(
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::environment(
|
||||
@@ -233,6 +250,51 @@ BatchedRendererServices<WidthT>::environment(
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
void
|
||||
BatchedRendererServices<WidthT>::pointcloud_search(
|
||||
BatchedShaderGlobals* bsg, ustring filename, const void* wcenter,
|
||||
Wide<const float> wradius, int max_points, bool sort,
|
||||
PointCloudSearchResults& results)
|
||||
{
|
||||
OSL_ASSERT(
|
||||
0
|
||||
&& "UNREACHABLE: BatchedRendererServices<WidthT>::pointcloud_search calls should be overridden or the target specific version in wide_oppointcloud.cpp should be called");
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::pointcloud_get(
|
||||
BatchedShaderGlobals* bsg, ustring filename, Wide<const int[]> windices,
|
||||
Wide<const int> wnum_points, ustring attr_name, MaskedData wout_data)
|
||||
{
|
||||
OSL_ASSERT(
|
||||
0
|
||||
&& "UNREACHABLE: BatchedRendererServices<WidthT>::pointcloud_get calls should be overridden or the target specific version in wide_oppointcloud.cpp should be called");
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
Mask<WidthT>
|
||||
BatchedRendererServices<WidthT>::pointcloud_write(
|
||||
BatchedShaderGlobals* bsg, ustring filename, Wide<const OSL::Vec3> wpos,
|
||||
int nattribs, const ustring* attr_names, const TypeDesc* attr_types,
|
||||
const void** pointers_to_wide_attr_value, Mask mask)
|
||||
{
|
||||
OSL_ASSERT(
|
||||
0
|
||||
&& "UNREACHABLE: BatchedRendererServices<WidthT>::pointcloud_write calls should be overridden or the target specific version in wide_oppointcloud.cpp should be called");
|
||||
return Mask(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
void
|
||||
BatchedRendererServices<WidthT>::trace(
|
||||
@@ -245,6 +307,8 @@ BatchedRendererServices<WidthT>::trace(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int WidthT>
|
||||
void
|
||||
BatchedRendererServices<WidthT>::getmessage(BatchedShaderGlobals* bsg,
|
||||
@@ -258,6 +322,8 @@ BatchedRendererServices<WidthT>::getmessage(BatchedShaderGlobals* bsg,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Explicitly instantiate BatchedRendererServices template
|
||||
template class OSLEXECPUBLIC BatchedRendererServices<16>;
|
||||
template class OSLEXECPUBLIC BatchedRendererServices<8>;
|
||||
|
||||
+276
-277
@@ -11,119 +11,118 @@
|
||||
|
||||
|
||||
#ifndef DECL
|
||||
#error Do not include this file unless DECL is defined
|
||||
# error Do not include this file unless DECL is defined
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define NOISE_IMPL(name) \
|
||||
DECL (osl_ ## name ## _ff, "ff") \
|
||||
DECL (osl_ ## name ## _fff, "fff") \
|
||||
DECL (osl_ ## name ## _fv, "fv") \
|
||||
DECL (osl_ ## name ## _fvf, "fvf") \
|
||||
DECL (osl_ ## name ## _vf, "xvf") \
|
||||
DECL (osl_ ## name ## _vff, "xvff") \
|
||||
DECL (osl_ ## name ## _vv, "xvv") \
|
||||
DECL (osl_ ## name ## _vvf, "xvvf")
|
||||
#define NOISE_IMPL(name) \
|
||||
DECL(osl_##name##_ff, "ff") \
|
||||
DECL(osl_##name##_fff, "fff") \
|
||||
DECL(osl_##name##_fv, "fv") \
|
||||
DECL(osl_##name##_fvf, "fvf") \
|
||||
DECL(osl_##name##_vf, "xvf") \
|
||||
DECL(osl_##name##_vff, "xvff") \
|
||||
DECL(osl_##name##_vv, "xvv") \
|
||||
DECL(osl_##name##_vvf, "xvvf")
|
||||
|
||||
#define NOISE_DERIV_IMPL(name) \
|
||||
DECL (osl_ ## name ## _dfdf, "xXX") \
|
||||
DECL (osl_ ## name ## _dfdff, "xXXf") \
|
||||
DECL (osl_ ## name ## _dffdf, "xXfX") \
|
||||
DECL (osl_ ## name ## _dfdfdf, "xXXX") \
|
||||
DECL (osl_ ## name ## _dfdv, "xXv") \
|
||||
DECL (osl_ ## name ## _dfdvf, "xXvf") \
|
||||
DECL (osl_ ## name ## _dfvdf, "xXvX") \
|
||||
DECL (osl_ ## name ## _dfdvdf, "xXvX") \
|
||||
DECL (osl_ ## name ## _dvdf, "xvX") \
|
||||
DECL (osl_ ## name ## _dvdff, "xvXf") \
|
||||
DECL (osl_ ## name ## _dvfdf, "xvfX") \
|
||||
DECL (osl_ ## name ## _dvdfdf, "xvXX") \
|
||||
DECL (osl_ ## name ## _dvdv, "xvv") \
|
||||
DECL (osl_ ## name ## _dvdvf, "xvvf") \
|
||||
DECL (osl_ ## name ## _dvvdf, "xvvX") \
|
||||
DECL (osl_ ## name ## _dvdvdf, "xvvX")
|
||||
#define NOISE_DERIV_IMPL(name) \
|
||||
DECL(osl_##name##_dfdf, "xXX") \
|
||||
DECL(osl_##name##_dfdff, "xXXf") \
|
||||
DECL(osl_##name##_dffdf, "xXfX") \
|
||||
DECL(osl_##name##_dfdfdf, "xXXX") \
|
||||
DECL(osl_##name##_dfdv, "xXv") \
|
||||
DECL(osl_##name##_dfdvf, "xXvf") \
|
||||
DECL(osl_##name##_dfvdf, "xXvX") \
|
||||
DECL(osl_##name##_dfdvdf, "xXvX") \
|
||||
DECL(osl_##name##_dvdf, "xvX") \
|
||||
DECL(osl_##name##_dvdff, "xvXf") \
|
||||
DECL(osl_##name##_dvfdf, "xvfX") \
|
||||
DECL(osl_##name##_dvdfdf, "xvXX") \
|
||||
DECL(osl_##name##_dvdv, "xvv") \
|
||||
DECL(osl_##name##_dvdvf, "xvvf") \
|
||||
DECL(osl_##name##_dvvdf, "xvvX") \
|
||||
DECL(osl_##name##_dvdvdf, "xvvX")
|
||||
|
||||
#define GENERIC_NOISE_DERIV_IMPL(name) \
|
||||
DECL (osl_ ## name ## _dfdf, "xsXXXX") \
|
||||
DECL (osl_ ## name ## _dfdfdf, "xsXXXXX") \
|
||||
DECL (osl_ ## name ## _dfdv, "xsXXXX") \
|
||||
DECL (osl_ ## name ## _dfdvdf, "xsXXXXX") \
|
||||
DECL (osl_ ## name ## _dvdf, "xsXXXX") \
|
||||
DECL (osl_ ## name ## _dvdfdf, "xsXXXXX") \
|
||||
DECL (osl_ ## name ## _dvdv, "xsXXXX") \
|
||||
DECL (osl_ ## name ## _dvdvdf, "xsXXXXX")
|
||||
#define GENERIC_NOISE_DERIV_IMPL(name) \
|
||||
DECL(osl_##name##_dfdf, "xsXXXX") \
|
||||
DECL(osl_##name##_dfdfdf, "xsXXXXX") \
|
||||
DECL(osl_##name##_dfdv, "xsXXXX") \
|
||||
DECL(osl_##name##_dfdvdf, "xsXXXXX") \
|
||||
DECL(osl_##name##_dvdf, "xsXXXX") \
|
||||
DECL(osl_##name##_dvdfdf, "xsXXXXX") \
|
||||
DECL(osl_##name##_dvdv, "xsXXXX") \
|
||||
DECL(osl_##name##_dvdvdf, "xsXXXXX")
|
||||
|
||||
#define PNOISE_IMPL(name) \
|
||||
DECL (osl_ ## name ## _fff, "fff") \
|
||||
DECL (osl_ ## name ## _fffff, "fffff") \
|
||||
DECL (osl_ ## name ## _fvv, "fvv") \
|
||||
DECL (osl_ ## name ## _fvfvf, "fvfvf") \
|
||||
DECL (osl_ ## name ## _vff, "xvff") \
|
||||
DECL (osl_ ## name ## _vffff, "xvffff") \
|
||||
DECL (osl_ ## name ## _vvv, "xvvv") \
|
||||
DECL (osl_ ## name ## _vvfvf, "xvvfvf")
|
||||
#define PNOISE_IMPL(name) \
|
||||
DECL(osl_##name##_fff, "fff") \
|
||||
DECL(osl_##name##_fffff, "fffff") \
|
||||
DECL(osl_##name##_fvv, "fvv") \
|
||||
DECL(osl_##name##_fvfvf, "fvfvf") \
|
||||
DECL(osl_##name##_vff, "xvff") \
|
||||
DECL(osl_##name##_vffff, "xvffff") \
|
||||
DECL(osl_##name##_vvv, "xvvv") \
|
||||
DECL(osl_##name##_vvfvf, "xvvfvf")
|
||||
|
||||
#define PNOISE_DERIV_IMPL(name) \
|
||||
DECL (osl_ ## name ## _dfdff, "xXXf") \
|
||||
DECL (osl_ ## name ## _dfdffff, "xXXfff") \
|
||||
DECL (osl_ ## name ## _dffdfff, "xXfXff") \
|
||||
DECL (osl_ ## name ## _dfdfdfff, "xXXXff") \
|
||||
DECL (osl_ ## name ## _dfdvv, "xXXv") \
|
||||
DECL (osl_ ## name ## _dfdvfvf, "xXvfvf") \
|
||||
DECL (osl_ ## name ## _dfvdfvf, "xXvXvf") \
|
||||
DECL (osl_ ## name ## _dfdvdfvf, "xXvXvf") \
|
||||
DECL (osl_ ## name ## _dvdff, "xvXf") \
|
||||
DECL (osl_ ## name ## _dvdffff, "xvXfff") \
|
||||
DECL (osl_ ## name ## _dvfdfff, "xvfXff") \
|
||||
DECL (osl_ ## name ## _dvdfdfff, "xvXXff") \
|
||||
DECL (osl_ ## name ## _dvdvv, "xvvv") \
|
||||
DECL (osl_ ## name ## _dvdvfvf, "xvvfvf") \
|
||||
DECL (osl_ ## name ## _dvvdfvf, "xvvXvf") \
|
||||
DECL (osl_ ## name ## _dvdvdfvf, "xvvXvf")
|
||||
#define PNOISE_DERIV_IMPL(name) \
|
||||
DECL(osl_##name##_dfdff, "xXXf") \
|
||||
DECL(osl_##name##_dfdffff, "xXXfff") \
|
||||
DECL(osl_##name##_dffdfff, "xXfXff") \
|
||||
DECL(osl_##name##_dfdfdfff, "xXXXff") \
|
||||
DECL(osl_##name##_dfdvv, "xXXv") \
|
||||
DECL(osl_##name##_dfdvfvf, "xXvfvf") \
|
||||
DECL(osl_##name##_dfvdfvf, "xXvXvf") \
|
||||
DECL(osl_##name##_dfdvdfvf, "xXvXvf") \
|
||||
DECL(osl_##name##_dvdff, "xvXf") \
|
||||
DECL(osl_##name##_dvdffff, "xvXfff") \
|
||||
DECL(osl_##name##_dvfdfff, "xvfXff") \
|
||||
DECL(osl_##name##_dvdfdfff, "xvXXff") \
|
||||
DECL(osl_##name##_dvdvv, "xvvv") \
|
||||
DECL(osl_##name##_dvdvfvf, "xvvfvf") \
|
||||
DECL(osl_##name##_dvvdfvf, "xvvXvf") \
|
||||
DECL(osl_##name##_dvdvdfvf, "xvvXvf")
|
||||
|
||||
#define GENERIC_PNOISE_DERIV_IMPL(name) \
|
||||
DECL (osl_ ## name ## _dfdff, "xsXXfXX") \
|
||||
DECL (osl_ ## name ## _dfdfdfff, "xsXXXffXX") \
|
||||
DECL (osl_ ## name ## _dfdvv, "xsXXvXX") \
|
||||
DECL (osl_ ## name ## _dfdvdfvf, "xsXvXvfXX") \
|
||||
DECL (osl_ ## name ## _dvdff, "xsvXfXX") \
|
||||
DECL (osl_ ## name ## _dvdfdfff, "xsvXXffXX") \
|
||||
DECL (osl_ ## name ## _dvdvv, "xsvvvXX") \
|
||||
DECL (osl_ ## name ## _dvdvdfvf, "xsvvXvfXX")
|
||||
#define GENERIC_PNOISE_DERIV_IMPL(name) \
|
||||
DECL(osl_##name##_dfdff, "xsXXfXX") \
|
||||
DECL(osl_##name##_dfdfdfff, "xsXXXffXX") \
|
||||
DECL(osl_##name##_dfdvv, "xsXXvXX") \
|
||||
DECL(osl_##name##_dfdvdfvf, "xsXvXvfXX") \
|
||||
DECL(osl_##name##_dvdff, "xsvXfXX") \
|
||||
DECL(osl_##name##_dvdfdfff, "xsvXXffXX") \
|
||||
DECL(osl_##name##_dvdvv, "xsvvvXX") \
|
||||
DECL(osl_##name##_dvdvdfvf, "xsvvXvfXX")
|
||||
|
||||
#define UNARY_OP_IMPL(name) \
|
||||
DECL (osl_ ## name ## _ff, "ff") \
|
||||
DECL (osl_ ## name ## _dfdf, "xXX") \
|
||||
DECL (osl_ ## name ## _vv, "xXX") \
|
||||
DECL (osl_ ## name ## _dvdv, "xXX")
|
||||
#define UNARY_OP_IMPL(name) \
|
||||
DECL(osl_##name##_ff, "ff") \
|
||||
DECL(osl_##name##_dfdf, "xXX") \
|
||||
DECL(osl_##name##_vv, "xXX") \
|
||||
DECL(osl_##name##_dvdv, "xXX")
|
||||
|
||||
#define BINARY_OP_IMPL(name) \
|
||||
DECL (osl_ ## name ## _fff, "fff") \
|
||||
DECL (osl_ ## name ## _dfdfdf, "xXXX") \
|
||||
DECL (osl_ ## name ## _dffdf, "xXfX") \
|
||||
DECL (osl_ ## name ## _dfdff, "xXXf") \
|
||||
DECL (osl_ ## name ## _vvv, "xXXX") \
|
||||
DECL (osl_ ## name ## _dvdvdv, "xXXX") \
|
||||
DECL (osl_ ## name ## _dvvdv, "xXXX") \
|
||||
DECL (osl_ ## name ## _dvdvv, "xXXX")
|
||||
#define BINARY_OP_IMPL(name) \
|
||||
DECL(osl_##name##_fff, "fff") \
|
||||
DECL(osl_##name##_dfdfdf, "xXXX") \
|
||||
DECL(osl_##name##_dffdf, "xXfX") \
|
||||
DECL(osl_##name##_dfdff, "xXXf") \
|
||||
DECL(osl_##name##_vvv, "xXXX") \
|
||||
DECL(osl_##name##_dvdvdv, "xXXX") \
|
||||
DECL(osl_##name##_dvvdv, "xXXX") \
|
||||
DECL(osl_##name##_dvdvv, "xXXX")
|
||||
|
||||
|
||||
|
||||
|
||||
DECL (osl_add_closure_closure, "CXCC")
|
||||
DECL (osl_mul_closure_float, "CXCf")
|
||||
DECL (osl_mul_closure_color, "CXCc")
|
||||
DECL (osl_allocate_closure_component, "CXii")
|
||||
DECL (osl_allocate_weighted_closure_component, "CXiiX")
|
||||
DECL (osl_closure_to_string, "sXC")
|
||||
DECL (osl_format, "ss*")
|
||||
DECL (osl_printf, "xXs*")
|
||||
DECL (osl_fprintf, "xXss*")
|
||||
DECL (osl_error, "xXs*")
|
||||
DECL (osl_warning, "xXs*")
|
||||
DECL (osl_split, "isXsii")
|
||||
DECL (osl_incr_layers_executed, "xX")
|
||||
DECL(osl_add_closure_closure, "CXCC")
|
||||
DECL(osl_mul_closure_float, "CXCf")
|
||||
DECL(osl_mul_closure_color, "CXCc")
|
||||
DECL(osl_allocate_closure_component, "CXii")
|
||||
DECL(osl_allocate_weighted_closure_component, "CXiiX")
|
||||
DECL(osl_closure_to_string, "sXC")
|
||||
DECL(osl_format, "ss*")
|
||||
DECL(osl_printf, "xXs*")
|
||||
DECL(osl_fprintf, "xXss*")
|
||||
DECL(osl_error, "xXs*")
|
||||
DECL(osl_warning, "xXs*")
|
||||
DECL(osl_split, "isXsii")
|
||||
DECL(osl_incr_layers_executed, "xX")
|
||||
|
||||
NOISE_IMPL(cellnoise)
|
||||
//NOISE_DERIV_IMPL(cellnoise)
|
||||
@@ -151,70 +150,70 @@ PNOISE_IMPL(psnoise)
|
||||
PNOISE_DERIV_IMPL(psnoise)
|
||||
GENERIC_PNOISE_DERIV_IMPL(gaborpnoise)
|
||||
GENERIC_PNOISE_DERIV_IMPL(genericpnoise)
|
||||
DECL (osl_noiseparams_set_anisotropic, "xXi")
|
||||
DECL (osl_noiseparams_set_do_filter, "xXi")
|
||||
DECL (osl_noiseparams_set_direction, "xXv")
|
||||
DECL (osl_noiseparams_set_bandwidth, "xXf")
|
||||
DECL (osl_noiseparams_set_impulses, "xXf")
|
||||
DECL (osl_count_noise, "xX")
|
||||
DECL (osl_hash_ii, "ii")
|
||||
DECL (osl_hash_if, "if")
|
||||
DECL (osl_hash_iff, "iff")
|
||||
DECL (osl_hash_iv, "iX")
|
||||
DECL (osl_hash_ivf, "iXf")
|
||||
DECL(osl_noiseparams_set_anisotropic, "xXi")
|
||||
DECL(osl_noiseparams_set_do_filter, "xXi")
|
||||
DECL(osl_noiseparams_set_direction, "xXv")
|
||||
DECL(osl_noiseparams_set_bandwidth, "xXf")
|
||||
DECL(osl_noiseparams_set_impulses, "xXf")
|
||||
DECL(osl_count_noise, "xX")
|
||||
DECL(osl_hash_ii, "ii")
|
||||
DECL(osl_hash_if, "if")
|
||||
DECL(osl_hash_iff, "iff")
|
||||
DECL(osl_hash_iv, "iX")
|
||||
DECL(osl_hash_ivf, "iXf")
|
||||
|
||||
DECL (osl_spline_fff, "xXXXXii")
|
||||
DECL (osl_spline_dfdfdf, "xXXXXii")
|
||||
DECL (osl_spline_dfdff, "xXXXXii")
|
||||
DECL (osl_spline_dffdf, "xXXXXii")
|
||||
DECL (osl_spline_vfv, "xXXXXii")
|
||||
DECL (osl_spline_dvdfdv, "xXXXXii")
|
||||
DECL (osl_spline_dvdfv, "xXXXXii")
|
||||
DECL (osl_spline_dvfdv, "xXXXXii")
|
||||
DECL (osl_splineinverse_fff, "xXXXXii")
|
||||
DECL (osl_splineinverse_dfdfdf, "xXXXXii")
|
||||
DECL (osl_splineinverse_dfdff, "xXXXXii")
|
||||
DECL (osl_splineinverse_dffdf, "xXXXXii")
|
||||
DECL (osl_setmessage, "xXsLXisi")
|
||||
DECL (osl_getmessage, "iXssLXiisi")
|
||||
DECL (osl_pointcloud_search, "iXsXfiiXXii*")
|
||||
DECL (osl_pointcloud_get, "iXsXisLX")
|
||||
DECL (osl_pointcloud_write, "iXsXiXXX")
|
||||
DECL (osl_pointcloud_write_helper, "xXXXisLX")
|
||||
DECL (osl_blackbody_vf, "xXXf")
|
||||
DECL (osl_wavelength_color_vf, "xXXf")
|
||||
DECL (osl_luminance_fv, "xXXX")
|
||||
DECL (osl_luminance_dfdv, "xXXX")
|
||||
DECL (osl_prepend_color_from, "xXXs")
|
||||
DECL (osl_prepend_matrix_from, "iXXs")
|
||||
DECL (osl_get_matrix, "iXXs")
|
||||
DECL (osl_get_inverse_matrix, "iXXs")
|
||||
DECL (osl_transform_triple, "iXXiXiXXi")
|
||||
DECL (osl_transform_triple_nonlinear, "iXXiXiXXi")
|
||||
DECL (osl_transform_vmv, "xXXX")
|
||||
DECL (osl_transform_dvmdv, "xXXX")
|
||||
DECL (osl_transformv_vmv, "xXXX")
|
||||
DECL (osl_transformv_dvmdv, "xXXX")
|
||||
DECL (osl_transformn_vmv, "xXXX")
|
||||
DECL (osl_transformn_dvmdv, "xXXX")
|
||||
DECL (osl_transformc, "iXXiXiXX")
|
||||
DECL(osl_spline_fff, "xXXXXii")
|
||||
DECL(osl_spline_dfdfdf, "xXXXXii")
|
||||
DECL(osl_spline_dfdff, "xXXXXii")
|
||||
DECL(osl_spline_dffdf, "xXXXXii")
|
||||
DECL(osl_spline_vfv, "xXXXXii")
|
||||
DECL(osl_spline_dvdfdv, "xXXXXii")
|
||||
DECL(osl_spline_dvdfv, "xXXXXii")
|
||||
DECL(osl_spline_dvfdv, "xXXXXii")
|
||||
DECL(osl_splineinverse_fff, "xXXXXii")
|
||||
DECL(osl_splineinverse_dfdfdf, "xXXXXii")
|
||||
DECL(osl_splineinverse_dfdff, "xXXXXii")
|
||||
DECL(osl_splineinverse_dffdf, "xXXXXii")
|
||||
DECL(osl_setmessage, "xXsLXisi")
|
||||
DECL(osl_getmessage, "iXssLXiisi")
|
||||
DECL(osl_pointcloud_search, "iXsXfiiXXii*")
|
||||
DECL(osl_pointcloud_get, "iXsXisLX")
|
||||
DECL(osl_pointcloud_write, "iXsXiXXX")
|
||||
DECL(osl_pointcloud_write_helper, "xXXXisLX")
|
||||
DECL(osl_blackbody_vf, "xXXf")
|
||||
DECL(osl_wavelength_color_vf, "xXXf")
|
||||
DECL(osl_luminance_fv, "xXXX")
|
||||
DECL(osl_luminance_dfdv, "xXXX")
|
||||
DECL(osl_prepend_color_from, "xXXs")
|
||||
DECL(osl_prepend_matrix_from, "iXXs")
|
||||
DECL(osl_get_matrix, "iXXs")
|
||||
DECL(osl_get_inverse_matrix, "iXXs")
|
||||
DECL(osl_transform_triple, "iXXiXiXXi")
|
||||
DECL(osl_transform_triple_nonlinear, "iXXiXiXXi")
|
||||
DECL(osl_transform_vmv, "xXXX")
|
||||
DECL(osl_transform_dvmdv, "xXXX")
|
||||
DECL(osl_transformv_vmv, "xXXX")
|
||||
DECL(osl_transformv_dvmdv, "xXXX")
|
||||
DECL(osl_transformn_vmv, "xXXX")
|
||||
DECL(osl_transformn_dvmdv, "xXXX")
|
||||
DECL(osl_transformc, "iXXiXiXX")
|
||||
|
||||
DECL (osl_dict_find_iis, "iXiX")
|
||||
DECL (osl_dict_find_iss, "iXXX")
|
||||
DECL (osl_dict_next, "iXi")
|
||||
DECL (osl_dict_value, "iXiXLX")
|
||||
DECL (osl_raytype_name, "iXX")
|
||||
DECL(osl_dict_find_iis, "iXiX")
|
||||
DECL(osl_dict_find_iss, "iXXX")
|
||||
DECL(osl_dict_next, "iXi")
|
||||
DECL(osl_dict_value, "iXiXLX")
|
||||
DECL(osl_raytype_name, "iXs")
|
||||
#ifdef OSL_LLVM_NO_BITCODE
|
||||
DECL (osl_range_check, "iiiXXXiXiXX")
|
||||
DECL(osl_range_check, "iiiXXXiXiXX")
|
||||
#endif
|
||||
DECL (osl_range_check_err, "iiiXXXiXiXX")
|
||||
DECL (osl_naninf_check, "xiXiXXiXiiX")
|
||||
DECL (osl_uninit_check, "xLXXXiXiXXiXiXii")
|
||||
DECL (osl_get_attribute, "iXiXXiiLX")
|
||||
DECL (osl_bind_interpolated_param, "iXXLiXiXiXi")
|
||||
DECL (osl_get_texture_options, "XX");
|
||||
DECL (osl_get_noise_options, "XX");
|
||||
DECL (osl_get_trace_options, "XX");
|
||||
DECL(osl_range_check_err, "iiiXXXiXiXX")
|
||||
DECL(osl_naninf_check, "xiXiXXiXiiX")
|
||||
DECL(osl_uninit_check, "xLXXXiXiXXiXiXii")
|
||||
DECL(osl_get_attribute, "iXiXXiiLX")
|
||||
DECL(osl_bind_interpolated_param, "iXXLiXiXiXi")
|
||||
DECL(osl_get_texture_options, "XX");
|
||||
DECL(osl_get_noise_options, "XX");
|
||||
DECL(osl_get_trace_options, "XX");
|
||||
|
||||
|
||||
// The following are defined inside llvm_ops.cpp. Only include these
|
||||
@@ -231,17 +230,17 @@ UNARY_OP_IMPL(sinh)
|
||||
UNARY_OP_IMPL(cosh)
|
||||
UNARY_OP_IMPL(tanh)
|
||||
|
||||
DECL (osl_safe_div_iii, "iii")
|
||||
DECL (osl_safe_div_fff, "fff")
|
||||
DECL (osl_safe_mod_iii, "iii")
|
||||
DECL (osl_sincos_fff, "xfXX")
|
||||
DECL (osl_sincos_dfdff, "xXXX")
|
||||
DECL (osl_sincos_dffdf, "xXXX")
|
||||
DECL (osl_sincos_dfdfdf, "xXXX")
|
||||
DECL (osl_sincos_vvv, "xXXX")
|
||||
DECL (osl_sincos_dvdvv, "xXXX")
|
||||
DECL (osl_sincos_dvvdv, "xXXX")
|
||||
DECL (osl_sincos_dvdvdv, "xXXX")
|
||||
DECL(osl_safe_div_iii, "iii")
|
||||
DECL(osl_safe_div_fff, "fff")
|
||||
DECL(osl_safe_mod_iii, "iii")
|
||||
DECL(osl_sincos_fff, "xfXX")
|
||||
DECL(osl_sincos_dfdff, "xXXX")
|
||||
DECL(osl_sincos_dffdf, "xXXX")
|
||||
DECL(osl_sincos_dfdfdf, "xXXX")
|
||||
DECL(osl_sincos_vvv, "xXXX")
|
||||
DECL(osl_sincos_dvdvv, "xXXX")
|
||||
DECL(osl_sincos_dvvdv, "xXXX")
|
||||
DECL(osl_sincos_dvdvdv, "xXXX")
|
||||
|
||||
UNARY_OP_IMPL(log)
|
||||
UNARY_OP_IMPL(log2)
|
||||
@@ -253,138 +252,138 @@ BINARY_OP_IMPL(pow)
|
||||
UNARY_OP_IMPL(erf)
|
||||
UNARY_OP_IMPL(erfc)
|
||||
|
||||
DECL (osl_pow_vvf, "xXXf")
|
||||
DECL (osl_pow_dvdvdf, "xXXX")
|
||||
DECL (osl_pow_dvvdf, "xXXX")
|
||||
DECL (osl_pow_dvdvf, "xXXf")
|
||||
DECL(osl_pow_vvf, "xXXf")
|
||||
DECL(osl_pow_dvdvdf, "xXXX")
|
||||
DECL(osl_pow_dvvdf, "xXXX")
|
||||
DECL(osl_pow_dvdvf, "xXXf")
|
||||
|
||||
UNARY_OP_IMPL(sqrt)
|
||||
UNARY_OP_IMPL(inversesqrt)
|
||||
UNARY_OP_IMPL(cbrt)
|
||||
|
||||
DECL (osl_logb_ff, "ff")
|
||||
DECL (osl_logb_vv, "xXX")
|
||||
DECL(osl_logb_ff, "ff")
|
||||
DECL(osl_logb_vv, "xXX")
|
||||
|
||||
DECL (osl_floor_ff, "ff")
|
||||
DECL (osl_floor_vv, "xXX")
|
||||
DECL (osl_ceil_ff, "ff")
|
||||
DECL (osl_ceil_vv, "xXX")
|
||||
DECL (osl_round_ff, "ff")
|
||||
DECL (osl_round_vv, "xXX")
|
||||
DECL (osl_trunc_ff, "ff")
|
||||
DECL (osl_trunc_vv, "xXX")
|
||||
DECL (osl_sign_ff, "ff")
|
||||
DECL (osl_sign_vv, "xXX")
|
||||
DECL (osl_step_fff, "fff")
|
||||
DECL (osl_step_vvv, "xXXX")
|
||||
DECL(osl_floor_ff, "ff")
|
||||
DECL(osl_floor_vv, "xXX")
|
||||
DECL(osl_ceil_ff, "ff")
|
||||
DECL(osl_ceil_vv, "xXX")
|
||||
DECL(osl_round_ff, "ff")
|
||||
DECL(osl_round_vv, "xXX")
|
||||
DECL(osl_trunc_ff, "ff")
|
||||
DECL(osl_trunc_vv, "xXX")
|
||||
DECL(osl_sign_ff, "ff")
|
||||
DECL(osl_sign_vv, "xXX")
|
||||
DECL(osl_step_fff, "fff")
|
||||
DECL(osl_step_vvv, "xXXX")
|
||||
|
||||
DECL (osl_isnan_if, "if")
|
||||
DECL (osl_isinf_if, "if")
|
||||
DECL (osl_isfinite_if, "if")
|
||||
DECL (osl_abs_ii, "ii")
|
||||
DECL (osl_fabs_ii, "ii")
|
||||
DECL(osl_isnan_if, "if")
|
||||
DECL(osl_isinf_if, "if")
|
||||
DECL(osl_isfinite_if, "if")
|
||||
DECL(osl_abs_ii, "ii")
|
||||
DECL(osl_fabs_ii, "ii")
|
||||
|
||||
UNARY_OP_IMPL(abs)
|
||||
UNARY_OP_IMPL(fabs)
|
||||
BINARY_OP_IMPL(fmod)
|
||||
|
||||
DECL (osl_smoothstep_ffff, "ffff")
|
||||
DECL (osl_smoothstep_dfffdf, "xXffX")
|
||||
DECL (osl_smoothstep_dffdff, "xXfXf")
|
||||
DECL (osl_smoothstep_dffdfdf, "xXfXX")
|
||||
DECL (osl_smoothstep_dfdfff, "xXXff")
|
||||
DECL (osl_smoothstep_dfdffdf, "xXXfX")
|
||||
DECL (osl_smoothstep_dfdfdff, "xXXXf")
|
||||
DECL (osl_smoothstep_dfdfdfdf, "xXXXX")
|
||||
DECL(osl_smoothstep_ffff, "ffff")
|
||||
DECL(osl_smoothstep_dfffdf, "xXffX")
|
||||
DECL(osl_smoothstep_dffdff, "xXfXf")
|
||||
DECL(osl_smoothstep_dffdfdf, "xXfXX")
|
||||
DECL(osl_smoothstep_dfdfff, "xXXff")
|
||||
DECL(osl_smoothstep_dfdffdf, "xXXfX")
|
||||
DECL(osl_smoothstep_dfdfdff, "xXXXf")
|
||||
DECL(osl_smoothstep_dfdfdfdf, "xXXXX")
|
||||
|
||||
DECL (osl_dot_fvv, "fXX")
|
||||
DECL (osl_dot_dfdvdv, "xXXX")
|
||||
DECL (osl_dot_dfdvv, "xXXX")
|
||||
DECL (osl_dot_dfvdv, "xXXX")
|
||||
DECL (osl_cross_vvv, "xXXX")
|
||||
DECL (osl_cross_dvdvdv, "xXXX")
|
||||
DECL (osl_cross_dvdvv, "xXXX")
|
||||
DECL (osl_cross_dvvdv, "xXXX")
|
||||
DECL (osl_length_fv, "fX")
|
||||
DECL (osl_length_dfdv, "xXX")
|
||||
DECL (osl_distance_fvv, "fXX")
|
||||
DECL (osl_distance_dfdvdv, "xXXX")
|
||||
DECL (osl_distance_dfdvv, "xXXX")
|
||||
DECL (osl_distance_dfvdv, "xXXX")
|
||||
DECL (osl_normalize_vv, "xXX")
|
||||
DECL (osl_normalize_dvdv, "xXX")
|
||||
DECL(osl_dot_fvv, "fXX")
|
||||
DECL(osl_dot_dfdvdv, "xXXX")
|
||||
DECL(osl_dot_dfdvv, "xXXX")
|
||||
DECL(osl_dot_dfvdv, "xXXX")
|
||||
DECL(osl_cross_vvv, "xXXX")
|
||||
DECL(osl_cross_dvdvdv, "xXXX")
|
||||
DECL(osl_cross_dvdvv, "xXXX")
|
||||
DECL(osl_cross_dvvdv, "xXXX")
|
||||
DECL(osl_length_fv, "fX")
|
||||
DECL(osl_length_dfdv, "xXX")
|
||||
DECL(osl_distance_fvv, "fXX")
|
||||
DECL(osl_distance_dfdvdv, "xXXX")
|
||||
DECL(osl_distance_dfdvv, "xXXX")
|
||||
DECL(osl_distance_dfvdv, "xXXX")
|
||||
DECL(osl_normalize_vv, "xXX")
|
||||
DECL(osl_normalize_dvdv, "xXX")
|
||||
#endif
|
||||
|
||||
|
||||
DECL (osl_mul_mmm, "xXXX")
|
||||
DECL (osl_mul_mmf, "xXXf")
|
||||
DECL(osl_mul_mmm, "xXXX")
|
||||
DECL(osl_mul_mmf, "xXXf")
|
||||
|
||||
DECL (osl_div_mmm, "xXXX")
|
||||
DECL (osl_div_mmf, "xXXf")
|
||||
DECL (osl_div_mfm, "xXfX")
|
||||
DECL(osl_div_mmm, "xXXX")
|
||||
DECL(osl_div_mmf, "xXXf")
|
||||
DECL(osl_div_mfm, "xXfX")
|
||||
|
||||
DECL (osl_get_from_to_matrix, "iXXss")
|
||||
DECL (osl_transpose_mm, "xXX")
|
||||
DECL (osl_determinant_fm, "fX")
|
||||
DECL(osl_get_from_to_matrix, "iXXss")
|
||||
DECL(osl_transpose_mm, "xXX")
|
||||
DECL(osl_determinant_fm, "fX")
|
||||
|
||||
DECL (osl_concat_sss, "sss")
|
||||
DECL (osl_strlen_is, "is")
|
||||
DECL (osl_hash_is, "is")
|
||||
DECL (osl_getchar_isi, "isi");
|
||||
DECL (osl_startswith_iss, "iss")
|
||||
DECL (osl_endswith_iss, "iss")
|
||||
DECL (osl_stoi_is, "is")
|
||||
DECL (osl_stof_fs, "fs")
|
||||
DECL (osl_substr_ssii, "ssii")
|
||||
DECL (osl_regex_impl, "iXsXisi")
|
||||
DECL(osl_concat_sss, "sss")
|
||||
DECL(osl_strlen_is, "is")
|
||||
DECL(osl_hash_is, "is")
|
||||
DECL(osl_getchar_isi, "isi");
|
||||
DECL(osl_startswith_iss, "iss")
|
||||
DECL(osl_endswith_iss, "iss")
|
||||
DECL(osl_stoi_is, "is")
|
||||
DECL(osl_stof_fs, "fs")
|
||||
DECL(osl_substr_ssii, "ssii")
|
||||
DECL(osl_regex_impl, "iXsXisi")
|
||||
|
||||
// Used by wide code generator, but are uniform calls
|
||||
DECL (osl_texture_decode_wrapmode, "iX");
|
||||
DECL (osl_texture_decode_interpmode, "iX");
|
||||
DECL(osl_texture_decode_wrapmode, "iX");
|
||||
DECL(osl_texture_decode_interpmode, "iX");
|
||||
|
||||
DECL (osl_texture_set_firstchannel, "xXi")
|
||||
DECL (osl_texture_set_swrap, "xXs")
|
||||
DECL (osl_texture_set_twrap, "xXs")
|
||||
DECL (osl_texture_set_rwrap, "xXs")
|
||||
DECL (osl_texture_set_stwrap, "xXs")
|
||||
DECL (osl_texture_set_swrap_code, "xXi")
|
||||
DECL (osl_texture_set_twrap_code, "xXi")
|
||||
DECL (osl_texture_set_rwrap_code, "xXi")
|
||||
DECL (osl_texture_set_stwrap_code, "xXi")
|
||||
DECL (osl_texture_set_sblur, "xXf")
|
||||
DECL (osl_texture_set_tblur, "xXf")
|
||||
DECL (osl_texture_set_rblur, "xXf")
|
||||
DECL (osl_texture_set_stblur, "xXf")
|
||||
DECL (osl_texture_set_swidth, "xXf")
|
||||
DECL (osl_texture_set_twidth, "xXf")
|
||||
DECL (osl_texture_set_rwidth, "xXf")
|
||||
DECL (osl_texture_set_stwidth, "xXf")
|
||||
DECL (osl_texture_set_fill, "xXf")
|
||||
DECL (osl_texture_set_time, "xXf")
|
||||
DECL (osl_texture_set_interp, "xXs")
|
||||
DECL (osl_texture_set_interp_code, "xXi")
|
||||
DECL (osl_texture_set_subimage, "xXi")
|
||||
DECL (osl_texture_set_subimagename, "xXs")
|
||||
DECL (osl_texture_set_missingcolor_arena, "xXX")
|
||||
DECL (osl_texture_set_missingcolor_alpha, "xXif")
|
||||
DECL (osl_texture, "iXXXXffffffiXXXXXXX")
|
||||
DECL (osl_texture3d, "iXXXXXXXXiXXXXXXX")
|
||||
DECL (osl_environment, "iXXXXXXXiXXXXXXX")
|
||||
DECL (osl_get_textureinfo, "iXXXXiiiXX")
|
||||
DECL (osl_get_textureinfo_st, "iXXXffXiiiXX")
|
||||
DECL(osl_texture_set_firstchannel, "xXi")
|
||||
DECL(osl_texture_set_swrap, "xXs")
|
||||
DECL(osl_texture_set_twrap, "xXs")
|
||||
DECL(osl_texture_set_rwrap, "xXs")
|
||||
DECL(osl_texture_set_stwrap, "xXs")
|
||||
DECL(osl_texture_set_swrap_code, "xXi")
|
||||
DECL(osl_texture_set_twrap_code, "xXi")
|
||||
DECL(osl_texture_set_rwrap_code, "xXi")
|
||||
DECL(osl_texture_set_stwrap_code, "xXi")
|
||||
DECL(osl_texture_set_sblur, "xXf")
|
||||
DECL(osl_texture_set_tblur, "xXf")
|
||||
DECL(osl_texture_set_rblur, "xXf")
|
||||
DECL(osl_texture_set_stblur, "xXf")
|
||||
DECL(osl_texture_set_swidth, "xXf")
|
||||
DECL(osl_texture_set_twidth, "xXf")
|
||||
DECL(osl_texture_set_rwidth, "xXf")
|
||||
DECL(osl_texture_set_stwidth, "xXf")
|
||||
DECL(osl_texture_set_fill, "xXf")
|
||||
DECL(osl_texture_set_time, "xXf")
|
||||
DECL(osl_texture_set_interp, "xXs")
|
||||
DECL(osl_texture_set_interp_code, "xXi")
|
||||
DECL(osl_texture_set_subimage, "xXi")
|
||||
DECL(osl_texture_set_subimagename, "xXs")
|
||||
DECL(osl_texture_set_missingcolor_arena, "xXX")
|
||||
DECL(osl_texture_set_missingcolor_alpha, "xXif")
|
||||
DECL(osl_texture, "iXXXXffffffiXXXXXXX")
|
||||
DECL(osl_texture3d, "iXXXXXXXXiXXXXXXX")
|
||||
DECL(osl_environment, "iXXXXXXXiXXXXXXX")
|
||||
DECL(osl_get_textureinfo, "iXXXXiiiXX")
|
||||
DECL(osl_get_textureinfo_st, "iXXXffXiiiXX")
|
||||
|
||||
DECL (osl_trace_set_mindist, "xXf")
|
||||
DECL (osl_trace_set_maxdist, "xXf")
|
||||
DECL (osl_trace_set_shade, "xXi")
|
||||
DECL (osl_trace_set_traceset, "xXs")
|
||||
DECL (osl_trace, "iXXXXXXXX")
|
||||
DECL(osl_trace_set_mindist, "xXf")
|
||||
DECL(osl_trace_set_maxdist, "xXf")
|
||||
DECL(osl_trace_set_shade, "xXi")
|
||||
DECL(osl_trace_set_traceset, "xXs")
|
||||
DECL(osl_trace, "iXXXXXXXX")
|
||||
|
||||
#ifdef OSL_LLVM_NO_BITCODE
|
||||
DECL (osl_calculatenormal, "xXXX")
|
||||
DECL (osl_area, "fX")
|
||||
DECL (osl_filterwidth_fdf, "fX")
|
||||
DECL (osl_filterwidth_vdv, "xXX")
|
||||
DECL (osl_raytype_bit, "iXi")
|
||||
DECL(osl_calculatenormal, "xXXX")
|
||||
DECL(osl_area, "fX")
|
||||
DECL(osl_filterwidth_fdf, "fX")
|
||||
DECL(osl_filterwidth_vdv, "xXX")
|
||||
DECL(osl_raytype_bit, "iXi")
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -143,15 +143,15 @@
|
||||
DECL(__OSL_MASKED_OP3(name, Wdv, Wv, Wdv), "xXXXi") \
|
||||
DECL(__OSL_MASKED_OP3(name, Wdv, Wdv, Wv), "xXXXi")
|
||||
|
||||
#define WIDE_BINARY_OP_IMPL(name) \
|
||||
DECL(__OSL_OP3(name, Wf, Wf, Wf), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdf, Wdf, Wdf), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdf, Wf, Wdf), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdf, Wdf, Wf), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wv, Wv, Wv), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdv, Wdv, Wdv), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdv, Wv, Wdv), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdv, Wdv, Wv), "xXXX") \
|
||||
#define WIDE_BINARY_OP_IMPL(name) \
|
||||
DECL(__OSL_OP3(name, Wf, Wf, Wf), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdf, Wdf, Wdf), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdf, Wf, Wdf), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdf, Wdf, Wf), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wv, Wv, Wv), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdv, Wdv, Wdv), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdv, Wv, Wdv), "xXXX") \
|
||||
DECL(__OSL_OP3(name, Wdv, Wdv, Wv), "xXXX") \
|
||||
WIDE_BINARY_OP_MASKED_IMPL(name)
|
||||
|
||||
|
||||
@@ -168,14 +168,12 @@
|
||||
DECL(__OSL_OP3(name, Wv, Wv, Wv), "xXXX") \
|
||||
DECL(__OSL_MASKED_OP3(name, Wv, Wv, Wv), "xXXXi")
|
||||
|
||||
#if 0 // incomplete closure support
|
||||
DECL (osl_add_closure_closure, "CXCC")
|
||||
DECL (osl_mul_closure_float, "CXCf")
|
||||
DECL (osl_mul_closure_color, "CXCc")
|
||||
DECL (osl_allocate_closure_component, "CXii")
|
||||
DECL (osl_allocate_weighted_closure_component, "CXiiX")
|
||||
DECL (osl_closure_to_string, "sXC")
|
||||
#endif
|
||||
DECL(__OSL_MASKED_OP(allocate_closure_component), "xXXiii")
|
||||
DECL(__OSL_MASKED_OP(allocate_weighted_closure_component), "xXXiiXi")
|
||||
DECL(__OSL_MASKED_OP(add_closure_closure), "xXXXXi")
|
||||
DECL(__OSL_MASKED_OP(mul_closure_float), "xXXXXi")
|
||||
DECL(__OSL_MASKED_OP(mul_closure_color), "xXXXXi")
|
||||
DECL(__OSL_OP(closure_to_string), "sXX")
|
||||
|
||||
DECL(__OSL_OP(format), "xXis*")
|
||||
DECL(__OSL_OP(printf), "xXis*")
|
||||
@@ -243,8 +241,19 @@ WIDE_NOISE_DERIV_IMPL(unullnoise)
|
||||
|
||||
DECL(__OSL_MASKED_OP(count_noise), "xXi")
|
||||
|
||||
DECL(__OSL_OP2(hash, Wi, Wi), "xXX")
|
||||
DECL(__OSL_OP2(hash, Wi, Wf), "xXX")
|
||||
DECL(__OSL_OP3(hash, Wi, Wf, Wf), "xXXX")
|
||||
DECL(__OSL_OP2(hash, Wi, Wv), "xXX")
|
||||
DECL(__OSL_OP3(hash, Wi, Wv, Wf), "xXXX")
|
||||
DECL(__OSL_MASKED_OP2(hash, Wi, Wi), "xXXi")
|
||||
DECL(__OSL_MASKED_OP2(hash, Wi, Wf), "xXXi")
|
||||
DECL(__OSL_MASKED_OP3(hash, Wi, Wf, Wf), "xXXXi")
|
||||
DECL(__OSL_MASKED_OP2(hash, Wi, Wv), "xXXi")
|
||||
DECL(__OSL_MASKED_OP3(hash, Wi, Wv, Wf), "xXXXi")
|
||||
|
||||
// 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.
|
||||
@@ -301,16 +310,12 @@ DECL(__OSL_MASKED_OP3(splineinverse, Wdf, f, Wdf), "xXXXXiii")
|
||||
// // unreachable, can't find .osl to produce this combination
|
||||
//DECL(__OSL_MASKED_OP3(splineinverse, Wdf, Wf, Wdf), "xXXXXiii")
|
||||
|
||||
#ifdef __OSL_TBD
|
||||
//DECL (osl_setmessage, "xXsLXisi")
|
||||
DECL (osl_pointcloud_search, "iXsXfiiXXii*")
|
||||
DECL (osl_pointcloud_get, "iXsXisLX")
|
||||
DECL (osl_pointcloud_write, "iXsXiXXX")
|
||||
DECL (osl_pointcloud_write_helper, "xXXXisLX")
|
||||
#endif
|
||||
DECL(__OSL_MASKED_OP(pointcloud_search), "xXXsXXiiXiXiiii*")
|
||||
DECL(__OSL_MASKED_OP(pointcloud_get), "iXsXiXsLXi")
|
||||
DECL(__OSL_MASKED_OP(pointcloud_write), "iXsXiXXXi")
|
||||
|
||||
DECL(__OSL_MASKED_OP(getmessage), "xXXssLXiisii")
|
||||
DECL(__OSL_MASKED_OP2(setmessage, s, WX), "xXXLXisii")
|
||||
DECL(__OSL_MASKED_OP2(setmessage, s, WX), "xXXLXisii")
|
||||
DECL(__OSL_MASKED_OP2(setmessage, Ws, WX), "xXXLXisii")
|
||||
|
||||
DECL(__OSL_OP(blackbody_vf), "xXXf")
|
||||
@@ -376,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
|
||||
@@ -453,11 +458,10 @@ WIDE_UNARY_F_OR_V_OP_IMPL(trunc)
|
||||
WIDE_UNARY_F_OR_V_OP_IMPL(sign)
|
||||
WIDE_BINARY_F_OR_V_OP_IMPL(step)
|
||||
|
||||
#ifdef __OSL_TBD
|
||||
WIDE_TEST_F_OP_IMPL(isnan)
|
||||
WIDE_TEST_F_OP_IMPL(isinf)
|
||||
WIDE_TEST_F_OP_IMPL(isfinite)
|
||||
#endif
|
||||
|
||||
WIDE_UNARY_OP_IMPL(abs)
|
||||
WIDE_UNARY_I_OP_IMPL(abs)
|
||||
WIDE_UNARY_OP_IMPL(fabs)
|
||||
|
||||
+49
-37
@@ -2,15 +2,16 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <OpenImageIO/sysutil.h>
|
||||
|
||||
#include <OSL/oslconfig.h>
|
||||
#include <OSL/oslclosure.h>
|
||||
#include <OSL/genclosure.h>
|
||||
#include <OSL/oslclosure.h>
|
||||
#include <OSL/oslconfig.h>
|
||||
|
||||
#include "oslexec_pvt.h"
|
||||
|
||||
|
||||
@@ -38,46 +39,54 @@ namespace pvt {
|
||||
|
||||
|
||||
static void
|
||||
print_component_value(std::ostream &out, ShadingSystemImpl *ss,
|
||||
TypeDesc type, const void *data)
|
||||
print_component_value(std::ostream& out, ShadingSystemImpl* ss, TypeDesc type,
|
||||
const void* data)
|
||||
|
||||
{
|
||||
if (type == TypeDesc::TypeInt)
|
||||
out << *(int *)data;
|
||||
out << *(int*)data;
|
||||
else if (type == TypeDesc::TypeFloat)
|
||||
out << *(float *)data;
|
||||
out << *(float*)data;
|
||||
else if (type == TypeDesc::TypeColor)
|
||||
out << "(" << ((Color3 *)data)->x << ", " << ((Color3 *)data)->y << ", " << ((Color3 *)data)->z << ")";
|
||||
out << "(" << ((Color3*)data)->x << ", " << ((Color3*)data)->y << ", "
|
||||
<< ((Color3*)data)->z << ")";
|
||||
else if (type == TypeDesc::TypeVector)
|
||||
out << "(" << ((Vec3 *)data)->x << ", " << ((Vec3 *)data)->y << ", " << ((Vec3 *)data)->z << ")";
|
||||
out << "(" << ((Vec3*)data)->x << ", " << ((Vec3*)data)->y << ", "
|
||||
<< ((Vec3*)data)->z << ")";
|
||||
else if (type == TypeDesc::TypeString)
|
||||
out << "\"" << *((ustring *)data) << "\"";
|
||||
out << "\"" << *((ustring*)data) << "\"";
|
||||
else if (type == TypeDesc::PTR) // this only happens for closures
|
||||
print_closure (out, *(const ClosureColor **)data, ss);
|
||||
print_closure(out, *(const ClosureColor**)data, ss);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
print_component (std::ostream &out, const ClosureComponent *comp, ShadingSystemImpl *ss, const Color3 &weight)
|
||||
print_component(std::ostream& out, const ClosureComponent* comp,
|
||||
ShadingSystemImpl* ss, const Color3& weight)
|
||||
{
|
||||
const ClosureRegistry::ClosureEntry *clentry = ss->find_closure(comp->id);
|
||||
const ClosureRegistry::ClosureEntry* clentry = ss->find_closure(comp->id);
|
||||
OSL_ASSERT(clentry);
|
||||
out << "(" << weight.x*comp->w.x << ", " << weight.y*comp->w.y << ", " << weight.z*comp->w.z << ") * ";
|
||||
out << "(" << weight.x * comp->w.x << ", " << weight.y * comp->w.y << ", "
|
||||
<< weight.z * comp->w.z << ") * ";
|
||||
out << clentry->name.c_str() << " (";
|
||||
for (int i = 0, nparams = clentry->params.size() - 1; i < nparams; ++i) {
|
||||
if (i) out << ", ";
|
||||
if (i)
|
||||
out << ", ";
|
||||
const ClosureParam& param = clentry->params[i];
|
||||
if (param.key != 0)
|
||||
out << "\"" << param.key << "\", ";
|
||||
if (param.type.numelements() > 1) out << "[";
|
||||
if (param.type.numelements() > 1)
|
||||
out << "[";
|
||||
for (size_t j = 0; j < param.type.numelements(); ++j) {
|
||||
if (j) out << ", ";
|
||||
if (j)
|
||||
out << ", ";
|
||||
print_component_value(out, ss, param.type.elementtype(),
|
||||
(const char *)comp->data() + param.offset
|
||||
+ param.type.elementsize() * j);
|
||||
(const char*)comp->data() + param.offset
|
||||
+ param.type.elementsize() * j);
|
||||
}
|
||||
if (clentry->params[i].type.numelements() > 1) out << "]";
|
||||
if (clentry->params[i].type.numelements() > 1)
|
||||
out << "]";
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
@@ -85,32 +94,35 @@ print_component (std::ostream &out, const ClosureComponent *comp, ShadingSystemI
|
||||
|
||||
|
||||
static void
|
||||
print_closure (std::ostream &out, const ClosureColor *closure, ShadingSystemImpl *ss, const Color3 &w, bool &first)
|
||||
print_closure(std::ostream& out, const ClosureColor* closure,
|
||||
ShadingSystemImpl* ss, const Color3& w, bool& first)
|
||||
{
|
||||
if (closure == NULL)
|
||||
return;
|
||||
|
||||
switch (closure->id) {
|
||||
case ClosureColor::MUL:
|
||||
print_closure(out, closure->as_mul()->closure, ss, closure->as_mul()->weight * w, first);
|
||||
break;
|
||||
case ClosureColor::ADD:
|
||||
print_closure(out, closure->as_add()->closureA, ss, w, first);
|
||||
print_closure(out, closure->as_add()->closureB, ss, w, first);
|
||||
break;
|
||||
default:
|
||||
if (!first)
|
||||
out << "\n\t+ ";
|
||||
print_component (out, closure->as_comp(), ss, w);
|
||||
first = false;
|
||||
break;
|
||||
case ClosureColor::MUL:
|
||||
print_closure(out, closure->as_mul()->closure, ss,
|
||||
closure->as_mul()->weight * w, first);
|
||||
break;
|
||||
case ClosureColor::ADD:
|
||||
print_closure(out, closure->as_add()->closureA, ss, w, first);
|
||||
print_closure(out, closure->as_add()->closureB, ss, w, first);
|
||||
break;
|
||||
default:
|
||||
if (!first)
|
||||
out << "\n\t+ ";
|
||||
print_component(out, closure->as_comp(), ss, w);
|
||||
first = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
print_closure (std::ostream &out, const ClosureColor *closure, ShadingSystemImpl *ss)
|
||||
print_closure(std::ostream& out, const ClosureColor* closure,
|
||||
ShadingSystemImpl* ss)
|
||||
{
|
||||
bool first = true;
|
||||
print_closure(out, closure, ss, Color3(1, 1, 1), first);
|
||||
@@ -118,7 +130,7 @@ print_closure (std::ostream &out, const ClosureColor *closure, ShadingSystemImpl
|
||||
|
||||
|
||||
|
||||
} // namespace pvt
|
||||
} // namespace pvt
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#include <OpenImageIO/thread.h>
|
||||
|
||||
@@ -27,48 +27,48 @@ namespace pvt {
|
||||
/// a new allocation tries to fit it in one of the allocated blocks, but
|
||||
/// if it won't fit anywhere, it makes a new block and adds it to the
|
||||
/// head of the list.
|
||||
template<class T>
|
||||
class ConstantPool {
|
||||
template<class T> class ConstantPool {
|
||||
public:
|
||||
/// Allocate a new pool of T's. The quanta, if supplied, is the
|
||||
/// number of T's to malloc at a time.
|
||||
ConstantPool (size_t quanta = 1000000) : m_quanta(quanta), m_total(0) { }
|
||||
ConstantPool(size_t quanta = 1000000) : m_quanta(quanta), m_total(0) {}
|
||||
|
||||
~ConstantPool () { }
|
||||
~ConstantPool() {}
|
||||
|
||||
/// Allocate space enough for n T's, and return a pointer to the
|
||||
/// start of that space.
|
||||
T * alloc (size_t n) {
|
||||
OIIO::lock_guard lock (m_mutex);
|
||||
T* alloc(size_t n)
|
||||
{
|
||||
OIIO::lock_guard lock(m_mutex);
|
||||
// Check each block in the block list to see if it has enough space
|
||||
for (auto&& block : m_block_list) {
|
||||
size_t s = block.size();
|
||||
if ((s+n) <= block.capacity()) {
|
||||
if ((s + n) <= block.capacity()) {
|
||||
// Enough space in this block. Use it.
|
||||
block.resize (s+n);
|
||||
block.resize(s + n);
|
||||
return &block[s];
|
||||
}
|
||||
}
|
||||
// If we got here, there were no mini-blocks in the list with enough
|
||||
// space. Make a new one.
|
||||
m_block_list.push_front (block_t());
|
||||
block_t &block (m_block_list.front());
|
||||
size_t s = std::max (m_quanta, n);
|
||||
block.reserve (s);
|
||||
m_block_list.push_front(block_t());
|
||||
block_t& block(m_block_list.front());
|
||||
size_t s = std::max(m_quanta, n);
|
||||
block.reserve(s);
|
||||
m_total += s * sizeof(T);
|
||||
block.resize (n);
|
||||
block.resize(n);
|
||||
return &block[0];
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::vector<T> block_t; ///< Type of block
|
||||
std::list<block_t> m_block_list; ///< List of memory blocks
|
||||
size_t m_quanta; ///< How big each memory block is (in T's, not bytes)
|
||||
size_t m_total; ///< Total memory allocated (bytes!)
|
||||
size_t m_quanta; ///< How big each memory block is (in T's, not bytes)
|
||||
size_t m_total; ///< Total memory allocated (bytes!)
|
||||
OIIO::mutex m_mutex; ///< Thread-safe lock
|
||||
};
|
||||
|
||||
|
||||
|
||||
}; // namespace OSL::pvt
|
||||
}; // namespace pvt
|
||||
OSL_NAMESPACE_EXIT
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user