gobj: improve performance of GeomPrimitive::make_nonindexed()

It now no longer has to create two GeomVertexArrayDataHandle objects for every vertex it visits.
This commit is contained in:
rdb 2018-12-04 12:36:03 +01:00
parent 8a0f438156
commit 301957c591
3 changed files with 66 additions and 32 deletions

View File

@ -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);

View File

@ -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);
}
GeomVertexDataPipelineReader reader(source, current_thread);
reader.check_array_readers();
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);
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);
}
}
/**
*
*/

View File

@ -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();