| 194 | } |
| 195 | |
| 196 | Status Runtime::AddProgram(const GlShader& shader, |
| 197 | const std::vector<Variable>& parameters, |
| 198 | const std::vector<Object>& objects, |
| 199 | const uint3& num_workgroups) { |
| 200 | GlProgram program; |
| 201 | RETURN_IF_ERROR(GlProgram::CreateWithShader(shader, &program)); |
| 202 | |
| 203 | for (auto& parameter : parameters) { |
| 204 | RETURN_IF_ERROR(program.SetParameter(parameter)); |
| 205 | } |
| 206 | |
| 207 | programs_.emplace_back( |
| 208 | CompiledProgramDescriptor{std::move(program), num_workgroups, {}}); |
| 209 | |
| 210 | // Create const buffers, resolve external references and collect internal |
| 211 | // buffer references. |
| 212 | for (auto& object : objects) { |
| 213 | auto& program = programs_.back(); |
| 214 | BindFunc binding_func; |
| 215 | if (IsRef(object)) { |
| 216 | // Reference object could be provided externally as a model input/output |
| 217 | // but also for debugging purposes. Otherwise all references are collected |
| 218 | // and allocated later. |
| 219 | Status status = MakeBindingFunc(object, GetRef(object), |
| 220 | *external_objects_, &binding_func); |
| 221 | if (!status.ok()) { |
| 222 | if (status.code() == StatusCode::kNotFound) { |
| 223 | program.refs.push_back(object); |
| 224 | continue; // don't add to binding. |
| 225 | } |
| 226 | return status; |
| 227 | } |
| 228 | } else { |
| 229 | // Allocate const object. |
| 230 | uint32_t id; |
| 231 | RETURN_IF_ERROR(AllocateConstObject(object, &id)); |
| 232 | RETURN_IF_ERROR( |
| 233 | MakeBindingFunc(object, id, const_objects_, &binding_func)); |
| 234 | } |
| 235 | program.bindings.push_back(std::move(binding_func)); |
| 236 | } |
| 237 | |
| 238 | // All parameters once set stay with program, therefore, we only need to keep |
| 239 | // program and bindings for execution. |
| 240 | return OkStatus(); |
| 241 | } |
| 242 | |
| 243 | Status Runtime::AllocateInternalObject(const Object& object) { |
| 244 | const ObjectRef ref = GetRef(object); |