| // |
| // Copyright (C) 2025 The Khronos Group Inc. |
| // All rights reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions |
| // are met: |
| // |
| // Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // |
| // Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following |
| // disclaimer in the documentation and/or other materials provided |
| // with the distribution. |
| // |
| // Neither the name of 3Dlabs Inc. Ltd. nor the names of its |
| // contributors may be used to endorse or promote products derived |
| // from this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
| // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
| // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
| // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| // POSSIBILITY OF SUCH DAMAGE. |
| // |
| |
| #include <stdint.h> |
| #include <stdio.h> |
| |
| #include <glslang/Include/glslang_c_interface.h> |
| |
| // Required for use of glslang_default_resource |
| #include <glslang/Public/resource_limits_c.h> |
| |
| typedef struct SpirVBinary { |
| uint32_t* words; // SPIR-V words |
| int size; // number of words in SPIR-V binary |
| } SpirVBinary; |
| |
| SpirVBinary compileShaderToSPIRV_Vulkan(glslang_stage_t stage, const char* shaderSource, const char* fileName) |
| { |
| const glslang_input_t input = { |
| .language = GLSLANG_SOURCE_GLSL, |
| .stage = stage, |
| .client = GLSLANG_CLIENT_VULKAN, |
| .client_version = GLSLANG_TARGET_VULKAN_1_2, |
| .target_language = GLSLANG_TARGET_SPV, |
| .target_language_version = GLSLANG_TARGET_SPV_1_5, |
| .code = shaderSource, |
| .default_version = 100, |
| .default_profile = GLSLANG_NO_PROFILE, |
| .force_default_version_and_profile = false, |
| .forward_compatible = false, |
| .messages = GLSLANG_MSG_DEFAULT_BIT, |
| .resource = glslang_default_resource(), |
| }; |
| |
| glslang_shader_t* shader = glslang_shader_create(&input); |
| |
| SpirVBinary bin = { |
| .words = NULL, |
| .size = 0, |
| }; |
| if (!glslang_shader_preprocess(shader, &input)) { |
| printf("GLSL preprocessing failed %s\n", fileName); |
| printf("%s\n", glslang_shader_get_info_log(shader)); |
| printf("%s\n", glslang_shader_get_info_debug_log(shader)); |
| printf("%s\n", input.code); |
| glslang_shader_delete(shader); |
| return bin; |
| } |
| |
| if (!glslang_shader_parse(shader, &input)) { |
| printf("GLSL parsing failed %s\n", fileName); |
| printf("%s\n", glslang_shader_get_info_log(shader)); |
| printf("%s\n", glslang_shader_get_info_debug_log(shader)); |
| printf("%s\n", glslang_shader_get_preprocessed_code(shader)); |
| glslang_shader_delete(shader); |
| return bin; |
| } |
| |
| glslang_program_t* program = glslang_program_create(); |
| glslang_program_add_shader(program, shader); |
| |
| if (!glslang_program_link(program, GLSLANG_MSG_SPV_RULES_BIT | GLSLANG_MSG_VULKAN_RULES_BIT)) { |
| printf("GLSL linking failed %s\n", fileName); |
| printf("%s\n", glslang_program_get_info_log(program)); |
| printf("%s\n", glslang_program_get_info_debug_log(program)); |
| glslang_program_delete(program); |
| glslang_shader_delete(shader); |
| return bin; |
| } |
| |
| glslang_program_SPIRV_generate(program, stage); |
| |
| bin.size = glslang_program_SPIRV_get_size(program); |
| bin.words = malloc(bin.size * sizeof(uint32_t)); |
| glslang_program_SPIRV_get(program, bin.words); |
| |
| const char* spirv_messages = glslang_program_SPIRV_get_messages(program); |
| if (spirv_messages) |
| printf("(%s) %s\b", fileName, spirv_messages); |
| |
| glslang_program_delete(program); |
| glslang_shader_delete(shader); |
| |
| return bin; |
| } |
| |
| int main() { return 0; } |