Enrico Galli | 3d449d2 | 2020-12-08 21:07:24 +0000 | [diff] [blame] | 1 | // Copyright 2020 The Tint Authors. |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | #include "src/transform/first_index_offset.h" |
| 16 | |
Ben Clayton | eb496d0 | 2021-02-24 15:55:24 +0000 | [diff] [blame] | 17 | #include <memory> |
Ben Clayton | 1d618b1 | 2021-04-09 16:19:48 +0000 | [diff] [blame] | 18 | #include <unordered_map> |
Enrico Galli | 3d449d2 | 2020-12-08 21:07:24 +0000 | [diff] [blame] | 19 | #include <utility> |
| 20 | |
Ben Clayton | a6b9a8e | 2021-01-26 16:57:10 +0000 | [diff] [blame] | 21 | #include "src/program_builder.h" |
Antonio Maiorano | 5cd71b8 | 2021-04-16 19:07:51 +0000 | [diff] [blame] | 22 | #include "src/sem/function.h" |
| 23 | #include "src/sem/member_accessor_expression.h" |
| 24 | #include "src/sem/struct.h" |
| 25 | #include "src/sem/variable.h" |
Enrico Galli | 3d449d2 | 2020-12-08 21:07:24 +0000 | [diff] [blame] | 26 | |
Ben Clayton | b5cd10c | 2021-06-25 10:26:26 +0000 | [diff] [blame] | 27 | TINT_INSTANTIATE_TYPEINFO(tint::transform::FirstIndexOffset); |
Ben Clayton | 1d618b1 | 2021-04-09 16:19:48 +0000 | [diff] [blame] | 28 | TINT_INSTANTIATE_TYPEINFO(tint::transform::FirstIndexOffset::BindingPoint); |
Ben Clayton | 7732ca5 | 2021-03-02 20:51:18 +0000 | [diff] [blame] | 29 | TINT_INSTANTIATE_TYPEINFO(tint::transform::FirstIndexOffset::Data); |
Ben Clayton | eb496d0 | 2021-02-24 15:55:24 +0000 | [diff] [blame] | 30 | |
Enrico Galli | 3d449d2 | 2020-12-08 21:07:24 +0000 | [diff] [blame] | 31 | namespace tint { |
| 32 | namespace transform { |
| 33 | namespace { |
| 34 | |
Ben Clayton | 1d618b1 | 2021-04-09 16:19:48 +0000 | [diff] [blame] | 35 | // Uniform buffer member names |
| 36 | constexpr char kFirstVertexName[] = "first_vertex_index"; |
| 37 | constexpr char kFirstInstanceName[] = "first_instance_index"; |
Ben Clayton | 3a7bba8 | 2020-12-10 17:47:41 +0000 | [diff] [blame] | 38 | |
Enrico Galli | 3d449d2 | 2020-12-08 21:07:24 +0000 | [diff] [blame] | 39 | } // namespace |
| 40 | |
Ben Clayton | 1d618b1 | 2021-04-09 16:19:48 +0000 | [diff] [blame] | 41 | FirstIndexOffset::BindingPoint::BindingPoint() = default; |
| 42 | FirstIndexOffset::BindingPoint::BindingPoint(uint32_t b, uint32_t g) |
| 43 | : binding(b), group(g) {} |
| 44 | FirstIndexOffset::BindingPoint::~BindingPoint() = default; |
| 45 | |
Ben Clayton | eb496d0 | 2021-02-24 15:55:24 +0000 | [diff] [blame] | 46 | FirstIndexOffset::Data::Data(bool has_vtx_index, |
| 47 | bool has_inst_index, |
| 48 | uint32_t first_vtx_offset, |
Ben Clayton | c1f7e90 | 2021-02-25 14:11:50 +0000 | [diff] [blame] | 49 | uint32_t first_inst_offset) |
Ben Clayton | eb496d0 | 2021-02-24 15:55:24 +0000 | [diff] [blame] | 50 | : has_vertex_index(has_vtx_index), |
| 51 | has_instance_index(has_inst_index), |
| 52 | first_vertex_offset(first_vtx_offset), |
Ben Clayton | c1f7e90 | 2021-02-25 14:11:50 +0000 | [diff] [blame] | 53 | first_instance_offset(first_inst_offset) {} |
Ben Clayton | eb496d0 | 2021-02-24 15:55:24 +0000 | [diff] [blame] | 54 | FirstIndexOffset::Data::Data(const Data&) = default; |
Ben Clayton | eb496d0 | 2021-02-24 15:55:24 +0000 | [diff] [blame] | 55 | FirstIndexOffset::Data::~Data() = default; |
| 56 | |
Ben Clayton | 1d618b1 | 2021-04-09 16:19:48 +0000 | [diff] [blame] | 57 | FirstIndexOffset::FirstIndexOffset() = default; |
Enrico Galli | 3d449d2 | 2020-12-08 21:07:24 +0000 | [diff] [blame] | 58 | FirstIndexOffset::~FirstIndexOffset() = default; |
| 59 | |
Ben Clayton | 800b8e3 | 2022-01-25 21:36:04 +0000 | [diff] [blame] | 60 | bool FirstIndexOffset::ShouldRun(const Program* program, const DataMap&) const { |
| 61 | for (auto* fn : program->AST().Functions()) { |
| 62 | if (fn->PipelineStage() == ast::PipelineStage::kVertex) { |
| 63 | return true; |
| 64 | } |
| 65 | } |
| 66 | return false; |
| 67 | } |
| 68 | |
Ben Clayton | b5cd10c | 2021-06-25 10:26:26 +0000 | [diff] [blame] | 69 | void FirstIndexOffset::Run(CloneContext& ctx, |
| 70 | const DataMap& inputs, |
Ben Clayton | 12d54d7 | 2022-01-25 20:53:25 +0000 | [diff] [blame] | 71 | DataMap& outputs) const { |
Ben Clayton | 1d618b1 | 2021-04-09 16:19:48 +0000 | [diff] [blame] | 72 | // Get the uniform buffer binding point |
| 73 | uint32_t ub_binding = binding_; |
| 74 | uint32_t ub_group = group_; |
Ben Clayton | b5cd10c | 2021-06-25 10:26:26 +0000 | [diff] [blame] | 75 | if (auto* binding_point = inputs.Get<BindingPoint>()) { |
Ben Clayton | 1d618b1 | 2021-04-09 16:19:48 +0000 | [diff] [blame] | 76 | ub_binding = binding_point->binding; |
| 77 | ub_group = binding_point->group; |
Ben Clayton | 3a7bba8 | 2020-12-10 17:47:41 +0000 | [diff] [blame] | 78 | } |
Enrico Galli | 3d449d2 | 2020-12-08 21:07:24 +0000 | [diff] [blame] | 79 | |
Ben Clayton | 1d618b1 | 2021-04-09 16:19:48 +0000 | [diff] [blame] | 80 | // Map of builtin usages |
Antonio Maiorano | 5cd71b8 | 2021-04-16 19:07:51 +0000 | [diff] [blame] | 81 | std::unordered_map<const sem::Variable*, const char*> builtin_vars; |
| 82 | std::unordered_map<const sem::StructMember*, const char*> builtin_members; |
Ben Clayton | 1d618b1 | 2021-04-09 16:19:48 +0000 | [diff] [blame] | 83 | |
| 84 | bool has_vertex_index = false; |
| 85 | bool has_instance_index = false; |
| 86 | |
| 87 | // Traverse the AST scanning for builtin accesses via variables (includes |
| 88 | // parameters) or structure member accesses. |
Ben Clayton | b5cd10c | 2021-06-25 10:26:26 +0000 | [diff] [blame] | 89 | for (auto* node : ctx.src->ASTNodes().Objects()) { |
Ben Clayton | 1d618b1 | 2021-04-09 16:19:48 +0000 | [diff] [blame] | 90 | if (auto* var = node->As<ast::Variable>()) { |
Ben Clayton | a996ffb | 2022-02-02 23:07:11 +0000 | [diff] [blame] | 91 | for (auto* attr : var->attributes) { |
| 92 | if (auto* builtin_attr = attr->As<ast::BuiltinAttribute>()) { |
| 93 | ast::Builtin builtin = builtin_attr->builtin; |
Ben Clayton | 1d618b1 | 2021-04-09 16:19:48 +0000 | [diff] [blame] | 94 | if (builtin == ast::Builtin::kVertexIndex) { |
| 95 | auto* sem_var = ctx.src->Sem().Get(var); |
| 96 | builtin_vars.emplace(sem_var, kFirstVertexName); |
| 97 | has_vertex_index = true; |
| 98 | } |
| 99 | if (builtin == ast::Builtin::kInstanceIndex) { |
| 100 | auto* sem_var = ctx.src->Sem().Get(var); |
| 101 | builtin_vars.emplace(sem_var, kFirstInstanceName); |
| 102 | has_instance_index = true; |
Ben Clayton | 1e29f4b | 2021-01-21 16:20:40 +0000 | [diff] [blame] | 103 | } |
| 104 | } |
Ben Clayton | 1d618b1 | 2021-04-09 16:19:48 +0000 | [diff] [blame] | 105 | } |
| 106 | } |
| 107 | if (auto* member = node->As<ast::StructMember>()) { |
Ben Clayton | a996ffb | 2022-02-02 23:07:11 +0000 | [diff] [blame] | 108 | for (auto* attr : member->attributes) { |
| 109 | if (auto* builtin_attr = attr->As<ast::BuiltinAttribute>()) { |
| 110 | ast::Builtin builtin = builtin_attr->builtin; |
Ben Clayton | 1d618b1 | 2021-04-09 16:19:48 +0000 | [diff] [blame] | 111 | if (builtin == ast::Builtin::kVertexIndex) { |
| 112 | auto* sem_mem = ctx.src->Sem().Get(member); |
| 113 | builtin_members.emplace(sem_mem, kFirstVertexName); |
| 114 | has_vertex_index = true; |
| 115 | } |
| 116 | if (builtin == ast::Builtin::kInstanceIndex) { |
| 117 | auto* sem_mem = ctx.src->Sem().Get(member); |
| 118 | builtin_members.emplace(sem_mem, kFirstInstanceName); |
| 119 | has_instance_index = true; |
| 120 | } |
| 121 | } |
| 122 | } |
| 123 | } |
| 124 | } |
| 125 | |
| 126 | // Byte offsets on the uniform buffer |
| 127 | uint32_t vertex_index_offset = 0; |
| 128 | uint32_t instance_index_offset = 0; |
| 129 | |
| 130 | if (has_vertex_index || has_instance_index) { |
| 131 | // Add uniform buffer members and calculate byte offsets |
| 132 | uint32_t offset = 0; |
| 133 | ast::StructMemberList members; |
| 134 | if (has_vertex_index) { |
| 135 | members.push_back(ctx.dst->Member(kFirstVertexName, ctx.dst->ty.u32())); |
| 136 | vertex_index_offset = offset; |
| 137 | offset += 4; |
| 138 | } |
| 139 | if (has_instance_index) { |
| 140 | members.push_back(ctx.dst->Member(kFirstInstanceName, ctx.dst->ty.u32())); |
| 141 | instance_index_offset = offset; |
| 142 | offset += 4; |
| 143 | } |
James Price | ebdfa5d | 2021-12-09 15:45:03 +0000 | [diff] [blame] | 144 | auto* struct_ = ctx.dst->Structure(ctx.dst->Sym(), std::move(members)); |
Ben Clayton | 1d618b1 | 2021-04-09 16:19:48 +0000 | [diff] [blame] | 145 | |
| 146 | // Create a global to hold the uniform buffer |
James Price | 65ae64d | 2021-04-29 12:59:14 +0000 | [diff] [blame] | 147 | Symbol buffer_name = ctx.dst->Sym(); |
Ben Clayton | 8758f10 | 2021-06-09 14:32:14 +0000 | [diff] [blame] | 148 | ctx.dst->Global(buffer_name, ctx.dst->ty.Of(struct_), |
| 149 | ast::StorageClass::kUniform, nullptr, |
Ben Clayton | a996ffb | 2022-02-02 23:07:11 +0000 | [diff] [blame] | 150 | ast::AttributeList{ |
| 151 | ctx.dst->create<ast::BindingAttribute>(ub_binding), |
| 152 | ctx.dst->create<ast::GroupAttribute>(ub_group), |
Ben Clayton | 1d618b1 | 2021-04-09 16:19:48 +0000 | [diff] [blame] | 153 | }); |
| 154 | |
| 155 | // Fix up all references to the builtins with the offsets |
Ben Clayton | 8648120 | 2021-10-19 18:38:54 +0000 | [diff] [blame] | 156 | ctx.ReplaceAll( |
| 157 | [=, &ctx](const ast::Expression* expr) -> const ast::Expression* { |
| 158 | if (auto* sem = ctx.src->Sem().Get(expr)) { |
| 159 | if (auto* user = sem->As<sem::VariableUser>()) { |
| 160 | auto it = builtin_vars.find(user->Variable()); |
| 161 | if (it != builtin_vars.end()) { |
| 162 | return ctx.dst->Add( |
| 163 | ctx.CloneWithoutTransform(expr), |
| 164 | ctx.dst->MemberAccessor(buffer_name, it->second)); |
| 165 | } |
| 166 | } |
| 167 | if (auto* access = sem->As<sem::StructMemberAccess>()) { |
| 168 | auto it = builtin_members.find(access->Member()); |
| 169 | if (it != builtin_members.end()) { |
| 170 | return ctx.dst->Add( |
| 171 | ctx.CloneWithoutTransform(expr), |
| 172 | ctx.dst->MemberAccessor(buffer_name, it->second)); |
| 173 | } |
| 174 | } |
Ben Clayton | 9481156 | 2021-04-30 10:16:45 +0000 | [diff] [blame] | 175 | } |
Ben Clayton | 8648120 | 2021-10-19 18:38:54 +0000 | [diff] [blame] | 176 | // Not interested in this experssion. Just clone. |
| 177 | return nullptr; |
| 178 | }); |
Ben Clayton | 1d618b1 | 2021-04-09 16:19:48 +0000 | [diff] [blame] | 179 | } |
| 180 | |
Ben Clayton | a8b20be | 2021-02-26 19:33:56 +0000 | [diff] [blame] | 181 | ctx.Clone(); |
Enrico Galli | 3d449d2 | 2020-12-08 21:07:24 +0000 | [diff] [blame] | 182 | |
Ben Clayton | b5cd10c | 2021-06-25 10:26:26 +0000 | [diff] [blame] | 183 | outputs.Add<Data>(has_vertex_index, has_instance_index, vertex_index_offset, |
| 184 | instance_index_offset); |
Enrico Galli | 3d449d2 | 2020-12-08 21:07:24 +0000 | [diff] [blame] | 185 | } |
| 186 | |
| 187 | } // namespace transform |
| 188 | } // namespace tint |