Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add API for building attribute getter free functions. #1704

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
d318962
Add API for building attribute getter free functions.
curtisblack Jun 23, 2023
1176fd4
Support all standard C++ types and ustring/ustringhash.
curtisblack Jul 21, 2023
c312d24
Fix different sign comparison.
curtisblack Jul 21, 2023
07bf09a
Fix memcpy error.
curtisblack Jul 21, 2023
6e352b6
Merge branch 'main' into getattribute_builder
curtisblack Jul 24, 2023
d3ec4fe
Disambiguate function call.
curtisblack Jul 24, 2023
637275d
Fix formatting.
curtisblack Jul 24, 2023
e4efe31
Fix formatting.
curtisblack Jul 24, 2023
4ad7c1d
Add helper functions and comments.
curtisblack Aug 17, 2023
9c929bd
Merge branch 'main' into getattribute_builder
curtisblack Aug 17, 2023
587fe5e
Use string params to ensure optimisation.
curtisblack Aug 18, 2023
46cc9e2
Merge branch 'main' into getattribute_builder
curtisblack Aug 18, 2023
9f05e03
Fix rebase conflict.
curtisblack Aug 18, 2023
02c4237
Convert return type to match virtual function signature.
curtisblack Aug 20, 2023
028aa6c
clang format
curtisblack Aug 20, 2023
e90f4e9
Fix incorrect indexing.
curtisblack Aug 21, 2023
0a1498d
Support userdata in attribute builder.
curtisblack Aug 21, 2023
0db9c26
Add missing derivatives argument.
curtisblack Aug 21, 2023
6c03cda
Fix typo.
curtisblack Aug 21, 2023
f914eeb
Use find_pv correctly.
curtisblack Aug 21, 2023
1577a8d
Merge branch 'main' into getattribute_builder
curtisblack Aug 21, 2023
630530f
Remove unused variable.
curtisblack Aug 21, 2023
a0dd0ed
clang format
curtisblack Aug 21, 2023
6f68b60
Fix some attribute types.
curtisblack Aug 21, 2023
651c7f9
Fix incorrect size.
curtisblack Aug 21, 2023
3edffb9
Cast to avoid ambiguity.
curtisblack Aug 25, 2023
697d1d3
Refactor for future reusability.
curtisblack Aug 25, 2023
217a238
Formatting.
curtisblack Aug 25, 2023
3006684
Fix template specialisations.
curtisblack Aug 25, 2023
3a0d66c
Formatting.
curtisblack Aug 25, 2023
74048bc
Remove templates.
curtisblack Aug 25, 2023
f8e449b
Fix asserts.
curtisblack Aug 25, 2023
c9cebdf
Fix type.
curtisblack Aug 25, 2023
8c5e57c
Merge branch 'main' into getattribute_builder
curtisblack Aug 28, 2023
e21087a
Use POD type with known size.
curtisblack Aug 28, 2023
7c62b2f
Update src/include/OSL/rendererservices.h
curtisblack Aug 31, 2023
c260dac
Make optional args const pointers.
curtisblack Sep 1, 2023
e72ddfb
clang format.
curtisblack Sep 1, 2023
2798354
clang format.
curtisblack Sep 1, 2023
c7971ef
constify ShaderGroup.
curtisblack Sep 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,15 @@ configure_package_config_file ("${PROJECT_SOURCE_DIR}/src/cmake/Config.cmake.in"
install (FILES "${OSL_PROJECT_CONFIG}" "${OSL_VERSION_CONFIG}"
DESTINATION "${OSL_CONFIG_INSTALL_DIR}")

install (FILES src/cmake/llvm_macros.cmake DESTINATION cmake)

set (PERMISSION_FLAGS OWNER_EXECUTE OWNER_READ OWNER_WRITE
GROUP_EXECUTE GROUP_READ
WORLD_EXECUTE WORLD_READ)
install (FILES src/build-scripts/serialize-bc.py
DESTINATION build-scripts
PERMISSIONS ${PERMISSION_FLAGS})

# install targets files
install (EXPORT OSL_EXPORTED_TARGETS
DESTINATION ${OSL_CONFIG_INSTALL_DIR}
Expand Down
24 changes: 8 additions & 16 deletions src/cmake/llvm_macros.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage

# TODO: Use CMAKE_CURRENT_FUNCTION_LIST_DIR in cmake-3.17
set(_THIS_MODULE_BASE_DIR "${CMAKE_CURRENT_LIST_DIR}")

function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_cpp extra_clang_args)
function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_cpp extra_clang_args include_dirs)

if (VERBOSE)
message (STATUS "EMBED_LLVM_BITCODE_IN_CPP src_list=${src_list}")
Expand Down Expand Up @@ -75,12 +77,8 @@ function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_
# endif ()
#endif ()

list (TRANSFORM IMATH_INCLUDES PREPEND -I
OUTPUT_VARIABLE ALL_IMATH_INCLUDES)
list (TRANSFORM OPENEXR_INCLUDES PREPEND -I
OUTPUT_VARIABLE ALL_OPENEXR_INCLUDES)
list (TRANSFORM OpenImageIO_INCLUDES PREPEND -I
OUTPUT_VARIABLE ALL_OpenImageIO_INCLUDES)
list (TRANSFORM include_dirs PREPEND -I
OUTPUT_VARIABLE ALL_INCLUDE_DIRS)

if (${LLVM_VERSION} VERSION_GREATER_EQUAL 15.0)
# Until we fully support opaque pointers, we need to disable
Expand All @@ -93,13 +91,7 @@ function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_
add_custom_command ( OUTPUT ${src_bc}
COMMAND ${LLVM_BC_GENERATOR}
${LLVM_COMPILE_FLAGS}
"-I${CMAKE_CURRENT_SOURCE_DIR}"
"-I${CMAKE_SOURCE_DIR}/src/include"
"-I${CMAKE_BINARY_DIR}/include"
${ALL_OpenImageIO_INCLUDES}
${ALL_IMATH_INCLUDES}
#"-isystem ${Boost_INCLUDE_DIRS}" #Does not pick up usr installed boost/thread/tss.hpp for oslexec_pvt.h
"-I${Boost_INCLUDE_DIRS}"
${ALL_INCLUDE_DIRS}
-DOSL_COMPILING_TO_BITCODE=1
-Wno-deprecated-register
# the following 2 warnings can be restored when all 3rd parties have fixed their export macros
Expand Down Expand Up @@ -131,9 +123,9 @@ function ( EMBED_LLVM_BITCODE_IN_CPP src_list suffix output_name list_to_append_
# Serialize the linked bitcode into a CPP file
set ( src_bc_cpp "${CMAKE_CURRENT_BINARY_DIR}/${output_name}.bc.cpp" )
add_custom_command ( OUTPUT ${src_bc_cpp}
COMMAND ${Python_EXECUTABLE} "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py"
COMMAND ${Python_EXECUTABLE} "${_THIS_MODULE_BASE_DIR}/../build-scripts/serialize-bc.py"
${linked_src_bc} ${src_bc_cpp} ${output_name}
DEPENDS "${CMAKE_SOURCE_DIR}/src/build-scripts/serialize-bc.py" ${linked_src_bc}
DEPENDS "${_THIS_MODULE_BASE_DIR}/../build-scripts/serialize-bc.py" ${linked_src_bc}
${exec_headers} ${PROJECT_PUBLIC_HEADERS}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" )

Expand Down
12 changes: 12 additions & 0 deletions src/include/OSL/oslexec.h
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,18 @@ class OSLEXECPUBLIC ShadingSystem {
void add_symlocs(cspan<SymLocationDesc> symlocs);
void add_symlocs(ShaderGroup* group, cspan<SymLocationDesc> symlocs);

// Find the SymLocationDesc for this named param, returning its pointer
// or nullptr if that name is not found.
const SymLocationDesc* find_symloc(ustring name) const;
const SymLocationDesc* find_symloc(ShaderGroup* group, ustring name) const;

// Find the SymLocationDesc for this named param but only if it matches
// the arena type, returning its pointer or nullptr if that name is not
// found.
const SymLocationDesc* find_symloc(ustring name, SymArena arena) const;
const SymLocationDesc* find_symloc(ShaderGroup* group, ustring name,
SymArena arena) const;

Copy link
Contributor Author

@curtisblack curtisblack Jun 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These additions are not strictly necessary for the rest of this PR to work, but it did seem to be useful to be able to query current symbol locations for a shader group inside the build_attribute_getter function.

/// Ensure that the group has been optimized and optionally JITed. The ctx pointer
/// supplies a ShadingContext to use.
void optimize_group(ShaderGroup* group, ShadingContext* ctx,
Expand Down
140 changes: 140 additions & 0 deletions src/include/OSL/rendererservices.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class RendererServices;
template<int WidthT> class BatchedRendererServices;
class ShadingContext;
struct ShaderGlobals;
class ShaderGroup;

// Tags for polymorphic dispatch
template<int SimdWidthT> class WidthOf {
Expand All @@ -29,6 +30,125 @@ typedef const void* TransformationPtr;
typedef void (*PrepareClosureFunc)(RendererServices*, int id, void* data);
typedef void (*SetupClosureFunc)(RendererServices*, int id, void* data);

enum class AttributeSpecBuiltinArg {
ShaderGlobalsPointer, // void* (ideally ShaderGlobals*)
ShadeIndex, // int
Derivatives, // int (ideally bool)
Type, // long long (ideally TypeDesc)
ArrayIndex, // int, Always zero for non-indexed array lookups.
ArrayLookup, // int (ideally bool)
ObjectName, // const char* (ideally ustring)
AlexMWells marked this conversation as resolved.
Show resolved Hide resolved
AttributeName, // const char* (ideally ustring)
};

// TODO: replace with std::variant
AlexMWells marked this conversation as resolved.
Show resolved Hide resolved
class AttributeSpecArg {
union {
AttributeSpecBuiltinArg m_builtin;
int32_t m_int32;
float m_float;
uint64_t m_uint64;
void* m_ptr;
};
uint32_t m_type;

public:
AttributeSpecArg() : m_type(0) {}
AttributeSpecArg(AttributeSpecBuiltinArg arg) : m_builtin(arg), m_type(1) {}
AttributeSpecArg(int32_t arg) : m_int32(arg), m_type(2) {}
AttributeSpecArg(float arg) : m_float(arg), m_type(3) {}
AttributeSpecArg(uint64_t arg) : m_uint64(arg), m_type(4) {}
AttributeSpecArg(void* arg) : m_ptr(arg), m_type(5) {}

template<typename T> bool is_holding() const
{
if (std::is_same<T, AttributeSpecBuiltinArg>::value)
return m_type == 1;
if (std::is_same<T, int32_t>::value)
return m_type == 2;
if (std::is_same<T, float>::value)
return m_type == 3;
if (std::is_same<T, uint64_t>::value)
return m_type == 4;
if (std::is_same<T, void*>::value)
return m_type == 5;
return false;
}

template<typename T> T get() const
{
assert(false);
return T();
}
};

template<>
inline AttributeSpecBuiltinArg
AttributeSpecArg::get() const
{
assert(is_holding<AttributeSpecBuiltinArg>());
return m_builtin;
}

template<>
inline int32_t
AttributeSpecArg::get() const
{
assert(is_holding<int32_t>());
return m_int32;
}

template<>
inline float
AttributeSpecArg::get() const
{
assert(is_holding<float>());
return m_float;
}

template<>
inline uint64_t
AttributeSpecArg::get() const
{
assert(is_holding<uint64_t>());
AlexMWells marked this conversation as resolved.
Show resolved Hide resolved
return m_uint64;
}

template<>
inline void*
AttributeSpecArg::get() const
{
assert(is_holding<void*>());
return m_ptr;
}

// The AttributeGetterSpec is never in device code, so it can be a bit more
// complex and have dynamic allocations. Although we do want to
// use an interface and not allow direct data member access
class AttributeGetterSpec {
ustring m_function_name;
AlexMWells marked this conversation as resolved.
Show resolved Hide resolved
std::vector<AttributeSpecArg> m_args;

public:
template<typename... ArgListT>
void set(ustring function_name, ArgListT... args)
AlexMWells marked this conversation as resolved.
Show resolved Hide resolved
{
m_function_name = function_name;
m_args.clear();
m_args.insert(m_args.end(), std::initializer_list<AttributeSpecArg> {
AttributeSpecArg { args }... });
}

const ustring& function_name() const { return m_function_name; }
size_t arg_count() const { return m_args.size(); }
const AttributeSpecArg& arg(size_t i) const
{
assert(i < m_args.size());
return m_args[i];
}
};


// Turn off warnings about unused params for this file, since we have lots
// of declarations with stub function bodies.
OSL_PRAGMA_WARNING_PUSH
Expand Down Expand Up @@ -156,6 +276,26 @@ class OSLEXECPUBLIC RendererServices {
Vec3* Pout, int npoints,
TypeDesc::VECSEMANTICS vectype);

/// @brief Builds a free function to provide a value for a given attribute.
AlexMWells marked this conversation as resolved.
Show resolved Hide resolved
/// @param group The shader group currently requesting the attribute.
/// @param object_name The object name. An empty string will be provided if
/// the value is not specified or it is not known at compile time.
/// @param attribute_name The attribute name. An empty string will be
/// provided if the value is not known at compile time.
/// @param type The type of the value being requested.
/// @param derivatives True if derivatives are also being requested.
/// @param object_lookup True if an object name was specified, even if the
/// value is not known at compile time.
/// @param array_lookup True if the attribute lookup provides an index.
/// @param spec The built attribute getter.
/// @return True if an attribute builder was provided. If false, the
/// existing get_attribute or get_array_attribute functions will be
/// used as the fallback.
AlexMWells marked this conversation as resolved.
Show resolved Hide resolved
virtual bool build_attribute_getter(ShaderGroup& group, ustring object_name,
ustring attribute_name, TypeDesc type,
bool derivatives, bool object_lookup,
bool array_lookup,
AttributeGetterSpec& spec);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might need to add one more argument to this function to allow render developers to pass through their own information.

e.g. consider a typical wrapper class:

class Material
{
  ShaderGroup group;

  void Compile()
  {
    shadingSystem->optimize_group(&group);
  }
};

class Renderer : RendererServices
{
  bool build_attribute_getter(ShaderGroup& group, ...) override
  {
    // how do we get access to the current Material here?
  }
};

Some ideas:

  • Add a user supplied pointer member to ShaderGroup: void Compile() { group.user_ptr = this; ... }
  • Pass a user supplied pointer through compilation: optimize_group(this, &group);
  • Something else?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be good to have a pointer passed through to jit-compilation. We use the same shader group for multiple compiles depending on how we're going to execute it, so we'd want it to be different-per-compile call. Calls that compile as a convenient side-effect would need to have access to to it as well, so it should be piped through there.

It would also be useful in the future for things like satisfying get-texture-info calls and the like at compile time.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, during shader execution, ShaderGlobals::renderstate exists so derived RendererServices can stow what ever it wants away. We are suggesting a move considering this ShaderGlobals as ExecContext, meaning this is the context during shader execution. So it figures we need a similar context during shader compilation/JIT/OPT. Would CompileContext work? Nice part is CompileContext is host only so free to be as complex as it wants. Now ExecContext contains OSL lib side stuff and Renderer stuff as well, not sure if CompileContext needs to be as complex or can just be an Opaque Pointer to whatever renderer passes into optimize/jit_group. I guess that is simplest to start with. If so, renderer is the supplier of it, maybe typedef void * OpaqueRendCompileContextPtr,

void optimize_group(ShaderGroup* group, OpaqueRendCompileContextPtr, ShadingContext* ctx,
                        bool do_jit = true)

Although looking at that, we do have the existing host side ShadingContext which is already sort of a per thread thing. Should the ShadingContext move towards being a CompileContext with a setter/getter for RendCompileContext. And simply pass the ShadingContext through to the bool build_attribute_getter(ShadingContext &sc, ShaderGroup& group, ...) override


/// Get the named attribute from the renderer and if found then
/// write it into 'val'. Otherwise, return false. If no object is
Expand Down
13 changes: 11 additions & 2 deletions src/liboslexec/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,16 @@ endmacro ( )

if (USE_LLVM_BITCODE)
set (llvm_ops_srcs llvm_ops.cpp)
EMBED_LLVM_BITCODE_IN_CPP ( "${llvm_ops_srcs}" "_host" "osl_llvm_compiled_ops" lib_src "")

set(include_dirs ${CMAKE_CURRENT_SOURCE_DIR})
list(APPEND include_dirs ${CMAKE_SOURCE_DIR}/src/include)
list(APPEND include_dirs ${CMAKE_BINARY_DIR}/include)
list(APPEND include_dirs ${IMATH_INCLUDES})
list(APPEND include_dirs ${OPENEXR_INCLUDES})
list(APPEND include_dirs ${OpenImageIO_INCLUDES})
list(APPEND include_dirs ${Boost_INCLUDE_DIRS})

EMBED_LLVM_BITCODE_IN_CPP ( "${llvm_ops_srcs}" "_host" "osl_llvm_compiled_ops" lib_src "" "${include_dirs}")

set (rs_dependent_ops_srcs
opmatrix.cpp
Expand All @@ -229,7 +238,7 @@ if (USE_LLVM_BITCODE)
# sources to rs_dependent_ops_srcs which avoids having to do it at runtime.
list (APPEND rs_dependent_ops_srcs ${llvm_ops_srcs})

EMBED_LLVM_BITCODE_IN_CPP ( "${rs_dependent_ops_srcs}" "_host_rs" "osl_llvm_compiled_rs_dependent_ops" lib_src "")
EMBED_LLVM_BITCODE_IN_CPP ( "${rs_dependent_ops_srcs}" "_host_rs" "osl_llvm_compiled_rs_dependent_ops" lib_src "" "${include_dirs}")

# Optionally repeat the bitcode compilation with CUDA-specific options
if (CUDA_FOUND)
Expand Down
64 changes: 64 additions & 0 deletions src/liboslexec/llvm_gen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3019,6 +3019,69 @@ LLVMGEN(llvm_gen_getattribute)
: rop.llvm_load_string(ustring());
llvm::Value* attr_name_arg = rop.llvm_load_value(Attribute);

ustring object_name = (object_lookup && ObjectName.is_constant())
? ObjectName.get_string()
: ustring();
ustring attribute_name = Attribute.is_constant() ? Attribute.get_string()
: ustring();

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if the attribute name isn't constant, since a constant getattribute("", result); can be pretty trivially turned into a "just fail" whereas if it was not constant, we want to do the run-time lookup. I bet it's pretty easy to get into a place where a "default" shader ends up doing a getattribute("",result) that can basically be used to skip a bunch of work, but if there's an attribute set in the shading node to cause that to turn into getattribute("mycoolval", result), there could be a lot of other stuff that would get run. If a non-constant attribute name causes us to call build_attribute_getter with "", we can no longer optimize the cases where it's a constant "".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other thing we could do is just pass in the Symbol& and let the renderer inspect them to find that info out.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other thing we could do is just pass in the Symbol& and let the renderer inspect them to find that info out.

If the name isn't constant, what could the renderer figure out from the Symbol&? (not rhetorical)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, my first comment was a bit nonsensical. It could discriminate between a non-const name and a "".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a bit of discussion with Larry and Alex, our proposal here would be to handle the compile time constant empty attribute name string internally, it would always produce a fail. In such case the build_attribute_getter function would not be called. The reason being is that a constant empty attribute name is not very sensical. With this in place, you could then be sure that on the renderer side if you receive an empty attribute name, the only possibility is because it's not known at compile time.

I'd prefer to avoid passing LLVM symbols out into user facing code if possible.

AttributeGetterSpec spec;
if (rop.renderer()->build_attribute_getter(
rop.group(), object_name, attribute_name, dest_type,
Destination.has_derivs(), object_lookup, array_lookup, spec)
&& !spec.function_name().empty()) {
std::vector<llvm::Value*> args;
for (int arg_index = 0; arg_index < spec.arg_count(); ++arg_index) {
const auto& arg = spec.arg(arg_index);
if (arg.is_holding<AttributeSpecBuiltinArg>()) {
switch (arg.get<AttributeSpecBuiltinArg>()) {
case AttributeSpecBuiltinArg::ShaderGlobalsPointer:
args.push_back(rop.sg_void_ptr());
break;
case AttributeSpecBuiltinArg::ShadeIndex:
args.push_back(rop.shadeindex());
break;
case AttributeSpecBuiltinArg::Derivatives:
args.push_back(
rop.ll.constant((int)Destination.has_derivs()));
break;
case AttributeSpecBuiltinArg::Type:
args.push_back(rop.ll.constant(dest_type));
break;
case AttributeSpecBuiltinArg::ArrayIndex:
if (array_lookup)
args.push_back(rop.llvm_load_value(Index));
else
args.push_back(rop.ll.constant((int)0));
break;
case AttributeSpecBuiltinArg::ArrayLookup:
args.push_back(rop.ll.constant((int)array_lookup));
break;
case AttributeSpecBuiltinArg::ObjectName:
args.push_back(obj_name_arg);
break;
case AttributeSpecBuiltinArg::AttributeName:
args.push_back(attr_name_arg);
break;
default: assert(false); break;
}
} else if (arg.is_holding<int32_t>()) {
args.push_back(rop.ll.constant(arg.get<int32_t>()));
} else if (arg.is_holding<float>()) {
args.push_back(rop.ll.constant(arg.get<float>()));
} else if (arg.is_holding<uint64_t>()) {
args.push_back(rop.ll.constant64(arg.get<uint64_t>()));
} else if (arg.is_holding<void*>()) {
args.push_back(rop.ll.constant_ptr(arg.get<void*>()));
} else {
assert(false);
}
}
args.push_back(rop.llvm_void_ptr(Destination));
llvm::Value* r = rop.ll.call_function(spec.function_name().c_str(),
args);
rop.llvm_store_value(r, Result);
} else {
llvm::Value* args[] = {
rop.sg_void_ptr(),
rop.ll.constant((int)Destination.has_derivs()),
Expand All @@ -3031,6 +3094,7 @@ LLVMGEN(llvm_gen_getattribute)
};
llvm::Value* r = rop.ll.call_function("osl_get_attribute", args);
rop.llvm_store_value(r, Result);
}

return true;
}
Expand Down
14 changes: 14 additions & 0 deletions src/liboslexec/oslexec_pvt.h
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,20 @@ class ShadingSystemImpl {
for (auto& s : symlocs)
m_symlocs.push_back(s);
}
const SymLocationDesc* find_symloc(ustring name) const
{
auto f = std::lower_bound(m_symlocs.begin(), m_symlocs.end(), name);
return (f == m_symlocs.end() || f->name != name) ? nullptr : &(*f);
}
const SymLocationDesc* find_symloc(ustring name, SymArena arena) const
{
auto f = std::lower_bound(m_symlocs.begin(), m_symlocs.end(), name);
if (f != m_symlocs.end() && f->name == name && f->arena == arena
&& f->offset != -1)
return &(*f);
else
return nullptr;
}

private:
void printstats() const;
Expand Down
13 changes: 13 additions & 0 deletions src/liboslexec/rendservices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,19 @@ RendererServices::transform_points(ShaderGlobals* sg, ustringhash from,



bool
RendererServices::build_attribute_getter(ShaderGroup& group,
ustring object_name,
ustring attribute_name, TypeDesc type,
bool derivatives, bool object_lookup,
bool array_lookup,
AttributeGetterSpec& spec)
{
return false;
}



bool
RendererServices::get_attribute(ShaderGlobals* sg, bool derivatives,
ustringhash object, TypeDesc type,
Expand Down
Loading
Loading