215 lines
7.7 KiB
C++
215 lines
7.7 KiB
C++
// Copyright 2021 The Tint Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#ifndef FUZZERS_TRANSFORM_BUILDER_H_
|
|
#define FUZZERS_TRANSFORM_BUILDER_H_
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "include/tint/tint.h"
|
|
|
|
#include "fuzzers/data_builder.h"
|
|
|
|
namespace tint {
|
|
namespace fuzzers {
|
|
|
|
/// Fuzzer utility class to build inputs for transforms and setup the transform
|
|
/// manager.
|
|
class TransformBuilder {
|
|
public:
|
|
/// @brief Initializes the internal builder using a seed value
|
|
/// @param seed - seed value passed to engine
|
|
explicit TransformBuilder(uint64_t seed) : builder_(seed) {}
|
|
|
|
/// @brief Initializes the internal builder using seed data
|
|
/// @param data - data fuzzer to calculate seed from
|
|
/// @param size - size of data buffer
|
|
explicit TransformBuilder(const uint8_t* data, size_t size)
|
|
: builder_(data, size) {
|
|
assert(data != nullptr && "|data| must be !nullptr");
|
|
}
|
|
|
|
~TransformBuilder() = default;
|
|
|
|
transform::Manager* manager() { return &manager_; }
|
|
transform::DataMap* data_map() { return &data_map_; }
|
|
|
|
/// Adds a transform and needed data to |manager_| and |data_map_|.
|
|
/// @tparam T - A class that inherits from transform::Transform and has an
|
|
/// explicit specialization in AddTransformImpl.
|
|
template <typename T>
|
|
void AddTransform() {
|
|
static_assert(std::is_base_of<transform::Transform, T>::value,
|
|
"T is not a transform::Transform");
|
|
AddTransformImpl<T>::impl(this);
|
|
}
|
|
|
|
/// Helper that invokes Add*Transform for all of the platform independent
|
|
/// passes.
|
|
void AddPlatformIndependentPasses() {
|
|
AddTransform<transform::Robustness>();
|
|
AddTransform<transform::FirstIndexOffset>();
|
|
AddTransform<transform::BindingRemapper>();
|
|
AddTransform<transform::Renamer>();
|
|
AddTransform<transform::SingleEntryPoint>();
|
|
AddTransform<transform::VertexPulling>();
|
|
}
|
|
|
|
private:
|
|
DataBuilder builder_;
|
|
transform::Manager manager_;
|
|
transform::DataMap data_map_;
|
|
|
|
DataBuilder* builder() { return &builder_; }
|
|
|
|
/// Implementation of AddTransform, specialized for each transform that is
|
|
/// implemented. Default implementation intentionally deleted to cause compile
|
|
/// error if unimplemented type passed in.
|
|
/// @tparam T - A fuzzer transform
|
|
template <typename T>
|
|
struct AddTransformImpl;
|
|
|
|
/// Implementation of AddTransform for transform::Robustness
|
|
template <>
|
|
struct AddTransformImpl<transform::Robustness> {
|
|
/// Add instance of transform::Robustness to TransformBuilder
|
|
/// @param tb - TransformBuilder to add transform to
|
|
static void impl(TransformBuilder* tb) {
|
|
tb->manager()->Add<transform::Robustness>();
|
|
}
|
|
};
|
|
|
|
/// Implementation of AddTransform for transform::FirstIndexOffset
|
|
template <>
|
|
struct AddTransformImpl<transform::FirstIndexOffset> {
|
|
/// Add instance of transform::FirstIndexOffset to TransformBuilder
|
|
/// @param tb - TransformBuilder to add transform to
|
|
static void impl(TransformBuilder* tb) {
|
|
struct Config {
|
|
uint32_t group;
|
|
uint32_t binding;
|
|
};
|
|
|
|
Config config = tb->builder()->build<Config>();
|
|
|
|
tb->data_map()->Add<tint::transform::FirstIndexOffset::BindingPoint>(
|
|
config.binding, config.group);
|
|
tb->manager()->Add<transform::FirstIndexOffset>();
|
|
}
|
|
};
|
|
|
|
/// Implementation of AddTransform for transform::BindingRemapper
|
|
template <>
|
|
struct AddTransformImpl<transform::BindingRemapper> {
|
|
/// Add instance of transform::BindingRemapper to TransformBuilder
|
|
/// @param tb - TransformBuilder to add transform to
|
|
static void impl(TransformBuilder* tb) {
|
|
struct Config {
|
|
uint8_t old_group;
|
|
uint8_t old_binding;
|
|
uint8_t new_group;
|
|
uint8_t new_binding;
|
|
ast::Access new_access;
|
|
};
|
|
|
|
std::vector<Config> configs = tb->builder()->vector<Config>();
|
|
transform::BindingRemapper::BindingPoints binding_points;
|
|
transform::BindingRemapper::AccessControls accesses;
|
|
for (const auto& config : configs) {
|
|
binding_points[{config.old_binding, config.old_group}] = {
|
|
config.new_binding, config.new_group};
|
|
accesses[{config.old_binding, config.old_group}] = config.new_access;
|
|
}
|
|
|
|
tb->data_map()->Add<transform::BindingRemapper::Remappings>(
|
|
binding_points, accesses, tb->builder()->build<bool>());
|
|
tb->manager()->Add<transform::BindingRemapper>();
|
|
}
|
|
};
|
|
|
|
/// Implementation of AddTransform for transform::Renamer
|
|
template <>
|
|
struct AddTransformImpl<transform::Renamer> {
|
|
/// Add instance of transform::Renamer to TransformBuilder
|
|
/// @param tb - TransformBuilder to add transform to
|
|
static void impl(TransformBuilder* tb) {
|
|
tb->manager()->Add<transform::Renamer>();
|
|
}
|
|
};
|
|
|
|
/// Implementation of AddTransform for transform::SingleEntryPoint
|
|
template <>
|
|
struct AddTransformImpl<transform::SingleEntryPoint> {
|
|
/// Add instance of transform::SingleEntryPoint to TransformBuilder
|
|
/// @param tb - TransformBuilder to add transform to
|
|
static void impl(TransformBuilder* tb) {
|
|
auto input = tb->builder()->build<std::string>();
|
|
transform::SingleEntryPoint::Config cfg(input);
|
|
|
|
tb->data_map()->Add<transform::SingleEntryPoint::Config>(cfg);
|
|
tb->manager()->Add<transform::SingleEntryPoint>();
|
|
}
|
|
}; // struct AddTransformImpl<transform::SingleEntryPoint>
|
|
|
|
/// Implementation of AddTransform for transform::VertexPulling
|
|
template <>
|
|
struct AddTransformImpl<transform::VertexPulling> {
|
|
/// Add instance of transform::VertexPulling to TransformBuilder
|
|
/// @param tb - TransformBuilder to add transform to
|
|
static void impl(TransformBuilder* tb) {
|
|
transform::VertexPulling::Config cfg;
|
|
cfg.entry_point_name = tb->builder()->build<std::string>();
|
|
cfg.vertex_state =
|
|
tb->builder()->vector<transform::VertexBufferLayoutDescriptor>(
|
|
GenerateVertexBufferLayoutDescriptor);
|
|
cfg.pulling_group = tb->builder()->build<uint32_t>();
|
|
|
|
tb->data_map()->Add<transform::VertexPulling::Config>(cfg);
|
|
tb->manager()->Add<transform::VertexPulling>();
|
|
}
|
|
|
|
private:
|
|
/// Generate an instance of transform::VertexAttributeDescriptor
|
|
/// @param b - DataBuilder to use
|
|
static transform::VertexAttributeDescriptor
|
|
GenerateVertexAttributeDescriptor(DataBuilder* b) {
|
|
transform::VertexAttributeDescriptor desc{};
|
|
desc.format = b->enum_class<transform::VertexFormat>(
|
|
static_cast<uint8_t>(transform::VertexFormat::kLastEntry) + 1);
|
|
desc.offset = b->build<uint32_t>();
|
|
desc.shader_location = b->build<uint32_t>();
|
|
return desc;
|
|
}
|
|
|
|
/// Generate an instance of VertexBufferLayoutDescriptor
|
|
/// @param b - DataBuilder to use
|
|
static transform::VertexBufferLayoutDescriptor
|
|
GenerateVertexBufferLayoutDescriptor(DataBuilder* b) {
|
|
transform::VertexBufferLayoutDescriptor desc;
|
|
desc.array_stride = b->build<uint32_t>();
|
|
desc.step_mode = b->enum_class<transform::VertexStepMode>(
|
|
static_cast<uint8_t>(transform::VertexStepMode::kLastEntry) + 1);
|
|
desc.attributes = b->vector<transform::VertexAttributeDescriptor>(
|
|
GenerateVertexAttributeDescriptor);
|
|
return desc;
|
|
}
|
|
};
|
|
}; // class TransformBuilder
|
|
|
|
} // namespace fuzzers
|
|
} // namespace tint
|
|
|
|
#endif // FUZZERS_TRANSFORM_BUILDER_H_
|