From 2803a8f1644ad9596dcb0bc5f4730ee54830d7d5 Mon Sep 17 00:00:00 2001 From: Bigfoot71 Date: Wed, 18 Mar 2026 21:58:21 +0100 Subject: [PATCH] moves color conversion to math part --- src/external/rlsw.h | 216 ++++++++++++++++++++++---------------------- 1 file changed, 108 insertions(+), 108 deletions(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index 5b75a0c8c..e37b6ca9b 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -1066,7 +1066,7 @@ typedef struct { static sw_context_t RLSW = { 0 }; #if SW_USE_COLOR_LUT -static float SW_LUT_U8_TO_F32[256] = { 0 }; +static float SW_LUT_UINT8_TO_FLOAT[256] = { 0 }; #endif //---------------------------------------------------------------------------------- @@ -1415,6 +1415,100 @@ static inline uint32_t sw_compress_8to3(uint8_t v) { return v >> 5; } static inline uint32_t sw_compress_8to4(uint8_t v) { return v >> 4; } static inline uint32_t sw_compress_8to5(uint8_t v) { return v >> 3; } static inline uint32_t sw_compress_8to6(uint8_t v) { return v >> 2; } + +static inline void sw_color8_to_color(float *SW_RESTRICT dst, const uint8_t *SW_RESTRICT src) +{ +#if defined(SW_HAS_NEON) + uint8x8_t bytes = vreinterpret_u8_u32(vld1_dup_u32((const uint32_t *)src)); + uint16x8_t words = vmovl_u8(bytes); + uint32x4_t dwords = vmovl_u16(vget_low_u16(words)); + float32x4_t fvals = vmulq_f32(vcvtq_f32_u32(dwords), vdupq_n_f32(SW_INV_255)); + vst1q_f32(dst, fvals); + +#elif defined(SW_HAS_SSE41) + __m128i bytes = _mm_loadu_si32(src); + __m128 fvals = _mm_mul_ps(_mm_cvtepi32_ps(_mm_cvtepu8_epi32(bytes)), _mm_set1_ps(SW_INV_255)); + _mm_storeu_ps(dst, fvals); + +#elif defined(SW_HAS_SSE2) + __m128i zero = _mm_setzero_si128(); + __m128i bytes = _mm_loadu_si32(src); + __m128i words = _mm_unpacklo_epi8(bytes, zero); + __m128i dwords = _mm_unpacklo_epi16(words, zero); + __m128 fvals = _mm_mul_ps(_mm_cvtepi32_ps(dwords), _mm_set1_ps(SW_INV_255)); + _mm_storeu_ps(dst, fvals); + +#elif defined(SW_HAS_RVV) + // TODO: WARNING: Sample code generated by AI, needs testing and review + size_t vl = __riscv_vsetvl_e8m1(4); // Set vector length for 8-bit input elements + vuint8m1_t vsrc_u8 = __riscv_vle8_v_u8m1(src, vl); // Load 4 unsigned 8-bit integers + vuint32m1_t vsrc_u32 = __riscv_vwcvt_xu_u_v_u32m1(vsrc_u8, vl); // Widen to 32-bit unsigned integers + vfloat32m1_t vsrc_f32 = __riscv_vfcvt_f_xu_v_f32m1(vsrc_u32, vl); // Convert to float32 + vfloat32m1_t vnorm = __riscv_vfmul_vf_f32m1(vsrc_f32, SW_INV_255, vl); // Multiply by 1/255.0 to normalize + __riscv_vse32_v_f32m1(dst, vnorm, vl); // Store result + +#elif SW_USE_COLOR_LUT + dst[0] = SW_LUT_UINT8_TO_FLOAT[src[0]]; + dst[1] = SW_LUT_UINT8_TO_FLOAT[src[1]]; + dst[2] = SW_LUT_UINT8_TO_FLOAT[src[2]]; + dst[3] = SW_LUT_UINT8_TO_FLOAT[src[3]]; + +#else + dst[0] = (float)src[0]*SW_INV_255; + dst[1] = (float)src[1]*SW_INV_255; + dst[2] = (float)src[2]*SW_INV_255; + dst[3] = (float)src[3]*SW_INV_255; +#endif +} + +static inline void sw_color_to_color8(uint8_t *SW_RESTRICT dst, const float *SW_RESTRICT src) +{ +#if defined(SW_HAS_NEON) + float32x4_t fvals = vmulq_f32(vld1q_f32(src), vdupq_n_f32(255.0f)); + uint32x4_t i32 = vcvtq_u32_f32(fvals); + uint16x4_t i16 = vmovn_u32(i32); + uint8x8_t i8 = vmovn_u16(vcombine_u16(i16, i16)); + vst1_lane_u32((uint32_t *)dst, vreinterpret_u32_u8(i8), 0); + +#elif defined(SW_HAS_SSE41) + __m128 fvals = _mm_mul_ps(_mm_loadu_ps(src), _mm_set1_ps(255.0f)); + __m128i i32 = _mm_cvttps_epi32(fvals); + __m128i i16 = _mm_packus_epi32(i32, i32); + __m128i i8 = _mm_packus_epi16(i16, i16); + _mm_storeu_si32(dst, i8); + +#elif defined(SW_HAS_SSE2) + __m128 fvals = _mm_mul_ps(_mm_loadu_ps(src), _mm_set1_ps(255.0f)); + __m128i i32 = _mm_cvttps_epi32(fvals); + __m128i i16 = _mm_packs_epi32(i32, i32); + __m128i i8 = _mm_packus_epi16(i16, i16); + _mm_storeu_si32(dst, i8); + +#elif defined(SW_HAS_RVV) + // TODO: WARNING: Sample code generated by AI, needs testing and review + // REVIEW: It shouldn't perform so many operations; take inspiration from other versions + // NOTE: RVV 1.0 specs define the use of __riscv_ prefix for instrinsic functions + size_t vl = __riscv_vsetvl_e32m1(4); // Load up to 4 floats into a vector register + vfloat32m1_t vsrc = __riscv_vle32_v_f32m1(src, vl); // Load float32 values + + // Multiply by 255.0f and add 0.5f for rounding + vfloat32m1_t vscaled = __riscv_vfmul_vf_f32m1(vsrc, 255.0f, vl); + vscaled = __riscv_vfadd_vf_f32m1(vscaled, 0.5f, vl); + + // Convert to unsigned integer (truncate toward zero) + vuint32m1_t vu32 = __riscv_vfcvt_xu_f_v_u32m1(vscaled, vl); + + // Narrow from u32 -> u8 + vuint8m1_t vu8 = __riscv_vnclipu_wx_u8m1(vu32, 0, vl); // Round toward zero + __riscv_vse8_v_u8m1(dst, vu8, vl); // Store result + +#else + dst[0] = (uint8_t)(src[0]*255.0f); + dst[1] = (uint8_t)(src[1]*255.0f); + dst[2] = (uint8_t)(src[2]*255.0f); + dst[3] = (uint8_t)(src[3]*255.0f); +#endif +} //------------------------------------------------------------------------------------------- // Object pool functions @@ -1655,100 +1749,6 @@ static inline bool sw_pixel_is_depth_format(sw_pixelformat_t format) return false; } -static inline void sw_pixel_color8_to_color(float *SW_RESTRICT dst, const uint8_t *SW_RESTRICT src) -{ -#if defined(SW_HAS_NEON) - uint8x8_t bytes = vreinterpret_u8_u32(vld1_dup_u32((const uint32_t *)src)); - uint16x8_t words = vmovl_u8(bytes); - uint32x4_t dwords = vmovl_u16(vget_low_u16(words)); - float32x4_t fvals = vmulq_f32(vcvtq_f32_u32(dwords), vdupq_n_f32(SW_INV_255)); - vst1q_f32(dst, fvals); - -#elif defined(SW_HAS_SSE41) - __m128i bytes = _mm_loadu_si32(src); - __m128 fvals = _mm_mul_ps(_mm_cvtepi32_ps(_mm_cvtepu8_epi32(bytes)), _mm_set1_ps(SW_INV_255)); - _mm_storeu_ps(dst, fvals); - -#elif defined(SW_HAS_SSE2) - __m128i zero = _mm_setzero_si128(); - __m128i bytes = _mm_loadu_si32(src); - __m128i words = _mm_unpacklo_epi8(bytes, zero); - __m128i dwords = _mm_unpacklo_epi16(words, zero); - __m128 fvals = _mm_mul_ps(_mm_cvtepi32_ps(dwords), _mm_set1_ps(SW_INV_255)); - _mm_storeu_ps(dst, fvals); - -#elif defined(SW_HAS_RVV) - // TODO: WARNING: Sample code generated by AI, needs testing and review - size_t vl = __riscv_vsetvl_e8m1(4); // Set vector length for 8-bit input elements - vuint8m1_t vsrc_u8 = __riscv_vle8_v_u8m1(src, vl); // Load 4 unsigned 8-bit integers - vuint32m1_t vsrc_u32 = __riscv_vwcvt_xu_u_v_u32m1(vsrc_u8, vl); // Widen to 32-bit unsigned integers - vfloat32m1_t vsrc_f32 = __riscv_vfcvt_f_xu_v_f32m1(vsrc_u32, vl); // Convert to float32 - vfloat32m1_t vnorm = __riscv_vfmul_vf_f32m1(vsrc_f32, SW_INV_255, vl); // Multiply by 1/255.0 to normalize - __riscv_vse32_v_f32m1(dst, vnorm, vl); // Store result - -#elif SW_USE_COLOR_LUT - dst[0] = SW_LUT_U8_TO_F32[src[0]]; - dst[1] = SW_LUT_U8_TO_F32[src[1]]; - dst[2] = SW_LUT_U8_TO_F32[src[2]]; - dst[3] = SW_LUT_U8_TO_F32[src[3]]; - -#else - dst[0] = (float)src[0]*SW_INV_255; - dst[1] = (float)src[1]*SW_INV_255; - dst[2] = (float)src[2]*SW_INV_255; - dst[3] = (float)src[3]*SW_INV_255; -#endif -} - -static inline void sw_pixel_color_to_color8(uint8_t *SW_RESTRICT dst, const float *SW_RESTRICT src) -{ -#if defined(SW_HAS_NEON) - float32x4_t fvals = vmulq_f32(vld1q_f32(src), vdupq_n_f32(255.0f)); - uint32x4_t i32 = vcvtq_u32_f32(fvals); - uint16x4_t i16 = vmovn_u32(i32); - uint8x8_t i8 = vmovn_u16(vcombine_u16(i16, i16)); - vst1_lane_u32((uint32_t *)dst, vreinterpret_u32_u8(i8), 0); - -#elif defined(SW_HAS_SSE41) - __m128 fvals = _mm_mul_ps(_mm_loadu_ps(src), _mm_set1_ps(255.0f)); - __m128i i32 = _mm_cvttps_epi32(fvals); - __m128i i16 = _mm_packus_epi32(i32, i32); - __m128i i8 = _mm_packus_epi16(i16, i16); - _mm_storeu_si32(dst, i8); - -#elif defined(SW_HAS_SSE2) - __m128 fvals = _mm_mul_ps(_mm_loadu_ps(src), _mm_set1_ps(255.0f)); - __m128i i32 = _mm_cvttps_epi32(fvals); - __m128i i16 = _mm_packs_epi32(i32, i32); - __m128i i8 = _mm_packus_epi16(i16, i16); - _mm_storeu_si32(dst, i8); - -#elif defined(SW_HAS_RVV) - // TODO: WARNING: Sample code generated by AI, needs testing and review - // REVIEW: It shouldn't perform so many operations; take inspiration from other versions - // NOTE: RVV 1.0 specs define the use of __riscv_ prefix for instrinsic functions - size_t vl = __riscv_vsetvl_e32m1(4); // Load up to 4 floats into a vector register - vfloat32m1_t vsrc = __riscv_vle32_v_f32m1(src, vl); // Load float32 values - - // Multiply by 255.0f and add 0.5f for rounding - vfloat32m1_t vscaled = __riscv_vfmul_vf_f32m1(vsrc, 255.0f, vl); - vscaled = __riscv_vfadd_vf_f32m1(vscaled, 0.5f, vl); - - // Convert to unsigned integer (truncate toward zero) - vuint32m1_t vu32 = __riscv_vfcvt_xu_f_v_u32m1(vscaled, vl); - - // Narrow from u32 -> u8 - vuint8m1_t vu8 = __riscv_vnclipu_wx_u8m1(vu32, 0, vl); // Round toward zero - __riscv_vse8_v_u8m1(dst, vu8, vl); // Store result - -#else - dst[0] = (uint8_t)(src[0]*255.0f); - dst[1] = (uint8_t)(src[1]*255.0f); - dst[2] = (uint8_t)(src[2]*255.0f); - dst[3] = (uint8_t)(src[3]*255.0f); -#endif -} - static inline void sw_pixel_read_color8_GRAYSCALE(uint8_t *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset) { uint8_t gray = ((const uint8_t *)pixels)[offset]; @@ -2065,40 +2065,40 @@ static inline void sw_pixel_read_color_R3G3B2(float *SW_RESTRICT color, const vo { uint8_t unpack[4]; sw_pixel_read_color8_R3G3B2(unpack, pixels, offset); - sw_pixel_color8_to_color(color, unpack); + sw_color8_to_color(color, unpack); } static inline void sw_pixel_read_color_R5G6B5(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset) { uint8_t unpack[4]; sw_pixel_read_color8_R5G6B5(unpack, pixels, offset); - sw_pixel_color8_to_color(color, unpack); + sw_color8_to_color(color, unpack); } static inline void sw_pixel_read_color_R8G8B8(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset) { uint8_t unpack[4]; sw_pixel_read_color8_R8G8B8(unpack, pixels, offset); - sw_pixel_color8_to_color(color, unpack); + sw_color8_to_color(color, unpack); } static inline void sw_pixel_read_color_R5G5B5A1(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset) { uint8_t unpack[4]; sw_pixel_read_color8_R5G5B5A1(unpack, pixels, offset); - sw_pixel_color8_to_color(color, unpack); + sw_color8_to_color(color, unpack); } static inline void sw_pixel_read_color_R4G4B4A4(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset) { uint8_t unpack[4]; sw_pixel_read_color8_R4G4B4A4(unpack, pixels, offset); - sw_pixel_color8_to_color(color, unpack); + sw_color8_to_color(color, unpack); } static inline void sw_pixel_read_color_R8G8B8A8(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset) { - sw_pixel_color8_to_color(color, &((const uint8_t *)pixels)[offset*4]); + sw_color8_to_color(color, &((const uint8_t *)pixels)[offset*4]); } static inline void sw_pixel_read_color_R32(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset) @@ -2200,41 +2200,41 @@ static inline void sw_pixel_write_color_GRAYALPHA(void *SW_RESTRICT pixels, cons static inline void sw_pixel_write_color_R3G3B2(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset) { uint8_t color8[4]; - sw_pixel_color_to_color8(color8, color); + sw_color_to_color8(color8, color); sw_pixel_write_color8_R3G3B2(pixels, color8, offset); } static inline void sw_pixel_write_color_R5G6B5(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset) { uint8_t color8[4]; - sw_pixel_color_to_color8(color8, color); + sw_color_to_color8(color8, color); sw_pixel_write_color8_R5G6B5(pixels, color8, offset); } static inline void sw_pixel_write_color_R8G8B8(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset) { uint8_t color8[4]; - sw_pixel_color_to_color8(color8, color); + sw_color_to_color8(color8, color); sw_pixel_write_color8_R8G8B8(pixels, color8, offset); } static inline void sw_pixel_write_color_R5G5B5A1(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset) { uint8_t color8[4]; - sw_pixel_color_to_color8(color8, color); + sw_color_to_color8(color8, color); sw_pixel_write_color8_R5G5B5A1(pixels, color8, offset); } static inline void sw_pixel_write_color_R4G4B4A4(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset) { uint8_t color8[4]; - sw_pixel_color_to_color8(color8, color); + sw_color_to_color8(color8, color); sw_pixel_write_color8_R4G4B4A4(pixels, color8, offset); } static inline void sw_pixel_write_color_R8G8B8A8(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset) { - sw_pixel_color_to_color8(&((uint8_t *)pixels)[offset*4], color); + sw_color_to_color8(&((uint8_t *)pixels)[offset*4], color); } static inline void sw_pixel_write_color_R32(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset) @@ -3952,7 +3952,7 @@ bool swInit(int w, int h) RLSW.cullFace = SW_BACK; #if SW_USE_COLOR_LUT - for (int i = 0; i < 256; i++) SW_LUT_U8_TO_F32[i] = (float)i*SW_INV_255; + for (int i = 0; i < 256; i++) SW_LUT_UINT8_TO_FLOAT[i] = (float)i*SW_INV_255; #endif SW_LOG("INFO: RLSW: Software renderer initialized successfully\n");