From: Francisco Casas fcasas@codeweavers.com
We can now pass (sm<4) and (sm>=4) to "fail" and "todo" qualifiers, and we also we can pass a specific range using two arguments separated with commas, if we need them, e.g. todo(sm>=4,sm<6).
Adding additional model ranges for the tests, if we need them, should be easier now, since they only have to be added to the "valid_args" array. --- tests/shader_runner.c | 160 +++++++++++++++++++++++++++++++++--------- 1 file changed, 125 insertions(+), 35 deletions(-)
diff --git a/tests/shader_runner.c b/tests/shader_runner.c index 0e6104ce3..12af65252 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -94,42 +94,133 @@ enum parse_state STATE_TEST, };
-static bool match_string(const char *line, const char *token, const char **const rest) +static void read_string_args(const char *line, const char **const rest, + enum shader_model *sm_min, enum shader_model *sm_max) +{ + unsigned int i; + + static const struct + { + const char *text; + enum shader_model sm_min, sm_max; + } + valid_args[] = + { + {"sm>=4", SHADER_MODEL_4_0, SHADER_MODEL_6_0}, + {"sm>=6", SHADER_MODEL_6_0, SHADER_MODEL_6_0}, + {"sm<4", SHADER_MODEL_2_0, SHADER_MODEL_4_0 - 1}, + {"sm<6", SHADER_MODEL_2_0, SHADER_MODEL_6_0 - 1}, + }; + + assert(*line == '('); + ++line; + + while (*line != ')') + { + + for (i = 0; i < ARRAY_SIZE(valid_args); ++i) + { + const char *option_text = valid_args[i].text; + + if (!strncmp(line, option_text, strlen(option_text))) + { + line += strlen(option_text); + *sm_min = max(*sm_min, valid_args[i].sm_min); + *sm_max = min(*sm_max, valid_args[i].sm_max); + + break; + } + } + + if (*line == ',') + { + ++line; + } + else if (*line != ')') + { + fatal_error("Invalid qualifier argument '%s'.\n", line); + return; + } + } + + assert(*line == ')'); + if (rest) + *rest = line + 1; +} + +static bool match_string_with_args(const char *line, const char *token, const char **const rest, + enum shader_model *sm_min, enum shader_model *sm_max) { size_t len = strlen(token);
+ assert(!!sm_max == !!sm_min); + while (isspace(*line)) ++line;
- if (strncmp(line, token, len) || !isspace(line[len])) + if (strncmp(line, token, len) || !(isspace(line[len]) || line[len] == '(')) return false; + line += len; + + if (sm_min) + { + *sm_min = SHADER_MODEL_2_0; + *sm_max = SHADER_MODEL_6_0; + + if (*line == '(') + read_string_args(line, &line, sm_min, sm_max); + } + if (rest) { - *rest = line + len; + *rest = line; while (isspace(**rest)) ++*rest; } return true; }
-static bool match_directive_substring(const char *line, const char *token, const char **const rest) +static bool match_string(const char *line, const char *token, const char **const rest) +{ + return match_string_with_args(line, token, rest, NULL, NULL); +} + +static bool match_directive_substring_with_args(const char *line, const char *token, + const char **const rest, enum shader_model *sm_min, enum shader_model *sm_max) { size_t len = strlen(token);
while (isspace(*line) || *line == ']') ++line;
- if (strncmp(line, token, len) || !(isspace(line[len]) || line[len] == ']')) + if (strncmp(line, token, len) || !(isspace(line[len]) || line[len] == ']' || line[len] == '(')) return false; + line += len; + + if (sm_min) + { + assert(sm_max); + *sm_min = SHADER_MODEL_2_0; + *sm_max = SHADER_MODEL_6_0; + + if (*line == '(') + read_string_args(line, &line, sm_min, sm_max); + } + if (rest) { - *rest = line + len; + *rest = line; while (isspace(**rest)) ++*rest; } return true; }
+static bool match_directive_substring(const char *line, const char *token, const char **const rest) +{ + return match_directive_substring_with_args(line, token, rest, NULL, NULL); +} + static void parse_require_directive(struct shader_runner *runner, const char *line) { bool less_than = false; @@ -535,17 +626,17 @@ static void read_uint64_t2(const char **line, struct u64vec2 *v)
static void parse_test_directive(struct shader_runner *runner, const char *line) { + enum shader_model sm_range_min, sm_range_max; char *rest; int ret;
runner->is_todo = false;
- if (match_string(line, "todo", &line)) - runner->is_todo = true; - else if (match_string(line, "todo(sm<6)", &line)) - runner->is_todo = runner->minimum_shader_model < SHADER_MODEL_6_0; - else if (match_string(line, "todo(sm>=6)", &line)) - runner->is_todo = runner->minimum_shader_model >= SHADER_MODEL_6_0; + if (match_string_with_args(line, "todo", &line, &sm_range_min, &sm_range_max)) + { + if (sm_range_min <= runner->minimum_shader_model && runner->minimum_shader_model <= sm_range_max) + runner->is_todo = true; + }
if (match_string(line, "dispatch", &line)) { @@ -1059,42 +1150,41 @@ static void compile_shader(struct shader_runner *runner, IDxcCompiler3 *dxc_comp } }
+static enum parse_state get_parse_state_todo(enum parse_state state) +{ + if (state == STATE_SHADER_COMPUTE) + return STATE_SHADER_COMPUTE_TODO; + else if (state == STATE_SHADER_PIXEL) + return STATE_SHADER_PIXEL_TODO; + else if (state == STATE_SHADER_VERTEX) + return STATE_SHADER_VERTEX_TODO; + else + return STATE_SHADER_EFFECT_TODO; +} + static enum parse_state read_shader_directive(struct shader_runner *runner, enum parse_state state, const char *line, const char *src, HRESULT *expect_hr) { + enum shader_model sm_range_min, sm_range_max; + while (*src && *src != ']') { - /* 'todo' is not meaningful when dxcompiler is in use, so it has no '(sm<6) qualifier. */ - if (match_directive_substring(src, "todo", &src)) + if (match_directive_substring_with_args(src, "todo", &src, &sm_range_min, &sm_range_max)) { + /* 'todo' is not meaningful when dxcompiler is in use. */ if (runner->minimum_shader_model >= SHADER_MODEL_6_0) continue; - if (state == STATE_SHADER_COMPUTE) - state = STATE_SHADER_COMPUTE_TODO; - else if (state == STATE_SHADER_PIXEL) - state = STATE_SHADER_PIXEL_TODO; - else if (state == STATE_SHADER_VERTEX) - state = STATE_SHADER_VERTEX_TODO; - else - state = STATE_SHADER_EFFECT_TODO; - } - else if (match_directive_substring(src, "fail", &src)) - { - *expect_hr = E_FAIL; + if (sm_range_min <= runner->minimum_shader_model && runner->minimum_shader_model <= sm_range_max) + state = get_parse_state_todo(state); } - else if (match_directive_substring(src, "fail(sm<6)", &src)) + else if (match_directive_substring_with_args(src, "fail", &src, &sm_range_min, &sm_range_max)) { - if (runner->minimum_shader_model < SHADER_MODEL_6_0) - *expect_hr = E_FAIL; - } - else if (match_directive_substring(src, "fail(sm>=6)", &src)) - { - if (runner->minimum_shader_model >= SHADER_MODEL_6_0) + if (sm_range_min <= runner->minimum_shader_model && runner->minimum_shader_model <= sm_range_max) *expect_hr = E_FAIL; } - else if (match_directive_substring(src, "notimpl(sm<6)", &src)) + else if (match_directive_substring_with_args(src, "notimpl", &src, &sm_range_min, &sm_range_max)) { - if (runner->minimum_shader_model < SHADER_MODEL_6_0) + if (sm_range_min <= runner->minimum_shader_model && runner->minimum_shader_model <= sm_range_max) *expect_hr = E_NOTIMPL; } else