gegl/buffer: make shape and offset of sampler prefetch adaptive

This makes reuse of prefetched data more likely, for the rotate test-case in
perf it doubles the throughput.
parent f13fe74d
......@@ -254,89 +254,36 @@ GeglRectangle _gegl_sampler_compute_rectangle (GeglSampler *sampler,
GeglRectangle rectangle;
GeglSamplerLevel *level = &sampler->level[level_no];
if (level->last_x || level->last_y)
{
gint x_delta = x - level->last_x;
gint y_delta = y - level->last_y;
gint max_delta_squared = 60 * 60;
if (x_delta * x_delta < max_delta_squared &&
y_delta * y_delta < max_delta_squared)
{
level->x_delta = level->x_delta * 0.99 + x_delta * 0.01;
level->y_delta = level->y_delta * 0.99 + y_delta * 0.01;
if (x_delta < 0) x_delta = -x_delta;
if (y_delta < 0) y_delta = -y_delta;
level->x_magnitude = level->x_magnitude * 0.99 + x_delta * 0.01;
level->y_magnitude = level->y_magnitude * 0.99 + y_delta * 0.01;
}
}
level->last_x = x;
level->last_y = y;
rectangle.width = level->context_rect.width + 2;
rectangle.height = level->context_rect.height + 2;
/* grow in direction of prediction */
if (level->delta_x * level->delta_x >
level->delta_y * level->delta_y)
{
rectangle.width *= 2;
}
else
{
rectangle.height *= 2;
}
rectangle.x = x + level->context_rect.x;
rectangle.y = y + level->context_rect.y;
/* grow area slightly, maybe getting a couple of extra
hits out of cour cache
*/
rectangle.x -= 2;
rectangle.y -= 2;
rectangle.width += 4;
rectangle.height += 4;
#if 0
/* XXX: FIXME: grow cached area based on sampling pattern profiling
* information, possibly with much bigger wins than the marginal wins the
* increase in size by 2 in each dir does.
*/
if (level->x_magnitude > 0.001 || level->y_magnitude > 0.001)
{
gfloat magnitude = sqrtf (level->x_magnitude * level->x_magnitude +
level->y_magnitude * level->y_magnitude);
gfloat new_magnitude;
if (level->x_magnitude > level->y_magnitude)
new_magnitude =
4 + 60 * (level->x_magnitude - level->y_magnitude) / level->x_magnitude;
else
new_magnitude =
4 + 60 * (level->y_magnitude - level->x_magnitude) / level->y_magnitude;
rectangle.width =
(level->x_magnitude / magnitude) * new_magnitude
+ level->context_rect.width + 2;
rectangle.height =
(level->y_magnitude / magnitude) * new_magnitude
+ level->context_rect.height + 2;
/* todo: if both xmag and ymag are small - but similar in magnitude
we should increase the size of the cache if it would fit, thus
perhaps working better on small local non-linear access patterns
*/
rectangle.x -= 1;
rectangle.y -= 1;
rectangle.width += 2;
rectangle.height += 2;
/* align rectangle corner we've likely entered with sampled pixel
*/
if (level->x_delta >=0)
rectangle.x = x + level->context_rect.x
- (rectangle.width - level->context_rect.x)/10;
else
rectangle.x = x + level->context_rect.x
- (rectangle.width - level->context_rect.width) * 9/10;
//fprintf (stderr, "{%f %f}", level->delta_x, level->delta_y);
if (level->y_delta >=0)
rectangle.y = y + level->context_rect.y
- (rectangle.height - level->context_rect.y)/10;
else
rectangle.y = y + level->context_rect.y
- (rectangle.height - level->context_rect.height) * 9/10;
}
#if 1
/* shift area based on prediction */
if (level->delta_x >=0.01)
rectangle.x -= rectangle.width * 0.3;
if (level->delta_y >=0.01)
rectangle.y -= rectangle.height * 0.3;
#endif
if (rectangle.width >= GEGL_SAMPLER_MAXIMUM_WIDTH)
......
......@@ -20,6 +20,7 @@
#include <glib-object.h>
#include <babl/babl.h>
#include <stdio.h>
G_BEGIN_DECLS
......@@ -52,13 +53,10 @@ typedef struct GeglSamplerLevel
GeglRectangle context_rect;
gpointer sampler_buffer;
GeglRectangle sampler_rectangle;
gint last_x;
gint last_y;
float x_delta;
float y_delta;
float x_magnitude;
float y_magnitude;
float delta_x;
float delta_y;
} GeglSamplerLevel;
struct _GeglSampler
......@@ -126,6 +124,7 @@ gegl_sampler_get_ptr (GeglSampler *sampler,
gint y,
GeglAbyssPolicy repeat_mode)
{
float delta_x, delta_y;
gint dx, dy, sof;
guchar *buffer_ptr;
......@@ -137,7 +136,8 @@ gegl_sampler_get_ptr (GeglSampler *sampler,
(y + level->context_rect.y + level->context_rect.height >
level->sampler_rectangle.y + level->sampler_rectangle.height))
{
level->sampler_rectangle = _gegl_sampler_compute_rectangle (sampler, x, y, 0);
level->sampler_rectangle =
_gegl_sampler_compute_rectangle (sampler, x, y, 0);
gegl_buffer_get (sampler->buffer,
&level->sampler_rectangle,
......@@ -146,6 +146,10 @@ gegl_sampler_get_ptr (GeglSampler *sampler,
level->sampler_buffer,
GEGL_SAMPLER_MAXIMUM_WIDTH * GEGL_SAMPLER_BPP,
repeat_mode);
level->last_x = x;
level->last_y = y;
level->delta_x = 0;
level->delta_y = 0;
}
dx = x - level->sampler_rectangle.x;
......@@ -153,6 +157,13 @@ gegl_sampler_get_ptr (GeglSampler *sampler,
sof = (dx + dy * GEGL_SAMPLER_MAXIMUM_WIDTH) * GEGL_SAMPLER_BPP;
buffer_ptr = (guchar *) level->sampler_buffer;
delta_x = level->last_x - x;
delta_y = level->last_y - y;
level->last_x = x;
level->last_y = y;
level->delta_x = (level->delta_x + delta_x) / 2;
level->delta_y = (level->delta_y + delta_y) / 2;
return (gfloat *) (buffer_ptr + sof);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment