From 12530f115dfc759b00ee4de6dc27bf5fa3f32fe0 Mon Sep 17 00:00:00 2001 From: Steena Monteiro Date: Wed, 20 Dec 2023 22:29:40 -0800 Subject: [PATCH] api: Ustringhash phase 3 (#1732) Move OSL library functions and remaining execution time interface from ustring to ustringhash. Intent is all code for cpu or device just use ustringhash only. This allows us to remove STRING_PARAM, ustringrep, and OSL_USTRINGREP_IS_HASH. All interfaces and library code should explicitly use ustringhash or ustring, or for library functions llvm can call ustringhash_pod or ustring_pod Compile time strings used in the OSL Library are represented in strdecls.h and will be available as ustring variables in the Strings namespace as well as available as unstringhash constexpr variables in the Hashes namespace. Compile time strings used by the Renderer should adopt a similiar strategy as exemplified by TestShade which keeps its strings in rs_strdecls.h and made available as ustring variables in the RS::Strings namespace as well as available as unstringhash constexpr variables in the RS::Hashes namespace. Added helper utility functions to generate ustring from ustringhash_pods Constant string arrays: Previously, array copys required copying data via address of symbol on host. To enable working on device, replaced memcpy with array allocation and loading of values. Constant arrays are now present as global arrays in final llvm module. On the Batched side compatability/integration: Batched OSL Library functions continue to use ustrings (not ustringhashes to reduce scope/risk). Batched OSL library functions that call their scalar counterparts were adjusted to pass arguments as ustringhash_pods and store results as ustrings STRING_PARAMS, device_string.h, and string_hash.h: Built-in strings on the CUDA side are now accessed via Hashes namespace, instead of STRING_PARAMS and are evaluated as ustringhashes. Similarly, DeviceString, StringParams, HDSTR are obsolete, and device_string.h is eliminated. Hashes.h, which only contains OIIO's strhash and pvtstrlen functions (both formerly in string_hash.h), replaces all inclusions of device_string.h. Namespace Hashes in hashes.h contains pre-compiled ustringhashes representing strings from strdecls.h. Texture, dictionary, closure: Helper implementation functions are used by both scalar and batched versions. However, since scalar uses ustringhashes and the batched version uses ustrings added a flag to inform functions on treating TypeDesc::STRING has either a ustring or a ustringhash testing: Added testing of bitcode rendereservices for unoptimized OSL shader. array-copy tests regression: Added new test to verify copying of arrays of unequal lengths Signed-off-by: Steena Monteiro * Deleted liboslexec/string_hash.h Signed-off-by: Steena Monteiro * Modified rs_get_attribute to use OpaqueExecutionContext and ustringhash. Changed example programs--testshade, testrenderer, and osltoy--to use device friendly constexpr (RS|OSL)::Hashes and (RS|OSL)::Strings variables with rs_strdecls.h vs constructing ustrings on the fly. Signed-off-by: Steena Monteiro * Fixed clang format issues; added uint64_t casts for constant64; removed unused variable; added array-copy to testsuite Signed-off-by: Steena Monteiro * Fixed clang format issues in llvm_instance.cpp Signed-off-by: Steena Monteiro * Added fix in llvm_assign_impl for assignment of non-constant scalar to an array Signed-off-by: Steena Monteiro * Fixed clang-format in simplerend.cpp. Signed-off-by: Steena Monteiro * Addressed review comments -- (1) Added ll.constant(ustring().cstr()) in llvm_gen and batched_llvm_gen and (2) Added comments for boolean arguments that indicate ustrings are treated as hashes Signed-off-by: Steena Monteiro * Addressed comments on Optix build failures Signed-off-by: Steena Monteiro * Resolved merge conflicts Signed-off-by: Steena Monteiro * Fixed clang-format Signed-off-by: Steena Monteiro * Fixed split-reg for batched Signed-off-by: Steena Monteiro * Replaced llvm_load_stringhash with llvm_const_hash; Changed format string to ustringhash_pod in osl_printf, osl_fprintf, osl_warning, osl_error stubs; Fixed ShaderGlobals' position, u, and v in optix_grid_renderer.cu. Signed-off-by: Steena Monteiro --------- Signed-off-by: Steena Monteiro Signed-off-by: Larry Gritz Co-authored-by: Larry Gritz --- src/cmake/testing.cmake | 27 ++- src/include/OSL/device_string.h | 133 ------------ src/include/OSL/hashes.h | 67 ++++++ src/include/OSL/llvm_util.h | 10 +- src/include/OSL/oslconfig.h.in | 69 +----- src/include/OSL/oslexec.h | 6 - src/include/OSL/rendererservices.h | 38 ++-- src/include/OSL/rs_free_function.h | 14 +- src/include/OSL/strdecls.h | 1 + src/include/OSL/wide.h | 9 + src/liboslexec/backendllvm.cpp | 203 +++++++----------- src/liboslexec/backendllvm.h | 95 ++------ src/liboslexec/batched_backendllvm.cpp | 8 + src/liboslexec/batched_llvm_gen.cpp | 119 +++++++--- src/liboslexec/builtindecl.h | 158 +++++++------- src/liboslexec/builtindecl_wide_xmacro.h | 19 +- src/liboslexec/closure.cpp | 40 ++-- src/liboslexec/constfold.cpp | 13 ++ src/liboslexec/dictionary.cpp | 52 +++-- src/liboslexec/llvm_gen.cpp | 184 ++++++++-------- src/liboslexec/llvm_instance.cpp | 148 ++++++++----- src/liboslexec/llvm_ops.cpp | 17 +- src/liboslexec/llvm_util.cpp | 50 +++-- src/liboslexec/opclosure.cpp | 6 +- src/liboslexec/opcolor.cpp | 136 ++++++------ src/liboslexec/opcolor.h | 34 +-- src/liboslexec/opfmt.cpp | 13 +- src/liboslexec/opmatrix.cpp | 85 ++++---- src/liboslexec/opmessage.cpp | 26 +-- src/liboslexec/opnoise.cpp | 194 +++++++++-------- src/liboslexec/opspline.cpp | 68 +++--- src/liboslexec/opstring.cpp | 134 +++++++----- src/liboslexec/optexture.cpp | 159 ++++++++------ src/liboslexec/oslexec_pvt.h | 61 +++--- src/liboslexec/pointcloud.cpp | 110 +++++----- src/liboslexec/rendservices.cpp | 7 + src/liboslexec/rs_fallback.cpp | 12 +- src/liboslexec/runtimeoptimize.h | 2 + src/liboslexec/shading_state_uniform.h | 8 +- src/liboslexec/shadingsys.cpp | 78 ++++--- src/liboslexec/splineimpl.h | 14 +- src/liboslexec/string_hash.h | 36 ---- src/liboslexec/wide/wide_opclosure.cpp | 2 +- src/liboslexec/wide/wide_opcolor.cpp | 75 ++++--- src/liboslexec/wide/wide_opdictionary.cpp | 17 +- src/liboslexec/wide/wide_opmatrix.cpp | 45 +--- src/liboslexec/wide/wide_opmessage.cpp | 14 +- src/liboslexec/wide/wide_oppointcloud.cpp | 8 +- src/liboslexec/wide/wide_opstring.cpp | 9 + src/liboslexec/wide/wide_optexture.cpp | 30 +-- src/liboslexec/wide/wide_shadingsys.cpp | 52 ++--- src/osltoy/osltoyrenderer.cpp | 149 +++++++------ src/osltoy/osltoyrenderer.h | 85 ++++---- src/osltoy/rs_strdecls.h | 36 ++++ src/testrender/cuda/optix_raytracer.cu | 2 +- src/testrender/cuda/rend_lib.cu | 73 +++---- src/testrender/cuda/rend_lib.h | 18 +- src/testrender/cuda/wrapper.cu | 7 +- src/testrender/optixraytracer.cpp | 28 +-- src/testrender/optixraytracer.h | 2 +- src/testrender/rs_strdecls.h | 35 +++ src/testrender/shading.cpp | 32 +-- src/testrender/simpleraytracer.cpp | 72 ++++--- src/testrender/simpleraytracer.h | 5 +- src/testshade/batched_simplerend.cpp | 2 +- src/testshade/cuda/optix_grid_renderer.cu | 29 +-- src/testshade/optixgridrender.cpp | 27 +-- src/testshade/optixgridrender.h | 2 +- src/testshade/render_state.h | 20 +- src/testshade/rs_simplerend.cpp | 113 +++++----- src/testshade/rs_strdecls.h | 5 + src/testshade/simplerend.cpp | 107 ++++----- src/testshade/simplerend.h | 4 +- .../array-copy-reg/test_arraycopy_u_int.osl | 2 + testsuite/array-copy/BATCHED | 0 testsuite/array-copy/OPTIX | 0 testsuite/array-copy/ref/out.txt | 18 ++ testsuite/array-copy/run.py | 7 + testsuite/array-copy/test.osl | 44 ++++ testsuite/raytype-reg/run.py | 4 +- 80 files changed, 2046 insertions(+), 1797 deletions(-) delete mode 100644 src/include/OSL/device_string.h create mode 100644 src/include/OSL/hashes.h delete mode 100644 src/liboslexec/string_hash.h create mode 100644 src/osltoy/rs_strdecls.h create mode 100644 src/testrender/rs_strdecls.h create mode 100644 testsuite/array-copy/BATCHED create mode 100644 testsuite/array-copy/OPTIX create mode 100644 testsuite/array-copy/ref/out.txt create mode 100755 testsuite/array-copy/run.py create mode 100644 testsuite/array-copy/test.osl diff --git a/src/cmake/testing.cmake b/src/cmake/testing.cmake index 3dd4f0c11..637f2a401 100644 --- a/src/cmake/testing.cmake +++ b/src/cmake/testing.cmake @@ -133,6 +133,17 @@ macro ( TESTSUITE ) add_one_testsuite ("${_testname}" "${_testsrcdir}" ENV TESTSHADE_OPT=0 ) endif () + # Run the same test again using bitcode based free function renderer + # services keeping unoptimized, unless it matches a few patterns that + # we don't test unoptimized (or has an OPTIMIZEONLY marker file). + if (NOT _testname MATCHES "optix" + AND NOT EXISTS "${_testsrcdir}/NOSCALAR" + AND NOT EXISTS "${_testsrcdir}/BATCHED_REGRESSION" + AND NOT EXISTS "${_testsrcdir}/OPTIMIZEONLY" + AND NOT EXISTS "${_testsrcdir}/NORSBITCODE") + add_one_testsuite ("${_testname}.rs_bitcode" "${_testsrcdir}" + ENV TESTSHADE_OPT=0 TESTSHADE_RS_BITCODE=1) + endif () # Run the same test again with aggressive -O2 runtime # optimization, triggered by setting TESTSHADE_OPT env variable. # Skip OptiX-only tests and those with a NOOPTIMIZE marker file. @@ -143,7 +154,8 @@ macro ( TESTSUITE ) add_one_testsuite ("${_testname}.opt" "${_testsrcdir}" ENV TESTSHADE_OPT=2 ) endif () - # Run the same test again with aggressive -O2 runtime + # Run the same test again using bitcode based free function renderer + # services keeping aggressive -O2 runtime # optimization, triggered by setting TESTSHADE_OPT env variable. # Skip OptiX-only tests and those with a NOOPTIMIZE marker file. if (NOT _testname MATCHES "optix" @@ -218,6 +230,13 @@ macro ( TESTSUITE ) endif () # if there is an RS_BITCODE marker file in the directory. + if ((EXISTS "${_testsrcdir}/RS_BITCODE" OR test_all_rs_bitcode) + AND NOT EXISTS "${_testsrcdir}/BATCHED_REGRESSION" + AND NOT EXISTS "${_testsrcdir}/RS_BITCODE_REGRESSION" + AND NOT EXISTS "${_testsrcdir}/OPTIMIZEONLY") + add_one_testsuite ("${_testname}.rsbitcode" "${_testsrcdir}" + ENV TESTSHADE_OPT=0 TESTSHADE_RS_BITCODE=1 ) + endif () if ((EXISTS "${_testsrcdir}/RS_BITCODE" OR test_all_rs_bitcode) AND NOT EXISTS "${_testsrcdir}/BATCHED_REGRESSION" AND NOT EXISTS "${_testsrcdir}/RS_BITCODE_REGRESSION" @@ -244,7 +263,7 @@ macro (osl_add_all_tests) # special installed tests. TESTSUITE ( aastep allowconnect-err andor-reg and-or-not-synonyms arithmetic area-reg arithmetic-reg - array array-reg array-copy-reg array-derivs array-range + array array-reg array-copy array-copy-reg array-derivs array-range array-aassign array-assign-reg array-length-reg bitwise-and-reg bitwise-or-reg bitwise-shl-reg bitwise-shr-reg bitwise-xor-reg blackbody blackbody-reg blendmath breakcont breakcont-reg @@ -356,8 +375,8 @@ macro (osl_add_all_tests) struct-nested struct-nested-assign struct-nested-deep ternary testshade-expr - test-fmt-arrays test-fmt-fileprint - test-fmt-cxpf test-fmt-noise test-fmt-matrixcolor + test-fmt-arrays test-fmt-fileprint + test-fmt-cxpf test-fmt-noise test-fmt-matrixcolor test-fmt-stpf test-fmt-errorwarning test-fmt-errorwarning-repeats texture-alpha texture-alpha-derivs texture-blur texture-connected-options diff --git a/src/include/OSL/device_string.h b/src/include/OSL/device_string.h deleted file mode 100644 index 6ef82ff54..000000000 --- a/src/include/OSL/device_string.h +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright Contributors to the Open Shading Language project. -// SPDX-License-Identifier: BSD-3-Clause -// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage - -#pragma once - -#include - -// USAGE NOTES: -// -// To define a "standard" DeviceString, add a STRDECL to -// specifying the string literal and the name to use for the variable. - - -OSL_NAMESPACE_ENTER - - -// In OptiX 7+: -// Strings are not stored on the GPU at all. Strings are represented by -// their hash values which are computed at compile-time. Because of this, -// we have no access to either the strings' contents or their lengths. - -struct DeviceString { -#ifdef __CUDA_ARCH__ - size_t m_chars; -#else - const char* m_chars; -#endif - -#ifdef __CUDA_ARCH__ - OSL_HOSTDEVICE DeviceString() {} - OSL_HOSTDEVICE DeviceString(uint64_t i) : m_chars(i) {} -#endif - - OSL_HOSTDEVICE uint64_t hash() const - { -#ifdef __CUDA_ARCH__ - return m_chars; -#else - return *(uint64_t*)(m_chars - sizeof(uint64_t) - sizeof(uint64_t)); -#endif - } - - // In OptiX 7 we don't store the string's length. Make this a compile - // time error. -#ifndef __CUDA_ARCH__ - OSL_HOSTDEVICE uint64_t length() const - { - return *(uint64_t*)(m_chars - sizeof(uint64_t)); - } -#endif - - // In OptiX 7 we can't return the string's contents. Make this a compile - // time error. -#ifndef __CUDA_ARCH__ - OSL_HOSTDEVICE const char* c_str() const - { - return m_chars; - } -#endif - - OSL_HOSTDEVICE bool operator==(const DeviceString& other) const - { - return m_chars == other.m_chars; - } - - OSL_HOSTDEVICE bool operator!=(const DeviceString& other) const - { - return m_chars != other.m_chars; - } - -#ifdef __CUDA_ARCH__ - - OSL_HOSTDEVICE bool operator==(const size_t other) const - { - return hash() == other; - } - - OSL_HOSTDEVICE bool operator!=(const size_t other) const - { - return hash() != other; - } - - OSL_HOSTDEVICE operator size_t() const - { - return hash(); - } - -#endif -}; - - -// Choose the right cast for string parameters depending on the target. The -// macro is the same as the USTR macro defined in oslexec_pvt.h when compiling -// for the host. -#ifndef __CUDA_ARCH__ -# define HDSTR(cstr) (*((ustring*)&cstr)) -#else -# define HDSTR(cstr) (*((OSL::DeviceString*)&cstr)) -#endif - - -// When compiling shadeops C++ sources for CUDA devices, we need to use -// DeviceString instead of ustring for some input parameters, so we use this -// typedef to select the correct type depending on the target. -#ifndef __CUDA_ARCH__ -typedef ustring StringParam; -#else -typedef DeviceString StringParam; -#endif - - -#ifdef __CUDA_ARCH__ -namespace DeviceStrings { -# define STRDECL(str, var_name) \ - extern __device__ OSL_NAMESPACE::DeviceString var_name; -# undef STRDECL -} // namespace DeviceStrings -#else -# ifdef OSL_HOST_RS_BITCODE -# define STRING_PARAMS(x) RS_##x -# else -# define STRING_PARAMS(x) StringParams::x -# endif -#endif - - -OSL_NAMESPACE_EXIT - - -#ifndef __CUDA_ARCH__ -namespace StringParams = OSL_NAMESPACE::Strings; -#endif diff --git a/src/include/OSL/hashes.h b/src/include/OSL/hashes.h new file mode 100644 index 000000000..2a3ed920d --- /dev/null +++ b/src/include/OSL/hashes.h @@ -0,0 +1,67 @@ +// Copyright Contributors to the Open Shading Language project. +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + +#pragma once + +#include +#include +#include + +// USAGE NOTES: +// +// To define a "standard" DeviceString, add a STRDECL to +// specifying the string literal and the name to use for the variable. + + +OSL_NAMESPACE_ENTER + +namespace pvt { + +OIIO_CONSTEXPR14 inline size_t +pvtstrlen(const char* s) +{ + if (s == nullptr) + return 0; + size_t len = 0; + while (s[len] != 0) + len++; + return len; +} + +} // namespace pvt + +// The string_view(const char *) is only constexpr for c++17 +// which would prevent OIIO::Strutil::strhash from being +// constexpr for c++14. +// workaround by using local version here with a private +// constexpr strlen +OIIO_CONSTEXPR14 inline size_t +strhash(const char* s) +{ + size_t len = pvt::pvtstrlen(s); + return OIIO::Strutil::strhash(OIIO::string_view(s, len)); +} + +// Template to ensure the hash is evaluated at compile time. +template static constexpr size_t HashConstEval = V; +#define OSL_HASHIFY(unquoted_string) \ + HashConstEval + +namespace { // Scope Hashes variables to just this translation unit +namespace Hashes { +#ifdef __CUDA_ARCH__ // TODO: restrict to CUDA version < 11.4, otherwise the contexpr should work +# define STRDECL(str, var_name) \ + __device__ const OSL::ustringhash var_name(OSL::strhash(str)); +#else +# define STRDECL(str, var_name) \ + constexpr OSL::ustringhash var_name(OSL::strhash(str)); +#endif +#include +#undef STRDECL +}; // namespace Hashes +} // unnamed namespace + + + +OSL_NAMESPACE_EXIT diff --git a/src/include/OSL/llvm_util.h b/src/include/OSL/llvm_util.h index e6810e686..7fa2980cc 100644 --- a/src/include/OSL/llvm_util.h +++ b/src/include/OSL/llvm_util.h @@ -27,6 +27,7 @@ class DISubroutineType; class ExecutionEngine; class Function; class FunctionType; +class GlobalVariable; class SectionMemoryManager; class JITEventListener; class Linker; @@ -546,6 +547,7 @@ class OSLEXECPUBLIC LLVM_Util { llvm::Type* type_matrix() const { return m_llvm_type_matrix; } llvm::Type* type_typedesc() const { return m_llvm_type_longlong; } llvm::Type* type_ustring() { return m_llvm_type_ustring; } + llvm::Type* type_real_ustring() { return m_llvm_type_real_ustring; } llvm::PointerType* type_void_ptr() const { return m_llvm_type_void_ptr; } llvm::PointerType* type_ustring_ptr() const { @@ -718,6 +720,10 @@ class OSLEXECPUBLIC LLVM_Util { llvm::Value* constant(ustring s); llvm::Value* constant(string_view s) { return constant(ustring(s)); } + llvm::Constant* constant_array(cspan constants); + llvm::GlobalVariable* create_global_constant(llvm::Constant* initializer, + const std::string& llname = {}); + llvm::Value* llvm_mask_to_native(llvm::Value* llvm_mask); llvm::Value* native_to_llvm_mask(llvm::Value* native_mask); @@ -1087,7 +1093,9 @@ class OSLEXECPUBLIC LLVM_Util { llvm::Type* m_llvm_type_void; llvm::Type* m_llvm_type_triple; llvm::Type* m_llvm_type_matrix; - llvm::Type* m_llvm_type_ustring; + llvm::Type* m_llvm_type_real_ustring; // True const char * + llvm::Type* + m_llvm_type_ustring; // UStringRep can change between int64(hash) and a const char * llvm::PointerType* m_llvm_type_void_ptr; llvm::PointerType* m_llvm_type_char_ptr; llvm::PointerType* m_llvm_type_bool_ptr; diff --git a/src/include/OSL/oslconfig.h.in b/src/include/OSL/oslconfig.h.in index 144f250a7..178c7efc8 100644 --- a/src/include/OSL/oslconfig.h.in +++ b/src/include/OSL/oslconfig.h.in @@ -151,62 +151,45 @@ fmtformat_to_n(OutIt &out, size_t n, const string_view& fmt, Args&&... args) } -/// OSL_USTRINGREP_IS_HASH will be 1 if the build-time option was enabled to -/// make the ustringrep be a ustringhash, rather than a ustring directly. -#cmakedefine01 OSL_USTRINGREP_IS_HASH - -#if OSL_USTRINGREP_IS_HASH -/// ustringrep is the class we use to represent strings in the shader. -using ustringrep = ustringhash; -#else -/// ustringrep is the class we use to represent strings in the shader. -using ustringrep = ustring; -#endif - /// ustringhash_pod is the type we use to pass hash data in llvm function calls. using ustringhash_pod = size_t; -#if OSL_USTRINGREP_IS_HASH -/// ustring_pod is the type we use to pass string data in llvm function calls. -using ustring_pod = ustringhash_pod; -#else /// ustring_pod is the type we use to pass string data in llvm function calls. using ustring_pod = const char*; -#endif /// Convenience function to convert to a ustring. inline ustring -ustring_from(ustringhash h) +ustring_from(ustringhash_pod h) { - return ustring::from_hash(h.hash()); + return ustring::from_hash(h); } /// Convenience function to convert to a ustring. inline ustring -ustring_from(ustring u) +ustring_from(ustringhash h) { - return u; + return ustring::from_hash(h.hash()); } /// Convenience function to convert to a ustring. inline ustring -ustring_from(string_view s) +ustring_from(ustring u) { - return ustring(s); + return u; } /// Convenience function to convert to a ustringhash. -inline ustringhash +OSL_HOSTDEVICE inline ustringhash ustringhash_from(ustringhash u) { return u; } /// Convenience function to convert USTRINGHASH_POD to a ustringhash. -inline ustringhash +OSL_HOSTDEVICE inline ustringhash ustringhash_from(ustringhash_pod u) { #if OIIO_VERSION_GREATER_EQUAL(2, 4, 10) @@ -230,42 +213,6 @@ ustringhash_from(ustring u) } -/// Convenience function to convert to a ustringrep. -inline ustringrep -ustringrep_from(ustringhash h) -{ -#if OSL_USTRINGREP_IS_HASH - return h; -#else - return ustring::from_hash(h.hash()); -#endif -} - -/// Convenience function to convert to a ustringrep. -inline ustringrep -ustringrep_from(ustring u) -{ -#if OSL_USTRINGREP_IS_HASH - return u.hash(); -#else - return u; -#endif -} - -/// Convenience function to convert to a ustringrep. -inline ustringrep -ustringrep_from(string_view s) -{ - ustring u(s); -#if OSL_USTRINGREP_IS_HASH - return u.hash(); -#else - return u; -#endif -} - - - using TypeDesc_pod = int64_t; static_assert(sizeof(TypeDesc_pod) == sizeof(TypeDesc), diff --git a/src/include/OSL/oslexec.h b/src/include/OSL/oslexec.h index 3ec98ea53..0ae628aff 100644 --- a/src/include/OSL/oslexec.h +++ b/src/include/OSL/oslexec.h @@ -50,12 +50,6 @@ namespace pvt { class ShadingSystemImpl; } -#ifdef __CUDA_ARCH__ -# define STRING_PARAMS(x) \ - UStringHash::HashConstEval -#else -# define STRING_PARAMS(x) StringParams::x -#endif namespace Strings { #ifdef __CUDA_ARCH__ diff --git a/src/include/OSL/rendererservices.h b/src/include/OSL/rendererservices.h index 66ad5dd26..8613bb4ab 100644 --- a/src/include/OSL/rendererservices.h +++ b/src/include/OSL/rendererservices.h @@ -33,14 +33,14 @@ typedef void (*PrepareClosureFunc)(RendererServices*, int id, void* data); typedef void (*SetupClosureFunc)(RendererServices*, int id, void* data); enum class AttributeSpecBuiltinArg { - ShaderGlobalsPointer, // void* (TODO: ideally ShaderGlobals*) - ShadeIndex, // int - Derivatives, // bool - Type, // TypeDesc_pod - ArrayIndex, // int, Always zero for non-indexed array lookups. - IsArrayLookup, // bool - ObjectName, // const char* (TODO: change to ustringhash) - AttributeName, // const char* (TODO: change to ustringhash) + OpaqueExecutionContext, //OpaqueExecContextPtr + ShadeIndex, // int + Derivatives, // bool + Type, // TypeDesc_pod + ArrayIndex, // int, Always zero for non-indexed array lookups. + IsArrayLookup, // bool + ObjectName, // ustringhash_pod + AttributeName, // ustringhash_pod }; using AttributeSpecArg = ArgVariant; @@ -253,6 +253,8 @@ class OSLEXECPUBLIC RendererServices { /// specified (object == ustring()), then the renderer should search *first* /// for the attribute on the currently shaded object, and next, if /// unsuccessful, on the currently shaded "scene". + /// NOTE: During shader execution when type==TypeDesc::STRING, + /// val should be populated with a ustringhash /// /// Note to renderers: if sg is NULL, that means /// get_attribute is being called speculatively by the runtime @@ -260,6 +262,8 @@ class OSLEXECPUBLIC RendererServices { /// run on. Be robust to this situation, return 'true' (retrieve the /// attribute) if you can (known object and attribute name), but /// otherwise just fail by returning 'false'. + /// NOTE: During shader compilation/optimization when type==TypeDesc::STRING, + /// val should be populated with a ustring virtual bool get_attribute(ShaderGlobals* sg, bool derivatives, ustringhash object, TypeDesc type, ustringhash name, void* val); @@ -274,6 +278,8 @@ class OSLEXECPUBLIC RendererServices { /// 'val'. If derivatives is true, the derivatives should be written into val /// as well. Return false if no user-data with the given name and type was /// found. + /// NOTE: During shader execution when type==TypeDesc::STRING, + /// val should be populated with a ustringhash virtual bool get_userdata(bool derivatives, ustringhash name, TypeDesc type, ShaderGlobals* sg, void* val); @@ -445,6 +451,8 @@ class OSLEXECPUBLIC RendererServices { /// of the requested type stored in out_data. /// /// Return 1 if the attribute is found, 0 otherwise. + /// NOTE: During shader execution when attr_type==TypeDesc::STRING, + /// out_data should be populated with a ustringhash virtual int pointcloud_get(ShaderGlobals* sg, ustringhash filename, size_t* indices, int count, ustringhash attr_name, TypeDesc attr_type, @@ -453,17 +461,19 @@ class OSLEXECPUBLIC RendererServices { /// Write a point to the named pointcloud, which will be saved /// at the end of the frame. Return true if everything is ok, /// false if there was an error. + /// NOTE: During shader execution when attribute types[i] == TypeDesc::STRING, + /// data[i] will point to a a ustringhash virtual bool pointcloud_write(ShaderGlobals* sg, ustringhash filename, const OSL::Vec3& pos, int nattribs, - const ustringrep* names, + const ustringhash* names, const TypeDesc* types, const void** data); /// Options for the trace call. struct TraceOpt { - float mindist; ///< ignore hits closer than this - float maxdist; ///< ignore hits farther than this - bool shade; ///< whether to shade what is hit - ustringrep traceset; ///< named trace set + float mindist; ///< ignore hits closer than this + float maxdist; ///< ignore hits farther than this + bool shade; ///< whether to shade what is hit + ustringhash traceset; ///< named trace set TraceOpt() : mindist(0.0f), maxdist(1.0e30), shade(false) {} enum class LLVMMemberIndex { @@ -485,6 +495,8 @@ class OSLEXECPUBLIC RendererServices { /// Get the named message from the renderer and if found then /// write it into 'val'. Otherwise, return false. This is only /// called for "sourced" messages, not ordinary intra-group messages. + /// NOTE: During shader execution when type==TypeDesc::STRING, + /// val should be populated with a ustringhash virtual bool getmessage(ShaderGlobals* sg, ustringhash source, ustringhash name, TypeDesc type, void* val, bool derivatives); diff --git a/src/include/OSL/rs_free_function.h b/src/include/OSL/rs_free_function.h index a0b5f1744..0e7269d62 100644 --- a/src/include/OSL/rs_free_function.h +++ b/src/include/OSL/rs_free_function.h @@ -26,7 +26,7 @@ extern "C" { } #endif -#include +#include #include // Prefix for OSL shade op declarations. @@ -60,7 +60,7 @@ rs_get_inverse_matrix_xform_time(OSL::OpaqueExecContextPtr oec, /// Returns true if ok, false if the named matrix is not known. OSL_RSOP bool rs_get_matrix_space_time(OSL::OpaqueExecContextPtr oec, OSL::Matrix44& result, - OSL::StringParam from, float time); + OSL::ustringhash from, float time); /// Get the 4x4 matrix that transforms points from "common" space to /// the named 'to' coordinate system to at the given time. Suggested @@ -68,7 +68,7 @@ rs_get_matrix_space_time(OSL::OpaqueExecContextPtr oec, OSL::Matrix44& result, /// particular renderer may have a better technique. OSL_RSOP bool rs_get_inverse_matrix_space_time(OSL::OpaqueExecContextPtr oec, - OSL::Matrix44& result, OSL::StringParam to, + OSL::Matrix44& result, OSL::ustringhash to, float time); /// Get the 4x4 matrix that transforms by the specified @@ -96,7 +96,7 @@ rs_get_inverse_matrix_xform(OSL::OpaqueExecContextPtr oec, /// at all). OSL_RSOP bool rs_get_matrix_space(OSL::OpaqueExecContextPtr oec, OSL::Matrix44& result, - OSL::StringParam from); + OSL::ustringhash from); /// Get the 4x4 matrix that transforms points from "common" space to /// the named 'to' coordinate system. Since there is no time value @@ -106,7 +106,7 @@ rs_get_matrix_space(OSL::OpaqueExecContextPtr oec, OSL::Matrix44& result, /// particular renderer may have a better technique. OSL_RSOP bool rs_get_inverse_matrix_space(OSL::OpaqueExecContextPtr oec, - OSL::Matrix44& result, OSL::StringParam to); + OSL::Matrix44& result, OSL::ustringhash to); /// Transform points Pin[0..npoints-1] in named coordinate system /// 'from' into 'to' coordinates, storing the result in Pout[] using @@ -129,8 +129,8 @@ rs_get_inverse_matrix_space(OSL::OpaqueExecContextPtr oec, /// if there isn't a special nonlinear transformation between the /// two spaces. OSL_RSOP bool -rs_transform_points(OSL::OpaqueExecContextPtr oec, OSL::StringParam from, - OSL::StringParam to, float time, const OSL::Vec3* Pin, +rs_transform_points(OSL::OpaqueExecContextPtr oec, OSL::ustringhash from, + OSL::ustringhash to, float time, const OSL::Vec3* Pin, OSL::Vec3* Pout, int npoints, OSL::TypeDesc::VECSEMANTICS vectype); diff --git a/src/include/OSL/strdecls.h b/src/include/OSL/strdecls.h index a51262ebc..d4b2f5628 100644 --- a/src/include/OSL/strdecls.h +++ b/src/include/OSL/strdecls.h @@ -146,3 +146,4 @@ STRDECL("arraylength", arraylength) STRDECL("unknown", unknown) STRDECL("ERROR: Unknown color space transformation \"%s\" -> \"%s\"\n", ErrorColorTransform) +STRDECL("world", world) \ No newline at end of file diff --git a/src/include/OSL/wide.h b/src/include/OSL/wide.h index b9b866fd1..ed0f866a4 100644 --- a/src/include/OSL/wide.h +++ b/src/include/OSL/wide.h @@ -2182,6 +2182,15 @@ template<> struct WideTraits { } }; +template<> struct WideTraits { + static bool matches(const TypeDesc& type_desc) + { + // NOTE: using bitwise & to avoid branches + return (type_desc.basetype == TypeDesc::STRING) + & (type_desc.aggregate == TypeDesc::SCALAR); + } +}; + // We let Vec3 match any vector semantics as we don't have a separate Point or Normal classes template<> struct WideTraits { static bool matches(const TypeDesc& type_desc) diff --git a/src/liboslexec/backendllvm.cpp b/src/liboslexec/backendllvm.cpp index c08321b4b..62855dfa1 100644 --- a/src/liboslexec/backendllvm.cpp +++ b/src/liboslexec/backendllvm.cpp @@ -32,8 +32,7 @@ BackendLLVM::BackendLLVM(ShadingSystemImpl& shadingsys, ShaderGroup& group, m_name_llvm_syms = shadingsys.m_llvm_output_bitcode; // Select the appropriate ustring representation - ll.ustring_rep(m_use_optix ? LLVM_Util::UstringRep::hash - : LLVM_Util::UstringRep::charptr); + ll.ustring_rep(LLVM_Util::UstringRep::hash); ll.dumpasm(shadingsys.m_llvm_dumpasm); ll.jit_fma(shadingsys.m_llvm_jit_fma); @@ -83,7 +82,10 @@ BackendLLVM::llvm_pass_type(const TypeSpec& typespec) else if (t == TypeDesc::INT) lt = ll.type_int(); else if (t == TypeDesc::STRING) - lt = (llvm::Type*)ll.type_ustring(); + // When interpretting parameters, "s" is a real string + // regardless of LLVM_Util::UStringRep + // And "h" is used for hashes which maps to OSL::TypeUint64 + lt = (llvm::Type*)ll.type_real_ustring(); else if (t.aggregate == TypeDesc::VEC3) lt = (llvm::Type*)ll.type_void_ptr(); //llvm_type_triple_ptr(); else if (t.aggregate == TypeDesc::MATRIX44) @@ -307,78 +309,6 @@ BackendLLVM::getOrAllocateLLVMSymbol(const Symbol& sym) } - -#if OSL_USE_OPTIX -llvm::Value* -BackendLLVM::addCUDAGlobalVariable(const std::string& name, int size, - int alignment, const void* init_data, - TypeDesc type) -{ - OSL_ASSERT(use_optix() - && "This function is only supposed to be used with OptiX!"); - - llvm::Constant* constant = nullptr; - - if (type == TypeDesc::TypeFloat) { - constant = ll.constant(*(const float*)init_data); - } else if (type == TypeDesc::TypeInt) { - constant = ll.constant(*(const int*)init_data); - } else if (type == TypeDesc::TypeString) { - constant = ll.constant64(((const ustring*)init_data)->hash()); - // N.B. Since this is the OptiX side specifically, we will represent - // strings as the ustringhash, so we know it as a constant. - } else { - // Handle unspecified types as generic byte arrays - llvm::ArrayRef arr_ref((uint8_t*)init_data, size); - constant = llvm::ConstantDataArray::get(ll.module()->getContext(), - arr_ref); - } - - llvm::GlobalVariable* g_var = reinterpret_cast( - ll.module()->getOrInsertGlobal(name, constant->getType())); - - OSL_DASSERT(g_var && "Unable to create GlobalVariable"); - -# if OSL_LLVM_VERSION >= 100 - g_var->setAlignment(llvm::MaybeAlign(alignment)); -# else - g_var->setAlignment(alignment); -# endif - - g_var->setLinkage(llvm::GlobalValue::PrivateLinkage); - g_var->setVisibility(llvm::GlobalValue::DefaultVisibility); - g_var->setInitializer(constant); - m_const_map[name] = g_var; - - return g_var; -} - - - -llvm::Value* -BackendLLVM::getOrAllocateCUDAVariable(const Symbol& sym) -{ - OSL_ASSERT(use_optix() - && "This function is only supported when using OptiX!"); - - std::string name = global_unique_symname(sym); - - // Return the Value if it has already been allocated - auto it = get_const_map().find(name); - if (it != get_const_map().end()) - return it->second; - - // TODO: Figure out the actual CUDA alignment requirements for the various - // OSL types. For now, be somewhat conservative and assume 8 for - // non-scalar types. - int alignment = (sym.typespec().is_scalarnum()) ? 4 : 8; - return addCUDAGlobalVariable(name, sym.size(), alignment, sym.data(), - sym.typespec().simpletype()); -} -#endif - - - llvm::Value* BackendLLVM::llvm_get_pointer(const Symbol& sym, int deriv, llvm::Value* arrayindex) @@ -392,26 +322,18 @@ BackendLLVM::llvm_get_pointer(const Symbol& sym, int deriv, llvm::Value* result = NULL; if (sym.symtype() == SymTypeConst) { - TypeSpec elemtype = sym.typespec().elementtype(); -#if OSL_USE_OPTIX - if (use_optix()) { - // Check the constant map for the named Symbol; if it's found, then - // a GlobalVariable has been created for it - llvm::Value* ptr = getOrAllocateCUDAVariable(sym); - if (ptr) { - result = llvm_ptr_cast(ptr, llvm_typedesc(elemtype), - llnamefmt("cast_to_{}_", sym.typespec())); - // N.B. llvm_typedesc() for a string will know that on OptiX, - // strings are actually represented as just the hash. - } - } else -#endif - { - // For constants on the CPU side, start with *OUR* pointer to the - // constant values. - result = ll.constant_ptr(sym.data(), - ll.type_ptr(llvm_type(elemtype))); + auto sym_name = sym.name().string(); + + std::string unique_symname = global_unique_symname(sym); + auto it = get_const_map().find(unique_symname); + OSL_ASSERT(it != get_const_map().end()); + result = it->second; + if (result) { + TypeSpec elemtype = sym.typespec().elementtype(); + result = llvm_ptr_cast(result, llvm_typedesc(elemtype), + llnamefmt("cast_to_{}_", sym.typespec())); } + return result; } else { // If the symbol is not a SymTypeConst, then start with the initial // pointer to the variable's memory location. @@ -471,7 +393,7 @@ BackendLLVM::llvm_load_value(const Symbol& sym, int deriv, return ll.constant(sym.get_float(component)); } if (sym.typespec().is_string()) { - return llvm_load_string(sym.get_string()); + return llvm_const_hash(sym.get_string()); } OSL_ASSERT(0 && "unhandled constant type"); } @@ -520,18 +442,6 @@ BackendLLVM::llvm_load_value(llvm::Value* ptr, const TypeSpec& type, int deriv, result = ll.op_float_to_int(result); else if (type.is_int() && cast == TypeDesc::TypeFloat) result = ll.op_int_to_float(result); - else if (type.is_string() && cast == TypeDesc::LONGLONG) { - result = ll.ptr_to_cast(result, ll.type_longlong()); - // FIXME -- is this case ever used? Seems strange. - } - - // We still disguise hashed strings as char*. Ideally, we would only do - // that if the rep were a charptr, but we disguise the hashes as char*'s - // also to avoid ugliness with function signatures differing between CPU - // and GPU. Maybe some day we'll use the hash representation on both - // sides? - if (type.is_string() && ll.ustring_rep() != LLVM_Util::UstringRep::charptr) - result = ll.int_to_ptr_cast(result); return result; } @@ -551,24 +461,31 @@ BackendLLVM::llvm_load_constant_value(const Symbol& sym, int arrayindex, OSL_DASSERT(arrayindex >= 0 && "Called llvm_load_constant_value with negative array index"); - if (sym.typespec().is_float()) { + int ncomps = (int)sym.typespec().aggregate(); + // Handle expanding single value to multiple. + // Caller's responsiblity to keep component index in bounds otherwise + if (ncomps == 1) + component = 0; + OSL_ASSERT(component < ncomps); + int linear_index = ncomps * arrayindex + component; + + if (sym.typespec().is_triple() || sym.typespec().is_matrix()) { + return ll.constant(sym.get_float(linear_index)); + } + if (sym.typespec().is_float_based()) { if (cast == TypeDesc::TypeInt) - return ll.constant((int)sym.get_float(arrayindex)); + return ll.constant((int)sym.get_float(linear_index)); else - return ll.constant(sym.get_float(arrayindex)); + return ll.constant(sym.get_float(linear_index)); } - if (sym.typespec().is_int()) { + if (sym.typespec().is_int_based()) { if (cast == TypeDesc::TypeFloat) - return ll.constant((float)sym.get_int(arrayindex)); + return ll.constant((float)sym.get_int(linear_index)); else - return ll.constant(sym.get_int(arrayindex)); - } - if (sym.typespec().is_triple() || sym.typespec().is_matrix()) { - int ncomps = (int)sym.typespec().aggregate(); - return ll.constant(sym.get_float(ncomps * arrayindex + component)); + return ll.constant(sym.get_int(linear_index)); } - if (sym.typespec().is_string()) { - return llvm_load_string(sym.get_string(arrayindex)); + if (sym.typespec().is_string_based()) { + return llvm_const_hash(sym.get_string(linear_index)); } OSL_ASSERT(0 && "unhandled constant type"); @@ -861,11 +778,15 @@ BackendLLVM::llvm_assign_impl(Symbol& Result, Symbol& Src, int arrayindex, return true; } - // Copying of entire arrays. It's ok if the array lengths don't match, + // Copying of entire arrays. But only for non-const source symbols + // as we don't want to generate memcpy to host memory or to ustrings + // when we are really using ustringhash for llvm gen. + // It's ok if the array lengths don't match, // it will only copy up to the length of the smaller one. The compiler // will ensure they are the same size, except for certain cases where // the size difference is intended (by the optimizer). - if (result_t.is_array() && src_t.is_array() && arrayindex == -1) { + if (result_t.is_array() && !Src.is_constant() && src_t.is_array() + && arrayindex == -1) { OSL_DASSERT(assignable(result_t.elementtype(), src_t.elementtype())); llvm::Value* resultptr = llvm_get_pointer(Result); llvm::Value* srcptr = llvm_get_pointer(Src); @@ -890,14 +811,38 @@ BackendLLVM::llvm_assign_impl(Symbol& Result, Symbol& Src, int arrayindex, const int num_components = rt.aggregate; const bool singlechan = (srccomp != -1) || (dstcomp != -1); if (!singlechan) { - for (int i = 0; i < num_components; ++i) { - llvm::Value* src_val - = Src.is_constant() - ? llvm_load_constant_value(Src, arrayindex, i, basetype) - : llvm_load_value(Src, 0, arrind, i, basetype); - if (!src_val) - return false; - llvm_store_value(src_val, Result, 0, arrind, i); + if (rt.is_array() && arrayindex == -1) { + // Initialize entire array + const int num_elements = std::min(rt.numelements(), + src_t.simpletype().numelements()); + for (int a = 0; a < num_elements; ++a) { + llvm::Value* const_arrind = ll.constant(a); + for (int i = 0; i < num_components; ++i) { + llvm::Value* src_val + = Src.is_constant() + ? llvm_load_constant_value(Src, a, i, basetype) + : llvm_load_value( + Src, 0, + Src.typespec().is_array() ? const_arrind + : nullptr, + (Src.typespec().aggregate() == 1) ? 0 : i, + basetype); + if (!src_val) + return false; + llvm_store_value(src_val, Result, 0, const_arrind, i); + } + } + } else { + for (int i = 0; i < num_components; ++i) { + llvm::Value* src_val + = Src.is_constant() + ? llvm_load_constant_value(Src, arrayindex, i, + basetype) + : llvm_load_value(Src, 0, arrind, i, basetype); + if (!src_val) + return false; + llvm_store_value(src_val, Result, 0, arrind, i); + } } } else { // connect individual component of an aggregate type diff --git a/src/liboslexec/backendllvm.h b/src/liboslexec/backendllvm.h index 711b6b2bc..2fbc67acd 100644 --- a/src/liboslexec/backendllvm.h +++ b/src/liboslexec/backendllvm.h @@ -73,6 +73,8 @@ class BackendLLVM final : public OSOProcessorBase { typedef std::map AllocationMap; + void llvm_create_constant(const Symbol& sym); + void llvm_assign_initial_value(const Symbol& sym, bool force = false); llvm::LLVMContext& llvm_context() const { return ll.context(); } AllocationMap& named_values() { return m_named_values; } @@ -133,28 +135,12 @@ class BackendLLVM final : public OSOProcessorBase { return llvm_load_value(sym, deriv, NULL, component, cast); } - /// Convenience function to load a string for CPU or GPU device - llvm::Value* llvm_load_string(const Symbol& sym) - { - OSL_DASSERT(sym.typespec().is_string()); - return llvm_load_value(sym); - } - - /// Convenience function to load a constant string for CPU or GPU device. - /// On the GPU, we use the ustring hash, not the character pointer. - llvm::Value* llvm_load_string(ustring str) { return ll.constant(str); } - - llvm::Value* llvm_load_string(string_view str) - { - return llvm_load_string(ustring(str)); - } - - llvm::Value* llvm_load_stringhash(string_view str) + llvm::Value* llvm_const_hash(string_view str) { - return llvm_load_stringhash(ustring(str)); + return llvm_const_hash(ustring(str)); } - llvm::Value* llvm_load_stringhash(ustring str) + llvm::Value* llvm_const_hash(ustring str) { return ll.constant64((uint64_t)str.hash()); } @@ -238,7 +224,6 @@ class BackendLLVM final : public OSOProcessorBase { /// map, the symbol is alloca'd and placed in the map. llvm::Value* getOrAllocateLLVMSymbol(const Symbol& sym); -#if OSL_USE_OPTIX /// Return a globally unique (to the JIT module) name for symbol `sym`, /// assuming it's part of the currently examined layer of the group. std::string global_unique_symname(const Symbol& sym) @@ -253,21 +238,6 @@ class BackendLLVM final : public OSOProcessorBase { sym_name, group().name(), inst_->layername(), layer); } - /// Allocate a CUDA variable for the given OSL symbol and return a pointer - /// to the corresponding LLVM GlobalVariable, or return the pointer if it - /// has already been allocated. - llvm::Value* getOrAllocateCUDAVariable(const Symbol& sym); - - /// Create a named CUDA global variable with the given type, size, and - /// alignment, and add it to the current Module. It will be initialized - /// with data pointed to by init_data. A record will be also added to - /// m_const_map, and will be retrieved by subsequent calls to - /// getOrAllocateCUDAVariable(). - llvm::Value* addCUDAGlobalVariable(const std::string& name, int size, - int alignment, const void* init_data, - TypeDesc type = TypeDesc::UNKNOWN); -#endif - /// Retrieve an llvm::Value that is a pointer holding the start address /// of the specified symbol. This always works for globals and params; /// for stack variables (locals/temps) is succeeds only if the symbol is @@ -304,20 +274,14 @@ class BackendLLVM final : public OSOProcessorBase { /// Return the ShaderGlobals pointer. /// - llvm::Value* sg_ptr() const - { - return m_llvm_shaderglobals_ptr; - } + llvm::Value* sg_ptr() const { return m_llvm_shaderglobals_ptr; } llvm::Type* llvm_type_closure_component(); llvm::Type* llvm_type_closure_component_ptr(); /// Return the ShaderGlobals pointer cast as a void*. /// - llvm::Value* sg_void_ptr() - { - return ll.void_ptr(m_llvm_shaderglobals_ptr); - } + llvm::Value* sg_void_ptr() { return ll.void_ptr(m_llvm_shaderglobals_ptr); } /// Cast the pointer variable specified by val to a pointer to the /// basic type comprising `type`. @@ -343,10 +307,7 @@ class BackendLLVM final : public OSOProcessorBase { /// Return the group data pointer. /// - llvm::Value* groupdata_ptr() const - { - return m_llvm_groupdata_ptr; - } + llvm::Value* groupdata_ptr() const { return m_llvm_groupdata_ptr; } /// Return the group data pointer cast as a void*. /// @@ -364,22 +325,13 @@ class BackendLLVM final : public OSOProcessorBase { TypeDesc type = TypeDesc::UNKNOWN); /// Return the userdata base pointer. - llvm::Value* userdata_base_ptr() const - { - return m_llvm_userdata_base_ptr; - } + llvm::Value* userdata_base_ptr() const { return m_llvm_userdata_base_ptr; } /// Return the output base pointer. - llvm::Value* output_base_ptr() const - { - return m_llvm_output_base_ptr; - } + llvm::Value* output_base_ptr() const { return m_llvm_output_base_ptr; } /// Return the shade index - llvm::Value* shadeindex() const - { - return m_llvm_shadeindex; - } + llvm::Value* shadeindex() const { return m_llvm_shadeindex; } // For a symloc, compute the llvm::Value of the pointer to its true, // offset location from the base pointer for shade index `sindex` @@ -507,10 +459,7 @@ class BackendLLVM final : public OSOProcessorBase { /// Return the basic block of the exit for the whole instance. /// - bool llvm_has_exit_instance_block() const - { - return m_exit_instance_block; - } + bool llvm_has_exit_instance_block() const { return m_exit_instance_block; } /// Return the basic block of the exit for the whole instance. /// @@ -531,10 +480,7 @@ class BackendLLVM final : public OSOProcessorBase { /// Print debugging line for the op void llvm_generate_debug_op_printf(const Opcode& op); - llvm::Function* layer_func() const - { - return ll.current_function(); - } + llvm::Function* layer_func() const { return ll.current_function(); } /// Call this when JITing a texture-like call, to track how many. void generated_texture_call(bool handle) @@ -544,10 +490,7 @@ class BackendLLVM final : public OSOProcessorBase { shadingsys().m_stat_tex_calls_as_handles += 1; } - void increment_useparam_ops() - { - shadingsys().m_stat_useparam_ops++; - } + void increment_useparam_ops() { shadingsys().m_stat_useparam_ops++; } /// Return the mapping from symbol names to GlobalVariables. std::map& get_const_map() @@ -556,16 +499,10 @@ class BackendLLVM final : public OSOProcessorBase { } /// Return whether or not we are compiling for an OptiX-based renderer. - bool use_optix() - { - return m_use_optix; - } + bool use_optix() { return m_use_optix; } /// Return if we should compile against free function versions of Renderer Service. - bool use_rs_bitcode() - { - return m_use_rs_bitcode; - } + bool use_rs_bitcode() { return m_use_rs_bitcode; } /// Return the userdata index for the given Symbol. Return -1 if the Symbol /// is not an input parameter or is constant and therefore doesn't have an diff --git a/src/liboslexec/batched_backendllvm.cpp b/src/liboslexec/batched_backendllvm.cpp index de98c7303..e5e3bf2c2 100644 --- a/src/liboslexec/batched_backendllvm.cpp +++ b/src/liboslexec/batched_backendllvm.cpp @@ -1767,6 +1767,14 @@ BatchedBackendLLVM::llvm_call_function(const FuncSpec& name, valargs[i] = llvm_load_value(s, /*deriv*/ 0, /*component*/ 0, TypeDesc::UNKNOWN, function_is_uniform); + if (function_is_uniform && t.simpletype() == TypeDesc::STRING) { + // We are going to be calling a function from the scalar version + // of the OSL library. The scalar version has + // changed to use ustringhash_pod, but the wide version hasn't yet + // So we will need to extract the hash from the ustring here. + valargs[i] = ll.call_function("osl_gen_ustringhash_pod", + valargs[i]); + } } } diff --git a/src/liboslexec/batched_llvm_gen.cpp b/src/liboslexec/batched_llvm_gen.cpp index 3f6e12af6..ba421f305 100644 --- a/src/liboslexec/batched_llvm_gen.cpp +++ b/src/liboslexec/batched_llvm_gen.cpp @@ -471,11 +471,12 @@ LLVMGEN(llvm_gen_printf) call_args[new_format_slot] = llvm_new_format_string; // Construct the function name and call it. - FuncSpec func_spec(op.opname().c_str()); + const char* func_name = op.opname().c_str(); if ((op.opname() == op_format) && op_is_uniform) { - func_spec.unbatch(); + func_name = "format_uniform"; } + FuncSpec func_spec(func_name); if (op_is_uniform) { llvm::Value* ret = rop.ll.call_function(rop.build_name(func_spec), @@ -864,6 +865,16 @@ LLVMGEN(llvm_gen_generic) func_spec, &(args[1]), op.nargs() - 1, /*deriv_ptrs*/ false, uniformFormOfFunction, functionIsLlvmInlined, false /*ptrToReturnStructIs1stArg*/); + + if (uniformFormOfFunction + && Result.typespec().simpletype() == TypeDesc::STRING) { + // We did call a function from the scalar version + // of the OSL library. The scalar version has + // changed to use ustringhash_pod, but the wide version hasn't yet + // So we will need to extract the ustring from the resulting ustringhash_pod. + r = rop.ll.call_function("osl_gen_ustring", r); + } + // The store will deal with masking rop.llvm_store_value(r, Result); } else { @@ -4411,7 +4422,9 @@ llvm_batched_texture_options(BatchedBackendLLVM& rop, int opnum, val = rop.ll.constant(mode); \ } else { \ val = rop.llvm_load_value(Val); \ - val = rop.ll.call_function(#llvm_decoder, val); \ + llvm::Value* scalar_value_uh \ + = rop.ll.call_function("osl_gen_ustringhash_pod", val); \ + val = rop.ll.call_function(#llvm_decoder, scalar_value_uh); \ } \ fieldname = val; \ continue; \ @@ -4432,7 +4445,10 @@ llvm_batched_texture_options(BatchedBackendLLVM& rop, int opnum, val = rop.ll.constant(mode); } else { val = rop.llvm_load_value(Val); - val = rop.ll.call_function("osl_texture_decode_wrapmode", val); + llvm::Value* scalar_value_uh + = rop.ll.call_function("osl_gen_ustringhash_pod", val); + val = rop.ll.call_function("osl_texture_decode_wrapmode", + scalar_value_uh); } swrap = val; twrap = val; @@ -4734,10 +4750,14 @@ llvm_batched_texture_varying_options(BatchedBackendLLVM& rop, int opnum, = rop.llvm_load_value(Val, /*deriv=*/0, /*component=*/0, TypeDesc::UNKNOWN, /*op_is_uniform=*/false); - llvm::Value* scalar_value = rop.ll.op_extract(wide_wrap, leadLane); + llvm::Value* scalar_value_wrap = rop.ll.op_extract(wide_wrap, + leadLane); + llvm::Value* scalar_value_wrap_uh + = rop.ll.call_function("osl_gen_ustringhash_pod", + scalar_value_wrap); llvm::Value* wrap_code = rop.ll.call_function("osl_texture_decode_wrapmode", - scalar_value); + scalar_value_wrap_uh); rop.ll.op_unmasked_store(wrap_code, rop.ll.GEP(bto_type, bto, 0, static_cast( @@ -4753,20 +4773,26 @@ llvm_batched_texture_varying_options(BatchedBackendLLVM& rop, int opnum, rop.ll.GEP(bto_type, bto, 0, static_cast(LLVMMemberIndex::rwrap))); - remainingMask = rop.ll.op_lanes_that_match_masked(scalar_value, + remainingMask = rop.ll.op_lanes_that_match_masked(scalar_value_wrap, wide_wrap, remainingMask); continue; } +// We are going to be calling a function from the scalar version +// of the OSL library. The scalar version has +// changed to use ustringhash_pod, but the wide version hasn't yet +// So we will need to extract the hash from the ustring to pass as an argument. #define PARAM_VARYING_STRING_CODE(paramname, llvm_decoder, fieldname) \ if (name == Strings::paramname && valtype == TypeDesc::STRING) { \ llvm::Value* wide_value \ = rop.llvm_load_value(Val, /*deriv=*/0, /*component=*/0, \ TypeDesc::UNKNOWN, /*op_is_uniform=*/false); \ llvm::Value* scalar_value = rop.ll.op_extract(wide_value, leadLane); \ - llvm::Value* scalar_code = rop.ll.call_function(#llvm_decoder, \ - scalar_value); \ + llvm::Value* scalar_value_uh \ + = rop.ll.call_function("osl_gen_ustringhash_pod", scalar_value); \ + llvm::Value* scalar_code = rop.ll.call_function(#llvm_decoder, \ + scalar_value_uh); \ rop.ll.op_unmasked_store(scalar_code, \ rop.ll.GEP(bto_type, bto, 0, \ static_cast( \ @@ -6107,6 +6133,14 @@ LLVMGEN(llvm_gen_noise) nameVal = rop.llvm_load_value(*Name, /*deriv=*/0, /*component=*/0, /*cast=*/TypeDesc::UNKNOWN, name_is_uniform); + if (op_is_uniform) { + // We are going to be calling a function from the scalar version + // of the OSL library. The scalar version has + // changed to use ustringhash_pod, but the wide version hasn't yet + // So we will need to extract the hash from the ustring here. + nameVal = rop.ll.call_function("osl_gen_ustringhash_pod", nameVal); + } + // If we are binning the name, we will replace this // argument later in the binning code; args.push_back(nameVal); @@ -7047,6 +7081,15 @@ LLVMGEN(llvm_gen_spline) llvm::Value* splineNameVal = rop.llvm_load_value(Spline, /*deriv=*/0, /*component=*/0, TypeDesc::UNKNOWN, Spline.is_uniform()); + + if (op_is_uniform) { + // We are going to be calling a function from the scalar version + // of the OSL library in opspline.cpp. The scalar version has + // changed to use ustringhash_pod, but the wide version hasn't yet + // So we will need to extract the hash from the spline here. + splineNameVal = rop.ll.call_function("osl_gen_ustringhash_pod", + splineNameVal); + } args.push_back(Spline.is_uniform() ? splineNameVal : nullptr); args.push_back(rop.llvm_void_ptr(Value)); // make things easy @@ -8307,6 +8350,14 @@ LLVMGEN(llvm_gen_split) } args.push_back(rop.llvm_load_arg(Str, false /*derivs*/, op_is_uniform)); + if (op_is_uniform) { + // We are going to be calling a function from the scalar version + // of the OSL library. The scalar version has + // changed to use ustringhash_pod, but the wide version hasn't yet + // So we will need to extract the hash from the ustring here. + args.back() = rop.ll.call_function("osl_gen_ustringhash_pod", + args.back()); + } llvm::Value* temp_results_array = nullptr; if (op_is_uniform && !result_is_uniform) { @@ -8324,9 +8375,9 @@ LLVMGEN(llvm_gen_split) rop.llvm_load_arg(*optSep, false /*derivs*/, op_is_uniform)); } else { if (op_is_uniform) { - args.push_back(rop.ll.constant("")); + args.push_back(rop.ll.constant(ustring("").c_str())); } else { - llvm::Value* wide_sep = rop.ll.wide_constant(""); + llvm::Value* wide_sep = rop.ll.wide_constant(ustring("").c_str()); llvm::Value* temp_wide_sep = rop.getOrAllocateTemp( TypeSpec(TypeDesc::STRING), false /*derivs*/, false /*op_is_uniform*/, false /*forceBool*/, "wide separator"); @@ -8334,6 +8385,14 @@ LLVMGEN(llvm_gen_split) args.push_back(rop.ll.void_ptr(temp_wide_sep)); } } + if (op_is_uniform) { + // We are going to be calling a function from the scalar version + // of the OSL library. The scalar version has + // changed to use ustringhash_pod, but the wide version hasn't yet + // So we will need to extract the hash from the ustring here. + args.back() = rop.ll.call_function("osl_gen_ustringhash_pod", + args.back()); + } if (optMaxsplit) { OSL_DASSERT(optMaxsplit->typespec().is_int()); @@ -8365,23 +8424,35 @@ LLVMGEN(llvm_gen_split) func_spec.unbatch(); } llvm::Value* ret = rop.ll.call_function(rop.build_name(func_spec), args); - if (op_is_uniform && !result_is_uniform) { - ret = rop.ll.widen_value(ret); - - OSL_ASSERT(temp_results_array); + if (op_is_uniform) { + // We did call a function from the scalar version + // of the OSL library. The scalar version has + // changed to use ustringhash_pod, but the wide version hasn't yet + // So we will need to extract the ustring from any resulting ustringhash_pod. llvm::Type* elem_type = rop.ll.llvm_type( Results.typespec().elementtype().simpletype()); for (int ai = 0; ai < Results.typespec().arraylength(); ++ai) { - llvm::Value* elem_ptr = rop.ll.GEP(elem_type, temp_results_array, - ai); - llvm::Value* elem = rop.ll.op_load(elem_type, elem_ptr); - llvm::Value* wide_elem = rop.ll.widen_value(elem); - rop.llvm_store_value(wide_elem, Results, 0 /*deriv*/, - rop.ll.constant(ai) /*arrayindex*/, - 0 /* component*/); + llvm::Value* elem; + llvm::Value* array_index = rop.ll.constant(ai); + if (result_is_uniform) { + elem = rop.llvm_load_value(Results, 0 /*deriv*/, array_index, + 0 /* component*/); + elem = rop.ll.call_function("osl_gen_ustring", + rop.ll.ptr_to_int64_cast(elem)); + } else { + llvm::Value* elem_ptr = rop.ll.GEP(elem_type, + temp_results_array, ai); + elem = rop.ll.op_load(elem_type, elem_ptr); + elem = rop.ll.call_function("osl_gen_ustring", + rop.ll.ptr_to_int64_cast(elem)); + elem = rop.ll.widen_value(elem); + } + rop.llvm_store_value(elem, Results, 0 /*deriv*/, + array_index /*arrayindex*/, 0 /* component*/); + } + if (!result_is_uniform) { + ret = rop.ll.widen_value(ret); } - } - if (op_is_uniform) { rop.llvm_store_value(ret, R); } return true; diff --git a/src/liboslexec/builtindecl.h b/src/liboslexec/builtindecl.h index cedf6ef54..dfe50b34b 100644 --- a/src/liboslexec/builtindecl.h +++ b/src/liboslexec/builtindecl.h @@ -45,14 +45,14 @@ DECL(osl_##name##_dvdvdf, "xvvX") #define GENERIC_NOISE_DERIV_IMPL(name) \ - DECL(osl_##name##_dfdf, "xsXXXX") \ - DECL(osl_##name##_dfdfdf, "xsXXXXX") \ - DECL(osl_##name##_dfdv, "xsXXXX") \ - DECL(osl_##name##_dfdvdf, "xsXXXXX") \ - DECL(osl_##name##_dvdf, "xsXXXX") \ - DECL(osl_##name##_dvdfdf, "xsXXXXX") \ - DECL(osl_##name##_dvdv, "xsXXXX") \ - DECL(osl_##name##_dvdvdf, "xsXXXXX") + DECL(osl_##name##_dfdf, "xhXXXX") \ + DECL(osl_##name##_dfdfdf, "xhXXXXX") \ + DECL(osl_##name##_dfdv, "xhXXXX") \ + DECL(osl_##name##_dfdvdf, "xhXXXXX") \ + DECL(osl_##name##_dvdf, "xhXXXX") \ + DECL(osl_##name##_dvdfdf, "xhXXXXX") \ + DECL(osl_##name##_dvdv, "xhXXXX") \ + DECL(osl_##name##_dvdvdf, "xhXXXXX") #define PNOISE_IMPL(name) \ DECL(osl_##name##_fff, "fff") \ @@ -83,14 +83,14 @@ DECL(osl_##name##_dvdvdfvf, "xvvXvf") #define GENERIC_PNOISE_DERIV_IMPL(name) \ - DECL(osl_##name##_dfdff, "xsXXfXX") \ - DECL(osl_##name##_dfdfdfff, "xsXXXffXX") \ - DECL(osl_##name##_dfdvv, "xsXXvXX") \ - DECL(osl_##name##_dfdvdfvf, "xsXvXvfXX") \ - DECL(osl_##name##_dvdff, "xsvXfXX") \ - DECL(osl_##name##_dvdfdfff, "xsvXXffXX") \ - DECL(osl_##name##_dvdvv, "xsvvvXX") \ - DECL(osl_##name##_dvdvdfvf, "xsvvXvfXX") + DECL(osl_##name##_dfdff, "xhXXfXX") \ + DECL(osl_##name##_dfdfdfff, "xhXXXffXX") \ + DECL(osl_##name##_dfdvv, "xhXXvXX") \ + DECL(osl_##name##_dfdvdfvf, "xhXvXvfXX") \ + DECL(osl_##name##_dvdff, "xhvXfXX") \ + DECL(osl_##name##_dvdfdfff, "xhvXXffXX") \ + DECL(osl_##name##_dvdvv, "xhvvvXX") \ + DECL(osl_##name##_dvdvdfvf, "xhvvXvfXX") #define UNARY_OP_IMPL(name) \ DECL(osl_##name##_ff, "ff") \ @@ -132,20 +132,22 @@ DECL(osl_allocate_weighted_closure_component, "XXiiX") DECL(osl_closure_to_string, "sXX") DECL(osl_closure_to_ustringhash, "hXX") #endif -DECL(osl_format, "ss*") +DECL(osl_format, "hh*") DECL(osl_gen_ustringhash_pod, "hs") +DECL(osl_gen_ustring, "sh") DECL(osl_gen_printfmt, "xXhiXiX") DECL(osl_gen_filefmt, "xXhhiXiX") DECL(osl_gen_errorfmt, "xXhiXiX") DECL(osl_gen_warningfmt, "xXhiXiX") -DECL(osl_split, "isXsii") +DECL(osl_formatfmt, "hXhiXiX") +DECL(osl_split, "ihXhii") DECL(osl_incr_layers_executed, "xX") // For legacy printf support -DECL(osl_printf, "xXs*") -DECL(osl_fprintf, "xXss*") -DECL(osl_error, "xXs*") -DECL(osl_warning, "xXs*") +DECL(osl_printf, "xXh*") +DECL(osl_fprintf, "xXhh*") +DECL(osl_error, "xXh*") +DECL(osl_warning, "xXh*") NOISE_IMPL(cellnoise) //NOISE_DERIV_IMPL(cellnoise) @@ -185,55 +187,55 @@ DECL(osl_hash_iff, "iff") DECL(osl_hash_iv, "iX") DECL(osl_hash_ivf, "iXf") -DECL(osl_spline_fff, "xXXXXii") -DECL(osl_spline_dfdfdf, "xXXXXii") -DECL(osl_spline_dfdff, "xXXXXii") -DECL(osl_spline_dffdf, "xXXXXii") -DECL(osl_spline_vfv, "xXXXXii") -DECL(osl_spline_dvdfdv, "xXXXXii") -DECL(osl_spline_dvdfv, "xXXXXii") -DECL(osl_spline_dvfdv, "xXXXXii") -DECL(osl_splineinverse_fff, "xXXXXii") -DECL(osl_splineinverse_dfdfdf, "xXXXXii") -DECL(osl_splineinverse_dfdff, "xXXXXii") -DECL(osl_splineinverse_dffdf, "xXXXXii") -DECL(osl_setmessage, "xXsLXisi") -DECL(osl_getmessage, "iXssLXiisi") -DECL(osl_pointcloud_search, "iXsXfiiXXii*") -DECL(osl_pointcloud_get, "iXsXisLX") -DECL(osl_pointcloud_write, "iXsXiXXX") -DECL(osl_pointcloud_write_helper, "xXXXisLX") +DECL(osl_spline_fff, "xXhXXii") +DECL(osl_spline_dfdfdf, "xXhXXii") +DECL(osl_spline_dfdff, "xXhXXii") +DECL(osl_spline_dffdf, "xXhXXii") +DECL(osl_spline_vfv, "xXhXXii") +DECL(osl_spline_dvdfdv, "xXhXXii") +DECL(osl_spline_dvdfv, "xXhXXii") +DECL(osl_spline_dvfdv, "xXhXXii") +DECL(osl_splineinverse_fff, "xXhXXii") +DECL(osl_splineinverse_dfdfdf, "xXhXXii") +DECL(osl_splineinverse_dfdff, "xXhXXii") +DECL(osl_splineinverse_dffdf, "xXhXXii") +DECL(osl_setmessage, "xXhLXihi") +DECL(osl_getmessage, "iXhhLXiihi") +DECL(osl_pointcloud_search, "iXhXfiiXXii*") +DECL(osl_pointcloud_get, "iXhXihLX") +DECL(osl_pointcloud_write, "iXhXiXXX") +DECL(osl_pointcloud_write_helper, "xXXXihLX") DECL(osl_blackbody_vf, "xXXf") DECL(osl_wavelength_color_vf, "xXXf") DECL(osl_luminance_fv, "xXXX") DECL(osl_luminance_dfdv, "xXXX") -DECL(osl_prepend_color_from, "xXXs") -DECL(osl_prepend_matrix_from, "iXXs") -DECL(osl_get_matrix, "iXXs") -DECL(osl_get_inverse_matrix, "iXXs") -DECL(osl_transform_triple, "iXXiXiXXi") -DECL(osl_transform_triple_nonlinear, "iXXiXiXXi") +DECL(osl_prepend_color_from, "xXXh") +DECL(osl_prepend_matrix_from, "iXXh") +DECL(osl_get_matrix, "iXXh") +DECL(osl_get_inverse_matrix, "iXXh") +DECL(osl_transform_triple, "iXXiXihhi") +DECL(osl_transform_triple_nonlinear, "iXXiXihhi") DECL(osl_transform_vmv, "xXXX") DECL(osl_transform_dvmdv, "xXXX") DECL(osl_transformv_vmv, "xXXX") DECL(osl_transformv_dvmdv, "xXXX") DECL(osl_transformn_vmv, "xXXX") DECL(osl_transformn_dvmdv, "xXXX") -DECL(osl_transformc, "iXXiXiXX") +DECL(osl_transformc, "iXXiXihh") -DECL(osl_dict_find_iis, "iXiX") -DECL(osl_dict_find_iss, "iXXX") +DECL(osl_dict_find_iis, "iXih") +DECL(osl_dict_find_iss, "iXhh") DECL(osl_dict_next, "iXi") -DECL(osl_dict_value, "iXiXLX") -DECL(osl_raytype_name, "iXs") +DECL(osl_dict_value, "iXihLX") +DECL(osl_raytype_name, "iXh") #ifdef OSL_LLVM_NO_BITCODE DECL(osl_range_check, "iiihXhihihh") #endif DECL(osl_range_check_err, "iiihXhihihh") DECL(osl_naninf_check, "xiXiXhihiih") DECL(osl_uninit_check, "xLXXhihihhihihii") -DECL(osl_get_attribute, "iXissiiLX") -DECL(osl_bind_interpolated_param, "iXsLiXiXiXi") +DECL(osl_get_attribute, "iXihhiiLX") +DECL(osl_bind_interpolated_param, "iXhLiXiXiXi") DECL(osl_get_texture_options, "XX"); DECL(osl_get_noise_options, "XX"); DECL(osl_get_trace_options, "XX"); @@ -350,30 +352,30 @@ DECL(osl_div_mmm, "xXXX") DECL(osl_div_mmf, "xXXf") DECL(osl_div_mfm, "xXfX") -DECL(osl_get_from_to_matrix, "iXXss") +DECL(osl_get_from_to_matrix, "iXXhh") DECL(osl_transpose_mm, "xXX") DECL(osl_determinant_fm, "fX") -DECL(osl_concat_sss, "sss") -DECL(osl_strlen_is, "is") -DECL(osl_hash_is, "is") -DECL(osl_getchar_isi, "isi"); -DECL(osl_startswith_iss, "iss") -DECL(osl_endswith_iss, "iss") -DECL(osl_stoi_is, "is") -DECL(osl_stof_fs, "fs") -DECL(osl_substr_ssii, "ssii") -DECL(osl_regex_impl, "iXsXisi") +DECL(osl_concat_sss, "hhh") +DECL(osl_strlen_is, "ih") +DECL(osl_hash_is, "ih") +DECL(osl_getchar_isi, "ihi"); +DECL(osl_startswith_iss, "ihh") +DECL(osl_endswith_iss, "ihh") +DECL(osl_stoi_is, "ih") +DECL(osl_stof_fs, "fh") +DECL(osl_substr_ssii, "hhii") +DECL(osl_regex_impl, "iXhXihi") // Used by wide code generator, but are uniform calls -DECL(osl_texture_decode_wrapmode, "is"); -DECL(osl_texture_decode_interpmode, "is"); +DECL(osl_texture_decode_wrapmode, "ih"); +DECL(osl_texture_decode_interpmode, "ih"); DECL(osl_texture_set_firstchannel, "xXi") -DECL(osl_texture_set_swrap, "xXs") -DECL(osl_texture_set_twrap, "xXs") -DECL(osl_texture_set_rwrap, "xXs") -DECL(osl_texture_set_stwrap, "xXs") +DECL(osl_texture_set_swrap, "xXh") +DECL(osl_texture_set_twrap, "xXh") +DECL(osl_texture_set_rwrap, "xXh") +DECL(osl_texture_set_stwrap, "xXh") DECL(osl_texture_set_swrap_code, "xXi") DECL(osl_texture_set_twrap_code, "xXi") DECL(osl_texture_set_rwrap_code, "xXi") @@ -388,22 +390,22 @@ DECL(osl_texture_set_rwidth, "xXf") DECL(osl_texture_set_stwidth, "xXf") DECL(osl_texture_set_fill, "xXf") DECL(osl_texture_set_time, "xXf") -DECL(osl_texture_set_interp, "xXs") +DECL(osl_texture_set_interp, "xXh") DECL(osl_texture_set_interp_code, "xXi") DECL(osl_texture_set_subimage, "xXi") -DECL(osl_texture_set_subimagename, "xXs") +DECL(osl_texture_set_subimagename, "xXh") DECL(osl_texture_set_missingcolor_arena, "xXX") DECL(osl_texture_set_missingcolor_alpha, "xXif") -DECL(osl_texture, "iXXXXffffffiXXXXXXX") -DECL(osl_texture3d, "iXXXXXXXXiXXXXXXX") -DECL(osl_environment, "iXXXXXXXiXXXXXXX") -DECL(osl_get_textureinfo, "iXXXXiiiXX") -DECL(osl_get_textureinfo_st, "iXXXffXiiiXX") +DECL(osl_texture, "iXhXXffffffiXXXXXXX") +DECL(osl_texture3d, "iXhXXXXXXiXXXXXXX") +DECL(osl_environment, "iXhXXXXXiXXXXXXX") +DECL(osl_get_textureinfo, "iXhXhiiiXX") +DECL(osl_get_textureinfo_st, "iXhXffhiiiXX") DECL(osl_trace_set_mindist, "xXf") DECL(osl_trace_set_maxdist, "xXf") DECL(osl_trace_set_shade, "xXi") -DECL(osl_trace_set_traceset, "xXs") +DECL(osl_trace_set_traceset, "xXh") DECL(osl_trace, "iXXXXXXXX") #ifdef OSL_LLVM_NO_BITCODE diff --git a/src/liboslexec/builtindecl_wide_xmacro.h b/src/liboslexec/builtindecl_wide_xmacro.h index 3e2484bbe..37171c0b1 100644 --- a/src/liboslexec/builtindecl_wide_xmacro.h +++ b/src/liboslexec/builtindecl_wide_xmacro.h @@ -176,6 +176,7 @@ DECL(__OSL_MASKED_OP(mul_closure_color), "xXXXXi") DECL(__OSL_OP(closure_to_string), "sXX") DECL(__OSL_OP(format), "xXis*") +DECL(__OSL_OP(format_uniform), "ss*") DECL(__OSL_OP(printf), "xXis*") DECL(__OSL_OP(error), "xXis*") DECL(__OSL_OP(warning), "xXis*") @@ -349,16 +350,16 @@ DECL(__OSL_MASKED_OP3(build_transform_matrix, Wm, Ws, s), "iXXXXi") DECL(__OSL_MASKED_OP3(build_transform_matrix, Wm, s, Ws), "iXXXXi") DECL(__OSL_MASKED_OP3(build_transform_matrix, Wm, Ws, Ws), "iXXXXi") -DECL(__OSL_OP(dict_find_iis), "iXiX") +DECL(__OSL_OP(dict_find_iis), "iXis") DECL(__OSL_MASKED_OP3(dict_find, Wi, Wi, Ws), "xXXXXi") -DECL(__OSL_OP(dict_find_iss), "iXXX") +DECL(__OSL_OP(dict_find_iss), "iXss") DECL(__OSL_MASKED_OP3(dict_find, Wi, Ws, Ws), "xXXXXi") DECL(__OSL_OP(dict_next), "iXi") DECL(__OSL_MASKED_OP(dict_next), "xXXXi") -DECL(__OSL_OP(dict_value), "iXiXLX") +DECL(__OSL_OP(dict_value), "iXisLX") DECL(__OSL_MASKED_OP(dict_value), "xXXXXLXi") @@ -519,8 +520,8 @@ DECL(__OSL_MASKED_OP3(transform_normal, Wdv, Wdv, Wm), "xXXXii") DECL(__OSL_MASKED_OP3(transform_normal, Wv, Wv, m), "xXXXii") DECL(__OSL_MASKED_OP3(transform_normal, Wdv, Wdv, m), "xXXXii") -DECL(__OSL_MASKED_OP3(transform_color, Wv, s, s), "xXXiXiXXi") -DECL(__OSL_OP3(transform_color, v, s, s), "xXXiXiXX") +DECL(__OSL_MASKED_OP3(transform_color, Wv, s, s), "xXXiXissi") +DECL(__OSL_OP3(transform_color, v, s, s), "xXXiXiss") DECL(__OSL_OP3(dot, Wf, Wv, Wv), "xXXX") DECL(__OSL_MASKED_OP3(dot, Wf, Wv, Wv), "xXXXi") @@ -616,12 +617,12 @@ DECL(__OSL_OP(regex_impl), "iXsXisi") // BATCH texturing manages the BatchedTextureOptions // directly in LLVM ir, and has no need for wide versions // of osl_texture_set_XXX functions -DECL(__OSL_MASKED_OP(texture), "iXXXXXXXXXXiXiXiXi") -DECL(__OSL_MASKED_OP(texture3d), "iXXXXXXXXiXiXiXi") -DECL(__OSL_MASKED_OP(environment), "iXXXXXXXiXiXiXi") +DECL(__OSL_MASKED_OP(texture), "iXsXXXXXXXXiXiXiXi") +DECL(__OSL_MASKED_OP(texture3d), "iXsXXXXXXiXiXiXi") +DECL(__OSL_MASKED_OP(environment), "iXsXXXXXiXiXiXi") DECL(__OSL_OP(resolve_udim_uniform), "XXXXff") DECL(__OSL_MASKED_OP(resolve_udim), "xXXXXXXi") -DECL(__OSL_OP(get_textureinfo_uniform), "iXXXXXX") +DECL(__OSL_OP(get_textureinfo_uniform), "iXsXsXX") // Wide Code generator will set trace options directly in LLVM IR // without calling helper functions diff --git a/src/liboslexec/closure.cpp b/src/liboslexec/closure.cpp index 37ef073ee..e511ae218 100644 --- a/src/liboslexec/closure.cpp +++ b/src/liboslexec/closure.cpp @@ -40,7 +40,7 @@ namespace pvt { static void print_component_value(std::ostream& out, ShadingSystemImpl* ss, TypeDesc type, - const void* data) + const void* data, bool treat_ustrings_as_hash) { if (type == TypeDesc::TypeInt) @@ -53,17 +53,23 @@ print_component_value(std::ostream& out, ShadingSystemImpl* ss, TypeDesc type, else if (type == TypeDesc::TypeVector) out << "(" << ((Vec3*)data)->x << ", " << ((Vec3*)data)->y << ", " << ((Vec3*)data)->z << ")"; - else if (type == TypeDesc::TypeString) - out << "\"" << *((ustring*)data) << "\""; - else if (type == TypeDesc::PTR) // this only happens for closures - print_closure(out, *(const ClosureColor**)data, ss); + else if (type == TypeDesc::TypeString) { + if (treat_ustrings_as_hash == true) { + out << "\"" << *((ustringhash*)data) << "\""; + } else { + out << "\"" << *((ustring*)data) << "\""; + } + } else if (type == TypeDesc::PTR) // this only happens for closures + print_closure(out, *(const ClosureColor**)data, ss, + treat_ustrings_as_hash); } static void print_component(std::ostream& out, const ClosureComponent* comp, - ShadingSystemImpl* ss, const Color3& weight) + ShadingSystemImpl* ss, const Color3& weight, + bool& treat_ustrings_as_hash) { const ClosureRegistry::ClosureEntry* clentry = ss->find_closure(comp->id); OSL_ASSERT(clentry); @@ -83,7 +89,8 @@ print_component(std::ostream& out, const ClosureComponent* comp, out << ", "; print_component_value(out, ss, param.type.elementtype(), (const char*)comp->data() + param.offset - + param.type.elementsize() * j); + + param.type.elementsize() * j, + treat_ustrings_as_hash); } if (clentry->params[i].type.numelements() > 1) out << "]"; @@ -95,7 +102,8 @@ print_component(std::ostream& out, const ClosureComponent* comp, static void print_closure(std::ostream& out, const ClosureColor* closure, - ShadingSystemImpl* ss, const Color3& w, bool& first) + ShadingSystemImpl* ss, const Color3& w, bool& first, + bool& treat_ustrings_as_hash) { if (closure == NULL) return; @@ -103,16 +111,19 @@ print_closure(std::ostream& out, const ClosureColor* closure, switch (closure->id) { case ClosureColor::MUL: print_closure(out, closure->as_mul()->closure, ss, - closure->as_mul()->weight * w, first); + closure->as_mul()->weight * w, first, + treat_ustrings_as_hash); break; case ClosureColor::ADD: - print_closure(out, closure->as_add()->closureA, ss, w, first); - print_closure(out, closure->as_add()->closureB, ss, w, first); + print_closure(out, closure->as_add()->closureA, ss, w, first, + treat_ustrings_as_hash); + print_closure(out, closure->as_add()->closureB, ss, w, first, + treat_ustrings_as_hash); break; default: if (!first) out << "\n\t+ "; - print_component(out, closure->as_comp(), ss, w); + print_component(out, closure->as_comp(), ss, w, treat_ustrings_as_hash); first = false; break; } @@ -122,10 +133,11 @@ print_closure(std::ostream& out, const ClosureColor* closure, void print_closure(std::ostream& out, const ClosureColor* closure, - ShadingSystemImpl* ss) + ShadingSystemImpl* ss, bool treat_ustrings_as_hash) { bool first = true; - print_closure(out, closure, ss, Color3(1, 1, 1), first); + print_closure(out, closure, ss, Color3(1, 1, 1), first, + treat_ustrings_as_hash); } diff --git a/src/liboslexec/constfold.cpp b/src/liboslexec/constfold.cpp index 87bfb9651..d8e218c09 100644 --- a/src/liboslexec/constfold.cpp +++ b/src/liboslexec/constfold.cpp @@ -2418,6 +2418,13 @@ DECLFOLDER(constfold_gettextureinfo) filename, nullptr, rop.shadingcontext()->texture_thread_info(), rop.shaderglobals(), 0 /* TODO: subimage? */, dataname, t, mydata, &em); + // Results from RendererServices for TypeDesc::STRING will actaully be a ustringhash + // as that is what we expect during execution. We will need to convert it back to + // a regular ustring before continuing since this is the compile/optimization phase. + if (result && t == TypeDesc::STRING) { + auto uh_mydata = reinterpret_cast(mydata)[0]; + reinterpret_cast(mydata)[0] = ustring_from(uh_mydata); + } ustring errormessage = ustring_from(em); // Now we turn // gettextureinfo result filename dataname data @@ -2793,6 +2800,12 @@ DECLFOLDER(constfold_pointcloud_get) "Folded constant pointcloud_get"); // Now make a constant array for those results we just retrieved... + if (valtype == TypeDesc::STRING) { + // Renderer services treat strings as ustringhash, + // so we need to convert it back to ustring before continuing + auto uh_data = reinterpret_cast(data.data())[0]; + reinterpret_cast(data.data())[0] = ustring_from(uh_data); + } int const_array_sym = rop.add_constant(valtype, &data[0]); // ... and add an instruction to copy the constant into the // original destination for the query. diff --git a/src/liboslexec/dictionary.cpp b/src/liboslexec/dictionary.cpp index 2d719d31b..9762819e3 100644 --- a/src/liboslexec/dictionary.cpp +++ b/src/liboslexec/dictionary.cpp @@ -62,7 +62,8 @@ class Dictionary { int dict_find(ExecContextPtr ec, ustring dictionaryname, ustring query); int dict_find(ExecContextPtr ec, int nodeID, ustring query); int dict_next(int nodeID); - int dict_value(int nodeID, ustring attribname, TypeDesc type, void* data); + int dict_value(int nodeID, ustring attribname, TypeDesc type, void* data, + bool treat_ustrings_as_hash); private: // We cache individual queries with a key that is a tuple of the @@ -307,7 +308,7 @@ Dictionary::dict_next(int nodeID) int Dictionary::dict_value(int nodeID, ustring attribname, TypeDesc type, - void* data) + void* data, bool treat_ustrings_as_hash) { if (nodeID <= 0 || nodeID >= (int)m_nodes.size()) return 0; // invalid node ID @@ -321,7 +322,11 @@ Dictionary::dict_value(int nodeID, ustring attribname, TypeDesc type, int n = type.numelements() * type.aggregate; if (type.basetype == TypeDesc::STRING) { OSL_DASSERT(n == 1 && "no string arrays in XML"); - ((ustring*)data)[0] = m_stringdata[offset]; + if (treat_ustrings_as_hash == true) { + ((ustringhash_pod*)data)[0] = m_stringdata[offset].hash(); + } else { + ((ustring*)data)[0] = m_stringdata[offset]; + } return 1; } if (type.basetype == TypeDesc::INT) { @@ -360,8 +365,12 @@ Dictionary::dict_value(int nodeID, ustring attribname, TypeDesc type, r.valueoffset = (int)m_stringdata.size(); ustring s(val); m_stringdata.push_back(s); - ((ustring*)data)[0] = s; - m_cache[q] = r; + if (treat_ustrings_as_hash == true) { + ((ustringhash_pod*)data)[0] = s.hash(); + } else { + ((ustring*)data)[0] = s; + } + m_cache[q] = r; return 1; } if (type.basetype == TypeDesc::INT) { @@ -435,11 +444,12 @@ ShadingContext::dict_next(int nodeID) int ShadingContext::dict_value(int nodeID, ustring attribname, TypeDesc type, - void* data) + void* data, bool treat_ustrings_as_hash) { if (!m_dictionary) return 0; - return m_dictionary->dict_value(nodeID, attribname, type, data); + return m_dictionary->dict_value(nodeID, attribname, type, data, + treat_ustrings_as_hash); } @@ -453,19 +463,24 @@ ShadingContext::free_dict_resources() OSL_SHADEOP int -osl_dict_find_iis(OpaqueExecContextPtr oec, int nodeID, void* query) +osl_dict_find_iis(OpaqueExecContextPtr oec, int nodeID, ustringhash_pod query_) { - auto ec = pvt::get_ec(oec); - return ec->context->dict_find(ec, nodeID, USTR(query)); + auto ec = pvt::get_ec(oec); + auto query = ustringhash_from(query_); + return ec->context->dict_find(ec, nodeID, ustring_from(query)); } OSL_SHADEOP int -osl_dict_find_iss(OpaqueExecContextPtr oec, void* dictionary, void* query) +osl_dict_find_iss(OpaqueExecContextPtr oec, ustringhash_pod dictionary_, + ustringhash_pod query_) { - auto ec = pvt::get_ec(oec); - return ec->context->dict_find(ec, USTR(dictionary), USTR(query)); + auto dictionary = ustringhash_from(dictionary_); + auto query = ustringhash_from(query_); + auto ec = pvt::get_ec(oec); + return ec->context->dict_find(ec, ustring_from(dictionary), + ustring_from(query)); } @@ -480,12 +495,13 @@ osl_dict_next(OpaqueExecContextPtr oec, int nodeID) OSL_SHADEOP int -osl_dict_value(OpaqueExecContextPtr oec, int nodeID, void* attribname, - long long type, void* data) +osl_dict_value(OpaqueExecContextPtr oec, int nodeID, + ustringhash_pod attribname_, long long type, void* data) { - auto ec = pvt::get_ec(oec); - return ec->context->dict_value(nodeID, USTR(attribname), TYPEDESC(type), - data); + auto ec = pvt::get_ec(oec); + auto attribname = ustringhash_from(attribname_); + return ec->context->dict_value(nodeID, ustring_from(attribname), + TYPEDESC(type), data, true); } diff --git a/src/liboslexec/llvm_gen.cpp b/src/liboslexec/llvm_gen.cpp index c422140bc..accf0445a 100644 --- a/src/liboslexec/llvm_gen.cpp +++ b/src/liboslexec/llvm_gen.cpp @@ -85,7 +85,7 @@ BackendLLVM::llvm_gen_debug_printf(string_view message) inst()->layername(), message); llvm::Value* valargs[] = { sg_void_ptr(), - llvm_load_stringhash(s), + llvm_const_hash(s), ll.constant(0) /*arg_count*/, ll.void_ptr_null() /*arg_types*/, ll.constant(0) /*arg_values_size*/, @@ -103,7 +103,7 @@ BackendLLVM::llvm_gen_warning(string_view message) // passing arguments. ustring s = ustring::fmtformat("{}\n", message); llvm::Value* valargs[] = { sg_void_ptr(), - llvm_load_stringhash(s), + llvm_const_hash(s), ll.constant(0) /*arg_count*/, ll.void_ptr_null() /*arg_types*/, ll.constant(0) /*arg_values_size*/, @@ -120,7 +120,7 @@ BackendLLVM::llvm_gen_error(string_view message) // passing arguments. ustring s = ustring::fmtformat("{}\n", message); llvm::Value* valargs[] = { sg_void_ptr(), - llvm_load_stringhash(s), + llvm_const_hash(s), ll.constant(0) /*arg_count*/, ll.void_ptr_null() /*arg_types*/, ll.constant(0) /*arg_values_size*/, @@ -434,7 +434,7 @@ LLVMGEN(llvm_gen_printf_legacy) // (where args_size is the size of arg0 + arg1 + arg2...) // // Make sure host has the format string so it can print it - call_args[new_format_slot] = rop.llvm_load_string(s); + call_args[new_format_slot] = rop.llvm_const_hash(s); size_t nargs = call_args.size() - (new_format_slot + 1); // Allocate space to store the arguments to osl_printf(). // Don't forget to pad a little extra to hold the size of the arguments itself. @@ -464,14 +464,16 @@ LLVMGEN(llvm_gen_printf_legacy) } llvm::Value* memptr = rop.ll.offset_ptr(voids, optix_size); if (arg->getType()->isIntegerTy()) { - llvm::Value* iptr = rop.ll.ptr_cast(memptr, - rop.ll.type_int_ptr()); - rop.ll.op_store(arg, iptr); + llvm::Type* ptr_type = nullptr; if (arg->getType()->isIntegerTy(64)) { optix_size += sizeof(uint64_t); + ptr_type = rop.ll.type_int64_ptr(); } else { optix_size += sizeof(int); + ptr_type = rop.ll.type_int_ptr(); } + llvm::Value* iptr = rop.ll.ptr_cast(memptr, ptr_type); + rop.ll.op_store(arg, iptr); } else if (arg->getType()->isFloatingPointTy()) { llvm::Value* fptr = rop.ll.ptr_cast(memptr, rop.ll.type_double_ptr()); @@ -489,7 +491,7 @@ LLVMGEN(llvm_gen_printf_legacy) } else #endif { - call_args[new_format_slot] = rop.llvm_load_string(s); + call_args[new_format_slot] = rop.llvm_const_hash(s); } // Construct the function name and call it. @@ -507,12 +509,6 @@ LLVMGEN(llvm_gen_print_fmt) { Opcode& op(rop.inst()->ops()[opnum]); - // The format op is currently handled by llvm_gen_printf_legacy, - // but could be moved here in future - // NOTE: format would not a callthrough to renderservices, - // but should be handled in opstring.cpp - OSL_ASSERT(op.opname() != op_format); - // Prepare the args for the call // Which argument is the format string? Usually 0, but for op @@ -535,8 +531,7 @@ LLVMGEN(llvm_gen_print_fmt) if (op.opname() == op_fprintf) { Symbol& Filename = *rop.opargsym(op, 0); ustring filename_ustring = Filename.get_string(); - call_args.push_back( - rop.llvm_load_stringhash(filename_ustring)); //filename + call_args.push_back(rop.llvm_const_hash(filename_ustring)); //filename } // We're going to need to adjust the format string as we go, but I'd @@ -647,14 +642,18 @@ LLVMGEN(llvm_gen_print_fmt) myformat += ourformat; myformat += "}"; + TypeDesc symty = sym.typespec().simpletype(); + TypeDesc basetype = TypeDesc::BASETYPE(symty.basetype); // NOTE(boulos): Only for debug mode do the derivatives get printed... for (int a = 0; a < num_elements; ++a) { - llvm::Value* arrind = simpletype.arraylen ? rop.ll.constant(a) - : NULL; + llvm::Value* const_arrind = simpletype.arraylen + ? rop.ll.constant(a) + : NULL; if (sym.typespec().is_closure_based()) { s += myformat; - llvm::Value* v = rop.llvm_load_value(sym, 0, arrind, 0); + llvm::Value* v = rop.llvm_load_value(sym, 0, const_arrind, + 0); v = rop.ll.call_function("osl_closure_to_ustringhash", rop.sg_void_ptr(), v); encodedtypes.push_back(et); @@ -668,28 +667,21 @@ LLVMGEN(llvm_gen_print_fmt) s += " "; s += myformat; - llvm::Value* loaded; - if (sym.typespec().is_string_based()) { - if (rop.ll.ustring_rep() - == LLVM_Util::UstringRep::hash) { - loaded = rop.llvm_load_value(sym, 0, arrind, c); - // The value loaded is already a hash, but masquarading as a const char * - // Just need to cast it to the correct type. - loaded = rop.ll.ptr_cast(loaded, - rop.ll.type_int64()); - } else { - if (sym.is_constant() - && !sym.typespec().is_array()) { - loaded = rop.llvm_load_stringhash( - sym.get_string()); - } else { - loaded = rop.llvm_load_value(sym, 0, arrind, c); - loaded = rop.ll.call_function( - "osl_gen_ustringhash_pod", loaded); - } - } - } else { - loaded = rop.llvm_load_value(sym, 0, arrind, c); + // TODO: Add llvm_load_value that does this check + // internally to reduce bloat and chance of missing it + llvm::Value* loaded + = sym.is_constant() + ? rop.llvm_load_constant_value(sym, a, c, + basetype) + : rop.llvm_load_value(sym, 0, const_arrind, c, + basetype); + + if (sym.typespec().is_string_based() + && (rop.ll.ustring_rep() + == LLVM_Util::UstringRep::charptr)) { + // Don't think this will need to be here soon + loaded = rop.ll.call_function("osl_gen_ustringhash_pod", + loaded); } encodedtypes.push_back(et); @@ -717,7 +709,7 @@ LLVMGEN(llvm_gen_print_fmt) rop.inst()->shadername(), s); } ustring s_ustring(s.c_str()); - call_args.push_back(rop.llvm_load_stringhash(s_ustring)); + call_args.push_back(rop.llvm_const_hash(s_ustring)); OSL_ASSERT(encodedtypes.size() == loaded_arg_values.size()); int arg_count = static_cast(encodedtypes.size()); @@ -786,7 +778,15 @@ LLVMGEN(llvm_gen_print_fmt) if (op.opname() == op_fprintf) rs_func_name = "osl_gen_filefmt"; - rop.ll.call_function(rs_func_name, call_args); + // NOTE: format creates a new ustring, so only works on host + if (op.opname() == op_format) + rs_func_name = "osl_formatfmt"; + + llvm::Value* ret = rop.ll.call_function(rs_func_name, call_args); + + // The format op returns a string value, put in in the right spot + if (op.opname() == op_format) + rop.llvm_store_value(ret, *rop.opargsym(op, 0)); return true; } @@ -794,8 +794,7 @@ LLVMGEN(llvm_gen_print_fmt) LLVMGEN(llvm_gen_printf) { - Opcode& op(rop.inst()->ops()[opnum]); - if ((op.opname() == "format" || rop.use_optix())) + if (rop.use_optix()) return llvm_gen_printf_legacy(rop, opnum); else return llvm_gen_print_fmt(rop, opnum); @@ -1107,7 +1106,7 @@ LLVMGEN(llvm_gen_modulus) if (!a || !b) return false; llvm::Value* r; - if (B.is_constant() && !rop.is_zero(B)) + if (!rop.use_optix() && B.is_constant() && !rop.is_zero(B)) r = rop.ll.op_mod(a, b); else r = rop.ll.call_function(safe_mod, a, b); @@ -1502,14 +1501,14 @@ LLVMGEN(llvm_gen_compref) llvm::Value* args[] = { c, rop.ll.constant(3), - rop.llvm_load_stringhash(Val.unmangled()), + rop.llvm_const_hash(Val.unmangled()), rop.sg_void_ptr(), - rop.llvm_load_stringhash(op.sourcefile()), + rop.llvm_const_hash(op.sourcefile()), rop.ll.constant(op.sourceline()), - rop.llvm_load_stringhash(rop.group().name()), + rop.llvm_const_hash(rop.group().name()), rop.ll.constant(rop.layer()), - rop.llvm_load_stringhash(rop.inst()->layername()), - rop.llvm_load_stringhash(rop.inst()->shadername()) }; + rop.llvm_const_hash(rop.inst()->layername()), + rop.llvm_const_hash(rop.inst()->shadername()) }; c = rop.ll.call_function("osl_range_check", args); } } @@ -1547,14 +1546,14 @@ LLVMGEN(llvm_gen_compassign) llvm::Value* args[] = { c, rop.ll.constant(3), - rop.llvm_load_stringhash(Result.unmangled()), + rop.llvm_const_hash(Result.unmangled()), rop.sg_void_ptr(), - rop.llvm_load_stringhash(op.sourcefile()), + rop.llvm_const_hash(op.sourcefile()), rop.ll.constant(op.sourceline()), - rop.llvm_load_stringhash(rop.group().name()), + rop.llvm_const_hash(rop.group().name()), rop.ll.constant(rop.layer()), - rop.llvm_load_stringhash(rop.inst()->layername()), - rop.llvm_load_stringhash(rop.inst()->shadername()) }; + rop.llvm_const_hash(rop.inst()->layername()), + rop.llvm_const_hash(rop.inst()->shadername()) }; c = rop.ll.call_function("osl_range_check", args); } } @@ -1594,14 +1593,14 @@ LLVMGEN(llvm_gen_mxcompref) llvm::Value* args[] = { row, rop.ll.constant(4), - rop.llvm_load_stringhash(M.name()), + rop.llvm_const_hash(M.name()), rop.sg_void_ptr(), - rop.llvm_load_stringhash(op.sourcefile()), + rop.llvm_const_hash(op.sourcefile()), rop.ll.constant(op.sourceline()), - rop.llvm_load_stringhash(rop.group().name()), + rop.llvm_const_hash(rop.group().name()), rop.ll.constant(rop.layer()), - rop.llvm_load_stringhash(rop.inst()->layername()), - rop.llvm_load_stringhash(rop.inst()->shadername()) }; + rop.llvm_const_hash(rop.inst()->layername()), + rop.llvm_const_hash(rop.inst()->shadername()) }; if (!(Row.is_constant() && Row.get_int() >= 0 && Row.get_int() < 4)) { row = rop.ll.call_function("osl_range_check", args); @@ -1651,14 +1650,14 @@ LLVMGEN(llvm_gen_mxcompassign) llvm::Value* args[] = { row, rop.ll.constant(4), - rop.llvm_load_stringhash(Result.name()), + rop.llvm_const_hash(Result.name()), rop.sg_void_ptr(), - rop.llvm_load_stringhash(op.sourcefile()), + rop.llvm_const_hash(op.sourcefile()), rop.ll.constant(op.sourceline()), - rop.llvm_load_stringhash(rop.group().name()), + rop.llvm_const_hash(rop.group().name()), rop.ll.constant(rop.layer()), - rop.llvm_load_stringhash(rop.inst()->layername()), - rop.llvm_load_stringhash(rop.inst()->shadername()) }; + rop.llvm_const_hash(rop.inst()->layername()), + rop.llvm_const_hash(rop.inst()->shadername()) }; if (!(Row.is_constant() && Row.get_int() >= 0 && Row.get_int() < 4)) { row = rop.ll.call_function("osl_range_check", args); @@ -1722,14 +1721,14 @@ LLVMGEN(llvm_gen_aref) llvm::Value* args[] = { index, rop.ll.constant(Src.typespec().arraylength()), - rop.llvm_load_stringhash(Src.unmangled()), + rop.llvm_const_hash(Src.unmangled()), rop.sg_void_ptr(), - rop.llvm_load_stringhash(op.sourcefile()), + rop.llvm_const_hash(op.sourcefile()), rop.ll.constant(op.sourceline()), - rop.llvm_load_stringhash(rop.group().name()), + rop.llvm_const_hash(rop.group().name()), rop.ll.constant(rop.layer()), - rop.llvm_load_stringhash(rop.inst()->layername()), - rop.llvm_load_stringhash(rop.inst()->shadername()) }; + rop.llvm_const_hash(rop.inst()->layername()), + rop.llvm_const_hash(rop.inst()->shadername()) }; index = rop.ll.call_function("osl_range_check", args); } } @@ -1767,14 +1766,14 @@ LLVMGEN(llvm_gen_aassign) llvm::Value* args[] = { index, rop.ll.constant(Result.typespec().arraylength()), - rop.llvm_load_stringhash(Result.unmangled()), + rop.llvm_const_hash(Result.unmangled()), rop.sg_void_ptr(), - rop.llvm_load_stringhash(op.sourcefile()), + rop.llvm_const_hash(op.sourcefile()), rop.ll.constant(op.sourceline()), - rop.llvm_load_stringhash(rop.group().name()), + rop.llvm_const_hash(rop.group().name()), rop.ll.constant(rop.layer()), - rop.llvm_load_stringhash(rop.inst()->layername()), - rop.llvm_load_stringhash(rop.inst()->shadername()) }; + rop.llvm_const_hash(rop.inst()->layername()), + rop.llvm_const_hash(rop.inst()->shadername()) }; index = rop.ll.call_function("osl_range_check", args); } } @@ -1842,7 +1841,7 @@ LLVMGEN(llvm_gen_construct_color) llvm::Value* args[] = { rop.sg_void_ptr(), // shader globals rop.llvm_void_ptr(Result, 0), // color - rop.llvm_load_string(Space), // from + rop.llvm_load_value(Space), // from }; rop.ll.call_function("osl_prepend_color_from", args); // FIXME(deriv): Punt on derivs for color ctrs with space names. @@ -1899,7 +1898,7 @@ LLVMGEN(llvm_gen_construct_triple) vectype = TypeDesc::NORMAL; llvm::Value* from_arg = rop.llvm_load_value(Space); - llvm::Value* to_arg = rop.llvm_load_string(Strings::common); + llvm::Value* to_arg = rop.llvm_const_hash(Strings::common); llvm::Value* args[] = { rop.sg_void_ptr(), rop.llvm_void_ptr(Result), @@ -2082,8 +2081,8 @@ LLVMGEN(llvm_gen_transformc) Opcode& op(rop.inst()->ops()[opnum]); OSL_DASSERT(op.nargs() == 4); Symbol* Result = rop.opargsym(op, 0); - Symbol* From = rop.opargsym(op, 1); - Symbol* To = rop.opargsym(op, 2); + Symbol& From = *rop.opargsym(op, 1); + Symbol& To = *rop.opargsym(op, 2); Symbol* C = rop.opargsym(op, 3); llvm::Value* args[] = { rop.sg_void_ptr(), @@ -2091,8 +2090,8 @@ LLVMGEN(llvm_gen_transformc) rop.ll.constant(C->has_derivs()), rop.llvm_void_ptr(*Result), rop.ll.constant(Result->has_derivs()), - rop.llvm_load_string(*From), - rop.llvm_load_string(*To) }; + rop.llvm_load_value(From), + rop.llvm_load_value(To) }; rop.ll.call_function("osl_transformc", args); return true; @@ -3233,7 +3232,7 @@ LLVMGEN(llvm_gen_noise) llvm::Value* args[10]; int nargs = 0; if (pass_name) { - args[nargs++] = rop.llvm_load_string(*Name); + args[nargs++] = rop.llvm_load_value(*Name); } llvm::Value* tmpresult = NULL; // triple return, or float return with derivs, passes result pointer @@ -3395,7 +3394,7 @@ LLVMGEN(llvm_gen_getattribute) TypeDesc dest_type = Destination.typespec().simpletype(); llvm::Value* obj_name_arg = object_lookup ? rop.llvm_load_value(ObjectName) - : rop.llvm_load_string(ustring()); + : rop.llvm_const_hash(ustring()); llvm::Value* attr_name_arg = rop.llvm_load_value(Attribute); ustring object_name = (object_lookup && ObjectName.is_constant()) @@ -3430,7 +3429,7 @@ LLVMGEN(llvm_gen_getattribute) if (arg.is_holding()) { switch (arg.get_builtin()) { default: OSL_DASSERT(false); break; - case AttributeSpecBuiltinArg::ShaderGlobalsPointer: + case AttributeSpecBuiltinArg::OpaqueExecutionContext: args.push_back(rop.sg_void_ptr()); break; case AttributeSpecBuiltinArg::ShadeIndex: @@ -3570,7 +3569,7 @@ LLVMGEN(llvm_gen_getmessage) llvm::Value* args[9]; args[0] = rop.sg_void_ptr(); args[1] = has_source ? rop.llvm_load_value(Source) - : rop.ll.constant(ustring()); + : rop.ll.constant64(uint64_t(ustring().hash())); args[2] = rop.llvm_load_value(Name); if (Data.typespec().is_closure_based()) { @@ -3586,7 +3585,7 @@ LLVMGEN(llvm_gen_getmessage) args[5] = rop.ll.constant((int)Data.has_derivs()); args[6] = rop.ll.constant(rop.inst()->id()); - args[7] = rop.ll.constant(op.sourcefile()); + args[7] = rop.llvm_const_hash(op.sourcefile()); args[8] = rop.ll.constant(op.sourceline()); llvm::Value* r = rop.ll.call_function("osl_getmessage", args); @@ -3620,7 +3619,7 @@ LLVMGEN(llvm_gen_setmessage) } args[4] = rop.ll.constant(rop.inst()->id()); - args[5] = rop.ll.constant(op.sourcefile()); + args[5] = rop.llvm_const_hash(op.sourcefile()); args[6] = rop.ll.constant(op.sourceline()); rop.ll.call_function("osl_setmessage", args); @@ -3753,7 +3752,7 @@ LLVMGEN(llvm_gen_spline) llvm::Value* args[] = { rop.llvm_void_ptr(Result), - rop.llvm_load_string(Spline), + rop.llvm_load_value(Spline), rop.llvm_void_ptr(Value), // make things easy rop.llvm_void_ptr(Knots), has_knot_count ? rop.llvm_load_value(Knot_count) @@ -4114,7 +4113,7 @@ LLVMGEN(llvm_gen_pointcloud_write) int nattrs = (op.nargs() - 3) / 2; // Generate local space for the names/types/values arrays - llvm::Value* names = rop.ll.op_alloca(rop.ll.type_ustring(), nattrs); + llvm::Value* names = rop.ll.op_alloca(rop.ll.type_int64(), nattrs); llvm::Value* types = rop.ll.op_alloca(rop.ll.type_typedesc(), nattrs); llvm::Value* values = rop.ll.op_alloca(rop.ll.type_void_ptr(), nattrs); @@ -4151,7 +4150,6 @@ LLVMGEN(llvm_gen_pointcloud_write) } - LLVMGEN(llvm_gen_dict_find) { // OSL has two variants of this function: @@ -4238,7 +4236,7 @@ LLVMGEN(llvm_gen_split) OSL_DASSERT(Sep.typespec().is_string()); args[2] = rop.llvm_load_value(Sep); } else { - args[2] = rop.ll.constant(""); + args[2] = rop.ll.constant(ustring("").c_str()); } if (op.nargs() >= 5) { Symbol& Maxsplit = *rop.opargsym(op, 4); @@ -4271,7 +4269,7 @@ LLVMGEN(llvm_gen_raytype) func = "osl_raytype_bit"; } else { // No way to know which name is being asked for - args[1] = rop.llvm_load_string(Name); + args[1] = rop.llvm_load_value(Name); func = "osl_raytype_name"; } llvm::Value* ret = rop.ll.call_function(func, args); diff --git a/src/liboslexec/llvm_instance.cpp b/src/liboslexec/llvm_instance.cpp index f364d240d..9ddfab3c5 100644 --- a/src/liboslexec/llvm_instance.cpp +++ b/src/liboslexec/llvm_instance.cpp @@ -482,6 +482,54 @@ BackendLLVM::build_offsets_of_ShaderGlobals( offset_by_index.push_back(offsetof(ShaderGlobals, flipHandedness)); offset_by_index.push_back(offsetof(ShaderGlobals, backfacing)); } +void +BackendLLVM::llvm_create_constant(const Symbol& sym) +{ + OSL_ASSERT((sym.symtype() == SymTypeConst)); + + TypeDesc t = sym.typespec().simpletype(); + const int num_components = t.aggregate; + + // Initialize entire array + const int num_elements = t.numelements(); + + const int array_len = num_elements * num_components; + std::vector elements; + elements.reserve(array_len); + for (int a = 0; a < num_elements; ++a) { + for (int i = 0; i < num_components; ++i) { + int linear_index = num_components * a + i; + llvm::Constant* const_element = nullptr; + if (sym.typespec().is_float_based()) { + const_element = ll.constant(sym.get_float(linear_index)); + } + if (sym.typespec().is_int_based()) { + const_element = ll.constant(sym.get_int(linear_index)); + } + if (sym.typespec().is_string_based()) { + // TODO: right now stored as char *, but change to int64 when we can + const_element = reinterpret_cast( + ll.constant_ptr( + OSL::bitcast( + ustring(sym.get_string(linear_index)).hash()), + ll.type_char_ptr())); + } + OSL_ASSERT(const_element && "unhandled type"); + elements.push_back(const_element); + } + } + + // NOTE: even if type is not an array, it could be aggregate 3 or 16 + // we always just linearize it all for constants. + auto const_array = ll.constant_array(elements); + std::string unique_symname = global_unique_symname(sym); + + auto global_var = ll.create_global_constant(const_array, unique_symname); + + // TODO: consider changing m_const_map to unordered_map + m_const_map[unique_symname] = global_var; +} + void BackendLLVM::llvm_assign_initial_value(const Symbol& sym, bool force) { @@ -519,7 +567,7 @@ BackendLLVM::llvm_assign_initial_value(const Symbol& sym, bool force) else if (sym.typespec().is_int_based()) u = ll.constant(std::numeric_limits::min()); else if (sym.typespec().is_string_based()) - u = llvm_load_string(Strings::uninitialized_string); + u = llvm_const_hash(Strings::uninitialized_string); if (u) { for (int a = 0; a < alen; ++a) { llvm::Value* aval = isarray ? ll.constant(a) : NULL; @@ -594,7 +642,7 @@ BackendLLVM::llvm_assign_initial_value(const Symbol& sym, bool force) // No pre-placement: fall back to call to the renderer callback. llvm::Value* args[] = { sg_void_ptr(), - llvm_load_string(symname), + llvm_const_hash(symname), ll.constant(type), ll.constant((int)group().m_userdata_derivs[userdata_index]), groupdata_field_ptr(2 + userdata_index), // userdata data ptr @@ -614,12 +662,12 @@ BackendLLVM::llvm_assign_initial_value(const Symbol& sym, bool force) llvm_void_ptr(sym), ll.constant((int)sym.has_derivs()), sg_void_ptr(), - llvm_load_stringhash(inst()->shadername()), + llvm_const_hash(inst()->shadername()), ll.constant(0), - llvm_load_stringhash(sym.unmangled()), + llvm_const_hash(sym.unmangled()), ll.constant(0), ll.constant(ncomps), - llvm_load_stringhash("") }; + llvm_const_hash("") }; ll.call_function("osl_naninf_check", args); } // userdata pre-placement always succeeds, we don't need to bother @@ -642,28 +690,20 @@ BackendLLVM::llvm_assign_initial_value(const Symbol& sym, bool force) if (sym.has_init_ops() && sym.valuesource() == Symbol::DefaultVal) { // Handle init ops. build_llvm_code(sym.initbegin(), sym.initend()); -#if OSL_USE_OPTIX - } else if (use_optix() && !sym.typespec().is_closure() - && !sym.lockgeom()) { - // If the call to osl_bind_interpolated_param returns 0, the default - // value needs to be loaded from a CUDA variable. - llvm::Value* cuda_var = getOrAllocateCUDAVariable(sym); - TypeSpec elemtype = sym.typespec().elementtype(); - llvm::Type* cuda_var_type = llvm_type(elemtype); - // memcpy the initial value from the CUDA variable - llvm::Value* src = ll.ptr_cast(ll.GEP(cuda_var_type, cuda_var, 0), - ll.type_void_ptr()); - llvm::Value* dst = llvm_void_ptr(sym); - TypeDesc t = sym.typespec().simpletype(); - ll.op_memcpy(dst, src, t.size(), t.basesize()); - if (sym.has_derivs()) - llvm_zero_derivs(sym); -#endif } else if (sym.interpolated() && !sym.typespec().is_closure()) { // geometrically-varying param; memcpy its default value TypeDesc t = sym.typespec().simpletype(); - ll.op_memcpy(llvm_void_ptr(sym), ll.constant_ptr(sym.data()), - t.size(), t.basesize() /*align*/); + if (sym.typespec().is_string()) { + //llvm_create_constant(sym); + auto default_str = ll.constant64( + uint64_t(sym.get_string().hash())); + + OSL_ASSERT(llvm_store_value(default_str, sym, 0, nullptr, 0)); + } else { + ll.op_memcpy(llvm_void_ptr(sym), ll.constant_ptr(sym.data()), + t.size(), t.basesize() /*align*/); + } + if (sym.has_derivs()) llvm_zero_derivs(sym); } else { @@ -679,12 +719,13 @@ BackendLLVM::llvm_assign_initial_value(const Symbol& sym, bool force) for (int i = 0; i < num_components; ++i, ++c) { // Fill in the constant val llvm::Value* init_val = 0; - if (elemtype.is_float_based()) + if (elemtype.is_float_based()) { init_val = ll.constant(sym.get_float(c)); - else if (elemtype.is_string()) - init_val = llvm_load_string(sym.get_string(c)); - else if (elemtype.is_int()) + } else if (elemtype.is_string()) { + init_val = llvm_const_hash(sym.get_string(c)); + } else if (elemtype.is_int()) { init_val = ll.constant(sym.get_int(c)); + } OSL_DASSERT(init_val); llvm_store_value(init_val, sym, 0, arrind, i); } @@ -764,12 +805,12 @@ BackendLLVM::llvm_generate_debugnan(const Opcode& op) llvm_void_ptr(sym), ll.constant((int)sym.has_derivs()), sg_void_ptr(), - llvm_load_stringhash(op.sourcefile()), + llvm_const_hash(op.sourcefile()), ll.constant(op.sourceline()), - llvm_load_stringhash(sym.unmangled()), + llvm_const_hash(sym.unmangled()), offset, ncheck, - llvm_load_stringhash(op.opname()) }; + llvm_const_hash(op.opname()) }; ll.call_function("osl_naninf_check", args); } } @@ -868,16 +909,16 @@ BackendLLVM::llvm_generate_debug_uninit(const Opcode& op) llvm::Value* args[] = { ll.constant(t), llvm_void_ptr(sym), sg_void_ptr(), - llvm_load_stringhash(op.sourcefile()), + llvm_const_hash(op.sourcefile()), ll.constant(op.sourceline()), - llvm_load_stringhash(group().name()), + llvm_const_hash(group().name()), ll.constant(layer()), - llvm_load_stringhash(inst()->layername()), - llvm_load_stringhash(inst()->shadername()), + llvm_const_hash(inst()->layername()), + llvm_const_hash(inst()->shadername()), ll.constant(int(&op - &inst()->ops()[0])), - llvm_load_stringhash(op.opname()), + llvm_const_hash(op.opname()), ll.constant(i), - llvm_load_stringhash(sym.unmangled()), + llvm_const_hash(sym.unmangled()), offset, ncheck }; ll.call_function("osl_uninit_check", args); @@ -1287,8 +1328,14 @@ BackendLLVM::build_llvm_instance(bool groupentry) // Skip constants -- we always inline scalar constants, and for // array constants we will just use the pointers to the copy of // the constant that belongs to the instance. - if (s.symtype() == SymTypeConst) + if (s.symtype() == SymTypeConst) { + // For array constants we will always need an llvm constant array + // and for scalar/aggregate constants that are passed by address + // we will need a constant as well. If not used, we expect + // the pruning pass to remove unreferenced variables + llvm_create_constant(s); continue; + } // Skip structure placeholders if (s.typespec().is_structure()) continue; @@ -1310,18 +1357,17 @@ BackendLLVM::build_llvm_instance(bool groupentry) TypeDesc t = s.typespec().simpletype(); if (t.basetype == TypeDesc::FLOAT) { // just check float-based types - int ncomps = t.numelements() * t.aggregate; - llvm::Value* args[] - = { ll.constant(ncomps), - llvm_void_ptr(s), - ll.constant((int)s.has_derivs()), - sg_void_ptr(), - llvm_load_stringhash(inst()->shadername()), - ll.constant(0), - llvm_load_stringhash(s.unmangled()), - ll.constant(0), - ll.constant(ncomps), - llvm_load_stringhash("") }; + int ncomps = t.numelements() * t.aggregate; + llvm::Value* args[] = { ll.constant(ncomps), + llvm_void_ptr(s), + ll.constant((int)s.has_derivs()), + sg_void_ptr(), + llvm_const_hash(inst()->shadername()), + ll.constant(0), + llvm_const_hash(s.unmangled()), + ll.constant(0), + ll.constant(ncomps), + llvm_const_hash("") }; ll.call_function("osl_naninf_check", args); } } @@ -1576,7 +1622,7 @@ BackendLLVM::initialize_llvm_group() } #endif llvm::Function* f = ll.make_function(funcname, false, - llvm_type(rettype), params, + llvm_pass_type(rettype), params, varargs); // Skipping this in the non-JIT OptiX case suppresses an LLVM warning diff --git a/src/liboslexec/llvm_ops.cpp b/src/liboslexec/llvm_ops.cpp index 91ba893cb..809f3dd90 100644 --- a/src/liboslexec/llvm_ops.cpp +++ b/src/liboslexec/llvm_ops.cpp @@ -26,9 +26,9 @@ examples), as you are just coding in C++, but there are some rules: * Argument passing: int and float (without derivs) are passed as int and float. Aggregates (color/point/vector/normal/matrix), arrays of any types, or floats with derivatives are passed as a void* and to their - memory location you need to cast appropriately. Strings are passed as - ustringrep. See the handy USTR, MAT, VEC, DFLOAT, DVEC macros for - handy/cheap casting of those void*'s to references to ustringrep&, + memory location you need to cast appropriately. See the handy + MAT, VEC, DFLOAT, DVEC macros for + handy/cheap casting of those void*'s to references to Matrix44&, Vec3&, Dual2&, and Dual2, respectively. * You must provide all allowable polymorphic and derivative combinations! @@ -101,8 +101,6 @@ void* __dso_handle = 0; // necessary to avoid linkage issues in bitcode // Handy re-casting macros -#define USTR(s) (*((ustringrep*)&s)) -#define USTREP(s) (*((ustringrep*)&s)) #define MAT(m) (*(Matrix44*)m) #define VEC(v) (*(Vec3*)v) #define DFLOAT(x) (*(Dual2*)x) @@ -110,15 +108,6 @@ void* __dso_handle = 0; // necessary to avoid linkage issues in bitcode #define COL(x) (*(Color3*)x) #define DCOL(x) (*(Dual2*)x) -#if OSL_USTRINGREP_IS_HASH -/// ustring_pod is the type we use to pass string data in llvm function calls. -using ustring_pod = size_t; -#else -/// ustring_pod is the type we use to pass string data in llvm function calls. -using ustring_pod = const char*; -#endif - - #ifndef OSL_SHADEOP # ifdef __CUDACC__ # define OSL_SHADEOP \ diff --git a/src/liboslexec/llvm_util.cpp b/src/liboslexec/llvm_util.cpp index dd263af53..9fbcc27d2 100644 --- a/src/liboslexec/llvm_util.cpp +++ b/src/liboslexec/llvm_util.cpp @@ -560,16 +560,19 @@ LLVM_Util::LLVM_Util(const PerThreadInfo& per_thread_info, int debuglevel, void LLVM_Util::ustring_rep(UstringRep rep) { - m_ustring_rep = rep; - m_llvm_type_ustring = llvm::Type::getInt8PtrTy(*m_llvm_context); - // ^^ When m_ustring_rep != UstringRep::charptr, we'd ideally want to make - // it a uint directly, but that is wreaking havoc with function - // signatures, so continue to disguise it as a pointer. - // m_llvm_type_ustring = (sizeof(size_t) == sizeof(uint64_t)) - // ? llvm::Type::getInt64Ty(*m_llvm_context) - // : llvm::Type::getInt32Ty(*m_llvm_context); - m_llvm_type_ustring_ptr = llvm::PointerType::get(m_llvm_type_ustring, 0); - m_llvm_type_wide_ustring = llvm_vector_type(m_llvm_type_ustring, + m_ustring_rep = rep; + m_llvm_type_real_ustring = llvm::Type::getInt8PtrTy(*m_llvm_context); + if (m_ustring_rep == UstringRep::charptr) { + m_llvm_type_ustring = m_llvm_type_real_ustring; + } else { + OSL_ASSERT(m_ustring_rep == UstringRep::hash); + m_llvm_type_ustring = llvm::Type::getInt64Ty(*m_llvm_context); + } + m_llvm_type_ustring_ptr = llvm::PointerType::get(m_llvm_type_ustring, 0); + + // Batched versions haven't been updated to handle hash yet. + // For now leave them using the real ustring regardless of UstringRep + m_llvm_type_wide_ustring = llvm_vector_type(m_llvm_type_real_ustring, m_vector_width); m_llvm_type_wide_ustring_ptr = llvm::PointerType::get(m_llvm_type_wide_ustring, 0); @@ -3022,6 +3025,7 @@ LLVM_Util::make_function(const std::string& name, bool fastcall, OSL_ASSERT(maybe_func && "getOrInsertFunction returned NULL"); // if (!llvm::isa(maybe_func)) { // print("make_function: getOrInsertFunction returned non-function for {}\n", name); + // print(" return type: {}\n", llvm_typename(rettype)); // for (auto p : params) // print(" param type: {}\n", llvm_typename(p)); // } @@ -3433,6 +3437,24 @@ LLVM_Util::constant128(uint64_t left, uint64_t right) return llvm::ConstantInt::get(context(), llvm::APInt(128, refBigNum)); } +llvm::Constant* +LLVM_Util::constant_array(cspan constants) +{ + OSL_ASSERT(constants.size() > 0); + auto element_type = constants[0]->getType(); + auto array_type = llvm::ArrayType::get(element_type, constants.size()); + return llvm::ConstantArray::get(array_type, toArrayRef(constants)); +} + +llvm::GlobalVariable* +LLVM_Util::create_global_constant(llvm::Constant* initializer, + const std::string& llname) +{ + return new llvm::GlobalVariable(*m_llvm_module, initializer->getType(), + true /*is_constant*/, + llvm::GlobalVariable::PrivateLinkage, + initializer, llname); +} llvm::Constant* LLVM_Util::wide_constant(int width, int value) @@ -3496,15 +3518,7 @@ LLVM_Util::constant(ustring s) size_t p = s.hash(); auto str = (size_t_bits == 64) ? constant64(uint64_t(p)) : constant(int(p)); -#if OSL_USTRINGREP_IS_HASH return str; -#else - // Then cast the int to a char*. Ideally, we would only do that if the rep - // were a charptr, but we disguise the hashes as char*'s also to avoid - // ugliness with function signatures differing between CPU and GPU. - return builder().CreateIntToPtr(str, m_llvm_type_ustring, - "ustring constant"); -#endif } } diff --git a/src/liboslexec/opclosure.cpp b/src/liboslexec/opclosure.cpp index fdca5fa4c..319b7ec0a 100644 --- a/src/liboslexec/opclosure.cpp +++ b/src/liboslexec/opclosure.cpp @@ -76,7 +76,8 @@ osl_closure_to_string(ShaderGlobals* sg, ClosureColor* c) // Special case for printing closures std::ostringstream stream; stream.imbue(std::locale::classic()); // force C locale - print_closure(stream, c, &sg->context->shadingsys()); + print_closure(stream, c, &sg->context->shadingsys(), + /*treat_ustrings_as_hash*/ false); return ustring(stream.str()).c_str(); } @@ -86,7 +87,8 @@ osl_closure_to_ustringhash(ShaderGlobals* sg, ClosureColor* c) // Special case for printing closures std::ostringstream stream; stream.imbue(std::locale::classic()); // force C locale - print_closure(stream, c, &sg->context->shadingsys()); + print_closure(stream, c, &sg->context->shadingsys(), + /*treat_ustrings_as_hash*/ true); return ustring(stream.str()).hash(); } diff --git a/src/liboslexec/opcolor.cpp b/src/liboslexec/opcolor.cpp index 7232f5944..0da9421b3 100644 --- a/src/liboslexec/opcolor.cpp +++ b/src/liboslexec/opcolor.cpp @@ -12,10 +12,10 @@ #include "oslexec_pvt.h" #include -#include #include #include #include +#include #include @@ -59,33 +59,33 @@ OSL_CONSTANT_DATA const ColorSystem::Chroma k_color_systems[13] = { OSL_HOSTDEVICE const ColorSystem::Chroma* -ColorSystem::fromString(StringParam colorspace) +ColorSystem::fromString(ustringhash colorspace) { - if (colorspace == STRING_PARAMS(Rec709)) + if (colorspace == Hashes::Rec709) return &k_color_systems[0]; - if (colorspace == STRING_PARAMS(sRGB)) + if (colorspace == Hashes::sRGB) return &k_color_systems[1]; - if (colorspace == STRING_PARAMS(NTSC)) + if (colorspace == Hashes::NTSC) return &k_color_systems[2]; - if (colorspace == STRING_PARAMS(EBU)) + if (colorspace == Hashes::EBU) return &k_color_systems[3]; - if (colorspace == STRING_PARAMS(PAL)) + if (colorspace == Hashes::PAL) return &k_color_systems[4]; - if (colorspace == STRING_PARAMS(SECAM)) + if (colorspace == Hashes::SECAM) return &k_color_systems[5]; - if (colorspace == STRING_PARAMS(SMPTE)) + if (colorspace == Hashes::SMPTE) return &k_color_systems[6]; - if (colorspace == STRING_PARAMS(HDTV)) + if (colorspace == Hashes::HDTV) return &k_color_systems[7]; - if (colorspace == STRING_PARAMS(CIE)) + if (colorspace == Hashes::CIE) return &k_color_systems[8]; - if (colorspace == STRING_PARAMS(AdobeRGB)) + if (colorspace == Hashes::AdobeRGB) return &k_color_systems[9]; - if (colorspace == STRING_PARAMS(XYZ)) + if (colorspace == Hashes::XYZ) return &k_color_systems[10]; - if (colorspace == STRING_PARAMS(ACES2065_1)) + if (colorspace == Hashes::ACES2065_1) return &k_color_systems[11]; - if (colorspace == STRING_PARAMS(ACEScg)) + if (colorspace == Hashes::ACEScg) return &k_color_systems[12]; return nullptr; } @@ -139,7 +139,7 @@ norm_rgb (Color3 &rgb) OSL_HOSTDEVICE bool -ColorSystem::set_colorspace(StringParam colorspace) +ColorSystem::set_colorspace(ustringhash colorspace) { if (colorspace == m_colorspace) return true; @@ -220,17 +220,19 @@ ColorSystem::set_colorspace(StringParam colorspace) template OSL_HOSTDEVICE Color -ColorSystem::ocio_transform(StringParam fromspace, StringParam tospace, +ColorSystem::ocio_transform(ustringhash fromspace, ustringhash tospace, const Color& C, ShadingContext* ctx, ExecContextPtr ec) const { // Currently CPU only supports ocio by going through ShadingContext -#if !defined(__CUDA_ARCH__) +#if !defined(__CUDA_ARCH__) && !defined(OSL_COMPILING_TO_BITCODE) Color Cout; assert(ctx); - - if (ctx->ocio_transform(fromspace, tospace, C, Cout)) + //Reverse lookup only possible on host + ustring fromspace_str = ustring_from(fromspace); + ustring tospace_str = ustring_from(tospace); + if (ctx->ocio_transform(fromspace_str, tospace_str, C, Cout)) return Cout; if (ec == nullptr) { @@ -242,7 +244,7 @@ ColorSystem::ocio_transform(StringParam fromspace, StringParam tospace, OSL::errorfmt(ec, "Unknown color space transformation \"{}\" -> \"{}\"", fromspace, tospace); } -#endif // !define(__CUDA_ARCH__) +#endif // !define(__CUDA_ARCH__) && !defined(OSL_COMPILING_TO_BITCODE) return C; } @@ -250,7 +252,7 @@ ColorSystem::ocio_transform(StringParam fromspace, StringParam tospace, OSL_HOSTDEVICE Dual2 -ColorSystem::ocio_transform(StringParam fromspace, StringParam tospace, +ColorSystem::ocio_transform(ustringhash fromspace, ustringhash tospace, const Dual2& C, ShadingContext* ctx, ExecContextPtr ec) const { @@ -260,7 +262,7 @@ ColorSystem::ocio_transform(StringParam fromspace, StringParam tospace, OSL_HOSTDEVICE Color3 -ColorSystem::ocio_transform(StringParam fromspace, StringParam tospace, +ColorSystem::ocio_transform(ustringhash fromspace, ustringhash tospace, const Color3& C, ShadingContext* ctx, ExecContextPtr ec) const { @@ -270,56 +272,56 @@ ColorSystem::ocio_transform(StringParam fromspace, StringParam tospace, OSL_HOSTDEVICE Color3 -ColorSystem::to_rgb(StringParam fromspace, const Color3& C, ShadingContext* ctx, +ColorSystem::to_rgb(ustringhash fromspace, const Color3& C, ShadingContext* ctx, ExecContextPtr ec) const { // NOTE: any changes here should be mirrored // in wide_prepend_color_from in wide_opcolor.cpp - if (fromspace == STRING_PARAMS(RGB) || fromspace == STRING_PARAMS(rgb) + if (fromspace == Hashes::RGB || fromspace == Hashes::rgb || fromspace == m_colorspace) return C; - if (fromspace == STRING_PARAMS(hsv)) + if (fromspace == Hashes::hsv) return hsv_to_rgb(C); - if (fromspace == STRING_PARAMS(hsl)) + if (fromspace == Hashes::hsl) return hsl_to_rgb(C); - if (fromspace == STRING_PARAMS(YIQ)) + if (fromspace == Hashes::YIQ) return YIQ_to_rgb(C); - if (fromspace == STRING_PARAMS(XYZ)) + if (fromspace == Hashes::XYZ) return XYZ_to_RGB(C); - if (fromspace == STRING_PARAMS(xyY)) + if (fromspace == Hashes::xyY) return XYZ_to_RGB(xyY_to_XYZ(C)); else - return ocio_transform(fromspace, STRING_PARAMS(RGB), C, ctx, ec); + return ocio_transform(fromspace, Hashes::RGB, C, ctx, ec); } OSL_HOSTDEVICE Color3 -ColorSystem::from_rgb(StringParam tospace, const Color3& C, ShadingContext* ctx, +ColorSystem::from_rgb(ustringhash tospace, const Color3& C, ShadingContext* ctx, ExecContextPtr ec) const { - if (tospace == STRING_PARAMS(RGB) || tospace == STRING_PARAMS(rgb) + if (tospace == Hashes::RGB || tospace == Hashes::rgb || tospace == m_colorspace) return C; - if (tospace == STRING_PARAMS(hsv)) + if (tospace == Hashes::hsv) return rgb_to_hsv(C); - if (tospace == STRING_PARAMS(hsl)) + if (tospace == Hashes::hsl) return rgb_to_hsl(C); - if (tospace == STRING_PARAMS(YIQ)) + if (tospace == Hashes::YIQ) return rgb_to_YIQ(C); - if (tospace == STRING_PARAMS(XYZ)) + if (tospace == Hashes::XYZ) return RGB_to_XYZ(C); - if (tospace == STRING_PARAMS(xyY)) + if (tospace == Hashes::xyY) return XYZ_to_xyY(RGB_to_XYZ(C)); else - return ocio_transform(STRING_PARAMS(RGB), tospace, C, ctx, ec); + return ocio_transform(Hashes::RGB, tospace, C, ctx, ec); } template OSL_HOSTDEVICE COLOR -ColorSystem::transformc(StringParam fromspace, StringParam tospace, +ColorSystem::transformc(ustringhash fromspace, ustringhash tospace, const COLOR& C, ShadingContext* ctx, ExecContextPtr ec) const { @@ -327,20 +329,20 @@ ColorSystem::transformc(StringParam fromspace, StringParam tospace, // in wide_transformc in wide_opcolor.cpp bool use_colorconfig = false; COLOR Crgb; - if (fromspace == STRING_PARAMS(RGB) || fromspace == STRING_PARAMS(rgb) - || fromspace == STRING_PARAMS(linear) || fromspace == m_colorspace) + if (fromspace == Hashes::RGB || fromspace == Hashes::rgb + || fromspace == Hashes::linear || fromspace == m_colorspace) Crgb = C; - else if (fromspace == STRING_PARAMS(hsv)) + else if (fromspace == Hashes::hsv) Crgb = hsv_to_rgb(C); - else if (fromspace == STRING_PARAMS(hsl)) + else if (fromspace == Hashes::hsl) Crgb = hsl_to_rgb(C); - else if (fromspace == STRING_PARAMS(YIQ)) + else if (fromspace == Hashes::YIQ) Crgb = YIQ_to_rgb(C); - else if (fromspace == STRING_PARAMS(XYZ)) + else if (fromspace == Hashes::XYZ) Crgb = XYZ_to_RGB(C); - else if (fromspace == STRING_PARAMS(xyY)) + else if (fromspace == Hashes::xyY) Crgb = XYZ_to_RGB(xyY_to_XYZ(C)); - else if (fromspace == STRING_PARAMS(sRGB)) + else if (fromspace == Hashes::sRGB) Crgb = sRGB_to_linear(C); else { use_colorconfig = true; @@ -349,20 +351,20 @@ ColorSystem::transformc(StringParam fromspace, StringParam tospace, COLOR Cto; if (use_colorconfig) { // do things the ColorConfig way, so skip all these other clauses... - } else if (tospace == STRING_PARAMS(RGB) || tospace == STRING_PARAMS(rgb) - || tospace == STRING_PARAMS(linear) || tospace == m_colorspace) + } else if (tospace == Hashes::RGB || tospace == Hashes::rgb + || tospace == Hashes::linear || tospace == m_colorspace) Cto = Crgb; - else if (tospace == STRING_PARAMS(hsv)) + else if (tospace == Hashes::hsv) Cto = rgb_to_hsv(Crgb); - else if (tospace == STRING_PARAMS(hsl)) + else if (tospace == Hashes::hsl) Cto = rgb_to_hsl(Crgb); - else if (tospace == STRING_PARAMS(YIQ)) + else if (tospace == Hashes::YIQ) Cto = rgb_to_YIQ(Crgb); - else if (tospace == STRING_PARAMS(XYZ)) + else if (tospace == Hashes::XYZ) Cto = RGB_to_XYZ(Crgb); - else if (tospace == STRING_PARAMS(xyY)) + else if (tospace == Hashes::xyY) Cto = XYZ_to_xyY(RGB_to_XYZ(Crgb)); - else if (tospace == STRING_PARAMS(sRGB)) + else if (tospace == Hashes::sRGB) Cto = linear_to_sRGB(Crgb); else { use_colorconfig = true; @@ -378,7 +380,7 @@ ColorSystem::transformc(StringParam fromspace, StringParam tospace, OSL_HOSTDEVICE Dual2 -ColorSystem::transformc(StringParam fromspace, StringParam tospace, +ColorSystem::transformc(ustringhash fromspace, ustringhash tospace, const Dual2& color, ShadingContext* ctx, ExecContextPtr ec) const { @@ -388,7 +390,7 @@ ColorSystem::transformc(StringParam fromspace, StringParam tospace, OSL_HOSTDEVICE Color3 -ColorSystem::transformc(StringParam fromspace, StringParam tospace, +ColorSystem::transformc(ustringhash fromspace, ustringhash tospace, const Color3& color, ShadingContext* ctx, ExecContextPtr ec) const { @@ -401,7 +403,7 @@ ColorSystem::transformc(StringParam fromspace, StringParam tospace, // For Optix, this will be defined by the renderer. Otherwise inline a getter. #ifdef __CUDACC__ extern "C" __device__ int -rend_get_userdata(StringParam name, void* data, int data_size, +rend_get_userdata(ustringhash name, void* data, int data_size, const OSL::TypeDesc& type, int index); namespace { @@ -410,8 +412,7 @@ __device__ static inline const ColorSystem& get_colorsystem(OSL::OpaqueExecContextPtr /*oec*/) { void* ptr; - rend_get_userdata(STRING_PARAMS(colorsystem), &ptr, 8, OSL::TypeDesc::PTR, - 0); + rend_get_userdata(Hashes::colorsystem, &ptr, 8, OSL::TypeDesc::PTR, 0); return *((ColorSystem*)ptr); } @@ -477,22 +478,25 @@ osl_luminance_dfdv(OpaqueExecContextPtr oec, void* out, void* c) OSL_SHADEOP OSL_HOSTDEVICE void -osl_prepend_color_from(OpaqueExecContextPtr oec, void* c_, const char* from) +osl_prepend_color_from(OpaqueExecContextPtr oec, void* c_, + ustringhash_pod from_) { + auto from = ustringhash_from(from_); const ColorSystem& cs = get_colorsystem(oec); auto ec = pvt::get_ec(oec); - COL(c_) = cs.to_rgb(HDSTR(from), COL(c_), ec->context, ec); + COL(c_) = cs.to_rgb(from, COL(c_), ec->context, ec); } OSL_SHADEOP OSL_HOSTDEVICE int osl_transformc(OpaqueExecContextPtr oec, void* Cin, int Cin_derivs, void* Cout, - int Cout_derivs, void* from_, void* to_) + int Cout_derivs, ustringhash_pod from_, ustringhash_pod to_) { const ColorSystem& cs = get_colorsystem(oec); - StringParam from = HDSTR(from_); - StringParam to = HDSTR(to_); + + auto from = ustringhash_from(from_); + auto to = ustringhash_from(to_); auto ec = pvt::get_ec(oec); diff --git a/src/liboslexec/opcolor.h b/src/liboslexec/opcolor.h index 6539be6ad..7112b90d4 100644 --- a/src/liboslexec/opcolor.h +++ b/src/liboslexec/opcolor.h @@ -12,9 +12,9 @@ ///////////////////////////////////////////////////////////////////////// #include -#include #include #include +#include #include @@ -41,7 +41,7 @@ class OSLEXECPUBLIC ColorSystem { float xRed, yRed, xGreen, yGreen, xBlue, yBlue, xWhite, yWhite; }; - OSL_HOSTDEVICE static const Chroma* fromString(StringParam colorspace); + OSL_HOSTDEVICE static const Chroma* fromString(ustringhash colorspace); /// Convert an XYZ color to RGB in our preferred color space. template OSL_HOSTDEVICE T XYZ_to_RGB(const T& XYZ) const @@ -81,37 +81,37 @@ class OSLEXECPUBLIC ColorSystem { /// Set the current color space. - OSL_HOSTDEVICE bool set_colorspace(StringParam colorspace); + OSL_HOSTDEVICE bool set_colorspace(ustringhash colorspace); - OSL_HOSTDEVICE Color3 to_rgb(StringParam fromspace, const Color3& C, + OSL_HOSTDEVICE Color3 to_rgb(ustringhash fromspace, const Color3& C, ShadingContext*, ExecContextPtr ec = nullptr) const; - OSL_HOSTDEVICE Color3 from_rgb(StringParam fromspace, const Color3& C, + OSL_HOSTDEVICE Color3 from_rgb(ustringhash fromspace, const Color3& C, ShadingContext*, ExecContextPtr ec = nullptr) const; - OSL_HOSTDEVICE Dual2 transformc(StringParam fromspace, - StringParam tospace, + OSL_HOSTDEVICE Dual2 transformc(ustringhash fromspace, + ustringhash tospace, const Dual2& color, ShadingContext*, ExecContextPtr ec = nullptr) const; - OSL_HOSTDEVICE Color3 transformc(StringParam fromspace, StringParam tospace, + OSL_HOSTDEVICE Color3 transformc(ustringhash fromspace, ustringhash tospace, const Color3& color, ShadingContext*, ExecContextPtr ec = nullptr) const; OSL_HOSTDEVICE Dual2 - ocio_transform(StringParam fromspace, StringParam tospace, + ocio_transform(ustringhash fromspace, ustringhash tospace, const Dual2& C, ShadingContext*, ExecContextPtr ec = nullptr) const; - OSL_HOSTDEVICE Color3 ocio_transform(StringParam fromspace, - StringParam tospace, const Color3& C, + OSL_HOSTDEVICE Color3 ocio_transform(ustringhash fromspace, + ustringhash tospace, const Color3& C, ShadingContext*, ExecContextPtr ec = nullptr) const; - OSL_HOSTDEVICE const StringParam& colorspace() const + OSL_HOSTDEVICE const ustringhash& colorspace() const { return m_colorspace; } @@ -119,12 +119,12 @@ class OSLEXECPUBLIC ColorSystem { private: template OSL_HOSTDEVICE inline Color - transformc(StringParam fromspace, StringParam tospace, const Color& C, + transformc(ustringhash fromspace, ustringhash tospace, const Color& C, ShadingContext*, ExecContextPtr ec = nullptr) const; template OSL_HOSTDEVICE inline Color - ocio_transform(StringParam fromspace, StringParam tospace, const Color& C, + ocio_transform(ustringhash fromspace, ustringhash tospace, const Color& C, ShadingContext*, ExecContextPtr ec = nullptr) const; @@ -137,15 +137,15 @@ class OSLEXECPUBLIC ColorSystem { Color3 m_blackbody_table[317]; ///< Precomputed blackbody table // Keep this last so the CUDA device string can be easily set - StringParam m_colorspace; ///< What RGB colors mean + ustringhash m_colorspace; ///< What RGB colors mean }; class OCIOColorSystem { #ifndef __CUDACC__ public: - OIIO::ColorProcessorHandle load_transform(StringParam fromspace, - StringParam tospace, + OIIO::ColorProcessorHandle load_transform(ustring fromspace, + ustring tospace, ShadingSystemImpl* shadingsys); private: diff --git a/src/liboslexec/opfmt.cpp b/src/liboslexec/opfmt.cpp index ee6b96f03..c0caa21fd 100644 --- a/src/liboslexec/opfmt.cpp +++ b/src/liboslexec/opfmt.cpp @@ -32,11 +32,17 @@ namespace pvt { // and forward on calls to re free functions. OSL_RSOP OSL::ustringhash_pod -osl_gen_ustringhash_pod(const char* s) +osl_gen_ustringhash_pod(ustring_pod s) { return USTR(s).hash(); } +OSL_RSOP const char* +osl_gen_ustring(OSL::ustringhash_pod hash) +{ + return ustring_from(hash).c_str(); +} + OSL_RSOP void osl_gen_errorfmt(OpaqueExecContextPtr exec_ctx, OSL::ustringhash_pod fmt_specification, int32_t arg_count, @@ -75,12 +81,9 @@ osl_gen_printfmt(OpaqueExecContextPtr exec_ctx, OSL::ustringhash rs_fmt_specification = OSL::ustringhash_from( fmt_specification); auto encoded_types = reinterpret_cast(arg_types); - //auto argValues2 = reinterpret_cast (arg_values); - rs_printfmt(exec_ctx, rs_fmt_specification, arg_count, encoded_types, - arg_values_size, - arg_values); //not argValues2 + arg_values_size, arg_values); } diff --git a/src/liboslexec/opmatrix.cpp b/src/liboslexec/opmatrix.cpp index e60405388..1dffbf5be 100644 --- a/src/liboslexec/opmatrix.cpp +++ b/src/liboslexec/opmatrix.cpp @@ -11,10 +11,10 @@ ///////////////////////////////////////////////////////////////////////// #include "oslexec_pvt.h" -#include #include #include #include +#include #include #include @@ -136,28 +136,28 @@ osl_transformn_dvmdv(void* result, void* M_, void* v_) #ifndef __CUDACC__ OSL_SHADEOP int -osl_get_matrix(OpaqueExecContextPtr oec, void* r, const char* from) +osl_get_matrix(OpaqueExecContextPtr oec, void* r, ustringhash_pod from_) { - if (HDSTR(from) == STRING_PARAMS(common) - || HDSTR(from) == get_commonspace_synonym(oec)) { + ustringhash from = ustringhash_from(from_); + if (from == Hashes::common || from == get_commonspace_synonym(oec)) { MAT(r).makeIdentity(); return true; } - if (HDSTR(from) == STRING_PARAMS(shader)) { + if (from == Hashes::shader) { rs_get_matrix_xform_time(oec, MAT(r), get_shader2common(oec), get_time(oec)); return true; } - if (HDSTR(from) == STRING_PARAMS(object)) { + if (from == Hashes::object) { rs_get_matrix_xform_time(oec, MAT(r), get_object2common(oec), get_time(oec)); return true; } - int ok = rs_get_matrix_space_time(oec, MAT(r), HDSTR(from), get_time(oec)); + int ok = rs_get_matrix_space_time(oec, MAT(r), from, get_time(oec)); if (!ok) { MAT(r).makeIdentity(); if (get_unknown_coordsys_error(oec)) { - OSL::errorfmt(oec, "Unknown transformation \"{}\"", HDSTR(from)); + OSL::errorfmt(oec, "Unknown transformation \"{}\"", from); } } return ok; @@ -166,29 +166,28 @@ osl_get_matrix(OpaqueExecContextPtr oec, void* r, const char* from) OSL_SHADEOP int -osl_get_inverse_matrix(OpaqueExecContextPtr oec, void* r, const char* to) +osl_get_inverse_matrix(OpaqueExecContextPtr oec, void* r, ustringhash_pod to_) { - if (HDSTR(to) == STRING_PARAMS(common) - || HDSTR(to) == get_commonspace_synonym(oec)) { + ustringhash to = ustringhash_from(to_); + if (to == Hashes::common || to == get_commonspace_synonym(oec)) { MAT(r).makeIdentity(); return true; } - if (HDSTR(to) == STRING_PARAMS(shader)) { + if (to == Hashes::shader) { rs_get_inverse_matrix_xform_time(oec, MAT(r), get_shader2common(oec), get_time(oec)); return true; } - if (HDSTR(to) == STRING_PARAMS(object)) { + if (to == Hashes::object) { rs_get_inverse_matrix_xform_time(oec, MAT(r), get_object2common(oec), get_time(oec)); return true; } - int ok = rs_get_inverse_matrix_space_time(oec, MAT(r), HDSTR(to), - get_time(oec)); + int ok = rs_get_inverse_matrix_space_time(oec, MAT(r), to, get_time(oec)); if (!ok) { MAT(r).makeIdentity(); if (get_unknown_coordsys_error(oec)) { - OSL::errorfmt(oec, "Unknown transformation \"{}\"", HDSTR(to)); + OSL::errorfmt(oec, "Unknown transformation \"{}\"", to); } } return ok; @@ -197,26 +196,28 @@ osl_get_inverse_matrix(OpaqueExecContextPtr oec, void* r, const char* to) // Implemented by the renderer # define OSL_SHADEOP_EXPORT extern "C" OSL_DLL_EXPORT OSL_SHADEOP_EXPORT OSL_HOSTDEVICE int -osl_get_matrix(OpaqueExecContextPtr oec, void* r, const char* from); +osl_get_matrix(OpaqueExecContextPtr oec, void* r, ustringhash_pod from); OSL_SHADEOP_EXPORT OSL_HOSTDEVICE int -osl_get_inverse_matrix(OpaqueExecContextPtr oec, void* r, const char* to); +osl_get_inverse_matrix(OpaqueExecContextPtr oec, void* r, ustringhash_pod to); # undef OSL_SHADEOP_EXPORT #endif // __CUDACC__ OSL_SHADEOP OSL_HOSTDEVICE int -osl_prepend_matrix_from(OpaqueExecContextPtr oec, void* r, const char* from) +osl_prepend_matrix_from(OpaqueExecContextPtr oec, void* r, + ustringhash_pod from_) { Matrix44 m; - bool ok = osl_get_matrix(oec, &m, from); + bool ok = osl_get_matrix(oec, &m, from_); if (ok) MAT(r) = m * MAT(r); #ifndef __CUDACC__ // TODO: How do we manage this in OptiX? else { if (get_unknown_coordsys_error(oec)) { - OSL::errorfmt(oec, "Unknown transformation \"{}\"", HDSTR(from)); + OSL::errorfmt(oec, "Unknown transformation \"{}\"", + ustringhash_from(from_)); } } #endif @@ -226,12 +227,12 @@ osl_prepend_matrix_from(OpaqueExecContextPtr oec, void* r, const char* from) OSL_SHADEOP OSL_HOSTDEVICE int -osl_get_from_to_matrix(OpaqueExecContextPtr oec, void* r, const char* from, - const char* to) +osl_get_from_to_matrix(OpaqueExecContextPtr oec, void* r, ustringhash_pod from_, + ustringhash_pod to_) { Matrix44 Mfrom, Mto; - int ok = osl_get_matrix(oec, &Mfrom, from); - ok &= osl_get_inverse_matrix(oec, &Mto, to); + int ok = osl_get_matrix(oec, &Mfrom, from_); + ok &= osl_get_inverse_matrix(oec, &Mto, to_); MAT(r) = Mfrom * Mto; return ok; } @@ -240,19 +241,21 @@ osl_get_from_to_matrix(OpaqueExecContextPtr oec, void* r, const char* from, OSL_SHADEOP OSL_HOSTDEVICE int osl_transform_triple(OpaqueExecContextPtr oec, void* Pin, int Pin_derivs, - void* Pout, int Pout_derivs, void* from, void* to, - int vectype) + void* Pout, int Pout_derivs, ustringhash_pod from_, + ustringhash_pod to_, int vectype) { Matrix44 M; int ok; Pin_derivs &= Pout_derivs; // ignore derivs if output doesn't need it - if (HDSTR(from) == STRING_PARAMS(common)) - ok = osl_get_inverse_matrix(oec, &M, (const char*)to); - else if (HDSTR(to) == STRING_PARAMS(common)) - ok = osl_get_matrix(oec, &M, (const char*)from); + ustringhash from = ustringhash_from(from_); + ustringhash to = ustringhash_from(to_); + + if (from == Hashes::common) + ok = osl_get_inverse_matrix(oec, &M, to_); + else if (to == Hashes::common) + ok = osl_get_matrix(oec, &M, from_); else - ok = osl_get_from_to_matrix(oec, &M, (const char*)from, - (const char*)to); + ok = osl_get_from_to_matrix(oec, &M, from_, to_); if (ok) { if (vectype == TypeDesc::POINT) { if (Pin_derivs) @@ -297,18 +300,20 @@ osl_transform_triple(OpaqueExecContextPtr oec, void* Pin, int Pin_derivs, OSL_SHADEOP OSL_HOSTDEVICE int osl_transform_triple_nonlinear(OpaqueExecContextPtr oec, void* Pin, int Pin_derivs, void* Pout, int Pout_derivs, - void* from, void* to, int vectype) + ustringhash_pod from_, ustringhash_pod to_, + int vectype) { #ifndef __CUDACC__ + ustringhash from = ustringhash_from(from_); + ustringhash to = ustringhash_from(to_); - if (rs_transform_points(oec, HDSTR(from), HDSTR(to), get_time(oec), - (const Vec3*)Pin, (Vec3*)Pout, 1, - (TypeDesc::VECSEMANTICS)vectype)) { + if (rs_transform_points(oec, from, to, get_time(oec), (const Vec3*)Pin, + (Vec3*)Pout, 1, (TypeDesc::VECSEMANTICS)vectype)) { // Renderer had a direct way to transform the points between the // two spaces. if (Pout_derivs) { if (Pin_derivs) { - rs_transform_points(oec, HDSTR(from), HDSTR(to), get_time(oec), + rs_transform_points(oec, from, to, get_time(oec), (const Vec3*)Pin + 1, (Vec3*)Pout + 1, 2, TypeDesc::VECTOR); } else { @@ -323,8 +328,8 @@ osl_transform_triple_nonlinear(OpaqueExecContextPtr oec, void* Pin, // Renderer couldn't or wouldn't transform directly // Except in OptiX we're the renderer will directly implement // the transform in osl_transform_triple. - return osl_transform_triple(oec, Pin, Pin_derivs, Pout, Pout_derivs, from, - to, vectype); + return osl_transform_triple(oec, Pin, Pin_derivs, Pout, Pout_derivs, from_, + to_, vectype); } diff --git a/src/liboslexec/opmessage.cpp b/src/liboslexec/opmessage.cpp index 5f0fb0817..ef63995f7 100644 --- a/src/liboslexec/opmessage.cpp +++ b/src/liboslexec/opmessage.cpp @@ -28,11 +28,12 @@ namespace pvt { OSL_SHADEOP void -osl_setmessage(ShaderGlobals* sg, ustring_pod name_, long long type_, void* val, - int layeridx, ustring_pod sourcefile_, int sourceline) +osl_setmessage(ShaderGlobals* sg, ustringhash_pod name_, long long type_, + void* val, int layeridx, ustringhash_pod sourcefile_, + int sourceline) { - ustringhash name = ustringhash_from(USTR(name_)); - ustringhash sourcefile = ustringhash_from(USTR(sourcefile_)); + auto name = ustringhash_from(name_); + auto sourcefile = ustringhash_from(sourcefile_); // recreate TypeDesc -- we just crammed it into an int! TypeDesc type = TYPEDESC(type_); bool is_closure = type.basetype == TypeDesc::UNKNOWN; // indicates closure @@ -67,13 +68,13 @@ osl_setmessage(ShaderGlobals* sg, ustring_pod name_, long long type_, void* val, OSL_SHADEOP int -osl_getmessage(ShaderGlobals* sg, ustring_pod source_, ustring_pod name_, - long long type_, void* val, int derivs, int layeridx, - ustring_pod sourcefile_, int sourceline) +osl_getmessage(ShaderGlobals* sg, ustringhash_pod source_, + ustringhash_pod name_, long long type_, void* val, int derivs, + int layeridx, ustringhash_pod sourcefile_, int sourceline) { - ustringhash source = ustringhash_from(USTR(source_)); - ustringhash name = ustringhash_from(USTR(name_)); - ustringhash sourcefile = ustringhash_from(USTR(sourcefile_)); + auto source = ustringhash_from(source_); + auto name = ustringhash_from(name_); + auto sourcefile = ustringhash_from(sourcefile_); // recreate TypeDesc -- we just crammed it into an int! TypeDesc type = TYPEDESC(type_); @@ -81,8 +82,9 @@ osl_getmessage(ShaderGlobals* sg, ustring_pod source_, ustring_pod name_, if (is_closure) type.basetype = TypeDesc::PTR; // for closures, we store a pointer - static ustringrep ktrace("trace"); - if (source == ktrace) { + static ustring ktrace("trace"); + + if (source == ustringhash_from(ktrace)) { // Source types where we need to ask the renderer return sg->renderer->getmessage(sg, source, name, type, val, derivs); } diff --git a/src/liboslexec/opnoise.cpp b/src/liboslexec/opnoise.cpp index 21a91f21e..d8c6d31ea 100644 --- a/src/liboslexec/opnoise.cpp +++ b/src/liboslexec/opnoise.cpp @@ -6,9 +6,9 @@ #include "oslexec_pvt.h" #include -#include #include #include +#include #include #include @@ -208,45 +208,53 @@ OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvvdf (char *r, char *x, char * #define NOISE_IMPL_DERIV_OPT(opname,implname) \ -OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdf (char *name, char *r, char *x, char *sg, char *opt) { \ +OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdf (ustringhash_pod name_, char *r, char *x, char *sg, char *opt) { \ implname impl; \ - impl (HDSTR(name), DFLOAT(r), DFLOAT(x), (ShaderGlobals *)sg, (NoiseParams *)opt); \ + ustringhash name = ustringhash_from(name_); \ + impl (name, DFLOAT(r), DFLOAT(x), (ShaderGlobals *)sg, (NoiseParams *)opt); \ } \ \ -OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdfdf (char *name, char *r, char *x, char *y, char *sg, char *opt) { \ +OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdfdf (ustringhash_pod name_, char *r, char *x, char *y, char *sg, char *opt) { \ implname impl; \ - impl (HDSTR(name), DFLOAT(r), DFLOAT(x), DFLOAT(y), (ShaderGlobals *)sg, (NoiseParams *)opt); \ + ustringhash name = ustringhash_from(name_); \ + impl (name, DFLOAT(r), DFLOAT(x), DFLOAT(y), (ShaderGlobals *)sg, (NoiseParams *)opt); \ } \ \ -OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdv (char *name, char *r, char *x, char *sg, char *opt) { \ +OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdv (ustringhash_pod name_, char *r, char *x, char *sg, char *opt) { \ implname impl; \ - impl (HDSTR(name), DFLOAT(r), DVEC(x), (ShaderGlobals *)sg, (NoiseParams *)opt); \ + ustringhash name = ustringhash_from(name_); \ + impl (name, DFLOAT(r), DVEC(x), (ShaderGlobals *)sg, (NoiseParams *)opt); \ } \ \ -OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdvdf (char *name, char *r, char *x, char *y, char *sg, char *opt) { \ +OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdvdf (ustringhash_pod name_, char *r, char *x, char *y, char *sg, char *opt) { \ implname impl; \ - impl (HDSTR(name), DFLOAT(r), DVEC(x), DFLOAT(y), (ShaderGlobals *)sg, (NoiseParams *)opt); \ + ustringhash name = ustringhash_from(name_); \ + impl (name, DFLOAT(r), DVEC(x), DFLOAT(y), (ShaderGlobals *)sg, (NoiseParams *)opt); \ } \ \ \ -OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdf (char *name, char *r, char *x, char *sg, char *opt) { \ +OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdf (ustringhash_pod name_, char *r, char *x, char *sg, char *opt) { \ implname impl; \ - impl (HDSTR(name), DVEC(r), DFLOAT(x), (ShaderGlobals *)sg, (NoiseParams *)opt); \ + ustringhash name = ustringhash_from(name_); \ + impl (name, DVEC(r), DFLOAT(x), (ShaderGlobals *)sg, (NoiseParams *)opt); \ } \ \ -OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdfdf (char *name, char *r, char *x, char *y, char *sg, char *opt) { \ +OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdfdf (ustringhash_pod name_, char *r, char *x, char *y, char *sg, char *opt) { \ implname impl; \ - impl (HDSTR(name), DVEC(r), DFLOAT(x), DFLOAT(y), (ShaderGlobals *)sg, (NoiseParams *)opt); \ + ustringhash name = ustringhash_from(name_); \ + impl (name, DVEC(r), DFLOAT(x), DFLOAT(y), (ShaderGlobals *)sg, (NoiseParams *)opt); \ } \ \ -OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdv (char *name, char *r, char *x, char *sg, char *opt) { \ +OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdv (ustringhash_pod name_, char *r, char *x, char *sg, char *opt) { \ implname impl; \ - impl (HDSTR(name), DVEC(r), DVEC(x), (ShaderGlobals *)sg, (NoiseParams *)opt); \ + ustringhash name = ustringhash_from(name_); \ + impl (name, DVEC(r), DVEC(x), (ShaderGlobals *)sg, (NoiseParams *)opt); \ } \ \ -OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdvdf (char *name, char *r, char *x, char *y, char *sg, char *opt) { \ +OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdvdf (ustringhash_pod name_, char *r, char *x, char *y, char *sg, char *opt) { \ implname impl; \ - impl (HDSTR(name), DVEC(r), DVEC(x), DFLOAT(y), (ShaderGlobals *)sg, (NoiseParams *)opt); \ + ustringhash name = ustringhash_from(name_); \ + impl (name, DVEC(r), DVEC(x), DFLOAT(y), (ShaderGlobals *)sg, (NoiseParams *)opt); \ } @@ -405,45 +413,53 @@ OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvvdfvf (char *r, char *x, char #define PNOISE_IMPL_DERIV_OPT(opname,implname) \ -OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdff (char *name, char *r, char *x, float px, char *sg, char *opt) { \ +OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdff (ustringhash_pod name_, char *r, char *x, float px, char *sg, char *opt) { \ implname impl; \ - impl (HDSTR(name), DFLOAT(r), DFLOAT(x), px, (ShaderGlobals *)sg, (NoiseParams *)opt); \ + ustringhash name = ustringhash_from(name_); \ + impl (name, DFLOAT(r), DFLOAT(x), px, (ShaderGlobals *)sg, (NoiseParams *)opt); \ } \ \ -OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdfdfff (char *name, char *r, char *x, char *y, float px, float py, char *sg, char *opt) { \ +OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdfdfff (ustringhash_pod name_, char *r, char *x, char *y, float px, float py, char *sg, char *opt) { \ implname impl; \ - impl (HDSTR(name), DFLOAT(r), DFLOAT(x), DFLOAT(y), px, py, (ShaderGlobals *)sg, (NoiseParams *)opt); \ + ustringhash name = ustringhash_from(name_); \ + impl (name, DFLOAT(r), DFLOAT(x), DFLOAT(y), px, py, (ShaderGlobals *)sg, (NoiseParams *)opt); \ } \ \ -OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdvv (char *name, char *r, char *x, char *px, char *sg, char *opt) { \ +OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdvv (ustringhash_pod name_, char *r, char *x, char *px, char *sg, char *opt) { \ implname impl; \ - impl (HDSTR(name), DFLOAT(r), DVEC(x), VEC(px), (ShaderGlobals *)sg, (NoiseParams *)opt); \ + ustringhash name = ustringhash_from(name_); \ + impl (name, DFLOAT(r), DVEC(x), VEC(px), (ShaderGlobals *)sg, (NoiseParams *)opt); \ } \ \ -OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdvdfvf (char *name, char *r, char *x, char *y, char *px, float py, char *sg, char *opt) { \ +OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dfdvdfvf (ustringhash_pod name_, char *r, char *x, char *y, char *px, float py, char *sg, char *opt) { \ implname impl; \ - impl (HDSTR(name), DFLOAT(r), DVEC(x), DFLOAT(y), VEC(px), py, (ShaderGlobals *)sg, (NoiseParams *)opt); \ + ustringhash name = ustringhash_from(name_); \ + impl (name, DFLOAT(r), DVEC(x), DFLOAT(y), VEC(px), py, (ShaderGlobals *)sg, (NoiseParams *)opt); \ } \ \ \ -OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdff (char *name, char *r, char *x, float px, char *sg, char *opt) { \ +OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdff (ustringhash_pod name_, char *r, char *x, float px, char *sg, char *opt) { \ implname impl; \ - impl (HDSTR(name), DVEC(r), DFLOAT(x), px, (ShaderGlobals *)sg, (NoiseParams *)opt); \ + ustringhash name = ustringhash_from(name_); \ + impl (name, DVEC(r), DFLOAT(x), px, (ShaderGlobals *)sg, (NoiseParams *)opt); \ } \ \ -OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdfdfff (char *name, char *r, char *x, char *y, float px, float py, char *sg, char *opt) { \ +OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdfdfff (ustringhash_pod name_, char *r, char *x, char *y, float px, float py, char *sg, char *opt) { \ implname impl; \ - impl (HDSTR(name), DVEC(r), DFLOAT(x), DFLOAT(y), px, py, (ShaderGlobals *)sg, (NoiseParams *)opt); \ + ustringhash name = ustringhash_from(name_); \ + impl (name, DVEC(r), DFLOAT(x), DFLOAT(y), px, py, (ShaderGlobals *)sg, (NoiseParams *)opt); \ } \ \ -OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdvv (char *name, char *r, char *x, char *px, char *sg, char *opt) { \ +OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdvv (ustringhash_pod name_, char *r, char *x, char *px, char *sg, char *opt) { \ implname impl; \ - impl (HDSTR(name), DVEC(r), DVEC(x), VEC(px), (ShaderGlobals *)sg, (NoiseParams *)opt); \ + ustringhash name = ustringhash_from(name_); \ + impl (name, DVEC(r), DVEC(x), VEC(px), (ShaderGlobals *)sg, (NoiseParams *)opt); \ } \ \ -OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdvdfvf (char *name, char *r, char *x, char *y, char *px, float py, char *sg, char *opt) { \ +OSL_SHADEOP OSL_HOSTDEVICE void osl_ ##opname## _dvdvdfvf (ustringhash_pod name_, char *r, char *x, char *y, char *px, float py, char *sg, char *opt) { \ implname impl; \ - impl (HDSTR(name), DVEC(r), DVEC(x), DFLOAT(y), VEC(px), py, (ShaderGlobals *)sg, (NoiseParams *)opt); \ + ustringhash name = ustringhash_from(name_); \ + impl (name, DVEC(r), DVEC(x), DFLOAT(y), VEC(px), py, (ShaderGlobals *)sg, (NoiseParams *)opt); \ } @@ -471,7 +487,7 @@ struct GaborNoise { // Gabor always uses derivatives, so dual versions only OSL_HOSTDEVICE - inline void operator()(StringParam /*noisename*/, Dual2& result, + inline void operator()(ustringhash /*noisename*/, Dual2& result, const Dual2& x, ShaderGlobals* /*sg*/, const NoiseParams* opt) const { @@ -479,7 +495,7 @@ struct GaborNoise { } OSL_HOSTDEVICE - inline void operator()(StringParam /*noisename*/, Dual2& result, + inline void operator()(ustringhash /*noisename*/, Dual2& result, const Dual2& x, const Dual2& y, ShaderGlobals* /*sg*/, const NoiseParams* opt) const { @@ -487,7 +503,7 @@ struct GaborNoise { } OSL_HOSTDEVICE - inline void operator()(StringParam /*noisename*/, Dual2& result, + inline void operator()(ustringhash /*noisename*/, Dual2& result, const Dual2& p, ShaderGlobals* /*sg*/, const NoiseParams* opt) const { @@ -495,7 +511,7 @@ struct GaborNoise { } OSL_HOSTDEVICE - inline void operator()(StringParam /*noisename*/, Dual2& result, + inline void operator()(ustringhash /*noisename*/, Dual2& result, const Dual2& p, const Dual2& /*t*/, ShaderGlobals* /*sg*/, const NoiseParams* opt) const { @@ -504,7 +520,7 @@ struct GaborNoise { } OSL_HOSTDEVICE - inline void operator()(StringParam /*noisename*/, Dual2& result, + inline void operator()(ustringhash /*noisename*/, Dual2& result, const Dual2& x, ShaderGlobals* /*sg*/, const NoiseParams* opt) const { @@ -512,7 +528,7 @@ struct GaborNoise { } OSL_HOSTDEVICE - inline void operator()(StringParam /*noisename*/, Dual2& result, + inline void operator()(ustringhash /*noisename*/, Dual2& result, const Dual2& x, const Dual2& y, ShaderGlobals* /*sg*/, const NoiseParams* opt) const { @@ -520,7 +536,7 @@ struct GaborNoise { } OSL_HOSTDEVICE - inline void operator()(StringParam /*noisename*/, Dual2& result, + inline void operator()(ustringhash /*noisename*/, Dual2& result, const Dual2& p, ShaderGlobals* /*sg*/, const NoiseParams* opt) const { @@ -528,7 +544,7 @@ struct GaborNoise { } OSL_HOSTDEVICE - inline void operator()(StringParam /*noisename*/, Dual2& result, + inline void operator()(ustringhash /*noisename*/, Dual2& result, const Dual2& p, const Dual2& /*t*/, ShaderGlobals* /*sg*/, const NoiseParams* opt) const { @@ -545,7 +561,7 @@ struct GaborPNoise { // Gabor always uses derivatives, so dual versions only OSL_HOSTDEVICE - inline void operator()(StringParam /*noisename*/, Dual2& result, + inline void operator()(ustringhash /*noisename*/, Dual2& result, const Dual2& x, float px, ShaderGlobals* /*sg*/, const NoiseParams* opt) const { @@ -553,7 +569,7 @@ struct GaborPNoise { } OSL_HOSTDEVICE - inline void operator()(StringParam /*noisename*/, Dual2& result, + inline void operator()(ustringhash /*noisename*/, Dual2& result, const Dual2& x, const Dual2& y, float px, float py, ShaderGlobals* /*sg*/, const NoiseParams* opt) const @@ -562,7 +578,7 @@ struct GaborPNoise { } OSL_HOSTDEVICE - inline void operator()(StringParam /*noisename*/, Dual2& result, + inline void operator()(ustringhash /*noisename*/, Dual2& result, const Dual2& p, const Vec3& pp, ShaderGlobals* /*sg*/, const NoiseParams* opt) const { @@ -570,7 +586,7 @@ struct GaborPNoise { } OSL_HOSTDEVICE - inline void operator()(StringParam /*noisename*/, Dual2& result, + inline void operator()(ustringhash /*noisename*/, Dual2& result, const Dual2& p, const Dual2& /*t*/, const Vec3& pp, float /*tp*/, ShaderGlobals* /*sg*/, const NoiseParams* opt) const @@ -580,7 +596,7 @@ struct GaborPNoise { } OSL_HOSTDEVICE - inline void operator()(StringParam /*noisename*/, Dual2& result, + inline void operator()(ustringhash /*noisename*/, Dual2& result, const Dual2& x, float px, ShaderGlobals* /*sg*/, const NoiseParams* opt) const { @@ -588,7 +604,7 @@ struct GaborPNoise { } OSL_HOSTDEVICE - inline void operator()(StringParam /*noisename*/, Dual2& result, + inline void operator()(ustringhash /*noisename*/, Dual2& result, const Dual2& x, const Dual2& y, float px, float py, ShaderGlobals* /*sg*/, const NoiseParams* opt) const @@ -597,7 +613,7 @@ struct GaborPNoise { } OSL_HOSTDEVICE - inline void operator()(StringParam /*noisename*/, Dual2& result, + inline void operator()(ustringhash /*noisename*/, Dual2& result, const Dual2& p, const Vec3& pp, ShaderGlobals* /*sg*/, const NoiseParams* opt) const { @@ -605,7 +621,7 @@ struct GaborPNoise { } OSL_HOSTDEVICE - inline void operator()(StringParam /*noisename*/, Dual2& result, + inline void operator()(ustringhash /*noisename*/, Dual2& result, const Dual2& p, const Dual2& /*t*/, const Vec3& pp, float /*tp*/, ShaderGlobals* /*sg*/, const NoiseParams* opt) const @@ -693,39 +709,39 @@ struct GenericNoise { // dual versions -- this is always called with derivs template - OSL_HOSTDEVICE inline void operator()(StringParam name, Dual2& result, + OSL_HOSTDEVICE inline void operator()(ustringhash name, Dual2& result, const Dual2& s, ShaderGlobals* sg, const NoiseParams* opt) const { - if (name == STRING_PARAMS(uperlin) || name == STRING_PARAMS(noise)) { + if (name == Hashes::uperlin || name == Hashes::noise) { Noise noise; noise(result, s); - } else if (name == STRING_PARAMS(perlin) - || name == STRING_PARAMS(snoise)) { + } else if (name == Hashes::perlin + || name == Hashes::snoise) { SNoise snoise; snoise(result, s); - } else if (name == STRING_PARAMS(simplexnoise) - || name == STRING_PARAMS(simplex)) { + } else if (name == Hashes::simplexnoise + || name == Hashes::simplex) { SimplexNoise simplexnoise; simplexnoise(result, s); - } else if (name == STRING_PARAMS(usimplexnoise) - || name == STRING_PARAMS(usimplex)) { + } else if (name == Hashes::usimplexnoise + || name == Hashes::usimplex) { USimplexNoise usimplexnoise; usimplexnoise(result, s); - } else if (name == STRING_PARAMS(cell)) { + } else if (name == Hashes::cell) { CellNoise cellnoise; cellnoise(result.val(), s.val()); result.clear_d(); - } else if (name == STRING_PARAMS(gabor)) { + } else if (name == Hashes::gabor) { GaborNoise gnoise; gnoise(name, result, s, sg, opt); - } else if (name == STRING_PARAMS(null)) { + } else if (name == Hashes::null) { NullNoise noise; noise(result, s); - } else if (name == STRING_PARAMS(unull)) { + } else if (name == Hashes::unull) { UNullNoise noise; noise(result, s); - } else if (name == STRING_PARAMS(hash)) { + } else if (name == Hashes::hash) { HashNoise hashnoise; hashnoise(result.val(), s.val()); result.clear_d(); @@ -740,40 +756,40 @@ struct GenericNoise { } template - OSL_HOSTDEVICE inline void operator()(StringParam name, Dual2& result, + OSL_HOSTDEVICE inline void operator()(ustringhash name, Dual2& result, const Dual2& s, const Dual2& t, ShaderGlobals* sg, const NoiseParams* opt) const { - if (name == STRING_PARAMS(uperlin) || name == STRING_PARAMS(noise)) { + if (name == Hashes::uperlin || name == Hashes::noise) { Noise noise; noise(result, s, t); - } else if (name == STRING_PARAMS(perlin) - || name == STRING_PARAMS(snoise)) { + } else if (name == Hashes::perlin + || name == Hashes::snoise) { SNoise snoise; snoise(result, s, t); - } else if (name == STRING_PARAMS(simplexnoise) - || name == STRING_PARAMS(simplex)) { + } else if (name == Hashes::simplexnoise + || name == Hashes::simplex) { SimplexNoise simplexnoise; simplexnoise(result, s, t); - } else if (name == STRING_PARAMS(usimplexnoise) - || name == STRING_PARAMS(usimplex)) { + } else if (name == Hashes::usimplexnoise + || name == Hashes::usimplex) { USimplexNoise usimplexnoise; usimplexnoise(result, s, t); - } else if (name == STRING_PARAMS(cell)) { + } else if (name == Hashes::cell) { CellNoise cellnoise; cellnoise(result.val(), s.val(), t.val()); result.clear_d(); - } else if (name == STRING_PARAMS(gabor)) { + } else if (name == Hashes::gabor) { GaborNoise gnoise; gnoise(name, result, s, t, sg, opt); - } else if (name == STRING_PARAMS(null)) { + } else if (name == Hashes::null) { NullNoise noise; noise(result, s, t); - } else if (name == STRING_PARAMS(unull)) { + } else if (name == Hashes::unull) { UNullNoise noise; noise(result, s, t); - } else if (name == STRING_PARAMS(hash)) { + } else if (name == Hashes::hash) { HashNoise hashnoise; hashnoise(result.val(), s.val(), t.val()); result.clear_d(); @@ -801,24 +817,24 @@ struct GenericPNoise { template OSL_HOSTDEVICE inline void - operator()(StringParam name, Dual2& result, const Dual2& s, + operator()(ustringhash name, Dual2& result, const Dual2& s, const S& sp, ShaderGlobals* sg, const NoiseParams* opt) const { - if (name == STRING_PARAMS(uperlin) || name == STRING_PARAMS(noise)) { + if (name == Hashes::uperlin || name == Hashes::noise) { PeriodicNoise noise; noise(result, s, sp); - } else if (name == STRING_PARAMS(perlin) - || name == STRING_PARAMS(snoise)) { + } else if (name == Hashes::perlin + || name == Hashes::snoise) { PeriodicSNoise snoise; snoise(result, s, sp); - } else if (name == STRING_PARAMS(cell)) { + } else if (name == Hashes::cell) { PeriodicCellNoise cellnoise; cellnoise(result.val(), s.val(), sp); result.clear_d(); - } else if (name == STRING_PARAMS(gabor)) { + } else if (name == Hashes::gabor) { GaborPNoise gnoise; gnoise(name, result, s, sp, sg, opt); - } else if (name == STRING_PARAMS(hash)) { + } else if (name == Hashes::hash) { PeriodicHashNoise hashnoise; hashnoise(result.val(), s.val(), sp); result.clear_d(); @@ -834,25 +850,25 @@ struct GenericPNoise { template OSL_HOSTDEVICE inline void - operator()(StringParam name, Dual2& result, const Dual2& s, + operator()(ustringhash name, Dual2& result, const Dual2& s, const Dual2& t, const S& sp, const T& tp, ShaderGlobals* sg, const NoiseParams* opt) const { - if (name == STRING_PARAMS(uperlin) || name == STRING_PARAMS(noise)) { + if (name == Hashes::uperlin || name == Hashes::noise) { PeriodicNoise noise; noise(result, s, t, sp, tp); - } else if (name == STRING_PARAMS(perlin) - || name == STRING_PARAMS(snoise)) { + } else if (name == Hashes::perlin + || name == Hashes::snoise) { PeriodicSNoise snoise; snoise(result, s, t, sp, tp); - } else if (name == STRING_PARAMS(cell)) { + } else if (name == Hashes::cell) { PeriodicCellNoise cellnoise; cellnoise(result.val(), s.val(), t.val(), sp, tp); result.clear_d(); - } else if (name == STRING_PARAMS(gabor)) { + } else if (name == Hashes::gabor) { GaborPNoise gnoise; gnoise(name, result, s, t, sp, tp, sg, opt); - } else if (name == STRING_PARAMS(hash)) { + } else if (name == Hashes::hash) { PeriodicHashNoise hashnoise; hashnoise(result.val(), s.val(), t.val(), sp, tp); result.clear_d(); diff --git a/src/liboslexec/opspline.cpp b/src/liboslexec/opspline.cpp index f5af4140b..eed07933b 100644 --- a/src/liboslexec/opspline.cpp +++ b/src/liboslexec/opspline.cpp @@ -19,8 +19,8 @@ #include "oslexec_pvt.h" #include -#include #include +#include #include #include "splineimpl.h" @@ -31,102 +31,110 @@ namespace pvt { OSL_SHADEOP OSL_HOSTDEVICE void -osl_spline_fff(void* out, const char* spline_, void* x, void* knots, +osl_spline_fff(void* out, ustringhash_pod spline_, void* x, void* knots, int knot_count, int knot_arraylen) { - Spline::SplineInterp::create(HDSTR(spline_)) + ustringhash spline = ustringhash_from(spline_); + Spline::SplineInterp::create(spline) .evaluate(*(float*)out, *(float*)x, (float*)knots, knot_count, knot_arraylen); } OSL_SHADEOP OSL_HOSTDEVICE void -osl_spline_dfdfdf(void* out, const char* spline_, void* x, void* knots, +osl_spline_dfdfdf(void* out, ustringhash_pod spline_, void* x, void* knots, int knot_count, int knot_arraylen) { - Spline::SplineInterp::create(HDSTR(spline_)) + ustringhash spline = ustringhash_from(spline_); + Spline::SplineInterp::create(spline) .evaluate, Dual2, Dual2, float, true>( DFLOAT(out), DFLOAT(x), (float*)knots, knot_count, knot_arraylen); } OSL_SHADEOP OSL_HOSTDEVICE void -osl_spline_dffdf(void* out, const char* spline_, void* x, void* knots, +osl_spline_dffdf(void* out, ustringhash_pod spline_, void* x, void* knots, int knot_count, int knot_arraylen) { - Spline::SplineInterp::create(HDSTR(spline_)) + ustringhash spline = ustringhash_from(spline_); + Spline::SplineInterp::create(spline) .evaluate, float, Dual2, float, true>( DFLOAT(out), *(float*)x, (float*)knots, knot_count, knot_arraylen); } OSL_SHADEOP OSL_HOSTDEVICE void -osl_spline_dfdff(void* out, const char* spline_, void* x, void* knots, +osl_spline_dfdff(void* out, ustringhash_pod spline_, void* x, void* knots, int knot_count, int knot_arraylen) { - Spline::SplineInterp::create(HDSTR(spline_)) + ustringhash spline = ustringhash_from(spline_); + Spline::SplineInterp::create(spline) .evaluate, Dual2, float, float, false>( DFLOAT(out), DFLOAT(x), (float*)knots, knot_count, knot_arraylen); } OSL_SHADEOP OSL_HOSTDEVICE void -osl_spline_vfv(void* out, const char* spline_, void* x, void* knots, +osl_spline_vfv(void* out, ustringhash_pod spline_, void* x, void* knots, int knot_count, int knot_arraylen) { - Spline::SplineInterp::create(HDSTR(spline_)) + ustringhash spline = ustringhash_from(spline_); + Spline::SplineInterp::create(spline) .evaluate(*(Vec3*)out, *(float*)x, (Vec3*)knots, knot_count, knot_arraylen); } OSL_SHADEOP OSL_HOSTDEVICE void -osl_spline_dvdfv(void* out, const char* spline_, void* x, void* knots, +osl_spline_dvdfv(void* out, ustringhash_pod spline_, void* x, void* knots, int knot_count, int knot_arraylen) { - Spline::SplineInterp::create(HDSTR(spline_)) + ustringhash spline = ustringhash_from(spline_); + Spline::SplineInterp::create(spline) .evaluate, Dual2, Vec3, Vec3, false>( DVEC(out), DFLOAT(x), (Vec3*)knots, knot_count, knot_arraylen); } OSL_SHADEOP OSL_HOSTDEVICE void -osl_spline_dvfdv(void* out, const char* spline_, void* x, void* knots, +osl_spline_dvfdv(void* out, ustringhash_pod spline_, void* x, void* knots, int knot_count, int knot_arraylen) { - Spline::SplineInterp::create(HDSTR(spline_)) + ustringhash spline = ustringhash_from(spline_); + Spline::SplineInterp::create(spline) .evaluate, float, Dual2, Vec3, true>( DVEC(out), *(float*)x, (Vec3*)knots, knot_count, knot_arraylen); } OSL_SHADEOP OSL_HOSTDEVICE void -osl_spline_dvdfdv(void* out, const char* spline_, void* x, void* knots, +osl_spline_dvdfdv(void* out, ustringhash_pod spline_, void* x, void* knots, int knot_count, int knot_arraylen) { - Spline::SplineInterp::create(HDSTR(spline_)) + ustringhash spline = ustringhash_from(spline_); + Spline::SplineInterp::create(spline) .evaluate, Dual2, Dual2, Vec3, true>( DVEC(out), DFLOAT(x), (Vec3*)knots, knot_count, knot_arraylen); } OSL_SHADEOP OSL_HOSTDEVICE void -osl_splineinverse_fff(void* out, const char* spline_, void* x, void* knots, +osl_splineinverse_fff(void* out, ustringhash_pod spline_, void* x, void* knots, int knot_count, int knot_arraylen) { // Version with no derivs - Spline::SplineInterp::create(HDSTR(spline_)) - .inverse(*(float*)out, *(float*)x, (float*)knots, knot_count, - knot_arraylen); + ustringhash spline = ustringhash_from(spline_); + Spline::SplineInterp::create(spline).inverse( + *(float*)out, *(float*)x, (float*)knots, knot_count, knot_arraylen); } OSL_SHADEOP OSL_HOSTDEVICE void -osl_splineinverse_dfdff(void* out, const char* spline_, void* x, void* knots, - int knot_count, int knot_arraylen) +osl_splineinverse_dfdff(void* out, ustringhash_pod spline_, void* x, + void* knots, int knot_count, int knot_arraylen) { // x has derivs, so return derivs as well - Spline::SplineInterp::create(HDSTR(spline_)) - .inverse>(DFLOAT(out), DFLOAT(x), (float*)knots, - knot_count, knot_arraylen); + ustringhash spline = ustringhash_from(spline_); + Spline::SplineInterp::create(spline).inverse>( + DFLOAT(out), DFLOAT(x), (float*)knots, knot_count, knot_arraylen); } OSL_SHADEOP OSL_HOSTDEVICE void -osl_splineinverse_dfdfdf(void* out, const char* spline_, void* x, void* knots, - int knot_count, int knot_arraylen) +osl_splineinverse_dfdfdf(void* out, ustringhash_pod spline_, void* x, + void* knots, int knot_count, int knot_arraylen) { // Ignore knot derivatives osl_splineinverse_dfdff(out, spline_, x, (float*)knots, knot_count, @@ -134,8 +142,8 @@ osl_splineinverse_dfdfdf(void* out, const char* spline_, void* x, void* knots, } OSL_SHADEOP OSL_HOSTDEVICE void -osl_splineinverse_dffdf(void* out, const char* spline_, void* x, void* knots, - int knot_count, int knot_arraylen) +osl_splineinverse_dffdf(void* out, ustringhash_pod spline_, void* x, + void* knots, int knot_count, int knot_arraylen) { // Ignore knot derivs float outtmp = 0; diff --git a/src/liboslexec/opstring.cpp b/src/liboslexec/opstring.cpp index 50c7fa206..e4d41ce5a 100644 --- a/src/liboslexec/opstring.cpp +++ b/src/liboslexec/opstring.cpp @@ -26,11 +26,17 @@ namespace pvt { // Only define 2-arg version of concat, sort it out upstream -OSL_SHADEOP const char* -osl_concat_sss(const char* s, const char* t) +OSL_SHADEOP ustringhash_pod +osl_concat_sss(ustringhash_pod s_, ustringhash_pod t_) { - size_t sl = USTR(s).length(); - size_t tl = USTR(t).length(); + ustringhash s_uh = ustringhash_from(s_); + ustringhash t_uh = ustringhash_from(t_); + + ustring s = ustring_from(s_uh); + ustring t = ustring_from(t_uh); + + size_t sl = s.size(); + size_t tl = t.size(); size_t len = sl + tl; std::unique_ptr heap_buf; char local_buf[256]; @@ -39,38 +45,43 @@ osl_concat_sss(const char* s, const char* t) heap_buf.reset(new char[len]); buf = heap_buf.get(); } - memcpy(buf, s, sl); - memcpy(buf + sl, t, tl); - return ustring(buf, len).c_str(); + memcpy(buf, s.c_str(), sl); + memcpy(buf + sl, t.c_str(), tl); + ustring result(buf, len); + + return result.uhash().hash(); } OSL_SHADEOP int -osl_strlen_is(const char* s) +osl_strlen_is(ustringhash_pod s_) { - return (int)USTR(s).length(); + auto s = ustring_from(s_); + return (int)s.length(); } OSL_SHADEOP int -osl_hash_is(const char* s) +osl_hash_is(ustringhash_pod s_) { - return (int)USTR(s).hash(); + auto s = ustring_from(s_); + return (int)s.hash(); } OSL_SHADEOP int -osl_getchar_isi(const char* str, int index) +osl_getchar_isi(ustringhash_pod str_, int index) { - return str && unsigned(index) < USTR(str).length() ? str[index] : 0; + auto str = ustring_from(str_); + return str.data() && unsigned(index) < str.length() ? str[index] : 0; } OSL_SHADEOP int -osl_startswith_iss(const char* s_, const char* substr_) +osl_startswith_iss(ustringhash_pod s_, ustringhash_pod substr_) { - ustring substr(USTR(substr_)); + auto substr = ustring_from(substr_); size_t substr_len = substr.length(); if (substr_len == 0) // empty substr always matches return 1; - ustring s(USTR(s_)); + auto s = ustring_from(s_); size_t s_len = s.length(); if (substr_len > s_len) // longer needle than haystack can't return 0; // match (including empty s) @@ -78,13 +89,13 @@ osl_startswith_iss(const char* s_, const char* substr_) } OSL_SHADEOP int -osl_endswith_iss(const char* s_, const char* substr_) +osl_endswith_iss(ustringhash_pod s_, ustringhash_pod substr_) { - ustring substr(USTR(substr_)); + auto substr = ustring_from(substr_); size_t substr_len = substr.length(); if (substr_len == 0) // empty substr always matches return 1; - ustring s(USTR(s_)); + auto s = ustring_from(s_); size_t s_len = s.length(); if (substr_len > s_len) // longer needle than haystack can't return 0; // match (including empty s) @@ -93,41 +104,47 @@ osl_endswith_iss(const char* s_, const char* substr_) } OSL_SHADEOP int -osl_stoi_is(const char* str) +osl_stoi_is(ustringhash_pod str_) { - return str ? Strutil::from_string(str) : 0; + auto str = ustring_from(str_); + return str.data() ? Strutil::from_string(str) : 0; } OSL_SHADEOP float -osl_stof_fs(const char* str) +osl_stof_fs(ustringhash_pod str_) { - return str ? Strutil::from_string(str) : 0.0f; + auto str = ustring_from(str_); + return str.data() ? Strutil::from_string(str) : 0.0f; } -OSL_SHADEOP const char* -osl_substr_ssii(const char* s_, int start, int length) +OSL_SHADEOP ustringhash_pod +osl_substr_ssii(ustringhash_pod s_, int start, int length) { - ustring s(USTR(s_)); + auto s = ustring_from(s_); int slen = int(s.length()); if (slen == 0) - return NULL; // No substring of empty string + return ustringhash_pod(); // No substring of empty string int b = start; if (b < 0) b += slen; b = Imath::clamp(b, 0, slen); - return ustring(s, b, Imath::clamp(length, 0, slen)).c_str(); + return ustringhash_from(ustring(s, b, Imath::clamp(length, 0, slen))).hash(); } OSL_SHADEOP int -osl_regex_impl(void* sg_, const char* subject_, void* results, int nresults, - const char* pattern, int fullmatch) -{ - ShaderGlobals* sg = (ShaderGlobals*)sg_; - ShadingContext* ctx = sg->context; - const std::string& subject(ustring::from_unique(subject_).string()); +osl_regex_impl(void* sg_, ustringhash_pod subject_, void* results, int nresults, + ustringhash_pod pattern_, int fullmatch) +{ + ShaderGlobals* sg = (ShaderGlobals*)sg_; + ShadingContext* ctx = sg->context; + ustringhash subject_hash = ustringhash_from(subject_); + ustring subject_ustr = ustring_from(subject_hash); + const std::string& subject(subject_ustr.string()); + ustringhash pattern_hash = ustringhash_from(pattern_); + ustring pattern = ustring_from(pattern_hash); std::match_results mresults; - const std::regex& regex(ctx->find_regex(USTR(pattern))); + const std::regex& regex(ctx->find_regex(pattern)); if (nresults > 0) { std::string::const_iterator start = subject.begin(); int res = fullmatch ? std::regex_match(subject, mresults, regex) @@ -140,7 +157,7 @@ osl_regex_impl(void* sg_, const char* subject_, void* results, int nresults, else m[r] = mresults[r / 2].second - start; } else { - m[r] = USTR(pattern).length(); + m[r] = pattern.length(); } } return res; @@ -152,28 +169,31 @@ osl_regex_impl(void* sg_, const char* subject_, void* results, int nresults, // TODO: transition format to from llvm_gen_printf_legacy // to llvm_gen_print_fmt by providing an osl_gen_formatfmt here -OSL_SHADEOP const char* -osl_format(const char* format_str, ...) +OSL_SHADEOP ustringhash_pod +osl_format(ustringhash_pod format_str_, ...) { + auto format_str = ustring_from(format_str_); va_list args; - va_start(args, format_str); - std::string s = Strutil::vsprintf(format_str, args); + va_start(args, format_str_); + std::string s = Strutil::vsprintf(format_str.c_str(), args); va_end(args); - return ustring(s).c_str(); + return ustring(s).hash(); } OSL_SHADEOP int -osl_split(const char* str, ustring* results, const char* sep, int maxsplit, - int resultslen) +osl_split(ustringhash_pod str_, ustringhash_pod* results, ustringhash_pod sep_, + int maxsplit, int resultslen) { + auto str = ustring_from(str_); + auto sep = ustring_from(sep_); maxsplit = OIIO::clamp(maxsplit, 0, resultslen); std::vector splits; - Strutil::split(USTR(str).string(), splits, USTR(sep).string(), maxsplit); + Strutil::split(str.string(), splits, sep.string(), maxsplit); int n = std::min(maxsplit, (int)splits.size()); for (int i = 0; i < n; ++i) - results[i] = ustring(splits[i]); + results[i] = ustring(splits[i]).uhash().hash(); return n; } @@ -187,28 +207,42 @@ osl_split(const char* str, ustring* results, const char* sep, int maxsplit, // compliant renderers have adapted. OSL_SHADEOP void -osl_printf(ShaderGlobals* sg, const char* format_str, ...) +osl_printf(ShaderGlobals* sg, OSL::ustringhash_pod format_str, ...) { } OSL_SHADEOP void -osl_error(ShaderGlobals* sg, const char* format_str, ...) +osl_error(ShaderGlobals* sg, OSL::ustringhash_pod format_str, ...) { } OSL_SHADEOP void -osl_warning(ShaderGlobals* sg, const char* format_str, ...) +osl_warning(ShaderGlobals* sg, OSL::ustringhash_pod format_str, ...) { } OSL_SHADEOP void -osl_fprintf(ShaderGlobals* /*sg*/, const char* filename, const char* format_str, - ...) +osl_fprintf(ShaderGlobals* /*sg*/, OSL::ustringhash_pod filename, + OSL::ustringhash_pod format_str, ...) { } //////// +OSL_RSOP OSL::ustringhash_pod +osl_formatfmt(OpaqueExecContextPtr exec_ctx, + OSL::ustringhash_pod fmt_specification, int32_t arg_count, + void* arg_types, uint32_t arg_values_size, uint8_t* arg_values) +{ + auto encoded_types = reinterpret_cast(arg_types); + + std::string decoded_str; + OSL::decode_message(fmt_specification, arg_count, encoded_types, arg_values, + decoded_str); + return ustring(decoded_str).hash(); +} + + } // end namespace pvt OSL_NAMESPACE_EXIT diff --git a/src/liboslexec/optexture.cpp b/src/liboslexec/optexture.cpp index 5521abe8a..27ce4277e 100644 --- a/src/liboslexec/optexture.cpp +++ b/src/liboslexec/optexture.cpp @@ -43,33 +43,43 @@ osl_texture_set_firstchannel(void* opt, int x) } OSL_SHADEOP int -osl_texture_decode_wrapmode(ustring_pod name) +osl_texture_decode_wrapmode(ustringhash_pod name_) { - return OIIO::TextureOpt::decode_wrapmode(ustring_from(USTR(name))); + ustringhash name_hash = ustringhash_from(name_); + ustring name = ustring_from(name_hash); + return OIIO::TextureOpt::decode_wrapmode(name); } OSL_SHADEOP void -osl_texture_set_swrap(void* opt, ustring_pod x) +osl_texture_set_swrap(void* opt, ustringhash_pod x_) { - ((TextureOpt*)opt)->swrap = TextureOpt::decode_wrapmode(USTR(x)); + ustringhash x_hash = ustringhash_from(x_); + ustring x = ustring_from(x_hash); + ((TextureOpt*)opt)->swrap = TextureOpt::decode_wrapmode(x); } OSL_SHADEOP void -osl_texture_set_twrap(void* opt, ustring_pod x) +osl_texture_set_twrap(void* opt, ustringhash_pod x_) { - ((TextureOpt*)opt)->twrap = TextureOpt::decode_wrapmode(USTR(x)); + ustringhash x_hash = ustringhash_from(x_); + ustring x = ustring_from(x_hash); + ((TextureOpt*)opt)->twrap = TextureOpt::decode_wrapmode(x); } OSL_SHADEOP void -osl_texture_set_rwrap(void* opt, ustring_pod x) +osl_texture_set_rwrap(void* opt, ustringhash_pod x_) { - ((TextureOpt*)opt)->rwrap = TextureOpt::decode_wrapmode(USTR(x)); + ustringhash x_hash = ustringhash_from(x_); + ustring x = ustring_from(x_hash); + ((TextureOpt*)opt)->rwrap = TextureOpt::decode_wrapmode(x); } OSL_SHADEOP void -osl_texture_set_stwrap(void* opt, ustring_pod x) +osl_texture_set_stwrap(void* opt, ustringhash_pod x_) { - TextureOpt::Wrap code = TextureOpt::decode_wrapmode(USTR(x)); + ustringhash x_hash = ustringhash_from(x_); + ustring x = ustring_from(x_hash); + TextureOpt::Wrap code = TextureOpt::decode_wrapmode(x); ((TextureOpt*)opt)->swrap = code; ((TextureOpt*)opt)->twrap = code; } @@ -162,15 +172,19 @@ osl_texture_set_time(void* opt, float x) } OSL_SHADEOP int -osl_texture_decode_interpmode(ustring_pod name) +osl_texture_decode_interpmode(ustringhash_pod name_) { - return tex_interp_to_code(ustring_from(USTR(name))); + ustringhash name_hash = ustringhash_from(name_); + ustring name = ustring_from(name_hash); + return tex_interp_to_code(name); } OSL_SHADEOP void -osl_texture_set_interp(void* opt, ustring_pod modename) +osl_texture_set_interp(void* opt, ustringhash_pod modename_) { - int mode = tex_interp_to_code(ustring_from(USTR(modename))); + ustringhash modename_hash = ustringhash_from(modename_); + ustring modename = ustring_from(modename_hash); + int mode = tex_interp_to_code(modename); if (mode >= 0) ((TextureOpt*)opt)->interpmode = (TextureOpt::InterpMode)mode; } @@ -189,9 +203,11 @@ osl_texture_set_subimage(void* opt, int subimage) OSL_SHADEOP void -osl_texture_set_subimagename(void* opt, ustring_pod subimagename) +osl_texture_set_subimagename(void* opt, ustringhash_pod subimagename_) { - ((TextureOpt*)opt)->subimagename = ustring_from(USTR(subimagename)); + ustringhash subimagename_hash = ustringhash_from(subimagename_); + ustring subimagename = ustring_from(subimagename_hash); + ((TextureOpt*)opt)->subimagename = subimagename; } OSL_SHADEOP void @@ -212,10 +228,10 @@ osl_texture_set_missingcolor_alpha(void* opt, int alphaindex, OSL_SHADEOP int -osl_texture(void* sg_, const char* name, void* handle, void* opt_, float s, +osl_texture(void* sg_, ustringhash_pod name_, void* handle, void* opt_, float s, float t, float dsdx, float dtdx, float dsdy, float dtdy, int chans, void* result, void* dresultdx, void* dresultdy, void* alpha, - void* dalphadx, void* dalphady, ustringrep* errormessage) + void* dalphadx, void* dalphady, ustringhash_pod* errormessage) { ShaderGlobals* sg = (ShaderGlobals*)sg_; TextureOpt* opt = (TextureOpt*)opt_; @@ -224,11 +240,14 @@ osl_texture(void* sg_, const char* name, void* handle, void* opt_, float s, // and ensure that they're being put in aligned memory. OIIO::simd::vfloat4 result_simd, dresultds_simd, dresultdt_simd; ustringhash em; - bool ok = sg->renderer->texture( - USTR(name).uhash(), (TextureSystem::TextureHandle*)handle, - sg->context->texture_thread_info(), *opt, sg, s, t, dsdx, dtdx, dsdy, - dtdy, 4, (float*)&result_simd, derivs ? (float*)&dresultds_simd : NULL, - derivs ? (float*)&dresultdt_simd : NULL, errormessage ? &em : nullptr); + ustringhash name = ustringhash_from(name_); + bool ok = sg->renderer->texture(name, (TextureSystem::TextureHandle*)handle, + sg->context->texture_thread_info(), *opt, + sg, s, t, dsdx, dtdx, dsdy, dtdy, 4, + (float*)&result_simd, + derivs ? (float*)&dresultds_simd : NULL, + derivs ? (float*)&dresultdt_simd : NULL, + errormessage ? &em : nullptr); for (int i = 0; i < chans; ++i) ((float*)result)[i] = result_simd[i]; @@ -256,18 +275,17 @@ osl_texture(void* sg_, const char* name, void* handle, void* opt_, float s, } if (errormessage) - *errormessage = ok ? ustringrep_from(Strings::_emptystring_) - : ustringrep_from(em); + *errormessage = ok ? ustringhash {}.hash() : em.hash(); return ok; } OSL_SHADEOP int -osl_texture3d(void* sg_, const char* name, void* handle, void* opt_, void* P_, - void* dPdx_, void* dPdy_, void* dPdz_, int chans, void* result, - void* dresultdx, void* dresultdy, void* alpha, void* dalphadx, - void* dalphady, ustringrep* errormessage) +osl_texture3d(void* sg_, ustringhash_pod name_, void* handle, void* opt_, + void* P_, void* dPdx_, void* dPdy_, void* dPdz_, int chans, + void* result, void* dresultdx, void* dresultdy, void* alpha, + void* dalphadx, void* dalphady, ustringhash_pod* errormessage) { const Vec3& P(*(Vec3*)P_); const Vec3& dPdx(*(Vec3*)dPdx_); @@ -284,13 +302,15 @@ osl_texture3d(void* sg_, const char* name, void* handle, void* opt_, void* P_, OIIO::simd::vfloat4 result_simd, dresultds_simd, dresultdt_simd, dresultdr_simd; ustringhash em; - bool ok = sg->renderer->texture3d( - USTR(name).uhash(), (TextureSystem::TextureHandle*)handle, - sg->context->texture_thread_info(), *opt, sg, P, dPdx, dPdy, dPdz, 4, - (float*)&result_simd, derivs ? (float*)&dresultds_simd : nullptr, - derivs ? (float*)&dresultdt_simd : nullptr, - derivs ? (float*)&dresultdr_simd : nullptr, - errormessage ? &em : nullptr); + ustringhash name = ustringhash_from(name_); + bool ok + = sg->renderer->texture3d(name, (TextureSystem::TextureHandle*)handle, + sg->context->texture_thread_info(), *opt, sg, + P, dPdx, dPdy, dPdz, 4, (float*)&result_simd, + derivs ? (float*)&dresultds_simd : nullptr, + derivs ? (float*)&dresultdt_simd : nullptr, + derivs ? (float*)&dresultdr_simd : nullptr, + errormessage ? &em : nullptr); for (int i = 0; i < chans; ++i) ((float*)result)[i] = result_simd[i]; @@ -318,18 +338,17 @@ osl_texture3d(void* sg_, const char* name, void* handle, void* opt_, void* P_, } if (errormessage) - *errormessage = ok ? ustringrep_from(Strings::_emptystring_) - : ustringrep_from(em); + *errormessage = ok ? ustringhash {}.hash() : em.hash(); return ok; } OSL_SHADEOP int -osl_environment(void* sg_, const char* name, void* handle, void* opt_, void* R_, - void* dRdx_, void* dRdy_, int chans, void* result, +osl_environment(void* sg_, ustringhash_pod name_, void* handle, void* opt_, + void* R_, void* dRdx_, void* dRdy_, int chans, void* result, void* dresultdx, void* dresultdy, void* alpha, void* dalphadx, - void* dalphady, ustringrep* errormessage) + void* dalphady, ustringhash_pod* errormessage) { const Vec3& R(*(Vec3*)R_); const Vec3& dRdx(*(Vec3*)dRdx_); @@ -340,12 +359,12 @@ osl_environment(void* sg_, const char* name, void* handle, void* opt_, void* R_, // and ensure that they're being put in aligned memory. OIIO::simd::vfloat4 local_result; ustringhash em; - bool ok = sg->renderer->environment(USTR(name).uhash(), - (TextureSystem::TextureHandle*)handle, - sg->context->texture_thread_info(), - *opt, sg, R, dRdx, dRdy, 4, - (float*)&local_result, NULL, NULL, - errormessage ? &em : nullptr); + ustringhash name = ustringhash_from(name_); + bool ok + = sg->renderer->environment(name, (TextureSystem::TextureHandle*)handle, + sg->context->texture_thread_info(), *opt, + sg, R, dRdx, dRdy, 4, (float*)&local_result, + NULL, NULL, errormessage ? &em : nullptr); for (int i = 0; i < chans; ++i) ((float*)result)[i] = local_result[i]; @@ -373,17 +392,16 @@ osl_environment(void* sg_, const char* name, void* handle, void* opt_, void* R_, } if (errormessage) - *errormessage = ok ? ustringrep_from(Strings::_emptystring_) - : ustringrep_from(em); + *errormessage = ok ? ustringhash {}.hash() : em.hash(); return ok; } OSL_SHADEOP int -osl_get_textureinfo(void* sg_, const char* name, void* handle, void* dataname, - int type, int arraylen, int aggregate, void* data, - ustringrep* errormessage) +osl_get_textureinfo(void* sg_, ustringhash_pod name_, void* handle, + ustringhash_pod dataname_, int type, int arraylen, + int aggregate, void* data, ustringhash_pod* errormessage) { // recreate TypeDesc TypeDesc typedesc; @@ -394,22 +412,24 @@ osl_get_textureinfo(void* sg_, const char* name, void* handle, void* dataname, ShaderGlobals* sg = (ShaderGlobals*)sg_; ustringhash em; - bool ok = sg->renderer->get_texture_info( - USTR(name).uhash(), (RendererServices::TextureHandle*)handle, - sg->context->texture_thread_info(), sg, 0 /*FIXME-ptex*/, - USTR(dataname).uhash(), typedesc, data, errormessage ? &em : nullptr); + ustringhash name = ustringhash_from(name_); + ustringhash dataname = ustringhash_from(dataname_); + bool ok = sg->renderer->get_texture_info( + name, (RendererServices::TextureHandle*)handle, + sg->context->texture_thread_info(), sg, 0 /*FIXME-ptex*/, dataname, + typedesc, data, errormessage ? &em : nullptr); if (errormessage) - *errormessage = ok ? ustringrep_from(Strings::_emptystring_) - : ustringrep_from(em); + *errormessage = ok ? ustringhash {}.hash() : em.hash(); return ok; } OSL_SHADEOP int -osl_get_textureinfo_st(void* sg_, const char* name, void* handle, float s, - float t, void* dataname, int type, int arraylen, - int aggregate, void* data, ustringrep* errormessage) +osl_get_textureinfo_st(void* sg_, ustringhash_pod name_, void* handle, float s, + float t, ustringhash_pod dataname_, int type, + int arraylen, int aggregate, void* data, + ustringhash_pod* errormessage) { // recreate TypeDesc TypeDesc typedesc; @@ -420,13 +440,14 @@ osl_get_textureinfo_st(void* sg_, const char* name, void* handle, float s, ShaderGlobals* sg = (ShaderGlobals*)sg_; ustringhash em; - bool ok = sg->renderer->get_texture_info( - USTR(name).uhash(), (RendererServices::TextureHandle*)handle, s, t, - sg->context->texture_thread_info(), sg, 0 /*FIXME-ptex*/, - USTR(dataname).uhash(), typedesc, data, errormessage ? &em : nullptr); + ustringhash name = ustringhash_from(name_); + ustringhash dataname = ustringhash_from(dataname_); + bool ok = sg->renderer->get_texture_info( + name, (RendererServices::TextureHandle*)handle, s, t, + sg->context->texture_thread_info(), sg, 0 /*FIXME-ptex*/, dataname, + typedesc, data, errormessage ? &em : nullptr); if (errormessage) - *errormessage = ok ? ustringrep_from(Strings::_emptystring_) - : ustringrep_from(em); + *errormessage = ok ? ustringhash {}.hash() : em.hash(); return ok; } @@ -465,9 +486,9 @@ osl_trace_set_shade(void* opt, int x) OSL_SHADEOP void -osl_trace_set_traceset(void* opt, const char* x) +osl_trace_set_traceset(void* opt, const ustringhash_pod x) { - ((RendererServices::TraceOpt*)opt)->traceset = USTR(x); + ((RendererServices::TraceOpt*)opt)->traceset = ustring_from(x); } diff --git a/src/liboslexec/oslexec_pvt.h b/src/liboslexec/oslexec_pvt.h index 740304962..af5d438da 100644 --- a/src/liboslexec/oslexec_pvt.h +++ b/src/liboslexec/oslexec_pvt.h @@ -22,7 +22,7 @@ #endif #ifdef __CUDACC__ -# include "string_hash.h" +# include #endif #include @@ -94,7 +94,7 @@ struct ConnectedParam; OSL_DLL_EXPORT void print_closure(std::ostream& out, const ClosureColor* closure, - ShadingSystemImpl* ss); + ShadingSystemImpl* ss, bool treat_ustrings_as_hash); /// Signature of the function that LLVM generates to run the shader /// group. @@ -249,24 +249,12 @@ struct AttributeNeeded { // Handy re-casting macros -inline ustringrep +inline ustring USTR(ustring_pod s) noexcept { - return OSL::bitcast(s); -} -inline ustringrep -USTREP(ustring_pod s) noexcept -{ - return OSL::bitcast(s); - // return *((ustringrep*)&s); + return OSL::bitcast(s); } -// Get rid of this one soon! -inline ustringrep -USTR(const void* s) noexcept -{ - return OSL::bitcast(s); -} #define MAT(m) (*(Matrix44*)m) #define VEC(v) (*(Vec3*)v) @@ -685,7 +673,7 @@ class ShadingSystemImpl { bool allow_shader_replacement() const { return m_allow_shader_replacement; } ustring commonspace_synonym() const { - return m_shading_state_uniform.m_commonspace_synonym; + return ustring_from(m_shading_state_uniform.m_commonspace_synonym); } bool llvm_jit_fma() const { return m_llvm_jit_fma; } @@ -745,8 +733,6 @@ class ShadingSystemImpl { return m_optix_force_inline_thresh; } - /// Set the current color space. - bool set_colorspace(ustring colorspace); OSLEXECPUBLIC int raytype_bit(ustring name); @@ -1445,16 +1431,18 @@ class ShaderInstance { /// symbols? bool empty_instance() const { - return (symbols().size() == 0 - && (ops().size() == 0 || + return ( + symbols().size() == 0 + && (ops().size() == 0 || #ifdef __CUDA_ARCH__ - (ops().size() == 1 - && UStringHash::Hash(ops()[0].opname().c_str()) - == STRING_PARAMS(end)) + // TODO: is this ever run on a device, why special case it? + (ops().size() == 1 + && ustringhash_from(OSL::strhash(ops()[0].opname().c_str())) + == Hashes::end) #else - (ops().size() == 1 && ops()[0].opname() == Strings::end) + (ops().size() == 1 && ops()[0].opname() == Strings::end) #endif - )); + )); } /// Make our own version of the code and args from the master. @@ -2369,7 +2357,8 @@ class OSLEXECPUBLIC ShadingContext { int dict_next(int nodeID); /// Look up an attribute of the given dictionary node. If /// attribname is "", return the value of the node itself. - int dict_value(int nodeID, ustring attribname, TypeDesc type, void* data); + int dict_value(int nodeID, ustring attribname, TypeDesc type, void* data, + bool treat_ustrings_as_hash); bool osl_get_attribute(ShaderGlobals* sg, void* objdata, int dest_derivs, ustringhash obj_name, ustringhash attr_name, @@ -2420,8 +2409,8 @@ class OSLEXECPUBLIC ShadingContext { } template - bool ocio_transform(StringParam fromspace, StringParam tospace, - const Color& C, Color& Cout); + bool ocio_transform(ustring fromspace, ustring tospace, const Color& C, + Color& Cout); void incr_layers_executed() { @@ -2588,22 +2577,22 @@ class OSLEXECPUBLIC ShadingContext { }; - -OSL_HOSTDEVICE +#ifndef __CUDACC__ inline int -tex_interp_to_code(StringParam modename) +tex_interp_to_code(ustring modename) { int mode = -1; - if (modename == STRING_PARAMS(smartcubic)) + if (modename == Strings::smartcubic) mode = TextureOpt::InterpSmartBicubic; - else if (modename == STRING_PARAMS(linear)) + else if (modename == Strings::linear) mode = TextureOpt::InterpBilinear; - else if (modename == STRING_PARAMS(cubic)) + else if (modename == Strings::cubic) mode = TextureOpt::InterpBicubic; - else if (modename == STRING_PARAMS(closest)) + else if (modename == Strings::closest) mode = TextureOpt::InterpClosest; return mode; } +#endif diff --git a/src/liboslexec/pointcloud.cpp b/src/liboslexec/pointcloud.cpp index 273f6e105..476bbc27b 100644 --- a/src/liboslexec/pointcloud.cpp +++ b/src/liboslexec/pointcloud.cpp @@ -58,7 +58,7 @@ PointCloud::PointCloud(ustringhash filename, for (int i = 0, e = m_partio_cloud->numAttributes(); i < e; ++i) { Partio::ParticleAttribute* a = new Partio::ParticleAttribute(); m_partio_cloud->attributeInfo(i, *a); - m_attributes[ustring(a->name)].reset(a); + m_attributes[ustringhash_from(ustring(a->name))].reset(a); } } } @@ -89,17 +89,17 @@ RendererServices::pointcloud_search(ShaderGlobals* sg, ustringhash filename, #ifdef USE_PARTIO if (filename.empty()) return 0; - PointCloud* pc = PointCloud::get(ustring_from(filename)); + PointCloud* pc = PointCloud::get(filename); if (pc == NULL) { // The file failed to load sg->context->errorfmt("pointcloud_search: could not open \"{}\"", - ustring_from(filename)); + filename); return 0; } const Partio::ParticlesData* cloud = pc->read_access(); if (cloud == NULL) { // The file failed to load sg->context->errorfmt("pointcloud_search: could not open \"{}\"", - ustring_from(filename)); + filename); return 0; } @@ -204,17 +204,17 @@ RendererServices::pointcloud_get(ShaderGlobals* sg, ustringhash filename, if (!count) return 1; // always succeed if not asking for any data - PointCloud* pc = PointCloud::get(ustring_from(filename)); + PointCloud* pc = PointCloud::get(filename); if (pc == NULL) { // The file failed to load sg->context->errorfmt("pointcloud_get: could not open \"{}\"", - ustring_from(filename)); + filename); return 0; } const Partio::ParticlesData* cloud = pc->read_access(); if (cloud == NULL) { // The file failed to load sg->context->errorfmt("pointcloud_get: could not open \"{}\"", - ustring_from(filename)); + filename); return 0; } @@ -223,7 +223,7 @@ RendererServices::pointcloud_get(ShaderGlobals* sg, ustringhash filename, if (!attr) { sg->context->errorfmt( "Accessing unexisting attribute {} in pointcloud \"{}\"", attr_name, - ustring_from(filename)); + filename); return 0; } @@ -236,7 +236,7 @@ RendererServices::pointcloud_get(ShaderGlobals* sg, ustringhash filename, if (!compatiblePartioType(partio_type, element_type)) { sg->context->errorfmt( "Type of attribute \"{}\" : {} not compatible with OSL's {} in \"{}\" pointcloud", - attr_name, partio_type, element_type, ustring_from(filename)); + attr_name, partio_type, element_type, filename); return 0; } @@ -267,9 +267,10 @@ RendererServices::pointcloud_get(ShaderGlobals* sg, ustringhash filename, for (int i = 0; i < count; ++i) { int ind = strindices[i]; if (ind >= 0 && ind < sicount) - ((ustringrep*)out_data)[i] = ustringrep(strings[ind]); + ((ustringhash*)out_data)[i] = ustringhash_from( + ustring(strings[ind])); else - ((ustringrep*)out_data)[i] = ustringrep(); + ((ustringhash*)out_data)[i] = ustringhash {}; } } else { // All cases aside from strings are simple. @@ -292,14 +293,13 @@ RendererServices::pointcloud_get(ShaderGlobals* sg, ustringhash filename, bool RendererServices::pointcloud_write(ShaderGlobals* /*sg*/, ustringhash filename, const Vec3& pos, int nattribs, - const ustringrep* names, + const ustringhash* names, const TypeDesc* types, const void** data) { #ifdef USE_PARTIO if (filename.empty()) return false; - PointCloud* pc = PointCloud::get(ustring_from(filename), - true /* create file to write */); + PointCloud* pc = PointCloud::get(filename, true /* create file to write */); spin_lock lock(pc->m_mutex); Partio::ParticlesDataMutable* cloud = pc->write_access(); if (cloud == NULL) // The file failed to load @@ -325,7 +325,7 @@ RendererServices::pointcloud_write(ShaderGlobals* /*sg*/, ustringhash filename, ok = false; } else { a = new Partio::ParticleAttribute(); - *a = cloud->addAttribute(names[i].c_str(), pt, + *a = cloud->addAttribute(ustring_from(names[i]).c_str(), pt, pt == Partio::VECTOR ? 3 : 1 /*count*/); pc->m_attributes[names[i]].reset(a); @@ -351,9 +351,10 @@ RendererServices::pointcloud_write(ShaderGlobals* /*sg*/, ustringhash filename, *(int*)cloud->dataWrite(*a, p) = *(int*)(data[i]); break; case Partio::INDEXEDSTR: { - ustringrep s = *(ustringrep*)(data[i]); - const char* sstr = s.c_str(); - int index = cloud->lookupIndexedStr(*a, sstr); + ustringhash s = *(ustringhash*)(data[i]); + ustring s_ustring = ustring_from(s); + const char* sstr = s_ustring.c_str(); + int index = cloud->lookupIndexedStr(*a, sstr); if (index == -1) index = cloud->registerIndexedStr(*a, sstr); *(int*)cloud->dataWrite(*a, p) = index; @@ -372,9 +373,10 @@ RendererServices::pointcloud_write(ShaderGlobals* /*sg*/, ustringhash filename, namespace pvt { OSL_SHADEOP int -osl_pointcloud_search(ShaderGlobals* sg, ustring_pod filename, void* center, - float radius, int max_points, int sort, void* out_indices, - void* out_distances, int derivs_offset, int nattrs, ...) +osl_pointcloud_search(ShaderGlobals* sg, ustringhash_pod filename_, + void* center, float radius, int max_points, int sort, + void* out_indices, void* out_distances, int derivs_offset, + int nattrs, ...) { ShadingSystemImpl& shadingsys(sg->context->shadingsys()); if (shadingsys.no_pointcloud()) // Debug mode to skip pointcloud expense @@ -392,20 +394,22 @@ osl_pointcloud_search(ShaderGlobals* sg, ustring_pod filename, void* center, else indices = OSL_ALLOCA(size_t, max_points); - int count - = sg->renderer->pointcloud_search(sg, USTR(filename), *((Vec3*)center), - radius, max_points, sort, indices, - (float*)out_distances, derivs_offset); + ustringhash filename = ustringhash_from(filename_); + int count = sg->renderer->pointcloud_search(sg, filename, *((Vec3*)center), + radius, max_points, sort, + indices, (float*)out_distances, + derivs_offset); va_list args; va_start(args, nattrs); for (int i = 0; i < nattrs; i++) { - ustring_pod attr_name_rep = (ustring_pod)va_arg(args, ustring_pod); - ustringrep attr_name = USTR(attr_name_rep); - long long lltype = va_arg(args, long long); - TypeDesc attr_type = TYPEDESC(lltype); - void* out_data = va_arg(args, void*); - sg->renderer->pointcloud_get(sg, USTR(filename), indices, count, - attr_name, attr_type, out_data); + ustringhash_pod attr_name_ = (ustringhash_pod)va_arg(args, + ustringhash_pod); + ustringhash attr_name = ustringhash_from(attr_name_); + long long lltype = va_arg(args, long long); + TypeDesc attr_type = TYPEDESC(lltype); + void* out_data = va_arg(args, void*); + sg->renderer->pointcloud_get(sg, filename, indices, count, attr_name, + attr_type, out_data); } va_end(args); @@ -422,9 +426,9 @@ osl_pointcloud_search(ShaderGlobals* sg, ustring_pod filename, void* center, OSL_SHADEOP int -osl_pointcloud_get(ShaderGlobals* sg, ustring_pod filename, void* in_indices, - int count, ustring_pod attr_name, long long attr_type, - void* out_data) +osl_pointcloud_get(ShaderGlobals* sg, ustringhash_pod filename_, + void* in_indices, int count, ustringhash_pod attr_name_, + long long attr_type, void* out_data) { ShadingSystemImpl& shadingsys(sg->context->shadingsys()); if (shadingsys.no_pointcloud()) // Debug mode to skip pointcloud expense @@ -436,37 +440,45 @@ osl_pointcloud_get(ShaderGlobals* sg, ustring_pod filename, void* in_indices, shadingsys.pointcloud_stats(0, 1, 0); - return sg->renderer->pointcloud_get(sg, USTR(filename), (size_t*)indices, - count, USTR(attr_name), - TYPEDESC(attr_type), out_data); + ustringhash filename = ustringhash_from(filename_); + ustringhash attr_name = ustringhash_from(attr_name_); + return sg->renderer->pointcloud_get(sg, filename, (size_t*)indices, count, + attr_name, TYPEDESC(attr_type), + out_data); } OSL_SHADEOP void -osl_pointcloud_write_helper(ustringrep* names, TypeDesc* types, void** values, - int index, ustring_pod name, long long type, - void* val) +osl_pointcloud_write_helper(ustringhash_pod* names_, TypeDesc* types, + void** values, int index, ustringhash_pod name_, + long long type, void* val) { - names[index] = USTR(name); - types[index] = TYPEDESC(type); - values[index] = val; + auto names = reinterpret_cast(names_); + ustringhash name = ustringhash_from(name_); + names[index] = name; + types[index] = TYPEDESC(type); + values[index] = val; } OSL_SHADEOP int -osl_pointcloud_write(ShaderGlobals* sg, ustring_pod filename, const Vec3* pos, - int nattribs, const ustringrep* names, - const TypeDesc* types, const void** values) +osl_pointcloud_write(ShaderGlobals* sg, ustringhash_pod filename_, + const Vec3* pos, int nattribs, + const ustringhash_pod* names_, const TypeDesc* types, + const void** values) { ShadingSystemImpl& shadingsys(sg->context->shadingsys()); if (shadingsys.no_pointcloud()) // Debug mode to skip pointcloud expense return 0; shadingsys.pointcloud_stats(0, 0, 0, 1); - return sg->renderer->pointcloud_write(sg, USTR(filename), *pos, nattribs, - names, types, values); + ustringhash filename = ustringhash_from(filename_); + auto names = reinterpret_cast(names_); + + return sg->renderer->pointcloud_write(sg, filename, *pos, nattribs, names, + types, values); } } // namespace pvt diff --git a/src/liboslexec/rendservices.cpp b/src/liboslexec/rendservices.cpp index c536f3eff..0ff278703 100644 --- a/src/liboslexec/rendservices.cpp +++ b/src/liboslexec/rendservices.cpp @@ -418,6 +418,13 @@ RendererServices::get_texture_info(ustringhash filename, texture_thread_info, subimage, ustring_from(dataname), datatype, data); + if (status && (datatype == TypeDesc::STRING)) { + // The TextureSubsystem still writes out ustrings, not ustringhashes! + // So we will need to go and convert that ustring to a hash + // for the rest of OSL to understand + auto ustr_data = reinterpret_cast(data); + (reinterpret_cast(data))[0] = ustr_data->hash(); + } if (!status) { std::string err = texturesys()->geterror(); if (err.size()) { diff --git a/src/liboslexec/rs_fallback.cpp b/src/liboslexec/rs_fallback.cpp index afd7f2162..449237ac6 100644 --- a/src/liboslexec/rs_fallback.cpp +++ b/src/liboslexec/rs_fallback.cpp @@ -49,7 +49,7 @@ rs_get_inverse_matrix_xform_time(OSL::OpaqueExecContextPtr exec_ctx, OSL_RSOP bool rs_get_matrix_space_time(OSL::OpaqueExecContextPtr exec_ctx, - OSL::Matrix44& result, OSL::StringParam from, + OSL::Matrix44& result, OSL::ustringhash from, float time) { auto sg = get_sg(exec_ctx); @@ -58,7 +58,7 @@ rs_get_matrix_space_time(OSL::OpaqueExecContextPtr exec_ctx, OSL_RSOP bool rs_get_inverse_matrix_space_time(OSL::OpaqueExecContextPtr exec_ctx, - OSL::Matrix44& result, OSL::StringParam to, + OSL::Matrix44& result, OSL::ustringhash to, float time) { auto sg = get_sg(exec_ctx); @@ -83,7 +83,7 @@ rs_get_inverse_matrix_xform(OSL::OpaqueExecContextPtr exec_ctx, OSL_RSOP bool rs_get_matrix_space(OSL::OpaqueExecContextPtr exec_ctx, OSL::Matrix44& result, - OSL::StringParam from) + OSL::ustringhash from) { auto sg = get_sg(exec_ctx); return sg->renderer->get_matrix(sg, result, from); @@ -91,15 +91,15 @@ rs_get_matrix_space(OSL::OpaqueExecContextPtr exec_ctx, OSL::Matrix44& result, OSL_RSOP bool rs_get_inverse_matrix_space(OSL::OpaqueExecContextPtr exec_ctx, - OSL::Matrix44& result, OSL::StringParam to) + OSL::Matrix44& result, OSL::ustringhash to) { auto sg = get_sg(exec_ctx); return sg->renderer->get_inverse_matrix(sg, result, to); } OSL_RSOP bool -rs_transform_points(OSL::OpaqueExecContextPtr exec_ctx, OSL::StringParam from, - OSL::StringParam to, float time, const OSL::Vec3* Pin, +rs_transform_points(OSL::OpaqueExecContextPtr exec_ctx, OSL::ustringhash from, + OSL::ustringhash to, float time, const OSL::Vec3* Pin, OSL::Vec3* Pout, int npoints, OSL::TypeDesc::VECSEMANTICS vectype) { diff --git a/src/liboslexec/runtimeoptimize.h b/src/liboslexec/runtimeoptimize.h index 7363ff9b6..d47d0ddac 100644 --- a/src/liboslexec/runtimeoptimize.h +++ b/src/liboslexec/runtimeoptimize.h @@ -79,6 +79,8 @@ class RuntimeOptimizer final : public OSOProcessorBase { /// Search for a constant whose type and value match type and data[...], /// returning its index if one exists, or else creating a new constant /// and returning its index. + /// NOTE: When datatype == TypeDesc::STRING, + /// the datatype is expected to be ustring, not ustringhash int add_constant(const TypeSpec& type, const void* data, TypeDesc datatype = TypeDesc::UNKNOWN); int add_constant(float c) { return add_constant(TypeDesc::TypeFloat, &c); } diff --git a/src/liboslexec/shading_state_uniform.h b/src/liboslexec/shading_state_uniform.h index de0d5efea..05fb1cf5b 100644 --- a/src/liboslexec/shading_state_uniform.h +++ b/src/liboslexec/shading_state_uniform.h @@ -18,9 +18,9 @@ namespace pvt { struct ShadingStateUniform { - ColorSystem m_colorsystem; ///< Data for current colorspace - ustring m_commonspace_synonym; ///< Synonym for "common" space - bool m_unknown_coordsys_error; ///< Error to use unknown xform name? + ColorSystem m_colorsystem; ///< Data for current colorspace + ustringhash m_commonspace_synonym; ///< Synonym for "common" space + bool m_unknown_coordsys_error; ///< Error to use unknown xform name? int m_max_warnings_per_thread; ///< How many warnings to display per thread before giving up? }; @@ -32,7 +32,7 @@ get_unknown_coordsys_error(const OpaqueExecContextPtr oec) return ssu->m_unknown_coordsys_error; } -inline ustring +inline ustringhash get_commonspace_synonym(const OpaqueExecContextPtr oec) { auto ec = pvt::get_ec(oec); diff --git a/src/liboslexec/shadingsys.cpp b/src/liboslexec/shadingsys.cpp index 8a3e8ef68..4a756549c 100644 --- a/src/liboslexec/shadingsys.cpp +++ b/src/liboslexec/shadingsys.cpp @@ -1132,7 +1132,7 @@ ShadingSystemImpl::ShadingSystemImpl(RendererServices* renderer, , m_stat_inst_merge_time(0) , m_stat_max_llvm_local_mem(0) { - m_shading_state_uniform.m_commonspace_synonym = ustring("world"); + m_shading_state_uniform.m_commonspace_synonym = Strings::world; m_shading_state_uniform.m_unknown_coordsys_error = true; m_shading_state_uniform.m_max_warnings_per_thread = 100; @@ -1233,7 +1233,7 @@ ShadingSystemImpl::ShadingSystemImpl(RendererServices* renderer, setup_op_descriptors(); - colorsystem().set_colorspace(m_colorspace); + colorsystem().set_colorspace(ustringhash_from(m_colorspace)); } @@ -1566,6 +1566,12 @@ ShadingSystemImpl::attribute(string_view name, TypeDesc type, const void* val) return true; \ } +#define ATTR_SET_STRINGHASH(_name, _dst) \ + if (name == _name && type == TypeDesc::STRING) { \ + _dst = ustringhash(*(const char**)val); \ + return true; \ + } + if (name == "options" && type == TypeDesc::STRING) { return OIIO::optparser(*this, *(const char**)val); } @@ -1653,8 +1659,8 @@ ShadingSystemImpl::attribute(string_view name, TypeDesc type, const void* val) ATTR_SET("optix_no_inline_rend_lib", int, m_optix_no_inline_rend_lib); ATTR_SET("optix_no_inline_thresh", int, m_optix_no_inline_thresh); ATTR_SET("optix_force_inline_thresh", int, m_optix_force_inline_thresh); - ATTR_SET_STRING("commonspace", - m_shading_state_uniform.m_commonspace_synonym); + ATTR_SET_STRINGHASH("commonspace", + m_shading_state_uniform.m_commonspace_synonym); ATTR_SET_STRING("debug_groupname", m_debug_groupname); ATTR_SET_STRING("debug_layername", m_debug_layername); ATTR_SET_STRING("opt_layername", m_opt_layername); @@ -1676,7 +1682,7 @@ ShadingSystemImpl::attribute(string_view name, TypeDesc type, const void* val) } if (name == "colorspace" && type == TypeDesc::STRING) { ustring c = ustring(*(const char**)val); - if (colorsystem().set_colorspace(c)) + if (colorsystem().set_colorspace(ustringhash_from(c))) m_colorspace = c; else errorfmt("Unknown color space \"{}\"", c); @@ -1752,6 +1758,12 @@ ShadingSystemImpl::getattribute(string_view name, TypeDesc type, void* val) return true; \ } +#define ATTR_DECODE_STRINGHASH(_name, _src) \ + if (name == _name && type == TypeDesc::STRING) { \ + *(const char**)(val) = ustring_from(_src).c_str(); \ + return true; \ + } + lock_guard guard(m_mutex); // Thread safety ATTR_DECODE_STRING("searchpath:shader", m_searchpath); @@ -1820,8 +1832,8 @@ ShadingSystemImpl::getattribute(string_view name, TypeDesc type, void* val) ATTR_DECODE("relaxed_param_typecheck", int, m_relaxed_param_typecheck); ATTR_DECODE("max_warnings_per_thread", int, m_shading_state_uniform.m_max_warnings_per_thread); - ATTR_DECODE_STRING("commonspace", - m_shading_state_uniform.m_commonspace_synonym); + ATTR_DECODE_STRINGHASH("commonspace", + m_shading_state_uniform.m_commonspace_synonym); ATTR_DECODE_STRING("colorspace", m_colorspace); ATTR_DECODE_STRING("debug_groupname", m_debug_groupname); ATTR_DECODE_STRING("debug_layername", m_debug_layername); @@ -4135,7 +4147,7 @@ ShadingSystemImpl::merge_instances(ShaderGroup& group, bool post_opt) #ifndef __CUDACC__ OIIO::ColorProcessorHandle -OCIOColorSystem::load_transform(StringParam fromspace, StringParam tospace, +OCIOColorSystem::load_transform(ustring fromspace, ustring tospace, ShadingSystemImpl* ss) { if (fromspace != m_last_colorproc_fromspace @@ -4367,7 +4379,7 @@ ClosureRegistry::get_entry(ustring name) const template<> bool -ShadingContext::ocio_transform(StringParam fromspace, StringParam tospace, +ShadingContext::ocio_transform(ustring fromspace, ustring tospace, const Color3& C, Color3& Cout) { #ifndef __CUDA_ARCH__ @@ -4384,7 +4396,7 @@ ShadingContext::ocio_transform(StringParam fromspace, StringParam tospace, template<> bool -ShadingContext::ocio_transform(StringParam fromspace, StringParam tospace, +ShadingContext::ocio_transform(ustring fromspace, ustring tospace, const Dual2& C, Dual2& Cout) { #ifndef __CUDA_ARCH__ @@ -4641,11 +4653,11 @@ osl_uninit_check(long long typedesc_, void* vals_, void* sg, } } if (typedesc.basetype == TypeDesc::STRING) { - ustring* vals = (ustring*)vals_; + OSL::ustringhash* vals = (OSL::ustringhash*)vals_; for (int c = firstcheck, e = firstcheck + nchecks; c < e; ++c) - if (vals[c] == Strings::uninitialized_string) { + if (vals[c] == Hashes::uninitialized_string) { uninit = true; - vals[c] = ustring(); + vals[c] = OSL::ustringhash(); } } if (uninit) { @@ -4698,51 +4710,61 @@ osl_range_check_err(int indexvalue, int length, ustringhash_pod symname_, // Asked if the raytype is a name we can't know until mid-shader. OSL_SHADEOP int -osl_raytype_name(void* sg_, ustring_pod name) +osl_raytype_name(void* sg_, ustringhash_pod name_) { ShaderGlobals* sg = (ShaderGlobals*)sg_; - int bit = sg->context->shadingsys().raytype_bit(USTR(name)); + auto name = ustring_from(name_); + // TODO: add 2nd version of raytype_bit that takes ustringhash + int bit = sg->context->shadingsys().raytype_bit(name); return (sg->raytype & bit) != 0; } OSL_SHADEOP int -osl_get_attribute(void* sg_, int dest_derivs, ustring_pod obj_name, - ustring_pod attr_name, int array_lookup, int index, +osl_get_attribute(void* sg_, int dest_derivs, ustringhash_pod obj_name_, + ustringhash_pod attr_name_, int array_lookup, int index, long long attr_type, void* attr_dest) { - ShaderGlobals* sg = (ShaderGlobals*)sg_; + ShaderGlobals* sg = (ShaderGlobals*)sg_; + ustringhash obj_name = ustringhash_from(obj_name_); + ustringhash attr_name = ustringhash_from(attr_name_); return sg->context->osl_get_attribute(sg, sg->objdata, dest_derivs, - USTR(obj_name), USTR(attr_name), - array_lookup, index, - TYPEDESC(attr_type), attr_dest); + obj_name, attr_name, array_lookup, + index, TYPEDESC(attr_type), + attr_dest); } OSL_SHADEOP int -osl_bind_interpolated_param(void* sg_, ustring_pod name, long long type, +osl_bind_interpolated_param(void* sg_, ustringhash_pod name_, long long type, int userdata_has_derivs, void* userdata_data, int /*symbol_has_derivs*/, void* symbol_data, int symbol_data_size, char* userdata_initialized, int /*userdata_index*/) { - char status = *userdata_initialized; + char status = *userdata_initialized; + ustringhash name = ustringhash_from(name_); if (status == 0) { // First time retrieving this userdata ShaderGlobals* sg = (ShaderGlobals*)sg_; - bool ok = sg->renderer->get_userdata(userdata_has_derivs, USTR(name), + bool ok = sg->renderer->get_userdata(userdata_has_derivs, name, TYPEDESC(type), sg, userdata_data); - // printf ("Binding %s %s : index %d, ok = %d\n", name, - // TYPEDESC(type).c_str(),userdata_index, ok); *userdata_initialized = status = 1 + ok; // 1 = not found, 2 = found sg->context->incr_get_userdata_calls(); } if (status == 2) { int udata_size = (userdata_has_derivs ? 3 : 1) * TYPEDESC(type).size(); // If userdata was present, copy it to the shader variable - memcpy(symbol_data, userdata_data, - std::min(symbol_data_size, udata_size)); + if (TYPEDESC(type) == TypeDesc::STRING) { + const ustringhash* uh_userdata + = reinterpret_cast(userdata_data); + memcpy(symbol_data, uh_userdata, + std::min(symbol_data_size, udata_size)); + } else { //not string + memcpy(symbol_data, userdata_data, + std::min(symbol_data_size, udata_size)); + } if (symbol_data_size > udata_size) memset((char*)symbol_data + udata_size, 0, symbol_data_size - udata_size); diff --git a/src/liboslexec/splineimpl.h b/src/liboslexec/splineimpl.h index 0b6bc7a31..1d8dbfa6b 100644 --- a/src/liboslexec/splineimpl.h +++ b/src/liboslexec/splineimpl.h @@ -92,17 +92,17 @@ OSL_CONSTANT_DATA const SplineBasis gBasisSet[kNumSplineTypes] = { OSL_HOSTDEVICE static int -basis_type_of(StringParam basis_name) +basis_type_of(ustringhash basis_name) { - if (basis_name == STRING_PARAMS(catmullrom)) + if (basis_name == Hashes::catmullrom) return kCatmullRom; - if (basis_name == STRING_PARAMS(bezier)) + if (basis_name == Hashes::bezier) return kBezier; - if (basis_name == STRING_PARAMS(bspline)) + if (basis_name == Hashes::bspline) return kBSpline; - if (basis_name == STRING_PARAMS(hermite)) + if (basis_name == Hashes::hermite) return kHermite; - if (basis_name == STRING_PARAMS(constant)) + if (basis_name == Hashes::constant) return kConstant; // Default to linear @@ -115,7 +115,7 @@ struct SplineInterp { const SplineBasis& spline; const bool constant; - OSL_HOSTDEVICE static SplineInterp create(StringParam basis_name) + OSL_HOSTDEVICE static SplineInterp create(ustringhash basis_name) { int splineType = basis_type_of(basis_name); diff --git a/src/liboslexec/string_hash.h b/src/liboslexec/string_hash.h deleted file mode 100644 index fd57bdf3c..000000000 --- a/src/liboslexec/string_hash.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright Contributors to the Open Shading Language project. -// SPDX-License-Identifier: BSD-3-Clause -// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage - -#pragma once - -#include -#include - -namespace pvt { - -OIIO_CONSTEXPR14 inline size_t -pvtstrlen(const char* s) -{ - if (s == nullptr) - return 0; - size_t len = 0; - while (s[len] != 0) - len++; - return len; -} - -} // namespace pvt - -namespace UStringHash { -OIIO_CONSTEXPR14 inline size_t -Hash(const char* s) -{ - size_t len = pvt::pvtstrlen(s); - - return len ? OIIO::farmhash::inlined::Hash(s, len) : 0; -} - -// Template to ensure the hash is evaluated at compile time. -template static constexpr size_t HashConstEval = V; -} // namespace UStringHash diff --git a/src/liboslexec/wide/wide_opclosure.cpp b/src/liboslexec/wide/wide_opclosure.cpp index 6dfdcd79c..872abe7fe 100644 --- a/src/liboslexec/wide/wide_opclosure.cpp +++ b/src/liboslexec/wide/wide_opclosure.cpp @@ -210,7 +210,7 @@ __OSL_OP(closure_to_string)(void* bsg_, ClosureColor* c) // Special case for printing closures std::ostringstream stream; stream.imbue(std::locale::classic()); // force C locale - print_closure(stream, c, &bsg->uniform.context->shadingsys()); + print_closure(stream, c, &bsg->uniform.context->shadingsys(), false); return ustring(stream.str()).c_str(); } diff --git a/src/liboslexec/wide/wide_opcolor.cpp b/src/liboslexec/wide/wide_opcolor.cpp index 7b5f29711..d1e96320f 100644 --- a/src/liboslexec/wide/wide_opcolor.cpp +++ b/src/liboslexec/wide/wide_opcolor.cpp @@ -176,12 +176,12 @@ namespace { // NOTE: keep implementation as mirror of ColorSystem::to_rgb void wide_prepend_color_from(ShadingContext* ctx, const ColorSystem& cs, - Masked wR, StringParam fromspace) + Masked wR, ustring fromspace) { // Rather than attempt outer loop vectorization of ColorSystem::to_rgb // we will pull it's implementation up and insert SIMD loops inside // the uniform branches - if (fromspace == STRING_PARAMS(RGB) || fromspace == STRING_PARAMS(rgb) + if (fromspace == Strings::RGB || fromspace == Strings::rgb || fromspace == cs.colorspace()) { OSL_OMP_PRAGMA(omp simd simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { @@ -190,7 +190,7 @@ wide_prepend_color_from(ShadingContext* ctx, const ColorSystem& cs, } return; } - if (fromspace == STRING_PARAMS(hsv)) { + if (fromspace == Strings::hsv) { OSL_OMP_PRAGMA(omp simd simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { Color3 C = wR[lane]; @@ -201,7 +201,7 @@ wide_prepend_color_from(ShadingContext* ctx, const ColorSystem& cs, } return; } - if (fromspace == STRING_PARAMS(hsl)) { + if (fromspace == Strings::hsl) { OSL_OMP_PRAGMA(omp simd simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { Color3 C = wR[lane]; @@ -212,7 +212,7 @@ wide_prepend_color_from(ShadingContext* ctx, const ColorSystem& cs, } return; } - if (fromspace == STRING_PARAMS(YIQ)) { + if (fromspace == Strings::YIQ) { OSL_OMP_PRAGMA(omp simd simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { Color3 C = wR[lane]; @@ -223,7 +223,7 @@ wide_prepend_color_from(ShadingContext* ctx, const ColorSystem& cs, } return; } - if (fromspace == STRING_PARAMS(XYZ)) { + if (fromspace == Strings::XYZ) { OSL_OMP_PRAGMA(omp simd simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { Color3 C = wR[lane]; @@ -234,7 +234,7 @@ wide_prepend_color_from(ShadingContext* ctx, const ColorSystem& cs, } return; } - if (fromspace == STRING_PARAMS(xyY)) { + if (fromspace == Strings::xyY) { OSL_OMP_PRAGMA(omp simd simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { Color3 C = wR[lane]; @@ -249,7 +249,7 @@ wide_prepend_color_from(ShadingContext* ctx, const ColorSystem& cs, // Serialize calls to ocio wR.mask().foreach ([=, &cs](ActiveLane lane) -> void { Color3 C = wR[lane]; - Color3 R = cs.ocio_transform(fromspace, STRING_PARAMS(RGB), C, ctx); + Color3 R = cs.ocio_transform(fromspace, Strings::RGB, C, ctx); wR[lane] = R; }); } @@ -267,7 +267,7 @@ __OSL_MASKED_OP2(prepend_color_from, Wv, s)(void* bsg_, void* c_, ShadingContext* ctx = context_from_bsg(bsg_); Masked wR(c_, Mask(mask_value)); - StringParam fromspace = USTR(from); + ustring fromspace = USTR(from); wide_prepend_color_from(ctx, cs, wR, fromspace); } @@ -305,16 +305,16 @@ namespace { template OSL_NOINLINE void -wide_transformc(const ColorSystem cs, StringParam fromspace, - StringParam tospace, Masked wOutput, - Wide wInput, ShadingContext* context); +wide_transformc(const ColorSystem cs, ustring fromspace, ustring tospace, + Masked wOutput, Wide wInput, + ShadingContext* context); // NOTE: keep implementation as mirror of ColorSystem::transformc template void -wide_transformc(const ColorSystem cs, StringParam fromspace, - StringParam tospace, Masked wOutput, - Wide wInput, ShadingContext* context) +wide_transformc(const ColorSystem cs, ustring fromspace, ustring tospace, + Masked wOutput, Wide wInput, + ShadingContext* context) { // Rather than attempt outer loop vectorization of ColorSystem::transformc // we will pull it's implementation up and insert SIMD loops inside @@ -322,14 +322,14 @@ wide_transformc(const ColorSystem cs, StringParam fromspace, bool use_colorconfig = false; Block bCrgb; Wide wCrgb(bCrgb); - if (fromspace == STRING_PARAMS(RGB) || fromspace == STRING_PARAMS(rgb) - || fromspace == STRING_PARAMS(linear) || fromspace == cs.colorspace()) { + if (fromspace == Strings::RGB || fromspace == Strings::rgb + || fromspace == Strings::linear || fromspace == cs.colorspace()) { WIDE_TRANSFORMC_OMP_SIMD_LOOP(simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { COLOR C = wInput[lane]; wCrgb[lane] = C; } - } else if (fromspace == STRING_PARAMS(hsv)) { + } else if (fromspace == Strings::hsv) { WIDE_TRANSFORMC_OMP_SIMD_LOOP(simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { COLOR C = wInput[lane]; @@ -338,7 +338,7 @@ wide_transformc(const ColorSystem cs, StringParam fromspace, wCrgb[ActiveLane(lane)] = R; } } - } else if (fromspace == STRING_PARAMS(hsl)) { + } else if (fromspace == Strings::hsl) { WIDE_TRANSFORMC_OMP_SIMD_LOOP(simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { COLOR C = wInput[lane]; @@ -347,7 +347,7 @@ wide_transformc(const ColorSystem cs, StringParam fromspace, wCrgb[ActiveLane(lane)] = R; } } - } else if (fromspace == STRING_PARAMS(YIQ)) { + } else if (fromspace == Strings::YIQ) { WIDE_TRANSFORMC_OMP_SIMD_LOOP(simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { COLOR C = wInput[lane]; @@ -356,7 +356,7 @@ wide_transformc(const ColorSystem cs, StringParam fromspace, wCrgb[ActiveLane(lane)] = R; } } - } else if (fromspace == STRING_PARAMS(XYZ)) { + } else if (fromspace == Strings::XYZ) { WIDE_TRANSFORMC_OMP_SIMD_LOOP(simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { COLOR C = wInput[lane]; @@ -365,7 +365,7 @@ wide_transformc(const ColorSystem cs, StringParam fromspace, wCrgb[ActiveLane(lane)] = R; } } - } else if (fromspace == STRING_PARAMS(xyY)) { + } else if (fromspace == Strings::xyY) { WIDE_TRANSFORMC_OMP_SIMD_LOOP(simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { COLOR C = wInput[lane]; @@ -374,7 +374,7 @@ wide_transformc(const ColorSystem cs, StringParam fromspace, wCrgb[ActiveLane(lane)] = R; } } - } else if (fromspace == STRING_PARAMS(sRGB)) { + } else if (fromspace == Strings::sRGB) { WIDE_TRANSFORMC_OMP_SIMD_LOOP(simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { COLOR C = wInput[lane]; @@ -389,15 +389,14 @@ wide_transformc(const ColorSystem cs, StringParam fromspace, if (use_colorconfig) { // do things the ColorConfig way, so skip all these other clauses... - } else if (tospace == STRING_PARAMS(RGB) || tospace == STRING_PARAMS(rgb) - || tospace == STRING_PARAMS(linear) - || tospace == cs.colorspace()) { + } else if (tospace == Strings::RGB || tospace == Strings::rgb + || tospace == Strings::linear || tospace == cs.colorspace()) { WIDE_TRANSFORMC_OMP_SIMD_LOOP(simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { COLOR C = wCrgb[lane]; wOutput[lane] = C; } - } else if (tospace == STRING_PARAMS(hsv)) { + } else if (tospace == Strings::hsv) { WIDE_TRANSFORMC_OMP_SIMD_LOOP(simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { COLOR Crgb = wCrgb[lane]; @@ -406,7 +405,7 @@ wide_transformc(const ColorSystem cs, StringParam fromspace, wOutput[ActiveLane(lane)] = Cto; } } - } else if (tospace == STRING_PARAMS(hsl)) { + } else if (tospace == Strings::hsl) { WIDE_TRANSFORMC_OMP_SIMD_LOOP(simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { COLOR Crgb = wCrgb[lane]; @@ -415,7 +414,7 @@ wide_transformc(const ColorSystem cs, StringParam fromspace, wOutput[ActiveLane(lane)] = Cto; } } - } else if (tospace == STRING_PARAMS(YIQ)) { + } else if (tospace == Strings::YIQ) { WIDE_TRANSFORMC_OMP_SIMD_LOOP(simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { COLOR Crgb = wCrgb[lane]; @@ -424,7 +423,7 @@ wide_transformc(const ColorSystem cs, StringParam fromspace, wOutput[ActiveLane(lane)] = Cto; } } - } else if (tospace == STRING_PARAMS(XYZ)) { + } else if (tospace == Strings::XYZ) { WIDE_TRANSFORMC_OMP_SIMD_LOOP(simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { COLOR Crgb = wCrgb[lane]; @@ -433,7 +432,7 @@ wide_transformc(const ColorSystem cs, StringParam fromspace, wOutput[ActiveLane(lane)] = Cto; } } - } else if (tospace == STRING_PARAMS(xyY)) { + } else if (tospace == Strings::xyY) { WIDE_TRANSFORMC_OMP_SIMD_LOOP(simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { COLOR Crgb = wCrgb[lane]; @@ -442,7 +441,7 @@ wide_transformc(const ColorSystem cs, StringParam fromspace, wOutput[ActiveLane(lane)] = Cto; } } - } else if (tospace == STRING_PARAMS(sRGB)) { + } else if (tospace == Strings::sRGB) { WIDE_TRANSFORMC_OMP_SIMD_LOOP(simdlen(__OSL_WIDTH)) for (int lane = 0; lane < __OSL_WIDTH; ++lane) { COLOR Crgb = wCrgb[lane]; @@ -472,10 +471,10 @@ wide_transformc(const ColorSystem cs, StringParam fromspace, OSL_BATCHOP void -__OSL_MASKED_OP3(transform_color, Wv, s, s)(void* bsg_, void* Cin, - int Cin_derivs, void* Cout, - int Cout_derivs, void* from_, - void* to_, unsigned int mask_value) +__OSL_MASKED_OP3(transform_color, Wv, s, + s)(void* bsg_, void* Cin, int Cin_derivs, void* Cout, + int Cout_derivs, ustring_pod from_, ustring_pod to_, + unsigned int mask_value) { const ColorSystem& cs = cs_from_bsg(bsg_); ShadingContext* ctx = context_from_bsg(bsg_); @@ -512,8 +511,8 @@ __OSL_MASKED_OP3(transform_color, Wv, s, s)(void* bsg_, void* Cin, OSL_BATCHOP void __OSL_OP3(transform_color, v, s, s)(void* bsg_, void* Cin, int Cin_derivs, - void* Cout, int Cout_derivs, void* from_, - void* to_) + void* Cout, int Cout_derivs, + ustring_pod from_, ustring_pod to_) { const ColorSystem& cs = cs_from_bsg(bsg_); ShadingContext* ctx = context_from_bsg(bsg_); diff --git a/src/liboslexec/wide/wide_opdictionary.cpp b/src/liboslexec/wide/wide_opdictionary.cpp index 64414d28c..e4a69300c 100644 --- a/src/liboslexec/wide/wide_opdictionary.cpp +++ b/src/liboslexec/wide/wide_opdictionary.cpp @@ -48,7 +48,7 @@ OSL_USING_DATA_WIDTH(__OSL_WIDTH) #include "define_opname_macros.h" OSL_BATCHOP int -__OSL_OP(dict_find_iis)(void* bsg_, int nodeID, void* query) +__OSL_OP(dict_find_iis)(void* bsg_, int nodeID, ustring_pod query) { auto* bsg = reinterpret_cast(bsg_); return bsg->uniform.context->dict_find( @@ -82,7 +82,7 @@ __OSL_MASKED_OP3(dict_find, Wi, Wi, Ws)(void* bsg_, void* wout, void* wnodeID, OSL_BATCHOP int -__OSL_OP(dict_find_iss)(void* bsg_, void* dictionary, void* query) +__OSL_OP(dict_find_iss)(void* bsg_, ustring_pod dictionary, ustring_pod query) { auto* bsg = reinterpret_cast(bsg_); return bsg->uniform.context->dict_find( @@ -145,12 +145,13 @@ __OSL_MASKED_OP(dict_next)(void* bsg_, void* wout, void* wNodeID, OSL_BATCHOP int -__OSL_OP(dict_value)(void* bsg_, int nodeID, void* attribname, long long type, - void* data) +__OSL_OP(dict_value)(void* bsg_, int nodeID, ustring_pod attribname, + long long type, void* data) { auto* bsg = reinterpret_cast(bsg_); return bsg->uniform.context->dict_value(nodeID, USTR(attribname), - TYPEDESC(type), data); + TYPEDESC(type), data, + /*treat_ustrings_as_hash*/ false); } namespace { // anonymous @@ -169,7 +170,8 @@ template struct DictValueGetter { ValueT value; int result = context->dict_value(nodeID, attribname, wdest.type(), - &value); + &value, + /*treat_ustrings_as_hash*/ false); wout[lane] = result; if (result) { dest[lane] = value; @@ -191,7 +193,8 @@ template struct DictValueGetter { ustring attribname = wAttribName[lane]; ElementType value[dest_array.length()]; int result = context->dict_value(nodeID, attribname, wdest.type(), - &value[0]); + &value[0], + /*treat_ustrings_as_hash*/ false); auto dest = dest_array[lane]; for (int element = 0; element < dest.length(); ++element) { dest[element] = value[element]; diff --git a/src/liboslexec/wide/wide_opmatrix.cpp b/src/liboslexec/wide/wide_opmatrix.cpp index 90536e772..33b3ef2aa 100644 --- a/src/liboslexec/wide/wide_opmatrix.cpp +++ b/src/liboslexec/wide/wide_opmatrix.cpp @@ -47,14 +47,12 @@ invoke(FunctorT f) // helper to make a Block from a pointer -#if !OSL_USTRINGREP_IS_HASH inline void block_ustringhash_from_ptr(Block& b, const void* w_ptr) { for (int i = 0; i < __OSL_WIDTH; ++i) b.set(i, reinterpret_cast(w_ptr)[i]); } -#endif OSL_FORCEINLINE void @@ -758,13 +756,9 @@ __OSL_MASKED_OP2(prepend_matrix_from, Wm, Ws)(void* bsg_, void* wr, auto* bsg = reinterpret_cast(bsg_); ShadingContext* ctx = bsg->uniform.context; -#if OSL_USTRINGREP_IS_HASH - Wide wFromName(w_from_name); -#else Block bwFromName; block_ustringhash_from_ptr(bwFromName, w_from_name); Wide wFromName(bwFromName); -#endif Block wMfrom; Masked from_matrix(wMfrom, Mask(mask_value)); @@ -914,13 +908,10 @@ __OSL_MASKED_OP3(get_from_to_matrix, Wm, s, Mask succeeded = impl_get_uniform_from_matrix_masked(bsg, from_matrix, from); -#if OSL_USTRINGREP_IS_HASH - Wide wToSpace(w_to_ptr); -#else Block bwToSpace; block_ustringhash_from_ptr(bwToSpace, w_to_ptr); Wide wToSpace(bwToSpace); -#endif + Block wMto; // NOTE: even if we failed to get a from matrix, it should have been set to // identity, so we still need to try to get the to matrix for the original mask @@ -942,13 +933,9 @@ __OSL_MASKED_OP3(get_from_to_matrix, Wm, Ws, auto* bsg = reinterpret_cast(bsg_); ShadingContext* ctx = bsg->uniform.context; -#if OSL_USTRINGREP_IS_HASH - Wide wFromName(w_from_ptr); -#else Block bwFromName; block_ustringhash_from_ptr(bwFromName, w_from_ptr); Wide wFromName(bwFromName); -#endif Block wMto; Masked to_matrix(wMto, Mask(mask_value)); @@ -976,26 +963,19 @@ __OSL_MASKED_OP3(get_from_to_matrix, Wm, Ws, auto* bsg = reinterpret_cast(bsg_); ShadingContext* ctx = bsg->uniform.context; -#if OSL_USTRINGREP_IS_HASH - Wide wFromName(w_from_ptr); -#else Block bwFromName; block_ustringhash_from_ptr(bwFromName, w_from_ptr); Wide wFromName(bwFromName); -#endif Block wMfrom; Masked from_matrix(wMfrom, Mask(mask_value)); Mask succeeded = impl_get_varying_from_matrix_batched(bsg, ctx, wFromName, from_matrix); -#if OSL_USTRINGREP_IS_HASH - Wide wToSpace(w_to_ptr); -#else Block bwToSpace; block_ustringhash_from_ptr(bwToSpace, w_to_ptr); Wide wToSpace(bwToSpace); -#endif + Block wMto; // NOTE: even if we failed to get a from matrix, it should have been set to // identity, so we still need to try to get the to matrix for the original mask @@ -1030,8 +1010,8 @@ __OSL_MASKED_OP3(build_transform_matrix, Wm, s, Masked mm(WM_, mask); ShadingContext* ctx = bsg->uniform.context; - ustringrep from = USTR(from_); - ustringrep to = USTR(to_); + ustring from = USTR(from_); + ustring to = USTR(to_); Mask succeeded; // Avoid matrix concatenation if possible by detecting when the @@ -1065,15 +1045,11 @@ __OSL_MASKED_OP3(build_transform_matrix, Wm, Ws, Mask mask(mask_value); Masked wrm(WM_, mask); -#if OSL_USTRINGREP_IS_HASH - Wide wfrom_space(wfrom_); -#else Block bwfrom_space; block_ustringhash_from_ptr(bwfrom_space, wfrom_); Wide wfrom_space(bwfrom_space); -#endif - ustringrep to_space = USTR(to_); + ustring to_space = USTR(to_); Block wMfrom, wMto; Masked from_matrix(wMfrom, wrm.mask()); @@ -1101,14 +1077,10 @@ __OSL_MASKED_OP3(build_transform_matrix, Wm, s, Mask mask(mask_value); Masked wrm(WM_, mask); - ustringrep from = USTR(from_); -#if OSL_USTRINGREP_IS_HASH - Wide wto_space(wto_); -#else + ustring from = USTR(from_); Block bwto_space; block_ustringhash_from_ptr(bwto_space, wto_); Wide wto_space(bwto_space); -#endif Block wMfrom, wMto; Masked from_matrix(wMfrom, wrm.mask()); @@ -1137,17 +1109,12 @@ __OSL_MASKED_OP3(build_transform_matrix, Wm, Ws, Ws)(void* bsg_, void* WM_, Mask mask(mask_value); Masked wrm(WM_, mask); -#if OSL_USTRINGREP_IS_HASH - Wide wfrom_space(wfrom_); - Wide wto_space(wto_); -#else Block bwfrom_space; block_ustringhash_from_ptr(bwfrom_space, wfrom_); Wide wfrom_space(bwfrom_space); Block bwto_space; block_ustringhash_from_ptr(bwto_space, wto_); Wide wto_space(bwto_space); -#endif Block wMfrom, wMto; Masked from_matrix(wMfrom, wrm.mask()); diff --git a/src/liboslexec/wide/wide_opmessage.cpp b/src/liboslexec/wide/wide_opmessage.cpp index 57166a4e1..de426f9c7 100644 --- a/src/liboslexec/wide/wide_opmessage.cpp +++ b/src/liboslexec/wide/wide_opmessage.cpp @@ -209,10 +209,10 @@ __OSL_MASKED_OP2(setmessage, s, WX)(BatchedShaderGlobals* bsg_, Mask mask(mask_value); OSL_ASSERT(mask.any_on()); - ustringrep name = USTR(name_); + ustring name = USTR(name_); MaskedData wsrcval(TYPEDESC(type), false /*has_derivs*/, mask, wvalue); - ustringrep sourcefile = USTR(sourcefile_); + ustring sourcefile = USTR(sourcefile_); auto* bsg = reinterpret_cast(bsg_); @@ -244,10 +244,10 @@ __OSL_MASKED_OP2(setmessage, Ws, WX)(BatchedShaderGlobals* bsg_, void* wname, Mask mask(mask_value); OSL_ASSERT(mask.any_on()); - Wide wName(wname); + Wide wName(wname); MaskedData wsrcval(TYPEDESC(type), false /*has_derivs*/, mask, wvalue); - ustringrep sourcefile = USTR(sourcefile_); + ustring sourcefile = USTR(sourcefile_); auto* bsg = reinterpret_cast(bsg_); @@ -280,9 +280,9 @@ __OSL_MASKED_OP(getmessage)(void* bsg_, void* result, ustring_pod source_, int derivs, int layeridx, ustring_pod sourcefile_, int sourceline, unsigned int mask_value) { - ustringrep source = USTR(source_); - ustringrep name = USTR(name_); - ustringrep sourcefile = USTR(sourcefile_); + ustring source = USTR(source_); + ustring name = USTR(name_); + ustring sourcefile = USTR(sourcefile_); Mask mask(mask_value); diff --git a/src/liboslexec/wide/wide_oppointcloud.cpp b/src/liboslexec/wide/wide_oppointcloud.cpp index c06432a88..1ed34138b 100644 --- a/src/liboslexec/wide/wide_oppointcloud.cpp +++ b/src/liboslexec/wide/wide_oppointcloud.cpp @@ -531,9 +531,9 @@ __OSL_MASKED_OP(pointcloud_search)( va_list args; va_start(args, nattrs); for (int i = 0; i < nattrs; i++) { - ustringrep attr_name = USTREP(va_arg(args, ustring_pod)); - TypeDesc attr_type = TYPEDESC(va_arg(args, long long)); - void* out_data = va_arg(args, void*); + ustring attr_name = USTR(va_arg(args, ustring_pod)); + TypeDesc attr_type = TYPEDESC(va_arg(args, long long)); + void* out_data = va_arg(args, void*); dispatch_pointcloud_get( bsg, USTR(filename), windices, wnum_points, attr_name, MaskedData { attr_type, false, Mask { mask_value }, out_data }); @@ -576,7 +576,7 @@ __OSL_MASKED_OP(pointcloud_get)(BatchedShaderGlobals* bsg, ustring_pod filename, OSL_BATCHOP int __OSL_MASKED_OP(pointcloud_write)(BatchedShaderGlobals* bsg, ustring_pod filename, const void* wpos_, - int nattribs, const ustringrep* attr_names, + int nattribs, const ustring* attr_names, const TypeDesc* attr_types, const void** ptrs_to_wide_attr_value, int mask_value) diff --git a/src/liboslexec/wide/wide_opstring.cpp b/src/liboslexec/wide/wide_opstring.cpp index 292dcc461..b08474e5e 100644 --- a/src/liboslexec/wide/wide_opstring.cpp +++ b/src/liboslexec/wide/wide_opstring.cpp @@ -394,6 +394,15 @@ __OSL_OP(format)(void* wide_output, unsigned int mask_value, OSL::assign_all(wOut, result); } +OSL_BATCHOP const char* +__OSL_OP(format_uniform)(const char* format_str, ...) +{ + va_list args; + va_start(args, format_str); + std::string s = Strutil::vsprintf(format_str, args); + va_end(args); + return ustring(s).c_str(); +} OSL_BATCHOP void diff --git a/src/liboslexec/wide/wide_optexture.cpp b/src/liboslexec/wide/wide_optexture.cpp index a23ffaa6f..393b13e9e 100644 --- a/src/liboslexec/wide/wide_optexture.cpp +++ b/src/liboslexec/wide/wide_optexture.cpp @@ -563,12 +563,12 @@ dispatch_environment(BatchedRendererServices* bsr, ustring filename, OSL_BATCHOP int -__OSL_MASKED_OP(texture)(void* bsg_, void* name, void* handle, const void* opt_, - const void* s, const void* t, const void* dsdx, - const void* dtdx, const void* dsdy, const void* dtdy, - int chans, void* result, int resultHasDerivs, - void* alpha, int alphaHasDerivs, void* errormessage, - int mask_) +__OSL_MASKED_OP(texture)(void* bsg_, ustring_pod name_, void* handle, + const void* opt_, const void* s, const void* t, + const void* dsdx, const void* dtdx, const void* dsdy, + const void* dtdy, int chans, void* result, + int resultHasDerivs, void* alpha, int alphaHasDerivs, + void* errormessage, int mask_) { Mask mask(mask_); OSL_ASSERT(!mask.all_off()); @@ -583,7 +583,7 @@ __OSL_MASKED_OP(texture)(void* bsg_, void* name, void* handle, const void* opt_, Mask retVal = dispatch_texture(bsg->uniform.renderer->batched(WidthTag()), - USTR(name), (TextureSystem::TextureHandle*)handle, + USTR(name_), (TextureSystem::TextureHandle*)handle, bsg->uniform.context->texture_thread_info(), opt, bsg, Wide(s), Wide(t), Wide(dsdx), Wide(dtdx), @@ -607,7 +607,7 @@ __OSL_MASKED_OP(texture)(void* bsg_, void* name, void* handle, const void* opt_, OSL_BATCHOP int -__OSL_MASKED_OP(texture3d)(void* bsg_, void* name, void* handle, +__OSL_MASKED_OP(texture3d)(void* bsg_, ustring_pod name_, void* handle, const void* opt_, const void* wP, const void* wPdx, const void* wPdy, const void* wPdz, int chans, void* result, int resultHasDerivs, void* alpha, @@ -631,7 +631,7 @@ __OSL_MASKED_OP(texture3d)(void* bsg_, void* name, void* handle, // for correcting our str texture space gradients into xyz-space gradients Mask retVal = dispatch_texture3d(bsg->uniform.renderer->batched(WidthTag()), - USTR(name), (TextureSystem::TextureHandle*)handle, + USTR(name_), (TextureSystem::TextureHandle*)handle, bsg->uniform.context->texture_thread_info(), opt, bsg, Wide(wP), Wide(wPdx), Wide(wPdy), Wide(wPdz), @@ -653,7 +653,7 @@ __OSL_MASKED_OP(texture3d)(void* bsg_, void* name, void* handle, OSL_BATCHOP int -__OSL_MASKED_OP(environment)(void* bsg_, void* name, void* handle, +__OSL_MASKED_OP(environment)(void* bsg_, ustring_pod name_, void* handle, const void* opt_, const void* wR, const void* wRdx, const void* wRdy, int chans, void* result, int resultHasDerivs, void* alpha, @@ -671,7 +671,7 @@ __OSL_MASKED_OP(environment)(void* bsg_, void* name, void* handle, // NOTE: If overridden, BatchedRendererServiced::texture is responsible // for correcting our str texture space gradients into xyz-space gradients Mask retVal = dispatch_environment( - bsg->uniform.renderer->batched(WidthTag()), USTR(name), + bsg->uniform.renderer->batched(WidthTag()), USTR(name_), (TextureSystem::TextureHandle*)handle, bsg->uniform.context->texture_thread_info(), opt, bsg, Wide(wR), Wide(wRdx), Wide(wRdy), @@ -756,8 +756,8 @@ __OSL_MASKED_OP(resolve_udim)(void* bsg_, const char* name, void* handle, OSL_BATCHOP int -__OSL_OP(get_textureinfo_uniform)(void* bsg_, const char* name, void* handle, - void* dataname, const void* attr_type, +__OSL_OP(get_textureinfo_uniform)(void* bsg_, ustring_pod name_, void* handle, + ustring_pod dataname_, const void* attr_type, void* attr_dest) { // recreate TypeDesc @@ -768,8 +768,8 @@ __OSL_OP(get_textureinfo_uniform)(void* bsg_, const char* name, void* handle, bool retVal = bsg->uniform.renderer->batched(WidthTag()) ->get_texture_info_uniform( bsg, bsg->uniform.context->texture_thread_info(), - USTR(name), (RendererServices::TextureHandle*)handle, - 0 /*FIXME-ptex*/, USTR(dataname), dest); + USTR(name_), (RendererServices::TextureHandle*)handle, + 0 /*FIXME-ptex*/, USTR(dataname_), dest); return retVal; } diff --git a/src/liboslexec/wide/wide_shadingsys.cpp b/src/liboslexec/wide/wide_shadingsys.cpp index 5041e2528..db52f8c0c 100644 --- a/src/liboslexec/wide/wide_shadingsys.cpp +++ b/src/liboslexec/wide/wide_shadingsys.cpp @@ -165,8 +165,8 @@ __OSL_OP2(uninit_check_values_offset, X, } } if (uninit) { - ustringrep groupname = USTR(groupname_); - ustringrep layername = USTR(layername_); + ustring groupname = USTR(groupname_); + ustring layername = USTR(layername_); ctx->errorfmt( "Detected possible use of uninitialized value in {} {} at {}:{} (group {}, layer {} {}, shader {}, op {} '{}', arg {})", typedesc, symbolname, sourcefile, sourceline, @@ -229,8 +229,8 @@ __OSL_MASKED_OP2(uninit_check_values_offset, WX, }); } if (lanes_uninit.any_on()) { - ustringrep groupname = USTR(groupname_); - ustringrep layername = USTR(layername_); + ustring groupname = USTR(groupname_); + ustring layername = USTR(layername_); ctx->errorfmt( "Detected possible use of uninitialized value in {} {} at {}:{} (group {}, layer {} {}, shader {}, op {} '{}', arg {}) for lanes({:x}) of batch", typedesc, symbolname, sourcefile, sourceline, @@ -295,8 +295,8 @@ __OSL_MASKED_OP2(uninit_check_values_offset, X, } if (lanes_uninit.any_on()) { - ustringrep groupname = USTR(groupname_); - ustringrep layername = USTR(layername_); + ustring groupname = USTR(groupname_); + ustring layername = USTR(layername_); ctx->errorfmt( "Detected possible use of uninitialized value in {} {} at {}:{} (group {}, layer {} {}, shader {}, op {} '{}', arg {}) for lanes({:x}) of batch", typedesc, symbolname, sourcefile, sourceline, @@ -363,8 +363,8 @@ __OSL_MASKED_OP2(uninit_check_values_offset, WX, } if (lanes_uninit.any_on()) { - ustringrep groupname = USTR(groupname_); - ustringrep layername = USTR(layername_); + ustring groupname = USTR(groupname_); + ustring layername = USTR(layername_); ctx->errorfmt( "Detected possible use of uninitialized value in {} {} at {}:{} (group {}, layer {} {}, shader {}, op {} '{}', arg {}) for lanes({:x}) of batch", typedesc, symbolname, sourcefile, sourceline, @@ -383,10 +383,10 @@ __OSL_OP(range_check)(int indexvalue, int length, ustring_pod symname, ustring_pod shadername) { if (indexvalue < 0 || indexvalue >= length) { - ustringrep groupname = USTR(groupname_); - ustringrep layername = USTR(layername_); - auto* bsg = reinterpret_cast(bsg_); - ShadingContext* ctx = bsg->uniform.context; + ustring groupname = USTR(groupname_); + ustring layername = USTR(layername_); + auto* bsg = reinterpret_cast(bsg_); + ShadingContext* ctx = bsg->uniform.context; ctx->errorfmt("Index [{}] out of range {}[0..{}]: {}:{}" " (group {}, layer {} {}, shader {})", indexvalue, USTR(symname), length - 1, USTR(sourcefile), @@ -412,9 +412,9 @@ __OSL_MASKED_OP(range_check)(void* wide_indexvalue, unsigned int mask_value, ustring_pod groupname_, int layer, ustring_pod layername_, ustring_pod shadername) { - ustringrep groupname = USTR(groupname_); - ustringrep layername = USTR(layername_); - auto* bsg = reinterpret_cast(bsg_); + ustring groupname = USTR(groupname_); + ustring layername = USTR(layername_); + auto* bsg = reinterpret_cast(bsg_); Masked wIndexValue(wide_indexvalue, Mask(mask_value)); wIndexValue.mask().foreach ([=](ActiveLane lane) -> void { int indexvalue = wIndexValue[lane]; @@ -449,9 +449,9 @@ __OSL_OP1(get_attribute, s)(void* bsg_, int dest_derivs, ustring_pod obj_name_, Mask mask(mask_); ASSERT(mask.any_on()); - auto* bsg = reinterpret_cast(bsg_); - ustringrep obj_name = USTR(obj_name_); - ustringrep attr_name = USTR(attr_name_); + auto* bsg = reinterpret_cast(bsg_); + ustring obj_name = USTR(obj_name_); + ustring attr_name = USTR(attr_name_); // Ignoring m_next_failed_attrib cache for now, // might be faster @@ -480,9 +480,9 @@ __OSL_MASKED_OP1(get_attribute, Mask mask(mask_); ASSERT(mask.any_on()); - auto* bsg = reinterpret_cast(bsg_); - ustringrep obj_name = USTR(obj_name_); - Wide wAttrName(wattr_name_); + auto* bsg = reinterpret_cast(bsg_); + ustring obj_name = USTR(obj_name_); + Wide wAttrName(wattr_name_); auto* renderer = bsg->uniform.context->batched<__OSL_WIDTH>().renderer(); Mask retVal(false); @@ -525,9 +525,9 @@ __OSL_OP(get_attribute_uniform)(void* bsg_, int dest_derivs, int array_lookup, int index, const void* attr_type, void* attr_dest) { - auto* bsg = reinterpret_cast(bsg_); - ustringrep obj_name = USTR(obj_name_); - ustringrep attr_name = USTR(attr_name_); + auto* bsg = reinterpret_cast(bsg_); + ustring obj_name = USTR(obj_name_); + ustring attr_name = USTR(attr_name_); auto* renderer = bsg->uniform.context->batched<__OSL_WIDTH>().renderer(); @@ -607,11 +607,11 @@ __OSL_OP(raytype_name)(void* bsg_, ustring_pod name) OSL_BATCHOP void -__OSL_MASKED_OP(raytype_name)(void* bsg_, void* r_, ustringrep* name_, +__OSL_MASKED_OP(raytype_name)(void* bsg_, void* r_, ustring* name_, unsigned int mask_value) { auto* bsg = reinterpret_cast(bsg_); - Wide wname(name_); + Wide wname(name_); Mask mask(mask_value); foreach_unique(wname, mask, [=](ustring name, Mask matching_lanes) -> void { diff --git a/src/osltoy/osltoyrenderer.cpp b/src/osltoy/osltoyrenderer.cpp index 5990e2a8b..26c6ad120 100644 --- a/src/osltoy/osltoyrenderer.cpp +++ b/src/osltoy/osltoyrenderer.cpp @@ -7,21 +7,38 @@ #include #include +#include #include #include "osltoyrenderer.h" +// Create ustrings for all strings used by the free function renderer services. +// Required to allow the reverse mapping of hash->string to work when processing messages +namespace RS { +namespace Strings { +#define RS_STRDECL(str, var_name) const OSL::ustring var_name { str }; +#include "rs_strdecls.h" +#undef RS_STRDECL +} // namespace Strings +} // namespace RS + +namespace RS { +namespace { +namespace Hashes { +#define RS_STRDECL(str, var_name) \ + constexpr OSL::ustringhash var_name(OSL::strhash(str)); +#include "rs_strdecls.h" +#undef RS_STRDECL +}; //namespace Hashes +} // unnamed namespace +}; //namespace RS + using namespace OSL; OSL_NAMESPACE_ENTER -static ustring u_camera("camera"), u_screen("screen"); -static ustring u_NDC("NDC"), u_raster("raster"); -static ustring u_perspective("perspective"); -static ustring u_s("s"), u_t("t"); -static ustring u_mouse("mouse"); static constexpr TypeDesc TypeFloatArray2(TypeDesc::FLOAT, 2); static constexpr TypeDesc TypeFloatArray4(TypeDesc::FLOAT, 4); static constexpr TypeDesc TypeIntArray2(TypeDesc::INT, 2); @@ -39,29 +56,29 @@ OSLToyRenderer::OSLToyRenderer() Matrix44 M; M.makeIdentity(); - camera_params(M, u_perspective, 90.0f, 0.1f, 1000.0f, 256, 256); + camera_params(M, RS::Hashes::perspective, 90.0f, 0.1f, 1000.0f, 256, 256); // Set up getters - m_attr_getters[ustring("osl:version")] = &OSLToyRenderer::get_osl_version; - m_attr_getters[ustring("camera:resolution")] + m_attr_getters[RS::Hashes::osl_version] = &OSLToyRenderer::get_osl_version; + m_attr_getters[RS::Hashes::camera_resolution] = &OSLToyRenderer::get_camera_resolution; - m_attr_getters[ustring("camera:projection")] + m_attr_getters[RS::Hashes::camera_projection] = &OSLToyRenderer::get_camera_projection; - m_attr_getters[ustring("camera:pixelaspect")] + m_attr_getters[RS::Hashes::camera_pixelaspect] = &OSLToyRenderer::get_camera_pixelaspect; - m_attr_getters[ustring("camera:screen_window")] + m_attr_getters[RS::Hashes::camera_screen_window] = &OSLToyRenderer::get_camera_screen_window; - m_attr_getters[ustring("camera:fov")] = &OSLToyRenderer::get_camera_fov; - m_attr_getters[ustring("camera:clip")] = &OSLToyRenderer::get_camera_clip; - m_attr_getters[ustring("camera:clip_near")] + m_attr_getters[RS::Hashes::camera_fov] = &OSLToyRenderer::get_camera_fov; + m_attr_getters[RS::Hashes::camera_clip] = &OSLToyRenderer::get_camera_clip; + m_attr_getters[RS::Hashes::camera_clip_near] = &OSLToyRenderer::get_camera_clip_near; - m_attr_getters[ustring("camera:clip_far")] + m_attr_getters[RS::Hashes::camera_clip_far] = &OSLToyRenderer::get_camera_clip_far; - m_attr_getters[ustring("camera:shutter")] + m_attr_getters[RS::Hashes::camera_shutter] = &OSLToyRenderer::get_camera_shutter; - m_attr_getters[ustring("camera:shutter_open")] + m_attr_getters[RS::Hashes::camera_shutter_open] = &OSLToyRenderer::get_camera_shutter_open; - m_attr_getters[ustring("camera:shutter_close")] + m_attr_getters[RS::Hashes::camera_shutter_close] = &OSLToyRenderer::get_camera_shutter_close; // Set up default shaderglobals @@ -135,7 +152,7 @@ OSLToyRenderer::supports(string_view /*feature*/) const void OSLToyRenderer::camera_params(const Matrix44& world_to_camera, - ustring projection, float hfov, float hither, + ustringhash projection, float hfov, float hither, float yon, int xres, int yres) { m_world_to_camera = world_to_camera; @@ -171,7 +188,7 @@ OSLToyRenderer::get_matrix(ShaderGlobals* /*sg*/, Matrix44& result, bool OSLToyRenderer::get_matrix(ShaderGlobals* /*sg*/, Matrix44& result, - ustring from, float /*time*/) + ustringhash from, float /*time*/) { TransformMap::const_iterator found = m_named_xforms.find(from); if (found != m_named_xforms.end()) { @@ -198,7 +215,7 @@ OSLToyRenderer::get_matrix(ShaderGlobals* /*sg*/, Matrix44& result, bool OSLToyRenderer::get_matrix(ShaderGlobals* /*sg*/, Matrix44& result, - ustring from) + ustringhash from) { // OSLToyRenderer doesn't understand motion blur, so we never fail // on account of time-varying transformations. @@ -215,13 +232,15 @@ OSLToyRenderer::get_matrix(ShaderGlobals* /*sg*/, Matrix44& result, bool OSLToyRenderer::get_inverse_matrix(ShaderGlobals* /*sg*/, Matrix44& result, - ustring to, float /*time*/) + ustringhash to, float /*time*/) { - if (to == u_camera || to == u_screen || to == u_NDC || to == u_raster) { + if (to == OSL::Hashes::camera || to == OSL::Hashes::screen + || to == OSL::Hashes::NDC || to == RS::Hashes::raster) { Matrix44 M = m_world_to_camera; - if (to == u_screen || to == u_NDC || to == u_raster) { + if (to == OSL::Hashes::screen || to == OSL::Hashes::NDC + || to == RS::Hashes::raster) { float depthrange = (double)m_yon - (double)m_hither; - if (m_projection == u_perspective) { + if (m_projection == RS::Hashes::perspective) { float tanhalffov = tanf(0.5f * m_fov * M_PI / 180.0); Matrix44 camera_to_screen(1 / tanhalffov, 0, 0, 0, 0, 1 / tanhalffov, 0, 0, 0, 0, @@ -234,7 +253,7 @@ OSLToyRenderer::get_inverse_matrix(ShaderGlobals* /*sg*/, Matrix44& result, -m_hither / depthrange, 1); M = M * camera_to_screen; } - if (to == u_NDC || to == u_raster) { + if (to == OSL::Hashes::NDC || to == RS::Hashes::raster) { float screenleft = -1.0, screenwidth = 2.0; float screenbottom = -1.0, screenheight = 2.0; Matrix44 screen_to_ndc(1 / screenwidth, 0, 0, 0, 0, @@ -242,7 +261,7 @@ OSLToyRenderer::get_inverse_matrix(ShaderGlobals* /*sg*/, Matrix44& result, -screenleft / screenwidth, -screenbottom / screenheight, 0, 1); M = M * screen_to_ndc; - if (to == u_raster) { + if (to == RS::Hashes::raster) { Matrix44 ndc_to_raster(m_xres, 0, 0, 0, 0, m_yres, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); M = M * ndc_to_raster; @@ -269,15 +288,15 @@ void OSLToyRenderer::name_transform(const char* name, const OSL::Matrix44& xform) { std::shared_ptr M(new OSL::Matrix44(xform)); - m_named_xforms[ustring(name)] = M; + m_named_xforms[ustringhash(name)] = M; } bool OSLToyRenderer::get_array_attribute(ShaderGlobals* sg, bool derivatives, - ustring object, TypeDesc type, ustring name, - int index, void* val) + ustringhash object, TypeDesc type, + ustringhash name, int index, void* val) { AttrGetterMap::const_iterator g = m_attr_getters.find(name); if (g != m_attr_getters.end()) { @@ -285,12 +304,14 @@ OSLToyRenderer::get_array_attribute(ShaderGlobals* sg, bool derivatives, return (this->*(getter))(sg, derivatives, object, type, name, val); } - if (object == u_mouse) { - if (name == u_s && type == TypeDesc::FLOAT && m_mouse_x >= 0) { + if (object == RS::Hashes::mouse) { + if (name == RS::Hashes::s && type == TypeDesc::FLOAT + && m_mouse_x >= 0) { *(float*)val = (m_mouse_x + 0.5f) / float(m_xres); return true; } - if (name == u_t && type == TypeDesc::FLOAT && m_mouse_y >= 0) { + if (name == RS::Hashes::t && type == TypeDesc::FLOAT + && m_mouse_y >= 0) { *(float*)val = (m_mouse_y + 0.5f) / float(m_yres); return true; } @@ -298,7 +319,7 @@ OSLToyRenderer::get_array_attribute(ShaderGlobals* sg, bool derivatives, // In order to test getattribute(), respond positively to // "options"/"blahblah" - if (object == "options" && name == "blahblah" + if (object == RS::Hashes::options && name == RS::Hashes::blahblah && type == TypeDesc::TypeFloat) { *(float*)val = 3.14159; return true; @@ -316,8 +337,8 @@ OSLToyRenderer::get_array_attribute(ShaderGlobals* sg, bool derivatives, bool OSLToyRenderer::get_attribute(ShaderGlobals* sg, bool derivatives, - ustring object, TypeDesc type, ustring name, - void* val) + ustringhash object, TypeDesc type, + ustringhash name, void* val) { return get_array_attribute(sg, derivatives, object, type, name, -1, val); } @@ -325,7 +346,7 @@ OSLToyRenderer::get_attribute(ShaderGlobals* sg, bool derivatives, bool -OSLToyRenderer::get_userdata(bool derivatives, ustring name, TypeDesc type, +OSLToyRenderer::get_userdata(bool derivatives, ustringhash name, TypeDesc type, ShaderGlobals* sg, void* val) { // Just to illustrate how this works, respect s and t userdata, filled @@ -333,7 +354,7 @@ OSLToyRenderer::get_userdata(bool derivatives, ustring name, TypeDesc type, // look up something specific to the primitive, rather than have hard- // coded names. - if (name == u_s && type == TypeDesc::TypeFloat) { + if (name == RS::Hashes::s && type == TypeDesc::TypeFloat) { ((float*)val)[0] = sg->u; if (derivatives) { ((float*)val)[1] = sg->dudx; @@ -341,7 +362,7 @@ OSLToyRenderer::get_userdata(bool derivatives, ustring name, TypeDesc type, } return true; } - if (name == u_t && type == TypeDesc::TypeFloat) { + if (name == RS::Hashes::t && type == TypeDesc::TypeFloat) { ((float*)val)[0] = sg->v; if (derivatives) { ((float*)val)[1] = sg->dvdx; @@ -356,8 +377,8 @@ OSLToyRenderer::get_userdata(bool derivatives, ustring name, TypeDesc type, bool OSLToyRenderer::get_osl_version(ShaderGlobals* /*sg*/, bool /*derivs*/, - ustring /*object*/, TypeDesc type, - ustring /*name*/, void* val) + ustringhash /*object*/, TypeDesc type, + ustringhash /*name*/, void* val) { if (type == TypeDesc::TypeInt) { ((int*)val)[0] = OSL_VERSION; @@ -369,8 +390,8 @@ OSLToyRenderer::get_osl_version(ShaderGlobals* /*sg*/, bool /*derivs*/, bool OSLToyRenderer::get_camera_resolution(ShaderGlobals* /*sg*/, bool /*derivs*/, - ustring /*object*/, TypeDesc type, - ustring /*name*/, void* val) + ustringhash /*object*/, TypeDesc type, + ustringhash /*name*/, void* val) { if (type == TypeIntArray2) { ((int*)val)[0] = m_xres; @@ -383,11 +404,11 @@ OSLToyRenderer::get_camera_resolution(ShaderGlobals* /*sg*/, bool /*derivs*/, bool OSLToyRenderer::get_camera_projection(ShaderGlobals* /*sg*/, bool /*derivs*/, - ustring /*object*/, TypeDesc type, - ustring /*name*/, void* val) + ustringhash /*object*/, TypeDesc type, + ustringhash /*name*/, void* val) { if (type == TypeDesc::TypeString) { - ((ustring*)val)[0] = m_projection; + ((ustringhash*)val)[0] = m_projection; return true; } return false; @@ -396,8 +417,8 @@ OSLToyRenderer::get_camera_projection(ShaderGlobals* /*sg*/, bool /*derivs*/, bool OSLToyRenderer::get_camera_fov(ShaderGlobals* /*sg*/, bool derivs, - ustring /*object*/, TypeDesc type, - ustring /*name*/, void* val) + ustringhash /*object*/, TypeDesc type, + ustringhash /*name*/, void* val) { // N.B. in a real renderer, this may be time-dependent if (type == TypeDesc::TypeFloat) { @@ -412,8 +433,8 @@ OSLToyRenderer::get_camera_fov(ShaderGlobals* /*sg*/, bool derivs, bool OSLToyRenderer::get_camera_pixelaspect(ShaderGlobals* /*sg*/, bool derivs, - ustring /*object*/, TypeDesc type, - ustring /*name*/, void* val) + ustringhash /*object*/, TypeDesc type, + ustringhash /*name*/, void* val) { if (type == TypeDesc::TypeFloat) { ((float*)val)[0] = m_pixelaspect; @@ -427,8 +448,8 @@ OSLToyRenderer::get_camera_pixelaspect(ShaderGlobals* /*sg*/, bool derivs, bool OSLToyRenderer::get_camera_clip(ShaderGlobals* /*sg*/, bool derivs, - ustring /*object*/, TypeDesc type, - ustring /*name*/, void* val) + ustringhash /*object*/, TypeDesc type, + ustringhash /*name*/, void* val) { if (type == TypeFloatArray2) { ((float*)val)[0] = m_hither; @@ -443,8 +464,8 @@ OSLToyRenderer::get_camera_clip(ShaderGlobals* /*sg*/, bool derivs, bool OSLToyRenderer::get_camera_clip_near(ShaderGlobals* /*sg*/, bool derivs, - ustring /*object*/, TypeDesc type, - ustring /*name*/, void* val) + ustringhash /*object*/, TypeDesc type, + ustringhash /*name*/, void* val) { if (type == TypeDesc::TypeFloat) { ((float*)val)[0] = m_hither; @@ -458,8 +479,8 @@ OSLToyRenderer::get_camera_clip_near(ShaderGlobals* /*sg*/, bool derivs, bool OSLToyRenderer::get_camera_clip_far(ShaderGlobals* /*sg*/, bool derivs, - ustring /*object*/, TypeDesc type, - ustring /*name*/, void* val) + ustringhash /*object*/, TypeDesc type, + ustringhash /*name*/, void* val) { if (type == TypeDesc::TypeFloat) { ((float*)val)[0] = m_yon; @@ -474,8 +495,8 @@ OSLToyRenderer::get_camera_clip_far(ShaderGlobals* /*sg*/, bool derivs, bool OSLToyRenderer::get_camera_shutter(ShaderGlobals* /*sg*/, bool derivs, - ustring /*object*/, TypeDesc type, - ustring /*name*/, void* val) + ustringhash /*object*/, TypeDesc type, + ustringhash /*name*/, void* val) { if (type == TypeFloatArray2) { ((float*)val)[0] = m_shutter[0]; @@ -490,8 +511,8 @@ OSLToyRenderer::get_camera_shutter(ShaderGlobals* /*sg*/, bool derivs, bool OSLToyRenderer::get_camera_shutter_open(ShaderGlobals* /*sg*/, bool derivs, - ustring /*object*/, TypeDesc type, - ustring /*name*/, void* val) + ustringhash /*object*/, TypeDesc type, + ustringhash /*name*/, void* val) { if (type == TypeDesc::TypeFloat) { ((float*)val)[0] = m_shutter[0]; @@ -505,8 +526,8 @@ OSLToyRenderer::get_camera_shutter_open(ShaderGlobals* /*sg*/, bool derivs, bool OSLToyRenderer::get_camera_shutter_close(ShaderGlobals* /*sg*/, bool derivs, - ustring /*object*/, TypeDesc type, - ustring /*name*/, void* val) + ustringhash /*object*/, TypeDesc type, + ustringhash /*name*/, void* val) { if (type == TypeDesc::TypeFloat) { ((float*)val)[0] = m_shutter[1]; @@ -520,8 +541,8 @@ OSLToyRenderer::get_camera_shutter_close(ShaderGlobals* /*sg*/, bool derivs, bool OSLToyRenderer::get_camera_screen_window(ShaderGlobals* /*sg*/, bool derivs, - ustring /*object*/, TypeDesc type, - ustring /*name*/, void* val) + ustringhash /*object*/, TypeDesc type, + ustringhash /*name*/, void* val) { // N.B. in a real renderer, this may be time-dependent if (type == TypeFloatArray4) { diff --git a/src/osltoy/osltoyrenderer.h b/src/osltoy/osltoyrenderer.h index b547e7854..963703891 100644 --- a/src/osltoy/osltoyrenderer.h +++ b/src/osltoy/osltoyrenderer.h @@ -31,7 +31,7 @@ class OSLToyRenderer final : public RendererServices { // Super simple camera and display parameters. Many options not // available, no motion blur, etc. - void camera_params(const Matrix44& world_to_camera, ustring projection, + void camera_params(const Matrix44& world_to_camera, ustringhash projection, float hfov, float hither, float yon, int xres, int yres); void set_resolution(int x, int y) @@ -68,23 +68,24 @@ class OSLToyRenderer final : public RendererServices { virtual int supports(string_view feature) const; virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result, TransformationPtr xform, float time); - virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result, ustring from, - float time); + virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result, + ustringhash from, float time); virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result, TransformationPtr xform); - virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result, ustring from); + virtual bool get_matrix(ShaderGlobals* sg, Matrix44& result, + ustringhash from); virtual bool get_inverse_matrix(ShaderGlobals* sg, Matrix44& result, - ustring to, float time); + ustringhash to, float time); void name_transform(const char* name, const Transformation& xform); virtual bool get_array_attribute(ShaderGlobals* sg, bool derivatives, - ustring object, TypeDesc type, - ustring name, int index, void* val); + ustringhash object, TypeDesc type, + ustringhash name, int index, void* val); virtual bool get_attribute(ShaderGlobals* sg, bool derivatives, - ustring object, TypeDesc type, ustring name, - void* val); - virtual bool get_userdata(bool derivatives, ustring name, TypeDesc type, + ustringhash object, TypeDesc type, + ustringhash name, void* val); + virtual bool get_userdata(bool derivatives, ustringhash name, TypeDesc type, ShaderGlobals* sg, void* val); private: @@ -96,7 +97,7 @@ class OSLToyRenderer final : public RendererServices { // Camera parameters Matrix44 m_world_to_camera; - ustring m_projection; + ustringhash m_projection; float m_fov, m_pixelaspect, m_hither, m_yon; float m_shutter[2]; float m_screen_window[4]; @@ -104,7 +105,7 @@ class OSLToyRenderer final : public RendererServices { int m_mouse_x = -1, m_mouse_y = -1; // Named transforms - typedef std::map> TransformMap; + typedef std::map> TransformMap; TransformMap m_named_xforms; // Attribute and userdata retrieval -- for fast dispatch, use a hash @@ -113,38 +114,44 @@ class OSLToyRenderer final : public RendererServices { // renderer, we would encourage benchmarking various methods and // alternate data structures. typedef bool (OSLToyRenderer::*AttrGetter)(ShaderGlobals* sg, bool derivs, - ustring object, TypeDesc type, - ustring name, void* val); - typedef std::unordered_map AttrGetterMap; + ustringhash object, + TypeDesc type, ustringhash name, + void* val); + typedef std::unordered_map AttrGetterMap; AttrGetterMap m_attr_getters; // Attribute getters - bool get_osl_version(ShaderGlobals* sg, bool derivs, ustring object, - TypeDesc type, ustring name, void* val); - bool get_camera_resolution(ShaderGlobals* sg, bool derivs, ustring object, - TypeDesc type, ustring name, void* val); - bool get_camera_projection(ShaderGlobals* sg, bool derivs, ustring object, - TypeDesc type, ustring name, void* val); - bool get_camera_fov(ShaderGlobals* sg, bool derivs, ustring object, - TypeDesc type, ustring name, void* val); - bool get_camera_pixelaspect(ShaderGlobals* sg, bool derivs, ustring object, - TypeDesc type, ustring name, void* val); - bool get_camera_clip(ShaderGlobals* sg, bool derivs, ustring object, - TypeDesc type, ustring name, void* val); - bool get_camera_clip_near(ShaderGlobals* sg, bool derivs, ustring object, - TypeDesc type, ustring name, void* val); - bool get_camera_clip_far(ShaderGlobals* sg, bool derivs, ustring object, - TypeDesc type, ustring name, void* val); - bool get_camera_shutter(ShaderGlobals* sg, bool derivs, ustring object, - TypeDesc type, ustring name, void* val); - bool get_camera_shutter_open(ShaderGlobals* sg, bool derivs, ustring object, - TypeDesc type, ustring name, void* val); + bool get_osl_version(ShaderGlobals* sg, bool derivs, ustringhash object, + TypeDesc type, ustringhash name, void* val); + bool get_camera_resolution(ShaderGlobals* sg, bool derivs, + ustringhash object, TypeDesc type, + ustringhash name, void* val); + bool get_camera_projection(ShaderGlobals* sg, bool derivs, + ustringhash object, TypeDesc type, + ustringhash name, void* val); + bool get_camera_fov(ShaderGlobals* sg, bool derivs, ustringhash object, + TypeDesc type, ustringhash name, void* val); + bool get_camera_pixelaspect(ShaderGlobals* sg, bool derivs, + ustringhash object, TypeDesc type, + ustringhash name, void* val); + bool get_camera_clip(ShaderGlobals* sg, bool derivs, ustringhash object, + TypeDesc type, ustringhash name, void* val); + bool get_camera_clip_near(ShaderGlobals* sg, bool derivs, + ustringhash object, TypeDesc type, + ustringhash name, void* val); + bool get_camera_clip_far(ShaderGlobals* sg, bool derivs, ustringhash object, + TypeDesc type, ustringhash name, void* val); + bool get_camera_shutter(ShaderGlobals* sg, bool derivs, ustringhash object, + TypeDesc type, ustringhash name, void* val); + bool get_camera_shutter_open(ShaderGlobals* sg, bool derivs, + ustringhash object, TypeDesc type, + ustringhash name, void* val); bool get_camera_shutter_close(ShaderGlobals* sg, bool derivs, - ustring object, TypeDesc type, ustring name, - void* val); + ustringhash object, TypeDesc type, + ustringhash name, void* val); bool get_camera_screen_window(ShaderGlobals* sg, bool derivs, - ustring object, TypeDesc type, ustring name, - void* val); + ustringhash object, TypeDesc type, + ustringhash name, void* val); }; OSL_NAMESPACE_EXIT diff --git a/src/osltoy/rs_strdecls.h b/src/osltoy/rs_strdecls.h new file mode 100644 index 000000000..33ed19a95 --- /dev/null +++ b/src/osltoy/rs_strdecls.h @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + + +// This file contains "declarations" for all the strings that might get used in +// JITed shader code or in renderer code. But the declaration itself is +// dependent on the RS_STRDECL macro, which should be declared by the outer file +// prior to including this file. Thus, this list may be repurposed and included +// multiple times, with different RS_STRDECL definitions. + + +#ifndef RS_STRDECL +# error Do not include this file unless RS_STRDECL is defined +#endif + + +RS_STRDECL("osl:version", osl_version) +RS_STRDECL("camera:resolution", camera_resolution) +RS_STRDECL("camera:projection", camera_projection) +RS_STRDECL("camera:pixelaspect", camera_pixelaspect) +RS_STRDECL("camera:screen_window", camera_screen_window) +RS_STRDECL("camera:fov", camera_fov) +RS_STRDECL("camera:clip", camera_clip) +RS_STRDECL("camera:clip_near", camera_clip_near) +RS_STRDECL("camera:clip_far", camera_clip_far) +RS_STRDECL("camera:shutter", camera_shutter) +RS_STRDECL("camera:shutter_open", camera_shutter_open) +RS_STRDECL("camera:shutter_close", camera_shutter_close) +RS_STRDECL("perspective", perspective) +RS_STRDECL("raster", raster) +RS_STRDECL("myspace", myspace) +RS_STRDECL("options", options) +RS_STRDECL("blahblah", blahblah) +RS_STRDECL("s", s) +RS_STRDECL("t", t) +RS_STRDECL("mouse", mouse) \ No newline at end of file diff --git a/src/testrender/cuda/optix_raytracer.cu b/src/testrender/cuda/optix_raytracer.cu index 43c43c322..43e910db7 100644 --- a/src/testrender/cuda/optix_raytracer.cu +++ b/src/testrender/cuda/optix_raytracer.cu @@ -9,7 +9,7 @@ #include -#include +#include #include "rend_lib.h" #include "render_params.h" diff --git a/src/testrender/cuda/rend_lib.cu b/src/testrender/cuda/rend_lib.cu index e14c5b519..9d59345e7 100644 --- a/src/testrender/cuda/rend_lib.cu +++ b/src/testrender/cuda/rend_lib.cu @@ -253,14 +253,14 @@ osl_add_closure_closure(void* sg_, void* a, void* b) __device__ bool -rend_get_userdata(OSL::StringParam name, void* data, int data_size, +rend_get_userdata(OSL::ustringhash name, void* data, int data_size, const OSL::TypeDesc& type, int index) { // Perform a userdata lookup using the parameter name, type, and // userdata index. If there is a match, memcpy the value into data and // return 1. - if (IS_PTR(type) && name.hash() == STRING_PARAMS(colorsystem)) { + if (IS_PTR(type) && name == OSL::Hashes::colorsystem) { *(void**)data = *reinterpret_cast(&OSL::pvt::s_color_system); return true; } @@ -279,17 +279,17 @@ rend_get_userdata(OSL::StringParam name, void* data, int data_size, __device__ int -osl_bind_interpolated_param(void* sg_, const char* name, long long type, - int userdata_has_derivs, void* userdata_data, - int symbol_has_derivs, void* symbol_data, - int symbol_data_size, char* userdata_initialized, - int userdata_index) +osl_bind_interpolated_param(void* sg_, OSL::ustringhash_pod name_, + long long type, int userdata_has_derivs, + void* userdata_data, int symbol_has_derivs, + void* symbol_data, int symbol_data_size, + char* userdata_initialized, int userdata_index) { char status = *userdata_initialized; if (status == 0) { - bool ok = rend_get_userdata(HDSTR(name), userdata_data, - symbol_data_size, (*(OSL::TypeDesc*)&type), - userdata_index); + OSL::ustringhash name = OSL::ustringhash_from(name_); + bool ok = rend_get_userdata(name, userdata_data, symbol_data_size, + (*(OSL::TypeDesc*)&type), userdata_index); *userdata_initialized = status = 1 + ok; } if (status == 2) { @@ -302,7 +302,7 @@ osl_bind_interpolated_param(void* sg_, const char* name, long long type, __device__ int -osl_strlen_is(const char* str) +osl_strlen_is(OSL::ustringhash_pod str) { //return HDSTR(str).length(); return 0; @@ -310,14 +310,14 @@ osl_strlen_is(const char* str) __device__ int -osl_hash_is(const char* str) +osl_hash_is(OSL::ustringhash_pod str) { - return HDSTR(str); + return static_cast(str); } __device__ int -osl_getchar_isi(const char* str, int index) +osl_getchar_isi(OSL::ustringhash_pod str, int index) { // return (str && unsigned(index) < HDSTR(str).length()) // ? str[index] : 0; @@ -330,10 +330,9 @@ osl_getchar_isi(const char* str, int index) // all the arguments to our print buffer. // Note: the first element of 'args' is the size of the argument list __device__ void -osl_printf(void* sg_, char* fmt_str, void* args) +osl_printf(void* sg_, OSL::ustringhash_pod fmt_str_hash, void* args) { - uint64_t fmt_str_hash = HDSTR(fmt_str).hash(); - uint64_t args_size = reinterpret_cast(args)[0]; + uint64_t args_size = reinterpret_cast(args)[0]; // This can be used to limit printing to one Cuda thread for debugging // if (launch_index.x == 0 && launch_index.y == 0) @@ -407,10 +406,11 @@ extern __device__ float4 osl_tex2DLookup(void* handle, float s, float t); __device__ int -osl_texture(void* sg_, const char* name, void* handle, void* opt_, float s, - float t, float dsdx, float dtdx, float dsdy, float dtdy, int chans, - void* result, void* dresultdx, void* dresultdy, void* alpha, - void* dalphadx, void* dalphady, void* ustring_errormessage) +osl_texture(void* sg_, OSL::ustringhash_pod name, void* handle, void* opt_, + float s, float t, float dsdx, float dtdx, float dsdy, float dtdy, + int chans, void* result, void* dresultdx, void* dresultdy, + void* alpha, void* dalphadx, void* dalphady, + void* ustringhash_errormessage) { if (!handle) return 0; @@ -442,19 +442,20 @@ osl_range_check_err(int indexvalue, int length, OSL::ustringhash_pod symname, #define MAT(m) (*(OSL::Matrix44*)__builtin_assume_aligned(m, alignof(float))) __device__ int -osl_get_matrix(void* sg_, void* r, const char* from) +osl_get_matrix(void* sg_, void* r, OSL::ustringhash_pod from_) { - r = __builtin_assume_aligned(r, alignof(float)); - ShaderGlobals* sg = (ShaderGlobals*)sg_; - if (HDSTR(from) == STRING_PARAMS(common)) { + r = __builtin_assume_aligned(r, alignof(float)); + OSL::ustringhash from = OSL::ustringhash_from(from_); + ShaderGlobals* sg = (ShaderGlobals*)sg_; + if (from == OSL::Hashes::common) { MAT(r).makeIdentity(); return true; } - if (HDSTR(from) == STRING_PARAMS(object)) { + if (from == OSL::Hashes::object) { MAT(r) = MAT(sg->object2common); return true; } - if (HDSTR(from) == STRING_PARAMS(shader)) { + if (from == OSL::Hashes::shader) { MAT(r) = MAT(sg->shader2common); return true; } @@ -462,8 +463,7 @@ osl_get_matrix(void* sg_, void* r, const char* from) // Find the index of the named transform in the transform list int match_idx = -1; for (size_t idx = 0; idx < OSL::pvt::num_named_xforms; ++idx) { - if (HDSTR(from) - == HDSTR(((uint64_t*)OSL::pvt::xform_name_buffer)[idx])) { + if (from == HDSTR(((uint64_t*)OSL::pvt::xform_name_buffer)[idx])) { match_idx = static_cast(idx); break; } @@ -487,20 +487,21 @@ osl_get_matrix(void* sg_, void* r, const char* from) __device__ int -osl_get_inverse_matrix(void* sg_, void* r, const char* to) +osl_get_inverse_matrix(void* sg_, void* r, OSL::ustringhash_pod to_) { - r = __builtin_assume_aligned(r, alignof(float)); - ShaderGlobals* sg = (ShaderGlobals*)sg_; - if (HDSTR(to) == STRING_PARAMS(common)) { + r = __builtin_assume_aligned(r, alignof(float)); + OSL::ustringhash to = OSL::ustringhash_from(to_); + ShaderGlobals* sg = (ShaderGlobals*)sg_; + if (to == OSL::Hashes::common) { MAT(r).makeIdentity(); return true; } - if (HDSTR(to) == STRING_PARAMS(object)) { + if (to == OSL::Hashes::object) { MAT(r) = MAT(sg->object2common); MAT(r).invert(); return true; } - if (HDSTR(to) == STRING_PARAMS(shader)) { + if (to == OSL::Hashes::shader) { MAT(r) = MAT(sg->shader2common); MAT(r).invert(); return true; @@ -509,7 +510,7 @@ osl_get_inverse_matrix(void* sg_, void* r, const char* to) // Find the index of the named transform in the transform list int match_idx = -1; for (size_t idx = 0; idx < OSL::pvt::num_named_xforms; ++idx) { - if (HDSTR(to) == HDSTR(((uint64_t*)OSL::pvt::xform_name_buffer)[idx])) { + if (to == HDSTR(((uint64_t*)OSL::pvt::xform_name_buffer)[idx])) { match_idx = static_cast(idx); break; } diff --git a/src/testrender/cuda/rend_lib.h b/src/testrender/cuda/rend_lib.h index 12ab2e7e7..0fe9a027d 100644 --- a/src/testrender/cuda/rend_lib.h +++ b/src/testrender/cuda/rend_lib.h @@ -14,25 +14,17 @@ # include #endif -#include "../../liboslexec/string_hash.h" +#include #include -#include OSL_NAMESPACE_ENTER -// Create an OptiX variable for each of the 'standard' strings declared in -// . -namespace DeviceStrings { -#define STRING_PARAMS(x) \ - UStringHash::HashConstEval -// Don't declare anything -#define STRDECL(str, var_name) - -#include -#undef STRDECL -} // namespace DeviceStrings +// TODO: update types from char * to ustringhash or ustringhash_pod +// and remove uses of HDSTR +#define HDSTR(cstr) (*((OSL::ustringhash*)&cstr)) + namespace pvt { extern __device__ CUdeviceptr s_color_system; extern __device__ CUdeviceptr osl_printf_buffer_start; diff --git a/src/testrender/cuda/wrapper.cu b/src/testrender/cuda/wrapper.cu index 31a5da14a..79c1dbce9 100644 --- a/src/testrender/cuda/wrapper.cu +++ b/src/testrender/cuda/wrapper.cu @@ -2,13 +2,12 @@ // SPDX-License-Identifier: BSD-3-Clause // https://github.com/AcademySoftwareFoundation/OpenShadingLanguage - +#include #include #include #include -#include #include #include "rend_lib.h" @@ -129,9 +128,9 @@ process_closure(const OSL::ClosureColor* closure_tree) case MICROFACET_ID: { const char* mem = (const char*)((OSL::ClosureComponent*)cur)->data(); - const char* dist_str = *(const char**)&mem[0]; + OSL::ustringhash dist_uh = *(OSL::ustringhash*)&mem[0]; - if (HDSTR(dist_str) == STRING_PARAMS(default)) + if (dist_uh == OSL::Hashes::default_) return make_float3(0.0f, 1.0f, 1.0f); else return make_float3(1.0f, 0.0f, 1.0f); diff --git a/src/testrender/optixraytracer.cpp b/src/testrender/optixraytracer.cpp index 9f58be2fc..a52118b58 100644 --- a/src/testrender/optixraytracer.cpp +++ b/src/testrender/optixraytracer.cpp @@ -209,6 +209,10 @@ OptixRaytracer::synch_attributes() shadingsys->attribute("max_optix_groupdata_alloc", 1024); { + // TODO: utilize opaque shading state uniform data structure + // which has a device friendly representation this data + // and is already accessed directly by opcolor and opmatrix for + // the cpu (just remove optix special casing) char* colorSys = nullptr; long long cpuDataSizes[2] = { 0, 0 }; if (!shadingsys->getattribute("colorsystem", TypeDesc::PTR, @@ -226,10 +230,11 @@ OptixRaytracer::synch_attributes() // Get the size data-size, minus the ustring size const size_t podDataSize = cpuDataSize - - sizeof(StringParam) * numStrings; + - sizeof(ustringhash) * numStrings; - CUDA_CHECK(cudaMalloc(reinterpret_cast(&d_color_system), - podDataSize + sizeof(DeviceString) * numStrings)); + CUDA_CHECK( + cudaMalloc(reinterpret_cast(&d_color_system), + podDataSize + sizeof(ustringhash_pod) * numStrings)); CUDA_CHECK(cudaMemcpy(reinterpret_cast(d_color_system), colorSys, podDataSize, cudaMemcpyHostToDevice)); @@ -240,18 +245,17 @@ OptixRaytracer::synch_attributes() // then copy the device string to the end, first strings starting at dataPtr - (numStrings) // FIXME -- Should probably handle alignment better. - const ustring* cpuString - = (const ustring*)(colorSys - + (cpuDataSize - - sizeof(StringParam) * numStrings)); + const ustringhash* cpuStringHash + = (const ustringhash*)(colorSys + + (cpuDataSize + - sizeof(ustringhash) * numStrings)); CUdeviceptr gpuStrings = d_color_system + podDataSize; - for (const ustring* end = cpuString + numStrings; cpuString < end; - ++cpuString) { - // convert the ustring to a device string - uint64_t devStr = cpuString->hash(); + for (const ustringhash* end = cpuStringHash + numStrings; + cpuStringHash < end; ++cpuStringHash) { + ustringhash_pod devStr = cpuStringHash->hash(); CUDA_CHECK(cudaMemcpy(reinterpret_cast(gpuStrings), &devStr, sizeof(devStr), cudaMemcpyHostToDevice)); - gpuStrings += sizeof(DeviceString); + gpuStrings += sizeof(ustringhash_pod); } } return true; diff --git a/src/testrender/optixraytracer.h b/src/testrender/optixraytracer.h index 199bbd8c0..b331a8422 100644 --- a/src/testrender/optixraytracer.h +++ b/src/testrender/optixraytracer.h @@ -8,7 +8,7 @@ #include -#include +#include #include "optix_compat.h" #include "render_params.h" diff --git a/src/testrender/rs_strdecls.h b/src/testrender/rs_strdecls.h new file mode 100644 index 000000000..6a50572da --- /dev/null +++ b/src/testrender/rs_strdecls.h @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + + +// This file contains "declarations" for all the strings that might get used in +// JITed shader code or in renderer code. But the declaration itself is +// dependent on the RS_STRDECL macro, which should be declared by the outer file +// prior to including this file. Thus, this list may be repurposed and included +// multiple times, with different RS_STRDECL definitions. + + +#ifndef RS_STRDECL +# error Do not include this file unless RS_STRDECL is defined +#endif + + +RS_STRDECL("osl:version", osl_version) +RS_STRDECL("camera:resolution", camera_resolution) +RS_STRDECL("camera:projection", camera_projection) +RS_STRDECL("camera:pixelaspect", camera_pixelaspect) +RS_STRDECL("camera:screen_window", camera_screen_window) +RS_STRDECL("camera:fov", camera_fov) +RS_STRDECL("camera:clip", camera_clip) +RS_STRDECL("camera:clip_near", camera_clip_near) +RS_STRDECL("camera:clip_far", camera_clip_far) +RS_STRDECL("camera:shutter", camera_shutter) +RS_STRDECL("camera:shutter_open", camera_shutter_open) +RS_STRDECL("camera:shutter_close", camera_shutter_close) +RS_STRDECL("perspective", perspective) +RS_STRDECL("raster", raster) +RS_STRDECL("myspace", myspace) +RS_STRDECL("options", options) +RS_STRDECL("blahblah", blahblah) +RS_STRDECL("s", s) +RS_STRDECL("t", t) \ No newline at end of file diff --git a/src/testrender/shading.cpp b/src/testrender/shading.cpp index 0771f5056..799e6b299 100644 --- a/src/testrender/shading.cpp +++ b/src/testrender/shading.cpp @@ -87,7 +87,7 @@ struct RefractionParams { float eta; }; struct MicrofacetParams { - ustring dist; + ustringhash dist; Vec3 N, U; float xalpha, yalpha, eta; int refract; @@ -100,7 +100,7 @@ struct MxOrenNayarDiffuseParams { Color3 albedo; float roughness; // optional - ustring label; + ustringhash label; }; struct MxBurleyDiffuseParams { @@ -108,7 +108,7 @@ struct MxBurleyDiffuseParams { Color3 albedo; float roughness; // optional - ustring label; + ustringhash label; }; // common to all MaterialX microfacet closures @@ -116,9 +116,9 @@ struct MxMicrofacetBaseParams { Vec3 N, U; float roughness_x; float roughness_y; - ustring distribution; + ustringhash distribution; // optional - ustring label; + ustringhash label; }; struct MxDielectricParams : public MxMicrofacetBaseParams { @@ -189,7 +189,7 @@ struct MxTranslucentParams { Vec3 N; Color3 albedo; // optional - ustring label; + ustringhash label; }; struct MxSubsurfaceParams { @@ -199,7 +199,7 @@ struct MxSubsurfaceParams { Color3 transmission_color; float anisotropy; // optional - ustring label; + ustringhash label; }; struct MxSheenParams { @@ -207,13 +207,13 @@ struct MxSheenParams { Color3 albedo; float roughness; // optional - ustring label; + ustringhash label; }; struct MxUniformEdfParams { Color3 emittance; // optional - ustring label; + ustringhash label; }; struct MxLayerParams { @@ -226,7 +226,7 @@ struct MxAnisotropicVdfParams { Color3 extinction; float anisotropy; // optional - ustring label; + ustringhash label; }; struct MxMediumVdfParams { @@ -237,7 +237,7 @@ struct MxMediumVdfParams { float ior; int priority; // optional - ustring label; + ustringhash label; }; } // anonymous namespace @@ -1523,9 +1523,9 @@ process_bsdf_closure(const OSL::ShaderGlobals& sg, ShadingResult& result, const ClosureColor* closure, const Color3& w, bool light_only) { - static const ustring u_ggx("ggx"); - static const ustring u_beckmann("beckmann"); - static const ustring u_default("default"); + static const ustringhash uh_ggx("ggx"); + static const ustringhash uh_beckmann("beckmann"); + static const ustringhash uh_default("default"); if (!closure) return; switch (closure->id) { @@ -1572,7 +1572,7 @@ process_bsdf_closure(const OSL::ShaderGlobals& sg, ShadingResult& result, break; case MICROFACET_ID: { const MicrofacetParams* mp = comp->as(); - if (mp->dist == u_ggx) { + if (mp->dist == uh_ggx) { switch (mp->refract) { case 0: ok = result.bsdf.add_bsdf(cw, *mp); @@ -1584,7 +1584,7 @@ process_bsdf_closure(const OSL::ShaderGlobals& sg, ShadingResult& result, ok = result.bsdf.add_bsdf(cw, *mp); break; } - } else if (mp->dist == u_beckmann || mp->dist == u_default) { + } else if (mp->dist == uh_beckmann || mp->dist == uh_default) { switch (mp->refract) { case 0: ok = result.bsdf.add_bsdf(cw, diff --git a/src/testrender/simpleraytracer.cpp b/src/testrender/simpleraytracer.cpp index 03fa5e7a5..6b3666109 100644 --- a/src/testrender/simpleraytracer.cpp +++ b/src/testrender/simpleraytracer.cpp @@ -11,17 +11,36 @@ namespace pugi = OIIO::pugi; #endif +#include #include "raytracer.h" #include "shading.h" #include "simpleraytracer.h" + +// Create ustrings for all strings used by the free function renderer services. +// Required to allow the reverse mapping of hash->string to work when processing messages +namespace RS { +namespace Strings { +#define RS_STRDECL(str, var_name) const OSL::ustring var_name { str }; +#include "rs_strdecls.h" +#undef RS_STRDECL +} // namespace Strings +} // namespace RS + +namespace RS { +namespace { +namespace Hashes { +#define RS_STRDECL(str, var_name) \ + constexpr OSL::ustringhash var_name(OSL::strhash(str)); +#include "rs_strdecls.h" +#undef RS_STRDECL +}; //namespace Hashes +} // unnamed namespace +}; //namespace RS + using namespace OSL; OSL_NAMESPACE_ENTER -static ustring u_camera("camera"), u_screen("screen"); -static ustring u_NDC("NDC"), u_raster("raster"); -static ustring u_perspective("perspective"); -static ustring u_s("s"), u_t("t"); static TypeDesc TypeFloatArray2(TypeDesc::FLOAT, 2); static TypeDesc TypeFloatArray4(TypeDesc::FLOAT, 4); static TypeDesc TypeIntArray2(TypeDesc::INT, 2); @@ -55,29 +74,29 @@ SimpleRaytracer::SimpleRaytracer() Matrix44 M; M.makeIdentity(); - camera_params(M, u_perspective, 90.0f, 0.1f, 1000.0f, 256, 256); + camera_params(M, RS::Hashes::perspective, 90.0f, 0.1f, 1000.0f, 256, 256); // Set up getters - m_attr_getters[ustring("osl:version")] = &SimpleRaytracer::get_osl_version; - m_attr_getters[ustring("camera:resolution")] + m_attr_getters[RS::Hashes::osl_version] = &SimpleRaytracer::get_osl_version; + m_attr_getters[RS::Hashes::camera_resolution] = &SimpleRaytracer::get_camera_resolution; - m_attr_getters[ustring("camera:projection")] + m_attr_getters[RS::Hashes::camera_projection] = &SimpleRaytracer::get_camera_projection; - m_attr_getters[ustring("camera:pixelaspect")] + m_attr_getters[RS::Hashes::camera_pixelaspect] = &SimpleRaytracer::get_camera_pixelaspect; - m_attr_getters[ustring("camera:screen_window")] + m_attr_getters[RS::Hashes::camera_screen_window] = &SimpleRaytracer::get_camera_screen_window; - m_attr_getters[ustring("camera:fov")] = &SimpleRaytracer::get_camera_fov; - m_attr_getters[ustring("camera:clip")] = &SimpleRaytracer::get_camera_clip; - m_attr_getters[ustring("camera:clip_near")] + m_attr_getters[RS::Hashes::camera_fov] = &SimpleRaytracer::get_camera_fov; + m_attr_getters[RS::Hashes::camera_clip] = &SimpleRaytracer::get_camera_clip; + m_attr_getters[RS::Hashes::camera_clip_near] = &SimpleRaytracer::get_camera_clip_near; - m_attr_getters[ustring("camera:clip_far")] + m_attr_getters[RS::Hashes::camera_clip_far] = &SimpleRaytracer::get_camera_clip_far; - m_attr_getters[ustring("camera:shutter")] + m_attr_getters[RS::Hashes::camera_shutter] = &SimpleRaytracer::get_camera_shutter; - m_attr_getters[ustring("camera:shutter_open")] + m_attr_getters[RS::Hashes::camera_shutter_open] = &SimpleRaytracer::get_camera_shutter_open; - m_attr_getters[ustring("camera:shutter_close")] + m_attr_getters[RS::Hashes::camera_shutter_close] = &SimpleRaytracer::get_camera_shutter_close; } @@ -125,7 +144,7 @@ SimpleRaytracer::attribute(string_view name, TypeDesc type, const void* value) void SimpleRaytracer::camera_params(const Matrix44& world_to_camera, - ustring projection, float hfov, float hither, + ustringhash projection, float hfov, float hither, float yon, int xres, int yres) { m_world_to_camera = world_to_camera; @@ -487,12 +506,13 @@ bool SimpleRaytracer::get_inverse_matrix(ShaderGlobals* /*sg*/, Matrix44& result, ustringhash to, float /*time*/) { - if (to == u_camera || to == u_screen || to == u_NDC || to == u_raster) { + if (to == OSL::Hashes::camera || to == OSL::Hashes::screen + || to == OSL::Hashes::NDC || to == RS::Hashes::raster) { // clang-format off Matrix44 M = m_world_to_camera; - if (to == u_screen || to == u_NDC || to == u_raster) { + if (to == OSL::Hashes::screen || to == OSL::Hashes::NDC || to == RS::Hashes::raster) { float depthrange = (double)m_yon-(double)m_hither; - if (m_projection == u_perspective) { + if (m_projection == RS::Hashes::perspective) { float tanhalffov = tanf (0.5f * m_fov * M_PI/180.0); Matrix44 camera_to_screen (1/tanhalffov, 0, 0, 0, 0, 1/tanhalffov, 0, 0, @@ -506,7 +526,7 @@ SimpleRaytracer::get_inverse_matrix(ShaderGlobals* /*sg*/, Matrix44& result, 0, 0, -m_hither/depthrange, 1); M = M * camera_to_screen; } - if (to == u_NDC || to == u_raster) { + if (to == OSL::Hashes::NDC || to == RS::Hashes::raster) { float screenleft = -1.0, screenwidth = 2.0; float screenbottom = -1.0, screenheight = 2.0; Matrix44 screen_to_ndc (1/screenwidth, 0, 0, 0, @@ -514,7 +534,7 @@ SimpleRaytracer::get_inverse_matrix(ShaderGlobals* /*sg*/, Matrix44& result, 0, 0, 1, 0, -screenleft/screenwidth, -screenbottom/screenheight, 0, 1); M = M * screen_to_ndc; - if (to == u_raster) { + if (to == RS::Hashes::raster) { Matrix44 ndc_to_raster (camera.xres, 0, 0, 0, 0, camera.yres, 0, 0, 0, 0, 1, 0, @@ -589,7 +609,7 @@ SimpleRaytracer::get_userdata(bool derivatives, ustringhash name, TypeDesc type, // look up something specific to the primitive, rather than have hard- // coded names. - if (name == u_s && type == TypeDesc::TypeFloat) { + if (name == RS::Hashes::s && type == TypeDesc::TypeFloat) { ((float*)val)[0] = sg->u; if (derivatives) { ((float*)val)[1] = sg->dudx; @@ -597,7 +617,7 @@ SimpleRaytracer::get_userdata(bool derivatives, ustringhash name, TypeDesc type, } return true; } - if (name == u_t && type == TypeDesc::TypeFloat) { + if (name == RS::Hashes::t && type == TypeDesc::TypeFloat) { ((float*)val)[0] = sg->v; if (derivatives) { ((float*)val)[1] = sg->dvdx; @@ -643,7 +663,7 @@ SimpleRaytracer::get_camera_projection(ShaderGlobals* /*sg*/, bool /*derivs*/, ustringhash /*name*/, void* val) { if (type == TypeDesc::TypeString) { - ((ustring*)val)[0] = m_projection; + ((ustringhash*)val)[0] = m_projection; return true; } return false; diff --git a/src/testrender/simpleraytracer.h b/src/testrender/simpleraytracer.h index 7220a39d8..fbddf68c5 100644 --- a/src/testrender/simpleraytracer.h +++ b/src/testrender/simpleraytracer.h @@ -9,7 +9,6 @@ #include #include -#include #include #include @@ -76,7 +75,7 @@ class SimpleRaytracer : public RendererServices { // Super simple camera and display parameters. Many options not // available, no motion blur, etc. virtual void camera_params(const Matrix44& world_to_camera, - ustring projection, float hfov, float hither, + ustringhash projection, float hfov, float hither, float yon, int xres, int yres); virtual void parse_scene_xml(const std::string& scenefile); @@ -103,7 +102,7 @@ class SimpleRaytracer : public RendererServices { private: // Camera parameters Matrix44 m_world_to_camera; - ustring m_projection; + ustringhash m_projection; float m_fov, m_pixelaspect, m_hither, m_yon; float m_shutter[2]; float m_screen_window[4]; diff --git a/src/testshade/batched_simplerend.cpp b/src/testshade/batched_simplerend.cpp index 86d51c262..937655af4 100644 --- a/src/testshade/batched_simplerend.cpp +++ b/src/testshade/batched_simplerend.cpp @@ -884,7 +884,7 @@ BatchedSimpleRenderer::get_camera_projection(ustringhash /*object*/, ustringhash /*name*/, RefOrMaskedT data) { - return assign_and_zero_derivs(data, m_sr.m_projection); + return assign_and_zero_derivs(data, OSL::ustring_from(m_sr.m_projection)); } diff --git a/src/testshade/cuda/optix_grid_renderer.cu b/src/testshade/cuda/optix_grid_renderer.cu index e73a149c4..1304e9bfa 100644 --- a/src/testshade/cuda/optix_grid_renderer.cu +++ b/src/testshade/cuda/optix_grid_renderer.cu @@ -82,9 +82,17 @@ __raygen__() auto sbtdata = reinterpret_cast(optixGetSbtDataPointer()); + const float invw = render_params.invw; + const float invh = render_params.invh; + bool flipv = render_params.flipv; + float3* output_buffer = reinterpret_cast( + render_params.output_buffer); + + // Compute the pixel coordinates - float2 d = make_float2(static_cast(launch_index.x) + 0.5f, - static_cast(launch_index.y) + 0.5f); + // Matching testshade's setup_shaderglobals for !pixelcenters + float2 d = make_float2((launch_dims.x == 1) ? 0.5f : invw * launch_index.x, + (launch_dims.y == 1) ? 0.5f : invh * launch_index.y); // TODO: Fixed-sized allocations can easily be exceeded by arbitrary shader // networks, so there should be (at least) some mechanism to issue a @@ -93,20 +101,14 @@ __raygen__() alignas(8) char closure_pool[256]; alignas(8) char params[256]; - const float invw = render_params.invw; - const float invh = render_params.invh; - bool flipv = render_params.flipv; - float3* output_buffer = reinterpret_cast( - render_params.output_buffer); - ShaderGlobals sg; // Setup the ShaderGlobals sg.I = make_float3(0, 0, 1); sg.N = make_float3(0, 0, 1); sg.Ng = make_float3(0, 0, 1); sg.P = make_float3(d.x, d.y, 0); - sg.u = d.x * invw; - sg.v = d.y * invh; + sg.u = d.x; + sg.v = d.y; if (flipv) sg.v = 1.f - sg.v; @@ -114,11 +116,10 @@ __raygen__() sg.dudy = 0; sg.dvdx = 0; sg.dvdy = invh; - sg.dPdu = make_float3(d.x, 0, 0); - sg.dPdv = make_float3(0, d.y, 0); - sg.dPdu = make_float3(1.f / invw, 0.f, 0.f); - sg.dPdv = make_float3(0.0f, 1.f / invh, 0.f); + // Matching testshade's setup_shaderglobals + sg.dPdu = make_float3(1.f, 0.f, 0.f); + sg.dPdv = make_float3(0.f, 1.f, 0.f); sg.dPdx = make_float3(1.f, 0.f, 0.f); sg.dPdy = make_float3(0.f, 1.f, 0.f); diff --git a/src/testshade/optixgridrender.cpp b/src/testshade/optixgridrender.cpp index 23876e9f4..ff64029cc 100644 --- a/src/testshade/optixgridrender.cpp +++ b/src/testshade/optixgridrender.cpp @@ -226,6 +226,10 @@ OptixGridRenderer::synch_attributes() { char* colorSys = nullptr; long long cpuDataSizes[2] = { 0, 0 }; + // TODO: utilize opaque shading state uniform data structure + // which has a device friendly representation this data + // and is already accessed directly by opcolor and opmatrix for + // the cpu (just remove optix special casing) if (!shadingsys->getattribute("colorsystem", TypeDesc::PTR, (void*)&colorSys) || !shadingsys->getattribute("colorsystem:sizes", @@ -241,7 +245,7 @@ OptixGridRenderer::synch_attributes() // Get the size data-size, minus the ustring size const size_t podDataSize = cpuDataSize - - sizeof(StringParam) * numStrings; + - sizeof(ustringhash) * numStrings; CUDA_CHECK(cudaMalloc(reinterpret_cast(&d_color_system), podDataSize + sizeof(uint64_t) * numStrings)); @@ -269,18 +273,17 @@ OptixGridRenderer::synch_attributes() // then copy the device string to the end, first strings starting at dataPtr - (numStrings) // FIXME -- Should probably handle alignment better. - const ustring* cpuString - = (const ustring*)(colorSys - + (cpuDataSize - - sizeof(StringParam) * numStrings)); + const ustringhash* cpuStringHash + = (const ustringhash*)(colorSys + + (cpuDataSize + - sizeof(ustringhash) * numStrings)); CUdeviceptr gpuStrings = d_color_system + podDataSize; - for (const ustring* end = cpuString + numStrings; cpuString < end; - ++cpuString) { - // convert the ustring to a device string - uint64_t devStr = cpuString->hash(); + for (const ustringhash* end = cpuStringHash + numStrings; + cpuStringHash < end; ++cpuStringHash) { + ustringhash_pod devStr = cpuStringHash->hash(); CUDA_CHECK(cudaMemcpy(reinterpret_cast(gpuStrings), &devStr, sizeof(devStr), cudaMemcpyHostToDevice)); - gpuStrings += sizeof(DeviceString); + gpuStrings += sizeof(ustringhash_pod); } } return true; @@ -916,8 +919,8 @@ OptixGridRenderer::render(int xres OSL_MAYBE_UNUSED, int yres OSL_MAYBE_UNUSED) m_yres = yres; RenderParams params; - params.invw = 1.0f / m_xres; - params.invh = 1.0f / m_yres; + params.invw = 1.0f / std::max(1, m_xres - 1); + params.invh = 1.0f / std::max(1, m_yres - 1); params.flipv = false; /* I don't see flipv being initialized anywhere */ params.output_buffer = d_output_buffer; params.osl_printf_buffer_start = d_osl_printf_buffer; diff --git a/src/testshade/optixgridrender.h b/src/testshade/optixgridrender.h index 70f1feeb6..5f630f922 100644 --- a/src/testshade/optixgridrender.h +++ b/src/testshade/optixgridrender.h @@ -8,7 +8,7 @@ #include -#include +#include #include "optix_compat.h" #include "simplerend.h" diff --git a/src/testshade/render_state.h b/src/testshade/render_state.h index 344459373..8aec4954f 100644 --- a/src/testshade/render_state.h +++ b/src/testshade/render_state.h @@ -4,10 +4,9 @@ #pragma once +#include #include -#include // for StringParam - // All the the state free functions in rs_simplerend.cpp will need to do their job // NOTE: Additional data is here that will be used by rs_simplerend.cpp in future PR's // procedurally generating ShaderGlobals. @@ -15,7 +14,7 @@ struct RenderState { int xres; int yres; OSL::Matrix44 world_to_camera; - OSL::StringParam projection; + OSL::ustringhash projection; float pixelaspect; float screen_window[4]; float shutter[2]; @@ -24,3 +23,18 @@ struct RenderState { float yon; void* journal_buffer; }; + + +// Create constexpr hashes for all strings used by the free function renderer services. +// NOTE: Actually ustring's should also be instantiated in host code someplace as well +// to allow the reverse mapping of hash->string to work when processing messages +namespace RS { +namespace { +namespace Hashes { +#define RS_STRDECL(str, var_name) \ + constexpr OSL::ustringhash var_name(OSL::strhash(str)); +#include "rs_strdecls.h" +#undef RS_STRDECL +}; //namespace Hashes +} // unnamed namespace +}; //namespace RS diff --git a/src/testshade/rs_simplerend.cpp b/src/testshade/rs_simplerend.cpp index b6c9897d4..86c653fea 100644 --- a/src/testshade/rs_simplerend.cpp +++ b/src/testshade/rs_simplerend.cpp @@ -13,19 +13,6 @@ #include "render_state.h" -// Extern all global string variables used by free function renderer services. -// NOTE: C linkage with a "RS_" prefix is used to allow for unmangled -// non-colliding global symbol names, so its easier to pass them to -// OSL::register_JIT_Global(name, addr) for host execution -// NOTE: the STRING_PARAMS macro adapts to OSL_HOST_RS_BITCODE -// to utilize the RS_ prefix. RS_ prefixed versions of all OSL::Strings -// instances have been created by rs_free_function.h, so the same STRING_PARAMS -// macro can be used for renderer service or OSL strings. -#define RS_STRDECL(str, var_name) extern "C" OSL::ustring RS_##var_name; -#include "rs_strdecls.h" -#undef RS_STRDECL - - // Keep free functions in sync with virtual function based SimpleRenderer. OSL_RSOP bool @@ -54,10 +41,10 @@ rs_get_inverse_matrix_xform_time(OSL::OpaqueExecContextPtr ec, OSL_RSOP bool rs_get_matrix_space_time(OSL::OpaqueExecContextPtr /*ec*/, - OSL::Matrix44& result, OSL::StringParam from, + OSL::Matrix44& result, OSL::ustringhash from, float /*time*/) { - if (from == STRING_PARAMS(myspace)) { + if (from == RS::Hashes::myspace) { OSL::Matrix44 Mmyspace; Mmyspace.scale(OSL::Vec3(1.0, 2.0, 1.0)); result = Mmyspace; @@ -69,22 +56,23 @@ rs_get_matrix_space_time(OSL::OpaqueExecContextPtr /*ec*/, OSL_RSOP bool rs_get_inverse_matrix_space_time(OSL::OpaqueExecContextPtr ec, - OSL::Matrix44& result, OSL::StringParam to, + OSL::Matrix44& result, OSL::ustringhash to, float time) { using OSL::Matrix44; + auto rs = OSL::get_rs(ec); - if (to == STRING_PARAMS(camera) || to == STRING_PARAMS(screen) - || to == STRING_PARAMS(NDC) || to == STRING_PARAMS(raster)) { + if (to == OSL::Hashes::camera || to == OSL::Hashes::screen + || to == OSL::Hashes::NDC || to == RS::Hashes::raster) { Matrix44 M { rs->world_to_camera }; - if (to == STRING_PARAMS(screen) || to == STRING_PARAMS(NDC) - || to == STRING_PARAMS(raster)) { - float depthrange = (double)rs->yon - (double)rs->hither; - const auto& proj = rs->projection; + if (to == OSL::Hashes::screen || to == OSL::Hashes::NDC + || to == RS::Hashes::raster) { + float depthrange = (double)rs->yon - (double)rs->hither; + OSL::ustringhash proj = rs->projection; - if (proj == STRING_PARAMS(perspective)) { + if (proj == RS::Hashes::perspective) { float tanhalffov = OIIO::fast_tan(0.5f * rs->fov * M_PI / 180.0); // clang-format off @@ -103,7 +91,7 @@ rs_get_inverse_matrix_space_time(OSL::OpaqueExecContextPtr ec, // clang-format on M = M * camera_to_screen; } - if (to == STRING_PARAMS(NDC) || to == STRING_PARAMS(raster)) { + if (to == OSL::Hashes::NDC || to == RS::Hashes::raster) { float screenleft = -1.0, screenwidth = 2.0; float screenbottom = -1.0, screenheight = 2.0; // clang-format off @@ -113,7 +101,7 @@ rs_get_inverse_matrix_space_time(OSL::OpaqueExecContextPtr ec, -screenleft/screenwidth, -screenbottom/screenheight, 0, 1); // clang-format on M = M * screen_to_ndc; - if (to == STRING_PARAMS(raster)) { + if (to == RS::Hashes::raster) { // clang-format off Matrix44 ndc_to_raster (rs->xres, 0, 0, 0, 0, rs->yres, 0, 0, @@ -162,9 +150,9 @@ rs_get_inverse_matrix_xform(OSL::OpaqueExecContextPtr ec, OSL::Matrix44& result, OSL_RSOP bool rs_get_matrix_space(OSL::OpaqueExecContextPtr /*ec*/, OSL::Matrix44& /*result*/, - OSL::StringParam from) + OSL::ustringhash from) { - if (from == STRING_PARAMS(myspace)) { + if (from == RS::Hashes::myspace) { return true; } else { return false; @@ -173,7 +161,7 @@ rs_get_matrix_space(OSL::OpaqueExecContextPtr /*ec*/, OSL::Matrix44& /*result*/, OSL_RSOP bool rs_get_inverse_matrix_space(OSL::OpaqueExecContextPtr ec, OSL::Matrix44& result, - OSL::StringParam to) + OSL::ustringhash to) { bool ok = rs_get_matrix_space(ec, result, to); if (ok) { @@ -183,8 +171,8 @@ rs_get_inverse_matrix_space(OSL::OpaqueExecContextPtr ec, OSL::Matrix44& result, } OSL_RSOP bool -rs_transform_points(OSL::OpaqueExecContextPtr /*ec*/, OSL::StringParam /*from*/, - OSL::StringParam /*to*/, float /*time*/, +rs_transform_points(OSL::OpaqueExecContextPtr /*ec*/, OSL::ustringhash /*from*/, + OSL::ustringhash /*to*/, float /*time*/, const OSL::Vec3* /*Pin*/, OSL::Vec3* /*Pout*/, int /*npoints*/, OSL::TypeDesc::VECSEMANTICS /*vectype*/) { @@ -192,9 +180,9 @@ rs_transform_points(OSL::OpaqueExecContextPtr /*ec*/, OSL::StringParam /*from*/, } OSL_RSOP bool -rs_get_attribute_constant_string(OSL::StringParam value, void* result) +rs_get_attribute_constant_string(OSL::ustringhash value, void* result) { - reinterpret_cast(result)[0] = value; + reinterpret_cast(result)[0] = value; return true; } @@ -299,74 +287,81 @@ rs_get_attribute_constant_float4(float value1, float value2, float value3, } OSL_RSOP bool -rs_get_shade_index(void* _sg, void* result) +rs_get_shade_index(OSL::OpaqueExecContextPtr oec, void* result) + { - reinterpret_cast(result)[0] = OSL::get_shade_index(_sg); + reinterpret_cast(result)[0] = OSL::get_shade_index(oec); return true; } OSL_RSOP bool -rs_get_attribute(void* _sg, const char* _object, const char* _name, - OSL::TypeDesc_pod _type, bool derivatives, int index, - void* result) +rs_get_attribute(OSL::OpaqueExecContextPtr oec, OSL::ustringhash_pod object_, + OSL::ustringhash_pod name_, OSL::TypeDesc_pod _type, + bool derivatives, int index, void* result) { - OSL::ShaderGlobals* sg = reinterpret_cast(_sg); - const OSL::StringParam object = OSL::bitcast(_object); - const OSL::StringParam name = OSL::bitcast(_name); - const OSL::TypeDesc type = OSL::TypeDesc_from(_type); - - const RenderState* rs = reinterpret_cast(sg->renderstate); + auto object = OSL::ustringhash_from(object_); + auto name = OSL::ustringhash_from(name_); + const OSL::TypeDesc type = OSL::TypeDesc_from(_type); + auto rs = OSL::get_rs(oec); // The many branches in the code below handle the case where we don't know // the attribute name at compile time. In the case it is known, dead-code // elimination should optimize this to only the relevant branch. - if (name == STRING_PARAMS(osl_version) && type == OSL::TypeInt) + if (name == RS::Hashes::osl_version && type == OSL::TypeInt) return rs_get_attribute_constant_int(OSL_VERSION, result); - if (name == STRING_PARAMS(camera_resolution) + if (name == RS::Hashes::camera_resolution && type == OSL::TypeDesc(OSL::TypeDesc::INT, 2)) return rs_get_attribute_constant_int2(rs->xres, rs->yres, result); - if (name == STRING_PARAMS(camera_projection) && type == OSL::TypeString) + if (name == RS::Hashes::camera_projection && type == OSL::TypeString) return rs_get_attribute_constant_string(rs->projection, result); - if (name == STRING_PARAMS(camera_pixelaspect) && type == OSL::TypeFloat) + if (name == RS::Hashes::camera_pixelaspect && type == OSL::TypeFloat) return rs_get_attribute_constant_float(rs->pixelaspect, derivatives, result); - if (name == STRING_PARAMS(camera_screen_window) + if (name == RS::Hashes::camera_screen_window && type == OSL::TypeDesc(OSL::TypeDesc::FLOAT, 4)) return rs_get_attribute_constant_float4(rs->screen_window[0], rs->screen_window[1], rs->screen_window[2], rs->screen_window[3], derivatives, result); - if (name == STRING_PARAMS(camera_fov) && type == OSL::TypeFloat) + if (name == RS::Hashes::camera_fov && type == OSL::TypeFloat) return rs_get_attribute_constant_float(rs->fov, derivatives, result); - if (name == STRING_PARAMS(camera_clip) + if (name == RS::Hashes::camera_clip && type == OSL::TypeDesc(OSL::TypeDesc::FLOAT, 2)) return rs_get_attribute_constant_float2(rs->hither, rs->yon, derivatives, result); - if (name == STRING_PARAMS(camera_clip_near) && type == OSL::TypeFloat) + if (name == RS::Hashes::camera_clip_near && type == OSL::TypeFloat) return rs_get_attribute_constant_float(rs->hither, derivatives, result); - if (name == STRING_PARAMS(camera_clip_far) && type == OSL::TypeFloat) + if (name == RS::Hashes::camera_clip_far && type == OSL::TypeFloat) return rs_get_attribute_constant_float(rs->yon, derivatives, result); - if (name == STRING_PARAMS(camera_shutter) + if (name == RS::Hashes::camera_shutter && type == OSL::TypeDesc(OSL::TypeDesc::FLOAT, 2)) return rs_get_attribute_constant_float2(rs->shutter[0], rs->shutter[1], derivatives, result); - if (name == STRING_PARAMS(camera_shutter_open) && type == OSL::TypeFloat) + if (name == RS::Hashes::camera_shutter_open && type == OSL::TypeFloat) return rs_get_attribute_constant_float(rs->shutter[0], derivatives, result); - if (name == STRING_PARAMS(camera_shutter_close) && type == OSL::TypeFloat) + if (name == RS::Hashes::camera_shutter_close && type == OSL::TypeFloat) return rs_get_attribute_constant_float(rs->shutter[1], derivatives, result); - if (name == STRING_PARAMS(shading_index) && type == OSL::TypeInt) - return rs_get_shade_index(sg, result); + if (name == RS::Hashes::shading_index && type == OSL::TypeInt) + return rs_get_shade_index(oec, result); - if (object == STRING_PARAMS(options) && name == STRING_PARAMS(blahblah) + if (object == RS::Hashes::options && name == RS::Hashes::blahblah && type == OSL::TypeFloat) return rs_get_attribute_constant_float(3.14159f, derivatives, result); - if (object.empty()) +#ifndef __CUDA_ARCH__ + if (object.empty()) { + // TODO: implement a true free function version of rs_get_userdata + // that only uses data from RenderState. Because that isn't done + // yet, for host only compilation we break encapsulation and cast + // to gain access to the virtual RendererServices. + auto sg = reinterpret_cast(oec); return sg->renderer->get_userdata(derivatives, name, type, sg, result); + } +#endif return false; } diff --git a/src/testshade/rs_strdecls.h b/src/testshade/rs_strdecls.h index b05b158e1..97917bfc6 100644 --- a/src/testshade/rs_strdecls.h +++ b/src/testshade/rs_strdecls.h @@ -32,3 +32,8 @@ RS_STRDECL("myspace", myspace) RS_STRDECL("options", options) RS_STRDECL("blahblah", blahblah) RS_STRDECL("shading:index", shading_index) +RS_STRDECL("s", s) +RS_STRDECL("t", t) +RS_STRDECL("red", red) +RS_STRDECL("green", green) +RS_STRDECL("blue", blue) \ No newline at end of file diff --git a/src/testshade/simplerend.cpp b/src/testshade/simplerend.cpp index 00e66d0c4..5d769caf1 100644 --- a/src/testshade/simplerend.cpp +++ b/src/testshade/simplerend.cpp @@ -7,22 +7,22 @@ #include #include +#include #include #include #include "simplerend.h" -// Instance all global string variables used by SimpleRend.cpp or -// rs_simplerend.cpp (free functions). -// NOTE: C linkage with a "RS_" prefix is used to allow for unmangled -// non-colliding global symbol names, so its easier to pass them to -// OSL::register_JIT_Global(name, addr) for host execution -extern "C" { -#define RS_STRDECL(str, var_name) OSL::ustring RS_##var_name { str }; +// Create ustrings for all strings used by the free function renderer services. +// Required to allow the reverse mapping of hash->string to work when processing messages +namespace RS { +namespace Strings { +#define RS_STRDECL(str, var_name) const OSL::ustring var_name { str }; #include "rs_strdecls.h" #undef RS_STRDECL -} +} // namespace Strings +} // namespace RS using namespace OSL; @@ -111,11 +111,6 @@ struct ParameterTestParams { OSL_NAMESPACE_ENTER -static ustring u_camera("camera"), u_screen("screen"); -static ustring u_NDC("NDC"), u_raster("raster"); -static ustring u_perspective("perspective"); -static ustring u_s("s"), u_t("t"); -static ustring u_red("red"), u_green("green"), u_blue("blue"); static TypeDesc TypeFloatArray2(TypeDesc::FLOAT, 2); static TypeDesc TypeFloatArray4(TypeDesc::FLOAT, 4); static TypeDesc TypeIntArray2(TypeDesc::INT, 2); @@ -228,29 +223,29 @@ SimpleRenderer::SimpleRenderer() { Matrix44 M; M.makeIdentity(); - camera_params(M, u_perspective, 90.0f, 0.1f, 1000.0f, 256, 256); + camera_params(M, RS::Hashes::perspective, 90.0f, 0.1f, 1000.0f, 256, 256); // Set up getters - m_attr_getters[ustring("osl:version")] = &SimpleRenderer::get_osl_version; - m_attr_getters[ustring("camera:resolution")] + m_attr_getters[RS::Hashes::osl_version] = &SimpleRenderer::get_osl_version; + m_attr_getters[RS::Hashes::camera_resolution] = &SimpleRenderer::get_camera_resolution; - m_attr_getters[ustring("camera:projection")] + m_attr_getters[RS::Hashes::camera_projection] = &SimpleRenderer::get_camera_projection; - m_attr_getters[ustring("camera:pixelaspect")] + m_attr_getters[RS::Hashes::camera_pixelaspect] = &SimpleRenderer::get_camera_pixelaspect; - m_attr_getters[ustring("camera:screen_window")] + m_attr_getters[RS::Hashes::camera_screen_window] = &SimpleRenderer::get_camera_screen_window; - m_attr_getters[ustring("camera:fov")] = &SimpleRenderer::get_camera_fov; - m_attr_getters[ustring("camera:clip")] = &SimpleRenderer::get_camera_clip; - m_attr_getters[ustring("camera:clip_near")] + m_attr_getters[RS::Hashes::camera_fov] = &SimpleRenderer::get_camera_fov; + m_attr_getters[RS::Hashes::camera_clip] = &SimpleRenderer::get_camera_clip; + m_attr_getters[RS::Hashes::camera_clip_near] = &SimpleRenderer::get_camera_clip_near; - m_attr_getters[ustring("camera:clip_far")] + m_attr_getters[RS::Hashes::camera_clip_far] = &SimpleRenderer::get_camera_clip_far; - m_attr_getters[ustring("camera:shutter")] + m_attr_getters[RS::Hashes::camera_shutter] = &SimpleRenderer::get_camera_shutter; - m_attr_getters[ustring("camera:shutter_open")] + m_attr_getters[RS::Hashes::camera_shutter_open] = &SimpleRenderer::get_camera_shutter_open; - m_attr_getters[ustring("camera:shutter_close")] + m_attr_getters[RS::Hashes::camera_shutter_close] = &SimpleRenderer::get_camera_shutter_close; } @@ -309,16 +304,12 @@ SimpleRenderer::attribute(string_view name, TypeDesc type, const void* value) void SimpleRenderer::register_JIT_Global_Variables() //callable from testshade { -#define RS_STRDECL(str, var_name) \ - OSL::register_JIT_Global(__OSL_STRINGIFY(RS_##var_name), &RS_##var_name); -#include "rs_strdecls.h" -#undef RS_STRDECL } void SimpleRenderer::camera_params(const Matrix44& world_to_camera, - ustring projection, float hfov, float hither, + ustringhash projection, float hfov, float hither, float yon, int xres, int yres) { m_world_to_camera = world_to_camera; @@ -400,11 +391,13 @@ bool SimpleRenderer::get_inverse_matrix(ShaderGlobals* /*sg*/, Matrix44& result, ustringhash to, float /*time*/) { - if (to == u_camera || to == u_screen || to == u_NDC || to == u_raster) { + if (to == OSL::Hashes::camera || to == OSL::Hashes::screen + || to == OSL::Hashes::NDC || to == RS::Hashes::raster) { Matrix44 M = m_world_to_camera; - if (to == u_screen || to == u_NDC || to == u_raster) { + if (to == OSL::Hashes::screen || to == OSL::Hashes::NDC + || to == RS::Hashes::raster) { float depthrange = (double)m_yon - (double)m_hither; - if (m_projection == u_perspective) { + if (m_projection == RS::Hashes::perspective) { float tanhalffov = tanf(0.5f * m_fov * M_PI / 180.0); Matrix44 camera_to_screen(1 / tanhalffov, 0, 0, 0, 0, 1 / tanhalffov, 0, 0, 0, 0, @@ -417,7 +410,7 @@ SimpleRenderer::get_inverse_matrix(ShaderGlobals* /*sg*/, Matrix44& result, -m_hither / depthrange, 1); M = M * camera_to_screen; } - if (to == u_NDC || to == u_raster) { + if (to == OSL::Hashes::NDC || to == RS::Hashes::raster) { float screenleft = -1.0, screenwidth = 2.0; float screenbottom = -1.0, screenheight = 2.0; Matrix44 screen_to_ndc(1 / screenwidth, 0, 0, 0, 0, @@ -425,7 +418,7 @@ SimpleRenderer::get_inverse_matrix(ShaderGlobals* /*sg*/, Matrix44& result, -screenleft / screenwidth, -screenbottom / screenheight, 0, 1); M = M * screen_to_ndc; - if (to == u_raster) { + if (to == RS::Hashes::raster) { Matrix44 ndc_to_raster(m_xres, 0, 0, 0, 0, m_yres, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); M = M * ndc_to_raster; @@ -470,13 +463,13 @@ SimpleRenderer::get_array_attribute(ShaderGlobals* sg, bool derivatives, // In order to test getattribute(), respond positively to // "options"/"blahblah" - if (object == "options" && name == "blahblah" + if (object == RS::Hashes::options && name == RS::Hashes::blahblah && type == TypeDesc::TypeFloat) { *(float*)val = 3.14159; return true; } - if (object.empty() && name == "shading:index" + if (object.empty() && name == RS::Hashes::shading_index && type == TypeDesc::TypeInt) { *(int*)val = OSL::get_shade_index(sg); return true; @@ -511,7 +504,7 @@ SimpleRenderer::get_userdata(bool derivatives, ustringhash name, TypeDesc type, // look up something specific to the primitive, rather than have hard- // coded names. - if (name == u_s && type == TypeDesc::TypeFloat) { + if (name == RS::Hashes::s && type == TypeDesc::TypeFloat) { ((float*)val)[0] = sg->u; if (derivatives) { ((float*)val)[1] = sg->dudx; @@ -519,7 +512,7 @@ SimpleRenderer::get_userdata(bool derivatives, ustringhash name, TypeDesc type, } return true; } - if (name == u_t && type == TypeDesc::TypeFloat) { + if (name == RS::Hashes::t && type == TypeDesc::TypeFloat) { ((float*)val)[0] = sg->v; if (derivatives) { ((float*)val)[1] = sg->dvdx; @@ -527,7 +520,8 @@ SimpleRenderer::get_userdata(bool derivatives, ustringhash name, TypeDesc type, } return true; } - if (name == u_red && type == TypeDesc::TypeFloat && sg->P.x > 0.5f) { + if (name == RS::Hashes::red && type == TypeDesc::TypeFloat + && sg->P.x > 0.5f) { ((float*)val)[0] = sg->u; if (derivatives) { ((float*)val)[1] = sg->dudx; @@ -535,7 +529,8 @@ SimpleRenderer::get_userdata(bool derivatives, ustringhash name, TypeDesc type, } return true; } - if (name == u_green && type == TypeDesc::TypeFloat && sg->P.x < 0.5f) { + if (name == RS::Hashes::green && type == TypeDesc::TypeFloat + && sg->P.x < 0.5f) { ((float*)val)[0] = sg->v; if (derivatives) { ((float*)val)[1] = sg->dvdx; @@ -543,7 +538,7 @@ SimpleRenderer::get_userdata(bool derivatives, ustringhash name, TypeDesc type, } return true; } - if (name == u_blue && type == TypeDesc::TypeFloat + if (name == RS::Hashes::blue && type == TypeDesc::TypeFloat && ((static_cast(sg->P.y * 12) % 2) == 0)) { ((float*)val)[0] = 1.0f - sg->u; if (derivatives) { @@ -553,9 +548,16 @@ SimpleRenderer::get_userdata(bool derivatives, ustringhash name, TypeDesc type, return true; } - if (const OIIO::ParamValue* p = userdata.find_pv(name, type)) { + if (const OIIO::ParamValue* p = userdata.find_pv(ustring_from(name), type)) { size_t size = p->type().size(); - memcpy(val, p->data(), size); + + if (p->type() == TypeDesc::STRING) { + const ustringhash* uh_data = reinterpret_cast( + p->data()); + memcpy(val, uh_data, size); + } else { + memcpy(val, p->data(), size); + } if (derivatives) memset((char*)val + size, 0, 2 * size); return true; @@ -658,10 +660,10 @@ SimpleRenderer::build_attribute_getter( && *attribute_name == ustring("shading:index") && type == OSL::TypeInt) { spec.set(rs_get_shade_index, - AttributeSpecBuiltinArg::ShaderGlobalsPointer); + AttributeSpecBuiltinArg::OpaqueExecutionContext); } else { spec.set(rs_get_attribute, - AttributeSpecBuiltinArg::ShaderGlobalsPointer, + AttributeSpecBuiltinArg::OpaqueExecutionContext, AttributeSpecBuiltinArg::ObjectName, AttributeSpecBuiltinArg::AttributeName, AttributeSpecBuiltinArg::Type, @@ -713,7 +715,7 @@ SimpleRenderer::getmessage(ShaderGlobals* sg, ustringhash source_, } if (name == ustring("geom:name")) { if (type == TypeString) { - *reinterpret_cast(val) = ustring("teapot"); + *reinterpret_cast(val) = ustringhash("teapot"); } } if (name == ustring("N")) { @@ -771,7 +773,7 @@ SimpleRenderer::get_camera_projection(ShaderGlobals* /*sg*/, bool /*derivs*/, ustringhash /*name*/, void* val) { if (type == TypeDesc::TypeString) { - ((ustring*)val)[0] = m_projection; + ((ustringhash*)val)[0] = m_projection; return true; } return false; @@ -923,12 +925,13 @@ SimpleRenderer::get_camera_screen_window(ShaderGlobals* /*sg*/, bool derivs, bool -SimpleRenderer::add_output(string_view varname, string_view filename, +SimpleRenderer::add_output(string_view varname_, string_view filename, TypeDesc datatype, int nchannels) { // FIXME: use name to figure out + ustring varname_us(varname_); OIIO::ImageSpec spec(m_xres, m_yres, nchannels, datatype); - m_outputvars.emplace_back(varname); + m_outputvars.emplace_back(varname_us); m_outputbufs.emplace_back( new OIIO::ImageBuf(filename, spec, OIIO::InitializePixels::Yes)); // OIIO::ImageBufAlgo::zero (*m_outputbufs.back()); @@ -949,7 +952,7 @@ SimpleRenderer::export_state(RenderState& state) const 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0); //perspective is not a member of StringParams (i.e not in strdecls.h) - state.projection = u_perspective; + state.projection = RS::Hashes::perspective; state.pixelaspect = m_pixelaspect; std::copy_n(m_screen_window, 4, state.screen_window); std::copy_n(m_shutter, 2, state.shutter); diff --git a/src/testshade/simplerend.h b/src/testshade/simplerend.h index b301f0cb6..74c633f70 100644 --- a/src/testshade/simplerend.h +++ b/src/testshade/simplerend.h @@ -115,7 +115,7 @@ class SimpleRenderer : public RendererServices { // Super simple camera and display parameters. Many options not // available, no motion blur, etc. - void camera_params(const Matrix44& world_to_camera, ustring projection, + void camera_params(const Matrix44& world_to_camera, ustringhash projection, float hfov, float hither, float yon, int xres, int yres); virtual bool add_output(string_view varname, string_view filename, @@ -182,7 +182,7 @@ class SimpleRenderer : public RendererServices { // Camera parameters Matrix44 m_world_to_camera; - ustring m_projection; + ustringhash m_projection; float m_fov, m_pixelaspect, m_hither, m_yon; float m_shutter[2]; float m_screen_window[4]; diff --git a/testsuite/array-copy-reg/test_arraycopy_u_int.osl b/testsuite/array-copy-reg/test_arraycopy_u_int.osl index 146e9140a..ef5c07844 100644 --- a/testsuite/array-copy-reg/test_arraycopy_u_int.osl +++ b/testsuite/array-copy-reg/test_arraycopy_u_int.osl @@ -18,6 +18,8 @@ test_arraycopy_u_int (output color Cout = color(0,0,0)) if (int(P[0]*64)%2==0) { farray3 = negfarray; } + printf("farray3=[%d,%d,%d]\n",farray3[0],farray3[1],farray3[2]); Cout = color(farray3[0]/10.0, farray3[1]/10.0, farray3[2]/10.0); + printf("Cout=%g\n",Cout); } diff --git a/testsuite/array-copy/BATCHED b/testsuite/array-copy/BATCHED new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/array-copy/OPTIX b/testsuite/array-copy/OPTIX new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/array-copy/ref/out.txt b/testsuite/array-copy/ref/out.txt new file mode 100644 index 000000000..e4e0df1b9 --- /dev/null +++ b/testsuite/array-copy/ref/out.txt @@ -0,0 +1,18 @@ +Compiled test.osl -> test.oso +farray3=[-5,-6,5] +farray3=[-5,-6,5] +farray3=[-5,-6,5] +farray3=[-5,-6,5] +farray3=[7,9,5] +farray3=[7,9,5] +farray3=[7,9,5] +farray3=[7,9,5] +farray3=[-5,-6,5] +farray3=[-5,-6,5] +farray3=[-5,-6,5] +farray3=[-5,-6,5] +farray3=[-5,-3,5] +farray3=[-5,-3,5] +farray3=[-5,-3,5] +farray3=[8,10,6] + diff --git a/testsuite/array-copy/run.py b/testsuite/array-copy/run.py new file mode 100755 index 000000000..115794f58 --- /dev/null +++ b/testsuite/array-copy/run.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +# Copyright Contributors to the Open Shading Language project. +# SPDX-License-Identifier: BSD-3-Clause +# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + +command = testshade("-g 16 1 test") diff --git a/testsuite/array-copy/test.osl b/testsuite/array-copy/test.osl new file mode 100644 index 000000000..12af50f6f --- /dev/null +++ b/testsuite/array-copy/test.osl @@ -0,0 +1,44 @@ +// Copyright Contributors to the Open Shading Language project. +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + +// Test copying arrays with fewer elements works + +shader +test() +{ + // Test array referencing with varying index + int farray[3] = { 7, 9, 5}; + int negfarray[2] = { -5,-6 }; + + int farray2[3]; + farray2 = farray; + + int farray3[3]; + farray3 = farray2; + + if (int(P[0]*64)%2==0) { + farray3 = negfarray; + } + + int negfarray2[2]; + negfarray2 = negfarray; + negfarray2[1] = -3; // ensure array is non-const + + if (u > 0.75) { + farray3 = negfarray2; + } + + int farray_nonconst[3]; + farray_nonconst = farray; + farray_nonconst[0]+=1; + farray_nonconst[1]+=1; + farray_nonconst[2]+=1; + if (u > 0.95) { + farray3 = farray_nonconst; + } + + printf("farray3=[%d,%d,%d]\n",farray3[0],farray3[1],farray3[2]); +} + + diff --git a/testsuite/raytype-reg/run.py b/testsuite/raytype-reg/run.py index 30eeb768f..15cea3357 100644 --- a/testsuite/raytype-reg/run.py +++ b/testsuite/raytype-reg/run.py @@ -8,10 +8,8 @@ command += testshade("-t 1 -g 64 64 -od uint8 raytype_all -o cout rta_out.tif") command += testshade("-t 1 -g 64 64 -od uint8 raytype_varying_result -o cout rtvr_out.tif") -# TODO: Fix scalar version, currently crashes, -# so we will just always test the batched version # NOTE: if using this regression test for GPUs might need to adjust this -command += testshade("-batched -t 1 -g 64 64 -od uint8 raytype_varying_name -o cout rtvn_out.tif") +command += testshade("-t 1 -g 64 64 -od uint8 raytype_varying_name -o cout rtvn_out.tif") outputs = [ "rt_out.tif",