Просмотр исходного кода

Add sve2 acceleration for blit2to2 key (#15953)

Gabriel Wang 1 день назад
Родитель
Сommit
7afd6c3497

+ 5 - 0
src/video/SDL_blit_N.c

@@ -3205,6 +3205,11 @@ SDL_BlitFunc SDL_CalculateBlitN(SDL_Surface *surface)
            If a particular case turns out to be useful we'll add it. */
 
         if (srcfmt->bytes_per_pixel == 2 && surface->map.identity != 0) {
+#ifdef SDL_SVE2_INTRINSICS
+            if (SDL_HasSVE2()) {
+                return Blit2to2KeySVE2;
+            }
+#endif
             return Blit2to2Key;
         } else {
 #ifdef SDL_ALTIVEC_BLITTERS

+ 1 - 1
src/video/arm/SDL_sve2_blit_A.c

@@ -96,7 +96,7 @@ static inline void sdl_sve_rgb565_stride_blend_with_opacity(uint16_t *SDL_RESTRI
                                                             size_t uStride,
                                                             uint16_t hwOpacity)
 {
-    sdl_sve_stride_loop_rgb16(uStride, vTailPred)
+    sdl_sve_stride_loop_u16(uStride, vTailPred)
     {
 
         svuint16x3_t vSource16x3 =

+ 272 - 0
src/video/arm/SDL_sve2_blit_N.c

@@ -61,4 +61,276 @@ void Blit8888to565PixelSwizzleSVE2(SDL_BlitInfo *info)
     sdl_sve_rgb32_to_rgb565_swizzle_dispatcher(info);
 }
 
+SDL_TARGETING("arch=armv8-a+sve2")
+ARM_NONNULL(1, 2)
+static inline void sdl_sve_rgb16_stride_key(uint16_t *SDL_RESTRICT phwSource,
+                                            uint16_t *SDL_RESTRICT phwTarget,
+                                            size_t uStride,
+                                            uint16_t hwKey,
+                                            uint16_t hwKeyMask)
+{
+    sdl_sve_stride_loop_u16(uStride, vTailPred)
+    {
+        svuint16_t vSource = svld1_u16(vTailPred, phwSource);
+        svuint16_t vTarget = svld1_u16(vTailPred, phwTarget);
+
+        svuint16_t vSourceMasked = svand_n_u16_m(vTailPred,
+                                                 vSource,
+                                                 hwKeyMask);
+        vTarget = svsel_u16(svcmpeq_n_u16(vTailPred, vSourceMasked, hwKey),
+                            vTarget,
+                            vSource);
+
+        svst1_u16(vTailPred, phwTarget, vTarget);
+
+        phwSource += sve_iteration_advance;
+        phwTarget += sve_iteration_advance;
+    }
+}
+
+SDL_TARGETING("arch=armv8-a+sve2")
+ARM_NONNULL(1, 3)
+static inline void sdl_sve_rgb16_key(uint8_t *SDL_RESTRICT pchSource,
+                                     size_t uSourceStride,
+                                     uint8_t *SDL_RESTRICT pchTarget,
+                                     size_t uTargetStride,
+                                     int nWidth,
+                                     int nHeight,
+                                     uint16_t hwKey,
+                                     uint16_t hwKeyMask)
+{
+    assert(0 == ((uintptr_t)pchSource & 0x01));
+    assert(0 == ((uintptr_t)pchTarget & 0x01));
+
+    while (nHeight--) {
+        sdl_sve_rgb16_stride_key((uint16_t *)pchSource,
+                                 (uint16_t *)pchTarget,
+                                 nWidth,
+                                 hwKey,
+                                 hwKeyMask);
+
+        pchSource += uSourceStride;
+        pchTarget += uTargetStride;
+    }
+}
+
+SDL_TARGETING("arch=armv8-a+sve2")
+void Blit2to2KeySVE2(SDL_BlitInfo *info)
+{
+    int width = info->dst_w;
+    int height = info->dst_h;
+    uint8_t *src = info->src;
+    int srcskip = info->src_skip;
+    uint8_t *dst = info->dst;
+    int dstskip = info->dst_skip;
+
+    const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
+    const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
+
+    // Set up some basic variables
+    int srcbpp = srcfmt->bytes_per_pixel;
+    int dstbpp = dstfmt->bytes_per_pixel;
+
+    assert(srcbpp == 2);
+    assert(dstbpp == 2);
+
+    int srcstride = srcskip + srcbpp * width;
+    int dststride = dstskip + dstbpp * width;
+
+    uint32_t ckey = info->colorkey;
+    uint32_t rgbmask = ~srcfmt->Amask;
+    ckey &= rgbmask;
+
+    sdl_sve_rgb16_key(src,
+                      srcstride,
+                      dst,
+                      dststride,
+                      width,
+                      height,
+                      ckey,
+                      rgbmask);
+}
+
+SDL_TARGETING("arch=armv8-a+sve2")
+ARM_NONNULL(1, 2)
+static inline void sdl_sve_rgb32_stride_key_copy_alpha(
+    uint32_t *SDL_RESTRICT pwSource,
+    uint32_t *SDL_RESTRICT pwTarget,
+    size_t uStride,
+    uint32_t wKey,
+    uint32_t wKeyMask,
+    uint32_t wOpacifyMask)
+{
+    sdl_sve_stride_loop_u32(uStride, vTailPred)
+    {
+        svuint32_t vSource = svld1_u32(vTailPred, pwSource);
+        svuint32_t vTarget = svld1_u32(vTailPred, pwTarget);
+
+        /*
+            uint32_t opamask = ((uint32_t)info->a) << dstfmt->Ashift;
+            ...
+            if ((*src32 & rgbmask) != ckey) {
+                *dst32 = *src32 | opamask;
+            }
+        */
+        svuint32_t vSourceMasked = svand_n_u32_m(vTailPred,
+                                                 vSource,
+                                                 wKeyMask);
+        vTarget = svsel_u32(svcmpeq_n_u32(vTailPred, vSourceMasked, wKey),
+                            vTarget,
+                            svorr_n_u32_m(vTailPred, vSource, wOpacifyMask));
+
+        svst1_u32(vTailPred, pwTarget, vTarget);
+
+        pwSource += sve_iteration_advance;
+        pwTarget += sve_iteration_advance;
+    }
+}
+
+SDL_TARGETING("arch=armv8-a+sve2")
+ARM_NONNULL(1, 2)
+static inline void sdl_sve_rgb32_stride_key_no_alpha(
+    uint32_t *SDL_RESTRICT pwSource,
+    uint32_t *SDL_RESTRICT pwTarget,
+    size_t uStride,
+    uint32_t wKey,
+    uint32_t wKeyMask,
+    uint32_t wActualRGBMask)
+{
+    sdl_sve_stride_loop_u32(uStride, vTailPred)
+    {
+        svuint32_t vSource = svld1_u32(vTailPred, pwSource);
+        svuint32_t vTarget = svld1_u32(vTailPred, pwTarget);
+
+        /*
+            uint32_t rgbmaskactual = srcfmt->Rmask | srcfmt->Gmask | srcfmt->Bmask;
+            ...
+            if ((*src32 & rgbmask) != ckey) {
+                *dst32 = *src32 & rgbmaskactual;
+            }
+        */
+        svuint32_t vSourceMasked = svand_n_u32_m(vTailPred,
+                                                 vSource,
+                                                 wKeyMask);
+        vTarget = svsel_u32(svcmpeq_n_u32(vTailPred, vSourceMasked, wKey),
+                            vTarget,
+                            svand_n_u32_m(vTailPred, vSource, wActualRGBMask));
+
+        svst1_u32(vTailPred, pwTarget, vTarget);
+
+        pwSource += sve_iteration_advance;
+        pwTarget += sve_iteration_advance;
+    }
+}
+
+SDL_TARGETING("arch=armv8-a+sve2")
+ARM_NONNULL(1, 3)
+static inline void sdl_sve_rgb32_key_copy_alpha(uint8_t *SDL_RESTRICT pchSource,
+                                                size_t uSourceStride,
+                                                uint8_t *SDL_RESTRICT pchTarget,
+                                                size_t uTargetStride,
+                                                int nWidth,
+                                                int nHeight,
+                                                uint32_t wKey,
+                                                uint32_t wKeyMask,
+                                                uint32_t wOpacifyMask)
+{
+    assert(0 == ((uintptr_t)pchSource & 0x03));
+    assert(0 == ((uintptr_t)pchTarget & 0x03));
+
+    while (nHeight--) {
+        sdl_sve_rgb32_stride_key_copy_alpha((uint32_t *)pchSource,
+                                            (uint32_t *)pchTarget,
+                                            nWidth,
+                                            wKey,
+                                            wKeyMask,
+                                            wOpacifyMask);
+
+        pchSource += uSourceStride;
+        pchTarget += uTargetStride;
+    }
+}
+
+SDL_TARGETING("arch=armv8-a+sve2")
+ARM_NONNULL(1, 3)
+static inline void sdl_sve_rgb32_key_no_alpha(uint8_t *SDL_RESTRICT pchSource,
+                                              size_t uSourceStride,
+                                              uint8_t *SDL_RESTRICT pchTarget,
+                                              size_t uTargetStride,
+                                              int nWidth,
+                                              int nHeight,
+                                              uint32_t wKey,
+                                              uint32_t wKeyMask,
+                                              uint32_t wActualRGBMask)
+{
+    assert(0 == ((uintptr_t)pchSource & 0x03));
+    assert(0 == ((uintptr_t)pchTarget & 0x03));
+
+    while (nHeight--) {
+        sdl_sve_rgb32_stride_key_no_alpha((uint32_t *)pchSource,
+                                          (uint32_t *)pchTarget,
+                                          nWidth,
+                                          wKey,
+                                          wKeyMask,
+                                          wActualRGBMask);
+
+        pchSource += uSourceStride;
+        pchTarget += uTargetStride;
+    }
+}
+
+SDL_TARGETING("arch=armv8-a+sve2")
+void Blit4to4KeySVE2(SDL_BlitInfo *info)
+{
+    int width = info->dst_w;
+    int height = info->dst_h;
+    uint8_t *src = info->src;
+    int srcskip = info->src_skip;
+    uint8_t *dst = info->dst;
+    int dstskip = info->dst_skip;
+
+    const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
+    const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
+
+    // Set up some basic variables
+    int srcbpp = srcfmt->bytes_per_pixel;
+    int dstbpp = dstfmt->bytes_per_pixel;
+
+    assert(srcbpp == 4);
+    assert(dstbpp == 4);
+
+    int srcstride = srcskip + srcbpp * width;
+    int dststride = dstskip + dstbpp * width;
+
+    uint32_t ckey = info->colorkey;
+    uint32_t rgbmask = ~srcfmt->Amask;
+    ckey &= rgbmask;
+
+    if (dstfmt->Amask) {
+        uint32_t opamask = ((uint32_t)info->a) << dstfmt->Ashift;
+        /* RGBA: set alpha from info->a */
+        sdl_sve_rgb32_key_copy_alpha(src,
+                                     srcstride,
+                                     dst,
+                                     dststride,
+                                     width,
+                                     height,
+                                     ckey,
+                                     rgbmask,
+                                     opamask);
+    } else {
+        /* RGBA->RGB: only copy rgb and set alpha to zero */
+        uint32_t rgbmaskactual = srcfmt->Rmask | srcfmt->Gmask | srcfmt->Bmask;
+        sdl_sve_rgb32_key_no_alpha(src,
+                                   srcstride,
+                                   dst,
+                                   dststride,
+                                   width,
+                                   height,
+                                   ckey,
+                                   rgbmask,
+                                   rgbmaskactual);
+    }
+}
+
 #endif /* SDL_SVE2_INTRINSICS */

+ 2 - 0
src/video/arm/SDL_sve2_blit_N.h

@@ -29,6 +29,8 @@
 
 void Blit8888to8888PixelSwizzleSVE2(SDL_BlitInfo *info);
 void Blit8888to565PixelSwizzleSVE2(SDL_BlitInfo *info);
+void Blit2to2KeySVE2(SDL_BlitInfo *info);
+void Blit4to4KeySVE2(SDL_BlitInfo *info);
 
 #endif /* SDL_SVE2_INTRINSICS */
 

+ 24 - 12
src/video/arm/SDL_sve2_extension.h

@@ -22,7 +22,7 @@
 /*
  * IMPORTANT: Please do NOT include this header file directly or indirectly
  *            outside the src/video/arm folder.
- * 
+ *
  */
 
 #if !defined(SDL_SVE2_EXTENSION_H) //&& (defined(__ARM_FEATURE_SVE2) && __ARM_FEATURE_SVE2)
@@ -31,15 +31,15 @@
 #include "SDL_sve2_util.h"
 
 /*
- * NOTE: Some Android builds didn't attach '-march=armv8-a+sve2' to 
+ * NOTE: Some Android builds didn't attach '-march=armv8-a+sve2' to
  *       SDL_sve2_*.c and hence the macro __ARM_FEATURE_SVE is not
- *       defined by the compiler. This might not be a problem as the 
+ *       defined by the compiler. This might not be a problem as the
  *       SDL_TARGETING("arch=armv8-a+sve2") enables the feature for
  *       individual functions, until some version of compilers
- *       provides arm_sve.h raising errors then __ARM_FEATURE_SVE 
- *       is not defined. Although it should be avoided, as a 
- *       workaround, we have to define the __ARM_FEATURE_SVE here as 
- *       an ugly hack. 
+ *       provides arm_sve.h raising errors then __ARM_FEATURE_SVE
+ *       is not defined. Although it should be avoided, as a
+ *       workaround, we have to define the __ARM_FEATURE_SVE here as
+ *       an ugly hack.
  */
 #ifdef SDL_PLATFORM_ANDROID
 #ifndef __ARM_FEATURE_SVE
@@ -66,12 +66,12 @@
 #define svlens32() svlenu32()
 #define svlens64() svlenu64()
 
-#define sdl_sve_stride_loop_accc8888(ma_stride_size, ma_pred_name)       \
+#define sdl_sve_stride_loop_pixel(ma_stride_size, ma_pred_name)          \
     for (svbool_t ma_pred_name, *pTemp = &ma_pred_name;                  \
          pTemp != NULL;                                                  \
          pTemp = NULL)                                                   \
         for (size_t SVE_SAFE_NAME(n) = 0,                                \
-                    sve_iteration_advance = svlenu32() * 4;              \
+                    sve_iteration_advance = svlenu8();                   \
              ({                                                          \
                  ma_pred_name = svwhilelt_b8((int32_t)SVE_SAFE_NAME(n),  \
                                              (int32_t)(ma_stride_size)); \
@@ -79,10 +79,9 @@
              });                                                         \
              SVE_SAFE_NAME(n) += sve_iteration_advance)
 
-#define sdl_sve_stride_loop_rgb32(ma_stride_size, ma_pred_name) \
-    sdl_sve_stride_loop_accc8888(ma_stride_size, ma_pred_name)
+#define sdl_sve_stride_loop_u8 sdl_sve_stride_loop_pixel
 
-#define sdl_sve_stride_loop_rgb16(ma_stride_size, ma_pred_name)           \
+#define sdl_sve_stride_loop_u16(ma_stride_size, ma_pred_name)             \
     for (svbool_t ma_pred_name, *pTemp = &ma_pred_name;                   \
          pTemp != NULL;                                                   \
          pTemp = NULL)                                                    \
@@ -95,6 +94,19 @@
              });                                                          \
              SVE_SAFE_NAME(n) += sve_iteration_advance)
 
+#define sdl_sve_stride_loop_u32(ma_stride_size, ma_pred_name)             \
+    for (svbool_t ma_pred_name, *pTemp = &ma_pred_name;                   \
+         pTemp != NULL;                                                   \
+         pTemp = NULL)                                                    \
+        for (size_t SVE_SAFE_NAME(n) = 0,                                 \
+                    sve_iteration_advance = svlenu32();                   \
+             ({                                                           \
+                 ma_pred_name = svwhilelt_b16((int32_t)SVE_SAFE_NAME(n),  \
+                                              (int32_t)(ma_stride_size)); \
+                 SVE_SAFE_NAME(n) < (ma_stride_size);                     \
+             });                                                          \
+             SVE_SAFE_NAME(n) += sve_iteration_advance)
+
 #define sdl_sve_pixel_ccc_foreach_chn(ma_source_u16x3,                    \
                                       ma_target_u16x3,                    \
                                       ...)                                \

+ 5 - 5
src/video/arm/SDL_sve2_swizzle.h

@@ -22,7 +22,7 @@
 /*
  * IMPORTANT: Please do NOT include this header file directly or indirectly
  *            outside the src/video/arm folder.
- * 
+ *
  */
 
 #if !defined(SD_SVE2_SWIZZLE_H) //&& (defined(__ARM_FEATURE_SVE2) && __ARM_FEATURE_SVE2)
@@ -31,7 +31,7 @@
 #include "SDL_sve2_extension.h"
 
 #define sdl_sve_rgb32_stride_impl(ma_sve_chn_iterator, ...)   \
-    sdl_sve_stride_loop_rgb32(uStride, vTailPred)             \
+    sdl_sve_stride_loop_pixel(uStride, vTailPred)             \
     {                                                         \
                                                               \
         svuint16x4_t vSourceLow16x4 = svundef4_u16();         \
@@ -71,7 +71,7 @@
     ma_alpha_idx,                                             \
     ma_sve_chn_iterator,                                      \
     ...)                                                      \
-    sdl_sve_stride_loop_rgb32(uStride, vTailPred)             \
+    sdl_sve_stride_loop_pixel(uStride, vTailPred)             \
     {                                                         \
                                                               \
         svuint16x4_t vSourceLow16x4 = svundef4_u16();         \
@@ -115,7 +115,7 @@
     }
 
 #define sdl_sve_rgb32_to_rgb565_stride_impl(ma_sve_chn_iterator, ...) \
-    sdl_sve_stride_loop_rgb32(uStride, vTailPred)                     \
+    sdl_sve_stride_loop_pixel(uStride, vTailPred)                     \
     {                                                                 \
                                                                       \
         svuint16x4_t vSourceLow16x4 = svundef4_u16();                 \
@@ -153,7 +153,7 @@
     ma_alpha_idx,                                             \
     ma_sve_chn_iterator,                                      \
     ...)                                                      \
-    sdl_sve_stride_loop_rgb32(uStride, vTailPred)             \
+    sdl_sve_stride_loop_pixel(uStride, vTailPred)             \
     {                                                         \
                                                               \
         svuint16x4_t vSourceLow16x4 = svundef4_u16();         \