761{
762 namespace fs = std::filesystem;
763
764 if (!is_command_available("glslc")) {
766 "glslc compiler not found in PATH. Install Vulkan SDK or enable MAYAFLUX_USE_SHADERC");
767 return {};
768 }
769
770 fs::path temp_dir = fs::temp_directory_path();
771 fs::path glsl_temp = temp_dir / "mayaflux_shader_temp.glsl";
772 fs::path spirv_temp = temp_dir / "mayaflux_shader_temp.spv";
773
774 {
775 std::ofstream out(glsl_temp);
776 if (!out.is_open()) {
778 "Failed to create temporary GLSL file: '{}'", glsl_temp.string());
779 return {};
780 }
781 out << glsl_source;
782 }
783
784 std::string stage_flag;
785 switch (stage) {
786 case vk::ShaderStageFlagBits::eVertex:
787 stage_flag = "-fshader-stage=vertex";
788 break;
789 case vk::ShaderStageFlagBits::eFragment:
790 stage_flag = "-fshader-stage=fragment";
791 break;
792 case vk::ShaderStageFlagBits::eCompute:
793 stage_flag = "-fshader-stage=compute";
794 break;
795 case vk::ShaderStageFlagBits::eGeometry:
796 stage_flag = "-fshader-stage=geometry";
797 break;
798 case vk::ShaderStageFlagBits::eTessellationControl:
799 stage_flag = "-fshader-stage=tesscontrol";
800 break;
801 case vk::ShaderStageFlagBits::eTessellationEvaluation:
802 stage_flag = "-fshader-stage=tesseval";
803 break;
804 case vk::ShaderStageFlagBits::eMeshEXT:
805 stage_flag = "-fshader-stage=mesh";
806 break;
807 case vk::ShaderStageFlagBits::eTaskEXT:
808 stage_flag = "-fshader-stage=task";
809 break;
810 default:
812 "Unsupported shader stage for external compilation: {}", vk::to_string(stage));
813 fs::remove(glsl_temp);
814 return {};
815 }
816
817#if defined(MAYAFLUX_PLATFORM_WINDOWS)
818 std::string cmd = "glslc " + stage_flag + " \"" + glsl_temp.string() + "\" -o \"" + spirv_temp.string() + "\"";
819#else
820 std::string cmd = "glslc " + stage_flag + " '" + glsl_temp.string() + "' -o '" + spirv_temp.string() + "'";
821#endif
822
823 for (const auto& dir : include_directories) {
824#if defined(MAYAFLUX_PLATFORM_WINDOWS)
825 cmd += " -I\"" + dir + "\"";
826#else
827 cmd += " -I'" + dir + "'";
828#endif
829 }
830
831 for (const auto& [name, value] : defines) {
832 cmd += " -D" + name;
833 if (!value.empty()) {
834 cmd += "=" + value;
835 }
836 }
837
838 std::string null_device = get_null_device();
839
841 "Invoking external glslc : {}", cmd);
842
843 int result = std::system(cmd.c_str());
844
845 fs::remove(glsl_temp);
846
847 if (result != 0) {
849 "External glslc compilation failed (exit code: {})", result);
851 "Make sure Vulkan SDK is installed or enable MAYAFLUX_USE_SHADERC for runtime compilation");
852 fs::remove(spirv_temp);
853 return {};
854 }
855
857
858 fs::remove(spirv_temp);
859
860 if (!spirv_code.empty()) {
862 "Compiled GLSL ({} stage) via external glslc -> {} bytes SPIR-V",
863 vk::to_string(stage), spirv_code.size() * 4);
864 }
865
866 return spirv_code;
867}
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
static std::vector< uint32_t > read_spirv_file(const std::string &filepath)
Read binary file into vector.
@ GraphicsBackend
Graphics/visual rendering backend (Vulkan, OpenGL)
@ Core
Core engine, backend, subsystems.