~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/gallium/drivers/zink/zink_state.c

  • Committer: mmach
  • Date: 2022-09-22 19:58:36 UTC
  • Revision ID: netbit73@gmail.com-20220922195836-9nl9joew85y8d25o
2022-07-04 12:44:28

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2018 Collabora Ltd.
 
3
 *
 
4
 * Permission is hereby granted, free of charge, to any person obtaining a
 
5
 * copy of this software and associated documentation files (the "Software"),
 
6
 * to deal in the Software without restriction, including without limitation
 
7
 * on the rights to use, copy, modify, merge, publish, distribute, sub
 
8
 * license, and/or sell copies of the Software, and to permit persons to whom
 
9
 * the Software is furnished to do so, subject to the following conditions:
 
10
 *
 
11
 * The above copyright notice and this permission notice (including the next
 
12
 * paragraph) shall be included in all copies or substantial portions of the
 
13
 * Software.
 
14
 *
 
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 
18
 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
 
19
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 
20
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 
21
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 
22
 */
 
23
 
 
24
#include "zink_state.h"
 
25
 
 
26
#include "zink_context.h"
 
27
#include "zink_format.h"
 
28
#include "zink_program.h"
 
29
#include "zink_screen.h"
 
30
 
 
31
#include "compiler/shader_enums.h"
 
32
#include "util/u_dual_blend.h"
 
33
#include "util/u_memory.h"
 
34
#include "util/u_helpers.h"
 
35
 
 
36
#include <math.h>
 
37
 
 
38
static void *
 
39
zink_create_vertex_elements_state(struct pipe_context *pctx,
 
40
                                  unsigned num_elements,
 
41
                                  const struct pipe_vertex_element *elements)
 
42
{
 
43
   struct zink_screen *screen = zink_screen(pctx->screen);
 
44
   unsigned int i;
 
45
   struct zink_vertex_elements_state *ves = CALLOC_STRUCT(zink_vertex_elements_state);
 
46
   if (!ves)
 
47
      return NULL;
 
48
   ves->hw_state.hash = _mesa_hash_pointer(ves);
 
49
 
 
50
   int buffer_map[PIPE_MAX_ATTRIBS];
 
51
   for (int i = 0; i < ARRAY_SIZE(buffer_map); ++i)
 
52
      buffer_map[i] = -1;
 
53
 
 
54
   int num_bindings = 0;
 
55
   unsigned num_decomposed = 0;
 
56
   uint32_t size8 = 0;
 
57
   uint32_t size16 = 0;
 
58
   uint32_t size32 = 0;
 
59
   for (i = 0; i < num_elements; ++i) {
 
60
      const struct pipe_vertex_element *elem = elements + i;
 
61
 
 
62
      int binding = elem->vertex_buffer_index;
 
63
      if (buffer_map[binding] < 0) {
 
64
         ves->binding_map[num_bindings] = binding;
 
65
         buffer_map[binding] = num_bindings++;
 
66
      }
 
67
      binding = buffer_map[binding];
 
68
 
 
69
      ves->bindings[binding].binding = binding;
 
70
      ves->bindings[binding].inputRate = elem->instance_divisor ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
 
71
 
 
72
      assert(!elem->instance_divisor || zink_screen(pctx->screen)->info.have_EXT_vertex_attribute_divisor);
 
73
      if (elem->instance_divisor > screen->info.vdiv_props.maxVertexAttribDivisor)
 
74
         debug_printf("zink: clamping instance divisor %u to %u\n", elem->instance_divisor, screen->info.vdiv_props.maxVertexAttribDivisor);
 
75
      ves->divisor[binding] = MIN2(elem->instance_divisor, screen->info.vdiv_props.maxVertexAttribDivisor);
 
76
 
 
77
      VkFormat format;
 
78
      if (screen->format_props[elem->src_format].bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)
 
79
         format = zink_get_format(screen, elem->src_format);
 
80
      else {
 
81
         enum pipe_format new_format = zink_decompose_vertex_format(elem->src_format);
 
82
         assert(new_format);
 
83
         num_decomposed++;
 
84
         assert(screen->format_props[new_format].bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT);
 
85
         if (util_format_get_blocksize(new_format) == 4)
 
86
            size32 |= BITFIELD_BIT(i);
 
87
         else if (util_format_get_blocksize(new_format) == 2)
 
88
            size16 |= BITFIELD_BIT(i);
 
89
         else
 
90
            size8 |= BITFIELD_BIT(i);
 
91
         format = zink_get_format(screen, new_format);
 
92
         unsigned size;
 
93
         if (i < 8)
 
94
            size = 1;
 
95
         else if (i < 16)
 
96
            size = 2;
 
97
         else
 
98
            size = 4;
 
99
         if (util_format_get_nr_components(elem->src_format) == 4) {
 
100
            ves->decomposed_attrs |= BITFIELD_BIT(i);
 
101
            ves->decomposed_attrs_size = size;
 
102
         } else {
 
103
            ves->decomposed_attrs_without_w |= BITFIELD_BIT(i);
 
104
            ves->decomposed_attrs_without_w_size = size;
 
105
         }
 
106
      }
 
107
 
 
108
      if (screen->info.have_EXT_vertex_input_dynamic_state) {
 
109
         ves->hw_state.dynattribs[i].sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT;
 
110
         ves->hw_state.dynattribs[i].binding = binding;
 
111
         ves->hw_state.dynattribs[i].location = i;
 
112
         ves->hw_state.dynattribs[i].format = format;
 
113
         assert(ves->hw_state.dynattribs[i].format != VK_FORMAT_UNDEFINED);
 
114
         ves->hw_state.dynattribs[i].offset = elem->src_offset;
 
115
      } else {
 
116
         ves->hw_state.attribs[i].binding = binding;
 
117
         ves->hw_state.attribs[i].location = i;
 
118
         ves->hw_state.attribs[i].format = format;
 
119
         assert(ves->hw_state.attribs[i].format != VK_FORMAT_UNDEFINED);
 
120
         ves->hw_state.attribs[i].offset = elem->src_offset;
 
121
      }
 
122
   }
 
123
   assert(num_decomposed + num_elements <= PIPE_MAX_ATTRIBS);
 
124
   u_foreach_bit(i, ves->decomposed_attrs | ves->decomposed_attrs_without_w) {
 
125
      const struct pipe_vertex_element *elem = elements + i;
 
126
      const struct util_format_description *desc = util_format_description(elem->src_format);
 
127
      unsigned size = 1;
 
128
      if (size32 & BITFIELD_BIT(i))
 
129
         size = 4;
 
130
      else if (size16 & BITFIELD_BIT(i))
 
131
         size = 2;
 
132
      else
 
133
         assert(size8 & BITFIELD_BIT(i));
 
134
      for (unsigned j = 1; j < desc->nr_channels; j++) {
 
135
         if (screen->info.have_EXT_vertex_input_dynamic_state) {
 
136
            memcpy(&ves->hw_state.dynattribs[num_elements], &ves->hw_state.dynattribs[i], sizeof(VkVertexInputAttributeDescription2EXT));
 
137
            ves->hw_state.dynattribs[num_elements].location = num_elements;
 
138
            ves->hw_state.dynattribs[num_elements].offset += j * size;
 
139
         } else {
 
140
            memcpy(&ves->hw_state.attribs[num_elements], &ves->hw_state.attribs[i], sizeof(VkVertexInputAttributeDescription));
 
141
            ves->hw_state.attribs[num_elements].location = num_elements;
 
142
            ves->hw_state.attribs[num_elements].offset += j * size;
 
143
         }
 
144
         num_elements++;
 
145
      }
 
146
   }
 
147
   ves->hw_state.num_bindings = num_bindings;
 
148
   ves->hw_state.num_attribs = num_elements;
 
149
   if (screen->info.have_EXT_vertex_input_dynamic_state) {
 
150
      for (int i = 0; i < num_bindings; ++i) {
 
151
         ves->hw_state.dynbindings[i].sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT;
 
152
         ves->hw_state.dynbindings[i].binding = ves->bindings[i].binding;
 
153
         ves->hw_state.dynbindings[i].inputRate = ves->bindings[i].inputRate;
 
154
         if (ves->divisor[i])
 
155
            ves->hw_state.dynbindings[i].divisor = ves->divisor[i];
 
156
         else
 
157
            ves->hw_state.dynbindings[i].divisor = 1;
 
158
      }
 
159
   } else {
 
160
      for (int i = 0; i < num_bindings; ++i) {
 
161
         ves->hw_state.b.bindings[i].binding = ves->bindings[i].binding;
 
162
         ves->hw_state.b.bindings[i].inputRate = ves->bindings[i].inputRate;
 
163
         if (ves->divisor[i]) {
 
164
            ves->hw_state.b.divisors[ves->hw_state.b.divisors_present].divisor = ves->divisor[i];
 
165
            ves->hw_state.b.divisors[ves->hw_state.b.divisors_present].binding = ves->bindings[i].binding;
 
166
            ves->hw_state.b.divisors_present++;
 
167
         }
 
168
      }
 
169
   }
 
170
   return ves;
 
171
}
 
172
 
 
173
static void
 
174
zink_bind_vertex_elements_state(struct pipe_context *pctx,
 
175
                                void *cso)
 
176
{
 
177
   struct zink_context *ctx = zink_context(pctx);
 
178
   struct zink_gfx_pipeline_state *state = &ctx->gfx_pipeline_state;
 
179
   ctx->element_state = cso;
 
180
   if (cso) {
 
181
      if (state->element_state != &ctx->element_state->hw_state) {
 
182
         ctx->vertex_state_changed = !zink_screen(pctx->screen)->info.have_EXT_vertex_input_dynamic_state;
 
183
         ctx->vertex_buffers_dirty = ctx->element_state->hw_state.num_bindings > 0;
 
184
      }
 
185
      const struct zink_vs_key *vs = zink_get_vs_key(ctx);
 
186
      uint32_t decomposed_attrs = 0, decomposed_attrs_without_w = 0;
 
187
      switch (vs->size) {
 
188
      case 1:
 
189
         decomposed_attrs = vs->u8.decomposed_attrs;
 
190
         decomposed_attrs_without_w = vs->u8.decomposed_attrs_without_w;
 
191
         break;
 
192
      case 2:
 
193
         decomposed_attrs = vs->u16.decomposed_attrs;
 
194
         decomposed_attrs_without_w = vs->u16.decomposed_attrs_without_w;
 
195
         break;
 
196
      case 4:
 
197
         decomposed_attrs = vs->u16.decomposed_attrs;
 
198
         decomposed_attrs_without_w = vs->u16.decomposed_attrs_without_w;
 
199
         break;
 
200
      }
 
201
      if (ctx->element_state->decomposed_attrs != decomposed_attrs ||
 
202
          ctx->element_state->decomposed_attrs_without_w != decomposed_attrs_without_w) {
 
203
         unsigned size = MAX2(ctx->element_state->decomposed_attrs_size, ctx->element_state->decomposed_attrs_without_w_size);
 
204
         struct zink_shader_key *key = (struct zink_shader_key *)zink_set_vs_key(ctx);
 
205
         key->size -= 2 * key->key.vs.size;
 
206
         switch (size) {
 
207
         case 1:
 
208
            key->key.vs.u8.decomposed_attrs = ctx->element_state->decomposed_attrs;
 
209
            key->key.vs.u8.decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w;
 
210
            break;
 
211
         case 2:
 
212
            key->key.vs.u16.decomposed_attrs = ctx->element_state->decomposed_attrs;
 
213
            key->key.vs.u16.decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w;
 
214
            break;
 
215
         case 4:
 
216
            key->key.vs.u32.decomposed_attrs = ctx->element_state->decomposed_attrs;
 
217
            key->key.vs.u32.decomposed_attrs_without_w = ctx->element_state->decomposed_attrs_without_w;
 
218
            break;
 
219
         default: break;
 
220
         }
 
221
         key->key.vs.size = size;
 
222
         key->size += 2 * size;
 
223
      }
 
224
      state->element_state = &ctx->element_state->hw_state;
 
225
   } else {
 
226
     state->element_state = NULL;
 
227
     ctx->vertex_buffers_dirty = false;
 
228
   }
 
229
}
 
230
 
 
231
static void
 
232
zink_delete_vertex_elements_state(struct pipe_context *pctx,
 
233
                                  void *ves)
 
234
{
 
235
   FREE(ves);
 
236
}
 
237
 
 
238
static VkBlendFactor
 
239
blend_factor(enum pipe_blendfactor factor)
 
240
{
 
241
   switch (factor) {
 
242
   case PIPE_BLENDFACTOR_ONE: return VK_BLEND_FACTOR_ONE;
 
243
   case PIPE_BLENDFACTOR_SRC_COLOR: return VK_BLEND_FACTOR_SRC_COLOR;
 
244
   case PIPE_BLENDFACTOR_SRC_ALPHA: return VK_BLEND_FACTOR_SRC_ALPHA;
 
245
   case PIPE_BLENDFACTOR_DST_ALPHA: return VK_BLEND_FACTOR_DST_ALPHA;
 
246
   case PIPE_BLENDFACTOR_DST_COLOR: return VK_BLEND_FACTOR_DST_COLOR;
 
247
   case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
 
248
      return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
 
249
   case PIPE_BLENDFACTOR_CONST_COLOR: return VK_BLEND_FACTOR_CONSTANT_COLOR;
 
250
   case PIPE_BLENDFACTOR_CONST_ALPHA: return VK_BLEND_FACTOR_CONSTANT_ALPHA;
 
251
   case PIPE_BLENDFACTOR_SRC1_COLOR: return VK_BLEND_FACTOR_SRC1_COLOR;
 
252
   case PIPE_BLENDFACTOR_SRC1_ALPHA: return VK_BLEND_FACTOR_SRC1_ALPHA;
 
253
 
 
254
   case PIPE_BLENDFACTOR_ZERO: return VK_BLEND_FACTOR_ZERO;
 
255
 
 
256
   case PIPE_BLENDFACTOR_INV_SRC_COLOR:
 
257
      return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
 
258
   case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
 
259
      return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
 
260
   case PIPE_BLENDFACTOR_INV_DST_ALPHA:
 
261
      return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
 
262
   case PIPE_BLENDFACTOR_INV_DST_COLOR:
 
263
      return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
 
264
 
 
265
   case PIPE_BLENDFACTOR_INV_CONST_COLOR:
 
266
      return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
 
267
   case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
 
268
      return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
 
269
   case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
 
270
      return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
 
271
   case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
 
272
      return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
 
273
   }
 
274
   unreachable("unexpected blend factor");
 
275
}
 
276
 
 
277
 
 
278
static bool
 
279
need_blend_constants(enum pipe_blendfactor factor)
 
280
{
 
281
   switch (factor) {
 
282
   case PIPE_BLENDFACTOR_CONST_COLOR:
 
283
   case PIPE_BLENDFACTOR_CONST_ALPHA:
 
284
   case PIPE_BLENDFACTOR_INV_CONST_COLOR:
 
285
   case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
 
286
      return true;
 
287
 
 
288
   default:
 
289
      return false;
 
290
   }
 
291
}
 
292
 
 
293
static VkBlendOp
 
294
blend_op(enum pipe_blend_func func)
 
295
{
 
296
   switch (func) {
 
297
   case PIPE_BLEND_ADD: return VK_BLEND_OP_ADD;
 
298
   case PIPE_BLEND_SUBTRACT: return VK_BLEND_OP_SUBTRACT;
 
299
   case PIPE_BLEND_REVERSE_SUBTRACT: return VK_BLEND_OP_REVERSE_SUBTRACT;
 
300
   case PIPE_BLEND_MIN: return VK_BLEND_OP_MIN;
 
301
   case PIPE_BLEND_MAX: return VK_BLEND_OP_MAX;
 
302
   }
 
303
   unreachable("unexpected blend function");
 
304
}
 
305
 
 
306
static VkLogicOp
 
307
logic_op(enum pipe_logicop func)
 
308
{
 
309
   switch (func) {
 
310
   case PIPE_LOGICOP_CLEAR: return VK_LOGIC_OP_CLEAR;
 
311
   case PIPE_LOGICOP_NOR: return VK_LOGIC_OP_NOR;
 
312
   case PIPE_LOGICOP_AND_INVERTED: return VK_LOGIC_OP_AND_INVERTED;
 
313
   case PIPE_LOGICOP_COPY_INVERTED: return VK_LOGIC_OP_COPY_INVERTED;
 
314
   case PIPE_LOGICOP_AND_REVERSE: return VK_LOGIC_OP_AND_REVERSE;
 
315
   case PIPE_LOGICOP_INVERT: return VK_LOGIC_OP_INVERT;
 
316
   case PIPE_LOGICOP_XOR: return VK_LOGIC_OP_XOR;
 
317
   case PIPE_LOGICOP_NAND: return VK_LOGIC_OP_NAND;
 
318
   case PIPE_LOGICOP_AND: return VK_LOGIC_OP_AND;
 
319
   case PIPE_LOGICOP_EQUIV: return VK_LOGIC_OP_EQUIVALENT;
 
320
   case PIPE_LOGICOP_NOOP: return VK_LOGIC_OP_NO_OP;
 
321
   case PIPE_LOGICOP_OR_INVERTED: return VK_LOGIC_OP_OR_INVERTED;
 
322
   case PIPE_LOGICOP_COPY: return VK_LOGIC_OP_COPY;
 
323
   case PIPE_LOGICOP_OR_REVERSE: return VK_LOGIC_OP_OR_REVERSE;
 
324
   case PIPE_LOGICOP_OR: return VK_LOGIC_OP_OR;
 
325
   case PIPE_LOGICOP_SET: return VK_LOGIC_OP_SET;
 
326
   }
 
327
   unreachable("unexpected logicop function");
 
328
}
 
329
 
 
330
/* from iris */
 
331
static enum pipe_blendfactor
 
332
fix_blendfactor(enum pipe_blendfactor f, bool alpha_to_one)
 
333
{
 
334
   if (alpha_to_one) {
 
335
      if (f == PIPE_BLENDFACTOR_SRC1_ALPHA)
 
336
         return PIPE_BLENDFACTOR_ONE;
 
337
 
 
338
      if (f == PIPE_BLENDFACTOR_INV_SRC1_ALPHA)
 
339
         return PIPE_BLENDFACTOR_ZERO;
 
340
   }
 
341
 
 
342
   return f;
 
343
}
 
344
 
 
345
static void *
 
346
zink_create_blend_state(struct pipe_context *pctx,
 
347
                        const struct pipe_blend_state *blend_state)
 
348
{
 
349
   struct zink_blend_state *cso = CALLOC_STRUCT(zink_blend_state);
 
350
   if (!cso)
 
351
      return NULL;
 
352
   cso->hash = _mesa_hash_pointer(cso);
 
353
 
 
354
   if (blend_state->logicop_enable) {
 
355
      cso->logicop_enable = VK_TRUE;
 
356
      cso->logicop_func = logic_op(blend_state->logicop_func);
 
357
   }
 
358
 
 
359
   /* TODO: figure out what to do with dither (nothing is probably "OK" for now,
 
360
    *       as dithering is undefined in GL
 
361
    */
 
362
 
 
363
   /* TODO: these are multisampling-state, and should be set there instead of
 
364
    *       here, as that's closer tied to the update-frequency
 
365
    */
 
366
   cso->alpha_to_coverage = blend_state->alpha_to_coverage;
 
367
   cso->alpha_to_one = blend_state->alpha_to_one;
 
368
 
 
369
   cso->need_blend_constants = false;
 
370
 
 
371
   for (int i = 0; i < blend_state->max_rt + 1; ++i) {
 
372
      const struct pipe_rt_blend_state *rt = blend_state->rt;
 
373
      if (blend_state->independent_blend_enable)
 
374
         rt = blend_state->rt + i;
 
375
 
 
376
      VkPipelineColorBlendAttachmentState att = {0};
 
377
 
 
378
      if (rt->blend_enable) {
 
379
         att.blendEnable = VK_TRUE;
 
380
         att.srcColorBlendFactor = blend_factor(fix_blendfactor(rt->rgb_src_factor, cso->alpha_to_one));
 
381
         att.dstColorBlendFactor = blend_factor(fix_blendfactor(rt->rgb_dst_factor, cso->alpha_to_one));
 
382
         att.colorBlendOp = blend_op(rt->rgb_func);
 
383
         att.srcAlphaBlendFactor = blend_factor(fix_blendfactor(rt->alpha_src_factor, cso->alpha_to_one));
 
384
         att.dstAlphaBlendFactor = blend_factor(fix_blendfactor(rt->alpha_dst_factor, cso->alpha_to_one));
 
385
         att.alphaBlendOp = blend_op(rt->alpha_func);
 
386
 
 
387
         if (need_blend_constants(rt->rgb_src_factor) ||
 
388
             need_blend_constants(rt->rgb_dst_factor) ||
 
389
             need_blend_constants(rt->alpha_src_factor) ||
 
390
             need_blend_constants(rt->alpha_dst_factor))
 
391
            cso->need_blend_constants = true;
 
392
      }
 
393
 
 
394
      if (rt->colormask & PIPE_MASK_R)
 
395
         att.colorWriteMask |= VK_COLOR_COMPONENT_R_BIT;
 
396
      if (rt->colormask & PIPE_MASK_G)
 
397
         att.colorWriteMask |= VK_COLOR_COMPONENT_G_BIT;
 
398
      if (rt->colormask & PIPE_MASK_B)
 
399
         att.colorWriteMask |= VK_COLOR_COMPONENT_B_BIT;
 
400
      if (rt->colormask & PIPE_MASK_A)
 
401
         att.colorWriteMask |= VK_COLOR_COMPONENT_A_BIT;
 
402
 
 
403
      cso->attachments[i] = att;
 
404
   }
 
405
   cso->dual_src_blend = util_blend_state_is_dual(blend_state, 0);
 
406
 
 
407
   return cso;
 
408
}
 
409
 
 
410
static void
 
411
zink_bind_blend_state(struct pipe_context *pctx, void *cso)
 
412
{
 
413
   struct zink_context *ctx = zink_context(pctx);
 
414
   struct zink_gfx_pipeline_state* state = &zink_context(pctx)->gfx_pipeline_state;
 
415
   struct zink_blend_state *blend = cso;
 
416
 
 
417
   if (state->blend_state != cso) {
 
418
      state->blend_state = cso;
 
419
      state->blend_id = blend ? blend->hash : 0;
 
420
      state->dirty = true;
 
421
      bool force_dual_color_blend = zink_screen(pctx->screen)->driconf.dual_color_blend_by_location &&
 
422
                                    blend && blend->dual_src_blend && state->blend_state->attachments[0].blendEnable;
 
423
      if (force_dual_color_blend != zink_get_fs_key(ctx)->force_dual_color_blend)
 
424
         zink_set_fs_key(ctx)->force_dual_color_blend = force_dual_color_blend;
 
425
      ctx->blend_state_changed = true;
 
426
   }
 
427
}
 
428
 
 
429
static void
 
430
zink_delete_blend_state(struct pipe_context *pctx, void *blend_state)
 
431
{
 
432
   FREE(blend_state);
 
433
}
 
434
 
 
435
static VkCompareOp
 
436
compare_op(enum pipe_compare_func func)
 
437
{
 
438
   switch (func) {
 
439
   case PIPE_FUNC_NEVER: return VK_COMPARE_OP_NEVER;
 
440
   case PIPE_FUNC_LESS: return VK_COMPARE_OP_LESS;
 
441
   case PIPE_FUNC_EQUAL: return VK_COMPARE_OP_EQUAL;
 
442
   case PIPE_FUNC_LEQUAL: return VK_COMPARE_OP_LESS_OR_EQUAL;
 
443
   case PIPE_FUNC_GREATER: return VK_COMPARE_OP_GREATER;
 
444
   case PIPE_FUNC_NOTEQUAL: return VK_COMPARE_OP_NOT_EQUAL;
 
445
   case PIPE_FUNC_GEQUAL: return VK_COMPARE_OP_GREATER_OR_EQUAL;
 
446
   case PIPE_FUNC_ALWAYS: return VK_COMPARE_OP_ALWAYS;
 
447
   }
 
448
   unreachable("unexpected func");
 
449
}
 
450
 
 
451
static VkStencilOp
 
452
stencil_op(enum pipe_stencil_op op)
 
453
{
 
454
   switch (op) {
 
455
   case PIPE_STENCIL_OP_KEEP: return VK_STENCIL_OP_KEEP;
 
456
   case PIPE_STENCIL_OP_ZERO: return VK_STENCIL_OP_ZERO;
 
457
   case PIPE_STENCIL_OP_REPLACE: return VK_STENCIL_OP_REPLACE;
 
458
   case PIPE_STENCIL_OP_INCR: return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
 
459
   case PIPE_STENCIL_OP_DECR: return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
 
460
   case PIPE_STENCIL_OP_INCR_WRAP: return VK_STENCIL_OP_INCREMENT_AND_WRAP;
 
461
   case PIPE_STENCIL_OP_DECR_WRAP: return VK_STENCIL_OP_DECREMENT_AND_WRAP;
 
462
   case PIPE_STENCIL_OP_INVERT: return VK_STENCIL_OP_INVERT;
 
463
   }
 
464
   unreachable("unexpected op");
 
465
}
 
466
 
 
467
static VkStencilOpState
 
468
stencil_op_state(const struct pipe_stencil_state *src)
 
469
{
 
470
   VkStencilOpState ret;
 
471
   ret.failOp = stencil_op(src->fail_op);
 
472
   ret.passOp = stencil_op(src->zpass_op);
 
473
   ret.depthFailOp = stencil_op(src->zfail_op);
 
474
   ret.compareOp = compare_op(src->func);
 
475
   ret.compareMask = src->valuemask;
 
476
   ret.writeMask = src->writemask;
 
477
   ret.reference = 0; // not used: we'll use a dynamic state for this
 
478
   return ret;
 
479
}
 
480
 
 
481
static void *
 
482
zink_create_depth_stencil_alpha_state(struct pipe_context *pctx,
 
483
                                      const struct pipe_depth_stencil_alpha_state *depth_stencil_alpha)
 
484
{
 
485
   struct zink_depth_stencil_alpha_state *cso = CALLOC_STRUCT(zink_depth_stencil_alpha_state);
 
486
   if (!cso)
 
487
      return NULL;
 
488
 
 
489
   cso->base = *depth_stencil_alpha;
 
490
 
 
491
   if (depth_stencil_alpha->depth_enabled) {
 
492
      cso->hw_state.depth_test = VK_TRUE;
 
493
      cso->hw_state.depth_compare_op = compare_op(depth_stencil_alpha->depth_func);
 
494
   }
 
495
 
 
496
   if (depth_stencil_alpha->depth_bounds_test) {
 
497
      cso->hw_state.depth_bounds_test = VK_TRUE;
 
498
      cso->hw_state.min_depth_bounds = depth_stencil_alpha->depth_bounds_min;
 
499
      cso->hw_state.max_depth_bounds = depth_stencil_alpha->depth_bounds_max;
 
500
   }
 
501
 
 
502
   if (depth_stencil_alpha->stencil[0].enabled) {
 
503
      cso->hw_state.stencil_test = VK_TRUE;
 
504
      cso->hw_state.stencil_front = stencil_op_state(depth_stencil_alpha->stencil);
 
505
   }
 
506
 
 
507
   if (depth_stencil_alpha->stencil[1].enabled)
 
508
      cso->hw_state.stencil_back = stencil_op_state(depth_stencil_alpha->stencil + 1);
 
509
   else
 
510
      cso->hw_state.stencil_back = cso->hw_state.stencil_front;
 
511
 
 
512
   cso->hw_state.depth_write = depth_stencil_alpha->depth_writemask;
 
513
 
 
514
   return cso;
 
515
}
 
516
 
 
517
static void
 
518
zink_bind_depth_stencil_alpha_state(struct pipe_context *pctx, void *cso)
 
519
{
 
520
   struct zink_context *ctx = zink_context(pctx);
 
521
 
 
522
   bool prev_zwrite = ctx->dsa_state ? ctx->dsa_state->hw_state.depth_write : false;
 
523
   ctx->dsa_state = cso;
 
524
 
 
525
   if (cso) {
 
526
      struct zink_gfx_pipeline_state *state = &ctx->gfx_pipeline_state;
 
527
      if (state->dyn_state1.depth_stencil_alpha_state != &ctx->dsa_state->hw_state) {
 
528
         state->dyn_state1.depth_stencil_alpha_state = &ctx->dsa_state->hw_state;
 
529
         state->dirty |= !zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state;
 
530
         ctx->dsa_state_changed = true;
 
531
      }
 
532
   }
 
533
   if (prev_zwrite != (ctx->dsa_state ? ctx->dsa_state->hw_state.depth_write : false)) {
 
534
      ctx->rp_changed = true;
 
535
      zink_batch_no_rp(ctx);
 
536
   }
 
537
}
 
538
 
 
539
static void
 
540
zink_delete_depth_stencil_alpha_state(struct pipe_context *pctx,
 
541
                                      void *depth_stencil_alpha)
 
542
{
 
543
   FREE(depth_stencil_alpha);
 
544
}
 
545
 
 
546
static float
 
547
round_to_granularity(float value, float granularity)
 
548
{
 
549
   return roundf(value / granularity) * granularity;
 
550
}
 
551
 
 
552
static float
 
553
line_width(float width, float granularity, const float range[2])
 
554
{
 
555
   assert(granularity >= 0);
 
556
   assert(range[0] <= range[1]);
 
557
 
 
558
   if (granularity > 0)
 
559
      width = round_to_granularity(width, granularity);
 
560
 
 
561
   return CLAMP(width, range[0], range[1]);
 
562
}
 
563
 
 
564
static void *
 
565
zink_create_rasterizer_state(struct pipe_context *pctx,
 
566
                             const struct pipe_rasterizer_state *rs_state)
 
567
{
 
568
   struct zink_screen *screen = zink_screen(pctx->screen);
 
569
 
 
570
   struct zink_rasterizer_state *state = CALLOC_STRUCT(zink_rasterizer_state);
 
571
   if (!state)
 
572
      return NULL;
 
573
 
 
574
   state->base = *rs_state;
 
575
   state->base.line_stipple_factor++;
 
576
   state->hw_state.line_stipple_enable = rs_state->line_stipple_enable;
 
577
 
 
578
   assert(rs_state->depth_clip_far == rs_state->depth_clip_near);
 
579
   state->hw_state.depth_clamp = rs_state->depth_clip_near == 0;
 
580
   state->hw_state.force_persample_interp = rs_state->force_persample_interp;
 
581
   state->hw_state.pv_last = !rs_state->flatshade_first;
 
582
   state->hw_state.clip_halfz = rs_state->clip_halfz;
 
583
 
 
584
   assert(rs_state->fill_front <= PIPE_POLYGON_MODE_POINT);
 
585
   if (rs_state->fill_back != rs_state->fill_front)
 
586
      debug_printf("BUG: vulkan doesn't support different front and back fill modes\n");
 
587
   state->hw_state.polygon_mode = rs_state->fill_front; // same values
 
588
   state->hw_state.cull_mode = rs_state->cull_face; // same bits
 
589
 
 
590
   state->front_face = rs_state->front_ccw ?
 
591
                       VK_FRONT_FACE_COUNTER_CLOCKWISE :
 
592
                       VK_FRONT_FACE_CLOCKWISE;
 
593
 
 
594
   state->hw_state.line_mode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
 
595
   if (rs_state->line_rectangular) {
 
596
      if (rs_state->line_smooth)
 
597
         state->hw_state.line_mode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;
 
598
      else
 
599
         state->hw_state.line_mode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
 
600
   } else {
 
601
      state->hw_state.line_mode = VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
 
602
   }
 
603
 
 
604
   if (!rs_state->line_stipple_enable) {
 
605
      state->base.line_stipple_factor = 0;
 
606
      state->base.line_stipple_pattern = UINT16_MAX;
 
607
   }
 
608
 
 
609
   state->offset_point = rs_state->offset_point;
 
610
   state->offset_line = rs_state->offset_line;
 
611
   state->offset_tri = rs_state->offset_tri;
 
612
   state->offset_units = rs_state->offset_units;
 
613
   state->offset_clamp = rs_state->offset_clamp;
 
614
   state->offset_scale = rs_state->offset_scale;
 
615
 
 
616
   state->line_width = line_width(rs_state->line_width,
 
617
                                  screen->info.props.limits.lineWidthGranularity,
 
618
                                  screen->info.props.limits.lineWidthRange);
 
619
 
 
620
   return state;
 
621
}
 
622
 
 
623
static void
 
624
zink_bind_rasterizer_state(struct pipe_context *pctx, void *cso)
 
625
{
 
626
   struct zink_context *ctx = zink_context(pctx);
 
627
   struct zink_screen *screen = zink_screen(pctx->screen);
 
628
   bool point_quad_rasterization = ctx->rast_state ? ctx->rast_state->base.point_quad_rasterization : false;
 
629
   bool scissor = ctx->rast_state ? ctx->rast_state->base.scissor : false;
 
630
   bool pv_last = ctx->rast_state ? ctx->rast_state->hw_state.pv_last : false;
 
631
   bool force_persample_interp = ctx->rast_state ? ctx->rast_state->hw_state.force_persample_interp : false;
 
632
   bool clip_halfz = ctx->rast_state ? ctx->rast_state->hw_state.clip_halfz : false;
 
633
   bool rasterizer_discard = ctx->rast_state ? ctx->rast_state->base.rasterizer_discard : false;
 
634
   ctx->rast_state = cso;
 
635
 
 
636
   if (ctx->rast_state) {
 
637
      if (screen->info.have_EXT_provoking_vertex &&
 
638
          pv_last != ctx->rast_state->hw_state.pv_last &&
 
639
          /* without this prop, change in pv mode requires new rp */
 
640
          !screen->info.pv_props.provokingVertexModePerPipeline)
 
641
         zink_batch_no_rp(ctx);
 
642
      uint32_t rast_bits = 0;
 
643
      memcpy(&rast_bits, &ctx->rast_state->hw_state, sizeof(struct zink_rasterizer_hw_state));
 
644
      ctx->gfx_pipeline_state.rast_state = rast_bits & BITFIELD_MASK(ZINK_RAST_HW_STATE_SIZE);
 
645
 
 
646
      ctx->gfx_pipeline_state.dirty = true;
 
647
      ctx->rast_state_changed = true;
 
648
 
 
649
      if (clip_halfz != ctx->rast_state->base.clip_halfz) {
 
650
         if (!screen->driver_workarounds.depth_clip_control_missing)
 
651
            ctx->gfx_pipeline_state.dirty = true;
 
652
         else
 
653
            zink_set_last_vertex_key(ctx)->clip_halfz = ctx->rast_state->base.clip_halfz;
 
654
         ctx->vp_state_changed = true;
 
655
      }
 
656
 
 
657
      if (ctx->gfx_pipeline_state.dyn_state1.front_face != ctx->rast_state->front_face) {
 
658
         ctx->gfx_pipeline_state.dyn_state1.front_face = ctx->rast_state->front_face;
 
659
         ctx->gfx_pipeline_state.dirty |= !zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state;
 
660
      }
 
661
      if (!ctx->primitives_generated_active)
 
662
         zink_set_rasterizer_discard(ctx, false);
 
663
      else if (rasterizer_discard != ctx->rast_state->base.rasterizer_discard)
 
664
         zink_set_color_write_enables(ctx);
 
665
 
 
666
      if (ctx->rast_state->base.point_quad_rasterization != point_quad_rasterization)
 
667
         zink_set_fs_point_coord_key(ctx);
 
668
      if (ctx->rast_state->base.scissor != scissor)
 
669
         ctx->scissor_changed = true;
 
670
 
 
671
      if (ctx->rast_state->base.force_persample_interp != force_persample_interp)
 
672
         zink_set_fs_key(ctx)->force_persample_interp = ctx->rast_state->base.force_persample_interp;
 
673
   }
 
674
}
 
675
 
 
676
static void
 
677
zink_delete_rasterizer_state(struct pipe_context *pctx, void *rs_state)
 
678
{
 
679
   FREE(rs_state);
 
680
}
 
681
 
 
682
struct pipe_vertex_state *
 
683
zink_create_vertex_state(struct pipe_screen *pscreen,
 
684
                          struct pipe_vertex_buffer *buffer,
 
685
                          const struct pipe_vertex_element *elements,
 
686
                          unsigned num_elements,
 
687
                          struct pipe_resource *indexbuf,
 
688
                          uint32_t full_velem_mask)
 
689
{
 
690
   struct zink_vertex_state *zstate = CALLOC_STRUCT(zink_vertex_state);
 
691
   _mesa_set_init(&zstate->masks, NULL, NULL, _mesa_key_pointer_equal);
 
692
 
 
693
   util_init_pipe_vertex_state(pscreen, buffer, elements, num_elements, indexbuf, full_velem_mask,
 
694
                               &zstate->b);
 
695
 
 
696
   /* Initialize the vertex element state in state->element.
 
697
    * Do it by creating a vertex element state object and copying it there.
 
698
    */
 
699
   struct zink_context ctx;
 
700
   ctx.base.screen = pscreen;
 
701
   struct zink_vertex_elements_state *elems = zink_create_vertex_elements_state(&ctx.base, num_elements, elements);
 
702
   for (unsigned i = 0; i < elems->hw_state.num_bindings; i++) {
 
703
      if (zink_screen(pscreen)->info.have_EXT_vertex_input_dynamic_state)
 
704
         elems->hw_state.dynbindings[i].stride = buffer->stride;
 
705
   }
 
706
   zstate->velems = *elems;
 
707
   zink_delete_vertex_elements_state(&ctx.base, elems);
 
708
 
 
709
   return &zstate->b;
 
710
}
 
711
 
 
712
void
 
713
zink_vertex_state_destroy(struct pipe_screen *pscreen, struct pipe_vertex_state *vstate)
 
714
{
 
715
   struct zink_vertex_state *zstate = (struct zink_vertex_state *)vstate;
 
716
   ralloc_free(zstate->masks.table);
 
717
   pipe_vertex_buffer_unreference(&vstate->input.vbuffer);
 
718
   pipe_resource_reference(&vstate->input.indexbuf, NULL);
 
719
   FREE(vstate);
 
720
}
 
721
 
 
722
const struct zink_vertex_elements_hw_state *
 
723
zink_vertex_state_mask(struct pipe_vertex_state *vstate, uint32_t partial_velem_mask, bool have_EXT_vertex_input_dynamic_state)
 
724
{
 
725
   struct zink_vertex_state *zstate = (struct zink_vertex_state *)vstate;
 
726
 
 
727
   if (partial_velem_mask == vstate->input.full_velem_mask)
 
728
      return &zstate->velems.hw_state;
 
729
   struct set_entry *he = _mesa_set_search_pre_hashed(&zstate->masks, partial_velem_mask, (void*)(uintptr_t)partial_velem_mask);
 
730
   if (he)
 
731
      return he->key;
 
732
 
 
733
   struct zink_vertex_elements_hw_state *hw_state = rzalloc(zstate->masks.table, struct zink_vertex_elements_hw_state);
 
734
   unsigned i = 0;
 
735
   if (have_EXT_vertex_input_dynamic_state) {
 
736
      u_foreach_bit(elem, vstate->input.full_velem_mask & partial_velem_mask) {
 
737
         unsigned idx = util_bitcount(vstate->input.full_velem_mask & BITFIELD_MASK(elem));
 
738
         hw_state->dynattribs[i] = zstate->velems.hw_state.dynattribs[idx];
 
739
         hw_state->dynattribs[i].location = i;
 
740
         i++;
 
741
      }
 
742
      memcpy(hw_state->dynbindings, zstate->velems.hw_state.dynbindings,
 
743
             zstate->velems.hw_state.num_bindings * sizeof(VkVertexInputBindingDescription2EXT));
 
744
   } else {
 
745
   }
 
746
   hw_state->num_attribs = i;
 
747
   hw_state->num_bindings = zstate->velems.hw_state.num_bindings;
 
748
   _mesa_set_add_pre_hashed(&zstate->masks, partial_velem_mask, hw_state);
 
749
   return hw_state;
 
750
}
 
751
 
 
752
struct pipe_vertex_state *
 
753
zink_cache_create_vertex_state(struct pipe_screen *pscreen,
 
754
                               struct pipe_vertex_buffer *buffer,
 
755
                               const struct pipe_vertex_element *elements,
 
756
                               unsigned num_elements,
 
757
                               struct pipe_resource *indexbuf,
 
758
                               uint32_t full_velem_mask)
 
759
{
 
760
   struct zink_screen *screen = zink_screen(pscreen);
 
761
 
 
762
   return util_vertex_state_cache_get(pscreen, buffer, elements, num_elements, indexbuf,
 
763
                                      full_velem_mask, &screen->vertex_state_cache);
 
764
}
 
765
 
 
766
void
 
767
zink_cache_vertex_state_destroy(struct pipe_screen *pscreen, struct pipe_vertex_state *vstate)
 
768
{
 
769
   struct zink_screen *screen = zink_screen(pscreen);
 
770
 
 
771
   util_vertex_state_destroy(pscreen, &screen->vertex_state_cache, vstate);
 
772
}
 
773
 
 
774
void
 
775
zink_context_state_init(struct pipe_context *pctx)
 
776
{
 
777
   pctx->create_vertex_elements_state = zink_create_vertex_elements_state;
 
778
   pctx->bind_vertex_elements_state = zink_bind_vertex_elements_state;
 
779
   pctx->delete_vertex_elements_state = zink_delete_vertex_elements_state;
 
780
 
 
781
   pctx->create_blend_state = zink_create_blend_state;
 
782
   pctx->bind_blend_state = zink_bind_blend_state;
 
783
   pctx->delete_blend_state = zink_delete_blend_state;
 
784
 
 
785
   pctx->create_depth_stencil_alpha_state = zink_create_depth_stencil_alpha_state;
 
786
   pctx->bind_depth_stencil_alpha_state = zink_bind_depth_stencil_alpha_state;
 
787
   pctx->delete_depth_stencil_alpha_state = zink_delete_depth_stencil_alpha_state;
 
788
 
 
789
   pctx->create_rasterizer_state = zink_create_rasterizer_state;
 
790
   pctx->bind_rasterizer_state = zink_bind_rasterizer_state;
 
791
   pctx->delete_rasterizer_state = zink_delete_rasterizer_state;
 
792
}