Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions src/cmake/testing.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ macro (osl_add_all_tests)
layers-nonlazycopy layers-repeatedoutputs
lazytrace
length-reg linearstep
lockgeom
logic loop luminance-reg
matrix matrix-reg matrix-arithmetic-reg
matrix-compref-reg max-reg message message-no-closure message-reg
Expand Down
60 changes: 52 additions & 8 deletions src/liboslexec/batched_analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1119,6 +1119,7 @@ class WriteEvent {
public:
static constexpr int InitialAssignmentOp() { return -1; }
static constexpr int UserDataPreplacementCopyOp() { return -2; }
static constexpr int UserDataInterpolatedOp() { return -3; }

WriteEvent(DependencyTreeTracker::Position pos_in_tree_, int op_num_,
int loop_op_index)
Expand All @@ -1134,7 +1135,7 @@ class WriteEvent {
, m_op_num(op_num_)
, m_loop_op_index(NoLoopIndex())
{
OSL_ASSERT(is_initial_assignment() || is_user_data_preplacement_copy());
OSL_ASSERT(is_initial_assignment() || is_user_data_preplacement_copy() || is_user_data_interpolated());
}

OSL_FORCEINLINE DependencyTreeTracker::Position pos_in_tree() const
Expand All @@ -1152,11 +1153,26 @@ class WriteEvent {
return m_op_num == UserDataPreplacementCopyOp();
}

OSL_FORCEINLINE bool is_user_data_interpolated() const
{
return m_op_num == UserDataInterpolatedOp();
}


OSL_FORCEINLINE int op_num() const
{
#if 0 // For getting callstack in debugger
if(is_initial_assignment()
|| is_user_data_preplacement_copy()
|| is_user_data_interpolated()) {
// Caller's logic should of special cased these
// so logic bug exists
__builtin_trap();
}
#endif
OSL_ASSERT(!is_initial_assignment()
&& !is_user_data_preplacement_copy());
&& !is_user_data_preplacement_copy()
&& !is_user_data_interpolated());
return m_op_num;
}

Expand Down Expand Up @@ -1397,7 +1413,8 @@ struct Analyzer {
write_iter != write_end; ++write_iter) {
// We don't bother masking initial assignment
if (write_iter->is_initial_assignment()
|| write_iter->is_user_data_preplacement_copy()) {
|| write_iter->is_user_data_preplacement_copy()
|| write_iter->is_user_data_interpolated()) {
continue;
}

Expand Down Expand Up @@ -1568,7 +1585,9 @@ struct Analyzer {
// Then the current write needs to be masked
for (auto write_iter = write_chronology.begin();
write_iter != write_end; ++write_iter) {
if (write_iter->is_initial_assignment()) {
if (write_iter->is_initial_assignment() ||
write_iter->is_user_data_preplacement_copy() ||
write_iter->is_user_data_interpolated()) {
// The initial assignment of all parameters happens before any instructions are generated?
// perhaps there is an ordering issue here for init_ops which could have early outs
// although not sure what that would do to execution, certainly returns in init_ops would
Expand Down Expand Up @@ -2201,6 +2220,19 @@ struct Analyzer {
OSL_DEV_ONLY(std::cout
<< " bind_interpolated_param called for symbol: "
<< s.name() << std::endl);

// NOTE: as this is the initial assignment to a parameter
// there could be no other reads/write to deal with to the symbol
OSL_ASSERT(m_write_chronology_by_symbol.find(&s)
== m_write_chronology_by_symbol.end());

// bind_interpolated_param will have written to s
// so we need a write event to model that and prevent
// s from being forced to boolean
m_write_chronology_by_symbol[&s].push_back(
WriteEvent(m_conditional_symbol_stack.top_pos(),
WriteEvent::UserDataInterpolatedOp()));

// Interpolated params are handled by calling batched version of
// osl_bind_interpolated_param. It will return a mask indicating which
// lanes had such userdata was available.
Expand Down Expand Up @@ -2238,12 +2270,13 @@ struct Analyzer {

// NOTE: as this is the initial assignment to a parameter
// there could be no other reads/write to deal with to the symbol
if (m_write_chronology_by_symbol.find(&s)
!= m_write_chronology_by_symbol.end()) {
// unless it was interpolated
if (!interpolate_param && (m_write_chronology_by_symbol.find(&s)
!= m_write_chronology_by_symbol.end())) {
__builtin_trap();
}
OSL_ASSERT(m_write_chronology_by_symbol.find(&s)
== m_write_chronology_by_symbol.end());
OSL_ASSERT(interpolate_param || (m_write_chronology_by_symbol.find(&s)
== m_write_chronology_by_symbol.end()));

m_write_chronology_by_symbol[&s].push_back(
WriteEvent(m_conditional_symbol_stack.top_pos(),
Expand Down Expand Up @@ -2412,6 +2445,17 @@ struct Analyzer {
// no need to continue checking additional writes
break;
}
} else if (write_iter->is_user_data_interpolated() ||
write_iter->is_user_data_preplacement_copy()) {
// the interpolated assignment should be the 1st write entry,
// so bool status should be unknown
OSL_ASSERT(b_status == BoolStatus::Unknown);
// The renderer could write any integer value, or
// the preplacement data could be any integer value
// so it can't be boolean!
b_status = BoolStatus::No;
// no need to continue checking additional writes
break;
} else {
int op_index = write_iter->op_num();
Opcode& opcode = m_opcodes[op_index];
Expand Down
116 changes: 86 additions & 30 deletions src/liboslexec/batched_llvm_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ static ustring op_aref("aref");
static ustring op_compref("compref");
static ustring op_mxcompref("mxcompref");
static ustring op_useparam("useparam");
static ustring op_pointcloud_get("pointcloud_get");
static ustring op_spline("spline");
static ustring op_splineinverse("splineinverse");
static ustring unknown_shader_group_name("<Unknown Shader Group Name>");


Expand Down Expand Up @@ -1620,7 +1623,8 @@ BatchedBackendLLVM::llvm_generate_debug_uninit(const Opcode& op)
}

llvm::Value* ncheck = ll.constant(int(t.numelements() * t.aggregate));
llvm::Value* offset = ll.constant(0);
llvm::Value* varying_nchecks = nullptr;
llvm::Value* offset = ll.constant(0);
BatchedBackendLLVM::TempScope temp_scope(*this);
llvm::Value* loc_varying_offsets = nullptr;

Expand Down Expand Up @@ -1701,6 +1705,31 @@ BatchedBackendLLVM::llvm_generate_debug_uninit(const Opcode& op)
ll.op_store(comp, loc_varying_offsets);
}
ncheck = ll.constant(1);
} else if (op.opname() == op_pointcloud_get && i == 2) {
// int pointcloud_get (string ptcname, int indices[], int count, string attr, type data[])
// will only read indices[0..count-1], so limit the check to count
OSL_ASSERT(3 < op.nargs());
Symbol& count_sym = *opargsym(op, 3);
if (count_sym.is_uniform()) {
ncheck = llvm_load_value(count_sym);
} else {
// Don't think we can have a uniform indices array that
// has a varying index count
if (!sym.is_uniform()) {
varying_nchecks = ll.void_ptr(llvm_get_pointer(count_sym));
}
}
} else if (((op.opname() == op_spline)
|| (op.opname() == op_splineinverse))
&& i == 4) {
// If an explicit knot count was provided to spline|splineinverse we should
// limit our check of knot values to that count
bool has_knot_count = (op.nargs() == 5);
if (has_knot_count) {
Symbol& knot_count_sym = *opargsym(op, 3);
OSL_ASSERT(knot_count_sym.is_uniform());
ncheck = llvm_load_value(knot_count_sym);
}
}

if (loc_varying_offsets != nullptr) {
Expand All @@ -1724,15 +1753,15 @@ BatchedBackendLLVM::llvm_generate_debug_uninit(const Opcode& op)
if (sym.is_uniform()) {
ll.call_function(build_name(
FuncSpec("uninit_check_values_offset")
.arg_uniform(TypeDesc::PTR)
.arg_varying(TypeInt)
.arg_uniform(TypeDesc::PTR) // vals
.arg_varying(TypeInt) // firstcheck
.mask()),
args);
} else {
ll.call_function(build_name(
FuncSpec("uninit_check_values_offset")
.arg_varying(TypeDesc::PTR)
.arg_varying(TypeInt)
.arg_varying(TypeDesc::PTR) // vals
.arg_varying(TypeInt) // firstcheck
.mask()),
args);
}
Expand All @@ -1756,33 +1785,60 @@ BatchedBackendLLVM::llvm_generate_debug_uninit(const Opcode& op)
ncheck };
ll.call_function(build_name(
FuncSpec("uninit_check_values_offset")
.arg_uniform(TypeDesc::PTR)
.arg_uniform(TypeInt)),
.arg_uniform(TypeDesc::PTR) // vals
.arg_uniform(TypeInt)), // firstcheck
args);
} else {
llvm::Value* args[]
= { ll.mask_as_int(ll.current_mask()),
ll.constant(t),
llvm_void_ptr(sym),
sg_void_ptr(),
ll.constant(op.sourcefile()),
ll.constant(op.sourceline()),
ll.constant(group().name()),
ll.constant(layer()),
ll.constant(inst()->layername()),
ll.constant(inst()->shadername().c_str()),
ll.constant(int(&op - &inst()->ops()[0])),
ll.constant(op.opname()),
ll.constant(i),
ll.constant(sym.unmangled()),
offset,
ncheck };
ll.call_function(build_name(
FuncSpec("uninit_check_values_offset")
.arg_varying(TypeDesc::PTR)
.arg_uniform(TypeInt)
.mask()),
args);
if (varying_nchecks != nullptr) {
llvm::Value* args[]
= { ll.mask_as_int(ll.current_mask()),
ll.constant(t),
llvm_void_ptr(sym),
sg_void_ptr(),
ll.constant(op.sourcefile()),
ll.constant(op.sourceline()),
ll.constant(group().name()),
ll.constant(layer()),
ll.constant(inst()->layername()),
ll.constant(inst()->shadername().c_str()),
ll.constant(int(&op - &inst()->ops()[0])),
ll.constant(op.opname()),
ll.constant(i),
ll.constant(sym.unmangled()),
offset,
varying_nchecks };
ll.call_function(
build_name(FuncSpec("uninit_check_values_offset")
.arg_varying(TypeDesc::PTR) // vals
.arg_uniform(TypeInt) // firstcheck
.arg_varying(TypeInt) // nchecks
.mask()),
args);
} else {
llvm::Value* args[]
= { ll.mask_as_int(ll.current_mask()),
ll.constant(t),
llvm_void_ptr(sym),
sg_void_ptr(),
ll.constant(op.sourcefile()),
ll.constant(op.sourceline()),
ll.constant(group().name()),
ll.constant(layer()),
ll.constant(inst()->layername()),
ll.constant(inst()->shadername().c_str()),
ll.constant(int(&op - &inst()->ops()[0])),
ll.constant(op.opname()),
ll.constant(i),
ll.constant(sym.unmangled()),
offset,
ncheck };
ll.call_function(
build_name(FuncSpec("uninit_check_values_offset")
.arg_varying(TypeDesc::PTR) // vals
.arg_uniform(TypeInt) // firstcheck
.mask()),
args);
}
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/liboslexec/builtindecl_wide_xmacro.h
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,8 @@ DECL(__OSL_MASKED_OP(range_check), "xXiisXsisiss")
DECL(__OSL_OP2(uninit_check_values_offset, X, i), "xLXXsisissisisii")
DECL(__OSL_MASKED_OP2(uninit_check_values_offset, X, Wi), "xiLXXsisissisisXi")
DECL(__OSL_MASKED_OP2(uninit_check_values_offset, WX, i), "xiLXXsisissisisii")
DECL(__OSL_MASKED_OP3(uninit_check_values_offset, WX, i, Wi),
"xiLXXsisissisisiX")
DECL(__OSL_MASKED_OP2(uninit_check_values_offset, WX, Wi), "xiLXXsisissisisXi")

DECL(__OSL_OP1(get_attribute, s), "iXissiiXXi")
Expand Down
23 changes: 21 additions & 2 deletions src/liboslexec/llvm_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ static ustring op_aref("aref");
static ustring op_compref("compref");
static ustring op_mxcompref("mxcompref");
static ustring op_useparam("useparam");
static ustring op_pointcloud_get("pointcloud_get");
static ustring op_spline("spline");
static ustring op_splineinverse("splineinverse");
static ustring unknown_shader_group_name("<Unknown Shader Group Name>");


Expand Down Expand Up @@ -1135,8 +1138,10 @@ BackendLLVM::llvm_generate_debug_uninit(const Opcode& op)
// don't generate uninit test code for it.
continue;
}
if (op.opname() == Strings::op_dowhile && i == 0) {
// The first argument of 'dowhile' is the condition temp, but
if (((op.opname() == Strings::op_dowhile)
|| (op.opname() == Strings::op_while))
&& i == 0) {
// The first argument of 'dowhile' or "while" is the condition temp, but
// most likely its initializer has not run yet. Unless there is
// no "condition" code block, in that case we should still test
// it for uninit.
Expand Down Expand Up @@ -1185,6 +1190,20 @@ BackendLLVM::llvm_generate_debug_uninit(const Opcode& op)
comp = ll.op_add(comp, col_ind);
offset = comp;
ncheck = ll.constant(1);
} else if (op.opname() == op_pointcloud_get && i == 2) {
// int pointcloud_get (string ptcname, int indices[], int count, string attr, type data[])
// will only read indices[0..count-1], so limit the check to count
OSL_ASSERT(3 < op.nargs());
ncheck = llvm_load_value(*opargsym(op, 3));
} else if (((op.opname() == op_spline)
|| (op.opname() == op_splineinverse))
&& i == 4) {
// If an explicit knot count was provided to spline|splineinverse we should
// limit our check of knot values to that count
bool has_knot_count = (op.nargs() == 5);
if (has_knot_count) {
ncheck = llvm_load_value(*opargsym(op, 3));
}
}

llvm::Value* args[] = { ll.constant(t),
Expand Down
Loading
Loading