Compare commits

...
74 Commits
Author SHA1 Message Date
Larry Gritz 71a9310f0b feat(gpu)!: GPU/OptiX support of ReParameter (#1686)
BREAKING CHANGE: to RendererServices ABI (including for CPU) and to
the renderer-side setup when using OptiX.

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

The basic gist is as follows:

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

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

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

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

* Interactive parameters are NOT constant folded during runtime
  optimization.

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

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

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

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

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

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

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

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

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

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

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

All tests pass for scalar and batch and optix.

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

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

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

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

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

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

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

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

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

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

Clean up OSL_USE_OPTIX and OSL_USE_BATCHED symbol defs

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

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

Note from LG explaining:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

For example, this shader:

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

allows us to do this:

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

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

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

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

Establish two new metadata hints about shader parameters:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

         int val = 3 + 1;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

This patch changes the behavior as follows:

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

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

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

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

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

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

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

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

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

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

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

Nothing, it seems. So eliminate it.

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

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

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

This PR starts along the path of phase 2.

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

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

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

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

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

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

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

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

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

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

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

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

* Fix ptx definitions of OSL_CONSTANT_DATA arrays

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

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

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

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

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

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

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

Some notes and guideposts:

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

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

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

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

Remove deprecated version of LLVM_Util::make_function.

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

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

get_alignment can also be OSL_DEV only as well as simplified

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

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

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-10-11 14:46:55 -07:00
177 changed files with 4493 additions and 2316 deletions
+7 -2
View File
@@ -19,6 +19,11 @@ on:
permissions: read-all
# Allow subsequent pushes to the same PR or REF to cancel any previous jobs.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
@@ -30,7 +35,7 @@ jobs:
fail-fast: false
matrix:
include:
- desc: sonary gcc9/C++14 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
- desc: sonar gcc9/C++14 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
nametag: static-analysis-sonar
os: ubuntu-latest
vfxyear: 2022
@@ -40,7 +45,7 @@ jobs:
python_ver: 3.9
pybind11_ver: v2.9.0
simd: avx2,f16c
batched: b8_AVX2
batched: b8_AVX2,b16_AVX512
coverage: 1
# skip_tests: 1
sonar: 1
+21 -15
View File
@@ -20,8 +20,10 @@ on:
- '**.rst'
- '**.tex'
schedule:
# Full nightly build
# Full nightly build, for the main project repo (not for forks)
- cron: "0 6 * * *"
if: github.repository == 'AcademySoftwareFoundation/OpenShadingLanguage'
permissions: read-all
@@ -45,7 +47,7 @@ jobs:
pybind11_ver: v2.4.2
- desc: clang9/C++14 llvm9 oiio-release boost1.66 avx2 exr2.3 py2.7
nametag: linux-clang9-llvm9
os: ubuntu-18.04
os: ubuntu-20.04
vfxyear: 2019
vfxsuffix: -clang9
cc_compiler: clang
@@ -66,7 +68,8 @@ jobs:
# pybind11_ver: v2.9.0
simd: avx2,f16c
skip_tests: 1
setenvs: export OSL_CMAKE_FLAGS="-DUSE_OPTIX=1" OPTIX_VERSION=7.0
setenvs: export OSL_CMAKE_FLAGS="-DUSE_OPTIX=1" OPTIX_VERSION=7.0
OPENIMAGEIO_CMAKE_FLAGS=-DBUILD_FMT_VERSION=8.1.1
- desc: gcc6/C++14 llvm10 py3.7 boost1.70 exr2.4 oiio2.2 sse4
nametag: linux-vfx2020
os: ubuntu-latest
@@ -111,11 +114,11 @@ jobs:
simd: avx2,f16c
batched: b8_AVX2,b8_AVX512,b16_AVX512
setenvs: USE_OPENVDB=0
- desc: icc/C++17 llvm13 py3.9 boost1.76 exr3.1 oiio-master avx2
- desc: icc/C++17 llvm14 py3.9 boost1.76 exr3.1 oiio-master avx2
nametag: linux-icc
os: ubuntu-latest
vfxyear: 2022
vfxsuffix: -clang13
vfxsuffix: -clang14
cc_compiler: icc
cxx_compiler: icpc
cxx_std: 17
@@ -128,11 +131,11 @@ jobs:
setenvs: export OSL_CMAKE_FLAGS="-DSTOP_ON_WARNING=OFF -DEXTRA_CPP_ARGS=-fp-model=consistent"
OPENIMAGEIO_CMAKE_FLAGS=-DBUILD_FMT_VERSION=7.1.3
USE_OPENVDB=0
- desc: icx/C++17 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
- desc: icx/C++17 llvm14 py3.9 boost1.76 exr3.1 oiio2.3 avx2
nametag: linux-icx
os: ubuntu-latest
vfxyear: 2022
vfxsuffix: -clang13
vfxsuffix: -clang14
cc_compiler: icx
cxx_compiler: icpx
cxx_std: 17
@@ -287,7 +290,7 @@ jobs:
include:
- desc: Debug gcc7/C++14 llvm9 py2.7 oiio2.3 exr2.4 sse4 boost1.65 exr2.4
nametag: linux-debug-gcc7-llvm9
os: ubuntu-18.04
os: ubuntu-20.04
cxx_compiler: g++-7
cxx_std: 14
openexr_ver: v2.4.3
@@ -301,7 +304,7 @@ jobs:
CTEST_TEST_TIMEOUT=240
- desc: gcc10/C++17 llvm10 oiio-release boost1.65 exr2.5 avx2
nametag: linux-2021ish-gcc10-llvm10
os: ubuntu-18.04
os: ubuntu-20.04
cxx_compiler: g++-10
cxx_std: 17
fmt_ver: 7.0.1
@@ -315,20 +318,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-20.04
os: ubuntu-22.04
cxx_compiler: g++-11
cxx_std: 17
fmt_ver: 9.1.0
openexr_ver: v3.1.5
openexr_ver: v3.1.7
openimageio_ver: master
pybind11_ver: v2.10.0
python_ver: 3.9
python_ver: "3.10"
simd: avx2,f16c
batched: b8_AVX2,b8_AVX512,b16_AVX512
setenvs: export LLVM_VERSION=13.0.0
LLVM_DISTRO_NAME=ubuntu-20.04
OPENCOLORIO_VERSION=v2.1.2
PUGIXML_VERSION=v1.11.4
OPENCOLORIO_VERSION=v2.2.0
PUGIXML_VERSION=v1.13
- desc: bleeding edge gcc12/C++17 llvm14 oiio/ocio/exr/pybind-master boost1.71 py3.10 avx2 batch-b16avx512
nametag: linux-bleeding-edge
os: ubuntu-22.04
@@ -352,7 +355,7 @@ jobs:
cc_compiler: clang
cxx_std: 17
fmt_ver: 8.1.1
openexr_ver: v3.1.5
openexr_ver: v3.1.7
openimageio_ver: master
pybind11_ver: v2.9.2
python_ver: 3.8
@@ -432,6 +435,8 @@ 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
@@ -441,6 +446,7 @@ 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}}
+8 -3
View File
@@ -10,18 +10,23 @@ 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"
+4 -3
View File
@@ -5,13 +5,14 @@ This is a checklist for TSC's to review as part of the intake process. The TSC s
- Existing Project Governance
- [X] Project License exists ( [LICENSE.md](../LICENSE.md) ) and is OSI-approved
- [X] Any third-party components/dependencies included are listed along with their licenses ( [THIRD_PARTY.md](../THIRD_PARTY.md) )
- [X] Governance defined, outlining community roles and how decsions are made ( [GOVERNANCE.md](../GOVERNANCE.md] )
- [X] Governance defined, outlining community roles and how decisions are made ( [GOVERNANCE.md](../GOVERNANCE.md) )
- Closed by https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1137
- [X] Contribution Policy defined ( [CONTRIBUTING.md](../CONTRIBUTING.md) )
- Closed by https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1137
- [X] Code of Conduct defined ( existing or pull from [ASWF Sample Project](https://github.com/AcademySoftwareFoundation/aswf-sample-project/blob/master/CODE_OF_CONDUCT.md) )
- Closed by https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1137
- [ ] Release methodology defined ( [release.md](process/release.md) )
- [X] Release methodology defined ( [RELEASING.md](../docs/RELEASING.md) )
- Closed by https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1572
- New Project Governance
- [X] TSC members identified
- [X] First TSC meeting held
@@ -41,7 +42,7 @@ This is a checklist for TSC's to review as part of the intake process. The TSC s
- [X] New project announcement done ( https://www.aswf.io/osl-joins-aswf/ )
- [X] Project added to ASWF website and ASWF landscape
- Graduation
- [ ] CII Badge achieved
- [X] OpenSSF Best Practices Badge achieved
- [ ] Committer Diversity established
- [ ] Commit/Contribution growth during incubation
- [ ] Committers defined in the project ( [COMMITTERS.csv](COMMITTERS.csv) or [COMMITTERS.yml](COMMITTERS.yml) )
+68 -1
View File
@@ -23,6 +23,10 @@ API changes, new options, new ShadingSystem features (for renderer writers):
SIMD batched shading mode:
* Fix some array overruns (asymptomatic, but still potentially buggy) in
common_ancestor_between. #1577 (1.13.0.2)
* Fix issue with closure keyword parameters. #1620 (1.13.2.0/1.12.8.0)
* Fix crash when adding a default initialized closure. #1624
(1.13.2.0/1.12.8.0)
* Fix support for closures with array types. #1630 (1.13.2.0/1.12.8.0)
OptiX rendering:
* OptiX 6.0 support has been removed. For GPU rendering with OptiX, a minimum
@@ -34,6 +38,14 @@ OptiX rendering:
* Better PTX cache hit rate by eliminating several sources of not being
strictly deterministic in the PTX text we were generating. #1566 #1570
(1.13.0.1)
* Fix PTX symbol visibility issues. #1609 (1.13.2.0)
* Hide more code that is only used for OptiX mode, when OptiX is disabled.
#1608 (1.13.2.0)
* Remove dependency on OptiX SDK for building core OSL with OptiX support. You
can now build OSL with OptiX support enabled even if you don't have the
OptiX SDK headers present at build time. But you will still need them to
build your OptiX-based application that uses OSL for GPU rendering. #1627
(1.13.2.0/1.12.8.0)
Performance improvements:
@@ -44,27 +56,82 @@ Bug fixes and other improvements (internals):
Internals/developer concerns:
* platform.h:
- New `OSL_ALLOCA` macro to allocate on the stack. #1589 (1.13.0.3)
- Define OSL::bitcast utility. #1610 (1.13.2.0)
* Make sure that std::hash is defined for ustring and ustringhash. #1599
(1.13.1.1)
* Deprecate LLVMUtil::internalize_module_functions. #1606 (1.13.1.0)
* Work toward always representing strings in shaders as ustringhash rather
than ustring: phase 1 #1603 phase2 #1612 (1.13.2.0)
Build & test system improvements:
* CMake build system and scripts:
- The version number is now a cache variable, and so can be overridden at
build time using `-DOSL_VERSION=...`. Use with extreme caution! #1579
(1.13.0.2)
(1.13.0.2) Revised again to reduce changes of user error in #1617
(1.13.2.0/1.12.7.1)
- Add clangSupport library as dependency to fix linker error on some
platforms. #1613 (1.13.2.0/1.12.7.1)
* Dependency version support:
- Fix some issues that came up with the new icx 2022.0 compiler. #1601
(1.13.1.0)
- Test against OpenColorIO 2.2. #1616 (1.13.2.0/1.12.7.1)
* Testing and Continuous integration (CI) systems:
- Dynamic analysis using address and leak sanitizers. #1581 (1.13.0.3)
- `testshade --help` now prints TextureSystem options and all hardware
information. #1584 (1.13.0.3)
- Improvements to SonarCloud and coverage analysis. #1596 (1.13.0.3)
#1607 (1.13.1.0)
- Disabling the dso version of testshade for the coverage analysis test.
#1604 (1.13.1.0)
- Be sure to run pointcloud tests when partio is found. #1611 (1.13.2.0)
- testshade: better testing of all closure parameter types. #1621
(1.13.2.0/1.12.8.0)
* Platform support:
- Include `immintrin.h` only when needed. #1605 (1.13.1.0)
Documentation:
* `doc/RELEASING.md` documents our release process and versioning policies.
#1572 (1.13.0.2)
Release 1.12.8.0 -- 3 Jan 2023 (compared to 1.12.7.1)
-------------------------------------------------------
* Remove dependency on OptiX SDK for building core OSL with OptiX support.
You can now build OSL with OptiX support enabled even if you don't have the
OptiX SDK headers present at build time. But you will still need them to
build your OptiX-based application that uses OSL for GPU rendering. #1627
* Batch mode: fix issue with closure keyword parameters. #1620
* Batch mode: fix crash when adding a default initialized closure. #1624
* Batch mode: Fix support for closures with array types. #1630
* testshade: better testing of all closure parameter types. #1621
* Fix various CI breaks as dependencies shifted. #1629 #1631 #1633
Release 1.12.7.1 -- 1 Dec 2022 (compared to 1.12.7.0)
-------------------------------------------------------
* Add clangSupport library as dependency to fix linker error on some
platforms. #1613
* Test against OpenColorIO 2.2. #1616
* Build: Fix how version overrides work to reduce the chance of user mistakes.
#1617
Release 1.12.7.0 -- 1 Nov 2022 (compared to 1.12.6.2)
-------------------------------------------------------
* Optix: Change naming of certain compiler-generated constants in a way that
improves use of the PTX cache. #1570
* Batch: Fix uninitialized members in ReadEvent internals. #1575
* `testshade --help` now prints TextureSystem options and hardware info. #1584
* oslc: Fix memory leak in ASTvariable_declaration. #1576
* Fix memory leaks in light path expression code. #1593 #1594
* Include the immintrin.h header only when needed. #1605
* icx: Improvements to fix problems exposed by new icx 2022.2 compiler. #1601
* Testing: CMake cache variables to control the testing timeout length. #1571
* CI: Add a dynamic analysis test using address and leak sanitizers. #1581
* CI: Now using SonarCloud static analysis. #1551
* CI: Many improvements in testing code coverage #1607
* CI: Make sure to run pointcloud tests when partio is found. #1611
* Developers: platform.h now defines OSL_ALLOCA macro. #1589
* Developers: platform.h now defines OSL::bitcast utility. #1610
Release 1.12 -- 1 Oct 2022 (compared to 1.11)
----------------------------------------------
Big Deal Changes:
+16 -7
View File
@@ -4,7 +4,14 @@
cmake_minimum_required (VERSION 3.12)
set (OSL_VERSION "1.13.1.0" CACHE STRING "Version")
set (OSL_VERSION "1.13.4.0")
set (OSL_VERSION_OVERRIDE "" CACHE STRING
"Version override (use with caution)!")
mark_as_advanced (OSL_VERSION_OVERRIDE)
if (OSL_VERSION_OVERRIDE)
set (OSL_VERSION ${OSL_VERSION_OVERRIDE})
endif ()
project (OSL VERSION ${OSL_VERSION}
LANGUAGES CXX C
HOMEPAGE_URL "https://github.com/AcademySoftwareFoundation/OpenShadingLanguage")
@@ -91,7 +98,8 @@ else ()
endif ()
option (OSL_BUILD_PLUGINS "Bool OSL plugins, for example OIIO plugin" ON)
option (OSL_BUILD_SHADERS "Build shaders" ON)
option (USE_OPTIX "Include OptiX support" OFF)
option (OSL_USE_OPTIX "Include OptiX support" OFF)
message(STATUS "OSL_USE_OPTIX: ${OSL_USE_OPTIX}")
set (OPTIX_EXTRA_LIBS CACHE STRING "Extra lib targets needed for OptiX")
set (CUDA_EXTRA_LIBS CACHE STRING "Extra lib targets needed for CUDA")
set (CUDA_TARGET_ARCH "sm_60" CACHE STRING "CUDA GPU architecture (e.g. sm_50)")
@@ -100,6 +108,7 @@ set (OSL_SHADER_INSTALL_DIR "${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT_NAME}/shade
set (OSL_PTX_INSTALL_DIR "${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT_NAME}/ptx"
CACHE STRING "Directory where OptiX PTX files will be installed")
set (CMAKE_DEBUG_POSTFIX "" CACHE STRING "Library naming postfix for Debug builds (e.g., '_debug')")
option (OSL_USTRINGREP_IS_HASH "Always use ustringhash for strings" OFF)
set (OSL_NO_DEFAULT_TEXTURESYSTEM OFF CACHE BOOL "Do not use create a raw OIIO::TextureSystem")
@@ -119,14 +128,14 @@ if (OIIO_FMATH_SIMD_FRIENDLY)
add_definitions (-DOIIO_FMATH_SIMD_FRIENDLY=1)
endif ()
if (USE_OPTIX)
add_definitions ("-DOSL_USE_OPTIX=1")
endif ()
# Define OSL_INTERNAL symbol only when building OSL itself, will not be
# defined for downstream projects using OSL.
add_definitions (-DOSL_INTERNAL=1)
# To make sure we aren't relying on deprecated OIIO features, we define
# OIIO_DISABLE_DEPRECATED before including any OIIO headers.
add_definitions (-DOIIO_DISABLE_DEPRECATED=1)
# Set the default namespace. For symbol hiding reasons, it's important that
# the project name is a subset of the namespace name.
set (${PROJ_NAME}_NAMESPACE ${PROJECT_NAME} CACHE STRING
@@ -214,7 +223,7 @@ if (OSL_BUILD_PLUGINS)
add_subdirectory (src/osl.imageio)
endif ()
if (USE_QT AND Qt5_FOUND)
if (USE_QT AND (Qt5_FOUND OR Qt6_FOUND))
add_subdirectory (src/osltoy)
endif ()
+8 -7
View File
@@ -12,11 +12,11 @@ Dependencies
OSL requires the following dependencies or tools.
NEW or CHANGED dependencies since the last major release are **bold**.
* Build system: [CMake](https://cmake.org/) 3.12 or newer (tested through 3.24)
* Build system: [CMake](https://cmake.org/) 3.12 or newer (tested through 3.26)
* A suitable C++14 or C++17 compiler to build OSL itself, which may be any of:
- GCC 6.1 or newer (tested through gcc 12.1)
- Clang 3.4 or newer (tested through clang 15)
- 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.
@@ -41,13 +41,14 @@ NEW or CHANGED dependencies since the last major release are **bold**.
DYLD_LIBRARY_PATH on OS X).
* [LLVM](http://www.llvm.org) 9, 10, 11, 12, 13, 14, or 15, including
clang libraries.
clang libraries. LLVM 16 doesn't work yet, we need to make changes
on the OSL side to be compatible.
* (optional) For GPU rendering on NVIDIA GPUs:
* [OptiX](https://developer.nvidia.com/rtx/ray-tracing/optix) 7.0 or higher.
* [Cuda](https://developer.nvidia.com/cuda-downloads) 8.0 or higher.
* [Boost](https://www.boost.org) 1.55 or newer (tested through boost 1.80)
* [Boost](https://www.boost.org) 1.55 or newer (tested through boost 1.81)
* [Ilmbase or Imath](https://github.com/AcademySoftwareFoundation/openexr) 2.3
or newer (recommended: 2.4 or higher; tested through 3.1)
* [Flex](https://github.com/westes/flex) 2.5.35 or newer and
@@ -55,7 +56,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/)
* [PugiXML](http://pugixml.org/) >= 1.8 (we have tested through 1.13).
* (optional) [Partio](https://www.disneyanimation.com/technology/partio.html)
If it is not found at build time, the OSL `pointcloud` functions will not
be operative.
@@ -64,8 +65,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) Qt >= 5.6 (tested through 5.15). If not found at build time,
the `osltoy` application will be disabled.
* (optional) Qt5 >= 5.6 or Qt6 (tested Qt5 through 5.15 and Qt6 through 6.4).
If not found at build time, the `osltoy` application will be disabled.
+5 -2
View File
@@ -209,7 +209,10 @@ ifneq (${BUILD_MISSING_DEPS},)
endif
ifneq (${USE_OPTIX},)
MY_CMAKE_FLAGS += -DUSE_OPTIX:BOOL=${USE_OPTIX}
MY_CMAKE_FLAGS += -DOSL_USE_OPTIX:BOOL=${USE_OPTIX}
endif
ifneq (${OSL_USE_OPTIX},)
MY_CMAKE_FLAGS += -DOSL_USE_OPTIX:BOOL=${OSL_USE_OPTIX}
endif
ifneq (${USE_PYTHON},)
@@ -397,7 +400,7 @@ help:
@echo " USE_SIMD=arch Build with SIMD support (comma-separated choices:"
@echo " 0, sse2, sse3, ssse3, sse4.1, sse4.2, f16c,"
@echo " avx, avx2, avx512f)"
@echo " USE_OPTIX=1 Build the OptiX test renderer"
@echo " OSL_USE_OPTIX=1 Build the OptiX test renderer"
@echo " USE_BATCHED=targets Build batched SIMD execution of shaders for (comma-separated choices:"
@echo " 0, b8_AVX, b8_AVX2, b8_AVX2_noFMA,"
@echo " b8_AVX512, b8_AVX512_noFMA,"
+22 -16
View File
@@ -225,8 +225,7 @@ adding OSL support):
* [Blender/Cycles](https://docs.blender.org/manual/en/dev/render/shader_nodes/osl.html)
* [Chaos Group: V-Ray](https://www.chaosgroup.com/)
* [Pixar: PhotoRealistic RenderMan RIS](https://renderman.pixar.com)
* [Isotropix: Clarisse](http://www.isotropix.com/clarisse)
* [Isotropix: Angie](http://www.isotropix.com/angie)
* Isotropix: [Clarisse iFX](https://www.isotropix.com/products/clarisse/ifx) / [Clarisse BUiLDER](https://www.isotropix.com/products/clarisse/builder) / [Angie](https://www.isotropix.com/products/angie)
* [Autodesk Beast](http://www.autodesk.com/products/beast/overview)
* [Appleseed](http://appleseedhq.net)
* [Animal Logic: Glimpse renderer](https://www.fxguide.com/featured/a-glimpse-at-animal-logic/)
@@ -390,8 +389,9 @@ Films using OSL (grouped by year of release date):
Last Night in Soho,
Ghostbusters: Afterlife,
Spider-Man 3: No Way Home,
Matrix Resurrections
* **(2022 / upcoming)**
Matrix Resurrections,
Sing 2
* **(2022)**
Hotel Transylvania 4: Transformania,
Death on the Nile,
Uncharted,
@@ -404,11 +404,15 @@ Films using OSL (grouped by year of release date):
Thor: Love and Thunder,
The Sea Beast,
DC League of Super Pets,
Minions: Rise of Gru,
Bullet Train,
Slumberland,
Glass Onion
* **(2023 / upcoming)**
Ant-Man and the Wasp: Quantumania,
...
Building and Installation
-------------------------
@@ -481,18 +485,20 @@ The current project leadership is documented in the
Many people have contributed features, bug fixes, and other changes to OSL
over the years: Steve Agland, Shane Ambler, Martijn Berger, Farchad
Bidgolirad, Nicholas Bishop, Solomon Boulos, Stefan Bruens, Stefan Büttner,
Matthaus G. Chajdas, Clark Chen, Alejandro Conty, Dieter De Baets, Thomas
Dinges, Mads Drøschler, Luke Emrose, Louis Feng, Mark Final, Henri Fousse,
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
Matthaus G. Chajdas, Clark Chen, Alejandro Conty, Damien Courtois, Dieter De
Baets, Thomas Dinges, Daniel Dresser, Mads Drøschler, Peter Ellerington, Luke
Emrose, Louis Feng, Mark Final, Henri Fousse, Stephen Friedman, Syoyo Fujita,
Tim Grant, Larry Gritz, Nicolas Guiard, Euan Haahr, Derek Haase, Sven-Hendrik
Haase, John Haddon, Niklas Harrysson, Daniel Heckenberg, Chris Hellmuth,
Adrien Herubel, Dan Horák, Thiago Ize, Matt Johnson, Ronan Keryell, Chris
Kulla, Elvic Liang, Max Liani, Adam Martinez, John Mertic, Bastien Montagne,
Steena Monteiro, 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.)
Steena Monteiro, Patrick Mours, Alexis Oblet, Erich Ocean, Mikko Ohtamaa, Jino
Park, Alexei Pawlow, Jay Reynolds, Declan Russell, Benoit Ruiz, Patrick
Scheibe, Alex Schworer, Jonathan Scruggs, Sergey Sharybin, Mark Sisson, Sandip
Shukla, Cliff Stein, Stephan Steinbach, Luya Tshimbalanga, Esteban Tovagliari,
Brecht Van Lommel, Alexander von Knorring, Alex Wells, Roman Zulak. (Listed
alphabetically; if we've left anybody out, it is inadvertent, please let us
know.)
We cannot possibly express sufficient gratitude to the managers at Sony
Pictures Imageworks who allowed this project to proceed, supported it
+11 -7
View File
@@ -33,7 +33,7 @@ endif # endif ${SP_OS}
MY_CMAKE_FLAGS += -DSP_OS=${SP_OS}
MY_CMAKE_FLAGS += -DSPI_COMPILER_PLATFORM=${SPI_COMPILER_PLATFORM}
MY_CMAKE_FLAGS += -DEXTRA_CPP_ARGS:STRING="-DOSL_SPI=1" -DOSL_SITE:STRING=spi
MY_CMAKE_FLAGS += -DOSL_SITE:STRING=spi
MY_CMAKE_FLAGS += -DSPI_TESTS=1
MY_CMAKE_FLAGS += -DOSL_NAMESPACE_INCLUDE_PATCH=1
REZ_PACKAGE_ROOT ?= /shots/spi/home/software/packages
@@ -147,14 +147,14 @@ ifeq (${SP_OS}, rhel7)
endif
# Cuda/OptiX
USE_OPTIX ?= 1
OSL_USE_OPTIX ?= 1
CUDA_VERSION ?= 11.1.1
OPTIX_VERSION ?= 7.2.0
# CUDA_TOOLKIT_ROOT_DIR = $(shell rez-env -b cuda-${CUDA_VERSION} ${SPI_COMPILER_PLATFORM} -c "echo '$CUDA_TOOLKIT_ROOT'")
CUDA_TOOLKIT_ROOT_DIR ?= /shots/spi/home/lib/arnold/rhel7/cuda_${CUDA_VERSION}
OptiX_ROOT ?= /shots/spi/home/lib/arnold/rhel7/optix_${OPTIX_VERSION}
OPTIXHOME = ${OptiX_ROOT}
MY_CMAKE_FLAGS += -DUSE_OPTIX=${USE_OPTIX} \
MY_CMAKE_FLAGS += -DOSL_USE_OPTIX=${OSL_USE_OPTIX} \
-DCUDA_TOOLKIT_ROOT_DIR=${CUDA_TOOLKIT_ROOT_DIR} \
-DCUDA_EXTRA_LIBS=${CUDA_EXTRA_LIBS} \
-DOPTIXHOME=${OPTIXHOME} -DOPTIX_EXTRA_LIBS=lzma
@@ -189,6 +189,10 @@ else ifeq (${platform}, macosx)
MY_CMAKE_FLAGS += \
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@15/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@15/bin/clang++
else ifeq (${COMPILER},clang16)
MY_CMAKE_FLAGS += \
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@16/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@16/bin/clang++
else ifeq (${COMPILER},clang)
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
else ifeq (${COMPILER},gcc)
@@ -196,13 +200,13 @@ else ifeq (${platform}, macosx)
else ifeq (${COMPILER},)
# default compiler is clang, taken from the LLVM directory
MY_CMAKE_FLAGS += \
-DCMAKE_C_COMPILER=${LLVM_DIRECTORY}/bin/clang \
-DCMAKE_CXX_COMPILER=${LLVM_DIRECTORY}/bin/clang++
-DCMAKE_C_COMPILER=${LLVM_ROOT}/bin/clang \
-DCMAKE_CXX_COMPILER=${LLVM_ROOT}/bin/clang++
else ifeq (${COMPILER},llvm)
# "llvm" means "use the clang from our llvm"
MY_CMAKE_FLAGS += \
-DCMAKE_C_COMPILER=${LLVM_DIRECTORY}/bin/clang \
-DCMAKE_CXX_COMPILER=${LLVM_DIRECTORY}/bin/clang++
-DCMAKE_C_COMPILER=${LLVM_ROOT}/bin/clang \
-DCMAKE_CXX_COMPILER=${LLVM_ROOT}/bin/clang++
endif
# end generic OSX
-3
View File
@@ -23,6 +23,3 @@ sonar.exclusions=src/include/OSL/Imath/*.h,src/build-scripts/*
# C/C++ analyzer properties
sonar.cfamily.build-wrapper-output=build/bw_output
sonar.cfamily.gcov.reportsPath=_coverage
sonar.cfamily.cache.enabled=true
sonar.cfamily.cache.path=/tmp/sonarcache
+1 -1
View File
@@ -14,7 +14,7 @@ uname
if [[ `uname` == "Linux" ]] ; then
LLVM_VERSION=${LLVM_VERSION:=13.0.0}
LLVM_VERSION=${LLVM_VERSION:=14.0.0}
LLVM_INSTALL_DIR=${LLVM_INSTALL_DIR:=${PWD}/llvm-install}
if [[ "$GITHUB_WORKFLOW" != "" ]] ; then
LLVM_DISTRO_NAME=${LLVM_DISTRO_NAME:=ubuntu-18.04}
+11 -6
View File
@@ -18,8 +18,8 @@ if [[ "$ASWF_ORG" != "" ]] ; then
#ls /etc/yum.repos.d
sudo yum install -y giflib giflib-devel && true
# sudo yum install -y ffmpeg ffmpeg-devel && true
sudo /usr/bin/yum install -y giflib giflib-devel && true
# sudo /usr/bin/yum install -y ffmpeg ffmpeg-devel && true
if [[ "${CONAN_LLVM_VERSION}" != "" ]] ; then
mkdir conan
@@ -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 yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic-2022.1.0-3768
sudo /usr/bin/yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic-2022.1.0-3768
# Because multiple (possibly newer) versions of oneAPI may be installed,
# use a config file to specify compiler and tbb versions
# NOTE: oneAPI components have independent version numbering.
@@ -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,8 +73,13 @@ else
libpugixml-dev \
libopencolorio-dev
time sudo apt-get -q install -y \
qt5-default || /bin/true
if [[ "${QT_VERSION:-5}" == "5" ]] ; then
time sudo apt-get -q install -y \
qt5-default || /bin/true
elif [[ "${QT_VERSION}" == "6" ]] ; then
time sudo apt-get -q install -y \
qt6-base-dev || /bin/true
fi
export CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu:$CMAKE_PREFIX_PATH
+8 -6
View File
@@ -19,6 +19,7 @@ if [[ `which brew` == "" ]] ; then
exit 1
fi
set -ex
if [[ "$DO_BREW_UPDATE" != "" ]] ; then
brew update >/dev/null
@@ -30,20 +31,21 @@ 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 ilmbase openexr
brew install --display-times -q imath openexr
#brew install --display-times -q freetype
brew install --display-times -q opencolorio partio pugixml
brew install --display-times -q --overwrite --force opencolorio || true
brew install --display-times -q partio pugixml
brew install --display-times -q pybind11 numpy || true
brew install --display-times -q tbb || true
brew install --display-times -q flex bison
brew install --display-times -q llvm${LLVMBREWVER}
brew install --display-times -q qt
brew install --display-times -q qt${QT_BREW_VERSION}
echo ""
echo "After brew installs:"
+6 -6
View File
@@ -121,11 +121,11 @@ endif ()
# give more fine-grained control for hiding symbols, because sometimes
# dependent libraries may not be well behaved and need extra hiding.
#
set (CXX_VISIBILITY_PRESET "hidden" CACHE STRING "Symbol visibility (hidden or default")
set (CMAKE_CXX_VISIBILITY_PRESET "hidden" CACHE STRING "Symbol visibility (hidden or default")
option (VISIBILITY_INLINES_HIDDEN "Hide symbol visibility of inline functions" ON)
set (VISIBILITY_MAP_FILE "${PROJECT_SOURCE_DIR}/src/build-scripts/hidesymbols.map" CACHE FILEPATH "Visibility map file")
set (C_VISIBILITY_PRESET ${CXX_VISIBILITY_PRESET})
if (${CXX_VISIBILITY_PRESET} STREQUAL "hidden" AND VISIBILITY_MAP_FILE AND
set (CMAKE_C_VISIBILITY_PRESET ${CMAKE_CXX_VISIBILITY_PRESET})
if (${CMAKE_CXX_VISIBILITY_PRESET} STREQUAL "hidden" AND VISIBILITY_MAP_FILE AND
(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG) AND
(CMAKE_SYSTEM_NAME MATCHES "Linux|kFreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "GNU"))
# Linux/FreeBSD/Hurd: also hide all the symbols of dependent libraries
@@ -342,17 +342,17 @@ set (USE_BATCHED "" CACHE STRING "Build batched SIMD shader execution for (0, b8
option (VEC_REPORT "Enable compiler's reporting system for vectorization" OFF)
set (BATCHED_SUPPORT_DEFINES "")
set (BATCHED_TARGET_LIBS "")
set (BUILD_BATCHED False)
set (OSL_BUILD_BATCHED 0)
if (NOT USE_BATCHED STREQUAL "")
message (STATUS "Compiling with batched SIMD targets ${USE_BATCHED}")
if (NOT USE_BATCHED STREQUAL "0")
set (BUILD_BATCHED 1)
set (OSL_BUILD_BATCHED 1)
string (REPLACE "," ";" BATCHED_TARGET_LIST ${USE_BATCHED})
foreach (batched_target ${BATCHED_TARGET_LIST})
if (VERBOSE)
message (STATUS "BATCHED target: ${batched_target}")
endif ()
set (BATCHED_SUPPORT_DEFINES ${BATCHED_SUPPORT_DEFINES} "__OSL_SUPPORTS_${batched_target}")
list (APPEND BATCHED_SUPPORT_DEFINES "__OSL_SUPPORTS_${batched_target}")
endforeach()
else ()
message (STATUS "Compiling with NO batched SIMD targets, USE_BATCHED=0")
+6
View File
@@ -21,6 +21,12 @@ function ( NVCC_COMPILE cuda_src extra_headers ptx_generated extra_nvcc_args )
list (TRANSFORM OpenImageIO_INCLUDES PREPEND -I
OUTPUT_VARIABLE ALL_OpenImageIO_INCLUDES)
if (${LLVM_VERSION} VERSION_GREATER_EQUAL 15.0)
# Until we fully support opaque pointers, we need to disable
# them when using LLVM 15.
list (APPEND LLVM_COMPILE_FLAGS -Xclang -no-opaque-pointers)
endif ()
add_custom_command ( OUTPUT ${cuda_ptx}
COMMAND ${CUDA_NVCC_EXECUTABLE}
"-I${OPTIX_INCLUDES}"
+54 -38
View File
@@ -115,6 +115,7 @@ checked_find_package (pugixml REQUIRED
# LLVM library setup
checked_find_package (LLVM REQUIRED
VERSION_MIN 9.0
VERSION_MAX 15.9
PRINT LLVM_SYSTEM_LIBRARIES CLANG_LIBRARIES)
# ensure include directory is added (in case of non-standard locations
include_directories (BEFORE SYSTEM "${LLVM_INCLUDES}")
@@ -144,6 +145,19 @@ 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)
@@ -153,58 +167,61 @@ find_python ()
# Qt -- used for osltoy
set (qt5_modules Core Gui Widgets)
if (OPENGL_FOUND)
list (APPEND qt5_modules OpenGL)
endif ()
option (USE_QT "Use Qt if found" ON)
checked_find_package (Qt5 COMPONENTS ${qt5_modules})
if (USE_QT AND NOT Qt5_FOUND AND APPLE)
message (STATUS " If you think you installed qt5 with Homebrew and it still doesn't work,")
message (STATUS " try: export PATH=/usr/local/opt/qt5/bin:$PATH")
if (USE_QT)
checked_find_package (Qt6 COMPONENTS Core Gui Widgets OpenGLWidgets)
if (NOT Qt6_FOUND)
checked_find_package (Qt5 COMPONENTS Core Gui Widgets OpenGL)
endif ()
if (NOT Qt5_FOUND AND NOT Qt6_FOUND AND APPLE)
message (STATUS " If you think you installed qt with Homebrew and it still doesn't work,")
message (STATUS " try: export PATH=/usr/local/opt/qt/bin:$PATH")
endif ()
endif ()
# CUDA setup
if (USE_CUDA OR USE_OPTIX)
if (NOT CUDA_TOOLKIT_ROOT_DIR AND NOT $ENV{CUDA_TOOLKIT_ROOT_DIR} STREQUAL "")
set (CUDA_TOOLKIT_ROOT_DIR $ENV{CUDA_TOOLKIT_ROOT_DIR})
endif ()
if (OSL_USE_OPTIX)
if (USE_LLVM_BITCODE)
if (NOT CUDA_TOOLKIT_ROOT_DIR AND NOT $ENV{CUDA_TOOLKIT_ROOT_DIR} STREQUAL "")
set (CUDA_TOOLKIT_ROOT_DIR $ENV{CUDA_TOOLKIT_ROOT_DIR})
endif ()
if (NOT CUDA_FIND_QUIETLY OR NOT OptiX_FIND_QUIETLY)
message (STATUS "CUDA_TOOLKIT_ROOT_DIR = ${CUDA_TOOLKIT_ROOT_DIR}")
endif ()
if (NOT CUDA_FIND_QUIETLY OR NOT OptiX_FIND_QUIETLY)
message (STATUS "CUDA_TOOLKIT_ROOT_DIR = ${CUDA_TOOLKIT_ROOT_DIR}")
endif ()
checked_find_package (CUDA REQUIRED
VERSION_MIN 8.0
PRINT CUDA_INCLUDES)
set (CUDA_INCLUDES ${CUDA_TOOLKIT_ROOT_DIR}/include)
include_directories (BEFORE "${CUDA_INCLUDES}")
checked_find_package (CUDA REQUIRED
VERSION_MIN 8.0
PRINT CUDA_INCLUDES)
set (CUDA_INCLUDES ${CUDA_TOOLKIT_ROOT_DIR}/include)
include_directories (BEFORE "${CUDA_INCLUDES}")
STRING (FIND ${LLVM_TARGETS} "NVPTX" nvptx_index)
if (NOT ${nvptx_index} GREATER -1)
message (FATAL_ERROR "NVPTX target is not available in the provided LLVM build")
endif()
STRING (FIND ${LLVM_TARGETS} "NVPTX" nvptx_index)
if (NOT ${nvptx_index} GREATER -1)
message (FATAL_ERROR "NVPTX target is not available in the provided LLVM build")
endif()
set (CUDA_LIB_FLAGS "--cuda-path=${CUDA_TOOLKIT_ROOT_DIR}")
set (CUDA_LIB_FLAGS "--cuda-path=${CUDA_TOOLKIT_ROOT_DIR}")
find_library(cuda_lib NAMES cudart
PATHS "${CUDA_TOOLKIT_ROOT_DIR}/lib64" "${CUDA_TOOLKIT_ROOT_DIR}/x64"
REQUIRED)
set(CUDA_LIBRARIES ${cuda_lib})
find_library(cuda_lib NAMES cudart
PATHS "${CUDA_TOOLKIT_ROOT_DIR}/lib64" "${CUDA_TOOLKIT_ROOT_DIR}/x64" "${CUDA_TOOLKIT_ROOT_DIR}/lib/x64"
REQUIRED)
set(CUDA_LIBRARIES ${cuda_lib})
# testrender & testshade need libnvrtc
if ("${CUDA_VERSION}" VERSION_GREATER_EQUAL "10.0")
find_library(nvrtc_lib NAMES nvrtc
PATHS "${CUDA_TOOLKIT_ROOT_DIR}/lib64" "${CUDA_TOOLKIT_ROOT_DIR}/x64"
REQUIRED)
set(CUDA_LIBRARIES ${CUDA_LIBRARIES} ${nvrtc_lib})
# testrender & testshade need libnvrtc
if ("${CUDA_VERSION}" VERSION_GREATER_EQUAL "10.0")
find_library(nvrtc_lib NAMES nvrtc
PATHS "${CUDA_TOOLKIT_ROOT_DIR}/lib64" "${CUDA_TOOLKIT_ROOT_DIR}/x64" "${CUDA_TOOLKIT_ROOT_DIR}/lib/x64"
REQUIRED)
set(CUDA_LIBRARIES ${CUDA_LIBRARIES} ${nvrtc_lib})
set(CUDA_EXTRA_LIBS ${CUDA_EXTRA_LIBS} dl)
set(CUDA_EXTRA_LIBS ${CUDA_EXTRA_LIBS} dl)
endif()
endif()
# OptiX setup
if (USE_OPTIX)
if (OSL_USE_OPTIX AND OSL_BUILD_TESTS)
checked_find_package (OptiX REQUIRED
VERSION_MIN 7.0)
include_directories (BEFORE "${OPTIX_INCLUDES}")
@@ -219,7 +236,6 @@ if (USE_CUDA OR USE_OPTIX)
target_compile_definitions (${TARGET} PRIVATE "-DPTX_PATH=\"${OSL_PTX_INSTALL_DIR}\"")
target_link_libraries (${TARGET} PRIVATE ${CUDA_LIBRARIES} ${CUDA_EXTRA_LIBS} ${OPTIX_LIBRARIES} ${OPTIX_EXTRA_LIBS})
endfunction()
else ()
function (osl_optix_target TARGET)
endfunction()
+8 -2
View File
@@ -23,7 +23,13 @@
# try to find llvm-config, with a specific version if specified
if (LLVM_DIRECTORY)
set (LLVM_CONFIG_PATH_HINTS "${LLVM_DIRECTORY}/bin")
list (APPEND LLVM_CONFIG_PATH_HINTS "${LLVM_DIRECTORY}/bin")
endif ()
if (LLVM_ROOT)
list (APPEND LLVM_CONFIG_PATH_HINTS "${LLVM_ROOT}/bin")
endif ()
if (DEFINED ENV{LLVM_ROOT})
list (APPEND LLVM_CONFIG_PATH_HINTS "$ENV{LLVM_ROOT}/bin")
endif ()
list (APPEND LLVM_CONFIG_PATH_HINTS
"/usr/local/opt/llvm/${LLVM_VERSION}/bin/"
@@ -121,7 +127,7 @@ endif ()
foreach (COMPONENT clangFrontend clangDriver clangSerialization
clangParse clangSema clangAnalysis clangAST clangBasic
clangEdit clangLex)
clangEdit clangLex clangSupport)
find_library ( _CLANG_${COMPONENT}_LIBRARY
NAMES ${COMPONENT}
PATHS ${LLVM_LIB_DIR})
+3 -6
View File
@@ -20,12 +20,9 @@ macro (find_python)
# Attempt to find the desired version, but fall back to other
# additional versions.
unset (_req)
if (USE_PYTHON)
set (_req REQUIRED)
if (PYTHON_VERSION)
list (APPEND _req EXACT)
endif ()
set (_req REQUIRED)
if (PYTHON_VERSION)
list (APPEND _req EXACT)
endif ()
checked_find_package (Python ${PYTHON_VERSION}
${_req}
+15 -10
View File
@@ -71,6 +71,10 @@ macro (add_one_testsuite testname testsrcdir)
set_tests_properties (${testname} PROPERTIES LABELS render
PROCESSORS 4 COST 10 TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
endif ()
# For debug builds, render tests are very slow, so give them a longer timeout
if (${testname} MATCHES "render-" AND ${CMAKE_BUILD_TYPE} STREQUAL Debug)
set_tests_properties (${testname} PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
endif ()
# Some labeling for fun
if (${testname} MATCHES "^texture")
set_tests_properties (${testname} PROPERTIES LABELS texture
@@ -139,14 +143,11 @@ 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
# run all tests with OptiX, even if there's no OPTIX marker.
if (USE_OPTIX
if (OSL_USE_OPTIX
AND (EXISTS "${_testsrcdir}/OPTIX" OR test_all_optix OR _testname MATCHES "optix")
AND NOT EXISTS "${_testsrcdir}/NOOPTIX"
AND NOT EXISTS "${_testsrcdir}/NOOPTIX-FIXME"
@@ -161,7 +162,7 @@ macro ( TESTSUITE )
ENV TESTSHADE_OPT=2 TESTSHADE_OPTIX=1 )
endif ()
if (BUILD_BATCHED)
if (OSL_BUILD_BATCHED)
# When building for Batched support, also run it in Batched mode
# if there is an BATCHED marker file in the directory.
# If an environment variable $TESTSUITE_BATCHED is nonzero, then
@@ -236,7 +237,8 @@ macro (osl_add_all_tests)
bug-array-heapoffsets bug-locallifetime bug-outputinit
bug-param-duplicate bug-peep bug-return
calculatenormal-reg
cellnoise closure closure-array color color-reg colorspace comparison
cellnoise closure closure-array closure-parameters closure-zero closure-conditional
color color-reg colorspace comparison
complement-reg compile-buffer compassign-reg
component-range
control-flow-reg connect-components
@@ -297,6 +299,7 @@ macro (osl_add_all_tests)
oslc-err-struct-dup oslc-err-struct-print
oslc-err-type-as-variable
oslc-err-unknown-ctr
oslc-literalfold
oslc-pragma-warnerr
oslc-warn-commainit
oslc-variadic-macro
@@ -308,7 +311,8 @@ macro (osl_add_all_tests)
pragma-nowarn
printf-reg
printf-whole-array
raytype raytype-reg raytype-specialized regex-reg reparam
raytype raytype-reg raytype-specialized regex-reg
reparam reparam-arrays
render-background render-bumptest
render-cornell render-furnace-diffuse
render-mx-furnace-burley-diffuse
@@ -322,6 +326,7 @@ macro (osl_add_all_tests)
render-mx-sheen
render-microfacet render-oren-nayar
render-uv render-veachmis render-ward
render-raytypes
select select-reg shaderglobals shortcircuit
smoothstep-reg
spline spline-reg splineinverse splineinverse-ident
@@ -351,7 +356,7 @@ macro (osl_add_all_tests)
transform transform-reg transformc transformc-reg trig trig-reg
typecast
unknown-instruction
userdata userdata-passthrough
userdata userdata-custom userdata-passthrough
vararray-connect vararray-default
vararray-deserialize vararray-param
vecctr vector vector-reg
@@ -383,7 +388,7 @@ macro (osl_add_all_tests)
endif()
# Only run pointcloud tests if Partio is found
if (PARTIO_FOUND)
if (partio_FOUND)
TESTSUITE ( pointcloud pointcloud-fold )
endif ()
@@ -393,7 +398,7 @@ macro (osl_add_all_tests)
endif ()
# Some regression tests have a lot of combinations and may need more time to finish
if (BUILD_BATCHED)
if (OSL_BUILD_BATCHED)
set_tests_properties (arithmetic-reg.regress.batched.opt
PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
set_tests_properties (transform-reg.regress.batched.opt
+63 -34
View File
@@ -2631,27 +2631,6 @@ and proceeds to the next iteration of the loop.
\section{Functions}
\label{sec:functions}
\subsection{Function calls}
\label{sec:syntax:functioncalls}
\index{function calls}
Function calls are very similar to C and related programming languages:
\begin{tabbing}
\hspace{0.5in} \= \hspace{0.3in} \= \kill
\> \emph{functionname} {\cf (} \emph{arg1} {\cf ,} ... {\cf ,} \emph{argn} {\cf )} \\
\end{tabbing}
If the function returns a value (not \void), you may use its value as
an expression. It is fine to completely ignore the value of even
a non-\void function.
In \langname, all arguments are passed by reference. This generally
will not be noticeably different from C-style ``pass by value''
semantics, except if you pass the same variable as two separate
arguments to a function that modifies an argument's value.
\subsection{Function definitions}
\label{sec:syntax:functiondefinitions}
\index{functions!definitions}
@@ -2699,6 +2678,35 @@ passing an {\cf int} when the function expects a {\cf float}, or passing a
{\cf float} when the function expects a \color), and finally by trying to
match the return value to the type of variable the result is assigned to.
\subsection{Function calls}
\label{sec:syntax:functioncalls}
\index{function calls}
Function calls are very similar to C and related programming languages:
\begin{tabbing}
\hspace{0.5in} \= \hspace{0.3in} \= \kill
\> \emph{functionname} {\cf (} \emph{arg1} {\cf ,} ... {\cf ,} \emph{argn} {\cf )} \\
\end{tabbing}
If the function returns a value (not \void), you may use its value as
an expression. It is fine to completely ignore the value of even
a non-\void function.
In \langname, all arguments are passed by reference. This generally
will not be noticeably different from C-style ``pass by value''
semantics, except if you pass the same variable as two separate
arguments to a function that modifies an argument's value.
Certain functions allow optional arguments to be passed.
Optional arguments are key-value pairs with the key passed as an
argument and the associated value passed as the subsequent argument:
\begin{tabbing}
\hspace{0.5in} \= \hspace{0.3in} \= \kill
\> \emph{functionname} {\cf (} \emph{arg1} {\cf ,} ... {\cf ,} \emph{argn} {\cf ,} \emph{"optionalkey"} {\cf ,} \emph{optionalvalue} {\cf ,} ... {\cf )} \\
\end{tabbing}
\subsection{Operator overloading}
\label{sec:syntax:operatoroverloading}
\index{operator overloading}
@@ -4083,8 +4091,8 @@ are assigned to a \float or a \color (or type cast to one of those)
determines whether the texture lookup is a single channel or three
channels.
The 2D lookup coordinate(s) may be followed by optional token/value
arguments that control the behavior of {\cf texture()}:
The 2D lookup coordinate(s) may be followed by optional key-value
arguments (see Section~\ref{sec:syntax:functioncalls}) that control the behavior of {\cf texture()}:
\apiitem{"blur", <float>}
\vspace{12pt}
@@ -5599,7 +5607,7 @@ forms of the function with no object name, or if the object name is the
empty string \qkw{}, the renderer will first search
per-object attributes on the current object (or interpolated variables
with that name attached to the object), then if not found it will search
searching global scene-wide attributes.
global scene-wide attributes.
If the attribute is found and can be converted to the type of
\emph{destination}, the attribute's value will be stored in
@@ -5901,17 +5909,38 @@ view-dependence into shaders.
The return value is 0 if the ray missed all geometry, 1 if it hit
anything within the distance range.
Optional parameters include:
The following optional key-value arguments
(see Section~\ref{sec:syntax:functioncalls}) can be passed:
\begin{tabular}{p{1.2in} p{0.5in} p{3.2in}}
\qkw{mindist} & {\cf float} & Minimum hit distance (default: zero) \\
\qkw{maxdist} & {\cf float} & Maximum hit distance (default: infinite) \\
\qkw{shade} & {\cf int} & Whether objects hit will be shaded
(default: 0) \\
\qkw{traceset} & {\cf string} & An optional named set of objects to
ray trace (if preceded by a `{\cf -}'
character, it means to exclude that set).
\end{tabular}
\apiitem{"mindist", <float>}
\vspace{12pt}
The minimum hit distance (default: 0).
The units of the {\cf "mindist"} and {\cf "maxdist"} are determined by the renderer
and are sometimes defined by the dir vector, which can lead to unexpected
behavior. So, generally, clearly written and portable shaders should pass
a unit length (see Section~\ref{sec:stdlib:geom}) dir vector.
\apiend
\vspace{-16pt}
\apiitem{"mindist", <float>}
\vspace{12pt}
The maximum hit distance (default: infinite).
\apiend
\vspace{-16pt}
\apiitem{"shade", <int>}
\vspace{12pt}
Defines whether objects hit will be shaded (default: 0).
\apiend
\vspace{-16pt}
\apiitem{"traceset", <string>}
\vspace{12pt}
An optional named set of objects to ray trace (if preceded by a `{\cf -}'
character, it means to exclude that set).
\apiend
\vspace{-16pt}
Information about the closest object hit by the ray may be retrieved
using \\ {\cf getmessage("trace",...)} (see Section~\ref{sec:getmessage}).
+35 -32
View File
@@ -82,12 +82,13 @@ public:
/// Return a Mask with lanes set to true if ok, false if the named matrix
/// is not known.
virtual Mask get_matrix(BatchedShaderGlobals* bsg, Masked<Matrix44> wresult,
ustring from, Wide<const float> wtime)
ustringhash from, Wide<const float> wtime)
{
return Mask(false);
}
virtual Mask get_matrix(BatchedShaderGlobals* bsg, Masked<Matrix44> result,
Wide<const ustring> wfrom, Wide<const float> wtime);
Wide<const ustringhash> wfrom,
Wide<const float> wtime);
virtual bool is_overridden_get_matrix_WmWsWf() const = 0;
@@ -97,12 +98,12 @@ public:
/// particular renderer may have a better technique and overload the
/// implementation.
virtual Mask get_inverse_matrix(BatchedShaderGlobals* bsg,
Masked<Matrix44> wresult, ustring to,
Masked<Matrix44> wresult, ustringhash to,
Wide<const float> wtime);
virtual bool is_overridden_get_inverse_matrix_WmsWf() const = 0;
virtual Mask get_inverse_matrix(BatchedShaderGlobals* bsg,
Masked<Matrix44> wresult,
Wide<const ustring> wto,
Wide<const ustringhash> wto,
Wide<const float> wtime);
virtual bool is_overridden_get_inverse_matrix_WmWsWf() const = 0;
@@ -124,22 +125,23 @@ public:
/// specified (object == ustring()), then the renderer should search *first*
/// for the attribute on the currently shaded object, and next, if
/// unsuccessful, on the currently shaded "scene".
virtual Mask get_attribute(BatchedShaderGlobals* bsg, ustring object,
ustring name, MaskedData wval)
virtual Mask get_attribute(BatchedShaderGlobals* bsg, ustringhash object,
ustringhash name, MaskedData wval)
{
return Mask(false);
}
/// Similar to get_attribute(); this method will fetch the 'index'
/// element of an attribute array.
virtual Mask get_array_attribute(BatchedShaderGlobals* bsg, ustring object,
ustring name, int index, MaskedData wval)
virtual Mask get_array_attribute(BatchedShaderGlobals* bsg,
ustringhash object, ustringhash name,
int index, MaskedData wval)
{
return Mask(false);
}
virtual bool get_attribute_uniform(BatchedShaderGlobals* bsg,
ustring object, ustring name,
ustringhash object, ustringhash name,
RefData val)
{
return false;
@@ -148,8 +150,9 @@ public:
/// Similar to get_attribute(); this method will fetch the 'index'
/// element of an attribute array.
virtual bool get_array_attribute_uniform(BatchedShaderGlobals* bsg,
ustring object, ustring name,
int index, RefData val)
ustringhash object,
ustringhash name, int index,
RefData val)
{
return false;
}
@@ -159,7 +162,7 @@ public:
/// as well. It is assumed the results are varying and returns Mask
// with its bit set to off if no user-data with the given name and type was
/// found.
virtual Mask get_userdata(ustring name, BatchedShaderGlobals* bsg,
virtual Mask get_userdata(ustringhash name, BatchedShaderGlobals* bsg,
MaskedData wval)
{
return Mask(false);
@@ -206,7 +209,7 @@ public:
/// error.
///
virtual Mask
texture(ustring filename, TextureSystem::TextureHandle* texture_handle,
texture(ustringhash filename, TextureSystem::TextureHandle* texture_handle,
TextureSystem::Perthread* texture_thread_info,
const BatchedTextureOptions& options, BatchedShaderGlobals* bsg,
Wide<const float> ws, Wide<const float> wt, Wide<const float> wdsdx,
@@ -240,7 +243,7 @@ public:
/// messages (in case of failure, when the function returns false) will
/// be stored there, leaving it up to the caller/shader to handle the
/// error.
virtual Mask texture3d(ustring filename,
virtual Mask texture3d(ustringhash filename,
TextureSystem::TextureHandle* texture_handle,
TextureSystem::Perthread* texture_thread_info,
const BatchedTextureOptions& options,
@@ -273,7 +276,7 @@ public:
/// messages (in case of failure, when the function returns false) will
/// be stored there, leaving it up to the caller/shader to handle the
/// error.
virtual Mask environment(ustring filename,
virtual Mask environment(ustringhash filename,
TextureSystem::TextureHandle* texture_handle,
TextureSystem::Perthread* texture_thread_info,
const BatchedTextureOptions& options,
@@ -300,12 +303,12 @@ public:
virtual TextureSystem::TextureHandle* resolve_udim_uniform(
BatchedShaderGlobals* bsg, TexturePerthread* texture_thread_info,
ustring filename, TextureSystem::TextureHandle* texture_handle, float S,
float T);
ustringhash filename, TextureSystem::TextureHandle* texture_handle,
float S, float T);
virtual void resolve_udim(BatchedShaderGlobals* bsg,
TexturePerthread* texture_thread_info,
ustring filename,
ustringhash filename,
TextureSystem::TextureHandle* texture_handle,
Wide<const float> wS, Wide<const float> wT,
Masked<TextureSystem::TextureHandle*> wresult);
@@ -313,8 +316,8 @@ public:
// Assumes any UDIM has been resolved already
virtual bool get_texture_info_uniform(
BatchedShaderGlobals* bsg, TexturePerthread* texture_thread_info,
ustring filename, TextureSystem::TextureHandle* texture_handle,
int subimage, ustring dataname, RefData val);
ustringhash filename, TextureSystem::TextureHandle* texture_handle,
int subimage, ustringhash dataname, RefData val);
/// Lookup nearest points in a point cloud. It will search for
@@ -407,26 +410,25 @@ public:
};
virtual void pointcloud_search(BatchedShaderGlobals* bsg, ustring filename,
const void* wcenter,
virtual void pointcloud_search(BatchedShaderGlobals* bsg,
ustringhash filename, const void* wcenter,
Wide<const float> wradius, int max_points,
bool sort, PointCloudSearchResults& results);
virtual bool is_overridden_pointcloud_search() const = 0;
virtual Mask pointcloud_get(BatchedShaderGlobals* bsg, ustring filename,
virtual Mask pointcloud_get(BatchedShaderGlobals* bsg, ustringhash filename,
Wide<const int[]> windices,
Wide<const int> wnum_points, ustring attr_name,
MaskedData wout_data);
Wide<const int> wnum_points,
ustringhash attr_name, MaskedData wout_data);
virtual bool is_overridden_pointcloud_get() const = 0;
virtual Mask pointcloud_write(BatchedShaderGlobals* bsg, ustring filename,
Wide<const OSL::Vec3> wpos, int nattribs,
const ustring* attr_names,
const TypeDesc* attr_types,
const void** pointers_to_wide_attr_value,
Mask mask);
virtual Mask
pointcloud_write(BatchedShaderGlobals* bsg, ustringhash filename,
Wide<const OSL::Vec3> wpos, int nattribs,
const ustring* attr_names, const TypeDesc* attr_types,
const void** pointers_to_wide_attr_value, Mask mask);
virtual bool is_overridden_pointcloud_write() const = 0;
/// Options for the trace call.
@@ -441,7 +443,8 @@ public:
Wide<const Vec3> wdRdy);
virtual void getmessage(BatchedShaderGlobals* bsg, Masked<int> wresult,
ustring source, ustring name, MaskedData wval);
ustringhash source, ustringhash name,
MaskedData wval);
// pointcloud_search is T.B.D.
+72
View File
@@ -0,0 +1,72 @@
// Copyright Contributors to the Open Shading Language project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
#pragma once
#include <OSL/oslconfig.h>
OSL_NAMESPACE_ENTER
/// Wrapper class for holding a "device" pointer -- GPU or whatnot. It
/// provides protections so that the pointer cannot easily be accessed on the
/// host side, where presumably it would not be valid memory.
template<class T> class device_ptr {
public:
device_ptr() = default;
// Copy ctr from another device_ptr of the same type
device_ptr(const device_ptr& other) = default;
/// On device, device_ptr can construct from a pointer.
/// On host, it must be explicitly constructed -- use with caution.
#ifdef __CUDA_ARCH__
device_ptr(T* ptr) : m_ptr(ptr) {}
#else
explicit device_ptr(T* ptr) : m_ptr(ptr) {}
#endif
#ifdef __CUDA_ARCH__
/// On device, act as a pointer. None of these things are allowed on the
/// host.
T* operator->() const
{
return m_ptr;
}
T& operator*() const
{
return *m_ptr;
}
#endif
/// Extract the raw device-side pointer. Use with caution! On the host,
/// this will not point to valid memory.
T* d_get() const
{
return m_ptr;
}
/// Evaluate as bool is a null pointer check.
operator bool() const noexcept
{
return m_ptr != nullptr;
}
/// Reset the pointer to `dptr`, which must be a device-side raw pointer,
/// or null. Since this device_ptr is non-owning, any previous value is
/// simply overwritten.
void reset(T* dptr = nullptr)
{
m_ptr = dptr;
}
private:
T* m_ptr = nullptr; // underlying pointer, initializes to null
};
OSL_NAMESPACE_EXIT
-15
View File
@@ -6,10 +6,6 @@
#include <OSL/oslconfig.h>
#ifdef __CUDA_ARCH__
# include <optix.h>
#endif
// USAGE NOTES:
//
// To define a "standard" DeviceString, add a STRDECL to <OSL/strdecls.h>
@@ -19,21 +15,10 @@
OSL_NAMESPACE_ENTER
// Strings are handled differently in OptiX 6 vs OptiX 7.
//
// In OptiX 7+:
// Strings are not stored on the GPU at all. Strings are represented by
// their hash values which are computed at compile-time. Because of this,
// we have no access to either the strings' contents or their lengths.
//
// In OptiX 6:
// Strings are stored in a block of CUDA device memory. String variables hold a
// pointer to the start of the char array for each string. Each canonical string
// has a unique entry in the table, so two strings can be tested for equality by
// comparing their addresses.
//
// As a convenience, the ustring hash and the length of the string are also
// stored in the table, in the 16 bytes preceding the characters.
struct DeviceString {
#ifdef __CUDA_ARCH__
+6 -9
View File
@@ -154,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,
@@ -640,6 +631,12 @@ public:
/// llvm type.
llvm::Type* type_array(llvm::Type* type, int n);
/// Return the true if the llvm::Type is an array
bool is_type_array(llvm::Type* type);
/// Return the llvm::Type of element that the array_type is made up of
llvm::Type* element_type_of(llvm::Type* array_type);
/// Return an llvm::FunctionType that describes a function with the
/// given return types, parameter types (in a cspan), and whether it
/// uses varargs conventions.
+123 -4
View File
@@ -4,6 +4,11 @@
#pragma once
#cmakedefine01 OSL_USE_OPTIX
#cmakedefine01 OSL_BUILD_BATCHED
#define OSL_USE_BATCHED OSL_BUILD_BATCHED
#include <OSL/export.h>
#include <OSL/oslversion.h>
#include <OSL/platform.h>
@@ -62,8 +67,6 @@
OSL_NAMESPACE_ENTER
#define OSL_USE_BATCHED @BUILD_BATCHED@
/// Various compile-time defaults are defined here that could, in
/// principle, be redefined if you are using OSL in some particular
/// renderer that wanted things a different way.
@@ -133,6 +136,101 @@ fmtformat(const Str& fmt, Args&&... args)
/// OSL_USTRINGREP_IS_HASH will be 1 if the build-time option was enabled to
/// make the ustringrep be a ustringhash, rather than a ustring directly.
#cmakedefine01 OSL_USTRINGREP_IS_HASH
#if OSL_USTRINGREP_IS_HASH
/// ustringrep is the class we use to represent strings in the shader.
using ustringrep = ustringhash;
#else
/// ustringrep is the class we use to represent strings in the shader.
using ustringrep = ustring;
#endif
#if OSL_USTRINGREP_IS_HASH
/// ustring_pod is the type we use to pass string data in llvm function calls.
using ustring_pod = size_t;
#else
/// ustring_pod is the type we use to pass string data in llvm function calls.
using ustring_pod = const char*;
#endif
/// Convenience function to convert to a ustring.
inline ustring
ustring_from(ustringhash h)
{
return ustring::from_hash(h.hash());
}
/// Convenience function to convert to a ustring.
inline ustring
ustring_from(ustring u)
{
return u;
}
/// Convenience function to convert to a ustring.
inline ustring
ustring_from(string_view s)
{
return ustring(s);
}
/// Convenience function to convert to a ustringhash.
inline ustringhash
ustringhash_from(ustringhash u)
{
return u;
}
/// Convenience function to convert to a ustringhash.
inline ustringhash
ustringhash_from(ustring u)
{
return u.uhash();
}
/// Convenience function to convert to a ustringrep.
inline ustringrep
ustringrep_from(ustringhash h)
{
#if OSL_USTRINGREP_IS_HASH
return h;
#else
return ustring::from_hash(h.hash());
#endif
}
/// Convenience function to convert to a ustringrep.
inline ustringrep
ustringrep_from(ustring u)
{
#if OSL_USTRINGREP_IS_HASH
return u.hash();
#else
return u;
#endif
}
/// Convenience function to convert to a ustringrep.
inline ustringrep
ustringrep_from(string_view s)
{
ustring u(s);
#if OSL_USTRINGREP_IS_HASH
return u.hash();
#else
return u;
#endif
}
// N.B. SymArena is not really "configuration", but we cram it here for
// lack of a better home.
@@ -143,6 +241,7 @@ enum class SymArena {
Heap, // Belongs to context heap
Outputs, // Belongs to output arena
UserData, // UserData arena
Interactive, // Interactively edited variables
// ShaderGlobals, // RESERVED
};
@@ -229,7 +328,8 @@ OSL_NAMESPACE_EXIT
namespace std { // not necessary in C++17, then we can just say std::hash
#ifndef OIIO_USTRING_HAS_STDHASH
// Not a new enough OIIO to define std::hash<ustring>, so we'll do it
// Not a new enough OIIO to define std::hash<ustring>, so we'll do it.
// This can be removed once OIIO minimum is 2.4.5+ or >=2.5.0.1
template<> struct hash<OSL::ustring> {
std::size_t operator()(OSL::ustring u) const noexcept { return u.hash(); }
};
@@ -243,7 +343,8 @@ template<> struct hash<OSL::ustringhash> {
};
#endif
// Not necessary once minimum OIIO defines operator< for ustringhash
// Not necessary once minimum OIIO defines operator< for ustringhash.
// This can be removed once OIIO minimum is 2.4.5+ or >=2.5.0.1
template<> struct less<OSL::ustringhash> {
OSL_HOSTDEVICE constexpr bool operator()(OSL::ustringhash u,
OSL::ustringhash v) const noexcept
@@ -252,3 +353,21 @@ template<> struct less<OSL::ustringhash> {
}
};
} // namespace std
#ifndef OIIO_HAS_USTRINGHASH_FORMATTER
// OIIO is too old to have fmt custom formatter for ustringhash.
// This can be removed once OIIO minimum is 2.4.5+ or >=2.5.0.1
FMT_BEGIN_NAMESPACE
template<> struct formatter<OIIO::ustringhash> : formatter<fmt::string_view, char> {
template<typename FormatContext>
auto format(const OIIO::ustringhash& h, FormatContext& ctx)
-> decltype(ctx.out()) const
{
OIIO::ustring u(h);
return formatter<fmt::string_view, char>::format({ u.data(), u.size() },
ctx);
}
};
FMT_END_NAMESPACE
#endif
+131 -15
View File
@@ -111,6 +111,67 @@ public:
/// Parameter property hint bitflag values. The enum values must be powers of
/// two so they can be combined with bitwise operators.
enum class ParamHints : uint32_t {
/// `none`: No special properties
none = 0,
/// `interpolated`: This parameter may be an interpolated "user data" or
/// "geometric primitive" variable, and so may take on different values at
/// different points on the surface or on different objects that share the
/// same material. Any optimization of the shader should take this into
/// account.
interpolated = 1,
/// `interactive`: Parameter may have its value interactively modified by
/// subsequent ReParameter calls. Any optimization of the shader should
/// take this into account.
interactive = 2
};
inline constexpr ParamHints
operator|(ParamHints a, ParamHints b)
{
return static_cast<ParamHints>(static_cast<int>(a) | static_cast<int>(b));
}
inline constexpr ParamHints
operator&(ParamHints a, ParamHints b)
{
return static_cast<ParamHints>(static_cast<int>(a) & static_cast<int>(b));
}
inline ParamHints&
operator|=(ParamHints& a, ParamHints b)
{
a = a | b;
return a;
}
inline ParamHints&
operator&=(ParamHints& a, ParamHints b)
{
a = a & b;
return a;
}
inline constexpr ParamHints
operator~(ParamHints a)
{
return static_cast<ParamHints>(~static_cast<int>(a));
}
inline ParamHints&
set(ParamHints& a, ParamHints b, bool on = true)
{
if (on)
a |= b;
else
a &= ~b;
return a;
}
class OSLEXECPUBLIC ShadingSystem {
public:
ShadingSystem(RendererServices* renderer = NULL,
@@ -173,7 +234,7 @@ public:
/// int lazyerror Run layers lazily even if they have error
/// ops after optimization (1).
/// int lazy_userdata Retrieve userdata lazily (0).
/// int userdata_isconnected Should lockgeom=0 params (that may
/// int userdata_isconnected Should interpolated=1 params (that may
/// receive userdata) return true from
/// isconnected()? (0)
/// int greedyjit Optimize and compile all shaders up front,
@@ -200,6 +261,7 @@ public:
/// that don't specify it (1). Lockgeom
/// means a param CANNOT be overridden by
/// interpolated geometric parameters.
/// This option is slated for deprecation.
/// int countlayerexecs Add extra code to count total layers run.
/// int allow_shader_replacement Allow shader to be specified more than
/// once, replacing former definition.
@@ -427,12 +489,15 @@ public:
/// ptr attributes_needed Retrieves a pointer to the ustring array
/// containing the names of the needed attributes.
/// Note that if the same attribute
/// is requested in multiple scopes, it will
/// is requested in multiple scopes, or with
/// multiple different types, it will
/// appear in the array multiple times - once for
/// each scope in which is is queried.
/// each scope/type in which is is queried.
/// ptr attribute_scopes Retrieves a pointer to a ustring array containing
/// the scopes associated with each attribute query
/// in the attributes_needed array.
/// ptr attribute_types Retrieves a pointer to the array of
/// TypeDesc describing the attributes.
/// int unknown_attributes_needed Nonzero if additional attributes may be
/// needed, whose names will not be known
/// until the shader actually runs.
@@ -443,6 +508,15 @@ public:
/// string entry_layers[] List of entry point layers.
/// string pickle Retrieves a serialized representation
/// of the shader group declaration.
/// int llvm_groupdata_size Size of the GroupData struct.
/// ptr interactive_params Pointer to the memory block containing
/// host-side interactive parameter values
/// for this shader group.
/// ptr device_interactive_params
/// Pointer to the memory block containing
/// device-side interactive parameter values
/// for this shader group.
///
/// Note: the attributes referred to as "string" are actually on the app
/// side as ustring or const char* (they have the same data layout), NOT
/// std::string!
@@ -530,15 +604,50 @@ public:
bool ShaderGroupEnd(ShaderGroup& group);
/// Set a parameter of the next shader that will be added to the group,
/// optionally setting the 'lockgeom' metadata for that parameter
/// (despite how it may have been set in the shader). If lockgeom is
/// false, it means that this parameter should NOT be considered locked
/// against changes by the geometry, and therefore the shader should not
/// optimize assuming that the instance value (the 'val' specified by
/// this call) is a constant.
/// optionally setting or overriding properties with the `hints` argument.
/// Individual `hints` bits are defined and documented by the ParamHints
/// enum class.
bool Parameter(ShaderGroup& group, string_view name, TypeDesc t,
const void* val, bool lockgeom = true);
const void* val, ParamHints hints = ParamHints::none);
/// DEPRECATED(1.13) Parameter() call: instead of a full ParamHints
/// argument, there is just a bool `lockgeom` that default to true, and
/// when set to false is the same thing as setting
/// `ParamHints::interpolated`.
bool Parameter(ShaderGroup& group, string_view name, TypeDesc t,
const void* val, bool lockgeom)
{
return Parameter(group, name, t, val,
lockgeom ? ParamHints::none
: ParamHints::interpolated);
}
// Shortcuts for param passing a single int, float, or string.
bool Parameter(ShaderGroup& group, string_view name, int val,
ParamHints hints = ParamHints::none)
{
return Parameter(group, name, TypeDesc::INT, &val, hints);
}
bool Parameter(ShaderGroup& group, string_view name, float val,
ParamHints hints = ParamHints::none)
{
return Parameter(group, name, TypeDesc::FLOAT, &val, hints);
}
bool Parameter(ShaderGroup& group, string_view name, const std::string& val,
ParamHints hints = ParamHints::none)
{
const char* s = val.c_str();
return Parameter(group, name, TypeDesc::STRING, &s, hints);
}
bool Parameter(ShaderGroup& group, string_view name, ustring val,
ParamHints hints = ParamHints::none)
{
return Parameter(group, name, TypeDesc::STRING, (const char**)&val,
hints);
}
// DEPRECATED(1.13): use the version above that takes ParamHints.
// This is the old version that takes `bool lockgeom`.
bool Parameter(ShaderGroup& group, string_view name, int val,
bool lockgeom = true)
{
@@ -589,10 +698,8 @@ public:
/// Replace a parameter value in a previously-declared shader group.
/// This is meant to called after the ShaderGroupBegin/End, but will
/// fail if the shader has already been irrevocably optimized/compiled,
/// unless the particular parameter is marked as lockgeom=0 (which
/// indicates that it's a parameter that may be overridden by the
/// geometric primitive). This call gives you a way of changing the
/// instance value, even if it's not a geometric override.
/// unless the particular parameter is marked as either interpolated=1
/// or interactive=1.
bool ReParameter(ShaderGroup& group, string_view layername,
string_view paramname, TypeDesc type, const void* val);
// Shortcuts for param passing a single int, float, or string.
@@ -628,13 +735,22 @@ public:
// above that take an explicit `ShaderGroup&`, which are thread-safe
// and re-entrant.
bool Parameter(string_view name, TypeDesc t, const void* val,
bool lockgeom = true);
ParamHints hints = ParamHints::none);
bool Shader(string_view shaderusage, string_view shadername,
string_view layername);
bool ConnectShaders(string_view srclayer, string_view srcparam,
string_view dstlayer, string_view dstparam);
bool ShaderGroupEnd(void);
// DEPRECATED(1.13): use the version above that takes ParamHints.
// This is the old version that takes `bool lockgeom`.
bool Parameter(string_view name, TypeDesc t, const void* val, bool lockgeom)
{
return Parameter(name, t, val,
lockgeom ? ParamHints::none
: ParamHints::interpolated);
}
/// Create a per-thread data needed for shader execution. It's very
/// important for the app to never use a PerThreadInfo from more than
/// one thread (and probably a good idea allocate only one PerThreadInfo
+292 -297
View File
File diff suppressed because it is too large Load Diff
+58
View File
@@ -18,10 +18,14 @@
#pragma once
#include <cstring>
#include <memory>
#include <OSL/oslversion.h>
#if defined(__x86_64__) && !defined(__CUDA_ARCH__)
# include <x86intrin.h>
#endif
/////////////////////////////////////////////////////////////////////////
// Detect which compiler and version we're using
@@ -499,6 +503,60 @@
OSL_NAMESPACE_ENTER
/// Standards-compliant bit cast of two equally sized types. This is used
/// equivalently to C++20 std::bit_cast, but it works prior to C++20 and
/// it has the right decorators to work with Cuda.
/// @version 1.13.2
template <typename To, typename From>
OSL_FORCEINLINE OSL_HOSTDEVICE To bitcast(const From& src) noexcept {
// NOTE: this is the only standards compliant way of doing this type of casting,
// luckily the compilers we care about know how to optimize away this idiom.
static_assert(sizeof(From) == sizeof(To),
"bit_cast must be between objects of the same size");
To dst;
memcpy((void*)&dst, &src, sizeof(From));
return dst;
}
#if defined(__x86_64__) && !defined(__CUDA_ARCH__) && \
(defined(__INTEL_COMPILER) || defined(__INTEL_LLVM_COMPILER) \
|| OSL_CLANG_VERSION >= 100000 || OSL_APPLE_CLANG_VERSION >= 130000)
// On x86/x86_64 for certain compilers we can use Intel CPU intrinsics for
// some common bitcast cases that might be even more understandable to the
// compiler and generate better code without its getting confused about the
// memcpy in the general case. We're a bit conservative with the compiler
// version checks here, it may be that some earlier versions support these
// intrinsics.
template<> OSL_FORCEINLINE uint32_t bitcast<uint32_t, float>(const float& val) noexcept {
return static_cast<uint32_t>(_castf32_u32(val));
}
template<> OSL_FORCEINLINE int32_t bitcast<int32_t, float>(const float& val) noexcept {
return static_cast<int32_t>(_castf32_u32(val));
}
template<> OSL_FORCEINLINE float bitcast<float, uint32_t>(const uint32_t& val) noexcept {
return _castu32_f32(val);
}
template<> OSL_FORCEINLINE float bitcast<float, int32_t>(const int32_t& val) noexcept {
return _castu32_f32(val);
}
template<> OSL_FORCEINLINE uint64_t bitcast<uint64_t, double>(const double& val) noexcept {
return static_cast<uint64_t>(_castf64_u64(val));
}
template<> OSL_FORCEINLINE int64_t bitcast<int64_t, double>(const double& val) noexcept {
return static_cast<int64_t>(_castf64_u64(val));
}
template<> OSL_FORCEINLINE double bitcast<double, uint64_t>(const uint64_t& val) noexcept {
return _castu64_f64(val);
}
template<> OSL_FORCEINLINE double bitcast<double, int64_t>(const int64_t& val) noexcept {
return _castu64_f64(val);
}
#endif
#if OSL_CPLUSPLUS_VERSION >= 20
using std::assume_aligned;
#else
+152 -126
View File
@@ -2,8 +2,6 @@
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
// clang-format off
#pragma once
@@ -13,14 +11,13 @@
OSL_NAMESPACE_ENTER
class RendererServices;
template<int WidthT>
class BatchedRendererServices;
template<int WidthT> class BatchedRendererServices;
class ShadingContext;
struct ShaderGlobals;
// Tags for polymorphic dispatch
template <int SimdWidthT>
class WidthOf {};
template<int SimdWidthT> class WidthOf {
};
/// Opaque pointer to whatever the renderer uses to represent a
@@ -49,7 +46,7 @@ public:
RendererServices(TextureSystem* texsys = NULL);
virtual ~RendererServices () { }
virtual ~RendererServices() {}
/// Given the name of a 'feature', return whether this RendererServices
/// supports it. Feature names include:
@@ -62,28 +59,34 @@ public:
/// support it, as long as the OSL runtime only uses that feature if the
/// supports("feature") says it's present, thus preserving source
/// compatibility.
virtual int supports (string_view feature) const { return false; }
virtual int supports(string_view feature) const { return false; }
/// Get the 4x4 matrix that transforms by the specified
/// transformation at the given time. Return true if ok, false
/// on error.
virtual bool get_matrix (ShaderGlobals *sg, Matrix44 &result,
TransformationPtr xform, float time) { return false; }
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result,
TransformationPtr xform, float time)
{
return false;
}
/// Get the 4x4 matrix that transforms by the specified
/// transformation at the given time. Return true if ok, false on
/// error. The default implementation is to use get_matrix and
/// invert it, but a particular renderer may have a better technique
/// and overload the implementation.
virtual bool get_inverse_matrix (ShaderGlobals *sg, Matrix44 &result,
TransformationPtr xform, float time);
virtual bool get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
TransformationPtr xform, float time);
/// Get the 4x4 matrix that transforms by the specified
/// transformation. Return true if ok, false on error. Since no
/// time value is given, also return false if the transformation may
/// be time-varying.
virtual bool get_matrix (ShaderGlobals *sg, Matrix44 &result,
TransformationPtr xform) { return false; }
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result,
TransformationPtr xform)
{
return false;
}
/// Get the 4x4 matrix that transforms by the specified
/// transformation. Return true if ok, false on error. Since no
@@ -91,29 +94,29 @@ public:
/// be time-varying. The default implementation is to use
/// get_matrix and invert it, but a particular renderer may have a
/// better technique and overload the implementation.
virtual bool get_inverse_matrix (ShaderGlobals *sg, Matrix44 &result,
TransformationPtr xform);
virtual bool get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
TransformationPtr xform);
/// Get the 4x4 matrix that transforms points from the named
/// 'from' coordinate system to "common" space at the given time.
/// Returns true if ok, false if the named matrix is not known.
virtual bool get_matrix (ShaderGlobals *sg, Matrix44 &result,
ustring from, float time) { return false; }
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result,
ustringhash from, float time);
/// Get the 4x4 matrix that transforms points from "common" space to
/// the named 'to' coordinate system to at the given time. The
/// default implementation is to use get_matrix and invert it, but a
/// particular renderer may have a better technique and overload the
/// implementation.
virtual bool get_inverse_matrix (ShaderGlobals *sg, Matrix44 &result,
ustring to, float time);
virtual bool get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
ustringhash to, float time);
/// Get the 4x4 matrix that transforms 'from' to "common" space.
/// Since there is no time value passed, return false if the
/// transformation may be time-varying (as well as if it's not found
/// at all).
virtual bool get_matrix (ShaderGlobals *sg, Matrix44 &result,
ustring from) { return false; }
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result,
ustringhash from);
/// Get the 4x4 matrix that transforms points from "common" space to
/// the named 'to' coordinate system. Since there is no time value
@@ -122,8 +125,8 @@ public:
/// implementation is to use get_matrix and invert it, but a
/// particular renderer may have a better technique and overload the
/// implementation.
virtual bool get_inverse_matrix (ShaderGlobals *sg, Matrix44 &result,
ustring to);
virtual bool get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
ustringhash to);
/// Transform points Pin[0..npoints-1] in named coordinate system
/// 'from' into 'to' coordinates, storing the result in Pout[] using
@@ -148,11 +151,10 @@ public:
/// Note to RendererServices implementations: just return 'false'
/// if there isn't a special nonlinear transformation between the
/// two spaces.
virtual bool transform_points (ShaderGlobals *sg,
ustring from, ustring to, float time,
const Vec3 *Pin, Vec3 *Pout, int npoints,
TypeDesc::VECSEMANTICS vectype)
{ return false; }
virtual bool transform_points(ShaderGlobals* sg, ustringhash from,
ustringhash to, float time, const Vec3* Pin,
Vec3* Pout, int npoints,
TypeDesc::VECSEMANTICS vectype);
/// Get the named attribute from the renderer and if found then
@@ -167,36 +169,39 @@ public:
/// run on. Be robust to this situation, return 'true' (retrieve the
/// attribute) if you can (known object and attribute name), but
/// otherwise just fail by returning 'false'.
virtual bool get_attribute (ShaderGlobals *sg, bool derivatives,
ustring object, TypeDesc type, ustring name,
void *val) { return false; }
virtual bool get_attribute(ShaderGlobals* sg, bool derivatives,
ustringhash object, TypeDesc type,
ustringhash name, void* val);
/// Similar to get_attribute(); this method will return the 'index'
/// element of an attribute array.
virtual bool get_array_attribute (ShaderGlobals *sg, bool derivatives,
ustring object, TypeDesc type,
ustring name, int index, void *val) { return false; }
virtual bool get_array_attribute(ShaderGlobals* sg, bool derivatives,
ustringhash object, TypeDesc type,
ustringhash name, int index, void* val);
/// Get the named user-data from the current object and write it into
/// 'val'. If derivatives is true, the derivatives should be written into val
/// as well. Return false if no user-data with the given name and type was
/// found.
virtual bool get_userdata (bool derivatives, ustring name, TypeDesc type,
ShaderGlobals *sg, void *val) { return false; }
virtual bool get_userdata(bool derivatives, ustringhash name, TypeDesc type,
ShaderGlobals* sg, void* val);
/// Given the name of a texture, return an opaque handle that can be
/// used with texture calls to avoid the name lookups.
virtual TextureHandle * get_texture_handle (ustring filename,
ShadingContext *context);
/// Given the name of a texture, return an opaque handle that can be used
/// with texture calls to avoid the name lookups. The `options`, if not
/// null, may be used in renderer-specific ways to specialize a handle
/// based on certain texture option choices.
virtual TextureHandle*
get_texture_handle(ustringhash filename, ShadingContext* context,
const TextureOpt* options = nullptr);
/// Return true if the texture handle (previously returned by
/// get_texture_handle()) is a valid texture that can be subsequently
/// read or sampled.
virtual bool good (TextureHandle *texture_handle);
virtual bool good(TextureHandle* texture_handle);
/// Return true if the texture handle (previously returned by
/// get_texture_handle()) is udim
virtual bool is_udim (TextureHandle *texture_handle);
virtual bool is_udim(TextureHandle* texture_handle);
/// Filtered 2D texture lookup for a single point.
///
@@ -224,13 +229,13 @@ public:
/// messages (in case of failure, when the function returns false) will
/// be stored there, leaving it up to the caller/shader to handle the
/// error.
virtual bool texture (ustring filename, TextureHandle *texture_handle,
TexturePerthread *texture_thread_info,
TextureOpt &options, ShaderGlobals *sg,
float s, float t, float dsdx, float dtdx,
float dsdy, float dtdy, int nchannels,
float *result, float *dresultds, float *dresultdt,
ustring *errormessage);
virtual bool texture(ustringhash filename, TextureHandle* texture_handle,
TexturePerthread* texture_thread_info,
TextureOpt& options, ShaderGlobals* sg, float s,
float t, float dsdx, float dtdx, float dsdy,
float dtdy, int nchannels, float* result,
float* dresultds, float* dresultdt,
ustringhash* errormessage);
/// Filtered 3D texture lookup for a single point.
///
@@ -257,14 +262,13 @@ public:
/// messages (in case of failure, when the function returns false) will
/// be stored there, leaving it up to the caller/shader to handle the
/// error.
virtual bool texture3d (ustring filename, TextureHandle *texture_handle,
TexturePerthread *texture_thread_info,
TextureOpt &options, ShaderGlobals *sg,
const Vec3 &P, const Vec3 &dPdx, const Vec3 &dPdy,
const Vec3 &dPdz, int nchannels,
float *result, float *dresultds,
float *dresultdt, float *dresultdr,
ustring *errormessage);
virtual bool texture3d(ustringhash filename, TextureHandle* texture_handle,
TexturePerthread* texture_thread_info,
TextureOpt& options, ShaderGlobals* sg,
const Vec3& P, const Vec3& dPdx, const Vec3& dPdy,
const Vec3& dPdz, int nchannels, float* result,
float* dresultds, float* dresultdt, float* dresultdr,
ustringhash* errormessage);
/// Filtered environment lookup for a single point.
///
@@ -288,13 +292,13 @@ public:
/// messages (in case of failure, when the function returns false) will
/// be stored there, leaving it up to the caller/shader to handle the
/// error.
virtual bool environment (ustring filename, TextureHandle *texture_handle,
TexturePerthread *texture_thread_info,
TextureOpt &options, ShaderGlobals *sg,
const Vec3 &R, const Vec3 &dRdx, const Vec3 &dRdy,
int nchannels, float *result,
float *dresultds, float *dresultdt,
ustring *errormessage);
virtual bool environment(ustringhash filename,
TextureHandle* texture_handle,
TexturePerthread* texture_thread_info,
TextureOpt& options, ShaderGlobals* sg,
const Vec3& R, const Vec3& dRdx, const Vec3& dRdy,
int nchannels, float* result, float* dresultds,
float* dresultdt, ustringhash* errormessage);
/// Get information about the given texture. Return true if found
/// and the data has been put in *data. Return false if the texture
@@ -315,24 +319,20 @@ public:
/// messages (in case of failure, when the function returns false) will
/// be stored there, leaving it up to the caller/shader to handle the
/// error.
virtual bool get_texture_info (ustring filename,
TextureHandle *texture_handle,
TexturePerthread *texture_thread_info,
ShadingContext *shading_context,
int subimage,
ustring dataname, TypeDesc datatype,
void *data,
ustring *errormessage);
virtual bool get_texture_info(ustringhash filename,
TextureHandle* texture_handle,
TexturePerthread* texture_thread_info,
ShadingContext* shading_context, int subimage,
ustringhash dataname, TypeDesc datatype,
void* data, ustringhash* errormessage);
virtual bool get_texture_info (ustring filename,
TextureHandle *texture_handle,
float s, float t,
TexturePerthread *texture_thread_info,
ShadingContext *shading_context,
int subimage,
ustring dataname, TypeDesc datatype,
void *data,
ustring *errormessage);
virtual bool get_texture_info(ustringhash filename,
TextureHandle* texture_handle, float s,
float t,
TexturePerthread* texture_thread_info,
ShadingContext* shading_context, int subimage,
ustringhash dataname, TypeDesc datatype,
void* data, ustringhash* errormessage);
/// Lookup nearest points in a point cloud. It will search for
@@ -343,40 +343,38 @@ public:
/// derivatives will be computed for distances (when provided).
///
/// Return the number of points found, always < max_points
virtual int pointcloud_search (ShaderGlobals *sg,
ustring filename, const OSL::Vec3 &center,
float radius, int max_points, bool sort,
size_t *out_indices,
float *out_distances, int derivs_offset);
virtual int pointcloud_search(ShaderGlobals* sg, ustringhash filename,
const OSL::Vec3& center, float radius,
int max_points, bool sort,
size_t* out_indices, float* out_distances,
int derivs_offset);
/// Retrieve an attribute for an index list. The result is another array
/// of the requested type stored in out_data.
///
/// Return 1 if the attribute is found, 0 otherwise.
virtual int pointcloud_get (ShaderGlobals *sg,
ustring filename, size_t *indices, int count,
ustring attr_name, TypeDesc attr_type,
void *out_data);
virtual int pointcloud_get(ShaderGlobals* sg, ustringhash filename,
size_t* indices, int count,
ustringhash attr_name, TypeDesc attr_type,
void* out_data);
/// Write a point to the named pointcloud, which will be saved
/// at the end of the frame. Return true if everything is ok,
/// false if there was an error.
virtual bool pointcloud_write (ShaderGlobals *sg,
ustring filename, const OSL::Vec3 &pos,
int nattribs, const ustring *names,
const TypeDesc *types,
const void **data);
virtual bool pointcloud_write(ShaderGlobals* sg, ustringhash filename,
const OSL::Vec3& pos, int nattribs,
const ustringrep* names,
const TypeDesc* types, const void** data);
/// Options for the trace call.
struct TraceOpt {
float mindist; ///< ignore hits closer than this
float maxdist; ///< ignore hits farther than this
bool shade; ///< whether to shade what is hit
ustring traceset; ///< named trace set
TraceOpt () : mindist(0.0f), maxdist(1.0e30), shade(false) { }
float mindist; ///< ignore hits closer than this
float maxdist; ///< ignore hits farther than this
bool shade; ///< whether to shade what is hit
ustringrep traceset; ///< named trace set
TraceOpt() : mindist(0.0f), maxdist(1.0e30), shade(false) {}
enum class LLVMMemberIndex
{
enum class LLVMMemberIndex {
mindist = 0,
maxdist,
shade,
@@ -387,37 +385,59 @@ public:
/// Immediately trace a ray from P in the direction R. Return true
/// if anything hit, otherwise false.
virtual bool trace (TraceOpt &options, ShaderGlobals *sg,
const OSL::Vec3 &P, const OSL::Vec3 &dPdx,
const OSL::Vec3 &dPdy, const OSL::Vec3 &R,
const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy) {
return false;
}
virtual bool trace(TraceOpt& options, ShaderGlobals* sg, const OSL::Vec3& P,
const OSL::Vec3& dPdx, const OSL::Vec3& dPdy,
const OSL::Vec3& R, const OSL::Vec3& dRdx,
const OSL::Vec3& dRdy);
/// Get the named message from the renderer and if found then
/// write it into 'val'. Otherwise, return false. This is only
/// called for "sourced" messages, not ordinary intra-group messages.
virtual bool getmessage (ShaderGlobals *sg, ustring source, ustring name,
TypeDesc type, void *val, bool derivatives) {
return false;
}
virtual bool getmessage(ShaderGlobals* sg, ustringhash source,
ustringhash name, TypeDesc type, void* val,
bool derivatives);
/// Return a pointer to the texture system (if available).
virtual TextureSystem *texturesys () const;
virtual TextureSystem* texturesys() const;
virtual uint64_t register_global (const std::string& var_name,
uint64_t value)
/// Allocate `size` bytes of memory on the device that will execute the
/// shaders. (Equivalent to malloc() on the CPU.)
virtual void* device_alloc(size_t size)
{
return 0;
return nullptr;
// Note: for an OptiX-based renderer, this method should be overriden
// with something like:
//
// void* dptr;
// auto r = cudaMalloc(&dptr, size);
// return r == cudaSuccess ? dptr : nullptr;
}
virtual bool fetch_global (const std::string& var_name,
uint64_t* value)
/// Free a previous allocation (by `device_alloc()`) on the device that
/// will execute the shaders. (Equivalent to free() on the CPU.)
virtual void device_free(void* ptr)
{
return false;
// Note: for an OptiX-based renderer, this method should be overriden
// with something like:
//
// cudaFree(ptr);
}
/// Copy `size` bytes from location `src_host` on the host/CPU (the
/// machine making this call) into location `dst_device` on the device
/// executing shaders. (Equivalent to `memcpy(dst, src, size)` on the
/// CPU.)
virtual void* copy_to_device(void* dst_device, const void* src_host,
size_t size)
{
return nullptr;
// Note: for an OptiX-based renderer, this method should be overriden
// with something like:
//
// auto r = cudaMemcpy(dst_device, src_host, size,
// cudaMemcpyHostToDevice);
// return dst_device;
}
/// Options we use for noise calls.
struct NoiseOpt {
@@ -426,19 +446,25 @@ public:
Vec3 direction;
float bandwidth;
float impulses;
NoiseOpt () : anisotropic(0), do_filter(true),
direction(1.0f,0.0f,0.0f), bandwidth(1.0f), impulses(16.0f) { }
NoiseOpt()
: anisotropic(0)
, do_filter(true)
, direction(1.0f, 0.0f, 0.0f)
, bandwidth(1.0f)
, impulses(16.0f)
{
}
};
/// A renderer may choose to support batched execution by providing pointers
/// to objects satisfying the BatchedRendererServices<WidthOf<#>> interface
/// for specific batch sizes.
/// Unless overridden, a nullptr is returned.
virtual BatchedRendererServices<16> * batched(WidthOf<16>);
virtual BatchedRendererServices<8> * batched(WidthOf<8>);
virtual BatchedRendererServices<16>* batched(WidthOf<16>);
virtual BatchedRendererServices<8>* batched(WidthOf<8>);
protected:
TextureSystem *m_texturesys; // A place to hold a TextureSystem
TextureSystem* m_texturesys; // A place to hold a TextureSystem
};
+89 -9
View File
@@ -895,6 +895,8 @@ template<int WidthT> struct alignas(VecReg<WidthT>) Block<Matrix44, WidthT> {
}
};
// Specialization of Block for ustring
template<int WidthT> struct alignas(VecReg<WidthT>) Block<ustring, WidthT> {
static constexpr int width = WidthT;
typedef ustring ValueType;
@@ -942,6 +944,58 @@ template<int WidthT> struct alignas(VecReg<WidthT>) Block<ustring, WidthT> {
}
};
// Specialization of Block for ustringhash
template<int WidthT> struct alignas(VecReg<WidthT>) Block<ustringhash, WidthT> {
static constexpr int width = WidthT;
typedef ustringhash ValueType;
// To enable vectorization, use uintptr_t to store the ustringhash (const char *)
size_t str[WidthT];
static_assert(sizeof(ustringhash) == sizeof(size_t),
"ustringhash must be size_t");
OSL_FORCEINLINE Block() = default;
// We want to avoid accidentally copying these when the intent was to just pass a reference
Block(const Block& other) = delete;
OSL_FORCEINLINE void set(int lane, const ustringhash& value)
{
str[lane] = value.hash();
}
OSL_FORCEINLINE void set(int lane, ustring value)
{
str[lane] = value.hash();
}
OSL_FORCEINLINE void set(int lane, const ustringhash& value, bool laneMask)
{
if (laneMask)
str[lane] = value.hash();
}
OSL_FORCEINLINE ustringhash get(int lane) const
{
#ifdef OIIO_USTRING_HAS_CTR_FROM_USTRINGHASH
return ustringhash::from_hash(str[lane]);
#else
return OSL::bitcast<ustringhash>(str[lane]);
#endif
}
OSL_FORCEINLINE pvt::LaneProxy<ValueType, WidthT> operator[](int lane)
{
return pvt::LaneProxy<ValueType, WidthT>(*this, lane);
}
OSL_FORCEINLINE pvt::ConstLaneProxy<const ValueType, WidthT>
operator[](int lane) const
{
return pvt::ConstLaneProxy<const ValueType, WidthT>(*this, lane);
}
};
template<int WidthT>
struct alignas(VecReg<WidthT>) Block<Dual2<float>, WidthT> {
typedef Dual2<float> ValueType;
@@ -2845,7 +2899,7 @@ public:
// Populate all data lanes of the MaskedData by broadcasting the
// single instance of data pointed to.
// Masked off lanes are not overwritten.
// Includes value, as well as Dx and Dy when has_derivs() is true
// when has_derivs() is true, Dx and Dy will be zeroed
OSL_FORCEINLINE void assign_all_from_scalar(const void* ptr_data) const;
@@ -2863,6 +2917,9 @@ private:
template<typename DataT>
OSL_NOINLINE void assign_all_from_scalar_type(const void* ptr_data,
int deriv_index) const;
template<typename DataT>
OSL_NOINLINE void zero_all_type(int deriv_index) const;
};
@@ -3378,6 +3435,33 @@ MaskedData<WidthT>::assign_all_from_scalar_type(const void* ptr_data,
}
}
template<int WidthT>
template<typename DataT>
OSL_NOINLINE void
MaskedData<WidthT>::zero_all_type(int deriv_index) const
{
// We can't just do a memset because some lanes may be masked off
// Use a SIMD loop to perform masked assignment.
auto* dst_blocks = pvt::block_cast<DataT, WidthT>(m_ptr);
int elem_count = static_cast<int>(m_type.numelements());
int comp_count = m_type.aggregate;
int deriv_offset = deriv_index * elem_count * comp_count;
for (int array_index = 0; array_index < elem_count; ++array_index) {
int array_offset = array_index * comp_count;
for (int comp_index = 0; comp_index < comp_count; ++comp_index) {
int combined_index = deriv_offset + array_offset + comp_index;
auto& bdst = dst_blocks[combined_index];
Masked<DataT, WidthT> wdest(bdst, mask());
OSL_OMP_PRAGMA(omp simd simdlen(WidthT))
for (int lane = 0; lane < WidthT; ++lane) {
wdest[lane] = DataT {};
}
}
}
}
template<int WidthT>
OSL_FORCEINLINE void
MaskedData<WidthT>::assign_all_from_scalar(const void* ptr_data) const
@@ -3393,16 +3477,12 @@ MaskedData<WidthT>::assign_all_from_scalar(const void* ptr_data) const
assign_all_from_scalar_type<ustring>(ptr_data, /*deriv_index*/ 0);
}
if (has_derivs()) {
size_t src_size = type().size();
const char* dx_src = reinterpret_cast<const char*>(ptr_data) + src_size;
const char* dy_src = dx_src + src_size;
if (isBase32bit) {
assign_all_from_scalar_type<int>(dx_src, /*deriv_index*/ 1);
assign_all_from_scalar_type<int>(dy_src, /*deriv_index*/ 2);
zero_all_type<int>(/*deriv_index*/ 1);
zero_all_type<int>(/*deriv_index*/ 2);
} else {
assign_all_from_scalar_type<ustring>(dx_src, /*deriv_index*/ 1);
assign_all_from_scalar_type<ustring>(dy_src, /*deriv_index*/ 2);
zero_all_type<ustring>(/*deriv_index*/ 1);
zero_all_type<ustring>(/*deriv_index*/ 2);
}
}
}
+4 -3
View File
@@ -8,7 +8,7 @@
#include <OSL/oslconfig.h>
#include <OSL/oslversion.h>
#ifdef OSL_USE_OPTIX
#if OSL_USE_OPTIX
# include <cuda_runtime_api.h>
# include <optix.h>
# ifdef _WIN32
@@ -18,8 +18,9 @@
# include <stdlib.h>
#endif
#include <OSL/device_ptr.h>
#if !defined(OSL_USE_OPTIX) && !defined(__CUDA_ARCH__)
#if !OSL_USE_OPTIX && !defined(__CUDA_ARCH__)
using CUdeviceptr = void*;
using float3 = OSL::Vec3;
#endif
@@ -28,7 +29,7 @@ using float3 = OSL::Vec3;
OSL_NAMESPACE_ENTER
#ifdef OSL_USE_OPTIX
#if OSL_USE_OPTIX
////////////////////////////////////////////////////////////////////////
// If OptiX is available, alias everything in optix:: namespace into
+50 -9
View File
@@ -386,6 +386,7 @@ public:
/// vector-like (and match their array-ness and closure-ness), or
/// if both are structures with matching fields.
friend bool equivalent(const TypeSpec& a, const TypeSpec& b);
friend bool relaxed_equivalent(const TypeSpec& a, const TypeSpec& b);
/// Is type src is assignable to dst? It is if they are the equivalent(),
/// or if dst is a float or float-aggregate and src is a float or int.
@@ -477,7 +478,9 @@ public:
, m_const_initializer(false)
, m_connected_down(false)
, m_initialized(false)
, m_lockgeom(false)
, m_interpolated(false)
, m_interactive(false)
, m_noninteractive(false)
, m_allowconnect(true)
, m_renderer_output(false)
, m_readonly(false)
@@ -629,7 +632,18 @@ public:
OSL_ASSERT(arena == SymArena::Absolute);
m_arena = static_cast<unsigned int>(arena);
m_data = ptr;
// m_dataoffset = static_cast<int64_t>((char*)ptr - (char*)0);
}
/// Specify the location of the symbol's data, relative to an arena
/// (which for now must be Absolute).
void set_dataptr(SymArena arena, void* ptr, int offset)
{
// OSL_ASSERT(arena == SymArena::Absolute);
m_arena = static_cast<unsigned int>(arena);
m_data = ptr;
m_dataoffset = offset;
OSL::print("setting sym {} arena {} offset {}\n", name(), int(m_arena),
m_dataoffset);
}
@@ -870,11 +884,36 @@ public:
bool lockgeom() const
{
return m_lockgeom;
// We can lock a value to a constant (at all places on all pieces of
// geometry) if it is neither interpolated nor interactively modified.
return !m_interpolated && !m_interactive;
}
void lockgeom(bool lock)
bool interpolated() const
{
m_lockgeom = lock;
return m_interpolated;
}
void interpolated(bool val)
{
m_interpolated = val;
}
bool interactive() const
{
return m_interactive;
}
void interactive(bool val)
{
m_interactive = val;
}
bool noninteractive() const
{
return m_noninteractive;
}
void noninteractive(bool val)
{
m_noninteractive = val;
}
bool allowconnect() const
@@ -1028,10 +1067,12 @@ protected:
unsigned m_symtype : 4; ///< Kind of symbol (param, local, etc.)
unsigned m_has_derivs : 1; ///< Step to derivs (0 == has no derivs)
unsigned m_const_initializer : 1; ///< initializer is a constant expression
unsigned m_connected_down : 1; ///< Connected to a later/downstream layer
unsigned m_initialized : 1; ///< If a param, has it been initialized?
unsigned m_lockgeom : 1; ///< Is the param not overridden by geom?
unsigned m_allowconnect : 1; ///< Is the param not overridden by geom?
unsigned m_connected_down : 1; ///< Connected to a later/downstream layer
unsigned m_initialized : 1; ///< If a param, has it been initialized?
unsigned m_interpolated : 1; ///< Is the param overridden by geom?
unsigned m_interactive : 1; ///< May the param change interactively?
unsigned m_noninteractive : 1; ///< The param def won't modify interactively
unsigned m_allowconnect : 1; ///< Is the param allowd to connect?
unsigned m_renderer_output : 1; ///< Is this sym a renderer output?
unsigned m_readonly : 1; ///< read-only symbol
unsigned m_is_uniform : 1; ///< symbol is uniform under batched execution
+97 -36
View File
@@ -1116,90 +1116,151 @@ ASTassign_expression::opword() const
OSL_ASSERT (0 && "unknown assignment expression");
return "assign"; // punt
}
// clang-format on
}
ASTunary_expression::ASTunary_expression (OSLCompilerImpl *comp, int op,
ASTNode *expr)
: ASTNode (unary_expression_node, comp, op, expr)
ASTunary_expression::ASTunary_expression(OSLCompilerImpl* comp, int op,
ASTNode* expr)
: ASTNode(unary_expression_node, comp, op, expr)
{
// Check for a user-overloaded function for this operator
Symbol *sym = comp->symtab().find(ustring::fmtformat("__operator__{}__", opword()));
Symbol* sym = comp->symtab().find(
ustring::fmtformat("__operator__{}__", opword()));
if (sym && sym->symtype() == SymTypeFunction)
m_function_overload = (FunctionSymbol *)sym;
m_function_overload = (FunctionSymbol*)sym;
}
const char *
ASTunary_expression::childname (size_t i) const
const char*
ASTunary_expression::childname(size_t i) const
{
static const char *name[] = { "expression" };
static const char* name[] = { "expression" };
return name[i];
}
const char *
ASTunary_expression::opname () const
const char*
ASTunary_expression::opname() const
{
switch (m_op) {
case Add : return "+";
case Sub : return "-";
case Not : return "!";
case Compl : return "~";
default:
OSL_ASSERT (0 && "unknown unary expression");
return "unknown";
case Add: return "+";
case Sub: return "-";
case Not: return "!";
case Compl: return "~";
default: OSL_ASSERT(0 && "unknown unary expression"); return "unknown";
}
}
const char *
ASTunary_expression::opword () const
const char*
ASTunary_expression::opword() const
{
switch (m_op) {
case Add : return "add";
case Sub : return "neg";
case Not : return "not";
case Compl : return "compl";
default:
OSL_ASSERT (0 && "unknown unary expression");
return "unknown";
case Add: return "add";
case Sub: return "neg";
case Not: return "not";
case Compl: return "compl";
default: OSL_ASSERT(0 && "unknown unary expression"); return "unknown";
}
}
ASTbinary_expression::ASTbinary_expression (OSLCompilerImpl *comp, Operator op,
ASTNode *left, ASTNode *right)
: ASTNode (binary_expression_node, comp, op, left, right)
ASTbinary_expression::ASTbinary_expression(OSLCompilerImpl* comp, Operator op,
ASTNode* left, ASTNode* right)
: ASTNode(binary_expression_node, comp, op, left, right)
{
// Check for a user-overloaded function for this operator.
// Disallow a few ops from overloading.
if (op != And && op != Or) {
ustring funcname = ustring::fmtformat("__operator__{}__", opword());
Symbol *sym = comp->symtab().find (funcname);
Symbol* sym = comp->symtab().find(funcname);
if (sym && sym->symtype() == SymTypeFunction)
m_function_overload = (FunctionSymbol *)sym;
m_function_overload = (FunctionSymbol*)sym;
}
}
const char *
ASTbinary_expression::childname (size_t i) const
ASTNode*
ASTbinary_expression::make(OSLCompilerImpl* comp, Operator op, ASTNode* left,
ASTNode* right)
{
static const char *name[] = { "left", "right" };
// If the left and right are both literal constants, fold the expression
if (left->nodetype() == literal_node && right->nodetype() == literal_node) {
ASTNode* cf = nullptr; // constant-folded result
if (left->typespec().is_int() && right->typespec().is_int()) {
int lv = dynamic_cast<ASTliteral*>(left)->intval();
int rv = dynamic_cast<ASTliteral*>(right)->intval();
switch (op) {
case Mul: cf = new ASTliteral(comp, lv * rv); break;
case Div: cf = new ASTliteral(comp, rv ? lv / rv : 0); break;
case Add: cf = new ASTliteral(comp, lv + rv); break;
case Sub: cf = new ASTliteral(comp, lv - rv); break;
case Mod: cf = new ASTliteral(comp, rv ? lv % rv : 0); break;
case Equal: cf = new ASTliteral(comp, lv == rv ? 1 : 0); break;
case NotEqual: cf = new ASTliteral(comp, lv != rv ? 1 : 0); break;
case Greater: cf = new ASTliteral(comp, lv > rv ? 1 : 0); break;
case Less: cf = new ASTliteral(comp, lv < rv ? 1 : 0); break;
case GreaterEqual:
cf = new ASTliteral(comp, lv >= rv ? 1 : 0);
break;
case LessEqual: cf = new ASTliteral(comp, lv <= rv ? 1 : 0); break;
case BitAnd: cf = new ASTliteral(comp, lv & rv); break;
case BitOr: cf = new ASTliteral(comp, lv | rv); break;
case Xor: cf = new ASTliteral(comp, lv ^ rv); break;
case ShiftLeft: cf = new ASTliteral(comp, lv << rv); break;
case ShiftRight: cf = new ASTliteral(comp, lv >> rv); break;
default: break;
}
} else if (left->typespec().is_float()
&& right->typespec().is_float()) {
float lv = dynamic_cast<ASTliteral*>(left)->floatval();
float rv = dynamic_cast<ASTliteral*>(right)->floatval();
switch (op) {
case Mul: cf = new ASTliteral(comp, lv * rv); break;
case Div: cf = new ASTliteral(comp, rv ? lv / rv : 0.0f); break;
case Add: cf = new ASTliteral(comp, lv + rv); break;
case Sub: cf = new ASTliteral(comp, lv - rv); break;
case Equal: cf = new ASTliteral(comp, lv == rv ? 1 : 0); break;
case NotEqual: cf = new ASTliteral(comp, lv != rv ? 1 : 0); break;
case Greater: cf = new ASTliteral(comp, lv > rv ? 1 : 0); break;
case Less: cf = new ASTliteral(comp, lv < rv ? 1 : 0); break;
case GreaterEqual:
cf = new ASTliteral(comp, lv >= rv ? 1 : 0);
break;
case LessEqual: cf = new ASTliteral(comp, lv <= rv ? 1 : 0); break;
default: break;
}
}
if (cf) {
delete left;
delete right;
return cf;
}
}
return new ASTbinary_expression(comp, op, left, right);
}
const char*
ASTbinary_expression::childname(size_t i) const
{
static const char* name[] = { "left", "right" };
return name[i];
}
const char *
ASTbinary_expression::opname () const
const char*
ASTbinary_expression::opname() const
{
// clang-format off
switch (m_op) {
+4
View File
@@ -832,6 +832,10 @@ public:
ASTbinary_expression(OSLCompilerImpl* comp, Operator op, ASTNode* left,
ASTNode* right);
// Special consructor wrapper that can collapse ops between literals
static ASTNode* make(OSLCompilerImpl* comp, Operator op, ASTNode* left,
ASTNode* right);
const char* nodetypename() const { return "binary_expression"; }
const char* childname(size_t i) const;
const char* opname() const;
+3 -2
View File
@@ -701,11 +701,12 @@ OSLCompilerImpl::write_oso_const_value(const ConstantSymbol* sym) const
osofmt("{}{}", sym->get_int(i), nelements > 1 ? " " : "");
else if (elemtype == TypeDesc::FLOAT)
for (int i = 0; i < nelements; ++i)
osofmt("{}{}", sym->floatval(i), nelements > 1 ? " " : "");
osofmt("{:.9g}{}", sym->floatval(i), nelements > 1 ? " " : "");
else if (equivalent(elemtype, TypeDesc::TypeVector))
for (int i = 0; i < nelements; ++i) {
Vec3 v = sym->get_vec3(i);
osofmt("{} {} {}{}", v.x, v.y, v.z, nelements > 1 ? " " : "");
osofmt("{:.9g} {:.9g} {:.9g}{}", v.x, v.y, v.z,
nelements > 1 ? " " : "");
}
else {
OSL_ASSERT(0 && "Don't know how to output this constant type");
+18 -18
View File
@@ -858,109 +858,109 @@ variable_ref
binary_expression
: expression OR_OP expression
{
$$ = new ASTbinary_expression (oslcompiler,
$$ = ASTbinary_expression::make(oslcompiler,
ASTNode::Or, $1, $3);
$$->sourceline (@2.first_line);
}
| expression AND_OP expression
{
$$ = new ASTbinary_expression (oslcompiler,
$$ = ASTbinary_expression::make(oslcompiler,
ASTNode::And, $1, $3);
$$->sourceline (@2.first_line);
}
| expression '|' expression
{
$$ = new ASTbinary_expression (oslcompiler,
$$ = ASTbinary_expression::make(oslcompiler,
ASTNode::BitOr, $1, $3);
$$->sourceline (@2.first_line);
}
| expression '^' expression
{
$$ = new ASTbinary_expression (oslcompiler,
$$ = ASTbinary_expression::make(oslcompiler,
ASTNode::Xor, $1, $3);
$$->sourceline (@2.first_line);
}
| expression '&' expression
{
$$ = new ASTbinary_expression (oslcompiler,
$$ = ASTbinary_expression::make(oslcompiler,
ASTNode::BitAnd, $1, $3);
$$->sourceline (@2.first_line);
}
| expression EQ_OP expression
{
$$ = new ASTbinary_expression (oslcompiler,
$$ = ASTbinary_expression::make(oslcompiler,
ASTNode::Equal, $1, $3);
$$->sourceline (@2.first_line);
}
| expression NE_OP expression
{
$$ = new ASTbinary_expression (oslcompiler,
$$ = ASTbinary_expression::make(oslcompiler,
ASTNode::NotEqual, $1, $3);
$$->sourceline (@2.first_line);
}
| expression '>' expression
{
$$ = new ASTbinary_expression (oslcompiler,
$$ = ASTbinary_expression::make(oslcompiler,
ASTNode::Greater, $1, $3);
$$->sourceline (@2.first_line);
}
| expression GE_OP expression
{
$$ = new ASTbinary_expression (oslcompiler,
$$ = ASTbinary_expression::make(oslcompiler,
ASTNode::GreaterEqual, $1, $3);
$$->sourceline (@2.first_line);
}
| expression '<' expression
{
$$ = new ASTbinary_expression (oslcompiler,
$$ = ASTbinary_expression::make(oslcompiler,
ASTNode::Less, $1, $3);
$$->sourceline (@2.first_line);
}
| expression LE_OP expression
{
$$ = new ASTbinary_expression (oslcompiler,
$$ = ASTbinary_expression::make(oslcompiler,
ASTNode::LessEqual, $1, $3);
$$->sourceline (@2.first_line);
}
| expression SHL_OP expression
{
$$ = new ASTbinary_expression (oslcompiler,
$$ = ASTbinary_expression::make(oslcompiler,
ASTNode::ShiftLeft, $1, $3);
$$->sourceline (@2.first_line);
}
| expression SHR_OP expression
{
$$ = new ASTbinary_expression (oslcompiler,
$$ = ASTbinary_expression::make(oslcompiler,
ASTNode::ShiftRight, $1, $3);
$$->sourceline (@2.first_line);
}
| expression '+' expression
{
$$ = new ASTbinary_expression (oslcompiler,
$$ = ASTbinary_expression::make(oslcompiler,
ASTNode::Add, $1, $3);
$$->sourceline (@2.first_line);
}
| expression '-' expression
{
$$ = new ASTbinary_expression (oslcompiler,
$$ = ASTbinary_expression::make(oslcompiler,
ASTNode::Sub, $1, $3);
$$->sourceline (@2.first_line);
}
| expression '*' expression
{
$$ = new ASTbinary_expression (oslcompiler,
$$ = ASTbinary_expression::make(oslcompiler,
ASTNode::Mul, $1, $3);
$$->sourceline (@2.first_line);
}
| expression '/' expression
{
$$ = new ASTbinary_expression (oslcompiler,
$$ = ASTbinary_expression::make(oslcompiler,
ASTNode::Div, $1, $3);
$$->sourceline (@2.first_line);
}
| expression '%' expression
{
$$ = new ASTbinary_expression (oslcompiler,
$$ = ASTbinary_expression::make(oslcompiler,
ASTNode::Mod, $1, $3);
$$->sourceline (@2.first_line);
}
-12
View File
@@ -397,15 +397,6 @@ OSLCompilerImpl::osl_parse_buffer (const std::string &preprocessed_buffer)
// Thread safety with the lexer/parser
std::lock_guard<std::mutex> lock(oslcompiler_mutex);
#ifndef OIIO_STRUTIL_HAS_STOF
// Force classic "C" locale for correct '.' decimal parsing.
// N.B. This is not safe in a multi-threaded program where another
// application thread is expecting the native locale to work properly.
// This is not necessary for versions of OIIO that have Strutil::stof,
// and we can remove it entirely when OIIO 1.9 is the minimum.
std::locale oldlocale = std::locale::global (std::locale::classic());
#endif
yyscan_t scanner;
yylex_init(&scanner);
YY_BUFFER_STATE buffer = yy_scan_string(preprocessed_buffer.c_str(), scanner);
@@ -415,9 +406,6 @@ OSLCompilerImpl::osl_parse_buffer (const std::string &preprocessed_buffer)
yy_delete_buffer (buffer, scanner);
yylex_destroy(scanner);
#ifndef OIIO_STRUTIL_HAS_STOF
std::locale::global (oldlocale); // Restore the original locale.
#endif
return parseerr;
}
+4
View File
@@ -143,6 +143,10 @@ Symbol::print(std::ostream& out, int maxvals) const
out << " renderer-output";
if (symtype() == SymTypeParam && !lockgeom())
out << " lockgeom=0";
if (symtype() == SymTypeParam && interactive())
out << " interactive=1";
if (symtype() == SymTypeParam && noninteractive())
out << " interactive=0";
}
out << "\n";
if (symtype() == SymTypeConst) {
+1 -1
View File
@@ -123,7 +123,7 @@ set (lib_src
llvm_gen.cpp llvm_instance.cpp llvm_util.cpp
rs_fallback.cpp
)
if (BUILD_BATCHED)
if (OSL_BUILD_BATCHED)
list(APPEND lib_src
batched_analysis.cpp
batched_backendllvm.cpp
+21 -72
View File
@@ -6,10 +6,6 @@
#include <OpenImageIO/filesystem.h>
#include <OpenImageIO/strutil.h>
#ifdef OSL_USE_OPTIX
# include <optix.h>
#endif
#include "oslexec_pvt.h"
#include "backendllvm.h"
@@ -21,55 +17,6 @@ OSL_NAMESPACE_ENTER
namespace pvt {
#ifdef OSL_SPI
static void
check_cwd(ShadingSystemImpl& shadingsys)
{
std::string err;
char pathname[1024] = { "" };
if (!getcwd(pathname, sizeof(pathname) - 1)) {
int e = errno;
err += fmtformat("Failed getcwd(), errno is {}: {}\n", errno, pathname);
if (e == EACCES || e == ENOENT) {
err += "Read/search permission problem or dir does not exist.\n";
const char* pwdenv = getenv("PWD");
if (!pwdenv) {
err += "$PWD is not even found in the environment.\n";
} else {
err += fmtformat("$PWD is \"{}\"\n", pwdenv);
err += fmtformat("That {}.\n", OIIO::Filesystem::exists(pwdenv)
? "exists"
: "does NOT exist");
err += fmtformat("That {} a directory.\n",
OIIO::Filesystem::is_directory(pwdenv)
? "is"
: "is NOT");
std::vector<std::string> pieces;
Strutil::split(pwdenv, pieces, "/");
std::string p;
for (size_t i = 0; i < pieces.size(); ++i) {
if (!pieces[i].size())
continue;
p += "/";
p += pieces[i];
err += fmtformat(" {} : {} and is{} a directory.\n", p,
OIIO::Filesystem::exists(p)
? "exists"
: "does NOT exist",
OIIO::Filesystem::is_directory(p)
? ""
: " NOT");
}
}
}
}
if (err.size())
shadingsys.error(err);
}
#endif
BackendLLVM::BackendLLVM(ShadingSystemImpl& shadingsys, ShaderGroup& group,
ShadingContext* ctx)
: OSOProcessorBase(shadingsys, group, ctx)
@@ -80,12 +27,7 @@ BackendLLVM::BackendLLVM(ShadingSystemImpl& shadingsys, ShaderGroup& group,
, m_stat_llvm_opt_time(0)
, m_stat_llvm_jit_time(0)
{
#ifdef OSL_SPI
// Temporary (I hope) check to diagnose an intermittent failure of
// getcwd inside LLVM. Oy.
check_cwd(shadingsys);
#endif
m_use_optix = shadingsys.renderer()->supports("OptiX");
m_use_optix = shadingsys.use_optix();
m_use_rs_bitcode = !shadingsys.m_rs_bitcode.empty();
m_name_llvm_syms = shadingsys.m_llvm_output_bitcode;
@@ -284,6 +226,15 @@ BackendLLVM::getLLVMSymbolBase(const Symbol& sym)
llvm_type(sym.typespec().elementtype()));
return result;
}
if (sym.symtype() == SymTypeParam && sym.interactive()) {
// Special case for interactively-edited parameters -- they live in
// the interactive data block for the group.
// Generate the pointer to this symbol by offsetting into the
// interactive data block.
int offset = group().interactive_param_offset(layer(), sym.name());
return ll.offset_ptr(m_llvm_interactive_params_ptr, offset,
llvm_ptr_type(sym.typespec().elementtype()));
}
if (sym.symtype() == SymTypeParam || sym.symtype() == SymTypeOutputParam) {
// Special case for params -- they live in the group data
@@ -339,6 +290,7 @@ BackendLLVM::getOrAllocateLLVMSymbol(const Symbol& sym)
#if OSL_USE_OPTIX
llvm::Value*
BackendLLVM::addCUDAGlobalVariable(const std::string& name, int size,
int alignment, const void* init_data,
@@ -354,7 +306,7 @@ BackendLLVM::addCUDAGlobalVariable(const std::string& name, int size,
} else if (type == TypeDesc::TypeInt) {
constant = ll.constant(*(const int*)init_data);
} else if (type == TypeDesc::TypeString) {
constant = ll.constant(((const ustring*)init_data)->hash());
constant = ll.constant64(((const ustring*)init_data)->hash());
// N.B. Since this is the OptiX side specifically, we will represent
// strings as the ustringhash, so we know it as a constant.
} else {
@@ -369,11 +321,11 @@ BackendLLVM::addCUDAGlobalVariable(const std::string& name, int size,
OSL_DASSERT(g_var && "Unable to create GlobalVariable");
#if OSL_LLVM_VERSION >= 100
# if OSL_LLVM_VERSION >= 100
g_var->setAlignment(llvm::MaybeAlign(alignment));
#else
# else
g_var->setAlignment(alignment);
#endif
# endif
g_var->setLinkage(llvm::GlobalValue::PrivateLinkage);
g_var->setVisibility(llvm::GlobalValue::DefaultVisibility);
@@ -391,14 +343,7 @@ BackendLLVM::getOrAllocateCUDAVariable(const Symbol& sym)
OSL_ASSERT(use_optix()
&& "This function is only supported when using OptiX!");
// 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);
std::string name
= fmtformat("{}{}_{}_{}_{}", sym_name.front() == '$' ? "_" : "",
sym_name, group().name(), inst()->layername(), sym.layer());
std::string name = global_unique_symname(sym);
// Return the Value if it has already been allocated
auto it = get_const_map().find(name);
@@ -412,6 +357,7 @@ BackendLLVM::getOrAllocateCUDAVariable(const Symbol& sym)
return addCUDAGlobalVariable(name, sym.size(), alignment, sym.data(),
sym.typespec().simpletype());
}
#endif
@@ -429,6 +375,7 @@ BackendLLVM::llvm_get_pointer(const Symbol& sym, int deriv,
llvm::Value* result = NULL;
if (sym.symtype() == SymTypeConst) {
TypeSpec elemtype = sym.typespec().elementtype();
#if OSL_USE_OPTIX
if (use_optix()) {
// Check the constant map for the named Symbol; if it's found, then
// a GlobalVariable has been created for it
@@ -439,7 +386,9 @@ BackendLLVM::llvm_get_pointer(const Symbol& sym, int deriv,
// N.B. llvm_typedesc() for a string will know that on OptiX,
// strings are actually represented as just the hash.
}
} else {
} else
#endif
{
// For constants on the CPU side, start with *OUR* pointer to the
// constant values.
result = ll.constant_ptr(sym.data(),
+69 -10
View File
@@ -216,6 +216,21 @@ public:
/// map, the symbol is alloca'd and placed in the map.
llvm::Value* getOrAllocateLLVMSymbol(const Symbol& sym);
#if OSL_USE_OPTIX
/// Return a globally unique (to the JIT module) name for symbol `sym`,
/// assuming it's part of the currently examined layer of the group.
std::string global_unique_symname(const Symbol& sym)
{
// We need to sanitize the symbol name for PTX compatibility. Also, if
// the sym name starts with a dollar sign, which are not allowed in
// PTX variable names, then prepend another underscore.
auto sym_name = Strutil::replace(sym.name(), ".", "_", true);
int layer = sym.layer();
const ShaderInstance* inst_ = group()[layer];
return fmtformat("{}{}_{}_{}_{}", sym_name.front() == '$' ? "_" : "",
sym_name, group().name(), inst_->layername(), layer);
}
/// Allocate a CUDA variable for the given OSL symbol and return a pointer
/// to the corresponding LLVM GlobalVariable, or return the pointer if it
/// has already been allocated.
@@ -229,6 +244,7 @@ public:
llvm::Value* addCUDAGlobalVariable(const std::string& name, int size,
int alignment, const void* init_data,
TypeDesc type = TypeDesc::UNKNOWN);
#endif
/// Retrieve an llvm::Value that is a pointer holding the start address
/// of the specified symbol. This always works for globals and params;
@@ -266,14 +282,20 @@ public:
/// Return the ShaderGlobals pointer.
///
llvm::Value* sg_ptr() const { return m_llvm_shaderglobals_ptr; }
llvm::Value* sg_ptr() const
{
return m_llvm_shaderglobals_ptr;
}
llvm::Type* llvm_type_closure_component();
llvm::Type* llvm_type_closure_component_ptr();
/// Return the ShaderGlobals pointer cast as a void*.
///
llvm::Value* sg_void_ptr() { return ll.void_ptr(m_llvm_shaderglobals_ptr); }
llvm::Value* sg_void_ptr()
{
return ll.void_ptr(m_llvm_shaderglobals_ptr);
}
/// Cast the pointer variable specified by val to a pointer to the
/// basic type comprising `type`.
@@ -299,7 +321,10 @@ public:
/// Return the group data pointer.
///
llvm::Value* groupdata_ptr() const { return m_llvm_groupdata_ptr; }
llvm::Value* groupdata_ptr() const
{
return m_llvm_groupdata_ptr;
}
/// Return the group data pointer cast as a void*.
///
@@ -317,13 +342,22 @@ public:
TypeDesc type = TypeDesc::UNKNOWN);
/// Return the userdata base pointer.
llvm::Value* userdata_base_ptr() const { return m_llvm_userdata_base_ptr; }
llvm::Value* userdata_base_ptr() const
{
return m_llvm_userdata_base_ptr;
}
/// Return the output base pointer.
llvm::Value* output_base_ptr() const { return m_llvm_output_base_ptr; }
llvm::Value* output_base_ptr() const
{
return m_llvm_output_base_ptr;
}
/// Return the shade index
llvm::Value* shadeindex() const { return m_llvm_shadeindex; }
llvm::Value* shadeindex() const
{
return m_llvm_shadeindex;
}
// For a symloc, compute the llvm::Value of the pointer to its true,
// offset location from the base pointer for shade index `sindex`
@@ -429,6 +463,13 @@ public:
return ll.llvm_type(llvm_typedesc(typespec));
}
/// Generate the appropriate llvm type definition for a pointer to
/// the type specified by the TypeSpec.
llvm::Type* llvm_ptr_type(const TypeSpec& typespec)
{
return ll.type_ptr(ll.llvm_type(llvm_typedesc(typespec)));
}
/// Generate the parameter-passing llvm type definition for an OSL
/// TypeSpec.
llvm::Type* llvm_pass_type(const TypeSpec& typespec);
@@ -444,7 +485,10 @@ public:
/// Return the basic block of the exit for the whole instance.
///
bool llvm_has_exit_instance_block() const { return m_exit_instance_block; }
bool llvm_has_exit_instance_block() const
{
return m_exit_instance_block;
}
/// Return the basic block of the exit for the whole instance.
///
@@ -465,7 +509,10 @@ public:
/// Print debugging line for the op
void llvm_generate_debug_op_printf(const Opcode& op);
llvm::Function* layer_func() const { return ll.current_function(); }
llvm::Function* layer_func() const
{
return ll.current_function();
}
/// Call this when JITing a texture-like call, to track how many.
void generated_texture_call(bool handle)
@@ -475,6 +522,11 @@ public:
shadingsys().m_stat_tex_calls_as_handles += 1;
}
void increment_useparam_ops()
{
shadingsys().m_stat_useparam_ops++;
}
/// Return the mapping from symbol names to GlobalVariables.
std::map<std::string, llvm::GlobalVariable*>& get_const_map()
{
@@ -482,10 +534,16 @@ public:
}
/// Return whether or not we are compiling for an OptiX-based renderer.
bool use_optix() { return m_use_optix; }
bool use_optix()
{
return m_use_optix;
}
/// Return if we should compile against free function versions of Renderer Service.
bool use_rs_bitcode() { return m_use_rs_bitcode; }
bool use_rs_bitcode()
{
return m_use_rs_bitcode;
}
/// Return the userdata index for the given Symbol. Return -1 if the Symbol
/// is not an input parameter or is constant and therefore doesn't have an
@@ -522,6 +580,7 @@ private:
std::map<const Symbol*, int> m_param_order_map;
llvm::Value* m_llvm_shaderglobals_ptr;
llvm::Value* m_llvm_groupdata_ptr;
llvm::Value* m_llvm_interactive_params_ptr;
llvm::Value* m_llvm_userdata_base_ptr;
llvm::Value* m_llvm_output_base_ptr;
llvm::Value* m_llvm_shadeindex;
+12
View File
@@ -2303,6 +2303,17 @@ struct Analyzer {
}
}
void make_closures_varying()
{
// We assume that closures are always stored as varying pointers
FOREACH_PARAM(Symbol & s, inst())
{
if (s.typespec().is_closure()) {
recursively_mark_varying(&s);
}
}
}
void push_varying_of_upstream_connections()
{
OSL_DEV_ONLY(std::cout << "connections to layer begin" << std::endl);
@@ -2395,6 +2406,7 @@ BatchedAnalysis::analyze_layer(ShaderInstance* inst)
analyzer.push_varying_of_shader_globals();
analyzer.make_interpolated_parameters_varying();
analyzer.make_renderer_outputs_varying();
analyzer.make_closures_varying();
analyzer.push_varying_of_upstream_connections();
analyzer.push_varying_of_implicitly_varying_ops();
+10
View File
@@ -448,6 +448,16 @@ BatchedBackendLLVM::getLLVMSymbolBase(const Symbol& sym)
return result;
}
if (sym.symtype() == SymTypeParam && sym.interactive()) {
// Special case for interactively-edited parameters -- they live in
// the interactive data block for the group.
// Generate the pointer to this symbol by offsetting into the
// interactive data block.
int offset = group().interactive_param_offset(layer(), sym.name());
return ll.offset_ptr(m_llvm_interactive_params_ptr, offset,
llvm_ptr_type(sym.typespec().elementtype()));
}
if (sym.symtype() == SymTypeParam || sym.symtype() == SymTypeOutputParam) {
// Special case for params -- they live in the group data
int fieldnum = m_param_order_map[&sym];
+12 -4
View File
@@ -6,8 +6,6 @@
#pragma once
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "oslexec_pvt.h"
@@ -15,7 +13,7 @@
using namespace OSL;
using namespace OSL::pvt;
#include "OSL/llvm_util.h"
#include <OSL/llvm_util.h>
#include "runtimeoptimize.h"
#include <llvm/ADT/SmallString.h>
@@ -658,6 +656,14 @@ public:
return ll.llvm_vector_type(llvm_typedesc(typespec));
}
/// Generate the appropriate llvm type definition for a pointer to
/// the type specified by the TypeSpec.
llvm::Type* llvm_ptr_type(const TypeSpec& typespec)
{
return reinterpret_cast<llvm::Type*>(
ll.type_ptr(ll.llvm_type(llvm_typedesc(typespec))));
}
/// Generate the parameter-passing llvm type definition for an OSL
/// TypeSpec.
llvm::Type* llvm_pass_type(const TypeSpec& typespec);
@@ -705,6 +711,8 @@ public:
shadingsys().m_stat_tex_calls_as_handles += 1;
}
void increment_useparam_ops() { shadingsys().m_stat_useparam_ops++; }
void llvm_print_mask(const char* title, llvm::Value* mask = nullptr);
/// Return the userdata index for the given Symbol. Return -1 if the Symbol
@@ -781,7 +789,7 @@ private:
std::map<const Symbol*, int> m_param_order_map;
llvm::Value* m_llvm_shaderglobals_ptr;
llvm::Value* m_llvm_groupdata_ptr;
llvm::Value* m_llvm_interactive_params_ptr;
llvm::Value* m_llvm_wide_shadeindex_ptr;
llvm::Value* m_llvm_userdata_base_ptr;
llvm::Value* m_llvm_output_base_ptr;
+110 -25
View File
@@ -92,13 +92,17 @@ BatchedBackendLLVM::llvm_call_layer(int layer, bool unconditional)
<< " unconditional=" << unconditional << std::endl);
// Make code that looks like:
// if (! groupdata->run[parentlayer])
// parent_layer (sg, groupdata);
// parent_layer (sg, groupdata, wide_shadeindex_ptr,
// userdata_base_ptr, output_base_ptr,
// execution_mask, interactive_params_ptr);
// if it's a conditional call, or
// parent_layer (sg, groupdata);
// parent_layer (sg, groupdata, wide_shadeindex_ptr,
// userdata_base_ptr, output_base_ptr,
// execution_mask, interactive_params_ptr);
// if it's run unconditionally.
// The code in the parent layer itself will set its 'executed' flag.
llvm::Value* args[6];
llvm::Value* args[7];
args[0] = sg_ptr();
args[1] = groupdata_ptr();
args[2] = ll.void_ptr(wide_shadeindex_ptr());
@@ -120,13 +124,11 @@ BatchedBackendLLVM::llvm_call_layer(int layer, bool unconditional)
llvm::Value* execution_required
= ll.op_ne(lanes_requiring_execution_value, ll.constant(0));
then_block = ll.new_basic_block(
llvm_debug()
? std::string("then layer ").append(std::to_string(layer))
: std::string());
llvm_debug() ? Strutil::fmt::format("then layer {}", layer)
: std::string());
after_block = ll.new_basic_block(
llvm_debug()
? std::string("after layer ").append(std::to_string(layer))
: std::string());
llvm_debug() ? Strutil::fmt::format("after layer {}", layer)
: std::string());
ll.op_branch(execution_required, then_block, after_block);
// insert point is now then_block
} else {
@@ -134,6 +136,7 @@ BatchedBackendLLVM::llvm_call_layer(int layer, bool unconditional)
}
args[5] = lanes_requiring_execution_value;
args[6] = m_llvm_interactive_params_ptr;
// Before the merge, keeping in case we broke it
//std::string name = fmtformat("{}_{}_{}", m_library_selector, parent->layername().c_str(),
@@ -149,6 +152,8 @@ BatchedBackendLLVM::llvm_call_layer(int layer, bool unconditional)
if (!unconditional)
ll.op_branch(after_block); // also moves insert point
shadingsys().m_stat_call_layers_inserted++;
}
@@ -199,6 +204,15 @@ BatchedBackendLLVM::llvm_run_connected_layers(const Symbol& sym, int symindex,
}
}
if (shadingsys().m_opt_useparam && inmain) {
// m_call_layers_inserted tracks if we've already run this layer inside the current basic block
const CallLayerKey key = { m_bblockids[opnum], con.srclayer };
if (m_call_layers_inserted.count(key)) {
continue;
}
m_call_layers_inserted.insert(key);
}
// If the earlier layer it comes from has not yet been
// executed, do so now.
llvm_call_layer(con.srclayer);
@@ -236,13 +250,16 @@ LLVMGEN(llvm_gen_useparam)
// initializing them lazily, now we have to do it.
if ((sym.symtype() == SymTypeParam
|| sym.symtype() == SymTypeOutputParam)
&& !sym.lockgeom() && !sym.typespec().is_closure()
&& sym.interpolated() && !sym.typespec().is_closure()
&& !sym.connected() && !sym.connected_down()
&& rop.shadingsys().lazy_userdata()) {
rop.llvm_assign_initial_value(sym, rop.ll.mask_as_int(
rop.ll.current_mask()));
}
}
rop.increment_useparam_ops();
return true;
}
@@ -1263,6 +1280,7 @@ LLVMGEN(llvm_gen_add)
OSL_ASSERT(!A.typespec().is_array() && !B.typespec().is_array());
if (Result.typespec().is_closure()) {
OSL_ASSERT(A.typespec().is_closure() && B.typespec().is_closure());
OSL_ASSERT(!A.is_uniform() && !B.is_uniform() && !result_is_uniform);
llvm::Value* valargs[] = { rop.sg_void_ptr(), rop.llvm_void_ptr(Result),
rop.llvm_void_ptr(A), rop.llvm_void_ptr(B),
rop.ll.mask_as_int(rop.ll.current_mask()) };
@@ -1676,6 +1694,7 @@ LLVMGEN(llvm_gen_modulus)
int num_components = type.aggregate;
#if 0
if (is_float && !op_is_uniform) {
// llvm 5.0.1 did not do a good job with op_mod when its
// parameters were <16xf32>. So we will go ahead
@@ -1702,7 +1721,9 @@ LLVMGEN(llvm_gen_modulus)
}
rop.ll.call_function(rop.build_name(func_spec), call_args);
} else {
} else
#endif
{
for (int i = 0; i < num_components; i++) {
llvm::Value* a = rop.loadLLVMValue(A, i, 0, type, op_is_uniform);
llvm::Value* b = rop.loadLLVMValue(B, i, 0, type, op_is_uniform);
@@ -7064,7 +7085,8 @@ LLVMGEN(llvm_gen_spline)
static void
llvm_gen_keyword_fill(BatchedBackendLLVM& rop, Opcode& op,
const ClosureRegistry::ClosureEntry* clentry,
ustring clname, llvm::Value* mem_void_ptr, int argsoffset)
ustring clname, llvm::Value* mem_void_ptr, int argsoffset,
int lane_index)
{
OSL_DASSERT(((op.nargs() - argsoffset) % 2) == 0);
@@ -7088,10 +7110,45 @@ llvm_gen_keyword_fill(BatchedBackendLLVM& rop, Opcode& op,
if (equivalent(p.type, ValueType) && !strcmp(key->c_str(), p.key)) {
// store data
OSL_DASSERT(p.offset + p.field_size <= clentry->struct_size);
llvm::Value* dst = rop.ll.offset_ptr(mem_void_ptr, p.offset);
llvm::Value* src = rop.llvm_void_ptr(Value);
rop.ll.op_memcpy(dst, src, (int)p.type.size(),
4 /* use 4 byte alignment for now */);
bool arg_is_uniform = Value.is_uniform();
TypeDesc simpletype(Value.typespec().simpletype());
// We don't currently offer a helper macro in genclosure.h for creating
// keyword array parameters, so perhaps we can assume we don't need to
// support them
OSL_DASSERT(simpletype.arraylen == 0);
int num_components = simpletype.aggregate;
llvm::Value* dest_base = rop.ll.offset_ptr(mem_void_ptr,
p.offset);
dest_base = rop.llvm_ptr_cast(dest_base, p.type);
for (int c = 0; c < num_components; c++) {
llvm::Value* dest_elem;
if (num_components > 1)
dest_elem = rop.ll.GEP(dest_base, 0, c);
else
dest_elem = dest_base;
// NOTE: We don't want any uniform arguments to be
// widened, so our typical op_is_uniform doesn't do what we
// want for this when loading. So just pass arg_is_uniform
// which will avoid widening any uniform arguments.
llvm::Value* loaded
= rop.llvm_load_value(Value, 0, NULL, c,
TypeDesc::UNKNOWN,
/*op_is_uniform*/ arg_is_uniform,
/*index_is_uniform*/ true);
if (!arg_is_uniform) {
loaded = rop.ll.op_extract(loaded, lane_index);
}
rop.ll.op_unmasked_store(loaded, dest_elem);
}
legal = true;
break;
}
@@ -7180,6 +7237,7 @@ 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
@@ -7193,14 +7251,16 @@ LLVMGEN(llvm_gen_closure)
// For the weighted closures, we need a surrounding "if" so that it's safe
// for osl_allocate_weighted_closure_component to return NULL (unless we
// know for sure that it's constant weighted and that the weight is
// not zero).
// not zero). We also need the surrounding "if" to reject writing
// to closures that aren't masked.
llvm::BasicBlock* next_block = NULL;
llvm::BasicBlock* notnull_block = rop.ll.new_basic_block(
"non_null_closure");
next_block = rop.ll.new_basic_block("");
llvm::Value* cond
= rop.ll.op_ne(rop.ll.ptr_cast(comp_ptr, rop.ll.type_void_ptr()),
rop.ll.void_ptr_null());
"non_null_and_masked_closure");
next_block = rop.ll.new_basic_block("");
llvm::Value* cond = rop.ll.op_and(
rop.ll.op_ne(rop.ll.ptr_cast(comp_ptr, rop.ll.type_void_ptr()),
rop.ll.void_ptr_null()),
rop.ll.test_mask_lane(mask, lane_index));
rop.ll.op_branch(cond, notnull_block, next_block);
// If the closure has a "prepare" method, call
@@ -7233,7 +7293,30 @@ LLVMGEN(llvm_gen_closure)
int num_components = simpletype.aggregate;
llvm::Value* dest_base = rop.ll.offset_ptr(mem_void_ptr, p.offset);
dest_base = rop.llvm_ptr_cast(dest_base, p.type);
llvm::Type* dest_type = rop.ll.llvm_type(
static_cast<const TypeSpec&>(p.type).simpletype());
dest_base = rop.ll.ptr_to_cast(dest_base, dest_type);
if (num_elements > 1) {
OSL_DASSERT(rop.ll.is_type_array(dest_type));
// The type is an array type,
// which means our pointer is to an array type,
// not to &[0] (the address of the 1st element).
// IE: typedef int Int5Array[5];
// Int5Array *dest_base;
// in contrast to what most of use might consider an array pointer
// int *dest_base;
// So if we dereference Int5Array* to with [4], the 5th element,
// we would be really be pointing to ((int *)dest_base)[5*4] which is
// out of bounds of our 1 instance of Int5Array.
// Thus when dealing with arrays we will just dereference it and get the address to get
// the address of the 1st element.
dest_base = rop.ll.GEP(dest_type, dest_base, 0, 0);
llvm::Type* element_type = rop.ll.element_type_of(dest_type);
dest_type = element_type;
}
for (int a = 0; a < num_elements; ++a) {
llvm::Value* arrind = simpletype.arraylen ? rop.ll.constant(a)
@@ -7241,7 +7324,9 @@ LLVMGEN(llvm_gen_closure)
for (int c = 0; c < num_components; c++) {
llvm::Value* dest_elem;
if (num_components > 1)
dest_elem = rop.ll.GEP(dest_base, a, c);
dest_elem = rop.ll.GEP(dest_type, dest_base, a, c);
else if (num_elements > 1)
dest_elem = rop.ll.GEP(dest_type, dest_base, a);
else
dest_elem = dest_base;
@@ -7275,7 +7360,7 @@ LLVMGEN(llvm_gen_closure)
}
llvm_gen_keyword_fill(rop, op, clentry, closure_name, mem_void_ptr,
2 + weighted + clentry->nformal);
2 + weighted + clentry->nformal, lane_index);
if (next_block)
rop.ll.op_branch(next_block);
+91 -46
View File
@@ -63,8 +63,19 @@ Schematically, we want to create code that resembles the following:
float param_1_bar;
};
// Data for the interactively adjusted parameters of this group -- these
// can't be turned into constants because the app may want to modify them
// as it runs (such as for user interaction). This block of memory has
// one global copy specific each the shader group, managed by OSL.
struct InteractiveParams {
float iparam_0_baz;
};
// Name of layer entry is $layer_ID
void $layer_0 (ShaderGlobals *sg, GroupData_1 *group)
void $layer_0(ShaderGlobals *sg, GroupData_1 *group,
wide_int* wide_shadeindex_ptr,
void* userdatda_base_ptr, void* output_base_ptr,
int mask, InteractiveParams* interactive_params)
{
// Declare locals, temps, constants, params with known values.
// Make them all look like stack memory locations:
@@ -74,9 +85,14 @@ Schematically, we want to create code that resembles the following:
// then run the shader body:
*x = sg->u * group->param_0_bar;
group->param_1_foo = *x;
*x += interactive_params->iparam_0_baz;
// ...
}
void $layer_1 (ShaderGlobals *sg, GroupData_1 *group)
void $layer_1(ShaderGlobals *sg, GroupData_1 *group,
wide_int* wide_shadeindex_ptr,
void* userdatda_base_ptr, void* output_base_ptr,
int mask, InteractiveParams* interactive_params)
{
// Because we need the outputs of layer 0 now, we call it if it
// hasn't already run:
@@ -87,7 +103,10 @@ Schematically, we want to create code that resembles the following:
*y = sg->u * group->$param_1_bar;
}
void $group_1 (ShaderGlobals *sg, GroupData_1 *group)
void $group_1(ShaderGlobals *sg, GroupData_1 *group,
wide_int* wide_shadeindex_ptr,
void* userdatda_base_ptr, void* output_base_ptr,
int mask, InteractiveParams* interactive_params)
{
group->layer_run[...] = 0;
// Run just the unconditional layers
@@ -901,14 +920,13 @@ BatchedBackendLLVM::llvm_type_groupdata()
if (offset & (align - 1))
offset += align - (offset & (align - 1));
if (llvm_debug() >= 2)
std::cout << " " << inst->layername() << " (" << inst->id()
<< ") " << sym.mangled() << " " << ts.c_str()
<< ", field " << order << ", size "
<< derivSize * int(sym.size()) << ", offset "
<< offset << std::endl;
print(" {} ({}) {} {}, field {}, size {}, offset {}{}{}\n",
inst->layername(), inst->id(), sym.mangled(), ts.c_str(),
order, derivSize * int(sym.size()), offset,
sym.interpolated() ? " (interpolated)" : "",
sym.interactive() ? " (interactive)" : "");
sym.wide_dataoffset((int)offset);
offset += derivSize * int(sym.size()) * m_width;
m_param_order_map[&sym] = order;
++order;
}
@@ -1041,10 +1059,10 @@ BatchedBackendLLVM::llvm_assign_initial_value(
llvm_assign_zero(sym);
return; // we're done, the parts below are just for params
}
ASSERT_MSG(sym.symtype() == SymTypeParam
|| sym.symtype() == SymTypeOutputParam,
"symtype was %d, data type was %s", (int)sym.symtype(),
sym.typespec().c_str());
OSL_ASSERT_MSG(sym.symtype() == SymTypeParam
|| sym.symtype() == SymTypeOutputParam,
"symtype was %d, data type was %s", (int)sym.symtype(),
sym.typespec().c_str());
// Handle interpolated params by calling osl_bind_interpolated_param,
// which will check if userdata is already retrieved, if not it will
@@ -1059,7 +1077,7 @@ BatchedBackendLLVM::llvm_assign_initial_value(
bool partial_userdata_mask_was_pushed = false;
const SymLocationDesc* symloc = nullptr;
LLVM_Util::ScopedMasking partial_data_masking_scope;
if (!sym.lockgeom() && !sym.typespec().is_closure()) {
if (sym.interpolated() && !sym.typespec().is_closure()) {
ustring symname = sym.name();
TypeDesc type = sym.typespec().simpletype();
@@ -1217,6 +1235,15 @@ BatchedBackendLLVM::llvm_assign_initial_value(
// Handle init ops.
build_llvm_code(sym.initbegin(), sym.initend());
#if 0 /* Is this needed? */
} else if (sym.interpolated() && !sym.typespec().is_closure()) {
// geometrically-varying param; memcpy its default value
TypeDesc t = sym.typespec().simpletype();
ll.op_memcpy(llvm_void_ptr(sym), ll.constant_ptr(sym.data()),
t.size(), t.basesize() /*align*/);
if (sym.has_derivs())
llvm_zero_derivs(sym);
#endif
} else {
// We think the non-memcpy route is preferable as it give the compiler
// a chance to optimize constant values Also memcpy would ignoring the
@@ -1738,16 +1765,17 @@ BatchedBackendLLVM::build_llvm_init()
OSL_ASSERT(m_library_selector);
std::string unique_name = fmtformat("{}_group_{}_init", m_library_selector,
group().id());
ll.current_function(ll.make_function(
unique_name, false,
ll.type_void(), // return type
{
llvm_type_sg_ptr(), llvm_type_groupdata_ptr(),
static_cast<llvm::Type*>(ll.type_void_ptr()), // wide_shader_index
static_cast<llvm::Type*>(ll.type_void_ptr()), // userdata_base_ptr
static_cast<llvm::Type*>(ll.type_void_ptr()), // output_base_ptr
ll.type_int() // mask
}));
ll.current_function(
ll.make_function(unique_name, false,
ll.type_void(), // return type
{
llvm_type_sg_ptr(), llvm_type_groupdata_ptr(),
ll.type_void_ptr(), // wide_shader_index
ll.type_void_ptr(), // userdata_base_ptr
ll.type_void_ptr(), // output_base_ptr
ll.type_int(), // mask
ll.type_void_ptr(), // FIXME: interactive params
}));
if (ll.debug_is_enabled()) {
ustring file_name
@@ -1757,14 +1785,20 @@ BatchedBackendLLVM::build_llvm_init()
}
// Get shader globals and groupdata pointers
m_llvm_shaderglobals_ptr = ll.current_function_arg(0); //arg_it++;
m_llvm_groupdata_ptr = ll.current_function_arg(1); //arg_it++;
m_llvm_shaderglobals_ptr = ll.current_function_arg(0); //arg_it++;
m_llvm_shaderglobals_ptr->setName("shaderglobals_ptr");
m_llvm_groupdata_ptr = ll.current_function_arg(1); //arg_it++;
m_llvm_groupdata_ptr->setName("groupdata_ptr");
m_llvm_wide_shadeindex_ptr = ll.current_function_arg(2); //arg_it++;
m_llvm_userdata_base_ptr = ll.current_function_arg(3); //arg_it++;
m_llvm_output_base_ptr = ll.current_function_arg(4); //arg_it++;
// TODO: do we need to utilize the shader mask in the init function?
//llvm::Value * llvm_initial_shader_mask_value = ll.current_function_arg(5); //arg_it++;
m_llvm_wide_shadeindex_ptr->setName("shadeindex");
m_llvm_userdata_base_ptr = ll.current_function_arg(3); //arg_it++;
m_llvm_userdata_base_ptr->setName("userdata_base_ptr");
m_llvm_output_base_ptr = ll.current_function_arg(4); //arg_it++;
m_llvm_output_base_ptr->setName("output_base_ptr");
llvm::Value* llvm_initial_shader_mask_value = ll.current_function_arg(5);
llvm_initial_shader_mask_value->setName("initial_shader_mask");
m_llvm_interactive_params_ptr = ll.current_function_arg(6); //arg_it++;
m_llvm_interactive_params_ptr->setName("interactive_params_ptr");
// New function, reset temp matrix pointer
m_llvm_temp_wide_matrix_ptr = nullptr;
@@ -1813,6 +1847,7 @@ BatchedBackendLLVM::build_llvm_init()
FOREACH_PARAM(Symbol & sym, gi)
{
if (sym.typespec().is_closure_based()) {
OSL_ASSERT(sym.is_varying());
int arraylen = std::max(1, sym.typespec().arraylength());
llvm::Value* val = ll.constant_ptr(NULL, ll.type_void_ptr());
if (!sym.is_uniform())
@@ -1874,10 +1909,11 @@ BatchedBackendLLVM::build_llvm_instance(bool groupentry)
ll.type_void(), // return type
{
llvm_type_sg_ptr(), llvm_type_groupdata_ptr(),
static_cast<llvm::Type*>(ll.type_void_ptr()), // wide_shader_index
static_cast<llvm::Type*>(ll.type_void_ptr()), // userdata_base_ptr
static_cast<llvm::Type*>(ll.type_void_ptr()), // output_base_ptr
ll.type_int() // mask
ll.type_void_ptr(), // wide_shader_index
ll.type_void_ptr(), // userdata_base_ptr
ll.type_void_ptr(), // output_base_ptr
ll.type_int(), // mask
ll.type_void_ptr(), // FIXME: interactive params
}));
if (ll.debug_is_enabled()) {
@@ -1887,14 +1923,20 @@ BatchedBackendLLVM::build_llvm_instance(bool groupentry)
}
// Get shader globals and groupdata pointers
m_llvm_shaderglobals_ptr = ll.current_function_arg(0); //arg_it++;
m_llvm_groupdata_ptr = ll.current_function_arg(1); //arg_it++;
m_llvm_shaderglobals_ptr = ll.current_function_arg(0); //arg_it++;
m_llvm_shaderglobals_ptr->setName("shaderglobals_ptr");
m_llvm_groupdata_ptr = ll.current_function_arg(1); //arg_it++;
m_llvm_groupdata_ptr->setName("groupdata_ptr");
m_llvm_wide_shadeindex_ptr = ll.current_function_arg(2); //arg_it++;
m_llvm_userdata_base_ptr = ll.current_function_arg(3); //arg_it++;
m_llvm_output_base_ptr = ll.current_function_arg(4); //arg_it++;
llvm::Value* llvm_initial_shader_mask_value = ll.current_function_arg(
5); //arg_it++;
m_llvm_wide_shadeindex_ptr->setName("shadeindex");
m_llvm_userdata_base_ptr = ll.current_function_arg(3); //arg_it++;
m_llvm_userdata_base_ptr->setName("userdata_base_ptr");
m_llvm_output_base_ptr = ll.current_function_arg(4); //arg_it++;
m_llvm_output_base_ptr->setName("output_base_ptr");
llvm::Value* llvm_initial_shader_mask_value = ll.current_function_arg(5);
llvm_initial_shader_mask_value->setName("initial_shader_mask");
m_llvm_interactive_params_ptr = ll.current_function_arg(6); //arg_it++;
m_llvm_interactive_params_ptr->setName("interactive_params_ptr");
// New function, reset temp matrix pointer
m_llvm_temp_wide_matrix_ptr = nullptr;
@@ -2069,10 +2111,12 @@ BatchedBackendLLVM::build_llvm_instance(bool groupentry)
&& !s.renderer_output())
continue;
// Skip if it's an interpolated (userdata) parameter and we're
// initializing them lazily.
if (s.symtype() == SymTypeParam && !s.lockgeom()
&& !s.typespec().is_closure() && !s.connected()
&& !s.connected_down() && shadingsys().lazy_userdata())
// initializing them lazily, or if it's an interactively-adjusted
// parameter.
if (s.symtype() == SymTypeParam && !s.typespec().is_closure()
&& !s.connected() && !s.connected_down()
&& (s.interactive()
|| (s.interpolated() && shadingsys().lazy_userdata())))
continue;
// Set initial value for params (may contain init ops)
llvm_assign_initial_value(s, llvm_initial_shader_mask_value);
@@ -2095,6 +2139,7 @@ BatchedBackendLLVM::build_llvm_instance(bool groupentry)
// records for each.
find_basic_blocks();
find_conditionals();
m_call_layers_inserted.clear();
build_llvm_code(inst()->maincodebegin(), inst()->maincodeend());
+22 -21
View File
@@ -41,7 +41,7 @@ template<int WidthT>
Mask<WidthT>
BatchedRendererServices<WidthT>::get_matrix(BatchedShaderGlobals* bsg,
Masked<Matrix44> wresult,
Wide<const ustring> wfrom,
Wide<const ustringhash> wfrom,
Wide<const float> wtime)
{
OSL_ASSERT(
@@ -70,7 +70,7 @@ template<int WidthT>
Mask<WidthT>
BatchedRendererServices<WidthT>::get_inverse_matrix(BatchedShaderGlobals* bsg,
Masked<Matrix44> wresult,
ustring to,
ustringhash to,
Wide<const float> wtime)
{
OSL_ASSERT(
@@ -85,7 +85,7 @@ template<int WidthT>
Mask<WidthT>
BatchedRendererServices<WidthT>::get_inverse_matrix(BatchedShaderGlobals* bsg,
Masked<Matrix44> wresult,
Wide<const ustring> wto,
Wide<const ustringhash> wto,
Wide<const float> wtime)
{
OSL_ASSERT(
@@ -109,13 +109,13 @@ template<int WidthT>
TextureSystem::TextureHandle*
BatchedRendererServices<WidthT>::resolve_udim_uniform(
BatchedShaderGlobals* bsg, TexturePerthread* texture_thread_info,
ustring filename, TextureSystem::TextureHandle* texture_handle, float S,
ustringhash filename, TextureSystem::TextureHandle* texture_handle, float S,
float T)
{
if (!texture_thread_info)
texture_thread_info = bsg->uniform.context->texture_thread_info();
if (!texture_handle)
texture_handle = texturesys()->get_texture_handle(filename,
texture_handle = texturesys()->get_texture_handle(ustring_from(filename),
texture_thread_info);
if (texturesys()->is_udim(texture_handle)) {
// Newer versions of the TextureSystem interface are able to determine the
@@ -141,14 +141,14 @@ template<int WidthT>
void
BatchedRendererServices<WidthT>::resolve_udim(
BatchedShaderGlobals* bsg, TexturePerthread* texture_thread_info,
ustring filename, TextureSystem::TextureHandle* texture_handle,
ustringhash filename, TextureSystem::TextureHandle* texture_handle,
Wide<const float> wS, Wide<const float> wT,
Masked<TextureSystem::TextureHandle*> wresult)
{
if (!texture_thread_info)
texture_thread_info = bsg->uniform.context->texture_thread_info();
if (!texture_handle)
texture_handle = texturesys()->get_texture_handle(filename,
texture_handle = texturesys()->get_texture_handle(ustring_from(filename),
texture_thread_info);
if (texturesys()->is_udim(texture_handle)) {
// Newer versions of the TextureSystem interface are able to determine the
@@ -176,17 +176,17 @@ template<int WidthT>
bool
BatchedRendererServices<WidthT>::get_texture_info_uniform(
BatchedShaderGlobals* bsg, TexturePerthread* texture_thread_info,
ustring filename, TextureSystem::TextureHandle* texture_handle,
int subimage, ustring dataname, RefData val)
ustringhash filename, TextureSystem::TextureHandle* texture_handle,
int subimage, ustringhash dataname, RefData val)
{
if (!texture_thread_info)
texture_thread_info = bsg->uniform.context->texture_thread_info();
if (!texture_handle)
texture_handle = texturesys()->get_texture_handle(filename,
texture_handle = texturesys()->get_texture_handle(ustring_from(filename),
texture_thread_info);
bool status = texturesys()->get_texture_info(texture_handle, NULL, subimage,
dataname, val.type(),
val.ptr());
ustring_from(dataname),
val.type(), val.ptr());
if (!status) {
std::string err = texturesys()->geterror();
@@ -203,7 +203,7 @@ BatchedRendererServices<WidthT>::get_texture_info_uniform(
template<int WidthT>
Mask<WidthT>
BatchedRendererServices<WidthT>::texture(
ustring filename, TextureSystem::TextureHandle* texture_handle,
ustringhash filename, TextureSystem::TextureHandle* texture_handle,
TextureSystem::Perthread* texture_thread_info,
const BatchedTextureOptions& options, BatchedShaderGlobals* bsg,
Wide<const float> ws, Wide<const float> wt, Wide<const float> wdsdx,
@@ -221,7 +221,7 @@ BatchedRendererServices<WidthT>::texture(
template<int WidthT>
Mask<WidthT>
BatchedRendererServices<WidthT>::texture3d(
ustring filename, TextureSystem::TextureHandle* texture_handle,
ustringhash filename, TextureSystem::TextureHandle* texture_handle,
TextureSystem::Perthread* texture_thread_info,
const BatchedTextureOptions& options, BatchedShaderGlobals* bsg,
Wide<const Vec3> wP, Wide<const Vec3> wdPdx, Wide<const Vec3> wdPdy,
@@ -238,7 +238,7 @@ BatchedRendererServices<WidthT>::texture3d(
template<int WidthT>
Mask<WidthT>
BatchedRendererServices<WidthT>::environment(
ustring filename, TextureSystem::TextureHandle* texture_handle,
ustringhash filename, TextureSystem::TextureHandle* texture_handle,
TextureSystem::Perthread* texture_thread_info,
const BatchedTextureOptions& options, BatchedShaderGlobals* bsg,
Wide<const Vec3> wR, Wide<const Vec3> wdRdx, Wide<const Vec3> wdRdy,
@@ -255,7 +255,7 @@ BatchedRendererServices<WidthT>::environment(
template<int WidthT>
void
BatchedRendererServices<WidthT>::pointcloud_search(
BatchedShaderGlobals* bsg, ustring filename, const void* wcenter,
BatchedShaderGlobals* bsg, ustringhash filename, const void* wcenter,
Wide<const float> wradius, int max_points, bool sort,
PointCloudSearchResults& results)
{
@@ -269,8 +269,8 @@ BatchedRendererServices<WidthT>::pointcloud_search(
template<int WidthT>
Mask<WidthT>
BatchedRendererServices<WidthT>::pointcloud_get(
BatchedShaderGlobals* bsg, ustring filename, Wide<const int[]> windices,
Wide<const int> wnum_points, ustring attr_name, MaskedData wout_data)
BatchedShaderGlobals* bsg, ustringhash filename, Wide<const int[]> windices,
Wide<const int> wnum_points, ustringhash attr_name, MaskedData wout_data)
{
OSL_ASSERT(
0
@@ -283,7 +283,7 @@ BatchedRendererServices<WidthT>::pointcloud_get(
template<int WidthT>
Mask<WidthT>
BatchedRendererServices<WidthT>::pointcloud_write(
BatchedShaderGlobals* bsg, ustring filename, Wide<const OSL::Vec3> wpos,
BatchedShaderGlobals* bsg, ustringhash filename, Wide<const OSL::Vec3> wpos,
int nattribs, const ustring* attr_names, const TypeDesc* attr_types,
const void** pointers_to_wide_attr_value, Mask mask)
{
@@ -312,8 +312,9 @@ BatchedRendererServices<WidthT>::trace(
template<int WidthT>
void
BatchedRendererServices<WidthT>::getmessage(BatchedShaderGlobals* bsg,
Masked<int> wresult, ustring source,
ustring name, MaskedData wval)
Masked<int> wresult,
ustringhash source,
ustringhash name, MaskedData wval)
{
// Currently this code path should only be followed when source == "trace"
OSL_DASSERT(wresult.mask() == wval.mask());
+14 -9
View File
@@ -204,13 +204,13 @@ DECL(osl_dict_next, "iXi")
DECL(osl_dict_value, "iXiXLX")
DECL(osl_raytype_name, "iXs")
#ifdef OSL_LLVM_NO_BITCODE
DECL(osl_range_check, "iiiXXXiXiXX")
DECL(osl_range_check, "iiisXsisiss")
#endif
DECL(osl_range_check_err, "iiiXXXiXiXX")
DECL(osl_naninf_check, "xiXiXXiXiiX")
DECL(osl_uninit_check, "xLXXXiXiXXiXiXii")
DECL(osl_get_attribute, "iXiXXiiLX")
DECL(osl_bind_interpolated_param, "iXXLiXiXiXi")
DECL(osl_range_check_err, "iiisXsisiss")
DECL(osl_naninf_check, "xiXiXsisiis")
DECL(osl_uninit_check, "xLXXsisissisisii")
DECL(osl_get_attribute, "iXissiiLX")
DECL(osl_bind_interpolated_param, "iXsLiXiXiXi")
DECL(osl_get_texture_options, "XX");
DECL(osl_get_noise_options, "XX");
DECL(osl_get_trace_options, "XX");
@@ -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,7 +285,12 @@ 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")
@@ -338,8 +343,8 @@ DECL(osl_substr_ssii, "ssii")
DECL(osl_regex_impl, "iXsXisi")
// Used by wide code generator, but are uniform calls
DECL(osl_texture_decode_wrapmode, "iX");
DECL(osl_texture_decode_interpmode, "iX");
DECL(osl_texture_decode_wrapmode, "is");
DECL(osl_texture_decode_interpmode, "is");
DECL(osl_texture_set_firstchannel, "xXi")
DECL(osl_texture_set_swrap, "xXs")
+15 -15
View File
@@ -315,7 +315,7 @@ DECL(__OSL_MASKED_OP(pointcloud_get), "iXsXiXsLXi")
DECL(__OSL_MASKED_OP(pointcloud_write), "iXsXiXXXi")
DECL(__OSL_MASKED_OP(getmessage), "xXXssLXiisii")
DECL(__OSL_MASKED_OP2(setmessage, s, WX), "xXXLXisii")
DECL(__OSL_MASKED_OP2(setmessage, s, WX), "xXsLXisii")
DECL(__OSL_MASKED_OP2(setmessage, Ws, WX), "xXXLXisii")
DECL(__OSL_OP(blackbody_vf), "xXXf")
@@ -362,24 +362,24 @@ DECL(__OSL_OP(dict_value), "iXiXLX")
DECL(__OSL_MASKED_OP(dict_value), "xXXXXLXi")
DECL(__OSL_OP(raytype_name), "iXX")
DECL(__OSL_OP(raytype_name), "iXs")
DECL(__OSL_MASKED_OP(raytype_name), "xXXXi")
DECL(__OSL_OP(naninf_check), "xiXiXXiXiiX")
DECL(__OSL_MASKED_OP1(naninf_check_offset, i), "xiiXiXXiXiiX")
DECL(__OSL_MASKED_OP1(naninf_check_offset, Wi), "xiiXiXXiXXiX")
DECL(__OSL_OP(range_check), "iiiXXXiXiXX")
DECL(__OSL_MASKED_OP(range_check), "xXiiXXXiXiXX")
DECL(__OSL_OP2(uninit_check_values_offset, X, i), "xLXXXiXiXXiXiXii")
DECL(__OSL_MASKED_OP2(uninit_check_values_offset, X, Wi), "xiLXXXiXiXXiXiXXi")
DECL(__OSL_MASKED_OP2(uninit_check_values_offset, WX, i), "xiLXXXiXiXXiXiXii")
DECL(__OSL_MASKED_OP2(uninit_check_values_offset, WX, Wi), "xiLXXXiXiXXiXiXXi")
DECL(__OSL_OP(naninf_check), "xiXiXsisiis")
DECL(__OSL_MASKED_OP1(naninf_check_offset, i), "xiiXiXsisiis")
DECL(__OSL_MASKED_OP1(naninf_check_offset, Wi), "xiiXiXsisXis")
DECL(__OSL_OP(range_check), "iiisXsisiss")
DECL(__OSL_MASKED_OP(range_check), "xXiisXsisiss")
DECL(__OSL_OP2(uninit_check_values_offset, X, i), "xLXXsisissisisii")
DECL(__OSL_MASKED_OP2(uninit_check_values_offset, X, Wi), "xiLXXsisissisisXi")
DECL(__OSL_MASKED_OP2(uninit_check_values_offset, WX, i), "xiLXXsisissisisii")
DECL(__OSL_MASKED_OP2(uninit_check_values_offset, WX, Wi), "xiLXXsisissisisXi")
DECL(__OSL_OP1(get_attribute, s), "iXiXXiiXXi")
DECL(__OSL_MASKED_OP1(get_attribute, Ws), "iXiXXiiXXi")
DECL(__OSL_OP(get_attribute_uniform), "iXiXXiiXX")
DECL(__OSL_OP1(get_attribute, s), "iXissiiXXi")
DECL(__OSL_MASKED_OP1(get_attribute, Ws), "iXisXiiXXi")
DECL(__OSL_OP(get_attribute_uniform), "iXissiiXX")
// TODO: shouldn't bind_interpolated_param be MASKED? change name to reflect
DECL(__OSL_OP(bind_interpolated_param), "iXXLiXiXiXii")
DECL(__OSL_OP(bind_interpolated_param), "iXsLiXiXiXii")
//DECL (osl_get_texture_options, "XX") // unneeded
DECL(__OSL_OP(get_noise_options), "XX")
+3 -2
View File
@@ -2413,11 +2413,12 @@ DECLFOLDER(constfold_gettextureinfo)
void* mydata = OSL_ALLOCA(char, t.size());
// FIXME(ptex) -- exclude folding of ptex, since these things
// can vary per face.
ustring errormessage;
ustringhash em;
int result = rop.renderer()->get_texture_info(
filename, nullptr, rop.shadingcontext()->texture_thread_info(),
rop.shadingcontext(), 0 /* TODO: subimage? */, dataname, t, mydata,
&errormessage);
&em);
ustring errormessage = ustring_from(em);
// Now we turn
// gettextureinfo result filename dataname data
// into this for success:
+9 -7
View File
@@ -133,7 +133,7 @@ ShadingContext::execute_init(ShaderGroup& sgroup, int shadeindex,
ssg.renderer = renderer();
ssg.Ci = NULL;
run_func(&ssg, m_heap.get(), userdata_base_ptr, output_base_ptr,
shadeindex);
shadeindex, sgroup.interactive_arena_ptr());
}
if (profile)
@@ -160,8 +160,8 @@ ShadingContext::execute_layer(int shadeindex, ShaderGlobals& ssg,
if (!run_func)
return false;
run_func(&ssg, m_heap.get(), userdata_base_ptr, output_base_ptr,
shadeindex);
run_func(&ssg, m_heap.get(), userdata_base_ptr, output_base_ptr, shadeindex,
group()->interactive_arena_ptr());
if (profile)
m_ticks += timer.ticks();
@@ -321,7 +321,8 @@ ShadingContext::Batched<WidthT>::execute_init(
run_mask.set_count_on(batch_size);
run_func(&bsg, context().m_heap.get(), &wide_shadeindex.data(),
userdata_base_ptr, output_base_ptr, run_mask.value());
userdata_base_ptr, output_base_ptr, run_mask.value(),
sgroup.interactive_arena_ptr());
}
}
@@ -360,7 +361,8 @@ ShadingContext::Batched<WidthT>::execute_layer(
run_mask.set_count_on(batch_size);
run_func(&bsg, context().m_heap.get(), &wide_shadeindex.data(),
userdata_base_ptr, output_base_ptr, run_mask.value());
userdata_base_ptr, output_base_ptr, run_mask.value(),
group()->interactive_arena_ptr());
}
if (profile)
@@ -625,8 +627,8 @@ ShadingContext::find_regex(ustring r)
bool
ShadingContext::osl_get_attribute(ShaderGlobals* sg, void* objdata,
int dest_derivs, ustring obj_name,
ustring attr_name, int array_lookup,
int dest_derivs, ustringhash obj_name,
ustringhash attr_name, int array_lookup,
int index, TypeDesc attr_type,
void* attr_dest)
{
+71 -49
View File
@@ -182,7 +182,8 @@ compatible_param(const TypeDesc& a, const TypeDesc& b)
void
ShaderInstance::parameters(const ParamValueList& params)
ShaderInstance::parameters(const ParamValueList& params,
cspan<ParamHints> hints)
{
// Seed the params with the master's defaults
m_iparams = m_master->m_idefaults;
@@ -195,11 +196,13 @@ ShaderInstance::parameters(const ParamValueList& params)
// on the master.
for (int i = 0, e = (int)m_instoverrides.size(); i < e; ++i) {
Symbol* sym = master()->symbol(i);
m_instoverrides[i].lockgeom(sym->lockgeom());
m_instoverrides[i].interpolated(sym->interpolated());
m_instoverrides[i].interactive(sym->interactive());
m_instoverrides[i].dataoffset(sym->dataoffset());
}
for (auto&& p : params) {
for (size_t pi = 0; pi < params.size(); ++pi) {
const ParamValue& p(params[pi]);
if (p.name().size() == 0)
continue; // skip empty names
int i = findparam(p.name());
@@ -244,22 +247,7 @@ ShaderInstance::parameters(const ParamValueList& params)
valuetype = TypeDesc::FLOAT;
}
// Relaxed rules just look to see that the types are isomorphic to each other (ie: same number of base values)
// Note that:
// * basetypes must match exactly (int vs float vs string)
// * valuetype cannot be unsized (we must know the concrete number of values)
// * if paramtype is sized (or not an array) just check for the total number of entries
// * if paramtype is unsized (shader writer is flexible about how many values come in) -- make sure we are a multiple of the target type
// * allow a single float setting a vec3 (or equivalent)
if (!(valuetype.basetype == paramtype.basetype
&& !valuetype.is_unsized_array()
&& ((!paramtype.is_unsized_array()
&& valuetype.basevalues() == paramtype.basevalues())
|| (paramtype.is_unsized_array()
&& valuetype.basevalues() % paramtype.aggregate
== 0)
|| (paramtype.is_vec3()
&& valuetype == TypeDesc::FLOAT)))) {
if (!relaxed_equivalent(sm_typespec, valuetype)) {
// We are being very relaxed in this mode, so if the user _still_ got it wrong
// something more serious is at play and we should treat it as an error.
shadingsys().errorfmt(
@@ -277,13 +265,14 @@ ShaderInstance::parameters(const ParamValueList& params)
// Mark that the override as an instance value
so->valuesource(Symbol::InstanceVal);
// Lock the param against geometric primitive overrides if the
// master thinks it was so locked, AND the Parameter() call
// didn't specify lockgeom=false (which would be indicated by
// the parameter's interpolation being non-CONSTANT).
bool lockgeom = (sm->lockgeom()
&& p.interp() == ParamValue::INTERP_CONSTANT);
so->lockgeom(lockgeom);
// Pass on any interpolated or interactive hints.
auto hint = hints[pi];
so->interpolated(sm->interpolated()
|| (hint & ParamHints::interpolated)
== ParamHints::interpolated);
so->interactive((hint & ParamHints::interactive)
== ParamHints::interactive);
bool lockgeom = !so->interpolated() && !so->interactive();
OSL_DASSERT(so->dataoffset() == sm->dataoffset());
so->dataoffset(sm->dataoffset());
@@ -467,7 +456,7 @@ ShaderInstance::evaluate_writes_globals_and_userdata_params()
// the symbol overrides. This is very important to get instance merging
// working correctly.
for (auto&& s : m_instoverrides) {
if (!s.lockgeom())
if (s.interpolated())
userdata_params(true);
}
}
@@ -506,7 +495,8 @@ ShaderInstance::copy_code_from_master(ShaderGroup& group)
si->arraylen(m_instoverrides[i].arraylen());
si->valuesource(m_instoverrides[i].valuesource());
si->connected_down(m_instoverrides[i].connected_down());
si->lockgeom(m_instoverrides[i].lockgeom());
si->interpolated(m_instoverrides[i].interpolated());
si->interactive(m_instoverrides[i].interactive());
si->dataoffset(m_instoverrides[i].dataoffset());
si->set_dataptr(SymArena::Absolute, param_storage(i));
}
@@ -649,10 +639,12 @@ ShaderInstance::mergeable(const ShaderInstance& b,
continue;
return false;
}
// But still, if they differ in their lockgeom'edness, we can't
// merge the instances.
if (m_instoverrides[i].lockgeom()
!= b.m_instoverrides[i].lockgeom()) {
// But still, if they differ in whether they are interpolated or
// interactive, we can't merge the instances.
if (m_instoverrides[i].interpolated()
!= b.m_instoverrides[i].interpolated()
|| m_instoverrides[i].interactive()
!= b.m_instoverrides[i].interactive()) {
return false;
}
}
@@ -668,10 +660,14 @@ ShaderInstance::mergeable(const ShaderInstance& b,
continue;
if (sym->typespec().is_closure())
continue; // Closures can't have instance override values
// Even if the symbols' values match now, they might not in the
// future with 'interactive' parameters.
const Symbol* b_sym = optimized ? b.symbol(i) : b.mastersymbol(i);
if ((sym->valuesource() == Symbol::InstanceVal
|| sym->valuesource() == Symbol::DefaultVal)
&& memcmp(param_storage(i), b.param_storage(i),
sym->typespec().simpletype().size())) {
&& (memcmp(param_storage(i), b.param_storage(i),
sym->typespec().simpletype().size())
|| b_sym->interactive())) {
return false;
}
}
@@ -736,7 +732,8 @@ ShaderInstance::mergeable(const ShaderInstance& b,
ShaderGroup::ShaderGroup(string_view name)
ShaderGroup::ShaderGroup(string_view name, ShadingSystemImpl& shadingsys)
: m_shadingsys(shadingsys)
{
m_id = ++(*(atomic_int*)&next_id);
if (name.size()) {
@@ -749,15 +746,6 @@ ShaderGroup::ShaderGroup(string_view name)
ShaderGroup::ShaderGroup(const ShaderGroup& g, string_view name)
: ShaderGroup(name) // delegate most of the work
{
m_num_entry_layers = g.m_num_entry_layers;
m_layers = g.m_layers;
}
ShaderGroup::~ShaderGroup()
{
#if 0
@@ -772,6 +760,11 @@ ShaderGroup::~ShaderGroup()
<< "executed on " << executions() << " points\n";
}
#endif
// Free any GPU memory associated with this group
if (m_device_interactive_arena)
shadingsys().renderer()->device_free(
m_device_interactive_arena.d_get());
}
@@ -824,6 +817,34 @@ ShaderGroup::mark_entry_layer(int layer)
void
ShaderGroup::setup_interactive_arena(cspan<uint8_t> paramblock)
{
if (paramblock.size()) {
// CPU side
m_interactive_arena_size = paramblock.size();
m_interactive_arena.reset(new uint8_t[m_interactive_arena_size]);
memcpy(m_interactive_arena.get(), paramblock.data(),
m_interactive_arena_size);
if (shadingsys().use_optix()) {
// GPU side
RendererServices* rs = shadingsys().renderer();
m_device_interactive_arena.reset(reinterpret_cast<uint8_t*>(
rs->device_alloc(m_interactive_arena_size)));
rs->copy_to_device(m_device_interactive_arena.d_get(),
paramblock.data(), m_interactive_arena_size);
// print("group {} has device interactive_params set to {:p}\n",
// name(), m_device_interactive_arena.d_get());
}
} else {
m_interactive_arena_size = 0;
m_interactive_arena.reset();
m_device_interactive_arena.reset();
}
}
std::string
ShaderGroup::serialize() const
{
@@ -876,11 +897,12 @@ ShaderGroup::serialize() const
OSL_ASSERT_MSG(0, "unknown type for serialization: %s (%s)",
type.c_str(), s->typespec().c_str());
}
bool lockgeom = dstsyms_exist
? s->lockgeom()
: inst->instoverride(p)->lockgeom();
if (!lockgeom)
print(out, " [[int lockgeom={}]]", lockgeom);
if (dstsyms_exist ? s->interpolated()
: inst->instoverride(p)->interpolated())
print(out, " [[int interpolated=1]]");
if (dstsyms_exist ? s->interactive()
: inst->instoverride(p)->interactive())
print(out, " [[int interactive=1]]");
out << " ;\n";
}
}
+38 -17
View File
@@ -6,11 +6,6 @@
#include <OpenImageIO/fmath.h>
#ifdef OSL_USE_OPTIX
# include <optix.h>
#endif
#include "oslexec_pvt.h"
#include <OSL/genclosure.h>
#include "backendllvm.h"
@@ -116,15 +111,16 @@ BackendLLVM::llvm_call_layer(int layer, bool unconditional)
// Make code that looks like:
// if (! groupdata->run[parentlayer])
// parent_layer (sg, groupdata, userdata_base_ptr,
// output_base_ptr, shadeindex);
// output_base_ptr, shadeindex, interactive_params);
// if it's a conditional call, or
// parent_layer (sg, groupdata, userdata_base_ptr,
// output_base_ptr, shadeindex);
// output_base_ptr, shadeindex, interactive_params);
// if it's run unconditionally.
// The code in the parent layer itself will set its 'executed' flag.
llvm::Value* args[] = { sg_ptr(), groupdata_ptr(), userdata_base_ptr(),
output_base_ptr(), shadeindex() };
llvm::Value* args[]
= { sg_ptr(), groupdata_ptr(), userdata_base_ptr(),
output_base_ptr(), shadeindex(), m_llvm_interactive_params_ptr };
ShaderInstance* parent = group()[layer];
llvm::Value* trueval = ll.constant_bool(true);
@@ -147,6 +143,8 @@ BackendLLVM::llvm_call_layer(int layer, bool unconditional)
if (!unconditional)
ll.op_branch(after_block); // also moves insert point
shadingsys().m_stat_call_layers_inserted++;
}
@@ -193,6 +191,15 @@ BackendLLVM::llvm_run_connected_layers(Symbol& sym, int symindex, int opnum,
}
}
if (shadingsys().m_opt_useparam && inmain) {
// m_call_layers_inserted tracks if we've already run this layer inside the current basic block
const CallLayerKey key = { m_bblockids[opnum], con.srclayer };
if (m_call_layers_inserted.count(key)) {
continue;
}
m_call_layers_inserted.insert(key);
}
// If the earlier layer it comes from has not yet been
// executed, do so now.
llvm_call_layer(con.srclayer);
@@ -232,12 +239,15 @@ LLVMGEN(llvm_gen_useparam)
// initializing them lazily, now we have to do it.
if ((sym.symtype() == SymTypeParam
|| sym.symtype() == SymTypeOutputParam)
&& !sym.lockgeom() && !sym.typespec().is_closure()
&& sym.interpolated() && !sym.typespec().is_closure()
&& !sym.connected() && !sym.connected_down()
&& rop.shadingsys().lazy_userdata()) {
rop.llvm_assign_initial_value(sym);
}
}
rop.increment_useparam_ops();
return true;
}
@@ -374,6 +384,7 @@ LLVMGEN(llvm_gen_printf)
}
#if OSL_USE_OPTIX
// In OptiX, printf currently supports 0 or 1 arguments, and the signature
// requires 1 argument, so push a null pointer onto the call args if there
// is no argument.
@@ -382,6 +393,7 @@ LLVMGEN(llvm_gen_printf)
// we push the size of the arguments on the stack
optix_size += sizeof(uint64_t);
}
#endif
// Some ops prepend things
if (op.opname() == op_error || op.opname() == op_warning) {
@@ -390,9 +402,8 @@ 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.llvm_load_string(s);
} else {
#if OSL_USE_OPTIX
if (rop.use_optix()) {
// In OptiX7+ case, we do this:
// void* args = { args_size, arg0, arg1, arg2 };
// (where args_size is the size of arg0 + arg1 + arg2...)
@@ -450,6 +461,10 @@ LLVMGEN(llvm_gen_printf)
}
call_args.resize(new_format_slot + 2);
call_args.back() = rop.ll.void_ptr(voids);
} else
#endif
{
call_args[new_format_slot] = rop.llvm_load_string(s);
}
// Construct the function name and call it.
@@ -2461,7 +2476,9 @@ LLVMGEN(llvm_gen_texture)
if (Filename.is_constant() && rop.shadingsys().opt_texture_handle()) {
texture_handle
= rop.renderer()->get_texture_handle(Filename.get_string(),
rop.shadingcontext());
rop.shadingcontext(), nullptr);
// FIXME(colorspace): that nullptr should be replaced by a TextureOpt*
// that has the colorspace set.
}
// Now call the osl_texture function, passing the options and all the
@@ -2526,7 +2543,9 @@ LLVMGEN(llvm_gen_texture3d)
if (Filename.is_constant() && rop.shadingsys().opt_texture_handle()) {
texture_handle
= rop.renderer()->get_texture_handle(Filename.get_string(),
rop.shadingcontext());
rop.shadingcontext(), nullptr);
// FIXME(colorspace): that nullptr should be replaced by a TextureOpt*
// that has the colorspace set.
}
// Now call the osl_texture3d function, passing the options and all the
@@ -2589,7 +2608,9 @@ LLVMGEN(llvm_gen_environment)
if (Filename.is_constant() && rop.shadingsys().opt_texture_handle()) {
texture_handle
= rop.renderer()->get_texture_handle(Filename.get_string(),
rop.shadingcontext());
rop.shadingcontext(), nullptr);
// FIXME(colorspace): that nullptr should be replaced by a TextureOpt*
// that has the colorspace set.
}
// Now call the osl_environment function, passing the options and all the
@@ -3040,7 +3061,7 @@ LLVMGEN(llvm_gen_gettextureinfo)
if (Filename.is_constant() && rop.shadingsys().opt_texture_handle()) {
texture_handle
= rop.renderer()->get_texture_handle(Filename.get_string(),
rop.shadingcontext());
rop.shadingcontext(), nullptr);
}
std::vector<llvm::Value*> args;
+92 -45
View File
@@ -18,10 +18,6 @@
#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"
@@ -61,10 +57,18 @@ Schematically, we want to create code that resembles the following:
float param_1_bar;
};
// Data for the interactively adjusted parameters of this group -- these
// can't be turned into constants because the app may want to modify them
// as it runs (such as for user interaction). This block of memory has
// one global copy specific each the shader group, managed by OSL.
struct InteractiveParams {
float iparam_0_baz;
};
// Name of layer entry is $layer_ID
void $layer_0(ShaderGlobals* sg, GroupData* group,
void* userdatda_base_ptr, void* output_base_ptr,
int shadeindex)
int shadeindex, InteractiveParams* interactive_params)
{
// Declare locals, temps, constants, params with known values.
// Make them all look like stack memory locations:
@@ -74,25 +78,27 @@ Schematically, we want to create code that resembles the following:
// then run the shader body:
*x = sg->u * group->param_0_bar;
group->param_1_foo = *x;
*x += interactive_params->iparam_0_baz;
// ...
}
void $layer_1(ShaderGlobals* sg, GroupData* group,
void* userdatda_base_ptr, void* output_base_ptr,
int shadeindex)
int shadeindex, InteractiveParams* interactive_params)
{
// Because we need the outputs of layer 0 now, we call it if it
// hasn't already run:
if (! group->layer_run[0]) {
group->layer_run[0] = 1;
$layer_0 (sg, group, userdata_base_ptr, output_base_ptr,
shadeindex); // because we need its outputs
shadeindex, interactive_params); // because we need its outputs
}
*y = sg->u * group->$param_1_bar;
}
void $group_1(ShaderGlobals* sg, GroupData* group,
void* userdatda_base_ptr, void* output_base_ptr,
int shadeindex)
int shadeindex, InteractiveParams* interactive_params)
{
group->layer_run[...] = 0;
// Run just the unconditional layers
@@ -100,7 +106,7 @@ Schematically, we want to create code that resembles the following:
if (! group->layer_run[1]) {
group->layer_run[1] = 1;
$layer_1(sg, group, userdata_base_ptr, output_base_ptr,
shadeindex);
shadeindex, interactive_params);
}
}
@@ -283,14 +289,10 @@ BackendLLVM::llvm_type_groupdata()
++order;
for (int i = 0; i < nuserdata; ++i) {
TypeDesc type = types[i];
// NB: Userdata derivs are not currently supported in OptiX, since
// making room for them in the GroupData struct can result in a
// large per-thread memory allocation, which could negatively
// impact performance.
int n = (!use_optix()) ? type.numelements()
* 3 // make room for derivs by default
: type.numelements();
type.arraylen = n;
// make room for float derivs only
type.arraylen = type.basetype == TypeDesc::FLOAT
? type.numelements() * 3
: type.numelements();
fields.push_back(llvm_type(type));
m_groupdata_field_names.emplace_back(
fmtformat("userdata{}_{}_", i, names[i]));
@@ -332,8 +334,8 @@ BackendLLVM::llvm_type_groupdata()
&& !sym.connected_down()) {
auto found = group().find_symloc(sym.name());
if (found)
OIIO::Strutil::print("layer {} \"{}\" : OUTPUT {}\n", layer,
inst->layername(), found->name);
print("layer {} \"{}\" : OUTPUT {}\n", layer,
inst->layername(), found->name);
}
// Alignment
@@ -343,11 +345,11 @@ BackendLLVM::llvm_type_groupdata()
if (offset & (align - 1))
offset += align - (offset & (align - 1));
if (llvm_debug() >= 2)
std::cout << " " << inst->layername() << " (" << inst->id()
<< ") " << sym.mangled() << " " << ts.c_str()
<< ", field " << order << ", size "
<< derivSize * int(sym.size()) << ", offset "
<< offset << std::endl;
print(" {} ({}) {} {}, field {}, size {}, offset {}{}{}\n",
inst->layername(), inst->id(), sym.mangled(), ts.c_str(),
order, derivSize * int(sym.size()), offset,
sym.interpolated() ? " (interpolated)" : "",
sym.interactive() ? " (interactive)" : "");
sym.dataoffset((int)offset);
// TODO(arenas): sym.set_dataoffset(SymArena::Heap, offset);
offset += derivSize * sym.size();
@@ -476,7 +478,7 @@ BackendLLVM::llvm_assign_initial_value(const Symbol& sym, bool force)
// such userdata was available.
llvm::BasicBlock* after_userdata_block = nullptr;
const SymLocationDesc* symloc = nullptr;
if (!sym.lockgeom() && !sym.typespec().is_closure()) {
if (sym.interpolated() && !sym.typespec().is_closure()) {
ustring symname = sym.name();
TypeDesc type = sym.typespec().simpletype();
@@ -560,6 +562,7 @@ 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());
#if OSL_USE_OPTIX
} 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.
@@ -570,7 +573,10 @@ BackendLLVM::llvm_assign_initial_value(const Symbol& sym, bool force)
llvm::Value* dst = llvm_void_ptr(sym);
TypeDesc t = sym.typespec().simpletype();
ll.op_memcpy(dst, src, t.size(), t.basesize());
} else if (!sym.lockgeom() && !sym.typespec().is_closure()) {
if (sym.has_derivs())
llvm_zero_derivs(sym);
#endif
} else if (sym.interpolated() && !sym.typespec().is_closure()) {
// geometrically-varying param; memcpy its default value
TypeDesc t = sym.typespec().simpletype();
ll.op_memcpy(llvm_void_ptr(sym), ll.constant_ptr(sym.data()),
@@ -864,10 +870,13 @@ BackendLLVM::build_llvm_init()
ll.current_function(
ll.make_function(unique_name, false,
ll.type_void(), // return type
{ llvm_type_sg_ptr(), llvm_type_groupdata_ptr(),
ll.type_void_ptr(), // userdata_base_ptr
ll.type_void_ptr(), // output_base_ptr
ll.type_int() }));
{
llvm_type_sg_ptr(), llvm_type_groupdata_ptr(),
ll.type_void_ptr(), // userdata_base_ptr
ll.type_void_ptr(), // output_base_ptr
ll.type_int(),
ll.type_void_ptr(), // FIXME: interactive params
}));
if (ll.debug_is_enabled()) {
ustring sourcefile
@@ -877,10 +886,17 @@ BackendLLVM::build_llvm_init()
// Get shader globals and groupdata pointers
m_llvm_shaderglobals_ptr = ll.current_function_arg(0); //arg_it++;
m_llvm_groupdata_ptr = ll.current_function_arg(1); //arg_it++;
m_llvm_shaderglobals_ptr->setName("shaderglobals_ptr");
m_llvm_groupdata_ptr = ll.current_function_arg(1); //arg_it++;
m_llvm_groupdata_ptr->setName("groupdata_ptr");
m_llvm_userdata_base_ptr = ll.current_function_arg(2); //arg_it++;
m_llvm_output_base_ptr = ll.current_function_arg(3); //arg_it++;
m_llvm_shadeindex = ll.current_function_arg(4); //arg_it++;
m_llvm_userdata_base_ptr->setName("userdata_base_ptr");
m_llvm_output_base_ptr = ll.current_function_arg(3); //arg_it++;
m_llvm_output_base_ptr->setName("output_base_ptr");
m_llvm_shadeindex = ll.current_function_arg(4); //arg_it++;
m_llvm_shadeindex->setName("shadeindex");
m_llvm_interactive_params_ptr = ll.current_function_arg(5); //arg_it++;
m_llvm_interactive_params_ptr->setName("interactive_params_ptr");
// Set up a new IR builder
llvm::BasicBlock* entry_bb = ll.new_basic_block(unique_name);
@@ -960,10 +976,13 @@ BackendLLVM::build_llvm_instance(bool groupentry)
unique_layer_name,
!is_entry_layer, // fastcall for non-entry layer functions
ll.type_void(), // return type
{ llvm_type_sg_ptr(), llvm_type_groupdata_ptr(),
ll.type_void_ptr(), // userdata_base_ptr
ll.type_void_ptr(), // output_base_ptr
ll.type_int() }));
{
llvm_type_sg_ptr(), llvm_type_groupdata_ptr(),
ll.type_void_ptr(), // userdata_base_ptr
ll.type_void_ptr(), // output_base_ptr
ll.type_int(),
ll.type_void_ptr(), // FIXME: interactive_params
}));
if (ll.debug_is_enabled()) {
const Opcode& mainbegin(inst()->op(inst()->maincodebegin()));
@@ -973,10 +992,17 @@ BackendLLVM::build_llvm_instance(bool groupentry)
// Get shader globals and groupdata pointers
m_llvm_shaderglobals_ptr = ll.current_function_arg(0); //arg_it++;
m_llvm_groupdata_ptr = ll.current_function_arg(1); //arg_it++;
m_llvm_shaderglobals_ptr->setName("shaderglobals_ptr");
m_llvm_groupdata_ptr = ll.current_function_arg(1); //arg_it++;
m_llvm_groupdata_ptr->setName("groupdata_ptr");
m_llvm_userdata_base_ptr = ll.current_function_arg(2); //arg_it++;
m_llvm_output_base_ptr = ll.current_function_arg(3); //arg_it++;
m_llvm_shadeindex = ll.current_function_arg(4); //arg_it++;
m_llvm_userdata_base_ptr->setName("userdata_base_ptr");
m_llvm_output_base_ptr = ll.current_function_arg(3); //arg_it++;
m_llvm_output_base_ptr->setName("output_base_ptr");
m_llvm_shadeindex = ll.current_function_arg(4); //arg_it++;
m_llvm_shadeindex->setName("shadeindex");
m_llvm_interactive_params_ptr = ll.current_function_arg(5); //arg_it++;
m_llvm_interactive_params_ptr->setName("interactive_params_ptr");
llvm::BasicBlock* entry_bb = ll.new_basic_block(unique_layer_name);
m_exit_instance_block = NULL;
@@ -1078,10 +1104,12 @@ BackendLLVM::build_llvm_instance(bool groupentry)
&& !s.renderer_output())
continue;
// Skip if it's an interpolated (userdata) parameter and we're
// initializing them lazily.
if (s.symtype() == SymTypeParam && !s.lockgeom()
&& !s.typespec().is_closure() && !s.connected()
&& !s.connected_down() && shadingsys().lazy_userdata())
// initializing them lazily, or if it's an interactively-adjusted
// parameter.
if (s.symtype() == SymTypeParam && !s.typespec().is_closure()
&& !s.connected() && !s.connected_down()
&& (s.interactive()
|| (s.interpolated() && shadingsys().lazy_userdata())))
continue;
// Set initial value for params (may contain init ops)
llvm_assign_initial_value(s);
@@ -1104,6 +1132,7 @@ BackendLLVM::build_llvm_instance(bool groupentry)
// records for each.
find_basic_blocks();
find_conditionals();
m_call_layers_inserted.clear();
build_llvm_code(inst()->maincodebegin(), inst()->maincodeend());
@@ -1305,10 +1334,12 @@ BackendLLVM::initialize_llvm_group()
}
types += advance;
}
#if OSL_USE_OPTIX
if (varargs && use_optix()) {
varargs = false;
params.push_back(ll.type_void_ptr());
}
#endif
llvm::Function* f = ll.make_function(funcname, false,
llvm_type(rettype), params,
varargs);
@@ -1364,6 +1395,19 @@ BackendLLVM::run()
#ifdef OSL_LLVM_NO_BITCODE
OSL_ASSERT(!use_rs_bitcode());
ll.module(ll.new_module("llvm_ops"));
# if 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()) {
@@ -1605,13 +1649,16 @@ BackendLLVM::run()
}
}
#if OSL_USE_OPTIX
if (use_optix()) {
ll.ptx_compile_group(nullptr, group().name().string(),
group().m_llvm_ptx_compiled_version);
if (group().m_llvm_ptx_compiled_version.empty()) {
OSL_ASSERT(0 && "Unable to generate PTX");
}
} else {
} else
#endif
{
// Force the JIT to happen now and retrieve the JITed function pointers
// for the initialization and all public entry points.
group().llvm_compiled_init(
+26 -17
View File
@@ -27,9 +27,8 @@ examples), as you are just coding in C++, but there are some rules:
float. Aggregates (color/point/vector/normal/matrix), arrays of any
types, or floats with derivatives are passed as a void* and to their
memory location you need to cast appropriately. Strings are passed as
char*, but they are always the characters of 'ustring' objects, so are
unique. See the handy USTR, MAT, VEC, DFLOAT, DVEC macros for
handy/cheap casting of those void*'s to references to ustring&,
ustringrep. See the handy USTR, MAT, VEC, DFLOAT, DVEC macros for
handy/cheap casting of those void*'s to references to ustringrep&,
Matrix44&, Vec3&, Dual2<float>&, and Dual2<Vec3>, respectively.
* You must provide all allowable polymorphic and derivative combinations!
@@ -101,13 +100,23 @@ void* __dso_handle = 0; // necessary to avoid linkage issues in bitcode
// Handy re-casting macros
#define USTR(cstr) (*((ustring*)&cstr))
#define MAT(m) (*(Matrix44*)m)
#define VEC(v) (*(Vec3*)v)
#define DFLOAT(x) (*(Dual2<Float>*)x)
#define DVEC(x) (*(Dual2<Vec3>*)x)
#define COL(x) (*(Color3*)x)
#define DCOL(x) (*(Dual2<Color3>*)x)
#define USTR(s) (*((ustringrep*)&s))
#define USTREP(s) (*((ustringrep*)&s))
#define MAT(m) (*(Matrix44*)m)
#define VEC(v) (*(Vec3*)v)
#define DFLOAT(x) (*(Dual2<Float>*)x)
#define DVEC(x) (*(Dual2<Vec3>*)x)
#define COL(x) (*(Color3*)x)
#define DCOL(x) (*(Dual2<Color3>*)x)
#if OSL_USTRINGREP_IS_HASH
/// ustring_pod is the type we use to pass string data in llvm function calls.
using ustring_pod = size_t;
#else
/// ustring_pod is the type we use to pass string data in llvm function calls.
using ustring_pod = const char*;
#endif
#ifndef OSL_SHADEOP
# ifdef __CUDACC__
@@ -975,17 +984,17 @@ osl_raytype_bit(void* sg_, int bit)
// extern declaration
OSL_SHADEOP_NOINLINE 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);
osl_range_check_err(int indexvalue, int length, ustring_pod symname, void* sg,
ustring_pod sourcefile, int sourceline,
ustring_pod groupname, int layer, ustring_pod layername,
ustring_pod shadername);
OSL_SHADEOP 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)
osl_range_check(int indexvalue, int length, ustring_pod symname, void* sg,
ustring_pod sourcefile, int sourceline, ustring_pod groupname,
int layer, ustring_pod layername, ustring_pod shadername)
{
if (indexvalue < 0 || indexvalue >= length) {
indexvalue = osl_range_check_err(indexvalue, length, symname, sg,
+57 -52
View File
@@ -92,10 +92,6 @@
#include <llvm/Transforms/Utils/Cloning.h>
#include <llvm/Transforms/Utils/SymbolRewriter.h>
#ifdef OSL_USE_OPTIX
# include <optix.h>
#endif
OSL_NAMESPACE_ENTER
@@ -1589,29 +1585,26 @@ LLVM_Util::make_jit_execengine(std::string* err, TargetISA requestedISA,
namespace /*anonymous*/ {
#ifdef OSL_DEV
// The return value of llvm::StructLayout::getAlignment()
// changed from an int to llvm::Align, hide with accessor function
#if OSL_LLVM_VERSION < 100
uint64_t
inline uint64_t
get_alignment(const llvm::StructLayout* layout)
{
# if OSL_LLVM_VERSION < 100
return layout->getAlignment();
}
#else
uint64_t
get_alignment(const llvm::StructLayout* layout)
{
# else
return layout->getAlignment().value();
# endif
}
#endif
} // namespace
void
LLVM_Util::dump_struct_data_layout(llvm::Type* Ty)
LLVM_Util::dump_struct_data_layout(llvm::Type* Ty OSL_MAYBE_UNUSED)
{
#ifdef OSL_DEV
OSL_ASSERT(Ty);
OSL_ASSERT(Ty->isStructTy());
@@ -1635,6 +1628,7 @@ LLVM_Util::dump_struct_data_layout(llvm::Type* Ty)
}
std::cout << std::endl;
}
#endif
}
@@ -2449,25 +2443,6 @@ LLVM_Util::internalize_module_functions(
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);
}
llvm::Function*
LLVM_Util::make_function(const std::string& name, bool fastcall,
llvm::Type* rettype, cspan<llvm::Type*> params,
@@ -2476,6 +2451,11 @@ LLVM_Util::make_function(const std::string& name, bool fastcall,
llvm::FunctionType* functype = type_function(rettype, params, varargs);
auto maybe_func = module()->getOrInsertFunction(name, functype).getCallee();
OSL_ASSERT(maybe_func && "getOrInsertFunction returned NULL");
// if (!llvm::isa<llvm::Function>(maybe_func)) {
// print("make_function: getOrInsertFunction returned non-function for {}\n", name);
// for (auto p : params)
// print(" param type: {}\n", llvm_typename(p));
// }
OSL_ASSERT_MSG(llvm::isa<llvm::Function>(maybe_func),
"Declaration for %s is wrong, LLVM had to make a cast",
name.c_str());
@@ -2694,7 +2674,18 @@ 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,
@@ -2871,15 +2862,21 @@ LLVM_Util::constant(ustring s)
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");
if (ustring_rep() == UstringRep::charptr) {
return constant_ptr((void*)s.c_str(), type_char_ptr());
} else {
size_t p = s.hash();
auto str = (size_t_bits == 64) ? constant64(p) : constant(int(p));
#if OSL_USTRINGREP_IS_HASH
return str;
#else
// 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.
return builder().CreateIntToPtr(str, m_llvm_type_ustring,
"ustring constant");
#endif
}
}
@@ -3535,8 +3532,12 @@ 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
if (offset == 0) {
// shortcut for 0 offset
if (ptrtype && ptrtype != type_void_ptr())
ptr = ptr_cast(ptr, ptrtype);
return ptr;
}
return offset_ptr(ptr, constant(size_t(offset)), ptrtype);
}
@@ -3612,9 +3613,9 @@ LLVM_Util::call_function(llvm::Value* func, cspan<llvm::Value*> args)
OSL_DASSERT(func);
#if 0
llvm::outs() << "llvm_call_function " << *func << "\n";
llvm::outs() << nargs << " args:\n";
for (int i = 0, nargs = args.size(); i < nargs; ++i)
llvm::outs() << "\t" << *(args[i]) << "\n";
llvm::outs() << args.size() << " args:\n";
for (auto a : args)
llvm::outs() << "\t" << *a << "\n";
#endif
//llvm_gen_debug_printf (std::string("start ") + std::string(name));
#if OSL_LLVM_VERSION >= 110
@@ -5831,6 +5832,7 @@ bool
LLVM_Util::ptx_compile_group(llvm::Module* lib_module, const std::string& name,
std::string& out)
{
#if OSL_USE_OPTIX
std::string target_triple = module()->getTargetTriple();
OSL_ASSERT(
@@ -5874,9 +5876,9 @@ LLVM_Util::ptx_compile_group(llvm::Module* lib_module, const std::string& name,
options.AllowFPOpFusion = llvm::FPOpFusion::Fast;
options.NoZerosInBSS = 0;
options.GuaranteedTailCallOpt = 0;
#if OSL_LLVM_VERSION < 120
# if OSL_LLVM_VERSION < 120
options.StackAlignmentOverride = 0;
#endif
# endif
options.UseInitArray = 0;
llvm::TargetMachine* target_machine = llvm_target->createTargetMachine(
@@ -5908,15 +5910,15 @@ LLVM_Util::ptx_compile_group(llvm::Module* lib_module, const std::string& name,
llvm::raw_svector_ostream assembly_stream(assembly);
// TODO: Make sure rounding modes, etc., are set correctly
#if OSL_LLVM_VERSION >= 100
# if OSL_LLVM_VERSION >= 100
target_machine->addPassesToEmitFile(mod_pm, assembly_stream,
nullptr, // FIXME: Correct?
llvm::CGFT_AssemblyFile);
#else
# else
target_machine->addPassesToEmitFile(mod_pm, assembly_stream,
nullptr, // FIXME: Correct?
llvm::TargetMachine::CGFT_AssemblyFile);
#endif
# endif
// Run the optimization passes on the functions
fn_pm.doInitialization();
@@ -5942,6 +5944,9 @@ LLVM_Util::ptx_compile_group(llvm::Module* lib_module, const std::string& name,
delete linked_module;
return true;
#else
return false;
#endif
}
+8 -2
View File
@@ -171,7 +171,7 @@ OSOReaderToMaster::symbol(SymType symtype, TypeSpec typespec, const char* name_)
sym.dataoffset (m_shadingsys.global_heap_offset (sym.name()));
}
#endif
sym.lockgeom(m_shadingsys.lockgeom_default());
sym.interpolated(!m_shadingsys.lockgeom_default());
m_master->m_symbols.push_back(sym);
m_symmap[name] = int(m_master->m_symbols.size()) - 1;
// Start the index at which we add specified defaults
@@ -419,7 +419,13 @@ OSOReaderToMaster::hint(string_view hintstring)
Symbol& sym(m_master->m_symbols.back());
if (type == TypeDesc::TypeInt && ident == "lockgeom"
&& Strutil::parse_int(h, ival) && ival >= 0)
sym.lockgeom(ival);
sym.interpolated(!ival); // soft deprecated
else if (type == TypeDesc::TypeInt && ident == "interpolated"
&& Strutil::parse_int(h, ival) && ival >= 0)
sym.interpolated(ival);
else if (type == TypeDesc::TypeInt && ident == "interactive"
&& Strutil::parse_int(h, ival) && ival >= 0)
sym.interactive(ival);
else if (type == TypeDesc::TypeInt && ident == "allowconnect"
&& Strutil::parse_int(h, ival) && ival >= 0)
sym.allowconnect(ival);
+1 -5
View File
@@ -18,10 +18,6 @@
#include <OpenImageIO/fmath.h>
#ifdef __CUDACC__
# include <optix.h>
#endif
#include "opcolor.h"
#include "opcolor_impl.h"
@@ -39,7 +35,7 @@ namespace pvt {
#define IlluminantACES 0.32168, 0.33767 /* For ACES, approximate D60 */
namespace { // anon namespace to avoid duplicate OptiX symbols
OSL_CONSTANT_DATA const static ColorSystem::Chroma k_color_systems[13] = {
OSL_CONSTANT_DATA const ColorSystem::Chroma k_color_systems[13] = {
// Index, Name xRed yRed xGreen yGreen xBlue yBlue White point
/* 0 Rec709 */ { 0.64, 0.33, 0.30, 0.60, 0.15, 0.06, IlluminantD65 },
/* 1 sRGB */ { 0.64, 0.33, 0.30, 0.60, 0.15, 0.06, IlluminantD65 },
+1 -1
View File
@@ -27,7 +27,7 @@ class ShadingContext;
namespace pvt {
class ColorSystem {
class OSLEXECPUBLIC ColorSystem {
#ifdef __CUDACC__
using Context = void*;
#else
+8 -3
View File
@@ -50,8 +50,13 @@ 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
static OSL_CONSTANT_DATA const float cie_colour_match[81 * 3] OSL_ALIGNAS(64) = {
// clang-format off
// 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
{
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,
@@ -79,8 +84,8 @@ static 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
+25 -25
View File
@@ -27,33 +27,34 @@ namespace pvt {
OSL_SHADEOP void
osl_setmessage(ShaderGlobals* sg, const char* name_, long long type_, void* val,
int layeridx, const char* sourcefile_, int sourceline)
osl_setmessage(ShaderGlobals* sg, ustring_pod name_, long long type_, void* val,
int layeridx, ustring_pod sourcefile_, int sourceline)
{
const ustring& name(USTR(name_));
const ustring& sourcefile(USTR(sourcefile_));
ustringhash name = ustringhash_from(USTR(name_));
ustringhash sourcefile = ustringhash_from(USTR(sourcefile_));
// recreate TypeDesc -- we just crammed it into an int!
TypeDesc type = TYPEDESC(type_);
bool is_closure = (type.basetype
== TypeDesc::UNKNOWN); // secret code for closure
bool is_closure = type.basetype == TypeDesc::UNKNOWN; // indicates closure
if (is_closure)
type.basetype = TypeDesc::PTR; // for closures, we store a pointer
MessageList& messages(sg->context->messages());
const Message* m = messages.find(name);
if (m != NULL) {
if (m) {
if (m->name == name) {
// message already exists?
if (m->has_data())
sg->context->errorfmt(
"message \"{}\" already exists (created here: {}:{})"
" cannot set again from {}:{}",
name, m->sourcefile, m->sourceline, sourcefile, sourceline);
name.c_str(), m->sourcefile.c_str(), m->sourceline,
sourcefile.c_str(), sourceline);
else // NOTE: this cannot be triggered when strict_messages=false because we won't record "failed" getmessage calls
sg->context->errorfmt(
"message \"{}\" was queried before being set (queried here: {}:{})"
" setting it now ({}:{}) would lead to inconsistent results",
name, m->sourcefile, m->sourceline, sourcefile, sourceline);
name.c_str(), m->sourcefile.c_str(), m->sourceline,
sourcefile.c_str(), sourceline);
return;
}
}
@@ -64,22 +65,21 @@ osl_setmessage(ShaderGlobals* sg, const char* name_, long long type_, void* val,
OSL_SHADEOP int
osl_getmessage(ShaderGlobals* sg, const char* source_, const char* name_,
osl_getmessage(ShaderGlobals* sg, ustring_pod source_, ustring_pod name_,
long long type_, void* val, int derivs, int layeridx,
const char* sourcefile_, int sourceline)
ustring_pod sourcefile_, int sourceline)
{
const ustring& source(USTR(source_));
const ustring& name(USTR(name_));
const ustring& sourcefile(USTR(sourcefile_));
ustringhash source = ustringhash_from(USTR(source_));
ustringhash name = ustringhash_from(USTR(name_));
ustringhash sourcefile = ustringhash_from(USTR(sourcefile_));
// recreate TypeDesc -- we just crammed it into an int!
TypeDesc type = TYPEDESC(type_);
bool is_closure = (type.basetype
== TypeDesc::UNKNOWN); // secret code for closure
bool is_closure = type.basetype == TypeDesc::UNKNOWN; // indicates closure
if (is_closure)
type.basetype = TypeDesc::PTR; // for closures, we store a pointer
static ustring ktrace("trace");
static ustringrep ktrace("trace");
if (source == ktrace) {
// Source types where we need to ask the renderer
return sg->renderer->getmessage(sg, source, name, type, val, derivs);
@@ -87,19 +87,19 @@ osl_getmessage(ShaderGlobals* sg, const char* source_, const char* name_,
MessageList& messages(sg->context->messages());
const Message* m = messages.find(name);
if (m != NULL) {
if (m) {
if (m->name == name) {
if (m->type != type) {
// found message, but types don't match
sg->context->errorfmt(
"type mismatch for message \"{}\" ({} as {} here: {}:{})"
" cannot fetch as {} from {}:{}",
name, m->has_data() ? "created" : "queried",
name.c_str(), m->has_data() ? "created" : "queried",
m->type == TypeDesc::PTR ? "closure color"
: m->type.c_str(),
m->sourcefile, m->sourceline,
is_closure ? "closure color" : type.c_str(), sourcefile,
sourceline);
m->sourcefile.c_str(), m->sourceline,
is_closure ? "closure color" : type.c_str(),
sourcefile.c_str(), sourceline);
return 0;
}
if (!m->has_data()) {
@@ -113,8 +113,8 @@ osl_getmessage(ShaderGlobals* sg, const char* source_, const char* name_,
" but is being queried by layer #{} ({}:{})"
" - messages may only be transferred from nodes "
"that appear earlier in the shading network",
name, m->layeridx, m->sourcefile, m->sourceline, layeridx,
sourcefile, sourceline);
name.c_str(), m->layeridx, m->sourcefile.c_str(),
m->sourceline, layeridx, sourcefile.c_str(), sourceline);
return 0;
}
// Message found!
@@ -127,7 +127,7 @@ osl_getmessage(ShaderGlobals* sg, const char* source_, const char* name_,
}
// Message not found -- we must record this event in case another layer tries to set the message again later on
if (sg->context->shadingsys().strict_messages())
messages.add(name, NULL, type, layeridx, sourcefile, sourceline);
messages.add(name, nullptr, type, layeridx, sourcefile, sourceline);
return 0;
}
+65 -50
View File
@@ -43,32 +43,31 @@ osl_texture_set_firstchannel(void* opt, int x)
}
OSL_SHADEOP int
osl_texture_decode_wrapmode(void* name)
osl_texture_decode_wrapmode(ustring_pod name)
{
const ustring& uname = USTR(name);
return OIIO::TextureOpt::decode_wrapmode(uname);
return OIIO::TextureOpt::decode_wrapmode(ustring_from(USTR(name)));
}
OSL_SHADEOP void
osl_texture_set_swrap(void* opt, const char* x)
osl_texture_set_swrap(void* opt, ustring_pod x)
{
((TextureOpt*)opt)->swrap = TextureOpt::decode_wrapmode(USTR(x));
}
OSL_SHADEOP void
osl_texture_set_twrap(void* opt, const char* x)
osl_texture_set_twrap(void* opt, ustring_pod x)
{
((TextureOpt*)opt)->twrap = TextureOpt::decode_wrapmode(USTR(x));
}
OSL_SHADEOP void
osl_texture_set_rwrap(void* opt, const char* x)
osl_texture_set_rwrap(void* opt, ustring_pod x)
{
((TextureOpt*)opt)->rwrap = TextureOpt::decode_wrapmode(USTR(x));
}
OSL_SHADEOP void
osl_texture_set_stwrap(void* opt, const char* x)
osl_texture_set_stwrap(void* opt, ustring_pod x)
{
TextureOpt::Wrap code = TextureOpt::decode_wrapmode(USTR(x));
((TextureOpt*)opt)->swrap = code;
@@ -163,16 +162,15 @@ osl_texture_set_time(void* opt, float x)
}
OSL_SHADEOP int
osl_texture_decode_interpmode(void* name)
osl_texture_decode_interpmode(ustring_pod name)
{
const ustring& uname = USTR(name);
return tex_interp_to_code(uname);
return tex_interp_to_code(ustring_from(USTR(name)));
}
OSL_SHADEOP void
osl_texture_set_interp(void* opt, const char* modename)
osl_texture_set_interp(void* opt, ustring_pod modename)
{
int mode = tex_interp_to_code(USTR(modename));
int mode = tex_interp_to_code(ustring_from(USTR(modename)));
if (mode >= 0)
((TextureOpt*)opt)->interpmode = (TextureOpt::InterpMode)mode;
}
@@ -191,9 +189,9 @@ osl_texture_set_subimage(void* opt, int subimage)
OSL_SHADEOP void
osl_texture_set_subimagename(void* opt, const char* subimagename)
osl_texture_set_subimagename(void* opt, ustring_pod subimagename)
{
((TextureOpt*)opt)->subimagename = USTR(subimagename);
((TextureOpt*)opt)->subimagename = ustring_from(USTR(subimagename));
}
OSL_SHADEOP void
@@ -217,19 +215,20 @@ OSL_SHADEOP 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, ustring* errormessage)
void* dalphadx, void* dalphady, ustringrep* errormessage)
{
ShaderGlobals* sg = (ShaderGlobals*)sg_;
TextureOpt* opt = (TextureOpt*)opt_;
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::float4 result_simd, dresultds_simd, dresultdt_simd;
OIIO::simd::vfloat4 result_simd, dresultds_simd, dresultdt_simd;
ustringhash em;
bool ok = sg->renderer->texture(
USTR(name), (TextureSystem::TextureHandle*)handle,
USTR(name).uhash(), (TextureSystem::TextureHandle*)handle,
sg->context->texture_thread_info(), *opt, sg, s, t, dsdx, dtdx, dsdy,
dtdy, 4, (float*)&result_simd, derivs ? (float*)&dresultds_simd : NULL,
derivs ? (float*)&dresultdt_simd : NULL, errormessage);
derivs ? (float*)&dresultdt_simd : NULL, errormessage ? &em : nullptr);
for (int i = 0; i < chans; ++i)
((float*)result)[i] = result_simd[i];
@@ -240,10 +239,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::float4 dresultdx_simd = dresultds_simd * dsdx
+ dresultdt_simd * dtdx;
OIIO::simd::float4 dresultdy_simd = dresultds_simd * dsdy
+ dresultdt_simd * dtdy;
OIIO::simd::vfloat4 dresultdx_simd = dresultds_simd * dsdx
+ dresultdt_simd * dtdx;
OIIO::simd::vfloat4 dresultdy_simd = dresultds_simd * dsdy
+ dresultdt_simd * dtdy;
if (dresultdx) {
for (int i = 0; i < chans; ++i)
((float*)dresultdx)[i] = dresultdx_simd[i];
@@ -256,8 +255,9 @@ osl_texture(void* sg_, const char* name, void* handle, void* opt_, float s,
}
}
if (ok && errormessage)
*errormessage = Strings::_emptystring_;
if (errormessage)
*errormessage = ok ? ustringrep_from(Strings::_emptystring_)
: ustringrep_from(em);
return ok;
}
@@ -267,7 +267,7 @@ OSL_SHADEOP int
osl_texture3d(void* sg_, const char* name, void* handle, void* opt_, void* P_,
void* dPdx_, void* dPdy_, void* dPdz_, int chans, void* result,
void* dresultdx, void* dresultdy, void* alpha, void* dalphadx,
void* dalphady, ustring* errormessage)
void* dalphady, ustringrep* errormessage)
{
const Vec3& P(*(Vec3*)P_);
const Vec3& dPdx(*(Vec3*)dPdx_);
@@ -281,14 +281,16 @@ 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::float4 result_simd, dresultds_simd, dresultdt_simd,
OIIO::simd::vfloat4 result_simd, dresultds_simd, dresultdt_simd,
dresultdr_simd;
ustringhash em;
bool ok = sg->renderer->texture3d(
USTR(name), (TextureSystem::TextureHandle*)handle,
USTR(name).uhash(), (TextureSystem::TextureHandle*)handle,
sg->context->texture_thread_info(), *opt, sg, P, dPdx, dPdy, dPdz, 4,
(float*)&result_simd, derivs ? (float*)&dresultds_simd : nullptr,
derivs ? (float*)&dresultdt_simd : nullptr,
derivs ? (float*)&dresultdr_simd : nullptr, errormessage);
derivs ? (float*)&dresultdr_simd : nullptr,
errormessage ? &em : nullptr);
for (int i = 0; i < chans; ++i)
((float*)result)[i] = result_simd[i];
@@ -297,12 +299,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::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;
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;
if (dresultdx) {
for (int i = 0; i < chans; ++i)
((float*)dresultdx)[i] = dresultdx_simd[i];
@@ -315,8 +317,9 @@ osl_texture3d(void* sg_, const char* name, void* handle, void* opt_, void* P_,
}
}
if (ok && errormessage)
*errormessage = Strings::_emptystring_;
if (errormessage)
*errormessage = ok ? ustringrep_from(Strings::_emptystring_)
: ustringrep_from(em);
return ok;
}
@@ -326,7 +329,7 @@ OSL_SHADEOP int
osl_environment(void* sg_, const char* name, void* handle, void* opt_, void* R_,
void* dRdx_, void* dRdy_, int chans, void* result,
void* dresultdx, void* dresultdy, void* alpha, void* dalphadx,
void* dalphady, ustring* errormessage)
void* dalphady, ustringrep* errormessage)
{
const Vec3& R(*(Vec3*)R_);
const Vec3& dRdx(*(Vec3*)dRdx_);
@@ -335,13 +338,14 @@ 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::float4 local_result;
bool ok = sg->renderer->environment(USTR(name),
OIIO::simd::vfloat4 local_result;
ustringhash em;
bool ok = sg->renderer->environment(USTR(name).uhash(),
(TextureSystem::TextureHandle*)handle,
sg->context->texture_thread_info(),
*opt, sg, R, dRdx, dRdy, 4,
(float*)&local_result, NULL, NULL,
errormessage);
errormessage ? &em : nullptr);
for (int i = 0; i < chans; ++i)
((float*)result)[i] = local_result[i];
@@ -368,8 +372,9 @@ osl_environment(void* sg_, const char* name, void* handle, void* opt_, void* R_,
((float*)dalphady)[0] = 0.0f;
}
if (ok && errormessage)
*errormessage = Strings::_emptystring_;
if (errormessage)
*errormessage = ok ? ustringrep_from(Strings::_emptystring_)
: ustringrep_from(em);
return ok;
}
@@ -378,7 +383,7 @@ osl_environment(void* sg_, const char* name, void* handle, void* opt_, void* R_,
OSL_SHADEOP int
osl_get_textureinfo(void* sg_, const char* name, void* handle, void* dataname,
int type, int arraylen, int aggregate, void* data,
ustring* errormessage)
ustringrep* errormessage)
{
// recreate TypeDesc
TypeDesc typedesc;
@@ -388,10 +393,15 @@ osl_get_textureinfo(void* sg_, const char* name, void* handle, void* dataname,
ShaderGlobals* sg = (ShaderGlobals*)sg_;
return sg->renderer->get_texture_info(
USTR(name), (RendererServices::TextureHandle*)handle,
ustringhash em;
bool ok = sg->renderer->get_texture_info(
USTR(name).uhash(), (RendererServices::TextureHandle*)handle,
sg->context->texture_thread_info(), sg->context, 0 /*FIXME-ptex*/,
USTR(dataname), typedesc, data, errormessage);
USTR(dataname).uhash(), typedesc, data, errormessage ? &em : nullptr);
if (errormessage)
*errormessage = ok ? ustringrep_from(Strings::_emptystring_)
: ustringrep_from(em);
return ok;
}
@@ -399,7 +409,7 @@ osl_get_textureinfo(void* sg_, const char* name, void* handle, void* dataname,
OSL_SHADEOP int
osl_get_textureinfo_st(void* sg_, const char* name, void* handle, float s,
float t, void* dataname, int type, int arraylen,
int aggregate, void* data, ustring* errormessage)
int aggregate, void* data, ustringrep* errormessage)
{
// recreate TypeDesc
TypeDesc typedesc;
@@ -409,10 +419,15 @@ osl_get_textureinfo_st(void* sg_, const char* name, void* handle, float s,
ShaderGlobals* sg = (ShaderGlobals*)sg_;
return sg->renderer->get_texture_info(
USTR(name), (RendererServices::TextureHandle*)handle, s, t,
ustringhash em;
bool ok = sg->renderer->get_texture_info(
USTR(name).uhash(), (RendererServices::TextureHandle*)handle, s, t,
sg->context->texture_thread_info(), sg->context, 0 /*FIXME-ptex*/,
USTR(dataname), typedesc, data, errormessage);
USTR(dataname).uhash(), typedesc, data, errormessage ? &em : nullptr);
if (errormessage)
*errormessage = ok ? ustringrep_from(Strings::_emptystring_)
: ustringrep_from(em);
return ok;
}
+168 -56
View File
@@ -19,7 +19,6 @@
// Pull in the modified Imath headers and the OSL_HOSTDEVICE macro
#ifdef __CUDACC__
# include <OSL/oslconfig.h>
# include <optix.h>
#endif
#ifdef __CUDACC__
@@ -34,6 +33,7 @@
#include "osl_pvt.h"
#include <OSL/device_ptr.h>
#include <OSL/dual.h>
#include <OSL/dual_vec.h>
#include <OSL/genclosure.h>
@@ -100,14 +100,16 @@ print_closure(std::ostream& out, const ClosureColor* closure,
/// group.
typedef void (*RunLLVMGroupFunc)(void* shaderglobals, void* heap_arena_ptr,
void* userdata_base_pointer,
void* output_base_pointer, int shadeindex);
void* output_base_pointer, int shadeindex,
void* interactive_params_ptr);
#if OSL_USE_BATCHED
typedef void (*RunLLVMGroupFuncWide)(void* batchedshaderglobals,
void* heap_arena_ptr,
const void* wide_shade_index,
void* userdata_base_pointer,
void* output_base_pointer,
int run_mask_value);
int run_mask_value,
void* interactive_params_ptr);
#endif
/// Signature of a constant-folding method
@@ -192,8 +194,10 @@ struct UserDataNeeded {
{
if (a.name != b.name)
return a.name < b.name;
if (a.layer_num != b.layer_num)
return a.layer_num < b.layer_num;
// 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.type.basetype != b.type.basetype)
return a.type.basetype < b.type.basetype;
if (a.type.aggregate != b.type.aggregate)
@@ -212,9 +216,11 @@ struct UserDataNeeded {
struct AttributeNeeded {
ustring name;
ustring scope;
TypeDesc type;
AttributeNeeded(ustring name, ustring scope = ustring())
: name(name), scope(scope)
AttributeNeeded(ustring name, ustring scope = ustring(),
TypeDesc type = TypeUnknown)
: name(name), scope(scope), type(type)
{
}
@@ -224,6 +230,15 @@ 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
}
};
@@ -234,18 +249,33 @@ struct AttributeNeeded {
// Handy re-casting macros
#define USTR(cstr) (*((ustring*)&cstr))
#define MAT(m) (*(Matrix44*)m)
#define VEC(v) (*(Vec3*)v)
#define DFLOAT(x) (*(Dual2<Float>*)x)
#define DVEC(x) (*(Dual2<Vec3>*)x)
#define COL(x) (*(Color3*)x)
#define DCOL(x) (*(Dual2<Color3>*)x)
#if OPENIMAGEIO_VERSION >= 20500
# define TYPEDESC(x) OIIO::bitcast<TypeDesc, long long>(x)
#else
# define TYPEDESC(x) OIIO::bit_cast<long long, TypeDesc>(x)
#endif
inline ustringrep
USTR(ustring_pod s) noexcept
{
return OSL::bitcast<ustringrep>(s);
}
inline ustringrep
USTREP(ustring_pod s) noexcept
{
return OSL::bitcast<ustringrep>(s);
// return *((ustringrep*)&s);
}
// Get rid of this one soon!
inline ustringrep
USTR(const void* s) noexcept
{
return OSL::bitcast<ustringrep>(s);
}
#define MAT(m) (*(Matrix44*)m)
#define VEC(v) (*(Vec3*)v)
#define DFLOAT(x) (*(Dual2<Float>*)x)
#define DVEC(x) (*(Dual2<Vec3>*)x)
#define COL(x) (*(Color3*)x)
#define DCOL(x) (*(Dual2<Color3>*)x)
#define TYPEDESC(x) OSL::bitcast<TypeDesc, long long>(x)
/// Like an int (of type T), but also internally keeps track of the
@@ -525,9 +555,9 @@ public:
void* val);
bool LoadMemoryCompiledShader(string_view shadername, string_view buffer);
bool Parameter(ShaderGroup& group, string_view name, TypeDesc t,
const void* val, bool lockgeom);
const void* val, ParamHints props);
bool Parameter(string_view name, TypeDesc t, const void* val,
bool lockgeom);
ParamHints props);
bool Shader(ShaderGroup& group, string_view shaderusage,
string_view shadername, string_view layername);
bool Shader(string_view shaderusage, string_view shadername,
@@ -612,6 +642,7 @@ public:
///
TextureSystem* texturesys() const { return m_texturesys; }
bool use_optix() const { return m_use_optix; }
bool debug_nan() const { return m_debugnan; }
bool debug_uninit() const { return m_debug_uninit; }
bool lockgeom_default() const { return m_lockgeom_default; }
@@ -696,7 +727,7 @@ public:
/// Set the current color space.
bool set_colorspace(ustring colorspace);
int raytype_bit(ustring name);
OSLEXECPUBLIC int raytype_bit(ustring name);
void optimize_all_groups(int nthreads = 0, int mythread = 0,
int totalthreads = 1, bool do_jit = true);
@@ -862,6 +893,7 @@ private:
bool m_opt_middleman; ///< Middle-man optimization?
bool m_opt_texture_handle; ///< Use texture handles?
bool m_opt_seed_bblock_aliases; ///< Turn on basic block alias seeds
bool m_opt_useparam; ///< Perform extra useparam analysis for culling run layer calls
bool m_opt_batched_analysis; ///< Perform extra analysis required for batched execution?
bool m_llvm_jit_fma; ///< Allow fused multiply/add in JIT
bool m_llvm_jit_aggressive; ///< Turn on llvm "aggressive" JIT
@@ -895,7 +927,8 @@ private:
std::vector<ustring> m_renderer_outputs; ///< Names of renderer outputs
std::vector<SymLocationDesc> m_symlocs;
int m_max_local_mem_KB; ///< Local storage can a shader use
bool m_compile_report; ///< Print compilation report?
int m_compile_report; ///< Print compilation report?
bool m_use_optix; ///< This is an OptiX-based renderer
bool m_buffer_printf; ///< Buffer/batch printf output?
bool m_no_noise; ///< Substitute trivial noise calls
bool m_no_pointcloud; ///< Substitute trivial pointcloud calls
@@ -941,6 +974,8 @@ private:
atomic_int m_stat_global_connections; ///< Stat: global connections elim'd
atomic_int m_stat_tex_calls_codegened; ///< Stat: total texture calls
atomic_int m_stat_tex_calls_as_handles; ///< Stat: texture calls with handles
atomic_int m_stat_useparam_ops; ///< Stat: pre-optimization useparam ops
atomic_int m_stat_call_layers_inserted; ///< Stat: post-opt layer calls
double m_stat_master_load_time; ///< Stat: time loading masters
double m_stat_optimization_time; ///< Stat: time spent optimizing
double m_stat_opt_locking_time; ///< locking time
@@ -1115,8 +1150,7 @@ public:
ShadingSystemImpl& shadingsys() const { return m_master->shadingsys(); }
/// Apply pending parameters
///
void parameters(const ParamValueList& params);
void parameters(const ParamValueList& params, cspan<ParamHints> hints);
/// Find the named symbol, return its index in the symbol array, or
/// -1 if not found.
@@ -1376,14 +1410,16 @@ public:
// Using bit fields to keep the data in 8 bytes in total.
unsigned char m_valuesource : 3;
bool m_connected_down : 1;
bool m_lockgeom : 1;
int m_arraylen : 27;
bool m_interpolated : 1;
bool m_interactive : 1;
int m_arraylen : 26;
int m_data_offset;
SymOverrideInfo()
: m_valuesource(Symbol::DefaultVal)
, m_connected_down(false)
, m_lockgeom(true)
, m_interpolated(false)
, m_interactive(false)
, m_arraylen(0)
, m_data_offset(0)
{
@@ -1400,8 +1436,10 @@ public:
bool connected_down() const { return m_connected_down; }
void connected_down(bool c) { m_connected_down = c; }
bool connected() const { return valuesource() == Symbol::ConnectedVal; }
bool lockgeom() const { return m_lockgeom; }
void lockgeom(bool l) { m_lockgeom = l; }
bool interpolated() const { return m_interpolated; }
void interpolated(bool val) { m_interpolated = val; }
bool interactive() const { return m_interactive; }
void interactive(bool val) { m_interactive = val; }
int arraylen() const { return m_arraylen; }
void arraylen(int s) { m_arraylen = s; }
int dataoffset() const { return m_data_offset; }
@@ -1410,11 +1448,13 @@ public:
const SymOverrideInfo& b)
{
return a.valuesource() == b.valuesource()
&& a.lockgeom() == b.lockgeom()
&& a.interpolated() == b.interpolated()
&& a.interactive() == b.interactive()
&& a.arraylen() == b.arraylen();
}
};
typedef std::vector<SymOverrideInfo> SymOverrideInfoVec;
static_assert(sizeof(SymOverrideInfo) == 8, "SymOverrideInfo size");
SymOverrideInfo* instoverride(int i)
{
@@ -1533,8 +1573,8 @@ private:
/// Represents a single message for use by getmessage and setmessage opcodes
///
struct Message {
Message(ustring name, const TypeDesc& type, int layeridx,
ustring sourcefile, int sourceline, Message* next)
Message(ustringhash name, const TypeDesc& type, int layeridx,
ustringhash sourcefile, int sourceline, Message* next)
: name(name)
, data(nullptr)
, type(type)
@@ -1545,43 +1585,42 @@ struct Message {
{
}
/// Some messages don't have data because getmessage() was called before setmessage
/// (which is flagged as an error to avoid ambiguities caused by execution order)
///
/// Some messages don't have data because getmessage() was called before
/// setmessage (which is flagged as an error to avoid ambiguities caused
/// by execution order)
bool has_data() const { return data != nullptr; }
ustring name; ///< name of this message
ustringhash name; ///< name of this message
char* data; ///< actual data of the message (will never change once the message is created)
TypeDesc
type; ///< what kind of data is stored here? FIXME: should be TypeSpec
int layeridx; ///< layer index where this was message was created
ustring
sourcefile; ///< source code file that contains the call that created this message
int sourceline; ///< source code line that contains the call that created this message
TypeDesc type; ///< what kind of data is stored here?
int layeridx; ///< layer index where this was message was created
ustringhash sourcefile; ///< location of the call that created this message
int sourceline; ///< location of the call that created this message
Message* next; ///< linked list of messages (managed by MessageList below)
};
/// Represents the list of messages set by a given shader using setmessage and getmessage
///
/// Represents the list of messages set by a given shader using setmessage and
/// getmessage.
struct MessageList {
MessageList() : list_head(nullptr), message_data() {}
void clear()
{
list_head = NULL;
list_head = nullptr;
message_data.clear();
}
const Message* find(ustring name) const
const Message* find(ustringhash name) const
{
for (const Message* m = list_head; m != NULL; m = m->next)
for (const Message* m = list_head; m; m = m->next)
if (m->name == name)
return m; // name matches
return nullptr; // not found
}
void add(ustring name, void* data, const TypeDesc& type, int layeridx,
ustring sourcefile, int sourceline)
void add(ustringhash name, void* data, const TypeDesc& type, int layeridx,
ustringhash sourcefile, int sourceline)
{
list_head = new (message_data.alloc(sizeof(Message), alignof(Message)))
Message(name, type, layeridx, sourcefile, sourceline, list_head);
@@ -1625,8 +1664,7 @@ struct BatchedMessageBuffer {
/// ShaderInstance), and the connections among them.
class ShaderGroup {
public:
ShaderGroup(string_view name);
ShaderGroup(const ShaderGroup& g, string_view name);
ShaderGroup(string_view name, ShadingSystemImpl& shadingsys);
~ShaderGroup();
/// Clear the layers
@@ -1656,6 +1694,9 @@ public:
/// Array indexing returns the i-th layer of the group
ShaderInstance* operator[](int i) const { return layer(i); }
/// Return a reference to the shading system for this group.
ShadingSystemImpl& shadingsys() const { return m_shadingsys; }
int optimized() const { return m_optimized; }
void optimized(int opt) { m_optimized = opt; }
@@ -1882,6 +1923,54 @@ public:
return nullptr;
}
// Given a data block for interactive params, allocate space for it to
// live with the group and copy the initial data.
void setup_interactive_arena(cspan<uint8_t> paramblock);
uint8_t* interactive_arena_ptr()
{
return m_interactive_arena.get();
}
device_ptr<uint8_t>& device_interactive_arena()
{
return m_device_interactive_arena;
}
struct InteractiveParamData {
int layer;
ustring name;
int offset;
InteractiveParamData(int layer, ustring name, int offset)
: layer(layer), name(name), offset(offset)
{
}
bool operator==(const InteractiveParamData& other) const
{
return layer == other.layer && name == other.name;
}
bool operator<(const InteractiveParamData& other) const
{
return layer < other.layer
|| (layer == other.layer && name < other.name);
}
};
void add_interactive_param(int layer, ustring name, size_t offset)
{
m_interactive_params.emplace_back(layer, name,
static_cast<int>(offset));
}
int interactive_param_offset(int layer, ustring name)
{
for (auto& f : m_interactive_params)
if (f.layer == layer && f.name == name)
return f.offset;
return -1;
}
private:
// Put all the things that are read-only (after optimization) and
// needed on every shade execution at the front of the struct, as much
@@ -1925,6 +2014,7 @@ 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;
@@ -1936,9 +2026,18 @@ private:
// PTX assembly for compiled ShaderGroup
std::string m_llvm_ptx_compiled_version;
ParamValueList m_pending_params; ///< Pending Parameter() values
ustring m_group_use; ///< "Usage" of group
bool m_complete = false; ///< Successfully ShaderGroupEnd?
ParamValueList m_pending_params; // Pending Parameter() values
std::vector<ParamHints> m_pending_hints; // ParamHints of pending params
ustring m_group_use; // "Usage" of group
bool m_complete = false; // Successfully ShaderGroupEnd?
ShadingSystemImpl& m_shadingsys; // Back-ptr to the shading system
// Per-group home for interactively editable parameters
std::vector<InteractiveParamData> m_interactive_params;
std::unique_ptr<uint8_t[]> m_interactive_arena;
size_t m_interactive_arena_size = 0;
device_ptr<uint8_t> m_device_interactive_arena;
friend class OSL::pvt::ShadingSystemImpl;
friend class OSL::pvt::BackendLLVM;
@@ -2210,7 +2309,7 @@ public:
int dict_value(int nodeID, ustring attribname, TypeDesc type, void* data);
bool osl_get_attribute(ShaderGlobals* sg, void* objdata, int dest_derivs,
ustring obj_name, ustring attr_name,
ustringhash obj_name, ustringhash attr_name,
int array_lookup, int index, TypeDesc attr_type,
void* attr_dest);
@@ -2593,6 +2692,19 @@ protected:
std::vector<char> m_in_conditional; ///< Whether each op is in a cond
std::vector<char> m_in_loop; ///< Whether each op is in a loop
int m_first_return; ///< Op number of first return or exit
struct CallLayerKey {
int bblockid;
int layerid;
bool operator<(const CallLayerKey& other) const
{
return bblockid < other.bblockid
|| (bblockid == other.bblockid && layerid < other.layerid);
}
};
std::set<CallLayerKey>
m_call_layers_inserted; ///< Lookup used during llvm gen
};
}; // namespace pvt
+1 -1
View File
@@ -27,7 +27,7 @@
#pragma clang diagnostic ignored "-Wparentheses-equality"
#endif
#if OSL_CLANG_VERSION >= 150000
#if (OSL_CLANG_VERSION >= 150000) || (OSL_INTEL_CLANG_VERSION >= 140000)
#pragma clang diagnostic ignored "-Wunused-but-set-variable"
#endif
+2 -21
View File
@@ -288,7 +288,8 @@ public:
}
// TODO: This is really the only part of parsing that needs the lock still.
// But the calling code setting locale complicates this.
// The calling code no longer sets the global locale, so it would
// likely be simple to clean this up.
//
bool parse(OSOReader* reader, const char* what) {
yy_switch_to_buffer(m_buffer, m_scanner);
@@ -310,12 +311,6 @@ 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);
@@ -326,7 +321,6 @@ 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;
}
@@ -339,22 +333,9 @@ 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;
}
+46 -40
View File
@@ -12,25 +12,26 @@ OSL_NAMESPACE_ENTER
namespace pvt {
#ifdef USE_PARTIO
typedef std::unordered_map<ustring, std::unique_ptr<PointCloud>> PointCloudMap;
using PointCloudMap
= std::unordered_map<ustringhash, std::unique_ptr<PointCloud>>;
static PointCloudMap pointclouds;
static OIIO::spin_mutex pointcloudmap_mutex;
PointCloud*
PointCloud::get(ustring filename, bool write)
PointCloud::get(ustringhash filename, bool write)
{
if (filename.empty())
return NULL;
return nullptr;
spin_lock lock(pointcloudmap_mutex);
PointCloudMap::const_iterator found = pointclouds.find(filename);
if (found != pointclouds.end())
return found->second.get();
// Not found. Create a new one.
Partio::ParticlesDataMutable* partio_cloud = NULL;
Partio::ParticlesDataMutable* partio_cloud = nullptr;
if (!write) {
partio_cloud = Partio::read(filename.c_str(), false);
if (!partio_cloud)
return NULL;
return nullptr;
} else {
partio_cloud = Partio::create();
}
@@ -40,7 +41,7 @@ PointCloud::get(ustring filename, bool write)
}
PointCloud::PointCloud(ustring filename,
PointCloud::PointCloud(ustringhash filename,
Partio::ParticlesDataMutable* partio_cloud, bool write)
: m_filename(filename), m_partio_cloud(partio_cloud), m_write(write)
{
@@ -76,8 +77,10 @@ PointCloud::~PointCloud()
} // namespace pvt
int
RendererServices::pointcloud_search(ShaderGlobals* sg, ustring filename,
RendererServices::pointcloud_search(ShaderGlobals* sg, ustringhash filename,
const Vec3& center, float radius,
int max_points, bool sort,
size_t* out_indices, float* out_distances,
@@ -86,17 +89,17 @@ RendererServices::pointcloud_search(ShaderGlobals* sg, ustring filename,
#ifdef USE_PARTIO
if (filename.empty())
return 0;
PointCloud* pc = PointCloud::get(filename);
PointCloud* pc = PointCloud::get(ustring_from(filename));
if (pc == NULL) { // The file failed to load
sg->context->errorfmt("pointcloud_search: could not open \"{}\"",
filename);
ustring_from(filename));
return 0;
}
const Partio::ParticlesData* cloud = pc->read_access();
if (cloud == NULL) { // The file failed to load
sg->context->errorfmt("pointcloud_search: could not open \"{}\"",
filename);
ustring_from(filename));
return 0;
}
@@ -192,25 +195,26 @@ RendererServices::pointcloud_search(ShaderGlobals* sg, ustring filename,
int
RendererServices::pointcloud_get(ShaderGlobals* sg, ustring filename,
size_t* indices, int count, ustring attr_name,
TypeDesc attr_type, void* out_data)
RendererServices::pointcloud_get(ShaderGlobals* sg, ustringhash filename,
size_t* indices, int count,
ustringhash attr_name, TypeDesc attr_type,
void* out_data)
{
#ifdef USE_PARTIO
if (!count)
return 1; // always succeed if not asking for any data
PointCloud* pc = PointCloud::get(filename);
PointCloud* pc = PointCloud::get(ustring_from(filename));
if (pc == NULL) { // The file failed to load
sg->context->errorfmt("pointcloud_get: could not open \"{}\"",
filename);
ustring_from(filename));
return 0;
}
const Partio::ParticlesData* cloud = pc->read_access();
if (cloud == NULL) { // The file failed to load
sg->context->errorfmt("pointcloud_get: could not open \"{}\"",
filename);
ustring_from(filename));
return 0;
}
@@ -219,7 +223,7 @@ RendererServices::pointcloud_get(ShaderGlobals* sg, ustring filename,
if (!attr) {
sg->context->errorfmt(
"Accessing unexisting attribute {} in pointcloud \"{}\"", attr_name,
filename);
ustring_from(filename));
return 0;
}
@@ -232,7 +236,7 @@ RendererServices::pointcloud_get(ShaderGlobals* sg, ustring filename,
if (!compatiblePartioType(partio_type, element_type)) {
sg->context->errorfmt(
"Type of attribute \"{}\" : {} not compatible with OSL's {} in \"{}\" pointcloud",
attr_name, partio_type, element_type, filename);
attr_name, partio_type, element_type, ustring_from(filename));
return 0;
}
@@ -263,9 +267,9 @@ RendererServices::pointcloud_get(ShaderGlobals* sg, ustring filename,
for (int i = 0; i < count; ++i) {
int ind = strindices[i];
if (ind >= 0 && ind < sicount)
((ustring*)out_data)[i] = ustring(strings[ind]);
((ustringrep*)out_data)[i] = ustringrep(strings[ind]);
else
((ustring*)out_data)[i] = ustring();
((ustringrep*)out_data)[i] = ustringrep();
}
} else {
// All cases aside from strings are simple.
@@ -286,15 +290,16 @@ RendererServices::pointcloud_get(ShaderGlobals* sg, ustring filename,
bool
RendererServices::pointcloud_write(ShaderGlobals* /*sg*/, ustring filename,
RendererServices::pointcloud_write(ShaderGlobals* /*sg*/, ustringhash filename,
const Vec3& pos, int nattribs,
const ustring* names, const TypeDesc* types,
const void** data)
const ustringrep* names,
const TypeDesc* types, const void** data)
{
#ifdef USE_PARTIO
if (filename.empty())
return false;
PointCloud* pc = PointCloud::get(filename, true /* create file to write */);
PointCloud* pc = PointCloud::get(ustring_from(filename),
true /* create file to write */);
spin_lock lock(pc->m_mutex);
Partio::ParticlesDataMutable* cloud = pc->write_access();
if (cloud == NULL) // The file failed to load
@@ -346,10 +351,11 @@ RendererServices::pointcloud_write(ShaderGlobals* /*sg*/, ustring filename,
*(int*)cloud->dataWrite<int>(*a, p) = *(int*)(data[i]);
break;
case Partio::INDEXEDSTR: {
const char* s = *(const char**)(data[i]);
int index = cloud->lookupIndexedStr(*a, s);
ustringrep s = *(ustringrep*)(data[i]);
const char* sstr = s.c_str();
int index = cloud->lookupIndexedStr(*a, sstr);
if (index == -1)
index = cloud->registerIndexedStr(*a, s);
index = cloud->registerIndexedStr(*a, sstr);
*(int*)cloud->dataWrite<int>(*a, p) = index;
} break;
case Partio::NONE: break;
@@ -366,7 +372,7 @@ RendererServices::pointcloud_write(ShaderGlobals* /*sg*/, ustring filename,
namespace pvt {
OSL_SHADEOP int
osl_pointcloud_search(ShaderGlobals* sg, const char* filename, void* center,
osl_pointcloud_search(ShaderGlobals* sg, ustring_pod filename, void* center,
float radius, int max_points, int sort, void* out_indices,
void* out_distances, int derivs_offset, int nattrs, ...)
{
@@ -393,11 +399,11 @@ osl_pointcloud_search(ShaderGlobals* sg, const char* filename, void* center,
va_list args;
va_start(args, nattrs);
for (int i = 0; i < nattrs; i++) {
ustring attr_name = ustring::from_unique(
(const char*)va_arg(args, const char*));
long long lltype = va_arg(args, long long);
TypeDesc attr_type = TYPEDESC(lltype);
void* out_data = va_arg(args, void*);
ustring_pod attr_name_rep = (ustring_pod)va_arg(args, ustring_pod);
ustringrep attr_name = USTR(attr_name_rep);
long long lltype = va_arg(args, long long);
TypeDesc attr_type = TYPEDESC(lltype);
void* out_data = va_arg(args, void*);
sg->renderer->pointcloud_get(sg, USTR(filename), indices, count,
attr_name, attr_type, out_data);
}
@@ -416,8 +422,8 @@ osl_pointcloud_search(ShaderGlobals* sg, const char* filename, void* center,
OSL_SHADEOP int
osl_pointcloud_get(ShaderGlobals* sg, const char* filename, void* in_indices,
int count, const char* attr_name, long long attr_type,
osl_pointcloud_get(ShaderGlobals* sg, ustring_pod filename, void* in_indices,
int count, ustring_pod attr_name, long long attr_type,
void* out_data)
{
ShadingSystemImpl& shadingsys(sg->context->shadingsys());
@@ -438,8 +444,8 @@ osl_pointcloud_get(ShaderGlobals* sg, const char* filename, void* in_indices,
OSL_SHADEOP void
osl_pointcloud_write_helper(ustring* names, TypeDesc* types, void** values,
int index, const char* name, long long type,
osl_pointcloud_write_helper(ustringrep* names, TypeDesc* types, void** values,
int index, ustring_pod name, long long type,
void* val)
{
names[index] = USTR(name);
@@ -450,9 +456,9 @@ osl_pointcloud_write_helper(ustring* names, TypeDesc* types, void** values,
OSL_SHADEOP int
osl_pointcloud_write(ShaderGlobals* sg, const char* filename, const Vec3* pos,
int nattribs, const ustring* names, const TypeDesc* types,
const void** values)
osl_pointcloud_write(ShaderGlobals* sg, ustring_pod filename, const Vec3* pos,
int nattribs, const ustringrep* names,
const TypeDesc* types, const void** values)
{
ShadingSystemImpl& shadingsys(sg->context->shadingsys());
if (shadingsys.no_pointcloud()) // Debug mode to skip pointcloud expense
+5 -5
View File
@@ -15,14 +15,14 @@ namespace pvt {
#ifdef USE_PARTIO
class PointCloud {
class OSLEXECPUBLIC PointCloud {
public:
PointCloud(ustring filename, Partio::ParticlesDataMutable* partio_cloud,
PointCloud(ustringhash filename, Partio::ParticlesDataMutable* partio_cloud,
bool write);
~PointCloud();
static PointCloud* get(ustring filename, bool write = false);
static PointCloud* get(ustringhash filename, bool write = false);
typedef std::unordered_map<ustring,
typedef std::unordered_map<ustringhash,
std::unique_ptr<Partio::ParticleAttribute>>
AttributeMap;
@@ -37,7 +37,7 @@ public:
return m_partio_cloud;
}
ustring m_filename;
ustringhash m_filename;
private:
// hide just this field, because we want to control how it is accessed
+141 -31
View File
@@ -47,6 +47,24 @@ RendererServices::texturesys() const
bool
RendererServices::get_matrix(ShaderGlobals* sg, Matrix44& result,
ustringhash from, float time)
{
return false;
}
bool
RendererServices::get_matrix(ShaderGlobals* sg, Matrix44& result,
ustringhash from)
{
return false;
}
bool
RendererServices::get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
TransformationPtr xform, float time)
@@ -73,8 +91,9 @@ RendererServices::get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
bool
RendererServices::get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
ustring to, float time)
ustringhash to, float time)
{
// return get_inverse_matrix(sg, result, ustring_from(to), time);
bool ok = get_matrix(sg, result, to, time);
if (ok)
result.invert();
@@ -85,8 +104,9 @@ RendererServices::get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
bool
RendererServices::get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
ustring to)
ustringhash to)
{
// return get_inverse_matrix(sg, result, ustring_from(to));
bool ok = get_matrix(sg, result, to);
if (ok)
result.invert();
@@ -95,11 +115,60 @@ RendererServices::get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
RendererServices::TextureHandle*
RendererServices::get_texture_handle(ustring filename, ShadingContext* context)
bool
RendererServices::transform_points(ShaderGlobals* sg, ustringhash from,
ustringhash to, float time, const Vec3* Pin,
Vec3* Pout, int npoints,
TypeDesc::VECSEMANTICS vectype)
{
return texturesys()->get_texture_handle(filename,
return false;
}
bool
RendererServices::get_attribute(ShaderGlobals* sg, bool derivatives,
ustringhash object, TypeDesc type,
ustringhash name, void* val)
{
return false;
}
bool
RendererServices::get_array_attribute(ShaderGlobals* sg, bool derivatives,
ustringhash object, TypeDesc type,
ustringhash name, int index, void* val)
{
return false;
}
bool
RendererServices::get_userdata(bool derivatives, ustringhash name,
TypeDesc type, ShaderGlobals* sg, void* val)
{
return false;
// return get_userdata(derivatives, ustring_from(name), type, sg, val);
}
RendererServices::TextureHandle*
RendererServices::get_texture_handle(ustringhash filename,
ShadingContext* context,
const TextureOpt* options)
{
#ifdef OIIO_TEXTURESYSTEM_SUPPORTS_COLORSPACE
return texturesys()->get_texture_handle(ustring_from(filename),
context->texture_thread_info(),
options);
#else
return texturesys()->get_texture_handle(ustring_from(filename),
context->texture_thread_info());
#endif
}
@@ -120,20 +189,26 @@ RendererServices::is_udim(TextureHandle* texture_handle)
bool
RendererServices::texture(ustring filename, TextureHandle* texture_handle,
RendererServices::texture(ustringhash filename, TextureHandle* texture_handle,
TexturePerthread* texture_thread_info,
TextureOpt& options, ShaderGlobals* sg, float s,
float t, float dsdx, float dtdx, float dsdy,
float dtdy, int nchannels, float* result,
float* dresultds, float* dresultdt,
ustring* errormessage)
ustringhash* errormessage)
{
ShadingContext* context = sg->context;
if (!texture_thread_info)
texture_thread_info = context->texture_thread_info();
if (!texture_handle)
texture_handle = texturesys()->get_texture_handle(filename,
#ifdef OIIO_TEXTURESYSTEM_SUPPORTS_COLORSPACE
texture_handle
= texturesys()->get_texture_handle(ustring_from(filename),
texture_thread_info, &options);
#else
texture_handle = texturesys()->get_texture_handle(ustring_from(filename),
texture_thread_info);
#endif
bool status = texturesys()->texture(texture_handle, texture_thread_info,
options, s, t, dsdx, dtdx, dsdy, dtdy,
nchannels, result, dresultds,
@@ -142,12 +217,12 @@ RendererServices::texture(ustring filename, TextureHandle* texture_handle,
std::string err = texturesys()->geterror();
if (err.size() && sg) {
if (errormessage) {
*errormessage = ustring(err);
*errormessage = ustringhash(err);
} else {
context->errorfmt("[RendererServices::texture] {}", err);
}
} else if (errormessage) {
*errormessage = Strings::unknown;
*errormessage = ustringhash(Strings::unknown);
}
}
return status;
@@ -156,20 +231,26 @@ RendererServices::texture(ustring filename, TextureHandle* texture_handle,
bool
RendererServices::texture3d(ustring filename, TextureHandle* texture_handle,
RendererServices::texture3d(ustringhash filename, TextureHandle* texture_handle,
TexturePerthread* texture_thread_info,
TextureOpt& options, ShaderGlobals* sg,
const Vec3& P, const Vec3& dPdx, const Vec3& dPdy,
const Vec3& dPdz, int nchannels, float* result,
float* dresultds, float* dresultdt,
float* dresultdr, ustring* errormessage)
float* dresultdr, ustringhash* errormessage)
{
ShadingContext* context = sg->context;
if (!texture_thread_info)
texture_thread_info = context->texture_thread_info();
if (!texture_handle)
texture_handle = texturesys()->get_texture_handle(filename,
#ifdef OIIO_TEXTURESYSTEM_SUPPORTS_COLORSPACE
texture_handle
= texturesys()->get_texture_handle(ustring_from(filename),
texture_thread_info, &options);
#else
texture_handle = texturesys()->get_texture_handle(ustring_from(filename),
texture_thread_info);
#endif
bool status = texturesys()->texture3d(texture_handle, texture_thread_info,
options, P, dPdx, dPdy, dPdz,
@@ -179,12 +260,12 @@ RendererServices::texture3d(ustring filename, TextureHandle* texture_handle,
std::string err = texturesys()->geterror();
if (err.size() && sg) {
if (errormessage) {
*errormessage = ustring(err);
*errormessage = ustringhash(err);
} else {
sg->context->errorfmt("[RendererServices::texture3d] {}", err);
}
} else if (errormessage) {
*errormessage = Strings::unknown;
*errormessage = Strings::unknown.uhash();
}
}
return status;
@@ -193,19 +274,26 @@ RendererServices::texture3d(ustring filename, TextureHandle* texture_handle,
bool
RendererServices::environment(ustring filename, TextureHandle* texture_handle,
RendererServices::environment(ustringhash filename,
TextureHandle* texture_handle,
TexturePerthread* texture_thread_info,
TextureOpt& options, ShaderGlobals* sg,
const Vec3& R, const Vec3& dRdx, const Vec3& dRdy,
int nchannels, float* result, float* dresultds,
float* dresultdt, ustring* errormessage)
float* dresultdt, ustringhash* errormessage)
{
ShadingContext* context = sg->context;
if (!texture_thread_info)
texture_thread_info = context->texture_thread_info();
if (!texture_handle)
texture_handle = texturesys()->get_texture_handle(filename,
#ifdef OIIO_TEXTURESYSTEM_SUPPORTS_COLORSPACE
texture_handle
= texturesys()->get_texture_handle(ustring_from(filename),
texture_thread_info, &options);
#else
texture_handle = texturesys()->get_texture_handle(ustring_from(filename),
texture_thread_info);
#endif
bool status = texturesys()->environment(texture_handle, texture_thread_info,
options, R, dRdx, dRdy, nchannels,
result, dresultds, dresultdt);
@@ -213,13 +301,13 @@ RendererServices::environment(ustring filename, TextureHandle* texture_handle,
std::string err = texturesys()->geterror();
if (err.size() && sg) {
if (errormessage) {
*errormessage = ustring(err);
*errormessage = ustringhash(err);
} else {
sg->context->errorfmt("[RendererServices::environment] {}",
err);
}
} else if (errormessage) {
*errormessage = Strings::unknown;
*errormessage = Strings::unknown.uhash();
}
}
return status;
@@ -228,34 +316,35 @@ RendererServices::environment(ustring filename, TextureHandle* texture_handle,
bool
RendererServices::get_texture_info(ustring filename,
RendererServices::get_texture_info(ustringhash filename,
TextureHandle* texture_handle,
TexturePerthread* texture_thread_info,
ShadingContext* shading_context,
int subimage, ustring dataname,
int subimage, ustringhash dataname,
TypeDesc datatype, void* data,
ustring* errormessage)
ustringhash* errormessage)
{
if (!texture_thread_info)
texture_thread_info = shading_context->texture_thread_info();
if (!texture_handle)
texture_handle = texturesys()->get_texture_handle(filename,
texture_handle = texturesys()->get_texture_handle(ustring_from(filename),
texture_thread_info);
bool status = texturesys()->get_texture_info(texture_handle,
texture_thread_info, subimage,
dataname, datatype, data);
ustring_from(dataname),
datatype, data);
if (!status) {
std::string err = texturesys()->geterror();
if (err.size()) {
if (errormessage) {
*errormessage = ustring(err);
*errormessage = ustringhash(err);
} else {
shading_context->errorfmt(
"[RendererServices::get_texture_info] {}", err);
}
} else if (errormessage) {
// gettextureinfo failed but did not provide an error, so none should be emitted
*errormessage = ustring();
*errormessage = ustringhash();
}
}
return status;
@@ -265,10 +354,10 @@ RendererServices::get_texture_info(ustring filename,
bool
RendererServices::get_texture_info(
ustring filename, TextureHandle* texture_handle, float s, float t,
ustringhash filename, TextureHandle* texture_handle, float s, float t,
TexturePerthread* texture_thread_info, ShadingContext* shading_context,
int subimage, ustring dataname, TypeDesc datatype, void* data,
ustring* errormessage)
int subimage, ustringhash dataname, TypeDesc datatype, void* data,
ustringhash* errormessage)
{
#if OIIO_VERSION >= 20307
// Newer versions of the TextureSystem interface are able to determine the
@@ -276,7 +365,7 @@ RendererServices::get_texture_info(
if (!texture_thread_info)
texture_thread_info = shading_context->texture_thread_info();
if (!texture_handle)
texture_handle = texturesys()->get_texture_handle(filename,
texture_handle = texturesys()->get_texture_handle(ustring_from(filename),
texture_thread_info);
if (texturesys()->is_udim(texture_handle)) {
TextureSystem::TextureHandle* udim_handle
@@ -297,6 +386,27 @@ RendererServices::get_texture_info(
bool
RendererServices::trace(TraceOpt& options, ShaderGlobals* sg,
const OSL::Vec3& P, const OSL::Vec3& dPdx,
const OSL::Vec3& dPdy, const OSL::Vec3& R,
const OSL::Vec3& dRdx, const OSL::Vec3& dRdy)
{
return false;
}
bool
RendererServices::getmessage(ShaderGlobals* sg, ustringhash source,
ustringhash name, TypeDesc type, void* val,
bool derivatives)
{
return false;
}
BatchedRendererServices<16>*
RendererServices::batched(WidthOf<16>)
{
+55 -16
View File
@@ -889,8 +889,10 @@ RuntimeOptimizer::simplify_params()
Symbol* s(inst()->symbol(i));
if (s->symtype() != SymTypeParam)
continue; // Skip non-params
if (!s->lockgeom())
continue; // Don't mess with params that can change with the geom
// Don't simplify params that are interpolated or interactively
// editable
if (s->interpolated() || s->interactive())
continue;
if (s->typespec().is_structure() || s->typespec().is_closure_based())
continue; // We don't mess with struct placeholders or closures
@@ -967,7 +969,7 @@ RuntimeOptimizer::simplify_params()
// examining.
ShaderInstance* uplayer = group()[c.srclayer];
Symbol* srcsym = uplayer->symbol(c.src.param);
if (!srcsym->lockgeom())
if (srcsym->interpolated())
continue; // Not if it can be overridden by geometry
// Is the source symbol known to be a global, from
@@ -2184,7 +2186,7 @@ RuntimeOptimizer::optimize_ops(int beginop, int endop,
if (opnum == inst()->m_maincodebegin) {
for (int i = inst()->firstparam(); i < inst()->lastparam(); ++i) {
Symbol* s(inst()->symbol(i));
if (s->symtype() == SymTypeOutputParam && s->lockgeom()
if (s->symtype() == SymTypeOutputParam && !s->interpolated()
&& (s->valuesource() == Symbol::DefaultVal
|| s->valuesource() == Symbol::InstanceVal)
&& !s->has_init_ops() && !s->typespec().is_closure_based()
@@ -2491,7 +2493,7 @@ RuntimeOptimizer::resolve_isconnected()
s = inst()->symbol(fieldsymid);
}
bool upconnected = s->connected();
if (!s->lockgeom() && shadingsys().userdata_isconnected())
if (s->interpolated() && shadingsys().userdata_isconnected())
upconnected = true;
int val = (upconnected ? 1 : 0) + (s->connected_down() ? 2 : 0);
turn_into_assign(op, add_constant(TypeDesc::TypeInt, &val),
@@ -3251,6 +3253,7 @@ RuntimeOptimizer::run()
m_userdata_needed.clear();
m_attributes_needed.clear();
bool does_nothing = true;
std::vector<uint8_t> interactive_data;
for (int layer = 0; layer < nlayers; ++layer) {
set_inst(layer);
if (inst()->unused())
@@ -3262,7 +3265,7 @@ RuntimeOptimizer::run()
// Find interpolated parameters
if ((s.symtype() == SymTypeParam
|| s.symtype() == SymTypeOutputParam)
&& !s.lockgeom()) {
&& s.interpolated()) {
UserDataNeeded udn(s.name(), layer, s.typespec().simpletype(),
s.data(), s.has_derivs());
std::set<UserDataNeeded>::iterator found;
@@ -3274,6 +3277,21 @@ RuntimeOptimizer::run()
m_userdata_needed.insert(udn);
}
}
// Find interactive parameters
if (s.symtype() == SymTypeParam && s.interactive()) {
// Make enough room in interactive_data to accommodate this
// interactive parameter, including correct alignment.
size_t offset = interactive_data.size();
size_t typesize = s.typespec().simpletype().size();
size_t alignment = typesize > 4 ? 8 : 4;
offset = OIIO::round_to_multiple_of_pow2(offset, alignment);
interactive_data.resize(offset + typesize);
// Copy from the instance value to the interactive block
memcpy(&interactive_data[offset], s.data(), typesize);
// Make sure the symbol remembers it's stored in the interactive
// arena with the right offset.
group().add_interactive_param(layer, s.name(), offset);
}
// Track which globals the group needs
if (s.symtype() == SymTypeGlobal) {
m_globals_needed.insert(s.name());
@@ -3331,27 +3349,44 @@ 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()));
} else {
OSL_DASSERT(op.nargs() == 4 || op.nargs() == 5);
AttributeNeeded(sym1->get_string(), ustring(),
sym2->typespec().simpletype()));
} else if (op.nargs() == 4) {
Symbol* sym2 = opargsym(op, 2);
Symbol* sym3 = opargsym(op, 3);
if (sym2->typespec().is_string()) {
// getattribute( scopename, attributename, result ) or
// getattribute( scopename, attributename, arrayindex, result )
// getattribute( scopename, attributename, result )
if (sym2->is_constant()) {
m_attributes_needed.insert(
AttributeNeeded(sym2->get_string(),
sym1->get_string()));
m_attributes_needed.insert(AttributeNeeded(
sym2->get_string(), sym1->get_string(),
sym3->typespec().simpletype()));
} else {
m_unknown_attributes_needed = true;
}
} else {
// getattribute( attributename, arrayindex, result )
m_attributes_needed.insert(
AttributeNeeded(sym1->get_string()));
AttributeNeeded(sym1->get_string(), ustring(),
sym3->typespec().simpletype()));
}
} 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;
@@ -3360,6 +3395,7 @@ RuntimeOptimizer::run()
}
}
group().does_nothing(does_nothing);
group().setup_interactive_arena(interactive_data);
m_stat_specialization_time = rop_timer();
{
@@ -3384,6 +3420,8 @@ RuntimeOptimizer::run()
new_nops, old_nops,
100.0 * double((long long)new_nops - (long long)old_nops)
/ double(old_nops));
}
if (shadingsys().m_compile_report > 1) {
if (does_nothing)
shadingcontext()->infofmt("Group does nothing");
if (m_textures_needed.size()) {
@@ -3403,7 +3441,8 @@ RuntimeOptimizer::run()
if (m_attributes_needed.size()) {
shadingcontext()->infofmt("Group needs attributes:");
for (auto&& f : m_attributes_needed)
shadingcontext()->infofmt(" {} {}", f.name, f.scope);
shadingcontext()->infofmt(" {} {} {}", f.name, f.scope,
f.type);
if (m_unknown_attributes_needed)
shadingcontext()->infofmt(
" Also may construct attribute names on the fly.");
+132 -64
View File
@@ -151,18 +151,18 @@ ShadingSystem::ShaderGroupEnd(void)
bool
ShadingSystem::Parameter(ShaderGroup& group, string_view name, TypeDesc t,
const void* val, bool lockgeom)
const void* val, ParamHints hints)
{
return m_impl->Parameter(group, name, t, val, lockgeom);
return m_impl->Parameter(group, name, t, val, hints);
}
bool
ShadingSystem::Parameter(string_view name, TypeDesc t, const void* val,
bool lockgeom)
ParamHints hints)
{
return m_impl->Parameter(name, t, val, lockgeom);
return m_impl->Parameter(name, t, val, hints);
}
@@ -943,6 +943,8 @@ ShadingSystem::convert_value(void* dst, TypeDesc dsttype, const void* src,
return false; // Unsupported conversion
}
void
register_JIT_Global(const char* global_var_name, void* global_var_addr)
{
@@ -1024,16 +1026,14 @@ ShadingSystemImpl::ShadingSystemImpl(RendererServices* renderer,
, m_opt_middleman(true)
, m_opt_texture_handle(true)
, m_opt_seed_bblock_aliases(true)
,
, m_opt_useparam(false)
#if OSL_USE_BATCHED
m_opt_batched_analysis((renderer->batched(WidthOf<16>()) != nullptr)
|| (renderer->batched(WidthOf<8>()) != nullptr))
,
, m_opt_batched_analysis((renderer->batched(WidthOf<16>()) != nullptr)
|| (renderer->batched(WidthOf<8>()) != nullptr))
#else
m_opt_batched_analysis(false)
,
, m_opt_batched_analysis(false)
#endif
m_llvm_jit_fma(false)
, m_llvm_jit_fma(false)
, m_llvm_jit_aggressive(false)
, m_optimize_nondebug(false)
, m_vector_width(4)
@@ -1049,7 +1049,8 @@ ShadingSystemImpl::ShadingSystemImpl(RendererServices* renderer,
, m_llvm_output_bitcode(0)
, m_llvm_dumpasm(0)
, m_max_local_mem_KB(2048)
, m_compile_report(false)
, m_compile_report(0)
, m_use_optix(renderer->supports("OptiX"))
, m_buffer_printf(true)
, m_no_noise(false)
, m_no_pointcloud(false)
@@ -1093,6 +1094,8 @@ ShadingSystemImpl::ShadingSystemImpl(RendererServices* renderer,
m_stat_global_connections = 0;
m_stat_tex_calls_codegened = 0;
m_stat_tex_calls_as_handles = 0;
m_stat_useparam_ops = 0;
m_stat_call_layers_inserted = 0;
m_stat_master_load_time = 0;
m_stat_optimization_time = 0;
m_stat_getattribute_time = 0;
@@ -1533,6 +1536,7 @@ ShadingSystemImpl::attribute(string_view name, TypeDesc type, const void* val)
ATTR_SET("opt_middleman", int, m_opt_middleman);
ATTR_SET("opt_texture_handle", int, m_opt_texture_handle);
ATTR_SET("opt_seed_bblock_aliases", int, m_opt_seed_bblock_aliases);
ATTR_SET("opt_useparam", int, m_opt_useparam);
ATTR_SET("opt_batched_analysis", int, m_opt_batched_analysis);
ATTR_SET("llvm_jit_fma", int, m_llvm_jit_fma);
ATTR_SET("llvm_jit_aggressive", int, m_llvm_jit_aggressive);
@@ -1702,6 +1706,7 @@ ShadingSystemImpl::getattribute(string_view name, TypeDesc type, void* val)
ATTR_DECODE("opt_middleman", int, m_opt_middleman);
ATTR_DECODE("opt_texture_handle", int, m_opt_texture_handle);
ATTR_DECODE("opt_seed_bblock_aliases", int, m_opt_seed_bblock_aliases);
ATTR_DECODE("opt_useparam", int, m_opt_useparam);
ATTR_DECODE("llvm_jit_fma", int, m_llvm_jit_fma);
ATTR_DECODE("llvm_jit_aggressive", int, m_llvm_jit_aggressive);
ATTR_DECODE_STRING("llvm_jit_target", m_llvm_jit_target);
@@ -1768,6 +1773,8 @@ ShadingSystemImpl::getattribute(string_view name, TypeDesc type, void* val)
ATTR_DECODE("stat:global_connections", int, m_stat_global_connections);
ATTR_DECODE("stat:tex_calls_codegened", int, m_stat_tex_calls_codegened);
ATTR_DECODE("stat:tex_calls_as_handles", int, m_stat_tex_calls_as_handles);
ATTR_DECODE("stat:useparam_ops", int, m_stat_useparam_ops);
ATTR_DECODE("stat:call_layers_inserted", int, m_stat_call_layers_inserted);
ATTR_DECODE("stat:master_load_time", float, m_stat_master_load_time);
ATTR_DECODE("stat:optimization_time", float, m_stat_optimization_time);
ATTR_DECODE("stat:opt_locking_time", float, m_stat_opt_locking_time);
@@ -2010,6 +2017,14 @@ ShadingSystemImpl::getattribute(ShaderGroup* group, string_view name,
*(std::string*)val = exists ? group->m_llvm_ptx_compiled_version : "";
return true;
}
if (name == "interactive_params" && type.basetype == TypeDesc::PTR) {
*(void**)val = group->m_interactive_arena.get();
return true;
}
if (name == "device_interactive_params" && type.basetype == TypeDesc::PTR) {
*(void**)val = group->m_device_interactive_arena.d_get();
return true;
}
// All the remaining attributes require the group to already be
// optimized.
@@ -2105,6 +2120,11 @@ 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;
@@ -2125,6 +2145,10 @@ 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;
}
@@ -2398,6 +2422,8 @@ ShadingSystemImpl::getstats(int level) const
* (double(m_stat_postopt_syms)
/ (std::max(1, (int)m_stat_preopt_syms))
- 1.0));
print(out, " Optimized {} useparam ops into {} llvm run layer calls\n",
m_stat_useparam_ops, m_stat_call_layers_inserted);
}
print(out, " Constant connections eliminated: {}\n",
(int)m_stat_const_connections);
@@ -2546,26 +2572,19 @@ ShadingSystemImpl::printstats() const
bool
ShadingSystemImpl::Parameter(string_view name, TypeDesc t, const void* val,
bool lockgeom)
ParamHints hints)
{
return Parameter(*m_curgroup, name, t, val, lockgeom);
return Parameter(*m_curgroup, name, t, val, hints);
}
bool
ShadingSystemImpl::Parameter(ShaderGroup& group, string_view name, TypeDesc t,
const void* val, bool lockgeom)
const void* val, ParamHints hints)
{
// We work very hard not to do extra copies of the data. First,
// grow the pending list by one (empty) slot...
group.m_pending_params.grow();
// ...then initialize it in place
group.m_pending_params.back().init(name, t, 1, val);
// If we have a possible geometric override (lockgeom=false), set the
// param's interpolation to VERTEX rather than the default CONSTANT.
if (lockgeom == false)
group.m_pending_params.back().interp(OIIO::ParamValue::INTERP_VERTEX);
group.m_pending_params.emplace_back(name, t, 1, val);
group.m_pending_hints.push_back(hints);
return true;
}
@@ -2574,7 +2593,7 @@ ShadingSystemImpl::Parameter(ShaderGroup& group, string_view name, TypeDesc t,
ShaderGroupRef
ShadingSystemImpl::ShaderGroupBegin(string_view groupname)
{
ShaderGroupRef group(new ShaderGroup(groupname));
ShaderGroupRef group(new ShaderGroup(groupname, *this));
group->m_exec_repeat = m_exec_repeat;
{
// Record the group in the SS's census of all extant groups
@@ -2702,9 +2721,11 @@ ShadingSystemImpl::Shader(ShaderGroup& group, string_view shaderusage,
}
ShaderInstanceRef instance(new ShaderInstance(master, layername));
instance->parameters(group.m_pending_params);
instance->parameters(group.m_pending_params, group.m_pending_hints);
group.m_pending_params.clear();
group.m_pending_params.shrink_to_fit();
group.m_pending_hints.clear();
group.m_pending_hints.shrink_to_fit();
if (group.m_group_use.empty()) {
// First in a group
@@ -2976,7 +2997,8 @@ ShadingSystemImpl::ShaderGroupBegin(string_view groupname, string_view usage,
}
}
string_view paramname(paramname_string);
int lockgeom = m_lockgeom_default;
int lockgeom = m_lockgeom_default;
ParamHints hints = ParamHints::none;
// For speed, reserve space. Note that for "unsized" arrays, we only
// preallocate 1 slot and let it grow as needed. That's ok. For
// everything else, we will reserve the right amount up front.
@@ -3080,6 +3102,26 @@ ShadingSystemImpl::ShaderGroupBegin(string_view groupname, string_view usage,
hint_name);
break;
}
set(hints, ParamHints::interpolated, lockgeom == 0);
} else if (hint_name == "interpolated"
&& hint_type == TypeInt) {
int v = 0;
if (!Strutil::parse_int(p, v)) {
err = true;
errdesc = fmtformat("hint {} expected int value",
hint_name);
break;
}
set(hints, ParamHints::interpolated, v);
} else if (hint_name == "interactive" && hint_type == TypeInt) {
int v = 0;
if (!Strutil::parse_int(p, v)) {
err = true;
errdesc = fmtformat("hint {} expected int value",
hint_name);
break;
}
set(hints, ParamHints::interactive, v);
} else {
err = true;
errdesc = fmtformat("unknown hint '{} {}'", hint_type,
@@ -3098,11 +3140,11 @@ ShadingSystemImpl::ShaderGroupBegin(string_view groupname, string_view usage,
bool ok = true;
if (type.basetype == TypeDesc::INT) {
ok = Parameter(*g, paramname, type, &intvals[0], lockgeom);
ok = Parameter(*g, paramname, type, &intvals[0], hints);
} else if (type.basetype == TypeDesc::FLOAT) {
ok = Parameter(*g, paramname, type, &floatvals[0], lockgeom);
ok = Parameter(*g, paramname, type, &floatvals[0], hints);
} else if (type.basetype == TypeDesc::STRING) {
ok = Parameter(*g, paramname, type, &stringvals[0], lockgeom);
ok = Parameter(*g, paramname, type, &stringvals[0], hints);
}
if (!ok) {
errstatement = pstart;
@@ -3158,10 +3200,12 @@ ShadingSystemImpl::ReParameter(ShaderGroup& group, string_view layername_,
{
// Find the named layer
ustring layername(layername_);
ShaderInstance* layer = NULL;
ShaderInstance* layer = nullptr;
int layerindex = -1;
for (int i = 0, e = group.nlayers(); i < e; ++i) {
if (group[i]->layername() == layername) {
layer = group[i];
layer = group[i];
layerindex = i;
break;
}
}
@@ -3181,8 +3225,18 @@ ShadingSystemImpl::ReParameter(ShaderGroup& group, string_view layername_,
return false;
}
// Check that it's declared to be an interactive parameter
if (!sym->interactive()) {
errorfmt(
"ReParameter cannot adjust {}.{}, which was not declared interactive",
layername, paramname);
return false;
}
// Check for mismatch versus previously-declared type
if (!equivalent(sym->typespec(), type))
if ((relaxed_param_typecheck() && !relaxed_equivalent(sym->typespec(), type))
|| (!relaxed_param_typecheck()
&& !relaxed_equivalent(sym->typespec(), type)))
return false;
// Can't change param value if the group has already been optimized,
@@ -3191,7 +3245,13 @@ ShadingSystemImpl::ReParameter(ShaderGroup& group, string_view layername_,
return false;
// Do the deed
memcpy(sym->data(), val, type.size());
int offset = group.interactive_param_offset(layerindex, sym->name());
memcpy(group.interactive_arena_ptr() + offset, val, type.size());
if (use_optix()) {
renderer()->copy_to_device(group.device_interactive_arena().d_get()
+ offset,
val, type.size());
}
return true;
}
@@ -3557,6 +3617,7 @@ 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;
@@ -4159,7 +4220,8 @@ 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), 0);
cp->apply((float*)&CC, 3, 1, 3, sizeof(float), sizeof(Color3),
3 * sizeof(Color3));
Cout.set(CC[0], (CC[1] - CC[0]) * (1.0f / eps),
(CC[2] - CC[0]) * (1.0f / eps));
return true;
@@ -4313,8 +4375,8 @@ OSL::OSLQuery::init(const ShaderGroup* group, int layernum)
// firstcheck,nchecks are used to check just one element of an array.
OSL_SHADEOP void
osl_naninf_check(int ncomps, const void* vals_, int has_derivs, void* sg,
const void* sourcefile, int sourceline, void* symbolname,
int firstcheck, int nchecks, const void* opname)
ustring_pod sourcefile, int sourceline, ustring_pod symbolname,
int firstcheck, int nchecks, ustring_pod opname)
{
ShadingContext* ctx = (ShadingContext*)((ShaderGlobals*)sg)->context;
const float* vals = (const float*)vals_;
@@ -4345,10 +4407,10 @@ osl_naninf_check(int ncomps, const void* vals_, int has_derivs, void* sg,
// element of an array.
OSL_SHADEOP void
osl_uninit_check(long long typedesc_, void* vals_, void* sg,
const void* sourcefile, int sourceline, const char* groupname,
int layer, const char* layername, const char* shadername,
int opnum, const char* opname, int argnum, void* symbolname,
int firstcheck, int nchecks)
ustring_pod sourcefile, int sourceline, ustring_pod groupname_,
int layer, ustring_pod layername_, ustring_pod shadername,
int opnum, ustring_pod opname, int argnum,
ustring_pod symbolname, int firstcheck, int nchecks)
{
TypeDesc typedesc = TYPEDESC(typedesc_);
ShadingContext* ctx = (ShadingContext*)((ShaderGlobals*)sg)->context;
@@ -4378,30 +4440,34 @@ osl_uninit_check(long long typedesc_, void* vals_, void* sg,
}
}
if (uninit) {
ustringrep groupname = USTR(groupname_);
ustringrep layername = USTR(layername_);
ctx->errorfmt(
"Detected possible use of uninitialized value in {} {} at {}:{} (group {}, layer {} {}, shader {}, op {} '{}', arg {})",
typedesc.c_str(), USTR(symbolname), USTR(sourcefile), sourceline,
(groupname && groupname[0]) ? groupname : "<unnamed group>", layer,
(layername && layername[0]) ? layername : "<unnamed layer>",
shadername, opnum, USTR(opname), argnum);
typedesc, USTR(symbolname), USTR(sourcefile), sourceline,
groupname.empty() ? "<unnamed group>" : groupname.c_str(), layer,
layername.empty() ? "<unnamed layer>" : layername.c_str(),
USTR(shadername), opnum, USTR(opname), argnum);
}
}
OSL_SHADEOP 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)
osl_range_check_err(int indexvalue, int length, ustring_pod symname, void* sg,
ustring_pod sourcefile, int sourceline,
ustring_pod groupname_, int layer, ustring_pod layername_,
ustring_pod shadername)
{
ustringrep groupname = USTR(groupname_);
ustringrep layername = USTR(layername_);
if (indexvalue < 0 || indexvalue >= length) {
ShadingContext* ctx = (ShadingContext*)((ShaderGlobals*)sg)->context;
ctx->errorfmt(
"Index [{}] out of range {}[0..{}]: {}:{} (group {}, layer {} {}, shader {})",
indexvalue, USTR(symname), length - 1, USTR(sourcefile), sourceline,
(groupname && groupname[0]) ? groupname : "<unnamed group>", layer,
(layername && layername[0]) ? layername : "<unnamed layer>",
groupname.empty() ? "<unnamed group>" : groupname.c_str(), layer,
layername.empty() ? "<unnamed layer>" : layername.c_str(),
USTR(shadername));
if (indexvalue >= length)
indexvalue = length - 1;
@@ -4415,7 +4481,7 @@ osl_range_check_err(int indexvalue, int length, const char* symname, void* sg,
// Asked if the raytype is a name we can't know until mid-shader.
OSL_SHADEOP int
osl_raytype_name(void* sg_, const char* name)
osl_raytype_name(void* sg_, ustring_pod name)
{
ShaderGlobals* sg = (ShaderGlobals*)sg_;
int bit = sg->context->shadingsys().raytype_bit(USTR(name));
@@ -4424,24 +4490,21 @@ osl_raytype_name(void* sg_, const char* name)
OSL_SHADEOP int
osl_get_attribute(void* sg_, int dest_derivs, void* obj_name_, void* attr_name_,
int array_lookup, int index, long long attr_type,
void* attr_dest)
osl_get_attribute(void* sg_, int dest_derivs, ustring_pod obj_name,
ustring_pod attr_name, int array_lookup, int index,
long long attr_type, void* attr_dest)
{
ShaderGlobals* sg = (ShaderGlobals*)sg_;
const ustring& obj_name = USTR(obj_name_);
const ustring& attr_name = USTR(attr_name_);
ShaderGlobals* sg = (ShaderGlobals*)sg_;
return sg->context->osl_get_attribute(sg, sg->objdata, dest_derivs,
obj_name, attr_name, array_lookup,
index, TYPEDESC(attr_type),
attr_dest);
USTR(obj_name), USTR(attr_name),
array_lookup, index,
TYPEDESC(attr_type), attr_dest);
}
OSL_SHADEOP int
osl_bind_interpolated_param(void* sg_, const void* name, long long type,
osl_bind_interpolated_param(void* sg_, ustring_pod 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,
@@ -4459,8 +4522,13 @@ 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, symbol_data_size);
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);
return 1;
}
return 0; // no such user data
+1 -1
View File
@@ -42,7 +42,7 @@ enum {
// clang-format off
namespace { // anon namespace to avoid duplicate OptiX symbols
OSL_CONSTANT_DATA const static SplineBasis gBasisSet[kNumSplineTypes] = {
OSL_CONSTANT_DATA const SplineBasis gBasisSet[kNumSplineTypes] = {
//
// catmullrom
//
+21
View File
@@ -149,6 +149,27 @@ 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
+4 -2
View File
@@ -90,8 +90,10 @@ 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)
#include "wide_opbinary_per_component_float_or_vector_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"
static OSL_FORCEINLINE float
+1 -6
View File
@@ -28,12 +28,7 @@ namespace {
OSL_FORCEINLINE OSL_HOSTDEVICE int
bitcast_to_uint(float x)
{
#if OPENIMAGEIO_VERSION >= 20500
return OIIO::bitcast<unsigned int, float>(x);
#else
// obsolete call
return OIIO::bit_cast<float, unsigned int>(x);
#endif
return OSL::bitcast<unsigned int>(x);
}
+102 -38
View File
@@ -45,6 +45,18 @@ invoke(FunctorT f)
f();
}
// helper to make a Block<ustringhash> from a pointer
#if !OSL_USTRINGREP_IS_HASH
inline void
block_ustringhash_from_ptr(Block<ustringhash>& b, const void* w_ptr)
{
for (int i = 0; i < __OSL_WIDTH; ++i)
b.set(i, reinterpret_cast<const ustring*>(w_ptr)[i]);
}
#endif
OSL_FORCEINLINE void
invert_wide_matrix(Masked<Matrix44> wresult, Wide<const Matrix44> wmatrix)
{
@@ -88,12 +100,12 @@ invert_wide_matrix(Masked<Matrix44> wresult, Wide<const Matrix44> wmatrix)
Mask
default_get_matrix(BatchedRendererServices* bsr, BatchedShaderGlobals* bsg,
Masked<Matrix44> wresult, Wide<const ustring> wfrom,
Masked<Matrix44> wresult, Wide<const ustringhash> wfrom,
Wide<const float> wtime)
{
Mask ok(false);
foreach_unique(wfrom, wresult.mask(),
[=, &ok](const ustring& from, Mask from_mask) {
[=, &ok](const ustringhash& from, Mask from_mask) {
// Reuse the uniform from implementation by restricting results to
// just the lanes with the same value of "from".
Masked<Matrix44> wsub_result(wresult.data(), from_mask);
@@ -110,7 +122,7 @@ default_get_matrix(BatchedRendererServices* bsr, BatchedShaderGlobals* bsg,
// execute the ISA optimized default version built right here.
OSL_FORCEINLINE Mask
dispatch_get_matrix(BatchedRendererServices* bsr, BatchedShaderGlobals* bsg,
Masked<Matrix44> result, Wide<const ustring> from,
Masked<Matrix44> result, Wide<const ustringhash> from,
Wide<const float> time)
{
if (bsr->is_overridden_get_matrix_WmWsWf()) {
@@ -154,7 +166,7 @@ dispatch_get_inverse_matrix(BatchedRendererServices* bsr,
Mask
default_get_inverse_matrix(BatchedRendererServices* bsr,
BatchedShaderGlobals* bsg, Masked<Matrix44> result,
ustring to, Wide<const float> time)
ustringhash to, Wide<const float> time)
{
OSL_FORCEINLINE_BLOCK
{
@@ -170,7 +182,7 @@ default_get_inverse_matrix(BatchedRendererServices* bsr,
OSL_FORCEINLINE Mask
dispatch_get_inverse_matrix(BatchedRendererServices* bsr,
BatchedShaderGlobals* bsg, Masked<Matrix44> result,
ustring to, Wide<const float> time)
ustringhash to, Wide<const float> time)
{
if (bsr->is_overridden_get_inverse_matrix_WmsWf()) {
return bsr->get_inverse_matrix(bsg, result, to, time);
@@ -183,12 +195,12 @@ dispatch_get_inverse_matrix(BatchedRendererServices* bsr,
Mask
default_get_inverse_matrix(BatchedRendererServices* bsr,
BatchedShaderGlobals* bsg, Masked<Matrix44> wresult,
Wide<const ustring> wto, Wide<const float> wtime)
Wide<const ustringhash> wto, Wide<const float> wtime)
{
if (bsr->is_overridden_get_inverse_matrix_WmsWf()) {
Mask ok(false);
foreach_unique(wto, wresult.mask(),
[=, &ok](const ustring& to, Mask from_mask) {
[=, &ok](const ustringhash& to, Mask from_mask) {
// Reuse the uniform from implementation by restricting results to
// just the lanes with the same value of "from".
Masked<Matrix44> wsub_result(wresult.data(),
@@ -213,7 +225,7 @@ default_get_inverse_matrix(BatchedRendererServices* bsr,
OSL_FORCEINLINE Mask
dispatch_get_inverse_matrix(BatchedRendererServices* bsr,
BatchedShaderGlobals* bsg, Masked<Matrix44> result,
Wide<const ustring> to, Wide<const float> time)
Wide<const ustringhash> to, Wide<const float> time)
{
if (bsr->is_overridden_get_inverse_matrix_WmWsWf()) {
return bsr->get_inverse_matrix(bsg, result, to, time);
@@ -627,7 +639,7 @@ impl_wide_mat_multiply(ResultAccessorT wresult, FromAccessorT wfrom,
OSL_FORCEINLINE Mask
impl_get_varying_from_matrix_batched(BatchedShaderGlobals* bsg,
ShadingContext* ctx,
Wide<const ustring> wFrom,
Wide<const ustringhash> wFrom,
Masked<Matrix44> wMfrom)
{
// Deal with a varying 'from' space
@@ -646,7 +658,7 @@ impl_get_varying_from_matrix_batched(BatchedShaderGlobals* bsg,
: common_space_bits, shader_space_bits,
object_space_bits, named_space_bits))
for (int lane = 0; lane < __OSL_WIDTH; ++lane) {
ustring from = wFrom[lane];
ustringhash from = wFrom[lane];
if (wMfrom.mask()[lane]) {
if (from == Strings::common || from == commonspace_synonym) {
// inline of Mask::set_on(lane)
@@ -703,10 +715,10 @@ impl_get_varying_from_matrix_batched(BatchedShaderGlobals* bsg,
if (ctx->shadingsys().unknown_coordsys_error()) {
for (int lane = 0; lane < __OSL_WIDTH; ++lane) {
if (failedLanes[lane]) {
ustring from = wFrom[lane];
ustringhash from = wFrom[lane];
ctx->batched<__OSL_WIDTH>().errorfmt(
Mask(Lane(lane)), "Unknown transformation \"{}\"",
from);
ustring(from));
}
}
}
@@ -746,7 +758,13 @@ __OSL_MASKED_OP2(prepend_matrix_from, Wm, Ws)(void* bsg_, void* wr,
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
ShadingContext* ctx = bsg->uniform.context;
Wide<const ustring> wFromName(w_from_name);
#if OSL_USTRINGREP_IS_HASH
Wide<const ustringhash> wFromName(w_from_name);
#else
Block<ustringhash> bwFromName;
block_ustringhash_from_ptr(bwFromName, w_from_name);
Wide<const ustringhash> wFromName(bwFromName);
#endif
Block<Matrix44> wMfrom;
Masked<Matrix44> from_matrix(wMfrom, Mask(mask_value));
@@ -762,7 +780,8 @@ __OSL_MASKED_OP2(prepend_matrix_from, Wm, Ws)(void* bsg_, void* wr,
namespace {
OSL_FORCEINLINE Mask
impl_get_varying_to_matrix_masked(BatchedShaderGlobals* bsg,
ShadingContext* ctx, Wide<const ustring> wTo,
ShadingContext* ctx,
Wide<const ustringhash> wTo,
Masked<Matrix44> wMto)
{
// Deal with a varying 'to' space
@@ -781,7 +800,7 @@ impl_get_varying_to_matrix_masked(BatchedShaderGlobals* bsg,
: common_space_bits, shader_space_bits,
object_space_bits, named_space_bits))
for (int lane = 0; lane < __OSL_WIDTH; ++lane) {
ustring to = wTo[lane];
ustringhash to = wTo[lane];
if (wMto.mask()[lane]) {
if (to == Strings::common || to == commonspace_synonym) {
// inline of Mask::set_on(lane)
@@ -836,10 +855,10 @@ impl_get_varying_to_matrix_masked(BatchedShaderGlobals* bsg,
if (ctx->shadingsys().unknown_coordsys_error()) {
for (int lane = 0; lane < __OSL_WIDTH; ++lane) {
if (failedLanes[lane]) {
ustring to = wTo[lane];
ustringhash to = wTo[lane];
ctx->batched<__OSL_WIDTH>().errorfmt(
Mask(Lane(lane)), "Unknown transformation \"{}\"",
to);
ustring(to));
}
}
}
@@ -895,7 +914,13 @@ __OSL_MASKED_OP3(get_from_to_matrix, Wm, s,
Mask succeeded = impl_get_uniform_from_matrix_masked(bsg, from_matrix,
from);
Wide<const ustring> wToSpace(w_to_ptr);
#if OSL_USTRINGREP_IS_HASH
Wide<const ustringhash> wToSpace(w_to_ptr);
#else
Block<ustringhash> bwToSpace;
block_ustringhash_from_ptr(bwToSpace, w_to_ptr);
Wide<const ustringhash> wToSpace(bwToSpace);
#endif
Block<Matrix44> wMto;
// NOTE: even if we failed to get a from matrix, it should have been set to
// identity, so we still need to try to get the to matrix for the original mask
@@ -917,7 +942,13 @@ __OSL_MASKED_OP3(get_from_to_matrix, Wm, Ws,
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
ShadingContext* ctx = bsg->uniform.context;
Wide<const ustring> wFromName(w_from_ptr);
#if OSL_USTRINGREP_IS_HASH
Wide<const ustringhash> wFromName(w_from_ptr);
#else
Block<ustringhash> bwFromName;
block_ustringhash_from_ptr(bwFromName, w_from_ptr);
Wide<const ustringhash> wFromName(bwFromName);
#endif
Block<Matrix44> wMto;
Masked<Matrix44> to_matrix(wMto, Mask(mask_value));
@@ -945,14 +976,26 @@ __OSL_MASKED_OP3(get_from_to_matrix, Wm, Ws,
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
ShadingContext* ctx = bsg->uniform.context;
Wide<const ustring> wFromName(w_from_ptr);
#if OSL_USTRINGREP_IS_HASH
Wide<const ustringhash> wFromName(w_from_ptr);
#else
Block<ustringhash> bwFromName;
block_ustringhash_from_ptr(bwFromName, w_from_ptr);
Wide<const ustringhash> wFromName(bwFromName);
#endif
Block<Matrix44> wMfrom;
Masked<Matrix44> from_matrix(wMfrom, Mask(mask_value));
Mask succeeded = impl_get_varying_from_matrix_batched(bsg, ctx, wFromName,
from_matrix);
Wide<const ustring> wToSpace(w_to_ptr);
#if OSL_USTRINGREP_IS_HASH
Wide<const ustringhash> wToSpace(w_to_ptr);
#else
Block<ustringhash> bwToSpace;
block_ustringhash_from_ptr(bwToSpace, w_to_ptr);
Wide<const ustringhash> wToSpace(bwToSpace);
#endif
Block<Matrix44> wMto;
// NOTE: even if we failed to get a from matrix, it should have been set to
// identity, so we still need to try to get the to matrix for the original mask
@@ -977,9 +1020,9 @@ __OSL_MASKED_OP3(get_from_to_matrix, Wm, Ws,
// Also zeroing of derivatives is left to the code generator.
OSL_BATCHOP int
__OSL_MASKED_OP3(build_transform_matrix, Wm, s, s)(void* bsg_, void* WM_,
void* from_, void* to_,
unsigned int mask_value)
__OSL_MASKED_OP3(build_transform_matrix, Wm, s,
s)(void* bsg_, void* WM_, ustring_pod from_, ustring_pod to_,
unsigned int mask_value)
{
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
@@ -987,8 +1030,8 @@ __OSL_MASKED_OP3(build_transform_matrix, Wm, s, s)(void* bsg_, void* WM_,
Masked<Matrix44> mm(WM_, mask);
ShadingContext* ctx = bsg->uniform.context;
ustring from = USTR(from_);
ustring to = USTR(to_);
ustringrep from = USTR(from_);
ustringrep to = USTR(to_);
Mask succeeded;
// Avoid matrix concatenation if possible by detecting when the
@@ -1013,18 +1056,24 @@ __OSL_MASKED_OP3(build_transform_matrix, Wm, s, s)(void* bsg_, void* WM_,
OSL_BATCHOP int
__OSL_MASKED_OP3(build_transform_matrix, Wm, Ws, s)(void* bsg_, void* WM_,
void* wfrom_, void* to_,
unsigned int mask_value)
__OSL_MASKED_OP3(build_transform_matrix, Wm, Ws,
s)(void* bsg_, void* WM_, void* wfrom_, ustring_pod to_,
unsigned int mask_value)
{
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
Mask mask(mask_value);
Masked<Matrix44> wrm(WM_, mask);
Wide<const ustring> wfrom_space(wfrom_);
#if OSL_USTRINGREP_IS_HASH
Wide<const ustringhash> wfrom_space(wfrom_);
#else
Block<ustringhash> bwfrom_space;
block_ustringhash_from_ptr(bwfrom_space, wfrom_);
Wide<const ustringhash> wfrom_space(bwfrom_space);
#endif
ustring to_space = USTR(to_);
ustringrep to_space = USTR(to_);
Block<Matrix44> wMfrom, wMto;
Masked<Matrix44> from_matrix(wMfrom, wrm.mask());
@@ -1043,17 +1092,23 @@ __OSL_MASKED_OP3(build_transform_matrix, Wm, Ws, s)(void* bsg_, void* WM_,
OSL_BATCHOP int
__OSL_MASKED_OP3(build_transform_matrix, Wm, s, Ws)(void* bsg_, void* WM_,
void* from_, void* wto_,
unsigned int mask_value)
__OSL_MASKED_OP3(build_transform_matrix, Wm, s,
Ws)(void* bsg_, void* WM_, ustring_pod from_, void* wto_,
unsigned int mask_value)
{
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
Mask mask(mask_value);
Masked<Matrix44> wrm(WM_, mask);
ustring from = USTR(from_);
Wide<const ustring> wto_space(wto_);
ustringrep from = USTR(from_);
#if OSL_USTRINGREP_IS_HASH
Wide<const ustringhash> wto_space(wto_);
#else
Block<ustringhash> bwto_space;
block_ustringhash_from_ptr(bwto_space, wto_);
Wide<const ustringhash> wto_space(bwto_space);
#endif
Block<Matrix44> wMfrom, wMto;
Masked<Matrix44> from_matrix(wMfrom, wrm.mask());
@@ -1082,8 +1137,17 @@ __OSL_MASKED_OP3(build_transform_matrix, Wm, Ws, Ws)(void* bsg_, void* WM_,
Mask mask(mask_value);
Masked<Matrix44> wrm(WM_, mask);
Wide<const ustring> wfrom_space(wfrom_);
Wide<const ustring> wto_space(wto_);
#if OSL_USTRINGREP_IS_HASH
Wide<const ustringhash> wfrom_space(wfrom_);
Wide<const ustringhash> wto_space(wto_);
#else
Block<ustringhash> bwfrom_space;
block_ustringhash_from_ptr(bwfrom_space, wfrom_);
Wide<const ustringhash> wfrom_space(bwfrom_space);
Block<ustringhash> bwto_space;
block_ustringhash_from_ptr(bwto_space, wto_);
Wide<const ustringhash> wto_space(bwto_space);
#endif
Block<Matrix44> wMfrom, wMto;
Masked<Matrix44> from_matrix(wMfrom, wrm.mask());
+15 -14
View File
@@ -200,18 +200,19 @@ impl_setmessage(BatchedShaderGlobals* bsg, ustring sourcefile, int sourceline,
OSL_BATCHOP void
__OSL_MASKED_OP2(setmessage, s, WX)(BatchedShaderGlobals* bsg_, void* wname,
long long type, void* wvalue, int layeridx,
const char* sourcefile_, int sourceline,
__OSL_MASKED_OP2(setmessage, s, WX)(BatchedShaderGlobals* bsg_,
ustring_pod name_, long long type,
void* wvalue, int layeridx,
ustring_pod sourcefile_, int sourceline,
unsigned int mask_value)
{
Mask mask(mask_value);
OSL_ASSERT(mask.any_on());
ustring name = USTR(wname);
ustringrep name = USTR(name_);
MaskedData wsrcval(TYPEDESC(type), false /*has_derivs*/, mask, wvalue);
const ustring& sourcefile(USTR(sourcefile_));
ustringrep sourcefile = USTR(sourcefile_);
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
@@ -237,16 +238,16 @@ __OSL_MASKED_OP2(setmessage, s, WX)(BatchedShaderGlobals* bsg_, void* wname,
OSL_BATCHOP void
__OSL_MASKED_OP2(setmessage, Ws, WX)(BatchedShaderGlobals* bsg_, void* wname,
long long type, void* wvalue, int layeridx,
const char* sourcefile_, int sourceline,
ustring_pod sourcefile_, int sourceline,
unsigned int mask_value)
{
Mask mask(mask_value);
OSL_ASSERT(mask.any_on());
Wide<const ustring> wName(wname);
Wide<const ustringrep> wName(wname);
MaskedData wsrcval(TYPEDESC(type), false /*has_derivs*/, mask, wvalue);
const ustring& sourcefile(USTR(sourcefile_));
ustringrep sourcefile = USTR(sourcefile_);
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
@@ -274,14 +275,14 @@ __OSL_MASKED_OP2(setmessage, Ws, WX)(BatchedShaderGlobals* bsg_, void* wname,
OSL_BATCHOP void
__OSL_MASKED_OP(getmessage)(void* bsg_, void* result, char* source_,
char* name_, long long type_, void* val, int derivs,
int layeridx, const char* sourcefile_,
__OSL_MASKED_OP(getmessage)(void* bsg_, void* result, ustring_pod source_,
ustring_pod name_, long long type_, void* val,
int derivs, int layeridx, ustring_pod sourcefile_,
int sourceline, unsigned int mask_value)
{
const ustring& source(USTR(source_));
const ustring& name(USTR(name_));
const ustring& sourcefile(USTR(sourcefile_));
ustringrep source = USTR(source_);
ustringrep name = USTR(name_);
ustringrep sourcefile = USTR(sourcefile_);
Mask mask(mask_value);
+26 -27
View File
@@ -35,7 +35,7 @@ using PointCloudSearchResults = BatchedRendererServices::PointCloudSearchResults
namespace {
OSL_FORCEINLINE void
default_pointcloud_search(BatchedShaderGlobals* bsg, ustring filename,
default_pointcloud_search(BatchedShaderGlobals* bsg, ustringhash filename,
const void* wcenter_, Wide<const float> wradius,
int max_points, bool sort,
PointCloudSearchResults& results)
@@ -199,7 +199,7 @@ default_pointcloud_search(BatchedShaderGlobals* bsg, ustring filename,
OSL_FORCEINLINE void
dispatch_pointcloud_search(BatchedShaderGlobals* bsg, ustring filename,
dispatch_pointcloud_search(BatchedShaderGlobals* bsg, ustringhash filename,
const void* wcenter, Wide<const float> wradius,
int max_points, bool sort,
PointCloudSearchResults& results)
@@ -217,9 +217,9 @@ dispatch_pointcloud_search(BatchedShaderGlobals* bsg, ustring filename,
OSL_FORCEINLINE Mask
default_pointcloud_get(BatchedShaderGlobals* bsg, ustring filename,
default_pointcloud_get(BatchedShaderGlobals* bsg, ustringhash filename,
Wide<const int[]> windices, Wide<const int> wnum_points,
ustring attr_name, MaskedData wout_data)
ustringhash attr_name, MaskedData wout_data)
{
#ifdef USE_PARTIO
Mask success { false };
@@ -364,9 +364,9 @@ default_pointcloud_get(BatchedShaderGlobals* bsg, ustring filename,
OSL_FORCEINLINE Mask
dispatch_pointcloud_get(BatchedShaderGlobals* bsg, ustring filename,
dispatch_pointcloud_get(BatchedShaderGlobals* bsg, ustringhash filename,
Wide<const int[]> windices, Wide<const int> wnum_points,
ustring attr_name, MaskedData wout_data)
ustringhash attr_name, MaskedData wout_data)
{
auto* bsr = bsg->uniform.renderer->batched(WidthTag());
if (bsr->is_overridden_pointcloud_get()) {
@@ -381,7 +381,7 @@ dispatch_pointcloud_get(BatchedShaderGlobals* bsg, ustring filename,
Mask
default_pointcloud_write(BatchedShaderGlobals* bsg, ustring filename,
default_pointcloud_write(BatchedShaderGlobals* bsg, ustringhash filename,
Wide<const OSL::Vec3> wpos, int nattribs,
const ustring* attr_names, const TypeDesc* attr_types,
const void** ptrs_to_wide_attr_value, Mask mask)
@@ -472,7 +472,7 @@ default_pointcloud_write(BatchedShaderGlobals* bsg, ustring filename,
OSL_FORCEINLINE Mask
dispatch_pointcloud_write(BatchedShaderGlobals* bsg, ustring filename,
dispatch_pointcloud_write(BatchedShaderGlobals* bsg, ustringhash filename,
Wide<const OSL::Vec3> wpos, int nattribs,
const ustring* attr_names, const TypeDesc* attr_types,
const void** ptrs_to_wide_attr_value, Mask mask)
@@ -494,7 +494,7 @@ dispatch_pointcloud_write(BatchedShaderGlobals* bsg, ustring filename,
OSL_BATCHOP void
__OSL_MASKED_OP(pointcloud_search)(
BatchedShaderGlobals* bsg, void* wout_num_points_, const char* filename,
BatchedShaderGlobals* bsg, void* wout_num_points_, ustring_pod filename,
const void* wcenter_, void* wradius_, int max_points, int sort,
void* wout_indices_, int indices_array_length, void* wout_distances_,
int distances_array_length, int distances_has_derivs, int mask_value,
@@ -509,16 +509,15 @@ __OSL_MASKED_OP(pointcloud_search)(
mask_value };
ShadingContext* ctx = bsg->uniform.context;
if (ctx->shadingsys()
.no_pointcloud()) // Debug mode to skip pointcloud expense
{
if (ctx->shadingsys().no_pointcloud()) {
// Debug mode to skip pointcloud expense
assign_all(pcsr.wnum_points(), 0);
return; // mask_value;
}
Wide<const float> wradius(wradius_);
dispatch_pointcloud_search(bsg, USTR(filename), wcenter_, wradius,
dispatch_pointcloud_search(bsg, USTR(filename).uhash(), wcenter_, wradius,
max_points, sort, pcsr);
if (nattrs > 0) {
@@ -528,11 +527,9 @@ __OSL_MASKED_OP(pointcloud_search)(
va_list args;
va_start(args, nattrs);
for (int i = 0; i < nattrs; i++) {
ustring attr_name = ustring::from_unique(
(const char*)va_arg(args, const char*));
long long lltype = va_arg(args, long long);
TypeDesc attr_type = TYPEDESC(lltype);
void* out_data = va_arg(args, void*);
ustringrep attr_name = USTREP(va_arg(args, ustring_pod));
TypeDesc attr_type = TYPEDESC(va_arg(args, long long));
void* out_data = va_arg(args, void*);
dispatch_pointcloud_get(
bsg, USTR(filename), windices, wnum_points, attr_name,
MaskedData { attr_type, false, Mask { mask_value }, out_data });
@@ -547,9 +544,9 @@ __OSL_MASKED_OP(pointcloud_search)(
OSL_BATCHOP int
__OSL_MASKED_OP(pointcloud_get)(BatchedShaderGlobals* bsg, const char* filename,
__OSL_MASKED_OP(pointcloud_get)(BatchedShaderGlobals* bsg, ustring_pod filename,
void* windices_, int indices_array_length,
void* wnum_points_, const char* attr_name,
void* wnum_points_, ustring_pod attr_name,
long long attr_type_, void* wout_data_,
int mask_value)
{
@@ -564,7 +561,8 @@ __OSL_MASKED_OP(pointcloud_get)(BatchedShaderGlobals* bsg, const char* filename,
TypeDesc attr_type = TYPEDESC(attr_type_);
Mask success = dispatch_pointcloud_get(
bsg, USTR(filename), windices, wnum_points, USTR(attr_name),
bsg, USTR(filename).uhash(), windices, wnum_points,
USTR(attr_name).uhash(),
MaskedData { attr_type, false, Mask { mask_value }, wout_data_ });
return success.value();
}
@@ -573,20 +571,21 @@ __OSL_MASKED_OP(pointcloud_get)(BatchedShaderGlobals* bsg, const char* filename,
OSL_BATCHOP int
__OSL_MASKED_OP(pointcloud_write)(BatchedShaderGlobals* bsg,
const char* filename, const void* wpos_,
int nattribs, const ustring* attr_names,
ustring_pod filename, const void* wpos_,
int nattribs, const ustringrep* attr_names,
const TypeDesc* attr_types,
const void** ptrs_to_wide_attr_value,
int mask_value)
{
ShadingContext* ctx = bsg->uniform.context;
if (ctx->shadingsys()
.no_pointcloud()) // Debug mode to skip pointcloud expense
return 0; // mask_value;
// Debug mode to skip pointcloud expense
if (ctx->shadingsys().no_pointcloud())
return 0; // mask_value;
Wide<const OSL::Vec3> wpos(wpos_);
Mask success = dispatch_pointcloud_write(bsg, USTR(filename), wpos,
Mask success = dispatch_pointcloud_write(bsg, USTR(filename).uhash(), wpos,
nattribs, attr_names, attr_types,
ptrs_to_wide_attr_value,
Mask(mask_value));
+2 -2
View File
@@ -456,7 +456,7 @@ spline_evaluate_wide(RAccessorT wR, ustring spline_basis, XAccessorT wX,
true /*is_basis_u_constant */, 1 /* basis_step */,
ConstantWeights, RAccessorT, XAccessorT, KAccessor_T> };
unsigned int basis_type = Spline::basis_type_of(USTR(spline_basis));
unsigned int basis_type = Spline::basis_type_of(spline_basis);
OSL_DASSERT(basis_type < Spline::kNumSplineTypes
&& "unsupported spline basis");
@@ -539,7 +539,7 @@ splineinverse_evaluate_wide(RAccessorT wR, ustring spline_basis, XAccessorT wX,
true /*is_basis_u_constant */, 1 /* basis_step */,
ConstantWeights, RAccessorT, XAccessorT, KAccessor_T> };
unsigned int basis_type = Spline::basis_type_of(USTR(spline_basis));
unsigned int basis_type = Spline::basis_type_of(spline_basis);
OSL_DASSERT(basis_type < Spline::kNumSplineTypes
&& "unsupported spline basis");
+2 -2
View File
@@ -354,7 +354,7 @@ __OSL_MASKED_OP(regex_impl)(void* bsg_, void* wsuccess_ptr, void* wsubject_ptr,
const std::string& subject = usubject.string();
std::match_results<std::string::const_iterator> mresults;
const std::regex& regex(ctx->find_regex(USTR(pattern)));
const std::regex& regex(ctx->find_regex(pattern));
if (nresults > 0) {
std::string::const_iterator start = subject.begin();
int res = fullmatch ? std::regex_match(subject, mresults, regex)
@@ -366,7 +366,7 @@ __OSL_MASKED_OP(regex_impl)(void* bsg_, void* wsuccess_ptr, void* wsubject_ptr,
else
results[r] = mresults[r / 2].second - start;
} else {
results[r] = USTR(pattern).length();
results[r] = pattern.length();
}
}
wsuccess[lane] = res;
+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::float4 to speedup texture transformation below
OIIO::simd::float4 result_simd, dresultds_simd, dresultdt_simd;
// NOTE: using simd::vfloat4 to speedup texture transformation below
OIIO::simd::vfloat4 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::float4 dresultdx_simd;
OIIO::simd::float4 dresultdy_simd;
OIIO::simd::vfloat4 dresultdx_simd;
OIIO::simd::vfloat4 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::float4 to speedup texture transformation below
OIIO::simd::float4 result_simd, dresultds_simd, dresultdt_simd,
// NOTE: using simd::vfloat4 to speedup texture transformation below
OIIO::simd::vfloat4 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::float4 dresultdx_simd;
OIIO::simd::float4 dresultdy_simd;
OIIO::simd::vfloat4 dresultdx_simd;
OIIO::simd::vfloat4 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::float4 to speedup texture transformation below
OIIO::simd::float4 result_simd;
// NOTE: using simd::vfloat4 to speedup texture transformation below
OIIO::simd::vfloat4 result_simd;
bool retVal = false;
+99 -84
View File
@@ -29,9 +29,9 @@ using WidthTag = OSL::WidthOf<__OSL_WIDTH>;
// firstcheck,nchecks are used to check just one element of an array.
OSL_BATCHOP void
__OSL_OP(naninf_check)(int ncomps, const void* vals_, int has_derivs,
void* bsg_, const void* sourcefile, int sourceline,
void* symbolname, int firstcheck, int nchecks,
const void* opname)
void* bsg_, ustring_pod sourcefile, int sourceline,
ustring_pod symbolname, int firstcheck, int nchecks,
ustring_pod opname)
{
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
ShadingContext* ctx = bsg->uniform.context;
@@ -56,9 +56,9 @@ __OSL_OP(naninf_check)(int ncomps, const void* vals_, int has_derivs,
OSL_BATCHOP void
__OSL_MASKED_OP1(naninf_check_offset,
i)(int mask_value, int ncomps, const void* vals_,
int has_derivs, void* bsg_, const void* sourcefile,
int sourceline, void* symbolname, int firstcheck,
int nchecks, const void* opname)
int has_derivs, void* bsg_, ustring_pod sourcefile,
int sourceline, ustring_pod symbolname, int firstcheck,
int nchecks, ustring_pod opname)
{
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
ShadingContext* ctx = bsg->uniform.context;
@@ -88,12 +88,12 @@ __OSL_MASKED_OP1(naninf_check_offset,
// Wide vals + mask + varying index
OSL_BATCHOP void
__OSL_MASKED_OP1(naninf_check_offset, Wi)(int mask_value, int ncomps,
const void* vals_, int has_derivs,
void* bsg_, const void* sourcefile,
int sourceline, void* symbolname,
const void* wide_offsets_ptr,
int nchecks, const void* opname)
__OSL_MASKED_OP1(naninf_check_offset,
Wi)(int mask_value, int ncomps, const void* vals_,
int has_derivs, void* bsg_, ustring_pod sourcefile,
int sourceline, ustring_pod symbolname,
const void* wide_offsets_ptr, int nchecks,
ustring_pod opname)
{
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
ShadingContext* ctx = bsg->uniform.context;
@@ -129,9 +129,9 @@ __OSL_MASKED_OP1(naninf_check_offset, Wi)(int mask_value, int ncomps,
OSL_BATCHOP void
__OSL_OP2(uninit_check_values_offset, X,
i)(long long typedesc_, void* vals_, void* bsg_,
const void* sourcefile, int sourceline, const char* groupname,
int layer, const char* layername, const char* shadername,
int opnum, const char* opname, int argnum, void* symbolname,
ustring_pod sourcefile, int sourceline, ustring_pod groupname_,
int layer, ustring_pod layername_, ustring_pod shadername,
int opnum, ustring_pod opname, int argnum, ustring_pod symbolname,
int firstcheck, int nchecks)
{
TypeDesc typedesc = TYPEDESC(typedesc_);
@@ -163,12 +163,14 @@ __OSL_OP2(uninit_check_values_offset, X,
}
}
if (uninit) {
ustringrep groupname = USTR(groupname_);
ustringrep layername = USTR(layername_);
ctx->errorfmt(
"Detected possible use of uninitialized value in {} {} at {}:{} (group {}, layer {} {}, shader {}, op {} '{}', arg {})",
typedesc, USTR(symbolname), USTR(sourcefile), sourceline,
(groupname && groupname[0]) ? groupname : "<unnamed group>", layer,
(layername && layername[0]) ? layername : "<unnamed layer>",
shadername, opnum, USTR(opname), argnum);
typedesc, symbolname, sourcefile, sourceline,
groupname.empty() ? "<unnamed group>" : groupname.c_str(), layer,
layername.empty() ? "<unnamed layer>" : layername.c_str(),
shadername, opnum, opname, argnum);
}
}
@@ -179,10 +181,11 @@ __OSL_OP2(uninit_check_values_offset, X,
OSL_BATCHOP void
__OSL_MASKED_OP2(uninit_check_values_offset, WX,
i)(int mask_value, long long typedesc_, void* vals_,
void* bsg_, const void* sourcefile, int sourceline,
const char* groupname, int layer, const char* layername,
const char* shadername, int opnum, const char* opname,
int argnum, void* symbolname, int firstcheck, int nchecks)
void* bsg_, ustring_pod sourcefile, int sourceline,
ustring_pod groupname_, int layer, ustring_pod layername_,
ustring_pod shadername, int opnum, ustring_pod opname,
int argnum, ustring_pod symbolname, int firstcheck,
int nchecks)
{
TypeDesc typedesc = TYPEDESC(typedesc_);
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
@@ -224,12 +227,14 @@ __OSL_MASKED_OP2(uninit_check_values_offset, WX,
});
}
if (lanes_uninit.any_on()) {
ustringrep groupname = USTR(groupname_);
ustringrep layername = USTR(layername_);
ctx->errorfmt(
"Detected possible use of uninitialized value in {} {} at {}:{} (group {}, layer {} {}, shader {}, op {} '{}', arg {}) for lanes({:x}) of batch",
typedesc, USTR(symbolname), USTR(sourcefile), sourceline,
(groupname && groupname[0]) ? groupname : "<unnamed group>", layer,
(layername && layername[0]) ? layername : "<unnamed layer>",
shadername, opnum, USTR(opname), argnum, lanes_uninit.value());
typedesc, symbolname, sourcefile, sourceline,
groupname.empty() ? "<unnamed group>" : groupname.c_str(), layer,
layername.empty() ? "<unnamed layer>" : layername.c_str(),
shadername, opnum, opname, argnum, lanes_uninit.value());
}
}
@@ -240,11 +245,11 @@ __OSL_MASKED_OP2(uninit_check_values_offset, WX,
OSL_BATCHOP void
__OSL_MASKED_OP2(uninit_check_values_offset, X,
Wi)(int mask_value, long long typedesc_, void* vals_,
void* bsg_, const void* sourcefile, int sourceline,
const char* groupname, int layer, const char* layername,
const char* shadername, int opnum, const char* opname,
int argnum, void* symbolname, const void* wide_offsets_ptr,
int nchecks)
void* bsg_, ustring_pod sourcefile, int sourceline,
ustring_pod groupname_, int layer, ustring_pod layername_,
ustring_pod shadername, int opnum, ustring_pod opname,
int argnum, ustring_pod symbolname,
const void* wide_offsets_ptr, int nchecks)
{
TypeDesc typedesc = TYPEDESC(typedesc_);
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
@@ -288,12 +293,14 @@ __OSL_MASKED_OP2(uninit_check_values_offset, X,
}
if (lanes_uninit.any_on()) {
ustringrep groupname = USTR(groupname_);
ustringrep layername = USTR(layername_);
ctx->errorfmt(
"Detected possible use of uninitialized value in {} {} at {}:{} (group {}, layer {} {}, shader {}, op {} '{}', arg {}) for lanes({:x}) of batch",
typedesc, USTR(symbolname), USTR(sourcefile), sourceline,
(groupname && groupname[0]) ? groupname : "<unnamed group>", layer,
(layername && layername[0]) ? layername : "<unnamed layer>",
shadername, opnum, USTR(opname), argnum, lanes_uninit.value());
typedesc, symbolname, sourcefile, sourceline,
groupname.empty() ? "<unnamed group>" : groupname.c_str(), layer,
layername.empty() ? "<unnamed layer>" : layername.c_str(),
shadername, opnum, opname, argnum, lanes_uninit.value());
}
}
@@ -304,11 +311,11 @@ __OSL_MASKED_OP2(uninit_check_values_offset, X,
OSL_BATCHOP void
__OSL_MASKED_OP2(uninit_check_values_offset, WX,
Wi)(int mask_value, long long typedesc_, void* vals_,
void* bsg_, const void* sourcefile, int sourceline,
const char* groupname, int layer, const char* layername,
const char* shadername, int opnum, const char* opname,
int argnum, void* symbolname, const void* wide_offsets_ptr,
int nchecks)
void* bsg_, ustring_pod sourcefile, int sourceline,
ustring_pod groupname_, int layer, ustring_pod layername_,
ustring_pod shadername, int opnum, ustring_pod opname,
int argnum, ustring_pod symbolname,
const void* wide_offsets_ptr, int nchecks)
{
TypeDesc typedesc = TYPEDESC(typedesc_);
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
@@ -354,33 +361,38 @@ __OSL_MASKED_OP2(uninit_check_values_offset, WX,
}
if (lanes_uninit.any_on()) {
ustringrep groupname = USTR(groupname_);
ustringrep layername = USTR(layername_);
ctx->errorfmt(
"Detected possible use of uninitialized value in {} {} at {}:{} (group {}, layer {} {}, shader {}, op {} '{}', arg {}) for lanes({:x}) of batch",
typedesc, USTR(symbolname), USTR(sourcefile), sourceline,
(groupname && groupname[0]) ? groupname : "<unnamed group>", layer,
(layername && layername[0]) ? layername : "<unnamed layer>",
shadername, opnum, USTR(opname), argnum, lanes_uninit.value());
typedesc, symbolname, sourcefile, sourceline,
groupname.empty() ? "<unnamed group>" : groupname.c_str(), layer,
layername.empty() ? "<unnamed layer>" : layername.c_str(),
shadername, opnum, opname, argnum, lanes_uninit.value());
}
}
OSL_BATCHOP int
__OSL_OP(range_check)(int indexvalue, int length, const char* symname,
void* bsg_, const void* sourcefile, int sourceline,
const char* groupname, int layer, const char* layername,
const char* shadername)
__OSL_OP(range_check)(int indexvalue, int length, ustring_pod symname,
void* bsg_, ustring_pod sourcefile, int sourceline,
ustring_pod groupname_, int layer, ustring_pod layername_,
ustring_pod shadername)
{
if (indexvalue < 0 || indexvalue >= length) {
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
ShadingContext* ctx = bsg->uniform.context;
ctx->errorfmt(
"Index [{}] out of range {}[0..{}]: {}:{}"
" (group {}, layer {} {}, shader {})",
indexvalue, USTR(symname), length - 1, USTR(sourcefile), sourceline,
(groupname && groupname[0]) ? groupname : "<unnamed group>", layer,
(layername && layername[0]) ? layername : "<unnamed layer>",
USTR(shadername));
ustringrep groupname = USTR(groupname_);
ustringrep layername = USTR(layername_);
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
ShadingContext* ctx = bsg->uniform.context;
ctx->errorfmt("Index [{}] out of range {}[0..{}]: {}:{}"
" (group {}, layer {} {}, shader {})",
indexvalue, USTR(symname), length - 1, USTR(sourcefile),
sourceline,
groupname.empty() ? "<unnamed group>" : groupname.c_str(),
layer,
layername.empty() ? "<unnamed layer>" : layername.c_str(),
USTR(shadername));
if (indexvalue >= length)
indexvalue = length - 1;
else
@@ -393,12 +405,14 @@ __OSL_OP(range_check)(int indexvalue, int length, const char* symname,
OSL_BATCHOP void
__OSL_MASKED_OP(range_check)(void* wide_indexvalue, unsigned int mask_value,
int length, const char* symname, void* bsg_,
const void* sourcefile, int sourceline,
const char* groupname, int layer,
const char* layername, const char* shadername)
int length, ustring_pod symname, void* bsg_,
ustring_pod sourcefile, int sourceline,
ustring_pod groupname_, int layer,
ustring_pod layername_, ustring_pod shadername)
{
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
ustringrep groupname = USTR(groupname_);
ustringrep layername = USTR(layername_);
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
Masked<int> wIndexValue(wide_indexvalue, Mask(mask_value));
wIndexValue.mask().foreach ([=](ActiveLane lane) -> void {
int indexvalue = wIndexValue[lane];
@@ -408,9 +422,9 @@ __OSL_MASKED_OP(range_check)(void* wide_indexvalue, unsigned int mask_value,
"Index [{}] out of range {}[0..{}]: {}:{} (group {}, layer {} {}, shader {})",
indexvalue, USTR(symname), length - 1, USTR(sourcefile),
sourceline,
(groupname && groupname[0]) ? groupname : "<unnamed group>",
groupname.empty() ? "<unnamed group>" : groupname.c_str(),
layer,
(layername && layername[0]) ? layername : "<unnamed layer>",
layername.empty() ? "<unnamed layer>" : layername.c_str(),
USTR(shadername));
if (indexvalue >= length)
indexvalue = length - 1;
@@ -425,17 +439,17 @@ __OSL_MASKED_OP(range_check)(void* wide_indexvalue, unsigned int mask_value,
OSL_BATCHOP int
__OSL_OP1(get_attribute, s)(void* bsg_, int dest_derivs, void* obj_name_,
void* attr_name_, int array_lookup, int index,
__OSL_OP1(get_attribute, s)(void* bsg_, int dest_derivs, ustring_pod obj_name_,
ustring_pod attr_name_, int array_lookup, int index,
const void* attr_type, void* wide_attr_dest,
int mask_)
{
Mask mask(mask_);
ASSERT(mask.any_on());
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
const ustring& obj_name = USTR(obj_name_);
const ustring& attr_name = USTR(attr_name_);
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
ustringrep obj_name = USTR(obj_name_);
ustringrep attr_name = USTR(attr_name_);
// Ignoring m_next_failed_attrib cache for now,
// might be faster
@@ -457,16 +471,16 @@ __OSL_OP1(get_attribute, s)(void* bsg_, int dest_derivs, void* obj_name_,
OSL_BATCHOP int
__OSL_MASKED_OP1(get_attribute,
Ws)(void* bsg_, int dest_derivs, void* obj_name_,
void* wattr_name_, int array_lookup, int index,
Ws)(void* bsg_, int dest_derivs, ustring_pod obj_name_,
ustring_pod* wattr_name_, int array_lookup, int index,
const void* attr_type, void* wide_attr_dest, int mask_)
{
Mask mask(mask_);
ASSERT(mask.any_on());
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
const ustring& obj_name = USTR(obj_name_);
Wide<const ustring> wAttrName(wattr_name_);
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
ustringrep obj_name = USTR(obj_name_);
Wide<const ustringrep> wAttrName(wattr_name_);
auto* renderer = bsg->uniform.context->batched<__OSL_WIDTH>().renderer();
Mask retVal(false);
@@ -504,13 +518,14 @@ __OSL_MASKED_OP1(get_attribute,
OSL_BATCHOP bool
__OSL_OP(get_attribute_uniform)(void* bsg_, int dest_derivs, void* obj_name_,
void* attr_name_, int array_lookup, int index,
__OSL_OP(get_attribute_uniform)(void* bsg_, int dest_derivs,
ustring_pod obj_name_, ustring_pod attr_name_,
int array_lookup, int index,
const void* attr_type, void* attr_dest)
{
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
const ustring& obj_name = USTR(obj_name_);
const ustring& attr_name = USTR(attr_name_);
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
ustringrep obj_name = USTR(obj_name_);
ustringrep attr_name = USTR(attr_name_);
auto* renderer = bsg->uniform.context->batched<__OSL_WIDTH>().renderer();
@@ -530,7 +545,7 @@ __OSL_OP(get_attribute_uniform)(void* bsg_, int dest_derivs, void* obj_name_,
OSL_BATCHOP int
__OSL_OP(bind_interpolated_param)(void* bsg_, const void* name, long long type,
__OSL_OP(bind_interpolated_param)(void* bsg_, ustring_pod name, long long type,
int userdata_has_derivs, void* userdata_data,
int symbol_has_derivs, void* symbol_data,
int symbol_data_size,
@@ -580,7 +595,7 @@ __OSL_OP(raytype_bit)(void* bsg_, int bit)
// Asked if the raytype is a name we can't know until mid-shader.
OSL_BATCHOP int
__OSL_OP(raytype_name)(void* bsg_, void* name)
__OSL_OP(raytype_name)(void* bsg_, ustring_pod name)
{
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
int bit = bsg->uniform.context->shadingsys().raytype_bit(USTR(name));
@@ -590,11 +605,11 @@ __OSL_OP(raytype_name)(void* bsg_, void* name)
OSL_BATCHOP void
__OSL_MASKED_OP(raytype_name)(void* bsg_, void* r_, void* name_,
__OSL_MASKED_OP(raytype_name)(void* bsg_, void* r_, ustringrep* name_,
unsigned int mask_value)
{
auto* bsg = reinterpret_cast<BatchedShaderGlobals*>(bsg_);
Wide<const ustring> wname(name_);
Wide<const ustringrep> wname(name_);
Mask mask(mask_value);
foreach_unique(wname, mask, [=](ustring name, Mask matching_lanes) -> void {
+5 -5
View File
@@ -67,11 +67,11 @@ scramble(uint32_t v0, uint32_t v1 = 0, uint32_t v2 = 0)
// clang-format off
namespace { // anon namespace to avoid duplicate OptiX symbols
static OSL_CONSTANT_DATA float zero[] = { 0.0f, 0.0f, 0.0f, 0.0f };
OSL_CONSTANT_DATA float zero[] = { 0.0f, 0.0f, 0.0f, 0.0f };
// Gradient table for 2D. These could be programmed the Ken Perlin way with
// some clever bit-twiddling, but this is more clear, and not really slower.
static OSL_CONSTANT_DATA float grad2lut[8][2] = {
OSL_CONSTANT_DATA float grad2lut[8][2] = {
{ -1.0f, -1.0f }, { 1.0f, 0.0f }, { -1.0f, 0.0f }, { 1.0f, 1.0f },
{ -1.0f, 1.0f }, { 0.0f, -1.0f }, { 0.0f, 1.0f }, { 1.0f, -1.0f }
};
@@ -82,7 +82,7 @@ static OSL_CONSTANT_DATA float grad2lut[8][2] = {
// but these 12 (including 4 repeats to make the array length a power
// of two) work better. They are not random, they are carefully chosen
// to represent a small, isotropic set of directions.
static OSL_CONSTANT_DATA float grad3lut[16][3] = {
OSL_CONSTANT_DATA float grad3lut[16][3] = {
{ 1.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f }, // 12 cube edges
{ -1.0f, 0.0f, 1.0f }, { 0.0f, -1.0f, 1.0f },
{ 1.0f, 0.0f, -1.0f }, { 0.0f, 1.0f, -1.0f },
@@ -94,7 +94,7 @@ static OSL_CONSTANT_DATA float grad3lut[16][3] = {
};
// Gradient directions for 4D
static OSL_CONSTANT_DATA float grad4lut[32][4] = {
OSL_CONSTANT_DATA float grad4lut[32][4] = {
{ 0.0f, 1.0f, 1.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, -1.0f }, { 0.0f, 1.0f, -1.0f, 1.0f }, { 0.0f, 1.0f, -1.0f, -1.0f }, // 32 tesseract edges
{ 0.0f, -1.0f, 1.0f, 1.0f }, { 0.0f, -1.0f, 1.0f, -1.0f }, { 0.0f, -1.0f, -1.0f, 1.0f }, { 0.0f, -1.0f, -1.0f, -1.0f },
{ 1.0f, 0.0f, 1.0f, 1.0f }, { 1.0f, 0.0f, 1.0f, -1.0f }, { 1.0f, 0.0f, -1.0f, 1.0f }, { 1.0f, 0.0f, -1.0f, -1.0f },
@@ -108,7 +108,7 @@ static OSL_CONSTANT_DATA float grad4lut[32][4] = {
// A lookup table to traverse the simplex around a given point in 4D.
// Details can be found where this table is used, in the 4D noise method.
/* TODO: This should not be required, backport it from Bill's GLSL code! */
static OSL_CONSTANT_DATA unsigned char simplex[64][4] = {
OSL_CONSTANT_DATA unsigned char simplex[64][4] = {
{0,1,2,3},{0,1,3,2},{0,0,0,0},{0,2,3,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,2,3,0},
{0,2,1,3},{0,0,0,0},{0,3,1,2},{0,3,2,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,3,2,0},
{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},
+2 -2
View File
@@ -521,8 +521,8 @@ OSLInput::open(const std::string& name, ImageSpec& newspec,
exprcount++);
std::string sourcecode = OIIO::Strutil::fmt::format(
"shader {} (\n"
" float s = u [[ int lockgeom=0 ]],\n"
" float t = v [[ int lockgeom=0 ]],\n"
" float s = u [[ int interpolated=1 ]],\n"
" float t = v [[ int interpolated=1 ]],\n"
" output color result = 0,\n"
" output float alpha = 1,\n"
" )\n"
+13 -2
View File
@@ -3,7 +3,7 @@
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
set (CMAKE_AUTOMOC ON)
if (Qt5_POSITION_INDEPENDENT_CODE)
if (Qt5_POSITION_INDEPENDENT_CODE OR Qt6_POSITION_INDEPENDENT_CODE)
set (CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
set (osltoy_srcs
@@ -13,6 +13,17 @@ set_target_properties (osltoy PROPERTIES FOLDER "Tools")
target_link_libraries (osltoy
PRIVATE
oslexec
Qt5::Core Qt5::Gui Qt5::Widgets
$<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>
${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)
+14 -1
View File
@@ -178,7 +178,8 @@ public:
layout->addWidget(m_image);
m_info = new QLabel(this);
m_info->setAlignment(Qt::AlignTop | Qt::AlignLeft);
m_info->setAlignment(
static_cast<Qt::Alignment>(Qt::AlignTop | Qt::AlignLeft));
m_info->setMinimumSize(textSize, m_res);
layout->addWidget(m_info);
@@ -198,7 +199,11 @@ 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;
};
@@ -293,7 +298,11 @@ 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();
@@ -343,7 +352,11 @@ 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,6 +16,10 @@
#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>
+10 -20
View File
@@ -16,30 +16,20 @@ 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" ]]
)
{
// 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);
}
// 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);
}
}
+1 -1
View File
@@ -8,7 +8,7 @@ set (testrender_srcs
simpleraytracer.cpp
testrender.cpp)
if (USE_OPTIX)
if (OSL_USE_OPTIX)
list (APPEND testrender_srcs optixraytracer.cpp)
set (testrender_cuda_srcs
cuda/quad.cu
+9 -8
View File
@@ -265,7 +265,7 @@ rend_get_userdata(OSL::StringParam name, void* data, int data_size,
__device__ int
osl_bind_interpolated_param(void* sg_, const void* name, long long type,
osl_bind_interpolated_param(void* sg_, OSL::StringParam 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,
@@ -411,10 +411,10 @@ osl_texture(void* sg_, const char* name, void* handle, void* opt_, float s,
__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)
osl_range_check_err(int indexvalue, int length, OSL::ustring_pod symname,
void* sg, OSL::ustring_pod sourcefile, int sourceline,
OSL::ustring_pod groupname, int layer,
OSL::ustring_pod layername, OSL::ustring_pod shadername)
{
if (indexvalue < 0 || indexvalue >= length) {
return indexvalue < 0 ? 0 : length - 1;
@@ -425,9 +425,10 @@ osl_range_check_err(int indexvalue, int length, const char* symname, void* sg,
__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)
osl_range_check(int indexvalue, int length, OSL::ustring_pod symname, void* sg,
OSL::ustring_pod sourcefile, int sourceline,
OSL::ustring_pod groupname, int layer,
OSL::ustring_pod layername, OSL::ustring_pod shadername)
{
if (indexvalue < 0 || indexvalue >= length) {
indexvalue = osl_range_check_err(indexvalue, length, symname, sg,
+11 -6
View File
@@ -183,14 +183,19 @@ __closesthit__closest_hit_osl()
sg.context = &shading_context;
// Run the OSL group and init functions
auto sbtdata = reinterpret_cast<GenericData*>(optixGetSbtDataPointer());
const unsigned int shaderInitOpIdx = 2u + 2u * sg.shaderID + 0u;
const unsigned int shaderGroupIdx = 2u + 2u * sg.shaderID + 1u;
optixDirectCall<void, ShaderGlobals*, void*, void*, void*, int>(
shaderInitOpIdx, &sg, params, nullptr, nullptr,
0); // call osl_init_func
optixDirectCall<void, ShaderGlobals*, void*, void*, void*, int>(
shaderGroupIdx, &sg, params, nullptr, nullptr,
0); // call osl_group_func
// call osl_init_func
optixDirectCall<void, ShaderGlobals*, void*, void*, void*, int, void*>(
shaderInitOpIdx, &sg /*shaderglobals_ptr*/, params /*groupdata_ptr*/,
nullptr /*userdata_base_ptr*/, nullptr /*output_base_ptr*/,
0 /*shadeindex - unused*/, sbtdata->data /*interactive_params_ptr*/);
// call osl_group_func
optixDirectCall<void, ShaderGlobals*, void*, void*, void*, int, void*>(
shaderGroupIdx, &sg /*shaderglobals_ptr*/, params /*groupdata_ptr*/,
nullptr /*userdata_base_ptr*/, nullptr /*output_base_ptr*/,
0 /*shadeindex - unused*/, sbtdata->data /*interactive_params_ptr*/);
float3 result = process_closure((OSL::ClosureColor*)sg.Ci);
uint3 launch_dims = optixGetLaunchDimensions();
+50 -23
View File
@@ -111,29 +111,42 @@ OptixRaytracer::~OptixRaytracer()
uint64_t
OptixRaytracer::register_global(const std::string& str, uint64_t value)
void*
OptixRaytracer::device_alloc(size_t size)
{
auto it = m_globals_map.find(ustring(str));
if (it != m_globals_map.end()) {
return it->second;
void* ptr = nullptr;
cudaError_t res = cudaMalloc(reinterpret_cast<void**>(&ptr), size);
if (res != cudaSuccess) {
errhandler().errorfmt("cudaMalloc({}) failed with error: {}\n", size,
cudaGetErrorString(res));
}
m_globals_map[ustring(str)] = value;
return value;
return ptr;
}
bool
OptixRaytracer::fetch_global(const std::string& str, uint64_t* value)
void
OptixRaytracer::device_free(void* ptr)
{
auto it = m_globals_map.find(ustring(str));
if (it != m_globals_map.end()) {
*value = it->second;
return true;
cudaError_t res = cudaFree(ptr);
if (res != cudaSuccess) {
errhandler().errorfmt("cudaFree() failed with error: {}\n",
cudaGetErrorString(res));
}
return false;
}
void*
OptixRaytracer::copy_to_device(void* dst_device, const void* src_host,
size_t size)
{
cudaError_t res = cudaMemcpy(dst_device, src_host, size,
cudaMemcpyHostToDevice);
if (res != cudaSuccess) {
errhandler().errorfmt(
"cudaMemcpy host->device of size {} failed with error: {}\n", size,
cudaGetErrorString(res));
}
return dst_device;
}
@@ -449,6 +462,7 @@ OptixRaytracer::make_optix_materials()
// Create materials
int mtl_id = 0;
std::vector<void*> material_interactive_params;
for (const auto& groupref : shaders()) {
std::string group_name, init_name, entry_name;
shadingsys->getattribute(groupref.get(), "groupname", group_name);
@@ -474,7 +488,6 @@ OptixRaytracer::make_optix_materials()
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);
@@ -486,6 +499,11 @@ OptixRaytracer::make_optix_materials()
OIIO::Filesystem::write_text_file(filename, osl_ptx);
}
void* interactive_params = nullptr;
shadingsys->getattribute(groupref.get(), "device_interactive_params",
TypeDesc::PTR, &interactive_params);
material_interactive_params.push_back(interactive_params);
OptixModule optix_module;
// Create Programs from the init and group_entry functions,
@@ -544,6 +562,7 @@ OptixRaytracer::make_optix_materials()
final_groups.push_back(sphere_fillSG_dc);
// append the shader groups to our "official" list of program groups
// size_t shader_groups_start_index = final_groups.size();
final_groups.insert(final_groups.end(), shader_groups.begin(),
shader_groups.end());
@@ -623,6 +642,13 @@ OptixRaytracer::make_optix_materials()
sbt_records[sbtIndex++].data = reinterpret_cast<void*>(d_quads_list);
sbt_records[sbtIndex++].data = reinterpret_cast<void*>(d_spheres_list);
// Fill in the data pointer for all the osl callables, starting at
// sbtIndex and 2 for each of the materials.
for (size_t i = 0, e = material_interactive_params.size(); i < e; ++i) {
sbt_records[sbtIndex + 2 * i].data = material_interactive_params[i];
sbt_records[sbtIndex + 2 * i + 1].data = material_interactive_params[i];
}
const int nshaders = int(shader_groups.size());
const int nhitgroups = (scene.quads.size() > 0)
+ (scene.spheres.size() > 0);
@@ -882,16 +908,17 @@ OptixRaytracer::good(TextureHandle* handle OSL_MAYBE_UNUSED)
/// Given the name of a texture, return an opaque handle that can be
/// used with texture calls to avoid the name lookups.
RendererServices::TextureHandle*
OptixRaytracer::get_texture_handle(ustring filename OSL_MAYBE_UNUSED,
ShadingContext* shading_context
OSL_MAYBE_UNUSED)
OptixRaytracer::get_texture_handle(ustringhash filename,
ShadingContext* /*shading_context*/,
const TextureOpt* options)
{
auto itr = m_samplers.find(filename);
if (itr == m_samplers.end()) {
// Open image
OIIO::ImageBuf image;
if (!image.init_spec(filename, 0, 0)) {
errhandler().errorfmt("Could not load: {}", filename);
if (!image.init_spec(ustring_from(filename), 0, 0)) {
errhandler().errorfmt("Could not load: {} (hash {})",
ustring_from(filename), filename);
return (TextureHandle*)nullptr;
}
@@ -1072,7 +1099,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,
dst += snprintf(&buffer[dst], BufferSize - dst, "%s",
fmt_string.c_str());
format_end_found = true;
break;
+19 -17
View File
@@ -25,10 +25,7 @@ public:
OptixRaytracer();
virtual ~OptixRaytracer();
uint64_t register_global(const std::string& str, uint64_t value);
bool fetch_global(const std::string& str, uint64_t* value);
virtual int supports(string_view feature) const
int supports(string_view feature) const override
{
if (feature == "OptiX")
return true;
@@ -38,24 +35,25 @@ public:
std::string load_ptx_file(string_view filename);
bool synch_attributes();
virtual bool init_optix_context(int xres, int yres);
virtual bool make_optix_materials();
virtual bool finalize_scene();
virtual void prepare_render();
virtual void warmup();
virtual void render(int xres, int yres);
virtual void finalize_pixel_buffer();
virtual void clear();
bool init_optix_context(int xres, int yres);
bool make_optix_materials();
bool finalize_scene();
void prepare_render() override;
void warmup() override;
void render(int xres, int yres) override;
void finalize_pixel_buffer() override;
void clear() override;
/// Return true if the texture handle (previously returned by
/// get_texture_handle()) is a valid texture that can be subsequently
/// read or sampled.
virtual bool good(TextureHandle* handle);
bool good(TextureHandle* handle) override;
/// Given the name of a texture, return an opaque handle that can be
/// used with texture calls to avoid the name lookups.
virtual TextureHandle* get_texture_handle(ustring filename,
ShadingContext* shading_context);
TextureHandle* get_texture_handle(ustringhash filename,
ShadingContext* shading_context,
const TextureOpt* options) override;
// Easy way to do Optix calls
optix::Context& optix_ctx() { return m_optix_ctx; }
@@ -64,6 +62,11 @@ public:
void processPrintfBuffer(void* buffer_data, size_t buffer_size);
virtual void* device_alloc(size_t size) override;
virtual void device_free(void* ptr) override;
virtual void* copy_to_device(void* dst_device, const void* src_host,
size_t size) override;
private:
optix::Context m_optix_ctx = nullptr;
@@ -93,8 +96,7 @@ private:
OptixProgramGroup* pg);
std::string m_materials_ptx;
std::unordered_map<OIIO::ustring, optix::TextureSampler> m_samplers;
std::unordered_map<OIIO::ustring, uint64_t> m_globals_map;
std::unordered_map<ustringhash, optix::TextureSampler> m_samplers;
};
+24 -7
View File
@@ -15,7 +15,7 @@
#include <OSL/oslconfig.h>
#ifdef OSL_USE_OPTIX
#if OSL_USE_OPTIX
# include <optix.h>
# include <vector_functions.h> // from CUDA
#endif
@@ -43,8 +43,24 @@ ortho(const Vec3& n, Vec3& x, Vec3& y)
// Note: not used in OptiX mode
struct Ray {
Ray(const Vec3& o, const Vec3& d, float radius, float spread)
: origin(o), direction(d), radius(radius), spread(spread)
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))
{
}
@@ -72,6 +88,7 @@ struct Ray {
Vec3 origin, direction;
float radius, spread;
int raytype;
};
@@ -116,7 +133,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);
return Ray(eye, v, 0, spread, Ray::CAMERA);
}
// Specified by user:
@@ -150,7 +167,7 @@ struct Primitive {
void getBounds(float& minx, float& miny, float& minz, float& maxx,
float& maxy, float& maxz) const;
#ifdef OSL_USE_OPTIX
#if OSL_USE_OPTIX
virtual void setOptixVariables(void* data) const = 0;
#endif
@@ -261,7 +278,7 @@ struct Sphere final : public Primitive {
return 1 / (TWOPI * (1 - cmax));
}
#ifdef OSL_USE_OPTIX
#if OSL_USE_OPTIX
virtual void setOptixVariables(void* data) const
{
SphereParams* sphere_data = reinterpret_cast<SphereParams*>(data);
@@ -360,7 +377,7 @@ struct Quad final : public Primitive {
return d2 / (a * fabsf(dir.dot(n)));
}
#ifdef OSL_USE_OPTIX
#if OSL_USE_OPTIX
virtual void setOptixVariables(void* data) const
{
QuadParams* quad_data = reinterpret_cast<QuadParams*>(data);
+12 -2
View File
@@ -1,9 +1,13 @@
// Copyright Contributors to the Open Shading Language project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
#pragma once
#include "optix_compat.h"
#if defined(OSL_USE_OPTIX) || defined(__CUDA_ARCH__)
#if OSL_USE_OPTIX || defined(__CUDA_ARCH__)
struct RenderParams {
float3 bad_color;
@@ -63,6 +67,12 @@ struct QuadParams : PrimitiveParams {
struct GenericData {
// For geometry hit callables, data is the pointer to the array of
// primitive params for that primitive type, and sbtGeoIndex is the index
// for this primitive.
//
// For shader/material callables, data points to the interactive parameter
// data arena for that material.
void* data;
unsigned int sbtGeoIndex;
};
@@ -72,7 +82,7 @@ struct GenericData {
struct GenericRecord {
__align__(
OPTIX_SBT_RECORD_ALIGNMENT) char header[OPTIX_SBT_RECORD_HEADER_SIZE];
// What follows should duplicate GenericData
void* data;
unsigned int sbtGeoIndex;
};
+5 -4
View File
@@ -154,10 +154,11 @@ struct MxConductorParams : public MxMicrofacetBaseParams {
Color3 evalT(float cos_theta) const { return Color3(0.0f); }
float get_ior() const
{
return 0; // no transmission possible
}
// Avoid function was declared but never referenced
// float get_ior() const
// {
// return 0; // no transmission possible
// }
};
struct MxGeneralizedSchlickParams : public MxMicrofacetBaseParams {
+45 -39
View File
@@ -441,7 +441,7 @@ SimpleRaytracer::get_matrix(ShaderGlobals* /*sg*/, Matrix44& result,
bool
SimpleRaytracer::get_matrix(ShaderGlobals* /*sg*/, Matrix44& result,
ustring from, float /*time*/)
ustringhash from, float /*time*/)
{
TransformMap::const_iterator found = m_named_xforms.find(from);
if (found != m_named_xforms.end()) {
@@ -468,7 +468,7 @@ SimpleRaytracer::get_matrix(ShaderGlobals* /*sg*/, Matrix44& result,
bool
SimpleRaytracer::get_matrix(ShaderGlobals* /*sg*/, Matrix44& result,
ustring from)
ustringhash from)
{
// SimpleRaytracer doesn't understand motion blur, so we never fail
// on account of time-varying transformations.
@@ -485,7 +485,7 @@ SimpleRaytracer::get_matrix(ShaderGlobals* /*sg*/, Matrix44& result,
bool
SimpleRaytracer::get_inverse_matrix(ShaderGlobals* /*sg*/, Matrix44& result,
ustring to, float /*time*/)
ustringhash to, float /*time*/)
{
if (to == u_camera || to == u_screen || to == u_NDC || to == u_raster) {
// clang-format off
@@ -544,15 +544,15 @@ void
SimpleRaytracer::name_transform(const char* name, const OSL::Matrix44& xform)
{
std::shared_ptr<Transformation> M(new OSL::Matrix44(xform));
m_named_xforms[ustring(name)] = M;
m_named_xforms[ustringhash(name)] = M;
}
bool
SimpleRaytracer::get_array_attribute(ShaderGlobals* sg, bool derivatives,
ustring object, TypeDesc type,
ustring name, int index, void* val)
ustringhash object, TypeDesc type,
ustringhash name, int index, void* val)
{
AttrGetterMap::const_iterator g = m_attr_getters.find(name);
if (g != m_attr_getters.end()) {
@@ -572,8 +572,8 @@ SimpleRaytracer::get_array_attribute(ShaderGlobals* sg, bool derivatives,
bool
SimpleRaytracer::get_attribute(ShaderGlobals* sg, bool derivatives,
ustring object, TypeDesc type, ustring name,
void* val)
ustringhash object, TypeDesc type,
ustringhash name, void* val)
{
return get_array_attribute(sg, derivatives, object, type, name, -1, val);
}
@@ -581,7 +581,7 @@ SimpleRaytracer::get_attribute(ShaderGlobals* sg, bool derivatives,
bool
SimpleRaytracer::get_userdata(bool derivatives, ustring name, TypeDesc type,
SimpleRaytracer::get_userdata(bool derivatives, ustringhash name, TypeDesc type,
ShaderGlobals* sg, void* val)
{
// Just to illustrate how this works, respect s and t userdata, filled
@@ -612,8 +612,8 @@ SimpleRaytracer::get_userdata(bool derivatives, ustring name, TypeDesc type,
bool
SimpleRaytracer::get_osl_version(ShaderGlobals* /*sg*/, bool /*derivs*/,
ustring /*object*/, TypeDesc type,
ustring /*name*/, void* val)
ustringhash /*object*/, TypeDesc type,
ustringhash /*name*/, void* val)
{
if (type == TypeDesc::TypeInt) {
((int*)val)[0] = OSL_VERSION;
@@ -625,8 +625,8 @@ SimpleRaytracer::get_osl_version(ShaderGlobals* /*sg*/, bool /*derivs*/,
bool
SimpleRaytracer::get_camera_resolution(ShaderGlobals* /*sg*/, bool /*derivs*/,
ustring /*object*/, TypeDesc type,
ustring /*name*/, void* val)
ustringhash /*object*/, TypeDesc type,
ustringhash /*name*/, void* val)
{
if (type == TypeIntArray2) {
((int*)val)[0] = camera.xres;
@@ -639,8 +639,8 @@ SimpleRaytracer::get_camera_resolution(ShaderGlobals* /*sg*/, bool /*derivs*/,
bool
SimpleRaytracer::get_camera_projection(ShaderGlobals* /*sg*/, bool /*derivs*/,
ustring /*object*/, TypeDesc type,
ustring /*name*/, void* val)
ustringhash /*object*/, TypeDesc type,
ustringhash /*name*/, void* val)
{
if (type == TypeDesc::TypeString) {
((ustring*)val)[0] = m_projection;
@@ -652,8 +652,8 @@ SimpleRaytracer::get_camera_projection(ShaderGlobals* /*sg*/, bool /*derivs*/,
bool
SimpleRaytracer::get_camera_fov(ShaderGlobals* /*sg*/, bool derivs,
ustring /*object*/, TypeDesc type,
ustring /*name*/, void* val)
ustringhash /*object*/, TypeDesc type,
ustringhash /*name*/, void* val)
{
// N.B. in a real renderer, this may be time-dependent
if (type == TypeDesc::TypeFloat) {
@@ -668,8 +668,8 @@ SimpleRaytracer::get_camera_fov(ShaderGlobals* /*sg*/, bool derivs,
bool
SimpleRaytracer::get_camera_pixelaspect(ShaderGlobals* /*sg*/, bool derivs,
ustring /*object*/, TypeDesc type,
ustring /*name*/, void* val)
ustringhash /*object*/, TypeDesc type,
ustringhash /*name*/, void* val)
{
if (type == TypeDesc::TypeFloat) {
((float*)val)[0] = m_pixelaspect;
@@ -683,8 +683,8 @@ SimpleRaytracer::get_camera_pixelaspect(ShaderGlobals* /*sg*/, bool derivs,
bool
SimpleRaytracer::get_camera_clip(ShaderGlobals* /*sg*/, bool derivs,
ustring /*object*/, TypeDesc type,
ustring /*name*/, void* val)
ustringhash /*object*/, TypeDesc type,
ustringhash /*name*/, void* val)
{
if (type == TypeFloatArray2) {
((float*)val)[0] = m_hither;
@@ -699,8 +699,8 @@ SimpleRaytracer::get_camera_clip(ShaderGlobals* /*sg*/, bool derivs,
bool
SimpleRaytracer::get_camera_clip_near(ShaderGlobals* /*sg*/, bool derivs,
ustring /*object*/, TypeDesc type,
ustring /*name*/, void* val)
ustringhash /*object*/, TypeDesc type,
ustringhash /*name*/, void* val)
{
if (type == TypeDesc::TypeFloat) {
((float*)val)[0] = m_hither;
@@ -714,8 +714,8 @@ SimpleRaytracer::get_camera_clip_near(ShaderGlobals* /*sg*/, bool derivs,
bool
SimpleRaytracer::get_camera_clip_far(ShaderGlobals* /*sg*/, bool derivs,
ustring /*object*/, TypeDesc type,
ustring /*name*/, void* val)
ustringhash /*object*/, TypeDesc type,
ustringhash /*name*/, void* val)
{
if (type == TypeDesc::TypeFloat) {
((float*)val)[0] = m_yon;
@@ -730,8 +730,8 @@ SimpleRaytracer::get_camera_clip_far(ShaderGlobals* /*sg*/, bool derivs,
bool
SimpleRaytracer::get_camera_shutter(ShaderGlobals* /*sg*/, bool derivs,
ustring /*object*/, TypeDesc type,
ustring /*name*/, void* val)
ustringhash /*object*/, TypeDesc type,
ustringhash /*name*/, void* val)
{
if (type == TypeFloatArray2) {
((float*)val)[0] = m_shutter[0];
@@ -746,8 +746,8 @@ SimpleRaytracer::get_camera_shutter(ShaderGlobals* /*sg*/, bool derivs,
bool
SimpleRaytracer::get_camera_shutter_open(ShaderGlobals* /*sg*/, bool derivs,
ustring /*object*/, TypeDesc type,
ustring /*name*/, void* val)
ustringhash /*object*/, TypeDesc type,
ustringhash /*name*/, void* val)
{
if (type == TypeDesc::TypeFloat) {
((float*)val)[0] = m_shutter[0];
@@ -761,8 +761,8 @@ SimpleRaytracer::get_camera_shutter_open(ShaderGlobals* /*sg*/, bool derivs,
bool
SimpleRaytracer::get_camera_shutter_close(ShaderGlobals* /*sg*/, bool derivs,
ustring /*object*/, TypeDesc type,
ustring /*name*/, void* val)
ustringhash /*object*/, TypeDesc type,
ustringhash /*name*/, void* val)
{
if (type == TypeDesc::TypeFloat) {
((float*)val)[0] = m_shutter[1];
@@ -776,8 +776,8 @@ SimpleRaytracer::get_camera_shutter_close(ShaderGlobals* /*sg*/, bool derivs,
bool
SimpleRaytracer::get_camera_screen_window(ShaderGlobals* /*sg*/, bool derivs,
ustring /*object*/, TypeDesc type,
ustring /*name*/, void* val)
ustringhash /*object*/, TypeDesc type,
ustringhash /*name*/, void* val)
{
// N.B. in a real renderer, this may be time-dependent
if (type == TypeFloatArray4) {
@@ -823,6 +823,7 @@ 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
@@ -831,13 +832,16 @@ SimpleRaytracer::globals_from_hit(ShaderGlobals& sg, const Ray& r,
}
Vec3
SimpleRaytracer::eval_background(const Dual2<Vec3>& dir, ShadingContext* ctx)
SimpleRaytracer::eval_background(const Dual2<Vec3>& dir, ShadingContext* ctx,
int bounce)
{
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);
}
@@ -859,7 +863,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 (backgroundResolution > 0) {
if (b > 0 && backgroundResolution > 0) {
float bg_pdf = 0;
Vec3 bg = background.eval(r.direction, bg_pdf);
path_radiance
@@ -869,7 +873,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);
* eval_background(r.direction, ctx, b);
}
}
break;
@@ -931,7 +935,8 @@ 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 = Ray(sg.P, bg_dir.val(), radius, 0,
Ray::SHADOW);
Dual2<float> shadow_dist;
if (!scene.intersect(shadow_ray, shadow_dist,
shadow_id)) // ray reached the background?
@@ -956,7 +961,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 = Ray(sg.P, ldir, radius, 0, Ray::SHADOW);
// 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
@@ -979,7 +984,8 @@ 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;
bsdf_pdf = p.pdf;
r.raytype = Ray::DIFFUSE; // FIXME? Use DIFFUSE for all indiirect rays
r.direction = p.wi;
r.radius = radius;
// Just simply use roughness as spread slope
+54 -47
View File
@@ -30,23 +30,23 @@ public:
virtual ~SimpleRaytracer() {}
// RendererServices support:
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result,
TransformationPtr xform, float time);
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result, ustring from,
float time);
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result,
TransformationPtr xform);
virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result, ustring from);
virtual bool get_inverse_matrix(ShaderGlobals* sg, Matrix44& result,
ustring to, float time);
virtual bool get_array_attribute(ShaderGlobals* sg, bool derivatives,
ustring object, TypeDesc type,
ustring name, int index, void* val);
virtual bool get_attribute(ShaderGlobals* sg, bool derivatives,
ustring object, TypeDesc type, ustring name,
void* val);
virtual bool get_userdata(bool derivatives, ustring name, TypeDesc type,
ShaderGlobals* sg, void* val);
bool get_matrix(ShaderGlobals* sg, Matrix44& result,
TransformationPtr xform, float time) override;
bool get_matrix(ShaderGlobals* sg, Matrix44& result, ustringhash from,
float time) override;
bool get_matrix(ShaderGlobals* sg, Matrix44& result,
TransformationPtr xform) override;
bool get_matrix(ShaderGlobals* sg, Matrix44& result,
ustringhash from) override;
bool get_inverse_matrix(ShaderGlobals* sg, Matrix44& result, ustringhash to,
float time) override;
bool get_array_attribute(ShaderGlobals* sg, bool derivatives,
ustringhash object, TypeDesc type,
ustringhash name, int index, void* val) override;
bool get_attribute(ShaderGlobals* sg, bool derivatives, ustringhash object,
TypeDesc type, ustringhash name, void* val) override;
bool get_userdata(bool derivatives, ustringhash name, TypeDesc type,
ShaderGlobals* sg, void* val) override;
void name_transform(const char* name, const Transformation& xform);
@@ -109,7 +109,7 @@ private:
float m_screen_window[4];
int backgroundShaderID = -1;
int backgroundResolution = 0;
int backgroundResolution = 1024;
int aa = 1;
int max_bounces = 1000000;
int rr_depth = 5;
@@ -121,7 +121,7 @@ private:
bool m_had_error = false;
// Named transforms
typedef std::map<ustring, std::shared_ptr<Transformation>> TransformMap;
typedef std::map<ustringhash, std::shared_ptr<Transformation>> TransformMap;
TransformMap m_named_xforms;
// Attribute and userdata retrieval -- for fast dispatch, use a hash
@@ -130,43 +130,50 @@ private:
// renderer, we would encourage benchmarking various methods and
// alternate data structures.
typedef bool (SimpleRaytracer::*AttrGetter)(ShaderGlobals* sg, bool derivs,
ustring object, TypeDesc type,
ustring name, void* val);
typedef std::unordered_map<ustring, AttrGetter> AttrGetterMap;
ustringhash object,
TypeDesc type, ustringhash name,
void* val);
typedef std::unordered_map<ustringhash, AttrGetter> AttrGetterMap;
AttrGetterMap m_attr_getters;
// Attribute getters
bool get_osl_version(ShaderGlobals* sg, bool derivs, ustring object,
TypeDesc type, ustring name, void* val);
bool get_camera_resolution(ShaderGlobals* sg, bool derivs, ustring object,
TypeDesc type, ustring name, void* val);
bool get_camera_projection(ShaderGlobals* sg, bool derivs, ustring object,
TypeDesc type, ustring name, void* val);
bool get_camera_fov(ShaderGlobals* sg, bool derivs, ustring object,
TypeDesc type, ustring name, void* val);
bool get_camera_pixelaspect(ShaderGlobals* sg, bool derivs, ustring object,
TypeDesc type, ustring name, void* val);
bool get_camera_clip(ShaderGlobals* sg, bool derivs, ustring object,
TypeDesc type, ustring name, void* val);
bool get_camera_clip_near(ShaderGlobals* sg, bool derivs, ustring object,
TypeDesc type, ustring name, void* val);
bool get_camera_clip_far(ShaderGlobals* sg, bool derivs, ustring object,
TypeDesc type, ustring name, void* val);
bool get_camera_shutter(ShaderGlobals* sg, bool derivs, ustring object,
TypeDesc type, ustring name, void* val);
bool get_camera_shutter_open(ShaderGlobals* sg, bool derivs, ustring object,
TypeDesc type, ustring name, void* val);
bool get_osl_version(ShaderGlobals* sg, bool derivs, ustringhash object,
TypeDesc type, ustringhash name, void* val);
bool get_camera_resolution(ShaderGlobals* sg, bool derivs,
ustringhash object, TypeDesc type,
ustringhash name, void* val);
bool get_camera_projection(ShaderGlobals* sg, bool derivs,
ustringhash object, TypeDesc type,
ustringhash name, void* val);
bool get_camera_fov(ShaderGlobals* sg, bool derivs, ustringhash object,
TypeDesc type, ustringhash name, void* val);
bool get_camera_pixelaspect(ShaderGlobals* sg, bool derivs,
ustringhash object, TypeDesc type,
ustringhash name, void* val);
bool get_camera_clip(ShaderGlobals* sg, bool derivs, ustringhash object,
TypeDesc type, ustringhash name, void* val);
bool get_camera_clip_near(ShaderGlobals* sg, bool derivs,
ustringhash object, TypeDesc type,
ustringhash name, void* val);
bool get_camera_clip_far(ShaderGlobals* sg, bool derivs, ustringhash object,
TypeDesc type, ustringhash name, void* val);
bool get_camera_shutter(ShaderGlobals* sg, bool derivs, ustringhash object,
TypeDesc type, ustringhash name, void* val);
bool get_camera_shutter_open(ShaderGlobals* sg, bool derivs,
ustringhash object, TypeDesc type,
ustringhash name, void* val);
bool get_camera_shutter_close(ShaderGlobals* sg, bool derivs,
ustring object, TypeDesc type, ustring name,
void* val);
ustringhash object, TypeDesc type,
ustringhash name, void* val);
bool get_camera_screen_window(ShaderGlobals* sg, bool derivs,
ustring object, TypeDesc type, ustring name,
void* val);
ustringhash object, TypeDesc type,
ustringhash name, void* val);
// 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);
Vec3 eval_background(const Dual2<Vec3>& dir, ShadingContext* ctx,
int bounce = -1);
Color3 subpixel_radiance(float x, float y, Sampler& sampler,
ShadingContext* ctx);
Color3 antialias_pixel(int x, int y, ShadingContext* ctx);
+20 -4
View File
@@ -25,7 +25,7 @@
#include "shading.h"
#include "simpleraytracer.h"
#ifdef OSL_USE_OPTIX
#if OSL_USE_OPTIX
# include "optixraytracer.h"
#endif
@@ -42,6 +42,7 @@ static bool saveptx = false;
static bool warmup = false;
static bool profile = false;
static bool O0 = false, O1 = false, O2 = false;
static int llvm_opt = 1; // LLVM optimization level
static bool debugnan = false;
static bool debug_uninit = false;
static bool userdata_isconnected = false;
@@ -76,8 +77,16 @@ set_shadingsys_options()
if (const char* opt_env = getenv("TESTSHADE_OPT")) // overrides opt
opt = atoi(opt_env);
shadingsys->attribute("optimize", opt);
// The cost of more optimization passes usually pays for itself by
// reducing the number of instructions JIT ultimately has to lower to
// the target ISA.
if (const char* llvm_opt_env = getenv(
"TESTSHADE_LLVM_OPT")) // overrides llvm_opt
llvm_opt = atoi(llvm_opt_env);
shadingsys->attribute("llvm_optimize", llvm_opt);
shadingsys->attribute("profile", int(profile));
shadingsys->attribute("lockgeom", 1);
shadingsys->attribute("debug_nan", debugnan);
shadingsys->attribute("debug_uninit", debug_uninit);
shadingsys->attribute("userdata_isconnected", userdata_isconnected);
@@ -91,6 +100,11 @@ 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;
}
@@ -149,6 +163,8 @@ getargs(int argc, const char* argv[])
.help("Do a little runtime shader optimization");
ap.arg("-O2", &O2)
.help("Do lots of runtime shader optimization");
ap.arg("--llvm_opt %d:LEVEL", &llvm_opt)
.help("LLVM JIT optimization level");
ap.arg("--debugnan", &debugnan)
.help("Turn on 'debugnan' mode");
ap.arg("--path SEARCHPATH", &shaderpath)
@@ -218,7 +234,7 @@ main(int argc, const char* argv[])
aa = aaoverride;
SimpleRaytracer* rend = nullptr;
#ifdef OSL_USE_OPTIX
#if OSL_USE_OPTIX
if (use_optix)
rend = new OptixRaytracer;
else
@@ -251,7 +267,7 @@ main(int argc, const char* argv[])
// Setup common attributes
set_shadingsys_options();
#ifdef OSL_USE_OPTIX
#if OSL_USE_OPTIX
if (use_optix)
reinterpret_cast<OptixRaytracer*>(rend)->synch_attributes();
#endif
+2 -2
View File
@@ -7,12 +7,12 @@ set ( testshade_srcs
testshade.cpp
simplerend.cpp )
if (BUILD_BATCHED)
if (OSL_BUILD_BATCHED)
list(APPEND testshade_srcs
batched_simplerend.cpp)
endif()
if (USE_OPTIX)
if (OSL_USE_OPTIX)
list (APPEND testshade_srcs optixgridrender.cpp)
set ( testshade_cuda_srcs
cuda/optix_grid_renderer.cu

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