Fix vulkan shader loading and runtime compilation
This commit is contained in:
parent
46628c6376
commit
c42bde8830
9 changed files with 64 additions and 31 deletions
|
@ -27,6 +27,7 @@ namespace file {
|
|||
data(std::move(f.data)) {}
|
||||
|
||||
~File() {
|
||||
if(handle != nullptr)
|
||||
fclose(handle);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "file.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "string_utils.hpp"
|
||||
#include "log.hpp"
|
||||
#include "assertions.hpp"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -541,17 +541,36 @@ GFXPipeline* GFXVulkan::create_graphics_pipeline(const GFXGraphicsPipelineCreate
|
|||
|
||||
vkDeviceWaitIdle(device);
|
||||
|
||||
// setup shader modules
|
||||
VkShaderModule vertex_module = VK_NULL_HANDLE, fragment_module = VK_NULL_HANDLE;
|
||||
|
||||
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();
|
||||
|
||||
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);
|
||||
fragment_module = createShaderModule(fragment_shader->cast_data<uint32_t>(), fragment_shader->size());
|
||||
}
|
||||
|
||||
auto fragment_module = createShaderModule(fragment_shader->cast_data<unsigned char>(), fragment_shader->size());
|
||||
name_object(device, VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)vertex_module, info.shaders.vertex_path);
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,6 +202,7 @@ 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;
|
||||
|
@ -211,6 +212,9 @@ std::string get_shader(std::string filename, bool skinned, bool cubemap) {
|
|||
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,6 +578,7 @@ 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;
|
||||
|
@ -585,4 +588,7 @@ std::string ShaderCompiler::compile_material_fragment(Material& material, bool u
|
|||
msl.set_msl_options(opts);
|
||||
|
||||
return msl.compile();
|
||||
#else
|
||||
return vertexSPIRV;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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() {
|
||||
|
|
Reference in a new issue