Compare commits

...

3 Commits

Author SHA1 Message Date
Powei Feng
b3fc8e3796 matc: initialize CustomVariable
The default values were not provided via default construction.
Caused matc to crash on Linux.
2024-08-22 13:32:54 -07:00
Mathias Agopian
5e7106b521 custom variables can now have their precision specified
e.g.:

    variables : [
        {
            name : vertex,
            precision : medium,
         }
    ],
2024-08-22 13:08:48 -07:00
Mathias Agopian
30387af61c reenable the SimplificationPass in spirv-opt
Issues with it were fixed (https://github.com/KhronosGroup/SPIRV-Cross/pull/2163),
so it should be safe to reenable. The invalid glsl code seems to be resolved.
2024-08-22 13:08:23 -07:00
7 changed files with 96 additions and 20 deletions

View File

@@ -1308,7 +1308,12 @@ Description
declare a variable called `eyeDirection` you can access it in the fragment shader using
`variable_eyeDirection`. In the vertex shader, the interpolant name is simply a member of
the `MaterialVertexInputs` structure (`material.eyeDirection` in your example). Each
interpolant is of type `float4` (`vec4`) in the shaders.
interpolant is of type `float4` (`vec4`) in the shaders. By default the precision of the
interpolant is `highp` in *both* the vertex and fragment shaders.
An alternate syntax can be used to specify both the name and precision of the interpolant.
In this case the specified precision is used as-is in both fragment and vertex stages, in
particular if `default` is specified the default precision is used is the fragment shader
(`mediump`) and in the vertex shader (`highp`).
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
material {
@@ -1320,7 +1325,11 @@ material {
}
],
variables : [
eyeDirection
eyeDirection,
{
name : eyeColor,
precision : medium
}
],
vertexDomain : device,
depthWrite : false,

View File

@@ -323,6 +323,9 @@ public:
//! Custom variables (all float4).
MaterialBuilder& variable(Variable v, const char* name) noexcept;
MaterialBuilder& variable(Variable v, const char* name,
ParameterPrecision precision) noexcept;
/**
* Require a specified attribute.
*
@@ -708,11 +711,17 @@ public:
ShaderStage stage;
};
struct CustomVariable {
utils::CString name;
Precision precision = Precision::DEFAULT;
bool hasPrecision = false;
};
static constexpr size_t MATERIAL_PROPERTIES_COUNT = filament::MATERIAL_PROPERTIES_COUNT;
using Property = filament::Property;
using PropertyList = bool[MATERIAL_PROPERTIES_COUNT];
using VariableList = utils::CString[MATERIAL_VARIABLES_COUNT];
using VariableList = CustomVariable[MATERIAL_VARIABLES_COUNT];
using OutputList = std::vector<Output>;
static constexpr size_t MAX_COLOR_OUTPUT = filament::backend::MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT;

View File

@@ -671,13 +671,15 @@ void GLSLPostProcessor::fixupClipDistance(
// - triggers a crash on some Adreno drivers (b/291140208, b/289401984, b/289393290)
// However Metal requires this pass in order to correctly generate half-precision MSL
//
// CreateSimplificationPass() creates a lot of problems:
// Note: CreateSimplificationPass() used to creates a lot of problems:
// - Adreno GPU show artifacts after running simplification passes (Vulkan)
// - spirv-cross fails generating working glsl
// (https://github.com/KhronosGroup/SPIRV-Cross/issues/2162)
// - generally it makes the code more complicated, e.g.: replacing for loops with
// while-if-break, unclear if it helps for anything.
// However, the simplification passes below are necessary when targeting Metal, otherwise the
//
// However this problem was addressed in spirv-cross here:
// https://github.com/KhronosGroup/SPIRV-Cross/pull/2163
//
// The simplification passes below are necessary when targeting Metal, otherwise the
// result is mismatched half / float assignments in MSL.
@@ -710,11 +712,11 @@ void GLSLPostProcessor::registerPerformancePasses(Optimizer& optimizer, Config c
RegisterPass(CreateAggressiveDCEPass());
RegisterPass(CreateRedundancyEliminationPass());
RegisterPass(CreateCombineAccessChainsPass());
RegisterPass(CreateSimplificationPass(), MaterialBuilder::TargetApi::METAL);
RegisterPass(CreateSimplificationPass());
RegisterPass(CreateVectorDCEPass());
RegisterPass(CreateDeadInsertElimPass());
RegisterPass(CreateDeadBranchElimPass());
RegisterPass(CreateSimplificationPass(), MaterialBuilder::TargetApi::METAL);
RegisterPass(CreateSimplificationPass());
RegisterPass(CreateIfConversionPass());
RegisterPass(CreateCopyPropagateArraysPass());
RegisterPass(CreateReduceLoadSizePass());
@@ -723,7 +725,7 @@ void GLSLPostProcessor::registerPerformancePasses(Optimizer& optimizer, Config c
RegisterPass(CreateRedundancyEliminationPass());
RegisterPass(CreateDeadBranchElimPass());
RegisterPass(CreateBlockMergePass());
RegisterPass(CreateSimplificationPass(), MaterialBuilder::TargetApi::METAL);
RegisterPass(CreateSimplificationPass());
}
void GLSLPostProcessor::registerSizePasses(Optimizer& optimizer, Config const& config) {

View File

@@ -234,7 +234,21 @@ MaterialBuilder& MaterialBuilder::variable(Variable v, const char* name) noexcep
case Variable::CUSTOM2:
case Variable::CUSTOM3:
assert(size_t(v) < MATERIAL_VARIABLES_COUNT);
mVariables[size_t(v)] = CString(name);
mVariables[size_t(v)] = { CString(name), Precision::DEFAULT, false };
break;
}
return *this;
}
MaterialBuilder& MaterialBuilder::variable(Variable v,
const char* name, ParameterPrecision precision) noexcept {
switch (v) {
case Variable::CUSTOM0:
case Variable::CUSTOM1:
case Variable::CUSTOM2:
case Variable::CUSTOM3:
assert(size_t(v) < MATERIAL_VARIABLES_COUNT);
mVariables[size_t(v)] = { CString(name), precision, true };
break;
}
return *this;
@@ -1383,7 +1397,7 @@ bool MaterialBuilder::checkMaterialLevelFeatures(MaterialInfo const& info) const
bool MaterialBuilder::hasCustomVaryings() const noexcept {
for (const auto& variable : mVariables) {
if (!variable.empty()) {
if (!variable.name.empty()) {
return true;
}
}

View File

@@ -451,15 +451,20 @@ io::sstream& CodeGenerator::generatePostProcessMain(io::sstream& out, ShaderStag
}
io::sstream& CodeGenerator::generateVariable(io::sstream& out, ShaderStage stage,
const CString& name, size_t index) {
const MaterialBuilder::CustomVariable& variable, size_t index) {
auto const& name = variable.name;
const char* precisionString = getPrecisionQualifier(variable.precision);
if (!name.empty()) {
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 << ") VARYING vec4 variable_" << name.c_str() << ";\n";
out << "LAYOUT_LOCATION(" << index << ") VARYING " << precisionString << " vec4 variable_" << name.c_str() << ";\n";
} else if (stage == ShaderStage::FRAGMENT) {
out << "\nLAYOUT_LOCATION(" << index << ") VARYING highp vec4 variable_" << name.c_str() << ";\n";
if (!variable.hasPrecision && variable.precision == Precision::DEFAULT) {
// for backward compatibility
precisionString = "highp";
}
out << "\nLAYOUT_LOCATION(" << index << ") VARYING " << precisionString << " vec4 variable_" << name.c_str() << ";\n";
}
}
return out;

View File

@@ -103,7 +103,7 @@ public:
// generate declarations for custom interpolants
static utils::io::sstream& generateVariable(utils::io::sstream& out, ShaderStage stage,
const utils::CString& name, size_t index);
const MaterialBuilder::CustomVariable& variable, size_t index);
// generate declarations for non-custom "in" variables
utils::io::sstream& generateShaderInputs(utils::io::sstream& out, ShaderStage type,

View File

@@ -615,14 +615,51 @@ static bool processVariables(MaterialBuilder& builder, const JsonishValue& value
}
for (size_t i = 0; i < elements.size(); i++) {
auto elementValue = elements[i];
ParameterPrecision precision = ParameterPrecision::DEFAULT;
MaterialBuilder::Variable v = intToVariable(i);
if (elementValue->getType() != JsonishValue::Type::STRING) {
std::string nameString;
auto elementValue = elements[i];
if (elementValue->getType() == JsonishValue::Type::OBJECT) {
JsonishObject const& jsonObject = *elementValue->toJsonObject();
const JsonishValue* nameValue = jsonObject.getValue("name");
if (!nameValue) {
std::cerr << "variables: entry without 'name' key." << std::endl;
return false;
}
if (nameValue->getType() != JsonishValue::STRING) {
std::cerr << "variables: name value must be STRING." << std::endl;
return false;
}
const JsonishValue* precisionValue = jsonObject.getValue("precision");
if (precisionValue) {
if (precisionValue->getType() != JsonishValue::STRING) {
std::cerr << "variables: precision must be a STRING." << std::endl;
return false;
}
auto precisionString = precisionValue->toJsonString();
if (!Enums::isValid<ParameterPrecision>(precisionString->getString())){
return logEnumIssue("variables", *precisionString, Enums::map<ParameterPrecision>());
}
}
nameString = nameValue->toJsonString()->getString();
if (precisionValue) {
precision = Enums::toEnum<ParameterPrecision>(
precisionValue->toJsonString()->getString());
}
builder.variable(v, nameString.c_str(), precision);
} else if (elementValue->getType() == JsonishValue::Type::STRING) {
nameString = elementValue->toJsonString()->getString();
builder.variable(v, nameString.c_str());
} else {
std::cerr << "variables: array index " << i << " is not a STRING. found:" <<
JsonishValue::typeToString(elementValue->getType()) << std::endl;
return false;
}
builder.variable(v, elementValue->toJsonString()->getString().c_str());
}
return true;