diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2014-07-09 20:35:21 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2014-07-09 20:35:21 +0000 |
commit | 90414e9e8766ee4a4f0ba93d8206de27cf984ce6 (patch) | |
tree | 83dd43b1cace3aa9d449e272b195871441746ae8 /dist/Mesa/src/glsl | |
parent | 417af3adbc72ea5a850bad6c0490b7b0f2424a38 (diff) |
Import Mesa 10.2.3
Diffstat (limited to 'dist/Mesa/src/glsl')
125 files changed, 11207 insertions, 1714 deletions
diff --git a/dist/Mesa/src/glsl/Android.gen.mk b/dist/Mesa/src/glsl/Android.gen.mk index 2ed9fa64b..7ec56d4f2 100644 --- a/dist/Mesa/src/glsl/Android.gen.mk +++ b/dist/Mesa/src/glsl/Android.gen.mk @@ -35,10 +35,6 @@ sources := \ glcpp/glcpp-lex.c \ glcpp/glcpp-parse.c -ifneq ($(LOCAL_IS_HOST_MODULE),true) -sources += builtin_function.cpp -endif - LOCAL_SRC_FILES := $(filter-out $(sources), $(LOCAL_SRC_FILES)) LOCAL_C_INCLUDES += $(intermediates) $(intermediates)/glcpp $(MESA_TOP)/src/glsl/glcpp @@ -81,18 +77,3 @@ $(intermediates)/glcpp/glcpp-lex.c: $(LOCAL_PATH)/glcpp/glcpp-lex.l $(intermediates)/glcpp/glcpp-parse.c: $(LOCAL_PATH)/glcpp/glcpp-parse.y $(call glsl_local-y-to-c-and-h) - -BUILTIN_COMPILER := $(BUILD_OUT_EXECUTABLES)/mesa_builtin_compiler$(BUILD_EXECUTABLE_SUFFIX) - -builtin_function_deps := \ - $(LOCAL_PATH)/builtins/tools/generate_builtins.py \ - $(LOCAL_PATH)/builtins/tools/texture_builtins.py \ - $(BUILTIN_COMPILER) \ - $(wildcard $(LOCAL_PATH)/builtins/profiles/*) \ - $(wildcard $(LOCAL_PATH)/builtins/ir/*) - -$(intermediates)/builtin_function.cpp: PRIVATE_SCRIPT := $(MESA_PYTHON2) $(LOCAL_PATH)/builtins/tools/generate_builtins.py -$(intermediates)/builtin_function.cpp: $(builtin_function_deps) - @mkdir -p $(dir $@) - @echo "Gen GLSL: $(PRIVATE_MODULE) <= $(notdir $@)" - $(hide) $(PRIVATE_SCRIPT) $(BUILTIN_COMPILER) > $@ || rm -f $@ diff --git a/dist/Mesa/src/glsl/Android.mk b/dist/Mesa/src/glsl/Android.mk index f088e67cb..8a3942652 100644 --- a/dist/Mesa/src/glsl/Android.mk +++ b/dist/Mesa/src/glsl/Android.mk @@ -50,32 +50,6 @@ include $(MESA_COMMON_MK) include $(BUILD_STATIC_LIBRARY) # --------------------------------------- -# Build mesa_builtin_compiler for host -# --------------------------------------- - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - $(LIBGLCPP_FILES) \ - $(LIBGLSL_FILES) \ - $(BUILTIN_COMPILER_CXX_FILES) \ - $(GLSL_COMPILER_CXX_FILES) - -LOCAL_C_INCLUDES := \ - $(MESA_TOP)/src/mapi \ - $(MESA_TOP)/src/mesa - -LOCAL_STATIC_LIBRARIES := libmesa_glsl_utils - -LOCAL_MODULE := mesa_builtin_compiler - -LOCAL_MODULE_CLASS := EXECUTABLES -LOCAL_IS_HOST_MODULE := true -include $(LOCAL_PATH)/Android.gen.mk -include $(MESA_COMMON_MK) -include $(BUILD_HOST_EXECUTABLE) - -# --------------------------------------- # Build glsl_compiler # --------------------------------------- diff --git a/dist/Mesa/src/glsl/Makefile.am b/dist/Mesa/src/glsl/Makefile.am index 2bbad3d65..fd0e837d1 100644 --- a/dist/Mesa/src/glsl/Makefile.am +++ b/dist/Mesa/src/glsl/Makefile.am @@ -19,8 +19,6 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -SUBDIRS = builtin_compiler - AM_CPPFLAGS = \ -I$(top_srcdir)/include \ -I$(top_srcdir)/src/mapi \ @@ -34,8 +32,10 @@ AM_CXXFLAGS = $(VISIBILITY_CXXFLAGS) include Makefile.sources TESTS = glcpp/tests/glcpp-test \ + tests/general-ir-test \ tests/optimization-test \ tests/ralloc-test \ + tests/sampler-types-test \ tests/uniform-initializer-test TESTS_ENVIRONMENT= \ @@ -46,9 +46,31 @@ noinst_LTLIBRARIES = libglsl.la libglcpp.la check_PROGRAMS = \ glcpp/glcpp \ glsl_test \ + tests/general-ir-test \ tests/ralloc-test \ + tests/sampler-types-test \ tests/uniform-initializer-test +noinst_PROGRAMS = glsl_compiler + +tests_general_ir_test_SOURCES = \ + $(top_srcdir)/src/mesa/main/hash_table.c \ + $(top_srcdir)/src/mesa/main/imports.c \ + $(top_srcdir)/src/mesa/program/prog_hash_table.c\ + $(top_srcdir)/src/mesa/program/symbol_table.c \ + $(GLSL_SRCDIR)/standalone_scaffolding.cpp \ + tests/builtin_variable_test.cpp \ + tests/invalidate_locations_test.cpp \ + tests/general_ir_test.cpp \ + tests/varyings_test.cpp \ + tests/common.c +tests_general_ir_test_CFLAGS = \ + $(PTHREAD_CFLAGS) +tests_general_ir_test_LDADD = \ + $(top_builddir)/src/gtest/libgtest.la \ + $(top_builddir)/src/glsl/libglsl.la \ + $(PTHREAD_LIBS) + tests_uniform_initializer_test_SOURCES = \ $(top_srcdir)/src/mesa/main/hash_table.c \ $(top_srcdir)/src/mesa/main/imports.c \ @@ -56,7 +78,8 @@ tests_uniform_initializer_test_SOURCES = \ $(top_srcdir)/src/mesa/program/symbol_table.c \ tests/copy_constant_to_storage_tests.cpp \ tests/set_uniform_initializer_tests.cpp \ - tests/uniform_initializer_utils.cpp + tests/uniform_initializer_utils.cpp \ + tests/common.c tests_uniform_initializer_test_CFLAGS = \ $(PTHREAD_CFLAGS) tests_uniform_initializer_test_LDADD = \ @@ -72,31 +95,46 @@ tests_ralloc_test_LDADD = \ $(top_builddir)/src/gtest/libgtest.la \ $(PTHREAD_LIBS) -if CROSS_COMPILING +tests_sampler_types_test_SOURCES = \ + $(top_srcdir)/src/mesa/program/prog_hash_table.c\ + $(top_srcdir)/src/mesa/program/symbol_table.c \ + tests/sampler_types_test.cpp \ + tests/common.c +tests_sampler_types_test_CFLAGS = \ + $(PTHREAD_CFLAGS) +tests_sampler_types_test_LDADD = \ + $(top_builddir)/src/gtest/libgtest.la \ + $(top_builddir)/src/glsl/libglsl.la \ + $(PTHREAD_LIBS) + libglcpp_la_SOURCES = \ glcpp/glcpp-lex.c \ glcpp/glcpp-parse.c \ $(LIBGLCPP_FILES) -else -libglcpp_la_LIBADD = builtin_compiler/libglcpp.la -endif glcpp_glcpp_SOURCES = \ glcpp/glcpp.c \ $(top_srcdir)/src/mesa/program/prog_hash_table.c -glcpp_glcpp_LDADD = libglcpp.la +glcpp_glcpp_LDADD = \ + libglcpp.la \ + -lm -libglsl_la_SOURCES = builtin_function.cpp libglsl_la_LIBADD = libglcpp.la -if CROSS_COMPILING -libglsl_la_SOURCES += \ +libglsl_la_SOURCES = \ glsl_lexer.cpp \ glsl_parser.cpp \ $(LIBGLSL_FILES) -else -libglsl_la_LIBADD += \ - builtin_compiler/libglslcore.la -endif + +glsl_compiler_SOURCES = \ + $(top_srcdir)/src/mesa/main/hash_table.c \ + $(top_srcdir)/src/mesa/main/imports.c \ + $(top_srcdir)/src/mesa/program/prog_hash_table.c \ + $(top_srcdir)/src/mesa/program/symbol_table.c \ + $(GLSL_COMPILER_CXX_FILES) + +glsl_compiler_LDADD = \ + libglsl.la \ + $(PTHREAD_LIBS) glsl_test_SOURCES = \ $(top_srcdir)/src/mesa/main/hash_table.c \ @@ -104,6 +142,7 @@ glsl_test_SOURCES = \ $(top_srcdir)/src/mesa/program/prog_hash_table.c \ $(top_srcdir)/src/mesa/program/symbol_table.c \ $(GLSL_SRCDIR)/standalone_scaffolding.cpp \ + tests/common.c \ test.cpp \ test_optpass.cpp @@ -146,11 +185,11 @@ glsl_lexer.cpp: glsl_lexer.ll $(AM_V_LEX) $(LEX) $(LFLAGS) -o $@ $< glcpp/glcpp-parse.c glcpp/glcpp-parse.h: glcpp/glcpp-parse.y - $(MKDIR_P) $(GLSL_BUILDDIR)/glcpp + $(AM_V_at)$(MKDIR_P) glcpp $(AM_V_YACC) $(YACC) $(YFLAGS) -o $@ -p "glcpp_parser_" --defines=$(GLSL_BUILDDIR)/glcpp/glcpp-parse.h $< glcpp/glcpp-lex.c: glcpp/glcpp-lex.l - $(MKDIR_P) $(GLSL_BUILDDIR)/glcpp + $(AM_V_at)$(MKDIR_P) glcpp $(AM_V_LEX) $(LEX) $(LFLAGS) -o $@ $< # Only the parsers (specifically the header files generated at the same time) @@ -168,6 +207,3 @@ CLEANFILES = \ glcpp/glcpp-parse.h \ glsl_parser.h \ $(BUILT_SOURCES) - -builtin_function.cpp: $(srcdir)/builtins/profiles/* $(srcdir)/builtins/ir/* $(srcdir)/builtins/glsl/* $(srcdir)/builtins/tools/generate_builtins.py $(srcdir)/builtins/tools/texture_builtins.py $(builddir)/builtin_compiler/builtin_compiler$(BUILD_EXEEXT) - $(AM_V_GEN) $(PYTHON2) $(PYTHON_FLAGS) $(srcdir)/builtins/tools/generate_builtins.py $(builddir)/builtin_compiler/builtin_compiler$(BUILD_EXEEXT) > builtin_function.cpp || rm -f builtin_function.cpp diff --git a/dist/Mesa/src/glsl/Makefile.in b/dist/Mesa/src/glsl/Makefile.in index 022aae477..d6c26d132 100644 --- a/dist/Mesa/src/glsl/Makefile.in +++ b/dist/Mesa/src/glsl/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.14 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -37,6 +37,7 @@ # shared source lists for Makefile, SConscript, and Android.mk + VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ @@ -105,146 +106,60 @@ target_triplet = @target@ DIST_COMMON = $(srcdir)/Makefile.sources $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/bin/depcomp \ $(top_srcdir)/bin/test-driver README TODO -TESTS = glcpp/tests/glcpp-test tests/optimization-test \ - tests/ralloc-test$(EXEEXT) \ +TESTS = glcpp/tests/glcpp-test tests/general-ir-test$(EXEEXT) \ + tests/optimization-test tests/ralloc-test$(EXEEXT) \ + tests/sampler-types-test$(EXEEXT) \ tests/uniform-initializer-test$(EXEEXT) check_PROGRAMS = glcpp/glcpp$(EXEEXT) glsl_test$(EXEEXT) \ - tests/ralloc-test$(EXEEXT) \ + tests/general-ir-test$(EXEEXT) tests/ralloc-test$(EXEEXT) \ + tests/sampler-types-test$(EXEEXT) \ tests/uniform-initializer-test$(EXEEXT) -@CROSS_COMPILING_TRUE@am__append_1 = \ -@CROSS_COMPILING_TRUE@ glsl_lexer.cpp \ -@CROSS_COMPILING_TRUE@ glsl_parser.cpp \ -@CROSS_COMPILING_TRUE@ $(LIBGLSL_FILES) - -@CROSS_COMPILING_FALSE@am__append_2 = \ -@CROSS_COMPILING_FALSE@ builtin_compiler/libglslcore.la - +noinst_PROGRAMS = glsl_compiler$(EXEEXT) subdir = src/glsl ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/ax_prog_bison.m4 \ - $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ - $(top_srcdir)/m4/ax_prog_cxx_for_build.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_gcc_builtin.m4 \ + $(top_srcdir)/m4/ax_prog_bison.m4 \ $(top_srcdir)/m4/ax_prog_flex.m4 \ - $(top_srcdir)/m4/ax_pthread.m4 \ - $(top_srcdir)/m4/ax_python_module.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac + $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/VERSION $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) -@CROSS_COMPILING_FALSE@libglcpp_la_DEPENDENCIES = \ -@CROSS_COMPILING_FALSE@ builtin_compiler/libglcpp.la -am__libglcpp_la_SOURCES_DIST = glcpp/glcpp-lex.c glcpp/glcpp-parse.c \ - $(GLSL_SRCDIR)/ralloc.c $(GLSL_SRCDIR)/glcpp/pp.c +libglcpp_la_LIBADD = am__objects_1 = ralloc.lo pp.lo -@CROSS_COMPILING_TRUE@am_libglcpp_la_OBJECTS = glcpp-lex.lo \ -@CROSS_COMPILING_TRUE@ glcpp-parse.lo $(am__objects_1) +am_libglcpp_la_OBJECTS = glcpp-lex.lo glcpp-parse.lo $(am__objects_1) libglcpp_la_OBJECTS = $(am_libglcpp_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = -libglsl_la_DEPENDENCIES = libglcpp.la $(am__append_2) -am__libglsl_la_SOURCES_DIST = builtin_function.cpp glsl_lexer.cpp \ - glsl_parser.cpp $(GLSL_SRCDIR)/ast_array_index.cpp \ - $(GLSL_SRCDIR)/ast_expr.cpp $(GLSL_SRCDIR)/ast_function.cpp \ - $(GLSL_SRCDIR)/ast_to_hir.cpp $(GLSL_SRCDIR)/ast_type.cpp \ - $(GLSL_SRCDIR)/builtin_types.cpp \ - $(GLSL_SRCDIR)/builtin_variables.cpp \ - $(GLSL_SRCDIR)/glsl_parser_extras.cpp \ - $(GLSL_SRCDIR)/glsl_types.cpp \ - $(GLSL_SRCDIR)/glsl_symbol_table.cpp \ - $(GLSL_SRCDIR)/hir_field_selection.cpp \ - $(GLSL_SRCDIR)/ir_basic_block.cpp \ - $(GLSL_SRCDIR)/ir_builder.cpp $(GLSL_SRCDIR)/ir_clone.cpp \ - $(GLSL_SRCDIR)/ir_constant_expression.cpp \ - $(GLSL_SRCDIR)/ir.cpp \ - $(GLSL_SRCDIR)/ir_expression_flattening.cpp \ - $(GLSL_SRCDIR)/ir_function_can_inline.cpp \ - $(GLSL_SRCDIR)/ir_function_detect_recursion.cpp \ - $(GLSL_SRCDIR)/ir_function.cpp \ - $(GLSL_SRCDIR)/ir_hierarchical_visitor.cpp \ - $(GLSL_SRCDIR)/ir_hv_accept.cpp \ - $(GLSL_SRCDIR)/ir_import_prototypes.cpp \ - $(GLSL_SRCDIR)/ir_print_visitor.cpp \ - $(GLSL_SRCDIR)/ir_reader.cpp \ - $(GLSL_SRCDIR)/ir_rvalue_visitor.cpp \ - $(GLSL_SRCDIR)/ir_set_program_inouts.cpp \ - $(GLSL_SRCDIR)/ir_validate.cpp \ - $(GLSL_SRCDIR)/ir_variable_refcount.cpp \ - $(GLSL_SRCDIR)/linker.cpp $(GLSL_SRCDIR)/link_functions.cpp \ - $(GLSL_SRCDIR)/link_interface_blocks.cpp \ - $(GLSL_SRCDIR)/link_uniforms.cpp \ - $(GLSL_SRCDIR)/link_uniform_initializers.cpp \ - $(GLSL_SRCDIR)/link_uniform_block_active_visitor.cpp \ - $(GLSL_SRCDIR)/link_uniform_blocks.cpp \ - $(GLSL_SRCDIR)/link_varyings.cpp \ - $(GLSL_SRCDIR)/loop_analysis.cpp \ - $(GLSL_SRCDIR)/loop_controls.cpp \ - $(GLSL_SRCDIR)/loop_unroll.cpp \ - $(GLSL_SRCDIR)/lower_clip_distance.cpp \ - $(GLSL_SRCDIR)/lower_discard.cpp \ - $(GLSL_SRCDIR)/lower_discard_flow.cpp \ - $(GLSL_SRCDIR)/lower_if_to_cond_assign.cpp \ - $(GLSL_SRCDIR)/lower_instructions.cpp \ - $(GLSL_SRCDIR)/lower_jumps.cpp \ - $(GLSL_SRCDIR)/lower_mat_op_to_vec.cpp \ - $(GLSL_SRCDIR)/lower_noise.cpp \ - $(GLSL_SRCDIR)/lower_packed_varyings.cpp \ - $(GLSL_SRCDIR)/lower_named_interface_blocks.cpp \ - $(GLSL_SRCDIR)/lower_packing_builtins.cpp \ - $(GLSL_SRCDIR)/lower_texture_projection.cpp \ - $(GLSL_SRCDIR)/lower_variable_index_to_cond_assign.cpp \ - $(GLSL_SRCDIR)/lower_vec_index_to_cond_assign.cpp \ - $(GLSL_SRCDIR)/lower_vec_index_to_swizzle.cpp \ - $(GLSL_SRCDIR)/lower_vector.cpp \ - $(GLSL_SRCDIR)/lower_vector_insert.cpp \ - $(GLSL_SRCDIR)/lower_output_reads.cpp \ - $(GLSL_SRCDIR)/lower_ubo_reference.cpp \ - $(GLSL_SRCDIR)/opt_algebraic.cpp \ - $(GLSL_SRCDIR)/opt_array_splitting.cpp \ - $(GLSL_SRCDIR)/opt_constant_folding.cpp \ - $(GLSL_SRCDIR)/opt_constant_propagation.cpp \ - $(GLSL_SRCDIR)/opt_constant_variable.cpp \ - $(GLSL_SRCDIR)/opt_copy_propagation.cpp \ - $(GLSL_SRCDIR)/opt_copy_propagation_elements.cpp \ - $(GLSL_SRCDIR)/opt_dead_builtin_varyings.cpp \ - $(GLSL_SRCDIR)/opt_dead_code.cpp \ - $(GLSL_SRCDIR)/opt_dead_code_local.cpp \ - $(GLSL_SRCDIR)/opt_dead_functions.cpp \ - $(GLSL_SRCDIR)/opt_flatten_nested_if_blocks.cpp \ - $(GLSL_SRCDIR)/opt_flip_matrices.cpp \ - $(GLSL_SRCDIR)/opt_function_inlining.cpp \ - $(GLSL_SRCDIR)/opt_if_simplification.cpp \ - $(GLSL_SRCDIR)/opt_noop_swizzle.cpp \ - $(GLSL_SRCDIR)/opt_redundant_jumps.cpp \ - $(GLSL_SRCDIR)/opt_structure_splitting.cpp \ - $(GLSL_SRCDIR)/opt_swizzle_swizzle.cpp \ - $(GLSL_SRCDIR)/opt_tree_grafting.cpp \ - $(GLSL_SRCDIR)/s_expression.cpp $(GLSL_SRCDIR)/strtod.c +libglsl_la_DEPENDENCIES = libglcpp.la am__objects_2 = ast_array_index.lo ast_expr.lo ast_function.lo \ - ast_to_hir.lo ast_type.lo builtin_types.lo \ - builtin_variables.lo glsl_parser_extras.lo glsl_types.lo \ - glsl_symbol_table.lo hir_field_selection.lo ir_basic_block.lo \ - ir_builder.lo ir_clone.lo ir_constant_expression.lo ir.lo \ + ast_to_hir.lo ast_type.lo builtin_functions.lo \ + builtin_types.lo builtin_variables.lo glsl_parser_extras.lo \ + glsl_types.lo glsl_symbol_table.lo hir_field_selection.lo \ + ir_basic_block.lo ir_builder.lo ir_clone.lo \ + ir_constant_expression.lo ir.lo ir_equals.lo \ ir_expression_flattening.lo ir_function_can_inline.lo \ ir_function_detect_recursion.lo ir_function.lo \ ir_hierarchical_visitor.lo ir_hv_accept.lo \ ir_import_prototypes.lo ir_print_visitor.lo ir_reader.lo \ ir_rvalue_visitor.lo ir_set_program_inouts.lo ir_validate.lo \ - ir_variable_refcount.lo linker.lo link_functions.lo \ - link_interface_blocks.lo link_uniforms.lo \ + ir_variable_refcount.lo linker.lo link_atomics.lo \ + link_functions.lo link_interface_blocks.lo link_uniforms.lo \ link_uniform_initializers.lo \ link_uniform_block_active_visitor.lo link_uniform_blocks.lo \ link_varyings.lo loop_analysis.lo loop_controls.lo \ loop_unroll.lo lower_clip_distance.lo lower_discard.lo \ lower_discard_flow.lo lower_if_to_cond_assign.lo \ lower_instructions.lo lower_jumps.lo lower_mat_op_to_vec.lo \ - lower_noise.lo lower_packed_varyings.lo \ + lower_noise.lo lower_offset_array.lo lower_packed_varyings.lo \ lower_named_interface_blocks.lo lower_packing_builtins.lo \ lower_texture_projection.lo \ lower_variable_index_to_cond_assign.lo \ @@ -254,33 +169,63 @@ am__objects_2 = ast_array_index.lo ast_expr.lo ast_function.lo \ lower_ubo_reference.lo opt_algebraic.lo opt_array_splitting.lo \ opt_constant_folding.lo opt_constant_propagation.lo \ opt_constant_variable.lo opt_copy_propagation.lo \ - opt_copy_propagation_elements.lo opt_dead_builtin_varyings.lo \ - opt_dead_code.lo opt_dead_code_local.lo opt_dead_functions.lo \ + opt_copy_propagation_elements.lo opt_cse.lo \ + opt_dead_builtin_varyings.lo opt_dead_code.lo \ + opt_dead_code_local.lo opt_dead_functions.lo \ opt_flatten_nested_if_blocks.lo opt_flip_matrices.lo \ opt_function_inlining.lo opt_if_simplification.lo \ opt_noop_swizzle.lo opt_redundant_jumps.lo \ opt_structure_splitting.lo opt_swizzle_swizzle.lo \ - opt_tree_grafting.lo s_expression.lo strtod.lo -@CROSS_COMPILING_TRUE@am__objects_3 = glsl_lexer.lo glsl_parser.lo \ -@CROSS_COMPILING_TRUE@ $(am__objects_2) -am_libglsl_la_OBJECTS = builtin_function.lo $(am__objects_3) + opt_tree_grafting.lo opt_vectorize.lo s_expression.lo \ + strtod.lo +am_libglsl_la_OBJECTS = glsl_lexer.lo glsl_parser.lo $(am__objects_2) libglsl_la_OBJECTS = $(am_libglsl_la_OBJECTS) +PROGRAMS = $(noinst_PROGRAMS) am_glcpp_glcpp_OBJECTS = glcpp.$(OBJEXT) prog_hash_table.$(OBJEXT) glcpp_glcpp_OBJECTS = $(am_glcpp_glcpp_OBJECTS) glcpp_glcpp_DEPENDENCIES = libglcpp.la am__dirstamp = $(am__leading_dot)dirstamp +am__objects_3 = standalone_scaffolding.$(OBJEXT) main.$(OBJEXT) +am_glsl_compiler_OBJECTS = hash_table.$(OBJEXT) imports.$(OBJEXT) \ + prog_hash_table.$(OBJEXT) symbol_table.$(OBJEXT) \ + $(am__objects_3) +glsl_compiler_OBJECTS = $(am_glsl_compiler_OBJECTS) +am__DEPENDENCIES_1 = +glsl_compiler_DEPENDENCIES = libglsl.la $(am__DEPENDENCIES_1) am_glsl_test_OBJECTS = hash_table.$(OBJEXT) imports.$(OBJEXT) \ prog_hash_table.$(OBJEXT) symbol_table.$(OBJEXT) \ - standalone_scaffolding.$(OBJEXT) test.$(OBJEXT) \ - test_optpass.$(OBJEXT) + standalone_scaffolding.$(OBJEXT) common.$(OBJEXT) \ + test.$(OBJEXT) test_optpass.$(OBJEXT) glsl_test_OBJECTS = $(am_glsl_test_OBJECTS) glsl_test_DEPENDENCIES = libglsl.la +am_tests_general_ir_test_OBJECTS = \ + tests_general_ir_test-hash_table.$(OBJEXT) \ + tests_general_ir_test-imports.$(OBJEXT) \ + tests_general_ir_test-prog_hash_table.$(OBJEXT) \ + tests_general_ir_test-symbol_table.$(OBJEXT) \ + standalone_scaffolding.$(OBJEXT) \ + builtin_variable_test.$(OBJEXT) \ + invalidate_locations_test.$(OBJEXT) general_ir_test.$(OBJEXT) \ + varyings_test.$(OBJEXT) tests_general_ir_test-common.$(OBJEXT) +tests_general_ir_test_OBJECTS = $(am_tests_general_ir_test_OBJECTS) +tests_general_ir_test_DEPENDENCIES = \ + $(top_builddir)/src/gtest/libgtest.la \ + $(top_builddir)/src/glsl/libglsl.la $(am__DEPENDENCIES_1) am_tests_ralloc_test_OBJECTS = ralloc_test.$(OBJEXT) \ tests_ralloc_test-ralloc.$(OBJEXT) tests_ralloc_test_OBJECTS = $(am_tests_ralloc_test_OBJECTS) -am__DEPENDENCIES_1 = tests_ralloc_test_DEPENDENCIES = \ $(top_builddir)/src/gtest/libgtest.la $(am__DEPENDENCIES_1) +am_tests_sampler_types_test_OBJECTS = \ + tests_sampler_types_test-prog_hash_table.$(OBJEXT) \ + tests_sampler_types_test-symbol_table.$(OBJEXT) \ + sampler_types_test.$(OBJEXT) \ + tests_sampler_types_test-common.$(OBJEXT) +tests_sampler_types_test_OBJECTS = \ + $(am_tests_sampler_types_test_OBJECTS) +tests_sampler_types_test_DEPENDENCIES = \ + $(top_builddir)/src/gtest/libgtest.la \ + $(top_builddir)/src/glsl/libglsl.la $(am__DEPENDENCIES_1) am_tests_uniform_initializer_test_OBJECTS = \ tests_uniform_initializer_test-hash_table.$(OBJEXT) \ tests_uniform_initializer_test-imports.$(OBJEXT) \ @@ -288,7 +233,8 @@ am_tests_uniform_initializer_test_OBJECTS = \ tests_uniform_initializer_test-symbol_table.$(OBJEXT) \ copy_constant_to_storage_tests.$(OBJEXT) \ set_uniform_initializer_tests.$(OBJEXT) \ - uniform_initializer_utils.$(OBJEXT) + uniform_initializer_utils.$(OBJEXT) \ + tests_uniform_initializer_test-common.$(OBJEXT) tests_uniform_initializer_test_OBJECTS = \ $(am_tests_uniform_initializer_test_OBJECTS) tests_uniform_initializer_test_DEPENDENCIES = \ @@ -347,34 +293,22 @@ am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(libglcpp_la_SOURCES) $(libglsl_la_SOURCES) \ - $(glcpp_glcpp_SOURCES) $(glsl_test_SOURCES) \ + $(glcpp_glcpp_SOURCES) $(glsl_compiler_SOURCES) \ + $(glsl_test_SOURCES) $(tests_general_ir_test_SOURCES) \ $(tests_ralloc_test_SOURCES) \ + $(tests_sampler_types_test_SOURCES) \ $(tests_uniform_initializer_test_SOURCES) -DIST_SOURCES = $(am__libglcpp_la_SOURCES_DIST) \ - $(am__libglsl_la_SOURCES_DIST) $(glcpp_glcpp_SOURCES) \ - $(glsl_test_SOURCES) $(tests_ralloc_test_SOURCES) \ +DIST_SOURCES = $(libglcpp_la_SOURCES) $(libglsl_la_SOURCES) \ + $(glcpp_glcpp_SOURCES) $(glsl_compiler_SOURCES) \ + $(glsl_test_SOURCES) $(tests_general_ir_test_SOURCES) \ + $(tests_ralloc_test_SOURCES) \ + $(tests_sampler_types_test_SOURCES) \ $(tests_uniform_initializer_test_SOURCES) -RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ - ctags-recursive dvi-recursive html-recursive info-recursive \ - install-data-recursive install-dvi-recursive \ - install-exec-recursive install-html-recursive \ - install-info-recursive install-pdf-recursive \ - install-ps-recursive install-recursive installcheck-recursive \ - installdirs-recursive pdf-recursive ps-recursive \ - tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac -RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ - distclean-recursive maintainer-clean-recursive -am__recursive_targets = \ - $(RECURSIVE_TARGETS) \ - $(RECURSIVE_CLEAN_TARGETS) \ - $(am__extra_recursive_targets) -AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ - check recheck distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is @@ -577,6 +511,7 @@ am__set_TESTS_bases = \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/bin/test-driver @@ -597,33 +532,7 @@ TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/bin/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) -DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -am__relativize = \ - dir0=`pwd`; \ - sed_first='s,^\([^/]*\)/.*$$,\1,'; \ - sed_rest='s,^[^/]*/*,,'; \ - sed_last='s,^.*/\([^/]*\)$$,\1,'; \ - sed_butlast='s,/*[^/]*$$,,'; \ - while test -n "$$dir1"; do \ - first=`echo "$$dir1" | sed -e "$$sed_first"`; \ - if test "$$first" != "."; then \ - if test "$$first" = ".."; then \ - dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ - dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ - else \ - first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ - if test "$$first2" = "$$first"; then \ - dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ - else \ - dir2="../$$dir2"; \ - fi; \ - dir0="$$dir0"/"$$first"; \ - fi; \ - fi; \ - dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ - done; \ - reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ @@ -632,39 +541,30 @@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ -BUILD_EXEEXT = @BUILD_EXEEXT@ -BUILD_OBJEXT = @BUILD_OBJEXT@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ -CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ -CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ CLANG_RESOURCE_DIR = @CLANG_RESOURCE_DIR@ CLOCK_LIB = @CLOCK_LIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ -CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ -CPP_FOR_BUILD = @CPP_FOR_BUILD@ CXX = @CXX@ CXXCPP = @CXXCPP@ -CXXCPPFLAGS_FOR_BUILD = @CXXCPPFLAGS_FOR_BUILD@ -CXXCPP_FOR_BUILD = @CXXCPP_FOR_BUILD@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ -CXXFLAGS_FOR_BUILD = @CXXFLAGS_FOR_BUILD@ -CXX_FOR_BUILD = @CXX_FOR_BUILD@ CYGPATH_W = @CYGPATH_W@ DEFINES = @DEFINES@ -DEFINES_FOR_BUILD = @DEFINES_FOR_BUILD@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DLOPEN_LIBS = @DLOPEN_LIBS@ DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@ DRI2PROTO_LIBS = @DRI2PROTO_LIBS@ +DRI3PROTO_CFLAGS = @DRI3PROTO_CFLAGS@ +DRI3PROTO_LIBS = @DRI3PROTO_LIBS@ DRIGL_CFLAGS = @DRIGL_CFLAGS@ DRIGL_LIBS = @DRIGL_LIBS@ DRI_DRIVER_INSTALL_DIR = @DRI_DRIVER_INSTALL_DIR@ @@ -680,41 +580,33 @@ EGL_CFLAGS = @EGL_CFLAGS@ EGL_CLIENT_APIS = @EGL_CLIENT_APIS@ EGL_DRIVER_INSTALL_DIR = @EGL_DRIVER_INSTALL_DIR@ EGL_LIB_DEPS = @EGL_LIB_DEPS@ -EGL_LIB_GLOB = @EGL_LIB_GLOB@ -EGL_LIB_NAME = @EGL_LIB_NAME@ EGL_NATIVE_PLATFORM = @EGL_NATIVE_PLATFORM@ -EGL_PLATFORMS = @EGL_PLATFORMS@ EGREP = @EGREP@ ELF_LIB = @ELF_LIB@ EXEEXT = @EXEEXT@ -EXPAT_INCLUDES = @EXPAT_INCLUDES@ +EXPAT_CFLAGS = @EXPAT_CFLAGS@ +EXPAT_LIBS = @EXPAT_LIBS@ FGREP = @FGREP@ FREEDRENO_CFLAGS = @FREEDRENO_CFLAGS@ FREEDRENO_LIBS = @FREEDRENO_LIBS@ -GALLIUM_DRI_LIB_DEPS = @GALLIUM_DRI_LIB_DEPS@ +GALLIUM_PIPE_LOADER_CLIENT_DEFINES = @GALLIUM_PIPE_LOADER_CLIENT_DEFINES@ +GALLIUM_PIPE_LOADER_CLIENT_LIBS = @GALLIUM_PIPE_LOADER_CLIENT_LIBS@ GALLIUM_PIPE_LOADER_DEFINES = @GALLIUM_PIPE_LOADER_DEFINES@ GALLIUM_PIPE_LOADER_LIBS = @GALLIUM_PIPE_LOADER_LIBS@ GALLIUM_PIPE_LOADER_XCB_CFLAGS = @GALLIUM_PIPE_LOADER_XCB_CFLAGS@ GALLIUM_PIPE_LOADER_XCB_LIBS = @GALLIUM_PIPE_LOADER_XCB_LIBS@ GBM_PC_LIB_PRIV = @GBM_PC_LIB_PRIV@ GBM_PC_REQ_PRIV = @GBM_PC_REQ_PRIV@ -GLAPI_LIB_GLOB = @GLAPI_LIB_GLOB@ -GLAPI_LIB_NAME = @GLAPI_LIB_NAME@ +GC_SECTIONS = @GC_SECTIONS@ GLESv1_CM_LIB_DEPS = @GLESv1_CM_LIB_DEPS@ -GLESv1_CM_LIB_GLOB = @GLESv1_CM_LIB_GLOB@ -GLESv1_CM_LIB_NAME = @GLESv1_CM_LIB_NAME@ GLESv1_CM_PC_LIB_PRIV = @GLESv1_CM_PC_LIB_PRIV@ GLESv2_LIB_DEPS = @GLESv2_LIB_DEPS@ -GLESv2_LIB_GLOB = @GLESv2_LIB_GLOB@ -GLESv2_LIB_NAME = @GLESv2_LIB_NAME@ GLESv2_PC_LIB_PRIV = @GLESv2_PC_LIB_PRIV@ GLPROTO_CFLAGS = @GLPROTO_CFLAGS@ GLPROTO_LIBS = @GLPROTO_LIBS@ GLX_TLS = @GLX_TLS@ GL_LIB = @GL_LIB@ GL_LIB_DEPS = @GL_LIB_DEPS@ -GL_LIB_GLOB = @GL_LIB_GLOB@ -GL_LIB_NAME = @GL_LIB_NAME@ GL_PC_CFLAGS = @GL_PC_CFLAGS@ GL_PC_LIB_PRIV = @GL_PC_LIB_PRIV@ GL_PC_REQ_PRIV = @GL_PC_REQ_PRIV@ @@ -731,7 +623,7 @@ INTEL_CFLAGS = @INTEL_CFLAGS@ INTEL_LIBS = @INTEL_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ -LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LD_NO_UNDEFINED = @LD_NO_UNDEFINED@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ @@ -739,16 +631,13 @@ LIBCLC_INCLUDEDIR = @LIBCLC_INCLUDEDIR@ LIBCLC_LIBEXECDIR = @LIBCLC_LIBEXECDIR@ LIBDRM_CFLAGS = @LIBDRM_CFLAGS@ LIBDRM_LIBS = @LIBDRM_LIBS@ -LIBDRM_XORG_CFLAGS = @LIBDRM_XORG_CFLAGS@ -LIBDRM_XORG_LIBS = @LIBDRM_XORG_LIBS@ -LIBKMS_XORG_CFLAGS = @LIBKMS_XORG_CFLAGS@ -LIBKMS_XORG_LIBS = @LIBKMS_XORG_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUDEV_CFLAGS = @LIBUDEV_CFLAGS@ LIBUDEV_LIBS = @LIBUDEV_LIBS@ LIB_DIR = @LIB_DIR@ +LIB_EXT = @LIB_EXT@ LIPO = @LIPO@ LLVM_BINDIR = @LLVM_BINDIR@ LLVM_CFLAGS = @LLVM_CFLAGS@ @@ -773,10 +662,13 @@ NOUVEAU_CFLAGS = @NOUVEAU_CFLAGS@ NOUVEAU_LIBS = @NOUVEAU_LIBS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ +OMX_CFLAGS = @OMX_CFLAGS@ +OMX_LIBS = @OMX_LIBS@ +OMX_LIB_INSTALL_DIR = @OMX_LIB_INSTALL_DIR@ +OPENCL_LIBNAME = @OPENCL_LIBNAME@ OPENCL_LIB_INSTALL_DIR = @OPENCL_LIB_INSTALL_DIR@ OSMESA_LIB = @OSMESA_LIB@ OSMESA_LIB_DEPS = @OSMESA_LIB_DEPS@ -OSMESA_LIB_NAME = @OSMESA_LIB_NAME@ OSMESA_MESA_DEPS = @OSMESA_MESA_DEPS@ OSMESA_PC_LIB_PRIV = @OSMESA_PC_LIB_PRIV@ OSMESA_PC_REQ = @OSMESA_PC_REQ@ @@ -796,6 +688,8 @@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POSIX_SHELL = @POSIX_SHELL@ +PRESENTPROTO_CFLAGS = @PRESENTPROTO_CFLAGS@ +PRESENTPROTO_LIBS = @PRESENTPROTO_LIBS@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ @@ -804,6 +698,7 @@ RADEON_CFLAGS = @RADEON_CFLAGS@ RADEON_LIBS = @RADEON_LIBS@ RANLIB = @RANLIB@ SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ @@ -815,8 +710,6 @@ VDPAU_MAJOR = @VDPAU_MAJOR@ VDPAU_MINOR = @VDPAU_MINOR@ VERSION = @VERSION@ VG_LIB_DEPS = @VG_LIB_DEPS@ -VG_LIB_GLOB = @VG_LIB_GLOB@ -VG_LIB_NAME = @VG_LIB_NAME@ VG_PC_LIB_PRIV = @VG_PC_LIB_PRIV@ VISIBILITY_CFLAGS = @VISIBILITY_CFLAGS@ VISIBILITY_CXXFLAGS = @VISIBILITY_CXXFLAGS@ @@ -830,15 +723,10 @@ XA_TINY = @XA_TINY@ XA_VERSION = @XA_VERSION@ XCB_DRI2_CFLAGS = @XCB_DRI2_CFLAGS@ XCB_DRI2_LIBS = @XCB_DRI2_LIBS@ -XEXT_CFLAGS = @XEXT_CFLAGS@ -XEXT_LIBS = @XEXT_LIBS@ XF86VIDMODE_CFLAGS = @XF86VIDMODE_CFLAGS@ XF86VIDMODE_LIBS = @XF86VIDMODE_LIBS@ XLIBGL_CFLAGS = @XLIBGL_CFLAGS@ XLIBGL_LIBS = @XLIBGL_LIBS@ -XORG_CFLAGS = @XORG_CFLAGS@ -XORG_DRIVER_INSTALL_DIR = @XORG_DRIVER_INSTALL_DIR@ -XORG_LIBS = @XORG_LIBS@ XVMC_CFLAGS = @XVMC_CFLAGS@ XVMC_LIBS = @XVMC_LIBS@ XVMC_LIB_INSTALL_DIR = @XVMC_LIB_INSTALL_DIR@ @@ -852,9 +740,7 @@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ -ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ ac_ct_CXX = @ac_ct_CXX@ -ac_ct_CXX_FOR_BUILD = @ac_ct_CXX_FOR_BUILD@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ @@ -906,7 +792,6 @@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -SUBDIRS = builtin_compiler AM_CPPFLAGS = \ -I$(top_srcdir)/include \ -I$(top_srcdir)/src/mapi \ @@ -937,6 +822,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/ast_function.cpp \ $(GLSL_SRCDIR)/ast_to_hir.cpp \ $(GLSL_SRCDIR)/ast_type.cpp \ + $(GLSL_SRCDIR)/builtin_functions.cpp \ $(GLSL_SRCDIR)/builtin_types.cpp \ $(GLSL_SRCDIR)/builtin_variables.cpp \ $(GLSL_SRCDIR)/glsl_parser_extras.cpp \ @@ -948,6 +834,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/ir_clone.cpp \ $(GLSL_SRCDIR)/ir_constant_expression.cpp \ $(GLSL_SRCDIR)/ir.cpp \ + $(GLSL_SRCDIR)/ir_equals.cpp \ $(GLSL_SRCDIR)/ir_expression_flattening.cpp \ $(GLSL_SRCDIR)/ir_function_can_inline.cpp \ $(GLSL_SRCDIR)/ir_function_detect_recursion.cpp \ @@ -962,6 +849,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/ir_validate.cpp \ $(GLSL_SRCDIR)/ir_variable_refcount.cpp \ $(GLSL_SRCDIR)/linker.cpp \ + $(GLSL_SRCDIR)/link_atomics.cpp \ $(GLSL_SRCDIR)/link_functions.cpp \ $(GLSL_SRCDIR)/link_interface_blocks.cpp \ $(GLSL_SRCDIR)/link_uniforms.cpp \ @@ -980,6 +868,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/lower_jumps.cpp \ $(GLSL_SRCDIR)/lower_mat_op_to_vec.cpp \ $(GLSL_SRCDIR)/lower_noise.cpp \ + $(GLSL_SRCDIR)/lower_offset_array.cpp \ $(GLSL_SRCDIR)/lower_packed_varyings.cpp \ $(GLSL_SRCDIR)/lower_named_interface_blocks.cpp \ $(GLSL_SRCDIR)/lower_packing_builtins.cpp \ @@ -998,6 +887,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/opt_constant_variable.cpp \ $(GLSL_SRCDIR)/opt_copy_propagation.cpp \ $(GLSL_SRCDIR)/opt_copy_propagation_elements.cpp \ + $(GLSL_SRCDIR)/opt_cse.cpp \ $(GLSL_SRCDIR)/opt_dead_builtin_varyings.cpp \ $(GLSL_SRCDIR)/opt_dead_code.cpp \ $(GLSL_SRCDIR)/opt_dead_code_local.cpp \ @@ -1011,6 +901,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/opt_structure_splitting.cpp \ $(GLSL_SRCDIR)/opt_swizzle_swizzle.cpp \ $(GLSL_SRCDIR)/opt_tree_grafting.cpp \ + $(GLSL_SRCDIR)/opt_vectorize.cpp \ $(GLSL_SRCDIR)/s_expression.cpp \ $(GLSL_SRCDIR)/strtod.c @@ -1021,29 +912,36 @@ GLSL_COMPILER_CXX_FILES = \ $(GLSL_SRCDIR)/main.cpp -# builtin_compiler -# -# This is built before libglsl to generate builtin_function.cpp for libglsl. -# For this to work, a dummy version of builtin_function.cpp, -# builtin_stubs.cpp, is used. -BUILTIN_COMPILER_CXX_FILES = \ - $(GLSL_SRCDIR)/builtin_compiler/builtin_stubs.cpp - -BUILTIN_COMPILER_GENERATED_CXX_FILES = \ - $(GLSL_BUILDDIR)/glsl_lexer.cpp \ - $(GLSL_BUILDDIR)/glsl_parser.cpp - - # libglsl generated sources LIBGLSL_GENERATED_CXX_FILES = \ - $(BUILTIN_COMPILER_GENERATED_CXX_FILES) \ - $(GLSL_BUILDDIR)/builtin_function.cpp + $(GLSL_BUILDDIR)/glsl_lexer.cpp \ + $(GLSL_BUILDDIR)/glsl_parser.cpp TESTS_ENVIRONMENT = \ export PYTHON2=$(PYTHON2); \ export PYTHON_FLAGS=$(PYTHON_FLAGS); noinst_LTLIBRARIES = libglsl.la libglcpp.la +tests_general_ir_test_SOURCES = \ + $(top_srcdir)/src/mesa/main/hash_table.c \ + $(top_srcdir)/src/mesa/main/imports.c \ + $(top_srcdir)/src/mesa/program/prog_hash_table.c\ + $(top_srcdir)/src/mesa/program/symbol_table.c \ + $(GLSL_SRCDIR)/standalone_scaffolding.cpp \ + tests/builtin_variable_test.cpp \ + tests/invalidate_locations_test.cpp \ + tests/general_ir_test.cpp \ + tests/varyings_test.cpp \ + tests/common.c + +tests_general_ir_test_CFLAGS = \ + $(PTHREAD_CFLAGS) + +tests_general_ir_test_LDADD = \ + $(top_builddir)/src/gtest/libgtest.la \ + $(top_builddir)/src/glsl/libglsl.la \ + $(PTHREAD_LIBS) + tests_uniform_initializer_test_SOURCES = \ $(top_srcdir)/src/mesa/main/hash_table.c \ $(top_srcdir)/src/mesa/main/imports.c \ @@ -1051,7 +949,8 @@ tests_uniform_initializer_test_SOURCES = \ $(top_srcdir)/src/mesa/program/symbol_table.c \ tests/copy_constant_to_storage_tests.cpp \ tests/set_uniform_initializer_tests.cpp \ - tests/uniform_initializer_utils.cpp + tests/uniform_initializer_utils.cpp \ + tests/common.c tests_uniform_initializer_test_CFLAGS = \ $(PTHREAD_CFLAGS) @@ -1070,25 +969,57 @@ tests_ralloc_test_LDADD = \ $(top_builddir)/src/gtest/libgtest.la \ $(PTHREAD_LIBS) -@CROSS_COMPILING_TRUE@libglcpp_la_SOURCES = \ -@CROSS_COMPILING_TRUE@ glcpp/glcpp-lex.c \ -@CROSS_COMPILING_TRUE@ glcpp/glcpp-parse.c \ -@CROSS_COMPILING_TRUE@ $(LIBGLCPP_FILES) +tests_sampler_types_test_SOURCES = \ + $(top_srcdir)/src/mesa/program/prog_hash_table.c\ + $(top_srcdir)/src/mesa/program/symbol_table.c \ + tests/sampler_types_test.cpp \ + tests/common.c + +tests_sampler_types_test_CFLAGS = \ + $(PTHREAD_CFLAGS) + +tests_sampler_types_test_LDADD = \ + $(top_builddir)/src/gtest/libgtest.la \ + $(top_builddir)/src/glsl/libglsl.la \ + $(PTHREAD_LIBS) + +libglcpp_la_SOURCES = \ + glcpp/glcpp-lex.c \ + glcpp/glcpp-parse.c \ + $(LIBGLCPP_FILES) -@CROSS_COMPILING_FALSE@libglcpp_la_LIBADD = builtin_compiler/libglcpp.la glcpp_glcpp_SOURCES = \ glcpp/glcpp.c \ $(top_srcdir)/src/mesa/program/prog_hash_table.c -glcpp_glcpp_LDADD = libglcpp.la -libglsl_la_SOURCES = builtin_function.cpp $(am__append_1) -libglsl_la_LIBADD = libglcpp.la $(am__append_2) +glcpp_glcpp_LDADD = \ + libglcpp.la \ + -lm + +libglsl_la_LIBADD = libglcpp.la +libglsl_la_SOURCES = \ + glsl_lexer.cpp \ + glsl_parser.cpp \ + $(LIBGLSL_FILES) + +glsl_compiler_SOURCES = \ + $(top_srcdir)/src/mesa/main/hash_table.c \ + $(top_srcdir)/src/mesa/main/imports.c \ + $(top_srcdir)/src/mesa/program/prog_hash_table.c \ + $(top_srcdir)/src/mesa/program/symbol_table.c \ + $(GLSL_COMPILER_CXX_FILES) + +glsl_compiler_LDADD = \ + libglsl.la \ + $(PTHREAD_LIBS) + glsl_test_SOURCES = \ $(top_srcdir)/src/mesa/main/hash_table.c \ $(top_srcdir)/src/mesa/main/imports.c \ $(top_srcdir)/src/mesa/program/prog_hash_table.c \ $(top_srcdir)/src/mesa/program/symbol_table.c \ $(GLSL_SRCDIR)/standalone_scaffolding.cpp \ + tests/common.c \ test.cpp \ test_optpass.cpp @@ -1140,7 +1071,7 @@ CLEANFILES = \ $(BUILT_SOURCES) all: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) all-recursive + $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .cpp .lo .log .o .obj .test .test$(EXEEXT) .trs @@ -1201,6 +1132,15 @@ clean-checkPROGRAMS: list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list glcpp/$(am__dirstamp): @$(MKDIR_P) glcpp @: > glcpp/$(am__dirstamp) @@ -1209,6 +1149,10 @@ glcpp/glcpp$(EXEEXT): $(glcpp_glcpp_OBJECTS) $(glcpp_glcpp_DEPENDENCIES) $(EXTRA @rm -f glcpp/glcpp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(glcpp_glcpp_OBJECTS) $(glcpp_glcpp_LDADD) $(LIBS) +glsl_compiler$(EXEEXT): $(glsl_compiler_OBJECTS) $(glsl_compiler_DEPENDENCIES) $(EXTRA_glsl_compiler_DEPENDENCIES) + @rm -f glsl_compiler$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(glsl_compiler_OBJECTS) $(glsl_compiler_LDADD) $(LIBS) + glsl_test$(EXEEXT): $(glsl_test_OBJECTS) $(glsl_test_DEPENDENCIES) $(EXTRA_glsl_test_DEPENDENCIES) @rm -f glsl_test$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(glsl_test_OBJECTS) $(glsl_test_LDADD) $(LIBS) @@ -1216,10 +1160,18 @@ tests/$(am__dirstamp): @$(MKDIR_P) tests @: > tests/$(am__dirstamp) +tests/general-ir-test$(EXEEXT): $(tests_general_ir_test_OBJECTS) $(tests_general_ir_test_DEPENDENCIES) $(EXTRA_tests_general_ir_test_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/general-ir-test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(tests_general_ir_test_OBJECTS) $(tests_general_ir_test_LDADD) $(LIBS) + tests/ralloc-test$(EXEEXT): $(tests_ralloc_test_OBJECTS) $(tests_ralloc_test_DEPENDENCIES) $(EXTRA_tests_ralloc_test_DEPENDENCIES) tests/$(am__dirstamp) @rm -f tests/ralloc-test$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(tests_ralloc_test_OBJECTS) $(tests_ralloc_test_LDADD) $(LIBS) +tests/sampler-types-test$(EXEEXT): $(tests_sampler_types_test_OBJECTS) $(tests_sampler_types_test_DEPENDENCIES) $(EXTRA_tests_sampler_types_test_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/sampler-types-test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(tests_sampler_types_test_OBJECTS) $(tests_sampler_types_test_LDADD) $(LIBS) + tests/uniform-initializer-test$(EXEEXT): $(tests_uniform_initializer_test_OBJECTS) $(tests_uniform_initializer_test_DEPENDENCIES) $(EXTRA_tests_uniform_initializer_test_DEPENDENCIES) tests/$(am__dirstamp) @rm -f tests/uniform-initializer-test$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(tests_uniform_initializer_test_OBJECTS) $(tests_uniform_initializer_test_LDADD) $(LIBS) @@ -1235,10 +1187,13 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ast_function.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ast_to_hir.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ast_type.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/builtin_function.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/builtin_functions.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/builtin_types.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/builtin_variable_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/builtin_variables.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/copy_constant_to_storage_tests.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/general_ir_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glcpp-lex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glcpp-parse.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glcpp.Po@am__quote@ @@ -1250,11 +1205,13 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash_table.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hir_field_selection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imports.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/invalidate_locations_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ir.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ir_basic_block.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ir_builder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ir_clone.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ir_constant_expression.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ir_equals.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ir_expression_flattening.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ir_function.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ir_function_can_inline.Plo@am__quote@ @@ -1268,6 +1225,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ir_set_program_inouts.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ir_validate.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ir_variable_refcount.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/link_atomics.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/link_functions.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/link_interface_blocks.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/link_uniform_block_active_visitor.Plo@am__quote@ @@ -1288,6 +1246,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lower_mat_op_to_vec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lower_named_interface_blocks.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lower_noise.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lower_offset_array.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lower_output_reads.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lower_packed_varyings.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lower_packing_builtins.Plo@am__quote@ @@ -1298,6 +1257,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lower_vec_index_to_swizzle.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lower_vector.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lower_vector_insert.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt_algebraic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt_array_splitting.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt_constant_folding.Plo@am__quote@ @@ -1305,6 +1265,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt_constant_variable.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt_copy_propagation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt_copy_propagation_elements.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt_cse.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt_dead_builtin_varyings.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt_dead_code.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt_dead_code_local.Plo@am__quote@ @@ -1318,23 +1279,35 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt_structure_splitting.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt_swizzle_swizzle.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt_tree_grafting.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt_vectorize.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prog_hash_table.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ralloc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ralloc_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s_expression.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sampler_types_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/set_uniform_initializer_tests.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/standalone_scaffolding.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strtod.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symbol_table.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_optpass.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests_general_ir_test-common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests_general_ir_test-hash_table.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests_general_ir_test-imports.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests_general_ir_test-prog_hash_table.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests_general_ir_test-symbol_table.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests_ralloc_test-ralloc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests_sampler_types_test-common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests_sampler_types_test-prog_hash_table.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests_sampler_types_test-symbol_table.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests_uniform_initializer_test-common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests_uniform_initializer_test-hash_table.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests_uniform_initializer_test-imports.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests_uniform_initializer_test-prog_hash_table.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tests_uniform_initializer_test-symbol_table.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uniform_initializer_utils.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/varyings_test.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -1462,6 +1435,90 @@ symbol_table.obj: $(top_srcdir)/src/mesa/program/symbol_table.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o symbol_table.obj `if test -f '$(top_srcdir)/src/mesa/program/symbol_table.c'; then $(CYGPATH_W) '$(top_srcdir)/src/mesa/program/symbol_table.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/mesa/program/symbol_table.c'; fi` +common.o: tests/common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common.o -MD -MP -MF $(DEPDIR)/common.Tpo -c -o common.o `test -f 'tests/common.c' || echo '$(srcdir)/'`tests/common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/common.Tpo $(DEPDIR)/common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/common.c' object='common.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common.o `test -f 'tests/common.c' || echo '$(srcdir)/'`tests/common.c + +common.obj: tests/common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common.obj -MD -MP -MF $(DEPDIR)/common.Tpo -c -o common.obj `if test -f 'tests/common.c'; then $(CYGPATH_W) 'tests/common.c'; else $(CYGPATH_W) '$(srcdir)/tests/common.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/common.Tpo $(DEPDIR)/common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/common.c' object='common.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common.obj `if test -f 'tests/common.c'; then $(CYGPATH_W) 'tests/common.c'; else $(CYGPATH_W) '$(srcdir)/tests/common.c'; fi` + +tests_general_ir_test-hash_table.o: $(top_srcdir)/src/mesa/main/hash_table.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -MT tests_general_ir_test-hash_table.o -MD -MP -MF $(DEPDIR)/tests_general_ir_test-hash_table.Tpo -c -o tests_general_ir_test-hash_table.o `test -f '$(top_srcdir)/src/mesa/main/hash_table.c' || echo '$(srcdir)/'`$(top_srcdir)/src/mesa/main/hash_table.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_general_ir_test-hash_table.Tpo $(DEPDIR)/tests_general_ir_test-hash_table.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/src/mesa/main/hash_table.c' object='tests_general_ir_test-hash_table.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -c -o tests_general_ir_test-hash_table.o `test -f '$(top_srcdir)/src/mesa/main/hash_table.c' || echo '$(srcdir)/'`$(top_srcdir)/src/mesa/main/hash_table.c + +tests_general_ir_test-hash_table.obj: $(top_srcdir)/src/mesa/main/hash_table.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -MT tests_general_ir_test-hash_table.obj -MD -MP -MF $(DEPDIR)/tests_general_ir_test-hash_table.Tpo -c -o tests_general_ir_test-hash_table.obj `if test -f '$(top_srcdir)/src/mesa/main/hash_table.c'; then $(CYGPATH_W) '$(top_srcdir)/src/mesa/main/hash_table.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/mesa/main/hash_table.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_general_ir_test-hash_table.Tpo $(DEPDIR)/tests_general_ir_test-hash_table.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/src/mesa/main/hash_table.c' object='tests_general_ir_test-hash_table.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -c -o tests_general_ir_test-hash_table.obj `if test -f '$(top_srcdir)/src/mesa/main/hash_table.c'; then $(CYGPATH_W) '$(top_srcdir)/src/mesa/main/hash_table.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/mesa/main/hash_table.c'; fi` + +tests_general_ir_test-imports.o: $(top_srcdir)/src/mesa/main/imports.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -MT tests_general_ir_test-imports.o -MD -MP -MF $(DEPDIR)/tests_general_ir_test-imports.Tpo -c -o tests_general_ir_test-imports.o `test -f '$(top_srcdir)/src/mesa/main/imports.c' || echo '$(srcdir)/'`$(top_srcdir)/src/mesa/main/imports.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_general_ir_test-imports.Tpo $(DEPDIR)/tests_general_ir_test-imports.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/src/mesa/main/imports.c' object='tests_general_ir_test-imports.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -c -o tests_general_ir_test-imports.o `test -f '$(top_srcdir)/src/mesa/main/imports.c' || echo '$(srcdir)/'`$(top_srcdir)/src/mesa/main/imports.c + +tests_general_ir_test-imports.obj: $(top_srcdir)/src/mesa/main/imports.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -MT tests_general_ir_test-imports.obj -MD -MP -MF $(DEPDIR)/tests_general_ir_test-imports.Tpo -c -o tests_general_ir_test-imports.obj `if test -f '$(top_srcdir)/src/mesa/main/imports.c'; then $(CYGPATH_W) '$(top_srcdir)/src/mesa/main/imports.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/mesa/main/imports.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_general_ir_test-imports.Tpo $(DEPDIR)/tests_general_ir_test-imports.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/src/mesa/main/imports.c' object='tests_general_ir_test-imports.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -c -o tests_general_ir_test-imports.obj `if test -f '$(top_srcdir)/src/mesa/main/imports.c'; then $(CYGPATH_W) '$(top_srcdir)/src/mesa/main/imports.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/mesa/main/imports.c'; fi` + +tests_general_ir_test-prog_hash_table.o: $(top_srcdir)/src/mesa/program/prog_hash_table.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -MT tests_general_ir_test-prog_hash_table.o -MD -MP -MF $(DEPDIR)/tests_general_ir_test-prog_hash_table.Tpo -c -o tests_general_ir_test-prog_hash_table.o `test -f '$(top_srcdir)/src/mesa/program/prog_hash_table.c' || echo '$(srcdir)/'`$(top_srcdir)/src/mesa/program/prog_hash_table.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_general_ir_test-prog_hash_table.Tpo $(DEPDIR)/tests_general_ir_test-prog_hash_table.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/src/mesa/program/prog_hash_table.c' object='tests_general_ir_test-prog_hash_table.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -c -o tests_general_ir_test-prog_hash_table.o `test -f '$(top_srcdir)/src/mesa/program/prog_hash_table.c' || echo '$(srcdir)/'`$(top_srcdir)/src/mesa/program/prog_hash_table.c + +tests_general_ir_test-prog_hash_table.obj: $(top_srcdir)/src/mesa/program/prog_hash_table.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -MT tests_general_ir_test-prog_hash_table.obj -MD -MP -MF $(DEPDIR)/tests_general_ir_test-prog_hash_table.Tpo -c -o tests_general_ir_test-prog_hash_table.obj `if test -f '$(top_srcdir)/src/mesa/program/prog_hash_table.c'; then $(CYGPATH_W) '$(top_srcdir)/src/mesa/program/prog_hash_table.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/mesa/program/prog_hash_table.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_general_ir_test-prog_hash_table.Tpo $(DEPDIR)/tests_general_ir_test-prog_hash_table.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/src/mesa/program/prog_hash_table.c' object='tests_general_ir_test-prog_hash_table.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -c -o tests_general_ir_test-prog_hash_table.obj `if test -f '$(top_srcdir)/src/mesa/program/prog_hash_table.c'; then $(CYGPATH_W) '$(top_srcdir)/src/mesa/program/prog_hash_table.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/mesa/program/prog_hash_table.c'; fi` + +tests_general_ir_test-symbol_table.o: $(top_srcdir)/src/mesa/program/symbol_table.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -MT tests_general_ir_test-symbol_table.o -MD -MP -MF $(DEPDIR)/tests_general_ir_test-symbol_table.Tpo -c -o tests_general_ir_test-symbol_table.o `test -f '$(top_srcdir)/src/mesa/program/symbol_table.c' || echo '$(srcdir)/'`$(top_srcdir)/src/mesa/program/symbol_table.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_general_ir_test-symbol_table.Tpo $(DEPDIR)/tests_general_ir_test-symbol_table.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/src/mesa/program/symbol_table.c' object='tests_general_ir_test-symbol_table.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -c -o tests_general_ir_test-symbol_table.o `test -f '$(top_srcdir)/src/mesa/program/symbol_table.c' || echo '$(srcdir)/'`$(top_srcdir)/src/mesa/program/symbol_table.c + +tests_general_ir_test-symbol_table.obj: $(top_srcdir)/src/mesa/program/symbol_table.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -MT tests_general_ir_test-symbol_table.obj -MD -MP -MF $(DEPDIR)/tests_general_ir_test-symbol_table.Tpo -c -o tests_general_ir_test-symbol_table.obj `if test -f '$(top_srcdir)/src/mesa/program/symbol_table.c'; then $(CYGPATH_W) '$(top_srcdir)/src/mesa/program/symbol_table.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/mesa/program/symbol_table.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_general_ir_test-symbol_table.Tpo $(DEPDIR)/tests_general_ir_test-symbol_table.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/src/mesa/program/symbol_table.c' object='tests_general_ir_test-symbol_table.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -c -o tests_general_ir_test-symbol_table.obj `if test -f '$(top_srcdir)/src/mesa/program/symbol_table.c'; then $(CYGPATH_W) '$(top_srcdir)/src/mesa/program/symbol_table.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/mesa/program/symbol_table.c'; fi` + +tests_general_ir_test-common.o: tests/common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -MT tests_general_ir_test-common.o -MD -MP -MF $(DEPDIR)/tests_general_ir_test-common.Tpo -c -o tests_general_ir_test-common.o `test -f 'tests/common.c' || echo '$(srcdir)/'`tests/common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_general_ir_test-common.Tpo $(DEPDIR)/tests_general_ir_test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/common.c' object='tests_general_ir_test-common.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -c -o tests_general_ir_test-common.o `test -f 'tests/common.c' || echo '$(srcdir)/'`tests/common.c + +tests_general_ir_test-common.obj: tests/common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -MT tests_general_ir_test-common.obj -MD -MP -MF $(DEPDIR)/tests_general_ir_test-common.Tpo -c -o tests_general_ir_test-common.obj `if test -f 'tests/common.c'; then $(CYGPATH_W) 'tests/common.c'; else $(CYGPATH_W) '$(srcdir)/tests/common.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_general_ir_test-common.Tpo $(DEPDIR)/tests_general_ir_test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/common.c' object='tests_general_ir_test-common.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_general_ir_test_CFLAGS) $(CFLAGS) -c -o tests_general_ir_test-common.obj `if test -f 'tests/common.c'; then $(CYGPATH_W) 'tests/common.c'; else $(CYGPATH_W) '$(srcdir)/tests/common.c'; fi` + tests_ralloc_test-ralloc.o: $(top_builddir)/src/glsl/ralloc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_ralloc_test_CFLAGS) $(CFLAGS) -MT tests_ralloc_test-ralloc.o -MD -MP -MF $(DEPDIR)/tests_ralloc_test-ralloc.Tpo -c -o tests_ralloc_test-ralloc.o `test -f '$(top_builddir)/src/glsl/ralloc.c' || echo '$(srcdir)/'`$(top_builddir)/src/glsl/ralloc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_ralloc_test-ralloc.Tpo $(DEPDIR)/tests_ralloc_test-ralloc.Po @@ -1476,6 +1533,48 @@ tests_ralloc_test-ralloc.obj: $(top_builddir)/src/glsl/ralloc.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_ralloc_test_CFLAGS) $(CFLAGS) -c -o tests_ralloc_test-ralloc.obj `if test -f '$(top_builddir)/src/glsl/ralloc.c'; then $(CYGPATH_W) '$(top_builddir)/src/glsl/ralloc.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/src/glsl/ralloc.c'; fi` +tests_sampler_types_test-prog_hash_table.o: $(top_srcdir)/src/mesa/program/prog_hash_table.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_sampler_types_test_CFLAGS) $(CFLAGS) -MT tests_sampler_types_test-prog_hash_table.o -MD -MP -MF $(DEPDIR)/tests_sampler_types_test-prog_hash_table.Tpo -c -o tests_sampler_types_test-prog_hash_table.o `test -f '$(top_srcdir)/src/mesa/program/prog_hash_table.c' || echo '$(srcdir)/'`$(top_srcdir)/src/mesa/program/prog_hash_table.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_sampler_types_test-prog_hash_table.Tpo $(DEPDIR)/tests_sampler_types_test-prog_hash_table.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/src/mesa/program/prog_hash_table.c' object='tests_sampler_types_test-prog_hash_table.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_sampler_types_test_CFLAGS) $(CFLAGS) -c -o tests_sampler_types_test-prog_hash_table.o `test -f '$(top_srcdir)/src/mesa/program/prog_hash_table.c' || echo '$(srcdir)/'`$(top_srcdir)/src/mesa/program/prog_hash_table.c + +tests_sampler_types_test-prog_hash_table.obj: $(top_srcdir)/src/mesa/program/prog_hash_table.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_sampler_types_test_CFLAGS) $(CFLAGS) -MT tests_sampler_types_test-prog_hash_table.obj -MD -MP -MF $(DEPDIR)/tests_sampler_types_test-prog_hash_table.Tpo -c -o tests_sampler_types_test-prog_hash_table.obj `if test -f '$(top_srcdir)/src/mesa/program/prog_hash_table.c'; then $(CYGPATH_W) '$(top_srcdir)/src/mesa/program/prog_hash_table.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/mesa/program/prog_hash_table.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_sampler_types_test-prog_hash_table.Tpo $(DEPDIR)/tests_sampler_types_test-prog_hash_table.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/src/mesa/program/prog_hash_table.c' object='tests_sampler_types_test-prog_hash_table.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_sampler_types_test_CFLAGS) $(CFLAGS) -c -o tests_sampler_types_test-prog_hash_table.obj `if test -f '$(top_srcdir)/src/mesa/program/prog_hash_table.c'; then $(CYGPATH_W) '$(top_srcdir)/src/mesa/program/prog_hash_table.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/mesa/program/prog_hash_table.c'; fi` + +tests_sampler_types_test-symbol_table.o: $(top_srcdir)/src/mesa/program/symbol_table.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_sampler_types_test_CFLAGS) $(CFLAGS) -MT tests_sampler_types_test-symbol_table.o -MD -MP -MF $(DEPDIR)/tests_sampler_types_test-symbol_table.Tpo -c -o tests_sampler_types_test-symbol_table.o `test -f '$(top_srcdir)/src/mesa/program/symbol_table.c' || echo '$(srcdir)/'`$(top_srcdir)/src/mesa/program/symbol_table.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_sampler_types_test-symbol_table.Tpo $(DEPDIR)/tests_sampler_types_test-symbol_table.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/src/mesa/program/symbol_table.c' object='tests_sampler_types_test-symbol_table.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_sampler_types_test_CFLAGS) $(CFLAGS) -c -o tests_sampler_types_test-symbol_table.o `test -f '$(top_srcdir)/src/mesa/program/symbol_table.c' || echo '$(srcdir)/'`$(top_srcdir)/src/mesa/program/symbol_table.c + +tests_sampler_types_test-symbol_table.obj: $(top_srcdir)/src/mesa/program/symbol_table.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_sampler_types_test_CFLAGS) $(CFLAGS) -MT tests_sampler_types_test-symbol_table.obj -MD -MP -MF $(DEPDIR)/tests_sampler_types_test-symbol_table.Tpo -c -o tests_sampler_types_test-symbol_table.obj `if test -f '$(top_srcdir)/src/mesa/program/symbol_table.c'; then $(CYGPATH_W) '$(top_srcdir)/src/mesa/program/symbol_table.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/mesa/program/symbol_table.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_sampler_types_test-symbol_table.Tpo $(DEPDIR)/tests_sampler_types_test-symbol_table.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/src/mesa/program/symbol_table.c' object='tests_sampler_types_test-symbol_table.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_sampler_types_test_CFLAGS) $(CFLAGS) -c -o tests_sampler_types_test-symbol_table.obj `if test -f '$(top_srcdir)/src/mesa/program/symbol_table.c'; then $(CYGPATH_W) '$(top_srcdir)/src/mesa/program/symbol_table.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/mesa/program/symbol_table.c'; fi` + +tests_sampler_types_test-common.o: tests/common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_sampler_types_test_CFLAGS) $(CFLAGS) -MT tests_sampler_types_test-common.o -MD -MP -MF $(DEPDIR)/tests_sampler_types_test-common.Tpo -c -o tests_sampler_types_test-common.o `test -f 'tests/common.c' || echo '$(srcdir)/'`tests/common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_sampler_types_test-common.Tpo $(DEPDIR)/tests_sampler_types_test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/common.c' object='tests_sampler_types_test-common.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_sampler_types_test_CFLAGS) $(CFLAGS) -c -o tests_sampler_types_test-common.o `test -f 'tests/common.c' || echo '$(srcdir)/'`tests/common.c + +tests_sampler_types_test-common.obj: tests/common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_sampler_types_test_CFLAGS) $(CFLAGS) -MT tests_sampler_types_test-common.obj -MD -MP -MF $(DEPDIR)/tests_sampler_types_test-common.Tpo -c -o tests_sampler_types_test-common.obj `if test -f 'tests/common.c'; then $(CYGPATH_W) 'tests/common.c'; else $(CYGPATH_W) '$(srcdir)/tests/common.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_sampler_types_test-common.Tpo $(DEPDIR)/tests_sampler_types_test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/common.c' object='tests_sampler_types_test-common.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_sampler_types_test_CFLAGS) $(CFLAGS) -c -o tests_sampler_types_test-common.obj `if test -f 'tests/common.c'; then $(CYGPATH_W) 'tests/common.c'; else $(CYGPATH_W) '$(srcdir)/tests/common.c'; fi` + tests_uniform_initializer_test-hash_table.o: $(top_srcdir)/src/mesa/main/hash_table.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_uniform_initializer_test_CFLAGS) $(CFLAGS) -MT tests_uniform_initializer_test-hash_table.o -MD -MP -MF $(DEPDIR)/tests_uniform_initializer_test-hash_table.Tpo -c -o tests_uniform_initializer_test-hash_table.o `test -f '$(top_srcdir)/src/mesa/main/hash_table.c' || echo '$(srcdir)/'`$(top_srcdir)/src/mesa/main/hash_table.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_uniform_initializer_test-hash_table.Tpo $(DEPDIR)/tests_uniform_initializer_test-hash_table.Po @@ -1532,6 +1631,20 @@ tests_uniform_initializer_test-symbol_table.obj: $(top_srcdir)/src/mesa/program/ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_uniform_initializer_test_CFLAGS) $(CFLAGS) -c -o tests_uniform_initializer_test-symbol_table.obj `if test -f '$(top_srcdir)/src/mesa/program/symbol_table.c'; then $(CYGPATH_W) '$(top_srcdir)/src/mesa/program/symbol_table.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/mesa/program/symbol_table.c'; fi` +tests_uniform_initializer_test-common.o: tests/common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_uniform_initializer_test_CFLAGS) $(CFLAGS) -MT tests_uniform_initializer_test-common.o -MD -MP -MF $(DEPDIR)/tests_uniform_initializer_test-common.Tpo -c -o tests_uniform_initializer_test-common.o `test -f 'tests/common.c' || echo '$(srcdir)/'`tests/common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_uniform_initializer_test-common.Tpo $(DEPDIR)/tests_uniform_initializer_test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/common.c' object='tests_uniform_initializer_test-common.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_uniform_initializer_test_CFLAGS) $(CFLAGS) -c -o tests_uniform_initializer_test-common.o `test -f 'tests/common.c' || echo '$(srcdir)/'`tests/common.c + +tests_uniform_initializer_test-common.obj: tests/common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_uniform_initializer_test_CFLAGS) $(CFLAGS) -MT tests_uniform_initializer_test-common.obj -MD -MP -MF $(DEPDIR)/tests_uniform_initializer_test-common.Tpo -c -o tests_uniform_initializer_test-common.obj `if test -f 'tests/common.c'; then $(CYGPATH_W) 'tests/common.c'; else $(CYGPATH_W) '$(srcdir)/tests/common.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tests_uniform_initializer_test-common.Tpo $(DEPDIR)/tests_uniform_initializer_test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/common.c' object='tests_uniform_initializer_test-common.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_uniform_initializer_test_CFLAGS) $(CFLAGS) -c -o tests_uniform_initializer_test-common.obj `if test -f 'tests/common.c'; then $(CYGPATH_W) 'tests/common.c'; else $(CYGPATH_W) '$(srcdir)/tests/common.c'; fi` + .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @@ -1588,6 +1701,13 @@ ast_type.lo: $(GLSL_SRCDIR)/ast_type.cpp @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ast_type.lo `test -f '$(GLSL_SRCDIR)/ast_type.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/ast_type.cpp +builtin_functions.lo: $(GLSL_SRCDIR)/builtin_functions.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT builtin_functions.lo -MD -MP -MF $(DEPDIR)/builtin_functions.Tpo -c -o builtin_functions.lo `test -f '$(GLSL_SRCDIR)/builtin_functions.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/builtin_functions.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/builtin_functions.Tpo $(DEPDIR)/builtin_functions.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$(GLSL_SRCDIR)/builtin_functions.cpp' object='builtin_functions.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o builtin_functions.lo `test -f '$(GLSL_SRCDIR)/builtin_functions.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/builtin_functions.cpp + builtin_types.lo: $(GLSL_SRCDIR)/builtin_types.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT builtin_types.lo -MD -MP -MF $(DEPDIR)/builtin_types.Tpo -c -o builtin_types.lo `test -f '$(GLSL_SRCDIR)/builtin_types.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/builtin_types.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/builtin_types.Tpo $(DEPDIR)/builtin_types.Plo @@ -1665,6 +1785,13 @@ ir.lo: $(GLSL_SRCDIR)/ir.cpp @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ir.lo `test -f '$(GLSL_SRCDIR)/ir.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/ir.cpp +ir_equals.lo: $(GLSL_SRCDIR)/ir_equals.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ir_equals.lo -MD -MP -MF $(DEPDIR)/ir_equals.Tpo -c -o ir_equals.lo `test -f '$(GLSL_SRCDIR)/ir_equals.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/ir_equals.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ir_equals.Tpo $(DEPDIR)/ir_equals.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$(GLSL_SRCDIR)/ir_equals.cpp' object='ir_equals.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ir_equals.lo `test -f '$(GLSL_SRCDIR)/ir_equals.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/ir_equals.cpp + ir_expression_flattening.lo: $(GLSL_SRCDIR)/ir_expression_flattening.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ir_expression_flattening.lo -MD -MP -MF $(DEPDIR)/ir_expression_flattening.Tpo -c -o ir_expression_flattening.lo `test -f '$(GLSL_SRCDIR)/ir_expression_flattening.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/ir_expression_flattening.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ir_expression_flattening.Tpo $(DEPDIR)/ir_expression_flattening.Plo @@ -1763,6 +1890,13 @@ linker.lo: $(GLSL_SRCDIR)/linker.cpp @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o linker.lo `test -f '$(GLSL_SRCDIR)/linker.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/linker.cpp +link_atomics.lo: $(GLSL_SRCDIR)/link_atomics.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT link_atomics.lo -MD -MP -MF $(DEPDIR)/link_atomics.Tpo -c -o link_atomics.lo `test -f '$(GLSL_SRCDIR)/link_atomics.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/link_atomics.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/link_atomics.Tpo $(DEPDIR)/link_atomics.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$(GLSL_SRCDIR)/link_atomics.cpp' object='link_atomics.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o link_atomics.lo `test -f '$(GLSL_SRCDIR)/link_atomics.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/link_atomics.cpp + link_functions.lo: $(GLSL_SRCDIR)/link_functions.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT link_functions.lo -MD -MP -MF $(DEPDIR)/link_functions.Tpo -c -o link_functions.lo `test -f '$(GLSL_SRCDIR)/link_functions.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/link_functions.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/link_functions.Tpo $(DEPDIR)/link_functions.Plo @@ -1889,6 +2023,13 @@ lower_noise.lo: $(GLSL_SRCDIR)/lower_noise.cpp @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o lower_noise.lo `test -f '$(GLSL_SRCDIR)/lower_noise.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/lower_noise.cpp +lower_offset_array.lo: $(GLSL_SRCDIR)/lower_offset_array.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT lower_offset_array.lo -MD -MP -MF $(DEPDIR)/lower_offset_array.Tpo -c -o lower_offset_array.lo `test -f '$(GLSL_SRCDIR)/lower_offset_array.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/lower_offset_array.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lower_offset_array.Tpo $(DEPDIR)/lower_offset_array.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$(GLSL_SRCDIR)/lower_offset_array.cpp' object='lower_offset_array.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o lower_offset_array.lo `test -f '$(GLSL_SRCDIR)/lower_offset_array.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/lower_offset_array.cpp + lower_packed_varyings.lo: $(GLSL_SRCDIR)/lower_packed_varyings.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT lower_packed_varyings.lo -MD -MP -MF $(DEPDIR)/lower_packed_varyings.Tpo -c -o lower_packed_varyings.lo `test -f '$(GLSL_SRCDIR)/lower_packed_varyings.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/lower_packed_varyings.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lower_packed_varyings.Tpo $(DEPDIR)/lower_packed_varyings.Plo @@ -2015,6 +2156,13 @@ opt_copy_propagation_elements.lo: $(GLSL_SRCDIR)/opt_copy_propagation_elements.c @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o opt_copy_propagation_elements.lo `test -f '$(GLSL_SRCDIR)/opt_copy_propagation_elements.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/opt_copy_propagation_elements.cpp +opt_cse.lo: $(GLSL_SRCDIR)/opt_cse.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT opt_cse.lo -MD -MP -MF $(DEPDIR)/opt_cse.Tpo -c -o opt_cse.lo `test -f '$(GLSL_SRCDIR)/opt_cse.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/opt_cse.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/opt_cse.Tpo $(DEPDIR)/opt_cse.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$(GLSL_SRCDIR)/opt_cse.cpp' object='opt_cse.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o opt_cse.lo `test -f '$(GLSL_SRCDIR)/opt_cse.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/opt_cse.cpp + opt_dead_builtin_varyings.lo: $(GLSL_SRCDIR)/opt_dead_builtin_varyings.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT opt_dead_builtin_varyings.lo -MD -MP -MF $(DEPDIR)/opt_dead_builtin_varyings.Tpo -c -o opt_dead_builtin_varyings.lo `test -f '$(GLSL_SRCDIR)/opt_dead_builtin_varyings.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/opt_dead_builtin_varyings.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/opt_dead_builtin_varyings.Tpo $(DEPDIR)/opt_dead_builtin_varyings.Plo @@ -2106,6 +2254,13 @@ opt_tree_grafting.lo: $(GLSL_SRCDIR)/opt_tree_grafting.cpp @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o opt_tree_grafting.lo `test -f '$(GLSL_SRCDIR)/opt_tree_grafting.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/opt_tree_grafting.cpp +opt_vectorize.lo: $(GLSL_SRCDIR)/opt_vectorize.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT opt_vectorize.lo -MD -MP -MF $(DEPDIR)/opt_vectorize.Tpo -c -o opt_vectorize.lo `test -f '$(GLSL_SRCDIR)/opt_vectorize.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/opt_vectorize.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/opt_vectorize.Tpo $(DEPDIR)/opt_vectorize.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$(GLSL_SRCDIR)/opt_vectorize.cpp' object='opt_vectorize.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o opt_vectorize.lo `test -f '$(GLSL_SRCDIR)/opt_vectorize.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/opt_vectorize.cpp + s_expression.lo: $(GLSL_SRCDIR)/s_expression.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT s_expression.lo -MD -MP -MF $(DEPDIR)/s_expression.Tpo -c -o s_expression.lo `test -f '$(GLSL_SRCDIR)/s_expression.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/s_expression.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/s_expression.Tpo $(DEPDIR)/s_expression.Plo @@ -2127,6 +2282,76 @@ standalone_scaffolding.obj: $(GLSL_SRCDIR)/standalone_scaffolding.cpp @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o standalone_scaffolding.obj `if test -f '$(GLSL_SRCDIR)/standalone_scaffolding.cpp'; then $(CYGPATH_W) '$(GLSL_SRCDIR)/standalone_scaffolding.cpp'; else $(CYGPATH_W) '$(srcdir)/$(GLSL_SRCDIR)/standalone_scaffolding.cpp'; fi` +main.o: $(GLSL_SRCDIR)/main.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT main.o -MD -MP -MF $(DEPDIR)/main.Tpo -c -o main.o `test -f '$(GLSL_SRCDIR)/main.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/main.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/main.Tpo $(DEPDIR)/main.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$(GLSL_SRCDIR)/main.cpp' object='main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o main.o `test -f '$(GLSL_SRCDIR)/main.cpp' || echo '$(srcdir)/'`$(GLSL_SRCDIR)/main.cpp + +main.obj: $(GLSL_SRCDIR)/main.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT main.obj -MD -MP -MF $(DEPDIR)/main.Tpo -c -o main.obj `if test -f '$(GLSL_SRCDIR)/main.cpp'; then $(CYGPATH_W) '$(GLSL_SRCDIR)/main.cpp'; else $(CYGPATH_W) '$(srcdir)/$(GLSL_SRCDIR)/main.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/main.Tpo $(DEPDIR)/main.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$(GLSL_SRCDIR)/main.cpp' object='main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o main.obj `if test -f '$(GLSL_SRCDIR)/main.cpp'; then $(CYGPATH_W) '$(GLSL_SRCDIR)/main.cpp'; else $(CYGPATH_W) '$(srcdir)/$(GLSL_SRCDIR)/main.cpp'; fi` + +builtin_variable_test.o: tests/builtin_variable_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT builtin_variable_test.o -MD -MP -MF $(DEPDIR)/builtin_variable_test.Tpo -c -o builtin_variable_test.o `test -f 'tests/builtin_variable_test.cpp' || echo '$(srcdir)/'`tests/builtin_variable_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/builtin_variable_test.Tpo $(DEPDIR)/builtin_variable_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tests/builtin_variable_test.cpp' object='builtin_variable_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o builtin_variable_test.o `test -f 'tests/builtin_variable_test.cpp' || echo '$(srcdir)/'`tests/builtin_variable_test.cpp + +builtin_variable_test.obj: tests/builtin_variable_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT builtin_variable_test.obj -MD -MP -MF $(DEPDIR)/builtin_variable_test.Tpo -c -o builtin_variable_test.obj `if test -f 'tests/builtin_variable_test.cpp'; then $(CYGPATH_W) 'tests/builtin_variable_test.cpp'; else $(CYGPATH_W) '$(srcdir)/tests/builtin_variable_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/builtin_variable_test.Tpo $(DEPDIR)/builtin_variable_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tests/builtin_variable_test.cpp' object='builtin_variable_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o builtin_variable_test.obj `if test -f 'tests/builtin_variable_test.cpp'; then $(CYGPATH_W) 'tests/builtin_variable_test.cpp'; else $(CYGPATH_W) '$(srcdir)/tests/builtin_variable_test.cpp'; fi` + +invalidate_locations_test.o: tests/invalidate_locations_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT invalidate_locations_test.o -MD -MP -MF $(DEPDIR)/invalidate_locations_test.Tpo -c -o invalidate_locations_test.o `test -f 'tests/invalidate_locations_test.cpp' || echo '$(srcdir)/'`tests/invalidate_locations_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/invalidate_locations_test.Tpo $(DEPDIR)/invalidate_locations_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tests/invalidate_locations_test.cpp' object='invalidate_locations_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o invalidate_locations_test.o `test -f 'tests/invalidate_locations_test.cpp' || echo '$(srcdir)/'`tests/invalidate_locations_test.cpp + +invalidate_locations_test.obj: tests/invalidate_locations_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT invalidate_locations_test.obj -MD -MP -MF $(DEPDIR)/invalidate_locations_test.Tpo -c -o invalidate_locations_test.obj `if test -f 'tests/invalidate_locations_test.cpp'; then $(CYGPATH_W) 'tests/invalidate_locations_test.cpp'; else $(CYGPATH_W) '$(srcdir)/tests/invalidate_locations_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/invalidate_locations_test.Tpo $(DEPDIR)/invalidate_locations_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tests/invalidate_locations_test.cpp' object='invalidate_locations_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o invalidate_locations_test.obj `if test -f 'tests/invalidate_locations_test.cpp'; then $(CYGPATH_W) 'tests/invalidate_locations_test.cpp'; else $(CYGPATH_W) '$(srcdir)/tests/invalidate_locations_test.cpp'; fi` + +general_ir_test.o: tests/general_ir_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT general_ir_test.o -MD -MP -MF $(DEPDIR)/general_ir_test.Tpo -c -o general_ir_test.o `test -f 'tests/general_ir_test.cpp' || echo '$(srcdir)/'`tests/general_ir_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/general_ir_test.Tpo $(DEPDIR)/general_ir_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tests/general_ir_test.cpp' object='general_ir_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o general_ir_test.o `test -f 'tests/general_ir_test.cpp' || echo '$(srcdir)/'`tests/general_ir_test.cpp + +general_ir_test.obj: tests/general_ir_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT general_ir_test.obj -MD -MP -MF $(DEPDIR)/general_ir_test.Tpo -c -o general_ir_test.obj `if test -f 'tests/general_ir_test.cpp'; then $(CYGPATH_W) 'tests/general_ir_test.cpp'; else $(CYGPATH_W) '$(srcdir)/tests/general_ir_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/general_ir_test.Tpo $(DEPDIR)/general_ir_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tests/general_ir_test.cpp' object='general_ir_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o general_ir_test.obj `if test -f 'tests/general_ir_test.cpp'; then $(CYGPATH_W) 'tests/general_ir_test.cpp'; else $(CYGPATH_W) '$(srcdir)/tests/general_ir_test.cpp'; fi` + +varyings_test.o: tests/varyings_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT varyings_test.o -MD -MP -MF $(DEPDIR)/varyings_test.Tpo -c -o varyings_test.o `test -f 'tests/varyings_test.cpp' || echo '$(srcdir)/'`tests/varyings_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/varyings_test.Tpo $(DEPDIR)/varyings_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tests/varyings_test.cpp' object='varyings_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o varyings_test.o `test -f 'tests/varyings_test.cpp' || echo '$(srcdir)/'`tests/varyings_test.cpp + +varyings_test.obj: tests/varyings_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT varyings_test.obj -MD -MP -MF $(DEPDIR)/varyings_test.Tpo -c -o varyings_test.obj `if test -f 'tests/varyings_test.cpp'; then $(CYGPATH_W) 'tests/varyings_test.cpp'; else $(CYGPATH_W) '$(srcdir)/tests/varyings_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/varyings_test.Tpo $(DEPDIR)/varyings_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tests/varyings_test.cpp' object='varyings_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o varyings_test.obj `if test -f 'tests/varyings_test.cpp'; then $(CYGPATH_W) 'tests/varyings_test.cpp'; else $(CYGPATH_W) '$(srcdir)/tests/varyings_test.cpp'; fi` + ralloc_test.o: tests/ralloc_test.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ralloc_test.o -MD -MP -MF $(DEPDIR)/ralloc_test.Tpo -c -o ralloc_test.o `test -f 'tests/ralloc_test.cpp' || echo '$(srcdir)/'`tests/ralloc_test.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ralloc_test.Tpo $(DEPDIR)/ralloc_test.Po @@ -2141,6 +2366,20 @@ ralloc_test.obj: tests/ralloc_test.cpp @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ralloc_test.obj `if test -f 'tests/ralloc_test.cpp'; then $(CYGPATH_W) 'tests/ralloc_test.cpp'; else $(CYGPATH_W) '$(srcdir)/tests/ralloc_test.cpp'; fi` +sampler_types_test.o: tests/sampler_types_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT sampler_types_test.o -MD -MP -MF $(DEPDIR)/sampler_types_test.Tpo -c -o sampler_types_test.o `test -f 'tests/sampler_types_test.cpp' || echo '$(srcdir)/'`tests/sampler_types_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sampler_types_test.Tpo $(DEPDIR)/sampler_types_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tests/sampler_types_test.cpp' object='sampler_types_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o sampler_types_test.o `test -f 'tests/sampler_types_test.cpp' || echo '$(srcdir)/'`tests/sampler_types_test.cpp + +sampler_types_test.obj: tests/sampler_types_test.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT sampler_types_test.obj -MD -MP -MF $(DEPDIR)/sampler_types_test.Tpo -c -o sampler_types_test.obj `if test -f 'tests/sampler_types_test.cpp'; then $(CYGPATH_W) 'tests/sampler_types_test.cpp'; else $(CYGPATH_W) '$(srcdir)/tests/sampler_types_test.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sampler_types_test.Tpo $(DEPDIR)/sampler_types_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tests/sampler_types_test.cpp' object='sampler_types_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o sampler_types_test.obj `if test -f 'tests/sampler_types_test.cpp'; then $(CYGPATH_W) 'tests/sampler_types_test.cpp'; else $(CYGPATH_W) '$(srcdir)/tests/sampler_types_test.cpp'; fi` + copy_constant_to_storage_tests.o: tests/copy_constant_to_storage_tests.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT copy_constant_to_storage_tests.o -MD -MP -MF $(DEPDIR)/copy_constant_to_storage_tests.Tpo -c -o copy_constant_to_storage_tests.o `test -f 'tests/copy_constant_to_storage_tests.cpp' || echo '$(srcdir)/'`tests/copy_constant_to_storage_tests.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/copy_constant_to_storage_tests.Tpo $(DEPDIR)/copy_constant_to_storage_tests.Po @@ -2191,61 +2430,14 @@ clean-libtool: -rm -rf glcpp/.libs glcpp/_libs -rm -rf tests/.libs tests/_libs -# This directory's subdirectories are mostly independent; you can cd -# into them and run 'make' without going through this Makefile. -# To change the values of 'make' variables: instead of editing Makefiles, -# (1) if the variable is set in 'config.status', edit 'config.status' -# (which will cause the Makefiles to be regenerated when you run 'make'); -# (2) otherwise, pass the desired values on the 'make' command line. -$(am__recursive_targets): - @fail=; \ - if $(am__make_keepgoing); then \ - failcom='fail=yes'; \ - else \ - failcom='exit 1'; \ - fi; \ - dot_seen=no; \ - target=`echo $@ | sed s/-recursive//`; \ - case "$@" in \ - distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ - *) list='$(SUBDIRS)' ;; \ - esac; \ - for subdir in $$list; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - dot_seen=yes; \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || eval $$failcom; \ - done; \ - if test "$$dot_seen" = "no"; then \ - $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ - fi; test -z "$$fail" - ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-recursive +tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ - if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ - include_option=--etags-include; \ - empty_fix=.; \ - else \ - include_option=--include; \ - empty_fix=; \ - fi; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - test ! -f $$subdir/TAGS || \ - set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ - fi; \ - done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ @@ -2258,7 +2450,7 @@ tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $$unique; \ fi; \ fi -ctags: ctags-recursive +ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) @@ -2271,7 +2463,7 @@ GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-recursive +cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ @@ -2438,6 +2630,13 @@ glcpp/tests/glcpp-test.log: glcpp/tests/glcpp-test --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/general-ir-test.log: tests/general-ir-test$(EXEEXT) + @p='tests/general-ir-test$(EXEEXT)'; \ + b='tests/general-ir-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) tests/optimization-test.log: tests/optimization-test @p='tests/optimization-test'; \ b='tests/optimization-test'; \ @@ -2452,6 +2651,13 @@ tests/ralloc-test.log: tests/ralloc-test$(EXEEXT) --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/sampler-types-test.log: tests/sampler-types-test$(EXEEXT) + @p='tests/sampler-types-test$(EXEEXT)'; \ + b='tests/sampler-types-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) tests/uniform-initializer-test.log: tests/uniform-initializer-test$(EXEEXT) @p='tests/uniform-initializer-test$(EXEEXT)'; \ b='tests/uniform-initializer-test'; \ @@ -2504,49 +2710,23 @@ distdir: $(DISTFILES) || exit 1; \ fi; \ done - @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - $(am__make_dryrun) \ - || test -d "$(distdir)/$$subdir" \ - || $(MKDIR_P) "$(distdir)/$$subdir" \ - || exit 1; \ - dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ - $(am__relativize); \ - new_distdir=$$reldir; \ - dir1=$$subdir; dir2="$(top_distdir)"; \ - $(am__relativize); \ - new_top_distdir=$$reldir; \ - echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ - echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ - ($(am__cd) $$subdir && \ - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$$new_top_distdir" \ - distdir="$$new_distdir" \ - am__remove_distdir=: \ - am__skip_length_check=: \ - am__skip_mode_fix=: \ - distdir) \ - || exit 1; \ - fi; \ - done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) check-recursive -all-am: Makefile $(LTLIBRARIES) -installdirs: installdirs-recursive -installdirs-am: + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) +installdirs: install: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) install-recursive -install-exec: install-exec-recursive -install-data: install-data-recursive -uninstall: uninstall-recursive + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am -installcheck: installcheck-recursive +installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ @@ -2575,91 +2755,90 @@ maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) -clean: clean-recursive +clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ - clean-noinstLTLIBRARIES mostlyclean-am + clean-noinstLTLIBRARIES clean-noinstPROGRAMS mostlyclean-am -distclean: distclean-recursive +distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags -dvi: dvi-recursive +dvi: dvi-am dvi-am: -html: html-recursive +html: html-am html-am: -info: info-recursive +info: info-am info-am: install-data-am: -install-dvi: install-dvi-recursive +install-dvi: install-dvi-am install-dvi-am: install-exec-am: -install-html: install-html-recursive +install-html: install-html-am install-html-am: -install-info: install-info-recursive +install-info: install-info-am install-info-am: install-man: -install-pdf: install-pdf-recursive +install-pdf: install-pdf-am install-pdf-am: -install-ps: install-ps-recursive +install-ps: install-ps-am install-ps-am: installcheck-am: -maintainer-clean: maintainer-clean-recursive +maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic -mostlyclean: mostlyclean-recursive +mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool -pdf: pdf-recursive +pdf: pdf-am pdf-am: -ps: ps-recursive +ps: ps-am ps-am: uninstall-am: -.MAKE: $(am__recursive_targets) all check check-am install install-am \ - install-strip +.MAKE: all check check-am install install-am install-strip -.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ - check-TESTS check-am clean clean-checkPROGRAMS clean-generic \ - clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ - ctags-am distclean distclean-compile distclean-generic \ +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ + clean-checkPROGRAMS clean-generic clean-libtool \ + clean-noinstLTLIBRARIES clean-noinstPROGRAMS cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs installdirs-am maintainer-clean \ + installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am @@ -2672,16 +2851,13 @@ glsl_lexer.cpp: glsl_lexer.ll $(AM_V_LEX) $(LEX) $(LFLAGS) -o $@ $< glcpp/glcpp-parse.c glcpp/glcpp-parse.h: glcpp/glcpp-parse.y - $(MKDIR_P) $(GLSL_BUILDDIR)/glcpp + $(AM_V_at)$(MKDIR_P) glcpp $(AM_V_YACC) $(YACC) $(YFLAGS) -o $@ -p "glcpp_parser_" --defines=$(GLSL_BUILDDIR)/glcpp/glcpp-parse.h $< glcpp/glcpp-lex.c: glcpp/glcpp-lex.l - $(MKDIR_P) $(GLSL_BUILDDIR)/glcpp + $(AM_V_at)$(MKDIR_P) glcpp $(AM_V_LEX) $(LEX) $(LFLAGS) -o $@ $< -builtin_function.cpp: $(srcdir)/builtins/profiles/* $(srcdir)/builtins/ir/* $(srcdir)/builtins/glsl/* $(srcdir)/builtins/tools/generate_builtins.py $(srcdir)/builtins/tools/texture_builtins.py $(builddir)/builtin_compiler/builtin_compiler$(BUILD_EXEEXT) - $(AM_V_GEN) $(PYTHON2) $(PYTHON_FLAGS) $(srcdir)/builtins/tools/generate_builtins.py $(builddir)/builtin_compiler/builtin_compiler$(BUILD_EXEEXT) > builtin_function.cpp || rm -f builtin_function.cpp - # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/dist/Mesa/src/glsl/Makefile.sources b/dist/Mesa/src/glsl/Makefile.sources index 979c4165f..5945590a5 100644 --- a/dist/Mesa/src/glsl/Makefile.sources +++ b/dist/Mesa/src/glsl/Makefile.sources @@ -21,6 +21,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/ast_function.cpp \ $(GLSL_SRCDIR)/ast_to_hir.cpp \ $(GLSL_SRCDIR)/ast_type.cpp \ + $(GLSL_SRCDIR)/builtin_functions.cpp \ $(GLSL_SRCDIR)/builtin_types.cpp \ $(GLSL_SRCDIR)/builtin_variables.cpp \ $(GLSL_SRCDIR)/glsl_parser_extras.cpp \ @@ -32,6 +33,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/ir_clone.cpp \ $(GLSL_SRCDIR)/ir_constant_expression.cpp \ $(GLSL_SRCDIR)/ir.cpp \ + $(GLSL_SRCDIR)/ir_equals.cpp \ $(GLSL_SRCDIR)/ir_expression_flattening.cpp \ $(GLSL_SRCDIR)/ir_function_can_inline.cpp \ $(GLSL_SRCDIR)/ir_function_detect_recursion.cpp \ @@ -46,6 +48,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/ir_validate.cpp \ $(GLSL_SRCDIR)/ir_variable_refcount.cpp \ $(GLSL_SRCDIR)/linker.cpp \ + $(GLSL_SRCDIR)/link_atomics.cpp \ $(GLSL_SRCDIR)/link_functions.cpp \ $(GLSL_SRCDIR)/link_interface_blocks.cpp \ $(GLSL_SRCDIR)/link_uniforms.cpp \ @@ -64,6 +67,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/lower_jumps.cpp \ $(GLSL_SRCDIR)/lower_mat_op_to_vec.cpp \ $(GLSL_SRCDIR)/lower_noise.cpp \ + $(GLSL_SRCDIR)/lower_offset_array.cpp \ $(GLSL_SRCDIR)/lower_packed_varyings.cpp \ $(GLSL_SRCDIR)/lower_named_interface_blocks.cpp \ $(GLSL_SRCDIR)/lower_packing_builtins.cpp \ @@ -82,6 +86,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/opt_constant_variable.cpp \ $(GLSL_SRCDIR)/opt_copy_propagation.cpp \ $(GLSL_SRCDIR)/opt_copy_propagation_elements.cpp \ + $(GLSL_SRCDIR)/opt_cse.cpp \ $(GLSL_SRCDIR)/opt_dead_builtin_varyings.cpp \ $(GLSL_SRCDIR)/opt_dead_code.cpp \ $(GLSL_SRCDIR)/opt_dead_code_local.cpp \ @@ -95,6 +100,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/opt_structure_splitting.cpp \ $(GLSL_SRCDIR)/opt_swizzle_swizzle.cpp \ $(GLSL_SRCDIR)/opt_tree_grafting.cpp \ + $(GLSL_SRCDIR)/opt_vectorize.cpp \ $(GLSL_SRCDIR)/s_expression.cpp \ $(GLSL_SRCDIR)/strtod.c @@ -104,20 +110,7 @@ GLSL_COMPILER_CXX_FILES = \ $(GLSL_SRCDIR)/standalone_scaffolding.cpp \ $(GLSL_SRCDIR)/main.cpp -# builtin_compiler -# -# This is built before libglsl to generate builtin_function.cpp for libglsl. -# For this to work, a dummy version of builtin_function.cpp, -# builtin_stubs.cpp, is used. - -BUILTIN_COMPILER_CXX_FILES = \ - $(GLSL_SRCDIR)/builtin_compiler/builtin_stubs.cpp - -BUILTIN_COMPILER_GENERATED_CXX_FILES = \ - $(GLSL_BUILDDIR)/glsl_lexer.cpp \ - $(GLSL_BUILDDIR)/glsl_parser.cpp - # libglsl generated sources LIBGLSL_GENERATED_CXX_FILES = \ - $(BUILTIN_COMPILER_GENERATED_CXX_FILES) \ - $(GLSL_BUILDDIR)/builtin_function.cpp + $(GLSL_BUILDDIR)/glsl_lexer.cpp \ + $(GLSL_BUILDDIR)/glsl_parser.cpp diff --git a/dist/Mesa/src/glsl/ast_array_index.cpp b/dist/Mesa/src/glsl/ast_array_index.cpp index 4baeb6f9d..f3b060ea6 100644 --- a/dist/Mesa/src/glsl/ast_array_index.cpp +++ b/dist/Mesa/src/glsl/ast_array_index.cpp @@ -25,6 +25,84 @@ #include "glsl_types.h" #include "ir.h" +void +ast_array_specifier::print(void) const +{ + if (this->is_unsized_array) { + printf("[ ] "); + } + + foreach_list_typed (ast_node, array_dimension, link, &this->array_dimensions) { + printf("[ "); + array_dimension->print(); + printf("] "); + } +} + +/** + * If \c ir is a reference to an array for which we are tracking the max array + * element accessed, track that the given element has been accessed. + * Otherwise do nothing. + * + * This function also checks whether the array is a built-in array whose + * maximum size is too small to accommodate the given index, and if so uses + * loc and state to report the error. + */ +static void +update_max_array_access(ir_rvalue *ir, unsigned idx, YYLTYPE *loc, + struct _mesa_glsl_parse_state *state) +{ + if (ir_dereference_variable *deref_var = ir->as_dereference_variable()) { + ir_variable *var = deref_var->var; + if (idx > var->data.max_array_access) { + var->data.max_array_access = idx; + + /* Check whether this access will, as a side effect, implicitly cause + * the size of a built-in array to be too large. + */ + check_builtin_array_max_size(var->name, idx+1, *loc, state); + } + } else if (ir_dereference_record *deref_record = + ir->as_dereference_record()) { + /* There are two possibilities we need to consider: + * + * - Accessing an element of an array that is a member of a named + * interface block (e.g. ifc.foo[i]) + * + * - Accessing an element of an array that is a member of a named + * interface block array (e.g. ifc[j].foo[i]). + */ + ir_dereference_variable *deref_var = + deref_record->record->as_dereference_variable(); + if (deref_var == NULL) { + if (ir_dereference_array *deref_array = + deref_record->record->as_dereference_array()) { + deref_var = deref_array->array->as_dereference_variable(); + } + } + + 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); + if (idx > deref_var->var->max_ifc_array_access[field_index]) { + deref_var->var->max_ifc_array_access[field_index] = idx; + + /* Check whether this access will, as a side effect, implicitly + * cause the size of a built-in array to be too large. + */ + check_builtin_array_max_size(deref_record->field, idx+1, *loc, + state); + } + } + } + } +} + + ir_rvalue * _mesa_ast_array_index_to_hir(void *mem_ctx, struct _mesa_glsl_parse_state *state, @@ -78,7 +156,7 @@ _mesa_ast_array_index_to_hir(void *mem_ctx, bound = array->type->vector_elements; } } else { - /* glsl_type::array_size() returns 0 for non-array types. This means + /* glsl_type::array_size() returns -1 for non-array types. This means * that we don't need to verify that the type is an array before * doing the bounds checking. */ @@ -97,27 +175,13 @@ _mesa_ast_array_index_to_hir(void *mem_ctx, type_name); } - if (array->type->is_array()) { - /* If the array is a variable dereference, it dereferences the - * whole array, by definition. Use this to get the variable. - * - * FINISHME: Should some methods for getting / setting / testing - * FINISHME: array access limits be added to ir_dereference? - */ - ir_variable *const v = array->whole_variable_referenced(); - if ((v != NULL) && (unsigned(idx) > v->max_array_access)) { - v->max_array_access = idx; - - /* Check whether this access will, as a side effect, implicitly - * cause the size of a built-in array to be too large. - */ - check_builtin_array_max_size(v->name, idx+1, loc, state); - } - } + if (array->type->is_array()) + update_max_array_access(array, idx, &loc, state); } else if (const_index == NULL && array->type->is_array()) { - if (array->type->array_size() == 0) { + if (array->type->is_unsized_array()) { _mesa_glsl_error(&loc, state, "unsized array index must be constant"); - } else if (array->type->fields.array->is_interface()) { + } else if (array->type->fields.array->is_interface() + && array->variable_referenced()->data.mode == ir_var_uniform) { /* Page 46 in section 4.3.7 of the OpenGL ES 3.00 spec says: * * "All indexes used to index a uniform block array must be @@ -133,7 +197,7 @@ _mesa_ast_array_index_to_hir(void *mem_ctx, */ ir_variable *v = array->whole_variable_referenced(); if (v != NULL) - v->max_array_access = array->type->array_size() - 1; + v->data.max_array_access = array->type->array_size() - 1; } /* From page 23 (29 of the PDF) of the GLSL 1.30 spec: diff --git a/dist/Mesa/src/glsl/builtin_functions.cpp b/dist/Mesa/src/glsl/builtin_functions.cpp new file mode 100644 index 000000000..f9f06862e --- /dev/null +++ b/dist/Mesa/src/glsl/builtin_functions.cpp @@ -0,0 +1,4405 @@ +/* + * Copyright © 2013 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 builtin_functions.cpp + * + * Support for GLSL built-in functions. + * + * This file is split into several main components: + * + * 1. Availability predicates + * + * A series of small functions that check whether the current shader + * supports the version/extensions required to expose a built-in. + * + * 2. Core builtin_builder class functionality + * + * 3. Lists of built-in functions + * + * The builtin_builder::create_builtins() function contains lists of all + * built-in function signatures, where they're available, what types they + * take, and so on. + * + * 4. Implementations of built-in function signatures + * + * A series of functions which create ir_function_signatures and emit IR + * via ir_builder to implement them. + * + * 5. External API + * + * A few functions the rest of the compiler can use to interact with the + * built-in function module. For example, searching for a built-in by + * name and parameters. + */ + +#include <stdarg.h> +#include <stdio.h> +#include "main/core.h" /* for struct gl_shader */ +#include "main/shaderobj.h" +#include "ir_builder.h" +#include "glsl_parser_extras.h" +#include "program/prog_instruction.h" +#include <limits> + +#define M_PIf ((float) M_PI) +#define M_PI_2f ((float) M_PI_2) +#define M_PI_4f ((float) M_PI_4) + +using namespace ir_builder; + +/** + * Availability predicates: + * @{ + */ +static bool +always_available(const _mesa_glsl_parse_state *) +{ + return true; +} + +static bool +compatibility_vs_only(const _mesa_glsl_parse_state *state) +{ + return state->stage == MESA_SHADER_VERTEX && + state->language_version <= 130 && + !state->es_shader; +} + +static bool +fs_only(const _mesa_glsl_parse_state *state) +{ + return state->stage == MESA_SHADER_FRAGMENT; +} + +static bool +gs_only(const _mesa_glsl_parse_state *state) +{ + return state->stage == MESA_SHADER_GEOMETRY; +} + +static bool +v110(const _mesa_glsl_parse_state *state) +{ + return !state->es_shader; +} + +static bool +v110_fs_only(const _mesa_glsl_parse_state *state) +{ + return !state->es_shader && state->stage == MESA_SHADER_FRAGMENT; +} + +static bool +v120(const _mesa_glsl_parse_state *state) +{ + return state->is_version(120, 300); +} + +static bool +v130(const _mesa_glsl_parse_state *state) +{ + return state->is_version(130, 300); +} + +static bool +v130_fs_only(const _mesa_glsl_parse_state *state) +{ + return state->is_version(130, 300) && + state->stage == MESA_SHADER_FRAGMENT; +} + +static bool +v140(const _mesa_glsl_parse_state *state) +{ + return state->is_version(140, 0); +} + +static bool +texture_rectangle(const _mesa_glsl_parse_state *state) +{ + return state->ARB_texture_rectangle_enable; +} + +static bool +texture_external(const _mesa_glsl_parse_state *state) +{ + return state->OES_EGL_image_external_enable; +} + +/** True if texturing functions with explicit LOD are allowed. */ +static bool +lod_exists_in_stage(const _mesa_glsl_parse_state *state) +{ + /* Texturing functions with "Lod" in their name exist: + * - In the vertex shader stage (for all languages) + * - In any stage for GLSL 1.30+ or GLSL ES 3.00 + * - In any stage for desktop GLSL with ARB_shader_texture_lod enabled. + * + * Since ARB_shader_texture_lod can only be enabled on desktop GLSL, we + * don't need to explicitly check state->es_shader. + */ + return state->stage == MESA_SHADER_VERTEX || + state->is_version(130, 300) || + state->ARB_shader_texture_lod_enable; +} + +static bool +v110_lod(const _mesa_glsl_parse_state *state) +{ + return !state->es_shader && lod_exists_in_stage(state); +} + +static bool +shader_texture_lod(const _mesa_glsl_parse_state *state) +{ + return state->ARB_shader_texture_lod_enable; +} + +static bool +shader_texture_lod_and_rect(const _mesa_glsl_parse_state *state) +{ + return state->ARB_shader_texture_lod_enable && + state->ARB_texture_rectangle_enable; +} + +static bool +shader_bit_encoding(const _mesa_glsl_parse_state *state) +{ + return state->is_version(330, 300) || + state->ARB_shader_bit_encoding_enable || + state->ARB_gpu_shader5_enable; +} + +static bool +shader_integer_mix(const _mesa_glsl_parse_state *state) +{ + return v130(state) && state->EXT_shader_integer_mix_enable; +} + +static bool +shader_packing_or_es3(const _mesa_glsl_parse_state *state) +{ + return state->ARB_shading_language_packing_enable || + state->is_version(400, 300); +} + +static bool +shader_packing_or_es3_or_gpu_shader5(const _mesa_glsl_parse_state *state) +{ + return state->ARB_shading_language_packing_enable || + state->ARB_gpu_shader5_enable || + state->is_version(400, 300); +} + +static bool +gpu_shader5(const _mesa_glsl_parse_state *state) +{ + return state->is_version(400, 0) || state->ARB_gpu_shader5_enable; +} + +static bool +shader_packing_or_gpu_shader5(const _mesa_glsl_parse_state *state) +{ + return state->ARB_shading_language_packing_enable || + gpu_shader5(state); +} + +static bool +texture_array_lod(const _mesa_glsl_parse_state *state) +{ + return lod_exists_in_stage(state) && + state->EXT_texture_array_enable; +} + +static bool +fs_texture_array(const _mesa_glsl_parse_state *state) +{ + return state->stage == MESA_SHADER_FRAGMENT && + state->EXT_texture_array_enable; +} + +static bool +texture_array(const _mesa_glsl_parse_state *state) +{ + return state->EXT_texture_array_enable; +} + +static bool +texture_multisample(const _mesa_glsl_parse_state *state) +{ + return state->is_version(150, 0) || + state->ARB_texture_multisample_enable; +} + +static bool +fs_texture_cube_map_array(const _mesa_glsl_parse_state *state) +{ + return state->stage == MESA_SHADER_FRAGMENT && + (state->is_version(400, 0) || + state->ARB_texture_cube_map_array_enable); +} + +static bool +texture_cube_map_array(const _mesa_glsl_parse_state *state) +{ + return state->is_version(400, 0) || + state->ARB_texture_cube_map_array_enable; +} + +static bool +texture_query_levels(const _mesa_glsl_parse_state *state) +{ + return state->is_version(430, 0) || + state->ARB_texture_query_levels_enable; +} + +static bool +texture_query_lod(const _mesa_glsl_parse_state *state) +{ + return state->stage == MESA_SHADER_FRAGMENT && + state->ARB_texture_query_lod_enable; +} + +static bool +texture_gather(const _mesa_glsl_parse_state *state) +{ + return state->is_version(400, 0) || + state->ARB_texture_gather_enable || + state->ARB_gpu_shader5_enable; +} + +/* Only ARB_texture_gather but not GLSL 4.0 or ARB_gpu_shader5. + * used for relaxation of const offset requirements. + */ +static bool +texture_gather_only(const _mesa_glsl_parse_state *state) +{ + return !state->is_version(400, 0) && + !state->ARB_gpu_shader5_enable && + state->ARB_texture_gather_enable; +} + +/* Desktop GL or OES_standard_derivatives + fragment shader only */ +static bool +fs_oes_derivatives(const _mesa_glsl_parse_state *state) +{ + return state->stage == MESA_SHADER_FRAGMENT && + (state->is_version(110, 300) || + state->OES_standard_derivatives_enable); +} + +static bool +tex1d_lod(const _mesa_glsl_parse_state *state) +{ + return !state->es_shader && lod_exists_in_stage(state); +} + +/** True if sampler3D exists */ +static bool +tex3d(const _mesa_glsl_parse_state *state) +{ + /* sampler3D exists in all desktop GLSL versions, GLSL ES 1.00 with the + * OES_texture_3D extension, and in GLSL ES 3.00. + */ + return !state->es_shader || + state->OES_texture_3D_enable || + state->language_version >= 300; +} + +static bool +fs_tex3d(const _mesa_glsl_parse_state *state) +{ + return state->stage == MESA_SHADER_FRAGMENT && + (!state->es_shader || state->OES_texture_3D_enable); +} + +static bool +tex3d_lod(const _mesa_glsl_parse_state *state) +{ + return tex3d(state) && lod_exists_in_stage(state); +} + +static bool +shader_atomic_counters(const _mesa_glsl_parse_state *state) +{ + return state->ARB_shader_atomic_counters_enable; +} + +static bool +shader_trinary_minmax(const _mesa_glsl_parse_state *state) +{ + return state->AMD_shader_trinary_minmax_enable; +} + +static bool +shader_image_load_store(const _mesa_glsl_parse_state *state) +{ + return (state->is_version(420, 0) || + state->ARB_shader_image_load_store_enable); +} + +/** @} */ + +/******************************************************************************/ + +namespace { + +/** + * builtin_builder: A singleton object representing the core of the built-in + * function module. + * + * It generates IR for every built-in function signature, and organizes them + * into functions. + */ +class builtin_builder { +public: + builtin_builder(); + ~builtin_builder(); + + void initialize(); + void release(); + ir_function_signature *find(_mesa_glsl_parse_state *state, + const char *name, exec_list *actual_parameters); + + /** + * A shader to hold all the built-in signatures; created by this module. + * + * This includes signatures for every built-in, regardless of version or + * enabled extensions. The availability predicate associated with each + * signature allows matching_signature() to filter out the irrelevant ones. + */ + gl_shader *shader; + +private: + void *mem_ctx; + + /** Global variables used by built-in functions. */ + ir_variable *gl_ModelViewProjectionMatrix; + ir_variable *gl_Vertex; + + void create_shader(); + void create_intrinsics(); + void create_builtins(); + + /** + * IR builder helpers: + * + * These convenience functions assist in emitting IR, but don't necessarily + * fit in ir_builder itself. Many of them rely on having a mem_ctx class + * member available. + */ + ir_variable *in_var(const glsl_type *type, const char *name); + ir_variable *out_var(const glsl_type *type, const char *name); + ir_constant *imm(float f, unsigned vector_elements=1); + ir_constant *imm(int i, unsigned vector_elements=1); + ir_constant *imm(unsigned u, unsigned vector_elements=1); + ir_constant *imm(const glsl_type *type, const ir_constant_data &); + ir_dereference_variable *var_ref(ir_variable *var); + ir_dereference_array *array_ref(ir_variable *var, int i); + ir_swizzle *matrix_elt(ir_variable *var, int col, int row); + + ir_expression *asin_expr(ir_variable *x); + + /** + * Call function \param f with parameters specified as the linked + * list \param params of \c ir_variable objects. \param ret should + * point to the ir_variable that will hold the function return + * value, or be \c NULL if the function has void return type. + */ + ir_call *call(ir_function *f, ir_variable *ret, exec_list params); + + /** Create a new function and add the given signatures. */ + void add_function(const char *name, ...); + + enum image_function_flags { + IMAGE_FUNCTION_EMIT_STUB = (1 << 0), + IMAGE_FUNCTION_RETURNS_VOID = (1 << 1), + IMAGE_FUNCTION_HAS_VECTOR_DATA_TYPE = (1 << 2), + IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE = (1 << 3), + IMAGE_FUNCTION_READ_ONLY = (1 << 4), + IMAGE_FUNCTION_WRITE_ONLY = (1 << 5) + }; + + /** + * Create a new image built-in function for all known image types. + * \p flags is a bitfield of \c image_function_flags flags. + */ + void add_image_function(const char *name, + const char *intrinsic_name, + unsigned num_arguments, + unsigned flags); + + /** + * Create new functions for all known image built-ins and types. + * If \p glsl is \c true, use the GLSL built-in names and emit code + * to call into the actual compiler intrinsic. If \p glsl is + * false, emit a function prototype with no body for each image + * intrinsic name. + */ + void add_image_functions(bool glsl); + + ir_function_signature *new_sig(const glsl_type *return_type, + builtin_available_predicate avail, + int num_params, ...); + + /** + * Function signature generators: + * @{ + */ + ir_function_signature *unop(builtin_available_predicate avail, + ir_expression_operation opcode, + const glsl_type *return_type, + const glsl_type *param_type); + ir_function_signature *binop(ir_expression_operation opcode, + builtin_available_predicate avail, + const glsl_type *return_type, + const glsl_type *param0_type, + const glsl_type *param1_type); + +#define B0(X) ir_function_signature *_##X(); +#define B1(X) ir_function_signature *_##X(const glsl_type *); +#define B2(X) ir_function_signature *_##X(const glsl_type *, const glsl_type *); +#define B3(X) ir_function_signature *_##X(const glsl_type *, const glsl_type *, const glsl_type *); +#define BA1(X) ir_function_signature *_##X(builtin_available_predicate, const glsl_type *); +#define BA2(X) ir_function_signature *_##X(builtin_available_predicate, const glsl_type *, const glsl_type *); + B1(radians) + B1(degrees) + B1(sin) + B1(cos) + B1(tan) + B1(asin) + B1(acos) + B1(atan2) + B1(atan) + B1(sinh) + B1(cosh) + B1(tanh) + B1(asinh) + B1(acosh) + B1(atanh) + B1(pow) + B1(exp) + B1(log) + B1(exp2) + B1(log2) + B1(sqrt) + B1(inversesqrt) + B1(abs) + B1(sign) + B1(floor) + B1(trunc) + B1(round) + B1(roundEven) + B1(ceil) + B1(fract) + B2(mod) + B1(modf) + BA2(min) + BA2(max) + BA2(clamp) + B2(mix_lrp) + ir_function_signature *_mix_sel(builtin_available_predicate avail, + const glsl_type *val_type, + const glsl_type *blend_type); + B2(step) + B2(smoothstep) + B1(isnan) + B1(isinf) + B1(floatBitsToInt) + B1(floatBitsToUint) + B1(intBitsToFloat) + B1(uintBitsToFloat) + ir_function_signature *_packUnorm2x16(builtin_available_predicate avail); + ir_function_signature *_packSnorm2x16(builtin_available_predicate avail); + ir_function_signature *_packUnorm4x8(builtin_available_predicate avail); + ir_function_signature *_packSnorm4x8(builtin_available_predicate avail); + ir_function_signature *_unpackUnorm2x16(builtin_available_predicate avail); + ir_function_signature *_unpackSnorm2x16(builtin_available_predicate avail); + ir_function_signature *_unpackUnorm4x8(builtin_available_predicate avail); + ir_function_signature *_unpackSnorm4x8(builtin_available_predicate avail); + ir_function_signature *_packHalf2x16(builtin_available_predicate avail); + ir_function_signature *_unpackHalf2x16(builtin_available_predicate avail); + B1(length) + B1(distance); + B1(dot); + B1(cross); + B1(normalize); + B0(ftransform); + B1(faceforward); + B1(reflect); + B1(refract); + B1(matrixCompMult); + B1(outerProduct); + B0(determinant_mat2); + B0(determinant_mat3); + B0(determinant_mat4); + B0(inverse_mat2); + B0(inverse_mat3); + B0(inverse_mat4); + B1(transpose); + BA1(lessThan); + BA1(lessThanEqual); + BA1(greaterThan); + BA1(greaterThanEqual); + BA1(equal); + BA1(notEqual); + B1(any); + B1(all); + B1(not); + B2(textureSize); + ir_function_signature *_textureSize(builtin_available_predicate avail, + const glsl_type *return_type, + const glsl_type *sampler_type); + +/** Flags to _texture() */ +#define TEX_PROJECT 1 +#define TEX_OFFSET 2 +#define TEX_COMPONENT 4 +#define TEX_OFFSET_NONCONST 8 +#define TEX_OFFSET_ARRAY 16 + + ir_function_signature *_texture(ir_texture_opcode opcode, + builtin_available_predicate avail, + const glsl_type *return_type, + const glsl_type *sampler_type, + const glsl_type *coord_type, + int flags = 0); + B0(textureCubeArrayShadow); + ir_function_signature *_texelFetch(builtin_available_predicate avail, + const glsl_type *return_type, + const glsl_type *sampler_type, + const glsl_type *coord_type, + const glsl_type *offset_type = NULL); + + B0(EmitVertex) + B0(EndPrimitive) + + B2(textureQueryLod); + B1(textureQueryLevels); + B1(dFdx); + B1(dFdy); + B1(fwidth); + B1(noise1); + B1(noise2); + B1(noise3); + B1(noise4); + + B1(bitfieldExtract) + B1(bitfieldInsert) + B1(bitfieldReverse) + B1(bitCount) + B1(findLSB) + B1(findMSB) + B1(fma) + B2(ldexp) + B2(frexp) + B1(uaddCarry) + B1(usubBorrow) + B1(mulExtended) + + ir_function_signature *_atomic_intrinsic(builtin_available_predicate avail); + ir_function_signature *_atomic_op(const char *intrinsic, + builtin_available_predicate avail); + + B1(min3) + B1(max3) + B1(mid3) + + ir_function_signature *_image_prototype(const glsl_type *image_type, + const char *intrinsic_name, + unsigned num_arguments, + unsigned flags); + ir_function_signature *_image(const glsl_type *image_type, + const char *intrinsic_name, + unsigned num_arguments, + unsigned flags); + + ir_function_signature *_memory_barrier_intrinsic( + builtin_available_predicate avail); + ir_function_signature *_memory_barrier( + builtin_available_predicate avail); + +#undef B0 +#undef B1 +#undef B2 +#undef B3 +#undef BA1 +#undef BA2 + /** @} */ +}; + +} /* anonymous namespace */ + +/** + * Core builtin_builder functionality: + * @{ + */ +builtin_builder::builtin_builder() + : shader(NULL), + gl_ModelViewProjectionMatrix(NULL), + gl_Vertex(NULL) +{ + mem_ctx = NULL; +} + +builtin_builder::~builtin_builder() +{ + ralloc_free(mem_ctx); +} + +ir_function_signature * +builtin_builder::find(_mesa_glsl_parse_state *state, + const char *name, exec_list *actual_parameters) +{ + /* The shader currently being compiled requested a built-in function; + * it needs to link against builtin_builder::shader in order to get them. + * + * Even if we don't find a matching signature, we still need to do this so + * that the "no matching signature" error will list potential candidates + * from the available built-ins. + */ + state->uses_builtin_functions = true; + + ir_function *f = shader->symbols->get_function(name); + if (f == NULL) + return NULL; + + ir_function_signature *sig = f->matching_signature(state, actual_parameters); + if (sig == NULL) + return NULL; + + return sig; +} + +void +builtin_builder::initialize() +{ + /* If already initialized, don't do it again. */ + if (mem_ctx != NULL) + return; + + mem_ctx = ralloc_context(NULL); + create_shader(); + create_intrinsics(); + create_builtins(); +} + +void +builtin_builder::release() +{ + ralloc_free(mem_ctx); + mem_ctx = NULL; + + ralloc_free(shader); + shader = NULL; +} + +void +builtin_builder::create_shader() +{ + /* The target doesn't actually matter. There's no target for generic + * GLSL utility code that could be linked against any stage, so just + * arbitrarily pick GL_VERTEX_SHADER. + */ + shader = _mesa_new_shader(NULL, 0, GL_VERTEX_SHADER); + shader->symbols = new(mem_ctx) glsl_symbol_table; + + gl_ModelViewProjectionMatrix = + new(mem_ctx) ir_variable(glsl_type::mat4_type, + "gl_ModelViewProjectionMatrix", + ir_var_uniform); + + shader->symbols->add_variable(gl_ModelViewProjectionMatrix); + + gl_Vertex = in_var(glsl_type::vec4_type, "gl_Vertex"); + shader->symbols->add_variable(gl_Vertex); +} + +/** @} */ + +/** + * Create ir_function and ir_function_signature objects for each + * intrinsic. + */ +void +builtin_builder::create_intrinsics() +{ + add_function("__intrinsic_atomic_read", + _atomic_intrinsic(shader_atomic_counters), + NULL); + add_function("__intrinsic_atomic_increment", + _atomic_intrinsic(shader_atomic_counters), + NULL); + add_function("__intrinsic_atomic_predecrement", + _atomic_intrinsic(shader_atomic_counters), + NULL); + + add_image_functions(false); + + add_function("__intrinsic_memory_barrier", + _memory_barrier_intrinsic(shader_image_load_store), + NULL); +} + +/** + * Create ir_function and ir_function_signature objects for each built-in. + * + * Contains a list of every available built-in. + */ +void +builtin_builder::create_builtins() +{ +#define F(NAME) \ + add_function(#NAME, \ + _##NAME(glsl_type::float_type), \ + _##NAME(glsl_type::vec2_type), \ + _##NAME(glsl_type::vec3_type), \ + _##NAME(glsl_type::vec4_type), \ + NULL); + +#define FI(NAME) \ + add_function(#NAME, \ + _##NAME(glsl_type::float_type), \ + _##NAME(glsl_type::vec2_type), \ + _##NAME(glsl_type::vec3_type), \ + _##NAME(glsl_type::vec4_type), \ + _##NAME(glsl_type::int_type), \ + _##NAME(glsl_type::ivec2_type), \ + _##NAME(glsl_type::ivec3_type), \ + _##NAME(glsl_type::ivec4_type), \ + NULL); + +#define FIU(NAME) \ + add_function(#NAME, \ + _##NAME(always_available, glsl_type::float_type), \ + _##NAME(always_available, glsl_type::vec2_type), \ + _##NAME(always_available, glsl_type::vec3_type), \ + _##NAME(always_available, glsl_type::vec4_type), \ + \ + _##NAME(always_available, glsl_type::int_type), \ + _##NAME(always_available, glsl_type::ivec2_type), \ + _##NAME(always_available, glsl_type::ivec3_type), \ + _##NAME(always_available, glsl_type::ivec4_type), \ + \ + _##NAME(v130, glsl_type::uint_type), \ + _##NAME(v130, glsl_type::uvec2_type), \ + _##NAME(v130, glsl_type::uvec3_type), \ + _##NAME(v130, glsl_type::uvec4_type), \ + NULL); + +#define IU(NAME) \ + add_function(#NAME, \ + _##NAME(glsl_type::int_type), \ + _##NAME(glsl_type::ivec2_type), \ + _##NAME(glsl_type::ivec3_type), \ + _##NAME(glsl_type::ivec4_type), \ + \ + _##NAME(glsl_type::uint_type), \ + _##NAME(glsl_type::uvec2_type), \ + _##NAME(glsl_type::uvec3_type), \ + _##NAME(glsl_type::uvec4_type), \ + NULL); + +#define FIUB(NAME) \ + add_function(#NAME, \ + _##NAME(always_available, glsl_type::float_type), \ + _##NAME(always_available, glsl_type::vec2_type), \ + _##NAME(always_available, glsl_type::vec3_type), \ + _##NAME(always_available, glsl_type::vec4_type), \ + \ + _##NAME(always_available, glsl_type::int_type), \ + _##NAME(always_available, glsl_type::ivec2_type), \ + _##NAME(always_available, glsl_type::ivec3_type), \ + _##NAME(always_available, glsl_type::ivec4_type), \ + \ + _##NAME(v130, glsl_type::uint_type), \ + _##NAME(v130, glsl_type::uvec2_type), \ + _##NAME(v130, glsl_type::uvec3_type), \ + _##NAME(v130, glsl_type::uvec4_type), \ + \ + _##NAME(always_available, glsl_type::bool_type), \ + _##NAME(always_available, glsl_type::bvec2_type), \ + _##NAME(always_available, glsl_type::bvec3_type), \ + _##NAME(always_available, glsl_type::bvec4_type), \ + NULL); + +#define FIU2_MIXED(NAME) \ + add_function(#NAME, \ + _##NAME(always_available, glsl_type::float_type, glsl_type::float_type), \ + _##NAME(always_available, glsl_type::vec2_type, glsl_type::float_type), \ + _##NAME(always_available, glsl_type::vec3_type, glsl_type::float_type), \ + _##NAME(always_available, glsl_type::vec4_type, glsl_type::float_type), \ + \ + _##NAME(always_available, glsl_type::vec2_type, glsl_type::vec2_type), \ + _##NAME(always_available, glsl_type::vec3_type, glsl_type::vec3_type), \ + _##NAME(always_available, glsl_type::vec4_type, glsl_type::vec4_type), \ + \ + _##NAME(always_available, glsl_type::int_type, glsl_type::int_type), \ + _##NAME(always_available, glsl_type::ivec2_type, glsl_type::int_type), \ + _##NAME(always_available, glsl_type::ivec3_type, glsl_type::int_type), \ + _##NAME(always_available, glsl_type::ivec4_type, glsl_type::int_type), \ + \ + _##NAME(always_available, glsl_type::ivec2_type, glsl_type::ivec2_type), \ + _##NAME(always_available, glsl_type::ivec3_type, glsl_type::ivec3_type), \ + _##NAME(always_available, glsl_type::ivec4_type, glsl_type::ivec4_type), \ + \ + _##NAME(v130, glsl_type::uint_type, glsl_type::uint_type), \ + _##NAME(v130, glsl_type::uvec2_type, glsl_type::uint_type), \ + _##NAME(v130, glsl_type::uvec3_type, glsl_type::uint_type), \ + _##NAME(v130, glsl_type::uvec4_type, glsl_type::uint_type), \ + \ + _##NAME(v130, glsl_type::uvec2_type, glsl_type::uvec2_type), \ + _##NAME(v130, glsl_type::uvec3_type, glsl_type::uvec3_type), \ + _##NAME(v130, glsl_type::uvec4_type, glsl_type::uvec4_type), \ + NULL); + + F(radians) + F(degrees) + F(sin) + F(cos) + F(tan) + F(asin) + F(acos) + + add_function("atan", + _atan(glsl_type::float_type), + _atan(glsl_type::vec2_type), + _atan(glsl_type::vec3_type), + _atan(glsl_type::vec4_type), + _atan2(glsl_type::float_type), + _atan2(glsl_type::vec2_type), + _atan2(glsl_type::vec3_type), + _atan2(glsl_type::vec4_type), + NULL); + + F(sinh) + F(cosh) + F(tanh) + F(asinh) + F(acosh) + F(atanh) + F(pow) + F(exp) + F(log) + F(exp2) + F(log2) + F(sqrt) + F(inversesqrt) + FI(abs) + FI(sign) + F(floor) + F(trunc) + F(round) + F(roundEven) + F(ceil) + F(fract) + + add_function("mod", + _mod(glsl_type::float_type, glsl_type::float_type), + _mod(glsl_type::vec2_type, glsl_type::float_type), + _mod(glsl_type::vec3_type, glsl_type::float_type), + _mod(glsl_type::vec4_type, glsl_type::float_type), + + _mod(glsl_type::vec2_type, glsl_type::vec2_type), + _mod(glsl_type::vec3_type, glsl_type::vec3_type), + _mod(glsl_type::vec4_type, glsl_type::vec4_type), + NULL); + + F(modf) + + FIU2_MIXED(min) + FIU2_MIXED(max) + FIU2_MIXED(clamp) + + add_function("mix", + _mix_lrp(glsl_type::float_type, glsl_type::float_type), + _mix_lrp(glsl_type::vec2_type, glsl_type::float_type), + _mix_lrp(glsl_type::vec3_type, glsl_type::float_type), + _mix_lrp(glsl_type::vec4_type, glsl_type::float_type), + + _mix_lrp(glsl_type::vec2_type, glsl_type::vec2_type), + _mix_lrp(glsl_type::vec3_type, glsl_type::vec3_type), + _mix_lrp(glsl_type::vec4_type, glsl_type::vec4_type), + + _mix_sel(v130, glsl_type::float_type, glsl_type::bool_type), + _mix_sel(v130, glsl_type::vec2_type, glsl_type::bvec2_type), + _mix_sel(v130, glsl_type::vec3_type, glsl_type::bvec3_type), + _mix_sel(v130, glsl_type::vec4_type, glsl_type::bvec4_type), + + _mix_sel(shader_integer_mix, glsl_type::int_type, glsl_type::bool_type), + _mix_sel(shader_integer_mix, glsl_type::ivec2_type, glsl_type::bvec2_type), + _mix_sel(shader_integer_mix, glsl_type::ivec3_type, glsl_type::bvec3_type), + _mix_sel(shader_integer_mix, glsl_type::ivec4_type, glsl_type::bvec4_type), + + _mix_sel(shader_integer_mix, glsl_type::uint_type, glsl_type::bool_type), + _mix_sel(shader_integer_mix, glsl_type::uvec2_type, glsl_type::bvec2_type), + _mix_sel(shader_integer_mix, glsl_type::uvec3_type, glsl_type::bvec3_type), + _mix_sel(shader_integer_mix, glsl_type::uvec4_type, glsl_type::bvec4_type), + + _mix_sel(shader_integer_mix, glsl_type::bool_type, glsl_type::bool_type), + _mix_sel(shader_integer_mix, glsl_type::bvec2_type, glsl_type::bvec2_type), + _mix_sel(shader_integer_mix, glsl_type::bvec3_type, glsl_type::bvec3_type), + _mix_sel(shader_integer_mix, glsl_type::bvec4_type, glsl_type::bvec4_type), + NULL); + + add_function("step", + _step(glsl_type::float_type, glsl_type::float_type), + _step(glsl_type::float_type, glsl_type::vec2_type), + _step(glsl_type::float_type, glsl_type::vec3_type), + _step(glsl_type::float_type, glsl_type::vec4_type), + + _step(glsl_type::vec2_type, glsl_type::vec2_type), + _step(glsl_type::vec3_type, glsl_type::vec3_type), + _step(glsl_type::vec4_type, glsl_type::vec4_type), + NULL); + + add_function("smoothstep", + _smoothstep(glsl_type::float_type, glsl_type::float_type), + _smoothstep(glsl_type::float_type, glsl_type::vec2_type), + _smoothstep(glsl_type::float_type, glsl_type::vec3_type), + _smoothstep(glsl_type::float_type, glsl_type::vec4_type), + + _smoothstep(glsl_type::vec2_type, glsl_type::vec2_type), + _smoothstep(glsl_type::vec3_type, glsl_type::vec3_type), + _smoothstep(glsl_type::vec4_type, glsl_type::vec4_type), + NULL); + + F(isnan) + F(isinf) + + F(floatBitsToInt) + F(floatBitsToUint) + add_function("intBitsToFloat", + _intBitsToFloat(glsl_type::int_type), + _intBitsToFloat(glsl_type::ivec2_type), + _intBitsToFloat(glsl_type::ivec3_type), + _intBitsToFloat(glsl_type::ivec4_type), + NULL); + add_function("uintBitsToFloat", + _uintBitsToFloat(glsl_type::uint_type), + _uintBitsToFloat(glsl_type::uvec2_type), + _uintBitsToFloat(glsl_type::uvec3_type), + _uintBitsToFloat(glsl_type::uvec4_type), + NULL); + + add_function("packUnorm2x16", _packUnorm2x16(shader_packing_or_es3_or_gpu_shader5), NULL); + add_function("packSnorm2x16", _packSnorm2x16(shader_packing_or_es3), NULL); + add_function("packUnorm4x8", _packUnorm4x8(shader_packing_or_gpu_shader5), NULL); + add_function("packSnorm4x8", _packSnorm4x8(shader_packing_or_gpu_shader5), NULL); + add_function("unpackUnorm2x16", _unpackUnorm2x16(shader_packing_or_es3_or_gpu_shader5), NULL); + add_function("unpackSnorm2x16", _unpackSnorm2x16(shader_packing_or_es3), NULL); + add_function("unpackUnorm4x8", _unpackUnorm4x8(shader_packing_or_gpu_shader5), NULL); + add_function("unpackSnorm4x8", _unpackSnorm4x8(shader_packing_or_gpu_shader5), NULL); + add_function("packHalf2x16", _packHalf2x16(shader_packing_or_es3), NULL); + add_function("unpackHalf2x16", _unpackHalf2x16(shader_packing_or_es3), NULL); + + F(length) + F(distance) + F(dot) + + add_function("cross", _cross(glsl_type::vec3_type), NULL); + + F(normalize) + add_function("ftransform", _ftransform(), NULL); + F(faceforward) + F(reflect) + F(refract) + // ... + add_function("matrixCompMult", + _matrixCompMult(glsl_type::mat2_type), + _matrixCompMult(glsl_type::mat3_type), + _matrixCompMult(glsl_type::mat4_type), + _matrixCompMult(glsl_type::mat2x3_type), + _matrixCompMult(glsl_type::mat2x4_type), + _matrixCompMult(glsl_type::mat3x2_type), + _matrixCompMult(glsl_type::mat3x4_type), + _matrixCompMult(glsl_type::mat4x2_type), + _matrixCompMult(glsl_type::mat4x3_type), + NULL); + add_function("outerProduct", + _outerProduct(glsl_type::mat2_type), + _outerProduct(glsl_type::mat3_type), + _outerProduct(glsl_type::mat4_type), + _outerProduct(glsl_type::mat2x3_type), + _outerProduct(glsl_type::mat2x4_type), + _outerProduct(glsl_type::mat3x2_type), + _outerProduct(glsl_type::mat3x4_type), + _outerProduct(glsl_type::mat4x2_type), + _outerProduct(glsl_type::mat4x3_type), + NULL); + add_function("determinant", + _determinant_mat2(), + _determinant_mat3(), + _determinant_mat4(), + NULL); + add_function("inverse", + _inverse_mat2(), + _inverse_mat3(), + _inverse_mat4(), + NULL); + add_function("transpose", + _transpose(glsl_type::mat2_type), + _transpose(glsl_type::mat3_type), + _transpose(glsl_type::mat4_type), + _transpose(glsl_type::mat2x3_type), + _transpose(glsl_type::mat2x4_type), + _transpose(glsl_type::mat3x2_type), + _transpose(glsl_type::mat3x4_type), + _transpose(glsl_type::mat4x2_type), + _transpose(glsl_type::mat4x3_type), + NULL); + FIU(lessThan) + FIU(lessThanEqual) + FIU(greaterThan) + FIU(greaterThanEqual) + FIUB(notEqual) + FIUB(equal) + + add_function("any", + _any(glsl_type::bvec2_type), + _any(glsl_type::bvec3_type), + _any(glsl_type::bvec4_type), + NULL); + + add_function("all", + _all(glsl_type::bvec2_type), + _all(glsl_type::bvec3_type), + _all(glsl_type::bvec4_type), + NULL); + + add_function("not", + _not(glsl_type::bvec2_type), + _not(glsl_type::bvec3_type), + _not(glsl_type::bvec4_type), + NULL); + + add_function("textureSize", + _textureSize(v130, glsl_type::int_type, glsl_type::sampler1D_type), + _textureSize(v130, glsl_type::int_type, glsl_type::isampler1D_type), + _textureSize(v130, glsl_type::int_type, glsl_type::usampler1D_type), + + _textureSize(v130, glsl_type::ivec2_type, glsl_type::sampler2D_type), + _textureSize(v130, glsl_type::ivec2_type, glsl_type::isampler2D_type), + _textureSize(v130, glsl_type::ivec2_type, glsl_type::usampler2D_type), + + _textureSize(v130, glsl_type::ivec3_type, glsl_type::sampler3D_type), + _textureSize(v130, glsl_type::ivec3_type, glsl_type::isampler3D_type), + _textureSize(v130, glsl_type::ivec3_type, glsl_type::usampler3D_type), + + _textureSize(v130, glsl_type::ivec2_type, glsl_type::samplerCube_type), + _textureSize(v130, glsl_type::ivec2_type, glsl_type::isamplerCube_type), + _textureSize(v130, glsl_type::ivec2_type, glsl_type::usamplerCube_type), + + _textureSize(v130, glsl_type::int_type, glsl_type::sampler1DShadow_type), + _textureSize(v130, glsl_type::ivec2_type, glsl_type::sampler2DShadow_type), + _textureSize(v130, glsl_type::ivec2_type, glsl_type::samplerCubeShadow_type), + + _textureSize(v130, glsl_type::ivec2_type, glsl_type::sampler1DArray_type), + _textureSize(v130, glsl_type::ivec2_type, glsl_type::isampler1DArray_type), + _textureSize(v130, glsl_type::ivec2_type, glsl_type::usampler1DArray_type), + _textureSize(v130, glsl_type::ivec3_type, glsl_type::sampler2DArray_type), + _textureSize(v130, glsl_type::ivec3_type, glsl_type::isampler2DArray_type), + _textureSize(v130, glsl_type::ivec3_type, glsl_type::usampler2DArray_type), + + _textureSize(v130, glsl_type::ivec2_type, glsl_type::sampler1DArrayShadow_type), + _textureSize(v130, glsl_type::ivec3_type, glsl_type::sampler2DArrayShadow_type), + + _textureSize(texture_cube_map_array, glsl_type::ivec3_type, glsl_type::samplerCubeArray_type), + _textureSize(texture_cube_map_array, glsl_type::ivec3_type, glsl_type::isamplerCubeArray_type), + _textureSize(texture_cube_map_array, glsl_type::ivec3_type, glsl_type::usamplerCubeArray_type), + _textureSize(texture_cube_map_array, glsl_type::ivec3_type, glsl_type::samplerCubeArrayShadow_type), + + _textureSize(v130, glsl_type::ivec2_type, glsl_type::sampler2DRect_type), + _textureSize(v130, glsl_type::ivec2_type, glsl_type::isampler2DRect_type), + _textureSize(v130, glsl_type::ivec2_type, glsl_type::usampler2DRect_type), + _textureSize(v130, glsl_type::ivec2_type, glsl_type::sampler2DRectShadow_type), + + _textureSize(v140, glsl_type::int_type, glsl_type::samplerBuffer_type), + _textureSize(v140, glsl_type::int_type, glsl_type::isamplerBuffer_type), + _textureSize(v140, glsl_type::int_type, glsl_type::usamplerBuffer_type), + _textureSize(texture_multisample, glsl_type::ivec2_type, glsl_type::sampler2DMS_type), + _textureSize(texture_multisample, glsl_type::ivec2_type, glsl_type::isampler2DMS_type), + _textureSize(texture_multisample, glsl_type::ivec2_type, glsl_type::usampler2DMS_type), + + _textureSize(texture_multisample, glsl_type::ivec3_type, glsl_type::sampler2DMSArray_type), + _textureSize(texture_multisample, glsl_type::ivec3_type, glsl_type::isampler2DMSArray_type), + _textureSize(texture_multisample, glsl_type::ivec3_type, glsl_type::usampler2DMSArray_type), + NULL); + + add_function("texture", + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::float_type), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::float_type), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::float_type), + + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type), + + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec3_type), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::vec3_type), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::vec3_type), + + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isamplerCube_type, glsl_type::vec3_type), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usamplerCube_type, glsl_type::vec3_type), + + _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, glsl_type::vec3_type), + _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, glsl_type::vec3_type), + _texture(ir_tex, v130, glsl_type::float_type, glsl_type::samplerCubeShadow_type, glsl_type::vec4_type), + + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler1DArray_type, glsl_type::vec2_type), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, glsl_type::vec2_type), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, glsl_type::vec2_type), + + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type), + + _texture(ir_tex, texture_cube_map_array, glsl_type::vec4_type, glsl_type::samplerCubeArray_type, glsl_type::vec4_type), + _texture(ir_tex, texture_cube_map_array, glsl_type::ivec4_type, glsl_type::isamplerCubeArray_type, glsl_type::vec4_type), + _texture(ir_tex, texture_cube_map_array, glsl_type::uvec4_type, glsl_type::usamplerCubeArray_type, glsl_type::vec4_type), + + _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler1DArrayShadow_type, glsl_type::vec3_type), + _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec4_type), + /* samplerCubeArrayShadow is special; it has an extra parameter + * for the shadow comparitor since there is no vec5 type. + */ + _textureCubeArrayShadow(), + + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type), + + _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec3_type), + + _texture(ir_txb, v130_fs_only, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::float_type), + _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::float_type), + _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::float_type), + + _texture(ir_txb, v130_fs_only, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type), + _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type), + _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type), + + _texture(ir_txb, v130_fs_only, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec3_type), + _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::vec3_type), + _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::vec3_type), + + _texture(ir_txb, v130_fs_only, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type), + _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isamplerCube_type, glsl_type::vec3_type), + _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usamplerCube_type, glsl_type::vec3_type), + + _texture(ir_txb, v130_fs_only, glsl_type::float_type, glsl_type::sampler1DShadow_type, glsl_type::vec3_type), + _texture(ir_txb, v130_fs_only, glsl_type::float_type, glsl_type::sampler2DShadow_type, glsl_type::vec3_type), + _texture(ir_txb, v130_fs_only, glsl_type::float_type, glsl_type::samplerCubeShadow_type, glsl_type::vec4_type), + + _texture(ir_txb, v130_fs_only, glsl_type::vec4_type, glsl_type::sampler1DArray_type, glsl_type::vec2_type), + _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, glsl_type::vec2_type), + _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, glsl_type::vec2_type), + + _texture(ir_txb, v130_fs_only, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type), + _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type), + _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type), + + _texture(ir_txb, fs_texture_cube_map_array, glsl_type::vec4_type, glsl_type::samplerCubeArray_type, glsl_type::vec4_type), + _texture(ir_txb, fs_texture_cube_map_array, glsl_type::ivec4_type, glsl_type::isamplerCubeArray_type, glsl_type::vec4_type), + _texture(ir_txb, fs_texture_cube_map_array, glsl_type::uvec4_type, glsl_type::usamplerCubeArray_type, glsl_type::vec4_type), + + _texture(ir_txb, v130_fs_only, glsl_type::float_type, glsl_type::sampler1DArrayShadow_type, glsl_type::vec3_type), + NULL); + + add_function("textureLod", + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::float_type), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::float_type), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::float_type), + + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type), + + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec3_type), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::vec3_type), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::vec3_type), + + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isamplerCube_type, glsl_type::vec3_type), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usamplerCube_type, glsl_type::vec3_type), + + _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, glsl_type::vec3_type), + _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, glsl_type::vec3_type), + + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler1DArray_type, glsl_type::vec2_type), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, glsl_type::vec2_type), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, glsl_type::vec2_type), + + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type), + + _texture(ir_txl, texture_cube_map_array, glsl_type::vec4_type, glsl_type::samplerCubeArray_type, glsl_type::vec4_type), + _texture(ir_txl, texture_cube_map_array, glsl_type::ivec4_type, glsl_type::isamplerCubeArray_type, glsl_type::vec4_type), + _texture(ir_txl, texture_cube_map_array, glsl_type::uvec4_type, glsl_type::usamplerCubeArray_type, glsl_type::vec4_type), + + _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler1DArrayShadow_type, glsl_type::vec3_type), + NULL); + + add_function("textureOffset", + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::float_type, TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::float_type, TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::float_type, TEX_OFFSET), + + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::vec3_type, TEX_OFFSET), + + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET), + + _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec3_type, TEX_OFFSET), + + _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, glsl_type::vec3_type, TEX_OFFSET), + + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler1DArray_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, glsl_type::vec2_type, TEX_OFFSET), + + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + + _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler1DArrayShadow_type, glsl_type::vec3_type, TEX_OFFSET), + + _texture(ir_txb, v130_fs_only, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::float_type, TEX_OFFSET), + _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::float_type, TEX_OFFSET), + _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::float_type, TEX_OFFSET), + + _texture(ir_txb, v130_fs_only, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + + _texture(ir_txb, v130_fs_only, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::vec3_type, TEX_OFFSET), + + _texture(ir_txb, v130_fs_only, glsl_type::float_type, glsl_type::sampler1DShadow_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_txb, v130_fs_only, glsl_type::float_type, glsl_type::sampler2DShadow_type, glsl_type::vec3_type, TEX_OFFSET), + + _texture(ir_txb, v130_fs_only, glsl_type::vec4_type, glsl_type::sampler1DArray_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, glsl_type::vec2_type, TEX_OFFSET), + + _texture(ir_txb, v130_fs_only, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_txb, v130_fs_only, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_txb, v130_fs_only, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + + _texture(ir_txb, v130_fs_only, glsl_type::float_type, glsl_type::sampler1DArrayShadow_type, glsl_type::vec3_type, TEX_OFFSET), + NULL); + + add_function("textureProj", + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec2_type, TEX_PROJECT), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::vec2_type, TEX_PROJECT), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::vec2_type, TEX_PROJECT), + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::vec4_type, TEX_PROJECT), + + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec4_type, TEX_PROJECT), + + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::vec4_type, TEX_PROJECT), + + _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, glsl_type::vec4_type, TEX_PROJECT), + + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec4_type, TEX_PROJECT), + + _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec4_type, TEX_PROJECT), + + _texture(ir_txb, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec2_type, TEX_PROJECT), + _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::vec2_type, TEX_PROJECT), + _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::vec2_type, TEX_PROJECT), + _texture(ir_txb, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::vec4_type, TEX_PROJECT), + + _texture(ir_txb, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_txb, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec4_type, TEX_PROJECT), + + _texture(ir_txb, v130, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::vec4_type, TEX_PROJECT), + + _texture(ir_txb, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txb, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("texelFetch", + _texelFetch(v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::int_type), + _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::int_type), + _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::int_type), + + _texelFetch(v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::ivec2_type), + _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::ivec2_type), + _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::ivec2_type), + + _texelFetch(v130, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::ivec3_type), + _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::ivec3_type), + _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::ivec3_type), + + _texelFetch(v130, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::ivec2_type), + _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::ivec2_type), + _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::ivec2_type), + + _texelFetch(v130, glsl_type::vec4_type, glsl_type::sampler1DArray_type, glsl_type::ivec2_type), + _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, glsl_type::ivec2_type), + _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, glsl_type::ivec2_type), + + _texelFetch(v130, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::ivec3_type), + _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::ivec3_type), + _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::ivec3_type), + + _texelFetch(v140, glsl_type::vec4_type, glsl_type::samplerBuffer_type, glsl_type::int_type), + _texelFetch(v140, glsl_type::ivec4_type, glsl_type::isamplerBuffer_type, glsl_type::int_type), + _texelFetch(v140, glsl_type::uvec4_type, glsl_type::usamplerBuffer_type, glsl_type::int_type), + + _texelFetch(texture_multisample, glsl_type::vec4_type, glsl_type::sampler2DMS_type, glsl_type::ivec2_type), + _texelFetch(texture_multisample, glsl_type::ivec4_type, glsl_type::isampler2DMS_type, glsl_type::ivec2_type), + _texelFetch(texture_multisample, glsl_type::uvec4_type, glsl_type::usampler2DMS_type, glsl_type::ivec2_type), + + _texelFetch(texture_multisample, glsl_type::vec4_type, glsl_type::sampler2DMSArray_type, glsl_type::ivec3_type), + _texelFetch(texture_multisample, glsl_type::ivec4_type, glsl_type::isampler2DMSArray_type, glsl_type::ivec3_type), + _texelFetch(texture_multisample, glsl_type::uvec4_type, glsl_type::usampler2DMSArray_type, glsl_type::ivec3_type), + NULL); + + add_function("texelFetchOffset", + _texelFetch(v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::int_type, glsl_type::int_type), + _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::int_type, glsl_type::int_type), + _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::int_type, glsl_type::int_type), + + _texelFetch(v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::ivec2_type, glsl_type::ivec2_type), + _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::ivec2_type, glsl_type::ivec2_type), + _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::ivec2_type, glsl_type::ivec2_type), + + _texelFetch(v130, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::ivec3_type, glsl_type::ivec3_type), + _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::ivec3_type, glsl_type::ivec3_type), + _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::ivec3_type, glsl_type::ivec3_type), + + _texelFetch(v130, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::ivec2_type, glsl_type::ivec2_type), + _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::ivec2_type, glsl_type::ivec2_type), + _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::ivec2_type, glsl_type::ivec2_type), + + _texelFetch(v130, glsl_type::vec4_type, glsl_type::sampler1DArray_type, glsl_type::ivec2_type, glsl_type::int_type), + _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, glsl_type::ivec2_type, glsl_type::int_type), + _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, glsl_type::ivec2_type, glsl_type::int_type), + + _texelFetch(v130, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::ivec3_type, glsl_type::ivec2_type), + _texelFetch(v130, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::ivec3_type, glsl_type::ivec2_type), + _texelFetch(v130, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::ivec3_type, glsl_type::ivec2_type), + + NULL); + + add_function("textureProjOffset", + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + + _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_tex, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + + _texture(ir_tex, v130, glsl_type::float_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + + _texture(ir_txb, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txb, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + + _texture(ir_txb, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txb, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + + _texture(ir_txb, v130, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txb, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txb, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + + _texture(ir_txb, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txb, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + NULL); + + add_function("textureLodOffset", + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::float_type, TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::float_type, TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::float_type, TEX_OFFSET), + + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::vec3_type, TEX_OFFSET), + + _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, glsl_type::vec3_type, TEX_OFFSET), + + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler1DArray_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, glsl_type::vec2_type, TEX_OFFSET), + + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + + _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler1DArrayShadow_type, glsl_type::vec3_type, TEX_OFFSET), + NULL); + + add_function("textureProjLod", + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec2_type, TEX_PROJECT), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::vec2_type, TEX_PROJECT), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::vec2_type, TEX_PROJECT), + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::vec4_type, TEX_PROJECT), + + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec4_type, TEX_PROJECT), + + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::vec4_type, TEX_PROJECT), + + _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("textureProjLodOffset", + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + + _texture(ir_txl, v130, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + + _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txl, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + NULL); + + add_function("textureGrad", + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::float_type), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::float_type), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::float_type), + + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type), + + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec3_type), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::vec3_type), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::vec3_type), + + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isamplerCube_type, glsl_type::vec3_type), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usamplerCube_type, glsl_type::vec3_type), + + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type), + + _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec3_type), + + _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, glsl_type::vec3_type), + _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, glsl_type::vec3_type), + _texture(ir_txd, v130, glsl_type::float_type, glsl_type::samplerCubeShadow_type, glsl_type::vec4_type), + + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler1DArray_type, glsl_type::vec2_type), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, glsl_type::vec2_type), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, glsl_type::vec2_type), + + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type), + + _texture(ir_txd, texture_cube_map_array, glsl_type::vec4_type, glsl_type::samplerCubeArray_type, glsl_type::vec4_type), + _texture(ir_txd, texture_cube_map_array, glsl_type::ivec4_type, glsl_type::isamplerCubeArray_type, glsl_type::vec4_type), + _texture(ir_txd, texture_cube_map_array, glsl_type::uvec4_type, glsl_type::usamplerCubeArray_type, glsl_type::vec4_type), + + _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler1DArrayShadow_type, glsl_type::vec3_type), + _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec4_type), + NULL); + + add_function("textureGradOffset", + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::float_type, TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::float_type, TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::float_type, TEX_OFFSET), + + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::vec3_type, TEX_OFFSET), + + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET), + + _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec3_type, TEX_OFFSET), + + _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, glsl_type::vec3_type, TEX_OFFSET), + + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler1DArray_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler1DArray_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler1DArray_type, glsl_type::vec2_type, TEX_OFFSET), + + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + + _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler1DArrayShadow_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec4_type, TEX_OFFSET), + NULL); + + add_function("textureProjGrad", + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec2_type, TEX_PROJECT), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::vec2_type, TEX_PROJECT), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::vec2_type, TEX_PROJECT), + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::vec4_type, TEX_PROJECT), + + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec4_type, TEX_PROJECT), + + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::vec4_type, TEX_PROJECT), + + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec4_type, TEX_PROJECT), + + _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec4_type, TEX_PROJECT), + + _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("textureProjGradOffset", + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::vec2_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler1D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler1D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler3D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler3D_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec3_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + + _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + + _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler1DShadow_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + _texture(ir_txd, v130, glsl_type::float_type, glsl_type::sampler2DShadow_type, glsl_type::vec4_type, TEX_PROJECT | TEX_OFFSET), + NULL); + + add_function("EmitVertex", _EmitVertex(), NULL); + add_function("EndPrimitive", _EndPrimitive(), NULL); + + add_function("textureQueryLOD", + _textureQueryLod(glsl_type::sampler1D_type, glsl_type::float_type), + _textureQueryLod(glsl_type::isampler1D_type, glsl_type::float_type), + _textureQueryLod(glsl_type::usampler1D_type, glsl_type::float_type), + + _textureQueryLod(glsl_type::sampler2D_type, glsl_type::vec2_type), + _textureQueryLod(glsl_type::isampler2D_type, glsl_type::vec2_type), + _textureQueryLod(glsl_type::usampler2D_type, glsl_type::vec2_type), + + _textureQueryLod(glsl_type::sampler3D_type, glsl_type::vec3_type), + _textureQueryLod(glsl_type::isampler3D_type, glsl_type::vec3_type), + _textureQueryLod(glsl_type::usampler3D_type, glsl_type::vec3_type), + + _textureQueryLod(glsl_type::samplerCube_type, glsl_type::vec3_type), + _textureQueryLod(glsl_type::isamplerCube_type, glsl_type::vec3_type), + _textureQueryLod(glsl_type::usamplerCube_type, glsl_type::vec3_type), + + _textureQueryLod(glsl_type::sampler1DArray_type, glsl_type::float_type), + _textureQueryLod(glsl_type::isampler1DArray_type, glsl_type::float_type), + _textureQueryLod(glsl_type::usampler1DArray_type, glsl_type::float_type), + + _textureQueryLod(glsl_type::sampler2DArray_type, glsl_type::vec2_type), + _textureQueryLod(glsl_type::isampler2DArray_type, glsl_type::vec2_type), + _textureQueryLod(glsl_type::usampler2DArray_type, glsl_type::vec2_type), + + _textureQueryLod(glsl_type::samplerCubeArray_type, glsl_type::vec3_type), + _textureQueryLod(glsl_type::isamplerCubeArray_type, glsl_type::vec3_type), + _textureQueryLod(glsl_type::usamplerCubeArray_type, glsl_type::vec3_type), + + _textureQueryLod(glsl_type::sampler1DShadow_type, glsl_type::float_type), + _textureQueryLod(glsl_type::sampler2DShadow_type, glsl_type::vec2_type), + _textureQueryLod(glsl_type::samplerCubeShadow_type, glsl_type::vec3_type), + _textureQueryLod(glsl_type::sampler1DArrayShadow_type, glsl_type::float_type), + _textureQueryLod(glsl_type::sampler2DArrayShadow_type, glsl_type::vec2_type), + _textureQueryLod(glsl_type::samplerCubeArrayShadow_type, glsl_type::vec3_type), + NULL); + + add_function("textureQueryLevels", + _textureQueryLevels(glsl_type::sampler1D_type), + _textureQueryLevels(glsl_type::sampler2D_type), + _textureQueryLevels(glsl_type::sampler3D_type), + _textureQueryLevels(glsl_type::samplerCube_type), + _textureQueryLevels(glsl_type::sampler1DArray_type), + _textureQueryLevels(glsl_type::sampler2DArray_type), + _textureQueryLevels(glsl_type::samplerCubeArray_type), + _textureQueryLevels(glsl_type::sampler1DShadow_type), + _textureQueryLevels(glsl_type::sampler2DShadow_type), + _textureQueryLevels(glsl_type::samplerCubeShadow_type), + _textureQueryLevels(glsl_type::sampler1DArrayShadow_type), + _textureQueryLevels(glsl_type::sampler2DArrayShadow_type), + _textureQueryLevels(glsl_type::samplerCubeArrayShadow_type), + + _textureQueryLevels(glsl_type::isampler1D_type), + _textureQueryLevels(glsl_type::isampler2D_type), + _textureQueryLevels(glsl_type::isampler3D_type), + _textureQueryLevels(glsl_type::isamplerCube_type), + _textureQueryLevels(glsl_type::isampler1DArray_type), + _textureQueryLevels(glsl_type::isampler2DArray_type), + _textureQueryLevels(glsl_type::isamplerCubeArray_type), + + _textureQueryLevels(glsl_type::usampler1D_type), + _textureQueryLevels(glsl_type::usampler2D_type), + _textureQueryLevels(glsl_type::usampler3D_type), + _textureQueryLevels(glsl_type::usamplerCube_type), + _textureQueryLevels(glsl_type::usampler1DArray_type), + _textureQueryLevels(glsl_type::usampler2DArray_type), + _textureQueryLevels(glsl_type::usamplerCubeArray_type), + + NULL); + + add_function("texture1D", + _texture(ir_tex, v110, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::float_type), + _texture(ir_txb, v110_fs_only, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::float_type), + NULL); + + add_function("texture1DArray", + _texture(ir_tex, texture_array, glsl_type::vec4_type, glsl_type::sampler1DArray_type, glsl_type::vec2_type), + _texture(ir_txb, fs_texture_array, glsl_type::vec4_type, glsl_type::sampler1DArray_type, glsl_type::vec2_type), + NULL); + + add_function("texture1DProj", + _texture(ir_tex, v110, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec2_type, TEX_PROJECT), + _texture(ir_tex, v110, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txb, v110_fs_only, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec2_type, TEX_PROJECT), + _texture(ir_txb, v110_fs_only, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("texture1DLod", + _texture(ir_txl, tex1d_lod, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::float_type), + NULL); + + add_function("texture1DArrayLod", + _texture(ir_txl, texture_array_lod, glsl_type::vec4_type, glsl_type::sampler1DArray_type, glsl_type::vec2_type), + NULL); + + add_function("texture1DProjLod", + _texture(ir_txl, tex1d_lod, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec2_type, TEX_PROJECT), + _texture(ir_txl, tex1d_lod, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("texture2D", + _texture(ir_tex, always_available, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type), + _texture(ir_txb, fs_only, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type), + _texture(ir_tex, texture_external, glsl_type::vec4_type, glsl_type::samplerExternalOES_type, glsl_type::vec2_type), + NULL); + + add_function("texture2DArray", + _texture(ir_tex, texture_array, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type), + _texture(ir_txb, fs_texture_array, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type), + NULL); + + add_function("texture2DProj", + _texture(ir_tex, always_available, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_tex, always_available, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txb, fs_only, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_txb, fs_only, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_tex, texture_external, glsl_type::vec4_type, glsl_type::samplerExternalOES_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_tex, texture_external, glsl_type::vec4_type, glsl_type::samplerExternalOES_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("texture2DLod", + _texture(ir_txl, lod_exists_in_stage, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type), + NULL); + + add_function("texture2DArrayLod", + _texture(ir_txl, texture_array_lod, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type), + NULL); + + add_function("texture2DProjLod", + _texture(ir_txl, v110_lod, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_txl, v110_lod, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("texture3D", + _texture(ir_tex, tex3d, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec3_type), + _texture(ir_txb, fs_tex3d, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec3_type), + NULL); + + add_function("texture3DProj", + _texture(ir_tex, tex3d, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txb, fs_tex3d, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("texture3DLod", + _texture(ir_txl, tex3d_lod, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec3_type), + NULL); + + add_function("texture3DProjLod", + _texture(ir_txl, tex3d_lod, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("textureCube", + _texture(ir_tex, always_available, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type), + _texture(ir_txb, fs_only, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type), + NULL); + + add_function("textureCubeLod", + _texture(ir_txl, v110_lod, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type), + NULL); + + add_function("texture2DRect", + _texture(ir_tex, texture_rectangle, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type), + NULL); + + add_function("texture2DRectProj", + _texture(ir_tex, texture_rectangle, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_tex, texture_rectangle, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("shadow1D", + _texture(ir_tex, v110, glsl_type::vec4_type, glsl_type::sampler1DShadow_type, glsl_type::vec3_type), + _texture(ir_txb, v110_fs_only, glsl_type::vec4_type, glsl_type::sampler1DShadow_type, glsl_type::vec3_type), + NULL); + + add_function("shadow1DArray", + _texture(ir_tex, texture_array, glsl_type::vec4_type, glsl_type::sampler1DArrayShadow_type, glsl_type::vec3_type), + _texture(ir_txb, fs_texture_array, glsl_type::vec4_type, glsl_type::sampler1DArrayShadow_type, glsl_type::vec3_type), + NULL); + + add_function("shadow2D", + _texture(ir_tex, v110, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec3_type), + _texture(ir_txb, v110_fs_only, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec3_type), + NULL); + + add_function("shadow2DArray", + _texture(ir_tex, texture_array, glsl_type::vec4_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec4_type), + _texture(ir_txb, fs_texture_array, glsl_type::vec4_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec4_type), + NULL); + + add_function("shadow1DProj", + _texture(ir_tex, v110, glsl_type::vec4_type, glsl_type::sampler1DShadow_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txb, v110_fs_only, glsl_type::vec4_type, glsl_type::sampler1DShadow_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("shadow2DProj", + _texture(ir_tex, v110, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec4_type, TEX_PROJECT), + _texture(ir_txb, v110_fs_only, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("shadow1DLod", + _texture(ir_txl, v110_lod, glsl_type::vec4_type, glsl_type::sampler1DShadow_type, glsl_type::vec3_type), + NULL); + + add_function("shadow2DLod", + _texture(ir_txl, v110_lod, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec3_type), + NULL); + + add_function("shadow1DArrayLod", + _texture(ir_txl, texture_array_lod, glsl_type::vec4_type, glsl_type::sampler1DArrayShadow_type, glsl_type::vec3_type), + NULL); + + add_function("shadow1DProjLod", + _texture(ir_txl, v110_lod, glsl_type::vec4_type, glsl_type::sampler1DShadow_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("shadow2DProjLod", + _texture(ir_txl, v110_lod, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("shadow2DRect", + _texture(ir_tex, texture_rectangle, glsl_type::vec4_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec3_type), + NULL); + + add_function("shadow2DRectProj", + _texture(ir_tex, texture_rectangle, glsl_type::vec4_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("texture1DGradARB", + _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::float_type), + NULL); + + add_function("texture1DProjGradARB", + _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec2_type, TEX_PROJECT), + _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type, glsl_type::sampler1D_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("texture2DGradARB", + _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type), + NULL); + + add_function("texture2DProjGradARB", + _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("texture3DGradARB", + _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec3_type), + NULL); + + add_function("texture3DProjGradARB", + _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type, glsl_type::sampler3D_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("textureCubeGradARB", + _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type), + NULL); + + add_function("shadow1DGradARB", + _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type, glsl_type::sampler1DShadow_type, glsl_type::vec3_type), + NULL); + + add_function("shadow1DProjGradARB", + _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type, glsl_type::sampler1DShadow_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("shadow2DGradARB", + _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec3_type), + NULL); + + add_function("shadow2DProjGradARB", + _texture(ir_txd, shader_texture_lod, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("texture2DRectGradARB", + _texture(ir_txd, shader_texture_lod_and_rect, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type), + NULL); + + add_function("texture2DRectProjGradARB", + _texture(ir_txd, shader_texture_lod_and_rect, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec3_type, TEX_PROJECT), + _texture(ir_txd, shader_texture_lod_and_rect, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("shadow2DRectGradARB", + _texture(ir_txd, shader_texture_lod_and_rect, glsl_type::vec4_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec3_type), + NULL); + + add_function("shadow2DRectProjGradARB", + _texture(ir_txd, shader_texture_lod_and_rect, glsl_type::vec4_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec4_type, TEX_PROJECT), + NULL); + + add_function("textureGather", + _texture(ir_tg4, texture_gather, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type), + _texture(ir_tg4, texture_gather, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type), + _texture(ir_tg4, texture_gather, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type), + + _texture(ir_tg4, texture_gather, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type), + _texture(ir_tg4, texture_gather, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type), + _texture(ir_tg4, texture_gather, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type), + + _texture(ir_tg4, texture_gather, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type), + _texture(ir_tg4, texture_gather, glsl_type::ivec4_type, glsl_type::isamplerCube_type, glsl_type::vec3_type), + _texture(ir_tg4, texture_gather, glsl_type::uvec4_type, glsl_type::usamplerCube_type, glsl_type::vec3_type), + + _texture(ir_tg4, texture_gather, glsl_type::vec4_type, glsl_type::samplerCubeArray_type, glsl_type::vec4_type), + _texture(ir_tg4, texture_gather, glsl_type::ivec4_type, glsl_type::isamplerCubeArray_type, glsl_type::vec4_type), + _texture(ir_tg4, texture_gather, glsl_type::uvec4_type, glsl_type::usamplerCubeArray_type, glsl_type::vec4_type), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_COMPONENT), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type, TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type, TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type, TEX_COMPONENT), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_COMPONENT), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type, TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isamplerCube_type, glsl_type::vec3_type, TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usamplerCube_type, glsl_type::vec3_type, TEX_COMPONENT), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::samplerCubeArray_type, glsl_type::vec4_type, TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isamplerCubeArray_type, glsl_type::vec4_type, TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usamplerCubeArray_type, glsl_type::vec4_type, TEX_COMPONENT), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec2_type), + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec3_type), + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::samplerCubeShadow_type, glsl_type::vec3_type), + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::samplerCubeArrayShadow_type, glsl_type::vec4_type), + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec2_type), + NULL); + + add_function("textureGatherOffset", + _texture(ir_tg4, texture_gather_only, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_tg4, texture_gather_only, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_tg4, texture_gather_only, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + + _texture(ir_tg4, texture_gather_only, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_tg4, texture_gather_only, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_tg4, texture_gather_only, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST | TEX_COMPONENT), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST | TEX_COMPONENT), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST | TEX_COMPONENT), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST), + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), + NULL); + + add_function("textureGatherOffsets", + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY | TEX_COMPONENT), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY | TEX_COMPONENT), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY | TEX_COMPONENT), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY), + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY), + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY), + NULL); + + F(dFdx) + F(dFdy) + F(fwidth) + F(noise1) + F(noise2) + F(noise3) + F(noise4) + + IU(bitfieldExtract) + IU(bitfieldInsert) + IU(bitfieldReverse) + IU(bitCount) + IU(findLSB) + IU(findMSB) + F(fma) + + add_function("ldexp", + _ldexp(glsl_type::float_type, glsl_type::int_type), + _ldexp(glsl_type::vec2_type, glsl_type::ivec2_type), + _ldexp(glsl_type::vec3_type, glsl_type::ivec3_type), + _ldexp(glsl_type::vec4_type, glsl_type::ivec4_type), + NULL); + + add_function("frexp", + _frexp(glsl_type::float_type, glsl_type::int_type), + _frexp(glsl_type::vec2_type, glsl_type::ivec2_type), + _frexp(glsl_type::vec3_type, glsl_type::ivec3_type), + _frexp(glsl_type::vec4_type, glsl_type::ivec4_type), + NULL); + add_function("uaddCarry", + _uaddCarry(glsl_type::uint_type), + _uaddCarry(glsl_type::uvec2_type), + _uaddCarry(glsl_type::uvec3_type), + _uaddCarry(glsl_type::uvec4_type), + NULL); + add_function("usubBorrow", + _usubBorrow(glsl_type::uint_type), + _usubBorrow(glsl_type::uvec2_type), + _usubBorrow(glsl_type::uvec3_type), + _usubBorrow(glsl_type::uvec4_type), + NULL); + add_function("imulExtended", + _mulExtended(glsl_type::int_type), + _mulExtended(glsl_type::ivec2_type), + _mulExtended(glsl_type::ivec3_type), + _mulExtended(glsl_type::ivec4_type), + NULL); + add_function("umulExtended", + _mulExtended(glsl_type::uint_type), + _mulExtended(glsl_type::uvec2_type), + _mulExtended(glsl_type::uvec3_type), + _mulExtended(glsl_type::uvec4_type), + NULL); + + add_function("atomicCounter", + _atomic_op("__intrinsic_atomic_read", + shader_atomic_counters), + NULL); + add_function("atomicCounterIncrement", + _atomic_op("__intrinsic_atomic_increment", + shader_atomic_counters), + NULL); + add_function("atomicCounterDecrement", + _atomic_op("__intrinsic_atomic_predecrement", + shader_atomic_counters), + NULL); + + add_function("min3", + _min3(glsl_type::float_type), + _min3(glsl_type::vec2_type), + _min3(glsl_type::vec3_type), + _min3(glsl_type::vec4_type), + + _min3(glsl_type::int_type), + _min3(glsl_type::ivec2_type), + _min3(glsl_type::ivec3_type), + _min3(glsl_type::ivec4_type), + + _min3(glsl_type::uint_type), + _min3(glsl_type::uvec2_type), + _min3(glsl_type::uvec3_type), + _min3(glsl_type::uvec4_type), + NULL); + + add_function("max3", + _max3(glsl_type::float_type), + _max3(glsl_type::vec2_type), + _max3(glsl_type::vec3_type), + _max3(glsl_type::vec4_type), + + _max3(glsl_type::int_type), + _max3(glsl_type::ivec2_type), + _max3(glsl_type::ivec3_type), + _max3(glsl_type::ivec4_type), + + _max3(glsl_type::uint_type), + _max3(glsl_type::uvec2_type), + _max3(glsl_type::uvec3_type), + _max3(glsl_type::uvec4_type), + NULL); + + add_function("mid3", + _mid3(glsl_type::float_type), + _mid3(glsl_type::vec2_type), + _mid3(glsl_type::vec3_type), + _mid3(glsl_type::vec4_type), + + _mid3(glsl_type::int_type), + _mid3(glsl_type::ivec2_type), + _mid3(glsl_type::ivec3_type), + _mid3(glsl_type::ivec4_type), + + _mid3(glsl_type::uint_type), + _mid3(glsl_type::uvec2_type), + _mid3(glsl_type::uvec3_type), + _mid3(glsl_type::uvec4_type), + NULL); + + add_image_functions(true); + + add_function("memoryBarrier", + _memory_barrier(shader_image_load_store), + NULL); + +#undef F +#undef FI +#undef FIU +#undef FIUB +#undef FIU2_MIXED +} + +void +builtin_builder::add_function(const char *name, ...) +{ + va_list ap; + + ir_function *f = new(mem_ctx) ir_function(name); + + va_start(ap, name); + while (true) { + ir_function_signature *sig = va_arg(ap, ir_function_signature *); + if (sig == NULL) + break; + + if (false) { + exec_list stuff; + stuff.push_tail(sig); + validate_ir_tree(&stuff); + } + + f->add_signature(sig); + } + va_end(ap); + + shader->symbols->add_function(f); +} + +void +builtin_builder::add_image_function(const char *name, + const char *intrinsic_name, + unsigned num_arguments, + unsigned flags) +{ + static const glsl_type *const types[] = { + glsl_type::image1D_type, + glsl_type::image2D_type, + glsl_type::image3D_type, + glsl_type::image2DRect_type, + glsl_type::imageCube_type, + glsl_type::imageBuffer_type, + glsl_type::image1DArray_type, + glsl_type::image2DArray_type, + glsl_type::imageCubeArray_type, + glsl_type::image2DMS_type, + glsl_type::image2DMSArray_type, + glsl_type::iimage1D_type, + glsl_type::iimage2D_type, + glsl_type::iimage3D_type, + glsl_type::iimage2DRect_type, + glsl_type::iimageCube_type, + glsl_type::iimageBuffer_type, + glsl_type::iimage1DArray_type, + glsl_type::iimage2DArray_type, + glsl_type::iimageCubeArray_type, + glsl_type::iimage2DMS_type, + glsl_type::iimage2DMSArray_type, + glsl_type::uimage1D_type, + glsl_type::uimage2D_type, + glsl_type::uimage3D_type, + glsl_type::uimage2DRect_type, + glsl_type::uimageCube_type, + glsl_type::uimageBuffer_type, + glsl_type::uimage1DArray_type, + glsl_type::uimage2DArray_type, + glsl_type::uimageCubeArray_type, + glsl_type::uimage2DMS_type, + glsl_type::uimage2DMSArray_type + }; + ir_function *f = new(mem_ctx) ir_function(name); + + for (unsigned i = 0; i < Elements(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, + num_arguments, flags)); + } + + shader->symbols->add_function(f); +} + +void +builtin_builder::add_image_functions(bool glsl) +{ + const unsigned flags = (glsl ? IMAGE_FUNCTION_EMIT_STUB : 0); + + add_image_function(glsl ? "imageLoad" : "__intrinsic_image_load", + "__intrinsic_image_load", 0, + (flags | IMAGE_FUNCTION_HAS_VECTOR_DATA_TYPE | + IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE | + IMAGE_FUNCTION_READ_ONLY)); + + add_image_function(glsl ? "imageStore" : "__intrinsic_image_store", + "__intrinsic_image_store", 1, + (flags | IMAGE_FUNCTION_RETURNS_VOID | + IMAGE_FUNCTION_HAS_VECTOR_DATA_TYPE | + IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE | + IMAGE_FUNCTION_WRITE_ONLY)); + + add_image_function(glsl ? "imageAtomicAdd" : "__intrinsic_image_atomic_add", + "__intrinsic_image_atomic_add", 1, flags); + + add_image_function(glsl ? "imageAtomicMin" : "__intrinsic_image_atomic_min", + "__intrinsic_image_atomic_min", 1, flags); + + add_image_function(glsl ? "imageAtomicMax" : "__intrinsic_image_atomic_max", + "__intrinsic_image_atomic_max", 1, flags); + + add_image_function(glsl ? "imageAtomicAnd" : "__intrinsic_image_atomic_and", + "__intrinsic_image_atomic_and", 1, flags); + + add_image_function(glsl ? "imageAtomicOr" : "__intrinsic_image_atomic_or", + "__intrinsic_image_atomic_or", 1, flags); + + add_image_function(glsl ? "imageAtomicXor" : "__intrinsic_image_atomic_xor", + "__intrinsic_image_atomic_xor", 1, flags); + + add_image_function((glsl ? "imageAtomicExchange" : + "__intrinsic_image_atomic_exchange"), + "__intrinsic_image_atomic_exchange", 1, flags); + + add_image_function((glsl ? "imageAtomicCompSwap" : + "__intrinsic_image_atomic_comp_swap"), + "__intrinsic_image_atomic_comp_swap", 2, flags); +} + +ir_variable * +builtin_builder::in_var(const glsl_type *type, const char *name) +{ + return new(mem_ctx) ir_variable(type, name, ir_var_function_in); +} + +ir_variable * +builtin_builder::out_var(const glsl_type *type, const char *name) +{ + return new(mem_ctx) ir_variable(type, name, ir_var_function_out); +} + +ir_constant * +builtin_builder::imm(float f, unsigned vector_elements) +{ + return new(mem_ctx) ir_constant(f, vector_elements); +} + +ir_constant * +builtin_builder::imm(int i, unsigned vector_elements) +{ + return new(mem_ctx) ir_constant(i, vector_elements); +} + +ir_constant * +builtin_builder::imm(unsigned u, unsigned vector_elements) +{ + return new(mem_ctx) ir_constant(u, vector_elements); +} + +ir_constant * +builtin_builder::imm(const glsl_type *type, const ir_constant_data &data) +{ + return new(mem_ctx) ir_constant(type, &data); +} + +ir_dereference_variable * +builtin_builder::var_ref(ir_variable *var) +{ + return new(mem_ctx) ir_dereference_variable(var); +} + +ir_dereference_array * +builtin_builder::array_ref(ir_variable *var, int idx) +{ + return new(mem_ctx) ir_dereference_array(var, imm(idx)); +} + +/** Return an element of a matrix */ +ir_swizzle * +builtin_builder::matrix_elt(ir_variable *var, int column, int row) +{ + return swizzle(array_ref(var, column), row, 1); +} + +/** + * Implementations of built-in functions: + * @{ + */ +ir_function_signature * +builtin_builder::new_sig(const glsl_type *return_type, + builtin_available_predicate avail, + int num_params, + ...) +{ + va_list ap; + + ir_function_signature *sig = + new(mem_ctx) ir_function_signature(return_type, avail); + + exec_list plist; + va_start(ap, num_params); + for (int i = 0; i < num_params; i++) { + plist.push_tail(va_arg(ap, ir_variable *)); + } + va_end(ap); + + sig->replace_parameters(&plist); + return sig; +} + +#define MAKE_SIG(return_type, avail, ...) \ + ir_function_signature *sig = \ + new_sig(return_type, avail, __VA_ARGS__); \ + ir_factory body(&sig->body, mem_ctx); \ + sig->is_defined = true; + +#define MAKE_INTRINSIC(return_type, avail, ...) \ + ir_function_signature *sig = \ + new_sig(return_type, avail, __VA_ARGS__); \ + sig->is_intrinsic = true; + +ir_function_signature * +builtin_builder::unop(builtin_available_predicate avail, + ir_expression_operation opcode, + const glsl_type *return_type, + const glsl_type *param_type) +{ + ir_variable *x = in_var(param_type, "x"); + MAKE_SIG(return_type, avail, 1, x); + body.emit(ret(expr(opcode, x))); + return sig; +} + +#define UNOP(NAME, OPCODE, AVAIL) \ +ir_function_signature * \ +builtin_builder::_##NAME(const glsl_type *type) \ +{ \ + return unop(&AVAIL, OPCODE, type, type); \ +} + +ir_function_signature * +builtin_builder::binop(ir_expression_operation opcode, + builtin_available_predicate avail, + const glsl_type *return_type, + const glsl_type *param0_type, + const glsl_type *param1_type) +{ + ir_variable *x = in_var(param0_type, "x"); + ir_variable *y = in_var(param1_type, "y"); + MAKE_SIG(return_type, avail, 2, x, y); + body.emit(ret(expr(opcode, x, y))); + return sig; +} + +#define BINOP(NAME, OPCODE, AVAIL) \ +ir_function_signature * \ +builtin_builder::_##NAME(const glsl_type *return_type, \ + const glsl_type *param0_type, \ + const glsl_type *param1_type) \ +{ \ + return binop(&AVAIL, OPCODE, return_type, param0_type, param1_type); \ +} + +/** + * Angle and Trigonometry Functions @{ + */ + +ir_function_signature * +builtin_builder::_radians(const glsl_type *type) +{ + ir_variable *degrees = in_var(type, "degrees"); + MAKE_SIG(type, always_available, 1, degrees); + body.emit(ret(mul(degrees, imm(0.0174532925f)))); + return sig; +} + +ir_function_signature * +builtin_builder::_degrees(const glsl_type *type) +{ + ir_variable *radians = in_var(type, "radians"); + MAKE_SIG(type, always_available, 1, radians); + body.emit(ret(mul(radians, imm(57.29578f)))); + return sig; +} + +UNOP(sin, ir_unop_sin, always_available) +UNOP(cos, ir_unop_cos, always_available) + +ir_function_signature * +builtin_builder::_tan(const glsl_type *type) +{ + ir_variable *theta = in_var(type, "theta"); + MAKE_SIG(type, always_available, 1, theta); + body.emit(ret(div(sin(theta), cos(theta)))); + return sig; +} + +ir_expression * +builtin_builder::asin_expr(ir_variable *x) +{ + return mul(sign(x), + sub(imm(M_PI_2f), + mul(sqrt(sub(imm(1.0f), abs(x))), + add(imm(M_PI_2f), + mul(abs(x), + add(imm(M_PI_4f - 1.0f), + mul(abs(x), + add(imm(0.086566724f), + mul(abs(x), imm(-0.03102955f)))))))))); +} + +ir_call * +builtin_builder::call(ir_function *f, ir_variable *ret, exec_list params) +{ + exec_list actual_params; + + foreach_list(node, ¶ms) { + ir_variable *var = (ir_variable *) node; + actual_params.push_tail(var_ref(var)); + } + + ir_function_signature *sig = + f->exact_matching_signature(NULL, &actual_params); + if (!sig) + return NULL; + + ir_dereference_variable *deref = + (sig->return_type->is_void() ? NULL : var_ref(ret)); + + return new(mem_ctx) ir_call(sig, deref, &actual_params); +} + +ir_function_signature * +builtin_builder::_asin(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + MAKE_SIG(type, always_available, 1, x); + + body.emit(ret(asin_expr(x))); + + return sig; +} + +ir_function_signature * +builtin_builder::_acos(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + MAKE_SIG(type, always_available, 1, x); + + body.emit(ret(sub(imm(M_PI_2f), asin_expr(x)))); + + return sig; +} + +ir_function_signature * +builtin_builder::_atan2(const glsl_type *type) +{ + ir_variable *vec_y = in_var(type, "vec_y"); + ir_variable *vec_x = in_var(type, "vec_x"); + MAKE_SIG(type, always_available, 2, vec_y, vec_x); + + ir_variable *vec_result = body.make_temp(type, "vec_result"); + ir_variable *r = body.make_temp(glsl_type::float_type, "r"); + for (int i = 0; i < type->vector_elements; i++) { + ir_variable *y = body.make_temp(glsl_type::float_type, "y"); + ir_variable *x = body.make_temp(glsl_type::float_type, "x"); + body.emit(assign(y, swizzle(vec_y, i, 1))); + body.emit(assign(x, swizzle(vec_x, i, 1))); + + /* If |x| >= 1.0e-8 * |y|: */ + ir_if *outer_if = + new(mem_ctx) ir_if(greater(abs(x), mul(imm(1.0e-8f), abs(y)))); + + ir_factory outer_then(&outer_if->then_instructions, mem_ctx); + + /* Then...call atan(y/x) */ + ir_variable *y_over_x = outer_then.make_temp(glsl_type::float_type, "y_over_x"); + outer_then.emit(assign(y_over_x, div(y, x))); + outer_then.emit(assign(r, mul(y_over_x, rsq(add(mul(y_over_x, y_over_x), + imm(1.0f)))))); + outer_then.emit(assign(r, asin_expr(r))); + + /* ...and fix it up: */ + ir_if *inner_if = new(mem_ctx) ir_if(less(x, imm(0.0f))); + inner_if->then_instructions.push_tail( + if_tree(gequal(y, imm(0.0f)), + assign(r, add(r, imm(M_PIf))), + assign(r, sub(r, imm(M_PIf))))); + outer_then.emit(inner_if); + + /* Else... */ + outer_if->else_instructions.push_tail( + assign(r, mul(sign(y), imm(M_PI_2f)))); + + body.emit(outer_if); + + body.emit(assign(vec_result, r, 1 << i)); + } + body.emit(ret(vec_result)); + + return sig; +} + +ir_function_signature * +builtin_builder::_atan(const glsl_type *type) +{ + ir_variable *y_over_x = in_var(type, "y_over_x"); + MAKE_SIG(type, always_available, 1, y_over_x); + + ir_variable *t = body.make_temp(type, "t"); + body.emit(assign(t, mul(y_over_x, rsq(add(mul(y_over_x, y_over_x), + imm(1.0f)))))); + + body.emit(ret(asin_expr(t))); + + return sig; +} + +ir_function_signature * +builtin_builder::_sinh(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + MAKE_SIG(type, v130, 1, x); + + /* 0.5 * (e^x - e^(-x)) */ + body.emit(ret(mul(imm(0.5f), sub(exp(x), exp(neg(x)))))); + + return sig; +} + +ir_function_signature * +builtin_builder::_cosh(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + MAKE_SIG(type, v130, 1, x); + + /* 0.5 * (e^x + e^(-x)) */ + body.emit(ret(mul(imm(0.5f), add(exp(x), exp(neg(x)))))); + + return sig; +} + +ir_function_signature * +builtin_builder::_tanh(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + MAKE_SIG(type, v130, 1, x); + + /* (e^x - e^(-x)) / (e^x + e^(-x)) */ + body.emit(ret(div(sub(exp(x), exp(neg(x))), + add(exp(x), exp(neg(x)))))); + + return sig; +} + +ir_function_signature * +builtin_builder::_asinh(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + MAKE_SIG(type, v130, 1, x); + + body.emit(ret(mul(sign(x), log(add(abs(x), sqrt(add(mul(x, x), + imm(1.0f)))))))); + return sig; +} + +ir_function_signature * +builtin_builder::_acosh(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + MAKE_SIG(type, v130, 1, x); + + body.emit(ret(log(add(x, sqrt(sub(mul(x, x), imm(1.0f))))))); + return sig; +} + +ir_function_signature * +builtin_builder::_atanh(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + MAKE_SIG(type, v130, 1, x); + + body.emit(ret(mul(imm(0.5f), log(div(add(imm(1.0f), x), + sub(imm(1.0f), x)))))); + return sig; +} +/** @} */ + +/** + * Exponential Functions @{ + */ + +ir_function_signature * +builtin_builder::_pow(const glsl_type *type) +{ + return binop(ir_binop_pow, always_available, type, type, type); +} + +UNOP(exp, ir_unop_exp, always_available) +UNOP(log, ir_unop_log, always_available) +UNOP(exp2, ir_unop_exp2, always_available) +UNOP(log2, ir_unop_log2, always_available) +UNOP(sqrt, ir_unop_sqrt, always_available) +UNOP(inversesqrt, ir_unop_rsq, always_available) + +/** @} */ + +UNOP(abs, ir_unop_abs, always_available) +UNOP(sign, ir_unop_sign, always_available) +UNOP(floor, ir_unop_floor, always_available) +UNOP(trunc, ir_unop_trunc, v130) +UNOP(round, ir_unop_round_even, always_available) +UNOP(roundEven, ir_unop_round_even, always_available) +UNOP(ceil, ir_unop_ceil, always_available) +UNOP(fract, ir_unop_fract, always_available) + +ir_function_signature * +builtin_builder::_mod(const glsl_type *x_type, const glsl_type *y_type) +{ + return binop(ir_binop_mod, always_available, x_type, x_type, y_type); +} + +ir_function_signature * +builtin_builder::_modf(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + ir_variable *i = out_var(type, "i"); + MAKE_SIG(type, v130, 2, x, i); + + ir_variable *t = body.make_temp(type, "t"); + body.emit(assign(t, expr(ir_unop_trunc, x))); + body.emit(assign(i, t)); + body.emit(ret(sub(x, t))); + + return sig; +} + +ir_function_signature * +builtin_builder::_min(builtin_available_predicate avail, + const glsl_type *x_type, const glsl_type *y_type) +{ + return binop(ir_binop_min, avail, x_type, x_type, y_type); +} + +ir_function_signature * +builtin_builder::_max(builtin_available_predicate avail, + const glsl_type *x_type, const glsl_type *y_type) +{ + return binop(ir_binop_max, avail, x_type, x_type, y_type); +} + +ir_function_signature * +builtin_builder::_clamp(builtin_available_predicate avail, + const glsl_type *val_type, const glsl_type *bound_type) +{ + ir_variable *x = in_var(val_type, "x"); + ir_variable *minVal = in_var(bound_type, "minVal"); + ir_variable *maxVal = in_var(bound_type, "maxVal"); + MAKE_SIG(val_type, avail, 3, x, minVal, maxVal); + + body.emit(ret(clamp(x, minVal, maxVal))); + + return sig; +} + +ir_function_signature * +builtin_builder::_mix_lrp(const glsl_type *val_type, const glsl_type *blend_type) +{ + ir_variable *x = in_var(val_type, "x"); + ir_variable *y = in_var(val_type, "y"); + ir_variable *a = in_var(blend_type, "a"); + MAKE_SIG(val_type, always_available, 3, x, y, a); + + body.emit(ret(lrp(x, y, a))); + + return sig; +} + +ir_function_signature * +builtin_builder::_mix_sel(builtin_available_predicate avail, + const glsl_type *val_type, + const glsl_type *blend_type) +{ + ir_variable *x = in_var(val_type, "x"); + ir_variable *y = in_var(val_type, "y"); + ir_variable *a = in_var(blend_type, "a"); + MAKE_SIG(val_type, avail, 3, x, y, a); + + /* csel matches the ternary operator in that a selector of true choses the + * first argument. This differs from mix(x, y, false) which choses the + * second argument (to remain consistent with the interpolating version of + * mix() which takes a blend factor from 0.0 to 1.0 where 0.0 is only x. + * + * To handle the behavior mismatch, reverse the x and y arguments. + */ + body.emit(ret(csel(a, y, x))); + + return sig; +} + +ir_function_signature * +builtin_builder::_step(const glsl_type *edge_type, const glsl_type *x_type) +{ + ir_variable *edge = in_var(edge_type, "edge"); + ir_variable *x = in_var(x_type, "x"); + MAKE_SIG(x_type, always_available, 2, edge, x); + + ir_variable *t = body.make_temp(x_type, "t"); + if (x_type->vector_elements == 1) { + /* Both are floats */ + body.emit(assign(t, b2f(gequal(x, edge)))); + } else if (edge_type->vector_elements == 1) { + /* x is a vector but edge is a float */ + for (int i = 0; i < x_type->vector_elements; i++) { + body.emit(assign(t, b2f(gequal(swizzle(x, i, 1), edge)), 1 << i)); + } + } else { + /* Both are vectors */ + for (int i = 0; i < x_type->vector_elements; i++) { + body.emit(assign(t, b2f(gequal(swizzle(x, i, 1), swizzle(edge, i, 1))), + 1 << i)); + } + } + body.emit(ret(t)); + + return sig; +} + +ir_function_signature * +builtin_builder::_smoothstep(const glsl_type *edge_type, const glsl_type *x_type) +{ + ir_variable *edge0 = in_var(edge_type, "edge0"); + ir_variable *edge1 = in_var(edge_type, "edge1"); + ir_variable *x = in_var(x_type, "x"); + MAKE_SIG(x_type, always_available, 3, edge0, edge1, x); + + /* From the GLSL 1.10 specification: + * + * genType t; + * t = clamp((x - edge0) / (edge1 - edge0), 0, 1); + * return t * t * (3 - 2 * t); + */ + + ir_variable *t = body.make_temp(x_type, "t"); + body.emit(assign(t, clamp(div(sub(x, edge0), sub(edge1, edge0)), + imm(0.0f), imm(1.0f)))); + + body.emit(ret(mul(t, mul(t, sub(imm(3.0f), mul(imm(2.0f), t)))))); + + return sig; +} + +ir_function_signature * +builtin_builder::_isnan(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + MAKE_SIG(glsl_type::bvec(type->vector_elements), v130, 1, x); + + body.emit(ret(nequal(x, x))); + + return sig; +} + +ir_function_signature * +builtin_builder::_isinf(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + MAKE_SIG(glsl_type::bvec(type->vector_elements), v130, 1, x); + + ir_constant_data infinities; + for (int i = 0; i < type->vector_elements; i++) { + infinities.f[i] = std::numeric_limits<float>::infinity(); + } + + body.emit(ret(equal(abs(x), imm(type, infinities)))); + + return sig; +} + +ir_function_signature * +builtin_builder::_floatBitsToInt(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + MAKE_SIG(glsl_type::ivec(type->vector_elements), shader_bit_encoding, 1, x); + body.emit(ret(bitcast_f2i(x))); + return sig; +} + +ir_function_signature * +builtin_builder::_floatBitsToUint(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + MAKE_SIG(glsl_type::uvec(type->vector_elements), shader_bit_encoding, 1, x); + body.emit(ret(bitcast_f2u(x))); + return sig; +} + +ir_function_signature * +builtin_builder::_intBitsToFloat(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + MAKE_SIG(glsl_type::vec(type->vector_elements), shader_bit_encoding, 1, x); + body.emit(ret(bitcast_i2f(x))); + return sig; +} + +ir_function_signature * +builtin_builder::_uintBitsToFloat(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + MAKE_SIG(glsl_type::vec(type->vector_elements), shader_bit_encoding, 1, x); + body.emit(ret(bitcast_u2f(x))); + return sig; +} + +ir_function_signature * +builtin_builder::_packUnorm2x16(builtin_available_predicate avail) +{ + ir_variable *v = in_var(glsl_type::vec2_type, "v"); + MAKE_SIG(glsl_type::uint_type, avail, 1, v); + body.emit(ret(expr(ir_unop_pack_unorm_2x16, v))); + return sig; +} + +ir_function_signature * +builtin_builder::_packSnorm2x16(builtin_available_predicate avail) +{ + ir_variable *v = in_var(glsl_type::vec2_type, "v"); + MAKE_SIG(glsl_type::uint_type, avail, 1, v); + body.emit(ret(expr(ir_unop_pack_snorm_2x16, v))); + return sig; +} + +ir_function_signature * +builtin_builder::_packUnorm4x8(builtin_available_predicate avail) +{ + ir_variable *v = in_var(glsl_type::vec4_type, "v"); + MAKE_SIG(glsl_type::uint_type, avail, 1, v); + body.emit(ret(expr(ir_unop_pack_unorm_4x8, v))); + return sig; +} + +ir_function_signature * +builtin_builder::_packSnorm4x8(builtin_available_predicate avail) +{ + ir_variable *v = in_var(glsl_type::vec4_type, "v"); + MAKE_SIG(glsl_type::uint_type, avail, 1, v); + body.emit(ret(expr(ir_unop_pack_snorm_4x8, v))); + return sig; +} + +ir_function_signature * +builtin_builder::_unpackUnorm2x16(builtin_available_predicate avail) +{ + ir_variable *p = in_var(glsl_type::uint_type, "p"); + MAKE_SIG(glsl_type::vec2_type, avail, 1, p); + body.emit(ret(expr(ir_unop_unpack_unorm_2x16, p))); + return sig; +} + +ir_function_signature * +builtin_builder::_unpackSnorm2x16(builtin_available_predicate avail) +{ + ir_variable *p = in_var(glsl_type::uint_type, "p"); + MAKE_SIG(glsl_type::vec2_type, avail, 1, p); + body.emit(ret(expr(ir_unop_unpack_snorm_2x16, p))); + return sig; +} + + +ir_function_signature * +builtin_builder::_unpackUnorm4x8(builtin_available_predicate avail) +{ + ir_variable *p = in_var(glsl_type::uint_type, "p"); + MAKE_SIG(glsl_type::vec4_type, avail, 1, p); + body.emit(ret(expr(ir_unop_unpack_unorm_4x8, p))); + return sig; +} + +ir_function_signature * +builtin_builder::_unpackSnorm4x8(builtin_available_predicate avail) +{ + ir_variable *p = in_var(glsl_type::uint_type, "p"); + MAKE_SIG(glsl_type::vec4_type, avail, 1, p); + body.emit(ret(expr(ir_unop_unpack_snorm_4x8, p))); + return sig; +} + +ir_function_signature * +builtin_builder::_packHalf2x16(builtin_available_predicate avail) +{ + ir_variable *v = in_var(glsl_type::vec2_type, "v"); + MAKE_SIG(glsl_type::uint_type, avail, 1, v); + body.emit(ret(expr(ir_unop_pack_half_2x16, v))); + return sig; +} + +ir_function_signature * +builtin_builder::_unpackHalf2x16(builtin_available_predicate avail) +{ + ir_variable *p = in_var(glsl_type::uint_type, "p"); + MAKE_SIG(glsl_type::vec2_type, avail, 1, p); + body.emit(ret(expr(ir_unop_unpack_half_2x16, p))); + return sig; +} + +ir_function_signature * +builtin_builder::_length(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + MAKE_SIG(glsl_type::float_type, always_available, 1, x); + + body.emit(ret(sqrt(dot(x, x)))); + + return sig; +} + +ir_function_signature * +builtin_builder::_distance(const glsl_type *type) +{ + ir_variable *p0 = in_var(type, "p0"); + ir_variable *p1 = in_var(type, "p1"); + MAKE_SIG(glsl_type::float_type, always_available, 2, p0, p1); + + if (type->vector_elements == 1) { + body.emit(ret(abs(sub(p0, p1)))); + } else { + ir_variable *p = body.make_temp(type, "p"); + body.emit(assign(p, sub(p0, p1))); + body.emit(ret(sqrt(dot(p, p)))); + } + + return sig; +} + +ir_function_signature * +builtin_builder::_dot(const glsl_type *type) +{ + if (type->vector_elements == 1) + return binop(ir_binop_mul, always_available, type, type, type); + + return binop(ir_binop_dot, always_available, + glsl_type::float_type, type, type); +} + +ir_function_signature * +builtin_builder::_cross(const glsl_type *type) +{ + ir_variable *a = in_var(type, "a"); + ir_variable *b = in_var(type, "b"); + MAKE_SIG(type, always_available, 2, a, b); + + int yzx = MAKE_SWIZZLE4(SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X, 0); + int zxy = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_X, SWIZZLE_Y, 0); + + body.emit(ret(sub(mul(swizzle(a, yzx, 3), swizzle(b, zxy, 3)), + mul(swizzle(a, zxy, 3), swizzle(b, yzx, 3))))); + + return sig; +} + +ir_function_signature * +builtin_builder::_normalize(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + MAKE_SIG(type, always_available, 1, x); + + if (type->vector_elements == 1) { + body.emit(ret(sign(x))); + } else { + body.emit(ret(mul(x, rsq(dot(x, x))))); + } + + return sig; +} + +ir_function_signature * +builtin_builder::_ftransform() +{ + MAKE_SIG(glsl_type::vec4_type, compatibility_vs_only, 0); + + body.emit(ret(new(mem_ctx) ir_expression(ir_binop_mul, + glsl_type::vec4_type, + var_ref(gl_ModelViewProjectionMatrix), + var_ref(gl_Vertex)))); + + /* FINISHME: Once the ir_expression() constructor handles type inference + * for matrix operations, we can simplify this to: + * + * body.emit(ret(mul(gl_ModelViewProjectionMatrix, gl_Vertex))); + */ + return sig; +} + +ir_function_signature * +builtin_builder::_faceforward(const glsl_type *type) +{ + ir_variable *N = in_var(type, "N"); + ir_variable *I = in_var(type, "I"); + ir_variable *Nref = in_var(type, "Nref"); + MAKE_SIG(type, always_available, 3, N, I, Nref); + + body.emit(if_tree(less(dot(Nref, I), imm(0.0f)), + ret(N), ret(neg(N)))); + + return sig; +} + +ir_function_signature * +builtin_builder::_reflect(const glsl_type *type) +{ + ir_variable *I = in_var(type, "I"); + ir_variable *N = in_var(type, "N"); + MAKE_SIG(type, always_available, 2, I, N); + + /* I - 2 * dot(N, I) * N */ + body.emit(ret(sub(I, mul(imm(2.0f), mul(dot(N, I), N))))); + + return sig; +} + +ir_function_signature * +builtin_builder::_refract(const glsl_type *type) +{ + ir_variable *I = in_var(type, "I"); + ir_variable *N = in_var(type, "N"); + ir_variable *eta = in_var(glsl_type::float_type, "eta"); + MAKE_SIG(type, always_available, 3, I, N, eta); + + ir_variable *n_dot_i = body.make_temp(glsl_type::float_type, "n_dot_i"); + body.emit(assign(n_dot_i, dot(N, I))); + + /* From the GLSL 1.10 specification: + * k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)) + * if (k < 0.0) + * return genType(0.0) + * else + * return eta * I - (eta * dot(N, I) + sqrt(k)) * N + */ + ir_variable *k = body.make_temp(glsl_type::float_type, "k"); + body.emit(assign(k, sub(imm(1.0f), + mul(eta, mul(eta, sub(imm(1.0f), + mul(n_dot_i, n_dot_i))))))); + body.emit(if_tree(less(k, imm(0.0f)), + ret(ir_constant::zero(mem_ctx, type)), + ret(sub(mul(eta, I), + mul(add(mul(eta, n_dot_i), sqrt(k)), N))))); + + return sig; +} + +ir_function_signature * +builtin_builder::_matrixCompMult(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + ir_variable *y = in_var(type, "y"); + MAKE_SIG(type, always_available, 2, x, y); + + ir_variable *z = body.make_temp(type, "z"); + for (int i = 0; i < type->matrix_columns; i++) { + body.emit(assign(array_ref(z, i), mul(array_ref(x, i), array_ref(y, i)))); + } + body.emit(ret(z)); + + return sig; +} + +ir_function_signature * +builtin_builder::_outerProduct(const glsl_type *type) +{ + ir_variable *c = in_var(glsl_type::vec(type->vector_elements), "c"); + ir_variable *r = in_var(glsl_type::vec(type->matrix_columns), "r"); + MAKE_SIG(type, v120, 2, c, r); + + ir_variable *m = body.make_temp(type, "m"); + for (int i = 0; i < type->matrix_columns; i++) { + body.emit(assign(array_ref(m, i), mul(c, swizzle(r, i, 1)))); + } + body.emit(ret(m)); + + return sig; +} + +ir_function_signature * +builtin_builder::_transpose(const glsl_type *orig_type) +{ + const glsl_type *transpose_type = + glsl_type::get_instance(GLSL_TYPE_FLOAT, + orig_type->matrix_columns, + orig_type->vector_elements); + + ir_variable *m = in_var(orig_type, "m"); + MAKE_SIG(transpose_type, v120, 1, m); + + ir_variable *t = body.make_temp(transpose_type, "t"); + for (int i = 0; i < orig_type->matrix_columns; i++) { + for (int j = 0; j < orig_type->vector_elements; j++) { + body.emit(assign(array_ref(t, j), + matrix_elt(m, i, j), + 1 << i)); + } + } + body.emit(ret(t)); + + return sig; +} + +ir_function_signature * +builtin_builder::_determinant_mat2() +{ + ir_variable *m = in_var(glsl_type::mat2_type, "m"); + MAKE_SIG(glsl_type::float_type, v120, 1, m); + + body.emit(ret(sub(mul(matrix_elt(m, 0, 0), matrix_elt(m, 1, 1)), + mul(matrix_elt(m, 1, 0), matrix_elt(m, 0, 1))))); + + return sig; +} + +ir_function_signature * +builtin_builder::_determinant_mat3() +{ + ir_variable *m = in_var(glsl_type::mat3_type, "m"); + MAKE_SIG(glsl_type::float_type, v120, 1, m); + + ir_expression *f1 = + sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 2, 2)), + mul(matrix_elt(m, 1, 2), matrix_elt(m, 2, 1))); + + ir_expression *f2 = + sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 2)), + mul(matrix_elt(m, 1, 2), matrix_elt(m, 2, 0))); + + ir_expression *f3 = + sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 1)), + mul(matrix_elt(m, 1, 1), matrix_elt(m, 2, 0))); + + body.emit(ret(add(sub(mul(matrix_elt(m, 0, 0), f1), + mul(matrix_elt(m, 0, 1), f2)), + mul(matrix_elt(m, 0, 2), f3)))); + + return sig; +} + +ir_function_signature * +builtin_builder::_determinant_mat4() +{ + ir_variable *m = in_var(glsl_type::mat4_type, "m"); + MAKE_SIG(glsl_type::float_type, v120, 1, m); + + ir_variable *SubFactor00 = body.make_temp(glsl_type::float_type, "SubFactor00"); + ir_variable *SubFactor01 = body.make_temp(glsl_type::float_type, "SubFactor01"); + ir_variable *SubFactor02 = body.make_temp(glsl_type::float_type, "SubFactor02"); + ir_variable *SubFactor03 = body.make_temp(glsl_type::float_type, "SubFactor03"); + ir_variable *SubFactor04 = body.make_temp(glsl_type::float_type, "SubFactor04"); + ir_variable *SubFactor05 = body.make_temp(glsl_type::float_type, "SubFactor05"); + ir_variable *SubFactor06 = body.make_temp(glsl_type::float_type, "SubFactor06"); + ir_variable *SubFactor07 = body.make_temp(glsl_type::float_type, "SubFactor07"); + ir_variable *SubFactor08 = body.make_temp(glsl_type::float_type, "SubFactor08"); + ir_variable *SubFactor09 = body.make_temp(glsl_type::float_type, "SubFactor09"); + ir_variable *SubFactor10 = body.make_temp(glsl_type::float_type, "SubFactor10"); + ir_variable *SubFactor11 = body.make_temp(glsl_type::float_type, "SubFactor11"); + ir_variable *SubFactor12 = body.make_temp(glsl_type::float_type, "SubFactor12"); + ir_variable *SubFactor13 = body.make_temp(glsl_type::float_type, "SubFactor13"); + ir_variable *SubFactor14 = body.make_temp(glsl_type::float_type, "SubFactor14"); + ir_variable *SubFactor15 = body.make_temp(glsl_type::float_type, "SubFactor15"); + ir_variable *SubFactor16 = body.make_temp(glsl_type::float_type, "SubFactor16"); + ir_variable *SubFactor17 = body.make_temp(glsl_type::float_type, "SubFactor17"); + ir_variable *SubFactor18 = body.make_temp(glsl_type::float_type, "SubFactor18"); + + body.emit(assign(SubFactor00, sub(mul(matrix_elt(m, 2, 2), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 2), matrix_elt(m, 2, 3))))); + body.emit(assign(SubFactor01, sub(mul(matrix_elt(m, 2, 1), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 2, 3))))); + body.emit(assign(SubFactor02, sub(mul(matrix_elt(m, 2, 1), matrix_elt(m, 3, 2)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 2, 2))))); + body.emit(assign(SubFactor03, sub(mul(matrix_elt(m, 2, 0), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 2, 3))))); + body.emit(assign(SubFactor04, sub(mul(matrix_elt(m, 2, 0), matrix_elt(m, 3, 2)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 2, 2))))); + body.emit(assign(SubFactor05, sub(mul(matrix_elt(m, 2, 0), matrix_elt(m, 3, 1)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 2, 1))))); + body.emit(assign(SubFactor06, sub(mul(matrix_elt(m, 1, 2), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 2), matrix_elt(m, 1, 3))))); + body.emit(assign(SubFactor07, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 1, 3))))); + body.emit(assign(SubFactor08, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 3, 2)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 1, 2))))); + body.emit(assign(SubFactor09, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 1, 3))))); + body.emit(assign(SubFactor10, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 3, 2)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 1, 2))))); + body.emit(assign(SubFactor11, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 1, 3))))); + body.emit(assign(SubFactor12, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 3, 1)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 1, 1))))); + body.emit(assign(SubFactor13, sub(mul(matrix_elt(m, 1, 2), matrix_elt(m, 2, 3)), mul(matrix_elt(m, 2, 2), matrix_elt(m, 1, 3))))); + body.emit(assign(SubFactor14, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 2, 3)), mul(matrix_elt(m, 2, 1), matrix_elt(m, 1, 3))))); + body.emit(assign(SubFactor15, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 2, 2)), mul(matrix_elt(m, 2, 1), matrix_elt(m, 1, 2))))); + body.emit(assign(SubFactor16, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 3)), mul(matrix_elt(m, 2, 0), matrix_elt(m, 1, 3))))); + body.emit(assign(SubFactor17, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 2)), mul(matrix_elt(m, 2, 0), matrix_elt(m, 1, 2))))); + body.emit(assign(SubFactor18, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 1)), mul(matrix_elt(m, 2, 0), matrix_elt(m, 1, 1))))); + + ir_variable *adj_0 = body.make_temp(glsl_type::vec4_type, "adj_0"); + + body.emit(assign(adj_0, + add(sub(mul(matrix_elt(m, 1, 1), SubFactor00), + mul(matrix_elt(m, 1, 2), SubFactor01)), + mul(matrix_elt(m, 1, 3), SubFactor02)), + WRITEMASK_X)); + body.emit(assign(adj_0, neg( + add(sub(mul(matrix_elt(m, 1, 0), SubFactor00), + mul(matrix_elt(m, 1, 2), SubFactor03)), + mul(matrix_elt(m, 1, 3), SubFactor04))), + WRITEMASK_Y)); + body.emit(assign(adj_0, + add(sub(mul(matrix_elt(m, 1, 0), SubFactor01), + mul(matrix_elt(m, 1, 1), SubFactor03)), + mul(matrix_elt(m, 1, 3), SubFactor05)), + WRITEMASK_Z)); + body.emit(assign(adj_0, neg( + add(sub(mul(matrix_elt(m, 1, 0), SubFactor02), + mul(matrix_elt(m, 1, 1), SubFactor04)), + mul(matrix_elt(m, 1, 2), SubFactor05))), + WRITEMASK_W)); + + body.emit(ret(dot(array_ref(m, 0), adj_0))); + + return sig; +} + +ir_function_signature * +builtin_builder::_inverse_mat2() +{ + ir_variable *m = in_var(glsl_type::mat2_type, "m"); + MAKE_SIG(glsl_type::mat2_type, v120, 1, m); + + ir_variable *adj = body.make_temp(glsl_type::mat2_type, "adj"); + body.emit(assign(array_ref(adj, 0), matrix_elt(m, 1, 1), 1 << 0)); + body.emit(assign(array_ref(adj, 0), neg(matrix_elt(m, 0, 1)), 1 << 1)); + body.emit(assign(array_ref(adj, 1), neg(matrix_elt(m, 1, 0)), 1 << 0)); + body.emit(assign(array_ref(adj, 1), matrix_elt(m, 0, 0), 1 << 1)); + + ir_expression *det = + sub(mul(matrix_elt(m, 0, 0), matrix_elt(m, 1, 1)), + mul(matrix_elt(m, 1, 0), matrix_elt(m, 0, 1))); + + body.emit(ret(div(adj, det))); + return sig; +} + +ir_function_signature * +builtin_builder::_inverse_mat3() +{ + ir_variable *m = in_var(glsl_type::mat3_type, "m"); + MAKE_SIG(glsl_type::mat3_type, v120, 1, m); + + ir_variable *f11_22_21_12 = body.make_temp(glsl_type::float_type, "f11_22_21_12"); + ir_variable *f10_22_20_12 = body.make_temp(glsl_type::float_type, "f10_22_20_12"); + ir_variable *f10_21_20_11 = body.make_temp(glsl_type::float_type, "f10_21_20_11"); + + body.emit(assign(f11_22_21_12, + sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 2, 2)), + mul(matrix_elt(m, 2, 1), matrix_elt(m, 1, 2))))); + body.emit(assign(f10_22_20_12, + sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 2)), + mul(matrix_elt(m, 2, 0), matrix_elt(m, 1, 2))))); + body.emit(assign(f10_21_20_11, + sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 1)), + mul(matrix_elt(m, 2, 0), matrix_elt(m, 1, 1))))); + + ir_variable *adj = body.make_temp(glsl_type::mat3_type, "adj"); + body.emit(assign(array_ref(adj, 0), f11_22_21_12, WRITEMASK_X)); + body.emit(assign(array_ref(adj, 1), neg(f10_22_20_12), WRITEMASK_X)); + body.emit(assign(array_ref(adj, 2), f10_21_20_11, WRITEMASK_X)); + + body.emit(assign(array_ref(adj, 0), neg( + sub(mul(matrix_elt(m, 0, 1), matrix_elt(m, 2, 2)), + mul(matrix_elt(m, 2, 1), matrix_elt(m, 0, 2)))), + WRITEMASK_Y)); + body.emit(assign(array_ref(adj, 1), + sub(mul(matrix_elt(m, 0, 0), matrix_elt(m, 2, 2)), + mul(matrix_elt(m, 2, 0), matrix_elt(m, 0, 2))), + WRITEMASK_Y)); + body.emit(assign(array_ref(adj, 2), neg( + sub(mul(matrix_elt(m, 0, 0), matrix_elt(m, 2, 1)), + mul(matrix_elt(m, 2, 0), matrix_elt(m, 0, 1)))), + WRITEMASK_Y)); + + body.emit(assign(array_ref(adj, 0), + sub(mul(matrix_elt(m, 0, 1), matrix_elt(m, 1, 2)), + mul(matrix_elt(m, 1, 1), matrix_elt(m, 0, 2))), + WRITEMASK_Z)); + body.emit(assign(array_ref(adj, 1), neg( + sub(mul(matrix_elt(m, 0, 0), matrix_elt(m, 1, 2)), + mul(matrix_elt(m, 1, 0), matrix_elt(m, 0, 2)))), + WRITEMASK_Z)); + body.emit(assign(array_ref(adj, 2), + sub(mul(matrix_elt(m, 0, 0), matrix_elt(m, 1, 1)), + mul(matrix_elt(m, 1, 0), matrix_elt(m, 0, 1))), + WRITEMASK_Z)); + + ir_expression *det = + add(sub(mul(matrix_elt(m, 0, 0), f11_22_21_12), + mul(matrix_elt(m, 0, 1), f10_22_20_12)), + mul(matrix_elt(m, 0, 2), f10_21_20_11)); + + body.emit(ret(div(adj, det))); + + return sig; +} + +ir_function_signature * +builtin_builder::_inverse_mat4() +{ + ir_variable *m = in_var(glsl_type::mat4_type, "m"); + MAKE_SIG(glsl_type::mat4_type, v120, 1, m); + + ir_variable *SubFactor00 = body.make_temp(glsl_type::float_type, "SubFactor00"); + ir_variable *SubFactor01 = body.make_temp(glsl_type::float_type, "SubFactor01"); + ir_variable *SubFactor02 = body.make_temp(glsl_type::float_type, "SubFactor02"); + ir_variable *SubFactor03 = body.make_temp(glsl_type::float_type, "SubFactor03"); + ir_variable *SubFactor04 = body.make_temp(glsl_type::float_type, "SubFactor04"); + ir_variable *SubFactor05 = body.make_temp(glsl_type::float_type, "SubFactor05"); + ir_variable *SubFactor06 = body.make_temp(glsl_type::float_type, "SubFactor06"); + ir_variable *SubFactor07 = body.make_temp(glsl_type::float_type, "SubFactor07"); + ir_variable *SubFactor08 = body.make_temp(glsl_type::float_type, "SubFactor08"); + ir_variable *SubFactor09 = body.make_temp(glsl_type::float_type, "SubFactor09"); + ir_variable *SubFactor10 = body.make_temp(glsl_type::float_type, "SubFactor10"); + ir_variable *SubFactor11 = body.make_temp(glsl_type::float_type, "SubFactor11"); + ir_variable *SubFactor12 = body.make_temp(glsl_type::float_type, "SubFactor12"); + ir_variable *SubFactor13 = body.make_temp(glsl_type::float_type, "SubFactor13"); + ir_variable *SubFactor14 = body.make_temp(glsl_type::float_type, "SubFactor14"); + ir_variable *SubFactor15 = body.make_temp(glsl_type::float_type, "SubFactor15"); + ir_variable *SubFactor16 = body.make_temp(glsl_type::float_type, "SubFactor16"); + ir_variable *SubFactor17 = body.make_temp(glsl_type::float_type, "SubFactor17"); + ir_variable *SubFactor18 = body.make_temp(glsl_type::float_type, "SubFactor18"); + + body.emit(assign(SubFactor00, sub(mul(matrix_elt(m, 2, 2), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 2), matrix_elt(m, 2, 3))))); + body.emit(assign(SubFactor01, sub(mul(matrix_elt(m, 2, 1), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 2, 3))))); + body.emit(assign(SubFactor02, sub(mul(matrix_elt(m, 2, 1), matrix_elt(m, 3, 2)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 2, 2))))); + body.emit(assign(SubFactor03, sub(mul(matrix_elt(m, 2, 0), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 2, 3))))); + body.emit(assign(SubFactor04, sub(mul(matrix_elt(m, 2, 0), matrix_elt(m, 3, 2)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 2, 2))))); + body.emit(assign(SubFactor05, sub(mul(matrix_elt(m, 2, 0), matrix_elt(m, 3, 1)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 2, 1))))); + body.emit(assign(SubFactor06, sub(mul(matrix_elt(m, 1, 2), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 2), matrix_elt(m, 1, 3))))); + body.emit(assign(SubFactor07, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 1, 3))))); + body.emit(assign(SubFactor08, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 3, 2)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 1, 2))))); + body.emit(assign(SubFactor09, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 1, 3))))); + body.emit(assign(SubFactor10, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 3, 2)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 1, 2))))); + body.emit(assign(SubFactor11, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 3, 3)), mul(matrix_elt(m, 3, 1), matrix_elt(m, 1, 3))))); + body.emit(assign(SubFactor12, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 3, 1)), mul(matrix_elt(m, 3, 0), matrix_elt(m, 1, 1))))); + body.emit(assign(SubFactor13, sub(mul(matrix_elt(m, 1, 2), matrix_elt(m, 2, 3)), mul(matrix_elt(m, 2, 2), matrix_elt(m, 1, 3))))); + body.emit(assign(SubFactor14, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 2, 3)), mul(matrix_elt(m, 2, 1), matrix_elt(m, 1, 3))))); + body.emit(assign(SubFactor15, sub(mul(matrix_elt(m, 1, 1), matrix_elt(m, 2, 2)), mul(matrix_elt(m, 2, 1), matrix_elt(m, 1, 2))))); + body.emit(assign(SubFactor16, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 3)), mul(matrix_elt(m, 2, 0), matrix_elt(m, 1, 3))))); + body.emit(assign(SubFactor17, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 2)), mul(matrix_elt(m, 2, 0), matrix_elt(m, 1, 2))))); + body.emit(assign(SubFactor18, sub(mul(matrix_elt(m, 1, 0), matrix_elt(m, 2, 1)), mul(matrix_elt(m, 2, 0), matrix_elt(m, 1, 1))))); + + ir_variable *adj = body.make_temp(glsl_type::mat4_type, "adj"); + body.emit(assign(array_ref(adj, 0), + add(sub(mul(matrix_elt(m, 1, 1), SubFactor00), + mul(matrix_elt(m, 1, 2), SubFactor01)), + mul(matrix_elt(m, 1, 3), SubFactor02)), + WRITEMASK_X)); + body.emit(assign(array_ref(adj, 1), neg( + add(sub(mul(matrix_elt(m, 1, 0), SubFactor00), + mul(matrix_elt(m, 1, 2), SubFactor03)), + mul(matrix_elt(m, 1, 3), SubFactor04))), + WRITEMASK_X)); + body.emit(assign(array_ref(adj, 2), + add(sub(mul(matrix_elt(m, 1, 0), SubFactor01), + mul(matrix_elt(m, 1, 1), SubFactor03)), + mul(matrix_elt(m, 1, 3), SubFactor05)), + WRITEMASK_X)); + body.emit(assign(array_ref(adj, 3), neg( + add(sub(mul(matrix_elt(m, 1, 0), SubFactor02), + mul(matrix_elt(m, 1, 1), SubFactor04)), + mul(matrix_elt(m, 1, 2), SubFactor05))), + WRITEMASK_X)); + + body.emit(assign(array_ref(adj, 0), neg( + add(sub(mul(matrix_elt(m, 0, 1), SubFactor00), + mul(matrix_elt(m, 0, 2), SubFactor01)), + mul(matrix_elt(m, 0, 3), SubFactor02))), + WRITEMASK_Y)); + body.emit(assign(array_ref(adj, 1), + add(sub(mul(matrix_elt(m, 0, 0), SubFactor00), + mul(matrix_elt(m, 0, 2), SubFactor03)), + mul(matrix_elt(m, 0, 3), SubFactor04)), + WRITEMASK_Y)); + body.emit(assign(array_ref(adj, 2), neg( + add(sub(mul(matrix_elt(m, 0, 0), SubFactor01), + mul(matrix_elt(m, 0, 1), SubFactor03)), + mul(matrix_elt(m, 0, 3), SubFactor05))), + WRITEMASK_Y)); + body.emit(assign(array_ref(adj, 3), + add(sub(mul(matrix_elt(m, 0, 0), SubFactor02), + mul(matrix_elt(m, 0, 1), SubFactor04)), + mul(matrix_elt(m, 0, 2), SubFactor05)), + WRITEMASK_Y)); + + body.emit(assign(array_ref(adj, 0), + add(sub(mul(matrix_elt(m, 0, 1), SubFactor06), + mul(matrix_elt(m, 0, 2), SubFactor07)), + mul(matrix_elt(m, 0, 3), SubFactor08)), + WRITEMASK_Z)); + body.emit(assign(array_ref(adj, 1), neg( + add(sub(mul(matrix_elt(m, 0, 0), SubFactor06), + mul(matrix_elt(m, 0, 2), SubFactor09)), + mul(matrix_elt(m, 0, 3), SubFactor10))), + WRITEMASK_Z)); + body.emit(assign(array_ref(adj, 2), + add(sub(mul(matrix_elt(m, 0, 0), SubFactor11), + mul(matrix_elt(m, 0, 1), SubFactor09)), + mul(matrix_elt(m, 0, 3), SubFactor12)), + WRITEMASK_Z)); + body.emit(assign(array_ref(adj, 3), neg( + add(sub(mul(matrix_elt(m, 0, 0), SubFactor08), + mul(matrix_elt(m, 0, 1), SubFactor10)), + mul(matrix_elt(m, 0, 2), SubFactor12))), + WRITEMASK_Z)); + + body.emit(assign(array_ref(adj, 0), neg( + add(sub(mul(matrix_elt(m, 0, 1), SubFactor13), + mul(matrix_elt(m, 0, 2), SubFactor14)), + mul(matrix_elt(m, 0, 3), SubFactor15))), + WRITEMASK_W)); + body.emit(assign(array_ref(adj, 1), + add(sub(mul(matrix_elt(m, 0, 0), SubFactor13), + mul(matrix_elt(m, 0, 2), SubFactor16)), + mul(matrix_elt(m, 0, 3), SubFactor17)), + WRITEMASK_W)); + body.emit(assign(array_ref(adj, 2), neg( + add(sub(mul(matrix_elt(m, 0, 0), SubFactor14), + mul(matrix_elt(m, 0, 1), SubFactor16)), + mul(matrix_elt(m, 0, 3), SubFactor18))), + WRITEMASK_W)); + body.emit(assign(array_ref(adj, 3), + add(sub(mul(matrix_elt(m, 0, 0), SubFactor15), + mul(matrix_elt(m, 0, 1), SubFactor17)), + mul(matrix_elt(m, 0, 2), SubFactor18)), + WRITEMASK_W)); + + ir_expression *det = + add(mul(matrix_elt(m, 0, 0), matrix_elt(adj, 0, 0)), + add(mul(matrix_elt(m, 0, 1), matrix_elt(adj, 1, 0)), + add(mul(matrix_elt(m, 0, 2), matrix_elt(adj, 2, 0)), + mul(matrix_elt(m, 0, 3), matrix_elt(adj, 3, 0))))); + + body.emit(ret(div(adj, det))); + + return sig; +} + + +ir_function_signature * +builtin_builder::_lessThan(builtin_available_predicate avail, + const glsl_type *type) +{ + return binop(ir_binop_less, avail, + glsl_type::bvec(type->vector_elements), type, type); +} + +ir_function_signature * +builtin_builder::_lessThanEqual(builtin_available_predicate avail, + const glsl_type *type) +{ + return binop(ir_binop_lequal, avail, + glsl_type::bvec(type->vector_elements), type, type); +} + +ir_function_signature * +builtin_builder::_greaterThan(builtin_available_predicate avail, + const glsl_type *type) +{ + return binop(ir_binop_greater, avail, + glsl_type::bvec(type->vector_elements), type, type); +} + +ir_function_signature * +builtin_builder::_greaterThanEqual(builtin_available_predicate avail, + const glsl_type *type) +{ + return binop(ir_binop_gequal, avail, + glsl_type::bvec(type->vector_elements), type, type); +} + +ir_function_signature * +builtin_builder::_equal(builtin_available_predicate avail, + const glsl_type *type) +{ + return binop(ir_binop_equal, avail, + glsl_type::bvec(type->vector_elements), type, type); +} + +ir_function_signature * +builtin_builder::_notEqual(builtin_available_predicate avail, + const glsl_type *type) +{ + return binop(ir_binop_nequal, avail, + glsl_type::bvec(type->vector_elements), type, type); +} + +ir_function_signature * +builtin_builder::_any(const glsl_type *type) +{ + return unop(always_available, ir_unop_any, glsl_type::bool_type, type); +} + +ir_function_signature * +builtin_builder::_all(const glsl_type *type) +{ + ir_variable *v = in_var(type, "v"); + MAKE_SIG(glsl_type::bool_type, always_available, 1, v); + + switch (type->vector_elements) { + case 2: + body.emit(ret(logic_and(swizzle_x(v), swizzle_y(v)))); + break; + case 3: + body.emit(ret(logic_and(logic_and(swizzle_x(v), swizzle_y(v)), + swizzle_z(v)))); + break; + case 4: + body.emit(ret(logic_and(logic_and(logic_and(swizzle_x(v), swizzle_y(v)), + swizzle_z(v)), + swizzle_w(v)))); + break; + } + + return sig; +} + +UNOP(not, ir_unop_logic_not, always_available) + +static bool +has_lod(const glsl_type *sampler_type) +{ + assert(sampler_type->is_sampler()); + + switch (sampler_type->sampler_dimensionality) { + case GLSL_SAMPLER_DIM_RECT: + case GLSL_SAMPLER_DIM_BUF: + case GLSL_SAMPLER_DIM_MS: + return false; + default: + return true; + } +} + +ir_function_signature * +builtin_builder::_textureSize(builtin_available_predicate avail, + const glsl_type *return_type, + const glsl_type *sampler_type) +{ + ir_variable *s = in_var(sampler_type, "sampler"); + /* The sampler always exists; add optional lod later. */ + MAKE_SIG(return_type, avail, 1, s); + + ir_texture *tex = new(mem_ctx) ir_texture(ir_txs); + tex->set_sampler(new(mem_ctx) ir_dereference_variable(s), return_type); + + if (has_lod(sampler_type)) { + ir_variable *lod = in_var(glsl_type::int_type, "lod"); + sig->parameters.push_tail(lod); + tex->lod_info.lod = var_ref(lod); + } else { + tex->lod_info.lod = imm(0u); + } + + body.emit(ret(tex)); + + return sig; +} + +ir_function_signature * +builtin_builder::_texture(ir_texture_opcode opcode, + builtin_available_predicate avail, + const glsl_type *return_type, + const glsl_type *sampler_type, + const glsl_type *coord_type, + int flags) +{ + ir_variable *s = in_var(sampler_type, "sampler"); + ir_variable *P = in_var(coord_type, "P"); + /* The sampler and coordinate always exist; add optional parameters later. */ + MAKE_SIG(return_type, avail, 2, s, P); + + ir_texture *tex = new(mem_ctx) ir_texture(opcode); + tex->set_sampler(var_ref(s), return_type); + + const int coord_size = sampler_type->coordinate_components(); + + if (coord_size == coord_type->vector_elements) { + tex->coordinate = var_ref(P); + } else { + /* The incoming coordinate also has the projector or shadow comparitor, + * so we need to swizzle those away. + */ + tex->coordinate = swizzle_for_size(P, coord_size); + } + + /* The projector is always in the last component. */ + if (flags & TEX_PROJECT) + tex->projector = swizzle(P, coord_type->vector_elements - 1, 1); + + if (sampler_type->sampler_shadow) { + if (opcode == ir_tg4) { + /* gather has refz as a separate parameter, immediately after the + * coordinate + */ + ir_variable *refz = in_var(glsl_type::float_type, "refz"); + sig->parameters.push_tail(refz); + tex->shadow_comparitor = var_ref(refz); + } else { + /* The shadow comparitor is normally in the Z component, but a few types + * have sufficiently large coordinates that it's in W. + */ + tex->shadow_comparitor = swizzle(P, MAX2(coord_size, SWIZZLE_Z), 1); + } + } + + if (opcode == ir_txl) { + ir_variable *lod = in_var(glsl_type::float_type, "lod"); + sig->parameters.push_tail(lod); + tex->lod_info.lod = var_ref(lod); + } else if (opcode == ir_txd) { + int grad_size = coord_size - (sampler_type->sampler_array ? 1 : 0); + ir_variable *dPdx = in_var(glsl_type::vec(grad_size), "dPdx"); + ir_variable *dPdy = in_var(glsl_type::vec(grad_size), "dPdy"); + sig->parameters.push_tail(dPdx); + sig->parameters.push_tail(dPdy); + tex->lod_info.grad.dPdx = var_ref(dPdx); + tex->lod_info.grad.dPdy = var_ref(dPdy); + } + + if (flags & (TEX_OFFSET | TEX_OFFSET_NONCONST)) { + int offset_size = coord_size - (sampler_type->sampler_array ? 1 : 0); + ir_variable *offset = + new(mem_ctx) ir_variable(glsl_type::ivec(offset_size), "offset", + (flags & TEX_OFFSET) ? ir_var_const_in : ir_var_function_in); + sig->parameters.push_tail(offset); + tex->offset = var_ref(offset); + } + + if (flags & TEX_OFFSET_ARRAY) { + ir_variable *offsets = + new(mem_ctx) ir_variable(glsl_type::get_array_instance(glsl_type::ivec2_type, 4), + "offsets", ir_var_const_in); + sig->parameters.push_tail(offsets); + tex->offset = var_ref(offsets); + } + + if (opcode == ir_tg4) { + if (flags & TEX_COMPONENT) { + ir_variable *component = + new(mem_ctx) ir_variable(glsl_type::int_type, "comp", ir_var_const_in); + sig->parameters.push_tail(component); + tex->lod_info.component = var_ref(component); + } + else { + tex->lod_info.component = imm(0); + } + } + + /* The "bias" parameter comes /after/ the "offset" parameter, which is + * inconsistent with both textureLodOffset and textureGradOffset. + */ + if (opcode == ir_txb) { + ir_variable *bias = in_var(glsl_type::float_type, "bias"); + sig->parameters.push_tail(bias); + tex->lod_info.bias = var_ref(bias); + } + + body.emit(ret(tex)); + + return sig; +} + +ir_function_signature * +builtin_builder::_textureCubeArrayShadow() +{ + ir_variable *s = in_var(glsl_type::samplerCubeArrayShadow_type, "sampler"); + ir_variable *P = in_var(glsl_type::vec4_type, "P"); + ir_variable *compare = in_var(glsl_type::float_type, "compare"); + MAKE_SIG(glsl_type::float_type, texture_cube_map_array, 3, s, P, compare); + + ir_texture *tex = new(mem_ctx) ir_texture(ir_tex); + tex->set_sampler(var_ref(s), glsl_type::float_type); + + tex->coordinate = var_ref(P); + tex->shadow_comparitor = var_ref(compare); + + body.emit(ret(tex)); + + return sig; +} + +ir_function_signature * +builtin_builder::_texelFetch(builtin_available_predicate avail, + const glsl_type *return_type, + const glsl_type *sampler_type, + const glsl_type *coord_type, + const glsl_type *offset_type) +{ + ir_variable *s = in_var(sampler_type, "sampler"); + ir_variable *P = in_var(coord_type, "P"); + /* The sampler and coordinate always exist; add optional parameters later. */ + MAKE_SIG(return_type, avail, 2, s, P); + + ir_texture *tex = new(mem_ctx) ir_texture(ir_txf); + tex->coordinate = var_ref(P); + tex->set_sampler(var_ref(s), return_type); + + if (sampler_type->sampler_dimensionality == GLSL_SAMPLER_DIM_MS) { + ir_variable *sample = in_var(glsl_type::int_type, "sample"); + sig->parameters.push_tail(sample); + tex->lod_info.sample_index = var_ref(sample); + tex->op = ir_txf_ms; + } else if (has_lod(sampler_type)) { + ir_variable *lod = in_var(glsl_type::int_type, "lod"); + sig->parameters.push_tail(lod); + tex->lod_info.lod = var_ref(lod); + } else { + tex->lod_info.lod = imm(0u); + } + + if (offset_type != NULL) { + ir_variable *offset = + new(mem_ctx) ir_variable(offset_type, "offset", ir_var_const_in); + sig->parameters.push_tail(offset); + tex->offset = var_ref(offset); + } + + body.emit(ret(tex)); + + return sig; +} + +ir_function_signature * +builtin_builder::_EmitVertex() +{ + MAKE_SIG(glsl_type::void_type, gs_only, 0); + + body.emit(new(mem_ctx) ir_emit_vertex()); + + return sig; +} + +ir_function_signature * +builtin_builder::_EndPrimitive() +{ + MAKE_SIG(glsl_type::void_type, gs_only, 0); + + body.emit(new(mem_ctx) ir_end_primitive()); + + return sig; +} + +ir_function_signature * +builtin_builder::_textureQueryLod(const glsl_type *sampler_type, + const glsl_type *coord_type) +{ + ir_variable *s = in_var(sampler_type, "sampler"); + ir_variable *coord = in_var(coord_type, "coord"); + /* The sampler and coordinate always exist; add optional parameters later. */ + MAKE_SIG(glsl_type::vec2_type, texture_query_lod, 2, s, coord); + + ir_texture *tex = new(mem_ctx) ir_texture(ir_lod); + tex->coordinate = var_ref(coord); + tex->set_sampler(var_ref(s), glsl_type::vec2_type); + + body.emit(ret(tex)); + + return sig; +} + +ir_function_signature * +builtin_builder::_textureQueryLevels(const glsl_type *sampler_type) +{ + ir_variable *s = in_var(sampler_type, "sampler"); + const glsl_type *return_type = glsl_type::int_type; + MAKE_SIG(return_type, texture_query_levels, 1, s); + + ir_texture *tex = new(mem_ctx) ir_texture(ir_query_levels); + tex->set_sampler(var_ref(s), return_type); + + body.emit(ret(tex)); + + return sig; +} + +UNOP(dFdx, ir_unop_dFdx, fs_oes_derivatives) +UNOP(dFdy, ir_unop_dFdy, fs_oes_derivatives) + +ir_function_signature * +builtin_builder::_fwidth(const glsl_type *type) +{ + ir_variable *p = in_var(type, "p"); + MAKE_SIG(type, fs_oes_derivatives, 1, p); + + body.emit(ret(add(abs(expr(ir_unop_dFdx, p)), abs(expr(ir_unop_dFdy, p))))); + + return sig; +} + +ir_function_signature * +builtin_builder::_noise1(const glsl_type *type) +{ + return unop(v110, ir_unop_noise, glsl_type::float_type, type); +} + +ir_function_signature * +builtin_builder::_noise2(const glsl_type *type) +{ + ir_variable *p = in_var(type, "p"); + MAKE_SIG(glsl_type::vec2_type, v110, 1, p); + + ir_constant_data b_offset; + b_offset.f[0] = 601.0f; + b_offset.f[1] = 313.0f; + b_offset.f[2] = 29.0f; + b_offset.f[3] = 277.0f; + + ir_variable *a = body.make_temp(glsl_type::float_type, "a"); + ir_variable *b = body.make_temp(glsl_type::float_type, "b"); + ir_variable *t = body.make_temp(glsl_type::vec2_type, "t"); + body.emit(assign(a, expr(ir_unop_noise, p))); + body.emit(assign(b, expr(ir_unop_noise, add(p, imm(type, b_offset))))); + body.emit(assign(t, a, WRITEMASK_X)); + body.emit(assign(t, b, WRITEMASK_Y)); + body.emit(ret(t)); + + return sig; +} + +ir_function_signature * +builtin_builder::_noise3(const glsl_type *type) +{ + ir_variable *p = in_var(type, "p"); + MAKE_SIG(glsl_type::vec3_type, v110, 1, p); + + ir_constant_data b_offset; + b_offset.f[0] = 601.0f; + b_offset.f[1] = 313.0f; + b_offset.f[2] = 29.0f; + b_offset.f[3] = 277.0f; + + ir_constant_data c_offset; + c_offset.f[0] = 1559.0f; + c_offset.f[1] = 113.0f; + c_offset.f[2] = 1861.0f; + c_offset.f[3] = 797.0f; + + ir_variable *a = body.make_temp(glsl_type::float_type, "a"); + ir_variable *b = body.make_temp(glsl_type::float_type, "b"); + ir_variable *c = body.make_temp(glsl_type::float_type, "c"); + ir_variable *t = body.make_temp(glsl_type::vec3_type, "t"); + body.emit(assign(a, expr(ir_unop_noise, p))); + body.emit(assign(b, expr(ir_unop_noise, add(p, imm(type, b_offset))))); + body.emit(assign(c, expr(ir_unop_noise, add(p, imm(type, c_offset))))); + body.emit(assign(t, a, WRITEMASK_X)); + body.emit(assign(t, b, WRITEMASK_Y)); + body.emit(assign(t, c, WRITEMASK_Z)); + body.emit(ret(t)); + + return sig; +} + +ir_function_signature * +builtin_builder::_noise4(const glsl_type *type) +{ + ir_variable *p = in_var(type, "p"); + MAKE_SIG(glsl_type::vec4_type, v110, 1, p); + + ir_variable *_p = body.make_temp(type, "_p"); + + ir_constant_data p_offset; + p_offset.f[0] = 1559.0f; + p_offset.f[1] = 113.0f; + p_offset.f[2] = 1861.0f; + p_offset.f[3] = 797.0f; + + body.emit(assign(_p, add(p, imm(type, p_offset)))); + + ir_constant_data offset; + offset.f[0] = 601.0f; + offset.f[1] = 313.0f; + offset.f[2] = 29.0f; + offset.f[3] = 277.0f; + + ir_variable *a = body.make_temp(glsl_type::float_type, "a"); + ir_variable *b = body.make_temp(glsl_type::float_type, "b"); + ir_variable *c = body.make_temp(glsl_type::float_type, "c"); + ir_variable *d = body.make_temp(glsl_type::float_type, "d"); + ir_variable *t = body.make_temp(glsl_type::vec4_type, "t"); + body.emit(assign(a, expr(ir_unop_noise, p))); + body.emit(assign(b, expr(ir_unop_noise, add(p, imm(type, offset))))); + body.emit(assign(c, expr(ir_unop_noise, _p))); + body.emit(assign(d, expr(ir_unop_noise, add(_p, imm(type, offset))))); + body.emit(assign(t, a, WRITEMASK_X)); + body.emit(assign(t, b, WRITEMASK_Y)); + body.emit(assign(t, c, WRITEMASK_Z)); + body.emit(assign(t, d, WRITEMASK_W)); + body.emit(ret(t)); + + return sig; +} + +ir_function_signature * +builtin_builder::_bitfieldExtract(const glsl_type *type) +{ + ir_variable *value = in_var(type, "value"); + ir_variable *offset = in_var(glsl_type::int_type, "offset"); + ir_variable *bits = in_var(glsl_type::int_type, "bits"); + MAKE_SIG(type, gpu_shader5, 3, value, offset, bits); + + body.emit(ret(expr(ir_triop_bitfield_extract, value, offset, bits))); + + return sig; +} + +ir_function_signature * +builtin_builder::_bitfieldInsert(const glsl_type *type) +{ + ir_variable *base = in_var(type, "base"); + ir_variable *insert = in_var(type, "insert"); + ir_variable *offset = in_var(glsl_type::int_type, "offset"); + ir_variable *bits = in_var(glsl_type::int_type, "bits"); + MAKE_SIG(type, gpu_shader5, 4, base, insert, offset, bits); + + body.emit(ret(bitfield_insert(base, insert, offset, bits))); + + return sig; +} + +UNOP(bitfieldReverse, ir_unop_bitfield_reverse, gpu_shader5) + +ir_function_signature * +builtin_builder::_bitCount(const glsl_type *type) +{ + return unop(gpu_shader5, ir_unop_bit_count, + glsl_type::ivec(type->vector_elements), type); +} + +ir_function_signature * +builtin_builder::_findLSB(const glsl_type *type) +{ + return unop(gpu_shader5, ir_unop_find_lsb, + glsl_type::ivec(type->vector_elements), type); +} + +ir_function_signature * +builtin_builder::_findMSB(const glsl_type *type) +{ + return unop(gpu_shader5, ir_unop_find_msb, + glsl_type::ivec(type->vector_elements), type); +} + +ir_function_signature * +builtin_builder::_fma(const glsl_type *type) +{ + ir_variable *a = in_var(type, "a"); + ir_variable *b = in_var(type, "b"); + ir_variable *c = in_var(type, "c"); + MAKE_SIG(type, gpu_shader5, 3, a, b, c); + + body.emit(ret(ir_builder::fma(a, b, c))); + + return sig; +} + +ir_function_signature * +builtin_builder::_ldexp(const glsl_type *x_type, const glsl_type *exp_type) +{ + return binop(ir_binop_ldexp, gpu_shader5, x_type, x_type, exp_type); +} + +ir_function_signature * +builtin_builder::_frexp(const glsl_type *x_type, const glsl_type *exp_type) +{ + ir_variable *x = in_var(x_type, "x"); + ir_variable *exponent = out_var(exp_type, "exp"); + MAKE_SIG(x_type, gpu_shader5, 2, x, exponent); + + const unsigned vec_elem = x_type->vector_elements; + const glsl_type *bvec = glsl_type::get_instance(GLSL_TYPE_BOOL, vec_elem, 1); + const glsl_type *uvec = glsl_type::get_instance(GLSL_TYPE_UINT, vec_elem, 1); + + /* Single-precision floating-point values are stored as + * 1 sign bit; + * 8 exponent bits; + * 23 mantissa bits. + * + * An exponent shift of 23 will shift the mantissa out, leaving only the + * exponent and sign bit (which itself may be zero, if the absolute value + * was taken before the bitcast and shift. + */ + ir_constant *exponent_shift = imm(23); + ir_constant *exponent_bias = imm(-126, vec_elem); + + ir_constant *sign_mantissa_mask = imm(0x807fffffu, vec_elem); + + /* Exponent of floating-point values in the range [0.5, 1.0). */ + ir_constant *exponent_value = imm(0x3f000000u, vec_elem); + + ir_variable *is_not_zero = body.make_temp(bvec, "is_not_zero"); + body.emit(assign(is_not_zero, nequal(abs(x), imm(0.0f, vec_elem)))); + + /* Since abs(x) ensures that the sign bit is zero, we don't need to bitcast + * to unsigned integers to ensure that 1 bits aren't shifted in. + */ + body.emit(assign(exponent, rshift(bitcast_f2i(abs(x)), exponent_shift))); + body.emit(assign(exponent, add(exponent, csel(is_not_zero, exponent_bias, + imm(0, vec_elem))))); + + ir_variable *bits = body.make_temp(uvec, "bits"); + body.emit(assign(bits, bitcast_f2u(x))); + body.emit(assign(bits, bit_and(bits, sign_mantissa_mask))); + body.emit(assign(bits, bit_or(bits, csel(is_not_zero, exponent_value, + imm(0u, vec_elem))))); + body.emit(ret(bitcast_u2f(bits))); + + return sig; +} + +ir_function_signature * +builtin_builder::_uaddCarry(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + ir_variable *y = in_var(type, "y"); + ir_variable *carry = out_var(type, "carry"); + MAKE_SIG(type, gpu_shader5, 3, x, y, carry); + + body.emit(assign(carry, ir_builder::carry(x, y))); + body.emit(ret(add(x, y))); + + return sig; +} + +ir_function_signature * +builtin_builder::_usubBorrow(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + ir_variable *y = in_var(type, "y"); + ir_variable *borrow = out_var(type, "borrow"); + MAKE_SIG(type, gpu_shader5, 3, x, y, borrow); + + body.emit(assign(borrow, ir_builder::borrow(x, y))); + body.emit(ret(sub(x, y))); + + return sig; +} + +/** + * For both imulExtended() and umulExtended() built-ins. + */ +ir_function_signature * +builtin_builder::_mulExtended(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + ir_variable *y = in_var(type, "y"); + ir_variable *msb = out_var(type, "msb"); + ir_variable *lsb = out_var(type, "lsb"); + MAKE_SIG(glsl_type::void_type, gpu_shader5, 4, x, y, msb, lsb); + + body.emit(assign(msb, imul_high(x, y))); + body.emit(assign(lsb, mul(x, y))); + + return sig; +} + +ir_function_signature * +builtin_builder::_atomic_intrinsic(builtin_available_predicate avail) +{ + ir_variable *counter = in_var(glsl_type::atomic_uint_type, "counter"); + MAKE_INTRINSIC(glsl_type::uint_type, avail, 1, counter); + return sig; +} + +ir_function_signature * +builtin_builder::_atomic_op(const char *intrinsic, + builtin_available_predicate avail) +{ + ir_variable *counter = in_var(glsl_type::atomic_uint_type, "atomic_counter"); + MAKE_SIG(glsl_type::uint_type, avail, 1, counter); + + ir_variable *retval = body.make_temp(glsl_type::uint_type, "atomic_retval"); + body.emit(call(shader->symbols->get_function(intrinsic), retval, + sig->parameters)); + body.emit(ret(retval)); + return sig; +} + +ir_function_signature * +builtin_builder::_min3(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + ir_variable *y = in_var(type, "y"); + ir_variable *z = in_var(type, "z"); + MAKE_SIG(type, shader_trinary_minmax, 3, x, y, z); + + ir_expression *min3 = min2(x, min2(y,z)); + body.emit(ret(min3)); + + return sig; +} + +ir_function_signature * +builtin_builder::_max3(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + ir_variable *y = in_var(type, "y"); + ir_variable *z = in_var(type, "z"); + MAKE_SIG(type, shader_trinary_minmax, 3, x, y, z); + + ir_expression *max3 = max2(x, max2(y,z)); + body.emit(ret(max3)); + + return sig; +} + +ir_function_signature * +builtin_builder::_mid3(const glsl_type *type) +{ + ir_variable *x = in_var(type, "x"); + ir_variable *y = in_var(type, "y"); + ir_variable *z = in_var(type, "z"); + MAKE_SIG(type, shader_trinary_minmax, 3, x, y, z); + + ir_expression *mid3 = max2(min2(x, y), max2(min2(x, z), min2(y, z))); + body.emit(ret(mid3)); + + return sig; +} + +ir_function_signature * +builtin_builder::_image_prototype(const glsl_type *image_type, + const char *intrinsic_name, + unsigned num_arguments, + unsigned flags) +{ + const glsl_type *data_type = glsl_type::get_instance( + image_type->sampler_type, + (flags & IMAGE_FUNCTION_HAS_VECTOR_DATA_TYPE ? 4 : 1), + 1); + const glsl_type *ret_type = (flags & IMAGE_FUNCTION_RETURNS_VOID ? + glsl_type::void_type : data_type); + + /* Addressing arguments that are always present. */ + ir_variable *image = in_var(image_type, "image"); + ir_variable *coord = in_var( + glsl_type::ivec(image_type->coordinate_components()), "coord"); + + ir_function_signature *sig = new_sig( + ret_type, shader_image_load_store, 2, image, coord); + + /* Sample index for multisample images. */ + if (image_type->sampler_dimensionality == GLSL_SAMPLER_DIM_MS) + sig->parameters.push_tail(in_var(glsl_type::int_type, "sample")); + + /* Data arguments. */ + for (unsigned i = 0; i < num_arguments; ++i) + sig->parameters.push_tail(in_var(data_type, + ralloc_asprintf(NULL, "arg%d", i))); + + /* Set the maximal set of qualifiers allowed for this image + * built-in. Function calls with arguments having fewer + * qualifiers than present in the prototype are allowed by the + * spec, but not with more, i.e. this will make the compiler + * accept everything that needs to be accepted, and reject cases + * like loads from write-only or stores to read-only images. + */ + image->data.image.read_only = flags & IMAGE_FUNCTION_READ_ONLY; + image->data.image.write_only = flags & IMAGE_FUNCTION_WRITE_ONLY; + image->data.image.coherent = true; + image->data.image._volatile = true; + image->data.image.restrict_flag = true; + + return sig; +} + +ir_function_signature * +builtin_builder::_image(const glsl_type *image_type, + const char *intrinsic_name, + unsigned num_arguments, + unsigned flags) +{ + ir_function_signature *sig = _image_prototype(image_type, intrinsic_name, + num_arguments, flags); + + if (flags & IMAGE_FUNCTION_EMIT_STUB) { + ir_factory body(&sig->body, mem_ctx); + ir_function *f = shader->symbols->get_function(intrinsic_name); + + if (flags & IMAGE_FUNCTION_RETURNS_VOID) { + body.emit(call(f, NULL, sig->parameters)); + } else { + ir_variable *ret_val = + body.make_temp(sig->return_type, "_ret_val"); + body.emit(call(f, ret_val, sig->parameters)); + body.emit(ret(ret_val)); + } + + sig->is_defined = true; + + } else { + sig->is_intrinsic = true; + } + + return sig; +} + +ir_function_signature * +builtin_builder::_memory_barrier_intrinsic(builtin_available_predicate avail) +{ + MAKE_INTRINSIC(glsl_type::void_type, avail, 0); + return sig; +} + +ir_function_signature * +builtin_builder::_memory_barrier(builtin_available_predicate avail) +{ + MAKE_SIG(glsl_type::void_type, avail, 0); + body.emit(call(shader->symbols->get_function("__intrinsic_memory_barrier"), + NULL, sig->parameters)); + return sig; +} + +/** @} */ + +/******************************************************************************/ + +/* The singleton instance of builtin_builder. */ +static builtin_builder builtins; +static mtx_t builtins_lock = _MTX_INITIALIZER_NP; + +/** + * External API (exposing the built-in module to the rest of the compiler): + * @{ + */ +void +_mesa_glsl_initialize_builtin_functions() +{ + mtx_lock(&builtins_lock); + builtins.initialize(); + mtx_unlock(&builtins_lock); +} + +void +_mesa_glsl_release_builtin_functions() +{ + mtx_lock(&builtins_lock); + builtins.release(); + mtx_unlock(&builtins_lock); +} + +ir_function_signature * +_mesa_glsl_find_builtin_function(_mesa_glsl_parse_state *state, + const char *name, exec_list *actual_parameters) +{ + ir_function_signature * s; + mtx_lock(&builtins_lock); + s = builtins.find(state, name, actual_parameters); + mtx_unlock(&builtins_lock); + return s; +} + +gl_shader * +_mesa_glsl_get_builtin_function_shader() +{ + return builtins.shader; +} + +/** @} */ diff --git a/dist/Mesa/src/glsl/builtin_type_macros.h b/dist/Mesa/src/glsl/builtin_type_macros.h index fec38da12..236e1ce8c 100644 --- a/dist/Mesa/src/glsl/builtin_type_macros.h +++ b/dist/Mesa/src/glsl/builtin_type_macros.h @@ -64,51 +64,87 @@ DECL_TYPE(mat3x4, GL_FLOAT_MAT3x4, GLSL_TYPE_FLOAT, 4, 3) DECL_TYPE(mat4x2, GL_FLOAT_MAT4x2, GLSL_TYPE_FLOAT, 2, 4) DECL_TYPE(mat4x3, GL_FLOAT_MAT4x3, GLSL_TYPE_FLOAT, 3, 4) -DECL_TYPE(sampler1D, GL_SAMPLER_1D, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2D, GL_SAMPLER_2D, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler3D, GL_SAMPLER_3D, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(samplerCube, GL_SAMPLER_CUBE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler1DArray, GL_SAMPLER_1D_ARRAY, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DArray, GL_SAMPLER_2D_ARRAY, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_FLOAT) -DECL_TYPE(samplerCubeArray, GL_SAMPLER_CUBE_MAP_ARRAY, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DRect, GL_SAMPLER_2D_RECT, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(samplerBuffer, GL_SAMPLER_BUFFER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DMS, GL_SAMPLER_2D_MULTISAMPLE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DMSArray, GL_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_FLOAT) - -DECL_TYPE(isampler1D, GL_INT_SAMPLER_1D, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isampler2D, GL_INT_SAMPLER_2D, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isampler3D, GL_INT_SAMPLER_3D, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isamplerCube, GL_INT_SAMPLER_CUBE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isampler1DArray, GL_INT_SAMPLER_1D_ARRAY, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_INT) -DECL_TYPE(isampler2DArray, GL_INT_SAMPLER_2D_ARRAY, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_INT) -DECL_TYPE(isamplerCubeArray, GL_INT_SAMPLER_CUBE_MAP_ARRAY, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_INT) -DECL_TYPE(isampler2DRect, GL_INT_SAMPLER_2D_RECT, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isamplerBuffer, GL_INT_SAMPLER_BUFFER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isampler2DMS, GL_INT_SAMPLER_2D_MULTISAMPLE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_INT) -DECL_TYPE(isampler2DMSArray, GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_INT) - -DECL_TYPE(usampler1D, GL_UNSIGNED_INT_SAMPLER_1D, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usampler2D, GL_UNSIGNED_INT_SAMPLER_2D, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usampler3D, GL_UNSIGNED_INT_SAMPLER_3D, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usamplerCube, GL_INT_SAMPLER_CUBE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usampler1DArray, GL_UNSIGNED_INT_SAMPLER_1D_ARRAY, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_UINT) -DECL_TYPE(usampler2DArray, GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_UINT) -DECL_TYPE(usamplerCubeArray, GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_UINT) -DECL_TYPE(usampler2DRect, GL_UNSIGNED_INT_SAMPLER_2D_RECT, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usamplerBuffer, GL_UNSIGNED_INT_SAMPLER_BUFFER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usampler2DMS, GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_UINT) -DECL_TYPE(usampler2DMSArray, GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_UINT) - -DECL_TYPE(sampler1DShadow, GL_SAMPLER_1D_SHADOW, GLSL_SAMPLER_DIM_1D, 1, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DShadow, GL_SAMPLER_2D_SHADOW, GLSL_SAMPLER_DIM_2D, 1, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(samplerCubeShadow, GL_SAMPLER_CUBE_SHADOW, GLSL_SAMPLER_DIM_CUBE, 1, 0, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler1DArrayShadow, GL_SAMPLER_1D_ARRAY_SHADOW, GLSL_SAMPLER_DIM_1D, 1, 1, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DArrayShadow, GL_SAMPLER_2D_ARRAY_SHADOW, GLSL_SAMPLER_DIM_2D, 1, 1, GLSL_TYPE_FLOAT) -DECL_TYPE(samplerCubeArrayShadow, GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW, GLSL_SAMPLER_DIM_CUBE, 1, 1, GLSL_TYPE_FLOAT) -DECL_TYPE(sampler2DRectShadow, GL_SAMPLER_2D_RECT_SHADOW, GLSL_SAMPLER_DIM_RECT, 1, 0, GLSL_TYPE_FLOAT) - -DECL_TYPE(samplerExternalOES, GL_SAMPLER_EXTERNAL_OES, GLSL_SAMPLER_DIM_EXTERNAL, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler1D, GL_SAMPLER_1D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2D, GL_SAMPLER_2D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler3D, GL_SAMPLER_3D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(samplerCube, GL_SAMPLER_CUBE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler1DArray, GL_SAMPLER_1D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DArray, GL_SAMPLER_2D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_FLOAT) +DECL_TYPE(samplerCubeArray, GL_SAMPLER_CUBE_MAP_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DRect, GL_SAMPLER_2D_RECT, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(samplerBuffer, GL_SAMPLER_BUFFER, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DMS, GL_SAMPLER_2D_MULTISAMPLE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DMSArray, GL_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_FLOAT) + +DECL_TYPE(isampler1D, GL_INT_SAMPLER_1D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isampler2D, GL_INT_SAMPLER_2D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isampler3D, GL_INT_SAMPLER_3D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isamplerCube, GL_INT_SAMPLER_CUBE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isampler1DArray, GL_INT_SAMPLER_1D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_INT) +DECL_TYPE(isampler2DArray, GL_INT_SAMPLER_2D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_INT) +DECL_TYPE(isamplerCubeArray, GL_INT_SAMPLER_CUBE_MAP_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_INT) +DECL_TYPE(isampler2DRect, GL_INT_SAMPLER_2D_RECT, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isamplerBuffer, GL_INT_SAMPLER_BUFFER, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isampler2DMS, GL_INT_SAMPLER_2D_MULTISAMPLE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_INT) +DECL_TYPE(isampler2DMSArray, GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_INT) + +DECL_TYPE(usampler1D, GL_UNSIGNED_INT_SAMPLER_1D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usampler2D, GL_UNSIGNED_INT_SAMPLER_2D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usampler3D, GL_UNSIGNED_INT_SAMPLER_3D, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usamplerCube, GL_UNSIGNED_INT_SAMPLER_CUBE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usampler1DArray, GL_UNSIGNED_INT_SAMPLER_1D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_UINT) +DECL_TYPE(usampler2DArray, GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_UINT) +DECL_TYPE(usamplerCubeArray, GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_UINT) +DECL_TYPE(usampler2DRect, GL_UNSIGNED_INT_SAMPLER_2D_RECT, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usamplerBuffer, GL_UNSIGNED_INT_SAMPLER_BUFFER, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usampler2DMS, GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_UINT) +DECL_TYPE(usampler2DMSArray, GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_UINT) + +DECL_TYPE(sampler1DShadow, GL_SAMPLER_1D_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 1, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DShadow, GL_SAMPLER_2D_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 1, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(samplerCubeShadow, GL_SAMPLER_CUBE_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 1, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler1DArrayShadow, GL_SAMPLER_1D_ARRAY_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_1D, 1, 1, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DArrayShadow, GL_SAMPLER_2D_ARRAY_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_2D, 1, 1, GLSL_TYPE_FLOAT) +DECL_TYPE(samplerCubeArrayShadow, GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_CUBE, 1, 1, GLSL_TYPE_FLOAT) +DECL_TYPE(sampler2DRectShadow, GL_SAMPLER_2D_RECT_SHADOW, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_RECT, 1, 0, GLSL_TYPE_FLOAT) + +DECL_TYPE(samplerExternalOES, GL_SAMPLER_EXTERNAL_OES, GLSL_TYPE_SAMPLER, GLSL_SAMPLER_DIM_EXTERNAL, 0, 0, GLSL_TYPE_FLOAT) + +DECL_TYPE(image1D, GL_IMAGE_1D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(image2D, GL_IMAGE_2D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(image3D, GL_IMAGE_3D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(image2DRect, GL_IMAGE_2D_RECT, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(imageCube, GL_IMAGE_CUBE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(imageBuffer, GL_IMAGE_BUFFER, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(image1DArray, GL_IMAGE_1D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_FLOAT); +DECL_TYPE(image2DArray, GL_IMAGE_2D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_FLOAT); +DECL_TYPE(imageCubeArray, GL_IMAGE_CUBE_MAP_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_FLOAT); +DECL_TYPE(image2DMS, GL_IMAGE_2D_MULTISAMPLE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_FLOAT); +DECL_TYPE(image2DMSArray, GL_IMAGE_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_FLOAT); +DECL_TYPE(iimage1D, GL_INT_IMAGE_1D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimage2D, GL_INT_IMAGE_2D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimage3D, GL_INT_IMAGE_3D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimage2DRect, GL_INT_IMAGE_2D_RECT, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimageCube, GL_INT_IMAGE_CUBE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimageBuffer, GL_INT_IMAGE_BUFFER, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimage1DArray, GL_INT_IMAGE_1D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_INT); +DECL_TYPE(iimage2DArray, GL_INT_IMAGE_2D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_INT); +DECL_TYPE(iimageCubeArray, GL_INT_IMAGE_CUBE_MAP_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_INT); +DECL_TYPE(iimage2DMS, GL_INT_IMAGE_2D_MULTISAMPLE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_INT); +DECL_TYPE(iimage2DMSArray, GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_INT); +DECL_TYPE(uimage1D, GL_UNSIGNED_INT_IMAGE_1D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimage2D, GL_UNSIGNED_INT_IMAGE_2D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimage3D, GL_UNSIGNED_INT_IMAGE_3D, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimage2DRect, GL_UNSIGNED_INT_IMAGE_2D_RECT, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimageCube, GL_UNSIGNED_INT_IMAGE_CUBE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimageBuffer, GL_UNSIGNED_INT_IMAGE_BUFFER, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimage1DArray, GL_UNSIGNED_INT_IMAGE_1D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_UINT); +DECL_TYPE(uimage2DArray, GL_UNSIGNED_INT_IMAGE_2D_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_UINT); +DECL_TYPE(uimageCubeArray, GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_CUBE, 0, 1, GLSL_TYPE_UINT); +DECL_TYPE(uimage2DMS, GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 0, GLSL_TYPE_UINT); +DECL_TYPE(uimage2DMSArray, GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY, GLSL_TYPE_IMAGE, GLSL_SAMPLER_DIM_MS, 0, 1, GLSL_TYPE_UINT); + +DECL_TYPE(atomic_uint, GL_UNSIGNED_INT_ATOMIC_COUNTER, GLSL_TYPE_ATOMIC_UINT, 1, 1) STRUCT_TYPE(gl_DepthRangeParameters) STRUCT_TYPE(gl_PointParameters) diff --git a/dist/Mesa/src/glsl/builtin_types.cpp b/dist/Mesa/src/glsl/builtin_types.cpp index 722eda2da..0a0fa8cd3 100644 --- a/dist/Mesa/src/glsl/builtin_types.cpp +++ b/dist/Mesa/src/glsl/builtin_types.cpp @@ -53,64 +53,64 @@ &glsl_type::_struct_##NAME##_type; static const struct glsl_struct_field gl_DepthRangeParameters_fields[] = { - { glsl_type::float_type, "near", false }, - { glsl_type::float_type, "far", false }, - { glsl_type::float_type, "diff", false }, + { glsl_type::float_type, "near", false, -1 }, + { glsl_type::float_type, "far", false, -1 }, + { glsl_type::float_type, "diff", false, -1 }, }; static const struct glsl_struct_field gl_PointParameters_fields[] = { - { glsl_type::float_type, "size", false }, - { glsl_type::float_type, "sizeMin", false }, - { glsl_type::float_type, "sizeMax", false }, - { glsl_type::float_type, "fadeThresholdSize", false }, - { glsl_type::float_type, "distanceConstantAttenuation", false }, - { glsl_type::float_type, "distanceLinearAttenuation", false }, - { glsl_type::float_type, "distanceQuadraticAttenuation", false }, + { glsl_type::float_type, "size", false, -1 }, + { glsl_type::float_type, "sizeMin", false, -1 }, + { glsl_type::float_type, "sizeMax", false, -1 }, + { glsl_type::float_type, "fadeThresholdSize", false, -1 }, + { glsl_type::float_type, "distanceConstantAttenuation", false, -1 }, + { glsl_type::float_type, "distanceLinearAttenuation", false, -1 }, + { glsl_type::float_type, "distanceQuadraticAttenuation", false, -1 }, }; static const struct glsl_struct_field gl_MaterialParameters_fields[] = { - { glsl_type::vec4_type, "emission", false }, - { glsl_type::vec4_type, "ambient", false }, - { glsl_type::vec4_type, "diffuse", false }, - { glsl_type::vec4_type, "specular", false }, - { glsl_type::float_type, "shininess", false }, + { glsl_type::vec4_type, "emission", false, -1 }, + { glsl_type::vec4_type, "ambient", false, -1 }, + { glsl_type::vec4_type, "diffuse", false, -1 }, + { glsl_type::vec4_type, "specular", false, -1 }, + { glsl_type::float_type, "shininess", false, -1 }, }; static const struct glsl_struct_field gl_LightSourceParameters_fields[] = { - { glsl_type::vec4_type, "ambient", false }, - { glsl_type::vec4_type, "diffuse", false }, - { glsl_type::vec4_type, "specular", false }, - { glsl_type::vec4_type, "position", false }, - { glsl_type::vec4_type, "halfVector", false }, - { glsl_type::vec3_type, "spotDirection", false }, - { glsl_type::float_type, "spotExponent", false }, - { glsl_type::float_type, "spotCutoff", false }, - { glsl_type::float_type, "spotCosCutoff", false }, - { glsl_type::float_type, "constantAttenuation", false }, - { glsl_type::float_type, "linearAttenuation", false }, - { glsl_type::float_type, "quadraticAttenuation", false }, + { glsl_type::vec4_type, "ambient", false, -1 }, + { glsl_type::vec4_type, "diffuse", false, -1 }, + { glsl_type::vec4_type, "specular", false, -1 }, + { glsl_type::vec4_type, "position", false, -1 }, + { glsl_type::vec4_type, "halfVector", false, -1 }, + { glsl_type::vec3_type, "spotDirection", false, -1 }, + { glsl_type::float_type, "spotExponent", false, -1 }, + { glsl_type::float_type, "spotCutoff", false, -1 }, + { glsl_type::float_type, "spotCosCutoff", false, -1 }, + { glsl_type::float_type, "constantAttenuation", false, -1 }, + { glsl_type::float_type, "linearAttenuation", false, -1 }, + { glsl_type::float_type, "quadraticAttenuation", false, -1 }, }; static const struct glsl_struct_field gl_LightModelParameters_fields[] = { - { glsl_type::vec4_type, "ambient", false }, + { glsl_type::vec4_type, "ambient", false, -1 }, }; static const struct glsl_struct_field gl_LightModelProducts_fields[] = { - { glsl_type::vec4_type, "sceneColor", false }, + { glsl_type::vec4_type, "sceneColor", false, -1 }, }; static const struct glsl_struct_field gl_LightProducts_fields[] = { - { glsl_type::vec4_type, "ambient", false }, - { glsl_type::vec4_type, "diffuse", false }, - { glsl_type::vec4_type, "specular", false }, + { glsl_type::vec4_type, "ambient", false, -1 }, + { glsl_type::vec4_type, "diffuse", false, -1 }, + { glsl_type::vec4_type, "specular", false, -1 }, }; static const struct glsl_struct_field gl_FogParameters_fields[] = { - { glsl_type::vec4_type, "color", false }, - { glsl_type::float_type, "density", false }, - { glsl_type::float_type, "start", false }, - { glsl_type::float_type, "end", false }, - { glsl_type::float_type, "scale", false }, + { glsl_type::vec4_type, "color", false, -1 }, + { glsl_type::float_type, "density", false, -1 }, + { glsl_type::float_type, "start", false, -1 }, + { glsl_type::float_type, "end", false, -1 }, + { glsl_type::float_type, "scale", false, -1 }, }; #include "builtin_type_macros.h" @@ -203,9 +203,45 @@ const static struct builtin_type_versions { T(sampler2DRectShadow, 140, 999) T(struct_gl_DepthRangeParameters, 110, 100) + + T(image1D, 420, 999) + T(image2D, 420, 999) + T(image3D, 420, 999) + T(image2DRect, 420, 999) + T(imageCube, 420, 999) + T(imageBuffer, 420, 999) + T(image1DArray, 420, 999) + T(image2DArray, 420, 999) + T(imageCubeArray, 420, 999) + T(image2DMS, 420, 999) + T(image2DMSArray, 420, 999) + T(iimage1D, 420, 999) + T(iimage2D, 420, 999) + T(iimage3D, 420, 999) + T(iimage2DRect, 420, 999) + T(iimageCube, 420, 999) + T(iimageBuffer, 420, 999) + T(iimage1DArray, 420, 999) + T(iimage2DArray, 420, 999) + T(iimageCubeArray, 420, 999) + T(iimage2DMS, 420, 999) + T(iimage2DMSArray, 420, 999) + T(uimage1D, 420, 999) + T(uimage2D, 420, 999) + T(uimage3D, 420, 999) + T(uimage2DRect, 420, 999) + T(uimageCube, 420, 999) + T(uimageBuffer, 420, 999) + T(uimage1DArray, 420, 999) + T(uimage2DArray, 420, 999) + T(uimageCubeArray, 420, 999) + T(uimage2DMS, 420, 999) + T(uimage2DMSArray, 420, 999) + + T(atomic_uint, 420, 999) }; -const glsl_type *const deprecated_types[] = { +static const glsl_type *const deprecated_types[] = { glsl_type::struct_gl_PointParameters_type, glsl_type::struct_gl_MaterialParameters_type, glsl_type::struct_gl_LightSourceParameters_type, @@ -284,5 +320,45 @@ _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state) if (state->OES_texture_3D_enable) { add_type(symbols, glsl_type::sampler3D_type); } + + if (state->ARB_shader_image_load_store_enable) { + add_type(symbols, glsl_type::image1D_type); + add_type(symbols, glsl_type::image2D_type); + add_type(symbols, glsl_type::image3D_type); + add_type(symbols, glsl_type::image2DRect_type); + add_type(symbols, glsl_type::imageCube_type); + add_type(symbols, glsl_type::imageBuffer_type); + add_type(symbols, glsl_type::image1DArray_type); + add_type(symbols, glsl_type::image2DArray_type); + add_type(symbols, glsl_type::imageCubeArray_type); + add_type(symbols, glsl_type::image2DMS_type); + add_type(symbols, glsl_type::image2DMSArray_type); + add_type(symbols, glsl_type::iimage1D_type); + add_type(symbols, glsl_type::iimage2D_type); + add_type(symbols, glsl_type::iimage3D_type); + add_type(symbols, glsl_type::iimage2DRect_type); + add_type(symbols, glsl_type::iimageCube_type); + add_type(symbols, glsl_type::iimageBuffer_type); + add_type(symbols, glsl_type::iimage1DArray_type); + add_type(symbols, glsl_type::iimage2DArray_type); + add_type(symbols, glsl_type::iimageCubeArray_type); + add_type(symbols, glsl_type::iimage2DMS_type); + add_type(symbols, glsl_type::iimage2DMSArray_type); + add_type(symbols, glsl_type::uimage1D_type); + add_type(symbols, glsl_type::uimage2D_type); + add_type(symbols, glsl_type::uimage3D_type); + add_type(symbols, glsl_type::uimage2DRect_type); + add_type(symbols, glsl_type::uimageCube_type); + add_type(symbols, glsl_type::uimageBuffer_type); + add_type(symbols, glsl_type::uimage1DArray_type); + add_type(symbols, glsl_type::uimage2DArray_type); + add_type(symbols, glsl_type::uimageCubeArray_type); + add_type(symbols, glsl_type::uimage2DMS_type); + add_type(symbols, glsl_type::uimage2DMSArray_type); + } + + if (state->ARB_shader_atomic_counters_enable) { + add_type(symbols, glsl_type::atomic_uint_type); + } } /** @} */ diff --git a/dist/Mesa/src/glsl/builtin_variables.cpp b/dist/Mesa/src/glsl/builtin_variables.cpp index 1e88b6a73..9b35850ee 100644 --- a/dist/Mesa/src/glsl/builtin_variables.cpp +++ b/dist/Mesa/src/glsl/builtin_variables.cpp @@ -30,18 +30,21 @@ #include "program/prog_statevars.h" #include "program/prog_instruction.h" +static const struct gl_builtin_uniform_element gl_NumSamples_elements[] = { + {NULL, {STATE_NUM_SAMPLES, 0, 0}, SWIZZLE_XXXX} +}; -static struct gl_builtin_uniform_element gl_DepthRange_elements[] = { +static const struct gl_builtin_uniform_element gl_DepthRange_elements[] = { {"near", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX}, {"far", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY}, {"diff", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ}, }; -static struct gl_builtin_uniform_element gl_ClipPlane_elements[] = { +static const struct gl_builtin_uniform_element gl_ClipPlane_elements[] = { {NULL, {STATE_CLIPPLANE, 0, 0}, SWIZZLE_XYZW} }; -static struct gl_builtin_uniform_element gl_Point_elements[] = { +static const struct gl_builtin_uniform_element gl_Point_elements[] = { {"size", {STATE_POINT_SIZE}, SWIZZLE_XXXX}, {"sizeMin", {STATE_POINT_SIZE}, SWIZZLE_YYYY}, {"sizeMax", {STATE_POINT_SIZE}, SWIZZLE_ZZZZ}, @@ -51,7 +54,7 @@ static struct gl_builtin_uniform_element gl_Point_elements[] = { {"distanceQuadraticAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ}, }; -static struct gl_builtin_uniform_element gl_FrontMaterial_elements[] = { +static const struct gl_builtin_uniform_element gl_FrontMaterial_elements[] = { {"emission", {STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW}, {"ambient", {STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW}, {"diffuse", {STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW}, @@ -59,7 +62,7 @@ static struct gl_builtin_uniform_element gl_FrontMaterial_elements[] = { {"shininess", {STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX}, }; -static struct gl_builtin_uniform_element gl_BackMaterial_elements[] = { +static const struct gl_builtin_uniform_element gl_BackMaterial_elements[] = { {"emission", {STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW}, {"ambient", {STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW}, {"diffuse", {STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW}, @@ -67,7 +70,7 @@ static struct gl_builtin_uniform_element gl_BackMaterial_elements[] = { {"shininess", {STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX}, }; -static struct gl_builtin_uniform_element gl_LightSource_elements[] = { +static const struct gl_builtin_uniform_element gl_LightSource_elements[] = { {"ambient", {STATE_LIGHT, 0, STATE_AMBIENT}, SWIZZLE_XYZW}, {"diffuse", {STATE_LIGHT, 0, STATE_DIFFUSE}, SWIZZLE_XYZW}, {"specular", {STATE_LIGHT, 0, STATE_SPECULAR}, SWIZZLE_XYZW}, @@ -86,67 +89,67 @@ static struct gl_builtin_uniform_element gl_LightSource_elements[] = { {"quadraticAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ}, }; -static struct gl_builtin_uniform_element gl_LightModel_elements[] = { +static const struct gl_builtin_uniform_element gl_LightModel_elements[] = { {"ambient", {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_FrontLightModelProduct_elements[] = { +static const struct gl_builtin_uniform_element gl_FrontLightModelProduct_elements[] = { {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_BackLightModelProduct_elements[] = { +static const struct gl_builtin_uniform_element gl_BackLightModelProduct_elements[] = { {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_FrontLightProduct_elements[] = { +static const struct gl_builtin_uniform_element gl_FrontLightProduct_elements[] = { {"ambient", {STATE_LIGHTPROD, 0, 0, STATE_AMBIENT}, SWIZZLE_XYZW}, {"diffuse", {STATE_LIGHTPROD, 0, 0, STATE_DIFFUSE}, SWIZZLE_XYZW}, {"specular", {STATE_LIGHTPROD, 0, 0, STATE_SPECULAR}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_BackLightProduct_elements[] = { +static const struct gl_builtin_uniform_element gl_BackLightProduct_elements[] = { {"ambient", {STATE_LIGHTPROD, 0, 1, STATE_AMBIENT}, SWIZZLE_XYZW}, {"diffuse", {STATE_LIGHTPROD, 0, 1, STATE_DIFFUSE}, SWIZZLE_XYZW}, {"specular", {STATE_LIGHTPROD, 0, 1, STATE_SPECULAR}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_TextureEnvColor_elements[] = { +static const struct gl_builtin_uniform_element gl_TextureEnvColor_elements[] = { {NULL, {STATE_TEXENV_COLOR, 0}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_EyePlaneS_elements[] = { +static const struct gl_builtin_uniform_element gl_EyePlaneS_elements[] = { {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_S}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_EyePlaneT_elements[] = { +static const struct gl_builtin_uniform_element gl_EyePlaneT_elements[] = { {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_T}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_EyePlaneR_elements[] = { +static const struct gl_builtin_uniform_element gl_EyePlaneR_elements[] = { {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_R}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_EyePlaneQ_elements[] = { +static const struct gl_builtin_uniform_element gl_EyePlaneQ_elements[] = { {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_Q}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_ObjectPlaneS_elements[] = { +static const struct gl_builtin_uniform_element gl_ObjectPlaneS_elements[] = { {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_S}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_ObjectPlaneT_elements[] = { +static const struct gl_builtin_uniform_element gl_ObjectPlaneT_elements[] = { {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_T}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_ObjectPlaneR_elements[] = { +static const struct gl_builtin_uniform_element gl_ObjectPlaneR_elements[] = { {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_R}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_ObjectPlaneQ_elements[] = { +static const struct gl_builtin_uniform_element gl_ObjectPlaneQ_elements[] = { {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_Q}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_Fog_elements[] = { +static const struct gl_builtin_uniform_element gl_Fog_elements[] = { {"color", {STATE_FOG_COLOR}, SWIZZLE_XYZW}, {"density", {STATE_FOG_PARAMS}, SWIZZLE_XXXX}, {"start", {STATE_FOG_PARAMS}, SWIZZLE_YYYY}, @@ -154,32 +157,32 @@ static struct gl_builtin_uniform_element gl_Fog_elements[] = { {"scale", {STATE_FOG_PARAMS}, SWIZZLE_WWWW}, }; -static struct gl_builtin_uniform_element gl_NormalScale_elements[] = { +static const struct gl_builtin_uniform_element gl_NormalScale_elements[] = { {NULL, {STATE_NORMAL_SCALE}, SWIZZLE_XXXX}, }; -static struct gl_builtin_uniform_element gl_BumpRotMatrix0MESA_elements[] = { +static const struct gl_builtin_uniform_element gl_BumpRotMatrix0MESA_elements[] = { {NULL, {STATE_INTERNAL, STATE_ROT_MATRIX_0}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_BumpRotMatrix1MESA_elements[] = { +static const struct gl_builtin_uniform_element gl_BumpRotMatrix1MESA_elements[] = { {NULL, {STATE_INTERNAL, STATE_ROT_MATRIX_1}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_FogParamsOptimizedMESA_elements[] = { +static const struct gl_builtin_uniform_element gl_FogParamsOptimizedMESA_elements[] = { {NULL, {STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_CurrentAttribVertMESA_elements[] = { +static const struct gl_builtin_uniform_element gl_CurrentAttribVertMESA_elements[] = { {NULL, {STATE_INTERNAL, STATE_CURRENT_ATTRIB, 0}, SWIZZLE_XYZW}, }; -static struct gl_builtin_uniform_element gl_CurrentAttribFragMESA_elements[] = { +static const struct gl_builtin_uniform_element gl_CurrentAttribFragMESA_elements[] = { {NULL, {STATE_INTERNAL, STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED, 0}, SWIZZLE_XYZW}, }; #define MATRIX(name, statevar, modifier) \ - static struct gl_builtin_uniform_element name ## _elements[] = { \ + static const struct gl_builtin_uniform_element name ## _elements[] = { \ { NULL, { statevar, 0, 0, 0, modifier}, SWIZZLE_XYZW }, \ { NULL, { statevar, 0, 1, 1, modifier}, SWIZZLE_XYZW }, \ { NULL, { statevar, 0, 2, 2, modifier}, SWIZZLE_XYZW }, \ @@ -222,7 +225,7 @@ MATRIX(gl_TextureMatrixTranspose, MATRIX(gl_TextureMatrixInverseTranspose, STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE); -static struct gl_builtin_uniform_element gl_NormalMatrix_elements[] = { +static const struct gl_builtin_uniform_element gl_NormalMatrix_elements[] = { { NULL, { STATE_MODELVIEW_MATRIX, 0, 0, 0, STATE_MATRIX_INVERSE}, MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z) }, { NULL, { STATE_MODELVIEW_MATRIX, 0, 1, 1, STATE_MATRIX_INVERSE}, @@ -236,6 +239,7 @@ static struct gl_builtin_uniform_element gl_NormalMatrix_elements[] = { #define STATEVAR(name) {#name, name ## _elements, Elements(name ## _elements)} static const struct gl_builtin_uniform_desc _mesa_builtin_uniform_desc[] = { + STATEVAR(gl_NumSamples), STATEVAR(gl_DepthRange), STATEVAR(gl_ClipPlane), STATEVAR(gl_Point), @@ -293,6 +297,55 @@ static const struct gl_builtin_uniform_desc _mesa_builtin_uniform_desc[] = { namespace { +/** + * Data structure that accumulates fields for the gl_PerVertex interface + * block. + */ +class per_vertex_accumulator +{ +public: + per_vertex_accumulator(); + void add_field(int slot, const glsl_type *type, const char *name); + const glsl_type *construct_interface_instance() const; + +private: + glsl_struct_field fields[10]; + unsigned num_fields; +}; + + +per_vertex_accumulator::per_vertex_accumulator() + : fields(), + num_fields(0) +{ +} + + +void +per_vertex_accumulator::add_field(int slot, const glsl_type *type, + const char *name) +{ + assert(this->num_fields < ARRAY_SIZE(this->fields)); + this->fields[this->num_fields].type = type; + this->fields[this->num_fields].name = name; + this->fields[this->num_fields].row_major = false; + this->fields[this->num_fields].location = slot; + this->fields[this->num_fields].interpolation = INTERP_QUALIFIER_NONE; + this->fields[this->num_fields].centroid = 0; + this->fields[this->num_fields].sample = 0; + this->num_fields++; +} + + +const glsl_type * +per_vertex_accumulator::construct_interface_instance() const +{ + return glsl_type::get_interface_instance(this->fields, this->num_fields, + GLSL_INTERFACE_PACKING_STD140, + "gl_PerVertex"); +} + + class builtin_variable_generator { public: @@ -303,6 +356,7 @@ public: void generate_vs_special_vars(); void generate_gs_special_vars(); void generate_fs_special_vars(); + void generate_cs_special_vars(); void generate_varyings(); private: @@ -336,6 +390,7 @@ private: enum ir_variable_mode mode, int slot); ir_variable *add_uniform(const glsl_type *type, const char *name); ir_variable *add_const(const char *name, int value); + ir_variable *add_const_ivec3(const char *name, int x, int y, int z); void add_varying(int slot, const glsl_type *type, const char *name, const char *name_as_gs_input); @@ -358,6 +413,9 @@ private: const glsl_type * const vec4_t; const glsl_type * const mat3_t; const glsl_type * const mat4_t; + + per_vertex_accumulator per_vertex_in; + per_vertex_accumulator per_vertex_out; }; @@ -379,13 +437,14 @@ builtin_variable_generator::add_variable(const char *name, enum ir_variable_mode mode, int slot) { ir_variable *var = new(symtab) ir_variable(type, name, mode); + var->data.how_declared = ir_var_declared_implicitly; - switch (var->mode) { + switch (var->data.mode) { case ir_var_auto: case ir_var_shader_in: case ir_var_uniform: case ir_var_system_value: - var->read_only = true; + var->data.read_only = true; break; case ir_var_shader_out: break; @@ -398,9 +457,9 @@ builtin_variable_generator::add_variable(const char *name, break; } - var->location = slot; - var->explicit_location = (slot >= 0); - var->explicit_index = 0; + var->data.location = slot; + var->data.explicit_location = (slot >= 0); + var->data.explicit_index = 0; /* Once the variable is created an initialized, add it to the symbol table * and add the declaration to the IR stream. @@ -439,7 +498,8 @@ builtin_variable_generator::add_uniform(const glsl_type *type, for (unsigned a = 0; a < array_count; a++) { for (unsigned j = 0; j < statevar->num_elements; j++) { - struct gl_builtin_uniform_element *element = &statevar->elements[j]; + const struct gl_builtin_uniform_element *element = + &statevar->elements[j]; memcpy(slots->tokens, element->tokens, sizeof(element->tokens)); if (type->is_array()) { @@ -467,7 +527,26 @@ builtin_variable_generator::add_const(const char *name, int value) ir_var_auto, -1); var->constant_value = new(var) ir_constant(value); var->constant_initializer = new(var) ir_constant(value); - var->has_initializer = true; + var->data.has_initializer = true; + return var; +} + + +ir_variable * +builtin_variable_generator::add_const_ivec3(const char *name, int x, int y, + int z) +{ + ir_variable *const var = add_variable(name, glsl_type::ivec3_type, + ir_var_auto, -1); + ir_constant_data data; + memset(&data, 0, sizeof(data)); + data.i[0] = x; + data.i[1] = y; + data.i[2] = z; + var->constant_value = new(var) ir_constant(glsl_type::ivec3_type, &data); + var->constant_initializer = + new(var) ir_constant(glsl_type::ivec3_type, &data); + var->data.has_initializer = true; return var; } @@ -497,11 +576,12 @@ builtin_variable_generator::generate_constants() */ if (state->is_version(0, 300)) { add_const("gl_MaxVertexOutputVectors", - state->Const.MaxVaryingFloats / 4); + state->ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents / 4); add_const("gl_MaxFragmentInputVectors", - state->Const.MaxVaryingFloats / 4); + state->ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxInputComponents / 4); } else { - add_const("gl_MaxVaryingVectors", state->Const.MaxVaryingFloats / 4); + add_const("gl_MaxVaryingVectors", + state->ctx->Const.MaxVarying); } } else { add_const("gl_MaxVertexUniformComponents", @@ -510,7 +590,7 @@ builtin_variable_generator::generate_constants() /* Note: gl_MaxVaryingFloats was deprecated in GLSL 1.30+, but not * removed */ - add_const("gl_MaxVaryingFloats", state->Const.MaxVaryingFloats); + add_const("gl_MaxVaryingFloats", state->ctx->Const.MaxVarying * 4); add_const("gl_MaxFragmentUniformComponents", state->Const.MaxFragmentUniformComponents); @@ -531,7 +611,38 @@ builtin_variable_generator::generate_constants() if (state->is_version(130, 0)) { add_const("gl_MaxClipDistances", state->Const.MaxClipPlanes); - add_const("gl_MaxVaryingComponents", state->Const.MaxVaryingFloats); + add_const("gl_MaxVaryingComponents", state->ctx->Const.MaxVarying * 4); + } + + if (state->is_version(150, 0)) { + add_const("gl_MaxVertexOutputComponents", + state->Const.MaxVertexOutputComponents); + add_const("gl_MaxGeometryInputComponents", + state->Const.MaxGeometryInputComponents); + add_const("gl_MaxGeometryOutputComponents", + state->Const.MaxGeometryOutputComponents); + add_const("gl_MaxFragmentInputComponents", + state->Const.MaxFragmentInputComponents); + add_const("gl_MaxGeometryTextureImageUnits", + state->Const.MaxGeometryTextureImageUnits); + add_const("gl_MaxGeometryOutputVertices", + state->Const.MaxGeometryOutputVertices); + add_const("gl_MaxGeometryTotalOutputComponents", + state->Const.MaxGeometryTotalOutputComponents); + add_const("gl_MaxGeometryUniformComponents", + state->Const.MaxGeometryUniformComponents); + + /* Note: the GLSL 1.50-4.40 specs require + * gl_MaxGeometryVaryingComponents to be present, and to be at least 64. + * But they do not define what it means (and there does not appear to be + * any corresponding constant in the GL specs). However, + * ARB_geometry_shader4 defines MAX_GEOMETRY_VARYING_COMPONENTS_ARB to + * be the maximum number of components available for use as geometry + * outputs. So we assume this is a synonym for + * gl_MaxGeometryOutputComponents. + */ + add_const("gl_MaxGeometryVaryingComponents", + state->Const.MaxGeometryOutputComponents); } if (compatibility) { @@ -555,6 +666,72 @@ builtin_variable_generator::generate_constants() */ add_const("gl_MaxTextureCoords", state->Const.MaxTextureCoords); } + + if (state->ARB_shader_atomic_counters_enable) { + add_const("gl_MaxVertexAtomicCounters", + state->Const.MaxVertexAtomicCounters); + add_const("gl_MaxGeometryAtomicCounters", + state->Const.MaxGeometryAtomicCounters); + add_const("gl_MaxFragmentAtomicCounters", + state->Const.MaxFragmentAtomicCounters); + add_const("gl_MaxCombinedAtomicCounters", + state->Const.MaxCombinedAtomicCounters); + add_const("gl_MaxAtomicCounterBindings", + state->Const.MaxAtomicBufferBindings); + add_const("gl_MaxTessControlAtomicCounters", 0); + add_const("gl_MaxTessEvaluationAtomicCounters", 0); + } + + if (state->is_version(430, 0) || state->ARB_compute_shader_enable) { + add_const_ivec3("gl_MaxComputeWorkGroupCount", + state->Const.MaxComputeWorkGroupCount[0], + state->Const.MaxComputeWorkGroupCount[1], + state->Const.MaxComputeWorkGroupCount[2]); + add_const_ivec3("gl_MaxComputeWorkGroupSize", + state->Const.MaxComputeWorkGroupSize[0], + state->Const.MaxComputeWorkGroupSize[1], + state->Const.MaxComputeWorkGroupSize[2]); + + /* From the GLSL 4.40 spec, section 7.1 (Built-In Language Variables): + * + * The built-in constant gl_WorkGroupSize is a compute-shader + * constant containing the local work-group size of the shader. The + * size of the work group in the X, Y, and Z dimensions is stored in + * the x, y, and z components. The constants values in + * gl_WorkGroupSize will match those specified in the required + * local_size_x, local_size_y, and local_size_z layout qualifiers + * for the current shader. This is a constant so that it can be + * used to size arrays of memory that can be shared within the local + * work group. It is a compile-time error to use gl_WorkGroupSize + * in a shader that does not declare a fixed local group size, or + * before that shader has declared a fixed local group size, using + * local_size_x, local_size_y, and local_size_z. + * + * To prevent the shader from trying to refer to gl_WorkGroupSize before + * the layout declaration, we don't define it here. Intead we define it + * in ast_cs_input_layout::hir(). + */ + } + + if (state->is_version(420, 0) || + state->ARB_shader_image_load_store_enable) { + add_const("gl_MaxImageUnits", + state->Const.MaxImageUnits); + add_const("gl_MaxCombinedImageUnitsAndFragmentOutputs", + state->Const.MaxCombinedImageUnitsAndFragmentOutputs); + add_const("gl_MaxImageSamples", + state->Const.MaxImageSamples); + add_const("gl_MaxVertexImageUniforms", + state->Const.MaxVertexImageUniforms); + add_const("gl_MaxTessControlImageUniforms", 0); + add_const("gl_MaxTessEvaluationImageUniforms", 0); + add_const("gl_MaxGeometryImageUniforms", + state->Const.MaxGeometryImageUniforms); + add_const("gl_MaxFragmentImageUniforms", + state->Const.MaxFragmentImageUniforms); + add_const("gl_MaxCombinedImageUniforms", + state->Const.MaxCombinedImageUniforms); + } } @@ -564,6 +741,7 @@ builtin_variable_generator::generate_constants() void builtin_variable_generator::generate_uniforms() { + add_uniform(int_t, "gl_NumSamples"); add_uniform(type("gl_DepthRangeParameters"), "gl_DepthRange"); add_uniform(array(vec4_t, VERT_ATTRIB_MAX), "gl_CurrentAttribVertMESA"); add_uniform(array(vec4_t, VARYING_SLOT_MAX), "gl_CurrentAttribFragMESA"); @@ -675,6 +853,10 @@ void builtin_variable_generator::generate_gs_special_vars() { add_output(VARYING_SLOT_LAYER, int_t, "gl_Layer"); + if (state->ARB_viewport_array_enable) + add_output(VARYING_SLOT_VIEWPORT, int_t, "gl_ViewportIndex"); + if (state->ARB_gpu_shader5_enable) + add_system_value(SYSTEM_VALUE_INVOCATION_ID, int_t, "gl_InvocationID"); /* Although gl_PrimitiveID appears in tessellation control and tessellation * evaluation shaders, it has a different function there than it has in @@ -686,8 +868,11 @@ builtin_variable_generator::generate_gs_special_vars() * the specific case of gl_PrimitiveIDIn. So we don't need to treat * gl_PrimitiveIDIn as an {ARB,EXT}_geometry_shader4-only variable. */ - add_input(VARYING_SLOT_PRIMITIVE_ID, int_t, "gl_PrimitiveIDIn"); - add_output(VARYING_SLOT_PRIMITIVE_ID, int_t, "gl_PrimitiveID"); + ir_variable *var; + var = add_input(VARYING_SLOT_PRIMITIVE_ID, int_t, "gl_PrimitiveIDIn"); + var->data.interpolation = INTERP_QUALIFIER_FLAT; + var = add_output(VARYING_SLOT_PRIMITIVE_ID, int_t, "gl_PrimitiveID"); + var->data.interpolation = INTERP_QUALIFIER_FLAT; } @@ -702,6 +887,12 @@ builtin_variable_generator::generate_fs_special_vars() if (state->is_version(120, 100)) add_input(VARYING_SLOT_PNTC, vec2_t, "gl_PointCoord"); + if (state->is_version(150, 0)) { + ir_variable *var = + add_input(VARYING_SLOT_PRIMITIVE_ID, int_t, "gl_PrimitiveID"); + var->data.interpolation = INTERP_QUALIFIER_FLAT; + } + /* gl_FragColor and gl_FragData were deprecated starting in desktop GLSL * 1.30, and were relegated to the compatibility profile in GLSL 4.20. * They were removed from GLSL ES 3.00. @@ -731,6 +922,33 @@ builtin_variable_generator::generate_fs_special_vars() if (state->AMD_shader_stencil_export_warn) var->warn_extension = "GL_AMD_shader_stencil_export"; } + + if (state->ARB_sample_shading_enable) { + add_system_value(SYSTEM_VALUE_SAMPLE_ID, int_t, "gl_SampleID"); + add_system_value(SYSTEM_VALUE_SAMPLE_POS, vec2_t, "gl_SamplePosition"); + /* From the ARB_sample_shading specification: + * "The number of elements in the array is ceil(<s>/32), where + * <s> is the maximum number of color samples supported by the + * implementation." + * Since no drivers expose more than 32x MSAA, we can simply set + * the array size to 1 rather than computing it. + */ + add_output(FRAG_RESULT_SAMPLE_MASK, array(int_t, 1), "gl_SampleMask"); + } + + if (state->ARB_gpu_shader5_enable) { + add_system_value(SYSTEM_VALUE_SAMPLE_MASK_IN, array(int_t, 1), "gl_SampleMaskIn"); + } +} + + +/** + * Generate variables which only exist in compute shaders. + */ +void +builtin_variable_generator::generate_cs_special_vars() +{ + /* TODO: finish this. */ } @@ -745,16 +963,19 @@ builtin_variable_generator::add_varying(int slot, const glsl_type *type, const char *name, const char *name_as_gs_input) { - switch (state->target) { - case geometry_shader: - add_input(slot, array(type, 0), name_as_gs_input); + switch (state->stage) { + case MESA_SHADER_GEOMETRY: + this->per_vertex_in.add_field(slot, type, name); /* FALLTHROUGH */ - case vertex_shader: - add_output(slot, type, name); + case MESA_SHADER_VERTEX: + this->per_vertex_out.add_field(slot, type, name); break; - case fragment_shader: + case MESA_SHADER_FRAGMENT: add_input(slot, type, name); break; + case MESA_SHADER_COMPUTE: + /* Compute shaders don't have varyings. */ + break; } } @@ -770,7 +991,7 @@ builtin_variable_generator::generate_varyings() add_varying(loc, type, name, name "In") /* gl_Position and gl_PointSize are not visible from fragment shaders. */ - if (state->target != fragment_shader) { + if (state->stage != MESA_SHADER_FRAGMENT) { ADD_VARYING(VARYING_SLOT_POS, vec4_t, "gl_Position"); ADD_VARYING(VARYING_SLOT_PSIZ, float_t, "gl_PointSize"); } @@ -783,7 +1004,7 @@ builtin_variable_generator::generate_varyings() if (compatibility) { ADD_VARYING(VARYING_SLOT_TEX0, array(vec4_t, 0), "gl_TexCoord"); ADD_VARYING(VARYING_SLOT_FOGC, float_t, "gl_FogFragCoord"); - if (state->target == fragment_shader) { + if (state->stage == MESA_SHADER_FRAGMENT) { ADD_VARYING(VARYING_SLOT_COL0, vec4_t, "gl_Color"); ADD_VARYING(VARYING_SLOT_COL1, vec4_t, "gl_SecondaryColor"); } else { @@ -794,6 +1015,27 @@ builtin_variable_generator::generate_varyings() ADD_VARYING(VARYING_SLOT_BFC1, vec4_t, "gl_BackSecondaryColor"); } } + + if (state->stage == MESA_SHADER_GEOMETRY) { + const glsl_type *per_vertex_in_type = + this->per_vertex_in.construct_interface_instance(); + add_variable("gl_in", array(per_vertex_in_type, 0), + ir_var_shader_in, -1); + } + if (state->stage == MESA_SHADER_VERTEX || state->stage == MESA_SHADER_GEOMETRY) { + const glsl_type *per_vertex_out_type = + this->per_vertex_out.construct_interface_instance(); + const glsl_struct_field *fields = per_vertex_out_type->fields.structure; + for (unsigned i = 0; i < per_vertex_out_type->length; i++) { + ir_variable *var = + add_variable(fields[i].name, fields[i].type, ir_var_shader_out, + fields[i].location); + var->data.interpolation = fields[i].interpolation; + var->data.centroid = fields[i].centroid; + var->data.sample = fields[i].sample; + var->init_interface_type(per_vertex_out_type); + } + } } @@ -811,15 +1053,18 @@ _mesa_glsl_initialize_variables(exec_list *instructions, gen.generate_varyings(); - switch (state->target) { - case vertex_shader: + switch (state->stage) { + case MESA_SHADER_VERTEX: gen.generate_vs_special_vars(); break; - case geometry_shader: + case MESA_SHADER_GEOMETRY: gen.generate_gs_special_vars(); break; - case fragment_shader: + case MESA_SHADER_FRAGMENT: gen.generate_fs_special_vars(); break; + case MESA_SHADER_COMPUTE: + gen.generate_cs_special_vars(); + break; } } diff --git a/dist/Mesa/src/glsl/glcpp/glcpp.h b/dist/Mesa/src/glsl/glcpp/glcpp.h index 8aaa551d1..79ccb234f 100644 --- a/dist/Mesa/src/glsl/glcpp/glcpp.h +++ b/dist/Mesa/src/glsl/glcpp/glcpp.h @@ -153,6 +153,7 @@ typedef enum skip_type { typedef struct skip_node { skip_type_t type; + bool has_else; YYLTYPE loc; /* location of the initial #if/#elif/... */ struct skip_node *next; } skip_node_t; @@ -172,6 +173,7 @@ struct glcpp_parser { int newline_as_space; int in_control_line; int paren_count; + int commented_newlines; skip_node_t *skip_stack; token_list_t *lex_from_list; token_node_t *lex_from_node; @@ -180,6 +182,9 @@ struct glcpp_parser { size_t output_length; size_t info_log_length; int error; + const struct gl_extensions *extensions; + gl_api api; + bool version_resolved; bool has_new_line_number; int new_line_number; bool has_new_source_number; @@ -190,7 +195,7 @@ struct glcpp_parser { struct gl_extensions; glcpp_parser_t * -glcpp_parser_create (const struct gl_extensions *extensions, int api); +glcpp_parser_create (const struct gl_extensions *extensions, gl_api api); int glcpp_parser_parse (glcpp_parser_t *parser); @@ -198,6 +203,9 @@ glcpp_parser_parse (glcpp_parser_t *parser); void glcpp_parser_destroy (glcpp_parser_t *parser); +void +glcpp_parser_resolve_implicit_version(glcpp_parser_t *parser); + int glcpp_preprocess(void *ralloc_ctx, const char **shader, char **info_log, const struct gl_extensions *extensions, struct gl_context *g_ctx); diff --git a/dist/Mesa/src/glsl/glcpp/pp.c b/dist/Mesa/src/glsl/glcpp/pp.c index 7e1b6c689..4a623f81e 100644 --- a/dist/Mesa/src/glsl/glcpp/pp.c +++ b/dist/Mesa/src/glsl/glcpp/pp.c @@ -151,6 +151,8 @@ glcpp_preprocess(void *ralloc_ctx, const char **shader, char **info_log, if (parser->skip_stack) glcpp_error (&parser->skip_stack->loc, parser, "Unterminated #if\n"); + glcpp_parser_resolve_implicit_version(parser); + ralloc_strcat(info_log, parser->info_log); ralloc_steal(ralloc_ctx, parser->output); diff --git a/dist/Mesa/src/glsl/glcpp/tests/000-content-with-spaces.c b/dist/Mesa/src/glsl/glcpp/tests/000-content-with-spaces.c index 696cb3a74..1f2320e6f 100644 --- a/dist/Mesa/src/glsl/glcpp/tests/000-content-with-spaces.c +++ b/dist/Mesa/src/glsl/glcpp/tests/000-content-with-spaces.c @@ -1 +1 @@ -this is four tokens + this is four tokens with spaces diff --git a/dist/Mesa/src/glsl/glcpp/tests/000-content-with-spaces.c.expected b/dist/Mesa/src/glsl/glcpp/tests/000-content-with-spaces.c.expected index 83f7834d5..5e17ec910 100644 --- a/dist/Mesa/src/glsl/glcpp/tests/000-content-with-spaces.c.expected +++ b/dist/Mesa/src/glsl/glcpp/tests/000-content-with-spaces.c.expected @@ -1,2 +1,2 @@ -this is four tokens + this is four tokens with spaces diff --git a/dist/Mesa/src/glsl/glcpp/tests/100-macro-with-colon.c.expected b/dist/Mesa/src/glsl/glcpp/tests/100-macro-with-colon.c.expected index 6cfac257b..36f98aa3e 100644 --- a/dist/Mesa/src/glsl/glcpp/tests/100-macro-with-colon.c.expected +++ b/dist/Mesa/src/glsl/glcpp/tests/100-macro-with-colon.c.expected @@ -2,7 +2,7 @@ switch (1) { - case 1 + 2: - break; + case 1 + 2: + break; } diff --git a/dist/Mesa/src/glsl/glcpp/tests/117-line-continuation-and-non-continuation-backslash.c.expected b/dist/Mesa/src/glsl/glcpp/tests/117-line-continuation-and-non-continuation-backslash.c.expected index 9b3eb676f..292d6516f 100644 --- a/dist/Mesa/src/glsl/glcpp/tests/117-line-continuation-and-non-continuation-backslash.c.expected +++ b/dist/Mesa/src/glsl/glcpp/tests/117-line-continuation-and-non-continuation-backslash.c.expected @@ -1,3 +1,4 @@ + @@ -6,7 +7,6 @@ - diff --git a/dist/Mesa/src/glsl/glcpp/tests/118-comment-becomes-space.c b/dist/Mesa/src/glsl/glcpp/tests/118-comment-becomes-space.c new file mode 100644 index 000000000..53e80394a --- /dev/null +++ b/dist/Mesa/src/glsl/glcpp/tests/118-comment-becomes-space.c @@ -0,0 +1,4 @@ +#define FOO first/* +*/second + +FOO diff --git a/dist/Mesa/src/glsl/glcpp/tests/118-comment-becomes-space.c.expected b/dist/Mesa/src/glsl/glcpp/tests/118-comment-becomes-space.c.expected new file mode 100644 index 000000000..2adf5d1ba --- /dev/null +++ b/dist/Mesa/src/glsl/glcpp/tests/118-comment-becomes-space.c.expected @@ -0,0 +1,5 @@ + + + +first second + diff --git a/dist/Mesa/src/glsl/glcpp/tests/118-multiple-else.c b/dist/Mesa/src/glsl/glcpp/tests/118-multiple-else.c new file mode 100644 index 000000000..62ad49cf7 --- /dev/null +++ b/dist/Mesa/src/glsl/glcpp/tests/118-multiple-else.c @@ -0,0 +1,6 @@ +#if 0 +#else +int foo; +#else +int bar; +#endif diff --git a/dist/Mesa/src/glsl/glcpp/tests/118-multiple-else.c.expected b/dist/Mesa/src/glsl/glcpp/tests/118-multiple-else.c.expected new file mode 100644 index 000000000..eaec48150 --- /dev/null +++ b/dist/Mesa/src/glsl/glcpp/tests/118-multiple-else.c.expected @@ -0,0 +1,8 @@ +0:4(1): preprocessor error: multiple #else + + +int foo; + +int bar; + + diff --git a/dist/Mesa/src/glsl/glcpp/tests/119-elif-after-else.c b/dist/Mesa/src/glsl/glcpp/tests/119-elif-after-else.c new file mode 100644 index 000000000..9b9e9233b --- /dev/null +++ b/dist/Mesa/src/glsl/glcpp/tests/119-elif-after-else.c @@ -0,0 +1,6 @@ +#if 0 +#else +int foo; +#elif 0 +int bar; +#endif diff --git a/dist/Mesa/src/glsl/glcpp/tests/119-elif-after-else.c.expected b/dist/Mesa/src/glsl/glcpp/tests/119-elif-after-else.c.expected new file mode 100644 index 000000000..33f051361 --- /dev/null +++ b/dist/Mesa/src/glsl/glcpp/tests/119-elif-after-else.c.expected @@ -0,0 +1,8 @@ +0:4(1): preprocessor error: #elif after #else + + +int foo; + +int bar; + + diff --git a/dist/Mesa/src/glsl/glcpp/tests/121-comment-bug-72686.c b/dist/Mesa/src/glsl/glcpp/tests/121-comment-bug-72686.c new file mode 100644 index 000000000..67ebe73e5 --- /dev/null +++ b/dist/Mesa/src/glsl/glcpp/tests/121-comment-bug-72686.c @@ -0,0 +1,2 @@ +/* + */ // diff --git a/dist/Mesa/src/glsl/glcpp/tests/121-comment-bug-72686.c.expected b/dist/Mesa/src/glsl/glcpp/tests/121-comment-bug-72686.c.expected new file mode 100644 index 000000000..402a76381 --- /dev/null +++ b/dist/Mesa/src/glsl/glcpp/tests/121-comment-bug-72686.c.expected @@ -0,0 +1,3 @@ + + + diff --git a/dist/Mesa/src/glsl/glsl_symbol_table.h b/dist/Mesa/src/glsl/glsl_symbol_table.h index 62d26b89a..f323fc305 100644 --- a/dist/Mesa/src/glsl/glsl_symbol_table.h +++ b/dist/Mesa/src/glsl/glsl_symbol_table.h @@ -98,7 +98,6 @@ public: /*@{*/ bool add_variable(ir_variable *v); bool add_type(const char *name, const glsl_type *t); - bool add_type_ast(const char *name, const class ast_type_specifier *t); bool add_function(ir_function *f); bool add_interface(const char *name, const glsl_type *i, enum ir_variable_mode mode); @@ -115,12 +114,19 @@ public: /*@{*/ ir_variable *get_variable(const char *name); const glsl_type *get_type(const char *name); - const class ast_type_specifier *get_type_ast(const char *name); ir_function *get_function(const char *name); const glsl_type *get_interface(const char *name, enum ir_variable_mode mode); /*@}*/ + /** + * Disable a previously-added variable so that it no longer appears to be + * in the symbol table. This is necessary when gl_PerVertex is redeclared, + * to ensure that previously-available built-in variables are no longer + * available. + */ + void disable_variable(const char *name); + private: symbol_table_entry *get_entry(const char *name); diff --git a/dist/Mesa/src/glsl/hir_field_selection.cpp b/dist/Mesa/src/glsl/hir_field_selection.cpp index ceb0a4cdb..1e92c89ae 100644 --- a/dist/Mesa/src/glsl/hir_field_selection.cpp +++ b/dist/Mesa/src/glsl/hir_field_selection.cpp @@ -53,13 +53,13 @@ _mesa_ast_field_selection_to_hir(const ast_expression *expr, expr->primary_expression.identifier); if (result->type->is_error()) { - _mesa_glsl_error(& loc, state, "Cannot access field `%s' of " + _mesa_glsl_error(& loc, state, "cannot access field `%s' of " "structure", expr->primary_expression.identifier); } } else if (expr->subexpressions[1] != NULL) { /* Handle "method calls" in GLSL 1.20 - namely, array.length() */ - state->check_version(120, 300, &loc, "Methods not supported"); + state->check_version(120, 300, &loc, "methods not supported"); ast_expression *call = expr->subexpressions[1]; assert(call->oper == ast_function_call); @@ -69,11 +69,11 @@ _mesa_ast_field_selection_to_hir(const ast_expression *expr, if (strcmp(method, "length") == 0) { if (!call->expressions.is_empty()) - _mesa_glsl_error(&loc, state, "length method takes no arguments."); + _mesa_glsl_error(&loc, state, "length method takes no arguments"); if (op->type->is_array()) { - if (op->type->array_size() == 0) - _mesa_glsl_error(&loc, state, "length called on unsized array."); + if (op->type->is_unsized_array()) + _mesa_glsl_error(&loc, state, "length called on unsized array"); result = new(ctx) ir_constant(op->type->array_size()); } else if (op->type->is_vector()) { @@ -82,7 +82,7 @@ _mesa_ast_field_selection_to_hir(const ast_expression *expr, result = new(ctx) ir_constant((int) op->type->vector_elements); } else { _mesa_glsl_error(&loc, state, "length method on matrix only available" - "with ARB_shading_language_420pack."); + "with ARB_shading_language_420pack"); } } else if (op->type->is_matrix()) { if (state->ARB_shading_language_420pack_enable) { @@ -90,11 +90,11 @@ _mesa_ast_field_selection_to_hir(const ast_expression *expr, result = new(ctx) ir_constant((int) op->type->matrix_columns); } else { _mesa_glsl_error(&loc, state, "length method on matrix only available" - "with ARB_shading_language_420pack."); + "with ARB_shading_language_420pack"); } } } else { - _mesa_glsl_error(&loc, state, "Unknown method: `%s'.", method); + _mesa_glsl_error(&loc, state, "unknown method: `%s'", method); } } else if (op->type->is_vector() || (state->ARB_shading_language_420pack_enable && @@ -109,12 +109,12 @@ _mesa_ast_field_selection_to_hir(const ast_expression *expr, * FINISHME: ir_swizzle::create. This allows the generation of more * FINISHME: specific error messages. */ - _mesa_glsl_error(& loc, state, "Invalid swizzle / mask `%s'", + _mesa_glsl_error(& loc, state, "invalid swizzle / mask `%s'", expr->primary_expression.identifier); } } else { - _mesa_glsl_error(& loc, state, "Cannot access field `%s' of " - "non-structure / non-vector.", + _mesa_glsl_error(& loc, state, "cannot access field `%s' of " + "non-structure / non-vector", expr->primary_expression.identifier); } diff --git a/dist/Mesa/src/glsl/ir_basic_block.cpp b/dist/Mesa/src/glsl/ir_basic_block.cpp index 2cbc682d4..426fda2f2 100644 --- a/dist/Mesa/src/glsl/ir_basic_block.cpp +++ b/dist/Mesa/src/glsl/ir_basic_block.cpp @@ -58,8 +58,8 @@ void call_for_basic_blocks(exec_list *instructions, ir_instruction *leader = NULL; ir_instruction *last = NULL; - foreach_iter(exec_list_iterator, iter, *instructions) { - ir_instruction *ir = (ir_instruction *)iter.get(); + foreach_list(n, instructions) { + ir_instruction *ir = (ir_instruction *) n; ir_if *ir_if; ir_loop *ir_loop; ir_function *ir_function; @@ -90,10 +90,8 @@ void call_for_basic_blocks(exec_list *instructions, * and the body of main(). Perhaps those instructions ought * to live inside of main(). */ - foreach_iter(exec_list_iterator, fun_iter, *ir_function) { - ir_function_signature *ir_sig; - - ir_sig = (ir_function_signature *)fun_iter.get(); + foreach_list(func_node, &ir_function->signatures) { + ir_function_signature *ir_sig = (ir_function_signature *) func_node; call_for_basic_blocks(&ir_sig->body, callback, data); } diff --git a/dist/Mesa/src/glsl/ir_builder.cpp b/dist/Mesa/src/glsl/ir_builder.cpp index 8fb30a02a..f4a1c6efa 100644 --- a/dist/Mesa/src/glsl/ir_builder.cpp +++ b/dist/Mesa/src/glsl/ir_builder.cpp @@ -46,13 +46,14 @@ ir_factory::make_temp(const glsl_type *type, const char *name) } ir_assignment * -assign(deref lhs, operand rhs, int writemask) +assign(deref lhs, operand rhs, operand condition, int writemask) { void *mem_ctx = ralloc_parent(lhs.val); ir_assignment *assign = new(mem_ctx) ir_assignment(lhs.val, rhs.val, - NULL, writemask); + condition.val, + writemask); return assign; } @@ -63,6 +64,25 @@ assign(deref lhs, operand rhs) return assign(lhs, rhs, (1 << lhs.val->type->vector_elements) - 1); } +ir_assignment * +assign(deref lhs, operand rhs, int writemask) +{ + return assign(lhs, rhs, (ir_rvalue *) NULL, writemask); +} + +ir_assignment * +assign(deref lhs, operand rhs, operand condition) +{ + return assign(lhs, rhs, condition, (1 << lhs.val->type->vector_elements) - 1); +} + +ir_return * +ret(operand retval) +{ + void *mem_ctx = ralloc_parent(retval.val); + return new(mem_ctx) ir_return(retval.val); +} + ir_swizzle * swizzle(operand a, int swizzle, int components) { @@ -173,6 +193,14 @@ expr(ir_expression_operation op, operand a, operand b) return new(mem_ctx) ir_expression(op, a.val, b.val); } +ir_expression * +expr(ir_expression_operation op, operand a, operand b, operand c) +{ + void *mem_ctx = ralloc_parent(a.val); + + return new(mem_ctx) ir_expression(op, a.val, b.val, c.val); +} + ir_expression *add(operand a, operand b) { return expr(ir_binop_add, a, b); @@ -183,23 +211,54 @@ ir_expression *sub(operand a, operand b) return expr(ir_binop_sub, a, b); } +ir_expression *min2(operand a, operand b) +{ + return expr(ir_binop_min, a, b); +} + +ir_expression *max2(operand a, operand b) +{ + return expr(ir_binop_max, a, b); +} + ir_expression *mul(operand a, operand b) { return expr(ir_binop_mul, a, b); } +ir_expression *imul_high(operand a, operand b) +{ + return expr(ir_binop_imul_high, a, b); +} + ir_expression *div(operand a, operand b) { return expr(ir_binop_div, a, b); } +ir_expression *carry(operand a, operand b) +{ + return expr(ir_binop_carry, a, b); +} + +ir_expression *borrow(operand a, operand b) +{ + return expr(ir_binop_borrow, a, b); +} + ir_expression *round_even(operand a) { return expr(ir_unop_round_even, a); } +/* dot for vectors, mul for scalars */ ir_expression *dot(operand a, operand b) { + assert(a.val->type == b.val->type); + + if (a.val->type->vector_elements == 1) + return expr(ir_binop_mul, a, b); + return expr(ir_binop_dot, a, b); } @@ -219,6 +278,60 @@ saturate(operand a) new(mem_ctx) ir_constant(0.0f)); } +ir_expression * +abs(operand a) +{ + return expr(ir_unop_abs, a); +} + +ir_expression * +neg(operand a) +{ + return expr(ir_unop_neg, a); +} + +ir_expression * +sin(operand a) +{ + return expr(ir_unop_sin, a); +} + +ir_expression * +cos(operand a) +{ + return expr(ir_unop_cos, a); +} + +ir_expression * +exp(operand a) +{ + return expr(ir_unop_exp, a); +} + +ir_expression * +rsq(operand a) +{ + return expr(ir_unop_rsq, a); +} + +ir_expression * +sqrt(operand a) +{ + return expr(ir_unop_sqrt, a); +} + +ir_expression * +log(operand a) +{ + return expr(ir_unop_log, a); +} + +ir_expression * +sign(operand a) +{ + return expr(ir_unop_sign, a); +} + ir_expression* equal(operand a, operand b) { @@ -226,6 +339,12 @@ equal(operand a, operand b) } ir_expression* +nequal(operand a, operand b) +{ + return expr(ir_binop_nequal, a, b); +} + +ir_expression* less(operand a, operand b) { return expr(ir_binop_less, a, b); @@ -304,12 +423,24 @@ f2i(operand a) } ir_expression* +bitcast_f2i(operand a) +{ + return expr(ir_unop_bitcast_f2i, a); +} + +ir_expression* i2f(operand a) { return expr(ir_unop_i2f, a); } ir_expression* +bitcast_i2f(operand a) +{ + return expr(ir_unop_bitcast_i2f, a); +} + +ir_expression* i2u(operand a) { return expr(ir_unop_i2u, a); @@ -328,11 +459,73 @@ f2u(operand a) } ir_expression* +bitcast_f2u(operand a) +{ + return expr(ir_unop_bitcast_f2u, a); +} + +ir_expression* u2f(operand a) { return expr(ir_unop_u2f, a); } +ir_expression* +bitcast_u2f(operand a) +{ + return expr(ir_unop_bitcast_u2f, a); +} + +ir_expression* +i2b(operand a) +{ + return expr(ir_unop_i2b, a); +} + +ir_expression* +b2i(operand a) +{ + return expr(ir_unop_b2i, a); +} + +ir_expression * +f2b(operand a) +{ + return expr(ir_unop_f2b, a); +} + +ir_expression * +b2f(operand a) +{ + return expr(ir_unop_b2f, a); +} + +ir_expression * +fma(operand a, operand b, operand c) +{ + return expr(ir_triop_fma, a, b, c); +} + +ir_expression * +lrp(operand x, operand y, operand a) +{ + return expr(ir_triop_lrp, x, y, a); +} + +ir_expression * +csel(operand a, operand b, operand c) +{ + return expr(ir_triop_csel, a, b, c); +} + +ir_expression * +bitfield_insert(operand a, operand b, operand c, operand d) +{ + void *mem_ctx = ralloc_parent(a.val); + return new(mem_ctx) ir_expression(ir_quadop_bitfield_insert, + a.val->type, a.val, b.val, c.val, d.val); +} + ir_if* if_tree(operand condition, ir_instruction *then_branch) diff --git a/dist/Mesa/src/glsl/ir_builder.h b/dist/Mesa/src/glsl/ir_builder.h index 690ac74eb..108b53a5e 100644 --- a/dist/Mesa/src/glsl/ir_builder.h +++ b/dist/Mesa/src/glsl/ir_builder.h @@ -82,9 +82,9 @@ public: class ir_factory { public: - ir_factory() - : instructions(NULL), - mem_ctx(NULL) + ir_factory(exec_list *instructions = NULL, void *mem_ctx = NULL) + : instructions(instructions), + mem_ctx(mem_ctx) { return; } @@ -122,19 +122,37 @@ public: ir_assignment *assign(deref lhs, operand rhs); ir_assignment *assign(deref lhs, operand rhs, int writemask); +ir_assignment *assign(deref lhs, operand rhs, operand condition); +ir_assignment *assign(deref lhs, operand rhs, operand condition, int writemask); + +ir_return *ret(operand retval); ir_expression *expr(ir_expression_operation op, operand a); ir_expression *expr(ir_expression_operation op, operand a, operand b); +ir_expression *expr(ir_expression_operation op, operand a, operand b, operand c); ir_expression *add(operand a, operand b); ir_expression *sub(operand a, operand b); ir_expression *mul(operand a, operand b); +ir_expression *imul_high(operand a, operand b); ir_expression *div(operand a, operand b); +ir_expression *carry(operand a, operand b); +ir_expression *borrow(operand a, operand b); ir_expression *round_even(operand a); ir_expression *dot(operand a, operand b); ir_expression *clamp(operand a, operand b, operand c); ir_expression *saturate(operand a); +ir_expression *abs(operand a); +ir_expression *neg(operand a); +ir_expression *sin(operand a); +ir_expression *cos(operand a); +ir_expression *exp(operand a); +ir_expression *rsq(operand a); +ir_expression *sqrt(operand a); +ir_expression *log(operand a); +ir_expression *sign(operand a); ir_expression *equal(operand a, operand b); +ir_expression *nequal(operand a, operand b); ir_expression *less(operand a, operand b); ir_expression *greater(operand a, operand b); ir_expression *lequal(operand a, operand b); @@ -151,12 +169,29 @@ ir_expression *lshift(operand a, operand b); ir_expression *rshift(operand a, operand b); ir_expression *f2i(operand a); +ir_expression *bitcast_f2i(operand a); ir_expression *i2f(operand a); +ir_expression *bitcast_i2f(operand a); ir_expression *f2u(operand a); +ir_expression *bitcast_f2u(operand a); ir_expression *u2f(operand a); +ir_expression *bitcast_u2f(operand a); ir_expression *i2u(operand a); ir_expression *u2i(operand a); +ir_expression *b2i(operand a); +ir_expression *i2b(operand a); +ir_expression *f2b(operand a); +ir_expression *b2f(operand a); + +ir_expression *min2(operand a, operand b); +ir_expression *max2(operand a, operand b); + +ir_expression *fma(operand a, operand b, operand c); +ir_expression *lrp(operand x, operand y, operand a); +ir_expression *csel(operand a, operand b, operand c); +ir_expression *bitfield_insert(operand a, operand b, operand c, operand d); +ir_swizzle *swizzle(operand a, int swizzle, int components); /** * Swizzle away later components, but preserve the ordering. */ diff --git a/dist/Mesa/src/glsl/ir_equals.cpp b/dist/Mesa/src/glsl/ir_equals.cpp new file mode 100644 index 000000000..65376cd94 --- /dev/null +++ b/dist/Mesa/src/glsl/ir_equals.cpp @@ -0,0 +1,200 @@ +/* + * Copyright © 2013 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. + */ + +#include "ir.h" + +/** + * Helper for checking equality when one instruction might be NULL, since you + * can't access a's vtable in that case. + */ +static bool +possibly_null_equals(ir_instruction *a, ir_instruction *b, enum ir_node_type ignore) +{ + if (!a || !b) + return !a && !b; + + return a->equals(b, ignore); +} + +/** + * The base equality function: Return not equal for anything we don't know + * about. + */ +bool +ir_instruction::equals(ir_instruction *, enum ir_node_type) +{ + return false; +} + +bool +ir_constant::equals(ir_instruction *ir, enum ir_node_type) +{ + const ir_constant *other = ir->as_constant(); + if (!other) + return false; + + if (type != other->type) + return false; + + for (unsigned i = 0; i < type->components(); i++) { + if (value.u[i] != other->value.u[i]) + return false; + } + + return true; +} + +bool +ir_dereference_variable::equals(ir_instruction *ir, enum ir_node_type) +{ + const ir_dereference_variable *other = ir->as_dereference_variable(); + if (!other) + return false; + + return var == other->var; +} + +bool +ir_dereference_array::equals(ir_instruction *ir, enum ir_node_type ignore) +{ + const ir_dereference_array *other = ir->as_dereference_array(); + if (!other) + return false; + + if (type != other->type) + return false; + + if (!array->equals(other->array, ignore)) + return false; + + if (!array_index->equals(other->array_index, ignore)) + return false; + + return true; +} + +bool +ir_swizzle::equals(ir_instruction *ir, enum ir_node_type ignore) +{ + const ir_swizzle *other = ir->as_swizzle(); + if (!other) + return false; + + if (type != other->type) + return false; + + if (ignore != ir_type_swizzle) { + if (mask.x != other->mask.x || + mask.y != other->mask.y || + mask.z != other->mask.z || + mask.w != other->mask.w) { + return false; + } + } + + return val->equals(other->val, ignore); +} + +bool +ir_texture::equals(ir_instruction *ir, enum ir_node_type ignore) +{ + const ir_texture *other = ir->as_texture(); + if (!other) + return false; + + if (type != other->type) + return false; + + if (op != other->op) + return false; + + if (!possibly_null_equals(coordinate, other->coordinate, ignore)) + return false; + + if (!possibly_null_equals(projector, other->projector, ignore)) + return false; + + if (!possibly_null_equals(shadow_comparitor, other->shadow_comparitor, ignore)) + return false; + + if (!possibly_null_equals(offset, other->offset, ignore)) + return false; + + if (!sampler->equals(other->sampler, ignore)) + return false; + + switch (op) { + case ir_tex: + case ir_lod: + case ir_query_levels: + break; + case ir_txb: + if (!lod_info.bias->equals(other->lod_info.bias, ignore)) + return false; + break; + case ir_txl: + case ir_txf: + case ir_txs: + if (!lod_info.lod->equals(other->lod_info.lod, ignore)) + return false; + break; + case ir_txd: + if (!lod_info.grad.dPdx->equals(other->lod_info.grad.dPdx, ignore) || + !lod_info.grad.dPdy->equals(other->lod_info.grad.dPdy, ignore)) + return false; + break; + case ir_txf_ms: + if (!lod_info.sample_index->equals(other->lod_info.sample_index, ignore)) + return false; + break; + case ir_tg4: + if (!lod_info.component->equals(other->lod_info.component, ignore)) + return false; + break; + default: + assert(!"Unrecognized texture op"); + } + + return true; +} + +bool +ir_expression::equals(ir_instruction *ir, enum ir_node_type ignore) +{ + const ir_expression *other = ir->as_expression(); + if (!other) + return false; + + if (type != other->type) + return false; + + if (operation != other->operation) + return false; + + for (unsigned i = 0; i < get_num_operands(); i++) { + if (!operands[i]->equals(other->operands[i], ignore)) + return false; + } + + return true; +} diff --git a/dist/Mesa/src/glsl/ir_expression_flattening.cpp b/dist/Mesa/src/glsl/ir_expression_flattening.cpp index b44e68ca3..c1cadb122 100644 --- a/dist/Mesa/src/glsl/ir_expression_flattening.cpp +++ b/dist/Mesa/src/glsl/ir_expression_flattening.cpp @@ -59,8 +59,8 @@ do_expression_flattening(exec_list *instructions, { ir_expression_flattening_visitor v(predicate); - foreach_iter(exec_list_iterator, iter, *instructions) { - ir_instruction *ir = (ir_instruction *)iter.get(); + foreach_list(n, instructions) { + ir_instruction *ir = (ir_instruction *) n; ir->accept(&v); } diff --git a/dist/Mesa/src/glsl/ir_hierarchical_visitor.cpp b/dist/Mesa/src/glsl/ir_hierarchical_visitor.cpp index f24414046..2e606dda4 100644 --- a/dist/Mesa/src/glsl/ir_hierarchical_visitor.cpp +++ b/dist/Mesa/src/glsl/ir_hierarchical_visitor.cpp @@ -69,6 +69,24 @@ ir_hierarchical_visitor::visit(ir_loop_jump *ir) } ir_visitor_status +ir_hierarchical_visitor::visit(ir_emit_vertex *ir) +{ + if (this->callback != NULL) + this->callback(ir, this->data); + + return visit_continue; +} + +ir_visitor_status +ir_hierarchical_visitor::visit(ir_end_primitive *ir) +{ + if (this->callback != NULL) + this->callback(ir, this->data); + + return visit_continue; +} + +ir_visitor_status ir_hierarchical_visitor::visit(ir_dereference_variable *ir) { if (this->callback != NULL) diff --git a/dist/Mesa/src/glsl/ir_uniform.h b/dist/Mesa/src/glsl/ir_uniform.h index 8198c4819..3508509d4 100644 --- a/dist/Mesa/src/glsl/ir_uniform.h +++ b/dist/Mesa/src/glsl/ir_uniform.h @@ -78,6 +78,26 @@ struct gl_uniform_driver_storage { void *data; }; +struct gl_opaque_uniform_index { + /** + * Base opaque uniform index + * + * If \c gl_uniform_storage::base_type is an opaque type, this + * represents its uniform index. If \c + * gl_uniform_storage::array_elements is not zero, the array will + * use opaque uniform indices \c index through \c index + \c + * gl_uniform_storage::array_elements - 1, inclusive. + * + * Note that the index may be different in each shader stage. + */ + uint8_t index; + + /** + * Whether this opaque uniform is used in this shader stage. + */ + bool active; +}; + struct gl_uniform_storage { char *name; /** Type of this uniform data stored. @@ -99,24 +119,9 @@ struct gl_uniform_storage { */ bool initialized; - struct { - /** - * Base sampler index - * - * If \c ::base_type is \c GLSL_TYPE_SAMPLER, this represents the index - * of this sampler. If \c ::array_elements is not zero, the array will - * use sampler indices \c ::sampler through \c ::sampler + - * \c ::array_elements - 1, inclusive. - * - * Note that the index may be different in each shader stage. - */ - uint8_t index; - - /** - * Whether this sampler is used in this shader stage. - */ - bool active; - } sampler[MESA_SHADER_TYPES]; + struct gl_opaque_uniform_index sampler[MESA_SHADER_STAGES]; + + struct gl_opaque_uniform_index image[MESA_SHADER_STAGES]; /** * Storage used by the driver for the uniform @@ -166,6 +171,19 @@ struct gl_uniform_storage { bool row_major; /** @} */ + + /** + * Index within gl_shader_program::AtomicBuffers[] of the atomic + * counter buffer this uniform is stored in, or -1 if this is not + * an atomic counter. + */ + int atomic_buffer_index; + + /** + * The 'base location' for this uniform in the uniform remap table. For + * arrays this is the first element in the array. + */ + unsigned remap_location; }; #ifdef __cplusplus diff --git a/dist/Mesa/src/glsl/ir_visitor.h b/dist/Mesa/src/glsl/ir_visitor.h index bd47ef7d5..40f96ffbc 100644 --- a/dist/Mesa/src/glsl/ir_visitor.h +++ b/dist/Mesa/src/glsl/ir_visitor.h @@ -63,6 +63,8 @@ public: virtual void visit(class ir_if *) = 0; virtual void visit(class ir_loop *) = 0; virtual void visit(class ir_loop_jump *) = 0; + virtual void visit(class ir_emit_vertex *) = 0; + virtual void visit(class ir_end_primitive *) = 0; /*@}*/ }; @@ -81,6 +83,8 @@ public: virtual void visit(class ir_assignment *) {} virtual void visit(class ir_constant *) {} virtual void visit(class ir_call *) {} + virtual void visit(class ir_emit_vertex *) {} + virtual void visit(class ir_end_primitive *) {} }; #endif /* __cplusplus */ diff --git a/dist/Mesa/src/glsl/link_atomics.cpp b/dist/Mesa/src/glsl/link_atomics.cpp new file mode 100644 index 000000000..d92cdb117 --- /dev/null +++ b/dist/Mesa/src/glsl/link_atomics.cpp @@ -0,0 +1,265 @@ +/* + * Copyright © 2013 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. + */ + +#include "glsl_parser_extras.h" +#include "ir.h" +#include "ir_uniform.h" +#include "linker.h" +#include "program/hash_table.h" +#include "main/macros.h" + +namespace { + /* + * Atomic counter as seen by the program. + */ + struct active_atomic_counter { + unsigned id; + ir_variable *var; + }; + + /* + * Atomic counter buffer referenced by the program. There is a one + * to one correspondence between these and the objects that can be + * queried using glGetActiveAtomicCounterBufferiv(). + */ + struct active_atomic_buffer { + active_atomic_buffer() + : counters(0), num_counters(0), stage_references(), size(0) + {} + + ~active_atomic_buffer() + { + free(counters); + } + + void push_back(unsigned id, ir_variable *var) + { + counters = (active_atomic_counter *) + realloc(counters, sizeof(active_atomic_counter) * (num_counters + 1)); + + counters[num_counters].id = id; + counters[num_counters].var = var; + num_counters++; + } + + active_atomic_counter *counters; + unsigned num_counters; + unsigned stage_references[MESA_SHADER_STAGES]; + unsigned size; + }; + + int + cmp_actives(const void *a, const void *b) + { + const active_atomic_counter *const first = (active_atomic_counter *) a; + const active_atomic_counter *const second = (active_atomic_counter *) b; + + return int(first->var->data.atomic.offset) - int(second->var->data.atomic.offset); + } + + bool + check_atomic_counters_overlap(const ir_variable *x, const ir_variable *y) + { + return ((x->data.atomic.offset >= y->data.atomic.offset && + x->data.atomic.offset < y->data.atomic.offset + y->type->atomic_size()) || + (y->data.atomic.offset >= x->data.atomic.offset && + y->data.atomic.offset < x->data.atomic.offset + x->type->atomic_size())); + } + + active_atomic_buffer * + find_active_atomic_counters(struct gl_context *ctx, + struct gl_shader_program *prog, + unsigned *num_buffers) + { + active_atomic_buffer *const buffers = + new active_atomic_buffer[ctx->Const.MaxAtomicBufferBindings]; + + *num_buffers = 0; + + for (unsigned i = 0; i < MESA_SHADER_STAGES; ++i) { + struct gl_shader *sh = prog->_LinkedShaders[i]; + if (sh == NULL) + continue; + + foreach_list(node, sh->ir) { + ir_variable *var = ((ir_instruction *)node)->as_variable(); + + if (var && var->type->contains_atomic()) { + unsigned id = 0; + bool found = prog->UniformHash->get(id, var->name); + assert(found); + (void) found; + active_atomic_buffer *buf = &buffers[var->data.binding]; + + /* If this is the first time the buffer is used, increment + * the counter of buffers used. + */ + if (buf->size == 0) + (*num_buffers)++; + + buf->push_back(id, var); + + buf->stage_references[i]++; + buf->size = MAX2(buf->size, var->data.atomic.offset + + var->type->atomic_size()); + } + } + } + + for (unsigned i = 0; i < ctx->Const.MaxAtomicBufferBindings; i++) { + if (buffers[i].size == 0) + continue; + + qsort(buffers[i].counters, buffers[i].num_counters, + sizeof(active_atomic_counter), + cmp_actives); + + for (unsigned j = 1; j < buffers[i].num_counters; j++) { + /* If an overlapping counter found, it must be a reference to the + * same counter from a different shader stage. + */ + if (check_atomic_counters_overlap(buffers[i].counters[j-1].var, + buffers[i].counters[j].var) + && strcmp(buffers[i].counters[j-1].var->name, + buffers[i].counters[j].var->name) != 0) { + linker_error(prog, "Atomic counter %s declared at offset %d " + "which is already in use.", + buffers[i].counters[j].var->name, + buffers[i].counters[j].var->data.atomic.offset); + } + } + } + return buffers; + } +} + +void +link_assign_atomic_counter_resources(struct gl_context *ctx, + struct gl_shader_program *prog) +{ + unsigned num_buffers; + active_atomic_buffer *abs = + find_active_atomic_counters(ctx, prog, &num_buffers); + + prog->AtomicBuffers = rzalloc_array(prog, gl_active_atomic_buffer, + num_buffers); + prog->NumAtomicBuffers = num_buffers; + + unsigned i = 0; + for (unsigned binding = 0; + binding < ctx->Const.MaxAtomicBufferBindings; + binding++) { + + /* If the binding was not used, skip. + */ + if (abs[binding].size == 0) + continue; + + active_atomic_buffer &ab = abs[binding]; + gl_active_atomic_buffer &mab = prog->AtomicBuffers[i]; + + /* Assign buffer-specific fields. */ + mab.Binding = binding; + mab.MinimumSize = ab.size; + mab.Uniforms = rzalloc_array(prog->AtomicBuffers, GLuint, + ab.num_counters); + mab.NumUniforms = ab.num_counters; + + /* Assign counter-specific fields. */ + for (unsigned j = 0; j < ab.num_counters; j++) { + ir_variable *const var = ab.counters[j].var; + const unsigned id = ab.counters[j].id; + gl_uniform_storage *const storage = &prog->UniformStorage[id]; + + mab.Uniforms[j] = id; + var->data.atomic.buffer_index = i; + storage->atomic_buffer_index = i; + storage->offset = var->data.atomic.offset; + storage->array_stride = (var->type->is_array() ? + var->type->element_type()->atomic_size() : 0); + } + + /* Assign stage-specific fields. */ + for (unsigned j = 0; j < MESA_SHADER_STAGES; ++j) + mab.StageReferences[j] = + (ab.stage_references[j] ? GL_TRUE : GL_FALSE); + + i++; + } + + delete [] abs; + assert(i == num_buffers); +} + +void +link_check_atomic_counter_resources(struct gl_context *ctx, + struct gl_shader_program *prog) +{ + unsigned num_buffers; + active_atomic_buffer *const abs = + find_active_atomic_counters(ctx, prog, &num_buffers); + unsigned atomic_counters[MESA_SHADER_STAGES] = {}; + unsigned atomic_buffers[MESA_SHADER_STAGES] = {}; + unsigned total_atomic_counters = 0; + unsigned total_atomic_buffers = 0; + + /* Sum the required resources. Note that this counts buffers and + * counters referenced by several shader stages multiple times + * against the combined limit -- That's the behavior the spec + * requires. + */ + for (unsigned i = 0; i < ctx->Const.MaxAtomicBufferBindings; i++) { + if (abs[i].size == 0) + continue; + + for (unsigned j = 0; j < MESA_SHADER_STAGES; ++j) { + const unsigned n = abs[i].stage_references[j]; + + if (n) { + atomic_counters[j] += n; + total_atomic_counters += n; + atomic_buffers[j]++; + total_atomic_buffers++; + } + } + } + + /* Check that they are within the supported limits. */ + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + if (atomic_counters[i] > ctx->Const.Program[i].MaxAtomicCounters) + linker_error(prog, "Too many %s shader atomic counters", + _mesa_shader_stage_to_string(i)); + + if (atomic_buffers[i] > ctx->Const.Program[i].MaxAtomicBuffers) + linker_error(prog, "Too many %s shader atomic counter buffers", + _mesa_shader_stage_to_string(i)); + } + + if (total_atomic_counters > ctx->Const.MaxCombinedAtomicCounters) + linker_error(prog, "Too many combined atomic counters"); + + if (total_atomic_buffers > ctx->Const.MaxCombinedAtomicBuffers) + linker_error(prog, "Too many combined atomic buffers"); + + delete [] abs; +} diff --git a/dist/Mesa/src/glsl/link_interface_blocks.cpp b/dist/Mesa/src/glsl/link_interface_blocks.cpp index b91860d03..52552cc68 100644 --- a/dist/Mesa/src/glsl/link_interface_blocks.cpp +++ b/dist/Mesa/src/glsl/link_interface_blocks.cpp @@ -30,12 +30,230 @@ #include "glsl_symbol_table.h" #include "linker.h" #include "main/macros.h" +#include "program/hash_table.h" + +namespace { + +/** + * Information about a single interface block definition that we need to keep + * track of in order to check linkage rules. + * + * Note: this class is expected to be short lived, so it doesn't make copies + * of the strings it references; it simply borrows the pointers from the + * ir_variable class. + */ +struct interface_block_definition +{ + /** + * Extract an interface block definition from an ir_variable that + * 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) + { + 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 type + */ + const glsl_type *type; + + /** + * For a named interface block, the instance name. Otherwise NULL. + */ + 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. + */ + bool explicitly_declared; +}; + + +/** + * Check if two interfaces match, according to intrastage interface matching + * rules. If they do, and the first interface uses an unsized array, it will + * be updated to reflect the array size declared in the second interface. + */ +bool +intrastage_match(interface_block_definition *a, + const interface_block_definition *b, + ir_variable_mode mode) +{ + /* Types must match. */ + if (a->type != b->type) { + /* Exception: if both the interface blocks are implicitly declared, + * don't force their types to match. They might mismatch due to the two + * shaders using different GLSL versions, and that's ok. + */ + if (a->explicitly_declared || b->explicitly_declared) + return false; + } + + /* Presence/absence of interface names must match. */ + if ((a->instance_name == NULL) != (b->instance_name == NULL)) + return false; + + /* For uniforms, instance names need not match. For shader ins/outs, + * it's not clear from the spec whether they need to match, but + * Mesa's implementation relies on them matching. + */ + if (a->instance_name != NULL && mode != ir_var_uniform && + strcmp(a->instance_name, b->instance_name) != 0) { + return false; + } + + /* Array vs. nonarray must be consistent, and sizes must be + * consistent, with the exception that unsized arrays match sized + * arrays. + */ + if ((a->array_size == -1) != (b->array_size == -1)) + 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; +} + + +/** + * Check if two interfaces match, according to interstage (in/out) interface + * matching rules. + * + * If \c extra_array_level is true, then vertex-to-geometry shader matching + * rules are enforced (i.e. a successful match requires the consumer interface + * to be an array and the producer interface to be a non-array). + */ bool -validate_intrastage_interface_blocks(const gl_shader **shader_list, +interstage_match(const interface_block_definition *producer, + const interface_block_definition *consumer, + bool extra_array_level) +{ + /* 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); + + /* Types must match. */ + if (consumer->type != producer->type) { + /* Exception: if both the interface blocks are implicitly declared, + * don't force their types to match. They might mismatch due to the two + * shaders using different GLSL versions, and that's ok. + */ + if (consumer->explicitly_declared || producer->explicitly_declared) + return false; + } + 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; + } 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) + return false; + } + return true; +} + + +/** + * This class keeps track of a mapping from an interface block name to the + * necessary information about that interface block to determine whether to + * generate a link error. + * + * Note: this class is expected to be short lived, so it doesn't make copies + * of the strings it references; it simply borrows the pointers from the + * ir_variable class. + */ +class interface_block_definitions +{ +public: + interface_block_definitions() + : mem_ctx(ralloc_context(NULL)), + ht(hash_table_ctor(0, hash_table_string_hash, + hash_table_string_compare)) + { + } + + ~interface_block_definitions() + { + hash_table_dtor(ht); + ralloc_free(mem_ctx); + } + + /** + * Lookup the interface definition having the given block name. Return + * NULL if none is found. + */ + interface_block_definition *lookup(const char *block_name) + { + return (interface_block_definition *) hash_table_find(ht, block_name); + } + + /** + * Add a new interface definition. + */ + void store(const interface_block_definition &def) + { + interface_block_definition *hash_entry = + rzalloc(mem_ctx, interface_block_definition); + *hash_entry = def; + hash_table_insert(ht, hash_entry, def.type->name); + } + +private: + /** + * Ralloc context for data structures allocated by this class. + */ + void *mem_ctx; + + /** + * Hash table mapping interface block name to an \c + * interface_block_definition struct. interface_block_definition structs + * are allocated using \c mem_ctx. + */ + hash_table *ht; +}; + + +}; /* anonymous namespace */ + + +void +validate_intrastage_interface_blocks(struct gl_shader_program *prog, + const gl_shader **shader_list, unsigned num_shaders) { - glsl_symbol_table interfaces; + interface_block_definitions in_interfaces; + interface_block_definitions out_interfaces; + interface_block_definitions uniform_interfaces; for (unsigned int i = 0; i < num_shaders; i++) { if (shader_list[i] == NULL) @@ -46,65 +264,122 @@ validate_intrastage_interface_blocks(const gl_shader **shader_list, if (!var) continue; - const glsl_type *iface_type = var->interface_type; + const glsl_type *iface_type = var->get_interface_type(); if (iface_type == NULL) continue; - const glsl_type *old_iface_type = - interfaces.get_interface(iface_type->name, - (enum ir_variable_mode) var->mode); + interface_block_definitions *definitions; + switch (var->data.mode) { + case ir_var_shader_in: + definitions = &in_interfaces; + break; + case ir_var_shader_out: + definitions = &out_interfaces; + break; + case ir_var_uniform: + definitions = &uniform_interfaces; + break; + default: + /* Only in, out, and uniform interfaces are legal, so we should + * never get here. + */ + assert(!"illegal interface type"); + continue; + } - if (old_iface_type == NULL) { + const interface_block_definition def(var); + interface_block_definition *prev_def = + definitions->lookup(iface_type->name); + + if (prev_def == NULL) { /* This is the first time we've seen the interface, so save - * it into our symbol table. + * it into the appropriate data structure. */ - interfaces.add_interface(iface_type->name, iface_type, - (enum ir_variable_mode) var->mode); - } else if (old_iface_type != iface_type) { - return false; + definitions->store(def); + } else if (!intrastage_match(prev_def, &def, + (ir_variable_mode) var->data.mode)) { + linker_error(prog, "definitions of interface block `%s' do not" + " match\n", iface_type->name); + return; } } } - - return true; } -bool -validate_interstage_interface_blocks(const gl_shader *producer, - const gl_shader *consumer) +void +validate_interstage_inout_blocks(struct gl_shader_program *prog, + const gl_shader *producer, + const gl_shader *consumer) { - glsl_symbol_table interfaces; + interface_block_definitions definitions; + const bool extra_array_level = consumer->Stage == MESA_SHADER_GEOMETRY; - /* Add non-output interfaces from the consumer to the symbol table. */ + /* Add input interfaces from the consumer to the symbol table. */ foreach_list(node, consumer->ir) { ir_variable *var = ((ir_instruction *) node)->as_variable(); - if (!var || !var->interface_type || var->mode == ir_var_shader_out) + if (!var || !var->get_interface_type() || var->data.mode != ir_var_shader_in) continue; - interfaces.add_interface(var->interface_type->name, - var->interface_type, - (enum ir_variable_mode) var->mode); + definitions.store(interface_block_definition(var)); } - /* Verify that the producer's interfaces match. */ + /* Verify that the producer's output interfaces match. */ foreach_list(node, producer->ir) { ir_variable *var = ((ir_instruction *) node)->as_variable(); - if (!var || !var->interface_type || var->mode == ir_var_shader_in) + if (!var || !var->get_interface_type() || var->data.mode != ir_var_shader_out) continue; - enum ir_variable_mode consumer_mode = - var->mode == ir_var_uniform ? ir_var_uniform : ir_var_shader_in; - const glsl_type *expected_type = - interfaces.get_interface(var->interface_type->name, consumer_mode); + interface_block_definition *consumer_def = + definitions.lookup(var->get_interface_type()->name); /* The consumer doesn't use this output block. Ignore it. */ - if (expected_type == NULL) + if (consumer_def == NULL) continue; - if (var->interface_type != expected_type) - return false; + const interface_block_definition producer_def(var); + + if (!interstage_match(&producer_def, consumer_def, extra_array_level)) { + linker_error(prog, "definitions of interface block `%s' do not " + "match\n", var->get_interface_type()->name); + return; + } } +} - return true; + +void +validate_interstage_uniform_blocks(struct gl_shader_program *prog, + gl_shader **stages, int num_stages) +{ + interface_block_definitions definitions; + + for (int i = 0; i < num_stages; i++) { + if (stages[i] == NULL) + continue; + + const gl_shader *stage = stages[i]; + foreach_list(node, stage->ir) { + ir_variable *var = ((ir_instruction *) node)->as_variable(); + if (!var || !var->get_interface_type() || var->data.mode != ir_var_uniform) + continue; + + interface_block_definition *old_def = + definitions.lookup(var->get_interface_type()->name); + const interface_block_definition new_def(var); + if (old_def == NULL) { + definitions.store(new_def); + } else { + /* Interstage uniform matching rules are the same as intrastage + * 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)) { + linker_error(prog, "definitions of interface block `%s' do not " + "match\n", var->get_interface_type()->name); + return; + } + } + } + } } diff --git a/dist/Mesa/src/glsl/link_uniform_block_active_visitor.cpp b/dist/Mesa/src/glsl/link_uniform_block_active_visitor.cpp index 56a8384e9..d19ce20c7 100644 --- a/dist/Mesa/src/glsl/link_uniform_block_active_visitor.cpp +++ b/dist/Mesa/src/glsl/link_uniform_block_active_visitor.cpp @@ -27,12 +27,12 @@ link_uniform_block_active * process_block(void *mem_ctx, struct hash_table *ht, ir_variable *var) { - const uint32_t h = _mesa_hash_string(var->interface_type->name); + const uint32_t h = _mesa_hash_string(var->get_interface_type()->name); const hash_entry *const existing_block = - _mesa_hash_table_search(ht, h, var->interface_type->name); + _mesa_hash_table_search(ht, h, var->get_interface_type()->name); const glsl_type *const block_type = var->is_interface_instance() - ? var->type : var->interface_type; + ? var->type : var->get_interface_type(); /* If a block with this block-name has not previously been seen, add it. @@ -46,7 +46,15 @@ process_block(void *mem_ctx, struct hash_table *ht, ir_variable *var) b->type = block_type; b->has_instance_name = var->is_interface_instance(); - _mesa_hash_table_insert(ht, h, var->interface_type->name, + if (var->data.explicit_binding) { + b->has_binding = true; + b->binding = var->data.binding; + } else { + b->has_binding = false; + b->binding = 0; + } + + _mesa_hash_table_insert(ht, h, var->get_interface_type()->name, (void *) b); return b; } else { @@ -90,7 +98,7 @@ link_uniform_block_active_visitor::visit_enter(ir_dereference_array *ir) if (b == NULL) { linker_error(prog, "uniform block `%s' has mismatching definitions", - var->interface_type->name); + var->get_interface_type()->name); this->success = false; return visit_stop; } @@ -149,7 +157,7 @@ link_uniform_block_active_visitor::visit(ir_dereference_variable *ir) if (b == NULL) { linker_error(this->prog, "uniform block `%s' has mismatching definitions", - var->interface_type->name); + var->get_interface_type()->name); this->success = false; return visit_stop; } diff --git a/dist/Mesa/src/glsl/link_uniform_block_active_visitor.h b/dist/Mesa/src/glsl/link_uniform_block_active_visitor.h index fba628a8f..d76dbcaf1 100644 --- a/dist/Mesa/src/glsl/link_uniform_block_active_visitor.h +++ b/dist/Mesa/src/glsl/link_uniform_block_active_visitor.h @@ -36,7 +36,10 @@ struct link_uniform_block_active { unsigned *array_elements; unsigned num_array_elements; + unsigned binding; + bool has_instance_name; + bool has_binding; }; class link_uniform_block_active_visitor : public ir_hierarchical_visitor { diff --git a/dist/Mesa/src/glsl/link_uniform_blocks.cpp b/dist/Mesa/src/glsl/link_uniform_blocks.cpp index e475147e5..1a0e64318 100644 --- a/dist/Mesa/src/glsl/link_uniform_blocks.cpp +++ b/dist/Mesa/src/glsl/link_uniform_blocks.cpp @@ -29,6 +29,8 @@ #include "main/hash_table.h" #include "program.h" +namespace { + class ubo_visitor : public program_resource_visitor { public: ubo_visitor(void *mem_ctx, gl_uniform_buffer_variable *variables, @@ -147,12 +149,14 @@ private: } }; +} /* anonymous namespace */ + struct block { const glsl_type *type; bool has_instance_name; }; -int +unsigned link_uniform_blocks(void *mem_ctx, struct gl_shader_program *prog, struct gl_shader **shader_list, @@ -247,7 +251,17 @@ link_uniform_blocks(void *mem_ctx, blocks[i].Name = ralloc_asprintf(blocks, "%s[%u]", name, b->array_elements[j]); blocks[i].Uniforms = &variables[parcel.index]; - blocks[i].Binding = 0; + + /* The GL_ARB_shading_language_420pack spec says: + * + * "If the binding identifier is used with a uniform block + * instanced as an array then the first element of the array + * takes the specified block binding and each subsequent + * element takes the next consecutive uniform block binding + * point." + */ + blocks[i].Binding = (b->has_binding) ? b->binding + j : 0; + blocks[i].UniformBufferSize = 0; blocks[i]._Packing = gl_uniform_block_packing(block_type->interface_packing); @@ -265,7 +279,7 @@ link_uniform_blocks(void *mem_ctx, } else { blocks[i].Name = ralloc_strdup(blocks, block_type->name); blocks[i].Uniforms = &variables[parcel.index]; - blocks[i].Binding = 0; + blocks[i].Binding = (b->has_binding) ? b->binding : 0; blocks[i].UniformBufferSize = 0; blocks[i]._Packing = gl_uniform_block_packing(block_type->interface_packing); diff --git a/dist/Mesa/src/glsl/link_uniform_initializers.cpp b/dist/Mesa/src/glsl/link_uniform_initializers.cpp index 3f6671047..2100e0517 100644 --- a/dist/Mesa/src/glsl/link_uniform_initializers.cpp +++ b/dist/Mesa/src/glsl/link_uniform_initializers.cpp @@ -46,6 +46,18 @@ 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->NumUniformBlocks; i++) { + if (!strcmp(shProg->UniformBlocks[i].Name, uniformBlockName)) + return i; + } + + return GL_INVALID_INDEX; +} + void copy_constant_to_storage(union gl_constant_value *storage, const ir_constant *val, @@ -69,6 +81,8 @@ copy_constant_to_storage(union gl_constant_value *storage, break; case GLSL_TYPE_ARRAY: case GLSL_TYPE_STRUCT: + case GLSL_TYPE_IMAGE: + case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_INTERFACE: case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: @@ -82,8 +96,7 @@ copy_constant_to_storage(union gl_constant_value *storage, } void -set_uniform_binding(void *mem_ctx, gl_shader_program *prog, - const char *name, const glsl_type *type, int binding) +set_sampler_binding(gl_shader_program *prog, const char *name, int binding) { struct gl_uniform_storage *const storage = get_storage(prog->UniformStorage, prog->NumUserUniformStorage, name); @@ -93,42 +106,53 @@ set_uniform_binding(void *mem_ctx, gl_shader_program *prog, return; } - if (storage->type->is_sampler()) { - unsigned elements = MAX2(storage->array_elements, 1); + const unsigned elements = MAX2(storage->array_elements, 1); - /* From section 4.4.4 of the GLSL 4.20 specification: - * "If the binding identifier is used with an array, the first element - * of the array takes the specified unit and each subsequent element - * takes the next consecutive unit." - */ - for (unsigned int i = 0; i < elements; i++) { - storage->storage[i].i = binding + i; - } + /* Section 4.4.4 (Opaque-Uniform Layout Qualifiers) of the GLSL 4.20 spec + * says: + * + * "If the binding identifier is used with an array, the first element + * of the array takes the specified unit and each subsequent element + * takes the next consecutive unit." + */ + for (unsigned int i = 0; i < elements; i++) { + storage->storage[i].i = binding + i; + } - for (int sh = 0; sh < MESA_SHADER_TYPES; sh++) { - gl_shader *shader = prog->_LinkedShaders[sh]; + for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) { + gl_shader *shader = prog->_LinkedShaders[sh]; - if (shader && storage->sampler[sh].active) { - for (unsigned i = 0; i < elements; i++) { - unsigned index = storage->sampler[sh].index + i; + if (shader && storage->sampler[sh].active) { + for (unsigned i = 0; i < elements; i++) { + unsigned index = storage->sampler[sh].index + i; - shader->SamplerUnits[index] = storage->storage[i].i; - } + shader->SamplerUnits[index] = storage->storage[i].i; } } - } else if (storage->block_index != -1) { + } + + storage->initialized = true; +} + +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; + } + /* This is a field of a UBO. val is the binding index. */ - for (int i = 0; i < MESA_SHADER_TYPES; i++) { - int stage_index = prog->UniformBlockStageIndex[i][storage->block_index]; + for (int i = 0; i < MESA_SHADER_STAGES; i++) { + int stage_index = prog->UniformBlockStageIndex[i][block_index]; if (stage_index != -1) { struct gl_shader *sh = prog->_LinkedShaders[i]; sh->UniformBlocks[stage_index].Binding = binding; } } - } - - storage->initialized = true; } void @@ -193,7 +217,7 @@ set_uniform_initializer(void *mem_ctx, gl_shader_program *prog, val->type->components()); if (storage->type->is_sampler()) { - for (int sh = 0; sh < MESA_SHADER_TYPES; sh++) { + for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) { gl_shader *shader = prog->_LinkedShaders[sh]; if (shader && storage->sampler[sh].active) { @@ -214,7 +238,7 @@ link_set_uniform_initializers(struct gl_shader_program *prog) { void *mem_ctx = NULL; - for (unsigned int i = 0; i < MESA_SHADER_TYPES; i++) { + for (unsigned int i = 0; i < MESA_SHADER_STAGES; i++) { struct gl_shader *shader = prog->_LinkedShaders[i]; if (shader == NULL) @@ -223,15 +247,60 @@ link_set_uniform_initializers(struct gl_shader_program *prog) foreach_list(node, shader->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if (!var || var->mode != ir_var_uniform) + if (!var || var->data.mode != ir_var_uniform) continue; if (!mem_ctx) mem_ctx = ralloc_context(NULL); - if (var->explicit_binding) { - linker::set_uniform_binding(mem_ctx, prog, var->name, - var->type, var->binding); + if (var->data.explicit_binding) { + const glsl_type *const type = var->type; + + if (type->is_sampler() + || (type->is_array() && type->fields.array->is_sampler())) { + linker::set_sampler_binding(prog, var->name, var->data.binding); + } else if (var->is_in_uniform_block()) { + const glsl_type *const iface_type = var->get_interface_type(); + + /* If the variable is an array and it is an interface instance, + * we need to set the binding for each array element. Just + * checking that the variable is an array is not sufficient. + * The variable could be an array element of a uniform block + * that lacks an instance name. For example: + * + * uniform U { + * float f[4]; + * }; + * + * In this case "f" would pass is_in_uniform_block (above) and + * type->is_array(), but it will fail is_interface_instance(). + */ + if (var->is_interface_instance() && var->type->is_array()) { + for (unsigned i = 0; i < var->type->length; i++) { + const char *name = + ralloc_asprintf(mem_ctx, "%s[%u]", iface_type->name, i); + + /* Section 4.4.3 (Uniform Block Layout Qualifiers) of the + * GLSL 4.20 spec says: + * + * "If the binding identifier is used with a uniform + * block instanced as an array then the first element + * of the array takes the specified block binding and + * each subsequent element takes the next consecutive + * uniform block binding point." + */ + linker::set_block_binding(prog, name, + var->data.binding + i); + } + } else { + linker::set_block_binding(prog, iface_type->name, + var->data.binding); + } + } else if (type->contains_atomic()) { + /* we don't actually need to do anything. */ + } else { + assert(!"Explicit binding not on a sampler, UBO or atomic."); + } } else if (var->constant_value) { linker::set_uniform_initializer(mem_ctx, prog, var->name, var->type, var->constant_value); diff --git a/dist/Mesa/src/glsl/link_uniforms.cpp b/dist/Mesa/src/glsl/link_uniforms.cpp index 6cec96e3f..29dc0b196 100644 --- a/dist/Mesa/src/glsl/link_uniforms.cpp +++ b/dist/Mesa/src/glsl/link_uniforms.cpp @@ -75,7 +75,63 @@ program_resource_visitor::process(ir_variable *var) */ /* Only strdup the name if we actually will need to modify it. */ - if (t->is_record() || (t->is_array() && t->fields.array->is_record())) { + if (var->data.from_named_ifc_block_array) { + /* lower_named_interface_blocks created this variable by lowering an + * interface block array to an array variable. For example if the + * original source code was: + * + * out Blk { vec4 bar } foo[3]; + * + * Then the variable is now: + * + * out vec4 bar[3]; + * + * We need to visit each array element using the names constructed like + * so: + * + * Blk[0].bar + * Blk[1].bar + * Blk[2].bar + */ + assert(t->is_array()); + const glsl_type *ifc_type = var->get_interface_type(); + char *name = ralloc_strdup(NULL, ifc_type->name); + size_t name_length = strlen(name); + for (unsigned i = 0; i < t->length; i++) { + size_t new_length = name_length; + ralloc_asprintf_rewrite_tail(&name, &new_length, "[%u].%s", i, + var->name); + /* Note: row_major is only meaningful for uniform blocks, and + * lowering is only applied to non-uniform interface blocks, so we + * can safely pass false for row_major. + */ + recursion(var->type, &name, new_length, false, NULL); + } + ralloc_free(name); + } else if (var->data.from_named_ifc_block_nonarray) { + /* lower_named_interface_blocks created this variable by lowering a + * named interface block (non-array) to an ordinary variable. For + * example if the original source code was: + * + * out Blk { vec4 bar } foo; + * + * Then the variable is now: + * + * out vec4 bar; + * + * We need to visit this variable using the name: + * + * Blk.bar + */ + const glsl_type *ifc_type = var->get_interface_type(); + char *name = ralloc_asprintf(NULL, "%s.%s", ifc_type->name, var->name); + /* Note: row_major is only meaningful for uniform blocks, and lowering + * is only applied to non-uniform interface blocks, so we can safely + * pass false for row_major. + */ + recursion(var->type, &name, strlen(name), false, NULL); + ralloc_free(name); + } else if (t->is_record() || (t->is_array() && t->fields.array->is_record())) { char *name = ralloc_strdup(NULL, var->name); recursion(var->type, &name, strlen(name), false, NULL); ralloc_free(name); @@ -156,7 +212,7 @@ program_resource_visitor::recursion(const glsl_type *t, char **name, void program_resource_visitor::visit_field(const glsl_type *type, const char *name, bool row_major, - const glsl_type *record_type) + const glsl_type *) { visit_field(type, name, row_major); } @@ -168,6 +224,8 @@ program_resource_visitor::visit_field(const glsl_struct_field *field) /* empty */ } +namespace { + /** * Class to help calculate the storage requirements for a set of uniforms * @@ -182,7 +240,8 @@ class count_uniform_size : public program_resource_visitor { public: count_uniform_size(struct string_to_uint_map *map) : num_active_uniforms(0), num_values(0), num_shader_samplers(0), - num_shader_uniform_components(0), is_ubo_var(false), map(map) + num_shader_images(0), num_shader_uniform_components(0), + is_ubo_var(false), map(map) { /* empty */ } @@ -190,6 +249,7 @@ public: void start_shader() { this->num_shader_samplers = 0; + this->num_shader_images = 0; this->num_shader_uniform_components = 0; } @@ -197,8 +257,8 @@ public: { this->is_ubo_var = var->is_in_uniform_block(); if (var->is_interface_instance()) - program_resource_visitor::process(var->interface_type, - var->interface_type->name); + program_resource_visitor::process(var->get_interface_type(), + var->get_interface_type()->name); else program_resource_visitor::process(var); } @@ -219,6 +279,11 @@ public: unsigned num_shader_samplers; /** + * Number of images used + */ + unsigned num_shader_images; + + /** * Number of uniforms used in the current shader */ unsigned num_shader_uniform_components; @@ -245,6 +310,15 @@ private: if (type->contains_sampler()) { this->num_shader_samplers += type->is_array() ? type->array_size() : 1; + } else if (type->contains_image()) { + this->num_shader_images += values; + + /* As drivers are likely to represent image uniforms as + * scalar indices, count them against the limit of uniform + * components in the default block. The spec allows image + * uniforms to use up no more than one scalar slot. + */ + this->num_shader_uniform_components += values; } else { /* Accumulate the total number of uniform slots used by this shader. * Note that samplers do not count against this limit because they @@ -272,6 +346,8 @@ private: struct string_to_uint_map *map; }; +} /* anonymous namespace */ + /** * Class to help parcel out pieces of backing storage to uniforms * @@ -296,14 +372,15 @@ public: { } - void start_shader(gl_shader_type shader_type) + void start_shader(gl_shader_stage shader_type) { - assert(shader_type < MESA_SHADER_TYPES); + assert(shader_type < MESA_SHADER_STAGES); this->shader_type = shader_type; this->shader_samplers_used = 0; this->shader_shadow_samplers = 0; this->next_sampler = 0; + this->next_image = 0; memset(this->targets, 0, sizeof(this->targets)); } @@ -313,10 +390,10 @@ public: ubo_block_index = -1; if (var->is_in_uniform_block()) { if (var->is_interface_instance() && var->type->is_array()) { - unsigned l = strlen(var->interface_type->name); + unsigned l = strlen(var->get_interface_type()->name); for (unsigned i = 0; i < prog->NumUniformBlocks; i++) { - if (strncmp(var->interface_type->name, + if (strncmp(var->get_interface_type()->name, prog->UniformBlocks[i].Name, l) == 0 && prog->UniformBlocks[i].Name[l] == '[') { @@ -326,7 +403,7 @@ public: } } else { for (unsigned i = 0; i < prog->NumUniformBlocks; i++) { - if (strcmp(var->interface_type->name, + if (strcmp(var->get_interface_type()->name, prog->UniformBlocks[i].Name) == 0) { ubo_block_index = i; break; @@ -348,17 +425,18 @@ public: const struct gl_uniform_block *const block = &prog->UniformBlocks[ubo_block_index]; - assert(var->location != -1); + assert(var->data.location != -1); const struct gl_uniform_buffer_variable *const ubo_var = - &block->Uniforms[var->location]; + &block->Uniforms[var->data.location]; ubo_row_major = ubo_var->RowMajor; ubo_byte_offset = ubo_var->Offset; } if (var->is_interface_instance()) - process(var->interface_type, var->interface_type->name); + process(var->get_interface_type(), + var->get_interface_type()->name); else process(var); } else @@ -368,7 +446,7 @@ public: int ubo_block_index; int ubo_byte_offset; bool ubo_row_major; - gl_shader_type shader_type; + gl_shader_stage shader_type; private: void handle_samplers(const glsl_type *base_type, @@ -399,6 +477,24 @@ private: } } + void handle_images(const glsl_type *base_type, + struct gl_uniform_storage *uniform) + { + if (base_type->is_image()) { + uniform->image[shader_type].index = this->next_image; + uniform->image[shader_type].active = true; + + /* Increment the image index by 1 for non-arrays and by the + * number of array elements for arrays. + */ + this->next_image += MAX2(1, uniform->array_elements); + + } else { + uniform->image[shader_type].index = ~0; + uniform->image[shader_type].active = false; + } + } + virtual void visit_field(const glsl_type *type, const char *name, bool row_major) { @@ -434,8 +530,9 @@ private: base_type = type; } - /* This assigns sampler uniforms to sampler units. */ + /* This assigns uniform indices to sampler and image uniforms. */ handle_samplers(base_type, &this->uniforms[id]); + handle_images(base_type, &this->uniforms[id]); /* If there is already storage associated with this uniform, it means * that it was set while processing an earlier shader stage. For @@ -452,6 +549,7 @@ private: this->uniforms[id].num_driver_storage = 0; this->uniforms[id].driver_storage = NULL; this->uniforms[id].storage = this->values; + this->uniforms[id].atomic_buffer_index = -1; if (this->ubo_block_index != -1) { this->uniforms[id].block_index = this->ubo_block_index; @@ -492,6 +590,7 @@ private: struct gl_uniform_storage *uniforms; unsigned next_sampler; + unsigned next_image; public: union gl_constant_value *values; @@ -575,10 +674,10 @@ link_update_uniform_buffer_variables(struct gl_shader *shader) if ((var == NULL) || !var->is_in_uniform_block()) continue; - assert(var->mode == ir_var_uniform); + assert(var->data.mode == ir_var_uniform); if (var->is_interface_instance()) { - var->location = 0; + var->data.location = 0; continue; } @@ -607,13 +706,13 @@ link_update_uniform_buffer_variables(struct gl_shader *shader) if (strncmp(var->name, begin, l) == 0) { found = true; - var->location = j; + var->data.location = j; break; } } else if (!strcmp(var->name, shader->UniformBlocks[i].Uniforms[j].Name)) { found = true; - var->location = j; + var->data.location = j; break; } } @@ -658,6 +757,41 @@ link_assign_uniform_block_offsets(struct gl_shader *shader) } } +/** + * Scan the program for image uniforms and store image unit access + * information into the gl_shader data structure. + */ +static void +link_set_image_access_qualifiers(struct gl_shader_program *prog) +{ + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + gl_shader *sh = prog->_LinkedShaders[i]; + + if (sh == NULL) + continue; + + foreach_list(node, sh->ir) { + ir_variable *var = ((ir_instruction *) node)->as_variable(); + + if (var && var->data.mode == ir_var_uniform && + var->type->contains_image()) { + unsigned id = 0; + bool found = prog->UniformHash->get(id, var->name); + assert(found); + (void) found; + const gl_uniform_storage *storage = &prog->UniformStorage[id]; + const unsigned index = storage->image[i].index; + const GLenum access = (var->data.image.read_only ? GL_READ_ONLY : + var->data.image.write_only ? GL_WRITE_ONLY : + GL_READ_WRITE); + + for (unsigned j = 0; j < MAX2(1, storage->array_elements); ++j) + sh->ImageAccess[index + j] = access; + } + } + } +} + void link_assign_uniform_locations(struct gl_shader_program *prog) { @@ -665,6 +799,10 @@ link_assign_uniform_locations(struct gl_shader_program *prog) prog->UniformStorage = NULL; prog->NumUserUniformStorage = 0; + ralloc_free(prog->UniformRemapTable); + prog->UniformRemapTable = NULL; + prog->NumUniformRemapTable = 0; + if (prog->UniformHash != NULL) { prog->UniformHash->clear(); } else { @@ -679,7 +817,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog) * glGetUniformLocation. */ count_uniform_size uniform_size(prog->UniformHash); - for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { struct gl_shader *sh = prog->_LinkedShaders[i]; if (sh == NULL) @@ -695,6 +833,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog) * types cannot have initializers." */ memset(sh->SamplerUnits, 0, sizeof(sh->SamplerUnits)); + memset(sh->ImageUnits, 0, sizeof(sh->ImageUnits)); link_update_uniform_buffer_variables(sh); @@ -705,7 +844,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog) foreach_list(node, sh->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != ir_var_uniform)) + if ((var == NULL) || (var->data.mode != ir_var_uniform)) continue; /* FINISHME: Update code to process built-in uniforms! @@ -720,6 +859,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog) } sh->num_samplers = uniform_size.num_shader_samplers; + sh->NumImages = uniform_size.num_shader_images; sh->num_uniform_components = uniform_size.num_shader_uniform_components; sh->num_combined_uniform_components = sh->num_uniform_components; @@ -747,16 +887,16 @@ link_assign_uniform_locations(struct gl_shader_program *prog) parcel_out_uniform_storage parcel(prog->UniformHash, uniforms, data); - for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { if (prog->_LinkedShaders[i] == NULL) continue; - parcel.start_shader((gl_shader_type)i); + parcel.start_shader((gl_shader_stage)i); foreach_list(node, prog->_LinkedShaders[i]->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != ir_var_uniform)) + if ((var == NULL) || (var->data.mode != ir_var_uniform)) continue; /* FINISHME: Update code to process built-in uniforms! @@ -775,19 +915,28 @@ link_assign_uniform_locations(struct gl_shader_program *prog) sizeof(prog->_LinkedShaders[i]->SamplerTargets)); } - /* Determine the size of the largest uniform array queryable via - * glGetUniformLocation. Using this as the location scale guarantees that - * there is enough "room" for the array index to be stored in the low order - * part of the uniform location. It also makes the locations be more - * tightly packed. - */ - unsigned max_array_size = 1; + /* Build the uniform remap table that is used to set/get uniform locations */ for (unsigned i = 0; i < num_user_uniforms; i++) { - if (uniforms[i].array_elements > max_array_size) - max_array_size = uniforms[i].array_elements; - } - prog->UniformLocationBaseScale = max_array_size; + /* how many new entries for this uniform? */ + const unsigned entries = MAX2(1, uniforms[i].array_elements); + + /* resize remap table to fit new entries */ + prog->UniformRemapTable = + reralloc(prog, + prog->UniformRemapTable, + gl_uniform_storage *, + prog->NumUniformRemapTable + entries); + + /* set pointers for this uniform */ + for (unsigned j = 0; j < entries; j++) + prog->UniformRemapTable[prog->NumUniformRemapTable+j] = &uniforms[i]; + + /* set the base location in remap table for the uniform */ + uniforms[i].remap_location = prog->NumUniformRemapTable; + + prog->NumUniformRemapTable += entries; + } #ifndef NDEBUG for (unsigned i = 0; i < num_user_uniforms; i++) { @@ -800,6 +949,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog) prog->NumUserUniformStorage = num_user_uniforms; prog->UniformStorage = uniforms; + link_set_image_access_qualifiers(prog); link_set_uniform_initializers(prog); return; diff --git a/dist/Mesa/src/glsl/link_varyings.cpp b/dist/Mesa/src/glsl/link_varyings.cpp index 51cbdaa0e..ac38a2f31 100644 --- a/dist/Mesa/src/glsl/link_varyings.cpp +++ b/dist/Mesa/src/glsl/link_varyings.cpp @@ -41,118 +41,232 @@ /** + * Validate the types and qualifiers of an output from one stage against the + * matching input to another stage. + */ +static void +cross_validate_types_and_qualifiers(struct gl_shader_program *prog, + const ir_variable *input, + const ir_variable *output, + gl_shader_stage consumer_stage, + gl_shader_stage producer_stage) +{ + /* Check that the types match between stages. + */ + const glsl_type *type_to_match = input->type; + if (consumer_stage == MESA_SHADER_GEOMETRY) { + assert(type_to_match->is_array()); /* Enforced by ast_to_hir */ + type_to_match = type_to_match->element_type(); + } + if (type_to_match != output->type) { + /* There is a bit of a special case for gl_TexCoord. This + * built-in is unsized by default. Applications that variable + * access it must redeclare it with a size. There is some + * language in the GLSL spec that implies the fragment shader + * and vertex shader do not have to agree on this size. Other + * driver behave this way, and one or two applications seem to + * rely on it. + * + * Neither declaration needs to be modified here because the array + * sizes are fixed later when update_array_sizes is called. + * + * From page 48 (page 54 of the PDF) of the GLSL 1.10 spec: + * + * "Unlike user-defined varying variables, the built-in + * varying variables don't have a strict one-to-one + * correspondence between the vertex language and the + * fragment language." + */ + if (!output->type->is_array() + || (strncmp("gl_", output->name, 3) != 0)) { + linker_error(prog, + "%s shader output `%s' declared as type `%s', " + "but %s shader input declared as type `%s'\n", + _mesa_shader_stage_to_string(producer_stage), + output->name, + output->type->name, + _mesa_shader_stage_to_string(consumer_stage), + input->type->name); + return; + } + } + + /* Check that all of the qualifiers match between stages. + */ + if (input->data.centroid != output->data.centroid) { + linker_error(prog, + "%s shader output `%s' %s centroid qualifier, " + "but %s shader input %s centroid qualifier\n", + _mesa_shader_stage_to_string(producer_stage), + output->name, + (output->data.centroid) ? "has" : "lacks", + _mesa_shader_stage_to_string(consumer_stage), + (input->data.centroid) ? "has" : "lacks"); + return; + } + + if (input->data.sample != output->data.sample) { + linker_error(prog, + "%s shader output `%s' %s sample qualifier, " + "but %s shader input %s sample qualifier\n", + _mesa_shader_stage_to_string(producer_stage), + output->name, + (output->data.sample) ? "has" : "lacks", + _mesa_shader_stage_to_string(consumer_stage), + (input->data.sample) ? "has" : "lacks"); + return; + } + + if (input->data.invariant != output->data.invariant) { + linker_error(prog, + "%s shader output `%s' %s invariant qualifier, " + "but %s shader input %s invariant qualifier\n", + _mesa_shader_stage_to_string(producer_stage), + output->name, + (output->data.invariant) ? "has" : "lacks", + _mesa_shader_stage_to_string(consumer_stage), + (input->data.invariant) ? "has" : "lacks"); + return; + } + + if (input->data.interpolation != output->data.interpolation) { + linker_error(prog, + "%s shader output `%s' specifies %s " + "interpolation qualifier, " + "but %s shader input specifies %s " + "interpolation qualifier\n", + _mesa_shader_stage_to_string(producer_stage), + output->name, + interpolation_string(output->data.interpolation), + _mesa_shader_stage_to_string(consumer_stage), + interpolation_string(input->data.interpolation)); + return; + } +} + +/** + * Validate front and back color outputs against single color input + */ +static void +cross_validate_front_and_back_color(struct gl_shader_program *prog, + const ir_variable *input, + const ir_variable *front_color, + const ir_variable *back_color, + gl_shader_stage consumer_stage, + gl_shader_stage producer_stage) +{ + if (front_color != NULL && front_color->data.assigned) + cross_validate_types_and_qualifiers(prog, input, front_color, + consumer_stage, producer_stage); + + if (back_color != NULL && back_color->data.assigned) + cross_validate_types_and_qualifiers(prog, input, back_color, + consumer_stage, producer_stage); +} + +/** * Validate that outputs from one stage match inputs of another */ -bool +void cross_validate_outputs_to_inputs(struct gl_shader_program *prog, gl_shader *producer, gl_shader *consumer) { glsl_symbol_table parameters; - const char *const producer_stage = - _mesa_glsl_shader_target_name(producer->Type); - const char *const consumer_stage = - _mesa_glsl_shader_target_name(consumer->Type); + ir_variable *explicit_locations[MAX_VARYING] = { NULL, }; /* Find all shader outputs in the "producer" stage. */ foreach_list(node, producer->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != ir_var_shader_out)) + if ((var == NULL) || (var->data.mode != ir_var_shader_out)) continue; - parameters.add_variable(var); + if (!var->data.explicit_location + || var->data.location < VARYING_SLOT_VAR0) + parameters.add_variable(var); + else { + /* User-defined varyings with explicit locations are handled + * differently because they do not need to have matching names. + */ + const unsigned idx = var->data.location - VARYING_SLOT_VAR0; + + if (explicit_locations[idx] != NULL) { + linker_error(prog, + "%s shader has multiple outputs explicitly " + "assigned to location %d\n", + _mesa_shader_stage_to_string(producer->Stage), + idx); + return; + } + + explicit_locations[idx] = var; + } } /* Find all shader inputs in the "consumer" stage. Any variables that have * matching outputs already in the symbol table must have the same type and * qualifiers. + * + * Exception: if the consumer is the geometry shader, then the inputs + * should be arrays and the type of the array element should match the type + * of the corresponding producer output. */ foreach_list(node, consumer->ir) { ir_variable *const input = ((ir_instruction *) node)->as_variable(); - if ((input == NULL) || (input->mode != ir_var_shader_in)) + if ((input == NULL) || (input->data.mode != ir_var_shader_in)) continue; - ir_variable *const output = parameters.get_variable(input->name); - if (output != NULL) { - /* Check that the types match between stages. - */ - if (input->type != output->type) { - /* There is a bit of a special case for gl_TexCoord. This - * built-in is unsized by default. Applications that variable - * access it must redeclare it with a size. There is some - * language in the GLSL spec that implies the fragment shader - * and vertex shader do not have to agree on this size. Other - * driver behave this way, and one or two applications seem to - * rely on it. - * - * Neither declaration needs to be modified here because the array - * sizes are fixed later when update_array_sizes is called. - * - * From page 48 (page 54 of the PDF) of the GLSL 1.10 spec: - * - * "Unlike user-defined varying variables, the built-in - * varying variables don't have a strict one-to-one - * correspondence between the vertex language and the - * fragment language." - */ - if (!output->type->is_array() - || (strncmp("gl_", output->name, 3) != 0)) { - linker_error(prog, - "%s shader output `%s' declared as type `%s', " - "but %s shader input declared as type `%s'\n", - producer_stage, output->name, - output->type->name, - consumer_stage, input->type->name); - return false; - } - } - - /* Check that all of the qualifiers match between stages. - */ - if (input->centroid != output->centroid) { - linker_error(prog, - "%s shader output `%s' %s centroid qualifier, " - "but %s shader input %s centroid qualifier\n", - producer_stage, - output->name, - (output->centroid) ? "has" : "lacks", - consumer_stage, - (input->centroid) ? "has" : "lacks"); - return false; - } - - if (input->invariant != output->invariant) { - linker_error(prog, - "%s shader output `%s' %s invariant qualifier, " - "but %s shader input %s invariant qualifier\n", - producer_stage, - output->name, - (output->invariant) ? "has" : "lacks", - consumer_stage, - (input->invariant) ? "has" : "lacks"); - return false; - } - - if (input->interpolation != output->interpolation) { - linker_error(prog, - "%s shader output `%s' specifies %s " - "interpolation qualifier, " - "but %s shader input specifies %s " - "interpolation qualifier\n", - producer_stage, - output->name, - output->interpolation_string(), - consumer_stage, - input->interpolation_string()); - return false; - } + if (strcmp(input->name, "gl_Color") == 0 && input->data.used) { + const ir_variable *const front_color = + parameters.get_variable("gl_FrontColor"); + + const ir_variable *const back_color = + parameters.get_variable("gl_BackColor"); + + cross_validate_front_and_back_color(prog, input, + front_color, back_color, + consumer->Stage, producer->Stage); + } else if (strcmp(input->name, "gl_SecondaryColor") == 0 && input->data.used) { + const ir_variable *const front_color = + parameters.get_variable("gl_FrontSecondaryColor"); + + const ir_variable *const back_color = + parameters.get_variable("gl_BackSecondaryColor"); + + cross_validate_front_and_back_color(prog, input, + front_color, back_color, + consumer->Stage, producer->Stage); + } else { + /* The rules for connecting inputs and outputs change in the presence + * of explicit locations. In this case, we no longer care about the + * names of the variables. Instead, we care only about the + * explicitly assigned location. + */ + ir_variable *output = NULL; + if (input->data.explicit_location + && input->data.location >= VARYING_SLOT_VAR0) { + output = explicit_locations[input->data.location - VARYING_SLOT_VAR0]; + + if (output == NULL) { + linker_error(prog, + "%s shader input `%s' with explicit location " + "has no matching output\n", + _mesa_shader_stage_to_string(consumer->Stage), + input->name); + } + } else { + output = parameters.get_variable(input->name); + } + + if (output != NULL) { + cross_validate_types_and_qualifiers(prog, input, output, + consumer->Stage, producer->Stage); + } } } - - return true; } @@ -165,8 +279,8 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog, * will fail to find any matching variable. */ void -tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog, - const void *mem_ctx, const char *input) +tfeedback_decl::init(struct gl_context *ctx, const void *mem_ctx, + const char *input) { /* We don't have to be pedantic about what is a valid GLSL variable name, * because any variable with an invalid name can't exist in the IR anyway. @@ -255,8 +369,8 @@ tfeedback_decl::assign_location(struct gl_context *ctx, assert(this->is_varying()); unsigned fine_location - = this->matched_candidate->toplevel_var->location * 4 - + this->matched_candidate->toplevel_var->location_frac + = this->matched_candidate->toplevel_var->data.location * 4 + + this->matched_candidate->toplevel_var->data.location_frac + this->matched_candidate->offset; if (this->matched_candidate->type->is_array()) { @@ -266,7 +380,7 @@ tfeedback_decl::assign_location(struct gl_context *ctx, const unsigned vector_elements = this->matched_candidate->type->fields.array->vector_elements; unsigned actual_array_size = this->is_clip_distance_mesa ? - prog->Vert.ClipDistanceArraySize : + prog->LastClipDistanceArraySize : this->matched_candidate->type->array_size(); if (this->is_subscripted) { @@ -436,7 +550,7 @@ parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog, char **varying_names, tfeedback_decl *decls) { for (unsigned i = 0; i < num_names; ++i) { - decls[i].init(ctx, prog, mem_ctx, varying_names[i]); + decls[i].init(ctx, mem_ctx, varying_names[i]); if (!decls[i].is_varying()) continue; @@ -535,6 +649,7 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog, return true; } +namespace { /** * Data structure recording the relationship between outputs of one shader @@ -547,7 +662,7 @@ public: ~varying_matches(); void record(ir_variable *producer_var, ir_variable *consumer_var); unsigned assign_locations(); - void store_locations(unsigned producer_base, unsigned consumer_base) const; + void store_locations() const; private: /** @@ -573,8 +688,8 @@ private: PACKING_ORDER_VEC3, }; - static unsigned compute_packing_class(ir_variable *var); - static packing_order_enum compute_packing_order(ir_variable *var); + static unsigned compute_packing_class(const ir_variable *var); + static packing_order_enum compute_packing_order(const ir_variable *var); static int match_comparator(const void *x_generic, const void *y_generic); /** @@ -627,6 +742,7 @@ private: const bool consumer_is_fs; }; +} /* anonymous namespace */ varying_matches::varying_matches(bool disable_varying_packing, bool consumer_is_fs) @@ -670,7 +786,10 @@ varying_matches::~varying_matches() void varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var) { - if (!producer_var->is_unmatched_generic_inout) { + assert(producer_var != NULL || consumer_var != NULL); + + if ((producer_var && !producer_var->data.is_unmatched_generic_inout) + || (consumer_var && !consumer_var->data.is_unmatched_generic_inout)) { /* Either a location already exists for this variable (since it is part * of fixed functionality), or it has already been recorded as part of a * previous match. @@ -688,12 +807,14 @@ varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var) * regardless of where they appear. We can trivially satisfy that * requirement by changing the interpolation type to flat here. */ - producer_var->centroid = false; - producer_var->interpolation = INTERP_QUALIFIER_FLAT; + producer_var->data.centroid = false; + producer_var->data.sample = false; + producer_var->data.interpolation = INTERP_QUALIFIER_FLAT; if (consumer_var) { - consumer_var->centroid = false; - consumer_var->interpolation = INTERP_QUALIFIER_FLAT; + consumer_var->data.centroid = false; + consumer_var->data.sample = false; + consumer_var->data.interpolation = INTERP_QUALIFIER_FLAT; } } @@ -703,26 +824,30 @@ varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var) realloc(this->matches, sizeof(*this->matches) * this->matches_capacity); } + + const ir_variable *const var = (producer_var != NULL) + ? producer_var : consumer_var; + this->matches[this->num_matches].packing_class - = this->compute_packing_class(producer_var); + = this->compute_packing_class(var); this->matches[this->num_matches].packing_order - = this->compute_packing_order(producer_var); + = this->compute_packing_order(var); if (this->disable_varying_packing) { - unsigned slots = producer_var->type->is_array() - ? (producer_var->type->length - * producer_var->type->fields.array->matrix_columns) - : producer_var->type->matrix_columns; + unsigned slots = var->type->is_array() + ? (var->type->length * var->type->fields.array->matrix_columns) + : var->type->matrix_columns; this->matches[this->num_matches].num_components = 4 * slots; } else { this->matches[this->num_matches].num_components - = producer_var->type->component_slots(); + = var->type->component_slots(); } this->matches[this->num_matches].producer_var = producer_var; this->matches[this->num_matches].consumer_var = consumer_var; this->num_matches++; - producer_var->is_unmatched_generic_inout = 0; + if (producer_var) + producer_var->data.is_unmatched_generic_inout = 0; if (consumer_var) - consumer_var->is_unmatched_generic_inout = 0; + consumer_var->data.is_unmatched_generic_inout = 0; } @@ -764,8 +889,7 @@ varying_matches::assign_locations() * assignments that were made by varying_matches::assign_locations(). */ void -varying_matches::store_locations(unsigned producer_base, - unsigned consumer_base) const +varying_matches::store_locations() const { for (unsigned i = 0; i < this->num_matches; i++) { ir_variable *producer_var = this->matches[i].producer_var; @@ -774,12 +898,15 @@ varying_matches::store_locations(unsigned producer_base, unsigned slot = generic_location / 4; unsigned offset = generic_location % 4; - producer_var->location = producer_base + slot; - producer_var->location_frac = offset; + if (producer_var) { + producer_var->data.location = VARYING_SLOT_VAR0 + slot; + producer_var->data.location_frac = offset; + } + if (consumer_var) { - assert(consumer_var->location == -1); - consumer_var->location = consumer_base + slot; - consumer_var->location_frac = offset; + assert(consumer_var->data.location == -1); + consumer_var->data.location = VARYING_SLOT_VAR0 + slot; + consumer_var->data.location_frac = offset; } } } @@ -791,7 +918,7 @@ varying_matches::store_locations(unsigned producer_base, * be safely backed into the same vec4. */ unsigned -varying_matches::compute_packing_class(ir_variable *var) +varying_matches::compute_packing_class(const ir_variable *var) { /* Without help from the back-end, there is no way to pack together * variables with different interpolation types, because @@ -809,9 +936,9 @@ varying_matches::compute_packing_class(ir_variable *var) * * Therefore, the packing class depends only on the interpolation type. */ - unsigned packing_class = var->centroid ? 1 : 0; + unsigned packing_class = var->data.centroid | (var->data.sample << 1); packing_class *= 4; - packing_class += var->interpolation; + packing_class += var->data.interpolation; return packing_class; } @@ -822,7 +949,7 @@ varying_matches::compute_packing_class(ir_variable *var) * other varyings in the same packing class. */ varying_matches::packing_order_enum -varying_matches::compute_packing_order(ir_variable *var) +varying_matches::compute_packing_order(const ir_variable *var) { const glsl_type *element_type = var->type; @@ -865,12 +992,12 @@ varying_matches::match_comparator(const void *x_generic, const void *y_generic) * varyings, but excludes variables such as gl_FrontFacing and gl_FragCoord. */ static bool -is_varying_var(GLenum shaderType, const ir_variable *var) +is_varying_var(gl_shader_stage stage, const ir_variable *var) { /* Only fragment shaders will take a varying variable as an input */ - if (shaderType == GL_FRAGMENT_SHADER && - var->mode == ir_var_shader_in) { - switch (var->location) { + if (stage == MESA_SHADER_FRAGMENT && + var->data.mode == ir_var_shader_in) { + switch (var->data.location) { case VARYING_SLOT_POS: case VARYING_SLOT_FACE: case VARYING_SLOT_PNTC: @@ -908,8 +1035,8 @@ public: this->toplevel_var = var; this->varying_floats = 0; if (var->is_interface_instance()) - program_resource_visitor::process(var->interface_type, - var->interface_type->name); + program_resource_visitor::process(var->get_interface_type(), + var->get_interface_type()->name); else program_resource_visitor::process(var); } @@ -959,6 +1086,157 @@ private: }; +namespace linker { + +bool +populate_consumer_input_sets(void *mem_ctx, exec_list *ir, + hash_table *consumer_inputs, + hash_table *consumer_interface_inputs, + ir_variable *consumer_inputs_with_locations[VARYING_SLOT_MAX]) +{ + memset(consumer_inputs_with_locations, + 0, + sizeof(consumer_inputs_with_locations[0]) * VARYING_SLOT_MAX); + + foreach_list(node, ir) { + ir_variable *const input_var = ((ir_instruction *) node)->as_variable(); + + if ((input_var != NULL) && (input_var->data.mode == ir_var_shader_in)) { + if (input_var->type->is_interface()) + return false; + + if (input_var->data.explicit_location) { + /* assign_varying_locations only cares about finding the + * ir_variable at the start of a contiguous location block. + * + * - For !producer, consumer_inputs_with_locations isn't used. + * + * - For !consumer, consumer_inputs_with_locations is empty. + * + * For consumer && producer, if you were trying to set some + * ir_variable to the middle of a location block on the other side + * of producer/consumer, cross_validate_outputs_to_inputs() should + * be link-erroring due to either type mismatch or location + * overlaps. If the variables do match up, then they've got a + * matching data.location and you only looked at + * consumer_inputs_with_locations[var->data.location], not any + * following entries for the array/structure. + */ + consumer_inputs_with_locations[input_var->data.location] = + input_var; + } else if (input_var->get_interface_type() != NULL) { + char *const iface_field_name = + ralloc_asprintf(mem_ctx, "%s.%s", + input_var->get_interface_type()->name, + input_var->name); + hash_table_insert(consumer_interface_inputs, input_var, + iface_field_name); + } else { + hash_table_insert(consumer_inputs, input_var, + ralloc_strdup(mem_ctx, input_var->name)); + } + } + } + + return true; +} + +/** + * Find a variable from the consumer that "matches" the specified variable + * + * This function only finds inputs with names that match. There is no + * validation (here) that the types, etc. are compatible. + */ +ir_variable * +get_matching_input(void *mem_ctx, + const ir_variable *output_var, + hash_table *consumer_inputs, + hash_table *consumer_interface_inputs, + ir_variable *consumer_inputs_with_locations[VARYING_SLOT_MAX]) +{ + ir_variable *input_var; + + if (output_var->data.explicit_location) { + input_var = consumer_inputs_with_locations[output_var->data.location]; + } else if (output_var->get_interface_type() != NULL) { + char *const iface_field_name = + ralloc_asprintf(mem_ctx, "%s.%s", + output_var->get_interface_type()->name, + output_var->name); + input_var = + (ir_variable *) hash_table_find(consumer_interface_inputs, + iface_field_name); + } else { + input_var = + (ir_variable *) hash_table_find(consumer_inputs, output_var->name); + } + + return (input_var == NULL || input_var->data.mode != ir_var_shader_in) + ? NULL : input_var; +} + +} + +static int +io_variable_cmp(const void *_a, const void *_b) +{ + const ir_variable *const a = *(const ir_variable **) _a; + const ir_variable *const b = *(const ir_variable **) _b; + + if (a->data.explicit_location && b->data.explicit_location) + return b->data.location - a->data.location; + + if (a->data.explicit_location && !b->data.explicit_location) + return 1; + + if (!a->data.explicit_location && b->data.explicit_location) + return -1; + + return -strcmp(a->name, b->name); +} + +/** + * Sort the shader IO variables into canonical order + */ +static void +canonicalize_shader_io(exec_list *ir, enum ir_variable_mode io_mode) +{ + ir_variable *var_table[MAX_PROGRAM_OUTPUTS * 4]; + unsigned num_variables = 0; + + foreach_list(node, ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + if (var == NULL || var->data.mode != io_mode) + continue; + + /* If we have already encountered more I/O variables that could + * successfully link, bail. + */ + if (num_variables == ARRAY_SIZE(var_table)) + return; + + var_table[num_variables++] = var; + } + + if (num_variables == 0) + return; + + /* Sort the list in reverse order (io_variable_cmp handles this). Later + * we're going to push the variables on to the IR list as a stack, so we + * want the last variable (in canonical order) to be first in the list. + */ + qsort(var_table, num_variables, sizeof(var_table[0]), io_variable_cmp); + + /* Remove the variable from it's current location in the IR, and put it at + * the front. + */ + for (unsigned i = 0; i < num_variables; i++) { + var_table[i]->remove(); + ir->push_head(var_table[i]); + } +} + /** * Assign locations for all variables that are produced in one pipeline stage * (the "producer") and consumed in the next stage (the "consumer"). @@ -975,6 +1253,9 @@ private: * each of these objects that matches one of the outputs of the * producer. * + * \param gs_input_vertices: if \c consumer is a geometry shader, this is the + * number of input vertices it accepts. Otherwise zero. + * * When num_tfeedback_decls is nonzero, it is permissible for the consumer to * be NULL. In this case, varying locations are assigned solely based on the * requirements of transform feedback. @@ -985,79 +1266,96 @@ assign_varying_locations(struct gl_context *ctx, struct gl_shader_program *prog, gl_shader *producer, gl_shader *consumer, unsigned num_tfeedback_decls, - tfeedback_decl *tfeedback_decls) + tfeedback_decl *tfeedback_decls, + unsigned gs_input_vertices) { - const unsigned producer_base = VARYING_SLOT_VAR0; - const unsigned consumer_base = VARYING_SLOT_VAR0; varying_matches matches(ctx->Const.DisableVaryingPacking, - consumer && consumer->Type == GL_FRAGMENT_SHADER); + consumer && consumer->Stage == MESA_SHADER_FRAGMENT); hash_table *tfeedback_candidates = hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare); hash_table *consumer_inputs = hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare); hash_table *consumer_interface_inputs = hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare); + ir_variable *consumer_inputs_with_locations[VARYING_SLOT_MAX] = { + NULL, + }; - /* Operate in a total of three passes. + /* Operate in a total of four passes. * - * 1. Assign locations for any matching inputs and outputs. + * 1. Sort inputs / outputs into a canonical order. This is necessary so + * that inputs / outputs of separable shaders will be assigned + * predictable locations regardless of the order in which declarations + * appeared in the shader source. * - * 2. Mark output variables in the producer that do not have locations as + * 2. Assign locations for any matching inputs and outputs. + * + * 3. Mark output variables in the producer that do not have locations as * not being outputs. This lets the optimizer eliminate them. * - * 3. Mark input variables in the consumer that do not have locations as + * 4. Mark input variables in the consumer that do not have locations as * not being inputs. This lets the optimizer eliminate them. */ + if (consumer) + canonicalize_shader_io(consumer->ir, ir_var_shader_in); + + if (producer) + canonicalize_shader_io(producer->ir, ir_var_shader_out); + + if (consumer + && !linker::populate_consumer_input_sets(mem_ctx, + consumer->ir, + consumer_inputs, + consumer_interface_inputs, + consumer_inputs_with_locations)) { + assert(!"populate_consumer_input_sets failed"); + hash_table_dtor(tfeedback_candidates); + hash_table_dtor(consumer_inputs); + hash_table_dtor(consumer_interface_inputs); + return false; + } - if (consumer) { - foreach_list(node, consumer->ir) { - ir_variable *const input_var = + if (producer) { + foreach_list(node, producer->ir) { + ir_variable *const output_var = ((ir_instruction *) node)->as_variable(); - if ((input_var != NULL) && (input_var->mode == ir_var_shader_in)) { - if (input_var->interface_type != NULL) { - char *const iface_field_name = - ralloc_asprintf(mem_ctx, "%s.%s", - input_var->interface_type->name, - input_var->name); - hash_table_insert(consumer_interface_inputs, input_var, - iface_field_name); - } else { - hash_table_insert(consumer_inputs, input_var, - ralloc_strdup(mem_ctx, input_var->name)); - } - } - } - } + if ((output_var == NULL) || + (output_var->data.mode != ir_var_shader_out)) + continue; - foreach_list(node, producer->ir) { - ir_variable *const output_var = ((ir_instruction *) node)->as_variable(); + tfeedback_candidate_generator g(mem_ctx, tfeedback_candidates); + g.process(output_var); - if ((output_var == NULL) || (output_var->mode != ir_var_shader_out)) - continue; + ir_variable *const input_var = + linker::get_matching_input(mem_ctx, output_var, consumer_inputs, + consumer_interface_inputs, + consumer_inputs_with_locations); - tfeedback_candidate_generator g(mem_ctx, tfeedback_candidates); - g.process(output_var); - - ir_variable *input_var; - if (output_var->interface_type != NULL) { - char *const iface_field_name = - ralloc_asprintf(mem_ctx, "%s.%s", - output_var->interface_type->name, - output_var->name); - input_var = - (ir_variable *) hash_table_find(consumer_interface_inputs, - iface_field_name); - } else { - input_var = - (ir_variable *) hash_table_find(consumer_inputs, output_var->name); + /* If a matching input variable was found, add this ouptut (and the + * input) to the set. If this is a separable program and there is no + * consumer stage, add the output. + */ + if (input_var || (prog->SeparateShader && consumer == NULL)) { + matches.record(output_var, input_var); + } } + } else { + /* If there's no producer stage, then this must be a separable program. + * For example, we may have a program that has just a fragment shader. + * Later this program will be used with some arbitrary vertex (or + * geometry) shader program. This means that locations must be assigned + * for all the inputs. + */ + foreach_list(node, consumer->ir) { + ir_variable *const input_var = + ((ir_instruction *) node)->as_variable(); - if (input_var && input_var->mode != ir_var_shader_in) - input_var = NULL; + if ((input_var == NULL) || + (input_var->data.mode != ir_var_shader_in)) + continue; - if (input_var) { - matches.record(output_var, input_var); + matches.record(NULL, input_var); } } @@ -1075,12 +1373,12 @@ assign_varying_locations(struct gl_context *ctx, return false; } - if (matched_candidate->toplevel_var->is_unmatched_generic_inout) + if (matched_candidate->toplevel_var->data.is_unmatched_generic_inout) matches.record(matched_candidate->toplevel_var, NULL); } const unsigned slots_used = matches.assign_locations(); - matches.store_locations(producer_base, consumer_base); + matches.store_locations(); for (unsigned i = 0; i < num_tfeedback_decls; ++i) { if (!tfeedback_decls[i].is_varying()) @@ -1105,20 +1403,22 @@ assign_varying_locations(struct gl_context *ctx, */ assert(!ctx->Extensions.EXT_transform_feedback); } else { - lower_packed_varyings(mem_ctx, producer_base, slots_used, - ir_var_shader_out, producer); + if (producer) { + lower_packed_varyings(mem_ctx, slots_used, ir_var_shader_out, + 0, producer); + } if (consumer) { - lower_packed_varyings(mem_ctx, consumer_base, slots_used, - ir_var_shader_in, consumer); + lower_packed_varyings(mem_ctx, slots_used, ir_var_shader_in, + gs_input_vertices, consumer); } } - if (consumer) { + if (consumer && producer) { foreach_list(node, consumer->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if (var && var->mode == ir_var_shader_in && - var->is_unmatched_generic_inout) { + if (var && var->data.mode == ir_var_shader_in && + var->data.is_unmatched_generic_inout) { if (prog->Version <= 120) { /* On page 25 (page 31 of the PDF) of the GLSL 1.20 spec: * @@ -1135,15 +1435,15 @@ assign_varying_locations(struct gl_context *ctx, linker_error(prog, "%s shader varying %s not written " "by %s shader\n.", - _mesa_glsl_shader_target_name(consumer->Type), + _mesa_shader_stage_to_string(consumer->Stage), var->name, - _mesa_glsl_shader_target_name(producer->Type)); + _mesa_shader_stage_to_string(producer->Stage)); } /* An 'in' variable is only really a shader input if its * value is written by the previous stage. */ - var->mode = ir_var_auto; + var->data.mode = ir_var_auto; } } } @@ -1152,40 +1452,79 @@ assign_varying_locations(struct gl_context *ctx, } bool -check_against_varying_limit(struct gl_context *ctx, - struct gl_shader_program *prog, - gl_shader *consumer) +check_against_output_limit(struct gl_context *ctx, + struct gl_shader_program *prog, + gl_shader *producer) { - unsigned varying_vectors = 0; + unsigned output_vectors = 0; - foreach_list(node, consumer->ir) { + foreach_list(node, producer->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if (var && var->mode == ir_var_shader_in && - is_varying_var(consumer->Type, var)) { - /* The packing rules used for vertex shader inputs are also - * used for fragment shader inputs. - */ - varying_vectors += count_attribute_slots(var->type); + if (var && var->data.mode == ir_var_shader_out && + is_varying_var(producer->Stage, var)) { + output_vectors += var->type->count_attribute_slots(); } } - if (ctx->API == API_OPENGLES2 || prog->IsES) { - if (varying_vectors > ctx->Const.MaxVarying) { - linker_error(prog, "shader uses too many varying vectors " + assert(producer->Stage != MESA_SHADER_FRAGMENT); + unsigned max_output_components = + ctx->Const.Program[producer->Stage].MaxOutputComponents; + + const unsigned output_components = output_vectors * 4; + if (output_components > max_output_components) { + if (ctx->API == API_OPENGLES2 || prog->IsES) + linker_error(prog, "shader uses too many output vectors " "(%u > %u)\n", - varying_vectors, ctx->Const.MaxVarying); - return false; - } - } else { - const unsigned float_components = varying_vectors * 4; - if (float_components > ctx->Const.MaxVarying * 4) { - linker_error(prog, "shader uses too many varying components " + output_vectors, + max_output_components / 4); + else + linker_error(prog, "shader uses too many output components " "(%u > %u)\n", - float_components, ctx->Const.MaxVarying * 4); - return false; + output_components, + max_output_components); + + return false; + } + + return true; +} + +bool +check_against_input_limit(struct gl_context *ctx, + struct gl_shader_program *prog, + gl_shader *consumer) +{ + unsigned input_vectors = 0; + + foreach_list(node, consumer->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + if (var && var->data.mode == ir_var_shader_in && + is_varying_var(consumer->Stage, var)) { + input_vectors += var->type->count_attribute_slots(); } } + assert(consumer->Stage != MESA_SHADER_VERTEX); + unsigned max_input_components = + ctx->Const.Program[consumer->Stage].MaxInputComponents; + + const unsigned input_components = input_vectors * 4; + if (input_components > max_input_components) { + if (ctx->API == API_OPENGLES2 || prog->IsES) + linker_error(prog, "shader uses too many input vectors " + "(%u > %u)\n", + input_vectors, + max_input_components / 4); + else + linker_error(prog, "shader uses too many input components " + "(%u > %u)\n", + input_components, + max_input_components); + + return false; + } + return true; } diff --git a/dist/Mesa/src/glsl/link_varyings.h b/dist/Mesa/src/glsl/link_varyings.h index 7f7be353b..6fa268176 100644 --- a/dist/Mesa/src/glsl/link_varyings.h +++ b/dist/Mesa/src/glsl/link_varyings.h @@ -91,8 +91,7 @@ struct tfeedback_candidate class tfeedback_decl { public: - void init(struct gl_context *ctx, struct gl_shader_program *prog, - const void *mem_ctx, const char *input); + void init(struct gl_context *ctx, const void *mem_ctx, const char *input); static bool is_same(const tfeedback_decl &x, const tfeedback_decl &y); bool assign_location(struct gl_context *ctx, struct gl_shader_program *prog); @@ -214,7 +213,7 @@ private: }; -bool +void cross_validate_outputs_to_inputs(struct gl_shader_program *prog, gl_shader *producer, gl_shader *consumer); @@ -234,11 +233,17 @@ assign_varying_locations(struct gl_context *ctx, struct gl_shader_program *prog, gl_shader *producer, gl_shader *consumer, unsigned num_tfeedback_decls, - tfeedback_decl *tfeedback_decls); + tfeedback_decl *tfeedback_decls, + unsigned gs_input_vertices); + +bool +check_against_output_limit(struct gl_context *ctx, + struct gl_shader_program *prog, + gl_shader *producer); bool -check_against_varying_limit(struct gl_context *ctx, - struct gl_shader_program *prog, - gl_shader *consumer); +check_against_input_limit(struct gl_context *ctx, + struct gl_shader_program *prog, + gl_shader *consumer); #endif /* GLSL_LINK_VARYINGS_H */ diff --git a/dist/Mesa/src/glsl/list.h b/dist/Mesa/src/glsl/list.h index 1d46365fa..694b686b0 100644 --- a/dist/Mesa/src/glsl/list.h +++ b/dist/Mesa/src/glsl/list.h @@ -76,24 +76,7 @@ struct exec_node { struct exec_node *prev; #ifdef __cplusplus - /* Callers of this ralloc-based new need not call delete. It's - * easier to just ralloc_free 'ctx' (or any of its ancestors). */ - static void* operator new(size_t size, void *ctx) - { - void *node; - - node = ralloc_size(ctx, size); - assert(node != NULL); - - return node; - } - - /* If the user *does* call delete, that's OK, we will just - * ralloc_free in that case. */ - static void operator delete(void *node) - { - ralloc_free(node); - } + DECLARE_RALLOC_CXX_OPERATORS(exec_node) exec_node() : next(NULL), prev(NULL) { @@ -223,86 +206,15 @@ struct exec_node { #ifdef __cplusplus struct exec_node; - -class iterator { -public: - void next() - { - } - - void *get() - { - return NULL; - } - - bool has_next() const - { - return false; - } -}; - -class exec_list_iterator : public iterator { -public: - exec_list_iterator(exec_node *n) : node(n), _next(n->next) - { - /* empty */ - } - - void next() - { - node = _next; - _next = node->next; - } - - void remove() - { - node->remove(); - } - - exec_node *get() - { - return node; - } - - bool has_next() const - { - return _next != NULL; - } - -private: - exec_node *node; - exec_node *_next; -}; - -#define foreach_iter(iter_type, iter, container) \ - for (iter_type iter = (container) . iterator(); iter.has_next(); iter.next()) #endif - struct exec_list { struct exec_node *head; struct exec_node *tail; struct exec_node *tail_pred; #ifdef __cplusplus - /* Callers of this ralloc-based new need not call delete. It's - * easier to just ralloc_free 'ctx' (or any of its ancestors). */ - static void* operator new(size_t size, void *ctx) - { - void *node; - - node = ralloc_size(ctx, size); - assert(node != NULL); - - return node; - } - - /* If the user *does* call delete, that's OK, we will just - * ralloc_free in that case. */ - static void operator delete(void *node) - { - ralloc_free(node); - } + DECLARE_RALLOC_CXX_OPERATORS(exec_list) exec_list() { @@ -438,16 +350,6 @@ struct exec_list { */ source->make_empty(); } - - exec_list_iterator iterator() - { - return exec_list_iterator(head); - } - - exec_list_iterator iterator() const - { - return exec_list_iterator((exec_node *) head); - } #endif }; @@ -481,6 +383,22 @@ inline void exec_node::insert_before(exec_list *before) ; (__node)->next != NULL \ ; (__node) = (__node)->next) +/** + * Iterate through two lists at once. Stops at the end of the shorter list. + * + * This is safe against either current node being removed or replaced. + */ +#define foreach_two_lists(__node1, __list1, __node2, __list2) \ + for (exec_node * __node1 = (__list1)->head, \ + * __node2 = (__list2)->head, \ + * __next1 = __node1->next, \ + * __next2 = __node2->next \ + ; __next1 != NULL && __next2 != NULL \ + ; __node1 = __next1, \ + __node2 = __next2, \ + __next1 = __next1->next, \ + __next2 = __next2->next) + #define foreach_list_const(__node, __list) \ for (const exec_node * __node = (__list)->head \ ; (__node)->next != NULL \ diff --git a/dist/Mesa/src/glsl/loop_controls.cpp b/dist/Mesa/src/glsl/loop_controls.cpp index 79c820436..3db06ad18 100644 --- a/dist/Mesa/src/glsl/loop_controls.cpp +++ b/dist/Mesa/src/glsl/loop_controls.cpp @@ -151,6 +151,7 @@ calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment, return (valid_loop) ? iter_value : -1; } +namespace { class loop_control_visitor : public ir_hierarchical_visitor { public: @@ -167,6 +168,7 @@ public: bool progress; }; +} /* anonymous namespace */ ir_visitor_status loop_control_visitor::visit_leave(ir_loop *ir) @@ -181,114 +183,41 @@ loop_control_visitor::visit_leave(ir_loop *ir) return visit_continue; } - /* Search the loop terminating conditions for one of the form 'i < c' where - * i is a loop induction variable, c is a constant, and < is any relative - * operator. - */ - int max_iterations = ls->max_iterations; - - if(ir->from && ir->to && ir->increment) - max_iterations = calculate_iterations(ir->from, ir->to, ir->increment, (ir_expression_operation)ir->cmp); - - if(max_iterations < 0) - max_iterations = INT_MAX; + if (ls->limiting_terminator != NULL) { + /* If the limiting terminator has an iteration count of zero, then we've + * proven that the loop cannot run, so delete it. + */ + int iterations = ls->limiting_terminator->iterations; + if (iterations == 0) { + ir->remove(); + this->progress = true; + return visit_continue; + } + } + /* Remove the conditional break statements associated with all terminators + * that are associated with a fixed iteration count, except for the one + * associated with the limiting terminator--that one needs to stay, since + * it terminates the loop. Exception: if the loop still has a normative + * bound, then that terminates the loop, so we don't even need the limiting + * terminator. + */ foreach_list(node, &ls->terminators) { loop_terminator *t = (loop_terminator *) node; - ir_if *if_stmt = t->ir; - /* If-statements can be either 'if (expr)' or 'if (deref)'. We only care - * about the former here. - */ - ir_expression *cond = if_stmt->condition->as_expression(); - if (cond == NULL) - continue; - - switch (cond->operation) { - case ir_binop_less: - case ir_binop_greater: - case ir_binop_lequal: - case ir_binop_gequal: { - /* The expressions that we care about will either be of the form - * 'counter < limit' or 'limit < counter'. Figure out which is - * which. - */ - ir_rvalue *counter = cond->operands[0]->as_dereference_variable(); - ir_constant *limit = cond->operands[1]->as_constant(); - enum ir_expression_operation cmp = cond->operation; - - if (limit == NULL) { - counter = cond->operands[1]->as_dereference_variable(); - limit = cond->operands[0]->as_constant(); - - switch (cmp) { - case ir_binop_less: cmp = ir_binop_greater; break; - case ir_binop_greater: cmp = ir_binop_less; break; - case ir_binop_lequal: cmp = ir_binop_gequal; break; - case ir_binop_gequal: cmp = ir_binop_lequal; break; - default: assert(!"Should not get here."); - } - } - - if ((counter == NULL) || (limit == NULL)) - break; - - ir_variable *var = counter->variable_referenced(); - - ir_rvalue *init = find_initial_value(ir, var); - - foreach_list(iv_node, &ls->induction_variables) { - loop_variable *lv = (loop_variable *) iv_node; - - if (lv->var == var) { - const int iterations = calculate_iterations(init, limit, - lv->increment, - cmp); - if (iterations >= 0) { - /* If the new iteration count is lower than the previously - * believed iteration count, update the loop control values. - */ - if (iterations < max_iterations) { - ir->from = init->clone(ir, NULL); - ir->to = limit->clone(ir, NULL); - ir->increment = lv->increment->clone(ir, NULL); - ir->counter = lv->var; - ir->cmp = cmp; - - max_iterations = iterations; - } - - /* Remove the conditional break statement. The loop - * controls are now set such that the exit condition will be - * satisfied. - */ - if_stmt->remove(); - - assert(ls->num_loop_jumps > 0); - ls->num_loop_jumps--; - - this->progress = true; - } - - break; - } - } - break; - } + if (t->iterations < 0) + continue; - default: - break; + if (t != ls->limiting_terminator) { + t->ir->remove(); + + assert(ls->num_loop_jumps > 0); + ls->num_loop_jumps--; + + this->progress = true; } } - /* If we have proven the one of the loop exit conditions is satisifed before - * running the loop once, remove the loop. - */ - if (max_iterations == 0) - ir->remove(); - else - ls->max_iterations = max_iterations; - return visit_continue; } diff --git a/dist/Mesa/src/glsl/loop_unroll.cpp b/dist/Mesa/src/glsl/loop_unroll.cpp index 3434fde62..da532804a 100644 --- a/dist/Mesa/src/glsl/loop_unroll.cpp +++ b/dist/Mesa/src/glsl/loop_unroll.cpp @@ -25,23 +25,33 @@ #include "loop_analysis.h" #include "ir_hierarchical_visitor.h" +#include "main/mtypes.h" + +namespace { + class loop_unroll_visitor : public ir_hierarchical_visitor { public: - loop_unroll_visitor(loop_state *state, unsigned max_iterations) + loop_unroll_visitor(loop_state *state, + const struct gl_shader_compiler_options *options) { this->state = state; this->progress = false; - this->max_iterations = max_iterations; + this->options = options; } virtual ir_visitor_status visit_leave(ir_loop *ir); + void simple_unroll(ir_loop *ir, int iterations); + void complex_unroll(ir_loop *ir, int iterations, + bool continue_from_then_branch); + void splice_post_if_instructions(ir_if *ir_if, exec_list *splice_dest); loop_state *state; bool progress; - unsigned max_iterations; + const struct gl_shader_compiler_options *options; }; +} /* anonymous namespace */ static bool is_break(ir_instruction *ir) @@ -53,36 +63,221 @@ is_break(ir_instruction *ir) class loop_unroll_count : public ir_hierarchical_visitor { public: int nodes; - bool fail; + bool unsupported_variable_indexing; + /* If there are nested loops, the node count will be inaccurate. */ + bool nested_loop; - loop_unroll_count(exec_list *list) + loop_unroll_count(exec_list *list, loop_variable_state *ls, + const struct gl_shader_compiler_options *options) + : ls(ls), options(options) { nodes = 0; - fail = false; + nested_loop = false; + unsupported_variable_indexing = false; run(list); } - virtual ir_visitor_status visit_enter(ir_assignment *ir) + virtual ir_visitor_status visit_enter(ir_assignment *) { nodes++; return visit_continue; } - virtual ir_visitor_status visit_enter(ir_expression *ir) + virtual ir_visitor_status visit_enter(ir_expression *) { nodes++; return visit_continue; } - virtual ir_visitor_status visit_enter(ir_loop *ir) + virtual ir_visitor_status visit_enter(ir_loop *) { - fail = true; + nested_loop = true; return visit_continue; } + + virtual ir_visitor_status visit_enter(ir_dereference_array *ir) + { + /* Check for arrays variably-indexed by a loop induction variable. + * Unrolling the loop may convert that access into constant-indexing. + * + * Many drivers don't support particular kinds of variable indexing, + * and have to resort to using lower_variable_index_to_cond_assign to + * handle it. This results in huge amounts of horrible code, so we'd + * like to avoid that if possible. Here, we just note that it will + * happen. + */ + if ((ir->array->type->is_array() || ir->array->type->is_matrix()) && + !ir->array_index->as_constant()) { + ir_variable *array = ir->array->variable_referenced(); + loop_variable *lv = ls->get(ir->array_index->variable_referenced()); + if (array && lv && lv->is_induction_var()) { + switch (array->data.mode) { + case ir_var_auto: + case ir_var_temporary: + case ir_var_const_in: + case ir_var_function_in: + case ir_var_function_out: + case ir_var_function_inout: + if (options->EmitNoIndirectTemp) + unsupported_variable_indexing = true; + break; + case ir_var_uniform: + if (options->EmitNoIndirectUniform) + unsupported_variable_indexing = true; + break; + case ir_var_shader_in: + if (options->EmitNoIndirectInput) + unsupported_variable_indexing = true; + break; + case ir_var_shader_out: + if (options->EmitNoIndirectOutput) + unsupported_variable_indexing = true; + break; + } + } + } + return visit_continue; + } + +private: + loop_variable_state *ls; + const struct gl_shader_compiler_options *options; }; +/** + * Unroll a loop which does not contain any jumps. For example, if the input + * is: + * + * (loop (...) ...instrs...) + * + * And the iteration count is 3, the output will be: + * + * ...instrs... ...instrs... ...instrs... + */ +void +loop_unroll_visitor::simple_unroll(ir_loop *ir, int iterations) +{ + void *const mem_ctx = ralloc_parent(ir); + + for (int i = 0; i < iterations; i++) { + exec_list copy_list; + + copy_list.make_empty(); + clone_ir_list(mem_ctx, ©_list, &ir->body_instructions); + + ir->insert_before(©_list); + } + + /* The loop has been replaced by the unrolled copies. Remove the original + * loop from the IR sequence. + */ + ir->remove(); + + this->progress = true; +} + + +/** + * Unroll a loop whose last statement is an ir_if. If \c + * continue_from_then_branch is true, the loop is repeated only when the + * "then" branch of the if is taken; otherwise it is repeated only when the + * "else" branch of the if is taken. + * + * For example, if the input is: + * + * (loop (...) + * ...body... + * (if (cond) + * (...then_instrs...) + * (...else_instrs...))) + * + * And the iteration count is 3, and \c continue_from_then_branch is true, + * then the output will be: + * + * ...body... + * (if (cond) + * (...then_instrs... + * ...body... + * (if (cond) + * (...then_instrs... + * ...body... + * (if (cond) + * (...then_instrs...) + * (...else_instrs...))) + * (...else_instrs...))) + * (...else_instrs)) + */ +void +loop_unroll_visitor::complex_unroll(ir_loop *ir, int iterations, + bool continue_from_then_branch) +{ + void *const mem_ctx = ralloc_parent(ir); + ir_instruction *ir_to_replace = ir; + + for (int i = 0; i < iterations; i++) { + exec_list copy_list; + + copy_list.make_empty(); + clone_ir_list(mem_ctx, ©_list, &ir->body_instructions); + + ir_if *ir_if = ((ir_instruction *) copy_list.get_tail())->as_if(); + assert(ir_if != NULL); + + ir_to_replace->insert_before(©_list); + ir_to_replace->remove(); + + /* placeholder that will be removed in the next iteration */ + ir_to_replace = + new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_continue); + + exec_list *const list = (continue_from_then_branch) + ? &ir_if->then_instructions : &ir_if->else_instructions; + + list->push_tail(ir_to_replace); + } + + ir_to_replace->remove(); + + this->progress = true; +} + + +/** + * Move all of the instructions which follow \c ir_if to the end of + * \c splice_dest. + * + * For example, in the code snippet: + * + * (if (cond) + * (...then_instructions... + * break) + * (...else_instructions...)) + * ...post_if_instructions... + * + * If \c ir_if points to the "if" instruction, and \c splice_dest points to + * (...else_instructions...), the code snippet is transformed into: + * + * (if (cond) + * (...then_instructions... + * break) + * (...else_instructions... + * ...post_if_instructions...)) + */ +void +loop_unroll_visitor::splice_post_if_instructions(ir_if *ir_if, + exec_list *splice_dest) +{ + while (!ir_if->get_next()->is_tail_sentinel()) { + ir_instruction *move_ir = (ir_instruction *) ir_if->get_next(); + + move_ir->remove(); + splice_dest->push_tail(move_ir); + } +} + + ir_visitor_status loop_unroll_visitor::visit_leave(ir_loop *ir) { @@ -97,155 +292,117 @@ loop_unroll_visitor::visit_leave(ir_loop *ir) return visit_continue; } - iterations = ls->max_iterations; - /* Don't try to unroll loops where the number of iterations is not known * at compile-time. */ - if (iterations < 0) + if (ls->limiting_terminator == NULL) return visit_continue; + iterations = ls->limiting_terminator->iterations; + + const int max_iterations = options->MaxUnrollIterations; + /* Don't try to unroll loops that have zillions of iterations either. */ - if (iterations > (int) max_iterations) + if (iterations > max_iterations) return visit_continue; /* Don't try to unroll nested loops and loops with a huge body. */ - loop_unroll_count count(&ir->body_instructions); + loop_unroll_count count(&ir->body_instructions, ls, options); - if (count.fail || count.nodes * iterations > (int)max_iterations * 5) - return visit_continue; + bool loop_too_large = + count.nested_loop || count.nodes * iterations > max_iterations * 5; - if (ls->num_loop_jumps > 1) + if (loop_too_large && !count.unsupported_variable_indexing) return visit_continue; - else if (ls->num_loop_jumps) { - ir_instruction *last_ir = (ir_instruction *) ir->body_instructions.get_tail(); - assert(last_ir != NULL); - - if (is_break(last_ir)) { - /* If the only loop-jump is a break at the end of the loop, the loop - * will execute exactly once. Remove the break, set the iteration - * count, and fall through to the normal unroller. - */ - last_ir->remove(); - iterations = 1; - - this->progress = true; - } else { - ir_if *ir_if = NULL; - ir_instruction *break_ir = NULL; - bool continue_from_then_branch = false; - - foreach_list(node, &ir->body_instructions) { - /* recognize loops in the form produced by ir_lower_jumps */ - ir_instruction *cur_ir = (ir_instruction *) node; - - ir_if = cur_ir->as_if(); - if (ir_if != NULL) { - /* Determine which if-statement branch, if any, ends with a - * break. The branch that did *not* have the break will get a - * temporary continue inserted in each iteration of the loop - * unroll. - * - * Note that since ls->num_loop_jumps is <= 1, it is impossible - * for both branches to end with a break. - */ - ir_instruction *ir_if_last = - (ir_instruction *) ir_if->then_instructions.get_tail(); - - if (is_break(ir_if_last)) { - continue_from_then_branch = false; - break_ir = ir_if_last; - break; - } else { - ir_if_last = - (ir_instruction *) ir_if->else_instructions.get_tail(); - - if (is_break(ir_if_last)) { - break_ir = ir_if_last; - continue_from_then_branch = true; - break; - } - } - } - } - - if (break_ir == NULL) - return visit_continue; - - /* move instructions after then if in the continue branch */ - while (!ir_if->get_next()->is_tail_sentinel()) { - ir_instruction *move_ir = (ir_instruction *) ir_if->get_next(); - - move_ir->remove(); - if (continue_from_then_branch) - ir_if->then_instructions.push_tail(move_ir); - else - ir_if->else_instructions.push_tail(move_ir); - } - - /* Remove the break from the if-statement. - */ - break_ir->remove(); - void *const mem_ctx = ralloc_parent(ir); - ir_instruction *ir_to_replace = ir; - - for (int i = 0; i < iterations; i++) { - exec_list copy_list; + /* Note: the limiting terminator contributes 1 to ls->num_loop_jumps. + * We'll be removing the limiting terminator before we unroll. + */ + assert(ls->num_loop_jumps > 0); + unsigned predicted_num_loop_jumps = ls->num_loop_jumps - 1; - copy_list.make_empty(); - clone_ir_list(mem_ctx, ©_list, &ir->body_instructions); + if (predicted_num_loop_jumps > 1) + return visit_continue; - ir_if = ((ir_instruction *) copy_list.get_tail())->as_if(); - assert(ir_if != NULL); + if (predicted_num_loop_jumps == 0) { + ls->limiting_terminator->ir->remove(); + simple_unroll(ir, iterations); + return visit_continue; + } - ir_to_replace->insert_before(©_list); - ir_to_replace->remove(); + ir_instruction *last_ir = (ir_instruction *) ir->body_instructions.get_tail(); + assert(last_ir != NULL); - /* placeholder that will be removed in the next iteration */ - ir_to_replace = - new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_continue); + if (is_break(last_ir)) { + /* If the only loop-jump is a break at the end of the loop, the loop + * will execute exactly once. Remove the break and use the simple + * unroller with an iteration count of 1. + */ + last_ir->remove(); - exec_list *const list = (continue_from_then_branch) - ? &ir_if->then_instructions : &ir_if->else_instructions; + ls->limiting_terminator->ir->remove(); + simple_unroll(ir, 1); + return visit_continue; + } - list->push_tail(ir_to_replace); + foreach_list(node, &ir->body_instructions) { + /* recognize loops in the form produced by ir_lower_jumps */ + ir_instruction *cur_ir = (ir_instruction *) node; + + /* Skip the limiting terminator, since it will go away when we + * unroll. + */ + if (cur_ir == ls->limiting_terminator->ir) + continue; + + ir_if *ir_if = cur_ir->as_if(); + if (ir_if != NULL) { + /* Determine which if-statement branch, if any, ends with a + * break. The branch that did *not* have the break will get a + * temporary continue inserted in each iteration of the loop + * unroll. + * + * Note that since ls->num_loop_jumps is <= 1, it is impossible + * for both branches to end with a break. + */ + ir_instruction *ir_if_last = + (ir_instruction *) ir_if->then_instructions.get_tail(); + + if (is_break(ir_if_last)) { + ls->limiting_terminator->ir->remove(); + splice_post_if_instructions(ir_if, &ir_if->else_instructions); + ir_if_last->remove(); + complex_unroll(ir, iterations, false); + return visit_continue; + } else { + ir_if_last = + (ir_instruction *) ir_if->else_instructions.get_tail(); + + if (is_break(ir_if_last)) { + ls->limiting_terminator->ir->remove(); + splice_post_if_instructions(ir_if, &ir_if->then_instructions); + ir_if_last->remove(); + complex_unroll(ir, iterations, true); + return visit_continue; + } } - - ir_to_replace->remove(); - - this->progress = true; - return visit_continue; } } - void *const mem_ctx = ralloc_parent(ir); - - for (int i = 0; i < iterations; i++) { - exec_list copy_list; - - copy_list.make_empty(); - clone_ir_list(mem_ctx, ©_list, &ir->body_instructions); - - ir->insert_before(©_list); - } - - /* The loop has been replaced by the unrolled copies. Remove the original - * loop from the IR sequence. + /* Did not find the break statement. It must be in a complex if-nesting, + * so don't try to unroll. */ - ir->remove(); - - this->progress = true; return visit_continue; } bool -unroll_loops(exec_list *instructions, loop_state *ls, unsigned max_iterations) +unroll_loops(exec_list *instructions, loop_state *ls, + const struct gl_shader_compiler_options *options) { - loop_unroll_visitor v(ls, max_iterations); + loop_unroll_visitor v(ls, options); v.run(instructions); diff --git a/dist/Mesa/src/glsl/lower_clip_distance.cpp b/dist/Mesa/src/glsl/lower_clip_distance.cpp index 50cd31552..2d6138d5a 100644 --- a/dist/Mesa/src/glsl/lower_clip_distance.cpp +++ b/dist/Mesa/src/glsl/lower_clip_distance.cpp @@ -50,16 +50,21 @@ #include "ir.h" #include "program/prog_instruction.h" /* For WRITEMASK_* */ +namespace { + class lower_clip_distance_visitor : public ir_rvalue_visitor { public: - lower_clip_distance_visitor() - : progress(false), old_clip_distance_var(NULL), - new_clip_distance_var(NULL) + explicit lower_clip_distance_visitor(gl_shader_stage shader_stage) + : progress(false), old_clip_distance_1d_var(NULL), + old_clip_distance_2d_var(NULL), new_clip_distance_1d_var(NULL), + new_clip_distance_2d_var(NULL), shader_stage(shader_stage) { } virtual ir_visitor_status visit(ir_variable *); void create_indices(ir_rvalue*, ir_rvalue *&, ir_rvalue *&); + bool is_clip_distance_vec8(ir_rvalue *ir); + ir_rvalue *lower_clip_distance_vec8(ir_rvalue *ir); virtual ir_visitor_status visit_leave(ir_assignment *); void visit_new_assignment(ir_assignment *ir); virtual ir_visitor_status visit_leave(ir_call *); @@ -72,15 +77,31 @@ public: /** * Pointer to the declaration of gl_ClipDistance, if found. + * + * Note: + * + * - the 2d_var is for geometry shader input only. + * + * - since gl_ClipDistance is available in geometry shaders as both an + * input and an output, it's possible for both old_clip_distance_1d_var + * and old_clip_distance_2d_var to be non-null. */ - ir_variable *old_clip_distance_var; + ir_variable *old_clip_distance_1d_var; + ir_variable *old_clip_distance_2d_var; /** * Pointer to the newly-created gl_ClipDistanceMESA variable. */ - ir_variable *new_clip_distance_var; + ir_variable *new_clip_distance_1d_var; + ir_variable *new_clip_distance_2d_var; + + /** + * Type of shader we are compiling (e.g. MESA_SHADER_VERTEX) + */ + const gl_shader_stage shader_stage; }; +} /* anonymous namespace */ /** * Replace any declaration of gl_ClipDistance as an array of floats with a @@ -89,30 +110,61 @@ public: ir_visitor_status lower_clip_distance_visitor::visit(ir_variable *ir) { - /* No point in looking for the declaration of gl_ClipDistance if - * we've already found it. - */ - if (this->old_clip_distance_var) + if (!ir->name || strcmp(ir->name, "gl_ClipDistance") != 0) return visit_continue; + assert (ir->type->is_array()); + + if (!ir->type->element_type()->is_array()) { + /* 1D gl_ClipDistance (used for vertex and geometry output, and fragment + * input). + */ + if (this->old_clip_distance_1d_var) + return visit_continue; - if (ir->name && strcmp(ir->name, "gl_ClipDistance") == 0) { this->progress = true; - this->old_clip_distance_var = ir; - assert (ir->type->is_array()); + this->old_clip_distance_1d_var = ir; assert (ir->type->element_type() == glsl_type::float_type); unsigned new_size = (ir->type->array_size() + 3) / 4; /* Clone the old var so that we inherit all of its properties */ - this->new_clip_distance_var = ir->clone(ralloc_parent(ir), NULL); + this->new_clip_distance_1d_var = ir->clone(ralloc_parent(ir), NULL); /* And change the properties that we need to change */ - this->new_clip_distance_var->name - = ralloc_strdup(this->new_clip_distance_var, "gl_ClipDistanceMESA"); - this->new_clip_distance_var->type + this->new_clip_distance_1d_var->name + = ralloc_strdup(this->new_clip_distance_1d_var, + "gl_ClipDistanceMESA"); + this->new_clip_distance_1d_var->type = glsl_type::get_array_instance(glsl_type::vec4_type, new_size); - this->new_clip_distance_var->max_array_access = ir->max_array_access / 4; + this->new_clip_distance_1d_var->data.max_array_access + = ir->data.max_array_access / 4; + + ir->replace_with(this->new_clip_distance_1d_var); + } else { + /* 2D gl_ClipDistance (used for geometry input). */ + assert(ir->data.mode == ir_var_shader_in && + this->shader_stage == MESA_SHADER_GEOMETRY); + if (this->old_clip_distance_2d_var) + return visit_continue; - ir->replace_with(this->new_clip_distance_var); + this->progress = true; + this->old_clip_distance_2d_var = ir; + assert (ir->type->element_type()->element_type() == glsl_type::float_type); + unsigned new_size = (ir->type->element_type()->array_size() + 3) / 4; + + /* Clone the old var so that we inherit all of its properties */ + this->new_clip_distance_2d_var = ir->clone(ralloc_parent(ir), NULL); + + /* And change the properties that we need to change */ + this->new_clip_distance_2d_var->name + = ralloc_strdup(this->new_clip_distance_2d_var, "gl_ClipDistanceMESA"); + this->new_clip_distance_2d_var->type = glsl_type::get_array_instance( + glsl_type::get_array_instance(glsl_type::vec4_type, + new_size), + ir->type->array_size()); + this->new_clip_distance_2d_var->data.max_array_access + = ir->data.max_array_access / 4; + + ir->replace_with(this->new_clip_distance_2d_var); } return visit_continue; } @@ -177,39 +229,111 @@ lower_clip_distance_visitor::create_indices(ir_rvalue *old_index, } +/** + * Determine whether the given rvalue describes an array of 8 floats that + * needs to be lowered to an array of 2 vec4's; that is, determine whether it + * matches one of the following patterns: + * + * - gl_ClipDistance (if gl_ClipDistance is 1D) + * - gl_ClipDistance[i] (if gl_ClipDistance is 2D) + */ +bool +lower_clip_distance_visitor::is_clip_distance_vec8(ir_rvalue *ir) +{ + /* Note that geometry shaders contain gl_ClipDistance both as an input + * (which is a 2D array) and an output (which is a 1D array), so it's + * possible for both this->old_clip_distance_1d_var and + * this->old_clip_distance_2d_var to be non-NULL in the same shader. + */ + + if (this->old_clip_distance_1d_var) { + ir_dereference_variable *var_ref = ir->as_dereference_variable(); + if (var_ref && var_ref->var == this->old_clip_distance_1d_var) + return true; + } + if (this->old_clip_distance_2d_var) { + /* 2D clip distance is only possible as a geometry input */ + assert(this->shader_stage == MESA_SHADER_GEOMETRY); + + ir_dereference_array *array_ref = ir->as_dereference_array(); + if (array_ref) { + ir_dereference_variable *var_ref = + array_ref->array->as_dereference_variable(); + if (var_ref && var_ref->var == this->old_clip_distance_2d_var) + return true; + } + } + return false; +} + + +/** + * If the given ir satisfies is_clip_distance_vec8(), return new ir + * representing its lowered equivalent. That is, map: + * + * - gl_ClipDistance => gl_ClipDistanceMESA (if gl_ClipDistance is 1D) + * - gl_ClipDistance[i] => gl_ClipDistanceMESA[i] (if gl_ClipDistance is 2D) + * + * Otherwise return NULL. + */ +ir_rvalue * +lower_clip_distance_visitor::lower_clip_distance_vec8(ir_rvalue *ir) +{ + if (this->old_clip_distance_1d_var) { + ir_dereference_variable *var_ref = ir->as_dereference_variable(); + if (var_ref && var_ref->var == this->old_clip_distance_1d_var) { + return new(ralloc_parent(ir)) + ir_dereference_variable(this->new_clip_distance_1d_var); + } + } + if (this->old_clip_distance_2d_var) { + /* 2D clip distance is only possible as a geometry input */ + assert(this->shader_stage == MESA_SHADER_GEOMETRY); + + ir_dereference_array *array_ref = ir->as_dereference_array(); + if (array_ref) { + ir_dereference_variable *var_ref = + array_ref->array->as_dereference_variable(); + if (var_ref && var_ref->var == this->old_clip_distance_2d_var) { + return new(ralloc_parent(ir)) + ir_dereference_array(this->new_clip_distance_2d_var, + array_ref->array_index); + } + } + } + return NULL; +} + + void lower_clip_distance_visitor::handle_rvalue(ir_rvalue **rv) { - /* If the gl_ClipDistance var hasn't been declared yet, then - * there's no way this deref can refer to it. - */ - if (!this->old_clip_distance_var || *rv == NULL) + if (*rv == NULL) return; ir_dereference_array *const array_deref = (*rv)->as_dereference_array(); if (array_deref == NULL) return; - /* Replace any expression that indexes into the gl_ClipDistance array + /* Replace any expression that indexes one of the floats in gl_ClipDistance * with an expression that indexes into one of the vec4's in * gl_ClipDistanceMESA and accesses the appropriate component. */ - ir_dereference_variable *old_var_ref = - array_deref->array->as_dereference_variable(); - if (old_var_ref && old_var_ref->var == this->old_clip_distance_var) { + ir_rvalue *lowered_vec8 = + this->lower_clip_distance_vec8(array_deref->array); + if (lowered_vec8 != NULL) { this->progress = true; ir_rvalue *array_index; ir_rvalue *swizzle_index; this->create_indices(array_deref->array_index, array_index, swizzle_index); void *mem_ctx = ralloc_parent(array_deref); - ir_dereference_array *const ClipDistanceMESA_deref = - new(mem_ctx) ir_dereference_array(this->new_clip_distance_var, - array_index); + ir_dereference_array *const new_array_deref = + new(mem_ctx) ir_dereference_array(lowered_vec8, array_index); ir_expression *const expr = new(mem_ctx) ir_expression(ir_binop_vector_extract, - ClipDistanceMESA_deref, + new_array_deref, swizzle_index); *rv = expr; @@ -243,10 +367,16 @@ lower_clip_distance_visitor::fix_lhs(ir_assignment *ir) } /** - * Replace any assignment having gl_ClipDistance (undereferenced) as its LHS - * or RHS with a sequence of assignments, one for each component of the array. - * Each of these assignments is lowered to refer to gl_ClipDistanceMESA as - * appropriate. + * Replace any assignment having the 1D gl_ClipDistance (undereferenced) as + * its LHS or RHS with a sequence of assignments, one for each component of + * the array. Each of these assignments is lowered to refer to + * gl_ClipDistanceMESA as appropriate. + * + * We need to do a similar replacement for 2D gl_ClipDistance, however since + * it's an input, the only case we need to address is where a 1D slice of it + * is the entire RHS of an assignment, e.g.: + * + * foo = gl_in[i].gl_ClipDistance */ ir_visitor_status lower_clip_distance_visitor::visit_leave(ir_assignment *ir) @@ -256,22 +386,20 @@ lower_clip_distance_visitor::visit_leave(ir_assignment *ir) */ ir_rvalue_visitor::visit_leave(ir); - ir_dereference_variable *lhs_var = ir->lhs->as_dereference_variable(); - ir_dereference_variable *rhs_var = ir->rhs->as_dereference_variable(); - if ((lhs_var && lhs_var->var == this->old_clip_distance_var) - || (rhs_var && rhs_var->var == this->old_clip_distance_var)) { - /* LHS or RHS of the assignment is the entire gl_ClipDistance array. - * Since we are reshaping gl_ClipDistance from an array of floats to an - * array of vec4's, this isn't going to work as a bulk assignment - * anymore, so unroll it to element-by-element assignments and lower - * each of them. + if (this->is_clip_distance_vec8(ir->lhs) || + this->is_clip_distance_vec8(ir->rhs)) { + /* LHS or RHS of the assignment is the entire 1D gl_ClipDistance array + * (or a 1D slice of a 2D gl_ClipDistance input array). Since we are + * reshaping gl_ClipDistance from an array of floats to an array of + * vec4's, this isn't going to work as a bulk assignment anymore, so + * unroll it to element-by-element assignments and lower each of them. * * Note: to unroll into element-by-element assignments, we need to make * clones of the LHS and RHS. This is safe because expressions and * l-values are side-effect free. */ void *ctx = ralloc_parent(ir); - int array_size = this->old_clip_distance_var->type->array_size(); + int array_size = ir->lhs->type->array_size(); for (int i = 0; i < array_size; ++i) { ir_dereference_array *new_lhs = new(ctx) ir_dereference_array( ir->lhs->clone(ctx, NULL), new(ctx) ir_constant(i)); @@ -331,11 +459,17 @@ lower_clip_distance_visitor::visit_new_assignment(ir_assignment *ir) /** - * If gl_ClipDistance appears as an argument in an ir_call expression, replace - * it with a temporary variable, and make sure the ir_call is preceded and/or - * followed by assignments that copy the contents of the temporary variable to - * and/or from gl_ClipDistance. Each of these assignments is then lowered to - * refer to gl_ClipDistanceMESA. + * If a 1D gl_ClipDistance variable appears as an argument in an ir_call + * expression, replace it with a temporary variable, and make sure the ir_call + * is preceded and/or followed by assignments that copy the contents of the + * temporary variable to and/or from gl_ClipDistance. Each of these + * assignments is then lowered to refer to gl_ClipDistanceMESA. + * + * We need to do a similar replacement for 2D gl_ClipDistance, however since + * it's an input, the only case we need to address is where a 1D slice of it + * is passed as an "in" parameter to an ir_call, e.g.: + * + * foo(gl_in[i].gl_ClipDistance) */ ir_visitor_status lower_clip_distance_visitor::visit_leave(ir_call *ir) @@ -354,20 +488,20 @@ lower_clip_distance_visitor::visit_leave(ir_call *ir) formal_param_node = formal_param_node->next; actual_param_node = actual_param_node->next; - ir_dereference_variable *deref = actual_param->as_dereference_variable(); - if (deref && deref->var == this->old_clip_distance_var) { - /* User is trying to pass the whole gl_ClipDistance array to a - * function call. Since we are reshaping gl_ClipDistance from an - * array of floats to an array of vec4's, this isn't going to work - * anymore, so use a temporary array instead. + if (this->is_clip_distance_vec8(actual_param)) { + /* User is trying to pass the whole 1D gl_ClipDistance array (or a 1D + * slice of a 2D gl_ClipDistance array) to a function call. Since we + * are reshaping gl_ClipDistance from an array of floats to an array + * of vec4's, this isn't going to work anymore, so use a temporary + * array instead. */ ir_variable *temp_clip_distance = new(ctx) ir_variable( actual_param->type, "temp_clip_distance", ir_var_temporary); this->base_ir->insert_before(temp_clip_distance); actual_param->replace_with( new(ctx) ir_dereference_variable(temp_clip_distance)); - if (formal_param->mode == ir_var_function_in - || formal_param->mode == ir_var_function_inout) { + if (formal_param->data.mode == ir_var_function_in + || formal_param->data.mode == ir_var_function_inout) { /* Copy from gl_ClipDistance to the temporary before the call. * Since we are going to insert this copy before the current * instruction, we need to visit it afterwards to make sure it @@ -375,19 +509,19 @@ lower_clip_distance_visitor::visit_leave(ir_call *ir) */ ir_assignment *new_assignment = new(ctx) ir_assignment( new(ctx) ir_dereference_variable(temp_clip_distance), - new(ctx) ir_dereference_variable(old_clip_distance_var)); + actual_param->clone(ctx, NULL)); this->base_ir->insert_before(new_assignment); this->visit_new_assignment(new_assignment); } - if (formal_param->mode == ir_var_function_out - || formal_param->mode == ir_var_function_inout) { + if (formal_param->data.mode == ir_var_function_out + || formal_param->data.mode == ir_var_function_inout) { /* Copy from the temporary to gl_ClipDistance after the call. * Since visit_list_elements() has already decided which * instruction it's going to visit next, we need to visit * afterwards to make sure it gets lowered. */ ir_assignment *new_assignment = new(ctx) ir_assignment( - new(ctx) ir_dereference_variable(old_clip_distance_var), + actual_param->clone(ctx, NULL), new(ctx) ir_dereference_variable(temp_clip_distance)); this->base_ir->insert_after(new_assignment); this->visit_new_assignment(new_assignment); @@ -402,12 +536,14 @@ lower_clip_distance_visitor::visit_leave(ir_call *ir) bool lower_clip_distance(gl_shader *shader) { - lower_clip_distance_visitor v; + lower_clip_distance_visitor v(shader->Stage); visit_list_elements(&v, shader->ir); - if (v.new_clip_distance_var) - shader->symbols->add_variable(v.new_clip_distance_var); + if (v.new_clip_distance_1d_var) + shader->symbols->add_variable(v.new_clip_distance_1d_var); + if (v.new_clip_distance_2d_var) + shader->symbols->add_variable(v.new_clip_distance_2d_var); return v.progress; } diff --git a/dist/Mesa/src/glsl/lower_discard.cpp b/dist/Mesa/src/glsl/lower_discard.cpp index cafd2dd3b..f2757d120 100644 --- a/dist/Mesa/src/glsl/lower_discard.cpp +++ b/dist/Mesa/src/glsl/lower_discard.cpp @@ -108,6 +108,8 @@ #include "glsl_types.h" #include "ir.h" +namespace { + class lower_discard_visitor : public ir_hierarchical_visitor { public: lower_discard_visitor() @@ -120,6 +122,7 @@ public: bool progress; }; +} /* anonymous namespace */ bool lower_discard(exec_list *instructions) diff --git a/dist/Mesa/src/glsl/lower_discard_flow.cpp b/dist/Mesa/src/glsl/lower_discard_flow.cpp index d385c1435..1bc56d79e 100644 --- a/dist/Mesa/src/glsl/lower_discard_flow.cpp +++ b/dist/Mesa/src/glsl/lower_discard_flow.cpp @@ -48,6 +48,8 @@ #include "ir.h" #include "program/hash_table.h" +namespace { + class lower_discard_flow_visitor : public ir_hierarchical_visitor { public: lower_discard_flow_visitor(ir_variable *discarded) @@ -71,6 +73,8 @@ public: void *mem_ctx; }; +} /* anonymous namespace */ + ir_visitor_status lower_discard_flow_visitor::visit_enter(ir_loop_jump *ir) { diff --git a/dist/Mesa/src/glsl/lower_mat_op_to_vec.cpp b/dist/Mesa/src/glsl/lower_mat_op_to_vec.cpp index 08cae29fa..105ee0d3f 100644 --- a/dist/Mesa/src/glsl/lower_mat_op_to_vec.cpp +++ b/dist/Mesa/src/glsl/lower_mat_op_to_vec.cpp @@ -35,6 +35,8 @@ #include "ir_expression_flattening.h" #include "glsl_types.h" +namespace { + class ir_mat_op_to_vec_visitor : public ir_hierarchical_visitor { public: ir_mat_op_to_vec_visitor() @@ -63,6 +65,8 @@ public: bool made_progress; }; +} /* anonymous namespace */ + static bool mat_op_to_vec_predicate(ir_instruction *ir) { diff --git a/dist/Mesa/src/glsl/lower_named_interface_blocks.cpp b/dist/Mesa/src/glsl/lower_named_interface_blocks.cpp index d0d491d3d..04e0d36e6 100644 --- a/dist/Mesa/src/glsl/lower_named_interface_blocks.cpp +++ b/dist/Mesa/src/glsl/lower_named_interface_blocks.cpp @@ -65,6 +65,8 @@ #include "ir_rvalue_visitor.h" #include "program/hash_table.h" +namespace { + class flatten_named_interface_blocks_declarations : public ir_rvalue_visitor { public: @@ -83,6 +85,8 @@ public: virtual void handle_rvalue(ir_rvalue **rvalue); }; +} /* anonymous namespace */ + void flatten_named_interface_blocks_declarations::run(exec_list *instructions) { @@ -104,7 +108,7 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions) * but, this will require changes to the other uniform block * support code. */ - if (var->mode == ir_var_uniform) + if (var->data.mode == ir_var_uniform) continue; const glsl_type * iface_t = var->type; @@ -121,37 +125,41 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions) for (unsigned i = 0; i < iface_t->length; i++) { const char * field_name = iface_t->fields.structure[i].name; char *iface_field_name = - ralloc_asprintf(mem_ctx, "%s.%s", - iface_t->name, field_name); + ralloc_asprintf(mem_ctx, "%s.%s.%s", + iface_t->name, var->name, field_name); ir_variable *found_var = (ir_variable *) hash_table_find(interface_namespace, iface_field_name); if (!found_var) { ir_variable *new_var; + char *var_name = + ralloc_strdup(mem_ctx, iface_t->fields.structure[i].name); if (array_t == NULL) { - char *var_name = - ralloc_strdup(mem_ctx, iface_t->fields.structure[i].name); new_var = new(mem_ctx) ir_variable(iface_t->fields.structure[i].type, var_name, - (ir_variable_mode) var->mode); + (ir_variable_mode) var->data.mode); + new_var->data.from_named_ifc_block_nonarray = 1; } else { const glsl_type *new_array_type = glsl_type::get_array_instance( iface_t->fields.structure[i].type, array_t->length); - char *var_name = - ralloc_asprintf(mem_ctx, "%s[%d]", - iface_t->fields.structure[i].name, - array_t->length); new_var = new(mem_ctx) ir_variable(new_array_type, var_name, - (ir_variable_mode) var->mode); + (ir_variable_mode) var->data.mode); + new_var->data.from_named_ifc_block_array = 1; } - - new_var->interface_type = iface_t; + new_var->data.location = iface_t->fields.structure[i].location; + new_var->data.explicit_location = (new_var->data.location >= 0); + new_var->data.interpolation = + iface_t->fields.structure[i].interpolation; + new_var->data.centroid = iface_t->fields.structure[i].centroid; + new_var->data.sample = iface_t->fields.structure[i].sample; + + new_var->init_interface_type(iface_t); hash_table_insert(interface_namespace, new_var, iface_field_name); insert_pos->insert_after(new_var); @@ -204,13 +212,13 @@ flatten_named_interface_blocks_declarations::handle_rvalue(ir_rvalue **rvalue) * but, this will require changes to the other uniform block * support code. */ - if (var->mode == ir_var_uniform) + if (var->data.mode == ir_var_uniform) return; - if (var->interface_type != NULL) { + if (var->get_interface_type() != NULL) { char *iface_field_name = - ralloc_asprintf(mem_ctx, "%s.%s", var->interface_type->name, - ir->field); + ralloc_asprintf(mem_ctx, "%s.%s.%s", var->get_interface_type()->name, + var->name, ir->field); /* Find the variable in the set of flattened interface blocks */ ir_variable *found_var = (ir_variable *) hash_table_find(interface_namespace, diff --git a/dist/Mesa/src/glsl/lower_offset_array.cpp b/dist/Mesa/src/glsl/lower_offset_array.cpp new file mode 100644 index 000000000..0c235eda3 --- /dev/null +++ b/dist/Mesa/src/glsl/lower_offset_array.cpp @@ -0,0 +1,90 @@ +/* + * Copyright © 2013 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 brw_lower_offset_array.cpp + * + * IR lower pass to decompose ir_texture ir_tg4 with an array of offsets + * into four ir_tg4s with a single ivec2 offset, select the .w component of each, + * and return those four values packed into a gvec4. + * + * \author Chris Forbes <chrisf@ijw.co.nz> + */ + +#include "glsl_types.h" +#include "ir.h" +#include "ir_builder.h" +#include "ir_optimization.h" +#include "ir_rvalue_visitor.h" + +using namespace ir_builder; + +class brw_lower_offset_array_visitor : public ir_rvalue_visitor { +public: + brw_lower_offset_array_visitor() + { + progress = false; + } + + void handle_rvalue(ir_rvalue **rv); + + bool progress; +}; + +void +brw_lower_offset_array_visitor::handle_rvalue(ir_rvalue **rv) +{ + if (*rv == NULL || (*rv)->ir_type != ir_type_texture) + return; + + ir_texture *ir = (ir_texture *) *rv; + if (ir->op != ir_tg4 || !ir->offset || !ir->offset->type->is_array()) + return; + + void *mem_ctx = ralloc_parent(ir); + + ir_variable *var = new (mem_ctx) ir_variable(ir->type, "result", ir_var_auto); + base_ir->insert_before(var); + + for (int i = 0; i < 4; i++) { + ir_texture *tex = ir->clone(mem_ctx, NULL); + tex->offset = new (mem_ctx) ir_dereference_array(tex->offset, + new (mem_ctx) ir_constant(i)); + + base_ir->insert_before(assign(var, swizzle_w(tex), 1 << i)); + } + + *rv = new (mem_ctx) ir_dereference_variable(var); + + progress = true; +} + +bool +lower_offset_arrays(exec_list *instructions) +{ + brw_lower_offset_array_visitor v; + + visit_list_elements(&v, instructions); + + return v.progress; +} diff --git a/dist/Mesa/src/glsl/lower_output_reads.cpp b/dist/Mesa/src/glsl/lower_output_reads.cpp index b93e254ec..afe17766b 100644 --- a/dist/Mesa/src/glsl/lower_output_reads.cpp +++ b/dist/Mesa/src/glsl/lower_output_reads.cpp @@ -37,6 +37,8 @@ * main() function to copy the final values to the actual shader outputs. */ +namespace { + class output_read_remover : public ir_hierarchical_visitor { protected: /** @@ -50,10 +52,13 @@ public: output_read_remover(); ~output_read_remover(); virtual ir_visitor_status visit(class ir_dereference_variable *); + virtual ir_visitor_status visit(class ir_emit_vertex *); virtual ir_visitor_status visit_leave(class ir_return *); virtual ir_visitor_status visit_leave(class ir_function_signature *); }; +} /* anonymous namespace */ + /** * Hash function for the output variables - computes the hash of the name. * NOTE: We're using the name string to ensure that the hash doesn't depend @@ -86,7 +91,7 @@ output_read_remover::~output_read_remover() ir_visitor_status output_read_remover::visit(ir_dereference_variable *ir) { - if (ir->var->mode != ir_var_shader_out) + if (ir->var->data.mode != ir_var_shader_out) return visit_continue; ir_variable *temp = (ir_variable *) hash_table_find(replacements, ir->var); @@ -117,7 +122,9 @@ copy(void *ctx, ir_variable *output, ir_variable *temp) return new(ctx) ir_assignment(lhs, rhs); } -/** Insert a copy-back assignment before a "return" statement */ +/** Insert a copy-back assignment before a "return" statement or a call to + * EmitVertex(). + */ static void emit_return_copy(const void *key, void *data, void *closure) { @@ -141,6 +148,14 @@ output_read_remover::visit_leave(ir_return *ir) } ir_visitor_status +output_read_remover::visit(ir_emit_vertex *ir) +{ + hash_table_call_foreach(replacements, emit_return_copy, ir); + hash_table_clear(replacements); + return visit_continue; +} + +ir_visitor_status output_read_remover::visit_leave(ir_function_signature *sig) { if (strcmp(sig->function_name(), "main") != 0) diff --git a/dist/Mesa/src/glsl/lower_packed_varyings.cpp b/dist/Mesa/src/glsl/lower_packed_varyings.cpp index cdf2289b4..e8654748f 100644 --- a/dist/Mesa/src/glsl/lower_packed_varyings.cpp +++ b/dist/Mesa/src/glsl/lower_packed_varyings.cpp @@ -74,12 +74,82 @@ * This lowering pass also handles varyings whose type is a struct or an array * of struct. Structs are packed in order and with no gaps, so there may be a * performance penalty due to structure elements being double-parked. + * + * Lowering of geometry shader inputs is slightly more complex, since geometry + * inputs are always arrays, so we need to lower arrays to arrays. For + * example, the following input: + * + * in struct Foo { + * float f; + * vec3 v; + * vec2 a[2]; + * } arr[3]; // location=4, location_frac=0 + * + * Would get lowered like this if it occurred in a fragment shader: + * + * struct Foo { + * float f; + * vec3 v; + * vec2 a[2]; + * } arr[3]; + * in vec4 packed4; // location=4, location_frac=0 + * in vec4 packed5; // location=5, location_frac=0 + * in vec4 packed6; // location=6, location_frac=0 + * in vec4 packed7; // location=7, location_frac=0 + * in vec4 packed8; // location=8, location_frac=0 + * in vec4 packed9; // location=9, location_frac=0 + * + * main() + * { + * arr[0].f = packed4.x; + * arr[0].v = packed4.yzw; + * arr[0].a[0] = packed5.xy; + * arr[0].a[1] = packed5.zw; + * arr[1].f = packed6.x; + * arr[1].v = packed6.yzw; + * arr[1].a[0] = packed7.xy; + * arr[1].a[1] = packed7.zw; + * arr[2].f = packed8.x; + * arr[2].v = packed8.yzw; + * arr[2].a[0] = packed9.xy; + * arr[2].a[1] = packed9.zw; + * ... + * } + * + * But it would get lowered like this if it occurred in a geometry shader: + * + * struct Foo { + * float f; + * vec3 v; + * vec2 a[2]; + * } arr[3]; + * in vec4 packed4[3]; // location=4, location_frac=0 + * in vec4 packed5[3]; // location=5, location_frac=0 + * + * main() + * { + * arr[0].f = packed4[0].x; + * arr[0].v = packed4[0].yzw; + * arr[0].a[0] = packed5[0].xy; + * arr[0].a[1] = packed5[0].zw; + * arr[1].f = packed4[1].x; + * arr[1].v = packed4[1].yzw; + * arr[1].a[0] = packed5[1].xy; + * arr[1].a[1] = packed5[1].zw; + * arr[2].f = packed4[2].x; + * arr[2].v = packed4[2].yzw; + * arr[2].a[0] = packed5[2].xy; + * arr[2].a[1] = packed5[2].zw; + * ... + * } */ #include "glsl_symbol_table.h" #include "ir.h" #include "ir_optimization.h" +namespace { + /** * Visitor that performs varying packing. For each varying declared in the * shader, this visitor determines whether it needs to be packed. If so, it @@ -90,10 +160,10 @@ class lower_packed_varyings_visitor { public: - lower_packed_varyings_visitor(void *mem_ctx, unsigned location_base, - unsigned locations_used, + lower_packed_varyings_visitor(void *mem_ctx, unsigned locations_used, ir_variable_mode mode, - exec_list *main_instructions); + unsigned gs_input_vertices, + exec_list *out_instructions); void run(exec_list *instructions); @@ -101,13 +171,16 @@ private: ir_assignment *bitwise_assign_pack(ir_rvalue *lhs, ir_rvalue *rhs); ir_assignment *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); + ir_variable *unpacked_var, const char *name, + bool gs_input_toplevel, unsigned vertex_index); unsigned lower_arraylike(ir_rvalue *rvalue, unsigned array_size, unsigned fine_location, - ir_variable *unpacked_var, const char *name); - ir_variable *get_packed_varying(unsigned location, - ir_variable *unpacked_var, - const char *name); + ir_variable *unpacked_var, const char *name, + bool gs_input_toplevel, unsigned vertex_index); + ir_dereference *get_packed_varying_deref(unsigned location, + ir_variable *unpacked_var, + const char *name, + unsigned vertex_index); bool needs_lowering(ir_variable *var); /** @@ -116,18 +189,10 @@ private: void * const mem_ctx; /** - * Location representing the first generic varying slot for this shader - * stage (e.g. VARYING_SLOT_VAR0 if we are packing vertex shader outputs). - * Varyings whose location is less than this value are assumed to - * correspond to special fixed function hardware, so they are not lowered. - */ - const unsigned location_base; - - /** * Number of generic varying slots which are used by this shader. This is - * used to allocate temporary intermediate data structures. If any any - * varying used by this shader has a location greater than or equal to - * location_base + locations_used, an assertion will fire. + * used to allocate temporary intermediate data structures. If any varying + * used by this shader has a location greater than or equal to + * VARYING_SLOT_VAR0 + locations_used, an assertion will fire. */ const unsigned locations_used; @@ -145,23 +210,32 @@ private: const ir_variable_mode mode; /** - * List of instructions corresponding to the main() function. This is - * where we add instructions to pack or unpack the varyings. + * If we are currently lowering geometry shader inputs, the number of input + * vertices the geometry shader accepts. Otherwise zero. + */ + const unsigned gs_input_vertices; + + /** + * Exec list into which the visitor should insert the packing instructions. + * Caller provides this list; it should insert the instructions into the + * appropriate place in the shader once the visitor has finished running. */ - exec_list *main_instructions; + exec_list *out_instructions; }; +} /* anonymous namespace */ + lower_packed_varyings_visitor::lower_packed_varyings_visitor( - void *mem_ctx, unsigned location_base, unsigned locations_used, - ir_variable_mode mode, exec_list *main_instructions) + void *mem_ctx, unsigned locations_used, ir_variable_mode mode, + unsigned gs_input_vertices, exec_list *out_instructions) : mem_ctx(mem_ctx), - location_base(location_base), locations_used(locations_used), packed_varyings((ir_variable **) rzalloc_array_size(mem_ctx, sizeof(*packed_varyings), locations_used)), mode(mode), - main_instructions(main_instructions) + gs_input_vertices(gs_input_vertices), + out_instructions(out_instructions) { } @@ -173,8 +247,8 @@ lower_packed_varyings_visitor::run(exec_list *instructions) if (var == NULL) continue; - if (var->mode != this->mode || - var->location < (int) this->location_base || + if (var->data.mode != this->mode || + var->data.location < VARYING_SLOT_VAR0 || !this->needs_lowering(var)) continue; @@ -183,19 +257,19 @@ lower_packed_varyings_visitor::run(exec_list *instructions) * safe, caller should ensure that integral varyings always use flat * interpolation, even when this is not required by GLSL. */ - assert(var->interpolation == INTERP_QUALIFIER_FLAT || + assert(var->data.interpolation == INTERP_QUALIFIER_FLAT || !var->type->contains_integer()); /* Change the old varying into an ordinary global. */ - var->mode = ir_var_auto; + var->data.mode = ir_var_auto; /* Create a reference to the old varying. */ ir_dereference_variable *deref = new(this->mem_ctx) ir_dereference_variable(var); /* Recursively pack or unpack it. */ - this->lower_rvalue(deref, var->location * 4 + var->location_frac, var, - var->name); + this->lower_rvalue(deref, var->data.location * 4 + var->data.location_frac, var, + var->name, this->gs_input_vertices != 0, 0); } } @@ -277,6 +351,15 @@ lower_packed_varyings_visitor::bitwise_assign_unpack(ir_rvalue *lhs, * in multiples of a float, rather than multiples of a vec4 as is used * elsewhere in Mesa. * + * \param gs_input_toplevel should be set to true if we are lowering geometry + * shader inputs, and we are currently lowering the whole input variable + * (i.e. we are lowering the array whose index selects the vertex). + * + * \param vertex_index: if we are lowering geometry shader inputs, and the + * level of the array that we are currently lowering is *not* the top level, + * then this indicates which vertex we are currently lowering. Otherwise it + * is ignored. + * * \return the location where the next constituent vector (after this one) * should be packed. */ @@ -284,8 +367,15 @@ unsigned lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue, unsigned fine_location, ir_variable *unpacked_var, - const char *name) + const char *name, + bool gs_input_toplevel, + unsigned vertex_index) { + /* When gs_input_toplevel is set, we should be looking at a geometry shader + * input array. + */ + assert(!gs_input_toplevel || rvalue->type->is_array()); + if (rvalue->type->is_record()) { for (unsigned i = 0; i < rvalue->type->length; i++) { if (i != 0) @@ -296,7 +386,8 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue, char *deref_name = ralloc_asprintf(this->mem_ctx, "%s.%s", name, field_name); fine_location = this->lower_rvalue(dereference_record, fine_location, - unpacked_var, deref_name); + unpacked_var, deref_name, false, + vertex_index); } return fine_location; } else if (rvalue->type->is_array()) { @@ -304,13 +395,15 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue, * sequence. */ return this->lower_arraylike(rvalue, rvalue->type->array_size(), - fine_location, unpacked_var, name); + fine_location, unpacked_var, name, + gs_input_toplevel, vertex_index); } else if (rvalue->type->is_matrix()) { /* Matrices are packed/unpacked by considering each column vector in * sequence. */ return this->lower_arraylike(rvalue, rvalue->type->matrix_columns, - fine_location, unpacked_var, name); + fine_location, unpacked_var, name, + false, vertex_index); } else if (rvalue->type->vector_elements + fine_location % 4 > 4) { /* This vector is going to be "double parked" across two varying slots, * so handle it as two separate assignments. @@ -340,9 +433,10 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue, 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); + unpacked_var, left_name, false, + vertex_index); return this->lower_rvalue(right_swizzle, fine_location, unpacked_var, - right_name); + right_name, false, vertex_index); } else { /* No special handling is necessary; pack the rvalue into the * varying. @@ -353,19 +447,19 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue, unsigned location_frac = fine_location % 4; for (unsigned i = 0; i < components; ++i) swizzle_values[i] = i + location_frac; - ir_dereference_variable *packed_deref = new(this->mem_ctx) - ir_dereference_variable(this->get_packed_varying(location, - unpacked_var, name)); + ir_dereference *packed_deref = + this->get_packed_varying_deref(location, unpacked_var, name, + vertex_index); 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->main_instructions->push_tail(assignment); + this->out_instructions->push_tail(assignment); } else { ir_assignment *assignment = this->bitwise_assign_unpack(rvalue, swizzle); - this->main_instructions->push_head(assignment); + this->out_instructions->push_tail(assignment); } return fine_location + components; } @@ -376,13 +470,24 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue, * constituent elements, accessing each one using an ir_dereference_array. * This takes care of both arrays and matrices, since ir_dereference_array * treats a matrix like an array of its column vectors. + * + * \param gs_input_toplevel should be set to true if we are lowering geometry + * shader inputs, and we are currently lowering the whole input variable + * (i.e. we are lowering the array whose index selects the vertex). + * + * \param vertex_index: if we are lowering geometry shader inputs, and the + * level of the array that we are currently lowering is *not* the top level, + * then this indicates which vertex we are currently lowering. Otherwise it + * is ignored. */ unsigned lower_packed_varyings_visitor::lower_arraylike(ir_rvalue *rvalue, unsigned array_size, unsigned fine_location, ir_variable *unpacked_var, - const char *name) + const char *name, + bool gs_input_toplevel, + unsigned vertex_index) { for (unsigned i = 0; i < array_size; i++) { if (i != 0) @@ -390,10 +495,21 @@ lower_packed_varyings_visitor::lower_arraylike(ir_rvalue *rvalue, ir_constant *constant = new(this->mem_ctx) ir_constant(i); ir_dereference_array *dereference_array = new(this->mem_ctx) ir_dereference_array(rvalue, constant); - char *subscripted_name - = ralloc_asprintf(this->mem_ctx, "%s[%d]", name, i); - fine_location = this->lower_rvalue(dereference_array, fine_location, - unpacked_var, subscripted_name); + if (gs_input_toplevel) { + /* Geometry shader inputs are a special case. Instead of storing + * each element of the array at a different location, all elements + * are at the same location, but with a different vertex index. + */ + (void) this->lower_rvalue(dereference_array, fine_location, + unpacked_var, name, false, i); + } else { + char *subscripted_name + = ralloc_asprintf(this->mem_ctx, "%s[%d]", name, i); + fine_location = + this->lower_rvalue(dereference_array, fine_location, + unpacked_var, subscripted_name, + false, vertex_index); + } } return fine_location; } @@ -406,40 +522,79 @@ lower_packed_varyings_visitor::lower_arraylike(ir_rvalue *rvalue, * The newly created varying inherits its interpolation parameters from \c * unpacked_var. Its base type is ivec4 if we are lowering a flat varying, * vec4 otherwise. + * + * \param vertex_index: if we are lowering geometry shader inputs, then this + * indicates which vertex we are currently lowering. Otherwise it is ignored. */ -ir_variable * -lower_packed_varyings_visitor::get_packed_varying(unsigned location, - ir_variable *unpacked_var, - const char *name) +ir_dereference * +lower_packed_varyings_visitor::get_packed_varying_deref( + unsigned location, ir_variable *unpacked_var, const char *name, + unsigned vertex_index) { - unsigned slot = location - this->location_base; + unsigned slot = location - VARYING_SLOT_VAR0; assert(slot < locations_used); if (this->packed_varyings[slot] == NULL) { char *packed_name = ralloc_asprintf(this->mem_ctx, "packed:%s", name); const glsl_type *packed_type; - if (unpacked_var->interpolation == INTERP_QUALIFIER_FLAT) + if (unpacked_var->data.interpolation == INTERP_QUALIFIER_FLAT) packed_type = glsl_type::ivec4_type; else packed_type = glsl_type::vec4_type; + if (this->gs_input_vertices != 0) { + packed_type = + glsl_type::get_array_instance(packed_type, + this->gs_input_vertices); + } ir_variable *packed_var = new(this->mem_ctx) ir_variable(packed_type, packed_name, this->mode); - packed_var->centroid = unpacked_var->centroid; - packed_var->interpolation = unpacked_var->interpolation; - packed_var->location = location; + if (this->gs_input_vertices != 0) { + /* Prevent update_array_sizes() from messing with the size of the + * array. + */ + packed_var->data.max_array_access = this->gs_input_vertices - 1; + } + packed_var->data.centroid = unpacked_var->data.centroid; + packed_var->data.sample = unpacked_var->data.sample; + packed_var->data.interpolation = unpacked_var->data.interpolation; + packed_var->data.location = location; unpacked_var->insert_before(packed_var); this->packed_varyings[slot] = packed_var; } else { - ralloc_asprintf_append((char **) &this->packed_varyings[slot]->name, - ",%s", name); + /* For geometry shader inputs, only update the packed variable name the + * first time we visit each component. + */ + if (this->gs_input_vertices == 0 || vertex_index == 0) { + ralloc_asprintf_append((char **) &this->packed_varyings[slot]->name, + ",%s", name); + } } - return this->packed_varyings[slot]; + + ir_dereference *deref = new(this->mem_ctx) + ir_dereference_variable(this->packed_varyings[slot]); + if (this->gs_input_vertices != 0) { + /* When lowering GS inputs, the packed variable is an array, so we need + * to dereference it using vertex_index. + */ + ir_constant *constant = new(this->mem_ctx) ir_constant(vertex_index); + deref = new(this->mem_ctx) ir_dereference_array(deref, constant); + } + return deref; } bool lower_packed_varyings_visitor::needs_lowering(ir_variable *var) { - /* Things composed of vec4's don't need lowering. Everything else does. */ + /* Things composed of vec4's and varyings with explicitly assigned + * locations don't need lowering. Everything else does. + */ + if (var->data.explicit_location) + return false; + const glsl_type *type = var->type; + if (this->gs_input_vertices != 0) { + assert(type->is_array()); + type = type->element_type(); + } if (type->is_array()) type = type->fields.array; if (type->vector_elements == 4) @@ -447,19 +602,80 @@ lower_packed_varyings_visitor::needs_lowering(ir_variable *var) return true; } + +/** + * Visitor that splices varying packing code before every use of EmitVertex() + * in a geometry shader. + */ +class lower_packed_varyings_gs_splicer : public ir_hierarchical_visitor +{ +public: + explicit lower_packed_varyings_gs_splicer(void *mem_ctx, + const exec_list *instructions); + + virtual ir_visitor_status visit(ir_emit_vertex *ev); + +private: + /** + * Memory context used to allocate new instructions for the shader. + */ + void * const mem_ctx; + + /** + * Instructions that should be spliced into place before each EmitVertex() + * call. + */ + const exec_list *instructions; +}; + + +lower_packed_varyings_gs_splicer::lower_packed_varyings_gs_splicer( + void *mem_ctx, const exec_list *instructions) + : mem_ctx(mem_ctx), instructions(instructions) +{ +} + + +ir_visitor_status +lower_packed_varyings_gs_splicer::visit(ir_emit_vertex *ev) +{ + foreach_list(node, this->instructions) { + ir_instruction *ir = (ir_instruction *) node; + ev->insert_before(ir->clone(this->mem_ctx, NULL)); + } + return visit_continue; +} + + void -lower_packed_varyings(void *mem_ctx, unsigned location_base, - unsigned locations_used, ir_variable_mode mode, +lower_packed_varyings(void *mem_ctx, unsigned locations_used, + ir_variable_mode mode, unsigned gs_input_vertices, gl_shader *shader) { exec_list *instructions = shader->ir; ir_function *main_func = shader->symbols->get_function("main"); exec_list void_parameters; ir_function_signature *main_func_sig - = main_func->matching_signature(&void_parameters); - exec_list *main_instructions = &main_func_sig->body; - lower_packed_varyings_visitor visitor(mem_ctx, location_base, - locations_used, mode, - main_instructions); + = main_func->matching_signature(NULL, &void_parameters); + exec_list new_instructions; + lower_packed_varyings_visitor visitor(mem_ctx, locations_used, mode, + gs_input_vertices, &new_instructions); visitor.run(instructions); + if (mode == ir_var_shader_out) { + if (shader->Stage == MESA_SHADER_GEOMETRY) { + /* For geometry shaders, outputs need to be lowered before each call + * to EmitVertex() + */ + lower_packed_varyings_gs_splicer splicer(mem_ctx, &new_instructions); + 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_instructions); + } + } else { + /* Shader inputs need to be lowered at the beginning of main() */ + main_func_sig->body.head->insert_before(&new_instructions); + } } diff --git a/dist/Mesa/src/glsl/lower_texture_projection.cpp b/dist/Mesa/src/glsl/lower_texture_projection.cpp index 6e3aaecce..16d637680 100644 --- a/dist/Mesa/src/glsl/lower_texture_projection.cpp +++ b/dist/Mesa/src/glsl/lower_texture_projection.cpp @@ -37,6 +37,8 @@ #include "ir.h" +namespace { + class lower_texture_projection_visitor : public ir_hierarchical_visitor { public: lower_texture_projection_visitor() @@ -49,6 +51,8 @@ public: bool progress; }; +} /* anonymous namespace */ + ir_visitor_status lower_texture_projection_visitor::visit_leave(ir_texture *ir) { diff --git a/dist/Mesa/src/glsl/lower_ubo_reference.cpp b/dist/Mesa/src/glsl/lower_ubo_reference.cpp index aade203e7..90e65bd0e 100644 --- a/dist/Mesa/src/glsl/lower_ubo_reference.cpp +++ b/dist/Mesa/src/glsl/lower_ubo_reference.cpp @@ -132,7 +132,8 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue) mem_ctx = ralloc_parent(*rvalue); const char *const field_name = - interface_field_name(mem_ctx, (char *) var->interface_type->name, deref); + interface_field_name(mem_ctx, (char *) var->get_interface_type()->name, + deref); this->uniform_block = -1; for (unsigned i = 0; i < shader->NumUniformBlocks; i++) { @@ -142,7 +143,7 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue) struct gl_uniform_block *block = &shader->UniformBlocks[i]; this->ubo_var = var->is_interface_instance() - ? &block->Uniforms[0] : &block->Uniforms[var->location]; + ? &block->Uniforms[0] : &block->Uniforms[var->data.location]; break; } @@ -193,12 +194,16 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue) array_stride = glsl_align(array_stride, 16); } - ir_constant *const_index = deref_array->array_index->as_constant(); + ir_rvalue *array_index = deref_array->array_index; + if (array_index->type->base_type == GLSL_TYPE_INT) + array_index = i2u(array_index); + + ir_constant *const_index = array_index->as_constant(); if (const_index) { - const_offset += array_stride * const_index->value.i[0]; + const_offset += array_stride * const_index->value.u[0]; } else { offset = add(offset, - mul(deref_array->array_index, + mul(array_index, new(mem_ctx) ir_constant(array_stride))); } deref = deref_array->array->as_dereference(); diff --git a/dist/Mesa/src/glsl/lower_vector.cpp b/dist/Mesa/src/glsl/lower_vector.cpp index 0cd6909db..a658410ae 100644 --- a/dist/Mesa/src/glsl/lower_vector.cpp +++ b/dist/Mesa/src/glsl/lower_vector.cpp @@ -31,9 +31,11 @@ #include "ir.h" #include "ir_rvalue_visitor.h" +namespace { + class lower_vector_visitor : public ir_rvalue_visitor { public: - lower_vector_visitor() : progress(false) + lower_vector_visitor() : dont_lower_swz(false), progress(false) { /* empty */ } @@ -48,6 +50,8 @@ public: bool progress; }; +} /* anonymous namespace */ + /** * Determine if an IR expression tree looks like an extended swizzle * diff --git a/dist/Mesa/src/glsl/lower_vector_insert.cpp b/dist/Mesa/src/glsl/lower_vector_insert.cpp index 0e640cc32..6d7cfa942 100644 --- a/dist/Mesa/src/glsl/lower_vector_insert.cpp +++ b/dist/Mesa/src/glsl/lower_vector_insert.cpp @@ -27,6 +27,8 @@ using namespace ir_builder; +namespace { + class vector_insert_visitor : public ir_rvalue_visitor { public: vector_insert_visitor(bool lower_nonconstant_index) @@ -48,6 +50,7 @@ public: bool lower_nonconstant_index; }; +} /* anonymous namespace */ void vector_insert_visitor::handle_rvalue(ir_rvalue **rv) diff --git a/dist/Mesa/src/glsl/opt_algebraic.cpp b/dist/Mesa/src/glsl/opt_algebraic.cpp index d706a6ad1..9d5539252 100644 --- a/dist/Mesa/src/glsl/opt_algebraic.cpp +++ b/dist/Mesa/src/glsl/opt_algebraic.cpp @@ -32,8 +32,11 @@ #include "ir_visitor.h" #include "ir_rvalue_visitor.h" #include "ir_optimization.h" +#include "ir_builder.h" #include "glsl_types.h" +using namespace ir_builder; + namespace { /** @@ -42,10 +45,11 @@ namespace { class ir_algebraic_visitor : public ir_rvalue_visitor { public: - ir_algebraic_visitor() + ir_algebraic_visitor(bool native_integers) { this->progress = false; this->mem_ctx = NULL; + this->native_integers = native_integers; } virtual ~ir_algebraic_visitor() @@ -67,6 +71,7 @@ public: void *mem_ctx; + bool native_integers; bool progress; }; @@ -85,6 +90,18 @@ is_vec_one(ir_constant *ir) } static inline bool +is_vec_two(ir_constant *ir) +{ + return (ir == NULL) ? false : ir->is_value(2.0, 2); +} + +static inline bool +is_vec_negative_one(ir_constant *ir) +{ + return (ir == NULL) ? false : ir->is_negative_one(); +} + +static inline bool is_vec_basis(ir_constant *ir) { return (ir == NULL) ? false : ir->is_basis(); @@ -188,7 +205,6 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) { ir_constant *op_const[4] = {NULL, NULL, NULL, NULL}; ir_expression *op_expr[4] = {NULL, NULL, NULL, NULL}; - ir_expression *temp; unsigned int i; assert(ir->get_num_operands() <= 4); @@ -204,6 +220,69 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) this->mem_ctx = ralloc_parent(ir); switch (ir->operation) { + case ir_unop_bit_not: + if (op_expr[0] && op_expr[0]->operation == ir_unop_bit_not) + return op_expr[0]->operands[0]; + break; + + case ir_unop_abs: + if (op_expr[0] == NULL) + break; + + switch (op_expr[0]->operation) { + case ir_unop_abs: + case ir_unop_neg: + return abs(op_expr[0]->operands[0]); + default: + break; + } + break; + + case ir_unop_neg: + if (op_expr[0] == NULL) + break; + + if (op_expr[0]->operation == ir_unop_neg) { + return op_expr[0]->operands[0]; + } + break; + + case ir_unop_exp: + if (op_expr[0] == NULL) + break; + + if (op_expr[0]->operation == ir_unop_log) { + return op_expr[0]->operands[0]; + } + break; + + case ir_unop_log: + if (op_expr[0] == NULL) + break; + + if (op_expr[0]->operation == ir_unop_exp) { + return op_expr[0]->operands[0]; + } + break; + + case ir_unop_exp2: + if (op_expr[0] == NULL) + break; + + if (op_expr[0]->operation == ir_unop_log2) { + return op_expr[0]->operands[0]; + } + break; + + case ir_unop_log2: + if (op_expr[0] == NULL) + break; + + if (op_expr[0]->operation == ir_unop_exp2) { + return op_expr[0]->operands[0]; + } + break; + case ir_unop_logic_not: { enum ir_expression_operation new_op = ir_unop_logic_not; @@ -227,7 +306,6 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) } if (new_op != ir_unop_logic_not) { - this->progress = true; return new(mem_ctx) ir_expression(new_op, ir->type, op_expr[0]->operands[0], @@ -238,90 +316,120 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) } case ir_binop_add: - if (is_vec_zero(op_const[0])) { - this->progress = true; - return swizzle_if_required(ir, ir->operands[1]); - } - if (is_vec_zero(op_const[1])) { - this->progress = true; - return swizzle_if_required(ir, ir->operands[0]); - } + if (is_vec_zero(op_const[0])) + return ir->operands[1]; + if (is_vec_zero(op_const[1])) + return ir->operands[0]; /* Reassociate addition of constants so that we can do constant * folding. */ if (op_const[0] && !op_const[1]) - reassociate_constant(ir, 0, op_const[0], - ir->operands[1]->as_expression()); + reassociate_constant(ir, 0, op_const[0], op_expr[1]); if (op_const[1] && !op_const[0]) - reassociate_constant(ir, 1, op_const[1], - ir->operands[0]->as_expression()); + reassociate_constant(ir, 1, op_const[1], op_expr[0]); + + /* Replace (-x + y) * a + x and commutative variations with lrp(x, y, a). + * + * (-x + y) * a + x + * (x * -a) + (y * a) + x + * x + (x * -a) + (y * a) + * x * (1 - a) + y * a + * lrp(x, y, a) + */ + for (int mul_pos = 0; mul_pos < 2; mul_pos++) { + ir_expression *mul = op_expr[mul_pos]; + + if (!mul || mul->operation != ir_binop_mul) + continue; + + /* Multiply found on one of the operands. Now check for an + * inner addition operation. + */ + for (int inner_add_pos = 0; inner_add_pos < 2; inner_add_pos++) { + ir_expression *inner_add = + mul->operands[inner_add_pos]->as_expression(); + + if (!inner_add || inner_add->operation != ir_binop_add) + continue; + + /* Inner addition found on one of the operands. Now check for + * one of the operands of the inner addition to be the negative + * of x_operand. + */ + for (int neg_pos = 0; neg_pos < 2; neg_pos++) { + ir_expression *neg = + inner_add->operands[neg_pos]->as_expression(); + + if (!neg || neg->operation != ir_unop_neg) + continue; + + ir_rvalue *x_operand = ir->operands[1 - mul_pos]; + + if (!neg->operands[0]->equals(x_operand)) + continue; + + ir_rvalue *y_operand = inner_add->operands[1 - neg_pos]; + ir_rvalue *a_operand = mul->operands[1 - inner_add_pos]; + + if (x_operand->type != y_operand->type || + x_operand->type != a_operand->type) + continue; + + return lrp(x_operand, y_operand, a_operand); + } + } + } break; case ir_binop_sub: - if (is_vec_zero(op_const[0])) { - this->progress = true; - temp = new(mem_ctx) ir_expression(ir_unop_neg, - ir->operands[1]->type, - ir->operands[1], - NULL); - return swizzle_if_required(ir, temp); - } - if (is_vec_zero(op_const[1])) { - this->progress = true; - return swizzle_if_required(ir, ir->operands[0]); - } + if (is_vec_zero(op_const[0])) + return neg(ir->operands[1]); + if (is_vec_zero(op_const[1])) + return ir->operands[0]; break; case ir_binop_mul: - if (is_vec_one(op_const[0])) { - this->progress = true; - return swizzle_if_required(ir, ir->operands[1]); - } - if (is_vec_one(op_const[1])) { - this->progress = true; - return swizzle_if_required(ir, ir->operands[0]); - } + if (is_vec_one(op_const[0])) + return ir->operands[1]; + if (is_vec_one(op_const[1])) + return ir->operands[0]; - if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) { - this->progress = true; + if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) return ir_constant::zero(ir, ir->type); - } + + if (is_vec_negative_one(op_const[0])) + return neg(ir->operands[1]); + if (is_vec_negative_one(op_const[1])) + return neg(ir->operands[0]); + /* Reassociate multiplication of constants so that we can do * constant folding. */ if (op_const[0] && !op_const[1]) - reassociate_constant(ir, 0, op_const[0], - ir->operands[1]->as_expression()); + reassociate_constant(ir, 0, op_const[0], op_expr[1]); if (op_const[1] && !op_const[0]) - reassociate_constant(ir, 1, op_const[1], - ir->operands[0]->as_expression()); + reassociate_constant(ir, 1, op_const[1], op_expr[0]); break; case ir_binop_div: if (is_vec_one(op_const[0]) && ir->type->base_type == GLSL_TYPE_FLOAT) { - this->progress = true; - temp = new(mem_ctx) ir_expression(ir_unop_rcp, + return new(mem_ctx) ir_expression(ir_unop_rcp, ir->operands[1]->type, ir->operands[1], NULL); - return swizzle_if_required(ir, temp); - } - if (is_vec_one(op_const[1])) { - this->progress = true; - return swizzle_if_required(ir, ir->operands[0]); } + if (is_vec_one(op_const[1])) + return ir->operands[0]; break; case ir_binop_dot: - if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) { - this->progress = true; + if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) return ir_constant::zero(mem_ctx, ir->type); - } + if (is_vec_basis(op_const[0])) { - this->progress = true; unsigned component = 0; for (unsigned c = 0; c < op_const[0]->type->vector_elements; c++) { if (op_const[0]->value.f[c] == 1.0) @@ -330,7 +438,6 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) return new(mem_ctx) ir_swizzle(ir->operands[1], component, 0, 0, 0, 1); } if (is_vec_basis(op_const[1])) { - this->progress = true; unsigned component = 0; for (unsigned c = 0; c < op_const[1]->type->vector_elements; c++) { if (op_const[1]->value.f[c] == 1.0) @@ -340,46 +447,77 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) } break; + case ir_binop_less: + case ir_binop_lequal: + case ir_binop_greater: + case ir_binop_gequal: + case ir_binop_equal: + case ir_binop_nequal: + for (int add_pos = 0; add_pos < 2; add_pos++) { + ir_expression *add = op_expr[add_pos]; + + if (!add || add->operation != ir_binop_add) + continue; + + ir_constant *zero = op_const[1 - add_pos]; + if (!is_vec_zero(zero)) + continue; + + return new(mem_ctx) ir_expression(ir->operation, + add->operands[0], + neg(add->operands[1])); + } + break; + + case ir_binop_rshift: + case ir_binop_lshift: + /* 0 >> x == 0 */ + if (is_vec_zero(op_const[0])) + return ir->operands[0]; + /* x >> 0 == x */ + if (is_vec_zero(op_const[1])) + return ir->operands[0]; + break; + case ir_binop_logic_and: - /* FINISHME: Also simplify (a && a) to (a). */ if (is_vec_one(op_const[0])) { - this->progress = true; return ir->operands[1]; } else if (is_vec_one(op_const[1])) { - this->progress = true; return ir->operands[0]; } else if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) { - this->progress = true; return ir_constant::zero(mem_ctx, ir->type); + } else if (op_expr[0] && op_expr[0]->operation == ir_unop_logic_not && + op_expr[1] && op_expr[1]->operation == ir_unop_logic_not) { + /* De Morgan's Law: + * (not A) and (not B) === not (A or B) + */ + return logic_not(logic_or(op_expr[0]->operands[0], + op_expr[1]->operands[0])); + } else if (ir->operands[0]->equals(ir->operands[1])) { + /* (a && a) == a */ + return ir->operands[0]; } break; case ir_binop_logic_xor: - /* FINISHME: Also simplify (a ^^ a) to (false). */ if (is_vec_zero(op_const[0])) { - this->progress = true; return ir->operands[1]; } else if (is_vec_zero(op_const[1])) { - this->progress = true; return ir->operands[0]; } else if (is_vec_one(op_const[0])) { - this->progress = true; - return new(mem_ctx) ir_expression(ir_unop_logic_not, ir->type, - ir->operands[1], NULL); + return logic_not(ir->operands[1]); } else if (is_vec_one(op_const[1])) { - this->progress = true; - return new(mem_ctx) ir_expression(ir_unop_logic_not, ir->type, - ir->operands[0], NULL); + return logic_not(ir->operands[0]); + } else if (ir->operands[0]->equals(ir->operands[1])) { + /* (a ^^ a) == false */ + return ir_constant::zero(mem_ctx, ir->type); } break; case ir_binop_logic_or: - /* FINISHME: Also simplify (a || a) to (a). */ if (is_vec_zero(op_const[0])) { - this->progress = true; return ir->operands[1]; } else if (is_vec_zero(op_const[1])) { - this->progress = true; return ir->operands[0]; } else if (is_vec_one(op_const[0]) || is_vec_one(op_const[1])) { ir_constant_data data; @@ -387,45 +525,97 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) for (unsigned i = 0; i < 16; i++) data.b[i] = true; - this->progress = true; return new(mem_ctx) ir_constant(ir->type, &data); + } else if (op_expr[0] && op_expr[0]->operation == ir_unop_logic_not && + op_expr[1] && op_expr[1]->operation == ir_unop_logic_not) { + /* De Morgan's Law: + * (not A) or (not B) === not (A and B) + */ + return logic_not(logic_and(op_expr[0]->operands[0], + op_expr[1]->operands[0])); + } else if (ir->operands[0]->equals(ir->operands[1])) { + /* (a || a) == a */ + return ir->operands[0]; + } + break; + + case ir_binop_pow: + /* 1^x == 1 */ + if (is_vec_one(op_const[0])) + return op_const[0]; + + /* x^1 == x */ + if (is_vec_one(op_const[1])) + return ir->operands[0]; + + /* pow(2,x) == exp2(x) */ + if (is_vec_two(op_const[0])) + return expr(ir_unop_exp2, ir->operands[1]); + + if (is_vec_two(op_const[1])) { + ir_variable *x = new(ir) ir_variable(ir->operands[1]->type, "x", + ir_var_temporary); + base_ir->insert_before(x); + base_ir->insert_before(assign(x, ir->operands[0])); + return mul(x, x); } + break; case ir_unop_rcp: - if (op_expr[0] && op_expr[0]->operation == ir_unop_rcp) { - this->progress = true; + if (op_expr[0] && op_expr[0]->operation == ir_unop_rcp) return op_expr[0]->operands[0]; - } - /* FINISHME: We should do rcp(rsq(x)) -> sqrt(x) for some - * backends, except that some backends will have done sqrt -> - * rcp(rsq(x)) and we don't want to undo it for them. + /* While ir_to_mesa.cpp will lower sqrt(x) to rcp(rsq(x)), it does so at + * its IR level, so we can always apply this transformation. */ + if (op_expr[0] && op_expr[0]->operation == ir_unop_rsq) + return sqrt(op_expr[0]->operands[0]); /* As far as we know, all backends are OK with rsq. */ if (op_expr[0] && op_expr[0]->operation == ir_unop_sqrt) { - this->progress = true; - temp = new(mem_ctx) ir_expression(ir_unop_rsq, - op_expr[0]->operands[0]->type, - op_expr[0]->operands[0], - NULL); - return swizzle_if_required(ir, temp); + return rsq(op_expr[0]->operands[0]); } break; + case ir_triop_fma: + /* Operands are op0 * op1 + op2. */ + if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) { + return ir->operands[2]; + } else if (is_vec_zero(op_const[2])) { + return mul(ir->operands[0], ir->operands[1]); + } else if (is_vec_one(op_const[0])) { + return add(ir->operands[1], ir->operands[2]); + } else if (is_vec_one(op_const[1])) { + return add(ir->operands[0], ir->operands[2]); + } + break; + case ir_triop_lrp: /* Operands are (x, y, a). */ if (is_vec_zero(op_const[2])) { - this->progress = true; - return swizzle_if_required(ir, ir->operands[0]); + return ir->operands[0]; } else if (is_vec_one(op_const[2])) { - this->progress = true; - return swizzle_if_required(ir, ir->operands[1]); + return ir->operands[1]; + } else if (ir->operands[0]->equals(ir->operands[1])) { + return ir->operands[0]; + } else if (is_vec_zero(op_const[0])) { + return mul(ir->operands[1], ir->operands[2]); + } else if (is_vec_zero(op_const[1])) { + unsigned op2_components = ir->operands[2]->type->vector_elements; + ir_constant *one = new(mem_ctx) ir_constant(1.0f, op2_components); + return mul(ir->operands[0], add(one, neg(ir->operands[2]))); } break; + case ir_triop_csel: + if (is_vec_one(op_const[0])) + return ir->operands[1]; + if (is_vec_zero(op_const[0])) + return ir->operands[2]; + break; + default: break; } @@ -443,13 +633,23 @@ ir_algebraic_visitor::handle_rvalue(ir_rvalue **rvalue) if (!expr || expr->operation == ir_quadop_vector) return; - *rvalue = handle_expression(expr); + ir_rvalue *new_rvalue = handle_expression(expr); + if (new_rvalue == *rvalue) + return; + + /* If the expr used to be some vec OP scalar returning a vector, and the + * optimization gave us back a scalar, we still need to turn it into a + * vector. + */ + *rvalue = swizzle_if_required(expr, new_rvalue); + + this->progress = true; } bool -do_algebraic(exec_list *instructions) +do_algebraic(exec_list *instructions, bool native_integers) { - ir_algebraic_visitor v; + ir_algebraic_visitor v(native_integers); visit_list_elements(&v, instructions); diff --git a/dist/Mesa/src/glsl/opt_array_splitting.cpp b/dist/Mesa/src/glsl/opt_array_splitting.cpp index f4a7ef99b..97d3a57e9 100644 --- a/dist/Mesa/src/glsl/opt_array_splitting.cpp +++ b/dist/Mesa/src/glsl/opt_array_splitting.cpp @@ -40,6 +40,8 @@ static bool debug = false; +namespace { + namespace opt_array_splitting { class variable_entry : public exec_node @@ -77,6 +79,7 @@ public: }; } /* namespace */ + using namespace opt_array_splitting; /** @@ -112,13 +115,15 @@ public: void *mem_ctx; }; +} /* namespace */ + variable_entry * ir_array_reference_visitor::get_variable_entry(ir_variable *var) { assert(var); - if (var->mode != ir_var_auto && - var->mode != ir_var_temporary) + if (var->data.mode != ir_var_auto && + var->data.mode != ir_var_temporary) return NULL; if (!(var->type->is_array() || var->type->is_matrix())) @@ -127,11 +132,11 @@ ir_array_reference_visitor::get_variable_entry(ir_variable *var) /* If the array hasn't been sized yet, we can't split it. After * linking, this should be resolved. */ - if (var->type->is_array() && var->type->length == 0) + if (var->type->is_unsized_array()) return NULL; - foreach_iter(exec_list_iterator, iter, this->variable_list) { - variable_entry *entry = (variable_entry *)iter.get(); + foreach_list(n, &this->variable_list) { + variable_entry *entry = (variable_entry *) n; if (entry->var == var) return entry; } @@ -219,8 +224,8 @@ ir_array_reference_visitor::get_split_list(exec_list *instructions, } /* Trim out variables we found that we can't split. */ - foreach_iter(exec_list_iterator, iter, variable_list) { - variable_entry *entry = (variable_entry *)iter.get(); + foreach_list_safe(n, &variable_list) { + variable_entry *entry = (variable_entry *) n; if (debug) { printf("array %s@%p: decl %d, split %d\n", @@ -265,8 +270,8 @@ ir_array_splitting_visitor::get_splitting_entry(ir_variable *var) { assert(var); - foreach_iter(exec_list_iterator, iter, *this->variable_list) { - variable_entry *entry = (variable_entry *)iter.get(); + foreach_list(n, this->variable_list) { + variable_entry *entry = (variable_entry *) n; if (entry->var == var) { return entry; } @@ -363,8 +368,8 @@ optimize_split_arrays(exec_list *instructions, bool linked) /* Replace the decls of the arrays to be split with their split * components. */ - foreach_iter(exec_list_iterator, iter, refs.variable_list) { - variable_entry *entry = (variable_entry *)iter.get(); + foreach_list(n, &refs.variable_list) { + variable_entry *entry = (variable_entry *) n; const struct glsl_type *type = entry->var->type; const struct glsl_type *subtype; @@ -395,7 +400,7 @@ optimize_split_arrays(exec_list *instructions, bool linked) visit_list_elements(&split, instructions); if (debug) - _mesa_print_ir(instructions, NULL); + _mesa_print_ir(stdout, instructions, NULL); ralloc_free(mem_ctx); diff --git a/dist/Mesa/src/glsl/opt_cse.cpp b/dist/Mesa/src/glsl/opt_cse.cpp new file mode 100644 index 000000000..1b8782bcb --- /dev/null +++ b/dist/Mesa/src/glsl/opt_cse.cpp @@ -0,0 +1,423 @@ +/* + * Copyright © 2013 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_cse.cpp + * + * constant subexpression elimination at the GLSL IR level. + * + * Compare to brw_fs_cse.cpp for a more complete CSE implementation. This one + * is generic and handles texture operations, but it's rather simple currently + * and doesn't support modification of variables in the available expressions + * list, so it can't do variables other than uniforms or shader inputs. + */ + +#include "ir.h" +#include "ir_visitor.h" +#include "ir_rvalue_visitor.h" +#include "ir_basic_block.h" +#include "ir_optimization.h" +#include "ir_builder.h" +#include "glsl_types.h" + +using namespace ir_builder; + +static bool debug = false; + +namespace { + +/** + * This is the record of an available expression for common subexpression + * elimination. + */ +class ae_entry : public exec_node +{ +public: + ae_entry(ir_instruction *base_ir, ir_rvalue **val) + : val(val), base_ir(base_ir) + { + assert(val); + assert(*val); + assert(base_ir); + + var = NULL; + } + + /** + * The pointer to the expression that we might be able to reuse + * + * Note the double pointer -- this is the place in the base_ir expression + * tree that we would rewrite to move the expression out to a new variable + * assignment. + */ + ir_rvalue **val; + + /** + * Root instruction in the basic block where the expression appeared. + * + * This is used so that we can insert the new variable declaration into the + * instruction stream (since *val is just somewhere in base_ir's expression + * tree). + */ + ir_instruction *base_ir; + + /** + * The variable that the expression has been stored in, if it's been CSEd + * once already. + */ + ir_variable *var; +}; + +class cse_visitor : public ir_rvalue_visitor { +public: + cse_visitor(exec_list *validate_instructions) + : validate_instructions(validate_instructions) + { + progress = false; + mem_ctx = ralloc_context(NULL); + this->ae = new(mem_ctx) exec_list; + } + ~cse_visitor() + { + ralloc_free(mem_ctx); + } + + virtual ir_visitor_status visit_enter(ir_function_signature *ir); + virtual ir_visitor_status visit_enter(ir_loop *ir); + virtual ir_visitor_status visit_enter(ir_if *ir); + virtual ir_visitor_status visit_enter(ir_call *ir); + virtual void handle_rvalue(ir_rvalue **rvalue); + + bool progress; + +private: + void *mem_ctx; + + ir_rvalue *try_cse(ir_rvalue *rvalue); + void add_to_ae(ir_rvalue **rvalue); + + /** List of ae_entry: The available expressions to reuse */ + exec_list *ae; + + /** + * The whole shader, so that we can validate_ir_tree in debug mode. + * + * This proved quite useful when trying to get the tree manipulation + * right. + */ + exec_list *validate_instructions; +}; + +/** + * Visitor to walk an expression tree to check that all variables referenced + * are constants. + */ +class is_cse_candidate_visitor : public ir_hierarchical_visitor +{ +public: + + is_cse_candidate_visitor() + : ok(true) + { + } + + virtual ir_visitor_status visit(ir_dereference_variable *ir); + + bool ok; +}; + + +class contains_rvalue_visitor : public ir_rvalue_visitor +{ +public: + + contains_rvalue_visitor(ir_rvalue *val) + : val(val) + { + found = false; + } + + virtual void handle_rvalue(ir_rvalue **rvalue); + + bool found; + +private: + ir_rvalue *val; +}; + +} /* unnamed namespace */ + +static void +dump_ae(exec_list *ae) +{ + int i = 0; + + printf("CSE: AE contents:\n"); + foreach_list(node, ae) { + ae_entry *entry = (ae_entry *)node; + + printf("CSE: AE %2d (%p): ", i, entry); + (*entry->val)->print(); + printf("\n"); + + if (entry->var) + printf("CSE: in var %p:\n", entry->var); + + i++; + } +} + +ir_visitor_status +is_cse_candidate_visitor::visit(ir_dereference_variable *ir) +{ + /* Currently, since we don't handle kills of the ae based on variables + * getting assigned, we can only handle constant variables. + */ + if (ir->var->data.read_only) { + return visit_continue; + } else { + ok = false; + return visit_stop; + } +} + +void +contains_rvalue_visitor::handle_rvalue(ir_rvalue **rvalue) +{ + if (*rvalue == val) + found = true; +} + +static bool +contains_rvalue(ir_rvalue *haystack, ir_rvalue *needle) +{ + contains_rvalue_visitor v(needle); + haystack->accept(&v); + return v.found; +} + +static bool +is_cse_candidate(ir_rvalue *ir) +{ + /* Our temporary variable assignment generation isn't ready to handle + * anything bigger than a vector. + */ + if (!ir->type->is_vector() && !ir->type->is_scalar()) + return false; + + /* Only handle expressions and textures currently. We may want to extend + * to variable-index array dereferences at some point. + */ + switch (ir->ir_type) { + case ir_type_expression: + case ir_type_texture: + break; + default: + return false; + } + + is_cse_candidate_visitor v; + + ir->accept(&v); + + return v.ok; +} + +/** + * Tries to find and return a reference to a previous computation of a given + * expression. + * + * Walk the list of available expressions checking if any of them match the + * rvalue, and if so, move the previous copy of the expression to a temporary + * and return a reference of the temporary. + */ +ir_rvalue * +cse_visitor::try_cse(ir_rvalue *rvalue) +{ + foreach_list(node, ae) { + ae_entry *entry = (ae_entry *)node; + + if (debug) { + printf("Comparing to AE %p: ", entry); + (*entry->val)->print(); + printf("\n"); + } + + if (!rvalue->equals(*entry->val)) + continue; + + if (debug) { + printf("CSE: Replacing: "); + (*entry->val)->print(); + printf("\n"); + printf("CSE: with: "); + rvalue->print(); + printf("\n"); + } + + if (!entry->var) { + ir_instruction *base_ir = entry->base_ir; + + ir_variable *var = new(rvalue) ir_variable(rvalue->type, + "cse", + ir_var_auto); + + /* Write the previous expression result into a new variable. */ + base_ir->insert_before(var); + ir_assignment *assignment = assign(var, *entry->val); + base_ir->insert_before(assignment); + + /* Replace the expression in the original tree with a deref of the + * variable, but keep tracking the expression for further reuse. + */ + *entry->val = new(rvalue) ir_dereference_variable(var); + entry->val = &assignment->rhs; + + entry->var = var; + + /* Update the base_irs in the AE list. We have to be sure that + * they're correct -- expressions from our base_ir that weren't moved + * need to stay in this base_ir (so that later consumption of them + * puts new variables between our new variable and our base_ir), but + * expressions from our base_ir that we *did* move need base_ir + * updated so that any further elimination from inside gets its new + * assignments put before our new assignment. + */ + foreach_list(fixup_node, ae) { + ae_entry *fixup_entry = (ae_entry *)fixup_node; + if (contains_rvalue(assignment->rhs, *fixup_entry->val)) + fixup_entry->base_ir = assignment; + } + + if (debug) + dump_ae(ae); + } + + /* Replace the expression in our current tree with the variable. */ + return new(rvalue) ir_dereference_variable(entry->var); + } + + return NULL; +} + +/** Add the rvalue to the list of available expressions for CSE. */ +void +cse_visitor::add_to_ae(ir_rvalue **rvalue) +{ + if (debug) { + printf("CSE: Add to AE: "); + (*rvalue)->print(); + printf("\n"); + } + + ae->push_tail(new(mem_ctx) ae_entry(base_ir, rvalue)); + + if (debug) + dump_ae(ae); +} + +void +cse_visitor::handle_rvalue(ir_rvalue **rvalue) +{ + if (!*rvalue) + return; + + if (debug) { + printf("CSE: handle_rvalue "); + (*rvalue)->print(); + printf("\n"); + } + + if (!is_cse_candidate(*rvalue)) + return; + + ir_rvalue *new_rvalue = try_cse(*rvalue); + if (new_rvalue) { + *rvalue = new_rvalue; + progress = true; + + if (debug) + validate_ir_tree(validate_instructions); + } else { + add_to_ae(rvalue); + } +} + +ir_visitor_status +cse_visitor::visit_enter(ir_if *ir) +{ + handle_rvalue(&ir->condition); + + ae->make_empty(); + visit_list_elements(this, &ir->then_instructions); + + ae->make_empty(); + visit_list_elements(this, &ir->else_instructions); + + ae->make_empty(); + return visit_continue_with_parent; +} + +ir_visitor_status +cse_visitor::visit_enter(ir_function_signature *ir) +{ + ae->make_empty(); + visit_list_elements(this, &ir->body); + + ae->make_empty(); + return visit_continue_with_parent; +} + +ir_visitor_status +cse_visitor::visit_enter(ir_loop *ir) +{ + ae->make_empty(); + visit_list_elements(this, &ir->body_instructions); + + ae->make_empty(); + return visit_continue_with_parent; +} + +ir_visitor_status +cse_visitor::visit_enter(ir_call *) +{ + /* Because call is an exec_list of ir_rvalues, handle_rvalue gets passed a + * pointer to the (ir_rvalue *) on the stack. Since we save those pointers + * in the AE list, we can't let handle_rvalue get called. + */ + return visit_continue_with_parent; +} + +/** + * Does a (uniform-value) constant subexpression elimination pass on the code + * present in the instruction stream. + */ +bool +do_cse(exec_list *instructions) +{ + cse_visitor v(instructions); + + visit_list_elements(&v, instructions); + + return v.progress; +} diff --git a/dist/Mesa/src/glsl/opt_dead_builtin_varyings.cpp b/dist/Mesa/src/glsl/opt_dead_builtin_varyings.cpp index 6745d5c64..6612592aa 100644 --- a/dist/Mesa/src/glsl/opt_dead_builtin_varyings.cpp +++ b/dist/Mesa/src/glsl/opt_dead_builtin_varyings.cpp @@ -42,9 +42,11 @@ * If any texture coordinate slots can be eliminated, the gl_TexCoord array is * broken down into separate vec4 variables with locations equal to * VARYING_SLOT_TEX0 + i. + * + * The same is done for the gl_FragData fragment shader output. */ -#include "main/imports.h" /* for snprintf */ +#include "main/core.h" /* for snprintf and ARRAY_SIZE */ #include "ir.h" #include "ir_rvalue_visitor.h" #include "ir_optimization.h" @@ -52,6 +54,7 @@ #include "glsl_types.h" #include "link_varyings.h" +namespace { /** * This obtains detailed information about built-in varyings from shader code. @@ -59,10 +62,14 @@ class varying_info_visitor : public ir_hierarchical_visitor { public: /* "mode" can be either ir_var_shader_in or ir_var_shader_out */ - varying_info_visitor(ir_variable_mode mode) + varying_info_visitor(ir_variable_mode mode, bool find_frag_outputs = false) : lower_texcoord_array(true), texcoord_array(NULL), texcoord_usage(0), + find_frag_outputs(find_frag_outputs), + lower_fragdata_array(true), + fragdata_array(NULL), + fragdata_usage(0), color_usage(0), tfeedback_color_usage(0), fog(NULL), @@ -78,8 +85,27 @@ public: { ir_variable *var = ir->variable_referenced(); - if (var && var->mode == this->mode && - var->location == VARYING_SLOT_TEX0) { + if (!var || var->data.mode != this->mode) + return visit_continue; + + if (this->find_frag_outputs && var->data.location == FRAG_RESULT_DATA0) { + this->fragdata_array = var; + + ir_constant *index = ir->array_index->as_constant(); + if (index == NULL) { + /* This is variable indexing. */ + this->fragdata_usage |= (1 << var->type->array_size()) - 1; + this->lower_fragdata_array = false; + } + else { + this->fragdata_usage |= 1 << index->get_uint_component(0); + } + + /* Don't visit the leaves of ir_dereference_array. */ + return visit_continue_with_parent; + } + + if (!this->find_frag_outputs && var->data.location == VARYING_SLOT_TEX0) { this->texcoord_array = var; ir_constant *index = ir->array_index->as_constant(); @@ -104,8 +130,17 @@ public: { ir_variable *var = ir->variable_referenced(); - if (var->mode == this->mode && var->type->is_array() && - var->location == VARYING_SLOT_TEX0) { + if (var->data.mode != this->mode || !var->type->is_array()) + return visit_continue; + + if (this->find_frag_outputs && var->data.location == FRAG_RESULT_DATA0) { + /* This is a whole array dereference. */ + this->fragdata_usage |= (1 << var->type->array_size()) - 1; + this->lower_fragdata_array = false; + return visit_continue; + } + + if (!this->find_frag_outputs && var->data.location == VARYING_SLOT_TEX0) { /* This is a whole array dereference like "gl_TexCoord = x;", * there's probably no point in lowering that. */ @@ -117,11 +152,15 @@ public: virtual ir_visitor_status visit(ir_variable *var) { - if (var->mode != this->mode) + if (var->data.mode != this->mode) + return visit_continue; + + /* Nothing to do here for fragment outputs. */ + if (this->find_frag_outputs) return visit_continue; /* Handle colors and fog. */ - switch (var->location) { + switch (var->data.location) { case VARYING_SLOT_COL0: this->color[0] = var; this->color_usage |= 1; @@ -184,12 +223,20 @@ public: if (!this->texcoord_array) { this->lower_texcoord_array = false; } + if (!this->fragdata_array) { + this->lower_fragdata_array = false; + } } bool lower_texcoord_array; ir_variable *texcoord_array; unsigned texcoord_usage; /* bitmask */ + bool find_frag_outputs; /* false if it's looking for varyings */ + bool lower_fragdata_array; + ir_variable *fragdata_array; + unsigned fragdata_usage; /* bitmask */ + ir_variable *color[2]; ir_variable *backcolor[2]; unsigned color_usage; /* bitmask */ @@ -221,6 +268,7 @@ public: { void *const ctx = ir; + memset(this->new_fragdata, 0, sizeof(this->new_fragdata)); memset(this->new_texcoord, 0, sizeof(this->new_texcoord)); memset(this->new_color, 0, sizeof(this->new_color)); memset(this->new_backcolor, 0, sizeof(this->new_backcolor)); @@ -235,31 +283,16 @@ public: * occurences of gl_TexCoord will be replaced with. */ if (info->lower_texcoord_array) { - for (int i = MAX_TEXTURE_COORD_UNITS-1; i >= 0; i--) { - if (info->texcoord_usage & (1 << i)) { - char name[32]; - - if (!(external_texcoord_usage & (1 << i))) { - /* This varying is unused in the next stage. Declare - * a temporary instead of an output. */ - snprintf(name, 32, "gl_%s_TexCoord%i_dummy", mode_str, i); - this->new_texcoord[i] = - new (ctx) ir_variable(glsl_type::vec4_type, name, - ir_var_temporary); - } - else { - snprintf(name, 32, "gl_%s_TexCoord%i", mode_str, i); - this->new_texcoord[i] = - new(ctx) ir_variable(glsl_type::vec4_type, name, - info->mode); - this->new_texcoord[i]->location = VARYING_SLOT_TEX0 + i; - this->new_texcoord[i]->explicit_location = true; - this->new_texcoord[i]->explicit_index = 0; - } - - ir->head->insert_before(new_texcoord[i]); - } - } + prepare_array(ir, this->new_texcoord, ARRAY_SIZE(this->new_texcoord), + VARYING_SLOT_TEX0, "TexCoord", mode_str, + info->texcoord_usage, external_texcoord_usage); + } + + /* Handle gl_FragData in the same way like gl_TexCoord. */ + if (info->lower_fragdata_array) { + prepare_array(ir, this->new_fragdata, ARRAY_SIZE(this->new_fragdata), + FRAG_RESULT_DATA0, "FragData", mode_str, + info->fragdata_usage, (1 << MAX_DRAW_BUFFERS) - 1); } /* Create dummy variables which will replace set-but-unused color and @@ -300,6 +333,41 @@ public: visit_list_elements(this, ir); } + void prepare_array(exec_list *ir, + struct ir_variable **new_var, + int max_elements, unsigned start_location, + const char *var_name, const char *mode_str, + unsigned usage, unsigned external_usage) + { + void *const ctx = ir; + + for (int i = max_elements-1; i >= 0; i--) { + if (usage & (1 << i)) { + char name[32]; + + if (!(external_usage & (1 << i))) { + /* This varying is unused in the next stage. Declare + * a temporary instead of an output. */ + snprintf(name, 32, "gl_%s_%s%i_dummy", mode_str, var_name, i); + new_var[i] = + new (ctx) ir_variable(glsl_type::vec4_type, name, + ir_var_temporary); + } + else { + snprintf(name, 32, "gl_%s_%s%i", mode_str, var_name, i); + new_var[i] = + new(ctx) ir_variable(glsl_type::vec4_type, name, + this->info->mode); + new_var[i]->data.location = start_location + i; + new_var[i]->data.explicit_location = true; + new_var[i]->data.explicit_index = 0; + } + + ir->head->insert_before(new_var[i]); + } + } + } + virtual ir_visitor_status visit(ir_variable *var) { /* Remove the gl_TexCoord array. */ @@ -308,6 +376,12 @@ public: var->remove(); } + /* Remove the gl_FragData array. */ + if (this->info->lower_fragdata_array && + var == this->info->fragdata_array) { + var->remove(); + } + /* Replace set-but-unused color and fog outputs with dummy variables. */ for (int i = 0; i < 2; i++) { if (var == this->info->color[i] && this->new_color[i]) { @@ -349,6 +423,19 @@ public: } } + /* Same for gl_FragData. */ + if (this->info->lower_fragdata_array) { + /* gl_FragData[i] occurence */ + ir_dereference_array *const da = (*rvalue)->as_dereference_array(); + + if (da && da->variable_referenced() == this->info->fragdata_array) { + unsigned i = da->array_index->as_constant()->get_uint_component(0); + + *rvalue = new(ctx) ir_dereference_variable(this->new_fragdata[i]); + return; + } + } + /* Replace set-but-unused color and fog outputs with dummy variables. */ ir_dereference_variable *const dv = (*rvalue)->as_dereference_variable(); if (!dv) @@ -391,12 +478,14 @@ public: private: const varying_info_visitor *info; - struct ir_variable *new_texcoord[MAX_TEXTURE_COORD_UNITS]; - struct ir_variable *new_color[2]; - struct ir_variable *new_backcolor[2]; - struct ir_variable *new_fog; + ir_variable *new_fragdata[MAX_DRAW_BUFFERS]; + ir_variable *new_texcoord[MAX_TEXTURE_COORD_UNITS]; + ir_variable *new_color[2]; + ir_variable *new_backcolor[2]; + ir_variable *new_fog; }; +} /* anonymous namespace */ static void lower_texcoord_array(exec_list *ir, const varying_info_visitor *info) @@ -406,6 +495,15 @@ lower_texcoord_array(exec_list *ir, const varying_info_visitor *info) 1 | 2, true); } +static void +lower_fragdata_array(exec_list *ir) +{ + varying_info_visitor info(ir_var_shader_out, true); + info.get(ir, 0, NULL); + + replace_varyings_visitor(ir, &info, 0, 0, 0); +} + void do_dead_builtin_varyings(struct gl_context *ctx, @@ -413,16 +511,16 @@ do_dead_builtin_varyings(struct gl_context *ctx, unsigned num_tfeedback_decls, tfeedback_decl *tfeedback_decls) { - /* This optimization has no effect with the core context and GLES2, because - * the built-in varyings we're eliminating here are not available there. - * - * EXT_separate_shader_objects doesn't allow this optimization, - * because a program object can be bound partially (e.g. only one - * stage of a program object can be bound). + /* Lower the gl_FragData array to separate variables. */ + if (consumer && consumer->Stage == MESA_SHADER_FRAGMENT) { + lower_fragdata_array(consumer->ir); + } + + /* Lowering of built-in varyings has no effect with the core context and + * GLES2, because they are not available there. */ if (ctx->API == API_OPENGL_CORE || - ctx->API == API_OPENGLES2 || - ctx->Extensions.EXT_separate_shader_objects) { + ctx->API == API_OPENGLES2) { return; } @@ -471,7 +569,7 @@ do_dead_builtin_varyings(struct gl_context *ctx, * This doesn't prevent elimination of the gl_TexCoord elements which * are not read by the fragment shader. We want to eliminate those anyway. */ - if (consumer->Type == GL_FRAGMENT_SHADER) { + if (consumer->Stage == MESA_SHADER_FRAGMENT) { producer_info.texcoord_usage = (1 << MAX_TEXTURE_COORD_UNITS) - 1; } diff --git a/dist/Mesa/src/glsl/opt_dead_code.cpp b/dist/Mesa/src/glsl/opt_dead_code.cpp index b65e5c2ce..af53d94fd 100644 --- a/dist/Mesa/src/glsl/opt_dead_code.cpp +++ b/dist/Mesa/src/glsl/opt_dead_code.cpp @@ -79,9 +79,9 @@ do_dead_code(exec_list *instructions, bool uniform_locations_assigned) /* Remove a single dead assignment to the variable we found. * Don't do so if it's a shader or function output, though. */ - if (entry->var->mode != ir_var_function_out && - entry->var->mode != ir_var_function_inout && - entry->var->mode != ir_var_shader_out) { + if (entry->var->data.mode != ir_var_function_out && + entry->var->data.mode != ir_var_function_inout && + entry->var->data.mode != ir_var_shader_out) { entry->assign->remove(); progress = true; @@ -99,7 +99,7 @@ do_dead_code(exec_list *instructions, bool uniform_locations_assigned) * stage. Also, once uniform locations have been assigned, the * declaration cannot be deleted. */ - if (entry->var->mode == ir_var_uniform && + if (entry->var->data.mode == ir_var_uniform && (uniform_locations_assigned || entry->var->constant_value)) continue; @@ -129,13 +129,12 @@ do_dead_code_unlinked(exec_list *instructions) { bool progress = false; - foreach_iter(exec_list_iterator, iter, *instructions) { - ir_instruction *ir = (ir_instruction *)iter.get(); + foreach_list(n, instructions) { + ir_instruction *ir = (ir_instruction *) n; ir_function *f = ir->as_function(); if (f) { - foreach_iter(exec_list_iterator, sigiter, *f) { - ir_function_signature *sig = - (ir_function_signature *) sigiter.get(); + foreach_list(signode, &f->signatures) { + ir_function_signature *sig = (ir_function_signature *) signode; /* The setting of the uniform_locations_assigned flag here is * irrelevent. If there is a uniform declaration encountered * inside the body of the function, something has already gone diff --git a/dist/Mesa/src/glsl/opt_flip_matrices.cpp b/dist/Mesa/src/glsl/opt_flip_matrices.cpp index 2107b1d47..9044fd680 100644 --- a/dist/Mesa/src/glsl/opt_flip_matrices.cpp +++ b/dist/Mesa/src/glsl/opt_flip_matrices.cpp @@ -104,8 +104,8 @@ matrix_flipper::visit_enter(ir_expression *ir) var_ref->var = texmat_transpose; - texmat_transpose->max_array_access = - MAX2(texmat_transpose->max_array_access, mat_var->max_array_access); + texmat_transpose->data.max_array_access = + MAX2(texmat_transpose->data.max_array_access, mat_var->data.max_array_access); progress = true; } diff --git a/dist/Mesa/src/glsl/opt_vectorize.cpp b/dist/Mesa/src/glsl/opt_vectorize.cpp new file mode 100644 index 000000000..f9a3b6183 --- /dev/null +++ b/dist/Mesa/src/glsl/opt_vectorize.cpp @@ -0,0 +1,395 @@ +/* + * Copyright © 2013 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_vectorize.cpp + * + * Combines scalar assignments of the same expression (modulo swizzle) to + * multiple channels of the same variable into a single vectorized expression + * and assignment. + * + * Many generated shaders contain scalarized code. That is, they contain + * + * r1.x = log2(v0.x); + * r1.y = log2(v0.y); + * r1.z = log2(v0.z); + * + * rather than + * + * r1.xyz = log2(v0.xyz); + * + * We look for consecutive assignments of the same expression (modulo swizzle) + * to each channel of the same variable. + * + * For instance, we want to convert these three scalar operations + * + * (assign (x) (var_ref r1) (expression float log2 (swiz x (var_ref v0)))) + * (assign (y) (var_ref r1) (expression float log2 (swiz y (var_ref v0)))) + * (assign (z) (var_ref r1) (expression float log2 (swiz z (var_ref v0)))) + * + * into a single vector operation + * + * (assign (xyz) (var_ref r1) (expression vec3 log2 (swiz xyz (var_ref v0)))) + */ + +#include "ir.h" +#include "ir_visitor.h" +#include "ir_optimization.h" +#include "glsl_types.h" +#include "program/prog_instruction.h" + +namespace { + +class ir_vectorize_visitor : public ir_hierarchical_visitor { +public: + void clear() + { + assignment[0] = NULL; + assignment[1] = NULL; + assignment[2] = NULL; + assignment[3] = NULL; + current_assignment = NULL; + last_assignment = NULL; + channels = 0; + has_swizzle = false; + } + + ir_vectorize_visitor() + { + clear(); + progress = false; + } + + virtual ir_visitor_status visit_enter(ir_assignment *); + virtual ir_visitor_status visit_enter(ir_swizzle *); + virtual ir_visitor_status visit_enter(ir_dereference_array *); + virtual ir_visitor_status visit_enter(ir_expression *); + virtual ir_visitor_status visit_enter(ir_if *); + virtual ir_visitor_status visit_enter(ir_loop *); + + virtual ir_visitor_status visit_leave(ir_assignment *); + + void try_vectorize(); + + ir_assignment *assignment[4]; + ir_assignment *current_assignment, *last_assignment; + unsigned channels; + bool has_swizzle; + + bool progress; +}; + +} /* unnamed namespace */ + +/** + * Rewrites the swizzles and types of a right-hand side of an assignment. + * + * From the example above, this function would be called (by visit_tree()) on + * the nodes of the tree (expression float log2 (swiz z (var_ref v0))), + * rewriting it into (expression vec3 log2 (swiz xyz (var_ref v0))). + * + * The function operates on ir_expressions (and its operands) and ir_swizzles. + * For expressions it sets a new type and swizzles any non-expression and non- + * swizzle scalar operands into appropriately sized vector arguments. For + * example, if combining + * + * (assign (x) (var_ref r1) (expression float + (swiz x (var_ref v0) (var_ref v1)))) + * (assign (y) (var_ref r1) (expression float + (swiz y (var_ref v0) (var_ref v1)))) + * + * where v1 is a scalar, rewrite_swizzle() would insert a swizzle on + * (var_ref v1) such that the final result was + * + * (assign (xy) (var_ref r1) (expression vec2 + (swiz xy (var_ref v0)) + * (swiz xx (var_ref v1)))) + * + * For swizzles, it sets a new type, and if the variable being swizzled is a + * vector it overwrites the swizzle mask with the ir_swizzle_mask passed as the + * data parameter. If the swizzled variable is scalar, then the swizzle was + * added by an earlier call to rewrite_swizzle() on an expression, so the + * mask should not be modified. + */ +static void +rewrite_swizzle(ir_instruction *ir, void *data) +{ + ir_swizzle_mask *mask = (ir_swizzle_mask *)data; + + switch (ir->ir_type) { + case ir_type_swizzle: { + ir_swizzle *swz = (ir_swizzle *)ir; + if (swz->val->type->is_vector()) { + swz->mask = *mask; + } + swz->type = glsl_type::get_instance(swz->type->base_type, + mask->num_components, 1); + break; + } + case ir_type_expression: { + ir_expression *expr = (ir_expression *)ir; + expr->type = glsl_type::get_instance(expr->type->base_type, + mask->num_components, 1); + for (unsigned i = 0; i < 4; i++) { + if (expr->operands[i]) { + ir_rvalue *rval = expr->operands[i]->as_rvalue(); + if (rval && rval->type->is_scalar() && + !rval->as_expression() && !rval->as_swizzle()) { + expr->operands[i] = new(ir) ir_swizzle(rval, 0, 0, 0, 0, + mask->num_components); + } + } + } + break; + } + default: + break; + } +} + +/** + * Attempt to vectorize the previously saved assignments, and clear them from + * consideration. + * + * If the assignments are able to be combined, it modifies in-place the last + * assignment seen to be an equivalent vector form of the scalar assignments. + * It then removes the other now obsolete scalar assignments. + */ +void +ir_vectorize_visitor::try_vectorize() +{ + if (this->last_assignment && this->channels > 1) { + ir_swizzle_mask mask = {0, 0, 0, 0, channels, 0}; + + this->last_assignment->write_mask = 0; + + for (unsigned i = 0, j = 0; i < 4; i++) { + if (this->assignment[i]) { + this->last_assignment->write_mask |= 1 << i; + + if (this->assignment[i] != this->last_assignment) { + this->assignment[i]->remove(); + } + + switch (j) { + case 0: mask.x = i; break; + case 1: mask.y = i; break; + case 2: mask.z = i; break; + case 3: mask.w = i; break; + } + + j++; + } + } + + visit_tree(this->last_assignment->rhs, rewrite_swizzle, &mask); + + this->progress = true; + } + clear(); +} + +/** + * Returns whether the write mask is a single channel. + */ +static bool +single_channel_write_mask(unsigned write_mask) +{ + return write_mask != 0 && (write_mask & (write_mask - 1)) == 0; +} + +/** + * Translates single-channeled write mask to single-channeled swizzle. + */ +static unsigned +write_mask_to_swizzle(unsigned write_mask) +{ + switch (write_mask) { + case WRITEMASK_X: return SWIZZLE_X; + case WRITEMASK_Y: return SWIZZLE_Y; + case WRITEMASK_Z: return SWIZZLE_Z; + case WRITEMASK_W: return SWIZZLE_W; + } + assert(!"not reached"); + unreachable(); +} + +/** + * Returns whether a single-channeled write mask matches a swizzle. + */ +static bool +write_mask_matches_swizzle(unsigned write_mask, + const ir_swizzle *swz) +{ + return ((write_mask == WRITEMASK_X && swz->mask.x == SWIZZLE_X) || + (write_mask == WRITEMASK_Y && swz->mask.x == SWIZZLE_Y) || + (write_mask == WRITEMASK_Z && swz->mask.x == SWIZZLE_Z) || + (write_mask == WRITEMASK_W && swz->mask.x == SWIZZLE_W)); +} + +/** + * Upon entering an ir_assignment, attempt to vectorize the currently tracked + * assignments if the current assignment is not suitable. Keep a pointer to + * the current assignment. + */ +ir_visitor_status +ir_vectorize_visitor::visit_enter(ir_assignment *ir) +{ + ir_dereference *lhs = this->last_assignment != NULL ? + this->last_assignment->lhs : NULL; + ir_rvalue *rhs = this->last_assignment != NULL ? + this->last_assignment->rhs : NULL; + + if (ir->condition || + this->channels >= 4 || + !single_channel_write_mask(ir->write_mask) || + this->assignment[write_mask_to_swizzle(ir->write_mask)] != NULL || + (lhs && !ir->lhs->equals(lhs)) || + (rhs && !ir->rhs->equals(rhs, ir_type_swizzle))) { + try_vectorize(); + } + + this->current_assignment = ir; + + return visit_continue; +} + +/** + * Upon entering an ir_swizzle, set ::has_swizzle if we're visiting from an + * ir_assignment (i.e., that ::current_assignment is set) and the swizzle mask + * matches the current assignment's write mask. + * + * If the write mask doesn't match the swizzle mask, remove the current + * assignment from further consideration. + */ +ir_visitor_status +ir_vectorize_visitor::visit_enter(ir_swizzle *ir) +{ + if (this->current_assignment) { + if (write_mask_matches_swizzle(this->current_assignment->write_mask, ir)) { + this->has_swizzle = true; + } else { + this->current_assignment = NULL; + } + } + return visit_continue; +} + +/* Upon entering an ir_array_dereference, remove the current assignment from + * further consideration. Since the index of an array dereference must scalar, + * we are not able to vectorize it. + * + * FINISHME: If all of scalar indices are identical we could vectorize. + */ +ir_visitor_status +ir_vectorize_visitor::visit_enter(ir_dereference_array *) +{ + this->current_assignment = NULL; + return visit_continue_with_parent; +} + +/** + * Upon entering an ir_expression, remove the current assignment from further + * consideration if the expression operates horizontally on vectors. + */ +ir_visitor_status +ir_vectorize_visitor::visit_enter(ir_expression *ir) +{ + if (ir->is_horizontal()) { + this->current_assignment = NULL; + return visit_continue_with_parent; + } + return visit_continue; +} + +/* Since there is no statement to visit between the "then" and "else" + * instructions try to vectorize before, in between, and after them to avoid + * combining statements from different basic blocks. + */ +ir_visitor_status +ir_vectorize_visitor::visit_enter(ir_if *ir) +{ + try_vectorize(); + + visit_list_elements(this, &ir->then_instructions); + try_vectorize(); + + visit_list_elements(this, &ir->else_instructions); + try_vectorize(); + + return visit_continue_with_parent; +} + +/* Since there is no statement to visit between the instructions in the body of + * the loop and the instructions after it try to vectorize before and after the + * body to avoid combining statements from different basic blocks. + */ +ir_visitor_status +ir_vectorize_visitor::visit_enter(ir_loop *ir) +{ + try_vectorize(); + + visit_list_elements(this, &ir->body_instructions); + try_vectorize(); + + return visit_continue_with_parent; +} + +/** + * Upon leaving an ir_assignment, save a pointer to it in ::assignment[] if + * the swizzle mask(s) found were appropriate. Also save a pointer in + * ::last_assignment so that we can compare future assignments with it. + * + * Finally, clear ::current_assignment and ::has_swizzle. + */ +ir_visitor_status +ir_vectorize_visitor::visit_leave(ir_assignment *ir) +{ + if (this->has_swizzle && this->current_assignment) { + assert(this->current_assignment == ir); + + unsigned channel = write_mask_to_swizzle(this->current_assignment->write_mask); + this->assignment[channel] = ir; + this->channels++; + + this->last_assignment = this->current_assignment; + } + this->current_assignment = NULL; + this->has_swizzle = false; + return visit_continue; +} + +/** + * Combines scalar assignments of the same expression (modulo swizzle) to + * multiple channels of the same variable into a single vectorized expression + * and assignment. + */ +bool +do_vectorize(exec_list *instructions) +{ + ir_vectorize_visitor v; + + v.run(instructions); + + /* Try to vectorize the last assignments seen. */ + v.try_vectorize(); + + return v.progress; +} diff --git a/dist/Mesa/src/glsl/ralloc.h b/dist/Mesa/src/glsl/ralloc.h index 67eb93833..4581a7a4e 100644 --- a/dist/Mesa/src/glsl/ralloc.h +++ b/dist/Mesa/src/glsl/ralloc.h @@ -404,4 +404,42 @@ bool ralloc_vasprintf_append(char **str, const char *fmt, va_list args); } /* end of extern "C" */ #endif +/** + * Declare C++ new and delete operators which use ralloc. + * + * Placing this macro in the body of a class makes it possible to do: + * + * TYPE *var = new(mem_ctx) TYPE(...); + * delete var; + * + * which is more idiomatic in C++ than calling ralloc. + */ +#define DECLARE_RALLOC_CXX_OPERATORS(TYPE) \ +private: \ + static void _ralloc_destructor(void *p) \ + { \ + reinterpret_cast<TYPE *>(p)->~TYPE(); \ + } \ +public: \ + static void* operator new(size_t size, void *mem_ctx) \ + { \ + void *p = ralloc_size(mem_ctx, size); \ + assert(p != NULL); \ + if (!HAS_TRIVIAL_DESTRUCTOR(TYPE)) \ + ralloc_set_destructor(p, _ralloc_destructor); \ + return p; \ + } \ + \ + static void operator delete(void *p) \ + { \ + /* The object's destructor is guaranteed to have already been \ + * called by the delete operator at this point -- Make sure it's \ + * not called again. \ + */ \ + if (!HAS_TRIVIAL_DESTRUCTOR(TYPE)) \ + ralloc_set_destructor(p, NULL); \ + ralloc_free(p); \ + } + + #endif diff --git a/dist/Mesa/src/glsl/standalone_scaffolding.cpp b/dist/Mesa/src/glsl/standalone_scaffolding.cpp index 11cd6cdc0..6c25010b7 100644 --- a/dist/Mesa/src/glsl/standalone_scaffolding.cpp +++ b/dist/Mesa/src/glsl/standalone_scaffolding.cpp @@ -76,6 +76,7 @@ _mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type) shader = rzalloc(NULL, struct gl_shader); if (shader) { shader->Type = type; + shader->Stage = _mesa_shader_enum_to_shader_stage(type); shader->Name = name; shader->RefCount = 1; } @@ -90,21 +91,36 @@ void initialize_context_to_defaults(struct gl_context *ctx, gl_api api) ctx->Extensions.dummy_false = false; ctx->Extensions.dummy_true = true; - ctx->Extensions.ARB_ES2_compatibility = true; - ctx->Extensions.ARB_ES3_compatibility = false; + ctx->Extensions.ARB_compute_shader = true; + ctx->Extensions.ARB_conservative_depth = true; ctx->Extensions.ARB_draw_instanced = true; + ctx->Extensions.ARB_ES2_compatibility = true; + ctx->Extensions.ARB_ES3_compatibility = true; + ctx->Extensions.ARB_explicit_attrib_location = true; ctx->Extensions.ARB_fragment_coord_conventions = true; - ctx->Extensions.EXT_texture_array = true; - ctx->Extensions.NV_texture_rectangle = true; - ctx->Extensions.EXT_texture3D = true; - ctx->Extensions.OES_EGL_image_external = true; + ctx->Extensions.ARB_gpu_shader5 = true; + ctx->Extensions.ARB_sample_shading = true; ctx->Extensions.ARB_shader_bit_encoding = true; + ctx->Extensions.ARB_shader_stencil_export = true; + ctx->Extensions.ARB_shader_texture_lod = true; + ctx->Extensions.ARB_shading_language_420pack = true; ctx->Extensions.ARB_shading_language_packing = true; - ctx->Extensions.OES_standard_derivatives = true; ctx->Extensions.ARB_texture_cube_map_array = true; + ctx->Extensions.ARB_texture_gather = true; ctx->Extensions.ARB_texture_multisample = true; + ctx->Extensions.ARB_texture_query_levels = true; ctx->Extensions.ARB_texture_query_lod = true; - ctx->Extensions.ARB_gpu_shader5 = true; + ctx->Extensions.ARB_uniform_buffer_object = true; + ctx->Extensions.ARB_viewport_array = true; + + ctx->Extensions.OES_EGL_image_external = true; + ctx->Extensions.OES_standard_derivatives = true; + + ctx->Extensions.EXT_shader_integer_mix = true; + ctx->Extensions.EXT_texture3D = true; + ctx->Extensions.EXT_texture_array = true; + + ctx->Extensions.NV_texture_rectangle = true; ctx->Const.GLSLVersion = 120; @@ -113,16 +129,29 @@ void initialize_context_to_defaults(struct gl_context *ctx, gl_api api) ctx->Const.MaxClipPlanes = 6; ctx->Const.MaxTextureUnits = 2; ctx->Const.MaxTextureCoordUnits = 2; - ctx->Const.VertexProgram.MaxAttribs = 16; + ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs = 16; - ctx->Const.VertexProgram.MaxUniformComponents = 512; + ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents = 512; + ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents = 32; ctx->Const.MaxVarying = 8; /* == gl_MaxVaryingFloats / 4 */ - ctx->Const.VertexProgram.MaxTextureImageUnits = 0; + ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = 0; ctx->Const.MaxCombinedTextureImageUnits = 2; - ctx->Const.FragmentProgram.MaxTextureImageUnits = 2; - ctx->Const.FragmentProgram.MaxUniformComponents = 64; + ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = 2; + ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents = 64; + ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxInputComponents = 32; ctx->Const.MaxDrawBuffers = 1; + ctx->Const.MaxComputeWorkGroupCount[0] = 65535; + ctx->Const.MaxComputeWorkGroupCount[1] = 65535; + ctx->Const.MaxComputeWorkGroupCount[2] = 65535; + ctx->Const.MaxComputeWorkGroupSize[0] = 1024; + ctx->Const.MaxComputeWorkGroupSize[1] = 1024; + ctx->Const.MaxComputeWorkGroupSize[2] = 64; + ctx->Const.MaxComputeWorkGroupInvocations = 1024; + ctx->Const.Program[MESA_SHADER_COMPUTE].MaxTextureImageUnits = 16; + ctx->Const.Program[MESA_SHADER_COMPUTE].MaxUniformComponents = 1024; + ctx->Const.Program[MESA_SHADER_COMPUTE].MaxInputComponents = 0; /* not used */ + ctx->Const.Program[MESA_SHADER_COMPUTE].MaxOutputComponents = 0; /* not used */ /* Set up default shader compiler options. */ struct gl_shader_compiler_options options; @@ -133,6 +162,6 @@ void initialize_context_to_defaults(struct gl_context *ctx, gl_api api) /* Default pragma settings */ options.DefaultPragmas.Optimize = true; - for (int sh = 0; sh < MESA_SHADER_TYPES; ++sh) + for (int sh = 0; sh < MESA_SHADER_STAGES; ++sh) memcpy(&ctx->ShaderCompilerOptions[sh], &options, sizeof(options)); } diff --git a/dist/Mesa/src/glsl/standalone_scaffolding.h b/dist/Mesa/src/glsl/standalone_scaffolding.h index 7afb1c313..df783afdb 100644 --- a/dist/Mesa/src/glsl/standalone_scaffolding.h +++ b/dist/Mesa/src/glsl/standalone_scaffolding.h @@ -48,8 +48,8 @@ extern "C" void _mesa_shader_debug(struct gl_context *ctx, GLenum type, GLuint *id, const char *msg, int len); -static inline gl_shader_type -_mesa_shader_type_to_index(GLenum v) +static inline gl_shader_stage +_mesa_shader_enum_to_shader_stage(GLenum v) { switch (v) { case GL_VERTEX_SHADER: @@ -58,9 +58,11 @@ _mesa_shader_type_to_index(GLenum v) return MESA_SHADER_FRAGMENT; case GL_GEOMETRY_SHADER: return MESA_SHADER_GEOMETRY; + case GL_COMPUTE_SHADER: + return MESA_SHADER_COMPUTE; default: - assert(!"bad value in _mesa_shader_type_to_index()"); - return MESA_SHADER_TYPES; + assert(!"bad value in _mesa_shader_enum_to_shader_stage()"); + return MESA_SHADER_VERTEX; } } diff --git a/dist/Mesa/src/glsl/test_optpass.cpp b/dist/Mesa/src/glsl/test_optpass.cpp index 67e2ab2b1..db5cb2662 100644 --- a/dist/Mesa/src/glsl/test_optpass.cpp +++ b/dist/Mesa/src/glsl/test_optpass.cpp @@ -62,11 +62,10 @@ do_optimization(struct exec_list *ir, const char *optimization, int int_3; int int_4; - if (sscanf(optimization, "do_common_optimization ( %d , %d ) ", - &int_0, &int_1) == 2) { - return do_common_optimization(ir, int_0 != 0, false, int_1, options); + if (sscanf(optimization, "do_common_optimization ( %d ) ", &int_0) == 1) { + return do_common_optimization(ir, int_0 != 0, false, options, true); } else if (strcmp(optimization, "do_algebraic") == 0) { - return do_algebraic(ir); + return do_algebraic(ir, true); } else if (strcmp(optimization, "do_constant_folding") == 0) { return do_constant_folding(ir); } else if (strcmp(optimization, "do_constant_variable") == 0) { @@ -204,11 +203,12 @@ int test_optpass(int argc, char **argv) struct gl_shader *shader = rzalloc(NULL, struct gl_shader); shader->Type = shader_type; + shader->Stage = _mesa_shader_enum_to_shader_stage(shader_type); string input = read_stdin_to_eof(); struct _mesa_glsl_parse_state *state - = new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader); + = new(shader) _mesa_glsl_parse_state(ctx, shader->Stage, shader); if (input_format_ir) { shader->ir = new(shader) exec_list; @@ -234,7 +234,7 @@ int test_optpass(int argc, char **argv) /* Print out the initial IR */ if (!state->error && !quiet) { printf("*** pre-optimization IR:\n"); - _mesa_print_ir(shader->ir, state); + _mesa_print_ir(stdout, shader->ir, state); printf("\n--\n"); } @@ -242,7 +242,7 @@ int test_optpass(int argc, char **argv) if (!state->error) { GLboolean progress; const struct gl_shader_compiler_options *options = - &ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(shader_type)]; + &ctx->ShaderCompilerOptions[_mesa_shader_enum_to_shader_stage(shader_type)]; do { progress = do_optimization_passes(shader->ir, &argv[optind], argc - optind, quiet != 0, options); @@ -254,7 +254,7 @@ int test_optpass(int argc, char **argv) if (!quiet) { printf("*** resulting IR:\n"); } - _mesa_print_ir(shader->ir, state); + _mesa_print_ir(stdout, shader->ir, state); if (!quiet) { printf("\n--\n"); } diff --git a/dist/Mesa/src/glsl/tests/builtin_variable_test.cpp b/dist/Mesa/src/glsl/tests/builtin_variable_test.cpp new file mode 100644 index 000000000..3fdfce57d --- /dev/null +++ b/dist/Mesa/src/glsl/tests/builtin_variable_test.cpp @@ -0,0 +1,394 @@ +/* + * Copyright © 2013 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. + */ +#include <gtest/gtest.h> +#include "standalone_scaffolding.h" +#include "main/compiler.h" +#include "main/mtypes.h" +#include "main/macros.h" +#include "ralloc.h" +#include "ir.h" +#include "glsl_parser_extras.h" +#include "glsl_symbol_table.h" + +class common_builtin : public ::testing::Test { +public: + common_builtin(GLenum shader_type) + : shader_type(shader_type) + { + /* empty */ + } + + virtual void SetUp(); + virtual void TearDown(); + + void string_starts_with_prefix(const char *str, const char *prefix); + void names_start_with_gl(); + void uniforms_and_system_values_dont_have_explicit_location(); + void constants_are_constant(); + void no_invalid_variable_modes(); + + GLenum shader_type; + struct _mesa_glsl_parse_state *state; + struct gl_shader *shader; + void *mem_ctx; + gl_context ctx; + exec_list ir; +}; + +void +common_builtin::SetUp() +{ + this->mem_ctx = ralloc_context(NULL); + this->ir.make_empty(); + + initialize_context_to_defaults(&this->ctx, API_OPENGL_COMPAT); + + this->shader = rzalloc(this->mem_ctx, gl_shader); + this->shader->Type = this->shader_type; + this->shader->Stage = _mesa_shader_enum_to_shader_stage(this->shader_type); + + this->state = + new(mem_ctx) _mesa_glsl_parse_state(&this->ctx, this->shader->Stage, + this->shader); + + _mesa_glsl_initialize_types(this->state); + _mesa_glsl_initialize_variables(&this->ir, this->state); +} + +void +common_builtin::TearDown() +{ + ralloc_free(this->mem_ctx); + this->mem_ctx = NULL; +} + +void +common_builtin::string_starts_with_prefix(const char *str, const char *prefix) +{ + const size_t len = strlen(prefix); + char *const name_prefix = new char[len + 1]; + + strncpy(name_prefix, str, len); + name_prefix[len] = '\0'; + EXPECT_STREQ(prefix, name_prefix) << "Bad name " << str; + + delete [] name_prefix; +} + +void +common_builtin::names_start_with_gl() +{ + foreach_list(node, &this->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + string_starts_with_prefix(var->name, "gl_"); + } +} + +void +common_builtin::uniforms_and_system_values_dont_have_explicit_location() +{ + foreach_list(node, &this->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + if (var->data.mode != ir_var_uniform && var->data.mode != ir_var_system_value) + continue; + + EXPECT_FALSE(var->data.explicit_location); + EXPECT_EQ(-1, var->data.location); + } +} + +void +common_builtin::constants_are_constant() +{ + foreach_list(node, &this->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + if (var->data.mode != ir_var_auto) + continue; + + EXPECT_FALSE(var->data.explicit_location); + EXPECT_EQ(-1, var->data.location); + EXPECT_TRUE(var->data.read_only); + } +} + +void +common_builtin::no_invalid_variable_modes() +{ + foreach_list(node, &this->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + switch (var->data.mode) { + case ir_var_auto: + case ir_var_uniform: + case ir_var_shader_in: + case ir_var_shader_out: + case ir_var_system_value: + break; + + default: + ADD_FAILURE() << "Built-in variable " << var->name + << " has an invalid mode " << int(var->data.mode); + break; + } + } +} + +/************************************************************/ + +class vertex_builtin : public common_builtin { +public: + vertex_builtin() + : common_builtin(GL_VERTEX_SHADER) + { + /* empty */ + } +}; + +TEST_F(vertex_builtin, names_start_with_gl) +{ + common_builtin::names_start_with_gl(); +} + +TEST_F(vertex_builtin, inputs_have_explicit_location) +{ + foreach_list(node, &this->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + if (var->data.mode != ir_var_shader_in) + continue; + + EXPECT_TRUE(var->data.explicit_location); + EXPECT_NE(-1, var->data.location); + EXPECT_GT(VERT_ATTRIB_GENERIC0, var->data.location); + EXPECT_EQ(0u, var->data.location_frac); + } +} + +TEST_F(vertex_builtin, outputs_have_explicit_location) +{ + foreach_list(node, &this->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + if (var->data.mode != ir_var_shader_out) + continue; + + EXPECT_TRUE(var->data.explicit_location); + EXPECT_NE(-1, var->data.location); + EXPECT_GT(VARYING_SLOT_VAR0, var->data.location); + EXPECT_EQ(0u, var->data.location_frac); + + /* Several varyings only exist in the fragment shader. Be sure that no + * outputs with these locations exist. + */ + EXPECT_NE(VARYING_SLOT_PNTC, var->data.location); + EXPECT_NE(VARYING_SLOT_FACE, var->data.location); + EXPECT_NE(VARYING_SLOT_PRIMITIVE_ID, var->data.location); + } +} + +TEST_F(vertex_builtin, uniforms_and_system_values_dont_have_explicit_location) +{ + common_builtin::uniforms_and_system_values_dont_have_explicit_location(); +} + +TEST_F(vertex_builtin, constants_are_constant) +{ + common_builtin::constants_are_constant(); +} + +TEST_F(vertex_builtin, no_invalid_variable_modes) +{ + common_builtin::no_invalid_variable_modes(); +} + +/********************************************************************/ + +class fragment_builtin : public common_builtin { +public: + fragment_builtin() + : common_builtin(GL_FRAGMENT_SHADER) + { + /* empty */ + } +}; + +TEST_F(fragment_builtin, names_start_with_gl) +{ + common_builtin::names_start_with_gl(); +} + +TEST_F(fragment_builtin, inputs_have_explicit_location) +{ + foreach_list(node, &this->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + if (var->data.mode != ir_var_shader_in) + continue; + + EXPECT_TRUE(var->data.explicit_location); + EXPECT_NE(-1, var->data.location); + EXPECT_GT(VARYING_SLOT_VAR0, var->data.location); + EXPECT_EQ(0u, var->data.location_frac); + + /* Several varyings only exist in the vertex / geometry shader. Be sure + * that no inputs with these locations exist. + */ + EXPECT_TRUE(_mesa_varying_slot_in_fs((gl_varying_slot) var->data.location)); + } +} + +TEST_F(fragment_builtin, outputs_have_explicit_location) +{ + foreach_list(node, &this->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + if (var->data.mode != ir_var_shader_out) + continue; + + EXPECT_TRUE(var->data.explicit_location); + EXPECT_NE(-1, var->data.location); + + /* gl_FragData[] has location FRAG_RESULT_DATA0. Locations beyond that + * are invalid. + */ + EXPECT_GE(FRAG_RESULT_DATA0, var->data.location); + + EXPECT_EQ(0u, var->data.location_frac); + } +} + +TEST_F(fragment_builtin, uniforms_and_system_values_dont_have_explicit_location) +{ + common_builtin::uniforms_and_system_values_dont_have_explicit_location(); +} + +TEST_F(fragment_builtin, constants_are_constant) +{ + common_builtin::constants_are_constant(); +} + +TEST_F(fragment_builtin, no_invalid_variable_modes) +{ + common_builtin::no_invalid_variable_modes(); +} + +/********************************************************************/ + +class geometry_builtin : public common_builtin { +public: + geometry_builtin() + : common_builtin(GL_GEOMETRY_SHADER) + { + /* empty */ + } +}; + +TEST_F(geometry_builtin, names_start_with_gl) +{ + common_builtin::names_start_with_gl(); +} + +TEST_F(geometry_builtin, inputs_have_explicit_location) +{ + foreach_list(node, &this->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + if (var->data.mode != ir_var_shader_in) + continue; + + if (var->is_interface_instance()) { + EXPECT_STREQ("gl_in", var->name); + EXPECT_FALSE(var->data.explicit_location); + EXPECT_EQ(-1, var->data.location); + + ASSERT_TRUE(var->type->is_array()); + + const glsl_type *const instance_type = var->type->fields.array; + + for (unsigned i = 0; i < instance_type->length; i++) { + const glsl_struct_field *const input = + &instance_type->fields.structure[i]; + + string_starts_with_prefix(input->name, "gl_"); + EXPECT_NE(-1, input->location); + EXPECT_GT(VARYING_SLOT_VAR0, input->location); + + /* Several varyings only exist in the fragment shader. Be sure + * that no inputs with these locations exist. + */ + EXPECT_NE(VARYING_SLOT_PNTC, input->location); + EXPECT_NE(VARYING_SLOT_FACE, input->location); + } + } else { + EXPECT_TRUE(var->data.explicit_location); + EXPECT_NE(-1, var->data.location); + EXPECT_GT(VARYING_SLOT_VAR0, var->data.location); + EXPECT_EQ(0u, var->data.location_frac); + } + + /* Several varyings only exist in the fragment shader. Be sure that no + * inputs with these locations exist. + */ + EXPECT_NE(VARYING_SLOT_PNTC, var->data.location); + EXPECT_NE(VARYING_SLOT_FACE, var->data.location); + } +} + +TEST_F(geometry_builtin, outputs_have_explicit_location) +{ + foreach_list(node, &this->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + if (var->data.mode != ir_var_shader_out) + continue; + + EXPECT_TRUE(var->data.explicit_location); + EXPECT_NE(-1, var->data.location); + EXPECT_GT(VARYING_SLOT_VAR0, var->data.location); + EXPECT_EQ(0u, var->data.location_frac); + + /* Several varyings only exist in the fragment shader. Be sure that no + * outputs with these locations exist. + */ + EXPECT_NE(VARYING_SLOT_PNTC, var->data.location); + EXPECT_NE(VARYING_SLOT_FACE, var->data.location); + } +} + +TEST_F(geometry_builtin, uniforms_and_system_values_dont_have_explicit_location) +{ + common_builtin::uniforms_and_system_values_dont_have_explicit_location(); +} + +TEST_F(geometry_builtin, constants_are_constant) +{ + common_builtin::constants_are_constant(); +} + +TEST_F(geometry_builtin, no_invalid_variable_modes) +{ + common_builtin::no_invalid_variable_modes(); +} diff --git a/dist/Mesa/src/glsl/tests/common.c b/dist/Mesa/src/glsl/tests/common.c new file mode 100644 index 000000000..d69f54d1d --- /dev/null +++ b/dist/Mesa/src/glsl/tests/common.c @@ -0,0 +1,30 @@ +/* + * 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. + */ +#include <stdio.h> +#include "main/errors.h" + +void +_mesa_error_no_memory(const char *caller) +{ + fprintf(stderr, "Mesa error: out of memory in %s", caller); +} diff --git a/dist/Mesa/src/glsl/tests/general_ir_test.cpp b/dist/Mesa/src/glsl/tests/general_ir_test.cpp new file mode 100644 index 000000000..862fa19ab --- /dev/null +++ b/dist/Mesa/src/glsl/tests/general_ir_test.cpp @@ -0,0 +1,89 @@ +/* + * Copyright © 2013 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. + */ +#include <gtest/gtest.h> +#include "main/compiler.h" +#include "main/mtypes.h" +#include "main/macros.h" +#include "ralloc.h" +#include "ir.h" + +TEST(ir_variable_constructor, interface) +{ + void *mem_ctx = ralloc_context(NULL); + + static const glsl_struct_field f[] = { + { + glsl_type::vec(4), + "v", + false + } + }; + + const glsl_type *const interface = + glsl_type::get_interface_instance(f, + ARRAY_SIZE(f), + GLSL_INTERFACE_PACKING_STD140, + "simple_interface"); + + static const char name[] = "named_instance"; + + ir_variable *const v = + new(mem_ctx) ir_variable(interface, name, ir_var_uniform); + + EXPECT_STREQ(name, v->name); + EXPECT_NE(name, v->name); + EXPECT_EQ(interface, v->type); + EXPECT_EQ(interface, v->get_interface_type()); +} + +TEST(ir_variable_constructor, interface_array) +{ + void *mem_ctx = ralloc_context(NULL); + + static const glsl_struct_field f[] = { + { + glsl_type::vec(4), + "v", + false + } + }; + + const glsl_type *const interface = + glsl_type::get_interface_instance(f, + ARRAY_SIZE(f), + GLSL_INTERFACE_PACKING_STD140, + "simple_interface"); + + const glsl_type *const interface_array = + glsl_type::get_array_instance(interface, 2); + + static const char name[] = "array_instance"; + + ir_variable *const v = + new(mem_ctx) ir_variable(interface_array, name, ir_var_uniform); + + EXPECT_STREQ(name, v->name); + EXPECT_NE(name, v->name); + EXPECT_EQ(interface_array, v->type); + EXPECT_EQ(interface, v->get_interface_type()); +} diff --git a/dist/Mesa/src/glsl/tests/invalidate_locations_test.cpp b/dist/Mesa/src/glsl/tests/invalidate_locations_test.cpp new file mode 100644 index 000000000..997592fc9 --- /dev/null +++ b/dist/Mesa/src/glsl/tests/invalidate_locations_test.cpp @@ -0,0 +1,196 @@ +/* + * Copyright © 2013 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. + */ +#include <gtest/gtest.h> +#include "main/compiler.h" +#include "main/mtypes.h" +#include "main/macros.h" +#include "ralloc.h" +#include "ir.h" +#include "linker.h" + +/** + * \file varyings_test.cpp + * + * Test various aspects of linking shader stage inputs and outputs. + */ + +class invalidate_locations : public ::testing::Test { +public: + virtual void SetUp(); + virtual void TearDown(); + + void *mem_ctx; + exec_list ir; +}; + +void +invalidate_locations::SetUp() +{ + this->mem_ctx = ralloc_context(NULL); + this->ir.make_empty(); +} + +void +invalidate_locations::TearDown() +{ + ralloc_free(this->mem_ctx); + this->mem_ctx = NULL; +} + +TEST_F(invalidate_locations, simple_vertex_in_generic) +{ + ir_variable *const var = + new(mem_ctx) ir_variable(glsl_type::vec(4), + "a", + ir_var_shader_in); + + EXPECT_FALSE(var->data.explicit_location); + EXPECT_EQ(-1, var->data.location); + + var->data.location = VERT_ATTRIB_GENERIC0; + var->data.location_frac = 2; + + ir.push_tail(var); + + link_invalidate_variable_locations(&ir); + + EXPECT_EQ(-1, var->data.location); + EXPECT_EQ(0u, var->data.location_frac); + EXPECT_FALSE(var->data.explicit_location); + EXPECT_TRUE(var->data.is_unmatched_generic_inout); +} + +TEST_F(invalidate_locations, explicit_location_vertex_in_generic) +{ + ir_variable *const var = + new(mem_ctx) ir_variable(glsl_type::vec(4), + "a", + ir_var_shader_in); + + EXPECT_FALSE(var->data.explicit_location); + EXPECT_EQ(-1, var->data.location); + + var->data.location = VERT_ATTRIB_GENERIC0; + var->data.explicit_location = true; + + ir.push_tail(var); + + link_invalidate_variable_locations(&ir); + + EXPECT_EQ(VERT_ATTRIB_GENERIC0, var->data.location); + EXPECT_EQ(0u, var->data.location_frac); + EXPECT_TRUE(var->data.explicit_location); + EXPECT_FALSE(var->data.is_unmatched_generic_inout); +} + +TEST_F(invalidate_locations, explicit_location_frac_vertex_in_generic) +{ + ir_variable *const var = + new(mem_ctx) ir_variable(glsl_type::vec(4), + "a", + ir_var_shader_in); + + EXPECT_FALSE(var->data.explicit_location); + EXPECT_EQ(-1, var->data.location); + + var->data.location = VERT_ATTRIB_GENERIC0; + var->data.location_frac = 2; + var->data.explicit_location = true; + + ir.push_tail(var); + + link_invalidate_variable_locations(&ir); + + EXPECT_EQ(VERT_ATTRIB_GENERIC0, var->data.location); + EXPECT_EQ(2u, var->data.location_frac); + EXPECT_TRUE(var->data.explicit_location); + EXPECT_FALSE(var->data.is_unmatched_generic_inout); +} + +TEST_F(invalidate_locations, vertex_in_builtin) +{ + ir_variable *const var = + new(mem_ctx) ir_variable(glsl_type::vec(4), + "gl_Vertex", + ir_var_shader_in); + + EXPECT_FALSE(var->data.explicit_location); + EXPECT_EQ(-1, var->data.location); + + var->data.location = VERT_ATTRIB_POS; + var->data.explicit_location = true; + + ir.push_tail(var); + + link_invalidate_variable_locations(&ir); + + EXPECT_EQ(VERT_ATTRIB_POS, var->data.location); + EXPECT_EQ(0u, var->data.location_frac); + EXPECT_TRUE(var->data.explicit_location); + EXPECT_FALSE(var->data.is_unmatched_generic_inout); +} + +TEST_F(invalidate_locations, simple_vertex_out_generic) +{ + ir_variable *const var = + new(mem_ctx) ir_variable(glsl_type::vec(4), + "a", + ir_var_shader_out); + + EXPECT_FALSE(var->data.explicit_location); + EXPECT_EQ(-1, var->data.location); + + var->data.location = VARYING_SLOT_VAR0; + + ir.push_tail(var); + + link_invalidate_variable_locations(&ir); + + EXPECT_EQ(-1, var->data.location); + EXPECT_EQ(0u, var->data.location_frac); + EXPECT_FALSE(var->data.explicit_location); + EXPECT_TRUE(var->data.is_unmatched_generic_inout); +} + +TEST_F(invalidate_locations, vertex_out_builtin) +{ + ir_variable *const var = + new(mem_ctx) ir_variable(glsl_type::vec(4), + "gl_FrontColor", + ir_var_shader_out); + + EXPECT_FALSE(var->data.explicit_location); + EXPECT_EQ(-1, var->data.location); + + var->data.location = VARYING_SLOT_COL0; + var->data.explicit_location = true; + + ir.push_tail(var); + + link_invalidate_variable_locations(&ir); + + EXPECT_EQ(VARYING_SLOT_COL0, var->data.location); + EXPECT_EQ(0u, var->data.location_frac); + EXPECT_TRUE(var->data.explicit_location); + EXPECT_FALSE(var->data.is_unmatched_generic_inout); +} diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/create_test_cases.py b/dist/Mesa/src/glsl/tests/lower_jumps/create_test_cases.py index fbc6f0a84..9974681e0 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/create_test_cases.py +++ b/dist/Mesa/src/glsl/tests/lower_jumps/create_test_cases.py @@ -291,7 +291,7 @@ def create_test_case(doc_string, input_sexp, expected_sexp, test_name, args = ['../../glsl_test', 'optpass', '--quiet', '--input-ir', optimization] test_file = '{0}.opt_test'.format(test_name) with open(test_file, 'w') as f: - f.write('#!/bin/bash\n#\n# This file was generated by create_test_cases.py.\n#\n') + f.write('#!/usr/bin/env bash\n#\n# This file was generated by create_test_cases.py.\n#\n') f.write(doc_string) f.write('{0} <<EOF\n'.format(bash_quote(*args))) f.write('{0}\nEOF\n'.format(input_str)) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_1.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_1.opt_test index 01ad7087a..b412ba8f2 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_1.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_1.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # @@ -8,6 +8,6 @@ ((declare (out) float a) (function main (signature void (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))) break)))))) EOF diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_1.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_1.opt_test.expected index d4bb6fc02..56ef3e424 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_1.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_1.opt_test.expected @@ -1,5 +1,5 @@ ((declare (out) float a) (function main (signature void (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))) break)))))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_2.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_2.opt_test index 0be22f953..f5de80339 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_2.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_2.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # @@ -8,7 +8,7 @@ ((declare (in) float b) (declare (out) float a) (function main (signature void (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))) (if (expression bool > (var_ref b) (constant float (0.000000))) (break) ()))))))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_2.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_2.opt_test.expected index a4cb2d6a1..dc231f975 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_2.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_2.opt_test.expected @@ -1,7 +1,7 @@ ((declare (in) float b) (declare (out) float a) (function main (signature void (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))) - (if (expression bool > (var_ref b) (constant float (0.000000))) (break) + (if (expression bool > (var_ref b) (constant float (0.0))) (break) ()))))))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_3.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_3.opt_test index 4149360b5..60368bc1d 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_3.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_3.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # @@ -9,7 +9,7 @@ ((declare (in) float b) (declare (out) float a) (declare (out) float c) (function main (signature void (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))) (if (expression bool > (var_ref b) (constant float (0.000000))) ((assign (x) (var_ref c) (constant float (1.000000))) break) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_3.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_3.opt_test.expected index 325f7b49a..8131b66ff 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_3.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_3.opt_test.expected @@ -1,8 +1,8 @@ ((declare (in) float b) (declare (out) float a) (declare (out) float c) (function main (signature void (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))) - (if (expression bool > (var_ref b) (constant float (0.000000))) + (if (expression bool > (var_ref b) (constant float (0.0))) ((assign (x) (var_ref c) (constant float (1.000000))) break) ()))))))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_4.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_4.opt_test index 70458bb4f..cde319793 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_4.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_4.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # @@ -8,7 +8,7 @@ ((declare (in) float b) (declare (out) float a) (function main (signature void (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))) (if (expression bool > (var_ref b) (constant float (0.000000))) () (break)))))))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_4.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_4.opt_test.expected index a7735457c..94dcb37be 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_4.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_4.opt_test.expected @@ -1,7 +1,7 @@ ((declare (in) float b) (declare (out) float a) (function main (signature void (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))) - (if (expression bool > (var_ref b) (constant float (0.000000))) () + (if (expression bool > (var_ref b) (constant float (0.0))) () (break)))))))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_5.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_5.opt_test index da9eef110..157b5892f 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_5.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_5.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # @@ -9,7 +9,7 @@ ((declare (in) float b) (declare (out) float a) (declare (out) float c) (function main (signature void (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))) (if (expression bool > (var_ref b) (constant float (0.000000))) () ((assign (x) (var_ref c) (constant float (1.000000))) break)))))))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_5.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_5.opt_test.expected index 0dd4a5293..5b46ccb67 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_5.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_5.opt_test.expected @@ -1,7 +1,7 @@ ((declare (in) float b) (declare (out) float a) (declare (out) float c) (function main (signature void (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))) - (if (expression bool > (var_ref b) (constant float (0.000000))) () + (if (expression bool > (var_ref b) (constant float (0.0))) () ((assign (x) (var_ref c) (constant float (1.000000))) break)))))))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_6.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_6.opt_test index 9440dfec8..4767df13e 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_6.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_6.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # @@ -12,7 +12,7 @@ (declare (in) float cb) (function main (signature void (parameters) - ((loop () () () () + ((loop ((if (expression bool > (var_ref a) (constant float (0.000000))) ((if (expression bool > (var_ref ba) (constant float (0.000000))) ((if (expression bool > (var_ref bb) (constant float (0.000000))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_6.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_6.opt_test.expected index 8222328e0..967ce642a 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_6.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_breaks_6.opt_test.expected @@ -5,18 +5,18 @@ (signature void (parameters) ((declare (temporary) bool break_flag) (assign (x) (var_ref break_flag) (constant bool (0))) - (loop () () () () + (loop ((declare (temporary) bool execute_flag) (assign (x) (var_ref execute_flag) (constant bool (1))) - (if (expression bool > (var_ref a) (constant float (0.000000))) - ((if (expression bool > (var_ref ba) (constant float (0.000000))) - ((if (expression bool > (var_ref bb) (constant float (0.000000))) + (if (expression bool > (var_ref a) (constant float (0.0))) + ((if (expression bool > (var_ref ba) (constant float (0.0))) + ((if (expression bool > (var_ref bb) (constant float (0.0))) ((assign (x) (var_ref execute_flag) (constant bool (0)))) ())) ()) (if (var_ref execute_flag) - ((if (expression bool > (var_ref ca) (constant float (0.000000))) - ((if (expression bool > (var_ref cb) (constant float (0.000000))) + ((if (expression bool > (var_ref ca) (constant float (0.0))) + ((if (expression bool > (var_ref cb) (constant float (0.0))) ((assign (x) (var_ref break_flag) (constant bool (1))) (assign (x) (var_ref execute_flag) (constant bool (0)))) ())) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_guarded_conditional_break.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/lower_guarded_conditional_break.opt_test index 379aa59b5..164914a42 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_guarded_conditional_break.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_guarded_conditional_break.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # @@ -10,7 +10,7 @@ ((declare (in) float aa) (declare (in) float ab) (declare (in) float b) (function main (signature void (parameters) - ((loop () () () () + ((loop ((if (expression bool > (var_ref aa) (constant float (0.000000))) ((if (expression bool > (var_ref ab) (constant float (0.000000))) (continue) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_guarded_conditional_break.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/lower_guarded_conditional_break.opt_test.expected index 7c6e73f77..841073ed9 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_guarded_conditional_break.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_guarded_conditional_break.opt_test.expected @@ -3,16 +3,16 @@ (signature void (parameters) ((declare (temporary) bool break_flag) (assign (x) (var_ref break_flag) (constant bool (0))) - (loop () () () () + (loop ((declare (temporary) bool execute_flag) (assign (x) (var_ref execute_flag) (constant bool (1))) - (if (expression bool > (var_ref aa) (constant float (0.000000))) - ((if (expression bool > (var_ref ab) (constant float (0.000000))) + (if (expression bool > (var_ref aa) (constant float (0.0))) + ((if (expression bool > (var_ref ab) (constant float (0.0))) ((assign (x) (var_ref execute_flag) (constant bool (0)))) ())) ()) (if (var_ref execute_flag) - ((if (expression bool > (var_ref b) (constant float (0.000000))) + ((if (expression bool > (var_ref b) (constant float (0.0))) ((assign (x) (var_ref break_flag) (constant bool (1))) (assign (x) (var_ref execute_flag) (constant bool (0)))) ())) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_pulled_out_jump.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/lower_pulled_out_jump.opt_test index 15f3c41d5..1a5c09690 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_pulled_out_jump.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_pulled_out_jump.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # @@ -19,7 +19,7 @@ ((return)) ())) ()) - (loop () () () () + (loop ((if (expression bool > (var_ref b) (constant float (0.000000))) ((if (expression bool > (var_ref c) (constant float (0.000000))) (break) (continue))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_pulled_out_jump.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/lower_pulled_out_jump.opt_test.expected index bf45c2c93..cf2ef3f08 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_pulled_out_jump.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_pulled_out_jump.opt_test.expected @@ -7,16 +7,16 @@ (assign (x) (var_ref execute_flag) (constant bool (1))) (declare (temporary) bool return_flag) (assign (x) (var_ref return_flag) (constant bool (0))) - (if (expression bool > (var_ref aa) (constant float (0.000000))) - ((if (expression bool > (var_ref ab) (constant float (0.000000))) + (if (expression bool > (var_ref aa) (constant float (0.0))) + ((if (expression bool > (var_ref ab) (constant float (0.0))) ((assign (x) (var_ref return_flag) (constant bool (1))) (assign (x) (var_ref execute_flag) (constant bool (0)))) ())) ()) (if (var_ref execute_flag) - ((loop () () () () - ((if (expression bool > (var_ref b) (constant float (0.000000))) - ((if (expression bool > (var_ref c) (constant float (0.000000))) () + ((loop + ((if (expression bool > (var_ref b) (constant float (0.0))) + ((if (expression bool > (var_ref c) (constant float (0.0))) () (continue))) ((assign (x) (var_ref return_flag) (constant bool (1))))) break)) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_1.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_1.opt_test index a1f895bbf..e73c51208 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_1.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_1.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_2.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_2.opt_test index 61673d4ef..da2dc7ee2 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_2.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_2.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_3.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_3.opt_test index 9881e2492..9509781fe 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_3.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_3.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_3.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_3.opt_test.expected index d4835e96b..5b62bbcde 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_3.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_3.opt_test.expected @@ -6,8 +6,8 @@ (declare (temporary) float return_value) (declare (temporary) bool return_flag) (assign (x) (var_ref return_flag) (constant bool (0))) - (if (expression bool > (var_ref a) (constant float (0.000000))) - ((if (expression bool > (var_ref b) (constant float (0.000000))) + (if (expression bool > (var_ref a) (constant float (0.0))) + ((if (expression bool > (var_ref b) (constant float (0.0))) ((assign (x) (var_ref return_value) (constant float (1.000000))) (assign (x) (var_ref return_flag) (constant bool (1))) (assign (x) (var_ref execute_flag) (constant bool (0)))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_4.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_4.opt_test index 9f54c67a1..c5bb9c898 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_4.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_4.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_4.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_4.opt_test.expected index b551a066f..07c6842d2 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_4.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_4.opt_test.expected @@ -6,7 +6,7 @@ (declare (temporary) float return_value) (declare (temporary) bool return_flag) (assign (x) (var_ref return_flag) (constant bool (0))) - (if (expression bool > (var_ref a) (constant float (0.000000))) + (if (expression bool > (var_ref a) (constant float (0.0))) ((assign (x) (var_ref return_value) (constant float (1.000000))) (assign (x) (var_ref return_flag) (constant bool (1))) (assign (x) (var_ref execute_flag) (constant bool (0)))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_main_false.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_main_false.opt_test index 5f97bfd3f..fdb1d0ed2 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_main_false.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_main_false.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_main_false.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_main_false.opt_test.expected index e8b36f144..7e3fe314f 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_main_false.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_main_false.opt_test.expected @@ -1,8 +1,8 @@ ((declare (in) float a) (declare (in) float b) (function main (signature void (parameters) - ((if (expression bool > (var_ref a) (constant float (0.000000))) - ((if (expression bool > (var_ref b) (constant float (0.000000))) + ((if (expression bool > (var_ref a) (constant float (0.0))) + ((if (expression bool > (var_ref b) (constant float (0.0))) ((return)) ())) ()))))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_main_true.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_main_true.opt_test index 59c7ba1dd..939ec8b0e 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_main_true.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_main_true.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_main_true.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_main_true.opt_test.expected index e15a97d1d..b47f5a433 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_main_true.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_main_true.opt_test.expected @@ -5,8 +5,8 @@ (assign (x) (var_ref execute_flag) (constant bool (1))) (declare (temporary) bool return_flag) (assign (x) (var_ref return_flag) (constant bool (0))) - (if (expression bool > (var_ref a) (constant float (0.000000))) - ((if (expression bool > (var_ref b) (constant float (0.000000))) + (if (expression bool > (var_ref a) (constant float (0.0))) + ((if (expression bool > (var_ref b) (constant float (0.0))) ((assign (x) (var_ref return_flag) (constant bool (1))) (assign (x) (var_ref execute_flag) (constant bool (0)))) ())) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_sub_false.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_sub_false.opt_test index 40e784e33..92a4e8a62 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_sub_false.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_sub_false.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_sub_false.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_sub_false.opt_test.expected index 07db6e708..7424968b2 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_sub_false.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_sub_false.opt_test.expected @@ -1,8 +1,8 @@ ((declare (in) float a) (declare (in) float b) (function sub (signature void (parameters) - ((if (expression bool > (var_ref a) (constant float (0.000000))) - ((if (expression bool > (var_ref b) (constant float (0.000000))) + ((if (expression bool > (var_ref a) (constant float (0.0))) + ((if (expression bool > (var_ref b) (constant float (0.0))) ((return)) ())) ()))))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_sub_true.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_sub_true.opt_test index 9fe6b90f0..789414ecb 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_sub_true.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_sub_true.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_sub_true.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_sub_true.opt_test.expected index 311098023..1a3eae5da 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_sub_true.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_returns_sub_true.opt_test.expected @@ -5,8 +5,8 @@ (assign (x) (var_ref execute_flag) (constant bool (1))) (declare (temporary) bool return_flag) (assign (x) (var_ref return_flag) (constant bool (0))) - (if (expression bool > (var_ref a) (constant float (0.000000))) - ((if (expression bool > (var_ref b) (constant float (0.000000))) + (if (expression bool > (var_ref a) (constant float (0.0))) + ((if (expression bool > (var_ref b) (constant float (0.0))) ((assign (x) (var_ref return_flag) (constant bool (1))) (assign (x) (var_ref execute_flag) (constant bool (0)))) ())) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_unified_returns.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/lower_unified_returns.opt_test index e71681314..5d6e51cff 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_unified_returns.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_unified_returns.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/lower_unified_returns.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/lower_unified_returns.opt_test.expected index 271cd3b46..c0b51e1ba 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/lower_unified_returns.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/lower_unified_returns.opt_test.expected @@ -6,15 +6,15 @@ (assign (x) (var_ref execute_flag) (constant bool (1))) (declare (temporary) bool return_flag) (assign (x) (var_ref return_flag) (constant bool (0))) - (if (expression bool > (var_ref aa) (constant float (0.000000))) - ((if (expression bool > (var_ref ab) (constant float (0.000000))) + (if (expression bool > (var_ref aa) (constant float (0.0))) + ((if (expression bool > (var_ref ab) (constant float (0.0))) ((assign (x) (var_ref return_flag) (constant bool (1))) (assign (x) (var_ref execute_flag) (constant bool (0)))) ())) ()) (if (var_ref execute_flag) - ((if (expression bool > (var_ref b) (constant float (0.000000))) - ((if (expression bool > (var_ref c) (constant float (0.000000))) () ()) + ((if (expression bool > (var_ref b) (constant float (0.0))) + ((if (expression bool > (var_ref c) (constant float (0.0))) () ()) (assign (x) (var_ref return_flag) (constant bool (1))) (assign (x) (var_ref execute_flag) (constant bool (0)))) ())) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/remove_continue_at_end_of_loop.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/remove_continue_at_end_of_loop.opt_test index 18efc37f6..8403bb204 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/remove_continue_at_end_of_loop.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/remove_continue_at_end_of_loop.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # @@ -8,6 +8,6 @@ ((declare (out) float a) (function main (signature void (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))) continue)))))) EOF diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/remove_continue_at_end_of_loop.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/remove_continue_at_end_of_loop.opt_test.expected index d2a02c6f3..98b74d71e 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/remove_continue_at_end_of_loop.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/remove_continue_at_end_of_loop.opt_test.expected @@ -1,5 +1,5 @@ ((declare (out) float a) (function main (signature void (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))))))))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_nothing.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_nothing.opt_test index 79c0e8245..1f62e7349 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_nothing.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_nothing.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # @@ -8,7 +8,7 @@ ((declare (out) float a) (declare (out) float b) (function sub (signature float (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))) (return (constant float (2.000000))))) (assign (x) (var_ref b) (constant float (3.000000))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_nothing.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_nothing.opt_test.expected index 2cf117a5e..040d383b6 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_nothing.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_nothing.opt_test.expected @@ -1,7 +1,7 @@ ((declare (out) float a) (declare (out) float b) (function sub (signature float (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))) (return (constant float (2.000000))))) (assign (x) (var_ref b) (constant float (3.000000))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return.opt_test index 920d2ad9f..42c4e7529 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # @@ -8,7 +8,7 @@ ((declare (out) float a) (declare (out) float b) (function sub (signature float (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))) (return (constant float (2.000000))))) (assign (x) (var_ref b) (constant float (3.000000))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return.opt_test.expected index 0bab8f16f..792cbf69a 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return.opt_test.expected @@ -6,7 +6,7 @@ (declare (temporary) float return_value) (declare (temporary) bool return_flag) (assign (x) (var_ref return_flag) (constant bool (0))) - (loop () () () () + (loop ((assign (x) (var_ref a) (constant float (1.000000))) (assign (x) (var_ref return_value) (constant float (2.000000))) (assign (x) (var_ref return_flag) (constant bool (1))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return_and_break.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return_and_break.opt_test index 99f1f8635..b3eef39b7 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return_and_break.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return_and_break.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # @@ -8,7 +8,7 @@ ((declare (out) float a) (declare (out) float b) (function sub (signature float (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))) (return (constant float (2.000000))))) (assign (x) (var_ref b) (constant float (3.000000))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return_and_break.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return_and_break.opt_test.expected index 0bab8f16f..792cbf69a 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return_and_break.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return_and_break.opt_test.expected @@ -6,7 +6,7 @@ (declare (temporary) float return_value) (declare (temporary) bool return_flag) (assign (x) (var_ref return_flag) (constant bool (0))) - (loop () () () () + (loop ((assign (x) (var_ref a) (constant float (1.000000))) (assign (x) (var_ref return_value) (constant float (2.000000))) (assign (x) (var_ref return_flag) (constant bool (1))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_nothing.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_nothing.opt_test index 63487d326..0408282d0 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_nothing.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_nothing.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # @@ -8,7 +8,7 @@ ((declare (out) float a) (declare (out) float b) (function main (signature void (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))) (return))) (assign (x) (var_ref b) (constant float (2.000000))))))) EOF diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_nothing.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_nothing.opt_test.expected index 0bd8037bf..569213e99 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_nothing.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_nothing.opt_test.expected @@ -1,6 +1,6 @@ ((declare (out) float a) (declare (out) float b) (function main (signature void (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))) (return))) (assign (x) (var_ref b) (constant float (2.000000))))))) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return.opt_test index 523c92a68..a7e65c86c 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # @@ -8,7 +8,7 @@ ((declare (out) float a) (declare (out) float b) (function main (signature void (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))) (return))) (assign (x) (var_ref b) (constant float (2.000000))))))) EOF diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return.opt_test.expected index 53814eaac..66f3aeca5 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return.opt_test.expected @@ -3,7 +3,7 @@ (signature void (parameters) ((declare (temporary) bool return_flag) (assign (x) (var_ref return_flag) (constant bool (0))) - (loop () () () () + (loop ((assign (x) (var_ref a) (constant float (1.000000))) (assign (x) (var_ref return_flag) (constant bool (1))) break)) diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return_and_break.opt_test b/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return_and_break.opt_test index 22b5581cb..7a5efe581 100755 --- a/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return_and_break.opt_test +++ b/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return_and_break.opt_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # This file was generated by create_test_cases.py. # @@ -8,7 +8,7 @@ ((declare (out) float a) (declare (out) float b) (function main (signature void (parameters) - ((loop () () () () + ((loop ((assign (x) (var_ref a) (constant float (1.000000))) (return))) (assign (x) (var_ref b) (constant float (2.000000))))))) EOF diff --git a/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return_and_break.opt_test.expected b/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return_and_break.opt_test.expected index 53814eaac..66f3aeca5 100644 --- a/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return_and_break.opt_test.expected +++ b/dist/Mesa/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return_and_break.opt_test.expected @@ -3,7 +3,7 @@ (signature void (parameters) ((declare (temporary) bool return_flag) (assign (x) (var_ref return_flag) (constant bool (0))) - (loop () () () () + (loop ((assign (x) (var_ref a) (constant float (1.000000))) (assign (x) (var_ref return_flag) (constant bool (1))) break)) diff --git a/dist/Mesa/src/glsl/tests/optimization-test b/dist/Mesa/src/glsl/tests/optimization-test index 59383f8f9..8ca777691 100755 --- a/dist/Mesa/src/glsl/tests/optimization-test +++ b/dist/Mesa/src/glsl/tests/optimization-test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash if [ ! -z "$srcdir" ]; then compare_ir=`pwd`/tests/compare_ir diff --git a/dist/Mesa/src/glsl/tests/sampler_types_test.cpp b/dist/Mesa/src/glsl/tests/sampler_types_test.cpp new file mode 100644 index 000000000..86d329a83 --- /dev/null +++ b/dist/Mesa/src/glsl/tests/sampler_types_test.cpp @@ -0,0 +1,101 @@ +/* + * Copyright © 2013 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. + */ +#include <gtest/gtest.h> +#include "main/compiler.h" +#include "main/mtypes.h" +#include "main/macros.h" +#include "ralloc.h" +#include "ir.h" + +/** + * \file sampler_types_test.cpp + * + * Test that built-in sampler types have the right properties. + */ + +#define ARRAY EXPECT_TRUE(type->sampler_array); +#define NONARRAY EXPECT_FALSE(type->sampler_array); +#define SHADOW EXPECT_TRUE(type->sampler_shadow); +#define COLOR EXPECT_FALSE(type->sampler_shadow); + +#define T(TYPE, DIM, DATA_TYPE, ARR, SHAD, COMPS) \ +TEST(sampler_types, TYPE) \ +{ \ + const glsl_type *type = glsl_type::TYPE##_type; \ + EXPECT_EQ(GLSL_TYPE_SAMPLER, type->base_type); \ + EXPECT_EQ(DIM, type->sampler_dimensionality); \ + EXPECT_EQ(DATA_TYPE, type->sampler_type); \ + ARR; \ + SHAD; \ + EXPECT_EQ(COMPS, type->coordinate_components()); \ +} + +T( sampler1D, GLSL_SAMPLER_DIM_1D, GLSL_TYPE_FLOAT, NONARRAY, COLOR, 1) +T( sampler2D, GLSL_SAMPLER_DIM_2D, GLSL_TYPE_FLOAT, NONARRAY, COLOR, 2) +T( sampler3D, GLSL_SAMPLER_DIM_3D, GLSL_TYPE_FLOAT, NONARRAY, COLOR, 3) +T( samplerCube, GLSL_SAMPLER_DIM_CUBE, GLSL_TYPE_FLOAT, NONARRAY, COLOR, 3) +T( sampler1DArray, GLSL_SAMPLER_DIM_1D, GLSL_TYPE_FLOAT, ARRAY, COLOR, 2) +T( sampler2DArray, GLSL_SAMPLER_DIM_2D, GLSL_TYPE_FLOAT, ARRAY, COLOR, 3) +T( samplerCubeArray, GLSL_SAMPLER_DIM_CUBE, GLSL_TYPE_FLOAT, ARRAY, COLOR, 4) +T( sampler2DRect, GLSL_SAMPLER_DIM_RECT, GLSL_TYPE_FLOAT, NONARRAY, COLOR, 2) +T( samplerBuffer, GLSL_SAMPLER_DIM_BUF, GLSL_TYPE_FLOAT, NONARRAY, COLOR, 1) +T( sampler2DMS, GLSL_SAMPLER_DIM_MS, GLSL_TYPE_FLOAT, NONARRAY, COLOR, 2) +T( sampler2DMSArray, GLSL_SAMPLER_DIM_MS, GLSL_TYPE_FLOAT, ARRAY, COLOR, 3) +T(isampler1D, GLSL_SAMPLER_DIM_1D, GLSL_TYPE_INT, NONARRAY, COLOR, 1) +T(isampler2D, GLSL_SAMPLER_DIM_2D, GLSL_TYPE_INT, NONARRAY, COLOR, 2) +T(isampler3D, GLSL_SAMPLER_DIM_3D, GLSL_TYPE_INT, NONARRAY, COLOR, 3) +T(isamplerCube, GLSL_SAMPLER_DIM_CUBE, GLSL_TYPE_INT, NONARRAY, COLOR, 3) +T(isampler1DArray, GLSL_SAMPLER_DIM_1D, GLSL_TYPE_INT, ARRAY, COLOR, 2) +T(isampler2DArray, GLSL_SAMPLER_DIM_2D, GLSL_TYPE_INT, ARRAY, COLOR, 3) +T(isamplerCubeArray, GLSL_SAMPLER_DIM_CUBE, GLSL_TYPE_INT, ARRAY, COLOR, 4) +T(isampler2DRect, GLSL_SAMPLER_DIM_RECT, GLSL_TYPE_INT, NONARRAY, COLOR, 2) +T(isamplerBuffer, GLSL_SAMPLER_DIM_BUF, GLSL_TYPE_INT, NONARRAY, COLOR, 1) +T(isampler2DMS, GLSL_SAMPLER_DIM_MS, GLSL_TYPE_INT, NONARRAY, COLOR, 2) +T(isampler2DMSArray, GLSL_SAMPLER_DIM_MS, GLSL_TYPE_INT, ARRAY, COLOR, 3) +T(usampler1D, GLSL_SAMPLER_DIM_1D, GLSL_TYPE_UINT, NONARRAY, COLOR, 1) +T(usampler2D, GLSL_SAMPLER_DIM_2D, GLSL_TYPE_UINT, NONARRAY, COLOR, 2) +T(usampler3D, GLSL_SAMPLER_DIM_3D, GLSL_TYPE_UINT, NONARRAY, COLOR, 3) +T(usamplerCube, GLSL_SAMPLER_DIM_CUBE, GLSL_TYPE_UINT, NONARRAY, COLOR, 3) +T(usampler1DArray, GLSL_SAMPLER_DIM_1D, GLSL_TYPE_UINT, ARRAY, COLOR, 2) +T(usampler2DArray, GLSL_SAMPLER_DIM_2D, GLSL_TYPE_UINT, ARRAY, COLOR, 3) +T(usamplerCubeArray, GLSL_SAMPLER_DIM_CUBE, GLSL_TYPE_UINT, ARRAY, COLOR, 4) +T(usampler2DRect, GLSL_SAMPLER_DIM_RECT, GLSL_TYPE_UINT, NONARRAY, COLOR, 2) +T(usamplerBuffer, GLSL_SAMPLER_DIM_BUF, GLSL_TYPE_UINT, NONARRAY, COLOR, 1) +T(usampler2DMS, GLSL_SAMPLER_DIM_MS, GLSL_TYPE_UINT, NONARRAY, COLOR, 2) +T(usampler2DMSArray, GLSL_SAMPLER_DIM_MS, GLSL_TYPE_UINT, ARRAY, COLOR, 3) + +T(sampler1DShadow, GLSL_SAMPLER_DIM_1D, GLSL_TYPE_FLOAT, NONARRAY, SHADOW, 1) +T(sampler2DShadow, GLSL_SAMPLER_DIM_2D, GLSL_TYPE_FLOAT, NONARRAY, SHADOW, 2) +T(samplerCubeShadow, GLSL_SAMPLER_DIM_CUBE, GLSL_TYPE_FLOAT, NONARRAY, SHADOW, 3) + +T(sampler1DArrayShadow, + GLSL_SAMPLER_DIM_1D, GLSL_TYPE_FLOAT, ARRAY, SHADOW, 2) +T(sampler2DArrayShadow, + GLSL_SAMPLER_DIM_2D, GLSL_TYPE_FLOAT, ARRAY, SHADOW, 3) +T(samplerCubeArrayShadow, + GLSL_SAMPLER_DIM_CUBE, GLSL_TYPE_FLOAT, ARRAY, SHADOW, 4) +T(sampler2DRectShadow, + GLSL_SAMPLER_DIM_RECT, GLSL_TYPE_FLOAT, NONARRAY, SHADOW, 2) + +T(samplerExternalOES, + GLSL_SAMPLER_DIM_EXTERNAL, GLSL_TYPE_FLOAT, NONARRAY, COLOR, 2) diff --git a/dist/Mesa/src/glsl/tests/set_uniform_initializer_tests.cpp b/dist/Mesa/src/glsl/tests/set_uniform_initializer_tests.cpp index 5c6d4a514..be202b3d5 100644 --- a/dist/Mesa/src/glsl/tests/set_uniform_initializer_tests.cpp +++ b/dist/Mesa/src/glsl/tests/set_uniform_initializer_tests.cpp @@ -116,7 +116,7 @@ establish_uniform_storage(struct gl_shader_program *prog, unsigned num_storage, prog->UniformStorage[index_to_set].type = type; prog->UniformStorage[index_to_set].array_elements = array_size; prog->UniformStorage[index_to_set].initialized = false; - for (int sh = 0; sh < MESA_SHADER_TYPES; sh++) { + for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) { prog->UniformStorage[index_to_set].sampler[sh].index = ~0; prog->UniformStorage[index_to_set].sampler[sh].active = false; } @@ -137,7 +137,7 @@ establish_uniform_storage(struct gl_shader_program *prog, unsigned num_storage, prog->UniformStorage[i].type = glsl_type::void_type; prog->UniformStorage[i].array_elements = 0; prog->UniformStorage[i].initialized = false; - for (int sh = 0; sh < MESA_SHADER_TYPES; sh++) { + for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) { prog->UniformStorage[i].sampler[sh].index = ~0; prog->UniformStorage[i].sampler[sh].active = false; } diff --git a/dist/Mesa/src/glsl/tests/uniform_initializer_utils.cpp b/dist/Mesa/src/glsl/tests/uniform_initializer_utils.cpp index a04f5ddc4..5e86c2432 100644 --- a/dist/Mesa/src/glsl/tests/uniform_initializer_utils.cpp +++ b/dist/Mesa/src/glsl/tests/uniform_initializer_utils.cpp @@ -92,6 +92,7 @@ generate_data_element(void *mem_ctx, const glsl_type *type, case GLSL_TYPE_BOOL: data.b[i] = bool(values[idx]); break; + case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_STRUCT: case GLSL_TYPE_ARRAY: case GLSL_TYPE_VOID: @@ -119,6 +120,7 @@ generate_data_element(void *mem_ctx, const glsl_type *type, case GLSL_TYPE_BOOL: ASSERT_EQ(data.b[i], val->value.b[i]); break; + case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_STRUCT: case GLSL_TYPE_ARRAY: case GLSL_TYPE_VOID: @@ -217,6 +219,7 @@ verify_data(gl_constant_value *storage, unsigned storage_array_size, case GLSL_TYPE_BOOL: EXPECT_EQ(int(val->value.b[i]), storage[i].i); break; + case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_STRUCT: case GLSL_TYPE_ARRAY: case GLSL_TYPE_VOID: diff --git a/dist/Mesa/src/glsl/tests/varyings_test.cpp b/dist/Mesa/src/glsl/tests/varyings_test.cpp new file mode 100644 index 000000000..662fc0e40 --- /dev/null +++ b/dist/Mesa/src/glsl/tests/varyings_test.cpp @@ -0,0 +1,357 @@ +/* + * Copyright © 2013 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. + */ +#include <gtest/gtest.h> +#include "main/compiler.h" +#include "main/mtypes.h" +#include "main/macros.h" +#include "ralloc.h" +#include "ir.h" +#include "program/hash_table.h" + +/** + * \file varyings_test.cpp + * + * Test various aspects of linking shader stage inputs and outputs. + */ + +namespace linker { +bool +populate_consumer_input_sets(void *mem_ctx, exec_list *ir, + hash_table *consumer_inputs, + hash_table *consumer_interface_inputs, + ir_variable *consumer_inputs_with_locations[VARYING_SLOT_MAX]); + +ir_variable * +get_matching_input(void *mem_ctx, + const ir_variable *output_var, + hash_table *consumer_inputs, + hash_table *consumer_interface_inputs, + ir_variable *consumer_inputs_with_locations[VARYING_SLOT_MAX]); +} + +class link_varyings : public ::testing::Test { +public: + link_varyings(); + + virtual void SetUp(); + virtual void TearDown(); + + char *interface_field_name(const glsl_type *iface, unsigned field = 0) + { + return ralloc_asprintf(mem_ctx, + "%s.%s", + iface->name, + iface->fields.structure[field].name); + } + + void *mem_ctx; + exec_list ir; + hash_table *consumer_inputs; + hash_table *consumer_interface_inputs; + + const glsl_type *simple_interface; + ir_variable *junk[VARYING_SLOT_MAX]; +}; + +link_varyings::link_varyings() +{ + static const glsl_struct_field f[] = { + { + glsl_type::vec(4), + "v", + false, + 0, + 0, + 0, + 0 + } + }; + + this->simple_interface = + glsl_type::get_interface_instance(f, + ARRAY_SIZE(f), + GLSL_INTERFACE_PACKING_STD140, + "simple_interface"); +} + +void +link_varyings::SetUp() +{ + this->mem_ctx = ralloc_context(NULL); + this->ir.make_empty(); + + this->consumer_inputs + = hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare); + + this->consumer_interface_inputs + = hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare); +} + +void +link_varyings::TearDown() +{ + ralloc_free(this->mem_ctx); + this->mem_ctx = NULL; + + hash_table_dtor(this->consumer_inputs); + this->consumer_inputs = NULL; + hash_table_dtor(this->consumer_interface_inputs); + this->consumer_interface_inputs = NULL; +} + +/** + * Hash table callback function that counts the elements in the table + * + * \sa num_elements + */ +static void +ht_count_callback(const void *, void *, void *closure) +{ + unsigned int *counter = (unsigned int *) closure; + + (*counter)++; +} + +/** + * Helper function to count the number of elements in a hash table. + */ +static unsigned +num_elements(hash_table *ht) +{ + unsigned int counter = 0; + + hash_table_call_foreach(ht, ht_count_callback, (void *) &counter); + + return counter; +} + +/** + * Helper function to determine whether a hash table is empty. + */ +static bool +is_empty(hash_table *ht) +{ + return num_elements(ht) == 0; +} + +TEST_F(link_varyings, single_simple_input) +{ + ir_variable *const v = + new(mem_ctx) ir_variable(glsl_type::vec(4), + "a", + ir_var_shader_in); + + + ir.push_tail(v); + + ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx, + &ir, + consumer_inputs, + consumer_interface_inputs, + junk)); + + EXPECT_EQ((void *) v, hash_table_find(consumer_inputs, "a")); + EXPECT_EQ(1u, num_elements(consumer_inputs)); + EXPECT_TRUE(is_empty(consumer_interface_inputs)); +} + +TEST_F(link_varyings, gl_ClipDistance) +{ + const glsl_type *const array_8_of_float = + glsl_type::get_array_instance(glsl_type::vec(1), 8); + + ir_variable *const clipdistance = + new(mem_ctx) ir_variable(array_8_of_float, + "gl_ClipDistance", + ir_var_shader_in); + + clipdistance->data.explicit_location = true; + clipdistance->data.location = VARYING_SLOT_CLIP_DIST0; + clipdistance->data.explicit_index = 0; + + ir.push_tail(clipdistance); + + ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx, + &ir, + consumer_inputs, + consumer_interface_inputs, + junk)); + + EXPECT_EQ(clipdistance, junk[VARYING_SLOT_CLIP_DIST0]); + EXPECT_TRUE(is_empty(consumer_inputs)); + EXPECT_TRUE(is_empty(consumer_interface_inputs)); +} + +TEST_F(link_varyings, single_interface_input) +{ + ir_variable *const v = + new(mem_ctx) ir_variable(simple_interface->fields.structure[0].type, + simple_interface->fields.structure[0].name, + ir_var_shader_in); + + v->init_interface_type(simple_interface); + + ir.push_tail(v); + + ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx, + &ir, + consumer_inputs, + consumer_interface_inputs, + junk)); + char *const full_name = interface_field_name(simple_interface); + + EXPECT_EQ((void *) v, hash_table_find(consumer_interface_inputs, full_name)); + EXPECT_EQ(1u, num_elements(consumer_interface_inputs)); + EXPECT_TRUE(is_empty(consumer_inputs)); +} + +TEST_F(link_varyings, one_interface_and_one_simple_input) +{ + ir_variable *const v = + new(mem_ctx) ir_variable(glsl_type::vec(4), + "a", + ir_var_shader_in); + + + ir.push_tail(v); + + ir_variable *const iface = + new(mem_ctx) ir_variable(simple_interface->fields.structure[0].type, + simple_interface->fields.structure[0].name, + ir_var_shader_in); + + iface->init_interface_type(simple_interface); + + ir.push_tail(iface); + + ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx, + &ir, + consumer_inputs, + consumer_interface_inputs, + junk)); + + char *const iface_field_name = interface_field_name(simple_interface); + + EXPECT_EQ((void *) iface, hash_table_find(consumer_interface_inputs, + iface_field_name)); + EXPECT_EQ(1u, num_elements(consumer_interface_inputs)); + + EXPECT_EQ((void *) v, hash_table_find(consumer_inputs, "a")); + EXPECT_EQ(1u, num_elements(consumer_inputs)); +} + +TEST_F(link_varyings, invalid_interface_input) +{ + ir_variable *const v = + new(mem_ctx) ir_variable(simple_interface, + "named_interface", + ir_var_shader_in); + + ASSERT_EQ(simple_interface, v->get_interface_type()); + + ir.push_tail(v); + + EXPECT_FALSE(linker::populate_consumer_input_sets(mem_ctx, + &ir, + consumer_inputs, + consumer_interface_inputs, + junk)); +} + +TEST_F(link_varyings, interface_field_doesnt_match_noninterface) +{ + char *const iface_field_name = interface_field_name(simple_interface); + + /* The input shader has a single input variable name "a.v" + */ + ir_variable *const in_v = + new(mem_ctx) ir_variable(glsl_type::vec(4), + iface_field_name, + ir_var_shader_in); + + ir.push_tail(in_v); + + ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx, + &ir, + consumer_inputs, + consumer_interface_inputs, + junk)); + + /* Create an output variable, "v", that is part of an interface block named + * "a". They should not match. + */ + ir_variable *const out_v = + new(mem_ctx) ir_variable(simple_interface->fields.structure[0].type, + simple_interface->fields.structure[0].name, + ir_var_shader_in); + + out_v->init_interface_type(simple_interface); + + ir_variable *const match = + linker::get_matching_input(mem_ctx, + out_v, + consumer_inputs, + consumer_interface_inputs, + junk); + + EXPECT_EQ(NULL, match); +} + +TEST_F(link_varyings, interface_field_doesnt_match_noninterface_vice_versa) +{ + char *const iface_field_name = interface_field_name(simple_interface); + + /* In input shader has a single variable, "v", that is part of an interface + * block named "a". + */ + ir_variable *const in_v = + new(mem_ctx) ir_variable(simple_interface->fields.structure[0].type, + simple_interface->fields.structure[0].name, + ir_var_shader_in); + + in_v->init_interface_type(simple_interface); + + ir.push_tail(in_v); + + ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx, + &ir, + consumer_inputs, + consumer_interface_inputs, + junk)); + + /* Create an output variable "a.v". They should not match. + */ + ir_variable *const out_v = + new(mem_ctx) ir_variable(glsl_type::vec(4), + iface_field_name, + ir_var_shader_out); + + ir_variable *const match = + linker::get_matching_input(mem_ctx, + out_v, + consumer_inputs, + consumer_interface_inputs, + junk); + + EXPECT_EQ(NULL, match); +} |