Runtime ShaderCompilation with Include Features
This commit is contained in:
2
.idea/.name
generated
2
.idea/.name
generated
@@ -1 +1 @@
|
|||||||
OpenVulkano
|
openVulkanoCpp
|
||||||
@@ -4,7 +4,17 @@ function(SetupVulkan TARGET)
|
|||||||
target_link_libraries(${TARGET} PRIVATE ${MoltenVK_LIBRARIES})
|
target_link_libraries(${TARGET} PRIVATE ${MoltenVK_LIBRARIES})
|
||||||
else ()
|
else ()
|
||||||
find_package(Vulkan REQUIRED)
|
find_package(Vulkan REQUIRED)
|
||||||
|
get_filename_component(Vulkan_SDK_DIR "${Vulkan_LIBRARIES}" DIRECTORY) # Get VulkanSDK/[version]/Bin
|
||||||
target_link_libraries(${TARGET} PRIVATE Vulkan::Vulkan)
|
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 ()
|
endif ()
|
||||||
target_include_directories(${TARGET} PUBLIC ${Vulkan_INCLUDE_DIR})
|
target_include_directories(${TARGET} PUBLIC ${Vulkan_INCLUDE_DIR})
|
||||||
|
|
||||||
@@ -18,3 +28,4 @@ function(SetupVulkan TARGET)
|
|||||||
target_link_libraries(${TARGET} PRIVATE ${XCB_LIBRARIES})
|
target_link_libraries(${TARGET} PRIVATE ${XCB_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
|||||||
@@ -17,10 +17,17 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "Shader/ShaderCompiler.hpp"
|
||||||
|
|
||||||
using namespace OpenVulkano;
|
using namespace OpenVulkano;
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
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<std::string> examples = {
|
std::vector<std::string> examples = {
|
||||||
"Cubes Example App",
|
"Cubes Example App",
|
||||||
"Moving Cube Example App",
|
"Moving Cube Example App",
|
||||||
|
|||||||
100
openVulkanoCpp/Shader/ShaderCompiler.cpp
Normal file
100
openVulkanoCpp/Shader/ShaderCompiler.cpp
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
#include "ShaderCompiler.hpp"
|
||||||
|
|
||||||
|
namespace OpenVulkano
|
||||||
|
{
|
||||||
|
Unique<void*> ShaderCompiler::CompileGLSLToSpirv(const std::string& absPath, const std::string& incPath,
|
||||||
|
const std::string& entryPoint, shaderc_shader_kind shaderStage,
|
||||||
|
bool bHaveIncludes)
|
||||||
|
{
|
||||||
|
Array<char> 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<ShaderIncluder>(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<const char*>(preResult.begin()), shaderStage, "", options);
|
||||||
|
|
||||||
|
if (result.GetCompilationStatus() != shaderc_compilation_status_success)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Failed to compile shader: " + result.GetErrorMessage());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Unique<void*> spirv = std::make_unique<void*>((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<char> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
45
openVulkanoCpp/Shader/ShaderCompiler.hpp
Normal file
45
openVulkanoCpp/Shader/ShaderCompiler.hpp
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Base/Utils.hpp"
|
||||||
|
#include "Base/Wrapper.hpp"
|
||||||
|
|
||||||
|
#include <spirv_cross/spirv_hlsl.hpp>
|
||||||
|
#include <spirv_cross/spirv_glsl.hpp>
|
||||||
|
#include <shaderc/shaderc.hpp>
|
||||||
|
|
||||||
|
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<std::string> 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<void*> CompileGLSLToSpirv(const std::string& absPath,
|
||||||
|
const std::string& incPath, const std::string& entryPoint,
|
||||||
|
shaderc_shader_kind shaderStage, bool bHaveIncludes);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -27,6 +27,10 @@ namespace OpenVulkano::Vulkan
|
|||||||
vk::MemoryPropertyFlags properties;
|
vk::MemoryPropertyFlags properties;
|
||||||
void* mapped = nullptr;
|
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()
|
~ManagedBuffer()
|
||||||
{
|
{
|
||||||
allocation->device.destroy(buffer);
|
allocation->device.destroy(buffer);
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
uint32_t offset = Utils::Align(allocation->used, memoryRequirements.alignment);
|
uint32_t offset = Utils::Align(allocation->used, memoryRequirements.alignment);
|
||||||
device->device.bindBufferMemory(buffer, allocation->memory, offset);
|
device->device.bindBufferMemory(buffer, allocation->memory, offset);
|
||||||
allocation->used += size + (offset - allocation->used);
|
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)
|
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*/);
|
return CreateBuffer(size, vk::BufferUsageFlagBits::eVertexBuffer, vk::MemoryPropertyFlagBits::eHostCoherent/* | vk::MemoryPropertyFlagBits::eDeviceLocal*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ManagedBufferDeleter::operator()(ManagedBuffer* buffer)
|
||||||
|
{
|
||||||
|
MemoryPool::ReleaseBuffer(buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,11 @@ namespace OpenVulkano::Vulkan
|
|||||||
class Device;
|
class Device;
|
||||||
class MemoryAllocation;
|
class MemoryAllocation;
|
||||||
class ManagedBuffer;
|
class ManagedBuffer;
|
||||||
struct ManagedBufferDeleter;
|
|
||||||
|
struct ManagedBufferDeleter
|
||||||
|
{
|
||||||
|
void operator()(ManagedBuffer* buffer);
|
||||||
|
};
|
||||||
|
|
||||||
class MemoryPool
|
class MemoryPool
|
||||||
{
|
{
|
||||||
@@ -55,12 +59,4 @@ namespace OpenVulkano::Vulkan
|
|||||||
|
|
||||||
static void ReleaseBuffer(ManagedBuffer* buffer);
|
static void ReleaseBuffer(ManagedBuffer* buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ManagedBufferDeleter
|
|
||||||
{
|
|
||||||
void operator()(ManagedBuffer* buffer)
|
|
||||||
{
|
|
||||||
MemoryPool::ReleaseBuffer(buffer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user