vk: Support not having a vertex shader
authorKristian Høgsberg <kristian.h.kristensen@intel.com>
Tue, 12 May 2015 05:17:04 +0000 (22:17 -0700)
committerKristian Høgsberg <kristian.h.kristensen@intel.com>
Tue, 12 May 2015 06:25:28 +0000 (23:25 -0700)
This lets us bypass the vertex shader and pass data straight into
the rasterizer part of the pipeline.

src/vulkan/compiler.cpp
src/vulkan/pipeline.c

index 39858426cf423f44aaa3a91639c651d134c08e1c..3f2435402ad8ae2a8daf6c701f8d45d94b9ba0da 100644 (file)
@@ -676,7 +676,8 @@ static void
 gen7_compute_urb_partition(struct anv_pipeline *pipeline)
 {
    const struct brw_device_info *devinfo = &pipeline->device->info;
-   unsigned vs_size = pipeline->vs_prog_data.base.urb_entry_size;
+   bool vs_present = pipeline->vs_simd8 != NO_KERNEL;
+   unsigned vs_size = vs_present ? pipeline->vs_prog_data.base.urb_entry_size : 1;
    unsigned vs_entry_size_bytes = vs_size * 64;
    bool gs_present = pipeline->gs_vec4 != NO_KERNEL;
    unsigned gs_size = gs_present ? pipeline->gs_prog_data.base.urb_entry_size : 1;
@@ -841,11 +842,8 @@ anv_compiler_run(struct anv_compiler *compiler, struct anv_pipeline *pipeline)
    fail_if(program == NULL || program->Shaders == NULL,
            "failed to create program\n");
 
-   /* FIXME: Only supports vs and fs combo at the moment */
-   assert(pipeline->shaders[VK_SHADER_STAGE_VERTEX]);
-   assert(pipeline->shaders[VK_SHADER_STAGE_FRAGMENT]);
-
-   anv_compile_shader(compiler, program, pipeline, VK_SHADER_STAGE_VERTEX);
+   if (pipeline->shaders[VK_SHADER_STAGE_VERTEX])
+      anv_compile_shader(compiler, program, pipeline, VK_SHADER_STAGE_VERTEX);
    anv_compile_shader(compiler, program, pipeline, VK_SHADER_STAGE_FRAGMENT);
    if (pipeline->shaders[VK_SHADER_STAGE_GEOMETRY])
       anv_compile_shader(compiler, program, pipeline, VK_SHADER_STAGE_GEOMETRY);
@@ -870,18 +868,25 @@ anv_compiler_run(struct anv_compiler *compiler, struct anv_pipeline *pipeline)
    success = really_do_wm_prog(brw, program, bfp, &wm_key, pipeline);
    fail_if(!success, "do_wm_prog failed\n");
    pipeline->prog_data[VK_SHADER_STAGE_FRAGMENT] = &pipeline->wm_prog_data.base;
+   pipeline->active_stages = VK_SHADER_STAGE_FRAGMENT_BIT;
 
 
-   struct brw_vs_prog_key vs_key;
-   struct gl_vertex_program *vp = (struct gl_vertex_program *)
-      program->_LinkedShaders[MESA_SHADER_VERTEX]->Program;
-   struct brw_vertex_program *bvp = brw_vertex_program(vp);
+   if (pipeline->shaders[VK_SHADER_STAGE_VERTEX]) {
+      struct brw_vs_prog_key vs_key;
+      struct gl_vertex_program *vp = (struct gl_vertex_program *)
+         program->_LinkedShaders[MESA_SHADER_VERTEX]->Program;
+      struct brw_vertex_program *bvp = brw_vertex_program(vp);
 
-   brw_vs_populate_key(brw, bvp, &vs_key);
+      brw_vs_populate_key(brw, bvp, &vs_key);
+
+      success = really_do_vs_prog(brw, program, bvp, &vs_key, pipeline);
+      fail_if(!success, "do_wm_prog failed\n");
+      pipeline->prog_data[VK_SHADER_STAGE_VERTEX] = &pipeline->vs_prog_data.base.base;
+      pipeline->active_stages |= VK_SHADER_STAGE_VERTEX_BIT;;
+   } else {
+      pipeline->vs_simd8 = NO_KERNEL;
+   }
 
-   success = really_do_vs_prog(brw, program, bvp, &vs_key, pipeline);
-   fail_if(!success, "do_wm_prog failed\n");
-   pipeline->prog_data[VK_SHADER_STAGE_VERTEX] = &pipeline->vs_prog_data.base.base;
 
    if (pipeline->shaders[VK_SHADER_STAGE_GEOMETRY]) {
       struct brw_gs_prog_key gs_key;
@@ -893,14 +898,10 @@ anv_compiler_run(struct anv_compiler *compiler, struct anv_pipeline *pipeline)
 
       success = really_do_gs_prog(brw, program, bgp, &gs_key, pipeline);
       fail_if(!success, "do_gs_prog failed\n");
-      pipeline->active_stages = VK_SHADER_STAGE_VERTEX_BIT |
-         VK_SHADER_STAGE_GEOMETRY_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
+      pipeline->active_stages |= VK_SHADER_STAGE_GEOMETRY_BIT;
       pipeline->prog_data[VK_SHADER_STAGE_GEOMETRY] = &pipeline->gs_prog_data.base.base;
-
    } else {
       pipeline->gs_vec4 = NO_KERNEL;
-      pipeline->active_stages =
-         VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
    }
 
 
index 33b4f64f4899af50f791408e8a24e1b93bbc01f0..445ffde94ff36d79d74eefdf29f7f456b6fe6495 100644 (file)
@@ -266,6 +266,13 @@ VkResult VKAPI vkCreateGraphicsPipeline(
 
    anv_compiler_run(device->compiler, pipeline);
 
+   /* FIXME: The compiler dead-codes FS inputs when we don't have a VS, so we
+    * hard code this to num_attributes - 2. This is because the attributes
+    * include VUE header and position, which aren't counted as varying
+    * inputs. */
+   if (pipeline->vs_simd8 == NO_KERNEL)
+      pipeline->wm_prog_data.num_varying_inputs = vi_info->attributeCount - 2;
+
    emit_vertex_input(pipeline, vi_info);
    emit_ia_state(pipeline, ia_info);
    emit_rs_state(pipeline, rs_info);
@@ -358,40 +365,50 @@ VkResult VKAPI vkCreateGraphicsPipeline(
    offset = 1;
    length = (vue_prog_data->vue_map.num_slots + 1) / 2 - offset;
 
-   anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VS,
-                  .KernelStartPointer = pipeline->vs_simd8,
-                  .SingleVertexDispatch = Multiple,
-                  .VectorMaskEnable = Dmask,
-                  .SamplerCount = 0,
-                  .BindingTableEntryCount =
+   if (pipeline->vs_simd8 == NO_KERNEL)
+      anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VS,
+                     .FunctionEnable = false,
+                     .VertexURBEntryOutputReadOffset = 1,
+                     /* Even if VS is disabled, SBE still gets the amount of
+                      * vertex data to read from this field. We use attribute
+                      * count - 1, as we don't count the VUE header here. */
+                     .VertexURBEntryOutputLength =
+                        DIV_ROUND_UP(vi_info->attributeCount - 1, 2));
+   else
+      anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VS,
+                     .KernelStartPointer = pipeline->vs_simd8,
+                     .SingleVertexDispatch = Multiple,
+                     .VectorMaskEnable = Dmask,
+                     .SamplerCount = 0,
+                     .BindingTableEntryCount =
                      vue_prog_data->base.binding_table.size_bytes / 4,
-                  .ThreadDispatchPriority = Normal,
-                  .FloatingPointMode = IEEE754,
-                  .IllegalOpcodeExceptionEnable = false,
-                  .AccessesUAV = false,
-                  .SoftwareExceptionEnable = false,
-
-                  /* FIXME: pointer needs to be assigned outside as it aliases
-                   * PerThreadScratchSpace.
-                   */
-                  .ScratchSpaceBasePointer = 0,
-                  .PerThreadScratchSpace = 0,
+                     .ThreadDispatchPriority = Normal,
+                     .FloatingPointMode = IEEE754,
+                     .IllegalOpcodeExceptionEnable = false,
+                     .AccessesUAV = false,
+                     .SoftwareExceptionEnable = false,
+
+                     /* FIXME: pointer needs to be assigned outside as it aliases
+                      * PerThreadScratchSpace.
+                      */
+                     .ScratchSpaceBasePointer = 0,
+                     .PerThreadScratchSpace = 0,
 
-                  .DispatchGRFStartRegisterForURBData =
+                     .DispatchGRFStartRegisterForURBData =
                      vue_prog_data->base.dispatch_grf_start_reg,
-                  .VertexURBEntryReadLength = vue_prog_data->urb_read_length,
-                  .VertexURBEntryReadOffset = 0,
-
-                  .MaximumNumberofThreads = device->info.max_vs_threads - 1,
-                  .StatisticsEnable = false,
-                  .SIMD8DispatchEnable = true,
-                  .VertexCacheDisable = ia_info->disableVertexReuse,
-                  .FunctionEnable = true,
-
-                  .VertexURBEntryOutputReadOffset = offset,
-                  .VertexURBEntryOutputLength = length,
-                  .UserClipDistanceClipTestEnableBitmask = 0,
-                  .UserClipDistanceCullTestEnableBitmask = 0);
+                     .VertexURBEntryReadLength = vue_prog_data->urb_read_length,
+                     .VertexURBEntryReadOffset = 0,
+
+                     .MaximumNumberofThreads = device->info.max_vs_threads - 1,
+                     .StatisticsEnable = false,
+                     .SIMD8DispatchEnable = true,
+                     .VertexCacheDisable = ia_info->disableVertexReuse,
+                     .FunctionEnable = true,
+
+                     .VertexURBEntryOutputReadOffset = offset,
+                     .VertexURBEntryOutputLength = length,
+                     .UserClipDistanceClipTestEnableBitmask = 0,
+                     .UserClipDistanceCullTestEnableBitmask = 0);
 
    const struct brw_wm_prog_data *wm_prog_data = &pipeline->wm_prog_data;
    uint32_t ksp0, ksp2, grf_start0, grf_start2;