43 const RenderState *RenderState::_empty_state =
nullptr;
44 UpdateSeq RenderState::_last_cycle_detect;
45 size_t RenderState::_garbage_index = 0;
47 PStatCollector RenderState::_cache_update_pcollector(
"*:State Cache:Update");
48 PStatCollector RenderState::_garbage_collect_pcollector(
"*:State Cache:Garbage Collect");
49 PStatCollector RenderState::_state_compose_pcollector(
"*:State Cache:Compose State");
50 PStatCollector RenderState::_state_invert_pcollector(
"*:State Cache:Invert State");
51 PStatCollector RenderState::_node_counter(
"RenderStates:On nodes");
53 PStatCollector RenderState::_state_break_cycles_pcollector(
"*:State Cache:Break Cycles");
54 PStatCollector RenderState::_state_validate_pcollector(
"*:State Cache:Validate");
71 if (_states ==
nullptr) {
76 _cache_stats.add_num_states(1);
77 _read_overrides =
nullptr;
78 _generated_shader =
nullptr;
80 #ifdef DO_MEMORY_USAGE
90 _filled_slots(copy._filled_slots),
95 for (
int i = 0; i < RenderAttribRegistry::_max_slots; ++i) {
96 _attributes[i] = copy._attributes[i];
101 _cache_stats.add_num_states(1);
102 _read_overrides =
nullptr;
103 _generated_shader =
nullptr;
105 #ifdef DO_MEMORY_USAGE
117 nassertv(!is_destructing());
123 nassertv(_saved_entry == -1);
124 nassertv(_composition_cache.
is_empty() && _invert_composition_cache.
is_empty());
142 SlotMask mask = _filled_slots | other._filled_slots;
145 int result = _attributes[slot].compare_to(other._attributes[slot]);
165 if (
this == &other) {
172 for (
int n = 0; n < num_sorted_slots; ++n) {
174 nassertr((_attributes[slot]._attrib !=
nullptr) == _filled_slots.
get_bit(slot), 0);
177 const RenderAttrib *b = other._attributes[slot]._attrib;
179 return a < b ? -1 : 1;
197 const RenderAttrib *b = other._attributes[slot]._attrib;
199 return a < b ? -1 : 1;
218 const Attribute &attrib = _attributes[slot];
219 nassertr(attrib._attrib !=
nullptr,
false);
220 if (!attrib._attrib->cull_callback(trav, data)) {
237 int slot = attrib->get_slot();
238 state->_attributes[slot].set(attrib,
override);
239 state->_filled_slots.
set_bit(slot);
240 return return_new(state);
250 state->_attributes[attrib1->get_slot()].set(attrib1,
override);
251 state->_attributes[attrib2->get_slot()].set(attrib2,
override);
252 state->_filled_slots.
set_bit(attrib1->get_slot());
253 state->_filled_slots.
set_bit(attrib2->get_slot());
254 return return_new(state);
265 state->_attributes[attrib1->get_slot()].set(attrib1,
override);
266 state->_attributes[attrib2->get_slot()].set(attrib2,
override);
267 state->_attributes[attrib3->get_slot()].set(attrib3,
override);
268 state->_filled_slots.
set_bit(attrib1->get_slot());
269 state->_filled_slots.
set_bit(attrib2->get_slot());
270 state->_filled_slots.
set_bit(attrib3->get_slot());
271 return return_new(state);
283 state->_attributes[attrib1->get_slot()].set(attrib1,
override);
284 state->_attributes[attrib2->get_slot()].set(attrib2,
override);
285 state->_attributes[attrib3->get_slot()].set(attrib3,
override);
286 state->_attributes[attrib4->get_slot()].set(attrib4,
override);
287 state->_filled_slots.
set_bit(attrib1->get_slot());
288 state->_filled_slots.
set_bit(attrib2->get_slot());
289 state->_filled_slots.
set_bit(attrib3->get_slot());
290 state->_filled_slots.
set_bit(attrib4->get_slot());
291 return return_new(state);
304 state->_attributes[attrib1->get_slot()].set(attrib1,
override);
305 state->_attributes[attrib2->get_slot()].set(attrib2,
override);
306 state->_attributes[attrib3->get_slot()].set(attrib3,
override);
307 state->_attributes[attrib4->get_slot()].set(attrib4,
override);
308 state->_attributes[attrib5->get_slot()].set(attrib5,
override);
309 state->_filled_slots.
set_bit(attrib1->get_slot());
310 state->_filled_slots.
set_bit(attrib2->get_slot());
311 state->_filled_slots.
set_bit(attrib3->get_slot());
312 state->_filled_slots.
set_bit(attrib4->get_slot());
313 state->_filled_slots.
set_bit(attrib5->get_slot());
314 return return_new(state);
321 make(
const RenderAttrib *
const *attrib,
int num_attribs,
int override) {
322 if (num_attribs == 0) {
326 for (
int i = 0; i < num_attribs; i++) {
327 int slot = attrib[i]->get_slot();
328 state->_attributes[slot].set(attrib[i],
override);
329 state->_filled_slots.
set_bit(slot);
331 return return_new(state);
358 return do_compose(other);
364 int index = _composition_cache.
find(other);
366 Composition &comp = ((
RenderState *)
this)->_composition_cache.modify_data(index);
367 if (comp._result ==
nullptr) {
372 comp._result = result;
397 ((
RenderState *)
this)->_composition_cache[other]._result = result;
402 ((
RenderState *)other)->_composition_cache[
this]._result =
nullptr;
447 return do_invert_compose(other);
453 int index = _invert_composition_cache.
find(other);
455 Composition &comp = ((
RenderState *)
this)->_invert_composition_cache.modify_data(index);
456 if (comp._result ==
nullptr) {
460 CPT(
RenderState) result = do_invert_compose(other);
461 comp._result = result;
481 CPT(
RenderState) result = do_invert_compose(other);
485 ((
RenderState *)
this)->_invert_composition_cache[other]._result = result;
490 ((
RenderState *)other)->_invert_composition_cache[
this]._result =
nullptr;
513 add_attrib(
const RenderAttrib *attrib,
int override)
const {
514 int slot = attrib->get_slot();
515 if (_filled_slots.
get_bit(slot) &&
516 _attributes[slot]._override >
override) {
523 new_state->_attributes[slot].set(attrib,
override);
524 new_state->_filled_slots.
set_bit(slot);
525 return return_new(new_state);
537 int slot = attrib->get_slot();
538 new_state->_attributes[slot]._attrib = attrib;
539 new_state->_filled_slots.
set_bit(slot);
540 return return_new(new_state);
550 set_attrib(
const RenderAttrib *attrib,
int override)
const {
552 int slot = attrib->get_slot();
553 new_state->_attributes[slot].set(attrib,
override);
554 new_state->_filled_slots.
set_bit(slot);
555 return return_new(new_state);
563 remove_attrib(
int slot)
const {
564 if (_attributes[slot]._attrib ==
nullptr) {
575 new_state->_attributes[slot].set(
nullptr, 0);
576 new_state->_filled_slots.
clear_bit(slot);
577 return return_new(new_state);
587 adjust_all_priorities(
int adjustment)
const {
590 SlotMask mask = _filled_slots;
593 Attribute &attrib = new_state->_attributes[slot];
594 nassertr(attrib._attrib !=
nullptr,
this);
595 attrib._override = std::max(attrib._override + adjustment, 0);
597 mask.clear_bit(slot);
598 slot = mask.get_lowest_on_bit();
601 return return_new(new_state);
612 if (garbage_collect_states || !state_cache) {
628 if (auto_break_cycles && uniquify_states) {
656 output(ostream &out)
const {
663 const char *sep =
"";
665 SlotMask mask = _filled_slots;
668 const Attribute &attrib = _attributes[slot];
669 nassertv(attrib._attrib !=
nullptr);
670 out << sep << attrib._attrib->get_type();
673 mask.clear_bit(slot);
674 slot = mask.get_lowest_on_bit();
684 write(ostream &out,
int indent_level)
const {
690 SlotMask mask = _filled_slots;
693 const Attribute &attrib = _attributes[slot];
694 nassertv(attrib._attrib !=
nullptr);
695 attrib._attrib->write(out, indent_level);
697 mask.clear_bit(slot);
698 slot = mask.get_lowest_on_bit();
719 if (_states ==
nullptr) {
741 if (_states ==
nullptr) {
749 StateCount state_count;
752 for (
size_t si = 0; si < size; ++si) {
757 for (i = 0; i < cache_size; ++i) {
759 if (result !=
nullptr && result != state) {
761 std::pair<StateCount::iterator, bool> ir =
762 state_count.insert(StateCount::value_type(result, 1));
766 (*(ir.first)).second++;
771 for (i = 0; i < cache_size; ++i) {
773 if (result !=
nullptr && result != state) {
774 std::pair<StateCount::iterator, bool> ir =
775 state_count.insert(StateCount::value_type(result, 1));
777 (*(ir.first)).second++;
788 StateCount::iterator sci;
789 for (sci = state_count.begin(); sci != state_count.end(); ++sci) {
791 int count = (*sci).second;
797 if (pgraph_cat.is_debug()) {
799 <<
"Unused state: " << (
void *)state <<
":"
801 state->write(pgraph_cat.debug(
false), 2);
824 if (_states ==
nullptr) {
838 TempStates temp_states;
839 temp_states.reserve(orig_size);
842 for (
size_t si = 0; si < size; ++si) {
844 temp_states.push_back(state);
849 TempStates::iterator ti;
850 for (ti = temp_states.begin(); ti != temp_states.end(); ++ti) {
855 for (i = 0; i < cache_size; ++i) {
857 if (result !=
nullptr && result != state) {
858 result->cache_unref();
863 state->_composition_cache.
clear();
866 for (i = 0; i < cache_size; ++i) {
868 if (result !=
nullptr && result != state) {
869 result->cache_unref();
874 state->_invert_composition_cache.
clear();
883 return orig_size - new_size;
898 if (_states ==
nullptr || !garbage_collect_states) {
904 PStatTimer timer(_garbage_collect_pcollector);
908 size_t size = orig_size;
909 size_t num_this_pass = std::max(0,
int(size * garbage_collect_states_rate));
910 if (num_this_pass <= 0) {
914 bool break_and_uniquify = (auto_break_cycles && uniquify_transforms);
916 size_t si = _garbage_index;
921 num_this_pass = std::min(num_this_pass, size);
922 size_t stop_at_element = (si + num_this_pass) % size;
926 if (break_and_uniquify) {
933 state->detect_and_break_cycles();
945 state->release_new();
946 state->remove_cache_pointers();
947 state->cache_unref_only();
955 if (stop_at_element > 0) {
960 si = (si + 1) % size;
961 }
while (si != stop_at_element);
974 return (
int)orig_size - (int)size + num_attribs;
986 for (
size_t si = 0; si < size; ++si) {
988 state->_mungers.
clear();
989 state->_munged_states.
clear();
990 state->_last_mi = -1;
1009 if (_states ==
nullptr) {
1015 VisitedStates visited;
1019 for (
size_t si = 0; si < size; ++si) {
1022 bool inserted = visited.insert(state).second;
1024 ++_last_cycle_detect;
1025 if (r_detect_cycles(state, state, 1, _last_cycle_detect, &cycle_desc)) {
1027 CompositionCycleDesc::reverse_iterator csi;
1029 out <<
"\nCycle detected of length " << cycle_desc.size() + 1 <<
":\n"
1030 <<
"state " << (
void *)state <<
":" << state->
get_ref_count()
1032 state->write(out, 2);
1033 for (csi = cycle_desc.rbegin(); csi != cycle_desc.rend(); ++csi) {
1034 const CompositionCycleDescEntry &entry = (*csi);
1035 if (entry._inverted) {
1036 out <<
"invert composed with ";
1038 out <<
"composed with ";
1040 out << (
const void *)entry._obj <<
":" << entry._obj->get_ref_count()
1041 <<
" " << *entry._obj <<
"\n"
1042 <<
"produces " << (
const void *)entry._result <<
":"
1043 << entry._result->get_ref_count() <<
" =\n";
1044 entry._result->write(out, 2);
1045 visited.insert(entry._result);
1050 ++_last_cycle_detect;
1051 if (r_detect_reverse_cycles(state, state, 1, _last_cycle_detect, &cycle_desc)) {
1053 CompositionCycleDesc::iterator csi;
1055 out <<
"\nReverse cycle detected of length " << cycle_desc.size() + 1 <<
":\n"
1057 for (csi = cycle_desc.begin(); csi != cycle_desc.end(); ++csi) {
1058 const CompositionCycleDescEntry &entry = (*csi);
1059 out << (
const void *)entry._result <<
":"
1060 << entry._result->get_ref_count() <<
" =\n";
1061 entry._result->write(out, 2);
1062 out << (
const void *)entry._obj <<
":"
1063 << entry._obj->get_ref_count() <<
" =\n";
1064 entry._obj->write(out, 2);
1065 visited.insert(entry._result);
1067 out << (
void *)state <<
":"
1069 state->write(out, 2);
1086 if (_states ==
nullptr) {
1087 out <<
"0 states:\n";
1093 out << size <<
" states:\n";
1094 for (
size_t si = 0; si < size; ++si) {
1096 state->write(out, 2);
1108 if (_states ==
nullptr) {
1112 PStatTimer timer(_state_validate_pcollector);
1121 <<
"RenderState::_states cache is invalid!\n";
1127 nassertr(si < size,
false);
1128 nassertr(_states->
get_key(si)->get_ref_count() >= 0,
false);
1131 while (snext < size) {
1132 nassertr(_states->
get_key(snext)->get_ref_count() >= 0,
false);
1137 if ((ci < 0) != (c > 0) ||
1138 (ci > 0) != (c < 0) ||
1139 (ci == 0) != (c == 0)) {
1141 <<
"RenderState::compare_to() not defined properly!\n";
1142 pgraph_cat.error(
false)
1143 <<
"(a, b): " << c <<
"\n";
1144 pgraph_cat.error(
false)
1145 <<
"(b, a): " << ci <<
"\n";
1146 ssi->write(pgraph_cat.error(
false), 2);
1147 ssnext->write(pgraph_cat.error(
false), 2);
1168 if (get_attrib(render_mode)) {
1171 if (get_attrib(tex_gen)) {
1174 if (get_attrib(tex_matrix)) {
1178 return geom_rendering;
1197 validate_filled_slots()
const {
1201 int max_slots = reg->get_max_slots();
1202 for (
int slot = 1; slot < max_slots; ++slot) {
1203 const Attribute &attribute = _attributes[slot];
1204 if (attribute._attrib !=
nullptr) {
1209 return (mask == _filled_slots);
1219 SlotMask mask = _filled_slots;
1222 const Attribute &attrib = _attributes[slot];
1223 nassertv(attrib._attrib !=
nullptr);
1227 mask.clear_bit(slot);
1228 slot = mask.get_lowest_on_bit();
1231 _flags |= F_hash_known;
1243 nassertr(state !=
nullptr, state);
1248 if (state->_attributes[0]._attrib !=
nullptr) {
1249 const RenderAttrib *attrib = state->_attributes[0]._attrib;
1250 if (attrib->get_type() == TypeHandle::none()) {
1253 <<
"Uninitialized RenderAttrib type: " << attrib->get_type()
1258 if (already_reported.insert(attrib->get_type()).second) {
1260 << attrib->get_type() <<
" did not initialize its slot number.\n";
1265 state->_attributes[0]._attrib =
nullptr;
1269 nassertr(state->validate_filled_slots(), state);
1272 if (!uniquify_states && !state->
is_empty()) {
1276 return return_unique(state);
1289 nassertr(state !=
nullptr,
nullptr);
1296 if (paranoid_const) {
1303 if (state->_saved_entry != -1) {
1311 if (!uniquify_attribs && !state->
is_empty()) {
1312 SlotMask mask = state->_filled_slots;
1315 Attribute &attrib = state->_attributes[slot];
1316 nassertd(attrib._attrib !=
nullptr) continue;
1317 attrib._attrib = attrib._attrib->get_unique();
1318 mask.clear_bit(slot);
1323 int si = _states->find(state);
1328 if (state->get_ref_count() == 0) {
1335 if (garbage_collect_states) {
1341 si = _states->
store(state,
nullptr);
1344 state->_saved_entry = si;
1358 SlotMask mask = _filled_slots | other->_filled_slots;
1359 new_state->_filled_slots = mask;
1363 const Attribute &a = _attributes[slot];
1364 const Attribute &b = other->_attributes[slot];
1365 Attribute &result = new_state->_attributes[slot];
1367 if (a._attrib ==
nullptr) {
1368 nassertr(b._attrib !=
nullptr,
this);
1372 }
else if (b._attrib ==
nullptr) {
1376 }
else if (b._override < a._override) {
1380 }
else if (a._override < b._override &&
1381 a._attrib->lower_attrib_can_override()) {
1393 result.set(a._attrib->compose(b._attrib), b._override);
1396 mask.clear_bit(slot);
1397 slot = mask.get_lowest_on_bit();
1400 return return_new(new_state);
1407 do_invert_compose(
const RenderState *other)
const {
1412 SlotMask mask = _filled_slots | other->_filled_slots;
1413 new_state->_filled_slots = mask;
1417 const Attribute &a = _attributes[slot];
1418 const Attribute &b = other->_attributes[slot];
1419 Attribute &result = new_state->_attributes[slot];
1421 if (a._attrib ==
nullptr) {
1422 nassertr(b._attrib !=
nullptr,
this);
1426 }
else if (b._attrib ==
nullptr) {
1433 result.set(a._attrib->invert_compose(b._attrib), 0);
1436 mask.clear_bit(slot);
1437 slot = mask.get_lowest_on_bit();
1439 return return_new(new_state);
1447 detect_and_break_cycles() {
1448 PStatTimer timer(_state_break_cycles_pcollector);
1450 ++_last_cycle_detect;
1451 if (r_detect_cycles(
this,
this, 1, _last_cycle_detect,
nullptr)) {
1454 if (pgraph_cat.is_debug()) {
1456 <<
"Breaking cycle involving " << (*this) <<
"\n";
1461 ++_last_cycle_detect;
1462 if (r_detect_reverse_cycles(
this,
this, 1, _last_cycle_detect,
nullptr)) {
1463 if (pgraph_cat.is_debug()) {
1465 <<
"Breaking cycle involving " << (*this) <<
"\n";
1485 if (current_state->_cycle_detect == this_seq) {
1491 return (current_state == start_state && length > 2);
1493 ((
RenderState *)current_state)->_cycle_detect = this_seq;
1496 size_t cache_size = current_state->_composition_cache.
get_num_entries();
1497 for (i = 0; i < cache_size; ++i) {
1499 if (result !=
nullptr) {
1500 if (r_detect_cycles(start_state, result, length + 1,
1501 this_seq, cycle_desc)) {
1503 if (cycle_desc !=
nullptr) {
1505 CompositionCycleDescEntry entry(other, result,
false);
1506 cycle_desc->push_back(entry);
1513 cache_size = current_state->_invert_composition_cache.
get_num_entries();
1514 for (i = 0; i < cache_size; ++i) {
1516 if (result !=
nullptr) {
1517 if (r_detect_cycles(start_state, result, length + 1,
1518 this_seq, cycle_desc)) {
1520 if (cycle_desc !=
nullptr) {
1522 CompositionCycleDescEntry entry(other, result,
true);
1523 cycle_desc->push_back(entry);
1540 r_detect_reverse_cycles(
const RenderState *start_state,
1544 if (current_state->_cycle_detect == this_seq) {
1550 return (current_state == start_state && length > 2);
1552 ((
RenderState *)current_state)->_cycle_detect = this_seq;
1555 size_t cache_size = current_state->_composition_cache.
get_num_entries();
1556 for (i = 0; i < cache_size; ++i) {
1558 if (other != current_state) {
1559 int oi = other->_composition_cache.
find(current_state);
1560 nassertr(oi != -1,
false);
1563 if (result !=
nullptr) {
1564 if (r_detect_reverse_cycles(start_state, result, length + 1,
1565 this_seq, cycle_desc)) {
1567 if (cycle_desc !=
nullptr) {
1569 CompositionCycleDescEntry entry(other, result,
false);
1570 cycle_desc->push_back(entry);
1578 cache_size = current_state->_invert_composition_cache.
get_num_entries();
1579 for (i = 0; i < cache_size; ++i) {
1581 if (other != current_state) {
1582 int oi = other->_invert_composition_cache.
find(current_state);
1583 nassertr(oi != -1,
false);
1586 if (result !=
nullptr) {
1587 if (r_detect_reverse_cycles(start_state, result, length + 1,
1588 this_seq, cycle_desc)) {
1590 if (cycle_desc !=
nullptr) {
1592 CompositionCycleDescEntry entry(other, result,
false);
1593 cycle_desc->push_back(entry);
1615 if (_saved_entry != -1) {
1617 nassertv_always(_states->
remove(
this));
1629 remove_cache_pointers() {
1647 if (_composition_cache.
is_empty() && _invert_composition_cache.
is_empty()) {
1656 while (!_composition_cache.
is_empty()) {
1667 Composition comp = _composition_cache.
get_data(i);
1676 if (other !=
this) {
1677 int oi = other->_composition_cache.
find(
this);
1683 Composition ocomp = other->_composition_cache.
get_data(oi);
1692 if (ocomp._result !=
nullptr && ocomp._result != other) {
1700 if (comp._result !=
nullptr && comp._result !=
this) {
1707 while (!_invert_composition_cache.
is_empty()) {
1709 nassertv(other !=
this);
1710 Composition comp = _invert_composition_cache.
get_data(i);
1714 if (other !=
this) {
1715 int oi = other->_invert_composition_cache.
find(
this);
1717 Composition ocomp = other->_invert_composition_cache.
get_data(oi);
1721 if (ocomp._result !=
nullptr && ocomp._result != other) {
1726 if (comp._result !=
nullptr && comp._result !=
this) {
1736 determine_bin_index() {
1738 if ((_flags & F_checked_bin_index) != 0) {
1743 std::string bin_name;
1747 if (get_attrib(bin)) {
1752 if (bin_name.empty()) {
1755 bin_name =
"opaque";
1758 if (get_attrib(transparency)) {
1759 switch (transparency->
get_mode()) {
1760 case TransparencyAttrib::M_alpha:
1761 case TransparencyAttrib::M_premultiplied_alpha:
1762 case TransparencyAttrib::M_dual:
1764 bin_name =
"transparent";
1774 _bin_index = bin_manager->
find_bin(bin_name);
1775 if (_bin_index == -1) {
1776 pgraph_cat.warning()
1777 <<
"No bin named " << bin_name <<
"; creating default bin.\n";
1778 _bin_index = bin_manager->
add_bin(bin_name, CullBinManager::BT_unsorted, 0);
1780 _flags |= F_checked_bin_index;
1787 determine_cull_callback() {
1789 if ((_flags & F_checked_cull_callback) != 0) {
1794 SlotMask mask = _filled_slots;
1797 const Attribute &attrib = _attributes[slot];
1798 nassertv(attrib._attrib !=
nullptr);
1799 if (attrib._attrib->has_cull_callback()) {
1800 _flags |= F_has_cull_callback;
1804 mask.clear_bit(slot);
1805 slot = mask.get_lowest_on_bit();
1808 _flags |= F_checked_cull_callback;
1818 for (
int slot = 1; slot < num_slots; ++slot) {
1830 update_pstats(
int old_referenced_bits,
int new_referenced_bits) {
1832 if ((old_referenced_bits & R_node) != 0) {
1833 _node_counter.sub_level(1);
1834 }
else if ((old_referenced_bits & R_cache) != 0) {
1835 _cache_counter.sub_level(1);
1837 if ((new_referenced_bits & R_node) != 0) {
1838 _node_counter.add_level(1);
1839 }
else if ((new_referenced_bits & R_cache) != 0) {
1840 _cache_counter.add_level(1);
1860 _states_lock =
new LightReMutex(
"RenderState::_states_lock");
1861 _cache_stats.
init();
1868 state->_saved_entry = _states->
store(state,
nullptr);
1869 _empty_state = state;
1889 nassertv(num_attribs == (
int)(uint16_t)num_attribs);
1897 const Attribute &attrib = _attributes[slot];
1898 nassertv(attrib._attrib !=
nullptr);
1915 int num_attribs = 0;
1918 for (
size_t i = 0; i < (*_read_overrides).size(); ++i) {
1919 int override = (*_read_overrides)[i];
1922 if (attrib !=
nullptr) {
1923 int slot = attrib->get_slot();
1924 if (slot > 0 && slot < reg->get_max_slots()) {
1925 _attributes[slot].set(attrib,
override);
1932 delete _read_overrides;
1933 _read_overrides =
nullptr;
1956 if (pointer == state) {
1996 state->fillin(scan, manager);
2011 _read_overrides =
new vector_int;
2012 (*_read_overrides).reserve(num_attribs);
2014 for (
int i = 0; i < num_attribs; ++i) {
2017 (*_read_overrides).push_back(
override);