Skip to content

Feature: Ability to sparsely gather scalar values and connect them to elements of a dynamic or statically sized array parameter #1826

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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 @@ -398,6 +398,7 @@ macro (osl_add_all_tests)
userdata userdata-defaults userdata-partial userdata-custom userdata-passthrough
vararray-connect vararray-default
vararray-deserialize vararray-param
vararray-scalar-connect
vecctr vector vector-reg
wavelength_color wavelength_color-reg Werror xml xml-reg )

Expand Down
71 changes: 44 additions & 27 deletions src/liboslexec/backendllvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -742,37 +742,40 @@ BackendLLVM::llvm_test_nonzero(Symbol& val, bool test_derivs)


bool
BackendLLVM::llvm_assign_impl(Symbol& Result, Symbol& Src, int arrayindex,
int srccomp, int dstcomp)
BackendLLVM::llvm_assign_impl(Symbol& Result, Symbol& Src, int srcarrayindex,
int dstarrayindex, int srccomp, int dstcomp)
{
OSL_DASSERT(!Result.typespec().is_structure());
OSL_DASSERT(!Src.typespec().is_structure());

const TypeSpec& result_t(Result.typespec());
const TypeSpec& src_t(Src.typespec());

llvm::Value* arrind = arrayindex >= 0 ? ll.constant(arrayindex) : NULL;
llvm::Value* sarrind = srcarrayindex >= 0 ? ll.constant(srcarrayindex)
: NULL;
llvm::Value* darrind = dstarrayindex >= 0 ? ll.constant(dstarrayindex)
: NULL;

if (Result.typespec().is_closure() || Src.typespec().is_closure()) {
if (Src.typespec().is_closure()) {
llvm::Value* srcval = llvm_load_value(Src, 0, arrind, 0);
llvm_store_value(srcval, Result, 0, arrind, 0);
llvm::Value* srcval = llvm_load_value(Src, 0, sarrind, 0);
llvm_store_value(srcval, Result, 0, darrind, 0);
} else {
llvm::Value* null = ll.constant_ptr(NULL, ll.type_void_ptr());
llvm_store_value(null, Result, 0, arrind, 0);
llvm_store_value(null, Result, 0, darrind, 0);
}
return true;
}

if (Result.typespec().is_matrix() && Src.typespec().is_int_or_float()) {
// Handle m=f, m=i separately
llvm::Value* src = llvm_load_value(Src, 0, arrind, 0,
llvm::Value* src = llvm_load_value(Src, 0, sarrind, 0,
TypeDesc::FLOAT /*cast*/);
// m=f sets the diagonal components to f, the others to zero
llvm::Value* zero = ll.constant(0.0f);
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
llvm_store_value(i == j ? src : zero, Result, 0, arrind,
llvm_store_value(i == j ? src : zero, Result, 0, darrind,
i * 4 + j);
llvm_zero_derivs(Result); // matrices don't have derivs currently
return true;
Expand All @@ -786,7 +789,7 @@ BackendLLVM::llvm_assign_impl(Symbol& Result, Symbol& Src, int arrayindex,
// 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.is_constant() && src_t.is_array()
&& arrayindex == -1) {
&& srcarrayindex == -1 && dstarrayindex == -1) {
OSL_DASSERT(assignable(result_t.elementtype(), src_t.elementtype()));
llvm::Value* resultptr = llvm_get_pointer(Result);
llvm::Value* srcptr = llvm_get_pointer(Src);
Expand All @@ -806,12 +809,14 @@ BackendLLVM::llvm_assign_impl(Symbol& Result, Symbol& Src, int arrayindex,

// The following code handles f=f, f=i, v=v, v=f, v=i, m=m, s=s.
// Remember that llvm_load_value will automatically convert scalar->triple.
TypeDesc rt = Result.typespec().simpletype();
TypeDesc basetype = TypeDesc::BASETYPE(rt.basetype);
const int num_components = rt.aggregate;
const bool singlechan = (srccomp != -1) || (dstcomp != -1);
if (!singlechan) {
if (rt.is_array() && arrayindex == -1) {
TypeDesc rt = Result.typespec().simpletype();
TypeDesc basetype = TypeDesc::BASETYPE(rt.basetype);
const int num_components = rt.aggregate;
const bool singlechan = (srccomp != -1) || (dstcomp != -1);
const bool scalar_to_array_elem = (Src.arraylen() == 0
&& dstarrayindex != -1);
if (!singlechan && !scalar_to_array_elem) {
if (rt.is_array() && srcarrayindex == -1 && dstarrayindex == -1) {
// Initialize entire array
const int num_elements = std::min(rt.numelements(),
src_t.simpletype().numelements());
Expand All @@ -836,32 +841,43 @@ BackendLLVM::llvm_assign_impl(Symbol& Result, Symbol& Src, int arrayindex,
for (int i = 0; i < num_components; ++i) {
llvm::Value* src_val
= Src.is_constant()
? llvm_load_constant_value(Src, arrayindex, i,
? llvm_load_constant_value(Src, srcarrayindex, i,
basetype)
: llvm_load_value(Src, 0, arrind, i, basetype);
: llvm_load_value(Src, 0, sarrind, i, basetype);
if (!src_val)
return false;
llvm_store_value(src_val, Result, 0, arrind, i);
llvm_store_value(src_val, Result, 0, darrind, i);
}
}
} else if (scalar_to_array_elem) {
for (int i = 0; i < num_components; ++i) {
llvm::Value* src_val
= Src.is_constant()
? llvm_load_constant_value(Src, -1, i, basetype)
: llvm_load_value(Src, 0, NULL, i, basetype);
if (!src_val)
return false;
llvm_store_value(src_val, Result, 0, darrind, i);
}
} else {
// connect individual component of an aggregate type
// set srccomp to 0 for case when src is actually a float
if (srccomp == -1)
srccomp = 0;
llvm::Value* src_val
= Src.is_constant()
? llvm_load_constant_value(Src, arrayindex, srccomp, basetype)
: llvm_load_value(Src, 0, arrind, srccomp, basetype);
? llvm_load_constant_value(Src, srcarrayindex, srccomp,
basetype)
: llvm_load_value(Src, 0, sarrind, srccomp, basetype);
if (!src_val)
return false;
// write source float into all components when dstcomp == -1, otherwise
// the single element requested.
if (dstcomp == -1) {
for (int i = 0; i < num_components; ++i)
llvm_store_value(src_val, Result, 0, arrind, i);
llvm_store_value(src_val, Result, 0, darrind, i);
} else
llvm_store_value(src_val, Result, 0, arrind, dstcomp);
llvm_store_value(src_val, Result, 0, darrind, dstcomp);
}

// Handle derivatives
Expand All @@ -871,18 +887,19 @@ BackendLLVM::llvm_assign_impl(Symbol& Result, Symbol& Src, int arrayindex,
if (!singlechan) {
for (int d = 1; d <= 2; ++d) {
for (int i = 0; i < num_components; ++i) {
llvm::Value* val = llvm_load_value(Src, d, arrind, i);
llvm_store_value(val, Result, d, arrind, i);
llvm::Value* val = llvm_load_value(Src, d, sarrind, i);
llvm_store_value(val, Result, d, darrind, i);
}
}
} else {
for (int d = 1; d <= 2; ++d) {
llvm::Value* val = llvm_load_value(Src, d, arrind, srccomp);
llvm::Value* val = llvm_load_value(Src, d, sarrind,
srccomp);
if (dstcomp == -1) {
for (int i = 0; i < num_components; ++i)
llvm_store_value(val, Result, d, arrind, i);
llvm_store_value(val, Result, d, darrind, i);
} else
llvm_store_value(val, Result, d, arrind, dstcomp);
llvm_store_value(val, Result, d, darrind, dstcomp);
}
}
} else {
Expand Down
8 changes: 5 additions & 3 deletions src/liboslexec/backendllvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ class BackendLLVM final : public OSOProcessorBase {

void llvm_create_constant(const Symbol& sym);

void llvm_assign_initial_value(const Symbol& sym, bool force = false);
void llvm_assign_initial_value(const Symbol& sym, bool force = false,
int arrayindex = -1);
llvm::LLVMContext& llvm_context() const { return ll.context(); }
AllocationMap& named_values() { return m_named_values; }

Expand Down Expand Up @@ -256,8 +257,9 @@ class BackendLLVM final : public OSOProcessorBase {

/// Implementation of Simple assignment. If arrayindex >= 0, in
/// designates a particular array index to assign.
bool llvm_assign_impl(Symbol& Result, Symbol& Src, int arrayindex = -1,
int srccomp = -1, int dstcomp = -1);
bool llvm_assign_impl(Symbol& Result, Symbol& Src, int srcarrayindex = -1,
int dstarrayindex = -1, int srccomp = -1,
int dstcomp = -1);


/// Convert the name of a global (and its derivative index) into the
Expand Down
84 changes: 51 additions & 33 deletions src/liboslexec/batched_backendllvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1894,7 +1894,8 @@ BatchedBackendLLVM::llvm_test_nonzero(const Symbol& val, bool test_derivs)

bool
BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,
int arrayindex, int srccomp, int dstcomp)
int srcarrayindex, int dstarrayindex,
int srccomp, int dstcomp)
{
OSL_DEV_ONLY(std::cout << "llvm_assign_impl arrayindex=" << arrayindex
<< " Result(" << Result.name()
Expand All @@ -1914,25 +1915,28 @@ BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,
const TypeSpec& result_t(Result.typespec());
const TypeSpec& src_t(Src.typespec());

llvm::Value* arrind = arrayindex >= 0 ? ll.constant(arrayindex) : NULL;
llvm::Value* sarrind = srcarrayindex >= 0 ? ll.constant(srcarrayindex)
: NULL;
llvm::Value* darrind = dstarrayindex >= 0 ? ll.constant(dstarrayindex)
: NULL;

if (Result.typespec().is_closure() || Src.typespec().is_closure()) {
if (Src.typespec().is_closure()) {
llvm::Value* srcval = llvm_load_value(Src, 0, arrind, 0,
llvm::Value* srcval = llvm_load_value(Src, 0, sarrind, 0,
TypeUnknown, op_is_uniform);
llvm_store_value(srcval, Result, 0, arrind, 0);
llvm_store_value(srcval, Result, 0, darrind, 0);
} else {
llvm::Value* null_value = ll.constant_ptr(NULL, ll.type_void_ptr());
if (!op_is_uniform)
null_value = ll.widen_value(null_value);
llvm_store_value(null_value, Result, 0, arrind, 0);
llvm_store_value(null_value, Result, 0, darrind, 0);
}
return true;
}

if (Result.typespec().is_matrix() && Src.typespec().is_int_or_float()) {
// Handle m=f, m=i separately
llvm::Value* src = llvm_load_value(Src, 0, arrind, 0,
llvm::Value* src = llvm_load_value(Src, 0, sarrind, 0,
TypeDesc::FLOAT /*cast*/,
op_is_uniform);
// m=f sets the diagonal components to f, the others to zero
Expand All @@ -1944,7 +1948,7 @@ BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,

for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
llvm_store_value(i == j ? src : zero, Result, 0, arrind,
llvm_store_value(i == j ? src : zero, Result, 0, darrind,
i * 4 + j);
llvm_zero_derivs(Result); // matrices don't have derivs currently
return true;
Expand All @@ -1954,34 +1958,36 @@ BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,

// The following code handles f=f, f=i, v=v, v=f, v=i, m=m, s=s.
// Remember that llvm_load_value will automatically convert scalar->triple.
TypeDesc rt = Result.typespec().simpletype();
TypeDesc basetype = TypeDesc::BASETYPE(rt.basetype);
const int num_components = rt.aggregate;
const bool singlechan = (srccomp != -1) || (dstcomp != -1);
TypeDesc rt = Result.typespec().simpletype();
TypeDesc basetype = TypeDesc::BASETYPE(rt.basetype);
const int num_components = rt.aggregate;
const bool singlechan = (srccomp != -1) || (dstcomp != -1);
const bool scalar_to_array_elem = (Src.arraylen() == 0
&& dstarrayindex != -1);

// Because we are not mem-copying arrays wholesale,
// We will add an outer array index loop to copy 1 element or entire array
int start_array_index = arrayindex;
int start_array_index = srcarrayindex;
int end_array_index = start_array_index + 1;
if (start_array_index == -1) {
if (srcarrayindex == -1 && dstarrayindex == -1) {
if (result_t.is_array() && src_t.is_array()) {
start_array_index = 0;
end_array_index = std::min(result_t.arraylength(),
src_t.arraylength());
start_array_index = dstarrayindex = srcarrayindex = 0;
end_array_index = std::min(result_t.arraylength(),
src_t.arraylength());
}
}
for (arrayindex = start_array_index; arrayindex < end_array_index;
++arrayindex) {
arrind = arrayindex >= 0 ? ll.constant(arrayindex) : NULL;

if (!singlechan) {
for (srcarrayindex = start_array_index; srcarrayindex < end_array_index;
++srcarrayindex, ++dstarrayindex) {
sarrind = srcarrayindex >= 0 ? ll.constant(srcarrayindex) : NULL;
darrind = dstarrayindex >= 0 ? ll.constant(dstarrayindex) : NULL;
if (!singlechan && !scalar_to_array_elem) {
for (int i = 0; i < num_components; ++i) {
// Automatically handle widening the source value to match the destination's
llvm::Value* src_val
= Src.is_constant()
? llvm_load_constant_value(Src, arrayindex, i,
? llvm_load_constant_value(Src, srcarrayindex, i,
basetype, op_is_uniform)
: llvm_load_value(Src, 0, arrind, i, basetype,
: llvm_load_value(Src, 0, sarrind, i, basetype,
op_is_uniform);
if (!src_val)
return false;
Expand All @@ -1991,7 +1997,19 @@ BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,
<< ll.llvm_typenameof(src_val) << std::endl);
// The llvm_load_value above should have handled bool to int conversions
// when the basetype == Typedesc::INT
llvm_store_value(src_val, Result, 0, arrind, i);
llvm_store_value(src_val, Result, 0, darrind, i);
}
} else if (scalar_to_array_elem) {
for (int i = 0; i < num_components; ++i) {
llvm::Value* src_val
= Src.is_constant()
? llvm_load_constant_value(Src, -1, i, basetype,
op_is_uniform)
: llvm_load_value(Src, 0, NULL, i, basetype,
op_is_uniform);
if (!src_val)
return false;
llvm_store_value(src_val, Result, 0, darrind, i);
}
} else {
// connect individual component of an aggregate type
Expand All @@ -2001,9 +2019,9 @@ BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,
// Automatically handle widening the source value to match the destination's
llvm::Value* src_val
= Src.is_constant()
? llvm_load_constant_value(Src, arrayindex, srccomp,
? llvm_load_constant_value(Src, srcarrayindex, srccomp,
basetype, op_is_uniform)
: llvm_load_value(Src, 0, arrind, srccomp, basetype,
: llvm_load_value(Src, 0, sarrind, srccomp, basetype,
op_is_uniform);
if (!src_val)
return false;
Expand All @@ -2015,9 +2033,9 @@ BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,
// the single element requested.
if (dstcomp == -1) {
for (int i = 0; i < num_components; ++i)
llvm_store_value(src_val, Result, 0, arrind, i);
llvm_store_value(src_val, Result, 0, darrind, i);
} else
llvm_store_value(src_val, Result, 0, arrind, dstcomp);
llvm_store_value(src_val, Result, 0, darrind, dstcomp);
}

// Handle derivatives
Expand All @@ -2036,25 +2054,25 @@ BatchedBackendLLVM::llvm_assign_impl(const Symbol& Result, const Symbol& Src,
if (Src.has_derivs()) {
// src and result both have derivs -- copy them
// allow a uniform Src to store to a varying Result,
val = llvm_load_value(Src, d, arrind, i,
val = llvm_load_value(Src, d, sarrind, i,
TypeUnknown, op_is_uniform);
}
llvm_store_value(val, Result, d, arrind, i);
llvm_store_value(val, Result, d, darrind, i);
}
} else {
llvm::Value* val = zero;
if (Src.has_derivs()) {
// src and result both have derivs -- copy them
// allow a uniform Src to store to a varying Result,
val = llvm_load_value(Src, d, arrind, srccomp,
val = llvm_load_value(Src, d, sarrind, srccomp,
TypeUnknown, op_is_uniform);
}

if (dstcomp == -1) {
for (int i = 0; i < num_components; ++i)
llvm_store_value(val, Result, d, arrind, i);
llvm_store_value(val, Result, d, darrind, i);
} else
llvm_store_value(val, Result, d, arrind, dstcomp);
llvm_store_value(val, Result, d, darrind, dstcomp);
}
}
}
Expand Down
Loading
Loading