From 5aa84db3e25108c13134be0fe1bc29b63e825035 Mon Sep 17 00:00:00 2001 From: Metehan Tuncbilek Date: Mon, 15 Jul 2024 17:30:29 +0300 Subject: [PATCH 1/6] utils::ReadFile nullTerminateString addition --- openVulkanoCpp/Base/Utils.cpp | 6 ++++-- openVulkanoCpp/Base/Utils.hpp | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/openVulkanoCpp/Base/Utils.cpp b/openVulkanoCpp/Base/Utils.cpp index d3f8fd1..a028fe6 100644 --- a/openVulkanoCpp/Base/Utils.cpp +++ b/openVulkanoCpp/Base/Utils.cpp @@ -61,7 +61,7 @@ namespace OpenVulkano #endif } - Array Utils::ReadFile(const std::string& filePath, bool emptyOnMissing) + Array Utils::ReadFile(const std::string& filePath, bool emptyOnMissing, bool nullTerminateString) { std::ifstream file(filePath, std::ios::ate | std::ios::binary); if (!file.is_open()) @@ -69,7 +69,9 @@ namespace OpenVulkano if (emptyOnMissing) return {}; throw std::runtime_error("Failed to open file '" + filePath + "'!"); } - const size_t fileSize = static_cast(file.tellg()); + size_t fileSize = static_cast(file.tellg()); + if (nullTerminateString) fileSize++; + Array data(fileSize); file.seekg(0); file.read(data.Data(), fileSize); diff --git a/openVulkanoCpp/Base/Utils.hpp b/openVulkanoCpp/Base/Utils.hpp index a29ea03..391a322 100644 --- a/openVulkanoCpp/Base/Utils.hpp +++ b/openVulkanoCpp/Base/Utils.hpp @@ -159,7 +159,8 @@ namespace OpenVulkano return subs; } - static Array ReadFile(const std::string& filePath, bool emptyOnMissing = false); + static Array ReadFile(const std::string& filePath, bool emptyOnMissing = false, + bool nullTerminateString = false); template static int GetUniqueTypeId() From 2b36969a84f39698c05f99605a640ef3d9e7178d Mon Sep 17 00:00:00 2001 From: Metehan Tuncbilek Date: Mon, 15 Jul 2024 17:31:02 +0300 Subject: [PATCH 2/6] Runtime ShaderCompilation with Include Features --- .idea/.name | 2 +- cmake/SetupVulkan.cmake | 13 ++- examples/main.cpp | 7 ++ openVulkanoCpp/Shader/ShaderCompiler.cpp | 100 ++++++++++++++++++ openVulkanoCpp/Shader/ShaderCompiler.hpp | 45 ++++++++ .../Vulkan/Resources/ManagedBuffer.hpp | 4 + .../Vulkan/Resources/MemoryPool.cpp | 7 +- .../Vulkan/Resources/MemoryPool.hpp | 14 +-- 8 files changed, 180 insertions(+), 12 deletions(-) create mode 100644 openVulkanoCpp/Shader/ShaderCompiler.cpp create mode 100644 openVulkanoCpp/Shader/ShaderCompiler.hpp diff --git a/.idea/.name b/.idea/.name index d8662b5..f081644 100644 --- a/.idea/.name +++ b/.idea/.name @@ -1 +1 @@ -OpenVulkano +openVulkanoCpp \ No newline at end of file diff --git a/cmake/SetupVulkan.cmake b/cmake/SetupVulkan.cmake index a880584..b386f3a 100644 --- a/cmake/SetupVulkan.cmake +++ b/cmake/SetupVulkan.cmake @@ -4,7 +4,17 @@ function(SetupVulkan TARGET) target_link_libraries(${TARGET} PRIVATE ${MoltenVK_LIBRARIES}) else () find_package(Vulkan REQUIRED) + get_filename_component(Vulkan_SDK_DIR "${Vulkan_LIBRARIES}" DIRECTORY) # Get VulkanSDK/[version]/Bin target_link_libraries(${TARGET} PRIVATE Vulkan::Vulkan) + if(CMAKE_BUILD_TYPE MATCHES "Debug") + target_link_libraries(${TARGET} PRIVATE "${Vulkan_SDK_DIR}/shaderc_combinedd.lib" + "${Vulkan_SDK_DIR}/spirv-cross-cored.lib" "${Vulkan_SDK_DIR}/spirv-cross-glsld.lib" + "${Vulkan_SDK_DIR}/spirv-cross-hlsld.lib") + else() + target_link_libraries(${TARGET} PRIVATE "${Vulkan_SDK_DIR}/shaderc_combined.lib" + "${Vulkan_SDK_DIR}/spirv-cross-core.lib" "${Vulkan_SDK_DIR}/spirv-cross-glsl.lib" + "${Vulkan_SDK_DIR}/spirv-cross-hlsl.lib") + endif() endif () target_include_directories(${TARGET} PUBLIC ${Vulkan_INCLUDE_DIR}) @@ -17,4 +27,5 @@ function(SetupVulkan TARGET) find_package(XCB REQUIRED) target_link_libraries(${TARGET} PRIVATE ${XCB_LIBRARIES}) endif() -endfunction() \ No newline at end of file +endfunction() + diff --git a/examples/main.cpp b/examples/main.cpp index 18a8431..ed4ab7d 100644 --- a/examples/main.cpp +++ b/examples/main.cpp @@ -17,10 +17,17 @@ #include #include +#include "Shader/ShaderCompiler.hpp" + using namespace OpenVulkano; int main(int argc, char** argv) { + // TEST CASE + if (false) + ShaderCompiler::CompileGLSLToSpirv(R"(D:\Projects\OpenVulkano\openVulkanoCpp\Shader\grid.vert)", "", "main", + shaderc_vertex_shader, false); + std::vector examples = { "Cubes Example App", "Moving Cube Example App", diff --git a/openVulkanoCpp/Shader/ShaderCompiler.cpp b/openVulkanoCpp/Shader/ShaderCompiler.cpp new file mode 100644 index 0000000..c2113fc --- /dev/null +++ b/openVulkanoCpp/Shader/ShaderCompiler.cpp @@ -0,0 +1,100 @@ +#include "ShaderCompiler.hpp" + +namespace OpenVulkano +{ + Unique ShaderCompiler::CompileGLSLToSpirv(const std::string& absPath, const std::string& incPath, + const std::string& entryPoint, shaderc_shader_kind shaderStage, + bool bHaveIncludes) + { + Array file = Utils::ReadFile(absPath, false, true); + +#if defined(_DEBUG) + printf("Compiling shader: %s\n", absPath.c_str()); + printf("%s\n", file.Data() + 1); +#endif + + shaderc::Compiler shaderCompiler; + shaderc::CompileOptions options; + + if (bHaveIncludes) options.SetIncluder(std::make_unique(incPath)); + options.SetSourceLanguage(shaderc_source_language_glsl); + options.SetSuppressWarnings(); + + shaderc::PreprocessedSourceCompilationResult preResult = + shaderCompiler.PreprocessGlsl(file.Data(), shaderStage, entryPoint.c_str(), options); + + if (preResult.GetCompilationStatus() != shaderc_compilation_status_success) + { + throw std::runtime_error("Failed to preprocess shader: " + preResult.GetErrorMessage()); + return nullptr; + } + + shaderc::CompilationResult result = + shaderCompiler.CompileGlslToSpv(static_cast(preResult.begin()), shaderStage, "", options); + + if (result.GetCompilationStatus() != shaderc_compilation_status_success) + { + throw std::runtime_error("Failed to compile shader: " + result.GetErrorMessage()); + return nullptr; + } + + Unique spirv = std::make_unique((void*) result.begin()); + return spirv; + } + + ShaderIncluder::ShaderIncluder(const std::string& path) + { + // TODO : Add the path to your include folder + m_includes.push_back(path); + } + + shaderc_include_result* ShaderIncluder::GetInclude(const char* requested_source, shaderc_include_type type, + const char* requesting_source, uint64_t include_depth) + { + const char* includePath = GetActualPath(requested_source); + const char* content = RecordInclude(includePath); + + shaderc_include_result* result = new shaderc_include_result(); + result->content = content; + result->content_length = strlen(content); + result->source_name = includePath; + result->source_name_length = strlen(includePath); + result->user_data = nullptr; + + return result; + } + + void ShaderIncluder::ReleaseInclude(shaderc_include_result* data) { delete data; } + + std::string ShaderIncluder::ResolveInclude(const std::string requestedSource) + { + // Check if the file exists in the include paths + for (const std::string& includePath: m_includes) + { + std::string path = includePath + requestedSource; + return path; + } + + return ""; + } + + const char* ShaderIncluder::RecordInclude(const std::string& requestedSource) + { + Array data = Utils::ReadFile(requestedSource); + + char* result = new char[data.Size() + 1]; + strcpy_s(result, data.Size(), data.Data()); + + return result; + } + + const char* ShaderIncluder::GetActualPath(const std::string& requestedSource) + { + std::string includePath = ResolveInclude(requestedSource); + + char* result = new char[includePath.size() + 1]; + strcpy_s(result, includePath.size(), includePath.c_str()); + + return result; + } +} diff --git a/openVulkanoCpp/Shader/ShaderCompiler.hpp b/openVulkanoCpp/Shader/ShaderCompiler.hpp new file mode 100644 index 0000000..b4d083d --- /dev/null +++ b/openVulkanoCpp/Shader/ShaderCompiler.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include "Base/Utils.hpp" +#include "Base/Wrapper.hpp" + +#include +#include +#include + +namespace OpenVulkano +{ + class ShaderIncluder : public shaderc::CompileOptions::IncluderInterface + { + public: + ShaderIncluder(const std::string& path); + ~ShaderIncluder() override = default; + + shaderc_include_result* GetInclude(const char* requested_source, shaderc_include_type type, + const char* requesting_source, uint64_t include_depth) override; + void ReleaseInclude(shaderc_include_result* data) override; + + private: + std::string ResolveInclude(const std::string requestedSource); + const char* RecordInclude(const std::string& requestedSource); + const char* GetActualPath(const std::string& requestedSource); + + private: + std::vector m_includes; + }; + + class ShaderCompiler + { + public: + /** + * @param absPath - absolute path of the shader that needs to be compiled + * @param incPath - include path that will be used to resolve includes + * @param entryPoint - the name of the void function in the shader + * @param shaderStage - type of the shader that needs to be compiled + * @param bHaveIncludes - if incPath is empty, make it false + */ + static Unique CompileGLSLToSpirv(const std::string& absPath, + const std::string& incPath, const std::string& entryPoint, + shaderc_shader_kind shaderStage, bool bHaveIncludes); + }; +} \ No newline at end of file diff --git a/openVulkanoCpp/Vulkan/Resources/ManagedBuffer.hpp b/openVulkanoCpp/Vulkan/Resources/ManagedBuffer.hpp index 86c1629..998a7fc 100644 --- a/openVulkanoCpp/Vulkan/Resources/ManagedBuffer.hpp +++ b/openVulkanoCpp/Vulkan/Resources/ManagedBuffer.hpp @@ -27,6 +27,10 @@ namespace OpenVulkano::Vulkan vk::MemoryPropertyFlags properties; void* mapped = nullptr; + ManagedBuffer(MemoryAllocation* alloc, vk::DeviceSize offset, vk::DeviceSize size, vk::Buffer buffer, vk::BufferUsageFlags usageFlags, vk::MemoryPropertyFlags memProperties) + : allocation(alloc), offset(offset), size(size), buffer(buffer), usage(usageFlags), properties(memProperties), mapped(nullptr) + {} + ~ManagedBuffer() { allocation->device.destroy(buffer); diff --git a/openVulkanoCpp/Vulkan/Resources/MemoryPool.cpp b/openVulkanoCpp/Vulkan/Resources/MemoryPool.cpp index 6fe32c5..4292dc3 100644 --- a/openVulkanoCpp/Vulkan/Resources/MemoryPool.cpp +++ b/openVulkanoCpp/Vulkan/Resources/MemoryPool.cpp @@ -131,7 +131,7 @@ namespace OpenVulkano::Vulkan uint32_t offset = Utils::Align(allocation->used, memoryRequirements.alignment); device->device.bindBufferMemory(buffer, allocation->memory, offset); allocation->used += size + (offset - allocation->used); - return ManagedBufferPtr{ new ManagedBuffer({allocation, offset, size, buffer, usage, properties, nullptr}) }; + return ManagedBufferPtr{ new ManagedBuffer(allocation, offset, size, buffer, usage, properties) }; } MemoryPool::ManagedBufferPtr MemoryPool::CreateSharedMemoryBuffer(size_t size) @@ -150,4 +150,9 @@ namespace OpenVulkano::Vulkan } return CreateBuffer(size, vk::BufferUsageFlagBits::eVertexBuffer, vk::MemoryPropertyFlagBits::eHostCoherent/* | vk::MemoryPropertyFlagBits::eDeviceLocal*/); } + + void ManagedBufferDeleter::operator()(ManagedBuffer* buffer) + { + MemoryPool::ReleaseBuffer(buffer); + } } diff --git a/openVulkanoCpp/Vulkan/Resources/MemoryPool.hpp b/openVulkanoCpp/Vulkan/Resources/MemoryPool.hpp index abd75df..2d5129e 100644 --- a/openVulkanoCpp/Vulkan/Resources/MemoryPool.hpp +++ b/openVulkanoCpp/Vulkan/Resources/MemoryPool.hpp @@ -17,7 +17,11 @@ namespace OpenVulkano::Vulkan class Device; class MemoryAllocation; class ManagedBuffer; - struct ManagedBufferDeleter; + + struct ManagedBufferDeleter + { + void operator()(ManagedBuffer* buffer); + }; class MemoryPool { @@ -55,12 +59,4 @@ namespace OpenVulkano::Vulkan static void ReleaseBuffer(ManagedBuffer* buffer); }; - - struct ManagedBufferDeleter - { - void operator()(ManagedBuffer* buffer) - { - MemoryPool::ReleaseBuffer(buffer); - } - }; } \ No newline at end of file From 97518bd57b83c46f74d2acaf8153cc99b304a68e Mon Sep 17 00:00:00 2001 From: Metehan Tuncbilek Date: Tue, 16 Jul 2024 11:08:00 +0300 Subject: [PATCH 3/6] dead skin removal at main.cpp --- examples/main.cpp | 5 ----- openVulkanoCpp/Shader/ShaderCompiler.cpp | 1 + 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/examples/main.cpp b/examples/main.cpp index ed4ab7d..c0a103b 100644 --- a/examples/main.cpp +++ b/examples/main.cpp @@ -23,11 +23,6 @@ using namespace OpenVulkano; int main(int argc, char** argv) { - // TEST CASE - if (false) - ShaderCompiler::CompileGLSLToSpirv(R"(D:\Projects\OpenVulkano\openVulkanoCpp\Shader\grid.vert)", "", "main", - shaderc_vertex_shader, false); - std::vector examples = { "Cubes Example App", "Moving Cube Example App", diff --git a/openVulkanoCpp/Shader/ShaderCompiler.cpp b/openVulkanoCpp/Shader/ShaderCompiler.cpp index c2113fc..2f24c67 100644 --- a/openVulkanoCpp/Shader/ShaderCompiler.cpp +++ b/openVulkanoCpp/Shader/ShaderCompiler.cpp @@ -72,6 +72,7 @@ namespace OpenVulkano for (const std::string& includePath: m_includes) { std::string path = includePath + requestedSource; + // TODO: Need to check if the folder exists return path; } From ac1c5f20ecfb1e1809e6e113e7488cbc4175e2e7 Mon Sep 17 00:00:00 2001 From: Metehan Tuncbilek Date: Tue, 16 Jul 2024 14:59:09 +0300 Subject: [PATCH 4/6] review fixes --- examples/main.cpp | 2 - openVulkanoCpp/Base/Utils.cpp | 18 ++++-- openVulkanoCpp/Shader/ShaderCompiler.cpp | 78 ++++++++---------------- openVulkanoCpp/Shader/ShaderCompiler.hpp | 16 +++-- openVulkanoCpp/Shader/test.vert | 8 +++ openVulkanoCpp/Shader/test1.glsl | 3 + 6 files changed, 59 insertions(+), 66 deletions(-) create mode 100644 openVulkanoCpp/Shader/test.vert create mode 100644 openVulkanoCpp/Shader/test1.glsl diff --git a/examples/main.cpp b/examples/main.cpp index c0a103b..18a8431 100644 --- a/examples/main.cpp +++ b/examples/main.cpp @@ -17,8 +17,6 @@ #include #include -#include "Shader/ShaderCompiler.hpp" - using namespace OpenVulkano; int main(int argc, char** argv) diff --git a/openVulkanoCpp/Base/Utils.cpp b/openVulkanoCpp/Base/Utils.cpp index a028fe6..cbdd6ed 100644 --- a/openVulkanoCpp/Base/Utils.cpp +++ b/openVulkanoCpp/Base/Utils.cpp @@ -7,9 +7,9 @@ #include "Utils.hpp" #ifdef _MSC_VER -#include + #include #else -#include + #include #endif #include #include @@ -57,7 +57,7 @@ namespace OpenVulkano #ifdef _MSC_VER return (uint64_t)::GetThreadId(::GetCurrentThread()); #else - return (uint64_t)pthread_self(); + return (uint64_t) pthread_self(); #endif } @@ -69,8 +69,16 @@ namespace OpenVulkano if (emptyOnMissing) return {}; throw std::runtime_error("Failed to open file '" + filePath + "'!"); } - size_t fileSize = static_cast(file.tellg()); - if (nullTerminateString) fileSize++; + const size_t fileSize = static_cast(file.tellg()); + if (nullTerminateString) + { + Array data(fileSize + 1); + file.seekg(0); + file.read(data.Data(), fileSize); + data[fileSize] = '\0'; + file.close(); + return data; + } Array data(fileSize); file.seekg(0); diff --git a/openVulkanoCpp/Shader/ShaderCompiler.cpp b/openVulkanoCpp/Shader/ShaderCompiler.cpp index 2f24c67..548986d 100644 --- a/openVulkanoCpp/Shader/ShaderCompiler.cpp +++ b/openVulkanoCpp/Shader/ShaderCompiler.cpp @@ -1,5 +1,9 @@ #include "ShaderCompiler.hpp" +#include "Base/Logger.hpp" + +#include + namespace OpenVulkano { Unique ShaderCompiler::CompileGLSLToSpirv(const std::string& absPath, const std::string& incPath, @@ -8,11 +12,6 @@ namespace OpenVulkano { Array file = Utils::ReadFile(absPath, false, true); -#if defined(_DEBUG) - printf("Compiling shader: %s\n", absPath.c_str()); - printf("%s\n", file.Data() + 1); -#endif - shaderc::Compiler shaderCompiler; shaderc::CompileOptions options; @@ -25,8 +24,7 @@ namespace OpenVulkano if (preResult.GetCompilationStatus() != shaderc_compilation_status_success) { - throw std::runtime_error("Failed to preprocess shader: " + preResult.GetErrorMessage()); - return nullptr; + throw std::runtime_error("Failed preprocessing shader. Reason: " + preResult.GetErrorMessage()); } shaderc::CompilationResult result = @@ -34,68 +32,42 @@ namespace OpenVulkano if (result.GetCompilationStatus() != shaderc_compilation_status_success) { - throw std::runtime_error("Failed to compile shader: " + result.GetErrorMessage()); - return nullptr; + throw std::runtime_error("Failed compiling shader. Reason: " + result.GetErrorMessage()); } Unique spirv = std::make_unique((void*) result.begin()); return spirv; } - ShaderIncluder::ShaderIncluder(const std::string& path) - { - // TODO : Add the path to your include folder - m_includes.push_back(path); - } + ShaderIncluder::ShaderIncluder(const std::string& path) : m_includePath(path) {} - shaderc_include_result* ShaderIncluder::GetInclude(const char* requested_source, shaderc_include_type type, - const char* requesting_source, uint64_t include_depth) + shaderc_include_result* ShaderIncluder::GetInclude(const char* requestedSource, shaderc_include_type type, + const char* requestingSource, uint64_t includeDepth) { - const char* includePath = GetActualPath(requested_source); - const char* content = RecordInclude(includePath); + IncludeData* includeData = new IncludeData(); + includeData->m_fullPath = ResolveInclude(requestedSource); + includeData->m_content = Utils::ReadFile(includeData->m_fullPath, false, false); // using nullTerminate as true causes crash in here. Needed to use as false. - shaderc_include_result* result = new shaderc_include_result(); - result->content = content; - result->content_length = strlen(content); - result->source_name = includePath; - result->source_name_length = strlen(includePath); - result->user_data = nullptr; + shaderc_include_result* result = &includeData->result; + result->content = includeData->m_content.Data(); + result->content_length = includeData->m_content.Size(); + result->source_name = includeData->m_fullPath.data(); + result->source_name_length = includeData->m_fullPath.size(); + result->user_data = includeData; return result; } - void ShaderIncluder::ReleaseInclude(shaderc_include_result* data) { delete data; } - - std::string ShaderIncluder::ResolveInclude(const std::string requestedSource) + void ShaderIncluder::ReleaseInclude(shaderc_include_result* data) { - // Check if the file exists in the include paths - for (const std::string& includePath: m_includes) - { - std::string path = includePath + requestedSource; - // TODO: Need to check if the folder exists - return path; - } - - return ""; + delete static_cast(data->user_data); } - const char* ShaderIncluder::RecordInclude(const std::string& requestedSource) + std::string ShaderIncluder::ResolveInclude(const std::string& requestedSource) const { - Array data = Utils::ReadFile(requestedSource); - - char* result = new char[data.Size() + 1]; - strcpy_s(result, data.Size(), data.Data()); - - return result; - } - - const char* ShaderIncluder::GetActualPath(const std::string& requestedSource) - { - std::string includePath = ResolveInclude(requestedSource); - - char* result = new char[includePath.size() + 1]; - strcpy_s(result, includePath.size(), includePath.c_str()); - - return result; + // Check if the file exists in the include path + std::string path = m_includePath + requestedSource; + if (std::filesystem::exists(path)) return path; + else throw std::runtime_error("Failed to resolve include '" + requestedSource + "'!"); } } diff --git a/openVulkanoCpp/Shader/ShaderCompiler.hpp b/openVulkanoCpp/Shader/ShaderCompiler.hpp index b4d083d..6eb0df0 100644 --- a/openVulkanoCpp/Shader/ShaderCompiler.hpp +++ b/openVulkanoCpp/Shader/ShaderCompiler.hpp @@ -11,21 +11,25 @@ namespace OpenVulkano { class ShaderIncluder : public shaderc::CompileOptions::IncluderInterface { + struct IncludeData + { + shaderc_include_result result = {}; + std::string m_fullPath; + Array m_content; + }; public: ShaderIncluder(const std::string& path); ~ShaderIncluder() override = default; - shaderc_include_result* GetInclude(const char* requested_source, shaderc_include_type type, - const char* requesting_source, uint64_t include_depth) override; + shaderc_include_result* GetInclude(const char* requestedSource, shaderc_include_type type, + const char* requestingSource, uint64_t includeDepth) override; void ReleaseInclude(shaderc_include_result* data) override; private: - std::string ResolveInclude(const std::string requestedSource); - const char* RecordInclude(const std::string& requestedSource); - const char* GetActualPath(const std::string& requestedSource); + std::string ResolveInclude(const std::string& requestedSource) const; private: - std::vector m_includes; + std::string m_includePath; }; class ShaderCompiler diff --git a/openVulkanoCpp/Shader/test.vert b/openVulkanoCpp/Shader/test.vert new file mode 100644 index 0000000..3d16cda --- /dev/null +++ b/openVulkanoCpp/Shader/test.vert @@ -0,0 +1,8 @@ +#version 460 +#extension GL_KHR_vulkan_glsl : enable + +#include "test1.glsl" + +void main() +{ +}; \ No newline at end of file diff --git a/openVulkanoCpp/Shader/test1.glsl b/openVulkanoCpp/Shader/test1.glsl new file mode 100644 index 0000000..92671bc --- /dev/null +++ b/openVulkanoCpp/Shader/test1.glsl @@ -0,0 +1,3 @@ +void testfunction() +{ +}; \ No newline at end of file From dbd7b2dad54a4506070b86b76d4f79cab378a9f1 Mon Sep 17 00:00:00 2001 From: Metehan Tuncbilek Date: Tue, 16 Jul 2024 18:31:43 +0300 Subject: [PATCH 5/6] review refactors --- cmake/SetupVulkan.cmake | 15 ++--- openVulkanoCpp/Base/Utils.cpp | 13 +--- openVulkanoCpp/Shader/ShaderCompiler.cpp | 75 ++++++++++++++++++++---- openVulkanoCpp/Shader/ShaderCompiler.hpp | 36 +++--------- openVulkanoCpp/Shader/test.vert | 8 --- openVulkanoCpp/Shader/test1.glsl | 3 - 6 files changed, 79 insertions(+), 71 deletions(-) delete mode 100644 openVulkanoCpp/Shader/test.vert delete mode 100644 openVulkanoCpp/Shader/test1.glsl diff --git a/cmake/SetupVulkan.cmake b/cmake/SetupVulkan.cmake index b386f3a..24ed595 100644 --- a/cmake/SetupVulkan.cmake +++ b/cmake/SetupVulkan.cmake @@ -4,17 +4,12 @@ function(SetupVulkan TARGET) target_link_libraries(${TARGET} PRIVATE ${MoltenVK_LIBRARIES}) else () find_package(Vulkan REQUIRED) - get_filename_component(Vulkan_SDK_DIR "${Vulkan_LIBRARIES}" DIRECTORY) # Get VulkanSDK/[version]/Bin target_link_libraries(${TARGET} PRIVATE Vulkan::Vulkan) - if(CMAKE_BUILD_TYPE MATCHES "Debug") - target_link_libraries(${TARGET} PRIVATE "${Vulkan_SDK_DIR}/shaderc_combinedd.lib" - "${Vulkan_SDK_DIR}/spirv-cross-cored.lib" "${Vulkan_SDK_DIR}/spirv-cross-glsld.lib" - "${Vulkan_SDK_DIR}/spirv-cross-hlsld.lib") - else() - target_link_libraries(${TARGET} PRIVATE "${Vulkan_SDK_DIR}/shaderc_combined.lib" - "${Vulkan_SDK_DIR}/spirv-cross-core.lib" "${Vulkan_SDK_DIR}/spirv-cross-glsl.lib" - "${Vulkan_SDK_DIR}/spirv-cross-hlsl.lib") - endif() + find_package(Vulkan OPTIONAL_COMPONENTS shaderc_combined) + if (Vulkan_shaderc_combined_FOUND) + target_link_libraries(${TARGET} PRIVATE Vulkan::shaderc_combined) + target_compile_definitions(${TARGET} PRIVATE HAS_SHADERC) + endif () endif () target_include_directories(${TARGET} PUBLIC ${Vulkan_INCLUDE_DIR}) diff --git a/openVulkanoCpp/Base/Utils.cpp b/openVulkanoCpp/Base/Utils.cpp index cbdd6ed..4987888 100644 --- a/openVulkanoCpp/Base/Utils.cpp +++ b/openVulkanoCpp/Base/Utils.cpp @@ -70,19 +70,10 @@ namespace OpenVulkano throw std::runtime_error("Failed to open file '" + filePath + "'!"); } const size_t fileSize = static_cast(file.tellg()); - if (nullTerminateString) - { - Array data(fileSize + 1); - file.seekg(0); - file.read(data.Data(), fileSize); - data[fileSize] = '\0'; - file.close(); - return data; - } - - Array data(fileSize); + Array data(fileSize + nullTerminateString); file.seekg(0); file.read(data.Data(), fileSize); + if (nullTerminateString) data[fileSize] = '\0'; file.close(); return data; } diff --git a/openVulkanoCpp/Shader/ShaderCompiler.cpp b/openVulkanoCpp/Shader/ShaderCompiler.cpp index 548986d..e8ccec7 100644 --- a/openVulkanoCpp/Shader/ShaderCompiler.cpp +++ b/openVulkanoCpp/Shader/ShaderCompiler.cpp @@ -2,41 +2,93 @@ #include "Base/Logger.hpp" +#include #include namespace OpenVulkano { - Unique ShaderCompiler::CompileGLSLToSpirv(const std::string& absPath, const std::string& incPath, - const std::string& entryPoint, shaderc_shader_kind shaderStage, - bool bHaveIncludes) +#if defined(HAS_SHADERC) + class ShaderIncluder : public shaderc::CompileOptions::IncluderInterface + { + struct IncludeData + { + shaderc_include_result result = {}; + std::string m_fullPath; + Array m_content; + }; + + public: + ShaderIncluder(const std::string& path); + ~ShaderIncluder() override = default; + + shaderc_include_result* GetInclude(const char* requestedSource, shaderc_include_type type, + const char* requestingSource, uint64_t includeDepth) override; + void ReleaseInclude(shaderc_include_result* data) override; + + private: + std::string ResolveInclude(const std::string& requestedSource) const; + + private: + std::string m_includePath; + }; + + shaderc_shader_kind CheckStage(const std::string& extensionName) + { + std::map stageMap = { + { "vert", shaderc_glsl_vertex_shader }, { "frag", shaderc_glsl_fragment_shader }, + { "comp", shaderc_glsl_compute_shader }, { "geom", shaderc_glsl_geometry_shader }, + { "tesc", shaderc_glsl_tess_control_shader }, { "tese", shaderc_glsl_tess_evaluation_shader }, + { "rgen", shaderc_glsl_raygen_shader }, { "rint", shaderc_glsl_intersection_shader }, + { "rahit", shaderc_glsl_anyhit_shader }, { "rchit", shaderc_glsl_closesthit_shader }, + { "rmiss", shaderc_glsl_miss_shader }, { "rcall", shaderc_glsl_callable_shader }, + { "task", shaderc_glsl_task_shader }, { "mesh", shaderc_glsl_mesh_shader } + }; + + auto it = stageMap.find(extensionName); + if (it != stageMap.end()) return it->second; + else throw std::runtime_error("Failed to find shader stage for extension '" + extensionName + "'!"); + } + + Array ShaderCompiler::CompileGLSLToSpirv(const std::string& absPath, bool hasIncludes, + const std::string& incPath, const std::string& entryPoint) { Array file = Utils::ReadFile(absPath, false, true); shaderc::Compiler shaderCompiler; shaderc::CompileOptions options; - if (bHaveIncludes) options.SetIncluder(std::make_unique(incPath)); + if (hasIncludes && incPath.size() > 0) { options.SetIncluder(std::make_unique(incPath)); } options.SetSourceLanguage(shaderc_source_language_glsl); options.SetSuppressWarnings(); + auto extensionSplit = Utils::SplitAtLastOccurrence(absPath, '.'); + shaderc::PreprocessedSourceCompilationResult preResult = - shaderCompiler.PreprocessGlsl(file.Data(), shaderStage, entryPoint.c_str(), options); + shaderCompiler.PreprocessGlsl(file.Data(), CheckStage(extensionSplit.second), entryPoint.c_str(), options); + + #if defined(_DEBUG) + std::string test = static_cast(preResult.begin(), preResult.end()); + // printf("Preprocessed shader: %s\n\n\n", test.c_str()); // Works fine + // Logger::APP->info("Preprocessed shader: {0}", test); gives error + #endif if (preResult.GetCompilationStatus() != shaderc_compilation_status_success) { throw std::runtime_error("Failed preprocessing shader. Reason: " + preResult.GetErrorMessage()); } - shaderc::CompilationResult result = - shaderCompiler.CompileGlslToSpv(static_cast(preResult.begin()), shaderStage, "", options); + shaderc::CompilationResult result = shaderCompiler.CompileGlslToSpv( + static_cast(preResult.begin()), CheckStage(extensionSplit.second), "", options); if (result.GetCompilationStatus() != shaderc_compilation_status_success) { throw std::runtime_error("Failed compiling shader. Reason: " + result.GetErrorMessage()); } - Unique spirv = std::make_unique((void*) result.begin()); - return spirv; + Array returnResult(result.cend() - result.cbegin()); + // Copy the data to the return array + std::copy(result.begin(), result.end(), returnResult.Data()); + return returnResult; } ShaderIncluder::ShaderIncluder(const std::string& path) : m_includePath(path) {} @@ -46,7 +98,9 @@ namespace OpenVulkano { IncludeData* includeData = new IncludeData(); includeData->m_fullPath = ResolveInclude(requestedSource); - includeData->m_content = Utils::ReadFile(includeData->m_fullPath, false, false); // using nullTerminate as true causes crash in here. Needed to use as false. + + // Do not null terminate the string + includeData->m_content = Utils::ReadFile(includeData->m_fullPath, false, false); shaderc_include_result* result = &includeData->result; result->content = includeData->m_content.Data(); @@ -70,4 +124,5 @@ namespace OpenVulkano if (std::filesystem::exists(path)) return path; else throw std::runtime_error("Failed to resolve include '" + requestedSource + "'!"); } +#endif } diff --git a/openVulkanoCpp/Shader/ShaderCompiler.hpp b/openVulkanoCpp/Shader/ShaderCompiler.hpp index 6eb0df0..ae3d561 100644 --- a/openVulkanoCpp/Shader/ShaderCompiler.hpp +++ b/openVulkanoCpp/Shader/ShaderCompiler.hpp @@ -3,35 +3,10 @@ #include "Base/Utils.hpp" #include "Base/Wrapper.hpp" -#include -#include #include namespace OpenVulkano { - class ShaderIncluder : public shaderc::CompileOptions::IncluderInterface - { - struct IncludeData - { - shaderc_include_result result = {}; - std::string m_fullPath; - Array m_content; - }; - public: - ShaderIncluder(const std::string& path); - ~ShaderIncluder() override = default; - - shaderc_include_result* GetInclude(const char* requestedSource, shaderc_include_type type, - const char* requestingSource, uint64_t includeDepth) override; - void ReleaseInclude(shaderc_include_result* data) override; - - private: - std::string ResolveInclude(const std::string& requestedSource) const; - - private: - std::string m_includePath; - }; - class ShaderCompiler { public: @@ -40,10 +15,13 @@ namespace OpenVulkano * @param incPath - include path that will be used to resolve includes * @param entryPoint - the name of the void function in the shader * @param shaderStage - type of the shader that needs to be compiled - * @param bHaveIncludes - if incPath is empty, make it false */ - static Unique CompileGLSLToSpirv(const std::string& absPath, - const std::string& incPath, const std::string& entryPoint, - shaderc_shader_kind shaderStage, bool bHaveIncludes); + static Array CompileGLSLToSpirv(const std::string& absPath, bool hasIncludes, + const std::string& incPath = std::string(), const std::string& entryPoint = "main") +#if defined(HAS_SHADERC) + ; +#else + { throw std::runtime_error("Shader compiler is not available on this platform"); } +#endif }; } \ No newline at end of file diff --git a/openVulkanoCpp/Shader/test.vert b/openVulkanoCpp/Shader/test.vert deleted file mode 100644 index 3d16cda..0000000 --- a/openVulkanoCpp/Shader/test.vert +++ /dev/null @@ -1,8 +0,0 @@ -#version 460 -#extension GL_KHR_vulkan_glsl : enable - -#include "test1.glsl" - -void main() -{ -}; \ No newline at end of file diff --git a/openVulkanoCpp/Shader/test1.glsl b/openVulkanoCpp/Shader/test1.glsl deleted file mode 100644 index 92671bc..0000000 --- a/openVulkanoCpp/Shader/test1.glsl +++ /dev/null @@ -1,3 +0,0 @@ -void testfunction() -{ -}; \ No newline at end of file From 7ea6fc8dc4ff1c04d59750801274c146ea06487f Mon Sep 17 00:00:00 2001 From: Metehan Tuncbilek Date: Tue, 16 Jul 2024 22:13:44 +0300 Subject: [PATCH 6/6] review fix done --- openVulkanoCpp/Shader/ShaderCompiler.cpp | 19 +++++++++++-------- openVulkanoCpp/Shader/ShaderCompiler.hpp | 2 -- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/openVulkanoCpp/Shader/ShaderCompiler.cpp b/openVulkanoCpp/Shader/ShaderCompiler.cpp index e8ccec7..e70a3f2 100644 --- a/openVulkanoCpp/Shader/ShaderCompiler.cpp +++ b/openVulkanoCpp/Shader/ShaderCompiler.cpp @@ -1,13 +1,16 @@ +#if defined(HAS_SHADERC) + #include "ShaderCompiler.hpp" #include "Base/Logger.hpp" +#include #include #include namespace OpenVulkano { -#if defined(HAS_SHADERC) + class ShaderIncluder : public shaderc::CompileOptions::IncluderInterface { struct IncludeData @@ -34,7 +37,7 @@ namespace OpenVulkano shaderc_shader_kind CheckStage(const std::string& extensionName) { - std::map stageMap = { + static std::map stageMap = { { "vert", shaderc_glsl_vertex_shader }, { "frag", shaderc_glsl_fragment_shader }, { "comp", shaderc_glsl_compute_shader }, { "geom", shaderc_glsl_geometry_shader }, { "tesc", shaderc_glsl_tess_control_shader }, { "tese", shaderc_glsl_tess_evaluation_shader }, @@ -50,7 +53,7 @@ namespace OpenVulkano } Array ShaderCompiler::CompileGLSLToSpirv(const std::string& absPath, bool hasIncludes, - const std::string& incPath, const std::string& entryPoint) + const std::string& incPath, const std::string& entryPoint) { Array file = Utils::ReadFile(absPath, false, true); @@ -66,11 +69,11 @@ namespace OpenVulkano shaderc::PreprocessedSourceCompilationResult preResult = shaderCompiler.PreprocessGlsl(file.Data(), CheckStage(extensionSplit.second), entryPoint.c_str(), options); - #if defined(_DEBUG) + #if defined(_DEBUG) std::string test = static_cast(preResult.begin(), preResult.end()); - // printf("Preprocessed shader: %s\n\n\n", test.c_str()); // Works fine - // Logger::APP->info("Preprocessed shader: {0}", test); gives error - #endif + // printf("Preprocessed shader: %s\n\n\n", test.c_str()); // Works fine + // Logger::APP->info("Preprocessed shader: {0}", test); gives error + #endif if (preResult.GetCompilationStatus() != shaderc_compilation_status_success) { @@ -124,5 +127,5 @@ namespace OpenVulkano if (std::filesystem::exists(path)) return path; else throw std::runtime_error("Failed to resolve include '" + requestedSource + "'!"); } -#endif } +#endif diff --git a/openVulkanoCpp/Shader/ShaderCompiler.hpp b/openVulkanoCpp/Shader/ShaderCompiler.hpp index ae3d561..4f42997 100644 --- a/openVulkanoCpp/Shader/ShaderCompiler.hpp +++ b/openVulkanoCpp/Shader/ShaderCompiler.hpp @@ -3,8 +3,6 @@ #include "Base/Utils.hpp" #include "Base/Wrapper.hpp" -#include - namespace OpenVulkano { class ShaderCompiler