Unify standalone and runtime shader compiler, rename old ShaderCompiler to MaterialCompiler
This commit is contained in:
parent
9cd7860ab9
commit
80fd8a375b
16 changed files with 411 additions and 455 deletions
|
@ -1,9 +1,9 @@
|
||||||
macro(compile_shader src)
|
macro(compile_shader src)
|
||||||
string(REGEX REPLACE "\\.[^.]*$" "" MYFILE_WITHOUT_EXT ${src})
|
string(REGEX REPLACE "\\.[^.]*$" "" MYFILE_WITHOUT_EXT ${src})
|
||||||
|
|
||||||
set(SHADER_COMPILER_COMMAND $<TARGET_FILE:ShaderCompiler>)
|
set(SHADER_COMPILER_COMMAND $<TARGET_FILE:ShaderCompilerTool>)
|
||||||
if(ENABLE_IOS)
|
if(ENABLE_IOS)
|
||||||
set(SHADER_COMPILER_COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/../build/bin/Debug/ShaderCompiler")
|
set(SHADER_COMPILER_COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/../build/bin/Debug/ShaderCompilerTool")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(EXTRA_PLATFORM_ARG "0")
|
set(EXTRA_PLATFORM_ARG "0")
|
||||||
|
@ -36,7 +36,7 @@ function(add_shader)
|
||||||
|
|
||||||
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/shaders)
|
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/shaders)
|
||||||
|
|
||||||
add_custom_target(BuildShaders DEPENDS ${SPV_FILES} ShaderCompiler)
|
add_custom_target(BuildShaders DEPENDS ${SPV_FILES} ShaderCompilerTool)
|
||||||
add_dependencies(${add_shader_TARGET} BuildShaders)
|
add_dependencies(${add_shader_TARGET} BuildShaders)
|
||||||
|
|
||||||
set(ALL_SHADER_FILES ${SPV_FILES} CACHE INTERNAL "" FORCE)
|
set(ALL_SHADER_FILES ${SPV_FILES} CACHE INTERNAL "" FORCE)
|
||||||
|
|
|
@ -5,6 +5,7 @@ add_subdirectory(gfx)
|
||||||
add_subdirectory(math)
|
add_subdirectory(math)
|
||||||
add_subdirectory(log)
|
add_subdirectory(log)
|
||||||
add_subdirectory(asset)
|
add_subdirectory(asset)
|
||||||
|
add_subdirectory(shadercompiler)
|
||||||
|
|
||||||
if(NOT ENABLE_IOS AND NOT ENABLE_TVOS)
|
if(NOT ENABLE_IOS AND NOT ENABLE_TVOS)
|
||||||
add_subdirectory(audio)
|
add_subdirectory(audio)
|
||||||
|
|
|
@ -7,8 +7,7 @@ set(SRC
|
||||||
include/imguipass.hpp
|
include/imguipass.hpp
|
||||||
include/smaapass.hpp
|
include/smaapass.hpp
|
||||||
include/scenecapture.hpp
|
include/scenecapture.hpp
|
||||||
include/shadercompiler.hpp
|
include/materialcompiler.hpp
|
||||||
include/DirStackIncluder.h
|
|
||||||
include/dofpass.hpp
|
include/dofpass.hpp
|
||||||
|
|
||||||
src/renderer.cpp
|
src/renderer.cpp
|
||||||
|
@ -17,7 +16,7 @@ set(SRC
|
||||||
src/imguipass.cpp
|
src/imguipass.cpp
|
||||||
src/smaapass.cpp
|
src/smaapass.cpp
|
||||||
src/scenecapture.cpp
|
src/scenecapture.cpp
|
||||||
src/shadercompiler.cpp
|
src/materialcompiler.cpp
|
||||||
src/dofpass.cpp)
|
src/dofpass.cpp)
|
||||||
|
|
||||||
add_library(Renderer STATIC ${SRC})
|
add_library(Renderer STATIC ${SRC})
|
||||||
|
@ -32,11 +31,9 @@ target_link_libraries(Renderer
|
||||||
Core
|
Core
|
||||||
imgui
|
imgui
|
||||||
SMAA::SMAA
|
SMAA::SMAA
|
||||||
${CROSS_LIBS})
|
ShaderCompiler)
|
||||||
target_include_directories(Renderer PUBLIC include)
|
target_include_directories(Renderer PUBLIC include)
|
||||||
set_target_properties(Renderer PROPERTIES CXX_STANDARD 17)
|
set_engine_properties(Renderer)
|
||||||
target_compile_features(Renderer PUBLIC cxx_std_17)
|
|
||||||
set_target_properties(Renderer PROPERTIES CXX_EXTENSIONS OFF)
|
|
||||||
|
|
||||||
include(../../cmake/BuildShaders.cmake)
|
include(../../cmake/BuildShaders.cmake)
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ constexpr int tangent_buffer_index = 5;
|
||||||
constexpr int bitangent_buffer_index = 6;
|
constexpr int bitangent_buffer_index = 6;
|
||||||
constexpr int bone_buffer_index = 7;
|
constexpr int bone_buffer_index = 7;
|
||||||
|
|
||||||
class ShaderCompiler {
|
class MaterialCompiler {
|
||||||
public:
|
public:
|
||||||
GFXPipeline* create_static_pipeline(GFXGraphicsPipelineCreateInfo createInfo, bool positions_only = false, bool cubemap = false);
|
GFXPipeline* create_static_pipeline(GFXGraphicsPipelineCreateInfo createInfo, bool positions_only = false, bool cubemap = false);
|
||||||
GFXPipeline* create_skinned_pipeline(GFXGraphicsPipelineCreateInfo createInfo, bool positions_only = false);
|
GFXPipeline* create_skinned_pipeline(GFXGraphicsPipelineCreateInfo createInfo, bool positions_only = false);
|
||||||
|
@ -24,4 +24,4 @@ public:
|
||||||
std::variant<std::string, std::vector<uint32_t>> 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;
|
static MaterialCompiler material_compiler;
|
|
@ -1,181 +1,10 @@
|
||||||
#include "shadercompiler.hpp"
|
#include "materialcompiler.hpp"
|
||||||
|
|
||||||
#include <spirv_cpp.hpp>
|
|
||||||
#include <spirv_msl.hpp>
|
|
||||||
#include <SPIRV/GlslangToSpv.h>
|
|
||||||
|
|
||||||
#include "file.hpp"
|
#include "file.hpp"
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
#include "string_utils.hpp"
|
#include "string_utils.hpp"
|
||||||
#include "DirStackIncluder.h"
|
#include "shadercompiler.hpp"
|
||||||
|
|
||||||
const TBuiltInResource DefaultTBuiltInResource = {
|
|
||||||
/* .MaxLights = */ 32,
|
|
||||||
/* .MaxClipPlanes = */ 6,
|
|
||||||
/* .MaxTextureUnits = */ 32,
|
|
||||||
/* .MaxTextureCoords = */ 32,
|
|
||||||
/* .MaxVertexAttribs = */ 64,
|
|
||||||
/* .MaxVertexUniformComponents = */ 4096,
|
|
||||||
/* .MaxVaryingFloats = */ 64,
|
|
||||||
/* .MaxVertexTextureImageUnits = */ 32,
|
|
||||||
/* .MaxCombinedTextureImageUnits = */ 80,
|
|
||||||
/* .MaxTextureImageUnits = */ 32,
|
|
||||||
/* .MaxFragmentUniformComponents = */ 4096,
|
|
||||||
/* .MaxDrawBuffers = */ 32,
|
|
||||||
/* .MaxVertexUniformVectors = */ 128,
|
|
||||||
/* .MaxVaryingVectors = */ 8,
|
|
||||||
/* .MaxFragmentUniformVectors = */ 16,
|
|
||||||
/* .MaxVertexOutputVectors = */ 16,
|
|
||||||
/* .MaxFragmentInputVectors = */ 15,
|
|
||||||
/* .MinProgramTexelOffset = */ -8,
|
|
||||||
/* .MaxProgramTexelOffset = */ 7,
|
|
||||||
/* .MaxClipDistances = */ 8,
|
|
||||||
/* .MaxComputeWorkGroupCountX = */ 65535,
|
|
||||||
/* .MaxComputeWorkGroupCountY = */ 65535,
|
|
||||||
/* .MaxComputeWorkGroupCountZ = */ 65535,
|
|
||||||
/* .MaxComputeWorkGroupSizeX = */ 1024,
|
|
||||||
/* .MaxComputeWorkGroupSizeY = */ 1024,
|
|
||||||
/* .MaxComputeWorkGroupSizeZ = */ 64,
|
|
||||||
/* .MaxComputeUniformComponents = */ 1024,
|
|
||||||
/* .MaxComputeTextureImageUnits = */ 16,
|
|
||||||
/* .MaxComputeImageUniforms = */ 8,
|
|
||||||
/* .MaxComputeAtomicCounters = */ 8,
|
|
||||||
/* .MaxComputeAtomicCounterBuffers = */ 1,
|
|
||||||
/* .MaxVaryingComponents = */ 60,
|
|
||||||
/* .MaxVertexOutputComponents = */ 64,
|
|
||||||
/* .MaxGeometryInputComponents = */ 64,
|
|
||||||
/* .MaxGeometryOutputComponents = */ 128,
|
|
||||||
/* .MaxFragmentInputComponents = */ 128,
|
|
||||||
/* .MaxImageUnits = */ 8,
|
|
||||||
/* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8,
|
|
||||||
/* .MaxCombinedShaderOutputResources = */ 8,
|
|
||||||
/* .MaxImageSamples = */ 0,
|
|
||||||
/* .MaxVertexImageUniforms = */ 0,
|
|
||||||
/* .MaxTessControlImageUniforms = */ 0,
|
|
||||||
/* .MaxTessEvaluationImageUniforms = */ 0,
|
|
||||||
/* .MaxGeometryImageUniforms = */ 0,
|
|
||||||
/* .MaxFragmentImageUniforms = */ 8,
|
|
||||||
/* .MaxCombinedImageUniforms = */ 8,
|
|
||||||
/* .MaxGeometryTextureImageUnits = */ 16,
|
|
||||||
/* .MaxGeometryOutputVertices = */ 256,
|
|
||||||
/* .MaxGeometryTotalOutputComponents = */ 1024,
|
|
||||||
/* .MaxGeometryUniformComponents = */ 1024,
|
|
||||||
/* .MaxGeometryVaryingComponents = */ 64,
|
|
||||||
/* .MaxTessControlInputComponents = */ 128,
|
|
||||||
/* .MaxTessControlOutputComponents = */ 128,
|
|
||||||
/* .MaxTessControlTextureImageUnits = */ 16,
|
|
||||||
/* .MaxTessControlUniformComponents = */ 1024,
|
|
||||||
/* .MaxTessControlTotalOutputComponents = */ 4096,
|
|
||||||
/* .MaxTessEvaluationInputComponents = */ 128,
|
|
||||||
/* .MaxTessEvaluationOutputComponents = */ 128,
|
|
||||||
/* .MaxTessEvaluationTextureImageUnits = */ 16,
|
|
||||||
/* .MaxTessEvaluationUniformComponents = */ 1024,
|
|
||||||
/* .MaxTessPatchComponents = */ 120,
|
|
||||||
/* .MaxPatchVertices = */ 32,
|
|
||||||
/* .MaxTessGenLevel = */ 64,
|
|
||||||
/* .MaxViewports = */ 16,
|
|
||||||
/* .MaxVertexAtomicCounters = */ 0,
|
|
||||||
/* .MaxTessControlAtomicCounters = */ 0,
|
|
||||||
/* .MaxTessEvaluationAtomicCounters = */ 0,
|
|
||||||
/* .MaxGeometryAtomicCounters = */ 0,
|
|
||||||
/* .MaxFragmentAtomicCounters = */ 8,
|
|
||||||
/* .MaxCombinedAtomicCounters = */ 8,
|
|
||||||
/* .MaxAtomicCounterBindings = */ 1,
|
|
||||||
/* .MaxVertexAtomicCounterBuffers = */ 0,
|
|
||||||
/* .MaxTessControlAtomicCounterBuffers = */ 0,
|
|
||||||
/* .MaxTessEvaluationAtomicCounterBuffers = */ 0,
|
|
||||||
/* .MaxGeometryAtomicCounterBuffers = */ 0,
|
|
||||||
/* .MaxFragmentAtomicCounterBuffers = */ 1,
|
|
||||||
/* .MaxCombinedAtomicCounterBuffers = */ 1,
|
|
||||||
/* .MaxAtomicCounterBufferSize = */ 16384,
|
|
||||||
/* .MaxTransformFeedbackBuffers = */ 4,
|
|
||||||
/* .MaxTransformFeedbackInterleavedComponents = */ 64,
|
|
||||||
/* .MaxCullDistances = */ 8,
|
|
||||||
/* .MaxCombinedClipAndCullDistances = */ 8,
|
|
||||||
/* .MaxSamples = */ 4,
|
|
||||||
/* .maxMeshOutputVerticesNV = */ 256,
|
|
||||||
/* .maxMeshOutputPrimitivesNV = */ 512,
|
|
||||||
/* .maxMeshWorkGroupSizeX_NV = */ 32,
|
|
||||||
/* .maxMeshWorkGroupSizeY_NV = */ 1,
|
|
||||||
/* .maxMeshWorkGroupSizeZ_NV = */ 1,
|
|
||||||
/* .maxTaskWorkGroupSizeX_NV = */ 32,
|
|
||||||
/* .maxTaskWorkGroupSizeY_NV = */ 1,
|
|
||||||
/* .maxTaskWorkGroupSizeZ_NV = */ 1,
|
|
||||||
/* .maxMeshViewCountNV = */ 4,
|
|
||||||
/* .maxDualSourceDrawBuffersEXT = */ 4,
|
|
||||||
|
|
||||||
/* .limits = */ TLimits{
|
|
||||||
/* .nonInductiveForLoops = */ true,
|
|
||||||
/* .whileLoops = */ true,
|
|
||||||
/* .doWhileLoops = */ true,
|
|
||||||
/* .generalUniformIndexing = */ true,
|
|
||||||
/* .generalAttributeMatrixVectorIndexing = */ true,
|
|
||||||
/* .generalVaryingIndexing = */ true,
|
|
||||||
/* .generalSamplerIndexing = */ true,
|
|
||||||
/* .generalVariableIndexing = */ true,
|
|
||||||
/* .generalConstantMatrixVectorIndexing = */ true,
|
|
||||||
}};
|
|
||||||
|
|
||||||
|
|
||||||
const std::vector<unsigned int> CompileGLSL(const std::string& filename, EShLanguage ShaderType, bool skinned, bool cubemap) {
|
|
||||||
std::string newString = "#version 430 core\n";
|
|
||||||
|
|
||||||
newString += "#extension GL_GOOGLE_include_directive : enable\n";
|
|
||||||
newString += "#extension GL_GOOGLE_cpp_style_line_directive : enable\n";
|
|
||||||
|
|
||||||
if(skinned)
|
|
||||||
newString += "#define BONE\n";
|
|
||||||
|
|
||||||
if(cubemap)
|
|
||||||
newString += "#define CUBEMAP\n";
|
|
||||||
|
|
||||||
newString += "#line 1\n";
|
|
||||||
|
|
||||||
newString += filename;
|
|
||||||
|
|
||||||
const char* InputCString = newString.c_str();
|
|
||||||
|
|
||||||
glslang::TShader Shader(ShaderType);
|
|
||||||
|
|
||||||
Shader.setStrings(&InputCString, 1);
|
|
||||||
|
|
||||||
int ClientInputSemanticsVersion = 100; // maps to, say, #define VULKAN 100
|
|
||||||
glslang::EShTargetClientVersion VulkanClientVersion = glslang::EShTargetVulkan_1_1;
|
|
||||||
glslang::EShTargetLanguageVersion TargetVersion = glslang::EShTargetSpv_1_0;
|
|
||||||
|
|
||||||
Shader.setEnvInput(glslang::EShSourceGlsl, ShaderType, glslang::EShClientVulkan, ClientInputSemanticsVersion);
|
|
||||||
Shader.setEnvClient(glslang::EShClientVulkan, VulkanClientVersion);
|
|
||||||
Shader.setEnvTarget(glslang::EShTargetSpv, TargetVersion);
|
|
||||||
|
|
||||||
TBuiltInResource Resources = DefaultTBuiltInResource;
|
|
||||||
EShMessages messages = (EShMessages) (EShMsgSpvRules);
|
|
||||||
|
|
||||||
DirStackFileIncluder includer;
|
|
||||||
includer.pushExternalLocalDirectory(file::get_domain_path(file::Domain::Internal).string());
|
|
||||||
|
|
||||||
if (!Shader.parse(&Resources, 100, false, (EShMessages)0, includer)) {
|
|
||||||
console::error(System::Renderer, "{}", Shader.getInfoLog());
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
glslang::TProgram Program;
|
|
||||||
Program.addShader(&Shader);
|
|
||||||
|
|
||||||
if(!Program.link(messages)) {
|
|
||||||
console::error(System::None, "Failed to link shader: {} {} {}", filename, Shader.getInfoLog(), Shader.getInfoDebugLog());
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<unsigned int> SpirV;
|
|
||||||
spv::SpvBuildLogger logger;
|
|
||||||
glslang::SpvOptions spvOptions;
|
|
||||||
glslang::GlslangToSpv(*Program.getIntermediate(ShaderType), SpirV, &logger, &spvOptions);
|
|
||||||
|
|
||||||
return SpirV;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::variant<std::string, std::vector<uint32_t>> 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);
|
auto shader_file = file::open(file::internal_domain / filename);
|
||||||
|
@ -184,31 +13,24 @@ std::variant<std::string, std::vector<uint32_t>> get_shader(std::string filename
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
EShLanguage lang;
|
ShaderStage stage;
|
||||||
if(filename.find("vert") != std::string::npos) {
|
if(filename.find("vert") != std::string::npos) {
|
||||||
lang = EShLangVertex;
|
stage = ShaderStage::Vertex;
|
||||||
} else {
|
} else {
|
||||||
lang = EShLangFragment;
|
stage = ShaderStage::Fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto vertexSPIRV = CompileGLSL(shader_file->read_as_string(), lang, skinned, cubemap);
|
CompileOptions options;
|
||||||
|
if(skinned)
|
||||||
|
options.add_definition("BONE");
|
||||||
|
|
||||||
#ifdef PLATFORM_MACOS
|
if(cubemap)
|
||||||
spirv_cross::CompilerMSL msl(std::move(vertexSPIRV));
|
options.add_definition("CUBEMAP");
|
||||||
|
|
||||||
spirv_cross::CompilerMSL::Options opts;
|
return shader_compiler.compile(ShaderLanguage::GLSL, stage, shader_file->read_as_string(), ShaderLanguage::MSL, options)->source;
|
||||||
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) {
|
GFXPipeline* MaterialCompiler::create_static_pipeline(GFXGraphicsPipelineCreateInfo createInfo, bool positions_only, bool cubemap) {
|
||||||
// take vertex src
|
// take vertex src
|
||||||
std::string vertex_path = createInfo.shaders.vertex_path.data();
|
std::string vertex_path = createInfo.shaders.vertex_path.data();
|
||||||
vertex_path += ".glsl";
|
vertex_path += ".glsl";
|
||||||
|
@ -245,7 +67,7 @@ GFXPipeline* ShaderCompiler::create_static_pipeline(GFXGraphicsPipelineCreateInf
|
||||||
return engine->get_gfx()->create_graphics_pipeline(createInfo);
|
return engine->get_gfx()->create_graphics_pipeline(createInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
GFXPipeline* ShaderCompiler::create_skinned_pipeline(GFXGraphicsPipelineCreateInfo createInfo, bool positions_only) {
|
GFXPipeline* MaterialCompiler::create_skinned_pipeline(GFXGraphicsPipelineCreateInfo createInfo, bool positions_only) {
|
||||||
createInfo.label += " (Skinned)";
|
createInfo.label += " (Skinned)";
|
||||||
|
|
||||||
// take vertex src
|
// take vertex src
|
||||||
|
@ -290,9 +112,7 @@ GFXPipeline* ShaderCompiler::create_skinned_pipeline(GFXGraphicsPipelineCreateIn
|
||||||
return engine->get_gfx()->create_graphics_pipeline(createInfo);
|
return engine->get_gfx()->create_graphics_pipeline(createInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<GFXPipeline*, GFXPipeline*> ShaderCompiler::create_pipeline_permutations(GFXGraphicsPipelineCreateInfo& createInfo, bool positions_only) {
|
std::tuple<GFXPipeline*, GFXPipeline*> MaterialCompiler::create_pipeline_permutations(GFXGraphicsPipelineCreateInfo& createInfo, bool positions_only) {
|
||||||
glslang::InitializeProcess();
|
|
||||||
|
|
||||||
auto st = create_static_pipeline(createInfo, positions_only);
|
auto st = create_static_pipeline(createInfo, positions_only);
|
||||||
auto ss = create_skinned_pipeline(createInfo, positions_only);
|
auto ss = create_skinned_pipeline(createInfo, positions_only);
|
||||||
|
|
||||||
|
@ -364,7 +184,7 @@ layout(push_constant, binding = 0) uniform PushConstant {\n \
|
||||||
int materialOffset;\n \
|
int materialOffset;\n \
|
||||||
};\n";
|
};\n";
|
||||||
|
|
||||||
std::variant<std::string, std::vector<uint32_t>> ShaderCompiler::compile_material_fragment(Material& material, bool use_ibl) {
|
std::variant<std::string, std::vector<uint32_t>> MaterialCompiler::compile_material_fragment(Material& material, bool use_ibl) {
|
||||||
walked_nodes.clear();
|
walked_nodes.clear();
|
||||||
|
|
||||||
if(!render_options.enable_ibl)
|
if(!render_options.enable_ibl)
|
||||||
|
@ -567,19 +387,5 @@ std::variant<std::string, std::vector<uint32_t>> ShaderCompiler::compile_materia
|
||||||
|
|
||||||
src += "}\n";
|
src += "}\n";
|
||||||
|
|
||||||
auto vertexSPIRV = CompileGLSL(src, EShLangFragment, false, false);
|
return shader_compiler.compile(ShaderLanguage::GLSL, ShaderStage::Fragment, src, ShaderLanguage::MSL)->source;
|
||||||
|
|
||||||
#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
|
|
||||||
}
|
}
|
|
@ -18,10 +18,11 @@
|
||||||
#include "shadowpass.hpp"
|
#include "shadowpass.hpp"
|
||||||
#include "smaapass.hpp"
|
#include "smaapass.hpp"
|
||||||
#include "scenecapture.hpp"
|
#include "scenecapture.hpp"
|
||||||
#include "shadercompiler.hpp"
|
#include "materialcompiler.hpp"
|
||||||
#include "assertions.hpp"
|
#include "assertions.hpp"
|
||||||
#include "dofpass.hpp"
|
#include "dofpass.hpp"
|
||||||
#include "frustum.hpp"
|
#include "frustum.hpp"
|
||||||
|
#include "shadercompiler.hpp"
|
||||||
|
|
||||||
struct ElementInstance {
|
struct ElementInstance {
|
||||||
Vector4 color;
|
Vector4 color;
|
||||||
|
@ -83,6 +84,8 @@ struct UIPushConstant {
|
||||||
Renderer::Renderer(GFX* gfx, const bool enable_imgui) : gfx(gfx) {
|
Renderer::Renderer(GFX* gfx, const bool enable_imgui) : gfx(gfx) {
|
||||||
Expects(gfx != nullptr);
|
Expects(gfx != nullptr);
|
||||||
|
|
||||||
|
shader_compiler.set_include_path(file::get_domain_path(file::Domain::Internal).string());
|
||||||
|
|
||||||
createDummyTexture();
|
createDummyTexture();
|
||||||
|
|
||||||
shadow_pass = std::make_unique<ShadowPass>(gfx);
|
shadow_pass = std::make_unique<ShadowPass>(gfx);
|
||||||
|
@ -691,19 +694,19 @@ void Renderer::create_mesh_pipeline(Material& material) {
|
||||||
pipelineInfo.blending.src_rgb = GFXBlendFactor::SrcAlpha;
|
pipelineInfo.blending.src_rgb = GFXBlendFactor::SrcAlpha;
|
||||||
pipelineInfo.blending.dst_rgb = GFXBlendFactor::OneMinusSrcAlpha;
|
pipelineInfo.blending.dst_rgb = GFXBlendFactor::OneMinusSrcAlpha;
|
||||||
|
|
||||||
pipelineInfo.shaders.fragment_src = shader_compiler.compile_material_fragment(material);
|
pipelineInfo.shaders.fragment_src = material_compiler.compile_material_fragment(material);
|
||||||
pipelineInfo.shaders.fragment_path = "";
|
pipelineInfo.shaders.fragment_path = "";
|
||||||
|
|
||||||
auto [static_pipeline, skinned_pipeline] = shader_compiler.create_pipeline_permutations(pipelineInfo);
|
auto [static_pipeline, skinned_pipeline] = material_compiler.create_pipeline_permutations(pipelineInfo);
|
||||||
|
|
||||||
material.static_pipeline = static_pipeline;
|
material.static_pipeline = static_pipeline;
|
||||||
material.skinned_pipeline = skinned_pipeline;
|
material.skinned_pipeline = skinned_pipeline;
|
||||||
|
|
||||||
pipelineInfo.render_pass = scene_capture->renderPass;
|
pipelineInfo.render_pass = scene_capture->renderPass;
|
||||||
|
|
||||||
pipelineInfo.shaders.fragment_src = shader_compiler.compile_material_fragment(material, false); // scene capture does not use IBL
|
pipelineInfo.shaders.fragment_src = material_compiler.compile_material_fragment(material, false); // scene capture does not use IBL
|
||||||
|
|
||||||
material.capture_pipeline = shader_compiler.create_static_pipeline(pipelineInfo, false, true);
|
material.capture_pipeline = material_compiler.create_static_pipeline(pipelineInfo, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::createDummyTexture() {
|
void Renderer::createDummyTexture() {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
#include "renderer.hpp"
|
#include "renderer.hpp"
|
||||||
#include "shadowpass.hpp"
|
#include "shadowpass.hpp"
|
||||||
#include "shadercompiler.hpp"
|
#include "materialcompiler.hpp"
|
||||||
#include "frustum.hpp"
|
#include "frustum.hpp"
|
||||||
|
|
||||||
struct PushConstant {
|
struct PushConstant {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "gfx.hpp"
|
#include "gfx.hpp"
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
#include "shadercompiler.hpp"
|
#include "materialcompiler.hpp"
|
||||||
#include "assertions.hpp"
|
#include "assertions.hpp"
|
||||||
#include "frustum.hpp"
|
#include "frustum.hpp"
|
||||||
|
|
||||||
|
@ -325,7 +325,7 @@ void ShadowPass::create_pipelines() {
|
||||||
{
|
{
|
||||||
pipelineInfo.label = "Sun Shadow";
|
pipelineInfo.label = "Sun Shadow";
|
||||||
|
|
||||||
auto [static_pipeline, skinned_pipeline] = shader_compiler.create_pipeline_permutations(pipelineInfo, true);
|
auto [static_pipeline, skinned_pipeline] = material_compiler.create_pipeline_permutations(pipelineInfo, true);
|
||||||
|
|
||||||
static_sun_pipeline = static_pipeline;
|
static_sun_pipeline = static_pipeline;
|
||||||
skinned_sun_pipeline = skinned_pipeline;
|
skinned_sun_pipeline = skinned_pipeline;
|
||||||
|
@ -337,7 +337,7 @@ void ShadowPass::create_pipelines() {
|
||||||
|
|
||||||
pipelineInfo.render_pass = cube_render_pass;
|
pipelineInfo.render_pass = cube_render_pass;
|
||||||
|
|
||||||
auto [static_pipeline, skinned_pipeline] = shader_compiler.create_pipeline_permutations(pipelineInfo, true);
|
auto [static_pipeline, skinned_pipeline] = material_compiler.create_pipeline_permutations(pipelineInfo, true);
|
||||||
|
|
||||||
static_spot_pipeline = static_pipeline;
|
static_spot_pipeline = static_pipeline;
|
||||||
skinned_spot_pipeline = skinned_pipeline;
|
skinned_spot_pipeline = skinned_pipeline;
|
||||||
|
@ -349,7 +349,7 @@ void ShadowPass::create_pipelines() {
|
||||||
|
|
||||||
pipelineInfo.shaders.fragment_path = "omnishadow.frag";
|
pipelineInfo.shaders.fragment_path = "omnishadow.frag";
|
||||||
|
|
||||||
auto [static_pipeline, skinned_pipeline] = shader_compiler.create_pipeline_permutations(pipelineInfo, true);
|
auto [static_pipeline, skinned_pipeline] = material_compiler.create_pipeline_permutations(pipelineInfo, true);
|
||||||
|
|
||||||
static_point_pipeline = static_pipeline;
|
static_point_pipeline = static_pipeline;
|
||||||
skinned_point_pipeline = skinned_pipeline;
|
skinned_point_pipeline = skinned_pipeline;
|
||||||
|
|
15
engine/shadercompiler/CMakeLists.txt
Executable file
15
engine/shadercompiler/CMakeLists.txt
Executable file
|
@ -0,0 +1,15 @@
|
||||||
|
set(SRC
|
||||||
|
include/shadercompiler.hpp
|
||||||
|
|
||||||
|
src/shadercompiler.cpp
|
||||||
|
src/includer.hpp
|
||||||
|
src/defaultresources.hpp)
|
||||||
|
|
||||||
|
add_library(ShaderCompiler STATIC ${SRC})
|
||||||
|
target_link_libraries(ShaderCompiler
|
||||||
|
PRIVATE
|
||||||
|
Utility
|
||||||
|
Log
|
||||||
|
${CROSS_LIBS})
|
||||||
|
target_include_directories(ShaderCompiler PUBLIC include PRIVATE src)
|
||||||
|
set_engine_properties(ShaderCompiler)
|
59
engine/shadercompiler/include/shadercompiler.hpp
Executable file
59
engine/shadercompiler/include/shadercompiler.hpp
Executable file
|
@ -0,0 +1,59 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <variant>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <string_view>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
enum class ShaderStage {
|
||||||
|
Vertex,
|
||||||
|
Fragment
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ShaderLanguage {
|
||||||
|
GLSL,
|
||||||
|
MSL,
|
||||||
|
SPIRV
|
||||||
|
};
|
||||||
|
|
||||||
|
class CompileOptions {
|
||||||
|
public:
|
||||||
|
void add_definition(const std::string_view name) {
|
||||||
|
definitions.emplace_back(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> definitions;
|
||||||
|
|
||||||
|
bool is_apple_mobile = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShaderSource {
|
||||||
|
public:
|
||||||
|
ShaderSource(const std::string source_string) : source(source_string) {}
|
||||||
|
ShaderSource(const std::vector<uint32_t> source_bytecode) : source(source_bytecode) {}
|
||||||
|
|
||||||
|
std::variant<std::string, std::vector<uint32_t>> source;
|
||||||
|
|
||||||
|
std::string_view as_string() const {
|
||||||
|
return std::get<std::string>(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t> as_bytecode() const {
|
||||||
|
return std::get<std::vector<uint32_t>>(source);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShaderCompiler {
|
||||||
|
public:
|
||||||
|
ShaderCompiler();
|
||||||
|
|
||||||
|
void set_include_path(const std::string_view path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Compiles from one shader language to another shader language.
|
||||||
|
*/
|
||||||
|
std::optional<ShaderSource> compile(const ShaderLanguage from_language, const ShaderStage shader_stage, const ShaderSource& shader_source, const ShaderLanguage to_language, const CompileOptions& options = CompileOptions());
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline ShaderCompiler shader_compiler;
|
108
engine/shadercompiler/src/defaultresources.hpp
Executable file
108
engine/shadercompiler/src/defaultresources.hpp
Executable file
|
@ -0,0 +1,108 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
const TBuiltInResource DefaultTBuiltInResource = {
|
||||||
|
/* .MaxLights = */ 32,
|
||||||
|
/* .MaxClipPlanes = */ 6,
|
||||||
|
/* .MaxTextureUnits = */ 32,
|
||||||
|
/* .MaxTextureCoords = */ 32,
|
||||||
|
/* .MaxVertexAttribs = */ 64,
|
||||||
|
/* .MaxVertexUniformComponents = */ 4096,
|
||||||
|
/* .MaxVaryingFloats = */ 64,
|
||||||
|
/* .MaxVertexTextureImageUnits = */ 32,
|
||||||
|
/* .MaxCombinedTextureImageUnits = */ 80,
|
||||||
|
/* .MaxTextureImageUnits = */ 32,
|
||||||
|
/* .MaxFragmentUniformComponents = */ 4096,
|
||||||
|
/* .MaxDrawBuffers = */ 32,
|
||||||
|
/* .MaxVertexUniformVectors = */ 128,
|
||||||
|
/* .MaxVaryingVectors = */ 8,
|
||||||
|
/* .MaxFragmentUniformVectors = */ 16,
|
||||||
|
/* .MaxVertexOutputVectors = */ 16,
|
||||||
|
/* .MaxFragmentInputVectors = */ 15,
|
||||||
|
/* .MinProgramTexelOffset = */ -8,
|
||||||
|
/* .MaxProgramTexelOffset = */ 7,
|
||||||
|
/* .MaxClipDistances = */ 8,
|
||||||
|
/* .MaxComputeWorkGroupCountX = */ 65535,
|
||||||
|
/* .MaxComputeWorkGroupCountY = */ 65535,
|
||||||
|
/* .MaxComputeWorkGroupCountZ = */ 65535,
|
||||||
|
/* .MaxComputeWorkGroupSizeX = */ 1024,
|
||||||
|
/* .MaxComputeWorkGroupSizeY = */ 1024,
|
||||||
|
/* .MaxComputeWorkGroupSizeZ = */ 64,
|
||||||
|
/* .MaxComputeUniformComponents = */ 1024,
|
||||||
|
/* .MaxComputeTextureImageUnits = */ 16,
|
||||||
|
/* .MaxComputeImageUniforms = */ 8,
|
||||||
|
/* .MaxComputeAtomicCounters = */ 8,
|
||||||
|
/* .MaxComputeAtomicCounterBuffers = */ 1,
|
||||||
|
/* .MaxVaryingComponents = */ 60,
|
||||||
|
/* .MaxVertexOutputComponents = */ 64,
|
||||||
|
/* .MaxGeometryInputComponents = */ 64,
|
||||||
|
/* .MaxGeometryOutputComponents = */ 128,
|
||||||
|
/* .MaxFragmentInputComponents = */ 128,
|
||||||
|
/* .MaxImageUnits = */ 8,
|
||||||
|
/* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8,
|
||||||
|
/* .MaxCombinedShaderOutputResources = */ 8,
|
||||||
|
/* .MaxImageSamples = */ 0,
|
||||||
|
/* .MaxVertexImageUniforms = */ 0,
|
||||||
|
/* .MaxTessControlImageUniforms = */ 0,
|
||||||
|
/* .MaxTessEvaluationImageUniforms = */ 0,
|
||||||
|
/* .MaxGeometryImageUniforms = */ 0,
|
||||||
|
/* .MaxFragmentImageUniforms = */ 8,
|
||||||
|
/* .MaxCombinedImageUniforms = */ 8,
|
||||||
|
/* .MaxGeometryTextureImageUnits = */ 16,
|
||||||
|
/* .MaxGeometryOutputVertices = */ 256,
|
||||||
|
/* .MaxGeometryTotalOutputComponents = */ 1024,
|
||||||
|
/* .MaxGeometryUniformComponents = */ 1024,
|
||||||
|
/* .MaxGeometryVaryingComponents = */ 64,
|
||||||
|
/* .MaxTessControlInputComponents = */ 128,
|
||||||
|
/* .MaxTessControlOutputComponents = */ 128,
|
||||||
|
/* .MaxTessControlTextureImageUnits = */ 16,
|
||||||
|
/* .MaxTessControlUniformComponents = */ 1024,
|
||||||
|
/* .MaxTessControlTotalOutputComponents = */ 4096,
|
||||||
|
/* .MaxTessEvaluationInputComponents = */ 128,
|
||||||
|
/* .MaxTessEvaluationOutputComponents = */ 128,
|
||||||
|
/* .MaxTessEvaluationTextureImageUnits = */ 16,
|
||||||
|
/* .MaxTessEvaluationUniformComponents = */ 1024,
|
||||||
|
/* .MaxTessPatchComponents = */ 120,
|
||||||
|
/* .MaxPatchVertices = */ 32,
|
||||||
|
/* .MaxTessGenLevel = */ 64,
|
||||||
|
/* .MaxViewports = */ 16,
|
||||||
|
/* .MaxVertexAtomicCounters = */ 0,
|
||||||
|
/* .MaxTessControlAtomicCounters = */ 0,
|
||||||
|
/* .MaxTessEvaluationAtomicCounters = */ 0,
|
||||||
|
/* .MaxGeometryAtomicCounters = */ 0,
|
||||||
|
/* .MaxFragmentAtomicCounters = */ 8,
|
||||||
|
/* .MaxCombinedAtomicCounters = */ 8,
|
||||||
|
/* .MaxAtomicCounterBindings = */ 1,
|
||||||
|
/* .MaxVertexAtomicCounterBuffers = */ 0,
|
||||||
|
/* .MaxTessControlAtomicCounterBuffers = */ 0,
|
||||||
|
/* .MaxTessEvaluationAtomicCounterBuffers = */ 0,
|
||||||
|
/* .MaxGeometryAtomicCounterBuffers = */ 0,
|
||||||
|
/* .MaxFragmentAtomicCounterBuffers = */ 1,
|
||||||
|
/* .MaxCombinedAtomicCounterBuffers = */ 1,
|
||||||
|
/* .MaxAtomicCounterBufferSize = */ 16384,
|
||||||
|
/* .MaxTransformFeedbackBuffers = */ 4,
|
||||||
|
/* .MaxTransformFeedbackInterleavedComponents = */ 64,
|
||||||
|
/* .MaxCullDistances = */ 8,
|
||||||
|
/* .MaxCombinedClipAndCullDistances = */ 8,
|
||||||
|
/* .MaxSamples = */ 4,
|
||||||
|
/* .maxMeshOutputVerticesNV = */ 256,
|
||||||
|
/* .maxMeshOutputPrimitivesNV = */ 512,
|
||||||
|
/* .maxMeshWorkGroupSizeX_NV = */ 32,
|
||||||
|
/* .maxMeshWorkGroupSizeY_NV = */ 1,
|
||||||
|
/* .maxMeshWorkGroupSizeZ_NV = */ 1,
|
||||||
|
/* .maxTaskWorkGroupSizeX_NV = */ 32,
|
||||||
|
/* .maxTaskWorkGroupSizeY_NV = */ 1,
|
||||||
|
/* .maxTaskWorkGroupSizeZ_NV = */ 1,
|
||||||
|
/* .maxMeshViewCountNV = */ 4,
|
||||||
|
/* .maxDualSourceDrawBuffersEXT = */ 4,
|
||||||
|
|
||||||
|
/* .limits = */ TLimits{
|
||||||
|
/* .nonInductiveForLoops = */ true,
|
||||||
|
/* .whileLoops = */ true,
|
||||||
|
/* .doWhileLoops = */ true,
|
||||||
|
/* .generalUniformIndexing = */ true,
|
||||||
|
/* .generalAttributeMatrixVectorIndexing = */ true,
|
||||||
|
/* .generalVaryingIndexing = */ true,
|
||||||
|
/* .generalSamplerIndexing = */ true,
|
||||||
|
/* .generalVariableIndexing = */ true,
|
||||||
|
/* .generalConstantMatrixVectorIndexing = */ true,
|
||||||
|
}};
|
|
@ -43,8 +43,6 @@
|
||||||
|
|
||||||
#include <glslang/Public/ShaderLang.h>
|
#include <glslang/Public/ShaderLang.h>
|
||||||
|
|
||||||
#include "file.hpp"
|
|
||||||
|
|
||||||
// Default include class for normal include convention of search backward
|
// Default include class for normal include convention of search backward
|
||||||
// through the stack of active include paths (for nested includes).
|
// through the stack of active include paths (for nested includes).
|
||||||
// Can be overridden to customize.
|
// Can be overridden to customize.
|
||||||
|
@ -136,6 +134,7 @@ protected:
|
||||||
// If no path markers, return current working directory.
|
// If no path markers, return current working directory.
|
||||||
// Otherwise, strip file name and return path leading up to it.
|
// Otherwise, strip file name and return path leading up to it.
|
||||||
virtual std::string getDirectory(const std::string) const {
|
virtual std::string getDirectory(const std::string) const {
|
||||||
return file::get_domain_path(file::Domain::Internal).string();
|
//return file::get_domain_path(file::Domain::Internal).string();
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
};
|
};
|
117
engine/shadercompiler/src/shadercompiler.cpp
Executable file
117
engine/shadercompiler/src/shadercompiler.cpp
Executable file
|
@ -0,0 +1,117 @@
|
||||||
|
#include "shadercompiler.hpp"
|
||||||
|
|
||||||
|
#include <spirv_cpp.hpp>
|
||||||
|
#include <spirv_msl.hpp>
|
||||||
|
#include <SPIRV/GlslangToSpv.h>
|
||||||
|
|
||||||
|
#include "log.hpp"
|
||||||
|
#include "string_utils.hpp"
|
||||||
|
#include "includer.hpp"
|
||||||
|
#include "defaultresources.hpp"
|
||||||
|
|
||||||
|
static inline std::string include_path;
|
||||||
|
|
||||||
|
ShaderCompiler::ShaderCompiler() {
|
||||||
|
glslang::InitializeProcess();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderCompiler::set_include_path(const std::string_view path) {
|
||||||
|
include_path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<uint32_t> compile_glsl_to_spv(const std::string_view source_string, const EShLanguage shader_language, const CompileOptions& options) {
|
||||||
|
std::string newString = "#version 430 core\n";
|
||||||
|
|
||||||
|
newString += "#extension GL_GOOGLE_include_directive : enable\n";
|
||||||
|
newString += "#extension GL_GOOGLE_cpp_style_line_directive : enable\n";
|
||||||
|
|
||||||
|
for(auto& definition : options.definitions)
|
||||||
|
newString += "#define " + definition + "\n";
|
||||||
|
|
||||||
|
newString += "#line 1\n";
|
||||||
|
|
||||||
|
newString += source_string;
|
||||||
|
|
||||||
|
const char* InputCString = newString.c_str();
|
||||||
|
|
||||||
|
glslang::TShader Shader(shader_language);
|
||||||
|
|
||||||
|
Shader.setStrings(&InputCString, 1);
|
||||||
|
|
||||||
|
int ClientInputSemanticsVersion = 100; // maps to, say, #define VULKAN 100
|
||||||
|
glslang::EShTargetClientVersion VulkanClientVersion = glslang::EShTargetVulkan_1_1;
|
||||||
|
glslang::EShTargetLanguageVersion TargetVersion = glslang::EShTargetSpv_1_0;
|
||||||
|
|
||||||
|
Shader.setEnvInput(glslang::EShSourceGlsl, shader_language, glslang::EShClientVulkan, ClientInputSemanticsVersion);
|
||||||
|
Shader.setEnvClient(glslang::EShClientVulkan, VulkanClientVersion);
|
||||||
|
Shader.setEnvTarget(glslang::EShTargetSpv, TargetVersion);
|
||||||
|
|
||||||
|
TBuiltInResource Resources = DefaultTBuiltInResource;
|
||||||
|
EShMessages messages = (EShMessages) (EShMsgSpvRules);
|
||||||
|
|
||||||
|
DirStackFileIncluder includer;
|
||||||
|
includer.pushExternalLocalDirectory(include_path);
|
||||||
|
|
||||||
|
if (!Shader.parse(&Resources, 100, false, (EShMessages)0, includer)) {
|
||||||
|
console::error(System::Renderer, "{}", Shader.getInfoLog());
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
glslang::TProgram Program;
|
||||||
|
Program.addShader(&Shader);
|
||||||
|
|
||||||
|
if(!Program.link(messages)) {
|
||||||
|
console::error(System::None, "Failed to link shader: {} {} {}", source_string.data(), Shader.getInfoLog(), Shader.getInfoDebugLog());
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned int> SpirV;
|
||||||
|
spv::SpvBuildLogger logger;
|
||||||
|
glslang::SpvOptions spvOptions;
|
||||||
|
glslang::GlslangToSpv(*Program.getIntermediate(shader_language), SpirV, &logger, &spvOptions);
|
||||||
|
|
||||||
|
return SpirV;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<ShaderSource> ShaderCompiler::compile(const ShaderLanguage from_language, const ShaderStage shader_stage, const ShaderSource& shader_source, const ShaderLanguage to_language, const CompileOptions& options) {
|
||||||
|
if(from_language != ShaderLanguage::GLSL) {
|
||||||
|
console::error(System::Renderer, "Non-supported input language!");
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
EShLanguage lang = EShLangMiss;
|
||||||
|
switch(shader_stage) {
|
||||||
|
case ShaderStage::Vertex:
|
||||||
|
lang = EShLangVertex;
|
||||||
|
break;
|
||||||
|
case ShaderStage::Fragment:
|
||||||
|
lang = EShLangFragment;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto spirv = compile_glsl_to_spv(shader_source.as_string(), lang, options);
|
||||||
|
if(spirv.empty()) {
|
||||||
|
console::error(System::Renderer, "SPIRV generation failed!");
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PLATFORM_MACOS
|
||||||
|
spirv_cross::CompilerMSL msl(std::move(spirv));
|
||||||
|
|
||||||
|
spirv_cross::CompilerMSL::Options opts;
|
||||||
|
if(options.is_apple_mobile) {
|
||||||
|
opts.platform = spirv_cross::CompilerMSL::Options::Platform::macOS;
|
||||||
|
} else {
|
||||||
|
opts.platform = spirv_cross::CompilerMSL::Options::Platform::iOS;
|
||||||
|
}
|
||||||
|
opts.enable_decoration_binding = true;
|
||||||
|
|
||||||
|
msl.set_msl_options(opts);
|
||||||
|
|
||||||
|
return msl.compile();
|
||||||
|
#else
|
||||||
|
return spirv;
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -8,7 +8,7 @@
|
||||||
#include "gfx.hpp"
|
#include "gfx.hpp"
|
||||||
#include "asset.hpp"
|
#include "asset.hpp"
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "shadercompiler.hpp"
|
#include "materialcompiler.hpp"
|
||||||
|
|
||||||
struct BillPushConstant {
|
struct BillPushConstant {
|
||||||
Matrix4x4 view, mvp;
|
Matrix4x4 view, mvp;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
add_executable(ShaderCompiler main.cpp)
|
add_executable(ShaderCompilerTool main.cpp)
|
||||||
target_link_libraries(ShaderCompiler
|
target_link_libraries(ShaderCompilerTool
|
||||||
PUBLIC
|
PRIVATE
|
||||||
${CROSS_LIBS}
|
ShaderCompiler
|
||||||
Log)
|
Log
|
||||||
set_engine_properties(ShaderCompiler)
|
Utility)
|
||||||
set_output_dir(ShaderCompiler)
|
set_engine_properties(ShaderCompilerTool)
|
||||||
|
set_output_dir(ShaderCompilerTool)
|
||||||
|
|
|
@ -1,236 +1,86 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include <spirv_cpp.hpp>
|
#include "shadercompiler.hpp"
|
||||||
#include <spirv_msl.hpp>
|
|
||||||
#include <glslang/Public/ShaderLang.h>
|
|
||||||
#include <SPIRV/GlslangToSpv.h>
|
|
||||||
|
|
||||||
#include "DirStackIncluder.h"
|
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
|
#include "string_utils.hpp"
|
||||||
|
|
||||||
const TBuiltInResource DefaultTBuiltInResource = {
|
bool has_extension(const std::filesystem::path path, const std::string_view extension) {
|
||||||
/* .MaxLights = */ 32,
|
return string_contains(path.filename().string(), extension);
|
||||||
/* .MaxClipPlanes = */ 6,
|
|
||||||
/* .MaxTextureUnits = */ 32,
|
|
||||||
/* .MaxTextureCoords = */ 32,
|
|
||||||
/* .MaxVertexAttribs = */ 64,
|
|
||||||
/* .MaxVertexUniformComponents = */ 4096,
|
|
||||||
/* .MaxVaryingFloats = */ 64,
|
|
||||||
/* .MaxVertexTextureImageUnits = */ 32,
|
|
||||||
/* .MaxCombinedTextureImageUnits = */ 80,
|
|
||||||
/* .MaxTextureImageUnits = */ 32,
|
|
||||||
/* .MaxFragmentUniformComponents = */ 4096,
|
|
||||||
/* .MaxDrawBuffers = */ 32,
|
|
||||||
/* .MaxVertexUniformVectors = */ 128,
|
|
||||||
/* .MaxVaryingVectors = */ 8,
|
|
||||||
/* .MaxFragmentUniformVectors = */ 16,
|
|
||||||
/* .MaxVertexOutputVectors = */ 16,
|
|
||||||
/* .MaxFragmentInputVectors = */ 15,
|
|
||||||
/* .MinProgramTexelOffset = */ -8,
|
|
||||||
/* .MaxProgramTexelOffset = */ 7,
|
|
||||||
/* .MaxClipDistances = */ 8,
|
|
||||||
/* .MaxComputeWorkGroupCountX = */ 65535,
|
|
||||||
/* .MaxComputeWorkGroupCountY = */ 65535,
|
|
||||||
/* .MaxComputeWorkGroupCountZ = */ 65535,
|
|
||||||
/* .MaxComputeWorkGroupSizeX = */ 1024,
|
|
||||||
/* .MaxComputeWorkGroupSizeY = */ 1024,
|
|
||||||
/* .MaxComputeWorkGroupSizeZ = */ 64,
|
|
||||||
/* .MaxComputeUniformComponents = */ 1024,
|
|
||||||
/* .MaxComputeTextureImageUnits = */ 16,
|
|
||||||
/* .MaxComputeImageUniforms = */ 8,
|
|
||||||
/* .MaxComputeAtomicCounters = */ 8,
|
|
||||||
/* .MaxComputeAtomicCounterBuffers = */ 1,
|
|
||||||
/* .MaxVaryingComponents = */ 60,
|
|
||||||
/* .MaxVertexOutputComponents = */ 64,
|
|
||||||
/* .MaxGeometryInputComponents = */ 64,
|
|
||||||
/* .MaxGeometryOutputComponents = */ 128,
|
|
||||||
/* .MaxFragmentInputComponents = */ 128,
|
|
||||||
/* .MaxImageUnits = */ 8,
|
|
||||||
/* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8,
|
|
||||||
/* .MaxCombinedShaderOutputResources = */ 8,
|
|
||||||
/* .MaxImageSamples = */ 0,
|
|
||||||
/* .MaxVertexImageUniforms = */ 0,
|
|
||||||
/* .MaxTessControlImageUniforms = */ 0,
|
|
||||||
/* .MaxTessEvaluationImageUniforms = */ 0,
|
|
||||||
/* .MaxGeometryImageUniforms = */ 0,
|
|
||||||
/* .MaxFragmentImageUniforms = */ 8,
|
|
||||||
/* .MaxCombinedImageUniforms = */ 8,
|
|
||||||
/* .MaxGeometryTextureImageUnits = */ 16,
|
|
||||||
/* .MaxGeometryOutputVertices = */ 256,
|
|
||||||
/* .MaxGeometryTotalOutputComponents = */ 1024,
|
|
||||||
/* .MaxGeometryUniformComponents = */ 1024,
|
|
||||||
/* .MaxGeometryVaryingComponents = */ 64,
|
|
||||||
/* .MaxTessControlInputComponents = */ 128,
|
|
||||||
/* .MaxTessControlOutputComponents = */ 128,
|
|
||||||
/* .MaxTessControlTextureImageUnits = */ 16,
|
|
||||||
/* .MaxTessControlUniformComponents = */ 1024,
|
|
||||||
/* .MaxTessControlTotalOutputComponents = */ 4096,
|
|
||||||
/* .MaxTessEvaluationInputComponents = */ 128,
|
|
||||||
/* .MaxTessEvaluationOutputComponents = */ 128,
|
|
||||||
/* .MaxTessEvaluationTextureImageUnits = */ 16,
|
|
||||||
/* .MaxTessEvaluationUniformComponents = */ 1024,
|
|
||||||
/* .MaxTessPatchComponents = */ 120,
|
|
||||||
/* .MaxPatchVertices = */ 32,
|
|
||||||
/* .MaxTessGenLevel = */ 64,
|
|
||||||
/* .MaxViewports = */ 16,
|
|
||||||
/* .MaxVertexAtomicCounters = */ 0,
|
|
||||||
/* .MaxTessControlAtomicCounters = */ 0,
|
|
||||||
/* .MaxTessEvaluationAtomicCounters = */ 0,
|
|
||||||
/* .MaxGeometryAtomicCounters = */ 0,
|
|
||||||
/* .MaxFragmentAtomicCounters = */ 8,
|
|
||||||
/* .MaxCombinedAtomicCounters = */ 8,
|
|
||||||
/* .MaxAtomicCounterBindings = */ 1,
|
|
||||||
/* .MaxVertexAtomicCounterBuffers = */ 0,
|
|
||||||
/* .MaxTessControlAtomicCounterBuffers = */ 0,
|
|
||||||
/* .MaxTessEvaluationAtomicCounterBuffers = */ 0,
|
|
||||||
/* .MaxGeometryAtomicCounterBuffers = */ 0,
|
|
||||||
/* .MaxFragmentAtomicCounterBuffers = */ 1,
|
|
||||||
/* .MaxCombinedAtomicCounterBuffers = */ 1,
|
|
||||||
/* .MaxAtomicCounterBufferSize = */ 16384,
|
|
||||||
/* .MaxTransformFeedbackBuffers = */ 4,
|
|
||||||
/* .MaxTransformFeedbackInterleavedComponents = */ 64,
|
|
||||||
/* .MaxCullDistances = */ 8,
|
|
||||||
/* .MaxCombinedClipAndCullDistances = */ 8,
|
|
||||||
/* .MaxSamples = */ 4,
|
|
||||||
/* .maxMeshOutputVerticesNV = */ 256,
|
|
||||||
/* .maxMeshOutputPrimitivesNV = */ 512,
|
|
||||||
/* .maxMeshWorkGroupSizeX_NV = */ 32,
|
|
||||||
/* .maxMeshWorkGroupSizeY_NV = */ 1,
|
|
||||||
/* .maxMeshWorkGroupSizeZ_NV = */ 1,
|
|
||||||
/* .maxTaskWorkGroupSizeX_NV = */ 32,
|
|
||||||
/* .maxTaskWorkGroupSizeY_NV = */ 1,
|
|
||||||
/* .maxTaskWorkGroupSizeZ_NV = */ 1,
|
|
||||||
/* .maxMeshViewCountNV = */ 4,
|
|
||||||
/* .maxDualSourceDrawBuffersEXT = */ 4,
|
|
||||||
|
|
||||||
/* .limits = */ TLimits{
|
|
||||||
/* .nonInductiveForLoops = */ true,
|
|
||||||
/* .whileLoops = */ true,
|
|
||||||
/* .doWhileLoops = */ true,
|
|
||||||
/* .generalUniformIndexing = */ true,
|
|
||||||
/* .generalAttributeMatrixVectorIndexing = */ true,
|
|
||||||
/* .generalVaryingIndexing = */ true,
|
|
||||||
/* .generalSamplerIndexing = */ true,
|
|
||||||
/* .generalVariableIndexing = */ true,
|
|
||||||
/* .generalConstantMatrixVectorIndexing = */ true,
|
|
||||||
}};
|
|
||||||
|
|
||||||
const std::vector<unsigned int> CompileGLSL(const std::string& filename, EShLanguage ShaderType) {
|
|
||||||
std::string newString = "#version 430 core\n";
|
|
||||||
|
|
||||||
newString += "#extension GL_GOOGLE_include_directive : enable\n";
|
|
||||||
newString += "#extension GL_GOOGLE_cpp_style_line_directive : enable\n";
|
|
||||||
|
|
||||||
newString += "#line 1\n";
|
|
||||||
|
|
||||||
newString += filename;
|
|
||||||
|
|
||||||
const char* InputCString = newString.c_str();
|
|
||||||
|
|
||||||
glslang::TShader Shader(ShaderType);
|
|
||||||
|
|
||||||
Shader.setStrings(&InputCString, 1);
|
|
||||||
|
|
||||||
int ClientInputSemanticsVersion = 100; // maps to, say, #define VULKAN 100
|
|
||||||
glslang::EShTargetClientVersion VulkanClientVersion = glslang::EShTargetVulkan_1_1;
|
|
||||||
glslang::EShTargetLanguageVersion TargetVersion = glslang::EShTargetSpv_1_0;
|
|
||||||
|
|
||||||
Shader.setEnvInput(glslang::EShSourceGlsl, ShaderType, glslang::EShClientVulkan, ClientInputSemanticsVersion);
|
|
||||||
Shader.setEnvClient(glslang::EShClientVulkan, VulkanClientVersion);
|
|
||||||
Shader.setEnvTarget(glslang::EShTargetSpv, TargetVersion);
|
|
||||||
|
|
||||||
TBuiltInResource Resources = DefaultTBuiltInResource;
|
|
||||||
EShMessages messages = (EShMessages) (EShMsgSpvRules);
|
|
||||||
|
|
||||||
DirStackFileIncluder includer;
|
|
||||||
|
|
||||||
if (!Shader.parse(&Resources, 100, false, messages, includer)) {
|
|
||||||
console::error(System::None, "Failed to parse shader: {} {} {}", filename, Shader.getInfoLog(), Shader.getInfoDebugLog());
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
glslang::TProgram Program;
|
|
||||||
Program.addShader(&Shader);
|
|
||||||
|
|
||||||
if(!Program.link(messages)) {
|
|
||||||
console::error(System::None, "Failed to link shader: {} {} {}", filename, Shader.getInfoLog(), Shader.getInfoDebugLog());
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<unsigned int> SpirV;
|
|
||||||
spv::SpvBuildLogger logger;
|
|
||||||
glslang::SpvOptions spvOptions;
|
|
||||||
glslang::GlslangToSpv(*Program.getIntermediate(ShaderType), SpirV, &logger, &spvOptions);
|
|
||||||
|
|
||||||
return SpirV;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
if(argc < 2)
|
if(argc < 2) {
|
||||||
|
console::error(System::Core, "Not enough arguments!");
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
glslang::InitializeProcess();
|
shader_compiler.set_include_path(std::filesystem::current_path().string());
|
||||||
|
|
||||||
|
std::filesystem::path source_path = argv[1];
|
||||||
|
std::filesystem::path destination_path = argv[2];
|
||||||
|
|
||||||
std::ifstream t(argv[1]);
|
std::ifstream t(source_path);
|
||||||
std::stringstream buffer;
|
std::stringstream buffer;
|
||||||
buffer << t.rdbuf();
|
buffer << t.rdbuf();
|
||||||
|
|
||||||
if(std::string(argv[1]).find("nocompile") != std::string::npos) {
|
if(has_extension(source_path, "nocompile")) {
|
||||||
std::string outname = argv[2];
|
std::string outname = argv[2];
|
||||||
outname = outname.substr(0, outname.length() - 5); // remove .glsl
|
outname = outname.substr(0, outname.length() - 5); // remove .glsl
|
||||||
outname = outname.substr(0, outname.length() - 10); // remove .nocompile
|
outname = outname.substr(0, outname.length() - 10); // remove .nocompile
|
||||||
|
|
||||||
std::ofstream out(outname + ".glsl");
|
std::ofstream out(outname + ".glsl");
|
||||||
out << buffer.rdbuf();
|
out << buffer.rdbuf();
|
||||||
|
|
||||||
|
console::info(System::Core, "Successfully written {} to {}.", source_path, destination_path);
|
||||||
|
|
||||||
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
EShLanguage lang;
|
ShaderStage stage;
|
||||||
if (std::string(argv[1]).find("vert") != std::string::npos) {
|
if(has_extension(source_path, ".vert"))
|
||||||
lang = EShLangVertex;
|
stage = ShaderStage::Vertex;
|
||||||
|
else
|
||||||
|
stage = ShaderStage::Fragment;
|
||||||
|
|
||||||
|
ShaderLanguage language;
|
||||||
|
CompileOptions options;
|
||||||
|
#ifdef PLATFORM_MACOS
|
||||||
|
options.is_apple_mobile = (bool)argv[3];
|
||||||
|
|
||||||
|
language = ShaderLanguage::MSL;
|
||||||
|
destination_path.replace_extension(".msl");
|
||||||
|
#else
|
||||||
|
language = ShaderLanguage::SPIRV;
|
||||||
|
destination_path.replace_extension(".spv");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const auto compiled_source = shader_compiler.compile(ShaderLanguage::GLSL, stage, buffer.str(), language, options);
|
||||||
|
if(!compiled_source.has_value()) {
|
||||||
|
console::error(System::Core, "Error when compiling {}!", source_path);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
lang = EShLangFragment;
|
switch(language) {
|
||||||
|
case ShaderLanguage::SPIRV:
|
||||||
|
{
|
||||||
|
const auto spirv = compiled_source->as_bytecode();
|
||||||
|
|
||||||
|
std::ofstream out(destination_path, std::ios::binary); // remove .glsl
|
||||||
|
out.write((char*)spirv.data(), spirv.size() * sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ShaderLanguage::MSL:
|
||||||
|
{
|
||||||
|
std::ofstream out(destination_path); // remove .glsl
|
||||||
|
out << compiled_source->as_string();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string outname = argv[2];
|
console::info(System::Core, "Successfully written shader from {} to {}.", source_path, destination_path);
|
||||||
outname = outname.substr(0, outname.length() - 5);
|
|
||||||
|
return 0;
|
||||||
// generate msl
|
|
||||||
#ifdef PLATFORM_MACOS
|
|
||||||
bool is_ios = (bool)argv[3];
|
|
||||||
|
|
||||||
{
|
|
||||||
auto vertexSPIRV = CompileGLSL(buffer.str(), lang);
|
|
||||||
if (vertexSPIRV.size() == 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
spirv_cross::CompilerMSL msl(std::move(vertexSPIRV));
|
|
||||||
|
|
||||||
spirv_cross::CompilerMSL::Options opts;
|
|
||||||
opts.platform = is_ios ? spirv_cross::CompilerMSL::Options::Platform::iOS : spirv_cross::CompilerMSL::Options::Platform::macOS;
|
|
||||||
opts.enable_decoration_binding = true;
|
|
||||||
|
|
||||||
msl.set_msl_options(opts);
|
|
||||||
|
|
||||||
std::string s = msl.compile();
|
|
||||||
|
|
||||||
std::ofstream out(outname + ".msl"); // remove .glsl
|
|
||||||
out << s;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// generate spv
|
|
||||||
{
|
|
||||||
auto vertexSPIRV = CompileGLSL(buffer.str(), lang);
|
|
||||||
if (vertexSPIRV.size() == 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
std::ofstream out(outname + ".spv", std::ios::binary); // remove .glsl
|
|
||||||
out.write((char*)vertexSPIRV.data(), vertexSPIRV.size() * sizeof(uint32_t));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue