From ef16ef8887c00bc3130335aa222c7c3b2b736cdb Mon Sep 17 00:00:00 2001 From: shg8 Date: Wed, 21 Feb 2024 16:20:23 -0600 Subject: [PATCH] Bundled shaders --- 3dgs/GSScene.cpp | 5 ++++- 3dgs/Renderer.cpp | 15 ++++++++------- CMakeLists.txt | 24 ++++++++++++++++++++++-- vulkan/Shader.cpp | 19 ++++++++++++------- vulkan/Shader.h | 22 +++++++++++++++++++--- vulkan/pipelines/ComputePipeline.cpp | 6 +++--- vulkan/pipelines/ComputePipeline.h | 5 +++-- 7 files changed, 71 insertions(+), 25 deletions(-) diff --git a/3dgs/GSScene.cpp b/3dgs/GSScene.cpp index c3514be..85d8e2f 100644 --- a/3dgs/GSScene.cpp +++ b/3dgs/GSScene.cpp @@ -6,6 +6,7 @@ #include "GSScene.h" #include +#include "shaders.h" #include "../vulkan/Utils.h" #include "../vulkan/DescriptorSet.h" @@ -155,7 +156,9 @@ std::shared_ptr GSScene::createBuffer(const std::shared_ptr&context) { cov3DBuffer = createBuffer(context, header.numVertices * sizeof(float) * 6); - auto pipeline = std::make_shared(context, "precomp_cov3d"); + auto pipeline = std::make_shared( + context, std::make_shared(context, "precomp_cov3d", SPV_PRECOMP_COV3D, SPV_PRECOMP_COV3D_len)); + auto descriptorSet = std::make_shared(context, FRAMES_IN_FLIGHT); descriptorSet->bindBufferToDescriptorSet(0, vk::DescriptorType::eStorageBuffer, vk::ShaderStageFlagBits::eCompute, vertexBuffer); diff --git a/3dgs/Renderer.cpp b/3dgs/Renderer.cpp index 91215f9..2b0952c 100644 --- a/3dgs/Renderer.cpp +++ b/3dgs/Renderer.cpp @@ -5,6 +5,7 @@ #include "../vulkan/Swapchain.h" #include +#include #include #include @@ -129,7 +130,7 @@ void Renderer::createPreprocessPipeline() { vertexAttributeBuffer = Buffer::storage(context, scene->getNumVertices() * sizeof(VertexAttributeBuffer), false); tileOverlapBuffer = Buffer::storage(context, scene->getNumVertices() * sizeof(uint32_t), false); - preprocessPipeline = std::make_shared(context, "preprocess"); + preprocessPipeline = std::make_shared(context, std::make_shared(context, "preprocess", SPV_PREPROCESS, SPV_PREPROCESS_len)); inputSet = std::make_shared(context, FRAMES_IN_FLIGHT); inputSet->bindBufferToDescriptorSet(0, vk::DescriptorType::eStorageBuffer, vk::ShaderStageFlagBits::eCompute, scene->vertexBuffer); @@ -174,7 +175,7 @@ void Renderer::createPrefixSumPipeline() { prefixSumPongBuffer = Buffer::storage(context, scene->getNumVertices() * sizeof(uint32_t), false); totalSumBufferHost = Buffer::staging(context, sizeof(uint32_t)); - prefixSumPipeline = std::make_shared(context, "prefix_sum"); + prefixSumPipeline = std::make_shared(context, std::make_shared(context, "prefix_sum", SPV_PREFIX_SUM, SPV_PREFIX_SUM_len)); auto descriptorSet = std::make_shared(context, FRAMES_IN_FLIGHT); descriptorSet->bindBufferToDescriptorSet(0, vk::DescriptorType::eStorageBuffer, vk::ShaderStageFlagBits::eCompute, prefixSumPingBuffer); @@ -206,8 +207,8 @@ void Renderer::createRadixSortPipeline() { sortHistBuffer = Buffer::storage(context, numWorkgroups * 256 * sizeof(uint32_t), false); - sortHistPipeline = std::make_shared(context, "hist"); - sortPipeline = std::make_shared(context, "sort"); + sortHistPipeline = std::make_shared(context, std::make_shared(context, "hist", SPV_HIST, SPV_HIST_len)); + sortPipeline = std::make_shared(context, std::make_shared(context, "sort", SPV_SORT, SPV_SORT_len)); auto descriptorSet = std::make_shared(context, FRAMES_IN_FLIGHT); descriptorSet->bindBufferToDescriptorSet(0, vk::DescriptorType::eStorageBuffer, vk::ShaderStageFlagBits::eCompute, @@ -248,7 +249,7 @@ void Renderer::createRadixSortPipeline() { void Renderer::createPreprocessSortPipeline() { spdlog::debug("Creating preprocess sort pipeline"); - preprocessSortPipeline = std::make_shared(context, "preprocess_sort"); + preprocessSortPipeline = std::make_shared(context, std::make_shared(context, "preprocess_sort", SPV_PREPROCESS_SORT, SPV_PREPROCESS_SORT_len)); auto descriptorSet = std::make_shared(context, FRAMES_IN_FLIGHT); descriptorSet->bindBufferToDescriptorSet(0, vk::DescriptorType::eStorageBuffer, vk::ShaderStageFlagBits::eCompute, vertexAttributeBuffer); @@ -274,7 +275,7 @@ void Renderer::createTileBoundaryPipeline() { auto tileY = (height + 16 - 1) / 16; tileBoundaryBuffer = Buffer::storage(context, tileX * tileY * sizeof(uint32_t) * 2, false); - tileBoundaryPipeline = std::make_shared(context, "tile_boundary"); + tileBoundaryPipeline = std::make_shared(context, std::make_shared(context, "tile_boundary", SPV_TILE_BOUNDARY, SPV_TILE_BOUNDARY_len)); auto descriptorSet = std::make_shared(context, FRAMES_IN_FLIGHT); descriptorSet->bindBufferToDescriptorSet(0, vk::DescriptorType::eStorageBuffer, vk::ShaderStageFlagBits::eCompute, sortKBufferEven); @@ -291,7 +292,7 @@ void Renderer::createTileBoundaryPipeline() { void Renderer::createRenderPipeline() { spdlog::debug("Creating render pipeline"); - renderPipeline = std::make_shared(context, "render"); + renderPipeline = std::make_shared(context, std::make_shared(context, "render", SPV_RENDER, SPV_RENDER_len)); auto inputSet = std::make_shared(context, FRAMES_IN_FLIGHT); inputSet->bindBufferToDescriptorSet(0, vk::DescriptorType::eStorageBuffer, vk::ShaderStageFlagBits::eCompute, vertexAttributeBuffer); diff --git a/CMakeLists.txt b/CMakeLists.txt index 548c456..e05044e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,21 +89,41 @@ if (APPLE) list(APPEND GLSLC_DEFINE "-DAPPLE") endif () +set(SHADER_HEADER "${PROJECT_BINARY_DIR}/shaders/shaders.h") +message(STATUS "Shader header file: ${SHADER_HEADER}") + foreach (GLSL ${GLSL_SOURCE_FILES}) - get_filename_component(FILE_NAME ${GLSL} NAME) + get_filename_component(FILE_NAME ${GLSL} NAME_WE) + string(TOUPPER ${FILE_NAME} FILE_NAME_UPPER) + set(FILE_NAME_UPPER "SPV_${FILE_NAME_UPPER}") set(SPIRV "${PROJECT_BINARY_DIR}/shaders/${FILE_NAME}.spv") + SET(TEMP_HEADER "${PROJECT_BINARY_DIR}/shaders/${FILE_NAME}.h") add_custom_command( OUTPUT ${SPIRV} COMMAND ${CMAKE_COMMAND} -E make_directory "${PROJECT_BINARY_DIR}/shaders/" COMMAND ${Vulkan_GLSLANG_VALIDATOR_EXECUTABLE} "--target-env" "vulkan1.2" -V ${GLSL} -o ${SPIRV} ${GLSLC_DEFINE} DEPENDS ${GLSL}) list(APPEND SPIRV_BINARY_FILES ${SPIRV}) + + add_custom_command( + OUTPUT ${TEMP_HEADER} + COMMAND xxd -i -n ${FILE_NAME_UPPER} ${SPIRV} > ${TEMP_HEADER} + DEPENDS ${SPIRV}) + + list(APPEND TEMP_HEADERS ${TEMP_HEADER}) endforeach (GLSL) +add_custom_command( + OUTPUT ${SHADER_HEADER} + COMMAND cat ${TEMP_HEADERS} > ${SHADER_HEADER} + DEPENDS ${TEMP_HEADERS} +) + add_custom_target( Shaders - DEPENDS ${SPIRV_BINARY_FILES} + DEPENDS ${SPIRV_BINARY_FILES} ${SHADER_HEADER} ) +include_directories(${PROJECT_BINARY_DIR}/shaders) include_directories(third_party) diff --git a/vulkan/Shader.cpp b/vulkan/Shader.cpp index 5e48a4b..7c24488 100644 --- a/vulkan/Shader.cpp +++ b/vulkan/Shader.cpp @@ -2,13 +2,18 @@ #include "Utils.h" void Shader::load() { - auto filename = "shaders/" + name + ".comp.spv"; - auto shader_code = Utils::readFile(filename); - if (shader_code.empty()) { - throw std::runtime_error("Failed to load shader: " + filename); - } vk::ShaderModuleCreateInfo create_info; - create_info.codeSize = shader_code.size(); - create_info.pCode = reinterpret_cast(shader_code.data()); + if (data == nullptr) { + auto fn = "shaders/" + filename + ".spv"; + auto shader_code = Utils::readFile(fn); + if (shader_code.empty()) { + throw std::runtime_error("Failed to load shader: " + fn); + } + create_info.codeSize = shader_code.size(); + create_info.pCode = reinterpret_cast(shader_code.data()); + } else { + create_info.codeSize = size; + create_info.pCode = reinterpret_cast(data); + } shader = context->device->createShaderModuleUnique(create_info); } diff --git a/vulkan/Shader.h b/vulkan/Shader.h index 31e19b5..9508420 100644 --- a/vulkan/Shader.h +++ b/vulkan/Shader.h @@ -9,17 +9,33 @@ class Shader { public: - Shader(const std::shared_ptr& _context, std::string name) + Shader(const std::shared_ptr& _context, std::string filename) : context(_context), - name(std::move(name)) { + filename(std::move(filename)) { + } + + Shader(const std::shared_ptr& _context, unsigned char *data, size_t size) + : context(_context), + filename(""), + data(data), + size(size) { + } + + Shader(const std::shared_ptr& context, const std::string& filename, unsigned char* data, size_t size) + : filename(filename), + context(context), + data(data), + size(size) { } void load(); vk::UniqueShaderModule shader; private: - const std::string name; + const std::string filename; std::shared_ptr context; + unsigned char* data; + size_t size; }; diff --git a/vulkan/pipelines/ComputePipeline.cpp b/vulkan/pipelines/ComputePipeline.cpp index d4f36ea..83cad78 100644 --- a/vulkan/pipelines/ComputePipeline.cpp +++ b/vulkan/pipelines/ComputePipeline.cpp @@ -2,14 +2,14 @@ #include "ComputePipeline.h" -ComputePipeline::ComputePipeline(const std::shared_ptr &context, const std::string &shaderFile) : Pipeline(context), shader(context, shaderFile) { - shader.load(); +ComputePipeline::ComputePipeline(const std::shared_ptr& context, std::shared_ptr shader): Pipeline(context), shader(std::move(shader)) { + shader->load(); } void ComputePipeline::build() { buildPipelineLayout(); - vk::PipelineShaderStageCreateInfo pipelineShaderStageCreateInfo({}, vk::ShaderStageFlagBits::eCompute, shader.shader.get(), "main"); + vk::PipelineShaderStageCreateInfo pipelineShaderStageCreateInfo({}, vk::ShaderStageFlagBits::eCompute, shader->shader.get(), "main"); vk::ComputePipelineCreateInfo computePipelineCreateInfo({}, pipelineShaderStageCreateInfo, pipelineLayout.get()); pipeline = context->device->createComputePipelineUnique(nullptr, computePipelineCreateInfo).value; } diff --git a/vulkan/pipelines/ComputePipeline.h b/vulkan/pipelines/ComputePipeline.h index 63e2ac7..62c8bc9 100644 --- a/vulkan/pipelines/ComputePipeline.h +++ b/vulkan/pipelines/ComputePipeline.h @@ -5,14 +5,15 @@ #include "Pipeline.h" +#include class ComputePipeline : public Pipeline { public: - explicit ComputePipeline(const std::shared_ptr &context, const std::string& shader); + explicit ComputePipeline(const std::shared_ptr &context, std::shared_ptr shader);; void build() override; private: - Shader shader; + std::shared_ptr shader; };