Compare commits

...
153 Commits
Author SHA1 Message Date
Larry Gritz 5e47ef444e Stage for v1.13.7.0
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-03-01 14:55:56 -08:00
olegul e94b0fec1e fix: Mute partio error prints (#1774)
Signed-off-by: Ole Gulbrandsen <olecgi@gmail.com>
2024-03-01 13:02:36 -08:00
Larry Gritz ee3403a916 Increase timeout for slow MacOS-13 runner
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-02-27 17:51:08 -08:00
Larry Gritz da77f89205 ci: Test with Mac ARM runner (#1770)
Tweak results for ARM tests that have minor numerical differences and
update references.

Set parallel build level to nprocs+2 instead of hard-coding to be
better for the new runners having more cores than they used to.

Speed up macosx build of deps by using unity build of OIIO.

Fix runtest, was clobbering parameters to oiiodiff

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-02-27 16:48:58 -08:00
Larry Gritz 5fede29c6e docs: Fix links to RTD docs from github landing page (#1768)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-02-15 13:35:49 -08:00
Larry Gritz 434914e7ee admin: Switch release announcement workflow to jmertic's awesome action (#1766)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-02-15 13:35:43 -08:00
Larry Gritz 726dc3ff0c Stage for release of v1.13.6.1
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-02-01 00:22:53 -08:00
Larry Gritz a88d708bc8 admin: git blame ignore for recent formatting change
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-02-01 00:20:17 -08:00
Larry Gritz 90d94caecb style: Reformat with clang-format 17 (modified PR 1761)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-02-01 00:18:36 -08:00
Larry Gritz 5da8e8c8bb style: Raise our formatting standard to clang-format 17 (#1761)
We had been using clang-format 14. Bump to 17 as our official
reference standard for formatting.

Moved the clang-format CI test from an aswf container to bare Ubuntu
to make it run faster -- it doesn't need to do a real build, so
there's no point wasting 2 minutes or so downloading a container holding
library dependencies it won't need.

Also fix a duplicate line in .clang-format that newer clang-format
complained about.

Document that it's specifically clang-format 17 that is our formatting
standard

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-02-01 00:18:36 -08:00
Tim Grant 9ceac106fa fix: Fix NVPTX TargetMachine leak, etc. (#1763)
* Delete the NVPTX target machine in the LLVM_Util destructor.

* Initalize m_nvptx_target_machine to nullptr.

* Workaround clang/CUDA12 texref issue.

* Remove the unnecessary null check before deleting the NVPTX TargetMachine.

---------

Signed-off-by: Tim Grant <tgrant@nvidia.com>
2024-01-23 10:33:03 -08:00
Larry Gritz 726049ad49 fix(build): Remove unused ustrings (#1764)
A recent change in OIIO master made some of the ustring methods
"trivial", and somehow that makes these variables warn about being
unused, which it did not do before.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-01-18 16:22:28 -08:00
Larry Gritz 710d1154b3 ci: test against LLVM 17 (#1760)
Bump the "bleeding edge" test to LLVM 17, the "stable latest releases"
test to 16.

Cover clang 17 compilation with MacOS-13 build

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2024-01-09 20:28:33 -08:00
Larry Gritz 04645499ab admin: Account for duplicate emails in the .mailmap (#1759)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-12-28 13:22:00 -08:00
Larry Gritz 0d9ab3c495 Stage for v1.13.6.0 (beta 1)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-12-20 12:26:30 -08:00
Larry Gritz 3d52f3906b build: handle case where OIIO uses a different Imath than OSL (#1758)
This can come up if, for example, you build an OIIO using a static
Imath library that's more recent than what you're forced to use for
your OSL build. (Don't ask, you don't want to know.) So we need
to see half.h before we include any OIIO headers. But it's the OIIO
headers that adjudicated where we get half.h from, so we need to
be a little more explicit in, of all places, rend_lib.h of testrender.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-12-03 00:32:42 -08:00
Alex Wells e154a220b6 fix(build): Partio build errors on pointcloud functions for MSVC (#1757)
Fixes #1755: Build error on MSVC with Partio

Explicitly mark unsupported/unused PointCould copy/move constructors and assignment operators as deleted.
Change SortedPointRecord index type from int to uint32_t and add static_cast during construction to avoid a warning.

Change SortedPointRecord index type from uint32_t to Partio::ParticleIndex to handle 64bit indices (where we can)
clang-format changes

Signed-off-by: Alex M. Wells <alex.m.wells@intel.com>
2023-11-27 18:57:40 -08:00
Rasmus Bonnedal da8f2be156 build: Fix struct align/pack for MSVC (#1754)
Signed-off-by: Rasmus Bonnedal <rasmus.bonnedal@gmail.com>
2023-11-20 13:56:04 -08:00
Alex Wells bc864771df build: refactor icc/icx specific pragma macros (#1756)
Added OSL_INTEL_CLASSIC_PRAGMA(...) which only emits for Intel(r) Classic C++ Compiler, previously OSL_INTEL_PRAGMA did that.
As many Intel compiler specicif pragmas are now supported by icx and icc,
redefined OSL_INTEL_PRAGMA to emit for the classic and llvm based Intel compilers (icc and icx).
Updated some uses of OSL_INTEL_PRAGMA to OSL_INTEL_CLASSIC_PRAGMA as appropriate.

Fixed long icx 2023.1.0, 2023.2.0, 2023.2.1 build times for certain files by removing the "-mllvm -inline-threshold=100000" flag for all but 1 file avoiding the overhead of optimization passes being applied to inlined code that wasn't actually part of the SIMD loop that we truly needed inlined.  icx now supports "#pragma forceinline recursive" which allows us to target just the SIMD loops to be inlined (as we did for icc).

Signed-off-by: Alex M. Wells <alex.m.wells@intel.com>
2023-11-20 13:54:22 -08:00
Larry Gritz b38487532d ci: Test ABI compliance (#1748)
This patch adds a new test to the CI matrix: verifying that we do not
break the ABI during releases. This is based on similar work done a
couple months ago in OpenImageIO.

Basically, in addition to building the current checkout, it also
builds a checkout of the designated "ABI standard" (generally, the
first non-beta release of a major version), then generates ABI dumps
of both versions and runs the ABI compliance checker using the tools
from https://github.com/lvc

Making two builds sounds expensive, but both builds are rigged to be
minimal, since only the libraries are needed for ABI checks (we can
turn off the binary tools, unit tests, python bindings, etc.), and of
course the test suite need not run. So actually, it's less expensive
than most of the test matrix entries, and it helps ensure that we
don't accidentally break ABI when we don't mean to.

I'm not sure how many false positives we'll have. We might need to
adjust the methodology slightly as we gain experience with this.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-11-17 15:27:53 -08:00
Larry Gritz 7985893a76 build: Better cmake verbose behavior (#1752)
When we bumped to cmake 3.15 minimum recently, we changed lots of
constructs like this:

    if (VERBOSE)
        message (STATUS "blah")
    endif ()

to this:

    message (VERBOSE "blah")

but I didn't realize that this was not enough, and to do it right
requires CMAKE_MESSAGE_LOG_LEVEL. So even when VERBOSE=ON, we weren't
actually getting all the verbose messages. Here, we fix it.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-11-17 12:50:11 -08:00
Alex Wells 58ae6a1551 fix: batched pointcloud if "index" is not passed (#1753)
Fixes #1750

Batched shading crashes in point_cloud search if "index" is not passed as an attribute.
Fixed by allocating space for indices on stack before calling into underlying search algorithm which requires them (thus crashed if not provided).

Added 2 new tests to exercise it with no indices provided and with indices array provided but not long enough.

    testsuite/pointcloud/rdcloud_varying_mismatch.osl
    testsuite/pointcloud/rdcloud_varying_no_index.osl

Added alternative test results for
testsuite/pointcloud/ref/out_rdcloud_varying_mismatch.macos.tif
testsuite/geomath/ref/out.icx.alt.txt

Format change for wide_oppointcloud.cpp

Signed-off-by: Alex M. Wells <alex.m.wells@intel.com>
2023-11-17 11:44:05 -08:00
Rasmus Bonnedal 9320db9f2a testrender: Fix wrong offset of MxSheen param (#1751)
Signed-off-by: Rasmus Bonnedal <rasmus.bonnedal@gmail.com>
2023-11-15 16:42:10 -08:00
Larry Gritz 4d39f8099f admin: Fix typo in slack-release-notifier version (#1749)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-11-01 19:50:56 -07:00
Larry Gritz 41a45b68ea docs: Regenerate PDF docs before 1.13 release (#1747)
This is probably the last time we'll regen the PDF docs, since we
are mid-transition to ReadTheDocs. We will probably not directly
distribute a PDF version with 1.14 or subsequent releases.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-10-27 15:18:51 -07:00
Larry Gritz 8374278a07 ci: For clarity, use the term 'runner' instead of 'os' (#1743)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-10-27 14:13:33 -07:00
Larry Gritz 78b861f34a ci: Skip analysis and scorecard workflows on push if only docs changed (#1744)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-10-26 18:04:40 -07:00
Larry Gritz 7710b1be46 fix: SymOverrideInfo bitfields should be the same type (#1745)
Stephen Friedman alerted me to the fact that on Windows, bit fields
within a struct will only be combined if they are the same type.  We
were a bit sloppy in the defintion of SymOverrideInfo, and that was
causing the struct to end up a different size in Windows.  I think the
solution is that all those bit fields should be `unsigned int`.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-10-26 15:50:17 -07:00
Larry Gritz 0e55efbd99 ci: Disable MacOS-11 CI (#1746)
The MacOS 11 CI seems to be broken on GitHub's runners. I'm not sure
why, but since it's old and getting various deprecation warnings from
Homebrew and GH, I'm inclined to just disable it rather than work hard
to keep this old version of the OS running.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-10-26 15:49:27 -07:00
Larry Gritz 0d4c343759 docs: First stab at ReadTheDocs (#1736)
Convert the LaTeX docs to Sphinx + Myst Markdown extension

I think this is in decent shape. It's going to need a lot of thorough
proofreading to ensure that thing got lost or mangled on the way from
the original docs. I suspect we will have several follow-up PRs to fix
thing.

After we're reasonably happy with it, we'll eventually remove the
.tex and the pdf.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-10-05 12:10:57 -07:00
Larry Gritz 9636c8c66c admin: Update pull request template (#1741)
It gave a VERY old link to the SPI CLA, which we no longer use.  In
fact, because we have CLA enforcement through the CLA bot, there is
not really a need to have it in the checklist... nobody can forget.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-10-05 10:20:01 -07:00
Larry Gritz 784bf53e88 admin: Alert slack "release-announcements" channel upon OSL release (#1740)
Add a GHA workflow that is triggered up on drafting a release, which
will echo a notice to the ASWF slack `#release-announcements` channel.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-10-05 10:19:13 -07:00
cdfec4f31d LLVM 16 and 17 support (#1730)
* Bump minimum supported LLVM version to 17
* Rename `makeArrayRef` to `toArrayRef` to avoid `llvm::makeArrayRef`
  deprecation warnings.
* Minor required changes related to `llvm::Align`.
* Disable `initializeInstrumentation` and `createPruneEHPass` which
  were remove and appear to serve no purpose now.
* Add assert when using default optimization levels with legacy pass
  manager, which is no longer supported.

This depends on both opaque pointers and new pass manager support.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>

* Keep CMAKE_CXX_STANDARD warning for LLVM 16

* Enable LLVM 17 too, adjust for changes in new pass manager PR

* Fix OptiX data layout mismatch with LLVM 16+

i128:128 was already in the NVPTX backend since LLVM 6, the docs
this was taken from seem outdated. Unclear it started failing now,
but the data layout seems clearly incomplete without this.

* Modify CI to run the bleeding edge test on LLVM 16

* Manually make global variable names valid for PTX

* Fix build with older LLVM

---------

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
Co-authored-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Tim Grant <tgrant@nvidia.com>
2023-10-03 19:26:30 -07:00
Larry Gritz 3567aac515 build(deps): Raise OpenEXR min to 2.4 (#1734)
Only for OSL 1.13. Will not be backported to the current release.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-10-03 10:47:54 -07:00
Larry GritzandBrecht Van Lommel 00ea8a80fd build: Bump Cuda minimum to 9.0 (#1737)
Based on Brecht's tests, we realize that OSL doesn't work at all with
Cuda 8.0 (which didn't support the C++14 that we use), so we're
raising the minimum to 9.0. And there are some flaky tests with 9 and
10, so we're making the recommended minimum be 11.0.

It's not our policy to change the minimum versions of dependencies on
release branches, but I think we should backport this to the release
branch. I believe what this change is doing is not removing actual
support for old versions, but rather, correctly documenting what has
been working (or not) for quite some time.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Brecht Van Lommel <brecht@blender.org>
2023-10-02 22:39:26 -07:00
Brecht Van Lommel a95116f793 ci: Fix python-oslquery test failure on macOS (#1739)
Use the absolute path to the Python executable to avoid picking up
a different executable with the same version.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2023-10-02 22:37:31 -07:00
Brecht Van Lommel b8a100e427 ci: Fix GPU job not actually enabling OptiX (#1738)
In #1668 USE_OPTIX changed to OSL_USE_OPTIX, but CI was not updated.

Also fix use of CPU SIMD flags for compiling CUDA bitcode

---------

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2023-10-02 22:34:49 -07:00
Brecht Van Lommel 0210c88374 testing: Fix tests passing when test commands fail (#1733)
PR #1563 accidentally changed tests to accept failing commands by
default. (This seems to have been a mistake -- a temporary change
added when debugging that LG neglected to remove before submitting
the PR.)

This can cause tests to pass even though the program crashed, when
a previous run created the correct output file.

---------

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2023-09-28 15:17:34 -07:00
Brecht Van Lommel baca4c2de6 LLVM new pass manager support (#1729)
LLVM 16 removes support for default optimizations levels (O1, O2, O3)
from the legacy pass manager, which are used by OSL. This adds supports
for the new pass manager while keeping the legacy pass manager working
for older LLVM versions.

* Enable new pass manager for LLVM 15+
* Both default and custom optimization levels have been implemented
* But the performance and correctness beyond passing tests has not been
  verified
* `ptx_compile_group` still uses the legacy pass manager

* Fix unecessary alias analysis and wrong #endif placement

* Fix LLVM 16 compatibility

* Ensure running prevent bitmasks pass is reentrant, and initialize once

* Make compiling with the new and legacy pass manager mutually exclusive

LLVM 17 removes even more legacy pass manager functions. With these
changes LLVM 17 works as well.

* OptiX fix, avoid using legacy pass manager for opt command since it does
not support default -O levels anymore

* Only enable new pass manager for LLVM 16+

---------

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2023-09-28 12:00:54 -07:00
Brecht Van Lommel e4766b4516 LLVM opaque pointers support (#1728)
* LLVM opaque pointers support

New LLVM versions require opaque pointers, that is you can no longer tell
from a pointer value which data type it points to.

* Remove deprecated GEP and op_load methods without type, and refactor
  code to always pass the type.
* Add element type argument to op_scatter and op_gather.
* Eliminate pointer type comparison which no longer work with
  opaque pointers.
* Keep interactive params marked as uniform in batched analysis, so
  we can deduce uniform/varying correctly from just the symbol
* Enable opaque pointers on LLVM 15, except when using OptiX

OptiX opaque pointers were not tested yet and left disabled. It is
likely broken due to the sneaky conversion in
`BackendLLVM::llvm_store_value` between `int64` and `char*`, but we
can no longer compare the pointer type. This function is called from
many places and it's unclear to me when this happens.

According to a4e779c4 this code is only temporary, so this may resolve
itself as the ustring refactoring gets completed.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>

* Fix debug_uninit and pointcloud batched testsß

Signed-off-by: Brecht Van Lommel <brecht@blender.org>

* Variable renaming and comment for clarity

Signed-off-by: Brecht Van Lommel <brecht@blender.org>

* Add/restore debug names for groupdata access

Make batched backend more consistent with the regular backend.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>

* Rename scalar_type to component_type

Signed-off-by: Brecht Van Lommel <brecht@blender.org>

* Alternative interactive param fix based on feedback from Alex

Signed-off-by: Brecht Van Lommel <brecht@blender.org>

* OptiX fixes

Signed-off-by: Brecht Van Lommel <brecht@blender.org>

* Use opaque pointers only for LLVM 16+

To avoid potentially breaking LLVM 15 with OptiX.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>

---------

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2023-09-27 22:09:15 -07:00
Larry Gritz f00da4f788 RS::get_texture_info make robust to empty shaderglobals param (#1731)
The unconditional dereferencing of the sg pointer is only necessary if
texture_thread_info is not supplied. And for that matter, the
texture_thread_info is only necessary if the texture_handle is not
supplied.

So rearranging the nesting skips a bunch of the work, and the need
for the caller to supply the sg if they have the texture_thread_info,
nor for them to need texture_thread_info if they already have the
handle.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-09-25 19:55:09 -07:00
Alex Wells e327241a30 fix(batch): Fix Force LLVM Boolean (#1717)
Fixes #1716:  Crash assigning boolean expression to int in batched mode

Modifying BatchedAnalysis::establish_symbols_forced_llvm_bool to excluded renderer outputs to fix the issue.
Added new test compassign-bool to recreate the issue and verify it is fixed.

Comprehensive Fix for Issue 1716:  Crash assigning boolean expression to int in batched mode

Rearchitected BatchedAnalysis::establish_symbols_forced_llvm_bool to track a BoolStatus per Symbol evaluating all operations that write to the symbol. Only if all ops that write to it always produce a logically boolean result will the BoolStatus be set to Yes.

There is another set of ops that could produce a logically boolean result if their inputs were also boolean.  In that case the BoolStatus is set to Maybe and its input symbols tracked (as they may not have a known BoolStatus yet) and deferred for a follow on pass.

After the initial pass is made, if there were any deferred Symbols, we can check their dependencies to see if they have a known BoolStatus and we can set the Symbol's BoolStatus to Yes or No depending on those input dependencies.  If the BoolStatus of any dependencies is still Unknown, we just defer it again.  We continue making passes over deferred Symbols until we have established a known BoolStatus for them all.  Afterwards we use forced_llvm_bool(true) on the Symbols where BoolStatus is Yes.

Improved support for storing forced_llvm_bool Symbol values by automatically converting from int->bool and then a vector of bools (mask) to the platforms native mask type (might be vector of integers on platforms without native mask support).

Fixed bug in BatchedAnalysis where arrays of closures were not being marked as varying, only closures where.
Allow GroupData to hold actual boolean or native mask data type vs. integers when a Symbol is forced_llvm_bool.
Improved batched GroupData layout calculation to use llvm offset and alignment calculations based on the actual DataLayout (might consider upgrading the scalar code gen to do the same).

Fixed bug where results of partial results from RendererServices::get_userdata allowed initops to execute unmasked effectively overwriting the results from RendererServices::get_userdata.  Issue stemmed from op_useparam not being modelled properly by BatchedAnalysis.

Added new test compassign-bool to recreate the issue and verify it is fixed.
Added new test closure-layered to recreate the issue and verify it is fixed.
Added new test userdata-partial recreate the issue and verify it is fixed.

Fixed bug in analysis of forced_llvm_bool for getattribute, whose return value is always a bool but result parameter when it is an integer should NOT be forced_llvm_bool.
Added test getattribute-shading to recreate the issue and verify its fixed.

Added testsuite/getattribute-shading/ref/out-scalar.txt to support builds that exclude batched.

---------

Signed-off-by: Alex M. Wells <alex.m.wells@intel.com>
2023-09-21 08:11:39 -07:00
Larry Gritz a569d4f0be CHANGES
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-09-15 12:47:56 -07:00
Larry Gritz 46250b4c10 build(deps): Raise minimum CMake dependency from 3.12 to 3.15 (#1724)
This bump brings access to the following interesting features (not a
comprehensive list):

- 3.13  Nov 21, 2018

    - -B, -S let you specify source and build directories without the "cd" dance
    - target_link_options()
    - ctest --progress / CTEST_PROGRESS_OUTPUT

- 3.14  Mar 14, 2019

    - cmake --build now supports -v/--verbose
    - file(CREATE_LINK )

- 3.15  Jul 17, 2019

    - env CMAKE_GENERATOR can be used instead of -G
    - when using --build, the --target can now list multiple targets (and also can be `-t`)
    - --install can be used separately without running through the whole build
    - message() now supports NOTICE, VERBOSE, DEBUG and TRACE.
    - CMAKE_FIND_PACKAGE_PREFER_CONFIG variable
    - Enable C++20 for Apple Clang

Make sure all CI cases have a new enough cmake

Use message(VERBOSE ...) feature to simplify lots of `if` blocks.

Clean up code for older cmake versions

Freshen some of our CI build_<dependency>.bash scripts.

Note that this will NOT be backported to the current release branch,
but it will be part of the upcoming 1.13 family of releases.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-09-15 09:20:02 -07:00
Larry Gritz e235661479 Change RendererServices::get_texture_handle back to ustring (#1726)
We were overzealous in switching everything to ustringhash.  The
filename argument to get_texture_handle should allow taking a ustring.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-09-12 10:45:11 -07:00
Larry Gritz fdc0579931 The recently added SS::find_symloc can have const args (#1723)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-09-12 10:44:30 -07:00
Chris Hellmuth d4faecd79d perf(gpu): Move qualifying GroupData params onto stack (#1710)
On SPI Arnold, we are seeing GroupData as a bottleneck for GPU performance. Regardless of whether the buffer is backed by local or global memory, it's off-chip and slow to access.

This change moves qualifying parameters out of the GroupData struct and onto the stack. On GPU this makes those parameters more likely to be stored in registers, leading to better performance.
Qualifying parameter details

The qualifying parameters are all the output parameters minus three exceptions.

A typical output parameter's lifetime is scoped to the execution of the instance it is associated with. The parameter is initialized at the beginning of instance execution, accessed during the body of the instance, and after the instance body its final state is broadcast to all its downstream connections. This lifetime makes output parameters a good fit for stack storage.

The three exceptions:

  - output parameters can be connected upstream and written to before instance execution
  - output closures are initialized at the beginning of shader execution
  - output parameters can be renderer outputs and read after instance execution

These are all identifiable at code generation time and can be flagged as disqualifying.

Improvements

On internal scenes, this change improves performance by about 15% on GPU. On CPU there aren't any performance regressions, but we don't see significant gains either. It also improves ptx generation and compilation by about 10%, and slightly lowers our memory footprint due to the GroupData size reduction.
Tests

Exceptions 2 & 3 are covered by existing tests. A new test is added for exception 1, and for the case of successful optimization. This patch was also run through our internal shading testsuite.

---------

Signed-off-by: Chris Hellmuth <chellmuth@gmail.com>
2023-09-11 10:06:30 -07:00
Tim Grant f449749f24 OptiX PTX pipeline overhaul (#1680)
## Description

This PR is an overhaul of PTX compilation in OSL. The goal is to minimize the size of the generated PTX to help reduce time spent in subsequent stages (e.g., module creation, pipeline linking, etc.).

### rend_lib

The main functional change is in how the functions defined in rend_lib.cu are handled. In the current setup, rend_lib.cu is compiled to a standalone PTX file using nvcc. The functions are considered `extern` in generated shaders, and the dependencies are satisfied when the final pipeline is linked together. Since the functions are `extern`, they are not available for optimization when each shader is generated. This prevents the inlining of small functions, which incurs a lot of function call overhead in terms of PTX size and run-time cost.

So instead of compiling rend_lib.cu separately, it is compiled to LLVM bitcode along with the rest of the "shadeops" sources. This bitcode is used to seed the LLVM Module for each shader. This makes the definitions available when each shader is being generated and optimized, which allows the optimizer to make better decisions. It also allows for better control of inlining decisions which affect the size and quality of the generated PTX.

### shadeops

Another significant functional change is in how the shadeops functions (including those defined in rend_lib.cu) are treated. In the current pipeline, each shader must carry along with it definitions for all non-inlined shadeops functions that are used. This bloats the size of the PTX for each shader, and results in many duplicate copies of those functions existing in the final linked pipeline.

In the new pipeline, the unified shadeops+rend_lib bitcode is compiled to PTX using the offline `llc` tool. This PTX is used by the renderer to create a single "shadeops" module that provides the definitions for those functions. This makes it possible to drop the definitions for those functions from the PTX for each shader, which can significantly reduce the size of the generated PTX.

### quirks

This PR contains some interesting "quirks" which are largely fallout from compiling rend_lib.cu using clang instead of nvcc:

- The clang-generated PTX is processed by a Python script to transform some function & symbol declarations to better match what was generated by nvcc. It might be possible to add the right decorators to the C++/CUDA code to get the correct visibility for these symbols, but I was not successful in doing so.
- It was necessary to change the function signatures for some of the rend_lib functions to use `void*` instead of the actual OSL types (e.g., `OSL::Color3*`). Trying to use the actual types produces an LLVM assertion failure, for reasons that I don't understand.
- I have enabled flush-to-zero (FTZ) for clang-compiled code, to better match the behavior of nvcc. I added a CMake variable to enable or disable FTZ in the event that somebody wants to disable it.
- I have added some alignment hints on pointer accesses in rend_lib.cu. clang does not appear to be able to deduce the alignment of pointers in many cases, which turns things like `memcpy` and `memset` into long series of byte operations. Functions like `osl_get_matrix` are bloated substantially if the hints aren't provided.

---------

Signed-off-by: Tim Grant <tgrant@nvidia.com>
2023-09-08 13:03:32 -07:00
Larry Gritz 8c2d8c03b4 Fix default fmt logic changing in latest openimageio release (#1725)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-09-05 18:37:28 -07:00
Larry Gritz 373e359b49 build(deps): Raise minimum OpenImageIO version to 2.4 (#1722)
This is just for future-looking OSL 1.13 releases, it won't be
backported to the 1.12 release branch.

Remember that by the time we release OSL 1.13 as a supported release
family, OIIO will also have done its annual release, of 2.5. So our
minimum of OIIO 2.4 means that we will be supporting the current
release, as well as the prior year's release (and, of course, we
always stay compatible with OIIO's trunk as it evolves). So we're
really keeping compatibility with 3 major releases, which seems like
plenty to juggle.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-09-03 18:50:36 -07:00
Curtis Black 7afd948737 feat: Add API for building attribute getter free functions. (#1704)
Adds a new RendererServices API build_attribute_getter which allows for building custom free functions that provide values for attributes, effectively replacing both get_attribute and get_array_attribute.

This new API is invoked at material compilation time to allow render developers to provide specialized functions capable of taking advantage of known compile time information. This will allow for many optimization opportunities, such as replacing run-time map lookups with direct memory reads from known locations, remove brancing required for checking if derivatives are needed, branching on type-conversions if required, etc.

This PR currently implements this approach for attributes, a future PR could do the same for user-data.
Tests

TestShade provides an example implementation showing how this compile time information can be used to select an appropriate function to use as the attribute provider, and how to configure the function signature.

---------

Signed-off-by: Curtis Black <curtis.w.black@gmail.com>
2023-09-01 09:44:44 -07:00
Larry Gritz 473bbfcdbd ci: Fix broken CI from new OIIO that needs newer cmake and openexr (#1719)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-26 14:23:49 -07:00
Tim Grant 05f4acee5b fix: Add missing members to ShaderGlobals in rend_lib.h (#1721)
* Add the missing thread_index and shade_index members to the copy of ShaderGlobals in testshade/cuda/rend_lib.h.

* Reorder the ShaderGlobals members in rend_lib.h to match the definition in shaderglobals.h.

---------

Signed-off-by: Tim Grant <tgrant@nvidia.com>
2023-08-25 14:33:07 -07:00
Larry Gritz a4e779c44f fix: Handle mixed string casting that plagues optix codegen (#1718)
The string situation is still a bit tricky on the OptiX side.  There's
a full overhaul of that coming separately as we continue to shift to
an all-ustringhash world.

But in the mean time, we were getting some testsuite failures that
were because of a mismatch between times we think of a gpu-side
ustring as a char* and when it's a uint64. IN FACT, they are always
the hashes, but we backed ourselves into a corner where sometimes that
64 bit pattern is passed around as a pointer, ugh.

This small patch attempts to catch this case and just do the
appropriate cast to compensate. It's a band-aid, a more comprehensive
fix is coming, as I said.

This gets us down to just ONE filing optix test case, which I will
tackle separately.

Signed-off-by: Larry Gritz <lg@larrygritz.com>

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-23 21:11:49 -07:00
Larry Gritz 271f8bc30e fix: Recent journaling changes break with some fmtlib versions (#1715)
Certain fmt library versions don't automatically know how to format
atomics. Explicitly load them to turn into regular ints to avoid new
build errors introduced by the recent journaling changes.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-22 17:47:52 -07:00
Larry Gritz 9e30a4e6df ci: Lock down icx version (#1706)
Intel's servers have again updated the default icx that you get when
you install from their yum repository, and the new one seems
incompatible with our libstdc++ toolchain. So lock down on 2023.1.0
for now so that our CI can pass.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-17 23:00:34 -07:00
Larry Gritz 3df1aa2f98 docs: Move logos and add an icon-only logo (#1707)
Move from cryptically named ASWF/images to more descriptive ASWF/logos.

Add an icon only version of the logo.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-17 23:00:04 -07:00
Larry Gritz afc44289fc ci: Simplify build_llvm.bash script (#1703)
* Remove leftover logic from when we used TravisCI.
* Pick a default for LLVM_DISTRO_NAME so it works when the script is run
  standalone when not on GitHub Actions CI.
* Switch the logic about file location to enumerate only the couple of
  old versions that uses the old download location, rather than trying
  to enumerate an ever-growing set of modern releases that use the current
  download location.
* Comment o say that when LLVM 10+ is the floor, the old case can go away
  entirely.

Also bump the CI "bleeding edge" test to use LLVM 15.0.6.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-17 22:59:08 -07:00
Larry Gritz 3bf59982e5 Restore stubs for printf (fixes OptiX problems with 1702) (#1711)
The recently merged PR 1702 fails all the OptiX tests. I tracked down
the problem and it's that the patch was a bit too aggressive about
removing things no longer needed. The intent was that even if you
don't use the new journaling, nothing should break. But it does break
for OptiX, and this patch restores some of the functions 1702 removed
(like the implementation of osl_printf) and some other necessary
stubs.

This takes us from failing all ~150 OptiX oriented tests to failing
only 4, which I believe are unrelated to 1702 and are merely revealed
by them. I will fix those in a separate PR.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-17 21:12:54 -07:00
Steena Monteiro cce40c38b8 Rs fmt specification - Journaling Algorithm for error, warning, fprintf (#1702)
* Journaling Algorithm for error, warning, fprintf

Removes dependence on ShadingContext and OIIO for logging error, warning, printf, and fprintf calls
for use on CPU and device, and tracks logging calls per thread index and shade index.
All calls to shader execution track thread index; ShaderGlobals contains shade_index (for processing
fmt specification calls) and thread_index for allocating memory per thread.

* Add new customization points in RendererServices for reporting errors, warnings, printf, and fprintf.
These customization points accept a fmtlib style format specifier (vs. printf style) whose argument types are represented as EncodedTypes (encodedtypes.h) and can be subsequently decoded via a utility function.

Removes dependence on ShadingContext and OSL::ErrorHandler for logging error, warning, printf, and fprintf calls
for use on CPU and device during Shader execution.  ShadingContext and OSL::ErrorHandler remain utilized during shader compilation/JIT.

Journal Buffer approach:  each thread gets its own chain of pages within the shared journal buffer for recording errors, warnings, etc.  By maintaining a separate chain per thread we can record errors (etc.) in a non-blocking fashion. Shade index is recorded for use by error reporter to sort messages but it is not used at present.
Using a Journal buffer is up to a Renderer.  The Renderer use the new customization points (rs_errorfmt, rs_filefmt, rs_printfmt, rs_warningfmt or their virtual function equivalents) to interact with a journal::Writer and journal buffer owned by its RenderState.  The Renderer would of have to allocate and initialized the journal buffer with the requested page size and number of threads before executing a shader. After a shader is done executing, the contents of the journal buffer can be transfered back to the host and processed with a journal::Reader, which reports them through a journal::Reporter's virtual interface. Intent is for Renderers's to use the Journal buffer and provide their own overriden version of the journal::Reporter.  Testshade provides example usage.  For legacy purposes, the default virtual RendererServices will route errors to ShadingSystem's OSL::ErrorHandler, but intent is for Renderer's to switch over to using a Journal buffer or their own custom logging.

NOTE:  OSL library functions as well use Renderer Service free functions can directly call OSL::filefmt, OSL::printfmt, OSL::errorfmt, OSL::warningfmt which wrappers to the underlying free functions (who may record the messages into a journal buffer).

Added a new hashcode datatype in typespec.cpp; represented as "h" in function arguments in builtindecl.
To print closures added a new OSL function osl_closure_to_ustringhash to return a ustringhash_pod value directly.

Shader execute functions now require a zero-based thread_index to identify the calling thread; used for journalling.
RendererServices::get_texture_info parameter ShadingContext * changed to ShaderGlobals * (aka ExecutionContext).

ShaderGlobals now tracks both shade_index and thread_index.
As we look to hide/remove ShaderGlobals in the future, we still need a context object to replace the role the ShaderGlobals struct is currently serving (just minus the actual shader global variables).  As a first step towards this goal, we introduce the concept of an ExecutionContext and OpaqueExecutionContext.  These just alias to ShaderGlobals currently, but start to establish the idea of hiding its contents.  Instead of direct memory access to the ExecutionContext/ShaderGlobals new getter functions have been added that accept an OpaqueExecutionContext and provide the requested data.  When inlined there should be no performance penalty, and reliance on the ShaderGlobals implementation detail will be reduced.  IE:
    inline const Vec3 & get_P(OpaqueExecContextPtr oec);
    template<typename RenderStateT> RenderStateT* get_rs(OpaqueExecContextPtr oec);
    inline int get_raytype(OpaqueExecContextPtr oec);
Updated free function renderer services and opcolor to use the ExecContext, but left the rest alone to minimize size of this PR.

We introduce opfmt.cpp that provides shim function for llvm_gen to call, where the shim adapts datatypes from llvm to c++ forwarding calls to the free function renderer service error, warning, print, fileprint functions.

Split llvm_gen_printf into llvm_gen_printf_legacy, for string format calls or when using optix, and the new llvm_gen_print_fmt which will convert the printf style specifier to the fmtlib format that the Renderer Service customization points are expecting.

fprintf by default no longer writes out to a file, is routed to journal::Reporter::report_file_print which could be overriden (example in TestShade to maintain existing behavior).  However for security reasons, we do not recommend allowing OSL shader's direct file system but instead just an annotated log entry.

To maintain existing behavior of disallowing output of repeated errors/warnings over a history window, we have provided 2 classes that could be used during reporting: TrackRecentlyReported and Report2ErrorHandler.  TrackRecentlyReported can turn on/off limitting errors and warnings and control the history capacity.  Report2ErrorHandler simply reports errors to an existing OSL::ErrorHandler to allow for easy integration.  However we expect Renderers to not use Report2ErrorHandler and provide their own to directly interact with their logging systems.


---------

Signed-off-by: Steena Monteiro <steena.monteiro@intel.com>
2023-08-17 16:31:34 -07:00
Larry Gritz 1863d04edc admin: Add missing copyright notice to many files (#1708)
Our latest license scan from LF reveailed that the usual copyright and
license declaration was missing on many shader source files in
testsuite. This was never intentional, it was simply overlooked for
certain test files. Just add the standard notice to those files.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-08-17 15:36:16 -07:00
Brecht Van Lommel 06c42d5c18 fix(build): duplicate osl lexing symbols when building as static libraries (#1709)
Like other oslcomp source files that are duplicated in oslexec, this
duplication should only be done for shared library builds where the
symbols are hidden from each other.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
2023-08-11 00:06:25 -07:00
Larry Gritz 8dae508b4f docs: Update logos (#1705)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-07-20 22:00:58 -07:00
Alejandro Conty b4f0517f0c fix: Zero derivs for interactive params when needed (#1700)
Sometimes an interactive param is used in a way that gets
flagged as needing derivs. But we were neither allocating space
for that nor zeroing them. This resulted on memory corruption.

This fixes incorrect renders in a production context where params are
often tagged as needing derivs.

Signed-off-by: Alejandro Conty <aconty@imageworks.com>
2023-06-20 10:50:42 -07:00
Larry Gritz 5e10537608 ci: Switch OIIO dev-2.3 branch to using v2.3.21.0 tag (#1701)
OIIO's 2.3 family is obsolete and no longer updating, so we removed
the branch marker. (Branch markers should always indicate places where
development may happen.)

But we still reference that named branch in a couple places for OSL's CI,
so just replace it with the immutable tag of the last release in the 2.3
family.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-19 13:15:02 -07:00
Larry Gritz 4962ac2a1b fix: Avoid deprecated OSLQuery ctr in test example (#1699)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-14 17:47:12 -07:00
Chris Hellmuth 1956e83954 gpu: OptiX direct callable API that owns groupdata buffer (#1683)
On gpu, the renderer currently owns a shader's groupdata params buffer so that it can pass its pointer to both the init and entry functions.

The downside of this approach is that in order to avoid dynamic memory allocation, the renderer must commit to a buffer size at build time. Using a conservative size to accommodate potentially large shaders can lead to gigabytes of unnecessary memory footprint.

This patch adds a new OptiX direct callable alternative to the existing init and entry callables. This new function allocates a perfectly-sized groupdata params buffer, so that the gpu only pays for the memory it needs, and then it calls init and entry.

Particularly large shaders can require larger buffers than there is space on the cuda stack. To handle this case, there is a new option, "max_optix_groupdata_alloc". Any shader requiring a groupdata buffer larger than this value will not allocate its own buffer, and instead use the pointer passed in by the renderer (presumably coming from a global memory pool).

Signed-off-by: Chris Hellmuth <chellmuth@gmail.com>
2023-06-14 13:04:02 -07:00
Larry Gritz 50ccc8736f docs: Amend the filmography (#1695)
docs: Update the filmography

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-14 11:09:42 -07:00
Larry Gritz 6a5c50e3f3 build: Fix for Apple clang 14+ warnings (#1697)
build: Fix for Apple clang 14 warnings

Add a MacOS 13 test to the CI matrix.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-14 11:09:05 -07:00
Larry Gritz 49aac8740d fix: Have ReParameter only copy data when it changes (#1698)
For GPU in particular, this prevents needless transfers to the device
when no values actually change.

Also, keep track of some statistics about how much ReParameter is
being used. (Which also help to verify that this change works as
intended.)

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-14 11:08:22 -07:00
Larry Gritz c06df65331 ci: Add VFX Platform 2023 tests using new ASWF containers (#1696)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-13 14:59:15 -07:00
Alejandro Conty 4e9e640e5b fix: Don't try to ReParameter symbols not in the group (#1693)
Sometimes, after optimization, symbols tagged as interactive
get removed because they are unused. But ReParameter is failing
with errors because it goes looking for the removed symbol to
master, which is, of course, not interactive. This patch avoids
that so the symbol is not found and we just return false.

Signed-off-by: Alejandro Conty <aconty@imageworks.com>
2023-06-09 10:34:13 -07:00
Mitch Prater b76a53a779 docs: Fixed booboos from the previous README commit. (#1694)
Fixed booboos from the previous commit.
2023-06-09 08:58:41 -07:00
Mitch Prater 4e958e92c1 docs: README.md: added filmography and Siggraph OSL course info. (#1692)
Updated README.md to include LAIKA films and added Siggraph OSL course info to Documentation.
2023-06-06 16:38:08 -07:00
Larry Gritz 188ec977a5 build: Changes to support fmt 10.0 (#1691)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-01 18:25:53 -07:00
Larry Gritz 417088e91a docs: Update CONTRIBUTING (#1689)
Tighten up some of the explanations and update obsolete parts of the
CONTRIBUTING document.

This doesn't change any of our policies or procedures. But some advice
was out of date or no longer applicable (for example, now that we use
clang-format, we do not need to detail all the formatting rules, they
are enforced automatically).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-01 07:35:52 -07:00
Larry Gritz 16d217a21f ci: Fix package name for icc (#1690)
The Intel yum repo renamed this package a couple weeks ago, and it
broke our CI. Update to the new name.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-06-01 07:31:41 -07:00
Larry Gritz 6a2e2960ef admin: Fix incorrect links in CONTRIBUTING (#1688)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-05-25 16:53:37 -07:00
Chris Hellmuth 606beade27 testing: interactive parameter initialization in optix testrender (#1687)
This change updates testrender's optix implementation of reparameter,
and adds a new test.

Previously we were grabbing the pointers from incorrect SBT records, so
this moves them into a global lookup table.

Signed-off-by: Chris Hellmuth <chellmuth@gmail.com>
2023-05-25 16:41:48 -07:00
Larry Gritz 71a9310f0b feat(gpu)!: GPU/OptiX support of ReParameter (#1686)
BREAKING CHANGE: to RendererServices ABI (including for CPU) and to
the renderer-side setup when using OptiX.

This overhauls the implementation of how interactively-editable
parameters work, where they live in memory, and get it all working on
GPU/OptiX so that renderers can support interactive adjustment of
those params without recompiling shaders.

The basic gist is as follows:

* We continue work to finish making a clean separation between
  "interpolated" parameters and "interactive" (editable) parameters.

* Interpolated params are collected and put into a separate memory
  area -- a separate per-group allocation on both the CPU and GPU
  (where applicable). It needs to remember the offset into this arena
  where each of the interpolated parameters resides. These allocations
  and eventual release are taken care of by the OSL shading system,
  they live in the ShaderGroup. When the group is set up, this block
  of memory is initialized with the correct initial values of the
  params and are ready to go.

* The implementation of ReParameter writes to this special memory
  area also, that's how it works now (both CPU and GPU).

* How does the OSL library know how to allocate, free, and copy to the
  device memory? It doesn't! Instead, we add new RendererServices
  methods `device_alloc()`, `device_free()`, and
  `copy_to_device()`. It's up to the renderer to provide those, so
  that the OSL library doesn't itself need to know about the Cuda
  runtime. These are trivial, there's really only one implementation
  that makes sense, and you can copy it from the ones in testshade and
  testrender.

* Interactive parameters are NOT constant folded during runtime
  optimization.

* The shader entry points themselves now take an extra parameter in
  the main call -- this will be the pointer to the beginning of the
  shader group's interactive parameter arena.

* When JITing, references to interactive parameters know to retrieve
  them from their designated offset into the interactive parameter
  area.

* This means that the renderer-side OptiX/Cuda code is responsible for
  adding this extra pointer parameter to the call to the shader entry
  points. You can see how this is done in the testshade and testrender
  Cuda code.

* It's up to the renderer to figure out how to make the OptiX hit program
  aware of the interactive parameter pointer for that particular material,
  in order to pass it to the osl shader entry point. The way I did it in
  testshade and testrender is using a field in the struct that's given
  to each entry of the shader binding table and can be retrieved on the
  OptiX side via optixGetSbtDataPointer(). In testshade/testrender, a
  data pointer already existed which wasn't used. In a real renderer, you
  may need to add a field or come up with whatever other way you want
  to somehow get this pointer, which can be retrieved via

      shadingsys->getattribute(shadergroupptr, "device_interactive_params",
                               TypeDesc::PTR, &myptr);

  you can see how I do that in optixraytracer.cpp (testrender) and in
  optixgridrender.cpp (testshade).

A number of other things you will see that's worth calling out:

I added a device_ptr utility template that is just a wrapper around a
device side pointer that makes it hard to accidentally dereference it
on the host side.

Since I was changing RendererServices anyway, I also remove unused
register_global, fetch_global, global_map which were unused. They were
leftovers from the way we handled strings in OptiX 6.x.

Encapsulate cuda global symbol name mangling into
BackendLLVM::global_unique_symname(). I did this early on, turns out
it wasn't necessary, but I still like that encapsulation, so I'm
keeping it.

I bumped the 3rd set of digits in the version to reflect that the
changes in RendererServices break ABI. This is only in main, it
obviously cannot be backported to a release branch.

All tests pass for scalar and batch and optix.

I added a new simple reparam test, and renamed the old reparem to
reparam-array. Oddly, the reparam-array test doesn't work properly on
optix (it had never been tried before), but it also failed in optix at
main -- so it's not related to this patch! Putting that on my list of
other oddities to investigate later. It may just be a quirk of
testshade, I'm not really sure yet.

Added to BackendLLVM (and batched) a llvm_ptr_type(TypeSpec) method
that returns the LLVM type of a pointer to the specified type.

Note: This patch doesn't account for the face that a parameter marked
"interactive" could prevent a shader from correctly building for the GPU
because it used the kind of construct that is fine in shader source code but
only will work on GPU if it can be resolved to be a constant by the time
we get done with the runtime optimization (as pointed out by Stephen
Friedman. We'll come back to the problem later with a more robust and
automatic fix -- and if we are lucky, Stephen will have the opportunity to
upstream the approach he already has.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-05-23 13:25:28 -07:00
Pascal LecocqandPascal Lecocq 5c49a7c6b5 fix(optix): fix userdata derivatives for interpolated params on GPU (#1685)
Following #1657, it turns out we forgot to zero initialize the userdata derivatives for the optix path.
This leads to some rendering glitches caused by the memory garbage left in those derivatives.

Signed-off-by: Pascal Lecocq <pascal.lecocq@gmail.com>
Co-authored-by: Pascal Lecocq <plecocq@imageworks.com>
2023-05-20 11:25:03 -07:00
Larry Gritz abdc966a19 Give ShadingSystemImpl a handy use_optix() method (#1682)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-05-10 21:48:46 -07:00
Larry Gritz 374543f040 cleanup: switch deprecated oiio simd names to modern (#1679)
Oops, I noticed that OSL was still using deprecated OIIO::simd type
aliases (float4, int4, bool4) instead of the modern vfloat4, vint4,
vbool4.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-05-10 14:06:53 -07:00
Larry Gritz 089268b87d build(cmake): Fix incorrect variable name to control symbol visibility (#1681)
As Fabrice Macagno pointed out on the oiio-dev mail list, we weren't
setting the correct variable name CMAKE_CXX_VISIBILITY_PRESET.

And, oops, this also revealed that there were some things that needed
to be declared public that were not (because, specifically, they
needed to be called across library boundaries by the per-ISA dynamic
libraries used by batch shading!).

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-05-09 19:25:00 -07:00
Larry Gritz 74b2b30669 refactor: Get rid of needless error check (#1677)
This was apparently something I put in to track down a possible
llvm-side problem many years ago. I haven't seen the error message in
recent memory (and it was only enabled at SPI anway), so I guess it
was a red herring or has long since been fixed. Get this cruft out of
here.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-05-09 18:24:03 -07:00
Larry Gritz 91699ba7d3 docs: Update (and typo fixes) to project intake checklist (#1676)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-05-06 08:27:49 -07:00
Larry Gritz 4afe9244e8 Remove extra pdf file that should not have been checked in
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-05-02 18:35:18 -07:00
Larry Gritz ed9857c416 build: Change cmake option USE_OPTIX -> OSL_USE_OPTIX (#1668)
This avoids some possible confusion with other projects, or if this
is built as a subproject.

Also, change from the C++ side having an OSL_USE_OPTIX defined -- only
for building OSL itself -- to having it always defined in oslconfig.h
and set to 0 or 1 depending on whether OptiX support was turned on at
build time. This allows app-side use of OSL headers to know if it's
dealing with an OptiX-capable OSL build.

Clean up OSL_USE_OPTIX and OSL_USE_BATCHED symbol defs

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-05-02 18:02:59 -07:00
AidanWelch cd22f602a4 Docs: Improve documentation of trace function (#1671)
Improve the documentation of optional parameters of trace to more accurately describe behavior.

Signed-off-by: Aidan Welch <aidan@freedwave.com>
2023-05-02 15:09:39 -07:00
Declan Russell 17d211a3d3 Fix constant float values being converted to ints (#1674)
This issue was caused by 8c52d48 . The problem is that the constant float values are being turned into ints. The PR restores the previous behavior and preserves the float format.

Note from LG explaining:

When outputting the oso and using fmt library to write the value, {} (equivalent to {:g}) prints the "simplest" text representation that, when re-parsed as a float, will give you the SAME binary float value. So the "true" value of -9.99999996e+11 is printed as -1000000000000, which when reparsed will give you the closest float to that, which is the original value. (Remember that the value of -1e12 is not exactly representable as a float.)

But if both will parse to the same float, why does the shader print -2147483648.000000 instead of -999999995904.000000? That's the interesting part.

The answer, and the real core of the problem, is that when we parse the oso file it sees -1000000000000 and thinks it's an int, lexically. Now, once it gets to figuring out what to do with that, if the initial value of a float parameter looks like an int, it's still no problem, it will convert the int to the equivalent float.

Except that in this case, because the text that looked lexically like an int is out of range for a 32 bit int, it gets INT_MIN, so by the time it's converted back to float, it's -2147483648.000000

Your fix works (at least in this instance) because it forces the value to print in a way that lexically can only be a float and not an int.

Signed-off-by: Declan Russell <declan.russell@autodesk.com>
2023-05-02 10:46:28 -07:00
Declan Russell 20299563ee build: Fix builds when USE_PYTHON=OFF (#1675)
This issue was caused by 5efe15a. Essentially, we now use Python_EXECUTABLE to execute the serialize-bc.py script. Therefore, we have to run find_package(python) so that the Python_EXECUTABLE variable gets setup.

Signed-off-by: Declan Russell <declan.russell@autodesk.com>
2023-05-02 09:23:35 -07:00
Alejandro Conty 5600d020a0 Fix userdata binding corner case (#1673)
This includes two fixes:

 1) When registering symbols that need user data, sort the entries in
 the set so the layer number is ignored. A needed udata iteam shouldn't
 depend on the layer and separating them makes find_userdata_index()
 sometimes find an index with different derivs status.

 2) osl_bind_interpolated_param() is memcpy'ing derivs that might not
 be there, yielding corrupted derivs and possibly a crash.

Signed-off-by: Alejandro Conty <aconty@imageworks.com>
2023-04-24 10:59:10 -07:00
Chris Hellmuth 37f4bbc1a2 Make recent run-layer optimizations optional, and fix init ops-related false positive (#1672)
My initial implementation of the run layer check optimizations didn’t account for the fact that init ops for symbols have their llvm code generated before we build basic blocks from the OSL IR.

This caused the code to be wrong in two ways: 1) the set of known run layer calls was being reset between instances too late in the pipeline, so a useparam inside an init op would actually be checking the previously compiled layer’s set, and 2) even when reset earlier, it assumed valid basic block ids existed for the init ops when they did not.

So, if a layer had a useparam inside one of its init ops that generally matched the same code location as a useparam in the previously compiled layer, the run layer check could be incorrectly omitted.

I’ve updated the code so that the default optimization behavior is reverted to the way it was before #1665, and added a new option opt_useparam that can be turned on to enable a fixed, restricted version of the optimization that only applies to code in the main section.

I'm working on a test that properly triggers the issue.

Signed-off-by: Chris Hellmuth <chellmuth@gmail.com>
2023-04-20 10:37:46 -07:00
cmstein b13b7f08b0 fix for ReParameterization corner case (#1670)
Take into account whether a parameter can change due to interactivity
when comparing parameters for "mergeability".

This proposed patch fixes a corner case we were seeing during live rendering with ReParameterization.

We were experiencing a problem when ss->ReParameterize() wasn't successfully applying parameter changes for us.

In our situation, a shader's parameter, "A", was marked with lockgeom=0 (ie. "live" or "editable") and was set via ss->Parameter(). This parameter was connected (through a series of copies and network links) to another shader's parameter, "B", downstream whose initialized value (ie. the one specified in the .osl/.oso file) matched A's set value. When this happened, A's shading layer was getting marked as "mergeable" and deleted, and we wouldn't see any updates to A via "reparameterization" take effect.

Signed-off-by: Clifford Stein <cstein@imageworks.com>
2023-04-13 11:22:45 -07:00
Chris Hellmuth 7ebfbc4a05 Apply recent run layer call optimization to batched execution (#1669)
Copy-paste the run layer call checks from #1665 into the batched execution mode.

Signed-off-by: Chris Hellmuth <chellmuth@gmail.com>
2023-04-12 09:43:56 -07:00
Larry Gritz e402988611 Fix type ambiguity that was giving warnings (#1667)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-04-11 16:24:05 -07:00
Larry Gritz 88be276ec1 Clean up OptiX comments (#1666)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-04-11 16:14:51 -07:00
Curtis Black 6f1fedb08d Add type information for needed attributes. (#1650)
We can currently query which attribute names and scopes are requested in a shader. This PR extends that idea to also allow querying the attribute types. This now more closely matches the equivalent available queries for user data.

For example, this shader:

```
shader Shader
{
  color c;
  getattribute("user_color", c);
  
  string s;
  getattribute("user_string", s);
}
```

allows us to do this:

```
int nattr = 0;
if (shadingSys->getattribute(shaderRef.get(), "num_attributes_needed", nattr) && nattr)
{
  // this already works
  OIIO::ustring* names = nullptr;
  shadingSys->getattribute(shaderRef.get(), "attributes_needed", OSL::TypeDesc::PTR, &names);
  
  // this is the added feature
  OIIO::TypeDesc* types = nullptr;
  shadingSys->getattribute(shaderRef.get(), "attribute_types", OSL::TypeDesc::PTR, &types);
  
  // nattr: 2
  // names: ["user_color", "user_string"]
  // types: [OIIO::TypeColor, OIIO::TypeString]
}
```

The motivation behind this feature is to perform additional type validation at material compile time when determining what primvars can be provided to the shader.

One side-effect of this change to be aware of is that, as mentioned in the code comments, if the same name is requested multiple times with different types, it will now be reported multiple times. Hopefully this is not too much of an issue as the same behaviour also occurs when an attribute is requested in multiple scopes, or when user data is requested with multiple types.

Signed-off-by: Curtis Black <curtis.w.black@gmail.com>
2023-04-10 18:38:59 -07:00
Larry Gritz 0bd014cfe2 Switch lockgeom to interpolated and interactive (#1662)
* Switch lockgeom to interpolated and interactive

Establish two new metadata hints about shader parameters:

  - "interpolated" means that the parameter comes from the geometry
    somehow and may be bound with a different value at different
    points on the surfaces, or different values for different
    primitives that share the material. This corresponds to concepts
    known variously as "geometric primitive data/variables", "user
    data", or "vertex variables", depending on the renderer.

  - "interactive" means that the user desires the parameter to be
    allowed to change when the scene is interactively rerendered,
    without incurring a full recompile of the shader. (Variables not
    so marked might still be capable of being changed, but not
    necessarily without a re-JIT of the shaders.)

Both of these require that the parameter not be fully constant-folded
or optimized away during runtime optimizeation or JIT, and thus
supplant the old "lockgeom=0" hint. But their semantics may differ in
other ways, so we thought it was worth introducing a separation, and
at the same time, finally fixing the mis-design of "lockgeom" (which
in retrospect is both a confusing name and also has the 0|1 sense
backwards, thwarting even my own intuition every time I use it).

We introduce new variants of `ShadingSystem::Parameter()` that changes
the optional `bool lockgeom` parameter for a new enum `ParamHints`
that allows for future expansion with more hinted properties.  For
now, the old calls still work (lockgeom=false is the same as passing
ParamHints::interpolated) and this does not introduce any break to
backwards ABI compatibility at this time.

In this PR, "interpolated" is basically the replacement for the old
lockgeom (though the sense is reversed). The "interactive" hint is put
in place but doesn't do anything especially useful at the moment that
is different from interpolated.  A few more things are coming down the
pike in subsequent PRs: (1) Make interactive work and fully hook it up
to ReParameter(), including on GPU. (2) Make a new global SS option
that says if you're building shaders for an interactive render or an
offline render. (If offline, the even "interactive" hinted params
should be constant-folded.)

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-04-08 15:34:26 -07:00
Chris Hellmuth 209c672b0b Don't insert redundant run layer calls inside a basic block (#1665)
This patch is a very simple part one of work to optimize the number of conditional run layer calls that OSL makes, which take the form:

    if (!groupdata->run[parentlayer])
        parent_layer([...]);

After examining our slowest JIT’ing shaders on gpu, @tgrant-nv showed us that these run layer calls were significantly bloating our ptx and slowing down their compilation. Many of them are unnecessary because static analysis can show we are guaranteed to have already run the layer in question.

For example, reading different fields from a connected struct like below will often generate multiple conditional run layer calls:

```
struct Pair {
    float x;
    float y;
};

shader example_shader(Pair p = {})
{
    if ([…]) {
        float xx = p.x;
        float yy = p.y;
        […]
    }
}
```

Since this is not really a performance issue on cpu (runtime overhead is just checking the conditional bit), OSL doesn’t make a huge effort to optimize away these redundant cases. Each useparam op will be careful not to insert more than one per layer, and code that is called unconditionally in the main section of the shader will also not have redundant checks, but there are plenty of examples like above that are not currently removed.

This patch takes a basic first step, adding metrics to track run layer call counts and removing duplicate run layer calls inside a basic block, covering cases like the example above.

On my set of production test scenes, this alone removes anywhere from 20-50% of total run layer calls, with our biggest shaders seeing the most improvement. Total ptx line reduction varies between 3-20%, and optix module compilation (jit time) is reduced between 1-15%.

Signed-off-by: Chris Hellmuth <chellmuth@gmail.com>
2023-04-08 11:28:31 -07:00
Larry Gritz 49cda0a472 Build: verify that OSL can build with clang16 (#1664)
But note: OSL does not yet work with LLVM 16.

Because homebrew recently upgraded its default llvm to 16.0, there may
be users for whom builds now break. The solution is:

    brew install llvm@14
    cmake ... -DLLVM_ROOT=/usr/local/opt/llvm@14

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-04-05 09:00:48 -07:00
Larry Gritz 787d8ce94e ci: Bump 'latest dependencies' tests to OpenEXR 3.1.7 (#1663)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-03-31 23:46:34 -07:00
Larry Gritz 89f1e69d88 Fix warnings about Qt compilation and enums (#1661)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-03-31 11:29:14 -07:00
Massimo Paladin fff0c5985d Remove SonarCloud cache setup as it is now offered by default (#1660)
Signed-off-by: Massimo Paladin <massimo.paladin@gmail.com>

No need to configure the cache anymore, SonarCloud now has an automatic analysis caching.
See https://docs.sonarcloud.io/advanced-setup/languages/c-c-objective-c/#analysis-cache.
2023-03-27 16:06:28 -07:00
Larry Gritz a047c065b7 Build: Fix cuda compilation flags for LLVM 15 (#1659)
For LLVM 15+, we need to disable opaque pointers. We did this for
regular bitcode generation in llvm_macros.cmake, but neglected to make
the corresponding change for copmiling to ptx in cuda_macros.cmake.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-03-27 11:22:27 -07:00
Larry Gritz bc735d02cf build: proper warnings about LLVM 16 (#1658)
LLVM 16 was just released. I'm pretty sure we won't build properly
against it because of the phase-out of typed pointers in LLVM IR, so
warn prominently so that anybody building against it who has problems
will know why.

Also, LLVM itself has bumped their toolchain requirements with the
release of 16. Technically, I'm not sure if that extends to projects
using the LLVM APIs, but warn anyway and hope for the best. If it
fails, at least the warning will supply an explanation.

At a later time, we'll need to upgrade the code on our side to have the
option of using opaque pointers so we can run with LLVM 16+.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-03-22 00:03:32 -07:00
Chris Hellmuth f64f6effc0 Enable userdata derivatives for interpolated params on GPU (#1657)
When generating calls to osl_bind_interpolated_param in llvm_instance.cpp, the userdata_has_derivs field is set to true if the parameter's derivatives are needed, but the code does not take into account that on gpu there is no space allocated for these derivatives.

This leads to an incorrect derivatives pointer getting passed into the renderer, which the renderer will use to write into unrelated groupdata fields.

For our renders, getting the correct image was worth the 1-2% inflation of groupdata struct size that we observed by simply re-enabling gpu userdata derivatives. If desired, adding an option to turn them on/off is straightforward, but I didn't want to preemptively bloat the code if it's not necessary.

Signed-off-by: Chris Hellmuth <chellmuth@gmail.com>
2023-03-22 00:02:38 -07:00
Larry Gritz a620231929 Qt6 compatibility (#1655)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-03-18 10:23:29 -07:00
Larry Gritz df818a7045 Be more careful about paths to look for llvm (#1656)
In particular, `${LLVM_ROOT}/bin` will end up being (incorrectly!)
`/bin` if LLVM_ROOT is empty. That is bad if some other llvm-config
happens to be in /bin.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-03-18 10:23:03 -07:00
Larry Gritz bee79468e0 oslc: simple constant folding of binary expressions on the oslc side (#1653)
The runtime optimization does a great job of constant folding, and
we'd pushed it there because, with instance parameter values and
shader network connections known, it can find so much more opportunity
to optimize than we could in oslc.

However, there is one pesky problem, which is that shader parameters
that are initialized to even simple expressions such as 3+1 end up
with "init ops", which although later constant folded by the time the
shader is JITed, make it impossible to know the value via OSLQuery.

So this patch just takes the simplest cases -- certain `int OP int`
and `float OP float` expressions involving literal constants, and
performs the operation as it's parsing the code. So

         int val = 3 + 1;

actually just immediately is turned into `val = 4` instead of making
an "add".

To reiterate, the add would never have happened while executing the
shader -- at runtime in the renderer, when it's time to optimize and
JIT the shader, it would know it's a constant 4 value. This is
strictly about making oslc directly output an .oso file that knows
that parameter `val` has default value 4 instead of throwing up its
hands and saying "it's math code that will be evaluated later."

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-03-15 11:57:25 -07:00
Larry Gritz f8ad0281aa Make compile_report attribute an int instead of just 0/1 (#1654)
In particular, 1 prints a short version of the compile report (just
the fact that it happened and the time), >1 prints more verbose info.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-03-15 11:56:45 -07:00
Larry Gritz b9cb0ae74c ci: update runners (#1651)
* Stop using the deprecated, soon to be removed, ubuntu-18.04 runners
  and switch to 20.04.
* Bump the "latest" test openexr to 3.1.6
* Update INSTALL.md to document some things we're already testing and
  are known to work.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-03-13 15:38:22 -07:00
Larry Gritz 5879868561 Fix missing // clang-format on in oslc.c (#1652)
We had turned it off in one function to preserve formatting, but
failed to turn it on at the end of the function. This led to several
small functions not being clang-formatted, now fixed.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-03-13 11:15:52 -07:00
Larry Gritz c5fe678c9e Update ref images from 1649
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-03-01 00:52:18 -08:00
Christopher Kulla dbe8c214e4 testrender: Don't use the cached background map on the first bounce (#1649)
* testrender: Don't use the cached background map on the first bounce (camera ray)

* testrender: Change the default resolution of the background so that importance sampling is enabled by default

Signed-off-by: Chris Kulla <ckulla@gmail.com>
2023-03-01 00:36:47 -08:00
Larry Gritz fbe141b42b fix: add missing fmod variants (#1643)
Apparently some varieties of fmod(triple,float) -- which were not
documented in the spec but were intended to work and did allow that
combination in oslc -- were not fully implemented in the runtime.

* Add all these tests to the arithmetic-reg test, to fully test all
  possible argument type and unif/vary/const combinations once and for
  all for fmod. Also add some more rudimentary testing to miscmath.

* Implement the missing bits and/or avoid the code paths that rely
  on the unimplemented parts.

The implementation of fmod for funny -- both for batch and non-batch,
it's got one code path that just directly generates code and doesn't
need any functional implementation in llvm_ops at all, and a second
code path that uses the functional implementations to work around
(different, in each case!) what appears to be bugs or limitations in
long-ago LLVM versions we don't need any more.  I'm trying to assess
whether those are still needed at all in the oldest versions of LLVM
we are using, and if not, I may amend even more simplification to this
whole thing.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-02-27 16:33:09 -08:00
Larry Gritz a68a972602 Set up ray types for testrender (#1648)
Try to set ray types correctly for rays -- a little naive now, only
using "camera", "shadow", and "diffuse" for all rays (leave
distinguishing between reflection, refraction, diffuse, glossy for
another day, and currently testrender doesn't support subsurface or
displacement, but maybe someday).

Also, for testshade, improve efficency -- don't decode raytype on
every point.  For each individual shade, testshade was converting the
name of the raytype from a string to a ustring, then decoding to a
bitfield. Pull it all out of the loops by computing the bitfield once.

Adjust glass shaders to not change behavior based on raytype:
The code path that was supposed to suppress noisy caustic rays never
worked properly before because we never set the ray type in
testrender. Now that testrender sets it -- but does not distinguish
between the different types of secondary rays -- the code path is
active, but incorrect, and causes tests to fail. Just remove the
offending clause for now and return to the old behavior of the shader
(no attempt to eliminate caustic rays). Later, we should revamp the
glass shader entirely by switching to the newer MaterialX-inspired
closures.

Note: when you specify a resolution in the Background command in our 
scene xml, it will  run the shader out of any ray context at all (therefore
having no raytype) in order to populate an environment map that will be
used as needed. If you omit the resolution, no importance sampling is
used at all, so it's much noisier. I think the right approach is to do both --
populate the map for importance sampling, but run the shader on the rays
themselves to get higher quality visible results.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-02-27 14:41:00 -08:00
Larry Gritz 23edc185a0 Fix mismatched strides when calling OCIO for transformc with derivs (#1646)
We were getting an exception thrown on the OCIO side, because we were
passing 0 for the y stride (which, us humans know, should have been fine
since there was only one row, so the stride shouldn't have mattered).
Now pass the right stride even though we don't need to step from row
to row.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-02-20 13:40:44 -08:00
Larry Gritz 203dcecafe ci: Fix broken Mac CI (#1647)
Make sure LLVM_ROOT/bin (either as a cmake var or as an env var) end
up in the hints list when searching for llvm-config.

Without this, one of our Mac CI jobs was ending up with clang 14 and
llvm 15, and that was causing problems. The particular test was
supposed to be using 14 for both.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-02-17 23:35:45 -08:00
Larry Gritz bbbc28d2ff docs: Update credits
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-02-17 23:04:33 -08:00
Larry Gritz 649f0b86a3 Typo in test shaders (#1644)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-02-08 18:21:39 -08:00
Larry Gritz 31e92ddc06 RendererServices API for letting get_texture_handle consider colorspace (#1641)
This makes some minor changes to the RS APIs to add an additional
optional parameter to get_texture_handle so it takes a `TextureOpt*`
to accommodate a similar change on the OIIO TextureSystem side
from https://github.com/OpenImageIO/oiio/pull/3761

The purpose here is to add color management options to texture calls.
However, please note that this PR only reserves a public API change we
know we'll want, but it does not fully implement the color management.
Further work will be needed, as follows:

* Current calls to RS::get_texture_handle should be updated to pass
  the TextureOpt*. (This is a formality for future-proofing in case
  future TS or alternate TS implementations want to bake the color
  space choice into the texture handle itself. But the OIIO change
  doesn't currently rely on that at the moment.)

* When the texture.h symbol `OIIO_TEXTURESYSTEM_SUPPORTS_COLORSPACE`
  exists, we are building against an OIIO that has the new int field
  `colortransformid` in the TextureOpt and TextureOptBatch structures.
  We should fill this in with a nonzero value when we want the texture
  call to be doing a color transformation as it reads texture tiles.

* Use the new TextureSystem:get_colortransform_id() to get that color
  transform ID given two named from/to color spaces. We agreed that
  it's a reasonable restriction that the color space names should be
  known by the end of runtime optimization, so that should be constant
  foldable.

* Recognize new optional argument(s) to the texture() call family that
  lets the caller specify the presumed color space of the texture,
  and use that value (with constant folded lookup of the ID, above)
  to set the value in the TextureOpt.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-02-04 14:49:48 -08:00
Chris Hellmuth 9ae5b69fd8 Expose llvm groupdata size as a shadergroup attribute (#1642)
Signed-off-by: Chris Hellmuth <chellmuth@gmail.com>
2023-02-04 14:48:59 -08:00
Declan Russell 3bd3778610 Fix some windows GPU build errors (#1638)
Signed-off-by: Declan Russell <declan.russell@autodesk.com>
2023-01-30 08:56:50 -08:00
pellerington a8d3ac06e6 Changed snprintf formatting to satisfy some compilers. (#1640)
Signed-off-by: Peter Ellerington <elleringtonp@gmail.com>
2023-01-27 15:58:39 -08:00
cmstein c0a5998c19 adding relaxed type-equivalency to ReParameter() (#1639)
Signed-off-by: Clifford Stein <cstein@imageworks.com>
2023-01-25 14:27:24 -08:00
danieldresser-ie 5dad5076bc Fix bug with masked wide llvm_gen_closure() (#1637)
Signed-off-by: Daniel Dresser <danield@image-engine.com>
2023-01-25 11:47:10 -08:00
Larry Gritz 317c59ed73 Fix doc typo
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-01-25 09:58:08 -08:00
Larry Gritz 66c9b61d72 platform.h: fully define bitcast template (#1635)
Ported from OIIO. This lets us not have to depend on the specific
definition in OIIO's fmath.h, and in particular not worry about
whether it's a new enough version of OIIO that the old bit_cast is now
marked as deprecated.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-01-12 22:48:55 -08:00
Larry Gritz 8036e174fb Bump version after developer preview tag
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-01-12 15:18:10 -08:00
danieldresser-ie b064b25721 Remove unnecessary setting of locale::global (#1636)
Signed-off-by: Daniel Dresser <danield@image-engine.com>
2023-01-12 15:14:14 -08:00
Larry Gritz 8d1d9f0cf6 CHANGES
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-01-03 17:02:40 -08:00
Larry Gritz 1c196d935c Temp workaround for botched aswftesting container yum (#1633)
It seems something in the latest builds of the aswftesting/ci-osl:2022
containers has changed, and explicitly running /usr/bin/yum (instead of
the broken /usr/local/bin/yum) fixes it for now. This was completely
breaking the icc & icx tests, which require yum to install the Intel
compilers.

Also, bump up to the -clang14 containers for those tests, just to
get to a more recent LLVM.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2023-01-02 17:08:20 -08:00
Larry Gritz a878883eeb CI: Fix build break by adjusting fmt version (#1631)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-12-20 12:28:50 -08:00
Alex Wells 1b3c96603c Fix batched support for closures with array types (#1630)
Fixed batched support for closures with array types.
Enabled testsuite/userdata-custom/BATCHED (follow up to PR1620/PR1621).

Added modified version of PR1625 (Fix Issues with Derivative of getattribute) from danieldresser-ie
changing default behavior of MaskedData<DataT>::assign_all_from_scalar(const void *) to zero out Dx Dy when DataT has derviatives.
Added testsuite/userdata-custom
Fixed bug in testshades handling of userdata with derivatives.

Added bool LLVM_Util::is_type_array(llvm::Type* type)
      llvm::Type* LLVM_Util::element_type_of(llvm::Type* array_type)

Fixed icx compiler warning with src/liboslexec/osogram.y
Fixed unreferenced function warning in src/testrender/shading.cpp

Signed-off-by: Alex M. Wells <alex.m.wells@intel.com>
2022-12-17 12:13:52 -08:00
Larry Gritz e468ef7595 CI: Fix Mac CI breakage (#1629)
To save build time, we had OSL's Mac CI tests use the homebrew
installation of openimageio. But... Homebrew recently switched its
default python to 3.11, which didn't match the versions we're testing
OSL against here and broke the python bindings, so need to make a few
adjustments.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-12-16 13:39:32 -08:00
Patrick Mours fae61e699f Remove dependency on OptiX SDK for building core OSL with OptiX support (#1627)
Signed-off-by: Patrick Mours <pmours@nvidia.com>
2022-12-16 12:20:24 -08:00
Larry Gritz 7b6854823d CMake: Adjust how version overrides work (#1617)
Related to https://github.com/OpenImageIO/oiio/pull/3653

Kai Pastor (dg0yt) points out that the recent change I made both in
OIIO and OSL to make the version a cache variable has some unexpected
side effects that can lead to unexpeted behavior by inadvertently
retaining a version number upon recompiles if the cache itself was not
cleared, and this can happen unexpectedly even when the user isn't
trying to override the version.

This patch changes the behavior as follows:

You must use the special `-DOSL_VERSION_OVERRIDE=...` to override the
version.

  * if you do so, you are playing with fire and get what you deserve
    if you misuse it or change branches and don't remember to clear
    the cache.

If you do a normal build (without trying to override the version),

  * you will get the real version number because it IS NOT cached
  * if you switch branches, you'll always get the right version number
  * ...but switching branches without clearing the cache can still, as
    always, have other subtle behavior differences versus doing a
    truly fresh build from scratch.

So in short, it still allows a way to override the version if you
really want to, but if you are not trying to do that, you can no
longer get yourself inadvertently into unexpected trouble.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-12-03 11:10:30 -08:00
danieldresser-ie f84126fb3e Fix Batched Mode Crash When Adding A Default Initialized Closure (#1624)
This is another fix I'm attempting without really understanding all this LLVM stuff.

I started by adding a simple test case that attempts to add two closure parameters, where one has not been set.  This crashes or returns random values from uninitialized memory, matching a problem I ran into while trying to get batched mode working in Gaffer.

I investigated some, and found that add_closure_closure is assuming closure pointers are stored with the width of the current batch, but build_llvm_init is creating uniform closures.  I checked with @sfriedmapixar, who confirmed that all the batched closure code is assuming wide closures, so it seems build_llvm_init is what needs fixing.

Adding a `sym.make_varying();` to build_llvm_init appears to fix the problem ... I really don't know enough about the overall structure to know if this is the right place to make this fix, or if it could have other consequences, but it's enough to get this test passing, so hopefully someone who does know the background can review it.

Signed-off-by: Daniel Dresser <danield@image-engine.com>
2022-11-30 16:32:25 -08:00
Larry Gritz 395e58d6bf CI: No longer add the ppa:ubuntu-toolchain-r/test repository (#1618)
Lately, it has been experiencing intermittent availability problems
that causes our CI to fail while setting up dependencies.

What happens if we don't use the problematic ubuntu-toolchain-r at all?

Nothing, it seems. So eliminate it.

I think that once upon a time, it was necessary to add this repo to
get certain new packages? But maybe they are mainstream enough now
that it's not necessary to add this repo? In any case, it doesn't seem
to hurt anything, it's one less moving part that can't fail if it's
not there.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-11-29 16:23:31 -08:00
danieldresser-ie 75401bda4c Add new testshade closure to allow testing all parameter types (#1621)
Signed-off-by: Daniel Dresser <danield@image-engine.com>
2022-11-23 13:44:26 -08:00
danieldresser-ie 8530aa059a Fix issue with closure keyparams batched (#1619) (#1620)
When evaluating varying closure keyword parameters in batched execution,
the value of the first lane in the batch would be used for the whole
batch.

Signed-off-by: Daniel Dresser <danield@image-engine.com>
2022-11-23 09:08:06 -08:00
Larry Gritz bd7fd4cf8c Checkpoint to phase 2 of the great ustringhash conversion (#1612)
Reminder: phase 1 changed the RendererServices APIs to be based
completely on ustringhash for public method calls, not ustring.

This PR starts along the path of phase 2.

In oslconfig.h, I define a new type `ustringrep` which is the
in-memory/in-shader CPU-side representation of a ustring. Currently,
it's still equivalent to a ustring.

I also define a type called `ustring_pod`, which is the "plain old
data" representation inside a ustringrep (i.e., a const char* when
it's a ustring, and a uint64_t when it's a ustringhash). For reasons
not important, it's exceedingly hard to pass a true
ustring/ustringhash as parameters to or from LLVM-jitted code without
running afoul of LLVM's type checking, so it's just easier to pass the
underlying data type.

So the main work of phase 2 is to change everything related to shader
data from a ustring into a ustringrep, and things passed as const
char* into passing a ustring_pod. In some sense, it's just renaming
and type conversion plumbing.  When that's done, phase 3 is to throw
the switch and change the definition of ustringrep to ustringhash (and
of course fix everything that's broken).

This PR does not complete phase 2, but takes a big bite out of it.
It's an arbitrary bite, not much rhyme or reason to which specific
parts I did so far. Just working on it piece by piece and felt that
this was a place where much has been done, everything still works, and
it's a reviewable chunk without getting too much out of control.

Areas I worked on are related to range_check, raytype, getattribute,
bind_interpolated_param, uninit_check, range_check, naninf_check,
getmessage/setmessage, some texture setup, pointcloud.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-11-04 14:42:03 -07:00
Larry Gritz 61ea4c9a31 CI: Test against OpenColorIO 2.2 (#1616)
Also fix ocio brew install on Mac

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-11-04 00:49:59 -07:00
Larry Gritz afec48ebde CI: Adjust when jobs are run to cut needless CI (#1615)
Changes:
* Scorecards and analysis -- allow new to cancel running old
* Scorecard only runs on main repo, no need to run on forks
* Nightly CI only runs on main repo, no need to run on forks

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-11-03 23:11:03 -07:00
Dieter De Baets 9ef1741056 Add clangSupport as dependency to fix linker error (#1613)
Signed-off-by: Dieter De Baets <dieter.baets@unity3d.com>
2022-11-02 08:29:43 -07:00
Larry Gritz 1e8ef316ac Try to have more optix-only parts hidden behind OSL_USE_OPTIX (#1608)
This seems to have shifted just enough things around to make
clang-format want to re-jigger a few things.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-23 19:18:38 -07:00
Larry Gritz aafb5cb74e Testing: run pointcloud tests when partio is found (#1611)
Wow, this has been lurking for a while. Our Findpartio.cmake tries
looking for a partio exported config, but if not found, falls back
to a simple code to find it manually.

All was fine with the fallback code, which if found would set both
"partio_FOUND" and "PARTIO_FOUND". But the config file, if found --
only for the newer partio versions -- only set partio_FOUND. And in
that circumstance, we were not seting up the pointcloud tests!

Although the partio tests were running in CI (thankfully), I was not
running them locally on my machine with a new-ish partio.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-20 08:43:27 -07:00
Damien Courtois d0e49675e5 fixed broken links to Isotropix products (#1598)
Signed-off-by: Damien Courtois <dcourtois@isotropix.com>
2022-10-19 09:16:34 -07:00
Larry Gritz dde0a3451a OSL::bitcast utility (#1610)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-19 08:08:52 -07:00
Chris Hellmuth 3187864f9b Fix ptx symbol visibility regression (#1609)
* Address -Winconsistent-missing-override clang warning

* Fix ptx definitions of OSL_CONSTANT_DATA arrays

LLVM 14 introduced two ptx regressions to our file-scoped static variables:
1) They gained the .visible directive
2) They stopped being optimized out when unused

This lead to duplicate symbol errors when building an OptiX pipeline with
multiple shaders.

We attempted a fix using anonymous namespaces in #1561, but kept the static
keyword, resulting in a partial solution.

Removing static generates ptx that matches LLVM 12 for the affected variable
definitions.

Signed-off-by: Chris Hellmuth <chellmuth@gmail.com>
2022-10-17 16:23:28 -07:00
Larry Gritz 66747ac1e6 Move string representation entirely to ustringhash -- phase I (#1603)
The first step of the great ustringhash conversion: This changes all
RendererServices methods (i.e., callbacks to the renderer from the
shader JITed code) that used to take ustring parameters, switched to
take ustringhash instead.

The second step -- which I will tackle after this part is merged --
will be to fully switch the in-memory representation of strings during
shading execution to ustringhash on the CPU (thus matching how we've
been doing it on GPU and making a number of data stuctures and
representations identical/shared for CPU and GPU).

But in the mean time, this lets renderers get started changing their
RendererServices specializations. Just like with OSL's internal
implementation, it may be easier for renderers to break the job into
phase I (rendererservices) and phase II (in-memory rep).

Some notes and guideposts:

* In oslconfig.h, define ustringrep to alias to either ustring or
  ustringhash, depending on a new (but temporary) CMake variable
  `OSL_USTRINGREP_IS_HASH`, which is OFF for now, meaning that
  ustringrep is still ustring.

* Also in oslconfig.h, several helper conversion functions among
  ustring, ustringhash, ustringrip.

* RendererServices and BatchedRendererServices (and their various
  subclasses in testshade and testrender): change the method
  signatures from ustring to ustringhash for all methods that are
  reachable from shader code.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-11 15:54:23 -07:00
Larry Gritz d867d98a50 Improve testing coverage (#1607)
Looking at the code coverage report and trying to get a higher
coverage amount, employing two strategies: (a) remove unused code
that is not covered because it's... unused; and (b) test things
that are used but aren't in the test run. Details follow.

Remove deprecated version of LLVM_Util::make_function.

Disable contents of dump_struct_data_layout when OSL_DEV is not
defined, it will never be called in any other circumstances -- it's
strictly a debugging tool, not part of the shipping library.

When OSL_USE_OPTIX is not enabled, exclude compiling contents of
ptx_compile_group.

get_alignment can also be OSL_DEV only as well as simplified

Arbitrarily pick a couple of render tests to use llvm_opt levels 12
and 13 to verify that they work correctly. (That's a couple hundred
lines of pass setup code that wouldn't otherwise be included in the
coverage analysis, nor tested in the testsuite.) This also required us
to add the --llvm_opt command to testrender, as it is in testshade.

Make the analysis run build for avx512 as well for more code coverage.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-11 14:46:55 -07:00
490 changed files with 24549 additions and 5124 deletions
-1
View File
@@ -4,7 +4,6 @@
Language: Cpp
BasedOnStyle: WebKit
SpaceBeforeParens: ControlStatements
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
+4
View File
@@ -43,3 +43,7 @@ c1045f2c2845a98e661c7181932a031eb3c76063
# clang-format: the very last piece of the puzzle (#1555)
4ee62cd2ef05543f818f4d95a19efc1d684a7381
5be7c6bd4e7bd2e560cb6be8c06f11985384a87a
# Raise CI formatting standard to clang-format 17
a9ce35135e6c022d538a4a184fee1b5ce908aed8
90d94caecbb97141c9df63abc634be6e8394b6c3
+4 -3
View File
@@ -15,8 +15,9 @@
<!-- Put an 'x' in the boxes as you complete the checklist items -->
- [ ] I have read the [contribution guidelines](../CONTRIBUTING.md).
- [ ] I have previously submitted a [Contributor License Agreement](http://opensource.imageworks.com/cla/).
- [ ] I have updated the documentation, if applicable.
- [ ] I have ensured that the change is tested somewhere in the testsuite (adding new test cases if necessary).
- [ ] My code follows the prevailing code style of this project.
- [ ] My code follows the prevailing code style of this project. If I haven't
already run clang-format v17 before submitting, I definitely will look at
the CI test that runs clang-format and fix anything that it highlights as
being nonconforming.
+12 -3
View File
@@ -1,4 +1,4 @@
# Copyright 2008-present Contributors to the Open Shading Language project.
# Copyright Contributors to the Open Shading Language project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
@@ -14,11 +14,20 @@ on:
branches:
- main
- '*analysis*'
paths-ignore:
- '**.md'
- '**.rst'
- '**.tex'
# Allow manual kicking off of the workflow from github.com
workflow_dispatch:
permissions: read-all
# Allow subsequent pushes to the same PR or REF to cancel any previous jobs.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
@@ -30,7 +39,7 @@ jobs:
fail-fast: false
matrix:
include:
- desc: sonary gcc9/C++14 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
- desc: sonar gcc9/C++14 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
nametag: static-analysis-sonar
os: ubuntu-latest
vfxyear: 2022
@@ -40,7 +49,7 @@ jobs:
python_ver: 3.9
pybind11_ver: v2.9.0
simd: avx2,f16c
batched: b8_AVX2
batched: b8_AVX2,b16_AVX512
coverage: 1
# skip_tests: 1
sonar: 1
+176 -99
View File
@@ -20,8 +20,10 @@ on:
- '**.rst'
- '**.tex'
schedule:
# Full nightly build
# Full nightly build, for the main project repo (not for forks)
- cron: "0 6 * * *"
if: github.repository == 'AcademySoftwareFoundation/OpenShadingLanguage'
permissions: read-all
@@ -34,65 +36,58 @@ jobs:
fail-fast: false
matrix:
include:
- desc: gcc6/C++14 llvm9 py2.7 boost1.66 exr2.3 oiio2.2 sse2
nametag: linux-vfx2019
os: ubuntu-latest
- desc: gcc6/C++14 llvm9 py2.7 boost1.66 exr2.4 oiio2.3 sse2
nametag: linux-vfx2020
runner: ubuntu-latest
container: aswftesting/ci-osl:2019-clang9
vfxyear: 2019
vfxsuffix: -clang9
cxx_std: 14
openimageio_ver: v2.3.17.0
openexr_ver: v2.4.3
openimageio_ver: v2.4.13.0
python_ver: 2.7
pybind11_ver: v2.4.2
- desc: clang9/C++14 llvm9 oiio-release boost1.66 avx2 exr2.3 py2.7
setenvs: export CMAKE_VERSION=3.15.5
- desc: clang9/C++14 llvm9 oiio-release boost1.66 avx2 exr2.4 py2.7
nametag: linux-clang9-llvm9
os: ubuntu-18.04
runner: ubuntu-20.04
container: aswftesting/ci-osl:2019-clang9
vfxyear: 2019
vfxsuffix: -clang9
cc_compiler: clang
cxx_compiler: clang++
cxx_std: 14
openexr_ver: v2.4.3
openimageio_ver: release
python_ver: 2.7
# pybind11_ver: v2.9.0
simd: avx
- desc: GPU Cuda10 gcc6/C++14 llvm10 py2.7 boost-1.70 exr-2.3 OIIO-master avx2
nametag: linux-optix7-2019
os: ubuntu-latest
vfxyear: 2019
vfxsuffix: -clang10
cxx_std: 14
openimageio_ver: master
python_ver: 2.7
# pybind11_ver: v2.9.0
simd: avx2,f16c
skip_tests: 1
setenvs: export OSL_CMAKE_FLAGS="-DUSE_OPTIX=1" OPTIX_VERSION=7.0
setenvs: export CMAKE_VERSION=3.15.5
- desc: gcc6/C++14 llvm10 py3.7 boost1.70 exr2.4 oiio2.2 sse4
nametag: linux-vfx2020
os: ubuntu-latest
runner: ubuntu-latest
container: aswftesting/ci-osl:2020
vfxyear: 2020
cxx_std: 14
openimageio_ver: v2.3.17.0
openimageio_ver: v2.4.13.0
python_ver: 3.7
pybind11_ver: v2.5.0
simd: sse4.2
setenvs: export CONAN_LLVM_VERSION=10.0.1
- desc: gcc9/C++17 llvm11 py3.7 boost1.73 exr2.5 oiio2.2 avx2 batch-b8avx2
- desc: gcc9/C++17 llvm11 py3.7 boost1.73 exr2.5 oiio2.3 avx2 batch-b8avx2
nametag: linux-vfx2021
os: ubuntu-latest
runner: ubuntu-latest
container: aswftesting/ci-osl:2021-clang11
vfxyear: 2021
vfxsuffix: -clang11
cxx_std: 17
openimageio_ver: dev-2.3
openimageio_ver: v2.4.13.0
python_ver: 3.7
pybind11_ver: v2.7.0
simd: avx2,f16c
batched: b8_AVX2_noFMA
- desc: gcc9/C++17 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
- desc: gcc9/C++17 llvm13 py3.9 boost1.76 exr3.1 oiio-rel avx2
nametag: linux-vfx2022
os: ubuntu-latest
runner: ubuntu-latest
container: aswftesting/ci-osl:2022-clang13
vfxyear: 2022
vfxsuffix: -clang13
cxx_std: 17
openimageio_ver: release
python_ver: 3.9
@@ -101,9 +96,9 @@ jobs:
batched: b8_AVX2
- desc: clang12/C++17 llvm12 oiio-master boost1.73 exr3.1 py3.9 avx2 batch-avx512
nametag: linux-clang12-llvm12-batch
os: ubuntu-latest
runner: ubuntu-latest
container: aswftesting/ci-osl:2022-clang12
vfxyear: 2022
vfxsuffix: -clang12
cxx_std: 17
openimageio_ver: master
python_ver: 3.9
@@ -111,11 +106,11 @@ jobs:
simd: avx2,f16c
batched: b8_AVX2,b8_AVX512,b16_AVX512
setenvs: USE_OPENVDB=0
- desc: icc/C++17 llvm13 py3.9 boost1.76 exr3.1 oiio-master avx2
- desc: icc/C++17 llvm14 py3.9 boost1.76 exr3.1 oiio-master avx2
nametag: linux-icc
os: ubuntu-latest
runner: ubuntu-latest
container: aswftesting/ci-osl:2022-clang14
vfxyear: 2022
vfxsuffix: -clang13
cc_compiler: icc
cxx_compiler: icpc
cxx_std: 17
@@ -128,11 +123,11 @@ jobs:
setenvs: export OSL_CMAKE_FLAGS="-DSTOP_ON_WARNING=OFF -DEXTRA_CPP_ARGS=-fp-model=consistent"
OPENIMAGEIO_CMAKE_FLAGS=-DBUILD_FMT_VERSION=7.1.3
USE_OPENVDB=0
- desc: icx/C++17 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
- desc: icx/C++17 llvm14 py3.9 boost1.76 exr3.1 oiio2.3 avx2
nametag: linux-icx
os: ubuntu-latest
runner: ubuntu-latest
container: aswftesting/ci-osl:2022-clang14
vfxyear: 2022
vfxsuffix: -clang13
cc_compiler: icx
cxx_compiler: icpx
cxx_std: 17
@@ -143,24 +138,50 @@ jobs:
simd: avx2,f16c
batched: b8_AVX2_noFMA
setenvs: export OSL_CMAKE_FLAGS="-DSTOP_ON_WARNING=OFF" USE_OPENVDB=0
- desc: oldest everything gcc6/C++14 llvm9 py2.7 boost1.66 oiio2.2 no-simd exr2.3
- desc: gcc11/C++17 llvm15 py3.10 boost1.80 exr3.1 oiio-rel avx2
nametag: linux-vfx2023
runner: ubuntu-latest
container: aswftesting/ci-osl:2023-clang15
vfxyear: 2023
cxx_std: 17
openimageio_ver: release
python_ver: "3.10"
pybind11_ver: v2.9.0
simd: avx2,f16c
batched: b8_AVX2
- desc: GPU Cuda11 gcc11/C++17 llvm15 py3.10 boost1.80 exr3.1 OIIO-master avx2
nametag: linux-optix7-2023
runner: ubuntu-latest
container: aswftesting/ci-osl:2023-clang15
vfxyear: 2023
cxx_std: 17
openimageio_ver: master
python_ver: "3.10"
pybind11_ver: v2.10.0
simd: avx2,f16c
skip_tests: 1
setenvs: export OSL_CMAKE_FLAGS="-DOSL_USE_OPTIX=1" OPTIX_VERSION=7.0
OPENIMAGEIO_CMAKE_FLAGS=-DBUILD_FMT_VERSION=9.1.0
- desc: oldest everything gcc6/C++14 llvm9 py2.7 boost1.66 oiio2.3 no-simd exr2.4
nametag: linux-oldest
os: ubuntu-latest
runner: ubuntu-latest
container: aswftesting/ci-osl:2019-clang9
vfxyear: 2019
vfxsuffix: -clang9
cxx_std: 14
openimageio_ver: v2.3.17.0
openexr_ver: v2.4.3
openimageio_ver: v2.4.13.0
python_ver: 2.7
pybind11_ver: v2.6.2
simd: 0
setenvs: export PUGIXML_VERSION=v1.8
CMAKE_VERSION=3.15.5
# Address and leak sanitizers
- desc: sanitizers
nametag: sanitizer
os: ubuntu-latest
runner: ubuntu-latest
container: aswftesting/ci-osl:2022-clang13
vfxyear: 2022
vfxsuffix: -clang13
cc_compiler: clang
cxx_compiler: clang++
cxx_std: 17
@@ -196,28 +217,33 @@ jobs:
# texture system adequately and is able to ignore the benign
# "leaks."
# Test formatting. This test entry doesn't do a full build, it
# just runs clang-format on everything, and passes if nothing is
# misformatted. Upon failure, the build artifact will be the full
# source code with the formatting fixed (diffs will also appear in
# the console output).
- desc: "clang-format"
nametag: clang-format
os: ubuntu-latest
vfxyear: 2022
vfxsuffix: -clang14
# Test ABI stability. `abi_check` is the version or commit that we
# believe is the current standard against which we don't want to
# break the ABI. Basically, we will build that version as well as
# the current one, and compare the resulting libraries.
- desc: abi check
nametag: linux-vfx2023
runner: ubuntu-latest
container: aswftesting/ci-osl:2023-clang15
vfxyear: 2023
cc_compiler: gcc
cxx_compiler: g++
cxx_std: 17
openimageio_ver: release
python_ver: 3.9
simd: avx2,f16c
# openimageio_ver: release
python_ver: "3.10"
simd: "avx2,f16c"
batched: b8_AVX2
fmt_ver: 10.1.1
pybind11_ver: v2.10.0
skip_tests: 1
setenvs: export BUILDTARGET=clang-format
OPENIMAGEIO_CMAKE_FLAGS=-DUSE_PYTHON=0
abi_check: 1726df72a9841df93bc74a5184d78cacb44b585d
setenvs: export OSL_CMAKE_FLAGS="-DOSL_BUILD_TESTS=0 -DBUILD_TESTING=OFF -DUSE_QT=0"
OPENIMAGEIO_CMAKE_FLAGS="-DUSE_PYTHON=0"
CMAKE_BUILD_TYPE=RelWithDebInfo
runs-on: ${{matrix.os}}
runs-on: ${{matrix.runner}}
container:
image: aswftesting/ci-osl:${{matrix.vfxyear}}${{matrix.vfxsuffix}}
image: ${{ matrix.container }}
env:
CXX: ${{matrix.cxx_compiler}}
CC: ${{matrix.cc_compiler}}
@@ -229,6 +255,7 @@ jobs:
PYTHON_VERSION: ${{matrix.python_ver}}
USE_BATCHED: ${{matrix.batched}}
USE_SIMD: ${{matrix.simd}}
ABI_CHECK: ${{matrix.abi_check}}
steps:
# We would like to use harden-runner, but it flags too many false
# positives, every time we download a dependency. We should use it only
@@ -269,11 +296,32 @@ jobs:
- name: Testsuite
if: matrix.skip_tests != '1'
run: src/build-scripts/ci-test.bash
- name: Check out ABI standard
if: matrix.abi_check != ''
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
with:
ref: ${{matrix.abi_check}}
path: abi_standard
- name: Build ABI standard
if: matrix.abi_check != ''
run: |
mkdir -p abi_standard/build
pushd abi_standard
export LD_LIBRARY_PATH="${PWD}/build/lib:${LD_LIBRARY_PATH}"
src/build-scripts/ci-build.bash
popd
- name: Check ABI
if: matrix.abi_check != ''
run: |
src/build-scripts/ci-abicheck.bash ./build abi_standard/build \
liboslexec liboslcomp liboslquery liboslnoise
- uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
if: failure()
with:
name: osl-${{github.job}}-${{matrix.nametag}}
path: |
build/cmake-save
build/compat_reports
build/*.cmake
build/CMake*
build/testsuite/*/*.*
@@ -287,11 +335,11 @@ jobs:
include:
- desc: Debug gcc7/C++14 llvm9 py2.7 oiio2.3 exr2.4 sse4 boost1.65 exr2.4
nametag: linux-debug-gcc7-llvm9
os: ubuntu-18.04
runner: ubuntu-20.04
cxx_compiler: g++-7
cxx_std: 14
openexr_ver: v2.4.3
openimageio_ver: dev-2.3
openimageio_ver: v2.4.13.0
pybind11_ver: v2.6.2
python_ver: 2.7
simd: sse4.2
@@ -301,7 +349,7 @@ jobs:
CTEST_TEST_TIMEOUT=240
- desc: gcc10/C++17 llvm10 oiio-release boost1.65 exr2.5 avx2
nametag: linux-2021ish-gcc10-llvm10
os: ubuntu-18.04
runner: ubuntu-20.04
cxx_compiler: g++-10
cxx_std: 17
fmt_ver: 7.0.1
@@ -313,25 +361,25 @@ jobs:
setenvs: export LLVM_VERSION=10.0.0
OPENIMAGEIO_CMAKE_FLAGS="-DBUILD_FMT_VERSION=7.0.1"
PUGIXML_VERSION=v1.10
- desc: latest releases gcc11/C++17 llvm13 boost1.71 exr3.1 py3.9 avx2 batch-b16avx512
- desc: latest releases gcc11/C++17 llvm16 boost1.71 exr3.2 py3.9 avx2 batch-b16avx512
nametag: linux-latest-releases
os: ubuntu-20.04
runner: ubuntu-22.04
cxx_compiler: g++-11
cxx_std: 17
fmt_ver: 9.1.0
openexr_ver: v3.1.5
fmt_ver: 10.1.0
openexr_ver: v3.2.1
openimageio_ver: master
pybind11_ver: v2.10.0
python_ver: 3.9
python_ver: "3.10"
simd: avx2,f16c
batched: b8_AVX2,b8_AVX512,b16_AVX512
setenvs: export LLVM_VERSION=13.0.0
LLVM_DISTRO_NAME=ubuntu-20.04
OPENCOLORIO_VERSION=v2.1.2
PUGIXML_VERSION=v1.11.4
- desc: bleeding edge gcc12/C++17 llvm14 oiio/ocio/exr/pybind-master boost1.71 py3.10 avx2 batch-b16avx512
setenvs: export LLVM_VERSION=16.0.4
LLVM_DISTRO_NAME=ubuntu-22.04
OPENCOLORIO_VERSION=v2.2.0
PUGIXML_VERSION=v1.13
- desc: bleeding edge gcc12/C++17 llvm17 oiio/ocio/exr/pybind-master boost1.71 py3.10 avx2 batch-b16avx512
nametag: linux-bleeding-edge
os: ubuntu-22.04
runner: ubuntu-22.04
cxx_compiler: g++-12
cxx_std: 17
fmt_ver: master
@@ -341,18 +389,18 @@ jobs:
python_ver: "3.10"
simd: avx2,f16c
batched: b8_AVX2,b8_AVX512,b16_AVX512
setenvs: export LLVM_VERSION=14.0.0
LLVM_DISTRO_NAME=ubuntu-18.04
setenvs: export LLVM_VERSION=17.0.6
LLVM_DISTRO_NAME=ubuntu-22.04
OPENCOLORIO_VERSION=main
PUGIXML_VERSION=master
- desc: clang14/C++17 llvm14 boost1.71 exr3.1 py3.8 avx2 batch-b16avx512
nametag: linux-latest-releases-clang
os: ubuntu-20.04
runner: ubuntu-20.04
cxx_compiler: clang++
cc_compiler: clang
cxx_std: 17
fmt_ver: 8.1.1
openexr_ver: v3.1.5
openexr_ver: v3.1.7
openimageio_ver: master
pybind11_ver: v2.9.2
python_ver: 3.8
@@ -362,8 +410,29 @@ jobs:
LLVM_DISTRO_NAME=ubuntu-18.04
OPENCOLORIO_VERSION=v2.1.2
PUGIXML_VERSION=v1.11.4
# Test formatting. This test entry doesn't do a full build, it
# just runs clang-format on everything, and passes if nothing is
# misformatted. Upon failure, the build artifact will be the full
# source code with the formatting fixed (diffs will also appear in
# the console output).
- desc: "clang-format"
nametag: clang-format
runner: ubuntu-latest
container: aswftesting/ci-osl:2022-clang14
cxx_std: 17
extra_artifacts: "src/*.*"
openimageio_ver: release
python_ver: "3.10"
simd: avx2,f16c
batched: b8_AVX2
skip_tests: 1
setenvs: export BUILDTARGET=clang-format
LLVM_VERSION=17.0.6
LLVM_DISTRO_NAME=ubuntu-22.04
OPENIMAGEIO_CMAKE_FLAGS=-DUSE_PYTHON=0
QT_VERSION=0
runs-on: ${{matrix.os}}
runs-on: ${{matrix.runner}}
env:
CXX: ${{matrix.cxx_compiler}}
CC: ${{matrix.cc_compiler}}
@@ -412,36 +481,43 @@ jobs:
with:
name: osl-${{github.job}}-${{matrix.nametag}}
path: |
build/cmake-save
build/*.cmake
build/CMake*
build/testsuite/*/*.*
${{ matrix.extra_artifacts }}
macos:
name: "${{matrix.os}} appleclang${{matrix.aclang}}/C++${{matrix.cxx_std}} py${{matrix.python_ver}} ${{matrix.desc}}"
name: "${{matrix.runner}} C++${{matrix.cxx_std}} py${{matrix.python_ver}} ${{matrix.desc}}"
strategy:
fail-fast: false
matrix:
include:
- desc: MacOS-11
os: macos-11
nametag: macos11-py39
cc_compiler: /usr/local/opt/llvm@14/bin/clang
cxx_compiler: /usr/local/opt/llvm@14/bin/clang++
- desc: MacOS-13 llvm17
runner: macos-13
nametag: macos13-p311
cc_compiler: /usr/local/opt/llvm/bin/clang
cxx_compiler: /usr/local/opt/llvm/bin/clang++
cxx_std: 17
python_ver: "3.10"
aclang: 13
setenvs: export LLVMBREWVER="@14" DO_BREW_UPDATE=1
- desc: MacOS-12
os: macos-12
nametag: macos11-p310
cc_compiler: /usr/local/opt/llvm@15/bin/clang
cxx_compiler: /usr/local/opt/llvm@15/bin/clang++
openimageio_ver: master
python_ver: "3.11"
aclang: 14
setenvs: export DO_BREW_UPDATE=1 CTEST_TEST_TIMEOUT=120
- desc: MacOS-14-ARM llvm17
runner: macos-14
nametag: macos14-arm-p311
cc_compiler: clang
cxx_compiler: clang++
Xcc_compiler: /usr/local/opt/llvm/bin/clang
Xcxx_compiler: /usr/local/opt/llvm/bin/clang++
cxx_std: 17
python_ver: "3.10"
aclang: 13
setenvs: export LLVMBREWVER="@15" DO_BREW_UPDATE=1
runs-on: ${{matrix.os}}
openimageio_ver: master
python_ver: "3.11"
aclang: 15
setenvs: export DO_BREW_UPDATE=1
runs-on: ${{matrix.runner}}
env:
CXX: ${{matrix.cxx_compiler}}
CC: ${{matrix.cc_compiler}}
@@ -468,7 +544,7 @@ jobs:
run: |
source src/build-scripts/install_homebrew_deps.bash
if [[ "$OPENIMAGEIO_VERSION" != "" ]] ; then \
OPENIMAGEIO_CMAKE_FLAGS="-DOIIO_BUILD_TESTS=0 -DUSE_OPENGL=0" ; \
OPENIMAGEIO_CMAKE_FLAGS="-DOIIO_BUILD_TESTS=0 -DUSE_OPENGL=0 -DCMAKE_UNITY_BUILD=ON" ; \
source src/build-scripts/build_openimageio.bash ; \
else \
brew install --display-times -q openimageio ; \
@@ -485,6 +561,7 @@ jobs:
with:
name: osl-${{github.job}}-${{matrix.nametag}}
path: |
build/cmake-save
build/*.cmake
build/CMake*
build/testsuite/*/*.*
+26
View File
@@ -0,0 +1,26 @@
# Copyright Contributors to the Open Shading Language project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/AcademySoftwareFoundation/OpenshadingLanguage
name: Publish Release Notice to ASWF Slack
on:
release:
types:
- published
# published should cover both 'released' and 'prereleased'
jobs:
publish:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Notify Slack
id: slack
with:
project_name: "Open Shading Language"
slack_bot_token: ${{ secrets.SLACK_BOT_TOKEN }}
slack_channel: "#release-announcements"
project_logo: "https://artwork.aswf.io/projects/openshadinglanguage/AcronymStack/Shaded/openshadinglanguage-AcronymStack-Shaded.png"
uses: jmertic/slack-release-notifier@main
+16 -3
View File
@@ -1,3 +1,7 @@
# Copyright Contributors to the Open Shading Language project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
name: Scorecards supply-chain security
on:
# Only the default branch is supported.
@@ -6,22 +10,31 @@ on:
- cron: '44 20 * * 6'
push:
branches: [ "main", "scorecard" ]
paths-ignore:
- '**.md'
- '**.rst'
- '**.tex'
# Declare default permissions as read only.
permissions: read-all
# Allow subsequent pushes to the same PR or REF to cancel any previous jobs.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
analysis:
name: Scorecards analysis
if: |
github.repository == 'AcademySoftwareFoundation/OpenShadingLanguage'
runs-on: ubuntu-latest
permissions:
# Needed to upload the results to code-scanning dashboard.
security-events: write
# Used to receive a badge. (Upcoming feature)
id-token: write
# Needs for private repositories.
contents: read
actions: read
steps:
- name: "Checkout code"
+47
View File
@@ -0,0 +1,47 @@
# This file establishes email equivalences so we can resolve what look like
# multiple authors, but actually are the same author who has used multiple
# emails over the course of their involvement with the project.
#
# The format is any of the following:
# <CANONICAL-EMAIL> <alternate-email>
# CANONICAL-NAME <CANONICAL-EMAIL> <alternate-email>
# CANONICAL-NAME <CANONICAL-EMAIL> alternate-name <alternate-email>
#
# You can check for duplicates with this command:
# git shortlog -sne --all
# That command (and others) will use this file to collapse the duplicates.
#
# If you see any duplicates we don't account for here, or if you look at your
# own entry here and want a different name or email to be your canonical one
# (we may not have guessed correctly and matched your preferences), please
# file a PR with the edits to this file.
Adam Martinez <amartinez.cg@gmail.com> amartinez-cg <amartinez.cg@gmail.com>
Alejandro Conty <aconty@imageworks.com> aconty <aconty@gmail.com>
Alejandro Conty <aconty@imageworks.com> Alejandro Conty <aconty@gmail.com>
Alex M. Wells <alex.m.wells@intel.com> <alex.m.wells@intel.com>
Alex M. Wells <alex.m.wells@intel.com> <AlexMWells@users.noreply.github.com>
Alex M. Wells <alex.m.wells@intel.com> <awells-np@argon.sea.pixar.com>
Alexis Oblet <alob@mikrosimage.eu> Alexis Oblet <aoblet@users.noreply.github.com>
Brecht Van Lommel <brecht@blender.org> <brecht@solidangle.com>
Brecht Van Lommel <brecht@blender.org> Brecht Van Lommel <brechtvanlommel@gmail.com>
Chris Kulla <ckulla@gmail.com> <ckulla@imageworks.com>
Chris Kulla <ckulla@gmail.com> <fpsunflower@users.noreply.github.com>
Chris Kulla <ckulla@gmail.com> Christopher Kulla <ckulla@gmail.com>
Chris Kulla <ckulla@gmail.com> fpsunflower <ckulla@gmail.com>
Clifford Stein <cstein@imageworks.com> Cliff Stein <clifford.stein@gmail.com>
Clifford Stein <cstein@imageworks.com> cmstein <cstein@imageworks.com>
Declan Russell <declan.russell@autodesk.com> Declan Russell <i7709212@bournemouth.ac.uk>
Derek Haase <derekhaase@gmail.com> Derek Haase <dhaase@imageworks.com>
Esteban Tovagliari <ramenhdr@gmail.com> est77 <ramenhdr@gmail.com>
Henri Fousse <henri.fousse@free.fr> darkhorse64 <henri.fousse@free.fr>
Larry Gritz <lg@imageworks.com> <larrygritz@gmail.com>
Larry Gritz <lg@imageworks.com> <lg@larrygritz.com>
Roman Zulak <marsupial@users.noreply.github.com> <rzulak@imageworks.com>
Roman Zulak <marsupial@users.noreply.github.com> Frederich Munch <marsupial@users.noreply.github.com>
Roman Zulak <marsupial@users.noreply.github.com> marsupial <marsupial@users.noreply.github.com>
Ronan Keryell <Ronan.Keryell@amd.com> Ronan Keryell <Ronan.Keryell@silkan.com>
Steena Monteiro <steena.monteiro@intel.com> steena.monteiro <smonteir@ortce-sklaw.jf.intel.com>
Sven-Hendrik Haase <sh@lutzhaase.com> Sven-Hendrik Haase <svenstaro@gmail.com>
Tim Grant <tgrant@nvidia.com> Tim Grant <87798327+tgrant-nv@users.noreply.github.com>
Tim Grant <tgrant@nvidia.com> timgrant <timgrant@users.noreply.github.com>
+29
View File
@@ -0,0 +1,29 @@
# .readthedocs.yml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# Build documentation with Sphinx
sphinx:
configuration: src/doc/conf.py
# Optionally build your docs in additional formats such as PDF and ePub
formats:
- pdf
- htmlzip
# Optionally set the version of Python and requirements required to build your docs
python:
install:
- requirements: src/doc/requirements.txt

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

+4 -3
View File
@@ -5,13 +5,14 @@ This is a checklist for TSC's to review as part of the intake process. The TSC s
- Existing Project Governance
- [X] Project License exists ( [LICENSE.md](../LICENSE.md) ) and is OSI-approved
- [X] Any third-party components/dependencies included are listed along with their licenses ( [THIRD_PARTY.md](../THIRD_PARTY.md) )
- [X] Governance defined, outlining community roles and how decsions are made ( [GOVERNANCE.md](../GOVERNANCE.md] )
- [X] Governance defined, outlining community roles and how decisions are made ( [GOVERNANCE.md](../GOVERNANCE.md) )
- Closed by https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1137
- [X] Contribution Policy defined ( [CONTRIBUTING.md](../CONTRIBUTING.md) )
- Closed by https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1137
- [X] Code of Conduct defined ( existing or pull from [ASWF Sample Project](https://github.com/AcademySoftwareFoundation/aswf-sample-project/blob/master/CODE_OF_CONDUCT.md) )
- Closed by https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1137
- [ ] Release methodology defined ( [release.md](process/release.md) )
- [X] Release methodology defined ( [RELEASING.md](../docs/RELEASING.md) )
- Closed by https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1572
- New Project Governance
- [X] TSC members identified
- [X] First TSC meeting held
@@ -41,7 +42,7 @@ This is a checklist for TSC's to review as part of the intake process. The TSC s
- [X] New project announcement done ( https://www.aswf.io/osl-joins-aswf/ )
- [X] Project added to ASWF website and ASWF landscape
- Graduation
- [ ] CII Badge achieved
- [X] OpenSSF Best Practices Badge achieved
- [ ] Committer Diversity established
- [ ] Commit/Contribution growth during incubation
- [ ] Committers defined in the project ( [COMMITTERS.csv](COMMITTERS.csv) or [COMMITTERS.yml](COMMITTERS.yml) )
+308 -28
View File
@@ -1,30 +1,78 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the Open Shading Language Project. -->
Release 1.13 -- ?? 2023 ?? (compared to 1.12)
--------------------------------------------------
Dependency and standards requirements changes:
* OptiX 6.0 support has been removed. For GPU rendering with OptiX, a minimum
of OptiX 7.0 is required.
* The minimum version OpenImageIO has been raised from 2.2 to 2.3. #1591
(1.13.0.3)
Release 1.13.7.0 -- 1 Mar 2024 (compared to 1.13.6.1)
--------------------------------------------------------
- *fix*: Mute partio error prints [#1774](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1774) (by olegul)
- *ci*: Test with Mac ARM runner [#1770](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1770)
- *docs*: Fix links to RTD docs from github landing page [#1768](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1768)
- *admin*: Switch release announcement workflow to jmertic's awesome action [#1766](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1766)
OSL Language and oslc compiler:
* Bug fix: shader params whose default values involve "init ops" could be
incorrectly initialized if their values came from instance parameters set to
zero. #1578 (1.13.0.2)
<br>
OSL Standard library:
API changes, new options, new ShadingSystem features (for renderer writers):
Release 1.13 -- Feb 1, 2024 (compared to 1.12)
===============================================
- beta 1: December 20, 2023
- release v1.13.6.1: Feb 1, 2024
### New minimum dependencies and compatibility changes:
* For GPU/OptiX mode, OptiX 6.0 support has been removed. For GPU rendering
with OptiX, a minimum of OptiX 7.0 is required, and the Cuda minimum has
been raised to 9.0 [#1737](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1737)
* The minimum version OpenImageIO has been raised from 2.2 to 2.4. [#1591](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1591) [#1722](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1722)
* The minimum CMake dependency has been raised from 3.12 to 3.15
[#1724](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1724) (1.13.5.0)
* The minimum Imath/OpenEXR has been raised from 2.3 to 2.4. (Note: OSL 1.13
is probably the last major release family that will support Imath/OpenEXR
2.x.)
### OSL Language and oslc compiler:
* There have been no substantive changes to the OSL language in this release.
### ⛰️ API changes, new options, new ShadingSystem features (for renderer writers):
* A new `shadingStateUniform` pointer field was added to ShaderGlobals for
planned future expansion and improved GPU support. #1585 (1.13.1.0)
* Adding relaxed type-equivalency to ReParameter() [#1639](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1639) (by cmstein) (1.13.2.1)
* Expose llvm groupdata size as a shadergroup attribute
[#1642](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1642) (by Chris Hellmuth) (1.13.4.0)
* RendererServices API for letting get_texture_handle consider colorspace
[#1641](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1641) (1.13.4.0)
* Make "compile_report" attribute an int instead of just 0/1. Passing 1 makes
a brief report, values >1 are more verbose. (Zero still prints no report.)
[#1654](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1654) (1.13.4.0)
* Switch `lockgeom` to `interpolated` and `interactive`. The `lockgeom=0`
was confusing. Now we use `interpolated=1` to mean "don't optimize it away
because it might be interpolated across the geometry and thus won't have
the same value at all points being shaded," and the subtly different
`interactive=1` to mean "don't optimize it away because although it will
always take on the same value at all points at the same time, the user
might want to interactively adjust the value and we don't want to have
to recompile the shader group if that happens."
[#1662](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1662) (1.13.4.0)
* Add type information for needed attributes. [#1650](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1650) (by Curtis Black) (1.13.4.0)
* Add API for building attribute getter free functions.
[#1704](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1704) (by Curtis Black) (1.13.5.0)
* Rs fmt specification - Journaling Algorithm for error, warning, fprintf
[#1702](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1702) (by Steena Monteiro) [#1711](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1711) [#1715](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1715) (1.13.5.0)
### 🚀 SIMD batched shading mode
SIMD batched shading mode:
* Fix some array overruns (asymptomatic, but still potentially buggy) in
common_ancestor_between. #1577 (1.13.0.2)
* Fix issue with closure keyword parameters. #1620 (1.13.2.0/1.12.8.0)
* Fix crash when adding a default initialized closure. #1624
(1.13.2.0/1.12.8.0)
* Fix support for closures with array types. #1630 (1.13.2.0/1.12.8.0)
* Fix bug with masked wide llvm_gen_closure() [#1637](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1637) (by danieldresser-ie) (1.13.2.1)
* Fix Force LLVM Boolean [#1717](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1717) (by Alex Wells)
* Batched pointcloud if "index" is not passed [#1753](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1753) (by Alex Wells)
### 🚀 OptiX GPU rendering
OptiX rendering:
* OptiX 6.0 support has been removed. For GPU rendering with OptiX, a minimum
of OptiX 7.0 is required.
* Big overhaul/simplification of how strings are represented on the GPU: the
@@ -34,36 +82,268 @@ OptiX rendering:
* Better PTX cache hit rate by eliminating several sources of not being
strictly deterministic in the PTX text we were generating. #1566 #1570
(1.13.0.1)
* Fix PTX symbol visibility issues. #1609 (1.13.2.0)
* Hide more code that is only used for OptiX mode, when OptiX is disabled.
#1608 (1.13.2.0)
* Remove dependency on OptiX SDK for building core OSL with OptiX support. You
can now build OSL with OptiX support enabled even if you don't have the
OptiX SDK headers present at build time. But you will still need them to
build your OptiX-based application that uses OSL for GPU rendering. #1627
(1.13.2.0/1.12.8.0)
* GPU/OptiX support of ReParameter [#1686](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1686) (1.13.4.0)
* Fix userdata derivatives for interpolated params on GPU [#1685](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1685) (by Pascal Lecocq) (1.13.4.0)
* Enable userdata derivatives for interpolated params on GPU
[#1657](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1657) (by Chris Hellmuth) (1.13.4.0)
* Move qualifying GroupData params onto stack for higher performance.
[#1710](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1710) (by Chris Hellmuth) (1.13.5.0)
* Handle mixed string casting that plagues optix codegen [#1718](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1718) (1.13.5.0)
* Add missing members to ShaderGlobals in rend_lib.h [#1721](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1721) (by Tim Grant) (1.13.5.0)
* OptiX direct callable API that owns groupdata buffer
[#1683](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1683) (by Chris Hellmuth) (1.13.5.0)
* OptiX PTX pipeline overhaul [#1680](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1680) (by Tim Grant) (1.13.5.0)
* Perf: Don't insert redundant run layer calls inside a basic block
[#1665](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1665) [#1669](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1669) [#1672](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1672) (by Chris Hellmuth) (1.13.4.0)
* Fix NVPTX TargetMachine leak, etc. [#1763](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1763) (by Tim Grant)
Performance improvements:
### 🐛/🔧 Internals: fixes, improvements, and developer concerns
Bug fixes and other improvements (internals):
* Fix memory leak in oslc ASTvariable_declaration. #1576 (1.13.0.2)
* Fix memory leaks in LPE code in error conditions. #1593 #1594 (1.13.0.3)
Internals/developer concerns:
* Fix mismatched strides when calling OCIO for transformc with derivs [#1646](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1646) (1.13.4.0)
* Set up ray types for testrender [#1648](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1648) (1.13.4.0)
* Fix userdata binding corner case [#1673](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1673) (by Alejandro Conty) (1.13.4.0)
* Fix constant float values being converted to ints [#1674](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1674) (by Declan Russell) (1.13.4.0)
* Don't try to ReParameter symbols not in the group [#1693](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1693) (by Alejandro Conty) (1.13.5.0)
* Have ReParameter only copy data when it changes [#1698](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1698) (1.13.5.0)
* Avoid deprecated OSLQuery ctr in test example [#1699](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1699) (1.13.5.0)
* Zero derivs for interactive params when needed [#1700](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1700) (by Alejandro Conty) (1.13.5.0)
* oslc bug fix: shader params whose default values involve "init ops" could be
incorrectly initialized if their values came from instance parameters set to
zero. #1578 (1.13.0.2)
* oslc: Add missing `fmod()` variants [#1643](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1643) (1.13.4.0)
* Simple constant folding of binary expressions now happen on the oslc side
[#1653](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1653) (1.13.4.0)
* platform.h:
- New `OSL_ALLOCA` macro to allocate on the stack. #1589 (1.13.0.3)
* New `OSL_ALLOCA` macro to allocate on the stack. #1589 (1.13.0.3)
* Define OSL::bitcast utility. #1610 (1.13.2.0)
* Make sure that std::hash is defined for ustring and ustringhash. #1599
(1.13.1.1)
* Deprecate LLVMUtil::internalize_module_functions. #1606 (1.13.1.0)
* Work toward always representing strings in shaders as ustringhash rather
than ustring: phase 1 #1603 phase2 #1612 (1.13.2.0) [#1726](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1726) (1.13.5.0)
* Remove unnecessary setting of locale::global [#1636](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1636) (by danieldresser-ie) (1.13.2.1)
* Fully define bitcast template [#1635](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1635) (1.13.2.1)
* Fix for ReParameter corner case [#1670](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1670) (by cmstein) (1.13.4.0)
* Switch deprecated oiio simd names to modern [#1679](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1679) (1.13.4.0)
* Give ShadingSystemImpl a handy use_optix() method [#1682](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1682) (1.13.4.0)
* Fix default fmt logic changing in latest openimageio release [#1725](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1725) (1.13.5.0)
* The recently added SS::find_symloc can have const args [#1723](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1723) (1.13.5.0)
* SymOverrideInfo bitfields should be the same type [#1745](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1745)
* Fix wrong offset of MxSheen param [#1751](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1751) (by Rasmus Bonnedal)
* Make get_texture_info robust to empty shaderglobals param [#1731](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1731)
### 🏗 Build/test/CI and platform ports
Build & test system improvements:
* CMake build system and scripts:
- The version number is now a cache variable, and so can be overridden at
* The version number is now a cache variable, and so can be overridden at
build time using `-DOSL_VERSION=...`. Use with extreme caution! #1579
(1.13.0.2)
(1.13.0.2) Revised again to reduce changes of user error in #1617
(1.13.2.0/1.12.7.1)
* Add clangSupport library as dependency to fix linker error on some
platforms. #1613 (1.13.2.0/1.12.7.1)
* Fix incorrect CMake variable name to control symbol visibility
[#1681](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1681) (1.13.4.0)
* Change cmake option `USE_OPTIX` -> `OSL_USE_OPTIX` [#1668](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1668) (1.13.4.0)
* Fix duplicate osl lexing symbols when building as static libraries
[#1709](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1709) (by Brecht Van Lommel) (1.13.5.0)
* Better cmake verbose behavior [#1752](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1752)
* Dependency version support:
- Fix some issues that came up with the new icx 2022.0 compiler. #1601
* Fix some issues that came up with the new icx 2022.0 compiler. #1601
(1.13.1.0)
* Test against OpenColorIO 2.2. #1616 (1.13.2.0/1.12.7.1)
* Proper warnings about LLVM 16 [#1658](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1658) (1.13.4.0)
* Fix cuda compilation flags for LLVM 15 [#1659](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1659) (1.13.4.0)
* Verify that OSL can build with clang16 [#1664](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1664) (1.13.4.0)
* Be more careful about paths to look for llvm [#1656](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1656) (1.13.4.0)
* Qt6 compatibility [#1655](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1655) (1.13.4.0)
* Fix warnings about Qt compilation and enums [#1661](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1661) (1.13.4.0)
* Changes to support fmt 10.0 [#1691](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1691) (1.13.5.0)
* Raise OpenEXR minimum to 2.4 [#1734](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1734)
* Fix Partio build errors on pointcloud functions for MSVC [#1757](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1757) (by Alex Wells)
* Bump Cuda minimum to 9.0 [#1737](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1737)
* LLVM 16 and 17 support: LLVM opaque pointers support [#1728](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1728),
LLVM new pass manager support [#1729](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1729),
finish LLVM 16 and 17 support [#1730](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1730) (all by Brecht Van Lommel)
* Testing and Continuous integration (CI) systems:
- Dynamic analysis using address and leak sanitizers. #1581 (1.13.0.3)
- `testshade --help` now prints TextureSystem options and all hardware
* Dynamic analysis using address and leak sanitizers. #1581 (1.13.0.3)
* `testshade --help` now prints TextureSystem options and all hardware
information. #1584 (1.13.0.3)
- Improvements to SonarCloud and coverage analysis. #1596 (1.13.0.3)
* Improvements to SonarCloud and coverage analysis. #1596 (1.13.0.3)
#1607 (1.13.1.0)
* Disabling the dso version of testshade for the coverage analysis test.
#1604 (1.13.1.0)
* Be sure to run pointcloud tests when partio is found. #1611 (1.13.2.0)
* testshade: better testing of all closure parameter types. #1621
(1.13.2.0/1.12.8.0)
* Don't use the cached background map on the first bounce
[#1649](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1649) (by Christopher Kulla) (1.13.4.0)
* Fix builds when USE_PYTHON=OFF [#1675](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1675) (by Declan Russell) (1.13.4.0)
* Remove SonarCloud cache setup as it is now offered by default
[#1660](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1660) (by Massimo Paladin) (1.13.4.0)
* *ci*: Simplify build_llvm.bash script [#1703](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1703) (1.13.5.0)
* Test interactive parameter initialization in optix testrender [#1687](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1687) (by Chris Hellmuth) (1.13.5.0)
* Fix GPU job not actually enabling OptiX [#1738](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1738) (by Brecht Van Lommel)
* Fix python-oslquery test failure on macOS [#1739](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1739) (by Brecht Van Lommel)
* Disable MacOS-11 CI [#1746](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1746)
* Skip analysis and scorecard workflows on push if only docs changed [#1744](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1744)
* For clarity, use the term 'runner' instead of 'os' [#1743](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1743)
* Test ABI compliance [#1748](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1748)
* Fix tests passing when test commands fail [#1733](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1733) (by Brecht Van Lommel)
* *ci*: Test against LLVM 17 [#1760](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1760)
* Platform support:
* Include `immintrin.h` only when needed. #1605 (1.13.1.0)
* Changed snprintf formatting to satisfy some compilers.
[#1640](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1640) (by pellerington) (1.13.4.0)
* Fix some windows GPU build errors [#1638](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1638) (by Declan Russell) (1.13.4.0)
* Fix for Apple clang 14+ warnings [#1697](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1697) (1.13.5.0)
* Fix struct align/pack for MSVC [#1754](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1754) (by Rasmus Bonnedal)
* Refactor icc/icx specific pragma macros [#1756](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1756) (by Alex Wells)
Documentation:
### 📚 Documentation
* First stab at ReadTheDocs -- new [Experimental OSL Documentation on
ReadTheDocs](https://open-shading-language.readthedocs.io/)
is still a little rough, but eventually will be our primary documentation.
[#1736](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1736)
* `doc/RELEASING.md` documents our release process and versioning policies.
#1572 (1.13.0.2)
* Improve documentation of `trace` function [#1671](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1671) (by AidanWelch) (1.13.4.0)
* Update CONTRIBUTING [#1689](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1689) (1.13.5.0)
* Update logos [#1705](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1705), Move logos and add an icon-only logo [#1707](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1707) (1.13.5.0)
### 🏢 Project Administration
* Alert slack "release-announcements" channel upon OSL release [#1740](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1740) [#1749](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1749)
* Update pull request template [#1741](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1741)
* Account for duplicate emails in the .mailmap [#1759](https://github.com/AcademySoftwareFoundation/OpenImageIO/pull/1759)
---
---
---
Release 1.12.13.0 -- 1 July 2023 (compared to 1.12.12.0)
--------------------------------------------------------
- *fix*: Fix constant float values being converted to ints
[#1674](https://github.com/OpenImageIO/oiio/pull/1674) (by Declan Russell)
- *build*: Fix builds when USE_PYTHON=OFF
[#1675](https://github.com/OpenImageIO/oiio/pull/1675) (by Declan Russell)
- *build*: Changes to support fmt 10.0
[#1691](https://github.com/OpenImageIO/oiio/pull/1691)
- *cleanup*: Switch deprecated oiio simd names to modern
[#1679](https://github.com/OpenImageIO/oiio/pull/1679)
- *testing*: Avoid deprecated OSLQuery ctr in test example
[#1699](https://github.com/OpenImageIO/oiio/pull/1699)
- *ci*: Fix package name for icc
[#1690](https://github.com/OpenImageIO/oiio/pull/1690)
- *ci*: Add VFX Platform 2023 tests using new ASWF containers
[#1696](https://github.com/OpenImageIO/oiio/pull/1696)
- *ci*: Switch oiio obsolete branch names to immutable tags
[#1701](https://github.com/OpenImageIO/oiio/pull/1701)
- *docs*: Improve documentation of `trace` function
[#1671](https://github.com/OpenImageIO/oiio/pull/1671) (by AidanWelch)
- *docs*: README.md: added filmography and Siggraph OSL course info.
[#1692](https://github.com/OpenImageIO/oiio/pull/1692)
[#1694](https://github.com/OpenImageIO/oiio/pull/1694) (by Mitch Prater)
- *docs*: Amend the filmography
[#1695](https://github.com/OpenImageIO/oiio/pull/1695)
- *docs*: Fix incorrect links in CONTRIBUTING
[#1688](https://github.com/OpenImageIO/oiio/pull/1688)
Release 1.12.12.0 -- 1 May 2023 (compared to 1.12.11.0)
--------------------------------------------------------
* New ShadingSystem getattribute query for shader groups: "attribute_types"
retrieves a pointer to the array of TypeDesc values describing the
attributes retrieved by existing "attributes_needed" and "attribute_scopes".
#1650
* Fix a bug with binding userdata when it's used by more than one shader
within the group and they disagree about whether derivatives are needed when
retrieving the attribute. #1673
Release 1.12.11.0 -- 5 Apr 2023 (compared to 1.12.10.0)
--------------------------------------------------------
* Build: Add Qt 6.x compatibility (Qt is only used for `osltoy`). #1655
* Build: more careful about paths to look for LLVM. #1656
* Build: Fix Cuda compilation flags for LLVM 15. #1659
* Notice: OSL does not yet build properly against the newly release LLVM 16.
You must use LLVM 9-15. For Mac users who get their llvm from Homebrew,
please be aware that Homebrew has changed its default llvm to 16, so you'll
need to `brew install llvm@14` and make your OSL CMake define:
`-DLLVM_ROOT=/usr/local/opt/llvm@14`
Release 1.12.10.0 -- 1 Mar 2023 (compared to 1.12.9.0)
--------------------------------------------------------
* feat(testrender): Modify testrender so that it correctly sets raytype to
"camera" for camera rays, "shadow" for shadow rays, and "diffuse" for all
secondary rays. Also rerun the shades for background shader group on the
camera rays rather than use the cached map. This helps the MaterialX project
use testrender for certain unit tests and verification. #1648 #1649
* feat: Expose llvm groupdata size as a shadergroup attribute
"llvm_groupdata_size". #1642
* fix: Crash could result from uncaught exception in OpenColorIO when calling
transformc with derivatives for color spaces that require OCIO. #1646
* fix: certain uses of fmod() in shaders could fail to generate LLVM code
correctly, due to a missing implementation for the fmod(triple,float)
varieties. #1643
* build: Change snprintf formatting to satisfy some compilers. #1640
* CI: Fix broken Mac ci. #1647
Release 1.12.9.0 -- 1 Feb 2023 (compared to 1.12.8.0)
-------------------------------------------------------
* Remove unnecessary setting of locale::global. #1630
* Batch shading: Fix bug with masked wide closure generation. #1637
* Make sure ReParameter() has the same relaxed type checking rules as
Parameter(). Before, it was stricter about type conversion. #1639
* Windows: Fix some GPU build errors. #1638
Release 1.12.8.0 -- 3 Jan 2023 (compared to 1.12.7.1)
-------------------------------------------------------
* Remove dependency on OptiX SDK for building core OSL with OptiX support.
You can now build OSL with OptiX support enabled even if you don't have the
OptiX SDK headers present at build time. But you will still need them to
build your OptiX-based application that uses OSL for GPU rendering. #1627
* Batch mode: fix issue with closure keyword parameters. #1620
* Batch mode: fix crash when adding a default initialized closure. #1624
* Batch mode: Fix support for closures with array types. #1630
* testshade: better testing of all closure parameter types. #1621
* Fix various CI breaks as dependencies shifted. #1629 #1631 #1633
Release 1.12.7.1 -- 1 Dec 2022 (compared to 1.12.7.0)
-------------------------------------------------------
* Add clangSupport library as dependency to fix linker error on some
platforms. #1613
* Test against OpenColorIO 2.2. #1616
* Build: Fix how version overrides work to reduce the chance of user mistakes.
#1617
Release 1.12.7.0 -- 1 Nov 2022 (compared to 1.12.6.2)
-------------------------------------------------------
* Optix: Change naming of certain compiler-generated constants in a way that
improves use of the PTX cache. #1570
* Batch: Fix uninitialized members in ReadEvent internals. #1575
* `testshade --help` now prints TextureSystem options and hardware info. #1584
* oslc: Fix memory leak in ASTvariable_declaration. #1576
* Fix memory leaks in light path expression code. #1593 #1594
* Include the immintrin.h header only when needed. #1605
* icx: Improvements to fix problems exposed by new icx 2022.2 compiler. #1601
* Testing: CMake cache variables to control the testing timeout length. #1571
* CI: Add a dynamic analysis test using address and leak sanitizers. #1581
* CI: Now using SonarCloud static analysis. #1551
* CI: Many improvements in testing code coverage #1607
* CI: Make sure to run pointcloud tests when partio is found. #1611
* Developers: platform.h now defines OSL_ALLOCA macro. #1589
* Developers: platform.h now defines OSL::bitcast utility. #1610
Release 1.12 -- 1 Oct 2022 (compared to 1.11)
----------------------------------------------
+35 -12
View File
@@ -2,21 +2,28 @@
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
cmake_minimum_required (VERSION 3.12)
cmake_minimum_required (VERSION 3.15)
set (OSL_VERSION "1.13.7.0")
set (OSL_VERSION_OVERRIDE "" CACHE STRING
"Version override (use with caution)!")
mark_as_advanced (OSL_VERSION_OVERRIDE)
if (OSL_VERSION_OVERRIDE)
set (OSL_VERSION ${OSL_VERSION_OVERRIDE})
endif ()
set (OSL_VERSION "1.13.1.0" CACHE STRING "Version")
project (OSL VERSION ${OSL_VERSION}
LANGUAGES CXX C
HOMEPAGE_URL "https://github.com/AcademySoftwareFoundation/OpenShadingLanguage")
set (PROJ_NAME ${PROJECT_NAME}) # short name
string (TOLOWER ${PROJ_NAME} PROJ_NAME_LOWER) # short name lower case
string (TOUPPER ${PROJ_NAME} PROJ_NAME_UPPER) # short name upper case
set (PROJECT_VERSION_RELEASE_TYPE "dev" CACHE STRING
set (PROJECT_VERSION_RELEASE_TYPE "" CACHE STRING
"Build type, for example: dev, beta2, RC1 (empty string for normal release)")
set (${PROJECT_NAME}_VERSION_RELEASE_TYPE ${PROJECT_VERSION_RELEASE_TYPE})
set (PROJECT_AUTHORS "Contributors to the Open Shading Language project")
option (${PROJECT_NAME}_SUPPORTED_RELEASE
"Set ON for supported release branch, OFF for master" OFF)
"Set ON for supported release branch, OFF for master" ON)
if (${PROJECT_NAME}_SUPPORTED_RELEASE)
set (${PROJECT_NAME}_DEV_RELEASE OFF)
else ()
@@ -81,6 +88,11 @@ include (GNUInstallDirs)
option (VERBOSE "Print lots of messages while compiling" OFF)
if (VERBOSE)
set (CMAKE_MESSAGE_LOG_LEVEL "VERBOSE" CACHE STRING "CMake log level to display")
else ()
set (CMAKE_MESSAGE_LOG_LEVEL "STATUS" CACHE STRING "CMake log level to display")
endif ()
set (OSL_LIBNAME_SUFFIX "" CACHE STRING
"Optional name appended to ${PROJECT_NAME} libraries that are built")
option (OSL_BUILD_TESTS "Build the unit tests, testshade, testrender" ON)
@@ -91,7 +103,8 @@ else ()
endif ()
option (OSL_BUILD_PLUGINS "Bool OSL plugins, for example OIIO plugin" ON)
option (OSL_BUILD_SHADERS "Build shaders" ON)
option (USE_OPTIX "Include OptiX support" OFF)
option (OSL_USE_OPTIX "Include OptiX support" OFF)
message(STATUS "OSL_USE_OPTIX: ${OSL_USE_OPTIX}")
set (OPTIX_EXTRA_LIBS CACHE STRING "Extra lib targets needed for OptiX")
set (CUDA_EXTRA_LIBS CACHE STRING "Extra lib targets needed for CUDA")
set (CUDA_TARGET_ARCH "sm_60" CACHE STRING "CUDA GPU architecture (e.g. sm_50)")
@@ -100,6 +113,7 @@ set (OSL_SHADER_INSTALL_DIR "${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT_NAME}/shade
set (OSL_PTX_INSTALL_DIR "${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT_NAME}/ptx"
CACHE STRING "Directory where OptiX PTX files will be installed")
set (CMAKE_DEBUG_POSTFIX "" CACHE STRING "Library naming postfix for Debug builds (e.g., '_debug')")
option (OSL_USTRINGREP_IS_HASH "Always use ustringhash for strings" OFF)
set (OSL_NO_DEFAULT_TEXTURESYSTEM OFF CACHE BOOL "Do not use create a raw OIIO::TextureSystem")
@@ -119,14 +133,14 @@ if (OIIO_FMATH_SIMD_FRIENDLY)
add_definitions (-DOIIO_FMATH_SIMD_FRIENDLY=1)
endif ()
if (USE_OPTIX)
add_definitions ("-DOSL_USE_OPTIX=1")
endif ()
# Define OSL_INTERNAL symbol only when building OSL itself, will not be
# defined for downstream projects using OSL.
add_definitions (-DOSL_INTERNAL=1)
# To make sure we aren't relying on deprecated OIIO features, we define
# OIIO_DISABLE_DEPRECATED before including any OIIO headers.
add_definitions (-DOIIO_DISABLE_DEPRECATED=1)
# Set the default namespace. For symbol hiding reasons, it's important that
# the project name is a subset of the namespace name.
set (${PROJ_NAME}_NAMESPACE ${PROJECT_NAME} CACHE STRING
@@ -205,7 +219,7 @@ add_subdirectory (src/liboslnoise)
add_subdirectory (src/oslc)
add_subdirectory (src/oslinfo)
if (OSL_BUILD_TESTS)
if (OSL_BUILD_TESTS AND BUILD_TESTING)
add_subdirectory (src/testshade)
add_subdirectory (src/testrender)
endif ()
@@ -214,7 +228,7 @@ if (OSL_BUILD_PLUGINS)
add_subdirectory (src/osl.imageio)
endif ()
if (USE_QT AND Qt5_FOUND)
if (USE_QT AND (Qt5_FOUND OR Qt6_FOUND) AND NOT DISABLE_OSLTOY)
add_subdirectory (src/osltoy)
endif ()
@@ -280,13 +294,22 @@ configure_package_config_file ("${PROJECT_SOURCE_DIR}/src/cmake/Config.cmake.in"
install (FILES "${OSL_PROJECT_CONFIG}" "${OSL_VERSION_CONFIG}"
DESTINATION "${OSL_CONFIG_INSTALL_DIR}")
install (FILES src/cmake/llvm_macros.cmake DESTINATION cmake)
set (PERMISSION_FLAGS OWNER_EXECUTE OWNER_READ OWNER_WRITE
GROUP_EXECUTE GROUP_READ
WORLD_EXECUTE WORLD_READ)
install (FILES src/build-scripts/serialize-bc.py
DESTINATION build-scripts
PERMISSIONS ${PERMISSION_FLAGS})
# install targets files
install (EXPORT OSL_EXPORTED_TARGETS
DESTINATION ${OSL_CONFIG_INSTALL_DIR}
FILE ${OSL_TARGETS_EXPORT_NAME}
NAMESPACE ${PROJECT_NAME}::)
if (${PROJECT_NAME}_BUILD_TESTS AND PROJECT_IS_TOP_LEVEL)
if (PROJECT_IS_TOP_LEVEL AND BUILD_TESTING AND ${PROJECT_NAME}_BUILD_TESTS)
osl_add_all_tests()
endif ()
+71 -121
View File
@@ -19,11 +19,10 @@ Contributors should be reading the osl-dev mail list:
You can sign up for the mail list on your own using the link above.
We also have an `openshadinglanguage` channel on the
[ASWF Slack](https://slack.aswf.io/). But note that the Slack channel is
not archived, so while it's ok for fleeting comments, it is unreliable as
a permanent repository of useful information. Serious discussions that are
we would want to refer to over time should be sent to the mail list instead.
The [ASWF Slack](https://slack.aswf.io/) has an `openshadinglanguage` channel.
Sign up for the Slack on your own, then under "channels", select "browse
channels" and you should see the openshadinglanguage channel (among those of
the other projects and working groups).
Bug Reports and Issue Tracking
@@ -55,15 +54,16 @@ Contributor License Agreement (CLA) and Intellectual Property
To protect the project -- and the contributors! -- we do require a
Contributor License Agreement (CLA) for anybody submitting changes.
* [Corporate CLA](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/ASWF/OSL-CLA-corporate.md)
* [Corporate CLA](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/blob/main/ASWF/CLA-corporate.md) :
If you are writing the code as part of your job, or if there is any
possibility that your employers might think they own any intellectual
property you create. This needs to be executed by someone who has
signatory power for the company.
* [Individual]((https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/ASWF/OSL-CLA-individual.md)).
If you are an individual writing the code on your own time and you're SURE
you are the sole owner of any intellectual property you contribute.
* [Individual CLA](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/blob/main/ASWF/CLA-individual.md) :
If you are an individual writing the code on your own time, using your own
equipment, and you're SURE you are the sole owner of any intellectual
property you contribute.
The easiest way to sign CLAs is digitally [using EasyCLA](https://corporate.v1.easycla.lfx.linuxfoundation.org).
Companies who prefer not to use the online tools may sign, scan, and email
@@ -79,8 +79,7 @@ Please note that these CLAs are based on the Apache 2.0 CLAs, and differ
minimally, only as much as was required to correctly describe the EasyCLA
process and our use of a CLA manager.
** Contribution sign off
**Contribution sign off**
ASWF requires the use of the [Developer’s Certificate of Origin 1.1
(DCO)](https://developercertificate.org/), which is the same mechanism that
@@ -115,7 +114,9 @@ repository. The protocol is like this:
own repository on GitHub, and then clone it to get a repository on your
local machine.
2. Edit, compile, and test your changes.
2. Edit, compile, and test your changes. Run clang-format (see the
instructions on coding style below). Our current formatting standard,
as checked by our CI, uses clang-format 17.0.
3. Push your changes to your fork (each unrelated pull request to a separate
"topic branch", please).
@@ -127,30 +128,26 @@ component that deserves extended discussion or debate among the wider OSL
community, then it may be prudent to email osl-dev pointing everybody to
the pull request URL and discussing any issues you think are important.
6. The reviewer will look over the code and critique on the "comments" area,
6. All pull requests automatically launch CI jobs on GitHub Actions to
ensure that the build completes and that the tests suite runs correctly, for
a variety of platform, compiler, library, and flag combinations. The status
of the CI tests for your PR will be displayed on the GitHub PR page. We will
not accept PRs that don't build cleanly or pass the existing testsuite.
7. The reviewer will look over the code and critique on the "comments" area,
or discuss in email. Reviewers may ask for changes, explain problems they
found, congratulate the author on a clever solution, etc. But until somebody
says "LGTM" (looks good to me), the code should not be committed. Sometimes
this takes a few rounds of give and take. Please don't take it hard if your
first try is not accepted. It happens to all of us.
7. After approval, one of the senior developers (with commit approval to the
8. After approval, one of the senior developers (with commit approval to the
official main repository) will merge your fixes into the master branch.
Coding Style
------------
There are two overarching rules:
1. When making changes, conform to the style and conventions of the surrounding code.
2. Strive for clarity, even if that means occasionally breaking the
guidelines. Use your head and ask for advice if your common sense seems to
disagree with the conventions.
Below we try to enumerate the guidelines embodied in the code.
#### File conventions
C++ implementation should be named `*.cpp`. Headers should be named `.h`.
@@ -158,115 +155,73 @@ All headers should contain
#pragma once
All source files should begin with these three lines:
All source files should begin with the copyright and license, which can be
found in the [LICENSE](LICENSE) file (or cut and pasted from any other other source
file). Two notes on this:
// Copyright Contributors to the Open Shading Language project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
* For NEW source files, please change the copyright year to the present. DO
NOT edit existing files only to update the copyright year, it just creates
pointless deltas and offers no increased protection.
as a comment in the syntax of whatever source code is used in that file (for
example, for python or shell files, use `#` rather than `//`).
* Occasionally a file contains substantial code from another project
and will also list its copyright. Do NOT copy that notice to any new files,
it really only applies to the particular file in which it appears.
Occasionally a file may contain substantial code from another project and will
also list its original copyright and license information. Do NOT alter that
notice or copy it to any new files, it really only applies to the particular
file in which it appears.
#### Formatting
We use clang-format to enforce formatting rules for the vast majority of the
code base. It is automatically run during CI and is a CI failure if the code
does not conform. There are, however, parts of the code base that are not
clang-formatted, either because we have not yet put them under the
clang-format regime, or because individual modules were deemed to be less
clear with clang-format than with hand formatting.
We use [clang-format](https://clang.llvm.org/docs/ClangFormat.html) v17
to uniformly format our source code prior to PR submission. Make sure that
clang-format is installed on your local machine, and just run
For non-clang-format regions of code, NEVER alter somebody else's code to
reformat just because you found something that violates the rules. Let the
group/author/leader know, and resist the temptation to change it yourself.
make clang-format
Each line of text in your code should be at most 80 characters long.
Exceptions are allowed for those rare cases where letting a line be longer
(and wrapping on an 80-character window) is actually a better and clearer
alternative than trying to split it into two lines. Sometimes this happens,
but it's extremely rare.
and it will automatically reformat your code according to the configuration
file found in the `.clang-format` file at the root directory of the OSL
source code checkout.
Indent 4 spaces at a time, and use actual spaces, not tabs. For files that
must use tabs for some reason, tabs should always be on 8's. Most editors
have a setting that forces indentations to be spaces. With emacs, you can do
this:
One of the CI test matrix entries runs clang-format and fails if any
diffs were generated (that is, if any of your code did not 100% conform to
the `.clang-format` formatting configuration). If it fails, clicking on that
test log will show you the diffs generated, so that you can easily correct
it on your end and update the PR with the formatting fixes.
(setq c-default-style "bsd")
(setq-default indent-tabs-mode nil)
If you don't have clang-format set up on your machine, and your patch is not
very long, you may find that it's more convenient to just submit it and hope
for the best, and if it doesn't pass the CI test, look at the diffs in the log
for the "clang-format" CI run and make the corrections by hand and then submit
an update to the patch (i.e. relying on CI to run clang-format for you).
Opening brace on the same line as the condition or loop.
Because the basic formatting is automated by clang-format, we won't
enumerate the rules here.
One statement per line, except in rare cases where violating this rule makes
the code more clear.
For the occasional non-clang-format regions of code, NEVER alter somebody
else's code to reformat just because you found something that violates the
rules. Let the group/author/leader know, and resist the temptation to change
it yourself.
Three (3) consecutive empty lines between function or class method
implementations, one blank line between method declarations within a class
definition. Put a single blank line within a function if it helps to
visually separate different sequential tasks. Don't put multiple blank lines
in a row within a function, or blank lines right after an opening brace or
right before a closing brace. The goal is to use just enough white space to
help developers visually parse the code (for example, spotting at a glance
where new functions begin), but not so much as to spread it out or be
confusing.
Each line of text in your code, including comments, should be at most 80
characters long. Exceptions are allowed for those rare cases where letting a
line be longer (and wrapping on an 80-character window) is actually a better
and clearer alternative than trying to split it into two lines. Sometimes this
happens, but it's extremely rare.
For if, for, while, etc., put a space before the paren, but NOT inside the parens. For example:
We prefer three (3) consecutive empty lines between freestanding functions or
class definitions, one blank line between method declarations within a class
definition. Put a single blank line within a function if it helps to visually
separate different sequential tasks, but don't put multiple blank lines in a
row within a function, or blank lines right after an opening brace or right
before a closing brace. The goal is to use just enough white space to help
developers visually parse the code (for example, spotting at a glance where
new functions begin), but not so much as to spread it out or be confusing.
if (foo) // Yes
if(foo) // No
if ( foo ) // No
Function calls should have a space between the function name and the opening
parenthesis, NO space inside the parenthesis, except for a single blank
space between each argument. For example:
x = foo(a, b); // Yes
x = foo ( a, b ); // No
x = foo (a,b); // No
Function declarations: function names should begin at column 0 for a full
function definition. (It's ok to violate this rule for very short inline
functions within class definitions.)
Here is a short code fragment that shows some of these rules in action:
static int
function(int a, int b)
{
int x = a + b;
if (a == 0 || b == 0) {
x += 1;
x *= 4;
} else {
x -= 3;
}
for (int i = 0; i < 3; ++i) {
x += a * i;
x *= foo(i); // function call
}
return x;
}
Don't ever reformat, re-indent, change whitespace, or make any other such
changes to working code. If you're adding just a few lines or fixing a bug
in existing code, stick to the style of the surrounding code. In very rare
circumstances, and with consensus of the group, reformatting is sometimes
helpful to improve code readability, but it should be done as a separate
formatting-only checkin.
#### Identifiers
In general, classes and templates should start with upper case and capitalize new words:
class CustomerList;
In general, local variables should start with lower case.
In general, classes and templates should start with upper case and
capitalize new words: `class CustomerList;` In general, local variables
should start with lower case. Macros should be `ALL_CAPS`, if used at all.
If your class is extremely similar to, or modeled after, something in the
standard library, Boost, or something else we interoperate with, it's ok to
@@ -278,8 +233,6 @@ were standards.
template <class T> shared_ptr;
class scoped_mutex;
Macros should be ALL_CAPS, if used at all.
Names of data should generally be nouns. Functions/methods are trickier: a
the name of a function that returns a value but has no side effects should
be a noun, but a procedure that performs an action should be a verb.
@@ -310,7 +263,7 @@ Prefer C++11 `std` rather than Boost or other third party libraries, where
both can do the same task.
If you see a third party library already used as a dependency (such as OIIO,
Boost, Ilmbase, or LLVM), feel free to any of its public features in OSL
Boost, Imath, or LLVM), feel free to any of its public features in OSL
internals (provided those features are present in the minimum version of
that library that we support).
@@ -334,9 +287,6 @@ protected members of classes), please use Doxygen-style comments. They looks
like this:
/// Explanation of a class. Note THREE slashes!
/// Also, you need at least two lines like this. If you don't have enough
/// for two lines, make one line blank like this:
///
class myclass {
....
float foo; ///< Doxygen comments on same line look like this
+29 -16
View File
@@ -12,16 +12,16 @@ Dependencies
OSL requires the following dependencies or tools.
NEW or CHANGED dependencies since the last major release are **bold**.
* Build system: [CMake](https://cmake.org/) 3.12 or newer (tested through 3.24)
* Build system: [CMake](https://cmake.org/) **3.15 or newer** (tested through 3.27)
* A suitable C++14 or C++17 compiler to build OSL itself, which may be any of:
- GCC 6.1 or newer (tested through gcc 12.1)
- Clang 3.4 or newer (tested through clang 15)
- Clang 3.4 or newer (tested through clang 17)
- Microsoft Visual Studio 2017 or newer
- Intel C++ compiler icc version 17 or newer or LLVM-based icx compiler
version 2022 or newer.
* **[OpenImageIO](http://openimageio.org) 2.3 or newer** (tested through 2.4)
* **[OpenImageIO](http://openimageio.org) 2.4 or newer** (tested through 2.5 and master)
OSL uses OIIO both for its texture mapping functionality as well as
numerous utility classes. If you are integrating OSL into an existing
@@ -40,32 +40,38 @@ NEW or CHANGED dependencies since the last major release are **bold**.
$OpenImageIO_ROOT/lib to be in your LD_LIBRARY_PATH (or
DYLD_LIBRARY_PATH on OS X).
* [LLVM](http://www.llvm.org) 9, 10, 11, 12, 13, 14, or 15, including
* [LLVM](http://www.llvm.org) 9, 10, 11, 12, 13, 14, 15, 16, or 17, including
clang libraries.
* (optional) For GPU rendering on NVIDIA GPUs:
* [OptiX](https://developer.nvidia.com/rtx/ray-tracing/optix) 7.0 or higher.
* [Cuda](https://developer.nvidia.com/cuda-downloads) 8.0 or higher.
* [Cuda](https://developer.nvidia.com/cuda-downloads) 9.0 or higher. It is
recommended that you use 11.0 or higher.
* [Boost](https://www.boost.org) 1.55 or newer (tested through boost 1.80)
* [Ilmbase or Imath](https://github.com/AcademySoftwareFoundation/openexr) 2.3
or newer (recommended: 2.4 or higher; tested through 3.1)
* [Boost](https://www.boost.org) 1.55 or newer (tested through boost 1.84)
* [Ilmbase or Imath](https://github.com/AcademySoftwareFoundation/Imath) 2.4
or newer (recommended: 3.1 or higher; tested through 3.2)
NOTE: It is likely that 1.13 is the last release that will support
Imath/OpenEXR 2.x.
* [Flex](https://github.com/westes/flex) 2.5.35 or newer and
[GNU Bison](https://www.gnu.org/software/bison/) 2.7 or newer.
Note that on some MacOS/xcode releases, the system-installed Bison is too
old, and it's better to install a newer Bison (via Homebrew is one way to
do this easily).
* [PugiXML](http://pugixml.org/)
* [PugiXML](http://pugixml.org/) >= 1.8 (we have tested through 1.13).
* (optional) [Partio](https://www.disneyanimation.com/technology/partio.html)
If it is not found at build time, the OSL `pointcloud` functions will not
be operative.
* (optional) Python: If you are building the Python bindings or running the
testsuite:
* Python >= 2.7 (tested against 2.7, 3.7, 3.8, 3.9, 3.10)
* pybind11 >= 2.4.2 (Tested through 2.10)
* Python >= 2.7 (tested against 2.7, 3.7, 3.8, 3.9, 3.10, 3.11)
NOTE: It is likely that 1.13 is the last release that will support
Python 2.7.
* pybind11 >= 2.4.2 (Tested through 2.11. Note that pybind11 v2.10+ does
not support Python < 3.6.)
* NumPy
* (optional) Qt >= 5.6 (tested through 5.15). If not found at build time,
the `osltoy` application will be disabled.
* (optional) Qt5 >= 5.6 or Qt6 (tested Qt5 through 5.15 and Qt6 through 6.6).
If not found at build time, the `osltoy` application will be disabled.
@@ -91,9 +97,16 @@ Here are the steps to check out, build, and test the OSL distribution:
options, and note that 'make nuke' will blow everything away for the
freshest possible compile.
NOTE: If the build breaks due to compiler warnings which have been
elevated to errors, you can try "make clean" followed by
"make STOP_ON_WARNING=0", that create a build that will only stop for
You can also ignore the top level Makefile wrapper, and instead use
CMake directly:
cmake -B build -S .
cmake --build build --target install
NOTE: If the build breaks due to compiler warnings which have been elevated
to errors, you can try "make clean" followed by "make STOP_ON_WARNING=0",
or if using cmake directly, add `-DSTOP_ON_WARNING=0` to the cmake
configuration command. That will create a build that will only stop for
full errors, not warnings.
4. After compilation, you'll end up with a full OSL distribution in
+6 -3
View File
@@ -46,7 +46,7 @@ INSTALL_PREFIX ?= ${working_dir}/${dist_dir}
VERBOSE ?= ${SHOWCOMMANDS}
ifneq (${VERBOSE},)
MY_MAKE_FLAGS += VERBOSE=${VERBOSE}
MY_CMAKE_FLAGS += -DVERBOSE:BOOL=${VERBOSE}
MY_CMAKE_FLAGS += -DVERBOSE:BOOL=${VERBOSE} --log-level=VERBOSE
ifneq (${VERBOSE},0)
MY_NINJA_FLAGS += -v
TEST_FLAGS += -V
@@ -209,7 +209,10 @@ ifneq (${BUILD_MISSING_DEPS},)
endif
ifneq (${USE_OPTIX},)
MY_CMAKE_FLAGS += -DUSE_OPTIX:BOOL=${USE_OPTIX}
MY_CMAKE_FLAGS += -DOSL_USE_OPTIX:BOOL=${USE_OPTIX}
endif
ifneq (${OSL_USE_OPTIX},)
MY_CMAKE_FLAGS += -DOSL_USE_OPTIX:BOOL=${OSL_USE_OPTIX}
endif
ifneq (${USE_PYTHON},)
@@ -397,7 +400,7 @@ help:
@echo " USE_SIMD=arch Build with SIMD support (comma-separated choices:"
@echo " 0, sse2, sse3, ssse3, sse4.1, sse4.2, f16c,"
@echo " avx, avx2, avx512f)"
@echo " USE_OPTIX=1 Build the OptiX test renderer"
@echo " OSL_USE_OPTIX=1 Build the OptiX test renderer"
@echo " USE_BATCHED=targets Build batched SIMD execution of shaders for (comma-separated choices:"
@echo " 0, b8_AVX, b8_AVX2, b8_AVX2_noFMA,"
@echo " b8_AVX512, b8_AVX512_noFMA,"
+76 -27
View File
@@ -1,7 +1,7 @@
<div align="center">
<img src="https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/blob/main/src/doc/Figures/osl-short.png" width=256 height=128>
<img src="ASWF/logos/openshadinglanguage-stacked-Shaded.png">
<H1>Open Shading Language</H1>
<!-- <H1>Open Shading Language</H1> -->
</div>
[![Open Shading Language Reel 2020](http://img.youtube.com/vi/nmwMz1YnGPA/0.jpg)](https://www.youtube.com/watch?v=nmwMz1YnGPA "Open Shading Language Reel 2020")
@@ -9,7 +9,7 @@
[![Build Status](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/workflows/CI/badge.svg)](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/actions)
[![License](https://img.shields.io/badge/license-BSD%203--Clause-blue.svg?style=flat-square)](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/LICENSE.md)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/3061/badge)](https://bestpractices.coreinfrastructure.org/projects/3061)
[![Documentation Status](https://readthedocs.org/projects/open-shading-language/badge/?version=main)](https://open-shading-language.readthedocs.io/en/main/?badge=main)
Introduction
@@ -219,14 +219,15 @@ inferred from public sources, or that we've been told is ok to list here. If
an OSL-using project is missing and it's not a secret, just email the OSL
project leader or submit a PR with edits to this file.*
Renderers and other tools with OSL support (in approximate order of
adding OSL support):
* Sony Pictures Imageworks: in-house "Arnold" renderer
### Renderers and other production tools with OSL support
(In approximate order of adding OSL support)
* [Sony Pictures Imageworks: in-house "Arnold" renderer](https://dl.acm.org/doi/10.1145/3180495)
* [Blender/Cycles](https://docs.blender.org/manual/en/dev/render/shader_nodes/osl.html)
* [Chaos Group: V-Ray](https://www.chaosgroup.com/)
* [Pixar: PhotoRealistic RenderMan RIS](https://renderman.pixar.com)
* [Isotropix: Clarisse](http://www.isotropix.com/clarisse)
* [Isotropix: Angie](http://www.isotropix.com/angie)
* Isotropix: [Clarisse iFX](https://www.isotropix.com/products/clarisse/ifx) / [Clarisse BUiLDER](https://www.isotropix.com/products/clarisse/builder) / [Angie](https://www.isotropix.com/products/angie)
* [Autodesk Beast](http://www.autodesk.com/products/beast/overview)
* [Appleseed](http://appleseedhq.net)
* [Animal Logic: Glimpse renderer](https://www.fxguide.com/featured/a-glimpse-at-animal-logic/)
@@ -237,7 +238,13 @@ adding OSL support):
* [Autodesk: 3DS Max 2019](https://help.autodesk.com/view/3DSMAX/2019/ENU/?guid=__developer_3ds_max_sdk_features_rendering_osl_html)
* [Maxon: Redshift](https://www.maxon.net/en/redshift)
Films using OSL (grouped by year of release date):
### Significant work using OSL, grouped by year of release date:
(Here we are considering "significant work" to mean a feature film released
theatrically or on a major streaming platform, TV/streaming series heavily
featuring visual effects or animation, or short films that have won or been
nominated for major awards.)
* **(2012)**
Men in Black 3, The Amazing Spider-Man, Hotel Transylvania
* **(2013)**
@@ -272,6 +279,7 @@ Films using OSL (grouped by year of release date):
Ghostbusters,
Star Trek Beyond,
Suicide Squad,
Kubo and the Two Strings,
Kingsglaive: Final Fantasy XV,
Storks,
Miss Peregrine's Home for Peculiar Children,
@@ -306,7 +314,7 @@ Films using OSL (grouped by year of release date):
* **(2018)**
Peter Rabbit,
Black Panther,
Annnihilation,
Annihilation,
Red Sparrow,
Pacific Rim Uprising,
Avengers Infinity War,
@@ -354,7 +362,8 @@ Films using OSL (grouped by year of release date):
Richard Jewell,
Game of Thrones (S8),
Lost in Space (S1),
Togo
Togo,
Missing Link
* **(2020)**
Underwater,
Birds of Prey,
@@ -370,7 +379,9 @@ Films using OSL (grouped by year of release date):
Over the Moon,
Wonder Woman 1984,
Soul,
The Mandalorian (S2)
The Mandalorian (S2),
The Boys (S2),
Umbrella Academy (S2)
* **(2021)**
Chaos Walking,
Peter Rabbit 2: The Runaway,
@@ -383,6 +394,7 @@ Films using OSL (grouped by year of release date):
F9,
Vivo,
Jungle Cruise,
Cinderella,
Dune,
No Time To Die,
Ron's Gone Wrong,
@@ -390,8 +402,9 @@ Films using OSL (grouped by year of release date):
Last Night in Soho,
Ghostbusters: Afterlife,
Spider-Man 3: No Way Home,
Matrix Resurrections
* **(2022 / upcoming)**
Matrix Resurrections,
Sing 2
* **(2022)**
Hotel Transylvania 4: Transformania,
Death on the Nile,
Uncharted,
@@ -404,11 +417,26 @@ Films using OSL (grouped by year of release date):
Thor: Love and Thunder,
The Sea Beast,
DC League of Super Pets,
Minions: Rise of Gru,
Bullet Train,
Slumberland,
Glass Onion,
Archive 81 (series),
Moon Night (series),
Obi-Wan Kenobi (series),
The Boys (S3),
Andor (S1)
* **(2023 / upcoming)**
Ant-Man and the Wasp: Quantumania,
The Mandalorian S3,
The Magician's Elephant,
Super Mario Bros Film,
Guardians of the Galaxy 3,
Spider-Man: Across the Spider-Verse,
Elemental,
...
Building and Installation
-------------------------
@@ -424,6 +452,24 @@ The OSL language specification can be found at
distribution) or in the share/doc/OSL/osl-languagespec.pdf file of an
installed binary distribution.
[Experimental OSL Documentation on ReadTheDocs](https://open-shading-language.readthedocs.io/)
This will be the future documentation. It's probably as complete as the PDF,
but it needs some proofreading, so the PDF is still considered the
authoritative source for now. But some time soon, the old PDF specification
will be deprecated in favor of
this online documentation.
<!-- is the best place to start if you are interested in how to use OSL,
its APIs. -->
There is also a [PDF
version](https://readthedocs.org/projects/open-shading-language/downloads/pdf/latest/).
For those interested in learning to program shaders in OSL, there is the
[Siggraph 2022 Educator's Forum](https://dl.acm.org/doi/proceedings/10.1145/3532724)
[OSL Shaders for RenderMan](https://dl.acm.org/doi/abs/10.1145/3532724.3535604) course,
which uses RenderMan in the examples and
[Supplementary Materials](https://github.com/LaikaStudios/OSLShadersForRenderMan),
but which is primarily about shader writing in OSL.
Contact & reporting problems
----------------------------
@@ -480,19 +526,22 @@ The current project leadership is documented in the
Many people have contributed features, bug fixes, and other changes to OSL
over the years: Steve Agland, Shane Ambler, Martijn Berger, Farchad
Bidgolirad, Nicholas Bishop, Solomon Boulos, Stefan Bruens, Stefan Büttner,
Matthaus G. Chajdas, Clark Chen, Alejandro Conty, Dieter De Baets, Thomas
Dinges, Mads Drøschler, Luke Emrose, Louis Feng, Mark Final, Henri Fousse,
Stephen Friedman, Syoyo Fujita, Tim Grant, Larry Gritz, Nicolas Guiard, Euan
Haahr, Derek Haase, Sven-Hendrik Haase, John Haddon, Niklas Harrysson, Daniel
Heckenberg, Adrien Herubel, Thiago Ize, Matt Johnson, Ronan Keryell, Chris
Kulla, Elvic Liang, Max Liani, Adam Martinez, John Mertic, Bastien Montagne,
Steena Monteiro, Alexis Oblet, Erich Ocean, Mikko Ohtamaa, Jino Park, Alexei
Pawlow, Jay Reynolds, Declan Russell, Benoit Ruiz, Patrick Scheibe, Alex
Schworer, Jonathan Scruggs, Sergey Sharybin, Sandip Shukla, Cliff Stein,
Bidgolirad, Nicholas Bishop, Curtis Black, Rasmus Bonnedal, Solomon Boulos,
Stefan Bruens, Stefan Büttner, Matthaus G. Chajdas, Clark Chen, Alejandro
Conty, Damien Courtois, Dieter De Baets, Thomas Dinges, Daniel Dresser, Mads
Drøschler, Peter Ellerington, Luke Emrose, Louis Feng, Mark Final, Henri
Fousse, Stephen Friedman, Syoyo Fujita, Tim Grant, Larry Gritz, Nicolas
Guiard, Euan Haahr, Derek Haase, Sven-Hendrik Haase, John Haddon, Niklas
Harrysson, Daniel Heckenberg, Chris Hellmuth, Adrien Herubel, Dan Horák,
Thiago Ize, Matt Johnson, Ronan Keryell, Chris Kulla, Elvic Liang, Max Liani,
Adam Martinez, John Mertic, Bastien Montagne, Steena Monteiro, Patrick Mours,
Alexis Oblet, Erich Ocean, Mikko Ohtamaa, Jino Park, Alexei Pawlow, Jay
Reynolds, Declan Russell, Benoit Ruiz, Patrick Scheibe, Alex Schworer,
Jonathan Scruggs, Sergey Sharybin, Mark Sisson, Sandip Shukla, Cliff Stein,
Stephan Steinbach, Luya Tshimbalanga, Esteban Tovagliari, Brecht Van Lommel,
Alexander von Knorring, Alex Wells, Roman Zulak. (Listed alphabetically; if
we've left anybody out, it is inadvertent, please let us know.)
Alexander von Knorring, Aidan Welch, Alex Wells, Roman Zulak. (Listed
alphabetically; if we've left anybody out, it is inadvertent, please let us
know.)
We cannot possibly express sufficient gratitude to the managers at Sony
Pictures Imageworks who allowed this project to proceed, supported it
@@ -0,0 +1,112 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the Open Shading Language Project. -->
Inlining Options for OptiX and CUDA
===================================
When compiling shaders for OptiX and CUDA (and in general), there is a tradeoff
between compile speed and shade-time performance. The LLVM optimizer generally
does a good job of balancing these concerns, but there might be cases where a
renderer can give additional hints to the optimizer to tip the balance one way
or the other.
Aggressive inlining can increase the run-time performance, but can negatively
impact the compile speed. Inlining can be very helpful with small functions
where the function call overhead tends to dwarf the useful instructions, so it
is important to inline such functions when possible.
Choosing to __not__ inline certain functions (e.g., very large noise functions)
allows them to be excluded from the module prior to running the LLVM optimizer
and JIT engine, which can greatly improve the compile time. This is particularly
beneficial when a function is not likely to be inlined anyway; removing such
large functions from the module prior to optimization can speed up compilation
considerably without affecting the generated PTX.
ShadingSystem Attributes
------------------------
There are a number of `ShadingSystem` attributes to help control the inlining
behavior. The default settings should work well in most circumstances, but they
can be adjusted to favor compile speed over shade-time performance, or vice
versa.
* `optix_no_inline_thresh`: Don't inline functions greater-than or equal-to the
threshold. This allows them to be excluded from the module prior to
optimization, which reduces the size of module and can greatly speed up the
optimization and JIT stages.
* `optix_force_inline_thresh`: Force inline functions less-than or equal-to the
threshold. This tends to be most helpful with relatively low values, < 30.
* `optix_no_inline`: Don't inline any functions. Offers the best compile times
at the expense of shade-time performance. This option is not recommended, but is
included for benchmarking and tuning purposes.
* `optix_no_inline_layer_funcs`: Don't inline the shader layer functions. This
can moderately improve compile times at the expense of shade-time performance.
* `optix_merge_layer_funcs`: Allow layer functions that are only called once to
be merged into their caller, even if `optix_no_inline_layer_funcs` is set. This
can help restore some of the shade-time performance lost by enabling
`optix_no_inline_layer_funcs`.
* `optix_no_inline_rend_lib`: Don't inline any functions defined in the
renderer-supplied `rend_lib` module. As an alternative, the renderer can simply
not supply the LLVM bitcode for the `rend_lib` module to the `ShadingSystem`.
Inline/Noinline Function Registration
-------------------------------------
In addition to the `ShadingSystem` attributes, individual functions can be
registered with the `ShadingSystem` as `inline` or `noinline`. Functions can
be unregistered to restore the default inlining behavior. This registration
takes precedence over the `ShadingSystem` inlining attributes, which allows
very fine-grained control when needed.
```C++
// Register
shadingsys->register_inline_function(ustring("osl_abs_ff"));
shadingsys->register_noinline_function(ustring("osl_gabornoise_dfdfdf"));
// Unregister
shadingsys->unregister_inline_function(ustring("osl_abs_ff"));
shadingsys->unregister_noinline_function(ustring("osl_gabornoise_dfdfdf"));
```
It might be best to prefer the `ShadingSystem` attributes to control the inlining
behavior, and to strategically register functions when it is known to be
beneficial through benchmarking and profiling.
Tuning and Analysis
-------------------
We have added a Python script (`src/build-scripts/analyze-ptx.py`) to help
identify functions that might be good candidates for inlining/noinling. This
script will generate a summary of the functions in the input PTX file, with a
list of all functions and their sizes in CSV format. It will also generate a
graphical reprensentation of the callgraph in DOT and PDF format.
An example tuning workflow might include the following steps:
1. Run `analyze-ptx.py` on the "shadeops" and "rend_lib" PTX files to generate
a list of the functions contained in those modules.
```bash
$ analyze_ptx.py shadeop_cuda.ptx
$ analyze_ptx.py rend_lib_myrender.ptx
```
2. Run `analyze-ptx.py` on the generated PTX for a representative shader:
```bash
$ analyze_ptx.py myshader.ptx
```
3. View the summary file (`myshader-summary.txt`) and the callgraph
(`myshader-callgraph.gv`) to deterimine which library functions were _not_
inlined. They will appear as boxes with a dashed outline in the callgraph.
In particular, be on the lookout for trivial functions (e.g., `osl_floor_ff`)
which have not been inlined. If such functions appear, that might be a sign
that the inline thresholds need to be adjusted, or that it might be
beneficial to register specific functions.
+11 -7
View File
@@ -33,7 +33,7 @@ endif # endif ${SP_OS}
MY_CMAKE_FLAGS += -DSP_OS=${SP_OS}
MY_CMAKE_FLAGS += -DSPI_COMPILER_PLATFORM=${SPI_COMPILER_PLATFORM}
MY_CMAKE_FLAGS += -DEXTRA_CPP_ARGS:STRING="-DOSL_SPI=1" -DOSL_SITE:STRING=spi
MY_CMAKE_FLAGS += -DOSL_SITE:STRING=spi
MY_CMAKE_FLAGS += -DSPI_TESTS=1
MY_CMAKE_FLAGS += -DOSL_NAMESPACE_INCLUDE_PATCH=1
REZ_PACKAGE_ROOT ?= /shots/spi/home/software/packages
@@ -147,14 +147,14 @@ ifeq (${SP_OS}, rhel7)
endif
# Cuda/OptiX
USE_OPTIX ?= 1
OSL_USE_OPTIX ?= 1
CUDA_VERSION ?= 11.1.1
OPTIX_VERSION ?= 7.2.0
# CUDA_TOOLKIT_ROOT_DIR = $(shell rez-env -b cuda-${CUDA_VERSION} ${SPI_COMPILER_PLATFORM} -c "echo '$CUDA_TOOLKIT_ROOT'")
CUDA_TOOLKIT_ROOT_DIR ?= /shots/spi/home/lib/arnold/rhel7/cuda_${CUDA_VERSION}
OptiX_ROOT ?= /shots/spi/home/lib/arnold/rhel7/optix_${OPTIX_VERSION}
OPTIXHOME = ${OptiX_ROOT}
MY_CMAKE_FLAGS += -DUSE_OPTIX=${USE_OPTIX} \
MY_CMAKE_FLAGS += -DOSL_USE_OPTIX=${OSL_USE_OPTIX} \
-DCUDA_TOOLKIT_ROOT_DIR=${CUDA_TOOLKIT_ROOT_DIR} \
-DCUDA_EXTRA_LIBS=${CUDA_EXTRA_LIBS} \
-DOPTIXHOME=${OPTIXHOME} -DOPTIX_EXTRA_LIBS=lzma
@@ -189,6 +189,10 @@ else ifeq (${platform}, macosx)
MY_CMAKE_FLAGS += \
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@15/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@15/bin/clang++
else ifeq (${COMPILER},clang16)
MY_CMAKE_FLAGS += \
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@16/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@16/bin/clang++
else ifeq (${COMPILER},clang)
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
else ifeq (${COMPILER},gcc)
@@ -196,13 +200,13 @@ else ifeq (${platform}, macosx)
else ifeq (${COMPILER},)
# default compiler is clang, taken from the LLVM directory
MY_CMAKE_FLAGS += \
-DCMAKE_C_COMPILER=${LLVM_DIRECTORY}/bin/clang \
-DCMAKE_CXX_COMPILER=${LLVM_DIRECTORY}/bin/clang++
-DCMAKE_C_COMPILER=${LLVM_ROOT}/bin/clang \
-DCMAKE_CXX_COMPILER=${LLVM_ROOT}/bin/clang++
else ifeq (${COMPILER},llvm)
# "llvm" means "use the clang from our llvm"
MY_CMAKE_FLAGS += \
-DCMAKE_C_COMPILER=${LLVM_DIRECTORY}/bin/clang \
-DCMAKE_CXX_COMPILER=${LLVM_DIRECTORY}/bin/clang++
-DCMAKE_C_COMPILER=${LLVM_ROOT}/bin/clang \
-DCMAKE_CXX_COMPILER=${LLVM_ROOT}/bin/clang++
endif
# end generic OSX
-3
View File
@@ -23,6 +23,3 @@ sonar.exclusions=src/include/OSL/Imath/*.h,src/build-scripts/*
# C/C++ analyzer properties
sonar.cfamily.build-wrapper-output=build/bw_output
sonar.cfamily.gcov.reportsPath=_coverage
sonar.cfamily.cache.enabled=true
sonar.cfamily.cache.path=/tmp/sonarcache
+413
View File
@@ -0,0 +1,413 @@
#!/usr/bin/env python3
# Copyright Contributors to the Open Shading Language project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
import getopt
import graphviz
import itertools
import os
import re
import sys
from collections import OrderedDict
from dataclasses import dataclass, field
from typing import Dict
#-------------------------------------------------------------------------------
# PTX parsing helpers
#-------------------------------------------------------------------------------
# pre-compile some regex patterns to speed up parsing
call_ptn = re.compile(r"^\s*(call\.uni).*$")
dec_ptn = re.compile(r"^\s*(\.pragma|\.extern|\.visible|\.func|\.local|\.global|\.reg|\.param|LBB[0-9_]+\:)(.*)$")
fn_ptn = re.compile(r"^(\.visible \.func|\.visible \.entry|\.weak \.func|\.func).*[\s]+([a-zA-Z0-9_]+)[\(\)]*$")
inst_ptn = re.compile(r"^\s*([@!%p0-9 ]*)([a-zA-Z0-9\.]+)\s*([a-zA-Z0-9\$\.,% _\[\]{}+-]+);.*$")
mem_ptn = re.compile(r"^\s*(st|ld).*;$")
ret_ptn = re.compile(r"^\s*(ret);.*$")
def get_func_name(line):
match = fn_ptn.match(line)
if match:
return match.group(2)
else:
return ""
def is_func_or_decl(line):
match = fn_ptn.match(line)
if match:
return True
else:
return False
def is_call_start(line):
if line.find("call.uni") != -1:
return True
else:
return False
def is_instruction(line):
match = call_ptn.match(line)
if match:
return True
if len(line) < 4:
return False
if not line.endswith(';'):
return False
match = dec_ptn.match(line)
if not match:
return True
else:
return False
def is_mem_inst(line):
match = mem_ptn.match(line)
if match:
return True
else:
return False
def parse_inst(line):
if not is_instruction(line):
return "", "", ""
match = call_ptn.match(line)
if match:
return "", "call.uni", ""
match = ret_ptn.match(line)
if match:
return "", "ret", ""
match = inst_ptn.match(line)
if match:
return match.group(1), match.group(2), match.group(3)
else:
return "", "", ""
#-------------------------------------------------------------------------------
@dataclass
class FuncStats:
func_name: str = ""
inst_count: int = 0
call_count: int = 0
mem_count: int = 0
call_dict: Dict[str, int] = field(default_factory=dict) # func name, count
inst_dict: Dict[str, int] = field(default_factory=dict) # inst, count
@dataclass
class FileStats:
total_funcs: int = 0
total_insts: int = 0
total_mem_insts: int = 0
total_calls: int = 0
extern_funcs: Dict[str, int] = field(default_factory=dict) # func name, count
func_calls: Dict[str, int] = field(default_factory=dict) # func name, count
summary_dict: Dict[str, str] = field(default_factory=dict) # func name, summary
inst_dict: Dict[str, int] = field(default_factory=dict) # inst, count
largest_function: str = ""
largest_size: int = 0
csv_string: str = ""
#-------------------------------------------------------------------------------
def parse_ptx(ptx_filename):
# read the raw PTX into a string
raw_ptx = ""
with open(ptx_filename, 'r') as ptx_file:
raw_ptx = ptx_file.read()
# variables to keep track of the parsing state
begin_func_or_decl = False
begin_call = False
in_func = False
brace_count = 0
func_stats = FuncStats()
func_dict = {}
for line in raw_ptx.splitlines():
# strip off comments
if line.find("//") != -1:
line = line[:line.find("//")]
# trim whitespace and trailing commas
line = line.strip(" \t\n\r,")
# keep track of when we hit a function declaration or definition
if is_func_or_decl(line):
begin_func_or_decl = True
func_stats.func_name = get_func_name(line)
# keep track of braces so we can have some picture of nesting
brace_count = brace_count + line.count('{')
brace_count = brace_count - line.count('}')
# if we hit a call.uni, we need to look for the name of the callee
# on the next pass
if is_call_start(line):
begin_call = True
func_stats.call_count = func_stats.call_count + 1
elif begin_call:
begin_call = False
func_stats.call_dict[line] = func_stats.call_dict.get(line, 0) + 1
pred, opcode, args = parse_inst(line)
if in_func and opcode != "":
func_stats.inst_count = func_stats.inst_count + 1
func_stats.mem_count = func_stats.mem_count + is_mem_inst(line)
inst = opcode
func_stats.inst_dict[inst] = func_stats.inst_dict.get((inst), 0) + 1
if begin_func_or_decl and brace_count == 1:
in_func = True
begin_func_or_decl = False
# exiting the function -- save off the stats
if in_func and brace_count == 0:
func_dict[func_stats.func_name] = func_stats
# prepare for the next iteration
func_stats = FuncStats()
begin_func_or_decl = False
begin_call = False
in_func = False
brace_count = 0
return func_dict
#-------------------------------------------------------------------------------
def gather_file_stats(func_dict):
file_stats = FileStats()
file_stats.total_funcs = len(func_dict)
file_stats.csv_string = "Function Name, Total Instructions, Memory Instructions, Function Calls\n"
# print the function statistics
for key, entry in sorted(func_dict.items()):
func_name = entry.func_name
file_stats.total_insts += entry.inst_count
file_stats.total_mem_insts += entry.mem_count
file_stats.total_calls += entry.call_count
# keep track of the largest function
if entry.inst_count > file_stats.largest_size:
file_stats.largest_function = func_name
file_stats.largest_size = entry.inst_count
# clamp the counts to prevent divide-by-zero
inst_count = max(1, entry.inst_count)
mem_count = max(1, entry.mem_count)
call_count = max(1, entry.call_count)
summary_string = ""
summary_string += " Function: {}\n".format(func_name)
summary_string += " Total Instructions: {}\n".format(inst_count)
summary_string += " Memory Instructions: {} ({:.2f}%)\n".format(mem_count, 100 * float(mem_count)/inst_count)
summary_string += " Total Calls: {}\n".format(entry.call_count)
summary_string += "\n"
summary_string += "Top 10 Function Calls (name, count, %):\n"
for name, count in itertools.islice(sorted(entry.call_dict.items(), key=lambda item: -item[1]), 0, 11):
summary_string += " {}, {}, {:.2f}%\n".format(name, count, 100 * float(count)/max(1,file_stats.total_calls))
# print the instruction mix
summary_string += "\n"
summary_string += "Instruction Mix (name, count, %):\n"
for inst, count in sorted(entry.inst_dict.items()):
summary_string += " {}, {}, {:.2f}%\n".format(inst, count, 100 * float(count)/inst_count)
file_stats.inst_dict[inst] = file_stats.inst_dict.get((inst), 0) + count
# print the call mix
summary_string += "\n"
summary_string += "Function Calls (name, count, %):\n"
for name, count in sorted(entry.call_dict.items()):
file_stats.func_calls[name] = file_stats.func_calls.get((name), 0) + count
summary_string += " {}, {}, {:.2f}%\n".format(name, count, 100 * float(count)/call_count)
if not name in func_dict:
file_stats.extern_funcs[name] = 1
file_stats.summary_dict[func_name] = summary_string
file_stats.csv_string += "{},{},{},{}\n".format(func_name, entry.inst_count, entry.mem_count, entry.call_count)
return file_stats
#-------------------------------------------------------------------------------
def generate_summary(func_dict, file_stats, out_name):
summary_string = "Overall Stats\n"
summary_string += " Total Functions: {}\n".format(file_stats.total_funcs)
summary_string += " Total Instructions: {}\n".format(file_stats.total_insts)
summary_string += " Memory Instructions: {} ({:.2f}%)\n".format(file_stats.total_mem_insts, 100 * float(file_stats.total_mem_insts)/max(1, file_stats.total_insts))
summary_string += " Total Calls: {}\n".format(file_stats.total_calls)
summary_string += " Biggest Function: {} ({} instructions)\n".format(file_stats.largest_function, file_stats.largest_size)
summary_string += "\n"
summary_string += "Top 10 Function Calls (name, count, %):\n"
for name, count in itertools.islice(sorted(file_stats.func_calls.items(), key=lambda item: -item[1]), 0, 11):
summary_string += " {}, {}, {:.2f}%\n".format(name, count, 100 * float(count)/max(1,file_stats.total_calls))
summary_string += "\n"
summary_string += "Function Call Counts (name, count, %):\n"
for name, count in sorted(file_stats.func_calls.items()):
summary_string += " {}, {}, {:.2f}%\n".format(name, count, 100 * float(count)/max(1,file_stats.total_calls))
summary_string += "\n"
summary_string += "Instruction Mix (name, count, %):\n"
for name, count in sorted(file_stats.inst_dict.items()):
summary_string += " {}, {}, {:.2f}%\n".format(name, count, 100 * float(count)/max(1,file_stats.total_insts))
summary_string += "\n"
summary_string += "Uncalled Functions:\n"
for name, count in sorted(func_dict.items()):
if not name in file_stats.func_calls:
summary_string += " {}\n".format(name)
summary_string += "\n"
summary_string += "Extern Functions:\n"
for name, val in sorted(file_stats.extern_funcs.items()):
summary_string += " {}\n".format(name)
with open("{}-summary.txt".format(out_name), "w") as summary_file:
summary_file.write(summary_string)
for func_name, summary in sorted(file_stats.summary_dict.items()):
summary_file.write("\n#---------------------------------------\n")
summary_file.write(summary)
with open("{}.csv".format(out_name), "w") as csv_file:
csv_file.write(file_stats.csv_string)
return summary_string
#-------------------------------------------------------------------------------
def wrap_name(name):
wrapped_name = ""
cur_line = ""
last_char = ''
wrap_len = 20
split_pos = 0
line_pos = 0
for cur_char in name:
cur_line = cur_line + cur_char
line_pos = line_pos + 1
if not cur_char.isalpha():
# prefer to split at non-alphabetic characters
split_pos = line_pos
elif last_char.isupper() and not cur_char.isupper():
# otherwise, prefer to split at the first capitalized letter
# of some group
split_pos = line_pos - 2
if line_pos == wrap_len:
wrapped_name = wrapped_name + cur_line[:split_pos] + '\n'
cur_line = cur_line[split_pos:]
line_pos = len(cur_line)
last_char = cur_char
wrapped_name = wrapped_name + cur_line + '\n'
return wrapped_name.strip(" \t\n\r,")
#-------------------------------------------------------------------------------
def generate_callgraph(func_dict, file_stats, out_name):
callgraph = graphviz.Digraph("{} Call Graph".format(out_name),
filename="{}-callgraph.gv".format(out_name),
engine="dot")
callgraph.attr("graph", rankdir="TB")
callgraph.attr("graph", splines="true")
callgraph.attr("graph", concentrate="false")
callgraph.attr("graph", clusterrank="none")
callgraph.attr("node", fontname="Courier New")
callgraph.attr("node", shape="square")
callgraph.attr("node", nojustify="true")
callgraph.attr("node", width="2.5")
callgraph.attr("node", height="2.5")
callgraph.attr("edge", penwidth="3")
callgraph.attr("edge", constrain="false")
# create a summary node
with callgraph.subgraph(name="Summary") as c:
c.attr("graph", rankdir="TB")
c.attr("graph", splines="true")
c.attr("graph", concentrate="false")
c.attr("graph", clusterrank="none")
c.attr("node", fontname="Courier New")
c.attr("node", shape="square")
c.attr("node", nojustify="false")
c.attr("node", width="2.5")
c.attr("node", height="2.5")
c.attr("edge", penwidth="3")
c.attr("edge", constrain="false")
c.node(name="SUMMARY",
label="Summary\linsts: {}\lfuncs: {}\lcalls: {}\l".format
(file_stats.total_insts, file_stats.total_funcs, file_stats.total_calls))
# create the nodes
for func_name, entry in sorted(func_dict.items()):
num_calls_to = 0
if func_name in file_stats.func_calls:
num_calls_to = file_stats.func_calls[func_name]
label = "{}\n\ninsts: {}\lcalls from: {}\lcalls to: {}\l".format(
wrap_name(func_name),
entry.inst_count,
entry.call_count,
num_calls_to)
callgraph.node(name=wrap_name(func_name), label=label)
# create nodes for the extern functions
callgraph.attr("node", style="dashed")
for key, entry in sorted(file_stats.extern_funcs.items()):
func_name = key
callgraph.node(wrap_name(func_name))
# cycle through a handful of edge colors to add a little eye candy
color_idx = 0
edge_colors = [ "#FF000080", # red
"#00800F80", # green
"#FFAF0080", # orange
"#0000FF80", # blue
"#40404080" ] # gray
# create the edges
for key, entry in sorted(func_dict.items()):
func_name = entry.func_name
callgraph.attr("edge", color=edge_colors[color_idx])
for calleeName, count in sorted(entry.call_dict.items()):
callgraph.attr("edge", tooltip="{} -> {}".format(func_name, calleeName))
callgraph.edge(wrap_name(func_name), wrap_name(calleeName))
color_idx = (color_idx + 1) % len(edge_colors)
callgraph.render()
return
#-------------------------------------------------------------------------------
def main():
if len(sys.argv) != 2:
sys.exit("Wrong number of arguments\nUsage: $ parse-ptx.py <path-to-PTX-file>")
in_name = sys.argv[1]
if not os.path.isfile(in_name):
sys.exit("Unable to open PTX file")
out_name = os.path.splitext(os.path.basename(in_name))[0]
func_dict = parse_ptx(in_name)
file_stats = gather_file_stats(func_dict)
generate_summary(func_dict, file_stats, out_name)
generate_callgraph(func_dict, file_stats, out_name)
return
if __name__ == "__main__":
main()
#-------------------------------------------------------------------------------
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env bash
# Utility script to download and build abi checking tools
#
# Copyright Contributors to the Open Shading Language project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
# Exit the whole script if any command fails.
set -ex
# Where to install the final results
: ${LOCAL_DEPS_DIR:=${PWD}/ext}
: ${ABITOOLS_INSTALL_DIR:=${LOCAL_DEPS_DIR}/dist}
mkdir -p ${LOCAL_DEPS_DIR}
pushd ${LOCAL_DEPS_DIR}
git clone https://github.com/lvc/vtable-dumper
pushd vtable-dumper ; make install prefix=${ABITOOLS_INSTALL_DIR} ; popd
git clone https://github.com/lvc/abi-dumper
pushd abi-dumper ; make install prefix=${ABITOOLS_INSTALL_DIR} ; popd
git clone https://github.com/lvc/abi-compliance-checker
pushd abi-compliance-checker ; make install prefix=${ABITOOLS_INSTALL_DIR} ; popd
popd
# ls -R ${LOCAL_DEPS_DIR}
export PATH=${PATH}:${ABITOOLS_INSTALL_DIR}/bin
+1 -1
View File
@@ -12,7 +12,7 @@ set -ex
echo "Building cmake"
uname
CMAKE_VERSION=${CMAKE_VERSION:=3.12.4}
CMAKE_VERSION=${CMAKE_VERSION:=3.18.5}
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
CMAKE_INSTALL_DIR=${CMAKE_INSTALL_DIR:=${LOCAL_DEPS_DIR}/cmake}
+7 -18
View File
@@ -14,29 +14,18 @@ uname
if [[ `uname` == "Linux" ]] ; then
LLVM_VERSION=${LLVM_VERSION:=13.0.0}
LLVM_INSTALL_DIR=${LLVM_INSTALL_DIR:=${PWD}/llvm-install}
if [[ "$GITHUB_WORKFLOW" != "" ]] ; then
LLVM_DISTRO_NAME=${LLVM_DISTRO_NAME:=ubuntu-18.04}
elif [[ "$TRAVIS_DIST" == "trusty" ]] ; then
LLVM_DISTRO_NAME=${LLVM_DISTRO_NAME:=ubuntu-14.04}
elif [[ "$TRAVIS_DIST" == "xenial" ]] ; then
LLVM_DISTRO_NAME=${LLVM_DISTRO_NAME:=ubuntu-16.04}
elif [[ "$TRAVIS_DIST" == "bionic" ]] ; then
LLVM_DISTRO_NAME=${LLVM_DISTRO_NAME:=ubuntu-18.04}
else
LLVM_DISTRO_NAME=${LLVM_DISTRO_NAME:=error}
fi
: ${LLVM_VERSION:=14.0.0}
: ${LLVM_INSTALL_DIR:=${PWD}/llvm-install}
: ${LLVM_DISTRO_NAME:=ubuntu-18.04}
LLVMTAR=clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-${LLVM_DISTRO_NAME}.tar.xz
echo LLVMTAR = $LLVMTAR
if [[ "$LLVM_VERSION" == "10.0.0" ]] || [[ "$LLVM_VERSION" == "11.0.0" ]] \
|| [[ "$LLVM_VERSION" == "11.1.0" ]] || [[ "$LLVM_VERSION" == "12.0.0" ]] \
|| [[ "$LLVM_VERSION" == "13.0.0" ]] || [[ "$LLVM_VERSION" == "14.0.0" ]] ;
if [[ "$LLVM_VERSION" == "9.0.0" ]] || [[ "$LLVM_VERSION" == "9.0.1" ]] ;
then
# old -- get rid of this when LLVM 10 is the newest we allow
curl --location http://releases.llvm.org/${LLVM_VERSION}/${LLVMTAR} -o $LLVMTAR
else
# new
curl --location https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/${LLVMTAR} -o $LLVMTAR
else
curl --location http://releases.llvm.org/${LLVM_VERSION}/${LLVMTAR} -o $LLVMTAR
fi
ls -l $LLVMTAR
tar xf $LLVMTAR
+6 -6
View File
@@ -11,13 +11,14 @@ set -ex
# Which OCIO to retrieve, how to build it
OPENCOLORIO_REPO=${OPENCOLORIO_REPO:=https://github.com/AcademySoftwareFoundation/OpenColorIO.git}
OPENCOLORIO_VERSION=${OPENCOLORIO_VERSION:=v1.1.1}
OPENCOLORIO_VERSION=${OPENCOLORIO_VERSION:=v2.2.1}
# Where to install the final results
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
OPENCOLORIO_SOURCE_DIR=${OPENCOLORIO_SOURCE_DIR:=${LOCAL_DEPS_DIR}/OpenColorIO}
OPENCOLORIO_BUILD_DIR=${OPENCOLORIO_BUILD_DIR:=${LOCAL_DEPS_DIR}/OpenColorIO-build}
OPENCOLORIO_INSTALL_DIR=${OPENCOLORIO_INSTALL_DIR:=${LOCAL_DEPS_DIR}/dist}
OPENCOLORIO_BUILD_TYPE=${OPENCOLORIO_BUILD_TYPE:=Release}
OPENCOLORIO_CXX_FLAGS=${OPENCOLORIO_CXX_FLAGS:="-Wno-unused-function -Wno-deprecated-declarations -Wno-cast-qual -Wno-write-strings"}
# Just need libs:
OPENCOLORIO_BUILDOPTS="-DOCIO_BUILD_APPS=OFF -DOCIO_BUILD_NUKE=OFF \
@@ -42,13 +43,12 @@ cd ${OPENCOLORIO_SOURCE_DIR}
echo "git checkout ${OPENCOLORIO_VERSION} --force"
git checkout ${OPENCOLORIO_VERSION} --force
mkdir -p ${OPENCOLORIO_BUILD_DIR}
cd ${OPENCOLORIO_BUILD_DIR}
time cmake -DCMAKE_BUILD_TYPE=Release \
time cmake -S . -B ${OPENCOLORIO_BUILD_DIR} \
-DCMAKE_BUILD_TYPE=${OPENCOLORIO_BUILD_TYPE} \
-DCMAKE_INSTALL_PREFIX=${OPENCOLORIO_INSTALL_DIR} \
-DCMAKE_CXX_FLAGS="${OPENCOLORIO_CXX_FLAGS}" \
${OPENCOLORIO_BUILDOPTS} ${OPENCOLORIO_SOURCE_DIR}
time cmake --build . --config Release --target install
${OPENCOLORIO_BUILDOPTS}
time cmake --build ${OPENCOLORIO_BUILD_DIR} --config Release --target install
popd
# ls -R ${OPENCOLORIO_INSTALL_DIR}
+16 -33
View File
@@ -12,7 +12,7 @@ set -ex
# Which OpenEXR to retrieve, how to build it
OPENEXR_REPO=${OPENEXR_REPO:=https://github.com/AcademySoftwareFoundation/openexr.git}
OPENEXR_VERSION=${OPENEXR_VERSION:=v3.1.1}
OPENEXR_VERSION=${OPENEXR_VERSION:=v3.1.11}
# Where to install the final results
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
@@ -37,42 +37,25 @@ if [[ ! -e ${OPENEXR_SOURCE_DIR} ]] ; then
git clone ${OPENEXR_REPO} ${OPENEXR_SOURCE_DIR}
fi
mkdir -p ${OPENEXR_INSTALL_DIR} && true
mkdir -p ${OPENEXR_BUILD_DIR} && true
pushd ${OPENEXR_SOURCE_DIR}
git checkout ${OPENEXR_VERSION} --force
if [[ ${OPENEXR_VERSION} == "v2.3.0" ]] ; then
# Simplified setup for 2.3+
cd ${OPENEXR_BUILD_DIR}
cmake -DCMAKE_BUILD_TYPE=${OPENEXR_BUILD_TYPE} \
-DCMAKE_INSTALL_PREFIX="${OPENEXR_INSTALL_DIR}" \
-DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}" \
-DILMBASE_PACKAGE_PREFIX="${OPENEXR_INSTALL_DIR}" \
-DOPENEXR_BUILD_UTILS=0 \
-DOPENEXR_BUILD_TESTS=0 \
-DOPENEXR_BUILD_PYTHON_LIBS=0 \
-DCMAKE_CXX_FLAGS="${OPENEXR_CXX_FLAGS}" \
${OPENEXR_CMAKE_FLAGS} ${OPENEXR_SOURCE_DIR}
time cmake --build . --target install --config ${OPENEXR_BUILD_TYPE}
else
# Simplified setup for 2.4+
cd ${OPENEXR_BUILD_DIR}
cmake -DCMAKE_BUILD_TYPE=${OPENEXR_BUILD_TYPE} \
-DCMAKE_INSTALL_PREFIX="${OPENEXR_INSTALL_DIR}" \
-DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}" \
-DILMBASE_PACKAGE_PREFIX="${OPENEXR_INSTALL_DIR}" \
-DOPENEXR_BUILD_UTILS=0 \
-DBUILD_TESTING=0 \
-DPYILMBASE_ENABLE=0 \
-DOPENEXR_VIEWERS_ENABLE=0 \
-DINSTALL_OPENEXR_EXAMPLES=0 \
-DOPENEXR_INSTALL_EXAMPLES=0 \
-DCMAKE_INSTALL_LIBDIR=lib \
-DCMAKE_CXX_FLAGS="${OPENEXR_CXX_FLAGS}" \
${OPENEXR_CMAKE_FLAGS} ${OPENEXR_SOURCE_DIR}
time cmake --build . --target install --config ${OPENEXR_BUILD_TYPE}
fi
cmake -S . -B ${OPENEXR_BUILD_DIR} \
-DCMAKE_BUILD_TYPE=${OPENEXR_BUILD_TYPE} \
-DCMAKE_INSTALL_PREFIX="${OPENEXR_INSTALL_DIR}" \
-DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}" \
-DILMBASE_PACKAGE_PREFIX="${OPENEXR_INSTALL_DIR}" \
-DOPENEXR_BUILD_UTILS=0 \
-DBUILD_TESTING=0 \
-DPYILMBASE_ENABLE=0 \
-DOPENEXR_VIEWERS_ENABLE=0 \
-DINSTALL_OPENEXR_EXAMPLES=0 \
-DOPENEXR_INSTALL_EXAMPLES=0 \
-DCMAKE_INSTALL_LIBDIR=lib \
-DCMAKE_CXX_FLAGS="${OPENEXR_CXX_FLAGS}" \
${OPENEXR_CMAKE_FLAGS}
time cmake --build ${OPENEXR_BUILD_DIR} --target install --config ${OPENEXR_BUILD_TYPE}
popd
+10 -9
View File
@@ -11,7 +11,7 @@ set -ex
# Repo and branch/tag/commit of pugixml to download if we don't have it yet
PUGIXML_REPO=${PUGIXML_REPO:=https://github.com/zeux/pugixml.git}
PUGIXML_VERSION=${PUGIXML_VERSION:=v1.10}
PUGIXML_VERSION=${PUGIXML_VERSION:=v1.11.4}
# Where to put pugixml repo source (default to the ext area)
PUGIXML_SRC_DIR=${PUGIXML_SRC_DIR:=${PWD}/ext/pugixml}
@@ -34,17 +34,18 @@ if [[ ! -e ${PUGIXML_SRC_DIR} ]] ; then
git clone ${PUGIXML_REPO} ${PUGIXML_SRC_DIR}
fi
cd ${PUGIXML_SRC_DIR}
echo "git checkout ${PUGIXML_VERSION} --force"
git checkout ${PUGIXML_VERSION} --force
mkdir -p ${PUGIXML_BUILD_DIR}
cd ${PUGIXML_BUILD_DIR}
time cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${PUGIXML_INSTALL_DIR} \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_TESTS=OFF \
${PUGIXML_BUILD_OPTS} ..
time cmake --build . --config Release --target install
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -S . -B ${PUGIXML_BUILD_DIR} -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${PUGIXML_INSTALL_DIR} \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_TESTS=OFF \
${PUGIXML_BUILD_OPTS} ..
time cmake --build ${PUGIXML_BUILD_DIR} --config Release --target install
fi
# ls -R ${PUGIXML_INSTALL_DIR}
popd
+3 -6
View File
@@ -42,15 +42,12 @@ cd ${PYBIND11_SRC_DIR}
echo "git checkout ${PYBIND11_VERSION} --force"
git checkout ${PYBIND11_VERSION} --force
mkdir -p ${PYBIND11_BUILD_DIR}
cd ${PYBIND11_BUILD_DIR}
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -DCMAKE_BUILD_TYPE=Release \
time cmake -S . -B ${PYBIND11_BUILD_DIR} -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${PYBIND11_INSTALL_DIR} \
-DPYBIND11_TEST=OFF \
${PYBIND11_BUILD_OPTS} ..
time cmake --build . --config Release --target install
${PYBIND11_BUILD_OPTS}
time cmake --build ${PYBIND11_BUILD_DIR} --config Release --target install
fi
# ls -R ${PYBIND11_INSTALL_DIR}
+54
View File
@@ -0,0 +1,54 @@
#!/usr/bin/env bash
# Copyright Contributors to the Open Shading Language project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
# Important: set -ex causes this whole script to terminate with error if
# any command in it fails. This is crucial for CI tests.
set -e
# Arguments to this script are:
# BUILDDIR_NEW BUILDDIR_OLD LIBRARIES...
BUILDDIR_NEW=$1
shift
BUILDDIR_OLD=$1
shift
LIBS=$*
#
# First, create ABI dumps from both builds
#
ABI_ARGS="-bin-only -skip-cxx -public-headers $PWD/dist/include/OSL "
echo "ABI_CHECK: PWD=${PWD} "
ls -l $BUILDDIR_NEW
ls -l $BUILDDIR_OLD
for dir in $BUILDDIR_NEW $BUILDDIR_OLD ; do
for lib in $LIBS ; do
abi-dumper $ABI_ARGS ${dir}/lib/${lib}.so -o ${dir}/abi-${lib}.dump
done
done
echo "Saved ABI dumps"
#
# Run the ABI compliance checker, saving the outputs to files
#
for lib in $LIBS ; do
abi-compliance-checker -l $lib -old $BUILDDIR_OLD/abi-$lib.dump -new $BUILDDIR_NEW/abi-$lib.dump | tee ${lib}-abi-results.txt || true
echo -e "\x1b[33;1m"
echo -e "$lib"
fgrep "Binary compatibility:" ${lib}-abi-results.txt
echo -e "\x1b[33;0m"
done
#
# If the "Binary compatibility" summary results say anything other than 100%,
# we fail!
#
for lib in $LIBS ; do
if [[ `fgrep "Binary compatibility:" ${lib}-abi-results.txt | grep -v 100\%` != "" ]] ; then
cp -r compat_reports ${BUILDDIR_NEW}/compat_reports
exit 1
fi
done
+4
View File
@@ -1,5 +1,9 @@
#!/usr/bin/env bash
# Copyright Contributors to the Open Shading Language project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
# Run code coverage analysis
# This assumes that the build occurred with CODECOV=1 andtests have already
# fully run.
+19 -5
View File
@@ -39,11 +39,6 @@ export CMAKE_GENERATOR=${CMAKE_GENERATOR:=Ninja}
export CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE:=Release}
export CMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD:=11}
export PARALLEL=${PARALLEL:=4}
export PAR_MAKEFLAGS=-j${PARALLEL}
export CMAKE_BUILD_PARALLEL_LEVEL=${CMAKE_BUILD_PARALLEL_LEVEL:=${PARALLEL}}
export CTEST_PARALLEL_LEVEL=${CTEST_PARALLEL_LEVEL:=${PARALLEL}}
export LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=$HOME/ext}
export CMAKE_PREFIX_PATH=${LOCAL_DEPS_DIR}/dist:${CMAKE_PREFIX_PATH}
export LD_LIBRARY_PATH=${LOCAL_DEPS_DIR}/dist/lib:$LD_LIBRARY_PATH
@@ -52,6 +47,25 @@ export DYLD_LIBRARY_PATH=${LOCAL_DEPS_DIR}/dist/lib:$DYLD_LIBRARY_PATH
export TESTSUITE_CLEANUP_ON_SUCCESS=${TESTSUITE_CLEANUP_ON_SUCCESS:=1}
# Parallel builds
if [[ `uname -s` == "Linux" ]] ; then
echo "procs: " `nproc`
head -40 /proc/cpuinfo
export PARALLEL=${PARALLEL:=$((2 + `nproc`))}
elif [[ "${RUNNER_OS}" == "macOS" ]] ; then
echo "procs: " `sysctl -n hw.ncpu`
sysctl machdep.cpu.features
export PARALLEL=${PARALLEL:=$((2 + `sysctl -n hw.ncpu`))}
elif [[ "${RUNNER_OS}" == "Windows" ]] ; then
# Presumably Windows
export PARALLEL=${PARALLEL:=$((2 + ${NUMBER_OF_PROCESSORS}))}
else
export PARALLEL=${PARALLEL:=6}
fi
export PAR_MAKEFLAGS=-j${PARALLEL}
export CMAKE_BUILD_PARALLEL_LEVEL=${CMAKE_BUILD_PARALLEL_LEVEL:=${PARALLEL}}
export CTEST_PARALLEL_LEVEL=${CTEST_PARALLEL_LEVEL:=${PARALLEL}}
mkdir -p build dist
echo "HOME = $HOME"
+41 -22
View File
@@ -18,8 +18,8 @@ if [[ "$ASWF_ORG" != "" ]] ; then
#ls /etc/yum.repos.d
sudo yum install -y giflib giflib-devel && true
# sudo yum install -y ffmpeg ffmpeg-devel && true
sudo /usr/bin/yum install -y giflib giflib-devel && true
# sudo /usr/bin/yum install -y ffmpeg ffmpeg-devel && true
if [[ "${CONAN_LLVM_VERSION}" != "" ]] ; then
mkdir conan
@@ -40,28 +40,29 @@ if [[ "$ASWF_ORG" != "" ]] ; then
popd
fi
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" || "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" ]] ; then
# Lock down icc to 2022.1 because newer versions hosted on the Intel
# repo require a glibc too new for the ASWF CentOS7-based containers
# we run CI on.
sudo cp src/build-scripts/oneAPI.repo /etc/yum.repos.d
sudo yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic-2022.1.0-3768
# Because multiple (possibly newer) versions of oneAPI may be installed,
# use a config file to specify compiler and tbb versions
# NOTE: oneAPI components have independent version numbering.
sudo /usr/bin/yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic-2022.1.0.x86_64
set +e; source /opt/intel/oneapi/setvars.sh --config oneapi_2022.1.0.cfg; set -e
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" ]] ; then
echo "Verifying installation of Intel(r) C++ Compiler:"
icpc --version
fi
if [[ "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
echo "Verifying installation of Intel(r) oneAPI DPC++/C++ Compiler:"
icpx --version
fi
elif [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" || "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
# Lock down icx to 2023.1 because newer versions hosted on the Intel
# repo require a libstd++ too new for the ASWF containers we run CI on
# because their default install of gcc 9 based toolchain.
sudo cp src/build-scripts/oneAPI.repo /etc/yum.repos.d
sudo yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic-2023.1.0.x86_64
# sudo yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic
set +e; source /opt/intel/oneapi/setvars.sh; set -e
echo "Verifying installation of Intel(r) oneAPI DPC++/C++ Compiler:"
icpx --version
fi
else
# Using native Ubuntu runner
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
# sudo add-apt-repository ppa:ubuntu-toolchain-r/test
time sudo apt-get update
time sudo apt-get -q install -y \
@@ -73,8 +74,13 @@ else
libpugixml-dev \
libopencolorio-dev
time sudo apt-get -q install -y \
qt5-default || /bin/true
if [[ "${QT_VERSION:-5}" == "5" ]] ; then
time sudo apt-get -q install -y \
qt5-default || /bin/true
elif [[ "${QT_VERSION}" == "6" ]] ; then
time sudo apt-get -q install -y \
qt6-base-dev || /bin/true
fi
export CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu:$CMAKE_PREFIX_PATH
@@ -120,6 +126,10 @@ else
source src/build-scripts/build_llvm.bash
fi
if [[ "$CMAKE_VERSION" != "" ]] ; then
source src/build-scripts/build_cmake.bash
fi
cmake --version
if [[ "$OPTIX_VERSION" != "" ]] ; then
@@ -141,6 +151,11 @@ if [[ "$OPTIX_VERSION" != "" ]] ; then
fi
#
# Packages we need to build from scratch.
#
source src/build-scripts/build_pybind11.bash
if [[ "$OPENEXR_VERSION" != "" ]] ; then
@@ -171,14 +186,18 @@ if [[ "$OPENIMAGEIO_VERSION" != "" ]] ; then
# Don't let warnings in OIIO break OSL's CI run
export OPENIMAGEIO_CMAKE_FLAGS+=" -DSTOP_ON_WARNING=OFF"
export OPENIMAGEIO_CMAKE_FLAGS+=" -DUSE_OPENGL=0"
if [[ $OPENIMAGEIO_VERSION == master && "${OPENIMAGEIO_UNITY:-1}" != "0" ]] ; then
export OPENIMAGEIO_CMAKE_FLAGS+=" -DUSE_OPENCV=0 -DUSE_FFMPEG=0 -DUSE_QT=0"
if [[ "${OPENIMAGEIO_UNITY:-1}" != "0" ]] ; then
# Speed up the OIIO build by doing a "unity" build. (Note: this is
# only a savings in CI where there are only 1-2 cores available, and
# is only supported for OIIO 2.3.14 and later)
# only a savings in CI where there are only 1-2 cores available.)
export OPENIMAGEIO_CMAKE_FLAGS+=" -DCMAKE_UNITY_BUILD=ON -DCMAKE_UNITY_BUILD_MODE=BATCH"
fi
source src/build-scripts/build_openimageio.bash
fi
if [[ "$ABI_CHECK" != "" ]] ; then
source src/build-scripts/build_abi_tools.bash
fi
# Save the env for use by other stages
src/build-scripts/save-env.bash
+19 -18
View File
@@ -19,6 +19,7 @@ if [[ `which brew` == "" ]] ; then
exit 1
fi
set -ex
if [[ "$DO_BREW_UPDATE" != "" ]] ; then
brew update >/dev/null
@@ -30,41 +31,41 @@ brew list --versions
brew install --display-times -q gcc ccache cmake ninja boost || true
brew link --overwrite gcc
brew install --display-times -q python@${PYTHON_VERSION} || true
brew unlink python@2.7 || true
brew unlink python@3.8 || true
brew unlink python@3.9 || true
# brew unlink python@3.8 || true
# brew unlink python@3.9 || true
brew unlink python@3.10 || true
brew link --overwrite --force python@${PYTHON_VERSION} || true
brew upgrade --display-times -q cmake || true
brew install --display-times -q ilmbase openexr
brew install --display-times -q imath openexr
#brew install --display-times -q freetype
brew install --display-times -q opencolorio partio pugixml
brew install --display-times -q --overwrite --force opencolorio || true
brew install --display-times -q partio pugixml
brew install --display-times -q pybind11 numpy || true
brew install --display-times -q tbb || true
brew install --display-times -q openvdb || true
brew install --display-times -q flex bison
brew install --display-times -q fmt
brew install --display-times -q llvm${LLVMBREWVER}
brew install --display-times -q qt
if [[ "${USE_QT}" != "0" ]] ; then
brew install --display-times -q qt${QT_VERSION}
fi
echo ""
echo "After brew installs:"
brew list --versions
# Needed on some systems
if [[ $PYTHON_VERSION != "2.7" ]] ; then
pip3 install numpy
else
pip install numpy
fi
pip${PYTHON_VERSION} install numpy
# Set up paths. These will only affect the caller if this script is
# run with 'source' rather than in a separate shell.
export PATH=/usr/local/opt/qt5/bin:$PATH
export PATH=/usr/local/opt/python/libexec/bin:$PATH
export PYTHONPATH=/usr/local/lib/python${PYTHON_VERSION}/site-packages:$PYTHONPATH
# export PATH=/usr/local/opt/llvm${LLVMBREWVER}/bin:$PATH
export LLVM_DIRECTORY=/usr/local/opt/llvm${LLVMBREWVER}
export LLVM_ROOT=/usr/local/opt/llvm${LLVMBREWVER}
export PATH=/usr/local/opt/flex/bin:/usr/local/opt/bison/bin:$PATH
export PATH=${HOMEBREW_PREFIX}/opt/qt5/bin:$PATH
export PATH=${HOMEBREW_PREFIX}/opt/python/libexec/bin:$PATH
export PYTHONPATH=${HOMEBREW_PREFIX}/lib/python${PYTHON_VERSION}/site-packages:$PYTHONPATH
# export PATH=${HOMEBREW_PREFIX}/opt/llvm${LLVMBREWVER}/bin:$PATH
export LLVM_DIRECTORY=${HOMEBREW_PREFIX}/opt/llvm${LLVMBREWVER}
export LLVM_ROOT=${HOMEBREW_PREFIX}/opt/llvm${LLVMBREWVER}
export PATH=${HOMEBREW_PREFIX}/opt/flex/bin:${HOMEBREW_PREFIX}/opt/bison/bin:$PATH
# Save the env for use by other stages
src/build-scripts/save-env.bash
+3
View File
@@ -0,0 +1,3 @@
# Small leaks that make CI fail, suppress until cause is identified.
leak:__cxa_thread_atexit
leak:std::string::_Rep::_S_create
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env python
# Copyright Contributors to the Open Shading Language project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
# Open a PTX file and:
# * add the `.visible` directive to all functions
# * add the `.visible` directive to global/constant variables
from __future__ import print_function, absolute_import
import re
import sys
in_name = sys.argv[1]
out_name = sys.argv[2]
ptx = ""
with open(in_name, 'r') as ptx_in:
ptx = ptx_in.read()
ptx = re.sub(r'(?m)^(\.const .align)', ".visible .const .align", ptx)
ptx = re.sub(r'(?m)^(\.global .align)', ".visible .global .align", ptx)
ptx = re.sub(r'(?m)^(\.func)', ".visible .func", ptx)
with open(out_name, 'w') as ptx_out:
ptx_out.write(ptx)
+4
View File
@@ -1,5 +1,9 @@
#!/usr/bin/env bash
# Copyright Contributors to the Open Shading Language project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
# Save the env for use by other stages. Exclude things that we know aren't
# needed.
printenv \
+21 -38
View File
@@ -15,13 +15,11 @@
###########################################################################
# Print some basic status about the system and compiler
#
if (VERBOSE)
message (STATUS "CMAKE_SYSTEM_NAME = ${CMAKE_SYSTEM_NAME}")
message (STATUS "CMAKE_SYSTEM_VERSION = ${CMAKE_SYSTEM_VERSION}")
message (STATUS "CMAKE_SYSTEM_PROCESSOR = ${CMAKE_SYSTEM_PROCESSOR}")
endif ()
message (STATUS "CMAKE_CXX_COMPILER = ${CMAKE_CXX_COMPILER}")
message (STATUS "CMAKE_CXX_COMPILER_ID = ${CMAKE_CXX_COMPILER_ID}")
message (VERBOSE "CMAKE_SYSTEM_NAME = ${CMAKE_SYSTEM_NAME}")
message (VERBOSE "CMAKE_SYSTEM_VERSION = ${CMAKE_SYSTEM_VERSION}")
message (VERBOSE "CMAKE_SYSTEM_PROCESSOR = ${CMAKE_SYSTEM_PROCESSOR}")
message (STATUS "CMAKE_CXX_COMPILER = ${CMAKE_CXX_COMPILER}")
message (STATUS "CMAKE_CXX_COMPILER_ID = ${CMAKE_CXX_COMPILER_ID}")
###########################################################################
@@ -44,9 +42,7 @@ if (CMAKE_COMPILER_IS_GNUCC)
execute_process (COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)
if (VERBOSE)
message (STATUS "Using gcc ${GCC_VERSION} as the compiler")
endif ()
message (VERBOSE "Using gcc ${GCC_VERSION} as the compiler")
else ()
set (GCC_VERSION 0)
endif ()
@@ -63,26 +59,18 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER MATCHES "[Cc]lan
set (CMAKE_CXX_COMPILER_ID "AppleClang")
set (CMAKE_COMPILER_IS_APPLECLANG 1)
string (REGEX REPLACE ".* version ([0-9]+\\.[0-9]+).*" "\\1" APPLECLANG_VERSION_STRING ${clang_full_version_string})
if (VERBOSE)
message (STATUS "The compiler is Clang: ${CMAKE_CXX_COMPILER_ID} version ${APPLECLANG_VERSION_STRING}")
endif ()
message (VERBOSE "The compiler is Clang: ${CMAKE_CXX_COMPILER_ID} version ${APPLECLANG_VERSION_STRING}")
elseif (CMAKE_CXX_COMPILER_ID MATCHES "IntelLLVM")
set (CMAKE_COMPILER_IS_INTELCLANG 1)
string (REGEX MATCH "[0-9]+(\\.[0-9]+)+" INTELCLANG_VERSION_STRING ${clang_full_version_string})
if (VERBOSE)
message (STATUS "The compiler is Intel Clang: ${CMAKE_CXX_COMPILER_ID} version ${INTELCLANG_VERSION_STRING}")
endif ()
message (VERBOSE "The compiler is Intel Clang: ${CMAKE_CXX_COMPILER_ID} version ${INTELCLANG_VERSION_STRING}")
else ()
string (REGEX REPLACE ".* version ([0-9]+\\.[0-9]+).*" "\\1" CLANG_VERSION_STRING ${clang_full_version_string})
if (VERBOSE)
message (STATUS "The compiler is Clang: ${CMAKE_CXX_COMPILER_ID} version ${CLANG_VERSION_STRING}")
endif ()
message (VERBOSE "The compiler is Clang: ${CMAKE_CXX_COMPILER_ID} version ${CLANG_VERSION_STRING}")
endif ()
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Intel")
set (CMAKE_COMPILER_IS_INTEL 1)
if (VERBOSE)
message (STATUS "Using Intel as the compiler")
endif ()
message (VERBOSE "Using Intel as the compiler")
endif ()
@@ -121,11 +109,11 @@ endif ()
# give more fine-grained control for hiding symbols, because sometimes
# dependent libraries may not be well behaved and need extra hiding.
#
set (CXX_VISIBILITY_PRESET "hidden" CACHE STRING "Symbol visibility (hidden or default")
set (CMAKE_CXX_VISIBILITY_PRESET "hidden" CACHE STRING "Symbol visibility (hidden or default")
option (VISIBILITY_INLINES_HIDDEN "Hide symbol visibility of inline functions" ON)
set (VISIBILITY_MAP_FILE "${PROJECT_SOURCE_DIR}/src/build-scripts/hidesymbols.map" CACHE FILEPATH "Visibility map file")
set (C_VISIBILITY_PRESET ${CXX_VISIBILITY_PRESET})
if (${CXX_VISIBILITY_PRESET} STREQUAL "hidden" AND VISIBILITY_MAP_FILE AND
set (CMAKE_C_VISIBILITY_PRESET ${CMAKE_CXX_VISIBILITY_PRESET})
if (${CMAKE_CXX_VISIBILITY_PRESET} STREQUAL "hidden" AND VISIBILITY_MAP_FILE AND
(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG) AND
(CMAKE_SYSTEM_NAME MATCHES "Linux|kFreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "GNU"))
# Linux/FreeBSD/Hurd: also hide all the symbols of dependent libraries
@@ -165,6 +153,7 @@ if (CMAKE_COMPILER_IS_CLANG OR CMAKE_COMPILER_IS_APPLECLANG)
# Suppress warnings about our strategic use of bitwise operations in place
# of logical operators to produce branchless code in some places.
if (CLANG_VERSION_STRING VERSION_GREATER_EQUAL 14.0
OR APPLECLANG_VERSION_STRING VERSION_GREATER_EQUAL 14.0
OR INTELCLANG_VERSION_STRING VERSION_GREATER_EQUAL 14.0)
add_compile_options ("-Wno-bitwise-instead-of-logical")
endif ()
@@ -313,9 +302,7 @@ if (NOT USE_SIMD STREQUAL "")
else ()
string (REPLACE "," ";" SIMD_FEATURE_LIST ${USE_SIMD})
foreach (feature ${SIMD_FEATURE_LIST})
if (VERBOSE)
message (STATUS "SIMD feature: ${feature}")
endif ()
message (VERBOSE "SIMD feature: ${feature}")
if (MSVC OR CMAKE_COMPILER_IS_INTEL)
set (SIMD_COMPILE_FLAGS ${SIMD_COMPILE_FLAGS} "/arch:${feature}")
else ()
@@ -342,17 +329,17 @@ set (USE_BATCHED "" CACHE STRING "Build batched SIMD shader execution for (0, b8
option (VEC_REPORT "Enable compiler's reporting system for vectorization" OFF)
set (BATCHED_SUPPORT_DEFINES "")
set (BATCHED_TARGET_LIBS "")
set (BUILD_BATCHED False)
set (OSL_BUILD_BATCHED 0)
if (NOT USE_BATCHED STREQUAL "")
message (STATUS "Compiling with batched SIMD targets ${USE_BATCHED}")
if (NOT USE_BATCHED STREQUAL "0")
set (BUILD_BATCHED 1)
set (OSL_BUILD_BATCHED 1)
string (REPLACE "," ";" BATCHED_TARGET_LIST ${USE_BATCHED})
foreach (batched_target ${BATCHED_TARGET_LIST})
if (VERBOSE)
message (STATUS "BATCHED target: ${batched_target}")
endif ()
set (BATCHED_SUPPORT_DEFINES ${BATCHED_SUPPORT_DEFINES} "__OSL_SUPPORTS_${batched_target}")
list (APPEND BATCHED_SUPPORT_DEFINES "__OSL_SUPPORTS_${batched_target}")
endforeach()
else ()
message (STATUS "Compiling with NO batched SIMD targets, USE_BATCHED=0")
@@ -422,7 +409,7 @@ if (CLANG_TIDY)
find_program(CLANG_TIDY_EXE NAMES "clang-tidy"
DOC "Path to clang-tidy executable")
message (STATUS "CLANG_TIDY_EXE ${CLANG_TIDY_EXE}")
if (CLANG_TIDY_EXE AND NOT ${CMAKE_VERSION} VERSION_LESS 3.6)
if (CLANG_TIDY_EXE)
set (CMAKE_CXX_CLANG_TIDY
"${CLANG_TIDY_EXE}"
)
@@ -524,9 +511,7 @@ else ()
set (SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}
CACHE STRING "Set the SO version for dynamic libraries")
endif ()
if (VERBOSE)
message(STATUS "Setting SOVERSION to: ${SOVERSION}")
endif ()
message(VERBOSE "Setting SOVERSION to: ${SOVERSION}")
###########################################################################
@@ -588,9 +573,7 @@ else ()
# add the automatically determined parts of the RPATH that
# point to directories outside the build tree to the install RPATH
set (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
if (VERBOSE)
message (STATUS "CMAKE_INSTALL_RPATH = ${CMAKE_INSTALL_RPATH}")
endif ()
message (VERBOSE "CMAKE_INSTALL_RPATH = ${CMAKE_INSTALL_RPATH}")
endif ()
# OSL considerations because we run oslc in the course of building:
# Use (i.e. don't skip) the full RPATH for the build tree
+98 -10
View File
@@ -3,6 +3,16 @@
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
set ($OSL_EXTRA_NVCC_ARGS "" CACHE STRING "Custom args passed to nvcc when compiling CUDA code")
set (CUDA_OPT_FLAG_NVCC "-O3" CACHE STRING "The optimization level to use when compiling CUDA/C++ files with nvcc")
set (CUDA_OPT_FLAG_CLANG "-O3" CACHE STRING "The optimization level to use when compiling CUDA/C++ files with clang")
# FTZ is enabled by default since it offers the best performance,
# but it may be disabled to debug numerical issues, to better match
# host behavior, etc.
set (CUDA_NO_FTZ OFF CACHE BOOL "Do not enable force-to-zero when compiling for CUDA")
if (CUDA_NO_FTZ)
add_definitions ("-DOSL_CUDA_NO_FTZ=1")
endif ()
# Compile a CUDA file to PTX using NVCC
function ( NVCC_COMPILE cuda_src extra_headers ptx_generated extra_nvcc_args )
@@ -21,6 +31,10 @@ function ( NVCC_COMPILE cuda_src extra_headers ptx_generated extra_nvcc_args )
list (TRANSFORM OpenImageIO_INCLUDES PREPEND -I
OUTPUT_VARIABLE ALL_OpenImageIO_INCLUDES)
if (NOT CUDA_NO_FTZ)
set (NVCC_FTZ_FLAG "--ftz=true")
endif ()
add_custom_command ( OUTPUT ${cuda_ptx}
COMMAND ${CUDA_NVCC_EXECUTABLE}
"-I${OPTIX_INCLUDES}"
@@ -37,7 +51,7 @@ function ( NVCC_COMPILE cuda_src extra_headers ptx_generated extra_nvcc_args )
${LLVM_COMPILE_FLAGS}
-DOSL_USE_FAST_MATH=1
-m64 -arch ${CUDA_TARGET_ARCH} -ptx
--std=c++14 -dc -O3 --use_fast_math --expt-relaxed-constexpr
--std=c++14 -dc --use_fast_math ${CUDA_OPT_FLAG_NVCC} ${NVCC_FTZ_FLAG} --expt-relaxed-constexpr
${extra_nvcc_args}
${OSL_EXTRA_NVCC_ARGS}
${cuda_src} -o ${cuda_ptx}
@@ -55,13 +69,11 @@ function ( MAKE_CUDA_BITCODE src suffix generated_bc extra_clang_args )
# Setup the compile flags
get_property (CURRENT_DEFINITIONS DIRECTORY PROPERTY COMPILE_DEFINITIONS)
if (VERBOSE)
message (STATUS "Current #defines are ${CURRENT_DEFINITIONS}")
endif ()
message (VERBOSE "Current #defines are ${CURRENT_DEFINITIONS}")
foreach (def ${CURRENT_DEFINITIONS})
set (LLVM_COMPILE_FLAGS ${LLVM_COMPILE_FLAGS} "-D${def}")
endforeach()
set (LLVM_COMPILE_FLAGS ${LLVM_COMPILE_FLAGS} ${SIMD_COMPILE_FLAGS} ${CSTD_FLAGS})
set (LLVM_COMPILE_FLAGS ${LLVM_COMPILE_FLAGS} ${CSTD_FLAGS})
# Setup the bitcode generator
if (NOT LLVM_BC_GENERATOR)
@@ -76,9 +88,7 @@ function ( MAKE_CUDA_BITCODE src suffix generated_bc extra_clang_args )
if (NOT LLVM_BC_GENERATOR)
message (FATAL_ERROR "You must have a valid llvm bitcode generator (clang++) somewhere.")
endif ()
if (VERBOSE)
message (STATUS "Using LLVM_BC_GENERATOR ${LLVM_BC_GENERATOR} to generate bitcode.")
endif()
message (VERBOSE "Using LLVM_BC_GENERATOR ${LLVM_BC_GENERATOR} to generate bitcode.")
if (NOT LLVM_AS_TOOL)
find_program (LLVM_AS_TOOL NAMES "llvm-as"
@@ -94,6 +104,20 @@ function ( MAKE_CUDA_BITCODE src suffix generated_bc extra_clang_args )
NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_ENVIRONMENT_PATH)
endif ()
if (NOT LLVM_LLC_TOOL)
find_program (LLVM_LLC_TOOL NAMES "llc"
PATHS "${LLVM_DIRECTORY}/bin" "${LLVM_DIRECTORY}/tools/llvm"
NO_CMAKE_PATH NO_DEFAULT_PATH NO_CMAKE_SYSTEM_PATH
NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_ENVIRONMENT_PATH)
endif ()
if (NOT LLVM_OPT_TOOL)
find_program (LLVM_OPT_TOOL NAMES "opt"
PATHS "${LLVM_DIRECTORY}/bin" "${LLVM_DIRECTORY}/tools/llvm"
NO_CMAKE_PATH NO_DEFAULT_PATH NO_CMAKE_SYSTEM_PATH
NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_ENVIRONMENT_PATH)
endif ()
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
# fix compilation error when using MSVC
set (CLANG_MSVC_FIX "-DBOOST_CONFIG_REQUIRES_THREADS_HPP")
@@ -104,6 +128,26 @@ function ( MAKE_CUDA_BITCODE src suffix generated_bc extra_clang_args )
set (CLANG_MSVC_FIX "${CLANG_MSVC_FIX} -Wno-ignored-attributes -Wno-unknown-attributes")
endif ()
if (NOT LLVM_OPAQUE_POINTERS AND ${LLVM_VERSION} VERSION_GREATER_EQUAL 15.0)
# Until we fully support opaque pointers, we need to disable
# them when using LLVM 15.
list (APPEND LLVM_COMPILE_FLAGS -Xclang -no-opaque-pointers)
endif ()
if (NOT CUDA_NO_FTZ)
set (CLANG_FTZ_FLAG "-fcuda-flush-denormals-to-zero")
endif ()
if ("${CUDA_VERSION}" VERSION_GREATER_EQUAL "12.0")
# The textureReference API was removed in CUDA 12.0, but it's still referenced
# in the clang headers, so compilation will fail with 12.0 and newer toolkits
# due to the missing definitions.
#
# We don't actually require any of the clang CUDA texture intrinsics, so we can
# side-step the issue by preventing them from being included by the preprocessor.
set (CUDA_TEXREF_FIX "-D__CLANG_CUDA_TEXTURE_INTRINSICS_H__")
endif()
list (TRANSFORM IMATH_INCLUDES PREPEND -I
OUTPUT_VARIABLE ALL_IMATH_INCLUDES)
list (TRANSFORM OPENEXR_INCLUDES PREPEND -I
@@ -116,6 +160,7 @@ function ( MAKE_CUDA_BITCODE src suffix generated_bc extra_clang_args )
"-I${OPTIX_INCLUDES}"
"-I${CUDA_INCLUDES}"
"-I${CMAKE_CURRENT_SOURCE_DIR}"
"-I${CMAKE_SOURCE_DIR}/src/liboslexec"
"-I${CMAKE_BINARY_DIR}/include"
"-I${PROJECT_SOURCE_DIR}/src/include"
"-I${PROJECT_SOURCE_DIR}/src/cuda_common"
@@ -123,11 +168,11 @@ function ( MAKE_CUDA_BITCODE src suffix generated_bc extra_clang_args )
${ALL_IMATH_INCLUDES}
${ALL_OPENEXR_INCLUDES}
"-I${Boost_INCLUDE_DIRS}"
${LLVM_COMPILE_FLAGS} ${CUDA_LIB_FLAGS} ${CLANG_MSVC_FIX}
${LLVM_COMPILE_FLAGS} ${CUDA_LIB_FLAGS} ${CLANG_MSVC_FIX} ${CUDA_TEXREF_FIX}
-D__CUDACC__ -DOSL_COMPILING_TO_BITCODE=1 -DNDEBUG -DOIIO_NO_SSE -D__CUDADEVRT_INTERNAL__
--language=cuda --cuda-device-only --cuda-gpu-arch=${CUDA_TARGET_ARCH}
-Wno-deprecated-register -Wno-format-security
-O3 -fno-math-errno -ffast-math -S -emit-llvm ${extra_clang_args}
-fno-math-errno -ffast-math ${CUDA_OPT_FLAG_CLANG} ${CLANG_FTZ_FLAG} -S -emit-llvm ${extra_clang_args}
${src} -o ${asm_cuda}
COMMAND ${LLVM_AS_TOOL} -f -o ${bc_cuda} ${asm_cuda}
DEPENDS ${exec_headers} ${PROJECT_PUBLIC_HEADERS} ${src}
@@ -149,3 +194,46 @@ function ( LLVM_COMPILE_CUDA llvm_src headers prefix llvm_bc_cpp_generated extra
DEPENDS "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py" ${llvm_src} ${headers} ${llvm_bc}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
endfunction ()
function ( MAKE_EMBEDDED_CPP symbol_name output_cpp input_file )
add_custom_command ( OUTPUT ${output_cpp}
COMMAND ${Python_EXECUTABLE} "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py"
${input_file} ${output_cpp} "${symbol_name}"
DEPENDS "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py" ${linked_bc}
${input_file} ${exec_headers} ${PROJECT_PUBLIC_HEADERS}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
endfunction ()
function ( CUDA_SHADEOPS_COMPILE prefix output_bc output_ptx input_srcs headers )
set (linked_bc "${CMAKE_CURRENT_BINARY_DIR}/linked_${prefix}.bc")
set (linked_ptx "${CMAKE_CURRENT_BINARY_DIR}/${prefix}.ptx")
set (${output_bc} ${linked_bc} PARENT_SCOPE )
set (${output_ptx} ${linked_ptx} PARENT_SCOPE )
foreach ( shadeops_src ${input_srcs} )
MAKE_CUDA_BITCODE ( ${shadeops_src} "_cuda" shadeops_bc "" )
list ( APPEND shadeops_bc_list ${shadeops_bc} )
endforeach ()
if (LLVM_NEW_PASS_MANAGER)
# There is no --nvptx-assign-valid-global-names flag for the new
# pass manager, but it appears to run this pass by default.
string(REPLACE "-O" "O" opt_tool_flags ${CUDA_OPT_FLAG_CLANG})
set (opt_tool_flags -passes="default<${opt_tool_flags}>")
else()
set (opt_tool_flags ${CUDA_OPT_FLAG_CLANG} --nvptx-assign-valid-global-names)
endif ()
# Link all of the individual LLVM bitcode files, and emit PTX for the linked bitcode
add_custom_command ( OUTPUT ${linked_bc} ${linked_ptx}
COMMAND ${LLVM_LINK_TOOL} ${shadeops_bc_list} -o ${linked_bc}
COMMAND ${LLVM_OPT_TOOL} ${opt_tool_flags} ${linked_bc} -o ${linked_bc}
COMMAND ${LLVM_LLC_TOOL} --march=nvptx64 -mcpu=${CUDA_TARGET_ARCH} ${linked_bc} -o ${linked_ptx}
# This script converts all of the .weak functions defined in the PTX into .visible functions.
COMMAND ${Python_EXECUTABLE} "${CMAKE_SOURCE_DIR}/src/build-scripts/process-ptx.py"
${linked_ptx} ${linked_ptx}
DEPENDS ${shadeops_bc_list} ${exec_headers} ${PROJECT_PUBLIC_HEADERS} ${input_srcs} ${headers}
"${CMAKE_SOURCE_DIR}/src/build-scripts/process-ptx.py"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
endfunction ()
+80 -43
View File
@@ -53,7 +53,9 @@ else ()
# cmake output (e.g. boost 1.70.0, cmake <= 3.14). Specifically it fails
# to set the expected variables printed below. So until that's fixed
# force FindBoost.cmake to use the original brute force path.
set (Boost_NO_BOOST_CMAKE ON)
if (NOT DEFINED Boost_NO_BOOST_CMAKE)
set (Boost_NO_BOOST_CMAKE ON)
endif ()
checked_find_package (Boost REQUIRED
VERSION_MIN 1.55
COMPONENTS ${Boost_COMPONENTS}
@@ -80,10 +82,10 @@ checked_find_package (ZLIB REQUIRED) # Needed by several packages
# IlmBase & OpenEXR
checked_find_package (OpenEXR REQUIRED
VERSION_MIN 2.3
RECOMMEND_MIN 2.4
VERSION_MIN 2.4
RECOMMEND_MIN 2.5
RECOMMEND_MIN_REASON
"Even extremely critical patches are no longer supplied to < 2.4"
"Even extremely critical patches are no longer supplied to < 2.5"
PRINT IMATH_INCLUDES
)
# Force Imath includes to be before everything else to ensure that we have
@@ -105,7 +107,7 @@ endif ()
# OpenImageIO
checked_find_package (OpenImageIO REQUIRED
VERSION_MIN 2.3.17
VERSION_MIN 2.4
DEFINITIONS -DOIIO_HIDE_FORMAT=1)
checked_find_package (pugixml REQUIRED
@@ -115,6 +117,7 @@ checked_find_package (pugixml REQUIRED
# LLVM library setup
checked_find_package (LLVM REQUIRED
VERSION_MIN 9.0
VERSION_MAX 17.9
PRINT LLVM_SYSTEM_LIBRARIES CLANG_LIBRARIES)
# ensure include directory is added (in case of non-standard locations
include_directories (BEFORE SYSTEM "${LLVM_INCLUDES}")
@@ -144,6 +147,35 @@ if (LLVM_VERSION VERSION_GREATER_EQUAL 15.0
"If you are using LLVM 15 or higher, you should also use clang version "
"15 or higher, or you may get build errors.${ColorReset}\n")
endif ()
if (LLVM_VERSION VERSION_GREATER_EQUAL 16.0)
if (CMAKE_CXX_STANDARD VERSION_LESS 17)
message (WARNING "${ColorYellow}LLVM 16+ requires C++17 or higher. "
"Please set CMAKE_CXX_STANDARD to 17 or higher.${ColorReset}\n")
endif ()
if (CMAKE_COMPILER_IS_GNUCC AND (GCC_VERSION VERSION_LESS 7.0))
message (WARNING "${ColorYellow}LLVM 16+ requires gcc 7.0 or higher.${ColorReset}\n")
endif ()
if (CMAKE_COMPILER_IS_CLANG AND (CLANG_VERSION_STRING VERSION_LESS 5.0))
message (WARNING "${ColorYellow}LLVM 16+ requires clang 5.0 or higher.${ColorReset}\n")
endif ()
endif ()
# Use opaque pointers starting with LLVM 16
if (${LLVM_VERSION} VERSION_GREATER_EQUAL 16.0)
set(LLVM_OPAQUE_POINTERS ON)
add_definitions (-DOSL_LLVM_OPAQUE_POINTERS)
else()
set(LLVM_OPAQUE_POINTERS OFF)
endif()
# Enable new pass manager for LLVM 16+
if (${LLVM_VERSION} VERSION_GREATER_EQUAL 16.0)
set(LLVM_NEW_PASS_MANAGER ON)
add_definitions (-DOSL_LLVM_NEW_PASS_MANAGER)
else()
set(LLVM_NEW_PASS_MANAGER OFF)
endif()
checked_find_package (partio)
@@ -153,58 +185,64 @@ find_python ()
# Qt -- used for osltoy
set (qt5_modules Core Gui Widgets)
if (OPENGL_FOUND)
list (APPEND qt5_modules OpenGL)
endif ()
option (USE_QT "Use Qt if found" ON)
checked_find_package (Qt5 COMPONENTS ${qt5_modules})
if (USE_QT AND NOT Qt5_FOUND AND APPLE)
message (STATUS " If you think you installed qt5 with Homebrew and it still doesn't work,")
message (STATUS " try: export PATH=/usr/local/opt/qt5/bin:$PATH")
if (USE_QT)
checked_find_package (Qt6 COMPONENTS Core Gui Widgets OpenGLWidgets)
if (NOT Qt6_FOUND)
checked_find_package (Qt5 COMPONENTS Core Gui Widgets OpenGL)
endif ()
if (NOT Qt5_FOUND AND NOT Qt6_FOUND AND APPLE)
message (STATUS " If you think you installed qt with Homebrew and it still doesn't work,")
message (STATUS " try: export PATH=/usr/local/opt/qt/bin:$PATH")
endif ()
endif ()
# CUDA setup
if (USE_CUDA OR USE_OPTIX)
if (NOT CUDA_TOOLKIT_ROOT_DIR AND NOT $ENV{CUDA_TOOLKIT_ROOT_DIR} STREQUAL "")
set (CUDA_TOOLKIT_ROOT_DIR $ENV{CUDA_TOOLKIT_ROOT_DIR})
endif ()
if (OSL_USE_OPTIX)
if (USE_LLVM_BITCODE)
if (NOT CUDA_TOOLKIT_ROOT_DIR AND NOT $ENV{CUDA_TOOLKIT_ROOT_DIR} STREQUAL "")
set (CUDA_TOOLKIT_ROOT_DIR $ENV{CUDA_TOOLKIT_ROOT_DIR})
endif ()
if (NOT CUDA_FIND_QUIETLY OR NOT OptiX_FIND_QUIETLY)
message (STATUS "CUDA_TOOLKIT_ROOT_DIR = ${CUDA_TOOLKIT_ROOT_DIR}")
endif ()
if (NOT CUDA_FIND_QUIETLY OR NOT OptiX_FIND_QUIETLY)
message (STATUS "CUDA_TOOLKIT_ROOT_DIR = ${CUDA_TOOLKIT_ROOT_DIR}")
endif ()
checked_find_package (CUDA REQUIRED
VERSION_MIN 8.0
PRINT CUDA_INCLUDES)
set (CUDA_INCLUDES ${CUDA_TOOLKIT_ROOT_DIR}/include)
include_directories (BEFORE "${CUDA_INCLUDES}")
checked_find_package (CUDA REQUIRED
VERSION_MIN 9.0
RECOMMEND_MIN 11.0
RECOMMEND_MIN_REASON
"We don't actively test CUDA older than 11"
PRINT CUDA_INCLUDES)
set (CUDA_INCLUDES ${CUDA_TOOLKIT_ROOT_DIR}/include)
include_directories (BEFORE "${CUDA_INCLUDES}")
STRING (FIND ${LLVM_TARGETS} "NVPTX" nvptx_index)
if (NOT ${nvptx_index} GREATER -1)
message (FATAL_ERROR "NVPTX target is not available in the provided LLVM build")
endif()
STRING (FIND ${LLVM_TARGETS} "NVPTX" nvptx_index)
if (NOT ${nvptx_index} GREATER -1)
message (FATAL_ERROR "NVPTX target is not available in the provided LLVM build")
endif()
set (CUDA_LIB_FLAGS "--cuda-path=${CUDA_TOOLKIT_ROOT_DIR}")
set (CUDA_LIB_FLAGS "--cuda-path=${CUDA_TOOLKIT_ROOT_DIR}")
find_library(cuda_lib NAMES cudart
PATHS "${CUDA_TOOLKIT_ROOT_DIR}/lib64" "${CUDA_TOOLKIT_ROOT_DIR}/x64"
REQUIRED)
set(CUDA_LIBRARIES ${cuda_lib})
find_library(cuda_lib NAMES cudart
PATHS "${CUDA_TOOLKIT_ROOT_DIR}/lib64" "${CUDA_TOOLKIT_ROOT_DIR}/x64" "${CUDA_TOOLKIT_ROOT_DIR}/lib/x64"
REQUIRED)
set(CUDA_LIBRARIES ${cuda_lib})
# testrender & testshade need libnvrtc
if ("${CUDA_VERSION}" VERSION_GREATER_EQUAL "10.0")
find_library(nvrtc_lib NAMES nvrtc
PATHS "${CUDA_TOOLKIT_ROOT_DIR}/lib64" "${CUDA_TOOLKIT_ROOT_DIR}/x64"
REQUIRED)
set(CUDA_LIBRARIES ${CUDA_LIBRARIES} ${nvrtc_lib})
# testrender & testshade need libnvrtc
if ("${CUDA_VERSION}" VERSION_GREATER_EQUAL "10.0")
find_library(nvrtc_lib NAMES nvrtc
PATHS "${CUDA_TOOLKIT_ROOT_DIR}/lib64" "${CUDA_TOOLKIT_ROOT_DIR}/x64" "${CUDA_TOOLKIT_ROOT_DIR}/lib/x64"
REQUIRED)
set(CUDA_LIBRARIES ${CUDA_LIBRARIES} ${nvrtc_lib})
set(CUDA_EXTRA_LIBS ${CUDA_EXTRA_LIBS} dl)
set(CUDA_EXTRA_LIBS ${CUDA_EXTRA_LIBS} dl)
endif()
endif()
# OptiX setup
if (USE_OPTIX)
if (OSL_USE_OPTIX AND OSL_BUILD_TESTS)
checked_find_package (OptiX REQUIRED
VERSION_MIN 7.0)
include_directories (BEFORE "${OPTIX_INCLUDES}")
@@ -219,7 +257,6 @@ if (USE_CUDA OR USE_OPTIX)
target_compile_definitions (${TARGET} PRIVATE "-DPTX_PATH=\"${OSL_PTX_INSTALL_DIR}\"")
target_link_libraries (${TARGET} PRIVATE ${CUDA_LIBRARIES} ${CUDA_EXTRA_LIBS} ${OPTIX_LIBRARIES} ${OPTIX_EXTRA_LIBS})
endfunction()
else ()
function (osl_optix_target TARGET)
endfunction()
+2 -6
View File
@@ -38,9 +38,7 @@ if ( FLEX_EXECUTABLE AND BISON_EXECUTABLE )
# XXX: This may be excessive now that OSL::pvt::ExtraArg is mangled into the function signature
add_definitions(-D${prefix}parse=${PROJ_NAMESPACE_V}_${prefix}parse)
if (VERBOSE)
message (STATUS "FLEX_BISON flex=${flexsrc} bison=${bisonsrc} prefix=${prefix}")
endif ()
message (VERBOSE "FLEX_BISON flex=${flexsrc} bison=${bisonsrc} prefix=${prefix}")
get_filename_component ( bisonsrc_we ${bisonsrc} NAME_WE )
set ( bisonoutputcxx "${CMAKE_CURRENT_BINARY_DIR}/${bisonsrc_we}.cpp" )
set ( bisonoutputh "${CMAKE_CURRENT_BINARY_DIR}/${bisonsrc_we}.h" )
@@ -54,9 +52,7 @@ if ( FLEX_EXECUTABLE AND BISON_EXECUTABLE )
get_filename_component ( FLEX_UP ${FLEX_EXECUTABLE} PATH )
get_filename_component ( FLEX_UP_UP ${FLEX_UP} PATH )
set ( FLEX_INCLUDE_DIR "${FLEX_UP_UP}/include" )
if (VERBOSE)
message (STATUS "Flex include dir = ${FLEX_INCLUDE_DIR}")
endif ()
message (VERBOSE "Flex include dir = ${FLEX_INCLUDE_DIR}")
include_directories ( ${FLEX_INCLUDE_DIR} )
# include_directories ( ${CMAKE_CURRENT_BINARY_DIR} )
+18 -37
View File
@@ -2,28 +2,24 @@
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
# TODO: Use CMAKE_CURRENT_FUNCTION_LIST_DIR in cmake-3.17
set(_THIS_MODULE_BASE_DIR "${CMAKE_CURRENT_LIST_DIR}")
function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_cpp extra_clang_args)
function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_cpp extra_clang_args include_dirs)
if (VERBOSE)
message (STATUS "EMBED_LLVM_BITCODE_IN_CPP src_list=${src_list}")
endif ()
message (VERBOSE "EMBED_LLVM_BITCODE_IN_CPP src_list=${src_list}")
foreach ( src ${src_list} )
get_filename_component ( src_we ${src} NAME_WE )
set ( src_asm "${CMAKE_CURRENT_BINARY_DIR}/${src_we}${suffix}.s" )
set ( src_bc "${CMAKE_CURRENT_BINARY_DIR}/${src_we}${suffix}.bc" )
if (VERBOSE)
message (STATUS "EMBED_LLVM_BITCODE_IN_CPP in=${src}")
message (STATUS "EMBED_LLVM_BITCODE_IN_CPP asm=${src_asm}")
message (STATUS "EMBED_LLVM_BITCODE_IN_CPP bc=${src_bc}")
endif ()
message (VERBOSE "EMBED_LLVM_BITCODE_IN_CPP in=${src}")
message (VERBOSE "EMBED_LLVM_BITCODE_IN_CPP asm=${src_asm}")
message (VERBOSE "EMBED_LLVM_BITCODE_IN_CPP bc=${src_bc}")
list ( APPEND src_bc_list ${src_bc} )
get_property (CURRENT_DEFINITIONS DIRECTORY PROPERTY COMPILE_DEFINITIONS)
if (VERBOSE)
message (STATUS "Current #defines are ${CURRENT_DEFINITIONS}")
endif ()
message (VERBOSE "Current #defines are ${CURRENT_DEFINITIONS}")
foreach (def ${CURRENT_DEFINITIONS})
set (LLVM_COMPILE_FLAGS ${LLVM_COMPILE_FLAGS} "-D${def}")
endforeach()
@@ -42,9 +38,7 @@ function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_
if (NOT LLVM_BC_GENERATOR)
message (FATAL_ERROR "You must have a valid llvm bitcode generator (clang++) somewhere.")
endif ()
if (VERBOSE)
message (STATUS "Using LLVM_BC_GENERATOR ${LLVM_BC_GENERATOR} to generate bitcode.")
endif()
message (VERBOSE "Using LLVM_BC_GENERATOR ${LLVM_BC_GENERATOR} to generate bitcode.")
if (NOT LLVM_AS_TOOL)
find_program (LLVM_AS_TOOL NAMES "llvm-as"
@@ -75,14 +69,10 @@ function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_
# endif ()
#endif ()
list (TRANSFORM IMATH_INCLUDES PREPEND -I
OUTPUT_VARIABLE ALL_IMATH_INCLUDES)
list (TRANSFORM OPENEXR_INCLUDES PREPEND -I
OUTPUT_VARIABLE ALL_OPENEXR_INCLUDES)
list (TRANSFORM OpenImageIO_INCLUDES PREPEND -I
OUTPUT_VARIABLE ALL_OpenImageIO_INCLUDES)
list (TRANSFORM include_dirs PREPEND -I
OUTPUT_VARIABLE ALL_INCLUDE_DIRS)
if (${LLVM_VERSION} VERSION_GREATER_EQUAL 15.0)
if (NOT LLVM_OPAQUE_POINTERS AND ${LLVM_VERSION} VERSION_GREATER_EQUAL 15.0)
# Until we fully support opaque pointers, we need to disable
# them when using LLVM 15.
list (APPEND LLVM_COMPILE_FLAGS -Xclang -no-opaque-pointers)
@@ -93,13 +83,7 @@ function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_
add_custom_command ( OUTPUT ${src_bc}
COMMAND ${LLVM_BC_GENERATOR}
${LLVM_COMPILE_FLAGS}
"-I${CMAKE_CURRENT_SOURCE_DIR}"
"-I${CMAKE_SOURCE_DIR}/src/include"
"-I${CMAKE_BINARY_DIR}/include"
${ALL_OpenImageIO_INCLUDES}
${ALL_IMATH_INCLUDES}
#"-isystem ${Boost_INCLUDE_DIRS}" #Does not pick up usr installed boost/thread/tss.hpp for oslexec_pvt.h
"-I${Boost_INCLUDE_DIRS}"
${ALL_INCLUDE_DIRS}
-DOSL_COMPILING_TO_BITCODE=1
-Wno-deprecated-register
# the following 2 warnings can be restored when all 3rd parties have fixed their export macros
@@ -114,12 +98,9 @@ function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
endforeach ()
if (VERBOSE)
message ( STATUS "^^^^^^^^^^^^^^^^^^^^^^^^^^" )
message ( STATUS "src_bc_list: ${src_bc_list} ")
message ( STATUS "^^^^^^^^^^^^^^^^^^^^^^^^^^" )
endif()
message (VERBOSE "^^^^^^^^^^^^^^^^^^^^^^^^^^" )
message (VERBOSE "src_bc_list: ${src_bc_list} ")
message (VERBOSE "^^^^^^^^^^^^^^^^^^^^^^^^^^" )
# Link all of the individual LLVM bitcode files
set ( linked_src_bc "${CMAKE_CURRENT_BINARY_DIR}/${output_name}.bc" )
@@ -131,9 +112,9 @@ function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_
# Serialize the linked bitcode into a CPP file
set ( src_bc_cpp "${CMAKE_CURRENT_BINARY_DIR}/${output_name}.bc.cpp" )
add_custom_command ( OUTPUT ${src_bc_cpp}
COMMAND ${Python_EXECUTABLE} "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py"
COMMAND ${Python_EXECUTABLE} "${_THIS_MODULE_BASE_DIR}/../build-scripts/serialize-bc.py"
${linked_src_bc} ${src_bc_cpp} ${output_name}
DEPENDS "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py" ${linked_src_bc}
DEPENDS "${_THIS_MODULE_BASE_DIR}/../build-scripts/serialize-bc.py" ${linked_src_bc}
${exec_headers} ${PROJECT_PUBLIC_HEADERS}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
+10 -3
View File
@@ -23,7 +23,13 @@
# try to find llvm-config, with a specific version if specified
if (LLVM_DIRECTORY)
set (LLVM_CONFIG_PATH_HINTS "${LLVM_DIRECTORY}/bin")
list (APPEND LLVM_CONFIG_PATH_HINTS "${LLVM_DIRECTORY}/bin")
endif ()
if (LLVM_ROOT)
list (APPEND LLVM_CONFIG_PATH_HINTS "${LLVM_ROOT}/bin")
endif ()
if (DEFINED ENV{LLVM_ROOT})
list (APPEND LLVM_CONFIG_PATH_HINTS "$ENV{LLVM_ROOT}/bin")
endif ()
list (APPEND LLVM_CONFIG_PATH_HINTS
"/usr/local/opt/llvm/${LLVM_VERSION}/bin/"
@@ -120,8 +126,9 @@ if (LLVM_VERSION VERSION_GREATER_EQUAL 9.0 AND (LLVM_SHARED_MODE STREQUAL "share
endif ()
foreach (COMPONENT clangFrontend clangDriver clangSerialization
clangParse clangSema clangAnalysis clangAST clangBasic
clangEdit clangLex)
clangParse clangSema clangAnalysis clangAST
clangASTMatchers clangBasic clangEdit clangLex
clangSupport)
find_library ( _CLANG_${COMPONENT}_LIBRARY
NAMES ${COMPONENT}
PATHS ${LLVM_LIB_DIR})
+5 -160
View File
@@ -7,7 +7,7 @@
# I'm afraid this is a mess, due to needing to support a wide range of
# OpenEXR versions.
#
# For OpenEXR & Imath 3.0, this will establish the following imported
# For OpenEXR & Imath 3.x, this will establish the following imported
# targets:
#
# Imath::Imath
@@ -24,14 +24,12 @@
# IlmBase::IlmThread
# OpenEXR::IlmImf
#
# For all versions -- but for OpenEXR < 2.4 the only thing this sets --
# are the following CMake variables:
# For all version, the following CMake variables:
#
# OPENEXR_FOUND true, if found
# OPENEXR_INCLUDES directory where OpenEXR headers are found
# OPENEXR_LIBRARIES libraries for OpenEXR + IlmBase
# OPENEXR_VERSION OpenEXR version (accurate for >= 2.0.0,
# otherwise will just guess 1.6.1)
# OPENEXR_VERSION OpenEXR version
# IMATH_INCLUDES directory where Imath headers are found
# ILMBASE_INCLUDES directory where IlmBase headers are found
# ILMBASE_LIBRARIES libraries just IlmBase
@@ -50,7 +48,7 @@ if (TARGET OpenEXR::OpenEXR AND TARGET Imath::Imath)
# OpenEXR 3.x if both of these targets are found
set (FOUND_OPENEXR_WITH_CONFIG 1)
if (NOT OpenEXR_FIND_QUIETLY)
message (STATUS "Found CONFIG for OpenEXR 3 (OPENEXR_VERSION=${OpenEXR_VERSION})")
message (STATUS "Found CONFIG for OpenEXR 3 (OpenEXR_VERSION=${OpenEXR_VERSION})")
endif ()
# Mimic old style variables
@@ -80,7 +78,7 @@ elseif (TARGET OpenEXR::IlmImf AND TARGET IlmBase::Imath AND
# OpenEXR 2.4 or 2.5 with exported config
set (FOUND_OPENEXR_WITH_CONFIG 1)
if (NOT OpenEXR_FIND_QUIETLY)
message (STATUS "Found CONFIG for OpenEXR 2 (OPENEXR_VERSION=${OpenEXR_VERSION})")
message (STATUS "Found CONFIG for OpenEXR 2 (OpenEXR_VERSION=${OpenEXR_VERSION})")
endif ()
# Mimic old style variables
@@ -111,157 +109,4 @@ elseif (TARGET OpenEXR::IlmImf AND TARGET IlmBase::Imath AND
string(REGEX REPLACE "include/OpenEXR$" "include" IMATH_INCLUDES "${IMATH_INCLUDES}")
string(REGEX REPLACE "include/OpenEXR$" "include" OPENEXR_INCLUDES "${OPENEXR_INCLUDES}")
else ()
# OpenEXR 2.x older versions without a config or whose configs we don't
# trust.
set (FOUND_OPENEXR_WITH_CONFIG 0)
# Other standard issue macros
include (FindPackageHandleStandardArgs)
include (SelectLibraryConfigurations)
find_package (ZLIB REQUIRED)
# Link with pthreads if required
find_package (Threads)
if (CMAKE_USE_PTHREADS_INIT)
set (ILMBASE_PTHREADS ${CMAKE_THREAD_LIBS_INIT})
endif ()
# Attempt to find OpenEXR with pkgconfig
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
if (NOT Ilmbase_ROOT AND NOT ILMBASE_ROOT
AND NOT DEFINED ENV{Ilmbase_ROOT} AND NOT DEFINED ENV{ILMBASE_ROOT})
pkg_check_modules(_ILMBASE QUIET IlmBase>=2.0.0)
endif ()
if (NOT OpenEXR_ROOT AND NOT OPENEXR_ROOT
AND NOT DEFINED ENV{OpenEXR_ROOT} AND NOT DEFINED ENV{OPENEXR_ROOT})
pkg_check_modules(_OPENEXR QUIET OpenEXR>=2.0.0)
endif ()
endif (PKG_CONFIG_FOUND)
# List of likely places to find the headers -- note priority override of
# ${OPENEXR_ROOT}/include.
# ILMBASE is needed in case ilmbase an openexr are installed in separate
# directories, like NixOS does
set (GENERIC_INCLUDE_PATHS
${OPENEXR_ROOT}/include
$ENV{OPENEXR_ROOT}/include
${ILMBASE_ROOT}/include
$ENV{ILMBASE_ROOT}/include
${_ILMBASE_INCLUDEDIR}
${_OPENEXR_INCLUDEDIR}
/usr/local/include
/usr/include
/usr/include/${CMAKE_LIBRARY_ARCHITECTURE}
/sw/include
/opt/local/include )
# Find the include file locations.
find_path (ILMBASE_INCLUDE_PATH OpenEXR/IlmBaseConfig.h
HINTS ${ILMBASE_INCLUDE_DIR} ${OPENEXR_INCLUDE_DIR}
${GENERIC_INCLUDE_PATHS} )
find_path (OPENEXR_INCLUDE_PATH OpenEXR/OpenEXRConfig.h
HINTS ${OPENEXR_INCLUDE_DIR}
${GENERIC_INCLUDE_PATHS} )
# Try to figure out version number
if (DEFINED _OPENEXR_VERSION AND NOT "${_OPENEXR_VERSION}" STREQUAL "")
set (OPENEXR_VERSION "${_OPENEXR_VERSION}")
string (REGEX REPLACE "([0-9]+)\\.[0-9\\.]+" "\\1" OPENEXR_VERSION_MAJOR "${_OPENEXR_VERSION}")
string (REGEX REPLACE "[0-9]+\\.([0-9]+)(\\.[0-9]+)?" "\\1" OPENEXR_VERSION_MINOR "${_OPENEXR_VERSION}")
elseif (EXISTS "${OPENEXR_INCLUDE_PATH}/OpenEXR/ImfMultiPartInputFile.h")
# Must be at least 2.0
file(STRINGS "${OPENEXR_INCLUDE_PATH}/OpenEXR/OpenEXRConfig.h" TMP REGEX "^#define OPENEXR_VERSION_STRING .*$")
string (REGEX MATCHALL "[0-9]+[.0-9]+" OPENEXR_VERSION ${TMP})
file(STRINGS "${OPENEXR_INCLUDE_PATH}/OpenEXR/OpenEXRConfig.h" TMP REGEX "^#define OPENEXR_VERSION_MAJOR .*$")
string (REGEX MATCHALL "[0-9]+" OPENEXR_VERSION_MAJOR ${TMP})
file(STRINGS "${OPENEXR_INCLUDE_PATH}/OpenEXR/OpenEXRConfig.h" TMP REGEX "^#define OPENEXR_VERSION_MINOR .*$")
string (REGEX MATCHALL "[0-9]+" OPENEXR_VERSION_MINOR ${TMP})
else ()
# Assume an old one, predates 2.x that had versions
set (OPENEXR_VERSION 1.6.1)
set (OPENEXR_MAJOR 1)
set (OPENEXR_MINOR 6)
endif ()
# List of likely places to find the libraries -- note priority override of
# ${OPENEXR_ROOT}/lib.
set (GENERIC_LIBRARY_PATHS
${OPENEXR_ROOT}/lib
${ILMBASE_ROOT}/lib
${OPENEXR_INCLUDE_PATH}/../lib
${ILMBASE_INCLUDE_PATH}/../lib
${_ILMBASE_LIBDIR}
${_OPENEXR_LIBDIR}
/usr/local/lib
/usr/local/lib/${CMAKE_LIBRARY_ARCHITECTURE}
/usr/lib
/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}
/sw/lib
/opt/local/lib
$ENV{PROGRAM_FILES}/OpenEXR/lib/static )
# message (STATUS "Generic lib paths: ${GENERIC_LIBRARY_PATHS}")
# Handle request for static libs by altering CMAKE_FIND_LIBRARY_SUFFIXES.
# We will restore it at the end of this file.
set (_openexr_orig_suffixes ${CMAKE_FIND_LIBRARY_SUFFIXES})
if (OpenEXR_USE_STATIC_LIBS)
if (WIN32)
set (CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
else ()
set (CMAKE_FIND_LIBRARY_SUFFIXES .a)
endif ()
endif ()
# Look for the libraries themselves, for all the components.
# This is complicated because the OpenEXR libraries may or may not be
# built with version numbers embedded.
set (_openexr_components IlmThread IlmImf Imath Iex Half)
foreach (COMPONENT ${_openexr_components})
string (TOUPPER ${COMPONENT} UPPERCOMPONENT)
# First try with the version embedded
find_library (OPENEXR_${UPPERCOMPONENT}_LIBRARY
NAMES ${COMPONENT}-${OPENEXR_VERSION_MAJOR}_${OPENEXR_VERSION_MINOR}
${COMPONENT}
${COMPONENT}-${OPENEXR_VERSION_MAJOR}_${OPENEXR_VERSION_MINOR}_d
${COMPONENT}_d
HINTS ${OPENEXR_LIBRARY_DIR} $ENV{OPENEXR_LIBRARY_DIR}
${GENERIC_LIBRARY_PATHS} )
endforeach ()
find_package_handle_standard_args (OpenEXR
REQUIRED_VARS ILMBASE_INCLUDE_PATH OPENEXR_INCLUDE_PATH
OPENEXR_IMATH_LIBRARY OPENEXR_ILMIMF_LIBRARY
OPENEXR_IEX_LIBRARY OPENEXR_HALF_LIBRARY
)
if (OPENEXR_FOUND)
set (OpenEXR_VERSION ${OPENEXR_VERSION})
set (ILMBASE_FOUND TRUE)
set (ILMBASE_INCLUDES ${ILMBASE_INCLUDE_PATH})
set (IMATH_INCLUDES ${ILMBASE_INCLUDE_PATH})
set (OPENEXR_INCLUDES ${OPENEXR_INCLUDE_PATH})
set (ILMBASE_INCLUDE_DIR ${ILMBASE_INCLUDE_PATH})
set (IMATH_INCLUDE_DIR ${ILMBASE_INCLUDE_PATH})
set (OPENEXR_INCLUDE_DIR ${OPENEXR_INCLUDE_PATH})
set (ILMBASE_LIBRARIES ${OPENEXR_IMATH_LIBRARY} ${OPENEXR_IEX_LIBRARY} ${OPENEXR_HALF_LIBRARY} ${OPENEXR_ILMTHREAD_LIBRARY} ${ILMBASE_PTHREADS} CACHE STRING "The libraries needed to use IlmBase")
set (OPENEXR_LIBRARIES ${OPENEXR_ILMIMF_LIBRARY} ${ILMBASE_LIBRARIES} ${ZLIB_LIBRARIES} CACHE STRING "The libraries needed to use OpenEXR")
set (FINDOPENEXR_FALLBACK TRUE)
endif ()
mark_as_advanced(
OPENEXR_ILMIMF_LIBRARY
OPENEXR_IMATH_LIBRARY
OPENEXR_IEX_LIBRARY
OPENEXR_HALF_LIBRARY
OPENEXR_VERSION)
# Restore the original CMAKE_FIND_LIBRARY_SUFFIXES
set (CMAKE_FIND_LIBRARY_SUFFIXES ${_openexr_orig_suffixes})
endif ()
+2 -6
View File
@@ -13,13 +13,9 @@
# Hack! prefer a config if it can be found
find_package(partio CONFIG)
if (PARTIO_FOUND OR partio_FOUND)
if (VERBOSE)
message (STATUS "partio found via config")
endif ()
message (VERBOSE "partio found via config")
else ()
if (VERBOSE)
message (STATUS "partio falling back to FindPartio.cmake")
endif ()
message (VERBOSE "partio falling back to FindPartio.cmake")
find_path (PARTIO_INCLUDE_DIR NAMES Partio.h)
+1 -1
View File
@@ -16,7 +16,7 @@ find_package (pugixml CONFIG)
if (TARGET pugixml::pugixml)
# New pugixml (>= 1.11) has nice config files we can rely on and makes a
# pugixml::pugixml target.
message (STATUS "Found CONFIG for pugixml (>=1.11)")
message (VERBOSE "Found CONFIG for pugixml (>=1.11)")
set (PUGIXML_FOUND true)
set (pugixml_FOUND true)
+7 -14
View File
@@ -20,12 +20,9 @@ macro (find_python)
# Attempt to find the desired version, but fall back to other
# additional versions.
unset (_req)
if (USE_PYTHON)
set (_req REQUIRED)
if (PYTHON_VERSION)
list (APPEND _req EXACT)
endif ()
set (_req REQUIRED)
if (PYTHON_VERSION)
list (APPEND _req EXACT)
endif ()
checked_find_package (Python ${PYTHON_VERSION}
${_req}
@@ -46,11 +43,9 @@ macro (find_python)
if (NOT DEFINED PYTHON_SITE_DIR)
set (PYTHON_SITE_DIR "${CMAKE_INSTALL_LIBDIR}/python${PYTHON_VERSION_FOUND}/site-packages")
endif ()
if (VERBOSE)
message (STATUS " Python site packages dir ${PYTHON_SITE_DIR}")
message (STATUS " Python to include 'lib' prefix: ${PYLIB_LIB_PREFIX}")
message (STATUS " Python to include SO version: ${PYLIB_INCLUDE_SONAME}")
endif ()
message (VERBOSE " Python site packages dir ${PYTHON_SITE_DIR}")
message (VERBOSE " Python to include 'lib' prefix: ${PYLIB_LIB_PREFIX}")
message (VERBOSE " Python to include SO version: ${PYLIB_INCLUDE_SONAME}")
endmacro()
@@ -98,9 +93,7 @@ macro (setup_python_module)
endif ()
if (PYLIB_INCLUDE_SONAME)
if (VERBOSE)
message(STATUS "Setting Py${lib_MODULE} SOVERSION to: ${SOVERSION}")
endif ()
message(VERBOSE "Setting Py${lib_MODULE} SOVERSION to: ${SOVERSION}")
set_target_properties(${target_name} PROPERTIES
VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
SOVERSION ${SOVERSION} )
+38 -20
View File
@@ -71,6 +71,10 @@ macro (add_one_testsuite testname testsrcdir)
set_tests_properties (${testname} PROPERTIES LABELS render
PROCESSORS 4 COST 10 TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
endif ()
# For debug builds, render tests are very slow, so give them a longer timeout
if (${testname} MATCHES "render-" AND ${CMAKE_BUILD_TYPE} STREQUAL Debug)
set_tests_properties (${testname} PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
endif ()
# Some labeling for fun
if (${testname} MATCHES "^texture")
set_tests_properties (${testname} PROPERTIES LABELS texture
@@ -139,14 +143,22 @@ macro ( TESTSUITE )
add_one_testsuite ("${_testname}.opt" "${_testsrcdir}"
ENV TESTSHADE_OPT=2 )
endif ()
if (_testname MATCHES "render-" AND ${CMAKE_BUILD_TYPE} STREQUAL Debug)
set_tests_properties (${_testname} PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
# Run the same test again with aggressive -O2 runtime
# optimization, triggered by setting TESTSHADE_OPT env variable.
# Skip OptiX-only tests and those with a NOOPTIMIZE marker file.
if (NOT _testname MATCHES "optix"
AND NOT EXISTS "${_testsrcdir}/NOSCALAR"
AND NOT EXISTS "${_testsrcdir}/BATCHED_REGRESSION"
AND NOT EXISTS "${_testsrcdir}/NOOPTIMIZE"
AND NOT EXISTS "${_testsrcdir}/NORSBITCODE")
add_one_testsuite ("${_testname}.opt.rs_bitcode" "${_testsrcdir}"
ENV TESTSHADE_OPT=2 TESTSHADE_RS_BITCODE=1)
endif ()
# When building for OptiX support, also run it in OptiX mode
# if there is an OPTIX marker file in the directory.
# If an environment variable $TESTSUITE_OPTIX is nonzero, then
# run all tests with OptiX, even if there's no OPTIX marker.
if (USE_OPTIX
if (OSL_USE_OPTIX
AND (EXISTS "${_testsrcdir}/OPTIX" OR test_all_optix OR _testname MATCHES "optix")
AND NOT EXISTS "${_testsrcdir}/NOOPTIX"
AND NOT EXISTS "${_testsrcdir}/NOOPTIX-FIXME"
@@ -159,9 +171,14 @@ macro ( TESTSUITE )
# and optimized
add_one_testsuite ("${_testname}.optix.opt" "${_testsrcdir}"
ENV TESTSHADE_OPT=2 TESTSHADE_OPTIX=1 )
if (NOT EXISTS "${_testsrcdir}/NOFUSED")
# and fused
add_one_testsuite ("${_testname}.optix.fused" "${_testsrcdir}"
ENV TESTSHADE_OPT=2 TESTSHADE_OPTIX=1 TESTSHADE_FUSED=1 )
endif()
endif ()
if (BUILD_BATCHED)
if (OSL_BUILD_BATCHED)
# When building for Batched support, also run it in Batched mode
# if there is an BATCHED marker file in the directory.
# If an environment variable $TESTSUITE_BATCHED is nonzero, then
@@ -219,9 +236,7 @@ macro ( TESTSUITE )
endif ()
endforeach ()
if (VERBOSE)
message (STATUS "Added tests: ${ALL_TEST_LIST}")
endif ()
message (VERBOSE "Added tests: ${ALL_TEST_LIST}")
endmacro ()
macro (osl_add_all_tests)
@@ -236,8 +251,9 @@ macro (osl_add_all_tests)
bug-array-heapoffsets bug-locallifetime bug-outputinit
bug-param-duplicate bug-peep bug-return
calculatenormal-reg
cellnoise closure closure-array color color-reg colorspace comparison
complement-reg compile-buffer compassign-reg
cellnoise closure closure-array closure-layered closure-parameters closure-zero closure-conditional
color color-reg colorspace comparison
complement-reg compile-buffer compassign-bool compassign-reg
component-range
control-flow-reg connect-components
const-array-params const-array-fill
@@ -252,10 +268,11 @@ macro (osl_add_all_tests)
for-reg format-reg fprintf
function-earlyreturn function-simple function-outputelem
function-overloads function-redef
geomath getattribute-camera getattribute-shader
geomath getattribute-camera getattribute-shader getattribute-shading
getsymbol-nonheap gettextureinfo gettextureinfo-reg
gettextureinfo-udim gettextureinfo-udim-reg
globals-needed
group-outputs groupstring
group-outputs groupdata-opt groupstring
hash hashnoise hex hyperb
ieee_fp ieee_fp-reg if if-reg incdec initlist
initops initops-instance-clash
@@ -297,6 +314,7 @@ macro (osl_add_all_tests)
oslc-err-struct-dup oslc-err-struct-print
oslc-err-type-as-variable
oslc-err-unknown-ctr
oslc-literalfold
oslc-pragma-warnerr
oslc-warn-commainit
oslc-variadic-macro
@@ -308,7 +326,8 @@ macro (osl_add_all_tests)
pragma-nowarn
printf-reg
printf-whole-array
raytype raytype-reg raytype-specialized regex-reg reparam
raytype raytype-reg raytype-specialized regex-reg
reparam reparam-arrays testoptix-reparam
render-background render-bumptest
render-cornell render-furnace-diffuse
render-mx-furnace-burley-diffuse
@@ -322,6 +341,7 @@ macro (osl_add_all_tests)
render-mx-sheen
render-microfacet render-oren-nayar
render-uv render-veachmis render-ward
render-raytypes
select select-reg shaderglobals shortcircuit
smoothstep-reg
spline spline-reg splineinverse splineinverse-ident
@@ -336,6 +356,9 @@ macro (osl_add_all_tests)
struct-nested struct-nested-assign struct-nested-deep
ternary
testshade-expr
test-fmt-arrays test-fmt-fileprint
test-fmt-cxpf test-fmt-noise test-fmt-matrixcolor
test-fmt-stpf test-fmt-errorwarning test-fmt-errorwarning-repeats
texture-alpha texture-alpha-derivs
texture-blur texture-connected-options
texture-derivs texture-environment texture-errormsg
@@ -351,17 +374,12 @@ macro (osl_add_all_tests)
transform transform-reg transformc transformc-reg trig trig-reg
typecast
unknown-instruction
userdata userdata-passthrough
userdata userdata-partial userdata-custom userdata-passthrough
vararray-connect vararray-default
vararray-deserialize vararray-param
vecctr vector vector-reg
wavelength_color wavelength_color-reg Werror xml xml-reg )
# Coordinate-aware gettextureinfo only works for TextureSystem >= 2.3.7
if (OpenImageIO_VERSION VERSION_GREATER_EQUAL 2.3.7)
TESTSUITE ( gettextureinfo-udim gettextureinfo-udim-reg )
endif ()
# Only run the ocio test if the OIIO we are using has OCIO support
if (OpenImageIO_HAS_OpenColorIO)
TESTSUITE ( ocio )
@@ -383,7 +401,7 @@ macro (osl_add_all_tests)
endif()
# Only run pointcloud tests if Partio is found
if (PARTIO_FOUND)
if (partio_FOUND)
TESTSUITE ( pointcloud pointcloud-fold )
endif ()
@@ -393,7 +411,7 @@ macro (osl_add_all_tests)
endif ()
# Some regression tests have a lot of combinations and may need more time to finish
if (BUILD_BATCHED)
if (OSL_BUILD_BATCHED)
set_tests_properties (arithmetic-reg.regress.batched.opt
PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
set_tests_properties (transform-reg.regress.batched.opt
+1 -3
View File
@@ -38,9 +38,7 @@ macro (docdeep_generate)
# ^^ syntax: prefix options one-arg-keywords multi-arg-keywords args
set (oslfile ${_docdeep_SOURCE})
set (mdfile "${_docdeep_NAME}.md.html")
if (VERBOSE)
message (STATUS "docdeep will make '${mdfile}'")
endif ()
message (VERBOSE "docdeep will make '${mdfile}'")
set (docdeep_program ${CMAKE_SOURCE_DIR}/src/build-scripts/docdeep.py)
add_custom_command (OUTPUT ${mdfile}
COMMAND ${Python_EXECUTABLE} ${docdeep_program} -d ${_docdeep_NAME} -s docs.css
+2556
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

+32
View File
@@ -30,3 +30,35 @@ clean:
.PHONY: clean
doxygen:
echo "make doxygen TBD"
doxygen Doxyfile
touch doxygen.turd
doxygen.turd: doxygen
doxygenclean:
cmake -E remove_directory ../../build/doxygen
cmake -E remove doxygen.turd
cmake -E remove_directory ../../build/sphinx
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SOURCEDIR = .
SPHINXBUILDDIR = ../../build/sphinx
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
sphinx : Makefile conf.py
# @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(SPHINXBUILDDIR)" $(SPHINXOPTS) $(O)
$(SPHINXBUILD) -b html "$(SOURCEDIR)" "$(SPHINXBUILDDIR)" $(SPHINXOPTS)
sphinxpdf : Makefile conf.py
# @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(SPHINXBUILDDIR)" $(SPHINXOPTS) $(O)
$(SPHINXBUILD) -b latex "$(SOURCEDIR)" "$(SPHINXBUILDDIR)/latex" $(SPHINXOPTS)
$(MAKE) -C $(SPHINXBUILDDIR)/latex all-pdf
# $(SPHINXBUILD) -b latexpdf "$(SOURCEDIR)" "$(SPHINXBUILDDIR)/latex" $(SPHINXOPTS)
+307
View File
@@ -0,0 +1,307 @@
<!--
Copyright Contributors to the Open Shading Language project.
SPDX-License-Identifier: CC-BY-4.0
-->
(chap-bigpicture=)
# The Big Picture
This chapter attempts to lay out the major concepts of OSL,
define key nomenclature, and sketch out how individual shaders fit
together in the context of a renderer as a whole.
<!--
Other than the background material of this chapter, the rest of this
specification deals strictly with the language itself. In the future,
there will be separate (shorter) documents explaining in detail the use
of the language compiler, the renderer-side issues, the library and APIs
for how a renderer actually causes shaders to be evaluated, and so on.
-->
#### A shader is code that performs a discrete task
A shader is a program, with inputs and outputs, that performs a specific
task when rendering a scene, such as determining the appearance behavior
of a material or light. The program code is written in OSL, the
specification of which comprises this document.
For example, here is a simple `gamma` shader that performs
simple gamma correction on is `Cin` input, storing the result
in its output `Cout`:
```{image} Figures/shaderschematic.png
:width: 6.0in
```
The shader's inputs and outputs are called *shader parameters*.
Parameters have default values, specified in the shader code, but may
also be given new values by the renderer at runtime.
#### Shader instances
A particular shader may be used many times in a scene, on different
objects or as different layers in a shader group. Each separate use of
a shader is called a *shader instance*. Although all instances of
a shader are comprised of the same program code, each instance may
override any or all of its default parameter values with its own set of
*instance values*.
Below is a schematic showing a `gamma` instance with the `gam` parameter
overridden with an instance-specific value of `2.2`.
```{image} Figures/instanceschematic.png
:width: 200px
```
#### Shader groups, layers, and connections
A *shader group* is an ordered sequence of individual shaders called *layers*
that are executed in turn. Output parameters of an earlier-executed layer may
be *connected* to an input parameter of a later-executed layer. This connected
network of layers is sometimes called a *shader network* or a *shader DAG*
(directed acyclic graph). Of course, it is fine for the shader group to
consist of a single shader layer.
Below is a schematic showing how several shader instances may be
connected to form a shader group.
```{image} Figures/groupschematic.png
:width: 6.0in
```
And here is sample pseudo-code shows how the above network may be assembled
using an API in the renderer [^rendererapi]:
```
ShaderGroupBegin ()
Shader ("texturemap", /* shader name */
"tex1", /* layer name */
"string name", "rings.tx") /* instance variable */
Shader ("texturemap", "tex2", "string name", "grain.tx")
Shader ("gamma", "gam1", "float gam", 2.2)
Shader ("gamma", "gam2", "float gam", 1)
Shader ("wood", "wood1")
ConnectShaders ("tex1", /* layer name A */
"Cout", /* an output parameter of A */
"gam1", /* layer name B */
"Cin") /* Connect this layer of B to A's Cout */
ConnectShaders ("tex2", "Cout", "gam2", "Cin")
ConnectShaders ("gam1", "Cout", "wood1", "rings")
ConnectShaders ("gam2", "Cout", "wood1", "grain")
ShaderGroupEnd ()
```
Or, expressed as serialized text (as detailed in Chapter [](chap-shader-groups):
param string name "rings.tx" ;
shader "texturemap" "tex1" ;
param string name "grain.tx" ;
shader "texturemap" "tex2" ;
param float gam 2.2 ;
shader "gamma" "gam1" ;
param float gam 1.0 ;
shader "gamma" "gam2" ;
shader "wood" "wood1" ;
connect tex1.Cout gam1.Cin ;
connect tex2.Cout gam2.Cin ;
connect gam1.Cout wood1.rings ;
connect gam2.Cout wood1.grain ;
The rules for which data types may be connected are generally the same as
the rules determining which variables may be assigned to each other in OSL
source code:
* `source` and `dest` are the same data type.
* `source` and `dest` are both *triples* (`color`, `point`,
`vector`, or `normal`), even if they are not the same kind of triple.
* `source` is an `int` and `dest` is a `float`.
* `source` is a `float` or `int` and `dest` is a
*triple* (the scalar value will be replicated for all three components
of the triple).
* `source` is a single component of an aggregate type (e.g. one
channel of a `color`) and `dest` is a `float` (or vice versa).
#### Geometric primitives
The *scene* consists of primarily of geometric primitives,
light sources, and cameras.
*Geometric primitives* are shapes such as NURBS, subdivision surfaces,
polygons, and curves. The exact set of supported primitives may vary
from renderer to renderer.
Each geometric primitive carries around a set of named *primitive
variables* (also sometimes called *interpolated values* or
*user data*). Nearly all shape types will have, among their primitive
variables, control point positions that, when interpolated, actually
designate the shape. Some shapes will also allow the specification of
normals or other shape-specific data. Arbitrary user data may also be
attached to a shape as primitive variables. Primitive variables may be
interpolated in a variety of ways: one constant value per primitive, one
constant value per face, or per-vertex values that are interpolated
across faces in various ways.
If a shader input parameter's name and type match the name and type
of a primitive variable on the object (and that input parameters is
not already explicitly connected to another layer's output), the
interpolated primitive variable will override the instance value or
default.
#### Attribute state and shader assignments
Every geometric primitive has a collection of *attributes* (sometimes
called the *graphics state*) that includes its transformation
matrix, the list of which lights illuminate it, whether it is one-sided
or two-sided, shader assignments, etc. There may also be a long list of
renderer-specific or user-designated attributes associated with each
object. A particular attribute state may be shared among many geometric
primitives.
The attribute state also includes shader assignments --- the shaders or
shader groups for each of several *shader uses*, such as surface
shaders that designate how light reflects or emits from each point on a shape,
displacement shaders that can add fine detail to the shape on a
point-by-point basis, and volume shaders that describe how light is
scattered within a region of space. A particular renderer may have
additional shader types that it supports.
#### Shader execution state: parameter binding and global variables
When the body of code of an individual shader is about to execute, all
its parameters are *bound* --- that is, take on specific values
(from connections from other layers, interpolated primitive variables,
instance values, or defaults, in that order).
Certain state about the position on the surface where the shading is
being run is stored in so-called *global variables*. This includes
such useful data as the 3D coordinates of the point being shaded, the
surface normal and tangents at that point, etc.
Additionally, the shader may query other information about other
elements of the attribute state attached to the primitive, and
information about the renderer as a whole (rendering options, etc.).
#### Surface and volume shaders compute closures
Surface shaders (and volume shaders) do not by themselves compute the
final color of light emanating from the surface (or along a volume).
Rather, they compute a *closure*, which is a symbolic representation
describing the appearance of the surface, that may be more fully
evaluated later. This is in effect a parameterized formula, in which
some inputs have definite numeric values, but others may depend on
quantities not yet known (such as the direction from which the surface
is being viewed, and the amount of light from each source that is
arriving at the surface).
For example, a surface shader may compute its result like this:
color paint = texture ("file.tx", u, v);
Ci = paint * diffuse (N);
In this example, the variable `paint` will take on a specific numeric
value (by looking up from a texture map). But the `diffuse()` function
returns a `color closure`, not a definite numeric `color`. The output
variable `Ci` that represents the appearance of the surface is also a `color
closure`, whose numeric value is not known yet, except that it will be the
product of `paint`` and a Lambertian reflectance.
```{image} Figures/shaderexecschematic.png
```
The closures output by surface and volume shaders can do a number of
interesting things that a mere number cannot:
* Evaluate: given input and output light directions, compute the
proportion of light propagating from input to output.
* Sample: given just an input (or output) direction, choose a
scattering direction with a probability distribution that is
proportional to the amount of light that will end up going in various
directions.
* Integrate: given all lights and a view direction, compute
the total amount of light leaving the surface in the view direction.
* Recompute: given changes only to lights (or only to one light),
recompute the integrated result without recomputing other lights or
any of the calculations that went into assembling constants in the
closure (such as texture lookups, noise functions, etc.).
<!--
At present, we are assuming that the primitive closure functions (such
as `diffuse`, `ward`, `cooktorrance`, etc.) are all built
into the renderer, or implemented as renderer plugins. At a later time,
possibly in a later draft or maybe not until a truly later version of
the spec, we will fully spec it out so that closure primitive functions
may be written in OSL. But I fear that if we do it too soon,
we'll screw it up. But, yes, the eventual goal is for you to be able to
write these primitive functions in the language itself.
-->
#### Integrators
The renderer contains a number of *integrators* (selectable via the
renderer's API) which will combine the color closures computed by
surfaces and volumes with the light sources and view-dependent
information, to yield the amount of light visible to the camera.
```{image} Figures/integratorschematic.png
:width: 6.0in
```
<!--
At present, this document is written as if the integrators are built
into the renderer itself (or implemented as renderer plug-ins). At a
later time, we intend to make it possible for integrators themselves
to be written in OSL.
-->
#### Units
You can tell the renderer (through a global option) what units the scene
is using for distance and time. Then the shader has a built-in function
called `transformu()` that works a lot like `transform()`, but
instead of converting between coordinate systems, it converts among
units. For example,
```
displacement bumpy (float bumpdist = 1,
string bumpunits = "cm")
{
// convert bumpdist to common units
float spacing = transformu (bumpunits, "common", bumpdist);
float n = noise (P / spacing);
displace (n);
}
```
So you can write a shader to achieve some effect in real world units,
and that shader is totally reusable on another show that used different
modeling units.
It knows all the standard names like `cm`, `in`, `km`,
etc., and can convert among any of those, as well as between named
coordinate systems. For example,
```
float x = transformu ("object", "mm", 1);
```
now `x` is the number of millimeters per unit of "object" space on
that primitive.
[^rendererapi]: This document does not dictate a specific renderer API for
declaring shader instances, groups, and connections; the code above is just
an example of how it might be done.
+139
View File
@@ -0,0 +1,139 @@
#!/usr/bin/env python3
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# http://www.sphinx-doc.org/en/master/config
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
from __future__ import absolute_import
import sys
import os
import shlex
import subprocess
# -- Project information -----------------------------------------------------
# The master toctree document.
master_doc = 'index'
default_role = 'code'
project = 'Open Shading Language'
copyright = 'Contributors to the Open Shading Language project'
author = 'Larry Gritz, editor'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
# LG addition: we search for it in the CMakeLists.txt so we don't need to
# keep modifying this file:
version = '0.0'
release = '0.0.0'
import re
version_regex = re.compile(r'set \(OSL_VERSION \"?((\d+\.\d+)\.\d+)\.\d+\"?\)')
f = open('../../CMakeLists.txt')
for l in f:
aa=re.search(version_regex, l)
if aa is not None:
release = aa.group(1)
version = aa.group(2)
break
f.close()
print ("OSL docs version = {}, release = {}".format(version, release))
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
# add custom extensions directory to python path
sys.path.insert(0, os.path.join(os.path.abspath(os.path.dirname(__file__)), 'extensions/sphinxtr'))
sys.path.insert(0, os.path.join(os.path.abspath(os.path.dirname(__file__)), '../../ext/breathe'))
#import html_mods
#import latex_mods
extensions = [
'breathe',
'myst_parser',
'sphinx_tabs.tabs',
]
myst_enable_extensions = [
# "amsmath",
"attrs_inline",
"colon_fence",
"deflist",
"dollarmath",
"fieldlist",
# "html_admonition",
# "html_image",
# "linkify",
# "replacements",
# "smartquotes",
# "strikethrough",
# "substitution",
# "tasklist",
]
myst_heading_anchors = 3
# Add any paths that contain templates here, relative to this directory.
templates_path = ['templates']
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
#html_theme = 'alabaster'
#html_theme = 'astropy-sphinx-theme'
# html_theme = 'sphinx_rtd_theme'
html_theme = 'furo'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Breathe options
breathe_projects = { "osl": "../../build/doxygen/xml" }
breathe_default_project = "osl"
breathe_domain_by_extension = {'h': 'cpp'}
breathe_default_members = ()
primary_domain = 'cpp'
highlight_language = 'cpp'
read_the_docs_build = os.getenv('READTHEDOCS') == 'True'
if read_the_docs_build:
print ("cwd =", os.getcwd())
print ("checkpoint -- rtd build")
if not os.path.exists('../../build/doxygen') :
os.makedirs ('../../build/doxygen')
print ("checkpoint 2 -- rtd build")
subprocess.call('echo "Calling Doxygen"', shell=True)
subprocess.call(['doxygen'], shell=True)
subprocess.call('echo "Ran Doxygen"', shell=True)
+31
View File
@@ -0,0 +1,31 @@
<!--
Copyright Contributors to the Open Shading Language project.
SPDX-License-Identifier: CC-BY-4.0
-->
# Copyright Notice
The code that implements Open Shading Language is licensed under the BSD
3-clause (also sometimes known as "new BSD" or "modified BSD") license.
```{include} ../../LICENSE.md
```
This manual and other text documentation about OSL are licensed under the
Creative Commons Attribution 4.0 International License.
```{image} figures/CC-BY.png
:alt: Beautiful Sunset
:width: 200px
:align: center
```
http://creativecommons.org/licenses/by/4.0/
OSL incorporates code from several other software packages with
compatible licenses. Copies of their licenses are reproduced here:
https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/blob/master/THIRD-PARTY.md
+709
View File
@@ -0,0 +1,709 @@
---
numbering:
heading_1: true
heading_2: true
heading_3: true
---
<!--
Copyright Contributors to the Open Shading Language project.
SPDX-License-Identifier: CC-BY-4.0
-->
(chap-types)=
# Data types
OSL provides several built-in simple data types for performing
computations inside your shader:
Type | Explanation
:---------- | :-----------
`int` | Integer data
`float` | Scalar floating-point data (numbers)
`point`, `vector`, `normal` | Three-dimensional positions, directions, and face orientations
`color` | Spectral reflectivities and light energy values
`matrix` | $4 \times 4$ transformation matrices
`string` | Character strings (such as filenames)
`void` | Indicates functions that do not return a value
In addition, you may create arrays and structures (much like C), and
OSL has a new type of data structure called a *closure*.
The remainder of this chapter will describe the simple and aggregate
data types available in OSL.
(sec-datatypes-int)=
## `int`
The basic type for discrete numeric values is `int`. The size of
the `int` type is renderer-dependent, but is guaranteed to be at
least 32 bits.
Integer constants are constructed the same way as in C. The following
are examples of `int` constants: `1`, `-2`, etc. Integer
constants may be specified as hexadecimal, for example: `0x01cf`.
Unlike C, no unsigned, bool, char, short, or long types are supplied.
This is to simplify the process of writing shaders (as well as
implementing shading systems).
The following operators may be used with `int` values (in order of
decreasing precedence, with each box holding operators of the same
precedence):
Operation | Result | Explanation
:--------- | :------ | :---
*int* `++` | `int` | post-increment by 1
*int* `--` | `int` | post-decrement by 1
| |
| |
`++` *int* | `int` | pre-increment by 1
`--` *int* | `int` | pre-decrement by 1
`-` *int* | `int` | unary negation
`~` *int* | `int` | bitwise complement (1 and 0 bits flipped)
`!` *int* | `int` | boolean `not' (1 if operand is zero, otherwise 0)
| |
| |
*int* `*` *int* | `int` | multiplication
*int* `/` *int* | `int` | division
*int* `%` *int* | `int` | modulus
| |
| |
*int* `+` *int* | `int` | addition
*int* `-` *int* | `int` | subtraction
| |
| |
*int* `<<` *int* | `int` | shift left
*int* `>>` *int* | `int` | shift right
| |
| |
*int* `<` *int* | `int` | 1 if the first value is less than the second, else 0
*int* `<=` *int* | `int` | 1 if the first value is less or equal to the second, else 0
*int* `>` *int* | `int` | 1 if the first value is greater than the second, else 0
*int* `>=` *int* | `int` | 1 if the first value is greater than or equal to the second, else 0
| |
| |
*int* `==` *int* | `int` | 1 if the two values are equal, else 0
*int* `!=` *int* | `int` | 1 if the two values are different, else 0
| |
| |
*int* `&` *int* | `int` | bitwise and
| |
| |
*int* `^` *int* | `int` | bitwise exclusive or
| |
| |
*int* `\|` *int* | `int` | bitwise or
| |
| |
*int* `&&` *int* | `int` | boolean and (1 if both operands are nonzero, otherwise 0)
| |
| |
*int* `\|\|` *int* | `int` | boolean or (1 if either operand is nonzero, otherwise 0)
Note that the `not`, `and`, and `or` keywords are synonyms for `!`, `&&`, and
`||`, respectively.
## `float`
The basic type for scalar floating-point numeric values is `float`. The
size of the `float` type is renderer-dependent, but is guaranteed to
be at least IEEE 32-bit float (the standard C `float` data type).
Individual renderer implementations may choose to implement `float` with
even more precision (such as using the C `double` as the underlying
representation).
Floating-point constants are constructed the same way as in C. The following
are examples of `float` constants: `1.0`, `2.48`, `-4.3e2`.
An `int` may be used in place of a `float` when used with any valid
`float` operator. In such cases, the `int` will be promoted to a
`float` and the resulting expression will be `float`. An `int` may
also be passed to a function that expects a `float` parameters, with the
`int` automatically promoted to `float`.
The following operators may be used with `float` values (in order of
decreasing precedence, with each box holding operators of the same
precedence):
Operation | Result | Explanation
:--------- | :------ | :---
*float* `++` | `float` | post-increment by 1
*float* `--` | `float` | post-decrement by 1
| |
| |
`++` *float* | `float` | pre-increment by 1
`--` *float* | `float` | pre-decrement by 1
`-` *float* | `float` | unary negation
| |
| |
*float* `*` *float* | `float` | multiplication
*float* `/` *float* | `float` | division
| |
| |
*float* `+` *float* | `float` | addition
*float* `-` *float* | `float` | subtraction
| |
| |
*float* `<` *float* | `int` | 1 if the first value is less than the second, else 0
*float* `<=` *float* | `int` | 1 if the first value is less or equal to the second, else 0
*float* `>` *float* | `int` | 1 if the first value is greater than the second, else 0
*float* `>=` *float* | `int` | 1 if the first value is greater than or equal to the second, else 0
| |
| |
*float* `==` *float* | `int` | 1 if the two values are equal, else 0
*float* `!=` *float* | `int` | 1 if the two values are different, else 0
## `color`
The `color` type is used to represent 3-component (RGB) spectral
reflectivities and light energies. You can assemble a
color out of three floats, either representing an RGB triple or some
other color space known to the renderer, as well as from a single
float (replicated for all three channels). Following are some examples:
```
color (0, 0, 0) // black
color ("rgb", .75, .5, .5) // pinkish
color ("hsv", .2, .5, .63) // specify in "hsv" space
color (0.5) // same as color (0.5, 0.5, 0.5)
```
All these expressions above return colors in "rgb" space. Even the third
example returns a color in "rgb" space --- specifically, the RGB value of the
color that is equivalent to hue 0.2, saturation 0.5, and value 0.63. In other
words, when assembling a color from components given relative to a specific
color space in this manner, there is an implied transformation to "rgb" space.
The following table lists the built-in color spaces.
% \caption{Names of color spaces.}\label{tab:colorspacenames}
| | |
:--------- | :------
`"rgb"` | The coordinate system that all colors start out in, and in which the renderer expects to find colors that are set by your shader.
`"hsv"` | hue, saturation, and value.
`"hsl"` | hue, saturation, and lightness.
`"YIQ"` | the color space used for the NTSC television standard.
`"XYZ"` | CIE *XYZ* coordinates.
`"xyY"` | CIE *xyY* coordinates.
Colors may be assigned another color or a `float` value (which sets
all three components to the value). For example:
```
color C;
C = color (0, 0.3, 0.3);
C = 0.5; // same as C = color (0.5, 0.5, 0.5)
```
Colors can have their individual components examined and set using the
`[]` array access notation. For example:
```
color C;
float g = C[1]; // get the green component
C[0] = 0.5; // set the red component
```
Components 0, 1, and 2 are red, green, and blue, respectively.
It is an error to access a color component with an index outside the
$[0...2]$ range.
Color variables may also have their components referenced using "named
components" that look like accessing structure fields named `r`, `g`, and `b`,
as synonyms for `[0]`, `[1]`, and `[2]`, respectively:
```
float green = C.g; // get the green component
C.r = 0.5; // set the red component
```
The following operators may be used with `color` values (in order of
decreasing precedence, with each box holding operators of the same
precedence):
Operation | Result | Explanation
:--------- | :------ | :---
*color* `[` *int* `]` | `float` | component access
| |
| |
`-` *color* | `color` | unary negation
| |
| |
*color* `*` *color* | `color` | component-wise multiplication
*color* `*` *float* | `color` | scaling
*float* `*` *color* | `color` | scaling
*color* `/` *color* | `color` | component-wise division
*color* `/` *float* | `color` | scaling
*float* `/` *color* | `color` | scaling
| |
| |
*color* `+` *color* | `color` | component-wise addition
*color* `-` *color* | `color` | component-wise subtraction
| |
| |
*color* `==` *color* | `int` | 1 if the two values are equal, else 0
*color* `!=` *color* | `int` | 1 if the two values are different, else 0
All of the binary operators may combine a scalar value (`float` or
`int`) with a `color`, treating the scalar if it were a `color` with
three identical components.
## Point-like types: `point`, `vector`, `normal`
Points, vectors, and normals are similar data types with identical
structures but subtly different semantics. We will frequently refer to
them collectively as the "point-like" data types when making
statements that apply to all three types.
A `point` is a position in 3D space. A `vector` has a length and
direction, but does not exist in a particular location. A `normal` is a
special type of vector that is *perpendicular* to a surface, and
thus describes the surface's orientation. Such a perpendicular vector
uses different transformation rules than ordinary vectors, as we will
describe below.
All of these point-like types are internally represented by three
floating-point numbers that uniquely describe a position or
direction relative to the three axes of some coordinate system.
All points, vectors, and normals are described relative to some
coordinate system. All data provided to a shader (surface information,
graphics state, parameters, and vertex data) are relative to one
particular coordinate system that we call the `"common"` coordinate
system. The `"common"` coordinate system is one that is convenient
for the renderer's shading calculations.
You can "assemble" a point-like type out of three floats using a
constructor:
```
point (0, 2.3, 1)
vector (a, b, c)
normal (0, 0, 1)
```
These expressions are interpreted as a point, vector, and normal
whose three components are the floats given, relative to "common" space .
As with colors, you may also specify the coordinates relative to some other
coordinate system:
```
Q = point ("object", 0, 0, 0);
```
This example assigns to `Q` the point at the origin of "object" space.
However, this statement does *not* set the components of `Q` to (0,0,0)!
Rather, `Q` will contain the "common" space coordinates of the point that is
at the same location as the origin of "object" space. In other words, the
point constructor that specifies a space name implicitly specifies a
transformation to "common" space. This type of constructor also can be used
for vectors and normals.
The choice of "common" space is renderer-dependent, though will usually
be equivalent to either "camera" space or "world" space.
Some computations may be easier in a coordinate system other than
"common" space. For example, it is much more convenient to apply a
"solid texture" to a moving object in its "object" space than in
"common" space. For these reasons, OSL provides a built-in
`transform()` function that
allows you to transform points, vectors, and normals
among different coordinate systems (see Section [](#sec-stdlib-geom)). Note,
however, that OSL does not keep track of which point variables are
in which coordinate systems. It is the responsibility of the shader
programmer to keep track of this and ensure that, for example, lighting
computations are performed using quantities in "common" space.
Several coordinate systems are predefined by name, listed in the following
table. Additionally, a renderer will probably allow for additional coordinate
systems to be named in the scene description, and these names may also be
referenced inside your shader to designate transformations.
% \caption{Names of predeclared geometric spaces.\label{tab:spacenames}}
`"common"`
: The coordinate system that all spatial values start out in and the one in
which all lighting calculations are carried out. Note that the choice of
`"common"` space may be different on each renderer.
`"object"`
: The local coordinate system of the graphics primitive (sphere, patch, etc.)
that we are shading.
`"shader"`
: The local coordinate system active at the time that the shader was
instanced.
`"world"`
: The world coordinate system designated in the scene.
`"camera"`
: The coordinate system with its origin at the center of the camera lens,
$x$-axis pointing right, $y$-axis pointing up, and $z$-axis pointing into
the screen.
`"screen"`
: The coordinate system of the camera's image plane (after perspective
transformation, if any). Coordinate (0,0) of `"screen"` space is looking
along the $z$-axis of "camera" space.
`"raster"`
: 2D pixel coordinates, with (0,0) as the upper-left
corner of the image and (xres, yres) as the lower-right corner.
`"NDC"`
: 2D Normalized Device Coordinates --- like raster space, but normalized so
that $x$ and $y$ both run from 0 to 1 across the whole image, with (0,0)
being at the upper left of the image, and (1,1) being at the lower right.
Point types can have their individual components examined and set using
the `[]` array access notation. For example:
```
point P;
float y = P[1]; // get the y component
P[0] = 0.5; // set the x component
```
Components 0, 1, and 2 are $x$, $y$, and $z$, respectively.
It is an error to access a point component with an index outside the
$[0...2]$ range.
Point-like variables may also have their components referenced using "named
components" that look like accessing structure fields named `x`, `y`, and `z`,
as synonyms for `[0]`, `[1]`, and `[2]`, respectively:
```
float yval = P.y; // get the [1] or y component
P.x = 0.5; // set the [0] or x component
```
The following operators may be used with point-like values (in order of
decreasing precedence, with each box holding operators of the same
precedence):
Operation | Result | Explanation
:--------- | :------ | :---
*ptype* `[` `int` `]` | `float` | component access
| |
| |
`-` *ptype* | `vector` | component-wise unary negation
| |
| |
*ptype* `*` *ptype* | *ptype* | component-wise multiplication
`float` `*` *ptype* | *ptype* | scaling of all components
*ptype* `*` `float` | *ptype* | scaling of all components
*ptype* `/` *ptype* | *ptype* | component-wise division
*ptype* `/` `float` | *ptype* | division of all components
`float` `/` *ptype* | *ptype* | division by all components
| |
| |
*ptype* `+` *ptype* | *ptype* | component-wise addition
*ptype* `-` *ptype* | `vector` | component-wise subtraction
| |
| |
*ptype* `==` *ptype* | `int` | 1 if the two values are equal, else 0
*ptype* `!=` *ptype* | `int` | 1 if the two values are different, else 0
The generic *ptype* is listed in places where any of `point`, `vector`, or
`normal` may be used.
All of the binary operators may combine a scalar value (`float` or `int`) with
a point-like type, treating the scalar if it were point-like with three
identical components.
## `matrix`
OSL has a `matrix` type that represents the transformation matrix required to
transform points and vectors between one coordinate system and another.
Matrices are represented internally by 16 floats (a $4 \times 4$ homogeneous
transformation matrix).
A `matrix` can be constructed from a single float or 16 floats. For example:
```
matrix zero = 0; // makes a matrix with all 0 components
matrix ident = 1; // makes the identity matrix
// Construct a matrix from 16 floats
matrix m = matrix (m00, m01, m02, m03, m10, m11, m12, m13,
m20, m21, m22, m23, m30, m31, m32, m33);
```
Assigning a single floating-point number $x$ to a matrix will result
in a matrix with diagonal components all being $x$ and other
components being zero (i.e., $x$ times the identity matrix).
Constructing a matrix with 16 floats will create the matrix whose
components are those floats, in row-major order.
Similar to point-like types, a `matrix` may be constructed in
reference to a named space:
```
// Construct matrices relative to something other than "common"
matrix q = matrix ("shader", 1);
matrix m = matrix ("world", m00, m01, m02, m03, m10, m11, m12, m13,
m20, m21, m22, m23, m30, m31, m32, m33);
```
The first form creates the matrix that transforms points from "shader" space
to "common" space. Transforming points by this matrix is identical to calling
`transform("shader", "common", ...)`. The second form prepends the
current-to-world transformation matrix onto the $4 \times 4$ matrix with
components $m_{0,0} ... m_{3,3}$. Note that although we have used `"shader"`
and `"world"` space in our examples, any named space is acceptable.
A matrix may also be constructed from the names of two coordinate
systems, yielding the matrix that transforms coordinates from the
first named space to the second named space:
```
matrix m = matrix ("object", "world");
```
The example returns the *object-to-world* transformation matrix.
Matrix variables can be tested for equality and inequality with the `==` and
`!=` boolean operators. Also, the `*` operator between matrices denotes
matrix multiplication, while `m1 / m2` denotes multiplying `m1` by the inverse
of matrix `m2`. Thus, a matrix can be inverted by writing `1/m`. In
addition, some functions will accept matrix variables as arguments, as
described in Section [](#chap-stdlibrary).
Individual components of a matrix variable may be set or accessed using array
notation, for example,
```
matrix M;
float x = M[row][col];
M[row][col] = 1;
```
Valid component indices are integers on $[0...3]$. It is an error to access a
matrix component with either a row or column outside this range.
The following operators may be used with matrices (in order of decreasing
precedence, with each box holding operators of the same precedence):
Operation | Result | Explanation
:--------- | :------ | :---
*matrix* `[` *int* `][` *int* `]` | `float` | component access (row, column)
| |
| |
`-` *matrix* | `matrix` | unary negation
| |
| |
*matrix* `*` *matrix* | `matrix` | matrix multiplication
*matrix* `*` *float* | `matrix` | component-wise scaling
*float* `*` *matrix* | `matrix` | component-wise scaling
*matrix* `/` *matrix* | `matrix` | multiply the first matrix by the *inverse of the second
*matrix* `/` *float* | `matrix` | component-wise division
*float* `/` *matrix* | `matrix` | multiply the *float* by the *inverse of the matrix
| |
| |
*matrix* `==` *matrix* | *int* | 1 if the two values are equal, else 0
*matrix* `!=` *matrix* | *int* | 1 if the two values are different, else 0
## `string`
The `string` type may hold character strings. The main application
of strings is to provide the names of files where textures may be
found. Strings can be compared using `==` and `!=`.
String constants are denoted by surrounding the characters with double
quotes, as in `"I am a string literal"`. As in C programs, string
literals may contain escape sequences such as `\n` (newline),
`\r` (carriage return), `\t` (tab), `\"` (double quote),
`\\` (backslash).
Two quote-quoted string literals that are separated only by whitespace
(spaces, tabs, or newlines) will be automatically concatenated into a
single string literal. In other words,
```text
"foo" "bar"
```
is exactly equivalent to `"foobar"`.
## `void`
The `void` type is used to designate a function that does not return a value.
No variable may have type `void`.
## Arrays
Arrays of any of the basic types are supported, provided that they
are 1D and statically sized, using the usual syntax for C-like languages:
```
float d[10]; // Declare an uninitialized array
float c[3] = { 0.1, 0.2, 3.14 }; // Initialize the array
float f = c[1]; // Access one element
```
The built-in function `arraylength()` returns the number of elements in an
array. For example:
```
float c[3];
int clen = arraylength(c); // should return 3
```
There are two circumstances when arrays do not need to have a declared
length --- an array parameter to a function, and a shader parameter that
is an array. This is indicated by empty array brackets, as shown in the
following example:
```
float sum (float x[])
{
float s = 0;
for (int i = 0; i < arraylength(x); ++i)
s += x[i];
return s;
}
```
It is allowed in OSL to copy an entire array at once using the `=` operator,
provided that the arrays contain elements of the same type and that the
destination array is at least as long as the source array. For example:
```
float array[4], anotherarray[4];
...
anotherarray = array;
```
## Structures
Structures are used to group several fields of potentially different types
into a single object that can be referred to by name. You may then use the
structure type name to declare structure variables as you would for any of the
built-in types. Structure elements are accessed using the `.` ("dot")
operator. The syntax for declaring and using structures is similar to C or
C++:
```
struct RGBA { // Define a structure type
color rgb;
float alpha;
};
RGBA col; // Declare a structure
r.rgb = color (1, 0, 0); // Assign to one field
color c = r.rgb; // Read from a structure field
RGBA b = { color(.1,.2,.3), 1 }; // Member-by-member initialization
```
You can use "constructor expressions" for a your struct types much like
you can construct built-in types like `color` or `point`:
> *struct_name* `(` *first_member_value*, ... `}`
For example,
```
RGBA c = RGBA(col,alpha); // Constructor syntax
RGBA add (RGBA a, RGBA b)
{
return RGBA (a.rgb+b.rgb, a.a+b.a); // return expression
}
// pass constructor expression as a parameter:
RGBA d = add (c, RGBA(color(.3,.4,.5), 0));
```
You may also use the *compound initializer list* syntax to construct a type
when it can be deduced from context which compound type is required. For
example, this is equivalent to the preceding example:
```
RGBA c = {col,alpha}; // deduce by what is being assigned to
RGBA add (RGBA a, RGBA b)
{
return { a.rgb+b.rgb, a.a+b.a }; // deduce by func return type
}
RGBA d = add (c, {{.3,.4,.5}, 0}); // deduce by expected arg type
```
It is permitted to have a structure field that is an array, as well as to have
an array of structures. But it is not currently permitted to "nest" arrays
(that is, to have an array of structs which contain members that are arrays).
```
struct A {
color a;
float b[4]; // Ok: struct may contain an array
};
RGBA vals[4]; // Ok: Array of structures
vals[0].a = 0;
A d[5]; // NO: Array of structures that contain arrays
```
## Closures
A `closure`is an expression or function call that will be stored, along
with necessary contextual information, to be evaluated at a later time.
In general, the type "`closure` *gentype*" behaves exactly like a
*gentype*, except that its numeric values may not be examined or
used for the duration of the shader's execution. For example, a
`color closure` behaves mostly like a color --- you can multiply it by a
scalar, assign it to a `color closure` variable, etc. --- but you may not
assign it to an ordinary `color` or examine its individual component's
numeric values.
It is legal to assign `0` to a closure, which is understood to mean setting it
to a *null closure* (even though in all other circumstances, assigning a
`float` to a `closure`would not be allowed).
At present, the only type of `closure`supported by OSL is the `color closure`,
and the only allowed operations are those that let you form a linear
combination of `color closure`'s. Additional closure types and operations are
reserved for future use.
Allowable operations on `color closure` include:
Operation | Result | Explanation
:--------- | :------ | :---
`-` *colorclosure* | `color closure` | unary negation
| |
| |
*color* `*` *colorclosure* | `color closure` | component-wise scaling
*colorclosure* `*` *color* | `color closure` | component-wise scaling
*float* `*` *colorclosure* | `color closure` | scaling
*colorclosure* `*` *float* | `color closure` | scaling
| |
| |
*colorclosure* `+` *colorclosure* | `color closure` | component-wise addition
% *colorclosure* `-` *colorclosure* | `color closure` | component-wise subtraction
+174
View File
@@ -0,0 +1,174 @@
<!--
Copyright Contributors to the Open Shading Language project.
SPDX-License-Identifier: CC-BY-4.0
-->
(chap-glossary)=
# Glossary
Attribute state
: The set of variables that determines all the properties (other than shape)
of a *geometric primitive* --- such as its local transformation matrix,
the surface, displacement, and volume shaders to be used, which light
sources illuminate objects that share the attribute state, whether
surfaces are one-sided or two-sided, etc. Basically all of the options
that determine the behavior and appearance of the primitives, that are not
determined by the shape itself or the code of the shaders. A single
attribute state may be shared among multiple geometric primitives. Also
sometimes called *graphics state*.
BSDF
: Bidirectional scattering distribution function, a function that describes
light scattering properties of a surface.
Built-in function
: A function callable from within a shader, where the implementation of the
function is provided by the renderer (as opposed to a function that the
shader author writes in OSL itself).
Closure
: A symbolic representation of a function to be called, and values for its
parameters, that are packaged up to be evaluated at a later time to yield
a final numeric value.
Connection
: A routing of the value of an *output parameter* of one *shader layer* to
an *input parameter* of another shader layer within the same *shader
group*.
Default parameter value
: The initial value of a *shader parameter*, if the renderer does not
override it with an *instance value*, an interpolated *primitive
variable*, or a *connection* to an output parameter of another *layer*
within the *group*. The default value of a shader parameter is explicitly
given in the code for that shader, and may either be a constant or a
computed expression.
EDF
: Emission distribution function, a function that describes the distribution
of light emitted by a light source.
Geometric primitive
: A single shape, such as a NURBS patch, a polygon or subdivision mesh, a
hair primitive, etc.
Global variables
: The set of "built-in" variables describing the common renderer inputs to
all shaders (as opposed to shader-specific parameters). These include
position (`P`), surface normal (`N`), surface tangents (`dPdu`, `dPdv`),
as well as standard radiance output (`Ci`). Different *shader types*
support different subsets of the global variables.
Graphics state
: See *attribute state*.
Group
: See *shader group*.
Input parameter
: A read-only *shader parameter* that provides a value to control a
shader's behavior. Can also refer to a read-only parameter to a
*shader function*.
Instance value
: A constant value that overrides a default parameter value for a
particular *shader instance*. Each instance of a shader may have a
completely different set of instance values for its parameters.
Layer
: See *shader layer*.
Output parameter
: A read/write *shader parameter* allows a shader to provide outputs beyond
the *global variables* such as `Ci`. Can also refer to a read/write
parameter to a *shader function*, allowing a function to provide more
outputs than a simple return value.
Primitive
: Usually refers to a *geometric primitive*.
Primitive variable
: A named variable, and values, attached to an individual geometric
primitive. Primitive variables may have one of several *interpolation
methods* --- such as a single value for the whole primitive, a value for
each piece or face of the primitive, or per-vertex values that are
smoothly interpolated across the surface.
% Public method
%
% : A function within a shader that has an entry point that is visible and
% directly callable by the renderer, as opposed to merely being called from
% other code within the shader. Public methods must be *top-level* (not
% defined within other functions) and must be preceded by the `public`
% keyword.
Shader
: A small self-contained program written in OSL, used to extend the
functionality of a renderer with custom behavior of materials and lights.
A particular shader may have multiple *shader instances* within a scene,
each of which has its unique *instance parameters*, transformation, etc.
Shader function
: A function written in OSL that may be called from within a shader.
Shader group
: An ordered collection of *shader instances* (individually called the
*layers* of a group) that are executed to collectively determine material
properties or displacement of a geometric primitive, emission of a light
source, or scattering properties of a volume. In addition to executing
sequentially, layers within a group may optionally have any of their input
parameters explicitly connected to output parameters of other layers
within the group in an acyclic manner (thus, sometimes being referred to
as a *shader network*).
Shader instance
: A particular reference to a *shader*, with a unique set of *instance
values*, transformation, and potentially other attributes. Each shader
instance is a separate entity, despite their sharing executable code.
Shader network
: See *shader group*.
Shader layer
: An individual *shader instance* within a *shader group*.
Shader parameter
: A named input or output variable of a shader. *Input parameters* provide
"knobs" that control the behavior of a shader; *output parameters*
additional provide a way for shaders to produce additional output beyond
the usual *global variables*.
Shading
: The computations within a renderer that implement the behavior and visual
appearance of materials and lights.
VDF
: Volumetric distribution function, a function that describes the scattering
properties of a volume.
+239
View File
@@ -0,0 +1,239 @@
---
numbering:
heading_1: true
heading_2: true
heading_3: true
---
<!--
Copyright Contributors to the Open Shading Language project.
SPDX-License-Identifier: CC-BY-4.0
-->
(chap-grammar)=
# Formal Language Grammar
This section gives the complete syntax of OSL. Syntactic structures that have
a name ending in `-opt` are optional. Structures surrounded by curly braces
`{ }` may be repeated 0 or more times. Text in `typewriter` face indicates
literal text. The $\epsilon$ character is used to indicate that it is
acceptable for there to be nothing (empty, no token).
#### Lexical elements
\<digit\> ::= "`0`" | "`1`" | "`2`" | "`3`" | "`4`" | "`5`" | "`6`" | "`7`" | "`8`" | "`9`"
\<digit-sequence\> ::= \<digit\> { \<digit\> }
\<hexdigit\> ::= \<digit\> | "`a`" | "`A`" | "`b`" | "`B`" | "`c`" | "`C`" | "`d`" | "`D`" | "`e`" | "`E`" | "`f`" | "`F`"
\<hexdigit-sequence\> ::= \<hexdigit\> { \<hexdigit\> }
\<integer\> ::= \<sign\> \<digit-sequence\>
<br>$~~~~~~~~~~$ | \<sign\> "`0x`" \<hexdigit-sequence\>
\<floating-point\> ::= \<digit-sequence\> \<decimal-part-opt\> \<exponent-opt\>
<br>$~~~~~~~~~~$ | \<decimal-part\> \<exponent-opt\>
\<decimal-part\> ::= '`.`' { \<digit\> }
\<exponent\> ::= '`e`' \<sign\> \<digit-sequence\>
\<sign\> ::= '`-`' | '`+`' | $\epsilon$
\<number\> ::= \<integer\>
<br>$~~~~~~~~~~$ | \<floating-point\>
\<char-sequence\> ::= { \<any-char\> }
\<stringliteral> ::= `"` \<char-sequence\> `"`
\<identifier\> ::= \<letter-or-underscore\> { \<letter-or-underscore-or-digit\> }
#### Overall structure
\<shader-file\> ::= { \<global-declaration\> }
\<global-declaration\> ::= \<function-declaration\>
<br>$~~~~~~~~~~$ | \<struct-declaration\>
<br>$~~~~~~~~~~$ | \<shader-declaration\>
\<shader-declaration\> ::= <br>$~~~~~~~~~~~~$ $~~~~~~~~~~$
\<shadertype\> \<identifier\> \<metadata-block-opt\>
"(" \<shader-formal-params-opt\> ")" "{" \<statement-list\> "}"
\<shadertype\> ::= "displacement" | "shader" | "surface" | "volume"
\<shader-formal-params\> ::= \<shader-formal-param\> { "," \<shader-formal-param\> }
\<shader-formal-param\> ::= \<outputspec\> \<typespec\> \<identifier\>
\<initializer\> \<metadata-block-opt\>
<br>$~~~~~~~~~~$ | \<outputspec\> \<typespec\> \<identifier\> \<arrayspec\>
\<initializer-list\> \<metadata-block-opt\>
\<metadata-block> ::= "[[" \<metadata\> { "," \<metadata\> } "]]"
\<metadata\> ::= \<simple-typespec\> \<identifier\> \<initializer\>
#### Declarations
\<function-declaration\> ::= <br>$~~~~~~~~~~~~$ \<typespec\> \<identifier\>
"(" \<function-formal-params-opt\> ")" "{" \<statement-list\> "}"
\<function-formal-params\> ::= \<function-formal-param\> { "," \<function-formal-param\> }
\<function-formal-param\> ::= \<outputspec\> \<typespec\> \<identifier\> \<arrayspec-opt\>
\<outputspec> ::= "output" | $\epsilon$
\<struct-declaration\> ::= "struct" \<identifier\> "{" \<field-declarations> "}" ";"
\<field-declarations\> ::= \<field-declaration\> { \<field-declaration\> }
\<field-declaration\> ::= \<typespec\> \<typed-field-list\> ";"
\<typed-field-list\> ::= \<typed-field\> { "," \<typed-field\> }
\<typed-field\> ::= \<identifier\> \<arrayspec-opt\>
\<local-declaration\> ::= \<function-declaration\>
<br>$~~~~~~~~~~$ | \<variable-declaration\>
\<arrayspec> ::= "[" \<integer\> "]"
<br>$~~~~~~~~~~$ | "[" "]"
\<variable-declaration\> ::= \<typespec\> \<def-expressions> ";"
\<def-expressions\> ::= \<def-expression\> { "," <def-expression\> }
\<def-expression\> ::= \<identifier\> \<initializer-opt\>
<br>$~~~~~~~~~~$ | \<identifier\> \<arrayspec\> \<initializer-list-opt\>
\<initializer\> ::= "=" \<expression\>
\<initializer-list\> ::= "=" \<compound-initializer\>
\<compound-initializer\> ::= "{" \<init-expression-list\> "}"
\<init-expression-list\> ::= \<init-expression\> { "," \<init-expression\> }
\<init-expression\> ::= \<expression\> | \<compound-initializer\>
\<typespec\> ::= \<simple-typename>
<br>$~~~~~~~~~~$ | "closure" \<simple-typename\>
<br>$~~~~~~~~~~$ | \<identifier-structname\>
\<simple-typename\> ::=
"color"
| "float"
| "matrix"
| "normal"
| "point"
| "string"
| "vector"
| "void"
#### Statements
\<statement-list\> ::= \<statement\> { \<statement\> }
\<statement\> ::=
\<compound-expression-opt\> ";"
<br>$~~~~~~~~~~$ | \<scoped-statements\>
<br>$~~~~~~~~~~$ | \<local-declaration\>
<br>$~~~~~~~~~~$ | \<conditional-statement\>
<br>$~~~~~~~~~~$ | \<loop-statement\>
<br>$~~~~~~~~~~$ | \<loopmod-statement\>
<br>$~~~~~~~~~~$ | \<return-statement\>
\<scoped-statements> ::= "{" \<statement-list-opt\> "}"
\<conditional-statement\> ::= <br>$~~~~~~~~~~~~$ "if" "(" \<compound-expression\> ")" \<statement\>
<br>$~~~~~~~~~~$ | "if" "(" \<compound-expression\> ")" \<statement\> "else" \<statement\>
\<loop-statement\> ::= <br>$~~~~~~~~~~~~$ "while" "(" \<compound-expression\> ")" \<statement\>
<br>$~~~~~~~~~~$ | "do" \<statement\> "while" "(" \<compound-expression\> ")" ";"
<br>$~~~~~~~~~~$ | "for" "(" \<for-init-statement-opt\> \<compound-expression-opt\> ";"
\<compound-expression-opt\> ")" \<statement\>
\<for-init-statement\> ::= <br>$~~~~~~~~~~~~$ \<expression-opt\> ";"
<br>$~~~~~~~~~~$ | \<variable-declaration\>
\<loopmod-statement\> ::= "break" ";"
<br>$~~~~~~~~~~$ | "continue" ";"
\<return-statement\> ::= "return" \<expression-opt\> ";"
#### Expressions
\<expression-list\> ::= \<expression\> { "," \<expression\> }
\<expression\> ::= \<number\>
<br>$~~~~~~~~~~$ | \<stringliteral\>
<br>$~~~~~~~~~~$ | \<type-constructor\>
<br>$~~~~~~~~~~$ | \<incdec-op\> \<variable-ref\>
<br>$~~~~~~~~~~$ | \<expression\> \<binary-op\> \<expression\>
<br>$~~~~~~~~~~$ | \<unary-op\> \<expression\>
<br>$~~~~~~~~~~$ | "(" \<compound-expression\> ")"
<br>$~~~~~~~~~~$ | \<function-call\>
<br>$~~~~~~~~~~$ | \<assign-expression\>
<br>$~~~~~~~~~~$ | \<ternary-expression\>
<br>$~~~~~~~~~~$ | \<typecast-expression\>
<br>$~~~~~~~~~~$ | \<variable-ref\>
<br>$~~~~~~~~~~$ | \<compound-initializer\>
\<compound-expression\> ::= \<expression\> { "," \<expression\> }
\<variable-lvalue\> ::= \<identifier\> \<array-deref-opt\> \<component-deref-opt\>
<br>$~~~~~~~~~~$ | \<variable_lvalue> "[" \<expression\> "]"
<br>$~~~~~~~~~~$ | \<variable_lvalue> "." \<identifier\>
\<variable-ref\> ::= \<identifier\> \<array-deref-opt\>
\<array-deref> ::= "[" \<expression\> "]"
\<component-deref> ::= "[" \<expression\> "]"
<br>$~~~~~~~~~~$ | "." \<component-field\>
\<component-field\> ::= "x" | "y" | "z" | "r" | "g" | "b"
\<binary-op> ::= "*" | "/" | "\%"
<br>$~~~~~~~~~~$ | "+" | "-"
<br>$~~~~~~~~~~$ | "<<" | ">>"
<br>$~~~~~~~~~~$ | "<" | "<=" | ">" | ">="
<br>$~~~~~~~~~~$ | "==" | "!="
<br>$~~~~~~~~~~$ | "&"
<br>$~~~~~~~~~~$ | "^"
<br>$~~~~~~~~~~$ | "|"
<br>$~~~~~~~~~~$ | "&&" | "and"
<br>$~~~~~~~~~~$ | "||" | "or"
\<unary-op> ::= "-" | "~" | "!" | "not"
\<incdec-op> ::= "++" | "--"
\<type-constructor\> ::= \<typespec> "(" \<expression-list\> ")"
\<function-call\> ::= \<identifier\> "(" \<function-args-opt\> ")"
\<function-args\> ::= \<expression\> { "," \<expression\> }
\<assign-expression\> ::= \<variable-lvalue\> \<assign-op\> \<expression\>
\<assign-op> ::= "=" | "*=" | "/=" | "+=" | "-=" | "&=" | "|=" | "^=" |
"<<=" | ">>="
\<ternary-expression\> ::= \<expression\> "?" \<expression\> ":" \<expression\>
\<typecast-expression\> ::= "(" \<simple-typename> ")" \<expression\>
+403
View File
@@ -0,0 +1,403 @@
<!--
Copyright Contributors to the Open Shading Language project.
SPDX-License-Identifier: CC-BY-4.0
-->
# Gross syntax, shader types, parameters
The overall structure of a shader is as follows:
> *optional-function-or-struct-declarations* \
\
shader-type shader-name `(` optional-parameters `)` \
`{` \
*statements* \
`}`
Note that *statements* may include function or structure definitions, local
variable declarations, or public methods, as well as ordinary execution
instructions (such as assignments, etc.).
## Shader types
Shader types include the following: `surface`, `displacement`, `light`,
`volume`, and generic `shader`. Some operations may only be performed from
within certain types of shaders (e.g., one may only call `displace()` or alter
`P` in a displacement shader), and some global variables may only be accessed
from within certain types of shaders (e.g., `dPdu` is not defined inside a
volume shader).
Following are brief descriptions of the basic types of shaders:
`surface` shaders
: Surface shaders determine the basic material properties of a surface and
how it reacts to light. They are responsible for computing a
`color closure` that describes the material, and optionally setting
other user-defined output variables. They may not alter
the position of the surface.
Surface shaders are written as if they describe the behavior of a single
point on the primitive, and the renderer will choose the positions
surface at which the shader must be evaluated.
Surface shaders also are used to describe emissive objects, i.e., light
sources. OSL does not need a separate shader type to describe lights.
`displacement` shaders
: Displacement shaders alter the position and shading normal (or,
optionally, just the shading normal) to make a piece of geometry appear
deformed, wrinkled, or bumpy. They are the only kind of shader that
is allowed to alter a primitive's position.
`volume` shaders
: Volume shaders describe how a participating medium (air, smoke, glass,
etc.) reacts to light and affects the appearance of objects on the other
side of the medium. They are similar to `surface` shaders, except
that they may be called from positions that do not lie upon (and are not
necessarily associated with) any particular primitive.
`shader` generic shaders
: Generic shaders are used for utility code, generic routines that may be
called as individual layers in a shader group. Generic shaders need not
specify a shader type, and therefore may be reused from inside surface,
displacement, or volume shader groups. But as a result, they may
not contain any functionality that cannot be performed from inside all
shader types (for example, they may not alter `P`, which can only be done
from within a displacement shader).
## Shader parameters
An individual shader has (optionally) many *parameters* whose
values may be set in a number of ways so that a single shader may have
different behaviors or appearances when used on different objects.
### Shader parameter syntax
Shader parameters are specified in the shader declaration, in
parentheses after the shader's name. This is much like the parameters
to an OSL function (or a function in C or similar languages),
except that shader parameters must have an *initializer*, giving a
default value for the parameter. Shader parameter default initializers
may be expressions (i.e., may be computed rather than restricted to
numeric constants), and are evaluated in the order that the parameters
are declared, and may include references to previously-declared
parameters. Formally, the grammar for a simple parameter
declaration looks like this:
> *type parametername* `=` *default-expression*
where *type* is one of the data types described in Chapter [](#chap-types),
*parametername* is the name of the parameter, and *default-expression* is a
valid expression (see Section [](#sec-expressions)). Multiple parameters are
simply separated by commas:
> *type1 parameter1* `=` *expr1* `,` *type2 parameter2* `=` *expr2* `,` ...
Fixed-length, one-dimensional array parameters are declared as follows:
> *type parametername* `[` *array-length* `] = {` *expr0* `,` *expr1* ... `}`
where *array-length* is a positive integer constant giving the length of the
array, and the initializer is a series of initializing expressions listed
between curly braces. The first initializing expression provides the
initializer for the first element of the array, the second expression provides
the initializer for the second element of the array, and so on. If the number
of initializing expressions is less than the length of the array, any
additional array elements will have undefined values.
Arrays may also be declared without a set length:
> *type parametername* `[ ] = {` *expr0* `,` *expr1* ... `}`
where no array length is found between the square brackets.
This indicates that the array's length will be determined based on
whatever is passed in --- a connection from the output of another shader
in the group (take on the length of that output), an instance value
(take on the length specified by the declaration of the instance value),
or a primitive variable (length determined by its declaration on the
primitive). If no instance value, primitive value, or connection is
supplied, then the number of initializing expressions will determine the
length, as well as the default values, of the array.
Structure parameters are also straightforward to declare:
> *structure-type parametername* `= {` *expr0* `,` *expr1* ... `}`
where *structure-type* is the name of a previously-declared `struct` type, and
the *expr* initializers correspond to each respective field within the
structure. An initializer of appropriate type is required for every field of
the structure.
### Shader output parameters
Shader parameters are, by default, read-only in the body of the
shader. However, special \emph{output parameters} may be altered
by execution of the shader. Parameters may be designated outputs
by use of the {\cf output} keyword immediately prior to the
type declaration of the parameter:
> `output` *type parametername* `=` *expr*
(Output parameters may be arrays and structures, but we will omit spelling out
the obvious syntax here.)
Output parameters may be connected to inputs of later-run shader layers in the
shader group, may be queried by later-run shaders in the group via message
passing (i.e., `getmessage()` calls), or used by the renderer as an output
image channel (in a manner described through the renderer's API).
### Shader parameter example
Here is an example of a shader declaration, with several parameters:
```
surface wood (
/* Simple params with constant initializers */
float Kd = 0.5,
color woodcolor = color (.7, .5, .3),
string texturename = "wood.tx",
/* Computed from an earlier parameter */
color ringcolor = 0.25 * woodcolor,
/* Fixed-length array */
color paintcolors[3] = { color(0,.25,0.7), color(1,1,1),
color(0.75,0.5,0.2) },
/* variable-length array */
int pattern[] = { 2, 4, 2, 1 },
/* output parameter */
output color Cunlit = 0
)
{
...
}
```
### How shader parameters get their values
Shader parameters get their values in the following manner,
in order of decreasing priority:
1. If the parameter has been designated by the renderer to be connected to an
output parameter of a previously-executed shader layer within the shader
group, that is the value it will get.
2. If the parameter matches the name and type of a per-primitive, per-face, or
per-vertex *primitive variable* on the particular piece of geometry
being shaded, the parameter's value will be computed by interpolating the
primitive variable for each position that must be shaded.
3. If there is no connection or primitive variable, the parameter may will
take on an *instance value*, if that parameter was given an explicit
per-instance value at the time that the renderer referenced the shader
(associating it with an object or set of objects).
4. If none of these overrides is present, the parameter's value will be
determined by executing the parameter initialization code in the shader.
This triage is performed per parameter, in order of declaration. So, for
example, in the code sample above where the default value for `ringcolor1 is a
scaled version of `woodcolor`, this relationship would hold whether
`woodcolor` was the default, an instance value, an interpolated primitive
value, or was connected to another layer's output. Unless `ringcolor` itself
was given an instance, primitive, or connection value, in which case that's
what would be used.
## Shader metadata
A shader may optionally include *metadata* (data *about* the
shader, as opposed to data *used by* the shader). Metadata may be
used to annotate the shader or any of its individual parameters with
additional hints or information that will be compiled into the shader
and may be queried by applications. A common use of metadata is to
specify user interface hints about shader parameters --- for example,
that a particular parameter should only take on integer values, should
have an on/off checkbox, is intended to be a filename, etc.
Metadata is specified inside double brackets `[[` and `]]` enclosing a
comma-separated list of metadata items. Each metadatum looks like a parameter
declaration --- having a data type, name, and initializer. However, metadata
may only be simple types or arrays of simple types (not structs or closures)
and their value initializers must be numeric or string constants (not computed
expressions).
Metadata about the shader as a whole is placed between the shader name
and the parameter list. Metadata about shader parameters are placed
immediately after the parameter's initializing expression, but before
the comma or closing parentheses that terminates the parameter
description.
Below is an example shader declaration showing the use of shader and
parameter metadata:
```
surface wood
[[ string help = "Realistic wood shader" ]]
(
float Kd = 0.5
[[ string help = "Diffuse reflectivity",
float min = 0, float max = 1 ]] ,
color woodcolor = color (.7, .5, .3)
[[ string help = "Base color of the wood" ]],
color ringcolor = 0.25 * woodcolor
[[ string help = "Color of the dark rings" ]],
string texturename = "wood.tx"
[[ string help = "Texture map for the grain",
string widget = "filename" ]],
int pattern = 0
[[ string widget = "mapper",
string options = "oak:0|elm:1|walnut:2" ]]
)
{
...
}
```
The metadata are not semantically meaningful; that is, the metadata does
not affect the actual execution of the shader. Most metadata exist only
to be embedded in the compiled shader and able to be queried by other
applications, such as to construct user interfaces for shader assignment
that allow usage tips, appropriate kinds of widgets for setting each
parameter, etc.
The choice of metadata and their meaning is completely up to the shader
writer and/or modeling system. However, we propose some conventions
below. These conventions are not intended to be comprehensive, nor to
meet all your needs --- merely to establish a common nomenclature for
the most common metadata uses.
The use of metadata is entirely optional on the part of the shader
writer, and any application that queries shader metadata is free to
honor or ignore any metadata it finds.
string label
: A short label to be displayed in the UI for this parameter. If not
present, the parameter name itself should be used as the widget label.
string help
: Help text that describes the purpose and use of the shader or parameter.
string page
: Helps to group related widgets by ``page.''
string widget
: The type of widget that should be used to adjust this parameter.
Suggested widget types:
"number"
: Provide a slider and/or numeric input. This is the default widget type for
`float` or `int` parameters. Numeric inputs also may be influenced by the
following metadata: `min`, `max`, `sensitivity`, `digits`, `slider`,
`slidermin`, `slidermax`, `slidercenter`, `sliderexponent`.
"string"
: Provide a text entry widget. This is the default widget type for
{\cf string} parameters.
"boolean"
: Provide a pop-up menu with "Yes" and "No" options. Works on strings
or numbers. With strings, "Yes" and "No" values are used, with
numbers, 0 and 1 are used.
"checkBox"
: A boolean widget displayed as a checkbox. Works on strings or
numbers. With strings, "Yes" and "No" values are used, with numbers,
0 and 1 are used.
"popup"
: A pop-up menu of literal choices. This widget further requires
parameter metadata `options` (a string listing the supported
menu items, delimited by the `|` character), and optionally `editable`
(an integer, which if nonzero means the widget should allow the
text field should be directly editable). For example:
```
string wrap = "default"
[[ string widget = "popup",
string options = "default|black|clamp|periodic|mirror" ]]
```
"mapper"
: A pop-up with associative choices (an enumerated type, if the values are
integers). This widget further requires parameter metadata `options`, a
`|`-delimited string with "key:value" pairs. For example:
```
int pattern = 0
[[ string widget = "mapper",
string options = "oak:0|elm:1|walnut:2" ]]
```
"filename"
: A file selection dialog.
"null"
: A hidden widget.
float min, float max, int min, int max
: The minimum and/or maximum value that the parameter may take on.
float sensitivity, int sensitivity
: The precision or step size for incrementing or decrementing the value
(within the appropriate min/max range).
int digits
: The number of digits to show (-1 for full precision).
int slider
: If nonzero, enables display of a slider sub-widget. This also respects the
following additional metadata that control the slider specifically:
`slidermin` (minimum value for the slider, `slidermax` (maximum value for
the slider), `slidercenter` (origin value for the slider), `sliderexponent`
(nonlinear slider options).
string URL
: Provides a URL for full documentation of the shader or parameter.
string units
: Gives the assumed units, if any, for the parameter (e.g., `cm`, `sec`,
`degrees`). The compiler or renderer may issue a warning if it detects that
this assumption is being violated (for example, the compiler can warn if a
`degrees` variable is passed as the argument to `cos`).
% We never implemented this:
% ## Public methods
%
% Ordinary (non-public) functions inside a shader may be called only from
% within the shader; they do not generate entry points that the renderer
% is aware of.
%
% A *public method* is a function that may be directly called by the
% renderer. Only top-level local functions of a shader --- that is,
% declared within the braces that define the local scope of the shader,
% but not within any other such function --- may be public methods. A
% function may be designated a public method by using the `public`
% keyword immediately before the function declaration:
%
% > *shader-type shader-name* `(` *params* `)` \
% > `{` \
% >
% > `public` *return-type* *function-name* `(` *optional-parameters* `)` \
% > `{` \
% > *statements* \
% > `}` \
% >
% > ...\\
% > `}`
% A given renderer will publish a list of public methods (names, arguments
% expected, and return value) that has particular meaning for that
% renderer. For example, a renderer may honor a public method
% ```
% public float maxdisplacement ()
% ```
% that computes and returns the maximum distance
% that a displacement shader will move any surface points.
% At some later point, this spec will recommend several ``standard''
% public methods that should be honored by most renderers.
+83
View File
@@ -0,0 +1,83 @@
..
Copyright Contributors to the Open Shading Language project.
SPDX-License-Identifier: CC-BY-4.0
.. image::
../../ASWF/logos/openshadinglanguage-stacked-Shaded.png
=============================================
Open Shading Language |version| Documentation
=============================================
.. only:: not latex
Editor: Larry Gritz, OSL Chief Architect
Open Shading Language (OSL) is a small but rich language for programmable
shading in advanced renderers and other applications, ideal for describing
materials, lights, displacement, and pattern generation.
Quick Links:
`GitHub repository <https://github.com/AcademySoftwareFoundation/OpenShadingLanguage>`_ /
`Developer mail list <https://lists.aswf.io/g/osl-dev>`_ /
`BSD License <https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/blob/master/LICENSE.md>`_
------------
.. default-role:: code
.. only:: not latex
Contents
--------
.. toctree::
:caption: Introduction
copyr
.. toctree::
:caption: The OSL Language Specification
:maxdepth: 2
:numbered: 2
intro
bigpicture
lexical
grosssyntax
datatypes
syntax
stdlib
grammar
shadergroups
glossary
.. comment
This is where we would put additional documentation sections
in the future.
.. comment
Helpful links when writing documentation:
Doxygen docs:
http://www.doxygen.nl/manual/index.html
Sphinx docs:
http://www.sphinx-doc.org/en/master/contents.html
http://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#cpp-domain
Breathe docs:
https://github.com/michaeljones/breathe
https://breathe.readthedocs.io/en/latest/directives.html
RST:
sphinx-tabs plugin for Sphinx:
https://pypi.org/project/sphinx-tabs/
https://sphinx-tabs.readthedocs.io/en/latest/#
+193
View File
@@ -0,0 +1,193 @@
<!--
Copyright Contributors to the Open Shading Language project.
SPDX-License-Identifier: CC-BY-4.0
SPDX-License-Identifier: BSD-3-Clause
-->
(chap-introduction=)
# Introduction
Welcome to Open Shading Language!
Open Shading Language (OSL) is a small but rich language for
programmable shading in advanced renderers and other applications, ideal
for describing materials, lights, displacement, and pattern generation.
OSL was developed by Sony Pictures Imageworks for use in its in-house
renderer used for feature film animation and visual effects. The
language specification was developed with input by other visual effects
and animation studios who also wish to use it.
OSL is distributed under the "New BSD" license. In short, you are free
to use it in your own applications, whether they are free or commercial,
open or proprietary, as well as to modify the OSL code as you desire,
provided that you retain the original copyright notices as described in
the license.
#### How OSL is different from other shading languages
OSL has syntax similar to C, as well as other shading languages.
However, it is specifically designed for advanced rendering algorithms
and has features such as radiance closures, BSDFs, and deferred ray
tracing as first-class concepts.
OSL has several unique characteristics not found in other shading
languages (certainly not all together). Here are some things you will
find are different in OSL compared to other languages:
* **Surface and volume shaders compute radiance closures, not final colors.**
OSL's surface and volume shaders compute an explicit symbolic
description, called a "closure," of the way a surface or volume
scatters light, in units of radiance. These radiance closures may be
evaluated in particular directions, sampled to find important
directions, or saved for later evaluation and re-evaluation.
This new approach is ideal for a physically-based renderer that
supports ray tracing and global illumination.
In contrast, other shading languages usually compute just a surface
color as visible from a particular direction. These old shaders are
"black boxes" that a renderer can do little with but execute to for
this once piece of information (for example, there is no effective way
to discover from them which directions are important to sample).
Furthermore, the physical units of lights and surfaces are often
underspecified, making it very difficult to ensure that shaders are
behaving in a physically correct manner.
* **Surface and volume shaders do not loop over lights or shoot rays.**
There are no "light loops" or explicitly traced rays in OSL surface
shaders. Instead, surface shaders compute a radiance closure
describing how the surface scatters light, and a part of the renderer
called an "integrator" evaluates the closures for a particular set of
light sources and determines in which directions rays should be
traced. Effects that would ordinarily require explicit ray tracing,
such as reflection and refraction, are simply part of the radiance
closure and look like any other BSDF.
Advantages of this approach include that integration and sampling may
be batched or re-ordered to increase ray coherence; a "ray budget" can
be allocated to optimally sample the BSDF; the closures may be used by
for bidirectional ray tracing or Metropolis light transport; and the
closures may be rapidly re-evaluated with new lighting without having
to re-run the shaders.
* **Surface and light shaders are the same thing.**
OSL does not have a separate kind of shader for light sources. Lights
are simply surfaces that are emissive, and all lights are area lights.
* **Transparency is just another kind of illumination.**
You don't need to explicitly set transparency/opacity variables in the
shader. Transparency is just another way for light to interact with a
surface, and is included in the main radiance closure computed by a
surface shader.
* **Renderer outputs (AOV's) are specified using "light path expressions."**
Sometimes it is desirable to output images containing individual
lighting components such as specular, diffuse, reflection, individual
lights, etc. In other languages, this is usually accomplished by
adding a plethora of "output variables" to the shaders that collect
these individual quantities.
OSL shaders need not be cluttered with any code or output variables to
accomplish this. Instead, there is a regular-expression-based
notation for describing which light paths should contribute to which
outputs. This is all done on the renderer side (though supported by
the OSL implementation). If you desire a new output, there is no need
to modify the shaders at all; you only need to tell the renderer the
new light path expression.
* **Shaders are organized into networks.**
OSL shaders are not monolithic, but rather can be organized into
networks of shaders (sometimes called a shader group, graph, or DAG),
with named outputs of some nodes being connected to named inputs of
other nodes within the network. These connections may be done
dynamically at render time, and do not affect compilation of
individual shader nodes. Furthermore, the individual nodes are
evaluated lazily, only their outputs are "pulled" from the later nodes
that depend on them (shader writers may remain blissfully unaware of
these details, and write shaders as if everything is evaluated
normally).
* **No "uniform" and "varying" keywords in the language.**
OSL shaders are evaluated in SIMD fashion, executing shaders on many
points at once, but there is no need to burden shader writers with
declaring which variables need to be uniform or varying.
In the open source OSL implementation, this is done both automatically
and dynamically, meaning that a variable can switch back and forth
between uniform and varying, on an instruction-by-instruction basis,
depending on what is assigned to it.
* **Arbitrary derivatives without grids or extra shading points.**
In OSL, you can take derivatives of any computed quantity in a shader,
and use arbitrary quantities as texture coordinates and expect correct
filtering. This does not require that shaded points be arranged in a
rectangular grid, or have any particular connectivity, or that any
"extra points" be shaded.
In the open source OSL implementation, this is possible because
derivatives are not computed by finite differences with neighboring
points, but rather by "automatic differentiation," computing partial
differentials for the variables that lead to derivatives, without any
intervention required by the shader writer.
## Acknowledgments
The original designer and project leader of OSL is Larry Gritz. Other early
developers of OSL are (in order of joining the project): Cliff Stein, Chris
Kulla, Alejandro Conty, Jay Reynolds, Solomon Boulos, Adam Martinez, Brecht
Van Lommel.
Additionally, many others have contributed features, bug fixes, and other
changes: Steve Agland, Shane Ambler, Martijn Berger, Farchad Bidgolirad,
Nicholas Bishop, Stefan Büttner, Matthaus G. Chajdas, Thomas Dinges, Henri
Fousse, Syoyo Fujita, Derek Haase, Sven-Hendrik Haase, John Haddon, Daniel
Heckenberg, Ronan Keryell, Elvic Liang, Max Liani, Bastien Montagne, Erich
Ocean, Mikko Ohtamaa, Alex Schworer, Sergey Sharybin, Stephan Steinbach,
Esteban Tovagliari, Alexander von Knorring, Roman Zulak. (Listed
alphabetically; if we've left anybody out, please let us know.)
We cannot possibly express sufficient gratitude to the managers at Sony
Pictures Imageworks who allowed this project to proceed, supported it
wholeheartedly, and permitted us to release the source, especially Rob
Bredow, Brian Keeney, Barbara Ford, Rene Limberger, and Erik Strauss.
Huge thanks also go to the crack shading team at SPI, and the brave
lookdev TDs and CG supes willing to use OSL on their shows. They served
as our guinea pigs, inspiration, testers, and a fantastic source of
feedback. Thank you, and we hope we've been responsive to your needs.
OSL was not developed in isolation. We owe a debt to the individuals
and studios who patiently read early drafts of the language
specification and gave us very helpful feedback and additional ideas,
and especially to those at other companies who have taken the risk of
incorporating OSL into their products and pipelines.
The open source OSL implementation incorporates or depends upon several
other open source packages:
- **OpenImageIO** Copyright Contributors to OpenImageIO.
http://openimageio.org
- **Imath** Copyright Contributors to Imath.
http://www.openexr.com
- **Boost** Copyright various authors. http://www.boost.org
- **LLVM** Copyright 2003-2010 University of Illinois at
Urbana-Champaign. http://llvm.org
These other packages are all distributed under licenses that allow them
to be used by and distributed with OSL.
+69 -40
View File
@@ -48,7 +48,7 @@
\def\langname{Open Shading Language\xspace}
\def\product{{\sffamily Open Shading Language}\xspace}
\def\versionnumber{1.12}
\def\versionnumber{1.13}
\def\productver{\product\ {\sffamily \versionnumber}\xspace}
@@ -59,14 +59,14 @@
Language Specification
} \bigskip }
\author{
\copyright\ Copyright 2009-present Contributors to the Open Shading Language project. \\
\copyright\ Copyright Contributors to the Open Shading Language project. \\
All rights reserved.
\bigskip \\
\vspace{1in} \\
Editor: Larry Gritz \\
\emph{lg@imageworks.com}
}
\date{{\large Date: 27 Aug 2022 \\
\date{{\large Date: 27 Oct 2023 \\
% (with corrections, 24 Nov 2021)
}
\bigskip
@@ -135,7 +135,7 @@ documentation are:
\vspace*{0.2in}
Copyright \textcopyright\ 2009-present, Contributors to the Open Shading
Copyright \textcopyright\ Contributors to the Open Shading
Language project. All Rights Reserved.
\vspace{0.5in}
@@ -380,9 +380,9 @@ The open source OSL implementation incorporates or depends upon several
other open source packages:
\begin{itemize}
\item {\cf OpenImageIO} \copyright\ 2008 Larry Gritz et al.
\item {\cf OpenImageIO} \copyright\ Contributors to OpenImageIO
\url{http://openimageio.org}
\item Ilmbase \copyright\ 2006, Industrial Light \& Magic.
\item Imath \copyright\ Contributors to Imath.
\url{http://www.openexr.com}
\item Boost \copyright\ various authors. \url{http://www.boost.org}
\item LLVM \copyright\ 2003-2010 University of Illinois at
@@ -2631,27 +2631,6 @@ and proceeds to the next iteration of the loop.
\section{Functions}
\label{sec:functions}
\subsection{Function calls}
\label{sec:syntax:functioncalls}
\index{function calls}
Function calls are very similar to C and related programming languages:
\begin{tabbing}
\hspace{0.5in} \= \hspace{0.3in} \= \kill
\> \emph{functionname} {\cf (} \emph{arg1} {\cf ,} ... {\cf ,} \emph{argn} {\cf )} \\
\end{tabbing}
If the function returns a value (not \void), you may use its value as
an expression. It is fine to completely ignore the value of even
a non-\void function.
In \langname, all arguments are passed by reference. This generally
will not be noticeably different from C-style ``pass by value''
semantics, except if you pass the same variable as two separate
arguments to a function that modifies an argument's value.
\subsection{Function definitions}
\label{sec:syntax:functiondefinitions}
\index{functions!definitions}
@@ -2699,6 +2678,35 @@ passing an {\cf int} when the function expects a {\cf float}, or passing a
{\cf float} when the function expects a \color), and finally by trying to
match the return value to the type of variable the result is assigned to.
\subsection{Function calls}
\label{sec:syntax:functioncalls}
\index{function calls}
Function calls are very similar to C and related programming languages:
\begin{tabbing}
\hspace{0.5in} \= \hspace{0.3in} \= \kill
\> \emph{functionname} {\cf (} \emph{arg1} {\cf ,} ... {\cf ,} \emph{argn} {\cf )} \\
\end{tabbing}
If the function returns a value (not \void), you may use its value as
an expression. It is fine to completely ignore the value of even
a non-\void function.
In \langname, all arguments are passed by reference. This generally
will not be noticeably different from C-style ``pass by value''
semantics, except if you pass the same variable as two separate
arguments to a function that modifies an argument's value.
Certain functions allow optional arguments to be passed.
Optional arguments are key-value pairs with the key passed as an
argument and the associated value passed as the subsequent argument:
\begin{tabbing}
\hspace{0.5in} \= \hspace{0.3in} \= \kill
\> \emph{functionname} {\cf (} \emph{arg1} {\cf ,} ... {\cf ,} \emph{argn} {\cf ,} \emph{"optionalkey"} {\cf ,} \emph{optionalvalue} {\cf ,} ... {\cf )} \\
\end{tabbing}
\subsection{Operator overloading}
\label{sec:syntax:operatoroverloading}
\index{operator overloading}
@@ -4083,8 +4091,8 @@ are assigned to a \float or a \color (or type cast to one of those)
determines whether the texture lookup is a single channel or three
channels.
The 2D lookup coordinate(s) may be followed by optional token/value
arguments that control the behavior of {\cf texture()}:
The 2D lookup coordinate(s) may be followed by optional key-value
arguments (see Section~\ref{sec:syntax:functioncalls}) that control the behavior of {\cf texture()}:
\apiitem{"blur", <float>}
\vspace{12pt}
@@ -5599,7 +5607,7 @@ forms of the function with no object name, or if the object name is the
empty string \qkw{}, the renderer will first search
per-object attributes on the current object (or interpolated variables
with that name attached to the object), then if not found it will search
searching global scene-wide attributes.
global scene-wide attributes.
If the attribute is found and can be converted to the type of
\emph{destination}, the attribute's value will be stored in
@@ -5901,17 +5909,38 @@ view-dependence into shaders.
The return value is 0 if the ray missed all geometry, 1 if it hit
anything within the distance range.
Optional parameters include:
The following optional key-value arguments
(see Section~\ref{sec:syntax:functioncalls}) can be passed:
\begin{tabular}{p{1.2in} p{0.5in} p{3.2in}}
\qkw{mindist} & {\cf float} & Minimum hit distance (default: zero) \\
\qkw{maxdist} & {\cf float} & Maximum hit distance (default: infinite) \\
\qkw{shade} & {\cf int} & Whether objects hit will be shaded
(default: 0) \\
\qkw{traceset} & {\cf string} & An optional named set of objects to
ray trace (if preceded by a `{\cf -}'
character, it means to exclude that set).
\end{tabular}
\apiitem{"mindist", <float>}
\vspace{12pt}
The minimum hit distance (default: 0).
The units of the {\cf "mindist"} and {\cf "maxdist"} are determined by the renderer
and are sometimes defined by the dir vector, which can lead to unexpected
behavior. So, generally, clearly written and portable shaders should pass
a unit length (see Section~\ref{sec:stdlib:geom}) dir vector.
\apiend
\vspace{-16pt}
\apiitem{"mindist", <float>}
\vspace{12pt}
The maximum hit distance (default: infinite).
\apiend
\vspace{-16pt}
\apiitem{"shade", <int>}
\vspace{12pt}
Defines whether objects hit will be shaded (default: 0).
\apiend
\vspace{-16pt}
\apiitem{"traceset", <string>}
\vspace{12pt}
An optional named set of objects to ray trace (if preceded by a `{\cf -}'
character, it means to exclude that set).
\apiend
\vspace{-16pt}
Information about the closest object hit by the ray may be retrieved
using \\ {\cf getmessage("trace",...)} (see Section~\ref{sec:getmessage}).
+122
View File
@@ -0,0 +1,122 @@
# Lexical structure
## Characters
Source code for OSL consists of ASCII or UTF-8 characters.
The characters for space, tab, carriage return, and linefeed are
collectively referred to as *whitespace*. Whitespace characters
delimit identifiers, keywords, or other symbols, but other than that
have no syntactic meaning. Multiple whitespace characters in a row
are equivalent to a single whitespace character.
Source code may be split into multiple lines, separated by end-of-line
markers (carriage return and/or linefeed). Lines may be of any length
and end-of-line markers carry no significant difference from other
whitespace, except that they terminate `//` comments and delimit
preprocessor directives.
## Identifiers
*Identifiers* are the names of variables, parameters, functions, and shaders.
In OSL, identifiers consist of one or more characters. The first character
may be a letter (`A`-`Z` or `a`-`z`) or underscore (`_`), and subsequent
characters may be letters, underscore, or numerals (`0`-`9`). Examples of
valid and invalid identifiers are:
```
opacity // valid
Long_name42 // valid - letters, underscores, numbers are ok
_foo // valid - ok to start with an underscore
2smart // invalid - starts with a numeral
bigbuck$ // invalid - $ is an illegal character
```
## Comments
*Comments* are text that are for the human reader of programs, and
are ignored entirely by the OSL compiler. Just like in C++, there
are two ways to designate comments in OSL:
1. Any text enclosed by `/*` and `*/` will be considered a comment, even if
the comment spans several lines.
```
/* this is a comment */
/* this is also
a comment, spanning
several lines */
```
2. Any text following `//`, up to the end of the current line, will be
considered a comment.
```
// This is a comment
a = 3; // another comment
```
## Keywords and reserved words
There are two sets of names that you may not use as identifiers:
keywords and reserved words.
The following are *keywords* that have special meaning in OSL:
and break closure color continue do else emit float for if illuminance
illuminate int matrix normal not or output point public return string
struct vector void while
The following are *reserved words* that currently have no special meaning in
OSL, but we reserve them for possible future use, or because they are
confusingly similar to keywords in related programming languages:
bool case catch char class const delete default double
enum extern false friend
goto inline long new operator private protected
short signed sizeof static
switch template this throw true try typedef
uniform union unsigned varying virtual volatile
## Preprocessor
Shader source code is passed through a standard C preprocessor as a
first step in parsing.
Preprocessor directives are designated by a hash mark `#` as the first
character on a line, followed by a preprocessor directive name. Whitespace may
optionally appear between the hash and the directive name.
OSL compilers support the full complement of C/C++ preprocessing directives,
including:
```
#define
#undef
#if
#ifdef
#ifndef
#elif
#else
#endif
#include
#pragma error "message"
#pragma once
#pragma osl ...
#pragma warning "message"
```
Additionally, the following preprocessor symbols will already be
defined by the compiler:
| | |
| ------ | :------- |
| `OSL_VERSION_MAJOR` | Major version (e.g., 1) |
| `OSL_VERSION_MINOR` | Minor version (e.g., 9) |
| `OSL_VERSION_PATCH` | Patch version (e.g., 3) |
| `OSL_VERSION` | Combined version number = `10000*major + 100*minor + patch` (e.g., 10903 for version 1.9.3) |
Binary file not shown.
+6
View File
@@ -0,0 +1,6 @@
sphinx >= 5.0
breathe == 4.34.0
sphinx-tabs
furo==2022.6.21
myst-parser
linkify
+100
View File
@@ -0,0 +1,100 @@
---
numbering:
heading_1: true
heading_2: true
heading_3: true
---
<!--
Copyright Contributors to the Open Shading Language project.
SPDX-License-Identifier: CC-BY-4.0
-->
(chap-shader-groups)=
# Describing shader groups
Below, we propose a simple grammar giving a standard way to serialize (i.e.,
express as text) a full shader group, including instance values and
connectivity of the shader layers. There are only three statements/operations:
set an instance value, make a shader instance, and connect two instances.
**`param`** *`type paramname value`*... **`;`** <br> **`param`** *`type paramname value`*... **`[[`** *`metadata`*... **`]] ;`**
: Declare an instance value of a shader parameter to be applied to the next
`shader` statement. We refer to the parameter values set, which have not
yet had their shader declared, as *pending parameters*.
The *`paramname`* is the name of the parameter whose instance values are
being specified.
The *`type`* is one of the basic numeric or string data types described in
Chapter [](#chap-types) (`int`, `float`,`color`, `point`, `vector`, `normal`,
`matrix`, or `string`), or an array thereof (indicated by the usual notation
of `[size]`). The *`type`* must match the declared type of the parameter in
the shader.
The actual values are listed individually, with multiple values (in the
case of an array or an aggregate such as a `color`) simply separated by
whitespace. If fewer values are supplied than the total number of array
elements or aggregate components, the remainder will be understood to be
filled with 0 values. String values must be enclosed in double quotes
(`"like this"`).
The `param` statement is terminated by a semicolon (`;`).
Optionally, metadata hints may be supplied enclosed by double brackets,
immediately before the semicolon.
**`shader`** *`shadername layername`* **`;`**
: Declares a shader instance, which will receive any pending parameters that
were declared since the previous `shader` statement (and in the process,
clear the list of pending parameters).
The `shadername` is an identifier that specifies the name of the shader
to use as the master for this instance. The `layername` is an identifier
that names the layer (e.g., to subsequently specify it as a source or
destination for connections).
The `shader` statement is terminated by a semicolon (`;`).
**`connect`** *`source_layername`* **`.`** *`paramname`* $~~$ *` destination_layername`* **`.`** *`paramname`* **`;`**
: Establish a connection between an output parameter of a source layer and an
input parameter of a destination layer, both of which have been previously
declared within this group. The source layer must have preceded the
destination layer when they were declared, and the parameters must exist and
be of a compatible type so that it is meaningful to establish a connection
(for example, you may connect a `color` to a `color`, but you may not connect
a `color` to a `matrix`).
If the named parameters are structures, the two structures must have
identical data layout, and establishing the connection will connect each
corresponding data member. It is also possible to make a connection of just
a single member of a structure by using the usual ``dot'' syntax, for
example, for layers `A` and `B`, `connect A.c.x B.y` might
connect A's parameter `c`, member `x`, to B's parameter `y` (the
types of `c.x` in A and `y` in B must match).
The `connect` statement is terminated by a semicolon (`;`).
**Example**
param string name "rings.tx" ; # set pending `name'
param float scale 3.5 ; # set pending `scale'
shader "texturemap" "tex1" ; # tex1 layer, picks up `name', `scale'
param string name "grain.tx" ;
shader "texturemap" "tex2" ;
param float gam 2.2 ;
shader "gamma" "gam1" ;
param float gam 1.0 ;
shader "gamma" "gam2" ;
param color woodcolor 0.42 0.38 0.22 ; # example of a color param
shader "wood" "wood1" ;
connect tex1.Cout gam1.Cin ; # connect tex1's Cout to gam1's Cin
connect tex2.Cout gam2.Cin ;
connect gam1.Cout wood1.rings ;
connect gam2.Cout wood1.grain ;
+2232
View File
File diff suppressed because it is too large Load Diff
+566
View File
@@ -0,0 +1,566 @@
---
numbering:
heading_1: true
heading_2: true
heading_3: true
---
<!--
Copyright Contributors to the Open Shading Language project.
SPDX-License-Identifier: CC-BY-4.0
-->
(chap-syntax)=
# Language Syntax
The body of a shader is a sequence of individual *statements*.
This chapter describes the types of statements and control-flow patterns
in OSL.
Statements in OSL include the following types of constructs:
* Scoped statements.
* Variable declarations.
* Expressions.
* Assignments.
* Control flow: `if`, `else`, `while`, `do`, `for`, `break`, `continue`
* Function declarations.
#### Scoping
Any place where it is legal to have a statement, it is legal to have multiple
statements enclosed by curly braces `{ }`. This is called a *scope*. Any
variables or functions declared within a scope are only visible within that
scope, and only may be used after their declaration. Variables or functions
that are referenced will always resolve to the matching name in the innermost
scope relative to its use. For example
```
float a = 1; // Call this the "outer" 'a'
float b = 2;
{
float a = 3; // Call this the "inner" 'a'
float c = 1;
b = a; // b gets 3, because a is resolved to the inner scope
}
b += c; // ERROR -- c was only in the inner scope
```
## Variable declarations and assignments
### Variable declarations
The syntax for declaring a variable in OSL is:
> *type* *name*
>
> *type* *name* `=` *value*
where
* *type* is one of the basic data types, described earlier.
* *name* is the name of the variable you are declaring.
* If you wish to initialize your variable an initial value, you may
immediately assign it a *value*, which may be any valid expression.
You may declare several variables of the same type in a single
declaration by separating multiple variable names by commas:
> *type* *name1* `,` *name2* ...
>
> *type* *name1* [ = *value1*] `,` *name2* [ `=` *value2* ] ...
Some examples of variable declarations are
```
float a; // Declare; current value is undefined
float b = 1; // Declare and assign a constant initializer
float c = a*b; // Computed initializer
float d, e = 2, f; // Declare several variables of the same type
```
### Arrays
Arrays are also supported, declared as follows:
> *type variablename* `[` *arraylen* `}`
>
> *type variablename* `[` *arraylen* `}` `=` `{` *init0 `,` *init1* ... `}`
Array variables in OSL must have a constant length (though function parameters
and shader parameters may have undetermined length). Some examples of array
variable declarations are:
```
float d[10]; // Declare an uninitialized array
float c[3] = { 0.1, 0.2, 3.14 }; // Initialize the array
```
### Structures
Structures are used to group several fields of potentially different
types into a single object that can be referred to by name. The syntax
for declaring a structure type is:
\spc `struct` *structname* {\cf \{}
\spc\spc *type1* *fieldname1* `;`
\spc\spc ...
\spc\spc *typeN* *fieldnameN* `;`
\spc `) ;`
You may then use the structure type name to declare structure variables
as you would for any of the built-in types:
\spc *structname* *variablename* `;`
\spc *structname* *variablename* {\cf = \{ }
*initializer1* `,` ... *initializerN* `) ;`
If initializers are supplied, each field of the structure will be
initialized with the initializer in the corresponding position, which
is expected to be of the appropriate type.
Structure elements are accessed in the same way as other C-like
languages, using the `dot' operator:
\spc *variablename*{\cf .} *fieldname*
Examples of declaration and use of structures:
```
struct ray {
point pos;
vector dir;
};
ray r; // Declare a structure
ray s = { point(0,0,0), vector(0,0,1) }; // declare and initialize
r.pos = point (1, 0, 0); // Assign to one field
```
It is permitted to have a structure field that is an array, as well as
to have an array of structures. But it is not permitted for one
structure to have a field that is another structure.
Please refer to Section~\ref{sec:types:struct} for more information
on using `struct`.
(sec-expressions)=
## Expressions
The expressions available in OSL include the following:
* Constants: integer (e.g., `1`, `42`), floating-point (e.g. `1.0`, `3`,
`-2.35e4`), or string literals (e.g., `"hello"`)
* point, vector, normal, or matrix constructors, for example:
```
color (1, 0.75, 0.5)
point ("object", 1, 2, 3)
```
If all the arguments to a constructor are themselves constants, the
constructed point is treated like a constant and has no runtime cost.
That is, `color(1,2,3)` is treated as a single constant entity, not
assembled bit by bit at runtime.
* Variable or parameter references
* An individual element of an array (using `[ ]`)
* An individual component of a `color`, `point`, `vector`, `normal` (using
`[ ]`), or of a `matrix` (using `[][]`)
* prefix and postfix increment and decrement operators:
Operator | Meaning
:-- | :--
*varref* `++` | post-increment
*varref* `--` | post-decrement
`++` *varref* | pre-increment
`--` *varref* | pre-decrement
The post-increment and post-decrement (e.g., {\cf a++}) returns the old
value, then increments or decrements the variable; the pre-increment and
pre-decrement ({\cf ++a}) will first increment or decrement the
variable, then return the new value.
* Unary and binary arithmetic operators on other expressions:
Operator | Meaning
:-- | :--
`-` *expr* | negation
`~` *expr* | bitwise complement
*expr* `*` *expr* | multiplication
*expr* `/` *expr* | division
*expr* `+` *expr* | addition
*expr* `-` *expr* | subtraction
*expr* `%` *expr* | integer modulus
*expr* `<<` *expr* | integer shift left
*expr* `>>` *expr* | integer shift right
*expr* `&` *expr* | bitwise and
*expr* `\|` *expr* | bitwise or
*expr* `^` *expr* | bitwise exclusive or
The operators `+`, `-`, `*`, `/`, and the unary `-` (negation) may be used
on most of the numeric types. For multicomponent types (`color`, `point`,
`vector`, `normal`, `matrix`), these operators combine their arguments on a
component-by-component basis. The only operators that may be applied to the
`matrix` type are `*` and `/`, which respectively denote matrix-matrix
multiplication and matrix multiplication by the inverse of another matrix.
The integer and bit-wise operators `%`, `<<`, `>>`, `&`, `|`, `^`, and `~`
may only be used with expressions of type `int`.
For details on which operators are allowed, please consult the operator
tables for each individual type in Chapter [](#chap-types).
* Relational operators (all lower precedence than the arithmetic operators):
Operator | Meaning
:-- | :--
*expr* `==` *expr* | equal to
*expr* `!=` *expr* | not equal to
*expr* `<` *expr* | less then
*expr* `<=` *expr* | less than or equal to
*expr* `>` *expr* | greater than
*expr* `>=` *expr* | greater than or equal
The `==` and `!=` operators may be performed between any two values of equal
type, and are performed component-by-component for multi-component types.
The `<`, `<=`, `>`, `>=` may not be used to compare multi-component types.
An `int` expression may be compared to a `float` (and is treated as if
they are both `float`). A `float` expression may be compared to a
multi-component type (and is treated as a multi-component type as if
constructed from a single float).
Relation comparisons produce Boolean (true/false) values. These
are implemented as `int` values, 0 if false and 1 if true.
* Logical unary and binary operators:
> `!` *expr*
> *expr1* `&&` *expr2*
> *expr1* `\|\|` *expr2*
Note that the `not`, `and`, and `or` keywords are synonyms for `!`, `&&`,
and `||`, respectively.
For the logical operators, numeric expressions (`int` or `float`) are
considered *true* if nonzero, *false* if zero. Multi-component types (such
as `color`) are considered *true* any component is nonzero, *false* all
components are zero. Strings are considered *true* if they are nonempty,
*false* if they are the empty string (`""`).
* another expression enclosed in parentheses: `( )`. Parentheses may be used
to guarantee associativity of operations.
* Type casts, specified either by having the type name in parentheses in front
of the value to cast (C-style typecasts) or the type name called as a
constructor (C++-style type constructors):
```
(vector) P /* cast a point to a vector */
(point) f /* cast a float to a point */
(color) P /* cast a point to a color! */
vector (P) /* Means the same thing */
point (f)
color (P)
```
The three-component types (`color`, `point`, `vector`, `normal`) may be cast
to other three-component types. A `float` may be cast to any of the
three-component types (by placing the float in all three components) or to a
`matrix` (which makes a matrix with all diagonal components being the
`float`). Obviously, there are some type casts that are not allowed because
they make no sense, like casting a `point` to a `float`, or casting a
`string` to a numerical type.
* function calls
* assignment expressions:
same thing as `var = var OP expr` :
Operator | Meaning
:-- | :--
*var* `=` *expr* | assign
*var* `+=` *expr* | add
*var* `-=` *expr* | subtract
*var* `*=` *expr* | multiply
*var* `/=` *expr* | divide
*int-var* `&=` *int-expr* | bitwise and
*int-var* `\|=` *int-expr* | bitwise or
*int-var* `^=` *int-expr* | bitwise exclusive or
*int-var* `<<=` *int-expr* | integer shift left
*int-var* `>>=` *int-expr* | integer shift right
Note that the integer and bit-wise operators are only allowed with `int`
variables and expressions. In general, `var OP= expr` is allowed only if
`var = var OP expr` is allowed, and means exactly the same thing. Please
consult the operator tables for each individual type in Chapter
[](#chap-types).
* ternary operator, just like C:
> *condition* `?` *expr1* `:` *expr2*
This expression takes on the value of *expr1* if *condition* is true
(nonzero), or *expr2* if *condition* is false (zero).
Please refer to Chapter [](#chap-types), where the section describing each
data type describes the full complement of operators that may be used with the
type. Operator precedence in OSL is identical to that of C.
## Control flow: `if`, `while`, `do`, `for`
Conditionals in OSL just like in C or C++:
\begin{tabbing}
\hspace{0.5in} \= \hspace{0.3in} \= \kill
\> {\cf if (} *condition* {\cf )} \\
\> \> *truestatement*
\end{tabbing}
and
\begin{tabbing}
\hspace{0.5in} \= \hspace{0.3in} \= \kill
\> {\cf if (} *condition* {\cf )} \\
\> \> *truestatement* \\
\> {\cf else} \\
\> \> *falsestatement*
\end{tabbing}
The statements can also be entire blocks, surrounded by curly
braces. For example,
```
if (s > 0.5) {
x = s;
y = 1;
} else {
x = s+t;
}
```
The *condition* may be any valid expression, including:
* The result of any comparison operator (such as `<`, `==`, etc.).
* Any numeric expression (`int`, `color`, `point`, `vector`, `normal`,
`matrix`), which is considered "true" if nonzero and "false" if zero.
* Any string expression, which is considered "true" if it is a nonempty
string, "false" if it is the empty string (`""`).
* A closure, which is considered "true" if it's empty (not assigned, or
initialized with {\cf =0}), and "false" if anything else has been assigned
to it.
* A logical combination of expressions using the operators `!` (not), `&&`
(logical "and"), or `||` (logical "or"). Note that `&&` and `\|\|`
*short circuit* as in C, i.e. `A && B` will only evaluate B if A
is true, and `A || B` will only evaluate B if A is false.
Repeated execution of statements for as long as a condition is true is
possible with a `while` statement:
> `while (` *condition* `)` *statements*
Or the test may happen after the body of the loop, with a `do/while` loop:
> `do` *statement* `while (` *condition* `)`
Also, `for` loops are also allowed:
> `for (` *initialization-statement* `;` *condition* `;` *iteration-statement* `)` \
> *body-statements*
As in C++, a `for` loop's initialization may contain variable declarations and
initializations, which are scoped locally to the `for` loop itself. For
example,
```
for (int i = 0; i < 3; ++i) {
...
}
```
As with `if` statements, loop conditions may be relations or numerical
quantities (which are considered "true" if nonzero, "false" if zero), or
strings (considered "true" if nonempty, "false" if the empty string `""`.
Inside the body of a loop, the `break` statement terminates the loop
altogether, and the `continue` statement skip to the end of the body and
proceeds to the next iteration of the loop.
## Functions
### Function definitions
You may define functions much like in C or C++.
> *return-type* *function-name* `(` *optional-parameters* `)` \
> `{` \
> *statements* \
> `}`
Parameters to functions are similar to shader parameters, except that they do
not permit initializers. A function call must pass values for all formal
parameters. Function parameters in OSL are all *passed by reference*, and are
read-only within the body of the function unless they are also designated as
`output` (in the same manner as output shader parameters).
Like for shaders, statements inside functions may be actual executions
(assignments, function call, etc.), local variable declarations (visible
only from within the body of the function), or local function
declarations (callable only from within the body of the function).
The return type may be any simple data type, a `struct`, or a
`closure`. Functions may not return arrays. The return type may be
`void`, indicating that the function does not return a value (and
should not contain a `return` statement). A `return` statement
inside the body of the function will halt execution of the function at
that point, and designates the value that will be returned (if not a
`void` function).
Functions may be *overloaded*. That is, multiple functions may be
defined to have the same name, as long as they have differently-typed
parameters, so that when the function is called the list of arguments can
select which version of the function is desired. When there are multiple
potential matches, function versions whose argument types match exactly are
favored, followed by those that match with type coercion (for example,
passing an `int` when the function expects a `float`, or passing a
`float` when the function expects a `color`), and finally by trying to
match the return value to the type of variable the result is assigned to.
(sec-syntax-functioncalls)=
### Function calls
Function calls are very similar to C and related programming languages:
> *functionname* `(` *arg1* `,` ... `,` *argn* `)`
If the function returns a value (not `void`), you may use its value as an
expression. It is fine to completely ignore the value of even a non-`void`
function.
In OSL, all arguments are passed by reference. This generally will not be
noticeably different from C-style "pass by value" semantics, except if you
pass the same variable as two separate arguments to a function that modifies
an argument's value.
Certain functions allow optional arguments to be passed.
Optional arguments are key-value pairs with the key passed as an argument and
the associated value passed as the subsequent argument:
> *functionname* `(` *arg1* `,` ... `,` *argn* `,` *"optionalkey"* `,` *optionalvalue* `,` ... `)`
### Operator overloading
OSL permits \emph{operator overloading}, which is the practice of providing a
function that will be called when you use an operator like `+` or `*`. This is
especially handy when you use `struct` to define mathematical types and wish
for the usual math operators to work with them. Here is a typical example,
which also shows the special naming convention that allows operator
overloading:
```
struct vector4 {
float x, y, z, w;
};
vector4 __operator__add__ (vector4 a, vector4 b) {
return vector4 (a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w);
}
shader test ()
{
vector4 a = vector4 (.2, .3, .4, .5);
vector4 b = vector4 (1, 2, 3, 4);
vector4 c = a + b; // Will call __operator__add__(vector4,vector4)
printf ("a+b = %g %g %g %g\n", c.x, c.y, c.z, c.w);
}
```
The full list of these special function names is as follows (in order of
decreasing operator precedence):
Operator | Overload function name | notes
:---------- | :----------- | :------
`-` | `__operator__neg__` | unary negation
`~` | `__operator__compl__` | unary bitwise
`!` | `__operator__not__` | unary boolean 'not'
`*` | `__operator__mul__` |
`/` | `__operator__div__` |
`\%` | `__operator__mod__` |
`+` | `__operator__add__` |
`-` | `__operator__sub__` |
`<<` | `__operator__shl__` |
`>>` | `__operator__shr__` |
`<` | `__operator__lt__` |
`<=` | `__operator__le__` |
`>` | `__operator__gt__` |
`>=` | `__operator__ge__` |
`==` | `__operator__eq__` |
`!=` | `__operator__ne__` |
`\&` | `__operator__bitand__` |
`^` | `__operator__xor__` |
`\|` | `__operator__bitor__` |
## Global variables
*Global variables* (sometimes called *graphics state variables*) contain the
basic information that the renderer knows about the point being shaded, such
as position, surface orientation, and default surface color. You need not
declare these variables; they are simply available by default in your shader.
Global variables available in shaders are listed in the following table:
Variable | Description
:---------- | :-----------
`point P` | Position of the point you are shading. In a displacement shader, changing this variable displaces the surface.
`vector I` | The *incident* ray direction, pointing from the viewing position to the shading position `P`.
`normal N` | The surface "Shading" "normal of the surface at `P`. Changing `N` yields bump mapping.
`normal Ng` | The true surface normal at `P`. This can differ from `N`; `N` can be overridden in various ways including bump mapping and user-provided vertex normals, but `Ng` is always the true surface geometric normal of the surface at `P`.
`float u, v` | The 2D parametric coordinates of \P (on the particular geometric primitive you are shading).
`vector dPdu, dPdv` | Partial derivatives $\partial P/\partial u$ and $\partial P/\partial v$ tangent to the surface at `P`.
`point Ps` | Position at which the light is being queried (currently only used for light attenuation shaders)
`float time` | Current shutter time for the point being shaded.
`float dtime` | The amount of time covered by this shading sample.
`vector dPdtime` | How the surface position \P is moving per unit time
`closure color Ci` | Incident radiance --- a closure representing the color of the light leaving the surface from `P` in the direction `-I`.
Accessibility of variables by shader type:
Variable | surface | displacement | volume
:---------- | ----- | -- | --
`P` | R | RW | R
`I` | R | | R
`N` | RW | RW |
`Ng` | R | R |
`dPdu` | R | R |
`dPdv` | R | R |
`Ps` | | | R
`u, v` | R | R | R
`time` | R | R | R
`dtime` | R | R | R
`dPdtime` | R | R | R
`Ci` | RW | | RW
+2 -6
View File
@@ -28,16 +28,12 @@ endif()
set (versionfile oslversion.h)
if (VERBOSE)
message (STATUS "Create ${versionfile} from ${versionfile}.in")
endif ()
message (VERBOSE "Create ${versionfile} from ${versionfile}.in")
configure_file (${PROJECT_NAME}/${versionfile}.in "${CMAKE_BINARY_DIR}/include/${PROJECT_NAME}/${versionfile}" @ONLY)
list (APPEND public_headers "${CMAKE_BINARY_DIR}/include/${PROJECT_NAME}/${versionfile}")
set (oslconfighfile oslconfig.h)
if (VERBOSE)
message (STATUS "Create ${oslconfighfile} from ${oslconfighfile}.in")
endif ()
message (VERBOSE "Create ${oslconfighfile} from ${oslconfighfile}.in")
configure_file (${PROJECT_NAME}/${oslconfighfile}.in "${CMAKE_BINARY_DIR}/include/${PROJECT_NAME}/${oslconfighfile}" @ONLY)
list (APPEND public_headers "${CMAKE_BINARY_DIR}/include/${PROJECT_NAME}/${oslconfighfile}")
+1 -1
View File
@@ -265,7 +265,7 @@ nonAffineInverse(const Matrix44 &source);
Matrix44 OSL_HOSTDEVICE nonAffineInverse(const Matrix44 &source)
{
OSL_INTEL_PRAGMA(float_control(strict,on,push))
OSL_INTEL_CLASSIC_PRAGMA(float_control(strict,on,push))
OSL_CLANG_PRAGMA(clang fp contract(off))
using ScalarT = typename Matrix44::BaseType;
+35 -32
View File
@@ -82,12 +82,13 @@ public:
/// Return a Mask with lanes set to true if ok, false if the named matrix
/// is not known.
virtual Mask get_matrix(BatchedShaderGlobals* bsg, Masked<Matrix44> wresult,
ustring from, Wide<const float> wtime)
ustringhash from, Wide<const float> wtime)
{
return Mask(false);
}
virtual Mask get_matrix(BatchedShaderGlobals* bsg, Masked<Matrix44> result,
Wide<const ustring> wfrom, Wide<const float> wtime);
Wide<const ustringhash> wfrom,
Wide<const float> wtime);
virtual bool is_overridden_get_matrix_WmWsWf() const = 0;
@@ -97,12 +98,12 @@ public:
/// particular renderer may have a better technique and overload the
/// implementation.
virtual Mask get_inverse_matrix(BatchedShaderGlobals* bsg,
Masked<Matrix44> wresult, ustring to,
Masked<Matrix44> wresult, ustringhash to,
Wide<const float> wtime);
virtual bool is_overridden_get_inverse_matrix_WmsWf() const = 0;
virtual Mask get_inverse_matrix(BatchedShaderGlobals* bsg,
Masked<Matrix44> wresult,
Wide<const ustring> wto,
Wide<const ustringhash> wto,
Wide<const float> wtime);
virtual bool is_overridden_get_inverse_matrix_WmWsWf() const = 0;
@@ -124,22 +125,23 @@ public:
/// specified (object == ustring()), then the renderer should search *first*
/// for the attribute on the currently shaded object, and next, if
/// unsuccessful, on the currently shaded "scene".
virtual Mask get_attribute(BatchedShaderGlobals* bsg, ustring object,
ustring name, MaskedData wval)
virtual Mask get_attribute(BatchedShaderGlobals* bsg, ustringhash object,
ustringhash name, MaskedData wval)
{
return Mask(false);
}
/// Similar to get_attribute(); this method will fetch the 'index'
/// element of an attribute array.
virtual Mask get_array_attribute(BatchedShaderGlobals* bsg, ustring object,
ustring name, int index, MaskedData wval)
virtual Mask get_array_attribute(BatchedShaderGlobals* bsg,
ustringhash object, ustringhash name,
int index, MaskedData wval)
{
return Mask(false);
}
virtual bool get_attribute_uniform(BatchedShaderGlobals* bsg,
ustring object, ustring name,
ustringhash object, ustringhash name,
RefData val)
{
return false;
@@ -148,8 +150,9 @@ public:
/// Similar to get_attribute(); this method will fetch the 'index'
/// element of an attribute array.
virtual bool get_array_attribute_uniform(BatchedShaderGlobals* bsg,
ustring object, ustring name,
int index, RefData val)
ustringhash object,
ustringhash name, int index,
RefData val)
{
return false;
}
@@ -159,7 +162,7 @@ public:
/// as well. It is assumed the results are varying and returns Mask
// with its bit set to off if no user-data with the given name and type was
/// found.
virtual Mask get_userdata(ustring name, BatchedShaderGlobals* bsg,
virtual Mask get_userdata(ustringhash name, BatchedShaderGlobals* bsg,
MaskedData wval)
{
return Mask(false);
@@ -206,7 +209,7 @@ public:
/// error.
///
virtual Mask
texture(ustring filename, TextureSystem::TextureHandle* texture_handle,
texture(ustringhash filename, TextureSystem::TextureHandle* texture_handle,
TextureSystem::Perthread* texture_thread_info,
const BatchedTextureOptions& options, BatchedShaderGlobals* bsg,
Wide<const float> ws, Wide<const float> wt, Wide<const float> wdsdx,
@@ -240,7 +243,7 @@ public:
/// messages (in case of failure, when the function returns false) will
/// be stored there, leaving it up to the caller/shader to handle the
/// error.
virtual Mask texture3d(ustring filename,
virtual Mask texture3d(ustringhash filename,
TextureSystem::TextureHandle* texture_handle,
TextureSystem::Perthread* texture_thread_info,
const BatchedTextureOptions& options,
@@ -273,7 +276,7 @@ public:
/// messages (in case of failure, when the function returns false) will
/// be stored there, leaving it up to the caller/shader to handle the
/// error.
virtual Mask environment(ustring filename,
virtual Mask environment(ustringhash filename,
TextureSystem::TextureHandle* texture_handle,
TextureSystem::Perthread* texture_thread_info,
const BatchedTextureOptions& options,
@@ -300,12 +303,12 @@ public:
virtual TextureSystem::TextureHandle* resolve_udim_uniform(
BatchedShaderGlobals* bsg, TexturePerthread* texture_thread_info,
ustring filename, TextureSystem::TextureHandle* texture_handle, float S,
float T);
ustringhash filename, TextureSystem::TextureHandle* texture_handle,
float S, float T);
virtual void resolve_udim(BatchedShaderGlobals* bsg,
TexturePerthread* texture_thread_info,
ustring filename,
ustringhash filename,
TextureSystem::TextureHandle* texture_handle,
Wide<const float> wS, Wide<const float> wT,
Masked<TextureSystem::TextureHandle*> wresult);
@@ -313,8 +316,8 @@ public:
// Assumes any UDIM has been resolved already
virtual bool get_texture_info_uniform(
BatchedShaderGlobals* bsg, TexturePerthread* texture_thread_info,
ustring filename, TextureSystem::TextureHandle* texture_handle,
int subimage, ustring dataname, RefData val);
ustringhash filename, TextureSystem::TextureHandle* texture_handle,
int subimage, ustringhash dataname, RefData val);
/// Lookup nearest points in a point cloud. It will search for
@@ -407,26 +410,25 @@ public:
};
virtual void pointcloud_search(BatchedShaderGlobals* bsg, ustring filename,
const void* wcenter,
virtual void pointcloud_search(BatchedShaderGlobals* bsg,
ustringhash filename, const void* wcenter,
Wide<const float> wradius, int max_points,
bool sort, PointCloudSearchResults& results);
virtual bool is_overridden_pointcloud_search() const = 0;
virtual Mask pointcloud_get(BatchedShaderGlobals* bsg, ustring filename,
virtual Mask pointcloud_get(BatchedShaderGlobals* bsg, ustringhash filename,
Wide<const int[]> windices,
Wide<const int> wnum_points, ustring attr_name,
MaskedData wout_data);
Wide<const int> wnum_points,
ustringhash attr_name, MaskedData wout_data);
virtual bool is_overridden_pointcloud_get() const = 0;
virtual Mask pointcloud_write(BatchedShaderGlobals* bsg, ustring filename,
Wide<const OSL::Vec3> wpos, int nattribs,
const ustring* attr_names,
const TypeDesc* attr_types,
const void** pointers_to_wide_attr_value,
Mask mask);
virtual Mask
pointcloud_write(BatchedShaderGlobals* bsg, ustringhash filename,
Wide<const OSL::Vec3> wpos, int nattribs,
const ustring* attr_names, const TypeDesc* attr_types,
const void** pointers_to_wide_attr_value, Mask mask);
virtual bool is_overridden_pointcloud_write() const = 0;
/// Options for the trace call.
@@ -441,7 +443,8 @@ public:
Wide<const Vec3> wdRdy);
virtual void getmessage(BatchedShaderGlobals* bsg, Masked<int> wresult,
ustring source, ustring name, MaskedData wval);
ustringhash source, ustringhash name,
MaskedData wval);
// pointcloud_search is T.B.D.
+1 -7
View File
@@ -41,9 +41,7 @@ template<int WidthT> struct VaryingTextureOptions {
Block<float, WidthT> swidth; ///< Multiplier for derivatives
Block<float, WidthT> twidth;
Block<float, WidthT> rwidth; // For 3D volume texture lookups only:
#if OIIO_VERSION_GREATER_EQUAL(2, 4, 0)
Block<float, WidthT> rnd; // For stochastic sampling
#endif
Block<float, WidthT> rnd; // For stochastic sampling
};
static_assert(std::alignment_of<VaryingTextureOptions<16>>::value
== VecReg<16>::alignment,
@@ -69,9 +67,7 @@ template<int WidthT> struct BatchedTextureOptions {
swidth,
twidth,
rwidth,
#if OIIO_VERSION_GREATER_EQUAL(2, 4, 0)
rnd,
#endif
firstchannel,
subimage,
subimagename,
@@ -123,10 +119,8 @@ static_assert(offsetof(OIIO::TextureOptBatch, twidth) % 64 == 0,
"oops unaligned wide variable");
static_assert(offsetof(OIIO::TextureOptBatch, rwidth) % 64 == 0,
"oops unaligned wide variable");
# if OIIO_VERSION_GREATER_EQUAL(2, 4, 0)
static_assert(offsetof(OIIO::TextureOptBatch, rnd) % 64 == 0,
"oops unaligned wide variable");
# endif
static_assert(sizeof(OIIO::TextureOptBatch)
== sizeof(BatchedTextureOptions<16>),
+57
View File
@@ -0,0 +1,57 @@
// Copyright Contributors to the Open Shading Language project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
#pragma once
#include <OSL/oslconfig.h>
OSL_NAMESPACE_ENTER
/// Wrapper class for holding a "device" pointer -- GPU or whatnot. It
/// provides protections so that the pointer cannot easily be accessed on the
/// host side, where presumably it would not be valid memory.
template<class T> class device_ptr {
public:
device_ptr() = default;
// Copy ctr from another device_ptr of the same type
device_ptr(const device_ptr& other) = default;
/// On device, device_ptr can construct from a pointer.
/// On host, it must be explicitly constructed -- use with caution.
#ifdef __CUDA_ARCH__
device_ptr(T* ptr) : m_ptr(ptr) {}
#else
explicit device_ptr(T* ptr) : m_ptr(ptr) {}
#endif
#ifdef __CUDA_ARCH__
/// On device, act as a pointer. None of these things are allowed on the
/// host.
T* operator->() const { return m_ptr; }
T& operator*() const { return *m_ptr; }
#endif
/// Extract the raw device-side pointer. Use with caution! On the host,
/// this will not point to valid memory.
T* d_get() const { return m_ptr; }
/// Evaluate as bool is a null pointer check.
operator bool() const noexcept { return m_ptr != nullptr; }
/// Reset the pointer to `dptr`, which must be a device-side raw pointer,
/// or null. Since this device_ptr is non-owning, any previous value is
/// simply overwritten.
void reset(T* dptr = nullptr) { m_ptr = dptr; }
private:
T* m_ptr = nullptr; // underlying pointer, initializes to null
};
OSL_NAMESPACE_EXIT
+2 -23
View File
@@ -6,10 +6,6 @@
#include <OSL/oslconfig.h>
#ifdef __CUDA_ARCH__
# include <optix.h>
#endif
// USAGE NOTES:
//
// To define a "standard" DeviceString, add a STRDECL to <OSL/strdecls.h>
@@ -19,21 +15,10 @@
OSL_NAMESPACE_ENTER
// Strings are handled differently in OptiX 6 vs OptiX 7.
//
// In OptiX 7+:
// Strings are not stored on the GPU at all. Strings are represented by
// their hash values which are computed at compile-time. Because of this,
// we have no access to either the strings' contents or their lengths.
//
// In OptiX 6:
// Strings are stored in a block of CUDA device memory. String variables hold a
// pointer to the start of the char array for each string. Each canonical string
// has a unique entry in the table, so two strings can be tested for equality by
// comparing their addresses.
//
// As a convenience, the ustring hash and the length of the string are also
// stored in the table, in the 16 bytes preceding the characters.
struct DeviceString {
#ifdef __CUDA_ARCH__
@@ -68,10 +53,7 @@ struct DeviceString {
// In OptiX 7 we can't return the string's contents. Make this a compile
// time error.
#ifndef __CUDA_ARCH__
OSL_HOSTDEVICE const char* c_str() const
{
return m_chars;
}
OSL_HOSTDEVICE const char* c_str() const { return m_chars; }
#endif
OSL_HOSTDEVICE bool operator==(const DeviceString& other) const
@@ -96,10 +78,7 @@ struct DeviceString {
return hash() != other;
}
OSL_HOSTDEVICE operator size_t() const
{
return hash();
}
OSL_HOSTDEVICE operator size_t() const { return hash(); }
#endif
};
+217
View File
@@ -0,0 +1,217 @@
// Copyright Contributors to the Open Shading Language project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
#pragma once
#include <OSL/oslconfig.h>
OSL_NAMESPACE_ENTER
// Substitute for variable argument list, which is traditionally used with a printf, with arrays
// of EncodedTypes to identify types contained in a blind payload of values.
enum class EncodedType : uint8_t {
// OSL Shaders could encode these types
kUstringHash = 0,
kInt32,
kFloat,
// OSL library functions or renderer services encode additional native types
kInt64,
kDouble,
kUInt32,
kUInt64,
kPointer,
kTypeDesc,
kCount
};
// Decode will use each EncodedType in the array to interpret the contents of the arg_values
// parameter alongwith a fmtlib specifier identified by the ustring that the format_hash represents.
// Contents of decoded_str are written over (not appended).
// Returns # of bytes read from arg_values
int
decode_message(uint64_t format_hash, int32_t arg_count,
const EncodedType* arg_types, const uint8_t* arg_values,
std::string& decoded_str);
namespace pvt {
constexpr inline uint32_t
size_of_encoded_type(EncodedType et)
{
constexpr uint32_t SizeByEncodedType[] = {
sizeof(OSL::ustringhash), sizeof(int32_t), sizeof(float),
sizeof(int64_t), sizeof(double), sizeof(uint32_t),
sizeof(uint64_t), sizeof(void*), sizeof(OSL::TypeDesc),
};
static_assert(sizeof(SizeByEncodedType) / sizeof(SizeByEncodedType[0])
== size_t(EncodedType::kCount),
"Keep array contents lined up with enum");
return SizeByEncodedType[static_cast<int>(et)];
}
template<typename T>
struct TypeEncoder; //Undefined on purpose; all types must have a specialization
template<> struct TypeEncoder<OSL::ustringhash> {
using DataType = ustringhash_pod;
static constexpr EncodedType value = EncodedType::kUstringHash;
static_assert(size_of_encoded_type(value) == sizeof(DataType),
"unexpected");
static DataType Encode(const OSL::ustringhash& val) { return val.hash(); }
};
template<> struct TypeEncoder<OSL::ustring> {
using DataType = ustringhash_pod;
static constexpr EncodedType value = EncodedType::kUstringHash;
static_assert(size_of_encoded_type(value) == sizeof(DataType),
"unexpected");
static DataType Encode(const OSL::ustring& val) { return val.hash(); }
};
template<> struct TypeEncoder<const char*> {
using DataType = ustringhash_pod;
static constexpr EncodedType value = EncodedType::kUstringHash;
static_assert(size_of_encoded_type(value) == sizeof(DataType),
"unexpected");
static DataType Encode(const char* val) { return ustring(val).hash(); }
};
template<> struct TypeEncoder<std::string> {
using DataType = ustringhash_pod;
static constexpr EncodedType value = EncodedType::kUstringHash;
static_assert(size_of_encoded_type(value) == sizeof(DataType),
"unexpected");
static DataType Encode(const std::string& val)
{
return ustring(val).hash();
}
};
template<> struct TypeEncoder<int32_t> {
using DataType = int32_t;
static constexpr EncodedType value = EncodedType::kInt32;
static_assert(size_of_encoded_type(value) == sizeof(DataType),
"unexpected");
static DataType Encode(const int32_t val) { return val; }
};
template<> struct TypeEncoder<float> {
using DataType = float;
static constexpr EncodedType value = EncodedType::kFloat;
static_assert(size_of_encoded_type(value) == sizeof(DataType),
"unexpected");
static DataType Encode(const float val) { return val; }
};
template<> struct TypeEncoder<int64_t> {
using DataType = int64_t;
static constexpr EncodedType value = EncodedType::kInt64;
static_assert(size_of_encoded_type(value) == sizeof(DataType),
"unexpected");
static DataType Encode(const int64_t val) { return val; }
};
// On macOS 10.+ ptrdiff_t is a long, but on linux this
// specialization would conflict with int64_t
#if defined(__APPLE__) && defined(__MACH__)
template<> struct TypeEncoder<ptrdiff_t> {
using DataType = int64_t;
static constexpr EncodedType value = EncodedType::kInt64;
static_assert(size_of_encoded_type(value) == sizeof(DataType),
"unexpected");
static DataType Encode(const ptrdiff_t val) { return val; }
};
#endif
template<> struct TypeEncoder<double> {
using DataType = double;
static constexpr EncodedType value = EncodedType::kDouble;
static_assert(size_of_encoded_type(value) == sizeof(DataType),
"unexpected");
static DataType Encode(const double val) { return val; }
};
template<> struct TypeEncoder<uint64_t> {
using DataType = uint64_t;
static constexpr EncodedType value = EncodedType::kUInt64;
static_assert(size_of_encoded_type(value) == sizeof(DataType),
"unexpected");
static DataType Encode(const uint64_t val) { return val; }
};
template<> struct TypeEncoder<uint32_t> {
using DataType = uint32_t;
static constexpr EncodedType value = EncodedType::kUInt32;
static_assert(size_of_encoded_type(value) == sizeof(DataType),
"unexpected");
static DataType Encode(const uint32_t val) { return val; }
};
template<typename T> struct TypeEncoder<T*> {
// fmtlib only supports const void *, all other pointers must be
// converted with a cast or helper like fmt::ptr(p)
static_assert(
(std::is_same<void*, T*>::value || std::is_same<const void*, T*>::value),
"formatting of non-void pointers is disallowed, wrap with fmt::ptr");
using DataType = const T*;
static constexpr EncodedType value = EncodedType::kPointer;
static_assert(size_of_encoded_type(value) == sizeof(DataType),
"unexpected");
static DataType Encode(const T* val) { return val; }
};
template<> struct TypeEncoder<OSL::TypeDesc> {
// To avoid warnings about non-pod types when we PackArgs
// we will encode into builtin type
using DataType = uint64_t;
static_assert(sizeof(OSL::TypeDesc) == sizeof(DataType), "unexpected");
static constexpr EncodedType value = EncodedType::kTypeDesc;
static_assert(size_of_encoded_type(value) == sizeof(DataType),
"unexpected");
static DataType Encode(const OSL::TypeDesc& val)
{
return OSL::bitcast<DataType>(val);
}
};
// Promote thinner types
template<> struct TypeEncoder<int16_t> {
using DataType = int32_t;
static constexpr EncodedType value = EncodedType::kInt32;
static_assert(size_of_encoded_type(value) == sizeof(DataType),
"unexpected");
static DataType Encode(const int16_t val) { return DataType(val); }
};
template<> struct TypeEncoder<int8_t> {
using DataType = int32_t;
static constexpr EncodedType value = EncodedType::kInt32;
static_assert(size_of_encoded_type(value) == sizeof(DataType),
"unexpected");
static DataType Encode(const int8_t val) { return DataType(val); }
};
template<> struct TypeEncoder<uint16_t> {
using DataType = uint32_t;
static constexpr EncodedType value = EncodedType::kUInt32;
static_assert(size_of_encoded_type(value) == sizeof(DataType),
"unexpected");
static DataType Encode(const uint16_t val) { return DataType(val); }
};
template<> struct TypeEncoder<uint8_t> {
using DataType = uint32_t;
static constexpr EncodedType value = EncodedType::kUInt32;
static_assert(size_of_encoded_type(value) == sizeof(DataType),
"unexpected");
static DataType Encode(const uint8_t val) { return DataType(val); }
};
} // namespace pvt
OSL_NAMESPACE_EXIT
+146
View File
@@ -0,0 +1,146 @@
// Copyright Contributors to the Open Shading Language project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
#pragma once
#include <OSL/rs_free_function.h>
// OSL library functions as well as Renderer Service free functions
// can utilize OSL::filefmt, OSL::printfmt, OSL::errorfmt, and
// OSL::warningfmt wrappers to accept variable arguments to be
// encoded into a EncodeType array and PackedArgument buffer
// that underlying render service free functions require.
// NOTE: All strings arguments to the underlying render service free
// functions must be ustringhash. To make this easier, these wrappers
// automatically convert ustring and const char * to ustringhash.
OSL_NAMESPACE_ENTER
namespace pvt {
// PackedArgs is similar to tuple but packs its data back to back
// in memory layout, which is what we need to build up payload
// to the fmt reporting system
OSL_PACK_STRUCTS_BEGIN
template<int IndexT, typename TypeT> struct alignas(1) PackedArg {
explicit PackedArg(const TypeT& a_value) : m_value(a_value) {}
TypeT m_value;
};
OSL_PACK_STRUCTS_END
template<typename IntSequenceT, typename... TypeListT> struct PackedArgsBase;
// Specialize to extract a parameter pack of the IntegerSquence
// so it can be expanded alongside the TypeListT parameter pack
OSL_PACK_STRUCTS_BEGIN
template<int... IntegerListT, typename... TypeListT>
struct alignas(1)
PackedArgsBase<std::integer_sequence<int, IntegerListT...>, TypeListT...>
: public PackedArg<IntegerListT, TypeListT>... {
explicit PackedArgsBase(const TypeListT&... a_values)
// multiple inheritance of individual components
// uniquely identified by the <Integer,Type> combo
: PackedArg<IntegerListT, TypeListT>(a_values)...
{
}
};
OSL_PACK_STRUCTS_END
template<typename... TypeListT> struct PackedArgs {
typedef std::make_integer_sequence<int, sizeof...(TypeListT)>
IndexSequenceType;
PackedArgsBase<IndexSequenceType, TypeListT...> m_components;
explicit PackedArgs(const TypeListT&... a_values)
: m_components(a_values...)
{
}
};
static_assert(sizeof(PackedArgs<int, char, int>)
== sizeof(int) + sizeof(char) + sizeof(int),
"PackedArgs<> type is not packed");
static_assert(alignof(PackedArgs<int, char, int>) == 1,
"PackedArgs<> type is not aligned to 1");
} // namespace pvt
template<typename FilenameT, typename SpecifierT, typename... ArgListT>
void
filefmt(OpaqueExecContextPtr oec, const FilenameT& filename_hash,
const SpecifierT& fmt_specification, ArgListT... args)
{
constexpr int32_t count = sizeof...(args);
constexpr OSL::EncodedType argTypes[]
= { pvt::TypeEncoder<ArgListT>::value... };
pvt::PackedArgs<typename pvt::TypeEncoder<ArgListT>::DataType...> argValues {
pvt::TypeEncoder<ArgListT>::Encode(args)...
};
rs_filefmt(oec, OSL::ustringhash { filename_hash },
OSL::ustringhash { fmt_specification }, count,
(count == 0) ? nullptr : argTypes,
static_cast<uint32_t>((count == 0) ? 0 : sizeof(argValues)),
(count == 0) ? nullptr : reinterpret_cast<uint8_t*>(&argValues));
}
template<typename SpecifierT, typename... ArgListT>
void
printfmt(OpaqueExecContextPtr oec, const SpecifierT& fmt_specification,
ArgListT... args)
{
constexpr int32_t count = sizeof...(args);
constexpr OSL::EncodedType argTypes[]
= { pvt::TypeEncoder<ArgListT>::value... };
pvt::PackedArgs<typename pvt::TypeEncoder<ArgListT>::DataType...> argValues {
pvt::TypeEncoder<ArgListT>::Encode(args)...
};
rs_printfmt(oec, OSL::ustringhash { fmt_specification }, count,
(count == 0) ? nullptr : argTypes,
static_cast<uint32_t>((count == 0) ? 0 : sizeof(argValues)),
(count == 0) ? nullptr
: reinterpret_cast<uint8_t*>(&argValues));
}
template<typename SpecifierT, typename... ArgListT>
void
errorfmt(OpaqueExecContextPtr oec, const SpecifierT& fmt_specification,
ArgListT... args)
{
constexpr int32_t count = sizeof...(args);
constexpr OSL::EncodedType argTypes[]
= { pvt::TypeEncoder<ArgListT>::value... };
pvt::PackedArgs<typename pvt::TypeEncoder<ArgListT>::DataType...> argValues {
pvt::TypeEncoder<ArgListT>::Encode(args)...
};
rs_errorfmt(oec, OSL::ustringhash { fmt_specification }, count,
(count == 0) ? nullptr : argTypes,
static_cast<uint32_t>((count == 0) ? 0 : sizeof(argValues)),
(count == 0) ? nullptr
: reinterpret_cast<uint8_t*>(&argValues));
}
template<typename SpecifierT, typename... ArgListT>
void
warningfmt(OpaqueExecContextPtr oec, const SpecifierT& fmt_specification,
ArgListT... args)
{
constexpr int32_t count = sizeof...(args);
constexpr OSL::EncodedType argTypes[]
= { pvt::TypeEncoder<ArgListT>::value... };
pvt::PackedArgs<typename pvt::TypeEncoder<ArgListT>::DataType...> argValues {
pvt::TypeEncoder<ArgListT>::Encode(args)...
};
rs_warningfmt(oec, OSL::ustringhash { fmt_specification }, count,
(count == 0) ? nullptr : argTypes,
static_cast<uint32_t>((count == 0) ? 0 : sizeof(argValues)),
(count == 0) ? nullptr
: reinterpret_cast<uint8_t*>(&argValues));
}
OSL_NAMESPACE_EXIT
+364
View File
@@ -0,0 +1,364 @@
// Copyright Contributors to the Open Shading Language project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
#pragma once
#include <list>
#ifdef __CUDACC__
# include <cuda/atomic>
#endif
#include <OSL/encodedtypes.h>
#include <OSL/oslconfig.h>
OSL_NAMESPACE_ENTER
/// Journal Buffer approach: each thread gets its own chain of pages within
/// the shared journal buffer for recording errors, warnings, etc.
/// By maintaining a separate chain per thread we can record errors (etc.) in a
/// non-blocking fashion. Shade index is recorded for use by error reporter to
/// sort messages but it is not used at present.
/// Using a Journal buffer is up to a Renderer. The Renderer use the new
/// customization points (rs_errorfmt, rs_filefmt, rs_printfmt, rs_warningfmt
/// or their virtual function equivalents) to interact with a journal::Writer
/// and journal buffer owned by its RenderState. The Renderer would of have to
/// allocate and initialized the journal buffer with the requested page size
/// and number of threads before executing a shader. After a shader is done
/// executing, the contents of the journal buffer can be transfered back to the
/// host and processed with a journal::Reader, which reports them through a
/// journal::Reporter's virtual interface. Intent is for Renderers's to use the
/// Journal buffer and provide their own overriden version of the
/// journal::Reporter. Testshade provides example usage.
/// For legacy purposes, the default virtual RendererServices will route errors
/// to ShadingSystem's OSL::ErrorHandler, but intent is for Renderer's to
/// switch over to using a Journal buffer or their own custom logging.
namespace journal {
namespace pvt {
//Per thread information for its page
struct alignas(64) PageInfo {
uint32_t pos;
uint32_t remaining;
uint32_t warning_count;
};
struct Organization //Initial bookkeeping
{
int thread_count;
uint32_t buf_size;
uint32_t page_size;
// rename free_pos bytes_used;
#ifdef __CUDACC__
using AtomicUint32 = cuda::std::atomic<std::uint32_t>;
#else
using AtomicUint32 = std::atomic<std::uint32_t>;
#endif
alignas(64)
AtomicUint32 free_pos; // cache line alignment to avoid false sharing
alignas(64) AtomicUint32
additional_bytes_required; // when the journal is full, how many more bytes would of been needed
alignas(64) AtomicUint32
exceeded_page_size; // when the a single entry exceeds the page size, we can't record it, but we can track how space it needed
uint32_t calc_end_of_page_infos() const
{
return sizeof(PageInfo) * thread_count + sizeof(Organization);
}
uint32_t calc_head_pos(int thread_index) const
{
return calc_end_of_page_infos() + (thread_index * page_size);
}
PageInfo& get_pageinfo(int thread_index)
{
return reinterpret_cast<PageInfo*>(
reinterpret_cast<uint8_t*>(this)
+ sizeof(Organization))[thread_index];
}
};
enum class Content : uint8_t {
PageTransition,
// Shader Language generated
Error,
Warning,
Print,
FilePrint
};
static_assert(sizeof(PageInfo) % 64 == 0, "PageInfo needs to be cache aligned");
} // namespace pvt
/// Call before launching shaders or after processing
/// returns: true for success,
/// false if buf_size can not accomadate at least 1 page per thread
OSLEXECPUBLIC bool
initialize_buffer(uint8_t* const buffer, uint32_t buf_size_,
uint32_t page_size_, int thread_count_);
/// Abstract base class intended for Renders to override and handle messages
/// decoded from a journal buffer
class OSLEXECPUBLIC Reporter {
//Methods will NOT be called by multiple threads (no synchronization needed)
public:
virtual ~Reporter() {}
virtual void report_error(int thread_index, int shade_index,
const OSL::string_view& message)
= 0;
virtual void report_warning(int thread_index, int shade_index,
const OSL::string_view& message)
= 0;
virtual void report_print(int thread_index, int shade_index,
const OSL::string_view& message)
= 0;
virtual void report_file_print(int thread_index, int shade_index,
const OSL::string_view& filename,
const OSL::string_view& message)
= 0;
};
/// Utility class to look for repeated errors or warnings over
/// a limited history window
class OSLEXECPUBLIC TrackRecentlyReported {
public:
TrackRecentlyReported(bool limit_errors = true,
int error_history_capacity = 32,
bool limit_warnings = true,
int warning_history_capacity = 32);
bool shouldReportError(const OSL::string_view& message);
bool shouldReportWarning(const OSL::string_view& message);
protected:
const bool m_limit_errors;
const int m_error_history_capacity;
const bool m_limit_warnings;
const int m_warning_history_capacity;
std::list<std::string> m_errseen, m_warnseen;
};
/// Concrete Reporter that utilizes a TrackRecentlyReported to filter and
/// forwards to a legacy OSL::ErrorHandler
class OSLEXECPUBLIC Report2ErrorHandler : public Reporter {
public:
Report2ErrorHandler(OSL::ErrorHandler* eh, TrackRecentlyReported& tracker);
void report_error(int thread_index, int shade_index,
const OSL::string_view& message) override;
void report_warning(int thread_index, int shade_index,
const OSL::string_view& message) override;
void report_print(int thread_index, int shade_index,
const OSL::string_view& message) override;
void report_file_print(int thread_index, int shade_index,
const OSL::string_view& filename,
const OSL::string_view& message) override;
protected:
OSL::ErrorHandler* m_eh;
TrackRecentlyReported& m_tracker;
};
/// Reader is a lightweight class meant to be constructed as a local variable
/// with an already initalized (and populated) journal buffer and a concreate
/// Reporter. Calling process will decode all of the messages in the journal
/// calling the appropriate methods on the provided Reportor.
/// NOTE: Renderer is expected to call initialize_buffer after Reader::process
/// before reusing the buffer for additional shading.
class OSLEXECPUBLIC Reader {
public:
Reader(const uint8_t* buffer_, Reporter& reporter);
void process();
private:
void process_entries_for_thread(int thread_index);
const uint8_t* const m_buffer; //Read from this?
const pvt::Organization& m_org; //
const pvt::PageInfo* m_pageinfo_by_thread_index;
Reporter& m_reporter;
};
/// Writer is a lightweight class meant to be constructed as a local variable
/// with an already initalized journal buffer and used to record error,
/// warnings, prints, or fprints into the buffer and then go out of scope.
/// Writer implementation entirely inlinable and intended for use on devices.
class OSLEXECPUBLIC Writer {
public:
Writer(void* buffer)
: m_buffer(static_cast<uint8_t*>(buffer))
, m_org(*(reinterpret_cast<pvt::Organization*>(buffer)))
, m_pageinfo_by_thread_index(reinterpret_cast<pvt::PageInfo*>(
m_buffer + sizeof(pvt::Organization)))
{
}
bool record_errorfmt(int thread_index, int shade_index,
OSL::ustringhash fmt_specification, int32_t arg_count,
const EncodedType* arg_types, uint32_t arg_values_size,
uint8_t* arg_values)
{
return write_entry(thread_index, shade_index, pvt::Content::Error,
fmt_specification, OSL::ustringhash {} /*filename*/,
arg_count, arg_types, arg_values_size, arg_values);
}
bool record_warningfmt(int max_warnings_per_thread, int thread_index,
int shade_index, OSL::ustringhash fmt_specification,
int32_t arg_count, const EncodedType* arg_types,
uint32_t arg_values_size, uint8_t* arg_values)
{
auto& info = m_pageinfo_by_thread_index[thread_index];
if (static_cast<int>(info.warning_count) >= max_warnings_per_thread) {
return false;
}
++info.warning_count;
return write_entry(thread_index, shade_index, pvt::Content::Warning,
fmt_specification, OSL::ustringhash {} /*filename*/,
arg_count, arg_types, arg_values_size, arg_values);
}
bool record_printfmt(int thread_index, int shade_index,
OSL::ustringhash fmt_specification, int32_t arg_count,
const EncodedType* arg_types, uint32_t arg_values_size,
uint8_t* arg_values)
{
return write_entry(thread_index, shade_index, pvt::Content::Print,
fmt_specification, OSL::ustringhash {} /*filename*/,
arg_count, arg_types, arg_values_size, arg_values);
}
bool record_filefmt(int thread_index, int shade_index,
OSL::ustringhash filename_hash,
OSL::ustringhash fmt_specification, int32_t arg_count,
const EncodedType* arg_types, uint32_t arg_values_size,
uint8_t* arg_values)
{
return write_entry(thread_index, shade_index, pvt::Content::FilePrint,
fmt_specification, filename_hash, arg_count,
arg_types, arg_values_size, arg_values);
}
private:
static constexpr size_t requiredForPageTransition()
{
return sizeof(pvt::Content::PageTransition) + sizeof(uint32_t);
}
bool allocatePage(int thread_index)
{
using pvt::Content;
auto& info = m_pageinfo_by_thread_index[thread_index];
OSL_ASSERT(info.remaining >= requiredForPageTransition());
// pre check if next_pos >= buf_size to prevent continuing to
// increment free_pos once its already past the end of a page
if ((m_org.free_pos.load() + m_org.page_size) >= m_org.buf_size)
return false;
uint32_t next_pos = m_org.free_pos.fetch_add(m_org.page_size);
// post check if next_pos >= buf_size because another thread could
// have bumped free_pos
if (next_pos >= m_org.buf_size)
return false;
// write page transition
uint8_t* dest_ptr = m_buffer + info.pos;
constexpr Content content = Content::PageTransition;
memcpy(dest_ptr, &content, sizeof(content));
memcpy(dest_ptr + sizeof(content), &next_pos, sizeof(next_pos));
// Don't bother update page info for the memory used by the transition
// because we are about to overwrite it.
// Update page info to point to newly allocated page
info.pos = next_pos;
info.remaining = m_org.page_size;
info.warning_count = 0;
return true;
}
bool write_entry(int thread_index, int shade_index, pvt::Content content,
OSL::ustringhash fmt_specification,
OSL::ustringhash filename, int32_t arg_count,
const EncodedType* arg_types, uint32_t arg_values_size,
uint8_t* arg_values)
{
using pvt::Content;
uint64_t fname_hash;
// calc required size for this entry
uint64_t fmt_spec_hash = fmt_specification.hash();
uint32_t required_bytes = sizeof(Content) + sizeof(int)
+ sizeof(fmt_spec_hash) + sizeof(arg_count)
+ sizeof(EncodedType) * arg_count
+ arg_values_size;
if (filename.hash()) {
fname_hash = filename.hash();
required_bytes += sizeof(fname_hash);
}
if (required_bytes > m_org.page_size) {
uint32_t exceeded = m_org.exceeded_page_size;
while (required_bytes > exceeded) {
if (m_org.exceeded_page_size.compare_exchange_weak(
exceeded, required_bytes)) {
break;
}
}
return false;
}
auto& info = m_pageinfo_by_thread_index[thread_index];
if ((info.remaining - requiredForPageTransition()) < required_bytes) {
// TODO (extra credit): get fancy spanning entry over multiple pages
if (!allocatePage(thread_index)) {
m_org.additional_bytes_required += required_bytes;
return false;
}
}
OSL_ASSERT(info.remaining >= required_bytes);
uint8_t* dest_ptr = m_buffer + info.pos;
memcpy(dest_ptr, &content, sizeof(content));
memcpy(dest_ptr + sizeof(content), &shade_index, sizeof(shade_index));
memcpy(dest_ptr + sizeof(content) + sizeof(shade_index), &fmt_spec_hash,
sizeof(fmt_spec_hash));
memcpy(dest_ptr + sizeof(content) + sizeof(shade_index)
+ sizeof(fmt_spec_hash),
&arg_count, sizeof(arg_count));
memcpy(dest_ptr + sizeof(content) + sizeof(shade_index)
+ sizeof(fmt_spec_hash) + sizeof(arg_count),
arg_types, sizeof(EncodedType) * arg_count);
memcpy(dest_ptr + sizeof(content) + sizeof(shade_index)
+ sizeof(fmt_spec_hash) + sizeof(arg_count)
+ sizeof(EncodedType) * arg_count,
arg_values, arg_values_size);
if (content == Content::FilePrint) {
uint64_t filename_hash = filename.hash();
memcpy(dest_ptr + sizeof(content) + sizeof(shade_index)
+ sizeof(fmt_spec_hash) + sizeof(arg_count)
+ sizeof(EncodedType) * arg_count + arg_values_size,
&filename_hash, sizeof(filename_hash));
}
info.remaining -= required_bytes;
info.pos += required_bytes;
return true;
}
uint8_t* m_buffer;
pvt::Organization& m_org;
pvt::PageInfo* m_pageinfo_by_thread_index;
};
} // namespace journal
OSL_NAMESPACE_EXIT
+61 -26
View File
@@ -34,6 +34,7 @@ class LLVMContext;
class Module;
class PointerType;
class StringRef;
class TargetMachine;
class Type;
class Value;
class VectorType;
@@ -62,6 +63,7 @@ enum class TargetISA {
AVX512,
AVX512_noFMA,
HOST,
NVPTX,
COUNT
};
@@ -154,15 +156,6 @@ public:
void debug_pop_inlined_function();
void debug_set_location(OIIO::ustring sourcefile, int sourceline);
/// Create a new function (that will later be populated with
/// instructions) with up to 4 args.
OSL_DEPRECATED("Use make_function flavor that takes a cspan (1.12)")
llvm::Function* make_function(const std::string& name, bool fastcall,
llvm::Type* rettype, llvm::Type* arg1 = NULL,
llvm::Type* arg2 = NULL,
llvm::Type* arg3 = NULL,
llvm::Type* arg4 = NULL);
/// Create a new function (that will later be populated with
/// instructions) with a cspan of args.
llvm::Function* make_function(const std::string& name, bool fastcall,
@@ -212,6 +205,9 @@ public:
/// target_isa() unless one of those has previously been called.
TargetISA target_isa() const { return m_target_isa; }
/// Set the TargetISA to be used during codegen.
void set_target_isa(TargetISA requestedISA) { m_target_isa = requestedISA; }
// Check support for certain CPU ISA features. These are only valid
// after detect_cpu_features() (or make_jit_execengine()) has been
// called.
@@ -272,6 +268,10 @@ public:
/// current one).
void execengine(llvm::ExecutionEngine* exec);
/// Return a pointer to the TargetMachine for NVPTX. Create the TargetMachine
/// if it has not yet been created.
llvm::TargetMachine* nvptx_target_machine();
enum class Linkage {
External, // Externally visible
LinkOnceODR, // One Definition Rule: Inline version, but allow replacement by equivalent.
@@ -536,6 +536,7 @@ public:
llvm::Type* type_int() const { return m_llvm_type_int; }
llvm::Type* type_int8() const { return m_llvm_type_int8; }
llvm::Type* type_int16() const { return m_llvm_type_int16; }
llvm::Type* type_int64() const { return m_llvm_type_int64; }
llvm::Type* type_addrint() const { return m_llvm_type_addrint; }
llvm::Type* type_bool() const { return m_llvm_type_bool; }
llvm::Type* type_char() const { return m_llvm_type_char; }
@@ -553,6 +554,8 @@ public:
llvm::PointerType* type_char_ptr() const { return m_llvm_type_char_ptr; }
llvm::PointerType* type_bool_ptr() const { return m_llvm_type_bool_ptr; }
llvm::PointerType* type_int_ptr() const { return m_llvm_type_int_ptr; }
llvm::PointerType* type_int8_ptr() const { return m_llvm_type_int8_ptr; }
llvm::PointerType* type_int64_ptr() const { return m_llvm_type_int64_ptr; }
llvm::PointerType* type_float_ptr() const { return m_llvm_type_float_ptr; }
llvm::PointerType* type_longlong_ptr() const
{
@@ -630,6 +633,9 @@ public:
const std::string& name = "",
bool is_packed = false);
// Return type of field at given index in a struct type.
llvm::Type* type_struct_field_at_index(llvm::Type* type, int index);
/// Return the llvm::Type that is a pointer to the given llvm type.
llvm::PointerType* type_ptr(llvm::Type* type);
@@ -640,6 +646,12 @@ public:
/// llvm type.
llvm::Type* type_array(llvm::Type* type, int n);
/// Return the true if the llvm::Type is an array
bool is_type_array(llvm::Type* type);
/// Return the llvm::Type of element that the array_type is made up of
llvm::Type* element_type_of(llvm::Type* array_type);
/// Return an llvm::FunctionType that describes a function with the
/// given return types, parameter types (in a cspan), and whether it
/// uses varargs conventions.
@@ -659,17 +671,29 @@ public:
/// Return the llvm::Type of the llvm value.
llvm::Type* llvm_typeof(llvm::Value* val) const;
/// Return number of bytes used to store the type
size_t llvm_sizeof(llvm::Type* type) const;
/// Return preferred byte alignment for a type
size_t llvm_alignmentof(llvm::Type* type) const;
/// Return the human-readable name of the type of the llvm value.
std::string llvm_typenameof(llvm::Value* val) const;
/// Return an llvm::Constant holding the given floating point constant.
llvm::Constant* constant(float f);
/// Return an llvm::Constant holding the given integer constant.
llvm::Constant* constant(int i);
/// Return an llvm::Constant holding the given floating point constant.
llvm::Constant* constant64(double f);
/// Return an llvm::Constant holding the given integer constant.
llvm::Constant* constant8(int i);
llvm::Constant* constant(int32_t i);
llvm::Constant* constant(uint32_t i);
/// Return an llvm::Constant holding the given integer constant.
llvm::Constant* constant8(int8_t i);
llvm::Constant* constant8(uint8_t i);
llvm::Constant* constant16(int16_t i);
llvm::Constant* constant16(uint16_t i);
llvm::Constant* constant64(uint64_t i);
llvm::Constant* constant128(uint64_t i);
@@ -762,6 +786,10 @@ public:
/// return the llvm::Value of the new pointer.
llvm::Value* int_to_ptr_cast(llvm::Value* val);
/// Cast the pointer specified by ptr to an int64, return the llvm::Value
/// of the new value.
llvm::Value* ptr_to_int64_cast(llvm::Value* ptr);
/// Cast the pointer variable specified by val to a pointer of type
/// void* return the llvm::Value of the new pointer.
llvm::Value* void_ptr(llvm::Value* val, const std::string& llname = {});
@@ -874,10 +902,9 @@ public:
/// type is the type of the thing being pointed to.
llvm::Value* op_load(llvm::Type* type, llvm::Value* ptr,
const std::string& llname = {});
// Blind pointer version that's deprecated as of LLVM13:
llvm::Value* op_load(llvm::Value* ptr, const std::string& llname = {});
llvm::Value* op_gather(llvm::Value* ptr, llvm::Value* index);
llvm::Value* op_gather(llvm::Type* src_type, llvm::Value* src_ptr,
llvm::Value* wide_index);
/// Store to a dereferenced pointer
/// respecting the current mask & masking_enabled flag: *ptr = val
@@ -894,8 +921,8 @@ public:
/// converting it to the native mask type for storage: *ptr = llvm_mask_to_native(val);
void op_store_mask(llvm::Value* llvm_mask, llvm::Value* native_mask_ptr);
void op_scatter(llvm::Value* wide_val, llvm::Value* ptr,
llvm::Value* wide_index);
void op_scatter(llvm::Value* wide_val, llvm::Type* src_type,
llvm::Value* src_ptr, llvm::Value* wide_index);
// N.B. "GEP" -- GetElementPointer -- is a particular LLVM-ism that is
// the means for retrieving elements from some kind of aggregate: the
@@ -908,17 +935,11 @@ public:
/// we're retrieving.
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, llvm::Value* elem,
const std::string& llname = {});
// Blind pointer version that's deprecated as of LLVM13:
llvm::Value* GEP(llvm::Value* ptr, llvm::Value* elem,
const std::string& llname = {});
/// Generate a GEP (get element pointer) with an integer element
/// offset. `type` is the type of the data we're retrieving.
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, int elem,
const std::string& llname = {});
// Blind pointer version that's deprecated as of LLVM13:
llvm::Value* GEP(llvm::Value* ptr, int elem,
const std::string& llname = {});
/// Generate a GEP (get element pointer) with two integer element
/// offsets. This is just a special (and common) case of GEP where
@@ -927,9 +948,14 @@ public:
/// retrieving.
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, int elem1, int elem2,
const std::string& llname = {});
// Blind pointer version that's deprecated as of LLVM13:
llvm::Value* GEP(llvm::Value* ptr, int elem1, int elem2,
const std::string& llname = {});
/// Generate a GEP (get element pointer) with three integer element
/// offsets. This is just a special (and common) case of GEP where
/// we have a 3-level hierarchy and we have fixed element indices
/// that are known at compile time. `type` is the type of the data we're
/// retrieving.
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, int elem1, int elem2,
int elem3, const std::string& llname = {});
// Arithmetic ops. It auto-detects the type (int vs float).
// ...
@@ -1018,6 +1044,7 @@ public:
private:
class MemoryManager;
class IRBuilder;
struct NewPassManager;
void SetupLLVM();
IRBuilder& builder();
@@ -1035,8 +1062,10 @@ private:
llvm::Function* m_current_function;
llvm::legacy::PassManager* m_llvm_module_passes;
llvm::legacy::FunctionPassManager* m_llvm_func_passes;
NewPassManager* m_new_pass_manager;
llvm::ExecutionEngine* m_llvm_exec;
TargetISA m_target_isa = TargetISA::UNKNOWN;
llvm::TargetMachine* m_nvptx_target_machine;
std::vector<llvm::BasicBlock*> m_return_block; // stack for func call
std::vector<llvm::BasicBlock*> m_loop_after_block; // stack for break
@@ -1050,6 +1079,7 @@ private:
llvm::Type* m_llvm_type_int;
llvm::Type* m_llvm_type_int8;
llvm::Type* m_llvm_type_int16;
llvm::Type* m_llvm_type_int64;
llvm::Type* m_llvm_type_addrint;
llvm::Type* m_llvm_type_bool;
llvm::Type* m_llvm_type_char;
@@ -1062,6 +1092,8 @@ private:
llvm::PointerType* m_llvm_type_char_ptr;
llvm::PointerType* m_llvm_type_bool_ptr;
llvm::PointerType* m_llvm_type_int_ptr;
llvm::PointerType* m_llvm_type_int8_ptr;
llvm::PointerType* m_llvm_type_int64_ptr;
llvm::PointerType* m_llvm_type_float_ptr;
llvm::PointerType* m_llvm_type_longlong_ptr;
llvm::PointerType* m_llvm_type_triple_ptr;
@@ -1194,6 +1226,9 @@ private:
llvm::Value* half_vec_2);
llvm::Value* op_combine_4x_vectors(llvm::Value* half_vec_1,
llvm::Value* half_vec_2);
void setup_legacy_optimization_passes(int optlevel, bool target_host);
void setup_new_optimization_passes(int optlevel, bool target_host);
};
+9 -36
View File
@@ -171,22 +171,13 @@ public:
}
OSL_FORCEINLINE ValueType value() const
{
return m_value;
}
OSL_FORCEINLINE ValueType value() const { return m_value; }
// count number of active bits
OSL_FORCEINLINE int count() const
{
return OSL::popcount(m_value);
}
OSL_FORCEINLINE int count() const { return OSL::popcount(m_value); }
// NOTE: undefined result if no bits are on
OSL_FORCEINLINE int first_on() const
{
return OSL::countr_zero(m_value);
}
OSL_FORCEINLINE int first_on() const { return OSL::countr_zero(m_value); }
OSL_FORCEINLINE Mask invert() const
{
@@ -239,10 +230,7 @@ public:
return (m_value != static_cast<ValueType>(0));
}
OSL_FORCEINLINE bool any_off() const
{
return (m_value < valid_bits);
}
OSL_FORCEINLINE bool any_off() const { return (m_value < valid_bits); }
OSL_FORCEINLINE bool any_off(const Mask& mask) const
{
@@ -257,39 +245,27 @@ public:
// So really only set_on or set_off is required
// Choose to not provide a generic set(int lane, bool flag)
OSL_FORCEINLINE void set_on(int lane)
{
m_value |= (1 << lane);
}
OSL_FORCEINLINE void set_on(int lane) { m_value |= (1 << lane); }
OSL_FORCEINLINE void set_on_if(int lane, bool cond)
{
m_value |= (cond << lane);
}
OSL_FORCEINLINE void set_all_on()
{
m_value = valid_bits;
}
OSL_FORCEINLINE void set_all_on() { m_value = valid_bits; }
OSL_FORCEINLINE void set_count_on(int count)
{
m_value = valid_bits >> (width - count);
}
OSL_FORCEINLINE void set_off(int lane)
{
m_value &= (~(1 << lane));
}
OSL_FORCEINLINE void set_off(int lane) { m_value &= (~(1 << lane)); }
OSL_FORCEINLINE void set_off_if(int lane, bool cond)
{
m_value &= (~(cond << lane));
}
OSL_FORCEINLINE void set_all_off()
{
m_value = static_cast<ValueType>(0);
}
OSL_FORCEINLINE void set_all_off() { m_value = static_cast<ValueType>(0); }
OSL_FORCEINLINE bool operator==(const Mask& other) const
{
@@ -323,10 +299,7 @@ public:
return Mask(m_value | other.m_value);
}
OSL_FORCEINLINE Mask operator~() const
{
return invert();
}
OSL_FORCEINLINE Mask operator~() const { return invert(); }
template<int MinOccupancyT, int MaxOccupancyT = width, typename FunctorT>
+2 -8
View File
@@ -109,14 +109,8 @@ OSL_ALIGNAS(16) ClosureComponent : public ClosureColor
Vec3 w; ///< Weight of this component
/// Handy method for getting the parameter memory as a void*.
OSL_HOSTDEVICE void* data()
{
return (char*)(this + 1);
}
OSL_HOSTDEVICE const void* data() const
{
return (const char*)(this + 1);
}
OSL_HOSTDEVICE void* data() { return (char*)(this + 1); }
OSL_HOSTDEVICE const void* data() const { return (const char*)(this + 1); }
/// Handy methods for extracting the underlying parameters as a struct
template<typename T> OSL_HOSTDEVICE const T* as() const
+172 -4
View File
@@ -4,6 +4,11 @@
#pragma once
#cmakedefine01 OSL_USE_OPTIX
#cmakedefine01 OSL_BUILD_BATCHED
#define OSL_USE_BATCHED OSL_BUILD_BATCHED
#include <OSL/export.h>
#include <OSL/oslversion.h>
#include <OSL/platform.h>
@@ -62,8 +67,6 @@
OSL_NAMESPACE_ENTER
#define OSL_USE_BATCHED @BUILD_BATCHED@
/// Various compile-time defaults are defined here that could, in
/// principle, be redefined if you are using OSL in some particular
/// renderer that wanted things a different way.
@@ -121,6 +124,7 @@ using OIIO::TypeInt;
using OIIO::TypeFloat2;
using OIIO::TypeVector2;
using OIIO::TypeVector4;
using OIIO::TypeUInt64;
using OIIO::Strutil::print;
@@ -131,6 +135,149 @@ fmtformat(const Str& fmt, Args&&... args)
return OIIO::Strutil::fmt::format(fmt, std::forward<Args>(args)...);
}
// TODO: notice the fmt argument is not templatised, this is because
// no implicit conversion exists betwen OSL::string_view and ::fmt::string_view
// so we choose to only accept OSL::string_view and explicitly convert to ::fmt::string_view
// OIIO should fix this if possible.
template<typename OutIt, typename... Args>
OSL_NODISCARD inline auto
fmtformat_to_n(OutIt &out, size_t n, const string_view& fmt, Args&&... args)
{
// DOES NOT EXIST AS PUBLIC API
//return OIIO::Strutil::fmt::format_to_n(out, n, fmt, std::forward<Args>(args)...);
// So call directly into underlying fmt library OIIO is using
// TODO: Add format_to_n as a public API in OIIO
return ::fmt::format_to_n(out, n, ::fmt::string_view{fmt.begin(), fmt.length()}, std::forward<Args>(args)...);
}
/// OSL_USTRINGREP_IS_HASH will be 1 if the build-time option was enabled to
/// make the ustringrep be a ustringhash, rather than a ustring directly.
#cmakedefine01 OSL_USTRINGREP_IS_HASH
#if OSL_USTRINGREP_IS_HASH
/// ustringrep is the class we use to represent strings in the shader.
using ustringrep = ustringhash;
#else
/// ustringrep is the class we use to represent strings in the shader.
using ustringrep = ustring;
#endif
/// ustringhash_pod is the type we use to pass hash data in llvm function calls.
using ustringhash_pod = size_t;
#if OSL_USTRINGREP_IS_HASH
/// ustring_pod is the type we use to pass string data in llvm function calls.
using ustring_pod = ustringhash_pod;
#else
/// ustring_pod is the type we use to pass string data in llvm function calls.
using ustring_pod = const char*;
#endif
/// Convenience function to convert to a ustring.
inline ustring
ustring_from(ustringhash h)
{
return ustring::from_hash(h.hash());
}
/// Convenience function to convert to a ustring.
inline ustring
ustring_from(ustring u)
{
return u;
}
/// Convenience function to convert to a ustring.
inline ustring
ustring_from(string_view s)
{
return ustring(s);
}
/// Convenience function to convert to a ustringhash.
inline ustringhash
ustringhash_from(ustringhash u)
{
return u;
}
/// Convenience function to convert USTRINGHASH_POD to a ustringhash.
inline ustringhash
ustringhash_from(ustringhash_pod u)
{
#if OIIO_VERSION_GREATER_EQUAL(2, 4, 10)
return ustringhash{u};
#else
// No constructor taking the pod type existed previously
// so bitcast it.
return OSL::bitcast<ustringhash>(u);
#endif
}
/// Convenience function to convert to a ustringhash.
inline ustringhash
ustringhash_from(ustring u)
{
ustringhash ret;
// Not legal to call uhash on an empty ustring
if(!u.empty())
ret = u.uhash();
return ret;
}
/// Convenience function to convert to a ustringrep.
inline ustringrep
ustringrep_from(ustringhash h)
{
#if OSL_USTRINGREP_IS_HASH
return h;
#else
return ustring::from_hash(h.hash());
#endif
}
/// Convenience function to convert to a ustringrep.
inline ustringrep
ustringrep_from(ustring u)
{
#if OSL_USTRINGREP_IS_HASH
return u.hash();
#else
return u;
#endif
}
/// Convenience function to convert to a ustringrep.
inline ustringrep
ustringrep_from(string_view s)
{
ustring u(s);
#if OSL_USTRINGREP_IS_HASH
return u.hash();
#else
return u;
#endif
}
using TypeDesc_pod = int64_t;
static_assert(sizeof(TypeDesc_pod) == sizeof(TypeDesc),
"TypeDesc size differs from its POD counterpart");
/// Convenience function to convert to a TypeDesc.
inline TypeDesc
TypeDesc_from(TypeDesc_pod type)
{
return OSL::bitcast<OSL::TypeDesc>(type);
}
// N.B. SymArena is not really "configuration", but we cram it here for
@@ -143,6 +290,7 @@ enum class SymArena {
Heap, // Belongs to context heap
Outputs, // Belongs to output arena
UserData, // UserData arena
Interactive, // Interactively edited variables
// ShaderGlobals, // RESERVED
};
@@ -229,7 +377,8 @@ OSL_NAMESPACE_EXIT
namespace std { // not necessary in C++17, then we can just say std::hash
#ifndef OIIO_USTRING_HAS_STDHASH
// Not a new enough OIIO to define std::hash<ustring>, so we'll do it
// Not a new enough OIIO to define std::hash<ustring>, so we'll do it.
// This can be removed once OIIO minimum is 2.4.5+ or >=2.5.0.1
template<> struct hash<OSL::ustring> {
std::size_t operator()(OSL::ustring u) const noexcept { return u.hash(); }
};
@@ -243,7 +392,8 @@ template<> struct hash<OSL::ustringhash> {
};
#endif
// Not necessary once minimum OIIO defines operator< for ustringhash
// Not necessary once minimum OIIO defines operator< for ustringhash.
// This can be removed once OIIO minimum is 2.4.5+ or >=2.5.0.1
template<> struct less<OSL::ustringhash> {
OSL_HOSTDEVICE constexpr bool operator()(OSL::ustringhash u,
OSL::ustringhash v) const noexcept
@@ -252,3 +402,21 @@ template<> struct less<OSL::ustringhash> {
}
};
} // namespace std
#ifndef OIIO_HAS_USTRINGHASH_FORMATTER
// OIIO is too old to have fmt custom formatter for ustringhash.
// This can be removed once OIIO minimum is 2.4.5+ or >=2.5.0.1
FMT_BEGIN_NAMESPACE
template<> struct formatter<OIIO::ustringhash> : formatter<fmt::string_view, char> {
template<typename FormatContext>
auto format(const OIIO::ustringhash& h, FormatContext& ctx)
-> decltype(ctx.out()) const
{
OIIO::ustring u(h);
return formatter<fmt::string_view, char>::format({ u.data(), u.size() },
ctx);
}
};
FMT_END_NAMESPACE
#endif
+176 -31
View File
@@ -51,7 +51,8 @@ class ShadingSystemImpl;
}
#ifdef __CUDA_ARCH__
# define STRING_PARAMS(x) UStringHash::Hash(__OSL_STRINGIFY(x))
# define STRING_PARAMS(x) \
UStringHash::HashConstEval<UStringHash::Hash(__OSL_STRINGIFY(x))>
#else
# define STRING_PARAMS(x) StringParams::x
#endif
@@ -111,6 +112,67 @@ public:
/// Parameter property hint bitflag values. The enum values must be powers of
/// two so they can be combined with bitwise operators.
enum class ParamHints : uint32_t {
/// `none`: No special properties
none = 0,
/// `interpolated`: This parameter may be an interpolated "user data" or
/// "geometric primitive" variable, and so may take on different values at
/// different points on the surface or on different objects that share the
/// same material. Any optimization of the shader should take this into
/// account.
interpolated = 1,
/// `interactive`: Parameter may have its value interactively modified by
/// subsequent ReParameter calls. Any optimization of the shader should
/// take this into account.
interactive = 2
};
inline constexpr ParamHints
operator|(ParamHints a, ParamHints b)
{
return static_cast<ParamHints>(static_cast<int>(a) | static_cast<int>(b));
}
inline constexpr ParamHints
operator&(ParamHints a, ParamHints b)
{
return static_cast<ParamHints>(static_cast<int>(a) & static_cast<int>(b));
}
inline ParamHints&
operator|=(ParamHints& a, ParamHints b)
{
a = a | b;
return a;
}
inline ParamHints&
operator&=(ParamHints& a, ParamHints b)
{
a = a & b;
return a;
}
inline constexpr ParamHints
operator~(ParamHints a)
{
return static_cast<ParamHints>(~static_cast<int>(a));
}
inline ParamHints&
set(ParamHints& a, ParamHints b, bool on = true)
{
if (on)
a |= b;
else
a &= ~b;
return a;
}
class OSLEXECPUBLIC ShadingSystem {
public:
ShadingSystem(RendererServices* renderer = NULL,
@@ -173,7 +235,7 @@ public:
/// int lazyerror Run layers lazily even if they have error
/// ops after optimization (1).
/// int lazy_userdata Retrieve userdata lazily (0).
/// int userdata_isconnected Should lockgeom=0 params (that may
/// int userdata_isconnected Should interpolated=1 params (that may
/// receive userdata) return true from
/// isconnected()? (0)
/// int greedyjit Optimize and compile all shaders up front,
@@ -200,11 +262,16 @@ public:
/// that don't specify it (1). Lockgeom
/// means a param CANNOT be overridden by
/// interpolated geometric parameters.
/// This option is slated for deprecation.
/// int countlayerexecs Add extra code to count total layers run.
/// int allow_shader_replacement Allow shader to be specified more than
/// once, replacing former definition.
/// string archive_groupname Name of a group to pickle and archive.
/// string archive_filename Name of file to save the group archive.
/// int max_optix_groupdata_alloc Maximum stack size for an OSL-managed
/// groupdata buffer when targeting OptiX (0).
/// OSL expects a pointer to a buffer when
/// requirements exceed max allocation.
/// 3. Attributes that that are intended for developers debugging
/// liboslexec itself:
/// These attributes may be helpful for liboslexec developers or
@@ -219,7 +286,7 @@ public:
/// opt_peephole, opt_coalesce_temps, opt_assign, opt_mix
/// opt_merge_instances, opt_merge_instance_with_userdata,
/// opt_fold_getattribute, opt_middleman, opt_texture_handle
/// opt_seed_bblock_aliases
/// opt_seed_bblock_aliases, opt_groupdata
/// int opt_passes Number of optimization passes per layer (10)
/// int llvm_optimize Which of several LLVM optimize strategies (1)
/// int llvm_debug Set LLVM extra debug level (0)
@@ -427,12 +494,15 @@ public:
/// ptr attributes_needed Retrieves a pointer to the ustring array
/// containing the names of the needed attributes.
/// Note that if the same attribute
/// is requested in multiple scopes, it will
/// is requested in multiple scopes, or with
/// multiple different types, it will
/// appear in the array multiple times - once for
/// each scope in which is is queried.
/// each scope/type in which is is queried.
/// ptr attribute_scopes Retrieves a pointer to a ustring array containing
/// the scopes associated with each attribute query
/// in the attributes_needed array.
/// ptr attribute_types Retrieves a pointer to the array of
/// TypeDesc describing the attributes.
/// int unknown_attributes_needed Nonzero if additional attributes may be
/// needed, whose names will not be known
/// until the shader actually runs.
@@ -443,6 +513,15 @@ public:
/// string entry_layers[] List of entry point layers.
/// string pickle Retrieves a serialized representation
/// of the shader group declaration.
/// int llvm_groupdata_size Size of the GroupData struct.
/// ptr interactive_params Pointer to the memory block containing
/// host-side interactive parameter values
/// for this shader group.
/// ptr device_interactive_params
/// Pointer to the memory block containing
/// device-side interactive parameter values
/// for this shader group.
///
/// Note: the attributes referred to as "string" are actually on the app
/// side as ustring or const char* (they have the same data layout), NOT
/// std::string!
@@ -530,15 +609,50 @@ public:
bool ShaderGroupEnd(ShaderGroup& group);
/// Set a parameter of the next shader that will be added to the group,
/// optionally setting the 'lockgeom' metadata for that parameter
/// (despite how it may have been set in the shader). If lockgeom is
/// false, it means that this parameter should NOT be considered locked
/// against changes by the geometry, and therefore the shader should not
/// optimize assuming that the instance value (the 'val' specified by
/// this call) is a constant.
/// optionally setting or overriding properties with the `hints` argument.
/// Individual `hints` bits are defined and documented by the ParamHints
/// enum class.
bool Parameter(ShaderGroup& group, string_view name, TypeDesc t,
const void* val, bool lockgeom = true);
const void* val, ParamHints hints = ParamHints::none);
/// DEPRECATED(1.13) Parameter() call: instead of a full ParamHints
/// argument, there is just a bool `lockgeom` that default to true, and
/// when set to false is the same thing as setting
/// `ParamHints::interpolated`.
bool Parameter(ShaderGroup& group, string_view name, TypeDesc t,
const void* val, bool lockgeom)
{
return Parameter(group, name, t, val,
lockgeom ? ParamHints::none
: ParamHints::interpolated);
}
// Shortcuts for param passing a single int, float, or string.
bool Parameter(ShaderGroup& group, string_view name, int val,
ParamHints hints = ParamHints::none)
{
return Parameter(group, name, TypeDesc::INT, &val, hints);
}
bool Parameter(ShaderGroup& group, string_view name, float val,
ParamHints hints = ParamHints::none)
{
return Parameter(group, name, TypeDesc::FLOAT, &val, hints);
}
bool Parameter(ShaderGroup& group, string_view name, const std::string& val,
ParamHints hints = ParamHints::none)
{
const char* s = val.c_str();
return Parameter(group, name, TypeDesc::STRING, &s, hints);
}
bool Parameter(ShaderGroup& group, string_view name, ustring val,
ParamHints hints = ParamHints::none)
{
return Parameter(group, name, TypeDesc::STRING, (const char**)&val,
hints);
}
// DEPRECATED(1.13): use the version above that takes ParamHints.
// This is the old version that takes `bool lockgeom`.
bool Parameter(ShaderGroup& group, string_view name, int val,
bool lockgeom = true)
{
@@ -589,10 +703,8 @@ public:
/// Replace a parameter value in a previously-declared shader group.
/// This is meant to called after the ShaderGroupBegin/End, but will
/// fail if the shader has already been irrevocably optimized/compiled,
/// unless the particular parameter is marked as lockgeom=0 (which
/// indicates that it's a parameter that may be overridden by the
/// geometric primitive). This call gives you a way of changing the
/// instance value, even if it's not a geometric override.
/// unless the particular parameter is marked as either interpolated=1
/// or interactive=1.
bool ReParameter(ShaderGroup& group, string_view layername,
string_view paramname, TypeDesc type, const void* val);
// Shortcuts for param passing a single int, float, or string.
@@ -628,13 +740,22 @@ public:
// above that take an explicit `ShaderGroup&`, which are thread-safe
// and re-entrant.
bool Parameter(string_view name, TypeDesc t, const void* val,
bool lockgeom = true);
ParamHints hints = ParamHints::none);
bool Shader(string_view shaderusage, string_view shadername,
string_view layername);
bool ConnectShaders(string_view srclayer, string_view srcparam,
string_view dstlayer, string_view dstparam);
bool ShaderGroupEnd(void);
// DEPRECATED(1.13): use the version above that takes ParamHints.
// This is the old version that takes `bool lockgeom`.
bool Parameter(string_view name, TypeDesc t, const void* val, bool lockgeom)
{
return Parameter(name, t, val,
lockgeom ? ParamHints::none
: ParamHints::interpolated);
}
/// Create a per-thread data needed for shader execution. It's very
/// important for the app to never use a PerThreadInfo from more than
/// one thread (and probably a good idea allocate only one PerThreadInfo
@@ -668,9 +789,10 @@ public:
/// execute_layer of the last (presumably group entry) layer, and
/// execute_cleanup. If run==false, just do the binding and setup, don't
/// actually run the shader.
bool execute(ShadingContext& ctx, ShaderGroup& group, int shadeindex,
ShaderGlobals& globals, void* userdata_base_ptr,
void* output_base_ptr, bool run = true);
bool execute(ShadingContext& ctx, ShaderGroup& group, int thread_index,
int shadeindex, ShaderGlobals& globals,
void* userdata_base_ptr, void* output_base_ptr,
bool run = true);
/// Future execute signature that will be range based. Shader globals will be
/// obtained from renderer services.
@@ -685,7 +807,7 @@ public:
bool execute(ShadingContext& ctx, ShaderGroup& group,
ShaderGlobals& globals, bool run = true)
{
return execute(ctx, group, 0, globals, nullptr, nullptr, run);
return execute(ctx, group, 0, 0, globals, nullptr, nullptr, run);
}
// DEPRECATED(2.0): ctx pointer
@@ -703,14 +825,15 @@ public:
/// preparation, but don't actually run the shader. Return true if the
/// shader executed, false if it did not (including if the shader itself
/// was empty).
bool execute_init(ShadingContext& ctx, ShaderGroup& group, int shadeindex,
ShaderGlobals& globals, void* userdata_base_ptr,
void* output_base_ptr, bool run = true);
bool execute_init(ShadingContext& ctx, ShaderGroup& group, int threadindex,
int shadeindex, ShaderGlobals& globals,
void* userdata_base_ptr, void* output_base_ptr,
bool run = true);
// DEPRECATED(2.0): no shadeindex or base pointers
bool execute_init(ShadingContext& ctx, ShaderGroup& group,
ShaderGlobals& globals, bool run = true)
{
return execute_init(ctx, group, 0, globals, nullptr, nullptr, run);
return execute_init(ctx, group, 0, 0, globals, nullptr, nullptr, run);
}
/// Execute the layer whose layernumber is specified, in this context.
@@ -718,16 +841,16 @@ public:
/// run==true, and that the call to execute_init() returned true. (One
/// reason why it might have returned false is if the shader group
/// turned out, after optimization, to do nothing.)
bool execute_layer(ShadingContext& ctx, int shadeindex,
bool execute_layer(ShadingContext& ctx, int threadindex, int shadeindex,
ShaderGlobals& globals, void* userdata_base_ptr,
void* output_base_ptr, int layernumber);
/// Execute the layer by name.
bool execute_layer(ShadingContext& ctx, int shadeindex,
bool execute_layer(ShadingContext& ctx, int threadindex, int shadeindex,
ShaderGlobals& globals, void* userdata_base_ptr,
void* output_base_ptr, ustring layername);
/// Execute the layer that has the given ShaderSymbol as an output.
/// (The symbol is one returned by find_symbol()).
bool execute_layer(ShadingContext& ctx, int shadeindex,
bool execute_layer(ShadingContext& ctx, int threadindex, int shadeindex,
ShaderGlobals& globals, void* userdata_base_ptr,
void* output_base_ptr, const ShaderSymbol* symbol);
@@ -735,17 +858,17 @@ public:
bool execute_layer(ShadingContext& ctx, ShaderGlobals& globals,
int layernumber)
{
return execute_layer(ctx, 0, globals, nullptr, nullptr, layernumber);
return execute_layer(ctx, 0, 0, globals, nullptr, nullptr, layernumber);
}
bool execute_layer(ShadingContext& ctx, ShaderGlobals& globals,
ustring layername)
{
return execute_layer(ctx, 0, globals, nullptr, nullptr, layername);
return execute_layer(ctx, 0, 0, globals, nullptr, nullptr, layername);
}
bool execute_layer(ShadingContext& ctx, ShaderGlobals& globals,
const ShaderSymbol* symbol)
{
return execute_layer(ctx, 0, globals, nullptr, nullptr, symbol);
return execute_layer(ctx, 0, 0, globals, nullptr, nullptr, symbol);
}
/// Signify that the context is done with the current execution of the
@@ -911,6 +1034,19 @@ public:
void add_symlocs(cspan<SymLocationDesc> symlocs);
void add_symlocs(ShaderGroup* group, cspan<SymLocationDesc> symlocs);
// Find the SymLocationDesc for this named param, returning its pointer
// or nullptr if that name is not found.
const SymLocationDesc* find_symloc(ustring name) const;
const SymLocationDesc* find_symloc(const ShaderGroup* group,
ustring name) const;
// Find the SymLocationDesc for this named param but only if it matches
// the arena type, returning its pointer or nullptr if that name is not
// found.
const SymLocationDesc* find_symloc(ustring name, SymArena arena) const;
const SymLocationDesc* find_symloc(const ShaderGroup* group, ustring name,
SymArena arena) const;
/// Ensure that the group has been optimized and optionally JITed. The ctx pointer
/// supplies a ShadingContext to use.
void optimize_group(ShaderGroup* group, ShadingContext* ctx,
@@ -976,6 +1112,15 @@ public:
static bool convert_value(void* dst, TypeDesc dsttype, const void* src,
TypeDesc srctype);
/// Tell the ShadingSystem if there are functions that should or should not
/// be inlined during LLVM optimization. Functions that are not registered
/// will not receive any special treatment, and may or may not be inlined.
void register_inline_function(ustring name);
void unregister_inline_function(ustring name);
void register_noinline_function(ustring name);
void unregister_noinline_function(ustring name);
private:
pvt::ShadingSystemImpl* m_impl;
};
+292 -297
View File
File diff suppressed because it is too large Load Diff
+84 -4
View File
@@ -18,10 +18,14 @@
#pragma once
#include <cstring>
#include <memory>
#include <OSL/oslversion.h>
#if defined(__x86_64__) && !defined(__CUDA_ARCH__)
# include <x86intrin.h>
#endif
/////////////////////////////////////////////////////////////////////////
// Detect which compiler and version we're using
@@ -202,9 +206,14 @@
# define OSL_CLANG_PRAGMA(UnQuotedPragma)
# endif
# if defined(__INTEL_COMPILER)
# define OSL_INTEL_PRAGMA(UnQuotedPragma) OSL_PRAGMA(UnQuotedPragma)
# define OSL_INTEL_CLASSIC_PRAGMA(UnQuotedPragma) OSL_PRAGMA(UnQuotedPragma)
# else
# define OSL_INTEL_PRAGMA(UnQuotedPragma)
# define OSL_INTEL_CLASSIC_PRAGMA(UnQuotedPragma)
# endif
# if defined(__INTEL_LLVM_COMPILER)
# define OSL_INTEL_LLVM_PRAGMA(UnQuotedPragma) OSL_PRAGMA(UnQuotedPragma)
# else
# define OSL_INTEL_LLVM_PRAGMA(UnQuotedPragma)
# endif
# define OSL_MSVS_PRAGMA(UnQuotedPragma)
#elif defined(_MSC_VER)
@@ -214,7 +223,8 @@
# define OSL_PRAGMA_VISIBILITY_POP /* N/A on MSVS */
# define OSL_GCC_PRAGMA(UnQuotedPragma)
# define OSL_CLANG_PRAGMA(UnQuotedPragma)
# define OSL_INTEL_PRAGMA(UnQuotedPragma)
# define OSL_INTEL_CLASSIC_PRAGMA(UnQuotedPragma)
# define OSL_INTEL_LLVM_PRAGMA(UnQuotedPragma)
# define OSL_MSVS_PRAGMA(UnQuotedPragma) OSL_PRAGMA(UnQuotedPragma)
#else
# define OSL_PRAGMA_WARNING_PUSH
@@ -223,10 +233,14 @@
# define OSL_PRAGMA_VISIBILITY_POP
# define OSL_GCC_PRAGMA(UnQuotedPragma)
# define OSL_CLANG_PRAGMA(UnQuotedPragma)
# define OSL_INTEL_PRAGMA(UnQuotedPragma)
# define OSL_INTEL_CLASSIC_PRAGMA(UnQuotedPragma)
# define OSL_INTEL_LLVM_PRAGMA(UnQuotedPragma)
# define OSL_MSVS_PRAGMA(UnQuotedPragma)
#endif
// A pragma that applies to both icc and icx
#define OSL_INTEL_PRAGMA(UnQuotedPragma) OSL_INTEL_CLASSIC_PRAGMA(UnQuotedPragma) OSL_INTEL_LLVM_PRAGMA(UnQuotedPragma)
#ifdef __clang__
#define OSL_CLANG_ATTRIBUTE(value) __attribute__((value))
#else
@@ -499,6 +513,72 @@
OSL_NAMESPACE_ENTER
/// Standards-compliant bit cast of two equally sized types. This is used
/// equivalently to C++20 std::bit_cast, but it works prior to C++20 and
/// it has the right decorators to work with Cuda.
/// @version 1.13.2
template <typename To, typename From>
OSL_FORCEINLINE OSL_HOSTDEVICE To bitcast(const From& src) noexcept {
// NOTE: this is the only standards compliant way of doing this type of casting,
// luckily the compilers we care about know how to optimize away this idiom.
static_assert(sizeof(From) == sizeof(To),
"bit_cast must be between objects of the same size");
To dst;
memcpy((void*)&dst, &src, sizeof(From));
return dst;
}
#if defined(__x86_64__) && !defined(__CUDA_ARCH__) && \
(defined(__INTEL_COMPILER) || defined(__INTEL_LLVM_COMPILER) \
|| OSL_CLANG_VERSION >= 100000 || OSL_APPLE_CLANG_VERSION >= 130000)
// On x86/x86_64 for certain compilers we can use Intel CPU intrinsics for
// some common bitcast cases that might be even more understandable to the
// compiler and generate better code without its getting confused about the
// memcpy in the general case. We're a bit conservative with the compiler
// version checks here, it may be that some earlier versions support these
// intrinsics.
template<> OSL_FORCEINLINE uint32_t bitcast<uint32_t, float>(const float& val) noexcept {
return static_cast<uint32_t>(_castf32_u32(val));
}
template<> OSL_FORCEINLINE int32_t bitcast<int32_t, float>(const float& val) noexcept {
return static_cast<int32_t>(_castf32_u32(val));
}
template<> OSL_FORCEINLINE float bitcast<float, uint32_t>(const uint32_t& val) noexcept {
return _castu32_f32(val);
}
template<> OSL_FORCEINLINE float bitcast<float, int32_t>(const int32_t& val) noexcept {
return _castu32_f32(val);
}
template<> OSL_FORCEINLINE uint64_t bitcast<uint64_t, double>(const double& val) noexcept {
return static_cast<uint64_t>(_castf64_u64(val));
}
template<> OSL_FORCEINLINE int64_t bitcast<int64_t, double>(const double& val) noexcept {
return static_cast<int64_t>(_castf64_u64(val));
}
template<> OSL_FORCEINLINE double bitcast<double, uint64_t>(const uint64_t& val) noexcept {
return _castu64_f64(val);
}
template<> OSL_FORCEINLINE double bitcast<double, int64_t>(const int64_t& val) noexcept {
return _castu64_f64(val);
}
#endif
/// OSL_PACK_STRUCTS_* is used to pack a struct or class tightly. Use it like
/// the following example. To set the alignment of the struct use the
/// alignas(x) directive.
///
/// OSL_PACK_STRUCTS_BEGIN
/// struct alignas(1) Foo {
/// char x, y, z;
/// };
/// OSL_PACK_STRUCTS_END
#define OSL_PACK_STRUCTS_BEGIN OSL_PRAGMA(pack(push, 1))
#define OSL_PACK_STRUCTS_END OSL_PRAGMA(pack(pop))
#if OSL_CPLUSPLUS_VERSION >= 20
using std::assume_aligned;
#else
+244 -127
View File
@@ -2,25 +2,24 @@
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
// clang-format off
#pragma once
#include <OSL/encodedtypes.h>
#include <OSL/oslconfig.h>
#include <OSL/variant.h>
OSL_NAMESPACE_ENTER
class RendererServices;
template<int WidthT>
class BatchedRendererServices;
template<int WidthT> class BatchedRendererServices;
class ShadingContext;
struct ShaderGlobals;
class ShaderGroup;
// Tags for polymorphic dispatch
template <int SimdWidthT>
class WidthOf {};
template<int SimdWidthT> class WidthOf {};
/// Opaque pointer to whatever the renderer uses to represent a
@@ -32,6 +31,20 @@ typedef const void* TransformationPtr;
typedef void (*PrepareClosureFunc)(RendererServices*, int id, void* data);
typedef void (*SetupClosureFunc)(RendererServices*, int id, void* data);
enum class AttributeSpecBuiltinArg {
ShaderGlobalsPointer, // void* (TODO: ideally ShaderGlobals*)
ShadeIndex, // int
Derivatives, // bool
Type, // TypeDesc_pod
ArrayIndex, // int, Always zero for non-indexed array lookups.
IsArrayLookup, // bool
ObjectName, // const char* (TODO: change to ustringhash)
AttributeName, // const char* (TODO: change to ustringhash)
};
using AttributeSpecArg = ArgVariant<AttributeSpecBuiltinArg>;
using AttributeGetterSpec = FunctionSpec<AttributeSpecArg>;
// Turn off warnings about unused params for this file, since we have lots
// of declarations with stub function bodies.
OSL_PRAGMA_WARNING_PUSH
@@ -49,11 +62,12 @@ public:
RendererServices(TextureSystem* texsys = NULL);
virtual ~RendererServices () { }
virtual ~RendererServices() {}
/// Given the name of a 'feature', return whether this RendererServices
/// supports it. Feature names include:
/// <none>
/// "OptiX"
/// "build_attribute_getter"
///
/// This allows some customization of JIT generated code based on the
/// facilities and features of a particular renderer. It also allows
@@ -62,28 +76,34 @@ public:
/// support it, as long as the OSL runtime only uses that feature if the
/// supports("feature") says it's present, thus preserving source
/// compatibility.
virtual int supports (string_view feature) const { return false; }
virtual int supports(string_view feature) const { return false; }
/// Get the 4x4 matrix that transforms by the specified
/// transformation at the given time. Return true if ok, false
/// on error.
virtual bool get_matrix (ShaderGlobals *sg, Matrix44 &result,
TransformationPtr xform, float time) { return false; }
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result,
TransformationPtr xform, float time)
{
return false;
}
/// Get the 4x4 matrix that transforms by the specified
/// transformation at the given time. Return true if ok, false on
/// error. The default implementation is to use get_matrix and
/// invert it, but a particular renderer may have a better technique
/// and overload the implementation.
virtual bool get_inverse_matrix (ShaderGlobals *sg, Matrix44 &result,
TransformationPtr xform, float time);
virtual bool get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
TransformationPtr xform, float time);
/// Get the 4x4 matrix that transforms by the specified
/// transformation. Return true if ok, false on error. Since no
/// time value is given, also return false if the transformation may
/// be time-varying.
virtual bool get_matrix (ShaderGlobals *sg, Matrix44 &result,
TransformationPtr xform) { return false; }
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result,
TransformationPtr xform)
{
return false;
}
/// Get the 4x4 matrix that transforms by the specified
/// transformation. Return true if ok, false on error. Since no
@@ -91,29 +111,29 @@ public:
/// be time-varying. The default implementation is to use
/// get_matrix and invert it, but a particular renderer may have a
/// better technique and overload the implementation.
virtual bool get_inverse_matrix (ShaderGlobals *sg, Matrix44 &result,
TransformationPtr xform);
virtual bool get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
TransformationPtr xform);
/// Get the 4x4 matrix that transforms points from the named
/// 'from' coordinate system to "common" space at the given time.
/// Returns true if ok, false if the named matrix is not known.
virtual bool get_matrix (ShaderGlobals *sg, Matrix44 &result,
ustring from, float time) { return false; }
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result,
ustringhash from, float time);
/// Get the 4x4 matrix that transforms points from "common" space to
/// the named 'to' coordinate system to at the given time. The
/// default implementation is to use get_matrix and invert it, but a
/// particular renderer may have a better technique and overload the
/// implementation.
virtual bool get_inverse_matrix (ShaderGlobals *sg, Matrix44 &result,
ustring to, float time);
virtual bool get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
ustringhash to, float time);
/// Get the 4x4 matrix that transforms 'from' to "common" space.
/// Since there is no time value passed, return false if the
/// transformation may be time-varying (as well as if it's not found
/// at all).
virtual bool get_matrix (ShaderGlobals *sg, Matrix44 &result,
ustring from) { return false; }
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result,
ustringhash from);
/// Get the 4x4 matrix that transforms points from "common" space to
/// the named 'to' coordinate system. Since there is no time value
@@ -122,8 +142,8 @@ public:
/// implementation is to use get_matrix and invert it, but a
/// particular renderer may have a better technique and overload the
/// implementation.
virtual bool get_inverse_matrix (ShaderGlobals *sg, Matrix44 &result,
ustring to);
virtual bool get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
ustringhash to);
/// Transform points Pin[0..npoints-1] in named coordinate system
/// 'from' into 'to' coordinates, storing the result in Pout[] using
@@ -148,12 +168,84 @@ public:
/// Note to RendererServices implementations: just return 'false'
/// if there isn't a special nonlinear transformation between the
/// two spaces.
virtual bool transform_points (ShaderGlobals *sg,
ustring from, ustring to, float time,
const Vec3 *Pin, Vec3 *Pout, int npoints,
TypeDesc::VECSEMANTICS vectype)
{ return false; }
virtual bool transform_points(ShaderGlobals* sg, ustringhash from,
ustringhash to, float time, const Vec3* Pin,
Vec3* Pout, int npoints,
TypeDesc::VECSEMANTICS vectype);
/// Report errors, warnings, printf, and fprintf.
/// Fmtlib style format specifier is used (vs. printf style)
/// Arguments are represented as EncodedTypes (encodedtypes.h) and
/// packed into an arg_values buffer. OSL::decode_message converts these
/// arguments into a std::string for renderer's handle to use as they please.
/// For device compatibility, the format specifier and any string arguments
/// are passed as ustringhash's.
/// Default implementation decodes the messages and fowards them to the
/// ShadingContext onto the ShadyingSystem's ErrorHandler.
/// It is recomended to override and make use of the
/// journal buffer to record everything to a buffer than can be post
/// processed as needed vs. going through the ShadingSystem ErrorHandler.
virtual void errorfmt(OSL::ShaderGlobals* sg,
OSL::ustringhash fmt_specification, int32_t arg_count,
const EncodedType* arg_types,
uint32_t arg_values_size, uint8_t* arg_values);
virtual void warningfmt(OSL::ShaderGlobals* sg,
OSL::ustringhash fmt_specification,
int32_t arg_count, const EncodedType* arg_types,
uint32_t arg_values_size, uint8_t* arg_values);
virtual void printfmt(OSL::ShaderGlobals* sg,
OSL::ustringhash fmt_specification, int32_t arg_count,
const EncodedType* arg_types,
uint32_t arg_values_size, uint8_t* arg_values);
virtual void filefmt(OSL::ShaderGlobals* sg, OSL::ustringhash filename_hash,
OSL::ustringhash fmt_specification, int32_t arg_count,
const EncodedType* arg_types, uint32_t arg_values_size,
uint8_t* arg_values);
/// Builds a free function to provide a value for a given attribute.
/// This occurs at shader compile time, not at execution time.
///
/// @param group
/// The shader group currently requesting the attribute.
///
/// @param is_object_lookup
/// True if an object name was specified, even if the value is not
/// known at compile time.
///
/// @param object_name
/// The object name, or nullptr if the value is not specified or it
/// is not known at compile time.
///
/// @param attribute_name
/// The attribute name, or nullptr if the value is not known at
/// compile time.
///
/// @param is_array_lookup
/// True if the attribute lookup provides an index.
///
/// @param array_index
/// The array index, or nullptr if the value is not specified or it
/// is not known at compile time.
///
/// @param type
/// The type of the value being requested.
///
/// @param derivatives
/// True if derivatives are also being requested.
///
/// @param spec
/// The built attribute getter. An empty function name is interpreted
/// as a missing attribute.
///
virtual void
build_attribute_getter(const ShaderGroup& group, bool is_object_lookup,
const ustring* object_name,
const ustring* attribute_name, bool is_array_lookup,
const int* array_index, TypeDesc type,
bool derivatives, AttributeGetterSpec& spec);
/// Get the named attribute from the renderer and if found then
/// write it into 'val'. Otherwise, return false. If no object is
@@ -167,36 +259,42 @@ public:
/// run on. Be robust to this situation, return 'true' (retrieve the
/// attribute) if you can (known object and attribute name), but
/// otherwise just fail by returning 'false'.
virtual bool get_attribute (ShaderGlobals *sg, bool derivatives,
ustring object, TypeDesc type, ustring name,
void *val) { return false; }
virtual bool get_attribute(ShaderGlobals* sg, bool derivatives,
ustringhash object, TypeDesc type,
ustringhash name, void* val);
/// Similar to get_attribute(); this method will return the 'index'
/// element of an attribute array.
virtual bool get_array_attribute (ShaderGlobals *sg, bool derivatives,
ustring object, TypeDesc type,
ustring name, int index, void *val) { return false; }
virtual bool get_array_attribute(ShaderGlobals* sg, bool derivatives,
ustringhash object, TypeDesc type,
ustringhash name, int index, void* val);
/// Get the named user-data from the current object and write it into
/// 'val'. If derivatives is true, the derivatives should be written into val
/// as well. Return false if no user-data with the given name and type was
/// found.
virtual bool get_userdata (bool derivatives, ustring name, TypeDesc type,
ShaderGlobals *sg, void *val) { return false; }
virtual bool get_userdata(bool derivatives, ustringhash name, TypeDesc type,
ShaderGlobals* sg, void* val);
/// Given the name of a texture, return an opaque handle that can be
/// used with texture calls to avoid the name lookups.
virtual TextureHandle * get_texture_handle (ustring filename,
ShadingContext *context);
/// Given the name of a texture, return an opaque handle that can be used
/// with texture calls to avoid the name lookups. The `options`, if not
/// null, may be used in renderer-specific ways to specialize a handle
/// based on certain texture option choices.
virtual TextureHandle*
get_texture_handle(ustring filename, ShadingContext* context,
const TextureOpt* options = nullptr);
virtual TextureHandle*
get_texture_handle(ustringhash filename, ShadingContext* context,
const TextureOpt* options = nullptr);
/// Return true if the texture handle (previously returned by
/// get_texture_handle()) is a valid texture that can be subsequently
/// read or sampled.
virtual bool good (TextureHandle *texture_handle);
virtual bool good(TextureHandle* texture_handle);
/// Return true if the texture handle (previously returned by
/// get_texture_handle()) is udim
virtual bool is_udim (TextureHandle *texture_handle);
virtual bool is_udim(TextureHandle* texture_handle);
/// Filtered 2D texture lookup for a single point.
///
@@ -224,13 +322,13 @@ public:
/// messages (in case of failure, when the function returns false) will
/// be stored there, leaving it up to the caller/shader to handle the
/// error.
virtual bool texture (ustring filename, TextureHandle *texture_handle,
TexturePerthread *texture_thread_info,
TextureOpt &options, ShaderGlobals *sg,
float s, float t, float dsdx, float dtdx,
float dsdy, float dtdy, int nchannels,
float *result, float *dresultds, float *dresultdt,
ustring *errormessage);
virtual bool texture(ustringhash filename, TextureHandle* texture_handle,
TexturePerthread* texture_thread_info,
TextureOpt& options, ShaderGlobals* sg, float s,
float t, float dsdx, float dtdx, float dsdy,
float dtdy, int nchannels, float* result,
float* dresultds, float* dresultdt,
ustringhash* errormessage);
/// Filtered 3D texture lookup for a single point.
///
@@ -257,14 +355,13 @@ public:
/// messages (in case of failure, when the function returns false) will
/// be stored there, leaving it up to the caller/shader to handle the
/// error.
virtual bool texture3d (ustring filename, TextureHandle *texture_handle,
TexturePerthread *texture_thread_info,
TextureOpt &options, ShaderGlobals *sg,
const Vec3 &P, const Vec3 &dPdx, const Vec3 &dPdy,
const Vec3 &dPdz, int nchannels,
float *result, float *dresultds,
float *dresultdt, float *dresultdr,
ustring *errormessage);
virtual bool texture3d(ustringhash filename, TextureHandle* texture_handle,
TexturePerthread* texture_thread_info,
TextureOpt& options, ShaderGlobals* sg,
const Vec3& P, const Vec3& dPdx, const Vec3& dPdy,
const Vec3& dPdz, int nchannels, float* result,
float* dresultds, float* dresultdt, float* dresultdr,
ustringhash* errormessage);
/// Filtered environment lookup for a single point.
///
@@ -288,13 +385,13 @@ public:
/// messages (in case of failure, when the function returns false) will
/// be stored there, leaving it up to the caller/shader to handle the
/// error.
virtual bool environment (ustring filename, TextureHandle *texture_handle,
TexturePerthread *texture_thread_info,
TextureOpt &options, ShaderGlobals *sg,
const Vec3 &R, const Vec3 &dRdx, const Vec3 &dRdy,
int nchannels, float *result,
float *dresultds, float *dresultdt,
ustring *errormessage);
virtual bool environment(ustringhash filename,
TextureHandle* texture_handle,
TexturePerthread* texture_thread_info,
TextureOpt& options, ShaderGlobals* sg,
const Vec3& R, const Vec3& dRdx, const Vec3& dRdy,
int nchannels, float* result, float* dresultds,
float* dresultdt, ustringhash* errormessage);
/// Get information about the given texture. Return true if found
/// and the data has been put in *data. Return false if the texture
@@ -315,24 +412,18 @@ public:
/// messages (in case of failure, when the function returns false) will
/// be stored there, leaving it up to the caller/shader to handle the
/// error.
virtual bool get_texture_info (ustring filename,
TextureHandle *texture_handle,
TexturePerthread *texture_thread_info,
ShadingContext *shading_context,
int subimage,
ustring dataname, TypeDesc datatype,
void *data,
ustring *errormessage);
virtual bool get_texture_info(ustringhash filename,
TextureHandle* texture_handle,
TexturePerthread* texture_thread_info,
ShaderGlobals* sg, int subimage,
ustringhash dataname, TypeDesc datatype,
void* data, ustringhash* errormessage);
virtual bool get_texture_info (ustring filename,
TextureHandle *texture_handle,
float s, float t,
TexturePerthread *texture_thread_info,
ShadingContext *shading_context,
int subimage,
ustring dataname, TypeDesc datatype,
void *data,
ustring *errormessage);
virtual bool
get_texture_info(ustringhash filename, TextureHandle* texture_handle,
float s, float t, TexturePerthread* texture_thread_info,
ShaderGlobals* sg, int subimage, ustringhash dataname,
TypeDesc datatype, void* data, ustringhash* errormessage);
/// Lookup nearest points in a point cloud. It will search for
@@ -343,40 +434,38 @@ public:
/// derivatives will be computed for distances (when provided).
///
/// Return the number of points found, always < max_points
virtual int pointcloud_search (ShaderGlobals *sg,
ustring filename, const OSL::Vec3 &center,
float radius, int max_points, bool sort,
size_t *out_indices,
float *out_distances, int derivs_offset);
virtual int pointcloud_search(ShaderGlobals* sg, ustringhash filename,
const OSL::Vec3& center, float radius,
int max_points, bool sort,
size_t* out_indices, float* out_distances,
int derivs_offset);
/// Retrieve an attribute for an index list. The result is another array
/// of the requested type stored in out_data.
///
/// Return 1 if the attribute is found, 0 otherwise.
virtual int pointcloud_get (ShaderGlobals *sg,
ustring filename, size_t *indices, int count,
ustring attr_name, TypeDesc attr_type,
void *out_data);
virtual int pointcloud_get(ShaderGlobals* sg, ustringhash filename,
size_t* indices, int count,
ustringhash attr_name, TypeDesc attr_type,
void* out_data);
/// Write a point to the named pointcloud, which will be saved
/// at the end of the frame. Return true if everything is ok,
/// false if there was an error.
virtual bool pointcloud_write (ShaderGlobals *sg,
ustring filename, const OSL::Vec3 &pos,
int nattribs, const ustring *names,
const TypeDesc *types,
const void **data);
virtual bool pointcloud_write(ShaderGlobals* sg, ustringhash filename,
const OSL::Vec3& pos, int nattribs,
const ustringrep* names,
const TypeDesc* types, const void** data);
/// Options for the trace call.
struct TraceOpt {
float mindist; ///< ignore hits closer than this
float maxdist; ///< ignore hits farther than this
bool shade; ///< whether to shade what is hit
ustring traceset; ///< named trace set
TraceOpt () : mindist(0.0f), maxdist(1.0e30), shade(false) { }
float mindist; ///< ignore hits closer than this
float maxdist; ///< ignore hits farther than this
bool shade; ///< whether to shade what is hit
ustringrep traceset; ///< named trace set
TraceOpt() : mindist(0.0f), maxdist(1.0e30), shade(false) {}
enum class LLVMMemberIndex
{
enum class LLVMMemberIndex {
mindist = 0,
maxdist,
shade,
@@ -387,37 +476,59 @@ public:
/// Immediately trace a ray from P in the direction R. Return true
/// if anything hit, otherwise false.
virtual bool trace (TraceOpt &options, ShaderGlobals *sg,
const OSL::Vec3 &P, const OSL::Vec3 &dPdx,
const OSL::Vec3 &dPdy, const OSL::Vec3 &R,
const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy) {
return false;
}
virtual bool trace(TraceOpt& options, ShaderGlobals* sg, const OSL::Vec3& P,
const OSL::Vec3& dPdx, const OSL::Vec3& dPdy,
const OSL::Vec3& R, const OSL::Vec3& dRdx,
const OSL::Vec3& dRdy);
/// Get the named message from the renderer and if found then
/// write it into 'val'. Otherwise, return false. This is only
/// called for "sourced" messages, not ordinary intra-group messages.
virtual bool getmessage (ShaderGlobals *sg, ustring source, ustring name,
TypeDesc type, void *val, bool derivatives) {
return false;
}
virtual bool getmessage(ShaderGlobals* sg, ustringhash source,
ustringhash name, TypeDesc type, void* val,
bool derivatives);
/// Return a pointer to the texture system (if available).
virtual TextureSystem *texturesys () const;
virtual TextureSystem* texturesys() const;
virtual uint64_t register_global (const std::string& var_name,
uint64_t value)
/// Allocate `size` bytes of memory on the device that will execute the
/// shaders. (Equivalent to malloc() on the CPU.)
virtual void* device_alloc(size_t size)
{
return 0;
return nullptr;
// Note: for an OptiX-based renderer, this method should be overriden
// with something like:
//
// void* dptr;
// auto r = cudaMalloc(&dptr, size);
// return r == cudaSuccess ? dptr : nullptr;
}
virtual bool fetch_global (const std::string& var_name,
uint64_t* value)
/// Free a previous allocation (by `device_alloc()`) on the device that
/// will execute the shaders. (Equivalent to free() on the CPU.)
virtual void device_free(void* ptr)
{
return false;
// Note: for an OptiX-based renderer, this method should be overriden
// with something like:
//
// cudaFree(ptr);
}
/// Copy `size` bytes from location `src_host` on the host/CPU (the
/// machine making this call) into location `dst_device` on the device
/// executing shaders. (Equivalent to `memcpy(dst, src, size)` on the
/// CPU.)
virtual void* copy_to_device(void* dst_device, const void* src_host,
size_t size)
{
return nullptr;
// Note: for an OptiX-based renderer, this method should be overriden
// with something like:
//
// auto r = cudaMemcpy(dst_device, src_host, size,
// cudaMemcpyHostToDevice);
// return dst_device;
}
/// Options we use for noise calls.
struct NoiseOpt {
@@ -426,19 +537,25 @@ public:
Vec3 direction;
float bandwidth;
float impulses;
NoiseOpt () : anisotropic(0), do_filter(true),
direction(1.0f,0.0f,0.0f), bandwidth(1.0f), impulses(16.0f) { }
NoiseOpt()
: anisotropic(0)
, do_filter(true)
, direction(1.0f, 0.0f, 0.0f)
, bandwidth(1.0f)
, impulses(16.0f)
{
}
};
/// A renderer may choose to support batched execution by providing pointers
/// to objects satisfying the BatchedRendererServices<WidthOf<#>> interface
/// for specific batch sizes.
/// Unless overridden, a nullptr is returned.
virtual BatchedRendererServices<16> * batched(WidthOf<16>);
virtual BatchedRendererServices<8> * batched(WidthOf<8>);
virtual BatchedRendererServices<16>* batched(WidthOf<16>);
virtual BatchedRendererServices<8>* batched(WidthOf<8>);
protected:
TextureSystem *m_texturesys; // A place to hold a TextureSystem
TextureSystem* m_texturesys; // A place to hold a TextureSystem
};
+174 -12
View File
@@ -2,6 +2,9 @@
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
#pragma once
#include <OSL/encodedtypes.h>
#include <OSL/oslconfig.h>
// Make all the strings defined in OSL
@@ -34,12 +37,13 @@ extern "C" {
// as opposed to using overloaded functions.
// Keep free functions in sync with virtual function based RendererServices.
// Must be re-enterant; Expect to be called from multiple threads
/// Get the 4x4 matrix that transforms by the specified
/// transformation at the given time. Return true if ok, false
/// on error.
OSL_RSOP bool
rs_get_matrix_xform_time(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
rs_get_matrix_xform_time(OSL::OpaqueExecContextPtr oec, OSL::Matrix44& result,
OSL::TransformationPtr from, float time);
/// Get the 4x4 matrix that transforms by the specified
@@ -47,14 +51,15 @@ rs_get_matrix_xform_time(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
/// error. Suggested implementation is to use rs_get_matrix_xform_time and
/// invert it, but a particular renderer may have a better technique.
OSL_RSOP bool
rs_get_inverse_matrix_xform_time(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
rs_get_inverse_matrix_xform_time(OSL::OpaqueExecContextPtr oec,
OSL::Matrix44& result,
OSL::TransformationPtr xform, float time);
/// Get the 4x4 matrix that transforms points from the named
/// 'from' coordinate system to "common" space at the given time.
/// Returns true if ok, false if the named matrix is not known.
OSL_RSOP bool
rs_get_matrix_space_time(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
rs_get_matrix_space_time(OSL::OpaqueExecContextPtr oec, OSL::Matrix44& result,
OSL::StringParam from, float time);
/// Get the 4x4 matrix that transforms points from "common" space to
@@ -62,15 +67,16 @@ rs_get_matrix_space_time(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
/// implementation is to use rs_get_matrix_space_time and invert it, but a
/// particular renderer may have a better technique.
OSL_RSOP bool
rs_get_inverse_matrix_space_time(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
OSL::StringParam to, float time);
rs_get_inverse_matrix_space_time(OSL::OpaqueExecContextPtr oec,
OSL::Matrix44& result, OSL::StringParam to,
float time);
/// Get the 4x4 matrix that transforms by the specified
/// transformation. Return true if ok, false on error. Since no
/// time value is given, also return false if the transformation may
/// be time-varying.
OSL_RSOP bool
rs_get_matrix_xform(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
rs_get_matrix_xform(OSL::OpaqueExecContextPtr oec, OSL::Matrix44& result,
OSL::TransformationPtr xform);
/// Get the 4x4 matrix that transforms by the specified
@@ -80,7 +86,8 @@ rs_get_matrix_xform(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
/// rs_get_matrix_xform and invert it, but a particular renderer may have a
/// better technique.
OSL_RSOP bool
rs_get_inverse_matrix_xform(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
rs_get_inverse_matrix_xform(OSL::OpaqueExecContextPtr oec,
OSL::Matrix44& result,
OSL::TransformationPtr xform);
/// Get the 4x4 matrix that transforms 'from' to "common" space.
@@ -88,7 +95,7 @@ rs_get_inverse_matrix_xform(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
/// transformation may be time-varying (as well as if it's not found
/// at all).
OSL_RSOP bool
rs_get_matrix_space(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
rs_get_matrix_space(OSL::OpaqueExecContextPtr oec, OSL::Matrix44& result,
OSL::StringParam from);
/// Get the 4x4 matrix that transforms points from "common" space to
@@ -98,8 +105,8 @@ rs_get_matrix_space(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
/// implementation is to use rs_get_matrix_space and invert it, but a
/// particular renderer may have a better technique.
OSL_RSOP bool
rs_get_inverse_matrix_space(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
OSL::StringParam to);
rs_get_inverse_matrix_space(OSL::OpaqueExecContextPtr oec,
OSL::Matrix44& result, OSL::StringParam to);
/// Transform points Pin[0..npoints-1] in named coordinate system
/// 'from' into 'to' coordinates, storing the result in Pout[] using
@@ -122,7 +129,162 @@ rs_get_inverse_matrix_space(OSL::ShaderGlobals* sg, OSL::Matrix44& result,
/// if there isn't a special nonlinear transformation between the
/// two spaces.
OSL_RSOP bool
rs_transform_points(OSL::ShaderGlobals* sg, OSL::StringParam from,
rs_transform_points(OSL::OpaqueExecContextPtr oec, OSL::StringParam from,
OSL::StringParam to, float time, const OSL::Vec3* Pin,
OSL::Vec3* Pout, int npoints,
OSL::TypeDesc::VECSEMANTICS vectype);
OSL::TypeDesc::VECSEMANTICS vectype);
/// Report errors, warnings, printf, and fprintf.
/// Fmtlib style format specifier is used (vs. printf style)
/// Arguments are represented as EncodedTypes (encodedtypes.h) and
/// packed into an arg_values buffer. OSL::decode_message converts these
/// arguments into a std::string for renderer's handle to use as they please.
/// For device compatibility, the format specifier and any string arguments
/// are passed as ustringhash's.
/// It is recomended to override and make use of the journal buffer to record
/// everything to a buffer than can be post processed as needed.
OSL_RSOP void
rs_errorfmt(OSL::OpaqueExecContextPtr oec, OSL::ustringhash fmt_specification,
int32_t count, const OSL::EncodedType* argTypes,
uint32_t argValuesSize, uint8_t* argValues);
OSL_RSOP void
rs_filefmt(OSL::OpaqueExecContextPtr oec, OSL::ustringhash filname_hash,
OSL::ustringhash fmt_specification, int32_t count,
const OSL::EncodedType* argTypes, uint32_t argValuesSize,
uint8_t* argValues);
OSL_RSOP void
rs_printfmt(OSL::OpaqueExecContextPtr oec, OSL::ustringhash fmt_specification,
int32_t count, const OSL::EncodedType* argTypes,
uint32_t argValuesSize, uint8_t* argValues);
OSL_RSOP void
rs_warningfmt(OSL::OpaqueExecContextPtr oec, OSL::ustringhash fmt_specification,
int32_t count, const OSL::EncodedType* argTypes,
uint32_t argValuesSize, uint8_t* argValues);
#if 0
// C++ helpers to accept variable arguements and encode messages to be sent
// through renderer service free functions
OSL_NAMESPACE_ENTER
namespace pvt {
// PackedArgs is similar to tuple but packs its data back to back
// in memory layout, which is what we need to build up payload
// to the fmt reporting system
template<int IndexT, typename TypeT> struct PackedArg {
explicit PackedArg(const TypeT& a_value) : m_value(a_value) {}
TypeT m_value;
} __attribute__((packed, aligned(1)));
template<typename IntSequenceT, typename... TypeListT> struct PackedArgsBase;
// Specialize to extract a parameter pack of the IntegerSquence
// so it can be expanded alongside the TypeListT parameter pack
template<int... IntegerListT, typename... TypeListT>
struct PackedArgsBase<std::integer_sequence<int, IntegerListT...>, TypeListT...>
: public PackedArg<IntegerListT, TypeListT>... {
explicit PackedArgsBase(const TypeListT&... a_values)
// multiple inheritance of individual components
// uniquely identified by the <Integer,Type> combo
: PackedArg<IntegerListT, TypeListT>(a_values)...
{
}
} __attribute__((packed, aligned(1)));
template<typename... TypeListT> struct PackedArgs {
typedef std::make_integer_sequence<int, sizeof...(TypeListT)>
IndexSequenceType;
PackedArgsBase<IndexSequenceType, TypeListT...> m_components;
explicit PackedArgs(const TypeListT&... a_values)
: m_components(a_values...)
{
}
};
} // namespace pvt
template<typename FilenameT, typename SpecifierT, typename... ArgListT>
void
filefmt(OpaqueExecContextPtr oec, const FilenameT& filename_hash,
const SpecifierT& fmt_specification, ArgListT... args)
{
constexpr int32_t count = sizeof...(args);
constexpr OSL::EncodedType argTypes[]
= { pvt::TypeEncoder<ArgListT>::value... };
pvt::PackedArgs<typename pvt::TypeEncoder<ArgListT>::DataType...> argValues {
pvt::TypeEncoder<ArgListT>::Encode(args)...
};
rs_filefmt(oec, OSL::ustringhash { filename_hash },
OSL::ustringhash { fmt_specification }, count,
(count == 0) ? nullptr : argTypes,
static_cast<uint32_t>((count == 0) ? 0 : sizeof(argValues)),
(count == 0) ? nullptr : reinterpret_cast<uint8_t*>(&argValues));
}
template<typename SpecifierT, typename... ArgListT>
void
printfmt(OpaqueExecContextPtr oec, const SpecifierT& fmt_specification,
ArgListT... args)
{
constexpr int32_t count = sizeof...(args);
constexpr OSL::EncodedType argTypes[]
= { pvt::TypeEncoder<ArgListT>::value... };
pvt::PackedArgs<typename pvt::TypeEncoder<ArgListT>::DataType...> argValues {
pvt::TypeEncoder<ArgListT>::Encode(args)...
};
rs_printfmt(oec, OSL::ustringhash { fmt_specification }, count,
(count == 0) ? nullptr : argTypes,
static_cast<uint32_t>((count == 0) ? 0 : sizeof(argValues)),
(count == 0) ? nullptr
: reinterpret_cast<uint8_t*>(&argValues));
}
template<typename SpecifierT, typename... ArgListT>
void
errorfmt(OpaqueExecContextPtr oec, const SpecifierT& fmt_specification,
ArgListT... args)
{
constexpr int32_t count = sizeof...(args);
constexpr OSL::EncodedType argTypes[]
= { pvt::TypeEncoder<ArgListT>::value... };
pvt::PackedArgs<typename pvt::TypeEncoder<ArgListT>::DataType...> argValues {
pvt::TypeEncoder<ArgListT>::Encode(args)...
};
rs_errorfmt(oec, OSL::ustringhash { fmt_specification }, count,
(count == 0) ? nullptr : argTypes,
static_cast<uint32_t>((count == 0) ? 0 : sizeof(argValues)),
(count == 0) ? nullptr
: reinterpret_cast<uint8_t*>(&argValues));
}
template<typename SpecifierT, typename... ArgListT>
void
warningfmt(OpaqueExecContextPtr oec, const SpecifierT& fmt_specification,
ArgListT... args)
{
constexpr int32_t count = sizeof...(args);
constexpr OSL::EncodedType argTypes[]
= { pvt::TypeEncoder<ArgListT>::value... };
pvt::PackedArgs<typename pvt::TypeEncoder<ArgListT>::DataType...> argValues {
pvt::TypeEncoder<ArgListT>::Encode(args)...
};
rs_warningfmt(oec, OSL::ustringhash { fmt_specification }, count,
(count == 0) ? nullptr : argTypes,
static_cast<uint32_t>((count == 0) ? 0 : sizeof(argValues)),
(count == 0) ? nullptr
: reinterpret_cast<uint8_t*>(&argValues));
}
OSL_NAMESPACE_EXIT
#endif
+336
View File
@@ -36,6 +36,22 @@ typedef const void* OpaqueShadingStateUniformPtr;
///
/// All points, vectors and normals are given in "common" space.
///
/// We are working towards making ShaderGlobals a private implementation
/// detail. Preference is given to utilizing an Opaque Execution Context
/// Pointer with accessor functions (setter/getters) to access shader global
/// values or any context for the currently executing shade. These accessors
/// are at the bottom of this file following the form:
/// const Vec3& get_P(const OpaqueExecContextPtr oec);
/// const Vec3& get_N(const OpaqueExecContextPtr oec);
/// float get_time(const OpaqueExecContextPtr oec);
/// int get_shade_index(const OpaqueExecContextPtr oec);
/// Currently ExecutionContext is a ShaderGlobals and can be used
/// interchangably. After inlining we don't expect worse performance.
/// Users should transition to the new accessor function API. Once transition
/// is complete, where the values are stored and how they are populated is
/// expected to change and the new API will provide a layer of encapsulation
/// that the raw ShaderGlobals struct doesn't allow.
struct ShaderGlobals {
/// Surface position (and its x & y differentials).
Vec3 P, dPdx, dPdy;
@@ -88,6 +104,13 @@ struct ShaderGlobals {
ShadingContext* context;
OpaqueShadingStateUniformPtr shadingStateUniform;
/// Shading System responsible for setting
/// 0 based thread index, required by journaling mechanism
int thread_index;
/// Shading System responsible for setting
int shade_index;
/// Pointer to the RendererServices object. This is how OSL finds its
/// way back to the renderer for callbacks.
RendererServices* renderer;
@@ -144,4 +167,317 @@ enum class SGBits {
last
};
typedef void* OpaqueExecContextPtr;
namespace pvt {
// As the concrete ExecutionContext is an implementation detail,
// it is placed in the pvt namespace.
// New accessor functions are provided below in the form
// OSL::get_???(const OpaqueExecContextPtr)
// Renderer's should use the accessor functions, and not attempt to cast or
// directly use the underlying ExecutionContext. This will allow the
// implemenation to change and possibly have accessors generated in llvm if
// needed. OSL library function implementions may directly use the
// ExecutionContext.
typedef ShaderGlobals ExecContext;
typedef ExecContext* ExecContextPtr;
OSL_HOSTDEVICE inline ExecContextPtr
get_ec(OSL::OpaqueExecContextPtr oec)
{
return reinterpret_cast<ExecContextPtr>(oec);
}
}; // namespace pvt
template<typename RenderStateT>
OSL_HOSTDEVICE inline RenderStateT*
get_rs(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
auto rs = reinterpret_cast<RenderStateT*>(ec->renderstate);
return rs;
}
template<typename TraceDataT>
OSL_HOSTDEVICE inline TraceDataT*
get_tracedata(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
auto tracedata = reinterpret_cast<TraceDataT*>(ec->tracedata);
return tracedata;
}
template<typename ObjectT>
OSL_HOSTDEVICE inline ObjectT*
get_objdata(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
auto objdata = reinterpret_cast<ObjectT*>(ec->objdata);
return objdata;
}
// TODO: not sure ci should be exposed via a getter or not
// its presence here maybe temporary
OSL_HOSTDEVICE inline ClosureColor*
get_Ci(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->Ci;
}
OSL_HOSTDEVICE inline TransformationPtr
get_object2common(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->object2common;
}
OSL_HOSTDEVICE inline TransformationPtr
get_shader2common(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->shader2common;
}
///Required by free function renderer services to process fmt specification calls; set by Shading System, and not by user
OSL_HOSTDEVICE inline int
get_shade_index(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->shade_index;
}
///Required for memory allocation on a per thread basis for journaling fmt specification calls; set by Shading System, and not by user
OSL_HOSTDEVICE inline int
get_thread_index(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->thread_index;
}
/// Surface position (and its x & y differentials).
OSL_HOSTDEVICE inline const Vec3&
get_P(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->P;
}
OSL_HOSTDEVICE inline const Vec3&
get_dPdx(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->dPdx;
}
OSL_HOSTDEVICE inline const Vec3&
get_dPdy(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->dPdy;
}
/// P's z differential, used for volume shading only.
OSL_HOSTDEVICE inline const Vec3&
get_dPdz(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->dPdz;
}
/// Incident ray, and its x and y derivatives.
OSL_HOSTDEVICE inline const Vec3&
get_I(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->I;
}
OSL_HOSTDEVICE inline const Vec3&
get_dIdx(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->dIdx;
}
OSL_HOSTDEVICE inline const Vec3&
get_dIdy(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->dIdy;
}
/// Shading normal, already front-facing.
OSL_HOSTDEVICE inline const Vec3&
get_N(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->N;
}
/// True geometric normal.
OSL_HOSTDEVICE inline const Vec3&
get_Ng(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->Ng;
}
/// 2D surface parameter u, and its differentials.
OSL_HOSTDEVICE inline float
get_u(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->u;
}
OSL_HOSTDEVICE inline float
get_dudx(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->dudx;
}
OSL_HOSTDEVICE inline float
get_dudy(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->dudy;
}
/// 2D surface parameter v, and its differentials.
OSL_HOSTDEVICE inline float
get_v(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->v;
}
OSL_HOSTDEVICE inline float
get_dvdx(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->dvdx;
}
OSL_HOSTDEVICE inline float
get_dvdy(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->dvdy;
}
/// Surface tangents: derivative of P with respect to surface u and v.
OSL_HOSTDEVICE inline const Vec3&
get_dPdu(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->dPdu;
}
OSL_HOSTDEVICE inline const Vec3&
get_dPdv(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->dPdv;
}
/// Time for this shading sample.
OSL_HOSTDEVICE inline float
get_time(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->time;
}
/// Time interval for the frame (or shading sample).
OSL_HOSTDEVICE inline float
get_dtime(const OpaqueExecContextPtr oec)
{
auto ec = reinterpret_cast<OSL::ShaderGlobals*>(oec);
return ec->dtime;
}
/// Velocity vector: derivative of position P with respect to time.
OSL_HOSTDEVICE inline const Vec3&
get_dPdtime(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->dPdtime;
}
/// For lights or light attenuation shaders: the point being illuminated
/// (Ps), and its differentials.
OSL_HOSTDEVICE inline const Vec3&
get_Ps(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->Ps;
}
OSL_HOSTDEVICE inline const Vec3&
get_dPsdx(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->dPsdx;
}
OSL_HOSTDEVICE inline const Vec3&
get_dPsdy(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->dPsdy;
}
/// If nonzero, we are shading the back side of a surface.
OSL_HOSTDEVICE inline int
get_backfacing(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->backfacing;
}
/// If nonzero, will flip the result of calculatenormal().
OSL_HOSTDEVICE inline int
get_flipHandedness(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->flipHandedness;
}
/// Bit field of ray type flags.
OSL_HOSTDEVICE inline int
get_raytype(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->raytype;
}
/// Surface area of the emissive object (used by light shaders for
/// energy normalization).
OSL_HOSTDEVICE inline float
get_surfacearea(const OpaqueExecContextPtr oec)
{
auto ec = pvt::get_ec(oec);
return ec->surfacearea;
}
namespace pvt {
// defined in opfmt.cpp
OSLEXECPUBLIC int
get_max_warnings_per_thread(const OSL::OpaqueExecContextPtr cptr);
} // namespace pvt
// Useful to pass to OSL::journal::Writer::record_warningfmt
inline int
get_max_warnings_per_thread(const OpaqueExecContextPtr oec)
{
return pvt::get_max_warnings_per_thread(oec);
}
OSL_NAMESPACE_EXIT
+254
View File
@@ -0,0 +1,254 @@
// Copyright Contributors to the Open Shading Language project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
#pragma once
#include <OSL/oslconfig.h>
OSL_NAMESPACE_ENTER
// TODO: When minimum required C++ reaches C++17, replace with std::variant.
template<typename TBuiltinArg> class ArgVariant {
public:
enum class Type {
Unspecified = 0,
Builtin,
Bool,
Int8,
Int16,
Int32,
Int64,
UInt8,
UInt16,
UInt32,
UInt64,
Float,
Double,
Pointer,
UString,
UStringHash,
};
private:
union {
TBuiltinArg m_builtin;
bool m_bool;
int8_t m_int8;
int16_t m_int16;
int32_t m_int32;
int64_t m_int64;
uint8_t m_uint8;
uint16_t m_uint16;
uint32_t m_uint32;
uint64_t m_uint64;
float m_float;
double m_double;
void* m_ptr;
ustring m_ustring;
ustringhash m_ustringhash;
};
Type m_type;
public:
ArgVariant() : m_type(Type::Unspecified) {}
ArgVariant(TBuiltinArg arg) : m_builtin(arg), m_type(Type::Builtin) {}
ArgVariant(bool arg) : m_bool(arg), m_type(Type::Bool) {}
ArgVariant(int8_t arg) : m_int8(arg), m_type(Type::Int8) {}
ArgVariant(int16_t arg) : m_int16(arg), m_type(Type::Int16) {}
ArgVariant(int32_t arg) : m_int32(arg), m_type(Type::Int32) {}
ArgVariant(int64_t arg) : m_int64(arg), m_type(Type::Int64) {}
ArgVariant(uint8_t arg) : m_uint8(arg), m_type(Type::UInt8) {}
ArgVariant(uint16_t arg) : m_uint16(arg), m_type(Type::UInt16) {}
ArgVariant(uint32_t arg) : m_uint32(arg), m_type(Type::UInt32) {}
ArgVariant(uint64_t arg) : m_uint64(arg), m_type(Type::UInt64) {}
ArgVariant(float arg) : m_float(arg), m_type(Type::Float) {}
ArgVariant(double arg) : m_double(arg), m_type(Type::Double) {}
ArgVariant(void* arg) : m_ptr(arg), m_type(Type::Pointer) {}
ArgVariant(ustring arg) : m_ustring(arg), m_type(Type::UString) {}
ArgVariant(ustringhash arg) : m_ustringhash(arg), m_type(Type::UStringHash)
{
}
ArgVariant(const ArgVariant& other)
{
memcpy((void*)this, &other, sizeof(ArgVariant));
}
ArgVariant(ArgVariant&& other)
{
memcpy((void*)this, &other, sizeof(ArgVariant));
}
~ArgVariant() {}
ArgVariant& operator=(const ArgVariant& other)
{
memcpy((void*)this, &other, sizeof(ArgVariant));
return *this;
}
ArgVariant& operator=(ArgVariant&& other)
{
memcpy((void*)this, &other, sizeof(ArgVariant));
return *this;
}
Type type() const { return m_type; }
template<typename T> bool is_holding() const
{
if (std::is_same<T, TBuiltinArg>::value)
return m_type == Type::Builtin;
if (std::is_same<T, bool>::value)
return m_type == Type::Bool;
if (std::is_same<T, int8_t>::value)
return m_type == Type::Int8;
if (std::is_same<T, int16_t>::value)
return m_type == Type::Int16;
if (std::is_same<T, int32_t>::value)
return m_type == Type::Int32;
if (std::is_same<T, int64_t>::value)
return m_type == Type::Int64;
if (std::is_same<T, uint8_t>::value)
return m_type == Type::UInt8;
if (std::is_same<T, uint16_t>::value)
return m_type == Type::UInt16;
if (std::is_same<T, uint32_t>::value)
return m_type == Type::UInt32;
if (std::is_same<T, uint64_t>::value)
return m_type == Type::UInt64;
if (std::is_same<T, float>::value)
return m_type == Type::Float;
if (std::is_same<T, double>::value)
return m_type == Type::Double;
if (std::is_same<T, void*>::value)
return m_type == Type::Pointer;
if (std::is_same<T, ustring>::value)
return m_type == Type::UString;
if (std::is_same<T, ustringhash>::value)
return m_type == Type::UStringHash;
return false;
}
TBuiltinArg get_builtin() const
{
OSL_DASSERT(is_holding<TBuiltinArg>());
return m_builtin;
}
bool get_bool() const
{
OSL_DASSERT(is_holding<bool>());
return m_bool;
}
int8_t get_int8() const
{
OSL_DASSERT(is_holding<int8_t>());
return m_int8;
}
int16_t get_int16() const
{
OSL_DASSERT(is_holding<int16_t>());
return m_int16;
}
int32_t get_int32() const
{
OSL_DASSERT(is_holding<int32_t>());
return m_int32;
}
int64_t get_int64() const
{
OSL_DASSERT(is_holding<int64_t>());
return m_int64;
}
uint8_t get_uint8() const
{
OSL_DASSERT(is_holding<uint8_t>());
return m_uint8;
}
uint16_t get_uint16() const
{
OSL_DASSERT(is_holding<uint16_t>());
return m_uint16;
}
uint32_t get_uint32() const
{
OSL_DASSERT(is_holding<uint32_t>());
return m_uint32;
}
uint64_t get_uint64() const
{
OSL_DASSERT(is_holding<uint64_t>());
return m_uint64;
}
float get_float() const
{
OSL_DASSERT(is_holding<float>());
return m_float;
}
double get_double() const
{
OSL_DASSERT(is_holding<double>());
return m_double;
}
void* get_ptr() const
{
OSL_DASSERT(is_holding<void*>());
return m_ptr;
}
ustring get_ustring() const
{
OSL_DASSERT(is_holding<ustring>());
return m_ustring;
}
ustringhash get_ustringhash() const
{
OSL_DASSERT(is_holding<ustringhash>());
return m_ustringhash;
}
};
// The FunctionSpec is never in device code, so it can be a bit more
// complex and have dynamic allocations. Although we do want to
// use an interface and not allow direct data member access
template<typename TArg> class FunctionSpec {
ustring m_function_name;
std::vector<TArg> m_args;
public:
template<typename... ArgListT>
void set(ustring function_name, ArgListT... args)
{
m_function_name = function_name;
m_args.clear();
m_args.insert(m_args.end(),
std::initializer_list<TArg> { TArg { args }... });
}
const ustring& function_name() const { return m_function_name; }
size_t arg_count() const { return m_args.size(); }
const TArg& arg(size_t i) const
{
OSL_DASSERT(i < m_args.size());
return m_args[i];
}
};
OSL_NAMESPACE_EXIT
+102 -34
View File
@@ -299,16 +299,13 @@ public:
// Specializations
template<int WidthT>
struct Block<float, WidthT> : public BlockOfBuiltin<float, WidthT> {
};
struct Block<float, WidthT> : public BlockOfBuiltin<float, WidthT> {};
template<int WidthT>
struct Block<int, WidthT> : public BlockOfBuiltin<int, WidthT> {
};
struct Block<int, WidthT> : public BlockOfBuiltin<int, WidthT> {};
template<typename DataT, int WidthT>
struct Block<DataT*, WidthT> : public BlockOfBuiltin<DataT*, WidthT> {
};
struct Block<DataT*, WidthT> : public BlockOfBuiltin<DataT*, WidthT> {};
// Vec4 isn't used by external interfaces, but some internal
@@ -895,6 +892,8 @@ template<int WidthT> struct alignas(VecReg<WidthT>) Block<Matrix44, WidthT> {
}
};
// Specialization of Block for ustring
template<int WidthT> struct alignas(VecReg<WidthT>) Block<ustring, WidthT> {
static constexpr int width = WidthT;
typedef ustring ValueType;
@@ -942,6 +941,58 @@ template<int WidthT> struct alignas(VecReg<WidthT>) Block<ustring, WidthT> {
}
};
// Specialization of Block for ustringhash
template<int WidthT> struct alignas(VecReg<WidthT>) Block<ustringhash, WidthT> {
static constexpr int width = WidthT;
typedef ustringhash ValueType;
// To enable vectorization, use uintptr_t to store the ustringhash (const char *)
size_t str[WidthT];
static_assert(sizeof(ustringhash) == sizeof(size_t),
"ustringhash must be size_t");
OSL_FORCEINLINE Block() = default;
// We want to avoid accidentally copying these when the intent was to just pass a reference
Block(const Block& other) = delete;
OSL_FORCEINLINE void set(int lane, const ustringhash& value)
{
str[lane] = value.hash();
}
OSL_FORCEINLINE void set(int lane, ustring value)
{
str[lane] = value.hash();
}
OSL_FORCEINLINE void set(int lane, const ustringhash& value, bool laneMask)
{
if (laneMask)
str[lane] = value.hash();
}
OSL_FORCEINLINE ustringhash get(int lane) const
{
#ifdef OIIO_USTRING_HAS_CTR_FROM_USTRINGHASH
return ustringhash::from_hash(str[lane]);
#else
return OSL::bitcast<ustringhash>(str[lane]);
#endif
}
OSL_FORCEINLINE pvt::LaneProxy<ValueType, WidthT> operator[](int lane)
{
return pvt::LaneProxy<ValueType, WidthT>(*this, lane);
}
OSL_FORCEINLINE pvt::ConstLaneProxy<const ValueType, WidthT>
operator[](int lane) const
{
return pvt::ConstLaneProxy<const ValueType, WidthT>(*this, lane);
}
};
template<int WidthT>
struct alignas(VecReg<WidthT>) Block<Dual2<float>, WidthT> {
typedef Dual2<float> ValueType;
@@ -2229,15 +2280,9 @@ template<typename DataT, int WidthT> struct MaskedLaneProxy {
// visibility to end user whose IDE
// might display these methods vs. free
// functions
OSL_FORCEINLINE bool is_on() const
{
return m_mask.is_on(m_lane);
}
OSL_FORCEINLINE bool is_on() const { return m_mask.is_on(m_lane); }
OSL_FORCEINLINE bool is_off() const
{
return m_mask.is_off(m_lane);
}
OSL_FORCEINLINE bool is_off() const { return m_mask.is_off(m_lane); }
private:
Block<DataT, WidthT>& m_ref_wide_data;
@@ -2299,15 +2344,9 @@ struct MaskedArrayLaneProxy {
// visibility to end user whose IDE
// might display these methods vs. free
// functions
OSL_FORCEINLINE bool is_on() const
{
return m_mask.is_on(m_lane);
}
OSL_FORCEINLINE bool is_on() const { return m_mask.is_on(m_lane); }
OSL_FORCEINLINE bool is_off() const
{
return m_mask.is_off(m_lane);
}
OSL_FORCEINLINE bool is_off() const { return m_mask.is_off(m_lane); }
OSL_FORCEINLINE MaskedLaneProxy<DataT, WidthT>
operator[](int array_index) const
@@ -2672,7 +2711,8 @@ struct MaskedDeriv : public Masked<DataT, WidthT> {
template<typename FirstT, typename... ListT,
std::enable_if_t<std::is_same<typename std::decay<FirstT>::type,
MaskedDeriv>::value,
bool> = true>
bool>
= true>
OSL_FORCEINLINE MaskedDeriv(FirstT&& first, ListT&&... argList)
: Masked<DataT, WidthT>(std::forward<FirstT>(first),
std::forward<ListT>(argList)...)
@@ -2683,7 +2723,8 @@ struct MaskedDeriv : public Masked<DataT, WidthT> {
template<typename FirstT, typename... ListT,
std::enable_if_t<!std::is_same<typename std::decay<FirstT>::type,
MaskedDeriv>::value,
bool> = true>
bool>
= true>
OSL_FORCEINLINE MaskedDeriv(FirstT&& first, ListT&&... argList)
: Masked<DataT, WidthT>(std::forward<FirstT>(first),
std::forward<ListT>(argList)...,
@@ -2845,7 +2886,7 @@ public:
// Populate all data lanes of the MaskedData by broadcasting the
// single instance of data pointed to.
// Masked off lanes are not overwritten.
// Includes value, as well as Dx and Dy when has_derivs() is true
// when has_derivs() is true, Dx and Dy will be zeroed
OSL_FORCEINLINE void assign_all_from_scalar(const void* ptr_data) const;
@@ -2863,6 +2904,9 @@ private:
template<typename DataT>
OSL_NOINLINE void assign_all_from_scalar_type(const void* ptr_data,
int deriv_index) const;
template<typename DataT>
OSL_NOINLINE void zero_all_type(int deriv_index) const;
};
@@ -3131,7 +3175,8 @@ template<typename DataT, int DerivIndexT> struct RefDeriv : public Ref<DataT> {
template<typename FirstT, typename... ListT,
std::enable_if_t<!std::is_same<typename std::decay<FirstT>::type,
RefDeriv>::value,
bool> = true>
bool>
= true>
explicit OSL_FORCEINLINE RefDeriv(FirstT&& first, ListT&&... argList)
: Ref<DataT>(std::forward<FirstT>(first),
std::forward<ListT>(argList)...,
@@ -3378,6 +3423,33 @@ MaskedData<WidthT>::assign_all_from_scalar_type(const void* ptr_data,
}
}
template<int WidthT>
template<typename DataT>
OSL_NOINLINE void
MaskedData<WidthT>::zero_all_type(int deriv_index) const
{
// We can't just do a memset because some lanes may be masked off
// Use a SIMD loop to perform masked assignment.
auto* dst_blocks = pvt::block_cast<DataT, WidthT>(m_ptr);
int elem_count = static_cast<int>(m_type.numelements());
int comp_count = m_type.aggregate;
int deriv_offset = deriv_index * elem_count * comp_count;
for (int array_index = 0; array_index < elem_count; ++array_index) {
int array_offset = array_index * comp_count;
for (int comp_index = 0; comp_index < comp_count; ++comp_index) {
int combined_index = deriv_offset + array_offset + comp_index;
auto& bdst = dst_blocks[combined_index];
Masked<DataT, WidthT> wdest(bdst, mask());
OSL_OMP_PRAGMA(omp simd simdlen(WidthT))
for (int lane = 0; lane < WidthT; ++lane) {
wdest[lane] = DataT {};
}
}
}
}
template<int WidthT>
OSL_FORCEINLINE void
MaskedData<WidthT>::assign_all_from_scalar(const void* ptr_data) const
@@ -3393,16 +3465,12 @@ MaskedData<WidthT>::assign_all_from_scalar(const void* ptr_data) const
assign_all_from_scalar_type<ustring>(ptr_data, /*deriv_index*/ 0);
}
if (has_derivs()) {
size_t src_size = type().size();
const char* dx_src = reinterpret_cast<const char*>(ptr_data) + src_size;
const char* dy_src = dx_src + src_size;
if (isBase32bit) {
assign_all_from_scalar_type<int>(dx_src, /*deriv_index*/ 1);
assign_all_from_scalar_type<int>(dy_src, /*deriv_index*/ 2);
zero_all_type<int>(/*deriv_index*/ 1);
zero_all_type<int>(/*deriv_index*/ 2);
} else {
assign_all_from_scalar_type<ustring>(dx_src, /*deriv_index*/ 1);
assign_all_from_scalar_type<ustring>(dy_src, /*deriv_index*/ 2);
zero_all_type<ustring>(/*deriv_index*/ 1);
zero_all_type<ustring>(/*deriv_index*/ 2);
}
}
}
+4 -3
View File
@@ -8,7 +8,7 @@
#include <OSL/oslconfig.h>
#include <OSL/oslversion.h>
#ifdef OSL_USE_OPTIX
#if OSL_USE_OPTIX
# include <cuda_runtime_api.h>
# include <optix.h>
# ifdef _WIN32
@@ -18,8 +18,9 @@
# include <stdlib.h>
#endif
#include <OSL/device_ptr.h>
#if !defined(OSL_USE_OPTIX) && !defined(__CUDA_ARCH__)
#if !OSL_USE_OPTIX && !defined(__CUDA_ARCH__)
using CUdeviceptr = void*;
using float3 = OSL::Vec3;
#endif
@@ -28,7 +29,7 @@ using float3 = OSL::Vec3;
OSL_NAMESPACE_ENTER
#ifdef OSL_USE_OPTIX
#if OSL_USE_OPTIX
////////////////////////////////////////////////////////////////////////
// If OptiX is available, alias everything in optix:: namespace into
+94 -215
View File
@@ -386,6 +386,7 @@ public:
/// vector-like (and match their array-ness and closure-ness), or
/// if both are structures with matching fields.
friend bool equivalent(const TypeSpec& a, const TypeSpec& b);
friend bool relaxed_equivalent(const TypeSpec& a, const TypeSpec& b);
/// Is type src is assignable to dst? It is if they are the equivalent(),
/// or if dst is a float or float-aggregate and src is a float or int.
@@ -477,7 +478,9 @@ public:
, m_const_initializer(false)
, m_connected_down(false)
, m_initialized(false)
, m_lockgeom(false)
, m_interpolated(false)
, m_interactive(false)
, m_noninteractive(false)
, m_allowconnect(true)
, m_renderer_output(false)
, m_readonly(false)
@@ -629,137 +632,70 @@ public:
OSL_ASSERT(arena == SymArena::Absolute);
m_arena = static_cast<unsigned int>(arena);
m_data = ptr;
// m_dataoffset = static_cast<int64_t>((char*)ptr - (char*)0);
}
/// Specify the location of the symbol's data, relative to an arena
/// (which for now must be Absolute).
void set_dataptr(SymArena arena, void* ptr, int offset)
{
// OSL_ASSERT(arena == SymArena::Absolute);
m_arena = static_cast<unsigned int>(arena);
m_data = ptr;
m_dataoffset = offset;
OSL::print("setting sym {} arena {} offset {}\n", name(), int(m_arena),
m_dataoffset);
}
void dataoffset(int d)
{
m_dataoffset = d;
}
int dataoffset() const
{
return m_dataoffset;
}
void dataoffset(int d) { m_dataoffset = d; }
int dataoffset() const { return m_dataoffset; }
void wide_dataoffset(int d)
{
m_wide_dataoffset = d;
}
int wide_dataoffset() const
{
return m_wide_dataoffset;
}
void wide_dataoffset(int d) { m_wide_dataoffset = d; }
int wide_dataoffset() const { return m_wide_dataoffset; }
SymArena arena() const
{
return static_cast<SymArena>(m_arena);
}
SymArena arena() const { return static_cast<SymArena>(m_arena); }
void initializers(int d)
{
m_initializers = d;
}
int initializers() const
{
return m_initializers;
}
void initializers(int d) { m_initializers = d; }
int initializers() const { return m_initializers; }
bool has_derivs() const
{
return m_has_derivs;
}
void has_derivs(bool new_derivs)
{
m_has_derivs = new_derivs;
}
int size() const
{
return m_size;
}
void size(size_t newsize)
{
m_size = (int)newsize;
}
bool has_derivs() const { return m_has_derivs; }
void has_derivs(bool new_derivs) { m_has_derivs = new_derivs; }
int size() const { return m_size; }
void size(size_t newsize) { m_size = (int)newsize; }
/// Return the size for each point, including derivs.
///
int derivsize() const
{
return m_has_derivs ? 3 * m_size : m_size;
}
int derivsize() const { return m_has_derivs ? 3 * m_size : m_size; }
bool connected() const
{
return valuesource() == ConnectedVal;
}
bool connected_down() const
{
return m_connected_down;
}
void connected_down(bool c)
{
m_connected_down = c;
}
bool connected() const { return valuesource() == ConnectedVal; }
bool connected_down() const { return m_connected_down; }
void connected_down(bool c) { m_connected_down = c; }
/// Where did the symbol's value come from?
///
enum ValueSource { DefaultVal, InstanceVal, GeomVal, ConnectedVal };
ValueSource valuesource() const
{
return (ValueSource)m_valuesource;
}
void valuesource(ValueSource v)
{
m_valuesource = v;
}
ValueSource valuesource() const { return (ValueSource)m_valuesource; }
void valuesource(ValueSource v) { m_valuesource = v; }
const char* valuesourcename() const;
static const char* valuesourcename(ValueSource v);
int fieldid() const
{
return m_fieldid;
}
void fieldid(int id)
{
m_fieldid = id;
}
int fieldid() const { return m_fieldid; }
void fieldid(int id) { m_fieldid = id; }
int layer() const
{
return m_layer;
}
void layer(int id)
{
m_layer = id;
}
int layer() const { return m_layer; }
void layer(int id) { m_layer = id; }
int initbegin() const
{
return m_initbegin;
}
void initbegin(int i)
{
m_initbegin = i;
}
int initend() const
{
return m_initend;
}
void initend(int i)
{
m_initend = i;
}
int initbegin() const { return m_initbegin; }
void initbegin(int i) { m_initbegin = i; }
int initend() const { return m_initend; }
void initend(int i) { m_initend = i; }
void set_initrange(int b = 0, int e = 0)
{
m_initbegin = b;
m_initend = e;
}
bool has_init_ops() const
{
return m_initbegin != m_initend;
}
bool has_init_ops() const { return m_initbegin != m_initend; }
/// Clear read/write usage info.
///
@@ -803,42 +739,15 @@ public:
}
}
int firstread() const
{
return m_firstread;
}
int lastread() const
{
return m_lastread;
}
int firstwrite() const
{
return m_firstwrite;
}
int lastwrite() const
{
return m_lastwrite;
}
int firstuse() const
{
return std::min(firstread(), firstwrite());
}
int lastuse() const
{
return std::max(lastread(), lastwrite());
}
bool everread() const
{
return lastread() >= 0;
}
bool everwritten() const
{
return lastwrite() >= 0;
}
bool everused() const
{
return everread() || everwritten();
}
int firstread() const { return m_firstread; }
int lastread() const { return m_lastread; }
int firstwrite() const { return m_firstwrite; }
int lastwrite() const { return m_lastwrite; }
int firstuse() const { return std::min(firstread(), firstwrite()); }
int lastuse() const { return std::max(lastread(), lastwrite()); }
bool everread() const { return lastread() >= 0; }
bool everwritten() const { return lastwrite() >= 0; }
bool everused() const { return everread() || everwritten(); }
// everused_in_group is an even more stringent test -- not only must
// the symbol not be used within the shader but it also must not be
// used elsewhere in the group, by being connected to something downstream
@@ -859,67 +768,44 @@ public:
m_lastwrite = last;
}
bool initialized() const
{
return m_initialized;
}
void initialized(bool init)
{
m_initialized = init;
}
bool initialized() const { return m_initialized; }
void initialized(bool init) { m_initialized = init; }
bool lockgeom() const
{
return m_lockgeom;
}
void lockgeom(bool lock)
{
m_lockgeom = lock;
// We can lock a value to a constant (at all places on all pieces of
// geometry) if it is neither interpolated nor interactively modified.
return !m_interpolated && !m_interactive;
}
bool allowconnect() const
{
return m_allowconnect;
}
void allowconnect(bool val)
{
m_allowconnect = val;
}
bool interpolated() const { return m_interpolated; }
void interpolated(bool val) { m_interpolated = val; }
int arraylen() const
{
return m_typespec.arraylength();
}
bool interactive() const { return m_interactive; }
void interactive(bool val) { m_interactive = val; }
bool noninteractive() const { return m_noninteractive; }
void noninteractive(bool val) { m_noninteractive = val; }
bool allowconnect() const { return m_allowconnect; }
void allowconnect(bool val) { m_allowconnect = val; }
int arraylen() const { return m_typespec.arraylength(); }
void arraylen(int len)
{
m_typespec.make_array(len);
m_size = m_typespec.simpletype().size();
}
bool renderer_output() const
{
return m_renderer_output;
}
void renderer_output(bool v)
{
m_renderer_output = v;
}
bool renderer_output() const { return m_renderer_output; }
void renderer_output(bool v) { m_renderer_output = v; }
// When not uniform a symbol will have a varying value under batched
// execution and must use a Wide data type to hold different values
// for each data lane executing
bool is_uniform() const
{
return m_is_uniform;
}
bool is_varying() const
{
return (m_is_uniform == 0);
}
void make_varying()
{
m_is_uniform = false;
}
bool is_uniform() const { return m_is_uniform; }
bool is_varying() const { return (m_is_uniform == 0); }
void make_varying() { m_is_uniform = false; }
// Results of a compare_op and other ops with logically boolean
// results under certain conditions could be forced to be represented
@@ -933,32 +819,14 @@ public:
// The value of forced_llvm_bool() is currently only respected during
// batched execution. Forced bools should not be coalesced with regular
// ints, only other forced bools.
bool forced_llvm_bool() const
{
return m_forced_llvm_bool;
}
void forced_llvm_bool(bool v)
{
m_forced_llvm_bool = v;
}
bool forced_llvm_bool() const { return m_forced_llvm_bool; }
void forced_llvm_bool(bool v) { m_forced_llvm_bool = v; }
bool readonly() const
{
return m_readonly;
}
void readonly(bool v)
{
m_readonly = v;
}
bool readonly() const { return m_readonly; }
void readonly(bool v) { m_readonly = v; }
bool is_constant() const
{
return symtype() == SymTypeConst;
}
bool is_temp() const
{
return symtype() == SymTypeTemp;
}
bool is_constant() const { return symtype() == SymTypeConst; }
bool is_temp() const { return symtype() == SymTypeTemp; }
// Retrieve the const float value (must be a const float!)
float get_float(int index = 0) const
@@ -1028,10 +896,12 @@ protected:
unsigned m_symtype : 4; ///< Kind of symbol (param, local, etc.)
unsigned m_has_derivs : 1; ///< Step to derivs (0 == has no derivs)
unsigned m_const_initializer : 1; ///< initializer is a constant expression
unsigned m_connected_down : 1; ///< Connected to a later/downstream layer
unsigned m_initialized : 1; ///< If a param, has it been initialized?
unsigned m_lockgeom : 1; ///< Is the param not overridden by geom?
unsigned m_allowconnect : 1; ///< Is the param not overridden by geom?
unsigned m_connected_down : 1; ///< Connected to a later/downstream layer
unsigned m_initialized : 1; ///< If a param, has it been initialized?
unsigned m_interpolated : 1; ///< Is the param overridden by geom?
unsigned m_interactive : 1; ///< May the param change interactively?
unsigned m_noninteractive : 1; ///< The param def won't modify interactively
unsigned m_allowconnect : 1; ///< Is the param allowd to connect?
unsigned m_renderer_output : 1; ///< Is this sym a renderer output?
unsigned m_readonly : 1; ///< read-only symbol
unsigned m_is_uniform : 1; ///< symbol is uniform under batched execution
@@ -1285,3 +1155,12 @@ typedef std::vector<Opcode> OpcodeVec;
}; // namespace pvt
OSL_NAMESPACE_EXIT
// Supply a fmtlib compatible custom formatter for TypeSpec.
#if FMT_VERSION >= 100000
FMT_BEGIN_NAMESPACE
template<> struct formatter<OSL::pvt::TypeSpec> : ostream_formatter {};
FMT_END_NAMESPACE
#endif
+98 -37
View File
@@ -46,7 +46,7 @@ ScopeExit print_node_counts([]() {
for (int i = 0; i < ASTNode::_last_node; ++i)
if (node_counts[i] > 0)
Strutil::print("ASTNode type {:2}: {:5} (peak {:5})\n", i,
node_counts[i], node_counts_peak[i]);
node_counts[i].load(), node_counts_peak[i].load());
});
} // namespace
#endif
@@ -1116,90 +1116,151 @@ ASTassign_expression::opword() const
OSL_ASSERT (0 && "unknown assignment expression");
return "assign"; // punt
}
// clang-format on
}
ASTunary_expression::ASTunary_expression (OSLCompilerImpl *comp, int op,
ASTNode *expr)
: ASTNode (unary_expression_node, comp, op, expr)
ASTunary_expression::ASTunary_expression(OSLCompilerImpl* comp, int op,
ASTNode* expr)
: ASTNode(unary_expression_node, comp, op, expr)
{
// Check for a user-overloaded function for this operator
Symbol *sym = comp->symtab().find(ustring::fmtformat("__operator__{}__", opword()));
Symbol* sym = comp->symtab().find(
ustring::fmtformat("__operator__{}__", opword()));
if (sym && sym->symtype() == SymTypeFunction)
m_function_overload = (FunctionSymbol *)sym;
m_function_overload = (FunctionSymbol*)sym;
}
const char *
ASTunary_expression::childname (size_t i) const
const char*
ASTunary_expression::childname(size_t i) const
{
static const char *name[] = { "expression" };
static const char* name[] = { "expression" };
return name[i];
}
const char *
ASTunary_expression::opname () const
const char*
ASTunary_expression::opname() const
{
switch (m_op) {
case Add : return "+";
case Sub : return "-";
case Not : return "!";
case Compl : return "~";
default:
OSL_ASSERT (0 && "unknown unary expression");
return "unknown";
case Add: return "+";
case Sub: return "-";
case Not: return "!";
case Compl: return "~";
default: OSL_ASSERT(0 && "unknown unary expression"); return "unknown";
}
}
const char *
ASTunary_expression::opword () const
const char*
ASTunary_expression::opword() const
{
switch (m_op) {
case Add : return "add";
case Sub : return "neg";
case Not : return "not";
case Compl : return "compl";
default:
OSL_ASSERT (0 && "unknown unary expression");
return "unknown";
case Add: return "add";
case Sub: return "neg";
case Not: return "not";
case Compl: return "compl";
default: OSL_ASSERT(0 && "unknown unary expression"); return "unknown";
}
}
ASTbinary_expression::ASTbinary_expression (OSLCompilerImpl *comp, Operator op,
ASTNode *left, ASTNode *right)
: ASTNode (binary_expression_node, comp, op, left, right)
ASTbinary_expression::ASTbinary_expression(OSLCompilerImpl* comp, Operator op,
ASTNode* left, ASTNode* right)
: ASTNode(binary_expression_node, comp, op, left, right)
{
// Check for a user-overloaded function for this operator.
// Disallow a few ops from overloading.
if (op != And && op != Or) {
ustring funcname = ustring::fmtformat("__operator__{}__", opword());
Symbol *sym = comp->symtab().find (funcname);
Symbol* sym = comp->symtab().find(funcname);
if (sym && sym->symtype() == SymTypeFunction)
m_function_overload = (FunctionSymbol *)sym;
m_function_overload = (FunctionSymbol*)sym;
}
}
const char *
ASTbinary_expression::childname (size_t i) const
ASTNode*
ASTbinary_expression::make(OSLCompilerImpl* comp, Operator op, ASTNode* left,
ASTNode* right)
{
static const char *name[] = { "left", "right" };
// If the left and right are both literal constants, fold the expression
if (left->nodetype() == literal_node && right->nodetype() == literal_node) {
ASTNode* cf = nullptr; // constant-folded result
if (left->typespec().is_int() && right->typespec().is_int()) {
int lv = dynamic_cast<ASTliteral*>(left)->intval();
int rv = dynamic_cast<ASTliteral*>(right)->intval();
switch (op) {
case Mul: cf = new ASTliteral(comp, lv * rv); break;
case Div: cf = new ASTliteral(comp, rv ? lv / rv : 0); break;
case Add: cf = new ASTliteral(comp, lv + rv); break;
case Sub: cf = new ASTliteral(comp, lv - rv); break;
case Mod: cf = new ASTliteral(comp, rv ? lv % rv : 0); break;
case Equal: cf = new ASTliteral(comp, lv == rv ? 1 : 0); break;
case NotEqual: cf = new ASTliteral(comp, lv != rv ? 1 : 0); break;
case Greater: cf = new ASTliteral(comp, lv > rv ? 1 : 0); break;
case Less: cf = new ASTliteral(comp, lv < rv ? 1 : 0); break;
case GreaterEqual:
cf = new ASTliteral(comp, lv >= rv ? 1 : 0);
break;
case LessEqual: cf = new ASTliteral(comp, lv <= rv ? 1 : 0); break;
case BitAnd: cf = new ASTliteral(comp, lv & rv); break;
case BitOr: cf = new ASTliteral(comp, lv | rv); break;
case Xor: cf = new ASTliteral(comp, lv ^ rv); break;
case ShiftLeft: cf = new ASTliteral(comp, lv << rv); break;
case ShiftRight: cf = new ASTliteral(comp, lv >> rv); break;
default: break;
}
} else if (left->typespec().is_float()
&& right->typespec().is_float()) {
float lv = dynamic_cast<ASTliteral*>(left)->floatval();
float rv = dynamic_cast<ASTliteral*>(right)->floatval();
switch (op) {
case Mul: cf = new ASTliteral(comp, lv * rv); break;
case Div: cf = new ASTliteral(comp, rv ? lv / rv : 0.0f); break;
case Add: cf = new ASTliteral(comp, lv + rv); break;
case Sub: cf = new ASTliteral(comp, lv - rv); break;
case Equal: cf = new ASTliteral(comp, lv == rv ? 1 : 0); break;
case NotEqual: cf = new ASTliteral(comp, lv != rv ? 1 : 0); break;
case Greater: cf = new ASTliteral(comp, lv > rv ? 1 : 0); break;
case Less: cf = new ASTliteral(comp, lv < rv ? 1 : 0); break;
case GreaterEqual:
cf = new ASTliteral(comp, lv >= rv ? 1 : 0);
break;
case LessEqual: cf = new ASTliteral(comp, lv <= rv ? 1 : 0); break;
default: break;
}
}
if (cf) {
delete left;
delete right;
return cf;
}
}
return new ASTbinary_expression(comp, op, left, right);
}
const char*
ASTbinary_expression::childname(size_t i) const
{
static const char* name[] = { "left", "right" };
return name[i];
}
const char *
ASTbinary_expression::opname () const
const char*
ASTbinary_expression::opname() const
{
// clang-format off
switch (m_op) {
+4
View File
@@ -832,6 +832,10 @@ public:
ASTbinary_expression(OSLCompilerImpl* comp, Operator op, ASTNode* left,
ASTNode* right);
// Special consructor wrapper that can collapse ops between literals
static ASTNode* make(OSLCompilerImpl* comp, Operator op, ASTNode* left,
ASTNode* right);
const char* nodetypename() const { return "binary_expression"; }
const char* childname(size_t i) const;
const char* opname() const;

Some files were not shown because too many files have changed in this diff Show More