Fix T49461: Dynamic paint wetmap flickers.

Regression from rBa4a968f, we would adjust current point's wetness without actually protecting it
in new multi-threaded context, leading to concurrent access mess.

Now delay applying wetness reduction to current point to end of function, allows us to avoid having
to lock current point twice together with neighbor one (and reducing spinlock awainting too).

To be backported to 2.78a.
This commit is contained in:
Bastien Montagne 2016-09-27 13:54:26 +02:00
parent e6dda514ba
commit 54ed22c843
Notes: blender-bot 2023-02-14 07:33:57 +01:00
Referenced by issue #49461, Dynamic paint wetmap flickers
1 changed files with 31 additions and 9 deletions

View File

@ -4779,6 +4779,8 @@ static void dynamic_paint_effect_drip_cb(void *userdata, const int index)
return;
CLAMP(w_factor, 0.0f, 1.0f);
float ppoint_wetness_diff = 0.0f;
/* get force affect points */
surface_determineForceTargetPoints(sData, index, &force[index * 4], closest_d, closest_id);
@ -4800,9 +4802,9 @@ static void dynamic_paint_effect_drip_cb(void *userdata, const int index)
/* Sort of spinlock, but only for given ePoint.
* Since the odds a same ePoint is modified at the same time by several threads is very low, this is
* much more efficient than a global spin lock. */
const unsigned int pointlock_idx = n_trgt / 8;
const uint8_t pointlock_bitmask = 1 << (n_trgt & 7); /* 7 == 0b111 */
while (atomic_fetch_and_or_uint8(&point_locks[pointlock_idx], pointlock_bitmask) & pointlock_bitmask);
const unsigned int epointlock_idx = n_trgt / 8;
const uint8_t epointlock_bitmask = 1 << (n_trgt & 7); /* 7 == 0b111 */
while (atomic_fetch_and_or_uint8(&point_locks[epointlock_idx], epointlock_bitmask) & epointlock_bitmask);
PaintPoint *ePoint = &((PaintPoint *)sData->type_data)[n_trgt];
const float e_wet = ePoint->wetness;
@ -4823,18 +4825,38 @@ static void dynamic_paint_effect_drip_cb(void *userdata, const int index)
CLAMP_MAX(ePoint->e_color[3], pPoint_prev->e_color[3]);
}
/* decrease paint wetness on current point */
pPoint->wetness -= (ePoint->wetness - e_wet);
CLAMP(pPoint->wetness, 0.0f, MAX_WETNESS);
/* Decrease paint wetness on current point
* (just store diff here, that way we can only lock current point once at the end to apply it). */
ppoint_wetness_diff += (ePoint->wetness - e_wet);
#ifndef NDEBUG
uint8_t ret = atomic_fetch_and_and_uint8(&point_locks[pointlock_idx], ~pointlock_bitmask);
BLI_assert(ret & pointlock_bitmask);
{
uint8_t ret = atomic_fetch_and_and_uint8(&point_locks[epointlock_idx], ~epointlock_bitmask);
BLI_assert(ret & epointlock_bitmask);
}
#else
atomic_fetch_and_and_uint8(&point_locks[pointlock_idx], ~pointlock_bitmask);
atomic_fetch_and_and_uint8(&point_locks[epointlock_idx], ~epointlock_bitmask);
#endif
}
}
{
const unsigned int ppointlock_idx = index / 8;
const uint8_t ppointlock_bitmask = 1 << (index & 7); /* 7 == 0b111 */
while (atomic_fetch_and_or_uint8(&point_locks[ppointlock_idx], ppointlock_bitmask) & ppointlock_bitmask);
pPoint->wetness -= ppoint_wetness_diff;
CLAMP(pPoint->wetness, 0.0f, MAX_WETNESS);
#ifndef NDEBUG
{
uint8_t ret = atomic_fetch_and_and_uint8(&point_locks[ppointlock_idx], ~ppointlock_bitmask);
BLI_assert(ret & ppointlock_bitmask);
}
#else
atomic_fetch_and_and_uint8(&point_locks[ppointlock_idx], ~ppointlock_bitmask);
#endif
}
}
static void dynamicPaint_doEffectStep(