|
9 | 9 | #include <cstring> |
10 | 10 | #include <fstream> |
11 | 11 |
|
| 12 | +#include <glslang/Public/ShaderLang.h> |
| 13 | +#include <glslang/Public/ResourceLimits.h> |
| 14 | +#include <glslang/SPIRV/GlslangToSpv.h> |
| 15 | + |
12 | 16 | #include "vulkanapp.h" |
13 | 17 |
|
14 | 18 | namespace OCIO_NAMESPACE |
@@ -651,25 +655,71 @@ void VulkanBuilder::buildShader(GpuShaderDescRcPtr & shaderDesc) |
651 | 655 |
|
652 | 656 | std::vector<uint32_t> VulkanBuilder::compileGLSLToSPIRV(const std::string & glslSource) |
653 | 657 | { |
654 | | - // This is a placeholder for GLSL to SPIR-V compilation. |
655 | | - // In a real implementation, you would use: |
656 | | - // - glslang library (libglslang) |
657 | | - // - shaderc library |
658 | | - // - Or call glslangValidator/glslc externally |
659 | | - |
660 | | - // For now, we'll throw an error indicating that SPIR-V compilation |
661 | | - // needs to be implemented with a proper shader compiler. |
| 658 | + // Initialize glslang (safe to call multiple times) |
| 659 | + static bool glslangInitialized = false; |
| 660 | + if (!glslangInitialized) |
| 661 | + { |
| 662 | + glslang::InitializeProcess(); |
| 663 | + glslangInitialized = true; |
| 664 | + } |
| 665 | + |
| 666 | + // Create shader object |
| 667 | + glslang::TShader shader(EShLangCompute); |
662 | 668 |
|
663 | | - // TODO: Implement GLSL to SPIR-V compilation using glslang or shaderc |
664 | | - // Example with shaderc: |
665 | | - // shaderc::Compiler compiler; |
666 | | - // shaderc::CompileOptions options; |
667 | | - // options.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_2); |
668 | | - // auto result = compiler.CompileGlslToSpv(glslSource, shaderc_compute_shader, "shader.comp", options); |
669 | | - // return std::vector<uint32_t>(result.cbegin(), result.cend()); |
670 | | - |
671 | | - throw std::runtime_error("GLSL to SPIR-V compilation not yet implemented. " |
672 | | - "Please link against glslang or shaderc library."); |
| 669 | + const char * shaderStrings[1] = { glslSource.c_str() }; |
| 670 | + shader.setStrings(shaderStrings, 1); |
| 671 | + |
| 672 | + // Set up Vulkan 1.2 / SPIR-V 1.5 environment |
| 673 | + shader.setEnvInput(glslang::EShSourceGlsl, EShLangCompute, glslang::EShClientVulkan, 460); |
| 674 | + shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_2); |
| 675 | + shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_5); |
| 676 | + |
| 677 | + // Get default resource limits |
| 678 | + const TBuiltInResource * resources = GetDefaultResources(); |
| 679 | + |
| 680 | + // Parse the shader |
| 681 | + const int defaultVersion = 460; |
| 682 | + const bool forwardCompatible = false; |
| 683 | + const EShMessages messages = static_cast<EShMessages>(EShMsgSpvRules | EShMsgVulkanRules); |
| 684 | + |
| 685 | + if (!shader.parse(resources, defaultVersion, forwardCompatible, messages)) |
| 686 | + { |
| 687 | + std::string errorMsg = "GLSL parsing failed:\n"; |
| 688 | + errorMsg += shader.getInfoLog(); |
| 689 | + errorMsg += "\n"; |
| 690 | + errorMsg += shader.getInfoDebugLog(); |
| 691 | + throw std::runtime_error(errorMsg); |
| 692 | + } |
| 693 | + |
| 694 | + // Create program and link |
| 695 | + glslang::TProgram program; |
| 696 | + program.addShader(&shader); |
| 697 | + |
| 698 | + if (!program.link(messages)) |
| 699 | + { |
| 700 | + std::string errorMsg = "GLSL linking failed:\n"; |
| 701 | + errorMsg += program.getInfoLog(); |
| 702 | + errorMsg += "\n"; |
| 703 | + errorMsg += program.getInfoDebugLog(); |
| 704 | + throw std::runtime_error(errorMsg); |
| 705 | + } |
| 706 | + |
| 707 | + // Convert to SPIR-V |
| 708 | + std::vector<uint32_t> spirv; |
| 709 | + glslang::SpvOptions spvOptions; |
| 710 | + spvOptions.generateDebugInfo = false; |
| 711 | + spvOptions.stripDebugInfo = true; |
| 712 | + spvOptions.disableOptimizer = false; |
| 713 | + spvOptions.optimizeSize = false; |
| 714 | + |
| 715 | + glslang::GlslangToSpv(*program.getIntermediate(EShLangCompute), spirv, &spvOptions); |
| 716 | + |
| 717 | + if (spirv.empty()) |
| 718 | + { |
| 719 | + throw std::runtime_error("SPIR-V generation produced empty output"); |
| 720 | + } |
| 721 | + |
| 722 | + return spirv; |
673 | 723 | } |
674 | 724 |
|
675 | 725 | void VulkanBuilder::allocateAllTextures(unsigned maxTextureSize) |
|
0 commit comments