Compare commits

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

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

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

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

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

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

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

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

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

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

* Fixed LLVM representation to accommodate ShaderGlobals::shadingStateUniform.

* Added missing Copyright Contributors license to shading_state_uniform.h

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

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

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

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

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

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

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

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

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

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

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

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

* Exclude Imath duplicate headers from Sonar analysis.

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

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

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

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

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

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

IMPORTANT TO-DO / CAVEATS:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    project (OSL VERSION 1.13.0.0 ...)

this patch decouples it

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

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

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

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

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

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

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

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

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

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

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

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

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

!!!

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Also slightly bump up the error tolerance for this test.

Also add one alternative that seems to frequently pop up.

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

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

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

Yay for static analysis!

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Add test cases for dielectric, conductor and generalized schlick closures

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

* Implement refraction case in microfacet closures

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

* Update reference images

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

* Relax diff threshold on render tests

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

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

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

* Add support for sheen in the layer closure

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

  * Add stub parameters and IDs for all MaterialX closures

  * Register all MaterialX closure types

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

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

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

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

Update reference images for new sampler

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

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

Some details worth noting:

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

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

* A lot of clunky OptiX-only code disappears.

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

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

* Remove register_string entirely from RendererServices

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

* Remove more register_string remnants

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

* comment typo

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

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

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

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

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

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

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

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

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

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

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

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

So remove this confusing sentence.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
2022-06-20 11:09:01 -07:00
358 changed files with 20028 additions and 15197 deletions
+37
View File
@@ -6,3 +6,40 @@ bdb473cbdb119f3d9060d48f75f965cbd45f6d7a
# More clang-format: liboslquery, oslinfo, oslc, osl.imageio, osltoy (#1220)
bf366d7a90c46599b82071dac6dbef7c5e3ca157
# Turn on clang-format for cpp files in testsuite (#1269)
00c895fc642eb89685797c292048bdff15d675e7
5e848fb761261521a3ee7cd8a4f6814f32fe4a47
# CI: Change our clang-format standard to clang11 (#1372)
91d22ebe2f65d4ed0599e421172a15d99fe0e1b4
# More clang-format (this time, testrender and liboslnoise) (#1511)
08706b7cbac781b6a9389780428016be985d9d89
# clang-format #1509
b4026fd1695c08532557b3ba1c2142323087ccf9
1f73b075c99861afa42fac44567b37f797bc72f2
7f2e83794e6fa63d5180653cffb77be2cc38b32b
28399fefc890442b5ac020e7a90cee0d5bf9f03c
e56851056d33233b0bb8324faac251907099961a
1c57fc61d8ab7c3f309be4335e4c71c26399edd4
46d451ce74d00e904874df476ebeca19bb119ea9
c1045f2c2845a98e661c7181932a031eb3c76063
# More clang-format (#1512)
8c6ffdd911b9eb7db4adf41ab88891360452d7c5
# style: more clang-format (#1515)
102430c83554fe7e328cd8c3317db00507bcfaba
# Revert some formatting (#1518)
21eac9d9215d071b0a7b9ce2c32f189ed0c62c4a
# Another round of clang-format (#1540)
38015b6be28643254aea530154b7860136cf5e15
89d5db2b5c5fda79184d8245d903e580fc6a4e9c
# clang-format: the very last piece of the puzzle (#1555)
4ee62cd2ef05543f818f4d95a19efc1d684a7381
5be7c6bd4e7bd2e560cb6be8c06f11985384a87a
+130
View File
@@ -0,0 +1,130 @@
# Copyright 2008-present Contributors to the Open Shading Language project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
name: Analysis
on:
schedule:
# Run nightly while we're still working our way through the warnings
- cron: "0 8 * * *"
# Run unconditionally once weekly
# - cron: "0 0 * * 0"
push:
branches:
- main
- '*analysis*'
# Allow manual kicking off of the workflow from github.com
workflow_dispatch:
permissions: read-all
# Allow subsequent pushes to the same PR or REF to cancel any previous jobs.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
aswf:
name: "SonarCloud Analysis"
if: |
github.repository == 'AcademySoftwareFoundation/OpenShadingLanguage'
strategy:
fail-fast: false
matrix:
include:
- desc: sonar gcc9/C++14 llvm13 py3.9 boost1.76 exr3.1 oiio2.3 avx2
nametag: static-analysis-sonar
os: ubuntu-latest
vfxyear: 2022
vfxsuffix: -clang13
cxx_std: 14
openimageio_ver: master
python_ver: 3.9
pybind11_ver: v2.9.0
simd: avx2,f16c
batched: b8_AVX2,b16_AVX512
coverage: 1
# skip_tests: 1
sonar: 1
setenvs: export SONAR_SCANNER_VERSION=4.7.0.2747
SONAR_SERVER_URL="https://sonarcloud.io"
BUILD_WRAPPER_OUT_DIR=bw_output
OSL_CMAKE_BUILD_WRAPPER="build-wrapper-linux-x86-64 --out-dir bw_output"
CMAKE_BUILD_TYPE=Debug
CMAKE_UNITY_BUILD=OFF
CODECOV=1
TESTRENDER_AA=1
OSL_TESTSUITE_SKIP_DIFF=1
CTEST_TEST_TIMEOUT=1200
OSL_CMAKE_FLAGS="-DOSL_TEST_BIG_TIMEOUT=1200 -DUSE_QT=0"
CTEST_EXCLUSIONS="broken|noise-reg.regress|noise-gabor-reg.regress"
runs-on: ${{ matrix.os }}
container:
image: aswf/ci-osl:${{matrix.vfxyear}}${{matrix.vfxsuffix}}
env:
CXX: ${{matrix.cxx_compiler}}
CC: ${{matrix.cc_compiler}}
CMAKE_CXX_STANDARD: ${{matrix.cxx_std}}
FMT_VERSION: ${{matrix.fmt_ver}}
OPENEXR_VERSION: ${{matrix.openexr_ver}}
OPENIMAGEIO_VERSION: ${{matrix.openimageio_ver}}
PYBIND11_VERSION: ${{matrix.pybind11_ver}}
PYTHON_VERSION: ${{matrix.python_ver}}
USE_BATCHED: ${{matrix.batched}}
USE_SIMD: ${{matrix.simd}}
# DEBUG_CI: 1
steps:
# We would like to use harden-runner, but it flags too many false
# positives, every time we download a dependency. We should use it only
# on CI runs where we are producing artifacts that users might rely on.
# - name: Harden Runner
# uses: step-security/harden-runner@248ae51c2e8cc9622ecf50685c8bf7150c6e8813 # v1.4.3
# with:
# egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
with:
fetch-depth: '0'
- name: Prepare ccache timestamp
id: ccache_cache_keys
run: echo "::set-output name=date::`date -u +'%Y-%m-%dT%H:%M:%SZ'`"
- name: ccache
id: ccache
uses: actions/cache@c3f1317a9e7b1ef106c153ac8c0f00fed3ddbc0d # v3.0.4
with:
path: /tmp/ccache
key: ${{github.job}}-${{matrix.nametag}}-${{steps.ccache_cache_keys.outputs.date}}
restore-keys: ${{github.job}}-
- name: Build setup
run: |
${{matrix.setenvs}}
src/build-scripts/ci-startup.bash
- name: Remove existing OIIO
if: matrix.openimageio_ver != ''
run: |
sudo rm -rf /usr/local/include/OpenImageIO
sudo rm -rf /usr/local/lib*/cmake/OpenImageIO
sudo rm -rf /usr/local/lib*/libOpenImageIO*
sudo rm -rf /usr/local/lib*/python3.9/site-packages/OpenImageIO*
- name: Dependencies
run: |
${{matrix.depcmds}}
src/build-scripts/gh-installdeps.bash
- name: Build
run: src/build-scripts/ci-build.bash
- name: Testsuite
if: matrix.skip_tests != '1'
run: src/build-scripts/ci-test.bash
- name: Code coverage
if: matrix.coverage == '1'
run: src/build-scripts/ci-coverage.bash
- name: Sonar-scanner
if: matrix.sonar == 1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
sonar-scanner -X --define sonar.host.url="${{ env.SONAR_SERVER_URL }}" --define sonar.cfamily.build-wrapper-output="build/bw_output" --define sonar.cfamily.gcov.reportsPath="_coverage"
+152 -85
View File
@@ -20,8 +20,12 @@ on:
- '**.rst'
- '**.tex'
schedule:
# Full nightly build
# Full nightly build, for the main project repo (not for forks)
- cron: "0 6 * * *"
if: github.repository == 'AcademySoftwareFoundation/OpenShadingLanguage'
permissions: read-all
jobs:
@@ -38,12 +42,12 @@ jobs:
vfxyear: 2019
vfxsuffix: -clang9
cxx_std: 14
openimageio_ver: v2.2.17.0
openimageio_ver: v2.3.17.0
python_ver: 2.7
pybind11_ver: v2.4.2
- desc: clang9/C++14 llvm9 oiio-release boost1.66 avx2 exr2.3 py2.7
nametag: linux-clang9-llvm9
os: ubuntu-18.04
os: ubuntu-20.04
vfxyear: 2019
vfxsuffix: -clang9
cc_compiler: clang
@@ -64,13 +68,14 @@ 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
vfxyear: 2020
cxx_std: 14
openimageio_ver: v2.2.17.0
openimageio_ver: v2.3.17.0
python_ver: 3.7
pybind11_ver: v2.5.0
simd: sse4.2
@@ -81,7 +86,7 @@ jobs:
vfxyear: 2021
vfxsuffix: -clang11
cxx_std: 17
openimageio_ver: dev-2.2
openimageio_ver: dev-2.3
python_ver: 3.7
pybind11_ver: v2.7.0
simd: avx2,f16c
@@ -109,10 +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
@@ -125,10 +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
@@ -145,12 +152,72 @@ jobs:
vfxyear: 2019
vfxsuffix: -clang9
cxx_std: 14
openimageio_ver: v2.2.17.0
openimageio_ver: v2.3.17.0
python_ver: 2.7
pybind11_ver: v2.6.2
simd: 0
setenvs: export PUGIXML_VERSION=v1.8
# Address and leak sanitizers
- desc: sanitizers
nametag: sanitizer
os: ubuntu-latest
vfxyear: 2022
vfxsuffix: -clang13
cc_compiler: clang
cxx_compiler: clang++
cxx_std: 17
openimageio_ver: master
python_ver: 3.9
pybind11_ver: v2.9.0
simd: avx2,f16c
batched: b8_AVX2
setenvs: export OSL_CMAKE_FLAGS="-DSANITIZE=address -DOSL_TEST_BIG_TIMEOUT=1200"
CMAKE_BUILD_TYPE=Debug
CTEST_TEST_TIMEOUT=1200
CTEST_EXCLUSIONS="broken|noise-reg.regress|noise-gabor-reg.regress|example-.*deformer|spline-reg.regress.batched|osl-imageio"
OSL_OPTIONS=llvm_debugging_symbols=1
TESTRENDER_AA=1
OSL_TESTSUITE_SKIP_DIFF=1
# Sanitizer notes:
# - There are a handful of tests we disable entirely with
# CTEST_EXCLUSIONS because they are irrelevant or just cannot be
# made to be clean (and that's ok).
# - Tests with sanitizers run slow, so we increase timeouts, and
# also set AA to 1 for render tests to speed them up.
# OSL_TESTSUITE_SKIP_DIFF prevents making the AA=1 image result
# fail, but that's ok because every other CI test is checking
# the results; here we have no reason to believe results will
# differ from other tests, we just need to run with sanitizers
# turned on.
# - In testing.cmake, we rig texture tests to disable the leak
# sanitizer, because we can't eliminate some completely benign
# leaks from the texture system, and because they are called
# from JITed code, we don't get a clean stack trace of things
# that happen in OIIO and therefore we just can't enumerate the
# allowed exceptions. So we trust that OIIO itself tests the
# texture system adequately and is able to ignore the benign
# "leaks."
# Test formatting. This test entry doesn't do a full build, it
# just runs clang-format on everything, and passes if nothing is
# misformatted. Upon failure, the build artifact will be the full
# source code with the formatting fixed (diffs will also appear in
# the console output).
- desc: "clang-format"
nametag: clang-format
os: ubuntu-latest
vfxyear: 2022
vfxsuffix: -clang14
cxx_std: 17
openimageio_ver: release
python_ver: 3.9
simd: avx2,f16c
batched: b8_AVX2
skip_tests: 1
setenvs: export BUILDTARGET=clang-format
OPENIMAGEIO_CMAKE_FLAGS=-DUSE_PYTHON=0
runs-on: ${{matrix.os}}
container:
image: aswftesting/ci-osl:${{matrix.vfxyear}}${{matrix.vfxsuffix}}
@@ -166,13 +233,20 @@ jobs:
USE_BATCHED: ${{matrix.batched}}
USE_SIMD: ${{matrix.simd}}
steps:
- uses: actions/checkout@v2
# We would like to use harden-runner, but it flags too many false
# positives, every time we download a dependency. We should use it only
# on CI runs where we are producing artifacts that users might rely on.
# - name: Harden Runner
# uses: step-security/harden-runner@248ae51c2e8cc9622ecf50685c8bf7150c6e8813 # v1.4.3
# with:
# egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Prepare ccache timestamp
id: ccache_cache_keys
run: echo "::set-output name=date::`date -u +'%Y-%m-%dT%H:%M:%SZ'`"
- name: ccache
id: ccache
uses: actions/cache@v2
uses: actions/cache@c3f1317a9e7b1ef106c153ac8c0f00fed3ddbc0d # v3.0.4
with:
path: /tmp/ccache
key: ${{github.job}}-${{matrix.nametag}}-${{steps.ccache_cache_keys.outputs.date}}
@@ -198,7 +272,7 @@ jobs:
- name: Testsuite
if: matrix.skip_tests != '1'
run: src/build-scripts/ci-test.bash
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
if: failure()
with:
name: osl-${{github.job}}-${{matrix.nametag}}
@@ -216,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
@@ -230,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
@@ -242,32 +316,32 @@ jobs:
setenvs: export LLVM_VERSION=10.0.0
OPENIMAGEIO_CMAKE_FLAGS="-DBUILD_FMT_VERSION=7.0.1"
PUGIXML_VERSION=v1.10
- desc: latest releases gcc11/C++17 llvm13 boost1.71 exr3.1 py3.8 avx2 batch-b16avx512
- desc: latest releases gcc11/C++17 llvm13 boost1.71 exr3.1 py3.9 avx2 batch-b16avx512
nametag: linux-latest-releases
os: ubuntu-20.04
os: ubuntu-22.04
cxx_compiler: g++-11
cxx_std: 17
fmt_ver: 8.1.1
openexr_ver: v3.1.5
fmt_ver: 9.1.0
openexr_ver: v3.1.7
openimageio_ver: master
pybind11_ver: v2.9.2
python_ver: 3.8
pybind11_ver: v2.10.0
python_ver: "3.10"
simd: avx2,f16c
batched: b8_AVX2,b8_AVX512,b16_AVX512
setenvs: export LLVM_VERSION=13.0.0
LLVM_DISTRO_NAME=ubuntu-20.04
OPENCOLORIO_VERSION=v2.1.2
PUGIXML_VERSION=v1.11.4
- desc: bleeding edge gcc11/C++17 llvm14 oiio/ocio/exr/pybind-master boost1.71 py3.9 avx2 batch-b16avx512
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-20.04
cxx_compiler: g++-11
os: ubuntu-22.04
cxx_compiler: g++-12
cxx_std: 17
fmt_ver: master
openexr_ver: main
openimageio_ver: master
pybind11_ver: master
python_ver: 3.9
python_ver: "3.10"
simd: avx2,f16c
batched: b8_AVX2,b8_AVX512,b16_AVX512
setenvs: export LLVM_VERSION=14.0.0
@@ -275,13 +349,13 @@ jobs:
OPENCOLORIO_VERSION=main
PUGIXML_VERSION=master
- desc: clang14/C++17 llvm14 boost1.71 exr3.1 py3.8 avx2 batch-b16avx512
nametag: linux-latest-releases
nametag: linux-latest-releases-clang
os: ubuntu-20.04
cxx_compiler: clang++
cc_compiler: clang
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
@@ -305,13 +379,20 @@ jobs:
USE_BATCHED: ${{matrix.batched}}
USE_SIMD: ${{matrix.simd}}
steps:
- uses: actions/checkout@v2
# We would like to use harden-runner, but it flags too many false
# positives, every time we download a dependency. We should use it only
# on CI runs where we are producing artifacts that users might rely on.
# - name: Harden Runner
# uses: step-security/harden-runner@248ae51c2e8cc9622ecf50685c8bf7150c6e8813 # v1.4.3
# with:
# egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Prepare ccache timestamp
id: ccache_cache_keys
run: echo "::set-output name=date::`date -u +'%Y-%m-%dT%H:%M:%SZ'`"
- name: ccache
id: ccache
uses: actions/cache@v2
uses: actions/cache@c3f1317a9e7b1ef106c153ac8c0f00fed3ddbc0d # v3.0.4
with:
path: /tmp/ccache
key: ${{github.job}}-${{matrix.nametag}}-${{steps.ccache_cache_keys.outputs.date}}
@@ -329,7 +410,7 @@ jobs:
- name: Testsuite
if: matrix.skip_tests != '1'
run: src/build-scripts/ci-test.bash
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
if: failure()
with:
name: osl-${{github.job}}-${{matrix.nametag}}
@@ -342,88 +423,74 @@ jobs:
macos:
name: "${{matrix.os}} appleclang${{matrix.aclang}}/C++${{matrix.cxx_std}} py${{matrix.python_ver}} ${{matrix.desc}}"
strategy:
fail-fast: false
matrix:
include:
- desc: llvm11
os: macos-10.15
nametag: macos10-py39
cxx_std: 14
python_ver: 3.9
aclang: 12
- desc: llvm11
- desc: MacOS-11
os: macos-11
nametag: macos11-py39
cc_compiler: /usr/local/opt/llvm@14/bin/clang
cxx_compiler: /usr/local/opt/llvm@14/bin/clang++
cxx_std: 17
python_ver: 3.9
python_ver: "3.10"
aclang: 13
setenvs: export LLVMBREWVER="@14" DO_BREW_UPDATE=1
OPENIMAGEIO_VERSION=release
QT_BREW_VERSION="@5"
- desc: MacOS-12
os: macos-12
nametag: macos11-p310
cc_compiler: /usr/local/opt/llvm@15/bin/clang
cxx_compiler: /usr/local/opt/llvm@15/bin/clang++
cxx_std: 17
python_ver: "3.10"
aclang: 13
setenvs: export LLVMBREWVER="@15" DO_BREW_UPDATE=1
OPENIMAGEIO_VERSION=master
runs-on: ${{matrix.os}}
env:
CC: clang
CXX: clang++
CXX: ${{matrix.cxx_compiler}}
CC: ${{matrix.cc_compiler}}
CMAKE_CXX_STANDARD: ${{matrix.cxx_std}}
PYTHON_VERSION: ${{matrix.python_ver}}
OPENIMAGEIO_VERSION: ${{matrix.openimageio_ver}}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
- name: Prepare ccache timestamp
id: ccache_cache_keys
run: echo "::set-output name=date::`date -u +'%Y-%m-%dT%H:%M:%SZ'`"
- name: ccache
id: ccache
uses: actions/cache@v2
uses: actions/cache@c3f1317a9e7b1ef106c153ac8c0f00fed3ddbc0d # v3.0.4
with:
path: /Users/runner/.ccache
key: ${{github.job}}-${{matrix.os}}-${{steps.ccache_cache_keys.outputs.date}}
restore-keys: ${{github.job}}-${{matrix.os}}-
key: ${{github.job}}-${{matrix.nametag}}-${{steps.ccache_cache_keys.outputs.date}}
restore-keys: ${{github.job}}-${{matrix.nametag}}-
- name: Build setup
run: src/build-scripts/ci-startup.bash
run: |
${{matrix.setenvs}}
src/build-scripts/ci-startup.bash
- name: Dependencies
run: |
source src/build-scripts/install_homebrew_deps.bash
# OPENIMAGEIO_CMAKE_FLAGS="-DOIIO_BUILD_TESTS=0 -DUSE_OPENGL=0"
# source src/build-scripts/build_openimageio.bash
brew install --display-times -q openimageio
PYTHONPATH=$PYTHONPATH:/usr/local/python${PYTHON_VERSION}/site-packages
if [[ "$OPENIMAGEIO_VERSION" != "" ]] ; then \
OPENIMAGEIO_CMAKE_FLAGS="-DOIIO_BUILD_TESTS=0 -DUSE_OPENGL=0" ; \
source src/build-scripts/build_openimageio.bash ; \
else \
brew install --display-times -q openimageio ; \
PYTHONPATH=$PYTHONPATH:/usr/local/python${PYTHON_VERSION}/site-packages ; \
fi
src/build-scripts/save-env.bash
- name: Build
run: |
src/build-scripts/ci-build.bash
- name: Testsuite
run: src/build-scripts/ci-test.bash
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
if: failure()
with:
name: osl-${{github.job}}
name: osl-${{github.job}}-${{matrix.nametag}}
path: |
build/*.cmake
build/CMake*
build/testsuite/*/*.*
clang-format:
# Test formatting. This test entry doesn't do a full build, it just runs
# clang-format on everything, and passes if nothing is misformatted.
# Upon failure, the build artifact will be the full source code with the
# formatting fixed (diffs will also appear in the console output).
name: "clang-format verification"
runs-on: ubuntu-18.04
container:
image: aswf/ci-osl:2021-clang11
env:
BUILDTARGET: run-clang-format
CMAKE_CXX_STANDARD: 17
PYTHON_VERSION: 3.7
steps:
- uses: actions/checkout@v2
- name: Build setup
run: |
src/build-scripts/ci-startup.bash
- name: Dependencies
run: |
src/build-scripts/gh-installdeps.bash
- name: Build
run: |
src/build-scripts/ci-build.bash
- uses: actions/upload-artifact@v2
if: failure()
with:
name: osl-${{github.job}}
path: src/*/*.{cpp,h}
+67
View File
@@ -0,0 +1,67 @@
name: Scorecards supply-chain security
on:
# Only the default branch is supported.
branch_protection_rule:
schedule:
- cron: '44 20 * * 6'
push:
branches: [ "main", "scorecard" ]
# Declare default permissions as read only.
permissions: read-all
# Allow subsequent pushes to the same PR or REF to cancel any previous jobs.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
analysis:
name: Scorecards analysis
if: |
github.repository == 'AcademySoftwareFoundation/OpenShadingLanguage'
runs-on: ubuntu-latest
permissions:
# Needed to upload the results to code-scanning dashboard.
security-events: write
# Used to receive a badge. (Upcoming feature)
id-token: write
steps:
- name: "Checkout code"
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@3e15ea8318eee9b333819ec77a36aca8d39df13e # v1.1.1
with:
results_file: results.sarif
results_format: sarif
# (Optional) Read-only PAT token. Uncomment the `repo_token` line below if:
# - you want to enable the Branch-Protection check on a *public* repository, or
# - you are installing Scorecards on a *private* repository
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
# repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}
# Publish the results for public repositories to enable scorecard badges. For more details, see
# https://github.com/ossf/scorecard-action#publishing-results.
# For private repositories, `publish_results` will automatically be set to `false`, regardless
# of the value entered here.
publish_results: true
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
with:
name: SARIF file
path: results.sarif
retention-days: 5
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@5f532563584d71fdef14ee64d17bafb34f751ce5 # v1.0.26
with:
sarif_file: results.sarif
+1
View File
@@ -9,4 +9,5 @@ build
*.pyc
*.log
.vscode
.envrc
+5 -4
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) )
@@ -50,4 +51,4 @@ This is a checklist for TSC's to review as part of the intake process. The TSC s
- [X] License scan completed and no issues found
- Minor issues were found but already fixed in PR https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1145
- [X] Code repository imported to ASWF GitHub organization
- [ ] Developer Certificate of Origin past commit signoff done and DCO Probot enabled.
- [X] Developer Certificate of Origin post commit signoff done and DCO Probot enabled.
+180 -8
View File
@@ -1,8 +1,151 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the Open Shading Language Project. -->
Release 1.12 -- ?? (compared to 1.11)
Release 1.13 -- ?? 2023 ?? (compared to 1.12)
--------------------------------------------------
Dependency and standards requirements changes:
* OptiX 6.0 support has been removed. For GPU rendering with OptiX, a minimum
of OptiX 7.0 is required.
* The minimum version OpenImageIO has been raised from 2.2 to 2.3. #1591
(1.13.0.3)
OSL Language and oslc compiler:
* Bug fix: shader params whose default values involve "init ops" could be
incorrectly initialized if their values came from instance parameters set to
zero. #1578 (1.13.0.2)
OSL Standard library:
API changes, new options, new ShadingSystem features (for renderer writers):
* A new `shadingStateUniform` pointer field was added to ShaderGlobals for
planned future expansion and improved GPU support. #1585 (1.13.1.0)
SIMD batched shading mode:
* Fix some array overruns (asymptomatic, but still potentially buggy) in
common_ancestor_between. #1577 (1.13.0.2)
* 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
of OptiX 7.0 is required.
* Big overhaul/simplification of how strings are represented on the GPU: the
extra level of indirection to global variables is removed, and strings are
simply represented in ordinary variables as the hash of their characters.
#1531 (1.13.0.0) #1553 (1.13.0.1)
* Better PTX cache hit rate by eliminating several sources of not being
strictly deterministic in the PTX text we were generating. #1566 #1570
(1.13.0.1)
* 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:
Bug fixes and other improvements (internals):
* Fix memory leak in oslc ASTvariable_declaration. #1576 (1.13.0.2)
* Fix memory leaks in LPE code in error conditions. #1593 #1594 (1.13.0.3)
Internals/developer concerns:
* platform.h:
- New `OSL_ALLOCA` macro to allocate on the stack. #1589 (1.13.0.3)
- 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) 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:
* **Batch shading**: A fully operational "batch shading" support when using
CPUs supporting the Intel AVX2 or AVX512 instruction set architectures,
allows shading 8 or 16 points at a time, accelerated by using SIMD
instructions. (Changes contributed by Intel.)
* **OptiX**: A reasonable subset of the OSL language can run on NVIDIA GPUs
for Cuda or OptiX-based renderers.
* **Standardized material closures**: Synchronize with MaterialX on a minimum
standard set of material closures. This is reflected in both the OSL spec as
well as reference implementations of those closures in testrender. #1533
#1536 #1537 #1538 #1539 #1541 #1542 #1547 #1557
Dependency and standards requirements changes:
* The minimum (and default) compilation mode is now C++14. C++17 and 20 are
also supported. #1362 #1369 (1.12.2)
@@ -33,6 +176,8 @@ OSL Standard library:
* Fix previously-broken color conversions from RGB to xyY. #1410 (1.12.3)
* Fully removed MaterialX shaders (get those from the MaterialX project).
#1450 (1.12.3)
* Fix incorrect implementation of `matrix4 * vector4` in vector4.h #1513
(1.12.5.0)
API changes, new options, new ShadingSystem features (for renderer writers):
* Custom experimental llvm optimization levels 10, 11, 12, and 13. These
@@ -58,7 +203,7 @@ API changes, new options, new ShadingSystem features (for renderer writers):
triggered for those cases that cannot be resolved by the end of the "runtime
optimization" phase. #1497 (1.12.4.6)
Continued work on experimental SIMD batched shading mode:
SIMD batched shading mode:
* Added support for masked operations to LLVMUtil. #1248 #1250 (1.12.0.0)
* Add interface to ShadingSystem for batched execution. #1272 (1.12.0.1)
* Add interface to batched RendererServices. #1276 (1.12.0.1)
@@ -83,8 +228,9 @@ Continued work on experimental SIMD batched shading mode:
* Batched isnan, isinf, isfinite. #1456 (1.12.4.2)
* Batched userdata and output placement. #1455 (1.12.4.2)
* Batched pointcloud functions. #1464 (1.12.4.4)
* Batched closures (#1500)
Continued work on experimental OptiX rendering:
OptiX rendering:
* Explicitly set the OptiX pipeline stack size. #1254 (1.12.0.0)
* CI tests now at least compile and build with USE_OPTIX=1 (though not yet
run the tests). #1281 (1.12.0.1)
@@ -101,10 +247,12 @@ Continued work on experimental OptiX rendering:
* Fix race conditions when compiling for OptiX 7. #1411 (1.12.3)
* osl_get_attribute() uses device strings when compiling for OptiX.
#1435 (1.12.3)
* Fix issue with OptiX + clang 14 with duplicate symbols. #1561 (1.12.6.0)
Performance improvements:
* Less mutex locking around use and retrieval of ColorSystem related to
doing color transforms. #1405 (1.12.3)
* Constant folding of `startswith()`. #1507 (1.12.5.0)
Bug fixes and other improvements (internals):
* Fix derivatives of texture calls when only derivatives of the "alpha"
@@ -142,8 +290,14 @@ Bug fixes and other improvements (internals):
* Print all 4 levels of version numbers in help messages. #1477 (1.12.4.4)
* Fix GPU code generation crash. #1479 (1.12.4.4)
* Work to transition internals to use modern std::format notation for
formatted output. #1487 #1490 (1.12.4.6)
* Fix testrender memory error on teardown. #1499 (1.12.4.6)
formatted output. #1487 #1490 (1.12.4.6) #1504 #1506 (1.12.5.0)
* testrender improvements:
* Fix testrender memory error on teardown. #1499 (1.12.4.6)
* Modernize the sampler in testrender, improving quality and performance.
#1534 (1.12.6.0)
* Switch to cone tracing for derivatives. #1543 (1.12.6.0)
* Fix error that prevented correct typecheck of ternary operator. #1552
(1.12.6.0)
Internals/developer concerns:
* Use the `final` keyword in certain internal classes where applicable.
@@ -167,6 +321,12 @@ Internals/developer concerns:
to be used in OSL 1.12. #1494 (1.12.5.0)
* Work on gradually converting printf-style formatted strings to fmt /
std::format style. #1493 (1.12.5.0)
* LLVM_Util: allow naming of llvm symbols to help with IR debugging. #1530
(1.12.6.0)
* clang-format the code base. #1508 #1509 #1511 #1512 #1515 #1518 #1540
(1.12.5.0) #1555 #1562 #1568 (1.12.6.0)
* A round of spell-checking all the comments in the code base. #1550
(1.12.5.0)
Build & test system improvements:
* CMake build system and scripts:
@@ -208,12 +368,14 @@ Build & test system improvements:
(1.12.4.4)
* Dependency version support:
- Build properly against Cuda 11 and OptiX 7.1. #1232 (1.12.0.1)
and up to OptiX 7.4 #1559 (1.12.6.0)
- PugiXML build fixes on some systems. #1262 (1.12.0.1/1.11.8)
- Cuda/OptiX back end: Add `__CUDADEVRT_INTERNAL__` define to bitcode
generation, needed to avoid duplicate cudaMalloc symbols with CUDA9+
#1271 (1.12.0.1)
- Build against LLVM 11 #1274 (1.12.0.1), LLVM 12 #1351 (1.12.1.0)
#1412 (1.12.3), LLVM 13 #1420 (1.12.3), LLVM 14 #1492 (1.12.4.6)
LLVM 15 #1592 (1.12.6.2)
- Fix build break against recent OIIO master change where m_mutex field
was removed from ImageInput. #1281 (1.12.0.1/1.11.9)
- Work to ensure that OIIO will build correctly against the upcoming
@@ -232,6 +394,8 @@ Build & test system improvements:
compilers. #1459 #1473 #1475. (1.12.4.4)
- Fixes for recent OIIO TextureSystem changes that hide Imath types.
#1476 (1.12.4.4)
- Changes to work correctly with OpenImageIO 2.4 and its master being
the start of 2.5. #1569 (1.12.6.0)
* Testing and Continuous integration (CI) systems:
- Eliminate the old Travis CI and Appveyor. #1334 #1338 (1.12.1)
- Use ccache + GitHub 'cache' action to greatly speed up CI runs. #1335
@@ -240,14 +404,15 @@ Build & test system improvements:
scripts for CentOS and Ubuntu ito a single script. #1338 (1.12.1)
- CI tests clang11, also batched shading with clang. #1379 (1.12.2)
- CI speeds up OIIO builds by not building its tests. #1380 (1.12.2)
- CI tests gcc11. #1381 (1.12.2)
- CI tests gcc11 #1381 (1.12.2) and gcc12 #1565 (1.12.6)
- Deal with OpenColorIO changing its master branch to "main". #1429
(1.12.3)
- Fix tests for texture3d now that OIIO has dropped support for Field3D.
#1437 (1.12.3)
- Test against LLVM13/clang13 for the VFX Platform 2022 tests. #1434
(1.12.3)
- Test against MacOS-11. #1434 (1.12.3)
- CI test against MacOS-11 #1434 (1.12.3) and MacOS-12 #1554 (1.12.6)
#1522 (1.12.5)
- Add testsuite coverage of environment(). #1438 (1.12.3)
- Use a project-specific environment variable `OSL_CI` instead of the more
generic `CI` to avoid clashes with other systems. #1446 (1.12.3)
@@ -262,6 +427,10 @@ Build & test system improvements:
#1501 (1.12.5.0)
- Overhaul of GHA ci.yml to use strategy matrix. #1474 (1.12.4.4)
- Test against clang 14 and fix new warnings. #1498 (1.12.5.0)
- Test against clang 15 and fix new warnings. #1586 (1.12.6.2)
- A scorecards workflow guards against a variety of security issues of
the CI system itself. #1529 (1.12.6.0)
- Enable SonarCloud static analysis. #1551 #1556 #1563 (1.12.6.0)
* Platform support:
- Various Windows compile fixes. #1263 #1285 (1.12.0.1)
- Windows+Cuda build fixes. #1292 (1.12.0.1)
@@ -281,6 +450,9 @@ Documentation:
#1326 (1.12.1)
* Fix missing explanation of the optional "errormessage" parameter to
environment() and texture3d(). #1442 (1.12.3/1.11.17)
* A SECURITY.md file explains how to confidentially report vulnerabilities.
#1529 (1.12.6)
* Document all the new MaterialX closures. #1564
@@ -748,7 +920,7 @@ Build & test system improvements:
use clang library components for preprocessing. #1089 (1.11.3)
* Add an optional build-time `EXTRA_WARNINGS` option (default: OFF) that
enables even more picky than usual warnings. Fix many warnings that cropped
up during testing, mostly related to unused function paramters. #1106 (1.11.3)
up during testing, mostly related to unused function parameters. #1106 (1.11.3)
* The testsuite can run in parallel, with a number of threads set by the
environment variable `CTEST_PARALLEL_LEVEL`. #1119 (1.11.4)
* oslconfig.h is now generated by a cmake configure_file step, from
+18 -7
View File
@@ -3,7 +3,16 @@
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
cmake_minimum_required (VERSION 3.12)
project (OSL VERSION 1.12.5.0
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")
set (PROJ_NAME ${PROJECT_NAME}) # short name
@@ -89,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)")
@@ -98,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")
@@ -117,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
@@ -212,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 ()
+13 -9
View File
@@ -173,9 +173,16 @@ it really only applies to the particular file in which it appears.
#### Formatting
NEVER alter somebody else's code to reformat just because you found
something that violates the rules. Let the group/author/leader know, and
resist the temptation to change it yourself.
We use clang-format to enforce formatting rules for the vast majority of the
code base. It is automatically run during CI and is a CI failure if the code
does not conform. There are, however, parts of the code base that are not
clang-formatted, either because we have not yet put them under the
clang-format regime, or because individual modules were deemed to be less
clear with clang-format than with hand formatting.
For non-clang-format regions of code, NEVER alter somebody else's code to
reformat just because you found something that violates the rules. Let the
group/author/leader know, and resist the temptation to change it yourself.
Each line of text in your code should be at most 80 characters long.
Exceptions are allowed for those rare cases where letting a line be longer
@@ -217,13 +224,10 @@ Function calls should have a space between the function name and the opening
parenthesis, NO space inside the parenthesis, except for a single blank
space between each argument. For example:
x = foo (a, b); // Yes, this is always ok
x = foo(a, b); // Yes
x = foo ( a, b ); // No
x = foo (a,b); // No
x = foo(a, b); // No
x = foo(a); // Occasionally, this just looks better, when the function name is short,
// and there's just one very short argument. What can I say, I do it too.
Function declarations: function names should begin at column 0 for a full
function definition. (It's ok to violate this rule for very short inline
@@ -233,7 +237,7 @@ functions within class definitions.)
Here is a short code fragment that shows some of these rules in action:
static int
function (int a, int b)
function(int a, int b)
{
int x = a + b;
if (a == 0 || b == 0) {
@@ -244,7 +248,7 @@ Here is a short code fragment that shows some of these rules in action:
}
for (int i = 0; i < 3; ++i) {
x += a * i;
x *= foo (i); // function call
x *= foo(i); // function call
}
return x;
}
+26 -26
View File
@@ -12,16 +12,16 @@ Dependencies
OSL requires the following dependencies or tools.
NEW or CHANGED dependencies since the last major release are **bold**.
* Build system: [CMake](https://cmake.org/) 3.12 or newer (tested through 3.23)
* 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 11.2)
- Clang 3.4 or newer (tested through clang 14)
- Microsoft Visual Studio **2017 or newer**
- Intel C++ compiler icc **version 17 or newer** or LLVM-based icx compiler
**version 2022 or newer**.
* A suitable C++14 or C++17 compiler to build OSL itself, which may be any of:
- GCC 6.1 or newer (tested through gcc 12.1)
- Clang 3.4 or newer (tested through clang 16)
- Microsoft Visual Studio 2017 or newer
- Intel C++ compiler icc version 17 or newer or LLVM-based icx compiler
version 2022 or newer.
* **[OpenImageIO](http://openimageio.org) 2.2 or newer** (tested through 2.3)
* **[OpenImageIO](http://openimageio.org) 2.3 or newer** (tested through 2.4)
OSL uses OIIO both for its texture mapping functionality as well as
numerous utility classes. If you are integrating OSL into an existing
@@ -40,10 +40,15 @@ NEW or CHANGED dependencies since the last major release are **bold**.
$OpenImageIO_ROOT/lib to be in your LD_LIBRARY_PATH (or
DYLD_LIBRARY_PATH on OS X).
* **[LLVM](http://www.llvm.org) 9, 10, 11, 12, 13, or 14**, including clang
libraries.
* [LLVM](http://www.llvm.org) 9, 10, 11, 12, 13, 14, or 15, including
clang libraries. LLVM 16 doesn't work yet, we need to make changes
on the OSL side to be compatible.
* [Boost](https://www.boost.org) 1.55 or newer (tested through boost 1.78)
* (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.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
@@ -51,17 +56,17 @@ 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.
* (optional) Python: If you are building the Python bindings or running the
testsuite:
* Python >= 2.7 (tested against 2.7, 3.7, 3.8, 3.9)
* pybind11 >= 2.4.2 (Tested through 2.9)
* Python >= 2.7 (tested against 2.7, 3.7, 3.8, 3.9, 3.10)
* pybind11 >= 2.4.2 (Tested through 2.10)
* NumPy
* (optional) Qt >= 5.6 (tested through 5.15). If not found at build time,
the `osltoy` application will be disabled.
* (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.
@@ -93,19 +98,14 @@ Here are the steps to check out, build, and test the OSL distribution:
full errors, not warnings.
4. After compilation, you'll end up with a full OSL distribution in
dist/ARCH, where ARCH is the architecture you are building on, one of
"linux", "linux64", "macosx", "windows", or "windows64".
dist/
Note: The default is to make an optimized "release" build. If
instead type 'make debug' at the top level, you will end up with
a debug build (no optimization, full symbols) in "dist/ARCH.debug".
5. Add the "dist/ARCH/bin" to your $PATH, and "dist/ARCH/lib" to your
$LD_LIBRAY_PATH (or $DYLD_LIBRARY_PATH on OS X), or copy the contents
5. Add the "dist/bin" to your $PATH, and "dist/lib" to your
$LD_LIBRAY_PATH (or $DYLD_LIBRARY_PATH on MacOS), or copy the contents
of those files to appropriate directories. Public include files
(those needed when building applications that incorporate OSL)
can be found in "dist/ARCH/include", and documentation can be found
in "dist/ARCH/share/doc".
can be found in "dist/include", and documentation can be found
in "dist/share/doc".
6. After building (and setting your library path), you can run the
test suite with:
+6 -3
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},)
@@ -294,7 +297,7 @@ package_source: install
# 'make clang-format' runs clang-format on all source files (if it's installed)
clang-format: config
@ ( cd ${build_dir} ; \
${CMAKE} --build . --target run-clang-format --config ${CMAKE_BUILD_TYPE} \
${CMAKE} --build . --target clang-format --config ${CMAKE_BUILD_TYPE} \
)
@@ -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,"
+41 -21
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,13 +389,30 @@ 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,
Turning Red,
The Adam Project,
Doctor Strange in the Multiverse of Madness,
Love, Death, and Robots: In Vaulted Halls Entombed,
Jurassic World: Dominion,
Lightyear,
Thor: Love and Thunder,
The Sea Beast,
DC League of Super Pets,
Minions: Rise of Gru,
Bullet Train,
Slumberland,
Glass Onion
* **(2023 / upcoming)**
Ant-Man and the Wasp: Quantumania,
...
Building and Installation
-------------------------
@@ -427,9 +443,13 @@ certain is a legit problem in the code, and for which you can give clear
instructions for how to reproduce, should be [reported as
issues](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/issues).
If confidentiality precludes a public question or issue, you may contact the
project administrator privately at [lg@imageworks.com](lg@imageworks.com),
including for security-related issues.
If you think you've found a potential vulnerability in OSL, please
confidentially report it by emailing the project administrators at
[security@openshadinglanguage.org](security@openshadinglanguage.org).
If any other issue requires confidentiality that precludes a public question
or issue, you may contact the project administrator privately at
[lg@larrygritz.com](lg@larrygritz.com).
Contributing
@@ -453,7 +473,6 @@ Contacts, Links, and References
[OSL home page](http://openshadinglanguage.org)
[Sony Pictures Imageworks main open source page](http://opensource.imageworks.com)
@@ -466,19 +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, Syoyo Fujita,
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, 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.)
Haase, John Haddon, Niklas Harrysson, Daniel Heckenberg, Chris Hellmuth,
Adrien Herubel, Dan Horák, Thiago Ize, Matt Johnson, Ronan Keryell, Chris
Kulla, Elvic Liang, Max Liani, Adam Martinez, John Mertic, Bastien Montagne,
Steena Monteiro, Patrick Mours, Alexis Oblet, Erich Ocean, Mikko Ohtamaa, Jino
Park, Alexei Pawlow, Jay Reynolds, Declan Russell, Benoit Ruiz, Patrick
Scheibe, Alex Schworer, Jonathan Scruggs, Sergey Sharybin, Mark Sisson, Sandip
Shukla, Cliff Stein, Stephan Steinbach, Luya Tshimbalanga, Esteban Tovagliari,
Brecht Van Lommel, Alexander von Knorring, Alex Wells, Roman Zulak. (Listed
alphabetically; if we've left anybody out, it is inadvertent, please let us
know.)
We cannot possibly express sufficient gratitude to the managers at Sony
Pictures Imageworks who allowed this project to proceed, supported it
+27
View File
@@ -0,0 +1,27 @@
# Security Policy
## Supported Versions
This gives guidance about which branches are supported with patches to
security vulnerabilities.
| Version / branch | Supported |
| --------- | ---------------------------------------------------- |
| main | :white_check_mark: :construction: ALL fixes immediately, but this is a branch under development with a frequently unstable ABI and occasionally unstable API. |
| 1.12.x | :white_check_mark: All fixes that can be backported without breaking ABI compatibility. New tagged releases monthly. |
| 1.11.x | :warning: Only the most critical fixes, only if they can be easily backported. |
| <= 1.10.x | :x: No longer receiving patches of any kind. |
## Reporting a Vulnerability
If you think you've found a potential vulnerability in OSL, please report it
by emailing the project administrators at
[security@openshadinglanguage.org](security@openshadinglanguage.org). Only the
project administrators have access to these messages. Include detailed steps to
reproduce the issue, and any other information that could aid an
investigation. Our policy is to respond to vulnerability reports within 14
days.
Our policy is to address critical security vulnerabilities rapidly and post
patches as quickly as possible.
+1 -1
View File
@@ -2,7 +2,7 @@
The OSL Documentation Project is a work in progress.
The plan is to adopt the OCIO Documentation Project's methodology for maintaining and building documention of various kinds as it becomes the blueprint for the ASWF.
The plan is to adopt the OCIO Documentation Project's methodology for maintaining and building documentation of various kinds as it becomes the blueprint for the ASWF.
There is much work to be done here.
+341
View File
@@ -0,0 +1,341 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the Open Shading Language Project. -->
# Release Procedures for Open Shading Language
## Version nomenclature and release cadence
### The meaning of the version parts
Our release numbers are of the form `MAJOR.MINOR.PATCH.TWEAK`, and we follow
an almost-semantic-versioning scheme.
MAJOR changes are those that break backward-compatibility of the public APIs,
requiring existing application code to change their source code where it calls
OSL API functions in order to compile and work correctly.
MINOR changes guarantee API backward-compatibility with prior releases that
have the same major number, but can introduce ABI or link incompatibilities.
Applications using OSL need to be recompiled to move to a new minor release,
but should not need to change their source code. Minor releases are allowed
to drop support for sufficiently old compilers and dependencies.
PATCH changes guarantee both API and ABI/link backward-compatibility with
prior releases that have the same minor number. Features and new public API
calls may be added (thus deviating from strict semantic versioning), but only
if they preserve ABI/link compatibility. This means that standalone functions
or static methods may be added, but existing functions will not change their
parameters, and no new virtual methods or struct data layouts change for patch
releases (for classes in public header files). Application code can be
re-linked to a new patch release without needing to be recompiled. We also
guarantee that any compilers or dependencies supported for the first release
of a minor series will continue to be supported for all patches to that minor
series.
TWEAK changes are restricted to critical bug fixes or build breaks that do
not alter public APIs in any way.
### Cadence of releases
Major (arbitrarily incompatible) releases happen rarely, usually with multiple
years between them.
Minor (API backward-compatible) releases are scheduled annually, targeted at
late summer (SIGGRAPH time) to be in beta, and early autumn for a full
release.
Patch (API and ABI backward-compatible) releases are scheduled monthly,
usually aiming for the first day of each month.
Tweak (fully forward and backward compatible) releases are not regularly
scheduled, and only happen sporadically, when a critical fix is needed in
between scheduled patch releases.
### Things are different in "main"
The "main" branch is where ongoing development occurs without any
compatibility guarantees. We don't always know if the next year's release from
main will turn out to be major (API breaking) or minor (only ABI breaking).
Some studios or products need the most up-to-date enhancements, and thus tend
to build OSL from the "main" branch rather than using tagged releases. For
these users, we try to set version numbers and occasionally tag in main, to
send a signal about which points in main seem safe to rely on various
compatibility levels. However, the rules are slightly different than we use
for releases.
In the "main" branch:
- TWEAK changes within "main" only guarantee ABI back-compatibility, but may
have additions or non-bug-fix behavior changes (akin to patch releases
within a release branch).
- PATCH changes within "main" are allowed to break ABI or API (changes that
would require minor or major releases, if they were not in "main").
- Beware of unmarked breaks in compatibility of commits in main that are
in between developer preview tags.
---
## Branch and tag names
**Branches** are places where commits containing new development may be added
(and thus the branch markers will move over time). Branch names obey the
following conventions:
- `main` is the area for arbitrary changes intended for the next year's major
or minor release.
- `dev-1.2` are the areas for staging additions to the next month's patch
release for the designated minor version series.
- `release` is a special branch marker that is always set to the latest tag of
the currently supported, stable release family. People can count on
"release" always being the latest stable release, whatever that may be at
the time.
**Tags** indicate releases or developer previews, and once a commit is
tagged, it is permanent and will never be moved. Tag names obey the following
conventions:
- `v1.2.3.4` is a specific public stable release, corresponding to official
major, minor, public, or tweak releases.
- `v1.2.3.4-alpha`, `v1.2.3.4-beta`, or `v1.2.3.4-RC1` are pre-releases for an
upcoming public stable release, at the alpha, beta, or release candidate
stages, respectively.
- `v1.2.3.4-dev` is a "developer preview" within "main." It is not an official
supported release, and while the numbering may indicate compatibility versus
other recent developer previews, they should not be assumed to be compatible
with any prior official stable releases.
*Very* occasionally, other branch or tag names (with custom suffixes or
different naming schemes) may be used for special purposes by particular
developers or users, but should not be considered reliable or permanent, and
in general should be ignored by anyone who didn't make the tag or branch.
---
## Release Procedures
### Soft freeze for monthly tweak releases:
We freely backport *safe*, non-ABI-breaking changes by cherry-picking them
from main to the supported branch continually throughout most of the month.
In the seven days before the new month, we do a "soft freeze" where only
important bug fixes are backported. Hold on to any other patches you wish to
backport until after the monthly patch release (i.e., save them for the next
month's release so you never have a release that contains changes that are
only a few days old, and therefore not as well tested). You may, of course,
continue to backport fixes to documentation or other non-code parts of the
project during this soft freeze.
### Branching for annual major/minor releases
By mid-June (about 1-2 months before the beta of a new annual big release),
you should branch and mark it as an alpha.
At the tip of "main," create a new branch named `dev-MAJOR.MINOR` that will be
the staging area for the next release.
Customarily, at that point we add a commit to main (but not to the new
dev-MAJ.MIN branch) that bumps main's version to the next minor level, to
avoid any confusion between builds from main versus what will be the next
release branch. This starts the divergence between main and the release
branch, and henceforth, any big or compatibility-breaking changes will only be
committed to main and not backported to the release branch. (Though we are
loose about this rule during the alpha period and allow continued breaking
changes in the alpha, but by the time we call it beta, we allow no more
breaking changes.)
### Prior to a release
1. Update CI dependencies: Ensure that the "latest" CI test specifies the
current releases of the dependencies and compilers (check their home
pages), and that the [INSTALL.md](../INSTALL.md) file correctly documents
the version ranges that we expect to work and that we actively test.
2. Release notes: [CHANGES.md](../CHANGES.md) should be updated to reflect
all the new features and fixes. Looking at the notes from older releases
should provide a good example of what we're aiming for.
- Patch and tweak releases can be brief one-line descriptions (often the
first line of the commit messages involved), presented in a single
section in either chronological or any other order that seems right.
- Minor or major releases have a much more extensive, prose-based
description of all changes since the last minor release, broken into
sections (dependency changes, major new features, enhancements and fixes,
internals and developer goodies, testing/CI/ports, etc.) and ordered for
readability and relevance.
3. Ensure docs are up to date:
- Actually read the [README.md](../README.md), [INSTALL.md](../INSTALL.md),
and other repository docs and make sure all the information is up to
date. Check the "contributor credits" in the README against the recent
repo history to be sure new contributors are listed. Also check the
list of films and make sure it includes any recent productions that are
known to have used OSL.
- Skim the primary user documentation to look for any obvious errors,
especially the parts that describe new features. In the case of PDF docs
(such as osl-languagespec.pdf), make sure that a new PDF book is built if
the documentation source has been changed since the last release.
- If we are using any online docs (like readthedocs), make sure it is
building and looks correct on the web site.
4. Make sure the the top-level CMakeLists.txt file is updated:
- The version on the `project()` call should be correct.
- The `PROJECT_VERSION_RELEASE_TYPE` variable should be set to "alpha" or
"beta" if appropriate, "RC" for release candidate, or empty string `""`
for most supported releases, and "dev" only for the main branch or
developer previews.
- The `${PROJECT_NAME}_SUPPORTED_RELEASE` variable should be `ON` for any
release branch, `OFF` for main.
5. Make sure everything passes the usual CI workflow. Also check the daily or
weekly "analysis" workflows to make sure there aren't any important
warnings that should be fixed.
### Staging alpha / beta / release candidate (annual minor/major releases only)
For monthly patch releases, we don't have any formal alpha/beta/RC stages.
For the annual minor or major releases we have a staged release:
- `alpha` is everything after we have branched, in which we think all the big
new features have been added, and while we will make continued changes and
fixes, we are aiming for increased stability and to minimize additional
breaking changes prior to the release.
- `beta` should be about one month prior to the final release date. We create
a tag `v1.2.3.4-beta` and announce the beta (see below "Making the
release"). Once we tag a beta, we try very hard not to allow any further
changes that change the API or are not ABI-compatible (i.e., safe fixes
only).
- `RC` or release candidates around one week prior to the final release date.
This is a trial run, hopefully identical to the final release (except for
removing the RC label and making a new tag). The only changes allowed after
RC are fixes to the most critical bugs or build breaks that would be bad for
users to encounter. If critical problems are found with RC1, they should be
fixed and immediately re-tagged as RC2, etc. All other fixes should be
postponed until the next month's patch release.
### Making the release
A final release is made on the scheduled date, provided the latest RC has
survived for at least a few days of testing without finding any critical
problems. Don't make the release final until you are sure there are no
truly critical bugs or build breaks that users will encounter.
The following are the steps for making the release:
1. Edit the top-level CMakeLists.txt to remove any RC designation
(i.e., `PROJECT_VERSION_RELEASE_TYPE` should be set to `""`).
2. Edit CHANGES.md to reflect the correct date of the release and ensure it
includes any last-minute changes that were made during beta or release
candidate stages.
3. Push it to **your** GitHub, make sure it passes CI.
4. Tag the release: `git tag v1.2.3.4` (no more beta, RC, or dev suffix).
5. If this will now be the recommended stable release, move the `release`
branch marker to the same position.
6. Push it to GitHub: `git push aswf release --tags`
(This example assumes "aswf" is the name of the remote for the GitHub
`AcademySoftwareFoundation/OpenShadingLanguage` repo.)
7. Draft a release on GitHub: On
https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/releases
select "Draft a new release." Choose the new tag you just pushed. Make the
release title "Open Shading Language v1.2.3.4" (and beta, etc., designation
if applicable). In the description, paste the release notes for this
release (from Changes.md). If this is a beta or release candidate, check
"this is a pre-release" box at the bottom.
8. Announce the release on the [osl-dev mail list](https://lists.aswf.io/g/osl-dev)
with the subject "Release: OSL v1.2.3.4" and using one of these templates
for the body of the email.
For a monthly patch release:
> We have tagged v1.2.3.4 as the latest production release and moved the
> "release" branch marker to that point. This is guaranteed to be API,
> ABI, and link back-compatible with prior 1.2 releases. Release notes
> are below.
>
> (Paste the full set of 1.2 changes here, just copy the appropriate
> part of CHANGES.md)
For an annual major/minor release:
> OSL version 1.2 has been released! Officially tagged as "v1.2.3.4", we
> have also moved the "release" branch tag to this position. Henceforth,
> 1.2 is the supported production release family. The API is now frozen --
> we promise that subsequent 1.2.x releases (which should happen monthly)
> will not break back-compatibility of API, ABI, or linkage, compared to
> this release. Please note that this release is *not* ABI or link
> compatible with 1.1 or older releases.
>
> Release notes for 1.2 outlining all the changes since last year's
> release are below.
>
> Please note that a few of the build and runtime dependencies have
> changed their minimum supported versions. (List here any important
> changes to dependencies, compilers, or C++ standard that users should be
> aware of.)
>
> (List here anything else that people should know about this release
> family that may be surprising if they haven't followed the last year of
> development closely, or that they must know even if they are too lazy to
> read the release notes. If this is a major release that is not
> backward-compatible with prior versions, warn about that here.)
>
> Enjoy, and please report any problems. We will continue to make patch
> releases to the 1.2 family roughly monthly, which will contain bug fixes
> and non-breaking enhancements.
>
> The older 1.1 series of releases is now considered obsolete. We will
> continue for now to make 1.1 patch releases, but over time, these will
> become less frequent and be reserved for only the most critical bug
> fixes.
>
> The "main" branch is now progressing toward an eventual 1.3 release next
> summer. As usual, you are welcome to use main for real work, but we do
> not make any compatibility guarantees and don't guarantee continuing API
> compatibility in main.
>
> (Paste the full set of 1.2 changes here, just copy the appropriate
> part of CHANGES.md)
For a beta leading up to the annual major/minor release:
> OSL version 1.2 is now in beta, tagged as "v1.2.3.4-beta". We
> will try very hard not to make any further API or ABI changes between
> now and the final release (unless it is absolutely necessary to fix
> an important problem identified during beta testing). The final 1.2
> release is scheduled for [DATE GOES HERE], so please try building and
> testing the beta so we are sure to find any problems.
>
> Release notes for 1.2 outlining all the changes since last year's
> release are below.
>
> (Paste the full set of 1.2 changes here, just copy the appropriate
> part of CHANGES.md)
### After the release
Odds and ends to do after the tag is pushed and the announcements are sent:
- Re-read RELEASING.md and ensure that the instructions match what you
have done. Update as necessary.
- For annual beta releases, post a short message to the "Open Shading
Language" channel of the ASWF slack. It can be a one-line announcement and
then just a link to the GitHub release page for this version.
+17 -13
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
@@ -181,14 +181,18 @@ else ifeq (${platform}, macosx)
MY_CMAKE_FLAGS += \
-DCMAKE_C_COMPILER=gcc-9 -DCMAKE_CXX_COMPILER=g++-9
USE_LIBCPLUSPLUS := 0
else ifeq (${COMPILER},clang11)
else ifeq (${COMPILER},clang14)
MY_CMAKE_FLAGS += \
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@11/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@11/bin/clang++
else ifeq (${COMPILER},clang12)
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@14/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@14/bin/clang++
else ifeq (${COMPILER},clang15)
MY_CMAKE_FLAGS += \
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@12/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@12/bin/clang++
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@15/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@15/bin/clang++
else ifeq (${COMPILER},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
+25
View File
@@ -0,0 +1,25 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright Contributors to the Open Shading Language Project.
sonar.host.url=https://sonarcloud.io
# Required metadata
sonar.organization=academysoftwarefoundation
sonar.projectName=OpenShadingLanguage
sonar.projectVersion=1.12
sonar.projectKey=AcademySoftwareFoundation_OpenShadingLanguage
# Project links
sonar.links.homepage=https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
sonar.links.ci=https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/actions
sonar.links.scm=https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
sonar.links.issue=https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/issues
# Source properties
sonar.sources=src
sonar.sourceEncoding=UTF-8
sonar.exclusions=src/include/OSL/Imath/*.h,src/build-scripts/*
# C/C++ analyzer properties
sonar.cfamily.build-wrapper-output=build/bw_output
sonar.cfamily.gcov.reportsPath=_coverage
+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}
+14 -1
View File
@@ -12,6 +12,10 @@ if [[ "$USE_SIMD" != "" ]] ; then
OSL_CMAKE_FLAGS="$OSL_CMAKE_FLAGS -DUSE_SIMD=$USE_SIMD"
fi
if [[ -n "$CODECOV" ]] ; then
OSL_CMAKE_FLAGS="$OSL_CMAKE_FLAGS -DCODECOV=${CODECOV}"
fi
pushd build
cmake .. -G "$CMAKE_GENERATOR" \
-DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" \
@@ -23,7 +27,16 @@ cmake .. -G "$CMAKE_GENERATOR" \
-DCMAKE_INSTALL_LIBDIR="$OSL_ROOT/lib" \
-DCMAKE_CXX_STANDARD="$CMAKE_CXX_STANDARD" \
$OSL_CMAKE_FLAGS -DVERBOSE=1
time cmake --build . --target ${BUILDTARGET:=install} --config ${CMAKE_BUILD_TYPE}
# Save a copy of the generated files for debugging broken CI builds.
mkdir cmake-save || /bin/true
cp -r CMake* *.cmake cmake-save
: ${BUILDTARGET:=install}
if [[ "$BUILDTARGET" != "none" ]] ; then
echo "Parallel build ${CMAKE_BUILD_PARALLEL_LEVEL} of target ${BUILDTARGET}"
time ${OSL_CMAKE_BUILD_WRAPPER} cmake --build . --target ${BUILDTARGET} --config ${CMAKE_BUILD_TYPE}
fi
popd
if [[ "${DEBUG_CI:=0}" != "0" ]] ; then
+34
View File
@@ -0,0 +1,34 @@
#!/usr/bin/env bash
# Run code coverage analysis
# This assumes that the build occurred with CODECOV=1 andtests have already
# fully run.
set -ex
echo "Performing code coverage analysis"
mkdir _coverage
pushd _coverage
ls -R ../build/src/
# Remove files or directories we want to exclude from code coverage analysis,
# generally because we don't expect to execute any of their code during our
# CI. (Because it's only used interactively, or is fallback code only used
# when certain dependencies are not found.) Including these when we know we
# won't be calling them during coverage gathering will just make our coverage
# percentage look artifically low.
rm -f ../build/src/osltoy/CMakeFiles/osltoy.dir/*.cpp.{gcno,gcda}
# The sed command below converts from:
# ../build/src/liboslexec/CMakeFiles/oslexec.dir/foo.gcno
# to:
# ../src/liboslexec/foo.cpp
for g in $(find ../build -name "*.gcno" -type f); do
echo "Processing $g"
echo "dirname $g = $(dirname $g) to " `$(echo "$g" | sed -e 's/\/build\//\//' -e 's/\.gcno/\.cpp/' -e 's/\.cpp\.cpp/\.cpp/' -e 's/\/CMakeFiles.*\.dir\//\//')`
gcov -l -p -o $(dirname "$g") $(echo "$g" | sed -e 's/\/build\//\//' -e 's/\.gcno/\.cpp/' -e 's/\/CMakeFiles.*\.dir\//\//')
done
popd
+1 -1
View File
@@ -23,7 +23,7 @@ export DYLD_LIBRARY_PATH=$OSL_ROOT/lib:$DYLD_LIBRARY_PATH
export LD_LIBRARY_PATH=$OSL_ROOT/lib:$LD_LIBRARY_PATH
export OIIO_LIBRARY_PATH=$OSL_ROOT/lib:${OIIO_LIBRARY_PATH}
export LSAN_OPTIONS=suppressions=$PWD/src/build-scripts/nosanitize.txt
export ASAN_OPTIONS=print_suppressions=0
export ASAN_OPTIONS=print_suppressions=0:detect_odr_violation=1
export USE_PYTHON=${USE_PYTHON:=1}
export PYTHON_VERSION=${PYTHON_VERSION:="2.7"}
+17 -3
View File
@@ -8,12 +8,26 @@
# any command in it fails. This is crucial for CI tests.
set -ex
: ${CTEST_EXCLUSIONS:="broken"}
: ${CTEST_TEST_TIMEOUT:=60}
$OSL_ROOT/bin/testshade --help
echo "Parallel test " ${CTEST_PARALLEL_LEVEL}
echo "Parallel test ${CTEST_PARALLEL_LEVEL}"
echo "Default timeout ${CTEST_TEST_TIMEOUT}"
echo "Test exclusions '${CTEST_EXCLUSIONS}'"
echo "CTEST_ARGS '${CTEST_ARGS}'"
pushd build
time ctest -C ${CMAKE_BUILD_TYPE} -E broken --force-new-ctest-process \
--output-on-failure --timeout ${CTEST_TEST_TIMEOUT:=60} ${CTEST_ARGS}
ctest -C ${CMAKE_BUILD_TYPE} --force-new-ctest-process --output-on-failure \
--timeout ${CTEST_TEST_TIMEOUT} -E "${CTEST_EXCLUSIONS}" ${CTEST_ARGS} \
|| \
ctest -C ${CMAKE_BUILD_TYPE} --force-new-ctest-process \
--rerun-failed --repeat until-pass:5 -R render --output-on-failure \
--timeout ${CTEST_TEST_TIMEOUT} -E "${CTEST_EXCLUSIONS}" ${CTEST_ARGS}
# The weird construct above allows the render-* tests to run multiple times
popd
+2 -2
View File
@@ -73,7 +73,7 @@ from __future__ import print_function, absolute_import
###
### Only one main doc region will be output by the `docdeep` program,
### specified with the `-d` command line argument. Any other doc-regions
### will not be included in the documention output of that run.
### will not be included in the documentation output of that run.
###
### However, one doc-region may *include* the text of another doc-region
### as follows:
@@ -114,7 +114,7 @@ from __future__ import print_function, absolute_import
### For pre-code comments, the contiguous comment region associated with
### a declaration immediately precedes the declaration. Such a comment
### set has its first line start with `///>`. For post-code comments,
### the documentaiton comments follows the code declaration, and this is
### the documentation comments follows the code declaration, and this is
### designated by having its first line start with `///<`. I like to
### just remember that the `<` or `>` points in the direction of the code
### declaration that the comment applies to.
+37 -25
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,8 +42,12 @@ if [[ "$ASWF_ORG" != "" ]] ; then
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" || "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
sudo cp src/build-scripts/oneAPI.repo /etc/yum.repos.d
sudo yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic
set +e; source /opt/intel/oneapi/setvars.sh; set -e
sudo /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.
set +e; source /opt/intel/oneapi/setvars.sh --config oneapi_2022.1.0.cfg; set -e
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" ]] ; then
echo "Verifying installation of Intel(r) C++ Compiler:"
icpc --version
@@ -57,22 +61,39 @@ if [[ "$ASWF_ORG" != "" ]] ; then
else
# Using native Ubuntu runner
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
# sudo add-apt-repository ppa:ubuntu-toolchain-r/test
time sudo apt-get update
time sudo apt-get -q install -y \
git cmake ninja-build ccache g++ \
libboost-dev libboost-thread-dev libboost-filesystem-dev \
libilmbase-dev libopenexr-dev \
python-dev python-numpy \
libtiff-dev libgif-dev libpng-dev \
flex bison libbison-dev \
libpugixml-dev \
libopencolorio-dev \
qt5-default
libopencolorio-dev
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
# Nonstandard python versions
if [[ "${PYTHON_VERSION}" == "3.9" ]] ; then
time sudo apt-get -q install -y python3.9-dev python3-numpy
pip3 --version
pip3 install numpy
elif [[ "$PYTHON_VERSION" == "2.7" ]] ; then
time sudo apt-get -q install -y python-dev python-numpy
else
pip3 install numpy
fi
if [[ "$CXX" == "g++-6" ]] ; then
time sudo apt-get install -y g++-6
elif [[ "$CXX" == "g++-7" ]] ; then
@@ -85,6 +106,8 @@ else
time sudo apt-get install -y g++-10
elif [[ "$CXX" == "g++-11" ]] ; then
time sudo apt-get install -y g++-11
elif [[ "$CXX" == "g++-12" ]] ; then
time sudo apt-get install -y g++-12
fi
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" || "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
@@ -92,22 +115,11 @@ else
sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB
echo "deb https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list
time sudo apt-get update
time sudo apt-get install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic
set +e; source /opt/intel/oneapi/setvars.sh; set -e
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" ]] ; then
icpc --version
fi
if [[ "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
icpx --version
fi
fi
# Nonstandard python versions
if [[ "${PYTHON_VERSION}" == "3.8" ]] ; then
#time sudo apt-get -q install -y python3.8-dev python3-numpy
echo "skip?"
elif [[ "${PYTHON_VERSION}" == "3.9" ]] ; then
time sudo apt-get -q install -y python3.9-dev python3-numpy
time sudo apt-get install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic=2022.1.0-3768
# Because multiple (possibly newer) versions of oneAPI may be installed,
# use a config file to specify compiler and tbb versions
# NOTE: oneAPI components have independent version numbering.
set +e; source /opt/intel/oneapi/setvars.sh --config oneapi_2022.1.0.cfg; set -e
fi
source src/build-scripts/build_llvm.bash
@@ -164,7 +176,7 @@ if [[ "$OPENIMAGEIO_VERSION" != "" ]] ; then
# Don't let warnings in OIIO break OSL's CI run
export OPENIMAGEIO_CMAKE_FLAGS+=" -DSTOP_ON_WARNING=OFF"
export OPENIMAGEIO_CMAKE_FLAGS+=" -DUSE_OPENGL=0"
if [[ $OPENIMAGEIO_VERSION == master ]] ; then
if [[ $OPENIMAGEIO_VERSION == master && "${OPENIMAGEIO_UNITY:-1}" != "0" ]] ; then
# Speed up the OIIO build by doing a "unity" build. (Note: this is
# only a savings in CI where there are only 1-2 cores available, and
# is only supported for OIIO 2.3.14 and later)
+14 -8
View File
@@ -4,7 +4,7 @@
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
# This script, which assumes it is runnign on a Mac OSX with Homebrew
# This script, which assumes it is running on a Mac OSX with Homebrew
# installed, does a "brew install" in all packages reasonably needed by
# OSL and its dependencies.
@@ -19,27 +19,33 @@ if [[ `which brew` == "" ]] ; then
exit 1
fi
set -ex
#brew update >/dev/null
if [[ "$DO_BREW_UPDATE" != "" ]] ; then
brew update >/dev/null
fi
echo ""
echo "Before my brew installs:"
brew list --versions
brew install --display-times -q gcc ccache cmake ninja boost || true
brew link --overwrite gcc
brew unlink python@2.7 || true
brew unlink python@3.9 || true
brew unlink python@3.8 || true
brew install --display-times -q python@${PYTHON_VERSION} || true
# brew unlink python@2.7 || true
# brew unlink python@3.8 || true
# brew unlink python@3.9 || true
brew unlink python@3.10 || true
brew link --overwrite --force python@${PYTHON_VERSION} || true
brew upgrade --display-times -q cmake || true
brew install --display-times -q ilmbase openexr
brew install --display-times -q imath openexr
#brew install --display-times -q freetype
brew install --display-times -q opencolorio partio pugixml
brew install --display-times -q --overwrite --force opencolorio || true
brew install --display-times -q partio pugixml
brew install --display-times -q pybind11 numpy || true
brew install --display-times -q tbb || true
brew install --display-times -q flex bison
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:"
-5
View File
@@ -1,5 +0,0 @@
leak:Imf_2_2
leak:Imf_2_3
leak:Imf_2_4
leak:libIlmImf
leak:oslgram.y
+3
View File
@@ -0,0 +1,3 @@
default=exclude
compiler=2022.1.0
tbb=2021.6.0
+1
View File
@@ -1,3 +1,4 @@
#!/usr/bin/env python
# Copyright Contributors to the Open Shading Language project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
+1 -1
View File
@@ -22,7 +22,7 @@ find_dependency(OpenImageIO @OpenImageIO_VERSION@ REQUIRED)
# Compute the installation prefix relative to this file
get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE)
# There's no guarantee that CMAKE_INSTALL_XXXDIR is a relative path so we extract the final component to handle asbolute paths
# There's no guarantee that CMAKE_INSTALL_XXXDIR is a relative path so we extract the final component to handle absolute paths
get_filename_component(_INCLUDE_DIR_NAME "@CMAKE_INSTALL_INCLUDEDIR@" NAME)
get_filename_component(_LIB_DIR_NAME "@CMAKE_INSTALL_LIBDIR@" NAME)
+12 -50
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
@@ -226,7 +226,7 @@ endif ()
# We wil use this for ccache and timing
# We will use this for ccache and timing
set (MY_RULE_LAUNCH "")
@@ -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")
@@ -376,11 +376,9 @@ include (CheckCXXSourceRuns)
option (CODECOV "Build code coverage tests" OFF)
if (CODECOV AND (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG))
message (STATUS "Compiling for code coverage analysis")
add_compile_options ("-ftest-coverage -fprofile-arcs -O0")
add_compile_options (-ftest-coverage -fprofile-arcs)
add_definitions ("-D${PROJ_NAME}_CODE_COVERAGE=1")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ftest-coverage -fprofile-arcs")
set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -ftest-coverage -fprofile-arcs")
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -ftest-coverage -fprofile-arcs")
link_libraries(gcov)
endif ()
@@ -394,22 +392,9 @@ if (SANITIZE AND (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG))
foreach (feature ${SANITIZE_FEATURE_LIST})
message (STATUS " sanitize feature: ${feature}")
add_compile_options (-fsanitize=${feature})
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=${feature}")
set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fsanitize=${feature}")
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=${feature}")
add_link_options (-fsanitize=${feature})
endforeach()
add_compile_options (-g -fno-omit-frame-pointer)
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set (SANITIZE_ON_LINUX 1)
endif ()
if (CMAKE_COMPILER_IS_GNUCC AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
add_compile_options ("-fuse-ld=gold")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fuse-ld=gold")
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=gold")
set (SANITIZE_LIBRARIES "asan;pthread")
# set (SANITIZE_LIBRARIES "asan" "ubsan")
endif()
if (CMAKE_COMPILER_IS_GNUCC)
# turn on glibcxx extra annotations to find vector writes past end
add_definitions ("-D_GLIBCXX_SANITIZE_VECTOR=1")
@@ -475,29 +460,7 @@ endif ()
# is being built as a subproject.
if (PROJECT_IS_TOP_LEVEL)
set (CLANG_FORMAT_EXE_HINT "" CACHE PATH "clang-format executable's directory (will search if not specified")
set (CLANG_FORMAT_INCLUDES # "src/*.cpp"
"src/*.h"
"src/*.cu"
"src/include/*.h"
"src/liboslcomp/*.cpp"
"src/liboslcomp/*.h"
"src/liboslexec/batch*.cpp"
"src/liboslexec/wide/*.cpp"
"src/liboslexec/wide/*.h"
"src/liboslexec/rs_fallback.cpp"
"src/liboslquery/*.cpp"
"src/liboslnoise/*.cpp"
"src/liboslquery/*.h"
"src/oslinfo/*.cpp"
"src/oslc/*.cpp"
"src/osl.imageio/*.cpp"
"src/osltoy/*.cpp"
"src/osltoy/*.h"
"src/testrender/*.h"
"src/testrender/*.cpp"
"src/testshade/*.h"
"src/testshade/*.cpp"
"testsuite/*.cpp"
set (CLANG_FORMAT_INCLUDES "src/*.cpp" "src/*.h" "src/*.cu"
CACHE STRING "Glob patterns to include for clang-format")
set (CLANG_FORMAT_EXCLUDES
# Files "imported and modified" that we don't want to reformat, so
@@ -508,7 +471,6 @@ if (PROJECT_IS_TOP_LEVEL)
"testsuite/*.h"
# Header files in shaders are OSL, not C++
"src/shaders/*.h"
""
CACHE STRING "Glob patterns to exclude for clang-format")
find_program (CLANG_FORMAT_EXE
NAMES clang-format bin/clang-format
@@ -529,7 +491,7 @@ if (PROJECT_IS_TOP_LEVEL)
# message (STATUS "clang-format file list: ${FILES_TO_FORMAT}")
file (COPY ${CMAKE_CURRENT_SOURCE_DIR}/.clang-format
DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
add_custom_target (run-clang-format
add_custom_target (clang-format
COMMAND "${CLANG_FORMAT_EXE}" -i -style=file ${FILES_TO_FORMAT} )
else ()
message (STATUS "clang-format not found.")
+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}"
+65 -41
View File
@@ -88,7 +88,7 @@ checked_find_package (OpenEXR REQUIRED
)
# Force Imath includes to be before everything else to ensure that we have
# the right Imath/OpenEXR version, not some older version in the system
# library. This shoudn't be necessary, except for the common case of people
# library. This shouldn't be necessary, except for the common case of people
# building against Imath/OpenEXR 3.x when there is still a system-level
# install version of 2.x.
include_directories(BEFORE ${IMATH_INCLUDES})
@@ -105,7 +105,7 @@ endif ()
# OpenImageIO
checked_find_package (OpenImageIO REQUIRED
VERSION_MIN 2.2.6
VERSION_MIN 2.3.17
DEFINITIONS -DOIIO_HIDE_FORMAT=1)
checked_find_package (pugixml REQUIRED
@@ -115,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}")
@@ -136,6 +137,27 @@ if (APPLE AND LLVM_VERSION VERSION_EQUAL 10.0.1 AND EXISTS "/usr/local/Cellar/ll
" brew upgrade llvm \n"
"${ColorReset}\n")
endif ()
if (LLVM_VERSION VERSION_GREATER_EQUAL 15.0
AND ( (CMAKE_COMPILER_IS_APPLECLANG AND APPLECLANG_VERSION_STRING VERSION_LESS 15.0)
OR (CMAKE_COMPILER_IS_CLANG AND CLANG_VERSION_STRING VERSION_LESS 15.0)))
message (WARNING
"${ColorYellow}"
"If you are using LLVM 15 or higher, you should also use clang version "
"15 or higher, or you may get build errors.${ColorReset}\n")
endif ()
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)
@@ -145,60 +167,63 @@ 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 5.1)
VERSION_MIN 7.0)
include_directories (BEFORE "${OPTIX_INCLUDES}")
if (NOT USE_LLVM_BITCODE OR NOT USE_FAST_MATH)
message (FATAL_ERROR "Enabling OptiX requires USE_LLVM_BITCODE=1 and USE_FAST_MATH=1")
@@ -211,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 -3
View File
@@ -82,6 +82,11 @@ function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_
list (TRANSFORM OpenImageIO_INCLUDES PREPEND -I
OUTPUT_VARIABLE ALL_OpenImageIO_INCLUDES)
if (${LLVM_VERSION} VERSION_GREATER_EQUAL 15.0)
# Until we fully support opaque pointers, we need to disable
# them when using LLVM 15.
list (APPEND LLVM_COMPILE_FLAGS -Xclang -no-opaque-pointers)
endif ()
# Command to turn the .cpp file into LLVM assembly language .s, into
# LLVM bitcode .bc, then back into a C++ file with the bc embedded!
@@ -103,8 +108,8 @@ function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_
-O3 -fno-math-errno -S -emit-llvm ${extra_clang_args}
-o ${src_asm} ${src}
COMMAND ${LLVM_AS_TOOL} -f -o ${src_bc} ${src_asm}
# Do NOT setup a MAIN_DEPENDENCY because only 1 may exist
# and we may have the several outputs dependant on the same source
# Do NOT setup a MAIN_DEPENDENCY because only 1 may exist
# and we may have the several outputs dependent on the same source
DEPENDS ${src} ${exec_headers} ${PROJECT_PUBLIC_HEADERS}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
endforeach ()
@@ -132,7 +137,7 @@ function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_
${exec_headers} ${PROJECT_PUBLIC_HEADERS}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
# add generated .cpp with embedded bitcode to the list of soures
# add generated .cpp with embedded bitcode to the list of sources
set ( ${list_to_append_cpp} ${${list_to_append_cpp}} ${src_bc_cpp} PARENT_SCOPE )
endfunction ( )
+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})
+1 -1
View File
@@ -10,7 +10,7 @@
# PARTIO_LIBRARIES - library to link against
# PARTIO_FOUND - true if Partio was found.
# Hack! perfer a config if it can be found
# Hack! prefer a config if it can be found
find_package(partio CONFIG)
if (PARTIO_FOUND OR partio_FOUND)
if (VERBOSE)
+1 -1
View File
@@ -1,4 +1,4 @@
# Copyright Contributors to the Open Shading Languge project.
# Copyright Contributors to the Open Shading Language project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/
+4 -7
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}
@@ -77,7 +74,7 @@ macro (setup_python_module)
PRIVATE
pybind11::pybind11
Python::Python
${lib_LIBS} ${SANITIZE_LIBRARIES})
${lib_LIBS})
if (APPLE)
set_target_properties (${target_name} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
endif ()
+67 -31
View File
@@ -1,4 +1,4 @@
# Copyright Contributors to the Open Shading Languge project.
# Copyright Contributors to the Open Shading Language project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/
@@ -16,6 +16,10 @@ add_custom_command (OUTPUT "${CMAKE_BINARY_DIR}/testsuite/runtest.py"
MAIN_DEPENDENCY "${CMAKE_SOURCE_DIR}/testsuite/runtest.py")
add_custom_target ( CopyFiles ALL DEPENDS "${CMAKE_BINARY_DIR}/testsuite/runtest.py" )
set (OSL_TEST_BIG_TIMEOUT 800 CACHE STRING "Timeout for tests that take a long time")
# add_one_testsuite() - set up one testsuite entry
#
# Usage:
@@ -26,10 +30,12 @@ add_custom_target ( CopyFiles ALL DEPENDS "${CMAKE_BINARY_DIR}/testsuite/runtest
# [COMMAND cmd...] - optional override of launch command
# )
#
macro (add_one_testsuite testname testsrcdir)
cmake_parse_arguments (_tst "" "" "ENV;COMMAND" ${ARGN})
set (testsuite "${CMAKE_SOURCE_DIR}/testsuite")
set (testdir "${CMAKE_BINARY_DIR}/testsuite/${testname}")
file (MAKE_DIRECTORY "${testdir}")
if (NOT _tst_COMMAND)
set (_tst_COMMAND ${Python_EXECUTABLE} "${testsuite}/runtest.py" ${testdir})
if (MSVC_IDE)
@@ -45,7 +51,17 @@ macro (add_one_testsuite testname testsrcdir)
OSL_TESTSUITE_SRC=${testsrcdir}
OSL_TESTSUITE_CUR=${testdir}
)
file (MAKE_DIRECTORY "${testdir}")
# We need to suppress the leak sanitizer for "texture" tests, because of a
# minor leak inside OIIO (140 bytes! -- inconsequential) but which we
# can't use the suppressions list becuase the leaks come from calls made
# inside JITed code for which there is not a good stack trace. Any real
# leaks from OIIO or its dependencies we assume will be caught by lsan on
# the OIIO side, where there is no JIT to complicate things.
if (${testname} MATCHES "^texture" OR ${testname} MATCHES "gettextureinfo")
list (APPEND _tst_ENV ASAN_OPTIONS=detect_leaks=0:$ENV{ASAN_OPTIONS})
endif ()
add_test ( NAME ${testname} COMMAND ${_tst_COMMAND} )
# message ("Test -- env ${_tst_ENV} cmd ${_tst_COMMAND}")
set_tests_properties (${testname} PROPERTIES ENVIRONMENT "${_tst_ENV}" )
@@ -53,8 +69,11 @@ macro (add_one_testsuite testname testsrcdir)
# from piling up together, allocate a few cores each.
if (${testname} MATCHES "^render-")
set_tests_properties (${testname} PROPERTIES LABELS render
TIMEOUT 240
PROCESSORS 4 COST 10 TIMEOUT 240)
PROCESSORS 4 COST 10 TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
endif ()
# 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")
@@ -76,7 +95,7 @@ macro (add_one_testsuite testname testsrcdir)
# These are batched shading regression tests. Some are quite
# long, so give them a higher cost and timeout.
set_tests_properties (${testname} PROPERTIES LABELS batchregression
COST 15 TIMEOUT 300)
COST 15 TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
endif ()
endmacro ()
@@ -107,7 +126,7 @@ macro ( TESTSUITE )
# Run the test unoptimized, unless it matches a few patterns that
# we don't test unoptimized (or has an OPTIMIZEONLY marker file).
if (NOT _testname MATCHES "optix"
if (NOT _testname MATCHES "optix"
AND NOT EXISTS "${_testsrcdir}/NOSCALAR"
AND NOT EXISTS "${_testsrcdir}/BATCHED_REGRESSION"
AND NOT EXISTS "${_testsrcdir}/OPTIMIZEONLY")
@@ -128,7 +147,7 @@ macro ( TESTSUITE )
# 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"
@@ -142,8 +161,8 @@ macro ( TESTSUITE )
add_one_testsuite ("${_testname}.optix.opt" "${_testsrcdir}"
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
@@ -156,7 +175,7 @@ macro ( TESTSUITE )
add_one_testsuite ("${_testname}.batched" "${_testsrcdir}"
ENV TESTSHADE_OPT=0 TESTSHADE_BATCHED=1 )
endif ()
if ((EXISTS "${_testsrcdir}/BATCHED" OR test_all_batched OR _testname MATCHES "batched")
AND NOT EXISTS "${_testsrcdir}/BATCHED_REGRESSION"
AND NOT EXISTS "${_testsrcdir}/NOBATCHED"
@@ -165,7 +184,7 @@ macro ( TESTSUITE )
add_one_testsuite ("${_testname}.batched.opt" "${_testsrcdir}"
ENV TESTSHADE_OPT=2 TESTSHADE_BATCHED=1 )
endif ()
# When building for Batched support, optionally run a regression test
# if there is an BATCHED_REGRESSION marker file in the directory.
if ((EXISTS "${_testsrcdir}/BATCHED_REGRESSION")
@@ -211,16 +230,17 @@ macro (osl_add_all_tests)
# special installed tests.
TESTSUITE ( aastep allowconnect-err andor-reg and-or-not-synonyms
arithmetic area-reg arithmetic-reg
array array-reg array-copy-reg array-derivs array-range
array array-reg array-copy-reg array-derivs array-range
array-aassign array-assign-reg array-length-reg
bitwise-and-reg bitwise-or-reg bitwise-shl-reg bitwise-shr-reg bitwise-xor-reg
blackbody blackbody-reg blendmath breakcont breakcont-reg
bug-array-heapoffsets bug-locallifetime bug-outputinit
bug-param-duplicate bug-peep bug-return
calculatenormal-reg
cellnoise closure closure-array color color-reg 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
component-range
control-flow-reg connect-components
const-array-params const-array-fill
debugnan debug-uninit
@@ -239,7 +259,9 @@ macro (osl_add_all_tests)
globals-needed
group-outputs groupstring
hash hashnoise hex hyperb
ieee_fp ieee_fp-reg if if-reg incdec initlist initops intbits isconnected
ieee_fp ieee_fp-reg if if-reg incdec initlist
initops initops-instance-clash
intbits isconnected
isconstant
layers layers-Ciassign layers-entry layers-lazy layers-lazyerror
layers-nonlazycopy layers-repeatedoutputs
@@ -259,7 +281,7 @@ macro (osl_add_all_tests)
noise-perlin noise-simplex
noise-reg
normalize-reg
pnoise pnoise-cell pnoise-gabor
pnoise pnoise-cell pnoise-gabor
pnoise-generic pnoise-perlin
pnoise-reg
operator-overloading
@@ -277,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
@@ -288,14 +311,25 @@ 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
render-mx-furnace-oren-nayar
render-mx-furnace-sheen
render-mx-burley-diffuse
render-mx-dielectric render-mx-dielectric-glass
render-mx-conductor
render-mx-generalized-schlick render-mx-generalized-schlick-glass
render-mx-layer
render-mx-sheen
render-microfacet render-oren-nayar
render-uv render-veachmis render-ward
render-raytypes
select select-reg shaderglobals shortcircuit
smoothstep-reg
spline spline-reg splineinverse splineinverse-ident
smoothstep-reg
spline spline-reg splineinverse splineinverse-ident
splineinverse-knots-ascend-reg splineinverse-knots-descend-reg
spline-boundarybug spline-derivbug
split-reg
@@ -319,10 +353,10 @@ macro (osl_add_all_tests)
trailing-commas
transcendental-reg
transitive-assign
transform transform-reg transformc transformc-reg trig trig-reg
transform transform-reg transformc transformc-reg trig trig-reg
typecast
unknown-instruction
userdata userdata-passthrough
userdata userdata-custom userdata-passthrough
vararray-connect vararray-default
vararray-deserialize vararray-param
vecctr vector vector-reg
@@ -339,10 +373,10 @@ macro (osl_add_all_tests)
endif ()
# Add tests that require the Python bindings if we built them.
# We also exclude these tests if this is a sanitizer build on Linux,
# because the Python interpreter itself won't be linked with the right asan
# We also exclude these tests if this is a sanitizer build, because the
# Python interpreter itself won't be linked with the right asan
# libraries to run correctly.
if (USE_PYTHON AND NOT SANITIZE_ON_LINUX)
if (USE_PYTHON AND NOT SANITIZE)
TESTSUITE ( python-oslquery )
endif ()
@@ -354,7 +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 ()
@@ -363,11 +397,13 @@ macro (osl_add_all_tests)
TESTSUITE ( testoptix testoptix-noise example-cuda)
endif ()
# Some regression tests have alot of combinations and may need more time to finish
if (BUILD_BATCHED)
set_tests_properties (arithmetic-reg.regress.batched.opt PROPERTIES TIMEOUT 800)
set_tests_properties (transform-reg.regress.batched.opt PROPERTIES TIMEOUT 800)
# Some regression tests have a lot of combinations and may need more time to finish
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
PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
endif ()
set_tests_properties (matrix-reg.regress.rsbitcode.opt PROPERTIES TIMEOUT 800)
set_tests_properties (matrix-reg.regress.rsbitcode.opt
PROPERTIES TIMEOUT ${OSL_TEST_BIG_TIMEOUT})
endmacro()
+773 -111
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
+5 -5
View File
@@ -11,7 +11,7 @@
_testshade_ basics
==================================================
The OSL software distribution inculdes `testshade`, a command-line utility
The OSL software distribution includes `testshade`, a command-line utility
that was written for OSL unit tests, and for a "test harness" in which we
can execute shaders for debugging (the shaders or OSL itself) in isolation
from any particular rendering system.
@@ -28,7 +28,7 @@ itself, it has a number of potential uses in a production studio, including:
* Baking procedural patterns into textures.
* Benchmarking shaders and evaluating their performance, including
comparitive tests such as "is it faster to code it this way or that way?"
comparative tests such as "is it faster to code it this way or that way?"
* Exploring the inner workings of OSL's runtime optimizer, to answer
questions like: "will this idiom optimize away at runtime when I use
@@ -176,7 +176,7 @@ Helpful command line arguments:
For the sake of simplicity, this document presents almost all examples as if
they consisted of just a single shader node. But `testshade` is able to
specify and execut entire shader groups (networks of shader nodes). The
specify and execute entire shader groups (networks of shader nodes). The
remainder of this section will explain how this can be done.
Let's make a simple shader network as an example.
@@ -582,7 +582,7 @@ single texture lookup.
## Controling optimization
## Controlling optimization
You can control the optimization level overall:
@@ -638,7 +638,7 @@ that they are not optimized away so as to lead you to an inaccurate
reflection of what optimizations would really happen at render time. At the
same time, be careful not to inadvertently set `lockgeom=0` for parameters
that will typically be set to default values, instance values, or
connections from layers that are likely to be analized and found to emit
connections from layers that are likely to be analyzed and found to emit
constants for theor outputs -- you also don't want your benchmarks to
incorrectly disable optimizations what would typically happen at render
time.
+1 -1
View File
@@ -72,7 +72,7 @@ public:
AccumRule(int outidx, bool toalpha)
: m_outidx(outidx), m_save_to_alpha(toalpha) {};
/// Called to accumulate from AccumAutomata. It will select the right ouput from
/// Called to accumulate from AccumAutomata. It will select the right output from
/// the given vector based in the AOV index number (they are guaranteed to match)
void accum(const Color3& color, std::vector<AovOutput>& outputs) const;
+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 -31
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,37 +15,26 @@
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 {
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
#ifdef __CUDA_ARCH__
size_t m_chars;
#else
const char* m_chars;
#endif
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
#ifdef __CUDA_ARCH__
OSL_HOSTDEVICE DeviceString() {}
OSL_HOSTDEVICE DeviceString(uint64_t i) : m_chars(i) {}
#endif
OSL_HOSTDEVICE uint64_t hash() const
{
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
#ifdef __CUDA_ARCH__
return m_chars;
#else
return *(uint64_t*)(m_chars - sizeof(uint64_t) - sizeof(uint64_t));
@@ -58,7 +43,7 @@ struct DeviceString {
// In OptiX 7 we don't store the string's length. Make this a compile
// time error.
#if !(defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000)
#ifndef __CUDA_ARCH__
OSL_HOSTDEVICE uint64_t length() const
{
return *(uint64_t*)(m_chars - sizeof(uint64_t));
@@ -67,8 +52,11 @@ struct DeviceString {
// In OptiX 7 we can't return the string's contents. Make this a compile
// time error.
#if !(defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000)
OSL_HOSTDEVICE const char* c_str() const { return m_chars; }
#ifndef __CUDA_ARCH__
OSL_HOSTDEVICE const char* c_str() const
{
return m_chars;
}
#endif
OSL_HOSTDEVICE bool operator==(const DeviceString& other) const
@@ -81,7 +69,7 @@ struct DeviceString {
return m_chars != other.m_chars;
}
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
#ifdef __CUDA_ARCH__
OSL_HOSTDEVICE bool operator==(const size_t other) const
{
@@ -93,7 +81,10 @@ struct DeviceString {
return hash() != other;
}
OSL_HOSTDEVICE operator size_t() const { return hash(); }
OSL_HOSTDEVICE operator size_t() const
{
return hash();
}
#endif
};
@@ -123,9 +114,6 @@ typedef DeviceString StringParam;
namespace DeviceStrings {
# define STRDECL(str, var_name) \
extern __device__ OSL_NAMESPACE::DeviceString var_name;
# if OPTIX_VERSION < 70000
# include <OSL/strdecls.h>
# endif
# undef STRDECL
} // namespace DeviceStrings
#else
@@ -140,10 +128,6 @@ namespace DeviceStrings {
OSL_NAMESPACE_EXIT
#ifdef __CUDA_ARCH__
# if OPTIX_VERSION < 70000
namespace StringParams = OSL_NAMESPACE::DeviceStrings;
# endif
#else
#ifndef __CUDA_ARCH__
namespace StringParams = OSL_NAMESPACE::Strings;
#endif
+1 -1
View File
@@ -223,7 +223,7 @@ public:
// delegating access to element storage to the DualStorage base class
template<
class T, // Base data type
int PARTIALS=1 // Number of dimentions of partial derivs
int PARTIALS=1 // Number of dimensions of partial derivs
>
class Dual : public DualStorage<T, PARTIALS> {
static const int elements = PARTIALS+1; // main value + partials
+65 -48
View File
@@ -108,6 +108,12 @@ public:
void jit_aggressive(bool val) { m_jit_aggressive = val; }
bool jit_aggressive() const { return m_jit_aggressive; }
// Select whether the representation of a ustring is going to be
// the character pointer, or the hash.
enum class UstringRep { charptr, hash };
UstringRep ustring_rep() const { return m_ustring_rep; }
void ustring_rep(UstringRep rep);
/// Return a reference to the current context.
llvm::LLVMContext& context() const { return *m_llvm_context; }
@@ -148,15 +154,6 @@ public:
void debug_pop_inlined_function();
void debug_set_location(OIIO::ustring sourcefile, int sourceline);
/// Create a new function (that will later be populated with
/// instructions) with up to 4 args.
OSL_DEPRECATED("Use make_function flavor that takes a cspan (1.12)")
llvm::Function* make_function(const std::string& name, bool fastcall,
llvm::Type* rettype, llvm::Type* arg1 = NULL,
llvm::Type* arg2 = NULL,
llvm::Type* arg3 = NULL,
llvm::Type* arg4 = NULL);
/// Create a new function (that will later be populated with
/// instructions) with a cspan of args.
llvm::Function* make_function(const std::string& name, bool fastcall,
@@ -223,7 +220,7 @@ public:
// Look up the TargetISA enum by name. Special names: "host" means
// figure out what this host is, "none" or "" mean to use the baseline
// or no special ops not availabe on all flavors of this family of CPUs.
// or no special ops not available on all flavors of this family of CPUs.
static TargetISA lookup_isa_by_name(string_view target_name = "");
// Name for this TargetISA enum.
@@ -283,12 +280,7 @@ public:
Linkage default_linkage = Linkage::Internal,
std::string* out_err = nullptr);
// OLD, might deprecate later
/// Change symbols in the module that are marked as having external
/// linkage to an alternate linkage that allows them to be discarded if
/// not used within the module. Only do this for functions that start
/// with prefix, and that DON'T match anything in the two exceptions
/// lists.
OSL_DEPRECATED("prune_and_internalize_module is better (1.13)")
void internalize_module_functions(
const std::string& prefix, const std::vector<std::string>& exceptions,
const std::vector<std::string>& moreexceptions);
@@ -311,7 +303,7 @@ public:
/// Create a new LLVM basic block (for the current function) and return
/// its handle.
llvm::BasicBlock* new_basic_block(const std::string& name = std::string());
llvm::BasicBlock* new_basic_block(const std::string& name = {});
/// Save the return block pointer when entering a function. If
/// after==NULL, generate a new basic block for where to go after the
@@ -383,13 +375,13 @@ public:
// vs. relying on a conditional result already in a register.
//
// To handle 'continue', we allocate a 'continue mask' that is
// initially populated with a 0 representing the deactived lanes by
// initially populated with a 0 representing the deactivated lanes by
// 'continue' operations. We require a location on the stack for each
// 'continue mask' in order for a 'continue' statement to modify it and
// cause a subset of the lanes to be deactivated. If an continue was
// processed, the 'continue mask' is where it will be stored and pulled
// from when applying to the unwinding conditional mask stack. When a
// loop's scope is exited, the continue mask is popped so it would't be
// loop's scope is exited, the continue mask is popped so it wouldn't be
// applied to an outer loop.
//
// The logic of when and how to actually apply these masks is handled
@@ -543,8 +535,8 @@ public:
llvm::Type* type_triple() const { return m_llvm_type_triple; }
llvm::Type* type_matrix() const { return m_llvm_type_matrix; }
llvm::Type* type_typedesc() const { return m_llvm_type_longlong; }
llvm::Type* type_ustring() { return m_llvm_type_ustring; }
llvm::PointerType* type_void_ptr() const { return m_llvm_type_void_ptr; }
llvm::PointerType* type_string() { return m_llvm_type_char_ptr; }
llvm::PointerType* type_ustring_ptr() const
{
return m_llvm_type_ustring_ptr;
@@ -579,7 +571,8 @@ public:
llvm::Type* type_wide_triple() const { return m_llvm_type_wide_triple; }
llvm::Type* type_wide_matrix() const { return m_llvm_type_wide_matrix; }
llvm::Type* type_wide_void_ptr() const { return m_llvm_type_wide_void_ptr; }
llvm::Type* type_wide_string() const
llvm::Type* type_wide_ustring() const { return m_llvm_type_wide_ustring; }
llvm::PointerType* type_wide_ustring_ptr() const
{
return m_llvm_type_wide_ustring_ptr;
}
@@ -629,7 +622,7 @@ public:
bool is_packed = false);
/// Return the llvm::Type that is a pointer to the given llvm type.
llvm::Type* type_ptr(llvm::Type* type);
llvm::PointerType* type_ptr(llvm::Type* type);
/// Return the llvm::Type that is the wide version of the given llvm type
llvm::Type* type_wide(llvm::Type* type);
@@ -638,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.
@@ -660,26 +659,26 @@ public:
/// Return the human-readable name of the type of the llvm value.
std::string llvm_typenameof(llvm::Value* val) const;
/// Return an llvm::Value holding the given floating point constant.
/// Return an llvm::Constant holding the given floating point constant.
llvm::Constant* constant(float f);
/// Return an llvm::Value holding the given integer constant.
/// Return an llvm::Constant holding the given integer constant.
llvm::Constant* constant(int i);
/// Return an llvm::Value holding the given integer constant.
/// Return an llvm::Constant holding the given integer constant.
llvm::Constant* constant8(int i);
llvm::Constant* constant16(uint16_t i);
llvm::Constant* constant64(uint64_t i);
llvm::Constant* constant128(uint64_t i);
llvm::Constant* constant128(uint64_t left, uint64_t right);
// Return an llvm::value holding an explicit signed int64_t constant.
// Return an llvm::Constant holding an explicit signed int64_t constant.
llvm::Constant* constanti64(int64_t i);
/// Return an llvm::Value holding the given size_t constant.
/// Return an llvm::Constant holding the given size_t constant.
llvm::Constant* constant(size_t i);
/// Return an llvm::Value holding the given bool constant.
/// Return an llvm::Constant holding the given bool constant.
/// Change the name so it doesn't get mixed up with int.
llvm::Constant* constant_bool(bool b);
@@ -687,7 +686,8 @@ public:
/// If the type specified is NULL, it will make a 'void *'.
llvm::Value* constant_ptr(void* p, llvm::PointerType* type = NULL);
/// Return an llvm::Value holding the given string constant.
/// Return an llvm::Value holding the given string constant (as
/// determined by the ustring_rep).
llvm::Value* constant(ustring s);
llvm::Value* constant(string_view s) { return constant(ustring(s)); }
@@ -735,19 +735,23 @@ public:
/// Cast the pointer variable specified by val to the kind of pointer
/// described by type (as an llvm pointer type).
llvm::Value* ptr_cast(llvm::Value* val, llvm::Type* type);
llvm::Value* ptr_cast(llvm::Value* val, llvm::PointerType* type)
llvm::Value* ptr_cast(llvm::Value* val, llvm::Type* type,
const std::string& llname = {});
llvm::Value* ptr_cast(llvm::Value* val, llvm::PointerType* type,
const std::string& llname = {})
{
return ptr_cast(val, (llvm::Type*)type);
return ptr_cast(val, (llvm::Type*)type, llname);
}
/// Cast the pointer variable specified by val to a pointer to the type
/// described by type (as an llvm data type).
llvm::Value* ptr_to_cast(llvm::Value* val, llvm::Type* type);
llvm::Value* ptr_to_cast(llvm::Value* val, llvm::Type* type,
const std::string& llname = {});
/// Cast the pointer variable specified by val to a pointer to the given
/// data type, return the llvm::Value of the new pointer.
llvm::Value* ptr_cast(llvm::Value* val, const OIIO::TypeDesc& type);
llvm::Value* ptr_cast(llvm::Value* val, const OIIO::TypeDesc& type,
const std::string& llname = {});
llvm::Value* wide_ptr_cast(llvm::Value* val, const OIIO::TypeDesc& type);
@@ -757,7 +761,7 @@ public:
/// Cast the pointer variable specified by val to a pointer of type
/// void* return the llvm::Value of the new pointer.
llvm::Value* void_ptr(llvm::Value* val);
llvm::Value* void_ptr(llvm::Value* val, const std::string& llname = {});
/// Generate a pointer that is (ptrtype)((char *)ptr + offset).
/// If ptrtype is NULL, just return a void*.
@@ -865,9 +869,10 @@ public:
/// Dereference a pointer: return *ptr
/// type is the type of the thing being pointed to.
llvm::Value* op_load(llvm::Type* type, llvm::Value* ptr);
llvm::Value* op_load(llvm::Type* type, llvm::Value* ptr,
const std::string& llname = {});
// Blind pointer version that's deprecated as of LLVM13:
llvm::Value* op_load(llvm::Value* ptr);
llvm::Value* op_load(llvm::Value* ptr, const std::string& llname = {});
llvm::Value* op_gather(llvm::Value* ptr, llvm::Value* index);
@@ -898,24 +903,30 @@ public:
/// llvm::Value, which can be generated from either a constant or a
/// runtime-computed integer element index. `type` is the type of the data
/// we're retrieving.
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, llvm::Value* elem);
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, llvm::Value* elem,
const std::string& llname = {});
// Blind pointer version that's deprecated as of LLVM13:
llvm::Value* GEP(llvm::Value* ptr, llvm::Value* elem);
llvm::Value* GEP(llvm::Value* ptr, llvm::Value* elem,
const std::string& llname = {});
/// Generate a GEP (get element pointer) with an integer element
/// offset. `type` is the type of the data we're retrieving.
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, int elem);
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, int elem,
const std::string& llname = {});
// Blind pointer version that's deprecated as of LLVM13:
llvm::Value* GEP(llvm::Value* ptr, int elem);
llvm::Value* GEP(llvm::Value* ptr, int elem,
const std::string& llname = {});
/// Generate a GEP (get element pointer) with two integer element
/// offsets. This is just a special (and common) case of GEP where
/// we have a 2-level hierarchy and we have fixed element indices
/// that are known at compile time. `type` is the type of the data we're
/// retrieving.
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, int elem1, int elem2);
llvm::Value* GEP(llvm::Type* type, llvm::Value* ptr, int elem1, int elem2,
const std::string& llname = {});
// Blind pointer version that's deprecated as of LLVM13:
llvm::Value* GEP(llvm::Value* ptr, int elem1, int elem2);
llvm::Value* GEP(llvm::Value* ptr, int elem1, int elem2,
const std::string& llname = {});
// Arithmetic ops. It auto-detects the type (int vs float).
// ...
@@ -1009,9 +1020,10 @@ private:
IRBuilder& builder();
int m_debug;
bool m_dumpasm = false;
bool m_jit_fma = false;
bool m_jit_aggressive = false;
bool m_dumpasm = false;
bool m_jit_fma = false;
bool m_jit_aggressive = false;
UstringRep m_ustring_rep = UstringRep::charptr;
PerThreadInfo::Impl* m_thread;
llvm::LLVMContext* m_llvm_context;
llvm::Module* m_llvm_module;
@@ -1027,6 +1039,9 @@ private:
std::vector<llvm::BasicBlock*> m_loop_after_block; // stack for break
std::vector<llvm::BasicBlock*> m_loop_step_block; // stack for continue
// Incrementing serial numbers
int m_next_serial_bb = 0;
llvm::Type* m_llvm_type_float;
llvm::Type* m_llvm_type_double;
llvm::Type* m_llvm_type_int;
@@ -1039,8 +1054,8 @@ private:
llvm::Type* m_llvm_type_void;
llvm::Type* m_llvm_type_triple;
llvm::Type* m_llvm_type_matrix;
llvm::Type* m_llvm_type_ustring;
llvm::PointerType* m_llvm_type_void_ptr;
llvm::PointerType* m_llvm_type_ustring_ptr;
llvm::PointerType* m_llvm_type_char_ptr;
llvm::PointerType* m_llvm_type_bool_ptr;
llvm::PointerType* m_llvm_type_int_ptr;
@@ -1049,6 +1064,7 @@ private:
llvm::PointerType* m_llvm_type_triple_ptr;
llvm::PointerType* m_llvm_type_matrix_ptr;
llvm::PointerType* m_llvm_type_double_ptr;
llvm::PointerType* m_llvm_type_ustring_ptr;
int m_vector_width;
llvm::Type* m_llvm_type_wide_float;
@@ -1060,11 +1076,12 @@ private:
llvm::Type* m_llvm_type_wide_triple;
llvm::Type* m_llvm_type_wide_matrix;
llvm::Type* m_llvm_type_wide_void_ptr;
llvm::Type* m_llvm_type_wide_ustring_ptr;
llvm::Type* m_llvm_type_wide_ustring;
llvm::PointerType* m_llvm_type_wide_char_ptr;
llvm::PointerType* m_llvm_type_wide_int_ptr;
llvm::PointerType* m_llvm_type_wide_bool_ptr;
llvm::PointerType* m_llvm_type_wide_float_ptr;
llvm::PointerType* m_llvm_type_wide_ustring_ptr;
llvm::Type* m_llvm_type_native_mask;
bool m_supports_masked_stores = false;
+38 -10
View File
@@ -4,7 +4,6 @@
#pragma once
#include <immintrin.h>
#include <type_traits>
#include <OSL/oslconfig.h>
@@ -23,6 +22,8 @@ using std::countr_zero;
#elif OSL_INTEL_CLASSIC_COMPILER_VERSION
#include <immintrin.h>
OSL_FORCEINLINE int popcount(uint32_t x) noexcept { return _mm_popcnt_u32(x);}
OSL_FORCEINLINE int popcount(uint64_t x) noexcept { return _mm_popcnt_u64(x); }
OSL_FORCEINLINE int countr_zero(uint32_t x) noexcept { return _bit_scan_forward(x); }
@@ -170,13 +171,22 @@ public:
}
OSL_FORCEINLINE ValueType value() const { return m_value; }
OSL_FORCEINLINE ValueType value() const
{
return m_value;
}
// count number of active bits
OSL_FORCEINLINE int count() const { return OSL::popcount(m_value); }
OSL_FORCEINLINE int count() const
{
return OSL::popcount(m_value);
}
// NOTE: undefined result if no bits are on
OSL_FORCEINLINE int first_on() const { return OSL::countr_zero(m_value); }
OSL_FORCEINLINE int first_on() const
{
return OSL::countr_zero(m_value);
}
OSL_FORCEINLINE Mask invert() const
{
@@ -229,7 +239,10 @@ public:
return (m_value != static_cast<ValueType>(0));
}
OSL_FORCEINLINE bool any_off() const { return (m_value < valid_bits); }
OSL_FORCEINLINE bool any_off() const
{
return (m_value < valid_bits);
}
OSL_FORCEINLINE bool any_off(const Mask& mask) const
{
@@ -244,27 +257,39 @@ public:
// So really only set_on or set_off is required
// Choose to not provide a generic set(int lane, bool flag)
OSL_FORCEINLINE void set_on(int lane) { m_value |= (1 << lane); }
OSL_FORCEINLINE void set_on(int lane)
{
m_value |= (1 << lane);
}
OSL_FORCEINLINE void set_on_if(int lane, bool cond)
{
m_value |= (cond << lane);
}
OSL_FORCEINLINE void set_all_on() { m_value = valid_bits; }
OSL_FORCEINLINE void set_all_on()
{
m_value = valid_bits;
}
OSL_FORCEINLINE void set_count_on(int count)
{
m_value = valid_bits >> (width - count);
}
OSL_FORCEINLINE void set_off(int lane) { m_value &= (~(1 << lane)); }
OSL_FORCEINLINE void set_off(int lane)
{
m_value &= (~(1 << lane));
}
OSL_FORCEINLINE void set_off_if(int lane, bool cond)
{
m_value &= (~(cond << lane));
}
OSL_FORCEINLINE void set_all_off() { m_value = static_cast<ValueType>(0); }
OSL_FORCEINLINE void set_all_off()
{
m_value = static_cast<ValueType>(0);
}
OSL_FORCEINLINE bool operator==(const Mask& other) const
{
@@ -298,7 +323,10 @@ public:
return Mask(m_value | other.m_value);
}
OSL_FORCEINLINE Mask operator~() const { return invert(); }
OSL_FORCEINLINE Mask operator~() const
{
return invert();
}
template<int MinOccupancyT, int MaxOccupancyT = width, typename FunctorT>
+8 -2
View File
@@ -109,8 +109,14 @@ OSL_ALIGNAS(16) ClosureComponent : public ClosureColor
Vec3 w; ///< Weight of this component
/// Handy method for getting the parameter memory as a void*.
OSL_HOSTDEVICE void* data() { return (char*)(this + 1); }
OSL_HOSTDEVICE const void* data() const { return (const char*)(this + 1); }
OSL_HOSTDEVICE void* data()
{
return (char*)(this + 1);
}
OSL_HOSTDEVICE const void* data() const
{
return (const char*)(this + 1);
}
/// Handy methods for extracting the underlying parameters as a struct
template<typename T> OSL_HOSTDEVICE const T* as() const
+149 -3
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.
@@ -102,7 +105,7 @@ using OIIO::TextureOpt;
// And some other things we borrow from OIIO...
using OIIO::ErrorHandler;
using OIIO::ustring;
using OIIO::ustringHash;
using OIIO::ustringhash;
using OIIO::string_view;
using OIIO::span;
using OIIO::cspan;
@@ -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
};
@@ -225,3 +324,50 @@ using ConstIndex = std::integral_constant<int, N>;
OSL_NAMESPACE_EXIT
namespace std { // not necessary in C++17, then we can just say std::hash
#ifndef OIIO_USTRING_HAS_STDHASH
// Not a new enough OIIO to define std::hash<ustring>, so we'll do it.
// 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(); }
};
template<> struct hash<OSL::ustringhash> {
OSL_HOSTDEVICE constexpr std::size_t
operator()(OSL::ustringhash u) const noexcept
{
return u.hash();
}
};
#endif
// Not necessary once minimum OIIO defines operator< for ustringhash.
// 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
{
return u.hash() < v.hash();
}
};
} // 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
+143 -23
View File
@@ -50,7 +50,7 @@ namespace pvt {
class ShadingSystemImpl;
}
#if defined(__CUDA_ARCH__) && OPTIX_VERSION >= 70000
#ifdef __CUDA_ARCH__
# define STRING_PARAMS(x) UStringHash::Hash(__OSL_STRINGIFY(x))
#else
# define STRING_PARAMS(x) StringParams::x
@@ -58,11 +58,7 @@ class ShadingSystemImpl;
namespace Strings {
#ifdef __CUDA_ARCH__
# if OPTIX_VERSION >= 70000
# define STRDECL(str, var_name)
# else
# define STRDECL(str, var_name) extern __device__ ustring var_name;
# endif
# define STRDECL(str, var_name)
#else
// Any strings referenced inside of a libsoslexec/wide/*.cpp
// or liboslnoise/wide/*.cpp will need OSLEXECPUBLIC
@@ -115,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,
@@ -177,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,
@@ -204,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.
@@ -235,8 +293,7 @@ public:
/// for debugging. (0)
/// int llvm_dumpasm Print the CPU assembly code from the JIT (0)
/// string llvm_prune_ir_strategy Strategy for pruning unnecessary
/// IR (choices: "prune" [default],
/// "internalize", or "none").
/// IR (choices: "prune" [default], or "none").
/// int max_local_mem_KB Error if shader group needs more than this
/// much local storage to execute (1024K)
/// string debug_groupname Name of shader group -- debug only this one
@@ -432,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.
@@ -448,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!
@@ -535,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)
{
@@ -594,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.
@@ -633,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
@@ -677,6 +788,15 @@ public:
ShaderGlobals& globals, void* userdata_base_ptr,
void* output_base_ptr, bool run = true);
/// Future execute signature that will be range based. Shader globals will be
/// obtained from renderer services.
#if 0 // TODO in future PR
bool execute(ShadingContext& ctx, ShaderGroup& group, OpaqueShadingStateUniformPtr ssu,
int shadeindex_begin_at, int shadeindex_end_before
void* userdata_base_ptr,
void* output_base_ptr, bool run = true);
#endif
// DEPRECATED(2.0): no shadeindex or base pointers
bool execute(ShadingContext& ctx, ShaderGroup& group,
ShaderGlobals& globals, bool run = true)
+318 -311
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -61,7 +61,7 @@ class OSOReaderQuery; // Just so OSLQuery can friend OSLReaderQuery
/// ~~~
///
/// And the `Parameter` structure will hold all the information you need
/// about that paramter. For example:
/// about that parameter. For example:
///
/// ~~~
/// std::cout << "Parameter " << p->name
@@ -123,7 +123,7 @@ public:
}
///< Construct an OSLQuery and open a compiled shader from a disk file.
/// The `shadername` may be either the name of the `.oso` file, or the
/// name of the shader. The optional `searchpath` paramter gives a
/// name of the shader. The optional `searchpath` parameter gives a
/// colon-separated list of directories to search for compiled shaders.
OSL_DEPRECATED("Use ShadingSystem::oslquery(group,layernum)")
+70 -4
View File
@@ -18,10 +18,14 @@
#pragma once
#include <cstring>
#include <memory>
#include <OSL/oslversion.h>
#if defined(__x86_64__) && !defined(__CUDA_ARCH__)
# include <x86intrin.h>
#endif
/////////////////////////////////////////////////////////////////////////
// Detect which compiler and version we're using
@@ -482,15 +486,77 @@
# define OSL_DASSERT_MSG(x, ...) ((void)sizeof(x)) /*NOLINT*/
#endif
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
#define OSL_STACK_ARRAY(TYPE, NAME, DYNAMIC_COUNT) TYPE * NAME = reinterpret_cast<TYPE *>(alloca(sizeof(TYPE)*(DYNAMIC_COUNT)))
/// OSL_ALLOCA is used to allocate smallish amount of memory on the stack,
/// equivalent of C99 type var_name[size].
///
/// NOTE: in a debug build, this will assert for allocations >= 1MB, which is
/// much too big. Hopefully this will keep us from abusing alloca and having
/// stack overflows. The rule of thumb is that it's ok to use alloca for small
/// things of bounded size, but not for anything that could be arbitrarily
/// big, which should instead use heap allocation.
#if defined(__GNUC__)
# define OSL_ALLOCA(type, size) (assert(size < (1<<20)), (size) != 0 ? (reinterpret_cast<type*>(__builtin_alloca((size) * sizeof(type)))) : nullptr)
#else
// Utilize variable length array compiler extension when available
#define OSL_STACK_ARRAY(TYPE, NAME, DYNAMIC_COUNT) TYPE NAME[DYNAMIC_COUNT]
# define OSL_ALLOCA(type, size) (assert(size < (1<<20)), (size) != 0 ? (reinterpret_cast<type*>(alloca((size) * sizeof(type)))) : nullptr)
#endif
OSL_NAMESPACE_ENTER
/// Standards-compliant bit cast of two equally sized types. This is used
/// equivalently to C++20 std::bit_cast, but it works prior to C++20 and
/// it has the right decorators to work with Cuda.
/// @version 1.13.2
template <typename To, typename From>
OSL_FORCEINLINE OSL_HOSTDEVICE To bitcast(const From& src) noexcept {
// NOTE: this is the only standards compliant way of doing this type of casting,
// luckily the compilers we care about know how to optimize away this idiom.
static_assert(sizeof(From) == sizeof(To),
"bit_cast must be between objects of the same size");
To dst;
memcpy((void*)&dst, &src, sizeof(From));
return dst;
}
#if 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
+150 -133
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,47 +385,60 @@ 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;
/// Register a string with the renderer, so that the renderer can arrange
/// to make the string available in GPU memory as needed. Optionally specify
/// a variable name to associate with the string value.
virtual uint64_t register_string (const std::string& str,
const std::string& var_name)
/// 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 uint64_t register_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 0;
// Note: for an OptiX-based renderer, this method should be overriden
// with something like:
//
// cudaFree(ptr);
}
virtual bool fetch_global (const std::string& var_name,
uint64_t* value)
/// 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 false;
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 {
int anisotropic;
@@ -435,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
};
+2 -2
View File
@@ -145,7 +145,7 @@ namespace sfm
//return static_cast<int>(rintf(x));
return rintf(x);
#else
// emulate rounding by adding/substracting 0.5
// emulate rounding by adding/subtracting 0.5
return static_cast<int>(x + copysignf(0.5f, x));
// Other possible factorings
@@ -441,7 +441,7 @@ namespace sfm
// Considering having functionally equivalent versions of Vec3, Color3, Matrix44
// with slight modifications to inlining and implementation to avoid aliasing and
// improve likelyhood of proper privation of local variables within a SIMD loop
// improve likelihood of proper privation of local variables within a SIMD loop
} // namespace sfm
+4
View File
@@ -17,6 +17,9 @@ class RendererServices;
/// coordinate transformation.
typedef const void* TransformationPtr;
/// Type for an opaque pointer to whatever the Shading System uses to represent
/// Uniform State.
typedef const void* OpaqueShadingStateUniformPtr;
/// The ShaderGlobals structure represents the state describing a particular
@@ -83,6 +86,7 @@ struct ShaderGlobals {
/// Back-pointer to the ShadingContext (set and used by OSL itself --
/// renderers shouldn't mess with this at all).
ShadingContext* context;
OpaqueShadingStateUniformPtr shadingStateUniform;
/// Pointer to the RendererServices object. This is how OSL finds its
/// way back to the renderer for callbacks.
+123 -26
View File
@@ -194,17 +194,17 @@ template<int WidthT> struct alignas(WidthT * sizeof(float)) VecReg {
};
static_assert(std::alignment_of<VecReg<16>>::value == 64,
"Unexepected alignment");
"Unexpected alignment");
static_assert(std::alignment_of<VecReg<8>>::value == 32,
"Unexepected alignment");
"Unexpected alignment");
static_assert(std::alignment_of<VecReg<4>>::value == 16,
"Unexepected alignment");
"Unexpected alignment");
static_assert(std::alignment_of<VecReg<16>>::value == VecReg<16>::alignment,
"Unexepected alignment");
"Unexpected alignment");
static_assert(std::alignment_of<VecReg<8>>::value == VecReg<8>::alignment,
"Unexepected alignment");
"Unexpected alignment");
static_assert(std::alignment_of<VecReg<4>>::value == VecReg<4>::alignment,
"Unexepected alignment");
"Unexpected alignment");
template<typename BuiltinT, int WidthT>
@@ -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;
@@ -1535,7 +1589,7 @@ assume_aligned(Block<DataT, WidthT>* block_ptr)
{
static_assert(std::alignment_of<Block<DataT, WidthT>>::value
== std::alignment_of<VecReg<WidthT>>::value,
"Unexepected alignment");
"Unexpected alignment");
return assume_aligned<VecReg<WidthT>::alignment>(block_ptr);
}
@@ -1545,7 +1599,7 @@ assume_aligned(const Block<DataT, WidthT>* block_ptr)
{
static_assert(std::alignment_of<Block<DataT, WidthT>>::value
== std::alignment_of<VecReg<WidthT>>::value,
"Unexepected alignment");
"Unexpected alignment");
return assume_aligned<VecReg<WidthT>::alignment>(block_ptr);
}
@@ -2089,7 +2143,7 @@ struct UniformAsWide : public pvt::UniformAsWideImpl<DataT, WidthT> {
template<typename DataT>
struct WideTraits; // undefined, all types used should be specialized
//{
//static bool mathes(const TypeDesc &) { return false; }
//static bool matches(const TypeDesc &) { return false; }
//};
template<> struct WideTraits<float> {
@@ -2128,7 +2182,7 @@ template<> struct WideTraits<ustring> {
}
};
// We let Vec3 match any vector semantics as we don't have a seperate Point or Normal classes
// We let Vec3 match any vector semantics as we don't have a separate Point or Normal classes
template<> struct WideTraits<Vec3> {
static bool matches(const TypeDesc& type_desc)
{
@@ -2229,9 +2283,15 @@ template<typename DataT, int WidthT> struct MaskedLaneProxy {
// visibility to end user whose IDE
// might display these methods vs. free
// functions
OSL_FORCEINLINE bool is_on() const { return m_mask.is_on(m_lane); }
OSL_FORCEINLINE bool is_on() const
{
return m_mask.is_on(m_lane);
}
OSL_FORCEINLINE bool is_off() const { return m_mask.is_off(m_lane); }
OSL_FORCEINLINE bool is_off() const
{
return m_mask.is_off(m_lane);
}
private:
Block<DataT, WidthT>& m_ref_wide_data;
@@ -2293,9 +2353,15 @@ struct MaskedArrayLaneProxy {
// visibility to end user whose IDE
// might display these methods vs. free
// functions
OSL_FORCEINLINE bool is_on() const { return m_mask.is_on(m_lane); }
OSL_FORCEINLINE bool is_on() const
{
return m_mask.is_on(m_lane);
}
OSL_FORCEINLINE bool is_off() const { return m_mask.is_off(m_lane); }
OSL_FORCEINLINE bool is_off() const
{
return m_mask.is_off(m_lane);
}
OSL_FORCEINLINE MaskedLaneProxy<DataT, WidthT>
operator[](int array_index) const
@@ -2727,19 +2793,24 @@ foreach_unique(Wide<DataT, WidthT> wdata, Mask<WidthT> data_mask, FunctorT f)
do {
ActiveLane lead_lane(remaining_mask.first_on());
DataT lead_data = wdata[lead_lane];
Mask<WidthT> matching_lanes(false);
// Use int instead of Mask<> to allow reduction clause in openmp simd declaration
int matching_lanes_bits { 0 };
OSL_FORCEINLINE_BLOCK
{
OSL_OMP_PRAGMA(omp simd simdlen(WidthT))
OSL_OMP_PRAGMA(omp simd simdlen(WidthT)
reduction(|
: matching_lanes_bits))
for (int lane = 0; lane < WidthT; ++lane) {
// NOTE: the comparison ignores the remaining_mask
bool lane_matches = (lead_data == wdata[lane]);
// NOTE: using bitwise & to avoid branches
if (lane_matches & remaining_mask[lane]) {
matching_lanes.set_on(lane);
// inline of Mask::set_on(lane)
matching_lanes_bits |= 1 << lane;
}
}
}
Mask<WidthT> matching_lanes { matching_lanes_bits };
f(lead_data, matching_lanes);
remaining_mask &= ~matching_lanes;
@@ -2828,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;
@@ -2846,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;
};
@@ -3361,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
@@ -3376,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);
}
}
}
+11 -11
View File
@@ -19,7 +19,7 @@ namespace __OSL_WIDE_PVT {
OSL_USING_DATA_WIDTH(__OSL_WIDTH)
// Foward declaration, implementation is in liboslnoise/wide_gabornoise.h
// Forward declaration, implementation is in liboslnoise/wide_gabornoise.h
struct DisabledFilterPolicy {
static constexpr bool active = false;
};
@@ -34,7 +34,7 @@ OSL_NOINLINE void
wide_gabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
NoiseParams const* opt, Block<Vec3>* opt_varying_direction);
// Foward declaration, implementation is in wide_gabor.h
// Forward declaration, implementation is in wide_gabor.h
template<int AnisotropicT, typename FilterPolicyT>
OSL_NOINLINE void
wide_gabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
@@ -46,20 +46,20 @@ OSL_NOINLINE void
wide_gabor(Masked<Dual2<float>> wResult, Wide<const Dual2<Vec3>> wP,
NoiseParams const* opt, Block<Vec3>* opt_varying_direction);
// Foward declaration, implementation is in wide_gabor.h
// Forward declaration, implementation is in wide_gabor.h
template<int AnisotropicT, typename FilterPolicyT>
OSL_NOINLINE void
wide_gabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
NoiseParams const* opt, Block<Vec3>* opt_varying_direction);
// Foward declaration, implementation is in wide_gabor.h
// Forward declaration, implementation is in wide_gabor.h
template<int AnisotropicT, typename FilterPolicyT>
OSL_NOINLINE void
wide_gabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
Wide<const Dual2<float>> wY, NoiseParams const* opt,
Block<Vec3>* opt_varying_direction);
// Foward declaration, implementation is in wide_gabor.h
// Forward declaration, implementation is in wide_gabor.h
template<int AnisotropicT, typename FilterPolicyT>
OSL_NOINLINE void
wide_gabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<Vec3>> wP,
@@ -71,14 +71,14 @@ wide_gabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<Vec3>> wP,
// Periodic gabor(s)
//////////////////////////////////////////////////////////////
// Foward declaration, implementation is in wide_gabor.h
// Forward declaration, implementation is in wide_gabor.h
template<int AnisotropicT, typename FilterPolicyT>
OSL_NOINLINE void
wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
Wide<const float> wXp, NoiseParams const* opt,
Block<Vec3>* opt_varying_direction);
// Foward declaration, implementation is in wide_gabor.h
// Forward declaration, implementation is in wide_gabor.h
template<int AnisotropicT, typename FilterPolicyT>
OSL_NOINLINE void
wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
@@ -86,7 +86,7 @@ wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<float>> wX,
Wide<const float> wYp, NoiseParams const* opt,
Block<Vec3>* opt_varying_direction);
// Foward declaration, implementation is in wide_gabor.h
// Forward declaration, implementation is in wide_gabor.h
template<int AnisotropicT, typename FilterPolicyT>
OSL_NOINLINE void
wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<Vec3>> wP,
@@ -95,14 +95,14 @@ wide_pgabor(Masked<Dual2<float>> wResult, Wide<const Dual2<Vec3>> wP,
// Foward declaration, implementation is in wide_gabor.h
// Forward declaration, implementation is in wide_gabor.h
template<int AnisotropicT, typename FilterPolicyT>
OSL_NOINLINE void
wide_pgabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
Wide<const float> wXp, NoiseParams const* opt,
Block<Vec3>* opt_varying_direction);
// Foward declaration, implementation is in wide_gabor.h
// Forward declaration, implementation is in wide_gabor.h
template<int AnisotropicT, typename FilterPolicyT>
OSL_NOINLINE void
wide_pgabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
@@ -110,7 +110,7 @@ wide_pgabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<float>> wX,
Wide<const float> wYp, NoiseParams const* opt,
Block<Vec3>* opt_varying_direction);
// Foward declaration, implementation is in wide_gabor.h
// Forward declaration, implementation is in wide_gabor.h
template<int AnisotropicT, typename FilterPolicyT>
OSL_NOINLINE void
wide_pgabor3(Masked<Dual2<Vec3>> wResult, Wide<const Dual2<Vec3>> wP,
+20 -10
View File
@@ -5,25 +5,31 @@
#pragma once
#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
# define NOMINMAX
# endif
# if (OPTIX_VERSION < 70000)
# include <optix_world.h>
# endif
#else
# include <stdlib.h>
#endif
#include <OSL/device_ptr.h>
#if !OSL_USE_OPTIX && !defined(__CUDA_ARCH__)
using CUdeviceptr = void*;
using float3 = OSL::Vec3;
#endif
OSL_NAMESPACE_ENTER
#ifdef OSL_USE_OPTIX
#if OSL_USE_OPTIX
////////////////////////////////////////////////////////////////////////
// If OptiX is available, alias everything in optix:: namespace into
@@ -31,14 +37,12 @@ OSL_NAMESPACE_ENTER
// TODO clean this up once OptiX6 support is dropped
# if (OPTIX_VERSION < 70000)
namespace optix = ::optix;
# else
namespace optix {
typedef OptixDeviceContext Context;
typedef cudaTextureObject_t TextureSampler;
using ::CUdeviceptr;
using ::float3;
} // namespace optix
# endif
using ::cudaFree;
using ::cudaMalloc;
@@ -49,13 +53,19 @@ using ::cudaMalloc;
////////////////////////////////////////////////////////////////////////
// If OptiX is not available, make reasonable proxies just so that we
// don't have to litter the code with quite as many #ifdef's.
// OSL::optix::
// Mostly under OSL::optix::
namespace optix {
typedef void* Context;
typedef void* Program;
typedef void* TextureSampler;
typedef void* CUdeviceptr;
using float3 = OSL::Vec3;
struct Exception {
static const char* what() { return "OSL compiled without Optix."; }
};
+261 -61
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)
@@ -558,7 +561,7 @@ public:
///
void scope(int s) { m_scope = s; }
/// Return teh AST node containing the declaration of this symbol.
/// Return the AST node containing the declaration of this symbol.
/// Use with care!
ASTNode* node() const { return m_node; }
@@ -629,59 +632,148 @@ public:
OSL_ASSERT(arena == SymArena::Absolute);
m_arena = static_cast<unsigned int>(arena);
m_data = ptr;
// m_dataoffset = static_cast<int64_t>((char*)ptr - (char*)0);
}
/// Specify the location of the symbol's data, relative to an arena
/// (which for now must be Absolute).
void set_dataptr(SymArena arena, void* ptr, int offset)
{
// OSL_ASSERT(arena == SymArena::Absolute);
m_arena = static_cast<unsigned int>(arena);
m_data = ptr;
m_dataoffset = offset;
OSL::print("setting sym {} arena {} offset {}\n", name(), int(m_arena),
m_dataoffset);
}
void dataoffset(int d) { m_dataoffset = d; }
int dataoffset() const { return m_dataoffset; }
void dataoffset(int d)
{
m_dataoffset = d;
}
int dataoffset() const
{
return m_dataoffset;
}
void wide_dataoffset(int d) { m_wide_dataoffset = d; }
int wide_dataoffset() const { return m_wide_dataoffset; }
void wide_dataoffset(int d)
{
m_wide_dataoffset = d;
}
int wide_dataoffset() const
{
return m_wide_dataoffset;
}
SymArena arena() const { return static_cast<SymArena>(m_arena); }
SymArena arena() const
{
return static_cast<SymArena>(m_arena);
}
void initializers(int d) { m_initializers = d; }
int initializers() const { return m_initializers; }
void initializers(int d)
{
m_initializers = d;
}
int initializers() const
{
return m_initializers;
}
bool has_derivs() const { return m_has_derivs; }
void has_derivs(bool new_derivs) { m_has_derivs = new_derivs; }
int size() const { return m_size; }
void size(size_t newsize) { m_size = (int)newsize; }
bool has_derivs() const
{
return m_has_derivs;
}
void has_derivs(bool new_derivs)
{
m_has_derivs = new_derivs;
}
int size() const
{
return m_size;
}
void size(size_t newsize)
{
m_size = (int)newsize;
}
/// Return the size for each point, including derivs.
///
int derivsize() const { return m_has_derivs ? 3 * m_size : m_size; }
int derivsize() const
{
return m_has_derivs ? 3 * m_size : m_size;
}
bool connected() const { return valuesource() == ConnectedVal; }
bool connected_down() const { return m_connected_down; }
void connected_down(bool c) { m_connected_down = c; }
bool connected() const
{
return valuesource() == ConnectedVal;
}
bool connected_down() const
{
return m_connected_down;
}
void connected_down(bool c)
{
m_connected_down = c;
}
/// Where did the symbol's value come from?
///
enum ValueSource { DefaultVal, InstanceVal, GeomVal, ConnectedVal };
ValueSource valuesource() const { return (ValueSource)m_valuesource; }
void valuesource(ValueSource v) { m_valuesource = v; }
ValueSource valuesource() const
{
return (ValueSource)m_valuesource;
}
void valuesource(ValueSource v)
{
m_valuesource = v;
}
const char* valuesourcename() const;
static const char* valuesourcename(ValueSource v);
int fieldid() const { return m_fieldid; }
void fieldid(int id) { m_fieldid = id; }
int fieldid() const
{
return m_fieldid;
}
void fieldid(int id)
{
m_fieldid = id;
}
int layer() const { return m_layer; }
void layer(int id) { m_layer = id; }
int layer() const
{
return m_layer;
}
void layer(int id)
{
m_layer = id;
}
int initbegin() const { return m_initbegin; }
void initbegin(int i) { m_initbegin = i; }
int initend() const { return m_initend; }
void initend(int i) { m_initend = i; }
int initbegin() const
{
return m_initbegin;
}
void initbegin(int i)
{
m_initbegin = i;
}
int initend() const
{
return m_initend;
}
void initend(int i)
{
m_initend = i;
}
void set_initrange(int b = 0, int e = 0)
{
m_initbegin = b;
m_initend = e;
}
bool has_init_ops() const { return m_initbegin != m_initend; }
bool has_init_ops() const
{
return m_initbegin != m_initend;
}
/// Clear read/write usage info.
///
@@ -725,15 +817,42 @@ public:
}
}
int firstread() const { return m_firstread; }
int lastread() const { return m_lastread; }
int firstwrite() const { return m_firstwrite; }
int lastwrite() const { return m_lastwrite; }
int firstuse() const { return std::min(firstread(), firstwrite()); }
int lastuse() const { return std::max(lastread(), lastwrite()); }
bool everread() const { return lastread() >= 0; }
bool everwritten() const { return lastwrite() >= 0; }
bool everused() const { return everread() || everwritten(); }
int firstread() const
{
return m_firstread;
}
int lastread() const
{
return m_lastread;
}
int firstwrite() const
{
return m_firstwrite;
}
int lastwrite() const
{
return m_lastwrite;
}
int firstuse() const
{
return std::min(firstread(), firstwrite());
}
int lastuse() const
{
return std::max(lastread(), lastwrite());
}
bool everread() const
{
return lastread() >= 0;
}
bool everwritten() const
{
return lastwrite() >= 0;
}
bool everused() const
{
return everread() || everwritten();
}
// everused_in_group is an even more stringent test -- not only must
// the symbol not be used within the shader but it also must not be
// used elsewhere in the group, by being connected to something downstream
@@ -754,31 +873,92 @@ public:
m_lastwrite = last;
}
bool initialized() const { return m_initialized; }
void initialized(bool init) { m_initialized = init; }
bool initialized() const
{
return m_initialized;
}
void initialized(bool init)
{
m_initialized = init;
}
bool lockgeom() const { return m_lockgeom; }
void lockgeom(bool lock) { m_lockgeom = lock; }
bool lockgeom() const
{
// We can lock a value to a constant (at all places on all pieces of
// geometry) if it is neither interpolated nor interactively modified.
return !m_interpolated && !m_interactive;
}
bool allowconnect() const { return m_allowconnect; }
void allowconnect(bool val) { m_allowconnect = val; }
bool interpolated() const
{
return m_interpolated;
}
void interpolated(bool val)
{
m_interpolated = val;
}
int arraylen() const { return m_typespec.arraylength(); }
bool interactive() const
{
return m_interactive;
}
void interactive(bool val)
{
m_interactive = val;
}
bool noninteractive() const
{
return m_noninteractive;
}
void noninteractive(bool val)
{
m_noninteractive = val;
}
bool allowconnect() const
{
return m_allowconnect;
}
void allowconnect(bool val)
{
m_allowconnect = val;
}
int arraylen() const
{
return m_typespec.arraylength();
}
void arraylen(int len)
{
m_typespec.make_array(len);
m_size = m_typespec.simpletype().size();
}
bool renderer_output() const { return m_renderer_output; }
void renderer_output(bool v) { m_renderer_output = v; }
bool renderer_output() const
{
return m_renderer_output;
}
void renderer_output(bool v)
{
m_renderer_output = v;
}
// When not uniform a symbol will have a varying value under batched
// execution and must use a Wide data type to hold different values
// for each data lane executing
bool is_uniform() const { return m_is_uniform; }
bool is_varying() const { return (m_is_uniform == 0); }
void make_varying() { m_is_uniform = false; }
bool is_uniform() const
{
return m_is_uniform;
}
bool is_varying() const
{
return (m_is_uniform == 0);
}
void make_varying()
{
m_is_uniform = false;
}
// Results of a compare_op and other ops with logically boolean
// results under certain conditions could be forced to be represented
@@ -792,14 +972,32 @@ public:
// The value of forced_llvm_bool() is currently only respected during
// batched execution. Forced bools should not be coalesced with regular
// ints, only other forced bools.
bool forced_llvm_bool() const { return m_forced_llvm_bool; }
void forced_llvm_bool(bool v) { m_forced_llvm_bool = v; }
bool forced_llvm_bool() const
{
return m_forced_llvm_bool;
}
void forced_llvm_bool(bool v)
{
m_forced_llvm_bool = v;
}
bool readonly() const { return m_readonly; }
void readonly(bool v) { m_readonly = v; }
bool readonly() const
{
return m_readonly;
}
void readonly(bool v)
{
m_readonly = v;
}
bool is_constant() const { return symtype() == SymTypeConst; }
bool is_temp() const { return symtype() == SymTypeTemp; }
bool is_constant() const
{
return symtype() == SymTypeConst;
}
bool is_temp() const
{
return symtype() == SymTypeTemp;
}
// Retrieve the const float value (must be a const float!)
float get_float(int index = 0) const
@@ -855,7 +1053,7 @@ public:
// Stream output. Note that print/print_vals assume that any string
// values are "raw" and they will be converted to C source code "escaped
// string" notation for printing. For example, a newline characer will
// string" notation for printing. For example, a newline character will
// be rendered into the stream as the two character sequence '\n'.
std::ostream& print(std::ostream& out, int maxvals = 100000000) const;
std::ostream& print_vals(std::ostream& out, int maxvals = 100000000) const;
@@ -869,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
+105 -38
View File
@@ -35,7 +35,7 @@ std::atomic<int> node_counts_peak[ASTNode::_last_node];
class ScopeExit {
public:
typedef std::function<void()> Task;
explicit ScopeExit(Task&& task) : m_task(std::forward<Task>(task)) {}
explicit ScopeExit(Task&& task) : m_task(std::move(task)) {}
~ScopeExit() { m_task(); }
private:
@@ -578,8 +578,14 @@ ASTvariable_declaration::ASTvariable_declaration(OSLCompilerImpl* comp,
if (symtype == SymTypeLocal && Strutil::starts_with(name, "__debug_tmp__"))
symtype = SymTypeTemp;
m_sym = new Symbol(name, type, symtype, this);
if (!m_ismetadata)
if (m_ismetadata) {
// Metadata doesn't go in the symbol table, so we need to retain
// an owning pointer so it doesn't leak.
m_sym_owned.reset(m_sym);
} else {
// Put in the symbol table, after which symtab is the owner
m_compiler->symtab().insert(m_sym);
}
// A struct really makes several subvariables
if (type.is_structure() || type.is_structure_array()) {
@@ -1110,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) {
+8 -3
View File
@@ -375,7 +375,7 @@ protected:
void codegen_initlist(ref init, TypeSpec type, Symbol* sym);
// Special code generation for structure initializers.
// It's in the ASTNode base class because it's used from mutiple
// It's in the ASTNode base class because it's used from multiple
// subclasses.
Symbol* codegen_struct_initializers(ref init, Symbol* sym,
bool is_constructor = false,
@@ -520,7 +520,7 @@ public:
private:
ustring m_name; ///< Name of the symbol (unmangled)
Symbol* m_sym; ///< Ptr to the symbol this declares
Symbol* m_sym; ///< Ptr to the symbol this declares (non-owning)
bool m_isparam; ///< Is this a parameter?
bool m_isoutput; ///< Is this an output parameter?
bool m_ismetadata; ///< Is this declaration a piece of metadata?
@@ -529,6 +529,7 @@ private:
// specific initializers.
typedef std::pair<ustring, ASTNode*> NamedInit;
std::vector<NamedInit> m_struct_field_inits;
std::unique_ptr<Symbol> m_sym_owned; // if we own the symbol
};
@@ -831,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;
@@ -949,7 +954,7 @@ private:
/// return false and call an appropriate error().
bool typecheck_printf_args(const char* format, ASTNode* arg);
/// Handle "funcion calls" that are really struct ctrs.
/// Handle "function calls" that are really struct ctrs.
TypeSpec typecheck_struct_constructor();
/// Is the argument number 'arg' read by the op?
+1 -1
View File
@@ -918,7 +918,7 @@ ASTNode::codegen_initlist(ref init, TypeSpec type, Symbol* sym)
}
if (paraminit) {
// Warn early about struct array paramters.
// Warn early about struct array parameters.
// Handling this will likely need changes to oso format.
if (type.is_structure_array()) {
errorfmt("array of struct are not allowed as parameters");
+4 -3
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");
@@ -1305,7 +1306,7 @@ OSLCompilerImpl::track_variable_dependencies()
// This naivite will never miss a dependency, but it may
// overestimate dependencies. (Hence we call this "conservative"
// rather than "wrong.") We deem this acceptable for now, since
// it's so much easer to implement the conservative dependency
// it's so much easier to implement the conservative dependency
// analysis, and it's not yet clear that getting it closer to
// optimal will have any performance impact on final shaders. Also
// because this is probably no worse than the "dependency slop" that
+1 -1
View File
@@ -490,7 +490,7 @@ private:
int m_main_method_start; ///< Instruction where 'main' starts
bool m_declaring_shader_formals; ///< Are we declaring shader formals?
std::set<std::pair<ustring, int>> m_nowarn_lines; ///< Lines for 'nowarn'
typedef std::unordered_map<ustring, std::string, ustringHash> FCMap;
typedef std::unordered_map<ustring, std::string> FCMap;
FCMap m_filecontents_map; ///< Contents of source files we've seen
ustring m_last_sourcefile; ///< Last filename for retrieve_source
std::string* m_last_filecontents = nullptr; //< Last file contents
+22 -18
View File
@@ -28,6 +28,10 @@
#pragma clang diagnostic ignored "-Wparentheses-equality"
#endif
#if (OSL_CLANG_VERSION >= 150000) || (OSL_INTEL_CLANG_VERSION >= 140000)
#pragma clang diagnostic ignored "-Wunused-but-set-variable"
#endif
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC visibility push(hidden)
#endif
@@ -854,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
@@ -186,7 +186,7 @@ private:
///
class SymbolTable {
public:
typedef std::unordered_map<ustring, Symbol*, ustringHash> ScopeTable;
typedef std::unordered_map<ustring, Symbol*> ScopeTable;
typedef std::vector<ScopeTable> ScopeTableStack;
typedef SymbolPtrVec::iterator iterator;
typedef SymbolPtrVec::const_iterator const_iterator;
+10 -8
View File
@@ -478,7 +478,7 @@ ASTbinary_expression::typecheck(TypeSpec expected)
TypeSpec returntype = m_compiler->type_from_code(code, &advance);
code += advance;
if (code[0] && check_simple_arg(l, code, true) && code[0]
&& check_simple_arg(r, code, true) && !code[0]) {
&& check_simple_arg(r, code, true) && !code[0]) { // NOSONAR
return m_typespec = returntype;
}
}
@@ -618,7 +618,7 @@ ASTternary_expression::typecheck(TypeSpec expected)
errorfmt("Cannot use an array as a condition");
// No arrays
if (t.is_array() || t.is_array()) {
if (t.is_array() || f.is_array()) {
errorfmt("Not allowed: '{} ? {} : {}'", c, t, f);
return TypeSpec();
}
@@ -678,7 +678,7 @@ ASTtype_constructor::typecheck(TypeSpec expected, bool report, bool bind)
if (expected.is_float()) {
patterns = float_patterns;
argexpected = TypeDesc::FLOAT;
// ^^^ Since simetimes tht constructor `float(expr)` is used as a
// ^^^ Since sometimes the constructor `float(expr)` is used as a
// synonym for a cast `(float)expr`, we know that ambiguously typed
// expressions should favor disambiguating to a float.
} else if (expected.is_triple()) {
@@ -762,7 +762,7 @@ public:
~TypeAdjuster()
{
// Commit infered types of all ASTcompound_initializers scanned.
// Commit inferred types of all ASTcompound_initializers scanned.
if (m_success) {
for (auto&& initer : m_adjust) {
ASTcompound_initializer* ciptr = std::get<0>(initer);
@@ -992,9 +992,9 @@ private:
const StructSpec::FieldSpec* field = nullptr)
{
if (node->typecheck(expected) != expected &&
// Alllow assignment with comparable type
// Allow assignment with comparable type
!assignable(expected, node->typespec()) &&
// Alllow closure assignments to '0'
// Allow closure assignments to '0'
!(expected.is_closure() && !node->typespec().is_closure()
&& node->typespec().is_int_or_float()
&& node->nodetype() == literal_node
@@ -1065,6 +1065,8 @@ bool
ASTNode::check_arglist(const char* /*funcname*/, ASTNode::ref arg,
const char* formals, bool coerce, bool bind)
{
if (!formals)
return false;
// std::cerr << "ca " << funcname << " formals='" << formals << "\n";
for (; arg; arg = arg->next()) {
if (!*formals) // More formal args, but no more actual args
@@ -1619,7 +1621,7 @@ class CandidateFunctions {
default:
// TODO: Scoring default function arguments would go here
// Curently an unused formal argument, so no match at all.
// Currently an unused formal argument, so no match at all.
return kNoMatch;
}
OSL_DASSERT(*formals == 0);
@@ -1994,7 +1996,7 @@ ASTfunction_call::typecheck(TypeSpec expected)
any_args_are_compound_initializers = true;
}
// Save the currently choosen symbol for error reporting later
// Save the currently chosen symbol for error reporting later
FunctionSymbol* poly = func();
CandidateFunctions candidates(m_compiler, expected, args(), poly);
+23 -10
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
@@ -209,7 +209,7 @@ macro ( CUDA_SHADEOPS_COMPILE srclist )
DEPENDS ${shadeops_bc_list} ${exec_headers} ${PROJECT_PUBLIC_HEADERS} ${shadeops_srcs}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )
# Serialize the linked bitcode into a CPP file and add it to the list of liboslexec soures
# Serialize the linked bitcode into a CPP file and add it to the list of liboslexec sources
add_custom_command ( OUTPUT ${shadeops_bc_cuda_cpp}
COMMAND ${Python_EXECUTABLE} "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py"
${linked_shadeops_bc} ${shadeops_bc_cuda_cpp} "osl_llvm_compiled_ops_cuda"
@@ -222,14 +222,14 @@ if (USE_LLVM_BITCODE)
set (llvm_ops_srcs llvm_ops.cpp)
EMBED_LLVM_BITCODE_IN_CPP ( "${llvm_ops_srcs}" "_host" "osl_llvm_compiled_ops" lib_src "")
set (rs_dependant_ops_srcs
set (rs_dependent_ops_srcs
opmatrix.cpp
)
# Achieve the effect of absorbing osl_llvm_compiled_ops by adding its
# sources to rs_dependant_ops_srcs which avoids having to do it at runtime.
list (APPEND rs_dependant_ops_srcs ${llvm_ops_srcs})
# sources to rs_dependent_ops_srcs which avoids having to do it at runtime.
list (APPEND rs_dependent_ops_srcs ${llvm_ops_srcs})
EMBED_LLVM_BITCODE_IN_CPP ( "${rs_dependant_ops_srcs}" "_host_rs" "osl_llvm_compiled_rs_dependant_ops" lib_src "")
EMBED_LLVM_BITCODE_IN_CPP ( "${rs_dependent_ops_srcs}" "_host_rs" "osl_llvm_compiled_rs_dependent_ops" lib_src "")
# Optionally repeat the bitcode compilation with CUDA-specific options
if (CUDA_FOUND)
@@ -352,7 +352,7 @@ foreach(batched_target ${BATCHED_TARGET_LIST})
endif ()
if (CMAKE_COMPILER_IS_CLANG OR CMAKE_COMPILER_IS_APPLECLANG)
# REQUIRES CLANG 7+ to use sucessfully vectorize with OpenMP simd
# REQUIRES CLANG 7+ to use successfully vectorize with OpenMP simd
if (${TARGET_OPT_ISA} STREQUAL "AVX512")
list (APPEND TARGET_CXX_OPTS "-march=skylake-avx512")
@@ -370,7 +370,13 @@ foreach(batched_target ${BATCHED_TARGET_LIST})
endif ()
if (${TARGET_OPT_FMA} STREQUAL "noFMA")
list (APPEND TARGET_CXX_OPTS "-mno-fma")
# Do NOT use "-mno-fma" as it may lower ISA to one without any FMA
# instructions (AVX512->AVX2). Our intent is to not generate
# FMA's but still use the available instructions and register
# width. However math library calls may use still end up using
# FMA's, but lets try turning of fused math ops because many OSL
# math functions are from OIIO/IMath headers generate non FMA
list (APPEND TARGET_CXX_OPTS "-ffp-contract=off")
endif ()
# large SIMD function loops will exceed llvm's -inline-threshold default of 225.
@@ -388,7 +394,8 @@ foreach(batched_target ${BATCHED_TARGET_LIST})
list (APPEND TARGET_CXX_OPTS "-fno-unroll-loops")
if (CMAKE_COMPILER_IS_INTELCLANG)
list (APPEND TARGET_CXX_OPTS "-qopenmp-simd")
# utilize Intel compiler's optimized openmp simd generation vs. open source "-qopenmp-simd"
list (APPEND TARGET_CXX_OPTS "-fiopenmp-simd")
else ()
list (APPEND TARGET_CXX_OPTS "-fopenmp")
endif ()
@@ -434,7 +441,13 @@ foreach(batched_target ${BATCHED_TARGET_LIST})
endif ()
if (${TARGET_OPT_FMA} STREQUAL "noFMA")
list (APPEND TARGET_CXX_OPTS "-mno-fma")
# Do NOT use "-mno-fma" as it may lower ISA to one without any FMA
# instructions (AVX512->AVX2). Our intent is to not generate
# FMA's but still use the available instructions and register
# width. However math library calls may use still end up using
# FMA's, but lets try turning of fused math ops because many OSL
# math functions are from OIIO/IMath headers generate non FMA
list (APPEND TARGET_CXX_OPTS "-ffp-contract=off")
endif ()
list (APPEND TARGET_CXX_OPTS "-fopenmp-simd")
+2 -2
View File
@@ -23,7 +23,7 @@ public:
MyAov(const TestPath* test, int id)
{
// Init for the test case array. For each test case set a bool
// in m_expected marking wether this AOV should get some color
// in m_expected marking whether this AOV should get some color
// from that test or not.
for (int i = 0; test[i].path[0]; ++i) { // iterate test cases
m_expected.push_back(false); // false by default
@@ -88,7 +88,7 @@ simulate(Accumulator& accum, const char** events, size_t testno)
int
main()
{
// Some constants to avoid refering to AOV's by number
// Some constants to avoid referring to AOV's by number
const int beauty = 0;
const int diffuse2_3 = 1;
const int light3 = 2;
+1 -1
View File
@@ -138,7 +138,7 @@ NdfAutomata::symbolsFrom(const IntSet& states, SymbolSet& out_symbols,
{
for (IntSet::const_iterator i = states.begin(); i != states.end(); ++i) {
const State* state = m_states[*i];
// For every state we have to go thorugh all the symbols in the transition table
// For every state we have to go through all the symbols in the transition table
// m_symbol_trans and add them to the output
for (SymbolToIntList::const_iterator j = state->m_symbol_trans.begin();
j != state->m_symbol_trans.end(); ++j)
+202 -198
View File
@@ -4,12 +4,12 @@
#pragma once
#include <set>
#include <map>
#include <list>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <OSL/oslconfig.h>
@@ -20,20 +20,21 @@ OSL_NAMESPACE_ENTER
// General container for all symbol sets
// General container for integer sets
typedef std::set<int> IntSet; // probably faster to test for equality, unions and so
typedef std::set<int>
IntSet; // probably faster to test for equality, unions and so
typedef std::unordered_set<ustring, ustringHash> SymbolSet;
typedef std::unordered_set<ustring> SymbolSet;
// This is for the transition table used in DfAutomata::State
typedef std::unordered_map<ustring, int, ustringHash> SymbolToInt;
typedef std::unordered_map<ustring, int> SymbolToInt;
// And this is for the transition table in NdfAutomata which
// has several movements for each symbol
typedef std::unordered_map<ustring, IntSet, ustringHash> SymbolToIntList;
typedef std::unordered_map<ustring, IntSet> SymbolToIntList;
typedef std::unordered_map<int, int> HashIntInt;
// For the rules in the deterministic states, we don't need a real set
// cause when converting from the NDF automata we will never find the same
// rule twice
typedef std::vector<void *> RuleSet;
typedef std::vector<void*> RuleSet;
// The lambda symbol (empty word)
extern ustring lambda;
@@ -45,9 +46,9 @@ extern ustring lambda;
/// any symbol which is not listed in its black list (m_minus).
struct Wildcard {
Wildcard() {};
Wildcard(SymbolSet &minus):m_minus(minus) {};
Wildcard(SymbolSet& minus) : m_minus(minus) {};
bool matches(ustring symbol)const
bool matches(ustring symbol) const
{
// true if the given symbol is not in m_minus
return (m_minus.find(symbol) == m_minus.end());
@@ -63,109 +64,110 @@ struct Wildcard {
/// symbol and allowed lambda transitions too. Light path expressions
/// build this automata easily. It is later converted to a DF automata.
class NdfAutomata {
public:
// Basic state for NDF automata
class State {
friend class NdfAutomata;
public:
// Basic state for NDF automata
class State {
friend class NdfAutomata;
public:
State(int id)
{
m_id = id;
m_wildcard_trans = -1;
m_wildcard = NULL;
m_rule = NULL;
};
~State() { delete m_wildcard; };
/// Get the set of state id's reachable by the given symbol
///
/// It doesn't clean the given result set, so you can use this
/// function to accumulate states.
void getTransitions (ustring symbol, IntSet &out_states)const;
/// Get all the lambda transitions
///
/// Returns the state collection as a pair of iterators [begin, end)
std::pair <IntSet::const_iterator, IntSet::const_iterator>
getLambdaTransitions ()const;
/// Add a standar transition (also valid for lambda)
void addTransition (ustring symbol, State *state);
/// Add a wildcard transition
///
/// Note that the state is going to take ownership of the wildcard
/// pointer. So it should be newly allocated on heap and you don't
/// have to delete ir
void addWildcardTransition(Wildcard *wildcard, State *state);
/// For final states, this sets the associated rule. Which
/// can be any kind of pointer
void setRule(void *rule) { m_rule = rule; };
void *getRule()const { return m_rule; };
int getId()const { return m_id; };
/// For debuging purposes
std::string tostr()const;
protected:
// State id (i.e index in the states vector)
int m_id;
// Transitions by single symbols
SymbolToIntList m_symbol_trans;
// In case m_wildcard is not NULL this holds the destination
// of the wildcard transition
int m_wildcard_trans;
// Wildcard (NULL if no wildcard transition present)
Wildcard *m_wildcard;
// Associated rule for final states, NULL if not final
void *m_rule;
State(int id)
{
m_id = id;
m_wildcard_trans = -1;
m_wildcard = NULL;
m_rule = NULL;
};
~State() { delete m_wildcard; };
NdfAutomata() { newState(); };
~NdfAutomata();
const State *getInitial()const { return m_states[0]; };
State *getInitial() { return m_states[0]; };
/// Creates a new state qith a valid id
State *newState();
const State *getState(int i)const { return m_states[i]; };
size_t size()const { return m_states.size(); };
/// return all the symbols that lead to other states starting
/// in any of the states in the given set. Also if there are
/// wildcard transitions, give back a new wildcard that guarantees
/// that its matches match all the wildcards in the set.
/// So the symbols returned in out_symbols do NOT overlap those that
/// match the returned wildcard (if present). And the union of out_symbols
/// and those matched by the wildcard, are all the valid transitions from
/// the given state set
void symbolsFrom(const IntSet &states, SymbolSet &out_symbols, Wildcard *&wildcard)const;
/// Get the set of states that are reachable from the given state set using the given symbol
void transitionsFrom(const IntSet &states, ustring symbol, IntSet &out_states)const;
/// Get the set of states that are reachable from the given state set by wildcard
void wildcardTransitionsFrom(const IntSet &states, IntSet &out_states)const;
/// Perform a lambda closure of a state set
/// Get the set of state id's reachable by the given symbol
///
/// In other words, complete the given set so it includes all the additional
/// states that are reachable by the lambda symbol
void lambdaClosure(IntSet &states)const;
/// It doesn't clean the given result set, so you can use this
/// function to accumulate states.
void getTransitions(ustring symbol, IntSet& out_states) const;
/// for debuging purposes
std::string tostr()const;
/// Get all the lambda transitions
///
/// Returns the state collection as a pair of iterators [begin, end)
std::pair<IntSet::const_iterator, IntSet::const_iterator>
getLambdaTransitions() const;
/// Add a standard transition (also valid for lambda)
void addTransition(ustring symbol, State* state);
/// Add a wildcard transition
///
/// Note that the state is going to take ownership of the wildcard
/// pointer. So it should be newly allocated on heap and you don't
/// have to delete ir
void addWildcardTransition(Wildcard* wildcard, State* state);
/// For final states, this sets the associated rule. Which
/// can be any kind of pointer
void setRule(void* rule) { m_rule = rule; };
void* getRule() const { return m_rule; };
int getId() const { return m_id; };
/// For debugging purposes
std::string tostr() const;
protected:
/// Vector of states
std::vector<State *> m_states;
// State id (i.e index in the states vector)
int m_id;
// Transitions by single symbols
SymbolToIntList m_symbol_trans;
// In case m_wildcard is not NULL this holds the destination
// of the wildcard transition
int m_wildcard_trans;
// Wildcard (NULL if no wildcard transition present)
Wildcard* m_wildcard;
// Associated rule for final states, NULL if not final
void* m_rule;
};
NdfAutomata() { newState(); };
~NdfAutomata();
const State* getInitial() const { return m_states[0]; };
State* getInitial() { return m_states[0]; };
/// Creates a new state with a valid id
State* newState();
const State* getState(int i) const { return m_states[i]; };
size_t size() const { return m_states.size(); };
/// return all the symbols that lead to other states starting
/// in any of the states in the given set. Also if there are
/// wildcard transitions, give back a new wildcard that guarantees
/// that its matches match all the wildcards in the set.
/// So the symbols returned in out_symbols do NOT overlap those that
/// match the returned wildcard (if present). And the union of out_symbols
/// and those matched by the wildcard, are all the valid transitions from
/// the given state set
void symbolsFrom(const IntSet& states, SymbolSet& out_symbols,
Wildcard*& wildcard) const;
/// Get the set of states that are reachable from the given state set using the given symbol
void transitionsFrom(const IntSet& states, ustring symbol,
IntSet& out_states) const;
/// Get the set of states that are reachable from the given state set by wildcard
void wildcardTransitionsFrom(const IntSet& states,
IntSet& out_states) const;
/// Perform a lambda closure of a state set
///
/// In other words, complete the given set so it includes all the additional
/// states that are reachable by the lambda symbol
void lambdaClosure(IntSet& states) const;
/// for debugging purposes
std::string tostr() const;
protected:
/// Vector of states
std::vector<State*> m_states;
};
@@ -177,7 +179,8 @@ class NdfAutomata {
typedef std::vector<int> StateSetKey;
// Compute the unique key for the given set of states
void keyFromStateSet(const IntSet &states, StateSetKey &out_key);
void
keyFromStateSet(const IntSet& states, StateSetKey& out_key);
@@ -188,84 +191,83 @@ void keyFromStateSet(const IntSet &states, StateSetKey &out_key);
/// time parsing of light path expressions
class DfAutomata {
friend class DfOptimizedAutomata;
public:
/// Simple state for a deterministic automata
class State {
friend class DfAutomata;
friend class DfOptimizedAutomata;
public:
/// Simple state for a deterministic automata
class State {
friend class DfAutomata;
friend class DfOptimizedAutomata;
public:
State(int id)
{
m_id = id;
m_wildcard_trans = -1;
}
State(int id)
{
m_id = id;
m_wildcard_trans = -1;
}
/// Get the transition for a symbol
//
/// Returns -1 if no transitions with that symbol. That means the
/// symbol is not recognized at this point of the automata
int getTransition(ustring symbol) const;
/// Get the transition for a symbol
//
/// Returns -1 if no transitions with that symbol. That means the
/// symbol is not recognized at this point of the automata
int getTransition(ustring symbol)const;
// Same semantics as in NdfAutomata::State
void addTransition(ustring symbol, State* state);
// WARNING: this has an optimized representation and has to be called
// always AFTER all the normal transitions have been added
void addWildcardTransition(Wildcard* wildcard, State* state);
// Same semantics as in NdfAutomata::State
void addTransition(ustring symbol, State *state);
// WARNING: this has an optimized representation and has to be called
// always AFTER all the normal transitions have been added
void addWildcardTransition(Wildcard *wildcard, State *state);
/// Optimize transitions
///
/// Sometimes the existing wildcard can be extended to wrap some of
/// the single symbol transitions. This function performs that optimization
void removeUselessTransitions();
void addRule(void *rule) { m_rules.push_back(rule); };
const RuleSet &getRules()const { return m_rules; };
int getId()const { return m_id; };
std::string tostr()const;
protected:
int m_id;
// Only one transition per symbol here
SymbolToInt m_symbol_trans;
int m_wildcard_trans;
// A final state here might contain several final states
// from the original NDF automata. Therefore, we need a list
// of rules here
RuleSet m_rules;
};
DfAutomata() {};
~DfAutomata();
State *newState();
const State *getState(int i)const { return m_states[i]; };
size_t size()const { return m_states.size(); };
// In case somebody wants to reuse the same object and recreate
// an automata, we provide this method
void clear();
/// Colapse all the equivalent states into single ones
void removeEquivalentStates();
/// Go through all the states and perform removeUselessTransitions
/// method call on them
/// Optimize transitions
///
/// Sometimes the existing wildcard can be extended to wrap some of
/// the single symbol transitions. This function performs that optimization
void removeUselessTransitions();
/// For debuging purposes
std::string tostr()const;
void addRule(void* rule) { m_rules.push_back(rule); };
const RuleSet& getRules() const { return m_rules; };
int getId() const { return m_id; };
std::string tostr() const;
protected:
int m_id;
// Only one transition per symbol here
SymbolToInt m_symbol_trans;
int m_wildcard_trans;
// A final state here might contain several final states
// from the original NDF automata. Therefore, we need a list
// of rules here
RuleSet m_rules;
};
/// Return true if two states are equivalent
///
/// Two states are equivalent if their transition tables lead
/// to the same states for the same symbols
bool equivalent(const State *dfstateA, const State *dfstateB);
// State vector with the automata
std::vector<State *> m_states;
DfAutomata() {};
~DfAutomata();
State* newState();
const State* getState(int i) const { return m_states[i]; };
size_t size() const { return m_states.size(); };
// In case somebody wants to reuse the same object and recreate
// an automata, we provide this method
void clear();
/// Colapse all the equivalent states into single ones
void removeEquivalentStates();
/// Go through all the states and perform removeUselessTransitions
/// method call on them
void removeUselessTransitions();
/// For debugging purposes
std::string tostr() const;
protected:
/// Return true if two states are equivalent
///
/// Two states are equivalent if their transition tables lead
/// to the same states for the same symbols
bool equivalent(const State* dfstateA, const State* dfstateB);
// State vector with the automata
std::vector<State*> m_states;
};
@@ -274,40 +276,42 @@ class DfAutomata {
/// of state sets that have already been found to be new states of the
/// deterministic automata
class StateSetRecord {
public:
StateSetRecord(const NdfAutomata &ndfautomata, DfAutomata &dfautomata):
m_ndfautomata(ndfautomata), m_dfautomata(dfautomata)
{};
public:
StateSetRecord(const NdfAutomata& ndfautomata, DfAutomata& dfautomata)
: m_ndfautomata(ndfautomata), m_dfautomata(dfautomata) {};
// A new found state is defined by the deterministic state created
// for it and the state(int) set in the original automata
typedef std::pair<DfAutomata::State *, IntSet> Discovery;
// The type that will index our new created states indexed by the set key
typedef std::map<StateSetKey, DfAutomata::State *> StateSetMap;
// A new found state is defined by the deterministic state created
// for it and the state(int) set in the original automata
typedef std::pair<DfAutomata::State*, IntSet> Discovery;
// The type that will index our new created states indexed by the set key
typedef std::map<StateSetKey, DfAutomata::State*> StateSetMap;
/// Take a state set and build a new df state (or return existing one)
/// Also, if it was newly created, append it to the discovered list so we
/// can iterate over it later
DfAutomata::State *ensureState(const IntSet &newstates, std::list<Discovery> &discovered);
/// Take a state set and build a new df state (or return existing one)
/// Also, if it was newly created, append it to the discovered list so we
/// can iterate over it later
DfAutomata::State* ensureState(const IntSet& newstates,
std::list<Discovery>& discovered);
private:
private:
/// Gather all the rules from the original automata in the given sets (if any)
/// and put them in the dfstate rule set
void getRulesFromSet(DfAutomata::State* dfstate,
const NdfAutomata& ndfautomata,
const IntSet& ndfstates);
/// Gather all the rules from the original automata in the given sets (if any)
/// and put them in the dfstate rule set
void getRulesFromSet(DfAutomata::State *dfstate, const NdfAutomata &ndfautomata, const IntSet &ndfstates);
const NdfAutomata &m_ndfautomata;
DfAutomata &m_dfautomata;
StateSetMap m_key_to_dfstate;
const NdfAutomata& m_ndfautomata;
DfAutomata& m_dfautomata;
StateSetMap m_key_to_dfstate;
};
/// NDF to DF automata convertion
/// NDF to DF automata conversion
///
/// This function is the most important pice of the whole process. It takes
/// a non-deterministic finite automata and computes an equivalent deterministic
/// one. It is equivalente in the sense that they both recognize the same language
void ndfautoToDfauto(const NdfAutomata &ndfautomata, DfAutomata &dfautomata);
void
ndfautoToDfauto(const NdfAutomata& ndfautomata, DfAutomata& dfautomata);
OSL_NAMESPACE_EXIT
+88 -309
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,13 +27,14 @@ 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;
// Select the appropriate ustring representation
ll.ustring_rep(m_use_optix ? LLVM_Util::UstringRep::hash
: LLVM_Util::UstringRep::charptr);
ll.dumpasm(shadingsys.m_llvm_dumpasm);
ll.jit_fma(shadingsys.m_llvm_jit_fma);
ll.jit_aggressive(shadingsys.m_llvm_jit_aggressive);
@@ -135,7 +83,7 @@ BackendLLVM::llvm_pass_type(const TypeSpec& typespec)
else if (t == TypeDesc::INT)
lt = ll.type_int();
else if (t == TypeDesc::STRING)
lt = (llvm::Type*)ll.type_string();
lt = (llvm::Type*)ll.type_ustring();
else if (t.aggregate == TypeDesc::VEC3)
lt = (llvm::Type*)ll.type_void_ptr(); //llvm_type_triple_ptr();
else if (t.aggregate == TypeDesc::MATRIX44)
@@ -230,6 +178,7 @@ static ustring fields[] = { ustring("P"),
ustring("tracedata"),
ustring("objdata"),
ustring("shadingcontext"),
ustring("shadingStateUniform"),
ustring("renderer"),
ustring("object2common"),
ustring("shader2common"),
@@ -259,7 +208,8 @@ BackendLLVM::llvm_global_symbol_ptr(ustring name)
// the ShaderGlobals struct.
int sg_index = ShaderGlobalNameToIndex(name);
OSL_ASSERT(sg_index >= 0);
return ll.void_ptr(ll.GEP(sg_ptr(), 0, sg_index));
return ll.void_ptr(ll.GEP(sg_ptr(), 0, sg_index),
llnamefmt("glob_{}_voidptr", name));
}
@@ -276,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
@@ -322,7 +281,7 @@ BackendLLVM::getOrAllocateLLVMSymbol(const Symbol& sym)
if (map_iter == named_values().end()) {
llvm::Value* a = llvm_alloca(sym.typespec(), sym.has_derivs(),
mangled_name);
llnamefmt("{}_mem", mangled_name));
named_values()[mangled_name] = a;
return a;
}
@@ -331,9 +290,11 @@ BackendLLVM::getOrAllocateLLVMSymbol(const Symbol& sym)
#if OSL_USE_OPTIX
llvm::Value*
BackendLLVM::addCUDAVariable(const std::string& name, int size, int alignment,
const void* data, TypeDesc type)
BackendLLVM::addCUDAGlobalVariable(const std::string& name, int size,
int alignment, const void* init_data,
TypeDesc type)
{
OSL_ASSERT(use_optix()
&& "This function is only supposed to be used with OptiX!");
@@ -341,40 +302,16 @@ BackendLLVM::addCUDAVariable(const std::string& name, int size, int alignment,
llvm::Constant* constant = nullptr;
if (type == TypeDesc::TypeFloat) {
constant = llvm::ConstantFP::get(llvm::Type::getFloatTy(
ll.module()->getContext()),
*(float*)data);
constant = ll.constant(*(const float*)init_data);
} else if (type == TypeDesc::TypeInt) {
constant = llvm::ConstantInt::get(llvm::Type::getInt32Ty(
ll.module()->getContext()),
*(int*)data);
constant = ll.constant(*(const int*)init_data);
} else if (type == TypeDesc::TypeString) {
// Register the string with the OptiX renderer. The renderer will add
// the string to a global table and create an OptiX variable to hold the
// char*.
shadingsys().renderer()->register_string(((ustring*)data)->string(),
name);
#if OPTIX_VERSION < 70000
// Leave the variable uninitialized to prevent raw pointers from
// appearing in the generated code. The OptiX renderer will set the
// variable to the string address before the kernel is launched.
constant = llvm::ConstantInt::get(llvm::Type::getInt64Ty(
ll.module()->getContext()),
0);
m_varname_map[name] = ((ustring*)data)->string();
#else
// DeviceStrings use the ustring hash to identify themselves. These hashes will
// match on both the device and host side.
constant = llvm::ConstantInt::get(llvm::Type::getInt64Ty(
ll.module()->getContext()),
((ustring*)data)->hash());
m_varname_map[name] = ((ustring*)data)->string();
#endif
constant = ll.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 {
// Handle unspecified types as generic byte arrays
llvm::ArrayRef<uint8_t> arr_ref((uint8_t*)data, size);
llvm::ArrayRef<uint8_t> arr_ref((uint8_t*)init_data, size);
constant = llvm::ConstantDataArray::get(ll.module()->getContext(),
arr_ref);
}
@@ -384,15 +321,13 @@ BackendLLVM::addCUDAVariable(const std::string& name, int size, int alignment,
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
#if (OPTIX_VERSION < 70000)
g_var->setLinkage(llvm::GlobalValue::ExternalLinkage);
#endif
g_var->setLinkage(llvm::GlobalValue::PrivateLinkage);
g_var->setVisibility(llvm::GlobalValue::DefaultVisibility);
g_var->setInitializer(constant);
m_const_map[name] = g_var;
@@ -402,156 +337,27 @@ BackendLLVM::addCUDAVariable(const std::string& name, int size, int alignment,
void
BackendLLVM::createOptixMetadata(const std::string& name, const Symbol& sym)
{
// Create additional variables with the semantic information needed by OptiX
// to access the global variable created above.
//
// There is no need to retain pointers to these variables, since they are not
// accessed during execution. They are only used internally by OptiX.
//
// Refer to the OptiX API documentation and optix_defines.h in the OptiX SDK
// for more information.
OSL_ASSERT(use_optix()
&& "This function is only supported when using OptiX!");
auto mangle_name = [](const std::string& name, const std::string& prefix) {
return fmtformat("_ZN{}rti_internal_{}{}{}E", prefix.size() + 13,
prefix, name.size(), name);
};
std::string optix_type;
const TypeDesc type = sym.typespec().simpletype();
if (!sym.typespec().is_array()) {
optix_type =
// Documented built-in types
(type == TypeDesc::TypeInt) ? "int"
: (type == TypeDesc::TypeFloat) ? "float"
: (type == TypeDesc::TypePoint) ? "float3"
: (type == TypeDesc::TypeVector) ? "float3"
: (type == TypeDesc::TypeNormal) ? "float3"
: (type == TypeDesc::TypeColor) ? "float3"
: (type == TypeDesc::TypeMatrix) ? "matrix"
: (type == TypeDesc::TypeString)
? "uint64_t"
:
// Catch-all for types that fall through, if there are any.
type.c_str();
// NB: TypeMatrix is assumed to be 4x4 and will be treated by OptiX as a
// user datatype (i.e., a generic struct).
} else {
// OptiX should handle int and float vectors between 2 and 4 dimensions
// with no problem. Larger arrays, or arrays of other element types,
// will be treated as a user datatype and will not work natively with
// OptiX's variable mechanism.
optix_type = fmtformat("{}{}", sym.typespec().elementtype(),
sym.typespec().arraylength());
}
struct rti_typeinfo {
unsigned int kind = 0x796152; // _OPTIX_VARIABLE
unsigned int size;
} type_info;
type_info.size = sym.size();
int type_enum = 0x1337; // _OPTIX_TYPE_ENUM_UNKNOWN
char zero = 0;
addCUDAVariable(mangle_name(name, "typeinfo"), 8, 4, &type_info);
addCUDAVariable(mangle_name(name, "typename"), optix_type.size() + 1, 16,
optix_type.data());
addCUDAVariable(mangle_name(name, "typeenum"), 4, 4, &type_enum,
TypeDesc::TypeInt);
addCUDAVariable(mangle_name(name, "semantic"), 1, 1, &zero);
addCUDAVariable(mangle_name(name, "annotation"), 1, 1, &zero);
}
llvm::Value*
BackendLLVM::getOrAllocateCUDAVariable(const Symbol& sym, bool addMetadata)
BackendLLVM::getOrAllocateCUDAVariable(const Symbol& sym)
{
OSL_ASSERT(use_optix()
&& "This function is only supported when using OptiX!");
std::ostringstream ss;
ss.imbue(std::locale::classic()); // force C locale
if (sym.typespec().is_string()) {
// Use the ustring hash to create a name for the symbol that's based on
// the string contents
//
// TODO: Collisions between variable names are unlikely, but still
// possible. Using something like a counter to handle collisions
// is unattractive because it depends on the order in which
// strings are encountered at run time.
//
// For now I am simply appending the length to the hash, but a
// more robust solution may be called for.
ss << "ds_"
#if OPTIX_VERSION >= 70000
<< group().name() << "_" << group().id() << "_"
#endif
<< std::setbase(16) << std::setfill('0') << std::setw(16)
<< sym.get_string().hash() << "_" << std::setbase(16)
<< std::setfill('0') << std::setw(4) << sym.get_string().length();
auto it = m_varname_map.find(ss.str());
const std::string old_str = (it != m_varname_map.end()) ? it->second
: "";
if (old_str != "" && old_str != sym.get_string().string()) {
std::cerr << "Warning: variable name collision between " << old_str
<< " and " << sym.get_string() << std::endl;
}
} else {
// We need to sanitize the symbol name for PTX compatibility
std::string sym_name = sym.name().c_str();
std::replace(sym_name.begin(), sym_name.end(), '.', '_');
std::string var_name = fmtformat("{}_{}_{}_{}_{}", sym_name,
group().name(), group().id(),
inst()->layername(), sym.layer());
// Leading dollar signs are not allowed in PTX variable names,
// so prepend an underscore.
if (var_name[0] == '$') {
ss << '_';
}
ss << var_name;
}
const std::string name = ss.str();
std::string name = global_unique_symname(sym);
// Return the Value if it has already been allocated
std::map<std::string, llvm::GlobalVariable*>::iterator it
= get_const_map().find(name);
if (it != get_const_map().end()) {
auto it = get_const_map().find(name);
if (it != get_const_map().end())
return it->second;
}
#if (OPTIX_VERSION < 70000)
// Add the extra metadata needed to make the variable visible to OptiX.
if (addMetadata || sym.typespec().is_string())
createOptixMetadata(name, sym);
#endif
// TODO: Figure out the actual CUDA alignment requirements for the various
// OSL types. For now, be somewhat conservative and assume 8 for
// non-scalar types.
int alignment = (sym.typespec().is_scalarnum()) ? 4 : 8;
llvm::Value* cuda_var = addCUDAVariable(name, sym.size(), alignment,
sym.data(),
sym.typespec().simpletype());
return cuda_var;
return addCUDAGlobalVariable(name, sym.size(), alignment, sym.data(),
sym.typespec().simpletype());
}
#endif
@@ -568,38 +374,40 @@ 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
llvm::Value* ptr = getOrAllocateCUDAVariable(sym);
if (ptr) {
llvm::Type* cast_type
= (!sym.typespec().is_string())
? ll.type_ptr(llvm_type(sym.typespec().elementtype()))
: ll.type_void_ptr();
result = ll.ptr_cast(ptr, cast_type);
result = llvm_ptr_cast(ptr, llvm_typedesc(elemtype),
llnamefmt("cast_to_{}_", sym.typespec()));
// N.B. llvm_typedesc() for a string will know that on OptiX,
// strings are actually represented as just the hash.
}
} else {
// For constants, start with *OUR* pointer to the constant values.
result = ll.ptr_cast(ll.constant_ptr(sym.data()),
ll.type_ptr(
llvm_type(sym.typespec().elementtype())));
} else
#endif
{
// For constants on the CPU side, start with *OUR* pointer to the
// constant values.
result = ll.constant_ptr(sym.data(),
ll.type_ptr(llvm_type(elemtype)));
}
} else {
// Start with the initial pointer to the variable's memory location
// If the symbol is not a SymTypeConst, then start with the initial
// pointer to the variable's memory location.
result = getLLVMSymbolBase(sym);
}
if (!result)
return NULL; // Error
// If it's an array or we're dealing with derivatives, step to the
// right element.
// If it's an array or we're dealing with derivatives, step to the right
// element.
TypeDesc t = sym.typespec().simpletype();
if (t.arraylen || has_derivs) {
int d = deriv * std::max(1, t.arraylen);
if (arrayindex)
if (arrayindex && d)
arrayindex = ll.op_add(arrayindex, ll.constant(d));
else
arrayindex = ll.constant(d);
@@ -645,13 +453,14 @@ BackendLLVM::llvm_load_value(const Symbol& sym, int deriv,
return ll.constant(sym.get_float(component));
}
if (sym.typespec().is_string()) {
return ll.constant(sym.get_string());
return llvm_load_string(sym.get_string());
}
OSL_ASSERT(0 && "unhandled constant type");
}
return llvm_load_value(llvm_get_pointer(sym), sym.typespec(), deriv,
arrayindex, component, cast);
arrayindex, component, cast,
llnamefmt("{}_", sym.name()));
}
@@ -659,7 +468,7 @@ BackendLLVM::llvm_load_value(const Symbol& sym, int deriv,
llvm::Value*
BackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type, int deriv,
llvm::Value* arrayindex, int component,
TypeDesc cast)
TypeDesc cast, const std::string& llname)
{
if (!ptr)
return NULL; // Error
@@ -681,7 +490,7 @@ BackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type, int deriv,
ptr = ll.GEP(ptr, 0, component);
// Now grab the value
llvm::Value* result = ll.op_load(ptr);
llvm::Value* result = ll.op_load(ptr, llname);
if (type.is_closure_based())
return result;
@@ -691,46 +500,20 @@ BackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type, int deriv,
result = ll.op_float_to_int(result);
else if (type.is_int() && cast == TypeDesc::TypeFloat)
result = ll.op_int_to_float(result);
else if (type.is_string() && cast == TypeDesc::LONGLONG)
else if (type.is_string() && cast == TypeDesc::LONGLONG) {
result = ll.ptr_to_cast(result, ll.type_longlong());
return result;
}
llvm::Value*
BackendLLVM::llvm_load_device_string(const Symbol& sym, bool follow)
{
// TODO: need to make this work with arrays of strings
OSL_ASSERT(use_optix() && "This is only intended to be used with CUDA");
// Recover the userdata index for non-constant parameters
int userdata_index = find_userdata_index(sym);
llvm::Value* val = NULL;
if (sym.symtype() == SymTypeLocal || sym.symtype() == SymTypeTemp) {
// Handle temporary and local variables
val = getOrAllocateLLVMSymbol(sym);
val = ll.ptr_cast(val, ll.type_longlong_ptr());
} else if (userdata_index < 0) {
// Handle non-varying variables
OSL_DASSERT(sym.data() && "NULL data in non-varying string");
val = getOrAllocateCUDAVariable(sym);
} else {
// Handle potentially varying variables
val = ll.ptr_cast(groupdata_field_ptr(2 + userdata_index),
ll.type_longlong_ptr());
// FIXME -- is this case ever used? Seems strange.
}
// It's preferable to deal with device strings "symbolically" through the
// CUDA variable (essentially a char**), which helps keep the code
// portable. But sometimes it's necessary to handle the underlying char*
// directly, e.g. when printing or writing out a closure param.
if (follow)
val = ll.int_to_ptr_cast(ll.op_load(val));
// We still disguise hashed strings as char*. Ideally, we would only do
// that if the rep were a charptr, but we disguise the hashes as char*'s
// also to avoid ugliness with function signatures differing between CPU
// and GPU. Maybe some day we'll use the hash representation on both
// sides?
if (type.is_string() && ll.ustring_rep() != LLVM_Util::UstringRep::charptr)
result = ll.int_to_ptr_cast(result);
return val;
return result;
}
@@ -764,13 +547,8 @@ BackendLLVM::llvm_load_constant_value(const Symbol& sym, int arrayindex,
int ncomps = (int)sym.typespec().aggregate();
return ll.constant(sym.get_float(ncomps * arrayindex + component));
}
if (sym.typespec().is_string() && use_optix()) {
OSL_DASSERT((arrayindex == 0)
&& "String arrays are not currently supported in OptiX");
return llvm_load_device_string(sym, /*follow*/ false);
}
if (sym.typespec().is_string()) {
return ll.constant(sym.get_string(arrayindex));
return llvm_load_string(sym.get_string(arrayindex));
}
OSL_ASSERT(0 && "unhandled constant type");
@@ -920,16 +698,20 @@ BackendLLVM::llvm_store_component_value(llvm::Value* new_val, const Symbol& sym,
llvm::Value*
BackendLLVM::groupdata_field_ref(int fieldnum)
{
return ll.GEP(groupdata_ptr(), 0, fieldnum);
return ll.GEP(groupdata_ptr(), 0, fieldnum,
llnamefmt("{}_ref", m_groupdata_field_names[fieldnum]));
}
llvm::Value*
BackendLLVM::groupdata_field_ptr(int fieldnum, TypeDesc type)
{
llvm::Value* result = ll.void_ptr(groupdata_field_ref(fieldnum));
llvm::Value* result = groupdata_field_ref(fieldnum);
std::string llname = llnamefmt("{}_ptr", m_groupdata_field_names[fieldnum]);
if (type != TypeDesc::UNKNOWN)
result = ll.ptr_to_cast(result, llvm_type(type));
result = ll.ptr_to_cast(result, llvm_type(type), llname);
else
result = ll.void_ptr(result, llname);
return result;
}
@@ -972,8 +754,6 @@ BackendLLVM::llvm_call_function(const char* name, cspan<const Symbol*> args,
const Symbol& s = *(args[i]);
if (s.typespec().is_closure())
valargs[i] = llvm_load_value(s);
else if (use_optix() && s.typespec().is_string())
valargs[i] = llvm_load_device_string(s, /*follow*/ true);
else if (s.typespec().simpletype().aggregate > 1
|| (deriv_ptrs && s.has_derivs()))
valargs[i] = llvm_void_ptr(s);
@@ -983,6 +763,8 @@ BackendLLVM::llvm_call_function(const char* name, cspan<const Symbol*> args,
return ll.call_function(name, cspan<llvm::Value*>(valargs, args.size()));
}
llvm::Value*
BackendLLVM::llvm_test_nonzero(Symbol& val, bool test_derivs)
{
@@ -1056,8 +838,8 @@ BackendLLVM::llvm_assign_impl(Symbol& Result, Symbol& Src, int arrayindex,
// the size difference is intended (by the optimizer).
if (result_t.is_array() && src_t.is_array() && arrayindex == -1) {
OSL_DASSERT(assignable(result_t.elementtype(), src_t.elementtype()));
llvm::Value* resultptr = llvm_void_ptr(Result);
llvm::Value* srcptr = llvm_void_ptr(Src);
llvm::Value* resultptr = llvm_get_pointer(Result);
llvm::Value* srcptr = llvm_get_pointer(Src);
int len = std::min(Result.size(), Src.size());
int align = result_t.is_closure_based()
? (int)sizeof(void*)
@@ -1078,10 +860,7 @@ BackendLLVM::llvm_assign_impl(Symbol& Result, Symbol& Src, int arrayindex,
TypeDesc basetype = TypeDesc::BASETYPE(rt.basetype);
const int num_components = rt.aggregate;
const bool singlechan = (srccomp != -1) || (dstcomp != -1);
if (use_optix() && Src.typespec().is_string()) {
llvm::Value* src = llvm_load_device_string(Src, /*follow*/ true);
llvm_store_value(ll.ptr_cast(src, ll.type_void_ptr()), Result);
} else if (!singlechan) {
if (!singlechan) {
for (int i = 0; i < num_components; ++i) {
llvm::Value* src_val
= Src.is_constant()
+291 -185
View File
@@ -4,15 +4,15 @@
#pragma once
#include <vector>
#include <map>
#include <vector>
#include "oslexec_pvt.h"
using namespace OSL;
using namespace OSL::pvt;
#include "runtimeoptimize.h"
#include <OSL/llvm_util.h>
#include "runtimeoptimize.h"
// additional includes for creating global OptiX variables
#include "llvm/IR/Constants.h"
@@ -22,7 +22,7 @@ using namespace OSL::pvt;
OSL_NAMESPACE_ENTER
namespace pvt { // OSL::pvt
namespace pvt { // OSL::pvt
@@ -30,16 +30,16 @@ namespace pvt { // OSL::pvt
/// code to implement a shader group.
class BackendLLVM final : public OSOProcessorBase {
public:
BackendLLVM (ShadingSystemImpl &shadingsys, ShaderGroup &group,
ShadingContext *context);
BackendLLVM(ShadingSystemImpl& shadingsys, ShaderGroup& group,
ShadingContext* context);
virtual ~BackendLLVM ();
virtual ~BackendLLVM();
virtual void set_inst (int layer);
virtual void set_inst(int layer);
/// Create an llvm function for the whole shader group, JIT it,
/// and store the llvm::Function* handle to it with the ShaderGroup.
virtual void run ();
virtual void run();
/// What LLVM debug level are we at?
@@ -47,33 +47,33 @@ public:
/// Set up a bunch of static things we'll need for the whole group.
///
void initialize_llvm_group ();
void initialize_llvm_group();
int layer_remap (int origlayer) const { return m_layer_remap[origlayer]; }
int layer_remap(int origlayer) const { return m_layer_remap[origlayer]; }
/// Create an llvm function for the current shader instance.
/// This will end up being the group entry if 'groupentry' is true.
llvm::Function* build_llvm_instance (bool groupentry);
llvm::Function* build_llvm_instance(bool groupentry);
/// Create an llvm function for group initialization code.
llvm::Function* build_llvm_init ();
llvm::Function* build_llvm_init();
/// Build up LLVM IR code for the given range [begin,end) or
/// opcodes, putting them (initially) into basic block bb (or the
/// current basic block if bb==NULL).
bool build_llvm_code (int beginop, int endop, llvm::BasicBlock *bb=NULL);
bool build_llvm_code(int beginop, int endop, llvm::BasicBlock* bb = NULL);
typedef std::map<std::string, llvm::Value*> AllocationMap;
void llvm_assign_initial_value (const Symbol& sym, bool force = false);
llvm::LLVMContext &llvm_context () const { return ll.context(); }
AllocationMap &named_values () { return m_named_values; }
void llvm_assign_initial_value(const Symbol& sym, bool force = false);
llvm::LLVMContext& llvm_context() const { return ll.context(); }
AllocationMap& named_values() { return m_named_values; }
/// Return an llvm::Value* corresponding to the address of the given
/// symbol element, with derivative (0=value, 1=dx, 2=dy) and array
/// index (NULL if it's not an array).
llvm::Value *llvm_get_pointer (const Symbol& sym, int deriv=0,
llvm::Value *arrayindex=NULL);
llvm::Value* llvm_get_pointer(const Symbol& sym, int deriv = 0,
llvm::Value* arrayindex = NULL);
/// Return the llvm::Value* corresponding to the given element
/// value, with derivative (0=value, 1=dx, 2=dy), array index (NULL
@@ -83,9 +83,9 @@ public:
/// return the scalar -- this allows automatic casting to triples.
/// Finally, auto-cast int<->float if requested (no conversion is
/// performed if cast is the default of UNKNOWN).
llvm::Value *llvm_load_value (const Symbol& sym, int deriv,
llvm::Value *arrayindex, int component,
TypeDesc cast=TypeDesc::UNKNOWN);
llvm::Value* llvm_load_value(const Symbol& sym, int deriv,
llvm::Value* arrayindex, int component,
TypeDesc cast = TypeDesc::UNKNOWN);
/// Given an llvm::Value* of a pointer (and the type of the data
@@ -97,62 +97,71 @@ public:
/// and it's a scalar, return the scalar -- this allows automatic
/// casting to triples. Finally, auto-cast int<->float if requested
/// (no conversion is performed if cast is the default of UNKNOWN).
llvm::Value *llvm_load_value (llvm::Value *ptr, const TypeSpec &type,
int deriv, llvm::Value *arrayindex,
int component, TypeDesc cast=TypeDesc::UNKNOWN);
llvm::Value* llvm_load_value(llvm::Value* ptr, const TypeSpec& type,
int deriv, llvm::Value* arrayindex,
int component,
TypeDesc cast = TypeDesc::UNKNOWN,
const std::string& llname = {});
/// Just like llvm_load_value, but when both the symbol and the
/// array index are known to be constants. This can even handle
/// pulling constant-indexed elements out of constant arrays. Use
/// arrayindex==-1 to indicate that it's not an array dereference.
llvm::Value *llvm_load_constant_value (const Symbol& sym,
int arrayindex, int component,
TypeDesc cast=TypeDesc::UNKNOWN);
llvm::Value* llvm_load_constant_value(const Symbol& sym, int arrayindex,
int component,
TypeDesc cast = TypeDesc::UNKNOWN);
/// llvm_load_value with non-constant component designation. Does
/// not work with arrays or do type casts!
llvm::Value *llvm_load_component_value (const Symbol& sym, int deriv,
llvm::Value *component);
llvm::Value* llvm_load_component_value(const Symbol& sym, int deriv,
llvm::Value* component);
/// Non-array version of llvm_load_value, with default deriv &
/// component.
llvm::Value *llvm_load_value (const Symbol& sym, int deriv = 0,
int component = 0,
TypeDesc cast=TypeDesc::UNKNOWN) {
return (use_optix() && ! sym.typespec().is_closure() && sym.typespec().is_string())
? llvm_load_device_string (sym, /*follow*/ true)
: llvm_load_value (sym, deriv, NULL, component, cast);
llvm::Value* llvm_load_value(const Symbol& sym, int deriv = 0,
int component = 0,
TypeDesc cast = TypeDesc::UNKNOWN)
{
return llvm_load_value(sym, deriv, NULL, component, cast);
}
/// Load the address of a global device-side string pointer, which may
/// reside in a global variable, the groupdata struct, or a local value.
llvm::Value *llvm_load_device_string (const Symbol& sym, bool follow);
/// Convenience function to load a string for CPU or GPU device
llvm::Value *llvm_load_string (const Symbol& sym) {
llvm::Value* llvm_load_string(const Symbol& sym)
{
OSL_DASSERT(sym.typespec().is_string());
return use_optix()
? llvm_load_device_string(sym, /*follow*/ true)
: llvm_load_value(sym);
return llvm_load_value(sym);
}
/// Convenience function to load a constant string for CPU or GPU device.
/// On the GPU, we use the ustring hash, not the character pointer.
llvm::Value* llvm_load_string(ustring str) { return ll.constant(str); }
llvm::Value* llvm_load_string(string_view str)
{
return llvm_load_string(ustring(str));
}
/// Legacy version
///
llvm::Value *loadLLVMValue (const Symbol& sym, int component=0,
int deriv=0, TypeDesc cast=TypeDesc::UNKNOWN) {
return llvm_load_value (sym, deriv, NULL, component, cast);
llvm::Value* loadLLVMValue(const Symbol& sym, int component = 0,
int deriv = 0, TypeDesc cast = TypeDesc::UNKNOWN)
{
return llvm_load_value(sym, deriv, NULL, component, cast);
}
/// Return an llvm::Value* that is either a scalar and derivs is
/// false, or a pointer to sym's values (if sym is an aggregate or
/// derivs == true). Furthermore, if deriv == true and sym doesn't
/// have derivs, coerce it into a variable with zero derivs.
llvm::Value *llvm_load_arg (const Symbol& sym, bool derivs);
/// Return an llvm::Value* in the form that we will pass a float-based
/// symbol as a function argument to any "built-in" OSL function -- as a
/// simple value if the symbol is a scalar and no derivs are needed, or as
/// a pointer to the data in all other cases (aggregates, arrays, or
/// derivs needed). If deriv == true and sym doesn't have derivs, coerce
/// it into a variable having derivatives set to 0.0.
llvm::Value* llvm_load_arg(const Symbol& sym, bool derivs);
/// Just like llvm_load_arg(sym,deriv), except use use sym's derivs
/// as-is, no coercion.
llvm::Value *llvm_load_arg (const Symbol& sym) {
return llvm_load_arg (sym, sym.has_derivs());
llvm::Value* llvm_load_arg(const Symbol& sym)
{
return llvm_load_arg(sym, sym.has_derivs());
}
/// Store new_val into the given symbol, given the derivative
@@ -161,8 +170,8 @@ public:
/// symbol doesn't have a deriv, it's a nop. If the component >0
/// and it's a scalar, set the scalar. Returns true if ok, false
/// upon failure.
bool llvm_store_value (llvm::Value *new_val, const Symbol& sym, int deriv,
llvm::Value *arrayindex, int component);
bool llvm_store_value(llvm::Value* new_val, const Symbol& sym, int deriv,
llvm::Value* arrayindex, int component);
/// Store new_val into the memory pointed to by dst_ptr, given the
/// derivative (0=value, 1=dx, 2=dy), array index (NULL if it's not
@@ -170,150 +179,194 @@ public:
/// and the symbol doesn't have a deriv, it's a nop. If the
/// component >0 and it's a scalar, set the scalar. Returns true if
/// ok, false upon failure.
bool llvm_store_value (llvm::Value* new_val, llvm::Value* dst_ptr,
const TypeSpec &type, int deriv,
llvm::Value* arrayindex, int component);
bool llvm_store_value(llvm::Value* new_val, llvm::Value* dst_ptr,
const TypeSpec& type, int deriv,
llvm::Value* arrayindex, int component);
/// Non-array version of llvm_store_value, with default deriv &
/// component.
bool llvm_store_value (llvm::Value *new_val, const Symbol& sym,
int deriv=0, int component=0) {
return llvm_store_value (new_val, sym, deriv, NULL, component);
bool llvm_store_value(llvm::Value* new_val, const Symbol& sym,
int deriv = 0, int component = 0)
{
return llvm_store_value(new_val, sym, deriv, NULL, component);
}
/// llvm_store_value with non-constant component designation. Does
/// not work with arrays or do type casts!
bool llvm_store_component_value (llvm::Value *new_val, const Symbol& sym,
int deriv, llvm::Value *component);
bool llvm_store_component_value(llvm::Value* new_val, const Symbol& sym,
int deriv, llvm::Value* component);
/// Legacy version
///
bool storeLLVMValue (llvm::Value* new_val, const Symbol& sym,
int component=0, int deriv=0) {
return llvm_store_value (new_val, sym, deriv, component);
bool storeLLVMValue(llvm::Value* new_val, const Symbol& sym,
int component = 0, int deriv = 0)
{
return llvm_store_value(new_val, sym, deriv, component);
}
/// Generate an alloca instruction to allocate space for the given
/// type, with derivs if derivs==true, and return the its pointer.
llvm::Value *llvm_alloca (const TypeSpec &type, bool derivs,
const std::string &name="", int align=0);
llvm::Value* llvm_alloca(const TypeSpec& type, bool derivs,
const std::string& name = "", int align = 0);
/// Given the OSL symbol, return the llvm::Value* corresponding to the
/// address of the start of that symbol (first element, first component,
/// and just the plain value if it has derivatives). This is retrieved
/// from the allocation map if already there; and if not yet in the
/// map, the symbol is alloca'd and placed in the map.
llvm::Value *getOrAllocateLLVMSymbol (const Symbol& sym);
llvm::Value* getOrAllocateLLVMSymbol(const Symbol& sym);
#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.
llvm::Value *getOrAllocateCUDAVariable (const Symbol& sym, bool addMetadata=false);
llvm::Value* getOrAllocateCUDAVariable(const Symbol& sym);
/// Create a CUDA global variable and add it to the current Module
llvm::Value *addCUDAVariable (const std::string& name, int size, int alignment,
const void* data, TypeDesc type=TypeDesc::UNKNOWN);
/// Create the extra semantic information needed for OptiX variables
void createOptixMetadata (const std::string& name, const Symbol& sym );
/// Create a named CUDA global variable with the given type, size, and
/// alignment, and add it to the current Module. It will be initialized
/// with data pointed to by init_data. A record will be also added to
/// m_const_map, and will be retrieved by subsequent calls to
/// getOrAllocateCUDAVariable().
llvm::Value* addCUDAGlobalVariable(const std::string& name, int size,
int alignment, const void* init_data,
TypeDesc type = TypeDesc::UNKNOWN);
#endif
/// Retrieve an llvm::Value that is a pointer holding the start address
/// of the specified symbol. This always works for globals and params;
/// for stack variables (locals/temps) is succeeds only if the symbol is
/// already in the allocation table (will fail otherwise). This method
/// is not designed to retrieve constants.
llvm::Value *getLLVMSymbolBase (const Symbol &sym);
llvm::Value* getLLVMSymbolBase(const Symbol& sym);
/// Retrieve the named global ("P", "N", etc.).
llvm::Value *llvm_global_symbol_ptr (ustring name);
llvm::Value* llvm_global_symbol_ptr(ustring name);
/// Test whether val is nonzero, return the llvm::Value* that's the
/// result of a CreateICmpNE or CreateFCmpUNE (depending on the
/// type). If test_derivs is true, it it also tests whether the
/// derivs are zero.
llvm::Value *llvm_test_nonzero (Symbol &val, bool test_derivs = false);
llvm::Value* llvm_test_nonzero(Symbol& val, bool test_derivs = false);
/// Implementaiton of Simple assignment. If arrayindex >= 0, in
/// Implementation of Simple assignment. If arrayindex >= 0, in
/// designates a particular array index to assign.
bool llvm_assign_impl (Symbol &Result, Symbol &Src, int arrayindex = -1,
int srccomp = -1, int dstcomp = -1);
bool llvm_assign_impl(Symbol& Result, Symbol& Src, int arrayindex = -1,
int srccomp = -1, int dstcomp = -1);
/// Convert the name of a global (and its derivative index) into the
/// field number of the ShaderGlobals struct.
int ShaderGlobalNameToIndex (ustring name);
int ShaderGlobalNameToIndex(ustring name);
/// Return the LLVM type handle for the ShaderGlobals struct.
///
llvm::Type *llvm_type_sg ();
llvm::Type* llvm_type_sg();
/// Return the LLVM type handle for a pointer to a
/// ShaderGlobals struct.
llvm::Type *llvm_type_sg_ptr ();
llvm::Type* llvm_type_sg_ptr();
/// Return the ShaderGlobals pointer.
///
llvm::Value *sg_ptr () const { return m_llvm_shaderglobals_ptr; }
llvm::Value* sg_ptr() const
{
return m_llvm_shaderglobals_ptr;
}
llvm::Type *llvm_type_closure_component ();
llvm::Type *llvm_type_closure_component_ptr ();
llvm::Type* llvm_type_closure_component();
llvm::Type* llvm_type_closure_component_ptr();
/// Return the ShaderGlobals pointer cast as a void*.
///
llvm::Value *sg_void_ptr () {
return ll.void_ptr (m_llvm_shaderglobals_ptr);
llvm::Value* sg_void_ptr()
{
return ll.void_ptr(m_llvm_shaderglobals_ptr);
}
llvm::Value *llvm_ptr_cast (llvm::Value* val, const TypeSpec &type) {
return ll.ptr_cast (val, type.simpletype());
/// Cast the pointer variable specified by val to a pointer to the
/// basic type comprising `type`.
llvm::Value* llvm_ptr_cast(llvm::Value* val, const TypeSpec& type,
const std::string& llname = {})
{
return ll.ptr_cast(val, type.simpletype(), llname);
}
llvm::Value *llvm_void_ptr (const Symbol &sym, int deriv=0) {
return ll.void_ptr (llvm_get_pointer(sym, deriv));
llvm::Value* llvm_void_ptr(const Symbol& sym, int deriv = 0)
{
return ll.void_ptr(llvm_get_pointer(sym, deriv),
llnamefmt("{}_voidptr", sym.mangled()));
}
/// Return the LLVM type handle for a structure of the common group
/// data that holds all the shader params.
llvm::Type *llvm_type_groupdata ();
llvm::Type* llvm_type_groupdata();
/// Return the LLVM type handle for a pointer to the common group
/// data that holds all the shader params.
llvm::Type *llvm_type_groupdata_ptr ();
llvm::Type* llvm_type_groupdata_ptr();
/// Return the group data pointer.
///
llvm::Value *groupdata_ptr () const { return m_llvm_groupdata_ptr; }
llvm::Value* groupdata_ptr() const
{
return m_llvm_groupdata_ptr;
}
/// Return the group data pointer cast as a void*.
///
llvm::Value *groupdata_void_ptr () {
return ll.void_ptr (m_llvm_groupdata_ptr);
llvm::Value* groupdata_void_ptr()
{
return ll.void_ptr(m_llvm_groupdata_ptr);
}
/// Return a reference to the specified field within the group data.
llvm::Value *groupdata_field_ref (int fieldnum);
llvm::Value* groupdata_field_ref(int fieldnum);
/// Return a pointer to the specified field within the group data,
/// optionally cast to pointer to a particular data type.
llvm::Value *groupdata_field_ptr (int fieldnum,
TypeDesc type = TypeDesc::UNKNOWN);
llvm::Value* groupdata_field_ptr(int fieldnum,
TypeDesc type = TypeDesc::UNKNOWN);
/// Return the userdata base pointer.
llvm::Value *userdata_base_ptr () const { return m_llvm_userdata_base_ptr; }
llvm::Value* userdata_base_ptr() const
{
return m_llvm_userdata_base_ptr;
}
/// Return the output base pointer.
llvm::Value *output_base_ptr () const { return m_llvm_output_base_ptr; }
llvm::Value* output_base_ptr() const
{
return m_llvm_output_base_ptr;
}
/// Return the shade index
llvm::Value *shadeindex () const { return m_llvm_shadeindex; }
llvm::Value* shadeindex() const
{
return m_llvm_shadeindex;
}
// For a symloc, compute the llvm::Value of the pointer to its true,
// offset location from the base pointer for shade index `sindex`
// (which should already be a i64, or if nullptr, then use
// m_llvm_shadeindex and convert it to i64).
llvm::Value *symloc_ptr(const SymLocationDesc* symloc,
llvm::Value* symloc_ptr(const SymLocationDesc* symloc,
llvm::Value* base_ptr,
llvm::Value* sindex = nullptr) {
llvm::Value* sindex = nullptr)
{
llvm::Value* offset = ll.constanti64(symloc->offset);
llvm::Value* stride = ll.constanti64(symloc->stride);
if (!sindex)
@@ -324,47 +377,47 @@ public:
/// Return a ref to the bool where the "layer_run" flag is stored for
/// the specified layer.
llvm::Value *layer_run_ref (int layer);
llvm::Value* layer_run_ref(int layer);
/// Return a ref to the bool where the "userdata_initialized" flag is
/// stored for the specified userdata index.
llvm::Value *userdata_initialized_ref (int userdata_index=0);
llvm::Value* userdata_initialized_ref(int userdata_index = 0);
/// Generate LLVM code to zero out the variable (including derivs)
///
void llvm_assign_zero (const Symbol &sym);
void llvm_assign_zero(const Symbol& sym);
/// Generate LLVM code to zero out the derivatives of sym.
///
void llvm_zero_derivs (const Symbol &sym);
void llvm_zero_derivs(const Symbol& sym);
/// Generate LLVM code to zero out the derivatives of an array
/// only for the first count elements of it.
///
void llvm_zero_derivs (const Symbol &sym, llvm::Value *count);
void llvm_zero_derivs(const Symbol& sym, llvm::Value* count);
/// Generate a debugging printf at shader execution time.
void llvm_gen_debug_printf (string_view message);
void llvm_gen_debug_printf(string_view message);
/// Generate a warning message at shader execution time.
void llvm_gen_warning (string_view message);
void llvm_gen_warning(string_view message);
/// Generate an error message at shader execution time.
void llvm_gen_error (string_view message);
void llvm_gen_error(string_view message);
/// Generate code to call the given layer. If 'unconditional' is
/// true, call it without even testing if the layer has already been
/// called.
void llvm_call_layer (int layer, bool unconditional = false);
void llvm_call_layer(int layer, bool unconditional = false);
/// Execute the upstream connection (if any, and if not yet run) that
/// establishes the value of symbol sym, which has index 'symindex'
/// within the current layer rop.inst(). If already_run is not NULL,
/// it points to a vector of layer indices that are known to have been
/// it points to a vector of layer indices that are known to have been
/// run -- those can be skipped without dynamically checking their
/// execution status.
void llvm_run_connected_layers (Symbol &sym, int symindex, int opnum = -1,
std::set<int> *already_run = NULL);
void llvm_run_connected_layers(Symbol& sym, int symindex, int opnum = -1,
std::set<int>* already_run = NULL);
/// Generate code for a call to the named function with the given
/// arg list as symbols -- float & ints will be passed by value,
@@ -372,133 +425,186 @@ public:
/// is true, pass pointers even for floats if they have derivs.
/// Return an llvm::Value* corresponding to the return value of the
/// function, if any.
llvm::Value *llvm_call_function (const char *name, cspan<const Symbol *> args,
bool deriv_ptrs=false);
llvm::Value *llvm_call_function (const char *name, const Symbol &A,
bool deriv_ptrs=false) {
return llvm_call_function (name, { &A }, deriv_ptrs);
llvm::Value* llvm_call_function(const char* name, cspan<const Symbol*> args,
bool deriv_ptrs = false);
llvm::Value* llvm_call_function(const char* name, const Symbol& A,
bool deriv_ptrs = false)
{
return llvm_call_function(name, { &A }, deriv_ptrs);
}
llvm::Value *llvm_call_function (const char *name, const Symbol &A,
const Symbol &B, bool deriv_ptrs=false) {
return llvm_call_function (name, { &A, &B }, deriv_ptrs);
llvm::Value* llvm_call_function(const char* name, const Symbol& A,
const Symbol& B, bool deriv_ptrs = false)
{
return llvm_call_function(name, { &A, &B }, deriv_ptrs);
}
llvm::Value *llvm_call_function (const char *name, const Symbol &A,
const Symbol &B, const Symbol &C,
bool deriv_ptrs=false) {
return llvm_call_function (name, { &A, &B, &C }, deriv_ptrs);
llvm::Value* llvm_call_function(const char* name, const Symbol& A,
const Symbol& B, const Symbol& C,
bool deriv_ptrs = false)
{
return llvm_call_function(name, { &A, &B, &C }, deriv_ptrs);
}
TypeDesc llvm_typedesc (const TypeSpec &typespec) {
return typespec.is_closure_based()
? TypeDesc(TypeDesc::PTR, typespec.arraylength())
: typespec.simpletype();
TypeDesc llvm_typedesc(const TypeSpec& typespec)
{
if (typespec.is_closure_based())
return TypeDesc(TypeDesc::PTR, typespec.arraylength());
else if (use_optix() && typespec.is_string_based()) {
// On the OptiX side, we use the uint64 hash to represent a string
return TypeDesc(TypeDesc::UINT64, typespec.arraylength());
} else
return typespec.simpletype();
}
/// Generate the appropriate llvm type definition for a TypeSpec
/// (this is the actual type, for example when we allocate it).
/// Allocates ptrs for closures.
llvm::Type *llvm_type (const TypeSpec &typespec) {
return ll.llvm_type (llvm_typedesc(typespec));
llvm::Type* llvm_type(const TypeSpec& typespec)
{
return ll.llvm_type(llvm_typedesc(typespec));
}
/// Generate the 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);
llvm::Type* llvm_pass_type(const TypeSpec& typespec);
llvm::PointerType *llvm_type_prepare_closure_func() { return m_llvm_type_prepare_closure_func; }
llvm::PointerType *llvm_type_setup_closure_func() { return m_llvm_type_setup_closure_func; }
llvm::PointerType* llvm_type_prepare_closure_func()
{
return m_llvm_type_prepare_closure_func;
}
llvm::PointerType* llvm_type_setup_closure_func()
{
return m_llvm_type_setup_closure_func;
}
/// Return the basic block of the exit for the whole instance.
///
bool llvm_has_exit_instance_block () const {
bool llvm_has_exit_instance_block() const
{
return m_exit_instance_block;
}
/// Return the basic block of the exit for the whole instance.
///
llvm::BasicBlock *llvm_exit_instance_block () {
if (! m_exit_instance_block) {
std::string name = fmtformat("{}_{}_exit_", inst()->layername(),
llvm::BasicBlock* llvm_exit_instance_block()
{
if (!m_exit_instance_block) {
std::string name = llnamefmt("{}_{}_exit_", inst()->layername(),
inst()->id());
m_exit_instance_block = ll.new_basic_block (name);
m_exit_instance_block = ll.new_basic_block(name);
}
return m_exit_instance_block;
}
/// Check for inf/nan in all written-to arguments of the op
void llvm_generate_debugnan (const Opcode &op);
void llvm_generate_debugnan(const Opcode& op);
/// Check for uninitialized values in all read-from arguments to the op
void llvm_generate_debug_uninit (const Opcode &op);
void llvm_generate_debug_uninit(const Opcode& op);
/// Print debugging line for the op
void llvm_generate_debug_op_printf (const Opcode &op);
void llvm_generate_debug_op_printf(const Opcode& op);
llvm::Function *layer_func () const { return ll.current_function(); }
llvm::Function* layer_func() const
{
return ll.current_function();
}
/// Call this when JITing a texture-like call, to track how many.
void generated_texture_call (bool handle) {
void generated_texture_call(bool handle)
{
shadingsys().m_stat_tex_calls_codegened += 1;
if (handle)
shadingsys().m_stat_tex_calls_as_handles += 1;
}
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() { return m_const_map; }
std::map<std::string, llvm::GlobalVariable*>& get_const_map()
{
return m_const_map;
}
/// Return whether or not we are compiling for an OptiX-based renderer.
bool use_optix() { return m_use_optix; }
bool use_optix()
{
return m_use_optix;
}
/// Return if we should compile against free function versions of Renderer Service.
bool use_rs_bitcode() {return m_use_rs_bitcode; }
bool use_rs_bitcode()
{
return m_use_rs_bitcode;
}
/// Return the userdata index for the given Symbol. Return -1 if the Symbol
/// is not an input parameter or is constant and therefore doesn't have an
/// entry in the groupdata struct.
int find_userdata_index (const Symbol& sym);
int find_userdata_index(const Symbol& sym);
LLVM_Util ll;
private:
std::vector<int> m_layer_remap; ///< Remapping of layer ordering
std::set<int> m_layers_already_run; ///< List of layers run
int m_num_used_layers; ///< Number of layers actually used
// Utility for constructing names for llvm symbols. It creates a formatted
// string if the shading system's "llvm_output_bitcode" option is set,
// otherwise it takes a shortcut and returns an empty string (since nobody
// is going to see the pretty bitcode anyway).
template<typename Str, typename... Args>
OSL_NODISCARD inline std::string llnamefmt(const Str& fmt,
Args&&... args) const
{
return m_name_llvm_syms ? fmtformat(fmt, std::forward<Args>(args)...)
: std::string();
}
double m_stat_total_llvm_time; ///< total time spent on LLVM
double m_stat_llvm_setup_time; ///< llvm setup time
double m_stat_llvm_irgen_time; ///< llvm IR generation time
double m_stat_llvm_opt_time; ///< llvm IR optimization time
double m_stat_llvm_jit_time; ///< llvm JIT time
private:
std::vector<int> m_layer_remap; ///< Remapping of layer ordering
std::set<int> m_layers_already_run; ///< List of layers run
int m_num_used_layers; ///< Number of layers actually used
double m_stat_total_llvm_time; ///< total time spent on LLVM
double m_stat_llvm_setup_time; ///< llvm setup time
double m_stat_llvm_irgen_time; ///< llvm IR generation time
double m_stat_llvm_opt_time; ///< llvm IR optimization time
double m_stat_llvm_jit_time; ///< llvm JIT time
// LLVM stuff
AllocationMap m_named_values;
std::map<const Symbol*,int> m_param_order_map;
llvm::Value *m_llvm_shaderglobals_ptr;
llvm::Value *m_llvm_groupdata_ptr;
llvm::Value *m_llvm_userdata_base_ptr;
llvm::Value *m_llvm_output_base_ptr;
llvm::Value *m_llvm_shadeindex;
llvm::BasicBlock * m_exit_instance_block; // exit point for the instance
llvm::Type *m_llvm_type_sg; // LLVM type of ShaderGlobals struct
llvm::Type *m_llvm_type_groupdata; // LLVM type of group data
llvm::Type *m_llvm_type_closure_component; // LLVM type for ClosureComponent
llvm::PointerType *m_llvm_type_prepare_closure_func;
llvm::PointerType *m_llvm_type_setup_closure_func;
int m_llvm_local_mem; // Amount of memory we use for locals
std::map<const Symbol*, int> m_param_order_map;
llvm::Value* m_llvm_shaderglobals_ptr;
llvm::Value* m_llvm_groupdata_ptr;
llvm::Value* m_llvm_interactive_params_ptr;
llvm::Value* m_llvm_userdata_base_ptr;
llvm::Value* m_llvm_output_base_ptr;
llvm::Value* m_llvm_shadeindex;
llvm::BasicBlock* m_exit_instance_block; // exit point for the instance
llvm::Type* m_llvm_type_sg; // LLVM type of ShaderGlobals struct
llvm::Type* m_llvm_type_groupdata; // LLVM type of group data
llvm::Type* m_llvm_type_closure_component; // LLVM type for ClosureComponent
llvm::PointerType* m_llvm_type_prepare_closure_func;
llvm::PointerType* m_llvm_type_setup_closure_func;
int m_llvm_local_mem; // Amount of memory we use for locals
bool m_name_llvm_syms; // Whether to name LLVM symbols
// A mapping from symbol names to llvm::GlobalVariables
std::map<std::string,llvm::GlobalVariable*> m_const_map;
std::map<std::string, llvm::GlobalVariable*> m_const_map;
// A mapping from canonical strings to string variable names, used to
// detect collisions that might occur due to using the string hash to
// create variable names.
std::map<std::string,std::string> m_varname_map;
// Name of each indexed field in the groupdata, mostly for debugging.
std::vector<std::string> m_groupdata_field_names;
bool m_use_optix; ///< Compile for OptiX?
bool m_use_rs_bitcode; /// To use free function versions of Renderer Service functions.
bool m_use_optix; ///< Compile for OptiX?
bool m_use_rs_bitcode; /// To use free function versions of Renderer Service functions.
friend class ShadingSystemImpl;
};
}; // namespace pvt
}; // namespace pvt
OSL_NAMESPACE_EXIT
+93 -35
View File
@@ -185,7 +185,7 @@ struct Symbols4ProtectedShaderGlobals {
SymbolPtrVec varying_symbols;
void check_if_varing(Symbol& s)
void check_if_varying(Symbol& s)
{
if (!is_shader_global_uniform_by_name(s.name())) {
s.make_varying();
@@ -202,13 +202,13 @@ struct Symbols4ProtectedShaderGlobals {
, surfacearea(Strings::op_surfacearea, TypeSpec(), SymTypeGlobal)
, time(Strings::time, TypeSpec(), SymTypeGlobal)
{
check_if_varing(shader2common);
check_if_varing(object2common);
check_if_varing(flipHandedness);
check_if_varing(raytype);
check_if_varing(backfacing);
check_if_varing(surfacearea);
check_if_varing(time);
check_if_varying(shader2common);
check_if_varying(object2common);
check_if_varying(flipHandedness);
check_if_varying(raytype);
check_if_varying(backfacing);
check_if_varying(surfacearea);
check_if_varying(time);
}
};
@@ -240,7 +240,7 @@ private:
static constexpr OpcodeTest no_test = nullptr;
// Map opcode names to a Dependency info
std::unordered_map<ustring, Dependency, ustringHash> m_lookup;
std::unordered_map<ustring, Dependency> m_lookup;
/// Return the ptr to the symbol that is the argnum-th argument to the
/// given op in the instance.
@@ -620,6 +620,20 @@ public:
}
Position common_ancestor_between(Position read_pos, Position write_pos)
{
// Early out when read and write are at the same position
if (read_pos == write_pos)
return read_pos;
// Early out if either position is the root of the dependency tree
if (read_pos == end_pos() || write_pos == end_pos())
return end_pos();
return search_for_common_ancestor_between(read_pos, write_pos);
}
// Because this function makes use of stack arrays, ensure is NOT inlined
// inside a loop to avoid repeatedly reserve stack space each iteration
OSL_NOINLINE Position search_for_common_ancestor_between(Position read_pos,
Position write_pos)
{
// To find common anscenstor
// Walk up both paths building 2 stacks of positions
@@ -629,8 +643,8 @@ public:
auto write_iter = begin_at(write_pos);
const int read_count = read_iter.depth() + 1;
OSL_STACK_ARRAY(Position, read_path, read_count);
int read_depth = 0;
Position* read_path = OSL_ALLOCA(Position, read_count);
int read_depth = 0;
{
// Loop structure is to allow
// writing the end position into the read path
@@ -644,8 +658,8 @@ public:
}
const int writeCount = write_iter.depth() + 1;
OSL_STACK_ARRAY(Position, write_path, writeCount);
int write_depth = 0;
Position* write_path = OSL_ALLOCA(Position, writeCount);
int write_depth = 0;
{
// Loop structure is to allow
// writing the end position into the write path
@@ -657,29 +671,53 @@ public:
++write_iter;
}
}
const int levelCount = std::min(read_depth, write_depth);
const int read_level = read_depth - 1;
const int write_level = write_depth - 1;
OSL_ASSERT(write_path[write_level] == end_pos());
OSL_ASSERT(read_path[read_level] == end_pos());
int level = 0;
OSL_ASSERT(read_path[read_level - level]
== write_path[write_level - level]);
do {
++level;
if (read_path[read_level - level]()
!= write_path[write_level - level]())
const int walkCount = std::min(read_depth, write_depth);
const int read_top = read_depth - 1;
const int write_top = write_depth - 1;
OSL_DASSERT(write_top < writeCount);
OSL_DASSERT(write_path[write_top] == end_pos());
OSL_DASSERT(read_top < read_count);
OSL_DASSERT(read_path[read_top] == end_pos());
int walkDepth = 0;
// Verify top of read and write stacks match positions
OSL_DASSERT((read_top - walkDepth) >= 0);
OSL_DASSERT((read_top - walkDepth) < read_count);
OSL_DASSERT((write_top - walkDepth) >= 0);
OSL_DASSERT((write_top - walkDepth) < writeCount);
OSL_DASSERT(read_path[read_top - walkDepth]
== write_path[write_top - walkDepth]);
// That position should technically be the root (no conditions in the dependency tree)
OSL_DASSERT(read_path[read_top - walkDepth] == end_pos());
// Because we know walkDepth 0 never differs, we can start iterating
// at walkDepth 1
// Walk down the read and write paths until they differ
for (walkDepth = 1; walkDepth < walkCount; ++walkDepth) {
OSL_DASSERT((read_top - walkDepth) >= 0);
OSL_DASSERT((read_top - walkDepth) < read_count);
OSL_DASSERT((write_top - walkDepth) >= 0);
OSL_DASSERT((write_top - walkDepth) < writeCount);
if (read_path[read_top - walkDepth]()
!= write_path[write_top - walkDepth]()) {
break;
} while (level < levelCount);
--level;
OSL_ASSERT(read_path[read_level - level]
== write_path[write_level - level]);
OSL_ASSERT(read_level - level >= 0);
return read_path[read_level - level];
}
}
// The previous walk depth's position was the common ancestor
--walkDepth;
OSL_DASSERT((read_top - walkDepth) >= 0);
OSL_DASSERT((read_top - walkDepth) < read_count);
OSL_DASSERT((write_top - walkDepth) >= 0);
OSL_DASSERT((write_top - walkDepth) < writeCount);
OSL_DASSERT(read_path[read_top - walkDepth]
== write_path[write_top - walkDepth]);
return read_path[read_top - walkDepth];
}
};
// Historically tracks stack of functions
// The Position returned by top_pos changes and function scopes are pushed and popped.
// However any given position is invariant as scopes change
@@ -1053,8 +1091,10 @@ typedef std::vector<WriteEvent> WriteChronology;
class ReadEvent {
DependencyTreeTracker::Position m_pos_in_tree;
#ifdef OSL_DEV
int m_op_num;
int m_loop_op_index;
#endif
public:
ReadEvent(DependencyTreeTracker::Position pos_in_tree_
@@ -1077,9 +1117,15 @@ public:
}
#ifdef OSL_DEV
OSL_FORCEINLINE int op_num() const { return m_op_num; }
OSL_FORCEINLINE int op_num() const
{
return m_op_num;
}
OSL_FORCEINLINE int loop_op_index() const { return m_loop_op_index; }
OSL_FORCEINLINE int loop_op_index() const
{
return m_loop_op_index;
}
#endif
};
@@ -1595,7 +1641,7 @@ struct Analyzer {
// Process arguments written to to handle early outs, cyclical reads,
// and record a WriteEvent to a potentially unmasked operations remembering
// the exact stack of conditional dependencies at that point.
// When we processed reads (above), we ensured that any reads occuring at a higher that on the stoCheck for
// When we processed reads (above), we ensured that any reads occurring at a higher that on the stoCheck for
for (int write_index = 0; write_index < write_count;
++write_index) {
const Symbol* symbolWrittenTo
@@ -1642,7 +1688,7 @@ struct Analyzer {
}
}
// Special case for op_getattribute which normaly would be
// Special case for op_getattribute which normally would be
// implicitly varying unless BatchedRendererServices says it
// is uniform.
if (opcode.opname() == Strings::op_getattribute) {
@@ -2257,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);
@@ -2349,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();
+20 -8
View File
@@ -188,7 +188,7 @@ BatchedBackendLLVM::llvm_pass_type(const TypeSpec& typespec)
else if (t == TypeDesc::INT)
lt = ll.type_int();
else if (t == TypeDesc::STRING)
lt = (llvm::Type*)ll.type_string();
lt = (llvm::Type*)ll.type_ustring();
else if (t.aggregate == TypeDesc::VEC3)
lt = (llvm::Type*)ll.type_void_ptr(); //llvm_type_triple_ptr();
else if (t.aggregate == TypeDesc::MATRIX44)
@@ -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];
@@ -867,7 +877,7 @@ BatchedBackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type,
|| (ll.llvm_typeof(result) == ll.type_float())
|| (ll.llvm_typeof(result) == ll.type_triple())
|| (ll.llvm_typeof(result) == ll.type_int())
|| (ll.llvm_typeof(result) == (llvm::Type*)ll.type_string())
|| (ll.llvm_typeof(result) == ll.type_ustring())
|| (ll.llvm_typeof(result) == ll.type_matrix())
|| (ll.llvm_typeof(result) == ll.type_longlong())) {
result = ll.widen_value(result);
@@ -888,7 +898,7 @@ BatchedBackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type,
(ll.llvm_typeof(result) == ll.type_wide_float())
|| (ll.llvm_typeof(result) == ll.type_wide_int())
|| (ll.llvm_typeof(result) == ll.type_wide_triple())
|| (ll.llvm_typeof(result) == ll.type_wide_string())
|| (ll.llvm_typeof(result) == ll.type_wide_ustring())
|| (ll.llvm_typeof(result) == ll.type_wide_bool())
|| (ll.llvm_typeof(result) == ll.type_wide_matrix())
|| (ll.llvm_typeof(result) == ll.type_wide_longlong()));
@@ -1218,7 +1228,8 @@ BatchedBackendLLVM::llvm_store_value(llvm::Value* new_val, llvm::Value* dst_ptr,
if (!type.is_closure_based() && t.aggregate > 1)
dst_ptr = ll.GEP(dst_ptr, 0, component);
if (ll.type_ptr(ll.llvm_typeof(new_val)) != ll.llvm_typeof(dst_ptr)) {
if ((const llvm::Type*)ll.type_ptr(ll.llvm_typeof(new_val))
!= ll.llvm_typeof(dst_ptr)) {
std::cerr << " new_val type=";
{
llvm::raw_os_ostream os_cerr(std::cerr);
@@ -1231,7 +1242,7 @@ BatchedBackendLLVM::llvm_store_value(llvm::Value* new_val, llvm::Value* dst_ptr,
}
std::cerr << std::endl;
}
OSL_ASSERT(ll.type_ptr(ll.llvm_typeof(new_val))
OSL_ASSERT((const llvm::Type*)ll.type_ptr(ll.llvm_typeof(new_val))
== ll.llvm_typeof(dst_ptr));
// Finally, store the value.
@@ -1766,7 +1777,8 @@ BatchedBackendLLVM::llvm_test_nonzero(const Symbol& val, bool test_derivs)
llvm::Value* llvmValue = llvm_get_pointer(val);
//OSL_DEV_ONLY(std::cout << "llvmValue type=" << ll.llvm_typenameof(llvmValue) << std::endl);
if (ll.llvm_typeof(llvmValue) == ll.type_ptr(ll.type_bool())) {
if (ll.llvm_typeof(llvmValue)
== (const llvm::Type*)ll.type_ptr(ll.type_bool())) {
return ll.op_ne(llvm_load_value(val), ll.constant_bool(0));
} else {
return ll.op_ne(llvm_load_value(val), ll.constant(0));
@@ -1846,7 +1858,7 @@ BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,
return true;
}
// memcpy complicated by promotion of uniform to wide during assignment, dissallow
// memcpy complicated by promotion of uniform to wide during assignment, disallow
// The following code handles f=f, f=i, v=v, v=f, v=i, m=m, s=s.
// Remember that llvm_load_value will automatically convert scalar->triple.
@@ -1904,7 +1916,7 @@ BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,
// The llvm_load_value above should have handled bool to int conversions
// when the basetype == Typedesc::INT
// write source float into all compnents when dstcomp == -1, otherwise
// write source float into all components when dstcomp == -1, otherwise
// the single element requested.
if (dstcomp == -1) {
for (int i = 0; i < num_components; ++i)
+19 -11
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>
@@ -164,7 +162,7 @@ public:
llvm::Value* llvm_load_mask(const Symbol& cond);
/// Return an llvm::Value* that is either a scalar and derivs is
/// false, or a pointer to sym's values (if sym is an aggreate or
/// false, or a pointer to sym's values (if sym is an aggregate or
/// derivs == true). Furthermore, if deriv == true and sym doesn't
/// have derivs, coerce it into a variable with zero derivs.
llvm::Value* llvm_load_arg(const Symbol& sym, bool derivs,
@@ -278,9 +276,9 @@ public:
public:
TempScope(BatchedBackendLLVM& backend);
TempScope(const TempScope& other) = delete;
TempScope(const TempScope&& other) = delete;
TempScope& operator=(const TempScope& other) = delete;
TempScope(const TempScope& other) = delete;
TempScope(const TempScope&& other) = delete;
TempScope& operator=(const TempScope& other) = delete;
TempScope& operator=(const TempScope&& other) = delete;
~TempScope();
};
@@ -331,7 +329,7 @@ public:
/// derivs are zero.
llvm::Value* llvm_test_nonzero(const Symbol& val, bool test_derivs = false);
/// Implementaiton of Simple assignment. If arrayindex >= 0, in
/// Implementation of Simple assignment. If arrayindex >= 0, in
/// designates a particular array index to assign.
bool llvm_assign_impl(const Symbol& Result, const Symbol& Src,
int arrayindex = -1, int srccomp = -1,
@@ -489,7 +487,7 @@ public:
// Encapsulate creation of function names that encode parameter types,
// including if each is varying or uniform, and if a mask is required.
// Utilize llvm::Twine to efficently combine multiple strings
// Utilize llvm::Twine to efficiently combine multiple strings
// Usage is to start with the function name then append arguments,
// and at any point masking can be turned on/off as well as batching.
// The effect of disabling batching would be the function name is
@@ -533,7 +531,7 @@ public:
ArgVector m_args;
public:
FuncSpec(const FuncSpec&) = delete;
FuncSpec(const FuncSpec&) = delete;
FuncSpec& operator=(const FuncSpec&) = delete;
FuncSpec(const llvm::Twine& name)
@@ -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;
+126 -41
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;
}
@@ -557,7 +574,7 @@ LLVMGEN(llvm_gen_arraylength)
int len = A.typespec().is_unsized_array() ? A.initializers()
: A.typespec().arraylength();
// Even thought the array's size should be uniform accross all lanes,
// Even thought the array's size should be uniform across all lanes,
// the symbol its being stored in maybe varying
llvm::Value* const_length = Result.is_uniform() ? rop.ll.constant(len)
: rop.ll.wide_constant(len);
@@ -605,7 +622,7 @@ LLVMGEN(llvm_gen_aref)
} else {
BatchedBackendLLVM::TempScope temp_scope(rop);
// We need a copy of the indices incase the range check clamps them
// We need a copy of the indices in case the range check clamps them
llvm::Value* loc_clamped_wide_index = rop.getOrAllocateTemp(
TypeSpec(TypeDesc::INT), false /*derivs*/, false /*is_uniform*/,
false /*forceBool*/,
@@ -687,7 +704,7 @@ LLVMGEN(llvm_gen_aassign)
}
} else {
BatchedBackendLLVM::TempScope temp_scope(rop);
// We need a copy of the indices incase the range check clamps them
// We need a copy of the indices in case the range check clamps them
llvm::Value* loc_clamped_wide_index = rop.getOrAllocateTemp(
TypeSpec(TypeDesc::INT), false /*derivs*/, false /*is_uniform*/,
false /*forceBool*/,
@@ -1110,10 +1127,10 @@ LLVMGEN(llvm_gen_if)
// contain a call to a lower level, those must not be executed
// if the mask is all off
//#define SKIP_TESTING_IF_ANY_LANES_ACTIVE_TO_AVOID_BRANCH 1
// NOTE: if SKIP_TESTING_IF_ANY_LANES_ACTIVE_TO_AVOID_BRANCH is defineed then
// NOTE: if SKIP_TESTING_IF_ANY_LANES_ACTIVE_TO_AVOID_BRANCH is defined then
// library and layer functions may get called with an entirely empty mask
#ifndef SKIP_TESTING_IF_ANY_LANES_ACTIVE_TO_AVOID_BRANCH
// We use the combined mask stack + the if condition's mask we aready pushed
// We use the combined mask stack + the if condition's mask we already pushed
llvm::Value* anyThenLanesActive = rop.ll.test_if_mask_is_non_zero(
rop.ll.current_mask());
#endif
@@ -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);
@@ -2302,7 +2323,7 @@ LLVMGEN(llvm_gen_compref)
if (rop.inst()->master()->range_checking()) {
BatchedBackendLLVM::TempScope temp_scope(rop);
// We need a copy of the indices incase the range check clamps them
// We need a copy of the indices in case the range check clamps them
llvm::Value* loc_clamped_wide_index = rop.getOrAllocateTemp(
TypeSpec(TypeDesc::INT), false /*derivs*/, false /*is_uniform*/,
false /*forceBool*/,
@@ -2418,7 +2439,7 @@ LLVMGEN(llvm_gen_compassign)
if (rop.inst()->master()->range_checking()) {
BatchedBackendLLVM::TempScope temp_scope(rop);
// We need a copy of the indices incase the range check clamps them
// We need a copy of the indices in case the range check clamps them
llvm::Value* loc_clamped_wide_index = rop.getOrAllocateTemp(
TypeSpec(TypeDesc::INT), false /*derivs*/, false /*is_uniform*/,
false /*forceBool*/,
@@ -2534,7 +2555,7 @@ LLVMGEN(llvm_gen_mxcompref)
}
} else {
BatchedBackendLLVM::TempScope temp_scope(rop);
// We need a copy of the indices incase the range check clamps them
// We need a copy of the indices in case the range check clamps them
llvm::Value* loc_clamped_wide_index = rop.getOrAllocateTemp(
TypeSpec(TypeDesc::INT), false /*derivs*/, false /*is_uniform*/,
false /*forceBool*/,
@@ -2636,7 +2657,7 @@ LLVMGEN(llvm_gen_mxcompassign)
}
} else {
BatchedBackendLLVM::TempScope temp_scope(rop);
// We need a copy of the indices incase the range check clamps them
// We need a copy of the indices in case the range check clamps them
llvm::Value* loc_clamped_wide_index = rop.getOrAllocateTemp(
TypeSpec(TypeDesc::INT), false /*derivs*/, false /*is_uniform*/,
false /*forceBool*/,
@@ -2955,7 +2976,7 @@ LLVMGEN(llvm_gen_compare_op)
if ((typeOfA == rop.ll.type_bool() && typeOfB == rop.ll.type_int())
|| (typeOfA == rop.ll.type_wide_bool()
&& typeOfB == rop.ll.type_wide_int())) {
// TODO: could optimize for contant 0 and 1 and skip the comparison
// TODO: could optimize for constant 0 and 1 and skip the comparison
a = rop.ll.op_bool_to_int(a);
}
if ((typeOfB == rop.ll.type_bool() && typeOfA == rop.ll.type_int())
@@ -3547,7 +3568,7 @@ LLVMGEN(llvm_gen_transform)
FuncSpec func_spec("build_transform_matrix");
func_spec.arg_varying(TypeDesc::TypeMatrix44);
// Ignore derivatives if uneeded or unsupplied
// Ignore derivatives if unneeded or unsupplied
func_spec.arg(*From, from_is_uniform);
func_spec.arg(*To, to_is_uniform);
func_spec.mask();
@@ -3570,7 +3591,7 @@ LLVMGEN(llvm_gen_transform)
FuncSpec func_spec(op.opname().c_str());
func_spec.unbatch();
//std::string func_name = std::string("osl_") + op.opname().c_str() + "_";
// Ignore derivatives if uneeded or unsupplied
// Ignore derivatives if unneeded or unsupplied
bool has_derivs = (Result->has_derivs() && P->has_derivs());
func_spec.arg(*P, has_derivs, P_is_uniform);
// The matrix is always varying if we looked it up,
@@ -5750,7 +5771,7 @@ llvm_batched_noise_options(BatchedBackendLLVM& rop, int opnum,
rop.ll.call_function("osl_noiseparams_set_do_filter", opt,
rop.llvm_load_value(Val));
} else if (name == Strings::direction && Val.typespec().is_triple()) {
// We are not going to bin by varing direction
// We are not going to bin by varying direction
// instead we will pass a pointer to its wide value
// as an extra parameter.
// If it is null, then the uniform value from noise options
@@ -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,8 +7237,9 @@ 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 compiliation
// was more expedient to write the for in C++ than IR, but if compilation
// of the extra ops becomes problematic, this choice can be revisited
for (int lane_index = 0; lane_index < rop.vector_width(); ++lane_index) {
llvm::Value* comp_ptr = rop.ll.op_extract(comp_wide_ptr, lane_index);
@@ -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);
@@ -7706,7 +7791,7 @@ LLVMGEN(llvm_gen_pointcloud_write)
TypeDesc::NOSEMANTICS, nattrs } };
TypeSpec valuesArrayType { TypeDesc { TypeDesc::PTR, TypeDesc::SCALAR,
TypeDesc::NOSEMANTICS, nattrs } };
llvm::Value* names = rop.ll.op_alloca(rop.ll.type_string(), nattrs);
llvm::Value* names = rop.ll.op_alloca(rop.ll.type_ustring(), nattrs);
llvm::Value* types = rop.ll.op_alloca(rop.ll.type_typedesc(), nattrs);
llvm::Value* values = rop.ll.op_alloca(rop.ll.type_void_ptr(), nattrs);
@@ -8191,7 +8276,7 @@ LLVMGEN(llvm_gen_split)
llvm::Value* wide_sep = rop.ll.wide_constant("");
llvm::Value* temp_wide_sep = rop.getOrAllocateTemp(
TypeSpec(TypeDesc::STRING), false /*derivs*/,
false /*op_is_uniform*/, false /*forceBool*/, "wide seperator");
false /*op_is_uniform*/, false /*forceBool*/, "wide separator");
rop.ll.op_unmasked_store(wide_sep, temp_wide_sep);
args.push_back(rop.ll.void_ptr(temp_wide_sep));
}
+99 -69
View File
@@ -31,7 +31,7 @@
#include "batched_backendllvm.h"
#include "oslexec_pvt.h"
// Create extrenal declarations for all built-in funcs we may call from LLVM
// Create external declarations for all built-in funcs we may call from LLVM
#define DECL(name, signature) extern "C" void name();
#include "builtindecl.h"
#undef DECL
@@ -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
@@ -760,11 +779,10 @@ BatchedBackendLLVM::llvm_type_batched_trace_options()
std::vector<llvm::Type*> sg_types;
// Uniform values of the batch
sg_types.push_back(ll.type_float()); // mindist
sg_types.push_back(ll.type_float()); // maxdist
sg_types.push_back(ll.type_int()); // shade
sg_types.push_back(
reinterpret_cast<llvm::Type*>(ll.type_string())); // traceset
sg_types.push_back(ll.type_float()); // mindist
sg_types.push_back(ll.type_float()); // maxdist
sg_types.push_back(ll.type_int()); // shade
sg_types.push_back(ll.type_ustring()); // traceset
m_llvm_type_batched_trace_options = ll.type_struct(sg_types, "TraceOptions",
false /*is_packed*/);
@@ -894,7 +912,7 @@ BatchedBackendLLVM::llvm_type_groupdata()
fields.push_back(llvm_wide_type(ts));
// Alignment
// TODO: this isn't quite right, cant rely on batch size to == ISA SIMD requirements
// TODO: this isn't quite right, can't rely on batch size to == ISA SIMD requirements
size_t base_size = sym.typespec().is_closure_based()
? sizeof(void*)
: sym.typespec().simpletype().basesize();
@@ -902,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;
}
@@ -1042,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
@@ -1060,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();
@@ -1126,7 +1143,7 @@ BatchedBackendLLVM::llvm_assign_initial_value(
// For ISA without a native mask (AVX & AVX2), this gather op will
// clamp the indices of masked off lanes to 0.
// This means the user data base pointer + sym_offset
// must be dereferencable with a shadeindex of 0.
// must be dereferenceable with a shadeindex of 0.
llvm::Value* wide_val
= ll.op_gather(userdata_sym_base_ptr, wide_index);
@@ -1218,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
@@ -1252,8 +1278,7 @@ BatchedBackendLLVM::llvm_assign_initial_value(
data_type = ll.type_float();
} else if (elemtype.is_string()) {
ptr_type = ll.type_ustring_ptr();
data_type = static_cast<llvm::Type*>(
ll.type_string());
data_type = ll.type_ustring();
} else if (elemtype.is_int()) {
ptr_type = ll.type_int_ptr();
data_type = ll.type_int();
@@ -1740,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
@@ -1759,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;
@@ -1815,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())
@@ -1876,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()) {
@@ -1889,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;
@@ -2071,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);
@@ -2097,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());
@@ -2693,21 +2736,9 @@ BatchedBackendLLVM::run()
// entry points, as well as for all the external functions that are
// just declarations (not definitions) in the module (which we have
// conveniently stashed in external_function_names).
#if 0
std::vector<std::string> entry_function_names;
entry_function_names.push_back (ll.func_name(init_func));
for (int layer = 0; layer < nlayers; ++layer) {
// set_inst (layer);
llvm::Function* f = funcs[layer];
if (f && group().is_entry_layer(layer))
entry_function_names.push_back (ll.func_name(f));
}
ll.internalize_module_functions ("osl_", external_function_names, entry_function_names);
#else
std::unordered_set<llvm::Function*> external_functions;
external_functions.insert(init_func);
for (int layer = 0; layer < nlayers; ++layer) {
// set_inst (layer);
llvm::Function* f = funcs[layer];
// If we plan to call bitcode_string of a layer's function after optimization
// it may not exist after optimization unless we treat it as external.
@@ -2716,7 +2747,6 @@ BatchedBackendLLVM::run()
}
}
ll.prune_and_internalize_module(external_functions);
#endif
// Debug code to dump the pre-optimized bitcode to a file
if (llvm_debug() >= 2 || shadingsys().llvm_output_bitcode()) {
+26 -27
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,15 +109,14 @@ 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 OPENIMAGEIO_VERSION >= 20307
if (texturesys()->is_udim(texture_handle)) {
// Newer versions of the TextureSystem interface are able to determine the
// specific UDIM tile we're using.
@@ -131,9 +130,9 @@ BatchedRendererServices<WidthT>::resolve_udim_uniform(
udim_handle = texture_handle;
}
return udim_handle;
} else
#endif
} else {
return texture_handle;
}
}
@@ -142,16 +141,15 @@ 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 OPENIMAGEIO_VERSION >= 20307
if (texturesys()->is_udim(texture_handle)) {
// Newer versions of the TextureSystem interface are able to determine the
// specific UDIM tile we're using.
@@ -167,9 +165,9 @@ BatchedRendererServices<WidthT>::resolve_udim(
}
wresult[l] = udim_handle;
});
} else
#endif
} else {
assign_all(wresult, texture_handle);
}
}
@@ -178,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();
@@ -205,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,
@@ -223,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,
@@ -240,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,
@@ -257,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)
{
@@ -271,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
@@ -285,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)
{
@@ -314,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());
+282 -278
View File
@@ -11,119 +11,118 @@
#ifndef DECL
#error Do not include this file unless DECL is defined
# error Do not include this file unless DECL is defined
#endif
#define NOISE_IMPL(name) \
DECL (osl_ ## name ## _ff, "ff") \
DECL (osl_ ## name ## _fff, "fff") \
DECL (osl_ ## name ## _fv, "fv") \
DECL (osl_ ## name ## _fvf, "fvf") \
DECL (osl_ ## name ## _vf, "xvf") \
DECL (osl_ ## name ## _vff, "xvff") \
DECL (osl_ ## name ## _vv, "xvv") \
DECL (osl_ ## name ## _vvf, "xvvf")
#define NOISE_IMPL(name) \
DECL(osl_##name##_ff, "ff") \
DECL(osl_##name##_fff, "fff") \
DECL(osl_##name##_fv, "fv") \
DECL(osl_##name##_fvf, "fvf") \
DECL(osl_##name##_vf, "xvf") \
DECL(osl_##name##_vff, "xvff") \
DECL(osl_##name##_vv, "xvv") \
DECL(osl_##name##_vvf, "xvvf")
#define NOISE_DERIV_IMPL(name) \
DECL (osl_ ## name ## _dfdf, "xXX") \
DECL (osl_ ## name ## _dfdff, "xXXf") \
DECL (osl_ ## name ## _dffdf, "xXfX") \
DECL (osl_ ## name ## _dfdfdf, "xXXX") \
DECL (osl_ ## name ## _dfdv, "xXv") \
DECL (osl_ ## name ## _dfdvf, "xXvf") \
DECL (osl_ ## name ## _dfvdf, "xXvX") \
DECL (osl_ ## name ## _dfdvdf, "xXvX") \
DECL (osl_ ## name ## _dvdf, "xvX") \
DECL (osl_ ## name ## _dvdff, "xvXf") \
DECL (osl_ ## name ## _dvfdf, "xvfX") \
DECL (osl_ ## name ## _dvdfdf, "xvXX") \
DECL (osl_ ## name ## _dvdv, "xvv") \
DECL (osl_ ## name ## _dvdvf, "xvvf") \
DECL (osl_ ## name ## _dvvdf, "xvvX") \
DECL (osl_ ## name ## _dvdvdf, "xvvX")
#define NOISE_DERIV_IMPL(name) \
DECL(osl_##name##_dfdf, "xXX") \
DECL(osl_##name##_dfdff, "xXXf") \
DECL(osl_##name##_dffdf, "xXfX") \
DECL(osl_##name##_dfdfdf, "xXXX") \
DECL(osl_##name##_dfdv, "xXv") \
DECL(osl_##name##_dfdvf, "xXvf") \
DECL(osl_##name##_dfvdf, "xXvX") \
DECL(osl_##name##_dfdvdf, "xXvX") \
DECL(osl_##name##_dvdf, "xvX") \
DECL(osl_##name##_dvdff, "xvXf") \
DECL(osl_##name##_dvfdf, "xvfX") \
DECL(osl_##name##_dvdfdf, "xvXX") \
DECL(osl_##name##_dvdv, "xvv") \
DECL(osl_##name##_dvdvf, "xvvf") \
DECL(osl_##name##_dvvdf, "xvvX") \
DECL(osl_##name##_dvdvdf, "xvvX")
#define GENERIC_NOISE_DERIV_IMPL(name) \
DECL (osl_ ## name ## _dfdf, "xsXXXX") \
DECL (osl_ ## name ## _dfdfdf, "xsXXXXX") \
DECL (osl_ ## name ## _dfdv, "xsXXXX") \
DECL (osl_ ## name ## _dfdvdf, "xsXXXXX") \
DECL (osl_ ## name ## _dvdf, "xsXXXX") \
DECL (osl_ ## name ## _dvdfdf, "xsXXXXX") \
DECL (osl_ ## name ## _dvdv, "xsXXXX") \
DECL (osl_ ## name ## _dvdvdf, "xsXXXXX")
#define GENERIC_NOISE_DERIV_IMPL(name) \
DECL(osl_##name##_dfdf, "xsXXXX") \
DECL(osl_##name##_dfdfdf, "xsXXXXX") \
DECL(osl_##name##_dfdv, "xsXXXX") \
DECL(osl_##name##_dfdvdf, "xsXXXXX") \
DECL(osl_##name##_dvdf, "xsXXXX") \
DECL(osl_##name##_dvdfdf, "xsXXXXX") \
DECL(osl_##name##_dvdv, "xsXXXX") \
DECL(osl_##name##_dvdvdf, "xsXXXXX")
#define PNOISE_IMPL(name) \
DECL (osl_ ## name ## _fff, "fff") \
DECL (osl_ ## name ## _fffff, "fffff") \
DECL (osl_ ## name ## _fvv, "fvv") \
DECL (osl_ ## name ## _fvfvf, "fvfvf") \
DECL (osl_ ## name ## _vff, "xvff") \
DECL (osl_ ## name ## _vffff, "xvffff") \
DECL (osl_ ## name ## _vvv, "xvvv") \
DECL (osl_ ## name ## _vvfvf, "xvvfvf")
#define PNOISE_IMPL(name) \
DECL(osl_##name##_fff, "fff") \
DECL(osl_##name##_fffff, "fffff") \
DECL(osl_##name##_fvv, "fvv") \
DECL(osl_##name##_fvfvf, "fvfvf") \
DECL(osl_##name##_vff, "xvff") \
DECL(osl_##name##_vffff, "xvffff") \
DECL(osl_##name##_vvv, "xvvv") \
DECL(osl_##name##_vvfvf, "xvvfvf")
#define PNOISE_DERIV_IMPL(name) \
DECL (osl_ ## name ## _dfdff, "xXXf") \
DECL (osl_ ## name ## _dfdffff, "xXXfff") \
DECL (osl_ ## name ## _dffdfff, "xXfXff") \
DECL (osl_ ## name ## _dfdfdfff, "xXXXff") \
DECL (osl_ ## name ## _dfdvv, "xXXv") \
DECL (osl_ ## name ## _dfdvfvf, "xXvfvf") \
DECL (osl_ ## name ## _dfvdfvf, "xXvXvf") \
DECL (osl_ ## name ## _dfdvdfvf, "xXvXvf") \
DECL (osl_ ## name ## _dvdff, "xvXf") \
DECL (osl_ ## name ## _dvdffff, "xvXfff") \
DECL (osl_ ## name ## _dvfdfff, "xvfXff") \
DECL (osl_ ## name ## _dvdfdfff, "xvXXff") \
DECL (osl_ ## name ## _dvdvv, "xvvv") \
DECL (osl_ ## name ## _dvdvfvf, "xvvfvf") \
DECL (osl_ ## name ## _dvvdfvf, "xvvXvf") \
DECL (osl_ ## name ## _dvdvdfvf, "xvvXvf")
#define PNOISE_DERIV_IMPL(name) \
DECL(osl_##name##_dfdff, "xXXf") \
DECL(osl_##name##_dfdffff, "xXXfff") \
DECL(osl_##name##_dffdfff, "xXfXff") \
DECL(osl_##name##_dfdfdfff, "xXXXff") \
DECL(osl_##name##_dfdvv, "xXXv") \
DECL(osl_##name##_dfdvfvf, "xXvfvf") \
DECL(osl_##name##_dfvdfvf, "xXvXvf") \
DECL(osl_##name##_dfdvdfvf, "xXvXvf") \
DECL(osl_##name##_dvdff, "xvXf") \
DECL(osl_##name##_dvdffff, "xvXfff") \
DECL(osl_##name##_dvfdfff, "xvfXff") \
DECL(osl_##name##_dvdfdfff, "xvXXff") \
DECL(osl_##name##_dvdvv, "xvvv") \
DECL(osl_##name##_dvdvfvf, "xvvfvf") \
DECL(osl_##name##_dvvdfvf, "xvvXvf") \
DECL(osl_##name##_dvdvdfvf, "xvvXvf")
#define GENERIC_PNOISE_DERIV_IMPL(name) \
DECL (osl_ ## name ## _dfdff, "xsXXfXX") \
DECL (osl_ ## name ## _dfdfdfff, "xsXXXffXX") \
DECL (osl_ ## name ## _dfdvv, "xsXXvXX") \
DECL (osl_ ## name ## _dfdvdfvf, "xsXvXvfXX") \
DECL (osl_ ## name ## _dvdff, "xsvXfXX") \
DECL (osl_ ## name ## _dvdfdfff, "xsvXXffXX") \
DECL (osl_ ## name ## _dvdvv, "xsvvvXX") \
DECL (osl_ ## name ## _dvdvdfvf, "xsvvXvfXX")
#define GENERIC_PNOISE_DERIV_IMPL(name) \
DECL(osl_##name##_dfdff, "xsXXfXX") \
DECL(osl_##name##_dfdfdfff, "xsXXXffXX") \
DECL(osl_##name##_dfdvv, "xsXXvXX") \
DECL(osl_##name##_dfdvdfvf, "xsXvXvfXX") \
DECL(osl_##name##_dvdff, "xsvXfXX") \
DECL(osl_##name##_dvdfdfff, "xsvXXffXX") \
DECL(osl_##name##_dvdvv, "xsvvvXX") \
DECL(osl_##name##_dvdvdfvf, "xsvvXvfXX")
#define UNARY_OP_IMPL(name) \
DECL (osl_ ## name ## _ff, "ff") \
DECL (osl_ ## name ## _dfdf, "xXX") \
DECL (osl_ ## name ## _vv, "xXX") \
DECL (osl_ ## name ## _dvdv, "xXX")
#define UNARY_OP_IMPL(name) \
DECL(osl_##name##_ff, "ff") \
DECL(osl_##name##_dfdf, "xXX") \
DECL(osl_##name##_vv, "xXX") \
DECL(osl_##name##_dvdv, "xXX")
#define BINARY_OP_IMPL(name) \
DECL (osl_ ## name ## _fff, "fff") \
DECL (osl_ ## name ## _dfdfdf, "xXXX") \
DECL (osl_ ## name ## _dffdf, "xXfX") \
DECL (osl_ ## name ## _dfdff, "xXXf") \
DECL (osl_ ## name ## _vvv, "xXXX") \
DECL (osl_ ## name ## _dvdvdv, "xXXX") \
DECL (osl_ ## name ## _dvvdv, "xXXX") \
DECL (osl_ ## name ## _dvdvv, "xXXX")
#define BINARY_OP_IMPL(name) \
DECL(osl_##name##_fff, "fff") \
DECL(osl_##name##_dfdfdf, "xXXX") \
DECL(osl_##name##_dffdf, "xXfX") \
DECL(osl_##name##_dfdff, "xXXf") \
DECL(osl_##name##_vvv, "xXXX") \
DECL(osl_##name##_dvdvdv, "xXXX") \
DECL(osl_##name##_dvvdv, "xXXX") \
DECL(osl_##name##_dvdvv, "xXXX")
DECL (osl_add_closure_closure, "CXCC")
DECL (osl_mul_closure_float, "CXCf")
DECL (osl_mul_closure_color, "CXCc")
DECL (osl_allocate_closure_component, "CXii")
DECL (osl_allocate_weighted_closure_component, "CXiiX")
DECL (osl_closure_to_string, "sXC")
DECL (osl_format, "ss*")
DECL (osl_printf, "xXs*")
DECL (osl_fprintf, "xXss*")
DECL (osl_error, "xXs*")
DECL (osl_warning, "xXs*")
DECL (osl_split, "isXsii")
DECL (osl_incr_layers_executed, "xX")
DECL(osl_add_closure_closure, "CXCC")
DECL(osl_mul_closure_float, "CXCf")
DECL(osl_mul_closure_color, "CXCc")
DECL(osl_allocate_closure_component, "CXii")
DECL(osl_allocate_weighted_closure_component, "CXiiX")
DECL(osl_closure_to_string, "sXC")
DECL(osl_format, "ss*")
DECL(osl_printf, "xXs*")
DECL(osl_fprintf, "xXss*")
DECL(osl_error, "xXs*")
DECL(osl_warning, "xXs*")
DECL(osl_split, "isXsii")
DECL(osl_incr_layers_executed, "xX")
NOISE_IMPL(cellnoise)
//NOISE_DERIV_IMPL(cellnoise)
@@ -151,70 +150,70 @@ PNOISE_IMPL(psnoise)
PNOISE_DERIV_IMPL(psnoise)
GENERIC_PNOISE_DERIV_IMPL(gaborpnoise)
GENERIC_PNOISE_DERIV_IMPL(genericpnoise)
DECL (osl_noiseparams_set_anisotropic, "xXi")
DECL (osl_noiseparams_set_do_filter, "xXi")
DECL (osl_noiseparams_set_direction, "xXv")
DECL (osl_noiseparams_set_bandwidth, "xXf")
DECL (osl_noiseparams_set_impulses, "xXf")
DECL (osl_count_noise, "xX")
DECL (osl_hash_ii, "ii")
DECL (osl_hash_if, "if")
DECL (osl_hash_iff, "iff")
DECL (osl_hash_iv, "iX")
DECL (osl_hash_ivf, "iXf")
DECL(osl_noiseparams_set_anisotropic, "xXi")
DECL(osl_noiseparams_set_do_filter, "xXi")
DECL(osl_noiseparams_set_direction, "xXv")
DECL(osl_noiseparams_set_bandwidth, "xXf")
DECL(osl_noiseparams_set_impulses, "xXf")
DECL(osl_count_noise, "xX")
DECL(osl_hash_ii, "ii")
DECL(osl_hash_if, "if")
DECL(osl_hash_iff, "iff")
DECL(osl_hash_iv, "iX")
DECL(osl_hash_ivf, "iXf")
DECL (osl_spline_fff, "xXXXXii")
DECL (osl_spline_dfdfdf, "xXXXXii")
DECL (osl_spline_dfdff, "xXXXXii")
DECL (osl_spline_dffdf, "xXXXXii")
DECL (osl_spline_vfv, "xXXXXii")
DECL (osl_spline_dvdfdv, "xXXXXii")
DECL (osl_spline_dvdfv, "xXXXXii")
DECL (osl_spline_dvfdv, "xXXXXii")
DECL (osl_splineinverse_fff, "xXXXXii")
DECL (osl_splineinverse_dfdfdf, "xXXXXii")
DECL (osl_splineinverse_dfdff, "xXXXXii")
DECL (osl_splineinverse_dffdf, "xXXXXii")
DECL (osl_setmessage, "xXsLXisi")
DECL (osl_getmessage, "iXssLXiisi")
DECL (osl_pointcloud_search, "iXsXfiiXXii*")
DECL (osl_pointcloud_get, "iXsXisLX")
DECL (osl_pointcloud_write, "iXsXiXXX")
DECL (osl_pointcloud_write_helper, "xXXXisLX")
DECL (osl_blackbody_vf, "xXXf")
DECL (osl_wavelength_color_vf, "xXXf")
DECL (osl_luminance_fv, "xXXX")
DECL (osl_luminance_dfdv, "xXXX")
DECL (osl_prepend_color_from, "xXXs")
DECL (osl_prepend_matrix_from, "iXXs")
DECL (osl_get_matrix, "iXXs")
DECL (osl_get_inverse_matrix, "iXXs")
DECL (osl_transform_triple, "iXXiXiXXi")
DECL (osl_transform_triple_nonlinear, "iXXiXiXXi")
DECL (osl_transform_vmv, "xXXX")
DECL (osl_transform_dvmdv, "xXXX")
DECL (osl_transformv_vmv, "xXXX")
DECL (osl_transformv_dvmdv, "xXXX")
DECL (osl_transformn_vmv, "xXXX")
DECL (osl_transformn_dvmdv, "xXXX")
DECL (osl_transformc, "iXXiXiXX")
DECL(osl_spline_fff, "xXXXXii")
DECL(osl_spline_dfdfdf, "xXXXXii")
DECL(osl_spline_dfdff, "xXXXXii")
DECL(osl_spline_dffdf, "xXXXXii")
DECL(osl_spline_vfv, "xXXXXii")
DECL(osl_spline_dvdfdv, "xXXXXii")
DECL(osl_spline_dvdfv, "xXXXXii")
DECL(osl_spline_dvfdv, "xXXXXii")
DECL(osl_splineinverse_fff, "xXXXXii")
DECL(osl_splineinverse_dfdfdf, "xXXXXii")
DECL(osl_splineinverse_dfdff, "xXXXXii")
DECL(osl_splineinverse_dffdf, "xXXXXii")
DECL(osl_setmessage, "xXsLXisi")
DECL(osl_getmessage, "iXssLXiisi")
DECL(osl_pointcloud_search, "iXsXfiiXXii*")
DECL(osl_pointcloud_get, "iXsXisLX")
DECL(osl_pointcloud_write, "iXsXiXXX")
DECL(osl_pointcloud_write_helper, "xXXXisLX")
DECL(osl_blackbody_vf, "xXXf")
DECL(osl_wavelength_color_vf, "xXXf")
DECL(osl_luminance_fv, "xXXX")
DECL(osl_luminance_dfdv, "xXXX")
DECL(osl_prepend_color_from, "xXXs")
DECL(osl_prepend_matrix_from, "iXXs")
DECL(osl_get_matrix, "iXXs")
DECL(osl_get_inverse_matrix, "iXXs")
DECL(osl_transform_triple, "iXXiXiXXi")
DECL(osl_transform_triple_nonlinear, "iXXiXiXXi")
DECL(osl_transform_vmv, "xXXX")
DECL(osl_transform_dvmdv, "xXXX")
DECL(osl_transformv_vmv, "xXXX")
DECL(osl_transformv_dvmdv, "xXXX")
DECL(osl_transformn_vmv, "xXXX")
DECL(osl_transformn_dvmdv, "xXXX")
DECL(osl_transformc, "iXXiXiXX")
DECL (osl_dict_find_iis, "iXiX")
DECL (osl_dict_find_iss, "iXXX")
DECL (osl_dict_next, "iXi")
DECL (osl_dict_value, "iXiXLX")
DECL (osl_raytype_name, "iXs")
DECL(osl_dict_find_iis, "iXiX")
DECL(osl_dict_find_iss, "iXXX")
DECL(osl_dict_next, "iXi")
DECL(osl_dict_value, "iXiXLX")
DECL(osl_raytype_name, "iXs")
#ifdef OSL_LLVM_NO_BITCODE
DECL (osl_range_check, "iiiXXXiXiXX")
DECL(osl_range_check, "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_get_texture_options, "XX");
DECL (osl_get_noise_options, "XX");
DECL (osl_get_trace_options, "XX");
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");
// The following are defined inside llvm_ops.cpp. Only include these
@@ -231,17 +230,17 @@ UNARY_OP_IMPL(sinh)
UNARY_OP_IMPL(cosh)
UNARY_OP_IMPL(tanh)
DECL (osl_safe_div_iii, "iii")
DECL (osl_safe_div_fff, "fff")
DECL (osl_safe_mod_iii, "iii")
DECL (osl_sincos_fff, "xfXX")
DECL (osl_sincos_dfdff, "xXXX")
DECL (osl_sincos_dffdf, "xXXX")
DECL (osl_sincos_dfdfdf, "xXXX")
DECL (osl_sincos_vvv, "xXXX")
DECL (osl_sincos_dvdvv, "xXXX")
DECL (osl_sincos_dvvdv, "xXXX")
DECL (osl_sincos_dvdvdv, "xXXX")
DECL(osl_safe_div_iii, "iii")
DECL(osl_safe_div_fff, "fff")
DECL(osl_safe_mod_iii, "iii")
DECL(osl_sincos_fff, "xfXX")
DECL(osl_sincos_dfdff, "xXXX")
DECL(osl_sincos_dffdf, "xXXX")
DECL(osl_sincos_dfdfdf, "xXXX")
DECL(osl_sincos_vvv, "xXXX")
DECL(osl_sincos_dvdvv, "xXXX")
DECL(osl_sincos_dvvdv, "xXXX")
DECL(osl_sincos_dvdvdv, "xXXX")
UNARY_OP_IMPL(log)
UNARY_OP_IMPL(log2)
@@ -249,142 +248,147 @@ 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)
DECL (osl_pow_vvf, "xXXf")
DECL (osl_pow_dvdvdf, "xXXX")
DECL (osl_pow_dvvdf, "xXXX")
DECL (osl_pow_dvdvf, "xXXf")
BINARY_OP_IMPL(pow)
DECL(osl_pow_vvf, "xXXf")
DECL(osl_pow_dvdvdf, "xXXX")
DECL(osl_pow_dvvdf, "xXXX")
DECL(osl_pow_dvdvf, "xXXf")
UNARY_OP_IMPL(sqrt)
UNARY_OP_IMPL(inversesqrt)
UNARY_OP_IMPL(cbrt)
DECL (osl_logb_ff, "ff")
DECL (osl_logb_vv, "xXX")
DECL(osl_logb_ff, "ff")
DECL(osl_logb_vv, "xXX")
DECL (osl_floor_ff, "ff")
DECL (osl_floor_vv, "xXX")
DECL (osl_ceil_ff, "ff")
DECL (osl_ceil_vv, "xXX")
DECL (osl_round_ff, "ff")
DECL (osl_round_vv, "xXX")
DECL (osl_trunc_ff, "ff")
DECL (osl_trunc_vv, "xXX")
DECL (osl_sign_ff, "ff")
DECL (osl_sign_vv, "xXX")
DECL (osl_step_fff, "fff")
DECL (osl_step_vvv, "xXXX")
DECL(osl_floor_ff, "ff")
DECL(osl_floor_vv, "xXX")
DECL(osl_ceil_ff, "ff")
DECL(osl_ceil_vv, "xXX")
DECL(osl_round_ff, "ff")
DECL(osl_round_vv, "xXX")
DECL(osl_trunc_ff, "ff")
DECL(osl_trunc_vv, "xXX")
DECL(osl_sign_ff, "ff")
DECL(osl_sign_vv, "xXX")
DECL(osl_step_fff, "fff")
DECL(osl_step_vvv, "xXXX")
DECL (osl_isnan_if, "if")
DECL (osl_isinf_if, "if")
DECL (osl_isfinite_if, "if")
DECL (osl_abs_ii, "ii")
DECL (osl_fabs_ii, "ii")
DECL(osl_isnan_if, "if")
DECL(osl_isinf_if, "if")
DECL(osl_isfinite_if, "if")
DECL(osl_abs_ii, "ii")
DECL(osl_fabs_ii, "ii")
UNARY_OP_IMPL(abs)
UNARY_OP_IMPL(fabs)
BINARY_OP_IMPL(fmod)
DECL(osl_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")
DECL (osl_smoothstep_dffdff, "xXfXf")
DECL (osl_smoothstep_dffdfdf, "xXfXX")
DECL (osl_smoothstep_dfdfff, "xXXff")
DECL (osl_smoothstep_dfdffdf, "xXXfX")
DECL (osl_smoothstep_dfdfdff, "xXXXf")
DECL (osl_smoothstep_dfdfdfdf, "xXXXX")
DECL(osl_smoothstep_ffff, "ffff")
DECL(osl_smoothstep_dfffdf, "xXffX")
DECL(osl_smoothstep_dffdff, "xXfXf")
DECL(osl_smoothstep_dffdfdf, "xXfXX")
DECL(osl_smoothstep_dfdfff, "xXXff")
DECL(osl_smoothstep_dfdffdf, "xXXfX")
DECL(osl_smoothstep_dfdfdff, "xXXXf")
DECL(osl_smoothstep_dfdfdfdf, "xXXXX")
DECL (osl_dot_fvv, "fXX")
DECL (osl_dot_dfdvdv, "xXXX")
DECL (osl_dot_dfdvv, "xXXX")
DECL (osl_dot_dfvdv, "xXXX")
DECL (osl_cross_vvv, "xXXX")
DECL (osl_cross_dvdvdv, "xXXX")
DECL (osl_cross_dvdvv, "xXXX")
DECL (osl_cross_dvvdv, "xXXX")
DECL (osl_length_fv, "fX")
DECL (osl_length_dfdv, "xXX")
DECL (osl_distance_fvv, "fXX")
DECL (osl_distance_dfdvdv, "xXXX")
DECL (osl_distance_dfdvv, "xXXX")
DECL (osl_distance_dfvdv, "xXXX")
DECL (osl_normalize_vv, "xXX")
DECL (osl_normalize_dvdv, "xXX")
DECL(osl_dot_fvv, "fXX")
DECL(osl_dot_dfdvdv, "xXXX")
DECL(osl_dot_dfdvv, "xXXX")
DECL(osl_dot_dfvdv, "xXXX")
DECL(osl_cross_vvv, "xXXX")
DECL(osl_cross_dvdvdv, "xXXX")
DECL(osl_cross_dvdvv, "xXXX")
DECL(osl_cross_dvvdv, "xXXX")
DECL(osl_length_fv, "fX")
DECL(osl_length_dfdv, "xXX")
DECL(osl_distance_fvv, "fXX")
DECL(osl_distance_dfdvdv, "xXXX")
DECL(osl_distance_dfdvv, "xXXX")
DECL(osl_distance_dfvdv, "xXXX")
DECL(osl_normalize_vv, "xXX")
DECL(osl_normalize_dvdv, "xXX")
#endif
DECL (osl_mul_mmm, "xXXX")
DECL (osl_mul_mmf, "xXXf")
DECL(osl_mul_mmm, "xXXX")
DECL(osl_mul_mmf, "xXXf")
DECL (osl_div_mmm, "xXXX")
DECL (osl_div_mmf, "xXXf")
DECL (osl_div_mfm, "xXfX")
DECL(osl_div_mmm, "xXXX")
DECL(osl_div_mmf, "xXXf")
DECL(osl_div_mfm, "xXfX")
DECL (osl_get_from_to_matrix, "iXXss")
DECL (osl_transpose_mm, "xXX")
DECL (osl_determinant_fm, "fX")
DECL(osl_get_from_to_matrix, "iXXss")
DECL(osl_transpose_mm, "xXX")
DECL(osl_determinant_fm, "fX")
DECL (osl_concat_sss, "sss")
DECL (osl_strlen_is, "is")
DECL (osl_hash_is, "is")
DECL (osl_getchar_isi, "isi");
DECL (osl_startswith_iss, "iss")
DECL (osl_endswith_iss, "iss")
DECL (osl_stoi_is, "is")
DECL (osl_stof_fs, "fs")
DECL (osl_substr_ssii, "ssii")
DECL (osl_regex_impl, "iXsXisi")
DECL(osl_concat_sss, "sss")
DECL(osl_strlen_is, "is")
DECL(osl_hash_is, "is")
DECL(osl_getchar_isi, "isi");
DECL(osl_startswith_iss, "iss")
DECL(osl_endswith_iss, "iss")
DECL(osl_stoi_is, "is")
DECL(osl_stof_fs, "fs")
DECL(osl_substr_ssii, "ssii")
DECL(osl_regex_impl, "iXsXisi")
// Used by wide code generator, but are uniform calls
DECL (osl_texture_decode_wrapmode, "iX");
DECL (osl_texture_decode_interpmode, "iX");
DECL(osl_texture_decode_wrapmode, "is");
DECL(osl_texture_decode_interpmode, "is");
DECL (osl_texture_set_firstchannel, "xXi")
DECL (osl_texture_set_swrap, "xXs")
DECL (osl_texture_set_twrap, "xXs")
DECL (osl_texture_set_rwrap, "xXs")
DECL (osl_texture_set_stwrap, "xXs")
DECL (osl_texture_set_swrap_code, "xXi")
DECL (osl_texture_set_twrap_code, "xXi")
DECL (osl_texture_set_rwrap_code, "xXi")
DECL (osl_texture_set_stwrap_code, "xXi")
DECL (osl_texture_set_sblur, "xXf")
DECL (osl_texture_set_tblur, "xXf")
DECL (osl_texture_set_rblur, "xXf")
DECL (osl_texture_set_stblur, "xXf")
DECL (osl_texture_set_swidth, "xXf")
DECL (osl_texture_set_twidth, "xXf")
DECL (osl_texture_set_rwidth, "xXf")
DECL (osl_texture_set_stwidth, "xXf")
DECL (osl_texture_set_fill, "xXf")
DECL (osl_texture_set_time, "xXf")
DECL (osl_texture_set_interp, "xXs")
DECL (osl_texture_set_interp_code, "xXi")
DECL (osl_texture_set_subimage, "xXi")
DECL (osl_texture_set_subimagename, "xXs")
DECL (osl_texture_set_missingcolor_arena, "xXX")
DECL (osl_texture_set_missingcolor_alpha, "xXif")
DECL (osl_texture, "iXXXXffffffiXXXXXXX")
DECL (osl_texture3d, "iXXXXXXXXiXXXXXXX")
DECL (osl_environment, "iXXXXXXXiXXXXXXX")
DECL (osl_get_textureinfo, "iXXXXiiiXX")
DECL (osl_get_textureinfo_st, "iXXXffXiiiXX")
DECL(osl_texture_set_firstchannel, "xXi")
DECL(osl_texture_set_swrap, "xXs")
DECL(osl_texture_set_twrap, "xXs")
DECL(osl_texture_set_rwrap, "xXs")
DECL(osl_texture_set_stwrap, "xXs")
DECL(osl_texture_set_swrap_code, "xXi")
DECL(osl_texture_set_twrap_code, "xXi")
DECL(osl_texture_set_rwrap_code, "xXi")
DECL(osl_texture_set_stwrap_code, "xXi")
DECL(osl_texture_set_sblur, "xXf")
DECL(osl_texture_set_tblur, "xXf")
DECL(osl_texture_set_rblur, "xXf")
DECL(osl_texture_set_stblur, "xXf")
DECL(osl_texture_set_swidth, "xXf")
DECL(osl_texture_set_twidth, "xXf")
DECL(osl_texture_set_rwidth, "xXf")
DECL(osl_texture_set_stwidth, "xXf")
DECL(osl_texture_set_fill, "xXf")
DECL(osl_texture_set_time, "xXf")
DECL(osl_texture_set_interp, "xXs")
DECL(osl_texture_set_interp_code, "xXi")
DECL(osl_texture_set_subimage, "xXi")
DECL(osl_texture_set_subimagename, "xXs")
DECL(osl_texture_set_missingcolor_arena, "xXX")
DECL(osl_texture_set_missingcolor_alpha, "xXif")
DECL(osl_texture, "iXXXXffffffiXXXXXXX")
DECL(osl_texture3d, "iXXXXXXXXiXXXXXXX")
DECL(osl_environment, "iXXXXXXXiXXXXXXX")
DECL(osl_get_textureinfo, "iXXXXiiiXX")
DECL(osl_get_textureinfo_st, "iXXXffXiiiXX")
DECL (osl_trace_set_mindist, "xXf")
DECL (osl_trace_set_maxdist, "xXf")
DECL (osl_trace_set_shade, "xXi")
DECL (osl_trace_set_traceset, "xXs")
DECL (osl_trace, "iXXXXXXXX")
DECL(osl_trace_set_mindist, "xXf")
DECL(osl_trace_set_maxdist, "xXf")
DECL(osl_trace_set_shade, "xXi")
DECL(osl_trace_set_traceset, "xXs")
DECL(osl_trace, "iXXXXXXXX")
#ifdef OSL_LLVM_NO_BITCODE
DECL (osl_calculatenormal, "xXXX")
DECL (osl_area, "fX")
DECL (osl_filterwidth_fdf, "fX")
DECL (osl_filterwidth_vdv, "xXX")
DECL (osl_raytype_bit, "iXi")
DECL(osl_calculatenormal, "xXXX")
DECL(osl_area, "fX")
DECL(osl_filterwidth_fdf, "fX")
DECL(osl_filterwidth_vdv, "xXX")
DECL(osl_raytype_bit, "iXi")
#endif
+17 -17
View File
@@ -253,7 +253,7 @@ DECL(__OSL_MASKED_OP2(hash, Wi, Wv), "xXXi")
DECL(__OSL_MASKED_OP3(hash, Wi, Wv, Wf), "xXXXi")
// Need wide for combinations of the 3 parameters allowed to be uniform
// caveat, some combos are unreachable/uneeded
// caveat, some combos are unreachable/unneeded
// When result has a derivative, there is
// no "easy" have a input parameter be non-derivative based on code
// analysis promoting all inputs to be derivative base.
@@ -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,26 +362,26 @@ 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") // uneeded
//DECL (osl_get_texture_options, "XX") // unneeded
DECL(__OSL_OP(get_noise_options), "XX")
// The following are defined inside llvm_ops.cpp. Only include these
+3 -2
View File
@@ -8,9 +8,10 @@
#include <OpenImageIO/sysutil.h>
#include <OSL/oslconfig.h>
#include <OSL/oslclosure.h>
#include <OSL/genclosure.h>
#include <OSL/oslclosure.h>
#include <OSL/oslconfig.h>
#include "oslexec_pvt.h"
+17 -17
View File
@@ -4,8 +4,8 @@
#pragma once
#include <vector>
#include <list>
#include <vector>
#include <OpenImageIO/thread.h>
@@ -27,48 +27,48 @@ namespace pvt {
/// a new allocation tries to fit it in one of the allocated blocks, but
/// if it won't fit anywhere, it makes a new block and adds it to the
/// head of the list.
template<class T>
class ConstantPool {
template<class T> class ConstantPool {
public:
/// Allocate a new pool of T's. The quanta, if supplied, is the
/// number of T's to malloc at a time.
ConstantPool (size_t quanta = 1000000) : m_quanta(quanta), m_total(0) { }
ConstantPool(size_t quanta = 1000000) : m_quanta(quanta), m_total(0) {}
~ConstantPool () { }
~ConstantPool() {}
/// Allocate space enough for n T's, and return a pointer to the
/// start of that space.
T * alloc (size_t n) {
OIIO::lock_guard lock (m_mutex);
T* alloc(size_t n)
{
OIIO::lock_guard lock(m_mutex);
// Check each block in the block list to see if it has enough space
for (auto&& block : m_block_list) {
size_t s = block.size();
if ((s+n) <= block.capacity()) {
if ((s + n) <= block.capacity()) {
// Enough space in this block. Use it.
block.resize (s+n);
block.resize(s + n);
return &block[s];
}
}
// If we got here, there were no mini-blocks in the list with enough
// space. Make a new one.
m_block_list.push_front (block_t());
block_t &block (m_block_list.front());
size_t s = std::max (m_quanta, n);
block.reserve (s);
m_block_list.push_front(block_t());
block_t& block(m_block_list.front());
size_t s = std::max(m_quanta, n);
block.reserve(s);
m_total += s * sizeof(T);
block.resize (n);
block.resize(n);
return &block[0];
}
private:
typedef std::vector<T> block_t; ///< Type of block
std::list<block_t> m_block_list; ///< List of memory blocks
size_t m_quanta; ///< How big each memory block is (in T's, not bytes)
size_t m_total; ///< Total memory allocated (bytes!)
size_t m_quanta; ///< How big each memory block is (in T's, not bytes)
size_t m_total; ///< Total memory allocated (bytes!)
OIIO::mutex m_mutex; ///< Thread-safe lock
};
}; // namespace OSL::pvt
}; // namespace pvt
OSL_NAMESPACE_EXIT
+6 -5
View File
@@ -2410,21 +2410,22 @@ DECLFOLDER(constfold_gettextureinfo)
ustring filename = Filename.get_string();
ustring dataname = Dataname.get_string();
TypeDesc t = Data.typespec().simpletype();
void* mydata = OIIO_ALLOCA(char, t.size());
void* mydata = OSL_ALLOCA(char, t.size());
// FIXME(ptex) -- exclude folding of ptex, since these things
// can vary per face.
ustring errormessage;
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:
// assign data [retrieved values]
// assign result 1
// into this for failure:
// error "%s" errormesage
// error "%s" errormessage
// assign result 0
if (result) {
int oldresultarg = rop.inst()->args()[op.firstarg() + 0];
@@ -2776,7 +2777,7 @@ DECLFOLDER(constfold_pointcloud_get)
return 0;
// Must transfer to size_t array
size_t* indices = OIIO_ALLOCA(size_t, count);
size_t* indices = OSL_ALLOCA(size_t, count);
for (int i = 0; i < count; ++i)
indices[i] = Indices.get_int(i);
+13 -10
View File
@@ -128,11 +128,12 @@ ShadingContext::execute_init(ShaderGroup& sgroup, int shadeindex,
RunLLVMGroupFunc run_func = sgroup.llvm_compiled_init();
if (!run_func)
return false;
ssg.context = this;
ssg.renderer = renderer();
ssg.Ci = NULL;
ssg.context = this;
ssg.shadingStateUniform = &(shadingsys().m_shading_state_uniform);
ssg.renderer = renderer();
ssg.Ci = NULL;
run_func(&ssg, m_heap.get(), userdata_base_ptr, output_base_ptr,
shadeindex);
shadeindex, sgroup.interactive_arena_ptr());
}
if (profile)
@@ -159,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();
@@ -320,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());
}
}
@@ -359,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)
@@ -624,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)
{
+1 -1
View File
@@ -115,7 +115,7 @@ private:
};
typedef std::unordered_map<Query, QueryResult, QueryHash> QueryMap;
typedef std::unordered_map<ustring, int, ustringHash> DocMap;
typedef std::unordered_map<ustring, int> DocMap;
ShadingContext* m_context; // back-pointer to shading context
+84 -57
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());
@@ -301,7 +290,7 @@ ShaderInstance::parameters(const ParamValueList& params)
if (paramtype.arraylen < 0) {
// An array of definite size was supplied to a parameter
// that was an array of indefinite size. Magic! The trick
// here is that we need to allocate paramter space at the
// here is that we need to allocate parameter space at the
// END of the ordinary param storage, since when we assigned
// data offsets to each parameter, we didn't know the length
// needed to allocate this param in its proper spot.
@@ -330,12 +319,19 @@ ShaderInstance::parameters(const ParamValueList& params)
// definite length in subsequent rerenders. Don't do that.
} else {
// If the instance value is the same as the master's default,
// just skip the parameter, let it "keep" the default.
// Note that this can't/shouldn't happen for the indefinite-
// sized array case, which is why we have it in the 'else'
// clause of that test.
// just skip the parameter, let it "keep" the default by
// marking the source as DefaultVal.
//
// N.B. Beware the situation where it has init ops, and so the
// "default value" slot only coincidentally has the same value
// as the instance value. We can't mark it as DefaultVal in
// that case, because the init ops need to be run.
//
// Note that this case also can't/shouldn't happen for the
// indefinite- sized array case, which is why we have it in
// the 'else' clause of that test.
void* defaultdata = m_master->param_default_storage(i);
if (lockgeom
if (lockgeom && !sm->has_init_ops()
&& memcmp(defaultdata, data, valuetype.size()) == 0) {
// Must reset valuesource to default, in case the parameter
// was set already, and now is being changed back to default.
@@ -459,11 +455,9 @@ ShaderInstance::evaluate_writes_globals_and_userdata_params()
// userdata_params as accurately as we can based on what we know from
// the symbol overrides. This is very important to get instance merging
// working correctly.
int p = 0;
for (auto&& s : m_instoverrides) {
if (!s.lockgeom())
if (s.interpolated())
userdata_params(true);
++p;
}
}
@@ -501,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));
}
@@ -644,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;
}
}
@@ -663,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;
}
}
@@ -731,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()) {
@@ -744,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
@@ -767,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());
}
@@ -819,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
{
@@ -871,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";
}
}
+1852 -1827
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+159 -85
View File
@@ -6,14 +6,14 @@
#include <OSL/oslconfig.h>
#include <llvm/Pass.h>
#include <llvm/IR/Constants.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Type.h>
#include <llvm/IR/DerivedTypes.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/Instruction.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/Type.h>
#include <llvm/Pass.h>
#include <llvm/Support/Casting.h>
OSL_NAMESPACE_ENTER
@@ -37,16 +37,18 @@ namespace {
// how instruction lowering happens then this pass may not be necessary.
// Also if future LLVM version takes on the work of this optimization pass,
// then it may be removed.
template <int WidthT>
template<int WidthT>
class PreventBitMasksFromBeingLiveinsToBasicBlocks final
: public llvm::FunctionPass
{
typedef llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter> IRBuilder;
: public llvm::FunctionPass {
typedef llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>
IRBuilder;
llvm::Type* m_llvm_mask_type;
llvm::Type* m_native_mask_type;
llvm::Constant* m_wide_zero_initializer;
std::unordered_map<llvm::Instruction*, llvm::Value*> m_native_mask_by_producing_inst;
std::unordered_map<llvm::Value*, llvm::Value*> m_llvm_mask_from_livein_by_native_mask;
std::unordered_map<llvm::Instruction*, llvm::Value*>
m_native_mask_by_producing_inst;
std::unordered_map<llvm::Value*, llvm::Value*>
m_llvm_mask_from_livein_by_native_mask;
std::vector<llvm::Instruction*> m_phiNodesWithNativeMasks;
public:
@@ -57,11 +59,13 @@ public:
, m_llvm_mask_type(nullptr)
, m_native_mask_type(nullptr)
, m_wide_zero_initializer(nullptr)
{}
{
}
bool doInitialization (llvm::Module &M) override {
llvm::Type* llvm_type_bool = llvm::Type::getInt1Ty (M.getContext());
llvm::Type* llvm_type_int32 = llvm::Type::getInt32Ty (M.getContext());
bool doInitialization(llvm::Module& M) override
{
llvm::Type* llvm_type_bool = llvm::Type::getInt1Ty(M.getContext());
llvm::Type* llvm_type_int32 = llvm::Type::getInt32Ty(M.getContext());
#if OSL_LLVM_VERSION >= 110
m_llvm_mask_type = llvm::FixedVectorType::get(llvm_type_bool, WidthT);
@@ -72,39 +76,45 @@ public:
// what the native mask type should be. And if necessary maintain a
// 16 bit and 32 bit native mask representation to be passed as a
// livein.
m_native_mask_type = llvm::FixedVectorType::get(llvm_type_int32, WidthT);
# if OSL_LLVM_VERSION >= 112
m_wide_zero_initializer = llvm::ConstantDataVector::getSplat(WidthT,
llvm::ConstantInt::get(M.getContext(), llvm::APInt(32,0)));
# else
m_native_mask_type = llvm::FixedVectorType::get(llvm_type_int32,
WidthT);
# if OSL_LLVM_VERSION >= 112
m_wide_zero_initializer = llvm::ConstantDataVector::getSplat(
WidthT, llvm::ConstantInt::get(M.getContext(), llvm::APInt(32, 0)));
# else
m_wide_zero_initializer = llvm::ConstantVector::getSplat(
llvm::ElementCount(WidthT, false),
llvm::ConstantInt::get (M.getContext(), llvm::APInt(32,0)));
# endif
llvm::ElementCount(WidthT, false),
llvm::ConstantInt::get(M.getContext(), llvm::APInt(32, 0)));
# endif
#else
m_llvm_mask_type = llvm::VectorType::get(llvm_type_bool, WidthT);
m_llvm_mask_type = llvm::VectorType::get(llvm_type_bool, WidthT);
m_native_mask_type = llvm::VectorType::get(llvm_type_int32, WidthT);
m_wide_zero_initializer = llvm::ConstantVector::getSplat(WidthT, llvm::ConstantInt::get (M.getContext(), llvm::APInt(32,0)));
m_wide_zero_initializer = llvm::ConstantVector::getSplat(
WidthT, llvm::ConstantInt::get(M.getContext(), llvm::APInt(32, 0)));
#endif
return false; // I don't think we modified the module
return false; // I don't think we modified the module
}
bool runOnFunction(llvm::Function &F) override {
OSL_DEV_ONLY(llvm::errs() << ">>>>>>>>>>>>>>>>>>PreventBitMasksFromBeingLiveinsToBasicBlocks<" << WidthT << ">:");
bool runOnFunction(llvm::Function& F) override
{
OSL_DEV_ONLY(
llvm::errs()
<< ">>>>>>>>>>>>>>>>>>PreventBitMasksFromBeingLiveinsToBasicBlocks<"
<< WidthT << ">:");
OSL_DEV_ONLY(llvm::errs().write_escaped(F.getName()) << '\n');
m_native_mask_by_producing_inst.clear();
bool changed = false;
for (llvm::BasicBlock &bb : F) {
for (llvm::BasicBlock& bb : F) {
OSL_DEV_ONLY(llvm::errs() << ">>>>>>>>>Basic Block: ");
OSL_DEV_ONLY(llvm::errs().write_escaped(bb.getName()) << '\n');
m_phiNodesWithNativeMasks.clear();
m_llvm_mask_from_livein_by_native_mask.clear();
for (llvm::Instruction &inst : bb) {
for (llvm::Instruction& inst : bb) {
// We could possibly identify all the instruction types that
// we "think" could be using a mask, but feel just looking
// at the operand types is cheaper.
@@ -120,21 +130,24 @@ public:
// back to llvm masks.
IRBuilder builder(&bb);
builder.SetInsertPoint(&inst);
for (llvm::Instruction* phiNodeWithNativeMask : m_phiNodesWithNativeMasks) {
llvm::Value* llvm_mask = builder.CreateICmpSLT (phiNodeWithNativeMask,m_wide_zero_initializer);
for (llvm::Instruction* phiNodeWithNativeMask :
m_phiNodesWithNativeMasks) {
llvm::Value* llvm_mask
= builder.CreateICmpSLT(phiNodeWithNativeMask,
m_wide_zero_initializer);
// Now we need to replace all uses of phiNodeWithNativeMask with our converted llvm mask
auto use_iter = phiNodeWithNativeMask->use_begin(),
use_end = phiNodeWithNativeMask->use_end();
for (; use_iter != use_end;)
{
llvm::Use &use = *use_iter;
use_end = phiNodeWithNativeMask->use_end();
for (; use_iter != use_end;) {
llvm::Use& use = *use_iter;
++use_iter;
auto *user = llvm::dyn_cast<llvm::Instruction>(use.getUser());
// We need to skip the use wher the user is our conversion to a llvm_mask
auto* user = llvm::dyn_cast<llvm::Instruction>(
use.getUser());
// We need to skip the use where the user is our conversion to a llvm_mask
if (user && user == llvm_mask)
continue;
use.set(llvm_mask);
}
}
}
m_phiNodesWithNativeMasks.clear();
@@ -151,7 +164,8 @@ public:
bool phiNodeHadOperandReplacedInLastPassOverOperands;
OSL_DEV_ONLY(llvm::errs() << ">>>>Op: ");
OSL_DEV_ONLY(llvm::errs().write_escaped(inst.getOpcodeName()) << '\n');
OSL_DEV_ONLY(llvm::errs().write_escaped(inst.getOpcodeName())
<< '\n');
// As we may have multiple operands that need to be replaced
// for a phi node, once we discover a qualifying replacement
@@ -167,25 +181,32 @@ public:
// As we could be replacing operands, but not the number of operands
// we use index vs. iterator based loop construct
for (unsigned operand_i = 0, num_operands = inst.getNumOperands();
operand_i != num_operands;
++operand_i) {
llvm::Value *op_val = inst.getOperand (operand_i);
for (unsigned operand_i = 0,
num_operands = inst.getNumOperands();
operand_i != num_operands; ++operand_i) {
llvm::Value* op_val = inst.getOperand(operand_i);
if (op_val != nullptr) {
llvm::Type* op_type = op_val->getType();
llvm::Type* op_type = op_val->getType();
if (op_type == m_llvm_mask_type) {
// See if the value came from an instruction
auto *producing_instr = llvm::dyn_cast<llvm::Instruction>(op_val);
auto* producing_instr
= llvm::dyn_cast<llvm::Instruction>(op_val);
if (producing_instr != nullptr) {
llvm::BasicBlock* producing_bb = producing_instr->getParent();
llvm::BasicBlock* producing_bb
= producing_instr->getParent();
// If a phi node needs to have one operand promoted,
// it will need all operands promoted even if they were
// produced in the same basic block, so the types match
if (phiNodeHadOperandReplaced || producing_bb != &bb) {
OSL_DEV_ONLY(llvm::errs() << "Uses llvm mask <" <<WidthT << "xi1> from different Basic Block: ");
OSL_DEV_ONLY(llvm::errs().write_escaped(op_val->getName()) << '\n');
if (phiNodeHadOperandReplaced
|| producing_bb != &bb) {
OSL_DEV_ONLY(
llvm::errs()
<< "Uses llvm mask <" << WidthT
<< "xi1> from different Basic Block: ");
OSL_DEV_ONLY(llvm::errs().write_escaped(
op_val->getName())
<< '\n');
changed = true;
// We can't let an unrepresentable data type of <16xi1>, <8xi1> or <4xi1>
@@ -195,37 +216,68 @@ public:
llvm::Value* native_mask = nullptr;
{
// We may have already created a native mask for this instruction
auto search_result = m_native_mask_by_producing_inst.find(producing_instr);
if (search_result == m_native_mask_by_producing_inst.end()) {
auto search_result
= m_native_mask_by_producing_inst
.find(producing_instr);
if (search_result
== m_native_mask_by_producing_inst
.end()) {
// Scan producing basic block for an existing sign extend instruction
// for the producing_instr. As the existence of a basic block means
// we most likely have a branch higher up whose test required a sign extend
for (llvm::Instruction &other_inst : *producing_bb) {
auto *existing_sign_ext = llvm::dyn_cast<llvm::SExtInst>(&other_inst);
for (llvm::Instruction&
other_inst :
*producing_bb) {
auto* existing_sign_ext
= llvm::dyn_cast<
llvm::SExtInst>(
&other_inst);
if (existing_sign_ext) {
OSL_ASSERT(existing_sign_ext->getNumOperands() == 1);
llvm::Value *existing_operand = existing_sign_ext->getOperand (0);
if (existing_operand == producing_instr) {
OSL_ASSERT(existing_sign_ext->getType() == m_native_mask_type);
OSL_DEV_ONLY(llvm::errs() << "Using existing sign ext in producing bb\n");
OSL_ASSERT(
existing_sign_ext
->getNumOperands()
== 1);
llvm::Value*
existing_operand
= existing_sign_ext
->getOperand(
0);
if (existing_operand
== producing_instr) {
OSL_ASSERT(
existing_sign_ext
->getType()
== m_native_mask_type);
OSL_DEV_ONLY(
llvm::errs()
<< "Using existing sign ext in producing bb\n");
native_mask = existing_sign_ext;
native_mask
= existing_sign_ext;
break;
}
}
}
if (nullptr == native_mask) {
IRBuilder builder(producing_bb);
builder.SetInsertPoint(&producing_bb->back());
IRBuilder builder(
producing_bb);
builder.SetInsertPoint(
&producing_bb->back());
native_mask = builder.CreateSExt(producing_instr, m_native_mask_type);
native_mask
= builder.CreateSExt(
producing_instr,
m_native_mask_type);
// NOTE: we did add instructions, but not to the BB we are currently
// iterating over instructions
}
m_native_mask_by_producing_inst.insert(std::make_pair(producing_instr,native_mask));
m_native_mask_by_producing_inst
.insert(std::make_pair(
producing_instr,
native_mask));
} else {
native_mask = search_result->second;
native_mask
= search_result->second;
}
}
OSL_ASSERT(native_mask);
@@ -239,16 +291,26 @@ public:
llvm::Value* llvm_mask = nullptr;
{
// We may have already created a llvm mask in this basic block for the native mask
auto search_result = m_llvm_mask_from_livein_by_native_mask.find(native_mask);
if (search_result == m_llvm_mask_from_livein_by_native_mask.end()) {
auto search_result
= m_llvm_mask_from_livein_by_native_mask
.find(native_mask);
if (search_result
== m_llvm_mask_from_livein_by_native_mask
.end()) {
// Insert the conversion from native to llvm mask
// somewhere before the 1st instruction that needs to use it in this basic block
IRBuilder builder(&bb);
builder.SetInsertPoint(&inst);
builder.SetInsertPoint(
&inst);
llvm_mask = builder.CreateICmpSLT (native_mask,m_wide_zero_initializer);
llvm_mask = builder.CreateICmpSLT(
native_mask,
m_wide_zero_initializer);
m_llvm_mask_from_livein_by_native_mask.insert(std::make_pair(native_mask,llvm_mask));
m_llvm_mask_from_livein_by_native_mask
.insert(std::make_pair(
native_mask,
llvm_mask));
// NOTE: we did add instructions to this bb,
// but the should be inserted before the current inst.
@@ -257,12 +319,13 @@ public:
// iterator should not invalidate the iterator
} else {
llvm_mask = search_result->second;
llvm_mask
= search_result->second;
}
}
inst.setOperand (operand_i, llvm_mask);
inst.setOperand(operand_i,
llvm_mask);
} else {
// Phi nodes have to exist at the top of a basic block which precludes
// our basic algorithm from just converting the native mask back to a llvm mask
// before the phi node.
@@ -270,24 +333,37 @@ public:
// and insert an instruction to convert it after the block of phi nodes
// However, this now means we will need to find all uses of the phi node's
// result and replace them with our converted llvm_mask
inst.setOperand (operand_i, native_mask);
inst.setOperand(operand_i,
native_mask);
phiNodeHadOperandReplaced = true;
phiNodeHadOperandReplacedInLastPassOverOperands = true;
phiNodeHadOperandReplacedInLastPassOverOperands
= true;
}
// We should be able to continue iterating over the rest of the operands
}
} else if (phiNodeHadOperandReplaced) {
auto *constant = llvm::dyn_cast<llvm::Constant>(op_val);
auto* constant
= llvm::dyn_cast<llvm::Constant>(
op_val);
if (constant) {
OSL_DEV_ONLY(llvm::errs() << "Uses constant llvm mask <" <<WidthT << "xi1> \n");
OSL_DEV_ONLY(
llvm::errs()
<< "Uses constant llvm mask <"
<< WidthT << "xi1> \n");
// Should handle promoting whatever the constant value is (most likely zeroinitializer)
llvm::ConstantFolder Folder;
auto *signExtConstant = Folder.CreateCast(llvm::Instruction::SExt, constant, m_native_mask_type);
auto* signExtConstant
= Folder.CreateCast(
llvm::Instruction::SExt,
constant, m_native_mask_type);
inst.setOperand (operand_i, signExtConstant);
inst.setOperand(operand_i,
signExtConstant);
} else {
OSL_ASSERT(0 && "Unhandled/Unexpected llvm mask type");
OSL_ASSERT(
0
&& "Unhandled/Unexpected llvm mask type");
}
}
}
@@ -321,11 +397,9 @@ public:
// including this file will need its own static members defined. LLVM will
// assign IDs when they get registered, so this initialization value is not
// important.
template<>
char PreventBitMasksFromBeingLiveinsToBasicBlocks<8>::ID = 0;
template<> char PreventBitMasksFromBeingLiveinsToBasicBlocks<8>::ID = 0;
template<>
char PreventBitMasksFromBeingLiveinsToBasicBlocks<16>::ID = 0;
template<> char PreventBitMasksFromBeingLiveinsToBasicBlocks<16>::ID = 0;
} // end of anonymous namespace
+2491 -2231
View File
File diff suppressed because it is too large Load Diff
+9 -3
View File
@@ -72,7 +72,7 @@ private:
int m_oso_major, m_oso_minor; ///< oso file format version
int m_sym_default_index; ///< Next sym default value to fill in
bool m_errors; ///< Did we hit any errors?
typedef std::unordered_map<ustring, int, ustringHash> UstringIntMap;
typedef std::unordered_map<ustring, int> UstringIntMap;
UstringIntMap m_symmap; ///< map sym name to index
};
@@ -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);
+141 -125
View File
@@ -12,23 +12,23 @@ OSL_NAMESPACE_ENTER
static ustring udot(".");
Parser::Parser(const std::vector<ustring> *user_events,
const std::vector<ustring> *user_scatterings)
Parser::Parser(const std::vector<ustring>* user_events,
const std::vector<ustring>* user_scatterings)
{
m_ingroup = false;
m_error = "";
m_error = "";
m_label_position[Labels::CAMERA] = 0;
m_label_position[Labels::LIGHT] = 0;
m_label_position[Labels::CAMERA] = 0;
m_label_position[Labels::LIGHT] = 0;
m_label_position[Labels::BACKGROUND] = 0;
m_label_position[Labels::VOLUME] = 0;
m_label_position[Labels::TRANSMIT] = 0;
m_label_position[Labels::REFLECT] = 0;
m_label_position[Labels::OBJECT] = 0;
m_label_position[Labels::DIFFUSE] = 1;
m_label_position[Labels::GLOSSY] = 1;
m_label_position[Labels::SINGULAR] = 1;
m_label_position[Labels::STRAIGHT] = 1;
m_label_position[Labels::VOLUME] = 0;
m_label_position[Labels::TRANSMIT] = 0;
m_label_position[Labels::REFLECT] = 0;
m_label_position[Labels::OBJECT] = 0;
m_label_position[Labels::DIFFUSE] = 1;
m_label_position[Labels::GLOSSY] = 1;
m_label_position[Labels::SINGULAR] = 1;
m_label_position[Labels::STRAIGHT] = 1;
m_basic_labels.insert(Labels::CAMERA);
m_basic_labels.insert(Labels::LIGHT);
@@ -47,42 +47,40 @@ Parser::Parser(const std::vector<ustring> *user_events,
m_minus_stop.insert(Labels::STOP);
if (user_events)
for (size_t i = 0; i < user_events->size(); ++i)
{
m_label_position[(*user_events)[i]] = 0;
m_basic_labels.insert((*user_events)[i]);
}
if (user_scatterings)
for (size_t i = 0; i < user_scatterings->size(); ++i)
{
m_label_position[(*user_scatterings)[i]] = 1;
m_basic_labels.insert((*user_scatterings)[i]);
}
for (auto&& e : *user_events) {
m_label_position[e] = 0;
m_basic_labels.insert(e);
}
if (user_scatterings)
for (auto&& s : *user_scatterings) {
m_label_position[s] = 1;
m_basic_labels.insert(s);
}
}
LPexp *
Parser::buildStop(LPexp *etype, LPexp *scatter, const std::list<LPexp*> &custom)
LPexp*
Parser::buildStop(LPexp* etype, LPexp* scatter, const std::list<LPexp*>& custom)
{
lpexp::Cat *cat = new lpexp::Cat();
lpexp::Cat* cat = new lpexp::Cat();
cat->append(etype);
cat->append(scatter);
for (std::list<LPexp*>::const_iterator i = custom.begin(); i != custom.end(); ++i)
cat->append(*i);
for (const auto& p : custom)
cat->append(p);
if (custom.size() < 5)
cat->append (new lpexp::Repeat (new lpexp::Wildexp (m_basic_labels)));
cat->append(new lpexp::Repeat(new lpexp::Wildexp(m_basic_labels)));
cat->append(new lpexp::Symbol(Labels::STOP));
return cat;
}
LPexp *
LPexp*
Parser::parseSymbol()
{
bool iscustom = false;
ustring sym = parseRawSymbol(iscustom);
ustring sym = parseRawSymbol(iscustom);
if (m_ingroup) {
if (sym == udot)
return new lpexp::Wildexp(m_minus_stop);
@@ -90,25 +88,26 @@ Parser::parseSymbol()
return new lpexp::Symbol(sym);
} else {
if (iscustom) {
std::list<LPexp *> custom;
std::list<LPexp*> custom;
custom.push_back(new lpexp::Symbol(sym));
return buildStop(new lpexp::Wildexp(m_minus_stop), new lpexp::Wildexp(m_minus_stop), custom);
return buildStop(new lpexp::Wildexp(m_minus_stop),
new lpexp::Wildexp(m_minus_stop), custom);
} else {
LPexp *basics[2] = {NULL, NULL};
LPexp* basics[2] = { NULL, NULL };
if (sym != ".") {
SymbolToInt::const_iterator i = m_label_position.find(sym);
if (i == m_label_position.end()) {
m_error = std::string("Unrecognized basic label: ") + sym.c_str();
return NULL;
m_error = fmtformat("Unrecognized basic label: {}", sym);
return nullptr;
}
int pos = i->second;
int pos = i->second;
basics[pos] = new lpexp::Symbol(sym);
}
for (int k = 0; k < 2; ++k)
if (!basics[k])
basics[k] = new lpexp::Wildexp(m_minus_stop);
std::list<LPexp *> empty;
return buildStop (basics[0], basics[1], empty);
std::list<LPexp*> empty;
return buildStop(basics[0], basics[1], empty);
}
}
}
@@ -116,7 +115,7 @@ Parser::parseSymbol()
ustring
Parser::parseRawSymbol(bool &iscustom)
Parser::parseRawSymbol(bool& iscustom)
{
std::string sym;
if (head() == '\'') {
@@ -144,47 +143,49 @@ Parser::parseRawSymbol(bool &iscustom)
LPexp *
LPexp*
Parser::parseCat()
{
//lpexp::Cat *cat = new lpexp::Cat();
std::vector<LPexp *> explist;
std::vector<LPexp*> explist;
char endchar;
if (head() == '(') {
next();
endchar = ')';
}
else endchar = 0;
} else
endchar = 0;
while (hasInput() && head() != endchar) {
while (hasInput() && head() != endchar) {
if (head() == '|') {
if (!explist.size()) {
m_error = "No left expression to or with |";
for (size_t i=0; i < explist.size(); ++i)
delete explist[i];
return NULL;
for (auto& exp : explist)
delete exp;
return nullptr;
}
next();
LPexp *e = _parse();
LPexp* e = _parse();
if (error()) {
for (size_t i=0; i < explist.size(); ++i)
delete explist[i];
return NULL;
delete e;
for (auto& exp : explist)
delete exp;
return nullptr;
}
if (explist.back()->getType() == lpexp::OR)
((lpexp::Orlist*)explist.back())->append(e);
else {
lpexp::Orlist *orexp = new lpexp::Orlist();
lpexp::Orlist* orexp = new lpexp::Orlist();
orexp->append(explist.back());
orexp->append(e);
explist[explist.size() - 1] = orexp;
}
} else {
LPexp *e = _parse();
LPexp* e = _parse();
if (error()) {
for (size_t i=0; i < explist.size(); ++i)
delete explist[i];
return NULL;
delete e;
for (auto& exp : explist)
delete exp;
return nullptr;
}
explist.push_back(e);
}
@@ -193,41 +194,47 @@ Parser::parseCat()
next();
else if (endchar != 0) {
m_error = "Reached end of line looking for )";
for (size_t i=0; i < explist.size(); ++i)
delete explist[i];
return NULL;
for (auto& exp : explist)
delete exp;
return nullptr;
}
lpexp::Cat *cat = new lpexp::Cat();
for (size_t i=0; i < explist.size(); ++i)
cat->append(explist[i]);
lpexp::Cat* cat = new lpexp::Cat();
for (auto& exp : explist)
cat->append(exp);
return cat;
}
LPexp *
LPexp*
Parser::parseGroup()
{
OSL_DASSERT(head() == '<');
if (m_ingroup) {
m_error = "No groups allowed inside of groups";
return NULL;
return nullptr;
}
int basicpos = 0;
LPexp *basics[2] = {NULL, NULL};
std::list<LPexp *> custom;
#define THROWAWAY() do{\
for (int i=0;i<2;++i) if(basics[i]) delete basics[i];\
for (std::list<LPexp *>::iterator i = custom.begin();i!=custom.end();++i) delete *i;\
m_ingroup = false;\
return NULL;\
}while(0)
int basicpos = 0;
LPexp* basics[2] = { nullptr, nullptr };
std::list<LPexp*> custom;
#define THROWAWAY() \
do { \
delete basics[0]; \
delete basics[1]; \
for (auto& p : custom) \
delete p; \
m_ingroup = false; \
return nullptr; \
} while (0)
m_ingroup = true;
next();
while (hasInput() && head() != '>') {
LPexp *e = _parse();
if (error()) THROWAWAY();
LPexp* e = _parse();
if (error()) {
delete e;
THROWAWAY();
}
if (basicpos < 2)
basics[basicpos++] = e;
else
@@ -247,65 +254,69 @@ Parser::parseGroup()
LPexp *
LPexp*
Parser::parseNegor()
{
OSL_DASSERT (head() == '^');
OSL_DASSERT(head() == '^');
SymbolSet symlist;
symlist.insert(Labels::STOP); // never allowed
symlist.insert(Labels::STOP); // never allowed
int pos = -1;
next();
while (hasInput() && head() != ']') {
bool iscustom = false;
ustring sym = parseRawSymbol(iscustom);
if (error()) return NULL;
ustring sym = parseRawSymbol(iscustom);
if (error())
return nullptr;
symlist.insert(sym);
if (iscustom) {
if (symlist.size() > 2 && pos != -1)
std::cerr << "[pathexp] you are mixing labels of different type in [...]" << std::endl;
if (symlist.size() > 2 && pos != -1)
std::cerr
<< "[pathexp] you are mixing labels of different type in [...]"
<< std::endl;
pos = -1;
} else {
SymbolToInt::const_iterator found = m_label_position.find(sym);
if (found == m_label_position.end()) {
m_error = "Unrecognized basic label";
return NULL;
return nullptr;
}
if (symlist.size() > 2 && found->second != pos)
std::cerr << "[pathexp] you are mixing labels of different type in [...]" << std::endl;
if (symlist.size() > 2 && found->second != pos)
std::cerr
<< "[pathexp] you are mixing labels of different type in [...]"
<< std::endl;
pos = found->second;
}
}
if (!hasInput()) {
m_error = "Reached end of line looking for ] to end an negative or list'";
return NULL;
m_error
= "Reached end of line looking for ] to end an negative or list'";
return nullptr;
}
if (symlist.size() < 2) {
m_error = "Empty or list [^] not allowed";
return NULL;
return nullptr;
}
next();
lpexp::Wildexp *wildcard = new lpexp::Wildexp(symlist);
lpexp::Wildexp* wildcard = new lpexp::Wildexp(symlist);
if (m_ingroup)
return wildcard;
else {
std::list<LPexp *> custom;
if (pos < 0) { // is a custom label
std::list<LPexp*> custom;
if (pos < 0) { // is a custom label
custom.push_back(wildcard);
return buildStop(new lpexp::Wildexp(m_minus_stop), new lpexp::Wildexp(m_minus_stop), custom);
return buildStop(new lpexp::Wildexp(m_minus_stop),
new lpexp::Wildexp(m_minus_stop), custom);
} else {
LPexp *basics[2] = {NULL, NULL};
basics[pos] = wildcard;
for (int i = 0; i < 2; ++i)
if (!basics[i])
basics[i] = new lpexp::Wildexp(m_minus_stop);
return buildStop(basics[0], basics[1], custom);
LPexp* w2 = new lpexp::Wildexp(m_minus_stop);
return buildStop(pos == 0 ? wildcard : w2, pos == 0 ? w2 : wildcard,
custom);
}
}
}
LPexp *
LPexp*
Parser::parseOrlist()
{
OSL_DASSERT(head() == '[');
@@ -313,19 +324,20 @@ Parser::parseOrlist()
if (hasInput() && head() == '^')
return parseNegor();
else {
lpexp::Orlist *orlist = new lpexp::Orlist();
lpexp::Orlist* orlist = new lpexp::Orlist();
while (hasInput() && head() != ']') {
LPexp *e = _parse();
LPexp* e = _parse();
if (error()) {
delete e;
delete orlist;
return NULL;
return nullptr;
}
orlist->append(e);
}
if (!hasInput()) {
m_error = "Reached end of line looking for ] to end an or list";
delete orlist;
return NULL;
return nullptr;
}
next();
return orlist;
@@ -360,29 +372,32 @@ Parser::parseRange()
}
next();
if (secondnum.size())
return std::pair<int, int>(atoi(firstnum.c_str()), atoi(secondnum.c_str()));
return std::pair<int, int>(OIIO::Strutil::stoi(firstnum),
OIIO::Strutil::stoi(secondnum));
else
return std::pair<int, int>(atoi(firstnum.c_str()), atoi(firstnum.c_str()));
return std::pair<int, int>(OIIO::Strutil::stoi(firstnum),
OIIO::Strutil::stoi(firstnum));
}
LPexp *
Parser::parseModifier(LPexp *e)
LPexp*
Parser::parseModifier(LPexp* e)
{
if (hasInput()) {
if (m_ingroup && (head() == '*' || head() == '{' || head() == '+')) {
m_error = std::string("Repetitions not allowed inside '<...>'");
return NULL;
return nullptr;
}
if (head() == '*') {
next();
return new lpexp::Repeat(e);
} else if (head() == '{') {
std::pair<int, int> range = parseRange();
if (error()) return NULL;
if (error())
return nullptr;
if (range.second < 0) {
lpexp::Cat *cat = new lpexp::Cat();
lpexp::Cat* cat = new lpexp::Cat();
cat->append(new lpexp::NRepeat(e, range.first, range.first));
cat->append(new lpexp::Repeat(e->clone()));
return cat;
@@ -390,23 +405,22 @@ Parser::parseModifier(LPexp *e)
return new lpexp::NRepeat(e, range.first, range.second);
} else if (head() == '+') {
next();
lpexp::Cat *cat = new lpexp::Cat();
lpexp::Cat* cat = new lpexp::Cat();
cat->append(e);
cat->append(new lpexp::Repeat(e->clone()));
return cat;
} else
return e;
}
else
} else
return e;
}
LPexp *
LPexp*
Parser::_parse()
{
LPexp *e;
LPexp* e = nullptr;
if (head() == '(')
e = parseCat();
else if (head() == '[')
@@ -415,24 +429,26 @@ Parser::_parse()
e = parseGroup();
else
e = parseSymbol();
if (error())
return NULL;
if (error()) {
delete e;
return nullptr;
}
return parseModifier(e);
}
LPexp *
Parser::parse(const char *text)
LPexp*
Parser::parse(const char* text)
{
m_error = "";
m_text = text;
m_pos = 0;
m_error = "";
m_text = text;
m_pos = 0;
m_ingroup = false;
if (hasInput())
return parseCat();
else
return NULL;
return nullptr;
}
+79 -80
View File
@@ -33,92 +33,91 @@ using lpexp::LPexp;
/// exp := wildexp | borexp | sorexp | catexp | group | repeat | repeat+ | mnrepeat
/// topexp := exp | topexp exp
///
class Parser
{
public:
class Parser {
public:
Parser(const std::vector<ustring>* user_events = NULL,
const std::vector<ustring>* user_scatterings = NULL);
Parser(const std::vector<ustring> *user_events = NULL,
const std::vector<ustring> *user_scatterings = NULL);
/// Parse a string and return the resulting light path expression tree or NULL if failed
LPexp* parse(const char* text);
/// Parse a string and return the resulting light path expression tree or NULL if failed
LPexp *parse(const char *text);
/// Check for error in the last parsed string
bool error() const { return m_error.size() > 0; };
/// Get the error string
const char* getErrorMsg() const { return m_error.c_str(); };
/// Get the position of the string where the error appeared
int getErrorPos() const { return m_pos; };
/// Check for error in the last parsed string
bool error()const { return m_error.size() > 0; };
/// Get the error string
const char *getErrorMsg()const { return m_error.c_str(); };
/// Get the position of the string where the error appeared
int getErrorPos()const { return m_pos; };
private:
/// Current char being parsed
char head() const { return m_text[m_pos]; };
/// Any input (including head) left?
bool hasInput() const { return m_text.size() > m_pos; };
/// Go to the next char in the string
void next() { m_pos++; };
private:
/// build the complete pattern for a pathtracing stop
///
/// That means the three basic label match expressions, plus those for the custom labels (if any),
/// plus an additional wildcard to eat extra custom labels at the end, and finally the stop mark.
/// So you provide the regexps for the basic three labels:
///
/// \param etype Event type (CFVL)
/// \param dir Direction (RD)
/// \param scatter Scattering type (DGSs)
///
/// That of course can be wildcards or any other expression willing to match them. And then you can
/// provide extra expressions to match the custom labels:
///
/// \param custom Custom label regexps
///
/// And the function will automatically add a "[^stop_mark]*stop_mark" at the end.
///
LPexp* buildStop(LPexp* etype, LPexp* scatter,
const std::list<LPexp*>& custom);
/// Given that a symbol is ready in head() to parse, parse it
LPexp* parseSymbol();
/// Given that a symbol is ready in head() to parse, parse it as a ustring
/// and report it was a custom symbol in the iscustom flag
ustring parseRawSymbol(bool& iscustom);
/// Given that the beginning of a concatenation of regexps is ready to
/// parse, parse it and it can be optionally be enclosed in parentheses ()
LPexp* parseCat();
/// Given that a fully qualified group like <.RD'custom'> is ready to parse, parse it
LPexp* parseGroup();
/// Given that a ^abcde] (note missing [) is ready to parse, parse it
LPexp* parseNegor();
/// Given that [abcde] is ready to parse, parse it, but if it finds that it was actually
/// [^abcd], fall back to parseNegor
LPexp* parseOrlist();
/// Given that a range like {5,7} or {2,} or {3} is ready to parse, parse it and return
/// the range. Second number being -1 if if was {2,} and equals the first if it was {3}
std::pair<int, int> parseRange();
/// Take an already parsed lpexp and parse its possible modifier (*={}) if present and
/// return the new lpexp
LPexp* parseModifier(LPexp* e);
/// Generic parse whatever comes next (just one item)
LPexp* _parse();
/// Current char being parsed
char head()const { return m_text[m_pos]; };
/// Any input (including head) left?
bool hasInput()const { return m_text.size() > m_pos; };
/// Go to the next char in the string
void next() { m_pos++; };
// error string
std::string m_error;
// True if we are actually parsing a group <>, since otherwise everything gets
// automatically converted to a group, this prevents that happening
bool m_ingroup;
// maps each basic label to its expected position in the appearance order,
// for instance the direction label can't be in the first pos of a group.
// This way we know where to put the expression when the user writes just
// S, which translates to <..S>
SymbolToInt m_label_position;
// The set of the basic labels
SymbolSet m_basic_labels;
// The black list for our wildcards, that have to exclude always the stop mark
SymbolSet m_minus_stop;
/// build the complete pattern for a pathtracing stop
///
/// That means the three basic label match expressions, plus those for the custom labels (if any),
/// plus an additional wildcard to eat extra custom labels at the end, and finally the stop mark.
/// So you provide the regexps for the basic three labels:
///
/// \param etype Event type (CFVL)
/// \param dir Direction (RD)
/// \param scatter Scattering type (DGSs)
///
/// That of course can be wildcards or any other expression willing to match them. And then you can
/// provide extra expressions to match the custom labels:
///
/// \param custom Custom label regexps
///
/// And the function will automatically add a "[^stop_mark]*stop_mark" at the end.
///
LPexp *buildStop(LPexp *etype, LPexp *scatter, const std::list<LPexp*> &custom);
/// Gicen that a symbol is ready in head() to parse, parse it
LPexp *parseSymbol();
/// Gicen that a symbol is ready in head() to parse, parse it as a ustring
/// and report it was a custom symbol in the iscustom flag
ustring parseRawSymbol(bool &iscustom);
/// Given that the begining of a concatenation of regexps is ready to parse, parse it
/// and it can be optionally be enclosed in parentheses ()
LPexp *parseCat();
/// Given that a fully qualified group like <.RD'custom'> is ready to parse, parse it
LPexp *parseGroup();
/// Given that a ^abcde] (note missing [) is ready to parse, parse it
LPexp *parseNegor();
/// Given that [abcde] is ready to parse, parse it, but if it finds that it was actually
/// [^abcd], fall back to parseNegor
LPexp *parseOrlist();
/// Given that a range like {5,7} or {2,} or {3} is ready to parse, parse it and return
/// the range. Second number being -1 if if was {2,} and equals the first if it was {3}
std::pair<int, int> parseRange();
/// Take an already parsed lpexp and parse its possible modifier (*={}) if present and
/// return the new lpexp
LPexp *parseModifier(LPexp *e);
/// Generic parse whatever comes next (just one item)
LPexp *_parse();
// error string
std::string m_error;
// True if we are actually parsing a group <>, since otherwise everything gets
// automatically converted to a group, this prevents that happening
bool m_ingroup;
// maps each basic label to its expected possition in the appearance order, for instance
// the direction label can't be in the first pos of a group. This way we know where to put the
// expression when the user writes just S, which translates to <..S>
SymbolToInt m_label_position;
// The set of the basic labels
SymbolSet m_basic_labels;
// The black list for our wildcards, that have to exclude always the stop mark
SymbolSet m_minus_stop;
// Current text being parsed
std::string m_text;
// Current position in the text for head()
size_t m_pos;
// Current text being parsed
std::string m_text;
// Current position in the text for head()
size_t m_pos;
};
+1 -1
View File
@@ -75,7 +75,7 @@ lpexp::Symbol::genAuto(NdfAutomata& automata) const
lpexp::FirstLast
lpexp::Wildexp::genAuto(NdfAutomata& automata) const
{
// Same as the Symbol lpexp but with a wildcard insted of a symbol
// Same as the Symbol lpexp but with a wildcard instead of a symbol
NdfAutomata::State* begin = automata.newState();
NdfAutomata::State* end = automata.newState();
begin->addWildcardTransition(new Wildcard(m_wildcard), end);

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