Cleanup shader generation
- refactor the code so that all defines are generated in the same place - generate common_type after all defines are generated - protect (with defines) structures and UBOs that are not needed, based on the variant
This commit is contained in:
committed by
Mathias Agopian
parent
de845d2885
commit
968c2c40fa
@@ -8,3 +8,4 @@ appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
|
||||
|
||||
## Release notes for next branch cut
|
||||
|
||||
- materials: prepare ES2 support [⚠️ **New Material Version**]
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
namespace filament {
|
||||
|
||||
// update this when a new version of filament wouldn't work with older materials
|
||||
static constexpr size_t MATERIAL_VERSION = 32;
|
||||
static constexpr size_t MATERIAL_VERSION = 33;
|
||||
|
||||
/**
|
||||
* Supported shading models
|
||||
|
||||
@@ -639,7 +639,7 @@ bool MaterialBuilder::runSemanticAnalysis(MaterialInfo const& info,
|
||||
using namespace backend;
|
||||
|
||||
TargetApi targetApi = semanticCodeGenParams.targetApi;
|
||||
TargetLanguage targetLanguage = semanticCodeGenParams.targetLanguage;
|
||||
TargetLanguage const targetLanguage = semanticCodeGenParams.targetLanguage;
|
||||
assertSingleTargetApi(targetApi);
|
||||
|
||||
if (mEnableFramebufferFetch) {
|
||||
@@ -648,13 +648,14 @@ bool MaterialBuilder::runSemanticAnalysis(MaterialInfo const& info,
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
ShaderModel model = semanticCodeGenParams.shaderModel;
|
||||
std::string shaderCode;
|
||||
ShaderModel const model = semanticCodeGenParams.shaderModel;
|
||||
if (mMaterialDomain == filament::MaterialDomain::COMPUTE) {
|
||||
std::string shaderCode = peek(ShaderStage::COMPUTE, semanticCodeGenParams, mProperties);
|
||||
shaderCode = peek(ShaderStage::COMPUTE, semanticCodeGenParams, mProperties);
|
||||
result = GLSLTools::analyzeComputeShader(shaderCode, model,
|
||||
targetApi, targetLanguage, info);
|
||||
} else {
|
||||
std::string shaderCode = peek(ShaderStage::VERTEX, semanticCodeGenParams, mProperties);
|
||||
shaderCode = peek(ShaderStage::VERTEX, semanticCodeGenParams, mProperties);
|
||||
result = GLSLTools::analyzeVertexShader(shaderCode, model, mMaterialDomain,
|
||||
targetApi, targetLanguage, info);
|
||||
if (result) {
|
||||
@@ -663,6 +664,9 @@ bool MaterialBuilder::runSemanticAnalysis(MaterialInfo const& info,
|
||||
targetApi, targetLanguage, mCustomSurfaceShading, info);
|
||||
}
|
||||
}
|
||||
if (!result && mPrintShaders) {
|
||||
slog.e << shaderCode << io::endl;
|
||||
}
|
||||
return result;
|
||||
#else
|
||||
return true;
|
||||
@@ -817,7 +821,7 @@ bool MaterialBuilder::generateShaders(JobSystem& jobSystem, const std::vector<Va
|
||||
shaderModel, targetApi, targetLanguage, info, v.variant, mInterpolation);
|
||||
} else if (v.stage == backend::ShaderStage::COMPUTE) {
|
||||
shader = sg.createComputeProgram(
|
||||
shaderModel, targetApi, targetLanguage, info, v.variant);
|
||||
shaderModel, targetApi, targetLanguage, info);
|
||||
}
|
||||
|
||||
#ifdef FILAMAT_LITE
|
||||
@@ -848,13 +852,16 @@ bool MaterialBuilder::generateShaders(JobSystem& jobSystem, const std::vector<Va
|
||||
config.glsl.subpassInputToColorLocation.emplace_back(0, 0);
|
||||
}
|
||||
|
||||
bool ok = postProcessor.process(shader, config, pGlsl, pSpirv, pMsl);
|
||||
bool const ok = postProcessor.process(shader, config, pGlsl, pSpirv, pMsl);
|
||||
#else
|
||||
bool ok = true;
|
||||
#endif
|
||||
if (!ok) {
|
||||
showErrorMessage(mMaterialName.c_str_safe(), v.variant, targetApi, v.stage, shader);
|
||||
cancelJobs = true;
|
||||
if (mPrintShaders) {
|
||||
slog.e << shader << io::endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -866,7 +873,7 @@ bool MaterialBuilder::generateShaders(JobSystem& jobSystem, const std::vector<Va
|
||||
|
||||
// NOTE: Everything below touches shared structures protected by a lock
|
||||
// NOTE: do not execute expensive work from here on!
|
||||
std::unique_lock<Mutex> lock(entriesLock);
|
||||
std::unique_lock<Mutex> const lock(entriesLock);
|
||||
|
||||
// below we rely on casting ShaderStage to uint8_t
|
||||
static_assert(sizeof(filament::backend::ShaderStage) == 1);
|
||||
@@ -1241,7 +1248,7 @@ std::string MaterialBuilder::peek(backend::ShaderStage stage,
|
||||
case backend::ShaderStage::COMPUTE:
|
||||
return sg.createComputeProgram(
|
||||
params.shaderModel, params.targetApi, params.targetLanguage,
|
||||
info, {});
|
||||
info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,6 @@ utils::io::sstream& CodeGenerator::generateProlog(utils::io::sstream& out, Shade
|
||||
if (material.hasExternalSamplers) {
|
||||
out << "#extension GL_OES_EGL_image_external_essl3 : require\n\n";
|
||||
}
|
||||
out << "#define TARGET_MOBILE\n";
|
||||
break;
|
||||
case ShaderModel::DESKTOP:
|
||||
if (mTargetLanguage == TargetLanguage::SPIRV ||
|
||||
@@ -85,28 +84,45 @@ utils::io::sstream& CodeGenerator::generateProlog(utils::io::sstream& out, Shade
|
||||
<< ") in;\n\n";
|
||||
}
|
||||
|
||||
if (mTargetApi == TargetApi::VULKAN) {
|
||||
out << "#define TARGET_VULKAN_ENVIRONMENT\n";
|
||||
}
|
||||
if (mTargetApi == TargetApi::METAL) {
|
||||
out << "#define TARGET_METAL_ENVIRONMENT\n";
|
||||
}
|
||||
if (mTargetApi == TargetApi::OPENGL && mShaderModel == ShaderModel::MOBILE) {
|
||||
out << "#define TARGET_GLES_ENVIRONMENT\n";
|
||||
}
|
||||
if (mTargetApi == TargetApi::OPENGL && mShaderModel == ShaderModel::DESKTOP) {
|
||||
out << "#define TARGET_GL_ENVIRONMENT\n";
|
||||
switch (mShaderModel) {
|
||||
case ShaderModel::MOBILE:
|
||||
out << "#define TARGET_MOBILE\n";
|
||||
break;
|
||||
case ShaderModel::DESKTOP:
|
||||
break;
|
||||
}
|
||||
|
||||
out << '\n';
|
||||
if (mTargetLanguage == TargetLanguage::SPIRV) {
|
||||
out << "#define FILAMENT_VULKAN_SEMANTICS\n";
|
||||
}
|
||||
if (mTargetLanguage == TargetLanguage::GLSL) {
|
||||
out << "#define FILAMENT_OPENGL_SEMANTICS\n";
|
||||
switch (mTargetApi) {
|
||||
case TargetApi::OPENGL:
|
||||
switch (mShaderModel) {
|
||||
case ShaderModel::MOBILE:
|
||||
out << "#define TARGET_GLES_ENVIRONMENT\n";
|
||||
break;
|
||||
case ShaderModel::DESKTOP:
|
||||
out << "#define TARGET_GL_ENVIRONMENT\n";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TargetApi::VULKAN:
|
||||
out << "#define TARGET_VULKAN_ENVIRONMENT\n";
|
||||
break;
|
||||
case TargetApi::METAL:
|
||||
out << "#define TARGET_METAL_ENVIRONMENT\n";
|
||||
break;
|
||||
case TargetApi::ALL:
|
||||
// invalid should never happen
|
||||
break;
|
||||
}
|
||||
|
||||
switch (mTargetLanguage) {
|
||||
case TargetLanguage::GLSL:
|
||||
out << "#define FILAMENT_OPENGL_SEMANTICS\n";
|
||||
break;
|
||||
case TargetLanguage::SPIRV:
|
||||
out << "#define FILAMENT_VULKAN_SEMANTICS\n";
|
||||
break;
|
||||
}
|
||||
|
||||
out << '\n';
|
||||
if (mTargetApi == TargetApi::VULKAN ||
|
||||
mTargetApi == TargetApi::METAL ||
|
||||
(mTargetApi == TargetApi::OPENGL && mShaderModel == ShaderModel::DESKTOP) ||
|
||||
@@ -114,7 +130,34 @@ utils::io::sstream& CodeGenerator::generateProlog(utils::io::sstream& out, Shade
|
||||
out << "#define FILAMENT_HAS_FEATURE_TEXTURE_GATHER\n";
|
||||
}
|
||||
|
||||
Precision defaultPrecision = getDefaultPrecision(stage);
|
||||
if (stage == ShaderStage::VERTEX) {
|
||||
CodeGenerator::generateDefine(out, "FLIP_UV_ATTRIBUTE", material.flipUV);
|
||||
CodeGenerator::generateDefine(out, "LEGACY_MORPHING", material.useLegacyMorphing);
|
||||
}
|
||||
|
||||
if (stage == ShaderStage::VERTEX) {
|
||||
generateDefine(out, "VARYING", "out");
|
||||
} else if (stage == ShaderStage::FRAGMENT) {
|
||||
generateDefine(out, "VARYING", "in");
|
||||
}
|
||||
|
||||
auto getShadingDefine = [](Shading shading) -> const char* {
|
||||
switch (shading) {
|
||||
case Shading::LIT: return "SHADING_MODEL_LIT";
|
||||
case Shading::UNLIT: return "SHADING_MODEL_UNLIT";
|
||||
case Shading::SUBSURFACE: return "SHADING_MODEL_SUBSURFACE";
|
||||
case Shading::CLOTH: return "SHADING_MODEL_CLOTH";
|
||||
case Shading::SPECULAR_GLOSSINESS: return "SHADING_MODEL_SPECULAR_GLOSSINESS";
|
||||
}
|
||||
};
|
||||
|
||||
CodeGenerator::generateDefine(out, getShadingDefine(material.shading), true);
|
||||
|
||||
generateQualityDefine(out, material.quality);
|
||||
|
||||
// precision qualifiers
|
||||
out << '\n';
|
||||
Precision const defaultPrecision = getDefaultPrecision(stage);
|
||||
const char* precision = getPrecisionQualifier(defaultPrecision);
|
||||
out << "precision " << precision << " float;\n";
|
||||
out << "precision " << precision << " int;\n";
|
||||
@@ -146,11 +189,6 @@ utils::io::sstream& CodeGenerator::generateProlog(utils::io::sstream& out, Shade
|
||||
out << '\n';
|
||||
out << SHADERS_COMMON_DEFINES_GLSL_DATA;
|
||||
|
||||
if (stage != ShaderStage::COMPUTE) {
|
||||
out << '\n';
|
||||
out << SHADERS_COMMON_TYPES_GLSL_DATA;
|
||||
}
|
||||
|
||||
out << "\n";
|
||||
return out;
|
||||
}
|
||||
@@ -159,25 +197,24 @@ Precision CodeGenerator::getDefaultPrecision(ShaderStage stage) const {
|
||||
switch (stage) {
|
||||
case ShaderStage::VERTEX:
|
||||
return Precision::HIGH;
|
||||
break;
|
||||
case ShaderStage::FRAGMENT:
|
||||
if (mShaderModel < ShaderModel::DESKTOP) {
|
||||
return Precision::MEDIUM;
|
||||
} else {
|
||||
return Precision::HIGH;
|
||||
switch (mShaderModel) {
|
||||
case ShaderModel::MOBILE:
|
||||
return Precision::MEDIUM;
|
||||
case ShaderModel::DESKTOP:
|
||||
return Precision::HIGH;
|
||||
}
|
||||
break;
|
||||
case ShaderStage::COMPUTE:
|
||||
return Precision::HIGH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Precision CodeGenerator::getDefaultUniformPrecision() const {
|
||||
if (mShaderModel < ShaderModel::DESKTOP) {
|
||||
return Precision::MEDIUM;
|
||||
} else {
|
||||
return Precision::HIGH;
|
||||
switch (mShaderModel) {
|
||||
case ShaderModel::MOBILE:
|
||||
return Precision::MEDIUM;
|
||||
case ShaderModel::DESKTOP:
|
||||
return Precision::HIGH;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,6 +223,23 @@ io::sstream& CodeGenerator::generateEpilog(io::sstream& out) {
|
||||
return out;
|
||||
}
|
||||
|
||||
io::sstream& CodeGenerator::generateCommonTypes(io::sstream& out, ShaderStage stage) {
|
||||
out << '\n';
|
||||
switch (stage) {
|
||||
case ShaderStage::VERTEX:
|
||||
out << '\n';
|
||||
out << SHADERS_COMMON_TYPES_GLSL_DATA;
|
||||
break;
|
||||
case ShaderStage::FRAGMENT:
|
||||
out << '\n';
|
||||
out << SHADERS_COMMON_TYPES_GLSL_DATA;
|
||||
break;
|
||||
case ShaderStage::COMPUTE:
|
||||
break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
io::sstream& CodeGenerator::generateShaderMain(io::sstream& out, ShaderStage stage) {
|
||||
switch (stage) {
|
||||
case ShaderStage::VERTEX:
|
||||
@@ -210,15 +264,15 @@ io::sstream& CodeGenerator::generatePostProcessMain(io::sstream& out, ShaderStag
|
||||
return out;
|
||||
}
|
||||
|
||||
io::sstream& CodeGenerator::generateVariable(io::sstream& out, ShaderStage type,
|
||||
io::sstream& CodeGenerator::generateVariable(io::sstream& out, ShaderStage stage,
|
||||
const CString& name, size_t index) {
|
||||
|
||||
if (!name.empty()) {
|
||||
if (type == ShaderStage::VERTEX) {
|
||||
if (stage == ShaderStage::VERTEX) {
|
||||
out << "\n#define VARIABLE_CUSTOM" << index << " " << name.c_str() << "\n";
|
||||
out << "\n#define VARIABLE_CUSTOM_AT" << index << " variable_" << name.c_str() << "\n";
|
||||
out << "LAYOUT_LOCATION(" << index << ") out vec4 variable_" << name.c_str() << ";\n";
|
||||
} else if (type == ShaderStage::FRAGMENT) {
|
||||
} else if (stage == ShaderStage::FRAGMENT) {
|
||||
out << "\nLAYOUT_LOCATION(" << index << ") in highp vec4 variable_" << name.c_str() << ";\n";
|
||||
}
|
||||
}
|
||||
@@ -231,26 +285,27 @@ io::sstream& CodeGenerator::generateShaderInputs(io::sstream& out, ShaderStage t
|
||||
const char* shading = getInterpolationQualifier(interpolation);
|
||||
out << "#define SHADING_INTERPOLATION " << shading << "\n";
|
||||
|
||||
bool hasTangents = attributes.test(VertexAttribute::TANGENTS);
|
||||
bool const hasTangents = attributes.test(VertexAttribute::TANGENTS);
|
||||
generateDefine(out, "HAS_ATTRIBUTE_TANGENTS", hasTangents);
|
||||
|
||||
bool hasColor = attributes.test(VertexAttribute::COLOR);
|
||||
bool const hasColor = attributes.test(VertexAttribute::COLOR);
|
||||
generateDefine(out, "HAS_ATTRIBUTE_COLOR", hasColor);
|
||||
|
||||
bool hasUV0 = attributes.test(VertexAttribute::UV0);
|
||||
bool const hasUV0 = attributes.test(VertexAttribute::UV0);
|
||||
generateDefine(out, "HAS_ATTRIBUTE_UV0", hasUV0);
|
||||
|
||||
bool hasUV1 = attributes.test(VertexAttribute::UV1);
|
||||
bool const hasUV1 = attributes.test(VertexAttribute::UV1);
|
||||
generateDefine(out, "HAS_ATTRIBUTE_UV1", hasUV1);
|
||||
|
||||
bool hasBoneIndices = attributes.test(VertexAttribute::BONE_INDICES);
|
||||
bool const hasBoneIndices = attributes.test(VertexAttribute::BONE_INDICES);
|
||||
generateDefine(out, "HAS_ATTRIBUTE_BONE_INDICES", hasBoneIndices);
|
||||
|
||||
bool hasBoneWeights = attributes.test(VertexAttribute::BONE_WEIGHTS);
|
||||
bool const hasBoneWeights = attributes.test(VertexAttribute::BONE_WEIGHTS);
|
||||
generateDefine(out, "HAS_ATTRIBUTE_BONE_WEIGHTS", hasBoneWeights);
|
||||
|
||||
for (int i = 0; i < MAX_CUSTOM_ATTRIBUTES; i++) {
|
||||
bool hasCustom = attributes.test(VertexAttribute::CUSTOM0 + i);
|
||||
UTILS_NOUNROLL
|
||||
for (size_t i = 0; i < MAX_CUSTOM_ATTRIBUTES; i++) {
|
||||
bool const hasCustom = attributes.test(VertexAttribute::CUSTOM0 + i);
|
||||
if (hasCustom) {
|
||||
generateIndexedDefine(out, "HAS_ATTRIBUTE_CUSTOM", i, 1);
|
||||
}
|
||||
@@ -286,10 +341,6 @@ io::sstream& CodeGenerator::generateShaderInputs(io::sstream& out, ShaderStage t
|
||||
}
|
||||
|
||||
out << SHADERS_ATTRIBUTES_VS_DATA;
|
||||
|
||||
generateDefine(out, "VARYING", "out");
|
||||
} else if (type == ShaderStage::FRAGMENT) {
|
||||
generateDefine(out, "VARYING", "in");
|
||||
}
|
||||
out << SHADERS_VARYINGS_GLSL_DATA;
|
||||
return out;
|
||||
@@ -393,8 +444,8 @@ io::sstream& CodeGenerator::generateBufferInterfaceBlock(io::sstream& out, Shade
|
||||
blockName.front() = char(std::toupper((unsigned char)blockName.front()));
|
||||
instanceName.front() = char(std::tolower((unsigned char)instanceName.front()));
|
||||
|
||||
Precision uniformPrecision = getDefaultUniformPrecision();
|
||||
Precision defaultPrecision = getDefaultPrecision(stage);
|
||||
Precision const uniformPrecision = getDefaultUniformPrecision();
|
||||
Precision const defaultPrecision = getDefaultPrecision(stage);
|
||||
|
||||
auto metalBufferBindingOffset = 0;
|
||||
switch (uib.getTarget()) {
|
||||
@@ -450,7 +501,7 @@ io::sstream& CodeGenerator::generateBufferInterfaceBlock(io::sstream& out, Shade
|
||||
if (uib.getTarget() == BufferInterfaceBlock::Target::SSBO) {
|
||||
uint8_t qualifiers = uib.getQualifier();
|
||||
while (qualifiers) {
|
||||
uint8_t mask = 1u << utils::ctz(unsigned(qualifiers));
|
||||
uint8_t const mask = 1u << utils::ctz(unsigned(qualifiers));
|
||||
switch (BufferInterfaceBlock::Qualifier(qualifiers & mask)) {
|
||||
case BufferInterfaceBlock::Qualifier::COHERENT: out << "coherent "; break;
|
||||
case BufferInterfaceBlock::Qualifier::WRITEONLY: out << "writeonly "; break;
|
||||
@@ -575,7 +626,7 @@ void CodeGenerator::fixupExternalSamplers(
|
||||
for (auto const& info : infos) {
|
||||
if (info.type == SamplerType::SAMPLER_EXTERNAL) {
|
||||
auto name = std::string("sampler2D ") + info.uniformName.c_str();
|
||||
size_t index = shader.find(name);
|
||||
size_t const index = shader.find(name);
|
||||
|
||||
if (index != std::string::npos) {
|
||||
hasExternalSampler = true;
|
||||
@@ -634,12 +685,12 @@ struct SpecializationConstantFormatter {
|
||||
utils::io::sstream& CodeGenerator::generateSpecializationConstant(utils::io::sstream& out,
|
||||
const char* name, uint32_t id, std::variant<int, float, bool> value) const {
|
||||
|
||||
std::string constantString = std::visit(SpecializationConstantFormatter(), value);
|
||||
std::string const constantString = std::visit(SpecializationConstantFormatter(), value);
|
||||
|
||||
static const char* types[] = { "int", "float", "bool" };
|
||||
if (mTargetLanguage == MaterialBuilderBase::TargetLanguage::SPIRV) {
|
||||
out << "layout (constant_id = " << id << ") const "
|
||||
<< types[value.index()] << " " << name << " = " << constantString << ";\n\n";
|
||||
<< types[value.index()] << " " << name << " = " << constantString << ";\n";
|
||||
} else {
|
||||
out << "#ifndef SPIRV_CROSS_CONSTANT_ID_" << id << '\n'
|
||||
<< "#define SPIRV_CROSS_CONSTANT_ID_" << id << " " << constantString << '\n'
|
||||
@@ -845,8 +896,7 @@ io::sstream& CodeGenerator::generateShaderUnlit(io::sstream& out, ShaderStage ty
|
||||
return out;
|
||||
}
|
||||
|
||||
io::sstream& CodeGenerator::generateShaderReflections(utils::io::sstream& out, ShaderStage type,
|
||||
filament::Variant variant) {
|
||||
io::sstream& CodeGenerator::generateShaderReflections(utils::io::sstream& out, ShaderStage type) {
|
||||
if (type == ShaderStage::VERTEX) {
|
||||
} else if (type == ShaderStage::FRAGMENT) {
|
||||
out << SHADERS_COMMON_LIGHTING_FS_DATA;
|
||||
|
||||
@@ -77,6 +77,8 @@ public:
|
||||
|
||||
static utils::io::sstream& generateEpilog(utils::io::sstream& out);
|
||||
|
||||
static utils::io::sstream& generateCommonTypes(utils::io::sstream& out, ShaderStage stage);
|
||||
|
||||
// generate common functions for the given shader
|
||||
static utils::io::sstream& generateCommon(utils::io::sstream& out, ShaderStage stage);
|
||||
static utils::io::sstream& generatePostProcessCommon(utils::io::sstream& out, ShaderStage type);
|
||||
@@ -97,11 +99,10 @@ public:
|
||||
filament::Variant variant, bool hasShadowMultiplier);
|
||||
|
||||
// generate the shader's code for the screen-space reflections
|
||||
static utils::io::sstream& generateShaderReflections(utils::io::sstream& out, ShaderStage type,
|
||||
filament::Variant variant);
|
||||
static utils::io::sstream& generateShaderReflections(utils::io::sstream& out, ShaderStage type);
|
||||
|
||||
// generate declarations for custom interpolants
|
||||
static utils::io::sstream& generateVariable(utils::io::sstream& out, ShaderStage type,
|
||||
static utils::io::sstream& generateVariable(utils::io::sstream& out, ShaderStage stage,
|
||||
const utils::CString& name, size_t index);
|
||||
|
||||
// generate declarations for non-custom "in" variables
|
||||
|
||||
@@ -36,36 +36,179 @@ using namespace filament;
|
||||
using namespace filament::backend;
|
||||
using namespace utils;
|
||||
|
||||
static const char* getShadingDefine(Shading shading) noexcept {
|
||||
switch (shading) {
|
||||
case Shading::LIT: return "SHADING_MODEL_LIT";
|
||||
case Shading::UNLIT: return "SHADING_MODEL_UNLIT";
|
||||
case Shading::SUBSURFACE: return "SHADING_MODEL_SUBSURFACE";
|
||||
case Shading::CLOTH: return "SHADING_MODEL_CLOTH";
|
||||
case Shading::SPECULAR_GLOSSINESS: return "SHADING_MODEL_SPECULAR_GLOSSINESS";
|
||||
void ShaderGenerator::generateSurfaceMaterialVariantDefines(utils::io::sstream& out,
|
||||
ShaderStage stage,
|
||||
MaterialInfo const& material, filament::Variant variant) noexcept {
|
||||
|
||||
bool const litVariants = material.isLit || material.hasShadowMultiplier;
|
||||
|
||||
CodeGenerator::generateDefine(out, "VARIANT_HAS_DIRECTIONAL_LIGHTING",
|
||||
litVariants && variant.hasDirectionalLighting());
|
||||
CodeGenerator::generateDefine(out, "VARIANT_HAS_DYNAMIC_LIGHTING",
|
||||
litVariants && variant.hasDynamicLighting());
|
||||
CodeGenerator::generateDefine(out, "VARIANT_HAS_SHADOWING",
|
||||
litVariants && filament::Variant::isShadowReceiverVariant(variant));
|
||||
CodeGenerator::generateDefine(out, "VARIANT_HAS_VSM",
|
||||
filament::Variant::isVSMVariant(variant));
|
||||
|
||||
switch (stage) {
|
||||
case ShaderStage::VERTEX:
|
||||
CodeGenerator::generateDefine(out, "VARIANT_HAS_SKINNING_OR_MORPHING",
|
||||
variant.hasSkinningOrMorphing());
|
||||
break;
|
||||
case ShaderStage::FRAGMENT:
|
||||
CodeGenerator::generateDefine(out, "VARIANT_HAS_FOG",
|
||||
filament::Variant::isFogVariant(variant));
|
||||
CodeGenerator::generateDefine(out, "VARIANT_HAS_PICKING",
|
||||
filament::Variant::isPickingVariant(variant));
|
||||
CodeGenerator::generateDefine(out, "VARIANT_HAS_SSR",
|
||||
filament::Variant::isSSRVariant(variant));
|
||||
break;
|
||||
case ShaderStage::COMPUTE:
|
||||
break;
|
||||
}
|
||||
|
||||
out << '\n';
|
||||
CodeGenerator::generateDefine(out, "MATERIAL_HAS_SHADOW_MULTIPLIER",
|
||||
material.hasShadowMultiplier);
|
||||
|
||||
CodeGenerator::generateDefine(out, "MATERIAL_HAS_INSTANCES", material.instanced);
|
||||
|
||||
CodeGenerator::generateDefine(out, "MATERIAL_HAS_VERTEX_DOMAIN_DEVICE_JITTERED",
|
||||
material.vertexDomainDeviceJittered);
|
||||
|
||||
CodeGenerator::generateDefine(out, "MATERIAL_HAS_TRANSPARENT_SHADOW",
|
||||
material.hasTransparentShadow);
|
||||
|
||||
if (stage == ShaderStage::FRAGMENT) {
|
||||
// We only support both screen-space refractions and reflections at the same time.
|
||||
// And the MATERIAL_HAS_REFRACTION/MATERIAL_HAS_REFLECTIONS defines signify if
|
||||
// refraction/reflections are supported by the material.
|
||||
|
||||
CodeGenerator::generateDefine(out, "MATERIAL_HAS_REFRACTION",
|
||||
material.refractionMode != RefractionMode::NONE);
|
||||
if (material.refractionMode != RefractionMode::NONE) {
|
||||
CodeGenerator::generateDefine(out, "REFRACTION_MODE_CUBEMAP",
|
||||
uint32_t(RefractionMode::CUBEMAP));
|
||||
CodeGenerator::generateDefine(out, "REFRACTION_MODE_SCREEN_SPACE",
|
||||
uint32_t(RefractionMode::SCREEN_SPACE));
|
||||
switch (material.refractionMode) {
|
||||
case RefractionMode::NONE:
|
||||
// can't be here
|
||||
break;
|
||||
case RefractionMode::CUBEMAP:
|
||||
CodeGenerator::generateDefine(out, "REFRACTION_MODE",
|
||||
"REFRACTION_MODE_CUBEMAP");
|
||||
break;
|
||||
case RefractionMode::SCREEN_SPACE:
|
||||
CodeGenerator::generateDefine(out, "REFRACTION_MODE",
|
||||
"REFRACTION_MODE_SCREEN_SPACE");
|
||||
break;
|
||||
}
|
||||
CodeGenerator::generateDefine(out, "REFRACTION_TYPE_SOLID",
|
||||
uint32_t(RefractionType::SOLID));
|
||||
CodeGenerator::generateDefine(out, "REFRACTION_TYPE_THIN",
|
||||
uint32_t(RefractionType::THIN));
|
||||
switch (material.refractionType) {
|
||||
case RefractionType::SOLID:
|
||||
CodeGenerator::generateDefine(out, "REFRACTION_TYPE", "REFRACTION_TYPE_SOLID");
|
||||
break;
|
||||
case RefractionType::THIN:
|
||||
CodeGenerator::generateDefine(out, "REFRACTION_TYPE", "REFRACTION_TYPE_THIN");
|
||||
break;
|
||||
}
|
||||
}
|
||||
CodeGenerator::generateDefine(out, "MATERIAL_HAS_REFLECTIONS",
|
||||
material.reflectionMode == ReflectionMode::SCREEN_SPACE);
|
||||
|
||||
CodeGenerator::generateDefine(out, "MATERIAL_HAS_DOUBLE_SIDED_CAPABILITY",
|
||||
material.hasDoubleSidedCapability);
|
||||
|
||||
CodeGenerator::generateDefine(out, "MATERIAL_HAS_CUSTOM_SURFACE_SHADING",
|
||||
material.hasCustomSurfaceShading);
|
||||
|
||||
out << '\n';
|
||||
switch (material.blendingMode) {
|
||||
case BlendingMode::OPAQUE:
|
||||
CodeGenerator::generateDefine(out, "BLEND_MODE_OPAQUE", true);
|
||||
break;
|
||||
case BlendingMode::TRANSPARENT:
|
||||
CodeGenerator::generateDefine(out, "BLEND_MODE_TRANSPARENT", true);
|
||||
break;
|
||||
case BlendingMode::ADD:
|
||||
CodeGenerator::generateDefine(out, "BLEND_MODE_ADD", true);
|
||||
break;
|
||||
case BlendingMode::MASKED:
|
||||
CodeGenerator::generateDefine(out, "BLEND_MODE_MASKED", true);
|
||||
break;
|
||||
case BlendingMode::FADE:
|
||||
// Fade is a special case of transparent
|
||||
CodeGenerator::generateDefine(out, "BLEND_MODE_TRANSPARENT", true);
|
||||
CodeGenerator::generateDefine(out, "BLEND_MODE_FADE", true);
|
||||
break;
|
||||
case BlendingMode::MULTIPLY:
|
||||
CodeGenerator::generateDefine(out, "BLEND_MODE_MULTIPLY", true);
|
||||
break;
|
||||
case BlendingMode::SCREEN:
|
||||
CodeGenerator::generateDefine(out, "BLEND_MODE_SCREEN", true);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (material.postLightingBlendingMode) {
|
||||
case BlendingMode::OPAQUE:
|
||||
CodeGenerator::generateDefine(out, "POST_LIGHTING_BLEND_MODE_OPAQUE", true);
|
||||
break;
|
||||
case BlendingMode::TRANSPARENT:
|
||||
CodeGenerator::generateDefine(out, "POST_LIGHTING_BLEND_MODE_TRANSPARENT", true);
|
||||
break;
|
||||
case BlendingMode::ADD:
|
||||
CodeGenerator::generateDefine(out, "POST_LIGHTING_BLEND_MODE_ADD", true);
|
||||
break;
|
||||
case BlendingMode::MULTIPLY:
|
||||
CodeGenerator::generateDefine(out, "POST_LIGHTING_BLEND_MODE_MULTIPLY", true);
|
||||
break;
|
||||
case BlendingMode::SCREEN:
|
||||
CodeGenerator::generateDefine(out, "POST_LIGHTING_BLEND_MODE_SCREEN", true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
out << '\n';
|
||||
CodeGenerator::generateDefine(out, "GEOMETRIC_SPECULAR_AA",
|
||||
material.specularAntiAliasing && material.isLit);
|
||||
|
||||
CodeGenerator::generateDefine(out, "CLEAR_COAT_IOR_CHANGE",
|
||||
material.clearCoatIorChange);
|
||||
}
|
||||
}
|
||||
|
||||
static void generateMaterialDefines(io::sstream& os, MaterialBuilder::PropertyList const properties,
|
||||
void ShaderGenerator::generateSurfaceMaterialVariantProperties(io::sstream& out,
|
||||
MaterialBuilder::PropertyList const properties,
|
||||
const MaterialBuilder::PreprocessorDefineList& defines) noexcept {
|
||||
|
||||
UTILS_NOUNROLL
|
||||
for (size_t i = 0; i < MaterialBuilder::MATERIAL_PROPERTIES_COUNT; i++) {
|
||||
CodeGenerator::generateMaterialProperty(os, static_cast<MaterialBuilder::Property>(i), properties[i]);
|
||||
CodeGenerator::generateMaterialProperty(out,
|
||||
static_cast<MaterialBuilder::Property>(i), properties[i]);
|
||||
}
|
||||
|
||||
// synthetic defines
|
||||
bool hasTBN =
|
||||
bool const hasTBN =
|
||||
properties[static_cast<int>(MaterialBuilder::Property::ANISOTROPY)] ||
|
||||
properties[static_cast<int>(MaterialBuilder::Property::NORMAL)] ||
|
||||
properties[static_cast<int>(MaterialBuilder::Property::BENT_NORMAL)] ||
|
||||
properties[static_cast<int>(MaterialBuilder::Property::CLEAR_COAT_NORMAL)];
|
||||
CodeGenerator::generateDefine(os, "MATERIAL_NEEDS_TBN", hasTBN);
|
||||
|
||||
CodeGenerator::generateDefine(out, "MATERIAL_NEEDS_TBN", hasTBN);
|
||||
|
||||
// Additional, user-provided defines.
|
||||
for (const auto& define : defines) {
|
||||
CodeGenerator::generateDefine(os, define.name.c_str(), define.value.c_str());
|
||||
CodeGenerator::generateDefine(out, define.name.c_str(), define.value.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
static void generateVertexDomain(io::sstream& vs, VertexDomain domain) noexcept {
|
||||
void ShaderGenerator::generateVertexDomainDefines(io::sstream& vs, VertexDomain domain) noexcept {
|
||||
switch (domain) {
|
||||
case VertexDomain::OBJECT:
|
||||
CodeGenerator::generateDefine(vs, "VERTEX_DOMAIN_OBJECT", true);
|
||||
@@ -82,37 +225,30 @@ static void generateVertexDomain(io::sstream& vs, VertexDomain domain) noexcept
|
||||
}
|
||||
}
|
||||
|
||||
static void generatePostProcessMaterialVariantDefines(io::sstream& shader,
|
||||
void ShaderGenerator::generatePostProcessMaterialVariantDefines(io::sstream& out,
|
||||
PostProcessVariant variant) noexcept {
|
||||
switch (variant) {
|
||||
case PostProcessVariant::OPAQUE:
|
||||
CodeGenerator::generateDefine(shader, "POST_PROCESS_OPAQUE", 1u);
|
||||
CodeGenerator::generateDefine(out, "POST_PROCESS_OPAQUE", 1u);
|
||||
break;
|
||||
case PostProcessVariant::TRANSLUCENT:
|
||||
CodeGenerator::generateDefine(shader, "POST_PROCESS_OPAQUE", 0u);
|
||||
CodeGenerator::generateDefine(out, "POST_PROCESS_OPAQUE", 0u);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t countLines(const char* s) noexcept {
|
||||
size_t lines = 0;
|
||||
size_t i = 0;
|
||||
while (s[i] != 0) {
|
||||
if (s[i++] == '\n') lines++;
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
static size_t countLines(const CString& s) noexcept {
|
||||
size_t lines = 0;
|
||||
for (char i : s) {
|
||||
if (i == '\n') lines++;
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
static void appendShader(io::sstream& ss,
|
||||
void ShaderGenerator::appendShader(io::sstream& ss,
|
||||
const CString& shader, size_t lineOffset) noexcept {
|
||||
|
||||
auto countLines = [](const char* s) -> size_t {
|
||||
size_t lines = 0;
|
||||
size_t i = 0;
|
||||
while (s[i]) {
|
||||
if (s[i++] == '\n') lines++;
|
||||
}
|
||||
return lines;
|
||||
};
|
||||
|
||||
if (!shader.empty()) {
|
||||
size_t lines = countLines(ss.c_str());
|
||||
ss << "#line " << lineOffset + 1 << '\n';
|
||||
@@ -122,16 +258,16 @@ static void appendShader(io::sstream& ss,
|
||||
lines++;
|
||||
}
|
||||
// + 2 to account for the #line directives we just added
|
||||
ss << "#line " << lines + countLines(shader) + 2 << "\n";
|
||||
ss << "#line " << lines + countLines(shader.c_str()) + 2 << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
static void generateUserSpecConstants(
|
||||
const CodeGenerator& cg, io::sstream& fs, MaterialBuilder::ConstantList constants) {
|
||||
void ShaderGenerator::generateUserSpecConstants(
|
||||
const CodeGenerator& cg, io::sstream& fs, MaterialBuilder::ConstantList const& constants) {
|
||||
// Constants 0 to CONFIG_MAX_RESERVED_SPEC_CONSTANTS - 1 are reserved by Filament.
|
||||
size_t index = CONFIG_MAX_RESERVED_SPEC_CONSTANTS;
|
||||
for (const auto& constant : constants) {
|
||||
std::string fullName = std::string("materialConstants_") + constant.name.c_str();
|
||||
std::string const fullName = std::string("materialConstants_") + constant.name.c_str();
|
||||
switch (constant.type) {
|
||||
case ConstantType::INT:
|
||||
cg.generateSpecializationConstant(
|
||||
@@ -149,6 +285,7 @@ static void generateUserSpecConstants(
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
ShaderGenerator::ShaderGenerator(
|
||||
MaterialBuilder::PropertyList const& properties,
|
||||
@@ -215,6 +352,7 @@ std::string ShaderGenerator::createVertexProgram(ShaderModel shaderModel,
|
||||
MaterialInfo const& material, const filament::Variant variant, Interpolation interpolation,
|
||||
VertexDomain vertexDomain) const noexcept {
|
||||
|
||||
assert_invariant(filament::Variant::isValid(variant));
|
||||
assert_invariant(mMaterialDomain != MaterialBuilder::MaterialDomain::COMPUTE);
|
||||
|
||||
if (mMaterialDomain == MaterialBuilder::MaterialDomain::POST_PROCESS) {
|
||||
@@ -225,22 +363,11 @@ std::string ShaderGenerator::createVertexProgram(ShaderModel shaderModel,
|
||||
io::sstream vs;
|
||||
|
||||
const CodeGenerator cg(shaderModel, targetApi, targetLanguage, material.featureLevel);
|
||||
const bool lit = material.isLit;
|
||||
|
||||
cg.generateProlog(vs, ShaderStage::VERTEX, material);
|
||||
|
||||
generateUserSpecConstants(cg, vs, mConstants);
|
||||
|
||||
cg.generateQualityDefine(vs, material.quality);
|
||||
|
||||
CodeGenerator::generateDefine(vs, "FLIP_UV_ATTRIBUTE", material.flipUV);
|
||||
|
||||
CodeGenerator::generateDefine(vs, "LEGACY_MORPHING", material.useLegacyMorphing);
|
||||
|
||||
const bool litVariants = lit || material.hasShadowMultiplier;
|
||||
|
||||
assert_invariant(filament::Variant::isValid(variant));
|
||||
|
||||
// note: even if the user vertex shader is empty, we can't use the "optimized" version if
|
||||
// we're in masked mode because fragment shader needs the color varyings
|
||||
const bool useOptimizedDepthVertexShader =
|
||||
@@ -258,31 +385,9 @@ std::string ShaderGenerator::createVertexProgram(ShaderModel shaderModel,
|
||||
CodeGenerator::generateDefine(vs, "USE_OPTIMIZED_DEPTH_VERTEX_SHADER",
|
||||
useOptimizedDepthVertexShader);
|
||||
|
||||
// material defines
|
||||
CodeGenerator::generateDefine(vs, "MATERIAL_HAS_SHADOW_MULTIPLIER",
|
||||
material.hasShadowMultiplier);
|
||||
generateSurfaceMaterialVariantDefines(vs, ShaderStage::VERTEX, material, variant);
|
||||
|
||||
CodeGenerator::generateDefine(vs, "MATERIAL_HAS_INSTANCES", material.instanced);
|
||||
|
||||
CodeGenerator::generateDefine(vs, "MATERIAL_HAS_VERTEX_DOMAIN_DEVICE_JITTERED",
|
||||
material.vertexDomainDeviceJittered);
|
||||
|
||||
CodeGenerator::generateDefine(vs, "MATERIAL_HAS_TRANSPARENT_SHADOW",
|
||||
material.hasTransparentShadow);
|
||||
|
||||
CodeGenerator::generateDefine(vs, "VARIANT_HAS_DIRECTIONAL_LIGHTING",
|
||||
litVariants && variant.hasDirectionalLighting());
|
||||
CodeGenerator::generateDefine(vs, "VARIANT_HAS_DYNAMIC_LIGHTING",
|
||||
litVariants && variant.hasDynamicLighting());
|
||||
CodeGenerator::generateDefine(vs, "VARIANT_HAS_SHADOWING",
|
||||
litVariants && filament::Variant::isShadowReceiverVariant(variant));
|
||||
CodeGenerator::generateDefine(vs, "VARIANT_HAS_SKINNING_OR_MORPHING",
|
||||
variant.hasSkinningOrMorphing());
|
||||
CodeGenerator::generateDefine(vs, "VARIANT_HAS_VSM",
|
||||
filament::Variant::isVSMVariant(variant));
|
||||
|
||||
CodeGenerator::generateDefine(vs, getShadingDefine(material.shading), true);
|
||||
generateMaterialDefines(vs, mProperties, mDefines);
|
||||
generateSurfaceMaterialVariantProperties(vs, mProperties, mDefines);
|
||||
|
||||
AttributeBitset attributes = material.requiredAttributes;
|
||||
if (variant.hasSkinningOrMorphing()) {
|
||||
@@ -301,6 +406,8 @@ std::string ShaderGenerator::createVertexProgram(ShaderModel shaderModel,
|
||||
}
|
||||
CodeGenerator::generateShaderInputs(vs, ShaderStage::VERTEX, attributes, interpolation);
|
||||
|
||||
CodeGenerator::generateCommonTypes(vs, ShaderStage::VERTEX);
|
||||
|
||||
// custom material variables
|
||||
size_t variableIndex = 0;
|
||||
for (const auto& variable : mVariables) {
|
||||
@@ -308,31 +415,40 @@ std::string ShaderGenerator::createVertexProgram(ShaderModel shaderModel,
|
||||
}
|
||||
|
||||
// materials defines
|
||||
generateVertexDomain(vs, vertexDomain);
|
||||
generateVertexDomainDefines(vs, vertexDomain);
|
||||
|
||||
// uniforms
|
||||
cg.generateUniforms(vs, ShaderStage::VERTEX,
|
||||
UniformBindingPoints::PER_VIEW, UibGenerator::getPerViewUib());
|
||||
|
||||
cg.generateUniforms(vs, ShaderStage::VERTEX,
|
||||
UniformBindingPoints::PER_RENDERABLE, UibGenerator::getPerRenderableUib());
|
||||
|
||||
const bool litVariants = material.isLit || material.hasShadowMultiplier;
|
||||
if (litVariants && filament::Variant::isShadowReceiverVariant(variant)) {
|
||||
cg.generateUniforms(vs, ShaderStage::FRAGMENT,
|
||||
UniformBindingPoints::SHADOW, UibGenerator::getShadowUib());
|
||||
}
|
||||
|
||||
if (variant.hasSkinningOrMorphing()) {
|
||||
cg.generateUniforms(vs, ShaderStage::VERTEX,
|
||||
UniformBindingPoints::PER_RENDERABLE_BONES,
|
||||
UibGenerator::getPerRenderableBonesUib());
|
||||
|
||||
cg.generateUniforms(vs, ShaderStage::VERTEX,
|
||||
UniformBindingPoints::PER_RENDERABLE_MORPHING,
|
||||
UibGenerator::getPerRenderableMorphingUib());
|
||||
|
||||
cg.generateSamplers(vs, SamplerBindingPoints::PER_RENDERABLE_MORPHING,
|
||||
material.samplerBindings.getBlockOffset(SamplerBindingPoints::PER_RENDERABLE_MORPHING),
|
||||
SibGenerator::getPerRenderPrimitiveMorphingSib(variant));
|
||||
}
|
||||
|
||||
cg.generateUniforms(vs, ShaderStage::VERTEX,
|
||||
UniformBindingPoints::PER_MATERIAL_INSTANCE, material.uib);
|
||||
|
||||
CodeGenerator::generateSeparator(vs);
|
||||
|
||||
// TODO: should we generate per-view SIB in the vertex shader?
|
||||
cg.generateSamplers(vs, SamplerBindingPoints::PER_MATERIAL_INSTANCE,
|
||||
material.samplerBindings.getBlockOffset(SamplerBindingPoints::PER_MATERIAL_INSTANCE),
|
||||
@@ -357,6 +473,7 @@ std::string ShaderGenerator::createFragmentProgram(ShaderModel shaderModel,
|
||||
MaterialInfo const& material, const filament::Variant variant,
|
||||
Interpolation interpolation) const noexcept {
|
||||
|
||||
assert_invariant(filament::Variant::isValid(variant));
|
||||
assert_invariant(mMaterialDomain != MaterialBuilder::MaterialDomain::COMPUTE);
|
||||
|
||||
if (mMaterialDomain == MaterialBuilder::MaterialDomain::POST_PROCESS) {
|
||||
@@ -365,146 +482,30 @@ std::string ShaderGenerator::createFragmentProgram(ShaderModel shaderModel,
|
||||
}
|
||||
|
||||
const CodeGenerator cg(shaderModel, targetApi, targetLanguage, material.featureLevel);
|
||||
const bool lit = material.isLit;
|
||||
|
||||
io::sstream fs;
|
||||
cg.generateProlog(fs, ShaderStage::FRAGMENT, material);
|
||||
|
||||
generateUserSpecConstants(cg, fs, mConstants);
|
||||
|
||||
cg.generateQualityDefine(fs, material.quality);
|
||||
|
||||
CodeGenerator::generateDefine(fs, "GEOMETRIC_SPECULAR_AA", material.specularAntiAliasing && lit);
|
||||
|
||||
CodeGenerator::generateDefine(fs, "CLEAR_COAT_IOR_CHANGE", material.clearCoatIorChange);
|
||||
generateSurfaceMaterialVariantDefines(fs, ShaderStage::FRAGMENT, material, variant);
|
||||
|
||||
auto defaultSpecularAO = shaderModel == ShaderModel::MOBILE ?
|
||||
SpecularAmbientOcclusion::NONE : SpecularAmbientOcclusion::SIMPLE;
|
||||
SpecularAmbientOcclusion::NONE : SpecularAmbientOcclusion::SIMPLE;
|
||||
auto specularAO = material.specularAOSet ? material.specularAO : defaultSpecularAO;
|
||||
CodeGenerator::generateDefine(fs, "SPECULAR_AMBIENT_OCCLUSION", uint32_t(specularAO));
|
||||
|
||||
// We only support both screen-space refractions and reflections at the same time.
|
||||
// And the MATERIAL_HAS_REFRACTION/MATERIAL_HAS_REFLECTIONS defines signify if refraction/reflections are supported by
|
||||
// the material.
|
||||
|
||||
CodeGenerator::generateDefine(fs, "MATERIAL_HAS_REFRACTION", material.refractionMode != RefractionMode::NONE);
|
||||
if (material.refractionMode != RefractionMode::NONE) {
|
||||
CodeGenerator::generateDefine(fs, "REFRACTION_MODE_CUBEMAP", uint32_t(RefractionMode::CUBEMAP));
|
||||
CodeGenerator::generateDefine(fs, "REFRACTION_MODE_SCREEN_SPACE", uint32_t(RefractionMode::SCREEN_SPACE));
|
||||
switch (material.refractionMode) {
|
||||
case RefractionMode::NONE:
|
||||
// can't be here
|
||||
break;
|
||||
case RefractionMode::CUBEMAP:
|
||||
CodeGenerator::generateDefine(fs, "REFRACTION_MODE", "REFRACTION_MODE_CUBEMAP");
|
||||
break;
|
||||
case RefractionMode::SCREEN_SPACE:
|
||||
CodeGenerator::generateDefine(fs, "REFRACTION_MODE", "REFRACTION_MODE_SCREEN_SPACE");
|
||||
break;
|
||||
}
|
||||
CodeGenerator::generateDefine(fs, "REFRACTION_TYPE_SOLID", uint32_t(RefractionType::SOLID));
|
||||
CodeGenerator::generateDefine(fs, "REFRACTION_TYPE_THIN", uint32_t(RefractionType::THIN));
|
||||
switch (material.refractionType) {
|
||||
case RefractionType::SOLID:
|
||||
CodeGenerator::generateDefine(fs, "REFRACTION_TYPE", "REFRACTION_TYPE_SOLID");
|
||||
break;
|
||||
case RefractionType::THIN:
|
||||
CodeGenerator::generateDefine(fs, "REFRACTION_TYPE", "REFRACTION_TYPE_THIN");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CodeGenerator::generateDefine(fs, "MATERIAL_HAS_REFLECTIONS",
|
||||
material.reflectionMode == ReflectionMode::SCREEN_SPACE);
|
||||
|
||||
bool multiBounceAO = material.multiBounceAOSet ?
|
||||
material.multiBounceAO : shaderModel == ShaderModel::DESKTOP;
|
||||
bool const multiBounceAO = material.multiBounceAOSet ?
|
||||
material.multiBounceAO : shaderModel == ShaderModel::DESKTOP;
|
||||
CodeGenerator::generateDefine(fs, "MULTI_BOUNCE_AMBIENT_OCCLUSION", multiBounceAO ? 1u : 0u);
|
||||
|
||||
assert_invariant(filament::Variant::isValid(variant));
|
||||
generateSurfaceMaterialVariantProperties(fs, mProperties, mDefines);
|
||||
|
||||
// lighting variants
|
||||
bool litVariants = lit || material.hasShadowMultiplier;
|
||||
|
||||
// material defines
|
||||
CodeGenerator::generateDefine(fs, "MATERIAL_HAS_SHADOW_MULTIPLIER",
|
||||
material.hasShadowMultiplier);
|
||||
CodeGenerator::generateShaderInputs(fs, ShaderStage::FRAGMENT,
|
||||
material.requiredAttributes, interpolation);
|
||||
|
||||
CodeGenerator::generateDefine(fs, "MATERIAL_HAS_INSTANCES", material.instanced);
|
||||
|
||||
CodeGenerator::generateDefine(fs, "MATERIAL_HAS_VERTEX_DOMAIN_DEVICE_JITTERED",
|
||||
material.vertexDomainDeviceJittered);
|
||||
|
||||
CodeGenerator::generateDefine(fs, "MATERIAL_HAS_TRANSPARENT_SHADOW",
|
||||
material.hasTransparentShadow);
|
||||
|
||||
CodeGenerator::generateDefine(fs, "VARIANT_HAS_DIRECTIONAL_LIGHTING",
|
||||
litVariants && variant.hasDirectionalLighting());
|
||||
CodeGenerator::generateDefine(fs, "VARIANT_HAS_DYNAMIC_LIGHTING",
|
||||
litVariants && variant.hasDynamicLighting());
|
||||
CodeGenerator::generateDefine(fs, "VARIANT_HAS_SHADOWING",
|
||||
litVariants && filament::Variant::isShadowReceiverVariant(variant));
|
||||
CodeGenerator::generateDefine(fs, "VARIANT_HAS_FOG",
|
||||
filament::Variant::isFogVariant(variant));
|
||||
CodeGenerator::generateDefine(fs, "VARIANT_HAS_PICKING",
|
||||
filament::Variant::isPickingVariant(variant));
|
||||
CodeGenerator::generateDefine(fs, "VARIANT_HAS_VSM",
|
||||
filament::Variant::isVSMVariant(variant));
|
||||
CodeGenerator::generateDefine(fs, "VARIANT_HAS_SSR",
|
||||
filament::Variant::isSSRVariant(variant));
|
||||
|
||||
CodeGenerator::generateDefine(fs, "MATERIAL_HAS_DOUBLE_SIDED_CAPABILITY",
|
||||
material.hasDoubleSidedCapability);
|
||||
switch (material.blendingMode) {
|
||||
case BlendingMode::OPAQUE:
|
||||
CodeGenerator::generateDefine(fs, "BLEND_MODE_OPAQUE", true);
|
||||
break;
|
||||
case BlendingMode::TRANSPARENT:
|
||||
CodeGenerator::generateDefine(fs, "BLEND_MODE_TRANSPARENT", true);
|
||||
break;
|
||||
case BlendingMode::ADD:
|
||||
CodeGenerator::generateDefine(fs, "BLEND_MODE_ADD", true);
|
||||
break;
|
||||
case BlendingMode::MASKED:
|
||||
CodeGenerator::generateDefine(fs, "BLEND_MODE_MASKED", true);
|
||||
break;
|
||||
case BlendingMode::FADE:
|
||||
// Fade is a special case of transparent
|
||||
CodeGenerator::generateDefine(fs, "BLEND_MODE_TRANSPARENT", true);
|
||||
CodeGenerator::generateDefine(fs, "BLEND_MODE_FADE", true);
|
||||
break;
|
||||
case BlendingMode::MULTIPLY:
|
||||
CodeGenerator::generateDefine(fs, "BLEND_MODE_MULTIPLY", true);
|
||||
break;
|
||||
case BlendingMode::SCREEN:
|
||||
CodeGenerator::generateDefine(fs, "BLEND_MODE_SCREEN", true);
|
||||
break;
|
||||
}
|
||||
switch (material.postLightingBlendingMode) {
|
||||
case BlendingMode::OPAQUE:
|
||||
CodeGenerator::generateDefine(fs, "POST_LIGHTING_BLEND_MODE_OPAQUE", true);
|
||||
break;
|
||||
case BlendingMode::TRANSPARENT:
|
||||
CodeGenerator::generateDefine(fs, "POST_LIGHTING_BLEND_MODE_TRANSPARENT", true);
|
||||
break;
|
||||
case BlendingMode::ADD:
|
||||
CodeGenerator::generateDefine(fs, "POST_LIGHTING_BLEND_MODE_ADD", true);
|
||||
break;
|
||||
case BlendingMode::MULTIPLY:
|
||||
CodeGenerator::generateDefine(fs, "POST_LIGHTING_BLEND_MODE_MULTIPLY", true);
|
||||
break;
|
||||
case BlendingMode::SCREEN:
|
||||
CodeGenerator::generateDefine(fs, "POST_LIGHTING_BLEND_MODE_SCREEN", true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
CodeGenerator::generateDefine(fs, getShadingDefine(material.shading), true);
|
||||
generateMaterialDefines(fs, mProperties, mDefines);
|
||||
|
||||
CodeGenerator::generateDefine(fs, "MATERIAL_HAS_CUSTOM_SURFACE_SHADING", material.hasCustomSurfaceShading);
|
||||
|
||||
CodeGenerator::generateShaderInputs(fs, ShaderStage::FRAGMENT, material.requiredAttributes, interpolation);
|
||||
CodeGenerator::generateCommonTypes(fs, ShaderStage::FRAGMENT);
|
||||
|
||||
// custom material variables
|
||||
size_t variableIndex = 0;
|
||||
@@ -515,22 +516,35 @@ std::string ShaderGenerator::createFragmentProgram(ShaderModel shaderModel,
|
||||
// uniforms and samplers
|
||||
cg.generateUniforms(fs, ShaderStage::FRAGMENT,
|
||||
UniformBindingPoints::PER_VIEW, UibGenerator::getPerViewUib());
|
||||
|
||||
cg.generateUniforms(fs, ShaderStage::FRAGMENT,
|
||||
UniformBindingPoints::PER_RENDERABLE, UibGenerator::getPerRenderableUib());
|
||||
cg.generateUniforms(fs, ShaderStage::FRAGMENT,
|
||||
UniformBindingPoints::LIGHTS, UibGenerator::getLightsUib());
|
||||
|
||||
if (variant.hasDynamicLighting()) {
|
||||
cg.generateUniforms(fs, ShaderStage::FRAGMENT,
|
||||
UniformBindingPoints::LIGHTS, UibGenerator::getLightsUib());
|
||||
}
|
||||
|
||||
bool const litVariants = material.isLit || material.hasShadowMultiplier;
|
||||
if (litVariants && filament::Variant::isShadowReceiverVariant(variant)) {
|
||||
cg.generateUniforms(fs, ShaderStage::FRAGMENT,
|
||||
UniformBindingPoints::SHADOW, UibGenerator::getShadowUib());
|
||||
}
|
||||
cg.generateUniforms(fs, ShaderStage::FRAGMENT,
|
||||
UniformBindingPoints::FROXEL_RECORDS, UibGenerator::getFroxelRecordUib());
|
||||
|
||||
if (variant.hasDynamicLighting()) {
|
||||
cg.generateUniforms(fs, ShaderStage::FRAGMENT,
|
||||
UniformBindingPoints::FROXEL_RECORDS, UibGenerator::getFroxelRecordUib());
|
||||
}
|
||||
|
||||
cg.generateUniforms(fs, ShaderStage::FRAGMENT,
|
||||
UniformBindingPoints::PER_MATERIAL_INSTANCE, material.uib);
|
||||
|
||||
CodeGenerator::generateSeparator(fs);
|
||||
|
||||
cg.generateSamplers(fs, SamplerBindingPoints::PER_VIEW,
|
||||
material.samplerBindings.getBlockOffset(SamplerBindingPoints::PER_VIEW),
|
||||
SibGenerator::getPerViewSib(variant));
|
||||
|
||||
cg.generateSamplers(fs, SamplerBindingPoints::PER_MATERIAL_INSTANCE,
|
||||
material.samplerBindings.getBlockOffset(SamplerBindingPoints::PER_MATERIAL_INSTANCE),
|
||||
material.sib);
|
||||
@@ -551,13 +565,13 @@ std::string ShaderGenerator::createFragmentProgram(ShaderModel shaderModel,
|
||||
if (material.blendingMode == BlendingMode::MASKED || material.hasTransparentShadow) {
|
||||
appendShader(fs, mMaterialFragmentCode, mMaterialLineOffset);
|
||||
}
|
||||
// these variants are special and are treated as DEPTH variants. Filament will never
|
||||
// These variants are special and are treated as DEPTH variants. Filament will never
|
||||
// request that variant for the color pass.
|
||||
CodeGenerator::generateDepthShaderMain(fs, ShaderStage::FRAGMENT);
|
||||
} else {
|
||||
appendShader(fs, mMaterialFragmentCode, mMaterialLineOffset);
|
||||
if (filament::Variant::isSSRVariant(variant)) {
|
||||
CodeGenerator::generateShaderReflections(fs, ShaderStage::FRAGMENT, variant);
|
||||
CodeGenerator::generateShaderReflections(fs, ShaderStage::FRAGMENT);
|
||||
} else if (material.isLit) {
|
||||
CodeGenerator::generateShaderLit(fs, ShaderStage::FRAGMENT, variant,
|
||||
material.shading,material.hasCustomSurfaceShading);
|
||||
@@ -576,7 +590,7 @@ std::string ShaderGenerator::createFragmentProgram(ShaderModel shaderModel,
|
||||
|
||||
std::string ShaderGenerator::createComputeProgram(filament::backend::ShaderModel shaderModel,
|
||||
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
|
||||
MaterialInfo const& material, filament::Variant variant) const noexcept {
|
||||
MaterialInfo const& material) const noexcept {
|
||||
assert_invariant(mMaterialDomain == MaterialBuilder::MaterialDomain::COMPUTE);
|
||||
assert_invariant(material.featureLevel >= FeatureLevel::FEATURE_LEVEL_2);
|
||||
const CodeGenerator cg(shaderModel, targetApi, targetLanguage, material.featureLevel);
|
||||
@@ -586,7 +600,7 @@ std::string ShaderGenerator::createComputeProgram(filament::backend::ShaderModel
|
||||
|
||||
generateUserSpecConstants(cg, s, mConstants);
|
||||
|
||||
cg.generateQualityDefine(s, material.quality);
|
||||
CodeGenerator::generateCommonTypes(s, ShaderStage::COMPUTE);
|
||||
|
||||
cg.generateUniforms(s, ShaderStage::COMPUTE,
|
||||
UniformBindingPoints::PER_VIEW, UibGenerator::getPerViewUib());
|
||||
@@ -622,8 +636,6 @@ std::string ShaderGenerator::createPostProcessVertexProgram(ShaderModel sm,
|
||||
io::sstream vs;
|
||||
cg.generateProlog(vs, ShaderStage::VERTEX, material);
|
||||
|
||||
cg.generateQualityDefine(vs, material.quality);
|
||||
|
||||
CodeGenerator::generateDefine(vs, "LOCATION_POSITION", uint32_t(VertexAttribute::POSITION));
|
||||
|
||||
// custom material variables
|
||||
@@ -637,6 +649,7 @@ std::string ShaderGenerator::createPostProcessVertexProgram(ShaderModel sm,
|
||||
|
||||
cg.generateUniforms(vs, ShaderStage::VERTEX,
|
||||
UniformBindingPoints::PER_VIEW, UibGenerator::getPerViewUib());
|
||||
|
||||
cg.generateUniforms(vs, ShaderStage::VERTEX,
|
||||
UniformBindingPoints::PER_MATERIAL_INSTANCE, material.uib);
|
||||
|
||||
@@ -662,8 +675,6 @@ std::string ShaderGenerator::createPostProcessFragmentProgram(ShaderModel sm,
|
||||
io::sstream fs;
|
||||
cg.generateProlog(fs, ShaderStage::FRAGMENT, material);
|
||||
|
||||
cg.generateQualityDefine(fs, material.quality);
|
||||
|
||||
generatePostProcessMaterialVariantDefines(fs, PostProcessVariant(variant));
|
||||
|
||||
// custom material variables
|
||||
@@ -674,6 +685,7 @@ std::string ShaderGenerator::createPostProcessFragmentProgram(ShaderModel sm,
|
||||
|
||||
cg.generateUniforms(fs, ShaderStage::FRAGMENT,
|
||||
UniformBindingPoints::PER_VIEW, UibGenerator::getPerViewUib());
|
||||
|
||||
cg.generateUniforms(fs, ShaderStage::FRAGMENT,
|
||||
UniformBindingPoints::PER_MATERIAL_INSTANCE, material.uib);
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
|
||||
std::string createComputeProgram(filament::backend::ShaderModel shaderModel,
|
||||
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
|
||||
MaterialInfo const& material, filament::Variant variant) const noexcept;
|
||||
MaterialInfo const& material) const noexcept;
|
||||
|
||||
/**
|
||||
* When a GLSL shader is optimized we run it through an intermediate SPIR-V
|
||||
@@ -75,6 +75,23 @@ public:
|
||||
MaterialInfo const& material) noexcept;
|
||||
|
||||
private:
|
||||
static void generateVertexDomainDefines(utils::io::sstream& out,
|
||||
filament::VertexDomain domain) noexcept;
|
||||
|
||||
static void generateSurfaceMaterialVariantProperties(utils::io::sstream& out,
|
||||
MaterialBuilder::PropertyList const properties,
|
||||
const MaterialBuilder::PreprocessorDefineList& defines) noexcept;
|
||||
|
||||
static void generateSurfaceMaterialVariantDefines(utils::io::sstream& out,
|
||||
filament::backend::ShaderStage stage,
|
||||
MaterialInfo const& material, filament::Variant variant) noexcept;
|
||||
|
||||
static void generatePostProcessMaterialVariantDefines(utils::io::sstream& out,
|
||||
filament::PostProcessVariant variant) noexcept;
|
||||
|
||||
static void generateUserSpecConstants(
|
||||
const CodeGenerator& cg, utils::io::sstream& fs,
|
||||
MaterialBuilder::ConstantList const& constants);
|
||||
|
||||
std::string createPostProcessVertexProgram(filament::backend::ShaderModel sm,
|
||||
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
|
||||
@@ -84,6 +101,9 @@ private:
|
||||
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
|
||||
MaterialInfo const& material, uint8_t variant) const noexcept;
|
||||
|
||||
static void appendShader(utils::io::sstream& ss,
|
||||
const utils::CString& shader, size_t lineOffset) noexcept;
|
||||
|
||||
MaterialBuilder::PropertyList mProperties;
|
||||
MaterialBuilder::VariableList mVariables;
|
||||
MaterialBuilder::OutputList mOutputs;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#if defined(VARIANT_HAS_SHADOWING)
|
||||
// Adreno drivers seem to ignore precision qualifiers in structs, unless they're used in
|
||||
// UBOs, which is is the case here.
|
||||
// UBOs, which is the case here.
|
||||
struct ShadowData {
|
||||
highp mat4 lightFromWorldMatrix;
|
||||
highp vec4 lightFromWorldZ;
|
||||
@@ -13,11 +14,14 @@ struct ShadowData {
|
||||
mediump uint reserved1;
|
||||
mediump uint reserved2;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(VARIANT_HAS_SKINNING_OR_MORPHING)
|
||||
struct BoneData {
|
||||
highp mat3x4 transform; // bone transform is mat4x3 stored in row-major (last row [0,0,0,1])
|
||||
highp uvec4 cof; // 8 first cofactor matrix of transform's upper left
|
||||
};
|
||||
#endif
|
||||
|
||||
struct PerRenderableData {
|
||||
highp mat4 worldFromModelMatrix;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
#include <filamat/MaterialBuilder.h>
|
||||
|
||||
@@ -71,7 +72,7 @@ bool MaterialCompiler::processMaterial(const MaterialLexeme& jsonLexeme,
|
||||
jlexer.lex(jsonLexeme.getStart(), jsonLexeme.getSize(), jsonLexeme.getLine());
|
||||
|
||||
JsonishParser parser(jlexer.getLexemes());
|
||||
std::unique_ptr<JsonishObject> json = parser.parse();
|
||||
std::unique_ptr<JsonishObject> const json = parser.parse();
|
||||
|
||||
if (json == nullptr) {
|
||||
std::cerr << "JsonishParser error (see above)." << std::endl;
|
||||
@@ -79,7 +80,7 @@ bool MaterialCompiler::processMaterial(const MaterialLexeme& jsonLexeme,
|
||||
}
|
||||
|
||||
ParametersProcessor parametersProcessor;
|
||||
bool ok = parametersProcessor.process(builder, *json);
|
||||
bool const ok = parametersProcessor.process(builder, *json);
|
||||
if (!ok) {
|
||||
std::cerr << "Error while processing material." << std::endl;
|
||||
return false;
|
||||
@@ -91,8 +92,8 @@ bool MaterialCompiler::processMaterial(const MaterialLexeme& jsonLexeme,
|
||||
bool MaterialCompiler::processVertexShader(const MaterialLexeme& lexeme,
|
||||
MaterialBuilder& builder) const noexcept {
|
||||
|
||||
MaterialLexeme trimmedLexeme = lexeme.trimBlockMarkers();
|
||||
std::string shaderStr = trimmedLexeme.getStringValue();
|
||||
MaterialLexeme const trimmedLexeme = lexeme.trimBlockMarkers();
|
||||
std::string const shaderStr = trimmedLexeme.getStringValue();
|
||||
|
||||
// getLine() returns a line number, with 1 being the first line, but .material wants a 0-based
|
||||
// line number offset, where 0 is the first line.
|
||||
@@ -103,8 +104,8 @@ bool MaterialCompiler::processVertexShader(const MaterialLexeme& lexeme,
|
||||
bool MaterialCompiler::processFragmentShader(const MaterialLexeme& lexeme,
|
||||
MaterialBuilder& builder) const noexcept {
|
||||
|
||||
MaterialLexeme trimmedLexeme = lexeme.trimBlockMarkers();
|
||||
std::string shaderStr = trimmedLexeme.getStringValue();
|
||||
MaterialLexeme const trimmedLexeme = lexeme.trimBlockMarkers();
|
||||
std::string const shaderStr = trimmedLexeme.getStringValue();
|
||||
|
||||
// getLine() returns a line number, with 1 being the first line, but .material wants a 0-based
|
||||
// line number offset, where 0 is the first line.
|
||||
@@ -117,8 +118,7 @@ bool MaterialCompiler::processComputeShader(const MaterialLexeme& lexeme,
|
||||
return MaterialCompiler::processFragmentShader(lexeme, builder);
|
||||
}
|
||||
|
||||
bool MaterialCompiler::ignoreLexeme(const MaterialLexeme& lexeme,
|
||||
MaterialBuilder& builder) const noexcept {
|
||||
bool MaterialCompiler::ignoreLexeme(const MaterialLexeme&, MaterialBuilder&) const noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ bool MaterialCompiler::processMaterialJSON(const JsonishValue* value,
|
||||
}
|
||||
|
||||
ParametersProcessor parametersProcessor;
|
||||
bool ok = parametersProcessor.process(builder, *value->toJsonObject());
|
||||
bool const ok = parametersProcessor.process(builder, *value->toJsonObject());
|
||||
if (!ok) {
|
||||
std::cerr << "Error while processing material." << std::endl;
|
||||
return false;
|
||||
@@ -208,12 +208,12 @@ bool MaterialCompiler::processComputeShaderJSON(const JsonishValue* value,
|
||||
}
|
||||
|
||||
bool MaterialCompiler::ignoreLexemeJSON(const JsonishValue*,
|
||||
filamat::MaterialBuilder& builder) const noexcept {
|
||||
filamat::MaterialBuilder&) const noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool reflectParameters(const MaterialBuilder& builder) {
|
||||
uint8_t count = builder.getParameterCount();
|
||||
uint8_t const count = builder.getParameterCount();
|
||||
const MaterialBuilder::ParameterList& parameters = builder.getParameters();
|
||||
|
||||
std::cout << "{" << std::endl;
|
||||
@@ -316,7 +316,7 @@ bool MaterialCompiler::run(const Config& config) {
|
||||
++endCursor;
|
||||
}
|
||||
// At this point, cursor points to the F in ${FOO} and endCursor points to the }.
|
||||
std::string_view macro(&buffer[cursor], endCursor - cursor);
|
||||
std::string_view const macro(&buffer[cursor], endCursor - cursor);
|
||||
if (auto iter = templateMap.find(macro); iter != templateMap.end()) {
|
||||
modifiedSize -= macro.size() + 3;
|
||||
modifiedSize += iter->second.size();
|
||||
@@ -342,24 +342,24 @@ bool MaterialCompiler::run(const Config& config) {
|
||||
ssize_t endCursor = cursor;
|
||||
while (buffer[endCursor] != '}') ++endCursor;
|
||||
// At this point, cursor points to the F in ${FOO} and endCursor points to the }.
|
||||
std::string_view macro(&buffer[cursor], endCursor - cursor);
|
||||
std::string_view const macro(&buffer[cursor], endCursor - cursor);
|
||||
const std::string& val = templateMap.find(macro)->second;
|
||||
for (size_t i = 0, n = val.size(); i < n; ++i, ++dstCursor) {
|
||||
modifiedBuffer[dstCursor] = val[i];
|
||||
}
|
||||
cursor = endCursor;
|
||||
}
|
||||
buffer.reset(modifiedBuffer.release());
|
||||
buffer = std::move(modifiedBuffer);
|
||||
size = modifiedSize;
|
||||
}
|
||||
|
||||
utils::Path materialFilePath = utils::Path(input->getName()).getAbsolutePath();
|
||||
utils::Path const materialFilePath = utils::Path(input->getName()).getAbsolutePath();
|
||||
assert(materialFilePath.isFile());
|
||||
|
||||
if (config.rawShaderMode()) {
|
||||
const std::string extension = materialFilePath.getExtension();
|
||||
glslang::InitializeProcess();
|
||||
bool success = compileRawShader(buffer.get(), size, config.isDebug(), config.getOutput(),
|
||||
bool const success = compileRawShader(buffer.get(), size, config.isDebug(), config.getOutput(),
|
||||
extension.c_str());
|
||||
glslang::FinalizeProcess();
|
||||
return success;
|
||||
@@ -414,7 +414,7 @@ bool MaterialCompiler::run(const Config& config) {
|
||||
js.adopt();
|
||||
|
||||
// Write builder.build() to output.
|
||||
Package package = builder.build(js);
|
||||
Package const package = builder.build(js);
|
||||
|
||||
js.emancipate();
|
||||
MaterialBuilder::shutdown();
|
||||
@@ -468,9 +468,9 @@ bool MaterialCompiler::parseMaterialAsJSON(const char* buffer, size_t size,
|
||||
}
|
||||
|
||||
// Retrieve function member pointer
|
||||
MaterialConfigProcessorJSON p = mConfigProcessorJSON.at(key);
|
||||
MaterialConfigProcessorJSON const p = mConfigProcessorJSON.at(key);
|
||||
// Call it.
|
||||
bool ok = (*this.*p)(entry.second, builder);
|
||||
bool const ok = (*this.*p)(entry.second, builder);
|
||||
if (!ok) {
|
||||
std::cerr << "Error while processing block with key:'" << key << "'" << std::endl;
|
||||
return false;
|
||||
@@ -539,7 +539,7 @@ bool MaterialCompiler::parseMaterial(const char* buffer, size_t size,
|
||||
return false;
|
||||
}
|
||||
} else if (lexeme.getType() == MaterialType::BLOCK) {
|
||||
MaterialConfigProcessor processor = mConfigProcessor.at(identifier);
|
||||
MaterialConfigProcessor const processor = mConfigProcessor.at(identifier);
|
||||
if (!(*this.*processor)(lexeme, builder)) {
|
||||
std::cerr << "Error while processing block with key:'" << identifier << "'"
|
||||
<< std::endl;
|
||||
@@ -559,7 +559,7 @@ bool MaterialCompiler::compileRawShader(const char* glsl, size_t size, bool isDe
|
||||
const EShLanguage shLang = !strcmp(ext, "vs") ? EShLangVertex : EShLangFragment;
|
||||
|
||||
// Add a terminating null by making a copy of the GLSL string.
|
||||
std::string nullTerminated(glsl, size);
|
||||
std::string const nullTerminated(glsl, size);
|
||||
glsl = nullTerminated.c_str();
|
||||
|
||||
TShader tShader(shLang);
|
||||
@@ -571,7 +571,7 @@ bool MaterialCompiler::compileRawShader(const char* glsl, size_t size, bool isDe
|
||||
|
||||
tShader.setAutoMapBindings(true);
|
||||
|
||||
bool parseOk = tShader.parse(&DefaultTBuiltInResource, version, false, msg);
|
||||
bool const parseOk = tShader.parse(&DefaultTBuiltInResource, version, false, msg);
|
||||
if (!parseOk) {
|
||||
std::cerr << "ERROR: Unable to parse " << ext << ":" << std::endl;
|
||||
std::cerr << tShader.getInfoLog() << std::endl;
|
||||
@@ -582,7 +582,7 @@ bool MaterialCompiler::compileRawShader(const char* glsl, size_t size, bool isDe
|
||||
// SPIR-V types
|
||||
TProgram program;
|
||||
program.addShader(&tShader);
|
||||
bool linkOk = program.link(msg);
|
||||
bool const linkOk = program.link(msg);
|
||||
if (!linkOk) {
|
||||
std::cerr << "ERROR: link failed " << std::endl << tShader.getInfoLog() << std::endl;
|
||||
return false;
|
||||
@@ -592,7 +592,7 @@ bool MaterialCompiler::compileRawShader(const char* glsl, size_t size, bool isDe
|
||||
SpvOptions options;
|
||||
GlslangToSpv(*tShader.getIntermediate(), spirv, &options);
|
||||
|
||||
if (spirv.size() == 0) {
|
||||
if (spirv.empty()) {
|
||||
std::cerr << "SPIRV blob is empty." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user