Skip to content

Commit 35aa264

Browse files
curtisblacklgritz
authored andcommitted
Add type information for needed attributes. (#1650)
We can currently query which attribute names and scopes are requested in a shader. This PR extends that idea to also allow querying the attribute types. This now more closely matches the equivalent available queries for user data. For example, this shader: ``` shader Shader { color c; getattribute("user_color", c); string s; getattribute("user_string", s); } ``` allows us to do this: ``` int nattr = 0; if (shadingSys->getattribute(shaderRef.get(), "num_attributes_needed", nattr) && nattr) { // this already works OIIO::ustring* names = nullptr; shadingSys->getattribute(shaderRef.get(), "attributes_needed", OSL::TypeDesc::PTR, &names); // this is the added feature OIIO::TypeDesc* types = nullptr; shadingSys->getattribute(shaderRef.get(), "attribute_types", OSL::TypeDesc::PTR, &types); // nattr: 2 // names: ["user_color", "user_string"] // types: [OIIO::TypeColor, OIIO::TypeString] } ``` The motivation behind this feature is to perform additional type validation at material compile time when determining what primvars can be provided to the shader. One side-effect of this change to be aware of is that, as mentioned in the code comments, if the same name is requested multiple times with different types, it will now be reported multiple times. Hopefully this is not too much of an issue as the same behaviour also occurs when an attribute is requested in multiple scopes, or when user data is requested with multiple types. Signed-off-by: Curtis Black <[email protected]>
1 parent 5c1617f commit 35aa264

File tree

5 files changed

+59
-16
lines changed

5 files changed

+59
-16
lines changed

src/include/OSL/oslexec.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,12 +432,15 @@ class OSLEXECPUBLIC ShadingSystem {
432432
/// ptr attributes_needed Retrieves a pointer to the ustring array
433433
/// containing the names of the needed attributes.
434434
/// Note that if the same attribute
435-
/// is requested in multiple scopes, it will
435+
/// is requested in multiple scopes, or with
436+
/// multiple different types, it will
436437
/// appear in the array multiple times - once for
437-
/// each scope in which is is queried.
438+
/// each scope/type in which is is queried.
438439
/// ptr attribute_scopes Retrieves a pointer to a ustring array containing
439440
/// the scopes associated with each attribute query
440441
/// in the attributes_needed array.
442+
/// ptr attribute_types Retrieves a pointer to the array of
443+
/// TypeDesc describing the attributes.
441444
/// int unknown_attributes_needed Nonzero if additional attributes may be
442445
/// needed, whose names will not be known
443446
/// until the shader actually runs.

src/liboslexec/oslexec_pvt.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,11 @@ struct UserDataNeeded {
211211
struct AttributeNeeded {
212212
ustring name;
213213
ustring scope;
214+
TypeDesc type;
214215

215-
AttributeNeeded(ustring name, ustring scope = ustring())
216-
: name(name), scope(scope)
216+
AttributeNeeded(ustring name, ustring scope = ustring(),
217+
TypeDesc type = TypeUnknown)
218+
: name(name), scope(scope), type(type)
217219
{
218220
}
219221

@@ -223,6 +225,15 @@ struct AttributeNeeded {
223225
return a.name < b.name;
224226
if (a.scope != b.scope)
225227
return a.scope < b.scope;
228+
if (a.type.basetype != b.type.basetype)
229+
return a.type.basetype < b.type.basetype;
230+
if (a.type.aggregate != b.type.aggregate)
231+
return a.type.aggregate < b.type.aggregate;
232+
if (a.type.arraylen != b.type.arraylen)
233+
return a.type.arraylen < b.type.arraylen;
234+
// Ignore vector semantics
235+
// if (a.type.vecsemantics != b.type.vecsemantics)
236+
// return a.type.vecsemantics < b.type.vecsemantics;
226237
return false; // they are equal
227238
}
228239
};
@@ -1919,6 +1930,7 @@ class ShaderGroup {
19191930
std::vector<void*> m_userdata_init_vals;
19201931
std::vector<ustring> m_attributes_needed;
19211932
std::vector<ustring> m_attribute_scopes;
1933+
std::vector<TypeDesc> m_attribute_types;
19221934
std::vector<ustring> m_renderer_outputs; ///< Names of renderer outputs
19231935
std::vector<SymLocationDesc> m_symlocs; ///< SORTED!!
19241936
bool m_unknown_textures_needed;

src/liboslexec/runtimeoptimize.cpp

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3331,27 +3331,44 @@ RuntimeOptimizer::run()
33313331
OSL_DASSERT(sym1 && sym1->typespec().is_string());
33323332
if (sym1->is_constant()) {
33333333
if (op.nargs() == 3) {
3334+
Symbol* sym2 = opargsym(op, 2);
33343335
// getattribute( attributename, result )
33353336
m_attributes_needed.insert(
3336-
AttributeNeeded(sym1->get_string()));
3337-
} else {
3338-
OSL_DASSERT(op.nargs() == 4 || op.nargs() == 5);
3337+
AttributeNeeded(sym1->get_string(), ustring(),
3338+
sym2->typespec().simpletype()));
3339+
} else if (op.nargs() == 4) {
33393340
Symbol* sym2 = opargsym(op, 2);
3341+
Symbol* sym3 = opargsym(op, 3);
33403342
if (sym2->typespec().is_string()) {
3341-
// getattribute( scopename, attributename, result ) or
3342-
// getattribute( scopename, attributename, arrayindex, result )
3343+
// getattribute( scopename, attributename, result )
33433344
if (sym2->is_constant()) {
3344-
m_attributes_needed.insert(
3345-
AttributeNeeded(sym2->get_string(),
3346-
sym1->get_string()));
3345+
m_attributes_needed.insert(AttributeNeeded(
3346+
sym2->get_string(), sym1->get_string(),
3347+
sym3->typespec().simpletype()));
33473348
} else {
33483349
m_unknown_attributes_needed = true;
33493350
}
33503351
} else {
33513352
// getattribute( attributename, arrayindex, result )
33523353
m_attributes_needed.insert(
3353-
AttributeNeeded(sym1->get_string()));
3354+
AttributeNeeded(sym1->get_string(), ustring(),
3355+
sym3->typespec().simpletype()));
3356+
}
3357+
} else if (op.nargs() == 5) {
3358+
Symbol* sym2 = opargsym(op, 2);
3359+
Symbol* sym4 = opargsym(op, 4);
3360+
if (sym2->typespec().is_string()) {
3361+
// getattribute( scopename, attributename, arrayindex, result )
3362+
if (sym2->is_constant()) {
3363+
m_attributes_needed.insert(AttributeNeeded(
3364+
sym2->get_string(), sym1->get_string(),
3365+
sym4->typespec().simpletype()));
3366+
} else {
3367+
m_unknown_attributes_needed = true;
3368+
}
33543369
}
3370+
} else {
3371+
OSL_DASSERT(false);
33553372
}
33563373
} else { // sym1 not constant
33573374
m_unknown_attributes_needed = true;
@@ -3403,7 +3420,8 @@ RuntimeOptimizer::run()
34033420
if (m_attributes_needed.size()) {
34043421
shadingcontext()->infofmt("Group needs attributes:");
34053422
for (auto&& f : m_attributes_needed)
3406-
shadingcontext()->infofmt(" {} {}", f.name, f.scope);
3423+
shadingcontext()->infofmt(" {} {} {}", f.name, f.scope,
3424+
f.type);
34073425
if (m_unknown_attributes_needed)
34083426
shadingcontext()->infofmt(
34093427
" Also may construct attribute names on the fly.");

src/liboslexec/shadingsys.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2102,6 +2102,11 @@ ShadingSystemImpl::getattribute(ShaderGroup* group, string_view name,
21022102
*(ustring**)val = n ? &group->m_attribute_scopes[0] : NULL;
21032103
return true;
21042104
}
2105+
if (name == "attribute_types" && type.basetype == TypeDesc::PTR) {
2106+
size_t n = group->m_attribute_types.size();
2107+
*(TypeDesc**)val = n ? &group->m_attribute_types[0] : NULL;
2108+
return true;
2109+
}
21052110
if (name == "unknown_attributes_needed" && type == TypeDesc::TypeInt) {
21062111
*(int*)val = (int)group->m_unknown_attributes_needed;
21072112
return true;
@@ -3560,6 +3565,7 @@ ShadingSystemImpl::optimize_group(ShaderGroup& group, ShadingContext* ctx,
35603565
for (auto&& f : rop.m_attributes_needed) {
35613566
group.m_attributes_needed.push_back(f.name);
35623567
group.m_attribute_scopes.push_back(f.scope);
3568+
group.m_attribute_types.push_back(f.type);
35633569
}
35643570
group.m_optimized = true;
35653571

src/testshade/testshade.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,13 +1468,17 @@ test_group_attributes(ShaderGroup* group)
14681468
std::cout << "Need " << nattr << " attributes:\n";
14691469
ustring* names = NULL;
14701470
ustring* scopes = NULL;
1471+
TypeDesc* types = NULL;
14711472
shadingsys->getattribute(group, "attributes_needed", TypeDesc::PTR,
14721473
&names);
14731474
shadingsys->getattribute(group, "attribute_scopes", TypeDesc::PTR,
14741475
&scopes);
1475-
OSL_DASSERT(names && scopes);
1476+
shadingsys->getattribute(group, "attribute_types", TypeDesc::PTR,
1477+
&types);
1478+
OSL_DASSERT(names && scopes && types);
14761479
for (int i = 0; i < nattr; ++i)
1477-
std::cout << " " << names[i] << ' ' << scopes[i] << "\n";
1480+
std::cout << " " << names[i] << ' ' << scopes[i] << ' '
1481+
<< types[i] << "\n";
14781482

14791483
int unk = 0;
14801484
shadingsys->getattribute(group, "unknown_attributes_needed", unk);

0 commit comments

Comments
 (0)