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/ast/type/array_type.h" 16 17 #include <cmath> 18 19 #include "src/ast/stride_decoration.h" 20 #include "src/ast/type/vector_type.h" 21 22 namespace tint { 23 namespace ast { 24 namespace type { 25 ArrayType(Type * subtype)26ArrayType::ArrayType(Type* subtype) : subtype_(subtype) {} 27 ArrayType(Type * subtype,uint32_t size)28ArrayType::ArrayType(Type* subtype, uint32_t size) 29 : subtype_(subtype), size_(size) {} 30 31 ArrayType::ArrayType(ArrayType&&) = default; 32 33 ArrayType::~ArrayType() = default; 34 IsArray() const35bool ArrayType::IsArray() const { 36 return true; 37 } 38 MinBufferBindingSize(MemoryLayout mem_layout) const39uint64_t ArrayType::MinBufferBindingSize(MemoryLayout mem_layout) const { 40 if (!has_array_stride()) { 41 // Arrays in buffers are required to have a stride. 42 return 0; 43 } 44 45 if (IsRuntimeArray()) { 46 // WebGPU spec 10.1.2: 47 // If the last field of the corresponding structure defined in the shader 48 // has an unbounded array type, then the value of minBufferBindingSize must 49 // be greater than or equal to the byte offset of that field plus the stride 50 // of the unbounded array 51 return array_stride(); 52 } else { 53 // Not including the padding for the last element 54 return (size_ - 1) * array_stride() + 55 subtype_->MinBufferBindingSize(mem_layout); 56 } 57 } 58 BaseAlignment(MemoryLayout mem_layout) const59uint64_t ArrayType::BaseAlignment(MemoryLayout mem_layout) const { 60 if (mem_layout == MemoryLayout::kUniformBuffer) { 61 float aligment = 16; // for a vec4 62 float unaligned = static_cast<float>(subtype_->BaseAlignment(mem_layout)); 63 return static_cast<uint64_t>(aligment * std::ceil(unaligned / aligment)); 64 } else if (mem_layout == MemoryLayout::kStorageBuffer) { 65 return subtype_->BaseAlignment(mem_layout); 66 } 67 return 0; 68 } 69 array_stride() const70uint32_t ArrayType::array_stride() const { 71 for (const auto& deco : decos_) { 72 if (deco->IsStride()) { 73 return deco->AsStride()->stride(); 74 } 75 } 76 return 0; 77 } 78 has_array_stride() const79bool ArrayType::has_array_stride() const { 80 for (const auto& deco : decos_) { 81 if (deco->IsStride()) { 82 return true; 83 } 84 } 85 return false; 86 } 87 type_name() const88std::string ArrayType::type_name() const { 89 assert(subtype_); 90 91 std::string type_name = "__array" + subtype_->type_name(); 92 if (!IsRuntimeArray()) 93 type_name += "_" + std::to_string(size_); 94 if (has_array_stride()) 95 type_name += "_stride_" + std::to_string(array_stride()); 96 97 return type_name; 98 } 99 100 } // namespace type 101 } // namespace ast 102 } // namespace tint 103