blob: f7160affd047e0202f137c49978d6522682d2c4f [file] [log] [blame]
/*
* 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