diff --git a/src/cmake/testing.cmake b/src/cmake/testing.cmake index 18b4ec7b6..92a69e58a 100644 --- a/src/cmake/testing.cmake +++ b/src/cmake/testing.cmake @@ -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 diff --git a/src/liboslexec/batched_analysis.cpp b/src/liboslexec/batched_analysis.cpp index 97287529b..8c60b1d70 100644 --- a/src/liboslexec/batched_analysis.cpp +++ b/src/liboslexec/batched_analysis.cpp @@ -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) @@ -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 @@ -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; } @@ -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; } @@ -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 @@ -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. @@ -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(), @@ -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]; diff --git a/src/liboslexec/batched_llvm_instance.cpp b/src/liboslexec/batched_llvm_instance.cpp index b9bf7423a..5d81ec018 100644 --- a/src/liboslexec/batched_llvm_instance.cpp +++ b/src/liboslexec/batched_llvm_instance.cpp @@ -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(""); @@ -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; @@ -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) { @@ -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); } @@ -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); + } } } } diff --git a/src/liboslexec/builtindecl_wide_xmacro.h b/src/liboslexec/builtindecl_wide_xmacro.h index f35889bf5..1a2314a4c 100644 --- a/src/liboslexec/builtindecl_wide_xmacro.h +++ b/src/liboslexec/builtindecl_wide_xmacro.h @@ -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") diff --git a/src/liboslexec/llvm_instance.cpp b/src/liboslexec/llvm_instance.cpp index f92f889ef..974f95b17 100644 --- a/src/liboslexec/llvm_instance.cpp +++ b/src/liboslexec/llvm_instance.cpp @@ -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(""); @@ -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. @@ -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), diff --git a/src/liboslexec/wide/wide_shadingsys.cpp b/src/liboslexec/wide/wide_shadingsys.cpp index 847705fb2..e25c665c5 100644 --- a/src/liboslexec/wide/wide_shadingsys.cpp +++ b/src/liboslexec/wide/wide_shadingsys.cpp @@ -169,10 +169,10 @@ __OSL_OP2(uninit_check_values_offset, X, ustring layername = USTR(layername_); ctx->errorfmt( "Detected possible use of uninitialized value in {} {} at {}:{} (group {}, layer {} {}, shader {}, op {} '{}', arg {})", - typedesc, symbolname, sourcefile, sourceline, + typedesc, USTR(symbolname), USTR(sourcefile), sourceline, groupname.empty() ? "" : groupname.c_str(), layer, layername.empty() ? "" : layername.c_str(), - shadername, opnum, opname, argnum); + USTR(shadername), opnum, USTR(opname), argnum); } } @@ -233,10 +233,82 @@ __OSL_MASKED_OP2(uninit_check_values_offset, WX, 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, + typedesc, USTR(symbolname), USTR(sourcefile), sourceline, groupname.empty() ? "" : groupname.c_str(), layer, layername.empty() ? "" : layername.c_str(), - shadername, opnum, opname, argnum, lanes_uninit.value()); + USTR(shadername), opnum, USTR(opname), argnum, + lanes_uninit.value()); + } +} + + + +// Many parameters, but the 3 parameters used in the function name +// correspond to: "vals", "firstcheck", and "nchecks" +OSL_BATCHOP void +__OSL_MASKED_OP3(uninit_check_values_offset, WX, i, + Wi)(int mask_value, long long typedesc_, void* vals_, + void* bsg_, ustring_pod sourcefile, int sourceline, + ustring_pod groupname_, int layer, ustring_pod layername_, + ustring_pod shadername, int opnum, ustring_pod opname, + int argnum, ustring_pod symbolname, int firstcheck, + int* nchecks_) +{ + TypeDesc typedesc = TYPEDESC(typedesc_); + auto* bsg = reinterpret_cast(bsg_); + ShadingContext* ctx = bsg->uniform.context; + const Mask mask(mask_value); + + Mask lanes_uninit(false); + + if (typedesc.basetype == TypeDesc::FLOAT) { + float* vals = (float*)vals_; + mask.foreach ([=, &lanes_uninit](ActiveLane lane) -> void { + int nchecks = nchecks_[lane]; + for (int c = firstcheck, e = firstcheck + nchecks; c < e; ++c) { + if (!std::isfinite(vals[c * __OSL_WIDTH + lane])) { + lanes_uninit.set_on(lane); + vals[c * __OSL_WIDTH + lane] = 0; + } + } + }); + } + if (typedesc.basetype == TypeDesc::INT) { + int* vals = (int*)vals_; + mask.foreach ([=, &lanes_uninit](ActiveLane lane) -> void { + int nchecks = nchecks_[lane]; + for (int c = firstcheck, e = firstcheck + nchecks; c < e; ++c) { + if (vals[c * __OSL_WIDTH + lane] + == std::numeric_limits::min()) { + lanes_uninit.set_on(lane); + vals[c * __OSL_WIDTH + lane] = 0; + } + } + }); + } + if (typedesc.basetype == TypeDesc::STRING) { + ustring* vals = (ustring*)vals_; + mask.foreach ([=, &lanes_uninit](ActiveLane lane) -> void { + int nchecks = nchecks_[lane]; + for (int c = firstcheck, e = firstcheck + nchecks; c < e; ++c) { + if (vals[c * __OSL_WIDTH + lane] + == Strings::uninitialized_string) { + lanes_uninit.set_on(lane); + vals[c * __OSL_WIDTH + lane] = ustring(); + } + } + }); + } + if (lanes_uninit.any_on()) { + 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, USTR(symbolname), USTR(sourcefile), sourceline, + groupname.empty() ? "" : groupname.c_str(), layer, + layername.empty() ? "" : layername.c_str(), + USTR(shadername), opnum, USTR(opname), argnum, + lanes_uninit.value()); } } @@ -299,10 +371,11 @@ __OSL_MASKED_OP2(uninit_check_values_offset, X, 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, + typedesc, USTR(symbolname), USTR(sourcefile), sourceline, groupname.empty() ? "" : groupname.c_str(), layer, layername.empty() ? "" : layername.c_str(), - shadername, opnum, opname, argnum, lanes_uninit.value()); + USTR(shadername), opnum, USTR(opname), argnum, + lanes_uninit.value()); } } @@ -367,10 +440,11 @@ __OSL_MASKED_OP2(uninit_check_values_offset, WX, 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, + typedesc, USTR(symbolname), USTR(sourcefile), sourceline, groupname.empty() ? "" : groupname.c_str(), layer, layername.empty() ? "" : layername.c_str(), - shadername, opnum, opname, argnum, lanes_uninit.value()); + USTR(shadername), opnum, USTR(opname), argnum, + lanes_uninit.value()); } } diff --git a/src/testshade/batched_simplerend.cpp b/src/testshade/batched_simplerend.cpp index 403c80894..470a6b604 100644 --- a/src/testshade/batched_simplerend.cpp +++ b/src/testshade/batched_simplerend.cpp @@ -21,6 +21,7 @@ struct UniqueStringCache { , red("red") , green("green") , blue("blue") + , face_idx("face_idx") , lookupTable("lookupTable") , blahblah("blahblah") , options("options") @@ -51,6 +52,7 @@ struct UniqueStringCache { ustring red; ustring green; ustring blue; + ustring face_idx; ustring lookupTable; ustring blahblah; ustring options; @@ -663,7 +665,16 @@ BatchedSimpleRenderer::get_userdata(ustringhash name, // For testing of interactions with default values // may not provide data for all lanes - if (name == ucache().s && Masked::is(val)) { + if (name == ucache().face_idx && Masked::is(val)) { + Masked out(val); + for (int i = 0; i < WidthT; ++i) { + if (out[i].is_on()) { + out[i] = int(4 * bsg->varying.u[i]); + } + } + return out.mask(); + } + else if (name == ucache().s && Masked::is(val)) { Masked out(val); for (int i = 0; i < WidthT; ++i) { // NOTE: assigning to out[i] will mask by itself diff --git a/src/testshade/rs_simplerend.cpp b/src/testshade/rs_simplerend.cpp index 13c3ce45c..93c9c960d 100644 --- a/src/testshade/rs_simplerend.cpp +++ b/src/testshade/rs_simplerend.cpp @@ -555,6 +555,13 @@ rs_get_attribute(OSL::OpaqueExecContextPtr oec, OSL::ustringhash_pod object_, return false; } +OSL_RSOP OSL_HOSTDEVICE bool +rs_get_interpolated_face_idx(OSL::OpaqueExecContextPtr ec, void* val) +{ + ((int*)val)[0] = int(4 * OSL::get_u(ec)); + return true; +} + OSL_RSOP OSL_HOSTDEVICE bool rs_get_interpolated_s(OSL::OpaqueExecContextPtr ec, bool derivatives, void* val) { diff --git a/src/testshade/rs_strdecls.h b/src/testshade/rs_strdecls.h index 0a072a470..f078dd334 100644 --- a/src/testshade/rs_strdecls.h +++ b/src/testshade/rs_strdecls.h @@ -37,4 +37,5 @@ RS_STRDECL("t", t) RS_STRDECL("red", red) RS_STRDECL("green", green) RS_STRDECL("blue", blue) +RS_STRDECL("face_idx", face_idx) RS_STRDECL("test", test) diff --git a/src/testshade/simplerend.cpp b/src/testshade/simplerend.cpp index 7e67ab063..7338aeb49 100644 --- a/src/testshade/simplerend.cpp +++ b/src/testshade/simplerend.cpp @@ -508,6 +508,10 @@ SimpleRenderer::get_userdata(bool derivatives, ustringhash name, TypeDesc type, // look up something specific to the primitive, rather than have hard- // coded names. + if (name == RS::Hashes::face_idx && type == TypeInt) { + ((int*)val)[0] = int(4 * sg->u); + return true; + } if (name == RS::Hashes::s && type == TypeFloat) { ((float*)val)[0] = sg->u; if (derivatives) { @@ -682,6 +686,7 @@ SimpleRenderer::build_interpolated_getter(const ShaderGroup& group, TypeDesc type, bool derivatives, InterpolatedGetterSpec& spec) { + static const OIIO::ustring rs_get_interpolated_face_idx("rs_get_interpolated_face_idx"); static const OIIO::ustring rs_get_interpolated_s("rs_get_interpolated_s"); static const OIIO::ustring rs_get_interpolated_t("rs_get_interpolated_t"); static const OIIO::ustring rs_get_interpolated_red( @@ -711,7 +716,10 @@ SimpleRenderer::build_interpolated_getter(const ShaderGroup& group, static const OIIO::ustring rs_get_attribute_constant_float4( "rs_get_attribute_constant_float4"); - if (param_name == RS::Hashes::s && type == OIIO::TypeFloat) { + if (param_name == RS::Hashes::face_idx && type == OIIO::TypeInt) { + spec.set(rs_get_interpolated_face_idx, + InterpolatedSpecBuiltinArg::OpaqueExecutionContext); + } else if (param_name == RS::Hashes::s && type == OIIO::TypeFloat) { spec.set(rs_get_interpolated_s, InterpolatedSpecBuiltinArg::OpaqueExecutionContext, InterpolatedSpecBuiltinArg::Derivatives); diff --git a/testsuite/debug-uninit/ref/out-opt2.txt b/testsuite/debug-uninit/ref/out-opt2.txt index 25d3b5860..fdf901da6 100644 --- a/testsuite/debug-uninit/ref/out-opt2.txt +++ b/testsuite/debug-uninit/ref/out-opt2.txt @@ -8,3 +8,5 @@ ERROR: [RendererServices::texture] ImageInput::create() called with no filename ERROR: Detected possible use of uninitialized value in float[3] A at test.osl:22 (group unnamed_group_1, layer 0 test_0, shader test, op 7 'aref', arg 1) ERROR: Detected possible use of uninitialized value in color C at test.osl:28 (group unnamed_group_1, layer 0 test_0, shader test, op 12 'compref', arg 1) ERROR: Detected possible use of uninitialized value in matrix M at test.osl:34 (group unnamed_group_1, layer 0 test_0, shader test, op 17 'mxcompref', arg 1) +ERROR: Detected possible use of uninitialized value in float[20] knots3 at test.osl:54 (group unnamed_group_1, layer 0 test_0, shader test, op 44 'spline', arg 4) +ERROR: Detected possible use of uninitialized value in float[20] knots4 at test.osl:55 (group unnamed_group_1, layer 0 test_0, shader test, op 46 'splineinverse', arg 4) diff --git a/testsuite/debug-uninit/ref/out.txt b/testsuite/debug-uninit/ref/out.txt index b549b7390..a0908b811 100644 --- a/testsuite/debug-uninit/ref/out.txt +++ b/testsuite/debug-uninit/ref/out.txt @@ -8,3 +8,5 @@ ERROR: [RendererServices::texture] ImageInput::create() called with no filename ERROR: Detected possible use of uninitialized value in float[3] A at test.osl:22 (group unnamed_group_1, layer 0 test_0, shader test, op 12 'aref', arg 1) ERROR: Detected possible use of uninitialized value in color C at test.osl:28 (group unnamed_group_1, layer 0 test_0, shader test, op 17 'compref', arg 1) ERROR: Detected possible use of uninitialized value in matrix M at test.osl:34 (group unnamed_group_1, layer 0 test_0, shader test, op 22 'mxcompref', arg 1) +ERROR: Detected possible use of uninitialized value in float[20] knots3 at test.osl:54 (group unnamed_group_1, layer 0 test_0, shader test, op 49 'spline', arg 4) +ERROR: Detected possible use of uninitialized value in float[20] knots4 at test.osl:55 (group unnamed_group_1, layer 0 test_0, shader test, op 51 'splineinverse', arg 4) diff --git a/testsuite/debug-uninit/test.osl b/testsuite/debug-uninit/test.osl index 1bb06aec0..92773383d 100644 --- a/testsuite/debug-uninit/test.osl +++ b/testsuite/debug-uninit/test.osl @@ -33,5 +33,29 @@ test (output color Cout = 0) x += M[1][2]; // NOT an error x += M[0][0]; // An error } + float knots[20]; + float knots2[20]; + float knots3[20]; + float knots4[20]; + int index=0; + // Ensure no false positive for temporary condition variable + while (index < 10) { + knots[index] = x*index; + knots2[index] = (1.0-x)*index; + knots3[index] = 2*x*index; + knots4[index] = 2*(1.0-x)*index; + ++index; + } + // Ensure no false positive for accessing initialized portion of a partially initialized array + x += spline ("linear", x, 10, knots); + x += splineinverse ("linear", x, 10, knots2); + + // Accessing uninitialized portion of a partially initialized array + x += spline ("linear", x, 15, knots3); + x += splineinverse ("linear", x, 15, knots4); + + // pointcloud_get could also have false postive and read partially initialized array + // leaving pointcloud_get out, as not all builds are configured for pointcloud support + Cout[0] += x; // force x results to not be optimized away } diff --git a/testsuite/lockgeom/BATCHED b/testsuite/lockgeom/BATCHED new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/lockgeom/ref/out.txt b/testsuite/lockgeom/ref/out.txt new file mode 100644 index 000000000..3101eca80 --- /dev/null +++ b/testsuite/lockgeom/ref/out.txt @@ -0,0 +1,12 @@ +Compiled test0.osl -> test0.oso +Compiled test1.osl -> test1.oso +Compiled test2.osl -> test2.oso +Compiled test3.osl -> test3.oso + +Output dst to out0.tif + +Output dst to out1.tif + +Output dst to out2.tif + +Output dst to out3.tif diff --git a/testsuite/lockgeom/ref/out0.tif b/testsuite/lockgeom/ref/out0.tif new file mode 100644 index 000000000..f74b7bcbb Binary files /dev/null and b/testsuite/lockgeom/ref/out0.tif differ diff --git a/testsuite/lockgeom/ref/out1.tif b/testsuite/lockgeom/ref/out1.tif new file mode 100644 index 000000000..f74b7bcbb Binary files /dev/null and b/testsuite/lockgeom/ref/out1.tif differ diff --git a/testsuite/lockgeom/ref/out2.tif b/testsuite/lockgeom/ref/out2.tif new file mode 100644 index 000000000..f74b7bcbb Binary files /dev/null and b/testsuite/lockgeom/ref/out2.tif differ diff --git a/testsuite/lockgeom/ref/out3.tif b/testsuite/lockgeom/ref/out3.tif new file mode 100644 index 000000000..f74b7bcbb Binary files /dev/null and b/testsuite/lockgeom/ref/out3.tif differ diff --git a/testsuite/lockgeom/run.py b/testsuite/lockgeom/run.py new file mode 100755 index 000000000..050c47d46 --- /dev/null +++ b/testsuite/lockgeom/run.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python + +# Copyright Contributors to the Open Shading Language project. +# SPDX-License-Identifier: BSD-3-Clause +# https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + +# The tests are similar but have different default values of face_idx +# to make sure batched analysis doesn't force interpolated integer +# argements to be boolean. +command = testshade("-t 1 --res 256 256 -od uint8 -o dst out0.tif test0") +command += testshade("-t 1 --res 256 256 -od uint8 -o dst out1.tif test1") +command += testshade("-t 1 --res 256 256 -od uint8 -o dst out2.tif test2") +command += testshade("-t 1 --res 256 256 -od uint8 -o dst out3.tif test3") +outputs.append ("out0.tif") +outputs.append ("out1.tif") +outputs.append ("out2.tif") +outputs.append ("out3.tif") diff --git a/testsuite/lockgeom/test0.osl b/testsuite/lockgeom/test0.osl new file mode 100644 index 000000000..d9c5ae20a --- /dev/null +++ b/testsuite/lockgeom/test0.osl @@ -0,0 +1,9 @@ +// Copyright Contributors to the Open Shading Language project. +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + +shader test0(int face_idx = 0 [[int lockgeom = 0]], + output color dst = 0) +{ + dst = color(face_idx * 0.25, 0, 0); +} \ No newline at end of file diff --git a/testsuite/lockgeom/test1.osl b/testsuite/lockgeom/test1.osl new file mode 100644 index 000000000..be6b43629 --- /dev/null +++ b/testsuite/lockgeom/test1.osl @@ -0,0 +1,9 @@ +// Copyright Contributors to the Open Shading Language project. +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + +shader test1(int face_idx = 1 [[int lockgeom = 0]], + output color dst = 0) +{ + dst = color(face_idx * 0.25, 0, 0); +} \ No newline at end of file diff --git a/testsuite/lockgeom/test2.osl b/testsuite/lockgeom/test2.osl new file mode 100644 index 000000000..68a013044 --- /dev/null +++ b/testsuite/lockgeom/test2.osl @@ -0,0 +1,9 @@ +// Copyright Contributors to the Open Shading Language project. +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + +shader test2(int face_idx = 2 [[int lockgeom = 0]], + output color dst = 0) +{ + dst = color(face_idx * 0.25, 0, 0); +} \ No newline at end of file diff --git a/testsuite/lockgeom/test3.osl b/testsuite/lockgeom/test3.osl new file mode 100644 index 000000000..abceaf980 --- /dev/null +++ b/testsuite/lockgeom/test3.osl @@ -0,0 +1,9 @@ +// Copyright Contributors to the Open Shading Language project. +// SPDX-License-Identifier: BSD-3-Clause +// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage + +shader test3(int face_idx = 3 [[int lockgeom = 0]], + output color dst = 0) +{ + dst = color(face_idx * 0.25, 0, 0); +} \ No newline at end of file