17ec681f3Smrg/*
27ec681f3Smrg * Copyright 2018 Collabora Ltd.
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
87ec681f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom
97ec681f3Smrg * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
197ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
207ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
217ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE.
227ec681f3Smrg */
237ec681f3Smrg
247ec681f3Smrg#include "zink_state.h"
257ec681f3Smrg
267ec681f3Smrg#include "zink_context.h"
277ec681f3Smrg#include "zink_format.h"
287ec681f3Smrg#include "zink_program.h"
297ec681f3Smrg#include "zink_screen.h"
307ec681f3Smrg
317ec681f3Smrg#include "compiler/shader_enums.h"
327ec681f3Smrg#include "util/u_dual_blend.h"
337ec681f3Smrg#include "util/u_memory.h"
347ec681f3Smrg
357ec681f3Smrg#include <math.h>
367ec681f3Smrg
377ec681f3Smrgstatic void *
387ec681f3Smrgzink_create_vertex_elements_state(struct pipe_context *pctx,
397ec681f3Smrg                                  unsigned num_elements,
407ec681f3Smrg                                  const struct pipe_vertex_element *elements)
417ec681f3Smrg{
427ec681f3Smrg   struct zink_screen *screen = zink_screen(pctx->screen);
437ec681f3Smrg   unsigned int i;
447ec681f3Smrg   struct zink_vertex_elements_state *ves = CALLOC_STRUCT(zink_vertex_elements_state);
457ec681f3Smrg   if (!ves)
467ec681f3Smrg      return NULL;
477ec681f3Smrg   ves->hw_state.hash = _mesa_hash_pointer(ves);
487ec681f3Smrg
497ec681f3Smrg   int buffer_map[PIPE_MAX_ATTRIBS];
507ec681f3Smrg   for (int i = 0; i < ARRAY_SIZE(buffer_map); ++i)
517ec681f3Smrg      buffer_map[i] = -1;
527ec681f3Smrg
537ec681f3Smrg   int num_bindings = 0;
547ec681f3Smrg   unsigned num_decomposed = 0;
557ec681f3Smrg   uint32_t size8 = 0;
567ec681f3Smrg   uint32_t size16 = 0;
577ec681f3Smrg   uint32_t size32 = 0;
587ec681f3Smrg   for (i = 0; i < num_elements; ++i) {
597ec681f3Smrg      const struct pipe_vertex_element *elem = elements + i;
607ec681f3Smrg
617ec681f3Smrg      int binding = elem->vertex_buffer_index;
627ec681f3Smrg      if (buffer_map[binding] < 0) {
637ec681f3Smrg         ves->binding_map[num_bindings] = binding;
647ec681f3Smrg         buffer_map[binding] = num_bindings++;
657ec681f3Smrg      }
667ec681f3Smrg      binding = buffer_map[binding];
677ec681f3Smrg
687ec681f3Smrg      ves->bindings[binding].binding = binding;
697ec681f3Smrg      ves->bindings[binding].inputRate = elem->instance_divisor ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
707ec681f3Smrg
717ec681f3Smrg      assert(!elem->instance_divisor || zink_screen(pctx->screen)->info.have_EXT_vertex_attribute_divisor);
727ec681f3Smrg      if (elem->instance_divisor > screen->info.vdiv_props.maxVertexAttribDivisor)
737ec681f3Smrg         debug_printf("zink: clamping instance divisor %u to %u\n", elem->instance_divisor, screen->info.vdiv_props.maxVertexAttribDivisor);
747ec681f3Smrg      ves->divisor[binding] = MIN2(elem->instance_divisor, screen->info.vdiv_props.maxVertexAttribDivisor);
757ec681f3Smrg
767ec681f3Smrg      VkFormat format;
777ec681f3Smrg      if (screen->format_props[elem->src_format].bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)
787ec681f3Smrg         format = zink_get_format(screen, elem->src_format);
797ec681f3Smrg      else {
807ec681f3Smrg         enum pipe_format new_format = zink_decompose_vertex_format(elem->src_format);
817ec681f3Smrg         assert(new_format);
827ec681f3Smrg         num_decomposed++;
837ec681f3Smrg         assert(screen->format_props[new_format].bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT);
847ec681f3Smrg         if (util_format_get_blocksize(new_format) == 4)
857ec681f3Smrg            size32 |= BITFIELD_BIT(i);
867ec681f3Smrg         else if (util_format_get_blocksize(new_format) == 2)
877ec681f3Smrg            size16 |= BITFIELD_BIT(i);
887ec681f3Smrg         else
897ec681f3Smrg            size8 |= BITFIELD_BIT(i);
907ec681f3Smrg         format = zink_get_format(screen, new_format);
917ec681f3Smrg         unsigned size;
927ec681f3Smrg         if (i < 8)
937ec681f3Smrg            size = 1;
947ec681f3Smrg         else if (i < 16)
957ec681f3Smrg            size = 2;
967ec681f3Smrg         else
977ec681f3Smrg            size = 4;
987ec681f3Smrg         if (util_format_get_nr_components(elem->src_format) == 4) {
997ec681f3Smrg            ves->decomposed_attrs |= BITFIELD_BIT(i);
1007ec681f3Smrg            ves->decomposed_attrs_size = size;
1017ec681f3Smrg         } else {
1027ec681f3Smrg            ves->decomposed_attrs_without_w |= BITFIELD_BIT(i);
1037ec681f3Smrg            ves->decomposed_attrs_without_w_size = size;
1047ec681f3Smrg         }
1057ec681f3Smrg      }
1067ec681f3Smrg
1077ec681f3Smrg      if (screen->info.have_EXT_vertex_input_dynamic_state) {
1087ec681f3Smrg         ves->hw_state.dynattribs[i].sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT;
1097ec681f3Smrg         ves->hw_state.dynattribs[i].binding = binding;
1107ec681f3Smrg         ves->hw_state.dynattribs[i].location = i;
1117ec681f3Smrg         ves->hw_state.dynattribs[i].format = format;
1127ec681f3Smrg         assert(ves->hw_state.dynattribs[i].format != VK_FORMAT_UNDEFINED);
1137ec681f3Smrg         ves->hw_state.dynattribs[i].offset = elem->src_offset;
1147ec681f3Smrg      } else {
1157ec681f3Smrg         ves->hw_state.attribs[i].binding = binding;
1167ec681f3Smrg         ves->hw_state.attribs[i].location = i;
1177ec681f3Smrg         ves->hw_state.attribs[i].format = format;
1187ec681f3Smrg         assert(ves->hw_state.attribs[i].format != VK_FORMAT_UNDEFINED);
1197ec681f3Smrg         ves->hw_state.attribs[i].offset = elem->src_offset;
1207ec681f3Smrg      }
1217ec681f3Smrg   }
1227ec681f3Smrg   assert(num_decomposed + num_elements <= PIPE_MAX_ATTRIBS);
1237ec681f3Smrg   u_foreach_bit(i, ves->decomposed_attrs | ves->decomposed_attrs_without_w) {
1247ec681f3Smrg      const struct pipe_vertex_element *elem = elements + i;
1257ec681f3Smrg      const struct util_format_description *desc = util_format_description(elem->src_format);
1267ec681f3Smrg      unsigned size = 1;
1277ec681f3Smrg      if (size32 & BITFIELD_BIT(i))
1287ec681f3Smrg         size = 4;
1297ec681f3Smrg      else if (size16 & BITFIELD_BIT(i))
1307ec681f3Smrg         size = 2;
1317ec681f3Smrg      for (unsigned j = 1; j < desc->nr_channels; j++) {
1327ec681f3Smrg         if (screen->info.have_EXT_vertex_input_dynamic_state) {
1337ec681f3Smrg            memcpy(&ves->hw_state.dynattribs[num_elements], &ves->hw_state.dynattribs[i], sizeof(VkVertexInputAttributeDescription2EXT));
1347ec681f3Smrg            ves->hw_state.dynattribs[num_elements].location = num_elements;
1357ec681f3Smrg            ves->hw_state.dynattribs[num_elements].offset += j * size;
1367ec681f3Smrg         } else {
1377ec681f3Smrg            memcpy(&ves->hw_state.attribs[num_elements], &ves->hw_state.attribs[i], sizeof(VkVertexInputAttributeDescription));
1387ec681f3Smrg            ves->hw_state.attribs[num_elements].location = num_elements;
1397ec681f3Smrg            ves->hw_state.attribs[num_elements].offset += j * size;
1407ec681f3Smrg         }
1417ec681f3Smrg         num_elements++;
1427ec681f3Smrg      }
1437ec681f3Smrg   }
1447ec681f3Smrg   ves->hw_state.num_bindings = num_bindings;
1457ec681f3Smrg   ves->hw_state.num_attribs = num_elements;
1467ec681f3Smrg   if (screen->info.have_EXT_vertex_input_dynamic_state) {
1477ec681f3Smrg      for (int i = 0; i < num_bindings; ++i) {
1487ec681f3Smrg         ves->hw_state.dynbindings[i].sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT;
1497ec681f3Smrg         ves->hw_state.dynbindings[i].binding = ves->bindings[i].binding;
1507ec681f3Smrg         ves->hw_state.dynbindings[i].inputRate = ves->bindings[i].inputRate;
1517ec681f3Smrg         if (ves->divisor[i])
1527ec681f3Smrg            ves->hw_state.dynbindings[i].divisor = ves->divisor[i];
1537ec681f3Smrg         else
1547ec681f3Smrg            ves->hw_state.dynbindings[i].divisor = 1;
1557ec681f3Smrg      }
1567ec681f3Smrg   } else {
1577ec681f3Smrg      for (int i = 0; i < num_bindings; ++i) {
1587ec681f3Smrg         ves->hw_state.b.bindings[i].binding = ves->bindings[i].binding;
1597ec681f3Smrg         ves->hw_state.b.bindings[i].inputRate = ves->bindings[i].inputRate;
1607ec681f3Smrg         if (ves->divisor[i]) {
1617ec681f3Smrg            ves->hw_state.b.divisors[ves->hw_state.b.divisors_present].divisor = ves->divisor[i];
1627ec681f3Smrg            ves->hw_state.b.divisors[ves->hw_state.b.divisors_present].binding = ves->bindings[i].binding;
1637ec681f3Smrg            ves->hw_state.b.divisors_present++;
1647ec681f3Smrg         }
1657ec681f3Smrg      }
1667ec681f3Smrg   }
1677ec681f3Smrg   return ves;
1687ec681f3Smrg}
1697ec681f3Smrg
1707ec681f3Smrgstatic void
1717ec681f3Smrgzink_bind_vertex_elements_state(struct pipe_context *pctx,
1727ec681f3Smrg                                void *cso)
1737ec681f3Smrg{
1747ec681f3Smrg   struct zink_context *ctx = zink_context(pctx);
1757ec681f3Smrg   struct zink_gfx_pipeline_state *state = &ctx->gfx_pipeline_state;
1767ec681f3Smrg   ctx->element_state = cso;
1777ec681f3Smrg   if (cso) {
1787ec681f3Smrg      if (state->element_state != &ctx->element_state->hw_state) {
1797ec681f3Smrg         ctx->vertex_state_changed = !zink_screen(pctx->screen)->info.have_EXT_vertex_input_dynamic_state;
1807ec681f3Smrg         ctx->vertex_buffers_dirty = ctx->element_state->hw_state.num_bindings > 0;
1817ec681f3Smrg      }
1827ec681f3Smrg      const struct zink_vs_key *vs = zink_get_vs_key(ctx);
1837ec681f3Smrg      uint32_t decomposed_attrs = 0, decomposed_attrs_without_w = 0;
1847ec681f3Smrg      switch (vs->size) {
1857ec681f3Smrg      case 1:
1867ec681f3Smrg         decomposed_attrs = vs->u8.decomposed_attrs;
1877ec681f3Smrg         decomposed_attrs_without_w = vs->u8.decomposed_attrs_without_w;
1887ec681f3Smrg         break;
1897ec681f3Smrg      case 2:
1907ec681f3Smrg         decomposed_attrs = vs->u16.decomposed_attrs;
1917ec681f3Smrg         decomposed_attrs_without_w = vs->u16.decomposed_attrs_without_w;
1927ec681f3Smrg         break;
1937ec681f3Smrg      case 4:
1947ec681f3Smrg         decomposed_attrs = vs->u16.decomposed_attrs;
1957ec681f3Smrg         decomposed_attrs_without_w = vs->u16.decomposed_attrs_without_w;
1967ec681f3Smrg         break;
1977ec681f3Smrg      }
1987ec681f3Smrg      if (ctx->element_state->decomposed_attrs != decomposed_attrs ||
1997ec681f3Smrg          ctx->element_state->decomposed_attrs_without_w != decomposed_attrs_without_w) {
2007ec681f3Smrg         unsigned size = MAX2(ctx->element_state->decomposed_attrs_size, ctx->element_state->decomposed_attrs_without_w_size);
2017ec681f3Smrg         struct zink_shader_key *key = (struct zink_shader_key *)zink_set_vs_key(ctx);
2027ec681f3Smrg         key->size -= 2 * key->key.vs.size;
2037ec681f3Smrg         switch (size) {
2047ec681f3Smrg         case 1:
2057ec681f3Smrg            key->key.vs.u8.decomposed_attrs = ctx->element_state->decomposed_attrs;
2067ec681f3Smrg            key->key.vs.u8.decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w;
2077ec681f3Smrg            break;
2087ec681f3Smrg         case 2:
2097ec681f3Smrg            key->key.vs.u16.decomposed_attrs = ctx->element_state->decomposed_attrs;
2107ec681f3Smrg            key->key.vs.u16.decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w;
2117ec681f3Smrg            break;
2127ec681f3Smrg         case 4:
2137ec681f3Smrg            key->key.vs.u32.decomposed_attrs = ctx->element_state->decomposed_attrs;
2147ec681f3Smrg            key->key.vs.u32.decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w;
2157ec681f3Smrg            break;
2167ec681f3Smrg         default: break;
2177ec681f3Smrg         }
2187ec681f3Smrg         key->key.vs.size = size;
2197ec681f3Smrg         key->size += 2 * size;
2207ec681f3Smrg      }
2217ec681f3Smrg      state->element_state = &ctx->element_state->hw_state;
2227ec681f3Smrg   } else {
2237ec681f3Smrg     state->element_state = NULL;
2247ec681f3Smrg     ctx->vertex_buffers_dirty = false;
2257ec681f3Smrg   }
2267ec681f3Smrg}
2277ec681f3Smrg
2287ec681f3Smrgstatic void
2297ec681f3Smrgzink_delete_vertex_elements_state(struct pipe_context *pctx,
2307ec681f3Smrg                                  void *ves)
2317ec681f3Smrg{
2327ec681f3Smrg   FREE(ves);
2337ec681f3Smrg}
2347ec681f3Smrg
2357ec681f3Smrgstatic VkBlendFactor
2367ec681f3Smrgblend_factor(enum pipe_blendfactor factor)
2377ec681f3Smrg{
2387ec681f3Smrg   switch (factor) {
2397ec681f3Smrg   case PIPE_BLENDFACTOR_ONE: return VK_BLEND_FACTOR_ONE;
2407ec681f3Smrg   case PIPE_BLENDFACTOR_SRC_COLOR: return VK_BLEND_FACTOR_SRC_COLOR;
2417ec681f3Smrg   case PIPE_BLENDFACTOR_SRC_ALPHA: return VK_BLEND_FACTOR_SRC_ALPHA;
2427ec681f3Smrg   case PIPE_BLENDFACTOR_DST_ALPHA: return VK_BLEND_FACTOR_DST_ALPHA;
2437ec681f3Smrg   case PIPE_BLENDFACTOR_DST_COLOR: return VK_BLEND_FACTOR_DST_COLOR;
2447ec681f3Smrg   case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
2457ec681f3Smrg      return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
2467ec681f3Smrg   case PIPE_BLENDFACTOR_CONST_COLOR: return VK_BLEND_FACTOR_CONSTANT_COLOR;
2477ec681f3Smrg   case PIPE_BLENDFACTOR_CONST_ALPHA: return VK_BLEND_FACTOR_CONSTANT_ALPHA;
2487ec681f3Smrg   case PIPE_BLENDFACTOR_SRC1_COLOR: return VK_BLEND_FACTOR_SRC1_COLOR;
2497ec681f3Smrg   case PIPE_BLENDFACTOR_SRC1_ALPHA: return VK_BLEND_FACTOR_SRC1_ALPHA;
2507ec681f3Smrg
2517ec681f3Smrg   case PIPE_BLENDFACTOR_ZERO: return VK_BLEND_FACTOR_ZERO;
2527ec681f3Smrg
2537ec681f3Smrg   case PIPE_BLENDFACTOR_INV_SRC_COLOR:
2547ec681f3Smrg      return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
2557ec681f3Smrg   case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
2567ec681f3Smrg      return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
2577ec681f3Smrg   case PIPE_BLENDFACTOR_INV_DST_ALPHA:
2587ec681f3Smrg      return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
2597ec681f3Smrg   case PIPE_BLENDFACTOR_INV_DST_COLOR:
2607ec681f3Smrg      return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
2617ec681f3Smrg
2627ec681f3Smrg   case PIPE_BLENDFACTOR_INV_CONST_COLOR:
2637ec681f3Smrg      return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
2647ec681f3Smrg   case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
2657ec681f3Smrg      return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
2667ec681f3Smrg   case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
2677ec681f3Smrg      return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
2687ec681f3Smrg   case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
2697ec681f3Smrg      return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
2707ec681f3Smrg   }
2717ec681f3Smrg   unreachable("unexpected blend factor");
2727ec681f3Smrg}
2737ec681f3Smrg
2747ec681f3Smrg
2757ec681f3Smrgstatic bool
2767ec681f3Smrgneed_blend_constants(enum pipe_blendfactor factor)
2777ec681f3Smrg{
2787ec681f3Smrg   switch (factor) {
2797ec681f3Smrg   case PIPE_BLENDFACTOR_CONST_COLOR:
2807ec681f3Smrg   case PIPE_BLENDFACTOR_CONST_ALPHA:
2817ec681f3Smrg   case PIPE_BLENDFACTOR_INV_CONST_COLOR:
2827ec681f3Smrg   case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
2837ec681f3Smrg      return true;
2847ec681f3Smrg
2857ec681f3Smrg   default:
2867ec681f3Smrg      return false;
2877ec681f3Smrg   }
2887ec681f3Smrg}
2897ec681f3Smrg
2907ec681f3Smrgstatic VkBlendOp
2917ec681f3Smrgblend_op(enum pipe_blend_func func)
2927ec681f3Smrg{
2937ec681f3Smrg   switch (func) {
2947ec681f3Smrg   case PIPE_BLEND_ADD: return VK_BLEND_OP_ADD;
2957ec681f3Smrg   case PIPE_BLEND_SUBTRACT: return VK_BLEND_OP_SUBTRACT;
2967ec681f3Smrg   case PIPE_BLEND_REVERSE_SUBTRACT: return VK_BLEND_OP_REVERSE_SUBTRACT;
2977ec681f3Smrg   case PIPE_BLEND_MIN: return VK_BLEND_OP_MIN;
2987ec681f3Smrg   case PIPE_BLEND_MAX: return VK_BLEND_OP_MAX;
2997ec681f3Smrg   }
3007ec681f3Smrg   unreachable("unexpected blend function");
3017ec681f3Smrg}
3027ec681f3Smrg
3037ec681f3Smrgstatic VkLogicOp
3047ec681f3Smrglogic_op(enum pipe_logicop func)
3057ec681f3Smrg{
3067ec681f3Smrg   switch (func) {
3077ec681f3Smrg   case PIPE_LOGICOP_CLEAR: return VK_LOGIC_OP_CLEAR;
3087ec681f3Smrg   case PIPE_LOGICOP_NOR: return VK_LOGIC_OP_NOR;
3097ec681f3Smrg   case PIPE_LOGICOP_AND_INVERTED: return VK_LOGIC_OP_AND_INVERTED;
3107ec681f3Smrg   case PIPE_LOGICOP_COPY_INVERTED: return VK_LOGIC_OP_COPY_INVERTED;
3117ec681f3Smrg   case PIPE_LOGICOP_AND_REVERSE: return VK_LOGIC_OP_AND_REVERSE;
3127ec681f3Smrg   case PIPE_LOGICOP_INVERT: return VK_LOGIC_OP_INVERT;
3137ec681f3Smrg   case PIPE_LOGICOP_XOR: return VK_LOGIC_OP_XOR;
3147ec681f3Smrg   case PIPE_LOGICOP_NAND: return VK_LOGIC_OP_NAND;
3157ec681f3Smrg   case PIPE_LOGICOP_AND: return VK_LOGIC_OP_AND;
3167ec681f3Smrg   case PIPE_LOGICOP_EQUIV: return VK_LOGIC_OP_EQUIVALENT;
3177ec681f3Smrg   case PIPE_LOGICOP_NOOP: return VK_LOGIC_OP_NO_OP;
3187ec681f3Smrg   case PIPE_LOGICOP_OR_INVERTED: return VK_LOGIC_OP_OR_INVERTED;
3197ec681f3Smrg   case PIPE_LOGICOP_COPY: return VK_LOGIC_OP_COPY;
3207ec681f3Smrg   case PIPE_LOGICOP_OR_REVERSE: return VK_LOGIC_OP_OR_REVERSE;
3217ec681f3Smrg   case PIPE_LOGICOP_OR: return VK_LOGIC_OP_OR;
3227ec681f3Smrg   case PIPE_LOGICOP_SET: return VK_LOGIC_OP_SET;
3237ec681f3Smrg   }
3247ec681f3Smrg   unreachable("unexpected logicop function");
3257ec681f3Smrg}
3267ec681f3Smrg
3277ec681f3Smrg/* from iris */
3287ec681f3Smrgstatic enum pipe_blendfactor
3297ec681f3Smrgfix_blendfactor(enum pipe_blendfactor f, bool alpha_to_one)
3307ec681f3Smrg{
3317ec681f3Smrg   if (alpha_to_one) {
3327ec681f3Smrg      if (f == PIPE_BLENDFACTOR_SRC1_ALPHA)
3337ec681f3Smrg         return PIPE_BLENDFACTOR_ONE;
3347ec681f3Smrg
3357ec681f3Smrg      if (f == PIPE_BLENDFACTOR_INV_SRC1_ALPHA)
3367ec681f3Smrg         return PIPE_BLENDFACTOR_ZERO;
3377ec681f3Smrg   }
3387ec681f3Smrg
3397ec681f3Smrg   return f;
3407ec681f3Smrg}
3417ec681f3Smrg
3427ec681f3Smrgstatic void *
3437ec681f3Smrgzink_create_blend_state(struct pipe_context *pctx,
3447ec681f3Smrg                        const struct pipe_blend_state *blend_state)
3457ec681f3Smrg{
3467ec681f3Smrg   struct zink_blend_state *cso = CALLOC_STRUCT(zink_blend_state);
3477ec681f3Smrg   if (!cso)
3487ec681f3Smrg      return NULL;
3497ec681f3Smrg   cso->hash = _mesa_hash_pointer(cso);
3507ec681f3Smrg
3517ec681f3Smrg   if (blend_state->logicop_enable) {
3527ec681f3Smrg      cso->logicop_enable = VK_TRUE;
3537ec681f3Smrg      cso->logicop_func = logic_op(blend_state->logicop_func);
3547ec681f3Smrg   }
3557ec681f3Smrg
3567ec681f3Smrg   /* TODO: figure out what to do with dither (nothing is probably "OK" for now,
3577ec681f3Smrg    *       as dithering is undefined in GL
3587ec681f3Smrg    */
3597ec681f3Smrg
3607ec681f3Smrg   /* TODO: these are multisampling-state, and should be set there instead of
3617ec681f3Smrg    *       here, as that's closer tied to the update-frequency
3627ec681f3Smrg    */
3637ec681f3Smrg   cso->alpha_to_coverage = blend_state->alpha_to_coverage;
3647ec681f3Smrg   cso->alpha_to_one = blend_state->alpha_to_one;
3657ec681f3Smrg
3667ec681f3Smrg   cso->need_blend_constants = false;
3677ec681f3Smrg
3687ec681f3Smrg   for (int i = 0; i < blend_state->max_rt + 1; ++i) {
3697ec681f3Smrg      const struct pipe_rt_blend_state *rt = blend_state->rt;
3707ec681f3Smrg      if (blend_state->independent_blend_enable)
3717ec681f3Smrg         rt = blend_state->rt + i;
3727ec681f3Smrg
3737ec681f3Smrg      VkPipelineColorBlendAttachmentState att = {0};
3747ec681f3Smrg
3757ec681f3Smrg      if (rt->blend_enable) {
3767ec681f3Smrg         att.blendEnable = VK_TRUE;
3777ec681f3Smrg         att.srcColorBlendFactor = blend_factor(fix_blendfactor(rt->rgb_src_factor, cso->alpha_to_one));
3787ec681f3Smrg         att.dstColorBlendFactor = blend_factor(fix_blendfactor(rt->rgb_dst_factor, cso->alpha_to_one));
3797ec681f3Smrg         att.colorBlendOp = blend_op(rt->rgb_func);
3807ec681f3Smrg         att.srcAlphaBlendFactor = blend_factor(fix_blendfactor(rt->alpha_src_factor, cso->alpha_to_one));
3817ec681f3Smrg         att.dstAlphaBlendFactor = blend_factor(fix_blendfactor(rt->alpha_dst_factor, cso->alpha_to_one));
3827ec681f3Smrg         att.alphaBlendOp = blend_op(rt->alpha_func);
3837ec681f3Smrg
3847ec681f3Smrg         if (need_blend_constants(rt->rgb_src_factor) ||
3857ec681f3Smrg             need_blend_constants(rt->rgb_dst_factor) ||
3867ec681f3Smrg             need_blend_constants(rt->alpha_src_factor) ||
3877ec681f3Smrg             need_blend_constants(rt->alpha_dst_factor))
3887ec681f3Smrg            cso->need_blend_constants = true;
3897ec681f3Smrg      }
3907ec681f3Smrg
3917ec681f3Smrg      if (rt->colormask & PIPE_MASK_R)
3927ec681f3Smrg         att.colorWriteMask |= VK_COLOR_COMPONENT_R_BIT;
3937ec681f3Smrg      if (rt->colormask & PIPE_MASK_G)
3947ec681f3Smrg         att.colorWriteMask |= VK_COLOR_COMPONENT_G_BIT;
3957ec681f3Smrg      if (rt->colormask & PIPE_MASK_B)
3967ec681f3Smrg         att.colorWriteMask |= VK_COLOR_COMPONENT_B_BIT;
3977ec681f3Smrg      if (rt->colormask & PIPE_MASK_A)
3987ec681f3Smrg         att.colorWriteMask |= VK_COLOR_COMPONENT_A_BIT;
3997ec681f3Smrg
4007ec681f3Smrg      cso->attachments[i] = att;
4017ec681f3Smrg   }
4027ec681f3Smrg   cso->dual_src_blend = util_blend_state_is_dual(blend_state, 0);
4037ec681f3Smrg
4047ec681f3Smrg   return cso;
4057ec681f3Smrg}
4067ec681f3Smrg
4077ec681f3Smrgstatic void
4087ec681f3Smrgzink_bind_blend_state(struct pipe_context *pctx, void *cso)
4097ec681f3Smrg{
4107ec681f3Smrg   struct zink_context *ctx = zink_context(pctx);
4117ec681f3Smrg   struct zink_gfx_pipeline_state* state = &zink_context(pctx)->gfx_pipeline_state;
4127ec681f3Smrg   struct zink_blend_state *blend = cso;
4137ec681f3Smrg
4147ec681f3Smrg   if (state->blend_state != cso) {
4157ec681f3Smrg      state->blend_state = cso;
4167ec681f3Smrg      state->blend_id = blend ? blend->hash : 0;
4177ec681f3Smrg      state->dirty = true;
4187ec681f3Smrg      bool force_dual_color_blend = zink_screen(pctx->screen)->driconf.dual_color_blend_by_location &&
4197ec681f3Smrg                                    blend && blend->dual_src_blend && state->blend_state->attachments[1].blendEnable;
4207ec681f3Smrg      if (force_dual_color_blend != zink_get_fs_key(ctx)->force_dual_color_blend)
4217ec681f3Smrg         zink_set_fs_key(ctx)->force_dual_color_blend = force_dual_color_blend;
4227ec681f3Smrg      ctx->blend_state_changed = true;
4237ec681f3Smrg   }
4247ec681f3Smrg}
4257ec681f3Smrg
4267ec681f3Smrgstatic void
4277ec681f3Smrgzink_delete_blend_state(struct pipe_context *pctx, void *blend_state)
4287ec681f3Smrg{
4297ec681f3Smrg   FREE(blend_state);
4307ec681f3Smrg}
4317ec681f3Smrg
4327ec681f3Smrgstatic VkCompareOp
4337ec681f3Smrgcompare_op(enum pipe_compare_func func)
4347ec681f3Smrg{
4357ec681f3Smrg   switch (func) {
4367ec681f3Smrg   case PIPE_FUNC_NEVER: return VK_COMPARE_OP_NEVER;
4377ec681f3Smrg   case PIPE_FUNC_LESS: return VK_COMPARE_OP_LESS;
4387ec681f3Smrg   case PIPE_FUNC_EQUAL: return VK_COMPARE_OP_EQUAL;
4397ec681f3Smrg   case PIPE_FUNC_LEQUAL: return VK_COMPARE_OP_LESS_OR_EQUAL;
4407ec681f3Smrg   case PIPE_FUNC_GREATER: return VK_COMPARE_OP_GREATER;
4417ec681f3Smrg   case PIPE_FUNC_NOTEQUAL: return VK_COMPARE_OP_NOT_EQUAL;
4427ec681f3Smrg   case PIPE_FUNC_GEQUAL: return VK_COMPARE_OP_GREATER_OR_EQUAL;
4437ec681f3Smrg   case PIPE_FUNC_ALWAYS: return VK_COMPARE_OP_ALWAYS;
4447ec681f3Smrg   }
4457ec681f3Smrg   unreachable("unexpected func");
4467ec681f3Smrg}
4477ec681f3Smrg
4487ec681f3Smrgstatic VkStencilOp
4497ec681f3Smrgstencil_op(enum pipe_stencil_op op)
4507ec681f3Smrg{
4517ec681f3Smrg   switch (op) {
4527ec681f3Smrg   case PIPE_STENCIL_OP_KEEP: return VK_STENCIL_OP_KEEP;
4537ec681f3Smrg   case PIPE_STENCIL_OP_ZERO: return VK_STENCIL_OP_ZERO;
4547ec681f3Smrg   case PIPE_STENCIL_OP_REPLACE: return VK_STENCIL_OP_REPLACE;
4557ec681f3Smrg   case PIPE_STENCIL_OP_INCR: return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
4567ec681f3Smrg   case PIPE_STENCIL_OP_DECR: return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
4577ec681f3Smrg   case PIPE_STENCIL_OP_INCR_WRAP: return VK_STENCIL_OP_INCREMENT_AND_WRAP;
4587ec681f3Smrg   case PIPE_STENCIL_OP_DECR_WRAP: return VK_STENCIL_OP_DECREMENT_AND_WRAP;
4597ec681f3Smrg   case PIPE_STENCIL_OP_INVERT: return VK_STENCIL_OP_INVERT;
4607ec681f3Smrg   }
4617ec681f3Smrg   unreachable("unexpected op");
4627ec681f3Smrg}
4637ec681f3Smrg
4647ec681f3Smrgstatic VkStencilOpState
4657ec681f3Smrgstencil_op_state(const struct pipe_stencil_state *src)
4667ec681f3Smrg{
4677ec681f3Smrg   VkStencilOpState ret;
4687ec681f3Smrg   ret.failOp = stencil_op(src->fail_op);
4697ec681f3Smrg   ret.passOp = stencil_op(src->zpass_op);
4707ec681f3Smrg   ret.depthFailOp = stencil_op(src->zfail_op);
4717ec681f3Smrg   ret.compareOp = compare_op(src->func);
4727ec681f3Smrg   ret.compareMask = src->valuemask;
4737ec681f3Smrg   ret.writeMask = src->writemask;
4747ec681f3Smrg   ret.reference = 0; // not used: we'll use a dynamic state for this
4757ec681f3Smrg   return ret;
4767ec681f3Smrg}
4777ec681f3Smrg
4787ec681f3Smrgstatic void *
4797ec681f3Smrgzink_create_depth_stencil_alpha_state(struct pipe_context *pctx,
4807ec681f3Smrg                                      const struct pipe_depth_stencil_alpha_state *depth_stencil_alpha)
4817ec681f3Smrg{
4827ec681f3Smrg   struct zink_depth_stencil_alpha_state *cso = CALLOC_STRUCT(zink_depth_stencil_alpha_state);
4837ec681f3Smrg   if (!cso)
4847ec681f3Smrg      return NULL;
4857ec681f3Smrg
4867ec681f3Smrg   cso->base = *depth_stencil_alpha;
4877ec681f3Smrg
4887ec681f3Smrg   if (depth_stencil_alpha->depth_enabled) {
4897ec681f3Smrg      cso->hw_state.depth_test = VK_TRUE;
4907ec681f3Smrg      cso->hw_state.depth_compare_op = compare_op(depth_stencil_alpha->depth_func);
4917ec681f3Smrg   }
4927ec681f3Smrg
4937ec681f3Smrg   if (depth_stencil_alpha->depth_bounds_test) {
4947ec681f3Smrg      cso->hw_state.depth_bounds_test = VK_TRUE;
4957ec681f3Smrg      cso->hw_state.min_depth_bounds = depth_stencil_alpha->depth_bounds_min;
4967ec681f3Smrg      cso->hw_state.max_depth_bounds = depth_stencil_alpha->depth_bounds_max;
4977ec681f3Smrg   }
4987ec681f3Smrg
4997ec681f3Smrg   if (depth_stencil_alpha->stencil[0].enabled) {
5007ec681f3Smrg      cso->hw_state.stencil_test = VK_TRUE;
5017ec681f3Smrg      cso->hw_state.stencil_front = stencil_op_state(depth_stencil_alpha->stencil);
5027ec681f3Smrg   }
5037ec681f3Smrg
5047ec681f3Smrg   if (depth_stencil_alpha->stencil[1].enabled)
5057ec681f3Smrg      cso->hw_state.stencil_back = stencil_op_state(depth_stencil_alpha->stencil + 1);
5067ec681f3Smrg   else
5077ec681f3Smrg      cso->hw_state.stencil_back = cso->hw_state.stencil_front;
5087ec681f3Smrg
5097ec681f3Smrg   cso->hw_state.depth_write = depth_stencil_alpha->depth_writemask;
5107ec681f3Smrg
5117ec681f3Smrg   return cso;
5127ec681f3Smrg}
5137ec681f3Smrg
5147ec681f3Smrgstatic void
5157ec681f3Smrgzink_bind_depth_stencil_alpha_state(struct pipe_context *pctx, void *cso)
5167ec681f3Smrg{
5177ec681f3Smrg   struct zink_context *ctx = zink_context(pctx);
5187ec681f3Smrg
5197ec681f3Smrg   bool prev_zwrite = ctx->dsa_state ? ctx->dsa_state->hw_state.depth_write : false;
5207ec681f3Smrg   ctx->dsa_state = cso;
5217ec681f3Smrg
5227ec681f3Smrg   if (cso) {
5237ec681f3Smrg      struct zink_gfx_pipeline_state *state = &ctx->gfx_pipeline_state;
5247ec681f3Smrg      if (state->dyn_state1.depth_stencil_alpha_state != &ctx->dsa_state->hw_state) {
5257ec681f3Smrg         state->dyn_state1.depth_stencil_alpha_state = &ctx->dsa_state->hw_state;
5267ec681f3Smrg         state->dirty |= !zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state;
5277ec681f3Smrg         ctx->dsa_state_changed = true;
5287ec681f3Smrg      }
5297ec681f3Smrg   }
5307ec681f3Smrg   if (prev_zwrite != (ctx->dsa_state ? ctx->dsa_state->hw_state.depth_write : false)) {
5317ec681f3Smrg      ctx->rp_changed = true;
5327ec681f3Smrg      zink_batch_no_rp(ctx);
5337ec681f3Smrg   }
5347ec681f3Smrg}
5357ec681f3Smrg
5367ec681f3Smrgstatic void
5377ec681f3Smrgzink_delete_depth_stencil_alpha_state(struct pipe_context *pctx,
5387ec681f3Smrg                                      void *depth_stencil_alpha)
5397ec681f3Smrg{
5407ec681f3Smrg   FREE(depth_stencil_alpha);
5417ec681f3Smrg}
5427ec681f3Smrg
5437ec681f3Smrgstatic float
5447ec681f3Smrground_to_granularity(float value, float granularity)
5457ec681f3Smrg{
5467ec681f3Smrg   return roundf(value / granularity) * granularity;
5477ec681f3Smrg}
5487ec681f3Smrg
5497ec681f3Smrgstatic float
5507ec681f3Smrgline_width(float width, float granularity, const float range[2])
5517ec681f3Smrg{
5527ec681f3Smrg   assert(granularity >= 0);
5537ec681f3Smrg   assert(range[0] <= range[1]);
5547ec681f3Smrg
5557ec681f3Smrg   if (granularity > 0)
5567ec681f3Smrg      width = round_to_granularity(width, granularity);
5577ec681f3Smrg
5587ec681f3Smrg   return CLAMP(width, range[0], range[1]);
5597ec681f3Smrg}
5607ec681f3Smrg
5617ec681f3Smrg#define warn_line_feature(feat) \
5627ec681f3Smrg   do { \
5637ec681f3Smrg      static bool warned = false; \
5647ec681f3Smrg      if (!warned) { \
5657ec681f3Smrg         fprintf(stderr, "WARNING: Incorrect rendering will happen, " \
5667ec681f3Smrg                         "because the Vulkan device doesn't support " \
5677ec681f3Smrg                         "the %s feature of " \
5687ec681f3Smrg                         "VK_EXT_line_rasterization\n", feat); \
5697ec681f3Smrg         warned = true; \
5707ec681f3Smrg      } \
5717ec681f3Smrg   } while (0)
5727ec681f3Smrg
5737ec681f3Smrgstatic void *
5747ec681f3Smrgzink_create_rasterizer_state(struct pipe_context *pctx,
5757ec681f3Smrg                             const struct pipe_rasterizer_state *rs_state)
5767ec681f3Smrg{
5777ec681f3Smrg   struct zink_screen *screen = zink_screen(pctx->screen);
5787ec681f3Smrg
5797ec681f3Smrg   struct zink_rasterizer_state *state = CALLOC_STRUCT(zink_rasterizer_state);
5807ec681f3Smrg   if (!state)
5817ec681f3Smrg      return NULL;
5827ec681f3Smrg
5837ec681f3Smrg   state->base = *rs_state;
5847ec681f3Smrg   state->base.line_stipple_factor++;
5857ec681f3Smrg   state->hw_state.line_stipple_enable = rs_state->line_stipple_enable;
5867ec681f3Smrg
5877ec681f3Smrg   assert(rs_state->depth_clip_far == rs_state->depth_clip_near);
5887ec681f3Smrg   state->hw_state.depth_clamp = rs_state->depth_clip_near == 0;
5897ec681f3Smrg   state->hw_state.rasterizer_discard = rs_state->rasterizer_discard;
5907ec681f3Smrg   state->hw_state.force_persample_interp = rs_state->force_persample_interp;
5917ec681f3Smrg   state->hw_state.pv_last = !rs_state->flatshade_first;
5927ec681f3Smrg   state->hw_state.clip_halfz = rs_state->clip_halfz;
5937ec681f3Smrg
5947ec681f3Smrg   assert(rs_state->fill_front <= PIPE_POLYGON_MODE_POINT);
5957ec681f3Smrg   if (rs_state->fill_back != rs_state->fill_front)
5967ec681f3Smrg      debug_printf("BUG: vulkan doesn't support different front and back fill modes\n");
5977ec681f3Smrg   state->hw_state.polygon_mode = rs_state->fill_front; // same values
5987ec681f3Smrg   state->hw_state.cull_mode = rs_state->cull_face; // same bits
5997ec681f3Smrg
6007ec681f3Smrg   state->front_face = rs_state->front_ccw ?
6017ec681f3Smrg                       VK_FRONT_FACE_COUNTER_CLOCKWISE :
6027ec681f3Smrg                       VK_FRONT_FACE_CLOCKWISE;
6037ec681f3Smrg
6047ec681f3Smrg   VkPhysicalDeviceLineRasterizationFeaturesEXT *line_feats =
6057ec681f3Smrg            &screen->info.line_rast_feats;
6067ec681f3Smrg   state->hw_state.line_mode =
6077ec681f3Smrg      VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
6087ec681f3Smrg
6097ec681f3Smrg   if (rs_state->line_stipple_enable) {
6107ec681f3Smrg      if (screen->info.have_EXT_line_rasterization) {
6117ec681f3Smrg         if (rs_state->line_rectangular) {
6127ec681f3Smrg            if (rs_state->line_smooth) {
6137ec681f3Smrg               if (line_feats->stippledSmoothLines)
6147ec681f3Smrg                  state->hw_state.line_mode =
6157ec681f3Smrg                     VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;
6167ec681f3Smrg               else
6177ec681f3Smrg                  warn_line_feature("stippledSmoothLines");
6187ec681f3Smrg            } else if (line_feats->stippledRectangularLines)
6197ec681f3Smrg               state->hw_state.line_mode =
6207ec681f3Smrg                  VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
6217ec681f3Smrg            else
6227ec681f3Smrg               warn_line_feature("stippledRectangularLines");
6237ec681f3Smrg         } else if (line_feats->stippledBresenhamLines)
6247ec681f3Smrg            state->hw_state.line_mode =
6257ec681f3Smrg               VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
6267ec681f3Smrg         else {
6277ec681f3Smrg            warn_line_feature("stippledBresenhamLines");
6287ec681f3Smrg
6297ec681f3Smrg            /* no suitable mode that supports line stippling */
6307ec681f3Smrg            state->base.line_stipple_factor = 0;
6317ec681f3Smrg            state->base.line_stipple_pattern = UINT16_MAX;
6327ec681f3Smrg         }
6337ec681f3Smrg      }
6347ec681f3Smrg   } else {
6357ec681f3Smrg      if (screen->info.have_EXT_line_rasterization) {
6367ec681f3Smrg         if (rs_state->line_rectangular) {
6377ec681f3Smrg            if (rs_state->line_smooth) {
6387ec681f3Smrg               if (line_feats->smoothLines)
6397ec681f3Smrg                  state->hw_state.line_mode =
6407ec681f3Smrg                     VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;
6417ec681f3Smrg               else
6427ec681f3Smrg                  warn_line_feature("smoothLines");
6437ec681f3Smrg            } else if (line_feats->rectangularLines)
6447ec681f3Smrg               state->hw_state.line_mode =
6457ec681f3Smrg                  VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
6467ec681f3Smrg            else
6477ec681f3Smrg               warn_line_feature("rectangularLines");
6487ec681f3Smrg         } else if (line_feats->bresenhamLines)
6497ec681f3Smrg            state->hw_state.line_mode =
6507ec681f3Smrg               VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
6517ec681f3Smrg         else
6527ec681f3Smrg            warn_line_feature("bresenhamLines");
6537ec681f3Smrg      }
6547ec681f3Smrg      state->base.line_stipple_factor = 0;
6557ec681f3Smrg      state->base.line_stipple_pattern = UINT16_MAX;
6567ec681f3Smrg   }
6577ec681f3Smrg
6587ec681f3Smrg   state->offset_point = rs_state->offset_point;
6597ec681f3Smrg   state->offset_line = rs_state->offset_line;
6607ec681f3Smrg   state->offset_tri = rs_state->offset_tri;
6617ec681f3Smrg   state->offset_units = rs_state->offset_units;
6627ec681f3Smrg   state->offset_clamp = rs_state->offset_clamp;
6637ec681f3Smrg   state->offset_scale = rs_state->offset_scale;
6647ec681f3Smrg
6657ec681f3Smrg   state->line_width = line_width(rs_state->line_width,
6667ec681f3Smrg                                  screen->info.props.limits.lineWidthGranularity,
6677ec681f3Smrg                                  screen->info.props.limits.lineWidthRange);
6687ec681f3Smrg
6697ec681f3Smrg   return state;
6707ec681f3Smrg}
6717ec681f3Smrg
6727ec681f3Smrgstatic void
6737ec681f3Smrgzink_bind_rasterizer_state(struct pipe_context *pctx, void *cso)
6747ec681f3Smrg{
6757ec681f3Smrg   struct zink_context *ctx = zink_context(pctx);
6767ec681f3Smrg   struct zink_screen *screen = zink_screen(pctx->screen);
6777ec681f3Smrg   bool point_quad_rasterization = ctx->rast_state ? ctx->rast_state->base.point_quad_rasterization : false;
6787ec681f3Smrg   bool scissor = ctx->rast_state ? ctx->rast_state->base.scissor : false;
6797ec681f3Smrg   bool pv_last = ctx->rast_state ? ctx->rast_state->hw_state.pv_last : false;
6807ec681f3Smrg   ctx->rast_state = cso;
6817ec681f3Smrg
6827ec681f3Smrg   if (ctx->rast_state) {
6837ec681f3Smrg      if (screen->info.have_EXT_provoking_vertex &&
6847ec681f3Smrg          pv_last != ctx->rast_state->hw_state.pv_last &&
6857ec681f3Smrg          /* without this prop, change in pv mode requires new rp */
6867ec681f3Smrg          !screen->info.pv_props.provokingVertexModePerPipeline)
6877ec681f3Smrg         zink_batch_no_rp(ctx);
6887ec681f3Smrg      uint32_t rast_bits = 0;
6897ec681f3Smrg      memcpy(&rast_bits, &ctx->rast_state->hw_state, sizeof(struct zink_rasterizer_hw_state));
6907ec681f3Smrg      ctx->gfx_pipeline_state.rast_state = rast_bits & BITFIELD_MASK(ZINK_RAST_HW_STATE_SIZE);
6917ec681f3Smrg
6927ec681f3Smrg      ctx->gfx_pipeline_state.dirty = true;
6937ec681f3Smrg      ctx->rast_state_changed = true;
6947ec681f3Smrg
6957ec681f3Smrg      if (zink_get_last_vertex_key(ctx)->clip_halfz != ctx->rast_state->base.clip_halfz) {
6967ec681f3Smrg         zink_set_last_vertex_key(ctx)->clip_halfz = ctx->rast_state->base.clip_halfz;
6977ec681f3Smrg         ctx->vp_state_changed = true;
6987ec681f3Smrg      }
6997ec681f3Smrg
7007ec681f3Smrg      if (ctx->gfx_pipeline_state.dyn_state1.front_face != ctx->rast_state->front_face) {
7017ec681f3Smrg         ctx->gfx_pipeline_state.dyn_state1.front_face = ctx->rast_state->front_face;
7027ec681f3Smrg         ctx->gfx_pipeline_state.dirty |= !zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state;
7037ec681f3Smrg      }
7047ec681f3Smrg      if (ctx->rast_state->base.point_quad_rasterization != point_quad_rasterization)
7057ec681f3Smrg         zink_set_fs_point_coord_key(ctx);
7067ec681f3Smrg      if (ctx->rast_state->base.scissor != scissor)
7077ec681f3Smrg         ctx->scissor_changed = true;
7087ec681f3Smrg   }
7097ec681f3Smrg}
7107ec681f3Smrg
7117ec681f3Smrgstatic void
7127ec681f3Smrgzink_delete_rasterizer_state(struct pipe_context *pctx, void *rs_state)
7137ec681f3Smrg{
7147ec681f3Smrg   FREE(rs_state);
7157ec681f3Smrg}
7167ec681f3Smrg
7177ec681f3Smrgvoid
7187ec681f3Smrgzink_context_state_init(struct pipe_context *pctx)
7197ec681f3Smrg{
7207ec681f3Smrg   pctx->create_vertex_elements_state = zink_create_vertex_elements_state;
7217ec681f3Smrg   pctx->bind_vertex_elements_state = zink_bind_vertex_elements_state;
7227ec681f3Smrg   pctx->delete_vertex_elements_state = zink_delete_vertex_elements_state;
7237ec681f3Smrg
7247ec681f3Smrg   pctx->create_blend_state = zink_create_blend_state;
7257ec681f3Smrg   pctx->bind_blend_state = zink_bind_blend_state;
7267ec681f3Smrg   pctx->delete_blend_state = zink_delete_blend_state;
7277ec681f3Smrg
7287ec681f3Smrg   pctx->create_depth_stencil_alpha_state = zink_create_depth_stencil_alpha_state;
7297ec681f3Smrg   pctx->bind_depth_stencil_alpha_state = zink_bind_depth_stencil_alpha_state;
7307ec681f3Smrg   pctx->delete_depth_stencil_alpha_state = zink_delete_depth_stencil_alpha_state;
7317ec681f3Smrg
7327ec681f3Smrg   pctx->create_rasterizer_state = zink_create_rasterizer_state;
7337ec681f3Smrg   pctx->bind_rasterizer_state = zink_bind_rasterizer_state;
7347ec681f3Smrg   pctx->delete_rasterizer_state = zink_delete_rasterizer_state;
7357ec681f3Smrg}
736