aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/glsl')
-rw-r--r--mesalib/src/glsl/Makefile.am8
-rw-r--r--mesalib/src/glsl/Makefile.sources1
-rw-r--r--mesalib/src/glsl/SConscript2
-rw-r--r--mesalib/src/glsl/ast_array_index.cpp4
-rw-r--r--mesalib/src/glsl/builtin_functions.cpp2
-rw-r--r--mesalib/src/glsl/builtin_variables.cpp2
-rw-r--r--mesalib/src/glsl/glcpp/pp.c1
-rw-r--r--mesalib/src/glsl/glsl_parser.yy4
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.cpp9
-rw-r--r--mesalib/src/glsl/ir.cpp6
-rw-r--r--mesalib/src/glsl/ir_clone.cpp2
-rw-r--r--mesalib/src/glsl/ir_constant_expression.cpp2
-rw-r--r--mesalib/src/glsl/ir_optimization.h1
-rw-r--r--mesalib/src/glsl/ir_rvalue_visitor.cpp19
-rw-r--r--mesalib/src/glsl/ir_rvalue_visitor.h3
-rw-r--r--mesalib/src/glsl/ir_validate.cpp15
-rw-r--r--mesalib/src/glsl/link_interface_blocks.cpp74
-rw-r--r--mesalib/src/glsl/linker.cpp93
-rw-r--r--mesalib/src/glsl/linker.h5
-rw-r--r--mesalib/src/glsl/loop_controls.cpp2
-rw-r--r--mesalib/src/glsl/lower_discard_flow.cpp9
-rw-r--r--mesalib/src/glsl/lower_instructions.cpp2
-rw-r--r--mesalib/src/glsl/lower_packed_varyings.cpp117
-rw-r--r--mesalib/src/glsl/nir/glsl_to_nir.cpp10
-rw-r--r--mesalib/src/glsl/nir/nir.c1
-rw-r--r--mesalib/src/glsl/nir/nir.h11
-rw-r--r--mesalib/src/glsl/nir/nir_from_ssa.c29
-rw-r--r--mesalib/src/glsl/nir/nir_intrinsics.h2
-rw-r--r--mesalib/src/glsl/nir/nir_live_variables.c5
-rw-r--r--mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c11
-rw-r--r--mesalib/src/glsl/nir/nir_opt_copy_propagate.c45
-rw-r--r--mesalib/src/glsl/nir/nir_opt_gcm.c4
-rw-r--r--mesalib/src/glsl/nir/nir_vla.h54
-rw-r--r--mesalib/src/glsl/opt_algebraic.cpp76
-rw-r--r--mesalib/src/glsl/opt_conditional_discard.cpp81
-rw-r--r--mesalib/src/glsl/opt_constant_folding.cpp24
-rw-r--r--mesalib/src/glsl/s_expression.cpp1
-rw-r--r--mesalib/src/glsl/s_expression.h4
-rw-r--r--mesalib/src/glsl/standalone_scaffolding.cpp1
39 files changed, 545 insertions, 197 deletions
diff --git a/mesalib/src/glsl/Makefile.am b/mesalib/src/glsl/Makefile.am
index 5a0a643da..b466a3b5c 100644
--- a/mesalib/src/glsl/Makefile.am
+++ b/mesalib/src/glsl/Makefile.am
@@ -33,8 +33,12 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/gtest/include \
-I$(top_builddir)/src/glsl/nir \
$(DEFINES)
-AM_CFLAGS = $(VISIBILITY_CFLAGS)
-AM_CXXFLAGS = $(VISIBILITY_CXXFLAGS)
+AM_CFLAGS = \
+ $(VISIBILITY_CFLAGS) \
+ $(MSVC2013_COMPAT_CFLAGS)
+AM_CXXFLAGS = \
+ $(VISIBILITY_CXXFLAGS) \
+ $(MSVC2013_COMPAT_CXXFLAGS)
EXTRA_DIST = tests glcpp/tests README TODO glcpp/README \
glsl_lexer.ll \
diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources
index d0210d170..b876642e8 100644
--- a/mesalib/src/glsl/Makefile.sources
+++ b/mesalib/src/glsl/Makefile.sources
@@ -157,6 +157,7 @@ LIBGLSL_FILES = \
lower_ubo_reference.cpp \
opt_algebraic.cpp \
opt_array_splitting.cpp \
+ opt_conditional_discard.cpp \
opt_constant_folding.cpp \
opt_constant_propagation.cpp \
opt_constant_variable.cpp \
diff --git a/mesalib/src/glsl/SConscript b/mesalib/src/glsl/SConscript
index 21c8266a6..26de455f0 100644
--- a/mesalib/src/glsl/SConscript
+++ b/mesalib/src/glsl/SConscript
@@ -6,6 +6,8 @@ from sys import executable as python_cmd
env = env.Clone()
+env.MSVC2013Compat()
+
env.Prepend(CPPPATH = [
'#include',
'#src',
diff --git a/mesalib/src/glsl/ast_array_index.cpp b/mesalib/src/glsl/ast_array_index.cpp
index ff0c7576d..ecef651f7 100644
--- a/mesalib/src/glsl/ast_array_index.cpp
+++ b/mesalib/src/glsl/ast_array_index.cpp
@@ -83,11 +83,9 @@ update_max_array_access(ir_rvalue *ir, int idx, YYLTYPE *loc,
if (deref_var != NULL) {
if (deref_var->var->is_interface_instance()) {
- const glsl_type *interface_type =
- deref_var->var->get_interface_type();
unsigned field_index =
deref_record->record->type->field_index(deref_record->field);
- assert(field_index < interface_type->length);
+ assert(field_index < deref_var->var->get_interface_type()->length);
unsigned *const max_ifc_array_access =
deref_var->var->get_max_ifc_array_access();
diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp
index b643927d0..84bbdc2a4 100644
--- a/mesalib/src/glsl/builtin_functions.cpp
+++ b/mesalib/src/glsl/builtin_functions.cpp
@@ -2549,7 +2549,7 @@ builtin_builder::add_image_function(const char *name,
};
ir_function *f = new(mem_ctx) ir_function(name);
- for (unsigned i = 0; i < Elements(types); ++i) {
+ for (unsigned i = 0; i < ARRAY_SIZE(types); ++i) {
if (types[i]->sampler_type != GLSL_TYPE_FLOAT ||
(flags & IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE))
f->add_signature(_image(types[i], intrinsic_name,
diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp
index 65e32ad73..21e7331c7 100644
--- a/mesalib/src/glsl/builtin_variables.cpp
+++ b/mesalib/src/glsl/builtin_variables.cpp
@@ -227,7 +227,7 @@ static const struct gl_builtin_uniform_element gl_NormalMatrix_elements[] = {
#undef MATRIX
-#define STATEVAR(name) {#name, name ## _elements, Elements(name ## _elements)}
+#define STATEVAR(name) {#name, name ## _elements, ARRAY_SIZE(name ## _elements)}
static const struct gl_builtin_uniform_desc _mesa_builtin_uniform_desc[] = {
STATEVAR(gl_NumSamples),
diff --git a/mesalib/src/glsl/glcpp/pp.c b/mesalib/src/glsl/glcpp/pp.c
index a54bcbe16..160c6662f 100644
--- a/mesalib/src/glsl/glcpp/pp.c
+++ b/mesalib/src/glsl/glcpp/pp.c
@@ -25,7 +25,6 @@
#include <string.h>
#include <ctype.h>
#include "glcpp.h"
-#include "main/core.h" /* for isblank() on MSVC */
void
glcpp_error (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...)
diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy
index ea3bd8a24..90c216ed9 100644
--- a/mesalib/src/glsl/glsl_parser.yy
+++ b/mesalib/src/glsl/glsl_parser.yy
@@ -1280,7 +1280,7 @@ layout_qualifier_id:
{ "triangles_adjacency", GL_TRIANGLES_ADJACENCY },
{ "triangle_strip", GL_TRIANGLE_STRIP },
};
- for (unsigned i = 0; i < Elements(map); i++) {
+ for (unsigned i = 0; i < ARRAY_SIZE(map); i++) {
if (match_layout_qualifier($1, map[i].s, state) == 0) {
$$.flags.q.prim_type = 1;
$$.prim_type = map[i].e;
@@ -1344,7 +1344,7 @@ layout_qualifier_id:
{ "r8_snorm", GL_R8_SNORM, GLSL_TYPE_FLOAT }
};
- for (unsigned i = 0; i < Elements(map); i++) {
+ for (unsigned i = 0; i < ARRAY_SIZE(map); i++) {
if (match_layout_qualifier($1, map[i].name, state) == 0) {
$$.flags.q.explicit_image_format = 1;
$$.image_format = map[i].format;
diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp
index 9f7931380..79624bc26 100644
--- a/mesalib/src/glsl/glsl_parser_extras.cpp
+++ b/mesalib/src/glsl/glsl_parser_extras.cpp
@@ -119,9 +119,9 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
this->Const.MaxAtomicBufferBindings = ctx->Const.MaxAtomicBufferBindings;
/* Compute shader constants */
- for (unsigned i = 0; i < Elements(this->Const.MaxComputeWorkGroupCount); i++)
+ for (unsigned i = 0; i < ARRAY_SIZE(this->Const.MaxComputeWorkGroupCount); i++)
this->Const.MaxComputeWorkGroupCount[i] = ctx->Const.MaxComputeWorkGroupCount[i];
- for (unsigned i = 0; i < Elements(this->Const.MaxComputeWorkGroupSize); i++)
+ for (unsigned i = 0; i < ARRAY_SIZE(this->Const.MaxComputeWorkGroupSize); i++)
this->Const.MaxComputeWorkGroupSize[i] = ctx->Const.MaxComputeWorkGroupSize[i];
this->Const.MaxImageUnits = ctx->Const.MaxImageUnits;
@@ -636,7 +636,7 @@ void _mesa_glsl_extension::set_flags(_mesa_glsl_parse_state *state,
*/
static const _mesa_glsl_extension *find_extension(const char *name)
{
- for (unsigned i = 0; i < Elements(_mesa_glsl_supported_extensions); ++i) {
+ for (unsigned i = 0; i < ARRAY_SIZE(_mesa_glsl_supported_extensions); ++i) {
if (strcmp(name, _mesa_glsl_supported_extensions[i].name) == 0) {
return &_mesa_glsl_supported_extensions[i];
}
@@ -674,7 +674,7 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
return false;
} else {
for (unsigned i = 0;
- i < Elements(_mesa_glsl_supported_extensions); ++i) {
+ i < ARRAY_SIZE(_mesa_glsl_supported_extensions); ++i) {
const _mesa_glsl_extension *extension
= &_mesa_glsl_supported_extensions[i];
if (extension->compatible_with_state(state)) {
@@ -1627,6 +1627,7 @@ do_common_optimization(exec_list *ir, bool linked,
}
progress = do_if_simplification(ir) || progress;
progress = opt_flatten_nested_if_blocks(ir) || progress;
+ progress = opt_conditional_discard(ir) || progress;
progress = do_copy_propagation(ir) || progress;
progress = do_copy_propagation_elements(ir) || progress;
diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp
index f4f92e9df..54656f899 100644
--- a/mesalib/src/glsl/ir.cpp
+++ b/mesalib/src/glsl/ir.cpp
@@ -618,8 +618,8 @@ static const char *const operator_strs[] = {
const char *ir_expression::operator_string(ir_expression_operation op)
{
- assert((unsigned int) op < Elements(operator_strs));
- assert(Elements(operator_strs) == (ir_quadop_vector + 1));
+ assert((unsigned int) op < ARRAY_SIZE(operator_strs));
+ assert(ARRAY_SIZE(operator_strs) == (ir_quadop_vector + 1));
return operator_strs[op];
}
@@ -1707,7 +1707,7 @@ const char *const ir_variable::warn_extension_table[] = {
void
ir_variable::enable_extension_warning(const char *extension)
{
- for (unsigned i = 0; i < Elements(warn_extension_table); i++) {
+ for (unsigned i = 0; i < ARRAY_SIZE(warn_extension_table); i++) {
if (strcmp(warn_extension_table[i], extension) == 0) {
this->data.warn_extension_index = i;
return;
diff --git a/mesalib/src/glsl/ir_clone.cpp b/mesalib/src/glsl/ir_clone.cpp
index 5c7279ca3..914e0e4d5 100644
--- a/mesalib/src/glsl/ir_clone.cpp
+++ b/mesalib/src/glsl/ir_clone.cpp
@@ -158,7 +158,7 @@ ir_call::clone(void *mem_ctx, struct hash_table *ht) const
ir_expression *
ir_expression::clone(void *mem_ctx, struct hash_table *ht) const
{
- ir_rvalue *op[Elements(this->operands)] = { NULL, };
+ ir_rvalue *op[ARRAY_SIZE(this->operands)] = { NULL, };
unsigned int i;
for (i = 0; i < get_num_operands(); i++) {
diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp
index 07dd439d5..388c4c286 100644
--- a/mesalib/src/glsl/ir_constant_expression.cpp
+++ b/mesalib/src/glsl/ir_constant_expression.cpp
@@ -506,7 +506,7 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
if (this->type->is_error())
return NULL;
- ir_constant *op[Elements(this->operands)] = { NULL, };
+ ir_constant *op[ARRAY_SIZE(this->operands)] = { NULL, };
ir_constant_data data;
memset(&data, 0, sizeof(data));
diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h
index 7eb861ae5..e6939f3fe 100644
--- a/mesalib/src/glsl/ir_optimization.h
+++ b/mesalib/src/glsl/ir_optimization.h
@@ -77,6 +77,7 @@ bool do_common_optimization(exec_list *ir, bool linked,
bool do_rebalance_tree(exec_list *instructions);
bool do_algebraic(exec_list *instructions, bool native_integers,
const struct gl_shader_compiler_options *options);
+bool opt_conditional_discard(exec_list *instructions);
bool do_constant_folding(exec_list *instructions);
bool do_constant_variable(exec_list *instructions);
bool do_constant_variable_unlinked(exec_list *instructions);
diff --git a/mesalib/src/glsl/ir_rvalue_visitor.cpp b/mesalib/src/glsl/ir_rvalue_visitor.cpp
index 34cdb1c98..2eee3da7b 100644
--- a/mesalib/src/glsl/ir_rvalue_visitor.cpp
+++ b/mesalib/src/glsl/ir_rvalue_visitor.cpp
@@ -135,6 +135,13 @@ ir_rvalue_base_visitor::rvalue_visit(ir_call *ir)
}
ir_visitor_status
+ir_rvalue_base_visitor::rvalue_visit(ir_discard *ir)
+{
+ handle_rvalue(&ir->condition);
+ return visit_continue;
+}
+
+ir_visitor_status
ir_rvalue_base_visitor::rvalue_visit(ir_return *ir)
{
handle_rvalue(&ir->value);;
@@ -205,6 +212,12 @@ ir_rvalue_visitor::visit_leave(ir_call *ir)
}
ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_discard *ir)
+{
+ return rvalue_visit(ir);
+}
+
+ir_visitor_status
ir_rvalue_visitor::visit_leave(ir_return *ir)
{
return rvalue_visit(ir);
@@ -271,6 +284,12 @@ ir_rvalue_enter_visitor::visit_enter(ir_call *ir)
}
ir_visitor_status
+ir_rvalue_enter_visitor::visit_enter(ir_discard *ir)
+{
+ return rvalue_visit(ir);
+}
+
+ir_visitor_status
ir_rvalue_enter_visitor::visit_enter(ir_return *ir)
{
return rvalue_visit(ir);
diff --git a/mesalib/src/glsl/ir_rvalue_visitor.h b/mesalib/src/glsl/ir_rvalue_visitor.h
index 04ec0fa39..185c72a5b 100644
--- a/mesalib/src/glsl/ir_rvalue_visitor.h
+++ b/mesalib/src/glsl/ir_rvalue_visitor.h
@@ -36,6 +36,7 @@ public:
ir_visitor_status rvalue_visit(ir_call *);
ir_visitor_status rvalue_visit(ir_dereference_array *);
ir_visitor_status rvalue_visit(ir_dereference_record *);
+ ir_visitor_status rvalue_visit(ir_discard *);
ir_visitor_status rvalue_visit(ir_expression *);
ir_visitor_status rvalue_visit(ir_if *);
ir_visitor_status rvalue_visit(ir_return *);
@@ -54,6 +55,7 @@ public:
virtual ir_visitor_status visit_leave(ir_call *);
virtual ir_visitor_status visit_leave(ir_dereference_array *);
virtual ir_visitor_status visit_leave(ir_dereference_record *);
+ virtual ir_visitor_status visit_leave(ir_discard *);
virtual ir_visitor_status visit_leave(ir_expression *);
virtual ir_visitor_status visit_leave(ir_if *);
virtual ir_visitor_status visit_leave(ir_return *);
@@ -70,6 +72,7 @@ public:
virtual ir_visitor_status visit_enter(ir_call *);
virtual ir_visitor_status visit_enter(ir_dereference_array *);
virtual ir_visitor_status visit_enter(ir_dereference_record *);
+ virtual ir_visitor_status visit_enter(ir_discard *);
virtual ir_visitor_status visit_enter(ir_expression *);
virtual ir_visitor_status visit_enter(ir_if *);
virtual ir_visitor_status visit_enter(ir_return *);
diff --git a/mesalib/src/glsl/ir_validate.cpp b/mesalib/src/glsl/ir_validate.cpp
index 667889480..7a7688cb2 100644
--- a/mesalib/src/glsl/ir_validate.cpp
+++ b/mesalib/src/glsl/ir_validate.cpp
@@ -61,6 +61,7 @@ public:
virtual ir_visitor_status visit(ir_variable *v);
virtual ir_visitor_status visit(ir_dereference_variable *ir);
+ virtual ir_visitor_status visit_enter(ir_discard *ir);
virtual ir_visitor_status visit_enter(ir_if *ir);
virtual ir_visitor_status visit_enter(ir_function *ir);
@@ -133,6 +134,20 @@ ir_validate::visit_enter(class ir_dereference_array *ir)
}
ir_visitor_status
+ir_validate::visit_enter(ir_discard *ir)
+{
+ if (ir->condition && ir->condition->type != glsl_type::bool_type) {
+ printf("ir_discard condition %s type instead of bool.\n",
+ ir->condition->type->name);
+ ir->print();
+ printf("\n");
+ abort();
+ }
+
+ return visit_continue;
+}
+
+ir_visitor_status
ir_validate::visit_enter(ir_if *ir)
{
if (ir->condition->type != glsl_type::bool_type) {
diff --git a/mesalib/src/glsl/link_interface_blocks.cpp b/mesalib/src/glsl/link_interface_blocks.cpp
index 0ce502d4f..07f5b4223 100644
--- a/mesalib/src/glsl/link_interface_blocks.cpp
+++ b/mesalib/src/glsl/link_interface_blocks.cpp
@@ -50,18 +50,20 @@ struct interface_block_definition
* represents either the interface instance (for named interfaces), or a
* member of the interface (for unnamed interfaces).
*/
- explicit interface_block_definition(const ir_variable *var)
- : type(var->get_interface_type()),
- instance_name(NULL),
- array_size(-1)
+ explicit interface_block_definition(ir_variable *var)
+ : var(var),
+ type(var->get_interface_type()),
+ instance_name(NULL)
{
if (var->is_interface_instance()) {
instance_name = var->name;
- if (var->type->is_array())
- array_size = var->type->length;
}
explicitly_declared = (var->data.how_declared != ir_var_declared_implicitly);
}
+ /**
+ * Interface block ir_variable
+ */
+ ir_variable *var;
/**
* Interface block type
@@ -74,12 +76,6 @@ struct interface_block_definition
const char *instance_name;
/**
- * For an interface block array, the array size (or 0 if unsized).
- * Otherwise -1.
- */
- int array_size;
-
- /**
* True if this interface block was explicitly declared in the shader;
* false if it was an implicitly declared built-in interface block.
*/
@@ -95,7 +91,8 @@ struct interface_block_definition
bool
intrastage_match(interface_block_definition *a,
const interface_block_definition *b,
- ir_variable_mode mode)
+ ir_variable_mode mode,
+ struct gl_shader_program *prog)
{
/* Types must match. */
if (a->type != b->type) {
@@ -120,18 +117,13 @@ intrastage_match(interface_block_definition *a,
return false;
}
- /* Array vs. nonarray must be consistent, and sizes must be
- * consistent, with the exception that unsized arrays match sized
- * arrays.
+ /* If a block is an array then it must match across the shader.
+ * Unsized arrays are also processed and matched agaist sized arrays.
*/
- if ((a->array_size == -1) != (b->array_size == -1))
+ if (b->var->type != a->var->type &&
+ (b->instance_name != NULL || a->instance_name != NULL) &&
+ !validate_intrastage_arrays(prog, b->var, a->var))
return false;
- if (b->array_size != 0) {
- if (a->array_size == 0)
- a->array_size = b->array_size;
- else if (a->array_size != b->array_size)
- return false;
- }
return true;
}
@@ -153,8 +145,8 @@ interstage_match(const interface_block_definition *producer,
/* Unsized arrays should not occur during interstage linking. They
* should have all been assigned a size by link_intrastage_shaders.
*/
- assert(consumer->array_size != 0);
- assert(producer->array_size != 0);
+ assert(!consumer->var->type->is_unsized_array());
+ assert(!producer->var->type->is_unsized_array());
/* Types must match. */
if (consumer->type != producer->type) {
@@ -165,20 +157,27 @@ interstage_match(const interface_block_definition *producer,
if (consumer->explicitly_declared || producer->explicitly_declared)
return false;
}
+
+ /* Ignore outermost array if geom shader */
+ const glsl_type *consumer_instance_type;
if (extra_array_level) {
- /* Consumer must be an array, and producer must not. */
- if (consumer->array_size == -1)
- return false;
- if (producer->array_size != -1)
- return false;
+ consumer_instance_type = consumer->var->type->fields.array;
} else {
- /* Array vs. nonarray must be consistent, and sizes must be consistent.
- * Since unsized arrays have been ruled out, we can check this by just
- * making sure the sizes are equal.
- */
- if (consumer->array_size != producer->array_size)
+ consumer_instance_type = consumer->var->type;
+ }
+
+ /* If a block is an array then it must match across shaders.
+ * Since unsized arrays have been ruled out, we can check this by just
+ * making sure the types are equal.
+ */
+ if ((consumer->instance_name != NULL &&
+ consumer_instance_type->is_array()) ||
+ (producer->instance_name != NULL &&
+ producer->var->type->is_array())) {
+ if (consumer_instance_type != producer->var->type)
return false;
}
+
return true;
}
@@ -298,7 +297,8 @@ validate_intrastage_interface_blocks(struct gl_shader_program *prog,
*/
definitions->store(def);
} else if (!intrastage_match(prev_def, &def,
- (ir_variable_mode) var->data.mode)) {
+ (ir_variable_mode) var->data.mode,
+ prog)) {
linker_error(prog, "definitions of interface block `%s' do not"
" match\n", iface_type->name);
return;
@@ -374,7 +374,7 @@ validate_interstage_uniform_blocks(struct gl_shader_program *prog,
* uniform matchin rules (for uniforms, it is as though all
* shaders are in the same shader stage).
*/
- if (!intrastage_match(old_def, &new_def, ir_var_uniform)) {
+ if (!intrastage_match(old_def, &new_def, ir_var_uniform, prog)) {
linker_error(prog, "definitions of interface block `%s' do not "
"match\n", var->get_interface_type()->name);
return;
diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp
index 3f5eac1e2..0c4467779 100644
--- a/mesalib/src/glsl/linker.cpp
+++ b/mesalib/src/glsl/linker.cpp
@@ -64,6 +64,7 @@
* \author Ian Romanick <ian.d.romanick@intel.com>
*/
+#include <ctype.h>
#include "main/core.h"
#include "glsl_symbol_table.h"
#include "glsl_parser_extras.h"
@@ -680,6 +681,45 @@ validate_geometry_shader_emissions(struct gl_context *ctx,
}
}
+bool
+validate_intrastage_arrays(struct gl_shader_program *prog,
+ ir_variable *const var,
+ ir_variable *const existing)
+{
+ /* Consider the types to be "the same" if both types are arrays
+ * of the same type and one of the arrays is implicitly sized.
+ * In addition, set the type of the linked variable to the
+ * explicitly sized array.
+ */
+ if (var->type->is_array() && existing->type->is_array() &&
+ (var->type->fields.array == existing->type->fields.array) &&
+ ((var->type->length == 0)|| (existing->type->length == 0))) {
+ if (var->type->length != 0) {
+ if (var->type->length <= existing->data.max_array_access) {
+ linker_error(prog, "%s `%s' declared as type "
+ "`%s' but outermost dimension has an index"
+ " of `%i'\n",
+ mode_string(var),
+ var->name, var->type->name,
+ existing->data.max_array_access);
+ }
+ existing->type = var->type;
+ return true;
+ } else if (existing->type->length != 0) {
+ if(existing->type->length <= var->data.max_array_access) {
+ linker_error(prog, "%s `%s' declared as type "
+ "`%s' but outermost dimension has an index"
+ " of `%i'\n",
+ mode_string(var),
+ var->name, existing->type->name,
+ var->data.max_array_access);
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
/**
* Perform validation of global variables used across multiple shaders
@@ -719,50 +759,23 @@ cross_validate_globals(struct gl_shader_program *prog,
*/
ir_variable *const existing = variables.get_variable(var->name);
if (existing != NULL) {
- if (var->type != existing->type) {
- /* Consider the types to be "the same" if both types are arrays
- * of the same type and one of the arrays is implicitly sized.
- * In addition, set the type of the linked variable to the
- * explicitly sized array.
- */
- if (var->type->is_array()
- && existing->type->is_array()
- && (var->type->fields.array == existing->type->fields.array)
- && ((var->type->length == 0)
- || (existing->type->length == 0))) {
- if (var->type->length != 0) {
- if (var->type->length <= existing->data.max_array_access) {
- linker_error(prog, "%s `%s' declared as type "
- "`%s' but outermost dimension has an index"
- " of `%i'\n",
- mode_string(var),
- var->name, var->type->name,
- existing->data.max_array_access);
- return;
- }
- existing->type = var->type;
- } else if (existing->type->length != 0
- && existing->type->length <=
- var->data.max_array_access) {
+ /* Check if types match. Interface blocks have some special
+ * rules so we handle those elsewhere.
+ */
+ if (var->type != existing->type &&
+ !var->is_interface_instance()) {
+ if (!validate_intrastage_arrays(prog, var, existing)) {
+ if (var->type->is_record() && existing->type->is_record()
+ && existing->type->record_compare(var->type)) {
+ existing->type = var->type;
+ } else {
linker_error(prog, "%s `%s' declared as type "
- "`%s' but outermost dimension has an index"
- " of `%i'\n",
+ "`%s' and type `%s'\n",
mode_string(var),
- var->name, existing->type->name,
- var->data.max_array_access);
+ var->name, var->type->name,
+ existing->type->name);
return;
}
- } else if (var->type->is_record()
- && existing->type->is_record()
- && existing->type->record_compare(var->type)) {
- existing->type = var->type;
- } else {
- linker_error(prog, "%s `%s' declared as type "
- "`%s' and type `%s'\n",
- mode_string(var),
- var->name, var->type->name,
- existing->type->name);
- return;
}
}
diff --git a/mesalib/src/glsl/linker.h b/mesalib/src/glsl/linker.h
index be4da5e0a..ce3dc3232 100644
--- a/mesalib/src/glsl/linker.h
+++ b/mesalib/src/glsl/linker.h
@@ -61,6 +61,11 @@ link_uniform_blocks(void *mem_ctx,
unsigned num_shaders,
struct gl_uniform_block **blocks_ret);
+bool
+validate_intrastage_arrays(struct gl_shader_program *prog,
+ ir_variable *const var,
+ ir_variable *const existing);
+
void
validate_intrastage_interface_blocks(struct gl_shader_program *prog,
const gl_shader **shader_list,
diff --git a/mesalib/src/glsl/loop_controls.cpp b/mesalib/src/glsl/loop_controls.cpp
index 2459fc1c3..d7f0b2809 100644
--- a/mesalib/src/glsl/loop_controls.cpp
+++ b/mesalib/src/glsl/loop_controls.cpp
@@ -123,7 +123,7 @@ calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment,
const int bias[] = { -1, 0, 1 };
bool valid_loop = false;
- for (unsigned i = 0; i < Elements(bias); i++) {
+ for (unsigned i = 0; i < ARRAY_SIZE(bias); i++) {
/* Increment may be of type int, uint or float. */
switch (increment->type->base_type) {
case GLSL_TYPE_INT:
diff --git a/mesalib/src/glsl/lower_discard_flow.cpp b/mesalib/src/glsl/lower_discard_flow.cpp
index 1bc56d79e..ee45bf221 100644
--- a/mesalib/src/glsl/lower_discard_flow.cpp
+++ b/mesalib/src/glsl/lower_discard_flow.cpp
@@ -90,7 +90,14 @@ ir_visitor_status
lower_discard_flow_visitor::visit_enter(ir_discard *ir)
{
ir_dereference *lhs = new(mem_ctx) ir_dereference_variable(discarded);
- ir_rvalue *rhs = new(mem_ctx) ir_constant(true);
+ ir_rvalue *rhs;
+ if (ir->condition) {
+ /* discarded <- condition, use (var_ref discarded) as the condition */
+ rhs = ir->condition;
+ ir->condition = new(mem_ctx) ir_dereference_variable(discarded);
+ } else {
+ rhs = new(mem_ctx) ir_constant(true);
+ }
ir_assignment *assign = new(mem_ctx) ir_assignment(lhs, rhs);
ir->insert_before(assign);
diff --git a/mesalib/src/glsl/lower_instructions.cpp b/mesalib/src/glsl/lower_instructions.cpp
index 4779de059..845cfff36 100644
--- a/mesalib/src/glsl/lower_instructions.cpp
+++ b/mesalib/src/glsl/lower_instructions.cpp
@@ -124,7 +124,7 @@
* Converts double trunc, ceil, floor, round to fract
*/
-#include "main/core.h" /* for M_LOG2E */
+#include "c99_math.h"
#include "program/prog_instruction.h" /* for swizzle */
#include "glsl_types.h"
#include "ir.h"
diff --git a/mesalib/src/glsl/lower_packed_varyings.cpp b/mesalib/src/glsl/lower_packed_varyings.cpp
index 5e844c792..2c9a1c495 100644
--- a/mesalib/src/glsl/lower_packed_varyings.cpp
+++ b/mesalib/src/glsl/lower_packed_varyings.cpp
@@ -146,7 +146,11 @@
#include "glsl_symbol_table.h"
#include "ir.h"
+#include "ir_builder.h"
#include "ir_optimization.h"
+#include "program/prog_instruction.h"
+
+using namespace ir_builder;
namespace {
@@ -163,13 +167,14 @@ public:
lower_packed_varyings_visitor(void *mem_ctx, unsigned locations_used,
ir_variable_mode mode,
unsigned gs_input_vertices,
- exec_list *out_instructions);
+ exec_list *out_instructions,
+ exec_list *out_variables);
void run(exec_list *instructions);
private:
- ir_assignment *bitwise_assign_pack(ir_rvalue *lhs, ir_rvalue *rhs);
- ir_assignment *bitwise_assign_unpack(ir_rvalue *lhs, ir_rvalue *rhs);
+ void bitwise_assign_pack(ir_rvalue *lhs, ir_rvalue *rhs);
+ void bitwise_assign_unpack(ir_rvalue *lhs, ir_rvalue *rhs);
unsigned lower_rvalue(ir_rvalue *rvalue, unsigned fine_location,
ir_variable *unpacked_var, const char *name,
bool gs_input_toplevel, unsigned vertex_index);
@@ -221,13 +226,19 @@ private:
* appropriate place in the shader once the visitor has finished running.
*/
exec_list *out_instructions;
+
+ /**
+ * Exec list into which the visitor should insert any new variables.
+ */
+ exec_list *out_variables;
};
} /* anonymous namespace */
lower_packed_varyings_visitor::lower_packed_varyings_visitor(
void *mem_ctx, unsigned locations_used, ir_variable_mode mode,
- unsigned gs_input_vertices, exec_list *out_instructions)
+ unsigned gs_input_vertices, exec_list *out_instructions,
+ exec_list *out_variables)
: mem_ctx(mem_ctx),
locations_used(locations_used),
packed_varyings((ir_variable **)
@@ -235,7 +246,8 @@ lower_packed_varyings_visitor::lower_packed_varyings_visitor(
locations_used)),
mode(mode),
gs_input_vertices(gs_input_vertices),
- out_instructions(out_instructions)
+ out_instructions(out_instructions),
+ out_variables(out_variables)
{
}
@@ -274,6 +286,7 @@ lower_packed_varyings_visitor::run(exec_list *instructions)
}
}
+#define SWIZZLE_ZWZW MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_Z, SWIZZLE_W)
/**
* Make an ir_assignment from \c rhs to \c lhs, performing appropriate
@@ -281,7 +294,7 @@ lower_packed_varyings_visitor::run(exec_list *instructions)
*
* This function is called when packing varyings.
*/
-ir_assignment *
+void
lower_packed_varyings_visitor::bitwise_assign_pack(ir_rvalue *lhs,
ir_rvalue *rhs)
{
@@ -300,12 +313,28 @@ lower_packed_varyings_visitor::bitwise_assign_pack(ir_rvalue *lhs,
rhs = new(this->mem_ctx)
ir_expression(ir_unop_bitcast_f2i, lhs->type, rhs);
break;
+ case GLSL_TYPE_DOUBLE:
+ assert(rhs->type->vector_elements <= 2);
+ if (rhs->type->vector_elements == 2) {
+ ir_variable *t = new(mem_ctx) ir_variable(lhs->type, "pack", ir_var_temporary);
+
+ assert(lhs->type->vector_elements == 4);
+ this->out_variables->push_tail(t);
+ this->out_instructions->push_tail(
+ assign(t, u2i(expr(ir_unop_unpack_double_2x32, swizzle_x(rhs->clone(mem_ctx, NULL)))), 0x3));
+ this->out_instructions->push_tail(
+ assign(t, u2i(expr(ir_unop_unpack_double_2x32, swizzle_y(rhs))), 0xc));
+ rhs = deref(t).val;
+ } else {
+ rhs = u2i(expr(ir_unop_unpack_double_2x32, rhs));
+ }
+ break;
default:
assert(!"Unexpected type conversion while lowering varyings");
break;
}
}
- return new(this->mem_ctx) ir_assignment(lhs, rhs);
+ this->out_instructions->push_tail(new (this->mem_ctx) ir_assignment(lhs, rhs));
}
@@ -315,7 +344,7 @@ lower_packed_varyings_visitor::bitwise_assign_pack(ir_rvalue *lhs,
*
* This function is called when unpacking varyings.
*/
-ir_assignment *
+void
lower_packed_varyings_visitor::bitwise_assign_unpack(ir_rvalue *lhs,
ir_rvalue *rhs)
{
@@ -334,12 +363,27 @@ lower_packed_varyings_visitor::bitwise_assign_unpack(ir_rvalue *lhs,
rhs = new(this->mem_ctx)
ir_expression(ir_unop_bitcast_i2f, lhs->type, rhs);
break;
+ case GLSL_TYPE_DOUBLE:
+ assert(lhs->type->vector_elements <= 2);
+ if (lhs->type->vector_elements == 2) {
+ ir_variable *t = new(mem_ctx) ir_variable(lhs->type, "unpack", ir_var_temporary);
+ assert(rhs->type->vector_elements == 4);
+ this->out_variables->push_tail(t);
+ this->out_instructions->push_tail(
+ assign(t, expr(ir_unop_pack_double_2x32, i2u(swizzle_xy(rhs->clone(mem_ctx, NULL)))), 0x1));
+ this->out_instructions->push_tail(
+ assign(t, expr(ir_unop_pack_double_2x32, i2u(swizzle(rhs->clone(mem_ctx, NULL), SWIZZLE_ZWZW, 2))), 0x2));
+ rhs = deref(t).val;
+ } else {
+ rhs = expr(ir_unop_pack_double_2x32, i2u(rhs));
+ }
+ break;
default:
assert(!"Unexpected type conversion while lowering varyings");
break;
}
}
- return new(this->mem_ctx) ir_assignment(lhs, rhs);
+ this->out_instructions->push_tail(new(this->mem_ctx) ir_assignment(lhs, rhs));
}
@@ -372,6 +416,7 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue,
bool gs_input_toplevel,
unsigned vertex_index)
{
+ unsigned dmul = rvalue->type->is_double() ? 2 : 1;
/* When gs_input_toplevel is set, we should be looking at a geometry shader
* input array.
*/
@@ -405,17 +450,26 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue,
return this->lower_arraylike(rvalue, rvalue->type->matrix_columns,
fine_location, unpacked_var, name,
false, vertex_index);
- } else if (rvalue->type->vector_elements + fine_location % 4 > 4) {
+ } else if (rvalue->type->vector_elements * dmul +
+ fine_location % 4 > 4) {
/* This vector is going to be "double parked" across two varying slots,
- * so handle it as two separate assignments.
+ * so handle it as two separate assignments. For doubles, a dvec3/dvec4
+ * can end up being spread over 3 slots. However the second splitting
+ * will happen later, here we just always want to split into 2.
*/
- unsigned left_components = 4 - fine_location % 4;
- unsigned right_components
- = rvalue->type->vector_elements - left_components;
+ unsigned left_components, right_components;
unsigned left_swizzle_values[4] = { 0, 0, 0, 0 };
unsigned right_swizzle_values[4] = { 0, 0, 0, 0 };
char left_swizzle_name[4] = { 0, 0, 0, 0 };
char right_swizzle_name[4] = { 0, 0, 0, 0 };
+
+ left_components = 4 - fine_location % 4;
+ if (rvalue->type->is_double()) {
+ /* We might actually end up with 0 left components! */
+ left_components /= 2;
+ }
+ right_components = rvalue->type->vector_elements - left_components;
+
for (unsigned i = 0; i < left_components; i++) {
left_swizzle_values[i] = i;
left_swizzle_name[i] = "xyzw"[i];
@@ -433,9 +487,13 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue,
= ralloc_asprintf(this->mem_ctx, "%s.%s", name, left_swizzle_name);
char *right_name
= ralloc_asprintf(this->mem_ctx, "%s.%s", name, right_swizzle_name);
- fine_location = this->lower_rvalue(left_swizzle, fine_location,
- unpacked_var, left_name, false,
- vertex_index);
+ if (left_components)
+ fine_location = this->lower_rvalue(left_swizzle, fine_location,
+ unpacked_var, left_name, false,
+ vertex_index);
+ else
+ /* Top up the fine location to the next slot */
+ fine_location++;
return this->lower_rvalue(right_swizzle, fine_location, unpacked_var,
right_name, false, vertex_index);
} else {
@@ -443,7 +501,7 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue,
* varying.
*/
unsigned swizzle_values[4] = { 0, 0, 0, 0 };
- unsigned components = rvalue->type->vector_elements;
+ unsigned components = rvalue->type->vector_elements * dmul;
unsigned location = fine_location / 4;
unsigned location_frac = fine_location % 4;
for (unsigned i = 0; i < components; ++i)
@@ -454,13 +512,9 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue,
ir_swizzle *swizzle = new(this->mem_ctx)
ir_swizzle(packed_deref, swizzle_values, components);
if (this->mode == ir_var_shader_out) {
- ir_assignment *assignment
- = this->bitwise_assign_pack(swizzle, rvalue);
- this->out_instructions->push_tail(assignment);
+ this->bitwise_assign_pack(swizzle, rvalue);
} else {
- ir_assignment *assignment
- = this->bitwise_assign_unpack(rvalue, swizzle);
- this->out_instructions->push_tail(assignment);
+ this->bitwise_assign_unpack(rvalue, swizzle);
}
return fine_location + components;
}
@@ -598,7 +652,7 @@ lower_packed_varyings_visitor::needs_lowering(ir_variable *var)
}
if (type->is_array())
type = type->fields.array;
- if (type->vector_elements == 4)
+ if (type->vector_elements == 4 && !type->is_double())
return false;
return true;
}
@@ -657,9 +711,11 @@ lower_packed_varyings(void *mem_ctx, unsigned locations_used,
exec_list void_parameters;
ir_function_signature *main_func_sig
= main_func->matching_signature(NULL, &void_parameters, false);
- exec_list new_instructions;
+ exec_list new_instructions, new_variables;
lower_packed_varyings_visitor visitor(mem_ctx, locations_used, mode,
- gs_input_vertices, &new_instructions);
+ gs_input_vertices,
+ &new_instructions,
+ &new_variables);
visitor.run(instructions);
if (mode == ir_var_shader_out) {
if (shader->Stage == MESA_SHADER_GEOMETRY) {
@@ -667,15 +723,22 @@ lower_packed_varyings(void *mem_ctx, unsigned locations_used,
* to EmitVertex()
*/
lower_packed_varyings_gs_splicer splicer(mem_ctx, &new_instructions);
+
+ /* Add all the variables in first. */
+ main_func_sig->body.head->insert_before(&new_variables);
+
+ /* Now update all the EmitVertex instances */
splicer.run(instructions);
} else {
/* For other shader types, outputs need to be lowered at the end of
* main()
*/
+ main_func_sig->body.append_list(&new_variables);
main_func_sig->body.append_list(&new_instructions);
}
} else {
/* Shader inputs need to be lowered at the beginning of main() */
main_func_sig->body.head->insert_before(&new_instructions);
+ main_func_sig->body.head->insert_before(&new_variables);
}
}
diff --git a/mesalib/src/glsl/nir/glsl_to_nir.cpp b/mesalib/src/glsl/nir/glsl_to_nir.cpp
index 544d0d932..adef19c80 100644
--- a/mesalib/src/glsl/nir/glsl_to_nir.cpp
+++ b/mesalib/src/glsl/nir/glsl_to_nir.cpp
@@ -563,8 +563,14 @@ nir_visitor::visit(ir_discard *ir)
* discards will be immediately followed by a return.
*/
- nir_intrinsic_instr *discard =
- nir_intrinsic_instr_create(this->shader, nir_intrinsic_discard);
+ nir_intrinsic_instr *discard;
+ if (ir->condition) {
+ discard = nir_intrinsic_instr_create(this->shader,
+ nir_intrinsic_discard_if);
+ discard->src[0] = evaluate_rvalue(ir->condition);
+ } else {
+ discard = nir_intrinsic_instr_create(this->shader, nir_intrinsic_discard);
+ }
nir_instr_insert_after_cf_list(this->cf_node_list, &discard->instr);
}
diff --git a/mesalib/src/glsl/nir/nir.c b/mesalib/src/glsl/nir/nir.c
index 5b0e4bc50..ab57fd4e2 100644
--- a/mesalib/src/glsl/nir/nir.c
+++ b/mesalib/src/glsl/nir/nir.c
@@ -63,6 +63,7 @@ reg_create(void *mem_ctx, struct exec_list *list)
{
nir_register *reg = ralloc(mem_ctx, nir_register);
+ reg->parent_instr = NULL;
reg->uses = _mesa_set_create(mem_ctx, _mesa_hash_pointer,
_mesa_key_pointer_equal);
reg->defs = _mesa_set_create(mem_ctx, _mesa_hash_pointer,
diff --git a/mesalib/src/glsl/nir/nir.h b/mesalib/src/glsl/nir/nir.h
index d74caa959..d5df59609 100644
--- a/mesalib/src/glsl/nir/nir.h
+++ b/mesalib/src/glsl/nir/nir.h
@@ -66,6 +66,7 @@ name(const in_type *parent) \
struct nir_function_overload;
struct nir_function;
struct nir_shader;
+struct nir_instr;
/**
@@ -386,6 +387,14 @@ typedef struct {
*/
bool is_packed;
+ /**
+ * If this pointer is non-NULL then this register has exactly one
+ * definition and that definition dominates all of its uses. This is
+ * set by the out-of-SSA pass so that backends can get SSA-like
+ * information even once they have gone out of SSA.
+ */
+ struct nir_instr *parent_instr;
+
/** set of nir_instr's where this register is used (read from) */
struct set *uses;
@@ -408,7 +417,7 @@ typedef enum {
nir_instr_type_parallel_copy,
} nir_instr_type;
-typedef struct {
+typedef struct nir_instr {
struct exec_node node;
nir_instr_type type;
struct nir_block *block;
diff --git a/mesalib/src/glsl/nir/nir_from_ssa.c b/mesalib/src/glsl/nir/nir_from_ssa.c
index 7c5009577..c3090fb06 100644
--- a/mesalib/src/glsl/nir/nir_from_ssa.c
+++ b/mesalib/src/glsl/nir/nir_from_ssa.c
@@ -26,6 +26,7 @@
*/
#include "nir.h"
+#include "nir_vla.h"
/*
* This file implements an out-of-SSA pass as described in "Revisiting
@@ -181,7 +182,7 @@ merge_merge_sets(merge_set *a, merge_set *b)
static bool
merge_sets_interfere(merge_set *a, merge_set *b)
{
- merge_node *dom[a->size + b->size];
+ NIR_VLA(merge_node *, dom, a->size + b->size);
int dom_idx = -1;
struct exec_node *an = exec_list_get_head(&a->nodes);
@@ -508,6 +509,13 @@ get_register_for_ssa_def(nir_ssa_def *def, struct from_ssa_state *state)
reg->num_components = def->num_components;
reg->num_array_elems = 0;
+ /* This register comes from an SSA definition that was not part of a
+ * phi-web. Therefore, we know it has a single unique definition
+ * that dominates all of its uses. Therefore, we can copy the
+ * parent_instr from the SSA def safely.
+ */
+ reg->parent_instr = def->parent_instr;
+
_mesa_hash_table_insert(state->ssa_table, def, reg);
return reg;
}
@@ -666,21 +674,16 @@ resolve_parallel_copy(nir_parallel_copy_instr *pcopy,
}
/* The register/source corresponding to the given index */
- nir_src values[num_copies * 2];
- memset(values, 0, sizeof values);
-
- /* The current location of a given piece of data */
- int loc[num_copies * 2];
+ NIR_VLA_ZERO(nir_src, values, num_copies * 2);
- /* The piece of data that the given piece of data is to be copied from */
- int pred[num_copies * 2];
+ /* The current location of a given piece of data. We will use -1 for "null" */
+ NIR_VLA_FILL(int, loc, num_copies * 2, -1);
- /* Initialize loc and pred. We will use -1 for "null" */
- memset(loc, -1, sizeof loc);
- memset(pred, -1, sizeof pred);
+ /* The piece of data that the given piece of data is to be copied from. We will use -1 for "null" */
+ NIR_VLA_FILL(int, pred, num_copies * 2, -1);
/* The destinations we have yet to properly fill */
- int to_do[num_copies * 2];
+ NIR_VLA(int, to_do, num_copies * 2);
int to_do_idx = -1;
/* Now we set everything up:
@@ -730,7 +733,7 @@ resolve_parallel_copy(nir_parallel_copy_instr *pcopy,
}
/* Currently empty destinations we can go ahead and fill */
- int ready[num_copies * 2];
+ NIR_VLA(int, ready, num_copies * 2);
int ready_idx = -1;
/* Mark the ones that are ready for copying. We know an index is a
diff --git a/mesalib/src/glsl/nir/nir_intrinsics.h b/mesalib/src/glsl/nir/nir_intrinsics.h
index d94866c85..3bf102fc1 100644
--- a/mesalib/src/glsl/nir/nir_intrinsics.h
+++ b/mesalib/src/glsl/nir/nir_intrinsics.h
@@ -68,6 +68,8 @@ INTRINSIC(interp_var_at_offset, 1, ARR(2), true, 0, 1, 0,
#define BARRIER(name) INTRINSIC(name, 0, ARR(), false, 0, 0, 0, 0)
BARRIER(discard)
+/** A conditional discard, with a single boolean source. */
+INTRINSIC(discard_if, 1, ARR(1), false, 0, 0, 0, 0)
INTRINSIC(emit_vertex, 0, ARR(), false, 0, 0, 1, 0)
INTRINSIC(end_primitive, 0, ARR(), false, 0, 0, 1, 0)
diff --git a/mesalib/src/glsl/nir/nir_live_variables.c b/mesalib/src/glsl/nir/nir_live_variables.c
index 7402dc087..1c96dcf36 100644
--- a/mesalib/src/glsl/nir/nir_live_variables.c
+++ b/mesalib/src/glsl/nir/nir_live_variables.c
@@ -26,6 +26,7 @@
#include "nir.h"
#include "nir_worklist.h"
+#include "nir_vla.h"
/*
* Basic liveness analysis. This works only in SSA form.
@@ -130,8 +131,8 @@ static bool
propagate_across_edge(nir_block *pred, nir_block *succ,
struct live_variables_state *state)
{
- BITSET_WORD live[state->bitset_words];
- memcpy(live, succ->live_in, sizeof live);
+ NIR_VLA(BITSET_WORD, live, state->bitset_words);
+ memcpy(live, succ->live_in, state->bitset_words * sizeof *live);
nir_foreach_instr(succ, instr) {
if (instr->type != nir_instr_type_phi)
diff --git a/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c b/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c
index 8af753029..9e9a418e3 100644
--- a/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c
+++ b/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c
@@ -26,6 +26,8 @@
*/
#include "nir.h"
+#include "nir_vla.h"
+
struct deref_node {
struct deref_node *parent;
@@ -899,8 +901,8 @@ rename_variables_block(nir_block *block, struct lower_variables_state *state)
static void
insert_phi_nodes(struct lower_variables_state *state)
{
- unsigned work[state->impl->num_blocks];
- unsigned has_already[state->impl->num_blocks];
+ NIR_VLA_ZERO(unsigned, work, state->impl->num_blocks);
+ NIR_VLA_ZERO(unsigned, has_already, state->impl->num_blocks);
/*
* Since the work flags already prevent us from inserting a node that has
@@ -910,10 +912,7 @@ insert_phi_nodes(struct lower_variables_state *state)
* function. So all we need to handle W is an array and a pointer to the
* next element to be inserted and the next element to be removed.
*/
- nir_block *W[state->impl->num_blocks];
-
- memset(work, 0, sizeof work);
- memset(has_already, 0, sizeof has_already);
+ NIR_VLA(nir_block *, W, state->impl->num_blocks);
unsigned w_start, w_end;
unsigned iter_count = 0;
diff --git a/mesalib/src/glsl/nir/nir_opt_copy_propagate.c b/mesalib/src/glsl/nir/nir_opt_copy_propagate.c
index dd0ec01ef..ee78e5aa0 100644
--- a/mesalib/src/glsl/nir/nir_opt_copy_propagate.c
+++ b/mesalib/src/glsl/nir/nir_opt_copy_propagate.c
@@ -53,22 +53,6 @@ static bool is_move(nir_alu_instr *instr)
}
-static bool
-is_swizzleless_move(nir_alu_instr *instr)
-{
- if (!is_move(instr))
- return false;
-
- for (unsigned i = 0; i < 4; i++) {
- if (!((instr->dest.write_mask >> i) & 1))
- break;
- if (instr->src[0].swizzle[i] != i)
- return false;
- }
-
- return true;
-}
-
static bool is_vec(nir_alu_instr *instr)
{
for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++)
@@ -80,6 +64,35 @@ static bool is_vec(nir_alu_instr *instr)
instr->op == nir_op_vec4;
}
+static bool
+is_swizzleless_move(nir_alu_instr *instr)
+{
+ if (is_move(instr)) {
+ for (unsigned i = 0; i < 4; i++) {
+ if (!((instr->dest.write_mask >> i) & 1))
+ break;
+ if (instr->src[0].swizzle[i] != i)
+ return false;
+ }
+ return true;
+ } else if (is_vec(instr)) {
+ nir_ssa_def *def = NULL;
+ for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs; i++) {
+ if (instr->src[i].swizzle[0] != i)
+ return false;
+
+ if (def == NULL) {
+ def = instr->src[i].src.ssa;
+ } else if (instr->src[i].src.ssa != def) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
typedef struct {
nir_ssa_def *def;
bool found;
diff --git a/mesalib/src/glsl/nir/nir_opt_gcm.c b/mesalib/src/glsl/nir/nir_opt_gcm.c
index bf565b969..b4f5fd3d5 100644
--- a/mesalib/src/glsl/nir/nir_opt_gcm.c
+++ b/mesalib/src/glsl/nir/nir_opt_gcm.c
@@ -121,9 +121,11 @@ gcm_pin_instructions_block(nir_block *block, void *void_state)
case nir_op_fddy_coarse:
/* These can only go in uniform control flow; pin them for now */
instr->pass_flags = GCM_INSTR_PINNED;
+ break;
default:
instr->pass_flags = 0;
+ break;
}
break;
@@ -134,9 +136,11 @@ gcm_pin_instructions_block(nir_block *block, void *void_state)
case nir_texop_lod:
/* These two take implicit derivatives so they need to be pinned */
instr->pass_flags = GCM_INSTR_PINNED;
+ break;
default:
instr->pass_flags = 0;
+ break;
}
break;
diff --git a/mesalib/src/glsl/nir/nir_vla.h b/mesalib/src/glsl/nir/nir_vla.h
new file mode 100644
index 000000000..753783316
--- /dev/null
+++ b/mesalib/src/glsl/nir/nir_vla.h
@@ -0,0 +1,54 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#pragma once
+
+
+#include "c99_alloca.h"
+
+
+/* Declare a variable length array, with no initialization */
+#define NIR_VLA(_type, _name, _length) \
+ _type *_name = alloca((_length) * sizeof *_name)
+
+
+/* Declare a variable length array, and initialize it with the given byte.
+ *
+ * _length is evaluated twice, so expressions with side-effects must be
+ * avoided.
+ */
+#define NIR_VLA_FILL(_type, _name, _length, _byte) \
+ _type *_name = memset(alloca((_length) * sizeof *_name), _byte, (_length) * sizeof *_name)
+
+
+/* Declare a variable length array, and zero it.
+ *
+ * Just like NIR_VLA_FILL, _length is evaluated twice, so expressions with
+ * side-effects must be avoided.
+ */
+#define NIR_VLA_ZERO(_type, _name, _length) \
+ NIR_VLA_FILL(_type, _name, _length, 0)
diff --git a/mesalib/src/glsl/opt_algebraic.cpp b/mesalib/src/glsl/opt_algebraic.cpp
index 6784242ff..c6040bff8 100644
--- a/mesalib/src/glsl/opt_algebraic.cpp
+++ b/mesalib/src/glsl/opt_algebraic.cpp
@@ -744,48 +744,65 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
* a saturate operation
*/
for (int op = 0; op < 2; op++) {
- ir_expression *minmax = op_expr[op];
+ ir_expression *inner_expr = op_expr[op];
ir_constant *outer_const = op_const[1 - op];
ir_expression_operation op_cond = (ir->operation == ir_binop_max) ?
ir_binop_min : ir_binop_max;
- if (!minmax || !outer_const || (minmax->operation != op_cond))
+ if (!inner_expr || !outer_const || (inner_expr->operation != op_cond))
continue;
+ /* One of these has to be a constant */
+ if (!inner_expr->operands[0]->as_constant() &&
+ !inner_expr->operands[1]->as_constant())
+ break;
+
/* Found a min(max) combination. Now try to see if its operands
* meet our conditions that we can do just a single saturate operation
*/
for (int minmax_op = 0; minmax_op < 2; minmax_op++) {
- ir_rvalue *inner_val_a = minmax->operands[minmax_op];
- ir_rvalue *inner_val_b = minmax->operands[1 - minmax_op];
+ ir_rvalue *x = inner_expr->operands[minmax_op];
+ ir_rvalue *y = inner_expr->operands[1 - minmax_op];
- if (!inner_val_a || !inner_val_b)
+ ir_constant *inner_const = y->as_constant();
+ if (!inner_const)
continue;
- /* Found a {min|max} ({max|min} (x, 0.0), 1.0) operation and its variations */
- if ((outer_const->is_one() && inner_val_a->is_zero()) ||
- (inner_val_a->is_one() && outer_const->is_zero()))
- return saturate(inner_val_b);
-
- /* Found a {min|max} ({max|min} (x, 0.0), b) where b < 1.0
- * and its variations
- */
- if (is_less_than_one(outer_const) && inner_val_b->is_zero())
- return expr(ir_binop_min, saturate(inner_val_a), outer_const);
-
- if (!inner_val_b->as_constant())
- continue;
-
- if (is_less_than_one(inner_val_b->as_constant()) && outer_const->is_zero())
- return expr(ir_binop_min, saturate(inner_val_a), inner_val_b);
-
- /* Found a {min|max} ({max|min} (x, b), 1.0), where b > 0.0
- * and its variations
- */
- if (outer_const->is_one() && is_greater_than_zero(inner_val_b->as_constant()))
- return expr(ir_binop_max, saturate(inner_val_a), inner_val_b);
- if (inner_val_b->as_constant()->is_one() && is_greater_than_zero(outer_const))
- return expr(ir_binop_max, saturate(inner_val_a), outer_const);
+ /* min(max(x, 0.0), 1.0) is sat(x) */
+ if (ir->operation == ir_binop_min &&
+ inner_const->is_zero() &&
+ outer_const->is_one())
+ return saturate(x);
+
+ /* max(min(x, 1.0), 0.0) is sat(x) */
+ if (ir->operation == ir_binop_max &&
+ inner_const->is_one() &&
+ outer_const->is_zero())
+ return saturate(x);
+
+ /* min(max(x, 0.0), b) where b < 1.0 is sat(min(x, b)) */
+ if (ir->operation == ir_binop_min &&
+ inner_const->is_zero() &&
+ is_less_than_one(outer_const))
+ return saturate(expr(ir_binop_min, x, outer_const));
+
+ /* max(min(x, b), 0.0) where b < 1.0 is sat(min(x, b)) */
+ if (ir->operation == ir_binop_max &&
+ is_less_than_one(inner_const) &&
+ outer_const->is_zero())
+ return saturate(expr(ir_binop_min, x, inner_const));
+
+ /* max(min(x, 1.0), b) where b > 0.0 is sat(max(x, b)) */
+ if (ir->operation == ir_binop_max &&
+ inner_const->is_one() &&
+ is_greater_than_zero(outer_const))
+ return saturate(expr(ir_binop_max, x, outer_const));
+
+ /* min(max(x, b), 1.0) where b > 0.0 is sat(max(x, b)) */
+ if (ir->operation == ir_binop_min &&
+ is_greater_than_zero(inner_const) &&
+ outer_const->is_one())
+ return saturate(expr(ir_binop_max, x, inner_const));
}
}
@@ -849,6 +866,7 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
one = new(mem_ctx) ir_constant(1.0, op2_components);
break;
default:
+ one = NULL;
unreachable("unexpected type");
}
diff --git a/mesalib/src/glsl/opt_conditional_discard.cpp b/mesalib/src/glsl/opt_conditional_discard.cpp
new file mode 100644
index 000000000..8a3ad2487
--- /dev/null
+++ b/mesalib/src/glsl/opt_conditional_discard.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file opt_conditional_discard.cpp
+ *
+ * Replace
+ *
+ * if (cond) discard;
+ *
+ * with
+ *
+ * (discard <condition>)
+ */
+
+#include "glsl_types.h"
+#include "ir.h"
+
+namespace {
+
+class opt_conditional_discard_visitor : public ir_hierarchical_visitor {
+public:
+ opt_conditional_discard_visitor()
+ {
+ progress = false;
+ }
+
+ ir_visitor_status visit_leave(ir_if *);
+
+ bool progress;
+};
+
+} /* anonymous namespace */
+
+bool
+opt_conditional_discard(exec_list *instructions)
+{
+ opt_conditional_discard_visitor v;
+ v.run(instructions);
+ return v.progress;
+}
+
+ir_visitor_status
+opt_conditional_discard_visitor::visit_leave(ir_if *ir)
+{
+ /* Look for "if (...) discard" with no else clause or extra statements. */
+ if (ir->then_instructions.is_empty() ||
+ !ir->then_instructions.head->next->is_tail_sentinel() ||
+ !((ir_instruction *) ir->then_instructions.head)->as_discard() ||
+ !ir->else_instructions.is_empty())
+ return visit_continue;
+
+ /* Move the condition and replace the ir_if with the ir_discard. */
+ ir_discard *discard = (ir_discard *) ir->then_instructions.head;
+ discard->condition = ir->condition;
+ ir->replace_with(discard);
+
+ progress = true;
+
+ return visit_continue;
+}
diff --git a/mesalib/src/glsl/opt_constant_folding.cpp b/mesalib/src/glsl/opt_constant_folding.cpp
index 74b855e5e..4aae3f0dd 100644
--- a/mesalib/src/glsl/opt_constant_folding.cpp
+++ b/mesalib/src/glsl/opt_constant_folding.cpp
@@ -50,6 +50,7 @@ public:
/* empty */
}
+ virtual ir_visitor_status visit_enter(ir_discard *ir);
virtual ir_visitor_status visit_enter(ir_assignment *ir);
virtual ir_visitor_status visit_enter(ir_call *ir);
@@ -94,6 +95,29 @@ ir_constant_folding_visitor::handle_rvalue(ir_rvalue **rvalue)
}
ir_visitor_status
+ir_constant_folding_visitor::visit_enter(ir_discard *ir)
+{
+ if (ir->condition) {
+ ir->condition->accept(this);
+ handle_rvalue(&ir->condition);
+
+ ir_constant *const_val = ir->condition->as_constant();
+ /* If the condition is constant, either remove the condition or
+ * remove the never-executed assignment.
+ */
+ if (const_val) {
+ if (const_val->value.b[0])
+ ir->condition = NULL;
+ else
+ ir->remove();
+ this->progress = true;
+ }
+ }
+
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
ir_constant_folding_visitor::visit_enter(ir_assignment *ir)
{
ir->rhs->accept(this);
diff --git a/mesalib/src/glsl/s_expression.cpp b/mesalib/src/glsl/s_expression.cpp
index 2928a4db8..7eaa491e2 100644
--- a/mesalib/src/glsl/s_expression.cpp
+++ b/mesalib/src/glsl/s_expression.cpp
@@ -24,6 +24,7 @@
#include <assert.h>
#include <limits>
+#include <stdio.h>
#include "s_expression.h"
s_symbol::s_symbol(const char *str, size_t n)
diff --git a/mesalib/src/glsl/s_expression.h b/mesalib/src/glsl/s_expression.h
index 1d4753530..f0dffb1b2 100644
--- a/mesalib/src/glsl/s_expression.h
+++ b/mesalib/src/glsl/s_expression.h
@@ -39,8 +39,8 @@
#define SX_AS_INT(x) SX_AS_(int, x)
/* Pattern matching macros */
-#define MATCH(list, pat) s_match(list, Elements(pat), pat, false)
-#define PARTIAL_MATCH(list, pat) s_match(list, Elements(pat), pat, true)
+#define MATCH(list, pat) s_match(list, ARRAY_SIZE(pat), pat, false)
+#define PARTIAL_MATCH(list, pat) s_match(list, ARRAY_SIZE(pat), pat, true)
/* For our purposes, S-Expressions are:
* - <int>
diff --git a/mesalib/src/glsl/standalone_scaffolding.cpp b/mesalib/src/glsl/standalone_scaffolding.cpp
index ad0d75bf8..6f5a27f85 100644
--- a/mesalib/src/glsl/standalone_scaffolding.cpp
+++ b/mesalib/src/glsl/standalone_scaffolding.cpp
@@ -30,6 +30,7 @@
#include "standalone_scaffolding.h"
#include <assert.h>
+#include <stdio.h>
#include <string.h>
#include "util/ralloc.h"