Branch data Line data Source code
1 : : /* 2 : : * This file is part of libplacebo. 3 : : * 4 : : * libplacebo is free software; you can redistribute it and/or 5 : : * modify it under the terms of the GNU Lesser General Public 6 : : * License as published by the Free Software Foundation; either 7 : : * version 2.1 of the License, or (at your option) any later version. 8 : : * 9 : : * libplacebo is distributed in the hope that it will be useful, 10 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 : : * GNU Lesser General Public License for more details. 13 : : * 14 : : * You should have received a copy of the GNU Lesser General Public 15 : : * License along with libplacebo. If not, see <http://www.gnu.org/licenses/>. 16 : : */ 17 : : 18 : : #include "config_internal.h" 19 : : 20 : : #include <assert.h> 21 : : 22 : : extern "C" { 23 : : #include "pl_alloc.h" 24 : : #include "pl_thread.h" 25 : : } 26 : : 27 : : #include <glslang/Public/ShaderLang.h> 28 : : #include <glslang/SPIRV/GlslangToSpv.h> 29 : : #include <glslang/build_info.h> 30 : : 31 : : #include "glslang.h" 32 : : 33 : : #if (GLSLANG_VERSION_MAJOR * 1000 + GLSLANG_VERSION_MINOR) >= 11013 34 : : #include <glslang/Public/ResourceLimits.h> 35 : : #define DefaultTBuiltInResource *GetDefaultResources() 36 : : #endif 37 : : 38 : : using namespace glslang; 39 : : 40 : : static pl_static_mutex pl_glslang_mutex = PL_STATIC_MUTEX_INITIALIZER; 41 : : static int pl_glslang_refcount; 42 : : 43 : 0 : bool pl_glslang_init(void) 44 : : { 45 : : bool ret = true; 46 : : 47 : 0 : pl_static_mutex_lock(&pl_glslang_mutex); 48 [ # # ]: 0 : if (pl_glslang_refcount++ == 0) 49 : 0 : ret = InitializeProcess(); 50 : 0 : pl_static_mutex_unlock(&pl_glslang_mutex); 51 : : 52 : 0 : return ret; 53 : : } 54 : : 55 : 0 : void pl_glslang_uninit(void) 56 : : { 57 : 0 : pl_static_mutex_lock(&pl_glslang_mutex); 58 [ # # ]: 0 : if (--pl_glslang_refcount == 0) 59 : 0 : FinalizeProcess(); 60 : 0 : pl_static_mutex_unlock(&pl_glslang_mutex); 61 : 0 : } 62 : : 63 : 0 : struct pl_glslang_res *pl_glslang_compile(struct pl_glsl_version glsl_ver, 64 : : struct pl_spirv_version spirv_ver, 65 : : enum glsl_shader_stage stage, 66 : : const char *text) 67 : : { 68 [ # # ]: 0 : assert(pl_glslang_refcount); 69 : 0 : struct pl_glslang_res *res = pl_zalloc_ptr(NULL, res); 70 : : 71 : : EShLanguage lang; 72 : : switch (stage) { 73 : : case GLSL_SHADER_VERTEX: lang = EShLangVertex; break; 74 : : case GLSL_SHADER_FRAGMENT: lang = EShLangFragment; break; 75 : : case GLSL_SHADER_COMPUTE: lang = EShLangCompute; break; 76 : 0 : default: abort(); 77 : : } 78 : : 79 [ # # ]: 0 : TShader *shader = new TShader(lang); 80 : : 81 : 0 : shader->setEnvClient(EShClientVulkan, (EShTargetClientVersion) spirv_ver.env_version); 82 : 0 : shader->setEnvTarget(EShTargetSpv, (EShTargetLanguageVersion) spirv_ver.spv_version); 83 : 0 : shader->setStrings(&text, 1); 84 : : 85 : 0 : TBuiltInResource limits = DefaultTBuiltInResource; 86 : 0 : limits.maxComputeWorkGroupSizeX = glsl_ver.max_group_size[0]; 87 : 0 : limits.maxComputeWorkGroupSizeY = glsl_ver.max_group_size[1]; 88 : 0 : limits.maxComputeWorkGroupSizeZ = glsl_ver.max_group_size[2]; 89 : 0 : limits.minProgramTexelOffset = glsl_ver.min_gather_offset; 90 : 0 : limits.maxProgramTexelOffset = glsl_ver.max_gather_offset; 91 : : 92 [ # # ]: 0 : if (!shader->parse(&limits, 0, true, EShMsgDefault)) { 93 : 0 : res->error_msg = pl_str0dup0(res, shader->getInfoLog()); 94 : 0 : delete shader; 95 : 0 : return res; 96 : : } 97 : : 98 [ # # ]: 0 : TProgram *prog = new TProgram(); 99 : 0 : prog->addShader(shader); 100 [ # # ]: 0 : if (!prog->link(EShMsgDefault)) { 101 : 0 : res->error_msg = pl_str0dup0(res, prog->getInfoLog()); 102 : 0 : delete shader; 103 : 0 : delete prog; 104 : 0 : return res; 105 : : } 106 : : 107 : 0 : SpvOptions options; 108 : : options.disableOptimizer = false; 109 : 0 : options.stripDebugInfo = true; 110 : 0 : options.optimizeSize = true; 111 : 0 : options.validate = true; 112 [ # # ]: 0 : std::vector<unsigned int> spirv; 113 [ # # ]: 0 : GlslangToSpv(*prog->getIntermediate(lang), spirv, &options); 114 : : 115 [ # # ]: 0 : res->success = true; 116 : 0 : res->size = spirv.size() * sizeof(unsigned int); 117 [ # # ]: 0 : res->data = pl_memdup(res, spirv.data(), res->size), 118 : 0 : delete shader; 119 : 0 : delete prog; 120 : : return res; 121 : : }