Undo: support implicit-sharing in memfile undo step #106903
|
@ -931,7 +931,8 @@ static void export_hair_curves_motion(Hair *hair,
|
|||
}
|
||||
|
||||
/* Export motion keys. */
|
||||
const int num_keys = hair->get_curve_keys().size();
|
||||
const size_t num_keys = hair->num_keys();
|
||||
const size_t num_curves = hair->num_curves();
|
||||
float4 *mP = attr_mP->data_float4() + motion_step * num_keys;
|
||||
bool have_motion = false;
|
||||
int num_motion_keys = 0;
|
||||
|
@ -944,6 +945,9 @@ static void export_hair_curves_motion(Hair *hair,
|
|||
|
||||
for (const int i : points_by_curve.index_range()) {
|
||||
const blender::IndexRange points = points_by_curve[i];
|
||||
if (curve_index >= num_curves) {
|
||||
break;
|
||||
}
|
||||
|
||||
Hair::Curve curve = hair->get_curve(curve_index);
|
||||
curve_index++;
|
||||
|
|
|
@ -661,9 +661,7 @@ void HIPDevice::tex_alloc(device_texture &mem)
|
|||
address_mode = hipAddressModeClamp;
|
||||
break;
|
||||
case EXTENSION_CLIP:
|
||||
/* TODO(@arya): setting this to Mode Clamp instead of Mode Border
|
||||
* because it's unsupported in HIP. */
|
||||
address_mode = hipAddressModeClamp;
|
||||
address_mode = hipAddressModeBorder;
|
||||
break;
|
||||
case EXTENSION_MIRROR:
|
||||
address_mode = hipAddressModeMirror;
|
||||
|
@ -855,7 +853,11 @@ void HIPDevice::tex_alloc(device_texture &mem)
|
|||
thread_scoped_lock lock(device_mem_map_mutex);
|
||||
cmem = &device_mem_map[&mem];
|
||||
|
||||
hip_assert(hipTexObjectCreate(&cmem->texobject, &resDesc, &texDesc, NULL));
|
||||
if (hipTexObjectCreate(&cmem->texobject, &resDesc, &texDesc, NULL) != hipSuccess) {
|
||||
set_error(
|
||||
"Failed to create texture. Maximum GPU texture size or available GPU memory was likely "
|
||||
"exceeded.");
|
||||
}
|
||||
|
||||
texture_info[slot].data = (uint64_t)cmem->texobject;
|
||||
}
|
||||
|
|
|
@ -5319,6 +5319,45 @@ static void write_grid_paint_mask(BlendWriter *writer,
|
|||
}
|
||||
}
|
||||
|
||||
static void blend_write_layer_data(BlendWriter *writer,
|
||||
const CustomDataLayer &layer,
|
||||
const int count)
|
||||
{
|
||||
switch (layer.type) {
|
||||
case CD_MDEFORMVERT:
|
||||
BKE_defvert_blend_write(writer, count, static_cast<const MDeformVert *>(layer.data));
|
||||
break;
|
||||
case CD_MDISPS:
|
||||
write_mdisps(
|
||||
writer, count, static_cast<const MDisps *>(layer.data), layer.flag & CD_FLAG_EXTERNAL);
|
||||
break;
|
||||
case CD_PAINT_MASK:
|
||||
BLO_write_raw(writer, sizeof(float) * count, static_cast<const float *>(layer.data));
|
||||
break;
|
||||
case CD_GRID_PAINT_MASK:
|
||||
write_grid_paint_mask(writer, count, static_cast<const GridPaintMask *>(layer.data));
|
||||
break;
|
||||
case CD_PROP_BOOL:
|
||||
BLO_write_raw(writer, sizeof(bool) * count, static_cast<const bool *>(layer.data));
|
||||
break;
|
||||
default: {
|
||||
const char *structname;
|
||||
int structnum;
|
||||
CustomData_file_write_info(eCustomDataType(layer.type), &structname, &structnum);
|
||||
if (structnum) {
|
||||
int datasize = structnum * count;
|
||||
BLO_write_struct_array_by_name(writer, structname, datasize, layer.data);
|
||||
}
|
||||
else if (!BLO_write_is_undo(writer)) { /* Do not warn on undo. */
|
||||
printf("%s error: layer '%s':%d - can't be written to file\n",
|
||||
__func__,
|
||||
structname,
|
||||
layer.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CustomData_blend_write(BlendWriter *writer,
|
||||
CustomData *data,
|
||||
Span<CustomDataLayer> layers_to_write,
|
||||
|
@ -5337,41 +5376,7 @@ void CustomData_blend_write(BlendWriter *writer,
|
|||
for (const CustomDataLayer &layer : layers_to_write) {
|
||||
const size_t size_in_bytes = CustomData_sizeof(eCustomDataType(layer.type)) * count;
|
||||
BLO_write_shared(writer, layer.data, size_in_bytes, layer.sharing_info, [&]() {
|
||||
switch (layer.type) {
|
||||
case CD_MDEFORMVERT:
|
||||
BKE_defvert_blend_write(writer, count, static_cast<const MDeformVert *>(layer.data));
|
||||
break;
|
||||
case CD_MDISPS:
|
||||
write_mdisps(writer,
|
||||
count,
|
||||
static_cast<const MDisps *>(layer.data),
|
||||
layer.flag & CD_FLAG_EXTERNAL);
|
||||
break;
|
||||
case CD_PAINT_MASK:
|
||||
BLO_write_raw(writer, sizeof(float) * count, static_cast<const float *>(layer.data));
|
||||
break;
|
||||
case CD_GRID_PAINT_MASK:
|
||||
write_grid_paint_mask(writer, count, static_cast<const GridPaintMask *>(layer.data));
|
||||
break;
|
||||
case CD_PROP_BOOL:
|
||||
BLO_write_raw(writer, sizeof(bool) * count, static_cast<const bool *>(layer.data));
|
||||
break;
|
||||
default: {
|
||||
const char *structname;
|
||||
int structnum;
|
||||
CustomData_file_write_info(eCustomDataType(layer.type), &structname, &structnum);
|
||||
if (structnum) {
|
||||
int datasize = structnum * count;
|
||||
BLO_write_struct_array_by_name(writer, structname, datasize, layer.data);
|
||||
}
|
||||
else if (!BLO_write_is_undo(writer)) { /* Do not warn on undo. */
|
||||
printf("%s error: layer '%s':%d - can't be written to file\n",
|
||||
__func__,
|
||||
structname,
|
||||
layer.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
blend_write_layer_data(writer, layer, count);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ static void add_values_to_text_cache(const GVArray &values,
|
|||
const float3 position = math::transform_point(object_to_world, positions[i]);
|
||||
const T &value = values_typed[i];
|
||||
|
||||
char numstr[32];
|
||||
char numstr[64];
|
||||
size_t numstr_len = 0;
|
||||
if constexpr (std::is_same_v<T, bool>) {
|
||||
numstr_len = SNPRINTF_RLEN(numstr, "%s", value ? "True" : "False");
|
||||
|
@ -77,7 +77,8 @@ static void add_values_to_text_cache(const GVArray &values,
|
|||
numstr, "(%.3f, %.3f, %.3f, %.3f)", value.r, value.g, value.b, value.a);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, math::Quaternion>) {
|
||||
numstr_len = SNPRINTF_RLEN(numstr, "(%g, %g, %g, %g)", value.w, value.x, value.y, value.z);
|
||||
numstr_len = SNPRINTF_RLEN(
|
||||
numstr, "(%.3f, %.3f, %.3f, %.3f)", value.w, value.x, value.y, value.z);
|
||||
}
|
||||
else {
|
||||
BLI_assert_unreachable();
|
||||
|
|
|
@ -1429,13 +1429,33 @@ static int imb_exr_split_token(const char *str, const char *end, const char **to
|
|||
return int(end - *token);
|
||||
}
|
||||
|
||||
static void imb_exr_pass_name_from_channel(char *passname,
|
||||
const ExrChannel *echan,
|
||||
const char *channelname,
|
||||
const bool has_xyz_channels)
|
||||
{
|
||||
const int passname_maxncpy = EXR_TOT_MAXNAME;
|
||||
|
||||
if (echan->chan_id == 'Z' && (!has_xyz_channels || BLI_strcaseeq(channelname, "depth"))) {
|
||||
BLI_strncpy(passname, "Depth", passname_maxncpy);
|
||||
}
|
||||
else if (echan->chan_id == 'Y' && !has_xyz_channels) {
|
||||
BLI_strncpy(passname, channelname, passname_maxncpy);
|
||||
}
|
||||
else if (ELEM(echan->chan_id, 'R', 'G', 'B', 'A', 'V', 'X', 'Y', 'Z')) {
|
||||
BLI_strncpy(passname, "Combined", passname_maxncpy);
|
||||
}
|
||||
else {
|
||||
BLI_strncpy(passname, channelname, passname_maxncpy);
|
||||
}
|
||||
}
|
||||
|
||||
static int imb_exr_split_channel_name(ExrChannel *echan,
|
||||
char *layname,
|
||||
char *passname,
|
||||
bool has_xyz_channels)
|
||||
{
|
||||
const int layname_maxncpy = EXR_TOT_MAXNAME;
|
||||
const int passname_maxncpy = EXR_TOT_MAXNAME;
|
||||
const char *name = echan->m->name.c_str();
|
||||
const char *end = name + strlen(name);
|
||||
const char *token;
|
||||
|
@ -1450,20 +1470,7 @@ static int imb_exr_split_channel_name(ExrChannel *echan,
|
|||
* versions of the listed channels. */
|
||||
echan->chan_id = BLI_toupper_ascii(name[0]);
|
||||
layname[0] = '\0';
|
||||
|
||||
if (echan->chan_id == 'Z' && !has_xyz_channels) {
|
||||
BLI_strncpy(passname, "Depth", passname_maxncpy);
|
||||
}
|
||||
else if (echan->chan_id == 'Y' && !has_xyz_channels) {
|
||||
BLI_strncpy(passname, name, passname_maxncpy);
|
||||
}
|
||||
else if (ELEM(echan->chan_id, 'R', 'G', 'B', 'A', 'V', 'X', 'Y', 'Z')) {
|
||||
BLI_strncpy(passname, "Combined", passname_maxncpy);
|
||||
}
|
||||
else {
|
||||
BLI_strncpy(passname, name, passname_maxncpy);
|
||||
}
|
||||
|
||||
imb_exr_pass_name_from_channel(passname, echan, name, has_xyz_channels);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1519,14 +1526,20 @@ static int imb_exr_split_channel_name(ExrChannel *echan,
|
|||
}
|
||||
end -= len + 1; /* +1 to skip '.' separator */
|
||||
|
||||
/* second token is pass name */
|
||||
len = imb_exr_split_token(name, end, &token);
|
||||
if (len == 0) {
|
||||
printf("multilayer read: bad channel name: %s\n", name);
|
||||
return 0;
|
||||
if (end > name) {
|
||||
/* second token is pass name */
|
||||
len = imb_exr_split_token(name, end, &token);
|
||||
if (len == 0) {
|
||||
printf("multilayer read: bad channel name: %s\n", name);
|
||||
return 0;
|
||||
}
|
||||
BLI_strncpy(passname, token, len + 1);
|
||||
end -= len + 1; /* +1 to skip '.' separator */
|
||||
}
|
||||
else {
|
||||
/* Single token, determine pass name from channel name. */
|
||||
imb_exr_pass_name_from_channel(passname, echan, channelname, has_xyz_channels);
|
||||
}
|
||||
BLI_strncpy(passname, token, len + 1);
|
||||
end -= len + 1; /* +1 to skip '.' separator */
|
||||
|
||||
/* all preceding tokens combined as layer name */
|
||||
if (end > name) {
|
||||
|
@ -1592,10 +1605,65 @@ static bool exr_has_xyz_channels(ExrHandle *exr_handle)
|
|||
return x_found && y_found && z_found;
|
||||
}
|
||||
|
||||
static bool imb_exr_multilayer_parse_channels_from_file(ExrHandle *data)
|
||||
/* Replacement for OpenEXR GetChannelsInMultiPartFile, that also handles the
|
||||
* case where parts are used for passes instead of multiview. */
|
||||
static std::vector<MultiViewChannelName> exr_channels_in_multi_part_file(
|
||||
const MultiPartInputFile &file)
|
||||
{
|
||||
std::vector<MultiViewChannelName> channels;
|
||||
GetChannelsInMultiPartFile(*data->ifile, channels);
|
||||
|
||||
/* Detect if file has multiview. */
|
||||
StringVector multiview;
|
||||
bool has_multiview = false;
|
||||
if (file.parts() == 1) {
|
||||
if (hasMultiView(file.header(0))) {
|
||||
multiview = multiView(file.header(0));
|
||||
has_multiview = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get channels from each part. */
|
||||
for (int p = 0; p < file.parts(); p++) {
|
||||
const ChannelList &c = file.header(p).channels();
|
||||
|
||||
std::string part_view = "";
|
||||
if (file.header(p).hasView()) {
|
||||
part_view = file.header(p).view();
|
||||
}
|
||||
std::string part_name = "";
|
||||
if (file.header(p).hasName()) {
|
||||
part_name = file.header(p).name();
|
||||
}
|
||||
|
||||
for (ChannelList::ConstIterator i = c.begin(); i != c.end(); i++) {
|
||||
MultiViewChannelName m;
|
||||
m.name = std::string(i.name());
|
||||
m.internal_name = m.name;
|
||||
|
||||
if (has_multiview) {
|
||||
m.view = viewFromChannelName(m.name, multiview);
|
||||
m.name = removeViewName(m.internal_name, m.view);
|
||||
}
|
||||
else {
|
||||
m.view = part_view;
|
||||
}
|
||||
|
||||
/* Prepend part name as potential layer or pass name. */
|
||||
if (!part_name.empty()) {
|
||||
m.name = part_name + "." + m.name;
|
||||
}
|
||||
|
||||
m.part_number = p;
|
||||
channels.push_back(m);
|
||||
}
|
||||
}
|
||||
|
||||
return channels;
|
||||
}
|
||||
|
||||
static bool imb_exr_multilayer_parse_channels_from_file(ExrHandle *data)
|
||||
{
|
||||
std::vector<MultiViewChannelName> channels = exr_channels_in_multi_part_file(*data->ifile);
|
||||
|
||||
imb_exr_get_views(*data->ifile, *data->multiView);
|
||||
|
||||
|
|
Loading…
Reference in New Issue