17ec681f3Smrg/*
27ec681f3Smrg * Copyright © 2015 Intel Corporation
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
97ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
217ec681f3Smrg * IN THE SOFTWARE.
227ec681f3Smrg */
237ec681f3Smrg
247ec681f3Smrg#include <assert.h>
257ec681f3Smrg#include <stdbool.h>
267ec681f3Smrg#include <string.h>
277ec681f3Smrg#include <unistd.h>
287ec681f3Smrg#include <fcntl.h>
297ec681f3Smrg
307ec681f3Smrg#include "anv_private.h"
317ec681f3Smrg#include "vk_format.h"
327ec681f3Smrg
337ec681f3Smrg#include "genxml/gen_macros.h"
347ec681f3Smrg#include "genxml/genX_pack.h"
357ec681f3Smrg
367ec681f3Smrg#if GFX_VERx10 == 70
377ec681f3Smrgstatic int64_t
387ec681f3Smrgclamp_int64(int64_t x, int64_t min, int64_t max)
397ec681f3Smrg{
407ec681f3Smrg   if (x < min)
417ec681f3Smrg      return min;
427ec681f3Smrg   else if (x < max)
437ec681f3Smrg      return x;
447ec681f3Smrg   else
457ec681f3Smrg      return max;
467ec681f3Smrg}
477ec681f3Smrg
487ec681f3Smrgvoid
497ec681f3Smrggfx7_cmd_buffer_emit_scissor(struct anv_cmd_buffer *cmd_buffer)
507ec681f3Smrg{
517ec681f3Smrg   struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
527ec681f3Smrg   uint32_t count = cmd_buffer->state.gfx.dynamic.scissor.count;
537ec681f3Smrg   const VkRect2D *scissors = cmd_buffer->state.gfx.dynamic.scissor.scissors;
547ec681f3Smrg
557ec681f3Smrg   /* Wa_1409725701:
567ec681f3Smrg    *    "The viewport-specific state used by the SF unit (SCISSOR_RECT) is
577ec681f3Smrg    *    stored as an array of up to 16 elements. The location of first
587ec681f3Smrg    *    element of the array, as specified by Pointer to SCISSOR_RECT, should
597ec681f3Smrg    *    be aligned to a 64-byte boundary.
607ec681f3Smrg    */
617ec681f3Smrg   uint32_t alignment = 64;
627ec681f3Smrg   struct anv_state scissor_state =
637ec681f3Smrg      anv_cmd_buffer_alloc_dynamic_state(cmd_buffer, count * 8, alignment);
647ec681f3Smrg
657ec681f3Smrg   for (uint32_t i = 0; i < count; i++) {
667ec681f3Smrg      const VkRect2D *s = &scissors[i];
677ec681f3Smrg
687ec681f3Smrg      /* Since xmax and ymax are inclusive, we have to have xmax < xmin or
697ec681f3Smrg       * ymax < ymin for empty clips.  In case clip x, y, width height are all
707ec681f3Smrg       * 0, the clamps below produce 0 for xmin, ymin, xmax, ymax, which isn't
717ec681f3Smrg       * what we want. Just special case empty clips and produce a canonical
727ec681f3Smrg       * empty clip. */
737ec681f3Smrg      static const struct GFX7_SCISSOR_RECT empty_scissor = {
747ec681f3Smrg         .ScissorRectangleYMin = 1,
757ec681f3Smrg         .ScissorRectangleXMin = 1,
767ec681f3Smrg         .ScissorRectangleYMax = 0,
777ec681f3Smrg         .ScissorRectangleXMax = 0
787ec681f3Smrg      };
797ec681f3Smrg
807ec681f3Smrg      const int max = 0xffff;
817ec681f3Smrg
827ec681f3Smrg      uint32_t y_min = s->offset.y;
837ec681f3Smrg      uint32_t x_min = s->offset.x;
847ec681f3Smrg      uint32_t y_max = s->offset.y + s->extent.height - 1;
857ec681f3Smrg      uint32_t x_max = s->offset.x + s->extent.width - 1;
867ec681f3Smrg
877ec681f3Smrg      /* Do this math using int64_t so overflow gets clamped correctly. */
887ec681f3Smrg      if (cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) {
897ec681f3Smrg         y_min = clamp_int64((uint64_t) y_min,
907ec681f3Smrg                             cmd_buffer->state.render_area.offset.y, max);
917ec681f3Smrg         x_min = clamp_int64((uint64_t) x_min,
927ec681f3Smrg                             cmd_buffer->state.render_area.offset.x, max);
937ec681f3Smrg         y_max = clamp_int64((uint64_t) y_max, 0,
947ec681f3Smrg                             cmd_buffer->state.render_area.offset.y +
957ec681f3Smrg                             cmd_buffer->state.render_area.extent.height - 1);
967ec681f3Smrg         x_max = clamp_int64((uint64_t) x_max, 0,
977ec681f3Smrg                             cmd_buffer->state.render_area.offset.x +
987ec681f3Smrg                             cmd_buffer->state.render_area.extent.width - 1);
997ec681f3Smrg      } else if (fb) {
1007ec681f3Smrg         y_min = clamp_int64((uint64_t) y_min, 0, max);
1017ec681f3Smrg         x_min = clamp_int64((uint64_t) x_min, 0, max);
1027ec681f3Smrg         y_max = clamp_int64((uint64_t) y_max, 0, fb->height - 1);
1037ec681f3Smrg         x_max = clamp_int64((uint64_t) x_max, 0, fb->width - 1);
1047ec681f3Smrg      }
1057ec681f3Smrg
1067ec681f3Smrg      struct GFX7_SCISSOR_RECT scissor = {
1077ec681f3Smrg         .ScissorRectangleYMin = y_min,
1087ec681f3Smrg         .ScissorRectangleXMin = x_min,
1097ec681f3Smrg         .ScissorRectangleYMax = y_max,
1107ec681f3Smrg         .ScissorRectangleXMax = x_max
1117ec681f3Smrg      };
1127ec681f3Smrg
1137ec681f3Smrg      if (s->extent.width <= 0 || s->extent.height <= 0) {
1147ec681f3Smrg         GFX7_SCISSOR_RECT_pack(NULL, scissor_state.map + i * 8,
1157ec681f3Smrg                                &empty_scissor);
1167ec681f3Smrg      } else {
1177ec681f3Smrg         GFX7_SCISSOR_RECT_pack(NULL, scissor_state.map + i * 8, &scissor);
1187ec681f3Smrg      }
1197ec681f3Smrg   }
1207ec681f3Smrg
1217ec681f3Smrg   anv_batch_emit(&cmd_buffer->batch,
1227ec681f3Smrg                  GFX7_3DSTATE_SCISSOR_STATE_POINTERS, ssp) {
1237ec681f3Smrg      ssp.ScissorRectPointer = scissor_state.offset;
1247ec681f3Smrg   }
1257ec681f3Smrg}
1267ec681f3Smrg#endif
1277ec681f3Smrg
1287ec681f3Smrgstatic uint32_t vk_to_intel_index_type(VkIndexType type)
1297ec681f3Smrg{
1307ec681f3Smrg   switch (type) {
1317ec681f3Smrg   case VK_INDEX_TYPE_UINT8_EXT:
1327ec681f3Smrg      return INDEX_BYTE;
1337ec681f3Smrg   case VK_INDEX_TYPE_UINT16:
1347ec681f3Smrg      return INDEX_WORD;
1357ec681f3Smrg   case VK_INDEX_TYPE_UINT32:
1367ec681f3Smrg      return INDEX_DWORD;
1377ec681f3Smrg   default:
1387ec681f3Smrg      unreachable("invalid index type");
1397ec681f3Smrg   }
1407ec681f3Smrg}
1417ec681f3Smrg
1427ec681f3Smrgstatic uint32_t restart_index_for_type(VkIndexType type)
1437ec681f3Smrg{
1447ec681f3Smrg   switch (type) {
1457ec681f3Smrg   case VK_INDEX_TYPE_UINT8_EXT:
1467ec681f3Smrg      return UINT8_MAX;
1477ec681f3Smrg   case VK_INDEX_TYPE_UINT16:
1487ec681f3Smrg      return UINT16_MAX;
1497ec681f3Smrg   case VK_INDEX_TYPE_UINT32:
1507ec681f3Smrg      return UINT32_MAX;
1517ec681f3Smrg   default:
1527ec681f3Smrg      unreachable("invalid index type");
1537ec681f3Smrg   }
1547ec681f3Smrg}
1557ec681f3Smrg
1567ec681f3Smrgvoid genX(CmdBindIndexBuffer)(
1577ec681f3Smrg    VkCommandBuffer                             commandBuffer,
1587ec681f3Smrg    VkBuffer                                    _buffer,
1597ec681f3Smrg    VkDeviceSize                                offset,
1607ec681f3Smrg    VkIndexType                                 indexType)
1617ec681f3Smrg{
1627ec681f3Smrg   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
1637ec681f3Smrg   ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
1647ec681f3Smrg
1657ec681f3Smrg   cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_INDEX_BUFFER;
1667ec681f3Smrg   if (GFX_VERx10 == 75)
1677ec681f3Smrg      cmd_buffer->state.restart_index = restart_index_for_type(indexType);
1687ec681f3Smrg   cmd_buffer->state.gfx.gfx7.index_buffer = buffer;
1697ec681f3Smrg   cmd_buffer->state.gfx.gfx7.index_type = vk_to_intel_index_type(indexType);
1707ec681f3Smrg   cmd_buffer->state.gfx.gfx7.index_offset = offset;
1717ec681f3Smrg}
1727ec681f3Smrg
1737ec681f3Smrgstatic uint32_t
1747ec681f3Smrgget_depth_format(struct anv_cmd_buffer *cmd_buffer)
1757ec681f3Smrg{
1767ec681f3Smrg   const struct anv_render_pass *pass = cmd_buffer->state.pass;
1777ec681f3Smrg   const struct anv_subpass *subpass = cmd_buffer->state.subpass;
1787ec681f3Smrg
1797ec681f3Smrg   if (!subpass->depth_stencil_attachment)
1807ec681f3Smrg      return D16_UNORM;
1817ec681f3Smrg
1827ec681f3Smrg   struct anv_render_pass_attachment *att =
1837ec681f3Smrg      &pass->attachments[subpass->depth_stencil_attachment->attachment];
1847ec681f3Smrg
1857ec681f3Smrg   switch (att->format) {
1867ec681f3Smrg   case VK_FORMAT_D16_UNORM:
1877ec681f3Smrg   case VK_FORMAT_D16_UNORM_S8_UINT:
1887ec681f3Smrg      return D16_UNORM;
1897ec681f3Smrg
1907ec681f3Smrg   case VK_FORMAT_X8_D24_UNORM_PACK32:
1917ec681f3Smrg   case VK_FORMAT_D24_UNORM_S8_UINT:
1927ec681f3Smrg      return D24_UNORM_X8_UINT;
1937ec681f3Smrg
1947ec681f3Smrg   case VK_FORMAT_D32_SFLOAT:
1957ec681f3Smrg   case VK_FORMAT_D32_SFLOAT_S8_UINT:
1967ec681f3Smrg      return D32_FLOAT;
1977ec681f3Smrg
1987ec681f3Smrg   default:
1997ec681f3Smrg      return D16_UNORM;
2007ec681f3Smrg   }
2017ec681f3Smrg}
2027ec681f3Smrg
2037ec681f3Smrgvoid
2047ec681f3SmrggenX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
2057ec681f3Smrg{
2067ec681f3Smrg   struct anv_graphics_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;
2077ec681f3Smrg   struct anv_dynamic_state *d = &cmd_buffer->state.gfx.dynamic;
2087ec681f3Smrg
2097ec681f3Smrg   if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) {
2107ec681f3Smrg      uint32_t topology;
2117ec681f3Smrg      if (anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL))
2127ec681f3Smrg         topology = pipeline->topology;
2137ec681f3Smrg      else
2147ec681f3Smrg         topology = genX(vk_to_intel_primitive_type)[d->primitive_topology];
2157ec681f3Smrg
2167ec681f3Smrg      cmd_buffer->state.gfx.primitive_topology = topology;
2177ec681f3Smrg   }
2187ec681f3Smrg
2197ec681f3Smrg   if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE |
2207ec681f3Smrg                                      ANV_CMD_DIRTY_RENDER_TARGETS |
2217ec681f3Smrg                                      ANV_CMD_DIRTY_DYNAMIC_LINE_WIDTH |
2227ec681f3Smrg                                      ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS |
2237ec681f3Smrg                                      ANV_CMD_DIRTY_DYNAMIC_CULL_MODE |
2247ec681f3Smrg                                      ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE |
2257ec681f3Smrg                                      ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE |
2267ec681f3Smrg                                      ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY)) {
2277ec681f3Smrg      /* Take dynamic primitive topology in to account with
2287ec681f3Smrg       *    3DSTATE_SF::MultisampleRasterizationMode
2297ec681f3Smrg       */
2307ec681f3Smrg      uint32_t ms_rast_mode = 0;
2317ec681f3Smrg
2327ec681f3Smrg      if (cmd_buffer->state.gfx.pipeline->dynamic_states &
2337ec681f3Smrg          ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) {
2347ec681f3Smrg         VkPrimitiveTopology primitive_topology =
2357ec681f3Smrg            cmd_buffer->state.gfx.dynamic.primitive_topology;
2367ec681f3Smrg
2377ec681f3Smrg         VkPolygonMode dynamic_raster_mode =
2387ec681f3Smrg            genX(raster_polygon_mode)(cmd_buffer->state.gfx.pipeline,
2397ec681f3Smrg                                      primitive_topology);
2407ec681f3Smrg
2417ec681f3Smrg         ms_rast_mode =
2427ec681f3Smrg            genX(ms_rasterization_mode)(pipeline, dynamic_raster_mode);
2437ec681f3Smrg      }
2447ec681f3Smrg
2457ec681f3Smrg      uint32_t sf_dw[GENX(3DSTATE_SF_length)];
2467ec681f3Smrg      struct GENX(3DSTATE_SF) sf = {
2477ec681f3Smrg         GENX(3DSTATE_SF_header),
2487ec681f3Smrg         .DepthBufferSurfaceFormat = get_depth_format(cmd_buffer),
2497ec681f3Smrg         .LineWidth = d->line_width,
2507ec681f3Smrg         .GlobalDepthOffsetConstant = d->depth_bias.bias,
2517ec681f3Smrg         .GlobalDepthOffsetScale = d->depth_bias.slope,
2527ec681f3Smrg         .GlobalDepthOffsetClamp = d->depth_bias.clamp,
2537ec681f3Smrg         .FrontWinding            = genX(vk_to_intel_front_face)[d->front_face],
2547ec681f3Smrg         .CullMode                = genX(vk_to_intel_cullmode)[d->cull_mode],
2557ec681f3Smrg         .GlobalDepthOffsetEnableSolid = d->depth_bias_enable,
2567ec681f3Smrg         .GlobalDepthOffsetEnableWireframe = d->depth_bias_enable,
2577ec681f3Smrg         .GlobalDepthOffsetEnablePoint = d->depth_bias_enable,
2587ec681f3Smrg         .MultisampleRasterizationMode = ms_rast_mode,
2597ec681f3Smrg      };
2607ec681f3Smrg      GENX(3DSTATE_SF_pack)(NULL, sf_dw, &sf);
2617ec681f3Smrg
2627ec681f3Smrg      anv_batch_emit_merge(&cmd_buffer->batch, sf_dw, pipeline->gfx7.sf);
2637ec681f3Smrg   }
2647ec681f3Smrg
2657ec681f3Smrg   if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_DYNAMIC_BLEND_CONSTANTS |
2667ec681f3Smrg                                      ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE)) {
2677ec681f3Smrg      struct anv_state cc_state =
2687ec681f3Smrg         anv_cmd_buffer_alloc_dynamic_state(cmd_buffer,
2697ec681f3Smrg                                            GENX(COLOR_CALC_STATE_length) * 4,
2707ec681f3Smrg                                            64);
2717ec681f3Smrg      struct GENX(COLOR_CALC_STATE) cc = {
2727ec681f3Smrg         .BlendConstantColorRed = d->blend_constants[0],
2737ec681f3Smrg         .BlendConstantColorGreen = d->blend_constants[1],
2747ec681f3Smrg         .BlendConstantColorBlue = d->blend_constants[2],
2757ec681f3Smrg         .BlendConstantColorAlpha = d->blend_constants[3],
2767ec681f3Smrg         .StencilReferenceValue = d->stencil_reference.front & 0xff,
2777ec681f3Smrg         .BackfaceStencilReferenceValue = d->stencil_reference.back & 0xff,
2787ec681f3Smrg      };
2797ec681f3Smrg      GENX(COLOR_CALC_STATE_pack)(NULL, cc_state.map, &cc);
2807ec681f3Smrg
2817ec681f3Smrg      anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_CC_STATE_POINTERS), ccp) {
2827ec681f3Smrg         ccp.ColorCalcStatePointer = cc_state.offset;
2837ec681f3Smrg      }
2847ec681f3Smrg   }
2857ec681f3Smrg
2867ec681f3Smrg   if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE) {
2877ec681f3Smrg      anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_LINE_STIPPLE), ls) {
2887ec681f3Smrg         ls.LineStipplePattern = d->line_stipple.pattern;
2897ec681f3Smrg         ls.LineStippleInverseRepeatCount =
2907ec681f3Smrg            1.0f / MAX2(1, d->line_stipple.factor);
2917ec681f3Smrg         ls.LineStippleRepeatCount = d->line_stipple.factor;
2927ec681f3Smrg      }
2937ec681f3Smrg   }
2947ec681f3Smrg
2957ec681f3Smrg   if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE |
2967ec681f3Smrg                                      ANV_CMD_DIRTY_RENDER_TARGETS |
2977ec681f3Smrg                                      ANV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK |
2987ec681f3Smrg                                      ANV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK |
2997ec681f3Smrg                                      ANV_CMD_DIRTY_DYNAMIC_DEPTH_TEST_ENABLE |
3007ec681f3Smrg                                      ANV_CMD_DIRTY_DYNAMIC_DEPTH_WRITE_ENABLE |
3017ec681f3Smrg                                      ANV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP |
3027ec681f3Smrg                                      ANV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE |
3037ec681f3Smrg                                      ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP)) {
3047ec681f3Smrg      uint32_t depth_stencil_dw[GENX(DEPTH_STENCIL_STATE_length)];
3057ec681f3Smrg
3067ec681f3Smrg      struct GENX(DEPTH_STENCIL_STATE) depth_stencil = {
3077ec681f3Smrg         .StencilTestMask = d->stencil_compare_mask.front & 0xff,
3087ec681f3Smrg         .StencilWriteMask = d->stencil_write_mask.front & 0xff,
3097ec681f3Smrg
3107ec681f3Smrg         .BackfaceStencilTestMask = d->stencil_compare_mask.back & 0xff,
3117ec681f3Smrg         .BackfaceStencilWriteMask = d->stencil_write_mask.back & 0xff,
3127ec681f3Smrg
3137ec681f3Smrg         .StencilBufferWriteEnable =
3147ec681f3Smrg            (d->stencil_write_mask.front || d->stencil_write_mask.back) &&
3157ec681f3Smrg            d->stencil_test_enable,
3167ec681f3Smrg
3177ec681f3Smrg         .DepthTestEnable = d->depth_test_enable,
3187ec681f3Smrg         .DepthBufferWriteEnable = d->depth_test_enable && d->depth_write_enable,
3197ec681f3Smrg         .DepthTestFunction = genX(vk_to_intel_compare_op)[d->depth_compare_op],
3207ec681f3Smrg         .StencilTestEnable = d->stencil_test_enable,
3217ec681f3Smrg         .StencilFailOp = genX(vk_to_intel_stencil_op)[d->stencil_op.front.fail_op],
3227ec681f3Smrg         .StencilPassDepthPassOp = genX(vk_to_intel_stencil_op)[d->stencil_op.front.pass_op],
3237ec681f3Smrg         .StencilPassDepthFailOp = genX(vk_to_intel_stencil_op)[d->stencil_op.front.depth_fail_op],
3247ec681f3Smrg         .StencilTestFunction = genX(vk_to_intel_compare_op)[d->stencil_op.front.compare_op],
3257ec681f3Smrg         .BackfaceStencilFailOp = genX(vk_to_intel_stencil_op)[d->stencil_op.back.fail_op],
3267ec681f3Smrg         .BackfaceStencilPassDepthPassOp = genX(vk_to_intel_stencil_op)[d->stencil_op.back.pass_op],
3277ec681f3Smrg         .BackfaceStencilPassDepthFailOp = genX(vk_to_intel_stencil_op)[d->stencil_op.back.depth_fail_op],
3287ec681f3Smrg         .BackfaceStencilTestFunction = genX(vk_to_intel_compare_op)[d->stencil_op.back.compare_op],
3297ec681f3Smrg      };
3307ec681f3Smrg      GENX(DEPTH_STENCIL_STATE_pack)(NULL, depth_stencil_dw, &depth_stencil);
3317ec681f3Smrg
3327ec681f3Smrg      struct anv_state ds_state =
3337ec681f3Smrg         anv_cmd_buffer_merge_dynamic(cmd_buffer, depth_stencil_dw,
3347ec681f3Smrg                                      pipeline->gfx7.depth_stencil_state,
3357ec681f3Smrg                                      GENX(DEPTH_STENCIL_STATE_length), 64);
3367ec681f3Smrg
3377ec681f3Smrg      anv_batch_emit(&cmd_buffer->batch,
3387ec681f3Smrg                     GENX(3DSTATE_DEPTH_STENCIL_STATE_POINTERS), dsp) {
3397ec681f3Smrg         dsp.PointertoDEPTH_STENCIL_STATE = ds_state.offset;
3407ec681f3Smrg      }
3417ec681f3Smrg   }
3427ec681f3Smrg
3437ec681f3Smrg   if (cmd_buffer->state.gfx.gfx7.index_buffer &&
3447ec681f3Smrg       cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE |
3457ec681f3Smrg                                      ANV_CMD_DIRTY_INDEX_BUFFER |
3467ec681f3Smrg                                      ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_RESTART_ENABLE)) {
3477ec681f3Smrg      struct anv_buffer *buffer = cmd_buffer->state.gfx.gfx7.index_buffer;
3487ec681f3Smrg      uint32_t offset = cmd_buffer->state.gfx.gfx7.index_offset;
3497ec681f3Smrg
3507ec681f3Smrg#if GFX_VERx10 == 75
3517ec681f3Smrg      anv_batch_emit(&cmd_buffer->batch, GFX75_3DSTATE_VF, vf) {
3527ec681f3Smrg         vf.IndexedDrawCutIndexEnable  = d->primitive_restart_enable;
3537ec681f3Smrg         vf.CutIndex                   = cmd_buffer->state.restart_index;
3547ec681f3Smrg      }
3557ec681f3Smrg#endif
3567ec681f3Smrg
3577ec681f3Smrg      anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_INDEX_BUFFER), ib) {
3587ec681f3Smrg#if GFX_VERx10 != 75
3597ec681f3Smrg         ib.CutIndexEnable        = d->primitive_restart_enable;
3607ec681f3Smrg#endif
3617ec681f3Smrg         ib.IndexFormat           = cmd_buffer->state.gfx.gfx7.index_type;
3627ec681f3Smrg         ib.MOCS                  = anv_mocs(cmd_buffer->device,
3637ec681f3Smrg                                             buffer->address.bo,
3647ec681f3Smrg                                             ISL_SURF_USAGE_INDEX_BUFFER_BIT);
3657ec681f3Smrg
3667ec681f3Smrg         ib.BufferStartingAddress = anv_address_add(buffer->address, offset);
3677ec681f3Smrg         ib.BufferEndingAddress   = anv_address_add(buffer->address,
3687ec681f3Smrg                                                    buffer->size);
3697ec681f3Smrg      }
3707ec681f3Smrg   }
3717ec681f3Smrg
3727ec681f3Smrg   /* 3DSTATE_WM in the hope we can avoid spawning fragment shaders
3737ec681f3Smrg    * threads or if we have dirty dynamic primitive topology state and
3747ec681f3Smrg    * need to toggle 3DSTATE_WM::MultisampleRasterizationMode dynamically.
3757ec681f3Smrg    */
3767ec681f3Smrg   if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE ||
3777ec681f3Smrg       cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) {
3787ec681f3Smrg      const uint8_t color_writes = cmd_buffer->state.gfx.dynamic.color_writes;
3797ec681f3Smrg
3807ec681f3Smrg      bool dirty_color_blend =
3817ec681f3Smrg         cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE;
3827ec681f3Smrg
3837ec681f3Smrg      bool dirty_primitive_topology =
3847ec681f3Smrg         cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY;
3857ec681f3Smrg
3867ec681f3Smrg      VkPolygonMode dynamic_raster_mode;
3877ec681f3Smrg      VkPrimitiveTopology primitive_topology =
3887ec681f3Smrg         cmd_buffer->state.gfx.dynamic.primitive_topology;
3897ec681f3Smrg      dynamic_raster_mode =
3907ec681f3Smrg         genX(raster_polygon_mode)(cmd_buffer->state.gfx.pipeline,
3917ec681f3Smrg                                   primitive_topology);
3927ec681f3Smrg
3937ec681f3Smrg      if (dirty_color_blend || dirty_primitive_topology) {
3947ec681f3Smrg         uint32_t dwords[GENX(3DSTATE_WM_length)];
3957ec681f3Smrg         struct GENX(3DSTATE_WM) wm = {
3967ec681f3Smrg            GENX(3DSTATE_WM_header),
3977ec681f3Smrg
3987ec681f3Smrg            .ThreadDispatchEnable = pipeline->force_fragment_thread_dispatch ||
3997ec681f3Smrg                                    color_writes,
4007ec681f3Smrg            .MultisampleRasterizationMode =
4017ec681f3Smrg               genX(ms_rasterization_mode)(pipeline, dynamic_raster_mode),
4027ec681f3Smrg         };
4037ec681f3Smrg         GENX(3DSTATE_WM_pack)(NULL, dwords, &wm);
4047ec681f3Smrg
4057ec681f3Smrg         anv_batch_emit_merge(&cmd_buffer->batch, dwords, pipeline->gfx7.wm);
4067ec681f3Smrg      }
4077ec681f3Smrg
4087ec681f3Smrg   }
4097ec681f3Smrg
4107ec681f3Smrg   if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS) {
4117ec681f3Smrg      genX(emit_multisample)(&cmd_buffer->batch,
4127ec681f3Smrg                             cmd_buffer->state.gfx.dynamic.sample_locations.samples,
4137ec681f3Smrg                             cmd_buffer->state.gfx.dynamic.sample_locations.locations);
4147ec681f3Smrg   }
4157ec681f3Smrg
4167ec681f3Smrg   if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE ||
4177ec681f3Smrg       cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP) {
4187ec681f3Smrg      const uint8_t color_writes = cmd_buffer->state.gfx.dynamic.color_writes;
4197ec681f3Smrg      bool dirty_color_blend =
4207ec681f3Smrg         cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE;
4217ec681f3Smrg
4227ec681f3Smrg      /* Blend states of each RT */
4237ec681f3Smrg      uint32_t surface_count = 0;
4247ec681f3Smrg      struct anv_pipeline_bind_map *map;
4257ec681f3Smrg      if (anv_pipeline_has_stage(pipeline, MESA_SHADER_FRAGMENT)) {
4267ec681f3Smrg         map = &pipeline->shaders[MESA_SHADER_FRAGMENT]->bind_map;
4277ec681f3Smrg         surface_count = map->surface_count;
4287ec681f3Smrg      }
4297ec681f3Smrg
4307ec681f3Smrg      uint32_t blend_dws[GENX(BLEND_STATE_length) +
4317ec681f3Smrg                         MAX_RTS * GENX(BLEND_STATE_ENTRY_length)];
4327ec681f3Smrg      uint32_t *dws = blend_dws;
4337ec681f3Smrg      memset(blend_dws, 0, sizeof(blend_dws));
4347ec681f3Smrg
4357ec681f3Smrg      /* Skip this part */
4367ec681f3Smrg      dws += GENX(BLEND_STATE_length);
4377ec681f3Smrg
4387ec681f3Smrg      bool dirty_logic_op =
4397ec681f3Smrg         cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP;
4407ec681f3Smrg
4417ec681f3Smrg      for (uint32_t i = 0; i < surface_count; i++) {
4427ec681f3Smrg         struct anv_pipeline_binding *binding = &map->surface_to_descriptor[i];
4437ec681f3Smrg         bool write_disabled =
4447ec681f3Smrg            dirty_color_blend && (color_writes & (1u << binding->index)) == 0;
4457ec681f3Smrg         struct GENX(BLEND_STATE_ENTRY) entry = {
4467ec681f3Smrg            .WriteDisableAlpha = write_disabled,
4477ec681f3Smrg            .WriteDisableRed   = write_disabled,
4487ec681f3Smrg            .WriteDisableGreen = write_disabled,
4497ec681f3Smrg            .WriteDisableBlue  = write_disabled,
4507ec681f3Smrg            .LogicOpFunction =
4517ec681f3Smrg               dirty_logic_op ? genX(vk_to_intel_logic_op)[d->logic_op] : 0,
4527ec681f3Smrg         };
4537ec681f3Smrg         GENX(BLEND_STATE_ENTRY_pack)(NULL, dws, &entry);
4547ec681f3Smrg         dws += GENX(BLEND_STATE_ENTRY_length);
4557ec681f3Smrg      }
4567ec681f3Smrg
4577ec681f3Smrg      uint32_t num_dwords = GENX(BLEND_STATE_length) +
4587ec681f3Smrg         GENX(BLEND_STATE_ENTRY_length) * surface_count;
4597ec681f3Smrg
4607ec681f3Smrg      struct anv_state blend_states =
4617ec681f3Smrg         anv_cmd_buffer_merge_dynamic(cmd_buffer, blend_dws,
4627ec681f3Smrg                                      pipeline->gfx7.blend_state, num_dwords, 64);
4637ec681f3Smrg      anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_BLEND_STATE_POINTERS), bsp) {
4647ec681f3Smrg         bsp.BlendStatePointer      = blend_states.offset;
4657ec681f3Smrg      }
4667ec681f3Smrg   }
4677ec681f3Smrg
4687ec681f3Smrg   cmd_buffer->state.gfx.dirty = 0;
4697ec681f3Smrg}
4707ec681f3Smrg
4717ec681f3Smrgvoid
4727ec681f3SmrggenX(cmd_buffer_enable_pma_fix)(struct anv_cmd_buffer *cmd_buffer,
4737ec681f3Smrg                                bool enable)
4747ec681f3Smrg{
4757ec681f3Smrg   /* The NP PMA fix doesn't exist on gfx7 */
4767ec681f3Smrg}
477