@@ -4416,177 +4416,249 @@ void GL_APIENTRY GL_ShaderBinary(GLsizei count,
44164416
44174417#include < shaderc/shaderc.h>
44184418#include < spirv_cross/spirv_cross_c.h>
4419- static void TryConvertAndSetShaderSource (Context *context,
4420- ShaderProgramID shaderPacked,
4421- GLsizei count,
4422- const GLchar *const *string,
4423- const GLint *length);
4424- static void TryConvertAndSetShaderSource (Context *context,
4425- ShaderProgramID shaderPacked,
4426- GLsizei count,
4427- const GLchar *const *string,
4428- const GLint *length)
4419+ static std::string MergeShaderSources (GLsizei count,
4420+ const GLchar *const *string,
4421+ const GLint *length)
4422+ {
4423+ std::string result;
4424+ for (GLsizei i = 0 ; i < count; ++i)
4425+ {
4426+ if (string[i] == nullptr )
4427+ continue ;
4428+ if (length && length[i] > 0 )
4429+ result.append (string[i], static_cast <size_t >(length[i]));
4430+ else
4431+ result.append (string[i]);
4432+ }
4433+ return result;
4434+ }
4435+
4436+
4437+ static bool TryConvertGLSL (const Context *context,
4438+ ShaderProgramID shaderPacked,
4439+ const std::string &inputSource,
4440+ std::string &outputSource)
44294441{
44304442 static std::once_flag initFlag;
44314443 static bool initSuccess = false ;
4444+
44324445 static shaderc_compiler_t (*p_shaderc_compiler_initialize)(void ) = nullptr ;
44334446 static void (*p_shaderc_compiler_release)(shaderc_compiler_t ) = nullptr ;
44344447 static shaderc_compile_options_t (*p_shaderc_compile_options_initialize)(void ) = nullptr ;
44354448 static void (*p_shaderc_compile_options_release)(shaderc_compile_options_t ) = nullptr ;
44364449 static void (*p_shaderc_compile_options_set_target_env)(shaderc_compile_options_t ,
4437- shaderc_target_env, unsigned int ) = nullptr ;
4450+ shaderc_target_env, uint32_t ) = nullptr ;
44384451 static void (*p_shaderc_compile_options_set_source_language)(shaderc_compile_options_t ,
44394452 shaderc_source_language) = nullptr ;
44404453 static void (*p_shaderc_compile_options_set_auto_bind_uniforms)(shaderc_compile_options_t ,
4441- int ) = nullptr ;
4454+ bool ) = nullptr ;
44424455 static shaderc_compilation_result_t (*p_shaderc_compile_into_spv)(
44434456 shaderc_compiler_t , const char *, size_t , shaderc_shader_kind,
4444- const char *, const char *, shaderc_compile_options_t ) = nullptr ;
4457+ const char *, const char *, const shaderc_compile_options_t ) = nullptr ;
44454458 static const char * (*p_shaderc_result_get_bytes)(const shaderc_compilation_result_t ) = nullptr ;
44464459 static size_t (*p_shaderc_result_get_length)(const shaderc_compilation_result_t ) = nullptr ;
44474460 static const char * (*p_shaderc_result_get_error_message)(const shaderc_compilation_result_t ) = nullptr ;
44484461 static void (*p_shaderc_result_release)(shaderc_compilation_result_t ) = nullptr ;
44494462
4450- static spirv_cross_t (*p_spirv_cross_new)(const uint32_t *, size_t ) = nullptr ;
4451- static void (*p_spirv_cross_delete)(spirv_cross_t ) = nullptr ;
4452- static void (*p_spirv_cross_set_glsl_version)(spirv_cross_t , int ) = nullptr ;
4453- static void (*p_spirv_cross_set_es)(spirv_cross_t , bool ) = nullptr ;
4454- static bool (*p_spirv_cross_compile)(spirv_cross_t ) = nullptr ;
4455- static const char * (*p_spirv_cross_get_glsl)(spirv_cross_t ) = nullptr ;
4463+ // spirv-cross 函数指针
4464+ static spvc_result (*p_spvc_context_create)(spvc_context *) = nullptr ;
4465+ static void (*p_spvc_context_destroy)(spvc_context) = nullptr ;
4466+ static void (*p_spvc_context_release_allocations)(spvc_context) = nullptr ;
4467+ static spvc_result (*p_spvc_context_parse_spirv)(spvc_context, const SpvId *, size_t , spvc_parsed_ir *) = nullptr ;
4468+ static spvc_result (*p_spvc_context_create_compiler)(spvc_context, spvc_backend,
4469+ spvc_parsed_ir, spvc_capture_mode,
4470+ spvc_compiler *) = nullptr ;
4471+ static spvc_result (*p_spvc_compiler_create_compiler_options)(spvc_compiler, spvc_compiler_options *) = nullptr ;
4472+ static spvc_result (*p_spvc_compiler_options_set_uint)(spvc_compiler_options,
4473+ spvc_compiler_option, unsigned ) = nullptr ;
4474+ static spvc_result (*p_spvc_compiler_options_set_bool)(spvc_compiler_options,
4475+ spvc_compiler_option, spvc_bool) = nullptr ;
4476+ static spvc_result (*p_spvc_compiler_install_compiler_options)(spvc_compiler,
4477+ spvc_compiler_options) = nullptr ;
4478+ static spvc_result (*p_spvc_compiler_compile)(spvc_compiler, const char **) = nullptr ;
44564479
44574480 std::call_once (initFlag, [&]() {
4458- void * shadercHandle = dlopen (" libshaderc.so" , RTLD_LAZY );
4459- if (!shadercHandle) return ;
4460- #define LOAD_SYM (handle, sym ) p_##sym = (decltype (p_##sym))dlsym(handle, #sym); if (!p_##sym) return ;
4461- LOAD_SYM (shadercHandle, shaderc_compiler_initialize);
4462- LOAD_SYM (shadercHandle, shaderc_compiler_release);
4463- LOAD_SYM (shadercHandle, shaderc_compile_options_initialize);
4464- LOAD_SYM (shadercHandle, shaderc_compile_options_release);
4465- LOAD_SYM (shadercHandle, shaderc_compile_options_set_target_env);
4466- LOAD_SYM (shadercHandle, shaderc_compile_options_set_source_language);
4467- LOAD_SYM (shadercHandle, shaderc_compile_options_set_auto_bind_uniforms);
4468- LOAD_SYM (shadercHandle, shaderc_compile_into_spv);
4469- LOAD_SYM (shadercHandle, shaderc_result_get_bytes);
4470- LOAD_SYM (shadercHandle, shaderc_result_get_length);
4471- LOAD_SYM (shadercHandle, shaderc_result_get_error_message);
4472- LOAD_SYM (shadercHandle, shaderc_result_release);
4473- #undef LOAD_SYM
4474-
4475- void * spirvCrossHandle = dlopen (" libspirv-cross-c-shared.so" , RTLD_LAZY );
4476- if (!spirvCrossHandle) {
4477- dlclose (shadercHandle);
4478- return ;
4479- }
4480- #define LOAD_SPIRV_SYM (handle, sym ) p_##sym = (decltype (p_##sym))dlsym(handle, #sym); if (!p_##sym) return ;
4481- LOAD_SPIRV_SYM (spirvCrossHandle, spirv_cross_new);
4482- LOAD_SPIRV_SYM (spirvCrossHandle, spirv_cross_delete);
4483- LOAD_SPIRV_SYM (spirvCrossHandle, spirv_cross_set_glsl_version);
4484- LOAD_SPIRV_SYM (spirvCrossHandle, spirv_cross_set_es);
4485- LOAD_SPIRV_SYM (spirvCrossHandle, spirv_cross_compile);
4486- LOAD_SPIRV_SYM (spirvCrossHandle, spirv_cross_get_glsl);
4487- #undef LOAD_SPIRV_SYM
4481+ // 加载 libshaderc.so
4482+ void *shadercLib = dlopen (" libshaderc.so" , RTLD_LAZY );
4483+ if (!shadercLib) return ;
4484+ #define LOAD_SHADERC (name ) \
4485+ p_##name = (decltype (p_##name))dlsym (shadercLib, #name); \
4486+ if (!p_##name) { dlclose (shadercLib); return ; }
4487+ LOAD_SHADERC (shaderc_compiler_initialize);
4488+ LOAD_SHADERC (shaderc_compiler_release);
4489+ LOAD_SHADERC (shaderc_compile_options_initialize);
4490+ LOAD_SHADERC (shaderc_compile_options_release);
4491+ LOAD_SHADERC (shaderc_compile_options_set_target_env);
4492+ LOAD_SHADERC (shaderc_compile_options_set_source_language);
4493+ LOAD_SHADERC (shaderc_compile_options_set_auto_bind_uniforms);
4494+ LOAD_SHADERC (shaderc_compile_into_spv);
4495+ LOAD_SHADERC (shaderc_result_get_bytes);
4496+ LOAD_SHADERC (shaderc_result_get_length);
4497+ LOAD_SHADERC (shaderc_result_get_error_message);
4498+ LOAD_SHADERC (shaderc_result_release);
4499+ #undef LOAD_SHADERC
4500+
4501+ // 加载 libspirv-cross-c-shared.so
4502+ void *spvcLib = dlopen (" libspirv-cross-c-shared.so" , RTLD_LAZY );
4503+ if (!spvcLib) { dlclose (shadercLib); return ; }
4504+ #define LOAD_SPVC (name ) \
4505+ p_##name = (decltype (p_##name))dlsym (spvcLib, #name); \
4506+ if (!p_##name) { dlclose (shadercLib); dlclose (spvcLib); return ; }
4507+ LOAD_SPVC (spvc_context_create);
4508+ LOAD_SPVC (spvc_context_destroy);
4509+ LOAD_SPVC (spvc_context_release_allocations);
4510+ LOAD_SPVC (spvc_context_parse_spirv);
4511+ LOAD_SPVC (spvc_context_create_compiler);
4512+ LOAD_SPVC (spvc_compiler_create_compiler_options);
4513+ LOAD_SPVC (spvc_compiler_options_set_uint);
4514+ LOAD_SPVC (spvc_compiler_options_set_bool);
4515+ LOAD_SPVC (spvc_compiler_install_compiler_options);
4516+ LOAD_SPVC (spvc_compiler_compile);
4517+ #undef LOAD_SPVC
44884518
44894519 initSuccess = true ;
44904520 printf (" GLSL converter initialized (shaderc + spirv-cross)\n " );
44914521 });
44924522
4493- if (!initSuccess) {
4494- context->shaderSource (shaderPacked, count, string, length);
4495- return ;
4496- }
4497-
4498- std::string originalSource;
4499- for (GLsizei i = 0 ; i < count; ++i) {
4500- if (!string[i]) continue ;
4501- if (length && length[i] > 0 )
4502- originalSource.append (string[i], length[i]);
4503- else
4504- originalSource.append (string[i]);
4505- }
4506- if (originalSource.empty ()) {
4507- context->shaderSource (shaderPacked, count, string, length);
4508- return ;
4509- }
4523+ if (!initSuccess)
4524+ return false ;
45104525
45114526 Shader *shaderObj = context->getShader (shaderPacked);
4512- if (!shaderObj) {
4513- context->shaderSource (shaderPacked, count, string, length);
4514- return ;
4515- }
4527+ if (!shaderObj)
4528+ return false ;
4529+
45164530 gl::ShaderType shaderType = shaderObj->getType ();
4517- shaderc_shader_kind kind = shaderc_vertex_shader;
4518- switch (shaderType) {
4531+ shaderc_shader_kind kind;
4532+ switch (shaderType)
4533+ {
45194534 case gl::ShaderType::Vertex: kind = shaderc_vertex_shader; break ;
45204535 case gl::ShaderType::Fragment: kind = shaderc_fragment_shader; break ;
45214536 case gl::ShaderType::Geometry: kind = shaderc_geometry_shader; break ;
45224537 case gl::ShaderType::Compute: kind = shaderc_compute_shader; break ;
4523- default :
4524- context->shaderSource (shaderPacked, count, string, length);
4525- return ;
4538+ // TODO
4539+ default : return false ;
45264540 }
45274541
45284542 shaderc_compiler_t compiler = p_shaderc_compiler_initialize ();
4529- if (!compiler) {
4530- context->shaderSource (shaderPacked, count, string, length);
4531- return ;
4532- }
4543+ if (!compiler) return false ;
4544+
45334545 shaderc_compile_options_t options = p_shaderc_compile_options_initialize ();
4534- if (!options) {
4546+ if (!options)
4547+ {
45354548 p_shaderc_compiler_release (compiler);
4536- context->shaderSource (shaderPacked, count, string, length);
4537- return ;
4549+ return false ;
45384550 }
45394551
45404552 p_shaderc_compile_options_set_target_env (options, shaderc_target_env_opengl, 450 );
45414553 p_shaderc_compile_options_set_source_language (options, shaderc_source_language_glsl);
4542- p_shaderc_compile_options_set_auto_bind_uniforms (options, 1 );
4554+ p_shaderc_compile_options_set_auto_bind_uniforms (options, true );
45434555
45444556 shaderc_compilation_result_t result = p_shaderc_compile_into_spv (
4545- compiler, originalSource.c_str (), originalSource.size (),
4546- kind, " shader" , " main" , options);
4557+ compiler,
4558+ inputSource.c_str (),
4559+ inputSource.size (),
4560+ kind,
4561+ " shader" ,
4562+ " main" ,
4563+ options);
4564+
45474565 p_shaderc_compile_options_release (options);
45484566
4549- if (!result || p_shaderc_result_get_bytes (result) == nullptr ) {
4567+ bool spvOk = (result != nullptr ) && (p_shaderc_result_get_bytes (result) != nullptr );
4568+ if (!spvOk)
4569+ {
45504570 if (result) p_shaderc_result_release (result);
45514571 p_shaderc_compiler_release (compiler);
4552- context->shaderSource (shaderPacked, count, string, length);
4553- return ;
4572+ return false ;
4573+ }
4574+
4575+ const uint32_t *spvData = reinterpret_cast <const uint32_t *>(p_shaderc_result_get_bytes (result));
4576+ size_t spvWordCount = p_shaderc_result_get_length (result) / sizeof (uint32_t );
4577+
4578+ spvc_context spvcCtx = nullptr ;
4579+ if (p_spvc_context_create (&spvcCtx) != SPVC_SUCCESS || !spvcCtx)
4580+ {
4581+ p_shaderc_result_release (result);
4582+ p_shaderc_compiler_release (compiler);
4583+ return false ;
45544584 }
45554585
4556- const uint32_t * spv_data = reinterpret_cast <const uint32_t *>(p_shaderc_result_get_bytes (result));
4557- size_t spv_word_count = p_shaderc_result_get_length (result) / sizeof (uint32_t );
4586+ spvc_parsed_ir parsedIr = nullptr ;
4587+ if (p_spvc_context_parse_spirv (spvcCtx, spvData, spvWordCount, &parsedIr) != SPVC_SUCCESS || !parsedIr)
4588+ {
4589+ p_spvc_context_destroy (spvcCtx);
4590+ p_shaderc_result_release (result);
4591+ p_shaderc_compiler_release (compiler);
4592+ return false ;
4593+ }
45584594
4559- spirv_cross_t cross = p_spirv_cross_new (spv_data, spv_word_count);
45604595 p_shaderc_result_release (result);
45614596 p_shaderc_compiler_release (compiler);
45624597
4563- if (!cross) {
4564- context->shaderSource (shaderPacked, count, string, length);
4565- return ;
4598+ spvc_compiler spvcCompiler = nullptr ;
4599+ if (p_spvc_context_create_compiler (spvcCtx, SPVC_BACKEND_GLSL , parsedIr,
4600+ SPVC_CAPTURE_MODE_TAKE_OWNERSHIP , &spvcCompiler) != SPVC_SUCCESS ||
4601+ !spvcCompiler)
4602+ {
4603+ p_spvc_context_destroy (spvcCtx);
4604+ return false ;
45664605 }
45674606
4568- p_spirv_cross_set_glsl_version (cross, 320 );
4569- p_spirv_cross_set_es (cross, true );
4607+ spvc_compiler_options spvcOptions = nullptr ;
4608+ if (p_spvc_compiler_create_compiler_options (spvcCompiler, &spvcOptions) != SPVC_SUCCESS || !spvcOptions)
4609+ {
4610+ p_spvc_context_destroy (spvcCtx);
4611+ return false ;
4612+ }
45704613
4571- if (!p_spirv_cross_compile (cross)) {
4572- p_spirv_cross_delete (cross);
4573- context->shaderSource (shaderPacked, count, string, length);
4574- return ;
4614+ p_spvc_compiler_options_set_uint (spvcOptions, SPVC_COMPILER_OPTION_GLSL_VERSION , 320 );
4615+ p_spvc_compiler_options_set_bool (spvcOptions, SPVC_COMPILER_OPTION_GLSL_ES , SPVC_FALSE );
4616+ p_spvc_compiler_options_set_bool (spvcOptions, SPVC_COMPILER_OPTION_GLSL_ENABLE_420PACK_EXTENSION , SPVC_FALSE );
4617+
4618+ if (p_spvc_compiler_install_compiler_options (spvcCompiler, spvcOptions) != SPVC_SUCCESS )
4619+ {
4620+ p_spvc_context_destroy (spvcCtx);
4621+ return false ;
45754622 }
45764623
4577- const char * glsl = p_spirv_cross_get_glsl (cross);
4578- if (!glsl || strlen (glsl) == 0 ) {
4579- p_spirv_cross_delete (cross);
4624+ const char *glslSource = nullptr ;
4625+ if (p_spvc_compiler_compile (spvcCompiler, &glslSource) != SPVC_SUCCESS || !glslSource)
4626+ {
4627+ p_spvc_context_destroy (spvcCtx);
4628+ return false ;
4629+ }
4630+
4631+ outputSource = glslSource;
4632+
4633+ p_spvc_context_destroy (spvcCtx);
4634+ return !outputSource.empty ();
4635+ }
4636+ static void TryConvertAndSetShaderSource (Context *context,
4637+ ShaderProgramID shaderPacked,
4638+ GLsizei count,
4639+ const GLchar *const *string,
4640+ const GLint *length)
4641+ {
4642+ std::string originalSource = MergeShaderSources (count, string, length);
4643+ if (originalSource.empty ())
4644+ {
45804645 context->shaderSource (shaderPacked, count, string, length);
45814646 return ;
45824647 }
45834648
4584- std::string convertedSource (glsl) ;
4585- p_spirv_cross_delete (cross );
4649+ std::string convertedSource;
4650+ bool converted = TryConvertGLSL (context, shaderPacked, originalSource, convertedSource );
45864651
4587- const GLchar *newString = convertedSource.c_str ();
4588- GLint newLength = static_cast <GLint>(convertedSource.size ());
4589- context->shaderSource (shaderPacked, 1 , &newString, &newLength);
4652+ if (converted && !convertedSource.empty ())
4653+ {
4654+ const GLchar *newStrings[] = { convertedSource.c_str () };
4655+ GLint newLengths[] = { static_cast <GLint>(convertedSource.size ()) };
4656+ context->shaderSource (shaderPacked, 1 , newStrings, newLengths);
4657+ }
4658+ else
4659+ {
4660+ context->shaderSource (shaderPacked, count, string, length);
4661+ }
45904662}
45914663void GL_APIENTRY GL_ShaderSource (GLuint shader,
45924664 GLsizei count,
0 commit comments