Compare commits
39
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be53b07590 | ||
|
|
3606edd98b | ||
|
|
2662e3c3a8 | ||
|
|
6a5b9fb1f1 | ||
|
|
4b12f100a3 | ||
|
|
2af62ddb81 | ||
|
|
2cd9387e18 | ||
|
|
7cc17a79cc | ||
|
|
dd4840e817 | ||
|
|
a7b5483989 | ||
|
|
6b89b52a28 | ||
|
|
ceda6e7c1c | ||
|
|
f5bc9b239e | ||
|
|
6a08652861 | ||
|
|
b75ed8e187 | ||
|
|
1b1a740241 | ||
|
|
92e2038866 | ||
|
|
0243926093 | ||
|
|
86dd484084 | ||
|
|
157198aef0 | ||
|
|
bcde312aab | ||
|
|
b6e0b7a52d | ||
|
|
4125540682 | ||
|
|
93f6c83ff3 | ||
|
|
3d5331c726 | ||
|
|
e95a49f39a | ||
|
|
b891e9d892 | ||
|
|
1626525b46 | ||
|
|
4568396f97 | ||
|
|
06d8cda6db | ||
|
|
7efc45ee76 | ||
|
|
28f45940a5 | ||
|
|
1e754f4fb6 | ||
|
|
2d47f217ca | ||
|
|
66982e9df0 | ||
|
|
c786fe0e09 | ||
|
|
84c5e24933 | ||
|
|
1ef5adadd8 | ||
|
|
da18dca6c5 |
@@ -1,6 +1,45 @@
|
||||
Changes:
|
||||
|
||||
Release 1.6 (1.6.5 - beta) -- 20 May 2015 (compared to 1.5)
|
||||
Release 1.6.9 -- 18 Nov 2015 (compared to 1.6.8)
|
||||
------------------------------------------------
|
||||
* Bug fix for code generation of struct parameters copied whole. #564
|
||||
* Fix Windows build issues. #561
|
||||
* Some changes that will allow us to build against OIIO 1.6 trunk (a few
|
||||
declarations have changed there). #581, #582
|
||||
|
||||
Release 1.6.8 -- 16 Jul 2015 (compared to 1.6.7)
|
||||
------------------------------------------------
|
||||
* Support shader parameters that are arrays of closures. (Thanks,
|
||||
Ubisoft!) #544
|
||||
* New shader group ShadingSystem::getattribute() queries:
|
||||
num_attributes_needed, attributes_needed, attribute_scopes, and
|
||||
unknown_attributes_needed. Collectively, these let you find out
|
||||
exactly which getattribute tokens a compiled shader group may request.
|
||||
(Works like the similar queries for userdata tokens.)
|
||||
(Thanks, Image Engine!) #537
|
||||
* Fix bugs when deserializing shader group strings with unsized arrays. #534
|
||||
* Fix bugs when serializing shader groups with unsized arrays. #539
|
||||
* Fix format() constant folding. #536
|
||||
* Fix bug with unconditional running of earlier layers -- could botch
|
||||
certain parameter initialization. #541
|
||||
* Make sure we build correctly against LLVM 3.5.
|
||||
* When building against LLVM 3.5, abort the build and give a clear error
|
||||
message if not also using USE_CPP11=1 (because LLVM3.5 requres C++11). #542
|
||||
* Fixes for clean VS2012 builds. #545
|
||||
* Fix static array initialization problem with VS2012.
|
||||
|
||||
|
||||
Release 1.6.7 -- 11 Jun 2015 (compared to 1.6.6)
|
||||
-----------------------------------------------
|
||||
* CMake option OSL_BUILD_TESTS=0 turns off building of test programs,
|
||||
testshade, testrender. #522
|
||||
* CMake option USE_fPIC=1 turns on -fPIC flag for C++ compilation. #521
|
||||
* CMake option to disallow creation of OIIO::TextureSystem. #523
|
||||
* Alternate place to find stdosl.h. (mostly for Pixar) #524
|
||||
* Site customization file for Pixar. #524
|
||||
|
||||
|
||||
Release 1.6 (1.6.6) -- 26 May 2015 (compared to 1.5)
|
||||
-----------------------------------------------
|
||||
Language, standard libary, and compiler changes (for shader writers):
|
||||
* It is now supported to have shader parameters that are arrays of
|
||||
@@ -215,6 +254,11 @@ Build & test system improvements and developer goodies:
|
||||
#487 #488 (1.6.4)
|
||||
* Fixes to work with LLVM 3.5 and 3.6, though 3.6 especially has not yet
|
||||
been very thoroughly tested for OSL. #487 (1.6.4)
|
||||
* C++11 support: the preprocessor symbol OSL_BUILD_CPP11 is set to 1 if
|
||||
OSL was built with C++11 (or higher) support, and the separate
|
||||
OSL_USING_CPP11 is set to 1 if C++11 is detected right now. (These can
|
||||
be different from the point of view of an app using OSL headers.)
|
||||
#508 (1.6.6RC1)
|
||||
|
||||
Documentation:
|
||||
* Short chapter added to spec describing the syntax of our serialization
|
||||
|
||||
+29
-10
@@ -3,8 +3,8 @@ project (OSL)
|
||||
# Release version of the library
|
||||
set (OSL_LIBRARY_VERSION_MAJOR 1)
|
||||
set (OSL_LIBRARY_VERSION_MINOR 6)
|
||||
set (OSL_LIBRARY_VERSION_PATCH 5)
|
||||
set (OSL_LIBRARY_VERSION_RELEASE_TYPE "beta") # "dev", "betaX", "RCY", ""
|
||||
set (OSL_LIBRARY_VERSION_PATCH 9)
|
||||
set (OSL_LIBRARY_VERSION_RELEASE_TYPE "") # "dev", "betaX", "RCY", ""
|
||||
|
||||
# Version of the OSO file format and instruction set
|
||||
set (OSO_FILE_VERSION_MAJOR 1)
|
||||
@@ -109,6 +109,11 @@ if (BUILDSTATIC)
|
||||
add_definitions ("-DOSL_STATIC_LIBRARY")
|
||||
endif()
|
||||
|
||||
set (USE_fPIC OFF CACHE BOOL "Build with -fPIC")
|
||||
if (USE_fPIC)
|
||||
add_definitions ("-fPIC")
|
||||
endif ()
|
||||
|
||||
if (CMAKE_COMPILER_IS_CLANG OR CMAKE_COMPILER_IS_GNUCC)
|
||||
# CMake doesn't automatically know what do do with
|
||||
# include_directories(SYSTEM...) when using clang or gcc.
|
||||
@@ -150,6 +155,7 @@ if (EXISTS "/usr/lib/libc++.dylib")
|
||||
endif ()
|
||||
|
||||
set (VERBOSE OFF CACHE BOOL "Print lots of messages while compiling")
|
||||
set (OSL_BUILD_TESTS ON CACHE BOOL "Build the unit tests, testshade, testrender")
|
||||
set (BUILDSTATIC OFF CACHE BOOL "Build static library instead of shared")
|
||||
set (HIDE_SYMBOLS OFF CACHE BOOL "Hide symbols not in the public API")
|
||||
set (USE_EXTERNAL_PUGIXML OFF CACHE BOOL
|
||||
@@ -162,10 +168,11 @@ else ()
|
||||
endif ()
|
||||
set (USE_PARTIO ON CACHE BOOL "Use Partio if found")
|
||||
set (USE_FAST_MATH ON CACHE BOOL "Use fast math approximations (if no, then use system math library)")
|
||||
set (USE_CPP11 OFF CACHE BOOL "Compile in C++11 mode")
|
||||
set (USE_LIBCPLUSPLUS OFF CACHE BOOL "Compile with clang libc++")
|
||||
set (OSL_BUILD_CPP11 OFF CACHE BOOL "Compile in C++11 mode")
|
||||
set (OSL_BUILD_LIBCPLUSPLUS OFF CACHE BOOL "Compile with clang libc++")
|
||||
set (EXTRA_CPP_ARGS "" CACHE STRING "Extra C++ command line definitions")
|
||||
set (USE_SIMD "" CACHE STRING "Use SIMD directives (0, sse2, sse3, sse4.1, sse4.2)")
|
||||
set (OSL_NO_DEFAULT_TEXTURESYSTEM OFF CACHE BOOL "Do not use create a raw OIIO::TextureSystem")
|
||||
|
||||
if (LLVM_NAMESPACE)
|
||||
add_definitions ("-DLLVM_NAMESPACE=${LLVM_NAMESPACE}")
|
||||
@@ -181,12 +188,16 @@ else ()
|
||||
add_definitions ("-DOSL_FAST_MATH=0")
|
||||
endif ()
|
||||
|
||||
if (OSL_NO_DEFAULT_TEXTURESYSTEM)
|
||||
add_definitions ("-DOSL_NO_DEFAULT_TEXTURESYSTEM=1")
|
||||
endif ()
|
||||
|
||||
if (EXTRA_CPP_ARGS)
|
||||
message (STATUS "Extra C++ args: ${EXTRA_CPP_ARGS}")
|
||||
add_definitions ("${EXTRA_CPP_ARGS}")
|
||||
endif()
|
||||
|
||||
if (USE_CPP11)
|
||||
if (OSL_BUILD_CPP11)
|
||||
message (STATUS "Building for C++11")
|
||||
add_definitions ("-std=c++11")
|
||||
if (CMAKE_COMPILER_IS_CLANG)
|
||||
@@ -274,8 +285,11 @@ add_subdirectory (src/liboslexec)
|
||||
add_subdirectory (src/oslc)
|
||||
add_subdirectory (src/shaders)
|
||||
add_subdirectory (src/oslinfo)
|
||||
|
||||
if (OSL_BUILD_TESTS)
|
||||
add_subdirectory (src/testshade)
|
||||
add_subdirectory (src/testrender)
|
||||
endif ()
|
||||
|
||||
add_subdirectory (src/include)
|
||||
add_subdirectory (src/doc)
|
||||
@@ -331,13 +345,14 @@ macro ( TESTSUITE )
|
||||
endforeach ()
|
||||
endmacro ()
|
||||
|
||||
if (OSL_BUILD_TESTS)
|
||||
# List all the individual testsuite tests here, except those that need
|
||||
# special installed tests.
|
||||
TESTSUITE ( and-or-not-synonyms aastep arithmetic array array-derivs array-range
|
||||
blackbody blendmath breakcont
|
||||
bug-array-heapoffsets
|
||||
bug-locallifetime bug-outputinit bug-param-duplicate bug-peep
|
||||
cellnoise closure color comparison
|
||||
cellnoise closure closure-array color comparison
|
||||
compile-buffer
|
||||
component-range const-array-params const-array-fill
|
||||
debugnan debug-uninit
|
||||
@@ -346,7 +361,8 @@ TESTSUITE ( and-or-not-synonyms aastep arithmetic array array-derivs array-range
|
||||
geomath getattribute-camera getsymbol-nonheap gettextureinfo
|
||||
group-outputs groupstring
|
||||
hyperb ieee_fp if incdec initops intbits isconnected
|
||||
layers layers-Ciassign layers-lazy layers-repeatedoutputs
|
||||
layers layers-Ciassign layers-lazy
|
||||
layers-nonlazycopy layers-repeatedoutputs
|
||||
logic loop matrix message mergeinstances-nouserdata
|
||||
metadata-braces miscmath missing-shader
|
||||
noise noise-cell
|
||||
@@ -368,8 +384,9 @@ TESTSUITE ( and-or-not-synonyms aastep arithmetic array array-derivs array-range
|
||||
render-microfacet render-oren-nayar render-veachmis render-ward
|
||||
shortcircuit spline splineinverse string
|
||||
struct struct-array struct-array-mixture
|
||||
struct-err struct-in-struct-init struct-layers struct-with-array
|
||||
struct-within-struct ternary
|
||||
struct-err struct-in-struct-init struct-init-copy struct-layers
|
||||
struct-with-array struct-within-struct
|
||||
ternary
|
||||
texture-alpha texture-blur texture-derivs texture-field3d
|
||||
texture-firstchannel texture-interp
|
||||
texture-missingcolor texture-simple
|
||||
@@ -377,9 +394,11 @@ TESTSUITE ( and-or-not-synonyms aastep arithmetic array array-derivs array-range
|
||||
texture-width texture-withderivs texture-wrap
|
||||
trailing-commas transform transformc trig typecast
|
||||
unknown-instruction
|
||||
vararray-connect vararray-default vararray-param
|
||||
vararray-connect vararray-default
|
||||
vararray-deserialize vararray-param
|
||||
vecctr vector
|
||||
wavelength_color xml )
|
||||
endif ()
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -37,6 +37,9 @@ $(info OSL_SITE = ${OSL_SITE})
|
||||
ifneq (${shell echo ${OSL_SITE} | grep imageworks},)
|
||||
include ${working_dir}/site/spi/Makefile-bits
|
||||
endif
|
||||
ifneq (${shell echo ${OSL_SITE} | grep pixar},)
|
||||
include ${working_dir}/site/pixar/Makefile-bits
|
||||
endif
|
||||
|
||||
# Set up variables holding the names of platform-dependent directories --
|
||||
# set these after evaluating site-specific instructions
|
||||
@@ -116,6 +119,10 @@ ifneq (${LINKSTATIC},)
|
||||
MY_CMAKE_FLAGS += -DLINKSTATIC:BOOL=${LINKSTATIC}
|
||||
endif
|
||||
|
||||
ifneq (${OSL_BUILD_TESTS},)
|
||||
MY_CMAKE_FLAGS += -DOSL_BUILD_TESTS:BOOL=${OSL_BUILD_TESTS}
|
||||
endif
|
||||
|
||||
ifneq (${USE_EXTERNAL_PUGIXML},)
|
||||
MY_CMAKE_FLAGS += -DUSE_EXTERNAL_PUGIXML:BOOL=${USE_EXTERNAL_PUGIXML} -DPUGIXML_HOME=${PUGIXML_HOME}
|
||||
endif
|
||||
@@ -136,11 +143,11 @@ MY_CMAKE_FLAGS += -DCMAKE_CXX_COMPILER:STRING="${MYCXX}"
|
||||
endif
|
||||
|
||||
ifneq (${USE_CPP11},)
|
||||
MY_CMAKE_FLAGS += -DUSE_CPP11:BOOL=${USE_CPP11}
|
||||
MY_CMAKE_FLAGS += -DOSL_BUILD_CPP11:BOOL=${USE_CPP11}
|
||||
endif
|
||||
|
||||
ifneq (${USE_LIBCPLUSPLUS},)
|
||||
MY_CMAKE_FLAGS += -DUSE_LIBCPLUSPLUS:BOOL=${USE_LIBCPLUSPLUS}
|
||||
MY_CMAKE_FLAGS += -DOSL_BUILD_LIBCPLUSPLUS:BOOL=${USE_LIBCPLUSPLUS}
|
||||
endif
|
||||
|
||||
ifneq (${EXTRA_CPP_ARGS},)
|
||||
@@ -286,6 +293,7 @@ help:
|
||||
@echo " OSL build-time options:"
|
||||
@echo " NAMESPACE=name Wrap OSL APIs in another namespace"
|
||||
@echo " USE_FAST_MATH=1 Use faster, but less accurate math (set to 0 for libm defaults)"
|
||||
@echo " OSL_BUILD_TESTS=0 Skip building the unit tests, testshade, testrender"
|
||||
@echo " USE_SIMD=arch Build with SIMD support (choices: 0, sse2, sse3,"
|
||||
@echo " sse4.1, sse4.2)"
|
||||
@echo ""
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# Pixar-specific settings
|
||||
|
||||
ifneq (${VERBOSE},)
|
||||
$(info Including pixar/Makefile-bits)
|
||||
endif
|
||||
|
||||
MY_CMAKE_FLAGS += -DUSE_fPIC:BOOL=1
|
||||
MY_CMAKE_FLAGS += -DENABLERTTI:BOOL=1
|
||||
MY_CMAKE_FLAGS += -DSTOP_ON_WARNING:BOOL=0
|
||||
MY_CMAKE_FLAGS += -DHIDE_SYMBOLS:BOOL=1
|
||||
MY_CMAKE_FLAGS += -DBUILDSTATIC:BOOL=1
|
||||
MY_CMAKE_FLAGS += -DLINKSTATIC:BOOL=1
|
||||
MY_CMAKE_FLAGS += -DUSE_FAST_MATH:BOOL=1
|
||||
MY_CMAKE_FLAGS += -DILMBASE_LIB_AREA:STRING=${ILMBASE_HOME}/lib/linux-ix86-64/gcc4.1
|
||||
MY_CMAKE_FLAGS += -DILMBASE_CUSTOM:BOOL=True
|
||||
MY_CMAKE_FLAGS += -DILMBASE_CUSTOM_LIBRARIES:STRING="Half-fPIC Iex-fPIC IexMath-fPIC IlmThread-fPIC Imath-fPIC"
|
||||
|
||||
# Don't build testshade or testrender (mostly because they require the
|
||||
# image-handling parts of OIIO, which Pixar doesn't build)
|
||||
MY_CMAKE_FLAGS += -DOSL_BUILD_TESTS:BOOL=0
|
||||
|
||||
# Don't let OSL create a default OIIO::TextureSystem. If the renderer
|
||||
# doesn't pass in whatever proxy it wants, it will assert.
|
||||
MY_CMAKE_FLAGS += -DOSL_NO_DEFAULT_TEXTURESYSTEM:BOOL=1
|
||||
|
||||
ifneq (${VERBOSE},)
|
||||
$(info MY_CMAKE_FLAGS: $(MY_CMAKE_FLAGS))
|
||||
endif
|
||||
@@ -172,6 +172,10 @@ if(NOT LLVM_DIRECTORY OR EXISTS ${LLVM_CONFIG})
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
endif()
|
||||
|
||||
if (LLVM_VERSION VERSION_GREATER 3.4.9 AND NOT OSL_BUILD_CPP11)
|
||||
message (FATAL_ERROR "LLVM ${LLVM_VERSION} requires C++11. You must build with USE_CPP11=1.")
|
||||
endif ()
|
||||
|
||||
find_library ( LLVM_LIBRARY
|
||||
NAMES LLVM-${LLVM_VERSION}
|
||||
PATHS ${LLVM_LIB_DIR})
|
||||
@@ -213,7 +217,6 @@ if ((LLVM_LIBRARY OR LLVM_STATIC) AND LLVM_INCLUDES AND LLVM_DIRECTORY AND LLVM_
|
||||
message (STATUS "LLVM library = ${LLVM_LIBRARY}")
|
||||
endif ()
|
||||
|
||||
|
||||
if (NOT LLVM_LIBRARY)
|
||||
message (FATAL_ERROR "LLVM library not found.")
|
||||
endif()
|
||||
|
||||
Binary file not shown.
@@ -46,28 +46,28 @@ struct ClosureParam {
|
||||
#define fieldsize(st, fld) sizeof(((st *)0)->fld)
|
||||
|
||||
#define CLOSURE_INT_PARAM(st, fld) \
|
||||
{ TypeDesc::TypeInt, reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
{ TypeDesc::TypeInt, (int)reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
#define CLOSURE_FLOAT_PARAM(st, fld) \
|
||||
{ TypeDesc::TypeFloat, reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
{ TypeDesc::TypeFloat, (int)reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
#define CLOSURE_COLOR_PARAM(st, fld) \
|
||||
{ TypeDesc::TypeColor, reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
{ TypeDesc::TypeColor, (int)reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
#define CLOSURE_VECTOR_PARAM(st, fld) \
|
||||
{ TypeDesc::TypeVector, reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
{ TypeDesc::TypeVector, (int)reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
#define CLOSURE_STRING_PARAM(st, fld) \
|
||||
{ TypeDesc::TypeString, reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
{ TypeDesc::TypeString, (int)reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
#define CLOSURE_CLOSURE_PARAM(st, fld) \
|
||||
{ TypeDesc::PTR, reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
{ TypeDesc::PTR, (int)reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
|
||||
#define CLOSURE_INT_ARRAY_PARAM(st, fld, n) \
|
||||
{ TypeDesc(TypeDesc::INT, TypeDesc::SCALAR, TypeDesc::NOXFORM, n),reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
{ TypeDesc(TypeDesc::INT, TypeDesc::SCALAR, TypeDesc::NOXFORM, n),(int)reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
#define CLOSURE_VECTOR_ARRAY_PARAM(st,fld,n) \
|
||||
{ TypeDesc(TypeDesc::FLOAT, TypeDesc::VEC3, TypeDesc::VECTOR, n),reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
{ TypeDesc(TypeDesc::FLOAT, TypeDesc::VEC3, TypeDesc::VECTOR, n),(int)reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
#define CLOSURE_COLOR_ARRAY_PARAM(st,fld,n) \
|
||||
{ TypeDesc(TypeDesc::FLOAT, TypeDesc::VEC3, TypeDesc::COLOR, n),reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
{ TypeDesc(TypeDesc::FLOAT, TypeDesc::VEC3, TypeDesc::COLOR, n),(int)reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
#define CLOSURE_FLOAT_ARRAY_PARAM(st,fld,n) \
|
||||
{ TypeDesc(TypeDesc::FLOAT, TypeDesc::SCALAR, TypeDesc::NOXFORM, n),reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
{ TypeDesc(TypeDesc::FLOAT, TypeDesc::SCALAR, TypeDesc::NOXFORM, n),(int)reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
#define CLOSURE_STRING_ARRAY_PARAM(st,fld,n) \
|
||||
{ TypeDesc(TypeDesc::STRING, TypeDesc::SCALAR, TypeDesc::NOXFORM, n),reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
{ TypeDesc(TypeDesc::STRING, TypeDesc::SCALAR, TypeDesc::NOXFORM, n),(int)reckless_offsetof(st, fld), NULL, fieldsize(st, fld) }
|
||||
|
||||
// NOTE: this keyword args have to be always at the end of the list
|
||||
#define CLOSURE_INT_KEYPARAM(key) \
|
||||
|
||||
@@ -35,9 +35,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
/// renderer that wanted things a different way.
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Test if we are using C++11
|
||||
// Detect if we're C++11.
|
||||
//
|
||||
// Note: oslversion.h defined OSL_BUILD_CPP11 to be 1 if OSL was built
|
||||
// using C++11. In contrast, OSL_USING_CPP11 defined below will be 1 if
|
||||
// we're compiling C++11 RIGHT NOW. These two things may be the same when
|
||||
// compiling OSL, but they may not be the same if another packages is
|
||||
// compiling against OSL and using these headers (OSL may be C++11 but the
|
||||
// client package may be older, or vice versa -- use these two symbols to
|
||||
// differentiate these cases, when important).
|
||||
#if (__cplusplus >= 201103L)
|
||||
#define OSL_USING_CPLUSPLUS11 1
|
||||
#define OSL_USING_CPP11 1
|
||||
#define OSL_USING_CPLUSPLUS11 1 /* DEPRECATED */
|
||||
#endif
|
||||
|
||||
// Symbol export defines
|
||||
@@ -56,7 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <OpenImageIO/ustring.h>
|
||||
|
||||
// Sort out smart pointers
|
||||
#ifdef OSL_USING_CPLUSPLUS11
|
||||
#ifdef OSL_USING_CPP11
|
||||
# include <memory>
|
||||
#else
|
||||
# include <boost/shared_ptr.hpp>
|
||||
@@ -109,7 +118,7 @@ using OIIO::ustringHash;
|
||||
using OIIO::string_view;
|
||||
|
||||
// Sort out smart pointers
|
||||
#ifdef OSL_USING_CPLUSPLUS11
|
||||
#ifdef OSL_USING_CPP11
|
||||
using std::shared_ptr;
|
||||
using std::weak_ptr;
|
||||
#else
|
||||
|
||||
@@ -263,6 +263,22 @@ public:
|
||||
/// ptr userdata_offsets Retrieves a pointer to the array of
|
||||
/// int describing the userdata offsets
|
||||
/// within the heap.
|
||||
/// int num_attributes_needed The number of attribute/scope pairs that
|
||||
/// are known to be queried by the group (the
|
||||
/// length of the attributes_needed and
|
||||
/// attribute_scopes arrays).
|
||||
/// 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
|
||||
/// appear in the array multiple times - once for
|
||||
/// each scope in which is is queried.
|
||||
/// ptr attribute_scopes Retrieves a pointer to a ustring array containing
|
||||
/// the scopes associated with each attribute query
|
||||
/// in the attributes_needed array.
|
||||
/// int unknown_attributes_needed Nonzero if additonal attributes may be
|
||||
/// needed, whose names will not be known
|
||||
/// until the shader actually runs.
|
||||
/// string pickle Retrieves a serialized representation
|
||||
/// of the shader group declaration.
|
||||
/// Note: the attributes referred to as "string" are actually on the app
|
||||
|
||||
@@ -87,5 +87,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define OSL_NAMESPACE_EXIT };
|
||||
#endif
|
||||
|
||||
/// OSL_BUILD_CPP11 will be 1 if this OSL was built using C++11
|
||||
#cmakedefine01 OSL_BUILD_CPP11
|
||||
/// OSL_BUILD_USELIBPLUSPLUS will be 1 if this OSL was built using libc++
|
||||
#cmakedefine01 OSL_BUILD_LIBCPLUSPLUS
|
||||
|
||||
#endif /* OSLVERSION_H */
|
||||
|
||||
@@ -30,12 +30,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "osl_pvt.h"
|
||||
#include "oslcomp_pvt.h"
|
||||
|
||||
#include <OpenImageIO/dassert.h>
|
||||
#include <OpenImageIO/filesystem.h>
|
||||
#include <OpenImageIO/strutil.h>
|
||||
namespace Strutil = OIIO::Strutil;
|
||||
|
||||
@@ -317,9 +316,9 @@ ASTvariable_declaration::ASTvariable_declaration (OSLCompilerImpl *comp,
|
||||
if (f && ! m_ismetadata) {
|
||||
std::string e = Strutil::format ("\"%s\" already declared in this scope", name.c_str());
|
||||
if (f->node()) {
|
||||
boost::filesystem::path p(f->node()->sourcefile().string());
|
||||
std::string filename = OIIO::Filesystem::filename(f->node()->sourcefile().string());
|
||||
e += Strutil::format ("\n\t\tprevious declaration was at %s:%d",
|
||||
p.filename().c_str(), f->node()->sourceline());
|
||||
filename, f->node()->sourceline());
|
||||
}
|
||||
if (f->scope() == 0 && f->symtype() == SymTypeFunction && isparam) {
|
||||
// special case: only a warning for param to mask global function
|
||||
|
||||
@@ -311,11 +311,14 @@ protected:
|
||||
/// true, we are (perhaps recursively) copying entire arrays, of
|
||||
/// or within the struct, and intindex is the element number if we
|
||||
/// know it -- these two items let us take some interesting shortcuts
|
||||
/// with whole arrays (copyarray versus assigning elements).
|
||||
/// with whole arrays (copyarray versus assigning elements). Pass
|
||||
/// paraminit=true if we're doing the assignment as init ops of a
|
||||
/// shader param.
|
||||
void codegen_assign_struct (StructSpec *structspec,
|
||||
ustring dstsym, ustring srcsym,
|
||||
Symbol *arrayindex,
|
||||
bool copywholearrays, int intindex);
|
||||
bool copywholearrays, int intindex,
|
||||
bool paraminit);
|
||||
|
||||
protected:
|
||||
NodeType m_nodetype; ///< Type of node this is
|
||||
|
||||
+24
-11
@@ -488,7 +488,7 @@ ASTassign_expression::codegen (Symbol *dest)
|
||||
StructSpec *structspec = typespec().structspec ();
|
||||
codegen_assign_struct (structspec, ustring(dest->mangled()),
|
||||
ustring(operand->mangled()), NULL,
|
||||
true, 0);
|
||||
true, 0, false /*not a shader param init*/);
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
@@ -505,13 +505,15 @@ ASTassign_expression::codegen (Symbol *dest)
|
||||
Symbol *v = index->lvalue()->codegen();
|
||||
codegen_assign_struct (structspec, ustring(v->mangled()),
|
||||
ustring(operand->mangled()), arrayindex,
|
||||
false, -1 /* means we don't know */);
|
||||
false, -1 /* means we don't know */,
|
||||
false /*not a shader param init*/);
|
||||
} else {
|
||||
// Assignment of one scalar struct to another scalar struct
|
||||
ASSERT (dest);
|
||||
codegen_assign_struct (structspec, ustring(dest->mangled()),
|
||||
ustring(operand->mangled()), NULL,
|
||||
true, 0);
|
||||
true, 0,
|
||||
false /*not a shader param init*/);
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
@@ -537,7 +539,8 @@ void
|
||||
ASTNode::codegen_assign_struct (StructSpec *structspec,
|
||||
ustring dstsym, ustring srcsym,
|
||||
Symbol *arrayindex,
|
||||
bool copywholearrays, int intindex)
|
||||
bool copywholearrays, int intindex,
|
||||
bool paraminit)
|
||||
{
|
||||
for (int i = 0; i < (int)structspec->numfields(); ++i) {
|
||||
const TypeSpec &fieldtype (structspec->field(i).type);
|
||||
@@ -547,7 +550,7 @@ ASTNode::codegen_assign_struct (StructSpec *structspec,
|
||||
codegen_assign_struct (fieldtype.structspec(),
|
||||
ustring::format ("%s.%s", dstsym, fieldname),
|
||||
ustring::format ("%s.%s", srcsym, fieldname),
|
||||
arrayindex, copywholearrays, 0);
|
||||
arrayindex, copywholearrays, 0, paraminit);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -561,7 +564,7 @@ ASTNode::codegen_assign_struct (StructSpec *structspec,
|
||||
codegen_assign_struct (fieldtype.structspec(),
|
||||
dstfield, srcfield,
|
||||
m_compiler->make_constant(i),
|
||||
copywholearrays, i);
|
||||
copywholearrays, i, paraminit);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -569,6 +572,10 @@ ASTNode::codegen_assign_struct (StructSpec *structspec,
|
||||
Symbol *dfield, *ofield;
|
||||
m_compiler->struct_field_pair (structspec, i, dstsym, srcsym,
|
||||
dfield, ofield);
|
||||
if (paraminit) {
|
||||
m_compiler->codegen_method (ustring(dfield->mangled()));
|
||||
dfield->initbegin (m_compiler->next_op_label ());
|
||||
}
|
||||
if (arrayindex) {
|
||||
// field is a scalar, but we're assigning to one element of
|
||||
// an array of structs.
|
||||
@@ -598,6 +605,8 @@ ASTNode::codegen_assign_struct (StructSpec *structspec,
|
||||
// field is a scalar, struct is a scalar
|
||||
emitcode ("assign", dfield, ofield);
|
||||
}
|
||||
if (paraminit)
|
||||
dfield->initend (m_compiler->next_op_label ());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -886,6 +895,13 @@ ASTvariable_declaration::codegen_initlist (ref init, TypeSpec type,
|
||||
Symbol *
|
||||
ASTvariable_declaration::codegen_struct_initializers (ref init)
|
||||
{
|
||||
// If we're doing this initialization for shader params for their
|
||||
// init ops, we need to take care to set the codegen method names
|
||||
// properly.
|
||||
bool paraminit = (m_compiler->codegen_method() != m_compiler->main_method_name() &&
|
||||
(m_sym->symtype() == SymTypeParam ||
|
||||
m_sym->symtype() == SymTypeOutputParam));
|
||||
|
||||
if (! init->next() && init->typespec() == m_typespec &&
|
||||
init->nodetype() != compound_initializer_node) {
|
||||
// Special case: just one initializer, it's a whole struct of
|
||||
@@ -894,16 +910,13 @@ ASTvariable_declaration::codegen_struct_initializers (ref init)
|
||||
if (initsym != m_sym) {
|
||||
StructSpec *structspec (m_typespec.structspec());
|
||||
codegen_assign_struct (structspec, ustring(m_sym->mangled()),
|
||||
ustring(initsym->mangled()), NULL, true, 0);
|
||||
ustring(initsym->mangled()), NULL, true, 0,
|
||||
paraminit);
|
||||
}
|
||||
return m_sym;
|
||||
}
|
||||
|
||||
// General case -- per-field initializers
|
||||
|
||||
bool paraminit = (m_compiler->codegen_method() != m_compiler->main_method_name() &&
|
||||
(m_sym->symtype() == SymTypeParam ||
|
||||
m_sym->symtype() == SymTypeOutputParam));
|
||||
for (int i = 0; init; init = init->next(), ++i) {
|
||||
// Structure element -- assign to the i-th member field
|
||||
StructSpec *structspec (m_typespec.structspec());
|
||||
|
||||
@@ -625,7 +625,7 @@ OSLCompilerImpl::write_oso_const_value (const ConstantSymbol *sym) const
|
||||
int nelements = std::max (1, type.arraylen);
|
||||
if (elemtype == TypeDesc::STRING)
|
||||
for (int i = 0; i < nelements; ++i)
|
||||
oso ("\"%s\"%s", sym->strval(i).c_str(), nelements>1 ? " " : "");
|
||||
oso ("\"%s\"%s", sym->strval(i), nelements>1 ? " " : "");
|
||||
else if (elemtype == TypeDesc::INT)
|
||||
for (int i = 0; i < nelements; ++i)
|
||||
oso ("%d%s", sym->intval(i), nelements>1 ? " " : "");
|
||||
|
||||
@@ -221,26 +221,28 @@ BackendLLVM::llvm_zero_derivs (const Symbol &sym, llvm::Value *count)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
BackendLLVM::ShaderGlobalNameToIndex (ustring name)
|
||||
namespace
|
||||
{
|
||||
// N.B. The order of names in this table MUST exactly match the
|
||||
// ShaderGlobals struct in oslexec.h, as well as the llvm 'sg' type
|
||||
// defined in llvm_type_sg().
|
||||
static ustring fields[] = {
|
||||
Strings::P, ustring("_dPdz"), Strings::I, Strings::N, Strings::Ng,
|
||||
Strings::u, Strings::v, Strings::dPdu, Strings::dPdv,
|
||||
Strings::time, Strings::dtime, Strings::dPdtime, Strings::Ps,
|
||||
ustring("P"), ustring("_dPdz"), ustring("I"),
|
||||
ustring("N"), ustring("Ng"),
|
||||
ustring("u"), ustring("v"), ustring("dPdu"), ustring("dPdv"),
|
||||
ustring("time"), ustring("dtime"), ustring("dPdtime"), ustring("Ps"),
|
||||
ustring("renderstate"), ustring("tracedata"), ustring("objdata"),
|
||||
ustring("shadingcontext"), ustring("renderer"),
|
||||
ustring("object2common"), ustring("shader2common"),
|
||||
Strings::Ci,
|
||||
ustring("Ci"),
|
||||
ustring("surfacearea"), ustring("raytype"),
|
||||
ustring("flipHandedness"), ustring("backfacing")
|
||||
};
|
||||
}
|
||||
|
||||
int
|
||||
BackendLLVM::ShaderGlobalNameToIndex (ustring name)
|
||||
{
|
||||
for (int i = 0; i < int(sizeof(fields)/sizeof(fields[0])); ++i)
|
||||
if (name == fields[i])
|
||||
return i;
|
||||
@@ -778,8 +780,8 @@ BackendLLVM::llvm_assign_impl (Symbol &Result, Symbol &Src,
|
||||
|
||||
llvm::Value *arrind = arrayindex >= 0 ? ll.constant (arrayindex) : NULL;
|
||||
|
||||
if (Result.typespec().is_closure_based() || Src.typespec().is_closure_based()) {
|
||||
if (Src.typespec().is_closure_based()) {
|
||||
if (Result.typespec().is_closure() || Src.typespec().is_closure()) {
|
||||
if (Src.typespec().is_closure()) {
|
||||
llvm::Value *srcval = llvm_load_value (Src, 0, arrind, 0);
|
||||
llvm_store_value (srcval, Result, 0, arrind, 0);
|
||||
} else {
|
||||
|
||||
@@ -1143,7 +1143,9 @@ DECLFOLDER(constfold_split)
|
||||
std::vector<int> args;
|
||||
args.push_back (resultsarg);
|
||||
args.push_back (cind);
|
||||
rop.insert_code (opnum, u_assign, args, true, 1 /* relation */);
|
||||
rop.insert_code (opnum, u_assign, args,
|
||||
RuntimeOptimizer::RecomputeRWRanges,
|
||||
RuntimeOptimizer::GroupWithNext);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1263,7 +1265,8 @@ DECLFOLDER(constfold_format)
|
||||
newargs[1] = rop.add_constant (ustring(prefix + suffix));
|
||||
ustring opname = op.opname();
|
||||
rop.turn_into_nop (op, "partial constant fold format()");
|
||||
rop.insert_code (opnum, opname, newargs);
|
||||
rop.insert_code (opnum, opname, newargs,
|
||||
RuntimeOptimizer::RecomputeRWRanges);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1457,13 +1460,15 @@ DECLFOLDER(constfold_mix)
|
||||
// just R=A and not have to access B
|
||||
int cond = rop.add_temp (TypeDesc::TypeInt);
|
||||
int fzero = rop.add_constant (0.0f);
|
||||
rop.insert_code (opnum++, u_eq, 1 /*relation*/, cond, Xind, fzero);
|
||||
rop.insert_code (opnum++, u_eq, RuntimeOptimizer::GroupWithNext,
|
||||
cond, Xind, fzero);
|
||||
if0op = opnum;
|
||||
rop.insert_code (opnum++, u_if, 1 /*relation*/, cond);
|
||||
rop.insert_code (opnum++, u_if, RuntimeOptimizer::GroupWithNext, cond);
|
||||
rop.op(if0op).argreadonly (0);
|
||||
rop.symbol(cond)->mark_rw (if0op, true, false);
|
||||
// Add the true (R=A) clause
|
||||
rop.insert_code (opnum++, u_assign, 1 /*relation*/, Rind, Aind);
|
||||
rop.insert_code (opnum++, u_assign,
|
||||
RuntimeOptimizer::GroupWithNext, Rind, Aind);
|
||||
}
|
||||
int if0op_false = opnum; // Where we jump if the 'if x==0' is false
|
||||
if (A.connected()) {
|
||||
@@ -1471,13 +1476,15 @@ DECLFOLDER(constfold_mix)
|
||||
// just R=B and not have to access A
|
||||
int cond = rop.add_temp (TypeDesc::TypeInt);
|
||||
int fone = rop.add_constant (1.0f);
|
||||
rop.insert_code (opnum++, u_eq, 1 /*relation*/, cond, Xind, fone);
|
||||
rop.insert_code (opnum++, u_eq, RuntimeOptimizer::GroupWithNext,
|
||||
cond, Xind, fone);
|
||||
if1op = opnum;
|
||||
rop.insert_code (opnum++, u_if, 1 /*relation*/, cond);
|
||||
rop.insert_code (opnum++, u_if, RuntimeOptimizer::GroupWithNext, cond);
|
||||
rop.op(if1op).argreadonly (0);
|
||||
rop.symbol(cond)->mark_rw (if1op, true, false);
|
||||
// Add the true (R=B) clause
|
||||
rop.insert_code (opnum++, u_assign, 1 /*relation*/, Rind, Bind);
|
||||
rop.insert_code (opnum++, u_assign, RuntimeOptimizer::GroupWithNext,
|
||||
Rind, Bind);
|
||||
}
|
||||
int if1op_false = opnum; // Where we jump if the 'if x==1' is false
|
||||
// Add the (R=A*(1-X)+B*X) clause -- always need that
|
||||
@@ -1485,10 +1492,14 @@ DECLFOLDER(constfold_mix)
|
||||
int temp1 = rop.add_temp (A.typespec());
|
||||
int temp2 = rop.add_temp (B.typespec());
|
||||
int fone = rop.add_constant (1.0f);
|
||||
rop.insert_code (opnum++, u_sub, 1 /*relation*/, one_minus_x, fone, Xind);
|
||||
rop.insert_code (opnum++, u_mul, 1 /*relation*/, temp1, Aind, one_minus_x);
|
||||
rop.insert_code (opnum++, u_mul, 1 /*relation*/, temp2, Bind, Xind);
|
||||
rop.insert_code (opnum++, u_add, 1 /*relation*/, Rind, temp1, temp2);
|
||||
rop.insert_code (opnum++, u_sub, RuntimeOptimizer::GroupWithNext,
|
||||
one_minus_x, fone, Xind);
|
||||
rop.insert_code (opnum++, u_mul, RuntimeOptimizer::GroupWithNext,
|
||||
temp1, Aind, one_minus_x);
|
||||
rop.insert_code (opnum++, u_mul, RuntimeOptimizer::GroupWithNext,
|
||||
temp2, Bind, Xind);
|
||||
rop.insert_code (opnum++, u_add, RuntimeOptimizer::GroupWithNext,
|
||||
Rind, temp1, temp2);
|
||||
// Now go back and patch the 'if' ops with the right jump addresses
|
||||
if (if0op >= 0)
|
||||
rop.op(if0op).set_jump (if0op_false, opnum);
|
||||
@@ -1722,7 +1733,9 @@ DECLFOLDER(constfold_sincos)
|
||||
std::vector<int> args_to_add;
|
||||
args_to_add.push_back (cosarg);
|
||||
args_to_add.push_back (rop.add_constant (c));
|
||||
rop.insert_code (opnum, u_assign, args_to_add, true, 1 /* relation */);
|
||||
rop.insert_code (opnum, u_assign, args_to_add,
|
||||
RuntimeOptimizer::RecomputeRWRanges,
|
||||
RuntimeOptimizer::GroupWithNext);
|
||||
Opcode &newop (rop.inst()->ops()[opnum]);
|
||||
newop.argwriteonly (0);
|
||||
newop.argreadonly (1);
|
||||
@@ -1909,7 +1922,9 @@ DECLFOLDER(constfold_getmatrix)
|
||||
std::vector<int> args_to_add;
|
||||
args_to_add.push_back (resultarg);
|
||||
args_to_add.push_back (rop.add_constant (TypeDesc::TypeInt, &one));
|
||||
rop.insert_code (opnum, u_assign, args_to_add, true, 1 /* relation */);
|
||||
rop.insert_code (opnum, u_assign, args_to_add,
|
||||
RuntimeOptimizer::RecomputeRWRanges,
|
||||
RuntimeOptimizer::GroupWithNext);
|
||||
Opcode &newop (rop.inst()->ops()[opnum]);
|
||||
newop.argwriteonly (0);
|
||||
newop.argread (1, true);
|
||||
@@ -2076,7 +2091,9 @@ DECLFOLDER(constfold_getattribute)
|
||||
std::vector<int> args_to_add;
|
||||
args_to_add.push_back (oldresultarg);
|
||||
args_to_add.push_back (rop.add_constant (TypeDesc::TypeInt, &one));
|
||||
rop.insert_code (opnum, u_assign, args_to_add, true, 1 /* relation */);
|
||||
rop.insert_code (opnum, u_assign, args_to_add,
|
||||
RuntimeOptimizer::RecomputeRWRanges,
|
||||
RuntimeOptimizer::GroupWithNext);
|
||||
Opcode &newop (rop.inst()->ops()[opnum]);
|
||||
newop.argwriteonly (0);
|
||||
newop.argread (1, true);
|
||||
@@ -2131,7 +2148,9 @@ DECLFOLDER(constfold_gettextureinfo)
|
||||
std::vector<int> args_to_add;
|
||||
args_to_add.push_back (oldresultarg);
|
||||
args_to_add.push_back (rop.add_constant (TypeDesc::TypeInt, &one));
|
||||
rop.insert_code (opnum, u_assign, args_to_add, true, 1 /* relation */);
|
||||
rop.insert_code (opnum, u_assign, args_to_add,
|
||||
RuntimeOptimizer::RecomputeRWRanges,
|
||||
RuntimeOptimizer::GroupWithNext);
|
||||
Opcode &newop (rop.inst()->ops()[opnum]);
|
||||
newop.argwriteonly (0);
|
||||
newop.argread (1, true);
|
||||
@@ -2404,7 +2423,9 @@ DECLFOLDER(constfold_pointcloud_search)
|
||||
std::vector<int> args_to_add;
|
||||
args_to_add.push_back (value_args[i]);
|
||||
args_to_add.push_back (const_array_sym);
|
||||
rop.insert_code (opnum, u_assign, args_to_add, true, 1 /* relation */);
|
||||
rop.insert_code (opnum, u_assign, args_to_add,
|
||||
RuntimeOptimizer::RecomputeRWRanges,
|
||||
RuntimeOptimizer::GroupWithNext);
|
||||
}
|
||||
|
||||
// Query results all copied. The only thing left to do is to assign
|
||||
@@ -2412,7 +2433,9 @@ DECLFOLDER(constfold_pointcloud_search)
|
||||
std::vector<int> args_to_add;
|
||||
args_to_add.push_back (result_sym);
|
||||
args_to_add.push_back (rop.add_constant (TypeDesc::TypeInt, &count));
|
||||
rop.insert_code (opnum, u_assign, args_to_add, true, 1 /* relation */);
|
||||
rop.insert_code (opnum, u_assign, args_to_add,
|
||||
RuntimeOptimizer::RecomputeRWRanges,
|
||||
RuntimeOptimizer::GroupWithNext);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -2468,7 +2491,9 @@ DECLFOLDER(constfold_pointcloud_get)
|
||||
std::vector<int> args_to_add;
|
||||
args_to_add.push_back (rop.oparg(op,5) /* Data symbol*/);
|
||||
args_to_add.push_back (const_array_sym);
|
||||
rop.insert_code (opnum, u_assign, args_to_add, true, 1 /* relation */);
|
||||
rop.insert_code (opnum, u_assign, args_to_add,
|
||||
RuntimeOptimizer::RecomputeRWRanges,
|
||||
RuntimeOptimizer::GroupWithNext);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -312,10 +312,10 @@ ShaderInstance::parameters (const ParamValueList ¶ms)
|
||||
{
|
||||
// Adjust the stats
|
||||
ShadingSystemImpl &ss (shadingsys());
|
||||
spin_lock lock (ss.m_stat_mutex);
|
||||
size_t symmem = vectorbytes(m_instoverrides);
|
||||
size_t parammem = (vectorbytes(m_iparams) + vectorbytes(m_fparams) +
|
||||
vectorbytes(m_sparams));
|
||||
spin_lock lock (ss.m_stat_mutex);
|
||||
ss.m_stat_mem_inst_syms += symmem;
|
||||
ss.m_stat_mem_inst_paramvals += parammem;
|
||||
ss.m_stat_mem_inst += (symmem+parammem);
|
||||
@@ -482,7 +482,7 @@ ShaderInstance::copy_code_from_master (ShaderGroup &group)
|
||||
|
||||
|
||||
std::string
|
||||
ShaderInstance::print ()
|
||||
ShaderInstance::print (const ShaderGroup &group)
|
||||
{
|
||||
std::stringstream out;
|
||||
out << "Shader " << shadername() << "\n";
|
||||
@@ -540,6 +540,24 @@ ShaderInstance::print ()
|
||||
out << " (" << filename << ":" << op.sourceline() << ")";
|
||||
out << "\n";
|
||||
}
|
||||
if (nconnections()) {
|
||||
out << " connections upstream:\n";
|
||||
for (int i = 0, e = nconnections(); i < e; ++i) {
|
||||
const Connection &c (connection(i));
|
||||
out << " " << c.dst.type.c_str() << ' '
|
||||
<< symbol(c.dst.param)->name();
|
||||
if (c.dst.arrayindex >= 0)
|
||||
out << '[' << c.dst.arrayindex << ']';
|
||||
out << " upconnected from layer " << c.srclayer << ' ';
|
||||
const ShaderInstance *up = group[c.srclayer];
|
||||
out << "(" << up->layername() << ") ";
|
||||
out << " " << c.src.type.c_str() << ' '
|
||||
<< up->symbol(c.src.param)->name();
|
||||
if (c.src.arrayindex >= 0)
|
||||
out << '[' << c.src.arrayindex << ']';
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
return out.str ();
|
||||
}
|
||||
|
||||
@@ -562,7 +580,8 @@ ShaderInstance::compute_run_lazily ()
|
||||
// Suggested warning below... but are there use cases where people
|
||||
// want these to run (because they will extract the results they
|
||||
// want from output params)?
|
||||
if (! outgoing_connections() && ! writes_globals())
|
||||
if (! outgoing_connections() && ! empty_instance() &&
|
||||
! writes_globals() && ! renderer_outputs())
|
||||
shadingsys().warning ("Layer \"%s\" (shader %s) will run even though it appears to have no used results",
|
||||
layername(), shadername());
|
||||
#endif
|
||||
@@ -704,7 +723,7 @@ ShaderInstance::mergeable (const ShaderInstance &b, const ShaderGroup &g) const
|
||||
// Make sure system didn't ask for instances that query userdata to be
|
||||
// immune from instance merging.
|
||||
if (! shadingsys().m_opt_merge_instances_with_userdata
|
||||
&& userdata_params()) {
|
||||
&& (userdata_params() || b.userdata_params())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -828,8 +847,16 @@ ShaderGroup::serialize () const
|
||||
: inst->instoverride(p)->valuesource();
|
||||
if (vs == Symbol::InstanceVal) {
|
||||
TypeDesc type = s->typespec().simpletype();
|
||||
out << "param " << type << ' ' << s->name();
|
||||
int offset = s->dataoffset();
|
||||
if (type.is_unsized_array() && ! dstsyms_exist) {
|
||||
// If we're being asked to serialize a group that isn't
|
||||
// yet optimized, any "unsized" arrays will have their
|
||||
// concrete length and offset in the SymOverrideInfo,
|
||||
// not in the Symbol belonging to the instance.
|
||||
type.arraylen = inst->instoverride(p)->arraylen();
|
||||
offset = inst->instoverride(p)->dataoffset();
|
||||
}
|
||||
out << "param " << type << ' ' << s->name();
|
||||
int nvals = type.numelements() * type.aggregate;
|
||||
if (type.basetype == TypeDesc::INT) {
|
||||
const int *vals = &inst->m_iparams[offset];
|
||||
|
||||
@@ -711,8 +711,8 @@ BackendLLVM::build_llvm_instance (bool groupentry)
|
||||
if (llvm_debug() && groupentry)
|
||||
llvm_gen_debug_printf (Strutil::format("\n\n\n\nGROUP! %s",group().name()));
|
||||
if (llvm_debug())
|
||||
llvm_gen_debug_printf (Strutil::format("enter layer %s %s",
|
||||
inst()->layername(), inst()->shadername()));
|
||||
llvm_gen_debug_printf (Strutil::format("enter layer %d %s %s",
|
||||
this->layer(), inst()->layername(), inst()->shadername()));
|
||||
#endif
|
||||
if (shadingsys().countlayerexecs())
|
||||
ll.call_function ("osl_incr_layers_executed", sg_void_ptr());
|
||||
@@ -746,9 +746,6 @@ BackendLLVM::build_llvm_instance (bool groupentry)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Unconditionally execute earlier layers that are not lazy
|
||||
if (! gi->run_lazily() && i < group().nlayers()-1)
|
||||
llvm_call_layer (i, true /* unconditionally run */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -816,6 +813,17 @@ BackendLLVM::build_llvm_instance (bool groupentry)
|
||||
|
||||
// All the symbols are stack allocated now.
|
||||
|
||||
if (groupentry) {
|
||||
// Group entries also need to run any earlier layers that must be
|
||||
// run unconditionally. It's important that we do this AFTER all the
|
||||
// parameter initialization for this layer.
|
||||
for (int i = 0; i < group().nlayers()-1; ++i) {
|
||||
ShaderInstance *gi = group()[i];
|
||||
if (!gi->unused() && !gi->empty_instance() && !gi->run_lazily())
|
||||
llvm_call_layer (i, true /* unconditionally run */);
|
||||
}
|
||||
}
|
||||
|
||||
// Mark all the basic blocks, including allocating llvm::BasicBlock
|
||||
// records for each.
|
||||
find_basic_blocks ();
|
||||
@@ -850,8 +858,8 @@ BackendLLVM::build_llvm_instance (bool groupentry)
|
||||
// All done
|
||||
#if 0 /* helpful for debugging */
|
||||
if (llvm_debug())
|
||||
llvm_gen_debug_printf (Strutil::format("exit layer %s %s",
|
||||
inst()->layername(), inst()->shadername()));
|
||||
llvm_gen_debug_printf (Strutil::format("exit layer %d %s %s",
|
||||
this->layer(), inst()->layername(), inst()->shadername()));
|
||||
#endif
|
||||
ll.op_return();
|
||||
|
||||
@@ -964,11 +972,17 @@ BackendLLVM::run ()
|
||||
int nlayers = group().nlayers();
|
||||
m_layer_remap.resize (nlayers);
|
||||
m_num_used_layers = 0;
|
||||
if (shadingsys().debug() >= 1)
|
||||
std::cout << "\nLayers used:\n";
|
||||
for (int layer = 0; layer < nlayers; ++layer) {
|
||||
bool lastlayer = (layer == (nlayers-1));
|
||||
if (lastlayer ||
|
||||
(! group()[layer]->unused() && !group()[layer]->empty_instance()))
|
||||
{
|
||||
if (shadingsys().debug() >= 1)
|
||||
std::cout << " " << layer << "\n";
|
||||
m_layer_remap[layer] = m_num_used_layers++;
|
||||
}
|
||||
else
|
||||
m_layer_remap[layer] = -1;
|
||||
}
|
||||
|
||||
@@ -28,10 +28,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
#include <OpenImageIO/thread.h>
|
||||
#include <boost/thread/tss.hpp> /* for thread_specific_ptr */
|
||||
|
||||
#include "OSL/oslconfig.h"
|
||||
#include "OSL/llvm_util.h"
|
||||
|
||||
#if OSL_LLVM_VERSION >= 35 && ! OSL_BUILD_CPP11
|
||||
#error "LLVM >= 3.5 requires USE_CPP11=1"
|
||||
#endif
|
||||
|
||||
#ifndef USE_MCJIT
|
||||
// MCJIT first appeared with LLVM 3.3
|
||||
# define USE_MCJIT (OSL_LLVM_VERSION>=33)
|
||||
@@ -120,7 +125,7 @@ namespace pvt {
|
||||
namespace {
|
||||
static OIIO::spin_mutex llvm_global_mutex;
|
||||
static bool setup_done = false;
|
||||
static OIIO::thread_specific_ptr<LLVM_Util::PerThreadInfo> perthread_infos;
|
||||
static boost::thread_specific_ptr<LLVM_Util::PerThreadInfo> perthread_infos;
|
||||
static std::vector<shared_ptr<llvm::JITMemoryManager> > jitmm_hold;
|
||||
};
|
||||
|
||||
@@ -457,7 +462,7 @@ LLVM_Util::module_from_bitcode (const char *bitcode, size_t size,
|
||||
// called functions due to disagreement about whether a leading "_"
|
||||
// is part of the symbol name.
|
||||
#if OSL_LLVM_VERSION >= 35
|
||||
llvm::ErrorOr<llvm::Module *> ModuleOrErr = llvm::ParseBitcodeFile (buf, context());
|
||||
llvm::ErrorOr<llvm::Module *> ModuleOrErr = llvm::parseBitcodeFile (buf, context());
|
||||
if (std::error_code EC = ModuleOrErr.getError())
|
||||
if (err)
|
||||
*err = EC.message();
|
||||
|
||||
@@ -168,7 +168,7 @@ OSOReaderToMaster::symbol (SymType symtype, TypeSpec typespec, const char *name_
|
||||
} else if (typespec.simpletype().basetype == TypeDesc::STRING) {
|
||||
sym.dataoffset ((int) m_master->m_sdefaults.size());
|
||||
expand (m_master->m_sdefaults, nvals);
|
||||
} else if (typespec.is_closure()) {
|
||||
} else if (typespec.is_closure_based()) {
|
||||
// Closures are pointers, so we allocate a string default taking
|
||||
// adventage of their default being NULL as well.
|
||||
sym.dataoffset ((int) m_master->m_sdefaults.size());
|
||||
|
||||
@@ -38,6 +38,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <boost/regex_fwd.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <boost/thread/tss.hpp> /* for thread_specific_ptr */
|
||||
|
||||
#include <OpenImageIO/ustring.h>
|
||||
#include <OpenImageIO/thread.h>
|
||||
@@ -62,7 +63,6 @@ using OIIO::mutex;
|
||||
using OIIO::lock_guard;
|
||||
using OIIO::spin_mutex;
|
||||
using OIIO::spin_lock;
|
||||
using OIIO::thread_specific_ptr;
|
||||
using OIIO::ustringHash;
|
||||
namespace Strutil = OIIO::Strutil;
|
||||
|
||||
@@ -185,8 +185,22 @@ struct UserDataNeeded {
|
||||
}
|
||||
};
|
||||
|
||||
// Struct defining an attribute needed by a shader group
|
||||
struct AttributeNeeded {
|
||||
ustring name;
|
||||
ustring scope;
|
||||
|
||||
AttributeNeeded (ustring name, ustring scope = ustring())
|
||||
: name(name), scope(scope) {}
|
||||
|
||||
friend bool operator< (const AttributeNeeded &a, const AttributeNeeded &b) {
|
||||
if (a.name != b.name)
|
||||
return a.name < b.name;
|
||||
if (a.scope != b.scope)
|
||||
return a.scope < b.scope;
|
||||
return false; // they are equal
|
||||
}
|
||||
};
|
||||
|
||||
// Prefix for OSL shade up declarations, so LLVM can find them
|
||||
#define OSL_SHADEOP extern "C" OSL_LLVM_EXPORT
|
||||
@@ -593,14 +607,14 @@ public:
|
||||
return std::pair<Symbol*,Symbol*> ((Symbol*)NULL, (Symbol*)NULL);
|
||||
else
|
||||
return std::pair<Symbol*,Symbol*> (&i->m_instsymbols[0],
|
||||
&i->m_instsymbols[i->m_instsymbols.size()]);
|
||||
&i->m_instsymbols[0] + i->m_instsymbols.size());
|
||||
}
|
||||
friend std::pair<const Symbol *,const Symbol *> sym_range (const ShaderInstance *i) {
|
||||
if (i->m_instsymbols.size() == 0)
|
||||
return std::pair<const Symbol*,const Symbol*> ((const Symbol*)NULL, (const Symbol*)NULL);
|
||||
else
|
||||
return std::pair<const Symbol*,const Symbol*> (&i->m_instsymbols[0],
|
||||
&i->m_instsymbols[i->m_instsymbols.size()]);
|
||||
&i->m_instsymbols[0] + i->m_instsymbols.size());
|
||||
}
|
||||
|
||||
int Psym () const { return m_Psym; }
|
||||
@@ -614,7 +628,7 @@ public:
|
||||
const OpcodeVec & ops () const { return m_instops; }
|
||||
OpcodeVec & ops () { return m_instops; }
|
||||
|
||||
std::string print (); // Debugging
|
||||
std::string print (const ShaderGroup &group); // Debugging
|
||||
|
||||
SymbolVec &symbols () { return m_instsymbols; }
|
||||
const SymbolVec &symbols () const { return m_instsymbols; }
|
||||
@@ -647,7 +661,7 @@ public:
|
||||
/// instance overrides from the master copy.
|
||||
struct SymOverrideInfo {
|
||||
// Using bit fields to keep the data in 8 bytes in total.
|
||||
char m_valuesource: 3;
|
||||
unsigned char m_valuesource: 3;
|
||||
bool m_connected_down: 1;
|
||||
bool m_lockgeom: 1;
|
||||
int m_arraylen: 27;
|
||||
@@ -1085,7 +1099,7 @@ private:
|
||||
ParamValueList m_pending_params; ///< Pending Parameter() values
|
||||
ShaderGroupRef m_curgroup; ///< Current shading attribute state
|
||||
mutable mutex m_mutex; ///< Thread safety
|
||||
mutable thread_specific_ptr<PerThreadInfo> m_perthread_info;
|
||||
mutable boost::thread_specific_ptr<PerThreadInfo> m_perthread_info;
|
||||
|
||||
// Stats
|
||||
atomic_int m_stat_shaders_loaded; ///< Stat: shaders loaded
|
||||
@@ -1355,9 +1369,12 @@ private:
|
||||
std::vector<TypeDesc> m_userdata_types;
|
||||
std::vector<int> m_userdata_offsets;
|
||||
std::vector<char> m_userdata_derivs;
|
||||
std::vector<ustring> m_attributes_needed;
|
||||
std::vector<ustring> m_attribute_scopes;
|
||||
std::vector<ustring> m_renderer_outputs; ///< Names of renderer outputs
|
||||
bool m_unknown_textures_needed;
|
||||
bool m_unknown_closures_needed;
|
||||
bool m_unknown_attributes_needed;
|
||||
atomic_ll m_executions; ///< Number of times the group executed
|
||||
atomic_ll m_stat_total_shading_time_ticks; ///< Total shading time (ticks)
|
||||
|
||||
|
||||
@@ -60,10 +60,18 @@ RendererServices::RendererServices (TextureSystem *texsys)
|
||||
if (texsys) {// caller provided a texture system
|
||||
texturesys_ = texsys;
|
||||
} else { // Need to create a new texture system
|
||||
#if OSL_NO_DEFAULT_TEXTURESYSTEM
|
||||
// This build option instructs OSL to never create a TextureSystem
|
||||
// itself. (Most likely reason: this build of OSL is for a renderer
|
||||
// that replaces OIIO's TextureSystem with its own, and therefore
|
||||
// wouldn't want to accidentally make an OIIO one here.
|
||||
ASSERT (0 && "RendererServices was not passed a working TextureSystem*");
|
||||
#else
|
||||
texturesys_ = TextureSystem::create (true /* shared */);
|
||||
// Make some good guesses about default options
|
||||
texturesys_->attribute ("automip", 1);
|
||||
texturesys_->attribute ("autotile", 64);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,8 @@ static ustring u_nop ("nop"),
|
||||
u_pointcloud_write ("pointcloud_write"),
|
||||
u_isconnected ("isconnected"),
|
||||
u_setmessage ("setmessage"),
|
||||
u_getmessage ("getmessage");
|
||||
u_getmessage ("getmessage"),
|
||||
u_getattribute ("getattribute");
|
||||
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
@@ -330,11 +331,11 @@ RuntimeOptimizer::turn_into_new_op (Opcode &op, ustring newop, int newarg0,
|
||||
DASSERT (opnum >= 0 && opnum < (int)inst()->ops().size());
|
||||
if (debug() > 1)
|
||||
std::cout << "turned op " << opnum
|
||||
<< " from " << op.opname() << " to "
|
||||
<< " from '" << op_string(op) << "' to '"
|
||||
<< newop << ' ' << inst()->symbol(newarg0)->name() << ' '
|
||||
<< inst()->symbol(newarg1)->name() << ' '
|
||||
<< (newarg2<0 ? "" : inst()->symbol(newarg2)->name().c_str())
|
||||
<< (why.size() ? " : " : "") << why << "\n";
|
||||
<< (why.size() ? "' : " : "'") << why << "\n";
|
||||
op.reset (newop, newarg2<0 ? 2 : 3);
|
||||
inst()->args()[op.firstarg()+0] = newarg0;
|
||||
op.argwriteonly (0);
|
||||
@@ -358,9 +359,9 @@ RuntimeOptimizer::turn_into_assign (Opcode &op, int newarg, string_view why)
|
||||
int opnum = &op - &(inst()->ops()[0]);
|
||||
if (debug() > 1)
|
||||
std::cout << "turned op " << opnum
|
||||
<< " from " << op.opname() << " to "
|
||||
<< " from '" << op_string(op) << "' to '"
|
||||
<< opargsym(op,0)->name() << " = "
|
||||
<< inst()->symbol(newarg)->name()
|
||||
<< inst()->symbol(newarg)->name() << "'"
|
||||
<< (why.size() ? " : " : "") << why << "\n";
|
||||
op.reset (u_assign, 2);
|
||||
inst()->args()[op.firstarg()+1] = newarg;
|
||||
@@ -415,7 +416,7 @@ RuntimeOptimizer::turn_into_nop (Opcode &op, string_view why)
|
||||
if (op.opname() != u_nop) {
|
||||
if (debug() > 1)
|
||||
std::cout << "turned op " << (&op - &(inst()->ops()[0]))
|
||||
<< " from " << op.opname() << " to nop"
|
||||
<< " from '" << op_string(op) << "' to 'nop'"
|
||||
<< (why.size() ? " : " : "") << why << "\n";
|
||||
op.reset (u_nop, 0);
|
||||
return 1;
|
||||
@@ -437,7 +438,7 @@ RuntimeOptimizer::turn_into_nop (int begin, int end, string_view why)
|
||||
}
|
||||
}
|
||||
if (debug() > 1 && changed)
|
||||
std::cout << "turned ops " << begin << "-" << (end-1) << " into nop"
|
||||
std::cout << "turned ops " << begin << "-" << (end-1) << " into 'nop'"
|
||||
<< (why.size() ? " : " : "") << why << "\n";
|
||||
return changed;
|
||||
}
|
||||
@@ -447,7 +448,8 @@ RuntimeOptimizer::turn_into_nop (int begin, int end, string_view why)
|
||||
void
|
||||
RuntimeOptimizer::insert_code (int opnum, ustring opname,
|
||||
const int *argsbegin, const int *argsend,
|
||||
bool recompute_rw_ranges, int relation)
|
||||
RecomputeRWRangesOption recompute_rw_ranges,
|
||||
InsertRelation relation)
|
||||
{
|
||||
OpcodeVec &code (inst()->ops());
|
||||
std::vector<int> &opargs (inst()->args());
|
||||
@@ -550,7 +552,8 @@ RuntimeOptimizer::insert_code (int opnum, ustring opname,
|
||||
void
|
||||
RuntimeOptimizer::insert_code (int opnum, ustring opname,
|
||||
const std::vector<int> &args_to_add,
|
||||
bool recompute_rw_ranges, int relation)
|
||||
RecomputeRWRangesOption recompute_rw_ranges,
|
||||
InsertRelation relation)
|
||||
{
|
||||
const int *argsbegin = (args_to_add.size())? &args_to_add[0]: NULL;
|
||||
const int *argsend = argsbegin + args_to_add.size();
|
||||
@@ -562,7 +565,8 @@ RuntimeOptimizer::insert_code (int opnum, ustring opname,
|
||||
|
||||
|
||||
void
|
||||
RuntimeOptimizer::insert_code (int opnum, ustring opname, int relation,
|
||||
RuntimeOptimizer::insert_code (int opnum, ustring opname,
|
||||
InsertRelation relation,
|
||||
int arg0, int arg1, int arg2, int arg3)
|
||||
{
|
||||
int args[4];
|
||||
@@ -571,7 +575,7 @@ RuntimeOptimizer::insert_code (int opnum, ustring opname, int relation,
|
||||
if (arg1 >= 0) args[nargs++] = arg1;
|
||||
if (arg2 >= 0) args[nargs++] = arg2;
|
||||
if (arg3 >= 0) args[nargs++] = arg3;
|
||||
insert_code (opnum, opname, args, args+nargs, true, relation);
|
||||
insert_code (opnum, opname, args, args+nargs, RecomputeRWRanges, relation);
|
||||
}
|
||||
|
||||
|
||||
@@ -584,7 +588,8 @@ RuntimeOptimizer::insert_useparam (size_t opnum,
|
||||
{
|
||||
ASSERT (params_to_use.size() > 0);
|
||||
OpcodeVec &code (inst()->ops());
|
||||
insert_code (opnum, u_useparam, params_to_use, 1);
|
||||
insert_code (opnum, u_useparam, params_to_use,
|
||||
RecomputeRWRanges, GroupWithNext);
|
||||
|
||||
// All ops are "read"
|
||||
code[opnum].argwrite (0, false);
|
||||
@@ -1660,7 +1665,8 @@ RuntimeOptimizer::peephole2 (int opnum)
|
||||
newargs.push_back (oparg(op,i));
|
||||
turn_into_nop (op, "combine closure+mul");
|
||||
turn_into_nop (next, "combine closure+mul");
|
||||
insert_code (opnum, u_closure, newargs, true, 1);
|
||||
insert_code (opnum, u_closure, newargs,
|
||||
RecomputeRWRanges, GroupWithNext);
|
||||
if (debug() > 1)
|
||||
std::cout << "op " << opnum << "-" << (op2num)
|
||||
<< " combined closure+mul\n";
|
||||
@@ -1816,7 +1822,7 @@ RuntimeOptimizer::eliminate_middleman ()
|
||||
dsym = downinst->mastersymbol(c.dst.param);
|
||||
const Symbol *usym = upinst->symbol(upstream_symbol);
|
||||
if (! usym)
|
||||
usym = downinst->mastersymbol(upstream_symbol);
|
||||
usym = upinst->mastersymbol(upstream_symbol);
|
||||
ASSERT (dsym && usym);
|
||||
std::cout << "Removed " << inst()->layername() << "."
|
||||
<< s.name() << " middleman for "
|
||||
@@ -2712,7 +2718,7 @@ RuntimeOptimizer::run ()
|
||||
std::cout.flush ();
|
||||
std::cout << "Before optimizing layer " << layer << " "
|
||||
<< inst()->layername()
|
||||
<< ", I get:\n" << inst()->print()
|
||||
<< ", I get:\n" << inst()->print(group())
|
||||
<< "\n--------------------------------\n\n";
|
||||
std::cout.flush ();
|
||||
}
|
||||
@@ -2787,7 +2793,11 @@ RuntimeOptimizer::run ()
|
||||
<< " out? " << (inst()->outgoing_connections()?'y':'n')
|
||||
<< (inst()->writes_globals() ? " writes_globals" : "")
|
||||
<< (inst()->userdata_params() ? " userdata_params" : "")
|
||||
<< "\n" << inst()->print()
|
||||
<< (inst()->run_lazily() ? " run_lazily" : "")
|
||||
<< (inst()->outgoing_connections() ? " outgoing_connections" : "")
|
||||
<< (inst()->renderer_outputs() ? " renderer_outputs" : "")
|
||||
<< (inst()->writes_globals() ? " writes_globals" : "")
|
||||
<< "\n" << inst()->print(group())
|
||||
<< "\n--------------------------------\n\n";
|
||||
std::cout.flush ();
|
||||
}
|
||||
@@ -2797,10 +2807,12 @@ RuntimeOptimizer::run ()
|
||||
|
||||
m_unknown_textures_needed = false;
|
||||
m_unknown_closures_needed = false;
|
||||
m_unknown_attributes_needed = false;
|
||||
m_textures_needed.clear();
|
||||
m_closures_needed.clear();
|
||||
m_globals_needed.clear();
|
||||
m_userdata_needed.clear();
|
||||
m_attributes_needed.clear();
|
||||
for (int layer = 0; layer < nlayers; ++layer) {
|
||||
set_inst (layer);
|
||||
if (inst()->unused())
|
||||
@@ -2850,6 +2862,34 @@ RuntimeOptimizer::run ()
|
||||
} else {
|
||||
m_unknown_closures_needed = true;
|
||||
}
|
||||
} else if (op.opname() == u_getattribute) {
|
||||
Symbol *sym1 = opargsym (op, 1);
|
||||
ASSERT (sym1 && sym1->typespec().is_string());
|
||||
if (sym1->is_constant()) {
|
||||
if (op.nargs() == 3) {
|
||||
// getattribute( attributename, result )
|
||||
m_attributes_needed.insert( AttributeNeeded( *(ustring *)sym1->data() ) );
|
||||
} else {
|
||||
ASSERT (op.nargs() == 4 || op.nargs() == 5);
|
||||
Symbol *sym2 = opargsym (op, 2);
|
||||
if (sym2->typespec().is_string()) {
|
||||
// getattribute( scopename, attributename, result ) or
|
||||
// getattribute( scopename, attributename, arrayindex, result )
|
||||
if (sym2->is_constant()) {
|
||||
m_attributes_needed.insert( AttributeNeeded(
|
||||
*(ustring *)sym2->data(), *(ustring *)sym1->data()
|
||||
) );
|
||||
} else {
|
||||
m_unknown_attributes_needed = true;
|
||||
}
|
||||
} else {
|
||||
// getattribute( attributename, arrayindex, result )
|
||||
m_attributes_needed.insert( AttributeNeeded( *(ustring *)sym1->data() ) );
|
||||
}
|
||||
}
|
||||
} else { // sym1 not constant
|
||||
m_unknown_attributes_needed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2884,6 +2924,13 @@ RuntimeOptimizer::run ()
|
||||
shadingcontext()->info (" %s %s %s", f.name, f.type,
|
||||
f.derivs ? "(derivs)" : "");
|
||||
}
|
||||
if (m_attributes_needed.size()) {
|
||||
shadingcontext()->info ("Group needs attributes:");
|
||||
BOOST_FOREACH (const AttributeNeeded &f, m_attributes_needed)
|
||||
shadingcontext()->info (" %s %s", f.name, f.scope);
|
||||
if (m_unknown_attributes_needed)
|
||||
shadingcontext()->info (" Also may construct attribute names on the fly.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -231,29 +231,35 @@ public:
|
||||
|
||||
void make_symbol_room (int howmany=1);
|
||||
|
||||
/// Insert instruction 'opname' with arguments 'args_to_add' into the
|
||||
/// code at instruction 'opnum'. The existing code and concatenated
|
||||
/// argument lists can be found in code and opargs, respectively, and
|
||||
/// allsyms contains pointers to all symbols. mainstart is a reference
|
||||
/// to the address where the 'main' shader begins, and may be modified
|
||||
/// if the new instruction is inserted before that point.
|
||||
/// If recompute_rw_ranges is true, also adjust all symbols' read/write
|
||||
/// ranges to take the new instruction into consideration.
|
||||
/// Relation indicates its relation to surrounding instructions:
|
||||
/// 0 means none, -1 means it should have the same method, sourcefile,
|
||||
/// and sourceline as the preceeding instruction, 1 means it should
|
||||
/// have the same method, sourcefile, and sourceline as the subsequent
|
||||
/// instruction.
|
||||
enum RecomputeRWRangesOption { DontRecomputeRWRanges, RecomputeRWRanges };
|
||||
enum InsertRelation { NoRelation=0, GroupWithPrevious=-1, GroupWithNext=1 };
|
||||
/// Insert instruction 'opname' with arguments 'args_to_add' into
|
||||
/// the code at instruction 'opnum'. The existing code and
|
||||
/// concatenated argument lists can be found in code and opargs,
|
||||
/// respectively, and allsyms contains pointers to all symbols.
|
||||
/// mainstart is a reference to the address where the 'main' shader
|
||||
/// begins, and may be modified if the new instruction is inserted
|
||||
/// before that point. The recompute_rw_ranges parameter determines
|
||||
/// whether all symbols' read/write ranges should be adjusted to
|
||||
/// take the new instruction into consideration. Relation indicates
|
||||
/// its relation to surrounding instructions: GroupWithPrevious
|
||||
/// means it should have the same method, sourcefile, and sourceline
|
||||
/// as the preceeding instruction; GroupWithNext means it should
|
||||
/// have the same method, sourcefile, and sourceline as the
|
||||
/// subsequent instruction; NoRelation means we have no information,
|
||||
/// so don't copy that info from anywhere.
|
||||
void insert_code (int opnum, ustring opname,
|
||||
const std::vector<int> &args_to_add,
|
||||
bool recompute_rw_ranges=false, int relation=0);
|
||||
RecomputeRWRangesOption recompute_rw_ranges,
|
||||
InsertRelation relation=GroupWithNext);
|
||||
/// insert_code with begin/end arg array pointers.
|
||||
void insert_code (int opnum, ustring opname,
|
||||
const int *argsbegin, const int *argsend,
|
||||
bool recompute_rw_ranges=false, int relation=0);
|
||||
RecomputeRWRangesOption recompute_rw_ranges,
|
||||
InsertRelation relation=GroupWithNext);
|
||||
/// insert_code with explicit arguments (up to 4, a value of -1 means
|
||||
/// the arg isn't used). Presume recompute_rw_ranges is true.
|
||||
void insert_code (int opnum, ustring opname, int relation,
|
||||
void insert_code (int opnum, ustring opname, InsertRelation relation,
|
||||
int arg0=-1, int arg1=-1, int arg2=-1, int arg3=-1);
|
||||
|
||||
void insert_useparam (size_t opnum, const std::vector<int> ¶ms_to_use);
|
||||
@@ -342,6 +348,13 @@ public:
|
||||
|
||||
void stop_optimizing () { m_stop_optimizing = true; }
|
||||
|
||||
std::string op_string (const Opcode &op) {
|
||||
std::string s = op.opname().string();
|
||||
for (int a = 0; a < op.nargs(); ++a)
|
||||
s = s + ' ' + opargsym(op,a)->name().string();
|
||||
return s;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_optimize; ///< Current optimization level
|
||||
bool m_opt_simplify_param; ///< Turn instance params into const?
|
||||
@@ -375,8 +388,10 @@ private:
|
||||
std::set<ustring> m_textures_needed;
|
||||
std::set<ustring> m_closures_needed;
|
||||
std::set<ustring> m_globals_needed;
|
||||
std::set<AttributeNeeded> m_attributes_needed;
|
||||
bool m_unknown_textures_needed;
|
||||
bool m_unknown_closures_needed;
|
||||
bool m_unknown_attributes_needed;
|
||||
std::set<UserDataNeeded> m_userdata_needed;
|
||||
double m_stat_opt_locking_time; ///< locking time
|
||||
double m_stat_specialization_time; ///< specialization time
|
||||
|
||||
@@ -34,6 +34,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
#include "oslexec_pvt.h"
|
||||
#include "OSL/genclosure.h"
|
||||
@@ -661,11 +662,19 @@ ShadingSystemImpl::ShadingSystemImpl (RendererServices *renderer,
|
||||
|
||||
// If we still don't have a texture system, create a new one
|
||||
if (! m_texturesys) {
|
||||
#if OSL_NO_DEFAULT_TEXTURESYSTEM
|
||||
// This build option instructs OSL to never create a TextureSystem
|
||||
// itself. (Most likely reason: this build of OSL is for a renderer
|
||||
// that replaces OIIO's TextureSystem with its own, and therefore
|
||||
// wouldn't want to accidentally make an OIIO one here.
|
||||
ASSERT (0 && "ShadingSystem was not passed a working TextureSystem*");
|
||||
#else
|
||||
m_texturesys = TextureSystem::create (true /* shared */);
|
||||
ASSERT (m_texturesys);
|
||||
// Make some good guesses about default options
|
||||
m_texturesys->attribute ("automip", 1);
|
||||
m_texturesys->attribute ("autotile", 64);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Alternate way of turning on LLVM debug mode (temporary/experimental)
|
||||
@@ -1295,6 +1304,34 @@ ShadingSystemImpl::getattribute (ShaderGroup *group, string_view name,
|
||||
*(ustring *)val = ustring(group->serialize());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (name == "num_attributes_needed" && type == TypeDesc::TypeInt) {
|
||||
if (! group->optimized())
|
||||
optimize_group (*group);
|
||||
*(int *)val = (int)group->m_attributes_needed.size();
|
||||
return true;
|
||||
}
|
||||
if (name == "attributes_needed" && type.basetype == TypeDesc::PTR) {
|
||||
if (! group->optimized())
|
||||
optimize_group (*group);
|
||||
size_t n = group->m_attributes_needed.size();
|
||||
*(ustring **)val = n ? &group->m_attributes_needed[0] : NULL;
|
||||
return true;
|
||||
}
|
||||
if (name == "attribute_scopes" && type.basetype == TypeDesc::PTR) {
|
||||
if (! group->optimized())
|
||||
optimize_group (*group);
|
||||
size_t n = group->m_attribute_scopes.size();
|
||||
*(ustring **)val = n ? &group->m_attribute_scopes[0] : NULL;
|
||||
return true;
|
||||
}
|
||||
if (name == "unknown_attributes_needed" && type == TypeDesc::TypeInt) {
|
||||
if (! group->optimized())
|
||||
optimize_group (*group);
|
||||
*(int *)val = (int)group->m_unknown_attributes_needed;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1911,7 +1948,7 @@ ShadingSystemImpl::ShaderGroupBegin (string_view groupname,
|
||||
break; // error
|
||||
}
|
||||
if (Strutil::parse_char (p, '[')) {
|
||||
int arraylen;
|
||||
int arraylen = -1;
|
||||
Strutil::parse_int (p, arraylen);
|
||||
Strutil::parse_char (p, ']');
|
||||
type.arraylen = arraylen;
|
||||
@@ -1928,27 +1965,59 @@ ShadingSystemImpl::ShaderGroupBegin (string_view groupname,
|
||||
}
|
||||
string_view paramname (paramname_string);
|
||||
int lockgeom = true;
|
||||
int nvals = type.numelements() * type.aggregate;
|
||||
// For speed, reserve space. Note that for "unsized" arrays,
|
||||
// numelements() will return 1, so we only preallocate 1 slot
|
||||
// and let it grow as needed. That's ok. For everything else, we
|
||||
// will reserve the right amount up front.
|
||||
int vals_to_preallocate = type.numelements() * type.aggregate;
|
||||
// Stop parsing values when we hit the limit based on the
|
||||
// declaration.
|
||||
int max_vals = type.is_unsized_array() ? 1<<28 : vals_to_preallocate;
|
||||
if (type.basetype == TypeDesc::INT) {
|
||||
intvals.clear ();
|
||||
intvals.resize (nvals, 0);
|
||||
for (int i = 0; i < nvals; ++i) {
|
||||
if (! Strutil::parse_int (p, intvals[i]))
|
||||
intvals.reserve (vals_to_preallocate);
|
||||
int i;
|
||||
for (i = 0; i < max_vals; ++i) {
|
||||
int val = 0;
|
||||
if (Strutil::parse_int (p, val))
|
||||
intvals.push_back (val);
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (type.is_unsized_array()) {
|
||||
// For unsized arrays, now set the size based on how many
|
||||
// values we actually read.
|
||||
type.arraylen = std::max (1, i/type.aggregate);
|
||||
}
|
||||
// Zero-pad if we parsed fewer values than we needed
|
||||
intvals.resize (type.numelements()*type.aggregate, 0);
|
||||
ASSERT (type.numelements()*type.aggregate == int(intvals.size()));
|
||||
Parameter (paramname, type, &intvals[0], lockgeom);
|
||||
} else if (type.basetype == TypeDesc::FLOAT) {
|
||||
floatvals.clear ();
|
||||
floatvals.resize (nvals, 0.0f);
|
||||
for (int i = 0; i < nvals; ++i) {
|
||||
if (! Strutil::parse_float (p, floatvals[i]))
|
||||
floatvals.reserve (vals_to_preallocate);
|
||||
int i;
|
||||
for (i = 0; i < max_vals; ++i) {
|
||||
float val = 0;
|
||||
if (Strutil::parse_float (p, val))
|
||||
floatvals.push_back (val);
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (type.is_unsized_array()) {
|
||||
// For unsized arrays, now set the size based on how many
|
||||
// values we actually read.
|
||||
type.arraylen = std::max (1, i/type.aggregate);
|
||||
}
|
||||
// Zero-pad if we parsed fewer values than we needed
|
||||
floatvals.resize (type.numelements()*type.aggregate, 0);
|
||||
ASSERT (type.numelements()*type.aggregate == int(floatvals.size()));
|
||||
Parameter (paramname, type, &floatvals[0], lockgeom);
|
||||
} else if (type.basetype == TypeDesc::STRING) {
|
||||
stringvals.clear ();
|
||||
stringvals.resize (nvals);
|
||||
for (int i = 0; i < nvals; ++i) {
|
||||
stringvals.reserve (vals_to_preallocate);
|
||||
int i;
|
||||
for (i = 0; i < max_vals; ++i) {
|
||||
std::string unescaped;
|
||||
string_view s;
|
||||
Strutil::skip_whitespace (p);
|
||||
@@ -1963,8 +2032,16 @@ ShadingSystemImpl::ShaderGroupBegin (string_view groupname,
|
||||
if (s.size() == 0)
|
||||
break;
|
||||
}
|
||||
stringvals[i] = ustring(s);
|
||||
stringvals.push_back (ustring(s));
|
||||
}
|
||||
if (type.is_unsized_array()) {
|
||||
// For unsized arrays, now set the size based on how many
|
||||
// values we actually read.
|
||||
type.arraylen = std::max (1, i/type.aggregate);
|
||||
}
|
||||
// Zero-pad if we parsed fewer values than we needed
|
||||
stringvals.resize (type.numelements()*type.aggregate, ustring());
|
||||
ASSERT (type.numelements()*type.aggregate == int(stringvals.size()));
|
||||
Parameter (paramname, type, &stringvals[0], lockgeom);
|
||||
}
|
||||
|
||||
@@ -2407,6 +2484,11 @@ ShadingSystemImpl::optimize_group (ShaderGroup &group)
|
||||
group.m_userdata_types.push_back (n.type);
|
||||
group.m_userdata_derivs.push_back (n.derivs);
|
||||
}
|
||||
group.m_unknown_attributes_needed = rop.m_unknown_attributes_needed;
|
||||
BOOST_FOREACH (const AttributeNeeded &f, rop.m_attributes_needed) {
|
||||
group.m_attributes_needed.push_back (f.name);
|
||||
group.m_attribute_scopes.push_back (f.scope);
|
||||
}
|
||||
|
||||
BackendLLVM lljitter (*this, group, ctx);
|
||||
lljitter.run ();
|
||||
@@ -2561,7 +2643,7 @@ ShadingSystemImpl::merge_instances (ShaderGroup &group, bool post_opt)
|
||||
if (con.srclayer == b) {
|
||||
con.srclayer = a;
|
||||
A->outgoing_connections (true);
|
||||
if (B->symbols().size()) {
|
||||
if (A->symbols().size() && B->symbols().size()) {
|
||||
ASSERT (A->symbol(con.src.param)->name() ==
|
||||
B->symbol(con.src.param)->name());
|
||||
}
|
||||
|
||||
@@ -78,7 +78,15 @@ stdoslpath ()
|
||||
boost::filesystem::path path (program); // our program
|
||||
path = path.parent_path (); // now the bin dir of our program
|
||||
path = path.parent_path (); // now the parent dir
|
||||
path = path / "shaders";
|
||||
boost::filesystem::path savepath = path;
|
||||
// We search two spots: ../../lib/osl/include, and ../shaders
|
||||
path = savepath / "lib" / "osl" / "include";
|
||||
if (OIIO::Filesystem::exists (path.string())) {
|
||||
path = path / "stdosl.h";
|
||||
if (OIIO::Filesystem::exists (path.string()))
|
||||
return path.string();
|
||||
}
|
||||
path = savepath / "shaders";
|
||||
if (OIIO::Filesystem::exists (path.string())) {
|
||||
path = path / "stdosl.h";
|
||||
if (OIIO::Filesystem::exists (path.string()))
|
||||
|
||||
@@ -29,7 +29,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <OpenImageIO/hash.h>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <OpenImageIO/ustring.h>
|
||||
#include "OSL/oslexec.h"
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
@@ -29,7 +29,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <OpenImageIO/hash.h>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <OpenImageIO/ustring.h>
|
||||
#include "OSL/oslexec.h"
|
||||
|
||||
OSL_NAMESPACE_ENTER
|
||||
|
||||
@@ -33,7 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
#include <OpenImageIO/imageio.h>
|
||||
#include <OpenImageIO/imagebuf.h>
|
||||
@@ -708,6 +708,26 @@ test_group_attributes (ShaderGroup *group)
|
||||
<< userdata_offsets[i] << " deriv="
|
||||
<< userdata_derivs[i] << "\n";
|
||||
}
|
||||
int nattr = 0;
|
||||
if (shadingsys->getattribute (group, "num_attributes_needed", nattr) && nattr) {
|
||||
std::cout << "Need " << nattr << " attributes:\n";
|
||||
ustring *names = NULL;
|
||||
ustring *scopes = NULL;
|
||||
shadingsys->getattribute (group, "attributes_needed",
|
||||
TypeDesc::PTR, &names);
|
||||
shadingsys->getattribute (group, "attribute_scopes",
|
||||
TypeDesc::PTR, &scopes);
|
||||
DASSERT (names && scopes);
|
||||
for (int i = 0; i < nattr; ++i)
|
||||
std::cout << " " << names[i] << ' '
|
||||
<< scopes[i] << "\n";
|
||||
|
||||
int unk = 0;
|
||||
shadingsys->getattribute (group, "unknown_attributes_needed", unk);
|
||||
if (unk)
|
||||
std::cout << " and unknown attributes\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
shader a (output closure color output_closure = 0)
|
||||
{
|
||||
printf("Shader a \n");
|
||||
for (int i = 1; i < 3 ; ++i)
|
||||
{
|
||||
output_closure += color(u/i, 2.0, 0.0) * diffuse(N);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
shader b (closure color input_closures[2] = {0})
|
||||
{
|
||||
printf("Shader b \n");
|
||||
for (int i = 0; i < 2 ; ++i)
|
||||
{
|
||||
printf("In %d : %s\n", i, input_closures[i]);
|
||||
Ci += input_closures[i];
|
||||
}
|
||||
printf("Ci : %s \n", Ci);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
shader c (
|
||||
closure color in0 = 0,
|
||||
closure color in1 = 0,
|
||||
output closure color output_closures[2] = {in0, in1}
|
||||
)
|
||||
{
|
||||
printf("Shader c \n");
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
shader d (output closure color output_closure = 0)
|
||||
{
|
||||
printf("Shader d \n");
|
||||
for (int i = 1; i < 4 ; ++i)
|
||||
{
|
||||
output_closure += color(v/i, 0.0, 3.0) * diffuse(N);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
Compiled a.osl -> a.oso
|
||||
Compiled b.osl -> b.oso
|
||||
Compiled c.osl -> c.oso
|
||||
Compiled d.osl -> d.oso
|
||||
Connect alayer.output_closure to clayer.in0
|
||||
Connect dlayer.output_closure to clayer.in1
|
||||
Connect clayer.output_closures to blayer.input_closures
|
||||
Shader b
|
||||
Shader a
|
||||
Shader d
|
||||
Shader c
|
||||
In 0 : (0.5, 2, 0) * diffuse ((0, 0, 1))
|
||||
+ (0.25, 2, 0) * diffuse ((0, 0, 1))
|
||||
In 1 : (0.5, 0, 3) * diffuse ((0, 0, 1))
|
||||
+ (0.25, 0, 3) * diffuse ((0, 0, 1))
|
||||
+ (0.166667, 0, 3) * diffuse ((0, 0, 1))
|
||||
Ci : (0.5, 2, 0) * diffuse ((0, 0, 1))
|
||||
+ (0.25, 2, 0) * diffuse ((0, 0, 1))
|
||||
+ (0.5, 0, 3) * diffuse ((0, 0, 1))
|
||||
+ (0.25, 0, 3) * diffuse ((0, 0, 1))
|
||||
+ (0.166667, 0, 3) * diffuse ((0, 0, 1))
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
command += testshade ("-layer alayer a -layer dlayer d --layer clayer c --layer blayer b --connect alayer output_closure clayer in0 --connect dlayer output_closure clayer in1 --connect clayer output_closures blayer input_closures ")
|
||||
@@ -0,0 +1,7 @@
|
||||
surface a ( output closure color CCout = 0 )
|
||||
{
|
||||
CCout = diffuse(N) * color(0,0.18,0);
|
||||
Ci = CCout;
|
||||
printf ("a: CCout = %s\n", CCout);
|
||||
printf ("a: Ci = %s\n", Ci);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
surface b ( closure color CCin = 0 )
|
||||
{
|
||||
printf("\nb: CCin = %s\n", CCin);
|
||||
Ci = CCin + diffuse(N) * color(.18,0,0);
|
||||
printf("b: Ci = %s\n",Ci);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
Compiled a.osl -> a.oso
|
||||
Compiled b.osl -> b.oso
|
||||
Connect alayer.CCout to blayer.CCin
|
||||
a: CCout = (0, 0.18, 0) * diffuse ((0, 0, 1))
|
||||
a: Ci = (0, 0.18, 0) * diffuse ((0, 0, 1))
|
||||
|
||||
b: CCin = (0, 0.18, 0) * diffuse ((0, 0, 1))
|
||||
b: Ci = (0, 0.18, 0) * diffuse ((0, 0, 1))
|
||||
+ (0.18, 0, 0) * diffuse ((0, 0, 1))
|
||||
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Example that failed with a prior bug.
|
||||
# The test case is that layer a modifies Ci so is unconditional, but also
|
||||
# its output CCout is connected to layer b's CCin. There was a bug where
|
||||
# the earlier layer was run and its values copied before (duh, not after)
|
||||
# b's params would be initialized, thus overwriting the copied values.
|
||||
|
||||
|
||||
command += testshade("-layer alayer a -layer blayer b --connect alayer CCout blayer CCin")
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
struct Astruct {
|
||||
float s, t;
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "Astruct.h"
|
||||
|
||||
shader a (output Astruct Aout = {-1, -1})
|
||||
{
|
||||
Aout.s = u;
|
||||
Aout.t = v;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "Astruct.h"
|
||||
|
||||
shader b (Astruct Ain = {0,0},
|
||||
output Astruct Bout = Ain,
|
||||
output color Cout = 0)
|
||||
{
|
||||
Cout = color (Bout.s, Bout.t, 0);
|
||||
printf ("%g : should be %g %g 0\n", Cout, u, v);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
Compiled a.osl -> a.oso
|
||||
Compiled b.osl -> b.oso
|
||||
Connect a.Aout to b.Ain
|
||||
|
||||
Output Cout to out.exr
|
||||
0.5 0.5 0 : should be 0.5 0.5 0
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
command = testshade("--layer a a --layer b b --connect a Aout b Ain -o Cout out.exr")
|
||||
@@ -0,0 +1,18 @@
|
||||
Compiled test.osl -> test.oso
|
||||
farr array length 5
|
||||
[0] = 1.1
|
||||
[1] = 1.2
|
||||
[2] = 1.3
|
||||
[3] = 1.4
|
||||
[4] = 1.5
|
||||
carr array length 2
|
||||
[0] = 0.1 0.2 0.3
|
||||
[1] = 0.4 0.5 0.6
|
||||
iarr array length 2
|
||||
[0] = 11
|
||||
[1] = 12
|
||||
sarr array length 3
|
||||
[0] = "foo"
|
||||
[1] = "bar"
|
||||
[2] = "baz"
|
||||
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
command += testshade("-group serial.oslgroup")
|
||||
@@ -0,0 +1,7 @@
|
||||
param float[] farr 1.1 1.2 1.3 1.4 1.5 ;
|
||||
param int[] iarr 11 12 ;
|
||||
param string[] sarr "foo" "bar" "baz" ;
|
||||
param color[] carr 0.1 0.2 0.3 0.4 0.5 0.6 ;
|
||||
shader test ;
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
void print_array_contents (string name, int arr[])
|
||||
{
|
||||
printf ("%s array length %d\n", name, arraylength(arr));
|
||||
for (int i = 0; i < arraylength(arr); ++i)
|
||||
printf (" [%d] = %d\n", i, arr[i]);
|
||||
}
|
||||
|
||||
|
||||
void print_array_contents (string name, float arr[])
|
||||
{
|
||||
printf ("%s array length %d\n", name, arraylength(arr));
|
||||
for (int i = 0; i < arraylength(arr); ++i)
|
||||
printf (" [%d] = %g\n", i, arr[i]);
|
||||
}
|
||||
|
||||
|
||||
void print_array_contents (string name, color arr[])
|
||||
{
|
||||
printf ("%s array length %d\n", name, arraylength(arr));
|
||||
for (int i = 0; i < arraylength(arr); ++i)
|
||||
printf (" [%d] = %g\n", i, arr[i]);
|
||||
}
|
||||
|
||||
|
||||
void print_array_contents (string name, string arr[])
|
||||
{
|
||||
printf ("%s array length %d\n", name, arraylength(arr));
|
||||
for (int i = 0; i < arraylength(arr); ++i)
|
||||
printf (" [%d] = \"%s\"\n", i, arr[i]);
|
||||
}
|
||||
|
||||
|
||||
shader test (float farr[] = {0},
|
||||
color carr[] = {0},
|
||||
int iarr[] = {0},
|
||||
string sarr[] = {""}
|
||||
)
|
||||
{
|
||||
print_array_contents ("farr", farr);
|
||||
print_array_contents ("carr", carr);
|
||||
print_array_contents ("iarr", iarr);
|
||||
print_array_contents ("sarr", sarr);
|
||||
}
|
||||
Reference in New Issue
Block a user