Skip to content

Commit

Permalink
custom variables can now have their precision specified
Browse files Browse the repository at this point in the history
e.g.:

    variables : [
        {
            name : vertex,
            precision : medium,
         }
    ],
  • Loading branch information
pixelflinger committed Aug 22, 2024
1 parent 30387af commit 5e7106b
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 13 deletions.
13 changes: 11 additions & 2 deletions docs/Materials.md.html
Original file line number Diff line number Diff line change
Expand Up @@ -1308,7 +1308,12 @@
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 {
Expand All @@ -1320,7 +1325,11 @@
}
],
variables : [
eyeDirection
eyeDirection,
{
name : eyeColor,
precision : medium
}
],
vertexDomain : device,
depthWrite : false,
Expand Down
11 changes: 10 additions & 1 deletion libs/filamat/include/filamat/MaterialBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,9 @@ class UTILS_PUBLIC MaterialBuilder : public MaterialBuilderBase {
//! 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.
*
Expand Down Expand Up @@ -708,11 +711,17 @@ class UTILS_PUBLIC MaterialBuilder : public MaterialBuilderBase {
ShaderStage stage;
};

struct CustomVariable {
utils::CString name;
Precision precision;
bool hasPrecision;
};

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;
Expand Down
18 changes: 16 additions & 2 deletions libs/filamat/src/MaterialBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
Expand Down
13 changes: 9 additions & 4 deletions libs/filamat/src/shaders/CodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion libs/filamat/src/shaders/CodeGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class UTILS_PRIVATE CodeGenerator {

// 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,
Expand Down
43 changes: 40 additions & 3 deletions tools/matc/src/matc/ParametersProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 5e7106b

Please sign in to comment.