+ if(!n_levels)
+ throw invalid_argument("Synchronizer::split_image_mipmap");
+
+ auto i = lower_bound_member(image_accesses, image, &ImageAccess::image);
+ if(i!=image_accesses.end() && i->image==image && i->level>=0)
+ return;
+
+ if(i!=image_accesses.end() && i->image==image && i->level==-1)
+ {
+ i = image_accesses.insert(i, n_levels-1, *i);
+ for(unsigned j=0; j<n_levels; ++i, ++j)
+ i->level = j;
+ }
+ else
+ {
+ ImageAccess access;
+ access.image = image;
+ access.aspect = aspect;
+ access.current_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ access.pending_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+
+ if(i->level==-2)
+ i = image_accesses.erase(i);
+
+ for(unsigned j=0; j<n_levels; ++i, ++j)
+ if(i==image_accesses.end() || i->image!=image || i->level>static_cast<int>(j))
+ {
+ i = image_accesses.insert(i, access);
+ i->level = j;
+ }
+ }
+}
+
+void Synchronizer::change_image_layout(VkImage image, unsigned aspect, int level, unsigned layout, bool discard)
+{
+ auto i = lower_bound_member(image_accesses, image, &ImageAccess::image);
+
+ if(level>=0)
+ {
+ if(i==image_accesses.end() || i->image!=image)
+ {
+ i = image_accesses.emplace(i);
+ i->image = image;
+ i->level = -2;
+ ++i;
+ }
+ else if(i->level==-1)
+ throw invalid_operation("Synchronizer::change_image_layout");
+ else
+ {
+ for(; (i!=image_accesses.end() && i->image==image && i->level<level); ++i) ;
+ }
+ }
+ else if(i!=image_accesses.end() && i->image==image && i->level==-2)
+ throw invalid_operation("Synchronizer::change_image_layout");
+
+ if(i==image_accesses.end() || i->image!=image || (level>=0 && i->level!=level))