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