| 161 | } |
| 162 | |
| 163 | void CheckLayouts() { |
| 164 | // Here we check if the set of accesses we have collected form a sequence |
| 165 | // we could declare as a struct, meaning they are properly aligned, |
| 166 | // contiguous, and have no overlaps between different types and sizes. |
| 167 | // We do this because an int access of size 2 at offset 0 followed by |
| 168 | // a float access of size 4 at offset 4 can compactly represented as a |
| 169 | // struct { short, float }, whereas something that reads from overlapping |
| 170 | // or discontinuous offsets would need a more complicated syntax that |
| 171 | // involves explicit offsets. |
| 172 | // We assume that the bulk of memory accesses are of this very regular kind, |
| 173 | // so we choose not to even emit struct layouts for irregular ones, |
| 174 | // given that they are rare and confusing, and thus do not benefit from |
| 175 | // being represented as if they were structs. |
| 176 | for (auto& var : vars) { |
| 177 | if (var.second.accesses.size() == 1) { |
| 178 | // If we have just one access, this is better represented as a pointer |
| 179 | // than a struct. |
| 180 | var.second.struct_layout = false; |
| 181 | continue; |
| 182 | } |
| 183 | uint64_t cur_offset = 0; |
| 184 | uint32_t idx = 0; |
| 185 | for (auto& access : var.second.accesses) { |
| 186 | access.second.idx = idx++; |
| 187 | if (!access.second.is_uniform) { |
| 188 | var.second.struct_layout = false; |
| 189 | break; |
| 190 | } |
| 191 | // Align to next access: all elements are expected to be aligned to |
| 192 | // a memory address thats a multiple of their own size. |
| 193 | auto mask = static_cast<uint64_t>(access.second.byte_size - 1); |
| 194 | cur_offset = (cur_offset + mask) & ~mask; |
| 195 | if (cur_offset != access.first) { |
| 196 | var.second.struct_layout = false; |
| 197 | break; |
| 198 | } |
| 199 | cur_offset += access.second.byte_size; |
| 200 | } |
| 201 | } |
| 202 | } |
| 203 | |
| 204 | std::string IdxToName(uint32_t idx) const { |
| 205 | return IndexToAlphaName(idx); // TODO: more descriptive names? |