gobj: try to fix some deadlocks modifying geometry while rendering

The correct locking order should be: the Geom's GeomVertexArrayData first, *then* the GeomPrimitive.
This commit is contained in:
rdb 2018-08-03 20:45:29 +02:00
parent c959d274be
commit 668a093c26
8 changed files with 76 additions and 28 deletions

View File

@ -96,9 +96,10 @@ draw(bool force, Thread *current_thread) {
nassertd(object->_geom != nullptr) continue; nassertd(object->_geom != nullptr) continue;
_gsg->set_state_and_transform(object->_state, object->_internal_transform); _gsg->set_state_and_transform(object->_state, object->_internal_transform);
data_reader.set_object(object->_munged_data);
GeomPipelineReader geom_reader(object->_geom, current_thread);
GeomVertexDataPipelineReader data_reader(object->_munged_data, current_thread);
data_reader.check_array_readers(); data_reader.check_array_readers();
geom_reader.set_object(object->_geom);
geom_reader.draw(_gsg, &data_reader, force); geom_reader.draw(_gsg, &data_reader, force);
} else { } else {
// It has a callback associated. // It has a callback associated.

View File

@ -82,9 +82,10 @@ draw(bool force, Thread *current_thread) {
nassertd(object->_geom != nullptr) continue; nassertd(object->_geom != nullptr) continue;
_gsg->set_state_and_transform(object->_state, object->_internal_transform); _gsg->set_state_and_transform(object->_state, object->_internal_transform);
data_reader.set_object(object->_munged_data);
GeomPipelineReader geom_reader(object->_geom, current_thread);
GeomVertexDataPipelineReader data_reader(object->_munged_data, current_thread);
data_reader.check_array_readers(); data_reader.check_array_readers();
geom_reader.set_object(object->_geom);
geom_reader.draw(_gsg, &data_reader, force); geom_reader.draw(_gsg, &data_reader, force);
} else { } else {
// It has a callback associated. // It has a callback associated.

View File

@ -96,9 +96,10 @@ draw(bool force, Thread *current_thread) {
nassertd(object->_geom != nullptr) continue; nassertd(object->_geom != nullptr) continue;
_gsg->set_state_and_transform(object->_state, object->_internal_transform); _gsg->set_state_and_transform(object->_state, object->_internal_transform);
data_reader.set_object(object->_munged_data);
GeomPipelineReader geom_reader(object->_geom, current_thread);
GeomVertexDataPipelineReader data_reader(object->_munged_data, current_thread);
data_reader.check_array_readers(); data_reader.check_array_readers();
geom_reader.set_object(object->_geom);
geom_reader.draw(_gsg, &data_reader, force); geom_reader.draw(_gsg, &data_reader, force);
} else { } else {
// It has a callback associated. // It has a callback associated.

View File

@ -81,9 +81,10 @@ draw(bool force, Thread *current_thread) {
nassertd(object->_geom != nullptr) continue; nassertd(object->_geom != nullptr) continue;
_gsg->set_state_and_transform(object->_state, object->_internal_transform); _gsg->set_state_and_transform(object->_state, object->_internal_transform);
data_reader.set_object(object->_munged_data);
GeomPipelineReader geom_reader(object->_geom, current_thread);
GeomVertexDataPipelineReader data_reader(object->_munged_data, current_thread);
data_reader.check_array_readers(); data_reader.check_array_readers();
geom_reader.set_object(object->_geom);
geom_reader.draw(_gsg, &data_reader, force); geom_reader.draw(_gsg, &data_reader, force);
} else { } else {
// It has a callback associated. // It has a callback associated.

View File

@ -55,9 +55,6 @@ void CullBinUnsorted::
draw(bool force, Thread *current_thread) { draw(bool force, Thread *current_thread) {
PStatTimer timer(_draw_this_pcollector, current_thread); PStatTimer timer(_draw_this_pcollector, current_thread);
GeomPipelineReader geom_reader(current_thread);
GeomVertexDataPipelineReader data_reader(current_thread);
Objects::iterator oi; Objects::iterator oi;
for (oi = _objects.begin(); oi != _objects.end(); ++oi) { for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
CullableObject *object = (*oi); CullableObject *object = (*oi);
@ -66,9 +63,10 @@ draw(bool force, Thread *current_thread) {
nassertd(object->_geom != nullptr) continue; nassertd(object->_geom != nullptr) continue;
_gsg->set_state_and_transform(object->_state, object->_internal_transform); _gsg->set_state_and_transform(object->_state, object->_internal_transform);
data_reader.set_object(object->_munged_data);
GeomPipelineReader geom_reader(object->_geom, current_thread);
GeomVertexDataPipelineReader data_reader(object->_munged_data, current_thread);
data_reader.check_array_readers(); data_reader.check_array_readers();
geom_reader.set_object(object->_geom);
geom_reader.draw(_gsg, &data_reader, force); geom_reader.draw(_gsg, &data_reader, force);
} else { } else {
// It has a callback associated. // It has a callback associated.

View File

@ -195,6 +195,9 @@ offset_vertices(const GeomVertexData *data, int offset) {
cdata->_data = (GeomVertexData *)data; cdata->_data = (GeomVertexData *)data;
#ifndef NDEBUG #ifndef NDEBUG
GeomVertexDataPipelineReader data_reader(data, current_thread);
data_reader.check_array_readers();
bool all_is_valid = true; bool all_is_valid = true;
#endif #endif
Primitives::iterator pi; Primitives::iterator pi;
@ -203,7 +206,7 @@ offset_vertices(const GeomVertexData *data, int offset) {
prim->offset_vertices(offset); prim->offset_vertices(offset);
#ifndef NDEBUG #ifndef NDEBUG
if (!prim->check_valid(data)) { if (!prim->check_valid(&data_reader)) {
gobj_cat.warning() gobj_cat.warning()
<< *prim << " is invalid for " << *data << ":\n"; << *prim << " is invalid for " << *data << ":\n";
prim->write(gobj_cat.warning(false), 4); prim->write(gobj_cat.warning(false), 4);
@ -423,6 +426,9 @@ decompose_in_place() {
CDWriter cdata(_cycler, true, current_thread); CDWriter cdata(_cycler, true, current_thread);
#ifndef NDEBUG #ifndef NDEBUG
GeomVertexDataPipelineReader data_reader(cdata->_data.get_read_pointer(current_thread), current_thread);
data_reader.check_array_readers();
bool all_is_valid = true; bool all_is_valid = true;
#endif #endif
Primitives::iterator pi; Primitives::iterator pi;
@ -431,7 +437,7 @@ decompose_in_place() {
(*pi) = (GeomPrimitive *)new_prim.p(); (*pi) = (GeomPrimitive *)new_prim.p();
#ifndef NDEBUG #ifndef NDEBUG
if (!new_prim->check_valid(cdata->_data.get_read_pointer(current_thread))) { if (!new_prim->check_valid(&data_reader)) {
all_is_valid = false; all_is_valid = false;
} }
#endif #endif
@ -457,6 +463,9 @@ doubleside_in_place() {
CDWriter cdata(_cycler, true, current_thread); CDWriter cdata(_cycler, true, current_thread);
#ifndef NDEBUG #ifndef NDEBUG
GeomVertexDataPipelineReader data_reader(cdata->_data.get_read_pointer(current_thread), current_thread);
data_reader.check_array_readers();
bool all_is_valid = true; bool all_is_valid = true;
#endif #endif
Primitives::iterator pi; Primitives::iterator pi;
@ -465,7 +474,7 @@ doubleside_in_place() {
(*pi) = (GeomPrimitive *)new_prim.p(); (*pi) = (GeomPrimitive *)new_prim.p();
#ifndef NDEBUG #ifndef NDEBUG
if (!new_prim->check_valid(cdata->_data.get_read_pointer(current_thread))) { if (!new_prim->check_valid(&data_reader)) {
all_is_valid = false; all_is_valid = false;
} }
#endif #endif
@ -491,6 +500,9 @@ reverse_in_place() {
CDWriter cdata(_cycler, true, current_thread); CDWriter cdata(_cycler, true, current_thread);
#ifndef NDEBUG #ifndef NDEBUG
GeomVertexDataPipelineReader data_reader(cdata->_data.get_read_pointer(current_thread), current_thread);
data_reader.check_array_readers();
bool all_is_valid = true; bool all_is_valid = true;
#endif #endif
Primitives::iterator pi; Primitives::iterator pi;
@ -499,7 +511,7 @@ reverse_in_place() {
(*pi) = (GeomPrimitive *)new_prim.p(); (*pi) = (GeomPrimitive *)new_prim.p();
#ifndef NDEBUG #ifndef NDEBUG
if (!new_prim->check_valid(cdata->_data.get_read_pointer(current_thread))) { if (!new_prim->check_valid(&data_reader)) {
all_is_valid = false; all_is_valid = false;
} }
#endif #endif
@ -525,6 +537,9 @@ rotate_in_place() {
CDWriter cdata(_cycler, true, current_thread); CDWriter cdata(_cycler, true, current_thread);
#ifndef NDEBUG #ifndef NDEBUG
GeomVertexDataPipelineReader data_reader(cdata->_data.get_read_pointer(current_thread), current_thread);
data_reader.check_array_readers();
bool all_is_valid = true; bool all_is_valid = true;
#endif #endif
Primitives::iterator pi; Primitives::iterator pi;
@ -533,7 +548,7 @@ rotate_in_place() {
(*pi) = (GeomPrimitive *)new_prim.p(); (*pi) = (GeomPrimitive *)new_prim.p();
#ifndef NDEBUG #ifndef NDEBUG
if (!new_prim->check_valid(cdata->_data.get_read_pointer(current_thread))) { if (!new_prim->check_valid(&data_reader)) {
all_is_valid = false; all_is_valid = false;
} }
#endif #endif
@ -640,6 +655,9 @@ unify_in_place(int max_indices, bool preserve_order) {
// primitives.) // primitives.)
nassertv(false); nassertv(false);
} }
GeomVertexDataPipelineReader data_reader(cdata->_data.get_read_pointer(current_thread), current_thread);
data_reader.check_array_readers();
#endif #endif
// Finally, iterate through the remaining primitives, and copy them to the // Finally, iterate through the remaining primitives, and copy them to the
@ -649,7 +667,7 @@ unify_in_place(int max_indices, bool preserve_order) {
for (npi = new_prims.begin(); npi != new_prims.end(); ++npi) { for (npi = new_prims.begin(); npi != new_prims.end(); ++npi) {
GeomPrimitive *prim = (*npi).second; GeomPrimitive *prim = (*npi).second;
nassertv(prim->check_valid(cdata->_data.get_read_pointer(current_thread))); nassertv(prim->check_valid(&data_reader));
// Each new primitive, naturally, inherits the Geom's overall shade model. // Each new primitive, naturally, inherits the Geom's overall shade model.
prim->set_shade_model(cdata->_shade_model); prim->set_shade_model(cdata->_shade_model);
@ -748,6 +766,9 @@ make_lines_in_place() {
CDWriter cdata(_cycler, true, current_thread); CDWriter cdata(_cycler, true, current_thread);
#ifndef NDEBUG #ifndef NDEBUG
GeomVertexDataPipelineReader data_reader(cdata->_data.get_read_pointer(current_thread), current_thread);
data_reader.check_array_readers();
bool all_is_valid = true; bool all_is_valid = true;
#endif #endif
Primitives::iterator pi; Primitives::iterator pi;
@ -756,7 +777,7 @@ make_lines_in_place() {
(*pi) = (GeomPrimitive *)new_prim.p(); (*pi) = (GeomPrimitive *)new_prim.p();
#ifndef NDEBUG #ifndef NDEBUG
if (!new_prim->check_valid(cdata->_data.get_read_pointer(current_thread))) { if (!new_prim->check_valid(&data_reader)) {
all_is_valid = false; all_is_valid = false;
} }
#endif #endif
@ -782,6 +803,9 @@ make_points_in_place() {
CDWriter cdata(_cycler, true, current_thread); CDWriter cdata(_cycler, true, current_thread);
#ifndef NDEBUG #ifndef NDEBUG
GeomVertexDataPipelineReader data_reader(cdata->_data.get_read_pointer(current_thread), current_thread);
data_reader.check_array_readers();
bool all_is_valid = true; bool all_is_valid = true;
#endif #endif
Primitives::iterator pi; Primitives::iterator pi;
@ -790,7 +814,7 @@ make_points_in_place() {
(*pi) = (GeomPrimitive *)new_prim.p(); (*pi) = (GeomPrimitive *)new_prim.p();
#ifndef NDEBUG #ifndef NDEBUG
if (!new_prim->check_valid(cdata->_data.get_read_pointer(current_thread))) { if (!new_prim->check_valid(&data_reader)) {
all_is_valid = false; all_is_valid = false;
} }
#endif #endif
@ -816,6 +840,9 @@ make_patches_in_place() {
CDWriter cdata(_cycler, true, current_thread); CDWriter cdata(_cycler, true, current_thread);
#ifndef NDEBUG #ifndef NDEBUG
GeomVertexDataPipelineReader data_reader(cdata->_data.get_read_pointer(current_thread), current_thread);
data_reader.check_array_readers();
bool all_is_valid = true; bool all_is_valid = true;
#endif #endif
Primitives::iterator pi; Primitives::iterator pi;
@ -824,7 +851,7 @@ make_patches_in_place() {
(*pi) = (GeomPrimitive *)new_prim.p(); (*pi) = (GeomPrimitive *)new_prim.p();
#ifndef NDEBUG #ifndef NDEBUG
if (!new_prim->check_valid(cdata->_data.get_read_pointer(current_thread))) { if (!new_prim->check_valid(&data_reader)) {
all_is_valid = false; all_is_valid = false;
} }
#endif #endif
@ -850,6 +877,9 @@ make_adjacency_in_place() {
CDWriter cdata(_cycler, true, current_thread); CDWriter cdata(_cycler, true, current_thread);
#ifndef NDEBUG #ifndef NDEBUG
GeomVertexDataPipelineReader data_reader(cdata->_data.get_read_pointer(current_thread), current_thread);
data_reader.check_array_readers();
bool all_is_valid = true; bool all_is_valid = true;
#endif #endif
Primitives::iterator pi; Primitives::iterator pi;
@ -859,7 +889,7 @@ make_adjacency_in_place() {
(*pi) = (GeomPrimitive *)new_prim.p(); (*pi) = (GeomPrimitive *)new_prim.p();
#ifndef NDEBUG #ifndef NDEBUG
if (!new_prim->check_valid(cdata->_data.get_read_pointer(current_thread))) { if (!new_prim->check_valid(&data_reader)) {
all_is_valid = false; all_is_valid = false;
} }
#endif #endif
@ -1465,13 +1495,20 @@ clear_prepared(PreparedGraphicsObjects *prepared_objects) {
*/ */
bool Geom:: bool Geom::
check_will_be_valid(const GeomVertexData *vertex_data) const { check_will_be_valid(const GeomVertexData *vertex_data) const {
CDReader cdata(_cycler); Thread *current_thread = Thread::get_current_thread();
CDReader cdata(_cycler, current_thread);
GeomVertexDataPipelineReader data_reader(vertex_data, current_thread);
data_reader.check_array_readers();
Primitives::const_iterator pi; Primitives::const_iterator pi;
for (pi = cdata->_primitives.begin(); for (pi = cdata->_primitives.begin();
pi != cdata->_primitives.end(); pi != cdata->_primitives.end();
++pi) { ++pi) {
if (!(*pi).get_read_pointer()->check_valid(vertex_data)) { GeomPrimitivePipelineReader reader((*pi).get_read_pointer(), current_thread);
reader.check_minmax();
if (!reader.check_valid(&data_reader)) {
return false; return false;
} }
} }

View File

@ -223,11 +223,19 @@ get_modified() const {
INLINE bool GeomPrimitive:: INLINE bool GeomPrimitive::
check_valid(const GeomVertexData *vertex_data) const { check_valid(const GeomVertexData *vertex_data) const {
Thread *current_thread = Thread::get_current_thread(); Thread *current_thread = Thread::get_current_thread();
GeomPrimitivePipelineReader reader(this, current_thread);
reader.check_minmax();
GeomVertexDataPipelineReader data_reader(vertex_data, current_thread); GeomVertexDataPipelineReader data_reader(vertex_data, current_thread);
data_reader.check_array_readers(); data_reader.check_array_readers();
return reader.check_valid(&data_reader); return check_valid(&data_reader);
}
/**
*
*/
INLINE bool GeomPrimitive::
check_valid(const GeomVertexDataPipelineReader *data_reader) const {
GeomPrimitivePipelineReader reader(this, data_reader->get_current_thread());
reader.check_minmax();
return reader.check_valid(data_reader);
} }
/** /**

View File

@ -146,6 +146,7 @@ PUBLISHED:
bool request_resident(Thread *current_thread = Thread::get_current_thread()) const; bool request_resident(Thread *current_thread = Thread::get_current_thread()) const;
INLINE bool check_valid(const GeomVertexData *vertex_data) const; INLINE bool check_valid(const GeomVertexData *vertex_data) const;
INLINE bool check_valid(const GeomVertexDataPipelineReader *data_reader) const;
virtual void output(std::ostream &out) const; virtual void output(std::ostream &out) const;
virtual void write(std::ostream &out, int indent_level) const; virtual void write(std::ostream &out, int indent_level) const;