| /* |
| * Copyright © 2023 Valve Corporation |
| * SPDX-License-Identifier: MIT |
| */ |
| |
| #ifndef NIR_TESTS_NIR_TEST_H |
| #define NIR_TESTS_NIR_TEST_H |
| |
| #include <gtest/gtest.h> |
| |
| #include "nir.h" |
| #include "nir_builder.h" |
| |
| #include "util/memstream.h" |
| |
| struct nir_reference_shader { |
| const char *string; |
| const char *file; |
| }; |
| |
| class nir_test : public ::testing::Test { |
| protected: |
| nir_test(const char *name) |
| : nir_test(name, MESA_SHADER_COMPUTE) |
| { |
| } |
| |
| nir_test(const char *name, gl_shader_stage stage) |
| { |
| glsl_type_singleton_init_or_ref(); |
| |
| _b = nir_builder_init_simple_shader(stage, &options, "%s", name); |
| b = &_b; |
| |
| b->shader->info.next_stage = MESA_SHADER_NONE; |
| b->shader->info.internal = false; |
| } |
| |
| virtual ~nir_test() |
| { |
| if (HasFailure()) { |
| printf("\nShader from the failed test:\n\n"); |
| nir_print_shader(b->shader, stdout); |
| } |
| |
| ralloc_free(b->shader); |
| |
| glsl_type_singleton_decref(); |
| } |
| |
| /** Compares the NIR shader against the string of a reference shader. */ |
| void check_nir_string(struct nir_reference_shader reference) |
| { |
| nir_index_ssa_defs(b->impl); |
| |
| char *result = NULL; |
| size_t result_size = 0; |
| struct u_memstream mem; |
| if (!u_memstream_open(&mem, &result, &result_size)) |
| return; |
| |
| FILE * memf = u_memstream_get(&mem); |
| nir_print_shader(b->shader, memf); |
| u_memstream_close(&mem); |
| |
| const char *expected = reference.string; |
| |
| /* Use a custom comparison that ignores spaces since spaces are not |
| * relevant for correctness. This is also intended to be used when |
| * specifying the expected shader for indentation. Indentation can |
| * not simply be handled by nir_print_shader because that would require |
| * computing the indentation. |
| */ |
| const char *result_iter = result; |
| size_t result_length = strlen(result); |
| const char *expected_iter = expected; |
| size_t expected_length = strlen(expected); |
| |
| bool failed = false; |
| |
| while (result_iter < result + result_length && expected_iter < expected + expected_length) { |
| if (isspace(*result_iter)) { |
| result_iter++; |
| continue; |
| } |
| |
| if (isspace(*expected_iter)) { |
| expected_iter++; |
| continue; |
| } |
| |
| if (*result_iter != *expected_iter) { |
| ADD_FAILURE(); |
| failed = true; |
| break; |
| } |
| |
| result_iter++; |
| expected_iter++; |
| } |
| |
| if (!failed) { |
| for (; result_iter < result + result_length; result_iter++) { |
| if (!isspace(*result_iter)) { |
| ADD_FAILURE(); |
| failed = true; |
| break; |
| } |
| } |
| } |
| |
| if (!failed) { |
| for (; expected_iter < expected + expected_length; expected_iter++) { |
| if (!isspace(*expected_iter)) { |
| ADD_FAILURE(); |
| failed = true; |
| break; |
| } |
| } |
| } |
| |
| if (failed || debug_get_bool_option("NIR_TEST_DUMP_SHADERS", false)) |
| printf("BEGIN RESULT\n%s\nEND\nBEGIN EXPECTED(%s)\n%s\nEND\n", result, reference.file, expected); |
| |
| free(result); |
| } |
| |
| nir_shader_compiler_options options = {}; |
| nir_builder _b; |
| nir_builder *b; |
| }; |
| |
| #define NIR_REFERENCE_SHADER(expected) nir_reference_shader{.string = expected, .file = __FILE__} |
| |
| #endif |