Skip to content

Commit

Permalink
MM Image Cache - Fix erasing group items
Browse files Browse the repository at this point in the history
When a user clears all the memory in a shot, the underlying
ImageCache::m_cpu_group_map would be changed, but the code is
iteratiting over it, so we must manually check the group exists each
time, and remove the first value each time. This probably has a
performance impact, but it's required for stability and safety.
  • Loading branch information
david-cattermole committed Oct 5, 2024
1 parent 625ae74 commit 91c1de1
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 46 deletions.
66 changes: 62 additions & 4 deletions src/mmSolver/cmd/MMImageCacheCmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ MStatus MMImageCacheCmd::parseArgs(const MArgList &args) {
MStringArray string_objects;
argData.getObjects(string_objects);

// TODO: Do we actually use the group name? Or can it be removed?
m_group_name = "";
if (string_objects.length() > 0) {
const std::string item_name = string_objects[0].asChar();
Expand Down Expand Up @@ -408,32 +409,73 @@ inline MStatus set_values(image::ImageCache &image_cache,
const std::vector<std::string> &item_names,
const std::string &group_name,
size_t &out_item_count) {
const bool verbose = false;
MStatus status = MStatus::kSuccess;

const auto command_flag_int = static_cast<int>(command_flag);
if (verbose) {
std::stringstream item_names_ss;
for (auto it = item_names.begin(); it != item_names.end(); it++) {
auto item_name = *it;
item_names_ss << item_name << ";";
}
MMSOLVER_MAYA_VRB("MMImageCacheCmd::set_values: "
<< "command_flag=" << command_flag_int
<< " gpu_capacity_bytes=" << gpu_capacity_bytes
<< " cpu_capacity_bytes=" << cpu_capacity_bytes
<< " item_names=" << item_names_ss.str()
<< " item_names.size()=" << item_names.size()
<< " group_name=" << group_name.c_str()
<< " group_name.size()=" << group_name.size());
}

out_item_count = 0;
if (command_flag == ImageCacheFlagMode::kGpuCapacity) {
MMSOLVER_MAYA_VRB("MMImageCacheCmd::set_values: "
<< "flag=\"" << GPU_CAPACITY_FLAG_LONG << "\"");

MHWRender::MTextureManager *texture_manager = nullptr;
status = get_texture_manager(texture_manager);
CHECK_MSTATUS_AND_RETURN_IT(status);

image_cache.set_gpu_capacity_bytes(texture_manager, gpu_capacity_bytes);
} else if (command_flag == ImageCacheFlagMode::kCpuCapacity) {
MMSOLVER_MAYA_VRB("MMImageCacheCmd::set_values: "
<< "flag=\"" << CPU_CAPACITY_FLAG_LONG << "\"");

image_cache.set_cpu_capacity_bytes(cpu_capacity_bytes);
} else if (command_flag == ImageCacheFlagMode::kGpuEraseItems) {
MMSOLVER_MAYA_VRB("MMImageCacheCmd::set_values: "
<< "flag=\"" << GPU_ERASE_ITEMS_FLAG_LONG << "\"");

MHWRender::MTextureManager *texture_manager = nullptr;
status = get_texture_manager(texture_manager);
CHECK_MSTATUS_AND_RETURN_IT(status);

for (auto it = item_names.begin(); it != item_names.end(); it++) {
const bool ok = image_cache.gpu_erase_item(texture_manager, *it);
auto item_name = *it;
MMSOLVER_MAYA_VRB("MMImageCacheCmd::set_values: "
<< "item_name=\"" << item_name.c_str() << "\"");
const bool ok =
image_cache.gpu_erase_item(texture_manager, item_name);
out_item_count += static_cast<bool>(ok);
}
} else if (command_flag == ImageCacheFlagMode::kCpuEraseItems) {
MMSOLVER_MAYA_VRB("MMImageCacheCmd::set_values: "
<< "flag=\"" << CPU_ERASE_ITEMS_FLAG_LONG << "\"");

for (auto it = item_names.begin(); it != item_names.end(); it++) {
const bool ok = image_cache.cpu_erase_item(*it);
auto item_name = *it;
MMSOLVER_MAYA_VRB("MMImageCacheCmd::set_values: "
<< "item_name=\"" << item_name.c_str() << "\"");
const bool ok = image_cache.cpu_erase_item(item_name);
out_item_count += static_cast<bool>(ok);
}
} else if (command_flag == ImageCacheFlagMode::kGpuEraseGroupItems) {
MMSOLVER_MAYA_VRB("MMImageCacheCmd::set_values: "
<< "flag=\"" << CPU_ERASE_GROUP_ITEMS_FLAG_LONG
<< "\"");

if (group_name.size() == 0) {
MMSOLVER_MAYA_ERR("MMImageCacheCmd::set_values: "
<< "\"" << GPU_ERASE_GROUP_ITEMS_FLAG_LONG
Expand All @@ -449,10 +491,17 @@ inline MStatus set_values(image::ImageCache &image_cache,
CHECK_MSTATUS_AND_RETURN_IT(status);

for (auto it = item_names.begin(); it != item_names.end(); it++) {
auto item_name = *it;
MMSOLVER_MAYA_VRB("MMImageCacheCmd::set_values: "
<< "item_name=\"" << item_name.c_str() << "\"");
out_item_count +=
image_cache.gpu_erase_group_items(texture_manager, *it);
image_cache.gpu_erase_group_items(texture_manager, item_name);
}
} else if (command_flag == ImageCacheFlagMode::kCpuEraseGroupItems) {
MMSOLVER_MAYA_VRB("MMImageCacheCmd::set_values: "
<< "flag=\"" << CPU_ERASE_GROUP_ITEMS_FLAG_LONG
<< "\"");

if (group_name.size() == 0) {
MMSOLVER_MAYA_ERR("MMImageCacheCmd::set_values: "
<< "\"" << CPU_ERASE_GROUP_ITEMS_FLAG_LONG
Expand All @@ -463,8 +512,14 @@ inline MStatus set_values(image::ImageCache &image_cache,
return MStatus::kFailure;
}

MMSOLVER_MAYA_VRB("MMImageCacheCmd::set_values: "
<< "group_name=\"" << group_name.c_str() << "\"");

for (auto it = item_names.begin(); it != item_names.end(); it++) {
out_item_count = image_cache.cpu_erase_group_items(*it);
auto item_name = *it;
MMSOLVER_MAYA_VRB("MMImageCacheCmd::set_values: "
<< "item_name=\"" << item_name.c_str() << "\"");
out_item_count += image_cache.cpu_erase_group_items(item_name);
}
} else {
MMSOLVER_MAYA_ERR(
Expand All @@ -475,6 +530,9 @@ inline MStatus set_values(image::ImageCache &image_cache,
return MStatus::kFailure;
}

MMSOLVER_MAYA_VRB(
"MMImageCacheCmd::set_values: out_item_count=" << out_item_count);

return status;
}

Expand Down
116 changes: 74 additions & 42 deletions src/mmSolver/image/ImageCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -842,18 +842,19 @@ size_t ImageCache::gpu_remove_item_from_group(const GPUCacheKey item_key) {
it2 = values_set.erase(it2);
count += 1;
MMSOLVER_MAYA_VRB(
"mmsolver::ImageCache::gpu_erase_item: "
"mmsolver::ImageCache::gpu_remove_item_from_group: "
<< "group_key=" << group_key << " item_key=" << item_key
<< " item_value_hash=" << item_value_hash << " - got it");
} else {
MMSOLVER_MAYA_VRB("mmsolver::ImageCache::gpu_erase_item: "
<< "item_key=" << item_key
<< " item_value_hash=" << item_value_hash);
MMSOLVER_MAYA_VRB(
"mmsolver::ImageCache::gpu_remove_item_from_group: "
<< "item_key=" << item_key
<< " item_value_hash=" << item_value_hash);
++it2;
}
}

MMSOLVER_MAYA_VRB("mmsolver::ImageCache::gpu_erase_item: "
MMSOLVER_MAYA_VRB("mmsolver::ImageCache::gpu_remove_item_from_group: "
<< "values_set.size()=" << values_set.size());

if (values_set.size() == 0) {
Expand All @@ -862,7 +863,7 @@ size_t ImageCache::gpu_remove_item_from_group(const GPUCacheKey item_key) {
++it;
}
}
MMSOLVER_MAYA_VRB("mmsolver::ImageCache::gpu_erase_item: "
MMSOLVER_MAYA_VRB("mmsolver::ImageCache::gpu_remove_item_from_group: "
<< "count=" << count);

return count;
Expand Down Expand Up @@ -893,18 +894,19 @@ size_t ImageCache::cpu_remove_item_from_group(const CPUCacheKey item_key) {
it2 = values_set.erase(it2);
count += 1;
MMSOLVER_MAYA_VRB(
"mmsolver::ImageCache::cpu_erase_item: "
"mmsolver::ImageCache::cpu_remove_item_from_group: "
<< "group_key=" << group_key << " item_key=" << item_key
<< " item_value_hash=" << item_value_hash << " - got it");
} else {
MMSOLVER_MAYA_VRB("mmsolver::ImageCache::cpu_erase_item: "
<< "item_key=" << item_key
<< " item_value_hash=" << item_value_hash);
MMSOLVER_MAYA_VRB(
"mmsolver::ImageCache::cpu_remove_item_from_group: "
<< "item_key=" << item_key
<< " item_value_hash=" << item_value_hash);
++it2;
}
}

MMSOLVER_MAYA_VRB("mmsolver::ImageCache::cpu_erase_item: "
MMSOLVER_MAYA_VRB("mmsolver::ImageCache::cpu_remove_item_from_group: "
<< "values_set.size()=" << values_set.size());

if (values_set.size() == 0) {
Expand All @@ -913,7 +915,7 @@ size_t ImageCache::cpu_remove_item_from_group(const CPUCacheKey item_key) {
++it;
}
}
MMSOLVER_MAYA_VRB("mmsolver::ImageCache::cpu_erase_item: "
MMSOLVER_MAYA_VRB("mmsolver::ImageCache::cpu_remove_item_from_group: "
<< "count=" << count);

return count;
Expand All @@ -924,7 +926,7 @@ bool ImageCache::gpu_erase_item(MHWRender::MTextureManager *texture_manager,
const bool verbose = false;
const GPUGroupKey item_key = mmsolver::hash::make_hash(file_path);
MMSOLVER_MAYA_VRB("mmsolver::ImageCache::gpu_erase_item: "
<< "item_key=" << item_key << "file_path=\""
<< "item_key=" << item_key << " file_path=\""
<< file_path.c_str() << "\"");
return ImageCache::gpu_erase_item(texture_manager, item_key);
}
Expand Down Expand Up @@ -958,7 +960,7 @@ bool ImageCache::cpu_erase_item(const CPUCacheString &file_path) {
const bool verbose = false;
const CPUGroupKey item_key = mmsolver::hash::make_hash(file_path);
MMSOLVER_MAYA_VRB("mmsolver::ImageCache::cpu_erase_item: "
<< "item_key=" << item_key << "file_path=\""
<< "item_key=" << item_key << " file_path=\""
<< file_path.c_str() << "\"");
return ImageCache::cpu_erase_item(item_key);
}
Expand Down Expand Up @@ -995,26 +997,41 @@ size_t ImageCache::gpu_erase_group_items(
if (verbose) {
const GPUGroupKey group_key = mmsolver::hash::make_hash(group_name);
MMSOLVER_MAYA_VRB("mmsolver::ImageCache::gpu_erase_group_items: "
<< "group_key=" << group_key << "group_name=\""
<< "group_key=" << group_key << " group_name=\""
<< group_name.c_str() << "\"");
}

const GPUGroupMapIt group_search = m_gpu_group_map.find(group_name);
const bool group_found = group_search != m_gpu_group_map.end();
if (!group_found) {
MMSOLVER_MAYA_WRN(
"mmsolver::ImageCache: gpu_erase_group_items: "
"Group name \""
<< group_name << "\" not found!");
return 0;
}

// Loop until all items in the group are removed.
size_t iteration = 0;
size_t count = 0;
GPUGroupSet &values_set = group_search->second;
for (auto it = values_set.begin(); it != values_set.end(); it++) {
GPUCacheString value = *it;
while (true) {
const GPUGroupMapIt group_search = m_gpu_group_map.find(group_name);
const bool group_found = group_search != m_gpu_group_map.end();
if (!group_found) {
if (iteration == 0) {
// When a user gives the wrong group name, we will
// print the warning, but if the group name is not
// valid after a removal (iteration > 0), then the
// user shouldn't be notified of that the group is not
// available.
MMSOLVER_MAYA_WRN(
"mmsolver::ImageCache: gpu_erase_group_items: "
"Group name \""
<< group_name << "\" not found!");
}
break;
}

GPUGroupSet &values_set = group_search->second;
GPUCacheString value = *values_set.begin();
// NOTE: This call will invalidate the 'values_set' value,
// because 'ImageCache::m_gpu_group_map' is changed by
// 'ImageCache::gpu_remove_item_from_group()' via
// 'ImageCache::gpu_erase_item()'.
const bool ok = ImageCache::gpu_erase_item(texture_manager, value);
count += static_cast<size_t>(ok);

iteration++;
}

return count;
Expand All @@ -1026,26 +1043,41 @@ size_t ImageCache::cpu_erase_group_items(const CPUCacheString &group_name) {
if (verbose) {
const CPUGroupKey group_key = mmsolver::hash::make_hash(group_name);
MMSOLVER_MAYA_VRB("mmsolver::ImageCache::cpu_erase_group_items: "
<< "group_key=" << group_key << "group_name=\""
<< "group_key=" << group_key << " group_name=\""
<< group_name.c_str() << "\"");
}

const CPUGroupMapIt group_search = m_cpu_group_map.find(group_name);
const bool group_found = group_search != m_cpu_group_map.end();
if (!group_found) {
MMSOLVER_MAYA_WRN(
"mmsolver::ImageCache: cpu_erase_group_items: "
"Group name \""
<< group_name << "\" not found!");
return 0;
}

// Loop until all items in the group are removed.
size_t iteration = 0;
size_t count = 0;
CPUGroupSet &values_set = group_search->second;
for (auto it = values_set.begin(); it != values_set.end(); it++) {
CPUCacheString value = *it;
while (true) {
const CPUGroupMapIt group_search = m_cpu_group_map.find(group_name);
const bool group_found = group_search != m_cpu_group_map.end();
if (!group_found) {
if (iteration == 0) {
// When a user gives the wrong group name, we will
// print the warning, but if the group name is not
// valid after a removal (iteration > 0), then the
// user shouldn't be notified of that the group is not
// available.
MMSOLVER_MAYA_WRN(
"mmsolver::ImageCache: cpu_erase_group_items: "
"Group name \""
<< group_name << "\" not found!");
}
break;
}

CPUGroupSet &values_set = group_search->second;
CPUCacheString value = *values_set.begin();
// NOTE: This call will invalidate the 'values_set' value,
// because 'ImageCache::m_cpu_group_map' is changed by
// 'ImageCache::cpu_remove_item_from_group()' via
// 'ImageCache::cpu_erase_item()'.
const bool ok = ImageCache::cpu_erase_item(value);
count += static_cast<size_t>(ok);

iteration++;
}

return count;
Expand Down

0 comments on commit 91c1de1

Please sign in to comment.