From 5ea825f55652ba9e91ab683308dcd6392cc32a97 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Thu, 31 Mar 2016 16:49:59 +1100 Subject: [PATCH 01/62] glsl: remove tabs and fix some other style issues in glcpp-parse.y Note there are still tabs left in the parser rules. Acked-by: Dave Airlie --- src/compiler/glsl/glcpp/glcpp-parse.y | 2526 ++++++++++++------------- 1 file changed, 1227 insertions(+), 1299 deletions(-) diff --git a/src/compiler/glsl/glcpp/glcpp-parse.y b/src/compiler/glsl/glcpp/glcpp-parse.y index e8646c0ad32..e1e46af27b1 100644 --- a/src/compiler/glsl/glcpp/glcpp-parse.y +++ b/src/compiler/glsl/glcpp/glcpp-parse.y @@ -33,125 +33,121 @@ #include "main/mtypes.h" /* for gl_api enum */ static void -yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error); +yyerror(YYLTYPE *locp, glcpp_parser_t *parser, const char *error); static void -_define_object_macro (glcpp_parser_t *parser, - YYLTYPE *loc, - const char *macro, - token_list_t *replacements); +_define_object_macro(glcpp_parser_t *parser, + YYLTYPE *loc, + const char *macro, + token_list_t *replacements); static void -_define_function_macro (glcpp_parser_t *parser, - YYLTYPE *loc, - const char *macro, - string_list_t *parameters, - token_list_t *replacements); +_define_function_macro(glcpp_parser_t *parser, + YYLTYPE *loc, + const char *macro, + string_list_t *parameters, + token_list_t *replacements); static string_list_t * -_string_list_create (void *ctx); +_string_list_create(void *ctx); static void -_string_list_append_item (string_list_t *list, const char *str); +_string_list_append_item(string_list_t *list, const char *str); static int -_string_list_contains (string_list_t *list, const char *member, int *index); +_string_list_contains(string_list_t *list, const char *member, int *index); static const char * -_string_list_has_duplicate (string_list_t *list); +_string_list_has_duplicate(string_list_t *list); static int -_string_list_length (string_list_t *list); +_string_list_length(string_list_t *list); static int -_string_list_equal (string_list_t *a, string_list_t *b); +_string_list_equal(string_list_t *a, string_list_t *b); static argument_list_t * -_argument_list_create (void *ctx); +_argument_list_create(void *ctx); static void -_argument_list_append (argument_list_t *list, token_list_t *argument); +_argument_list_append(argument_list_t *list, token_list_t *argument); static int -_argument_list_length (argument_list_t *list); +_argument_list_length(argument_list_t *list); static token_list_t * -_argument_list_member_at (argument_list_t *list, int index); +_argument_list_member_at(argument_list_t *list, int index); /* Note: This function ralloc_steal()s the str pointer. */ static token_t * -_token_create_str (void *ctx, int type, char *str); +_token_create_str(void *ctx, int type, char *str); static token_t * -_token_create_ival (void *ctx, int type, int ival); +_token_create_ival(void *ctx, int type, int ival); static token_list_t * -_token_list_create (void *ctx); +_token_list_create(void *ctx); static void -_token_list_append (token_list_t *list, token_t *token); +_token_list_append(token_list_t *list, token_t *token); static void -_token_list_append_list (token_list_t *list, token_list_t *tail); +_token_list_append_list(token_list_t *list, token_list_t *tail); static int -_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b); +_token_list_equal_ignoring_space(token_list_t *a, token_list_t *b); static void -_parser_active_list_push (glcpp_parser_t *parser, - const char *identifier, - token_node_t *marker); +_parser_active_list_push(glcpp_parser_t *parser, const char *identifier, + token_node_t *marker); static void -_parser_active_list_pop (glcpp_parser_t *parser); +_parser_active_list_pop(glcpp_parser_t *parser); static int -_parser_active_list_contains (glcpp_parser_t *parser, const char *identifier); +_parser_active_list_contains(glcpp_parser_t *parser, const char *identifier); typedef enum { - EXPANSION_MODE_IGNORE_DEFINED, - EXPANSION_MODE_EVALUATE_DEFINED + EXPANSION_MODE_IGNORE_DEFINED, + EXPANSION_MODE_EVALUATE_DEFINED } expansion_mode_t; /* Expand list, and begin lexing from the result (after first * prefixing a token of type 'head_token_type'). */ static void -_glcpp_parser_expand_and_lex_from (glcpp_parser_t *parser, - int head_token_type, - token_list_t *list, - expansion_mode_t mode); +_glcpp_parser_expand_and_lex_from(glcpp_parser_t *parser, int head_token_type, + token_list_t *list, expansion_mode_t mode); /* Perform macro expansion in-place on the given list. */ static void -_glcpp_parser_expand_token_list (glcpp_parser_t *parser, - token_list_t *list, - expansion_mode_t mode); +_glcpp_parser_expand_token_list(glcpp_parser_t *parser, token_list_t *list, + expansion_mode_t mode); static void -_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser, - token_list_t *list); +_glcpp_parser_print_expanded_token_list(glcpp_parser_t *parser, + token_list_t *list); static void -_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc, - int condition); +_glcpp_parser_skip_stack_push_if(glcpp_parser_t *parser, YYLTYPE *loc, + int condition); static void -_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc, - const char *type, int condition); +_glcpp_parser_skip_stack_change_if(glcpp_parser_t *parser, YYLTYPE *loc, + const char *type, int condition); static void -_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc); +_glcpp_parser_skip_stack_pop(glcpp_parser_t *parser, YYLTYPE *loc); static void _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t version, const char *ident, bool explicitly_set); static int -glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser); +glcpp_parser_lex(YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser); static void -glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list); +glcpp_parser_lex_from(glcpp_parser_t *parser, token_list_t *list); static void add_builtin_define(glcpp_parser_t *parser, const char *name, int value); @@ -163,11 +159,11 @@ add_builtin_define(glcpp_parser_t *parser, const char *name, int value); %locations %initial-action { - @$.first_line = 1; - @$.first_column = 1; - @$.last_line = 1; - @$.last_column = 1; - @$.source = 0; + @$.first_line = 1; + @$.first_column = 1; + @$.last_line = 1; + @$.last_column = 1; + @$.source = 0; } %parse-param {glcpp_parser_t *parser} @@ -175,7 +171,7 @@ add_builtin_define(glcpp_parser_t *parser, const char *name, int value); %expect 0 - /* We use HASH_TOKEN, DEFINE_TOKEN and VERSION_TOKEN (as opposed to + /* We use HASH_TOKEN, DEFINE_TOKEN and VERSION_TOKEN (as opposed to * HASH, DEFINE, and VERSION) to avoid conflicts with other symbols, * (such as the and start conditions in the lexer). */ %token DEFINED ELIF_EXPANDED HASH_TOKEN DEFINE_TOKEN FUNC_IDENTIFIER OBJ_IDENTIFIER ELIF ELSE ENDIF ERROR_TOKEN IF IFDEF IFNDEF LINE PRAGMA UNDEF VERSION_TOKEN GARBAGE IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING LINE_EXPANDED NEWLINE OTHER PLACEHOLDER SPACE PLUS_PLUS MINUS_MINUS @@ -730,438 +726,433 @@ operator: %% string_list_t * -_string_list_create (void *ctx) +_string_list_create(void *ctx) { - string_list_t *list; + string_list_t *list; - list = ralloc (ctx, string_list_t); - list->head = NULL; - list->tail = NULL; + list = ralloc (ctx, string_list_t); + list->head = NULL; + list->tail = NULL; - return list; + return list; } void -_string_list_append_item (string_list_t *list, const char *str) +_string_list_append_item(string_list_t *list, const char *str) { - string_node_t *node; + string_node_t *node; - node = ralloc (list, string_node_t); - node->str = ralloc_strdup (node, str); + node = ralloc (list, string_node_t); + node->str = ralloc_strdup (node, str); - node->next = NULL; + node->next = NULL; - if (list->head == NULL) { - list->head = node; - } else { - list->tail->next = node; - } + if (list->head == NULL) { + list->head = node; + } else { + list->tail->next = node; + } - list->tail = node; + list->tail = node; } int -_string_list_contains (string_list_t *list, const char *member, int *index) +_string_list_contains(string_list_t *list, const char *member, int *index) { - string_node_t *node; - int i; + string_node_t *node; + int i; - if (list == NULL) - return 0; + if (list == NULL) + return 0; - for (i = 0, node = list->head; node; i++, node = node->next) { - if (strcmp (node->str, member) == 0) { - if (index) - *index = i; - return 1; - } - } + for (i = 0, node = list->head; node; i++, node = node->next) { + if (strcmp (node->str, member) == 0) { + if (index) + *index = i; + return 1; + } + } - return 0; + return 0; } /* Return duplicate string in list (if any), NULL otherwise. */ const char * -_string_list_has_duplicate (string_list_t *list) +_string_list_has_duplicate(string_list_t *list) { - string_node_t *node, *dup; + string_node_t *node, *dup; - if (list == NULL) - return NULL; + if (list == NULL) + return NULL; - for (node = list->head; node; node = node->next) { - for (dup = node->next; dup; dup = dup->next) { - if (strcmp (node->str, dup->str) == 0) - return node->str; - } - } + for (node = list->head; node; node = node->next) { + for (dup = node->next; dup; dup = dup->next) { + if (strcmp (node->str, dup->str) == 0) + return node->str; + } + } - return NULL; + return NULL; } int -_string_list_length (string_list_t *list) +_string_list_length(string_list_t *list) { - int length = 0; - string_node_t *node; + int length = 0; + string_node_t *node; - if (list == NULL) - return 0; + if (list == NULL) + return 0; - for (node = list->head; node; node = node->next) - length++; + for (node = list->head; node; node = node->next) + length++; - return length; + return length; } int -_string_list_equal (string_list_t *a, string_list_t *b) +_string_list_equal(string_list_t *a, string_list_t *b) { - string_node_t *node_a, *node_b; + string_node_t *node_a, *node_b; - if (a == NULL && b == NULL) - return 1; + if (a == NULL && b == NULL) + return 1; - if (a == NULL || b == NULL) - return 0; + if (a == NULL || b == NULL) + return 0; - for (node_a = a->head, node_b = b->head; - node_a && node_b; - node_a = node_a->next, node_b = node_b->next) - { - if (strcmp (node_a->str, node_b->str)) - return 0; - } + for (node_a = a->head, node_b = b->head; + node_a && node_b; + node_a = node_a->next, node_b = node_b->next) + { + if (strcmp (node_a->str, node_b->str)) + return 0; + } - /* Catch the case of lists being different lengths, (which - * would cause the loop above to terminate after the shorter - * list). */ - return node_a == node_b; + /* Catch the case of lists being different lengths, (which + * would cause the loop above to terminate after the shorter + * list). */ + return node_a == node_b; } argument_list_t * -_argument_list_create (void *ctx) +_argument_list_create(void *ctx) { - argument_list_t *list; + argument_list_t *list; - list = ralloc (ctx, argument_list_t); - list->head = NULL; - list->tail = NULL; + list = ralloc (ctx, argument_list_t); + list->head = NULL; + list->tail = NULL; - return list; + return list; } void -_argument_list_append (argument_list_t *list, token_list_t *argument) +_argument_list_append(argument_list_t *list, token_list_t *argument) { - argument_node_t *node; + argument_node_t *node; - node = ralloc (list, argument_node_t); - node->argument = argument; + node = ralloc (list, argument_node_t); + node->argument = argument; - node->next = NULL; + node->next = NULL; - if (list->head == NULL) { - list->head = node; - } else { - list->tail->next = node; - } + if (list->head == NULL) { + list->head = node; + } else { + list->tail->next = node; + } - list->tail = node; + list->tail = node; } int -_argument_list_length (argument_list_t *list) +_argument_list_length(argument_list_t *list) { - int length = 0; - argument_node_t *node; + int length = 0; + argument_node_t *node; - if (list == NULL) - return 0; + if (list == NULL) + return 0; - for (node = list->head; node; node = node->next) - length++; + for (node = list->head; node; node = node->next) + length++; - return length; + return length; } token_list_t * -_argument_list_member_at (argument_list_t *list, int index) +_argument_list_member_at(argument_list_t *list, int index) { - argument_node_t *node; - int i; + argument_node_t *node; + int i; - if (list == NULL) - return NULL; + if (list == NULL) + return NULL; - node = list->head; - for (i = 0; i < index; i++) { - node = node->next; - if (node == NULL) - break; - } + node = list->head; + for (i = 0; i < index; i++) { + node = node->next; + if (node == NULL) + break; + } - if (node) - return node->argument; + if (node) + return node->argument; - return NULL; + return NULL; } /* Note: This function ralloc_steal()s the str pointer. */ token_t * -_token_create_str (void *ctx, int type, char *str) +_token_create_str(void *ctx, int type, char *str) { - token_t *token; + token_t *token; - token = ralloc (ctx, token_t); - token->type = type; - token->value.str = str; + token = ralloc (ctx, token_t); + token->type = type; + token->value.str = str; - ralloc_steal (token, str); + ralloc_steal (token, str); - return token; + return token; } token_t * -_token_create_ival (void *ctx, int type, int ival) +_token_create_ival(void *ctx, int type, int ival) { - token_t *token; + token_t *token; - token = ralloc (ctx, token_t); - token->type = type; - token->value.ival = ival; + token = ralloc (ctx, token_t); + token->type = type; + token->value.ival = ival; - return token; + return token; } token_list_t * -_token_list_create (void *ctx) +_token_list_create(void *ctx) { - token_list_t *list; + token_list_t *list; - list = ralloc (ctx, token_list_t); - list->head = NULL; - list->tail = NULL; - list->non_space_tail = NULL; + list = ralloc (ctx, token_list_t); + list->head = NULL; + list->tail = NULL; + list->non_space_tail = NULL; - return list; + return list; } void -_token_list_append (token_list_t *list, token_t *token) +_token_list_append(token_list_t *list, token_t *token) { - token_node_t *node; + token_node_t *node; - node = ralloc (list, token_node_t); - node->token = token; - node->next = NULL; + node = ralloc (list, token_node_t); + node->token = token; + node->next = NULL; - if (list->head == NULL) { - list->head = node; - } else { - list->tail->next = node; - } + if (list->head == NULL) { + list->head = node; + } else { + list->tail->next = node; + } - list->tail = node; - if (token->type != SPACE) - list->non_space_tail = node; + list->tail = node; + if (token->type != SPACE) + list->non_space_tail = node; } void -_token_list_append_list (token_list_t *list, token_list_t *tail) +_token_list_append_list(token_list_t *list, token_list_t *tail) { - if (tail == NULL || tail->head == NULL) - return; + if (tail == NULL || tail->head == NULL) + return; - if (list->head == NULL) { - list->head = tail->head; - } else { - list->tail->next = tail->head; - } + if (list->head == NULL) { + list->head = tail->head; + } else { + list->tail->next = tail->head; + } - list->tail = tail->tail; - list->non_space_tail = tail->non_space_tail; + list->tail = tail->tail; + list->non_space_tail = tail->non_space_tail; } static token_list_t * -_token_list_copy (void *ctx, token_list_t *other) +_token_list_copy(void *ctx, token_list_t *other) { - token_list_t *copy; - token_node_t *node; + token_list_t *copy; + token_node_t *node; - if (other == NULL) - return NULL; + if (other == NULL) + return NULL; - copy = _token_list_create (ctx); - for (node = other->head; node; node = node->next) { - token_t *new_token = ralloc (copy, token_t); - *new_token = *node->token; - _token_list_append (copy, new_token); - } + copy = _token_list_create (ctx); + for (node = other->head; node; node = node->next) { + token_t *new_token = ralloc (copy, token_t); + *new_token = *node->token; + _token_list_append (copy, new_token); + } - return copy; + return copy; } static void -_token_list_trim_trailing_space (token_list_t *list) +_token_list_trim_trailing_space(token_list_t *list) { - token_node_t *tail, *next; + token_node_t *tail, *next; - if (list->non_space_tail) { - tail = list->non_space_tail->next; - list->non_space_tail->next = NULL; - list->tail = list->non_space_tail; + if (list->non_space_tail) { + tail = list->non_space_tail->next; + list->non_space_tail->next = NULL; + list->tail = list->non_space_tail; - while (tail) { - next = tail->next; - ralloc_free (tail); - tail = next; - } - } + while (tail) { + next = tail->next; + ralloc_free (tail); + tail = next; + } + } } static int -_token_list_is_empty_ignoring_space (token_list_t *l) +_token_list_is_empty_ignoring_space(token_list_t *l) { - token_node_t *n; + token_node_t *n; - if (l == NULL) - return 1; + if (l == NULL) + return 1; - n = l->head; - while (n != NULL && n->token->type == SPACE) - n = n->next; + n = l->head; + while (n != NULL && n->token->type == SPACE) + n = n->next; - return n == NULL; + return n == NULL; } int -_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b) +_token_list_equal_ignoring_space(token_list_t *a, token_list_t *b) { - token_node_t *node_a, *node_b; + token_node_t *node_a, *node_b; - if (a == NULL || b == NULL) { - int a_empty = _token_list_is_empty_ignoring_space(a); - int b_empty = _token_list_is_empty_ignoring_space(b); - return a_empty == b_empty; - } + if (a == NULL || b == NULL) { + int a_empty = _token_list_is_empty_ignoring_space(a); + int b_empty = _token_list_is_empty_ignoring_space(b); + return a_empty == b_empty; + } - node_a = a->head; - node_b = b->head; + node_a = a->head; + node_b = b->head; - while (1) - { - if (node_a == NULL && node_b == NULL) - break; + while (1) + { + if (node_a == NULL && node_b == NULL) + break; - if (node_a == NULL || node_b == NULL) - return 0; - /* Make sure whitespace appears in the same places in both. - * It need not be exactly the same amount of whitespace, - * though. - */ - if (node_a->token->type == SPACE - && node_b->token->type == SPACE) { - while (node_a && node_a->token->type == SPACE) - node_a = node_a->next; - while (node_b && node_b->token->type == SPACE) - node_b = node_b->next; - continue; - } + if (node_a == NULL || node_b == NULL) + return 0; + /* Make sure whitespace appears in the same places in both. + * It need not be exactly the same amount of whitespace, + * though. + */ + if (node_a->token->type == SPACE && node_b->token->type == SPACE) { + while (node_a && node_a->token->type == SPACE) + node_a = node_a->next; + while (node_b && node_b->token->type == SPACE) + node_b = node_b->next; + continue; + } - if (node_a->token->type != node_b->token->type) - return 0; + if (node_a->token->type != node_b->token->type) + return 0; - switch (node_a->token->type) { - case INTEGER: - if (node_a->token->value.ival != - node_b->token->value.ival) - { - return 0; - } - break; - case IDENTIFIER: - case INTEGER_STRING: - case OTHER: - if (strcmp (node_a->token->value.str, - node_b->token->value.str)) - { - return 0; - } - break; - } + switch (node_a->token->type) { + case INTEGER: + if (node_a->token->value.ival != node_b->token->value.ival) { + return 0; + } + break; + case IDENTIFIER: + case INTEGER_STRING: + case OTHER: + if (strcmp(node_a->token->value.str, node_b->token->value.str)) { + return 0; + } + break; + } - node_a = node_a->next; - node_b = node_b->next; - } + node_a = node_a->next; + node_b = node_b->next; + } - return 1; + return 1; } static void -_token_print (char **out, size_t *len, token_t *token) +_token_print(char **out, size_t *len, token_t *token) { - if (token->type < 256) { - ralloc_asprintf_rewrite_tail (out, len, "%c", token->type); - return; - } + if (token->type < 256) { + ralloc_asprintf_rewrite_tail (out, len, "%c", token->type); + return; + } - switch (token->type) { - case INTEGER: - ralloc_asprintf_rewrite_tail (out, len, "%" PRIiMAX, token->value.ival); - break; - case IDENTIFIER: - case INTEGER_STRING: - case OTHER: - ralloc_asprintf_rewrite_tail (out, len, "%s", token->value.str); - break; - case SPACE: - ralloc_asprintf_rewrite_tail (out, len, " "); - break; - case LEFT_SHIFT: - ralloc_asprintf_rewrite_tail (out, len, "<<"); - break; - case RIGHT_SHIFT: - ralloc_asprintf_rewrite_tail (out, len, ">>"); - break; - case LESS_OR_EQUAL: - ralloc_asprintf_rewrite_tail (out, len, "<="); - break; - case GREATER_OR_EQUAL: - ralloc_asprintf_rewrite_tail (out, len, ">="); - break; - case EQUAL: - ralloc_asprintf_rewrite_tail (out, len, "=="); - break; - case NOT_EQUAL: - ralloc_asprintf_rewrite_tail (out, len, "!="); - break; - case AND: - ralloc_asprintf_rewrite_tail (out, len, "&&"); - break; - case OR: - ralloc_asprintf_rewrite_tail (out, len, "||"); - break; - case PASTE: - ralloc_asprintf_rewrite_tail (out, len, "##"); - break; - case PLUS_PLUS: - ralloc_asprintf_rewrite_tail (out, len, "++"); - break; - case MINUS_MINUS: - ralloc_asprintf_rewrite_tail (out, len, "--"); - break; - case DEFINED: - ralloc_asprintf_rewrite_tail (out, len, "defined"); - break; - case PLACEHOLDER: - /* Nothing to print. */ - break; - default: - assert(!"Error: Don't know how to print token."); + switch (token->type) { + case INTEGER: + ralloc_asprintf_rewrite_tail (out, len, "%" PRIiMAX, token->value.ival); + break; + case IDENTIFIER: + case INTEGER_STRING: + case OTHER: + ralloc_asprintf_rewrite_tail (out, len, "%s", token->value.str); + break; + case SPACE: + ralloc_asprintf_rewrite_tail (out, len, " "); + break; + case LEFT_SHIFT: + ralloc_asprintf_rewrite_tail (out, len, "<<"); + break; + case RIGHT_SHIFT: + ralloc_asprintf_rewrite_tail (out, len, ">>"); + break; + case LESS_OR_EQUAL: + ralloc_asprintf_rewrite_tail (out, len, "<="); + break; + case GREATER_OR_EQUAL: + ralloc_asprintf_rewrite_tail (out, len, ">="); + break; + case EQUAL: + ralloc_asprintf_rewrite_tail (out, len, "=="); + break; + case NOT_EQUAL: + ralloc_asprintf_rewrite_tail (out, len, "!="); + break; + case AND: + ralloc_asprintf_rewrite_tail (out, len, "&&"); + break; + case OR: + ralloc_asprintf_rewrite_tail (out, len, "||"); + break; + case PASTE: + ralloc_asprintf_rewrite_tail (out, len, "##"); + break; + case PLUS_PLUS: + ralloc_asprintf_rewrite_tail (out, len, "++"); + break; + case MINUS_MINUS: + ralloc_asprintf_rewrite_tail (out, len, "--"); + break; + case DEFINED: + ralloc_asprintf_rewrite_tail (out, len, "defined"); + break; + case PLACEHOLDER: + /* Nothing to print. */ + break; + default: + assert(!"Error: Don't know how to print token."); - break; - } + break; + } } /* Return a new token (ralloc()ed off of 'token') formed by pasting @@ -1171,148 +1162,143 @@ _token_print (char **out, size_t *len, token_t *token) * Caution: Only very cursory error-checking is performed to see if * the final result is a valid single token. */ static token_t * -_token_paste (glcpp_parser_t *parser, token_t *token, token_t *other) +_token_paste(glcpp_parser_t *parser, token_t *token, token_t *other) { - token_t *combined = NULL; + token_t *combined = NULL; - /* Pasting a placeholder onto anything makes no change. */ - if (other->type == PLACEHOLDER) - return token; + /* Pasting a placeholder onto anything makes no change. */ + if (other->type == PLACEHOLDER) + return token; - /* When 'token' is a placeholder, just return 'other'. */ - if (token->type == PLACEHOLDER) - return other; + /* When 'token' is a placeholder, just return 'other'. */ + if (token->type == PLACEHOLDER) + return other; - /* A very few single-character punctuators can be combined - * with another to form a multi-character punctuator. */ - switch (token->type) { - case '<': - if (other->type == '<') - combined = _token_create_ival (token, LEFT_SHIFT, LEFT_SHIFT); - else if (other->type == '=') - combined = _token_create_ival (token, LESS_OR_EQUAL, LESS_OR_EQUAL); - break; - case '>': - if (other->type == '>') - combined = _token_create_ival (token, RIGHT_SHIFT, RIGHT_SHIFT); - else if (other->type == '=') - combined = _token_create_ival (token, GREATER_OR_EQUAL, GREATER_OR_EQUAL); - break; - case '=': - if (other->type == '=') - combined = _token_create_ival (token, EQUAL, EQUAL); - break; - case '!': - if (other->type == '=') - combined = _token_create_ival (token, NOT_EQUAL, NOT_EQUAL); - break; - case '&': - if (other->type == '&') - combined = _token_create_ival (token, AND, AND); - break; - case '|': - if (other->type == '|') - combined = _token_create_ival (token, OR, OR); - break; - } + /* A very few single-character punctuators can be combined + * with another to form a multi-character punctuator. */ + switch (token->type) { + case '<': + if (other->type == '<') + combined = _token_create_ival (token, LEFT_SHIFT, LEFT_SHIFT); + else if (other->type == '=') + combined = _token_create_ival (token, LESS_OR_EQUAL, LESS_OR_EQUAL); + break; + case '>': + if (other->type == '>') + combined = _token_create_ival (token, RIGHT_SHIFT, RIGHT_SHIFT); + else if (other->type == '=') + combined = _token_create_ival (token, GREATER_OR_EQUAL, GREATER_OR_EQUAL); + break; + case '=': + if (other->type == '=') + combined = _token_create_ival (token, EQUAL, EQUAL); + break; + case '!': + if (other->type == '=') + combined = _token_create_ival (token, NOT_EQUAL, NOT_EQUAL); + break; + case '&': + if (other->type == '&') + combined = _token_create_ival (token, AND, AND); + break; + case '|': + if (other->type == '|') + combined = _token_create_ival (token, OR, OR); + break; + } - if (combined != NULL) { - /* Inherit the location from the first token */ - combined->location = token->location; - return combined; - } + if (combined != NULL) { + /* Inherit the location from the first token */ + combined->location = token->location; + return combined; + } - /* Two string-valued (or integer) tokens can usually just be - * mashed together. (We also handle a string followed by an - * integer here as well.) - * - * There are some exceptions here. Notably, if the first token - * is an integer (or a string representing an integer), then - * the second token must also be an integer or must be a - * string representing an integer that begins with a digit. - */ - if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING || token->type == INTEGER) && - (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING || other->type == INTEGER)) - { - char *str; - int combined_type; + /* Two string-valued (or integer) tokens can usually just be + * mashed together. (We also handle a string followed by an + * integer here as well.) + * + * There are some exceptions here. Notably, if the first token + * is an integer (or a string representing an integer), then + * the second token must also be an integer or must be a + * string representing an integer that begins with a digit. + */ + if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING || token->type == INTEGER) && + (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING || other->type == INTEGER)) + { + char *str; + int combined_type; - /* Check that pasting onto an integer doesn't create a - * non-integer, (that is, only digits can be - * pasted. */ - if (token->type == INTEGER_STRING || token->type == INTEGER) - { - switch (other->type) { - case INTEGER_STRING: - if (other->value.str[0] < '0' || - other->value.str[0] > '9') - goto FAIL; - break; - case INTEGER: - if (other->value.ival < 0) - goto FAIL; - break; - default: - goto FAIL; - } - } + /* Check that pasting onto an integer doesn't create a + * non-integer, (that is, only digits can be + * pasted. */ + if (token->type == INTEGER_STRING || token->type == INTEGER) { + switch (other->type) { + case INTEGER_STRING: + if (other->value.str[0] < '0' || other->value.str[0] > '9') + goto FAIL; + break; + case INTEGER: + if (other->value.ival < 0) + goto FAIL; + break; + default: + goto FAIL; + } + } - if (token->type == INTEGER) - str = ralloc_asprintf (token, "%" PRIiMAX, - token->value.ival); - else - str = ralloc_strdup (token, token->value.str); - + if (token->type == INTEGER) + str = ralloc_asprintf (token, "%" PRIiMAX, token->value.ival); + else + str = ralloc_strdup (token, token->value.str); - if (other->type == INTEGER) - ralloc_asprintf_append (&str, "%" PRIiMAX, - other->value.ival); - else - ralloc_strcat (&str, other->value.str); + if (other->type == INTEGER) + ralloc_asprintf_append (&str, "%" PRIiMAX, other->value.ival); + else + ralloc_strcat (&str, other->value.str); - /* New token is same type as original token, unless we - * started with an integer, in which case we will be - * creating an integer-string. */ - combined_type = token->type; - if (combined_type == INTEGER) - combined_type = INTEGER_STRING; + /* New token is same type as original token, unless we + * started with an integer, in which case we will be + * creating an integer-string. */ + combined_type = token->type; + if (combined_type == INTEGER) + combined_type = INTEGER_STRING; - combined = _token_create_str (token, combined_type, str); - combined->location = token->location; - return combined; - } + combined = _token_create_str (token, combined_type, str); + combined->location = token->location; + return combined; + } FAIL: - glcpp_error (&token->location, parser, ""); - ralloc_asprintf_rewrite_tail (&parser->info_log, &parser->info_log_length, "Pasting \""); - _token_print (&parser->info_log, &parser->info_log_length, token); - ralloc_asprintf_rewrite_tail (&parser->info_log, &parser->info_log_length, "\" and \""); - _token_print (&parser->info_log, &parser->info_log_length, other); - ralloc_asprintf_rewrite_tail (&parser->info_log, &parser->info_log_length, "\" does not give a valid preprocessing token.\n"); + glcpp_error (&token->location, parser, ""); + ralloc_asprintf_rewrite_tail (&parser->info_log, &parser->info_log_length, "Pasting \""); + _token_print (&parser->info_log, &parser->info_log_length, token); + ralloc_asprintf_rewrite_tail (&parser->info_log, &parser->info_log_length, "\" and \""); + _token_print (&parser->info_log, &parser->info_log_length, other); + ralloc_asprintf_rewrite_tail (&parser->info_log, &parser->info_log_length, "\" does not give a valid preprocessing token.\n"); - return token; + return token; } static void -_token_list_print (glcpp_parser_t *parser, token_list_t *list) +_token_list_print(glcpp_parser_t *parser, token_list_t *list) { - token_node_t *node; + token_node_t *node; - if (list == NULL) - return; + if (list == NULL) + return; - for (node = list->head; node; node = node->next) - _token_print (&parser->output, &parser->output_length, node->token); + for (node = list->head; node; node = node->next) + _token_print (&parser->output, &parser->output_length, node->token); } void -yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error) +yyerror(YYLTYPE *locp, glcpp_parser_t *parser, const char *error) { - glcpp_error(locp, parser, "%s", error); + glcpp_error(locp, parser, "%s", error); } -static void add_builtin_define(glcpp_parser_t *parser, - const char *name, int value) +static void +add_builtin_define(glcpp_parser_t *parser, const char *name, int value) { token_t *tok; token_list_t *list; @@ -1325,63 +1311,63 @@ static void add_builtin_define(glcpp_parser_t *parser, } glcpp_parser_t * -glcpp_parser_create (const struct gl_extensions *extensions, gl_api api) +glcpp_parser_create(const struct gl_extensions *extensions, gl_api api) { - glcpp_parser_t *parser; + glcpp_parser_t *parser; - parser = ralloc (NULL, glcpp_parser_t); + parser = ralloc (NULL, glcpp_parser_t); - glcpp_lex_init_extra (parser, &parser->scanner); - parser->defines = hash_table_ctor (32, hash_table_string_hash, - hash_table_string_compare); - parser->active = NULL; - parser->lexing_directive = 0; - parser->space_tokens = 1; - parser->last_token_was_newline = 0; - parser->last_token_was_space = 0; - parser->first_non_space_token_this_line = 1; - parser->newline_as_space = 0; - parser->in_control_line = 0; - parser->paren_count = 0; - parser->commented_newlines = 0; + glcpp_lex_init_extra (parser, &parser->scanner); + parser->defines = hash_table_ctor(32, hash_table_string_hash, + hash_table_string_compare); + parser->active = NULL; + parser->lexing_directive = 0; + parser->space_tokens = 1; + parser->last_token_was_newline = 0; + parser->last_token_was_space = 0; + parser->first_non_space_token_this_line = 1; + parser->newline_as_space = 0; + parser->in_control_line = 0; + parser->paren_count = 0; + parser->commented_newlines = 0; - parser->skip_stack = NULL; - parser->skipping = 0; + parser->skip_stack = NULL; + parser->skipping = 0; - parser->lex_from_list = NULL; - parser->lex_from_node = NULL; + parser->lex_from_list = NULL; + parser->lex_from_node = NULL; - parser->output = ralloc_strdup(parser, ""); - parser->output_length = 0; - parser->info_log = ralloc_strdup(parser, ""); - parser->info_log_length = 0; - parser->error = 0; + parser->output = ralloc_strdup(parser, ""); + parser->output_length = 0; + parser->info_log = ralloc_strdup(parser, ""); + parser->info_log_length = 0; + parser->error = 0; - parser->extensions = extensions; - parser->api = api; - parser->version_resolved = false; + parser->extensions = extensions; + parser->api = api; + parser->version_resolved = false; - parser->has_new_line_number = 0; - parser->new_line_number = 1; - parser->has_new_source_number = 0; - parser->new_source_number = 0; + parser->has_new_line_number = 0; + parser->new_line_number = 1; + parser->has_new_source_number = 0; + parser->new_source_number = 0; - return parser; + return parser; } void -glcpp_parser_destroy (glcpp_parser_t *parser) +glcpp_parser_destroy(glcpp_parser_t *parser) { - glcpp_lex_destroy (parser->scanner); - hash_table_dtor (parser->defines); - ralloc_free (parser); + glcpp_lex_destroy (parser->scanner); + hash_table_dtor (parser->defines); + ralloc_free (parser); } typedef enum function_status { - FUNCTION_STATUS_SUCCESS, - FUNCTION_NOT_A_FUNCTION, - FUNCTION_UNBALANCED_PARENTHESES + FUNCTION_STATUS_SUCCESS, + FUNCTION_NOT_A_FUNCTION, + FUNCTION_UNBALANCED_PARENTHESES } function_status_t; /* Find a set of function-like macro arguments by looking for a @@ -1396,100 +1382,92 @@ typedef enum function_status * * FUNCTION_STATUS_SUCCESS: * - * Successfully parsed a set of function arguments. + * Successfully parsed a set of function arguments. * * FUNCTION_NOT_A_FUNCTION: * - * Macro name not followed by a '('. This is not an error, but - * simply that the macro name should be treated as a non-macro. + * Macro name not followed by a '('. This is not an error, but + * simply that the macro name should be treated as a non-macro. * * FUNCTION_UNBALANCED_PARENTHESES * - * Macro name is not followed by a balanced set of parentheses. + * Macro name is not followed by a balanced set of parentheses. */ static function_status_t -_arguments_parse (argument_list_t *arguments, - token_node_t *node, - token_node_t **last) +_arguments_parse(argument_list_t *arguments, token_node_t *node, + token_node_t **last) { - token_list_t *argument; - int paren_count; + token_list_t *argument; + int paren_count; - node = node->next; + node = node->next; - /* Ignore whitespace before first parenthesis. */ - while (node && node->token->type == SPACE) - node = node->next; + /* Ignore whitespace before first parenthesis. */ + while (node && node->token->type == SPACE) + node = node->next; - if (node == NULL || node->token->type != '(') - return FUNCTION_NOT_A_FUNCTION; + if (node == NULL || node->token->type != '(') + return FUNCTION_NOT_A_FUNCTION; - node = node->next; + node = node->next; - argument = _token_list_create (arguments); - _argument_list_append (arguments, argument); + argument = _token_list_create (arguments); + _argument_list_append (arguments, argument); - for (paren_count = 1; node; node = node->next) { - if (node->token->type == '(') - { - paren_count++; - } - else if (node->token->type == ')') - { - paren_count--; - if (paren_count == 0) - break; - } + for (paren_count = 1; node; node = node->next) { + if (node->token->type == '(') { + paren_count++; + } else if (node->token->type == ')') { + paren_count--; + if (paren_count == 0) + break; + } - if (node->token->type == ',' && - paren_count == 1) - { - _token_list_trim_trailing_space (argument); - argument = _token_list_create (arguments); - _argument_list_append (arguments, argument); - } - else { - if (argument->head == NULL) { - /* Don't treat initial whitespace as - * part of the argument. */ - if (node->token->type == SPACE) - continue; - } - _token_list_append (argument, node->token); - } - } + if (node->token->type == ',' && paren_count == 1) { + _token_list_trim_trailing_space (argument); + argument = _token_list_create (arguments); + _argument_list_append (arguments, argument); + } else { + if (argument->head == NULL) { + /* Don't treat initial whitespace as part of the argument. */ + if (node->token->type == SPACE) + continue; + } + _token_list_append (argument, node->token); + } + } - if (paren_count) - return FUNCTION_UNBALANCED_PARENTHESES; + if (paren_count) + return FUNCTION_UNBALANCED_PARENTHESES; - *last = node; + *last = node; - return FUNCTION_STATUS_SUCCESS; + return FUNCTION_STATUS_SUCCESS; } static token_list_t * -_token_list_create_with_one_ival (void *ctx, int type, int ival) +_token_list_create_with_one_ival(void *ctx, int type, int ival) { - token_list_t *list; - token_t *node; + token_list_t *list; + token_t *node; - list = _token_list_create (ctx); - node = _token_create_ival (list, type, ival); - _token_list_append (list, node); + list = _token_list_create(ctx); + node = _token_create_ival(list, type, ival); + _token_list_append(list, node); - return list; + return list; } static token_list_t * -_token_list_create_with_one_space (void *ctx) +_token_list_create_with_one_space(void *ctx) { - return _token_list_create_with_one_ival (ctx, SPACE, SPACE); + return _token_list_create_with_one_ival(ctx, SPACE, SPACE); } static token_list_t * -_token_list_create_with_one_integer (void *ctx, int ival) +_token_list_create_with_one_integer(void *ctx, int ival) { - return _token_list_create_with_one_ival (ctx, INTEGER, ival); + return _token_list_create_with_one_ival(ctx, INTEGER, ival); } /* Evaluate a DEFINED token node (based on subsequent tokens in the list). @@ -1501,119 +1479,117 @@ _token_list_create_with_one_integer (void *ctx, int ival) * (optionally preceded and followed by '(' and ')' tokens) then the following * occurs: * - * If the identifier is a defined macro, this function returns 1. + * If the identifier is a defined macro, this function returns 1. * - * If the identifier is not a defined macro, this function returns 0. + * If the identifier is not a defined macro, this function returns 0. * - * In either case, *last will be updated to the last node in the list - * consumed by the evaluation, (either the token of the identifier or the - * token of the closing parenthesis). + * In either case, *last will be updated to the last node in the list + * consumed by the evaluation, (either the token of the identifier or the + * token of the closing parenthesis). * * In all other cases, (such as "node is the final node of the list", or * "missing closing parenthesis", etc.), this function generates a * preprocessor error, returns -1 and *last will not be set. */ static int -_glcpp_parser_evaluate_defined (glcpp_parser_t *parser, - token_node_t *node, - token_node_t **last) +_glcpp_parser_evaluate_defined(glcpp_parser_t *parser, token_node_t *node, + token_node_t **last) { - token_node_t *argument, *defined = node; + token_node_t *argument, *defined = node; - assert (node->token->type == DEFINED); + assert(node->token->type == DEFINED); - node = node->next; + node = node->next; - /* Ignore whitespace after DEFINED token. */ - while (node && node->token->type == SPACE) - node = node->next; + /* Ignore whitespace after DEFINED token. */ + while (node && node->token->type == SPACE) + node = node->next; - if (node == NULL) - goto FAIL; + if (node == NULL) + goto FAIL; - if (node->token->type == IDENTIFIER || node->token->type == OTHER) { - argument = node; - } else if (node->token->type == '(') { - node = node->next; + if (node->token->type == IDENTIFIER || node->token->type == OTHER) { + argument = node; + } else if (node->token->type == '(') { + node = node->next; - /* Ignore whitespace after '(' token. */ - while (node && node->token->type == SPACE) - node = node->next; + /* Ignore whitespace after '(' token. */ + while (node && node->token->type == SPACE) + node = node->next; - if (node == NULL || (node->token->type != IDENTIFIER && - node->token->type != OTHER)) - { - goto FAIL; - } + if (node == NULL || (node->token->type != IDENTIFIER && + node->token->type != OTHER)) { + goto FAIL; + } - argument = node; + argument = node; - node = node->next; + node = node->next; - /* Ignore whitespace after identifier, before ')' token. */ - while (node && node->token->type == SPACE) - node = node->next; + /* Ignore whitespace after identifier, before ')' token. */ + while (node && node->token->type == SPACE) + node = node->next; - if (node == NULL || node->token->type != ')') - goto FAIL; - } else { - goto FAIL; - } + if (node == NULL || node->token->type != ')') + goto FAIL; + } else { + goto FAIL; + } - *last = node; + *last = node; - return hash_table_find (parser->defines, - argument->token->value.str) ? 1 : 0; + return hash_table_find(parser->defines, + argument->token->value.str) ? 1 : 0; FAIL: - glcpp_error (&defined->token->location, parser, - "\"defined\" not followed by an identifier"); - return -1; + glcpp_error (&defined->token->location, parser, + "\"defined\" not followed by an identifier"); + return -1; } /* Evaluate all DEFINED nodes in a given list, modifying the list in place. */ static void -_glcpp_parser_evaluate_defined_in_list (glcpp_parser_t *parser, - token_list_t *list) +_glcpp_parser_evaluate_defined_in_list(glcpp_parser_t *parser, + token_list_t *list) { - token_node_t *node, *node_prev, *replacement, *last = NULL; - int value; + token_node_t *node, *node_prev, *replacement, *last = NULL; + int value; - if (list == NULL) - return; + if (list == NULL) + return; - node_prev = NULL; - node = list->head; + node_prev = NULL; + node = list->head; - while (node) { + while (node) { - if (node->token->type != DEFINED) - goto NEXT; + if (node->token->type != DEFINED) + goto NEXT; - value = _glcpp_parser_evaluate_defined (parser, node, &last); - if (value == -1) - goto NEXT; + value = _glcpp_parser_evaluate_defined (parser, node, &last); + if (value == -1) + goto NEXT; - replacement = ralloc (list, token_node_t); - replacement->token = _token_create_ival (list, INTEGER, value); + replacement = ralloc (list, token_node_t); + replacement->token = _token_create_ival (list, INTEGER, value); - /* Splice replacement node into list, replacing from "node" - * through "last". */ - if (node_prev) - node_prev->next = replacement; - else - list->head = replacement; - replacement->next = last->next; - if (last == list->tail) - list->tail = replacement; + /* Splice replacement node into list, replacing from "node" + * through "last". */ + if (node_prev) + node_prev->next = replacement; + else + list->head = replacement; + replacement->next = last->next; + if (last == list->tail) + list->tail = replacement; - node = replacement; + node = replacement; - NEXT: - node_prev = node; - node = node->next; - } + NEXT: + node_prev = node; + node = node->next; + } } /* Perform macro expansion on 'list', placing the resulting tokens @@ -1625,62 +1601,59 @@ _glcpp_parser_evaluate_defined_in_list (glcpp_parser_t *parser, * of the "mode" parameter. */ static void -_glcpp_parser_expand_and_lex_from (glcpp_parser_t *parser, - int head_token_type, - token_list_t *list, - expansion_mode_t mode) +_glcpp_parser_expand_and_lex_from(glcpp_parser_t *parser, int head_token_type, + token_list_t *list, expansion_mode_t mode) { - token_list_t *expanded; - token_t *token; + token_list_t *expanded; + token_t *token; - expanded = _token_list_create (parser); - token = _token_create_ival (parser, head_token_type, head_token_type); - _token_list_append (expanded, token); - _glcpp_parser_expand_token_list (parser, list, mode); - _token_list_append_list (expanded, list); - glcpp_parser_lex_from (parser, expanded); + expanded = _token_list_create (parser); + token = _token_create_ival (parser, head_token_type, head_token_type); + _token_list_append (expanded, token); + _glcpp_parser_expand_token_list (parser, list, mode); + _token_list_append_list (expanded, list); + glcpp_parser_lex_from (parser, expanded); } static void -_glcpp_parser_apply_pastes (glcpp_parser_t *parser, token_list_t *list) +_glcpp_parser_apply_pastes(glcpp_parser_t *parser, token_list_t *list) { - token_node_t *node; + token_node_t *node; - node = list->head; - while (node) - { - token_node_t *next_non_space; + node = list->head; + while (node) { + token_node_t *next_non_space; - /* Look ahead for a PASTE token, skipping space. */ - next_non_space = node->next; - while (next_non_space && next_non_space->token->type == SPACE) - next_non_space = next_non_space->next; + /* Look ahead for a PASTE token, skipping space. */ + next_non_space = node->next; + while (next_non_space && next_non_space->token->type == SPACE) + next_non_space = next_non_space->next; - if (next_non_space == NULL) - break; + if (next_non_space == NULL) + break; - if (next_non_space->token->type != PASTE) { - node = next_non_space; - continue; - } + if (next_non_space->token->type != PASTE) { + node = next_non_space; + continue; + } - /* Now find the next non-space token after the PASTE. */ - next_non_space = next_non_space->next; - while (next_non_space && next_non_space->token->type == SPACE) - next_non_space = next_non_space->next; + /* Now find the next non-space token after the PASTE. */ + next_non_space = next_non_space->next; + while (next_non_space && next_non_space->token->type == SPACE) + next_non_space = next_non_space->next; - if (next_non_space == NULL) { - yyerror (&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n"); - return; - } + if (next_non_space == NULL) { + yyerror(&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n"); + return; + } - node->token = _token_paste (parser, node->token, next_non_space->token); - node->next = next_non_space->next; - if (next_non_space == list->tail) - list->tail = node; - } + node->token = _token_paste(parser, node->token, next_non_space->token); + node->next = next_non_space->next; + if (next_non_space == list->tail) + list->tail = node; + } - list->non_space_tail = list->tail; + list->non_space_tail = list->tail; } /* This is a helper function that's essentially part of the @@ -1704,103 +1677,89 @@ _glcpp_parser_apply_pastes (glcpp_parser_t *parser, token_list_t *list) * of the "mode" parameter. */ static token_list_t * -_glcpp_parser_expand_function (glcpp_parser_t *parser, - token_node_t *node, - token_node_t **last, - expansion_mode_t mode) +_glcpp_parser_expand_function(glcpp_parser_t *parser, token_node_t *node, + token_node_t **last, expansion_mode_t mode) { - macro_t *macro; - const char *identifier; - argument_list_t *arguments; - function_status_t status; - token_list_t *substituted; - int parameter_index; + macro_t *macro; + const char *identifier; + argument_list_t *arguments; + function_status_t status; + token_list_t *substituted; + int parameter_index; - identifier = node->token->value.str; + identifier = node->token->value.str; - macro = hash_table_find (parser->defines, identifier); + macro = hash_table_find(parser->defines, identifier); - assert (macro->is_function); + assert(macro->is_function); - arguments = _argument_list_create (parser); - status = _arguments_parse (arguments, node, last); + arguments = _argument_list_create(parser); + status = _arguments_parse(arguments, node, last); - switch (status) { - case FUNCTION_STATUS_SUCCESS: - break; - case FUNCTION_NOT_A_FUNCTION: - return NULL; - case FUNCTION_UNBALANCED_PARENTHESES: - glcpp_error (&node->token->location, parser, "Macro %s call has unbalanced parentheses\n", identifier); - return NULL; - } + switch (status) { + case FUNCTION_STATUS_SUCCESS: + break; + case FUNCTION_NOT_A_FUNCTION: + return NULL; + case FUNCTION_UNBALANCED_PARENTHESES: + glcpp_error(&node->token->location, parser, "Macro %s call has unbalanced parentheses\n", identifier); + return NULL; + } - /* Replace a macro defined as empty with a SPACE token. */ - if (macro->replacements == NULL) { - ralloc_free (arguments); - return _token_list_create_with_one_space (parser); - } + /* Replace a macro defined as empty with a SPACE token. */ + if (macro->replacements == NULL) { + ralloc_free(arguments); + return _token_list_create_with_one_space(parser); + } - if (! ((_argument_list_length (arguments) == - _string_list_length (macro->parameters)) || - (_string_list_length (macro->parameters) == 0 && - _argument_list_length (arguments) == 1 && - arguments->head->argument->head == NULL))) - { - glcpp_error (&node->token->location, parser, - "Error: macro %s invoked with %d arguments (expected %d)\n", - identifier, - _argument_list_length (arguments), - _string_list_length (macro->parameters)); - return NULL; - } + if (!((_argument_list_length (arguments) == + _string_list_length (macro->parameters)) || + (_string_list_length (macro->parameters) == 0 && + _argument_list_length (arguments) == 1 && + arguments->head->argument->head == NULL))) { + glcpp_error(&node->token->location, parser, + "Error: macro %s invoked with %d arguments (expected %d)\n", + identifier, _argument_list_length (arguments), + _string_list_length(macro->parameters)); + return NULL; + } - /* Perform argument substitution on the replacement list. */ - substituted = _token_list_create (arguments); + /* Perform argument substitution on the replacement list. */ + substituted = _token_list_create(arguments); - for (node = macro->replacements->head; node; node = node->next) - { - if (node->token->type == IDENTIFIER && - _string_list_contains (macro->parameters, - node->token->value.str, - ¶meter_index)) - { - token_list_t *argument; - argument = _argument_list_member_at (arguments, - parameter_index); - /* Before substituting, we expand the argument - * tokens, or append a placeholder token for - * an empty argument. */ - if (argument->head) { - token_list_t *expanded_argument; - expanded_argument = _token_list_copy (parser, - argument); - _glcpp_parser_expand_token_list (parser, - expanded_argument, - mode); - _token_list_append_list (substituted, - expanded_argument); - } else { - token_t *new_token; + for (node = macro->replacements->head; node; node = node->next) { + if (node->token->type == IDENTIFIER && + _string_list_contains(macro->parameters, node->token->value.str, + ¶meter_index)) { + token_list_t *argument; + argument = _argument_list_member_at(arguments, parameter_index); + /* Before substituting, we expand the argument tokens, or append a + * placeholder token for an empty argument. */ + if (argument->head) { + token_list_t *expanded_argument; + expanded_argument = _token_list_copy(parser, argument); + _glcpp_parser_expand_token_list(parser, expanded_argument, mode); + _token_list_append_list(substituted, expanded_argument); + } else { + token_t *new_token; - new_token = _token_create_ival (substituted, - PLACEHOLDER, - PLACEHOLDER); - _token_list_append (substituted, new_token); - } - } else { - _token_list_append (substituted, node->token); - } - } + new_token = _token_create_ival(substituted, PLACEHOLDER, + PLACEHOLDER); + _token_list_append(substituted, new_token); + } + } else { + _token_list_append(substituted, node->token); + } + } - /* After argument substitution, and before further expansion - * below, implement token pasting. */ + /* After argument substitution, and before further expansion + * below, implement token pasting. */ - _token_list_trim_trailing_space (substituted); + _token_list_trim_trailing_space(substituted); - _glcpp_parser_apply_pastes (parser, substituted); + _glcpp_parser_apply_pastes(parser, substituted); - return substituted; + return substituted; } /* Compute the complete expansion of node, (and subsequent nodes after @@ -1813,78 +1772,74 @@ _glcpp_parser_expand_function (glcpp_parser_t *parser, * and sets *last to the last node in the list that was consumed by * the expansion. Specifically, *last will be set as follows: * - * As 'node' in the case of object-like macro expansion. + * As 'node' in the case of object-like macro expansion. * - * As the token of the closing right parenthesis in the case of - * function-like macro expansion. + * As the token of the closing right parenthesis in the case of + * function-like macro expansion. * * See the documentation of _glcpp_parser_expand_token_list for a description * of the "mode" parameter. */ static token_list_t * -_glcpp_parser_expand_node (glcpp_parser_t *parser, - token_node_t *node, - token_node_t **last, - expansion_mode_t mode) +_glcpp_parser_expand_node(glcpp_parser_t *parser, token_node_t *node, + token_node_t **last, expansion_mode_t mode) { - token_t *token = node->token; - const char *identifier; - macro_t *macro; + token_t *token = node->token; + const char *identifier; + macro_t *macro; - /* We only expand identifiers */ - if (token->type != IDENTIFIER) { - return NULL; - } + /* We only expand identifiers */ + if (token->type != IDENTIFIER) { + return NULL; + } - *last = node; - identifier = token->value.str; + *last = node; + identifier = token->value.str; - /* Special handling for __LINE__ and __FILE__, (not through - * the hash table). */ - if (strcmp(identifier, "__LINE__") == 0) - return _token_list_create_with_one_integer (parser, node->token->location.first_line); + /* Special handling for __LINE__ and __FILE__, (not through + * the hash table). */ + if (strcmp(identifier, "__LINE__") == 0) + return _token_list_create_with_one_integer(parser, node->token->location.first_line); - if (strcmp(identifier, "__FILE__") == 0) - return _token_list_create_with_one_integer (parser, node->token->location.source); + if (strcmp(identifier, "__FILE__") == 0) + return _token_list_create_with_one_integer(parser, node->token->location.source); - /* Look up this identifier in the hash table. */ - macro = hash_table_find (parser->defines, identifier); + /* Look up this identifier in the hash table. */ + macro = hash_table_find(parser->defines, identifier); - /* Not a macro, so no expansion needed. */ - if (macro == NULL) - return NULL; + /* Not a macro, so no expansion needed. */ + if (macro == NULL) + return NULL; - /* Finally, don't expand this macro if we're already actively - * expanding it, (to avoid infinite recursion). */ - if (_parser_active_list_contains (parser, identifier)) { - /* We change the token type here from IDENTIFIER to - * OTHER to prevent any future expansion of this - * unexpanded token. */ - char *str; - token_list_t *expansion; - token_t *final; + /* Finally, don't expand this macro if we're already actively + * expanding it, (to avoid infinite recursion). */ + if (_parser_active_list_contains (parser, identifier)) { + /* We change the token type here from IDENTIFIER to OTHER to prevent any + * future expansion of this unexpanded token. */ + char *str; + token_list_t *expansion; + token_t *final; - str = ralloc_strdup (parser, token->value.str); - final = _token_create_str (parser, OTHER, str); - expansion = _token_list_create (parser); - _token_list_append (expansion, final); - return expansion; - } + str = ralloc_strdup(parser, token->value.str); + final = _token_create_str(parser, OTHER, str); + expansion = _token_list_create(parser); + _token_list_append(expansion, final); + return expansion; + } - if (! macro->is_function) - { - token_list_t *replacement; + if (! macro->is_function) { + token_list_t *replacement; - /* Replace a macro defined as empty with a SPACE token. */ - if (macro->replacements == NULL) - return _token_list_create_with_one_space (parser); + /* Replace a macro defined as empty with a SPACE token. */ + if (macro->replacements == NULL) + return _token_list_create_with_one_space(parser); - replacement = _token_list_copy (parser, macro->replacements); - _glcpp_parser_apply_pastes (parser, replacement); - return replacement; - } + replacement = _token_list_copy(parser, macro->replacements); + _glcpp_parser_apply_pastes(parser, replacement); + return replacement; + } - return _glcpp_parser_expand_function (parser, node, last, mode); + return _glcpp_parser_expand_function(parser, node, last, mode); } /* Push a new identifier onto the parser's active list. @@ -1895,49 +1850,48 @@ _glcpp_parser_expand_node (glcpp_parser_t *parser, * active stack. */ static void -_parser_active_list_push (glcpp_parser_t *parser, - const char *identifier, - token_node_t *marker) +_parser_active_list_push(glcpp_parser_t *parser, const char *identifier, + token_node_t *marker) { - active_list_t *node; + active_list_t *node; - node = ralloc (parser->active, active_list_t); - node->identifier = ralloc_strdup (node, identifier); - node->marker = marker; - node->next = parser->active; + node = ralloc(parser->active, active_list_t); + node->identifier = ralloc_strdup(node, identifier); + node->marker = marker; + node->next = parser->active; - parser->active = node; + parser->active = node; } static void -_parser_active_list_pop (glcpp_parser_t *parser) +_parser_active_list_pop(glcpp_parser_t *parser) { - active_list_t *node = parser->active; + active_list_t *node = parser->active; - if (node == NULL) { - parser->active = NULL; - return; - } + if (node == NULL) { + parser->active = NULL; + return; + } - node = parser->active->next; - ralloc_free (parser->active); + node = parser->active->next; + ralloc_free (parser->active); - parser->active = node; + parser->active = node; } static int -_parser_active_list_contains (glcpp_parser_t *parser, const char *identifier) +_parser_active_list_contains(glcpp_parser_t *parser, const char *identifier) { - active_list_t *node; + active_list_t *node; - if (parser->active == NULL) - return 0; + if (parser->active == NULL) + return 0; - for (node = parser->active; node; node = node->next) - if (strcmp (node->identifier, identifier) == 0) - return 1; + for (node = parser->active; node; node = node->next) + if (strcmp(node->identifier, identifier) == 0) + return 1; - return 0; + return 0; } /* Walk over the token list replacing nodes with their expansion. @@ -1948,400 +1902,376 @@ _parser_active_list_contains (glcpp_parser_t *parser, const char *identifier) * The "mode" argument controls the handling of any DEFINED tokens that * result from expansion as follows: * - * EXPANSION_MODE_IGNORE_DEFINED: Any resulting DEFINED tokens will be - * left in the final list, unevaluated. This is the correct mode - * for expanding any list in any context other than a - * preprocessor conditional, (#if or #elif). + * EXPANSION_MODE_IGNORE_DEFINED: Any resulting DEFINED tokens will be + * left in the final list, unevaluated. This is the correct mode + * for expanding any list in any context other than a + * preprocessor conditional, (#if or #elif). * - * EXPANSION_MODE_EVALUATE_DEFINED: Any resulting DEFINED tokens will be - * evaluated to 0 or 1 tokens depending on whether the following - * token is the name of a defined macro. If the DEFINED token is - * not followed by an (optionally parenthesized) identifier, then - * an error will be generated. This the correct mode for - * expanding any list in the context of a preprocessor - * conditional, (#if or #elif). + * EXPANSION_MODE_EVALUATE_DEFINED: Any resulting DEFINED tokens will be + * evaluated to 0 or 1 tokens depending on whether the following + * token is the name of a defined macro. If the DEFINED token is + * not followed by an (optionally parenthesized) identifier, then + * an error will be generated. This the correct mode for + * expanding any list in the context of a preprocessor + * conditional, (#if or #elif). */ static void -_glcpp_parser_expand_token_list (glcpp_parser_t *parser, - token_list_t *list, - expansion_mode_t mode) +_glcpp_parser_expand_token_list(glcpp_parser_t *parser, token_list_t *list, + expansion_mode_t mode) { - token_node_t *node_prev; - token_node_t *node, *last = NULL; - token_list_t *expansion; - active_list_t *active_initial = parser->active; + token_node_t *node_prev; + token_node_t *node, *last = NULL; + token_list_t *expansion; + active_list_t *active_initial = parser->active; - if (list == NULL) - return; + if (list == NULL) + return; - _token_list_trim_trailing_space (list); + _token_list_trim_trailing_space (list); - node_prev = NULL; - node = list->head; + node_prev = NULL; + node = list->head; - if (mode == EXPANSION_MODE_EVALUATE_DEFINED) - _glcpp_parser_evaluate_defined_in_list (parser, list); + if (mode == EXPANSION_MODE_EVALUATE_DEFINED) + _glcpp_parser_evaluate_defined_in_list (parser, list); - while (node) { + while (node) { - while (parser->active && parser->active->marker == node) - _parser_active_list_pop (parser); + while (parser->active && parser->active->marker == node) + _parser_active_list_pop (parser); - expansion = _glcpp_parser_expand_node (parser, node, &last, mode); - if (expansion) { - token_node_t *n; + expansion = _glcpp_parser_expand_node (parser, node, &last, mode); + if (expansion) { + token_node_t *n; - if (mode == EXPANSION_MODE_EVALUATE_DEFINED) { - _glcpp_parser_evaluate_defined_in_list (parser, - expansion); - } + if (mode == EXPANSION_MODE_EVALUATE_DEFINED) { + _glcpp_parser_evaluate_defined_in_list (parser, expansion); + } - for (n = node; n != last->next; n = n->next) - while (parser->active && - parser->active->marker == n) - { - _parser_active_list_pop (parser); - } + for (n = node; n != last->next; n = n->next) + while (parser->active && parser->active->marker == n) { + _parser_active_list_pop (parser); + } - _parser_active_list_push (parser, - node->token->value.str, - last->next); - - /* Splice expansion into list, supporting a - * simple deletion if the expansion is - * empty. */ - if (expansion->head) { - if (node_prev) - node_prev->next = expansion->head; - else - list->head = expansion->head; - expansion->tail->next = last->next; - if (last == list->tail) - list->tail = expansion->tail; - } else { - if (node_prev) - node_prev->next = last->next; - else - list->head = last->next; - if (last == list->tail) - list->tail = NULL; - } - } else { - node_prev = node; - } - node = node_prev ? node_prev->next : list->head; - } + _parser_active_list_push(parser, node->token->value.str, last->next); - /* Remove any lingering effects of this invocation on the - * active list. That is, pop until the list looks like it did - * at the beginning of this function. */ - while (parser->active && parser->active != active_initial) - _parser_active_list_pop (parser); + /* Splice expansion into list, supporting a simple deletion if the + * expansion is empty. + */ + if (expansion->head) { + if (node_prev) + node_prev->next = expansion->head; + else + list->head = expansion->head; + expansion->tail->next = last->next; + if (last == list->tail) + list->tail = expansion->tail; + } else { + if (node_prev) + node_prev->next = last->next; + else + list->head = last->next; + if (last == list->tail) + list->tail = NULL; + } + } else { + node_prev = node; + } + node = node_prev ? node_prev->next : list->head; + } - list->non_space_tail = list->tail; + /* Remove any lingering effects of this invocation on the + * active list. That is, pop until the list looks like it did + * at the beginning of this function. */ + while (parser->active && parser->active != active_initial) + _parser_active_list_pop (parser); + + list->non_space_tail = list->tail; } void -_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser, - token_list_t *list) +_glcpp_parser_print_expanded_token_list(glcpp_parser_t *parser, + token_list_t *list) { - if (list == NULL) - return; + if (list == NULL) + return; - _glcpp_parser_expand_token_list (parser, list, EXPANSION_MODE_IGNORE_DEFINED); + _glcpp_parser_expand_token_list (parser, list, EXPANSION_MODE_IGNORE_DEFINED); - _token_list_trim_trailing_space (list); + _token_list_trim_trailing_space (list); - _token_list_print (parser, list); + _token_list_print (parser, list); } static void -_check_for_reserved_macro_name (glcpp_parser_t *parser, YYLTYPE *loc, - const char *identifier) +_check_for_reserved_macro_name(glcpp_parser_t *parser, YYLTYPE *loc, + const char *identifier) { - /* Section 3.3 (Preprocessor) of the GLSL 1.30 spec (and later) and - * the GLSL ES spec (all versions) say: - * - * "All macro names containing two consecutive underscores ( __ ) - * are reserved for future use as predefined macro names. All - * macro names prefixed with "GL_" ("GL" followed by a single - * underscore) are also reserved." - * - * The intention is that names containing __ are reserved for internal - * use by the implementation, and names prefixed with GL_ are reserved - * for use by Khronos. Since every extension adds a name prefixed - * with GL_ (i.e., the name of the extension), that should be an - * error. Names simply containing __ are dangerous to use, but should - * be allowed. - * - * A future version of the GLSL specification will clarify this. - */ - if (strstr(identifier, "__")) { - glcpp_warning(loc, parser, - "Macro names containing \"__\" are reserved " - "for use by the implementation.\n"); - } - if (strncmp(identifier, "GL_", 3) == 0) { - glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n"); - } - if (strcmp(identifier, "defined") == 0) { - glcpp_error (loc, parser, "\"defined\" cannot be used as a macro name"); - } + /* Section 3.3 (Preprocessor) of the GLSL 1.30 spec (and later) and + * the GLSL ES spec (all versions) say: + * + * "All macro names containing two consecutive underscores ( __ ) + * are reserved for future use as predefined macro names. All + * macro names prefixed with "GL_" ("GL" followed by a single + * underscore) are also reserved." + * + * The intention is that names containing __ are reserved for internal + * use by the implementation, and names prefixed with GL_ are reserved + * for use by Khronos. Since every extension adds a name prefixed + * with GL_ (i.e., the name of the extension), that should be an + * error. Names simply containing __ are dangerous to use, but should + * be allowed. + * + * A future version of the GLSL specification will clarify this. + */ + if (strstr(identifier, "__")) { + glcpp_warning(loc, parser, "Macro names containing \"__\" are reserved " + "for use by the implementation.\n"); + } + if (strncmp(identifier, "GL_", 3) == 0) { + glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n"); + } + if (strcmp(identifier, "defined") == 0) { + glcpp_error (loc, parser, "\"defined\" cannot be used as a macro name"); + } } static int -_macro_equal (macro_t *a, macro_t *b) +_macro_equal(macro_t *a, macro_t *b) { - if (a->is_function != b->is_function) - return 0; + if (a->is_function != b->is_function) + return 0; - if (a->is_function) { - if (! _string_list_equal (a->parameters, b->parameters)) - return 0; - } + if (a->is_function) { + if (! _string_list_equal (a->parameters, b->parameters)) + return 0; + } - return _token_list_equal_ignoring_space (a->replacements, - b->replacements); + return _token_list_equal_ignoring_space(a->replacements, b->replacements); } void -_define_object_macro (glcpp_parser_t *parser, - YYLTYPE *loc, - const char *identifier, - token_list_t *replacements) +_define_object_macro(glcpp_parser_t *parser, YYLTYPE *loc, + const char *identifier, token_list_t *replacements) { - macro_t *macro, *previous; + macro_t *macro, *previous; - /* We define pre-defined macros before we've started parsing the - * actual file. So if there's no location defined yet, that's what - * were doing and we don't want to generate an error for using the - * reserved names. */ - if (loc != NULL) - _check_for_reserved_macro_name(parser, loc, identifier); + /* We define pre-defined macros before we've started parsing the actual + * file. So if there's no location defined yet, that's what were doing and + * we don't want to generate an error for using the reserved names. */ + if (loc != NULL) + _check_for_reserved_macro_name(parser, loc, identifier); - macro = ralloc (parser, macro_t); + macro = ralloc (parser, macro_t); - macro->is_function = 0; - macro->parameters = NULL; - macro->identifier = ralloc_strdup (macro, identifier); - macro->replacements = replacements; - ralloc_steal (macro, replacements); + macro->is_function = 0; + macro->parameters = NULL; + macro->identifier = ralloc_strdup (macro, identifier); + macro->replacements = replacements; + ralloc_steal (macro, replacements); - previous = hash_table_find (parser->defines, identifier); - if (previous) { - if (_macro_equal (macro, previous)) { - ralloc_free (macro); - return; - } - glcpp_error (loc, parser, "Redefinition of macro %s\n", - identifier); - } + previous = hash_table_find (parser->defines, identifier); + if (previous) { + if (_macro_equal (macro, previous)) { + ralloc_free (macro); + return; + } + glcpp_error (loc, parser, "Redefinition of macro %s\n", identifier); + } - hash_table_insert (parser->defines, macro, identifier); + hash_table_insert (parser->defines, macro, identifier); } void -_define_function_macro (glcpp_parser_t *parser, - YYLTYPE *loc, - const char *identifier, - string_list_t *parameters, - token_list_t *replacements) +_define_function_macro(glcpp_parser_t *parser, YYLTYPE *loc, + const char *identifier, string_list_t *parameters, + token_list_t *replacements) { - macro_t *macro, *previous; - const char *dup; + macro_t *macro, *previous; + const char *dup; - _check_for_reserved_macro_name(parser, loc, identifier); + _check_for_reserved_macro_name(parser, loc, identifier); /* Check for any duplicate parameter names. */ - if ((dup = _string_list_has_duplicate (parameters)) != NULL) { - glcpp_error (loc, parser, "Duplicate macro parameter \"%s\"", - dup); - } + if ((dup = _string_list_has_duplicate (parameters)) != NULL) { + glcpp_error (loc, parser, "Duplicate macro parameter \"%s\"", dup); + } - macro = ralloc (parser, macro_t); - ralloc_steal (macro, parameters); - ralloc_steal (macro, replacements); + macro = ralloc (parser, macro_t); + ralloc_steal (macro, parameters); + ralloc_steal (macro, replacements); - macro->is_function = 1; - macro->parameters = parameters; - macro->identifier = ralloc_strdup (macro, identifier); - macro->replacements = replacements; - previous = hash_table_find (parser->defines, identifier); - if (previous) { - if (_macro_equal (macro, previous)) { - ralloc_free (macro); - return; - } - glcpp_error (loc, parser, "Redefinition of macro %s\n", - identifier); - } + macro->is_function = 1; + macro->parameters = parameters; + macro->identifier = ralloc_strdup (macro, identifier); + macro->replacements = replacements; + previous = hash_table_find (parser->defines, identifier); + if (previous) { + if (_macro_equal (macro, previous)) { + ralloc_free (macro); + return; + } + glcpp_error (loc, parser, "Redefinition of macro %s\n", identifier); + } - hash_table_insert (parser->defines, macro, identifier); + hash_table_insert(parser->defines, macro, identifier); } static int -glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser) +glcpp_parser_lex(YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser) { - token_node_t *node; - int ret; + token_node_t *node; + int ret; - if (parser->lex_from_list == NULL) { - ret = glcpp_lex (yylval, yylloc, parser->scanner); + if (parser->lex_from_list == NULL) { + ret = glcpp_lex(yylval, yylloc, parser->scanner); - /* XXX: This ugly block of code exists for the sole - * purpose of converting a NEWLINE token into a SPACE - * token, but only in the case where we have seen a - * function-like macro name, but have not yet seen its - * closing parenthesis. - * - * There's perhaps a more compact way to do this with - * mid-rule actions in the grammar. - * - * I'm definitely not pleased with the complexity of - * this code here. - */ - if (parser->newline_as_space) - { - if (ret == '(') { - parser->paren_count++; - } else if (ret == ')') { - parser->paren_count--; - if (parser->paren_count == 0) - parser->newline_as_space = 0; - } else if (ret == NEWLINE) { - ret = SPACE; - } else if (ret != SPACE) { - if (parser->paren_count == 0) - parser->newline_as_space = 0; - } - } - else if (parser->in_control_line) - { - if (ret == NEWLINE) - parser->in_control_line = 0; - } - else if (ret == DEFINE_TOKEN || - ret == UNDEF || ret == IF || - ret == IFDEF || ret == IFNDEF || - ret == ELIF || ret == ELSE || - ret == ENDIF || ret == HASH_TOKEN) - { - parser->in_control_line = 1; - } - else if (ret == IDENTIFIER) - { - macro_t *macro; - macro = hash_table_find (parser->defines, - yylval->str); - if (macro && macro->is_function) { - parser->newline_as_space = 1; - parser->paren_count = 0; - } - } + /* XXX: This ugly block of code exists for the sole + * purpose of converting a NEWLINE token into a SPACE + * token, but only in the case where we have seen a + * function-like macro name, but have not yet seen its + * closing parenthesis. + * + * There's perhaps a more compact way to do this with + * mid-rule actions in the grammar. + * + * I'm definitely not pleased with the complexity of + * this code here. + */ + if (parser->newline_as_space) { + if (ret == '(') { + parser->paren_count++; + } else if (ret == ')') { + parser->paren_count--; + if (parser->paren_count == 0) + parser->newline_as_space = 0; + } else if (ret == NEWLINE) { + ret = SPACE; + } else if (ret != SPACE) { + if (parser->paren_count == 0) + parser->newline_as_space = 0; + } + } else if (parser->in_control_line) { + if (ret == NEWLINE) + parser->in_control_line = 0; + } + else if (ret == DEFINE_TOKEN || ret == UNDEF || ret == IF || + ret == IFDEF || ret == IFNDEF || ret == ELIF || ret == ELSE || + ret == ENDIF || ret == HASH_TOKEN) { + parser->in_control_line = 1; + } else if (ret == IDENTIFIER) { + macro_t *macro; + macro = hash_table_find (parser->defines, + yylval->str); + if (macro && macro->is_function) { + parser->newline_as_space = 1; + parser->paren_count = 0; + } + } - return ret; - } + return ret; + } - node = parser->lex_from_node; + node = parser->lex_from_node; - if (node == NULL) { - ralloc_free (parser->lex_from_list); - parser->lex_from_list = NULL; - return NEWLINE; - } + if (node == NULL) { + ralloc_free (parser->lex_from_list); + parser->lex_from_list = NULL; + return NEWLINE; + } - *yylval = node->token->value; - ret = node->token->type; + *yylval = node->token->value; + ret = node->token->type; - parser->lex_from_node = node->next; + parser->lex_from_node = node->next; - return ret; + return ret; } static void -glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list) +glcpp_parser_lex_from(glcpp_parser_t *parser, token_list_t *list) { - token_node_t *node; + token_node_t *node; - assert (parser->lex_from_list == NULL); + assert (parser->lex_from_list == NULL); - /* Copy list, eliminating any space tokens. */ - parser->lex_from_list = _token_list_create (parser); + /* Copy list, eliminating any space tokens. */ + parser->lex_from_list = _token_list_create (parser); - for (node = list->head; node; node = node->next) { - if (node->token->type == SPACE) - continue; - _token_list_append (parser->lex_from_list, node->token); - } + for (node = list->head; node; node = node->next) { + if (node->token->type == SPACE) + continue; + _token_list_append (parser->lex_from_list, node->token); + } - ralloc_free (list); + ralloc_free (list); - parser->lex_from_node = parser->lex_from_list->head; + parser->lex_from_node = parser->lex_from_list->head; - /* It's possible the list consisted of nothing but whitespace. */ - if (parser->lex_from_node == NULL) { - ralloc_free (parser->lex_from_list); - parser->lex_from_list = NULL; - } + /* It's possible the list consisted of nothing but whitespace. */ + if (parser->lex_from_node == NULL) { + ralloc_free (parser->lex_from_list); + parser->lex_from_list = NULL; + } } static void -_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc, - int condition) +_glcpp_parser_skip_stack_push_if(glcpp_parser_t *parser, YYLTYPE *loc, + int condition) { - skip_type_t current = SKIP_NO_SKIP; - skip_node_t *node; + skip_type_t current = SKIP_NO_SKIP; + skip_node_t *node; - if (parser->skip_stack) - current = parser->skip_stack->type; + if (parser->skip_stack) + current = parser->skip_stack->type; - node = ralloc (parser, skip_node_t); - node->loc = *loc; + node = ralloc (parser, skip_node_t); + node->loc = *loc; - if (current == SKIP_NO_SKIP) { - if (condition) - node->type = SKIP_NO_SKIP; - else - node->type = SKIP_TO_ELSE; - } else { - node->type = SKIP_TO_ENDIF; - } + if (current == SKIP_NO_SKIP) { + if (condition) + node->type = SKIP_NO_SKIP; + else + node->type = SKIP_TO_ELSE; + } else { + node->type = SKIP_TO_ENDIF; + } - node->has_else = false; - node->next = parser->skip_stack; - parser->skip_stack = node; + node->has_else = false; + node->next = parser->skip_stack; + parser->skip_stack = node; } static void -_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc, - const char *type, int condition) +_glcpp_parser_skip_stack_change_if(glcpp_parser_t *parser, YYLTYPE *loc, + const char *type, int condition) { - if (parser->skip_stack == NULL) { - glcpp_error (loc, parser, "#%s without #if\n", type); - return; - } + if (parser->skip_stack == NULL) { + glcpp_error (loc, parser, "#%s without #if\n", type); + return; + } - if (parser->skip_stack->type == SKIP_TO_ELSE) { - if (condition) - parser->skip_stack->type = SKIP_NO_SKIP; - } else { - parser->skip_stack->type = SKIP_TO_ENDIF; - } + if (parser->skip_stack->type == SKIP_TO_ELSE) { + if (condition) + parser->skip_stack->type = SKIP_NO_SKIP; + } else { + parser->skip_stack->type = SKIP_TO_ENDIF; + } } static void -_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc) +_glcpp_parser_skip_stack_pop(glcpp_parser_t *parser, YYLTYPE *loc) { - skip_node_t *node; + skip_node_t *node; - if (parser->skip_stack == NULL) { - glcpp_error (loc, parser, "#endif without #if\n"); - return; - } + if (parser->skip_stack == NULL) { + glcpp_error (loc, parser, "#endif without #if\n"); + return; + } - node = parser->skip_stack; - parser->skip_stack = node->next; - ralloc_free (node); + node = parser->skip_stack; + parser->skip_stack = node->next; + ralloc_free (node); } static void @@ -2349,210 +2279,209 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio const char *es_identifier, bool explicitly_set) { - const struct gl_extensions *extensions = parser->extensions; + const struct gl_extensions *extensions = parser->extensions; - if (parser->version_resolved) - return; + if (parser->version_resolved) + return; - parser->version_resolved = true; + parser->version_resolved = true; - add_builtin_define (parser, "__VERSION__", version); + add_builtin_define (parser, "__VERSION__", version); - parser->is_gles = (version == 100) || - (es_identifier && - (strcmp(es_identifier, "es") == 0)); + parser->is_gles = (version == 100) || + (es_identifier && (strcmp(es_identifier, "es") == 0)); - /* Add pre-defined macros. */ - if (parser->is_gles) { - add_builtin_define(parser, "GL_ES", 1); - add_builtin_define(parser, "GL_EXT_separate_shader_objects", 1); - add_builtin_define(parser, "GL_EXT_draw_buffers", 1); + /* Add pre-defined macros. */ + if (parser->is_gles) { + add_builtin_define(parser, "GL_ES", 1); + add_builtin_define(parser, "GL_EXT_separate_shader_objects", 1); + add_builtin_define(parser, "GL_EXT_draw_buffers", 1); - if (extensions != NULL) { - if (extensions->OES_EGL_image_external) - add_builtin_define(parser, "GL_OES_EGL_image_external", 1); - if (extensions->OES_sample_variables) { - add_builtin_define(parser, "GL_OES_sample_variables", 1); - add_builtin_define(parser, "GL_OES_shader_multisample_interpolation", 1); - } - if (extensions->OES_standard_derivatives) - add_builtin_define(parser, "GL_OES_standard_derivatives", 1); - if (extensions->ARB_texture_multisample) - add_builtin_define(parser, "GL_OES_texture_storage_multisample_2d_array", 1); - if (extensions->ARB_blend_func_extended) - add_builtin_define(parser, "GL_EXT_blend_func_extended", 1); + if (extensions != NULL) { + if (extensions->OES_EGL_image_external) + add_builtin_define(parser, "GL_OES_EGL_image_external", 1); + if (extensions->OES_sample_variables) { + add_builtin_define(parser, "GL_OES_sample_variables", 1); + add_builtin_define(parser, "GL_OES_shader_multisample_interpolation", 1); + } + if (extensions->OES_standard_derivatives) + add_builtin_define(parser, "GL_OES_standard_derivatives", 1); + if (extensions->ARB_texture_multisample) + add_builtin_define(parser, "GL_OES_texture_storage_multisample_2d_array", 1); + if (extensions->ARB_blend_func_extended) + add_builtin_define(parser, "GL_EXT_blend_func_extended", 1); - if (version >= 310) { - if (extensions->ARB_shader_image_load_store) - add_builtin_define(parser, "GL_OES_shader_image_atomic", 1); + if (version >= 310) { + if (extensions->ARB_shader_image_load_store) + add_builtin_define(parser, "GL_OES_shader_image_atomic", 1); - if (extensions->OES_geometry_shader) { - add_builtin_define(parser, "GL_OES_geometry_point_size", 1); - add_builtin_define(parser, "GL_OES_geometry_shader", 1); - } - if (extensions->ARB_gpu_shader5) { - add_builtin_define(parser, "GL_EXT_gpu_shader5", 1); - add_builtin_define(parser, "GL_OES_gpu_shader5", 1); - } - if (extensions->OES_texture_buffer) { - add_builtin_define(parser, "GL_EXT_texture_buffer", 1); - add_builtin_define(parser, "GL_OES_texture_buffer", 1); - } - } - } - } else { - add_builtin_define(parser, "GL_ARB_draw_buffers", 1); - add_builtin_define(parser, "GL_ARB_enhanced_layouts", 1); - add_builtin_define(parser, "GL_ARB_separate_shader_objects", 1); - add_builtin_define(parser, "GL_ARB_texture_rectangle", 1); - add_builtin_define(parser, "GL_AMD_shader_trinary_minmax", 1); + if (extensions->OES_geometry_shader) { + add_builtin_define(parser, "GL_OES_geometry_point_size", 1); + add_builtin_define(parser, "GL_OES_geometry_shader", 1); + } + if (extensions->ARB_gpu_shader5) { + add_builtin_define(parser, "GL_EXT_gpu_shader5", 1); + add_builtin_define(parser, "GL_OES_gpu_shader5", 1); + } + if (extensions->OES_texture_buffer) { + add_builtin_define(parser, "GL_EXT_texture_buffer", 1); + add_builtin_define(parser, "GL_OES_texture_buffer", 1); + } + } + } + } else { + add_builtin_define(parser, "GL_ARB_draw_buffers", 1); + add_builtin_define(parser, "GL_ARB_enhanced_layouts", 1); + add_builtin_define(parser, "GL_ARB_separate_shader_objects", 1); + add_builtin_define(parser, "GL_ARB_texture_rectangle", 1); + add_builtin_define(parser, "GL_AMD_shader_trinary_minmax", 1); + if (extensions != NULL) { + if (extensions->EXT_texture_array) + add_builtin_define(parser, "GL_EXT_texture_array", 1); - if (extensions != NULL) { - if (extensions->EXT_texture_array) - add_builtin_define(parser, "GL_EXT_texture_array", 1); + if (extensions->ARB_arrays_of_arrays) + add_builtin_define(parser, "GL_ARB_arrays_of_arrays", 1); - if (extensions->ARB_arrays_of_arrays) - add_builtin_define(parser, "GL_ARB_arrays_of_arrays", 1); + if (extensions->ARB_fragment_coord_conventions) { + add_builtin_define(parser, "GL_ARB_fragment_coord_conventions", + 1); + } - if (extensions->ARB_fragment_coord_conventions) - add_builtin_define(parser, "GL_ARB_fragment_coord_conventions", - 1); + if (extensions->ARB_fragment_layer_viewport) + add_builtin_define(parser, "GL_ARB_fragment_layer_viewport", 1); - if (extensions->ARB_fragment_layer_viewport) - add_builtin_define(parser, "GL_ARB_fragment_layer_viewport", 1); + if (extensions->ARB_explicit_attrib_location) + add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1); - if (extensions->ARB_explicit_attrib_location) - add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1); + if (extensions->ARB_explicit_uniform_location) + add_builtin_define(parser, "GL_ARB_explicit_uniform_location", 1); - if (extensions->ARB_explicit_uniform_location) - add_builtin_define(parser, "GL_ARB_explicit_uniform_location", 1); + if (extensions->ARB_shader_texture_lod) + add_builtin_define(parser, "GL_ARB_shader_texture_lod", 1); - if (extensions->ARB_shader_texture_lod) - add_builtin_define(parser, "GL_ARB_shader_texture_lod", 1); + if (extensions->ARB_draw_instanced) + add_builtin_define(parser, "GL_ARB_draw_instanced", 1); - if (extensions->ARB_draw_instanced) - add_builtin_define(parser, "GL_ARB_draw_instanced", 1); + if (extensions->ARB_conservative_depth) { + add_builtin_define(parser, "GL_AMD_conservative_depth", 1); + add_builtin_define(parser, "GL_ARB_conservative_depth", 1); + } - if (extensions->ARB_conservative_depth) { - add_builtin_define(parser, "GL_AMD_conservative_depth", 1); - add_builtin_define(parser, "GL_ARB_conservative_depth", 1); - } + if (extensions->ARB_shader_bit_encoding) + add_builtin_define(parser, "GL_ARB_shader_bit_encoding", 1); - if (extensions->ARB_shader_bit_encoding) - add_builtin_define(parser, "GL_ARB_shader_bit_encoding", 1); + if (extensions->ARB_shader_clock) + add_builtin_define(parser, "GL_ARB_shader_clock", 1); - if (extensions->ARB_shader_clock) - add_builtin_define(parser, "GL_ARB_shader_clock", 1); + if (extensions->ARB_uniform_buffer_object) + add_builtin_define(parser, "GL_ARB_uniform_buffer_object", 1); - if (extensions->ARB_uniform_buffer_object) - add_builtin_define(parser, "GL_ARB_uniform_buffer_object", 1); + if (extensions->ARB_texture_cube_map_array) + add_builtin_define(parser, "GL_ARB_texture_cube_map_array", 1); - if (extensions->ARB_texture_cube_map_array) - add_builtin_define(parser, "GL_ARB_texture_cube_map_array", 1); + if (extensions->ARB_shading_language_packing) + add_builtin_define(parser, "GL_ARB_shading_language_packing", 1); - if (extensions->ARB_shading_language_packing) - add_builtin_define(parser, "GL_ARB_shading_language_packing", 1); + if (extensions->ARB_texture_multisample) + add_builtin_define(parser, "GL_ARB_texture_multisample", 1); - if (extensions->ARB_texture_multisample) - add_builtin_define(parser, "GL_ARB_texture_multisample", 1); + if (extensions->ARB_texture_query_levels) + add_builtin_define(parser, "GL_ARB_texture_query_levels", 1); - if (extensions->ARB_texture_query_levels) - add_builtin_define(parser, "GL_ARB_texture_query_levels", 1); + if (extensions->ARB_texture_query_lod) + add_builtin_define(parser, "GL_ARB_texture_query_lod", 1); - if (extensions->ARB_texture_query_lod) - add_builtin_define(parser, "GL_ARB_texture_query_lod", 1); + if (extensions->ARB_gpu_shader5) + add_builtin_define(parser, "GL_ARB_gpu_shader5", 1); - if (extensions->ARB_gpu_shader5) - add_builtin_define(parser, "GL_ARB_gpu_shader5", 1); + if (extensions->ARB_gpu_shader_fp64) + add_builtin_define(parser, "GL_ARB_gpu_shader_fp64", 1); - if (extensions->ARB_gpu_shader_fp64) - add_builtin_define(parser, "GL_ARB_gpu_shader_fp64", 1); + if (extensions->ARB_vertex_attrib_64bit) + add_builtin_define(parser, "GL_ARB_vertex_attrib_64bit", 1); - if (extensions->ARB_vertex_attrib_64bit) - add_builtin_define(parser, "GL_ARB_vertex_attrib_64bit", 1); + if (extensions->AMD_vertex_shader_layer) + add_builtin_define(parser, "GL_AMD_vertex_shader_layer", 1); - if (extensions->AMD_vertex_shader_layer) - add_builtin_define(parser, "GL_AMD_vertex_shader_layer", 1); + if (extensions->AMD_vertex_shader_viewport_index) + add_builtin_define(parser, "GL_AMD_vertex_shader_viewport_index", 1); - if (extensions->AMD_vertex_shader_viewport_index) - add_builtin_define(parser, "GL_AMD_vertex_shader_viewport_index", 1); + if (extensions->ARB_shading_language_420pack) + add_builtin_define(parser, "GL_ARB_shading_language_420pack", 1); - if (extensions->ARB_shading_language_420pack) - add_builtin_define(parser, "GL_ARB_shading_language_420pack", 1); + if (extensions->ARB_sample_shading) + add_builtin_define(parser, "GL_ARB_sample_shading", 1); - if (extensions->ARB_sample_shading) - add_builtin_define(parser, "GL_ARB_sample_shading", 1); + if (extensions->ARB_texture_gather) + add_builtin_define(parser, "GL_ARB_texture_gather", 1); - if (extensions->ARB_texture_gather) - add_builtin_define(parser, "GL_ARB_texture_gather", 1); + if (extensions->ARB_shader_atomic_counters) + add_builtin_define(parser, "GL_ARB_shader_atomic_counters", 1); - if (extensions->ARB_shader_atomic_counters) - add_builtin_define(parser, "GL_ARB_shader_atomic_counters", 1); + if (extensions->ARB_shader_atomic_counter_ops) + add_builtin_define(parser, "GL_ARB_shader_atomic_counter_ops", 1); - if (extensions->ARB_shader_atomic_counter_ops) - add_builtin_define(parser, "GL_ARB_shader_atomic_counter_ops", 1); + if (extensions->ARB_viewport_array) + add_builtin_define(parser, "GL_ARB_viewport_array", 1); - if (extensions->ARB_viewport_array) - add_builtin_define(parser, "GL_ARB_viewport_array", 1); + if (extensions->ARB_compute_shader) + add_builtin_define(parser, "GL_ARB_compute_shader", 1); - if (extensions->ARB_compute_shader) - add_builtin_define(parser, "GL_ARB_compute_shader", 1); + if (extensions->ARB_shader_image_load_store) + add_builtin_define(parser, "GL_ARB_shader_image_load_store", 1); - if (extensions->ARB_shader_image_load_store) - add_builtin_define(parser, "GL_ARB_shader_image_load_store", 1); + if (extensions->ARB_shader_image_size) + add_builtin_define(parser, "GL_ARB_shader_image_size", 1); - if (extensions->ARB_shader_image_size) - add_builtin_define(parser, "GL_ARB_shader_image_size", 1); + if (extensions->ARB_shader_texture_image_samples) + add_builtin_define(parser, "GL_ARB_shader_texture_image_samples", 1); - if (extensions->ARB_shader_texture_image_samples) - add_builtin_define(parser, "GL_ARB_shader_texture_image_samples", 1); + if (extensions->ARB_derivative_control) + add_builtin_define(parser, "GL_ARB_derivative_control", 1); - if (extensions->ARB_derivative_control) - add_builtin_define(parser, "GL_ARB_derivative_control", 1); + if (extensions->ARB_shader_precision) + add_builtin_define(parser, "GL_ARB_shader_precision", 1); - if (extensions->ARB_shader_precision) - add_builtin_define(parser, "GL_ARB_shader_precision", 1); + if (extensions->ARB_shader_storage_buffer_object) + add_builtin_define(parser, "GL_ARB_shader_storage_buffer_object", 1); - if (extensions->ARB_shader_storage_buffer_object) - add_builtin_define(parser, "GL_ARB_shader_storage_buffer_object", 1); + if (extensions->ARB_tessellation_shader) + add_builtin_define(parser, "GL_ARB_tessellation_shader", 1); - if (extensions->ARB_tessellation_shader) - add_builtin_define(parser, "GL_ARB_tessellation_shader", 1); + if (extensions->ARB_shader_subroutine) + add_builtin_define(parser, "GL_ARB_shader_subroutine", 1); - if (extensions->ARB_shader_subroutine) - add_builtin_define(parser, "GL_ARB_shader_subroutine", 1); + if (extensions->ARB_shader_draw_parameters) + add_builtin_define(parser, "GL_ARB_shader_draw_parameters", 1); + } + } - if (extensions->ARB_shader_draw_parameters) - add_builtin_define(parser, "GL_ARB_shader_draw_parameters", 1); - } - } + if (extensions != NULL) { + if (extensions->EXT_shader_integer_mix) + add_builtin_define(parser, "GL_EXT_shader_integer_mix", 1); - if (extensions != NULL) { - if (extensions->EXT_shader_integer_mix) - add_builtin_define(parser, "GL_EXT_shader_integer_mix", 1); + if (extensions->EXT_shader_samples_identical) + add_builtin_define(parser, "GL_EXT_shader_samples_identical", 1); + } - if (extensions->EXT_shader_samples_identical) - add_builtin_define(parser, "GL_EXT_shader_samples_identical", 1); - } + if (version >= 150) + add_builtin_define(parser, "GL_core_profile", 1); - if (version >= 150) - add_builtin_define(parser, "GL_core_profile", 1); + /* Currently, all ES2/ES3 implementations support highp in the + * fragment shader, so we always define this macro in ES2/ES3. + * If we ever get a driver that doesn't support highp, we'll + * need to add a flag to the gl_context and check that here. + */ + if (version >= 130 || parser->is_gles) + add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1); - /* Currently, all ES2/ES3 implementations support highp in the - * fragment shader, so we always define this macro in ES2/ES3. - * If we ever get a driver that doesn't support highp, we'll - * need to add a flag to the gl_context and check that here. - */ - if (version >= 130 || parser->is_gles) - add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1); - - if (explicitly_set) { - ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, - "#version %" PRIiMAX "%s%s", version, - es_identifier ? " " : "", - es_identifier ? es_identifier : ""); - } + if (explicitly_set) { + ralloc_asprintf_rewrite_tail(&parser->output, &parser->output_length, + "#version %" PRIiMAX "%s%s", version, + es_identifier ? " " : "", + es_identifier ? es_identifier : ""); + } } /* GLSL version if no version is explicitly specified. */ @@ -2564,10 +2493,9 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio void glcpp_parser_resolve_implicit_version(glcpp_parser_t *parser) { - int language_version = parser->api == API_OPENGLES2 ? - IMPLICIT_GLSL_ES_VERSION : - IMPLICIT_GLSL_VERSION; + int language_version = parser->api == API_OPENGLES2 ? + IMPLICIT_GLSL_ES_VERSION : IMPLICIT_GLSL_VERSION; - _glcpp_parser_handle_version_declaration(parser, language_version, - NULL, false); + _glcpp_parser_handle_version_declaration(parser, language_version, + NULL, false); } From ea8f4a6b13b94eb060bff4ccc6c13efc01d2b682 Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Thu, 17 Mar 2016 14:15:39 +0100 Subject: [PATCH 02/62] gallium: add compute shader IR type Signed-off-by: Bas Nieuwenhuizen Reviewed-by: Ilia Mirkin Reviewed-by: Dave Airlie --- src/gallium/drivers/trace/tr_dump_state.c | 4 +++- src/gallium/include/pipe/p_state.h | 1 + src/gallium/state_trackers/clover/core/kernel.cpp | 1 + src/gallium/tests/trivial/compute.c | 1 + src/mesa/state_tracker/st_program.c | 1 + 5 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c index 0627e5ab5d7..b53d7dbec2f 100644 --- a/src/gallium/drivers/trace/tr_dump_state.c +++ b/src/gallium/drivers/trace/tr_dump_state.c @@ -317,8 +317,10 @@ void trace_dump_compute_state(const struct pipe_compute_state *state) trace_dump_struct_begin("pipe_compute_state"); + trace_dump_member(uint, state, ir_type); + trace_dump_member_begin("prog"); - if (state->prog) { + if (state->prog && state->ir_type == PIPE_SHADER_IR_TGSI) { static char str[64 * 1024]; tgsi_dump_str(state->prog, 0, str, sizeof(str)); trace_dump_string(str); diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h index 2e720ce25f3..5ab53728e82 100644 --- a/src/gallium/include/pipe/p_state.h +++ b/src/gallium/include/pipe/p_state.h @@ -727,6 +727,7 @@ struct pipe_llvm_program_header struct pipe_compute_state { + enum pipe_shader_ir ir_type; /**< IR type contained in prog. */ const void *prog; /**< Compute program to be executed. */ unsigned req_local_mem; /**< Required size of the LOCAL resource. */ unsigned req_private_mem; /**< Required size of the PRIVATE resource. */ diff --git a/src/gallium/state_trackers/clover/core/kernel.cpp b/src/gallium/state_trackers/clover/core/kernel.cpp index c12755b0420..bce3b525b13 100644 --- a/src/gallium/state_trackers/clover/core/kernel.cpp +++ b/src/gallium/state_trackers/clover/core/kernel.cpp @@ -223,6 +223,7 @@ kernel::exec_context::bind(intrusive_ptr _q, if (st) _q->pipe->delete_compute_state(_q->pipe, st); + cs.ir_type = q->device().ir_format(); cs.prog = &(msec.data[0]); cs.req_local_mem = mem_local; cs.req_input_mem = input.size(); diff --git a/src/gallium/tests/trivial/compute.c b/src/gallium/tests/trivial/compute.c index 5d5e0b0b8c3..2ddfc42e9cd 100644 --- a/src/gallium/tests/trivial/compute.c +++ b/src/gallium/tests/trivial/compute.c @@ -144,6 +144,7 @@ static void init_prog(struct context *ctx, unsigned local_sz, struct pipe_context *pipe = ctx->pipe; struct tgsi_token prog[1024]; struct pipe_compute_state cs = { + .ir_type = PIPE_SHADER_IR_TGSI, .prog = prog, .req_local_mem = local_sz, .req_private_mem = private_sz, diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 94dc48971ec..d2d68ac05bf 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -1463,6 +1463,7 @@ st_translate_compute_program(struct st_context *st, st_translate_program_common(st, &stcp->Base.Base, stcp->glsl_to_tgsi, ureg, TGSI_PROCESSOR_COMPUTE, &prog); + stcp->tgsi.ir_type = PIPE_SHADER_IR_TGSI; stcp->tgsi.prog = prog.tokens; stcp->tgsi.req_local_mem = stcp->Base.SharedSize; stcp->tgsi.req_private_mem = 0; From 01f993a21f859d372d68c2818d845ebf47d70492 Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Mon, 28 Mar 2016 02:40:03 +0200 Subject: [PATCH 03/62] gallium: add threads per block TGSI property The value 0 for unknown has been chosen to so that drivers using tgsi_scan_shader do not need to detect missing properties if they zero-initialize the struct. Signed-off-by: Bas Nieuwenhuizen Reviewed-by: Ilia Mirkin Reviewed-by: Dave Airlie --- src/gallium/auxiliary/tgsi/tgsi_strings.c | 3 +++ src/gallium/docs/source/tgsi.rst | 6 ++++++ src/gallium/include/pipe/p_shader_tokens.h | 5 ++++- src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 18 ++++++++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/gallium/auxiliary/tgsi/tgsi_strings.c b/src/gallium/auxiliary/tgsi/tgsi_strings.c index ae779a8320a..d613f5e8cfb 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_strings.c +++ b/src/gallium/auxiliary/tgsi/tgsi_strings.c @@ -146,6 +146,9 @@ const char *tgsi_property_names[TGSI_PROPERTY_COUNT] = "NUM_CULLDIST_ENABLED", "FS_EARLY_DEPTH_STENCIL", "NEXT_SHADER", + "CS_FIXED_BLOCK_WIDTH", + "CS_FIXED_BLOCK_HEIGHT", + "CS_FIXED_BLOCK_DEPTH" }; const char *tgsi_return_type_names[TGSI_RETURN_TYPE_COUNT] = diff --git a/src/gallium/docs/source/tgsi.rst b/src/gallium/docs/source/tgsi.rst index 3ac6ba3c25a..ac6052a244a 100644 --- a/src/gallium/docs/source/tgsi.rst +++ b/src/gallium/docs/source/tgsi.rst @@ -3220,6 +3220,12 @@ Which shader stage will MOST LIKELY follow after this shader when the shader is bound. This is only a hint to the driver and doesn't have to be precise. Only set for VS and TES. +TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH / HEIGHT / DEPTH +""""""""""""""""""""""""""""""""""""""""""""""""""" + +Threads per block in each dimension, if known at compile time. If the block size +is known all three should be at least 1. If it is unknown they should all be set +to 0 or not set. Texture Sampling and Texture Formats ------------------------------------ diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h index 5cc18a293d3..c25786e871e 100644 --- a/src/gallium/include/pipe/p_shader_tokens.h +++ b/src/gallium/include/pipe/p_shader_tokens.h @@ -276,7 +276,10 @@ union tgsi_immediate_data #define TGSI_PROPERTY_NUM_CULLDIST_ENABLED 16 #define TGSI_PROPERTY_FS_EARLY_DEPTH_STENCIL 17 #define TGSI_PROPERTY_NEXT_SHADER 18 -#define TGSI_PROPERTY_COUNT 19 +#define TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH 19 +#define TGSI_PROPERTY_CS_FIXED_BLOCK_HEIGHT 20 +#define TGSI_PROPERTY_CS_FIXED_BLOCK_DEPTH 21 +#define TGSI_PROPERTY_COUNT 22 struct tgsi_property { unsigned Type : 4; /**< TGSI_TOKEN_TYPE_PROPERTY */ diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 23786b85529..cd481c166e7 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -5935,6 +5935,20 @@ find_array(unsigned attr, struct array_decl *arrays, unsigned count, return false; } +static void +emit_compute_block_size(const struct gl_program *program, + struct ureg_program *ureg) { + const struct gl_compute_program *cp = + (const struct gl_compute_program *)program; + + ureg_property(ureg, TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH, + cp->LocalSize[0]); + ureg_property(ureg, TGSI_PROPERTY_CS_FIXED_BLOCK_HEIGHT, + cp->LocalSize[1]); + ureg_property(ureg, TGSI_PROPERTY_CS_FIXED_BLOCK_DEPTH, + cp->LocalSize[2]); +} + /** * Translate intermediate IR (glsl_to_tgsi_instruction) to TGSI format. * \param program the program to translate @@ -6180,6 +6194,10 @@ st_translate_program( } } + if (procType == TGSI_PROCESSOR_COMPUTE) { + emit_compute_block_size(proginfo, ureg); + } + /* Declare address register. */ if (program->num_address_regs > 0) { From be5899dcf9a337548d8095a00060d4451b0df222 Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Thu, 24 Mar 2016 23:11:03 +0100 Subject: [PATCH 04/62] gallium: add global buffer memory barrier bit Currently radeonsi synchronizes after every dispatch and Clover does nothing to synchronize. This is overzealous, especially with GL compute, so add a barrier for global buffers. Signed-off-by: Bas Nieuwenhuizen Reviewed-by: Dave Airlie --- src/gallium/include/pipe/p_defines.h | 1 + src/gallium/state_trackers/clover/core/kernel.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index 8257b4a7142..6f30f9ed7d3 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -368,6 +368,7 @@ enum pipe_flush_flags #define PIPE_BARRIER_IMAGE (1 << 8) #define PIPE_BARRIER_FRAMEBUFFER (1 << 9) #define PIPE_BARRIER_STREAMOUT_BUFFER (1 << 10) +#define PIPE_BARRIER_GLOBAL_BUFFER (1 << 11) /** * Resource binding flags -- state tracker must specify in advance all diff --git a/src/gallium/state_trackers/clover/core/kernel.cpp b/src/gallium/state_trackers/clover/core/kernel.cpp index bce3b525b13..266d50e6145 100644 --- a/src/gallium/state_trackers/clover/core/kernel.cpp +++ b/src/gallium/state_trackers/clover/core/kernel.cpp @@ -89,6 +89,8 @@ kernel::launch(command_queue &q, exec.sviews.size(), NULL); q.pipe->bind_sampler_states(q.pipe, PIPE_SHADER_COMPUTE, 0, exec.samplers.size(), NULL); + + q.pipe->memory_barrier(q.pipe, PIPE_BARRIER_GLOBAL_BUFFER); exec.unbind(); } From 1a5c8c24b5791efa02a7beefa4ba1c49ae033c73 Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Fri, 25 Mar 2016 02:06:50 +0100 Subject: [PATCH 05/62] gallium: distinguish between shader IR in get_compute_param For radeonsi, native and TGSI use different compilers and this results in different limits for different IR's. The set we strictly need for radeonsi is only the MAX_BLOCK_SIZE and MAX_THREADS_PER_BLOCK params, but I added a few others as shader related that seemed like they would also typically depend on the compiler. Signed-off-by: Bas Nieuwenhuizen Reviewed-by: Dave Airlie --- src/gallium/docs/source/screen.rst | 18 +++++------ src/gallium/drivers/ilo/ilo_screen.c | 1 + .../drivers/nouveau/nv50/nv50_screen.c | 1 + .../drivers/nouveau/nvc0/nvc0_screen.c | 1 + src/gallium/drivers/r600/r600_pipe.c | 2 +- src/gallium/drivers/radeon/r600_pipe_common.c | 3 +- src/gallium/drivers/radeonsi/si_pipe.c | 2 +- src/gallium/drivers/trace/tr_screen.c | 4 ++- src/gallium/include/pipe/p_screen.h | 13 +++++--- .../state_trackers/clover/core/device.cpp | 31 ++++++++++--------- src/gallium/tests/trivial/compute.c | 4 ++- src/mesa/state_tracker/st_extensions.c | 13 ++++---- 12 files changed, 54 insertions(+), 39 deletions(-) diff --git a/src/gallium/docs/source/screen.rst b/src/gallium/docs/source/screen.rst index 46ec3815412..47a19de6ea9 100644 --- a/src/gallium/docs/source/screen.rst +++ b/src/gallium/docs/source/screen.rst @@ -436,26 +436,26 @@ pipe_screen::get_compute_param. ``processor-arch-manufacturer-os`` that will be passed on to the compiler. This CAP is only relevant for drivers that specify PIPE_SHADER_IR_LLVM or PIPE_SHADER_IR_NATIVE for their preferred IR. - Value type: null-terminated string. + Value type: null-terminated string. Shader IR type dependent. * ``PIPE_COMPUTE_CAP_GRID_DIMENSION``: Number of supported dimensions - for grid and block coordinates. Value type: ``uint64_t``. + for grid and block coordinates. Value type: ``uint64_t``. Shader IR type dependent. * ``PIPE_COMPUTE_CAP_MAX_GRID_SIZE``: Maximum grid size in block - units. Value type: ``uint64_t []``. + units. Value type: ``uint64_t []``. Shader IR type dependent. * ``PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE``: Maximum block size in thread - units. Value type: ``uint64_t []``. + units. Value type: ``uint64_t []``. Shader IR type dependent. * ``PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK``: Maximum number of threads that - a single block can contain. Value type: ``uint64_t``. + a single block can contain. Value type: ``uint64_t``. Shader IR type dependent. This may be less than the product of the components of MAX_BLOCK_SIZE and is usually limited by the number of threads that can be resident simultaneously on a compute unit. * ``PIPE_COMPUTE_CAP_MAX_GLOBAL_SIZE``: Maximum size of the GLOBAL - resource. Value type: ``uint64_t``. + resource. Value type: ``uint64_t``. Shader IR type dependent. * ``PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE``: Maximum size of the LOCAL - resource. Value type: ``uint64_t``. + resource. Value type: ``uint64_t``. Shader IR type dependent. * ``PIPE_COMPUTE_CAP_MAX_PRIVATE_SIZE``: Maximum size of the PRIVATE - resource. Value type: ``uint64_t``. + resource. Value type: ``uint64_t``. Shader IR type dependent. * ``PIPE_COMPUTE_CAP_MAX_INPUT_SIZE``: Maximum size of the INPUT - resource. Value type: ``uint64_t``. + resource. Value type: ``uint64_t``. Shader IR type dependent. * ``PIPE_COMPUTE_CAP_MAX_MEM_ALLOC_SIZE``: Maximum size of a memory object allocation in bytes. Value type: ``uint64_t``. * ``PIPE_COMPUTE_CAP_MAX_CLOCK_FREQUENCY``: Maximum frequency of the GPU diff --git a/src/gallium/drivers/ilo/ilo_screen.c b/src/gallium/drivers/ilo/ilo_screen.c index 548d215c718..7812c826250 100644 --- a/src/gallium/drivers/ilo/ilo_screen.c +++ b/src/gallium/drivers/ilo/ilo_screen.c @@ -179,6 +179,7 @@ ilo_get_video_param(struct pipe_screen *screen, static int ilo_get_compute_param(struct pipe_screen *screen, + enum pipe_shader_ir ir_type, enum pipe_compute_cap param, void *ret) { diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c index 57e28992727..ba5e5003b69 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c @@ -368,6 +368,7 @@ nv50_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param) static int nv50_screen_get_compute_param(struct pipe_screen *pscreen, + enum pipe_shader_ir ir_type, enum pipe_compute_cap param, void *data) { struct nv50_screen *screen = nv50_screen(pscreen); diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c index 590dac972a7..14438ced7a3 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c @@ -395,6 +395,7 @@ nvc0_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param) static int nvc0_screen_get_compute_param(struct pipe_screen *pscreen, + enum pipe_shader_ir ir_type, enum pipe_compute_cap param, void *data) { struct nvc0_screen *screen = nvc0_screen(pscreen); diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index b8011917907..c97e34121e3 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -499,7 +499,7 @@ static int r600_get_shader_param(struct pipe_screen* pscreen, unsigned shader, e case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE: if (shader == PIPE_SHADER_COMPUTE) { uint64_t max_const_buffer_size; - pscreen->get_compute_param(pscreen, + pscreen->get_compute_param(pscreen, PIPE_SHADER_IR_TGSI, PIPE_COMPUTE_CAP_MAX_MEM_ALLOC_SIZE, &max_const_buffer_size); return max_const_buffer_size; diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c index 720fc06ece2..32bd6e40d32 100644 --- a/src/gallium/drivers/radeon/r600_pipe_common.c +++ b/src/gallium/drivers/radeon/r600_pipe_common.c @@ -612,6 +612,7 @@ const char *r600_get_llvm_processor_name(enum radeon_family family) } static int r600_get_compute_param(struct pipe_screen *screen, + enum pipe_shader_ir ir_type, enum pipe_compute_cap param, void *ret) { @@ -678,7 +679,7 @@ static int r600_get_compute_param(struct pipe_screen *screen, uint64_t *max_global_size = ret; uint64_t max_mem_alloc_size; - r600_get_compute_param(screen, + r600_get_compute_param(screen, ir_type, PIPE_COMPUTE_CAP_MAX_MEM_ALLOC_SIZE, &max_mem_alloc_size); diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c index ed84dc224ff..407b9e19cc4 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.c +++ b/src/gallium/drivers/radeonsi/si_pipe.c @@ -467,7 +467,7 @@ static int si_get_shader_param(struct pipe_screen* pscreen, unsigned shader, enu case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE: { uint64_t max_const_buffer_size; - pscreen->get_compute_param(pscreen, + pscreen->get_compute_param(pscreen, PIPE_SHADER_IR_TGSI, PIPE_COMPUTE_CAP_MAX_MEM_ALLOC_SIZE, &max_const_buffer_size); return max_const_buffer_size; diff --git a/src/gallium/drivers/trace/tr_screen.c b/src/gallium/drivers/trace/tr_screen.c index b24e1856aca..260f1df5ce7 100644 --- a/src/gallium/drivers/trace/tr_screen.c +++ b/src/gallium/drivers/trace/tr_screen.c @@ -175,6 +175,7 @@ trace_screen_get_paramf(struct pipe_screen *_screen, static int trace_screen_get_compute_param(struct pipe_screen *_screen, + enum pipe_shader_ir ir_type, enum pipe_compute_cap param, void *data) { struct trace_screen *tr_scr = trace_screen(_screen); @@ -184,10 +185,11 @@ trace_screen_get_compute_param(struct pipe_screen *_screen, trace_dump_call_begin("pipe_screen", "get_compute_param"); trace_dump_arg(ptr, screen); + trace_dump_arg(int, ir_type); trace_dump_arg(int, param); trace_dump_arg(ptr, data); - result = screen->get_compute_param(screen, param, data); + result = screen->get_compute_param(screen, ir_type, param, data); trace_dump_ret(int, result); diff --git a/src/gallium/include/pipe/p_screen.h b/src/gallium/include/pipe/p_screen.h index 4f30e75ab49..3ac5f3cc9ff 100644 --- a/src/gallium/include/pipe/p_screen.h +++ b/src/gallium/include/pipe/p_screen.h @@ -109,13 +109,16 @@ struct pipe_screen { /** * Query a compute-specific capability/parameter/limit. - * \param param one of PIPE_COMPUTE_CAP_x - * \param ret pointer to a preallocated buffer that will be - * initialized to the parameter value, or NULL. - * \return size in bytes of the parameter value that would be - * returned. + * \param ir_type shader IR type for which the param applies, or don't care + * if the param is not shader related + * \param param one of PIPE_COMPUTE_CAP_x + * \param ret pointer to a preallocated buffer that will be + * initialized to the parameter value, or NULL. + * \return size in bytes of the parameter value that would be + * returned. */ int (*get_compute_param)(struct pipe_screen *, + enum pipe_shader_ir ir_type, enum pipe_compute_cap param, void *ret); diff --git a/src/gallium/state_trackers/clover/core/device.cpp b/src/gallium/state_trackers/clover/core/device.cpp index 1be2f6413f4..39f39f436c6 100644 --- a/src/gallium/state_trackers/clover/core/device.cpp +++ b/src/gallium/state_trackers/clover/core/device.cpp @@ -30,11 +30,12 @@ using namespace clover; namespace { template std::vector - get_compute_param(pipe_screen *pipe, pipe_compute_cap cap) { - int sz = pipe->get_compute_param(pipe, cap, NULL); + get_compute_param(pipe_screen *pipe, pipe_shader_ir ir_format, + pipe_compute_cap cap) { + int sz = pipe->get_compute_param(pipe, ir_format, cap, NULL); std::vector v(sz / sizeof(T)); - pipe->get_compute_param(pipe, cap, &v.front()); + pipe->get_compute_param(pipe, ir_format, cap, &v.front()); return v; } } @@ -115,19 +116,19 @@ device::max_samplers() const { cl_ulong device::max_mem_global() const { - return get_compute_param(pipe, + return get_compute_param(pipe, ir_format(), PIPE_COMPUTE_CAP_MAX_GLOBAL_SIZE)[0]; } cl_ulong device::max_mem_local() const { - return get_compute_param(pipe, + return get_compute_param(pipe, ir_format(), PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE)[0]; } cl_ulong device::max_mem_input() const { - return get_compute_param(pipe, + return get_compute_param(pipe, ir_format(), PIPE_COMPUTE_CAP_MAX_INPUT_SIZE)[0]; } @@ -146,30 +147,30 @@ device::max_const_buffers() const { size_t device::max_threads_per_block() const { return get_compute_param( - pipe, PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK)[0]; + pipe, ir_format(), PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK)[0]; } cl_ulong device::max_mem_alloc_size() const { - return get_compute_param(pipe, + return get_compute_param(pipe, ir_format(), PIPE_COMPUTE_CAP_MAX_MEM_ALLOC_SIZE)[0]; } cl_uint device::max_clock_frequency() const { - return get_compute_param(pipe, + return get_compute_param(pipe, ir_format(), PIPE_COMPUTE_CAP_MAX_CLOCK_FREQUENCY)[0]; } cl_uint device::max_compute_units() const { - return get_compute_param(pipe, + return get_compute_param(pipe, ir_format(), PIPE_COMPUTE_CAP_MAX_COMPUTE_UNITS)[0]; } bool device::image_support() const { - return get_compute_param(pipe, + return get_compute_param(pipe, ir_format(), PIPE_COMPUTE_CAP_IMAGES_SUPPORTED)[0]; } @@ -181,13 +182,15 @@ device::has_doubles() const { std::vector device::max_block_size() const { - auto v = get_compute_param(pipe, PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE); + auto v = get_compute_param(pipe, ir_format(), + PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE); return { v.begin(), v.end() }; } cl_uint device::subgroup_size() const { - return get_compute_param(pipe, PIPE_COMPUTE_CAP_SUBGROUP_SIZE)[0]; + return get_compute_param(pipe, ir_format(), + PIPE_COMPUTE_CAP_SUBGROUP_SIZE)[0]; } std::string @@ -209,7 +212,7 @@ device::ir_format() const { std::string device::ir_target() const { std::vector target = get_compute_param( - pipe, PIPE_COMPUTE_CAP_IR_TARGET); + pipe, ir_format(), PIPE_COMPUTE_CAP_IR_TARGET); return { target.data() }; } diff --git a/src/gallium/tests/trivial/compute.c b/src/gallium/tests/trivial/compute.c index 2ddfc42e9cd..5d012ac3838 100644 --- a/src/gallium/tests/trivial/compute.c +++ b/src/gallium/tests/trivial/compute.c @@ -58,7 +58,9 @@ struct context { uint64_t __v[4]; \ int __i, __n; \ \ - __n = ctx->screen->get_compute_param(ctx->screen, c, __v); \ + __n = ctx->screen->get_compute_param(ctx->screen, \ + PIPE_SHADER_IR_TGSI, \ + c, __v); \ printf("%s: {", #c); \ \ for (__i = 0; __i < __n / sizeof(*__v); ++__i) \ diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index 8748ab5c876..6c0df8d2a98 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -1124,14 +1124,15 @@ void st_init_extensions(struct pipe_screen *screen, if (compute_supported_irs & (1 << PIPE_SHADER_IR_TGSI)) { uint64_t grid_size[3], block_size[3]; - screen->get_compute_param(screen, PIPE_COMPUTE_CAP_MAX_GRID_SIZE, - grid_size); - screen->get_compute_param(screen, PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE, - block_size); - screen->get_compute_param(screen, + screen->get_compute_param(screen, PIPE_SHADER_IR_TGSI, + PIPE_COMPUTE_CAP_MAX_GRID_SIZE, grid_size); + screen->get_compute_param(screen, PIPE_SHADER_IR_TGSI, + PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE, block_size); + screen->get_compute_param(screen, PIPE_SHADER_IR_TGSI, PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK, &consts->MaxComputeWorkGroupInvocations); - screen->get_compute_param(screen, PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE, + screen->get_compute_param(screen, PIPE_SHADER_IR_TGSI, + PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE, &consts->MaxComputeSharedMemorySize); for (i = 0; i < 3; i++) { From ef1b397b0770ddc24240462a1426f6c3fd4952bb Mon Sep 17 00:00:00 2001 From: Jordan Justen Date: Fri, 11 Mar 2016 16:44:06 -0800 Subject: [PATCH 06/62] glsl: Don't require matching centroid qualifiers Note: This patch appears to violate older OpenGL and OpenGLES specs. The OpenGLES GLSL 3.1 and OpenGL GLSL 4.3 specifications both remove the requirement for the output and input centroid qualifiers to match. The deqp dEQP-GLES3.functional.shaders.linkage.varying.rules.differing_interpolation_2 test wants the newer OpenGLES 3.1 specification behavior, even for OpenGLES 3.0. This patch simply removes the checking in all cases. The OpenGLES 3.0 conformance test suite doesn't appear to require the older ("must match") spec behavior. For reference, here are the relavent spec citations: The OpenGL 4.2 spec says: "the last active shader stage output variables and fragment shader input variables of the same name must match in type and qualification (other than out matching to in)" The OpenGL 4.3 spec says: "interpolation qualification (e.g., flat) and auxiliary qualification (e.g. centroid) may differ." The OpenGLES GLSL 3.00.4 specification says: "The output of the vertex shader and the input of the fragment shader form an interface. For this interface, vertex shader output variables and fragment shader input variables of the same name must match in type and qualification (other than precision and out matching to in)." The OpenGLES GLSL 3.10 Specification says: "interpolation qualification (e.g., flat) and auxiliary qualification (e.g. centroid) may differ" Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92743 Bugzilla: https://cvs.khronos.org/bugzilla/show_bug.cgi?id=7819 Signed-off-by: Jordan Justen Cc: Ian Romanick Reviewed-by: Kenneth Graunke --- src/compiler/glsl/link_varyings.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/compiler/glsl/link_varyings.cpp b/src/compiler/glsl/link_varyings.cpp index 848668c4381..e9d0067459a 100644 --- a/src/compiler/glsl/link_varyings.cpp +++ b/src/compiler/glsl/link_varyings.cpp @@ -240,7 +240,16 @@ cross_validate_types_and_qualifiers(struct gl_shader_program *prog, /* Check that all of the qualifiers match between stages. */ - if (input->data.centroid != output->data.centroid) { + + /* According to the OpenGL and OpenGLES GLSL specs, the centroid qualifier + * should match until OpenGL 4.3 and OpenGLES 3.1. The OpenGLES 3.0 + * conformance test suite does not verify that the qualifiers must match. + * The deqp test suite expects the opposite (OpenGLES 3.1) behavior for + * OpenGLES 3.0 drivers, so we relax the checking in all cases. + */ + if (false /* always skip the centroid check */ && + prog->Version < (prog->IsES ? 310 : 430) && + input->data.centroid != output->data.centroid) { linker_error(prog, "%s shader output `%s' %s centroid qualifier, " "but %s shader input %s centroid qualifier\n", From 15cd3ebede62a0c73bfa1513a0c9ab942906cd5a Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Mon, 21 Mar 2016 14:01:24 -0700 Subject: [PATCH 07/62] mesa: Make _mesa_choose_tex_format() handle stencil textures. This is necessary for ARB_texture_stencil8 support on classic drivers. Presumably Gallium works because it implements its own ChooseTexFormat. Signed-off-by: Kenneth Graunke Reviewed-by: Jason Ekstrand --- src/mesa/main/texformat.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/mesa/main/texformat.c b/src/mesa/main/texformat.c index 419fd78e893..be2581b004f 100644 --- a/src/mesa/main/texformat.c +++ b/src/mesa/main/texformat.c @@ -765,6 +765,11 @@ _mesa_choose_tex_format(struct gl_context *ctx, GLenum target, RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_UNORM); break; + case GL_STENCIL_INDEX: + case GL_STENCIL_INDEX8: + RETURN_IF_SUPPORTED(MESA_FORMAT_S_UINT8); + break; + default: /* For non-generic compressed format we assert two things: * From 33df1c293504597c195cb2dca6b0b84e462388cf Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Fri, 1 Apr 2016 21:00:32 -0700 Subject: [PATCH 08/62] glsl: Exclude ir_var_hidden variables from the program resource list. We occasionally generate variables internally that we want to exclude from the program resource list, as applications won't be expecting them to be present. The next patch will make use of this. Signed-off-by: Kenneth Graunke Reviewed-by: Timothy Arceri Reviewed-by: Ilia Mirkin --- src/compiler/glsl/linker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index 510a22e5bd3..cd096bafd0a 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -3525,7 +3525,7 @@ add_interface_variables(struct gl_shader_program *shProg, ir_variable *var = node->as_variable(); uint8_t mask = 0; - if (!var) + if (!var || var->data.how_declared == ir_var_hidden) continue; switch (var->data.mode) { From 2c5afe1fa98d01eb90577c8dbe785fc408f8608f Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Fri, 1 Apr 2016 20:52:33 -0700 Subject: [PATCH 09/62] glsl: Make vertex ID lowering declare gl_BaseVertex as hidden. If the GL_ARB_shader_draw_parameters extension is enabled, we'll already have a gl_BaseVertex variable. It will have var->how_declared set to ir_var_declared_implicitly, and will appear in the program resource list. If not, we make one for internal use. We don't want it to be listed in the program resource list, as the application won't be expecting it. Marking it hidden will properly exclude it. Signed-off-by: Kenneth Graunke Reviewed-by: Timothy Arceri Reviewed-by: Ilia Mirkin --- src/compiler/glsl/lower_vertex_id.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/glsl/lower_vertex_id.cpp b/src/compiler/glsl/lower_vertex_id.cpp index 3da7a2f1b3b..6f46945026c 100644 --- a/src/compiler/glsl/lower_vertex_id.cpp +++ b/src/compiler/glsl/lower_vertex_id.cpp @@ -100,7 +100,7 @@ lower_vertex_id_visitor::visit(ir_dereference_variable *ir) if (gl_BaseVertex == NULL) { gl_BaseVertex = new(mem_ctx) ir_variable(int_t, "gl_BaseVertex", ir_var_system_value); - gl_BaseVertex->data.how_declared = ir_var_declared_implicitly; + gl_BaseVertex->data.how_declared = ir_var_hidden; gl_BaseVertex->data.read_only = true; gl_BaseVertex->data.location = SYSTEM_VALUE_BASE_VERTEX; gl_BaseVertex->data.explicit_location = true; From 356c99b4e79631e195058a2796eba0cdfc1d7a29 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Tue, 29 Mar 2016 11:31:10 -0700 Subject: [PATCH 10/62] glsl: Pass stage to add_interface_variables(). add_interface_variables is supposed to add variables from either the first or last stage of a linked shader. But it has no way of knowing the stage it's being asked to process, which makes it impossible to produce correct stagerefs. Signed-off-by: Kenneth Graunke Reviewed-by: Timothy Arceri --- src/compiler/glsl/linker.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index cd096bafd0a..52df52c244e 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -3519,8 +3519,10 @@ create_shader_variable(struct gl_shader_program *shProg, const ir_variable *in) static bool add_interface_variables(struct gl_shader_program *shProg, - exec_list *ir, GLenum programInterface) + unsigned stage, GLenum programInterface) { + exec_list *ir = shProg->_LinkedShaders[stage]->ir; + foreach_in_list(ir_instruction, node, ir) { ir_variable *var = node->as_variable(); uint8_t mask = 0; @@ -3893,12 +3895,10 @@ build_program_resource_list(struct gl_context *ctx, return; /* Add inputs and outputs to the resource list. */ - if (!add_interface_variables(shProg, shProg->_LinkedShaders[input_stage]->ir, - GL_PROGRAM_INPUT)) + if (!add_interface_variables(shProg, input_stage, GL_PROGRAM_INPUT)) return; - if (!add_interface_variables(shProg, shProg->_LinkedShaders[output_stage]->ir, - GL_PROGRAM_OUTPUT)) + if (!add_interface_variables(shProg, output_stage, GL_PROGRAM_OUTPUT)) return; /* Add transform feedback varyings. */ From 998ef1ad713df583e07c0d172b7c42a10759b879 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Tue, 29 Mar 2016 11:37:48 -0700 Subject: [PATCH 11/62] glsl: Clarify "mask" variable in add_interface_variables(). This is a bitfield of which stages refer to a variable. It is not used to mask off bits. In fact, it's used to contribute additional bits. Rename it and tidy a bit of the logic. Signed-off-by: Kenneth Graunke Reviewed-by: Timothy Arceri --- src/compiler/glsl/linker.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index 52df52c244e..3f06e3b2661 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -3525,7 +3525,7 @@ add_interface_variables(struct gl_shader_program *shProg, foreach_in_list(ir_instruction, node, ir) { ir_variable *var = node->as_variable(); - uint8_t mask = 0; + uint8_t stages = 0; if (!var || var->data.how_declared == ir_var_hidden) continue; @@ -3544,7 +3544,7 @@ add_interface_variables(struct gl_shader_program *shProg, /* Mark special built-in inputs referenced by the vertex stage so * that they are considered active by the shader queries. */ - mask = (1 << (MESA_SHADER_VERTEX)); + stages = (1 << (MESA_SHADER_VERTEX)); /* FALLTHROUGH */ case ir_var_shader_in: if (programInterface != GL_PROGRAM_INPUT) @@ -3574,9 +3574,9 @@ add_interface_variables(struct gl_shader_program *shProg, if (!sha_v) return false; - if (!add_program_resource(shProg, programInterface, sha_v, - build_stageref(shProg, sha_v->name, - sha_v->mode) | mask)) + stages |= build_stageref(shProg, sha_v->name, sha_v->mode); + + if (!add_program_resource(shProg, programInterface, sha_v, stages)) return false; } return true; From 47daf17da02f069b685e41f6f2b251bfafc0b9c5 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Tue, 29 Mar 2016 11:41:46 -0700 Subject: [PATCH 12/62] glsl: Make add_interface_variables only consider the appropriate stage. add_interface_variables() is supposed to add variables for the inputs of the first shader stage linked into a program, and the outputs of the last shader stage linked into a program. From the ARB_program_interface_query specification: "* PROGRAM_INPUT corresponds to the set of active input variables used by the first shader stage of . If includes multiple shader stages, input variables from any shader stage other than the first will not be enumerated. * PROGRAM_OUTPUT corresponds to the set of active output variables (section 2.14.11) used by the last shader stage of . If includes multiple shader stages, output variables from any shader stage other than the last will not be enumerated." Previously, we used build_stageref here, which walks over all linked shaders in the program. This meant that internal varyings would be visible. We don't actually need any of build_stageref's code: we already explicitly skip packed varyings, handle modes, and the name comparisons just do a fuzzy string comparison of name with itself. Fixes two tests: dEQP-GLES31.functional.program_interface_query. program_{input,output}.referenced_by.referenced_by_vertex_fragment. These tests have a VS and FS linked together into a single program. Both stages have an input called "shaderInput". But the FS input should not be visible because it isn't the first stage. Signed-off-by: Kenneth Graunke Reviewed-by: Timothy Arceri --- src/compiler/glsl/linker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index 3f06e3b2661..a8d9cf4ce2a 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -3574,7 +3574,7 @@ add_interface_variables(struct gl_shader_program *shProg, if (!sha_v) return false; - stages |= build_stageref(shProg, sha_v->name, sha_v->mode); + stages |= 1 << stage; if (!add_program_resource(shProg, programInterface, sha_v, stages)) return false; From 6e8b9d5bdd200a8e65cdefe1d2f97bacc5a2c63d Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Tue, 29 Mar 2016 12:11:55 -0700 Subject: [PATCH 13/62] glsl: Delete hack for VS system values. This makes no sense. If the stage being considered is the vertex shader, then we'll add inputs and system values appropriately. If we're not considering the vertex shader, then we absolutely should not do anything with it. Signed-off-by: Kenneth Graunke Reviewed-by: Timothy Arceri --- src/compiler/glsl/linker.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index a8d9cf4ce2a..0005d4965e1 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -3541,10 +3541,6 @@ add_interface_variables(struct gl_shader_program *shProg, var->data.location != SYSTEM_VALUE_VERTEX_ID_ZERO_BASE && var->data.location != SYSTEM_VALUE_INSTANCE_ID) continue; - /* Mark special built-in inputs referenced by the vertex stage so - * that they are considered active by the shader queries. - */ - stages = (1 << (MESA_SHADER_VERTEX)); /* FALLTHROUGH */ case ir_var_shader_in: if (programInterface != GL_PROGRAM_INPUT) From 98c22c04036da4f0a7fcc396dc6c5e0bfe5890e5 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Tue, 29 Mar 2016 12:07:37 -0700 Subject: [PATCH 14/62] glsl: Add all system variables to the input resource list. System values are just built-in input variables that we've opted to special-case out of convenience. We need to consider all inputs, regardless of how we've classified them. Unfortunately, there's one exception: we shouldn't add gl_BaseVertex unless ARB_shader_draw_parameters is enabled, because it doesn't actually exist in the language, and shouldn't be counted in the GL_ACTIVE_RESOURCES query. Fixes dEQP-GLES31.functional.program_interface_query.program_input. resource_list.compute.empty, which expects gl_NumWorkGroups to appear in the resource list. v2: Delete more code Signed-off-by: Kenneth Graunke Reviewed-by: Timothy Arceri --- src/compiler/glsl/linker.cpp | 10 ---------- src/mesa/main/shader_query.cpp | 9 +-------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index 0005d4965e1..19f4641c724 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -3531,17 +3531,7 @@ add_interface_variables(struct gl_shader_program *shProg, continue; switch (var->data.mode) { - /* From GL 4.3 core spec, section 11.1.1 (Vertex Attributes): - * "For GetActiveAttrib, all active vertex shader input variables - * are enumerated, including the special built-in inputs gl_VertexID - * and gl_InstanceID." - */ case ir_var_system_value: - if (var->data.location != SYSTEM_VALUE_VERTEX_ID && - var->data.location != SYSTEM_VALUE_VERTEX_ID_ZERO_BASE && - var->data.location != SYSTEM_VALUE_INSTANCE_ID) - continue; - /* FALLTHROUGH */ case ir_var_shader_in: if (programInterface != GL_PROGRAM_INPUT) continue; diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp index 993dc863220..e85e81d897c 100644 --- a/src/mesa/main/shader_query.cpp +++ b/src/mesa/main/shader_query.cpp @@ -112,14 +112,7 @@ is_active_attrib(const gl_shader_variable *var) return var->location != -1; case ir_var_system_value: - /* From GL 4.3 core spec, section 11.1.1 (Vertex Attributes): - * "For GetActiveAttrib, all active vertex shader input variables - * are enumerated, including the special built-in inputs gl_VertexID - * and gl_InstanceID." - */ - return var->location == SYSTEM_VALUE_VERTEX_ID || - var->location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE || - var->location == SYSTEM_VALUE_INSTANCE_ID; + return true; default: return false; From 013f25c3b3aa676cbd580fc070454d74db27a400 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Tue, 29 Mar 2016 12:31:28 -0700 Subject: [PATCH 15/62] glsl: Clean up some leftover cruft. stages is always 1 << stage now. Signed-off-by: Kenneth Graunke Reviewed-by: Timothy Arceri --- src/compiler/glsl/linker.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index 19f4641c724..064e7f5ca21 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -3525,7 +3525,6 @@ add_interface_variables(struct gl_shader_program *shProg, foreach_in_list(ir_instruction, node, ir) { ir_variable *var = node->as_variable(); - uint8_t stages = 0; if (!var || var->data.how_declared == ir_var_hidden) continue; @@ -3560,9 +3559,7 @@ add_interface_variables(struct gl_shader_program *shProg, if (!sha_v) return false; - stages |= 1 << stage; - - if (!add_program_resource(shProg, programInterface, sha_v, stages)) + if (!add_program_resource(shProg, programInterface, sha_v, 1 << stage)) return false; } return true; From 9fe211bec4533bd5cebeb61b38343ae9c174abb7 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Tue, 29 Mar 2016 13:32:32 -0700 Subject: [PATCH 16/62] glsl: Consolidate gl_VertexIDMESA -> gl_VertexID query hacks. A program will either have gl_VertexID or gl_VertexIDMESA (the lowered zero-based version), not both. Just spoof it in the resource list so the hacks are done in a single place. Signed-off-by: Kenneth Graunke Reviewed-by: Timothy Arceri --- src/compiler/glsl/linker.cpp | 12 ++++++++++-- src/mesa/main/shader_query.cpp | 17 ----------------- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index 064e7f5ca21..c0d310746f3 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -3503,12 +3503,20 @@ create_shader_variable(struct gl_shader_program *shProg, const ir_variable *in) if (!out) return NULL; - out->type = in->type; - out->name = ralloc_strdup(shProg, in->name); + /* Since gl_VertexID may be lowered to gl_VertexIDMESA, but applications + * expect to see gl_VertexID in the program resource list. Pretend. + */ + if (in->data.mode == ir_var_system_value && + in->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) { + out->name = ralloc_strdup(shProg, "gl_VertexID"); + } else { + out->name = ralloc_strdup(shProg, in->name); + } if (!out->name) return NULL; + out->type = in->type; out->location = in->data.location; out->index = in->data.index; out->patch = in->data.patch; diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp index e85e81d897c..caff79f39af 100644 --- a/src/mesa/main/shader_query.cpp +++ b/src/mesa/main/shader_query.cpp @@ -164,15 +164,6 @@ _mesa_GetActiveAttrib(GLuint program, GLuint desired_index, const char *var_name = var->name; - /* Since gl_VertexID may be lowered to gl_VertexIDMESA, we need to - * consider gl_VertexIDMESA as gl_VertexID for purposes of checking - * active attributes. - */ - if (var->mode == ir_var_system_value && - var->location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) { - var_name = "gl_VertexID"; - } - _mesa_copy_string(name, maxLength, length, var_name); if (size) @@ -421,7 +412,6 @@ _mesa_GetFragDataLocation(GLuint program, const GLchar *name) const char* _mesa_program_resource_name(struct gl_program_resource *res) { - const gl_shader_variable *var; switch (res->Type) { case GL_UNIFORM_BLOCK: case GL_SHADER_STORAGE_BLOCK: @@ -429,13 +419,6 @@ _mesa_program_resource_name(struct gl_program_resource *res) case GL_TRANSFORM_FEEDBACK_VARYING: return RESOURCE_XFV(res)->Name; case GL_PROGRAM_INPUT: - var = RESOURCE_VAR(res); - /* Special case gl_VertexIDMESA -> gl_VertexID. */ - if (var->mode == ir_var_system_value && - var->location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) { - return "gl_VertexID"; - } - /* fallthrough */ case GL_PROGRAM_OUTPUT: return RESOURCE_VAR(res)->name; case GL_UNIFORM: From c123294dfe2e52443f2eff2723ef922f22972ef5 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Tue, 29 Mar 2016 13:21:48 -0700 Subject: [PATCH 17/62] glsl: Return -1 for program interface query locations in many cases. We were recording locations for all variables, even ones without an explicit location set. Implement the rules from the spec, and record -1 in the resource list accordngly. Make program_resource_location stop doing math on negative values. Remove hacks that are no longer necessary now that we've stopped doing that. Fixes 4 dEQP-GLES31.functional.program_interface_query tests: - program_input.location.separable_fragment.var - program_input.location.separable_fragment.var_array - program_output.location.separable_vertex.var_array - program_output.location.separable_vertex.var_array v2: Delete more code Signed-off-by: Kenneth Graunke Reviewed-by: Timothy Arceri --- src/compiler/glsl/linker.cpp | 38 ++++++++++++++++++--- src/mesa/main/shader_query.cpp | 62 +++++----------------------------- 2 files changed, 42 insertions(+), 58 deletions(-) diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index c0d310746f3..71dbddd8763 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -3497,7 +3497,8 @@ build_stageref(struct gl_shader_program *shProg, const char *name, * Create gl_shader_variable from ir_variable class. */ static gl_shader_variable * -create_shader_variable(struct gl_shader_program *shProg, const ir_variable *in) +create_shader_variable(struct gl_shader_program *shProg, + const ir_variable *in, bool use_implicit_location) { gl_shader_variable *out = ralloc(shProg, struct gl_shader_variable); if (!out) @@ -3516,8 +3517,29 @@ create_shader_variable(struct gl_shader_program *shProg, const ir_variable *in) if (!out->name) return NULL; + /* From the ARB_program_interface_query specification: + * + * "Not all active variables are assigned valid locations; the + * following variables will have an effective location of -1: + * + * * uniforms declared as atomic counters; + * + * * members of a uniform block; + * + * * built-in inputs, outputs, and uniforms (starting with "gl_"); and + * + * * inputs or outputs not declared with a "location" layout qualifier, + * except for vertex shader inputs and fragment shader outputs." + */ + if (in->type->base_type == GLSL_TYPE_ATOMIC_UINT || + is_gl_identifier(in->name) || + !(in->data.explicit_location || use_implicit_location)) { + out->location = -1; + } else { + out->location = in->data.location; + } + out->type = in->type; - out->location = in->data.location; out->index = in->data.index; out->patch = in->data.patch; out->mode = in->data.mode; @@ -3563,7 +3585,12 @@ add_interface_variables(struct gl_shader_program *shProg, if (strncmp(var->name, "gl_out_FragData", 15) == 0) continue; - gl_shader_variable *sha_v = create_shader_variable(shProg, var); + const bool vs_input_or_fs_output = + (stage == MESA_SHADER_VERTEX && var->data.mode == ir_var_shader_in) || + (stage == MESA_SHADER_FRAGMENT && var->data.mode == ir_var_shader_out); + + gl_shader_variable *sha_v = + create_shader_variable(shProg, var, vs_input_or_fs_output); if (!sha_v) return false; @@ -3597,7 +3624,8 @@ add_packed_varyings(struct gl_shader_program *shProg, int stage, GLenum type) } if (type == iface) { - gl_shader_variable *sha_v = create_shader_variable(shProg, var); + gl_shader_variable *sha_v = + create_shader_variable(shProg, var, false); if (!sha_v) return false; if (!add_program_resource(shProg, iface, sha_v, @@ -3622,7 +3650,7 @@ add_fragdata_arrays(struct gl_shader_program *shProg) ir_variable *var = node->as_variable(); if (var) { assert(var->data.mode == ir_var_shader_out); - gl_shader_variable *sha_v = create_shader_variable(shProg, var); + gl_shader_variable *sha_v = create_shader_variable(shProg, var, true); if (!sha_v) return false; if (!add_program_resource(shProg, GL_PROGRAM_OUTPUT, sha_v, diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp index caff79f39af..190f6387987 100644 --- a/src/mesa/main/shader_query.cpp +++ b/src/mesa/main/shader_query.cpp @@ -101,24 +101,6 @@ _mesa_BindAttribLocation(GLuint program, GLuint index, */ } -static bool -is_active_attrib(const gl_shader_variable *var) -{ - if (!var) - return false; - - switch (var->mode) { - case ir_var_shader_in: - return var->location != -1; - - case ir_var_system_value: - return true; - - default: - return false; - } -} - void GLAPIENTRY _mesa_GetActiveAttrib(GLuint program, GLuint desired_index, GLsizei maxLength, GLsizei * length, GLint * size, @@ -159,9 +141,6 @@ _mesa_GetActiveAttrib(GLuint program, GLuint desired_index, const gl_shader_variable *const var = RESOURCE_VAR(res); - if (!is_active_attrib(var)) - return; - const char *var_name = var->name; _mesa_copy_string(name, maxLength, length, var_name); @@ -208,19 +187,7 @@ _mesa_GetAttribLocation(GLuint program, const GLchar * name) if (!res) return -1; - GLint loc = program_resource_location(shProg, res, name, array_index); - - /* The extra check against against 0 is made because of builtin-attribute - * locations that have offset applied. Function program_resource_location - * can return built-in attribute locations < 0 and glGetAttribLocation - * cannot be used on "conventional" attributes. - * - * From page 95 of the OpenGL 3.0 spec: - * - * "If name is not an active attribute, if name is a conventional - * attribute, or if an error occurs, -1 will be returned." - */ - return (loc >= 0) ? loc : -1; + return program_resource_location(shProg, res, name, array_index); } unsigned @@ -235,8 +202,7 @@ _mesa_count_active_attribs(struct gl_shader_program *shProg) unsigned count = 0; for (unsigned j = 0; j < shProg->NumProgramResourceList; j++, res++) { if (res->Type == GL_PROGRAM_INPUT && - res->StageReferences & (1 << MESA_SHADER_VERTEX) && - is_active_attrib(RESOURCE_VAR(res))) + res->StageReferences & (1 << MESA_SHADER_VERTEX)) count++; } return count; @@ -394,19 +360,7 @@ _mesa_GetFragDataLocation(GLuint program, const GLchar *name) if (!res) return -1; - GLint loc = program_resource_location(shProg, res, name, array_index); - - /* The extra check against against 0 is made because of builtin-attribute - * locations that have offset applied. Function program_resource_location - * can return built-in attribute locations < 0 and glGetFragDataLocation - * cannot be used on "conventional" attributes. - * - * From page 95 of the OpenGL 3.0 spec: - * - * "If name is not an active attribute, if name is a conventional - * attribute, or if an error occurs, -1 will be returned." - */ - return (loc >= 0) ? loc : -1; + return program_resource_location(shProg, res, name, array_index); } const char* @@ -826,10 +780,6 @@ program_resource_location(struct gl_shader_program *shProg, struct gl_program_resource *res, const char *name, unsigned array_index) { - /* Built-in locations should report GL_INVALID_INDEX. */ - if (is_gl_identifier(name)) - return GL_INVALID_INDEX; - /* VERT_ATTRIB_GENERIC0 and FRAG_RESULT_DATA0 are decremented as these * offsets are used internally to differentiate between built-in attributes * and user-defined attributes. @@ -838,6 +788,9 @@ program_resource_location(struct gl_shader_program *shProg, case GL_PROGRAM_INPUT: { const gl_shader_variable *var = RESOURCE_VAR(res); + if (var->location == -1) + return -1; + /* If the input is an array, fail if the index is out of bounds. */ if (array_index > 0 && array_index >= var->type->length) { @@ -848,6 +801,9 @@ program_resource_location(struct gl_shader_program *shProg, VERT_ATTRIB_GENERIC0); } case GL_PROGRAM_OUTPUT: + if (RESOURCE_VAR(res)->location == -1) + return -1; + /* If the output is an array, fail if the index is out of bounds. */ if (array_index > 0 && array_index >= RESOURCE_VAR(res)->type->length) { From 94ed482c19916ddede91c3c2ea3a538039ddb489 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Tue, 29 Mar 2016 14:15:14 -0700 Subject: [PATCH 18/62] glsl: Fix prorgram interface query locations biasing for SSO. With SSO, the GL_PROGRAM_INPUT and GL_PROGRAM_OUTPUT interfaces refer to the first and last shader stage linked into a program. This may not be the vertex and fragment shader stages. So, subtracting VERT_ATTRIB_GENERIC0 and FRAG_RESULT_DATA0 is bogus. We need to subtract VERT_ATTRIB_GENERIC0 for VS inputs, FRAG_RESULT_DATA0 for FS outputs, and VARYING_SLOT_VAR0 for other cases. Note that built-in variables get a location of -1. Fixes 4 dEQP-GLES31.functional.program_interface_query tests: - program_input.location.separable_fragment.var_explicit_location - program_input.location.separable_fragment.var_array_explicit_location - program_output.location.separable_vertex.var_array_explicit_location - program_output.location.separable_vertex.var_array_explicit_location Signed-off-by: Kenneth Graunke Reviewed-by: Timothy Arceri --- src/compiler/glsl/linker.cpp | 18 +++++++++++++----- src/mesa/main/shader_query.cpp | 11 +++-------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index 71dbddd8763..736852e7809 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -3498,7 +3498,8 @@ build_stageref(struct gl_shader_program *shProg, const char *name, */ static gl_shader_variable * create_shader_variable(struct gl_shader_program *shProg, - const ir_variable *in, bool use_implicit_location) + const ir_variable *in, bool use_implicit_location, + int location_bias) { gl_shader_variable *out = ralloc(shProg, struct gl_shader_variable); if (!out) @@ -3536,7 +3537,7 @@ create_shader_variable(struct gl_shader_program *shProg, !(in->data.explicit_location || use_implicit_location)) { out->location = -1; } else { - out->location = in->data.location; + out->location = in->data.location - location_bias; } out->type = in->type; @@ -3559,15 +3560,21 @@ add_interface_variables(struct gl_shader_program *shProg, if (!var || var->data.how_declared == ir_var_hidden) continue; + int loc_bias; + switch (var->data.mode) { case ir_var_system_value: case ir_var_shader_in: if (programInterface != GL_PROGRAM_INPUT) continue; + loc_bias = (stage == MESA_SHADER_VERTEX) ? int(VERT_ATTRIB_GENERIC0) + : int(VARYING_SLOT_VAR0); break; case ir_var_shader_out: if (programInterface != GL_PROGRAM_OUTPUT) continue; + loc_bias = (stage == MESA_SHADER_FRAGMENT) ? int(FRAG_RESULT_DATA0) + : int(VARYING_SLOT_VAR0); break; default: continue; @@ -3590,7 +3597,7 @@ add_interface_variables(struct gl_shader_program *shProg, (stage == MESA_SHADER_FRAGMENT && var->data.mode == ir_var_shader_out); gl_shader_variable *sha_v = - create_shader_variable(shProg, var, vs_input_or_fs_output); + create_shader_variable(shProg, var, vs_input_or_fs_output, loc_bias); if (!sha_v) return false; @@ -3625,7 +3632,7 @@ add_packed_varyings(struct gl_shader_program *shProg, int stage, GLenum type) if (type == iface) { gl_shader_variable *sha_v = - create_shader_variable(shProg, var, false); + create_shader_variable(shProg, var, false, VARYING_SLOT_VAR0); if (!sha_v) return false; if (!add_program_resource(shProg, iface, sha_v, @@ -3650,7 +3657,8 @@ add_fragdata_arrays(struct gl_shader_program *shProg) ir_variable *var = node->as_variable(); if (var) { assert(var->data.mode == ir_var_shader_out); - gl_shader_variable *sha_v = create_shader_variable(shProg, var, true); + gl_shader_variable *sha_v = + create_shader_variable(shProg, var, true, FRAG_RESULT_DATA0); if (!sha_v) return false; if (!add_program_resource(shProg, GL_PROGRAM_OUTPUT, sha_v, diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp index 190f6387987..4650a5c9ef1 100644 --- a/src/mesa/main/shader_query.cpp +++ b/src/mesa/main/shader_query.cpp @@ -780,10 +780,6 @@ program_resource_location(struct gl_shader_program *shProg, struct gl_program_resource *res, const char *name, unsigned array_index) { - /* VERT_ATTRIB_GENERIC0 and FRAG_RESULT_DATA0 are decremented as these - * offsets are used internally to differentiate between built-in attributes - * and user-defined attributes. - */ switch (res->Type) { case GL_PROGRAM_INPUT: { const gl_shader_variable *var = RESOURCE_VAR(res); @@ -796,9 +792,8 @@ program_resource_location(struct gl_shader_program *shProg, && array_index >= var->type->length) { return -1; } - return (var->location + - (array_index * var->type->without_array()->matrix_columns) - - VERT_ATTRIB_GENERIC0); + return var->location + + (array_index * var->type->without_array()->matrix_columns); } case GL_PROGRAM_OUTPUT: if (RESOURCE_VAR(res)->location == -1) @@ -809,7 +804,7 @@ program_resource_location(struct gl_shader_program *shProg, && array_index >= RESOURCE_VAR(res)->type->length) { return -1; } - return RESOURCE_VAR(res)->location + array_index - FRAG_RESULT_DATA0; + return RESOURCE_VAR(res)->location + array_index; case GL_UNIFORM: /* If the uniform is built-in, fail. */ if (RESOURCE_UNI(res)->builtin) From 0163881528c8ee650ceb9e3fd932876481a41f37 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Sat, 2 Apr 2016 11:06:39 +1100 Subject: [PATCH 19/62] glsl: only set buffer block binding once during initialisation Since 8683d54d2be825 there is now a single instance of the buffer block information that needs to be updated rather than one instance for each stage. Reviewed-by: Kenneth Graunke --- .../glsl/link_uniform_initializers.cpp | 32 ++++--------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/src/compiler/glsl/link_uniform_initializers.cpp b/src/compiler/glsl/link_uniform_initializers.cpp index 870bc5bfebd..e5edf2e72e4 100644 --- a/src/compiler/glsl/link_uniform_initializers.cpp +++ b/src/compiler/glsl/link_uniform_initializers.cpp @@ -44,18 +44,6 @@ get_storage(gl_uniform_storage *storage, unsigned num_storage, return NULL; } -static unsigned -get_uniform_block_index(const gl_shader_program *shProg, - const char *uniformBlockName) -{ - for (unsigned i = 0; i < shProg->NumBufferInterfaceBlocks; i++) { - if (!strcmp(shProg->BufferInterfaceBlocks[i].Name, uniformBlockName)) - return i; - } - - return GL_INVALID_INDEX; -} - void copy_constant_to_storage(union gl_constant_value *storage, const ir_constant *val, @@ -168,22 +156,14 @@ set_opaque_binding(void *mem_ctx, gl_shader_program *prog, void set_block_binding(gl_shader_program *prog, const char *block_name, int binding) { - const unsigned block_index = get_uniform_block_index(prog, block_name); - - if (block_index == GL_INVALID_INDEX) { - assert(block_index != GL_INVALID_INDEX); - return; + for (unsigned i = 0; i < prog->NumBufferInterfaceBlocks; i++) { + if (!strcmp(prog->BufferInterfaceBlocks[i].Name, block_name)) { + prog->BufferInterfaceBlocks[i].Binding = binding; + return; + } } - /* This is a field of a UBO. val is the binding index. */ - for (int i = 0; i < MESA_SHADER_STAGES; i++) { - int stage_index = prog->InterfaceBlockStageIndex[i][block_index]; - - if (stage_index != -1) { - struct gl_shader *sh = prog->_LinkedShaders[i]; - sh->BufferInterfaceBlocks[stage_index]->Binding = binding; - } - } + unreachable("Failed to initialize block binding"); } void From 3e74bf5b9de39a482716f8b5d090fb45ec6cc3ca Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Sat, 2 Apr 2016 12:12:10 +1100 Subject: [PATCH 20/62] glsl: split buffer block arrays earlier This will allow us to use them when checking resources in a following patch and clean up a bunch of code. Reviewed-by: Kenneth Graunke --- src/compiler/glsl/linker.cpp | 54 ++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index 736852e7809..ab90961a898 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -4713,6 +4713,33 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) has_xfb_qualifiers)) goto done; + /* Split BufferInterfaceBlocks into UniformBlocks and ShaderStorageBlocks + * for gl_shader_program and gl_shader, so that drivers that need separate + * index spaces for each set can have that. + */ + for (unsigned i = MESA_SHADER_VERTEX; i < MESA_SHADER_STAGES; i++) { + if (prog->_LinkedShaders[i] != NULL) { + gl_shader *sh = prog->_LinkedShaders[i]; + split_ubos_and_ssbos(sh, + sh->BufferInterfaceBlocks, + NULL, + sh->NumBufferInterfaceBlocks, + &sh->UniformBlocks, + &sh->NumUniformBlocks, + &sh->ShaderStorageBlocks, + &sh->NumShaderStorageBlocks); + } + } + + split_ubos_and_ssbos(prog, + NULL, + prog->BufferInterfaceBlocks, + prog->NumBufferInterfaceBlocks, + &prog->UniformBlocks, + &prog->NumUniformBlocks, + &prog->ShaderStorageBlocks, + &prog->NumShaderStorageBlocks); + update_array_sizes(prog); link_assign_uniform_locations(prog, ctx->Const.UniformBooleanTrue, num_explicit_uniform_locs, @@ -4764,33 +4791,6 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) } } - /* Split BufferInterfaceBlocks into UniformBlocks and ShaderStorageBlocks - * for gl_shader_program and gl_shader, so that drivers that need separate - * index spaces for each set can have that. - */ - for (unsigned i = MESA_SHADER_VERTEX; i < MESA_SHADER_STAGES; i++) { - if (prog->_LinkedShaders[i] != NULL) { - gl_shader *sh = prog->_LinkedShaders[i]; - split_ubos_and_ssbos(sh, - sh->BufferInterfaceBlocks, - NULL, - sh->NumBufferInterfaceBlocks, - &sh->UniformBlocks, - &sh->NumUniformBlocks, - &sh->ShaderStorageBlocks, - &sh->NumShaderStorageBlocks); - } - } - - split_ubos_and_ssbos(prog, - NULL, - prog->BufferInterfaceBlocks, - prog->NumBufferInterfaceBlocks, - &prog->UniformBlocks, - &prog->NumUniformBlocks, - &prog->ShaderStorageBlocks, - &prog->NumShaderStorageBlocks); - for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { if (prog->_LinkedShaders[i] == NULL) continue; From 0082b33a78cd007054f7774c57a4f7ea9fc1d209 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Sat, 2 Apr 2016 11:48:27 +1100 Subject: [PATCH 21/62] glsl: simplify SSBO resources check We already have a count of active SSBOs per stage so use it. Reviewed-by: Kenneth Graunke --- src/compiler/glsl/linker.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index ab90961a898..47087c86243 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -3072,13 +3072,7 @@ check_image_resources(struct gl_context *ctx, struct gl_shader_program *prog) ctx->Const.Program[i].MaxImageUniforms); total_image_units += sh->NumImages; - - for (unsigned j = 0; j < prog->NumBufferInterfaceBlocks; j++) { - int stage_index = prog->InterfaceBlockStageIndex[i][j]; - if (stage_index != -1 && - sh->BufferInterfaceBlocks[stage_index]->IsShaderStorage) - total_shader_storage_blocks++; - } + total_shader_storage_blocks += sh->NumShaderStorageBlocks; if (i == MESA_SHADER_FRAGMENT) { foreach_in_list(ir_instruction, node, sh->ir) { From d8855d66f4ae2acf994eae31e59fd2cfa5483627 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Sat, 2 Apr 2016 12:16:01 +1100 Subject: [PATCH 22/62] glsl: simplify buffer block resource limit checking This changes the code to use the buffer counts stored for each stage rather than counting from scratch. It also moves the checks outside of the for loop which means we now just get a single link error message if we go over the max rather than X error messages where X is the number we have exceeded the max by. Reviewed-by: Kenneth Graunke --- src/compiler/glsl/linker.cpp | 87 +++++++++++++----------------------- 1 file changed, 32 insertions(+), 55 deletions(-) diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index 47087c86243..f440dbce888 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -2890,6 +2890,9 @@ store_fragdepth_layout(struct gl_shader_program *prog) static void check_resources(struct gl_context *ctx, struct gl_shader_program *prog) { + unsigned total_uniform_blocks = 0; + unsigned total_shader_storage_blocks = 0; + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { struct gl_shader *sh = prog->_LinkedShaders[i]; @@ -2928,12 +2931,37 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog) _mesa_shader_stage_to_string(i)); } } + + total_shader_storage_blocks += sh->NumShaderStorageBlocks; + total_uniform_blocks += sh->NumUniformBlocks; + + const unsigned max_uniform_blocks = + ctx->Const.Program[i].MaxUniformBlocks; + if (max_uniform_blocks < sh->NumUniformBlocks) { + linker_error(prog, "Too many %s uniform blocks (%d/%d)\n", + _mesa_shader_stage_to_string(i), sh->NumUniformBlocks, + max_uniform_blocks); + } + + const unsigned max_shader_storage_blocks = + ctx->Const.Program[i].MaxShaderStorageBlocks; + if (max_shader_storage_blocks < sh->NumShaderStorageBlocks) { + linker_error(prog, "Too many %s shader storage blocks (%d/%d)\n", + _mesa_shader_stage_to_string(i), + sh->NumShaderStorageBlocks, max_shader_storage_blocks); + } } - unsigned blocks[MESA_SHADER_STAGES] = {0}; - unsigned total_uniform_blocks = 0; - unsigned shader_blocks[MESA_SHADER_STAGES] = {0}; - unsigned total_shader_storage_blocks = 0; + if (total_uniform_blocks > ctx->Const.MaxCombinedUniformBlocks) { + linker_error(prog, "Too many combined uniform blocks (%d/%d)\n", + total_uniform_blocks, ctx->Const.MaxCombinedUniformBlocks); + } + + if (total_shader_storage_blocks > ctx->Const.MaxCombinedShaderStorageBlocks) { + linker_error(prog, "Too many combined shader storage blocks (%d/%d)\n", + total_shader_storage_blocks, + ctx->Const.MaxCombinedShaderStorageBlocks); + } for (unsigned i = 0; i < prog->NumBufferInterfaceBlocks; i++) { /* Don't check SSBOs for Uniform Block Size */ @@ -2952,57 +2980,6 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog) prog->BufferInterfaceBlocks[i].UniformBufferSize, ctx->Const.MaxShaderStorageBlockSize); } - - for (unsigned j = 0; j < MESA_SHADER_STAGES; j++) { - if (prog->InterfaceBlockStageIndex[j][i] != -1) { - struct gl_shader *sh = prog->_LinkedShaders[j]; - int stage_index = prog->InterfaceBlockStageIndex[j][i]; - if (sh && - sh->BufferInterfaceBlocks[stage_index]->IsShaderStorage) { - shader_blocks[j]++; - total_shader_storage_blocks++; - } else { - blocks[j]++; - total_uniform_blocks++; - } - } - } - - if (total_uniform_blocks > ctx->Const.MaxCombinedUniformBlocks) { - linker_error(prog, "Too many combined uniform blocks (%d/%d)\n", - total_uniform_blocks, - ctx->Const.MaxCombinedUniformBlocks); - } else { - for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { - const unsigned max_uniform_blocks = - ctx->Const.Program[i].MaxUniformBlocks; - if (blocks[i] > max_uniform_blocks) { - linker_error(prog, "Too many %s uniform blocks (%d/%d)\n", - _mesa_shader_stage_to_string(i), - blocks[i], - max_uniform_blocks); - break; - } - } - } - - if (total_shader_storage_blocks > ctx->Const.MaxCombinedShaderStorageBlocks) { - linker_error(prog, "Too many combined shader storage blocks (%d/%d)\n", - total_shader_storage_blocks, - ctx->Const.MaxCombinedShaderStorageBlocks); - } else { - for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { - const unsigned max_shader_storage_blocks = - ctx->Const.Program[i].MaxShaderStorageBlocks; - if (shader_blocks[i] > max_shader_storage_blocks) { - linker_error(prog, "Too many %s shader storage blocks (%d/%d)\n", - _mesa_shader_stage_to_string(i), - shader_blocks[i], - max_shader_storage_blocks); - break; - } - } - } } } From 1265e1c4e17dec5c9931fda8b6d44a4006ed1a4c Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Sat, 2 Apr 2016 12:51:12 +1100 Subject: [PATCH 23/62] glsl: store stage reference in gl_uniform_block This allows us to simplify the code and drop InterfaceBlockStageIndex which is a per stage array of integers the size of all blocks in the program combined including duplicates across stages. Adding a stage ref per block will use less memory. Reviewed-by: Kenneth Graunke --- src/compiler/glsl/linker.cpp | 37 ++++++++++++-------- src/compiler/glsl/standalone_scaffolding.cpp | 7 ---- src/mesa/main/mtypes.h | 13 ++----- src/mesa/main/shader_query.cpp | 2 +- src/mesa/main/shaderobj.c | 4 --- 5 files changed, 26 insertions(+), 37 deletions(-) diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index f440dbce888..f750f5b7722 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -1171,6 +1171,8 @@ cross_validate_uniforms(struct gl_shader_program *prog) static bool interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog) { + int *InterfaceBlockStageIndex[MESA_SHADER_STAGES]; + unsigned max_num_uniform_blocks = 0; for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { if (prog->_LinkedShaders[i]) @@ -1180,10 +1182,9 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog) for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { struct gl_shader *sh = prog->_LinkedShaders[i]; - prog->InterfaceBlockStageIndex[i] = ralloc_array(prog, int, - max_num_uniform_blocks); + InterfaceBlockStageIndex[i] = new int[max_num_uniform_blocks]; for (unsigned int j = 0; j < max_num_uniform_blocks; j++) - prog->InterfaceBlockStageIndex[i][j] = -1; + InterfaceBlockStageIndex[i][j] = -1; if (sh == NULL) continue; @@ -1194,13 +1195,17 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog) &prog->NumBufferInterfaceBlocks, sh->BufferInterfaceBlocks[j]); - if (index == -1) { - linker_error(prog, "uniform block `%s' has mismatching definitions\n", - sh->BufferInterfaceBlocks[j]->Name); - return false; - } + if (index == -1) { + linker_error(prog, "uniform block `%s' has mismatching definitions\n", + sh->BufferInterfaceBlocks[j]->Name); - prog->InterfaceBlockStageIndex[i][index] = j; + for (unsigned k = 0; k <= i; k++) { + delete[] InterfaceBlockStageIndex[k]; + } + return false; + } + + InterfaceBlockStageIndex[i][index] = j; } } @@ -1209,18 +1214,23 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog) */ for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { for (unsigned j = 0; j < prog->NumBufferInterfaceBlocks; j++) { - int stage_index = - prog->InterfaceBlockStageIndex[i][j]; + int stage_index = InterfaceBlockStageIndex[i][j]; if (stage_index != -1) { struct gl_shader *sh = prog->_LinkedShaders[i]; + prog->BufferInterfaceBlocks[j].stageref |= (1 << i); + sh->BufferInterfaceBlocks[stage_index] = &prog->BufferInterfaceBlocks[j]; } } } + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + delete[] InterfaceBlockStageIndex[i]; + } + return true; } @@ -3933,10 +3943,7 @@ build_program_resource_list(struct gl_context *ctx, /* Add stagereferences for uniforms in a uniform block. */ int block_index = shProg->UniformStorage[i].block_index; if (block_index != -1) { - for (unsigned j = 0; j < MESA_SHADER_STAGES; j++) { - if (shProg->InterfaceBlockStageIndex[j][block_index] != -1) - stageref |= (1 << j); - } + stageref |= shProg->BufferInterfaceBlocks[block_index].stageref; } bool is_shader_storage = shProg->UniformStorage[i].is_shader_storage; diff --git a/src/compiler/glsl/standalone_scaffolding.cpp b/src/compiler/glsl/standalone_scaffolding.cpp index e350f702099..49b4a26dc12 100644 --- a/src/compiler/glsl/standalone_scaffolding.cpp +++ b/src/compiler/glsl/standalone_scaffolding.cpp @@ -96,8 +96,6 @@ _mesa_delete_shader(struct gl_context *ctx, struct gl_shader *sh) void _mesa_clear_shader_program_data(struct gl_shader_program *shProg) { - unsigned i; - shProg->NumUniformStorage = 0; shProg->UniformStorage = NULL; shProg->NumUniformRemapTable = 0; @@ -119,11 +117,6 @@ _mesa_clear_shader_program_data(struct gl_shader_program *shProg) shProg->ShaderStorageBlocks = NULL; shProg->NumShaderStorageBlocks = 0; - for (i = 0; i < MESA_SHADER_STAGES; i++) { - ralloc_free(shProg->InterfaceBlockStageIndex[i]); - shProg->InterfaceBlockStageIndex[i] = NULL; - } - ralloc_free(shProg->AtomicBuffers); shProg->AtomicBuffers = NULL; shProg->NumAtomicBuffers = 0; diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index f2cb4cb107b..e579794de3c 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2529,6 +2529,9 @@ struct gl_uniform_block */ bool IsShaderStorage; + /** Stages that reference this block */ + uint8_t stageref; + /** * Layout specified in the shader * @@ -2829,16 +2832,6 @@ struct gl_shader_program unsigned NumShaderStorageBlocks; struct gl_uniform_block **ShaderStorageBlocks; - /** - * Indices into the BufferInterfaceBlocks[] array for each stage they're - * used in, or -1. - * - * This is used to maintain the Binding values of the stage's - * BufferInterfaceBlocks[] and to answer the - * GL_UNIFORM_BLOCK_REFERENCED_BY_*_SHADER queries. - */ - int *InterfaceBlockStageIndex[MESA_SHADER_STAGES]; - /** * Map of active uniform names to locations * diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp index 4650a5c9ef1..4ef6a81204e 100644 --- a/src/mesa/main/shader_query.cpp +++ b/src/mesa/main/shader_query.cpp @@ -926,7 +926,7 @@ is_resource_referenced(struct gl_shader_program *shProg, return RESOURCE_ATC(res)->StageReferences[stage]; if (res->Type == GL_UNIFORM_BLOCK || res->Type == GL_SHADER_STORAGE_BLOCK) - return shProg->InterfaceBlockStageIndex[stage][index] != -1; + return shProg->BufferInterfaceBlocks[index].stageref & (1 << stage); return res->StageReferences & (1 << stage); } diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c index 9a4eb6b56fd..8b9166ceecb 100644 --- a/src/mesa/main/shaderobj.c +++ b/src/mesa/main/shaderobj.c @@ -295,10 +295,6 @@ _mesa_clear_shader_program_data(struct gl_shader_program *shProg) ralloc_free(shProg->BufferInterfaceBlocks); shProg->BufferInterfaceBlocks = NULL; shProg->NumBufferInterfaceBlocks = 0; - for (i = 0; i < MESA_SHADER_STAGES; i++) { - ralloc_free(shProg->InterfaceBlockStageIndex[i]); - shProg->InterfaceBlockStageIndex[i] = NULL; - } ralloc_free(shProg->AtomicBuffers); shProg->AtomicBuffers = NULL; From 0fbd073dc284f952ea7df691941a65ddc89b7554 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Sat, 2 Apr 2016 13:54:06 +1100 Subject: [PATCH 24/62] glsl: store ubo or ssbo index in block index Previously we store the buffer block index i.e the index of a combined ubo/ssbo list. Fixes several dEQP-GLES31.functional tests: - program_interface_query.uniform.block_index.block_array - program_interface_query.uniform.block_index.named_block - program_interface_query.uniform.block_index.unnamed_block - program_interface_query.uniform.random.10 - program_interface_query.uniform.random.15 - program_interface_query.uniform.random.22 - program_interface_query.uniform.random.24 - program_interface_query.uniform.random.26 - program_interface_query.uniform.random.28 - program_interface_query.uniform.random.3 - program_interface_query.uniform.random.31 - program_interface_query.uniform.random.38 - program_interface_query.uniform.random.5 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94116 Reviewed-by: Kenneth Graunke --- src/compiler/glsl/link_uniforms.cpp | 41 ++++++++++++++++------------- src/compiler/glsl/linker.cpp | 10 ++++--- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/compiler/glsl/link_uniforms.cpp b/src/compiler/glsl/link_uniforms.cpp index 0a230cad034..43ff52522ee 100644 --- a/src/compiler/glsl/link_uniforms.cpp +++ b/src/compiler/glsl/link_uniforms.cpp @@ -460,30 +460,33 @@ public: field_counter = 0; this->record_next_sampler = new string_to_uint_map; - ubo_block_index = -1; + buffer_block_index = -1; if (var->is_in_buffer_block()) { + struct gl_uniform_block **blks = var->is_in_shader_storage_block() ? + prog->ShaderStorageBlocks : prog->UniformBlocks; + unsigned num_blks = var->is_in_shader_storage_block() ? + prog->NumShaderStorageBlocks : prog->NumUniformBlocks; + if (var->is_interface_instance() && var->type->is_array()) { unsigned l = strlen(var->get_interface_type()->name); - for (unsigned i = 0; i < prog->NumBufferInterfaceBlocks; i++) { - if (strncmp(var->get_interface_type()->name, - prog->BufferInterfaceBlocks[i].Name, - l) == 0 - && prog->BufferInterfaceBlocks[i].Name[l] == '[') { - ubo_block_index = i; + for (unsigned i = 0; i < num_blks; i++) { + if (strncmp(var->get_interface_type()->name, blks[i]->Name, l) + == 0 && blks[i]->Name[l] == '[') { + buffer_block_index = i; break; } } } else { - for (unsigned i = 0; i < prog->NumBufferInterfaceBlocks; i++) { - if (strcmp(var->get_interface_type()->name, - prog->BufferInterfaceBlocks[i].Name) == 0) { - ubo_block_index = i; + for (unsigned i = 0; i < num_blks; i++) { + if (strcmp(var->get_interface_type()->name, blks[i]->Name) == + 0) { + buffer_block_index = i; break; } } } - assert(ubo_block_index != -1); + assert(buffer_block_index != -1); /* Uniform blocks that were specified with an instance name must be * handled a little bit differently. The name of the variable is the @@ -497,7 +500,7 @@ public: var->get_interface_type()->name); } else { const struct gl_uniform_block *const block = - &prog->BufferInterfaceBlocks[ubo_block_index]; + blks[buffer_block_index]; assert(var->data.location != -1); @@ -519,7 +522,7 @@ public: delete this->record_next_sampler; } - int ubo_block_index; + int buffer_block_index; int ubo_byte_offset; gl_shader_stage shader_type; @@ -659,7 +662,7 @@ private: virtual void enter_record(const glsl_type *type, const char *, bool row_major, const unsigned packing) { assert(type->is_record()); - if (this->ubo_block_index == -1) + if (this->buffer_block_index == -1) return; if (packing == GLSL_INTERFACE_PACKING_STD430) this->ubo_byte_offset = glsl_align( @@ -672,7 +675,7 @@ private: virtual void leave_record(const glsl_type *type, const char *, bool row_major, const unsigned packing) { assert(type->is_record()); - if (this->ubo_block_index == -1) + if (this->buffer_block_index == -1) return; if (packing == GLSL_INTERFACE_PACKING_STD430) this->ubo_byte_offset = glsl_align( @@ -719,7 +722,7 @@ private: /* For array of arrays or struct arrays the base location may have * already been set so don't set it again. */ - if (ubo_block_index == -1 && current_var->data.location == -1) { + if (buffer_block_index == -1 && current_var->data.location == -1) { current_var->data.location = id; } @@ -766,8 +769,8 @@ private: this->uniforms[id].is_shader_storage = current_var->is_in_shader_storage_block(); - if (this->ubo_block_index != -1) { - this->uniforms[id].block_index = this->ubo_block_index; + if (this->buffer_block_index != -1) { + this->uniforms[id].block_index = this->buffer_block_index; unsigned alignment = type->std140_base_alignment(row_major); if (packing == GLSL_INTERFACE_PACKING_STD430) diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index f750f5b7722..d9a681ccca1 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -3804,7 +3804,9 @@ calculate_array_size_and_stride(struct gl_shader_program *shProg, int array_stride = -1; char *var_name = get_top_level_name(uni->name); char *interface_name = - get_top_level_name(shProg->BufferInterfaceBlocks[block_index].Name); + get_top_level_name(uni->is_shader_storage ? + shProg->ShaderStorageBlocks[block_index]->Name : + shProg->UniformBlocks[block_index]->Name); if (strcmp(var_name, interface_name) == 0) { /* Deal with instanced array of SSBOs */ @@ -3941,12 +3943,14 @@ build_program_resource_list(struct gl_context *ctx, ir_var_uniform); /* Add stagereferences for uniforms in a uniform block. */ + bool is_shader_storage = shProg->UniformStorage[i].is_shader_storage; int block_index = shProg->UniformStorage[i].block_index; if (block_index != -1) { - stageref |= shProg->BufferInterfaceBlocks[block_index].stageref; + stageref |= is_shader_storage ? + shProg->ShaderStorageBlocks[block_index]->stageref : + shProg->UniformBlocks[block_index]->stageref; } - bool is_shader_storage = shProg->UniformStorage[i].is_shader_storage; GLenum type = is_shader_storage ? GL_BUFFER_VARIABLE : GL_UNIFORM; if (!should_add_buffer_variable(shProg, type, shProg->UniformStorage[i].name)) From 070e5a740545a93a75fa5c79a79b50f472cb8e16 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Sat, 2 Apr 2016 13:59:46 +1100 Subject: [PATCH 25/62] glsl: rename var and simplify if is_ubo_var is true for both UBOs and SSBOs Reviewed-by: Kenneth Graunke --- src/compiler/glsl/link_uniforms.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compiler/glsl/link_uniforms.cpp b/src/compiler/glsl/link_uniforms.cpp index 43ff52522ee..7d8a4b4fb79 100644 --- a/src/compiler/glsl/link_uniforms.cpp +++ b/src/compiler/glsl/link_uniforms.cpp @@ -282,7 +282,7 @@ public: : num_active_uniforms(0), num_hidden_uniforms(0), num_values(0), num_shader_samplers(0), num_shader_images(0), num_shader_uniform_components(0), num_shader_subroutines(0), - is_ubo_var(false), is_shader_storage(false), map(map), + is_buffer_block(false), is_shader_storage(false), map(map), hidden_map(hidden_map) { /* empty */ @@ -299,7 +299,7 @@ public: void process(ir_variable *var) { this->current_var = var; - this->is_ubo_var = var->is_in_buffer_block(); + this->is_buffer_block = var->is_in_buffer_block(); this->is_shader_storage = var->is_in_shader_storage_block(); if (var->is_interface_instance()) program_resource_visitor::process(var->get_interface_type(), @@ -340,7 +340,7 @@ public: */ unsigned num_shader_subroutines; - bool is_ubo_var; + bool is_buffer_block; bool is_shader_storage; struct string_to_uint_map *map; @@ -380,7 +380,7 @@ private: * Note that samplers do not count against this limit because they * don't use any storage on current hardware. */ - if (!is_ubo_var && !is_shader_storage) + if (!is_buffer_block) this->num_shader_uniform_components += values; } From ef10b5427a1ac6e9899116d0e9f0eaa2d87e7957 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 31 Mar 2016 14:17:26 -0600 Subject: [PATCH 26/62] tgsi: add simple tgsi_is_msaa_target() helper Reviewed-by: Jose Fonseca --- src/gallium/auxiliary/tgsi/tgsi_util.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/gallium/auxiliary/tgsi/tgsi_util.h b/src/gallium/auxiliary/tgsi/tgsi_util.h index 3a049ee5667..ca07bfdaf08 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_util.h +++ b/src/gallium/auxiliary/tgsi/tgsi_util.h @@ -88,6 +88,14 @@ tgsi_util_get_shadow_ref_src_index(unsigned tgsi_tex); boolean tgsi_is_shadow_target(unsigned target); + +static inline boolean +tgsi_is_msaa_target(unsigned target) +{ + return (target == TGSI_TEXTURE_2D_MSAA || + target == TGSI_TEXTURE_2D_ARRAY_MSAA); +} + #if defined __cplusplus } #endif From b283c763425983480f85ed5b92ac8a984b6aa942 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 31 Mar 2016 14:19:17 -0600 Subject: [PATCH 27/62] svga: check TXF instruction's target to determine MSAA Rather than the currently bound texture. This goes along with the earlier patch to get away from examining bound textures and sampler views during shader translation. Fixes VMware bug 1632739. Reviewed-by: Jose Fonseca --- src/gallium/drivers/svga/svga_tgsi_vgpu10.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gallium/drivers/svga/svga_tgsi_vgpu10.c b/src/gallium/drivers/svga/svga_tgsi_vgpu10.c index 0d5628251df..f8f615e7651 100644 --- a/src/gallium/drivers/svga/svga_tgsi_vgpu10.c +++ b/src/gallium/drivers/svga/svga_tgsi_vgpu10.c @@ -5439,7 +5439,7 @@ emit_txf(struct svga_shader_emitter_v10 *emit, const struct tgsi_full_instruction *inst) { const uint unit = inst->Src[1].Register.Index; - const unsigned msaa = emit->key.tex[unit].texture_msaa; + const boolean msaa = tgsi_is_msaa_target(inst->Texture.Texture); int offsets[3]; struct tex_swizzle_info swz_info; From 36d8fed798c9c3f008e7bbd5b98d3ad37d47b0bd Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 31 Mar 2016 14:23:34 -0600 Subject: [PATCH 28/62] svga: remove unused svga_compile_key::texture_msaa field Reviewed-by: Jose Fonseca --- src/gallium/drivers/svga/svga_shader.c | 1 - src/gallium/drivers/svga/svga_shader.h | 1 - 2 files changed, 2 deletions(-) diff --git a/src/gallium/drivers/svga/svga_shader.c b/src/gallium/drivers/svga/svga_shader.c index 78eb3f65b61..d56cce49de5 100644 --- a/src/gallium/drivers/svga/svga_shader.c +++ b/src/gallium/drivers/svga/svga_shader.c @@ -195,7 +195,6 @@ svga_init_shader_key_common(const struct svga_context *svga, unsigned shader, } } - key->tex[i].texture_msaa = view->texture->nr_samples > 1; if (!svga->curr.sampler[shader][i]->normalized_coords) { assert(idx < (1 << 5)); /* width_height_idx:5 bitfield */ key->tex[i].width_height_idx = idx++; diff --git a/src/gallium/drivers/svga/svga_shader.h b/src/gallium/drivers/svga/svga_shader.h index 3f915740b1f..b53a4bf514c 100644 --- a/src/gallium/drivers/svga/svga_shader.h +++ b/src/gallium/drivers/svga/svga_shader.h @@ -99,7 +99,6 @@ struct svga_compile_key unsigned unnormalized:1; unsigned width_height_idx:5; /**< texture unit */ unsigned is_array:1; - unsigned texture_msaa:1; /**< A multisample texture? */ unsigned sprite_texgen:1; unsigned swizzle_r:3; unsigned swizzle_g:3; From 0852c5703b57cb277b893e7e9db48c47712a0846 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Sat, 2 Apr 2016 19:55:30 +0200 Subject: [PATCH 29/62] nv50/ir: fix envyas variants when building the code lib nvc0 and nve4 have been respectively replaced by gf100 and gk104. Signed-off-by: Samuel Pitoiset Reviewed-by: Ilia Mirkin --- src/gallium/drivers/nouveau/codegen/lib/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gallium/drivers/nouveau/codegen/lib/Makefile b/src/gallium/drivers/nouveau/codegen/lib/Makefile index 06d1979d8b2..115f6d0c067 100644 --- a/src/gallium/drivers/nouveau/codegen/lib/Makefile +++ b/src/gallium/drivers/nouveau/codegen/lib/Makefile @@ -3,9 +3,9 @@ ENVYAS ?= envyas all: gf100.asm.h gk104.asm.h gk110.asm.h gm107.asm.h gf100.asm.h: %.asm.h: %.asm - $(ENVYAS) -a -W -mnvc0 -Vnvc0 $< -o $@ + $(ENVYAS) -a -W -mgf100 -Vgf100 $< -o $@ gk104.asm.h: %.asm.h: %.asm - $(ENVYAS) -a -W -mnvc0 -Vnve4 $< -o $@ + $(ENVYAS) -a -W -mgf100 -Vgk104 $< -o $@ gk110.asm.h: %.asm.h: %.asm $(ENVYAS) -a -W -mgk110 $< -o $@ gm107.asm.h: %.asm.h: %.asm From 2a529a8ac810b3b40e7a9a071d9544b168928b94 Mon Sep 17 00:00:00 2001 From: Christian Schmidbauer Date: Sun, 13 Mar 2016 22:50:31 +0100 Subject: [PATCH 30/62] st/nine: specify WINAPI only for i386 and amd64 Currently mesa fails building with the x32 abi as ms_abi is not defined in such a case. The patch uses ms_abi only for amd64 targets and stdcall only for i386 targets to be sure that those are defined. This patch additionally checks for __GNUC__ to guarantee that __attribute__ is available. CC: "11.1 11.2" Signed-off-by: Christian Schmidbauer Acked-by: Axel Davy --- include/D3D9/d3d9types.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/include/D3D9/d3d9types.h b/include/D3D9/d3d9types.h index d74ce80bb30..e0b86523daa 100644 --- a/include/D3D9/d3d9types.h +++ b/include/D3D9/d3d9types.h @@ -178,11 +178,17 @@ typedef struct _RGNDATA { #undef WINAPI #endif /* WINAPI*/ -#if defined(__x86_64__) || defined(_M_X64) -#define WINAPI __attribute__((ms_abi)) -#else /* x86_64 */ -#define WINAPI __attribute__((__stdcall__)) -#endif /* x86_64 */ +#ifdef __GNUC__ + #if (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) + #define WINAPI __attribute__((ms_abi)) + #elif defined(__i386) || defined(_M_IX86) + #define WINAPI __attribute__((__stdcall__)) + #else /* neither amd64 nor i386 */ + #define WINAPI + #endif +#else /* __GNUC__ */ + #define WINAPI +#endif /* Implementation caps */ #define D3DPRESENT_BACK_BUFFERS_MAX 3 From 3610b1466d573983d80e3019e8e01ebb97d67d9c Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sat, 2 Apr 2016 17:46:58 -0400 Subject: [PATCH 31/62] nv50/ir: we can't load local memory directly into an output This fixes piglit tests like tests/spec/glsl-1.10/execution/variable-indexing/vs-output-array-float-index-wr.shader_test and related ones. Signed-off-by: Ilia Mirkin Cc: "11.1 11.2" --- src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nv50.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nv50.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nv50.cpp index 02c4f1a4ca8..36ab837f6e2 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nv50.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nv50.cpp @@ -372,7 +372,8 @@ NV50LegalizeSSA::propagateWriteToOutput(Instruction *st) return; for (int s = 0; di->srcExists(s); ++s) - if (di->src(s).getFile() == FILE_IMMEDIATE) + if (di->src(s).getFile() == FILE_IMMEDIATE || + di->src(s).getFile() == FILE_MEMORY_LOCAL) return; if (prog->getType() == Program::TYPE_GEOMETRY) { From d64134ecaec46f95189e355de65f631b1b7f7007 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sat, 2 Apr 2016 19:25:59 -0400 Subject: [PATCH 32/62] gm107/ir: add OP_SELP emission, used in DSQRT lowering The current DSQRT lowering code emits an OP_SELP, so we have to handle its emission. This will eventually go away, but no harm supporting this op. Signed-off-by: Ilia Mirkin --- .../nouveau/codegen/nv50_ir_emit_gm107.cpp | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp index e079a574cc8..31ddb119ccb 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp @@ -126,6 +126,7 @@ private: void emitF2I(); void emitI2F(); void emitI2I(); + void emitSEL(); void emitSHFL(); void emitDADD(); @@ -893,6 +894,32 @@ CodeEmitterGM107::emitI2I() emitGPR (0x00, insn->def(0)); } +void +CodeEmitterGM107::emitSEL() +{ + switch (insn->src(1).getFile()) { + case FILE_GPR: + emitInsn(0x5ca00000); + emitGPR (0x14, insn->src(1)); + break; + case FILE_MEMORY_CONST: + emitInsn(0x4ca00000); + emitCBUF(0x22, -1, 0x14, 16, 2, insn->src(1)); + break; + case FILE_IMMEDIATE: + emitInsn(0x38a00000); + emitIMMD(0x14, 19, insn->src(1)); + break; + default: + assert(!"bad src1 file"); + break; + } + + emitPRED(0x27, insn->src(2)); + emitGPR (0x08, insn->src(0)); + emitGPR (0x00, insn->def(0)); +} + void CodeEmitterGM107::emitSHFL() { @@ -2963,6 +2990,9 @@ CodeEmitterGM107::emitInstruction(Instruction *i) emitISETP(); } break; + case OP_SELP: + emitSEL(); + break; case OP_PRESIN: case OP_PREEX2: emitRRO(); From 6d54096fa6cde0ebc7da29468071fe2c34aec0cf Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Sat, 2 Apr 2016 21:07:50 +1100 Subject: [PATCH 33/62] mesa: remove unrequired else The if always returns so no need for an else. Reviewed-by: Brian Paul --- src/mesa/program/prog_parameter.c | 77 +++++++++++++++---------------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/src/mesa/program/prog_parameter.c b/src/mesa/program/prog_parameter.c index 02d84f20cd8..c294b005b85 100644 --- a/src/mesa/program/prog_parameter.c +++ b/src/mesa/program/prog_parameter.c @@ -248,54 +248,51 @@ _mesa_add_parameter(struct gl_program_parameter_list *paramList, paramList->Size = 0; return -1; } - else { - GLuint i, j; - paramList->NumParameters = oldNum + sz4; + GLuint i, j; - memset(¶mList->Parameters[oldNum], 0, - sz4 * sizeof(struct gl_program_parameter)); + paramList->NumParameters = oldNum + sz4; - for (i = 0; i < sz4; i++) { - struct gl_program_parameter *p = paramList->Parameters + oldNum + i; - p->Name = name ? strdup(name) : NULL; - p->Type = type; - p->Size = size; - p->DataType = datatype; - if (values) { - if (size >= 4) { - COPY_4V(paramList->ParameterValues[oldNum + i], values); + memset(¶mList->Parameters[oldNum], 0, + sz4 * sizeof(struct gl_program_parameter)); + + for (i = 0; i < sz4; i++) { + struct gl_program_parameter *p = paramList->Parameters + oldNum + i; + p->Name = name ? strdup(name) : NULL; + p->Type = type; + p->Size = size; + p->DataType = datatype; + if (values) { + if (size >= 4) { + COPY_4V(paramList->ParameterValues[oldNum + i], values); + } else { + /* copy 1, 2 or 3 values */ + GLuint remaining = size % 4; + assert(remaining < 4); + for (j = 0; j < remaining; j++) { + paramList->ParameterValues[oldNum + i][j].f = values[j].f; } - else { - /* copy 1, 2 or 3 values */ - GLuint remaining = size % 4; - assert(remaining < 4); - for (j = 0; j < remaining; j++) { - paramList->ParameterValues[oldNum + i][j].f = values[j].f; - } - /* fill in remaining positions with zeros */ - for (; j < 4; j++) { - paramList->ParameterValues[oldNum + i][j].f = 0.0f; - } + /* fill in remaining positions with zeros */ + for (; j < 4; j++) { + paramList->ParameterValues[oldNum + i][j].f = 0.0f; } - values += 4; - p->Initialized = GL_TRUE; } - else { - /* silence valgrind */ - for (j = 0; j < 4; j++) - paramList->ParameterValues[oldNum + i][j].f = 0; - } - size -= 4; + values += 4; + p->Initialized = GL_TRUE; + } else { + /* silence valgrind */ + for (j = 0; j < 4; j++) + paramList->ParameterValues[oldNum + i][j].f = 0; } - - if (state) { - for (i = 0; i < STATE_LENGTH; i++) - paramList->Parameters[oldNum].StateIndexes[i] = state[i]; - } - - return (GLint) oldNum; + size -= 4; } + + if (state) { + for (i = 0; i < STATE_LENGTH; i++) + paramList->Parameters[oldNum].StateIndexes[i] = state[i]; + } + + return (GLint) oldNum; } From bcfb86b09de3bfc9c7cdf6925658b5e529a8fc62 Mon Sep 17 00:00:00 2001 From: Jose Fonseca Date: Sat, 2 Apr 2016 14:31:16 +0100 Subject: [PATCH 34/62] gallivm: Use standard LLVMSetAlignment from LLVM 3.4 onwards. Only provide a fallback for LLVM 3.3. One less dependency on LLVM C++ interface. Reviewed-by: Brian Paul Reviewed-by: Roland Scheidegger --- src/gallium/auxiliary/draw/draw_llvm.c | 4 +-- src/gallium/auxiliary/gallivm/lp_bld.h | 14 ++++++++++ .../gallivm/lp_bld_format_aos_array.c | 2 +- src/gallium/auxiliary/gallivm/lp_bld_gather.c | 2 +- src/gallium/auxiliary/gallivm/lp_bld_init.h | 8 ------ src/gallium/auxiliary/gallivm/lp_bld_misc.cpp | 26 ++++++++++++------- .../auxiliary/gallivm/lp_bld_sample_soa.c | 2 +- src/gallium/auxiliary/gallivm/lp_bld_struct.c | 4 +-- src/gallium/drivers/llvmpipe/lp_state_fs.c | 4 +-- 9 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index b48bdcc779e..9c68d4fbf78 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -817,7 +817,7 @@ store_aos(struct gallivm_state *gallivm, #endif /* Unaligned store due to the vertex header */ - lp_set_store_alignment(LLVMBuildStore(builder, value, data_ptr), sizeof(float)); + LLVMSetAlignment(LLVMBuildStore(builder, value, data_ptr), sizeof(float)); } /** @@ -1069,7 +1069,7 @@ store_clip(struct gallivm_state *gallivm, clip_ptr = LLVMBuildPointerCast(builder, clip_ptr, clip_ptr_type, ""); /* Unaligned store */ - lp_set_store_alignment(LLVMBuildStore(builder, aos[j], clip_ptr), sizeof(float)); + LLVMSetAlignment(LLVMBuildStore(builder, aos[j], clip_ptr), sizeof(float)); } } diff --git a/src/gallium/auxiliary/gallivm/lp_bld.h b/src/gallium/auxiliary/gallivm/lp_bld.h index 7ba925c4803..239c27e3c25 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld.h +++ b/src/gallium/auxiliary/gallivm/lp_bld.h @@ -95,4 +95,18 @@ typedef void *LLVMMCJITMemoryManagerRef; #define LLVMInsertBasicBlock ILLEGAL_LLVM_FUNCTION #define LLVMCreateBuilder ILLEGAL_LLVM_FUNCTION + +/* + * Before LLVM 3.4 LLVMSetAlignment only supported GlobalValue, not + * LoadInst/StoreInst as we need. + */ +#if HAVE_LLVM < 0x0304 +# ifdef __cplusplus + extern "C" +# endif + void LLVMSetAlignmentBackport(LLVMValueRef V, unsigned Bytes); +# define LLVMSetAlignment LLVMSetAlignmentBackport +#endif + + #endif /* LP_BLD_H */ diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_aos_array.c b/src/gallium/auxiliary/gallivm/lp_bld_format_aos_array.c index ee3ca86c000..8cad3a6fc65 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_format_aos_array.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_format_aos_array.c @@ -74,7 +74,7 @@ lp_build_fetch_rgba_aos_array(struct gallivm_state *gallivm, ptr = LLVMBuildGEP(builder, base_ptr, &offset, 1, ""); ptr = LLVMBuildPointerCast(builder, ptr, LLVMPointerType(src_vec_type, 0), ""); res = LLVMBuildLoad(builder, ptr, ""); - lp_set_load_alignment(res, src_type.width / 8); + LLVMSetAlignment(res, src_type.width / 8); /* Truncate doubles to float */ if (src_type.floating && src_type.width == 64) { diff --git a/src/gallium/auxiliary/gallivm/lp_bld_gather.c b/src/gallium/auxiliary/gallivm/lp_bld_gather.c index d02602041ce..c641c8bafc1 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_gather.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_gather.c @@ -112,7 +112,7 @@ lp_build_gather_elem(struct gallivm_state *gallivm, * gallium could not do anything else except 16 no matter what... */ if (!aligned) { - lp_set_load_alignment(res, 1); + LLVMSetAlignment(res, 1); } assert(src_width <= dst_width); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_init.h b/src/gallium/auxiliary/gallivm/lp_bld_init.h index ab44661a271..f0155b3a2ef 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_init.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_init.h @@ -77,14 +77,6 @@ func_pointer gallivm_jit_function(struct gallivm_state *gallivm, LLVMValueRef func); -void -lp_set_load_alignment(LLVMValueRef Inst, - unsigned Align); - -void -lp_set_store_alignment(LLVMValueRef Inst, - unsigned Align); - #ifdef __cplusplus } #endif diff --git a/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp b/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp index 30ef37c9d22..61a50fa3b2e 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp +++ b/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp @@ -187,22 +187,28 @@ lp_build_load_volatile(LLVMBuilderRef B, LLVMValueRef PointerVal, } -extern "C" -void -lp_set_load_alignment(LLVMValueRef Inst, - unsigned Align) -{ - llvm::unwrap(Inst)->setAlignment(Align); -} +#if HAVE_LLVM < 0x0304 extern "C" void -lp_set_store_alignment(LLVMValueRef Inst, - unsigned Align) +LLVMSetAlignmentBackport(LLVMValueRef V, + unsigned Bytes) { - llvm::unwrap(Inst)->setAlignment(Align); + switch (LLVMGetInstructionOpcode(V)) { + case LLVMLoad: + llvm::unwrap(V)->setAlignment(Bytes); + break; + case LLVMStore: + llvm::unwrap(V)->setAlignment(Bytes); + break; + default: + assert(0); + break; + } } +#endif + #if HAVE_LLVM < 0x0306 typedef llvm::JITMemoryManager BaseMemoryManager; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c index e21933ffc85..937948bbb02 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c @@ -1939,7 +1939,7 @@ lp_build_clamp_border_color(struct lp_build_sample_context *bld, LLVMPointerType(vec4_bld.vec_type, 0), ""); border_color = LLVMBuildLoad(builder, border_color_ptr, ""); /* we don't have aligned type in the dynamic state unfortunately */ - lp_set_load_alignment(border_color, 4); + LLVMSetAlignment(border_color, 4); /* * Instead of having some incredibly complex logic which will try to figure out diff --git a/src/gallium/auxiliary/gallivm/lp_bld_struct.c b/src/gallium/auxiliary/gallivm/lp_bld_struct.c index cc248d15e97..0df44164d80 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_struct.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_struct.c @@ -157,7 +157,7 @@ lp_build_pointer_get_unaligned(LLVMBuilderRef builder, assert(LLVMGetTypeKind(LLVMTypeOf(ptr)) == LLVMPointerTypeKind); element_ptr = LLVMBuildGEP(builder, ptr, &index, 1, ""); res = LLVMBuildLoad(builder, element_ptr, ""); - lp_set_load_alignment(res, alignment); + LLVMSetAlignment(res, alignment); #ifdef DEBUG lp_build_name(res, "%s[%s]", LLVMGetValueName(ptr), LLVMGetValueName(index)); #endif @@ -188,5 +188,5 @@ lp_build_pointer_set_unaligned(LLVMBuilderRef builder, LLVMValueRef instr; element_ptr = LLVMBuildGEP(builder, ptr, &index, 1, ""); instr = LLVMBuildStore(builder, value, element_ptr); - lp_set_store_alignment(instr, alignment); + LLVMSetAlignment(instr, alignment); } diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index 83ff97659fb..ca0533b4a0f 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -786,7 +786,7 @@ load_unswizzled_block(struct gallivm_state *gallivm, dst[i] = LLVMBuildLoad(builder, dst_ptr, ""); - lp_set_load_alignment(dst[i], dst_alignment); + LLVMSetAlignment(dst[i], dst_alignment); } } @@ -830,7 +830,7 @@ store_unswizzled_block(struct gallivm_state *gallivm, src_ptr = LLVMBuildStore(builder, src[i], src_ptr); - lp_set_store_alignment(src_ptr, src_alignment); + LLVMSetAlignment(src_ptr, src_alignment); } } From 11c4e5b45c246b638b5d98822ff512d1bb09c4fd Mon Sep 17 00:00:00 2001 From: Jose Fonseca Date: Sat, 2 Apr 2016 14:33:33 +0100 Subject: [PATCH 35/62] gallivm: Remove lp_build_load_volatile. No longer needed. Reviewed-by: Brian Paul Reviewed-by: Roland Scheidegger --- src/gallium/auxiliary/gallivm/lp_bld_misc.cpp | 8 -------- src/gallium/auxiliary/gallivm/lp_bld_misc.h | 4 ---- 2 files changed, 12 deletions(-) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp b/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp index 61a50fa3b2e..c1e262bc1ed 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp +++ b/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp @@ -178,14 +178,6 @@ gallivm_dispose_target_library_info(LLVMTargetLibraryInfoRef library_info) *>(library_info); } -extern "C" -LLVMValueRef -lp_build_load_volatile(LLVMBuilderRef B, LLVMValueRef PointerVal, - const char *Name) -{ - return llvm::wrap(llvm::unwrap(B)->CreateLoad(llvm::unwrap(PointerVal), true, Name)); -} - #if HAVE_LLVM < 0x0304 diff --git a/src/gallium/auxiliary/gallivm/lp_bld_misc.h b/src/gallium/auxiliary/gallivm/lp_bld_misc.h index 30b7b1674af..d038e3bee00 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_misc.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_misc.h @@ -55,10 +55,6 @@ extern void lp_set_target_options(void); -extern LLVMValueRef -lp_build_load_volatile(LLVMBuilderRef B, LLVMValueRef PointerVal, - const char *Name); - extern int lp_build_create_jit_compiler_for_module(LLVMExecutionEngineRef *OutJIT, struct lp_generated_code **OutCode, From b284f1f7f9afa560d6f4c0863681a7e36913955c Mon Sep 17 00:00:00 2001 From: Jose Fonseca Date: Sat, 2 Apr 2016 15:13:38 +0100 Subject: [PATCH 36/62] gallivm: Fix performance regressions due to vector selects. LLVM often can't determine the mask elements are all ones/zeros, and there doesn't seem to be a good way to hint that. Thanks to Roland Scheidegger for spotting and analyzing the issue. Reviewed-by: Roland Scheidegger --- src/gallium/auxiliary/gallivm/lp_bld_logic.c | 40 +++++++++----------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_logic.c b/src/gallium/auxiliary/gallivm/lp_bld_logic.c index 5b0b6c6b234..91f316c4565 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_logic.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_logic.c @@ -39,6 +39,7 @@ #include "lp_bld_type.h" #include "lp_bld_const.h" +#include "lp_bld_swizzle.h" #include "lp_bld_init.h" #include "lp_bld_intr.h" #include "lp_bld_debug.h" @@ -314,35 +315,30 @@ lp_build_select(struct lp_build_context *bld, mask = LLVMBuildTrunc(builder, mask, LLVMInt1TypeInContext(lc), ""); res = LLVMBuildSelect(builder, mask, a, b, ""); } - else if (HAVE_LLVM >= 0x0303) { + else if (LLVMIsConstant(mask) || + LLVMGetInstructionOpcode(mask) == LLVMSExt) { /* Generate a vector select. * - * Using vector selects would avoid emitting intrinsics, but they weren't - * properly supported yet for a long time. - * - * LLVM 3.3 appears to reliably support it. - * - * LLVM 3.1 supports it, but it yields buggy code (e.g. lp_blend_test). - * - * LLVM 3.0 includes experimental support provided the -promote-elements - * options is passed to LLVM's command line (e.g., via - * llvm::cl::ParseCommandLineOptions), but resulting code quality is much - * worse, probably because some optimization passes don't know how to - * handle vector selects. - * - * See also: - * - http://lists.cs.uiuc.edu/pipermail/llvmdev/2011-October/043659.html + * Using vector selects should avoid emitting intrinsics hence avoid + * hidering optimization passes, but vector selects weren't properly + * supported yet for a long time, and LLVM will generate poor code when + * the mask is not the result of a comparison. */ /* Convert the mask to a vector of booleans. - * XXX: There are two ways to do this. Decide what's best. + * + * XXX: In x86 the mask is controlled by the MSB, so if we shifted the + * mask by `type.width - 1`, LLVM should realize the mask is ready. Alas + * what really happens is that LLVM will emit two shifts back to back. */ - if (1) { - LLVMTypeRef bool_vec_type = LLVMVectorType(LLVMInt1TypeInContext(lc), type.length); - mask = LLVMBuildTrunc(builder, mask, bool_vec_type, ""); - } else { - mask = LLVMBuildICmp(builder, LLVMIntNE, mask, LLVMConstNull(bld->int_vec_type), ""); + if (0) { + LLVMValueRef shift = LLVMConstInt(bld->int_elem_type, bld->type.width - 1, 0); + shift = lp_build_broadcast(bld->gallivm, bld->int_vec_type, shift); + mask = LLVMBuildLShr(builder, mask, shift, ""); } + LLVMTypeRef bool_vec_type = LLVMVectorType(LLVMInt1TypeInContext(lc), type.length); + mask = LLVMBuildTrunc(builder, mask, bool_vec_type, ""); + res = LLVMBuildSelect(builder, mask, a, b, ""); } else if (((util_cpu_caps.has_sse4_1 && From 522ebe701dd1f05c5058d053bd638df75a7adae0 Mon Sep 17 00:00:00 2001 From: Jose Fonseca Date: Sun, 3 Apr 2016 11:09:35 +0100 Subject: [PATCH 37/62] llvmpipe: Build lp_test_arit on MSVC too. It builds fine now. Probably due to C99 support. Trivial. --- src/gallium/drivers/llvmpipe/SConscript | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/gallium/drivers/llvmpipe/SConscript b/src/gallium/drivers/llvmpipe/SConscript index 11cc3bcc858..8188156afc2 100644 --- a/src/gallium/drivers/llvmpipe/SConscript +++ b/src/gallium/drivers/llvmpipe/SConscript @@ -25,15 +25,13 @@ if not env['embedded']: env.Prepend(LIBS = [llvmpipe, gallium, mesautil]) tests = [ + 'arit', 'format', 'blend', 'conv', 'printf', ] - if not env['msvc']: - tests.append('arit') - for test in tests: testname = 'lp_test_' + test target = env.Program( From 5fa31a4aba5bce5b42ba4188119eafa0f6c3a7f1 Mon Sep 17 00:00:00 2001 From: Jose Fonseca Date: Fri, 1 Apr 2016 11:50:43 +0100 Subject: [PATCH 38/62] llvmpipe: Test abs. Trivial. --- src/gallium/drivers/llvmpipe/lp_test_arit.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gallium/drivers/llvmpipe/lp_test_arit.c b/src/gallium/drivers/llvmpipe/lp_test_arit.c index 290c523f049..a0f2db780bb 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_arit.c +++ b/src/gallium/drivers/llvmpipe/lp_test_arit.c @@ -272,6 +272,7 @@ const float fract_values[] = { static const struct unary_test_t unary_tests[] = { + {"abs", &lp_build_abs, &fabsf, exp2_values, Elements(exp2_values), 20.0 }, {"neg", &lp_build_negate, &negf, exp2_values, Elements(exp2_values), 20.0 }, {"exp2", &lp_build_exp2, &exp2f, exp2_values, Elements(exp2_values), 20.0 }, {"log2", &lp_build_log2_safe, &log2f, log2_values, Elements(log2_values), 20.0 }, From 324451e73fae17c2844f24c7e02000bddc260e78 Mon Sep 17 00:00:00 2001 From: Jose Fonseca Date: Fri, 1 Apr 2016 11:06:30 +0100 Subject: [PATCH 39/62] gallivm: Add debug option to force SSE2. For simulating less capable machines. Reviewed-by: Roland Scheidegger --- src/gallium/auxiliary/gallivm/lp_bld_init.c | 25 ++++++++++++--------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_init.c b/src/gallium/auxiliary/gallivm/lp_bld_init.c index ab55be4c439..6e08ac48d72 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_init.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_init.c @@ -399,6 +399,20 @@ lp_build_init(void) util_cpu_detect(); + /* For simulating less capable machines */ +#ifdef DEBUG + if (debug_get_bool_option("LP_FORCE_SSE2", FALSE)) { + assert(util_cpu_caps.has_sse2); + util_cpu_caps.has_sse3 = 0; + util_cpu_caps.has_ssse3 = 0; + util_cpu_caps.has_sse4_1 = 0; + util_cpu_caps.has_sse4_2 = 0; + util_cpu_caps.has_avx = 0; + util_cpu_caps.has_avx2 = 0; + util_cpu_caps.has_f16c = 0; + } +#endif + /* AMD Bulldozer AVX's throughput is the same as SSE2; and because using * 8-wide vector needs more floating ops than 4-wide (due to padding), it is * actually more efficient to use 4-wide vectors on this processor. @@ -456,17 +470,6 @@ lp_build_init(void) gallivm_initialized = TRUE; -#if 0 - /* For simulating less capable machines */ - util_cpu_caps.has_sse3 = 0; - util_cpu_caps.has_ssse3 = 0; - util_cpu_caps.has_sse4_1 = 0; - util_cpu_caps.has_sse4_2 = 0; - util_cpu_caps.has_avx = 0; - util_cpu_caps.has_avx2 = 0; - util_cpu_caps.has_f16c = 0; -#endif - return TRUE; } From e4f01da15d8c6ce3e8c77ff3ff3d2ce2574a3f7b Mon Sep 17 00:00:00 2001 From: Jose Fonseca Date: Fri, 1 Apr 2016 11:50:28 +0100 Subject: [PATCH 40/62] gallivm: Prefer backend agnostic intrinsic for rounding. We could unconditionally use these instrinsics, but performance with SSE2 would suck, as LLVM falls back to calling libm. lp_test_arit. Reviewed-by: Roland Scheidegger --- src/gallium/auxiliary/gallivm/lp_bld_arit.c | 46 +++++++++++++++++---- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c index 01c6ba96e3f..12777436d7c 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c @@ -1675,13 +1675,13 @@ enum lp_build_round_mode * result is the even value. That is, rounding 2.5 will be 2.0, and not 3.0. */ static inline LLVMValueRef -lp_build_round_sse41(struct lp_build_context *bld, - LLVMValueRef a, - enum lp_build_round_mode mode) +lp_build_nearest_sse41(struct lp_build_context *bld, + LLVMValueRef a) { LLVMBuilderRef builder = bld->gallivm->builder; const struct lp_type type = bld->type; LLVMTypeRef i32t = LLVMInt32TypeInContext(bld->gallivm->context); + LLVMValueRef mode = LLVMConstNull(i32t); const char *intrinsic; LLVMValueRef res; @@ -1714,7 +1714,7 @@ lp_build_round_sse41(struct lp_build_context *bld, args[0] = undef; args[1] = LLVMBuildInsertElement(builder, undef, a, index0, ""); - args[2] = LLVMConstInt(i32t, mode, 0); + args[2] = mode; res = lp_build_intrinsic(builder, intrinsic, vec_type, args, Elements(args), 0); @@ -1754,7 +1754,7 @@ lp_build_round_sse41(struct lp_build_context *bld, res = lp_build_intrinsic_binary(builder, intrinsic, bld->vec_type, a, - LLVMConstInt(i32t, mode, 0)); + mode); } return res; @@ -1856,8 +1856,40 @@ lp_build_round_arch(struct lp_build_context *bld, LLVMValueRef a, enum lp_build_round_mode mode) { - if (util_cpu_caps.has_sse4_1) - return lp_build_round_sse41(bld, a, mode); + if (util_cpu_caps.has_sse4_1) { + LLVMBuilderRef builder = bld->gallivm->builder; + const struct lp_type type = bld->type; + const char *intrinsic_root; + char intrinsic[32]; + + assert(type.floating); + assert(lp_check_value(type, a)); + (void)type; + + switch (mode) { + case LP_BUILD_ROUND_NEAREST: + if (HAVE_LLVM >= 0x0304) { + intrinsic_root = "llvm.round"; + } else { + return lp_build_nearest_sse41(bld, a); + } + break; + case LP_BUILD_ROUND_FLOOR: + intrinsic_root = "llvm.floor"; + break; + case LP_BUILD_ROUND_CEIL: + intrinsic_root = "llvm.ceil"; + break; + case LP_BUILD_ROUND_TRUNCATE: + intrinsic_root = "llvm.trunc"; + break; + } + + util_snprintf(intrinsic, sizeof intrinsic, "%s.v%uf%u", + intrinsic_root, type.length, type.width); + + return lp_build_intrinsic_unary(builder, intrinsic, bld->vec_type, a); + } else /* (util_cpu_caps.has_altivec) */ return lp_build_round_altivec(bld, a, mode); } From a293f57e1357e6affa319cd07199b457c0aead47 Mon Sep 17 00:00:00 2001 From: Jose Fonseca Date: Fri, 1 Apr 2016 11:51:27 +0100 Subject: [PATCH 41/62] gallivm: Use llvm.fabs. Exactly the same code. Reviewed-by: Roland Scheidegger --- src/gallium/auxiliary/gallivm/lp_bld_arit.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c index 12777436d7c..587c83acfa0 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c @@ -1492,14 +1492,9 @@ lp_build_abs(struct lp_build_context *bld, return a; if(type.floating) { - /* Mask out the sign bit */ - LLVMTypeRef int_vec_type = lp_build_int_vec_type(bld->gallivm, type); - unsigned long long absMask = ~(1ULL << (type.width - 1)); - LLVMValueRef mask = lp_build_const_int_vec(bld->gallivm, type, ((unsigned long long) absMask)); - a = LLVMBuildBitCast(builder, a, int_vec_type, ""); - a = LLVMBuildAnd(builder, a, mask, ""); - a = LLVMBuildBitCast(builder, a, vec_type, ""); - return a; + char intrinsic[32]; + util_snprintf(intrinsic, sizeof intrinsic, "llvm.fabs.v%uf%u", type.length, type.width); + return lp_build_intrinsic_unary(builder, intrinsic, vec_type, a); } if(type.width*type.length == 128 && util_cpu_caps.has_ssse3) { From 1708e24f654706565633c4deacf83f7422e5b2a7 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Fri, 19 Feb 2016 13:26:43 -0500 Subject: [PATCH 42/62] mesa: add ES3_1_compatibility extension enable Signed-off-by: Ilia Mirkin Reviewed-by: Dave Airlie --- src/mesa/main/extensions_table.h | 1 + src/mesa/main/mtypes.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/mesa/main/extensions_table.h b/src/mesa/main/extensions_table.h index 7c36b1e1d0b..119039083f6 100644 --- a/src/mesa/main/extensions_table.h +++ b/src/mesa/main/extensions_table.h @@ -27,6 +27,7 @@ EXT(APPLE_texture_max_level , dummy_true EXT(APPLE_vertex_array_object , dummy_true , GLL, x , x , x , 2002) EXT(ARB_ES2_compatibility , ARB_ES2_compatibility , GLL, GLC, x , x , 2009) +EXT(ARB_ES3_1_compatibility , ARB_ES3_1_compatibility , x , GLC, x , x , 2014) EXT(ARB_ES3_compatibility , ARB_ES3_compatibility , GLL, GLC, x , x , 2012) EXT(ARB_arrays_of_arrays , ARB_arrays_of_arrays , GLL, GLC, x , x , 2012) EXT(ARB_base_instance , ARB_base_instance , GLL, GLC, x , x , 2011) diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index e579794de3c..b2060c282f4 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -3774,6 +3774,7 @@ struct gl_extensions GLboolean ANGLE_texture_compression_dxt; GLboolean ARB_ES2_compatibility; GLboolean ARB_ES3_compatibility; + GLboolean ARB_ES3_1_compatibility; GLboolean ARB_arrays_of_arrays; GLboolean ARB_base_instance; GLboolean ARB_blend_func_extended; From 9abbc4971264233a4b4f9ec6ddb88d0dc4c9a25e Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Fri, 19 Feb 2016 14:03:39 -0500 Subject: [PATCH 43/62] glsl: add ARB_ES3_1_compatibility support Oddly a bunch of the features it adds are actually from ESSL 3.20. But the spec is quite clear, oh well. Signed-off-by: Ilia Mirkin Reviewed-by: Dave Airlie --- src/compiler/glsl/builtin_functions.cpp | 2 ++ src/compiler/glsl/builtin_variables.cpp | 16 +++++++++------- src/compiler/glsl/glcpp/glcpp-parse.y | 3 +++ src/compiler/glsl/glsl_parser_extras.cpp | 3 ++- src/compiler/glsl/glsl_parser_extras.h | 2 ++ 5 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/compiler/glsl/builtin_functions.cpp b/src/compiler/glsl/builtin_functions.cpp index 65309fdc09c..1f6fb22924b 100644 --- a/src/compiler/glsl/builtin_functions.cpp +++ b/src/compiler/glsl/builtin_functions.cpp @@ -210,6 +210,7 @@ static bool shader_integer_mix(const _mesa_glsl_parse_state *state) { return state->is_version(450, 310) || + state->ARB_ES3_1_compatibility_enable || (v130(state) && state->EXT_shader_integer_mix_enable); } @@ -478,6 +479,7 @@ static bool shader_image_atomic_exchange_float(const _mesa_glsl_parse_state *state) { return (state->is_version(450, 320) || + state->ARB_ES3_1_compatibility_enable || state->OES_shader_image_atomic_enable); } diff --git a/src/compiler/glsl/builtin_variables.cpp b/src/compiler/glsl/builtin_variables.cpp index 7d77f705356..f31f9f61ef6 100644 --- a/src/compiler/glsl/builtin_variables.cpp +++ b/src/compiler/glsl/builtin_variables.cpp @@ -845,11 +845,6 @@ builtin_variable_generator::generate_constants() state->Const.MaxImageSamples); } - if (state->is_version(450, 310)) { - add_const("gl_MaxCombinedShaderOutputResources", - state->Const.MaxCombinedShaderOutputResources); - } - if (state->is_version(400, 0) || state->ARB_tessellation_shader_enable) { add_const("gl_MaxTessControlImageUniforms", @@ -859,6 +854,12 @@ builtin_variable_generator::generate_constants() } } + if (state->is_version(450, 310) || + state->ARB_ES3_1_compatibility_enable) { + add_const("gl_MaxCombinedShaderOutputResources", + state->Const.MaxCombinedShaderOutputResources); + } + if (state->is_version(410, 0) || state->ARB_viewport_array_enable) add_const("gl_MaxViewports", state->Const.MaxViewports); @@ -880,7 +881,8 @@ builtin_variable_generator::generate_constants() } if (state->is_version(450, 320) || - state->OES_sample_variables_enable) + state->OES_sample_variables_enable || + state->ARB_ES3_1_compatibility_enable) add_const("gl_MaxSamples", state->Const.MaxSamples); } @@ -1174,7 +1176,7 @@ builtin_variable_generator::generate_fs_special_vars() var->data.interpolation = INTERP_QUALIFIER_FLAT; } - if (state->is_version(450, 310)/* || state->ARB_ES3_1_compatibility_enable*/) + if (state->is_version(450, 310) || state->ARB_ES3_1_compatibility_enable) add_system_value(SYSTEM_VALUE_HELPER_INVOCATION, bool_t, "gl_HelperInvocation"); } diff --git a/src/compiler/glsl/glcpp/glcpp-parse.y b/src/compiler/glsl/glcpp/glcpp-parse.y index e1e46af27b1..a48266cf1b2 100644 --- a/src/compiler/glsl/glcpp/glcpp-parse.y +++ b/src/compiler/glsl/glcpp/glcpp-parse.y @@ -2340,6 +2340,9 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio if (extensions->EXT_texture_array) add_builtin_define(parser, "GL_EXT_texture_array", 1); + if (extensions->ARB_ES3_1_compatibility) + add_builtin_define(parser, "GL_ARB_ES3_1_compatibility", 1); + if (extensions->ARB_arrays_of_arrays) add_builtin_define(parser, "GL_ARB_arrays_of_arrays", 1); diff --git a/src/compiler/glsl/glsl_parser_extras.cpp b/src/compiler/glsl/glsl_parser_extras.cpp index 3dc68741902..76321aac921 100644 --- a/src/compiler/glsl/glsl_parser_extras.cpp +++ b/src/compiler/glsl/glsl_parser_extras.cpp @@ -226,7 +226,7 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->supported_versions[this->num_supported_versions].es = true; this->num_supported_versions++; } - if (_mesa_is_gles31(ctx)) { + if (_mesa_is_gles31(ctx) || ctx->Extensions.ARB_ES3_1_compatibility) { this->supported_versions[this->num_supported_versions].ver = 310; this->supported_versions[this->num_supported_versions].es = true; this->num_supported_versions++; @@ -565,6 +565,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { /* ARB extensions go here, sorted alphabetically. */ + EXT(ARB_ES3_1_compatibility, true, false, ARB_ES3_1_compatibility), EXT(ARB_arrays_of_arrays, true, false, ARB_arrays_of_arrays), EXT(ARB_compute_shader, true, false, ARB_compute_shader), EXT(ARB_conservative_depth, true, false, ARB_conservative_depth), diff --git a/src/compiler/glsl/glsl_parser_extras.h b/src/compiler/glsl/glsl_parser_extras.h index 0cc2d259f3a..c774fbea05a 100644 --- a/src/compiler/glsl/glsl_parser_extras.h +++ b/src/compiler/glsl/glsl_parser_extras.h @@ -510,6 +510,8 @@ struct _mesa_glsl_parse_state { /*@{*/ /* ARB extensions go here, sorted alphabetically. */ + bool ARB_ES3_1_compatibility_enable; + bool ARB_ES3_1_compatibility_warn; bool ARB_arrays_of_arrays_enable; bool ARB_arrays_of_arrays_warn; bool ARB_compute_shader_enable; From d50ffb5e464e18894eaf8cb779df3a74f5836ef9 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Fri, 8 Jan 2016 15:48:44 -0500 Subject: [PATCH 44/62] mesa: add always-false-for-now enables for GL 4.3, 4.4, 4.5. As the relevant extensions get implemented, the lines should be uncommented. I believe this is (almost) everything needed for those GL versions though. Signed-off-by: Ilia Mirkin Reviewed-by: Dave Airlie --- src/mesa/main/version.c | 49 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/mesa/main/version.c b/src/mesa/main/version.c index 112a73dc0e7..2af3653f7bb 100644 --- a/src/mesa/main/version.c +++ b/src/mesa/main/version.c @@ -351,8 +351,55 @@ compute_version(const struct gl_extensions *extensions, extensions->ARB_shading_language_packing && extensions->ARB_texture_compression_bptc && extensions->ARB_transform_feedback_instanced); + const bool ver_4_3 = (ver_4_2 && + consts->GLSLVersion >= 430 && + extensions->ARB_ES3_compatibility && + extensions->ARB_arrays_of_arrays && + extensions->ARB_compute_shader && + extensions->ARB_copy_image && + extensions->ARB_explicit_uniform_location && + extensions->ARB_fragment_layer_viewport && + extensions->ARB_framebuffer_no_attachments && + extensions->ARB_internalformat_query2 && + /* extensions->ARB_robust_buffer_access_behavior */ 0 && + extensions->ARB_shader_image_size && + extensions->ARB_shader_storage_buffer_object && + extensions->ARB_stencil_texturing && + extensions->ARB_texture_buffer_range && + extensions->ARB_texture_query_levels && + extensions->ARB_texture_view); + const bool ver_4_4 = (ver_4_3 && + consts->GLSLVersion >= 440 && + extensions->ARB_buffer_storage && + extensions->ARB_clear_texture && + extensions->ARB_enhanced_layouts && + extensions->ARB_query_buffer_object && + extensions->ARB_texture_mirror_clamp_to_edge && + extensions->ARB_texture_stencil8 && + extensions->ARB_vertex_type_10f_11f_11f_rev); + const bool ver_4_5 = (ver_4_4 && + consts->GLSLVersion >= 450 && + extensions->ARB_ES3_1_compatibility && + extensions->ARB_clip_control && + extensions->ARB_conditional_render_inverted && + /* extensions->ARB_cull_distance */ 0 && + extensions->ARB_derivative_control && + extensions->ARB_shader_texture_image_samples && + extensions->NV_texture_barrier); - if (ver_4_2) { + if (ver_4_5) { + major = 4; + minor = 5; + } + else if (ver_4_4) { + major = 4; + minor = 4; + } + else if (ver_4_3) { + major = 4; + minor = 3; + } + else if (ver_4_2) { major = 4; minor = 2; } From 87906cbc37cb99089caa0be4346ebfbe2b7e2d3e Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sat, 2 Apr 2016 21:08:25 -0400 Subject: [PATCH 45/62] glsl: allow conservative depth qualifiers in GLSL 420 Signed-off-by: Ilia Mirkin Reviewed-by: Dave Airlie --- src/compiler/glsl/ast_to_hir.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/compiler/glsl/ast_to_hir.cpp b/src/compiler/glsl/ast_to_hir.cpp index 3fe90079420..7c9be8171b6 100644 --- a/src/compiler/glsl/ast_to_hir.cpp +++ b/src/compiler/glsl/ast_to_hir.cpp @@ -3326,6 +3326,7 @@ apply_layout_qualifier_to_variable(const struct ast_type_qualifier *qual, + qual->flags.q.depth_less + qual->flags.q.depth_unchanged; if (depth_layout_count > 0 + && !state->is_version(420, 0) && !state->AMD_conservative_depth_enable && !state->ARB_conservative_depth_enable) { _mesa_glsl_error(loc, state, @@ -3708,7 +3709,8 @@ get_variable_being_redeclared(ir_variable *var, YYLTYPE loc, earlier->data.interpolation = var->data.interpolation; /* Layout qualifiers for gl_FragDepth. */ - } else if ((state->AMD_conservative_depth_enable || + } else if ((state->is_version(420, 0) || + state->AMD_conservative_depth_enable || state->ARB_conservative_depth_enable) && strcmp(var->name, "gl_FragDepth") == 0 && earlier->type == var->type From aebb0e0186b6ed086c204c3c2989ae84b0cc1bf5 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sat, 2 Apr 2016 21:50:22 -0400 Subject: [PATCH 46/62] glsl: make ssbo predicate return true when in a GLSL 430 or ESSL 310 shader I can't tell whether this actually matters, but we're creating function signatures with this predicate, so it should probably match when SSBO's are available. Signed-off-by: Ilia Mirkin Reviewed-by: Dave Airlie --- src/compiler/glsl/lower_ubo_reference.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/glsl/lower_ubo_reference.cpp b/src/compiler/glsl/lower_ubo_reference.cpp index d6269f7cbac..3155ab6225e 100644 --- a/src/compiler/glsl/lower_ubo_reference.cpp +++ b/src/compiler/glsl/lower_ubo_reference.cpp @@ -372,7 +372,8 @@ lower_ubo_reference_visitor::ubo_load(void *mem_ctx, static bool shader_storage_buffer_object(const _mesa_glsl_parse_state *state) { - return state->ARB_shader_storage_buffer_object_enable; + return state->ARB_shader_storage_buffer_object_enable || + state->is_version(430, 310); } uint32_t From 7af12a8dc6c96b8b0da802b3b25fbd6a197b2d62 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sat, 2 Apr 2016 22:56:49 -0400 Subject: [PATCH 47/62] glsl: make *sampler2DMSArray available in ESSL 3.20 Also avoid double-adding the *sampler2DMS types when the array ext is enabled. Signed-off-by: Ilia Mirkin Reviewed-by: Dave Airlie --- src/compiler/glsl/builtin_types.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/compiler/glsl/builtin_types.cpp b/src/compiler/glsl/builtin_types.cpp index d250234f652..5f208f8e9d6 100644 --- a/src/compiler/glsl/builtin_types.cpp +++ b/src/compiler/glsl/builtin_types.cpp @@ -181,7 +181,7 @@ static const struct builtin_type_versions { T(sampler2DRect, 140, 999) T(samplerBuffer, 140, 320) T(sampler2DMS, 150, 310) - T(sampler2DMSArray, 150, 999) + T(sampler2DMSArray, 150, 320) T(isampler1D, 130, 999) T(isampler2D, 130, 300) @@ -193,7 +193,7 @@ static const struct builtin_type_versions { T(isampler2DRect, 140, 999) T(isamplerBuffer, 140, 320) T(isampler2DMS, 150, 310) - T(isampler2DMSArray, 150, 999) + T(isampler2DMSArray, 150, 320) T(usampler1D, 130, 999) T(usampler2D, 130, 300) @@ -205,7 +205,7 @@ static const struct builtin_type_versions { T(usampler2DRect, 140, 999) T(usamplerBuffer, 140, 320) T(usampler2DMS, 150, 310) - T(usampler2DMSArray, 150, 999) + T(usampler2DMSArray, 150, 320) T(sampler1DShadow, 110, 999) T(sampler2DShadow, 110, 300) @@ -305,11 +305,13 @@ _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state) add_type(symbols, glsl_type::usamplerCubeArray_type); } - if (state->ARB_texture_multisample_enable || - state->OES_texture_storage_multisample_2d_array_enable) { + if (state->ARB_texture_multisample_enable) { add_type(symbols, glsl_type::sampler2DMS_type); add_type(symbols, glsl_type::isampler2DMS_type); add_type(symbols, glsl_type::usampler2DMS_type); + } + if (state->ARB_texture_multisample_enable || + state->OES_texture_storage_multisample_2d_array_enable) { add_type(symbols, glsl_type::sampler2DMSArray_type); add_type(symbols, glsl_type::isampler2DMSArray_type); add_type(symbols, glsl_type::usampler2DMSArray_type); From 7ad49daca61a638f5029fedacd98357943c67ea8 Mon Sep 17 00:00:00 2001 From: Jose Fonseca Date: Sun, 3 Apr 2016 22:52:53 +0100 Subject: [PATCH 48/62] gallivm: Introduce lp_format_intrinsic. For adding .v4f32 like suffixes to intrinsics, taking special care for scalar case, which was being often neglected. This fixes invalid IR when doing mipmap filtering on SSE2 (the only case where we'd use intrinsics with scalars.) Reviewed-by: Roland Scheidegger --- src/gallium/auxiliary/gallivm/lp_bld_arit.c | 19 +++------ src/gallium/auxiliary/gallivm/lp_bld_intr.c | 43 +++++++++++++++++++++ src/gallium/auxiliary/gallivm/lp_bld_intr.h | 6 +++ 3 files changed, 54 insertions(+), 14 deletions(-) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c index 587c83acfa0..0c43617d531 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c @@ -1493,7 +1493,7 @@ lp_build_abs(struct lp_build_context *bld, if(type.floating) { char intrinsic[32]; - util_snprintf(intrinsic, sizeof intrinsic, "llvm.fabs.v%uf%u", type.length, type.width); + lp_format_intrinsic(intrinsic, sizeof intrinsic, "llvm.fabs", vec_type); return lp_build_intrinsic_unary(builder, intrinsic, vec_type, a); } @@ -1880,9 +1880,7 @@ lp_build_round_arch(struct lp_build_context *bld, break; } - util_snprintf(intrinsic, sizeof intrinsic, "%s.v%uf%u", - intrinsic_root, type.length, type.width); - + lp_format_intrinsic(intrinsic, sizeof intrinsic, intrinsic_root, bld->vec_type); return lp_build_intrinsic_unary(builder, intrinsic, bld->vec_type, a); } else /* (util_cpu_caps.has_altivec) */ @@ -2026,7 +2024,7 @@ lp_build_floor(struct lp_build_context *bld, if (type.width != 32) { char intrinsic[32]; - util_snprintf(intrinsic, sizeof intrinsic, "llvm.floor.v%uf%u", type.length, type.width); + lp_format_intrinsic(intrinsic, sizeof intrinsic, "llvm.floor", vec_type); return lp_build_intrinsic_unary(builder, intrinsic, vec_type, a); } @@ -2101,7 +2099,7 @@ lp_build_ceil(struct lp_build_context *bld, if (type.width != 32) { char intrinsic[32]; - util_snprintf(intrinsic, sizeof intrinsic, "llvm.ceil.v%uf%u", type.length, type.width); + lp_format_intrinsic(intrinsic, sizeof intrinsic, "llvm.ceil", vec_type); return lp_build_intrinsic_unary(builder, intrinsic, vec_type, a); } @@ -2438,15 +2436,8 @@ lp_build_sqrt(struct lp_build_context *bld, assert(lp_check_value(type, a)); - /* TODO: optimize the constant case */ - assert(type.floating); - if (type.length == 1) { - util_snprintf(intrinsic, sizeof intrinsic, "llvm.sqrt.f%u", type.width); - } - else { - util_snprintf(intrinsic, sizeof intrinsic, "llvm.sqrt.v%uf%u", type.length, type.width); - } + lp_format_intrinsic(intrinsic, sizeof intrinsic, "llvm.sqrt", vec_type); return lp_build_intrinsic_unary(builder, intrinsic, vec_type, a); } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_intr.c b/src/gallium/auxiliary/gallivm/lp_bld_intr.c index 30f4863ec44..e153389e6a9 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_intr.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_intr.c @@ -45,6 +45,7 @@ #include "util/u_debug.h" +#include "util/u_string.h" #include "lp_bld_const.h" #include "lp_bld_intr.h" @@ -52,6 +53,48 @@ #include "lp_bld_pack.h" +void +lp_format_intrinsic(char *name, + size_t size, + const char *name_root, + LLVMTypeRef type) +{ + unsigned length = 0; + unsigned width; + char c; + + LLVMTypeKind kind = LLVMGetTypeKind(type); + if (kind == LLVMVectorTypeKind) { + length = LLVMGetVectorSize(type); + type = LLVMGetElementType(type); + kind = LLVMGetTypeKind(type); + } + + switch (kind) { + case LLVMIntegerTypeKind: + c = 'i'; + width = LLVMGetIntTypeWidth(type); + break; + case LLVMFloatTypeKind: + c = 'f'; + width = 32; + break; + case LLVMDoubleTypeKind: + c = 'f'; + width = 64; + break; + default: + assert(0); + } + + if (length) { + util_snprintf(name, size, "%s.v%u%c%u", name_root, length, c, width); + } else { + util_snprintf(name, size, "%s.%c%u", name_root, c, width); + } +} + + LLVMValueRef lp_declare_intrinsic(LLVMModuleRef module, const char *name, diff --git a/src/gallium/auxiliary/gallivm/lp_bld_intr.h b/src/gallium/auxiliary/gallivm/lp_bld_intr.h index a54b367961a..7d80ac28f70 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_intr.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_intr.h @@ -47,6 +47,12 @@ #define LP_MAX_FUNC_ARGS 32 +void +lp_format_intrinsic(char *name, + size_t size, + const char *name_root, + LLVMTypeRef type); + LLVMValueRef lp_declare_intrinsic(LLVMModuleRef module, const char *name, From 40628886ca892f4b43f37335d3efbad55fb3c8bd Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Sun, 3 Apr 2016 01:25:03 -0700 Subject: [PATCH 49/62] glsl: Print "precise" on ir_variable nodes. Signed-off-by: Kenneth Graunke Reviewed-by: Eduardo Lima Mitev --- src/compiler/glsl/ir_print_visitor.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/compiler/glsl/ir_print_visitor.cpp b/src/compiler/glsl/ir_print_visitor.cpp index 960b23fe0ed..e06acce782a 100644 --- a/src/compiler/glsl/ir_print_visitor.cpp +++ b/src/compiler/glsl/ir_print_visitor.cpp @@ -173,6 +173,7 @@ void ir_print_visitor::visit(ir_variable *ir) const char *const samp = (ir->data.sample) ? "sample " : ""; const char *const patc = (ir->data.patch) ? "patch " : ""; const char *const inv = (ir->data.invariant) ? "invariant " : ""; + const char *const prec = (ir->data.precise) ? "precise " : ""; const char *const mode[] = { "", "uniform ", "shader_storage ", "shader_shared ", "shader_in ", "shader_out ", "in ", "out ", "inout ", @@ -182,8 +183,8 @@ void ir_print_visitor::visit(ir_variable *ir) const char *const interp[] = { "", "smooth", "flat", "noperspective" }; STATIC_ASSERT(ARRAY_SIZE(interp) == INTERP_QUALIFIER_COUNT); - fprintf(f, "(%s%s%s%s%s%s%s%s) ", - loc, cent, samp, patc, inv, mode[ir->data.mode], + fprintf(f, "(%s%s%s%s%s%s%s%s%s) ", + loc, cent, samp, patc, inv, prec, mode[ir->data.mode], stream[ir->data.stream], interp[ir->data.interpolation]); From 807e2c27ac03718df8f53c2f28686dfed4c12677 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sun, 3 Apr 2016 02:28:53 -0400 Subject: [PATCH 50/62] mesa: expose EXT_polygon_offset_clamp in ES contexts The extension spec was extended to also support ES. This functionality is provided all the way back to ES 1.0. Signed-off-by: Ilia Mirkin Reviewed-by: Dave Airlie --- src/mapi/glapi/gen/gl_API.xml | 2 +- src/mesa/main/extensions_table.h | 2 +- src/mesa/main/get_hash_params.py | 6 +++--- src/mesa/main/tests/dispatch_sanity.cpp | 6 ++++++ 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml index 8b49f915169..cdd680c70ee 100644 --- a/src/mapi/glapi/gen/gl_API.xml +++ b/src/mapi/glapi/gen/gl_API.xml @@ -12741,7 +12741,7 @@ - + diff --git a/src/mesa/main/extensions_table.h b/src/mesa/main/extensions_table.h index 119039083f6..a31a9a1dc51 100644 --- a/src/mesa/main/extensions_table.h +++ b/src/mesa/main/extensions_table.h @@ -214,7 +214,7 @@ EXT(EXT_packed_pixels , dummy_true EXT(EXT_pixel_buffer_object , EXT_pixel_buffer_object , GLL, GLC, x , x , 2004) EXT(EXT_point_parameters , EXT_point_parameters , GLL, x , x , x , 1997) EXT(EXT_polygon_offset , dummy_true , GLL, x , x , x , 1995) -EXT(EXT_polygon_offset_clamp , EXT_polygon_offset_clamp , GLL, GLC, x , x , 2014) +EXT(EXT_polygon_offset_clamp , EXT_polygon_offset_clamp , GLL, GLC, ES1, ES2, 2014) EXT(EXT_provoking_vertex , EXT_provoking_vertex , GLL, GLC, x , x , 2009) EXT(EXT_read_format_bgra , dummy_true , x , x , ES1, ES2, 2009) EXT(EXT_rescale_normal , dummy_true , GLL, x , x , x , 1997) diff --git a/src/mesa/main/get_hash_params.py b/src/mesa/main/get_hash_params.py index a0cc4f8e842..59d6557eb4a 100644 --- a/src/mesa/main/get_hash_params.py +++ b/src/mesa/main/get_hash_params.py @@ -135,6 +135,9 @@ descriptor=[ [ "MAX_LABEL_LENGTH", "CONST(MAX_LABEL_LENGTH), NO_EXTRA" ], [ "MAX_DEBUG_GROUP_STACK_DEPTH", "CONST(MAX_DEBUG_GROUP_STACK_DEPTH), NO_EXTRA" ], [ "DEBUG_GROUP_STACK_DEPTH", "LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA" ], + +# GL_EXT_polygon_offset_clamp + [ "POLYGON_OFFSET_CLAMP_EXT", "CONTEXT_FLOAT(Polygon.OffsetClamp), extra_EXT_polygon_offset_clamp" ], ]}, # Enums in OpenGL and GLES1 @@ -857,9 +860,6 @@ descriptor=[ # GL_ARB_shader_image_load_store [ "MAX_IMAGE_SAMPLES", "CONTEXT_INT(Const.MaxImageSamples), extra_ARB_shader_image_load_store" ], -# GL_EXT_polygon_offset_clamp - [ "POLYGON_OFFSET_CLAMP_EXT", "CONTEXT_FLOAT(Polygon.OffsetClamp), extra_EXT_polygon_offset_clamp" ], - # GL_ARB_shader_storage_buffer_object [ "MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_CTRL].MaxShaderStorageBlocks), extra_ARB_shader_storage_buffer_object" ], [ "MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS", "CONTEXT_INT(Const.Program[MESA_SHADER_TESS_EVAL].MaxShaderStorageBlocks), extra_ARB_shader_storage_buffer_object" ], diff --git a/src/mesa/main/tests/dispatch_sanity.cpp b/src/mesa/main/tests/dispatch_sanity.cpp index 9f278be47ca..c6599fd5cea 100644 --- a/src/mesa/main/tests/dispatch_sanity.cpp +++ b/src/mesa/main/tests/dispatch_sanity.cpp @@ -2064,6 +2064,9 @@ const struct function gles11_functions_possible[] = { { "glObjectLabelKHR", 11, -1 }, { "glObjectPtrLabelKHR", 11, -1 }, + /* GL_EXT_polygon_offset_clamp */ + { "glPolygonOffsetClampEXT", 11, -1 }, + { NULL, 0, -1 } }; @@ -2300,6 +2303,9 @@ const struct function gles2_functions_possible[] = { { "glObjectLabelKHR", 20, -1 }, { "glObjectPtrLabelKHR", 20, -1 }, + /* GL_EXT_polygon_offset_clamp */ + { "glPolygonOffsetClampEXT", 11, -1 }, + { NULL, 0, -1 } }; From d76e1cd2dd24d0807a8db78fb6f7ebfeb50f22b4 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sun, 3 Apr 2016 02:44:50 -0400 Subject: [PATCH 51/62] mesa: expose EXT_base_instance in ES3 contexts This extension is identical to ARB_base_instance. Reuse the same entrypoints. Signed-off-by: Ilia Mirkin Reviewed-by: Dave Airlie --- src/mapi/glapi/gen/es_EXT.xml | 34 +++++++++++++++++++++++++ src/mesa/main/extensions_table.h | 1 + src/mesa/main/tests/dispatch_sanity.cpp | 5 ++++ src/mesa/vbo/vbo_exec_array.c | 2 +- 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/mapi/glapi/gen/es_EXT.xml b/src/mapi/glapi/gen/es_EXT.xml index 3b2c15ebf5c..bf67eae40d4 100644 --- a/src/mapi/glapi/gen/es_EXT.xml +++ b/src/mapi/glapi/gen/es_EXT.xml @@ -924,6 +924,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Date: Sun, 3 Apr 2016 21:17:46 -0400 Subject: [PATCH 52/62] docs: add note about GL_EXT_base_instance, sort entries Trivial. Signed-off-by: Ilia Mirkin --- docs/relnotes/11.3.0.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/relnotes/11.3.0.html b/docs/relnotes/11.3.0.html index 8aa9444c54c..6f8fcfbde29 100644 --- a/docs/relnotes/11.3.0.html +++ b/docs/relnotes/11.3.0.html @@ -49,9 +49,10 @@ Note: some of the new features are only available with certain drivers.
  • GL_ARB_shader_image_load_store on radeonsi, softpipe
  • GL_ARB_shader_image_size on radeonsi
  • GL_ATI_fragment_shader on all Gallium drivers
  • +
  • GL_EXT_base_instance on all drivers that support GL_ARB_base_instance
  • GL_OES_draw_buffers_indexed and GL_EXT_draw_buffers_indexed on all drivers that support GL_ARB_draw_buffers_blend
  • -
  • GL_OES_texture_border_clamp and GL_EXT_texture_border_clamp on all drivers that support GL_ARB_texture_border_clamp
  • GL_OES_shader_image_atomic on all drivers that support GL_ARB_shader_image_load_store
  • +
  • GL_OES_texture_border_clamp and GL_EXT_texture_border_clamp on all drivers that support GL_ARB_texture_border_clamp
  • Bug fixes

    From 4bc3b1ca487df6072aec13dbfbf724c0de9995c5 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sun, 3 Apr 2016 14:13:33 -0400 Subject: [PATCH 53/62] nvc0: add hardware ETC2 and ASTC support on GK20A and GM107+ Signed-off-by: Ilia Mirkin --- .../drivers/nouveau/nv50/nv50_formats.c | 46 +++++++++++++++++++ .../drivers/nouveau/nvc0/nvc0_screen.c | 13 ++++++ src/gallium/drivers/nouveau/nvc0/nvc0_tex.c | 7 ++- 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/gallium/drivers/nouveau/nv50/nv50_formats.c b/src/gallium/drivers/nouveau/nv50/nv50_formats.c index 717067cf2f7..5b965672357 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_formats.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_formats.c @@ -23,6 +23,7 @@ #if NOUVEAU_DRIVER == 0xc0 # include "nvc0/nvc0_screen.h" # include "nvc0/nvc0_3d.xml.h" +# include "nvc0/gm107_texture.xml.h" #else # include "nv50/nv50_screen.h" # include "nv50/nv50_3d.xml.h" @@ -65,6 +66,7 @@ #define SF_A(sz) G80_TIC_0_COMPONENTS_SIZES_##sz #define SF_B(sz) G200_TIC_0_COMPONENTS_SIZES_##sz #define SF_C(sz) GF100_TIC_0_COMPONENTS_SIZES_##sz +#define SF_D(sz) GM107_TIC2_0_COMPONENTS_SIZES_##sz #define SF(c, pf, sf, r, g, b, a, t0, t1, t2, t3, sz, u) \ [PIPE_FORMAT_##pf] = { \ sf, { \ @@ -236,6 +238,50 @@ const struct nv50_format nv50_format_table[PIPE_FORMAT_COUNT] = F3(C, BPTC_RGB_FLOAT, NONE, R, G, B, xx, FLOAT, BC6H_SF16, t), F3(C, BPTC_RGB_UFLOAT, NONE, R, G, B, xx, FLOAT, BC6H_UF16, t), +#if NOUVEAU_DRIVER == 0xc0 + F3(D, ETC1_RGB8, NONE, R, G, B, xx, UNORM, ETC2_RGB, t), + F3(D, ETC2_RGB8, NONE, R, G, B, xx, UNORM, ETC2_RGB, t), + F3(D, ETC2_SRGB8, NONE, R, G, B, xx, UNORM, ETC2_RGB, t), + C4(D, ETC2_RGB8A1, NONE, R, G, B, A, UNORM, ETC2_RGB_PTA, t), + C4(D, ETC2_SRGB8A1, NONE, R, G, B, A, UNORM, ETC2_RGB_PTA, t), + C4(D, ETC2_RGBA8, NONE, R, G, B, A, UNORM, ETC2_RGBA, t), + C4(D, ETC2_SRGBA8, NONE, R, G, B, A, UNORM, ETC2_RGBA, t), + F1(D, ETC2_R11_UNORM, NONE, R, xx, xx, xx, UNORM, EAC, t), + F1(D, ETC2_R11_SNORM, NONE, R, xx, xx, xx, SNORM, EAC, t), + F2(D, ETC2_RG11_UNORM, NONE, R, G, xx, xx, UNORM, EACX2, t), + F2(D, ETC2_RG11_SNORM, NONE, R, G, xx, xx, SNORM, EACX2, t), + + C4(D, ASTC_4x4, NONE, R, G, B, A, UNORM, ASTC_2D_4X4, t), + C4(D, ASTC_5x4, NONE, R, G, B, A, UNORM, ASTC_2D_5X4, t), + C4(D, ASTC_5x5, NONE, R, G, B, A, UNORM, ASTC_2D_5X5, t), + C4(D, ASTC_6x5, NONE, R, G, B, A, UNORM, ASTC_2D_6X5, t), + C4(D, ASTC_6x6, NONE, R, G, B, A, UNORM, ASTC_2D_6X6, t), + C4(D, ASTC_8x5, NONE, R, G, B, A, UNORM, ASTC_2D_8X5, t), + C4(D, ASTC_8x6, NONE, R, G, B, A, UNORM, ASTC_2D_8X6, t), + C4(D, ASTC_8x8, NONE, R, G, B, A, UNORM, ASTC_2D_8X8, t), + C4(D, ASTC_10x5, NONE, R, G, B, A, UNORM, ASTC_2D_10X5, t), + C4(D, ASTC_10x6, NONE, R, G, B, A, UNORM, ASTC_2D_10X6, t), + C4(D, ASTC_10x8, NONE, R, G, B, A, UNORM, ASTC_2D_10X8, t), + C4(D, ASTC_10x10, NONE, R, G, B, A, UNORM, ASTC_2D_10X10, t), + C4(D, ASTC_12x10, NONE, R, G, B, A, UNORM, ASTC_2D_12X10, t), + C4(D, ASTC_12x12, NONE, R, G, B, A, UNORM, ASTC_2D_12X12, t), + + C4(D, ASTC_4x4_SRGB, NONE, R, G, B, A, UNORM, ASTC_2D_4X4, t), + C4(D, ASTC_5x4_SRGB, NONE, R, G, B, A, UNORM, ASTC_2D_5X4, t), + C4(D, ASTC_5x5_SRGB, NONE, R, G, B, A, UNORM, ASTC_2D_5X5, t), + C4(D, ASTC_6x5_SRGB, NONE, R, G, B, A, UNORM, ASTC_2D_6X5, t), + C4(D, ASTC_6x6_SRGB, NONE, R, G, B, A, UNORM, ASTC_2D_6X6, t), + C4(D, ASTC_8x5_SRGB, NONE, R, G, B, A, UNORM, ASTC_2D_8X5, t), + C4(D, ASTC_8x6_SRGB, NONE, R, G, B, A, UNORM, ASTC_2D_8X6, t), + C4(D, ASTC_8x8_SRGB, NONE, R, G, B, A, UNORM, ASTC_2D_8X8, t), + C4(D, ASTC_10x5_SRGB, NONE, R, G, B, A, UNORM, ASTC_2D_10X5, t), + C4(D, ASTC_10x6_SRGB, NONE, R, G, B, A, UNORM, ASTC_2D_10X6, t), + C4(D, ASTC_10x8_SRGB, NONE, R, G, B, A, UNORM, ASTC_2D_10X8, t), + C4(D, ASTC_10x10_SRGB, NONE, R, G, B, A, UNORM, ASTC_2D_10X10, t), + C4(D, ASTC_12x10_SRGB, NONE, R, G, B, A, UNORM, ASTC_2D_12X10, t), + C4(D, ASTC_12x12_SRGB, NONE, R, G, B, A, UNORM, ASTC_2D_12X12, t), +#endif + C4(A, R32G32B32A32_FLOAT, RGBA32_FLOAT, R, G, B, A, FLOAT, R32_G32_B32_A32, IB), C4(A, R32G32B32A32_UNORM, NONE, R, G, B, A, UNORM, R32_G32_B32_A32, T), C4(A, R32G32B32A32_SNORM, NONE, R, G, B, A, SNORM, R32_G32_B32_A32, T), diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c index 14438ced7a3..ec2340ee0c3 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c @@ -45,6 +45,8 @@ nvc0_screen_is_format_supported(struct pipe_screen *pscreen, unsigned sample_count, unsigned bindings) { + const struct util_format_description *desc = util_format_description(format); + if (sample_count > 8) return false; if (!(0x117 & (1 << sample_count))) /* 0, 1, 2, 4 or 8 */ @@ -65,6 +67,17 @@ nvc0_screen_is_format_supported(struct pipe_screen *pscreen, sample_count > 1) return false; + /* Restrict ETC2 and ASTC formats here. These are only supported on GK20A. + */ + if ((desc->layout == UTIL_FORMAT_LAYOUT_ETC || + desc->layout == UTIL_FORMAT_LAYOUT_ASTC) && + /* The claim is that this should work on GM107 but it doesn't. Need to + * test further and figure out if it's a nouveau issue or a HW one. + nouveau_screen(pscreen)->class_3d < GM107_3D_CLASS && + */ + nouveau_screen(pscreen)->class_3d != NVEA_3D_CLASS) + return false; + /* transfers & shared are always supported */ bindings &= ~(PIPE_BIND_TRANSFER_READ | PIPE_BIND_TRANSFER_WRITE | diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c b/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c index ce6a6dce39c..e04573f8249 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c @@ -250,6 +250,7 @@ gf100_create_texture_view(struct pipe_context *pipe, uint32_t swz[4]; uint32_t width, height; uint32_t depth; + uint32_t tex_fmt; struct nv50_tic_entry *view; struct nv50_miptree *mt; bool tex_int; @@ -275,12 +276,13 @@ gf100_create_texture_view(struct pipe_context *pipe, fmt = &nvc0_format_table[view->pipe.format]; tex_int = util_format_is_pure_integer(view->pipe.format); + tex_fmt = fmt->tic.format & 0x3f; swz[0] = nv50_tic_swizzle(fmt, view->pipe.swizzle_r, tex_int); swz[1] = nv50_tic_swizzle(fmt, view->pipe.swizzle_g, tex_int); swz[2] = nv50_tic_swizzle(fmt, view->pipe.swizzle_b, tex_int); swz[3] = nv50_tic_swizzle(fmt, view->pipe.swizzle_a, tex_int); - tic[0] = (fmt->tic.format << G80_TIC_0_COMPONENTS_SIZES__SHIFT) | + tic[0] = (tex_fmt << G80_TIC_0_COMPONENTS_SIZES__SHIFT) | (fmt->tic.type_r << G80_TIC_0_R_DATA_TYPE__SHIFT) | (fmt->tic.type_g << G80_TIC_0_G_DATA_TYPE__SHIFT) | (fmt->tic.type_b << G80_TIC_0_B_DATA_TYPE__SHIFT) | @@ -288,7 +290,8 @@ gf100_create_texture_view(struct pipe_context *pipe, (swz[0] << G80_TIC_0_X_SOURCE__SHIFT) | (swz[1] << G80_TIC_0_Y_SOURCE__SHIFT) | (swz[2] << G80_TIC_0_Z_SOURCE__SHIFT) | - (swz[3] << G80_TIC_0_W_SOURCE__SHIFT); + (swz[3] << G80_TIC_0_W_SOURCE__SHIFT) | + ((fmt->tic.format & 0x40) << (GK20A_TIC_0_USE_COMPONENT_SIZES_EXTENDED__SHIFT - 6)); address = mt->base.address; From f9b8b48bed2f35592a5e77d9404019e9603ee160 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 4 Apr 2016 07:54:28 +0100 Subject: [PATCH 54/62] mesa/get: fix MAX_GEOMETRY_SHADER_STORAGE_BLOCKS this was returning the fragment shader value. Reviewed-by: Kenneth Graunke Signed-off-by: Dave Airlie --- src/mesa/main/get_hash_params.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesa/main/get_hash_params.py b/src/mesa/main/get_hash_params.py index 59d6557eb4a..33ec60d9ce0 100644 --- a/src/mesa/main/get_hash_params.py +++ b/src/mesa/main/get_hash_params.py @@ -535,7 +535,7 @@ descriptor=[ [ "MAX_GEOMETRY_ATOMIC_COUNTERS", "CONTEXT_INT(Const.Program[MESA_SHADER_GEOMETRY].MaxAtomicCounters), extra_ARB_shader_atomic_counters_and_geometry_shader" ], # GL_ARB_shader_storage_buffer_object / geometry shader - [ "MAX_GEOMETRY_SHADER_STORAGE_BLOCKS", "CONTEXT_INT(Const.Program[MESA_SHADER_FRAGMENT].MaxShaderStorageBlocks), extra_ARB_shader_storage_buffer_object_and_geometry_shader" ], + [ "MAX_GEOMETRY_SHADER_STORAGE_BLOCKS", "CONTEXT_INT(Const.Program[MESA_SHADER_GEOMETRY].MaxShaderStorageBlocks), extra_ARB_shader_storage_buffer_object_and_geometry_shader" ], # GL_ARB_uniform_buffer_object / geometry shader [ "MAX_GEOMETRY_UNIFORM_BLOCKS", "CONTEXT_INT(Const.Program[MESA_SHADER_GEOMETRY].MaxUniformBlocks), extra_ARB_uniform_buffer_object_and_geometry_shader" ], From 7dc11ed0b2eeefc4ed90ce7cb00016fd351aba7c Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Mon, 4 Apr 2016 11:39:34 +0100 Subject: [PATCH 55/62] docs: Update 11.2.0 release notes Signed-off-by: Emil Velikov (cherry picked from commit ff9ddb9eb1b3b25f40e71a95bb48421abfcb11d9) --- docs/relnotes/11.2.0.html | 214 +++++++++++++++++++++++++++++++++++++- 1 file changed, 212 insertions(+), 2 deletions(-) diff --git a/docs/relnotes/11.2.0.html b/docs/relnotes/11.2.0.html index baedb4ca756..f6053896609 100644 --- a/docs/relnotes/11.2.0.html +++ b/docs/relnotes/11.2.0.html @@ -14,7 +14,7 @@
    -

    Mesa 11.2.0 Release Notes / TBD

    +

    Mesa 11.2.0 Release Notes / 4 April 2016

    Mesa 11.2.0 is a new development release. @@ -70,7 +70,217 @@ Note: some of the new features are only available with certain drivers.

    Bug fixes

    -TBD. +
      + +
    • Bug 27512 - Illegal instruction _mesa_x86_64_transform_points4_general
    • + +
    • Bug 75165 - compute.c:464:49: error: function definition is not allowed here
    • + +
    • Bug 79783 - Distorted output in obs-studio where other vendors "work"
    • + +
    • Bug 89330 - piglit glsl-1.50 invariant-qualifier-in-out-block-01 regression
    • + +
    • Bug 89969 - nouveau: add support for chunk decoding in order to support vaapi (st/va)
    • + +
    • Bug 90348 - Spilling failure of b96 merged value
    • + +
    • Bug 91526 - World of Warcraft (on Wine) has UI corruption with nouveau
    • + +
    • Bug 91596 - EGL_KHR_gl_colorspace (v2) causes problem with Android-x86 GUI
    • + +
    • Bug 91806 - configure does not test whether assembler supports sse4.1
    • + +
    • Bug 91927 - [SKL] [regression] piglit compressed textures tests fail with kernel upgrade
    • + +
    • Bug 92193 - [SKL] ES2-CTS.gtf.GL2ExtensionTests.compressed_astc_texture.compressed_astc_texture fails
    • + +
    • Bug 92229 - [APITRACE] SOMA have serious graphical errors
    • + +
    • Bug 92233 - Unigine Heaven 4.0 silhuette run
    • + +
    • Bug 92363 - [BSW/BDW] ogles1conform Gets test fails
    • + +
    • Bug 92438 - Segfault in pushbuf_kref when running the android emulator (qemu) on nv50
    • + +
    • Bug 92589 - [BDW BSW SKL CTS] ES31-CTS.texture_gather.* GPU_HANG
    • + +
    • Bug 92595 - [HSW,BDW,SKL][GLES 3.1 CTS] Big difference in the results for the ES31-CTS.shader_bitfield_operation.* tests
    • + +
    • Bug 92609 - [BDW, BSW] piglit sampling-2d-array-as-2d-layer fails
    • + +
    • Bug 92687 - Add support for ARB_internalformat_query2
    • + +
    • Bug 92706 - glBlitFramebuffer refuses to blit RGBA to RGB with MSAA
    • + +
    • Bug 92709 - "LLVM triggered Diagnostic Handler: unsupported call to function ldexpf in main" when starting race in stuntrally
    • + +
    • Bug 92743 - Centroid shouldn't have to match between the FS and the VS
    • + +
    • Bug 92759 - [Regression, bisected] Visuals without alpha bits are not sRGB-capable
    • + +
    • Bug 92849 - [IVB HSW BDW] piglit image load/store load-from-cleared-image.shader_test fails
    • + +
    • Bug 92909 - Offset/alignment issue with layout std140 and vec3
    • + +
    • Bug 93004 - Guild Wars 2 crash on nouveau DX11 cards
    • + +
    • Bug 93048 - [CTS regression] mesa af2723 breaks GL Conformance for debug extension
    • + +
    • Bug 93063 - drm_helper.h:227:1: error: static declaration of ‘pipe_virgl_create_screen’ follows non-static declaration
    • + +
    • Bug 93091 - [opencl] segfault when running any opencl programs (like clinfo)
    • + +
    • Bug 93092 - lp_test_format regression
    • + +
    • Bug 93126 - wrongly claim supporting GL_EXT_texture_rg
    • + +
    • Bug 93180 - [regression] arb_separate_shader_objects.active sampler conflict fails
    • + +
    • Bug 93189 - "./util/u_inlines.h", line 83: operands have incompatible types: void ":" int
    • + +
    • Bug 93215 - [Regression bisected] Ogles1conform Automatic mipmap generation test is fail
    • + +
    • Bug 93235 - [regression] dispatch sanity broken by GetPointerv
    • + +
    • Bug 93257 - [SKL, bisected] ASTC dEQP tests segfault
    • + +
    • Bug 93264 - Tonga VM Faults since llvm ScheduleDAGInstrs: Rework schedule graph builder.
    • + +
    • Bug 93266 - gl_arb_shading_language_420pack does not allow binding of image variables
    • + +
    • Bug 93300 - Two Worlds 2 renders water incorrectly
    • + +
    • Bug 93312 - [SKL][GLES 3.1 CTS] ES31-CTS.layout_binding* GPU_HANG
    • + +
    • Bug 93320 - [HSW,BDW,SKL][GLES 3.1 CTS] ES31-CTS.vertex_attrib_binding.advanced-bindingUpdate fail
    • + +
    • Bug 93322 - [HSW,BDW,SKL][GLES 3.1 CTS] ES31-CTS.compute_shader.resource-ubo fail
    • + +
    • Bug 93323 - [HSW,BDW,SKL][GLES 3.1 CTS]ES31-CTS.shader_image_load_store.basic-allTargets-store-fs fail
    • + +
    • Bug 93325 - [HSW,BDW,SKL]ES31-CTS.explicit_uniform_location.uniform-loc-* 2 tests fail
    • + +
    • Bug 93339 - glLinkProgram() should fail when a varying is never written to in a previous stage
    • + +
    • Bug 93348 - [HSW,BDW,SKL][GLES 3.1 CTS] ES31-CTS.compute_shader.* segfault
    • + +
    • Bug 93358 - [HSW] Unreal Elemental demo - assertion error in copy_image_with_blitter
    • + +
    • Bug 93387 - inverse() shouldn’t be exposed in GLSL 1.20 and 1.30
    • + +
    • Bug 93388 - [i965, regression, bisection] MESA_FORMAT_B8G8R8X8_SRGB changes break kwin
    • + +
    • Bug 93407 - [SKL][GLES 3.1 CTS]ES31-CTS.compute_shader.resources-texture fail
    • + +
    • Bug 93410 - [BDW,SKL][GLES 3.1 CTS]ES31-CTS.shader_image_load_store.negative-linkErrors fail
    • + +
    • Bug 93418 - Geometry Shaders output wrong vertices on Sandy Bridge
    • + +
    • Bug 93426 - [SKL,BDW,BSW,BXT] CTS regression: es2-cts.gtf.gl2fixedtests.buffer_objects.buffer_object,s
    • + +
    • Bug 93524 - Clover doesn't build
    • + +
    • Bug 93526 - GfxBench 4 tessellation demos misrender
    • + +
    • Bug 93532 - [HSW,BDW,SKL][GLES 3.1 CTS] ES31-CTS.compute_shader.*. Regression, bisected.
    • + +
    • Bug 93540 - [BISECTED, HSW] Rendering issue in Heaven (and other benchmarks)
    • + +
    • Bug 93560 - opt_combine_constants failing fabsf(reg->f) == table.imm[i].val assertion
    • + +
    • Bug 93599 - Strange green flashes with "Metro: Last Light Redux" + "Metro 2033 Redux" with Intel Mesa driver
    • + +
    • Bug 93648 - Random lines being rendered when playing Dolphin (geometry shaders related, w/ apitrace)
    • + +
    • Bug 93650 - GL_ARB_separate_shader_objects is buggy (PCSX2)
    • + +
    • Bug 93667 - Crash in eglCreateImageKHR with huge texture size
    • + +
    • Bug 93696 - [HSW,BDW;SKL][GLES 3.1 CTS]ES31-CTS.explicit_uniform_location.uniform-loc-mix-with-implicit-max-* fail
    • + +
    • Bug 93700 - [SKL, regression] deqp-gles2.functional.texture.completeness
    • + +
    • Bug 93717 - Meta mipmap generation can corrupt texture state
    • + +
    • Bug 93722 - Segfault when compiling shader with a subroutine that takes a parameter
    • + +
    • Bug 93725 - [HSW, regression, bisected] ES31-CTS.texture_gather.*depth*
    • + +
    • Bug 93731 - glUniformSubroutinesuiv segfaults when subroutine uniform is bound to a specific location
    • + +
    • Bug 93761 - A conditional discard in a fragment shader causes no depth writing at all
    • + +
    • Bug 93790 - [HSW] Use after free with compute programs
    • + +
    • Bug 93792 - [HSW] intel_mipmap_tree.c:1325: intel_miptree_copy_slice: Assertion `src_mt->format == dst_mt->format
    • + +
    • Bug 93813 - Incorrect viewport range when GL_CLIP_ORIGIN is GL_UPPER_LEFT
    • + +
    • Bug 93840 - [i965] Alien: Isolation fails with GL_ARB_compute_shader enabled
    • + +
    • Bug 93862 - [Bisected] "drm/amdgpu: fix amdgpu_bo_pin_restricted VRAM placing v2" is bad
    • + +
    • Bug 93878 - [llvmpipe][softpipe] piglit arb_gpu_shader_fp64-double-gettransformfeedbackvarying regression
    • + +
    • Bug 93957 - [HSW] Mishandling of sample count when using an attachment-less framebuffer (assertion error)
    • + +
    • Bug 93961 - virgl build failure after 2016-02-01 changes - no previous prototype for 'virgl_drm_winsys_create'
    • + +
    • Bug 93962 - [HSW, regression, bisected, CTS] ES2-CTS.gtf.GL2FixedTests.scissor.scissor - segfault/asserts
    • + +
    • Bug 93989 - build: flex-2.5.39 seems to be failing for glsl_lexer.ll
    • + +
    • Bug 94016 - make check MesaExtensionsTest.AlphabeticallySorted regression
    • + +
    • Bug 94019 - [bisected] 3D acceleration broken with gallium/radeon: just get num_tile_pipes from the winsys
    • + +
    • Bug 94050 - test_vec4_register_coalesce regression
    • + +
    • Bug 94073 - Miscompilation of abs_vec3_vert_xvary_ref.vert in WebGL conformance
    • + +
    • Bug 94081 - [HSW] compute shader shared var + atomic op = fail
    • + +
    • Bug 94088 - [llvmpipe] SIGFPE pthread_barrier_destroy.c:40
    • + +
    • Bug 94091 - Tonga unreal elemental segfault since radeonsi: put image, fmask, and sampler descriptors into one array
    • + +
    • Bug 94100 - [HSW] compute indirect dispatch with 0 work groups causes gpu hang
    • + +
    • Bug 94134 - [regression] piglit.spec.arb_texture_view.sampling-2d-array-as-2d-layer assertion
    • + +
    • Bug 94139 - [regression, HSW, IVB] piglit.spec.arb_compute_shader.minmax
    • + +
    • Bug 94150 - UE4 Suntemple rendering errors
    • + +
    • Bug 94186 - Crash when launching glxinfo and World of Warcraft with RV790
    • + +
    • Bug 94188 - define (or undef) defined behaves stupidly
    • + +
    • Bug 94193 - [llvmpipe] Line antialiasing looks different when GL_LINE_STIPPLE is enabled with pattern 0xffff
    • + +
    • Bug 94199 - Shader abort/crash
    • + +
    • Bug 94253 - [llvmpipe] piglit gl-1.0-swapbuffers-behavior regression
    • + +
    • Bug 94254 - [llvmpipe] [softpipe] piglit read-front regression
    • + +
    • Bug 94257 - [softpipe] piglit glx-copy-sub-buffer regression
    • + +
    • Bug 94274 - [swrast] piglit arb_occlusion_query2-render regression
    • + +
    • Bug 94284 - [radeonsi] outlast segfault on start
    • + +
    • Bug 94388 - r600_blit.c:281: r600_decompress_depth_textures: Assertion `tex->is_depth && !tex->is_flushing_texture' failed.
    • + +
    • Bug 94412 - Trine 3 misrender
    • + +
    • Bug 94481 - softpipe - access violation in img_filter_2d_nearest
    • + +
    • Bug 94524 - Wrong gl_TessLevelOuter interpretation for isolines
    • + +
    • Bug 94595 - [Mesa AMD&swrast] Texture views attached as framebuffers return their viewed tecture's color encoding and render incorrectly
    • + +

    Changes

    From dc4923d41f8059834d9d54f8c8ba75bb8143f64b Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Mon, 4 Apr 2016 12:55:27 +0100 Subject: [PATCH 56/62] docs: add sha256 checksums for 11.2.0 Signed-off-by: Emil Velikov (cherry picked from commit e7fb889dcc002f87c316f3cdc6e7907a88c12697) --- docs/relnotes/11.2.0.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/relnotes/11.2.0.html b/docs/relnotes/11.2.0.html index f6053896609..a83d527466b 100644 --- a/docs/relnotes/11.2.0.html +++ b/docs/relnotes/11.2.0.html @@ -33,7 +33,8 @@ because compatibility contexts are not supported.

    SHA256 checksums

    -TBD.
    +dea3d8143929aad5c24ef0993ddb05807b30c284b488fc62903adfcc1c127887  mesa-11.2.0.tar.gz
    +1c1fed2674abf3f16ed2623e9a5694d6752c293194e18462ebc644a19cfaafb2  mesa-11.2.0.tar.xz
     
    From 35132c413ce3bc29a8f51ab2cbac60bf68eb8d9b Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Mon, 4 Apr 2016 12:57:56 +0100 Subject: [PATCH 57/62] docs: add news item and link release notes for 11.2.0 Signed-off-by: Emil Velikov --- docs/index.html | 7 +++++++ docs/relnotes.html | 1 + 2 files changed, 8 insertions(+) diff --git a/docs/index.html b/docs/index.html index 8c13a0a5b3e..6ccc3d6bc66 100644 --- a/docs/index.html +++ b/docs/index.html @@ -16,6 +16,13 @@

    News

    +

    April 4, 2016

    +

    +Mesa 11.2.0 is released. This is a +new development release. See the release notes for more information +about the release. +

    +

    February 10, 2016

    Mesa 11.1.2 is released. diff --git a/docs/relnotes.html b/docs/relnotes.html index 90fdf9287b0..3c88a284fdd 100644 --- a/docs/relnotes.html +++ b/docs/relnotes.html @@ -21,6 +21,7 @@ The release notes summarize what's new or changed in each Mesa release.

      +
    • 11.2.0 release notes
    • 11.1.2 release notes
    • 11.0.9 release notes
    • 11.1.1 release notes From 1eeec7ec41dcc5f6aeb133ef7f533696a883327f Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Mon, 4 Apr 2016 10:33:11 -0600 Subject: [PATCH 58/62] docs: remove stray 'TBD' in 11.2.0 relnotes file --- docs/relnotes/11.2.0.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/relnotes/11.2.0.html b/docs/relnotes/11.2.0.html index a83d527466b..b0d0a609e26 100644 --- a/docs/relnotes/11.2.0.html +++ b/docs/relnotes/11.2.0.html @@ -289,7 +289,7 @@ Microsoft Visual Studio 2013 or later is now required for building on Windows. Previously, Visual Studio 2008 and later were supported. -TBD. +
    From 3aa51e02d6659c8f2e34a4153ae140a4f90cc51b Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Mon, 4 Apr 2016 00:45:25 -0700 Subject: [PATCH 59/62] i965: Allow 8x MSAA on >= 64bpp formats on Gen8+. See commit 3b0279a69 - this restriction is documented in the "Surface Format" field of RENDER_SURFACE_STATE. Looking at newer documentation, this restriction appears to exist on Haswell, but no longer applies on Gen8+. Signed-off-by: Kenneth Graunke Reviewed-by: Ben Widawsky --- src/mesa/drivers/dri/i965/brw_surface_formats.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mesa/drivers/dri/i965/brw_surface_formats.c b/src/mesa/drivers/dri/i965/brw_surface_formats.c index 3c0b23b4a42..ba9b5b90b63 100644 --- a/src/mesa/drivers/dri/i965/brw_surface_formats.c +++ b/src/mesa/drivers/dri/i965/brw_surface_formats.c @@ -806,7 +806,8 @@ brw_render_target_supported(struct brw_context *brw, /* Under some conditions, MSAA is not supported for formats whose width is * more than 64 bits. */ - if (rb->NumSamples > 0 && _mesa_get_format_bytes(format) > 8) { + if (brw->gen < 8 && + rb->NumSamples > 0 && _mesa_get_format_bytes(format) > 8) { /* Gen6: MSAA on >64 bit formats is unsupported. */ if (brw->gen <= 6) return false; From 65fbc43d54403905e3eaea02372b5a364dc1d773 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Wed, 27 Jan 2016 12:21:04 -0800 Subject: [PATCH 60/62] i965: Add an INTEL_PRECISE_TRIG=1 option to fix SIN/COS output range. The SIN and COS instructions on Intel hardware can produce values slightly outside of the [-1.0, 1.0] range for a small set of values. Obviously, this can break everyone's expectations about trig functions. According to an internal presentation, the COS instruction can produce a value up to 1.000027 for inputs in the range (0.08296, 0.09888). One suggested workaround is to multiply by 0.99997, scaling down the amplitude slightly. Apparently this also minimizes the error function, reducing the maximum error from 0.00006 to about 0.00003. When enabled, fixes 16 dEQP precision tests dEQP-GLES31.functional.shaders.builtin_functions.precision. {cos,sin}.{highp,mediump}_compute.{scalar,vec2,vec4,vec4}. at the cost of making every sin and cos call more expensive (about twice the number of cycles on recent hardware). Enabling this option has been shown to reduce GPUTest Volplosion performance by about 10%. Signed-off-by: Kenneth Graunke Reviewed-by: Matt Turner Reviewed-by: Jason Ekstrand --- src/mesa/drivers/dri/i965/brw_compiler.c | 2 ++ src/mesa/drivers/dri/i965/brw_compiler.h | 6 ++++++ src/mesa/drivers/dri/i965/brw_fs_nir.cpp | 16 ++++++++++++++-- src/mesa/drivers/dri/i965/brw_vec4_nir.cpp | 16 ++++++++++++++-- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_compiler.c b/src/mesa/drivers/dri/i965/brw_compiler.c index 3da6aac2cbf..6509267a52e 100644 --- a/src/mesa/drivers/dri/i965/brw_compiler.c +++ b/src/mesa/drivers/dri/i965/brw_compiler.c @@ -147,6 +147,8 @@ brw_compiler_create(void *mem_ctx, const struct brw_device_info *devinfo) brw_fs_alloc_reg_sets(compiler); brw_vec4_alloc_reg_set(compiler); + compiler->precise_trig = env_var_as_boolean("INTEL_PRECISE_TRIG", false); + compiler->scalar_stage[MESA_SHADER_VERTEX] = devinfo->gen >= 8 && !(INTEL_DEBUG & DEBUG_VEC4VS); compiler->scalar_stage[MESA_SHADER_TESS_CTRL] = false; diff --git a/src/mesa/drivers/dri/i965/brw_compiler.h b/src/mesa/drivers/dri/i965/brw_compiler.h index 27a95a3c661..231e0001d54 100644 --- a/src/mesa/drivers/dri/i965/brw_compiler.h +++ b/src/mesa/drivers/dri/i965/brw_compiler.h @@ -92,6 +92,12 @@ struct brw_compiler { bool scalar_stage[MESA_SHADER_STAGES]; struct gl_shader_compiler_options glsl_compiler_options[MESA_SHADER_STAGES]; + + /** + * Apply workarounds for SIN and COS output range problems. + * This can negatively impact performance. + */ + bool precise_trig; }; diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp index 7839428c52e..5cca91ec5b4 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp @@ -775,12 +775,24 @@ fs_visitor::nir_emit_alu(const fs_builder &bld, nir_alu_instr *instr) break; case nir_op_fsin: - inst = bld.emit(SHADER_OPCODE_SIN, result, op[0]); + if (!compiler->precise_trig) { + inst = bld.emit(SHADER_OPCODE_SIN, result, op[0]); + } else { + fs_reg tmp = bld.vgrf(BRW_REGISTER_TYPE_F); + inst = bld.emit(SHADER_OPCODE_SIN, tmp, op[0]); + inst = bld.MUL(result, tmp, brw_imm_f(0.99997)); + } inst->saturate = instr->dest.saturate; break; case nir_op_fcos: - inst = bld.emit(SHADER_OPCODE_COS, result, op[0]); + if (!compiler->precise_trig) { + inst = bld.emit(SHADER_OPCODE_COS, result, op[0]); + } else { + fs_reg tmp = bld.vgrf(BRW_REGISTER_TYPE_F); + inst = bld.emit(SHADER_OPCODE_COS, tmp, op[0]); + inst = bld.MUL(result, tmp, brw_imm_f(0.99997)); + } inst->saturate = instr->dest.saturate; break; diff --git a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp index ee6929b16a2..6c8fd06fb5e 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp @@ -1101,12 +1101,24 @@ vec4_visitor::nir_emit_alu(nir_alu_instr *instr) break; case nir_op_fsin: - inst = emit_math(SHADER_OPCODE_SIN, dst, op[0]); + if (!compiler->precise_trig) { + inst = emit_math(SHADER_OPCODE_SIN, dst, op[0]); + } else { + src_reg tmp = src_reg(this, glsl_type::vec4_type); + inst = emit_math(SHADER_OPCODE_SIN, dst_reg(tmp), op[0]); + inst = emit(MUL(dst, tmp, brw_imm_f(0.99997))); + } inst->saturate = instr->dest.saturate; break; case nir_op_fcos: - inst = emit_math(SHADER_OPCODE_COS, dst, op[0]); + if (!compiler->precise_trig) { + inst = emit_math(SHADER_OPCODE_COS, dst, op[0]); + } else { + src_reg tmp = src_reg(this, glsl_type::vec4_type); + inst = emit_math(SHADER_OPCODE_COS, dst_reg(tmp), op[0]); + inst = emit(MUL(dst, tmp, brw_imm_f(0.99997))); + } inst->saturate = instr->dest.saturate; break; From eb93d6dec82cd02e97b0a673fb11eef1f31777e7 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Mon, 28 Mar 2016 11:12:33 -0700 Subject: [PATCH 61/62] nir/search: Don't match inexact expressions with exact subexpressions In the first pass of implementing exact handling, I made a mistake with search-and-replace. In particular, we only reallly handled exact/inexact on the root of the tree. Instead, we need to check every node in the tree for an exact/inexact match. As an example of this, consider the following GLSL code precise float a = b + c; if (a < 0) { do_stuff(); } In that case, only the add will be declared "exact" and an expression that looks for "b + c < 0" will still match and replace it with "b < -c" which may yield different results. The solution is to simply bail if any of the values are exact when matching an inexact expression. Reviewed-by: Ian Romanick --- src/compiler/nir/nir_search.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/compiler/nir/nir_search.c b/src/compiler/nir/nir_search.c index 6e630631453..b915101ce32 100644 --- a/src/compiler/nir/nir_search.c +++ b/src/compiler/nir/nir_search.c @@ -28,6 +28,8 @@ #include "nir_search.h" struct match_state { + bool inexact_match; + bool has_exact_alu; unsigned variables_seen; nir_alu_src variables[NIR_SEARCH_MAX_VARIABLES]; }; @@ -239,7 +241,10 @@ match_expression(const nir_search_expression *expr, nir_alu_instr *instr, return false; assert(instr->dest.dest.is_ssa); - if (expr->inexact && instr->exact) + + state->inexact_match = expr->inexact || state->inexact_match; + state->has_exact_alu = instr->exact || state->has_exact_alu; + if (state->inexact_match && state->has_exact_alu) return false; assert(!instr->dest.saturate); @@ -410,7 +415,7 @@ bitsize_tree_filter_down(bitsize_tree *tree, unsigned size) static nir_alu_src construct_value(const nir_search_value *value, - unsigned num_components, bitsize_tree *bitsize, bool exact, + unsigned num_components, bitsize_tree *bitsize, struct match_state *state, nir_instr *instr, void *mem_ctx) { @@ -424,10 +429,16 @@ construct_value(const nir_search_value *value, nir_alu_instr *alu = nir_alu_instr_create(mem_ctx, expr->opcode); nir_ssa_dest_init(&alu->instr, &alu->dest.dest, num_components, bitsize->dest_size, NULL); - alu->exact = exact; alu->dest.write_mask = (1 << num_components) - 1; alu->dest.saturate = false; + /* We have no way of knowing what values in a given search expression + * map to a particular replacement value. Therefore, if the + * expression we are replacing has any exact values, the entire + * replacement should be exact. + */ + alu->exact = state->has_exact_alu; + for (unsigned i = 0; i < nir_op_infos[expr->opcode].num_inputs; i++) { /* If the source is an explicitly sized source, then we need to reset * the number of components to match. @@ -436,7 +447,7 @@ construct_value(const nir_search_value *value, num_components = nir_op_infos[alu->op].input_sizes[i]; alu->src[i] = construct_value(expr->srcs[i], - num_components, bitsize->srcs[i], exact, + num_components, bitsize->srcs[i], state, instr, mem_ctx); } @@ -546,6 +557,8 @@ nir_replace_instr(nir_alu_instr *instr, const nir_search_expression *search, assert(instr->dest.dest.is_ssa); struct match_state state; + state.inexact_match = false; + state.has_exact_alu = false; state.variables_seen = 0; if (!match_expression(search, instr, instr->dest.dest.ssa.num_components, @@ -569,7 +582,7 @@ nir_replace_instr(nir_alu_instr *instr, const nir_search_expression *search, mov->src[0] = construct_value(replace, instr->dest.dest.ssa.num_components, tree, - instr->exact, &state, &instr->instr, mem_ctx); + &state, &instr->instr, mem_ctx); nir_instr_insert_before(&instr->instr, &mov->instr); nir_ssa_def_rewrite_uses(&instr->dest.dest.ssa, From 88ef2476dcdd61000cbae7ded9c8fa52927429d8 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Mon, 28 Mar 2016 11:47:27 -0700 Subject: [PATCH 62/62] i965/peephole_ffma: Only match a mul+add if none of the ops are exact Reviewed-by: Ian Romanick --- src/mesa/drivers/dri/i965/brw_nir_opt_peephole_ffma.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/mesa/drivers/dri/i965/brw_nir_opt_peephole_ffma.c b/src/mesa/drivers/dri/i965/brw_nir_opt_peephole_ffma.c index 6e8b1f99505..22ff2e3c9f8 100644 --- a/src/mesa/drivers/dri/i965/brw_nir_opt_peephole_ffma.c +++ b/src/mesa/drivers/dri/i965/brw_nir_opt_peephole_ffma.c @@ -84,6 +84,17 @@ get_mul_for_src(nir_alu_src *src, int num_components, return NULL; nir_alu_instr *alu = nir_instr_as_alu(instr); + + /* We want to bail if any of the other ALU operations involved is labled + * exact. One reason for this is that, while the value that is changing is + * actually the result of the add and not the multiply, the intention of + * the user when they specify an exact multiply is that they want *that* + * value and what they don't care about is the add. Another reason is that + * SPIR-V explicitly requires this behaviour. + */ + if (alu->exact) + return NULL; + switch (alu->op) { case nir_op_imov: case nir_op_fmov: