Krita Source Code Documentation
Loading...
Searching...
No Matches
KoStreamedMath< _impl > Struct Template Reference

#include <KoStreamedMath.h>

Public Types

using float_v = xsimd::batch<float, _impl>
 
using int_v = xsimd::batch<int, _impl>
 
using uint_v = xsimd::batch<unsigned int, _impl>
 

Static Public Member Functions

template<bool aligned>
static float_v fetch_alpha_32 (const void *data)
 
template<bool aligned>
static void fetch_colors_32 (const void *data, float_v &c1, float_v &c2, float_v &c3)
 
static float_v fetch_mask_8 (const quint8 *data)
 
template<bool useMask, bool useFlow, class Compositor , int pixelSize>
static void genericComposite (const KoCompositeOp::ParameterInfo &params)
 
template<bool useMask, bool useFlow, class Compositor >
static void genericComposite128 (const KoCompositeOp::ParameterInfo &params)
 
template<bool useMask, bool useFlow, class Compositor >
static void genericComposite128_novector (const KoCompositeOp::ParameterInfo &params)
 
template<bool useMask, bool useFlow, class Compositor >
static void genericComposite32 (const KoCompositeOp::ParameterInfo &params)
 
template<bool useMask, bool useFlow, class Compositor >
static void genericComposite32_novector (const KoCompositeOp::ParameterInfo &params)
 
template<bool useMask, bool useFlow, class Compositor >
static void genericComposite64 (const KoCompositeOp::ParameterInfo &params)
 
template<bool useMask, bool useFlow, class Compositor >
static void genericComposite64_novector (const KoCompositeOp::ParameterInfo &params)
 
template<bool useMask, bool useFlow, class Compositor , int pixelSize>
static void genericComposite_novector (const KoCompositeOp::ParameterInfo &params)
 
static quint8 lerp_mixed_u8_float (quint8 a, quint8 b, float alpha)
 
static quint8 round_float_to_u8 (float x)
 
static void write_channels_32 (void *data, const float_v alpha, const float_v c1, const float_v c2, const float_v c3)
 
static void write_channels_32_unaligned (void *data, const float_v alpha, const float_v c1, const float_v c2, const float_v c3)
 

Detailed Description

template<typename _impl>
struct KoStreamedMath< _impl >

Definition at line 154 of file KoStreamedMath.h.

Member Typedef Documentation

◆ float_v

template<typename _impl >
using KoStreamedMath< _impl >::float_v = xsimd::batch<float, _impl>

Definition at line 157 of file KoStreamedMath.h.

◆ int_v

template<typename _impl >
using KoStreamedMath< _impl >::int_v = xsimd::batch<int, _impl>

Definition at line 155 of file KoStreamedMath.h.

◆ uint_v

template<typename _impl >
using KoStreamedMath< _impl >::uint_v = xsimd::batch<unsigned int, _impl>

Definition at line 156 of file KoStreamedMath.h.

Member Function Documentation

◆ fetch_alpha_32()

template<typename _impl >
template<bool aligned>
static float_v KoStreamedMath< _impl >::fetch_alpha_32 ( const void * data)
inlinestatic

Get an alpha values from float_v::size pixels 32-bit each (4 channels, 8 bit per channel). The alpha value is considered to be stored in the most significant byte of the pixel

aligned controls whether the data is fetched using aligned instruction or not. 1) Fetching aligned data with unaligned instruction degrades performance. 2) Fetching unaligned data with aligned instruction causes #GP (General Protection Exception)

Definition at line 256 of file KoStreamedMath.h.

257 {
258 using U = typename std::conditional<aligned, xsimd::aligned_mode, xsimd::unaligned_mode>::type;
259 const auto data_i = uint_v::load(static_cast<const typename uint_v::value_type *>(data), U{});
260 return xsimd::to_float(xsimd::bitwise_cast_compat<int>(data_i >> 24));
261 }

◆ fetch_colors_32()

template<typename _impl >
template<bool aligned>
static void KoStreamedMath< _impl >::fetch_colors_32 ( const void * data,
float_v & c1,
float_v & c2,
float_v & c3 )
inlinestatic

Get color values from float_v::size pixels 32-bit each (4 channels, 8 bit per channel). The color data is considered to be stored in the 3 least significant bytes of the pixel.

aligned controls whether the data is fetched using aligned instruction or not. 1) Fetching aligned data with unaligned instruction degrades performance. 2) Fetching unaligned data with aligned instruction causes #GP (General Protection Exception)

Definition at line 276 of file KoStreamedMath.h.

277 {
278 using U = typename std::conditional<aligned, xsimd::aligned_mode, xsimd::unaligned_mode>::type;
279
280 const auto data_i = uint_v::load(static_cast<const typename uint_v::value_type *>(data), U{});
281
282 const uint_v mask(0xFF);
283
284 c1 = xsimd::to_float(xsimd::bitwise_cast_compat<int>((data_i >> 16) & mask));
285 c2 = xsimd::to_float(xsimd::bitwise_cast_compat<int>((data_i >> 8) & mask));
286 c3 = xsimd::to_float(xsimd::bitwise_cast_compat<int>((data_i) & mask));
287 }
xsimd::batch< unsigned int, _impl > uint_v

◆ fetch_mask_8()

template<typename _impl >
static float_v KoStreamedMath< _impl >::fetch_mask_8 ( const quint8 * data)
inlinestatic

Get a vector containing first float_v::size values of mask. Each source mask element is considered to be a 8-bit integer

Definition at line 238 of file KoStreamedMath.h.

239 {
240 return xsimd::batch_cast<float>(xsimd::load_and_extend<int_v>(data));
241 }

◆ genericComposite()

template<typename _impl >
template<bool useMask, bool useFlow, class Compositor , int pixelSize>
static void KoStreamedMath< _impl >::genericComposite ( const KoCompositeOp::ParameterInfo & params)
inlinestatic

Composes src pixels into dst pixels. Is optimized for 32-bit-per-pixel colorspaces. Uses Compositor strategy parameter for doing actual math of the composition

Definition at line 327 of file KoStreamedMath.h.

328 {
329 const int vectorSize = static_cast<int>(float_v::size);
330 const qint32 vectorInc = pixelSize * vectorSize;
331 const qint32 linearInc = pixelSize;
332 qint32 srcVectorInc = vectorInc;
333 qint32 srcLinearInc = pixelSize;
334
335 quint8 *dstRowStart = params.dstRowStart;
336 const quint8 *maskRowStart = params.maskRowStart;
337 const quint8 *srcRowStart = params.srcRowStart;
338 typename Compositor::ParamsWrapper paramsWrapper(params);
339
340 if (!params.srcRowStride) {
341 if (pixelSize == 4) {
342 auto *buf = reinterpret_cast<uint_v *>(xsimd::vector_aligned_malloc<typename uint_v::value_type>(vectorSize));
343 *buf = uint_v(*(reinterpret_cast<const quint32 *>(srcRowStart)));
344 srcRowStart = reinterpret_cast<quint8 *>(buf);
345 srcLinearInc = 0;
346 srcVectorInc = 0;
347 } else {
348 auto *buf = xsimd::vector_aligned_malloc<quint8>(vectorInc);
349 quint8 *ptr = buf;
350
351 for (size_t i = 0; i < vectorSize; i++) {
352 memcpy(ptr, params.srcRowStart, pixelSize);
353 ptr += pixelSize;
354 }
355
356 srcRowStart = buf;
357 srcLinearInc = 0;
358 srcVectorInc = 0;
359 }
360 }
361#if BLOCKDEBUG
362 int totalBlockAlign = 0;
363 int totalBlockAlignedVector = 0;
364 int totalBlockUnalignedVector = 0;
365 int totalBlockRest = 0;
366#endif
367
368 for (qint32 r = params.rows; r > 0; --r) {
369 // Hint: Mask is allowed to be unaligned
370 const quint8 *mask = maskRowStart;
371
372 const quint8 *src = srcRowStart;
373 quint8 *dst = dstRowStart;
374
375 const int pixelsAlignmentMask = vectorSize * sizeof(float) - 1;
376 auto srcPtrValue = reinterpret_cast<uintptr_t>(src);
377 auto dstPtrValue = reinterpret_cast<uintptr_t>(dst);
378 uintptr_t srcAlignment = srcPtrValue & pixelsAlignmentMask;
379 uintptr_t dstAlignment = dstPtrValue & pixelsAlignmentMask;
380
381 // Uncomment if facing problems with alignment:
382 // Q_ASSERT_X(!(dstAlignment & 3), "Compositing",
383 // "Pixel data must be aligned on pixels borders!");
384
385 int blockAlign = params.cols;
386 int blockAlignedVector = 0;
387 int blockUnalignedVector = 0;
388 int blockRest = 0;
389
390 int *vectorBlock =
391 srcAlignment == dstAlignment || !srcVectorInc ? &blockAlignedVector : &blockUnalignedVector;
392
393 if (!dstAlignment) {
394 blockAlign = 0;
395 *vectorBlock = params.cols / vectorSize;
396 blockRest = params.cols % vectorSize;
397 } else if (params.cols > 2 * vectorSize) {
398 blockAlign = (vectorInc - dstAlignment) / pixelSize;
399 const int restCols = params.cols - blockAlign;
400 if (restCols > 0) {
401 *vectorBlock = restCols / vectorSize;
402 blockRest = restCols % vectorSize;
403 } else {
404 blockAlign = params.cols;
405 *vectorBlock = 0;
406 blockRest = 0;
407 }
408 }
409#if BLOCKDEBUG
410 totalBlockAlign += blockAlign;
411 totalBlockAlignedVector += blockAlignedVector;
412 totalBlockUnalignedVector += blockUnalignedVector;
413 totalBlockRest += blockRest;
414#endif
415
416 for (int i = 0; i < blockAlign; i++) {
417 Compositor::template compositeOnePixelScalar<useMask, _impl>(src,
418 dst,
419 mask,
420 params.opacity,
421 paramsWrapper);
422 src += srcLinearInc;
423 dst += linearInc;
424
425 if (useMask) {
426 mask++;
427 }
428 }
429
430 for (int i = 0; i < blockAlignedVector; i++) {
431 Compositor::template compositeVector<useMask, true, _impl>(src,
432 dst,
433 mask,
434 params.opacity,
435 paramsWrapper);
436 src += srcVectorInc;
437 dst += vectorInc;
438
439 if (useMask) {
440 mask += vectorSize;
441 }
442 }
443
444 for (int i = 0; i < blockUnalignedVector; i++) {
445 Compositor::template compositeVector<useMask, false, _impl>(src,
446 dst,
447 mask,
448 params.opacity,
449 paramsWrapper);
450 src += srcVectorInc;
451 dst += vectorInc;
452
453 if (useMask) {
454 mask += vectorSize;
455 }
456 }
457
458 for (int i = 0; i < blockRest; i++) {
459 Compositor::template compositeOnePixelScalar<useMask, _impl>(src,
460 dst,
461 mask,
462 params.opacity,
463 paramsWrapper);
464 src += srcLinearInc;
465 dst += linearInc;
466
467 if (useMask) {
468 mask++;
469 }
470 }
471
472 srcRowStart += params.srcRowStride;
473 dstRowStart += params.dstRowStride;
474
475 if (useMask) {
476 maskRowStart += params.maskRowStride;
477 }
478 }
479
480#if BLOCKDEBUG
481 dbgPigment << "I"
482 << "rows:" << params.rows << "\tpad(S):" << totalBlockAlign << "\tbav(V):" << totalBlockAlignedVector
483 << "\tbuv(V):" << totalBlockUnalignedVector << "\tres(S)"
484 << totalBlockRest; // << srcAlignment << dstAlignment;
485#endif
486
487 if (!params.srcRowStride) {
488 xsimd::vector_aligned_free(srcRowStart);
489 }
490 }
#define dbgPigment
void vector_aligned_free(const T *ptr) noexcept

References KoCompositeOp::ParameterInfo::cols, dbgPigment, KoCompositeOp::ParameterInfo::dstRowStart, KoCompositeOp::ParameterInfo::dstRowStride, KoCompositeOp::ParameterInfo::maskRowStart, KoCompositeOp::ParameterInfo::maskRowStride, KoCompositeOp::ParameterInfo::opacity, KoCompositeOp::ParameterInfo::rows, KoCompositeOp::ParameterInfo::srcRowStart, KoCompositeOp::ParameterInfo::srcRowStride, and xsimd::vector_aligned_free().

◆ genericComposite128()

template<typename _impl >
template<bool useMask, bool useFlow, class Compositor >
static void KoStreamedMath< _impl >::genericComposite128 ( const KoCompositeOp::ParameterInfo & params)
inlinestatic

Definition at line 499 of file KoStreamedMath.h.

500 {
501 genericComposite<useMask, useFlow, Compositor, 16>(params);
502 }

◆ genericComposite128_novector()

template<typename _impl >
template<bool useMask, bool useFlow, class Compositor >
static void KoStreamedMath< _impl >::genericComposite128_novector ( const KoCompositeOp::ParameterInfo & params)
inlinestatic

Definition at line 213 of file KoStreamedMath.h.

214 {
215 genericComposite_novector<useMask, useFlow, Compositor, 16>(params);
216 }

◆ genericComposite32()

template<typename _impl >
template<bool useMask, bool useFlow, class Compositor >
static void KoStreamedMath< _impl >::genericComposite32 ( const KoCompositeOp::ParameterInfo & params)
inlinestatic

Definition at line 493 of file KoStreamedMath.h.

494 {
495 genericComposite<useMask, useFlow, Compositor, 4>(params);
496 }

◆ genericComposite32_novector()

template<typename _impl >
template<bool useMask, bool useFlow, class Compositor >
static void KoStreamedMath< _impl >::genericComposite32_novector ( const KoCompositeOp::ParameterInfo & params)
inlinestatic

Definition at line 207 of file KoStreamedMath.h.

208 {
209 genericComposite_novector<useMask, useFlow, Compositor, 4>(params);
210 }

◆ genericComposite64()

template<typename _impl >
template<bool useMask, bool useFlow, class Compositor >
static void KoStreamedMath< _impl >::genericComposite64 ( const KoCompositeOp::ParameterInfo & params)
inlinestatic

Definition at line 505 of file KoStreamedMath.h.

506 {
507 genericComposite<useMask, useFlow, Compositor, 8>(params);
508 }

◆ genericComposite64_novector()

template<typename _impl >
template<bool useMask, bool useFlow, class Compositor >
static void KoStreamedMath< _impl >::genericComposite64_novector ( const KoCompositeOp::ParameterInfo & params)
inlinestatic

Definition at line 219 of file KoStreamedMath.h.

220 {
221 genericComposite_novector<useMask, useFlow, Compositor, 8>(params);
222 }

◆ genericComposite_novector()

template<typename _impl >
template<bool useMask, bool useFlow, class Compositor , int pixelSize>
static void KoStreamedMath< _impl >::genericComposite_novector ( const KoCompositeOp::ParameterInfo & params)
inlinestatic

Composes src into dst without using vector instructions

Definition at line 166 of file KoStreamedMath.h.

167 {
168 const qint32 linearInc = pixelSize;
169 qint32 srcLinearInc = params.srcRowStride ? pixelSize : 0;
170
171 quint8 *dstRowStart = params.dstRowStart;
172 const quint8 *maskRowStart = params.maskRowStart;
173 const quint8 *srcRowStart = params.srcRowStart;
174 typename Compositor::ParamsWrapper paramsWrapper(params);
175
176 for (qint32 r = params.rows; r > 0; --r) {
177 const quint8 *mask = maskRowStart;
178 const quint8 *src = srcRowStart;
179 quint8 *dst = dstRowStart;
180
181 int blockRest = params.cols;
182
183 for (int i = 0; i < blockRest; i++) {
184 Compositor::template compositeOnePixelScalar<useMask, _impl>(src,
185 dst,
186 mask,
187 params.opacity,
188 paramsWrapper);
189 src += srcLinearInc;
190 dst += linearInc;
191
192 if (useMask) {
193 mask++;
194 }
195 }
196
197 srcRowStart += params.srcRowStride;
198 dstRowStart += params.dstRowStride;
199
200 if (useMask) {
201 maskRowStart += params.maskRowStride;
202 }
203 }
204 }

References KoCompositeOp::ParameterInfo::cols, KoCompositeOp::ParameterInfo::dstRowStart, KoCompositeOp::ParameterInfo::dstRowStride, KoCompositeOp::ParameterInfo::maskRowStart, KoCompositeOp::ParameterInfo::maskRowStride, KoCompositeOp::ParameterInfo::opacity, KoCompositeOp::ParameterInfo::rows, KoCompositeOp::ParameterInfo::srcRowStart, and KoCompositeOp::ParameterInfo::srcRowStride.

◆ lerp_mixed_u8_float()

template<typename _impl >
static quint8 KoStreamedMath< _impl >::lerp_mixed_u8_float ( quint8 a,
quint8 b,
float alpha )
inlinestatic

Definition at line 229 of file KoStreamedMath.h.

230 {
231 return round_float_to_u8(float(b - a) * alpha + float(a));
232 }
static quint8 round_float_to_u8(float x)

References KoStreamedMath< _impl >::round_float_to_u8().

◆ round_float_to_u8()

template<typename _impl >
static quint8 KoStreamedMath< _impl >::round_float_to_u8 ( float x)
inlinestatic

Definition at line 224 of file KoStreamedMath.h.

225 {
227 }
static ALWAYS_INLINE result_type roundScalar(const float value)

References OptiRound< _impl, result_type >::roundScalar().

◆ write_channels_32()

template<typename _impl >
static void KoStreamedMath< _impl >::write_channels_32 ( void * data,
const float_v alpha,
const float_v c1,
const float_v c2,
const float_v c3 )
inlinestatic

Pack color and alpha values to float_v::size pixels 32-bit each (4 channels, 8 bit per channel). The color data is considered to be stored in the 3 least significant bytes of the pixel, alpha - in the most significant byte

NOTE: data must be aligned pointer!

Definition at line 298 of file KoStreamedMath.h.

299 {
300 const int_v mask(0xFF);
301
302 const auto v1 = (xsimd::nearbyint_as_int(alpha)) << 24;
303 const auto v2 = (xsimd::nearbyint_as_int(c1) & mask) << 16;
304 const auto v3 = (xsimd::nearbyint_as_int(c2) & mask) << 8;
305 const auto v4 = (xsimd::nearbyint_as_int(c3) & mask);
306 xsimd::store_aligned(static_cast<typename int_v::value_type *>(data), (v1 | v2) | (v3 | v4));
307 }
xsimd::batch< int, _impl > int_v

◆ write_channels_32_unaligned()

template<typename _impl >
static void KoStreamedMath< _impl >::write_channels_32_unaligned ( void * data,
const float_v alpha,
const float_v c1,
const float_v c2,
const float_v c3 )
inlinestatic

Definition at line 310 of file KoStreamedMath.h.

311 {
312 const int_v mask(0xFF);
313
314 const auto v1 = (xsimd::nearbyint_as_int(alpha)) << 24;
315 const auto v2 = (xsimd::nearbyint_as_int(c1) & mask) << 16;
316 const auto v3 = (xsimd::nearbyint_as_int(c2) & mask) << 8;
317 const auto v4 = (xsimd::nearbyint_as_int(c3) & mask);
318 xsimd::store_unaligned(static_cast<typename int_v::value_type *>(data), (v1 | v2) | (v3 | v4));
319 }

The documentation for this struct was generated from the following file: