blob: 80ca099ccc1f2e846368f722ce94ef82ef81a49d [file] [log] [blame]
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001/*
2 * Copyright 2015-2016 ARM Limited
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Hans-Kristian Arntzen147e53a2016-04-04 09:36:04 +020017#include "spirv_cpp.hpp"
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010018
19using namespace spv;
Hans-Kristian Arntzen147e53a2016-04-04 09:36:04 +020020using namespace spirv_cross;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010021using namespace std;
22
23void CompilerCPP::emit_buffer_block(const SPIRVariable &var)
24{
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +020025 auto &type = get<SPIRType>(var.basetype);
26 auto instance_name = to_name(var.self);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010027
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +020028 uint32_t descriptor_set = meta[var.self].decoration.set;
29 uint32_t binding = meta[var.self].decoration.binding;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010030
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +020031 emit_struct(type);
32 statement("internal::Resource<", type_to_glsl(type), type_to_array_glsl(type), "> ", instance_name, "__;");
33 statement_no_indent("#define ", instance_name, " __res->", instance_name, "__.get()");
34 resource_registrations.push_back(
35 join("s.register_resource(", instance_name, "__", ", ", descriptor_set, ", ", binding, ");"));
36 statement("");
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010037}
38
39void CompilerCPP::emit_interface_block(const SPIRVariable &var)
40{
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +020041 auto &type = get<SPIRType>(var.basetype);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010042
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +020043 const char *qual = var.storage == StorageClassInput ? "StageInput" : "StageOutput";
44 const char *lowerqual = var.storage == StorageClassInput ? "stage_input" : "stage_output";
45 auto instance_name = to_name(var.self);
46 uint32_t location = meta[var.self].decoration.location;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010047
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +020048 auto flags = meta[type.self].decoration.decoration_flags;
49 if (flags & (1ull << DecorationBlock))
50 emit_struct(type);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010051
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +020052 statement("internal::", qual, "<", type_to_glsl(type), type_to_array_glsl(type), "> ", instance_name, "__;");
53 statement_no_indent("#define ", instance_name, " __res->", instance_name, "__.get()");
54 resource_registrations.push_back(join("s.register_", lowerqual, "(", instance_name, "__", ", ", location, ");"));
55 statement("");
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010056}
57
58void CompilerCPP::emit_shared(const SPIRVariable &var)
59{
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +020060 auto instance_name = to_name(var.self);
61 statement(variable_decl(var), ";");
62 statement_no_indent("#define ", instance_name, " __res->", instance_name);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010063}
64
65void CompilerCPP::emit_uniform(const SPIRVariable &var)
66{
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +020067 auto &type = get<SPIRType>(var.basetype);
68 auto instance_name = to_name(var.self);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010069
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +020070 uint32_t descriptor_set = meta[var.self].decoration.set;
71 uint32_t binding = meta[var.self].decoration.binding;
72 uint32_t location = meta[var.self].decoration.location;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010073
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +020074 if (type.basetype == SPIRType::Image || type.basetype == SPIRType::SampledImage ||
75 type.basetype == SPIRType::AtomicCounter)
76 {
77 statement("internal::Resource<", type_to_glsl(type), type_to_array_glsl(type), "> ", instance_name, "__;");
78 statement_no_indent("#define ", instance_name, " __res->", instance_name, "__.get()");
79 resource_registrations.push_back(
80 join("s.register_resource(", instance_name, "__", ", ", descriptor_set, ", ", binding, ");"));
81 }
82 else
83 {
84 statement("internal::UniformConstant<", type_to_glsl(type), type_to_array_glsl(type), "> ", instance_name,
85 "__;");
86 statement_no_indent("#define ", instance_name, " __res->", instance_name, "__.get()");
87 resource_registrations.push_back(
88 join("s.register_uniform_constant(", instance_name, "__", ", ", location, ");"));
89 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010090
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +020091 statement("");
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010092}
93
94void CompilerCPP::emit_push_constant_block(const SPIRVariable &var)
95{
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +020096 auto &type = get<SPIRType>(var.basetype);
97 auto &flags = meta[var.self].decoration.decoration_flags;
98 if ((flags & (1ull << DecorationBinding)) || (flags & (1ull << DecorationDescriptorSet)))
99 throw CompilerError("Push constant blocks cannot be compiled to GLSL with Binding or Set syntax. "
100 "Remap to location with reflection API first or disable these decorations.");
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100101
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200102 emit_struct(type);
103 auto instance_name = to_name(var.self);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100104
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200105 statement("internal::PushConstant<", type_to_glsl(type), type_to_array_glsl(type), "> ", instance_name, ";");
106 statement_no_indent("#define ", instance_name, " __res->", instance_name, ".get()");
107 resource_registrations.push_back(join("s.register_push_constant(", instance_name, "__", ");"));
108 statement("");
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100109}
110
111void CompilerCPP::emit_resources()
112{
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200113 // Output all basic struct types which are not Block or BufferBlock as these are declared inplace
114 // when such variables are instantiated.
115 for (auto &id : ids)
116 {
117 if (id.get_type() == TypeType)
118 {
119 auto &type = id.get<SPIRType>();
120 if (type.basetype == SPIRType::Struct && type.array.empty() && !type.pointer &&
121 (meta[type.self].decoration.decoration_flags &
122 ((1ull << DecorationBlock) | (1ull << DecorationBufferBlock))) == 0)
123 {
124 emit_struct(type);
125 }
126 }
127 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100128
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200129 statement("struct Resources : ", resource_type);
130 begin_scope();
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100131
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200132 // Output UBOs and SSBOs
133 for (auto &id : ids)
134 {
135 if (id.get_type() == TypeVariable)
136 {
137 auto &var = id.get<SPIRVariable>();
138 auto &type = get<SPIRType>(var.basetype);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100139
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200140 if (type.pointer && type.storage == StorageClassUniform && !is_builtin_variable(var) &&
141 (meta[type.self].decoration.decoration_flags &
142 ((1ull << DecorationBlock) | (1ull << DecorationBufferBlock))))
143 {
144 emit_buffer_block(var);
145 }
146 }
147 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100148
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200149 // Output push constant blocks
150 for (auto &id : ids)
151 {
152 if (id.get_type() == TypeVariable)
153 {
154 auto &var = id.get<SPIRVariable>();
155 auto &type = get<SPIRType>(var.basetype);
156 if (type.pointer && type.storage == StorageClassPushConstant)
157 emit_push_constant_block(var);
158 }
159 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100160
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200161 // Output in/out interfaces.
162 for (auto &id : ids)
163 {
164 if (id.get_type() == TypeVariable)
165 {
166 auto &var = id.get<SPIRVariable>();
167 auto &type = get<SPIRType>(var.basetype);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100168
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200169 if (!is_builtin_variable(var) && !var.remapped_variable && type.pointer &&
170 (var.storage == StorageClassInput || var.storage == StorageClassOutput))
171 {
172 emit_interface_block(var);
173 }
174 }
175 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100176
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200177 // Output Uniform Constants (values, samplers, images, etc).
178 for (auto &id : ids)
179 {
180 if (id.get_type() == TypeVariable)
181 {
182 auto &var = id.get<SPIRVariable>();
183 auto &type = get<SPIRType>(var.basetype);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100184
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200185 if (!is_builtin_variable(var) && !var.remapped_variable && type.pointer &&
186 (type.storage == StorageClassUniformConstant || type.storage == StorageClassAtomicCounter))
187 {
188 emit_uniform(var);
189 }
190 }
191 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100192
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200193 // Global variables.
194 bool emitted = false;
195 for (auto global : global_variables)
196 {
197 auto &var = get<SPIRVariable>(global);
198 if (var.storage == StorageClassWorkgroup)
199 {
200 emit_shared(var);
201 emitted = true;
202 }
203 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100204
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200205 if (emitted)
206 statement("");
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100207
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200208 statement("inline void init(spirv_cross_shader& s)");
209 begin_scope();
210 statement(resource_type, "::init(s);");
211 for (auto &reg : resource_registrations)
212 statement(reg);
213 end_scope();
214 resource_registrations.clear();
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100215
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200216 end_scope_decl();
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100217
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200218 statement("");
219 statement("Resources* __res;");
220 if (execution.model == ExecutionModelGLCompute)
221 statement("ComputePrivateResources __priv_res;");
222 statement("");
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100223
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200224 // Emit regular globals which are allocated per invocation.
225 emitted = false;
226 for (auto global : global_variables)
227 {
228 auto &var = get<SPIRVariable>(global);
229 if (var.storage == StorageClassPrivate)
230 {
231 if (var.storage == StorageClassWorkgroup)
232 emit_shared(var);
233 else
234 statement(variable_decl(var), ";");
235 emitted = true;
236 }
237 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100238
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200239 if (emitted)
240 statement("");
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100241}
242
243string CompilerCPP::compile()
244{
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200245 // Do not deal with ES-isms like precision, older extensions and such.
246 options.es = false;
247 options.version = 450;
248 backend.float_literal_suffix = true;
249 backend.uint32_t_literal_suffix = true;
250 backend.basic_int_type = "int32_t";
251 backend.basic_uint_type = "uint32_t";
252 backend.swizzle_is_function = true;
253 backend.shared_is_implied = true;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100254
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200255 uint32_t pass_count = 0;
256 do
257 {
258 if (pass_count >= 3)
259 throw CompilerError("Over 3 compilation loops detected. Must be a bug!");
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100260
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200261 resource_registrations.clear();
262 reset();
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100263
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200264 // Move constructor for this type is broken on GCC 4.9 ...
265 buffer = unique_ptr<ostringstream>(new ostringstream());
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100266
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200267 emit_header();
268 emit_resources();
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100269
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200270 emit_function(get<SPIRFunction>(execution.entry_point), 0);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100271
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200272 pass_count++;
273 } while (force_recompile);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100274
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200275 // Match opening scope of emit_header().
276 end_scope_decl();
277 // namespace
278 end_scope();
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100279
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200280 // Emit C entry points
281 emit_c_linkage();
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100282
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200283 return buffer->str();
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100284}
285
286void CompilerCPP::emit_c_linkage()
287{
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200288 statement("");
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100289
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200290 statement("spirv_cross_shader_t* spirv_cross_construct(void)");
291 begin_scope();
292 statement("return new ", impl_type, "();");
293 end_scope();
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100294
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200295 statement("");
296 statement("void spirv_cross_destruct(spirv_cross_shader_t *shader)");
297 begin_scope();
298 statement("delete static_cast<", impl_type, "*>(shader);");
299 end_scope();
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100300
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200301 statement("");
302 statement("void spirv_cross_invoke(spirv_cross_shader_t *shader)");
303 begin_scope();
304 statement("static_cast<", impl_type, "*>(shader)->invoke();");
305 end_scope();
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100306
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200307 statement("");
308 statement("static const struct spirv_cross_interface vtable =");
309 begin_scope();
310 statement("spirv_cross_construct,");
311 statement("spirv_cross_destruct,");
312 statement("spirv_cross_invoke,");
313 end_scope_decl();
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100314
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200315 statement("");
316 statement("const struct spirv_cross_interface* spirv_cross_get_interface(void)");
317 begin_scope();
318 statement("return &vtable;");
319 end_scope();
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100320}
321
322void CompilerCPP::emit_function_prototype(SPIRFunction &func, uint64_t)
323{
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200324 local_variables.clear();
325 string decl;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100326
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200327 auto &type = get<SPIRType>(func.return_type);
328 decl += "inline ";
329 decl += type_to_glsl(type);
330 decl += " ";
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100331
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200332 if (func.self == execution.entry_point)
333 {
334 decl += "main";
335 processing_entry_point = true;
336 }
337 else
338 decl += to_name(func.self);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100339
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200340 decl += "(";
341 for (auto &arg : func.arguments)
342 {
343 add_local_variable(arg.id);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100344
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200345 decl += argument_decl(arg);
346 if (&arg != &func.arguments.back())
347 decl += ", ";
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100348
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200349 // Hold a pointer to the parameter so we can invalidate the readonly field if needed.
350 auto *var = maybe_get<SPIRVariable>(arg.id);
351 if (var)
352 var->parameter = &arg;
353 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100354
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200355 decl += ")";
356 statement(decl);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100357}
358
359string CompilerCPP::argument_decl(const SPIRFunction::Parameter &arg)
360{
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200361 auto &type = expression_type(arg.id);
362 bool constref = !type.pointer || arg.write_count == 0;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100363
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200364 auto &var = get<SPIRVariable>(arg.id);
365 return join(constref ? "const " : "", type_to_glsl(type), "& ", to_name(var.self), type_to_array_glsl(type));
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100366}
367
368void CompilerCPP::emit_header()
369{
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200370 statement("// This C++ shader is autogenerated by spirv-cross.");
371 statement("#include \"spirv_cross/internal_interface.hpp\"");
372 statement("#include \"spirv_cross/external_interface.h\"");
373 statement("#include <stdint.h>");
374 statement("");
375 statement("using namespace spirv_cross;");
376 statement("using namespace glm;");
377 statement("");
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100378
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200379 statement("namespace Impl");
380 begin_scope();
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100381
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200382 switch (execution.model)
383 {
384 case ExecutionModelGeometry:
385 case ExecutionModelTessellationControl:
386 case ExecutionModelTessellationEvaluation:
387 case ExecutionModelGLCompute:
388 case ExecutionModelFragment:
389 case ExecutionModelVertex:
390 statement("struct Shader");
391 begin_scope();
392 break;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100393
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200394 default:
395 throw CompilerError("Unsupported execution model.");
396 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100397
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200398 switch (execution.model)
399 {
400 case ExecutionModelGeometry:
401 impl_type = "GeometryShader<Impl::Shader, Impl::Shader::Resources>";
402 resource_type = "GeometryResources";
403 break;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100404
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200405 case ExecutionModelVertex:
406 impl_type = "VertexShader<Impl::Shader, Impl::Shader::Resources>";
407 resource_type = "VertexResources";
408 break;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100409
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200410 case ExecutionModelFragment:
411 impl_type = "FragmentShader<Impl::Shader, Impl::Shader::Resources>";
412 resource_type = "FragmentResources";
413 break;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100414
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200415 case ExecutionModelGLCompute:
416 impl_type = join("ComputeShader<Impl::Shader, Impl::Shader::Resources, ", execution.workgroup_size.x, ", ",
417 execution.workgroup_size.y, ", ", execution.workgroup_size.z, ">");
418 resource_type = "ComputeResources";
419 break;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100420
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200421 case ExecutionModelTessellationControl:
422 impl_type = "TessControlShader<Impl::Shader, Impl::Shader::Resources>";
423 resource_type = "TessControlResources";
424 break;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100425
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200426 case ExecutionModelTessellationEvaluation:
427 impl_type = "TessEvaluationShader<Impl::Shader, Impl::Shader::Resources>";
428 resource_type = "TessEvaluationResources";
429 break;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100430
Hans-Kristian Arntzen4b8ed532016-05-05 09:33:18 +0200431 default:
432 throw CompilerError("Unsupported execution model.");
433 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100434}