Repository: google/filament
File: libs/filamat/src/shaders/CodeGenerator.cpp (C++)

Code before:
        }
        out << "};\n";
        out << "const " << STRUCT_NAME << " " << PUSH_CONSTANT_STRUCT_VAR_NAME << " = "
            << STRUCT_NAME << "(0);\n";
        return out;
    }


    bool const outputSpirv =
            mTargetLanguage == TargetLanguage::SPIRV && mTargetApi != TargetApi::OPENGL;
    auto const getType = [](ConstantType const& type) {
        switch (type) {
            case ConstantType::BOOL:
                return "bool";
            case ConstantType::INT:
                return "int";
            case ConstantType::FLOAT:
                return "float";
        }
    };
    if (outputSpirv) {
        out << "layout(push_constant) uniform " << STRUCT_NAME << " {\n ";
    } else {
        out << "struct " << STRUCT_NAME << " {\n";
    }

    for (auto const& constant: pushConstants) {
        out << getType(constant.type) << " " << constant.name.c_str() << ";\n";
    }

    if (outputSpirv) {
        out << "} " << PUSH_CONSTANT_STRUCT_VAR_NAME << ";\n";
    } else {
        out << "};\n";
        out << "LAYOUT_LOCATION(" << static_cast<int>(layoutLocation) << ") uniform " << STRUCT_NAME
            << " " << PUSH_CONSTANT_STRUCT_VAR_NAME << ";\n";
    }
    return out;
}

io::sstream& CodeGenerator::generateMaterialProperty(io::sstream& out,
        MaterialBuilder::Property property, bool isSet) {
    if (isSet) {
        out << "#define " << "MATERIAL_HAS_" << getConstantName(property) << "\n";
    }
    return out;
}

io::sstream& CodeGenerator::generateQualityDefine(io::sstream& out, ShaderQuality quality) const {
    out << "#define FILAMENT_QUALITY_LOW    0\n";
    out << "#define FILAMENT_QUALITY_NORMAL 1\n";

Review comment (bug):
I recommend an assert that the `pushConstants` has one value with the one name we expect. Otherwise, things/assumptions have changed and this part of the code should fail loudly. Also, it makes the hack here more obvious (in addition to your comment).

Code after:
                return "bool";
            case ConstantType::INT:
                return "int";
            case ConstantType::FLOAT:
                return "float";
        }
    };
    // This is a workaround for WebGPU not supporting push constants for skinning.
    // We replace the push constant with a regular constant struct initialized to 0.
    if (mTargetApi == TargetApi::WEBGPU) {
        assert_invariant(
                pushConstants.size() == 1 &&
                "The current workaround for WebGPU push constants assumes for now that only 1");
        assert_invariant(pushConstants[0].name == CString("morphingBufferOffset") &&
                         "The current workaround for WebGPU push constants assumes only the "
                         "morphingBufferOffset constant is present.");
        assert_invariant(pushConstants[0].type == ConstantType::INT &&
                         "The current workaround for WebGPU push constants assumes "
                         "morphingBufferOffset is an integer type.");
        out << "struct " << STRUCT_NAME << " {\n";
        for (auto const& constant: pushConstants) {
            out << "    " << getType(constant.type) << " " << constant.name.c_str() << ";\n";
        }
        out << "};\n";
        out << "const " << STRUCT_NAME << " " << PUSH_CONSTANT_STRUCT_VAR_NAME << " = "
            << STRUCT_NAME << "(0);\n";
        return out;
    }

    bool const outputSpirv =
            mTargetLanguage == TargetLanguage::SPIRV && mTargetApi != TargetApi::OPENGL;
    if (outputSpirv) {
        out << "layout(push_constant) uniform " << STRUCT_NAME << " {\n ";
    } else {
        out << "struct " << STRUCT_NAME << " {\n";
    }

    for (auto const& constant: pushConstants) {
        out << getType(constant.type) << " " << constant.name.c_str() << ";\n";
    }

    if (outputSpirv) {
        out << "} " << PUSH_CONSTANT_STRUCT_VAR_NAME << ";\n";
    } else {
        out << "};\n";
        out << "LAYOUT_LOCATION(" << static_cast<int>(layoutLocation) << ") uniform " << STRUCT_NAME
            << " " << PUSH_CONSTANT_STRUCT_VAR_NAME << ";\n";
    }
    return out;
}