review uint8_t <-> float conversion

This commit is contained in:
Bigfoot71 2026-03-15 17:42:42 +01:00
parent f73909a71a
commit 52d4fbaea6

114
src/external/rlsw.h vendored
View File

@ -983,7 +983,7 @@ static inline float sw_fract(float x)
return (x - floorf(x)); return (x - floorf(x));
} }
static inline uint8_t sw_luminancei(const uint8_t *color) static inline uint8_t sw_luminance8(const uint8_t *color)
{ {
return (uint8_t)((color[0]*77 + color[1]*150 + color[2]*29) >> 8); return (uint8_t)((color[0]*77 + color[1]*150 + color[2]*29) >> 8);
} }
@ -1178,7 +1178,6 @@ static inline uint32_t sw_compress_fto3(float v) { return (uint32_t)(v* 7.0f + 0
static inline uint32_t sw_compress_fto4(float v) { return (uint32_t)(v*15.0f + 0.5f) & 0x0F; } static inline uint32_t sw_compress_fto4(float v) { return (uint32_t)(v*15.0f + 0.5f) & 0x0F; }
static inline uint32_t sw_compress_fto5(float v) { return (uint32_t)(v*31.0f + 0.5f) & 0x1F; } static inline uint32_t sw_compress_fto5(float v) { return (uint32_t)(v*31.0f + 0.5f) & 0x1F; }
static inline uint32_t sw_compress_fto6(float v) { return (uint32_t)(v*63.0f + 0.5f) & 0x3F; } static inline uint32_t sw_compress_fto6(float v) { return (uint32_t)(v*63.0f + 0.5f) & 0x3F; }
static inline uint32_t sw_compress_fto8(float v) { return (uint32_t)(v*255.0f); }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
@ -1452,13 +1451,13 @@ static inline void sw_pixel_get_color8(uint8_t *SW_RESTRICT color, const void *S
static inline void sw_pixel_set_color8_GRAYSCALE(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset) static inline void sw_pixel_set_color8_GRAYSCALE(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
{ {
((uint8_t*)pixels)[offset] = sw_luminancei(color); ((uint8_t*)pixels)[offset] = sw_luminance8(color);
} }
static inline void sw_pixel_set_color8_GRAYALPHA(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset) static inline void sw_pixel_set_color8_GRAYALPHA(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
{ {
uint8_t *dst = &((uint8_t*)pixels)[offset*2]; uint8_t *dst = &((uint8_t*)pixels)[offset*2];
dst[0] = sw_luminancei(color); dst[0] = sw_luminance8(color);
dst[1] = color[3]; dst[1] = color[3];
} }
@ -1515,7 +1514,7 @@ static inline void sw_pixel_set_color8_R8G8B8A8(void *SW_RESTRICT pixels, const
static inline void sw_pixel_set_color8_R32(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset) static inline void sw_pixel_set_color8_R32(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
{ {
((float*)pixels)[offset] = sw_luminancei(color)*SW_INV_255; ((float*)pixels)[offset] = sw_luminance8(color)*SW_INV_255;
} }
static inline void sw_pixel_set_color8_R32G32B32(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset) static inline void sw_pixel_set_color8_R32G32B32(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
@ -1537,7 +1536,7 @@ static inline void sw_pixel_set_color8_R32G32B32A32(void *SW_RESTRICT pixels, co
static inline void sw_pixel_set_color8_R16(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset) static inline void sw_pixel_set_color8_R16(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
{ {
((uint16_t*)pixels)[offset] = sw_float_to_half(sw_luminancei(color)*SW_INV_255); ((uint16_t*)pixels)[offset] = sw_float_to_half(sw_luminance8(color)*SW_INV_255);
} }
static inline void sw_pixel_set_color8_R16G16B16(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset) static inline void sw_pixel_set_color8_R16G16B16(void *SW_RESTRICT pixels, const uint8_t *SW_RESTRICT color, uint32_t offset)
@ -1680,10 +1679,42 @@ static inline void sw_pixel_get_color_R4G4B4A4(float *SW_RESTRICT color, const v
static inline void sw_pixel_get_color_R8G8B8A8(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset) static inline void sw_pixel_get_color_R8G8B8A8(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
{ {
const uint8_t *src = &((const uint8_t*)pixels)[offset*4]; const uint8_t *src = &((const uint8_t*)pixels)[offset*4];
color[0] = src[0]*SW_INV_255;
color[1] = src[1]*SW_INV_255; #if defined(SW_HAS_NEON)
color[2] = src[2]*SW_INV_255; uint32_t tmp = (uint32_t)src[0] | ((uint32_t)src[1] << 8) | ((uint32_t)src[2] << 16) | ((uint32_t)src[3] << 24);
color[3] = src[3]*SW_INV_255; uint8x8_t bytes = vreinterpret_u8_u32(vdup_n_u32(tmp));
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(color, 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(color, fvals);
#elif defined(SW_HAS_SSE2)
__m128i bytes = _mm_loadu_si32(src);
__m128i words = _mm_unpacklo_epi8(bytes, _mm_setzero_si128());
__m128i dwords = _mm_unpacklo_epi16(words, _mm_setzero_si128());
__m128 fvals = _mm_mul_ps(_mm_cvtepi32_ps(dwords), _mm_set1_ps(SW_INV_255));
_mm_storeu_ps(color, fvals);
#elif defined(SW_HAS_RVV)
// TODO: 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(color, vnorm, vl); // Store result
#else
color[0] = (float)src[0]*SW_INV_255;
color[1] = (float)src[1]*SW_INV_255;
color[2] = (float)src[2]*SW_INV_255;
color[3] = (float)src[3]*SW_INV_255;
#endif
} }
static inline void sw_pixel_get_color_R32(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset) static inline void sw_pixel_get_color_R32(float *SW_RESTRICT color, const void *SW_RESTRICT pixels, uint32_t offset)
@ -1811,7 +1842,7 @@ static inline void sw_pixel_set_color_GRAYALPHA(void *SW_RESTRICT pixels, const
{ {
uint8_t *dst = &((uint8_t*)pixels)[offset*2]; uint8_t *dst = &((uint8_t*)pixels)[offset*2];
dst[0] = (uint8_t)(sw_luminance(color)*255.0f); dst[0] = (uint8_t)(sw_luminance(color)*255.0f);
dst[1] = sw_compress_fto8(color[3]); dst[1] = (uint8_t)(color[3]*255.0f);
} }
static inline void sw_pixel_set_color_R3G3B2(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset) static inline void sw_pixel_set_color_R3G3B2(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset)
@ -1833,9 +1864,9 @@ static inline void sw_pixel_set_color_R5G6B5(void *SW_RESTRICT pixels, const flo
static inline void sw_pixel_set_color_R8G8B8(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset) static inline void sw_pixel_set_color_R8G8B8(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset)
{ {
uint8_t *dst = &((uint8_t*)pixels)[offset*3]; uint8_t *dst = &((uint8_t*)pixels)[offset*3];
dst[0] = sw_compress_fto8(color[0]); dst[0] = (uint8_t)(color[0]*255.0f);
dst[1] = sw_compress_fto8(color[1]); dst[1] = (uint8_t)(color[1]*255.0f);
dst[2] = sw_compress_fto8(color[2]); dst[2] = (uint8_t)(color[2]*255.0f);
} }
static inline void sw_pixel_set_color_R5G5B5A1(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset) static inline void sw_pixel_set_color_R5G5B5A1(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset)
@ -1859,10 +1890,55 @@ static inline void sw_pixel_set_color_R4G4B4A4(void *SW_RESTRICT pixels, const f
static inline void sw_pixel_set_color_R8G8B8A8(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset) static inline void sw_pixel_set_color_R8G8B8A8(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset)
{ {
uint8_t *dst = &((uint8_t*)pixels)[offset*4]; uint8_t *dst = &((uint8_t*)pixels)[offset*4];
dst[0] = sw_compress_fto8(color[0]);
dst[1] = sw_compress_fto8(color[1]); #if defined(SW_HAS_NEON)
dst[2] = sw_compress_fto8(color[2]); float32x4_t fvals = vmulq_f32(vld1q_f32(color), vdupq_n_f32(255.0f));
dst[3] = sw_compress_fto8(color[3]); uint32x4_t i32 = vcvtq_u32_f32(fvals);
uint16x4_t i16 = vmovn_u32(i32);
uint8x8_t i8 = vmovn_u16(vcombine_u16(i16, i16));
dst[0] = vget_lane_u8(i8, 0);
dst[1] = vget_lane_u8(i8, 1);
dst[2] = vget_lane_u8(i8, 2);
dst[3] = vget_lane_u8(i8, 3);
#elif defined(SW_HAS_SSE41)
__m128 fvals = _mm_mul_ps(_mm_loadu_ps(color), _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(color), _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: 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)(color[0]*255.0f);
dst[1] = (uint8_t)(color[1]*255.0f);
dst[2] = (uint8_t)(color[2]*255.0f);
dst[3] = (uint8_t)(color[3]*255.0f);
#endif
} }
static inline void sw_pixel_set_color_R32(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset) static inline void sw_pixel_set_color_R32(void *SW_RESTRICT pixels, const float *SW_RESTRICT color, uint32_t offset)
@ -2680,7 +2756,7 @@ static void sw_triangle_clip_and_project(void)
#define DEFINE_TRIANGLE_RASTER_SCANLINE(FUNC_NAME, ENABLE_TEXTURE, ENABLE_DEPTH_TEST, ENABLE_COLOR_BLEND) \ #define DEFINE_TRIANGLE_RASTER_SCANLINE(FUNC_NAME, ENABLE_TEXTURE, ENABLE_DEPTH_TEST, ENABLE_COLOR_BLEND) \
static void FUNC_NAME(const sw_texture_t *tex, const sw_vertex_t *start, \ static void FUNC_NAME(const sw_texture_t *tex, const sw_vertex_t *start, \
const sw_vertex_t *end, float dUdy, float dVdy) \ const sw_vertex_t *end, float dUdy, float dVdy) \
{ \ { \
/* Gets the start and end coordinates */ \ /* Gets the start and end coordinates */ \
int xStart = (int)start->screen[0]; \ int xStart = (int)start->screen[0]; \