• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2     This code is based on the glslang_c_interface implementation by Viktor Latypov
3 **/
4 
5 /**
6 BSD 2-Clause License
7 
8 Copyright (c) 2019, Viktor Latypov
9 All rights reserved.
10 
11 Redistribution and use in source and binary forms, with or without
12 modification, are permitted provided that the following conditions are met:
13 
14 1. Redistributions of source code must retain the above copyright notice, this
15    list of conditions and the following disclaimer.
16 
17 2. Redistributions in binary form must reproduce the above copyright notice,
18    this list of conditions and the following disclaimer in the documentation
19    and/or other materials provided with the distribution.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 **/
32 
33 #include "glslang/Include/glslang_c_interface.h"
34 
35 #include "StandAlone/DirStackFileIncluder.h"
36 #include "glslang/Public/ResourceLimits.h"
37 #include "glslang/Include/ShHandle.h"
38 
39 #include "glslang/Include/ResourceLimits.h"
40 #include "glslang/MachineIndependent/Versions.h"
41 #include "glslang/MachineIndependent/localintermediate.h"
42 
43 static_assert(int(GLSLANG_STAGE_COUNT) == EShLangCount, "");
44 static_assert(int(GLSLANG_STAGE_MASK_COUNT) == EShLanguageMaskCount, "");
45 static_assert(int(GLSLANG_SOURCE_COUNT) == glslang::EShSourceCount, "");
46 static_assert(int(GLSLANG_CLIENT_COUNT) == glslang::EShClientCount, "");
47 static_assert(int(GLSLANG_TARGET_COUNT) == glslang::EShTargetCount, "");
48 static_assert(int(GLSLANG_TARGET_CLIENT_VERSION_COUNT) == glslang::EShTargetClientVersionCount, "");
49 static_assert(int(GLSLANG_TARGET_LANGUAGE_VERSION_COUNT) == glslang::EShTargetLanguageVersionCount, "");
50 static_assert(int(GLSLANG_OPT_LEVEL_COUNT) == EshOptLevelCount, "");
51 static_assert(int(GLSLANG_TEX_SAMP_TRANS_COUNT) == EShTexSampTransCount, "");
52 static_assert(int(GLSLANG_MSG_COUNT) == EShMsgCount, "");
53 static_assert(int(GLSLANG_REFLECTION_COUNT) == EShReflectionCount, "");
54 static_assert(int(GLSLANG_PROFILE_COUNT) == EProfileCount, "");
55 static_assert(sizeof(glslang_limits_t) == sizeof(TLimits), "");
56 static_assert(sizeof(glslang_resource_t) == sizeof(TBuiltInResource), "");
57 
58 typedef struct glslang_shader_s {
59     glslang::TShader* shader;
60     std::string preprocessedGLSL;
61 } glslang_shader_t;
62 
63 typedef struct glslang_program_s {
64     glslang::TProgram* program;
65     std::vector<unsigned int> spirv;
66     std::string loggerMessages;
67 } glslang_program_t;
68 
69 /* Wrapper/Adapter for C glsl_include_callbacks_t functions
70 
71    This class contains a 'glsl_include_callbacks_t' structure
72    with C include_local/include_system callback pointers.
73 
74    This class implement TShader::Includer interface
75    by redirecting C++ virtual methods to C callbacks.
76 
77    The 'IncludeResult' instances produced by this Includer
78    contain a reference to glsl_include_result_t C structure
79    to allow its lifetime management by another C callback
80    (CallbackIncluder::callbacks::free_include_result)
81 */
82 class CallbackIncluder : public glslang::TShader::Includer {
83 public:
CallbackIncluder(glsl_include_callbacks_t _callbacks,void * _context)84     CallbackIncluder(glsl_include_callbacks_t _callbacks, void* _context) : callbacks(_callbacks), context(_context) {}
85 
~CallbackIncluder()86     virtual ~CallbackIncluder() {}
87 
includeSystem(const char * headerName,const char * includerName,size_t inclusionDepth)88     virtual IncludeResult* includeSystem(const char* headerName, const char* includerName,
89                                          size_t inclusionDepth) override
90     {
91         if (this->callbacks.include_system) {
92             glsl_include_result_t* result =
93                 this->callbacks.include_system(this->context, headerName, includerName, inclusionDepth);
94             return makeIncludeResult(result);
95         }
96 
97         return glslang::TShader::Includer::includeSystem(headerName, includerName, inclusionDepth);
98     }
99 
includeLocal(const char * headerName,const char * includerName,size_t inclusionDepth)100     virtual IncludeResult* includeLocal(const char* headerName, const char* includerName,
101                                         size_t inclusionDepth) override
102     {
103         if (this->callbacks.include_local) {
104             glsl_include_result_t* result =
105                 this->callbacks.include_local(this->context, headerName, includerName, inclusionDepth);
106             return makeIncludeResult(result);
107         }
108 
109         return glslang::TShader::Includer::includeLocal(headerName, includerName, inclusionDepth);
110     }
111 
112     /* This function only calls free_include_result callback
113        when the IncludeResult instance is allocated by a C function */
releaseInclude(IncludeResult * result)114     virtual void releaseInclude(IncludeResult* result) override
115     {
116         if (result == nullptr)
117             return;
118 
119         if (this->callbacks.free_include_result) {
120             this->callbacks.free_include_result(this->context, static_cast<glsl_include_result_t*>(result->userData));
121         }
122 
123         delete result;
124     }
125 
126 private:
CallbackIncluder()127     CallbackIncluder() {}
128 
makeIncludeResult(glsl_include_result_t * result)129     IncludeResult* makeIncludeResult(glsl_include_result_t* result) {
130         if (!result) {
131             return nullptr;
132         }
133 
134         return new glslang::TShader::Includer::IncludeResult(
135             std::string(result->header_name), result->header_data, result->header_length, result);
136     }
137 
138     /* C callback pointers */
139     glsl_include_callbacks_t callbacks;
140     /* User-defined context */
141     void* context;
142 };
143 
glslang_initialize_process()144 GLSLANG_EXPORT int glslang_initialize_process() { return static_cast<int>(glslang::InitializeProcess()); }
145 
glslang_finalize_process()146 GLSLANG_EXPORT void glslang_finalize_process() { glslang::FinalizeProcess(); }
147 
c_shader_stage(glslang_stage_t stage)148 static EShLanguage c_shader_stage(glslang_stage_t stage)
149 {
150     switch (stage) {
151     case GLSLANG_STAGE_VERTEX:
152         return EShLangVertex;
153     case GLSLANG_STAGE_TESSCONTROL:
154         return EShLangTessControl;
155     case GLSLANG_STAGE_TESSEVALUATION:
156         return EShLangTessEvaluation;
157     case GLSLANG_STAGE_GEOMETRY:
158         return EShLangGeometry;
159     case GLSLANG_STAGE_FRAGMENT:
160         return EShLangFragment;
161     case GLSLANG_STAGE_COMPUTE:
162         return EShLangCompute;
163     case GLSLANG_STAGE_RAYGEN_NV:
164         return EShLangRayGen;
165     case GLSLANG_STAGE_INTERSECT_NV:
166         return EShLangIntersect;
167     case GLSLANG_STAGE_ANYHIT_NV:
168         return EShLangAnyHit;
169     case GLSLANG_STAGE_CLOSESTHIT_NV:
170         return EShLangClosestHit;
171     case GLSLANG_STAGE_MISS_NV:
172         return EShLangMiss;
173     case GLSLANG_STAGE_CALLABLE_NV:
174         return EShLangCallable;
175     case GLSLANG_STAGE_TASK:
176         return EShLangTask;
177     case GLSLANG_STAGE_MESH:
178         return EShLangMesh;
179     default:
180         break;
181     }
182     return EShLangCount;
183 }
184 
c_shader_messages(glslang_messages_t messages)185 static int c_shader_messages(glslang_messages_t messages)
186 {
187 #define CONVERT_MSG(in, out)                                                                                           \
188     if ((messages & in) == in)                                                                                         \
189         res |= out;
190 
191     int res = 0;
192 
193     CONVERT_MSG(GLSLANG_MSG_RELAXED_ERRORS_BIT, EShMsgRelaxedErrors);
194     CONVERT_MSG(GLSLANG_MSG_SUPPRESS_WARNINGS_BIT, EShMsgSuppressWarnings);
195     CONVERT_MSG(GLSLANG_MSG_AST_BIT, EShMsgAST);
196     CONVERT_MSG(GLSLANG_MSG_SPV_RULES_BIT, EShMsgSpvRules);
197     CONVERT_MSG(GLSLANG_MSG_VULKAN_RULES_BIT, EShMsgVulkanRules);
198     CONVERT_MSG(GLSLANG_MSG_ONLY_PREPROCESSOR_BIT, EShMsgOnlyPreprocessor);
199     CONVERT_MSG(GLSLANG_MSG_READ_HLSL_BIT, EShMsgReadHlsl);
200     CONVERT_MSG(GLSLANG_MSG_CASCADING_ERRORS_BIT, EShMsgCascadingErrors);
201     CONVERT_MSG(GLSLANG_MSG_KEEP_UNCALLED_BIT, EShMsgKeepUncalled);
202     CONVERT_MSG(GLSLANG_MSG_HLSL_OFFSETS_BIT, EShMsgHlslOffsets);
203     CONVERT_MSG(GLSLANG_MSG_DEBUG_INFO_BIT, EShMsgDebugInfo);
204     CONVERT_MSG(GLSLANG_MSG_HLSL_ENABLE_16BIT_TYPES_BIT, EShMsgHlslEnable16BitTypes);
205     CONVERT_MSG(GLSLANG_MSG_HLSL_LEGALIZATION_BIT, EShMsgHlslLegalization);
206     CONVERT_MSG(GLSLANG_MSG_HLSL_DX9_COMPATIBLE_BIT, EShMsgHlslDX9Compatible);
207     CONVERT_MSG(GLSLANG_MSG_BUILTIN_SYMBOL_TABLE_BIT, EShMsgBuiltinSymbolTable);
208     return res;
209 #undef CONVERT_MSG
210 }
211 
212 static glslang::EShTargetLanguageVersion
c_shader_target_language_version(glslang_target_language_version_t target_language_version)213 c_shader_target_language_version(glslang_target_language_version_t target_language_version)
214 {
215     switch (target_language_version) {
216     case GLSLANG_TARGET_SPV_1_0:
217         return glslang::EShTargetSpv_1_0;
218     case GLSLANG_TARGET_SPV_1_1:
219         return glslang::EShTargetSpv_1_1;
220     case GLSLANG_TARGET_SPV_1_2:
221         return glslang::EShTargetSpv_1_2;
222     case GLSLANG_TARGET_SPV_1_3:
223         return glslang::EShTargetSpv_1_3;
224     case GLSLANG_TARGET_SPV_1_4:
225         return glslang::EShTargetSpv_1_4;
226     case GLSLANG_TARGET_SPV_1_5:
227         return glslang::EShTargetSpv_1_5;
228     case GLSLANG_TARGET_SPV_1_6:
229         return glslang::EShTargetSpv_1_6;
230     default:
231         break;
232     }
233     return glslang::EShTargetSpv_1_0;
234 }
235 
c_shader_client(glslang_client_t client)236 static glslang::EShClient c_shader_client(glslang_client_t client)
237 {
238     switch (client) {
239     case GLSLANG_CLIENT_VULKAN:
240         return glslang::EShClientVulkan;
241     case GLSLANG_CLIENT_OPENGL:
242         return glslang::EShClientOpenGL;
243     default:
244         break;
245     }
246 
247     return glslang::EShClientNone;
248 }
249 
c_shader_client_version(glslang_target_client_version_t client_version)250 static glslang::EShTargetClientVersion c_shader_client_version(glslang_target_client_version_t client_version)
251 {
252     switch (client_version) {
253     case GLSLANG_TARGET_VULKAN_1_1:
254         return glslang::EShTargetVulkan_1_1;
255     case GLSLANG_TARGET_VULKAN_1_2:
256         return glslang::EShTargetVulkan_1_2;
257     case GLSLANG_TARGET_VULKAN_1_3:
258         return glslang::EShTargetVulkan_1_3;
259     case GLSLANG_TARGET_OPENGL_450:
260         return glslang::EShTargetOpenGL_450;
261     default:
262         break;
263     }
264 
265     return glslang::EShTargetVulkan_1_0;
266 }
267 
c_shader_target_language(glslang_target_language_t target_language)268 static glslang::EShTargetLanguage c_shader_target_language(glslang_target_language_t target_language)
269 {
270     if (target_language == GLSLANG_TARGET_NONE)
271         return glslang::EShTargetNone;
272 
273     return glslang::EShTargetSpv;
274 }
275 
c_shader_source(glslang_source_t source)276 static glslang::EShSource c_shader_source(glslang_source_t source)
277 {
278     switch (source) {
279     case GLSLANG_SOURCE_GLSL:
280         return glslang::EShSourceGlsl;
281     case GLSLANG_SOURCE_HLSL:
282         return glslang::EShSourceHlsl;
283     default:
284         break;
285     }
286 
287     return glslang::EShSourceNone;
288 }
289 
c_shader_profile(glslang_profile_t profile)290 static EProfile c_shader_profile(glslang_profile_t profile)
291 {
292     switch (profile) {
293     case GLSLANG_BAD_PROFILE:
294         return EBadProfile;
295     case GLSLANG_NO_PROFILE:
296         return ENoProfile;
297     case GLSLANG_CORE_PROFILE:
298         return ECoreProfile;
299     case GLSLANG_COMPATIBILITY_PROFILE:
300         return ECompatibilityProfile;
301     case GLSLANG_ES_PROFILE:
302         return EEsProfile;
303     case GLSLANG_PROFILE_COUNT: // Should not use this
304         break;
305     }
306 
307     return EProfile();
308 }
309 
glslang_shader_create(const glslang_input_t * input)310 GLSLANG_EXPORT glslang_shader_t* glslang_shader_create(const glslang_input_t* input)
311 {
312     if (!input || !input->code) {
313         printf("Error creating shader: null input(%p)/input->code\n", input);
314 
315         if (input)
316             printf("input->code = %p\n", input->code);
317 
318         return nullptr;
319     }
320 
321     glslang_shader_t* shader = new glslang_shader_t();
322 
323     shader->shader = new glslang::TShader(c_shader_stage(input->stage));
324     shader->shader->setStrings(&input->code, 1);
325     shader->shader->setEnvInput(c_shader_source(input->language), c_shader_stage(input->stage),
326                                 c_shader_client(input->client), input->default_version);
327     shader->shader->setEnvClient(c_shader_client(input->client), c_shader_client_version(input->client_version));
328     shader->shader->setEnvTarget(c_shader_target_language(input->target_language),
329                                  c_shader_target_language_version(input->target_language_version));
330 
331     return shader;
332 }
333 
glslang_shader_set_preamble(glslang_shader_t * shader,const char * s)334 GLSLANG_EXPORT void glslang_shader_set_preamble(glslang_shader_t* shader, const char* s) {
335     shader->shader->setPreamble(s);
336 }
337 
glslang_shader_shift_binding(glslang_shader_t * shader,glslang_resource_type_t res,unsigned int base)338 GLSLANG_EXPORT void glslang_shader_shift_binding(glslang_shader_t* shader, glslang_resource_type_t res, unsigned int base)
339 {
340     const glslang::TResourceType res_type = glslang::TResourceType(res);
341     shader->shader->setShiftBinding(res_type, base);
342 }
343 
glslang_shader_shift_binding_for_set(glslang_shader_t * shader,glslang_resource_type_t res,unsigned int base,unsigned int set)344 GLSLANG_EXPORT void glslang_shader_shift_binding_for_set(glslang_shader_t* shader, glslang_resource_type_t res, unsigned int base, unsigned int set)
345 {
346     const glslang::TResourceType res_type = glslang::TResourceType(res);
347     shader->shader->setShiftBindingForSet(res_type, base, set);
348 }
349 
glslang_shader_set_options(glslang_shader_t * shader,int options)350 GLSLANG_EXPORT void glslang_shader_set_options(glslang_shader_t* shader, int options)
351 {
352     if (options & GLSLANG_SHADER_AUTO_MAP_BINDINGS) {
353         shader->shader->setAutoMapBindings(true);
354     }
355 
356     if (options & GLSLANG_SHADER_AUTO_MAP_LOCATIONS) {
357         shader->shader->setAutoMapLocations(true);
358     }
359 
360     if (options & GLSLANG_SHADER_VULKAN_RULES_RELAXED) {
361         shader->shader->setEnvInputVulkanRulesRelaxed();
362     }
363 }
364 
glslang_shader_set_glsl_version(glslang_shader_t * shader,int version)365 GLSLANG_EXPORT void glslang_shader_set_glsl_version(glslang_shader_t* shader, int version)
366 {
367     shader->shader->setOverrideVersion(version);
368 }
369 
glslang_shader_get_preprocessed_code(glslang_shader_t * shader)370 GLSLANG_EXPORT const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader)
371 {
372     return shader->preprocessedGLSL.c_str();
373 }
374 
glslang_shader_preprocess(glslang_shader_t * shader,const glslang_input_t * input)375 GLSLANG_EXPORT int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input)
376 {
377     DirStackFileIncluder dirStackFileIncluder;
378     CallbackIncluder callbackIncluder(input->callbacks, input->callbacks_ctx);
379     glslang::TShader::Includer& Includer = (input->callbacks.include_local||input->callbacks.include_system)
380         ? static_cast<glslang::TShader::Includer&>(callbackIncluder)
381         : static_cast<glslang::TShader::Includer&>(dirStackFileIncluder);
382     return shader->shader->preprocess(
383         reinterpret_cast<const TBuiltInResource*>(input->resource),
384         input->default_version,
385         c_shader_profile(input->default_profile),
386         input->force_default_version_and_profile != 0,
387         input->forward_compatible != 0,
388         (EShMessages)c_shader_messages(input->messages),
389         &shader->preprocessedGLSL,
390         Includer
391     );
392 }
393 
glslang_shader_parse(glslang_shader_t * shader,const glslang_input_t * input)394 GLSLANG_EXPORT int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input)
395 {
396     const char* preprocessedCStr = shader->preprocessedGLSL.c_str();
397     shader->shader->setStrings(&preprocessedCStr, 1);
398 
399     return shader->shader->parse(
400         reinterpret_cast<const TBuiltInResource*>(input->resource),
401         input->default_version,
402         input->forward_compatible != 0,
403         (EShMessages)c_shader_messages(input->messages)
404     );
405 }
406 
glslang_shader_get_info_log(glslang_shader_t * shader)407 GLSLANG_EXPORT const char* glslang_shader_get_info_log(glslang_shader_t* shader) { return shader->shader->getInfoLog(); }
408 
glslang_shader_get_info_debug_log(glslang_shader_t * shader)409 GLSLANG_EXPORT const char* glslang_shader_get_info_debug_log(glslang_shader_t* shader) { return shader->shader->getInfoDebugLog(); }
410 
glslang_shader_delete(glslang_shader_t * shader)411 GLSLANG_EXPORT void glslang_shader_delete(glslang_shader_t* shader)
412 {
413     if (!shader)
414         return;
415 
416     delete (shader->shader);
417     delete (shader);
418 }
419 
glslang_program_create()420 GLSLANG_EXPORT glslang_program_t* glslang_program_create()
421 {
422     glslang_program_t* p = new glslang_program_t();
423     p->program = new glslang::TProgram();
424     return p;
425 }
426 
glslang_program_delete(glslang_program_t * program)427 GLSLANG_EXPORT void glslang_program_delete(glslang_program_t* program)
428 {
429     if (!program)
430         return;
431 
432     delete (program->program);
433     delete (program);
434 }
435 
glslang_program_add_shader(glslang_program_t * program,glslang_shader_t * shader)436 GLSLANG_EXPORT void glslang_program_add_shader(glslang_program_t* program, glslang_shader_t* shader)
437 {
438     program->program->addShader(shader->shader);
439 }
440 
glslang_program_link(glslang_program_t * program,int messages)441 GLSLANG_EXPORT int glslang_program_link(glslang_program_t* program, int messages)
442 {
443     return (int)program->program->link((EShMessages)messages);
444 }
445 
glslang_program_add_source_text(glslang_program_t * program,glslang_stage_t stage,const char * text,size_t len)446 GLSLANG_EXPORT void glslang_program_add_source_text(glslang_program_t* program, glslang_stage_t stage, const char* text, size_t len) {
447     glslang::TIntermediate* intermediate = program->program->getIntermediate(c_shader_stage(stage));
448     intermediate->addSourceText(text, len);
449 }
450 
glslang_program_set_source_file(glslang_program_t * program,glslang_stage_t stage,const char * file)451 GLSLANG_EXPORT void glslang_program_set_source_file(glslang_program_t* program, glslang_stage_t stage, const char* file) {
452     glslang::TIntermediate* intermediate = program->program->getIntermediate(c_shader_stage(stage));
453     intermediate->setSourceFile(file);
454 }
455 
glslang_program_map_io(glslang_program_t * program)456 GLSLANG_EXPORT int glslang_program_map_io(glslang_program_t* program)
457 {
458     return (int)program->program->mapIO();
459 }
460 
glslang_program_get_info_log(glslang_program_t * program)461 GLSLANG_EXPORT const char* glslang_program_get_info_log(glslang_program_t* program)
462 {
463     return program->program->getInfoLog();
464 }
465 
glslang_program_get_info_debug_log(glslang_program_t * program)466 GLSLANG_EXPORT const char* glslang_program_get_info_debug_log(glslang_program_t* program)
467 {
468     return program->program->getInfoDebugLog();
469 }
470