Compare commits

..
90 Commits
Author SHA1 Message Date
Larry Gritz f4db549061 runner
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-10 22:40:36 -07:00
Larry Gritz 4debd96adc Set up workflows to have subsequent PR pushes cancel previous in-progress jobs
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-10 22:30:58 -07:00
Larry Gritz 30a4a95b7e Experiment: use new big runner to speed up the expensive analysis run
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-10 22:18:46 -07:00
Larry Gritz a38aa58c0e typo
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-10 22:08:46 -07:00
Larry Gritz e126a20df7 Analysis build for avx512 as well for more code coverage
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-10 22:05:08 -07:00
Larry Gritz 52cf2ee418 Improve testing coverage
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.

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.

Remove deprecated version of LLVM_Util::make_function.

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

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-10 21:54:57 -07:00
Larry Gritz 83a1e7e74b WIP: improve coverage analysis
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.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-10 18:06:54 -07:00
Larry Gritz 6069b7cfc0 Fully deprecate LLVM_Util::internalize_module_functions (#1606)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-10 18:04:57 -07:00
Dan Horák 41cc6d78db include the immintrin.h header only when needed (#1605)
The immintrin.h header is required for the implementation of the
popcount and coutr_zero function only when the Intel compiler is used.
Move the inclusion accordingly. The current state breaks build on
platforms that don't provide the header, but provide the alternative
means (gcc/clang built-ins, etc).

Signed-off-by: Dan Horák <dan@danny.cz>
2022-10-10 14:08:13 -07:00
Larry Gritz 8561a817ea Disabling dso testshade to fix coverage missing testshade.cpp (#1604)
We compile testshade.cpp twice -- one for a special "does it compile
as a DSO" check but that isn't run from the testsuite. This was
causing the coverage analysis to think nothing in testshade.cpp (at
least one copy of it) was getting run, which is technically true, and
counting all of its lines as untested for the coverage analysis. Just
exclude that funny dso build from the coverage case.

Also exclude anything in src/build-scripts from coverage analysis,
that's not code that ships, so to speak.

We're trying to chip away at untested code bit by bit to get our
coverage to over 80% of lines. We're getting close.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-10 00:06:55 -07:00
Larry Gritz cfaf643d0e Remove unused cuda variable that was warning (#1602)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-07 12:13:13 -07:00
Larry Gritz c505c4ca5f Hashing cleanup for ustrings (#1599)
Define std::hash for ustring and ustringhash, when not using an OIIO
new enough to do so.

Define std::less for ustringhash, when not using an OIIO new enough
to have operator< defined for ustringhash (will be fixed separately).

No need now for ustringHash, which is also unwisely similar to
ustringhash, just use std::hash instead.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-06 17:14:41 -07:00
Larry Gritz 318f0e488e CHANGES and bump version to 1.13.1.0 after ShaderGlobals change
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-06 15:36:14 -07:00
Steena Monteiro b22c9b7c84 Shading state uniform (#1585)
* Reduce dependency on ShadingContext and ShadingSystem objects
for accessing the ShadingSystem and consequently the ColorSystem. In its current form
it is not device-friendly.

We introduce a self-contained pvt::ShadingStateUniform that maintains a proper
state and is independent of the ShadingContext and ShadingSystem. We add an
opaque pointer to ShadingStateUniform in the ShaderGlobals structure.
Update uses of ColorSystem in opcolor.cpp to go through
ShaderGlobals::shadingStateUniform.  Also update uses of m_commonspace_synonym
and m_unknown_coordsys_error in opmatrix.cpp to go through
ShaderGlobals::shadingStateUniform.

NOTE: The ShadingStateUniform is private and an OSL implementation detail and
does not change the public interface other than adding an opaque pointer to
ShaderGlobals.

* Fixed LLVM representation to accommodate ShaderGlobals::shadingStateUniform.

* Added missing Copyright Contributors license to shading_state_uniform.h

* Removed m_commonspace_synonym data member
Moved ShadingStateUniform closer to its use in osl_prepend_matrix_from

* Fixed clang-format diffs. Added void* shadingStateUniform to ShaderGlobals in rend_lib.h. Needed for proper working.

* Added shadingStateUniform to wide_opmatrix and batched_shader_globals.h
Adjusted batched struct data layout check in codegen.

* Reordered headers to include shading_state_uniform.h with the other headers
from liboslexec

Signed-off-by: Steena Monteiro <steena.monteiro@intel.com>
2022-10-06 15:29:55 -07:00
Larry Gritz bd491d025e Git rid of the last remnants of the Cuda string_table (#1600)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-06 14:59:13 -07:00
Alex Wells 6140c72aa6 CI: address regressions with new icx compiler (#1601)
Some explicit SIMD loops were technically illegal because each lane was not truly independent, fixed by adding "reduction" clause.  Some Mask objects had to be replaced with just "int" to allow it to be specified in the reduction clause.

icx v2022.2.0 does apppear to have some regressions for large amounts of Dual code in a couple use cases, added alternative(improved) Single Statement Assignment (SSA) version of OIIO::fast_sincos which allowed unit tests to pass.  Consider updating OIIO fmath.h to use SSA coding style (which would allow this workaround to be removed).
Another regression with transform_normals was avoiding by introducing an OSL_UNLIKELY(condition) to generate a branch vs. masked execution, this change is a general improvement and should be left in.

Avoid flex_bison produced warning in osogram.cpp "variable 'osonerrs' set but not used".

Due to a number of regressions that appear to be fixed in next revision, choose to skip icx 2022.2 and continue CI for the time being with icx 2022.1 until the next release.

Because multiple (possibly newer) versions of oneapi may be installed, use a config file to specific a specific compiler and tbb version NOTE: Individual oneapi components may independent version numbering.

For centos images, use a config file to specificy a specific oneapi compiler and tbb version

Signed-off-by: Alex M. Wells <alex.m.wells@intel.com>
2022-10-06 09:44:58 -07:00
Larry Gritz 7fcdc3f71c Run analysis upon push to main
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-05 11:19:35 -07:00
Larry Gritz 22feb208c2 CI: fix analysis run after OIIO upgrade
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-05 09:27:36 -07:00
Larry Gritz ab65bbad4b CHANGES and other minor docs adjustments after the 1.12 release
Also belatedly bump the version in main to 1.13.0.3

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-02 15:45:15 -07:00
Larry Gritz 64c66949e7 CI: Improvements to the coverage analysis (#1596)
* For analysis, USE_QT=0 will disable osltoy from building (since we
  don't/can't test it in the testsuite, it's unexecuted but really
  shouldn't count against our code coverage metric).

* Exclude Imath duplicate headers from Sonar analysis.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-02 15:42:18 -07:00
Larry Gritz 2fe18079a3 Raise OIIO minimum to 2.3 (#1591)
Traditionally, OSL has supported building against the current and also
the previous supported version of OIIO, but not necessarily any older.

With OIIO 2.4 released (any day now), and OSL "main" is actually going
to be next year's supported release, it seems reasonable to change the
forward-looking development of OSL to have a minimum of OIIO 2.3,
which means that OSL-next will support OIIO 2.3, 2.4, and the
currently-in-progress 2.5 (or whatever it's called by that point).

The main reason to do this bump is because we'd like to depend on the
ustringhash class, and possibly other things we will probably be able
to easily backport to 2.3 but not to 2.2.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-30 18:23:09 -07:00
Larry Gritz e0a66c7bc6 Fix LPE leak in error condition (#1594)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-30 17:03:31 -07:00
Larry Gritz e4e5088ed6 LLVM 15.0 support (#1592)
* A variety of changes to get a clean build and passing tests when
  using LLVM 15.0.

* I've noticed problems when using LLVM 15 but building with earlier
  clang, so the cmake scripts now print a warning in that case, so if
  users encounter trouble they have a hint about what to do to fix it.

* For our CI tests on Mac, force the MacOS-11 test to use llvm 14,
  and the MacOS-12 test to use llvm 15.

IMPORTANT TO-DO / CAVEATS:

1. When doing JIT at optlevel 12 or 13, I had to disable a number of
   passes that don't seem to exist anymore in LLVM 15. This is enough
   to get it working, and to be honest, I don't know if anybody uses
   these opt levels.  But we need to revisit this, because I don't
   know if there these are cases where the names of the passes merely
   changed or that new passes take their place (in which case we
   should add the new passes, not stop after merely disabling the
   deprecated ones). For that matter, optlevel modes 11, 12, 13 are
   supposed to match what clang does for -O1, -O2, -O3, and that
   changes from one release to the next, so we should probably revisit
   this list and make sure it's matching clang's current choices
   (which I assume are crafted and periodically revised by clang's
   authors).

2. LLVM 15 switches to "opaque pointers". It still supports typed
   pointers...  for now. But as you can see in the diffs, I had to
   disable a variety of deprecation warnings and take some other
   actions to put LLVM 15 in the old "opaque ptr" mode to match our
   use of LLVM <= 14. But this is only temporary, because the typed
   pointer mode is expected to be removed entirely in LLVM 16. So at
   some point in the next few months, we are going to need to support
   opaque pointers in our use of LLVM. (Also note: for a while, we're
   going to have a bunch of ugly `#if` guards or other logic to
   support both opaque pointers for users with llvm >= 16 and also
   typed pointers for users with llvm <= 14, until such time as our
   LLVM minimum is at least 15, which I expect is not a reasonable
   assumption for at least a couple years.)

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-29 10:10:58 -07:00
Larry Gritz aea281dcad Fix memory leaks found by static analysis in leparse.cpp (#1593)
Several places in leparse.cpp were found by static analysis to have
memory leaks -- results of calling _parse() that, in the case of
early exists in error conditions, never got deleted.

I also did some other modernization: changed NULL to nullptr, changed
some loops to more compact range-for, utilize some Strutil helpers
that will be more efficient than the alternative std::string
manipulation.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-29 09:57:19 -07:00
Larry Gritz b5aba16147 OSL_ALLOCA (#1589)
We use OIIO_ALLOCA in many places. Make an OSL version and put it
in platform.h.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-27 15:31:12 -07:00
Larry Gritz 4ba1678561 Fixes to compile with clang 15 (#1586)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-27 14:55:29 -07:00
Larry Gritz 8417f8eb04 CI: Move clang-format test to main section (#1588)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-27 11:24:39 -07:00
Larry Gritz 55029e388f Make testshade --help print texturesystem options and hardware info (#1584)
This was meant to work all along, which is why this patch is so small!

But a tiny detail -- not explicitly passing info about the `--help`
argument -- made ArgParse substitute its own default, which exits
after printing the usage info. But, as I apparently meant to do all
along, if you specify it explicitly, you get to handle it, and the way
we handled it alsp printed the extra information.

Anyway, with this patch, `testshade --help` not only prints all the
testshade command options, but also it prints some information at the
end about some of the build settings of OSL, versions of key
dependencies, hardware info, and a run-down of the ShadingSystem
options. This can be helpful for debugging.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-21 17:13:34 -07:00
Larry Gritz 89c033bda9 Docs: Some minor updates to CONTRIBUTIONS and INSTALL docs (#1582)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-21 16:33:13 -07:00
Mark Sisson 0b57ae6b03 add .envrc to .gitignore (#1583)
direnv (https://github.com/direnv/direnv) can be used for local developer workflow enhancements.  direnv uses .envrc file for configuration.  Because .envrc is usually specific to a developer workflow, it is generally not committed.

Signed-off-by: Mark Sisson <5761292+marksisson@users.noreply.github.com>
2022-09-20 15:59:32 -07:00
Larry Gritz 6588caafa6 CI: Set up a dynamic analysis test using address and leak sanitizers (#1581)
- There are a handful of tests we disable entirely with because they
  are irrelevant or just cannot be made to be clean (and that's ok).

- Tests with sanitizers run slow, so we increase timeouts, and also
  set AA to 1 for render tests to speed them up.  We rig it so a
  non-matching output won't fail, and that's ok because every other CI
  test is checking the results; here we have no reason to believe
  results will differ from other tests, we just need to run with
  sanitizers turned on.

- In testing.cmake, we rig texture tests to disable the leak
  sanitizer, because we can't eliminate some completely benign leaks
  from the texture system, and because they are called from JITed
  code, we don't get a clean stack trace of things that happen in OIIO
  and therefore we just can't enumerate the allowed exceptions. So we
  trust that OIIO itself tests the texture system adequately and is
  able to ignore the benign "leaks."

- We already submitted PRs and merged the little fixes that were
  discovered by enabling address and leak sanitizers. This is just the
  final bit to turn it on for CI runs from here on out.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-19 18:28:56 -07:00
Chris Hellmuth b11fb97626 Docs: Minor spec typos (#1580)
* Fix minor spec typos

Signed-off-by: Chris Hellmuth <chellmuth@gmail.com>
2022-09-15 13:47:53 -07:00
Larry Gritz 7a885c68b6 CHANGES and designate this spot as 1.13.0.2
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-13 15:25:10 -07:00
Larry Gritz 32278d3f77 Build: Make the version number be a cmake cache variable (#1579)
Rather than specify the version in the usual project() statement,

    project (OSL VERSION 1.13.0.0 ...)

this patch decouples it

    set (OSL_VERSION "1.13.0.0" CACHE STRING "Version")
    project (OSL VERSION ${OSLVERSION} ...)

thus allowing the possibility of overriding the version number at
build confuguration time (`cmake -DOSL_VERSION=3.1.4.1`).

This should be used with extreme caution. Probably never used by most
people. I don't need to describe all the ways that things can go
sideways if you make your build of x.y.z.w actually be arbitrarily
different from the x.y.z.w that everyone else uses and that is
documented.

That said, there are two scenarios I have in mind for which this
ability is very useful:

1. Sometimes, we add or deprecate API features "in advance" by having
   an `#if` enable or disable code based on the version, essentially
   putting in place changes that can't be enabled yet because they
   would break compatibility rules, but we want to integrate the code
   now and have it become active upon reaching a particular future
   version in which that incompatibility will be allowed. The version
   number override makes it easy to test this by quickly doing a build
   "as if" we had already bumped the version number to see what will
   happen when we actually do.

2. Every once in a while we need to do an internal build that, to
   conform to version compatibility rules, needs to appear to still be
   part of a past version family. This lets individual sites play some
   games with version number overrides rather than have to create new
   branches and tags for certain one-off internal releases.

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

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-13 15:06:49 -07:00
Larry Gritz c8dd33f5a3 Bug fix: assigning init-op param its default value as instance got lost (#1578)
This is a tricky situation to describe. Consider this shader:

    shader test (float A = 0.5,
                 float B = A)
    {
        printf("A = %g, B = %g\n", A, B);
    }

By default, A is 0.5 and B gets A's value, also 0.5. If you give A a
different instance value, like 1.0, then B will also get the same
value, they'll both be 1.0.  If you give B an instance value, that
will be used for B rather than copying A's value, like this:

    $ testshade  -param B 1.0 -shader test test
    A = 0.5, B = 1

But there is a corner case bug: if we assign B an instance value of
0.0, it will incorrectly fall into a special case where it thinks it
gets a default value, only coincidentally because 0.0 is in an unused
slot for the default value (unused because it has no default -- its
default comes from "init ops", that assignment).

    $ testshade  -param B 0.0 -shader test test
    A = 0.5, B = 0.5

!!!

Reading the patch should be self-explanatory for what the bug is and
how we fix it.

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

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-12 16:49:49 -07:00
Larry Gritz 1a7670600c Fix memory leak in ASTvariable_declaration (#1576)
* Fix memory leak in ASTvariable_declaration

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-08 21:02:15 -07:00
Larry Gritz a6ff40b0b2 Docs: RELEASING.md (#1572)
I've tried to write a complete set of step-by-step instructions for
everything about how to coordinate and deploy a release. This is a
living document, we will amend over time. I'm sure there must be
things I've forgotten.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-08 18:50:49 -07:00
Larry GritzandAlex Wells 54cf8b209c Fix overrunning allocation region in debug common_ancestor_between (#1577)
Signed-off-by: Alex Wells <alex.m.wells@intel.com>
Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Alex Wells <alex.m.wells@intel.com>
2022-09-08 10:12:21 -07:00
Larry Gritz 2e941e612f Batched analysis: ReadEvent remove uninitialized members (#1575)
The little ReadEvent class had two members that are never set when
OSL_DEV is not defined, nor are they accessible (the accessor
functions also are disabled based on OSL_DEV). It looked to the static
analyzer like the data members were uninitialized, which they
were. Add OSL_DEV guards around the declarations of those members as
well, so they aren't even present in the struct when not needed for
this debugging mode.

Food for thought: another alternative is to keep the members but just
remove the OSL_DEV guards entirely -- just let the two int data
members be used all the time, not just for OSL_DEV. It's too small to
have any perf penalty, and it unclutters the declaration by removing
all those `#ifdef` lines.

For that matter, I also wonder if there's any real point to having
private members and accessor functions for this tiny internal-only
class, and maybe it's better to just let it be compact declaration
of a simple `struct` with three directly accessible data members.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-07 22:54:01 -07:00
Larry Gritz 051f2bfe2f Rewrite confusing loop in testshade for clarity (#1574)
In testshade, there was a "loop" that wasn't really a loop, and it
was getting flagged by static analysis as being fishy. This patch
rewrites it as an "if".

Also take the opportunity to change from stream output to OSL::print
formatted output.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-06 11:23:48 -07:00
Larry Gritz f13463e6b6 Build/test: parameterize the timeout for expensive tests (#1571)
We had hard-coded longer allowable timeouts for particular testsuite
tests. But for the static analysis runs, it takes extra long and we
need a way to tell it to increase the timeouts even more, and to
exclude the longest running tests from the analysis coverage run (it's
not necessary to run those tests, they don't increase coverage enough
to justify being an hours long run).

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

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-04 18:00:50 -07:00
Larry Gritz cd2fa1650d Rename compiler-generated constants non-sequentially (#1570)
In the course of our runtime optimization of shader networks, we
generate lots of new constant symbols (for example, as we optimize an
"a = b + c" into "a = newconst" if b and c can be determined to be
constants). The new constants are named with a numerical suffix doled
out in a sequental manner.

I've always thought that maybe it would be helpful for me when
debugging optimizer output if the name of the symbol also revealed the
value of the constant it held (when possible). Never did anything
about it.

Now it turns out that this has an application for JIT to PTX, where
the PTX cache can save compilation-to-PTX time if it encounters LLVM
IR that is exactly the same as it has seen before and is cache.  If
the constants are generated in a different order, it generates
non-functional, purely text differences in the code we generate, and
this means the PTX cache doesn't function as efficiently as possible.

So this change alters the compiler-generated constant naming for two
cases: int constants, and string constants. The int constants append
the value of the integer (using '_' instead of '-' for negatives), and
the string constants append the hexidecimal value of the ustring hash
for that string. In both cases it does this without using or
incrementing the `m_next_newconst` counter that it uses to
sequentially name the other types that can't easily encode the value
to generate a unique name.

It's really to help the PTX cache, but as a side benefit, it will
be slightly easier for me to make sense of the optimized code when
I need to read it with my own eyes while debugging.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-02 10:07:13 -07:00
Larry Gritz c23da3df34 CHANGES
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-01 18:39:03 -07:00
Larry Gritz 95c1408d27 Rebuild PDF docs
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-01 18:33:19 -07:00
Larry Gritz e278f4c24a Deal with deprecated bit_cast function in OIIO 2.5 (#1569)
Today's branching of OIIO 2.4 and subsequent changing of its master
branch to think it's "2.5" seems to have triggered an automatic fuse
that annotates a particular function in OIIO as deprecated for version
2.5 and beyond. OSL was still calling the old version, so some
immediate changes are necessary to call the correct new name when
using a new OIIO.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-09-01 15:32:42 -07:00
Larry Gritz 365f2c4b2b Sonar static analysis improvements (#1567)
* Exclude osltoy from coverage analysis, since we don't have a way to
  run it from CI
* Run batch shading for analysis to get better code coverage
* llvm_gen_select: extra check that we can't overrun memory of cond[]

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-31 16:56:19 -07:00
Larry Gritz ac59af9bd1 Make sure all clang-format changes are in .git-blame-ignore-revs (#1568)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-31 16:55:48 -07:00
Larry Gritz 9d5d6203b9 New closure docs (#1564)
* Change the languagespec to document the new MaterialX-synchronized
  closures.

* Document the old ones as "deprecated" -- still supported for 1.x but
  assumed to be on the slate for removal in OSL 2.x.

* Change stdosl.h so that the new closures, instead of being seen only
  if MATERIALX_CLOSURES is defined, to being enabled by default, but
  (for now) can be disabled if NO_MATERIALX_CLOSURES is defined.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-31 14:22:06 -07:00
Larry Gritz 1a66a2b8dd CI: test against python 3.10, gcc 12, latest fmt, update INSTALL (#1565)
Mostly, updating the "latest versions" test to the current latest
versions.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-31 14:21:08 -07:00
Chris Hellmuth 3b97ecef47 Generate deterministic ptx for OptiX cache hits (#1566)
Removing the suffix ids and callseq comments generated by global counters
leads to deterministic ptx in a multithreaded environment.

Signed-off-by: Chris Hellmuth <chellmuth@gmail.com>
2022-08-30 10:56:55 -07:00
Larry Gritz ed5b5a2a0c Simplify clang-format call now that we include virtually everything (#1562)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-28 12:52:48 -07:00
Larry Gritz 37cbab5bad Sonar warning fixes and improvements (#1563)
* Minor changes to fix a couple more warnings given by SonarCloud
  static analysis.

* Get the code coverage enabled, it wasn't running properly.

* testrender: allow secret TESTRENDER_AA to override command line --aa

* runtest.py: allow secret OSL_TESTSUITE_SKIP_DIFF to force skipping
  the reference comparison step.

* For analysis run, set TESTRENDER_AA=1 to keep the tests from being
  prohibitively expensive, and OSL_TESTSUITE_SKIP_DIFF=1 to keep it
  from failing because the aa=1 images are different.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-28 12:52:07 -07:00
Larry Gritz 11127b72b5 Fix OptiX + clang14 issue with duplicate symbols (#1561)
We had been using clang/llvm 12 and when trying out 14 I started
getting test failures with OptiX complaining about duplicate
symbols. They all seemed to be the things we declared as
OSL_CONSTANT_DATA. It looks like there's a difference in llvm 12 vs 14
in how the generated PTX marks its symbol visibility.

The solution (thanks to a clever suggestion by Alex Conty) was just to
enclose those declarations in anonymous namespaces. Works like a
charm!

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-27 15:47:47 -07:00
Larry Gritz d5d87f1e64 More detailed messages when encountering failed OptiX calls (#1560)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-26 18:22:54 -07:00
Larry Gritz fa6f228b87 Fix minor bugs and warnings uncovered by SonarCloud (#1556)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-26 14:01:05 -07:00
Larry Gritz 21f1a2f47e Fixes needed to support OptiX 7.4 (#1559)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-24 11:34:17 -07:00
Larry Gritz 5be7c6bd4e clang-format: the very last piece of the puzzle (#1555)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-23 13:32:31 -07:00
Christopher Kulla 9f8e92ce93 Add missing cases for MaterilaX closure refraction index detection (#1557)
This allows the refraction index to be detected even if a medium closure
is not present. Additionally, the medium detection now traverses layer()
closures.

Signed-off-by: Chris Kulla <ckulla@gmail.com>
2022-08-23 00:03:59 -07:00
Larry Gritz 4bbaca7fe5 Testing: Try to fix testsuite/render-microfacet failures (#1558)
There seems to be just a teensy bit of nondeterminism or
platform-variance in this one test that we haven't tracked down the
source of yet, that moves some specular fireflies around. Smells like
maybe an uninitialized variable somewhere in testrender? Because it
doesn't happen on any other test and we haven't detected it in our
real renderer, we don't currently suspect that it's an actual error
in oslexec.

Big hack: Re-run failed "render" tests up to 5 additional times before
giving up.

This makes me feel dirty. But it makes tests pass for now. Eventually we
will find the embarrassing testrender bug that is responsible for the
occasionally different specular sampling noise.

Also slightly bump up the error tolerance for this test.

Also add one alternative that seems to frequently pop up.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-22 14:38:27 -07:00
Larry Gritz cf1b4ef3e6 CI: For Mac, test python 3.9 for MacOS11, and 3.10 for MacOS12 (#1554)
This cleans up some recently-failing CI tests.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-20 22:23:16 -07:00
Larry Gritz c3e36affa8 CHANGES and other misc docs fixups
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-20 17:16:11 -07:00
Larry Gritz e9a614ba53 Bump patch level 2022-08-19 19:10:20 -07:00
Larry Gritz d57a462462 GPU string fix -- needed missing cast (#1553)
Fix slightly incorrect code generation when getting a string address
for GPU.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-19 14:21:57 -07:00
Larry Gritz ac114aded4 Fix typo error that prevented correct typecheck of ternary (#1552)
Didn't properly detect the disallowed use of arrays for the false
clause because we checked `t` twice.

Yay for static analysis!

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-14 22:08:51 -07:00
Larry Gritz 74fc27de12 Try to enable Sonar Cloud static analysis (#1551)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-12 08:25:13 -07:00
Larry Gritz 826b6767c9 Spell check comments (#1550)
Yay for "codespell"

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-03 20:44:27 -07:00
Larry Gritz 89d5db2b5c Another round of clang-format (#1540)
* Another round of clang-format

* Bump the standard clang-format we use for CI from clang11 to clang14.
  This will make some minor additional changes.

* Due to a mismatched target name, we weren't actually checking the
  formatting in CI on all the files we thought we were, and therefore
  not assuring that certain code was correctly formatted. So there is
  some fixup needed, which is included here.

* And a bunch of files we didn't try to do before, either.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-03 10:05:33 -07:00
Alejandro Conty 1dd33050da Switch testrender to cone tracing (#1543)
The idea is to stop propagating derivs through BSDFs, which we
never did properly. Instead we trace rays with radius + spread,
which we turn into OSL derivs in SG when we hit a surface. Then
when bouncing off a surface we use the BSDF roughness to set the
spread. In addition we also:

  * Return BSDF samples/eval as a small struct Sample(). This
    avoids output parameters in the methods.
  * Stop passing a full ShaderGlobals to the BSDF methods. Pass
    a viewing direction wo instead so they could run in a simpler
    context.

Signed-off-by: Alejandro Conty <aconty@imageworks.com>
2022-08-02 10:56:07 -07:00
Larry Gritz 0879638dda Testing: Adjust comparison thresholds to account for platform diffs (#1549)
Also fix a CI test label -- we had a duplicate.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-02 09:46:35 -07:00
Christopher Kulla 8a7b9b96ba Implement MaterialX medium closure and use it to drive the refraction closures (#1547)
This simplifies the logic around the ior which drives reflection/transmission (fresnel effect)
from the ior which drives refraction (and total internal reflection). Setting both iors equal to each other
gives the expected physical behavior.

Also tweak the bsdf constructor to support variadic arguments which simplifies a bunch of code.

Add a new test to validate the refractive version of generalized_schlick_bsdf.

Signed-off-by: Chris Kulla <ckulla@gmail.com>
2022-08-02 06:09:25 -07:00
Christopher Kulla 23ea0644f8 Add furnace tests for MaterialX closures (#1542)
Implement get_albedo for the sheen closure, based on fit derived by the MaterialX team

Add optional mode to testrender to visualize the result of the get_albedo method. This can be useful for validation of the get_albedo method.

Signed-off-by: Chris Kulla <ckulla@gmail.com>
2022-08-01 15:25:31 -07:00
Larry Gritz bd6d856b0e Increase error threshold for tests (#1546)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-08-01 07:46:26 -07:00
Christopher Kulla 6424177e3a Implement microfacet based MaterialX closures (#1541)
* Implement reflective microfacet based MaterialX closures

Add test cases for dielectric, conductor and generalized schlick closures

Signed-off-by: Chris Kulla <ckulla@gmail.com>

* Implement refraction case in microfacet closures

Signed-off-by: Chris Kulla <ckulla@gmail.com>

* Update reference images

Signed-off-by: Chris Kulla <ckulla@gmail.com>

* Relax diff threshold on render tests

Signed-off-by: Chris Kulla <ckulla@gmail.com>
2022-08-01 07:09:28 -07:00
Larry Gritz 0b92d2b03b Label ci jobs better (#1545)
This was resulting in confusing artifact names for the Intel compiler
cases.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-07-31 16:29:58 -07:00
Larry Gritz bf04610296 Fix error message for texture-errormsg test (#1544)
It printed the u,v coordinates where the error was first discovered.
This is not necessarily deterministic, of course!

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-07-30 04:32:56 -07:00
Adrien Herubel ff9560f401 Layer closure implementation in testrender (#1538)
* Add support for layer closure with dielectric reflections as top layers, and a test with nested layer closures

* Add support for sheen in the layer closure

Signed-off-by: Adrien Herubel <adrien.herubel@autodesk.com>
2022-07-24 14:27:56 -07:00
Adrien Herubel e0d6a21438 Missing documentation for the exponent parameter in the generalized_schlick_bsdf, and missing storage for the parameter (#1539)
Signed-off-by: Adrien Herubel <adrien.herubel@autodesk.com>
2022-07-24 11:29:40 -07:00
Christopher Kulla da794de6fd Implement MaterialX closure sheen_bsdf (#1537)
Signed-off-by: Chris Kulla <ckulla@gmail.com>
2022-07-20 14:12:46 -07:00
Christopher Kulla a1e941c43b Implement MaterialX closure burley_diffuse_bsdf (#1536)
Signed-off-by: Chris Kulla <ckulla@gmail.com>
2022-07-20 10:52:55 -07:00
Christopher Kulla 3bb41960fd Implement basic support for MaterialX closures in testrender (#1533)
* Extend the bsdf interface in testrender to use Color3 instead of float in preparation for MaterialX closures which are almost all tinted

  * Add stub parameters and IDs for all MaterialX closures

  * Register all MaterialX closure types

  * Implement most MaterialX closures, reusing the existing implementations for now

This commit is mainly intended to do the busy work of adding the new closures, no new BSDFs are actually implemented yet. This means that some of
the closures are handled in a very rudimentary way, ignoring some key parameters. The intent is to improve support for these over time.

Signed-off-by: Chris Kulla <ckulla@gmail.com>
2022-07-19 09:05:20 -07:00
Christopher Kulla 95fa78d3fd Modernize sampler in testrender (#1534)
The sampler implementation in testrender was very close to the 2020 article from Brent Burley. This patch
catches up to best practices, including a faster owen scrambler from Nathan Vegdahl and recognizing that
the index scrambling can be achived by the same owen scrambler method (which saves a bunch of logic and runs
faster). Finally, avoid the redundant bit reversals and use compiler intrinsics when available to benefit
from hardware instructions (for ARM or GPUs). Finally the integer hash constants were updated to the latest
from the hash prospector project.

While more optimizations are certainly possible, this is a reasonable balance between quality and speed.

Update reference images for new sampler

Signed-off-by: Chris Kulla <ckulla@gmail.com>
2022-07-18 23:22:51 -07:00
Larry Gritz eff3dede3a Mark DCO task as long since done (#1532)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-07-18 08:53:45 -07:00
Larry Gritz 7b4c7cffd7 GPU string overhaul (#1531)
* GPU string overhaul

Big string cleanup, yet again, for GPU. We still had this tricky
double indirection happening with strings for OptiX -- the string was
a pointer to a "global", which in turn held the hash. No, throw all
that out.  Just directly store strings as the ustring hash on
OptiX. No extra indirection. Many fewer differences between how things
are handled on OptiX versus CPU (except for the fact itself that the
"string" holds the hash rather than the char*).

Some details worth noting:

* LLVM_Util loses "type_string()" and calls it "type_ustring()" to
  emphasize it's the type we're using to represent a ustring, and
  definitely not a C or C++std string. Also, LLVM_Util itself now lets
  the caller tell it whether it prefers that the representation of a
  ustring be the charptr or the hash, and then handles most of the
  details internally. The BackendLLVM, then, makes that decision early
  on, charptr for CPU and hash for GPU.

* Several more spots in LLVM_Util and BackendLLVM have been plumbed to
  pass around llvm IR SSA variable names to try to make the resulting
  LLVM IR more readable when I'm trying to debug it. (This was
  strictly debugging scaffalding aid for me, but comes along for the
  ride because it's useful to keep.) I also added a
  BackendLLVM::llnamefmt to format strings, which only does the
  formatting when the shading system knows it's going to save the IR
  for inspection, and otherwise (that is, in production) it does not
  do the string formatting or pass the names along, so it's not doing
  all that string manipulation when no human is going to be looking at
  the IR dumps.

* A lot of clunky OptiX-only code disappears.

* Some side effects of my reducing complexity of the IR as I debugged:
  there were times we were generating redundant pointer casting in the
  IR, such as grabbing a pointer, then casting it to a void*, then
  casting back to some other kind of pointer. In some cases I reduced
  that quite a bit. Again, this was mostly just a scramble to make the
  IR more readable while I debugged, but it probably has a minor
  performance gain as well since it reduced somewhat the sheer amount
  of IR we generate and pass to the optimizer and JIT.

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

* Remove register_string entirely from RendererServices

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

* Remove more register_string remnants

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

* comment typo

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-07-13 08:36:12 -07:00
Adrien Herubel 8281721bde Fix permission error and build errors when running serialize-bc.py on Linux (#1527)
Signed-off-by: Adrien Herubel <adrien.herubel@autodesk.com>
2022-07-06 08:55:50 -07:00
Larry Gritz 2ece55aa97 Security policy fixes (#1529)
* Set up a SECURITY.md explaining how to confidentially report
  vulnerabilities.

* Create scorecards.yml workflow to run OSSF scorecard to check supply
  chain security issues.

* Use exact SHA's for actions versions to guard against hijacked
  actions repos that might try to substutite something else at the
  version tag we use.

* Make sure actions we use don't get write perms on our repo.

* Tried to use harden-runner action to ensure no actions on the runner
  overwrite source code or have unauthorized outgoing net connections
  during the GHA run, but currently leaving it disabled because of too
  many false positives -- it flags every dependency download as a case
  of altering source code. Which it technically is, but it doesn't
  matter for any jobs that aren't producing any artifacts that will be
  consumed or relied on by users.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-06-30 17:23:39 -07:00
Larry Gritz 88c471a315 Allow naming of llvm symbols for many ops (#1530)
Most LLVM API IR calls that generate ops allow an optional name of the
llvm symbol that will hold the result of the operation. By default, it
will make one up, such as "%37", "%38", etc. Needless to say, these
are difficult to understand when reading volumes of IR dumped for
debugging purposes.

So in this patch, I'm starting to expose the ability for our own code
to pass names through our wrapper functions. I needed this for some
deep debugging.

I haven't instrumented the entire set, just trying it on for some of
the specific areas I needed to debug. But this is a useful first step.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-06-30 16:03:53 -07:00
Adrien Herubel 11afddc8da Remove unwanted characters causing compilation errors in the MaterialX closure definitions (#1528)
Signed-off-by: Adrien Herubel <adrien.herubel@autodesk.com>
2022-06-24 11:15:59 -07:00
Larry Gritz f7cac87979 Remove OptiX 6 support (#1524)
This makes OptiX 7.0 the minimum version we accept, and greatly
simplifies a lot of code we were separately maintaining for 6 and 7.

This will go into main AFTER the release branch for 1.12 is split off.
The dropping of OptiX 6 will be a 1.13 (or whatever we call it) change.

Don't build the optix modules at all when not USE_OPTIX.
Totally remove stringtable.
Other simplifications stemming from these.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-06-20 16:18:40 -07:00
Larry Gritz 5401e8417b Bump version to 1.13 after branching for 1.12 (#1523)
Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-06-20 11:14:38 -07:00
Larry Gritz c61a85e217 Remove confusing licensing comment (#1521)
The implementation of simplex noise we've been using is public domain,
but looks like when we pasted the license notice into our repo, there
was one stray sentence (probably left over from an earlier license
scheme Stefan Gustavson used?) that makes reference to GPL. But the
software and its repo are NOT -- it's very clear that it's public
domain: https://github.com/stegu/perlin-noise/blob/master/LICENSE.md

So remove this confusing sentence.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-06-20 11:09:01 -07:00
157 changed files with 1812 additions and 5428 deletions
+16 -4
View File
@@ -12,7 +12,7 @@ on:
# - cron: "0 0 * * 0"
push:
branches:
# - master
- main
- '*analysis*'
# Allow manual kicking off of the workflow from github.com
workflow_dispatch:
@@ -37,10 +37,12 @@ jobs:
include:
- desc: sonar gcc9/C++14 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
nametag: static-analysis-sonar
os: ubuntu-latest
os: ubuntu-20.04-8c-32g-300h
# os: ubuntu-latest
vfxyear: 2022
vfxsuffix: -clang13
cxx_std: 14
openimageio_ver: master
python_ver: 3.9
pybind11_ver: v2.9.0
simd: avx2,f16c
@@ -58,7 +60,7 @@ jobs:
TESTRENDER_AA=1
OSL_TESTSUITE_SKIP_DIFF=1
CTEST_TEST_TIMEOUT=1200
OSL_CMAKE_FLAGS="-DOSL_TEST_BIG_TIMEOUT=1200"
OSL_CMAKE_FLAGS="-DOSL_TEST_BIG_TIMEOUT=1200 -DUSE_QT=0"
CTEST_EXCLUSIONS="broken|noise-reg.regress|noise-gabor-reg.regress"
runs-on: ${{ matrix.os }}
@@ -68,11 +70,14 @@ jobs:
CXX: ${{matrix.cxx_compiler}}
CC: ${{matrix.cc_compiler}}
CMAKE_CXX_STANDARD: ${{matrix.cxx_std}}
USE_SIMD: ${{matrix.simd}}
FMT_VERSION: ${{matrix.fmt_ver}}
OPENEXR_VERSION: ${{matrix.openexr_ver}}
OPENIMAGEIO_VERSION: ${{matrix.openimageio_ver}}
PYBIND11_VERSION: ${{matrix.pybind11_ver}}
PYTHON_VERSION: ${{matrix.python_ver}}
USE_BATCHED: ${{matrix.batched}}
USE_SIMD: ${{matrix.simd}}
PARALLEL: 24
# DEBUG_CI: 1
steps:
# We would like to use harden-runner, but it flags too many false
@@ -99,6 +104,13 @@ jobs:
run: |
${{matrix.setenvs}}
src/build-scripts/ci-startup.bash
- name: Remove existing OIIO
if: matrix.openimageio_ver != ''
run: |
sudo rm -rf /usr/local/include/OpenImageIO
sudo rm -rf /usr/local/lib*/cmake/OpenImageIO
sudo rm -rf /usr/local/lib*/libOpenImageIO*
sudo rm -rf /usr/local/lib*/python3.9/site-packages/OpenImageIO*
- name: Dependencies
run: |
${{matrix.depcmds}}
+39 -52
View File
@@ -20,13 +20,16 @@ on:
- '**.rst'
- '**.tex'
schedule:
# Full nightly build, for the main project repo (not for forks)
# Full nightly build
- cron: "0 6 * * *"
if: github.repository == 'AcademySoftwareFoundation/OpenShadingLanguage'
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:
@@ -36,20 +39,20 @@ jobs:
fail-fast: false
matrix:
include:
- desc: gcc6/C++14 llvm9 py2.7 boost1.66 exr2.3 oiio2.3 sse2
- desc: gcc6/C++14 llvm9 py2.7 boost1.66 exr2.3 oiio2.2 sse2
nametag: linux-vfx2019
os: ubuntu-latest
container: aswftesting/ci-osl:2019-clang9
vfxyear: 2019
vfxsuffix: -clang9
cxx_std: 14
openimageio_ver: v2.2.17.0
openimageio_ver: v2.3.17.0
python_ver: 2.7
pybind11_ver: v2.4.2
- desc: clang9/C++14 llvm9 oiio-release boost1.66 avx2 exr2.3 py2.7
nametag: linux-clang9-llvm9
os: ubuntu-20.04
container: aswftesting/ci-osl:2019-clang9
os: ubuntu-18.04
vfxyear: 2019
vfxsuffix: -clang9
cc_compiler: clang
cxx_compiler: clang++
cxx_std: 14
@@ -60,43 +63,41 @@ jobs:
- 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
container: aswftesting/ci-osl:2019-clang10
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
OPENIMAGEIO_CMAKE_FLAGS=-DBUILD_FMT_VERSION=8.1.1
setenvs: export OSL_CMAKE_FLAGS="-DUSE_OPTIX=1" OPTIX_VERSION=7.0
- desc: gcc6/C++14 llvm10 py3.7 boost1.70 exr2.4 oiio2.2 sse4
nametag: linux-vfx2020
os: ubuntu-latest
container: aswftesting/ci-osl:2020
vfxyear: 2020
cxx_std: 14
openimageio_ver: v2.2.17.0
openimageio_ver: v2.3.17.0
python_ver: 3.7
pybind11_ver: v2.5.0
simd: sse4.2
setenvs: export CONAN_LLVM_VERSION=10.0.1
- desc: gcc9/C++17 llvm11 py3.7 boost1.73 exr2.5 oiio2.3 avx2 batch-b8avx2
- desc: gcc9/C++17 llvm11 py3.7 boost1.73 exr2.5 oiio2.2 avx2 batch-b8avx2
nametag: linux-vfx2021
os: ubuntu-latest
container: aswftesting/ci-osl:2021-clang11
vfxyear: 2021
vfxsuffix: -clang11
cxx_std: 17
openimageio_ver: v2.2.21.0
openimageio_ver: dev-2.3
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 oiio-rel avx2
- desc: gcc9/C++17 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
nametag: linux-vfx2022
os: ubuntu-latest
container: aswftesting/ci-osl:2022-clang13
vfxyear: 2022
vfxsuffix: -clang13
cxx_std: 17
openimageio_ver: release
python_ver: 3.9
@@ -106,8 +107,8 @@ jobs:
- desc: clang12/C++17 llvm12 oiio-master boost1.73 exr3.1 py3.9 avx2 batch-avx512
nametag: linux-clang12-llvm12-batch
os: ubuntu-latest
container: aswftesting/ci-osl:2022-clang12
vfxyear: 2022
vfxsuffix: -clang12
cxx_std: 17
openimageio_ver: master
python_ver: 3.9
@@ -115,11 +116,11 @@ jobs:
simd: avx2,f16c
batched: b8_AVX2,b8_AVX512,b16_AVX512
setenvs: USE_OPENVDB=0
- desc: icc/C++17 llvm14 py3.9 boost1.76 exr3.1 oiio-master avx2
- desc: icc/C++17 llvm13 py3.9 boost1.76 exr3.1 oiio-master avx2
nametag: linux-icc
os: ubuntu-latest
container: aswftesting/ci-osl:2022-clang14
vfxyear: 2022
vfxsuffix: -clang13
cc_compiler: icc
cxx_compiler: icpc
cxx_std: 17
@@ -132,11 +133,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 llvm14 py3.9 boost1.76 exr3.1 oiio2.3 avx2
- desc: icx/C++17 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
nametag: linux-icx
os: ubuntu-latest
container: aswftesting/ci-osl:2022-clang14
vfxyear: 2022
vfxsuffix: -clang13
cc_compiler: icx
cxx_compiler: icpx
cxx_std: 17
@@ -147,24 +148,13 @@ jobs:
simd: avx2,f16c
batched: b8_AVX2_noFMA
setenvs: export OSL_CMAKE_FLAGS="-DSTOP_ON_WARNING=OFF" USE_OPENVDB=0
- desc: gcc11/C++17 llvm15 py3.10 boost1.80 exr3.1 oiio-rel avx2
nametag: linux-vfx2023
os: 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: oldest everything gcc6/C++14 llvm9 py2.7 boost1.66 oiio2.3 no-simd exr2.3
- desc: oldest everything gcc6/C++14 llvm9 py2.7 boost1.66 oiio2.2 no-simd exr2.3
nametag: linux-oldest
os: ubuntu-latest
container: aswftesting/ci-osl:2019-clang9
vfxyear: 2019
vfxsuffix: -clang9
cxx_std: 14
openimageio_ver: v2.2.17.0
openimageio_ver: v2.3.17.0
python_ver: 2.7
pybind11_ver: v2.6.2
simd: 0
@@ -174,8 +164,8 @@ jobs:
- desc: sanitizers
nametag: sanitizer
os: ubuntu-latest
container: aswftesting/ci-osl:2022-clang13
vfxyear: 2022
vfxsuffix: -clang13
cc_compiler: clang
cxx_compiler: clang++
cxx_std: 17
@@ -219,8 +209,8 @@ jobs:
- desc: "clang-format"
nametag: clang-format
os: ubuntu-latest
container: aswftesting/ci-osl:2022-clang14
vfxyear: 2022
vfxsuffix: -clang14
cxx_std: 17
openimageio_ver: release
python_ver: 3.9
@@ -232,7 +222,7 @@ jobs:
runs-on: ${{matrix.os}}
container:
image: ${{ matrix.container }}
image: aswftesting/ci-osl:${{matrix.vfxyear}}${{matrix.vfxsuffix}}
env:
CXX: ${{matrix.cxx_compiler}}
CC: ${{matrix.cc_compiler}}
@@ -302,11 +292,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-20.04
os: ubuntu-18.04
cxx_compiler: g++-7
cxx_std: 14
openexr_ver: v2.4.3
openimageio_ver: v2.3.21.0
openimageio_ver: dev-2.3
pybind11_ver: v2.6.2
python_ver: 2.7
simd: sse4.2
@@ -316,7 +306,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-20.04
os: ubuntu-18.04
cxx_compiler: g++-10
cxx_std: 17
fmt_ver: 7.0.1
@@ -330,20 +320,20 @@ jobs:
PUGIXML_VERSION=v1.10
- desc: latest releases gcc11/C++17 llvm13 boost1.71 exr3.1 py3.9 avx2 batch-b16avx512
nametag: linux-latest-releases
os: ubuntu-22.04
os: ubuntu-20.04
cxx_compiler: g++-11
cxx_std: 17
fmt_ver: 9.1.0
openexr_ver: v3.1.7
openexr_ver: v3.1.5
openimageio_ver: master
pybind11_ver: v2.10.0
python_ver: "3.10"
python_ver: 3.9
simd: avx2,f16c
batched: b8_AVX2,b8_AVX512,b16_AVX512
setenvs: export LLVM_VERSION=13.0.0
LLVM_DISTRO_NAME=ubuntu-20.04
OPENCOLORIO_VERSION=v2.2.0
PUGIXML_VERSION=v1.13
OPENCOLORIO_VERSION=v2.1.2
PUGIXML_VERSION=v1.11.4
- desc: bleeding edge gcc12/C++17 llvm14 oiio/ocio/exr/pybind-master boost1.71 py3.10 avx2 batch-b16avx512
nametag: linux-bleeding-edge
os: ubuntu-22.04
@@ -367,7 +357,7 @@ jobs:
cc_compiler: clang
cxx_std: 17
fmt_ver: 8.1.1
openexr_ver: v3.1.7
openexr_ver: v3.1.5
openimageio_ver: master
pybind11_ver: v2.9.2
python_ver: 3.8
@@ -447,8 +437,6 @@ jobs:
python_ver: "3.10"
aclang: 13
setenvs: export LLVMBREWVER="@14" DO_BREW_UPDATE=1
OPENIMAGEIO_VERSION=release
QT_BREW_VERSION="@5"
- desc: MacOS-12
os: macos-12
nametag: macos11-p310
@@ -458,7 +446,6 @@ jobs:
python_ver: "3.10"
aclang: 13
setenvs: export LLVMBREWVER="@15" DO_BREW_UPDATE=1
OPENIMAGEIO_VERSION=master
runs-on: ${{matrix.os}}
env:
CXX: ${{matrix.cxx_compiler}}
+3 -8
View File
@@ -10,23 +10,18 @@ on:
# 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"

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

+53 -112
View File
@@ -1,123 +1,69 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the Open Shading Language Project. -->
Release 1.12.14.0 -- 1 Aug? 2023 (compared to 1.12.13.0)
--------------------------------------------------------
Release 1.13 -- ?? 2023 ?? (compared to 1.12)
--------------------------------------------------
Dependency and standards requirements changes:
* OptiX 6.0 support has been removed. For GPU rendering with OptiX, a minimum
of OptiX 7.0 is required.
* The minimum version OpenImageIO has been raised from 2.2 to 2.3. #1591
(1.13.0.3)
OSL Language and oslc compiler:
* Bug fix: shader params whose default values involve "init ops" could be
incorrectly initialized if their values came from instance parameters set to
zero. #1578 (1.13.0.2)
OSL Standard library:
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)
API changes, new options, new ShadingSystem features (for renderer writers):
* A new `shadingStateUniform` pointer field was added to ShaderGlobals for
planned future expansion and improved GPU support. #1585 (1.13.1.0)
SIMD batched shading mode:
* Fix some array overruns (asymptomatic, but still potentially buggy) in
common_ancestor_between. #1577 (1.13.0.2)
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
OptiX rendering:
* OptiX 6.0 support has been removed. For GPU rendering with OptiX, a minimum
of OptiX 7.0 is required.
* Big overhaul/simplification of how strings are represented on the GPU: the
extra level of indirection to global variables is removed, and strings are
simply represented in ordinary variables as the hash of their characters.
#1531 (1.13.0.0) #1553 (1.13.0.1)
* Better PTX cache hit rate by eliminating several sources of not being
strictly deterministic in the PTX text we were generating. #1566 #1570
(1.13.0.1)
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`
Performance improvements:
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
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)
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
Internals/developer concerns:
* platform.h:
- New `OSL_ALLOCA` macro to allocate on the stack. #1589 (1.13.0.3)
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
Build & test system improvements:
* CMake build system and scripts:
- The version number is now a cache variable, and so can be overridden at
build time using `-DOSL_VERSION=...`. Use with extreme caution! #1579
(1.13.0.2)
* Dependency version support:
- Fix some issues that came up with the new icx 2022.0 compiler. #1601
(1.13.1.0)
* Testing and Continuous integration (CI) systems:
- Dynamic analysis using address and leak sanitizers. #1581 (1.13.0.3)
- `testshade --help` now prints TextureSystem options and all hardware
information. #1584 (1.13.0.3)
- Improvements to SonarCloud and coverage analysis. #1596 (1.13.0.3)
* Platform support:
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
Documentation:
* `doc/RELEASING.md` documents our release process and versioning policies.
#1572 (1.13.0.2)
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)
----------------------------------------------
@@ -215,9 +161,7 @@ SIMD batched shading mode:
* Batched isnan, isinf, isfinite. #1456 (1.12.4.2)
* Batched userdata and output placement. #1455 (1.12.4.2)
* Batched pointcloud functions. #1464 (1.12.4.4)
* Batched closures #1500
* Fix overrunning allocation region in debug common_ancestor_between. #1577
(1.12.6.1)
* Batched closures (#1500)
OptiX rendering:
* Explicitly set the OptiX pipeline stack size. #1254 (1.12.0.0)
@@ -287,8 +231,6 @@ Bug fixes and other improvements (internals):
* Switch to cone tracing for derivatives. #1543 (1.12.6.0)
* Fix error that prevented correct typecheck of ternary operator. #1552
(1.12.6.0)
* Fix bug where assigning an init-op param its default value as an instance
value would get lost. #1578 (1.12.6.1)
Internals/developer concerns:
* Use the `final` keyword in certain internal classes where applicable.
@@ -357,7 +299,6 @@ Build & test system improvements:
(1.12.4.1)
- Make exported cmake configs relocatable by using relative paths. #1466
(1.12.4.4)
- Make the version number be a cmake cache variable. #1579 (1.12.6.1)
* Dependency version support:
- Build properly against Cuda 11 and OptiX 7.1. #1232 (1.12.0.1)
and up to OptiX 7.4 #1559 (1.12.6.0)
+4 -15
View File
@@ -4,26 +4,19 @@
cmake_minimum_required (VERSION 3.12)
set (OSL_VERSION "1.12.14.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 "" CACHE STRING
set (PROJECT_VERSION_RELEASE_TYPE "dev" 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" ON)
"Set ON for supported release branch, OFF for master" OFF)
if (${PROJECT_NAME}_SUPPORTED_RELEASE)
set (${PROJECT_NAME}_DEV_RELEASE OFF)
else ()
@@ -134,10 +127,6 @@ endif ()
# 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
@@ -225,7 +214,7 @@ if (OSL_BUILD_PLUGINS)
add_subdirectory (src/osl.imageio)
endif ()
if (USE_QT AND (Qt5_FOUND OR Qt6_FOUND))
if (USE_QT AND Qt5_FOUND)
add_subdirectory (src/osltoy)
endif ()
+2 -2
View File
@@ -55,13 +55,13 @@ 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/blob/main/ASWF/CLA-corporate.md)
* [Corporate CLA](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/ASWF/OSL-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 CLA](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/blob/main/ASWF/CLA-individual.md).
* [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.
+15 -17
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.26)
* Build system: [CMake](https://cmake.org/) 3.12 or newer (tested through 3.24)
* A suitable **C++14 or C++17** compiler to build OSL itself, which may be any of:
- **GCC 6.1 or newer** (tested through gcc 12.1)
- Clang 3.4 or newer (tested through clang 16)
- Microsoft Visual Studio **2017 or newer**
- Intel C++ compiler icc **version 17 or newer** or LLVM-based icx compiler
**version 2022 or newer**.
* A suitable C++14 or C++17 compiler to build OSL itself, which may be any of:
- GCC 6.1 or newer (tested through gcc 12.1)
- Clang 3.4 or newer (tested through clang 15)
- Microsoft Visual Studio 2017 or newer
- Intel C++ compiler icc version 17 or newer or LLVM-based icx compiler
version 2022 or newer.
* **[OpenImageIO](http://openimageio.org) 2.2 or newer** (tested through 2.4)
* **[OpenImageIO](http://openimageio.org) 2.3 or newer** (tested through 2.4)
OSL uses OIIO both for its texture mapping functionality as well as
numerous utility classes. If you are integrating OSL into an existing
@@ -40,16 +40,14 @@ NEW or CHANGED dependencies since the last major release are **bold**.
$OpenImageIO_ROOT/lib to be in your LD_LIBRARY_PATH (or
DYLD_LIBRARY_PATH on OS X).
* **[LLVM](http://www.llvm.org) 9, 10, 11, 12, 13, 14, or 15**, including
clang libraries. LLVM 16 doesn't work yet, we need to make changes
on the OSL side to be compatible.
* [LLVM](http://www.llvm.org) 9, 10, 11, 12, 13, 14, or 15, 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.
* [OptiX](https://developer.nvidia.com/rtx/ray-tracing/optix) 5.1 or higher
(though 7.0+ is highly recommended).
* [Boost](https://www.boost.org) 1.55 or newer (tested through boost 1.81)
* [Boost](https://www.boost.org) 1.55 or newer (tested through boost 1.80)
* [Ilmbase or Imath](https://github.com/AcademySoftwareFoundation/openexr) 2.3
or newer (recommended: 2.4 or higher; tested through 3.1)
* [Flex](https://github.com/westes/flex) 2.5.35 or newer and
@@ -57,7 +55,7 @@ NEW or CHANGED dependencies since the last major release are **bold**.
Note that on some MacOS/xcode releases, the system-installed Bison is too
old, and it's better to install a newer Bison (via Homebrew is one way to
do this easily).
* [PugiXML](http://pugixml.org/) >= 1.8 (we have tested through 1.13).
* [PugiXML](http://pugixml.org/)
* (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.
@@ -66,8 +64,8 @@ NEW or CHANGED dependencies since the last major release are **bold**.
* Python >= 2.7 (tested against 2.7, 3.7, 3.8, 3.9, 3.10)
* pybind11 >= 2.4.2 (Tested through 2.10)
* NumPy
* (optional) Qt5 >= 5.6 or Qt6 (tested Qt5 through 5.15 and Qt6 through 6.4).
If not found at build time, the `osltoy` application will be disabled.
* (optional) Qt >= 5.6 (tested through 5.15). If not found at build time,
the `osltoy` application will be disabled.
+25 -62
View File
@@ -1,7 +1,7 @@
<div align="center">
<img src="ASWF/logos/openshadinglanguage-stacked-Shaded.png">
<img src="https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/blob/main/src/doc/Figures/osl-short.png" width=256 height=128>
<!-- <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")
@@ -219,15 +219,14 @@ 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 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)
Renderers and other tools with OSL support (in approximate order of
adding OSL support):
* Sony Pictures Imageworks: in-house "Arnold" renderer
* [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 iFX](https://www.isotropix.com/products/clarisse/ifx) / [Clarisse BUiLDER](https://www.isotropix.com/products/clarisse/builder) / [Angie](https://www.isotropix.com/products/angie)
* [Isotropix: Clarisse](http://www.isotropix.com/clarisse)
* [Isotropix: Angie](http://www.isotropix.com/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/)
@@ -238,13 +237,7 @@ project leader or submit a PR with edits to this file.*
* [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)
### 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.)
Films using OSL (grouped by year of release date):
* **(2012)**
Men in Black 3, The Amazing Spider-Man, Hotel Transylvania
* **(2013)**
@@ -279,7 +272,6 @@ nominated for major awards.)
Ghostbusters,
Star Trek Beyond,
Suicide Squad,
Kubo and the Two Strings,
Kingsglaive: Final Fantasy XV,
Storks,
Miss Peregrine's Home for Peculiar Children,
@@ -314,7 +306,7 @@ nominated for major awards.)
* **(2018)**
Peter Rabbit,
Black Panther,
Annihilation,
Annnihilation,
Red Sparrow,
Pacific Rim Uprising,
Avengers Infinity War,
@@ -362,8 +354,7 @@ nominated for major awards.)
Richard Jewell,
Game of Thrones (S8),
Lost in Space (S1),
Togo,
Missing Link
Togo
* **(2020)**
Underwater,
Birds of Prey,
@@ -379,9 +370,7 @@ nominated for major awards.)
Over the Moon,
Wonder Woman 1984,
Soul,
The Mandalorian (S2),
The Boys (S2),
Umbrella Academy (S2)
The Mandalorian (S2)
* **(2021)**
Chaos Walking,
Peter Rabbit 2: The Runaway,
@@ -394,7 +383,6 @@ nominated for major awards.)
F9,
Vivo,
Jungle Cruise,
Cinderella,
Dune,
No Time To Die,
Ron's Gone Wrong,
@@ -402,9 +390,8 @@ nominated for major awards.)
Last Night in Soho,
Ghostbusters: Afterlife,
Spider-Man 3: No Way Home,
Matrix Resurrections,
Sing 2
* **(2022)**
Matrix Resurrections
* **(2022 / upcoming)**
Hotel Transylvania 4: Transformania,
Death on the Nile,
Uncharted,
@@ -417,26 +404,11 @@ nominated for major awards.)
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
-------------------------
@@ -452,13 +424,6 @@ The OSL language specification can be found at
distribution) or in the share/doc/OSL/osl-languagespec.pdf file of an
installed binary distribution.
For those interested in learning to program 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
----------------------------
@@ -516,20 +481,18 @@ The current project leadership is documented in the
Many people have contributed features, bug fixes, and other changes to OSL
over the years: Steve Agland, Shane Ambler, Martijn Berger, Farchad
Bidgolirad, Nicholas Bishop, Solomon Boulos, Stefan Bruens, Stefan Büttner,
Matthaus G. Chajdas, Clark Chen, Alejandro Conty, 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
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, 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.)
Steena Monteiro, Alexis Oblet, Erich Ocean, Mikko Ohtamaa, Jino Park, Alexei
Pawlow, Jay Reynolds, Declan Russell, Benoit Ruiz, Patrick Scheibe, Alex
Schworer, Jonathan Scruggs, Sergey Sharybin, Sandip Shukla, Cliff Stein,
Stephan Steinbach, Luya Tshimbalanga, Esteban Tovagliari, Brecht Van Lommel,
Alexander von Knorring, Alex Wells, Roman Zulak. (Listed alphabetically; if
we've left anybody out, it is inadvertent, please let us know.)
We cannot possibly express sufficient gratitude to the managers at Sony
Pictures Imageworks who allowed this project to proceed, supported it
+2 -7
View File
@@ -144,8 +144,7 @@ branch, and henceforth, any big or compatibility-breaking changes will only be
committed to main and not backported to the release branch. (Though we are
loose about this rule during the alpha period and allow continued breaking
changes in the alpha, but by the time we call it beta, we allow no more
breaking changes.) Also at this stage, the main branch's CHANGES.md should
have a heading added at the top for the *next* version.
breaking changes.)
### Prior to a release
@@ -339,8 +338,4 @@ Odds and ends to do after the tag is pushed and the announcements are sent:
Language" channel of the ASWF slack. It can be a one-line announcement and
then just a link to the GitHub release page for this version.
- Edit the top-level CMakeList.txt to update the version to the *next*
anticipated release on the branch, in order to ensure that anybody building
from subsequent patches won't get a release number that advertises itself
incorrectly as a prior tagged release. Also edit CHANGES.md to add a new
(blank) heading for the next patch or release.
+4 -8
View File
@@ -189,10 +189,6 @@ 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)
@@ -200,13 +196,13 @@ else ifeq (${platform}, macosx)
else ifeq (${COMPILER},)
# default compiler is clang, taken from the LLVM directory
MY_CMAKE_FLAGS += \
-DCMAKE_C_COMPILER=${LLVM_ROOT}/bin/clang \
-DCMAKE_CXX_COMPILER=${LLVM_ROOT}/bin/clang++
-DCMAKE_C_COMPILER=${LLVM_DIRECTORY}/bin/clang \
-DCMAKE_CXX_COMPILER=${LLVM_DIRECTORY}/bin/clang++
else ifeq (${COMPILER},llvm)
# "llvm" means "use the clang from our llvm"
MY_CMAKE_FLAGS += \
-DCMAKE_C_COMPILER=${LLVM_ROOT}/bin/clang \
-DCMAKE_CXX_COMPILER=${LLVM_ROOT}/bin/clang++
-DCMAKE_C_COMPILER=${LLVM_DIRECTORY}/bin/clang \
-DCMAKE_CXX_COMPILER=${LLVM_DIRECTORY}/bin/clang++
endif
# end generic OSX
+1
View File
@@ -18,6 +18,7 @@ sonar.links.issue=https://github.com/AcademySoftwareFoundation/OpenShadingLangua
# Source properties
sonar.sources=src
sonar.sourceEncoding=UTF-8
sonar.exclusions=src/include/OSL/Imath/*.h,src/build-scripts/*
# C/C++ analyzer properties
sonar.cfamily.build-wrapper-output=build/bw_output
+1 -1
View File
@@ -14,7 +14,7 @@ uname
if [[ `uname` == "Linux" ]] ; then
LLVM_VERSION=${LLVM_VERSION:=14.0.0}
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}
+9
View File
@@ -12,6 +12,15 @@ pushd _coverage
ls -R ../build/src/
# Remove files or directories we want to exclude from code coverage analysis,
# generally because we don't expect to execute any of their code during our
# CI. (Because it's only used interactively, or is fallback code only used
# when certain dependencies are not found.) Including these when we know we
# won't be calling them during coverage gathering will just make our coverage
# percentage look artifically low.
rm -f ../build/src/osltoy/CMakeFiles/osltoy.dir/*.cpp.{gcno,gcda}
# The sed command below converts from:
# ../build/src/liboslexec/CMakeFiles/oslexec.dir/foo.gcno
# to:
+1
View File
@@ -61,6 +61,7 @@ echo "uname -a: " `uname -a`
echo "uname -m: " `uname -m`
echo "uname -s: " `uname -s`
echo "uname -n: " `uname -n`
echo "nproc " `nproc`
pwd
ls
env | sort
+6 -11
View File
@@ -18,8 +18,8 @@ if [[ "$ASWF_ORG" != "" ]] ; then
#ls /etc/yum.repos.d
sudo /usr/bin/yum install -y giflib giflib-devel && true
# sudo /usr/bin/yum install -y ffmpeg ffmpeg-devel && true
sudo yum install -y giflib giflib-devel && true
# sudo yum install -y ffmpeg ffmpeg-devel && true
if [[ "${CONAN_LLVM_VERSION}" != "" ]] ; then
mkdir conan
@@ -42,7 +42,7 @@ if [[ "$ASWF_ORG" != "" ]] ; then
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" || "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
sudo cp src/build-scripts/oneAPI.repo /etc/yum.repos.d
sudo /usr/bin/yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic-2022.1.0.x86_64
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.
@@ -61,7 +61,7 @@ if [[ "$ASWF_ORG" != "" ]] ; then
else
# Using native Ubuntu runner
# sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
time sudo apt-get update
time sudo apt-get -q install -y \
@@ -73,13 +73,8 @@ else
libpugixml-dev \
libopencolorio-dev
if [[ "${QT_VERSION:-5}" == "5" ]] ; then
time sudo apt-get -q install -y \
qt5-default || /bin/true
elif [[ "${QT_VERSION}" == "6" ]] ; then
time sudo apt-get -q install -y \
qt6-base-dev || /bin/true
fi
time sudo apt-get -q install -y \
qt5-default || /bin/true
export CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu:$CMAKE_PREFIX_PATH
+6 -8
View File
@@ -19,7 +19,6 @@ if [[ `which brew` == "" ]] ; then
exit 1
fi
set -ex
if [[ "$DO_BREW_UPDATE" != "" ]] ; then
brew update >/dev/null
@@ -31,21 +30,20 @@ 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@2.7 || true
brew unlink python@3.8 || true
brew unlink python@3.9 || true
brew unlink python@3.10 || true
brew link --overwrite --force python@${PYTHON_VERSION} || true
brew upgrade --display-times -q cmake || true
brew install --display-times -q imath openexr
brew install --display-times -q ilmbase openexr
#brew install --display-times -q freetype
brew install --display-times -q --overwrite --force opencolorio || true
brew install --display-times -q partio pugixml
brew install --display-times -q opencolorio partio pugixml
brew install --display-times -q pybind11 numpy || true
brew install --display-times -q tbb || true
brew install --display-times -q flex bison
brew install --display-times -q llvm${LLVMBREWVER}
brew install --display-times -q qt${QT_BREW_VERSION}
brew install --display-times -q qt
echo ""
echo "After brew installs:"
-6
View File
@@ -21,12 +21,6 @@ function ( NVCC_COMPILE cuda_src extra_headers ptx_generated extra_nvcc_args )
list (TRANSFORM OpenImageIO_INCLUDES PREPEND -I
OUTPUT_VARIABLE ALL_OpenImageIO_INCLUDES)
if (${LLVM_VERSION} VERSION_GREATER_EQUAL 15.0)
# Until we fully support opaque pointers, we need to disable
# them when using LLVM 15.
list (APPEND LLVM_COMPILE_FLAGS -Xclang -no-opaque-pointers)
endif ()
add_custom_command ( OUTPUT ${cuda_ptx}
COMMAND ${CUDA_NVCC_EXECUTABLE}
"-I${OPTIX_INCLUDES}"
+39 -55
View File
@@ -105,7 +105,7 @@ endif ()
# OpenImageIO
checked_find_package (OpenImageIO REQUIRED
VERSION_MIN 2.2.6
VERSION_MIN 2.3.17
DEFINITIONS -DOIIO_HIDE_FORMAT=1)
checked_find_package (pugixml REQUIRED
@@ -115,7 +115,6 @@ checked_find_package (pugixml REQUIRED
# LLVM library setup
checked_find_package (LLVM REQUIRED
VERSION_MIN 9.0
VERSION_MAX 15.9
PRINT LLVM_SYSTEM_LIBRARIES CLANG_LIBRARIES)
# ensure include directory is added (in case of non-standard locations
include_directories (BEFORE SYSTEM "${LLVM_INCLUDES}")
@@ -145,19 +144,6 @@ 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)
message (ERROR "${ColorYellow}OSL is not yet compatible with LLVM 16.${ColorReset}\n")
if (CMAKE_CXX_STANDARD VERSION_LESS 17)
message (WARNING "${ColorYellow}LLVM 16+ requires C++17 or higher. "
"Please set CMAKE_CXX_STANDARD to 17 or higher.${ColorReset}\n")
endif ()
if (CMAKE_COMPILER_IS_GNUCC AND (GCC_VERSION VERSION_LESS 7.0))
message (WARNING "${ColorYellow}LLVM 16+ requires gcc 7.0 or higher.${ColorReset}\n")
endif ()
if (CMAKE_COMPILER_IS_CLANG AND (CLANG_VERSION_STRING VERSION_LESS 5.0))
message (WARNING "${ColorYellow}LLVM 16+ requires clang 5.0 or higher.${ColorReset}\n")
endif ()
endif ()
checked_find_package (partio)
@@ -167,63 +153,60 @@ 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)
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 ()
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")
endif ()
# CUDA setup
if (USE_CUDA OR 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_TOOLKIT_ROOT_DIR AND NOT $ENV{CUDA_TOOLKIT_ROOT_DIR} STREQUAL "")
set (CUDA_TOOLKIT_ROOT_DIR $ENV{CUDA_TOOLKIT_ROOT_DIR})
endif ()
if (NOT CUDA_FIND_QUIETLY OR NOT OptiX_FIND_QUIETLY)
message (STATUS "CUDA_TOOLKIT_ROOT_DIR = ${CUDA_TOOLKIT_ROOT_DIR}")
endif ()
if (NOT CUDA_FIND_QUIETLY OR NOT OptiX_FIND_QUIETLY)
message (STATUS "CUDA_TOOLKIT_ROOT_DIR = ${CUDA_TOOLKIT_ROOT_DIR}")
endif ()
checked_find_package (CUDA REQUIRED
VERSION_MIN 8.0
PRINT CUDA_INCLUDES)
set (CUDA_INCLUDES ${CUDA_TOOLKIT_ROOT_DIR}/include)
include_directories (BEFORE "${CUDA_INCLUDES}")
checked_find_package (CUDA REQUIRED
VERSION_MIN 8.0
PRINT CUDA_INCLUDES)
set (CUDA_INCLUDES ${CUDA_TOOLKIT_ROOT_DIR}/include)
include_directories (BEFORE "${CUDA_INCLUDES}")
STRING (FIND ${LLVM_TARGETS} "NVPTX" nvptx_index)
if (NOT ${nvptx_index} GREATER -1)
message (FATAL_ERROR "NVPTX target is not available in the provided LLVM build")
endif()
STRING (FIND ${LLVM_TARGETS} "NVPTX" nvptx_index)
if (NOT ${nvptx_index} GREATER -1)
message (FATAL_ERROR "NVPTX target is not available in the provided LLVM build")
endif()
set (CUDA_LIB_FLAGS "--cuda-path=${CUDA_TOOLKIT_ROOT_DIR}")
set (CUDA_LIB_FLAGS "--cuda-path=${CUDA_TOOLKIT_ROOT_DIR}")
find_library(cuda_lib NAMES cudart
PATHS "${CUDA_TOOLKIT_ROOT_DIR}/lib64" "${CUDA_TOOLKIT_ROOT_DIR}/x64" "${CUDA_TOOLKIT_ROOT_DIR}/lib/x64"
REQUIRED)
set(CUDA_LIBRARIES ${cuda_lib})
find_library(cuda_lib NAMES cudart
PATHS "${CUDA_TOOLKIT_ROOT_DIR}/lib64" "${CUDA_TOOLKIT_ROOT_DIR}/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" "${CUDA_TOOLKIT_ROOT_DIR}/lib/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"
REQUIRED)
set(CUDA_LIBRARIES ${CUDA_LIBRARIES} ${nvrtc_lib})
set(CUDA_EXTRA_LIBS ${CUDA_EXTRA_LIBS} dl)
endif()
set(CUDA_EXTRA_LIBS ${CUDA_EXTRA_LIBS} dl)
endif()
# OptiX setup
if (USE_OPTIX AND OSL_BUILD_TESTS)
if (USE_OPTIX)
checked_find_package (OptiX REQUIRED
VERSION_MIN 5.1)
VERSION_MIN 7.0)
include_directories (BEFORE "${OPTIX_INCLUDES}")
if (NOT USE_LLVM_BITCODE OR NOT USE_FAST_MATH)
message (FATAL_ERROR "Enabling OptiX requires USE_LLVM_BITCODE=1 and USE_FAST_MATH=1")
@@ -236,6 +219,7 @@ 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 -8
View File
@@ -23,13 +23,7 @@
# try to find llvm-config, with a specific version if specified
if (LLVM_DIRECTORY)
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")
set (LLVM_CONFIG_PATH_HINTS "${LLVM_DIRECTORY}/bin")
endif ()
list (APPEND LLVM_CONFIG_PATH_HINTS
"/usr/local/opt/llvm/${LLVM_VERSION}/bin/"
@@ -127,7 +121,7 @@ endif ()
foreach (COMPONENT clangFrontend clangDriver clangSerialization
clangParse clangSema clangAnalysis clangAST clangBasic
clangEdit clangLex clangSupport)
clangEdit clangLex)
find_library ( _CLANG_${COMPONENT}_LIBRARY
NAMES ${COMPONENT}
PATHS ${LLVM_LIB_DIR})
+6 -3
View File
@@ -20,9 +20,12 @@ macro (find_python)
# Attempt to find the desired version, but fall back to other
# additional versions.
set (_req REQUIRED)
if (PYTHON_VERSION)
list (APPEND _req EXACT)
unset (_req)
if (USE_PYTHON)
set (_req REQUIRED)
if (PYTHON_VERSION)
list (APPEND _req EXACT)
endif ()
endif ()
checked_find_package (Python ${PYTHON_VERSION}
${_req}
+6 -9
View File
@@ -71,10 +71,6 @@ 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
@@ -143,6 +139,9 @@ macro ( TESTSUITE )
add_one_testsuite ("${_testname}.opt" "${_testsrcdir}"
ENV TESTSHADE_OPT=2 )
endif ()
if (_testname MATCHES "render-" AND ${CMAKE_BUILD_TYPE} STREQUAL Debug)
set_tests_properties (${_testname} PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
endif ()
# When building for OptiX support, also run it in OptiX mode
# if there is an OPTIX marker file in the directory.
# If an environment variable $TESTSUITE_OPTIX is nonzero, then
@@ -237,8 +236,7 @@ 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 closure-parameters closure-zero closure-conditional
color color-reg colorspace comparison
cellnoise closure closure-array color color-reg colorspace comparison
complement-reg compile-buffer compassign-reg
component-range
control-flow-reg connect-components
@@ -324,7 +322,6 @@ 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
@@ -354,7 +351,7 @@ macro (osl_add_all_tests)
transform transform-reg transformc transformc-reg trig trig-reg
typecast
unknown-instruction
userdata userdata-custom userdata-passthrough
userdata userdata-passthrough
vararray-connect vararray-default
vararray-deserialize vararray-param
vecctr vector vector-reg
@@ -386,7 +383,7 @@ macro (osl_add_all_tests)
endif()
# Only run pointcloud tests if Partio is found
if (partio_FOUND)
if (PARTIO_FOUND)
TESTSUITE ( pointcloud pointcloud-fold )
endif ()
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

+34 -63
View File
@@ -2631,6 +2631,27 @@ 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}
@@ -2678,35 +2699,6 @@ 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}
@@ -4091,8 +4083,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 key-value
arguments (see Section~\ref{sec:syntax:functioncalls}) that control the behavior of {\cf texture()}:
The 2D lookup coordinate(s) may be followed by optional token/value
arguments that control the behavior of {\cf texture()}:
\apiitem{"blur", <float>}
\vspace{12pt}
@@ -5607,7 +5599,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
global scene-wide attributes.
searching 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
@@ -5909,38 +5901,17 @@ view-dependence into shaders.
The return value is 0 if the ray missed all geometry, 1 if it hit
anything within the distance range.
The following optional key-value arguments
(see Section~\ref{sec:syntax:functioncalls}) can be passed:
Optional parameters include:
\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}
\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}
Information about the closest object hit by the ray may be retrieved
using \\ {\cf getmessage("trace",...)} (see Section~\ref{sec:getmessage}).
+11 -14
View File
@@ -6,6 +6,10 @@
#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>
@@ -32,20 +36,20 @@ OSL_NAMESPACE_ENTER
// stored in the table, in the 16 bytes preceding the characters.
struct DeviceString {
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
#ifdef __CUDA_ARCH__
size_t m_chars;
#else
const char* m_chars;
#endif
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
#ifdef __CUDA_ARCH__
OSL_HOSTDEVICE DeviceString() {}
OSL_HOSTDEVICE DeviceString(uint64_t i) : m_chars(i) {}
#endif
OSL_HOSTDEVICE uint64_t hash() const
{
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
#ifdef __CUDA_ARCH__
return m_chars;
#else
return *(uint64_t*)(m_chars - sizeof(uint64_t) - sizeof(uint64_t));
@@ -54,7 +58,7 @@ struct DeviceString {
// In OptiX 7 we don't store the string's length. Make this a compile
// time error.
#if !(defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000)
#ifndef __CUDA_ARCH__
OSL_HOSTDEVICE uint64_t length() const
{
return *(uint64_t*)(m_chars - sizeof(uint64_t));
@@ -63,7 +67,7 @@ struct DeviceString {
// In OptiX 7 we can't return the string's contents. Make this a compile
// time error.
#if !(defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000)
#ifndef __CUDA_ARCH__
OSL_HOSTDEVICE const char* c_str() const
{
return m_chars;
@@ -80,7 +84,7 @@ struct DeviceString {
return m_chars != other.m_chars;
}
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
#ifdef __CUDA_ARCH__
OSL_HOSTDEVICE bool operator==(const size_t other) const
{
@@ -125,9 +129,6 @@ typedef DeviceString StringParam;
namespace DeviceStrings {
# define STRDECL(str, var_name) \
extern __device__ OSL_NAMESPACE::DeviceString var_name;
# if OPTIX_VERSION < 70000
# include <OSL/strdecls.h>
# endif
# undef STRDECL
} // namespace DeviceStrings
#else
@@ -142,10 +143,6 @@ namespace DeviceStrings {
OSL_NAMESPACE_EXIT
#ifdef __CUDA_ARCH__
# if OPTIX_VERSION < 70000
namespace StringParams = OSL_NAMESPACE::DeviceStrings;
# endif
#else
#ifndef __CUDA_ARCH__
namespace StringParams = OSL_NAMESPACE::Strings;
#endif
+25 -31
View File
@@ -108,6 +108,12 @@ public:
void jit_aggressive(bool val) { m_jit_aggressive = val; }
bool jit_aggressive() const { return m_jit_aggressive; }
// Select whether the representation of a ustring is going to be
// the character pointer, or the hash.
enum class UstringRep { charptr, hash };
UstringRep ustring_rep() const { return m_ustring_rep; }
void ustring_rep(UstringRep rep);
/// Return a reference to the current context.
llvm::LLVMContext& context() const { return *m_llvm_context; }
@@ -148,15 +154,6 @@ public:
void debug_pop_inlined_function();
void debug_set_location(OIIO::ustring sourcefile, int sourceline);
/// Create a new function (that will later be populated with
/// instructions) with up to 4 args.
OSL_DEPRECATED("Use make_function flavor that takes a cspan (1.12)")
llvm::Function* make_function(const std::string& name, bool fastcall,
llvm::Type* rettype, llvm::Type* arg1 = NULL,
llvm::Type* arg2 = NULL,
llvm::Type* arg3 = NULL,
llvm::Type* arg4 = NULL);
/// Create a new function (that will later be populated with
/// instructions) with a cspan of args.
llvm::Function* make_function(const std::string& name, bool fastcall,
@@ -283,12 +280,7 @@ public:
Linkage default_linkage = Linkage::Internal,
std::string* out_err = nullptr);
// OLD, might deprecate later
/// Change symbols in the module that are marked as having external
/// linkage to an alternate linkage that allows them to be discarded if
/// not used within the module. Only do this for functions that start
/// with prefix, and that DON'T match anything in the two exceptions
/// lists.
OSL_DEPRECATED("prune_and_internalize_module is better (1.13)")
void internalize_module_functions(
const std::string& prefix, const std::vector<std::string>& exceptions,
const std::vector<std::string>& moreexceptions);
@@ -311,7 +303,7 @@ public:
/// Create a new LLVM basic block (for the current function) and return
/// its handle.
llvm::BasicBlock* new_basic_block(const std::string& name = std::string());
llvm::BasicBlock* new_basic_block(const std::string& name = {});
/// Save the return block pointer when entering a function. If
/// after==NULL, generate a new basic block for where to go after the
@@ -543,8 +535,8 @@ public:
llvm::Type* type_triple() const { return m_llvm_type_triple; }
llvm::Type* type_matrix() const { return m_llvm_type_matrix; }
llvm::Type* type_typedesc() const { return m_llvm_type_longlong; }
llvm::Type* type_ustring() { return m_llvm_type_ustring; }
llvm::PointerType* type_void_ptr() const { return m_llvm_type_void_ptr; }
llvm::PointerType* type_string() { return m_llvm_type_char_ptr; }
llvm::PointerType* type_ustring_ptr() const
{
return m_llvm_type_ustring_ptr;
@@ -579,7 +571,8 @@ public:
llvm::Type* type_wide_triple() const { return m_llvm_type_wide_triple; }
llvm::Type* type_wide_matrix() const { return m_llvm_type_wide_matrix; }
llvm::Type* type_wide_void_ptr() const { return m_llvm_type_wide_void_ptr; }
llvm::Type* type_wide_string() const
llvm::Type* type_wide_ustring() const { return m_llvm_type_wide_ustring; }
llvm::PointerType* type_wide_ustring_ptr() const
{
return m_llvm_type_wide_ustring_ptr;
}
@@ -629,7 +622,7 @@ public:
bool is_packed = false);
/// Return the llvm::Type that is a pointer to the given llvm type.
llvm::Type* type_ptr(llvm::Type* type);
llvm::PointerType* type_ptr(llvm::Type* type);
/// Return the llvm::Type that is the wide version of the given llvm type
llvm::Type* type_wide(llvm::Type* type);
@@ -638,12 +631,6 @@ 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.
@@ -693,7 +680,8 @@ public:
/// If the type specified is NULL, it will make a 'void *'.
llvm::Value* constant_ptr(void* p, llvm::PointerType* type = NULL);
/// Return an llvm::Value holding the given string constant.
/// Return an llvm::Value holding the given string constant (as
/// determined by the ustring_rep).
llvm::Value* constant(ustring s);
llvm::Value* constant(string_view s) { return constant(ustring(s)); }
@@ -1026,9 +1014,10 @@ private:
IRBuilder& builder();
int m_debug;
bool m_dumpasm = false;
bool m_jit_fma = false;
bool m_jit_aggressive = false;
bool m_dumpasm = false;
bool m_jit_fma = false;
bool m_jit_aggressive = false;
UstringRep m_ustring_rep = UstringRep::charptr;
PerThreadInfo::Impl* m_thread;
llvm::LLVMContext* m_llvm_context;
llvm::Module* m_llvm_module;
@@ -1044,6 +1033,9 @@ private:
std::vector<llvm::BasicBlock*> m_loop_after_block; // stack for break
std::vector<llvm::BasicBlock*> m_loop_step_block; // stack for continue
// Incrementing serial numbers
int m_next_serial_bb = 0;
llvm::Type* m_llvm_type_float;
llvm::Type* m_llvm_type_double;
llvm::Type* m_llvm_type_int;
@@ -1056,8 +1048,8 @@ private:
llvm::Type* m_llvm_type_void;
llvm::Type* m_llvm_type_triple;
llvm::Type* m_llvm_type_matrix;
llvm::Type* m_llvm_type_ustring;
llvm::PointerType* m_llvm_type_void_ptr;
llvm::PointerType* m_llvm_type_ustring_ptr;
llvm::PointerType* m_llvm_type_char_ptr;
llvm::PointerType* m_llvm_type_bool_ptr;
llvm::PointerType* m_llvm_type_int_ptr;
@@ -1066,6 +1058,7 @@ private:
llvm::PointerType* m_llvm_type_triple_ptr;
llvm::PointerType* m_llvm_type_matrix_ptr;
llvm::PointerType* m_llvm_type_double_ptr;
llvm::PointerType* m_llvm_type_ustring_ptr;
int m_vector_width;
llvm::Type* m_llvm_type_wide_float;
@@ -1077,11 +1070,12 @@ private:
llvm::Type* m_llvm_type_wide_triple;
llvm::Type* m_llvm_type_wide_matrix;
llvm::Type* m_llvm_type_wide_void_ptr;
llvm::Type* m_llvm_type_wide_ustring_ptr;
llvm::Type* m_llvm_type_wide_ustring;
llvm::PointerType* m_llvm_type_wide_char_ptr;
llvm::PointerType* m_llvm_type_wide_int_ptr;
llvm::PointerType* m_llvm_type_wide_bool_ptr;
llvm::PointerType* m_llvm_type_wide_float_ptr;
llvm::PointerType* m_llvm_type_wide_ustring_ptr;
llvm::Type* m_llvm_type_native_mask;
bool m_supports_masked_stores = false;
+28 -1
View File
@@ -102,7 +102,7 @@ using OIIO::TextureOpt;
// And some other things we borrow from OIIO...
using OIIO::ErrorHandler;
using OIIO::ustring;
using OIIO::ustringHash;
using OIIO::ustringhash;
using OIIO::string_view;
using OIIO::span;
using OIIO::cspan;
@@ -225,3 +225,30 @@ using ConstIndex = std::integral_constant<int, N>;
OSL_NAMESPACE_EXIT
namespace std { // not necessary in C++17, then we can just say std::hash
#ifndef OIIO_USTRING_HAS_STDHASH
// Not a new enough OIIO to define std::hash<ustring>, so we'll do it
template<> struct hash<OSL::ustring> {
std::size_t operator()(OSL::ustring u) const noexcept { return u.hash(); }
};
template<> struct hash<OSL::ustringhash> {
OSL_HOSTDEVICE constexpr std::size_t
operator()(OSL::ustringhash u) const noexcept
{
return u.hash();
}
};
#endif
// Not necessary once minimum OIIO defines operator< for ustringhash
template<> struct less<OSL::ustringhash> {
OSL_HOSTDEVICE constexpr bool operator()(OSL::ustringhash u,
OSL::ustringhash v) const noexcept
{
return u.hash() < v.hash();
}
};
} // namespace std
+14 -14
View File
@@ -50,7 +50,7 @@ namespace pvt {
class ShadingSystemImpl;
}
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
#ifdef __CUDA_ARCH__
# define STRING_PARAMS(x) UStringHash::Hash(__OSL_STRINGIFY(x))
#else
# define STRING_PARAMS(x) StringParams::x
@@ -58,11 +58,7 @@ class ShadingSystemImpl;
namespace Strings {
#ifdef __CUDA_ARCH__
# if OPTIX_VERSION >= 70000
# define STRDECL(str, var_name)
# else
# define STRDECL(str, var_name) extern __device__ const ustring var_name;
# endif
# define STRDECL(str, var_name)
#else
// Any strings referenced inside of a libsoslexec/wide/*.cpp
// or liboslnoise/wide/*.cpp will need OSLEXECPUBLIC
@@ -235,8 +231,7 @@ public:
/// for debugging. (0)
/// int llvm_dumpasm Print the CPU assembly code from the JIT (0)
/// string llvm_prune_ir_strategy Strategy for pruning unnecessary
/// IR (choices: "prune" [default],
/// "internalize", or "none").
/// IR (choices: "prune" [default], or "none").
/// int max_local_mem_KB Error if shader group needs more than this
/// much local storage to execute (1024K)
/// string debug_groupname Name of shader group -- debug only this one
@@ -432,15 +427,12 @@ 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, or with
/// multiple different types, it will
/// is requested in multiple scopes, it will
/// appear in the array multiple times - once for
/// each scope/type in which is is queried.
/// each scope 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.
@@ -451,7 +443,6 @@ 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.
/// 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!
@@ -681,6 +672,15 @@ public:
ShaderGlobals& globals, void* userdata_base_ptr,
void* output_base_ptr, bool run = true);
/// Future execute signature that will be range based. Shader globals will be
/// obtained from renderer services.
#if 0 // TODO in future PR
bool execute(ShadingContext& ctx, ShaderGroup& group, OpaqueShadingStateUniformPtr ssu,
int shadeindex_begin_at, int shadeindex_end_before
void* userdata_base_ptr,
void* output_base_ptr, bool run = true);
#endif
// DEPRECATED(2.0): no shadeindex or base pointers
bool execute(ShadingContext& ctx, ShaderGroup& group,
ShaderGlobals& globals, bool run = true)
+291 -291
View File
File diff suppressed because it is too large Load Diff
-19
View File
@@ -18,7 +18,6 @@
#pragma once
#include <cstring>
#include <memory>
#include <OSL/oslversion.h>
@@ -500,24 +499,6 @@
OSL_NAMESPACE_ENTER
/// Standards-compliant bit cast of two equally sized types. This is used
/// equivalently to C++20 std::bit_cast, but it works prior to C++20 and
/// it has the right decorators to work with Cuda.
/// @version 1.13.2
template <typename To, typename From>
OSL_FORCEINLINE OSL_HOSTDEVICE To bitcast(const From& src) noexcept {
// NOTE: this is the only standards compliant way of doing this type of casting,
// luckily the compilers we care about know how to optimize away this idiom.
static_assert(sizeof(From) == sizeof(To),
"bit_cast must be between objects of the same size");
To dst;
memcpy((void*)&dst, &src, sizeof(From));
return dst;
}
#if OSL_CPLUSPLUS_VERSION >= 20
using std::assume_aligned;
#else
-9
View File
@@ -405,15 +405,6 @@ public:
/// Return a pointer to the texture system (if available).
virtual TextureSystem *texturesys () const;
/// Register a string with the renderer, so that the renderer can arrange
/// to make the string available in GPU memory as needed. Optionally specify
/// a variable name to associate with the string value.
virtual uint64_t register_string (const std::string& str,
const std::string& var_name)
{
return 0;
}
virtual uint64_t register_global (const std::string& var_name,
uint64_t value)
{
+4
View File
@@ -17,6 +17,9 @@ class RendererServices;
/// coordinate transformation.
typedef const void* TransformationPtr;
/// Type for an opaque pointer to whatever the Shading System uses to represent
/// Uniform State.
typedef const void* OpaqueShadingStateUniformPtr;
/// The ShaderGlobals structure represents the state describing a particular
@@ -83,6 +86,7 @@ struct ShaderGlobals {
/// Back-pointer to the ShadingContext (set and used by OSL itself --
/// renderers shouldn't mess with this at all).
ShadingContext* context;
OpaqueShadingStateUniformPtr shadingStateUniform;
/// Pointer to the RendererServices object. This is how OSL finds its
/// way back to the renderer for callbacks.
+9 -35
View File
@@ -2845,7 +2845,7 @@ public:
// Populate all data lanes of the MaskedData by broadcasting the
// single instance of data pointed to.
// Masked off lanes are not overwritten.
// when has_derivs() is true, Dx and Dy will be zeroed
// Includes value, as well as Dx and Dy when has_derivs() is true
OSL_FORCEINLINE void assign_all_from_scalar(const void* ptr_data) const;
@@ -2863,9 +2863,6 @@ 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;
};
@@ -3381,33 +3378,6 @@ 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
@@ -3423,12 +3393,16 @@ 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) {
zero_all_type<int>(/*deriv_index*/ 1);
zero_all_type<int>(/*deriv_index*/ 2);
assign_all_from_scalar_type<int>(dx_src, /*deriv_index*/ 1);
assign_all_from_scalar_type<int>(dy_src, /*deriv_index*/ 2);
} else {
zero_all_type<ustring>(/*deriv_index*/ 1);
zero_all_type<ustring>(/*deriv_index*/ 2);
assign_all_from_scalar_type<ustring>(dx_src, /*deriv_index*/ 1);
assign_all_from_scalar_type<ustring>(dy_src, /*deriv_index*/ 2);
}
}
}
+17 -8
View File
@@ -5,6 +5,7 @@
#pragma once
#include <OSL/oslconfig.h>
#include <OSL/oslversion.h>
#ifdef OSL_USE_OPTIX
@@ -13,14 +14,18 @@
# ifdef _WIN32
# define NOMINMAX
# endif
# if (OPTIX_VERSION < 70000)
# include <optix_world.h>
# endif
#else
# include <stdlib.h>
#endif
#if !defined(OSL_USE_OPTIX) && !defined(__CUDA_ARCH__)
using CUdeviceptr = void*;
using float3 = OSL::Vec3;
#endif
OSL_NAMESPACE_ENTER
#ifdef OSL_USE_OPTIX
@@ -31,14 +36,12 @@ OSL_NAMESPACE_ENTER
// TODO clean this up once OptiX6 support is dropped
# if (OPTIX_VERSION < 70000)
namespace optix = ::optix;
# else
namespace optix {
typedef OptixDeviceContext Context;
typedef cudaTextureObject_t TextureSampler;
using ::CUdeviceptr;
using ::float3;
} // namespace optix
# endif
using ::cudaFree;
using ::cudaMalloc;
@@ -49,13 +52,19 @@ using ::cudaMalloc;
////////////////////////////////////////////////////////////////////////
// If OptiX is not available, make reasonable proxies just so that we
// don't have to litter the code with quite as many #ifdef's.
// OSL::optix::
// Mostly under OSL::optix::
namespace optix {
typedef void* Context;
typedef void* Program;
typedef void* TextureSampler;
typedef void* CUdeviceptr;
using float3 = OSL::Vec3;
struct Exception {
static const char* what() { return "OSL compiled without Optix."; }
};
-11
View File
@@ -386,7 +386,6 @@ 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.
@@ -1286,13 +1285,3 @@ 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
+36 -34
View File
@@ -1116,88 +1116,90 @@ 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
const char *
ASTbinary_expression::childname (size_t i) const
{
static const char* name[] = { "left", "right" };
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) {
+2 -3
View File
@@ -701,12 +701,11 @@ OSLCompilerImpl::write_oso_const_value(const ConstantSymbol* sym) const
osofmt("{}{}", sym->get_int(i), nelements > 1 ? " " : "");
else if (elemtype == TypeDesc::FLOAT)
for (int i = 0; i < nelements; ++i)
osofmt("{:.9g}{}", sym->floatval(i), nelements > 1 ? " " : "");
osofmt("{}{}", sym->floatval(i), nelements > 1 ? " " : "");
else if (equivalent(elemtype, TypeDesc::TypeVector))
for (int i = 0; i < nelements; ++i) {
Vec3 v = sym->get_vec3(i);
osofmt("{:.9g} {:.9g} {:.9g}{}", v.x, v.y, v.z,
nelements > 1 ? " " : "");
osofmt("{} {} {}{}", v.x, v.y, v.z, nelements > 1 ? " " : "");
}
else {
OSL_ASSERT(0 && "Don't know how to output this constant type");
+1 -1
View File
@@ -490,7 +490,7 @@ private:
int m_main_method_start; ///< Instruction where 'main' starts
bool m_declaring_shader_formals; ///< Are we declaring shader formals?
std::set<std::pair<ustring, int>> m_nowarn_lines; ///< Lines for 'nowarn'
typedef std::unordered_map<ustring, std::string, ustringHash> FCMap;
typedef std::unordered_map<ustring, std::string> FCMap;
FCMap m_filecontents_map; ///< Contents of source files we've seen
ustring m_last_sourcefile; ///< Last filename for retrieve_source
std::string* m_last_filecontents = nullptr; //< Last file contents
+12
View File
@@ -397,6 +397,15 @@ OSLCompilerImpl::osl_parse_buffer (const std::string &preprocessed_buffer)
// Thread safety with the lexer/parser
std::lock_guard<std::mutex> lock(oslcompiler_mutex);
#ifndef OIIO_STRUTIL_HAS_STOF
// Force classic "C" locale for correct '.' decimal parsing.
// N.B. This is not safe in a multi-threaded program where another
// application thread is expecting the native locale to work properly.
// This is not necessary for versions of OIIO that have Strutil::stof,
// and we can remove it entirely when OIIO 1.9 is the minimum.
std::locale oldlocale = std::locale::global (std::locale::classic());
#endif
yyscan_t scanner;
yylex_init(&scanner);
YY_BUFFER_STATE buffer = yy_scan_string(preprocessed_buffer.c_str(), scanner);
@@ -406,6 +415,9 @@ OSLCompilerImpl::osl_parse_buffer (const std::string &preprocessed_buffer)
yy_delete_buffer (buffer, scanner);
yylex_destroy(scanner);
#ifndef OIIO_STRUTIL_HAS_STOF
std::locale::global (oldlocale); // Restore the original locale.
#endif
return parseerr;
}
+1 -1
View File
@@ -186,7 +186,7 @@ private:
///
class SymbolTable {
public:
typedef std::unordered_map<ustring, Symbol*, ustringHash> ScopeTable;
typedef std::unordered_map<ustring, Symbol*> ScopeTable;
typedef std::vector<ScopeTable> ScopeTableStack;
typedef SymbolPtrVec::iterator iterator;
typedef SymbolPtrVec::const_iterator const_iterator;
+3 -3
View File
@@ -23,12 +23,12 @@ OSL_NAMESPACE_ENTER
typedef std::set<int>
IntSet; // probably faster to test for equality, unions and so
typedef std::unordered_set<ustring, ustringHash> SymbolSet;
typedef std::unordered_set<ustring> SymbolSet;
// This is for the transition table used in DfAutomata::State
typedef std::unordered_map<ustring, int, ustringHash> SymbolToInt;
typedef std::unordered_map<ustring, int> SymbolToInt;
// And this is for the transition table in NdfAutomata which
// has several movements for each symbol
typedef std::unordered_map<ustring, IntSet, ustringHash> SymbolToIntList;
typedef std::unordered_map<ustring, IntSet> SymbolToIntList;
typedef std::unordered_map<int, int> HashIntInt;
// For the rules in the deterministic states, we don't need a real set
+76 -243
View File
@@ -6,6 +6,10 @@
#include <OpenImageIO/filesystem.h>
#include <OpenImageIO/strutil.h>
#ifdef OSL_USE_OPTIX
# include <optix.h>
#endif
#include "oslexec_pvt.h"
#include "backendllvm.h"
@@ -83,6 +87,12 @@ BackendLLVM::BackendLLVM(ShadingSystemImpl& shadingsys, ShaderGroup& group,
#endif
m_use_optix = shadingsys.renderer()->supports("OptiX");
m_use_rs_bitcode = !shadingsys.m_rs_bitcode.empty();
m_name_llvm_syms = shadingsys.m_llvm_output_bitcode;
// Select the appropriate ustring representation
ll.ustring_rep(m_use_optix ? LLVM_Util::UstringRep::hash
: LLVM_Util::UstringRep::charptr);
ll.dumpasm(shadingsys.m_llvm_dumpasm);
ll.jit_fma(shadingsys.m_llvm_jit_fma);
ll.jit_aggressive(shadingsys.m_llvm_jit_aggressive);
@@ -131,7 +141,7 @@ BackendLLVM::llvm_pass_type(const TypeSpec& typespec)
else if (t == TypeDesc::INT)
lt = ll.type_int();
else if (t == TypeDesc::STRING)
lt = (llvm::Type*)ll.type_string();
lt = (llvm::Type*)ll.type_ustring();
else if (t.aggregate == TypeDesc::VEC3)
lt = (llvm::Type*)ll.type_void_ptr(); //llvm_type_triple_ptr();
else if (t.aggregate == TypeDesc::MATRIX44)
@@ -226,6 +236,7 @@ static ustring fields[] = { ustring("P"),
ustring("tracedata"),
ustring("objdata"),
ustring("shadingcontext"),
ustring("shadingStateUniform"),
ustring("renderer"),
ustring("object2common"),
ustring("shader2common"),
@@ -256,7 +267,7 @@ BackendLLVM::llvm_global_symbol_ptr(ustring name)
int sg_index = ShaderGlobalNameToIndex(name);
OSL_ASSERT(sg_index >= 0);
return ll.void_ptr(ll.GEP(sg_ptr(), 0, sg_index),
fmtformat("glob_{}_voidptr", name));
llnamefmt("glob_{}_voidptr", name));
}
@@ -319,7 +330,7 @@ BackendLLVM::getOrAllocateLLVMSymbol(const Symbol& sym)
if (map_iter == named_values().end()) {
llvm::Value* a = llvm_alloca(sym.typespec(), sym.has_derivs(),
mangled_name);
llnamefmt("{}_mem", mangled_name));
named_values()[mangled_name] = a;
return a;
}
@@ -329,8 +340,9 @@ BackendLLVM::getOrAllocateLLVMSymbol(const Symbol& sym)
llvm::Value*
BackendLLVM::addCUDAVariable(const std::string& name, int size, int alignment,
const void* data, TypeDesc type)
BackendLLVM::addCUDAGlobalVariable(const std::string& name, int size,
int alignment, const void* init_data,
TypeDesc type)
{
OSL_ASSERT(use_optix()
&& "This function is only supposed to be used with OptiX!");
@@ -338,40 +350,16 @@ BackendLLVM::addCUDAVariable(const std::string& name, int size, int alignment,
llvm::Constant* constant = nullptr;
if (type == TypeDesc::TypeFloat) {
constant = llvm::ConstantFP::get(llvm::Type::getFloatTy(
ll.module()->getContext()),
*(float*)data);
constant = ll.constant(*(const float*)init_data);
} else if (type == TypeDesc::TypeInt) {
constant = llvm::ConstantInt::get(llvm::Type::getInt32Ty(
ll.module()->getContext()),
*(int*)data);
constant = ll.constant(*(const int*)init_data);
} else if (type == TypeDesc::TypeString) {
// Register the string with the OptiX renderer. The renderer will add
// the string to a global table and create an OptiX variable to hold the
// char*.
shadingsys().renderer()->register_string(((ustring*)data)->string(),
name);
#if OPTIX_VERSION < 70000
// Leave the variable uninitialized to prevent raw pointers from
// appearing in the generated code. The OptiX renderer will set the
// variable to the string address before the kernel is launched.
constant = llvm::ConstantInt::get(llvm::Type::getInt64Ty(
ll.module()->getContext()),
0);
m_varname_map[name] = ((ustring*)data)->string();
#else
// DeviceStrings use the ustring hash to identify themselves. These hashes will
// match on both the device and host side.
constant = llvm::ConstantInt::get(llvm::Type::getInt64Ty(
ll.module()->getContext()),
((ustring*)data)->hash());
m_varname_map[name] = ((ustring*)data)->string();
#endif
constant = ll.constant(((const ustring*)init_data)->hash());
// N.B. Since this is the OptiX side specifically, we will represent
// strings as the ustringhash, so we know it as a constant.
} else {
// Handle unspecified types as generic byte arrays
llvm::ArrayRef<uint8_t> arr_ref((uint8_t*)data, size);
llvm::ArrayRef<uint8_t> arr_ref((uint8_t*)init_data, size);
constant = llvm::ConstantDataArray::get(ll.module()->getContext(),
arr_ref);
}
@@ -387,9 +375,7 @@ BackendLLVM::addCUDAVariable(const std::string& name, int size, int alignment,
g_var->setAlignment(alignment);
#endif
#if (OPTIX_VERSION < 70000)
g_var->setLinkage(llvm::GlobalValue::ExternalLinkage);
#endif
g_var->setLinkage(llvm::GlobalValue::PrivateLinkage);
g_var->setVisibility(llvm::GlobalValue::DefaultVisibility);
g_var->setInitializer(constant);
m_const_map[name] = g_var;
@@ -399,155 +385,32 @@ BackendLLVM::addCUDAVariable(const std::string& name, int size, int alignment,
void
BackendLLVM::createOptixMetadata(const std::string& name, const Symbol& sym)
{
// Create additional variables with the semantic information needed by OptiX
// to access the global variable created above.
//
// There is no need to retain pointers to these variables, since they are not
// accessed during execution. They are only used internally by OptiX.
//
// Refer to the OptiX API documentation and optix_defines.h in the OptiX SDK
// for more information.
OSL_ASSERT(use_optix()
&& "This function is only supported when using OptiX!");
auto mangle_name = [](const std::string& name, const std::string& prefix) {
return fmtformat("_ZN{}rti_internal_{}{}{}E", prefix.size() + 13,
prefix, name.size(), name);
};
std::string optix_type;
const TypeDesc type = sym.typespec().simpletype();
if (!sym.typespec().is_array()) {
optix_type =
// Documented built-in types
(type == TypeDesc::TypeInt) ? "int"
: (type == TypeDesc::TypeFloat) ? "float"
: (type == TypeDesc::TypePoint) ? "float3"
: (type == TypeDesc::TypeVector) ? "float3"
: (type == TypeDesc::TypeNormal) ? "float3"
: (type == TypeDesc::TypeColor) ? "float3"
: (type == TypeDesc::TypeMatrix) ? "matrix"
: (type == TypeDesc::TypeString)
? "uint64_t"
:
// Catch-all for types that fall through, if there are any.
type.c_str();
// NB: TypeMatrix is assumed to be 4x4 and will be treated by OptiX as a
// user datatype (i.e., a generic struct).
} else {
// OptiX should handle int and float vectors between 2 and 4 dimensions
// with no problem. Larger arrays, or arrays of other element types,
// will be treated as a user datatype and will not work natively with
// OptiX's variable mechanism.
optix_type = fmtformat("{}{}", sym.typespec().elementtype(),
sym.typespec().arraylength());
}
struct rti_typeinfo {
unsigned int kind = 0x796152; // _OPTIX_VARIABLE
unsigned int size;
} type_info;
type_info.size = sym.size();
int type_enum = 0x1337; // _OPTIX_TYPE_ENUM_UNKNOWN
char zero = 0;
addCUDAVariable(mangle_name(name, "typeinfo"), 8, 4, &type_info);
addCUDAVariable(mangle_name(name, "typename"), optix_type.size() + 1, 16,
optix_type.data());
addCUDAVariable(mangle_name(name, "typeenum"), 4, 4, &type_enum,
TypeDesc::TypeInt);
addCUDAVariable(mangle_name(name, "semantic"), 1, 1, &zero);
addCUDAVariable(mangle_name(name, "annotation"), 1, 1, &zero);
}
llvm::Value*
BackendLLVM::getOrAllocateCUDAVariable(const Symbol& sym, bool addMetadata)
BackendLLVM::getOrAllocateCUDAVariable(const Symbol& sym)
{
OSL_ASSERT(use_optix()
&& "This function is only supported when using OptiX!");
std::ostringstream ss;
ss.imbue(std::locale::classic()); // force C locale
if (sym.typespec().is_string()) {
// Use the ustring hash to create a name for the symbol that's based on
// the string contents
//
// TODO: Collisions between variable names are unlikely, but still
// possible. Using something like a counter to handle collisions
// is unattractive because it depends on the order in which
// strings are encountered at run time.
//
// For now I am simply appending the length to the hash, but a
// more robust solution may be called for.
// We need to sanitize the symbol name for PTX compatibility. Also, if the
// sym name starts with a dollar sign, which are not allowed in PTX
// variable names, then prepend another underscore.
std::string sym_name = Strutil::replace(sym.name(), ".", "_", true);
ss << "ds_"
#if OPTIX_VERSION >= 70000
<< group().name() << "_" << group().id() << "_"
#endif
<< std::setbase(16) << std::setfill('0') << std::setw(16)
<< sym.get_string().hash() << "_" << std::setbase(16)
<< std::setfill('0') << std::setw(4) << sym.get_string().length();
auto it = m_varname_map.find(ss.str());
const std::string old_str = (it != m_varname_map.end()) ? it->second
: "";
if (old_str != "" && old_str != sym.get_string().string()) {
std::cerr << "Warning: variable name collision between " << old_str
<< " and " << sym.get_string() << std::endl;
}
} else {
// We need to sanitize the symbol name for PTX compatibility
std::string sym_name = sym.name().c_str();
std::replace(sym_name.begin(), sym_name.end(), '.', '_');
std::string var_name = fmtformat("{}_{}_{}_{}_{}", sym_name,
group().name(), group().id(),
inst()->layername(), sym.layer());
// Leading dollar signs are not allowed in PTX variable names,
// so prepend an underscore.
if (var_name[0] == '$') {
ss << '_';
}
ss << var_name;
}
const std::string name = ss.str();
std::string name
= fmtformat("{}{}_{}_{}_{}", sym_name.front() == '$' ? "_" : "",
sym_name, group().name(), inst()->layername(), sym.layer());
// Return the Value if it has already been allocated
std::map<std::string, llvm::GlobalVariable*>::iterator it
= get_const_map().find(name);
if (it != get_const_map().end()) {
auto it = get_const_map().find(name);
if (it != get_const_map().end())
return it->second;
}
#if (OPTIX_VERSION < 70000)
// Add the extra metadata needed to make the variable visible to OptiX.
if (addMetadata || sym.typespec().is_string())
createOptixMetadata(name, sym);
#endif
// TODO: Figure out the actual CUDA alignment requirements for the various
// OSL types. For now, be somewhat conservative and assume 8 for
// non-scalar types.
int alignment = (sym.typespec().is_scalarnum()) ? 4 : 8;
llvm::Value* cuda_var = addCUDAVariable(name, sym.size(), alignment,
sym.data(),
sym.typespec().simpletype());
return cuda_var;
return addCUDAGlobalVariable(name, sym.size(), alignment, sym.data(),
sym.typespec().simpletype());
}
@@ -565,38 +428,37 @@ BackendLLVM::llvm_get_pointer(const Symbol& sym, int deriv,
llvm::Value* result = NULL;
if (sym.symtype() == SymTypeConst) {
TypeSpec elemtype = sym.typespec().elementtype();
if (use_optix()) {
// Check the constant map for the named Symbol; if it's found, then
// a GlobalVariable has been created for it
llvm::Value* ptr = getOrAllocateCUDAVariable(sym);
if (ptr) {
llvm::Type* cast_type
= (!sym.typespec().is_string())
? ll.type_ptr(llvm_type(sym.typespec().elementtype()))
: ll.type_void_ptr();
result = ll.ptr_cast(ptr, cast_type);
result = llvm_ptr_cast(ptr, llvm_typedesc(elemtype),
llnamefmt("cast_to_{}_", sym.typespec()));
// N.B. llvm_typedesc() for a string will know that on OptiX,
// strings are actually represented as just the hash.
}
} else {
// For constants, start with *OUR* pointer to the constant values.
result = ll.ptr_cast(ll.constant_ptr(sym.data()),
ll.type_ptr(
llvm_type(sym.typespec().elementtype())));
// For constants on the CPU side, start with *OUR* pointer to the
// constant values.
result = ll.constant_ptr(sym.data(),
ll.type_ptr(llvm_type(elemtype)));
}
} else {
// Start with the initial pointer to the variable's memory location
// If the symbol is not a SymTypeConst, then start with the initial
// pointer to the variable's memory location.
result = getLLVMSymbolBase(sym);
}
if (!result)
return NULL; // Error
// If it's an array or we're dealing with derivatives, step to the
// right element.
// If it's an array or we're dealing with derivatives, step to the right
// element.
TypeDesc t = sym.typespec().simpletype();
if (t.arraylen || has_derivs) {
int d = deriv * std::max(1, t.arraylen);
if (arrayindex)
if (arrayindex && d)
arrayindex = ll.op_add(arrayindex, ll.constant(d));
else
arrayindex = ll.constant(d);
@@ -642,13 +504,14 @@ BackendLLVM::llvm_load_value(const Symbol& sym, int deriv,
return ll.constant(sym.get_float(component));
}
if (sym.typespec().is_string()) {
return ll.constant(sym.get_string());
return llvm_load_string(sym.get_string());
}
OSL_ASSERT(0 && "unhandled constant type");
}
return llvm_load_value(llvm_get_pointer(sym), sym.typespec(), deriv,
arrayindex, component, cast, sym.name().string());
arrayindex, component, cast,
llnamefmt("{}_", sym.name()));
}
@@ -688,46 +551,20 @@ BackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type, int deriv,
result = ll.op_float_to_int(result);
else if (type.is_int() && cast == TypeDesc::TypeFloat)
result = ll.op_int_to_float(result);
else if (type.is_string() && cast == TypeDesc::LONGLONG)
else if (type.is_string() && cast == TypeDesc::LONGLONG) {
result = ll.ptr_to_cast(result, ll.type_longlong());
return result;
}
llvm::Value*
BackendLLVM::llvm_load_device_string(const Symbol& sym, bool follow)
{
// TODO: need to make this work with arrays of strings
OSL_ASSERT(use_optix() && "This is only intended to be used with CUDA");
// Recover the userdata index for non-constant parameters
int userdata_index = find_userdata_index(sym);
llvm::Value* val = NULL;
if (sym.symtype() == SymTypeLocal || sym.symtype() == SymTypeTemp) {
// Handle temporary and local variables
val = getOrAllocateLLVMSymbol(sym);
val = ll.ptr_cast(val, ll.type_longlong_ptr());
} else if (userdata_index < 0) {
// Handle non-varying variables
OSL_DASSERT(sym.data() && "NULL data in non-varying string");
val = getOrAllocateCUDAVariable(sym);
} else {
// Handle potentially varying variables
val = ll.ptr_cast(groupdata_field_ptr(2 + userdata_index),
ll.type_longlong_ptr());
// FIXME -- is this case ever used? Seems strange.
}
// It's preferable to deal with device strings "symbolically" through the
// CUDA variable (essentially a char**), which helps keep the code
// portable. But sometimes it's necessary to handle the underlying char*
// directly, e.g. when printing or writing out a closure param.
if (follow)
val = ll.int_to_ptr_cast(ll.op_load(val));
// We still disguise hashed strings as char*. Ideally, we would only do
// that if the rep were a charptr, but we disguise the hashes as char*'s
// also to avoid ugliness with function signatures differing between CPU
// and GPU. Maybe some day we'll use the hash representation on both
// sides?
if (type.is_string() && ll.ustring_rep() != LLVM_Util::UstringRep::charptr)
result = ll.int_to_ptr_cast(result);
return val;
return result;
}
@@ -761,13 +598,8 @@ BackendLLVM::llvm_load_constant_value(const Symbol& sym, int arrayindex,
int ncomps = (int)sym.typespec().aggregate();
return ll.constant(sym.get_float(ncomps * arrayindex + component));
}
if (sym.typespec().is_string() && use_optix()) {
OSL_DASSERT((arrayindex == 0)
&& "String arrays are not currently supported in OptiX");
return llvm_load_device_string(sym, /*follow*/ false);
}
if (sym.typespec().is_string()) {
return ll.constant(sym.get_string(arrayindex));
return llvm_load_string(sym.get_string(arrayindex));
}
OSL_ASSERT(0 && "unhandled constant type");
@@ -917,16 +749,20 @@ BackendLLVM::llvm_store_component_value(llvm::Value* new_val, const Symbol& sym,
llvm::Value*
BackendLLVM::groupdata_field_ref(int fieldnum)
{
return ll.GEP(groupdata_ptr(), 0, fieldnum);
return ll.GEP(groupdata_ptr(), 0, fieldnum,
llnamefmt("{}_ref", m_groupdata_field_names[fieldnum]));
}
llvm::Value*
BackendLLVM::groupdata_field_ptr(int fieldnum, TypeDesc type)
{
llvm::Value* result = ll.void_ptr(groupdata_field_ref(fieldnum));
llvm::Value* result = groupdata_field_ref(fieldnum);
std::string llname = llnamefmt("{}_ptr", m_groupdata_field_names[fieldnum]);
if (type != TypeDesc::UNKNOWN)
result = ll.ptr_to_cast(result, llvm_type(type));
result = ll.ptr_to_cast(result, llvm_type(type), llname);
else
result = ll.void_ptr(result, llname);
return result;
}
@@ -969,8 +805,6 @@ BackendLLVM::llvm_call_function(const char* name, cspan<const Symbol*> args,
const Symbol& s = *(args[i]);
if (s.typespec().is_closure())
valargs[i] = llvm_load_value(s);
else if (use_optix() && s.typespec().is_string())
valargs[i] = llvm_load_device_string(s, /*follow*/ true);
else if (s.typespec().simpletype().aggregate > 1
|| (deriv_ptrs && s.has_derivs()))
valargs[i] = llvm_void_ptr(s);
@@ -980,6 +814,8 @@ BackendLLVM::llvm_call_function(const char* name, cspan<const Symbol*> args,
return ll.call_function(name, cspan<llvm::Value*>(valargs, args.size()));
}
llvm::Value*
BackendLLVM::llvm_test_nonzero(Symbol& val, bool test_derivs)
{
@@ -1053,8 +889,8 @@ BackendLLVM::llvm_assign_impl(Symbol& Result, Symbol& Src, int arrayindex,
// the size difference is intended (by the optimizer).
if (result_t.is_array() && src_t.is_array() && arrayindex == -1) {
OSL_DASSERT(assignable(result_t.elementtype(), src_t.elementtype()));
llvm::Value* resultptr = llvm_void_ptr(Result);
llvm::Value* srcptr = llvm_void_ptr(Src);
llvm::Value* resultptr = llvm_get_pointer(Result);
llvm::Value* srcptr = llvm_get_pointer(Src);
int len = std::min(Result.size(), Src.size());
int align = result_t.is_closure_based()
? (int)sizeof(void*)
@@ -1075,10 +911,7 @@ BackendLLVM::llvm_assign_impl(Symbol& Result, Symbol& Src, int arrayindex,
TypeDesc basetype = TypeDesc::BASETYPE(rt.basetype);
const int num_components = rt.aggregate;
const bool singlechan = (srccomp != -1) || (dstcomp != -1);
if (use_optix() && Src.typespec().is_string()) {
llvm::Value* src = llvm_load_device_string(Src, /*follow*/ true);
llvm_store_value(ll.ptr_cast(src, ll.type_void_ptr()), Result);
} else if (!singlechan) {
if (!singlechan) {
for (int i = 0; i < num_components; ++i) {
llvm::Value* src_val
= Src.is_constant()
+57 -36
View File
@@ -122,22 +122,23 @@ public:
int component = 0,
TypeDesc cast = TypeDesc::UNKNOWN)
{
return (use_optix() && !sym.typespec().is_closure()
&& sym.typespec().is_string())
? llvm_load_device_string(sym, /*follow*/ true)
: llvm_load_value(sym, deriv, NULL, component, cast);
return llvm_load_value(sym, deriv, NULL, component, cast);
}
/// Load the address of a global device-side string pointer, which may
/// reside in a global variable, the groupdata struct, or a local value.
llvm::Value* llvm_load_device_string(const Symbol& sym, bool follow);
/// Convenience function to load a string for CPU or GPU device
llvm::Value* llvm_load_string(const Symbol& sym)
{
OSL_DASSERT(sym.typespec().is_string());
return use_optix() ? llvm_load_device_string(sym, /*follow*/ true)
: llvm_load_value(sym);
return llvm_load_value(sym);
}
/// Convenience function to load a constant string for CPU or GPU device.
/// On the GPU, we use the ustring hash, not the character pointer.
llvm::Value* llvm_load_string(ustring str) { return ll.constant(str); }
llvm::Value* llvm_load_string(string_view str)
{
return llvm_load_string(ustring(str));
}
/// Legacy version
@@ -148,10 +149,12 @@ public:
return llvm_load_value(sym, deriv, NULL, component, cast);
}
/// Return an llvm::Value* that is either a scalar and derivs is
/// false, or a pointer to sym's values (if sym is an aggregate or
/// derivs == true). Furthermore, if deriv == true and sym doesn't
/// have derivs, coerce it into a variable with zero derivs.
/// Return an llvm::Value* in the form that we will pass a float-based
/// symbol as a function argument to any "built-in" OSL function -- as a
/// simple value if the symbol is a scalar and no derivs are needed, or as
/// a pointer to the data in all other cases (aggregates, arrays, or
/// derivs needed). If deriv == true and sym doesn't have derivs, coerce
/// it into a variable having derivatives set to 0.0.
llvm::Value* llvm_load_arg(const Symbol& sym, bool derivs);
/// Just like llvm_load_arg(sym,deriv), except use use sym's derivs
@@ -216,16 +219,16 @@ public:
/// Allocate a CUDA variable for the given OSL symbol and return a pointer
/// to the corresponding LLVM GlobalVariable, or return the pointer if it
/// has already been allocated.
llvm::Value* getOrAllocateCUDAVariable(const Symbol& sym,
bool addMetadata = false);
llvm::Value* getOrAllocateCUDAVariable(const Symbol& sym);
/// Create a CUDA global variable and add it to the current Module
llvm::Value* addCUDAVariable(const std::string& name, int size,
int alignment, const void* data,
TypeDesc type = TypeDesc::UNKNOWN);
/// Create the extra semantic information needed for OptiX variables
void createOptixMetadata(const std::string& name, const Symbol& sym);
/// Create a named CUDA global variable with the given type, size, and
/// alignment, and add it to the current Module. It will be initialized
/// with data pointed to by init_data. A record will be also added to
/// m_const_map, and will be retrieved by subsequent calls to
/// getOrAllocateCUDAVariable().
llvm::Value* addCUDAGlobalVariable(const std::string& name, int size,
int alignment, const void* init_data,
TypeDesc type = TypeDesc::UNKNOWN);
/// Retrieve an llvm::Value that is a pointer holding the start address
/// of the specified symbol. This always works for globals and params;
@@ -272,14 +275,18 @@ public:
///
llvm::Value* sg_void_ptr() { return ll.void_ptr(m_llvm_shaderglobals_ptr); }
llvm::Value* llvm_ptr_cast(llvm::Value* val, const TypeSpec& type)
/// Cast the pointer variable specified by val to a pointer to the
/// basic type comprising `type`.
llvm::Value* llvm_ptr_cast(llvm::Value* val, const TypeSpec& type,
const std::string& llname = {})
{
return ll.ptr_cast(val, type.simpletype());
return ll.ptr_cast(val, type.simpletype(), llname);
}
llvm::Value* llvm_void_ptr(const Symbol& sym, int deriv = 0)
{
return ll.void_ptr(llvm_get_pointer(sym, deriv));
return ll.void_ptr(llvm_get_pointer(sym, deriv),
llnamefmt("{}_voidptr", sym.mangled()));
}
/// Return the LLVM type handle for a structure of the common group
@@ -405,9 +412,13 @@ public:
TypeDesc llvm_typedesc(const TypeSpec& typespec)
{
return typespec.is_closure_based()
? TypeDesc(TypeDesc::PTR, typespec.arraylength())
: typespec.simpletype();
if (typespec.is_closure_based())
return TypeDesc(TypeDesc::PTR, typespec.arraylength());
else if (use_optix() && typespec.is_string_based()) {
// On the OptiX side, we use the uint64 hash to represent a string
return TypeDesc(TypeDesc::UINT64, typespec.arraylength());
} else
return typespec.simpletype();
}
/// Generate the appropriate llvm type definition for a TypeSpec
@@ -440,7 +451,7 @@ public:
llvm::BasicBlock* llvm_exit_instance_block()
{
if (!m_exit_instance_block) {
std::string name = fmtformat("{}_{}_exit_", inst()->layername(),
std::string name = llnamefmt("{}_{}_exit_", inst()->layername(),
inst()->id());
m_exit_instance_block = ll.new_basic_block(name);
}
@@ -483,6 +494,18 @@ public:
LLVM_Util ll;
// Utility for constructing names for llvm symbols. It creates a formatted
// string if the shading system's "llvm_output_bitcode" option is set,
// otherwise it takes a shortcut and returns an empty string (since nobody
// is going to see the pretty bitcode anyway).
template<typename Str, typename... Args>
OSL_NODISCARD inline std::string llnamefmt(const Str& fmt,
Args&&... args) const
{
return m_name_llvm_syms ? fmtformat(fmt, std::forward<Args>(args)...)
: std::string();
}
private:
std::vector<int> m_layer_remap; ///< Remapping of layer ordering
std::set<int> m_layers_already_run; ///< List of layers run
@@ -508,18 +531,16 @@ private:
llvm::Type* m_llvm_type_closure_component; // LLVM type for ClosureComponent
llvm::PointerType* m_llvm_type_prepare_closure_func;
llvm::PointerType* m_llvm_type_setup_closure_func;
int m_llvm_local_mem; // Amount of memory we use for locals
int m_llvm_local_mem; // Amount of memory we use for locals
bool m_name_llvm_syms; // Whether to name LLVM symbols
// A mapping from symbol names to llvm::GlobalVariables
std::map<std::string, llvm::GlobalVariable*> m_const_map;
// A mapping from canonical strings to string variable names, used to
// detect collisions that might occur due to using the string hash to
// create variable names.
std::map<std::string, std::string> m_varname_map;
// Name of each indexed field in the groupdata, mostly for debugging.
std::vector<std::string> m_groupdata_field_names;
bool m_use_optix; ///< Compile for OptiX?
bool m_use_rs_bitcode; /// To use free function versions of Renderer Service functions.
friend class ShadingSystemImpl;
+1 -13
View File
@@ -240,7 +240,7 @@ private:
static constexpr OpcodeTest no_test = nullptr;
// Map opcode names to a Dependency info
std::unordered_map<ustring, Dependency, ustringHash> m_lookup;
std::unordered_map<ustring, Dependency> m_lookup;
/// Return the ptr to the symbol that is the argnum-th argument to the
/// given op in the instance.
@@ -2303,17 +2303,6 @@ struct Analyzer {
}
}
void make_closures_varying()
{
// We assume that closures are always stored as varying pointers
FOREACH_PARAM(Symbol & s, inst())
{
if (s.typespec().is_closure()) {
recursively_mark_varying(&s);
}
}
}
void push_varying_of_upstream_connections()
{
OSL_DEV_ONLY(std::cout << "connections to layer begin" << std::endl);
@@ -2406,7 +2395,6 @@ BatchedAnalysis::analyze_layer(ShaderInstance* inst)
analyzer.push_varying_of_shader_globals();
analyzer.make_interpolated_parameters_varying();
analyzer.make_renderer_outputs_varying();
analyzer.make_closures_varying();
analyzer.push_varying_of_upstream_connections();
analyzer.push_varying_of_implicitly_varying_ops();
+8 -6
View File
@@ -188,7 +188,7 @@ BatchedBackendLLVM::llvm_pass_type(const TypeSpec& typespec)
else if (t == TypeDesc::INT)
lt = ll.type_int();
else if (t == TypeDesc::STRING)
lt = (llvm::Type*)ll.type_string();
lt = (llvm::Type*)ll.type_ustring();
else if (t.aggregate == TypeDesc::VEC3)
lt = (llvm::Type*)ll.type_void_ptr(); //llvm_type_triple_ptr();
else if (t.aggregate == TypeDesc::MATRIX44)
@@ -867,7 +867,7 @@ BatchedBackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type,
|| (ll.llvm_typeof(result) == ll.type_float())
|| (ll.llvm_typeof(result) == ll.type_triple())
|| (ll.llvm_typeof(result) == ll.type_int())
|| (ll.llvm_typeof(result) == (llvm::Type*)ll.type_string())
|| (ll.llvm_typeof(result) == ll.type_ustring())
|| (ll.llvm_typeof(result) == ll.type_matrix())
|| (ll.llvm_typeof(result) == ll.type_longlong())) {
result = ll.widen_value(result);
@@ -888,7 +888,7 @@ BatchedBackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type,
(ll.llvm_typeof(result) == ll.type_wide_float())
|| (ll.llvm_typeof(result) == ll.type_wide_int())
|| (ll.llvm_typeof(result) == ll.type_wide_triple())
|| (ll.llvm_typeof(result) == ll.type_wide_string())
|| (ll.llvm_typeof(result) == ll.type_wide_ustring())
|| (ll.llvm_typeof(result) == ll.type_wide_bool())
|| (ll.llvm_typeof(result) == ll.type_wide_matrix())
|| (ll.llvm_typeof(result) == ll.type_wide_longlong()));
@@ -1218,7 +1218,8 @@ BatchedBackendLLVM::llvm_store_value(llvm::Value* new_val, llvm::Value* dst_ptr,
if (!type.is_closure_based() && t.aggregate > 1)
dst_ptr = ll.GEP(dst_ptr, 0, component);
if (ll.type_ptr(ll.llvm_typeof(new_val)) != ll.llvm_typeof(dst_ptr)) {
if ((const llvm::Type*)ll.type_ptr(ll.llvm_typeof(new_val))
!= ll.llvm_typeof(dst_ptr)) {
std::cerr << " new_val type=";
{
llvm::raw_os_ostream os_cerr(std::cerr);
@@ -1231,7 +1232,7 @@ BatchedBackendLLVM::llvm_store_value(llvm::Value* new_val, llvm::Value* dst_ptr,
}
std::cerr << std::endl;
}
OSL_ASSERT(ll.type_ptr(ll.llvm_typeof(new_val))
OSL_ASSERT((const llvm::Type*)ll.type_ptr(ll.llvm_typeof(new_val))
== ll.llvm_typeof(dst_ptr));
// Finally, store the value.
@@ -1766,7 +1767,8 @@ BatchedBackendLLVM::llvm_test_nonzero(const Symbol& val, bool test_derivs)
llvm::Value* llvmValue = llvm_get_pointer(val);
//OSL_DEV_ONLY(std::cout << "llvmValue type=" << ll.llvm_typenameof(llvmValue) << std::endl);
if (ll.llvm_typeof(llvmValue) == ll.type_ptr(ll.type_bool())) {
if (ll.llvm_typeof(llvmValue)
== (const llvm::Type*)ll.type_ptr(ll.type_bool())) {
return ll.op_ne(llvm_load_value(val), ll.constant_bool(0));
} else {
return ll.op_ne(llvm_load_value(val), ll.constant(0));
+16 -84
View File
@@ -1263,7 +1263,6 @@ LLVMGEN(llvm_gen_add)
OSL_ASSERT(!A.typespec().is_array() && !B.typespec().is_array());
if (Result.typespec().is_closure()) {
OSL_ASSERT(A.typespec().is_closure() && B.typespec().is_closure());
OSL_ASSERT(!A.is_uniform() && !B.is_uniform() && !result_is_uniform);
llvm::Value* valargs[] = { rop.sg_void_ptr(), rop.llvm_void_ptr(Result),
rop.llvm_void_ptr(A), rop.llvm_void_ptr(B),
rop.ll.mask_as_int(rop.ll.current_mask()) };
@@ -1677,7 +1676,6 @@ LLVMGEN(llvm_gen_modulus)
int num_components = type.aggregate;
#if 0
if (is_float && !op_is_uniform) {
// llvm 5.0.1 did not do a good job with op_mod when its
// parameters were <16xf32>. So we will go ahead
@@ -1704,9 +1702,7 @@ LLVMGEN(llvm_gen_modulus)
}
rop.ll.call_function(rop.build_name(func_spec), call_args);
} else
#endif
{
} else {
for (int i = 0; i < num_components; i++) {
llvm::Value* a = rop.loadLLVMValue(A, i, 0, type, op_is_uniform);
llvm::Value* b = rop.loadLLVMValue(B, i, 0, type, op_is_uniform);
@@ -7068,8 +7064,7 @@ LLVMGEN(llvm_gen_spline)
static void
llvm_gen_keyword_fill(BatchedBackendLLVM& rop, Opcode& op,
const ClosureRegistry::ClosureEntry* clentry,
ustring clname, llvm::Value* mem_void_ptr, int argsoffset,
int lane_index)
ustring clname, llvm::Value* mem_void_ptr, int argsoffset)
{
OSL_DASSERT(((op.nargs() - argsoffset) % 2) == 0);
@@ -7093,45 +7088,10 @@ llvm_gen_keyword_fill(BatchedBackendLLVM& rop, Opcode& op,
if (equivalent(p.type, ValueType) && !strcmp(key->c_str(), p.key)) {
// store data
OSL_DASSERT(p.offset + p.field_size <= clentry->struct_size);
bool arg_is_uniform = Value.is_uniform();
TypeDesc simpletype(Value.typespec().simpletype());
// We don't currently offer a helper macro in genclosure.h for creating
// keyword array parameters, so perhaps we can assume we don't need to
// support them
OSL_DASSERT(simpletype.arraylen == 0);
int num_components = simpletype.aggregate;
llvm::Value* dest_base = rop.ll.offset_ptr(mem_void_ptr,
p.offset);
dest_base = rop.llvm_ptr_cast(dest_base, p.type);
for (int c = 0; c < num_components; c++) {
llvm::Value* dest_elem;
if (num_components > 1)
dest_elem = rop.ll.GEP(dest_base, 0, c);
else
dest_elem = dest_base;
// NOTE: We don't want any uniform arguments to be
// widened, so our typical op_is_uniform doesn't do what we
// want for this when loading. So just pass arg_is_uniform
// which will avoid widening any uniform arguments.
llvm::Value* loaded
= rop.llvm_load_value(Value, 0, NULL, c,
TypeDesc::UNKNOWN,
/*op_is_uniform*/ arg_is_uniform,
/*index_is_uniform*/ true);
if (!arg_is_uniform) {
loaded = rop.ll.op_extract(loaded, lane_index);
}
rop.ll.op_unmasked_store(loaded, dest_elem);
}
llvm::Value* dst = rop.ll.offset_ptr(mem_void_ptr, p.offset);
llvm::Value* src = rop.llvm_void_ptr(Value);
rop.ll.op_memcpy(dst, src, (int)p.type.size(),
4 /* use 4 byte alignment for now */);
legal = true;
break;
}
@@ -7220,7 +7180,6 @@ LLVMGEN(llvm_gen_closure)
rop.ll.type_ptr(rop.llvm_type_closure_component_wide_ptr()));
llvm::Value* comp_wide_ptr = rop.ll.op_load(comp_wide_ptr_ptr);
llvm::Value* mask = rop.ll.current_mask();
// This is an unrolled vector-width loop. It was unrolled because it's
// was more expedient to write the for in C++ than IR, but if compilation
// of the extra ops becomes problematic, this choice can be revisited
@@ -7234,16 +7193,14 @@ LLVMGEN(llvm_gen_closure)
// For the weighted closures, we need a surrounding "if" so that it's safe
// for osl_allocate_weighted_closure_component to return NULL (unless we
// know for sure that it's constant weighted and that the weight is
// not zero). We also need the surrounding "if" to reject writing
// to closures that aren't masked.
// not zero).
llvm::BasicBlock* next_block = NULL;
llvm::BasicBlock* notnull_block = rop.ll.new_basic_block(
"non_null_and_masked_closure");
next_block = rop.ll.new_basic_block("");
llvm::Value* cond = rop.ll.op_and(
rop.ll.op_ne(rop.ll.ptr_cast(comp_ptr, rop.ll.type_void_ptr()),
rop.ll.void_ptr_null()),
rop.ll.test_mask_lane(mask, lane_index));
"non_null_closure");
next_block = rop.ll.new_basic_block("");
llvm::Value* cond
= rop.ll.op_ne(rop.ll.ptr_cast(comp_ptr, rop.ll.type_void_ptr()),
rop.ll.void_ptr_null());
rop.ll.op_branch(cond, notnull_block, next_block);
// If the closure has a "prepare" method, call
@@ -7276,30 +7233,7 @@ LLVMGEN(llvm_gen_closure)
int num_components = simpletype.aggregate;
llvm::Value* dest_base = rop.ll.offset_ptr(mem_void_ptr, p.offset);
llvm::Type* dest_type = rop.ll.llvm_type(
static_cast<const TypeSpec&>(p.type).simpletype());
dest_base = rop.ll.ptr_to_cast(dest_base, dest_type);
if (num_elements > 1) {
OSL_DASSERT(rop.ll.is_type_array(dest_type));
// The type is an array type,
// which means our pointer is to an array type,
// not to &[0] (the address of the 1st element).
// IE: typedef int Int5Array[5];
// Int5Array *dest_base;
// in contrast to what most of use might consider an array pointer
// int *dest_base;
// So if we dereference Int5Array* to with [4], the 5th element,
// we would be really be pointing to ((int *)dest_base)[5*4] which is
// out of bounds of our 1 instance of Int5Array.
// Thus when dealing with arrays we will just dereference it and get the address to get
// the address of the 1st element.
dest_base = rop.ll.GEP(dest_type, dest_base, 0, 0);
llvm::Type* element_type = rop.ll.element_type_of(dest_type);
dest_type = element_type;
}
dest_base = rop.llvm_ptr_cast(dest_base, p.type);
for (int a = 0; a < num_elements; ++a) {
llvm::Value* arrind = simpletype.arraylen ? rop.ll.constant(a)
@@ -7307,9 +7241,7 @@ LLVMGEN(llvm_gen_closure)
for (int c = 0; c < num_components; c++) {
llvm::Value* dest_elem;
if (num_components > 1)
dest_elem = rop.ll.GEP(dest_type, dest_base, a, c);
else if (num_elements > 1)
dest_elem = rop.ll.GEP(dest_type, dest_base, a);
dest_elem = rop.ll.GEP(dest_base, a, c);
else
dest_elem = dest_base;
@@ -7343,7 +7275,7 @@ LLVMGEN(llvm_gen_closure)
}
llvm_gen_keyword_fill(rop, op, clentry, closure_name, mem_void_ptr,
2 + weighted + clentry->nformal, lane_index);
2 + weighted + clentry->nformal);
if (next_block)
rop.ll.op_branch(next_block);
@@ -7774,7 +7706,7 @@ LLVMGEN(llvm_gen_pointcloud_write)
TypeDesc::NOSEMANTICS, nattrs } };
TypeSpec valuesArrayType { TypeDesc { TypeDesc::PTR, TypeDesc::SCALAR,
TypeDesc::NOSEMANTICS, nattrs } };
llvm::Value* names = rop.ll.op_alloca(rop.ll.type_string(), nattrs);
llvm::Value* names = rop.ll.op_alloca(rop.ll.type_ustring(), nattrs);
llvm::Value* types = rop.ll.op_alloca(rop.ll.type_typedesc(), nattrs);
llvm::Value* values = rop.ll.op_alloca(rop.ll.type_void_ptr(), nattrs);
+5 -21
View File
@@ -760,11 +760,10 @@ BatchedBackendLLVM::llvm_type_batched_trace_options()
std::vector<llvm::Type*> sg_types;
// Uniform values of the batch
sg_types.push_back(ll.type_float()); // mindist
sg_types.push_back(ll.type_float()); // maxdist
sg_types.push_back(ll.type_int()); // shade
sg_types.push_back(
reinterpret_cast<llvm::Type*>(ll.type_string())); // traceset
sg_types.push_back(ll.type_float()); // mindist
sg_types.push_back(ll.type_float()); // maxdist
sg_types.push_back(ll.type_int()); // shade
sg_types.push_back(ll.type_ustring()); // traceset
m_llvm_type_batched_trace_options = ll.type_struct(sg_types, "TraceOptions",
false /*is_packed*/);
@@ -1252,8 +1251,7 @@ BatchedBackendLLVM::llvm_assign_initial_value(
data_type = ll.type_float();
} else if (elemtype.is_string()) {
ptr_type = ll.type_ustring_ptr();
data_type = static_cast<llvm::Type*>(
ll.type_string());
data_type = ll.type_ustring();
} else if (elemtype.is_int()) {
ptr_type = ll.type_int_ptr();
data_type = ll.type_int();
@@ -1815,7 +1813,6 @@ BatchedBackendLLVM::build_llvm_init()
FOREACH_PARAM(Symbol & sym, gi)
{
if (sym.typespec().is_closure_based()) {
OSL_ASSERT(sym.is_varying());
int arraylen = std::max(1, sym.typespec().arraylength());
llvm::Value* val = ll.constant_ptr(NULL, ll.type_void_ptr());
if (!sym.is_uniform())
@@ -2694,21 +2691,9 @@ BatchedBackendLLVM::run()
// entry points, as well as for all the external functions that are
// just declarations (not definitions) in the module (which we have
// conveniently stashed in external_function_names).
#if 0
std::vector<std::string> entry_function_names;
entry_function_names.push_back (ll.func_name(init_func));
for (int layer = 0; layer < nlayers; ++layer) {
// set_inst (layer);
llvm::Function* f = funcs[layer];
if (f && group().is_entry_layer(layer))
entry_function_names.push_back (ll.func_name(f));
}
ll.internalize_module_functions ("osl_", external_function_names, entry_function_names);
#else
std::unordered_set<llvm::Function*> external_functions;
external_functions.insert(init_func);
for (int layer = 0; layer < nlayers; ++layer) {
// set_inst (layer);
llvm::Function* f = funcs[layer];
// If we plan to call bitcode_string of a layer's function after optimization
// it may not exist after optimization unless we treat it as external.
@@ -2717,7 +2702,6 @@ BatchedBackendLLVM::run()
}
}
ll.prune_and_internalize_module(external_functions);
#endif
// Debug code to dump the pre-optimized bitcode to a file
if (llvm_debug() >= 2 || shadingsys().llvm_output_bitcode()) {
+4 -6
View File
@@ -117,7 +117,6 @@ BatchedRendererServices<WidthT>::resolve_udim_uniform(
if (!texture_handle)
texture_handle = texturesys()->get_texture_handle(filename,
texture_thread_info);
#if OPENIMAGEIO_VERSION >= 20307
if (texturesys()->is_udim(texture_handle)) {
// Newer versions of the TextureSystem interface are able to determine the
// specific UDIM tile we're using.
@@ -131,9 +130,9 @@ BatchedRendererServices<WidthT>::resolve_udim_uniform(
udim_handle = texture_handle;
}
return udim_handle;
} else
#endif
} else {
return texture_handle;
}
}
@@ -151,7 +150,6 @@ BatchedRendererServices<WidthT>::resolve_udim(
if (!texture_handle)
texture_handle = texturesys()->get_texture_handle(filename,
texture_thread_info);
#if OPENIMAGEIO_VERSION >= 20307
if (texturesys()->is_udim(texture_handle)) {
// Newer versions of the TextureSystem interface are able to determine the
// specific UDIM tile we're using.
@@ -167,9 +165,9 @@ BatchedRendererServices<WidthT>::resolve_udim(
}
wresult[l] = udim_handle;
});
} else
#endif
} else {
assign_all(wresult, texture_handle);
}
}
+1 -6
View File
@@ -248,10 +248,10 @@ UNARY_OP_IMPL(log10)
UNARY_OP_IMPL(exp)
UNARY_OP_IMPL(exp2)
UNARY_OP_IMPL(expm1)
BINARY_OP_IMPL(pow)
UNARY_OP_IMPL(erf)
UNARY_OP_IMPL(erfc)
BINARY_OP_IMPL(pow)
DECL(osl_pow_vvf, "xXXf")
DECL(osl_pow_dvdvdf, "xXXX")
DECL(osl_pow_dvvdf, "xXXX")
@@ -285,12 +285,7 @@ DECL(osl_fabs_ii, "ii")
UNARY_OP_IMPL(abs)
UNARY_OP_IMPL(fabs)
BINARY_OP_IMPL(fmod)
DECL(osl_fmod_vvf, "xXXf")
DECL(osl_fmod_dvdvdf, "xXXX")
DECL(osl_fmod_dvvdf, "xXXX")
DECL(osl_fmod_dvdvf, "xXXf")
DECL(osl_smoothstep_ffff, "ffff")
DECL(osl_smoothstep_dfffdf, "xXffX")
+4 -3
View File
@@ -128,9 +128,10 @@ ShadingContext::execute_init(ShaderGroup& sgroup, int shadeindex,
RunLLVMGroupFunc run_func = sgroup.llvm_compiled_init();
if (!run_func)
return false;
ssg.context = this;
ssg.renderer = renderer();
ssg.Ci = NULL;
ssg.context = this;
ssg.shadingStateUniform = &(shadingsys().m_shading_state_uniform);
ssg.renderer = renderer();
ssg.Ci = NULL;
run_func(&ssg, m_heap.get(), userdata_base_ptr, output_base_ptr,
shadeindex);
}
+1 -1
View File
@@ -115,7 +115,7 @@ private:
};
typedef std::unordered_map<Query, QueryResult, QueryHash> QueryMap;
typedef std::unordered_map<ustring, int, ustringHash> DocMap;
typedef std::unordered_map<ustring, int> DocMap;
ShadingContext* m_context; // back-pointer to shading context
+16 -1
View File
@@ -244,7 +244,22 @@ ShaderInstance::parameters(const ParamValueList& params)
valuetype = TypeDesc::FLOAT;
}
if (!relaxed_equivalent(sm_typespec, valuetype)) {
// Relaxed rules just look to see that the types are isomorphic to each other (ie: same number of base values)
// Note that:
// * basetypes must match exactly (int vs float vs string)
// * valuetype cannot be unsized (we must know the concrete number of values)
// * if paramtype is sized (or not an array) just check for the total number of entries
// * if paramtype is unsized (shader writer is flexible about how many values come in) -- make sure we are a multiple of the target type
// * allow a single float setting a vec3 (or equivalent)
if (!(valuetype.basetype == paramtype.basetype
&& !valuetype.is_unsized_array()
&& ((!paramtype.is_unsized_array()
&& valuetype.basevalues() == paramtype.basevalues())
|| (paramtype.is_unsized_array()
&& valuetype.basevalues() % paramtype.aggregate
== 0)
|| (paramtype.is_vec3()
&& valuetype == TypeDesc::FLOAT)))) {
// We are being very relaxed in this mode, so if the user _still_ got it wrong
// something more serious is at play and we should treat it as an error.
shadingsys().errorfmt(
+37 -134
View File
@@ -6,6 +6,11 @@
#include <OpenImageIO/fmath.h>
#ifdef OSL_USE_OPTIX
# include <optix.h>
#endif
#include "oslexec_pvt.h"
#include <OSL/genclosure.h>
#include "backendllvm.h"
@@ -279,7 +284,7 @@ LLVMGEN(llvm_gen_printf)
const char* format = format_ustring.c_str();
std::string s;
int arg = format_arg + 1;
size_t optix_size = 0;
size_t optix_size = 0; // how much buffer size does optix need?
while (*format != '\0') {
if (*format == '%') {
if (format[1] == '%') {
@@ -345,42 +350,19 @@ LLVMGEN(llvm_gen_printf)
s += " ";
s += ourformat;
llvm::Value* loaded = nullptr;
if (rop.use_optix()
&& simpletype.basetype == TypeDesc::STRING) {
// In the OptiX case, we register each string separately.
if (simpletype.arraylen >= 1) {
// Mangle the element's name in case llvm_load_device_string calls getOrAllocateLLVMSymbol
ustring name
= ustring::fmtformat("__symname__{}[{}]",
sym.mangled(), a);
Symbol lsym(name, TypeDesc::TypeString,
sym.symtype());
lsym.set_dataptr(SymArena::Absolute,
&((ustring*)sym.dataptr())[a]);
loaded
= rop.llvm_load_device_string(lsym,
/*follow*/ true);
} else {
loaded
= rop.llvm_load_device_string(sym,
/*follow*/ true);
}
llvm::Value* loaded = rop.llvm_load_value(sym, 0, arrind,
c);
if (simpletype.basetype == TypeDesc::FLOAT) {
// C varargs convention upconverts float->double.
loaded = rop.ll.op_float_to_double(loaded);
// Ensure that 64-bit values are aligned to 8-byte boundaries
optix_size = (optix_size + sizeof(double) - 1)
& ~(sizeof(double) - 1);
optix_size += sizeof(double);
} else if (simpletype.basetype == TypeDesc::INT)
optix_size += sizeof(int);
else if (simpletype.basetype == TypeDesc::STRING)
optix_size += sizeof(uint64_t);
} else {
loaded = rop.llvm_load_value(sym, 0, arrind, c);
if (simpletype.basetype == TypeDesc::FLOAT) {
// C varargs convention upconverts float->double.
loaded = rop.ll.op_float_to_double(loaded);
// Ensure that 64-bit values are aligned to 8-byte boundaries
optix_size = (optix_size + sizeof(double) - 1)
& ~(sizeof(double) - 1);
optix_size += sizeof(double);
} else if (simpletype.basetype == TypeDesc::INT)
optix_size += sizeof(int);
}
call_args.push_back(loaded);
}
}
@@ -397,10 +379,8 @@ LLVMGEN(llvm_gen_printf)
// is no argument.
if (rop.use_optix() && arg == format_arg + 1) {
call_args.push_back(rop.ll.void_ptr_null());
#if OPTIX_VERSION >= 70000
// we push the size of the arguments on the stack
optix_size += sizeof(uint64_t);
#endif
}
// Some ops prepend things
@@ -411,58 +391,33 @@ LLVMGEN(llvm_gen_printf)
// Now go back and put the new format string in its place
if (!rop.use_optix()) {
call_args[new_format_slot] = rop.ll.constant(s.c_str());
call_args[new_format_slot] = rop.llvm_load_string(s);
} else {
// In OptiX 6 we do this:
// void* args = { arg0, arg1, arg2 };
// osl_printf(sg, fmt, args);
// vprintf(fmt, args);
// However, in the OptiX7+ case, we do this:
// In OptiX7+ case, we do this:
// void* args = { args_size, arg0, arg1, arg2 };
// (where args_size is the size of arg0 + arg1 + arg2...)
//
#if !defined(OSL_USE_OPTIX) || OPTIX_VERSION < 70000
Symbol sym(format_sym.name(), format_sym.typespec(),
format_sym.symtype());
format_ustring = s;
sym.set_dataptr(SymArena::Absolute, &format_ustring);
call_args[new_format_slot] = rop.ll.int_to_ptr_cast(
rop.llvm_load_device_string(sym, /*follow*/ true));
#else
// Make sure host has the format string so it can print it
format_ustring = s;
rop.shadingsys().renderer()->register_string(format_ustring.string(),
"");
call_args[new_format_slot] = rop.ll.int_to_ptr_cast(
rop.ll.constant64(format_ustring.hash()));
#endif
size_t nargs = call_args.size() - (new_format_slot + 1);
call_args[new_format_slot] = rop.llvm_load_string(s);
size_t nargs = call_args.size() - (new_format_slot + 1);
// Allocate space to store the arguments to osl_printf().
#if !defined(OSL_USE_OPTIX) || OPTIX_VERSION < 70000
llvm::Value* voids = rop.ll.op_alloca(rop.ll.type_char(), optix_size,
std::string(), 8);
#else
// Don't forget to pad a little extra to hold the size of the arguments itself.
llvm::Value* voids = rop.ll.op_alloca(rop.ll.type_char(),
optix_size + sizeof(uint64_t),
std::string(), 8);
#endif
llvm::Value* voids = rop.ll.op_alloca(
rop.ll.type_char(), optix_size + sizeof(uint64_t),
fmtformat("printf_argbuf_L{}sz{}_", op.sourceline(), optix_size),
8);
#if defined(OSL_USE_OPTIX) && OPTIX_VERSION >= 70000
// Size of the collection of arguments comes before all the arguments
{
llvm::Value* args_size = rop.ll.constant64(optix_size);
llvm::Value* memptr = rop.ll.offset_ptr(voids, 0);
llvm::Value* iptr = rop.ll.ptr_cast(memptr,
rop.ll.type_longlong_ptr());
rop.ll.type_longlong_ptr(),
"printf_argbuf_as_llptr");
rop.ll.op_store(args_size, iptr);
}
optix_size = sizeof(
uint64_t); // first 'args' element is the size of the argument list
#else
optix_size = 0;
#endif
for (size_t i = 0; i < nargs; ++i) {
llvm::Value* arg = call_args[new_format_slot + 1 + i];
if (arg->getType()->isFloatingPointTy()
@@ -1004,6 +959,7 @@ LLVMGEN(llvm_gen_select)
&& Result.typespec().is_float_based());
int num_components = type.aggregate;
int x_components = X.typespec().aggregate();
OSL_DASSERT(x_components <= 3);
bool derivs = (Result.has_derivs() && (A.has_derivs() || B.has_derivs()));
llvm::Value* zero = X.typespec().is_int() ? rop.ll.constant(0)
@@ -1600,23 +1556,8 @@ LLVMGEN(llvm_gen_construct_triple)
else if (op.opname() == "normal")
vectype = TypeDesc::NORMAL;
llvm::Value* from_arg = nullptr;
llvm::Value* to_arg = nullptr;
if (!rop.use_optix()) {
from_arg = rop.llvm_load_value(Space);
to_arg = rop.ll.constant(Strings::common);
} else {
// Create a Symbol for Strings::common. The symbol name isn't important,
// since a new name will be created based on the string hash.
//
// TODO: This pattern is used elsewhere (e.g., in llvm_assign_initial_value),
// so it might make sense to refactor it.
Symbol to_sym(ustring("Strings__common"), TypeDesc::TypeString,
SymTypeConst);
to_sym.set_dataptr(SymArena::Absolute, (void*)&Strings::common);
from_arg = rop.llvm_load_device_string(Space, /*follow*/ true);
to_arg = rop.llvm_load_device_string(to_sym, /*follow*/ true);
}
llvm::Value* from_arg = rop.llvm_load_value(Space);
llvm::Value* to_arg = rop.llvm_load_string(Strings::common);
llvm::Value* args[] = { rop.sg_void_ptr(),
rop.llvm_void_ptr(Result),
@@ -1923,28 +1864,6 @@ LLVMGEN(llvm_gen_compare_op)
llvm::Value* final_result = 0;
ustring opname = op.opname();
if (rop.use_optix() && A.typespec().is_string()) {
OSL_DASSERT(B.typespec().is_string()
&& "Only string-to-string comparison is supported");
llvm::Value* a = rop.llvm_load_device_string(A, /*follow*/ true);
llvm::Value* b = rop.llvm_load_device_string(B, /*follow*/ true);
if (opname == op_eq) {
final_result = rop.ll.op_eq(a, b);
} else if (opname == op_neq) {
final_result = rop.ll.op_ne(a, b);
} else {
// Don't know how to handle this.
OSL_ASSERT(0 && "OptiX only supports equality testing for strings");
}
OSL_ASSERT(final_result);
final_result = rop.ll.op_bool_to_int(final_result);
rop.storeLLVMValue(final_result, Result, 0, 0);
return true;
}
for (int i = 0; i < num_components; i++) {
// Get A&B component i -- note that these correctly handle mixed
// scalar/triple comparisons as well as int->float casts as needed.
@@ -3075,20 +2994,9 @@ LLVMGEN(llvm_gen_getattribute)
// necessary conversions from its internal format to OSL's.
TypeDesc dest_type = Destination.typespec().simpletype();
llvm::Value* obj_name_arg = NULL;
llvm::Value* attr_name_arg = NULL;
if (rop.use_optix()) {
// We need to make a DeviceString for the parameter names
if (object_lookup)
obj_name_arg = rop.llvm_load_device_string(ObjectName, true);
else
obj_name_arg = rop.ll.constant(ustring());
attr_name_arg = rop.llvm_load_device_string(Attribute, true);
} else {
obj_name_arg = object_lookup ? rop.llvm_load_value(ObjectName)
: rop.ll.constant(ustring());
attr_name_arg = rop.llvm_load_value(Attribute);
}
llvm::Value* obj_name_arg = object_lookup ? rop.llvm_load_value(ObjectName)
: rop.llvm_load_string(ustring());
llvm::Value* attr_name_arg = rop.llvm_load_value(Attribute);
llvm::Value* args[] = {
rop.sg_void_ptr(),
@@ -3515,13 +3423,8 @@ LLVMGEN(llvm_gen_closure)
Symbol& sym = *rop.opargsym(op, carg + 2 + weighted);
TypeDesc t = sym.typespec().simpletype();
if (rop.use_optix() && sym.typespec().is_string()) {
llvm::Value* dst = rop.ll.offset_ptr(mem_void_ptr, p.offset);
llvm::Value* src = rop.llvm_load_device_string(sym,
/*follow*/ false);
rop.ll.op_memcpy(dst, src, 8, 8);
} else if (!sym.typespec().is_closure_array()
&& !sym.typespec().is_structure() && equivalent(t, p.type)) {
if (!sym.typespec().is_closure_array() && !sym.typespec().is_structure()
&& equivalent(t, p.type)) {
llvm::Value* dst = rop.ll.offset_ptr(mem_void_ptr, p.offset);
llvm::Value* src = rop.llvm_void_ptr(sym);
rop.ll.op_memcpy(dst, src, (int)p.type.size(),
@@ -3733,7 +3636,7 @@ LLVMGEN(llvm_gen_pointcloud_write)
int nattrs = (op.nargs() - 3) / 2;
// Generate local space for the names/types/values arrays
llvm::Value* names = rop.ll.op_alloca(rop.ll.type_string(), nattrs);
llvm::Value* names = rop.ll.op_alloca(rop.ll.type_ustring(), nattrs);
llvm::Value* types = rop.ll.op_alloca(rop.ll.type_typedesc(), nattrs);
llvm::Value* values = rop.ll.op_alloca(rop.ll.type_void_ptr(), nattrs);
+37 -94
View File
@@ -18,11 +18,15 @@
#include <OpenImageIO/sysutil.h>
#include <OpenImageIO/timer.h>
#ifdef OSL_USE_OPTIX
# include <optix.h>
#endif
#include "../liboslcomp/oslcomp_pvt.h"
#include "oslexec_pvt.h"
#include "backendllvm.h"
// Create extrenal declarations for all built-in funcs we may call from LLVM
// Create external declarations for all built-in funcs we may call from LLVM
#define DECL(name, signature) extern "C" void name();
#include "builtindecl.h"
#undef DECL
@@ -212,6 +216,7 @@ BackendLLVM::llvm_type_sg()
sg_types.push_back(vp); // opaque tracedata*
sg_types.push_back(vp); // opaque objdata*
sg_types.push_back(vp); // ShadingContext*
sg_types.push_back(vp); // OpaqueShadingStateUniformPtr
sg_types.push_back(vp); // RendererServices*
sg_types.push_back(vp); // object2common
sg_types.push_back(vp); // shader2common
@@ -245,6 +250,7 @@ BackendLLVM::llvm_type_groupdata()
std::vector<llvm::Type*> fields;
int offset = 0;
int order = 0;
m_groupdata_field_names.clear();
if (llvm_debug() >= 2)
std::cout << "Group param struct:\n";
@@ -256,6 +262,7 @@ BackendLLVM::llvm_type_groupdata()
<< " at offset " << offset << "\n";
int sz = (m_num_used_layers + 3) & (~3); // Round up to 32 bit boundary
fields.push_back(ll.type_array(ll.type_bool(), sz));
m_groupdata_field_names.emplace_back("layer_runflags");
offset += sz * sizeof(bool);
++order;
@@ -271,6 +278,7 @@ BackendLLVM::llvm_type_groupdata()
int* offsets = &group().m_userdata_offsets[0];
int sz = (nuserdata + 3) & (~3);
fields.push_back(ll.type_array(ll.type_bool(), sz));
m_groupdata_field_names.emplace_back("userdata_init_flags");
offset += nuserdata * sizeof(bool);
++order;
for (int i = 0; i < nuserdata; ++i) {
@@ -284,6 +292,8 @@ BackendLLVM::llvm_type_groupdata()
: type.numelements();
type.arraylen = n;
fields.push_back(llvm_type(type));
m_groupdata_field_names.emplace_back(
fmtformat("userdata{}_{}_", i, names[i]));
// Alignment
int align = type.basesize();
offset = OIIO::round_to_multiple_of_pow2(offset, align);
@@ -314,6 +324,8 @@ BackendLLVM::llvm_type_groupdata()
const int derivSize = (sym.has_derivs() ? 3 : 1);
ts.make_array(arraylen * derivSize);
fields.push_back(llvm_type(ts));
m_groupdata_field_names.emplace_back(
fmtformat("lay{}param_{}_", layer, sym.name()));
// FIXME(arena) -- temporary debugging
if (debug() && sym.symtype() == SymTypeOutputParam
@@ -347,9 +359,8 @@ BackendLLVM::llvm_type_groupdata()
if (llvm_debug() >= 2)
print(" Group struct had {} fields, total size {}\n\n", order, offset);
std::string groupdataname = fmtformat("Groupdata_{}",
group().name().hash());
m_llvm_type_groupdata = ll.type_struct(fields, groupdataname);
m_llvm_type_groupdata = ll.type_struct(fields, "Groupdata");
OSL_ASSERT(fields.size() == m_groupdata_field_names.size());
return m_llvm_type_groupdata;
}
@@ -398,11 +409,10 @@ BackendLLVM::llvm_assign_initial_value(const Symbol& sym, bool force)
if (!force && sym.valuesource() == Symbol::ConnectedVal
&& !sym.typespec().is_closure_based())
return;
// For "globals" that are closures, there is nothing to initialize.
if (sym.typespec().is_closure_based() && sym.symtype() == SymTypeGlobal)
return;
int arraylen = std::max(1, sym.typespec().arraylength());
// Closures need to get their storage before anything can be
// assigned to them. Unless they are params, in which case we took
// care of it in the group entry point.
@@ -412,9 +422,11 @@ BackendLLVM::llvm_assign_initial_value(const Symbol& sym, bool force)
return;
}
// For local variables (including temps), when "debug_uninit" is enabled,
// we store special values in the variable to make it easier to detect
// uninitialized use.
if ((sym.symtype() == SymTypeLocal || sym.symtype() == SymTypeTemp)
&& shadingsys().debug_uninit()) {
// Handle the "debug uninitialized values" case
bool isarray = sym.typespec().is_array();
int alen = isarray ? sym.typespec().arraylength() : 1;
llvm::Value* u = NULL;
@@ -425,7 +437,7 @@ BackendLLVM::llvm_assign_initial_value(const Symbol& sym, bool force)
else if (sym.typespec().is_int_based())
u = ll.constant(std::numeric_limits<int>::min());
else if (sym.typespec().is_string_based())
u = ll.constant(Strings::uninitialized_string);
u = llvm_load_string(Strings::uninitialized_string);
if (u) {
for (int a = 0; a < alen; ++a) {
llvm::Value* aval = isarray ? ll.constant(a) : NULL;
@@ -436,6 +448,7 @@ BackendLLVM::llvm_assign_initial_value(const Symbol& sym, bool force)
return;
}
// Local/temp strings are always initialized to the empty string.
if ((sym.symtype() == SymTypeLocal || sym.symtype() == SymTypeTemp)
&& sym.typespec().is_string_based()) {
// Strings are pointers. Can't take any chance on leaving
@@ -444,6 +457,10 @@ BackendLLVM::llvm_assign_initial_value(const Symbol& sym, bool force)
return; // we're done, the parts below are just for params
}
// FIXME: Future work -- how expensive would it be to initialize all
// locals to 0? We should test this for performance hit, and if
// reasonable, it may be a good idea to do it by default.
// From here on, everything we are dealing with is a shader parameter
// (either ordinary or output).
OSL_ASSERT_MSG(sym.symtype() == SymTypeParam
@@ -453,7 +470,7 @@ BackendLLVM::llvm_assign_initial_value(const Symbol& sym, bool force)
// Handle interpolated params by calling osl_bind_interpolated_param,
// which will check if userdata is already retrieved, if not it will
// call RendererServices::get_userdata to retrived it. In either case,
// call RendererServices::get_userdata to retrieve it. In either case,
// it will return 1 if it put the userdata in the right spot (either
// retrieved de novo or copied from a previous retrieval), or 0 if no
// such userdata was available.
@@ -493,23 +510,9 @@ BackendLLVM::llvm_assign_initial_value(const Symbol& sym, bool force)
ll.op_memset(ll.offset_ptr(dstptr, size), 0, 2 * size);
} else {
// No pre-placement: fall back to call to the renderer callback.
llvm::Value* name_arg = NULL;
if (use_optix()) {
// We need to make a DeviceString for the parameter name
ustring arg_name = ustring::fmtformat("osl_paramname_{}_{}",
symname, sym.layer());
Symbol symname_const(arg_name, TypeDesc::TypeString,
SymTypeConst);
symname_const.set_dataptr(SymArena::Absolute, &symname);
name_arg = llvm_load_device_string(symname_const,
/*follow*/ true);
} else {
name_arg = ll.constant(symname);
}
llvm::Value* args[] = {
sg_void_ptr(),
name_arg,
llvm_load_string(symname),
ll.constant(type),
ll.constant((int)group().m_userdata_derivs[userdata_index]),
groupdata_field_ptr(2 + userdata_index), // userdata data ptr
@@ -529,12 +532,12 @@ BackendLLVM::llvm_assign_initial_value(const Symbol& sym, bool force)
llvm_void_ptr(sym),
ll.constant((int)sym.has_derivs()),
sg_void_ptr(),
ll.constant(ustring(inst()->shadername())),
llvm_load_string(inst()->shadername()),
ll.constant(0),
ll.constant(sym.unmangled()),
llvm_load_string(sym.unmangled()),
ll.constant(0),
ll.constant(ncomps),
ll.constant("<get_userdata>") };
llvm_load_string("<get_userdata>") };
ll.call_function("osl_naninf_check", args);
}
// userdata pre-placement always succeeds, we don't need to bother
@@ -557,32 +560,16 @@ BackendLLVM::llvm_assign_initial_value(const Symbol& sym, bool force)
if (sym.has_init_ops() && sym.valuesource() == Symbol::DefaultVal) {
// Handle init ops.
build_llvm_code(sym.initbegin(), sym.initend());
} else if (use_optix() && !sym.typespec().is_closure()
&& !sym.typespec().is_string()) {
} else if (use_optix() && !sym.typespec().is_closure()) {
// If the call to osl_bind_interpolated_param returns 0, the default
// value needs to be loaded from a CUDA variable.
ustring var_name = ustring::fmtformat("{}_{}_{}_{}", sym.name(),
inst()->layername(),
group().name(), group().id());
// The "true" argument triggers the creation of the metadata needed to
// make the variable visible to OptiX.
llvm::Value* cuda_var = getOrAllocateCUDAVariable(sym, true);
llvm::Value* cuda_var = getOrAllocateCUDAVariable(sym);
// memcpy the initial value from the CUDA variable
llvm::Value* src = ll.ptr_cast(ll.GEP(cuda_var, 0),
ll.type_void_ptr());
llvm::Value* dst = llvm_void_ptr(sym);
TypeDesc t = sym.typespec().simpletype();
ll.op_memcpy(dst, src, t.size(), t.basesize());
} else if (use_optix() && !sym.typespec().is_closure()) {
// For convenience, we always pack string addresses into the groupdata
// struct.
int userdata_index = find_userdata_index(sym);
llvm::Value* init_val = getOrAllocateCUDAVariable(sym);
init_val = ll.ptr_cast(init_val, ll.type_void_ptr());
ll.op_memcpy(groupdata_field_ptr(2 + userdata_index), init_val, 8,
4);
} else if (!sym.lockgeom() && !sym.typespec().is_closure()) {
// geometrically-varying param; memcpy its default value
TypeDesc t = sym.typespec().simpletype();
@@ -594,6 +581,7 @@ BackendLLVM::llvm_assign_initial_value(const Symbol& sym, bool force)
// Use default value
int num_components = sym.typespec().simpletype().aggregate;
TypeSpec elemtype = sym.typespec().elementtype();
int arraylen = std::max(1, sym.typespec().arraylength());
for (int a = 0, c = 0; a < arraylen; ++a) {
llvm::Value* arrind = sym.typespec().is_array() ? ll.constant(a)
: NULL;
@@ -605,7 +593,7 @@ BackendLLVM::llvm_assign_initial_value(const Symbol& sym, bool force)
if (elemtype.is_float_based())
init_val = ll.constant(sym.get_float(c));
else if (elemtype.is_string())
init_val = ll.constant(sym.get_string(c));
init_val = llvm_load_string(sym.get_string(c));
else if (elemtype.is_int())
init_val = ll.constant(sym.get_int(c));
OSL_DASSERT(init_val);
@@ -871,8 +859,8 @@ BackendLLVM::build_llvm_init()
{
// Make a group init function: void group_init(ShaderGlobals*, GroupData*)
// Note that the GroupData* is passed as a void*.
std::string unique_name = fmtformat("__direct_callable__group_{}_{}_init",
group().name(), group().id());
std::string unique_name = fmtformat("__direct_callable__group_{}_init",
group().name());
ll.current_function(
ll.make_function(unique_name, false,
ll.type_void(), // return type
@@ -1376,19 +1364,6 @@ BackendLLVM::run()
#ifdef OSL_LLVM_NO_BITCODE
OSL_ASSERT(!use_rs_bitcode());
ll.module(ll.new_module("llvm_ops"));
# ifdef OSL_USE_OPTIX
if (use_optix()) {
// If the module is created from LLVM bitcode, the target and
// data layout is inherited from that, but if creating an empty
// module like here, have to manually set those, otherwise
// compiling will later fail because the NVPTX target is not found.
// The target triple and data layout used here are those specified
// for NVPTX (https://www.llvm.org/docs/NVPTXUsage.html#triples).
ll.module()->setDataLayout(
"e-i64:64-i128:128-v16:16-v32:32-n16:32:64");
ll.module()->setTargetTriple("nvptx64-nvidia-cuda");
}
# endif
#else
if (!use_optix()) {
if (use_rs_bitcode()) {
@@ -1527,21 +1502,6 @@ BackendLLVM::run()
if (shadingsys().llvm_prune_ir_strategy() == "none") {
// Do nothing! This is only useful for testing how much we reduce
// optimization and JIT time with the other strategies.
} else if (shadingsys().llvm_prune_ir_strategy() == "internalize") {
// Mark as 'internal' all functions that start with "osl_" but are
// but are not among the known entry points. LLVM can then quickly
// realize that any 'internal' functions not called can be
// discarded. This was our original stab at this strategy.
std::vector<std::string> entry_function_names;
entry_function_names.push_back(ll.func_name(init_func));
for (int layer = 0; layer < nlayers; ++layer) {
// set_inst (layer);
llvm::Function* f = funcs[layer];
if (f && group().is_entry_layer(layer))
entry_function_names.push_back(ll.func_name(f));
}
ll.internalize_module_functions("osl_", external_function_names,
entry_function_names);
} else /* if (shadingsys().llvm_prune_ir_strategy() == "prune") */ {
// New (2020) and default behavior, from Alex Wells:
// Full prune of uncalled functions, and marking as 'internal' to
@@ -1646,25 +1606,8 @@ BackendLLVM::run()
}
if (use_optix()) {
std::string name = fmtformat("{}_{}", group().name(), group().id());
#if (OPTIX_VERSION < 70000)
// Create an llvm::Module from the renderer-supplied library bitcode
std::vector<char>& bitcode = shadingsys().m_lib_bitcode;
OSL_ASSERT(bitcode.size() && "Library bitcode is empty");
// TODO: Is it really necessary to build this Module for every ShaderGroup
llvm::Module* lib_module
= ll.module_from_bitcode(static_cast<const char*>(bitcode.data()),
bitcode.size(), "cuda_lib");
ll.ptx_compile_group(lib_module, name,
ll.ptx_compile_group(nullptr, group().name().string(),
group().m_llvm_ptx_compiled_version);
#else
ll.ptx_compile_group(nullptr, name,
group().m_llvm_ptx_compiled_version);
#endif
if (group().m_llvm_ptx_compiled_version.empty()) {
OSL_ASSERT(0 && "Unable to generate PTX");
}
+82 -148
View File
@@ -92,6 +92,10 @@
#include <llvm/Transforms/Utils/Cloning.h>
#include <llvm/Transforms/Utils/SymbolRewriter.h>
#ifdef OSL_USE_OPTIX
# include <optix.h>
#endif
OSL_NAMESPACE_ENTER
@@ -442,8 +446,6 @@ LLVM_Util::LLVM_Util(const PerThreadInfo& per_thread_info, int debuglevel,
*m_llvm_context);
m_llvm_type_float_ptr = (llvm::PointerType*)llvm::Type::getFloatPtrTy(
*m_llvm_context);
m_llvm_type_ustring_ptr
= (llvm::PointerType*)llvm::PointerType::get(m_llvm_type_char_ptr, 0);
m_llvm_type_longlong_ptr = (llvm::PointerType*)llvm::Type::getInt64PtrTy(
*m_llvm_context);
m_llvm_type_void_ptr = m_llvm_type_char_ptr;
@@ -474,12 +476,10 @@ LLVM_Util::LLVM_Util(const PerThreadInfo& per_thread_info, int debuglevel,
m_llvm_type_wide_longlong = llvm_vector_type(m_llvm_type_longlong,
m_vector_width);
m_llvm_type_wide_char_ptr = llvm::PointerType::get(m_llvm_type_wide_char,
0);
m_llvm_type_wide_ustring_ptr = llvm_vector_type(m_llvm_type_char_ptr,
m_vector_width);
m_llvm_type_wide_void_ptr = llvm_vector_type(m_llvm_type_void_ptr,
m_vector_width);
m_llvm_type_wide_char_ptr = llvm::PointerType::get(m_llvm_type_wide_char,
0);
m_llvm_type_wide_void_ptr = llvm_vector_type(m_llvm_type_void_ptr,
m_vector_width);
m_llvm_type_wide_int_ptr = llvm::PointerType::get(m_llvm_type_wide_int, 0);
m_llvm_type_wide_bool_ptr = llvm::PointerType::get(m_llvm_type_wide_bool,
0);
@@ -493,6 +493,28 @@ LLVM_Util::LLVM_Util(const PerThreadInfo& per_thread_info, int debuglevel,
// A matrix is a struct composed 16 floats
std::vector<llvm::Type*> matrix_wide_fields(16, m_llvm_type_wide_float);
m_llvm_type_wide_matrix = type_struct(matrix_wide_fields, "WideMatrix4");
ustring_rep(m_ustring_rep); // setup ustring-related types
}
void
LLVM_Util::ustring_rep(UstringRep rep)
{
m_ustring_rep = rep;
m_llvm_type_ustring = llvm::Type::getInt8PtrTy(*m_llvm_context);
// ^^ When m_ustring_rep != UstringRep::charptr, we'd ideally want to make
// it a uint directly, but that is wreaking havoc with function
// signatures, so continue to disguise it as a pointer.
// m_llvm_type_ustring = (sizeof(size_t) == sizeof(uint64_t))
// ? llvm::Type::getInt64Ty(*m_llvm_context)
// : llvm::Type::getInt32Ty(*m_llvm_context);
m_llvm_type_ustring_ptr = llvm::PointerType::get(m_llvm_type_ustring, 0);
m_llvm_type_wide_ustring = llvm_vector_type(m_llvm_type_ustring,
m_vector_width);
m_llvm_type_wide_ustring_ptr
= llvm::PointerType::get(m_llvm_type_wide_ustring, 0);
}
@@ -2415,89 +2437,12 @@ LLVM_Util::validate_global_mappings(
// Soon to be deprecated
// DEPRECATED(1.13)
void
LLVM_Util::internalize_module_functions(
const std::string& prefix, const std::vector<std::string>& exceptions,
const std::vector<std::string>& moreexceptions)
{
for (llvm::Function& func : module()->getFunctionList()) {
llvm::Function* sym = &func;
std::string symname = sym->getName().str();
if (prefix.size() && !OIIO::Strutil::starts_with(symname, prefix))
continue;
bool needed = false;
for (size_t i = 0, e = exceptions.size(); i < e; ++i)
if (sym->getName() == exceptions[i]) {
needed = true;
// std::cout << " necessary LLVM module function "
// << sym->getName().str() << "\n";
break;
}
for (size_t i = 0, e = moreexceptions.size(); i < e; ++i)
if (sym->getName() == moreexceptions[i]) {
needed = true;
// std::cout << " necessary LLVM module function "
// << sym->getName().str() << "\n";
break;
}
if (!needed) {
llvm::GlobalValue::LinkageTypes linkage = sym->getLinkage();
// std::cout << " unnecessary LLVM module function "
// << sym->getName().str() << " linkage " << int(linkage) << "\n";
if (linkage == llvm::GlobalValue::ExternalLinkage)
sym->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
// ExternalLinkage means it's potentially externally callable,
// and so will definitely have code generated.
// LinkOnceODRLinkage keeps one copy so it can be inlined or
// called internally to the module, but allows it to be
// discarded otherwise.
}
}
#if 0
// I don't think we need to worry about linkage of global symbols, but
// here is an example of how to iterate over the globals anyway.
for (llvm::Module::global_iterator iter = module()->global_begin(); iter != module()->global_end(); iter++) {
llvm::GlobalValue *sym = llvm::dyn_cast<llvm::GlobalValue>(iter);
if (!sym)
continue;
std::string symname = sym->getName();
if (prefix.size() && ! OIIO::Strutil::starts_with(symname, prefix))
continue;
bool needed = false;
for (size_t i = 0, e = exceptions.size(); i < e; ++i)
if (sym->getName() == exceptions[i]) {
needed = true;
break;
}
if (! needed) {
llvm::GlobalValue::LinkageTypes linkage = sym->getLinkage();
// std::cout << " unnecessary LLVM global " << sym->getName().str()
// << " linkage " << int(linkage) << "\n";
if (linkage == llvm::GlobalValue::ExternalLinkage)
f->setLinkage (llvm::GlobalValue::LinkOnceODRLinkage);
}
}
#endif
}
llvm::Function*
LLVM_Util::make_function(const std::string& name, bool fastcall,
llvm::Type* rettype, llvm::Type* arg1,
llvm::Type* arg2, llvm::Type* arg3, llvm::Type* arg4)
{
std::vector<llvm::Type*> argtypes;
if (arg1)
argtypes.emplace_back(arg1);
if (arg2)
argtypes.emplace_back(arg2);
if (arg3)
argtypes.emplace_back(arg3);
if (arg4)
argtypes.emplace_back(arg4);
return make_function(name, fastcall, rettype, argtypes, false);
}
@@ -2550,9 +2495,9 @@ LLVM_Util::current_function_arg(int a)
llvm::BasicBlock*
LLVM_Util::new_basic_block(const std::string& name)
{
return llvm::BasicBlock::Create(context(),
debug() ? name : llvm::Twine::createNull(),
current_function());
std::string n = fmtformat("bb_{}{}{}", name, name.size() ? "_" : "",
m_next_serial_bb++);
return llvm::BasicBlock::Create(context(), n, current_function());
}
@@ -2709,7 +2654,7 @@ LLVM_Util::type_struct(cspan<llvm::Type*> types, const std::string& name,
llvm::Type*
llvm::PointerType*
LLVM_Util::type_ptr(llvm::Type* type)
{
return llvm::PointerType::get(type, 0);
@@ -2728,18 +2673,7 @@ LLVM_Util::type_array(llvm::Type* type, int n)
return llvm::ArrayType::get(type, n);
}
bool
LLVM_Util::is_type_array(llvm::Type* type)
{
return type->isArrayTy();
}
llvm::Type*
LLVM_Util::element_type_of(llvm::Type* array_type)
{
OSL_DASSERT(is_type_array(array_type));
return array_type->getArrayElementType();
}
llvm::FunctionType*
LLVM_Util::type_function(llvm::Type* rettype, cspan<llvm::Type*> params,
@@ -2913,32 +2847,30 @@ LLVM_Util::constant_ptr(void* p, llvm::PointerType* type)
llvm::Value*
LLVM_Util::constant(ustring s)
{
// Create a const size_t with the ustring contents
size_t bits = sizeof(size_t) * 8;
llvm::Value* str
= llvm::ConstantInt::get(context(),
llvm::APInt(bits, size_t(s.c_str()), true));
// Then cast the int to a char*.
return builder().CreateIntToPtr(str, type_string(), "ustring constant");
const size_t size_t_bits = sizeof(size_t) * 8;
// Create a const size_t with the ustring character address, or hash,
// depending on the representation we're using.
size_t p = (ustring_rep() == UstringRep::charptr) ? size_t(s.c_str())
: s.hash();
auto str = (size_t_bits == 64) ? constant64(p) : constant(int(p));
// Then cast the int to a char*. Ideally, we would only do that if the rep
// were a charptr, but we disguise the hashes as char*'s also to avoid
// ugliness with function signatures differing between CPU and GPU.
// Maybe some day we'll use the hash representation on both sides?
return builder().CreateIntToPtr(str, m_llvm_type_ustring,
"ustring constant");
}
llvm::Value*
LLVM_Util::wide_constant(ustring s)
{
// Create a const size_t with the ustring contents
size_t bits = sizeof(size_t) * 8;
llvm::Value* str
= llvm::ConstantInt::get(context(),
llvm::APInt(bits, size_t(s.c_str()), true));
// Then cast the int to a char*.
llvm::Value* constant_value = builder().CreateIntToPtr(str, type_string(),
"ustring constant");
return builder().CreateVectorSplat(m_vector_width, constant_value);
return builder().CreateVectorSplat(m_vector_width, constant(s));
}
llvm::Value*
LLVM_Util::llvm_mask_to_native(llvm::Value* llvm_mask)
{
@@ -3492,7 +3424,7 @@ LLVM_Util::llvm_type(const TypeDesc& typedesc)
else if (t == TypeDesc::INT)
lt = type_int();
else if (t == TypeDesc::STRING)
lt = type_string();
lt = type_ustring();
else if (t.aggregate == TypeDesc::VEC3)
lt = type_triple();
else if (t.aggregate == TypeDesc::MATRIX44)
@@ -3501,6 +3433,8 @@ LLVM_Util::llvm_type(const TypeDesc& typedesc)
lt = type_void();
else if (t == TypeDesc::UINT8)
lt = type_char();
else if (t == TypeDesc::UINT64)
lt = type_longlong();
else if (t == TypeDesc::PTR)
lt = type_void_ptr();
else {
@@ -3536,7 +3470,7 @@ LLVM_Util::llvm_vector_type(const TypeDesc& typedesc)
else if (t == TypeDesc::INT)
lt = type_wide_int();
else if (t == TypeDesc::STRING)
lt = type_wide_string();
lt = type_wide_ustring();
else if (t.aggregate == TypeDesc::VEC3)
lt = type_wide_triple();
else if (t.aggregate == TypeDesc::MATRIX44)
@@ -3570,7 +3504,7 @@ LLVM_Util::offset_ptr(llvm::Value* ptr, llvm::Value* offset,
if (offset)
i = op_add(i, offset);
ptr = int_to_ptr_cast(i);
if (ptrtype)
if (ptrtype && ptrtype != type_void_ptr())
ptr = ptr_cast(ptr, ptrtype);
return ptr;
}
@@ -3580,6 +3514,8 @@ LLVM_Util::offset_ptr(llvm::Value* ptr, llvm::Value* offset,
llvm::Value*
LLVM_Util::offset_ptr(llvm::Value* ptr, int offset, llvm::Type* ptrtype)
{
if (offset == 0)
return ptr; // shortcut for 0 offset
return offset_ptr(ptr, constant(size_t(offset)), ptrtype);
}
@@ -3609,10 +3545,9 @@ LLVM_Util::op_alloca(llvm::Type* llvmtype, int n, const std::string& name,
llvm::BasicBlock* entry_block = &current_function()->getEntryBlock();
m_builder->SetInsertPoint(entry_block, entry_block->begin());
llvm::ConstantInt* numalloc = (llvm::ConstantInt*)constant(n);
llvm::AllocaInst* allocainst
= builder().CreateAlloca(llvmtype, numalloc,
debug() ? name : llvm::Twine::createNull());
llvm::ConstantInt* numalloc = (llvm::ConstantInt*)constant(n);
llvm::AllocaInst* allocainst = builder().CreateAlloca(llvmtype, numalloc,
name);
if (align > 0) {
#if OSL_LLVM_VERSION >= 110
using AlignmentType = llvm::Align;
@@ -4160,7 +4095,7 @@ LLVM_Util::op_gather(llvm::Value* ptr, llvm::Value* wide_index)
return builder().CreateIntToPtr(op_combine_8x_vectors(gather1,
gather2),
type_wide_string());
type_wide_ustring());
}
case 8: {
// Gather 64bit integer, as that is binary compatible with 64bit pointers of ustring
@@ -4189,12 +4124,12 @@ LLVM_Util::op_gather(llvm::Value* ptr, llvm::Value* wide_index)
return builder().CreateIntToPtr(op_combine_4x_vectors(gather1,
gather2),
type_wide_string());
type_wide_ustring());
}
default: OSL_ASSERT(0 && "unsupported native bit mask width");
}
} else {
return clamped_gather_from_uniform(type_wide_string());
return clamped_gather_from_uniform(type_wide_ustring());
}
} else if (ptr->getType() == type_wide_float_ptr()) {
if (m_supports_avx512f) {
@@ -4367,8 +4302,7 @@ LLVM_Util::op_gather(llvm::Value* ptr, llvm::Value* wide_index)
} else {
return clamped_gather_from_varying(type_wide_int());
}
} else if (ptr->getType()
== llvm::PointerType::get(type_wide_string(), 0)) {
} else if (ptr->getType() == type_wide_ustring_ptr()) {
if (m_supports_avx512f) {
// TODO: Are we guaranteed a 64bit pointer?
switch (m_vector_width) {
@@ -4402,7 +4336,7 @@ LLVM_Util::op_gather(llvm::Value* ptr, llvm::Value* wide_index)
return builder().CreateIntToPtr(op_combine_8x_vectors(gather1,
gather2),
type_wide_string());
type_wide_ustring());
}
case 8: {
// Gather 64bit integer, as that is binary compatible with 64bit pointers of ustring
@@ -4442,7 +4376,7 @@ LLVM_Util::op_gather(llvm::Value* ptr, llvm::Value* wide_index)
return builder().CreateIntToPtr(op_combine_4x_vectors(gather1,
gather2),
type_wide_string());
type_wide_ustring());
}
default: OSL_ASSERT(0 && "unsupported native bit mask width");
}
@@ -4450,7 +4384,7 @@ LLVM_Util::op_gather(llvm::Value* ptr, llvm::Value* wide_index)
} else {
// AVX2 case falls through to here, choose not to specialize and use
// generic code gen as 4 AVX2 gathers would be required
return clamped_gather_from_varying(type_wide_string());
return clamped_gather_from_varying(type_wide_ustring());
}
} else {
@@ -4488,7 +4422,7 @@ LLVM_Util::op_scatter(llvm::Value* wide_val, llvm::Value* ptr,
llvm::BasicBlock* test_scatter_per_lane[MaxSupportedSimdLaneCount + 1];
for (int l = 0; l < m_vector_width; ++l) {
test_scatter_per_lane[l] = new_basic_block(
std::string("test scatter lane=").append(std::to_string(l)));
fmtformat("test scatter lane={}", l));
}
test_scatter_per_lane[m_vector_width] = new_basic_block(
"after scatter");
@@ -4512,7 +4446,7 @@ LLVM_Util::op_scatter(llvm::Value* wide_val, llvm::Value* ptr,
op_branch(test_scatter_per_lane[0]);
for (int l = 0; l < m_vector_width; ++l) {
llvm::BasicBlock* scatter_block = new_basic_block(
std::string("scatter lane=").append(std::to_string(l)));
fmtformat("scatter lane={}", l));
op_branch(mask_per_lane[l], scatter_block,
test_scatter_per_lane[l + 1]);
@@ -4587,7 +4521,7 @@ LLVM_Util::op_scatter(llvm::Value* wide_val, llvm::Value* ptr,
return;
}
} else if (ptr->getType() == type_ustring_ptr()) {
OSL_ASSERT(wide_val->getType() == type_wide_string());
OSL_ASSERT(wide_val->getType() == type_wide_ustring());
if (m_supports_avx512f) {
switch (m_vector_width) {
case 16: {
@@ -4742,9 +4676,8 @@ LLVM_Util::op_scatter(llvm::Value* wide_val, llvm::Value* ptr,
/*is_dest_wide*/ true);
return;
}
} else if (ptr->getType()
== llvm::PointerType::get(type_wide_string(), 0)) {
OSL_ASSERT(wide_val->getType() == type_wide_string());
} else if (ptr->getType() == type_wide_ustring_ptr()) {
OSL_ASSERT(wide_val->getType() == type_wide_ustring());
if (m_supports_avx512f) {
switch (m_vector_width) {
case 16: {
@@ -5901,13 +5834,6 @@ LLVM_Util::ptx_compile_group(llvm::Module* lib_module, const std::string& name,
failed = llvm::Linker::linkModules(*linked_module, std::move(lib_ptr));
}
# if (OPTIX_VERSION < 70000)
// Internalize the Globals to match code generated by NVCC
for (auto& g_var : linked_module->globals()) {
g_var.setLinkage(llvm::GlobalValue::InternalLinkage);
}
# endif
// Verify that the NVPTX target has been initialized
std::string error;
const llvm::Target* llvm_target
@@ -5982,8 +5908,16 @@ LLVM_Util::ptx_compile_group(llvm::Module* lib_module, const std::string& name,
// Run the optimization passes on the module to generate the PTX
mod_pm.run(*linked_module);
// TODO: Minimize string copying
out = assembly_stream.str().str();
// In a multithreaded environment, llvm will return "callseq <ID>" comments
// with a non-deterministic ID, leading to OptiX JIT cache misses.
// Filter them out. TODO: Address upstream in llvm
std::istringstream raw_ptx(assembly_stream.str().str());
std::stringstream ptx_stream;
std::string line;
while (std::getline(raw_ptx, line)) {
ptx_stream << line.substr(0, line.find("// callseq")) << std::endl;
}
out = ptx_stream.str();
delete linked_module;
+1 -1
View File
@@ -72,7 +72,7 @@ private:
int m_oso_major, m_oso_minor; ///< oso file format version
int m_sym_default_index; ///< Next sym default value to fill in
bool m_errors; ///< Did we hit any errors?
typedef std::unordered_map<ustring, int, ustringHash> UstringIntMap;
typedef std::unordered_map<ustring, int> UstringIntMap;
UstringIntMap m_symmap; ///< map sym name to index
};
+9 -8
View File
@@ -18,6 +18,10 @@
#include <OpenImageIO/fmath.h>
#ifdef __CUDACC__
# include <optix.h>
#endif
#include "opcolor.h"
#include "opcolor_impl.h"
@@ -229,17 +233,12 @@ rend_get_userdata(StringParam name, void* data, int data_size,
OSL_HOSTDEVICE void
ColorSystem::error(StringParam src, StringParam dst, Context sg) const
{
# if !defined(__CUDA_ARCH__) || OPTIX_VERSION < 70000
# ifndef __CUDA_ARCH__
const char* args[2] = { src.c_str(), dst.c_str() };
osl_printf(sg,
(char*) // FIXME!
"ERROR: Unknown color space transformation \"%s\" -> \"%s\"\n",
args);
# else
uint64_t fmt_hash = UStringHash::Hash(
"ERROR: Unknown color space transformation \"%s\" -> \"%s\"\n");
uint64_t args[3] = { 2 * sizeof(uint64_t), dst, src };
osl_printf(sg, (char*)fmt_hash, args);
# endif
}
@@ -266,9 +265,11 @@ ColorSystem::error(StringParam src, StringParam dst, Context context) const
}
static inline const ColorSystem&
op_color_colorsystem(void* sg)
op_color_colorsystem(void* sg_)
{
return ((ShaderGlobals*)sg)->context->shadingsys().colorsystem();
ShaderGlobals* sg = (ShaderGlobals*)sg_;
ShadingStateUniform* ssu = (ShadingStateUniform*)sg->shadingStateUniform;
return ssu->m_colorsystem;
}
static inline OSL::ShadingContext*
+3 -8
View File
@@ -50,13 +50,8 @@ clamp_zero(Color3& c)
//OSL_CONSTANT_DATA const float cie_colour_match[81][3] =
// Choose to access 1d array vs 2d to allow better code generation of gathers
namespace { // anon namespace to avoid duplicate OptiX symbols
// clang-format off
#ifdef __CUDACC__
OSL_CONSTANT_DATA const float cie_colour_match[81*3] =
#else
OSL_CONSTANT_DATA const float cie_colour_match[81 * 3] OSL_ALIGNAS(64) =
#endif
{
static OSL_CONSTANT_DATA const float cie_colour_match[81 * 3] OSL_ALIGNAS(64) = {
// clang-format off
0.0014,0.0000,0.0065, 0.0022,0.0001,0.0105, 0.0042,0.0001,0.0201,
0.0076,0.0002,0.0362, 0.0143,0.0004,0.0679, 0.0232,0.0006,0.1102,
0.0435,0.0012,0.2074, 0.0776,0.0022,0.3713, 0.1344,0.0040,0.6456,
@@ -84,8 +79,8 @@ OSL_CONSTANT_DATA const float cie_colour_match[81 * 3] OSL_ALIGNAS(64) =
0.0007,0.0002,0.0000, 0.0005,0.0002,0.0000, 0.0003,0.0001,0.0000,
0.0002,0.0001,0.0000, 0.0002,0.0001,0.0000, 0.0001,0.0000,0.0000,
0.0001,0.0000,0.0000, 0.0001,0.0000,0.0000, 0.0000,0.0000,0.0000
// clang-format on
};
// clang-format on
} // namespace
+15 -12
View File
@@ -138,10 +138,10 @@ osl_transformn_dvmdv(void* result, void* M_, void* v_)
OSL_SHADEOP int
osl_get_matrix(void* sg_, void* r, const char* from)
{
ShaderGlobals* sg = (ShaderGlobals*)sg_;
ShadingContext* ctx = (ShadingContext*)sg->context;
ShaderGlobals* sg = (ShaderGlobals*)sg_;
ShadingStateUniform* ssu = (ShadingStateUniform*)sg->shadingStateUniform;
if (HDSTR(from) == STRING_PARAMS(common)
|| HDSTR(from) == ctx->shadingsys().commonspace_synonym()) {
|| HDSTR(from) == ssu->m_commonspace_synonym) {
MAT(r).makeIdentity();
return true;
}
@@ -157,7 +157,7 @@ osl_get_matrix(void* sg_, void* r, const char* from)
if (!ok) {
MAT(r).makeIdentity();
ShadingContext* ctx = (ShadingContext*)((ShaderGlobals*)sg)->context;
if (ctx->shadingsys().unknown_coordsys_error())
if (ssu->m_unknown_coordsys_error)
ctx->errorfmt("Unknown transformation \"{}\"", from);
}
return ok;
@@ -168,10 +168,10 @@ osl_get_matrix(void* sg_, void* r, const char* from)
OSL_SHADEOP int
osl_get_inverse_matrix(void* sg_, void* r, const char* to)
{
ShaderGlobals* sg = (ShaderGlobals*)sg_;
ShadingContext* ctx = (ShadingContext*)sg->context;
ShaderGlobals* sg = (ShaderGlobals*)sg_;
ShadingStateUniform* ssu = (ShadingStateUniform*)sg->shadingStateUniform;
if (HDSTR(to) == STRING_PARAMS(common)
|| HDSTR(to) == ctx->shadingsys().commonspace_synonym()) {
|| HDSTR(to) == ssu->m_commonspace_synonym) {
MAT(r).makeIdentity();
return true;
}
@@ -189,7 +189,7 @@ osl_get_inverse_matrix(void* sg_, void* r, const char* to)
if (!ok) {
MAT(r).makeIdentity();
ShadingContext* ctx = (ShadingContext*)((ShaderGlobals*)sg)->context;
if (ctx->shadingsys().unknown_coordsys_error())
if (ssu->m_unknown_coordsys_error)
ctx->errorfmt("Unknown transformation \"{}\"", to);
}
return ok;
@@ -207,18 +207,21 @@ osl_get_inverse_matrix(void* sg_, void* r, const char* to);
OSL_SHADEOP OSL_HOSTDEVICE int
osl_prepend_matrix_from(void* sg, void* r, const char* from)
osl_prepend_matrix_from(void* sg_, void* r, const char* from)
{
ShaderGlobals* sg = (ShaderGlobals*)sg_;
Matrix44 m;
bool ok = osl_get_matrix((ShaderGlobals*)sg, &m, from);
bool ok = osl_get_matrix(sg, &m, from);
if (ok)
MAT(r) = m * MAT(r);
#ifndef __CUDACC__
// TODO: How do we manage this in OptiX?
else {
ShadingContext* ctx = (ShadingContext*)((ShaderGlobals*)sg)->context;
if (ctx->shadingsys().unknown_coordsys_error())
ShadingStateUniform* ssu = (ShadingStateUniform*)sg->shadingStateUniform;
if (ssu->m_unknown_coordsys_error) {
ShadingContext* ctx = (ShadingContext*)(sg)->context;
ctx->errorfmt("Unknown transformation \"{}\"", from);
}
}
#endif
return ok;
+13 -13
View File
@@ -224,7 +224,7 @@ osl_texture(void* sg_, const char* name, void* handle, void* opt_, float s,
bool derivs = (dresultdx || dalphadx);
// It's actually faster to ask for 4 channels (even if we need fewer)
// and ensure that they're being put in aligned memory.
OIIO::simd::vfloat4 result_simd, dresultds_simd, dresultdt_simd;
OIIO::simd::float4 result_simd, dresultds_simd, dresultdt_simd;
bool ok = sg->renderer->texture(
USTR(name), (TextureSystem::TextureHandle*)handle,
sg->context->texture_thread_info(), *opt, sg, s, t, dsdx, dtdx, dsdy,
@@ -240,10 +240,10 @@ osl_texture(void* sg_, const char* name, void* handle, void* opt_, float s,
if (derivs) {
OSL_DASSERT((dresultdx == nullptr) == (dresultdy == nullptr));
OSL_DASSERT((dalphadx == nullptr) == (dalphady == nullptr));
OIIO::simd::vfloat4 dresultdx_simd = dresultds_simd * dsdx
+ dresultdt_simd * dtdx;
OIIO::simd::vfloat4 dresultdy_simd = dresultds_simd * dsdy
+ dresultdt_simd * dtdy;
OIIO::simd::float4 dresultdx_simd = dresultds_simd * dsdx
+ dresultdt_simd * dtdx;
OIIO::simd::float4 dresultdy_simd = dresultds_simd * dsdy
+ dresultdt_simd * dtdy;
if (dresultdx) {
for (int i = 0; i < chans; ++i)
((float*)dresultdx)[i] = dresultdx_simd[i];
@@ -281,7 +281,7 @@ osl_texture3d(void* sg_, const char* name, void* handle, void* opt_, void* P_,
bool derivs = (dresultdx != NULL || dalphadx != NULL);
// It's actually faster to ask for 4 channels (even if we need fewer)
// and ensure that they're being put in aligned memory.
OIIO::simd::vfloat4 result_simd, dresultds_simd, dresultdt_simd,
OIIO::simd::float4 result_simd, dresultds_simd, dresultdt_simd,
dresultdr_simd;
bool ok = sg->renderer->texture3d(
USTR(name), (TextureSystem::TextureHandle*)handle,
@@ -297,12 +297,12 @@ osl_texture3d(void* sg_, const char* name, void* handle, void* opt_, void* P_,
// Correct our str texture space gradients into xyz-space gradients
if (derivs) {
OIIO::simd::vfloat4 dresultdx_simd = dresultds_simd * dPdx.x
+ dresultdt_simd * dPdx.y
+ dresultdr_simd * dPdx.z;
OIIO::simd::vfloat4 dresultdy_simd = dresultds_simd * dPdy.x
+ dresultdt_simd * dPdy.y
+ dresultdr_simd * dPdy.z;
OIIO::simd::float4 dresultdx_simd = dresultds_simd * dPdx.x
+ dresultdt_simd * dPdx.y
+ dresultdr_simd * dPdx.z;
OIIO::simd::float4 dresultdy_simd = dresultds_simd * dPdy.x
+ dresultdt_simd * dPdy.y
+ dresultdr_simd * dPdy.z;
if (dresultdx) {
for (int i = 0; i < chans; ++i)
((float*)dresultdx)[i] = dresultdx_simd[i];
@@ -335,7 +335,7 @@ osl_environment(void* sg_, const char* name, void* handle, void* opt_, void* R_,
TextureOpt* opt = (TextureOpt*)opt_;
// It's actually faster to ask for 4 channels (even if we need fewer)
// and ensure that they're being put in aligned memory.
OIIO::simd::vfloat4 local_result;
OIIO::simd::float4 local_result;
bool ok = sg->renderer->environment(USTR(name),
(TextureSystem::TextureHandle*)handle,
sg->context->texture_thread_info(),
+30 -41
View File
@@ -19,12 +19,11 @@
// Pull in the modified Imath headers and the OSL_HOSTDEVICE macro
#ifdef __CUDACC__
# include <OSL/oslconfig.h>
# include <optix.h>
#endif
#ifdef __CUDACC__
# if OPTIX_VERSION >= 70000
# include "string_hash.h"
# endif
# include "string_hash.h"
#endif
#include <OpenImageIO/color.h>
@@ -34,6 +33,7 @@
#include <OpenImageIO/ustring.h>
#include "osl_pvt.h"
#include <OSL/dual.h>
#include <OSL/dual_vec.h>
#include <OSL/genclosure.h>
@@ -43,6 +43,8 @@
#include <OSL/oslexec.h>
#include <OSL/rendererservices.h>
#include <OSL/shaderglobals.h>
#include "shading_state_uniform.h"
#include "constantpool.h"
#include "opcolor.h"
@@ -58,7 +60,6 @@ using OIIO::ParamValueList;
using OIIO::RefCnt;
using OIIO::spin_lock;
using OIIO::spin_mutex;
using OIIO::ustringHash;
namespace Strutil = OIIO::Strutil;
@@ -191,10 +192,8 @@ struct UserDataNeeded {
{
if (a.name != b.name)
return a.name < b.name;
// Checking for layer_num means that if derivs differ find_userdata_index
// may find the wrong layer symbol with the wrong derivs setting.
//if (a.layer_num != b.layer_num)
// return a.layer_num < b.layer_num;
if (a.layer_num != b.layer_num)
return a.layer_num < b.layer_num;
if (a.type.basetype != b.type.basetype)
return a.type.basetype < b.type.basetype;
if (a.type.aggregate != b.type.aggregate)
@@ -213,11 +212,9 @@ struct UserDataNeeded {
struct AttributeNeeded {
ustring name;
ustring scope;
TypeDesc type;
AttributeNeeded(ustring name, ustring scope = ustring(),
TypeDesc type = TypeUnknown)
: name(name), scope(scope), type(type)
AttributeNeeded(ustring name, ustring scope = ustring())
: name(name), scope(scope)
{
}
@@ -227,15 +224,6 @@ struct AttributeNeeded {
return a.name < b.name;
if (a.scope != b.scope)
return a.scope < b.scope;
if (a.type.basetype != b.type.basetype)
return a.type.basetype < b.type.basetype;
if (a.type.aggregate != b.type.aggregate)
return a.type.aggregate < b.type.aggregate;
if (a.type.arraylen != b.type.arraylen)
return a.type.arraylen < b.type.arraylen;
// Ignore vector semantics
// if (a.type.vecsemantics != b.type.vecsemantics)
// return a.type.vecsemantics < b.type.vecsemantics;
return false; // they are equal
}
};
@@ -629,7 +617,10 @@ public:
bool lockgeom_default() const { return m_lockgeom_default; }
bool strict_messages() const { return m_strict_messages; }
bool range_checking() const { return m_range_checking; }
bool unknown_coordsys_error() const { return m_unknown_coordsys_error; }
bool unknown_coordsys_error() const
{
return m_shading_state_uniform.m_unknown_coordsys_error;
}
bool connection_error() const { return m_connection_error; }
bool relaxed_param_typecheck() const { return m_relaxed_param_typecheck; }
int optimize() const { return m_optimize; }
@@ -654,7 +645,10 @@ public:
bool no_pointcloud() const { return m_no_pointcloud; }
bool force_derivs() const { return m_force_derivs; }
bool allow_shader_replacement() const { return m_allow_shader_replacement; }
ustring commonspace_synonym() const { return m_commonspace_synonym; }
ustring commonspace_synonym() const
{
return m_shading_state_uniform.m_commonspace_synonym;
}
bool llvm_jit_fma() const { return m_llvm_jit_fma; }
ustring llvm_jit_target() const { return m_llvm_jit_target; }
@@ -707,8 +701,7 @@ public:
void optimize_all_groups(int nthreads = 0, int mythread = 0,
int totalthreads = 1, bool do_jit = true);
typedef std::unordered_map<ustring, OpDescriptor, ustringHash>
OpDescriptorMap;
typedef std::unordered_map<ustring, OpDescriptor> OpDescriptorMap;
/// Look up OpDescriptor for the named op, return NULL for unknown op.
///
@@ -733,7 +726,7 @@ public:
void count_noise(int number = 1) { m_stat_noise_calls += number; }
ColorSystem& colorsystem() { return m_colorsystem; }
ColorSystem& colorsystem() { return m_shading_state_uniform.m_colorsystem; }
std::shared_ptr<OIIO::ColorConfig> colorconfig();
@@ -847,10 +840,9 @@ private:
bool m_strict_messages; ///< Strict checking of message passing usage?
bool m_error_repeats; ///< Allow repeats of identical err/warn?
bool m_range_checking; ///< Range check arrays & components?
bool m_unknown_coordsys_error; ///< Error to use unknown xform name?
bool m_connection_error; ///< Error for ConnectShaders to fail?
bool m_greedyjit; ///< JIT as much as we can?
bool m_countlayerexecs; ///< Count number of layer execs?
bool m_connection_error; ///< Error for ConnectShaders to fail?
bool m_greedyjit; ///< JIT as much as we can?
bool m_countlayerexecs; ///< Count number of layer execs?
bool m_relaxed_param_typecheck; ///< Allow parameters to be set from isomorphic types (same data layout)
int m_max_warnings_per_thread; ///< How many warnings to display per thread before giving up?
int m_profile; ///< Level of profiling of shader execution
@@ -899,7 +891,6 @@ private:
std::string m_library_searchpath; ///< Library search path
std::vector<std::string>
m_library_searchpath_dirs; ///< All library searchpath dirs
ustring m_commonspace_synonym; ///< Synonym for "common" space
std::vector<ustring> m_raytypes; ///< Names of ray types
std::vector<ustring> m_renderer_outputs; ///< Names of renderer outputs
std::vector<SymLocationDesc> m_symlocs;
@@ -915,8 +906,10 @@ private:
int m_gpu_opt_error; ///< Error on inability to optimize
///< away things that can't GPU.
ustring m_colorspace; ///< What RGB colors mean
ColorSystem m_colorsystem; ///< Data for current colorspace
ustring m_colorspace; ///< What RGB colors mean
ShadingStateUniform m_shading_state_uniform;
std::shared_ptr<OIIO::ColorConfig>
m_colorconfig; ///< OIIO/OCIO color configuration
@@ -1360,7 +1353,7 @@ public:
{
return (symbols().size() == 0
&& (ops().size() == 0 ||
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
#ifdef __CUDA_ARCH__
(ops().size() == 1
&& UStringHash::Hash(ops()[0].opname().c_str())
== STRING_PARAMS(end))
@@ -1932,16 +1925,13 @@ private:
std::vector<void*> m_userdata_init_vals;
std::vector<ustring> m_attributes_needed;
std::vector<ustring> m_attribute_scopes;
std::vector<TypeDesc> m_attribute_types;
std::vector<ustring> m_renderer_outputs; ///< Names of renderer outputs
std::vector<SymLocationDesc> m_symlocs; ///< SORTED!!
bool m_unknown_textures_needed;
bool m_unknown_closures_needed;
bool m_unknown_attributes_needed;
atomic_ll m_executions { 0 }; ///< Number of times the group executed
atomic_ll m_stat_total_shading_time_ticks {
0
}; ///< Total shading time (ticks)
atomic_ll m_stat_total_shading_time_ticks { 0 }; // Shading time (ticks)
// PTX assembly for compiled ShaderGroup
std::string m_llvm_ptx_compiled_version;
@@ -2369,8 +2359,7 @@ private:
nullptr, &OIIO::aligned_free
};
size_t m_heapsize = 0;
using RegexMap
= std::unordered_map<ustring, std::unique_ptr<std::regex>, ustringHash>;
using RegexMap = std::unordered_map<ustring, std::unique_ptr<std::regex>>;
RegexMap m_regex_map; ///< Compiled regex's
MessageList m_messages; ///< Message blackboard
#if OSL_USE_BATCHED
@@ -2584,7 +2573,7 @@ public:
std::string layer_function_name(const ShaderGroup& group,
const ShaderInstance& inst)
{
return fmtformat("{}_{}_{}", group.name(), inst.layername(), inst.id());
return fmtformat("{}_{}", group.name(), inst.layername());
}
std::string layer_function_name()
{
+1 -1
View File
@@ -27,7 +27,7 @@
#pragma clang diagnostic ignored "-Wparentheses-equality"
#endif
#if (OSL_CLANG_VERSION >= 150000) || (OSL_INTEL_CLANG_VERSION >= 140000)
#if OSL_CLANG_VERSION >= 150000
#pragma clang diagnostic ignored "-Wunused-but-set-variable"
#endif
+21 -2
View File
@@ -288,8 +288,7 @@ public:
}
// TODO: This is really the only part of parsing that needs the lock still.
// The calling code no longer sets the global locale, so it would
// likely be simple to clean this up.
// But the calling code setting locale complicates this.
//
bool parse(OSOReader* reader, const char* what) {
yy_switch_to_buffer(m_buffer, m_scanner);
@@ -311,6 +310,12 @@ OSOReader::parse_file (const std::string &filename)
// can actually be reading a .oso file at a time.
std::lock_guard<std::mutex> guard (osoread_mutex);
// Force classic "C" locale for correct '.' decimal parsing.
// N.B. This is not safe in a multi-threaded program where another
// application thread is expecting the native locale to work properly.
std::locale oldlocale; // save the previous native locale
std::locale::global (std::locale::classic());
FILE* osoin = OIIO::Filesystem::fopen (filename, "r");
if (! osoin) {
m_err.errorfmt("File {} not found", filename);
@@ -321,6 +326,7 @@ OSOReader::parse_file (const std::string &filename)
bool ok = scope.parse(this, filename.c_str());
fclose (osoin);
std::locale::global (oldlocale); // Restore the original locale.
return ok;
}
@@ -333,9 +339,22 @@ OSOReader::parse_memory (const std::string &buffer)
// can actually be reading a .oso file at a time.
std::lock_guard<std::mutex> guard (osoread_mutex);
#ifndef OIIO_STRUTIL_HAS_STOF
// Force classic "C" locale for correct '.' decimal parsing.
// N.B. This is not safe in a multi-threaded program where another
// application thread is expecting the native locale to work properly.
// This is not necessary for versions of OIIO that have Strutil::stof,
// and we can remove it entirely when OIIO 1.9 is the minimum.
std::locale oldlocale = std::locale::global (std::locale::classic());
#endif
Scope scope(buffer);
bool ok = scope.parse(this, "preloaded OSO code");
#ifndef OIIO_STRUTIL_HAS_STOF
std::locale::global (oldlocale); // Restore the original locale.
#endif
return ok;
}
+1 -2
View File
@@ -12,8 +12,7 @@ OSL_NAMESPACE_ENTER
namespace pvt {
#ifdef USE_PARTIO
typedef std::unordered_map<ustring, std::unique_ptr<PointCloud>, ustringHash>
PointCloudMap;
typedef std::unordered_map<ustring, std::unique_ptr<PointCloud>> PointCloudMap;
static PointCloudMap pointclouds;
static OIIO::spin_mutex pointcloudmap_mutex;
+2 -2
View File
@@ -22,8 +22,8 @@ public:
~PointCloud();
static PointCloud* get(ustring filename, bool write = false);
typedef std::unordered_map<
ustring, std::unique_ptr<Partio::ParticleAttribute>, ustringHash>
typedef std::unordered_map<ustring,
std::unique_ptr<Partio::ParticleAttribute>>
AttributeMap;
const Partio::ParticlesData* read_access() const
+1 -4
View File
@@ -114,14 +114,11 @@ RendererServices::good(TextureHandle* texture_handle)
bool
RendererServices::is_udim(TextureHandle* texture_handle)
{
#if OPENIMAGEIO_VERSION >= 20307
return texturesys()->is_udim(texture_handle);
#else
return false;
#endif
}
bool
RendererServices::texture(ustring filename, TextureHandle* texture_handle,
TexturePerthread* texture_thread_info,
+10 -28
View File
@@ -3331,44 +3331,27 @@ RuntimeOptimizer::run()
OSL_DASSERT(sym1 && sym1->typespec().is_string());
if (sym1->is_constant()) {
if (op.nargs() == 3) {
Symbol* sym2 = opargsym(op, 2);
// getattribute( attributename, result )
m_attributes_needed.insert(
AttributeNeeded(sym1->get_string(), ustring(),
sym2->typespec().simpletype()));
} else if (op.nargs() == 4) {
AttributeNeeded(sym1->get_string()));
} else {
OSL_DASSERT(op.nargs() == 4 || op.nargs() == 5);
Symbol* sym2 = opargsym(op, 2);
Symbol* sym3 = opargsym(op, 3);
if (sym2->typespec().is_string()) {
// getattribute( scopename, attributename, result )
// getattribute( scopename, attributename, result ) or
// getattribute( scopename, attributename, arrayindex, result )
if (sym2->is_constant()) {
m_attributes_needed.insert(AttributeNeeded(
sym2->get_string(), sym1->get_string(),
sym3->typespec().simpletype()));
m_attributes_needed.insert(
AttributeNeeded(sym2->get_string(),
sym1->get_string()));
} else {
m_unknown_attributes_needed = true;
}
} else {
// getattribute( attributename, arrayindex, result )
m_attributes_needed.insert(
AttributeNeeded(sym1->get_string(), ustring(),
sym3->typespec().simpletype()));
AttributeNeeded(sym1->get_string()));
}
} else if (op.nargs() == 5) {
Symbol* sym2 = opargsym(op, 2);
Symbol* sym4 = opargsym(op, 4);
if (sym2->typespec().is_string()) {
// getattribute( scopename, attributename, arrayindex, result )
if (sym2->is_constant()) {
m_attributes_needed.insert(AttributeNeeded(
sym2->get_string(), sym1->get_string(),
sym4->typespec().simpletype()));
} else {
m_unknown_attributes_needed = true;
}
}
} else {
OSL_DASSERT(false);
}
} else { // sym1 not constant
m_unknown_attributes_needed = true;
@@ -3420,8 +3403,7 @@ RuntimeOptimizer::run()
if (m_attributes_needed.size()) {
shadingcontext()->infofmt("Group needs attributes:");
for (auto&& f : m_attributes_needed)
shadingcontext()->infofmt(" {} {} {}", f.name, f.scope,
f.type);
shadingcontext()->infofmt(" {} {}", f.name, f.scope);
if (m_unknown_attributes_needed)
shadingcontext()->infofmt(
" Also may construct attribute names on the fly.");
+1 -1
View File
@@ -481,7 +481,7 @@ private:
ShaderGlobals m_shaderglobals; ///< Dummy ShaderGlobals
// Keep track of some things for the whole shader group:
typedef std::unordered_map<ustring, ustring, ustringHash> ustringmap_t;
typedef std::unordered_map<ustring, ustring> ustringmap_t;
std::vector<ustringmap_t> m_params_holding_globals;
///< Which params of each layer really just hold globals
+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
#include "opcolor.h"
OSL_NAMESPACE_ENTER
namespace pvt {
// Intent is for a device to export or serialize the ShadingStateUniform from the
// ShadingSystem into a device side buffer that can be passed into
// kernel launches.
// Requires data to be self-contained and flat in memory to be device friendly.
struct ShadingStateUniform {
ColorSystem m_colorsystem; ///< Data for current colorspace
ustring m_commonspace_synonym; ///< Synonym for "common" space
bool m_unknown_coordsys_error; ///< Error to use unknown xform name?
};
} // namespace pvt
OSL_NAMESPACE_EXIT
+21 -36
View File
@@ -1002,7 +1002,6 @@ ShadingSystemImpl::ShadingSystemImpl(RendererServices* renderer,
, m_strict_messages(true)
, m_error_repeats(false)
, m_range_checking(true)
, m_unknown_coordsys_error(true)
, m_connection_error(true)
, m_greedyjit(false)
, m_countlayerexecs(false)
@@ -1049,7 +1048,6 @@ ShadingSystemImpl::ShadingSystemImpl(RendererServices* renderer,
, m_llvm_profiling_events(0)
, m_llvm_output_bitcode(0)
, m_llvm_dumpasm(0)
, m_commonspace_synonym("world")
, m_max_local_mem_KB(2048)
, m_compile_report(false)
, m_buffer_printf(true)
@@ -1071,6 +1069,9 @@ ShadingSystemImpl::ShadingSystemImpl(RendererServices* renderer,
, m_stat_inst_merge_time(0)
, m_stat_max_llvm_local_mem(0)
{
m_shading_state_uniform.m_commonspace_synonym = ustring("world");
m_shading_state_uniform.m_unknown_coordsys_error = true;
m_stat_shaders_loaded = 0;
m_stat_shaders_requested = 0;
m_stat_groups = 0;
@@ -1551,7 +1552,8 @@ ShadingSystemImpl::attribute(string_view name, TypeDesc type, const void* val)
ATTR_SET_STRING("llvm_prune_ir_strategy", m_llvm_prune_ir_strategy);
ATTR_SET("strict_messages", int, m_strict_messages);
ATTR_SET("range_checking", int, m_range_checking);
ATTR_SET("unknown_coordsys_error", int, m_unknown_coordsys_error);
ATTR_SET("unknown_coordsys_error", int,
m_shading_state_uniform.m_unknown_coordsys_error);
ATTR_SET("connection_error", int, m_connection_error);
ATTR_SET("greedyjit", int, m_greedyjit);
ATTR_SET("relaxed_param_typecheck", int, m_relaxed_param_typecheck);
@@ -1567,7 +1569,8 @@ ShadingSystemImpl::attribute(string_view name, TypeDesc type, const void* val)
ATTR_SET("exec_repeat", int, m_exec_repeat);
ATTR_SET("opt_warnings", int, m_opt_warnings);
ATTR_SET("gpu_opt_error", int, m_gpu_opt_error);
ATTR_SET_STRING("commonspace", m_commonspace_synonym);
ATTR_SET_STRING("commonspace",
m_shading_state_uniform.m_commonspace_synonym);
ATTR_SET_STRING("debug_groupname", m_debug_groupname);
ATTR_SET_STRING("debug_layername", m_debug_layername);
ATTR_SET_STRING("opt_layername", m_opt_layername);
@@ -1718,13 +1721,15 @@ ShadingSystemImpl::getattribute(string_view name, TypeDesc type, void* val)
ATTR_DECODE("strict_messages", int, m_strict_messages);
ATTR_DECODE("error_repeats", int, m_error_repeats);
ATTR_DECODE("range_checking", int, m_range_checking);
ATTR_DECODE("unknown_coordsys_error", int, m_unknown_coordsys_error);
ATTR_DECODE("unknown_coordsys_error", int,
m_shading_state_uniform.m_unknown_coordsys_error);
ATTR_DECODE("connection_error", int, m_connection_error);
ATTR_DECODE("greedyjit", int, m_greedyjit);
ATTR_DECODE("countlayerexecs", int, m_countlayerexecs);
ATTR_DECODE("relaxed_param_typecheck", int, m_relaxed_param_typecheck);
ATTR_DECODE("max_warnings_per_thread", int, m_max_warnings_per_thread);
ATTR_DECODE_STRING("commonspace", m_commonspace_synonym);
ATTR_DECODE_STRING("commonspace",
m_shading_state_uniform.m_commonspace_synonym);
ATTR_DECODE_STRING("colorspace", m_colorspace);
ATTR_DECODE_STRING("debug_groupname", m_debug_groupname);
ATTR_DECODE_STRING("debug_layername", m_debug_layername);
@@ -1974,18 +1979,16 @@ ShadingSystemImpl::getattribute(ShaderGroup* group, string_view name,
return true;
}
if (name == "group_init_name" && type.basetype == TypeDesc::STRING) {
*(ustring*)val
= ustring::fmtformat("__direct_callable__group_{}_{}_init",
group->name(), group->id());
*(ustring*)val = ustring::fmtformat("__direct_callable__group_{}_init",
group->name());
return true;
}
if (name == "group_entry_name" && type.basetype == TypeDesc::STRING) {
int nlayers = group->nlayers();
ShaderInstance* inst = (*group)[nlayers - 1];
// This formulation mirrors OSOProcessorBase::layer_function_name()
*(ustring*)val = ustring::fmtformat("__direct_callable__{}_{}_{}",
group->name(), inst->layername(),
inst->id());
*(ustring*)val = ustring::fmtformat("__direct_callable__{}_{}",
group->name(), inst->layername());
return true;
}
if (name == "layer_osofiles" && type.basetype == TypeDesc::STRING) {
@@ -2102,11 +2105,6 @@ ShadingSystemImpl::getattribute(ShaderGroup* group, string_view name,
*(ustring**)val = n ? &group->m_attribute_scopes[0] : NULL;
return true;
}
if (name == "attribute_types" && type.basetype == TypeDesc::PTR) {
size_t n = group->m_attribute_types.size();
*(TypeDesc**)val = n ? &group->m_attribute_types[0] : NULL;
return true;
}
if (name == "unknown_attributes_needed" && type == TypeDesc::TypeInt) {
*(int*)val = (int)group->m_unknown_attributes_needed;
return true;
@@ -2127,10 +2125,6 @@ ShadingSystemImpl::getattribute(ShaderGroup* group, string_view name,
*(void**)val = n ? &group->m_userdata_init_vals[0] : NULL;
return true;
}
if (name == "llvm_groupdata_size" && type == TypeDesc::TypeInt) {
*(int*)val = (int)group->llvm_groupdata_size();
return true;
}
return false;
}
@@ -2392,14 +2386,14 @@ ShadingSystemImpl::getstats(int level) const
<< (int)(100.0f * m_stat_empty_groups / m_stat_groups_compiled)
<< "%)\n";
if (m_stat_instances_compiled > 0 || m_stat_groups_compiled > 0) {
print(out, " Optimized {} ops to {} ({:.1f}%)\n",
(int)m_stat_preopt_ops, (int)m_stat_postopt_ops,
print(out, " Optimized {} ops to {} ({:.1f}%)\n", m_stat_preopt_ops,
m_stat_postopt_ops,
100.0
* (double(m_stat_postopt_ops)
/ (std::max(1, (int)m_stat_preopt_ops))
- 1.0));
print(out, " Optimized {} symbols to {} ({:.1f}%)\n",
(int)m_stat_preopt_syms, (int)m_stat_postopt_syms,
m_stat_preopt_syms, m_stat_postopt_syms,
100.0
* (double(m_stat_postopt_syms)
/ (std::max(1, (int)m_stat_preopt_syms))
@@ -3188,9 +3182,7 @@ ShadingSystemImpl::ReParameter(ShaderGroup& group, string_view layername_,
}
// Check for mismatch versus previously-declared type
if ((relaxed_param_typecheck() && !relaxed_equivalent(sym->typespec(), type))
|| (!relaxed_param_typecheck()
&& !relaxed_equivalent(sym->typespec(), type)))
if (!equivalent(sym->typespec(), type))
return false;
// Can't change param value if the group has already been optimized,
@@ -3565,7 +3557,6 @@ ShadingSystemImpl::optimize_group(ShaderGroup& group, ShadingContext* ctx,
for (auto&& f : rop.m_attributes_needed) {
group.m_attributes_needed.push_back(f.name);
group.m_attribute_scopes.push_back(f.scope);
group.m_attribute_types.push_back(f.type);
}
group.m_optimized = true;
@@ -4168,8 +4159,7 @@ ShadingContext::ocio_transform(StringParam fromspace, StringParam tospace,
const float eps = 0.001f;
Color3 CC[3] = { C.val(), C.val() + eps * C.dx(),
C.val() + eps * C.dy() };
cp->apply((float*)&CC, 3, 1, 3, sizeof(float), sizeof(Color3),
3 * sizeof(Color3));
cp->apply((float*)&CC, 3, 1, 3, sizeof(float), sizeof(Color3), 0);
Cout.set(CC[0], (CC[1] - CC[0]) * (1.0f / eps),
(CC[2] - CC[0]) * (1.0f / eps));
return true;
@@ -4469,13 +4459,8 @@ osl_bind_interpolated_param(void* sg_, const void* name, long long type,
sg->context->incr_get_userdata_calls();
}
if (status == 2) {
int udata_size = (userdata_has_derivs ? 3 : 1) * TYPEDESC(type).size();
// If userdata was present, copy it to the shader variable
memcpy(symbol_data, userdata_data,
std::min(symbol_data_size, udata_size));
if (symbol_data_size > udata_size)
memset((char*)symbol_data + udata_size, 0,
symbol_data_size - udata_size);
memcpy(symbol_data, userdata_data, symbol_data_size);
return 1;
}
return 0; // no such user data
-21
View File
@@ -149,27 +149,6 @@ equivalent(const TypeSpec& a, const TypeSpec& b)
|| a.is_unsized_array() != b.is_unsized_array());
}
// Relaxed rules just look to see that the types are isomorphic to each other (ie: same number of base values)
// Note that:
// * basetypes must match exactly (int vs float vs string)
// * valuetype cannot be unsized (we must know the concrete number of values)
// * if paramtype is sized (or not an array) just check for the total number of entries
// * if paramtype is unsized (shader writer is flexible about how many values come in) -- make sure we are a multiple of the target type
// * allow a single float setting a vec3 (or equivalent)
bool
relaxed_equivalent(const TypeSpec& a, const TypeSpec& b)
{
const TypeDesc paramtype = a.simpletype();
const TypeDesc valuetype = b.simpletype();
return valuetype.basetype == paramtype.basetype
&& !valuetype.is_unsized_array()
&& ((!paramtype.is_unsized_array()
&& valuetype.basevalues() == paramtype.basevalues())
|| (paramtype.is_unsized_array()
&& valuetype.basevalues() % paramtype.aggregate == 0)
|| (paramtype.is_vec3() && valuetype == TypeDesc::FLOAT));
}
}; // namespace pvt
+2 -4
View File
@@ -90,10 +90,8 @@ abs(const Dual2<float>& x)
#define __OSL_XMACRO_ARGS (fabs, std::abs)
#include "wide_opunary_int_xmacro.h"
#define __OSL_XMACRO_ARGS (fmod, OIIO::safe_fmod, safe_fmod)
#include "wide_opbinary_per_component_xmacro.h"
#define __OSL_XMACRO_ARGS (fmod, OIIO::safe_fmod, safe_fmod)
#include "wide_opbinary_per_component_mixed_vector_float_xmacro.h"
#define __OSL_XMACRO_ARGS (fmod, OIIO::safe_fmod)
#include "wide_opbinary_per_component_float_or_vector_xmacro.h"
static OSL_FORCEINLINE float
+10 -10
View File
@@ -105,8 +105,8 @@ default_texture(BatchedRendererServices* bsr, ustring filename,
// It's actually faster to ask for 4 channels (even if we need fewer)
// and ensure that they're being put in aligned memory.
// TODO: investigate if the above statement is true when nchannels==1
// NOTE: using simd::vfloat4 to speedup texture transformation below
OIIO::simd::vfloat4 result_simd, dresultds_simd, dresultdt_simd;
// NOTE: using simd::float4 to speedup texture transformation below
OIIO::simd::float4 result_simd, dresultds_simd, dresultdt_simd;
bool retVal = false;
@@ -120,8 +120,8 @@ default_texture(BatchedRendererServices* bsr, ustring filename,
has_derivs ? (float*)&dresultds_simd : NULL,
has_derivs ? (float*)&dresultdt_simd : NULL);
OIIO::simd::vfloat4 dresultdx_simd;
OIIO::simd::vfloat4 dresultdy_simd;
OIIO::simd::float4 dresultdx_simd;
OIIO::simd::float4 dresultdy_simd;
if (has_derivs) {
// Correct our st texture space gradients into xy-space gradients
dresultdx_simd = dresultds_simd * dsdx + dresultdt_simd * dtdx;
@@ -297,8 +297,8 @@ default_texture3d(BatchedRendererServices* bsr, ustring filename,
// and ensure that they're being put in aligned memory.
// TODO: investigate if the above statement is true when nchannels==1
// NOTE: using simd::vfloat4 to speedup texture transformation below
OIIO::simd::vfloat4 result_simd, dresultds_simd, dresultdt_simd,
// NOTE: using simd::float4 to speedup texture transformation below
OIIO::simd::float4 result_simd, dresultds_simd, dresultdt_simd,
dresultdr_simd;
bool retVal = false;
@@ -314,8 +314,8 @@ default_texture3d(BatchedRendererServices* bsr, ustring filename,
has_derivs ? (float*)&dresultdt_simd : nullptr,
has_derivs ? (float*)&dresultdr_simd : nullptr);
OIIO::simd::vfloat4 dresultdx_simd;
OIIO::simd::vfloat4 dresultdy_simd;
OIIO::simd::float4 dresultdx_simd;
OIIO::simd::float4 dresultdy_simd;
if (has_derivs) {
// Correct our str texture space gradients into xyz-space gradients
dresultdx_simd = dresultds_simd * dPdx.x + dresultdt_simd * dPdx.y
@@ -480,8 +480,8 @@ default_environment(BatchedRendererServices* bsr, ustring filename,
// and ensure that they're being put in aligned memory.
// TODO: investigate if the above statement is true when nchannels==1
// NOTE: using simd::vfloat4 to speedup texture transformation below
OIIO::simd::vfloat4 result_simd;
// NOTE: using simd::float4 to speedup texture transformation below
OIIO::simd::float4 result_simd;
bool retVal = false;
+2 -4
View File
@@ -73,8 +73,7 @@ __OSL_MASKED_OP1(naninf_check_offset,
"Detected {} value in {}{} at {}:{} (op {}) batch lane:{}",
vals[i * __OSL_WIDTH + lane],
d > 0 ? "the derivatives of " : "", USTR(symbolname),
USTR(sourcefile), sourceline, USTR(opname),
lane.value());
USTR(sourcefile), sourceline, USTR(opname), lane);
// continue checking all data lanes, and all components
// for that matter, we want to find all issues, not just
// the 1st, right?
@@ -112,8 +111,7 @@ __OSL_MASKED_OP1(naninf_check_offset, Wi)(int mask_value, int ncomps,
"Detected {} value in {}{} at {}:{} (op {}) batch lane:{}",
vals[i * __OSL_WIDTH + lane],
d > 0 ? "the derivatives of " : "", USTR(symbolname),
USTR(sourcefile), sourceline, USTR(opname),
lane.value());
USTR(sourcefile), sourceline, USTR(opname), lane);
// continue checking all data lanes, and all components
// for that matter, we want to find all issues, not just
// the 1st, right?
+2 -13
View File
@@ -3,7 +3,7 @@
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
set (CMAKE_AUTOMOC ON)
if (Qt5_POSITION_INDEPENDENT_CODE OR Qt6_POSITION_INDEPENDENT_CODE)
if (Qt5_POSITION_INDEPENDENT_CODE)
set (CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
set (osltoy_srcs
@@ -13,17 +13,6 @@ set_target_properties (osltoy PROPERTIES FOLDER "Tools")
target_link_libraries (osltoy
PRIVATE
oslexec
$<TARGET_NAME_IF_EXISTS:Qt5::Core>
$<TARGET_NAME_IF_EXISTS:Qt5::Gui>
$<TARGET_NAME_IF_EXISTS:Qt5::Widgets>
$<TARGET_NAME_IF_EXISTS:Qt6::Core>
$<TARGET_NAME_IF_EXISTS:Qt6::Gui>
$<TARGET_NAME_IF_EXISTS:Qt6::Widgets>
Qt5::Core Qt5::Gui Qt5::Widgets
${Boost_LIBRARIES} ${CMAKE_DL_LIBS})
if (Qt5_FOUND)
target_compile_definitions(osltoy PRIVATE OSL_QT_MAJOR=5)
endif ()
if (Qt6_FOUND)
target_compile_definitions(osltoy PRIVATE OSL_QT_MAJOR=6)
endif ()
install_targets (osltoy)
-12
View File
@@ -198,11 +198,7 @@ public:
QWidget::hideEvent(e);
}
#if OSL_QT_MAJOR < 6
void enterEvent(QEvent* event) override;
#else
void enterEvent(QEnterEvent* event) override;
#endif
void mouseMoveEvent(QMouseEvent* event) override;
};
@@ -297,11 +293,7 @@ public:
void mouseMoveEvent(QMouseEvent* /*event*/) override { magnifierEvent(); }
#if OSL_QT_MAJOR < 6
void enterEvent(QEvent* /*event*/) override
#else
void enterEvent(QEnterEvent* /*event*/) override
#endif
{
if (shouldShowMagnifier())
showMagnifier();
@@ -351,11 +343,7 @@ public:
};
void
#if OSL_QT_MAJOR < 6
Magnifier::enterEvent(QEvent* event)
#else
Magnifier::enterEvent(QEnterEvent* event)
#endif
{
if (m_renderview)
m_renderview->magnifierEvent();
-4
View File
@@ -16,10 +16,6 @@
#include <OSL/oslquery.h>
#include <OSL/rendererservices.h>
#ifndef OSL_QT_MAJOR
# error "Build problem? OSL_QT_MAJOR not defined."
#endif
#include <QAction>
#include <QMainWindow>
#include <QTimer>
+1 -1
View File
@@ -115,7 +115,7 @@ private:
typedef bool (OSLToyRenderer::*AttrGetter)(ShaderGlobals* sg, bool derivs,
ustring object, TypeDesc type,
ustring name, void* val);
typedef std::unordered_map<ustring, AttrGetter, ustringHash> AttrGetterMap;
typedef std::unordered_map<ustring, AttrGetter> AttrGetterMap;
AttrGetterMap m_attr_getters;
// Attribute getters
+20 -10
View File
@@ -16,20 +16,30 @@ glass
float eta = 1.5
[[ string help = "Index of refraction",
float min = 1, float max = 3 ]],
int caustics = 0
[[ string help = "Enable indirect lighting through glass",
string widget = "checkBox" ]],
int TIR = 0
[[ string help = "Enable Total Internal Reflection",
string widget = "checkBox" ]]
)
{
// Take into account backfacing to invert eta accordingly
if (backfacing()) {
Ci = Cs * refraction(N, 1.0 / eta);
// If Total Internal Reflection is enabled, we also return a
// reflection closure, which might make rays bounce too much
// inside an object. That's why we make it optional.
if (TIR)
Ci += Ks * reflection(N, 1.0 / eta);
} else {
Ci = Ks * reflection(N, eta) + Cs * refraction(N, eta);
// If the current ray type is glossy or diffuse, that means we
// are computing indirect lighting. Letting that interact with
// glass produces caustics, which are normally hard to trace and
// noisy. So we only return closures if that's not the case or
// the "caustics" flag is on.
if (caustics || (!raytype("glossy") && !raytype("diffuse"))) {
// Take into account backfacing to invert eta accordingly
if (backfacing()) {
Ci = Cs * refraction(N, 1.0 / eta);
// If Total Internal Reflection is enabled, we also return a
// reflection closure, which might make rays bounce too much
// inside an object. That's why we make it optional.
if (TIR)
Ci += Ks * reflection(N, 1.0 / eta);
} else {
Ci = Ks * reflection(N, eta) + Cs * refraction(N, eta);
}
}
}
+7 -9
View File
@@ -3,21 +3,19 @@
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
# The 'testrender' executable
file(GLOB testrender_srcs *.cpp)
set (testrender_srcs
shading.cpp
simpleraytracer.cpp
testrender.cpp)
if (USE_OPTIX)
list (APPEND testrender_srcs optixraytracer.cpp)
set (testrender_cuda_srcs
cuda/quad.cu
cuda/optix_raytracer.cu
cuda/sphere.cu
cuda/wrapper.cu )
# We only need to generate the PTX for rend_lib.cu if we are using OptiX 7.0+.
# Some of OptiX 6 device functions defined in rend_lib.cu cannot be compiled
# with NVCC, they must be compiled with clang using the LLVM_COMPILE_CUDA macro.
if (OPTIX_VERSION VERSION_GREATER_EQUAL 7)
list (APPEND testshade_cuda_srcs cuda/rend_lib.cu)
endif ()
cuda/wrapper.cu
cuda/rend_lib.cu)
# We need to make sure that the PTX files are regenerated whenever these
# headers change.
+4 -88
View File
@@ -5,96 +5,14 @@
#include <optix.h>
#if (OPTIX_VERSION < 70000)
# include <optixu/optixu_math_namespace.h>
# include <optixu/optixu_vector_types.h>
#endif
#include "util.h"
#if (OPTIX_VERSION < 70000)
using namespace optix;
#include <optix_device.h>
// Launch variables
rtDeclareVariable(uint2, launch_index, rtLaunchIndex, );
rtDeclareVariable(uint2, launch_dim, rtLaunchDim, );
#include <OSL/device_string.h>
// Scene/Shading variables
rtDeclareVariable(float3, bad_color, , );
rtDeclareVariable(float3, bg_color, , );
rtDeclareVariable(rtObject, top_object, , );
// Ray payload
rtDeclareVariable(PRD_radiance, prd_radiance, rtPayload, );
// Geometry/Intersection attributes
rtDeclareVariable(float3, geometric_normal, attribute geometric_normal, );
rtDeclareVariable(float3, shading_normal, attribute shading_normal, );
// Camera variables
rtDeclareVariable(float3, eye, , );
rtDeclareVariable(float3, dir, , );
rtDeclareVariable(float3, cx, , );
rtDeclareVariable(float3, cy, , );
rtDeclareVariable(float, invw, , );
rtDeclareVariable(float, invh, , );
// Buffers
rtBuffer<float3, 2> output_buffer;
RT_PROGRAM void
raygen()
{
// Compute the pixel coordinates
float2 d = make_float2(static_cast<float>(launch_index.x) + 0.5f,
static_cast<float>(launch_index.y) + 0.5f);
// Make the ray for the current pixel
RayGeometry r;
r.origin = eye;
r.direction = optix::normalize(cx * (d.x * invw - 0.5f)
+ cy * (0.5f - d.y * invh) + dir);
Ray ray = optix::make_Ray(r.origin, r.direction, 0, 1e-3f, RT_DEFAULT_MAX);
// Create a struct to hold the shading result
PRD_radiance prd;
prd.result = make_float3(0.0f);
// Trace the ray against the scene. The hit/miss program is called before
// this call returns.
rtTrace(top_object, ray, prd);
// Write the shading result to the output buffer
output_buffer[launch_index] = prd.result;
}
RT_PROGRAM void
miss()
{
prd_radiance.result = bg_color;
}
RT_PROGRAM void
exception()
{
rtPrintExceptionDetails();
output_buffer[launch_index] = bad_color;
}
#else //#if (OPTIX_VERSION < 70000)
# include <optix.h>
# include <optix_device.h>
# include <OSL/device_string.h>
# include "rend_lib.h"
# include "render_params.h"
#include "rend_lib.h"
#include "render_params.h"
extern "C" {
@@ -175,5 +93,3 @@ osl_tex2DLookup(void* handle, float s, float t)
cudaTextureObject_t texID = cudaTextureObject_t(handle);
return tex2D<float4>(texID, s, t);
}
#endif //#if (OPTIX_VERSION < 70000)
+3 -76
View File
@@ -5,82 +5,11 @@
#include <optix.h>
#if (OPTIX_VERSION < 70000)
# include <optixu/optixu_aabb_namespace.h>
# include <optixu/optixu_math_namespace.h>
# include <optixu/optixu_vector_types.h>
#include "rend_lib.h"
#include "render_params.h"
#include "wrapper.h"
using namespace optix;
rtDeclareVariable(float3, p, , );
rtDeclareVariable(float3, ex, , );
rtDeclareVariable(float3, ey, , );
rtDeclareVariable(float3, n, , );
rtDeclareVariable(float, eu, , );
rtDeclareVariable(float, ev, , );
rtDeclareVariable(float, a, , );
rtDeclareVariable(float3, texcoord, attribute texcoord, );
rtDeclareVariable(float3, geometric_normal, attribute geometric_normal, );
rtDeclareVariable(float3, shading_normal, attribute shading_normal, );
rtDeclareVariable(float, surface_area, attribute surface_area, );
rtDeclareVariable(float3, dPdu, attribute dPdu, );
rtDeclareVariable(float3, dPdv, attribute dPdv, );
rtDeclareVariable(optix::Ray, ray, rtCurrentRay, );
RT_PROGRAM void
intersect(void)
{
float dn = dot(ray.direction, n);
float en = dot(p - ray.origin, n);
if (dn * en > 0) {
float t = en / dn;
float3 h = (ray.origin + ray.direction * t) - p;
float dx = dot(h, ex) * eu;
float dy = dot(h, ey) * ev;
if (dx >= 0 && dx < 1.0f && dy >= 0 && dy < 1.0f
&& rtPotentialIntersection(t)) {
shading_normal = geometric_normal = n;
texcoord = make_float3(dot(h, ex) * eu, dot(h, ey) * ev, 0.0f);
dPdu = ey;
dPdv = ex;
surface_area = a;
rtReportIntersection(0);
}
}
}
RT_PROGRAM void
bounds(int, float result[6])
{
const float3 p00 = p;
const float3 p01 = p + ex;
const float3 p10 = p + ey;
const float3 p11 = p + ex + ey;
const float area = length(cross(ex, ey));
optix::Aabb* aabb = reinterpret_cast<optix::Aabb*>(result);
if (area > 0.0f && !isinf(area)) {
aabb->m_min = fminf(fminf(p00, p01), fminf(p10, p11));
aabb->m_max = fmaxf(fmaxf(p00, p01), fmaxf(p10, p11));
} else {
aabb->invalidate();
}
}
#else //#if (OPTIX_VERSION < 70000)
# include "rend_lib.h"
# include "render_params.h"
# include "wrapper.h"
extern "C" __device__ void
__direct_callable__quad_shaderglobals(const unsigned int idx, const float t_hit,
const float3 ray_origin,
@@ -131,5 +60,3 @@ __intersection__quad()
optixReportIntersection(t, RAYTRACER_HIT_QUAD);
}
}
#endif //#if (OPTIX_VERSION < 70000)
+15 -475
View File
@@ -4,473 +4,15 @@
#include <optix.h>
#include <optix_device.h>
#if (OPTIX_VERSION < 70000)
# include <optix_math.h>
# include <optixu/optixu_matrix_namespace.h>
#else
# define OPTIX_COMPATIBILITY 7
# include <cuda_runtime.h>
# include <optix_device.h>
#endif
#define OPTIX_COMPATIBILITY 7
#include <OSL/oslclosure.h>
#include <cuda_runtime.h>
#include <optix_device.h>
#include "rend_lib.h"
#if (OPTIX_VERSION < 70000)
rtDeclareVariable(uint2, launch_index, rtLaunchIndex, );
rtDeclareVariable(uint2, launch_dim, rtLaunchDim, );
rtDeclareVariable(char*, test_str_1, , );
rtDeclareVariable(char*, test_str_2, , );
// N.B. These will be cast to OSL::Matrix44 variables when used.
rtDeclareVariable(optix::Matrix4x4, object2common, , );
rtDeclareVariable(optix::Matrix4x4, shader2common, , );
rtBuffer<uint64_t> xform_name_buffer;
rtBuffer<optix::Matrix4x4> xform_buffer;
OSL_NAMESPACE_ENTER
namespace pvt {
rtBuffer<char, 1> s_color_system;
}
OSL_NAMESPACE_EXIT
// Taken from the SimplePool class
__device__ static inline size_t
alignment_offset_calc(void* ptr, size_t alignment)
{
uintptr_t ptrbits = reinterpret_cast<uintptr_t>(ptr);
uintptr_t offset = ((ptrbits + alignment - 1) & -alignment) - ptrbits;
return offset;
}
// These functions are declared extern to prevent name mangling.
extern "C" {
__device__ void*
closure_component_allot(void* pool, int id, size_t prim_size,
const OSL::Color3& w)
{
((OSL::ClosureComponent*)pool)->id = id;
((OSL::ClosureComponent*)pool)->w = w;
size_t needed = (sizeof(OSL::ClosureComponent) - sizeof(void*) + prim_size
+ (alignof(OSL::ClosureComponent) - 1))
& ~(alignof(OSL::ClosureComponent) - 1);
char* char_ptr = (char*)pool;
return (void*)&char_ptr[needed];
}
__device__ void*
closure_mul_allot(void* pool, const OSL::Color3& w, OSL::ClosureColor* c)
{
((OSL::ClosureMul*)pool)->id = OSL::ClosureColor::MUL;
((OSL::ClosureMul*)pool)->weight = w;
((OSL::ClosureMul*)pool)->closure = c;
size_t needed = (sizeof(OSL::ClosureMul)
+ (alignof(OSL::ClosureComponent) - 1))
& ~(alignof(OSL::ClosureComponent) - 1);
char* char_ptr = (char*)pool;
return &char_ptr[needed];
}
__device__ void*
closure_mul_float_allot(void* pool, const float& w, OSL::ClosureColor* c)
{
((OSL::ClosureMul*)pool)->id = OSL::ClosureColor::MUL;
((OSL::ClosureMul*)pool)->weight.x = w;
((OSL::ClosureMul*)pool)->weight.y = w;
((OSL::ClosureMul*)pool)->weight.z = w;
((OSL::ClosureMul*)pool)->closure = c;
size_t needed = (sizeof(OSL::ClosureMul)
+ (alignof(OSL::ClosureComponent) - 1))
& ~(alignof(OSL::ClosureComponent) - 1);
char* char_ptr = (char*)pool;
return &char_ptr[needed];
}
__device__ void*
closure_add_allot(void* pool, OSL::ClosureColor* a, OSL::ClosureColor* b)
{
((OSL::ClosureAdd*)pool)->id = OSL::ClosureColor::ADD;
((OSL::ClosureAdd*)pool)->closureA = a;
((OSL::ClosureAdd*)pool)->closureB = b;
size_t needed = (sizeof(OSL::ClosureAdd)
+ (alignof(OSL::ClosureComponent) - 1))
& ~(alignof(OSL::ClosureComponent) - 1);
char* char_ptr = (char*)pool;
return &char_ptr[needed];
}
__device__ void*
osl_allocate_closure_component(void* sg_, int id, int size)
{
ShaderGlobals* sg_ptr = (ShaderGlobals*)sg_;
OSL::Color3 w = OSL::Color3(1, 1, 1);
// Fix up the alignment
void* ret = ((char*)sg_ptr->renderstate)
+ alignment_offset_calc(sg_ptr->renderstate,
alignof(OSL::ClosureComponent));
size = max(4, size);
sg_ptr->renderstate = closure_component_allot(ret, id, size, w);
return ret;
}
__device__ void*
osl_allocate_weighted_closure_component(void* sg_, int id, int size,
const OSL::Color3* w)
{
ShaderGlobals* sg_ptr = (ShaderGlobals*)sg_;
if (w->x == 0.0f && w->y == 0.0f && w->z == 0.0f) {
return NULL;
}
size = max(4, size);
// Fix up the alignment
void* ret = ((char*)sg_ptr->renderstate)
+ alignment_offset_calc(sg_ptr->renderstate,
alignof(OSL::ClosureComponent));
sg_ptr->renderstate = closure_component_allot(ret, id, size, *w);
return ret;
}
__device__ void*
osl_mul_closure_color(void* sg_, OSL::ClosureColor* a, const OSL::Color3* w)
{
ShaderGlobals* sg_ptr = (ShaderGlobals*)sg_;
if (a == NULL) {
return NULL;
}
if (w->x == 0.0f && w->y == 0.0f && w->z == 0.0f) {
return NULL;
}
if (w->x == 1.0f && w->y == 1.0f && w->z == 1.0f) {
return a;
}
// Fix up the alignment
void* ret = ((char*)sg_ptr->renderstate)
+ alignment_offset_calc(sg_ptr->renderstate,
alignof(OSL::ClosureComponent));
sg_ptr->renderstate = closure_mul_allot(ret, *w, a);
return ret;
}
__device__ void*
osl_mul_closure_float(void* sg_, OSL::ClosureColor* a, float w)
{
ShaderGlobals* sg_ptr = (ShaderGlobals*)sg_;
if (a == NULL || w == 0.0f) {
return NULL;
}
if (w == 1.0f) {
return a;
}
// Fix up the alignment
void* ret = ((char*)sg_ptr->renderstate)
+ alignment_offset_calc(sg_ptr->renderstate,
alignof(OSL::ClosureComponent));
sg_ptr->renderstate = closure_mul_float_allot(ret, w, a);
return ret;
}
__device__ void*
osl_add_closure_closure(void* sg_, OSL::ClosureColor* a, OSL::ClosureColor* b)
{
ShaderGlobals* sg_ptr = (ShaderGlobals*)sg_;
if (a == NULL) {
return b;
}
if (b == NULL) {
return a;
}
// Fix up the alignment
void* ret = ((char*)sg_ptr->renderstate)
+ alignment_offset_calc(sg_ptr->renderstate,
alignof(OSL::ClosureComponent));
sg_ptr->renderstate = closure_add_allot(ret, a, b);
return ret;
}
# define IS_STRING(type) (type.basetype == OSL::TypeDesc::STRING)
# define IS_PTR(type) (type.basetype == OSL::TypeDesc::PTR)
# define IS_COLOR(type) (type.vecsemantics == OSL::TypeDesc::COLOR)
__device__ bool
rend_get_userdata(OSL::StringParam name, void* data, int data_size,
const OSL::TypeDesc& type, int index)
{
// Perform a userdata lookup using the parameter name, type, and
// userdata index. If there is a match, memcpy the value into data and
// return 1.
if (IS_PTR(type) && name == STRING_PARAMS(colorsystem)) {
*(void**)data = &OSL::pvt::s_color_system[0];
return true;
}
// TODO: This is temporary code for initial testing and demonstration.
if (IS_STRING(type) && name == HDSTR(test_str_1)) {
memcpy(data, &test_str_2, 8);
return true;
}
return false;
}
# undef IS_COLOR
# undef IS_STRING
# undef IS_PTR
__device__ int
osl_bind_interpolated_param(void* sg_, const void* name, long long type,
int userdata_has_derivs, void* userdata_data,
int symbol_has_derivs, void* symbol_data,
int symbol_data_size, char* userdata_initialized,
int userdata_index)
{
char status = *userdata_initialized;
if (status == 0) {
bool ok = rend_get_userdata(HDSTR(name), userdata_data,
symbol_data_size, (*(OSL::TypeDesc*)&type),
userdata_index);
*userdata_initialized = status = 1 + ok;
}
if (status == 2) {
memcpy(symbol_data, userdata_data, symbol_data_size);
return 1;
}
return 0;
}
__device__ int
osl_strlen_is(const char* str)
{
return HDSTR(str).length();
}
__device__ int
osl_hash_is(const char* str)
{
return HDSTR(str).hash();
}
__device__ int
osl_getchar_isi(const char* str, int index)
{
return (str && unsigned(index) < HDSTR(str).length()) ? str[index] : 0;
}
__device__ void
osl_printf(void* sg_, char* fmt_str, void* args)
{
// This can be used to limit printing to one Cuda thread for debugging
// if (launch_index.x == 0 && launch_index.y == 0)
//
vprintf(fmt_str, (const char*)args);
}
__device__ void*
osl_get_noise_options(void* sg_)
{
ShaderGlobals* sg = ((ShaderGlobals*)sg_);
NoiseOptCUDA* opt
= (NoiseOptCUDA*)((ShadingContextCUDA*)sg->context)->noise_options_ptr();
new (opt) NoiseOptCUDA;
return opt;
}
__device__ void*
osl_get_texture_options(void* sg_)
{
return 0;
}
__device__ void
osl_texture_set_interp_code(void* opt, int mode)
{
// ((TextureOpt *)opt)->interpmode = (TextureOpt::InterpMode)mode;
}
__device__ void
osl_texture_set_stwrap_code(void* opt, int mode)
{
//((TextureOpt *)opt)->swrap = (TextureOpt::Wrap)mode;
//((TextureOpt *)opt)->twrap = (TextureOpt::Wrap)mode;
}
__device__ int
osl_texture(void* sg_, const char* name, void* handle, void* opt_, float s,
float t, float dsdx, float dtdx, float dsdy, float dtdy, int chans,
void* result, void* dresultdx, void* dresultdy, void* alpha,
void* dalphadx, void* dalphady, void* ustring_errormessage)
{
if (!handle)
return 0;
int64_t texID = int64_t(handle);
*((float3*)result) = make_float3(optix::rtTex2D<float4>(texID, s, t));
return 1;
}
__device__ int
osl_range_check_err(int indexvalue, int length, const char* symname, void* sg,
const void* sourcefile, int sourceline,
const char* groupname, int layer, const char* layername,
const char* shadername)
{
if (indexvalue < 0 || indexvalue >= length) {
return indexvalue < 0 ? 0 : length - 1;
}
return indexvalue;
}
__device__ int
osl_range_check(int indexvalue, int length, const char* symname, void* sg,
const void* sourcefile, int sourceline, const char* groupname,
int layer, const char* layername, const char* shadername)
{
if (indexvalue < 0 || indexvalue >= length) {
indexvalue = osl_range_check_err(indexvalue, length, symname, sg,
sourcefile, sourceline, groupname,
layer, layername, shadername);
}
return indexvalue;
}
# define MAT(m) (*(OSL::Matrix44*)m)
__device__ int
osl_get_matrix(void* sg_, void* r, const char* from)
{
ShaderGlobals* sg = (ShaderGlobals*)sg_;
if (HDSTR(from) == STRING_PARAMS(common)) {
MAT(r).makeIdentity();
return true;
}
if (HDSTR(from) == STRING_PARAMS(object)) {
MAT(r) = MAT(&object2common);
return true;
}
if (HDSTR(from) == STRING_PARAMS(shader)) {
MAT(r) = MAT(&shader2common);
return true;
}
// Find the index of the named transform in the transform list
int match_idx = -1;
for (size_t idx = 0; idx < xform_name_buffer.size(); ++idx) {
if (HDSTR(from) == HDSTR(xform_name_buffer[idx])) {
match_idx = static_cast<int>(idx);
break;
}
}
// Return the transform if there is a match
if (match_idx >= 0) {
MAT(r) = MAT(&xform_buffer[match_idx]);
return true;
}
int ok = false; // TODO: Implement transform
if (!ok) {
MAT(r).makeIdentity();
// TBR: OSL would throw an error here, what should we do?
}
return ok;
}
__device__ int
osl_get_inverse_matrix(void* sg_, void* r, const char* to)
{
ShaderGlobals* sg = (ShaderGlobals*)sg_;
if (HDSTR(to) == STRING_PARAMS(common)) {
MAT(r).makeIdentity();
return true;
}
if (HDSTR(to) == STRING_PARAMS(object)) {
MAT(r) = MAT(&object2common);
MAT(r).invert();
return true;
}
if (HDSTR(to) == STRING_PARAMS(shader)) {
MAT(r) = MAT(&shader2common);
MAT(r).invert();
return true;
}
// Find the index of the named transform in the transform list
int match_idx = -1;
for (size_t idx = 0; idx < xform_name_buffer.size(); ++idx) {
if (HDSTR(to) == HDSTR(xform_name_buffer[idx])) {
match_idx = static_cast<int>(idx);
break;
}
}
// Return the transform if there is a match
if (match_idx >= 0) {
MAT(r) = MAT(&xform_buffer[match_idx]);
MAT(r).invert();
return true;
}
int ok = false; // TODO: Implement transform
if (!ok) {
MAT(r).makeIdentity();
// TBR: OSL would throw an error here, what should we do?
}
return ok;
}
# undef MAT
}
#else //#if (OPTIX_VERSION < 70000)
OSL_NAMESPACE_ENTER
@@ -690,9 +232,9 @@ osl_add_closure_closure(void* sg_, OSL::ClosureColor* a, OSL::ClosureColor* b)
}
# define IS_STRING(type) (type.basetype == OSL::TypeDesc::STRING)
# define IS_PTR(type) (type.basetype == OSL::TypeDesc::PTR)
# define IS_COLOR(type) (type.vecsemantics == OSL::TypeDesc::COLOR)
#define IS_STRING(type) (type.basetype == OSL::TypeDesc::STRING)
#define IS_PTR(type) (type.basetype == OSL::TypeDesc::PTR)
#define IS_COLOR(type) (type.vecsemantics == OSL::TypeDesc::COLOR)
__device__ bool
@@ -716,9 +258,9 @@ rend_get_userdata(OSL::StringParam name, void* data, int data_size,
return false;
}
# undef IS_COLOR
# undef IS_STRING
# undef IS_PTR
#undef IS_COLOR
#undef IS_STRING
#undef IS_PTR
@@ -857,8 +399,8 @@ osl_texture(void* sg_, const char* name, void* handle, void* opt_, float s,
{
if (!handle)
return 0;
cudaTextureObject_t texID = cudaTextureObject_t(handle);
float4 fromTexture = osl_tex2DLookup(handle, s, t);
// cudaTextureObject_t texID = cudaTextureObject_t(handle);
float4 fromTexture = osl_tex2DLookup(handle, s, t);
// see note above
// float4 fromTexture = tex2D<float4>(texID, s, t);
*((float3*)result) = make_float3(fromTexture.x, fromTexture.y,
@@ -897,7 +439,7 @@ osl_range_check(int indexvalue, int length, const char* symname, void* sg,
# define MAT(m) (*(OSL::Matrix44*)m)
#define MAT(m) (*(OSL::Matrix44*)m)
__device__ int
osl_get_matrix(void* sg_, void* r, const char* from)
@@ -986,7 +528,5 @@ osl_get_inverse_matrix(void* sg_, void* r, const char* to)
return ok;
}
# undef MAT
#undef MAT
}
#endif //#if (OPTIX_VERSION < 70000)
+9 -25
View File
@@ -4,34 +4,24 @@
#pragma once
#if (OPTIX_VERSION < 70000)
# include <optix_math.h>
#else
# include "../../liboslexec/string_hash.h"
# include <OSL/oslexec.h>
#endif
#include "../../liboslexec/string_hash.h"
#include <OSL/oslexec.h>
#include <OSL/device_string.h>
OSL_NAMESPACE_ENTER
// Create an OptiX variable for each of the 'standard' strings declared in
// <OSL/strdecls.h>.
namespace DeviceStrings {
#if OPTIX_VERSION < 70000
# define STRDECL(str, var_name) \
rtDeclareVariable(OSL_NAMESPACE::DeviceString, var_name, , );
# define STRING_PARAMS(x) StringParams::x
#else
# define STRING_PARAMS(x) UStringHash::Hash(__OSL_STRINGIFY(x))
#define STRING_PARAMS(x) UStringHash::Hash(__OSL_STRINGIFY(x))
// Don't declare anything
# define STRDECL(str, var_name)
#endif
#define STRDECL(str, var_name)
#include <OSL/strdecls.h>
#undef STRDECL
} // namespace DeviceStrings
#if OPTIX_VERSION >= 70000
namespace pvt {
extern __device__ CUdeviceptr s_color_system;
extern __device__ CUdeviceptr osl_printf_buffer_start;
@@ -42,17 +32,11 @@ extern __device__ uint64_t num_named_xforms;
extern __device__ CUdeviceptr xform_name_buffer;
extern __device__ CUdeviceptr xform_buffer;
} // namespace pvt
#endif
OSL_NAMESPACE_EXIT
namespace { // anonymous namespace
#if (OPTIX_VERSION < 70000)
# ifdef __cplusplus
typedef optix::float3 float3;
# endif
#endif
// These are CUDA variants of various OSL options structs. Their layouts and
// default values are identical to the host versions, but they might differ in
// how they are constructed. They are duplicated here as a convenience and to
@@ -114,6 +98,7 @@ struct ShaderGlobals {
float3 dPdtime;
float3 Ps, dPsdx, dPsdy;
void* renderstate;
void* shadingStateUniform;
void* tracedata;
void* objdata;
void* context;
@@ -159,7 +144,7 @@ enum ClosureIDs {
HOLDOUT_ID,
};
#if (OPTIX_VERSION >= 70000)
// ========================================
//
// Some helper vector functions
@@ -208,6 +193,5 @@ normalize(const float3& v)
}
//
// ========================================
#endif //#if (OPTIX_VERSION >= 70000)
} // anonymous namespace
+3 -123
View File
@@ -5,128 +5,10 @@
#include <optix.h>
#if (OPTIX_VERSION < 70000)
# include <optixu/optixu_aabb_namespace.h>
# include <optixu/optixu_math_namespace.h>
# include <optixu/optixu_vector_types.h>
# include <OSL/dual.h>
# include <OSL/dual_vec.h>
# include <OSL/oslconfig.h>
# include <OSL/shaderglobals.h>
# include <OpenImageIO/fmath.h>
using namespace optix;
using OSL::Dual2;
using OSL::Vec3;
rtDeclareVariable(float4, sphere, , );
rtDeclareVariable(float, r2, , );
rtDeclareVariable(float, a, , );
rtDeclareVariable(float3, texcoord, attribute texcoord, );
rtDeclareVariable(float3, geometric_normal, attribute geometric_normal, );
rtDeclareVariable(float3, shading_normal, attribute shading_normal, );
rtDeclareVariable(float, surface_area, attribute surface_area, );
rtDeclareVariable(float3, dPdu, attribute dPdu, );
rtDeclareVariable(float3, dPdv, attribute dPdv, );
rtDeclareVariable(optix::Ray, ray, rtCurrentRay, );
static __device__ __inline__ void
calc_uv()
{
Dual2<Vec3> n(Vec3(shading_normal.x, shading_normal.y, shading_normal.z));
Dual2<float> nx(n.val().x, n.dx().x, n.dy().x);
Dual2<float> ny(n.val().y, n.dx().y, n.dy().y);
Dual2<float> nz(n.val().z, n.dx().z, n.dy().z);
Dual2<float> u = (fast_atan2(nx, nz) + Dual2<float>(M_PI)) * 0.5f
* float(M_1_PI);
Dual2<float> v = fast_acos(ny) * float(M_1_PI);
float xz2 = nx.val() * nx.val() + nz.val() * nz.val();
if (xz2 > 0.0f) {
const float PI = float(M_PI);
const float TWOPI = float(2 * M_PI);
float xz = sqrtf(xz2);
float inv = 1.0f / xz;
dPdu.x = -TWOPI * nx.val();
dPdu.y = TWOPI * nz.val();
dPdu.z = 0.0f;
dPdv.x = -PI * nz.val() * inv * ny.val();
dPdv.y = -PI * nx.val() * inv * ny.val();
dPdv.z = PI * xz;
} else {
// pick arbitrary axes for poles to avoid division by 0
if (ny.val() > 0.0f) {
dPdu = make_float3(0.0f, 0.0f, 1.0f);
dPdv = make_float3(1.0f, 0.0f, 0.0f);
} else {
dPdu = make_float3(0.0f, 0.0f, 1.0f);
dPdv = make_float3(-1.0f, 0.0f, 0.0f);
}
}
texcoord = make_float3(u.val(), v.val(), 0.0f);
}
// Intersection adapted from testrender/raytracer.h
RT_PROGRAM void
intersect(void)
{
float3 c = make_float3(sphere);
float3 oc = c - ray.origin;
float b = dot(oc, ray.direction);
float det = b * b - dot(oc, oc) + r2;
if (det >= 0.0f) {
det = sqrtf(det);
float x = b - det;
float y = b + det;
// NB: this does not included the 'self' check from
// the testrender sphere intersection
float t = (x > 0) ? x : ((y > 0) ? y : 0);
if (rtPotentialIntersection(t)) {
float3 P = ray.origin + ray.direction * t;
float3 N = normalize(P - c);
shading_normal = geometric_normal = N;
surface_area = a;
// Calculate the texture coordinates and derivatives
calc_uv();
rtReportIntersection(0);
}
}
}
RT_PROGRAM void
bounds(int, float result[6])
{
const float3 center = make_float3(sphere);
const float3 radius = make_float3(sphere.w);
optix::Aabb* aabb = reinterpret_cast<optix::Aabb*>(result);
if (radius.x > 0.0f && !isinf(radius.x)) {
aabb->m_min = center - radius;
aabb->m_max = center + radius;
} else {
aabb->invalidate();
}
}
#else //#if (OPTIX_VERSION < 70000)
# include "rend_lib.h"
# include "render_params.h"
# include "wrapper.h"
#include "rend_lib.h"
#include "render_params.h"
#include "wrapper.h"
static __device__ __inline__ void
@@ -212,5 +94,3 @@ __intersection__sphere()
optixReportIntersection(t, RAYTRACER_HIT_SPHERE);
}
}
#endif //#if (OPTIX_VERSION < 70000)
-7
View File
@@ -7,13 +7,6 @@
#include <optix.h>
#if (OPTIX_VERSION < 70000)
# include <optixu/optixu_math_namespace.h>
# include <optixu/optixu_vector_types.h>
typedef optix::float3 float3;
typedef optix::uchar4 uchar4;
#endif
#include <stdint.h>
+3 -196
View File
@@ -5,12 +5,8 @@
#include <optix.h>
#if (OPTIX_VERSION < 70000)
# include <optixu/optixu_math_namespace.h>
#else
# include <cuda_runtime.h>
# include <optix.h>
#endif
#include <cuda_runtime.h>
#include <optix.h>
#include <OSL/device_string.h>
#include <OSL/oslclosure.h>
@@ -18,194 +14,7 @@
#include "rend_lib.h"
#include "util.h"
#if (OPTIX_VERSION < 70000)
// Ray payload
rtDeclareVariable(PRD_radiance, prd_radiance, rtPayload, );
// ray/hit variables
rtDeclareVariable(float3, shading_normal, attribute shading_normal, );
rtDeclareVariable(float3, geometric_normal, attribute geometric_normal, );
rtDeclareVariable(float3, texcoord, attribute texcoord, );
rtDeclareVariable(float, surface_area, attribute surface_area, );
rtDeclareVariable(float3, dPdu, attribute dPdu, );
rtDeclareVariable(float3, dPdv, attribute dPdv, );
rtDeclareVariable(int, obj_id, attribute obj_id, );
rtDeclareVariable(int, lgt_idx, attribute lgt_idx, );
// ray/hit variables
rtDeclareVariable(uint2, launch_index, rtLaunchIndex, );
rtDeclareVariable(uint2, launch_dim, rtLaunchDim, );
rtDeclareVariable(optix::Ray, ray, rtCurrentRay, );
rtDeclareVariable(float, t_hit, rtIntersectionDistance, );
// Buffers
rtBuffer<float3, 2> output_buffer;
// Function pointers for the OSL shader
rtDeclareVariable(rtCallableProgramId<void(void*, void*)>, osl_init_func, , );
rtDeclareVariable(rtCallableProgramId<void(void*, void*)>, osl_group_func, , );
RT_PROGRAM void
any_hit_shadow()
{
rtTerminateRay();
}
static __device__ void
globals_from_hit(ShaderGlobals& sg)
{
// Setup the ShaderGlobals
sg.I = ray.direction;
sg.N = normalize(rtTransformNormal(RT_OBJECT_TO_WORLD, shading_normal));
sg.Ng = normalize(rtTransformNormal(RT_OBJECT_TO_WORLD, geometric_normal));
sg.P = ray.origin + t_hit * ray.direction;
sg.dPdu = dPdu;
sg.u = texcoord.x;
sg.v = texcoord.y;
sg.Ci = NULL;
sg.surfacearea = surface_area;
sg.backfacing = (dot(sg.N, sg.I) > 0.0f);
if (sg.backfacing) {
sg.N = -sg.N;
sg.Ng = -sg.Ng;
}
// NB: These variables are not used in the current iteration of the sample
sg.raytype = CAMERA;
sg.flipHandedness = 0;
}
static __device__ float3
process_closure(const OSL::ClosureColor* closure_tree)
{
OSL::Color3 result = OSL::Color3(0.0f);
if (!closure_tree) {
return make_float3(result.x, result.y, result.z);
}
// The depth of the closure tree must not exceed the stack size.
// A stack size of 8 is probably quite generous for relatively
// balanced trees.
const int STACK_SIZE = 8;
// Non-recursive traversal stack
int stack_idx = 0;
const OSL::ClosureColor* ptr_stack[STACK_SIZE];
OSL::Color3 weight_stack[STACK_SIZE];
// Shading accumulator
OSL::Color3 weight = OSL::Color3(1.0f);
const void* cur = closure_tree;
while (cur) {
switch (((OSL::ClosureColor*)cur)->id) {
case OSL::ClosureColor::ADD: {
ptr_stack[stack_idx] = ((OSL::ClosureAdd*)cur)->closureB;
weight_stack[stack_idx++] = weight;
cur = ((OSL::ClosureAdd*)cur)->closureA;
break;
}
case OSL::ClosureColor::MUL: {
weight *= ((OSL::ClosureMul*)cur)->weight;
cur = ((OSL::ClosureMul*)cur)->closure;
break;
}
case EMISSION_ID: {
cur = NULL;
break;
}
case DIFFUSE_ID:
case OREN_NAYAR_ID:
case PHONG_ID:
case WARD_ID:
case REFLECTION_ID:
case REFRACTION_ID:
case FRESNEL_REFLECTION_ID: {
result += ((OSL::ClosureComponent*)cur)->w * weight;
cur = NULL;
break;
}
case MICROFACET_ID: {
const char* mem = (const char*)((OSL::ClosureComponent*)cur)->data();
const char* dist_str = *(const char**)&mem[0];
# if 0
if (launch_index.x == launch_dim.x / 2 && launch_index.y == launch_dim.y / 2)
printf ("microfacet, dist: %s\n", HDSTR(dist_str).c_str());
# endif
if (HDSTR(dist_str) == OSL::DeviceStrings::default_)
return make_float3(0.0f, 1.0f, 1.0f);
return make_float3(1.0f, 0.0f, 1.0f);
}
default: cur = NULL; break;
}
if (cur == NULL && stack_idx > 0) {
cur = ptr_stack[--stack_idx];
weight = weight_stack[stack_idx];
}
}
return make_float3(result.x, result.y, result.z);
}
RT_PROGRAM void
closest_hit_osl()
{
// TODO: Fixed-sized allocations can easily be exceeded by arbitrary shader
// networks, so there should be (at least) some mechanism to issue a
// warning or error if the closure or param storage can possibly be
// exceeded.
alignas(8) char closure_pool[256];
alignas(8) char params[256];
ShaderGlobals sg;
globals_from_hit(sg);
// Pack the "closure pool" into one of the ShaderGlobals pointers
*(int*)&closure_pool[0] = 0;
sg.renderstate = &closure_pool[0];
// Create some run-time options structs. The OSL shader fills in the structs
// as it executes, based on the options specified in the shader source.
NoiseOptCUDA noiseopt;
TextureOptCUDA textureopt;
TraceOptCUDA traceopt;
// Pack the pointers to the options structs in a faux "context",
// which is a rough stand-in for the host ShadingContext.
ShadingContextCUDA shading_context = { &noiseopt, &textureopt, &traceopt };
sg.context = &shading_context;
// Run the OSL group and init functions
osl_init_func(&sg, params);
osl_group_func(&sg, params);
prd_radiance.result = process_closure((OSL::ClosureColor*)sg.Ci);
}
#else //#if (OPTIX_VERSION < 70000)
# include "../render_params.h"
#include "../render_params.h"
extern "C" {
@@ -392,5 +201,3 @@ __closesthit__closest_hit_osl()
int pixel = launch_index.y * launch_dims.x + launch_index.x;
output_buffer[pixel] = make_float3(result.x, result.y, result.z);
}
#endif //#if (OPTIX_VERSION < 70000)
-174
View File
@@ -1,174 +0,0 @@
// Copyright Contributors to the Open Shading Language project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
#ifdef OSL_USE_OPTIX
# include <optix.h>
#endif
#if OPTIX_VERSION < 70000
# include "optix_stringtable.h"
using OIIO::ustring;
OSL_NAMESPACE_ENTER
OptiXStringTable::OptiXStringTable(optix::Context ctx)
: m_ptr(nullptr), m_size(1 << 16), m_offset(0), m_optix_ctx(ctx)
{
}
OptiXStringTable::~OptiXStringTable()
{
freetable();
}
void
OptiXStringTable::freetable()
{
if (m_ptr)
OSL::cudaFree(m_ptr);
m_ptr = nullptr;
}
void
OptiXStringTable::init(optix::Context ctx OSL_MAYBE_UNUSED)
{
# ifdef OSL_USE_OPTIX
OSL_ASSERT(!m_ptr && "StringTable should only be initialized once");
m_optix_ctx = ctx;
OSL_ASSERT((m_optix_ctx->getEnabledDeviceCount() == 1)
&& "Only one CUDA device is currently supported");
OSL::cudaMalloc(reinterpret_cast<void**>(&m_ptr), (m_size));
// Add the statically-declared strings to the table, and create OptiX
// variables for them in the OSL::DeviceStrings namespace.
//
// The names of the variables created here must match the extern variables
// declared in OSL/device_string.h for OptiX's variable scoping mechanisms
// to work.
# define STRDECL(str, var_name) \
addString(ustring(str), ustring(OSL_NAMESPACE_STRING \
"::DeviceStrings::" #var_name));
# include <OSL/strdecls.h>
# undef STRDECL
# endif
}
uint64_t
OptiXStringTable::addString(ustring str OSL_MAYBE_UNUSED,
ustring var_name OSL_MAYBE_UNUSED)
{
# ifdef OSL_USE_OPTIX
OSL_ASSERT(m_ptr && "StringTable has not been initialized");
// The strings are laid out in the table as a struct:
//
// struct TableRep {
// size_t len;
// size_t hash;
// char str[len+1];
// };
// Compute the size of the entry before adding it to the table
size_t size = sizeof(size_t) + sizeof(size_t) + str.size() + 1;
if (((m_offset + size) >= m_size)) {
reallocTable();
}
// It should be hard to trigger this assert, unless the table size is
// very small and the string is very large.
OSL_ASSERT(m_offset + size <= m_size && "String table allocation error");
int offset = getOffset(str.string());
if (offset < 0) {
// Place the hash and length of the string before the characters
size_t hash = str.hash();
cudaMemcpy(m_ptr + m_offset, (void*)&hash, sizeof(size_t),
cudaMemcpyHostToDevice);
m_offset += sizeof(size_t);
size_t len = str.length();
cudaMemcpy(m_ptr + m_offset, (void*)&len, sizeof(size_t),
cudaMemcpyHostToDevice);
m_offset += sizeof(size_t);
offset = m_offset;
m_offset_map[str] = offset;
m_name_map[str] = var_name;
// Copy the raw characters to the table
cudaMemcpy(m_ptr + m_offset, str.c_str(), str.size() + 1,
cudaMemcpyHostToDevice);
m_offset += str.size() + 1;
// Align the offset for the next entry to 8-byte boundaries
m_offset = (m_offset + 0x7u) & ~0x7u;
} else if (!var_name.empty()) {
// update what str points to
m_name_map[str] = var_name;
}
uint64_t addr = reinterpret_cast<uint64_t>(m_ptr + offset);
// Optionally create an OptiX variable for the string. It's not necessary to
// create a variable for strings that do not appear by name in compiled code
// (in either the OSL library functions or in the renderer).
if (!var_name.empty())
m_optix_ctx[var_name.string()]->setUserData(8, &addr);
return addr;
# else
return 0;
# endif
}
int
OptiXStringTable::getOffset(const std::string& str) const
{
auto it = m_offset_map.find(ustring(str));
return (it != m_offset_map.end()) ? it->second : -1;
}
void
OptiXStringTable::reallocTable()
{
# ifdef OSL_USE_OPTIX
OSL_ASSERT((m_optix_ctx->getEnabledDeviceCount() == 1)
&& "Only one CUDA device is currently supported");
m_size *= 2;
OSL::cudaFree(m_ptr);
OSL::cudaMalloc(reinterpret_cast<void**>(&m_ptr), (m_size));
// The offsets need to be recomputed
m_offset = 0;
m_offset_map.clear();
// Add the string collection to the newly-allocated memory
for (auto& entry : m_name_map) {
addString(entry.first, entry.second);
}
# endif
}
OSL_NAMESPACE_EXIT
#endif
-89
View File
@@ -1,89 +0,0 @@
// Copyright Contributors to the Open Shading Language project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
#pragma once
#include <map>
#include <unordered_map>
#include <utility>
#include "optix_compat.h"
#include <OSL/oslexec.h>
#include <OpenImageIO/ustring.h>
OSL_NAMESPACE_ENTER
typedef std::unordered_map<OIIO::ustring, int64_t, OIIO::ustringHash>
StringTableMap;
// The OptiXStringTable manages a block of CUDA device memory designated
// to hold all of the string constants that a shader might access during
// execution.
//
// Any string that needs to be visible on the device needs to be added using the
// addString function.
class OptiXStringTable {
public:
OptiXStringTable(optix::Context ctx = nullptr);
~OptiXStringTable();
// Allocate CUDA device memory for the raw string table and add the
// "standard" strings declared in strdecls.h.
void init(optix::Context ctx);
const StringTableMap& contents() const { return m_addr_table; }
// Add a string to the table (if it hasn't already been added), and return
// its address in device memory. Also, create an OptiX variable to hold the
// address of each string variable, through which the strings will be
// accessed during execution.
//
// Creating variables for the strings -- rather than using the string
// addresses directly -- is necessary for keeping the generated PTX stable
// from run to run, regardless of the order in which strings are added to
// the table. This helps make the PTX more cacheable.
//
// This function should not be called when a kernel that could potentially
// access the table is running, since it has the potential to invalidate
// pointers if reallocation is triggered.
uint64_t addString(OIIO::ustring str, OIIO::ustring var_name);
void freetable();
private:
// If a string has already been added to the table, return its offset in the
// char array; otherwise, return -1.
int getOffset(const std::string& str) const;
// Free the previous allocation, allocate a new block of GPU memory of twice
// the size, copy the string contents into the new allocation, and update the
// OptiX variables that hold the string addresses.
void reallocTable();
// A byte array containing the concatenation of all strings added to the
// table, allocated in CUDA device memory. The hash value and length of each
// string are stored in the 16 bytes preceding the raw characters.
char* m_ptr;
// The size of the table in bytes.
size_t m_size;
// The offset in the char array at which the next string will be added.
int m_offset;
// A handle on the OptiX Context to use when creating global variables.
optix::Context m_optix_ctx;
// The memory offsets associated with each canonical string.
std::map<OIIO::ustring, int> m_offset_map;
// The variable names associated with each canonical string.
std::map<OIIO::ustring, OIIO::ustring> m_name_map;
StringTableMap m_addr_table;
};
OSL_NAMESPACE_EXIT
+110 -524
View File
@@ -13,14 +13,11 @@
#include "render_params.h"
#ifdef OSL_USE_OPTIX
# if (OPTIX_VERSION >= 70000)
# include <cuda.h>
# include <optix_function_table_definition.h>
# include <optix_stack_size.h>
# include <optix_stubs.h>
# endif
#endif
#include <cuda.h>
#include <optix_function_table_definition.h>
#include <optix_stack_size.h>
#include <optix_stubs.h>
// The pre-compiled renderer support library LLVM bitcode is embedded
// into the executable and made available through these variables.
@@ -30,33 +27,41 @@ extern unsigned char rend_llvm_compiled_ops_block[];
OSL_NAMESPACE_ENTER
#if (OPTIX_VERSION >= 70000)
# define CUDA_CHECK(call) \
{ \
cudaError_t error = call; \
if (error != cudaSuccess) { \
std::stringstream ss; \
ss << "CUDA call (" << #call << " ) failed with error: '" \
<< cudaGetErrorString(error) << "' (" __FILE__ << ":" \
<< __LINE__ << ")\n"; \
print(stderr, "[CUDA ERROR] {}", ss.str()); \
} \
}
#define CUDA_CHECK(call) \
{ \
cudaError_t res = call; \
if (res != cudaSuccess) { \
print(stderr, \
"[CUDA ERROR] Cuda call '{}' failed with error:" \
" {} ({}:{})\n", \
#call, cudaGetErrorString(res), __FILE__, __LINE__); \
} \
}
# define OPTIX_CHECK(call) \
{ \
OptixResult res = call; \
if (res != OPTIX_SUCCESS) { \
std::stringstream ss; \
ss << "Optix call '" << #call \
<< "' failed with error: " << optixGetErrorName(res) \
<< " (" __FILE__ ":" << __LINE__ << ")\n"; \
print(stderr, "[OPTIX ERROR] {}", ss.str()); \
exit(1); \
} \
}
#endif
#define OPTIX_CHECK(call) \
{ \
OptixResult res = call; \
if (res != OPTIX_SUCCESS) { \
print(stderr, \
"[OPTIX ERROR] OptiX call '{}' failed with error:" \
" {} ({}:{})\n", \
#call, optixGetErrorName(res), __FILE__, __LINE__); \
exit(1); \
} \
}
#define OPTIX_CHECK_MSG(call, msg) \
{ \
OptixResult res = call; \
if (res != OPTIX_SUCCESS) { \
print(stderr, \
"[OPTIX ERROR] OptiX call '{}' failed with error:" \
" {} ({}:{})\nMessage: {}\n", \
#call, optixGetErrorName(res), __FILE__, __LINE__, msg); \
exit(1); \
} \
}
#define CUDA_SYNC_CHECK() \
{ \
@@ -69,18 +74,17 @@ OSL_NAMESPACE_ENTER
} \
}
#if defined(OSL_USE_OPTIX) && OPTIX_VERSION >= 70000
static void
context_log_cb(unsigned int level, const char* tag, const char* message,
void* /*cbdata */)
{
// std::cerr << "[ ** LOGCALLBACK** " << std::setw( 2 ) << level << "][" << std::setw( 12 ) << tag << "]: " << message << "\n";
}
#endif
OptixRaytracer::OptixRaytracer()
{
#if defined(OSL_USE_OPTIX) && OPTIX_VERSION >= 70000
// Initialize CUDA
cudaFree(0);
@@ -95,36 +99,22 @@ OptixRaytracer::OptixRaytracer()
CUDA_CHECK(cudaSetDevice(0));
CUDA_CHECK(cudaStreamCreate(&m_cuda_stream));
# define STRDECL(str, var_name) \
register_string(str, \
OSL_NAMESPACE_STRING "::DeviceStrings::" #var_name);
# include <OSL/strdecls.h>
# undef STRDECL
#endif
}
OptixRaytracer::~OptixRaytracer()
{
#ifdef OSL_USE_OPTIX
# if (OPTIX_VERSION < 70000)
m_str_table.freetable();
if (m_optix_ctx)
m_optix_ctx->destroy();
# else
if (m_optix_ctx)
OPTIX_CHECK(optixDeviceContextDestroy(m_optix_ctx));
# endif
#endif
}
uint64_t
OptixRaytracer::register_global(const std::string& str, uint64_t value)
{
auto it = m_globals_map.find(ustring(str));
if (it != m_globals_map.end()) {
return it->second;
}
@@ -132,6 +122,8 @@ OptixRaytracer::register_global(const std::string& str, uint64_t value)
return value;
}
bool
OptixRaytracer::fetch_global(const std::string& str, uint64_t* value)
{
@@ -144,10 +136,11 @@ OptixRaytracer::fetch_global(const std::string& str, uint64_t* value)
return false;
}
std::string
OptixRaytracer::load_ptx_file(string_view filename)
{
#ifdef OSL_USE_OPTIX
std::vector<std::string> paths
= { OIIO::Filesystem::parent_path(OIIO::Sysutil::this_program_path()),
PTX_PATH };
@@ -158,7 +151,6 @@ OptixRaytracer::load_ptx_file(string_view filename)
if (OIIO::Filesystem::read_text_file(filepath, ptx_string))
return ptx_string;
}
#endif
errhandler().severefmt("Unable to load {}", filename);
return {};
}
@@ -169,85 +161,6 @@ bool
OptixRaytracer::init_optix_context(int xres OSL_MAYBE_UNUSED,
int yres OSL_MAYBE_UNUSED)
{
#ifdef OSL_USE_OPTIX
# if (OPTIX_VERSION < 70000)
// NB: renderers using OptiX7+ are expected to link it rend_lib.cu manually
// to avoid duplicate 'rend_lib' symbols in each shader group.
shadingsys->attribute("lib_bitcode",
{ OSL::TypeDesc::UINT8, rend_llvm_compiled_ops_size },
rend_llvm_compiled_ops_block);
// Set up the OptiX context
m_optix_ctx = optix::Context::create();
// Set up the string table. This allocates a block of CUDA device memory to
// hold all of the static strings used by the OSL shaders. The strings can
// be accessed via OptiX variables that hold pointers to the table entries.
m_str_table.init(m_optix_ctx);
if (m_optix_ctx->getEnabledDeviceCount() != 1)
errhandler().warningfmt("Only one CUDA device is currently supported");
m_optix_ctx->setRayTypeCount(2);
m_optix_ctx->setEntryPointCount(1);
m_optix_ctx->setStackSize(2048);
m_optix_ctx->setPrintEnabled(true);
// Load the renderer CUDA source and generate PTX for it
std::string progName = "optix_raytracer.ptx";
std::string renderer_ptx = load_ptx_file(progName);
if (renderer_ptx.empty()) {
errhandler().severefmt("Could not find PTX for the raygen program");
return false;
}
// Create the OptiX programs and set them on the optix::Context
m_program = m_optix_ctx->createProgramFromPTXString(renderer_ptx, "raygen");
m_optix_ctx->setRayGenerationProgram(0, m_program);
if (scene.num_prims()) {
m_optix_ctx["radiance_ray_type"]->setUint(0u);
m_optix_ctx["shadow_ray_type"]->setUint(1u);
m_optix_ctx["bg_color"]->setFloat(0.0f, 0.0f, 0.0f);
m_optix_ctx["bad_color"]->setFloat(1.0f, 0.0f, 1.0f);
// Create the OptiX programs and set them on the optix::Context
if (renderer_ptx.size()) {
m_optix_ctx->setMissProgram(
0,
m_optix_ctx->createProgramFromPTXString(renderer_ptx, "miss"));
m_optix_ctx->setExceptionProgram(
0, m_optix_ctx->createProgramFromPTXString(renderer_ptx,
"exception"));
}
// Load the PTX for the wrapper program. It will be used to
// create OptiX Materials from the OSL ShaderGroups
m_materials_ptx = load_ptx_file("wrapper.ptx");
if (m_materials_ptx.empty())
return false;
// Load the PTX for the primitives
std::string sphere_ptx = load_ptx_file("sphere.ptx");
std::string quad_ptx = load_ptx_file("quad.ptx");
if (sphere_ptx.empty() || quad_ptx.empty())
return false;
// Create the sphere and quad intersection programs.
sphere_bounds = m_optix_ctx->createProgramFromPTXString(sphere_ptx,
"bounds");
quad_bounds = m_optix_ctx->createProgramFromPTXString(quad_ptx,
"bounds");
sphere_intersect = m_optix_ctx->createProgramFromPTXString(sphere_ptx,
"intersect");
quad_intersect = m_optix_ctx->createProgramFromPTXString(quad_ptx,
"intersect");
}
# endif //#if (OPTIX_VERSION < 70000)
#endif
return true;
}
@@ -256,89 +169,11 @@ OptixRaytracer::init_optix_context(int xres OSL_MAYBE_UNUSED,
bool
OptixRaytracer::synch_attributes()
{
#ifdef OSL_USE_OPTIX
# if (OPTIX_VERSION < 70000)
// FIXME -- this is for testing only
// Make some device strings to test userdata parameters
uint64_t addr1 = register_string("ud_str_1", "");
uint64_t addr2 = register_string("userdata string", "");
m_optix_ctx["test_str_1"]->setUserData(sizeof(char*), &addr1);
m_optix_ctx["test_str_2"]->setUserData(sizeof(char*), &addr2);
{
const char* name = OSL_NAMESPACE_STRING "::pvt::s_color_system";
char* colorSys = nullptr;
long long cpuDataSizes[2] = { 0, 0 };
if (!shadingsys->getattribute("colorsystem", TypeDesc::PTR,
(void*)&colorSys)
|| !shadingsys->getattribute("colorsystem:sizes",
TypeDesc(TypeDesc::LONGLONG, 2),
(void*)&cpuDataSizes)
|| !colorSys || !cpuDataSizes[0]) {
errhandler().errorfmt("No colorsystem available.");
return false;
}
auto cpuDataSize = cpuDataSizes[0];
auto numStrings = cpuDataSizes[1];
// Get the size data-size, minus the ustring size
const size_t podDataSize = cpuDataSize
- sizeof(StringParam) * numStrings;
optix::Buffer buffer = m_optix_ctx->createBuffer(RT_BUFFER_INPUT,
RT_FORMAT_USER);
if (!buffer) {
errhandler().errorfmt("Could not create buffer for '{}'.", name);
return false;
}
// set the element size to char
buffer->setElementSize(sizeof(char));
// and number of elements to the actual size needed.
buffer->setSize(podDataSize + sizeof(DeviceString) * numStrings);
// copy the base data
char* gpuData = (char*)buffer->map();
if (!gpuData) {
errhandler().errorfmt("Could not map buffer for '{}' (size: {}).",
name,
podDataSize
+ sizeof(DeviceString) * numStrings);
return false;
}
::memcpy(gpuData, colorSys, podDataSize);
// then copy the device string to the end, first strings starting at dataPtr - (numStrings)
// FIXME -- Should probably handle alignment better.
const ustring* cpuString
= (const ustring*)(colorSys
+ (cpuDataSize
- sizeof(StringParam) * numStrings));
char* gpuStrings = gpuData + podDataSize;
for (const ustring* end = cpuString + numStrings; cpuString < end;
++cpuString) {
// convert the ustring to a device string
uint64_t devStr = register_string(cpuString->string(), "");
::memcpy(gpuStrings, &devStr, sizeof(devStr));
gpuStrings += sizeof(DeviceString);
}
buffer->unmap();
m_optix_ctx[name]->setBuffer(buffer);
}
# else // #if (OPTIX_VERSION < 70000)
// FIXME -- this is for testing only
// Make some device strings to test userdata parameters
ustring userdata_str1("ud_str_1");
ustring userdata_str2("userdata string");
register_string(userdata_str1.string(), "");
register_string(userdata_str2.string(), "");
// Store the user-data
test_str_1 = userdata_str1.hash();
test_str_2 = userdata_str2.hash();
@@ -383,18 +218,17 @@ OptixRaytracer::synch_attributes()
for (const ustring* end = cpuString + numStrings; cpuString < end;
++cpuString) {
// convert the ustring to a device string
uint64_t devStr = register_string(cpuString->string(), "");
uint64_t devStr = cpuString->hash();
CUDA_CHECK(cudaMemcpy(reinterpret_cast<void*>(gpuStrings), &devStr,
sizeof(devStr), cudaMemcpyHostToDevice));
gpuStrings += sizeof(DeviceString);
}
}
# endif // #if (OPTIX_VERSION < 70000)
#endif
return true;
}
#if (OPTIX_VERSION >= 70000)
bool
OptixRaytracer::load_optix_module(
const char* filename,
@@ -412,16 +246,18 @@ OptixRaytracer::load_optix_module(
}
size_t sizeof_msg_log = sizeof(msg_log);
OPTIX_CHECK(optixModuleCreateFromPTX(m_optix_ctx, module_compile_options,
pipeline_compile_options,
program_ptx.c_str(),
program_ptx.size(), msg_log,
&sizeof_msg_log, program_module));
//if (sizeof_msg_log > 1)
// printf ("Creating Module from PTX-file %s:\n%s\n", filename, msg_log);
OPTIX_CHECK_MSG(optixModuleCreateFromPTX(m_optix_ctx,
module_compile_options,
pipeline_compile_options,
program_ptx.c_str(),
program_ptx.size(), msg_log,
&sizeof_msg_log, program_module),
fmtformat("Creating Module from PTX-file {}", msg_log));
return true;
}
bool
OptixRaytracer::create_optix_pg(const OptixProgramGroupDesc* pg_desc,
const int num_pg,
@@ -430,103 +266,19 @@ OptixRaytracer::create_optix_pg(const OptixProgramGroupDesc* pg_desc,
{
char msg_log[8192];
size_t sizeof_msg_log = sizeof(msg_log);
OPTIX_CHECK(optixProgramGroupCreate(m_optix_ctx, pg_desc, num_pg,
program_options, msg_log,
&sizeof_msg_log, pg));
//if (sizeof_msg_log > 1)
// printf ("Creating program group:\n%s\n", msg_log);
OPTIX_CHECK_MSG(optixProgramGroupCreate(m_optix_ctx, pg_desc, num_pg,
program_options, msg_log,
&sizeof_msg_log, pg),
fmtformat("Creating program group: {}", msg_log));
return true;
}
#endif
bool
OptixRaytracer::make_optix_materials()
{
#ifdef OSL_USE_OPTIX
# if (OPTIX_VERSION < 70000)
optix::Program closest_hit, any_hit;
if (scene.num_prims()) {
closest_hit = m_optix_ctx->createProgramFromPTXString(m_materials_ptx,
"closest_hit_osl");
any_hit = m_optix_ctx->createProgramFromPTXString(m_materials_ptx,
"any_hit_shadow");
}
// Stand-in: names of shader outputs to preserve
// FIXME
std::vector<const char*> outputs { "Cout" };
// Optimize each ShaderGroup in the scene, and use the resulting
// PTX to create OptiX Programs which can be called by the closest
// hit program in the wrapper to execute the compiled OSL shader.
int mtl_id = 0;
for (const auto& groupref : shaders()) {
shadingsys->attribute(groupref.get(), "renderer_outputs",
TypeDesc(TypeDesc::STRING, outputs.size()),
outputs.data());
shadingsys->optimize_group(groupref.get(), nullptr);
if (!scene.num_prims()) {
if (!shadingsys->find_symbol(*groupref.get(), ustring(outputs[0]))) {
errhandler().warningfmt(
"Requested output '{}', which wasn't found", outputs[0]);
}
}
std::string group_name, init_name, entry_name;
shadingsys->getattribute(groupref.get(), "groupname", group_name);
shadingsys->getattribute(groupref.get(), "group_init_name", init_name);
shadingsys->getattribute(groupref.get(), "group_entry_name",
entry_name);
// Retrieve the compiled ShaderGroup PTX
std::string osl_ptx;
shadingsys->getattribute(groupref.get(), "ptx_compiled_version",
OSL::TypeDesc::PTR, &osl_ptx);
if (osl_ptx.empty()) {
errhandler().errorfmt("Failed to generate PTX for ShaderGroup {}",
group_name);
return false;
}
if (options.get_int("saveptx")) {
std::string filename = fmtformat("{}_{}.ptx", group_name, mtl_id++);
OIIO::Filesystem::write_text_file(filename, osl_ptx);
}
// Create Programs from the init and group_entry functions,
// and set the OSL functions as Callable Programs so that they
// can be executed by the closest hit program in the wrapper
optix::Program osl_init
= m_optix_ctx->createProgramFromPTXString(osl_ptx, init_name);
optix::Program osl_group
= m_optix_ctx->createProgramFromPTXString(osl_ptx, entry_name);
if (scene.num_prims()) {
// Create a new Material using the wrapper PTX
optix::Material mtl = m_optix_ctx->createMaterial();
mtl->setClosestHitProgram(0, closest_hit);
mtl->setAnyHitProgram(1, any_hit);
// Set the OSL functions as Callable Programs so that they can be
// executed by the closest hit program in the wrapper
mtl["osl_init_func"]->setProgramId(osl_init);
mtl["osl_group_func"]->setProgramId(osl_group);
scene.optix_mtls.push_back(mtl);
} else {
// Grid shading
m_program["osl_init_func"]->setProgramId(osl_init);
m_program["osl_group_func"]->setProgramId(osl_group);
}
}
if (!synch_attributes())
return false;
# else //#if (OPTIX_VERSION < 70000)
// Stand-in: names of shader outputs to preserve
std::vector<const char*> outputs { "Cout" };
@@ -541,12 +293,12 @@ OptixRaytracer::make_optix_materials()
module_compile_options.maxRegisterCount
= OPTIX_COMPILE_DEFAULT_MAX_REGISTER_COUNT;
module_compile_options.optLevel = OPTIX_COMPILE_OPTIMIZATION_DEFAULT;
# if OPTIX_VERSION >= 70400
module_compile_options.optLevel = OPTIX_COMPILE_OPTIMIZATION_DEFAULT;
#if OPTIX_VERSION >= 70400
module_compile_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_MINIMAL;
# else
#else
module_compile_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_LINEINFO;
# endif
#endif
OptixPipelineCompileOptions pipeline_compile_options = {};
@@ -606,14 +358,13 @@ OptixRaytracer::make_optix_materials()
OptixProgramGroup setglobals_raygen_group;
sizeof_msg_log = sizeof(msg_log);
OPTIX_CHECK(optixProgramGroupCreate(m_optix_ctx, &setglobals_raygen_desc,
1, // number of program groups
&program_options, // program options
msg_log, &sizeof_msg_log,
&setglobals_raygen_group));
//if (sizeof_msg_log > 1)
// printf ("Creating set-globals 'ray-gen' program group:\n%s\n", msg_log);
OPTIX_CHECK_MSG(
optixProgramGroupCreate(m_optix_ctx, &setglobals_raygen_desc,
1, // number of program groups
&program_options, // program options
msg_log, &sizeof_msg_log,
&setglobals_raygen_group),
fmtformat("Creating set-globals 'ray-gen' program group: {}", msg_log));
// Miss group
OptixProgramGroupDesc miss_desc = {};
@@ -741,13 +492,13 @@ OptixRaytracer::make_optix_materials()
// and set the OSL functions as Callable Programs so that they
// can be executed by the closest hit program in the wrapper
sizeof_msg_log = sizeof(msg_log);
OPTIX_CHECK(
OPTIX_CHECK_MSG(
optixModuleCreateFromPTX(m_optix_ctx, &module_compile_options,
&pipeline_compile_options, osl_ptx.c_str(),
osl_ptx.size(), msg_log, &sizeof_msg_log,
&optix_module));
//if (sizeof_msg_log > 1)
// printf ("Creating module for PTX group '%s':\n%s\n", group_name.c_str(), msg_log);
&optix_module),
fmtformat("Creating module for PTX group {}: {}", group_name,
msg_log));
modules.push_back(optix_module);
// Create 2x program groups (for direct callables)
@@ -765,21 +516,20 @@ OptixRaytracer::make_optix_materials()
shader_groups.resize(shader_groups.size() + 2);
sizeof_msg_log = sizeof(msg_log);
OPTIX_CHECK(
OPTIX_CHECK_MSG(
optixProgramGroupCreate(m_optix_ctx, &pgDesc[0], 2,
&program_options, msg_log, &sizeof_msg_log,
&shader_groups[shader_groups.size() - 2]));
//if (sizeof_msg_log > 1)
// printf ("Creating 'shader' group for group '%s':\n%s\n", group_name.c_str(), msg_log);
&shader_groups[shader_groups.size() - 2]),
fmtformat("Creating 'shader' group for group {}: {}", group_name,
msg_log));
}
OptixPipelineLinkOptions pipeline_link_options;
pipeline_link_options.maxTraceDepth = 1;
pipeline_link_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_FULL;
# if (OPTIX_VERSION < 70100)
#if (OPTIX_VERSION < 70100)
pipeline_link_options.overrideUsesMotionBlur = false;
# endif
#endif
// Set up OptiX pipeline
std::vector<OptixProgramGroup> final_groups = { rend_lib_group,
@@ -802,12 +552,12 @@ OptixRaytracer::make_optix_materials()
final_groups.push_back(setglobals_miss_group);
sizeof_msg_log = sizeof(msg_log);
OPTIX_CHECK(optixPipelineCreate(m_optix_ctx, &pipeline_compile_options,
&pipeline_link_options, final_groups.data(),
int(final_groups.size()), msg_log,
&sizeof_msg_log, &m_optix_pipeline));
//if (sizeof_msg_log > 1)
// printf ("Creating optix pipeline:\n%s\n", msg_log);
OPTIX_CHECK_MSG(optixPipelineCreate(m_optix_ctx, &pipeline_compile_options,
&pipeline_link_options,
final_groups.data(),
int(final_groups.size()), msg_log,
&sizeof_msg_log, &m_optix_pipeline),
fmtformat("Creating optix pipeline: {}", msg_log));
// Set the pipeline stack size
OptixStackSizes stack_sizes = {};
@@ -939,75 +689,14 @@ OptixRaytracer::make_optix_materials()
}
modules.clear();
# endif //#if (OPTIX_VERSION < 70000)
#endif
return true;
}
bool
OptixRaytracer::finalize_scene()
{
#ifdef OSL_USE_OPTIX
# if (OPTIX_VERSION < 70000)
make_optix_materials();
// Create a GeometryGroup to contain the scene geometry
optix::GeometryGroup geom_group = m_optix_ctx->createGeometryGroup();
m_optix_ctx["top_object"]->set(geom_group);
m_optix_ctx["top_shadower"]->set(geom_group);
// NB: Since the scenes in the test suite consist of only a few primitives,
// using 'NoAccel' instead of 'Trbvh' might yield a slight performance
// improvement. For more complex scenes (e.g., scenes with meshes),
// using 'Trbvh' is recommended to achieve maximum performance.
geom_group->setAcceleration(m_optix_ctx->createAcceleration("Trbvh"));
// Translate the primitives parsed from the scene description into OptiX scene
// objects
for (const auto& sphere : scene.spheres) {
optix::Geometry sphere_geom = m_optix_ctx->createGeometry();
sphere.setOptixVariables(sphere_geom, sphere_bounds, sphere_intersect);
optix::GeometryInstance sphere_gi = m_optix_ctx->createGeometryInstance(
sphere_geom, &scene.optix_mtls[sphere.shaderid()],
&scene.optix_mtls[sphere.shaderid()] + 1);
geom_group->addChild(sphere_gi);
}
for (const auto& quad : scene.quads) {
optix::Geometry quad_geom = m_optix_ctx->createGeometry();
quad.setOptixVariables(quad_geom, quad_bounds, quad_intersect);
optix::GeometryInstance quad_gi = m_optix_ctx->createGeometryInstance(
quad_geom, &scene.optix_mtls[quad.shaderid()],
&scene.optix_mtls[quad.shaderid()] + 1);
geom_group->addChild(quad_gi);
}
// Set the camera variables on the OptiX Context, to be used by the ray gen program
m_optix_ctx["eye"]->setFloat(vec3_to_float3(camera.eye));
m_optix_ctx["dir"]->setFloat(vec3_to_float3(camera.dir));
m_optix_ctx["cx"]->setFloat(vec3_to_float3(camera.cx));
m_optix_ctx["cy"]->setFloat(vec3_to_float3(camera.cy));
m_optix_ctx["invw"]->setFloat(camera.invw);
m_optix_ctx["invh"]->setFloat(camera.invh);
// Create the output buffer
optix::Buffer buffer = m_optix_ctx->createBuffer(RT_BUFFER_OUTPUT,
RT_FORMAT_FLOAT3,
camera.xres, camera.yres);
m_optix_ctx["output_buffer"]->set(buffer);
m_optix_ctx->validate();
# else //#if (OPTIX_VERSION < 70000)
// Build acceleration structures
OptixAccelBuildOptions accelOptions;
OptixBuildInput buildInputs[2];
@@ -1060,13 +749,13 @@ OptixRaytracer::finalize_scene()
unsigned int quadSbtRecord;
quadSbtRecord = OPTIX_GEOMETRY_FLAG_NONE;
if (scene.quads.size() > 0) {
# if (OPTIX_VERSION < 70100)
#if (OPTIX_VERSION < 70100)
OptixBuildInputCustomPrimitiveArray& quadsInput
= buildInputs[numBuildInputs].aabbArray;
# else
#else
OptixBuildInputCustomPrimitiveArray& quadsInput
= buildInputs[numBuildInputs].customPrimitiveArray;
# endif
#endif
buildInputs[numBuildInputs].type
= OPTIX_BUILD_INPUT_TYPE_CUSTOM_PRIMITIVES;
quadsInput.flags = &quadSbtRecord;
@@ -1120,13 +809,13 @@ OptixRaytracer::finalize_scene()
unsigned int sphereSbtRecord;
sphereSbtRecord = OPTIX_GEOMETRY_FLAG_NONE;
if (scene.spheres.size() > 0) {
# if (OPTIX_VERSION < 70100)
#if (OPTIX_VERSION < 70100)
OptixBuildInputCustomPrimitiveArray& spheresInput
= buildInputs[numBuildInputs].aabbArray;
# else
#else
OptixBuildInputCustomPrimitiveArray& spheresInput
= buildInputs[numBuildInputs].customPrimitiveArray;
# endif
#endif
buildInputs[numBuildInputs].type
= OPTIX_BUILD_INPUT_TYPE_CUSTOM_PRIMITIVES;
spheresInput.flags = &sphereSbtRecord;
@@ -1174,9 +863,6 @@ OptixRaytracer::finalize_scene()
// h_aabb.maxX, h_aabb.maxY, h_aabb.maxZ );
make_optix_materials();
# endif //#if (OPTIX_VERSION < 70000)
#endif //#ifdef OSL_USE_OPTIX
return true;
}
@@ -1188,17 +874,7 @@ OptixRaytracer::finalize_scene()
bool
OptixRaytracer::good(TextureHandle* handle OSL_MAYBE_UNUSED)
{
#ifdef OSL_USE_OPTIX
# if (OPTIX_VERSION < 70000)
return intptr_t(handle) != RT_TEXTURE_ID_NULL;
# else
return handle != nullptr;
# endif
#else
return false;
#endif
}
@@ -1210,58 +886,6 @@ OptixRaytracer::get_texture_handle(ustring filename OSL_MAYBE_UNUSED,
ShadingContext* shading_context
OSL_MAYBE_UNUSED)
{
#ifdef OSL_USE_OPTIX
# if (OPTIX_VERSION < 70000)
auto itr = m_samplers.find(filename);
if (itr == m_samplers.end()) {
optix::TextureSampler sampler = context()->createTextureSampler();
sampler->setWrapMode(0, RT_WRAP_REPEAT);
sampler->setWrapMode(1, RT_WRAP_REPEAT);
sampler->setWrapMode(2, RT_WRAP_REPEAT);
sampler->setFilteringModes(RT_FILTER_LINEAR, RT_FILTER_LINEAR,
RT_FILTER_NONE);
sampler->setIndexingMode(false
? RT_TEXTURE_INDEX_ARRAY_INDEX
: RT_TEXTURE_INDEX_NORMALIZED_COORDINATES);
sampler->setReadMode(RT_TEXTURE_READ_NORMALIZED_FLOAT);
sampler->setMaxAnisotropy(1.0f);
OIIO::ImageBuf image;
if (!image.init_spec(filename, 0, 0)) {
errhandler().errorfmt("Could not load: {}", filename);
return (TextureHandle*)(intptr_t(RT_TEXTURE_ID_NULL));
}
int nchan = image.spec().nchannels;
OIIO::ROI roi = OIIO::get_roi_full(image.spec());
int width = roi.width(), height = roi.height();
std::vector<float> pixels(width * height * nchan);
image.get_pixels(roi, OIIO::TypeDesc::FLOAT, pixels.data());
optix::Buffer buffer = context()->createBuffer(RT_BUFFER_INPUT,
RT_FORMAT_FLOAT4, width,
height);
float* device_ptr = static_cast<float*>(buffer->map());
unsigned int pixel_idx = 0;
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
memcpy(device_ptr, &pixels[pixel_idx], sizeof(float) * nchan);
device_ptr += 4;
pixel_idx += nchan;
}
}
buffer->unmap();
sampler->setBuffer(buffer);
itr = m_samplers.emplace(std::move(filename), std::move(sampler)).first;
}
return (RendererServices::TextureHandle*)intptr_t(itr->second->getId());
# else //#if (OPTIX_VERSION < 70000)
auto itr = m_samplers.find(filename);
if (itr == m_samplers.end()) {
// Open image
@@ -1317,12 +941,6 @@ OptixRaytracer::get_texture_handle(ustring filename OSL_MAYBE_UNUSED,
itr = m_samplers.emplace(std::move(filename), std::move(cuda_tex)).first;
}
return reinterpret_cast<RendererServices::TextureHandle*>(itr->second);
# endif //#if (OPTIX_VERSION < 70000)
#else
return nullptr;
#endif
}
@@ -1330,13 +948,11 @@ OptixRaytracer::get_texture_handle(ustring filename OSL_MAYBE_UNUSED,
void
OptixRaytracer::prepare_render()
{
#ifdef OSL_USE_OPTIX
// Set up the OptiX Context
init_optix_context(camera.xres, camera.yres);
// Set up the OptiX scene graph
finalize_scene();
#endif
}
@@ -1344,16 +960,10 @@ OptixRaytracer::prepare_render()
void
OptixRaytracer::warmup()
{
#ifdef OSL_USE_OPTIX
// Perform a tiny launch to warm up the OptiX context
# if (OPTIX_VERSION < 70000)
m_optix_ctx->launch(0, 1, 1);
# else
OPTIX_CHECK(optixLaunch(m_optix_pipeline, m_cuda_stream, d_launch_params,
sizeof(RenderParams), &m_optix_sbt, 0, 0, 1));
CUDA_SYNC_CHECK();
# endif
#endif
}
@@ -1361,16 +971,11 @@ OptixRaytracer::warmup()
void
OptixRaytracer::render(int xres OSL_MAYBE_UNUSED, int yres OSL_MAYBE_UNUSED)
{
#ifdef OSL_USE_OPTIX
# if (OPTIX_VERSION < 70000)
m_optix_ctx->launch(0, xres, yres);
# else
CUDA_CHECK(cudaMalloc(reinterpret_cast<void**>(&d_output_buffer),
xres * yres * 4 * sizeof(float)));
CUDA_CHECK(cudaMalloc(reinterpret_cast<void**>(&d_launch_params),
sizeof(RenderParams)));
m_xres = xres;
m_yres = yres;
@@ -1421,11 +1026,10 @@ OptixRaytracer::render(int xres OSL_MAYBE_UNUSED, int yres OSL_MAYBE_UNUSED)
OSL_PRINTF_BUFFER_SIZE, cudaMemcpyDeviceToHost));
processPrintfBuffer(printf_buffer.data(), OSL_PRINTF_BUFFER_SIZE);
# endif
#endif
}
#if defined(OSL_USE_OPTIX) && OPTIX_VERSION >= 70000
void
OptixRaytracer::processPrintfBuffer(void* buffer_data, size_t buffer_size)
{
@@ -1450,10 +1054,9 @@ OptixRaytracer::processPrintfBuffer(void* buffer_data, size_t buffer_size)
// have we reached the end?
if (fmt_str_hash == 0)
break;
const char* format = m_hash_map[fmt_str_hash];
OSL_ASSERT(
format != nullptr
&& "The format string should have been registered with the renderer");
const char* format = ustring::from_hash(fmt_str_hash).c_str();
OSL_ASSERT(format != nullptr
&& "The string should have been a valid ustring");
const size_t len = strlen(format);
for (size_t j = 0; j < len; j++) {
@@ -1469,7 +1072,7 @@ OptixRaytracer::processPrintfBuffer(void* buffer_data, size_t buffer_size)
switch (format[j]) {
case '%':
// seems like a silly to print a '%', but it keeps the logic parallel with the other cases
dst += snprintf(&buffer[dst], BufferSize - dst, "%s",
dst += snprintf(&buffer[dst], BufferSize - dst,
fmt_string.c_str());
format_end_found = true;
break;
@@ -1503,10 +1106,10 @@ OptixRaytracer::processPrintfBuffer(void* buffer_data, size_t buffer_size)
& ~(sizeof(double) - 1);
uint64_t str_hash = *reinterpret_cast<const uint64_t*>(
&ptr[src]);
const char* str = m_hash_map[str_hash];
const char* str = ustring::from_hash(str_hash).c_str();
OSL_ASSERT(
str != nullptr
&& "The string should have been regisgtered with the renderer");
&& "The string should have been a valid ustring");
dst += snprintf(&buffer[dst], BufferSize - dst,
fmt_string.c_str(), str);
src += sizeof(uint64_t);
@@ -1528,27 +1131,19 @@ OptixRaytracer::processPrintfBuffer(void* buffer_data, size_t buffer_size)
printf("%s", buffer);
}
}
#endif
void
OptixRaytracer::finalize_pixel_buffer()
{
#ifdef OSL_USE_OPTIX
std::string buffer_name = "output_buffer";
# if (OPTIX_VERSION < 70000)
const void* buffer_ptr = m_optix_ctx[buffer_name]->getBuffer()->map();
if (!buffer_ptr)
errhandler().severefmt("Unable to map buffer {}", buffer_name);
pixelbuf.set_pixels(OIIO::ROI::All(), OIIO::TypeFloat, buffer_ptr);
# else
std::vector<float> tmp_buff(m_xres * m_yres * 3);
CUDA_CHECK(cudaMemcpy(tmp_buff.data(),
reinterpret_cast<void*>(d_output_buffer),
m_xres * m_yres * 3 * sizeof(float),
cudaMemcpyDeviceToHost));
pixelbuf.set_pixels(OIIO::ROI::All(), OIIO::TypeFloat, tmp_buff.data());
# endif
#endif
}
@@ -1557,17 +1152,8 @@ void
OptixRaytracer::clear()
{
shaders().clear();
#ifdef OSL_USE_OPTIX
# if (OPTIX_VERSION < 70000)
if (m_optix_ctx) {
m_optix_ctx->destroy();
m_optix_ctx = nullptr;
}
# else
OPTIX_CHECK(optixDeviceContextDestroy(m_optix_ctx));
m_optix_ctx = 0;
# endif
#endif
}
OSL_NAMESPACE_EXIT
+10 -51
View File
@@ -11,11 +11,8 @@
#include <OSL/device_string.h>
#include "optix_compat.h"
#include "simpleraytracer.h"
#if OPTIX_VERSION < 70000
# include "optix_stringtable.h"
#endif
#include "render_params.h"
#include "simpleraytracer.h"
OSL_NAMESPACE_ENTER
@@ -28,21 +25,6 @@ public:
OptixRaytracer();
virtual ~OptixRaytracer();
uint64_t register_string(const std::string& str,
const std::string& var_name)
{
ustring ustr = ustring(str);
#if OPTIX_VERSION < 70000
uint64_t addr = m_str_table.addString(ustr, ustring(var_name));
if (!var_name.empty())
register_global(var_name, addr);
return addr;
#else
m_hash_map[ustr.hash()] = ustr.c_str();
return 0;
#endif
}
uint64_t register_global(const std::string& str, uint64_t value);
bool fetch_global(const std::string& str, uint64_t* value);
@@ -76,50 +58,30 @@ public:
ShadingContext* shading_context);
// Easy way to do Optix calls
optix::Context& optix_ctx()
{
return m_optix_ctx;
}
optix::Context& context()
{
return m_optix_ctx;
}
optix::Context& operator->()
{
return context();
}
optix::Context& optix_ctx() { return m_optix_ctx; }
optix::Context& context() { return m_optix_ctx; }
optix::Context& operator->() { return context(); }
#if (OPTIX_VERSION >= 70000)
void processPrintfBuffer(void* buffer_data, size_t buffer_size);
#endif
private:
optix::Context m_optix_ctx = nullptr;
#if (OPTIX_VERSION < 70000)
OptiXStringTable m_str_table;
optix::Program m_program = nullptr;
optix::Program sphere_intersect = nullptr;
optix::Program sphere_bounds = nullptr;
optix::Program quad_intersect = nullptr;
optix::Program quad_bounds = nullptr;
#else
CUstream m_cuda_stream;
OptixTraversableHandle m_travHandle;
OptixShaderBindingTable m_optix_sbt = {};
OptixShaderBindingTable m_optix_sbt = {};
OptixShaderBindingTable m_setglobals_optix_sbt = {};
OptixPipeline m_optix_pipeline = {};
OptixPipeline m_optix_pipeline = {};
CUdeviceptr d_output_buffer;
CUdeviceptr d_launch_params = 0;
CUdeviceptr d_quads_list = 0;
CUdeviceptr d_spheres_list = 0;
CUdeviceptr d_quads_list = 0;
CUdeviceptr d_spheres_list = 0;
int m_xres, m_yres;
CUdeviceptr d_osl_printf_buffer;
CUdeviceptr d_color_system;
uint64_t test_str_1;
uint64_t test_str_2;
const unsigned long OSL_PRINTF_BUFFER_SIZE = 8 * 1024 * 1024;
std::unordered_map<uint64_t, const char*> m_hash_map;
bool load_optix_module(
const char* filename,
@@ -130,12 +92,9 @@ private:
OptixProgramGroupOptions* program_options,
OptixProgramGroup* pg);
#endif
std::string m_materials_ptx;
std::unordered_map<OIIO::ustring, optix::TextureSampler, OIIO::ustringHash>
m_samplers;
std::unordered_map<OIIO::ustring, uint64_t, OIIO::ustringHash> m_globals_map;
std::unordered_map<OIIO::ustring, optix::TextureSampler> m_samplers;
std::unordered_map<OIIO::ustring, uint64_t> m_globals_map;
};
+3 -71
View File
@@ -17,15 +17,6 @@
#ifdef OSL_USE_OPTIX
# include <optix.h>
# if (OPTIX_VERSION < 70000)
// Converts from Imath::Vec3 to optix::float3
inline optix::float3
vec3_to_float3(const OSL::Vec3& vec)
{
return optix::make_float3(vec.x, vec.y, vec.z);
}
# endif
# include <vector_functions.h> // from CUDA
#endif
@@ -52,24 +43,8 @@ ortho(const Vec3& n, Vec3& x, Vec3& y)
// Note: not used in OptiX mode
struct Ray {
enum RayType {
CAMERA = 1,
SHADOW = 2,
REFLECTION = 4,
REFRACTION = 8,
DIFFUSE = 16,
GLOSSY = 32,
SUBSURFACE = 64,
DISPLACEMENT = 128
};
Ray(const Vec3& o, const Vec3& d, float radius, float spread,
RayType raytype)
: origin(o)
, direction(d)
, radius(radius)
, spread(spread)
, raytype(static_cast<int>(raytype))
Ray(const Vec3& o, const Vec3& d, float radius, float spread)
: origin(o), direction(d), radius(radius), spread(spread)
{
}
@@ -97,7 +72,6 @@ struct Ray {
Vec3 origin, direction;
float radius, spread;
int raytype;
};
@@ -142,7 +116,7 @@ struct Camera {
const float cos_a = dir.dot(v);
const float spread
= sqrtf(invw * invh * cx.length() * cy.length() * cos_a) * cos_a;
return Ray(eye, v, 0, spread, Ray::CAMERA);
return Ray(eye, v, 0, spread);
}
// Specified by user:
@@ -177,12 +151,7 @@ struct Primitive {
float& maxy, float& maxz) const;
#ifdef OSL_USE_OPTIX
# if (OPTIX_VERSION < 70000)
virtual void setOptixVariables(optix::Geometry geom, optix::Program bounds,
optix::Program intersect) const = 0;
# else
virtual void setOptixVariables(void* data) const = 0;
# endif
#endif
private:
@@ -293,19 +262,6 @@ struct Sphere final : public Primitive {
}
#ifdef OSL_USE_OPTIX
# if (OPTIX_VERSION < 70000)
virtual void setOptixVariables(optix::Geometry geom, optix::Program bounds,
optix::Program intersect) const
{
geom->setPrimitiveCount(1u);
geom->setBoundingBoxProgram(bounds);
geom->setIntersectionProgram(intersect);
geom["sphere"]->setFloat(optix::make_float4(c.x, c.y, c.z, sqrtf(r2)));
geom["r2"]->setFloat(r2);
geom["a"]->setFloat(M_PIf * (r2 * r2));
}
# else
virtual void setOptixVariables(void* data) const
{
SphereParams* sphere_data = reinterpret_cast<SphereParams*>(data);
@@ -314,7 +270,6 @@ struct Sphere final : public Primitive {
sphere_data->a = M_PI * (r2 * r2);
sphere_data->shaderID = shaderid();
}
# endif
#endif
private:
@@ -406,23 +361,6 @@ struct Quad final : public Primitive {
}
#ifdef OSL_USE_OPTIX
# if (OPTIX_VERSION < 70000)
virtual void setOptixVariables(optix::Geometry geom, optix::Program bounds,
optix::Program intersect) const
{
geom->setPrimitiveCount(1u);
geom->setBoundingBoxProgram(bounds);
geom->setIntersectionProgram(intersect);
geom["p"]->setFloat(vec3_to_float3(p));
geom["ex"]->setFloat(vec3_to_float3(ex));
geom["ey"]->setFloat(vec3_to_float3(ey));
geom["n"]->setFloat(vec3_to_float3(n));
geom["eu"]->setFloat(eu);
geom["ev"]->setFloat(ev);
geom["a"]->setFloat(a);
}
# else
virtual void setOptixVariables(void* data) const
{
QuadParams* quad_data = reinterpret_cast<QuadParams*>(data);
@@ -435,7 +373,6 @@ struct Quad final : public Primitive {
quad_data->a = a;
quad_data->shaderID = shaderid();
}
# endif
#endif
private:
@@ -535,11 +472,6 @@ struct Scene {
std::vector<Sphere> spheres;
std::vector<Quad> quads;
#ifdef OSL_USE_OPTIX
# if (OPTIX_VERSION < 70000)
std::vector<optix::Material> optix_mtls;
# endif
#endif
};
OSL_NAMESPACE_EXIT
+15 -1
View File
@@ -1,6 +1,10 @@
#pragma once
#if (OPTIX_VERSION >= 70000)
#include "optix_compat.h"
#if defined(OSL_USE_OPTIX) || defined(__CUDA_ARCH__)
struct RenderParams {
float3 bad_color;
float3 bg_color;
@@ -31,16 +35,22 @@ struct RenderParams {
uint64_t test_str_2;
};
struct PrimitiveParams {
float a; // area
unsigned int shaderID;
};
struct SphereParams : PrimitiveParams {
float3 c; // center
float r2; // radius ^2
};
struct QuadParams : PrimitiveParams {
float3 p;
float3 ex;
@@ -50,11 +60,15 @@ struct QuadParams : PrimitiveParams {
float ev;
};
struct GenericData {
void* data;
unsigned int sbtGeoIndex;
};
struct GenericRecord {
__align__(
OPTIX_SBT_RECORD_ALIGNMENT) char header[OPTIX_SBT_RECORD_HEADER_SIZE];
+4 -5
View File
@@ -154,11 +154,10 @@ struct MxConductorParams : public MxMicrofacetBaseParams {
Color3 evalT(float cos_theta) const { return Color3(0.0f); }
// Avoid function was declared but never referenced
// float get_ior() const
// {
// return 0; // no transmission possible
// }
float get_ior() const
{
return 0; // no transmission possible
}
};
struct MxGeneralizedSchlickParams : public MxMicrofacetBaseParams {
+6 -12
View File
@@ -823,7 +823,6 @@ SimpleRaytracer::globals_from_hit(ShaderGlobals& sg, const Ray& r,
sg.N = -sg.N;
sg.Ng = -sg.Ng;
}
sg.raytype = r.raytype;
sg.flipHandedness = sg.dPdx.cross(sg.dPdy).dot(sg.N) < 0;
// In our SimpleRaytracer, the "renderstate" itself just a pointer to
@@ -832,16 +831,13 @@ SimpleRaytracer::globals_from_hit(ShaderGlobals& sg, const Ray& r,
}
Vec3
SimpleRaytracer::eval_background(const Dual2<Vec3>& dir, ShadingContext* ctx,
int bounce)
SimpleRaytracer::eval_background(const Dual2<Vec3>& dir, ShadingContext* ctx)
{
ShaderGlobals sg;
memset((char*)&sg, 0, sizeof(ShaderGlobals));
sg.I = dir.val();
sg.dIdx = dir.dx();
sg.dIdy = dir.dy();
if (bounce >= 0)
sg.raytype = bounce > 0 ? Ray::DIFFUSE : Ray::CAMERA;
shadingsys->execute(*ctx, *m_shaders[backgroundShaderID], sg);
return process_background_closure(sg.Ci);
}
@@ -863,7 +859,7 @@ SimpleRaytracer::subpixel_radiance(float x, float y, Sampler& sampler,
if (!scene.intersect(r, t, id)) {
// we hit nothing? check background shader
if (backgroundShaderID >= 0) {
if (b > 0 && backgroundResolution > 0) {
if (backgroundResolution > 0) {
float bg_pdf = 0;
Vec3 bg = background.eval(r.direction, bg_pdf);
path_radiance
@@ -873,7 +869,7 @@ SimpleRaytracer::subpixel_radiance(float x, float y, Sampler& sampler,
} else {
// we aren't importance sampling the background - so just run it directly
path_radiance += path_weight
* eval_background(r.direction, ctx, b);
* eval_background(r.direction, ctx);
}
}
break;
@@ -935,8 +931,7 @@ SimpleRaytracer::subpixel_radiance(float x, float y, Sampler& sampler,
b.pdf);
if ((contrib.x + contrib.y + contrib.z) > 0) {
int shadow_id = id;
Ray shadow_ray = Ray(sg.P, bg_dir.val(), radius, 0,
Ray::SHADOW);
Ray shadow_ray = Ray(sg.P, bg_dir.val(), radius, 0);
Dual2<float> shadow_dist;
if (!scene.intersect(shadow_ray, shadow_dist,
shadow_id)) // ray reached the background?
@@ -961,7 +956,7 @@ SimpleRaytracer::subpixel_radiance(float x, float y, Sampler& sampler,
* MIS::power_heuristic<MIS::EVAL_WEIGHT>(light_pdf,
b.pdf);
if ((contrib.x + contrib.y + contrib.z) > 0) {
Ray shadow_ray = Ray(sg.P, ldir, radius, 0, Ray::SHADOW);
Ray shadow_ray = Ray(sg.P, ldir, radius, 0);
// trace a shadow ray and see if we actually hit the target
// in this tiny renderer, tracing a ray is probably cheaper than evaluating the light shader
int shadow_id = id; // ignore self hit
@@ -984,8 +979,7 @@ SimpleRaytracer::subpixel_radiance(float x, float y, Sampler& sampler,
// trace indirect ray and continue
BSDF::Sample p = result.bsdf.sample(-sg.I, xi, yi, zi);
path_weight *= p.weight;
bsdf_pdf = p.pdf;
r.raytype = Ray::DIFFUSE; // FIXME? Use DIFFUSE for all indiirect rays
bsdf_pdf = p.pdf;
r.direction = p.wi;
r.radius = radius;
// Just simply use roughness as spread slope
+3 -4
View File
@@ -109,7 +109,7 @@ private:
float m_screen_window[4];
int backgroundShaderID = -1;
int backgroundResolution = 1024;
int backgroundResolution = 0;
int aa = 1;
int max_bounces = 1000000;
int rr_depth = 5;
@@ -132,7 +132,7 @@ private:
typedef bool (SimpleRaytracer::*AttrGetter)(ShaderGlobals* sg, bool derivs,
ustring object, TypeDesc type,
ustring name, void* val);
typedef std::unordered_map<ustring, AttrGetter, ustringHash> AttrGetterMap;
typedef std::unordered_map<ustring, AttrGetter> AttrGetterMap;
AttrGetterMap m_attr_getters;
// Attribute getters
@@ -166,8 +166,7 @@ private:
// CPU renderer helpers
void globals_from_hit(ShaderGlobals& sg, const Ray& r,
const Dual2<float>& t, int id);
Vec3 eval_background(const Dual2<Vec3>& dir, ShadingContext* ctx,
int bounce = -1);
Vec3 eval_background(const Dual2<Vec3>& dir, ShadingContext* ctx);
Color3 subpixel_radiance(float x, float y, Sampler& sampler,
ShadingContext* ctx);
Color3 antialias_pixel(int x, int y, ShadingContext* ctx);
+100 -113
View File
@@ -21,16 +21,13 @@
#include <OpenImageIO/thread.h>
#include <OpenImageIO/timer.h>
#ifdef OSL_USE_OPTIX
// purely to get optix version -- once optix 7.0 is required this can go away
# include <optix.h>
#endif
#include <OSL/oslexec.h>
#include "optixraytracer.h"
#include "shading.h"
#include "simpleraytracer.h"
#ifdef OSL_USE_OPTIX
# include "optixraytracer.h"
#endif
using namespace OSL;
@@ -104,11 +101,6 @@ set_shadingsys_options()
shadingsys->attribute("llvm_debugging_symbols", 1);
shadingsys->attribute("llvm_profiling_events", 1);
// We rely on the default set of "raytypes" tags. To use a custom set,
// this is where we would do:
// shadingsys->attribute("raytypes", TypeDesc(TypeDesc::STRING, num_raytypes),
// raytype_names);
shadingsys_options_set = true;
}
@@ -223,124 +215,119 @@ main(int argc, const char* argv[])
OIIO::simd::set_denorms_zero_mode(false);
#endif
#if (OPTIX_VERSION < 70000)
try {
using namespace OIIO;
Timer timer;
// Read command line arguments
getargs(argc, argv);
// Allow magic env variable TESTRENDER_AA to override the --aa option,
// this is helpful for certain CI tests in special debug modes that would
// be too slow to be practical.
int aaoverride = OIIO::Strutil::stoi(
OIIO::Sysutil::getenv("TESTRENDER_AA"));
if (aaoverride)
aa = aaoverride;
SimpleRaytracer* rend = nullptr;
#ifdef OSL_USE_OPTIX
if (use_optix)
rend = new OptixRaytracer;
else
#endif
using namespace OIIO;
Timer timer;
rend = new SimpleRaytracer;
// Read command line arguments
getargs(argc, argv);
// Other renderer and global options
if (debug1 || verbose)
rend->errhandler().verbosity(ErrorHandler::VERBOSE);
rend->attribute("saveptx", (int)saveptx);
rend->attribute("max_bounces", max_bounces);
rend->attribute("rr_depth", rr_depth);
rend->attribute("aa", aa);
rend->attribute("show_albedo_scale", show_albedo_scale);
OIIO::attribute("threads", num_threads);
SimpleRaytracer* rend = nullptr;
if (use_optix)
rend = new OptixRaytracer;
else
rend = new SimpleRaytracer;
// Create a new shading system. We pass it the RendererServices
// object that services callbacks from the shading system, the
// TextureSystem (note: passing nullptr just makes the ShadingSystem
// make its own TS), and an error handler.
shadingsys = new ShadingSystem(rend, nullptr, &rend->errhandler());
rend->shadingsys = shadingsys;
// Other renderer and global options
if (debug1 || verbose)
rend->errhandler().verbosity(ErrorHandler::VERBOSE);
rend->attribute("saveptx", (int)saveptx);
rend->attribute("max_bounces", max_bounces);
rend->attribute("rr_depth", rr_depth);
rend->attribute("aa", aa);
rend->attribute("show_albedo_scale", show_albedo_scale);
OIIO::attribute("threads", num_threads);
// Register the layout of all closures known to this renderer
// Any closure used by the shader which is not registered, or
// registered with a different number of arguments will lead
// to a runtime error.
register_closures(shadingsys);
// Create a new shading system. We pass it the RendererServices
// object that services callbacks from the shading system, the
// TextureSystem (note: passing nullptr just makes the ShadingSystem
// make its own TS), and an error handler.
shadingsys = new ShadingSystem(rend, nullptr, &rend->errhandler());
rend->shadingsys = shadingsys;
// Register the layout of all closures known to this renderer
// Any closure used by the shader which is not registered, or
// registered with a different number of arguments will lead
// to a runtime error.
register_closures(shadingsys);
// Setup common attributes
set_shadingsys_options();
// Setup common attributes
set_shadingsys_options();
#ifdef OSL_USE_OPTIX
# if (OPTIX_VERSION >= 70000)
if (use_optix)
reinterpret_cast<OptixRaytracer*>(rend)->synch_attributes();
# endif
if (use_optix)
reinterpret_cast<OptixRaytracer*>(rend)->synch_attributes();
#endif
// Loads a scene, creating camera, geometry and assigning shaders
rend->camera.resolution(xres, yres);
rend->parse_scene_xml(scenefile);
// Loads a scene, creating camera, geometry and assigning shaders
rend->camera.resolution(xres, yres);
rend->parse_scene_xml(scenefile);
rend->prepare_render();
rend->prepare_render();
rend->pixelbuf.reset(ImageSpec(xres, yres, 3, TypeDesc::FLOAT));
rend->pixelbuf.reset(ImageSpec(xres, yres, 3, TypeDesc::FLOAT));
double setuptime = timer.lap();
double setuptime = timer.lap();
if (warmup)
rend->warmup();
double warmuptime = timer.lap();
if (warmup)
rend->warmup();
double warmuptime = timer.lap();
// Launch the kernel to render the scene
for (int i = 0; i < iters; ++i)
rend->render(xres, yres);
double runtime = timer.lap();
// Launch the kernel to render the scene
for (int i = 0; i < iters; ++i)
rend->render(xres, yres);
double runtime = timer.lap();
rend->finalize_pixel_buffer();
rend->finalize_pixel_buffer();
// Write image to disk
if (Strutil::iends_with(imagefile, ".jpg")
|| Strutil::iends_with(imagefile, ".jpeg")
|| Strutil::iends_with(imagefile, ".gif")
|| Strutil::iends_with(imagefile, ".png")) {
// JPEG, GIF, and PNG images should be automatically saved as sRGB
// because they are almost certainly supposed to be displayed on web
// pages.
ImageBufAlgo::colorconvert(rend->pixelbuf, rend->pixelbuf, "linear",
"sRGB", false, "", "");
}
rend->pixelbuf.set_write_format(TypeDesc::HALF);
if (!rend->pixelbuf.write(imagefile))
rend->errhandler().errorfmt("Unable to write output image: {}",
rend->pixelbuf.geterror());
double writetime = timer.lap();
// Print some debugging info
if (debug1 || runstats || profile) {
std::cout << "\n";
std::cout << "Setup : "
<< OIIO::Strutil::timeintervalformat(setuptime, 4)
<< "\n";
std::cout << "Warmup: "
<< OIIO::Strutil::timeintervalformat(warmuptime, 4)
<< "\n";
std::cout << "Run : "
<< OIIO::Strutil::timeintervalformat(runtime, 4) << "\n";
std::cout << "Write : "
<< OIIO::Strutil::timeintervalformat(writetime, 4)
<< "\n";
std::cout << "\n";
std::cout << shadingsys->getstats(5) << "\n";
OIIO::TextureSystem* texturesys = shadingsys->texturesys();
if (texturesys)
std::cout << texturesys->getstats(5) << "\n";
std::cout << ustring::getstats() << "\n";
}
// We're done with the shading system now, destroy it
rend->clear();
delete shadingsys;
delete rend;
#if (OPTIX_VERSION < 70000)
} catch (const OSL::optix::Exception& e) {
OSL::print("Optix Error: {}\n", e.what());
} catch (const std::exception& e) {
OSL::print("Unknown Error: {}\n", e.what());
// Write image to disk
if (Strutil::iends_with(imagefile, ".jpg")
|| Strutil::iends_with(imagefile, ".jpeg")
|| Strutil::iends_with(imagefile, ".gif")
|| Strutil::iends_with(imagefile, ".png")) {
// JPEG, GIF, and PNG images should be automatically saved as sRGB
// because they are almost certainly supposed to be displayed on web
// pages.
ImageBufAlgo::colorconvert(rend->pixelbuf, rend->pixelbuf, "linear",
"sRGB", false, "", "");
}
#endif
rend->pixelbuf.set_write_format(TypeDesc::HALF);
if (!rend->pixelbuf.write(imagefile))
rend->errhandler().errorfmt("Unable to write output image: {}",
rend->pixelbuf.geterror());
double writetime = timer.lap();
// Print some debugging info
if (debug1 || runstats || profile) {
std::cout << "\n";
std::cout << "Setup : "
<< OIIO::Strutil::timeintervalformat(setuptime, 4) << "\n";
std::cout << "Warmup: "
<< OIIO::Strutil::timeintervalformat(warmuptime, 4) << "\n";
std::cout << "Run : " << OIIO::Strutil::timeintervalformat(runtime, 4)
<< "\n";
std::cout << "Write : "
<< OIIO::Strutil::timeintervalformat(writetime, 4) << "\n";
std::cout << "\n";
std::cout << shadingsys->getstats(5) << "\n";
OIIO::TextureSystem* texturesys = shadingsys->texturesys();
if (texturesys)
std::cout << texturesys->getstats(5) << "\n";
std::cout << ustring::getstats() << "\n";
}
// We're done with the shading system now, destroy it
rend->clear();
delete shadingsys;
delete rend;
return EXIT_SUCCESS;
}

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