2019-07-14 16:49:44 +02:00
|
|
|
/*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2017 by Blender Foundation.
|
|
|
|
* All rights reserved.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** \file
|
|
|
|
* \ingroup draw
|
|
|
|
*
|
|
|
|
* \brief Extraction of Mesh data into VBO to feed to GPU.
|
|
|
|
*/
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
2021-06-08 16:35:33 +02:00
|
|
|
#include <optional>
|
|
|
|
|
2021-06-01 09:23:37 +02:00
|
|
|
#include "atomic_ops.h"
|
2020-07-10 04:38:28 +02:00
|
|
|
|
2021-06-01 09:23:37 +02:00
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
#include "DNA_scene_types.h"
|
2020-07-10 04:38:28 +02:00
|
|
|
|
2021-06-08 16:35:33 +02:00
|
|
|
#include "BLI_array.hh"
|
|
|
|
#include "BLI_math_bits.h"
|
2021-06-01 09:23:37 +02:00
|
|
|
#include "BLI_task.h"
|
2021-06-01 12:12:13 +02:00
|
|
|
#include "BLI_vector.hh"
|
2019-07-14 16:49:44 +02:00
|
|
|
|
2021-06-01 09:23:37 +02:00
|
|
|
#include "BKE_editmesh.h"
|
2021-05-31 17:11:01 +02:00
|
|
|
|
2021-06-01 09:23:37 +02:00
|
|
|
#include "GPU_capabilities.h"
|
2020-07-10 04:38:28 +02:00
|
|
|
|
2021-06-01 09:23:37 +02:00
|
|
|
#include "draw_cache_extract.h"
|
|
|
|
#include "draw_cache_inline.h"
|
2021-05-31 17:11:01 +02:00
|
|
|
|
2021-07-26 14:54:59 +02:00
|
|
|
#include "mesh_extractors/extract_mesh.h"
|
|
|
|
|
2021-06-01 09:23:37 +02:00
|
|
|
// #define DEBUG_TIME
|
2019-07-14 16:49:44 +02:00
|
|
|
|
2021-06-01 09:23:37 +02:00
|
|
|
#ifdef DEBUG_TIME
|
|
|
|
# include "PIL_time_utildefines.h"
|
|
|
|
#endif
|
2019-07-14 16:49:44 +02:00
|
|
|
|
2021-06-01 12:12:13 +02:00
|
|
|
namespace blender::draw {
|
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
/* ---------------------------------------------------------------------- */
|
2021-06-01 09:23:37 +02:00
|
|
|
/** \name Mesh Elements Extract Struct
|
2019-07-14 16:49:44 +02:00
|
|
|
* \{ */
|
2021-12-14 05:49:31 +01:00
|
|
|
|
2021-06-08 16:35:33 +02:00
|
|
|
using TaskId = int;
|
|
|
|
using TaskLen = int;
|
2019-07-14 16:49:44 +02:00
|
|
|
|
2021-06-01 12:59:15 +02:00
|
|
|
struct ExtractorRunData {
|
|
|
|
/* Extractor where this run data belongs to. */
|
2021-06-01 09:23:37 +02:00
|
|
|
const MeshExtract *extractor;
|
2021-06-01 12:59:15 +02:00
|
|
|
/* During iteration the VBO/IBO that is being build. */
|
|
|
|
void *buffer = nullptr;
|
2021-06-10 16:01:36 +02:00
|
|
|
uint32_t data_offset = 0;
|
2019-07-14 16:49:44 +02:00
|
|
|
|
2021-06-01 12:59:15 +02:00
|
|
|
ExtractorRunData(const MeshExtract *extractor) : extractor(extractor)
|
|
|
|
{
|
|
|
|
}
|
2021-06-07 13:34:30 +02:00
|
|
|
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("DRAW:ExtractorRunData")
|
|
|
|
#endif
|
2021-06-01 12:59:15 +02:00
|
|
|
};
|
2021-01-11 09:48:42 +01:00
|
|
|
|
2021-06-01 12:59:15 +02:00
|
|
|
class ExtractorRunDatas : public Vector<ExtractorRunData> {
|
|
|
|
public:
|
2021-07-16 21:18:54 +02:00
|
|
|
void filter_into(ExtractorRunDatas &result, eMRIterType iter_type, const bool is_mesh) const
|
2021-06-01 12:59:15 +02:00
|
|
|
{
|
|
|
|
for (const ExtractorRunData &data : *this) {
|
|
|
|
const MeshExtract *extractor = data.extractor;
|
2021-07-16 21:18:54 +02:00
|
|
|
if ((iter_type & MR_ITER_LOOPTRI) && *(&extractor->iter_looptri_bm + is_mesh)) {
|
2021-06-01 12:59:15 +02:00
|
|
|
result.append(data);
|
|
|
|
continue;
|
|
|
|
}
|
2021-07-16 21:18:54 +02:00
|
|
|
if ((iter_type & MR_ITER_POLY) && *(&extractor->iter_poly_bm + is_mesh)) {
|
2021-06-01 12:59:15 +02:00
|
|
|
result.append(data);
|
|
|
|
continue;
|
|
|
|
}
|
2021-07-16 21:18:54 +02:00
|
|
|
if ((iter_type & MR_ITER_LEDGE) && *(&extractor->iter_ledge_bm + is_mesh)) {
|
2021-06-01 12:59:15 +02:00
|
|
|
result.append(data);
|
|
|
|
continue;
|
|
|
|
}
|
2021-07-16 21:18:54 +02:00
|
|
|
if ((iter_type & MR_ITER_LVERT) && *(&extractor->iter_lvert_bm + is_mesh)) {
|
2021-06-01 12:59:15 +02:00
|
|
|
result.append(data);
|
|
|
|
continue;
|
|
|
|
}
|
2021-01-11 09:48:42 +01:00
|
|
|
}
|
2021-06-01 12:59:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void filter_threaded_extractors_into(ExtractorRunDatas &result)
|
|
|
|
{
|
|
|
|
for (const ExtractorRunData &data : *this) {
|
|
|
|
const MeshExtract *extractor = data.extractor;
|
|
|
|
if (extractor->use_threading) {
|
|
|
|
result.append(extractor);
|
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
}
|
2021-06-01 12:59:15 +02:00
|
|
|
}
|
|
|
|
|
2021-06-08 16:35:33 +02:00
|
|
|
eMRIterType iter_types() const
|
2021-06-01 12:59:15 +02:00
|
|
|
{
|
|
|
|
eMRIterType iter_type = static_cast<eMRIterType>(0);
|
|
|
|
|
|
|
|
for (const ExtractorRunData &data : *this) {
|
|
|
|
const MeshExtract *extractor = data.extractor;
|
|
|
|
iter_type |= mesh_extract_iter_type(extractor);
|
2020-06-30 16:13:39 +02:00
|
|
|
}
|
2021-06-01 12:59:15 +02:00
|
|
|
return iter_type;
|
2019-07-14 16:49:44 +02:00
|
|
|
}
|
|
|
|
|
2021-06-18 06:27:43 +02:00
|
|
|
uint iter_types_len() const
|
2021-06-08 16:35:33 +02:00
|
|
|
{
|
|
|
|
const eMRIterType iter_type = iter_types();
|
|
|
|
uint bits = static_cast<uint>(iter_type);
|
|
|
|
return count_bits_i(bits);
|
|
|
|
}
|
|
|
|
|
2021-06-01 12:59:15 +02:00
|
|
|
eMRDataType data_types()
|
|
|
|
{
|
|
|
|
eMRDataType data_type = static_cast<eMRDataType>(0);
|
|
|
|
for (const ExtractorRunData &data : *this) {
|
|
|
|
const MeshExtract *extractor = data.extractor;
|
|
|
|
data_type |= extractor->data_type;
|
2019-10-15 01:49:53 +02:00
|
|
|
}
|
2021-06-01 12:59:15 +02:00
|
|
|
return data_type;
|
2019-10-15 01:49:53 +02:00
|
|
|
}
|
2021-06-07 13:34:30 +02:00
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
size_t data_size_total()
|
|
|
|
{
|
|
|
|
size_t data_size = 0;
|
|
|
|
for (const ExtractorRunData &data : *this) {
|
|
|
|
const MeshExtract *extractor = data.extractor;
|
|
|
|
data_size += extractor->data_size;
|
|
|
|
}
|
|
|
|
return data_size;
|
|
|
|
}
|
|
|
|
|
2021-06-07 13:34:30 +02:00
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("DRAW:ExtractorRunDatas")
|
|
|
|
#endif
|
2021-06-01 12:59:15 +02:00
|
|
|
};
|
2019-10-15 01:49:53 +02:00
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
2021-05-31 17:11:01 +02:00
|
|
|
/* ---------------------------------------------------------------------- */
|
2021-06-10 16:01:36 +02:00
|
|
|
/** \name ExtractTaskData
|
|
|
|
* \{ */
|
2021-12-14 05:49:31 +01:00
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
struct ExtractTaskData {
|
|
|
|
const MeshRenderData *mr = nullptr;
|
|
|
|
MeshBatchCache *cache = nullptr;
|
|
|
|
ExtractorRunDatas *extractors = nullptr;
|
2021-08-23 17:33:12 +02:00
|
|
|
MeshBufferList *mbuflist = nullptr;
|
2021-06-10 16:01:36 +02:00
|
|
|
|
|
|
|
eMRIterType iter_type;
|
|
|
|
bool use_threading = false;
|
|
|
|
|
|
|
|
ExtractTaskData(const MeshRenderData *mr,
|
|
|
|
struct MeshBatchCache *cache,
|
|
|
|
ExtractorRunDatas *extractors,
|
2021-08-23 17:33:12 +02:00
|
|
|
MeshBufferList *mbuflist,
|
2021-06-10 16:01:36 +02:00
|
|
|
const bool use_threading)
|
2021-08-23 17:33:12 +02:00
|
|
|
: mr(mr),
|
|
|
|
cache(cache),
|
|
|
|
extractors(extractors),
|
|
|
|
mbuflist(mbuflist),
|
|
|
|
use_threading(use_threading)
|
2021-06-10 16:01:36 +02:00
|
|
|
{
|
|
|
|
iter_type = extractors->iter_types();
|
|
|
|
};
|
|
|
|
|
|
|
|
ExtractTaskData(const ExtractTaskData &src) = default;
|
|
|
|
|
|
|
|
~ExtractTaskData()
|
|
|
|
{
|
|
|
|
delete extractors;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("DRW:ExtractTaskData")
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
static void extract_task_data_free(void *data)
|
|
|
|
{
|
|
|
|
ExtractTaskData *task_data = static_cast<ExtractTaskData *>(data);
|
|
|
|
delete task_data;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/** \name Extract Init and Finish
|
2021-05-31 17:11:01 +02:00
|
|
|
* \{ */
|
|
|
|
|
|
|
|
BLI_INLINE void extract_init(const MeshRenderData *mr,
|
|
|
|
struct MeshBatchCache *cache,
|
2021-06-01 12:59:15 +02:00
|
|
|
ExtractorRunDatas &extractors,
|
2021-08-23 17:33:12 +02:00
|
|
|
MeshBufferList *mbuflist,
|
2021-06-10 16:01:36 +02:00
|
|
|
void *data_stack)
|
2021-05-31 17:11:01 +02:00
|
|
|
{
|
2021-06-10 16:01:36 +02:00
|
|
|
uint32_t data_offset = 0;
|
2021-06-01 12:59:15 +02:00
|
|
|
for (ExtractorRunData &run_data : extractors) {
|
2021-06-01 12:12:13 +02:00
|
|
|
const MeshExtract *extractor = run_data.extractor;
|
2021-08-23 17:33:12 +02:00
|
|
|
run_data.buffer = mesh_extract_buffer_get(extractor, mbuflist);
|
2021-06-10 16:01:36 +02:00
|
|
|
run_data.data_offset = data_offset;
|
|
|
|
extractor->init(mr, cache, run_data.buffer, POINTER_OFFSET(data_stack, data_offset));
|
|
|
|
data_offset += (uint32_t)extractor->data_size;
|
2021-05-31 17:11:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
BLI_INLINE void extract_finish(const MeshRenderData *mr,
|
|
|
|
struct MeshBatchCache *cache,
|
|
|
|
const ExtractorRunDatas &extractors,
|
|
|
|
void *data_stack)
|
2021-05-31 17:11:01 +02:00
|
|
|
{
|
2021-06-10 16:01:36 +02:00
|
|
|
for (const ExtractorRunData &run_data : extractors) {
|
|
|
|
const MeshExtract *extractor = run_data.extractor;
|
|
|
|
if (extractor->finish) {
|
|
|
|
extractor->finish(
|
|
|
|
mr, cache, run_data.buffer, POINTER_OFFSET(data_stack, run_data.data_offset));
|
2021-05-31 17:11:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/** \name Extract In Parallel Ranges
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
struct ExtractorIterData {
|
2021-06-01 12:59:15 +02:00
|
|
|
ExtractorRunDatas extractors;
|
2021-06-10 16:01:36 +02:00
|
|
|
const MeshRenderData *mr = nullptr;
|
|
|
|
const void *elems = nullptr;
|
|
|
|
const int *loose_elems = nullptr;
|
2021-05-31 17:11:01 +02:00
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("DRW:MeshRenderDataUpdateTaskData")
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
static void extract_task_reduce(const void *__restrict userdata,
|
|
|
|
void *__restrict chunk_to,
|
|
|
|
void *__restrict chunk_from)
|
|
|
|
{
|
|
|
|
const ExtractorIterData *data = static_cast<const ExtractorIterData *>(userdata);
|
|
|
|
for (const ExtractorRunData &run_data : data->extractors) {
|
|
|
|
const MeshExtract *extractor = run_data.extractor;
|
|
|
|
if (extractor->task_reduce) {
|
|
|
|
extractor->task_reduce(POINTER_OFFSET(chunk_to, run_data.data_offset),
|
|
|
|
POINTER_OFFSET(chunk_from, run_data.data_offset));
|
2021-05-31 17:11:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
static void extract_range_iter_looptri_bm(void *__restrict userdata,
|
|
|
|
const int iter,
|
|
|
|
const TaskParallelTLS *__restrict tls)
|
2021-05-31 17:11:01 +02:00
|
|
|
{
|
2021-06-10 16:01:36 +02:00
|
|
|
const ExtractorIterData *data = static_cast<ExtractorIterData *>(userdata);
|
|
|
|
void *extract_data = tls->userdata_chunk;
|
|
|
|
const MeshRenderData *mr = data->mr;
|
|
|
|
BMLoop **elt = ((BMLoop * (*)[3]) data->elems)[iter];
|
|
|
|
for (const ExtractorRunData &run_data : data->extractors) {
|
|
|
|
run_data.extractor->iter_looptri_bm(
|
|
|
|
mr, elt, iter, POINTER_OFFSET(extract_data, run_data.data_offset));
|
2021-05-31 17:11:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
static void extract_range_iter_looptri_mesh(void *__restrict userdata,
|
|
|
|
const int iter,
|
|
|
|
const TaskParallelTLS *__restrict tls)
|
2021-05-31 17:11:01 +02:00
|
|
|
{
|
2021-06-10 16:01:36 +02:00
|
|
|
void *extract_data = tls->userdata_chunk;
|
2021-05-31 17:11:01 +02:00
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
const ExtractorIterData *data = static_cast<ExtractorIterData *>(userdata);
|
|
|
|
const MeshRenderData *mr = data->mr;
|
|
|
|
const MLoopTri *mlt = &((const MLoopTri *)data->elems)[iter];
|
|
|
|
for (const ExtractorRunData &run_data : data->extractors) {
|
|
|
|
run_data.extractor->iter_looptri_mesh(
|
|
|
|
mr, mlt, iter, POINTER_OFFSET(extract_data, run_data.data_offset));
|
2021-05-31 17:11:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
static void extract_range_iter_poly_bm(void *__restrict userdata,
|
|
|
|
const int iter,
|
|
|
|
const TaskParallelTLS *__restrict tls)
|
2021-05-31 17:11:01 +02:00
|
|
|
{
|
2021-06-10 16:01:36 +02:00
|
|
|
void *extract_data = tls->userdata_chunk;
|
2021-05-31 17:11:01 +02:00
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
const ExtractorIterData *data = static_cast<ExtractorIterData *>(userdata);
|
|
|
|
const MeshRenderData *mr = data->mr;
|
|
|
|
const BMFace *f = ((const BMFace **)data->elems)[iter];
|
|
|
|
for (const ExtractorRunData &run_data : data->extractors) {
|
|
|
|
run_data.extractor->iter_poly_bm(
|
|
|
|
mr, f, iter, POINTER_OFFSET(extract_data, run_data.data_offset));
|
2021-05-31 17:11:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
static void extract_range_iter_poly_mesh(void *__restrict userdata,
|
|
|
|
const int iter,
|
|
|
|
const TaskParallelTLS *__restrict tls)
|
2021-05-31 17:11:01 +02:00
|
|
|
{
|
2021-06-10 16:01:36 +02:00
|
|
|
void *extract_data = tls->userdata_chunk;
|
2021-05-31 17:11:01 +02:00
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
const ExtractorIterData *data = static_cast<ExtractorIterData *>(userdata);
|
|
|
|
const MeshRenderData *mr = data->mr;
|
|
|
|
const MPoly *mp = &((const MPoly *)data->elems)[iter];
|
|
|
|
for (const ExtractorRunData &run_data : data->extractors) {
|
|
|
|
run_data.extractor->iter_poly_mesh(
|
|
|
|
mr, mp, iter, POINTER_OFFSET(extract_data, run_data.data_offset));
|
2021-05-31 17:11:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
static void extract_range_iter_ledge_bm(void *__restrict userdata,
|
|
|
|
const int iter,
|
|
|
|
const TaskParallelTLS *__restrict tls)
|
2021-05-31 17:11:01 +02:00
|
|
|
{
|
2021-06-10 16:01:36 +02:00
|
|
|
void *extract_data = tls->userdata_chunk;
|
2021-05-31 17:11:01 +02:00
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
const ExtractorIterData *data = static_cast<ExtractorIterData *>(userdata);
|
|
|
|
const MeshRenderData *mr = data->mr;
|
|
|
|
const int ledge_index = data->loose_elems[iter];
|
|
|
|
const BMEdge *eed = ((const BMEdge **)data->elems)[ledge_index];
|
|
|
|
for (const ExtractorRunData &run_data : data->extractors) {
|
|
|
|
run_data.extractor->iter_ledge_bm(
|
|
|
|
mr, eed, iter, POINTER_OFFSET(extract_data, run_data.data_offset));
|
2021-05-31 17:11:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
static void extract_range_iter_ledge_mesh(void *__restrict userdata,
|
|
|
|
const int iter,
|
|
|
|
const TaskParallelTLS *__restrict tls)
|
2021-05-31 17:11:01 +02:00
|
|
|
{
|
2021-06-10 16:01:36 +02:00
|
|
|
void *extract_data = tls->userdata_chunk;
|
2021-05-31 17:11:01 +02:00
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
const ExtractorIterData *data = static_cast<ExtractorIterData *>(userdata);
|
|
|
|
const MeshRenderData *mr = data->mr;
|
|
|
|
const int ledge_index = data->loose_elems[iter];
|
|
|
|
const MEdge *med = &((const MEdge *)data->elems)[ledge_index];
|
|
|
|
for (const ExtractorRunData &run_data : data->extractors) {
|
|
|
|
run_data.extractor->iter_ledge_mesh(
|
|
|
|
mr, med, iter, POINTER_OFFSET(extract_data, run_data.data_offset));
|
2021-05-31 17:11:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
static void extract_range_iter_lvert_bm(void *__restrict userdata,
|
|
|
|
const int iter,
|
|
|
|
const TaskParallelTLS *__restrict tls)
|
2021-05-31 17:11:01 +02:00
|
|
|
{
|
2021-06-10 16:01:36 +02:00
|
|
|
void *extract_data = tls->userdata_chunk;
|
|
|
|
|
|
|
|
const ExtractorIterData *data = static_cast<ExtractorIterData *>(userdata);
|
|
|
|
const MeshRenderData *mr = data->mr;
|
|
|
|
const int lvert_index = data->loose_elems[iter];
|
|
|
|
const BMVert *eve = ((const BMVert **)data->elems)[lvert_index];
|
|
|
|
for (const ExtractorRunData &run_data : data->extractors) {
|
|
|
|
run_data.extractor->iter_lvert_bm(
|
|
|
|
mr, eve, iter, POINTER_OFFSET(extract_data, run_data.data_offset));
|
2021-05-31 17:11:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
static void extract_range_iter_lvert_mesh(void *__restrict userdata,
|
|
|
|
const int iter,
|
|
|
|
const TaskParallelTLS *__restrict tls)
|
2021-06-08 16:35:33 +02:00
|
|
|
{
|
2021-06-10 16:01:36 +02:00
|
|
|
void *extract_data = tls->userdata_chunk;
|
|
|
|
|
|
|
|
const ExtractorIterData *data = static_cast<ExtractorIterData *>(userdata);
|
|
|
|
const MeshRenderData *mr = data->mr;
|
|
|
|
const int lvert_index = data->loose_elems[iter];
|
|
|
|
const MVert *mv = &((const MVert *)data->elems)[lvert_index];
|
|
|
|
for (const ExtractorRunData &run_data : data->extractors) {
|
|
|
|
run_data.extractor->iter_lvert_mesh(
|
|
|
|
mr, mv, iter, POINTER_OFFSET(extract_data, run_data.data_offset));
|
2021-06-08 16:35:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
BLI_INLINE void extract_task_range_run_iter(const MeshRenderData *mr,
|
|
|
|
ExtractorRunDatas *extractors,
|
|
|
|
const eMRIterType iter_type,
|
|
|
|
bool is_mesh,
|
|
|
|
TaskParallelSettings *settings)
|
2021-06-08 16:35:33 +02:00
|
|
|
{
|
2021-06-10 16:01:36 +02:00
|
|
|
ExtractorIterData range_data;
|
|
|
|
range_data.mr = mr;
|
|
|
|
|
|
|
|
TaskParallelRangeFunc func;
|
|
|
|
int stop;
|
|
|
|
switch (iter_type) {
|
|
|
|
case MR_ITER_LOOPTRI:
|
|
|
|
range_data.elems = is_mesh ? mr->mlooptri : (void *)mr->edit_bmesh->looptris;
|
|
|
|
func = is_mesh ? extract_range_iter_looptri_mesh : extract_range_iter_looptri_bm;
|
|
|
|
stop = mr->tri_len;
|
|
|
|
break;
|
|
|
|
case MR_ITER_POLY:
|
|
|
|
range_data.elems = is_mesh ? mr->mpoly : (void *)mr->bm->ftable;
|
|
|
|
func = is_mesh ? extract_range_iter_poly_mesh : extract_range_iter_poly_bm;
|
|
|
|
stop = mr->poly_len;
|
|
|
|
break;
|
|
|
|
case MR_ITER_LEDGE:
|
|
|
|
range_data.loose_elems = mr->ledges;
|
|
|
|
range_data.elems = is_mesh ? mr->medge : (void *)mr->bm->etable;
|
|
|
|
func = is_mesh ? extract_range_iter_ledge_mesh : extract_range_iter_ledge_bm;
|
|
|
|
stop = mr->edge_loose_len;
|
|
|
|
break;
|
|
|
|
case MR_ITER_LVERT:
|
|
|
|
range_data.loose_elems = mr->lverts;
|
|
|
|
range_data.elems = is_mesh ? mr->mvert : (void *)mr->bm->vtable;
|
|
|
|
func = is_mesh ? extract_range_iter_lvert_mesh : extract_range_iter_lvert_bm;
|
|
|
|
stop = mr->vert_loose_len;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
BLI_assert(false);
|
|
|
|
return;
|
2021-06-08 16:35:33 +02:00
|
|
|
}
|
2021-06-10 16:01:36 +02:00
|
|
|
|
2021-07-16 21:18:54 +02:00
|
|
|
extractors->filter_into(range_data.extractors, iter_type, is_mesh);
|
2021-06-10 16:01:36 +02:00
|
|
|
BLI_task_parallel_range(0, stop, &range_data, func, settings);
|
2021-06-08 16:35:33 +02:00
|
|
|
}
|
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
static void extract_task_range_run(void *__restrict taskdata)
|
2021-05-31 17:11:01 +02:00
|
|
|
{
|
2021-06-10 16:01:36 +02:00
|
|
|
ExtractTaskData *data = (ExtractTaskData *)taskdata;
|
|
|
|
const eMRIterType iter_type = data->iter_type;
|
|
|
|
const bool is_mesh = data->mr->extract_type != MR_EXTRACT_BMESH;
|
2021-06-08 16:35:33 +02:00
|
|
|
|
2021-06-10 16:13:01 +02:00
|
|
|
size_t userdata_chunk_size = data->extractors->data_size_total();
|
2021-06-18 13:25:36 +02:00
|
|
|
void *userdata_chunk = MEM_callocN(userdata_chunk_size, __func__);
|
2021-06-10 16:13:01 +02:00
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
TaskParallelSettings settings;
|
|
|
|
BLI_parallel_range_settings_defaults(&settings);
|
|
|
|
settings.use_threading = data->use_threading;
|
2021-06-10 16:13:01 +02:00
|
|
|
settings.userdata_chunk = userdata_chunk;
|
|
|
|
settings.userdata_chunk_size = userdata_chunk_size;
|
|
|
|
settings.func_reduce = extract_task_reduce;
|
2021-06-18 16:09:35 +02:00
|
|
|
settings.min_iter_per_thread = MIN_RANGE_LEN;
|
2021-06-10 16:01:36 +02:00
|
|
|
|
2021-08-23 17:33:12 +02:00
|
|
|
extract_init(data->mr, data->cache, *data->extractors, data->mbuflist, userdata_chunk);
|
2021-05-31 17:11:01 +02:00
|
|
|
|
|
|
|
if (iter_type & MR_ITER_LOOPTRI) {
|
2021-06-10 16:01:36 +02:00
|
|
|
extract_task_range_run_iter(data->mr, data->extractors, MR_ITER_LOOPTRI, is_mesh, &settings);
|
2021-05-31 17:11:01 +02:00
|
|
|
}
|
|
|
|
if (iter_type & MR_ITER_POLY) {
|
2021-06-10 16:01:36 +02:00
|
|
|
extract_task_range_run_iter(data->mr, data->extractors, MR_ITER_POLY, is_mesh, &settings);
|
2021-05-31 17:11:01 +02:00
|
|
|
}
|
|
|
|
if (iter_type & MR_ITER_LEDGE) {
|
2021-06-10 16:01:36 +02:00
|
|
|
extract_task_range_run_iter(data->mr, data->extractors, MR_ITER_LEDGE, is_mesh, &settings);
|
2021-05-31 17:11:01 +02:00
|
|
|
}
|
|
|
|
if (iter_type & MR_ITER_LVERT) {
|
2021-06-10 16:01:36 +02:00
|
|
|
extract_task_range_run_iter(data->mr, data->extractors, MR_ITER_LVERT, is_mesh, &settings);
|
2021-05-31 17:11:01 +02:00
|
|
|
}
|
2021-06-10 16:01:36 +02:00
|
|
|
|
2021-06-18 13:25:36 +02:00
|
|
|
extract_finish(data->mr, data->cache, *data->extractors, userdata_chunk);
|
|
|
|
MEM_freeN(userdata_chunk);
|
2021-05-31 17:11:01 +02:00
|
|
|
}
|
2019-07-14 16:49:44 +02:00
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
2021-06-10 16:13:01 +02:00
|
|
|
/** \name Extract In Parallel Ranges
|
2019-07-14 16:49:44 +02:00
|
|
|
* \{ */
|
2021-06-01 12:12:13 +02:00
|
|
|
|
2021-06-10 16:01:36 +02:00
|
|
|
static struct TaskNode *extract_task_node_create(struct TaskGraph *task_graph,
|
|
|
|
const MeshRenderData *mr,
|
|
|
|
MeshBatchCache *cache,
|
|
|
|
ExtractorRunDatas *extractors,
|
2021-08-23 17:33:12 +02:00
|
|
|
MeshBufferList *mbuflist,
|
2021-06-10 16:01:36 +02:00
|
|
|
const bool use_threading)
|
2020-06-02 15:07:17 +02:00
|
|
|
{
|
2021-08-23 17:33:12 +02:00
|
|
|
ExtractTaskData *taskdata = new ExtractTaskData(mr, cache, extractors, mbuflist, use_threading);
|
2021-06-10 16:01:36 +02:00
|
|
|
struct TaskNode *task_node = BLI_task_graph_node_create(
|
|
|
|
task_graph,
|
|
|
|
extract_task_range_run,
|
|
|
|
taskdata,
|
|
|
|
(TaskGraphNodeFreeFunction)extract_task_data_free);
|
|
|
|
return task_node;
|
2020-06-02 15:07:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/** \name Task Node - Update Mesh Render Data
|
|
|
|
* \{ */
|
2021-12-14 05:49:31 +01:00
|
|
|
|
2021-06-01 12:12:13 +02:00
|
|
|
struct MeshRenderDataUpdateTaskData {
|
|
|
|
MeshRenderData *mr = nullptr;
|
2021-08-23 17:35:43 +02:00
|
|
|
MeshBufferCache *cache = nullptr;
|
2020-06-02 15:07:17 +02:00
|
|
|
eMRIterType iter_type;
|
|
|
|
eMRDataType data_flag;
|
2021-06-01 12:12:13 +02:00
|
|
|
|
2021-06-15 15:31:17 +02:00
|
|
|
MeshRenderDataUpdateTaskData(MeshRenderData *mr,
|
2021-08-23 17:35:43 +02:00
|
|
|
MeshBufferCache *cache,
|
2021-06-15 15:31:17 +02:00
|
|
|
eMRIterType iter_type,
|
|
|
|
eMRDataType data_flag)
|
|
|
|
: mr(mr), cache(cache), iter_type(iter_type), data_flag(data_flag)
|
2021-06-07 16:06:30 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-06-01 12:12:13 +02:00
|
|
|
~MeshRenderDataUpdateTaskData()
|
|
|
|
{
|
|
|
|
mesh_render_data_free(mr);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("DRW:MeshRenderDataUpdateTaskData")
|
|
|
|
#endif
|
|
|
|
};
|
2020-06-02 15:07:17 +02:00
|
|
|
|
2021-06-07 16:06:30 +02:00
|
|
|
static void mesh_render_data_update_task_data_free(void *data)
|
2020-06-02 15:07:17 +02:00
|
|
|
{
|
2021-06-07 16:06:30 +02:00
|
|
|
MeshRenderDataUpdateTaskData *taskdata = static_cast<MeshRenderDataUpdateTaskData *>(data);
|
2020-06-02 15:07:17 +02:00
|
|
|
BLI_assert(taskdata);
|
2021-06-01 12:12:13 +02:00
|
|
|
delete taskdata;
|
2020-06-02 15:07:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void mesh_extract_render_data_node_exec(void *__restrict task_data)
|
|
|
|
{
|
2021-06-01 12:12:13 +02:00
|
|
|
MeshRenderDataUpdateTaskData *update_task_data = static_cast<MeshRenderDataUpdateTaskData *>(
|
|
|
|
task_data);
|
2020-06-15 15:25:25 +02:00
|
|
|
MeshRenderData *mr = update_task_data->mr;
|
|
|
|
const eMRIterType iter_type = update_task_data->iter_type;
|
|
|
|
const eMRDataType data_flag = update_task_data->data_flag;
|
|
|
|
|
2021-06-01 13:18:04 +02:00
|
|
|
mesh_render_data_update_normals(mr, data_flag);
|
2020-06-15 15:25:25 +02:00
|
|
|
mesh_render_data_update_looptris(mr, iter_type, data_flag);
|
2021-07-21 19:45:02 +02:00
|
|
|
mesh_render_data_update_loose_geom(mr, update_task_data->cache, iter_type, data_flag);
|
2021-07-20 16:43:38 +02:00
|
|
|
mesh_render_data_update_polys_sorted(mr, update_task_data->cache, data_flag);
|
2020-06-02 15:07:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct TaskNode *mesh_extract_render_data_node_create(struct TaskGraph *task_graph,
|
|
|
|
MeshRenderData *mr,
|
2021-08-23 17:35:43 +02:00
|
|
|
MeshBufferCache *cache,
|
2020-06-02 15:07:17 +02:00
|
|
|
const eMRIterType iter_type,
|
|
|
|
const eMRDataType data_flag)
|
|
|
|
{
|
2021-06-07 16:06:30 +02:00
|
|
|
MeshRenderDataUpdateTaskData *task_data = new MeshRenderDataUpdateTaskData(
|
2021-06-15 15:31:17 +02:00
|
|
|
mr, cache, iter_type, data_flag);
|
2020-06-02 15:07:17 +02:00
|
|
|
|
|
|
|
struct TaskNode *task_node = BLI_task_graph_node_create(
|
|
|
|
task_graph,
|
|
|
|
mesh_extract_render_data_node_exec,
|
|
|
|
task_data,
|
|
|
|
(TaskGraphNodeFreeFunction)mesh_render_data_update_task_data_free);
|
|
|
|
return task_node;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/** \name Extract Loop
|
|
|
|
* \{ */
|
|
|
|
|
2021-06-01 12:12:13 +02:00
|
|
|
static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
|
|
|
|
MeshBatchCache *cache,
|
2021-08-23 18:28:55 +02:00
|
|
|
MeshBufferCache *mbc,
|
2021-06-01 12:12:13 +02:00
|
|
|
Mesh *me,
|
2020-06-02 15:07:17 +02:00
|
|
|
|
2021-06-01 12:12:13 +02:00
|
|
|
const bool is_editmode,
|
|
|
|
const bool is_paint_mode,
|
|
|
|
const bool is_mode_active,
|
|
|
|
const float obmat[4][4],
|
|
|
|
const bool do_final,
|
|
|
|
const bool do_uvedit,
|
|
|
|
const bool use_subsurf_fdots,
|
|
|
|
const Scene *scene,
|
|
|
|
const ToolSettings *ts,
|
|
|
|
const bool use_hide)
|
2019-07-14 16:49:44 +02:00
|
|
|
{
|
2020-06-02 15:07:17 +02:00
|
|
|
/* For each mesh where batches needs to be updated a sub-graph will be added to the task_graph.
|
2021-05-31 17:11:01 +02:00
|
|
|
* This sub-graph starts with an extract_render_data_node. This fills/converts the required
|
|
|
|
* data from Mesh.
|
2020-06-02 15:07:17 +02:00
|
|
|
*
|
|
|
|
* Small extractions and extractions that can't be multi-threaded are grouped in a single
|
|
|
|
* `extract_single_threaded_task_node`.
|
|
|
|
*
|
|
|
|
* Other extractions will create a node for each loop exceeding 8192 items. these nodes are
|
2020-06-25 08:56:49 +02:00
|
|
|
* linked to the `user_data_init_task_node`. the `user_data_init_task_node` prepares the
|
|
|
|
* user_data needed for the extraction based on the data extracted from the mesh.
|
|
|
|
* counters are used to check if the finalize of a task has to be called.
|
2020-06-02 15:07:17 +02:00
|
|
|
*
|
|
|
|
* Mesh extraction sub graph
|
|
|
|
*
|
|
|
|
* +----------------------+
|
|
|
|
* +-----> | extract_task1_loop_1 |
|
|
|
|
* | +----------------------+
|
|
|
|
* +------------------+ +----------------------+ +----------------------+
|
|
|
|
* | mesh_render_data | --> | | --> | extract_task1_loop_2 |
|
|
|
|
* +------------------+ | | +----------------------+
|
|
|
|
* | | | +----------------------+
|
|
|
|
* | | user_data_init | --> | extract_task2_loop_1 |
|
|
|
|
* v | | +----------------------+
|
|
|
|
* +------------------+ | | +----------------------+
|
|
|
|
* | single_threaded | | | --> | extract_task2_loop_2 |
|
|
|
|
* +------------------+ +----------------------+ +----------------------+
|
|
|
|
* | +----------------------+
|
|
|
|
* +-----> | extract_task2_loop_3 |
|
|
|
|
* +----------------------+
|
|
|
|
*/
|
2021-05-31 17:11:01 +02:00
|
|
|
const bool do_hq_normals = (scene->r.perf_flag & SCE_PERF_HQ_NORMALS) != 0 ||
|
|
|
|
GPU_use_hq_normals_workaround();
|
2021-06-09 16:20:38 +02:00
|
|
|
const bool override_single_mat = mesh_render_mat_len_get(me) <= 1;
|
2019-07-14 16:49:44 +02:00
|
|
|
|
2021-05-31 17:11:01 +02:00
|
|
|
/* Create an array containing all the extractors that needs to be executed. */
|
2021-06-01 12:59:15 +02:00
|
|
|
ExtractorRunDatas extractors;
|
2020-06-02 15:07:17 +02:00
|
|
|
|
2021-08-23 18:28:55 +02:00
|
|
|
MeshBufferList *mbuflist = &mbc->buff;
|
|
|
|
|
2021-06-28 15:13:08 +02:00
|
|
|
#define EXTRACT_ADD_REQUESTED(type, name) \
|
2019-07-14 16:49:44 +02:00
|
|
|
do { \
|
2021-08-23 17:33:12 +02:00
|
|
|
if (DRW_##type##_requested(mbuflist->type.name)) { \
|
2021-06-09 16:20:38 +02:00
|
|
|
const MeshExtract *extractor = mesh_extract_override_get( \
|
|
|
|
&extract_##name, do_hq_normals, override_single_mat); \
|
2021-06-01 12:59:15 +02:00
|
|
|
extractors.append(extractor); \
|
2019-07-14 16:49:44 +02:00
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
2021-06-28 15:13:08 +02:00
|
|
|
EXTRACT_ADD_REQUESTED(vbo, pos_nor);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, lnor);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, uv);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, tan);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, vcol);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, sculpt_data);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, orco);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, edge_fac);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, weights);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, edit_data);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, edituv_data);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_area);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_angle);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, mesh_analysis);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, fdots_pos);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, fdots_nor);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, fdots_uv);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, fdots_edituv_data);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, poly_idx);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, edge_idx);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, vert_idx);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, fdot_idx);
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, skin_roots);
|
2021-10-26 23:16:33 +02:00
|
|
|
for (int i = 0; i < GPU_MAX_ATTR; i++) {
|
|
|
|
EXTRACT_ADD_REQUESTED(vbo, attr[i]);
|
|
|
|
}
|
2021-06-28 15:13:08 +02:00
|
|
|
|
|
|
|
EXTRACT_ADD_REQUESTED(ibo, tris);
|
2021-08-23 17:33:12 +02:00
|
|
|
if (DRW_ibo_requested(mbuflist->ibo.lines_loose)) {
|
2021-06-28 15:59:40 +02:00
|
|
|
/* `ibo.lines_loose` require the `ibo.lines` buffer. */
|
2021-08-23 17:33:12 +02:00
|
|
|
if (mbuflist->ibo.lines == nullptr) {
|
|
|
|
DRW_ibo_request(nullptr, &mbuflist->ibo.lines);
|
2021-06-28 15:59:40 +02:00
|
|
|
}
|
2021-08-23 17:33:12 +02:00
|
|
|
const MeshExtract *extractor = DRW_ibo_requested(mbuflist->ibo.lines) ?
|
2021-06-28 15:59:40 +02:00
|
|
|
&extract_lines_with_lines_loose :
|
|
|
|
&extract_lines_loose_only;
|
|
|
|
extractors.append(extractor);
|
|
|
|
}
|
2021-08-23 17:33:12 +02:00
|
|
|
else if (DRW_ibo_requested(mbuflist->ibo.lines)) {
|
2021-06-05 14:46:00 +02:00
|
|
|
const MeshExtract *extractor;
|
2021-08-23 17:33:12 +02:00
|
|
|
if (mbuflist->ibo.lines_loose != nullptr) {
|
2021-06-28 15:59:40 +02:00
|
|
|
/* Update `ibo.lines_loose` as it depends on `ibo.lines`. */
|
2021-06-05 14:46:00 +02:00
|
|
|
extractor = &extract_lines_with_lines_loose;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
extractor = &extract_lines;
|
|
|
|
}
|
|
|
|
extractors.append(extractor);
|
|
|
|
}
|
2021-06-28 15:13:08 +02:00
|
|
|
EXTRACT_ADD_REQUESTED(ibo, points);
|
|
|
|
EXTRACT_ADD_REQUESTED(ibo, fdots);
|
|
|
|
EXTRACT_ADD_REQUESTED(ibo, lines_paint_mask);
|
|
|
|
EXTRACT_ADD_REQUESTED(ibo, lines_adjacency);
|
|
|
|
EXTRACT_ADD_REQUESTED(ibo, edituv_tris);
|
|
|
|
EXTRACT_ADD_REQUESTED(ibo, edituv_lines);
|
|
|
|
EXTRACT_ADD_REQUESTED(ibo, edituv_points);
|
|
|
|
EXTRACT_ADD_REQUESTED(ibo, edituv_fdots);
|
2021-05-31 17:11:01 +02:00
|
|
|
|
|
|
|
#undef EXTRACT_ADD_REQUESTED
|
|
|
|
|
2021-06-01 12:12:13 +02:00
|
|
|
if (extractors.is_empty()) {
|
2021-05-28 16:51:05 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-05-31 21:28:00 +02:00
|
|
|
#ifdef DEBUG_TIME
|
|
|
|
double rdata_start = PIL_check_seconds_timer();
|
|
|
|
#endif
|
|
|
|
|
2021-07-22 13:59:43 +02:00
|
|
|
MeshRenderData *mr = mesh_render_data_create(
|
|
|
|
me, is_editmode, is_paint_mode, is_mode_active, obmat, do_final, do_uvedit, ts);
|
2019-07-14 16:49:44 +02:00
|
|
|
mr->use_hide = use_hide;
|
|
|
|
mr->use_subsurf_fdots = use_subsurf_fdots;
|
|
|
|
mr->use_final_mesh = do_final;
|
|
|
|
|
|
|
|
#ifdef DEBUG_TIME
|
2021-05-31 21:28:00 +02:00
|
|
|
double rdata_end = PIL_check_seconds_timer();
|
2019-07-14 16:49:44 +02:00
|
|
|
#endif
|
|
|
|
|
2021-07-21 19:45:02 +02:00
|
|
|
eMRIterType iter_type = extractors.iter_types();
|
|
|
|
eMRDataType data_flag = extractors.data_types();
|
|
|
|
|
2020-06-02 15:07:17 +02:00
|
|
|
struct TaskNode *task_node_mesh_render_data = mesh_extract_render_data_node_create(
|
2021-08-23 18:28:55 +02:00
|
|
|
task_graph, mr, mbc, iter_type, data_flag);
|
2019-07-14 16:49:44 +02:00
|
|
|
|
2021-05-31 17:11:01 +02:00
|
|
|
/* Simple heuristic. */
|
2021-06-18 16:09:35 +02:00
|
|
|
const bool use_thread = (mr->loop_len + mr->loop_loose_len) > MIN_RANGE_LEN;
|
2021-05-31 17:11:01 +02:00
|
|
|
|
|
|
|
if (use_thread) {
|
|
|
|
/* First run the requested extractors that do not support asynchronous ranges. */
|
2021-06-01 12:59:15 +02:00
|
|
|
for (const ExtractorRunData &run_data : extractors) {
|
2021-06-01 12:12:13 +02:00
|
|
|
const MeshExtract *extractor = run_data.extractor;
|
2021-05-31 17:11:01 +02:00
|
|
|
if (!extractor->use_threading) {
|
2021-06-01 12:59:15 +02:00
|
|
|
ExtractorRunDatas *single_threaded_extractors = new ExtractorRunDatas();
|
|
|
|
single_threaded_extractors->append(extractor);
|
2021-06-10 16:01:36 +02:00
|
|
|
struct TaskNode *task_node = extract_task_node_create(
|
2021-08-23 17:33:12 +02:00
|
|
|
task_graph, mr, cache, single_threaded_extractors, mbuflist, false);
|
2021-06-10 16:01:36 +02:00
|
|
|
|
2021-05-31 17:11:01 +02:00
|
|
|
BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Distribute the remaining extractors into ranges per core. */
|
2021-06-01 12:59:15 +02:00
|
|
|
ExtractorRunDatas *multi_threaded_extractors = new ExtractorRunDatas();
|
|
|
|
extractors.filter_threaded_extractors_into(*multi_threaded_extractors);
|
2021-06-01 12:12:13 +02:00
|
|
|
if (!multi_threaded_extractors->is_empty()) {
|
2021-06-10 16:01:36 +02:00
|
|
|
struct TaskNode *task_node = extract_task_node_create(
|
2021-08-23 17:33:12 +02:00
|
|
|
task_graph, mr, cache, multi_threaded_extractors, mbuflist, true);
|
2021-06-10 16:01:36 +02:00
|
|
|
|
|
|
|
BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
|
2021-05-31 17:11:01 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* No tasks created freeing extractors list. */
|
2021-06-01 12:12:13 +02:00
|
|
|
delete multi_threaded_extractors;
|
2021-05-31 17:11:01 +02:00
|
|
|
}
|
2020-06-02 15:07:17 +02:00
|
|
|
}
|
|
|
|
else {
|
2021-05-31 17:11:01 +02:00
|
|
|
/* Run all requests on the same thread. */
|
2021-06-01 12:59:15 +02:00
|
|
|
ExtractorRunDatas *extractors_copy = new ExtractorRunDatas(extractors);
|
2021-06-10 16:01:36 +02:00
|
|
|
struct TaskNode *task_node = extract_task_node_create(
|
2021-08-23 17:33:12 +02:00
|
|
|
task_graph, mr, cache, extractors_copy, mbuflist, false);
|
2021-05-31 17:11:01 +02:00
|
|
|
|
|
|
|
BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
|
2020-06-02 15:07:17 +02:00
|
|
|
}
|
2019-12-03 08:27:55 +01:00
|
|
|
|
2020-06-02 15:07:17 +02:00
|
|
|
/* Trigger the sub-graph for this mesh. */
|
|
|
|
BLI_task_graph_node_push_work(task_node_mesh_render_data);
|
2019-12-05 08:14:32 +01:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
#ifdef DEBUG_TIME
|
2020-06-02 15:07:17 +02:00
|
|
|
BLI_task_graph_work_and_wait(task_graph);
|
2019-07-14 16:49:44 +02:00
|
|
|
double end = PIL_check_seconds_timer();
|
|
|
|
|
|
|
|
static double avg = 0;
|
|
|
|
static double avg_fps = 0;
|
|
|
|
static double avg_rdata = 0;
|
|
|
|
static double end_prev = 0;
|
|
|
|
|
|
|
|
if (end_prev == 0) {
|
|
|
|
end_prev = end;
|
|
|
|
}
|
|
|
|
|
|
|
|
avg = avg * 0.95 + (end - rdata_end) * 0.05;
|
|
|
|
avg_fps = avg_fps * 0.95 + (end - end_prev) * 0.05;
|
|
|
|
avg_rdata = avg_rdata * 0.95 + (rdata_end - rdata_start) * 0.05;
|
|
|
|
|
|
|
|
printf(
|
|
|
|
"rdata %.0fms iter %.0fms (frame %.0fms)\n", avg_rdata * 1000, avg * 1000, avg_fps * 1000);
|
|
|
|
|
|
|
|
end_prev = end;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-12-14 05:49:31 +01:00
|
|
|
/** \} */
|
|
|
|
|
2021-06-01 12:12:13 +02:00
|
|
|
} // namespace blender::draw
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
|
|
|
|
MeshBatchCache *cache,
|
2021-08-23 18:28:55 +02:00
|
|
|
MeshBufferCache *mbc,
|
2021-06-01 12:12:13 +02:00
|
|
|
Mesh *me,
|
|
|
|
|
|
|
|
const bool is_editmode,
|
|
|
|
const bool is_paint_mode,
|
|
|
|
const bool is_mode_active,
|
|
|
|
const float obmat[4][4],
|
|
|
|
const bool do_final,
|
|
|
|
const bool do_uvedit,
|
|
|
|
const bool use_subsurf_fdots,
|
|
|
|
const Scene *scene,
|
|
|
|
const ToolSettings *ts,
|
|
|
|
const bool use_hide)
|
|
|
|
{
|
|
|
|
blender::draw::mesh_buffer_cache_create_requested(task_graph,
|
|
|
|
cache,
|
2021-08-23 18:28:55 +02:00
|
|
|
mbc,
|
2021-06-01 12:12:13 +02:00
|
|
|
me,
|
|
|
|
is_editmode,
|
|
|
|
is_paint_mode,
|
|
|
|
is_mode_active,
|
|
|
|
obmat,
|
|
|
|
do_final,
|
|
|
|
do_uvedit,
|
|
|
|
use_subsurf_fdots,
|
|
|
|
scene,
|
|
|
|
ts,
|
|
|
|
use_hide);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // extern "C"
|