1// Copyright Contributors to the Open Shading Language project.
2// SPDX-License-Identifier: BSD-3-Clause
3// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
4
5#pragma once
6
7
8#include <OSL/platform.h>
9#include <OSL/export.h>
10#include <OSL/oslversion.h>
11
12
13// All the things we need from Imath.
14#define OSL_USING_IMATH @OSL_USING_IMATH@
15#if OSL_USING_IMATH >= 3
16#   include <Imath/ImathVec.h>
17#   include <Imath/ImathMatrix.h>
18#   include <Imath/ImathColor.h>
19#else
20    // OpenEXR 2.x lacks the Cuda decorators we need, so we replicated some
21    // Imath files in OSL/Imathx, adding the decorations needed for them to
22    // be safe to compile with Cuda (and sometimes other improvements).
23#   include <OSL/Imathx/ImathLimits.h>
24#   include <OSL/Imathx/ImathVec.h>
25#   include <OSL/Imathx/ImathMatrix.h>
26#   include <OSL/Imathx/ImathColor.h>
27#   include <OSL/matrix22.h>
28#endif
29
30// The fmt library causes trouble for Cuda. Work around by disabling it from
31// oiio headers (OIIO <= 2.1) or telling fmt not to use the troublesome
32// int128 that Cuda doesn't understand (OIIO >= 2.2).
33#ifdef __CUDA_ARCH__
34#    define OIIO_USE_FMT 0
35#    define FMT_USE_INT128 0
36#endif
37
38// All the things we need from OpenImageIO
39#include <OpenImageIO/oiioversion.h>
40#include <OpenImageIO/errorhandler.h>
41#include <OpenImageIO/texture.h>
42#include <OpenImageIO/typedesc.h>
43#include <OpenImageIO/ustring.h>
44#include <OpenImageIO/platform.h>
45#include <OpenImageIO/span.h>
46
47
48OSL_NAMESPACE_ENTER
49
50/// Various compile-time defaults are defined here that could, in
51/// principle, be redefined if you are using OSL in some particular
52/// renderer that wanted things a different way.
53
54/// By default, we operate with single precision float.  Change this
55/// definition to make a shading system that fundamentally operates
56/// on doubles.
57/// FIXME: it's very likely that all sorts of other things will break
58/// if you do this, but eventually we should make sure it works.
59typedef float Float;
60
61/// By default, use the excellent Imath vector, matrix, and color types
62/// from the IlmBase package from: http://www.openexr.com
63///
64/// It's permissible to override these types with the vector, matrix,
65/// and color classes of your choice, provided that (a) your vectors
66/// have the same data layout as a simple Float[n]; (b) your
67/// matrices have the same data layout as Float[n][n]; and (c) your
68/// classes have most of the obvious constructors and overloaded
69/// operators one would expect from a C++ vector/matrix/color class.
70using Vec2     = Imath::Vec2<Float>;
71using Vec3     = Imath::Vec3<Float>;
72using Color3   = Imath::Color3<Float>;
73using Matrix33 = Imath::Matrix33<Float>;
74using Matrix44 = Imath::Matrix44<Float>;
75
76#if OSL_USING_IMATH >= 3
77using Matrix22 = Imath::Matrix22<Float>;
78#else
79using Matrix22 = Imathx::Matrix22<Float>;
80#endif
81
82
83/// Assume that we are dealing with OpenImageIO's texture system.  It
84/// doesn't literally have to be OIIO's... it just needs to have the
85/// same API as OIIO's TextureSystem class, it's a purely abstract class
86/// anyway.
87using OIIO::TextureSystem;
88using OIIO::TextureOpt;
89
90// And some other things we borrow from OIIO...
91using OIIO::ErrorHandler;
92using OIIO::TypeDesc;
93using OIIO::ustring;
94using OIIO::ustringHash;
95using OIIO::string_view;
96using OIIO::span;
97using OIIO::cspan;
98
99
100
101/////////////////////////////////////////////////////////////////////////
102// Define various macros and templates that need to be different for
103// various C++ versions or compilers, or to make up for things not
104// yet available in earlier C++ standards.
105
106#if OSL_CPLUSPLUS_VERSION >= 17
107    // fold expression to expand
108    #define __OSL_EXPAND_PARAMETER_PACKS(EXPRESSION) \
109        (void((EXPRESSION)) , ... );
110#else
111    // Choose to use initializer list to expand our parameter pack so that
112    // the order they are evaluated in the order they appear
113    #define __OSL_EXPAND_PARAMETER_PACKS(EXPRESSION) \
114        { \
115            using expander = int [sizeof...(IntListT)]; \
116            (void)expander{((EXPRESSION),0)...}; \
117        }
118#endif
119
120
121namespace pvt {
122
123#if (OSL_CPLUSPLUS_VERSION >= 14)
124    template<int... IntegerListT>
125    using int_sequence = std::integer_sequence<int, IntegerListT...>;
126
127    template<int EndBeforeT>
128    using make_int_sequence =  std::make_integer_sequence<int, EndBeforeT>;
129
130    template<bool... BoolListT >
131    using bool_sequence = std::integer_sequence<bool, BoolListT... >;
132#else
133    // std::integer_sequence requires c++14 library support,
134    // we have our own version here in case the environment is c++14 compiler
135    // building against c++11 library.
136    template<int... IntegerListT>
137    struct int_sequence
138    {
139    };
140
141    template<int StartAtT, int EndBeforeT, typename IntSequenceT>
142    struct int_sequence_generator;
143
144    template<int StartAtT, int EndBeforeT, int... IntegerListT>
145    struct int_sequence_generator<StartAtT, EndBeforeT, int_sequence<IntegerListT...>>
146    {
147        typedef typename int_sequence_generator<StartAtT+1, EndBeforeT, int_sequence<IntegerListT..., StartAtT>>::type type;
148    };
149
150    template<int EndBeforeT, int... IntegerListT>
151    struct int_sequence_generator<EndBeforeT, EndBeforeT, int_sequence<IntegerListT...>>
152    {
153        typedef int_sequence<IntegerListT...> type;
154    };
155
156    template<int EndBeforeT>
157    using make_int_sequence = typename int_sequence_generator<0, EndBeforeT, int_sequence<> >::type;
158
159    template<bool... BoolListT >
160    struct bool_sequence
161	{
162	};
163#endif
164
165#if (OSL_CPLUSPLUS_VERSION >= 17)
166    template<class... ListT>
167    using conjunction = std::conjunction<ListT...>;
168#else
169    template<class... ListT>
170    using conjunction = std::is_same<bool_sequence<true,ListT::value...>, bool_sequence<ListT::value..., true>>;
171#endif
172
173    // We need the SFINAE type to be different for
174    // enable_if_type from disable_if_type so that we can apply both to
175    // the same template signature to avoid
176    // "error: invalid redeclaration of member function template"
177    // NOTE: std::enable_if_t is a c++14 library feature, our baseline
178    // and we wish to remain compatible with c++11 header libraries.
179    // Also we are using std::true_type vs. void as the default type
180    template <bool TestT, typename TypeT = std::true_type>
181    using enable_if_type = typename std::enable_if<TestT, TypeT>::type;
182
183} // namespace pvt
184
185// Instead of relying on compiler loop unrolling, we can statically call functor
186// for each integer in a sequence
187template <template<int> class ConstantWrapperT, int... IntListT, typename FunctorT>
188static OSL_FORCEINLINE OSL_HOSTDEVICE void static_foreach(pvt::int_sequence<IntListT...>, const FunctorT &iFunctor) {
189     __OSL_EXPAND_PARAMETER_PACKS( iFunctor(ConstantWrapperT<IntListT>{}) );
190}
191
192template <template<int> class ConstantWrapperT, int N, typename FunctorT>
193static OSL_FORCEINLINE OSL_HOSTDEVICE void static_foreach(const FunctorT &iFunctor) {
194    static_foreach<ConstantWrapperT>(pvt::make_int_sequence<N>(), iFunctor);
195}
196
197#if (OSL_CPLUSPLUS_VERSION >= 14)
198    template<int N>
199    using ConstIndex = std::integral_constant<int, N>;
200#else
201    template<int N>
202    struct ConstIndex : public std::integral_constant<int, N>
203    {
204        // C++14 adds this conversion operator we need to allow non-generic
205        // lambda functions (pre C++14) to accept an "int" instead of a
206        // typed ConstIndex<N> with "auto"
207        constexpr int operator()() const noexcept {
208            return N;
209        }
210    };
211#endif
212
213
214// During development it can be useful to output extra information
215// NOTE:  internal use only
216#ifdef OSL_DEV
217    #define OSL_DEV_ONLY(...) __VA_ARGS__
218#else
219    #define OSL_DEV_ONLY(...)
220#endif
221
222
223OSL_NAMESPACE_EXIT
224