~uriboni/qt-halide/autopkgtest

« back to all changes in this revision

Viewing changes to backend/modules/QtHalide/halide_function.cpp

  • Committer: Florian Boucault
  • Author(s): Florian Boucault
  • Date: 2015-04-01 15:05:46 UTC
  • mfrom: (273.2.11 property_type_checking)
  • Revision ID: florian_boucault-20150401150546-265gtnzbbruvmi73
HalideFunction: perform property type checking against Halide generator's parameters.

Show diffs side-by-side

added added

removed removed

Lines of Context:
43
43
    }
44
44
}
45
45
 
 
46
QString halideTypeName(Halide::Type type)
 
47
{
 
48
    QString name;
 
49
 
 
50
    if (type.is_vector()) {
 
51
        name += "vector of ";
 
52
    }
 
53
 
 
54
    if (type.is_bool()) {
 
55
        name += "bool";
 
56
    } else if (type.is_handle()) {
 
57
        name += "handle (void *)";
 
58
    } else {
 
59
        if (type.is_float()) {
 
60
            name += "float";
 
61
        } else if (type.is_int()) {
 
62
            name += "int";
 
63
        } else if (type.is_uint()) {
 
64
            name += "unsigned int";
 
65
        }
 
66
        name += QString(" (%1 bits)").arg(type.bits);
 
67
    }
 
68
 
 
69
    return name;
 
70
}
 
71
 
 
72
QString halideTypeToQmlType(Halide::Type type, bool& possibleOverflow)
 
73
{
 
74
    QString qmlType;
 
75
    possibleOverflow = false;
 
76
 
 
77
    if (type.is_vector()) {
 
78
        qmlType = "N/A";
 
79
    }
 
80
 
 
81
    if (type.is_bool()) {
 
82
        qmlType = "bool";
 
83
    } else if (type.is_handle()) {
 
84
        qmlType = "N/A";
 
85
    } else if (type.is_float()) {
 
86
        qmlType = "real";
 
87
        possibleOverflow = type.bits < (int)sizeof(double);
 
88
    } else if (type.is_int() || type.is_uint()) {
 
89
        qmlType = "int";
 
90
        possibleOverflow = type.bits < (int)sizeof(int);
 
91
    }
 
92
 
 
93
    return qmlType;
 
94
}
 
95
 
 
96
Halide::Type qMetaTypeToHalideType(int qMetaType)
 
97
{
 
98
    switch (qMetaType) {
 
99
    case QMetaType::Bool:
 
100
        return Halide::type_of<bool>();
 
101
        break;
 
102
    case QMetaType::Int:
 
103
        return Halide::type_of<int>();
 
104
        break;
 
105
    case QMetaType::SChar:
 
106
    case QMetaType::Char:
 
107
        return Halide::type_of<int8_t>();
 
108
        break;
 
109
    case QMetaType::Short:
 
110
        return Halide::type_of<short>();
 
111
        break;
 
112
    case QMetaType::Long:
 
113
        return Halide::type_of<long>();
 
114
        break;
 
115
    case QMetaType::LongLong:
 
116
        return Halide::type_of<int64_t>();
 
117
        break;
 
118
    case QMetaType::UInt:
 
119
        return Halide::type_of<unsigned int>();
 
120
        break;
 
121
    case QMetaType::UChar:
 
122
        return Halide::type_of<unsigned char>();
 
123
        break;
 
124
    case QMetaType::UShort:
 
125
        return Halide::type_of<unsigned short>();
 
126
        break;
 
127
    case QMetaType::ULong:
 
128
        return Halide::type_of<unsigned long>();
 
129
        break;
 
130
    case QMetaType::ULongLong:
 
131
        return Halide::type_of<uint64_t>();
 
132
        break;
 
133
    case QMetaType::Float:
 
134
        return Halide::type_of<float>();
 
135
        break;
 
136
    case QMetaType::Double:
 
137
        return Halide::type_of<double>();
 
138
        break;
 
139
    default:
 
140
        Halide::Type t;
 
141
        t.bits = 0;
 
142
        t.width = 0;
 
143
        return t;
 
144
        break;
 
145
    }
 
146
}
 
147
 
 
148
QString halideArgumentToQmlType(const Halide::Argument& argument, bool& possibleOverflow)
 
149
{
 
150
    if (argument.is_buffer) {
 
151
        return "HalideImage";
 
152
    } else {
 
153
        return halideTypeToQmlType(argument.type, possibleOverflow);
 
154
    }
 
155
}
 
156
 
 
157
bool isHalideArgumentCompatible(const Halide::Argument& argument, int qMetaType)
 
158
{
 
159
    if (argument.is_buffer) {
 
160
        return qMetaType == qMetaTypeId<HalideImage*>();
 
161
    } else {
 
162
        if (argument.type.code == Halide::Type::TypeCode::UInt && qMetaType == QMetaType::Int) {
 
163
            // FIXME: this is a workaround to allow QML int to represent
 
164
            // generators' unsigned int parameters; necessary due to the lack of
 
165
            // unsigned int in QML
 
166
            return true;
 
167
        } else {
 
168
            return qMetaTypeToHalideType(qMetaType).can_represent(argument.type);
 
169
        }
 
170
    }
 
171
}
 
172
 
 
173
QString halideArgumentTypeName(const Halide::Argument& argument)
 
174
{
 
175
    if (argument.is_buffer) {
 
176
        return "ImageParam";
 
177
    } else {
 
178
        return halideTypeName(argument.type);
 
179
    }
 
180
}
 
181
 
 
182
 
46
183
void HalideFunction::matchPropertiesToArguments(const std::vector<Halide::Argument>& arguments)
47
184
{
48
185
    m_signalMappers.clear();
53
190
        int propertyIndex = meta->indexOfProperty(argument.name.c_str());
54
191
        QString propertyName = QString::fromStdString(argument.name);
55
192
        m_propertiesValid[propertyName] = false;
56
 
        // FIXME: should check that the type of the property is compatible with the type of the parameter
 
193
        bool possibleOverflow;
 
194
        QString expectedQmlType = halideArgumentToQmlType(argument, possibleOverflow);
 
195
        QString argumentTypeName = halideArgumentTypeName(argument);
57
196
        if (propertyIndex == -1) {
58
 
            // FIXME: convert type.code to human readable format
59
 
            qWarning() << "Missing property" << propertyName << "of type" << argument.type.code;
 
197
            qWarning().noquote() << QString("HalideFunction '%1' is missing property '%2' of type %3.")
 
198
                                           .arg(m_name)
 
199
                                           .arg(propertyName)
 
200
                                           .arg(expectedQmlType);
60
201
        } else {
61
 
            m_propertiesValid[propertyName] = isPropertyValid(propertyName);
62
 
            connectToPropertyChange(propertyName);
 
202
            int propertyType = meta->property(propertyIndex).userType();
 
203
            if (isHalideArgumentCompatible(argument, propertyType)) {
 
204
                m_propertiesValid[propertyName] = isPropertyValid(propertyName);
 
205
                connectToPropertyChange(propertyName);
 
206
            } else {
 
207
                QString propertyTypeName = QMetaType::typeName(propertyType);
 
208
                qWarning().noquote() << QString("HalideFunction '%1': property '%2' is of type %3 incompatible "
 
209
                                                "with generator parameter of Halide type %4. Type should be %5.")
 
210
                                               .arg(m_name)
 
211
                                               .arg(propertyName)
 
212
                                               .arg(propertyTypeName)
 
213
                                               .arg(argumentTypeName)
 
214
                                               .arg(expectedQmlType);
 
215
            }
 
216
        }
 
217
        if (possibleOverflow) {
 
218
            qWarning() << QString("Conversion from QML %1 to %2 could overflow").arg(expectedQmlType).arg(argumentTypeName);
63
219
        }
64
220
    }
65
221
    updateAllPropertiesValid();