| 103 | } |
| 104 | |
| 105 | Status Compile(const GraphFloat32& graph, |
| 106 | const std::unordered_set<int>& tflite_graph_io, |
| 107 | const ShaderCodeCallback& callback) final { |
| 108 | // It is important to have ids in a compiled graph identical to the given |
| 109 | // graph. |
| 110 | RETURN_IF_ERROR(graph.MakeExactCopy(&compiled_graph_)); |
| 111 | |
| 112 | // Clear out batch dimension for dynamic batch support. |
| 113 | if (options_.dynamic_batch) { |
| 114 | for (auto value : compiled_graph_.values()) { |
| 115 | value->tensor.shape.b = 1; |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | // Generate a shader for a node and all input/output objects. |
| 120 | for (auto node : compiled_graph_.nodes()) { |
| 121 | CompiledNodeAttributes attr; |
| 122 | attr.node_indices.push_back(node->id); |
| 123 | RETURN_IF_ERROR(node_shader_.GenerateCode( |
| 124 | {&compiled_graph_, &gpu_info_, node, options_}, &attr.code)); |
| 125 | node->operation.attributes = std::move(attr); |
| 126 | } |
| 127 | |
| 128 | ModelTransformer transformer(&compiled_graph_, nullptr); |
| 129 | if (options_.fuse_operations) { |
| 130 | FuseAutoOutputWithInline fuse_inline; |
| 131 | if (!transformer.Apply("fuse_auto_with_inline", &fuse_inline)) { |
| 132 | return InternalError("fuse_auto_with_inline failed"); |
| 133 | } |
| 134 | FuseInplaceUpdate fuse_inplace; |
| 135 | if (!transformer.Apply("fuse_inplace_update", &fuse_inplace)) { |
| 136 | return InternalError("fuse_inplace failed"); |
| 137 | } |
| 138 | if (options_.auto_input_fusion) { |
| 139 | FuseAutoInput fuse_auto_input; |
| 140 | if (!transformer.Apply("fuse_auto_input", &fuse_auto_input)) { |
| 141 | return InternalError("fuse_auto_input failed"); |
| 142 | } |
| 143 | } |
| 144 | } |
| 145 | RemoveUnusedInplaceUpdates remove_inplace_updates; |
| 146 | if (!transformer.Apply("remove_inplace_updates", &remove_inplace_updates)) { |
| 147 | return InternalError("remove_inplace_updates failed"); |
| 148 | } |
| 149 | |
| 150 | // Prepare internal objects. |
| 151 | std::unordered_map<ValueId, Object> objects; |
| 152 | for (auto value : compiled_graph_.values()) { |
| 153 | Object object = MakePHWC4Ref(value->id, value->tensor.shape); |
| 154 | object.data_type = value->tensor.type; |
| 155 | // External references may not be upgraded to f16 nor be represented as |
| 156 | // textures. |
| 157 | const bool is_external = |
| 158 | graph.IsGraphInput(value->id) || graph.IsGraphOutput(value->id) || |
| 159 | tflite_graph_io.find(value->tensor.ref) != tflite_graph_io.end(); |
| 160 | if (is_external) { |
| 161 | object.object_type = ObjectType::BUFFER; |
| 162 | } else if (options_.allow_precision_loss) { |
no test coverage detected