Merge remote-tracking branch 'mesa-public/master' into vulkan
[mesa.git] / src / vulkan / anv_pipeline.c
index 6e6b71c785a490853324902228d8b0cc867e50b5..3d9e0705626ebdbe626491c56c5fe1be1c91bff9 100644 (file)
@@ -121,20 +121,11 @@ static const gl_shader_stage vk_shader_stage_to_mesa_stage[] = {
    [VK_SHADER_STAGE_COMPUTE] = MESA_SHADER_COMPUTE,
 };
 
-static bool
-is_scalar_shader_stage(const struct brw_compiler *compiler, VkShaderStage stage)
+bool
+anv_is_scalar_shader_stage(const struct brw_compiler *compiler,
+                           VkShaderStage stage)
 {
-   switch (stage) {
-   case VK_SHADER_STAGE_VERTEX:
-      return compiler->scalar_vs;
-   case VK_SHADER_STAGE_GEOMETRY:
-      return false;
-   case VK_SHADER_STAGE_FRAGMENT:
-   case VK_SHADER_STAGE_COMPUTE:
-      return true;
-   default:
-      unreachable("Unsupported shader stage");
-   }
+   return compiler->scalar_stage[vk_shader_stage_to_mesa_stage[stage]];
 }
 
 /* Eventually, this will become part of anv_CreateShader.  Unfortunately,
@@ -170,6 +161,9 @@ anv_shader_compile_to_nir(struct anv_device *device,
    }
    nir_validate_shader(nir);
 
+   /* Vulkan uses the separate-shader linking model */
+   nir->info.separate_shader = true;
+
    /* Make sure the provided shader has exactly one entrypoint and that the
     * name matches the name that came in from the VkShader.
     */
@@ -183,8 +177,7 @@ anv_shader_compile_to_nir(struct anv_device *device,
    }
    assert(entrypoint != NULL);
 
-   brw_preprocess_nir(nir, &device->info,
-                      is_scalar_shader_stage(compiler, vk_stage));
+   nir = brw_preprocess_nir(nir, compiler->scalar_stage[stage]);
 
    nir_shader_gather_info(nir, entrypoint);
 
@@ -240,7 +233,8 @@ void anv_DestroyPipeline(
 
    anv_reloc_list_finish(&pipeline->batch_relocs, pipeline->device);
    anv_state_stream_finish(&pipeline->program_stream);
-   anv_state_pool_free(&device->dynamic_state_pool, pipeline->blend_state);
+   if (pipeline->blend_state.map)
+      anv_state_pool_free(&device->dynamic_state_pool, pipeline->blend_state);
    anv_device_free(pipeline->device, pipeline);
 }
 
@@ -255,7 +249,7 @@ static const uint32_t vk_to_gen_primitive_type[] = {
    [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_ADJ]       = _3DPRIM_LINESTRIP_ADJ,
    [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_ADJ]    = _3DPRIM_TRILIST_ADJ,
    [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_ADJ]   = _3DPRIM_TRISTRIP_ADJ,
-   [VK_PRIMITIVE_TOPOLOGY_PATCH]                = _3DPRIM_PATCHLIST_1
+/*   [VK_PRIMITIVE_TOPOLOGY_PATCH]                = _3DPRIM_PATCHLIST_1 */
 };
 
 static void
@@ -282,6 +276,15 @@ populate_vs_prog_key(const struct brw_device_info *devinfo,
    /* XXX: Handle sampler_prog_key */
 }
 
+static void
+populate_gs_prog_key(const struct brw_device_info *devinfo,
+                     struct brw_gs_prog_key *key)
+{
+   memset(key, 0, sizeof(*key));
+
+   populate_sampler_prog_key(devinfo, &key->tex);
+}
+
 static void
 populate_wm_prog_key(const struct brw_device_info *devinfo,
                      const VkGraphicsPipelineCreateInfo *info,
@@ -293,6 +296,8 @@ populate_wm_prog_key(const struct brw_device_info *devinfo,
 
    populate_sampler_prog_key(devinfo, &key->tex);
 
+   /* TODO: Fill out key->input_slots_valid */
+
    /* Vulkan doesn't specify a default */
    key->high_quality_derivatives = false;
 
@@ -343,18 +348,12 @@ anv_pipeline_compile(struct anv_pipeline *pipeline,
    if (nir == NULL)
       return NULL;
 
-   bool have_push_constants = false;
-   nir_foreach_variable(var, &nir->uniforms) {
-      if (!glsl_type_is_sampler(var->type)) {
-         have_push_constants = true;
-         break;
-      }
-   }
+   anv_nir_lower_push_constants(nir, anv_is_scalar_shader_stage(compiler, stage));
 
    /* Figure out the number of parameters */
    prog_data->nr_params = 0;
 
-   if (have_push_constants) {
+   if (nir->num_uniforms > 0) {
       /* If the shader uses any push constants at all, we'll just give
        * them the maximum possible number
        */
@@ -362,7 +361,7 @@ anv_pipeline_compile(struct anv_pipeline *pipeline,
    }
 
    if (pipeline->layout && pipeline->layout->stage[stage].has_dynamic_offsets)
-      prog_data->nr_params += MAX_DYNAMIC_BUFFERS;
+      prog_data->nr_params += MAX_DYNAMIC_BUFFERS * 2;
 
    if (prog_data->nr_params > 0) {
       prog_data->param = (const gl_constant_value **)
@@ -376,7 +375,7 @@ anv_pipeline_compile(struct anv_pipeline *pipeline,
        * params array, it doesn't really matter what we put here.
        */
       struct anv_push_constants *null_data = NULL;
-      if (have_push_constants) {
+      if (nir->num_uniforms > 0) {
          /* Fill out the push constants section of the param array */
          for (unsigned i = 0; i < MAX_PUSH_CONSTANTS_SIZE / sizeof(float); i++)
             prog_data->param[i] = (const gl_constant_value *)
@@ -397,11 +396,12 @@ anv_pipeline_compile(struct anv_pipeline *pipeline,
    prog_data->binding_table.size_bytes = 0;
    prog_data->binding_table.texture_start = bias;
    prog_data->binding_table.ubo_start = bias;
+   prog_data->binding_table.ssbo_start = bias;
    prog_data->binding_table.image_start = bias;
 
    /* Finish the optimization and compilation process */
-   brw_postprocess_nir(nir, &pipeline->device->info,
-                       is_scalar_shader_stage(compiler, stage));
+   nir = brw_lower_nir(nir, &pipeline->device->info, NULL,
+                       anv_is_scalar_shader_stage(compiler, stage));
 
    /* nir_lower_io will only handle the push constants; we need to set this
     * to the full number of possible uniforms.
@@ -480,7 +480,7 @@ anv_pipeline_compile_vs(struct anv_pipeline *pipeline,
    brw_compute_vue_map(&pipeline->device->info,
                        &prog_data->base.vue_map,
                        nir->info.outputs_written,
-                       false /* XXX: Do SSO? */);
+                       nir->info.separate_shader);
 
    unsigned code_size;
    const unsigned *shader_code =
@@ -509,6 +509,60 @@ anv_pipeline_compile_vs(struct anv_pipeline *pipeline,
    return VK_SUCCESS;
 }
 
+static VkResult
+anv_pipeline_compile_gs(struct anv_pipeline *pipeline,
+                        const VkGraphicsPipelineCreateInfo *info,
+                        struct anv_shader *shader)
+{
+   const struct brw_compiler *compiler =
+      pipeline->device->instance->physicalDevice.compiler;
+   struct brw_gs_prog_data *prog_data = &pipeline->gs_prog_data;
+   struct brw_gs_prog_key key;
+
+   populate_gs_prog_key(&pipeline->device->info, &key);
+
+   /* TODO: Look up shader in cache */
+
+   memset(prog_data, 0, sizeof(*prog_data));
+
+   nir_shader *nir = anv_pipeline_compile(pipeline, shader,
+                                          VK_SHADER_STAGE_GEOMETRY,
+                                          &prog_data->base.base);
+   if (nir == NULL)
+      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+   void *mem_ctx = ralloc_context(NULL);
+
+   if (shader->module->nir == NULL)
+      ralloc_steal(mem_ctx, nir);
+
+   brw_compute_vue_map(&pipeline->device->info,
+                       &prog_data->base.vue_map,
+                       nir->info.outputs_written,
+                       nir->info.separate_shader);
+
+   unsigned code_size;
+   const unsigned *shader_code =
+      brw_compile_gs(compiler, NULL, mem_ctx, &key, prog_data, nir,
+                     NULL, -1, &code_size, NULL);
+   if (shader_code == NULL) {
+      ralloc_free(mem_ctx);
+      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+   }
+
+   /* TODO: SIMD8 GS */
+   pipeline->gs_vec4 =
+      anv_pipeline_upload_kernel(pipeline, shader_code, code_size);
+   pipeline->gs_vertex_count = nir->info.gs.vertices_in;
+
+   ralloc_free(mem_ctx);
+
+   anv_pipeline_add_compiled_stage(pipeline, VK_SHADER_STAGE_GEOMETRY,
+                                   &prog_data->base.base);
+
+   return VK_SUCCESS;
+}
+
 static VkResult
 anv_pipeline_compile_fs(struct anv_pipeline *pipeline,
                         const VkGraphicsPipelineCreateInfo *info,
@@ -957,6 +1011,9 @@ anv_pipeline_init(struct anv_pipeline *pipeline, struct anv_device *device,
       case VK_SHADER_STAGE_VERTEX:
          anv_pipeline_compile_vs(pipeline, pCreateInfo, shader);
          break;
+      case VK_SHADER_STAGE_GEOMETRY:
+         anv_pipeline_compile_gs(pipeline, pCreateInfo, shader);
+         break;
       case VK_SHADER_STAGE_FRAGMENT:
          anv_pipeline_compile_fs(pipeline, pCreateInfo, shader);
          break;
@@ -1019,7 +1076,10 @@ anv_graphics_pipeline_create(
 
    switch (device->info.gen) {
    case 7:
-      return gen7_graphics_pipeline_create(_device, pCreateInfo, extra, pPipeline);
+      if (device->info.is_haswell)
+         return gen75_graphics_pipeline_create(_device, pCreateInfo, extra, pPipeline);
+      else
+         return gen7_graphics_pipeline_create(_device, pCreateInfo, extra, pPipeline);
    case 8:
       return gen8_graphics_pipeline_create(_device, pCreateInfo, extra, pPipeline);
    default:
@@ -1061,7 +1121,10 @@ static VkResult anv_compute_pipeline_create(
 
    switch (device->info.gen) {
    case 7:
-      return gen7_compute_pipeline_create(_device, pCreateInfo, pPipeline);
+      if (device->info.is_haswell)
+         return gen75_compute_pipeline_create(_device, pCreateInfo, pPipeline);
+      else
+         return gen7_compute_pipeline_create(_device, pCreateInfo, pPipeline);
    case 8:
       return gen8_compute_pipeline_create(_device, pCreateInfo, pPipeline);
    default:
@@ -1093,121 +1156,3 @@ VkResult anv_CreateComputePipelines(
 
    return VK_SUCCESS;
 }
-
-// Pipeline layout functions
-
-VkResult anv_CreatePipelineLayout(
-    VkDevice                                    _device,
-    const VkPipelineLayoutCreateInfo*           pCreateInfo,
-    VkPipelineLayout*                           pPipelineLayout)
-{
-   ANV_FROM_HANDLE(anv_device, device, _device);
-   struct anv_pipeline_layout l, *layout;
-
-   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
-
-   l.num_sets = pCreateInfo->descriptorSetCount;
-
-   unsigned dynamic_offset_count = 0;
-
-   memset(l.stage, 0, sizeof(l.stage));
-   for (uint32_t set = 0; set < pCreateInfo->descriptorSetCount; set++) {
-      ANV_FROM_HANDLE(anv_descriptor_set_layout, set_layout,
-                      pCreateInfo->pSetLayouts[set]);
-      l.set[set].layout = set_layout;
-
-      l.set[set].dynamic_offset_start = dynamic_offset_count;
-      for (uint32_t b = 0; b < set_layout->binding_count; b++) {
-         if (set_layout->binding[b].dynamic_offset_index >= 0)
-            dynamic_offset_count += set_layout->binding[b].array_size;
-      }
-
-      for (VkShaderStage s = 0; s < VK_SHADER_STAGE_NUM; s++) {
-         l.set[set].stage[s].surface_start = l.stage[s].surface_count;
-         l.set[set].stage[s].sampler_start = l.stage[s].sampler_count;
-
-         for (uint32_t b = 0; b < set_layout->binding_count; b++) {
-            unsigned array_size = set_layout->binding[b].array_size;
-
-            if (set_layout->binding[b].stage[s].surface_index >= 0) {
-               l.stage[s].surface_count += array_size;
-
-               if (set_layout->binding[b].dynamic_offset_index >= 0)
-                  l.stage[s].has_dynamic_offsets = true;
-            }
-
-            if (set_layout->binding[b].stage[s].sampler_index >= 0)
-               l.stage[s].sampler_count += array_size;
-         }
-      }
-   }
-
-   unsigned num_bindings = 0;
-   for (VkShaderStage s = 0; s < VK_SHADER_STAGE_NUM; s++)
-      num_bindings += l.stage[s].surface_count + l.stage[s].sampler_count;
-
-   size_t size = sizeof(*layout) + num_bindings * sizeof(layout->entries[0]);
-
-   layout = anv_device_alloc(device, size, 8, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
-   if (layout == NULL)
-      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
-   /* Now we can actually build our surface and sampler maps */
-   struct anv_pipeline_binding *entry = layout->entries;
-   for (VkShaderStage s = 0; s < VK_SHADER_STAGE_NUM; s++) {
-      l.stage[s].surface_to_descriptor = entry;
-      entry += l.stage[s].surface_count;
-      l.stage[s].sampler_to_descriptor = entry;
-      entry += l.stage[s].sampler_count;
-
-      int surface = 0;
-      int sampler = 0;
-      for (uint32_t set = 0; set < pCreateInfo->descriptorSetCount; set++) {
-         struct anv_descriptor_set_layout *set_layout = l.set[set].layout;
-
-         unsigned set_offset = 0;
-         for (uint32_t b = 0; b < set_layout->binding_count; b++) {
-            unsigned array_size = set_layout->binding[b].array_size;
-
-            if (set_layout->binding[b].stage[s].surface_index >= 0) {
-               assert(surface == l.set[set].stage[s].surface_start +
-                                 set_layout->binding[b].stage[s].surface_index);
-               for (unsigned i = 0; i < array_size; i++) {
-                  l.stage[s].surface_to_descriptor[surface + i].set = set;
-                  l.stage[s].surface_to_descriptor[surface + i].offset = set_offset + i;
-               }
-               surface += array_size;
-            }
-
-            if (set_layout->binding[b].stage[s].sampler_index >= 0) {
-               assert(sampler == l.set[set].stage[s].sampler_start +
-                                 set_layout->binding[b].stage[s].sampler_index);
-               for (unsigned i = 0; i < array_size; i++) {
-                  l.stage[s].sampler_to_descriptor[sampler + i].set = set;
-                  l.stage[s].sampler_to_descriptor[sampler + i].offset = set_offset + i;
-               }
-               sampler += array_size;
-            }
-
-            set_offset += array_size;
-         }
-      }
-   }
-
-   /* Finally, we're done setting it up, copy into the allocated version */
-   *layout = l;
-
-   *pPipelineLayout = anv_pipeline_layout_to_handle(layout);
-
-   return VK_SUCCESS;
-}
-
-void anv_DestroyPipelineLayout(
-    VkDevice                                    _device,
-    VkPipelineLayout                            _pipelineLayout)
-{
-   ANV_FROM_HANDLE(anv_device, device, _device);
-   ANV_FROM_HANDLE(anv_pipeline_layout, pipeline_layout, _pipelineLayout);
-
-   anv_device_free(device, pipeline_layout);
-}