Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1 | // 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 | #include "src/tint/fuzzers/tint_common_fuzzer.h" |
| 16 | |
dan sinclair | 5ab6dcb | 2023-03-23 19:35:02 +0000 | [diff] [blame] | 17 | #include <algorithm> |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 18 | #include <cassert> |
| 19 | #include <cstring> |
| 20 | #include <fstream> |
dan sinclair | 6cc183c | 2023-03-02 21:28:45 +0000 | [diff] [blame] | 21 | #include <iostream> |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 22 | #include <memory> |
| 23 | #include <sstream> |
| 24 | #include <string> |
dan sinclair | 5ab6dcb | 2023-03-23 19:35:02 +0000 | [diff] [blame] | 25 | #include <unordered_map> |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 26 | #include <utility> |
| 27 | #include <vector> |
| 28 | |
Austin Eng | 142bddf | 2023-03-07 09:27:45 +0000 | [diff] [blame] | 29 | #if TINT_BUILD_SPV_READER || TINT_BUILD_SPV_WRITER |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 30 | #include "spirv-tools/libspirv.hpp" |
Austin Eng | 142bddf | 2023-03-07 09:27:45 +0000 | [diff] [blame] | 31 | #endif // TINT_BUILD_SPV_READER || TINT_BUILD_SPV_WRITER |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 32 | |
| 33 | #include "src/tint/ast/module.h" |
| 34 | #include "src/tint/diagnostic/formatter.h" |
| 35 | #include "src/tint/program.h" |
dan sinclair | 5ab6dcb | 2023-03-23 19:35:02 +0000 | [diff] [blame] | 36 | #include "src/tint/sem/binding_point.h" |
| 37 | #include "src/tint/sem/variable.h" |
| 38 | #include "src/tint/type/external_texture.h" |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 39 | #include "src/tint/utils/hash.h" |
Antonio Maiorano | 4e98fb0 | 2022-05-02 19:49:19 +0000 | [diff] [blame] | 40 | #include "src/tint/writer/flatten_bindings.h" |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 41 | |
dan sinclair | 62a1d71 | 2022-04-07 17:46:04 +0000 | [diff] [blame] | 42 | namespace tint::fuzzers { |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 43 | |
| 44 | namespace { |
| 45 | |
| 46 | // A macro is used to avoid FATAL_ERROR creating its own stack frame. This leads |
| 47 | // to better de-duplication of bug reports, because ClusterFuzz only uses the |
| 48 | // top few stack frames for de-duplication, and a FATAL_ERROR stack frame |
| 49 | // provides no useful information. |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 50 | #define FATAL_ERROR(diags, msg_string) \ |
| 51 | do { \ |
| 52 | std::string msg = msg_string; \ |
| 53 | auto printer = tint::diag::Printer::create(stderr, true); \ |
| 54 | if (!msg.empty()) { \ |
| 55 | printer->write(msg + "\n", {diag::Color::kRed, true}); \ |
| 56 | } \ |
| 57 | tint::diag::Formatter().format(diags, printer.get()); \ |
| 58 | __builtin_trap(); \ |
| 59 | } while (false) |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 60 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 61 | [[noreturn]] void TintInternalCompilerErrorReporter(const tint::diag::List& diagnostics) { |
| 62 | FATAL_ERROR(diagnostics, ""); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 63 | } |
| 64 | |
| 65 | // Wrapping in a macro, so it can be a one-liner in the code, but not |
| 66 | // introduce another level in the stack trace. This will help with de-duping |
| 67 | // ClusterFuzz issues. |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 68 | #define CHECK_INSPECTOR(program, inspector) \ |
| 69 | do { \ |
| 70 | if ((inspector).has_error()) { \ |
| 71 | if (!enforce_validity) { \ |
| 72 | return; \ |
| 73 | } \ |
| 74 | FATAL_ERROR((program)->Diagnostics(), "Inspector failed: " + (inspector).error()); \ |
| 75 | } \ |
| 76 | } while (false) |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 77 | |
| 78 | // Wrapping in a macro to make code more readable and help with issue de-duping. |
| 79 | #define VALIDITY_ERROR(diags, msg_string) \ |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 80 | do { \ |
| 81 | if (!enforce_validity) { \ |
| 82 | return 0; \ |
| 83 | } \ |
| 84 | FATAL_ERROR(diags, msg_string); \ |
| 85 | } while (false) |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 86 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 87 | bool SPIRVToolsValidationCheck(const tint::Program& program, const std::vector<uint32_t>& spirv) { |
| 88 | spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_1); |
| 89 | const tint::diag::List& diags = program.Diagnostics(); |
| 90 | tools.SetMessageConsumer( |
| 91 | [diags](spv_message_level_t, const char*, const spv_position_t& pos, const char* msg) { |
| 92 | std::stringstream out; |
| 93 | out << "Unexpected spirv-val error:\n" |
| 94 | << (pos.line + 1) << ":" << (pos.column + 1) << ": " << msg << std::endl; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 95 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 96 | auto printer = tint::diag::Printer::create(stderr, true); |
| 97 | printer->write(out.str(), {diag::Color::kYellow, false}); |
| 98 | tint::diag::Formatter().format(diags, printer.get()); |
| 99 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 100 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 101 | return tools.Validate(spirv.data(), spirv.size(), spvtools::ValidatorOptions()); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 102 | } |
| 103 | |
| 104 | } // namespace |
| 105 | |
| 106 | void GenerateSpirvOptions(DataBuilder* b, writer::spirv::Options* options) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 107 | *options = b->build<writer::spirv::Options>(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 108 | } |
| 109 | |
| 110 | void GenerateWgslOptions(DataBuilder* b, writer::wgsl::Options* options) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 111 | *options = b->build<writer::wgsl::Options>(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 112 | } |
| 113 | |
| 114 | void GenerateHlslOptions(DataBuilder* b, writer::hlsl::Options* options) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 115 | *options = b->build<writer::hlsl::Options>(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 116 | } |
| 117 | |
| 118 | void GenerateMslOptions(DataBuilder* b, writer::msl::Options* options) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 119 | *options = b->build<writer::msl::Options>(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 120 | } |
| 121 | |
| 122 | CommonFuzzer::CommonFuzzer(InputFormat input, OutputFormat output) |
| 123 | : input_(input), output_(output) {} |
| 124 | |
| 125 | CommonFuzzer::~CommonFuzzer() = default; |
| 126 | |
| 127 | int CommonFuzzer::Run(const uint8_t* data, size_t size) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 128 | tint::SetInternalCompilerErrorReporter(&TintInternalCompilerErrorReporter); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 129 | |
| 130 | #if TINT_BUILD_WGSL_WRITER |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 131 | tint::Program::printer = [](const tint::Program* program) { |
| 132 | auto result = tint::writer::wgsl::Generate(program, {}); |
| 133 | if (!result.error.empty()) { |
| 134 | return "error: " + result.error; |
| 135 | } |
| 136 | return result.wgsl; |
| 137 | }; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 138 | #endif // TINT_BUILD_WGSL_WRITER |
| 139 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 140 | Program program; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 141 | |
| 142 | #if TINT_BUILD_SPV_READER |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 143 | std::vector<uint32_t> spirv_input(size / sizeof(uint32_t)); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 144 | |
| 145 | #endif // TINT_BUILD_SPV_READER |
| 146 | |
| 147 | #if TINT_BUILD_WGSL_READER || TINT_BUILD_SPV_READER |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 148 | auto dump_input_data = [&](auto& content, const char* extension) { |
| 149 | size_t hash = utils::Hash(content); |
| 150 | auto filename = "fuzzer_input_" + std::to_string(hash) + extension; // |
| 151 | std::ofstream fout(filename, std::ios::binary); |
| 152 | fout.write(reinterpret_cast<const char*>(data), static_cast<std::streamsize>(size)); |
| 153 | std::cout << "Dumped input data to " << filename << std::endl; |
| 154 | }; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 155 | #endif |
| 156 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 157 | switch (input_) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 158 | case InputFormat::kWGSL: { |
Brandon Jones | 13d1452 | 2023-01-20 00:11:00 +0000 | [diff] [blame] | 159 | #if TINT_BUILD_WGSL_READER |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 160 | // Clear any existing diagnostics, as these will hold pointers to file_, |
| 161 | // which we are about to release. |
| 162 | diagnostics_ = {}; |
| 163 | std::string str(reinterpret_cast<const char*>(data), size); |
| 164 | file_ = std::make_unique<Source::File>("test.wgsl", str); |
| 165 | if (dump_input_) { |
| 166 | dump_input_data(str, ".wgsl"); |
| 167 | } |
| 168 | program = reader::wgsl::Parse(file_.get()); |
Brandon Jones | 13d1452 | 2023-01-20 00:11:00 +0000 | [diff] [blame] | 169 | #endif // TINT_BUILD_WGSL_READER |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 170 | break; |
| 171 | } |
Brandon Jones | 13d1452 | 2023-01-20 00:11:00 +0000 | [diff] [blame] | 172 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 173 | case InputFormat::kSpv: { |
Brandon Jones | 13d1452 | 2023-01-20 00:11:00 +0000 | [diff] [blame] | 174 | #if TINT_BUILD_SPV_READER |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 175 | // `spirv_input` has been initialized with the capacity to store `size / |
| 176 | // sizeof(uint32_t)` uint32_t values. If `size` is not a multiple of |
| 177 | // sizeof(uint32_t) then not all of `data` can be copied into |
| 178 | // `spirv_input`, and any trailing bytes are discarded. |
| 179 | std::memcpy(spirv_input.data(), data, spirv_input.size() * sizeof(uint32_t)); |
| 180 | if (spirv_input.empty()) { |
| 181 | return 0; |
| 182 | } |
| 183 | if (dump_input_) { |
| 184 | dump_input_data(spirv_input, ".spv"); |
| 185 | } |
| 186 | program = reader::spirv::Parse(spirv_input); |
Brandon Jones | 13d1452 | 2023-01-20 00:11:00 +0000 | [diff] [blame] | 187 | #endif // TINT_BUILD_SPV_READER |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 188 | break; |
| 189 | } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 190 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 191 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 192 | if (!program.IsValid()) { |
| 193 | diagnostics_ = program.Diagnostics(); |
| 194 | return 0; |
| 195 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 196 | |
| 197 | #if TINT_BUILD_SPV_READER |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 198 | if (input_ == InputFormat::kSpv && !SPIRVToolsValidationCheck(program, spirv_input)) { |
| 199 | FATAL_ERROR(program.Diagnostics(), |
| 200 | "Fuzzing detected invalid input spirv not being caught by Tint"); |
| 201 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 202 | #endif // TINT_BUILD_SPV_READER |
| 203 | |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 204 | RunInspector(&program); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 205 | diagnostics_ = program.Diagnostics(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 206 | |
dan sinclair | 65edd3d | 2022-09-19 18:59:41 +0000 | [diff] [blame] | 207 | auto validate_program = [&](auto& out) { |
James Price | 0e6534e | 2023-05-17 01:21:45 +0000 | [diff] [blame] | 208 | if (!out.IsValid()) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 209 | // Transforms can produce error messages for bad input. |
| 210 | // Catch ICEs and errors from non transform systems. |
James Price | 0e6534e | 2023-05-17 01:21:45 +0000 | [diff] [blame] | 211 | for (const auto& diag : out.Diagnostics()) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 212 | if (diag.severity > diag::Severity::Error || |
| 213 | diag.system != diag::System::Transform) { |
| 214 | VALIDITY_ERROR(program.Diagnostics(), |
| 215 | "Fuzzing detected valid input program being " |
| 216 | "transformed into an invalid output program"); |
| 217 | } |
| 218 | } |
Ben Clayton | 8954189 | 2022-12-01 15:34:55 +0000 | [diff] [blame] | 219 | return 0; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 220 | } |
| 221 | |
James Price | 0e6534e | 2023-05-17 01:21:45 +0000 | [diff] [blame] | 222 | program = std::move(out); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 223 | RunInspector(&program); |
dan sinclair | 65edd3d | 2022-09-19 18:59:41 +0000 | [diff] [blame] | 224 | return 1; |
| 225 | }; |
| 226 | |
| 227 | if (transform_manager_) { |
James Price | 0e6534e | 2023-05-17 01:21:45 +0000 | [diff] [blame] | 228 | transform::DataMap outputs; |
| 229 | auto out = transform_manager_->Run(&program, *transform_inputs_, outputs); |
dan sinclair | 65edd3d | 2022-09-19 18:59:41 +0000 | [diff] [blame] | 230 | if (!validate_program(out)) { |
| 231 | return 0; |
| 232 | } |
| 233 | } |
| 234 | |
| 235 | { |
| 236 | // Run SubstituteOverride if required |
| 237 | |
James Price | b4acbb8 | 2023-05-11 21:27:16 +0000 | [diff] [blame] | 238 | ast::transform::SubstituteOverride::Config cfg; |
dan sinclair | 65edd3d | 2022-09-19 18:59:41 +0000 | [diff] [blame] | 239 | inspector::Inspector inspector(&program); |
| 240 | auto default_values = inspector.GetOverrideDefaultValues(); |
| 241 | for (const auto& [override_id, scalar] : default_values) { |
| 242 | // If the override is not null, then it has a default value, we can just let it use the |
| 243 | // provided default instead of overriding. |
| 244 | if (!scalar.IsNull()) { |
| 245 | continue; |
| 246 | } |
| 247 | |
| 248 | cfg.map.insert({override_id, 0.0}); |
| 249 | } |
| 250 | |
James Price | c1fd631 | 2023-05-24 16:55:30 +0000 | [diff] [blame] | 251 | if (!default_values.empty()) { |
James Price | 0e6534e | 2023-05-17 01:21:45 +0000 | [diff] [blame] | 252 | transform::DataMap override_data; |
James Price | b4acbb8 | 2023-05-11 21:27:16 +0000 | [diff] [blame] | 253 | override_data.Add<ast::transform::SubstituteOverride::Config>(cfg); |
dan sinclair | 65edd3d | 2022-09-19 18:59:41 +0000 | [diff] [blame] | 254 | |
| 255 | transform::Manager mgr; |
James Price | b4acbb8 | 2023-05-11 21:27:16 +0000 | [diff] [blame] | 256 | mgr.append(std::make_unique<ast::transform::SubstituteOverride>()); |
dan sinclair | 65edd3d | 2022-09-19 18:59:41 +0000 | [diff] [blame] | 257 | |
James Price | 0e6534e | 2023-05-17 01:21:45 +0000 | [diff] [blame] | 258 | transform::DataMap outputs; |
| 259 | auto out = mgr.Run(&program, override_data, outputs); |
dan sinclair | 65edd3d | 2022-09-19 18:59:41 +0000 | [diff] [blame] | 260 | if (!validate_program(out)) { |
| 261 | return 0; |
| 262 | } |
| 263 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 264 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 265 | |
dan sinclair | 5ab6dcb | 2023-03-23 19:35:02 +0000 | [diff] [blame] | 266 | // For the generates which use MultiPlanar, make sure the configuration options are provided so |
| 267 | // that the transformer will execute. |
dan sinclair | d146c8a | 2023-04-11 23:02:38 +0000 | [diff] [blame] | 268 | if (output_ == OutputFormat::kMSL || output_ == OutputFormat::kHLSL || |
| 269 | output_ == OutputFormat::kSpv) { |
dan sinclair | 5ab6dcb | 2023-03-23 19:35:02 +0000 | [diff] [blame] | 270 | // Gather external texture binding information |
| 271 | // Collect next valid binding number per group |
| 272 | std::unordered_map<uint32_t, uint32_t> group_to_next_binding_number; |
| 273 | std::vector<sem::BindingPoint> ext_tex_bps; |
| 274 | for (auto* var : program.AST().GlobalVariables()) { |
| 275 | if (auto* sem_var = program.Sem().Get(var)->As<sem::GlobalVariable>()) { |
Ben Clayton | 5f4847c | 2023-04-19 13:24:27 +0000 | [diff] [blame] | 276 | if (auto bp = sem_var->BindingPoint()) { |
| 277 | auto& n = group_to_next_binding_number[bp->group]; |
| 278 | n = std::max(n, bp->binding + 1); |
dan sinclair | 5ab6dcb | 2023-03-23 19:35:02 +0000 | [diff] [blame] | 279 | |
Ben Clayton | 5f4847c | 2023-04-19 13:24:27 +0000 | [diff] [blame] | 280 | if (sem_var->Type()->UnwrapRef()->Is<type::ExternalTexture>()) { |
| 281 | ext_tex_bps.emplace_back(*bp); |
| 282 | } |
dan sinclair | 5ab6dcb | 2023-03-23 19:35:02 +0000 | [diff] [blame] | 283 | } |
| 284 | } |
| 285 | } |
| 286 | |
| 287 | writer::ExternalTextureOptions::BindingsMap new_bindings_map; |
| 288 | for (auto bp : ext_tex_bps) { |
| 289 | uint32_t g = bp.group; |
| 290 | uint32_t& next_num = group_to_next_binding_number[g]; |
| 291 | auto new_bps = |
| 292 | writer::ExternalTextureOptions::BindingPoints{{g, next_num++}, {g, next_num++}}; |
| 293 | |
| 294 | new_bindings_map[bp] = new_bps; |
| 295 | } |
| 296 | |
| 297 | switch (output_) { |
| 298 | case OutputFormat::kMSL: { |
| 299 | options_msl_.external_texture_options.bindings_map = new_bindings_map; |
| 300 | break; |
| 301 | } |
| 302 | case OutputFormat::kHLSL: { |
| 303 | options_hlsl_.external_texture_options.bindings_map = new_bindings_map; |
| 304 | break; |
| 305 | } |
dan sinclair | d146c8a | 2023-04-11 23:02:38 +0000 | [diff] [blame] | 306 | case OutputFormat::kSpv: { |
| 307 | options_spirv_.external_texture_options.bindings_map = new_bindings_map; |
| 308 | break; |
| 309 | } |
dan sinclair | 5ab6dcb | 2023-03-23 19:35:02 +0000 | [diff] [blame] | 310 | default: |
| 311 | break; |
| 312 | } |
| 313 | } |
| 314 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 315 | switch (output_) { |
| 316 | case OutputFormat::kWGSL: { |
| 317 | #if TINT_BUILD_WGSL_WRITER |
dan sinclair | 8dbd4d0 | 2022-07-27 18:54:05 +0000 | [diff] [blame] | 318 | writer::wgsl::Generate(&program, options_wgsl_); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 319 | #endif // TINT_BUILD_WGSL_WRITER |
| 320 | break; |
| 321 | } |
| 322 | case OutputFormat::kSpv: { |
| 323 | #if TINT_BUILD_SPV_WRITER |
| 324 | auto result = writer::spirv::Generate(&program, options_spirv_); |
| 325 | generated_spirv_ = std::move(result.spirv); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 326 | |
| 327 | if (!SPIRVToolsValidationCheck(program, generated_spirv_)) { |
| 328 | VALIDITY_ERROR(program.Diagnostics(), |
| 329 | "Fuzzing detected invalid spirv being emitted by Tint"); |
| 330 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 331 | |
| 332 | #endif // TINT_BUILD_SPV_WRITER |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 333 | break; |
| 334 | } |
| 335 | case OutputFormat::kHLSL: { |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 336 | #if TINT_BUILD_HLSL_WRITER |
dan sinclair | 8dbd4d0 | 2022-07-27 18:54:05 +0000 | [diff] [blame] | 337 | writer::hlsl::Generate(&program, options_hlsl_); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 338 | #endif // TINT_BUILD_HLSL_WRITER |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 339 | break; |
| 340 | } |
| 341 | case OutputFormat::kMSL: { |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 342 | #if TINT_BUILD_MSL_WRITER |
Antonio Maiorano | 4e98fb0 | 2022-05-02 19:49:19 +0000 | [diff] [blame] | 343 | // Remap resource numbers to a flat namespace. |
| 344 | // TODO(crbug.com/tint/1501): Do this via Options::BindingMap. |
| 345 | auto input_program = &program; |
| 346 | auto flattened = tint::writer::FlattenBindings(&program); |
| 347 | if (flattened) { |
| 348 | input_program = &*flattened; |
| 349 | } |
| 350 | |
dan sinclair | 8dbd4d0 | 2022-07-27 18:54:05 +0000 | [diff] [blame] | 351 | writer::msl::Generate(input_program, options_msl_); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 352 | #endif // TINT_BUILD_MSL_WRITER |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 353 | break; |
| 354 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 355 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 356 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 357 | return 0; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 358 | } |
| 359 | |
| 360 | void CommonFuzzer::RunInspector(Program* program) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 361 | inspector::Inspector inspector(program); |
| 362 | diagnostics_ = program->Diagnostics(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 363 | |
Ben Clayton | 3f24fdc | 2022-11-01 00:23:14 +0000 | [diff] [blame] | 364 | if (!program->IsValid()) { |
| 365 | // It's not safe to use the inspector on invalid programs. |
| 366 | return; |
| 367 | } |
| 368 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 369 | auto entry_points = inspector.GetEntryPoints(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 370 | CHECK_INSPECTOR(program, inspector); |
| 371 | |
Ben Clayton | 9a6acc4 | 2022-07-27 20:50:40 +0000 | [diff] [blame] | 372 | auto override_ids = inspector.GetOverrideDefaultValues(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 373 | CHECK_INSPECTOR(program, inspector); |
| 374 | |
Ben Clayton | 9a6acc4 | 2022-07-27 20:50:40 +0000 | [diff] [blame] | 375 | auto override_name_to_id = inspector.GetNamedOverrideIds(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 376 | CHECK_INSPECTOR(program, inspector); |
| 377 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 378 | for (auto& ep : entry_points) { |
| 379 | inspector.GetStorageSize(ep.name); |
| 380 | CHECK_INSPECTOR(program, inspector); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 381 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 382 | inspector.GetResourceBindings(ep.name); |
| 383 | CHECK_INSPECTOR(program, inspector); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 384 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 385 | inspector.GetUniformBufferResourceBindings(ep.name); |
| 386 | CHECK_INSPECTOR(program, inspector); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 387 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 388 | inspector.GetStorageBufferResourceBindings(ep.name); |
| 389 | CHECK_INSPECTOR(program, inspector); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 390 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 391 | inspector.GetReadOnlyStorageBufferResourceBindings(ep.name); |
| 392 | CHECK_INSPECTOR(program, inspector); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 393 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 394 | inspector.GetSamplerResourceBindings(ep.name); |
| 395 | CHECK_INSPECTOR(program, inspector); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 396 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 397 | inspector.GetComparisonSamplerResourceBindings(ep.name); |
| 398 | CHECK_INSPECTOR(program, inspector); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 399 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 400 | inspector.GetSampledTextureResourceBindings(ep.name); |
| 401 | CHECK_INSPECTOR(program, inspector); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 402 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 403 | inspector.GetMultisampledTextureResourceBindings(ep.name); |
| 404 | CHECK_INSPECTOR(program, inspector); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 405 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 406 | inspector.GetWriteOnlyStorageTextureResourceBindings(ep.name); |
| 407 | CHECK_INSPECTOR(program, inspector); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 408 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 409 | inspector.GetDepthTextureResourceBindings(ep.name); |
| 410 | CHECK_INSPECTOR(program, inspector); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 411 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 412 | inspector.GetDepthMultisampledTextureResourceBindings(ep.name); |
| 413 | CHECK_INSPECTOR(program, inspector); |
| 414 | |
| 415 | inspector.GetExternalTextureResourceBindings(ep.name); |
| 416 | CHECK_INSPECTOR(program, inspector); |
| 417 | |
| 418 | inspector.GetSamplerTextureUses(ep.name); |
| 419 | CHECK_INSPECTOR(program, inspector); |
| 420 | |
| 421 | inspector.GetWorkgroupStorageSize(ep.name); |
| 422 | CHECK_INSPECTOR(program, inspector); |
| 423 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 424 | } |
| 425 | |
dan sinclair | 62a1d71 | 2022-04-07 17:46:04 +0000 | [diff] [blame] | 426 | } // namespace tint::fuzzers |