Austin Eng | cc2516a | 2023-10-17 20:57:54 +0000 | [diff] [blame] | 1 | // Copyright 2020 The Dawn & Tint Authors |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 2 | // |
Austin Eng | cc2516a | 2023-10-17 20:57:54 +0000 | [diff] [blame] | 3 | // Redistribution and use in source and binary forms, with or without |
| 4 | // modification, are permitted provided that the following conditions are met: |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 5 | // |
Austin Eng | cc2516a | 2023-10-17 20:57:54 +0000 | [diff] [blame] | 6 | // 1. Redistributions of source code must retain the above copyright notice, this |
| 7 | // list of conditions and the following disclaimer. |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 8 | // |
Austin Eng | cc2516a | 2023-10-17 20:57:54 +0000 | [diff] [blame] | 9 | // 2. Redistributions in binary form must reproduce the above copyright notice, |
| 10 | // this list of conditions and the following disclaimer in the documentation |
| 11 | // and/or other materials provided with the distribution. |
| 12 | // |
| 13 | // 3. Neither the name of the copyright holder nor the names of its |
| 14 | // contributors may be used to endorse or promote products derived from |
| 15 | // this software without specific prior written permission. |
| 16 | // |
| 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 20 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
| 21 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 22 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| 24 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| 25 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 27 | |
dan sinclair | 99181d8 | 2023-07-20 01:14:15 +0000 | [diff] [blame] | 28 | #include "src/tint/lang/wgsl/ast/transform/first_index_offset.h" |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 29 | |
| 30 | #include <memory> |
| 31 | #include <unordered_map> |
| 32 | #include <utility> |
| 33 | |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 34 | #include "src/tint/lang/core/builtin_value.h" |
dan sinclair | ce6dffe | 2023-08-14 21:01:40 +0000 | [diff] [blame] | 35 | #include "src/tint/lang/core/fluent_types.h" |
Ben Clayton | ae18c41 | 2023-07-29 13:00:40 +0000 | [diff] [blame] | 36 | #include "src/tint/lang/wgsl/program/clone_context.h" |
dan sinclair | 96db554 | 2023-07-20 09:21:10 +0000 | [diff] [blame] | 37 | #include "src/tint/lang/wgsl/program/program_builder.h" |
Ben Clayton | 915ceca | 2023-07-29 13:12:58 +0000 | [diff] [blame] | 38 | #include "src/tint/lang/wgsl/resolver/resolve.h" |
dan sinclair | d3b1369 | 2023-07-20 01:14:15 +0000 | [diff] [blame] | 39 | #include "src/tint/lang/wgsl/sem/function.h" |
| 40 | #include "src/tint/lang/wgsl/sem/member_accessor_expression.h" |
| 41 | #include "src/tint/lang/wgsl/sem/struct.h" |
| 42 | #include "src/tint/lang/wgsl/sem/variable.h" |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 43 | |
dan sinclair | ce6dffe | 2023-08-14 21:01:40 +0000 | [diff] [blame] | 44 | using namespace tint::core::fluent_types; // NOLINT |
| 45 | |
James Price | b4acbb8 | 2023-05-11 21:27:16 +0000 | [diff] [blame] | 46 | TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::FirstIndexOffset); |
| 47 | TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::FirstIndexOffset::BindingPoint); |
| 48 | TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::FirstIndexOffset::Data); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 49 | |
James Price | b4acbb8 | 2023-05-11 21:27:16 +0000 | [diff] [blame] | 50 | namespace tint::ast::transform { |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 51 | namespace { |
| 52 | |
| 53 | // Uniform buffer member names |
| 54 | constexpr char kFirstVertexName[] = "first_vertex_index"; |
| 55 | constexpr char kFirstInstanceName[] = "first_instance_index"; |
| 56 | |
Ben Clayton | 5ed5cc4 | 2023-09-22 10:31:04 +0000 | [diff] [blame] | 57 | bool ShouldRun(const Program& program) { |
| 58 | for (auto* fn : program.AST().Functions()) { |
James Price | 2b7406a | 2023-05-12 01:43:50 +0000 | [diff] [blame] | 59 | if (fn->PipelineStage() == PipelineStage::kVertex) { |
Ben Clayton | c6b3814 | 2022-11-03 08:41:19 +0000 | [diff] [blame] | 60 | return true; |
| 61 | } |
| 62 | } |
| 63 | return false; |
| 64 | } |
| 65 | |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 66 | } // namespace |
| 67 | |
| 68 | FirstIndexOffset::BindingPoint::BindingPoint() = default; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 69 | FirstIndexOffset::BindingPoint::BindingPoint(uint32_t b, uint32_t g) : binding(b), group(g) {} |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 70 | FirstIndexOffset::BindingPoint::~BindingPoint() = default; |
| 71 | |
Peng Huang | ad5a0e2 | 2023-05-31 10:09:56 +0000 | [diff] [blame] | 72 | FirstIndexOffset::Data::Data(bool has_vtx_index, bool has_inst_index) |
| 73 | : has_vertex_index(has_vtx_index), has_instance_index(has_inst_index) {} |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 74 | FirstIndexOffset::Data::Data(const Data&) = default; |
| 75 | FirstIndexOffset::Data::~Data() = default; |
| 76 | |
| 77 | FirstIndexOffset::FirstIndexOffset() = default; |
| 78 | FirstIndexOffset::~FirstIndexOffset() = default; |
| 79 | |
Ben Clayton | 5ed5cc4 | 2023-09-22 10:31:04 +0000 | [diff] [blame] | 80 | Transform::ApplyResult FirstIndexOffset::Apply(const Program& src, |
Ben Clayton | c6b3814 | 2022-11-03 08:41:19 +0000 | [diff] [blame] | 81 | const DataMap& inputs, |
| 82 | DataMap& outputs) const { |
| 83 | if (!ShouldRun(src)) { |
| 84 | return SkipTransform; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 85 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 86 | |
Ben Clayton | c6b3814 | 2022-11-03 08:41:19 +0000 | [diff] [blame] | 87 | ProgramBuilder b; |
Ben Clayton | 5ed5cc4 | 2023-09-22 10:31:04 +0000 | [diff] [blame] | 88 | program::CloneContext ctx{&b, &src, /* auto_clone_symbols */ true}; |
Ben Clayton | c6b3814 | 2022-11-03 08:41:19 +0000 | [diff] [blame] | 89 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 90 | // Get the uniform buffer binding point |
| 91 | uint32_t ub_binding = binding_; |
| 92 | uint32_t ub_group = group_; |
| 93 | if (auto* binding_point = inputs.Get<BindingPoint>()) { |
| 94 | ub_binding = binding_point->binding; |
| 95 | ub_group = binding_point->group; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 96 | } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 97 | |
| 98 | // Map of builtin usages |
| 99 | std::unordered_map<const sem::Variable*, const char*> builtin_vars; |
dan sinclair | cedcdf3 | 2023-08-10 02:39:48 +0000 | [diff] [blame] | 100 | std::unordered_map<const core::type::StructMember*, const char*> builtin_members; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 101 | |
Peng Huang | ad5a0e2 | 2023-05-31 10:09:56 +0000 | [diff] [blame] | 102 | bool has_vertex_index = false; |
| 103 | bool has_instance_index = false; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 104 | |
| 105 | // Traverse the AST scanning for builtin accesses via variables (includes |
| 106 | // parameters) or structure member accesses. |
| 107 | for (auto* node : ctx.src->ASTNodes().Objects()) { |
James Price | 2b7406a | 2023-05-12 01:43:50 +0000 | [diff] [blame] | 108 | if (auto* var = node->As<Variable>()) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 109 | for (auto* attr : var->attributes) { |
James Price | 2b7406a | 2023-05-12 01:43:50 +0000 | [diff] [blame] | 110 | if (auto* builtin_attr = attr->As<BuiltinAttribute>()) { |
Ben Clayton | 5ed5cc4 | 2023-09-22 10:31:04 +0000 | [diff] [blame] | 111 | core::BuiltinValue builtin = src.Sem().Get(builtin_attr)->Value(); |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 112 | if (builtin == core::BuiltinValue::kVertexIndex) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 113 | auto* sem_var = ctx.src->Sem().Get(var); |
| 114 | builtin_vars.emplace(sem_var, kFirstVertexName); |
Peng Huang | ad5a0e2 | 2023-05-31 10:09:56 +0000 | [diff] [blame] | 115 | has_vertex_index = true; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 116 | } |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 117 | if (builtin == core::BuiltinValue::kInstanceIndex) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 118 | auto* sem_var = ctx.src->Sem().Get(var); |
| 119 | builtin_vars.emplace(sem_var, kFirstInstanceName); |
Peng Huang | ad5a0e2 | 2023-05-31 10:09:56 +0000 | [diff] [blame] | 120 | has_instance_index = true; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 121 | } |
| 122 | } |
| 123 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 124 | } |
James Price | 2b7406a | 2023-05-12 01:43:50 +0000 | [diff] [blame] | 125 | if (auto* member = node->As<StructMember>()) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 126 | for (auto* attr : member->attributes) { |
James Price | 2b7406a | 2023-05-12 01:43:50 +0000 | [diff] [blame] | 127 | if (auto* builtin_attr = attr->As<BuiltinAttribute>()) { |
Ben Clayton | 5ed5cc4 | 2023-09-22 10:31:04 +0000 | [diff] [blame] | 128 | core::BuiltinValue builtin = src.Sem().Get(builtin_attr)->Value(); |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 129 | if (builtin == core::BuiltinValue::kVertexIndex) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 130 | auto* sem_mem = ctx.src->Sem().Get(member); |
| 131 | builtin_members.emplace(sem_mem, kFirstVertexName); |
Peng Huang | ad5a0e2 | 2023-05-31 10:09:56 +0000 | [diff] [blame] | 132 | has_vertex_index = true; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 133 | } |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 134 | if (builtin == core::BuiltinValue::kInstanceIndex) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 135 | auto* sem_mem = ctx.src->Sem().Get(member); |
| 136 | builtin_members.emplace(sem_mem, kFirstInstanceName); |
Peng Huang | ad5a0e2 | 2023-05-31 10:09:56 +0000 | [diff] [blame] | 137 | has_instance_index = true; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 138 | } |
| 139 | } |
| 140 | } |
| 141 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 142 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 143 | |
Peng Huang | ad5a0e2 | 2023-05-31 10:09:56 +0000 | [diff] [blame] | 144 | if (has_vertex_index || has_instance_index) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 145 | // Add uniform buffer members and calculate byte offsets |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 146 | tint::Vector<const StructMember*, 8> members; |
Ben Clayton | c6b3814 | 2022-11-03 08:41:19 +0000 | [diff] [blame] | 147 | members.Push(b.Member(kFirstVertexName, b.ty.u32())); |
| 148 | members.Push(b.Member(kFirstInstanceName, b.ty.u32())); |
| 149 | auto* struct_ = b.Structure(b.Sym(), std::move(members)); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 150 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 151 | // Create a global to hold the uniform buffer |
Ben Clayton | c6b3814 | 2022-11-03 08:41:19 +0000 | [diff] [blame] | 152 | Symbol buffer_name = b.Sym(); |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 153 | b.GlobalVar(buffer_name, b.ty.Of(struct_), core::AddressSpace::kUniform, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 154 | tint::Vector{ |
Ben Clayton | c6b3814 | 2022-11-03 08:41:19 +0000 | [diff] [blame] | 155 | b.Binding(AInt(ub_binding)), |
| 156 | b.Group(AInt(ub_group)), |
| 157 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 158 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 159 | // Fix up all references to the builtins with the offsets |
James Price | 2b7406a | 2023-05-12 01:43:50 +0000 | [diff] [blame] | 160 | ctx.ReplaceAll([=, &ctx](const Expression* expr) -> const Expression* { |
Ben Clayton | 0b4a2f1 | 2023-02-05 22:59:40 +0000 | [diff] [blame] | 161 | if (auto* sem = ctx.src->Sem().GetVal(expr)) { |
Ben Clayton | 2f9a988 | 2022-12-17 02:20:04 +0000 | [diff] [blame] | 162 | if (auto* user = sem->UnwrapLoad()->As<sem::VariableUser>()) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 163 | auto it = builtin_vars.find(user->Variable()); |
| 164 | if (it != builtin_vars.end()) { |
| 165 | return ctx.dst->Add(ctx.CloneWithoutTransform(expr), |
| 166 | ctx.dst->MemberAccessor(buffer_name, it->second)); |
| 167 | } |
| 168 | } |
| 169 | if (auto* access = sem->As<sem::StructMemberAccess>()) { |
| 170 | auto it = builtin_members.find(access->Member()); |
| 171 | if (it != builtin_members.end()) { |
| 172 | return ctx.dst->Add(ctx.CloneWithoutTransform(expr), |
| 173 | ctx.dst->MemberAccessor(buffer_name, it->second)); |
| 174 | } |
| 175 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 176 | } |
Ben Clayton | b90b6bf | 2022-08-23 16:23:05 +0000 | [diff] [blame] | 177 | // Not interested in this expression. Just clone. |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 178 | return nullptr; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 179 | }); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 180 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 181 | |
Peng Huang | ad5a0e2 | 2023-05-31 10:09:56 +0000 | [diff] [blame] | 182 | outputs.Add<Data>(has_vertex_index, has_instance_index); |
Ben Clayton | c6b3814 | 2022-11-03 08:41:19 +0000 | [diff] [blame] | 183 | |
| 184 | ctx.Clone(); |
Ben Clayton | 915ceca | 2023-07-29 13:12:58 +0000 | [diff] [blame] | 185 | return resolver::Resolve(b); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 186 | } |
| 187 | |
James Price | b4acbb8 | 2023-05-11 21:27:16 +0000 | [diff] [blame] | 188 | } // namespace tint::ast::transform |