Fix #139471: Grease Pencil: Trace materials must be created on main thread

Creating materials in worker threads does not work, this relies on BKE functions
which must only be called from the main thread. Create the foreground/background
materials in advance before starting the trace job.

Pull Request: https://projects.blender.org/blender/blender/pulls/139532
This commit is contained in:
Lukas Tönne
2025-05-28 18:23:25 +02:00
parent 20eff58509
commit 2a317bad3e

View File

@@ -98,6 +98,8 @@ struct TraceJob {
TraceMode mode;
/* Custom source frame, allows overriding the default scene frame. */
int frame_number;
int foreground_material_index;
int background_material_index;
bool success;
bool was_canceled;
@@ -207,17 +209,18 @@ static bke::CurvesGeometry grease_pencil_trace_image(TraceJob &trace_job, const
/* Assign different materials to foreground curves and hole curves. */
bke::MutableAttributeAccessor attributes = trace_curves.attributes_for_write();
const int material_fg = ensure_foreground_material(
trace_job.bmain, trace_job.ob_grease_pencil, "Stroke");
const int material_bg = ensure_background_material(
trace_job.bmain, trace_job.ob_grease_pencil, "Holdout");
BLI_assert_msg(trace_job.foreground_material_index >= 0,
"ensure_foreground_material must be called on the main thread");
BLI_assert_msg(trace_job.background_material_index >= 0,
"ensure_background_material must be called on the main thread");
const VArraySpan<bool> holes = *attributes.lookup<bool>(hole_attribute_id);
bke::SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_span<int>(
"material_index", bke::AttrDomain::Curve);
threading::parallel_for(trace_curves.curves_range(), 4096, [&](const IndexRange range) {
for (const int curve_i : range) {
const bool is_hole = holes[curve_i];
material_indices.span[curve_i] = (is_hole ? material_bg : material_fg);
material_indices.span[curve_i] = (is_hole ? trace_job.background_material_index :
trace_job.foreground_material_index);
}
});
material_indices.finish();
@@ -424,6 +427,12 @@ static wmOperatorStatus grease_pencil_trace_image_exec(bContext *C, wmOperator *
/* Back to active base. */
blender::ed::object::base_activate(job->C, job->base_active);
/* Create materials on the main thread before starting the job. */
job->foreground_material_index = ensure_foreground_material(
job->bmain, job->ob_grease_pencil, "Stroke");
job->background_material_index = ensure_background_material(
job->bmain, job->ob_grease_pencil, "Holdout");
if ((job->image->source == IMA_SRC_FILE) || (job->frame_number > 0)) {
wmJobWorkerStatus worker_status = {};
trace_start_job(job, &worker_status);