blob: 8ba5e476b1d0414cbdfc588ab9887a003f24f15f [file] [log] [blame]
Ryan Harrisonc57642c2021-09-30 18:58:32 +00001// Copyright 2021 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#ifndef FUZZERS_TRANSFORM_BUILDER_H_
16#define FUZZERS_TRANSFORM_BUILDER_H_
17
18#include <string>
19#include <vector>
20
21#include "include/tint/tint.h"
22
23#include "fuzzers/data_builder.h"
24
25namespace tint {
26namespace fuzzers {
27
28/// Fuzzer utility class to build inputs for transforms and setup the transform
29/// manager.
30class TransformBuilder {
31 public:
Ryan Harrisond3f628b2021-11-01 18:14:42 +000032 /// @brief Initializes the internal builder using a seed value
33 /// @param seed - seed value passed to engine
34 explicit TransformBuilder(uint64_t seed) : builder_(seed) {}
35
36 /// @brief Initializes the internal builder using seed data
37 /// @param data - data fuzzer to calculate seed from
Ryan Harrisonc57642c2021-09-30 18:58:32 +000038 /// @param size - size of data buffer
39 explicit TransformBuilder(const uint8_t* data, size_t size)
Ryan Harrisond3f628b2021-11-01 18:14:42 +000040 : builder_(data, size) {
41 assert(data != nullptr && "|data| must be !nullptr");
42 }
43
44 ~TransformBuilder() = default;
Ryan Harrisonc57642c2021-09-30 18:58:32 +000045
46 transform::Manager* manager() { return &manager_; }
47 transform::DataMap* data_map() { return &data_map_; }
Ryan Harrisonc57642c2021-09-30 18:58:32 +000048
49 /// Adds a transform and needed data to |manager_| and |data_map_|.
50 /// @tparam T - A class that inherits from transform::Transform and has an
51 /// explicit specialization in AddTransformImpl.
52 template <typename T>
53 void AddTransform() {
54 static_assert(std::is_base_of<transform::Transform, T>::value,
55 "T is not a transform::Transform");
56 AddTransformImpl<T>::impl(this);
57 }
58
59 /// Helper that invokes Add*Transform for all of the platform independent
60 /// passes.
61 void AddPlatformIndependentPasses() {
62 AddTransform<transform::Robustness>();
63 AddTransform<transform::FirstIndexOffset>();
64 AddTransform<transform::BindingRemapper>();
65 AddTransform<transform::Renamer>();
66 AddTransform<transform::SingleEntryPoint>();
67 AddTransform<transform::VertexPulling>();
68 }
69
70 private:
71 DataBuilder builder_;
72 transform::Manager manager_;
73 transform::DataMap data_map_;
74
Ryan Harrisond3f628b2021-11-01 18:14:42 +000075 DataBuilder* builder() { return &builder_; }
76
Ryan Harrisonc57642c2021-09-30 18:58:32 +000077 /// Implementation of AddTransform, specialized for each transform that is
78 /// implemented. Default implementation intentionally deleted to cause compile
79 /// error if unimplemented type passed in.
80 /// @tparam T - A fuzzer transform
81 template <typename T>
82 struct AddTransformImpl;
83
84 /// Implementation of AddTransform for transform::Robustness
85 template <>
86 struct AddTransformImpl<transform::Robustness> {
87 /// Add instance of transform::Robustness to TransformBuilder
88 /// @param tb - TransformBuilder to add transform to
89 static void impl(TransformBuilder* tb) {
90 tb->manager()->Add<transform::Robustness>();
91 }
92 };
93
94 /// Implementation of AddTransform for transform::FirstIndexOffset
95 template <>
96 struct AddTransformImpl<transform::FirstIndexOffset> {
97 /// Add instance of transform::FirstIndexOffset to TransformBuilder
98 /// @param tb - TransformBuilder to add transform to
99 static void impl(TransformBuilder* tb) {
100 struct Config {
101 uint32_t group;
102 uint32_t binding;
103 };
104
105 Config config = tb->builder()->build<Config>();
106
107 tb->data_map()->Add<tint::transform::FirstIndexOffset::BindingPoint>(
108 config.binding, config.group);
109 tb->manager()->Add<transform::FirstIndexOffset>();
110 }
111 };
112
113 /// Implementation of AddTransform for transform::BindingRemapper
114 template <>
115 struct AddTransformImpl<transform::BindingRemapper> {
116 /// Add instance of transform::BindingRemapper to TransformBuilder
117 /// @param tb - TransformBuilder to add transform to
118 static void impl(TransformBuilder* tb) {
119 struct Config {
120 uint8_t old_group;
121 uint8_t old_binding;
122 uint8_t new_group;
123 uint8_t new_binding;
124 ast::Access new_access;
125 };
126
127 std::vector<Config> configs = tb->builder()->vector<Config>();
128 transform::BindingRemapper::BindingPoints binding_points;
129 transform::BindingRemapper::AccessControls accesses;
130 for (const auto& config : configs) {
131 binding_points[{config.old_binding, config.old_group}] = {
132 config.new_binding, config.new_group};
133 accesses[{config.old_binding, config.old_group}] = config.new_access;
134 }
135
136 tb->data_map()->Add<transform::BindingRemapper::Remappings>(
137 binding_points, accesses, tb->builder()->build<bool>());
138 tb->manager()->Add<transform::BindingRemapper>();
139 }
140 };
141
142 /// Implementation of AddTransform for transform::Renamer
143 template <>
144 struct AddTransformImpl<transform::Renamer> {
145 /// Add instance of transform::Renamer to TransformBuilder
146 /// @param tb - TransformBuilder to add transform to
147 static void impl(TransformBuilder* tb) {
148 tb->manager()->Add<transform::Renamer>();
149 }
150 };
151
152 /// Implementation of AddTransform for transform::SingleEntryPoint
153 template <>
154 struct AddTransformImpl<transform::SingleEntryPoint> {
155 /// Add instance of transform::SingleEntryPoint to TransformBuilder
156 /// @param tb - TransformBuilder to add transform to
157 static void impl(TransformBuilder* tb) {
158 auto input = tb->builder()->build<std::string>();
159 transform::SingleEntryPoint::Config cfg(input);
160
161 tb->data_map()->Add<transform::SingleEntryPoint::Config>(cfg);
162 tb->manager()->Add<transform::SingleEntryPoint>();
163 }
164 }; // struct AddTransformImpl<transform::SingleEntryPoint>
165
166 /// Implementation of AddTransform for transform::VertexPulling
167 template <>
168 struct AddTransformImpl<transform::VertexPulling> {
169 /// Add instance of transform::VertexPulling to TransformBuilder
170 /// @param tb - TransformBuilder to add transform to
171 static void impl(TransformBuilder* tb) {
172 transform::VertexPulling::Config cfg;
173 cfg.entry_point_name = tb->builder()->build<std::string>();
174 cfg.vertex_state =
175 tb->builder()->vector<transform::VertexBufferLayoutDescriptor>(
176 GenerateVertexBufferLayoutDescriptor);
177 cfg.pulling_group = tb->builder()->build<uint32_t>();
178
179 tb->data_map()->Add<transform::VertexPulling::Config>(cfg);
180 tb->manager()->Add<transform::VertexPulling>();
181 }
182
183 private:
184 /// Generate an instance of transform::VertexAttributeDescriptor
185 /// @param b - DataBuilder to use
186 static transform::VertexAttributeDescriptor
187 GenerateVertexAttributeDescriptor(DataBuilder* b) {
188 transform::VertexAttributeDescriptor desc{};
189 desc.format = b->enum_class<transform::VertexFormat>(
190 static_cast<uint8_t>(transform::VertexFormat::kLastEntry) + 1);
191 desc.offset = b->build<uint32_t>();
192 desc.shader_location = b->build<uint32_t>();
193 return desc;
194 }
195
196 /// Generate an instance of VertexBufferLayoutDescriptor
197 /// @param b - DataBuilder to use
198 static transform::VertexBufferLayoutDescriptor
199 GenerateVertexBufferLayoutDescriptor(DataBuilder* b) {
200 transform::VertexBufferLayoutDescriptor desc;
201 desc.array_stride = b->build<uint32_t>();
202 desc.step_mode = b->enum_class<transform::VertexStepMode>(
203 static_cast<uint8_t>(transform::VertexStepMode::kLastEntry) + 1);
204 desc.attributes = b->vector<transform::VertexAttributeDescriptor>(
205 GenerateVertexAttributeDescriptor);
206 return desc;
207 }
208 };
209}; // class TransformBuilder
210
211} // namespace fuzzers
212} // namespace tint
213
214#endif // FUZZERS_TRANSFORM_BUILDER_H_