This repository has been archived by the owner on Jan 3, 2023. It is now read-only.
forked from KhronosGroup/SPIRV-Cross
-
Notifications
You must be signed in to change notification settings - Fork 6
/
spirv_ispc.hpp
286 lines (248 loc) · 13.5 KB
/
spirv_ispc.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2017, Intel Corporation
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of
// the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
* Copyright 2015-2017 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SPIRV_CROSS_ISPC_HPP
#define SPIRV_CROSS_ISPC_HPP
#include "spirv_glsl.hpp"
#include <set>
#include <utility>
#include <vector>
namespace spirv_cross
{
class CompilerISPC : public CompilerGLSL
{
public:
CompilerISPC(std::vector<uint32_t> spirv_)
: CompilerGLSL(move(spirv_))
{
}
CompilerISPC(const uint32_t *ir, size_t word_count)
: CompilerGLSL(ir, word_count)
{
}
std::string compile() override;
// Sets a custom symbol name that can override
// spirv_cross_get_interface.
//
// Useful when several shader interfaces are linked
// statically into the same binary.
void set_interface_name(std::string name)
{
interface_name = std::move(name);
}
// Sets the debug flags.
// Currently disables inline functions
void set_debug()
{
debug = true;
}
// Doesn't emit any runtime array padding.
// HLSL doesn't seem to want to honour the arraystride option in SPV.
// Could be a bug in the SPV translator?
void set_ignore_runtimearray_padding()
{
ignore_runtimearray_padding = true;
}
// Group Syncs and Group Barriers are not currently supported by ISPC, so ignore them
void set_ignore_group_barriers()
{
ignore_group_barriers = true;
}
protected:
// Specifically for the ISPC compiler
// Look for potential targets to vectorise
struct VectorisationHandler : OpcodeHandler
{
VectorisationHandler(CompilerISPC &compiler_)
: compiler(compiler_)
{
}
void set_current_block(const SPIRBlock &) override;
void set_current_function(const SPIRFunction &) override;
bool begin_function_scope(const uint32_t *, uint32_t) override;
bool end_function_scope(const uint32_t *, uint32_t) override;
bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override;
bool propogate_ispc_varyings_for_builtins();
bool propogate_ispc_varyings(const uint32_t var);
bool reverse_propogate_ispc_varyings(const uint32_t var);
void dump_varying_dependancies();
void dump_varying_dependancy_branch(const uint32_t index, uint32_t tab_count, bool recurse,
std::unordered_set<uint32_t> &branch);
CompilerISPC &compiler;
std::unordered_map<uint32_t, std::unordered_set<uint32_t>>
dependee_hierarchy; // a = b; a is dependant upon b, so [b] = a. If a is a varying, then b must be
std::unordered_map<uint32_t, std::unordered_set<uint32_t>>
dependant_hierarchy; // a = b; a is dependant upon b, but for return types we propogate backwards so if a is a varying, the b should be
// Used for reverse propogating varyings for return types. ie. If a func arg is a varying, then the return type is a varying.
// Anything also assigned to the return type should be a varying
std::set<uint32_t> reverse_propogation_varyings;
const SPIRBlock *current_block = nullptr;
const SPIRFunction *current_func = nullptr;
std::stack<CFG *> cfg_stack;
struct conditional_block_tracker
{
uint32_t condition = 0;
uint32_t next_block = 0;
uint32_t this_block = 0;
const SPIRFunction *func = nullptr;
};
std::vector<conditional_block_tracker *> condition_block_stack;
};
std::string matrix_to_vector(uint32_t index, bool index_is_literal) override;
private:
void emit_header() override;
void emit_ispc_main();
void emit_function_prototype(SPIRFunction &func, const Bitset &return_flags) override;
void emit_resources();
void emit_buffer_block(const SPIRVariable &type) override;
void emit_push_constant_block(const SPIRVariable &var) override;
void emit_interface_block(const SPIRVariable &type);
void emit_block_chain(SPIRBlock &block);
void emit_uniform(const SPIRVariable &var) override;
void emit_shared(const SPIRVariable &var);
void emit_block_struct(SPIRType &type);
void emit_instruction(const Instruction &instruction) override;
void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args,
uint32_t count) override;
std::string read_access_chain(const SPIRAccessChain &chain);
void emit_load(const Instruction &instruction);
void emit_store(const Instruction &instruction);
void emit_access_chain(const Instruction &instruction);
void emit_stdlib();
void emit_struct(SPIRType &type);
void emit_specialization_constants();
void emit_workgroup_variables();
bool maybe_emit_array_assignment(uint32_t id_lhs, uint32_t id_rhs);
bool check_scalar_atomic_image(uint32_t id);
std::string variable_decl(const SPIRType &type, const std::string &name, uint32_t id) override;
std::string to_qualifiers_glsl(uint32_t id) override;
std::string to_varying_qualifiers_ispc(uint32_t id) override;
std::string argument_decl(const SPIRFunction::Parameter &arg) override;
std::string type_to_glsl(const SPIRType &type, uint32_t id = 0) override;
std::string type_to_glsl_constructor(const SPIRType &type) override;
std::string bitcast_glsl_op(const SPIRType &result_type, const SPIRType &argument_type) override;
bool optimize_read_modify_write(const SPIRType &type, const std::string &lhs, const std::string &rhs) override;
void find_vectorisation_variables();
void extract_global_variables_from_functions();
std::unordered_map<uint32_t, std::set<uint32_t>> function_global_vars;
void extract_global_variables_from_function(uint32_t func_id, std::set<uint32_t> &added_arg_ids,
std::unordered_set<uint32_t> &global_var_ids,
std::unordered_set<uint32_t> &processed_func_ids);
void find_loop_variables_from_functions();
void find_loop_variables_from_function(uint32_t func_id, std::unordered_set<uint32_t> &processed_functions);
void localize_global_variables();
std::string ensure_valid_name(std::string name, std::string pfx);
std::string entry_point_args(bool append_comma, bool want_builtins, bool want_workgroup_vars);
std::string entry_point_args_init(bool append_comma);
void find_entry_point_args();
std::string layout_for_member(const SPIRType &type, uint32_t index) override;
bool optimize_read_modify_write(const std::string &, const std::string &)
{
return false;
}
std::vector<std::string> resource_registrations;
std::vector<std::string> resource_entry_arguments;
std::vector<std::string> resource_entry_arguments_init;
std::vector<Variant *> entry_point_ids;
std::vector<Variant *> workgroup_variable_ids;
std::string impl_type;
std::string resource_type;
uint32_t shared_counter = 0;
std::string interface_name;
bool debug = false;
bool ignore_runtimearray_padding = false;
bool ignore_group_barriers = false;
// stdlib codegen
void codegen_constructor(std::string type, bool varying, uint32_t width, uint32_t arg_count, uint32_t arg_width[4]);
void codegen_cast_constructor(std::string src_type, std::string dst_type, bool varying, uint32_t width);
void codegen_matrix_constructor(std::string type, bool varying);
void codegen_load_op(std::string type, uint32_t width);
void codegen_store_op(std::string type, uint32_t width);
void codegen_default_structs(std::string type, uint32_t width);
void codegen_default_image_structs(uint32_t width);
void codegen_default_pixel_structs(uint32_t width);
void codegen_default_texture_structs(uint32_t width);
void codegen_default_binary_op(std::string type, uint32_t width, std::string op);
void codegen_unary_float_op(
std::string func_name, std::vector<std::vector<std::string>> &varyings, std::vector<std::uint32_t> vector_width,
const std::function<void(std::vector<std::string> varyings, uint32_t vector_width)> &func);
void codegen_unary_float_op_scalar_return(
std::string func_name, std::vector<std::vector<std::string>> &varyings, std::vector<std::uint32_t> vector_width,
const std::function<void(std::vector<std::string> varyings, uint32_t vector_width)> &func);
void codegen_unary_float_op_scalar_bool_return(
std::string func_name, std::vector<std::vector<std::string>> &varyings, std::vector<uint32_t> vector_width,
const std::function<void(std::vector<std::string> varyings, uint32_t vector_width)> &func);
void codegen_unary_float_op_simple(std::string func_name, std::vector<std::vector<std::string>> &varyings,
std::vector<uint32_t> vector_width);
void codegen_unary_float_op_int_return(
std::string func_name, std::vector<std::vector<std::string>> &varyings, std::vector<uint32_t> vector_width,
const std::function<void(std::vector<std::string> varyings, uint32_t vector_width)> &func);
void codegen_binary_float_op(
std::string func_name, std::vector<std::vector<std::string>> &varyings, std::vector<std::uint32_t> vector_width,
const std::function<void(std::vector<std::string> varyings, uint32_t vector_width)> &func);
void codegen_binary_float_op_scalar_return(
std::string func_name, std::vector<std::vector<std::string>> &varyings, std::vector<std::uint32_t> vector_width,
const std::function<void(std::vector<std::string> varyings, uint32_t vector_width)> &func);
void codegen_binary_float_op_simple(std::string func_name, std::vector<std::vector<std::string>> &varyings,
std::vector<uint32_t> vector_width);
void codegen_ternary_float_op(
std::string func_name, std::vector<std::vector<std::string>> &varyings, std::vector<std::uint32_t> vector_width,
const std::function<void(std::vector<std::string> varyings, uint32_t vector_width)> &func);
void codegen_ternary_float_op_scalar_return(
std::string func_name, std::vector<std::vector<std::string>> &varyings, std::vector<std::uint32_t> vector_width,
const std::function<void(std::vector<std::string> varyings, uint32_t vector_width)> &func);
void codegen_ternary_float_op_simple(std::string func_name, std::vector<std::vector<std::string>> &varyings,
std::vector<uint32_t> vector_width);
void codegen_ternary_float_op_multiple_widths(
std::string func_name, std::vector<std::vector<std::string>> &varyings,
std::vector<std::vector<uint32_t>> vector_widths,
const std::function<void(std::vector<std::string> varyings, std::vector<uint32_t> vector_widths)> &func);
void codegen_unary_op_scalar_return(
std::string func_name, std::vector<std::vector<std::string>> &varyings, std::vector<std::string> &types,
std::vector<uint32_t> vector_width,
const std::function<void(std::vector<std::string> varyings, std::vector<std::string> types,
uint32_t vector_width)> &func);
void codegen_binary_op_scalar_return(
std::string func_name, std::vector<std::vector<std::string>> &varyings, std::vector<std::string> &types,
std::vector<uint32_t> vector_width,
const std::function<void(std::vector<std::string> varyings, std::vector<std::string> types,
uint32_t vector_width)> &func);
void codegen_binary_op(std::string func_name, std::vector<std::vector<std::string>> &varyings,
std::vector<std::string> &types, std::vector<uint32_t> vector_width,
const std::function<void(std::vector<std::string> varyings, std::vector<std::string> types,
uint32_t vector_width)> &func);
void codegen_matrix_multiply(uint32_t dim, std::vector<std::vector<std::string>> &varyings);
void codegen_matrix_transpose(uint32_t dim, std::vector<std::vector<std::string>> &varyings);
void codegen_matrix_times_scalar(uint32_t dim, std::vector<std::vector<std::string>> &varyings);
void codegen_vector_times_matrix(uint32_t dim, std::vector<std::vector<std::string>> &varyings);
void codegen_matrix_times_vector(uint32_t dim, std::vector<std::vector<std::string>> &varyings);
void codegen_matrix_inverse(std::string &varying);
};
} // namespace spirv_cross
#endif