Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions src_c/collisions.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,10 @@ pgIntersection_LineRect(pgLineBase *line, SDL_Rect *rect, double *X, double *Y,
double *T)
{
#if AVX2_IS_SUPPORTED
return pgIntersection_LineRect_avx2(line, rect, X, Y, T);
#else
if (pg_HasAVX2())
return pgIntersection_LineRect_avx2(line, rect, X, Y, T);
#endif /* ~__AVX2__ */

double x = (double)rect->x;
double y = (double)rect->y;
double w = (double)rect->w;
Expand Down Expand Up @@ -237,15 +239,16 @@ pgIntersection_LineRect(pgLineBase *line, SDL_Rect *rect, double *X, double *Y,
}

return ret;
#endif /* ~__AVX2__ */
}

static int
pgCollision_RectLine(SDL_Rect *rect, pgLineBase *line)
{
#if AVX2_IS_SUPPORTED
return pgCollision_RectLine_avx2(rect, line);
#else
if (pg_HasAVX2())
return pgCollision_RectLine_avx2(rect, line);
#endif /* ~__AVX2__ */

double x = (double)rect->x;
double y = (double)rect->y;
double w = (double)rect->w;
Expand All @@ -258,7 +261,6 @@ pgCollision_RectLine(SDL_Rect *rect, pgLineBase *line)

return pgCollision_LineLine(line, &a) || pgCollision_LineLine(line, &b) ||
pgCollision_LineLine(line, &c) || pgCollision_LineLine(line, &d);
#endif /* ~__AVX2__ */
}

static int
Expand Down Expand Up @@ -361,8 +363,10 @@ static int
pgRaycast_LineRect(pgLineBase *line, SDL_Rect *rect, double max_t, double *T)
{
#if AVX2_IS_SUPPORTED
return pgRaycast_LineRect_avx2(line, rect, max_t, T);
#else
if (pg_HasAVX2())
return pgRaycast_LineRect_avx2(line, rect, max_t, T);
#endif /* ~__AVX2__ */

double x = (double)rect->x;
double y = (double)rect->y;
double w = (double)rect->w;
Expand Down Expand Up @@ -392,7 +396,6 @@ pgRaycast_LineRect(pgLineBase *line, SDL_Rect *rect, double max_t, double *T)
}

return ret;
#endif /* ~__AVX2__ */
}

static int
Expand Down
3 changes: 3 additions & 0 deletions src_c/simd_collisions.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
#endif /* ~defined(__AVX2__) && defined(HAVE_IMMINTRIN_H) && \
!defined(SDL_DISABLE_IMMINTRIN_H) */

PG_FORCEINLINE static int
pg_HasAVX2(void);

#ifdef AVX2_IS_SUPPORTED
PG_FORCEINLINE static int
pgIntersection_LineRect_avx2(pgLineBase *line, SDL_Rect *rect, double *X,
Expand Down
55 changes: 50 additions & 5 deletions src_c/simd_collisions_avx2.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,59 @@
#include "include/pygame.h"
#include "simd_collisions.h"
#include <string.h>

#if defined(_MSC_VER)
#include <intrin.h>
#include <malloc.h>
#endif

#if defined(HAVE_IMMINTRIN_H) && !defined(SDL_DISABLE_IMMINTRIN_H)
#include <immintrin.h>
#endif /* defined(HAVE_IMMINTRIN_H) && !defined(SDL_DISABLE_IMMINTRIN_H) */

PG_FORCEINLINE static int
pg_HasAVX2(void)
{
// The check is cached.
static int has_avx2 = -1;
if (has_avx2 != -1)
return has_avx2;

#if AVX2_IS_SUPPORTED
#if defined(__GNUC__)
// Reference:
// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/X86-Built-in-Functions.html
has_avx2 = __builtin_cpu_supports("avx2");
#elif defined(_MSC_VER)
// Reference:
// https://learn.microsoft.com/en-us/cpp/intrinsics/cpuid-cpuidex?view=msvc-170

int cpu_info[4];
__cpuid(cpu_info, 0);

int info_n = cpu_info[0];
int *data = (int *)_alloca(sizeof(int) * info_n * 4);
// int data[info_n][4];

for (int i = 0; i <= info_n; i++) {
__cpuidex(cpu_info, i, 0);

// memcpy(&data[i], cpu_info, sizeof(int) * 4);
memcpy(data + i * 4, cpu_info, sizeof(int) * 4);
}

// has_avx2 = data[7][1] >> 5 & 1;
has_avx2 = data[7 * 4 + 1] >> 5 & 1;
#else
has_avx2 = 0;
#endif
#else
has_avx2 = 0;
#endif /* ~__AVX2__ */

return has_avx2;
}

#if AVX2_IS_SUPPORTED
PG_FORCEINLINE static int
pgIntersection_LineRect_avx2(pgLineBase *line, SDL_Rect *rect, double *X,
Expand Down Expand Up @@ -97,9 +146,7 @@ pgIntersection_LineRect_avx2(pgLineBase *line, SDL_Rect *rect, double *X,

return 1;
}
#endif /* ~AVX2_IS_SUPPORTED */

#if AVX2_IS_SUPPORTED
PG_FORCEINLINE static int
pgCollision_RectLine_avx2(SDL_Rect *rect, pgLineBase *line)
{
Expand Down Expand Up @@ -168,9 +215,7 @@ pgCollision_RectLine_avx2(SDL_Rect *rect, pgLineBase *line)
// if no lines touch the rectangle then this will be false
return _mm256_movemask_pd(t_u_256d) != 0x0;
}
#endif /* ~AVX2_IS_SUPPORTED */

#if AVX2_IS_SUPPORTED
PG_FORCEINLINE static int
pgRaycast_LineRect_avx2(pgLineBase *line, SDL_Rect *rect, double max_t,
double *T)
Expand Down Expand Up @@ -255,4 +300,4 @@ pgRaycast_LineRect_avx2(pgLineBase *line, SDL_Rect *rect, double max_t,

return 1;
}
#endif /* ~AVX2_IS_SUPPORTED */
#endif /* ~AVX2_IS_SUPPORTED */