From fe1cb39814174d5b8a808eeb56c4ae4964f68f30 Mon Sep 17 00:00:00 2001 From: GhostNaN Date: Thu, 12 Nov 2020 12:19:26 -0500 Subject: [PATCH] Compile GLSL shaders at runtime This will require shaderc as a new dep --- README.md | 4 +++ meson.build | 3 +- vulkan/shader.frag => shaders/default.frag | 0 vulkan/shader.vert => shaders/default.vert | 0 src/vulkan.cpp | 39 ++++++++++++++------- vulkan/frag.spv | Bin 488 -> 0 bytes vulkan/vert.spv | Bin 1084 -> 0 bytes 7 files changed, 32 insertions(+), 14 deletions(-) rename vulkan/shader.frag => shaders/default.frag (100%) rename vulkan/shader.vert => shaders/default.vert (100%) delete mode 100644 vulkan/frag.spv delete mode 100644 vulkan/vert.spv diff --git a/README.md b/README.md index 66f8ed4..32d1ef7 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,8 @@ The Bad: - Teminal display - libconfig - Config file manager +- shaderc + - Runtime shader compilation #### Must have at least one: - portaudio(optional) @@ -39,6 +41,7 @@ AUR package - https://aur.archlinux.org/packages/recidia-audio-visualizer/ #### Requirements: - meson - ninja +- vulkan-headers #### To build: ``` @@ -52,6 +55,7 @@ And if you wish to install: ninja -C build install mkdir ~/.config/recidia/ cp settings.cfg ~/.config/recidia/ +cp -r shaders ~/.config/recidia/ ``` ## Usage diff --git a/meson.build b/meson.build index fb0e9c7..9143392 100644 --- a/meson.build +++ b/meson.build @@ -6,6 +6,7 @@ fftw = dependency('fftw3') threads = dependency('threads') curses = dependency('ncursesw') libconfig = dependency('libconfig++') +shaderc = dependency('shaderc') audio_check = false @@ -31,4 +32,4 @@ qt5 = dependency('qt5', modules: ['Core', 'Gui', 'Widgets']) executable(meson.project_name(), ['src/main.cpp', 'src/audio.c', 'src/processing.cpp', 'src/curses.cpp', 'src/config.cpp', 'src/window.cpp', 'src/vulkan.cpp'], include_directories : ['inc'], -dependencies: [gsl, fftw, threads, curses, libconfig, pulse_simple, portaudio, qt5], install: true) +dependencies: [gsl, fftw, threads, curses, libconfig, pulse_simple, portaudio, qt5, shaderc], install: true) diff --git a/vulkan/shader.frag b/shaders/default.frag similarity index 100% rename from vulkan/shader.frag rename to shaders/default.frag diff --git a/vulkan/shader.vert b/shaders/default.vert similarity index 100% rename from vulkan/shader.vert rename to shaders/default.vert diff --git a/src/vulkan.cpp b/src/vulkan.cpp index dbf8ef2..0f00b9c 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -3,6 +3,7 @@ #include #include +#include #include @@ -82,30 +83,42 @@ VulkanRenderer::VulkanRenderer(VulkanWindow *window) { vulkan_window = window; } -VkShaderModule createShader(const string name) { +VkShaderModule createShader(const string name, shaderc_shader_kind shader_kind) { + string homeDir = getenv("HOME"); + vector shaderFileLocations = {"shaders/", + "../shaders/", + homeDir + "/.config/recidia/shaders/", + "/etc/recidia/shaders/"}; // Read shader file - ifstream file(name, ios::ate | ios::binary); + ifstream file; + for (uint i=0; i < shaderFileLocations.size(); i++) { + file.open(shaderFileLocations[i] + name); + if (file.is_open()) { + break; + } + } if (!file.is_open()) { - throw std::runtime_error("failed to open file!"); + throw std::runtime_error("Failed to find shader file!"); } - size_t fileSize = (size_t) file.tellg(); - std::vector buffer(fileSize); - file.seekg(0); - file.read(buffer.data(), fileSize); + std::string shaderText( (std::istreambuf_iterator(file) ), + (std::istreambuf_iterator() ) ); file.close(); - auto shaderCode = buffer; + shaderc::Compiler compiler; + shaderc::SpvCompilationResult result = compiler.CompileGlslToSpv(shaderText, shader_kind, ""); + vector spvCode; + spvCode.assign(result.cbegin(), result.cend()); VkShaderModuleCreateInfo shaderInfo; shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - shaderInfo.codeSize = shaderCode.size(); - shaderInfo.pCode = reinterpret_cast(shaderCode.data()); + shaderInfo.codeSize = sizeof(uint32_t) * spvCode.size(); + shaderInfo.pCode = (const uint32_t*) spvCode.data(); shaderInfo.pNext = nullptr; // WILL SEGV WITHOUT VkShaderModule shaderModule; VkResult err = dev_funct->vkCreateShaderModule(vulkan_dev, &shaderInfo, nullptr, &shaderModule); if (err != VK_SUCCESS) { - qWarning("Failed to create shader module: %d", err); + printf("Failed to create shader module: %d\n", err); return VK_NULL_HANDLE; } @@ -167,8 +180,8 @@ void VulkanRenderer::initResources() { pipelineInfo.pVertexInputState = &vertexInputInfo; // Shaders - VkShaderModule vertShaderModule = createShader("../vulkan/vert.spv"); - VkShaderModule fragShaderModule = createShader("../vulkan/frag.spv"); + VkShaderModule vertShaderModule = createShader("default.vert", shaderc_shader_kind::shaderc_glsl_vertex_shader); + VkShaderModule fragShaderModule = createShader("default.frag", shaderc_shader_kind::shaderc_glsl_fragment_shader); VkPipelineShaderStageCreateInfo vertShaderStageInfo{}; vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; diff --git a/vulkan/frag.spv b/vulkan/frag.spv deleted file mode 100644 index 52738f7aff0d4eebbd34e01c5126dfb8875b4f69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 488 zcmYk2-Acni5QWF4+t$>dilBE=@xFMWA`}HHlAAz5A7ELNRUa^dX%&pU=+DPf6@Z6hJb&GL$|%?adSw z6PvIxYyyrt3SbxER*_E}>Vrs9eRIFi&Niks-fH(^a@*?q@zrMDk%`G9%Vm<@>8xqA z^B<+vWl>q37cHpb-I5!1xT4C+Ro(>@h;DC6ROqi>`P;gzTeJj4g?^t}^Sl-loZ=iu z1h5!$rgglJX*kbum`uX{0Q&*7DeMqD=Vr|MQ~XEpd^zg#znC?sF(1R@dH(Z^S(DlY fdSpG`#l)iBDGM7S8GX3F!W9lo=p$;8&p&)nJE7tW4-C6>Q&@RsIyz8K}#<9R|N#=NdX_gRsStK43= z>XWM)_d}u37H3bctbOClLg-@PbI*YLqPg_H)R~$#$Gwz0%l+i7ubZqGxmk`Wk-N_G zSuW8mm=7z_k2(2b)-qts?Msziot1f61zs=A(HAZ9UM%jxiauiPyYZsNL=27a&=WEC zV9X~~hCRGg2$~LMEMoM`$Gj;qJ+@Uv-9w$hne6wpTaX{f_EoPBEX4HMRlFoWkg*<3 zW4?}q62YwGW6Pj9qRPt5GV$REgaR?HJKOR#5pQ*_1xrVebF{