Răsfoiți Sursa

gobj: improve performance of GeomPrimitive::make_nonindexed()

It now no longer has to create two GeomVertexArrayDataHandle objects for every vertex it visits.
rdb 7 ani în urmă
părinte
comite
301957c591

+ 20 - 9
panda/src/gobj/geomPrimitive.cxx

@@ -538,15 +538,26 @@ offset_vertices(int offset, int begin_row, int end_row) {
 void GeomPrimitive::
 make_nonindexed(GeomVertexData *dest, const GeomVertexData *source) {
   Thread *current_thread = Thread::get_current_thread();
-  int num_vertices = get_num_vertices();
-  int dest_start = dest->get_num_rows();
-  int strip_cut_index = get_strip_cut_index();
-
-  dest->set_num_rows(dest_start + num_vertices);
-  for (int i = 0; i < num_vertices; ++i) {
-    int v = get_vertex(i);
-    nassertd(v != strip_cut_index) continue;
-    dest->copy_row_from(dest_start + i, source, v, current_thread);
+
+  int num_vertices, dest_start;
+  {
+    GeomPrimitivePipelineReader reader(this, current_thread);
+    num_vertices = reader.get_num_vertices();
+    int strip_cut_index = reader.get_strip_cut_index();
+
+    GeomVertexDataPipelineWriter data_writer(dest, false, current_thread);
+    data_writer.check_array_writers();
+    dest_start = data_writer.get_num_rows();
+    data_writer.set_num_rows(dest_start + num_vertices);
+
+    GeomVertexDataPipelineReader data_reader(source, current_thread);
+    data_reader.check_array_readers();
+
+    for (int i = 0; i < num_vertices; ++i) {
+      int v = reader.get_vertex(i);
+      nassertd(v != strip_cut_index) continue;
+      data_writer.copy_row_from(dest_start + i, data_reader, v);
+    }
   }
 
   set_nonindexed_vertices(dest_start, num_vertices);

+ 44 - 24
panda/src/gobj/geomVertexData.cxx

@@ -686,32 +686,13 @@ copy_from(const GeomVertexData *source, bool keep_data_objects,
 void GeomVertexData::
 copy_row_from(int dest_row, const GeomVertexData *source,
               int source_row, Thread *current_thread) {
-  const GeomVertexFormat *source_format = source->get_format();
-  const GeomVertexFormat *dest_format = get_format();
-  nassertv(source_format == dest_format);
-  nassertv(source_row >= 0 && source_row < source->get_num_rows());
-
-  if (dest_row >= get_num_rows()) {
-    // Implicitly add enough rows to get to the indicated row.
-    set_num_rows(dest_row + 1);
-  }
-
-  int num_arrays = source_format->get_num_arrays();
 
-  for (int i = 0; i < num_arrays; ++i) {
-    PT(GeomVertexArrayDataHandle) dest_handle = modify_array_handle(i);
-    unsigned char *dest_array_data = dest_handle->get_write_pointer();
-
-    CPT(GeomVertexArrayDataHandle) source_array_handle = source->get_array_handle(i);
-    const unsigned char *source_array_data = source_array_handle->get_read_pointer(true);
+  GeomVertexDataPipelineReader reader(source, current_thread);
+  reader.check_array_readers();
 
-    const GeomVertexArrayFormat *array_format = source_format->get_array(i);
-    int stride = array_format->get_stride();
-
-    memcpy(dest_array_data + stride * dest_row,
-           source_array_data + stride * source_row,
-           stride);
-  }
+  GeomVertexDataPipelineWriter writer(this, true, current_thread);
+  writer.check_array_writers();
+  writer.copy_row_from(dest_row, reader, source_row);
 }
 
 /**
@@ -2601,6 +2582,45 @@ set_array(size_t i, const GeomVertexArrayData *array) {
   }
 }
 
+/**
+ * Copies a single row of the data from the other array into the indicated row
+ * of this array.  In this case, the source format must exactly match the
+ * destination format.
+ *
+ * Don't call this in a downstream thread unless you don't mind it blowing
+ * away other changes you might have recently made in an upstream thread.
+ */
+void GeomVertexDataPipelineWriter::
+copy_row_from(int dest_row, const GeomVertexDataPipelineReader &source,
+              int source_row) {
+  const GeomVertexFormat *source_format = source.get_format();
+  const GeomVertexFormat *dest_format = get_format();
+  nassertv(source_format == dest_format);
+  nassertv(source_row >= 0 && source_row < source.get_num_rows());
+  nassertv(_got_array_writers);
+
+  if (dest_row >= get_num_rows()) {
+    // Implicitly add enough rows to get to the indicated row.
+    set_num_rows(dest_row + 1);
+  }
+
+  size_t num_arrays = source_format->get_num_arrays();
+  for (size_t i = 0; i < num_arrays; ++i) {
+    GeomVertexArrayDataHandle *dest_handle = get_array_writer(i);
+    unsigned char *dest_array_data = dest_handle->get_write_pointer();
+
+    const GeomVertexArrayDataHandle *source_array_handle = source.get_array_reader(i);
+    const unsigned char *source_array_data = source_array_handle->get_read_pointer(true);
+
+    const GeomVertexArrayFormat *array_format = source_format->get_array(i);
+    int stride = array_format->get_stride();
+
+    memcpy(dest_array_data + stride * dest_row,
+           source_array_data + stride * source_row,
+           stride);
+  }
+}
+
 /**
  *
  */

+ 3 - 0
panda/src/gobj/geomVertexData.h

@@ -526,6 +526,9 @@ public:
   bool unclean_set_num_rows(int n);
   bool reserve_num_rows(int n);
 
+  void copy_row_from(int dest_row, const GeomVertexDataPipelineReader &source,
+                     int source_row);
+
 private:
   void make_array_writers();
   void delete_array_writers();