radeonsi: remove redundant si_shader_info::images_declared
[mesa.git] / src / gallium / drivers / zink / zink_state.c
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_screen.h"
28
29 #include "util/u_memory.h"
30
31 #include <math.h>
32
33 static void *
34 zink_create_vertex_elements_state(struct pipe_context *pctx,
35 unsigned num_elements,
36 const struct pipe_vertex_element *elements)
37 {
38 struct zink_screen *screen = zink_screen(pctx->screen);
39 unsigned int i;
40 struct zink_vertex_elements_state *ves = CALLOC_STRUCT(zink_vertex_elements_state);
41 if (!ves)
42 return NULL;
43
44 int buffer_map[PIPE_MAX_ATTRIBS];
45 for (int i = 0; i < ARRAY_SIZE(buffer_map); ++i)
46 buffer_map[i] = -1;
47
48 int num_bindings = 0;
49 for (i = 0; i < num_elements; ++i) {
50 const struct pipe_vertex_element *elem = elements + i;
51 assert(!elem->instance_divisor);
52
53 int binding = elem->vertex_buffer_index;
54 if (buffer_map[binding] < 0) {
55 ves->binding_map[num_bindings] = binding;
56 buffer_map[binding] = num_bindings++;
57 }
58 binding = buffer_map[binding];
59
60
61 ves->bindings[binding].binding = binding;
62 ves->bindings[binding].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
63
64 ves->hw_state.attribs[i].binding = binding;
65 ves->hw_state.attribs[i].location = i; // TODO: unsure
66 ves->hw_state.attribs[i].format = zink_get_format(screen,
67 elem->src_format);
68 assert(ves->hw_state.attribs[i].format != VK_FORMAT_UNDEFINED);
69 ves->hw_state.attribs[i].offset = elem->src_offset;
70 }
71
72 ves->hw_state.num_bindings = num_bindings;
73 ves->hw_state.num_attribs = num_elements;
74 return ves;
75 }
76
77 static void
78 zink_bind_vertex_elements_state(struct pipe_context *pctx,
79 void *cso)
80 {
81 struct zink_context *ctx = zink_context(pctx);
82 struct zink_gfx_pipeline_state *state = &ctx->gfx_pipeline_state;
83 ctx->element_state = cso;
84 state->hash = 0;
85 if (cso) {
86 state->element_state = &ctx->element_state->hw_state;
87 struct zink_vertex_elements_state *ves = cso;
88 for (int i = 0; i < state->element_state->num_bindings; ++i) {
89 state->bindings[i].binding = ves->bindings[i].binding;
90 state->bindings[i].inputRate = ves->bindings[i].inputRate;
91 }
92 } else
93 state->element_state = NULL;
94 }
95
96 static void
97 zink_delete_vertex_elements_state(struct pipe_context *pctx,
98 void *ves)
99 {
100 }
101
102 static VkBlendFactor
103 blend_factor(enum pipe_blendfactor factor)
104 {
105 switch (factor) {
106 case PIPE_BLENDFACTOR_ONE: return VK_BLEND_FACTOR_ONE;
107 case PIPE_BLENDFACTOR_SRC_COLOR: return VK_BLEND_FACTOR_SRC_COLOR;
108 case PIPE_BLENDFACTOR_SRC_ALPHA: return VK_BLEND_FACTOR_SRC_ALPHA;
109 case PIPE_BLENDFACTOR_DST_ALPHA: return VK_BLEND_FACTOR_DST_ALPHA;
110 case PIPE_BLENDFACTOR_DST_COLOR: return VK_BLEND_FACTOR_DST_COLOR;
111 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
112 return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
113 case PIPE_BLENDFACTOR_CONST_COLOR: return VK_BLEND_FACTOR_CONSTANT_COLOR;
114 case PIPE_BLENDFACTOR_CONST_ALPHA: return VK_BLEND_FACTOR_CONSTANT_ALPHA;
115 case PIPE_BLENDFACTOR_SRC1_COLOR: return VK_BLEND_FACTOR_SRC1_COLOR;
116 case PIPE_BLENDFACTOR_SRC1_ALPHA: return VK_BLEND_FACTOR_SRC1_ALPHA;
117
118 case PIPE_BLENDFACTOR_ZERO: return VK_BLEND_FACTOR_ZERO;
119
120 case PIPE_BLENDFACTOR_INV_SRC_COLOR:
121 return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
122 case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
123 return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
124 case PIPE_BLENDFACTOR_INV_DST_ALPHA:
125 return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
126 case PIPE_BLENDFACTOR_INV_DST_COLOR:
127 return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
128
129 case PIPE_BLENDFACTOR_INV_CONST_COLOR:
130 return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
131 case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
132 return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
133 case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
134 return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
135 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
136 return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
137 }
138 unreachable("unexpected blend factor");
139 }
140
141
142 static bool
143 need_blend_constants(enum pipe_blendfactor factor)
144 {
145 switch (factor) {
146 case PIPE_BLENDFACTOR_CONST_COLOR:
147 case PIPE_BLENDFACTOR_CONST_ALPHA:
148 case PIPE_BLENDFACTOR_INV_CONST_COLOR:
149 case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
150 return true;
151
152 default:
153 return false;
154 }
155 }
156
157 static VkBlendOp
158 blend_op(enum pipe_blend_func func)
159 {
160 switch (func) {
161 case PIPE_BLEND_ADD: return VK_BLEND_OP_ADD;
162 case PIPE_BLEND_SUBTRACT: return VK_BLEND_OP_SUBTRACT;
163 case PIPE_BLEND_REVERSE_SUBTRACT: return VK_BLEND_OP_REVERSE_SUBTRACT;
164 case PIPE_BLEND_MIN: return VK_BLEND_OP_MIN;
165 case PIPE_BLEND_MAX: return VK_BLEND_OP_MAX;
166 }
167 unreachable("unexpected blend function");
168 }
169
170 static VkLogicOp
171 logic_op(enum pipe_logicop func)
172 {
173 switch (func) {
174 case PIPE_LOGICOP_CLEAR: return VK_LOGIC_OP_CLEAR;
175 case PIPE_LOGICOP_NOR: return VK_LOGIC_OP_NOR;
176 case PIPE_LOGICOP_AND_INVERTED: return VK_LOGIC_OP_AND_INVERTED;
177 case PIPE_LOGICOP_COPY_INVERTED: return VK_LOGIC_OP_COPY_INVERTED;
178 case PIPE_LOGICOP_AND_REVERSE: return VK_LOGIC_OP_AND_REVERSE;
179 case PIPE_LOGICOP_INVERT: return VK_LOGIC_OP_INVERT;
180 case PIPE_LOGICOP_XOR: return VK_LOGIC_OP_XOR;
181 case PIPE_LOGICOP_NAND: return VK_LOGIC_OP_NAND;
182 case PIPE_LOGICOP_AND: return VK_LOGIC_OP_AND;
183 case PIPE_LOGICOP_EQUIV: return VK_LOGIC_OP_EQUIVALENT;
184 case PIPE_LOGICOP_NOOP: return VK_LOGIC_OP_NO_OP;
185 case PIPE_LOGICOP_OR_INVERTED: return VK_LOGIC_OP_OR_INVERTED;
186 case PIPE_LOGICOP_COPY: return VK_LOGIC_OP_COPY;
187 case PIPE_LOGICOP_OR_REVERSE: return VK_LOGIC_OP_OR_REVERSE;
188 case PIPE_LOGICOP_OR: return VK_LOGIC_OP_OR;
189 case PIPE_LOGICOP_SET: return VK_LOGIC_OP_SET;
190 }
191 unreachable("unexpected logicop function");
192 }
193
194 static void *
195 zink_create_blend_state(struct pipe_context *pctx,
196 const struct pipe_blend_state *blend_state)
197 {
198 struct zink_blend_state *cso = CALLOC_STRUCT(zink_blend_state);
199 if (!cso)
200 return NULL;
201
202 if (blend_state->logicop_enable) {
203 cso->logicop_enable = VK_TRUE;
204 cso->logicop_func = logic_op(blend_state->logicop_func);
205 }
206
207 /* TODO: figure out what to do with dither (nothing is probably "OK" for now,
208 * as dithering is undefined in GL
209 */
210
211 /* TODO: these are multisampling-state, and should be set there instead of
212 * here, as that's closer tied to the update-frequency
213 */
214 cso->alpha_to_coverage = blend_state->alpha_to_coverage;
215 cso->alpha_to_one = blend_state->alpha_to_one;
216
217 cso->need_blend_constants = false;
218
219 for (int i = 0; i < PIPE_MAX_COLOR_BUFS; ++i) {
220 const struct pipe_rt_blend_state *rt = blend_state->rt;
221 if (blend_state->independent_blend_enable)
222 rt = blend_state->rt + i;
223
224 VkPipelineColorBlendAttachmentState att = { };
225
226 if (rt->blend_enable) {
227 att.blendEnable = VK_TRUE;
228 att.srcColorBlendFactor = blend_factor(rt->rgb_src_factor);
229 att.dstColorBlendFactor = blend_factor(rt->rgb_dst_factor);
230 att.colorBlendOp = blend_op(rt->rgb_func);
231 att.srcAlphaBlendFactor = blend_factor(rt->alpha_src_factor);
232 att.dstAlphaBlendFactor = blend_factor(rt->alpha_dst_factor);
233 att.alphaBlendOp = blend_op(rt->alpha_func);
234
235 if (need_blend_constants(rt->rgb_src_factor) ||
236 need_blend_constants(rt->rgb_dst_factor) ||
237 need_blend_constants(rt->alpha_src_factor) ||
238 need_blend_constants(rt->alpha_dst_factor))
239 cso->need_blend_constants = true;
240 }
241
242 if (rt->colormask & PIPE_MASK_R)
243 att.colorWriteMask |= VK_COLOR_COMPONENT_R_BIT;
244 if (rt->colormask & PIPE_MASK_G)
245 att.colorWriteMask |= VK_COLOR_COMPONENT_G_BIT;
246 if (rt->colormask & PIPE_MASK_B)
247 att.colorWriteMask |= VK_COLOR_COMPONENT_B_BIT;
248 if (rt->colormask & PIPE_MASK_A)
249 att.colorWriteMask |= VK_COLOR_COMPONENT_A_BIT;
250
251 cso->attachments[i] = att;
252 }
253
254 return cso;
255 }
256
257 static void
258 zink_bind_blend_state(struct pipe_context *pctx, void *cso)
259 {
260 struct zink_gfx_pipeline_state* state = &zink_context(pctx)->gfx_pipeline_state;
261
262 if (state->blend_state != cso) {
263 state->blend_state = cso;
264 state->hash = 0;
265 }
266 }
267
268 static void
269 zink_delete_blend_state(struct pipe_context *pctx, void *blend_state)
270 {
271 FREE(blend_state);
272 }
273
274 static VkCompareOp
275 compare_op(enum pipe_compare_func func)
276 {
277 switch (func) {
278 case PIPE_FUNC_NEVER: return VK_COMPARE_OP_NEVER;
279 case PIPE_FUNC_LESS: return VK_COMPARE_OP_LESS;
280 case PIPE_FUNC_EQUAL: return VK_COMPARE_OP_EQUAL;
281 case PIPE_FUNC_LEQUAL: return VK_COMPARE_OP_LESS_OR_EQUAL;
282 case PIPE_FUNC_GREATER: return VK_COMPARE_OP_GREATER;
283 case PIPE_FUNC_NOTEQUAL: return VK_COMPARE_OP_NOT_EQUAL;
284 case PIPE_FUNC_GEQUAL: return VK_COMPARE_OP_GREATER_OR_EQUAL;
285 case PIPE_FUNC_ALWAYS: return VK_COMPARE_OP_ALWAYS;
286 }
287 unreachable("unexpected func");
288 }
289
290 static VkStencilOp
291 stencil_op(enum pipe_stencil_op op)
292 {
293 switch (op) {
294 case PIPE_STENCIL_OP_KEEP: return VK_STENCIL_OP_KEEP;
295 case PIPE_STENCIL_OP_ZERO: return VK_STENCIL_OP_ZERO;
296 case PIPE_STENCIL_OP_REPLACE: return VK_STENCIL_OP_REPLACE;
297 case PIPE_STENCIL_OP_INCR: return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
298 case PIPE_STENCIL_OP_DECR: return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
299 case PIPE_STENCIL_OP_INCR_WRAP: return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
300 case PIPE_STENCIL_OP_DECR_WRAP: return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
301 case PIPE_STENCIL_OP_INVERT: return VK_STENCIL_OP_INVERT;
302 }
303 unreachable("unexpected op");
304 }
305
306 static VkStencilOpState
307 stencil_op_state(const struct pipe_stencil_state *src)
308 {
309 VkStencilOpState ret;
310 ret.failOp = stencil_op(src->fail_op);
311 ret.passOp = stencil_op(src->zpass_op);
312 ret.depthFailOp = stencil_op(src->zfail_op);
313 ret.compareOp = compare_op(src->func);
314 ret.compareMask = src->valuemask;
315 ret.writeMask = src->writemask;
316 ret.reference = 0; // not used: we'll use a dynamic state for this
317 return ret;
318 }
319
320 static void *
321 zink_create_depth_stencil_alpha_state(struct pipe_context *pctx,
322 const struct pipe_depth_stencil_alpha_state *depth_stencil_alpha)
323 {
324 struct zink_depth_stencil_alpha_state *cso = CALLOC_STRUCT(zink_depth_stencil_alpha_state);
325 if (!cso)
326 return NULL;
327
328 if (depth_stencil_alpha->depth.enabled) {
329 cso->depth_test = VK_TRUE;
330 cso->depth_compare_op = compare_op(depth_stencil_alpha->depth.func);
331 }
332
333 if (depth_stencil_alpha->depth.bounds_test) {
334 cso->depth_bounds_test = VK_TRUE;
335 cso->min_depth_bounds = depth_stencil_alpha->depth.bounds_min;
336 cso->max_depth_bounds = depth_stencil_alpha->depth.bounds_max;
337 }
338
339 if (depth_stencil_alpha->stencil[0].enabled) {
340 cso->stencil_test = VK_TRUE;
341 cso->stencil_front = stencil_op_state(depth_stencil_alpha->stencil);
342 }
343
344 if (depth_stencil_alpha->stencil[0].enabled)
345 cso->stencil_back = stencil_op_state(depth_stencil_alpha->stencil + 1);
346 else
347 cso->stencil_back = cso->stencil_front;
348
349 cso->depth_write = depth_stencil_alpha->depth.writemask;
350
351 return cso;
352 }
353
354 static void
355 zink_bind_depth_stencil_alpha_state(struct pipe_context *pctx, void *cso)
356 {
357 struct zink_gfx_pipeline_state* state = &zink_context(pctx)->gfx_pipeline_state;
358
359 if (state->depth_stencil_alpha_state != cso) {
360 state->depth_stencil_alpha_state = cso;
361 state->hash = 0;
362 }
363 }
364
365 static void
366 zink_delete_depth_stencil_alpha_state(struct pipe_context *pctx,
367 void *depth_stencil_alpha)
368 {
369 FREE(depth_stencil_alpha);
370 }
371
372 static float
373 round_to_granularity(float value, float granularity)
374 {
375 return roundf(value / granularity) * granularity;
376 }
377
378 static float
379 line_width(float width, float granularity, const float range[2])
380 {
381 assert(granularity >= 0);
382 assert(range[0] <= range[1]);
383
384 if (granularity > 0)
385 width = round_to_granularity(width, granularity);
386
387 return CLAMP(width, range[0], range[1]);
388 }
389
390 static void *
391 zink_create_rasterizer_state(struct pipe_context *pctx,
392 const struct pipe_rasterizer_state *rs_state)
393 {
394 struct zink_screen *screen = zink_screen(pctx->screen);
395
396 struct zink_rasterizer_state *state = CALLOC_STRUCT(zink_rasterizer_state);
397 if (!state)
398 return NULL;
399
400 state->base = *rs_state;
401
402 assert(rs_state->depth_clip_far == rs_state->depth_clip_near);
403 state->hw_state.depth_clamp = rs_state->depth_clip_near == 0;
404 state->hw_state.rasterizer_discard = rs_state->rasterizer_discard;
405
406 assert(rs_state->fill_front <= PIPE_POLYGON_MODE_POINT);
407 if (rs_state->fill_back != rs_state->fill_front)
408 debug_printf("BUG: vulkan doesn't support different front and back fill modes\n");
409 state->hw_state.polygon_mode = (VkPolygonMode)rs_state->fill_front; // same values
410 state->hw_state.cull_mode = (VkCullModeFlags)rs_state->cull_face; // same bits
411
412 state->hw_state.front_face = rs_state->front_ccw ?
413 VK_FRONT_FACE_COUNTER_CLOCKWISE :
414 VK_FRONT_FACE_CLOCKWISE;
415
416 state->offset_point = rs_state->offset_point;
417 state->offset_line = rs_state->offset_line;
418 state->offset_tri = rs_state->offset_tri;
419 state->offset_units = rs_state->offset_units;
420 state->offset_clamp = rs_state->offset_clamp;
421 state->offset_scale = rs_state->offset_scale;
422
423 state->line_width = line_width(rs_state->line_width,
424 screen->props.limits.lineWidthGranularity,
425 screen->props.limits.lineWidthRange);
426
427 return state;
428 }
429
430 static void
431 zink_bind_rasterizer_state(struct pipe_context *pctx, void *cso)
432 {
433 struct zink_context *ctx = zink_context(pctx);
434 ctx->rast_state = cso;
435
436 if (ctx->rast_state) {
437 if (ctx->gfx_pipeline_state.rast_state != &ctx->rast_state->hw_state) {
438 ctx->gfx_pipeline_state.rast_state = &ctx->rast_state->hw_state;
439 ctx->gfx_pipeline_state.hash = 0;
440 }
441
442 if (ctx->line_width != ctx->rast_state->line_width) {
443 ctx->line_width = ctx->rast_state->line_width;
444 ctx->gfx_pipeline_state.hash = 0;
445 }
446 }
447 }
448
449 static void
450 zink_delete_rasterizer_state(struct pipe_context *pctx, void *rs_state)
451 {
452 FREE(rs_state);
453 }
454
455 void
456 zink_context_state_init(struct pipe_context *pctx)
457 {
458 pctx->create_vertex_elements_state = zink_create_vertex_elements_state;
459 pctx->bind_vertex_elements_state = zink_bind_vertex_elements_state;
460 pctx->delete_vertex_elements_state = zink_delete_vertex_elements_state;
461
462 pctx->create_blend_state = zink_create_blend_state;
463 pctx->bind_blend_state = zink_bind_blend_state;
464 pctx->delete_blend_state = zink_delete_blend_state;
465
466 pctx->create_depth_stencil_alpha_state = zink_create_depth_stencil_alpha_state;
467 pctx->bind_depth_stencil_alpha_state = zink_bind_depth_stencil_alpha_state;
468 pctx->delete_depth_stencil_alpha_state = zink_delete_depth_stencil_alpha_state;
469
470 pctx->create_rasterizer_state = zink_create_rasterizer_state;
471 pctx->bind_rasterizer_state = zink_bind_rasterizer_state;
472 pctx->delete_rasterizer_state = zink_delete_rasterizer_state;
473 }