Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2016-05-05 15:45:00 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2016-05-05 15:45:00 +0300
commit6f83710af94a9f6d117ef60537329941cd8614fa (patch)
treed36a9f136aec24d8f3f20a00de364b6549728ea0 /source/blender/imbuf
parentc81d9fda46665ebf2b2b98624c4c7ad01088a346 (diff)
Optimize projection painting with big brushes
Multi-threaded partial buffer update, gives about 2x speedup with big brushes. Thanks Campbell for testing and benchmarking!
Diffstat (limited to 'source/blender/imbuf')
-rw-r--r--source/blender/imbuf/intern/divers.c87
1 files changed, 69 insertions, 18 deletions
diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
index 455b78bce4d..3aabf7e18cc 100644
--- a/source/blender/imbuf/intern/divers.c
+++ b/source/blender/imbuf/intern/divers.c
@@ -674,25 +674,24 @@ void IMB_rect_from_float(ImBuf *ibuf)
ibuf->userflags &= ~IB_RECT_INVALID;
}
-/* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */
-void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w, int h, bool is_data)
-{
- const float *rect_float;
+typedef struct PartialThreadData {
+ ImBuf *ibuf;
+ float *buffer;
uchar *rect_byte;
- int profile_from = IB_PROFILE_LINEAR_RGB;
-
- /* verify we have a float buffer */
- if (ibuf->rect_float == NULL || buffer == NULL)
- return;
-
- /* create byte rect if it didn't exist yet */
- if (ibuf->rect == NULL)
- imb_addrectImBuf(ibuf);
-
- /* do conversion */
- rect_float = ibuf->rect_float + (x + ((size_t)y) * ibuf->x) * ibuf->channels;
- rect_byte = (uchar *)ibuf->rect + (x + ((size_t)y) * ibuf->x) * 4;
-
+ const float *rect_float;
+ int width;
+ bool is_data;
+} PartialThreadData;
+
+static void partial_rect_from_float_slice(float *buffer,
+ uchar *rect_byte,
+ ImBuf *ibuf,
+ const float *rect_float,
+ const int w,
+ const int h,
+ const bool is_data)
+{
+ const int profile_from = IB_PROFILE_LINEAR_RGB;
if (is_data) {
/* exception for non-color data, just copy float */
IMB_buffer_float_from_float(buffer, rect_float,
@@ -715,6 +714,58 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w
4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0,
w, h, ibuf->x, w);
}
+}
+
+static void partial_rect_from_float_thread_do(void *data_v,
+ int start_scanline,
+ int num_scanlines)
+{
+ PartialThreadData *data = (PartialThreadData *)data_v;
+ ImBuf *ibuf = data->ibuf;
+ size_t global_offset = ((size_t)ibuf->x) * start_scanline;
+ size_t local_offset = ((size_t)data->width) * start_scanline;
+ partial_rect_from_float_slice(data->buffer + local_offset * ibuf->channels,
+ data->rect_byte + global_offset * 4,
+ ibuf,
+ data->rect_float + global_offset * ibuf->channels,
+ data->width,
+ num_scanlines,
+ data->is_data);
+}
+
+/* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */
+void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w, int h, bool is_data)
+{
+ const float *rect_float;
+ uchar *rect_byte;
+
+ /* verify we have a float buffer */
+ if (ibuf->rect_float == NULL || buffer == NULL)
+ return;
+
+ /* create byte rect if it didn't exist yet */
+ if (ibuf->rect == NULL)
+ imb_addrectImBuf(ibuf);
+
+ /* do conversion */
+ rect_float = ibuf->rect_float + (x + ((size_t)y) * ibuf->x) * ibuf->channels;
+ rect_byte = (uchar *)ibuf->rect + (x + ((size_t)y) * ibuf->x) * 4;
+
+ if (((size_t)w) * h < 64 * 64) {
+ partial_rect_from_float_slice(
+ buffer, rect_byte, ibuf, rect_float, w, h, is_data);
+ }
+ else {
+ PartialThreadData data;
+ data.ibuf = ibuf;
+ data.buffer = buffer;
+ data.rect_byte = rect_byte;
+ data.rect_float = rect_float;
+ data.width = w;
+ data.is_data = is_data;
+ IMB_processor_apply_threaded_scanlines(
+ h, partial_rect_from_float_thread_do, &data);
+ }
/* ensure user flag is reset */
ibuf->userflags &= ~IB_RECT_INVALID;