Skip to content

Commit 500dce0

Browse files
authored
Port SDL_cpuinfo.h (#2308)
* Add `get_cpu_instruction_sets` Add `get_cpu_count` Add `get_cpu_cache_line_size` Add `get_system_ram` * format * Return False instead of None * add docs * remove unused variables * fix typo * Remove `get_cpu_count()` Remove `get_cpu_cache_line_size()` * add tests * update docs * get_system_ram -> get_total_ram * fix docs
1 parent ecdf468 commit 500dce0

File tree

5 files changed

+150
-0
lines changed

5 files changed

+150
-0
lines changed

buildconfig/stubs/pygame/system.pyi

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,29 @@ from typing import List, Optional
22

33
from typing_extensions import TypedDict
44

5+
class _InstructionSets(TypedDict):
6+
RDTSC: bool
7+
ALTIVEC: bool
8+
MMX: bool
9+
SSE: bool
10+
SSE2: bool
11+
SSE3: bool
12+
SSE41: bool
13+
SSE42: bool
14+
AVX: bool
15+
AVX2: bool
16+
AVX512F: bool
17+
NEON: bool
18+
ARMSIMD: bool
19+
LSX: bool
20+
LASX: bool
21+
522
# dict at runtime, TypedDict exists solely for the typechecking benefits
623
class _Locale(TypedDict):
724
language: str
825
country: Optional[str]
926

27+
def get_cpu_instruction_sets() -> _InstructionSets: ...
28+
def get_total_ram() -> int: ...
1029
def get_pref_path(org: str, app: str) -> str: ...
1130
def get_pref_locales() -> List[_Locale]: ...

docs/reST/ref/system.rst

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,57 @@ open just in case something obvious comes up.
1616

1717
.. versionadded:: 2.2.0
1818

19+
.. function:: get_cpu_instruction_sets
20+
21+
| :sl:`get the information of CPU instruction sets`
22+
| :sg:`get_cpu_instruction_sets() -> instruction_sets`
23+
24+
Returns a dict of the information of CPU instruction sets. The keys of
25+
the dict are the names of instruction sets and the values determine
26+
whether the instruction set is available.
27+
28+
Some of functions like ``Surface.blit`` can be accelerated by SIMD
29+
instruction sets like SSE2 or AVX2. By checking the availability of
30+
instruction sets, you can check if these accelerations are available.
31+
32+
Here is an example of the returned dict
33+
::
34+
35+
{
36+
'RDTSC': True,
37+
'ALTIVEC': False,
38+
'MMX': True,
39+
'SSE': True,
40+
'SSE2': True,
41+
'SSE3': True,
42+
'SSE41': True,
43+
'SSE42': True,
44+
'AVX': True,
45+
'AVX2': True,
46+
'AVX512F': False,
47+
'NEON': False,
48+
'ARMSIMD': False,
49+
'LSX': False,
50+
'LASX': False
51+
}
52+
53+
.. Note:: The value of ``ARMSIMD`` will be always False if
54+
SDL version < 2.0.12.
55+
56+
The values of ``LSX`` and ``LASX`` will be always False if
57+
SDL version < 2.24.0.
58+
59+
.. versionadded:: 2.3.1
60+
61+
.. function:: get_total_ram
62+
63+
| :sl:`get the amount of RAM configured in the system`
64+
| :sg:`get_total_ram() -> ram_size`
65+
66+
Returns the amount of RAM configured in the system in MiB.
67+
68+
.. versionadded:: 2.3.1
69+
1970
.. function:: get_pref_path
2071

2172
| :sl:`get a writeable folder for your app`

src_c/doc/system_doc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
/* Auto generated file: with makeref.py . Docs go in docs/reST/ref/ . */
22
#define DOC_SYSTEM "pygame module to provide additional context about the system"
3+
#define DOC_SYSTEM_GETCPUINSTRUCTIONSETS "get_cpu_instruction_sets() -> instruction_sets\nget the information of CPU instruction sets"
4+
#define DOC_SYSTEM_GETTOTALRAM "get_total_ram() -> ram_size\nget the amount of RAM configured in the system"
35
#define DOC_SYSTEM_GETPREFPATH "get_pref_path(org, app) -> path\nget a writeable folder for your app"
46
#define DOC_SYSTEM_GETPREFLOCALES "get_pref_locales() -> list[locale]\nget preferred locales set on the system"

src_c/system.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,68 @@
44

55
#include "doc/system_doc.h"
66

7+
static PyObject *
8+
pg_system_get_cpu_instruction_sets(PyObject *self, PyObject *_null)
9+
{
10+
PyObject *tmp_bool = NULL;
11+
PyObject *instruction_sets = NULL;
12+
13+
instruction_sets = PyDict_New();
14+
if (!instruction_sets) {
15+
goto error;
16+
}
17+
18+
#define INSERT_INSTRUCTIONSET_INFO(name, SDL_fn_name) \
19+
tmp_bool = PyBool_FromLong((SDL_fn_name)()); \
20+
if (PyDict_SetItemString(instruction_sets, (name), tmp_bool)) { \
21+
Py_DECREF(tmp_bool); \
22+
goto error; \
23+
} \
24+
Py_DECREF(tmp_bool);
25+
26+
INSERT_INSTRUCTIONSET_INFO("RDTSC", SDL_HasRDTSC);
27+
INSERT_INSTRUCTIONSET_INFO("ALTIVEC", SDL_HasAltiVec);
28+
INSERT_INSTRUCTIONSET_INFO("MMX", SDL_HasMMX);
29+
INSERT_INSTRUCTIONSET_INFO("SSE", SDL_HasSSE);
30+
INSERT_INSTRUCTIONSET_INFO("SSE2", SDL_HasSSE2);
31+
INSERT_INSTRUCTIONSET_INFO("SSE3", SDL_HasSSE3);
32+
INSERT_INSTRUCTIONSET_INFO("SSE41", SDL_HasSSE41);
33+
INSERT_INSTRUCTIONSET_INFO("SSE42", SDL_HasSSE42);
34+
INSERT_INSTRUCTIONSET_INFO("AVX", SDL_HasAVX);
35+
INSERT_INSTRUCTIONSET_INFO("AVX2", SDL_HasAVX2);
36+
INSERT_INSTRUCTIONSET_INFO("AVX512F", SDL_HasAVX512F);
37+
INSERT_INSTRUCTIONSET_INFO("NEON", SDL_HasNEON);
38+
#if SDL_VERSION_ATLEAST(2, 0, 12)
39+
INSERT_INSTRUCTIONSET_INFO("ARMSIMD", SDL_HasARMSIMD);
40+
#else
41+
if (PyDict_SetItemString(instruction_sets, "ARMSIMD", Py_False))
42+
goto error;
43+
#endif
44+
#if SDL_VERSION_ATLEAST(2, 24, 0)
45+
INSERT_INSTRUCTIONSET_INFO("LSX", SDL_HasLSX);
46+
INSERT_INSTRUCTIONSET_INFO("LASX", SDL_HasLASX);
47+
#else
48+
if (PyDict_SetItemString(instruction_sets, "LSX", Py_False))
49+
goto error;
50+
if (PyDict_SetItemString(instruction_sets, "LASX", Py_False))
51+
goto error;
52+
#endif
53+
54+
#undef INSERT_INSTRUCTIONSET_INFO
55+
56+
return instruction_sets;
57+
58+
error:
59+
Py_XDECREF(instruction_sets);
60+
return NULL;
61+
}
62+
63+
static PyObject *
64+
pg_system_get_total_ram(PyObject *self, PyObject *_null)
65+
{
66+
return PyLong_FromLong(SDL_GetSystemRAM());
67+
}
68+
769
static PyObject *
870
pg_system_get_pref_path(PyObject *self, PyObject *args, PyObject *kwargs)
971
{
@@ -100,6 +162,10 @@ pg_system_get_pref_locales(PyObject *self, PyObject *_null)
100162
}
101163

102164
static PyMethodDef _system_methods[] = {
165+
{"get_cpu_instruction_sets", pg_system_get_cpu_instruction_sets,
166+
METH_NOARGS, DOC_SYSTEM_GETCPUINSTRUCTIONSETS},
167+
{"get_total_ram", pg_system_get_total_ram, METH_NOARGS,
168+
DOC_SYSTEM_GETTOTALRAM},
103169
{"get_pref_path", (PyCFunction)pg_system_get_pref_path,
104170
METH_VARARGS | METH_KEYWORDS, DOC_SYSTEM_GETPREFPATH},
105171
{"get_pref_locales", pg_system_get_pref_locales, METH_NOARGS,

test/system_test.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@
55

66

77
class SystemModuleTest(unittest.TestCase):
8+
def test_get_cpu_instruction_sets(self):
9+
instruction_sets = pygame.system.get_cpu_instruction_sets()
10+
11+
for name in instruction_sets:
12+
self.assertIsInstance(name, str)
13+
self.assertIsInstance(instruction_sets[name], bool)
14+
15+
def test_get_total_ram(self):
16+
ram = pygame.system.get_total_ram()
17+
18+
self.assertIsInstance(ram, int)
19+
820
def test_get_pref_path(self):
921
get_pref_path = pygame.system.get_pref_path
1022

0 commit comments

Comments
 (0)