implement the last 2 mask:mask blends simd
This commit is contained in:
parent
47f5c13a67
commit
a519ecdf13
2 changed files with 57 additions and 3 deletions
|
@ -647,24 +647,63 @@ when defined(amd64) and allowSimd:
|
|||
|
||||
mm_or_si128(backdropEven, mm_slli_epi16(backdropOdd, 8))
|
||||
|
||||
proc maskBlendSubtractSimd*(backdrop, source: M128i): M128i {.inline.} =
|
||||
let
|
||||
oddMask = mm_set1_epi16(cast[int16](0xff00))
|
||||
vec255 = mm_set1_epi8(255)
|
||||
div255 = mm_set1_epi16(cast[int16](0x8081))
|
||||
|
||||
let sourceMinus255 = mm_sub_epi8(vec255, source)
|
||||
|
||||
var
|
||||
multiplierEven = mm_slli_epi16(sourceMinus255, 8)
|
||||
multiplierOdd = mm_and_si128(sourceMinus255, oddMask)
|
||||
backdropEven = mm_slli_epi16(backdrop, 8)
|
||||
backdropOdd = mm_and_si128(backdrop, oddMask)
|
||||
|
||||
backdropEven = mm_mulhi_epu16(backdropEven, multiplierEven)
|
||||
backdropOdd = mm_mulhi_epu16(backdropOdd, multiplierOdd)
|
||||
|
||||
backdropEven = mm_srli_epi16(mm_mulhi_epu16(backdropEven, div255), 7)
|
||||
backdropOdd = mm_srli_epi16(mm_mulhi_epu16(backdropOdd, div255), 7)
|
||||
|
||||
mm_or_si128(backdropEven, mm_slli_epi16(backdropOdd, 8))
|
||||
|
||||
proc maskBlendExcludeSimd*(backdrop, source: M128i): M128i {.inline.} =
|
||||
mm_sub_epi8(mm_max_epu8(backdrop, source), mm_min_epu8(backdrop, source))
|
||||
|
||||
proc maskBlendNormalSimdMasker(backdrop, source: M128i): M128i =
|
||||
maskBlendNormalSimd(backdrop, source)
|
||||
|
||||
proc maskBlendMaskSimdMasker(backdrop, source: M128i): M128i =
|
||||
maskBlendMaskSimd(backdrop, source)
|
||||
|
||||
proc maskBlendExcludeSimdMasker(backdrop, source: M128i): M128i =
|
||||
maskBlendExcludeSimd(backdrop, source)
|
||||
|
||||
proc maskBlendSubtractSimdMasker(backdrop, source: M128i): M128i =
|
||||
maskBlendSubtractSimd(backdrop, source)
|
||||
|
||||
proc maskerSimd*(blendMode: BlendMode): MaskerSimd {.raises: [PixieError].} =
|
||||
## Returns a blend masking function with SIMD support.
|
||||
case blendMode:
|
||||
of NormalBlend: maskBlendNormalSimdMasker
|
||||
of MaskBlend: maskBlendMaskSimdMasker
|
||||
of OverwriteBlend: overwriteSimdBlender
|
||||
of SubtractMaskBlend: maskBlendSubtractSimdMasker
|
||||
of ExcludeMaskBlend: maskBlendExcludeSimdMasker
|
||||
else:
|
||||
raise newException(PixieError, "No SIMD masker for " & $blendMode)
|
||||
|
||||
proc hasSimdMasker*(blendMode: BlendMode): bool {.inline, raises: [].} =
|
||||
## Is there a blend masking function with SIMD support?
|
||||
blendMode in {NormalBlend, MaskBlend, OverwriteBlend}
|
||||
blendMode in {
|
||||
NormalBlend,
|
||||
MaskBlend,
|
||||
OverwriteBlend,
|
||||
SubtractMaskBlend,
|
||||
ExcludeMaskBlend
|
||||
}
|
||||
|
||||
when defined(release):
|
||||
{.pop.}
|
||||
|
|
|
@ -1572,6 +1572,17 @@ proc fillHits(
|
|||
windingRule: WindingRule,
|
||||
blendMode: BlendMode
|
||||
) =
|
||||
template simdBlob(mask: Mask, x: var int, blendProc: untyped) =
|
||||
when allowSimd:
|
||||
when defined(amd64):
|
||||
let vec255 = mm_set1_epi8(255)
|
||||
for _ in 0 ..< fillLen div 16:
|
||||
let
|
||||
index = mask.dataIndex(x, y)
|
||||
backdrop = mm_loadu_si128(mask.data[index].addr)
|
||||
mm_storeu_si128(mask.data[index].addr, blendProc(backdrop, vec255))
|
||||
x += 16
|
||||
|
||||
case blendMode:
|
||||
of NormalBlend, OverwriteBlend:
|
||||
walkHits hits, numHits, windingRule, y, mask.width:
|
||||
|
@ -1590,13 +1601,17 @@ proc fillHits(
|
|||
|
||||
of SubtractMaskBlend:
|
||||
walkHits hits, numHits, windingRule, y, mask.width:
|
||||
for x in fillStart ..< fillStart + fillLen:
|
||||
var x = fillStart
|
||||
simdBlob(mask, x, maskBlendSubtractSimd)
|
||||
for x in x ..< fillStart + fillLen:
|
||||
let backdrop = mask.unsafe[x, y]
|
||||
mask.unsafe[x, y] = maskBlendSubtract(backdrop, 255)
|
||||
|
||||
of ExcludeMaskBlend:
|
||||
walkHits hits, numHits, windingRule, y, mask.width:
|
||||
for x in fillStart ..< fillStart + fillLen:
|
||||
var x = fillStart
|
||||
simdBlob(mask, x, maskBlendExcludeSimd)
|
||||
for x in x ..< fillStart + fillLen:
|
||||
let backdrop = mask.unsafe[x, y]
|
||||
mask.unsafe[x, y] = maskBlendExclude(backdrop, 255)
|
||||
|
||||
|
|
Loading…
Reference in a new issue