implement the last 2 mask:mask blends simd

This commit is contained in:
Ryan Oldenburg 2022-06-16 01:48:34 -05:00
parent 47f5c13a67
commit a519ecdf13
2 changed files with 57 additions and 3 deletions

View file

@ -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.}

View file

@ -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)