glsl: Remove integer matrix support from ir_dereference_array::constant_expression_value
[mesa.git] / src / compiler / glsl / standalone.cpp
index efc6da9d0045b81fe88565a820de44cf1b233b95..9a7f7d58ed6fcf4909d33a94a5a68732c133d984 100644 (file)
 #include "loop_analysis.h"
 #include "standalone_scaffolding.h"
 #include "standalone.h"
-#include "util/string_to_uint_map.h"
+#include "string_to_uint_map.h"
+#include "util/set.h"
+#include "linker.h"
+#include "glsl_parser_extras.h"
+#include "ir_builder_print_visitor.h"
+#include "builtin_functions.h"
 #include "opt_add_neg_to_sub.h"
+#include "main/mtypes.h"
+#include "program/program.h"
+
+class dead_variable_visitor : public ir_hierarchical_visitor {
+public:
+   dead_variable_visitor()
+   {
+      variables = _mesa_pointer_set_create(NULL);
+   }
+
+   virtual ~dead_variable_visitor()
+   {
+      _mesa_set_destroy(variables, NULL);
+   }
+
+   virtual ir_visitor_status visit(ir_variable *ir)
+   {
+      /* If the variable is auto or temp, add it to the set of variables that
+       * are candidates for removal.
+       */
+      if (ir->data.mode != ir_var_auto && ir->data.mode != ir_var_temporary)
+         return visit_continue;
+
+      _mesa_set_add(variables, ir);
+
+      return visit_continue;
+   }
+
+   virtual ir_visitor_status visit(ir_dereference_variable *ir)
+   {
+      struct set_entry *entry = _mesa_set_search(variables, ir->var);
+
+      /* If a variable is dereferenced at all, remove it from the set of
+       * variables that are candidates for removal.
+       */
+      if (entry != NULL)
+         _mesa_set_remove(variables, entry);
+
+      return visit_continue;
+   }
+
+   void remove_dead_variables()
+   {
+      set_foreach(variables, entry) {
+         ir_variable *ir = (ir_variable *) entry->key;
+
+         assert(ir->ir_type == ir_type_variable);
+         ir->remove();
+      }
+   }
+
+private:
+   set *variables;
+};
+
+static void
+init_gl_program(struct gl_program *prog, bool is_arb_asm, gl_shader_stage stage)
+{
+   prog->RefCount = 1;
+   prog->Format = GL_PROGRAM_FORMAT_ASCII_ARB;
+   prog->is_arb_asm = is_arb_asm;
+   prog->info.stage = stage;
+}
+
+static struct gl_program *
+new_program(UNUSED struct gl_context *ctx, gl_shader_stage stage,
+            UNUSED GLuint id, bool is_arb_asm)
+{
+   struct gl_program *prog = rzalloc(NULL, struct gl_program);
+   init_gl_program(prog, is_arb_asm, stage);
+   return prog;
+}
 
 static const struct standalone_options *options;
 
@@ -45,12 +122,15 @@ static void
 initialize_context(struct gl_context *ctx, gl_api api)
 {
    initialize_context_to_defaults(ctx, api);
+   _mesa_glsl_builtin_functions_init_or_ref();
 
    /* The standalone compiler needs to claim support for almost
     * everything in order to compile the built-in functions.
     */
    ctx->Const.GLSLVersion = options->glsl_version;
    ctx->Extensions.ARB_ES3_compatibility = true;
+   ctx->Extensions.ARB_ES3_1_compatibility = true;
+   ctx->Extensions.ARB_ES3_2_compatibility = true;
    ctx->Const.MaxComputeWorkGroupCount[0] = 65535;
    ctx->Const.MaxComputeWorkGroupCount[1] = 65535;
    ctx->Const.MaxComputeWorkGroupCount[2] = 65535;
@@ -139,6 +219,9 @@ initialize_context(struct gl_context *ctx, gl_api api)
       ctx->Const.MaxLights = 8;
       ctx->Const.MaxTextureCoordUnits = 8;
       ctx->Const.MaxTextureUnits = 2;
+      ctx->Const.MaxUniformBufferBindings = 84;
+      ctx->Const.MaxVertexStreams = 4;
+      ctx->Const.MaxTransformFeedbackBuffers = 4;
 
       ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs = 16;
       ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = 16;
@@ -164,6 +247,7 @@ initialize_context(struct gl_context *ctx, gl_api api)
    case 430:
    case 440:
    case 450:
+   case 460:
       ctx->Const.MaxClipPlanes = 8;
       ctx->Const.MaxDrawBuffers = 8;
       ctx->Const.MinProgramTexelOffset = -8;
@@ -171,6 +255,12 @@ initialize_context(struct gl_context *ctx, gl_api api)
       ctx->Const.MaxLights = 8;
       ctx->Const.MaxTextureCoordUnits = 8;
       ctx->Const.MaxTextureUnits = 2;
+      ctx->Const.MaxUniformBufferBindings = 84;
+      ctx->Const.MaxVertexStreams = 4;
+      ctx->Const.MaxTransformFeedbackBuffers = 4;
+      ctx->Const.MaxShaderStorageBufferBindings = 4;
+      ctx->Const.MaxShaderStorageBlockSize = 4096;
+      ctx->Const.MaxAtomicBufferBindings = 4;
 
       ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs = 16;
       ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = 16;
@@ -212,6 +302,9 @@ initialize_context(struct gl_context *ctx, gl_api api)
       ctx->Const.MaxLights = 0;
       ctx->Const.MaxTextureCoordUnits = 0;
       ctx->Const.MaxTextureUnits = 0;
+      ctx->Const.MaxUniformBufferBindings = 84;
+      ctx->Const.MaxVertexStreams = 4;
+      ctx->Const.MaxTransformFeedbackBuffers = 4;
 
       ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs = 16;
       ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = 16;
@@ -237,7 +330,7 @@ initialize_context(struct gl_context *ctx, gl_api api)
    ctx->Const.MaxUserAssignableUniformLocations =
       4 * MESA_SHADER_STAGES * MAX_UNIFORMS;
 
-   ctx->Driver.NewShader = _mesa_new_linked_shader;
+   ctx->Driver.NewProgram = new_program;
 }
 
 /* Returned string will have 'ctx' as its ralloc owner. */
@@ -284,13 +377,14 @@ load_text_file(void *ctx, const char *file_name)
    return text;
 }
 
-void
+static void
 compile_shader(struct gl_context *ctx, struct gl_shader *shader)
 {
    struct _mesa_glsl_parse_state *state =
       new(shader) _mesa_glsl_parse_state(ctx, shader->Stage, shader);
 
-   _mesa_glsl_compile_shader(ctx, shader, options->dump_ast, options->dump_hir);
+   _mesa_glsl_compile_shader(ctx, shader, options->dump_ast,
+                             options->dump_hir, true);
 
    /* Print out the resulting IR */
    if (!state->error && options->dump_lir) {
@@ -300,26 +394,11 @@ compile_shader(struct gl_context *ctx, struct gl_shader *shader)
    return;
 }
 
-void
-init_gl_program(struct gl_program *prog, GLenum target)
-{
-   mtx_init(&prog->Mutex, mtx_plain);
-
-   prog->RefCount = 1;
-   prog->Format = GL_PROGRAM_FORMAT_ASCII_ARB;
-
-   /* default mapping from samplers to texture units */
-   for (int i = 0; i < MAX_SAMPLERS; i++)
-      prog->SamplerUnits[i] = i;
-}
-
 extern "C" struct gl_shader_program *
 standalone_compile_shader(const struct standalone_options *_options,
-      unsigned num_files, char* const* files)
+      unsigned num_files, char* const* files, struct gl_context *ctx)
 {
    int status = EXIT_SUCCESS;
-   static struct gl_context local_ctx;
-   struct gl_context *ctx = &local_ctx;
    bool glsl_es = false;
 
    options = _options;
@@ -341,6 +420,7 @@ standalone_compile_shader(const struct standalone_options *_options,
    case 430:
    case 440:
    case 450:
+   case 460:
       glsl_es = false;
       break;
    default:
@@ -354,11 +434,21 @@ standalone_compile_shader(const struct standalone_options *_options,
       initialize_context(ctx, options->glsl_version > 130 ? API_OPENGL_CORE : API_OPENGL_COMPAT);
    }
 
+   if (options->lower_precision) {
+      for (unsigned i = MESA_SHADER_VERTEX; i <= MESA_SHADER_FRAGMENT; i++) {
+         struct gl_shader_compiler_options *options =
+            &ctx->Const.ShaderCompilerOptions[i];
+         options->LowerPrecision = true;
+      }
+   }
+
    struct gl_shader_program *whole_program;
 
    whole_program = rzalloc (NULL, struct gl_shader_program);
    assert(whole_program != NULL);
-   whole_program->InfoLog = ralloc_strdup(whole_program, "");
+   whole_program->data = rzalloc(whole_program, struct gl_shader_program_data);
+   assert(whole_program->data != NULL);
+   whole_program->data->InfoLog = ralloc_strdup(whole_program->data, "");
 
    /* Created just to avoid segmentation faults */
    whole_program->AttributeBindings = new string_to_uint_map;
@@ -421,17 +511,56 @@ standalone_compile_shader(const struct standalone_options *_options,
       }
    }
 
-   if ((status == EXIT_SUCCESS) && options->do_link)  {
+   if (status == EXIT_SUCCESS) {
       _mesa_clear_shader_program_data(ctx, whole_program);
 
-      link_shaders(ctx, whole_program);
-      status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE;
+      if (options->do_link)  {
+         link_shaders(ctx, whole_program);
+      } else {
+         const gl_shader_stage stage = whole_program->Shaders[0]->Stage;
+
+         whole_program->data->LinkStatus = LINKING_SUCCESS;
+         whole_program->_LinkedShaders[stage] =
+            link_intrastage_shaders(whole_program /* mem_ctx */,
+                                    ctx,
+                                    whole_program,
+                                    whole_program->Shaders,
+                                    1,
+                                    true);
+
+         /* Par-linking can fail, for example, if there are undefined external
+          * references.
+          */
+         if (whole_program->_LinkedShaders[stage] != NULL) {
+            assert(whole_program->data->LinkStatus);
+
+            struct gl_shader_compiler_options *const compiler_options =
+               &ctx->Const.ShaderCompilerOptions[stage];
+
+            exec_list *const ir =
+               whole_program->_LinkedShaders[stage]->ir;
+
+            bool progress;
+            do {
+               progress = do_function_inlining(ir);
+
+               progress = do_common_optimization(ir,
+                                                 false,
+                                                 false,
+                                                 compiler_options,
+                                                 true)
+                  && progress;
+            } while(progress);
+         }
+      }
+
+      status = (whole_program->data->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE;
 
-      if (strlen(whole_program->InfoLog) > 0) {
+      if (strlen(whole_program->data->InfoLog) > 0) {
          printf("\n");
          if (!options->just_log)
             printf("Info log for linking:\n");
-         printf("%s", whole_program->InfoLog);
+         printf("%s", whole_program->data->InfoLog);
          if (!options->just_log)
             printf("\n");
       }
@@ -445,14 +574,31 @@ standalone_compile_shader(const struct standalone_options *_options,
          add_neg_to_sub_visitor v;
          visit_list_elements(&v, shader->ir);
 
-         shader->Program = rzalloc(shader, gl_program);
-         init_gl_program(shader->Program, shader->Stage);
+         dead_variable_visitor dv;
+         visit_list_elements(&dv, shader->ir);
+         dv.remove_dead_variables();
+      }
+
+      if (options->dump_builder) {
+         for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+            struct gl_linked_shader *shader = whole_program->_LinkedShaders[i];
+
+            if (!shader)
+               continue;
+
+            _mesa_print_builder_for_ir(stdout, shader->ir);
+         }
       }
    }
 
    return whole_program;
 
 fail:
+   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+      if (whole_program->_LinkedShaders[i])
+         ralloc_free(whole_program->_LinkedShaders[i]->Program);
+   }
+
    ralloc_free(whole_program);
    return NULL;
 }
@@ -460,14 +606,15 @@ fail:
 extern "C" void
 standalone_compiler_cleanup(struct gl_shader_program *whole_program)
 {
-   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++)
-      ralloc_free(whole_program->_LinkedShaders[i]);
+   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+      if (whole_program->_LinkedShaders[i])
+         ralloc_free(whole_program->_LinkedShaders[i]->Program);
+   }
 
    delete whole_program->AttributeBindings;
    delete whole_program->FragDataBindings;
    delete whole_program->FragDataIndexBindings;
 
    ralloc_free(whole_program);
-   _mesa_glsl_release_types();
-   _mesa_glsl_release_builtin_functions();
+   _mesa_glsl_builtin_functions_decref();
 }