1 /* 2 * Copyright © 2023 Valve Corporation 3 * SPDX-License-Identifier: MIT 4 */ 5 6 #ifndef NIR_TESTS_NIR_TEST_H 7 #define NIR_TESTS_NIR_TEST_H 8 9 #include <gtest/gtest.h> 10 11 #include "nir.h" 12 #include "nir_builder.h" 13 14 #include "util/memstream.h" 15 16 struct nir_reference_shader { 17 const char *string; 18 const char *file; 19 uint32_t line; 20 }; 21 22 class nir_test : public ::testing::Test { 23 protected: nir_test(const char * name)24 nir_test(const char *name) 25 : nir_test(name, MESA_SHADER_COMPUTE) 26 { 27 } 28 nir_test(const char * name,gl_shader_stage stage)29 nir_test(const char *name, gl_shader_stage stage) 30 { 31 glsl_type_singleton_init_or_ref(); 32 33 _b = nir_builder_init_simple_shader(stage, &options, "%s", name); 34 b = &_b; 35 36 b->shader->info.next_stage = MESA_SHADER_NONE; 37 b->shader->info.internal = false; 38 } 39 ~nir_test()40 virtual ~nir_test() 41 { 42 if (HasFailure()) { 43 printf("\nShader from the failed test:\n\n"); 44 nir_print_shader(b->shader, stdout); 45 } 46 47 ralloc_free(b->shader); 48 49 glsl_type_singleton_decref(); 50 } 51 52 /** Compares the NIR shader against the string of a reference shader. */ check_nir_string(struct nir_reference_shader reference)53 void check_nir_string(struct nir_reference_shader reference) 54 { 55 nir_index_ssa_defs(b->impl); 56 57 char *result = NULL; 58 size_t result_size = 0; 59 struct u_memstream mem; 60 if (!u_memstream_open(&mem, &result, &result_size)) 61 return; 62 63 FILE * memf = u_memstream_get(&mem); 64 nir_print_shader(b->shader, memf); 65 u_memstream_close(&mem); 66 67 const char *expected = reference.string; 68 69 /* Use a custom comparison that ignores spaces since spaces are not 70 * relevant for correctness. This is also intended to be used when 71 * specifying the expected shader for indentation. Indentation can 72 * not simply be handled by nir_print_shader because that would require 73 * computing the indentation. 74 */ 75 const char *result_iter = result; 76 size_t result_length = strlen(result); 77 const char *expected_iter = expected; 78 size_t expected_length = strlen(expected); 79 80 bool failed = false; 81 82 while (result_iter < result + result_length && expected_iter < expected + expected_length) { 83 if (isspace(*result_iter)) { 84 result_iter++; 85 continue; 86 } 87 88 if (isspace(*expected_iter)) { 89 expected_iter++; 90 continue; 91 } 92 93 if (*result_iter != *expected_iter) { 94 ADD_FAILURE(); 95 failed = true; 96 break; 97 } 98 99 result_iter++; 100 expected_iter++; 101 } 102 103 if (!failed) { 104 for (; result_iter < result + result_length; result_iter++) { 105 if (!isspace(*result_iter)) { 106 ADD_FAILURE(); 107 failed = true; 108 break; 109 } 110 } 111 } 112 113 if (!failed) { 114 for (; expected_iter < expected + expected_length; expected_iter++) { 115 if (!isspace(*expected_iter)) { 116 ADD_FAILURE(); 117 failed = true; 118 break; 119 } 120 } 121 } 122 123 if (failed || debug_get_bool_option("NIR_TEST_DUMP_SHADERS", false)) 124 printf("Got:\n%s\nExpected (%s:%u):\n%s\n", result, reference.file, reference.line, expected); 125 126 free(result); 127 } 128 129 nir_shader_compiler_options options = {}; 130 nir_builder _b; 131 nir_builder *b; 132 }; 133 134 #define NIR_REFERENCE_SHADER(expected) nir_reference_shader{.string = expected, .file = __FILE__, .line = __LINE__} 135 136 #endif 137