vk: Add an initial implementation of the actual Khronos WSI extension
[mesa.git] / src / vulkan / anv_compiler.cpp
index c0aed33bd128d8163b146be18476f9b6320c4b08..5f189c7ce8e4f1a99c69966cffdf9e5478772060 100644 (file)
@@ -646,21 +646,6 @@ brw_cs_populate_key(struct brw_context *brw,
    key->program_string_id = bcp->id;
 }
 
-static void
-fail_on_compile_error(int status, const char *msg)
-{
-   int source, line, column;
-   char error[256];
-
-   if (status)
-      return;
-
-   if (sscanf(msg, "%d:%d(%d): error: %255[^\n]", &source, &line, &column, error) == 4)
-      fail_if(!status, "%d:%s\n", line, error);
-   else
-      fail_if(!status, "%s\n", msg);
-}
-
 struct anv_compiler {
    struct anv_device *device;
    struct intel_screen *screen;
@@ -691,8 +676,6 @@ anv_compiler_create(struct anv_device *device)
 
    compiler->device = device;
 
-   compiler->brw->optionCache.info = NULL;
-   compiler->brw->bufmgr = NULL;
    compiler->brw->gen = devinfo->gen;
    compiler->brw->is_g4x = devinfo->is_g4x;
    compiler->brw->is_baytrail = devinfo->is_baytrail;
@@ -724,19 +707,9 @@ anv_compiler_create(struct anv_device *device)
    ctx = &compiler->brw->ctx;
    _mesa_init_shader_object_functions(&ctx->Driver);
 
-   _mesa_init_constants(&ctx->Const, API_OPENGL_CORE);
-
-   brw_initialize_context_constants(compiler->brw);
-
-   intelInitExtensions(ctx);
-
-   /* Set dd::NewShader */
-   brwInitFragProgFuncs(&ctx->Driver);
-
+   /* brw_select_clip_planes() needs this for bogus reasons. */
    ctx->_Shader = &compiler->pipeline;
 
-   compiler->brw->precompile = false;
-
    return compiler;
 
  fail:
@@ -898,58 +871,30 @@ struct spirv_header{
    uint32_t gen_magic;
 };
 
-static const char *
-src_as_glsl(const char *data)
-{
-   const struct spirv_header *as_spirv = (const struct spirv_header *)data;
-
-   /* Check alignment */
-   if ((intptr_t)data & 0x3) {
-      return data;
-   }
-
-   if (as_spirv->magic == SPIR_V_MAGIC_NUMBER) {
-      /* LunarG back-door */
-      if (as_spirv->version == 0)
-         return data + 12;
-      else
-         return NULL;
-   } else {
-      return data;
-   }
-}
-
 static void
-anv_compile_shader_glsl(struct anv_compiler *compiler,
-                   struct gl_shader_program *program,
-                   struct anv_pipeline *pipeline, uint32_t stage)
-{
-   struct brw_context *brw = compiler->brw;
-   struct gl_shader *shader;
-   int name = 0;
-
-   shader = brw_new_shader(&brw->ctx, name, stage_info[stage].token);
-   fail_if(shader == NULL, "failed to create %s shader\n", stage_info[stage].name);
-
-   shader->Source = strdup(src_as_glsl(pipeline->shaders[stage]->module->data));
-   _mesa_glsl_compile_shader(&brw->ctx, shader, false, false);
-   fail_on_compile_error(shader->CompileStatus, shader->InfoLog);
-
-   program->Shaders[program->NumShaders] = shader;
-   program->NumShaders++;
-}
-
-static void
-setup_nir_io(struct gl_program *prog,
+setup_nir_io(struct gl_shader *mesa_shader,
              nir_shader *shader)
 {
+   struct gl_program *prog = mesa_shader->Program;
    foreach_list_typed(nir_variable, var, node, &shader->inputs) {
       prog->InputsRead |= BITFIELD64_BIT(var->data.location);
+      if (shader->stage == MESA_SHADER_FRAGMENT) {
+         struct gl_fragment_program *fprog = (struct gl_fragment_program *)prog;
+
+         fprog->InterpQualifier[var->data.location] =
+            (glsl_interp_qualifier)var->data.interpolation;
+         if (var->data.centroid)
+            fprog->IsCentroid |= BITFIELD64_BIT(var->data.location);
+         if (var->data.sample)
+            fprog->IsSample |= BITFIELD64_BIT(var->data.location);
+      }
    }
 
    foreach_list_typed(nir_variable, var, node, &shader->outputs) {
       prog->OutputsWritten |= BITFIELD64_BIT(var->data.location);
    }
+
+   mesa_shader->num_uniform_components = shader->num_uniforms;
 }
 
 static void
@@ -961,25 +906,38 @@ anv_compile_shader_spirv(struct anv_compiler *compiler,
    struct anv_shader *shader = pipeline->shaders[stage];
    struct gl_shader *mesa_shader;
    int name = 0;
+   uint32_t *spirv;
 
    mesa_shader = brw_new_shader(&brw->ctx, name, stage_info[stage].token);
    fail_if(mesa_shader == NULL,
            "failed to create %s shader\n", stage_info[stage].name);
 
+#define CREATE_PROGRAM(stage) \
+   _mesa_init_##stage##_program(&brw->ctx, &ralloc(mesa_shader, struct brw_##stage##_program)->program, 0, 0)
+
+   bool is_scalar;
+   struct gl_program *prog;
    switch (stage) {
    case VK_SHADER_STAGE_VERTEX:
-      mesa_shader->Program = &rzalloc(mesa_shader, struct brw_vertex_program)->program.Base;
+      prog = CREATE_PROGRAM(vertex);
+      is_scalar = compiler->screen->compiler->scalar_vs;
       break;
    case VK_SHADER_STAGE_GEOMETRY:
-      mesa_shader->Program = &rzalloc(mesa_shader, struct brw_geometry_program)->program.Base;
+      prog = CREATE_PROGRAM(geometry);
+      is_scalar = false;
       break;
    case VK_SHADER_STAGE_FRAGMENT:
-      mesa_shader->Program = &rzalloc(mesa_shader, struct brw_fragment_program)->program.Base;
+      prog = CREATE_PROGRAM(fragment);
+      is_scalar = true;
       break;
    case VK_SHADER_STAGE_COMPUTE:
-      mesa_shader->Program = &rzalloc(mesa_shader, struct brw_compute_program)->program.Base;
+      prog = CREATE_PROGRAM(compute);
+      is_scalar = true;
       break;
+   default:
+      unreachable("Unsupported shader stage");
    }
+   _mesa_reference_program(&brw->ctx, &mesa_shader->Program, prog);
 
    mesa_shader->Program->Parameters =
       rzalloc(mesa_shader, struct gl_program_parameter_list);
@@ -987,26 +945,29 @@ anv_compile_shader_spirv(struct anv_compiler *compiler,
    mesa_shader->Type = stage_info[stage].token;
    mesa_shader->Stage = stage_info[stage].stage;
 
-   assert(shader->module->size % 4 == 0);
-
    struct gl_shader_compiler_options *glsl_options =
       &compiler->screen->compiler->glsl_compiler_options[stage_info[stage].stage];
 
+   spirv = (uint32_t *) shader->module->data;
+   assert(spirv[0] == SPIR_V_MAGIC_NUMBER);
+   assert(shader->module->size % 4 == 0);
+
    mesa_shader->Program->nir =
-      spirv_to_nir((uint32_t *)shader->module->data, shader->module->size / 4,
+      spirv_to_nir(spirv, shader->module->size / 4,
                    stage_info[stage].stage, glsl_options->NirOptions);
    nir_validate_shader(mesa_shader->Program->nir);
 
    brw_process_nir(mesa_shader->Program->nir,
                    compiler->screen->devinfo,
-                   NULL, mesa_shader->Stage, false);
+                   NULL, mesa_shader->Stage, is_scalar);
 
-   setup_nir_io(mesa_shader->Program, mesa_shader->Program->nir);
+   setup_nir_io(mesa_shader, mesa_shader->Program->nir);
 
    fail_if(mesa_shader->Program->nir == NULL,
            "failed to translate SPIR-V to NIR\n");
 
-   program->Shaders[program->NumShaders] = mesa_shader;
+   _mesa_reference_shader(&brw->ctx, &program->Shaders[program->NumShaders],
+                          mesa_shader);
    program->NumShaders++;
 }
 
@@ -1056,41 +1017,14 @@ anv_compiler_run(struct anv_compiler *compiler, struct anv_pipeline *pipeline)
    fail_if(program == NULL || program->Shaders == NULL,
            "failed to create program\n");
 
-   bool all_spirv = true;
    for (unsigned i = 0; i < VK_SHADER_STAGE_NUM; i++) {
-      if (pipeline->shaders[i] == NULL)
-         continue;
-
-      /* You need at least this much for "void main() { }" anyway */
-      assert(pipeline->shaders[i]->module->size >= 12);
-
-      if (src_as_glsl(pipeline->shaders[i]->module->data)) {
-         all_spirv = false;
-         break;
-      }
-
-      assert(pipeline->shaders[i]->module->size % 4 == 0);
+      if (pipeline->shaders[i])
+         anv_compile_shader_spirv(compiler, program, pipeline, i);
    }
 
-   if (all_spirv) {
-      for (unsigned i = 0; i < VK_SHADER_STAGE_NUM; i++) {
-         if (pipeline->shaders[i])
-            anv_compile_shader_spirv(compiler, program, pipeline, i);
-      }
-
-      for (unsigned i = 0; i < program->NumShaders; i++) {
-         struct gl_shader *shader = program->Shaders[i];
-         program->_LinkedShaders[shader->Stage] = shader;
-      }
-   } else {
-      for (unsigned i = 0; i < VK_SHADER_STAGE_NUM; i++) {
-         if (pipeline->shaders[i])
-            anv_compile_shader_glsl(compiler, program, pipeline, i);
-      }
-
-      _mesa_glsl_link_shader(&brw->ctx, program);
-      fail_on_compile_error(program->LinkStatus,
-                            program->InfoLog);
+   for (unsigned i = 0; i < program->NumShaders; i++) {
+      struct gl_shader *shader = program->Shaders[i];
+      program->_LinkedShaders[shader->Stage] = shader;
    }
 
    bool success;
@@ -1166,11 +1100,7 @@ anv_compiler_run(struct anv_compiler *compiler, struct anv_pipeline *pipeline)
                          &pipeline->cs_prog_data.base);
    }
 
-   /* XXX: Deleting the shader is broken with our current SPIR-V hacks.  We
-    * need to fix this ASAP.
-    */
-   if (!all_spirv)
-      brw->ctx.Driver.DeleteShaderProgram(&brw->ctx, program);
+   brw->ctx.Driver.DeleteShaderProgram(&brw->ctx, program);
 
    struct anv_device *device = compiler->device;
    while (device->scratch_block_pool.bo.size < pipeline->total_scratch)