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