anv: pipeline: gen7: fix assert in debug mode
[mesa.git] / src / intel / vulkan / genX_pipeline_util.h
index 654d2e0d43f6cb026df5ef15b9743193a6dc620b..679fb5768351370674b307c9ff2da97615e6718c 100644 (file)
@@ -21,6 +21,9 @@
  * IN THE SOFTWARE.
  */
 
+#include "vk_format_info.h"
+#include "genX_multisample.h"
+
 static uint32_t
 vertex_element_comp_control(enum isl_format format, unsigned comp)
 {
@@ -100,10 +103,10 @@ emit_vertex_input(struct anv_pipeline *pipeline,
    for (uint32_t i = 0; i < info->vertexAttributeDescriptionCount; i++) {
       const VkVertexInputAttributeDescription *desc =
          &info->pVertexAttributeDescriptions[i];
-      enum isl_format format = anv_get_isl_format(desc->format,
+      enum isl_format format = anv_get_isl_format(&pipeline->device->info,
+                                                  desc->format,
                                                   VK_IMAGE_ASPECT_COLOR_BIT,
-                                                  VK_IMAGE_TILING_LINEAR,
-                                                  NULL);
+                                                  VK_IMAGE_TILING_LINEAR);
 
       assert(desc->binding < 32);
 
@@ -130,12 +133,13 @@ emit_vertex_input(struct anv_pipeline *pipeline,
        * that controls instancing.  On Haswell and prior, that's part of
        * VERTEX_BUFFER_STATE which we emit later.
        */
-      anv_batch_emit(&pipeline->batch, GENX(3DSTATE_VF_INSTANCING),
-                     .InstancingEnable = pipeline->instancing_enable[desc->binding],
-                     .VertexElementIndex = slot,
-                     /* Vulkan so far doesn't have an instance divisor, so
-                      * this is always 1 (ignored if not instancing). */
-                     .InstanceDataStepRate = 1);
+      anv_batch_emit(&pipeline->batch, GENX(3DSTATE_VF_INSTANCING), vfi) {
+         vfi.InstancingEnable = pipeline->instancing_enable[desc->binding],
+         vfi.VertexElementIndex = slot,
+         /* Vulkan so far doesn't have an instance divisor, so
+          * this is always 1 (ignored if not instancing). */
+         vfi.InstanceDataStepRate = 1;
+      }
 #endif
    }
 
@@ -172,13 +176,14 @@ emit_vertex_input(struct anv_pipeline *pipeline,
    }
 
 #if GEN_GEN >= 8
-   anv_batch_emit(&pipeline->batch, GENX(3DSTATE_VF_SGVS),
-                  .VertexIDEnable = vs_prog_data->uses_vertexid,
-                  .VertexIDComponentNumber = 2,
-                  .VertexIDElementOffset = id_slot,
-                  .InstanceIDEnable = vs_prog_data->uses_instanceid,
-                  .InstanceIDComponentNumber = 3,
-                  .InstanceIDElementOffset = id_slot);
+   anv_batch_emit(&pipeline->batch, GENX(3DSTATE_VF_SGVS), sgvs) {
+      sgvs.VertexIDEnable              = vs_prog_data->uses_vertexid;
+      sgvs.VertexIDComponentNumber     = 2;
+      sgvs.VertexIDElementOffset       = id_slot;
+      sgvs.InstanceIDEnable            = vs_prog_data->uses_instanceid;
+      sgvs.InstanceIDComponentNumber   = 3;
+      sgvs.InstanceIDElementOffset     = id_slot;
+   }
 #endif
 }
 
@@ -196,28 +201,20 @@ emit_urb_setup(struct anv_pipeline *pipeline)
     *    3DSTATE_SAMPLER_STATE_POINTER_VS command.  Only one PIPE_CONTROL
     *    needs to be sent before any combination of VS associated 3DSTATE."
     */
-   anv_batch_emit(&pipeline->batch, GEN7_PIPE_CONTROL,
-                  .DepthStallEnable = true,
-                  .PostSyncOperation = WriteImmediateData,
-                  .Address = { &device->workaround_bo, 0 });
-#endif
-
-   unsigned push_start = 0;
-   for (int i = MESA_SHADER_VERTEX; i <= MESA_SHADER_FRAGMENT; i++) {
-      unsigned push_size = pipeline->urb.push_size[i];
-      anv_batch_emit(&pipeline->batch, GENX(3DSTATE_PUSH_CONSTANT_ALLOC_VS),
-         ._3DCommandSubOpcode                   = 18 + i,
-         .ConstantBufferOffset                  = (push_size > 0) ? push_start : 0,
-         .ConstantBufferSize                    = push_size);
-      push_start += pipeline->urb.push_size[i];
+   anv_batch_emit(&pipeline->batch, GEN7_PIPE_CONTROL, pc) {
+      pc.DepthStallEnable  = true;
+      pc.PostSyncOperation = WriteImmediateData;
+      pc.Address           = (struct anv_address) { &device->workaround_bo, 0 };
    }
+#endif
 
    for (int i = MESA_SHADER_VERTEX; i <= MESA_SHADER_GEOMETRY; i++) {
-      anv_batch_emit(&pipeline->batch, GENX(3DSTATE_URB_VS),
-         ._3DCommandSubOpcode                   = 48 + i,
-         .VSURBStartingAddress                  = pipeline->urb.start[i],
-         .VSURBEntryAllocationSize              = pipeline->urb.size[i] - 1,
-         .VSNumberofURBEntries                  = pipeline->urb.entries[i]);
+      anv_batch_emit(&pipeline->batch, GENX(3DSTATE_URB_VS), urb) {
+         urb._3DCommandSubOpcode       = 48 + i;
+         urb.VSURBStartingAddress      = pipeline->urb.start[i];
+         urb.VSURBEntryAllocationSize  = pipeline->urb.size[i] - 1;
+         urb.VSNumberofURBEntries      = pipeline->urb.entries[i];
+      }
    }
 }
 
@@ -295,6 +292,11 @@ emit_3dstate_sbe(struct anv_pipeline *pipeline)
       if (input_index < 0)
          continue;
 
+      if (attr == VARYING_SLOT_PNTC) {
+         sbe.PointSpriteTextureCoordinateEnable = 1 << input_index;
+         continue;
+      }
+
       const int slot = fs_input_map->varying_to_slot[attr];
 
       if (input_index >= 16)
@@ -361,6 +363,158 @@ static const uint32_t vk_to_gen_front_face[] = {
    [VK_FRONT_FACE_CLOCKWISE]                 = 0
 };
 
+static void
+emit_rs_state(struct anv_pipeline *pipeline,
+              const VkPipelineRasterizationStateCreateInfo *rs_info,
+              const VkPipelineMultisampleStateCreateInfo *ms_info,
+              const struct anv_render_pass *pass,
+              const struct anv_subpass *subpass,
+              const struct anv_graphics_pipeline_create_info *extra)
+{
+   struct GENX(3DSTATE_SF) sf = {
+      GENX(3DSTATE_SF_header),
+   };
+
+   sf.ViewportTransformEnable = !(extra && extra->use_rectlist);
+   sf.StatisticsEnable = true;
+   sf.TriangleStripListProvokingVertexSelect = 0;
+   sf.LineStripListProvokingVertexSelect = 0;
+   sf.TriangleFanProvokingVertexSelect = 1;
+   sf.PointWidthSource = Vertex;
+   sf.PointWidth = 1.0;
+
+#if GEN_GEN >= 8
+   struct GENX(3DSTATE_RASTER) raster = {
+      GENX(3DSTATE_RASTER_header),
+   };
+#else
+#  define raster sf
+#endif
+
+   /* For details on 3DSTATE_RASTER multisample state, see the BSpec table
+    * "Multisample Modes State".
+    */
+#if GEN_GEN >= 8
+   raster.DXMultisampleRasterizationEnable = true;
+   raster.ForcedSampleCount = FSC_NUMRASTSAMPLES_0;
+   raster.ForceMultisampling = false;
+#else
+   raster.MultisampleRasterizationMode =
+      (ms_info && ms_info->rasterizationSamples > 1) ?
+      MSRASTMODE_ON_PATTERN : MSRASTMODE_OFF_PIXEL;
+#endif
+
+   raster.FrontWinding = vk_to_gen_front_face[rs_info->frontFace];
+   raster.CullMode = vk_to_gen_cullmode[rs_info->cullMode];
+   raster.FrontFaceFillMode = vk_to_gen_fillmode[rs_info->polygonMode];
+   raster.BackFaceFillMode = vk_to_gen_fillmode[rs_info->polygonMode];
+   raster.ScissorRectangleEnable = !(extra && extra->use_rectlist);
+
+#if GEN_GEN >= 9
+   /* GEN9+ splits ViewportZClipTestEnable into near and far enable bits */
+   raster.ViewportZFarClipTestEnable = !pipeline->depth_clamp_enable;
+   raster.ViewportZNearClipTestEnable = !pipeline->depth_clamp_enable;
+#elif GEN_GEN >= 8
+   raster.ViewportZClipTestEnable = !pipeline->depth_clamp_enable;
+#endif
+
+   raster.GlobalDepthOffsetEnableSolid = rs_info->depthBiasEnable;
+   raster.GlobalDepthOffsetEnableWireframe = rs_info->depthBiasEnable;
+   raster.GlobalDepthOffsetEnablePoint = rs_info->depthBiasEnable;
+
+#if GEN_GEN == 7
+   /* Gen7 requires that we provide the depth format in 3DSTATE_SF so that it
+    * can get the depth offsets correct.
+    */
+   if (subpass->depth_stencil_attachment < pass->attachment_count) {
+      VkFormat vk_format =
+         pass->attachments[subpass->depth_stencil_attachment].format;
+      assert(vk_format_is_depth_or_stencil(vk_format));
+      if (vk_format_aspects(vk_format) & VK_IMAGE_ASPECT_DEPTH_BIT) {
+         enum isl_format isl_format =
+            anv_get_isl_format(&pipeline->device->info, vk_format,
+                               VK_IMAGE_ASPECT_DEPTH_BIT,
+                               VK_IMAGE_TILING_OPTIMAL);
+         sf.DepthBufferSurfaceFormat =
+            isl_format_get_depth_format(isl_format, false);
+      }
+   }
+#endif
+
+#if GEN_GEN >= 8
+   GENX(3DSTATE_SF_pack)(NULL, pipeline->gen8.sf, &sf);
+   GENX(3DSTATE_RASTER_pack)(NULL, pipeline->gen8.raster, &raster);
+#else
+#  undef raster
+   GENX(3DSTATE_SF_pack)(NULL, &pipeline->gen7.sf, &sf);
+#endif
+}
+
+static void
+emit_ms_state(struct anv_pipeline *pipeline,
+              const VkPipelineMultisampleStateCreateInfo *info)
+{
+   uint32_t samples = 1;
+   uint32_t log2_samples = 0;
+
+   /* From the Vulkan 1.0 spec:
+    *    If pSampleMask is NULL, it is treated as if the mask has all bits
+    *    enabled, i.e. no coverage is removed from fragments.
+    *
+    * 3DSTATE_SAMPLE_MASK.SampleMask is 16 bits.
+    */
+#if GEN_GEN >= 8
+   uint32_t sample_mask = 0xffff;
+#else
+   uint32_t sample_mask = 0xff;
+#endif
+
+   if (info) {
+      samples = info->rasterizationSamples;
+      log2_samples = __builtin_ffs(samples) - 1;
+   }
+
+   if (info && info->pSampleMask)
+      sample_mask &= info->pSampleMask[0];
+
+   anv_batch_emit(&pipeline->batch, GENX(3DSTATE_MULTISAMPLE), ms) {
+      ms.NumberofMultisamples       = log2_samples;
+
+#if GEN_GEN >= 8
+      /* The PRM says that this bit is valid only for DX9:
+       *
+       *    SW can choose to set this bit only for DX9 API. DX10/OGL API's
+       *    should not have any effect by setting or not setting this bit.
+       */
+      ms.PixelPositionOffsetEnable  = false;
+      ms.PixelLocation              = CENTER;
+#else
+      ms.PixelLocation              = PIXLOC_CENTER;
+
+      switch (samples) {
+      case 1:
+         SAMPLE_POS_1X(ms.Sample);
+         break;
+      case 2:
+         SAMPLE_POS_2X(ms.Sample);
+         break;
+      case 4:
+         SAMPLE_POS_4X(ms.Sample);
+         break;
+      case 8:
+         SAMPLE_POS_8X(ms.Sample);
+         break;
+      default:
+         break;
+      }
+#endif
+   }
+
+   anv_batch_emit(&pipeline->batch, GENX(3DSTATE_SAMPLE_MASK), sm) {
+      sm.SampleMask = sample_mask;
+   }
+}
+
 static const uint32_t vk_to_gen_logic_op[] = {
    [VK_LOGIC_OP_COPY]                        = LOGICOP_COPY,
    [VK_LOGIC_OP_CLEAR]                       = LOGICOP_CLEAR,
@@ -431,3 +585,266 @@ static const uint32_t vk_to_gen_stencil_op[] = {
    [VK_STENCIL_OP_INCREMENT_AND_WRAP]           = STENCILOP_INCR,
    [VK_STENCIL_OP_DECREMENT_AND_WRAP]           = STENCILOP_DECR,
 };
+
+static void
+emit_ds_state(struct anv_pipeline *pipeline,
+              const VkPipelineDepthStencilStateCreateInfo *info,
+              const struct anv_render_pass *pass,
+              const struct anv_subpass *subpass)
+{
+#if GEN_GEN == 7
+#  define depth_stencil_dw pipeline->gen7.depth_stencil_state
+#elif GEN_GEN == 8
+#  define depth_stencil_dw pipeline->gen8.wm_depth_stencil
+#else
+#  define depth_stencil_dw pipeline->gen9.wm_depth_stencil
+#endif
+
+   if (info == NULL) {
+      /* We're going to OR this together with the dynamic state.  We need
+       * to make sure it's initialized to something useful.
+       */
+      memset(depth_stencil_dw, 0, sizeof(depth_stencil_dw));
+      return;
+   }
+
+   /* VkBool32 depthBoundsTestEnable; // optional (depth_bounds_test) */
+
+#if GEN_GEN <= 7
+   struct GENX(DEPTH_STENCIL_STATE) depth_stencil = {
+#else
+   struct GENX(3DSTATE_WM_DEPTH_STENCIL) depth_stencil = {
+#endif
+      .DepthTestEnable = info->depthTestEnable,
+      .DepthBufferWriteEnable = info->depthWriteEnable,
+      .DepthTestFunction = vk_to_gen_compare_op[info->depthCompareOp],
+      .DoubleSidedStencilEnable = true,
+
+      .StencilTestEnable = info->stencilTestEnable,
+      .StencilBufferWriteEnable = info->stencilTestEnable,
+      .StencilFailOp = vk_to_gen_stencil_op[info->front.failOp],
+      .StencilPassDepthPassOp = vk_to_gen_stencil_op[info->front.passOp],
+      .StencilPassDepthFailOp = vk_to_gen_stencil_op[info->front.depthFailOp],
+      .StencilTestFunction = vk_to_gen_compare_op[info->front.compareOp],
+      .BackfaceStencilFailOp = vk_to_gen_stencil_op[info->back.failOp],
+      .BackfaceStencilPassDepthPassOp = vk_to_gen_stencil_op[info->back.passOp],
+      .BackfaceStencilPassDepthFailOp =vk_to_gen_stencil_op[info->back.depthFailOp],
+      .BackfaceStencilTestFunction = vk_to_gen_compare_op[info->back.compareOp],
+   };
+
+   VkImageAspectFlags aspects = 0;
+   if (pass->attachments == NULL) {
+      /* This comes from meta.  Assume we have verything. */
+      aspects = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+   } else if (subpass->depth_stencil_attachment != VK_ATTACHMENT_UNUSED) {
+      VkFormat depth_stencil_format =
+         pass->attachments[subpass->depth_stencil_attachment].format;
+      aspects = vk_format_aspects(depth_stencil_format);
+   }
+
+   /* The Vulkan spec requires that if either depth or stencil is not present,
+    * the pipeline is to act as if the test silently passes.
+    */
+   if (!(aspects & VK_IMAGE_ASPECT_DEPTH_BIT)) {
+      depth_stencil.DepthBufferWriteEnable = false;
+      depth_stencil.DepthTestFunction = PREFILTEROPALWAYS;
+   }
+
+   if (!(aspects & VK_IMAGE_ASPECT_STENCIL_BIT)) {
+      depth_stencil.StencilBufferWriteEnable = false;
+      depth_stencil.StencilTestFunction = PREFILTEROPALWAYS;
+      depth_stencil.BackfaceStencilTestFunction = PREFILTEROPALWAYS;
+   }
+
+   /* From the Broadwell PRM:
+    *
+    *    "If Depth_Test_Enable = 1 AND Depth_Test_func = EQUAL, the
+    *    Depth_Write_Enable must be set to 0."
+    */
+   if (info->depthTestEnable && info->depthCompareOp == VK_COMPARE_OP_EQUAL)
+      depth_stencil.DepthBufferWriteEnable = false;
+
+#if GEN_GEN <= 7
+   GENX(DEPTH_STENCIL_STATE_pack)(NULL, depth_stencil_dw, &depth_stencil);
+#else
+   GENX(3DSTATE_WM_DEPTH_STENCIL_pack)(NULL, depth_stencil_dw, &depth_stencil);
+#endif
+}
+
+static void
+emit_cb_state(struct anv_pipeline *pipeline,
+              const VkPipelineColorBlendStateCreateInfo *info,
+              const VkPipelineMultisampleStateCreateInfo *ms_info)
+{
+   struct anv_device *device = pipeline->device;
+
+   const uint32_t num_dwords = GENX(BLEND_STATE_length);
+   pipeline->blend_state =
+      anv_state_pool_alloc(&device->dynamic_state_pool, num_dwords * 4, 64);
+
+   struct GENX(BLEND_STATE) blend_state = {
+#if GEN_GEN >= 8
+      .AlphaToCoverageEnable = ms_info && ms_info->alphaToCoverageEnable,
+      .AlphaToOneEnable = ms_info && ms_info->alphaToOneEnable,
+#else
+      /* Make sure it gets zeroed */
+      .Entry = { { 0, }, },
+#endif
+   };
+
+   /* Default everything to disabled */
+   for (uint32_t i = 0; i < 8; i++) {
+      blend_state.Entry[i].WriteDisableAlpha = true;
+      blend_state.Entry[i].WriteDisableRed = true;
+      blend_state.Entry[i].WriteDisableGreen = true;
+      blend_state.Entry[i].WriteDisableBlue = true;
+   }
+
+   struct anv_pipeline_bind_map *map =
+      &pipeline->bindings[MESA_SHADER_FRAGMENT];
+
+   bool has_writeable_rt = false;
+   for (unsigned i = 0; i < map->surface_count; i++) {
+      struct anv_pipeline_binding *binding = &map->surface_to_descriptor[i];
+
+      /* All color attachments are at the beginning of the binding table */
+      if (binding->set != ANV_DESCRIPTOR_SET_COLOR_ATTACHMENTS)
+         break;
+
+      /* We can have at most 8 attachments */
+      assert(i < 8);
+
+      if (binding->index >= info->attachmentCount)
+         continue;
+
+      assert(binding->binding == 0);
+      const VkPipelineColorBlendAttachmentState *a =
+         &info->pAttachments[binding->index];
+
+      blend_state.Entry[i] = (struct GENX(BLEND_STATE_ENTRY)) {
+#if GEN_GEN < 8
+         .AlphaToCoverageEnable = ms_info && ms_info->alphaToCoverageEnable,
+         .AlphaToOneEnable = ms_info && ms_info->alphaToOneEnable,
+#endif
+         .LogicOpEnable = info->logicOpEnable,
+         .LogicOpFunction = vk_to_gen_logic_op[info->logicOp],
+         .ColorBufferBlendEnable = a->blendEnable,
+         .ColorClampRange = COLORCLAMP_RTFORMAT,
+         .PreBlendColorClampEnable = true,
+         .PostBlendColorClampEnable = true,
+         .SourceBlendFactor = vk_to_gen_blend[a->srcColorBlendFactor],
+         .DestinationBlendFactor = vk_to_gen_blend[a->dstColorBlendFactor],
+         .ColorBlendFunction = vk_to_gen_blend_op[a->colorBlendOp],
+         .SourceAlphaBlendFactor = vk_to_gen_blend[a->srcAlphaBlendFactor],
+         .DestinationAlphaBlendFactor = vk_to_gen_blend[a->dstAlphaBlendFactor],
+         .AlphaBlendFunction = vk_to_gen_blend_op[a->alphaBlendOp],
+         .WriteDisableAlpha = !(a->colorWriteMask & VK_COLOR_COMPONENT_A_BIT),
+         .WriteDisableRed = !(a->colorWriteMask & VK_COLOR_COMPONENT_R_BIT),
+         .WriteDisableGreen = !(a->colorWriteMask & VK_COLOR_COMPONENT_G_BIT),
+         .WriteDisableBlue = !(a->colorWriteMask & VK_COLOR_COMPONENT_B_BIT),
+      };
+
+      if (a->srcColorBlendFactor != a->srcAlphaBlendFactor ||
+          a->dstColorBlendFactor != a->dstAlphaBlendFactor ||
+          a->colorBlendOp != a->alphaBlendOp) {
+#if GEN_GEN >= 8
+         blend_state.IndependentAlphaBlendEnable = true;
+#else
+         blend_state.Entry[i].IndependentAlphaBlendEnable = true;
+#endif
+      }
+
+      if (a->colorWriteMask != 0)
+         has_writeable_rt = true;
+
+      /* Our hardware applies the blend factor prior to the blend function
+       * regardless of what function is used.  Technically, this means the
+       * hardware can do MORE than GL or Vulkan specify.  However, it also
+       * means that, for MIN and MAX, we have to stomp the blend factor to
+       * ONE to make it a no-op.
+       */
+      if (a->colorBlendOp == VK_BLEND_OP_MIN ||
+          a->colorBlendOp == VK_BLEND_OP_MAX) {
+         blend_state.Entry[i].SourceBlendFactor = BLENDFACTOR_ONE;
+         blend_state.Entry[i].DestinationBlendFactor = BLENDFACTOR_ONE;
+      }
+      if (a->alphaBlendOp == VK_BLEND_OP_MIN ||
+          a->alphaBlendOp == VK_BLEND_OP_MAX) {
+         blend_state.Entry[i].SourceAlphaBlendFactor = BLENDFACTOR_ONE;
+         blend_state.Entry[i].DestinationAlphaBlendFactor = BLENDFACTOR_ONE;
+      }
+   }
+
+#if GEN_GEN >= 8
+   struct GENX(BLEND_STATE_ENTRY) *bs0 = &blend_state.Entry[0];
+   anv_batch_emit(&pipeline->batch, GENX(3DSTATE_PS_BLEND), blend) {
+      blend.AlphaToCoverageEnable         = blend_state.AlphaToCoverageEnable;
+      blend.HasWriteableRT                = has_writeable_rt;
+      blend.ColorBufferBlendEnable        = bs0->ColorBufferBlendEnable;
+      blend.SourceAlphaBlendFactor        = bs0->SourceAlphaBlendFactor;
+      blend.DestinationAlphaBlendFactor   = bs0->DestinationAlphaBlendFactor;
+      blend.SourceBlendFactor             = bs0->SourceBlendFactor;
+      blend.DestinationBlendFactor        = bs0->DestinationBlendFactor;
+      blend.AlphaTestEnable               = false;
+      blend.IndependentAlphaBlendEnable   =
+         blend_state.IndependentAlphaBlendEnable;
+   }
+#else
+   (void)has_writeable_rt;
+#endif
+
+   GENX(BLEND_STATE_pack)(NULL, pipeline->blend_state.map, &blend_state);
+   if (!device->info.has_llc)
+      anv_state_clflush(pipeline->blend_state);
+
+   anv_batch_emit(&pipeline->batch, GENX(3DSTATE_BLEND_STATE_POINTERS), bsp) {
+      bsp.BlendStatePointer      = pipeline->blend_state.offset;
+#if GEN_GEN >= 8
+      bsp.BlendStatePointerValid = true;
+#endif
+   }
+}
+
+static void
+emit_3dstate_clip(struct anv_pipeline *pipeline,
+                  const VkPipelineViewportStateCreateInfo *vp_info,
+                  const VkPipelineRasterizationStateCreateInfo *rs_info,
+                  const struct anv_graphics_pipeline_create_info *extra)
+{
+   const struct brw_wm_prog_data *wm_prog_data = get_wm_prog_data(pipeline);
+   (void) wm_prog_data;
+   anv_batch_emit(&pipeline->batch, GENX(3DSTATE_CLIP), clip) {
+      clip.ClipEnable               = !(extra && extra->use_rectlist);
+      clip.EarlyCullEnable          = true;
+      clip.APIMode                  = APIMODE_D3D,
+      clip.ViewportXYClipTestEnable = true;
+
+      clip.ClipMode = CLIPMODE_NORMAL;
+
+      clip.TriangleStripListProvokingVertexSelect = 0;
+      clip.LineStripListProvokingVertexSelect     = 0;
+      clip.TriangleFanProvokingVertexSelect       = 1;
+
+      clip.MinimumPointWidth = 0.125;
+      clip.MaximumPointWidth = 255.875;
+      clip.MaximumVPIndex    = vp_info->viewportCount - 1;
+
+#if GEN_GEN == 7
+      clip.FrontWinding            = vk_to_gen_front_face[rs_info->frontFace];
+      clip.CullMode                = vk_to_gen_cullmode[rs_info->cullMode];
+      clip.ViewportZClipTestEnable = !pipeline->depth_clamp_enable;
+#else
+      clip.NonPerspectiveBarycentricEnable = wm_prog_data ?
+         (wm_prog_data->barycentric_interp_modes & 0x38) != 0 : 0;
+#endif
+   }
+}
+
+static void
+emit_3dstate_streamout(struct anv_pipeline *pipeline,
+                       const VkPipelineRasterizationStateCreateInfo *rs_info)
+{
+   anv_batch_emit(&pipeline->batch, GENX(3DSTATE_STREAMOUT), so) {
+      so.RenderingDisable = rs_info->rasterizerDiscardEnable;
+   }
+}