Archived
1
Fork 0

Fix vulkan shader loading and runtime compilation

This commit is contained in:
redstrate 2020-08-14 17:45:51 -04:00
parent 46628c6376
commit c42bde8830
9 changed files with 64 additions and 31 deletions

View file

@ -27,7 +27,8 @@ namespace file {
data(std::move(f.data)) {}
~File() {
fclose(handle);
if(handle != nullptr)
fclose(handle);
}
/** Loads a type.

View file

@ -1,5 +1,7 @@
#include "file.hpp"
#include <cstdio>
#include "string_utils.hpp"
#include "log.hpp"
#include "assertions.hpp"

View file

@ -2,6 +2,7 @@
#include <string>
#include <vector>
#include <variant>
class GFXBuffer;
class GFXPipeline;
@ -143,7 +144,8 @@ struct GFXGraphicsPipelineCreateInfo {
struct Shaders {
std::string_view vertex_path, fragment_path;
std::string vertex_src, fragment_src;
std::variant<std::string, std::vector<uint32_t>> vertex_src, fragment_src;
GFXShaderConstants vertex_constants, fragment_constants;
} shaders;

View file

@ -68,7 +68,7 @@ private:
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
void transitionImageLayout(VkImage image, VkFormat format, VkImageAspectFlags aspect, VkImageLayout oldLayout, VkImageLayout newLayout);
VkShaderModule createShaderModule(const unsigned char* code, const int length);
VkShaderModule createShaderModule(const uint32_t* code, const int length);
VkCommandBuffer beginSingleTimeCommands();
void endSingleTimeCommands(VkCommandBuffer commandBuffer);

View file

@ -541,17 +541,36 @@ GFXPipeline* GFXVulkan::create_graphics_pipeline(const GFXGraphicsPipelineCreate
vkDeviceWaitIdle(device);
// setup shader modules
auto vertex_shader = file::open(file::internal_domain / (std::string(info.shaders.vertex_path) + ".spv"));
vertex_shader->read_all();
VkShaderModule vertex_module = VK_NULL_HANDLE, fragment_module = VK_NULL_HANDLE;
auto fragment_shader = file::open(file::internal_domain / (std::string(info.shaders.fragment_path) + ".spv"));
fragment_shader->read_all();
const bool vertex_use_shader_source = info.shaders.vertex_path.empty();
const bool fragment_use_shader_source = info.shaders.fragment_path.empty();
if (vertex_use_shader_source) {
auto& vertex_shader_vector = std::get<std::vector<uint32_t>>(info.shaders.vertex_src);
vertex_module = createShaderModule(vertex_shader_vector.data(), vertex_shader_vector.size() * sizeof(uint32_t));
}
else {
auto vertex_shader = file::open(file::internal_domain / (std::string(info.shaders.vertex_path) + ".spv"));
vertex_shader->read_all();
vertex_module = createShaderModule(vertex_shader->cast_data<uint32_t>(), vertex_shader->size());
}
if (fragment_use_shader_source) {
auto& fragment_shader_vector = std::get<std::vector<uint32_t>>(info.shaders.fragment_src);
fragment_module = createShaderModule(fragment_shader_vector.data(), fragment_shader_vector.size() * sizeof(uint32_t));
}
else {
auto fragment_shader = file::open(file::internal_domain / (std::string(info.shaders.fragment_path) + ".spv"));
fragment_shader->read_all();
fragment_module = createShaderModule(fragment_shader->cast_data<uint32_t>(), fragment_shader->size());
}
auto vertex_module = createShaderModule(vertex_shader->cast_data<unsigned char>(), vertex_shader->size());
name_object(device, VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)vertex_module, info.shaders.vertex_path);
auto fragment_module = createShaderModule(fragment_shader->cast_data<unsigned char>(), fragment_shader->size());
name_object(device, VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)fragment_module, info.shaders.fragment_path);
VkPipelineShaderStageCreateInfo vertShaderStageInfo = {};
@ -754,15 +773,13 @@ GFXSize GFXVulkan::get_alignment(GFXSize size) {
return (size + minUboAlignment / 2) & ~int(minUboAlignment - 1);
}
void GFXVulkan::submit(GFXCommandBuffer *command_buffer, const int identifier) {
void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) {
vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, std::numeric_limits<uint64_t>::max());
uint32_t imageIndex = 0;
VkResult result = vkAcquireNextImageKHR(device, swapchain, std::numeric_limits<uint64_t>::max(), imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
//std::cout << "oops??" << std::endl;
if (result == VK_ERROR_OUT_OF_DATE_KHR)
return;
}
VkCommandBufferBeginInfo beginInfo = {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
@ -1004,7 +1021,7 @@ VkResult CreateDebugUtilsMessengerEXT(
void GFXVulkan::createInstance(std::vector<const char*> layers, std::vector<const char*> extensions) {
VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo = {};
debugCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
debugCreateInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
debugCreateInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
debugCreateInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT ;
debugCreateInfo.pfnUserCallback = DebugCallback; // global function
@ -1476,7 +1493,7 @@ void GFXVulkan::transitionImageLayout(VkImage image, VkFormat format, VkImageAsp
endSingleTimeCommands(commandBuffer);
}
VkShaderModule GFXVulkan::createShaderModule(const unsigned char* code, const int length) {
VkShaderModule GFXVulkan::createShaderModule(const uint32_t* code, const int length) {
VkShaderModuleCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
createInfo.codeSize = length;

View file

@ -21,7 +21,7 @@ public:
// generates static and skinned versions of the pipeline provided
std::tuple<GFXPipeline*, GFXPipeline*> create_pipeline_permutations(GFXGraphicsPipelineCreateInfo& createInfo, bool positions_only = false);
std::string compile_material_fragment(Material& material, bool use_ibl = true);
std::variant<std::string, std::vector<uint32_t>> compile_material_fragment(Material& material, bool use_ibl = true);
};
static ShaderCompiler shader_compiler;

View file

@ -186,7 +186,7 @@ const std::vector<unsigned int> CompileGLSL(const std::string& filename, EShLang
return SpirV;
}
std::string get_shader(std::string filename, bool skinned, bool cubemap) {
std::variant<std::string, std::vector<uint32_t>> get_shader(std::string filename, bool skinned, bool cubemap) {
auto shader_file = file::open(file::internal_domain / filename);
if(!shader_file) {
std::cerr << "Failed to open " << filename << "!!" << std::endl;
@ -202,15 +202,19 @@ std::string get_shader(std::string filename, bool skinned, bool cubemap) {
auto vertexSPIRV = CompileGLSL(shader_file->read_as_string(), lang, skinned, cubemap);
#ifdef PLATFORM_MACOS
spirv_cross::CompilerMSL msl(std::move(vertexSPIRV));
spirv_cross::CompilerMSL::Options opts;
opts.platform = spirv_cross::CompilerMSL::Options::Platform::macOS;
opts.enable_decoration_binding = true;
msl.set_msl_options(opts);
return msl.compile();
#else
return vertexSPIRV;
#endif
}
GFXPipeline* ShaderCompiler::create_static_pipeline(GFXGraphicsPipelineCreateInfo createInfo, bool positions_only, bool cubemap) {
@ -218,8 +222,7 @@ GFXPipeline* ShaderCompiler::create_static_pipeline(GFXGraphicsPipelineCreateInf
std::string vertex_path = createInfo.shaders.vertex_path.data();
vertex_path += ".glsl";
std::string vertex_src = get_shader(vertex_path, false, cubemap);
createInfo.shaders.vertex_src = vertex_src;
createInfo.shaders.vertex_src = get_shader(vertex_path, false, cubemap);
createInfo.shaders.vertex_path = "";
if(positions_only) {
@ -258,8 +261,7 @@ GFXPipeline* ShaderCompiler::create_skinned_pipeline(GFXGraphicsPipelineCreateIn
std::string vertex_path = createInfo.shaders.vertex_path.data();
vertex_path += ".glsl";
std::string vertex_src = get_shader(vertex_path, true, false);
createInfo.shaders.vertex_src = vertex_src;
createInfo.shaders.vertex_src = get_shader(vertex_path, true, false);
createInfo.shaders.vertex_path = "";
if(positions_only) {
@ -371,7 +373,7 @@ layout(push_constant, binding = 0) uniform PushConstant {\n \
int materialOffset;\n \
};\n";
std::string ShaderCompiler::compile_material_fragment(Material& material, bool use_ibl) {
std::variant<std::string, std::vector<uint32_t>> ShaderCompiler::compile_material_fragment(Material& material, bool use_ibl) {
walked_nodes.clear();
if(!render_options.enable_ibl)
@ -576,13 +578,17 @@ std::string ShaderCompiler::compile_material_fragment(Material& material, bool u
auto vertexSPIRV = CompileGLSL(src, EShLangFragment, false, false);
#ifdef PLATFORM_MACOS
spirv_cross::CompilerMSL msl(std::move(vertexSPIRV));
spirv_cross::CompilerMSL::Options opts;
opts.platform = spirv_cross::CompilerMSL::Options::Platform::macOS;
opts.enable_decoration_binding = true;
msl.set_msl_options(opts);
return msl.compile();
#else
return vertexSPIRV;
#endif
}

View file

@ -17,4 +17,7 @@ add_custom_target(PlatformWindows_IDE SOURCES
function(add_platform_commands target)
set_target_properties(${target} PROPERTIES
LINK_FLAGS /SUBSYSTEM:WINDOWS)
add_custom_command(TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/shaders $<TARGET_FILE_DIR:${target}>/shaders)
add_custom_command(TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/data $<TARGET_FILE_DIR:${target}>/data)
endfunction()

View file

@ -1,7 +1,9 @@
#include "file.hpp"
#include "string_utils.hpp"
void file::set_domain_path(const file::Domain domain, const file::Path path) {
domain_data[(int)domain] = path.string();
domain_data[(int)domain] = replace_substring(path.string(), "{resource_dir}", ".");
}
file::Path file::get_writeable_directory() {