|
| 1 | +/* |
| 2 | + * spvm-shadertoy |
| 3 | + |
| 4 | + * |
| 5 | + */ |
| 6 | + |
| 7 | +#include "compiler.h" |
| 8 | +#include "glslang/Include/glslang_c_interface.h" |
| 9 | +#include "glslang/Public/ShaderLang.h" |
| 10 | +#include "resourcelimits.h" |
| 11 | +#include "logger.h" |
| 12 | + |
| 13 | +namespace SPVM { |
| 14 | +namespace ShaderToy { |
| 15 | + |
| 16 | +static std::vector<uint32_t> compileShaderInternal(glslang_stage_t stage, const char *shaderSource) { |
| 17 | + const glslang_input_t input = { |
| 18 | + .language = GLSLANG_SOURCE_GLSL, |
| 19 | + .stage = stage, |
| 20 | + .client = GLSLANG_CLIENT_VULKAN, |
| 21 | + .client_version = GLSLANG_TARGET_VULKAN_1_2, |
| 22 | + .target_language = GLSLANG_TARGET_SPV, |
| 23 | + .target_language_version = GLSLANG_TARGET_SPV_1_5, |
| 24 | + .code = shaderSource, |
| 25 | + .default_version = 100, |
| 26 | + .default_profile = GLSLANG_NO_PROFILE, |
| 27 | + .force_default_version_and_profile = false, |
| 28 | + .forward_compatible = false, |
| 29 | + .messages = GLSLANG_MSG_DEFAULT_BIT, |
| 30 | + .resource = reinterpret_cast<const glslang_resource_t *>(&glslang::DefaultTBuiltInResource), |
| 31 | + }; |
| 32 | + |
| 33 | + glslang_shader_t *shader = glslang_shader_create(&input); |
| 34 | + |
| 35 | + if (!glslang_shader_preprocess(shader, &input)) { |
| 36 | + LOGE("GLSL preprocessing failed:"); |
| 37 | + LOGE("%s", glslang_shader_get_info_log(shader)); |
| 38 | + LOGE("%s", glslang_shader_get_info_debug_log(shader)); |
| 39 | + LOGE("%s", input.code); |
| 40 | + glslang_shader_delete(shader); |
| 41 | + return std::vector<uint32_t>(); |
| 42 | + } |
| 43 | + |
| 44 | + if (!glslang_shader_parse(shader, &input)) { |
| 45 | + LOGE("GLSL parsing failed:"); |
| 46 | + LOGE("%s", glslang_shader_get_info_log(shader)); |
| 47 | + LOGE("%s", glslang_shader_get_info_debug_log(shader)); |
| 48 | + LOGE("%s", glslang_shader_get_preprocessed_code(shader)); |
| 49 | + glslang_shader_delete(shader); |
| 50 | + return std::vector<uint32_t>(); |
| 51 | + } |
| 52 | + |
| 53 | + glslang_program_t *program = glslang_program_create(); |
| 54 | + glslang_program_add_shader(program, shader); |
| 55 | + |
| 56 | + if (!glslang_program_link(program, GLSLANG_MSG_SPV_RULES_BIT | GLSLANG_MSG_VULKAN_RULES_BIT)) { |
| 57 | + LOGE("GLSL linking failed:"); |
| 58 | + LOGE("%s", glslang_program_get_info_log(program)); |
| 59 | + LOGE("%s", glslang_program_get_info_debug_log(program)); |
| 60 | + glslang_program_delete(program); |
| 61 | + glslang_shader_delete(shader); |
| 62 | + return std::vector<uint32_t>(); |
| 63 | + } |
| 64 | + |
| 65 | + glslang_program_SPIRV_generate(program, stage); |
| 66 | + |
| 67 | + std::vector<uint32_t> outShaderModule(glslang_program_SPIRV_get_size(program)); |
| 68 | + glslang_program_SPIRV_get(program, outShaderModule.data()); |
| 69 | + |
| 70 | + const char *spirv_messages = glslang_program_SPIRV_get_messages(program); |
| 71 | + if (spirv_messages) { |
| 72 | + LOGI("GLSLang: %s", spirv_messages); |
| 73 | + } |
| 74 | + |
| 75 | + glslang_program_delete(program); |
| 76 | + glslang_shader_delete(shader); |
| 77 | + |
| 78 | + return outShaderModule; |
| 79 | +} |
| 80 | + |
| 81 | +std::vector<uint32_t> Compiler::compileShaderFragment(const char *shaderSource) { |
| 82 | + glslang::InitializeProcess(); |
| 83 | + auto ret = compileShaderInternal(GLSLANG_STAGE_FRAGMENT, shaderSource); |
| 84 | + glslang::FinalizeProcess(); |
| 85 | + return ret; |
| 86 | +} |
| 87 | + |
| 88 | +} |
| 89 | +} |
0 commit comments