99#version 450 core
1010
1111${define_required_extensions("buffer ", DTYPE)}
12+ ${define_required_extensions(INDEX_STORAGE, "int ")}
1213
1314#define PRECISION ${PRECISION}
1415
@@ -22,19 +23,68 @@ layout(std430) buffer;
2223
2324${layout_declare_tensor(B, "w", "t_out", DTYPE, "buffer ")}
2425${layout_declare_tensor(B, "r", "t_self", DTYPE, "buffer ")}
25- ${layout_declare_tensor(B, "r", "t_index", "int ", " buffer " )}
26+ ${layout_declare_tensor(B, "r", "t_index", "int ", INDEX_STORAGE )}
2627
2728${layout_declare_ubo(B, "BufferMetadata", "outp")}
2829${layout_declare_ubo(B, "BufferMetadata", "inp")}
29- ${layout_declare_ubo(B, "BufferMetadata", "index")}
30+ $if INDEX_STORAGE == "buffer ":
31+ ${layout_declare_ubo(B, "BufferMetadata", "index")}
32+ $else :
33+ ${layout_declare_ubo(B, "TextureMetadata", "index")}
34+
35+ layout (push_constant) uniform restrict Block {
36+ ivec2 index_params;
37+ };
3038
3139layout (local_size_x_id = 0 , local_size_y_id = 1 , local_size_z_id = 2 ) in ;
3240
3341#include "dispatch.glslh"
3442
35- // Implements aten.index.Tensor for the case where self is 1D and there is
36- // exactly one index tensor. Each output element is:
43+ // Implements aten.index.Tensor with exactly one index tensor. Each output
44+ // element is:
3745// output[...] = self[index[...]]
46+ ${layout_declare_spec_const(C, "int ", "out_layout", "CONTIG_LAYOUT_INT")}
47+ ${layout_declare_spec_const(C, "int ", "inp_layout", "CONTIG_LAYOUT_INT")}
48+ ${layout_declare_spec_const(C, "int ", "index_layout", "CONTIG_LAYOUT_INT")}
49+
50+ int load_index(const TensorIndex out_tidx) {
51+ $if INDEX_STORAGE == "buffer ":
52+ uint index_bufi = 0 ;
53+ for (int d = 0 ; d < index_params.y; ++ d) {
54+ index_bufi +=
55+ stride_at(index, d) * idx_at(out_tidx, index_params.x + d);
56+ }
57+ return t_index[index_bufi];
58+ $else :
59+ TensorIndex4D index_tidx = zero_tensor4d_idx();
60+ index_tidx.data.x = int (idx_at(out_tidx, index_params.x));
61+ if (index_params.y > 1 ) {
62+ index_tidx.data.y = int (idx_at(out_tidx, index_params.x + 1 ));
63+ }
64+ if (index_params.y > 2 ) {
65+ index_tidx.data.z = int (idx_at(out_tidx, index_params.x + 2 ));
66+ }
67+ if (index_params.y > 3 ) {
68+ index_tidx.data.w = int (idx_at(out_tidx, index_params.x + 3 ));
69+ }
70+ const TextureElementIndex index_elem =
71+ tensor4d_idx_to_texture_element_idx_simple(
72+ index, index_tidx, index_layout);
73+ return texelFetch(t_index, index_elem.pos, 0 )[index_elem.comp];
74+ }
75+
76+ uint self_idx_at(
77+ const TensorIndex out_tidx,
78+ const int self_axis,
79+ const uint index_value) {
80+ if (self_axis == index_params.x) {
81+ return index_value;
82+ }
83+ const int out_axis = self_axis < index_params.x
84+ ? self_axis
85+ : self_axis + index_params.y - 1 ;
86+ return idx_at(out_tidx, out_axis);
87+ }
3888
3989void main() {
4090 const uint out_bufi = linear_idx_from_gid();
@@ -45,22 +95,20 @@ void main() {
4595 // Convert output buffer index to tensor index
4696 TensorIndex out_tidx = linear_idx_to_tensor_idx(outp, out_bufi);
4797
48- const uint self_rank = ndim(inp);
49- const uint index_rank = ndim(index);
50- // WHCN order places self's trailing axes before the index axes.
51- const uint index_axis_offset = self_rank - 1 ;
52-
53- uint index_bufi = 0 ;
54- for (uint d = 0 ; d < index_rank; ++ d) {
55- index_bufi +=
56- stride_at(index, d) * idx_at(out_tidx, index_axis_offset + d);
57- }
58- const int idx = t_index[index_bufi];
59-
60- uint self_bufi = stride_at(inp, self_rank - 1 ) * uint (idx);
61- for (uint d = 0 ; d + 1 < self_rank; ++ d) {
62- self_bufi += stride_at(inp, d) * idx_at(out_tidx, d);
63- }
98+ const int idx = load_index(out_tidx);
99+
100+ TensorIndex self_tidx;
101+ initialize(self_tidx);
102+ const int self_rank = int_ndim(inp);
103+ if (self_rank > 0 ) self_tidx.data[0 ].x = self_idx_at(out_tidx, 0 , uint (idx));
104+ if (self_rank > 1 ) self_tidx.data[0 ].y = self_idx_at(out_tidx, 1 , uint (idx));
105+ if (self_rank > 2 ) self_tidx.data[0 ].z = self_idx_at(out_tidx, 2 , uint (idx));
106+ if (self_rank > 3 ) self_tidx.data[0 ].w = self_idx_at(out_tidx, 3 , uint (idx));
107+ if (self_rank > 4 ) self_tidx.data[1 ].x = self_idx_at(out_tidx, 4 , uint (idx));
108+ if (self_rank > 5 ) self_tidx.data[1 ].y = self_idx_at(out_tidx, 5 , uint (idx));
109+ if (self_rank > 6 ) self_tidx.data[1 ].z = self_idx_at(out_tidx, 6 , uint (idx));
110+ if (self_rank > 7 ) self_tidx.data[1 ].w = self_idx_at(out_tidx, 7 , uint (idx));
111+ const uint self_bufi = tensor_idx_to_linear_idx(inp, self_tidx);
64112
65113 t_out[out_bufi] = t_self[self_bufi];
66114}
0 commit comments