gstaichi 0.1.18.dev1__cp310-cp310-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools/cmake/SPIRV-ToolsConfig.cmake +5 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools/cmake/SPIRV-ToolsTarget-release.cmake +29 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools/cmake/SPIRV-ToolsTarget.cmake +113 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-diff/cmake/SPIRV-Tools-diffConfig.cmake +5 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-diff/cmake/SPIRV-Tools-diffTargets-release.cmake +19 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-diff/cmake/SPIRV-Tools-diffTargets.cmake +122 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-link/cmake/SPIRV-Tools-linkConfig.cmake +5 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-link/cmake/SPIRV-Tools-linkTargets-release.cmake +19 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-link/cmake/SPIRV-Tools-linkTargets.cmake +122 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-lint/cmake/SPIRV-Tools-lintConfig.cmake +5 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-lint/cmake/SPIRV-Tools-lintTargets-release.cmake +19 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-lint/cmake/SPIRV-Tools-lintTargets.cmake +122 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-opt/cmake/SPIRV-Tools-optConfig.cmake +5 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-opt/cmake/SPIRV-Tools-optTargets-release.cmake +19 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-opt/cmake/SPIRV-Tools-optTargets.cmake +122 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-reduce/cmake/SPIRV-Tools-reduceConfig.cmake +5 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-reduce/cmake/SPIRV-Tools-reduceTarget-release.cmake +19 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-reduce/cmake/SPIRV-Tools-reduceTarget.cmake +122 -0
- gstaichi-0.1.18.dev1.data/data/bin/SPIRV-Tools-shared.dll +0 -0
- gstaichi-0.1.18.dev1.data/data/include/GLFW/glfw3.h +6389 -0
- gstaichi-0.1.18.dev1.data/data/include/GLFW/glfw3native.h +594 -0
- gstaichi-0.1.18.dev1.data/data/include/spirv-tools/instrument.hpp +268 -0
- gstaichi-0.1.18.dev1.data/data/include/spirv-tools/libspirv.h +907 -0
- gstaichi-0.1.18.dev1.data/data/include/spirv-tools/libspirv.hpp +375 -0
- gstaichi-0.1.18.dev1.data/data/include/spirv-tools/linker.hpp +97 -0
- gstaichi-0.1.18.dev1.data/data/include/spirv-tools/optimizer.hpp +970 -0
- gstaichi-0.1.18.dev1.data/data/lib/SPIRV-Tools-diff.lib +0 -0
- gstaichi-0.1.18.dev1.data/data/lib/SPIRV-Tools-link.lib +0 -0
- gstaichi-0.1.18.dev1.data/data/lib/SPIRV-Tools-lint.lib +0 -0
- gstaichi-0.1.18.dev1.data/data/lib/SPIRV-Tools-opt.lib +0 -0
- gstaichi-0.1.18.dev1.data/data/lib/SPIRV-Tools-reduce.lib +0 -0
- gstaichi-0.1.18.dev1.data/data/lib/SPIRV-Tools-shared.lib +0 -0
- gstaichi-0.1.18.dev1.data/data/lib/SPIRV-Tools.lib +0 -0
- gstaichi-0.1.18.dev1.data/data/lib/cmake/glfw3/glfw3Config.cmake +3 -0
- gstaichi-0.1.18.dev1.data/data/lib/cmake/glfw3/glfw3ConfigVersion.cmake +65 -0
- gstaichi-0.1.18.dev1.data/data/lib/cmake/glfw3/glfw3Targets-release.cmake +19 -0
- gstaichi-0.1.18.dev1.data/data/lib/cmake/glfw3/glfw3Targets.cmake +107 -0
- gstaichi-0.1.18.dev1.data/data/lib/glfw3.lib +0 -0
- gstaichi-0.1.18.dev1.dist-info/METADATA +108 -0
- gstaichi-0.1.18.dev1.dist-info/RECORD +198 -0
- gstaichi-0.1.18.dev1.dist-info/WHEEL +5 -0
- gstaichi-0.1.18.dev1.dist-info/entry_points.txt +2 -0
- gstaichi-0.1.18.dev1.dist-info/licenses/LICENSE +201 -0
- gstaichi-0.1.18.dev1.dist-info/top_level.txt +1 -0
- taichi/CHANGELOG.md +15 -0
- taichi/__init__.py +44 -0
- taichi/__main__.py +5 -0
- taichi/_funcs.py +706 -0
- taichi/_kernels.py +420 -0
- taichi/_lib/__init__.py +3 -0
- taichi/_lib/c_api/bin/taichi_c_api.dll +0 -0
- taichi/_lib/c_api/include/taichi/cpp/taichi.hpp +1401 -0
- taichi/_lib/c_api/include/taichi/taichi.h +29 -0
- taichi/_lib/c_api/include/taichi/taichi_core.h +1111 -0
- taichi/_lib/c_api/include/taichi/taichi_cpu.h +29 -0
- taichi/_lib/c_api/include/taichi/taichi_cuda.h +36 -0
- taichi/_lib/c_api/include/taichi/taichi_platform.h +55 -0
- taichi/_lib/c_api/include/taichi/taichi_unity.h +64 -0
- taichi/_lib/c_api/include/taichi/taichi_vulkan.h +151 -0
- taichi/_lib/c_api/lib/taichi_c_api.lib +0 -0
- taichi/_lib/c_api/runtime/runtime_cuda.bc +0 -0
- taichi/_lib/c_api/runtime/runtime_x64.bc +0 -0
- taichi/_lib/c_api/runtime/slim_libdevice.10.bc +0 -0
- taichi/_lib/c_api/taichi/lib/cmake/taichi/TaichiConfig.cmake +29 -0
- taichi/_lib/c_api/taichi/lib/cmake/taichi/TaichiConfigVersion.cmake +65 -0
- taichi/_lib/c_api/taichi/lib/cmake/taichi/TaichiTargets.cmake +121 -0
- taichi/_lib/core/__init__.py +0 -0
- taichi/_lib/core/py.typed +0 -0
- taichi/_lib/core/taichi_python.cp310-win_amd64.pyd +0 -0
- taichi/_lib/core/taichi_python.pyi +3077 -0
- taichi/_lib/runtime/runtime_cuda.bc +0 -0
- taichi/_lib/runtime/runtime_x64.bc +0 -0
- taichi/_lib/runtime/slim_libdevice.10.bc +0 -0
- taichi/_lib/utils.py +249 -0
- taichi/_logging.py +131 -0
- taichi/_main.py +552 -0
- taichi/_snode/__init__.py +5 -0
- taichi/_snode/fields_builder.py +189 -0
- taichi/_snode/snode_tree.py +34 -0
- taichi/_ti_module/__init__.py +3 -0
- taichi/_ti_module/cppgen.py +309 -0
- taichi/_ti_module/module.py +145 -0
- taichi/_version.py +1 -0
- taichi/_version_check.py +100 -0
- taichi/ad/__init__.py +3 -0
- taichi/ad/_ad.py +530 -0
- taichi/algorithms/__init__.py +3 -0
- taichi/algorithms/_algorithms.py +117 -0
- taichi/aot/__init__.py +12 -0
- taichi/aot/_export.py +28 -0
- taichi/aot/conventions/__init__.py +3 -0
- taichi/aot/conventions/gfxruntime140/__init__.py +38 -0
- taichi/aot/conventions/gfxruntime140/dr.py +244 -0
- taichi/aot/conventions/gfxruntime140/sr.py +613 -0
- taichi/aot/module.py +253 -0
- taichi/aot/utils.py +151 -0
- taichi/assets/.git +1 -0
- taichi/assets/Go-Regular.ttf +0 -0
- taichi/assets/static/imgs/ti_gallery.png +0 -0
- taichi/examples/minimal.py +28 -0
- taichi/experimental.py +16 -0
- taichi/graph/__init__.py +3 -0
- taichi/graph/_graph.py +292 -0
- taichi/lang/__init__.py +50 -0
- taichi/lang/_ndarray.py +348 -0
- taichi/lang/_ndrange.py +152 -0
- taichi/lang/_texture.py +172 -0
- taichi/lang/_wrap_inspect.py +189 -0
- taichi/lang/any_array.py +99 -0
- taichi/lang/argpack.py +411 -0
- taichi/lang/ast/__init__.py +5 -0
- taichi/lang/ast/ast_transformer.py +1806 -0
- taichi/lang/ast/ast_transformer_utils.py +328 -0
- taichi/lang/ast/checkers.py +106 -0
- taichi/lang/ast/symbol_resolver.py +57 -0
- taichi/lang/ast/transform.py +9 -0
- taichi/lang/common_ops.py +310 -0
- taichi/lang/exception.py +80 -0
- taichi/lang/expr.py +180 -0
- taichi/lang/field.py +464 -0
- taichi/lang/impl.py +1246 -0
- taichi/lang/kernel_arguments.py +157 -0
- taichi/lang/kernel_impl.py +1415 -0
- taichi/lang/matrix.py +1877 -0
- taichi/lang/matrix_ops.py +341 -0
- taichi/lang/matrix_ops_utils.py +190 -0
- taichi/lang/mesh.py +687 -0
- taichi/lang/misc.py +807 -0
- taichi/lang/ops.py +1489 -0
- taichi/lang/runtime_ops.py +13 -0
- taichi/lang/shell.py +35 -0
- taichi/lang/simt/__init__.py +5 -0
- taichi/lang/simt/block.py +94 -0
- taichi/lang/simt/grid.py +7 -0
- taichi/lang/simt/subgroup.py +191 -0
- taichi/lang/simt/warp.py +96 -0
- taichi/lang/snode.py +487 -0
- taichi/lang/source_builder.py +150 -0
- taichi/lang/struct.py +855 -0
- taichi/lang/util.py +381 -0
- taichi/linalg/__init__.py +8 -0
- taichi/linalg/matrixfree_cg.py +310 -0
- taichi/linalg/sparse_cg.py +59 -0
- taichi/linalg/sparse_matrix.py +303 -0
- taichi/linalg/sparse_solver.py +123 -0
- taichi/math/__init__.py +11 -0
- taichi/math/_complex.py +204 -0
- taichi/math/mathimpl.py +886 -0
- taichi/profiler/__init__.py +6 -0
- taichi/profiler/kernel_metrics.py +260 -0
- taichi/profiler/kernel_profiler.py +592 -0
- taichi/profiler/memory_profiler.py +15 -0
- taichi/profiler/scoped_profiler.py +36 -0
- taichi/shaders/Circles_vk.frag +29 -0
- taichi/shaders/Circles_vk.vert +45 -0
- taichi/shaders/Circles_vk_frag.spv +0 -0
- taichi/shaders/Circles_vk_vert.spv +0 -0
- taichi/shaders/Lines_vk.frag +9 -0
- taichi/shaders/Lines_vk.vert +11 -0
- taichi/shaders/Lines_vk_frag.spv +0 -0
- taichi/shaders/Lines_vk_vert.spv +0 -0
- taichi/shaders/Mesh_vk.frag +71 -0
- taichi/shaders/Mesh_vk.vert +68 -0
- taichi/shaders/Mesh_vk_frag.spv +0 -0
- taichi/shaders/Mesh_vk_vert.spv +0 -0
- taichi/shaders/Particles_vk.frag +95 -0
- taichi/shaders/Particles_vk.vert +73 -0
- taichi/shaders/Particles_vk_frag.spv +0 -0
- taichi/shaders/Particles_vk_vert.spv +0 -0
- taichi/shaders/SceneLines2quad_vk_comp.spv +0 -0
- taichi/shaders/SceneLines_vk.frag +9 -0
- taichi/shaders/SceneLines_vk.vert +12 -0
- taichi/shaders/SceneLines_vk_frag.spv +0 -0
- taichi/shaders/SceneLines_vk_vert.spv +0 -0
- taichi/shaders/SetImage_vk.frag +21 -0
- taichi/shaders/SetImage_vk.vert +15 -0
- taichi/shaders/SetImage_vk_frag.spv +0 -0
- taichi/shaders/SetImage_vk_vert.spv +0 -0
- taichi/shaders/Triangles_vk.frag +16 -0
- taichi/shaders/Triangles_vk.vert +29 -0
- taichi/shaders/Triangles_vk_frag.spv +0 -0
- taichi/shaders/Triangles_vk_vert.spv +0 -0
- taichi/shaders/lines2quad_vk_comp.spv +0 -0
- taichi/sparse/__init__.py +3 -0
- taichi/sparse/_sparse_grid.py +77 -0
- taichi/tools/__init__.py +12 -0
- taichi/tools/diagnose.py +124 -0
- taichi/tools/np2ply.py +364 -0
- taichi/tools/vtk.py +38 -0
- taichi/types/__init__.py +19 -0
- taichi/types/annotations.py +47 -0
- taichi/types/compound_types.py +90 -0
- taichi/types/enums.py +49 -0
- taichi/types/ndarray_type.py +147 -0
- taichi/types/primitive_types.py +203 -0
- taichi/types/quant.py +88 -0
- taichi/types/texture_type.py +85 -0
- taichi/types/utils.py +13 -0
taichi/lang/_ndrange.py
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
# type: ignore
|
2
|
+
|
3
|
+
import collections.abc
|
4
|
+
from typing import Iterable
|
5
|
+
|
6
|
+
import numpy as np
|
7
|
+
|
8
|
+
from taichi.lang import ops
|
9
|
+
from taichi.lang.exception import TaichiSyntaxError, TaichiTypeError
|
10
|
+
from taichi.lang.expr import Expr
|
11
|
+
from taichi.lang.matrix import Matrix
|
12
|
+
from taichi.types.utils import is_integral
|
13
|
+
|
14
|
+
|
15
|
+
class _Ndrange:
|
16
|
+
def __init__(self, *args):
|
17
|
+
args = list(args)
|
18
|
+
for i, arg in enumerate(args):
|
19
|
+
if not isinstance(arg, collections.abc.Sequence):
|
20
|
+
args[i] = (0, arg)
|
21
|
+
if len(args[i]) != 2:
|
22
|
+
raise TaichiSyntaxError(
|
23
|
+
"Every argument of ndrange should be a scalar or a tuple/list like (begin, end)"
|
24
|
+
)
|
25
|
+
args[i] = (args[i][0], ops.max(args[i][0], args[i][1]))
|
26
|
+
for arg in args:
|
27
|
+
for bound in arg:
|
28
|
+
if not isinstance(bound, (int, np.integer)) and not (
|
29
|
+
isinstance(bound, Expr) and is_integral(bound.ptr.get_rvalue_type())
|
30
|
+
):
|
31
|
+
raise TaichiTypeError(
|
32
|
+
"Every argument of ndrange should be an integer scalar or a tuple/list of (int, int)"
|
33
|
+
)
|
34
|
+
self.bounds = args
|
35
|
+
|
36
|
+
self.dimensions = [None] * len(args)
|
37
|
+
for i, bound in enumerate(self.bounds):
|
38
|
+
self.dimensions[i] = bound[1] - bound[0]
|
39
|
+
|
40
|
+
self.acc_dimensions = self.dimensions.copy()
|
41
|
+
for i in reversed(range(len(self.bounds) - 1)):
|
42
|
+
self.acc_dimensions[i] = self.acc_dimensions[i] * self.acc_dimensions[i + 1]
|
43
|
+
if len(self.acc_dimensions) == 0: # for the empty case, e.g. ti.ndrange()
|
44
|
+
self.acc_dimensions = [1]
|
45
|
+
|
46
|
+
def __iter__(self):
|
47
|
+
def gen(d, prefix):
|
48
|
+
if d == len(self.bounds):
|
49
|
+
yield prefix
|
50
|
+
else:
|
51
|
+
for t in range(self.bounds[d][0], self.bounds[d][1]):
|
52
|
+
yield from gen(d + 1, prefix + (t,))
|
53
|
+
|
54
|
+
yield from gen(0, ())
|
55
|
+
|
56
|
+
def grouped(self):
|
57
|
+
return GroupedNDRange(self)
|
58
|
+
|
59
|
+
|
60
|
+
def ndrange(*args) -> Iterable:
|
61
|
+
"""Return an immutable iterator object for looping over multi-dimensional indices.
|
62
|
+
|
63
|
+
This returned set of multi-dimensional indices is the direct product (in the set-theory sense)
|
64
|
+
of n groups of integers, where n equals the number of arguments in the input list, and looks like
|
65
|
+
|
66
|
+
range(x1, y1) x range(x2, y2) x ... x range(xn, yn)
|
67
|
+
|
68
|
+
The k-th argument corresponds to the k-th `range()` factor in the above product, and each
|
69
|
+
argument must be an integer or a pair of two integers. An integer argument n will be interpreted
|
70
|
+
as `range(0, n)`, and a pair of two integers (start, end) will be interpreted as `range(start, end)`.
|
71
|
+
|
72
|
+
You can loop over these multi-dimensonal indices in different ways, see the examples below.
|
73
|
+
|
74
|
+
Args:
|
75
|
+
entries: (int, tuple): Must be either an integer, or a tuple/list of two integers.
|
76
|
+
|
77
|
+
Returns:
|
78
|
+
An immutable iterator object.
|
79
|
+
|
80
|
+
Example::
|
81
|
+
|
82
|
+
You can loop over 1-D integers in range [start, end), as in native Python
|
83
|
+
|
84
|
+
>>> @ti.kernel
|
85
|
+
>>> def loop_1d():
|
86
|
+
>>> start = 2
|
87
|
+
>>> end = 5
|
88
|
+
>>> for i in ti.ndrange((start, end)):
|
89
|
+
>>> print(i) # will print 2 3 4
|
90
|
+
|
91
|
+
Note the braces around `(start, end)` in the above code. If without them,
|
92
|
+
the parameter `2` will be interpreted as `range(0, 2)`, `5` will be
|
93
|
+
interpreted as `range(0, 5)`, and you will get a set of 2-D indices which
|
94
|
+
contains 2x5=10 elements, and need two indices i, j to loop over them:
|
95
|
+
|
96
|
+
>>> @ti.kernel
|
97
|
+
>>> def loop_2d():
|
98
|
+
>>> for i, j in ti.ndrange(2, 5):
|
99
|
+
>>> print(i, j)
|
100
|
+
0 0
|
101
|
+
...
|
102
|
+
0 4
|
103
|
+
...
|
104
|
+
1 4
|
105
|
+
|
106
|
+
But you do can use a single index i to loop over these 2-D indices, in this case
|
107
|
+
the indices are returned as a 1-D array `(0, 1, ..., 9)`:
|
108
|
+
|
109
|
+
>>> @ti.kernel
|
110
|
+
>>> def loop_2d_as_1d():
|
111
|
+
>>> for i in ti.ndrange(2, 5):
|
112
|
+
>>> print(i)
|
113
|
+
will print 0 1 2 3 4 5 6 7 8 9
|
114
|
+
|
115
|
+
In general, you can use any `1 <= k <= n` iterators to loop over a set of n-D
|
116
|
+
indices. For `k=n` all the indices are n-dimensional, and they are returned in
|
117
|
+
lexical order, but for `k<n` iterators the last n-k+1 dimensions will be collapsed into
|
118
|
+
a 1-D array of consecutive integers `(0, 1, 2, ...)` whose length equals the
|
119
|
+
total number of indices in the last n-k+1 dimensions:
|
120
|
+
|
121
|
+
>>> @ti.kernel
|
122
|
+
>>> def loop_3d_as_2d():
|
123
|
+
>>> # use two iterators to loop over a set of 3-D indices
|
124
|
+
>>> # the last two dimensions for 4, 5 will collapse into
|
125
|
+
>>> # the array [0, 1, 2, ..., 19]
|
126
|
+
>>> for i, j in ti.ndrange(3, 4, 5):
|
127
|
+
>>> print(i, j)
|
128
|
+
will print 0 0, 0 1, ..., 0 19, ..., 2 19.
|
129
|
+
|
130
|
+
A typical usage of `ndrange` is when you want to loop over a tensor and process
|
131
|
+
its entries in parallel. You should avoid writing nested `for` loops here since
|
132
|
+
only top level `for` loops are paralleled in taichi, instead you can use `ndrange`
|
133
|
+
to hold all entries in one top level loop:
|
134
|
+
|
135
|
+
>>> @ti.kernel
|
136
|
+
>>> def loop_tensor():
|
137
|
+
>>> for row, col, channel in ti.ndrange(image_height, image_width, channels):
|
138
|
+
>>> image[row, col, channel] = ...
|
139
|
+
"""
|
140
|
+
return _Ndrange(*args)
|
141
|
+
|
142
|
+
|
143
|
+
class GroupedNDRange:
|
144
|
+
def __init__(self, r):
|
145
|
+
self.r = r
|
146
|
+
|
147
|
+
def __iter__(self):
|
148
|
+
for ind in self.r:
|
149
|
+
yield Matrix(list(ind))
|
150
|
+
|
151
|
+
|
152
|
+
__all__ = ["ndrange"]
|
taichi/lang/_texture.py
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
# type: ignore
|
2
|
+
|
3
|
+
import numpy as np
|
4
|
+
|
5
|
+
from taichi._lib import core as _ti_core
|
6
|
+
from taichi.lang import impl
|
7
|
+
from taichi.lang.expr import Expr, make_expr_group
|
8
|
+
from taichi.lang.matrix import Matrix
|
9
|
+
from taichi.lang.util import taichi_scope
|
10
|
+
from taichi.types import vector
|
11
|
+
from taichi.types.primitive_types import f32
|
12
|
+
|
13
|
+
|
14
|
+
def _get_entries(mat):
|
15
|
+
if isinstance(mat, Matrix):
|
16
|
+
return mat.entries
|
17
|
+
return [mat]
|
18
|
+
|
19
|
+
|
20
|
+
class TextureSampler:
|
21
|
+
def __init__(self, ptr_expr, num_dims) -> None:
|
22
|
+
self.ptr_expr = ptr_expr
|
23
|
+
self.num_dims = num_dims
|
24
|
+
|
25
|
+
@taichi_scope
|
26
|
+
def sample_lod(self, uv, lod):
|
27
|
+
ast_builder = impl.get_runtime().compiling_callable.ast_builder()
|
28
|
+
dbg_info = _ti_core.DebugInfo(impl.get_runtime().get_current_src_info())
|
29
|
+
args_group = make_expr_group(*_get_entries(uv), lod)
|
30
|
+
v = ast_builder.make_texture_op_expr(_ti_core.TextureOpType.kSampleLod, self.ptr_expr, args_group, dbg_info)
|
31
|
+
r = impl.call_internal("composite_extract_0", v, with_runtime_context=False)
|
32
|
+
g = impl.call_internal("composite_extract_1", v, with_runtime_context=False)
|
33
|
+
b = impl.call_internal("composite_extract_2", v, with_runtime_context=False)
|
34
|
+
a = impl.call_internal("composite_extract_3", v, with_runtime_context=False)
|
35
|
+
return vector(4, f32)([r, g, b, a])
|
36
|
+
|
37
|
+
@taichi_scope
|
38
|
+
def fetch(self, index, lod):
|
39
|
+
ast_builder = impl.get_runtime().compiling_callable.ast_builder()
|
40
|
+
dbg_info = _ti_core.DebugInfo(impl.get_runtime().get_current_src_info())
|
41
|
+
args_group = make_expr_group(*_get_entries(index), lod)
|
42
|
+
v = ast_builder.make_texture_op_expr(_ti_core.TextureOpType.kFetchTexel, self.ptr_expr, args_group, dbg_info)
|
43
|
+
r = impl.call_internal("composite_extract_0", v, with_runtime_context=False)
|
44
|
+
g = impl.call_internal("composite_extract_1", v, with_runtime_context=False)
|
45
|
+
b = impl.call_internal("composite_extract_2", v, with_runtime_context=False)
|
46
|
+
a = impl.call_internal("composite_extract_3", v, with_runtime_context=False)
|
47
|
+
return vector(4, f32)([r, g, b, a])
|
48
|
+
|
49
|
+
|
50
|
+
class RWTextureAccessor:
|
51
|
+
def __init__(self, ptr_expr, num_dims) -> None:
|
52
|
+
# taichi_python.TexturePtrExpression.
|
53
|
+
self.ptr_expr = ptr_expr
|
54
|
+
self.num_dims = num_dims
|
55
|
+
|
56
|
+
@taichi_scope
|
57
|
+
def load(self, index):
|
58
|
+
ast_builder = impl.get_runtime().compiling_callable.ast_builder()
|
59
|
+
dbg_info = _ti_core.DebugInfo(impl.get_runtime().get_current_src_info())
|
60
|
+
args_group = make_expr_group(*_get_entries(index))
|
61
|
+
v = ast_builder.make_texture_op_expr(_ti_core.TextureOpType.kLoad, self.ptr_expr, args_group, dbg_info)
|
62
|
+
r = impl.call_internal("composite_extract_0", v, with_runtime_context=False)
|
63
|
+
g = impl.call_internal("composite_extract_1", v, with_runtime_context=False)
|
64
|
+
b = impl.call_internal("composite_extract_2", v, with_runtime_context=False)
|
65
|
+
a = impl.call_internal("composite_extract_3", v, with_runtime_context=False)
|
66
|
+
return vector(4, f32)([r, g, b, a])
|
67
|
+
|
68
|
+
@taichi_scope
|
69
|
+
def store(self, index, value):
|
70
|
+
ast_builder = impl.get_runtime().compiling_callable.ast_builder()
|
71
|
+
dbg_info = _ti_core.DebugInfo(impl.get_runtime().get_current_src_info())
|
72
|
+
args_group = make_expr_group(*_get_entries(index), *_get_entries(value))
|
73
|
+
impl.expr_init(
|
74
|
+
ast_builder.make_texture_op_expr(_ti_core.TextureOpType.kStore, self.ptr_expr, args_group, dbg_info)
|
75
|
+
)
|
76
|
+
|
77
|
+
@property
|
78
|
+
@taichi_scope
|
79
|
+
def shape(self):
|
80
|
+
"""A list containing sizes for each dimension. Note that element shape will be excluded.
|
81
|
+
|
82
|
+
Returns:
|
83
|
+
List[Int]: The result list.
|
84
|
+
"""
|
85
|
+
dim = _ti_core.get_external_tensor_dim(self.ptr_expr)
|
86
|
+
dbg_info = _ti_core.DebugInfo(impl.get_runtime().get_current_src_info())
|
87
|
+
ret = [Expr(_ti_core.get_external_tensor_shape_along_axis(self.ptr_expr, i, dbg_info)) for i in range(dim)]
|
88
|
+
return ret
|
89
|
+
|
90
|
+
@taichi_scope
|
91
|
+
def _loop_range(self):
|
92
|
+
"""Gets the corresponding taichi_python.Expr to serve as loop range.
|
93
|
+
|
94
|
+
Returns:
|
95
|
+
taichi_python.Expr: See above.
|
96
|
+
"""
|
97
|
+
return self.ptr_expr
|
98
|
+
|
99
|
+
|
100
|
+
class Texture:
|
101
|
+
"""Taichi Texture class.
|
102
|
+
|
103
|
+
Args:
|
104
|
+
fmt (ti.Format): Color format of the texture.
|
105
|
+
shape (Tuple[int]): Shape of the Texture.
|
106
|
+
"""
|
107
|
+
|
108
|
+
def __init__(self, fmt, arr_shape):
|
109
|
+
self.tex = impl.get_runtime().prog.create_texture(fmt, arr_shape)
|
110
|
+
self.fmt = fmt
|
111
|
+
self.num_dims = len(arr_shape)
|
112
|
+
self.shape = arr_shape
|
113
|
+
|
114
|
+
def from_ndarray(self, ndarray):
|
115
|
+
"""Loads an ndarray to texture.
|
116
|
+
|
117
|
+
Args:
|
118
|
+
ndarray (ti.Ndarray): Source ndarray to load from.
|
119
|
+
"""
|
120
|
+
self.tex.from_ndarray(ndarray.arr)
|
121
|
+
|
122
|
+
def from_field(self, field):
|
123
|
+
"""Loads a field to texture.
|
124
|
+
|
125
|
+
Args:
|
126
|
+
field (ti.Field): Source field to load from.
|
127
|
+
"""
|
128
|
+
self.tex.from_snode(field.snode.ptr)
|
129
|
+
|
130
|
+
def _device_allocation_ptr(self):
|
131
|
+
return self.tex.device_allocation_ptr()
|
132
|
+
|
133
|
+
def from_image(self, image):
|
134
|
+
"""Loads a PIL image to texture. This method is only allowed a 2D texture with `ti.Format.rgba8`.
|
135
|
+
|
136
|
+
Args:
|
137
|
+
image (PIL.Image.Image): Source PIL image to load from.
|
138
|
+
|
139
|
+
"""
|
140
|
+
from PIL import Image # pylint: disable=import-outside-toplevel
|
141
|
+
|
142
|
+
assert isinstance(image, Image.Image)
|
143
|
+
if image.mode != "RGB":
|
144
|
+
image = image.convert("RGB")
|
145
|
+
assert image.size == tuple(self.shape)
|
146
|
+
|
147
|
+
assert self.num_dims == 2
|
148
|
+
# Don't use transpose method since its enums are too new
|
149
|
+
image = image.rotate(90, expand=True)
|
150
|
+
arr = np.asarray(image)
|
151
|
+
from taichi._kernels import ( # pylint: disable=import-outside-toplevel
|
152
|
+
load_texture_from_numpy,
|
153
|
+
)
|
154
|
+
|
155
|
+
load_texture_from_numpy(self, arr)
|
156
|
+
|
157
|
+
def to_image(self):
|
158
|
+
"""Saves a texture to a PIL image in RGB mode. This method is only allowed a 2D texture with `ti.Format.rgba8`.
|
159
|
+
|
160
|
+
Returns:
|
161
|
+
img (PIL.Image.Image): a PIL image in RGB mode, with the same size as source texture.
|
162
|
+
"""
|
163
|
+
assert self.num_dims == 2
|
164
|
+
from PIL import Image # pylint: disable=import-outside-toplevel
|
165
|
+
|
166
|
+
res = np.zeros(self.shape + (3,), np.uint8)
|
167
|
+
from taichi._kernels import ( # pylint: disable=import-outside-toplevel
|
168
|
+
save_texture_to_numpy,
|
169
|
+
)
|
170
|
+
|
171
|
+
save_texture_to_numpy(self, res)
|
172
|
+
return Image.fromarray(res).rotate(270, expand=True)
|
@@ -0,0 +1,189 @@
|
|
1
|
+
# type: ignore
|
2
|
+
|
3
|
+
# Taichi's custom inspect module.
|
4
|
+
# This module is used by Taichi's ast transformer to parse the source code.
|
5
|
+
# Currently this module is aimed for working in the following modes:
|
6
|
+
# 1. Usual Python/IPython mode, e.g. python script.py
|
7
|
+
# In this case we mainly rely on the built-in `inspect` module, except
|
8
|
+
# we need some hacks when we are in IPython mode and there is a cell magic.
|
9
|
+
# 2. Blender's scripting mode, e.g. Users write Taichi code in the scripting
|
10
|
+
# window in Blender and press the run button. In this case we need to
|
11
|
+
# retrieve the source using Blender's `bpy.data.texts` and write it to a temp
|
12
|
+
# file so that the inspect module can parse.
|
13
|
+
# 3. The interactive shell mode, e.g. Users directly type their code in the
|
14
|
+
# interactive shell. In this case we use `dill` to get the source.
|
15
|
+
#
|
16
|
+
# NB: Running Taichi in other modes are likely not supported.
|
17
|
+
|
18
|
+
import atexit
|
19
|
+
import inspect
|
20
|
+
import os
|
21
|
+
import tempfile
|
22
|
+
|
23
|
+
import dill
|
24
|
+
|
25
|
+
_builtin_getfile = inspect.getfile
|
26
|
+
_builtin_findsource = inspect.findsource
|
27
|
+
|
28
|
+
|
29
|
+
def _find_source_with_custom_getfile_func(func, obj):
|
30
|
+
"""Use a custom function `func` to replace inspect's `getfile`, return the
|
31
|
+
source found by the new routine and restore the original `getfile` back.
|
32
|
+
"""
|
33
|
+
inspect.getfile = func # replace with our custom func
|
34
|
+
source = inspect.findsource(obj)
|
35
|
+
inspect.getfile = _builtin_getfile # restore
|
36
|
+
return source
|
37
|
+
|
38
|
+
|
39
|
+
def _blender_get_text_name(filename: str):
|
40
|
+
"""Extract filename from path in the Blender mode."""
|
41
|
+
# In Blender's scripting mode, unsaved files are named
|
42
|
+
# like `/Text`, `/Text.001`, `/test.py`, etc.
|
43
|
+
# We simply remove this path seperator.
|
44
|
+
if filename.startswith(os.path.sep) and filename.count(os.path.sep) == 1:
|
45
|
+
return filename[1:] # "/Text.001" --> "Text.001"
|
46
|
+
|
47
|
+
# Saved text files are named like `some-path/xxx.blend/Text` or
|
48
|
+
# `some-path/xxx.blend/test.py`
|
49
|
+
# We drop the path and extract the filename with extension.
|
50
|
+
index = filename.rfind(".blend" + os.path.sep)
|
51
|
+
if index != -1:
|
52
|
+
return filename[index + 7 :] # "xxx.blend/test.py" --> "test.py"
|
53
|
+
|
54
|
+
return None
|
55
|
+
|
56
|
+
|
57
|
+
def _blender_findsource(obj):
|
58
|
+
try:
|
59
|
+
import bpy # pylint: disable=import-outside-toplevel
|
60
|
+
except:
|
61
|
+
raise ImportError("Not in Blender environment!")
|
62
|
+
|
63
|
+
# Inspect's built-in `getfile` returns the filename like
|
64
|
+
# `/Text`, `/Text.001`, `some-path/xxx.blend/test.py`
|
65
|
+
# This filename may not be a full valid path.
|
66
|
+
filename = _builtin_getfile(obj)
|
67
|
+
# Extract the text name without path
|
68
|
+
text_name = _blender_get_text_name(filename)
|
69
|
+
if text_name is None:
|
70
|
+
raise IOError("Object `{obj.__name__}` is not defined in a .blend file!")
|
71
|
+
# Get the lines of code via text_name
|
72
|
+
lines = bpy.data.texts[text_name].as_string()
|
73
|
+
# Now we have found the lines of code.
|
74
|
+
# We first check if they are already cached, to avoid file io in each query.
|
75
|
+
try:
|
76
|
+
filename = _blender_findsource._saved_inspect_cache[lines] # pylint: disable=no-member
|
77
|
+
except KeyError:
|
78
|
+
# Save the code to a valid path.
|
79
|
+
fd, filename = tempfile.mkstemp(prefix="_Blender_", suffix=f"_{text_name}.py")
|
80
|
+
os.close(fd)
|
81
|
+
|
82
|
+
with open(filename, "w") as f:
|
83
|
+
f.write(lines)
|
84
|
+
|
85
|
+
_blender_findsource._saved_inspect_cache[lines] = filename # pylint: disable=no-member
|
86
|
+
atexit.register(os.unlink, filename) # Remove file when program exits
|
87
|
+
|
88
|
+
# Our custom getfile function
|
89
|
+
def wrapped_getfile(ob):
|
90
|
+
if id(ob) == id(obj):
|
91
|
+
return filename
|
92
|
+
|
93
|
+
return _builtin_getfile(ob)
|
94
|
+
|
95
|
+
return _find_source_with_custom_getfile_func(wrapped_getfile, obj)
|
96
|
+
|
97
|
+
|
98
|
+
_blender_findsource._saved_inspect_cache = {}
|
99
|
+
|
100
|
+
|
101
|
+
def _Python_IPython_findsource(obj):
|
102
|
+
try:
|
103
|
+
# In Python and IPython the builtin inspect would suffice in most cases
|
104
|
+
return _builtin_findsource(obj)
|
105
|
+
except IOError:
|
106
|
+
# Except that the cell has a magic command like %%time or %%timeit
|
107
|
+
# In this case the filename returned by the built-in's getfile is wrong,
|
108
|
+
# it becomes something like `<timed exec>` or `<magic-timeit>`.
|
109
|
+
filename = _builtin_getfile(obj)
|
110
|
+
if filename in {"<timed exec>", "<magic-timeit>"}:
|
111
|
+
try:
|
112
|
+
ip = get_ipython()
|
113
|
+
if ip is not None:
|
114
|
+
# So we are in IPython's cell magic
|
115
|
+
session_id = ip.history_manager.get_last_session_id()
|
116
|
+
fd, filename = tempfile.mkstemp(prefix="_IPython_", suffix=f"_{session_id}.py")
|
117
|
+
os.close(fd)
|
118
|
+
# The latest lines of code can be retrived from here
|
119
|
+
lines = ip.history_manager._i00
|
120
|
+
|
121
|
+
# `lines` is a string that also contains the cell magic
|
122
|
+
# command, we need to remove the magic command
|
123
|
+
# (and spaces/sep around it) to obtain a valid Python code
|
124
|
+
# snippet before saving it to a file
|
125
|
+
index = lines.find("%time")
|
126
|
+
lines_stripped = lines[index:]
|
127
|
+
lines_stripped = lines_stripped.split(maxsplit=1)[1]
|
128
|
+
|
129
|
+
with open(filename, "w") as f:
|
130
|
+
f.write(lines_stripped)
|
131
|
+
|
132
|
+
atexit.register(os.unlink, filename) # Remove the file after the program exits
|
133
|
+
func = lambda obj: filename
|
134
|
+
return _find_source_with_custom_getfile_func(func, obj)
|
135
|
+
|
136
|
+
except ImportError:
|
137
|
+
pass
|
138
|
+
raise IOError(
|
139
|
+
f"Cannot find source code for Object: {obj}, it's likely \
|
140
|
+
you are not running Taichi from command line or IPython."
|
141
|
+
)
|
142
|
+
|
143
|
+
|
144
|
+
def _REPL_findsource(obj):
|
145
|
+
"""Findsource in the interactive shell mode."""
|
146
|
+
return dill.source.findsource(obj)
|
147
|
+
|
148
|
+
|
149
|
+
def _custom_findsource(obj):
|
150
|
+
try:
|
151
|
+
return _Python_IPython_findsource(obj)
|
152
|
+
except IOError:
|
153
|
+
try:
|
154
|
+
return _REPL_findsource(obj)
|
155
|
+
except:
|
156
|
+
try:
|
157
|
+
return _blender_findsource(obj)
|
158
|
+
except:
|
159
|
+
raise IOError(
|
160
|
+
f"Cannot find source code for Object: {obj}, this \
|
161
|
+
is possibly because of you are running Taichi in an environment that Taichi's own \
|
162
|
+
inspect module cannot find the source. Please report an issue to help us fix: \
|
163
|
+
https://github.com/taichi-dev/taichi/issues"
|
164
|
+
)
|
165
|
+
|
166
|
+
|
167
|
+
class _InspectContextManager:
|
168
|
+
def __enter__(self):
|
169
|
+
inspect.findsource = _custom_findsource
|
170
|
+
return self
|
171
|
+
|
172
|
+
def __exit__(self, *_):
|
173
|
+
inspect.findsource = _builtin_findsource
|
174
|
+
|
175
|
+
|
176
|
+
def getsourcelines(obj):
|
177
|
+
with _InspectContextManager():
|
178
|
+
return inspect.getsourcelines(obj)
|
179
|
+
|
180
|
+
|
181
|
+
def getsourcefile(obj):
|
182
|
+
with _InspectContextManager():
|
183
|
+
ret = inspect.getsourcefile(obj)
|
184
|
+
if ret is None:
|
185
|
+
ret = inspect.getfile(obj)
|
186
|
+
return ret
|
187
|
+
|
188
|
+
|
189
|
+
__all__ = ["getsourcelines", "getsourcefile"]
|
taichi/lang/any_array.py
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# type: ignore
|
2
|
+
|
3
|
+
from taichi._lib import core as _ti_core
|
4
|
+
from taichi.lang import impl
|
5
|
+
from taichi.lang.expr import Expr, make_expr_group
|
6
|
+
from taichi.lang.util import taichi_scope
|
7
|
+
from taichi.types.enums import Layout
|
8
|
+
from taichi.types.ndarray_type import NdarrayTypeMetadata
|
9
|
+
|
10
|
+
|
11
|
+
class AnyArray:
|
12
|
+
"""Class for arbitrary arrays in Python AST.
|
13
|
+
|
14
|
+
Args:
|
15
|
+
ptr (taichi_python.Expr): A taichi_python.Expr wrapping a taichi_python.ExternalTensorExpression.
|
16
|
+
element_shape (Tuple[Int]): () if scalar elements (default), (n) if vector elements, and (n, m) if matrix elements.
|
17
|
+
layout (Layout): Memory layout.
|
18
|
+
"""
|
19
|
+
|
20
|
+
def __init__(self, ptr):
|
21
|
+
assert ptr.is_external_tensor_expr()
|
22
|
+
self.ptr = ptr
|
23
|
+
self.ptr.type_check(impl.get_runtime().prog.config())
|
24
|
+
|
25
|
+
def element_shape(self):
|
26
|
+
return _ti_core.get_external_tensor_element_shape(self.ptr)
|
27
|
+
|
28
|
+
def layout(self):
|
29
|
+
# 0: scalar; 1: vector (SOA); 2: matrix (SOA); -1: vector
|
30
|
+
# (AOS); -2: matrix (AOS)
|
31
|
+
element_dim = _ti_core.get_external_tensor_element_dim(self.ptr)
|
32
|
+
if element_dim == 1 or element_dim == 2:
|
33
|
+
return Layout.SOA
|
34
|
+
return Layout.AOS
|
35
|
+
|
36
|
+
def get_type(self):
|
37
|
+
return NdarrayTypeMetadata(
|
38
|
+
_ti_core.get_external_tensor_element_type(self.ptr), None, _ti_core.get_external_tensor_needs_grad(self.ptr)
|
39
|
+
) # AnyArray can take any shape
|
40
|
+
|
41
|
+
@property
|
42
|
+
@taichi_scope
|
43
|
+
def grad(self):
|
44
|
+
"""Returns the gradient of this array."""
|
45
|
+
return AnyArray(_ti_core.make_external_tensor_grad_expr(self.ptr))
|
46
|
+
|
47
|
+
@property
|
48
|
+
@taichi_scope
|
49
|
+
def shape(self):
|
50
|
+
"""A list containing sizes for each dimension. Note that element shape will be excluded.
|
51
|
+
|
52
|
+
Returns:
|
53
|
+
List[Int]: The result list.
|
54
|
+
"""
|
55
|
+
dim = _ti_core.get_external_tensor_dim(self.ptr)
|
56
|
+
dbg_info = _ti_core.DebugInfo(impl.get_runtime().get_current_src_info())
|
57
|
+
return [Expr(_ti_core.get_external_tensor_shape_along_axis(self.ptr, i, dbg_info)) for i in range(dim)]
|
58
|
+
|
59
|
+
@taichi_scope
|
60
|
+
def _loop_range(self):
|
61
|
+
"""Gets the corresponding taichi_python.Expr to serve as loop range.
|
62
|
+
|
63
|
+
Returns:
|
64
|
+
taichi_python.Expr: See above.
|
65
|
+
"""
|
66
|
+
return self.ptr
|
67
|
+
|
68
|
+
|
69
|
+
class AnyArrayAccess:
|
70
|
+
"""Class for first-level access to AnyArray with Vector/Matrix elements in Python AST.
|
71
|
+
|
72
|
+
Args:
|
73
|
+
arr (AnyArray): See above.
|
74
|
+
indices_first (Tuple[Int]): Indices of first-level access.
|
75
|
+
"""
|
76
|
+
|
77
|
+
def __init__(self, arr, indices_first):
|
78
|
+
self.arr = arr
|
79
|
+
self.indices_first = indices_first
|
80
|
+
|
81
|
+
@taichi_scope
|
82
|
+
def subscript(self, i, j):
|
83
|
+
ast_builder = impl.get_runtime().compiling_callable.ast_builder()
|
84
|
+
|
85
|
+
indices_second = (i,) if len(self.arr.element_shape()) == 1 else (i, j)
|
86
|
+
if self.arr.layout() == Layout.SOA:
|
87
|
+
indices = indices_second + self.indices_first
|
88
|
+
else:
|
89
|
+
indices = self.indices_first + indices_second
|
90
|
+
return Expr(
|
91
|
+
ast_builder.expr_subscript(
|
92
|
+
self.arr.ptr,
|
93
|
+
make_expr_group(*indices),
|
94
|
+
_ti_core.DebugInfo(impl.get_runtime().get_current_src_info()),
|
95
|
+
)
|
96
|
+
)
|
97
|
+
|
98
|
+
|
99
|
+
__all__ = []
|