Race condition in one of Kritas internal Data Manager implementations?

Florian Reiser reiserfm at gmail.com
Thu Nov 2 20:39:29 GMT 2023


Hi Dmitry,

Thank you for your answer.

It was also my first thought, that the blocking by
image->immediateLockForReadOnly() causes the problem and that waiting for
the end of the stroke by calling barrierLock() would just take too long to
satisfy the 10Hz condition.
But then I wondered, where the data comes from and how it is possible to
explain the strange behaviour I observed. Am I right, that with

device->makeCloneFromRough(image->projection(), image->bounds());

we just create a new clone of our image without any data? And that the real
data, we are building our PNG and JPEG exports on, comes from this read
call:

device->readBytes(reinterpret_cast<quint8 *>(imageBuffer.data()), 0, 0,
width, height);

I would imagine that the second command needs far more time than the first
one. And that this data must be continuously updated by the painting engine
somehow. And that the strange data, I get exported, must in the end come
from this read call instead of the clone call.
But please correct me, if my thoughts are wrong. I really would like to
understand Krita better in this place.


It would make the framerate of the final production not very stable (though
> I'm not sure if it is a problem)
>

Actually, four our use case, this is a problem (unfortunately). My wife and
I are producing tutorial videos. We make them by a mixture of live screen
capturing of the tool we want to show and by hand drawing comic style
sketches to explain a theory or to show something in the screen capturing.
Until now, we are using OBS to get our raw material, but this has many
disadvantages. It would be so cool, if we just could use the krita recorder
tool directly. It would save us so much work and the video quality would be
way better. But to use it, we must achieve at least a frame rate of 30Hz.
Therefore, I introduced a new Real Time Feature for the Krita recorder
plugin (
https://invent.kde.org/freiser/krita-freiser/-/tree/freiser/RecorderRealTimeMT?ref_type=heads),
which works really smooth. But naturally, the bug hits us here in the same
way. For big colored areas, which are drawn in a short period, we receive
white frames and the areas are not build up as expected in the exported
video. Everything else, especially fine brush strokes are recorded smooth
and in the expected frame rate.

If you like this new real time feature, I would be honored if you will
accept my merge request as soon as I'm done with the cleanup. But I fear,
with the bug still there, it doesn't make much sense to integrate it.


Back to the bug. I thought a little bit about it and did some research on
the Krita code. As it turns out, you use the Qt OpenGl Render engine in
many places. Especially the KisOpenGLCanvasRenderer caught my interest. If
it were possible for the recorder to access the framebuffer, we would
probably be many times faster at capturing the current image than by the
current method, wouldn't we? But it's just an idea and before I start
investigating in this direction, I would be curious about your opinion. Do
you think it makes sense to rebuild the capturing code by using OpenGL?

Florian




Am Mi., 1. Nov. 2023 um 08:59 Uhr schrieb Dmitry Kazakov <dimula73 at gmail.com
>:

> Hi, Florian!
>
> The problem happens a bit higher in the hierarchy. The problem is that the
> recorder does not wait for the stroke to finish. Instead it just locks the
> image for read-only in the middle of the action and reads the data. You can
> see that in this piece of code:
>
> image->immediateLockForReadOnly();
> device->makeCloneFromRough(image->projection(), image->bounds());
> image->unlock()
>
> The only wait to avoid white/incomplete frames in the recorder is to make
> snapshots "between" the strokes. There are two ways to achieve that: either
> use barrierLock() (not-recommended) or create a stroke that makes a copy of
> the image. Just like Overview and Channels dockers do. The only problem
> with this approach is that the 100ms timing will not be satisfied in this
> case. The recorder would wait for the user's stroke to end (which might
> easily take more than 100ms) and then just add a frame. It would make the
> framerate of the final production not very stable (though I'm not sure if
> it is a problem).
>
> Alternatively, we could implement an epoche-based brush updates, but that
> is a huge ton of work. We wanted to implement that to handle tearing in the
> updates back in 2018, but never had time to actually implement that.
>
> On Tue, Oct 31, 2023 at 12:38 PM Florian Reiser <reiserfm at gmail.com>
> wrote:
>
>> Hi everyone,
>>
>> not sure if this is the right channel to ask this. I hope this mail
>> reaches some of the right people.
>>
>> I've created a bug report for the newest Krita Version (
>> https://bugs.kde.org/show_bug.cgi?id=476326). But I think the bug only
>> showed up just yet, because with Krita 5.2 we introduced the 10Hz recording
>> feature. There is a good chance that it has already existed for quite some
>> time.
>>
>> Can someone support me to fix it. We really want to use the new 10Hz
>> Feature for one of our projects, it would reduce our post production work a
>> lot.
>>
>> Thank you very much for your help
>> Florian
>>
>
>
> --
> Dmitry Kazakov
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.kde.org/pipermail/kimageshop/attachments/20231102/d5f80597/attachment.htm>


More information about the kimageshop mailing list