2 * Copyright 2018 Collabora Ltd.
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:
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
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.
24 #include "zink_state.h"
26 #include "zink_context.h"
27 #include "zink_screen.h"
29 #include "util/u_memory.h"
34 zink_create_vertex_elements_state(struct pipe_context
*pctx
,
35 unsigned num_elements
,
36 const struct pipe_vertex_element
*elements
)
39 struct zink_vertex_elements_state
*ves
= CALLOC_STRUCT(zink_vertex_elements_state
);
43 int buffer_map
[PIPE_MAX_ATTRIBS
];
44 for (int i
= 0; i
< ARRAY_SIZE(buffer_map
); ++i
)
48 for (i
= 0; i
< num_elements
; ++i
) {
49 const struct pipe_vertex_element
*elem
= elements
+ i
;
50 assert(!elem
->instance_divisor
);
52 int binding
= elem
->vertex_buffer_index
;
53 if (buffer_map
[binding
] < 0) {
54 ves
->binding_map
[num_bindings
] = binding
;
55 buffer_map
[binding
] = num_bindings
++;
57 binding
= buffer_map
[binding
];
60 ves
->bindings
[binding
].binding
= binding
;
61 ves
->bindings
[binding
].inputRate
= VK_VERTEX_INPUT_RATE_VERTEX
;
63 ves
->hw_state
.attribs
[i
].binding
= binding
;
64 ves
->hw_state
.attribs
[i
].location
= i
; // TODO: unsure
65 ves
->hw_state
.attribs
[i
].format
= zink_get_format(elem
->src_format
);
66 assert(ves
->hw_state
.attribs
[i
].format
!= VK_FORMAT_UNDEFINED
);
67 ves
->hw_state
.attribs
[i
].offset
= elem
->src_offset
;
70 ves
->hw_state
.num_bindings
= num_bindings
;
71 ves
->hw_state
.num_attribs
= num_elements
;
76 zink_bind_vertex_elements_state(struct pipe_context
*pctx
,
79 struct zink_context
*ctx
= zink_context(pctx
);
80 struct zink_gfx_pipeline_state
*state
= &ctx
->gfx_pipeline_state
;
81 ctx
->element_state
= cso
;
83 state
->element_state
= &ctx
->element_state
->hw_state
;
84 struct zink_vertex_elements_state
*ves
= cso
;
85 for (int i
= 0; i
< state
->element_state
->num_bindings
; ++i
) {
86 state
->bindings
[i
].binding
= ves
->bindings
[i
].binding
;
87 state
->bindings
[i
].inputRate
= ves
->bindings
[i
].inputRate
;
90 state
->element_state
= NULL
;
94 zink_delete_vertex_elements_state(struct pipe_context
*pctx
,
100 blend_factor(enum pipe_blendfactor factor
)
103 case PIPE_BLENDFACTOR_ONE
: return VK_BLEND_FACTOR_ONE
;
104 case PIPE_BLENDFACTOR_SRC_COLOR
: return VK_BLEND_FACTOR_SRC_COLOR
;
105 case PIPE_BLENDFACTOR_SRC_ALPHA
: return VK_BLEND_FACTOR_SRC_ALPHA
;
106 case PIPE_BLENDFACTOR_DST_ALPHA
: return VK_BLEND_FACTOR_DST_ALPHA
;
107 case PIPE_BLENDFACTOR_DST_COLOR
: return VK_BLEND_FACTOR_DST_COLOR
;
108 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
:
109 return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE
;
110 case PIPE_BLENDFACTOR_CONST_COLOR
: return VK_BLEND_FACTOR_CONSTANT_COLOR
;
111 case PIPE_BLENDFACTOR_CONST_ALPHA
: return VK_BLEND_FACTOR_CONSTANT_ALPHA
;
112 case PIPE_BLENDFACTOR_SRC1_COLOR
: return VK_BLEND_FACTOR_SRC1_COLOR
;
113 case PIPE_BLENDFACTOR_SRC1_ALPHA
: return VK_BLEND_FACTOR_SRC1_ALPHA
;
115 case PIPE_BLENDFACTOR_ZERO
: return VK_BLEND_FACTOR_ZERO
;
117 case PIPE_BLENDFACTOR_INV_SRC_COLOR
:
118 return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR
;
119 case PIPE_BLENDFACTOR_INV_SRC_ALPHA
:
120 return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA
;
121 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
122 return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA
;
123 case PIPE_BLENDFACTOR_INV_DST_COLOR
:
124 return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR
;
126 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
127 return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR
;
128 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
129 return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA
;
130 case PIPE_BLENDFACTOR_INV_SRC1_COLOR
:
131 return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR
;
132 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA
:
133 return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA
;
135 unreachable("unexpected blend factor");
140 need_blend_constants(enum pipe_blendfactor factor
)
143 case PIPE_BLENDFACTOR_CONST_COLOR
:
144 case PIPE_BLENDFACTOR_CONST_ALPHA
:
145 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
146 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
155 blend_op(enum pipe_blend_func func
)
158 case PIPE_BLEND_ADD
: return VK_BLEND_OP_ADD
;
159 case PIPE_BLEND_SUBTRACT
: return VK_BLEND_OP_SUBTRACT
;
160 case PIPE_BLEND_REVERSE_SUBTRACT
: return VK_BLEND_OP_REVERSE_SUBTRACT
;
161 case PIPE_BLEND_MIN
: return VK_BLEND_OP_MIN
;
162 case PIPE_BLEND_MAX
: return VK_BLEND_OP_MAX
;
164 unreachable("unexpected blend function");
168 logic_op(enum pipe_logicop func
)
171 case PIPE_LOGICOP_CLEAR
: return VK_LOGIC_OP_CLEAR
;
172 case PIPE_LOGICOP_NOR
: return VK_LOGIC_OP_NOR
;
173 case PIPE_LOGICOP_AND_INVERTED
: return VK_LOGIC_OP_AND_INVERTED
;
174 case PIPE_LOGICOP_COPY_INVERTED
: return VK_LOGIC_OP_COPY_INVERTED
;
175 case PIPE_LOGICOP_AND_REVERSE
: return VK_LOGIC_OP_AND_REVERSE
;
176 case PIPE_LOGICOP_INVERT
: return VK_LOGIC_OP_INVERT
;
177 case PIPE_LOGICOP_XOR
: return VK_LOGIC_OP_XOR
;
178 case PIPE_LOGICOP_NAND
: return VK_LOGIC_OP_NAND
;
179 case PIPE_LOGICOP_AND
: return VK_LOGIC_OP_AND
;
180 case PIPE_LOGICOP_EQUIV
: return VK_LOGIC_OP_EQUIVALENT
;
181 case PIPE_LOGICOP_NOOP
: return VK_LOGIC_OP_NO_OP
;
182 case PIPE_LOGICOP_OR_INVERTED
: return VK_LOGIC_OP_OR_INVERTED
;
183 case PIPE_LOGICOP_COPY
: return VK_LOGIC_OP_COPY
;
184 case PIPE_LOGICOP_OR_REVERSE
: return VK_LOGIC_OP_OR_REVERSE
;
185 case PIPE_LOGICOP_OR
: return VK_LOGIC_OP_OR
;
186 case PIPE_LOGICOP_SET
: return VK_LOGIC_OP_SET
;
188 unreachable("unexpected logicop function");
192 zink_create_blend_state(struct pipe_context
*pctx
,
193 const struct pipe_blend_state
*blend_state
)
195 struct zink_blend_state
*cso
= CALLOC_STRUCT(zink_blend_state
);
199 if (blend_state
->logicop_enable
) {
200 cso
->logicop_enable
= VK_TRUE
;
201 cso
->logicop_func
= logic_op(blend_state
->logicop_func
);
204 /* TODO: figure out what to do with dither (nothing is probably "OK" for now,
205 * as dithering is undefined in GL
208 /* TODO: these are multisampling-state, and should be set there instead of
209 * here, as that's closer tied to the update-frequency
211 cso
->alpha_to_coverage
= blend_state
->alpha_to_coverage
;
212 cso
->alpha_to_one
= blend_state
->alpha_to_one
;
214 cso
->need_blend_constants
= false;
216 for (int i
= 0; i
< PIPE_MAX_COLOR_BUFS
; ++i
) {
217 const struct pipe_rt_blend_state
*rt
= blend_state
->rt
;
218 if (blend_state
->independent_blend_enable
)
219 rt
= blend_state
->rt
+ i
;
221 VkPipelineColorBlendAttachmentState att
= { };
223 if (rt
->blend_enable
) {
224 att
.blendEnable
= VK_TRUE
;
225 att
.srcColorBlendFactor
= blend_factor(rt
->rgb_src_factor
);
226 att
.dstColorBlendFactor
= blend_factor(rt
->rgb_dst_factor
);
227 att
.colorBlendOp
= blend_op(rt
->rgb_func
);
228 att
.srcAlphaBlendFactor
= blend_factor(rt
->alpha_src_factor
);
229 att
.dstAlphaBlendFactor
= blend_factor(rt
->alpha_dst_factor
);
230 att
.alphaBlendOp
= blend_op(rt
->alpha_func
);
232 if (need_blend_constants(rt
->rgb_src_factor
) ||
233 need_blend_constants(rt
->rgb_dst_factor
) ||
234 need_blend_constants(rt
->alpha_src_factor
) ||
235 need_blend_constants(rt
->alpha_dst_factor
))
236 cso
->need_blend_constants
= true;
239 if (rt
->colormask
& PIPE_MASK_R
)
240 att
.colorWriteMask
|= VK_COLOR_COMPONENT_R_BIT
;
241 if (rt
->colormask
& PIPE_MASK_G
)
242 att
.colorWriteMask
|= VK_COLOR_COMPONENT_G_BIT
;
243 if (rt
->colormask
& PIPE_MASK_B
)
244 att
.colorWriteMask
|= VK_COLOR_COMPONENT_B_BIT
;
245 if (rt
->colormask
& PIPE_MASK_A
)
246 att
.colorWriteMask
|= VK_COLOR_COMPONENT_A_BIT
;
248 cso
->attachments
[i
] = att
;
255 zink_bind_blend_state(struct pipe_context
*pctx
, void *cso
)
257 zink_context(pctx
)->gfx_pipeline_state
.blend_state
= cso
;
261 zink_delete_blend_state(struct pipe_context
*pctx
, void *blend_state
)
267 compare_op(enum pipe_compare_func func
)
270 case PIPE_FUNC_NEVER
: return VK_COMPARE_OP_NEVER
;
271 case PIPE_FUNC_LESS
: return VK_COMPARE_OP_LESS
;
272 case PIPE_FUNC_EQUAL
: return VK_COMPARE_OP_EQUAL
;
273 case PIPE_FUNC_LEQUAL
: return VK_COMPARE_OP_LESS_OR_EQUAL
;
274 case PIPE_FUNC_GREATER
: return VK_COMPARE_OP_GREATER
;
275 case PIPE_FUNC_NOTEQUAL
: return VK_COMPARE_OP_NOT_EQUAL
;
276 case PIPE_FUNC_GEQUAL
: return VK_COMPARE_OP_GREATER_OR_EQUAL
;
277 case PIPE_FUNC_ALWAYS
: return VK_COMPARE_OP_ALWAYS
;
279 unreachable("unexpected func");
283 stencil_op(enum pipe_stencil_op op
)
286 case PIPE_STENCIL_OP_KEEP
: return VK_STENCIL_OP_KEEP
;
287 case PIPE_STENCIL_OP_ZERO
: return VK_STENCIL_OP_ZERO
;
288 case PIPE_STENCIL_OP_REPLACE
: return VK_STENCIL_OP_REPLACE
;
289 case PIPE_STENCIL_OP_INCR
: return VK_STENCIL_OP_INCREMENT_AND_CLAMP
;
290 case PIPE_STENCIL_OP_DECR
: return VK_STENCIL_OP_DECREMENT_AND_CLAMP
;
291 case PIPE_STENCIL_OP_INCR_WRAP
: return VK_STENCIL_OP_INCREMENT_AND_CLAMP
;
292 case PIPE_STENCIL_OP_DECR_WRAP
: return VK_STENCIL_OP_DECREMENT_AND_CLAMP
;
293 case PIPE_STENCIL_OP_INVERT
: return VK_STENCIL_OP_INVERT
;
295 unreachable("unexpected op");
298 static VkStencilOpState
299 stencil_op_state(const struct pipe_stencil_state
*src
)
301 VkStencilOpState ret
;
302 ret
.failOp
= stencil_op(src
->fail_op
);
303 ret
.passOp
= stencil_op(src
->zpass_op
);
304 ret
.depthFailOp
= stencil_op(src
->zfail_op
);
305 ret
.compareOp
= compare_op(src
->func
);
306 ret
.compareMask
= src
->valuemask
;
307 ret
.writeMask
= src
->writemask
;
308 ret
.reference
= 0; // not used: we'll use a dynamic state for this
313 zink_create_depth_stencil_alpha_state(struct pipe_context
*pctx
,
314 const struct pipe_depth_stencil_alpha_state
*depth_stencil_alpha
)
316 struct zink_depth_stencil_alpha_state
*cso
= CALLOC_STRUCT(zink_depth_stencil_alpha_state
);
320 if (depth_stencil_alpha
->depth
.enabled
) {
321 cso
->depth_test
= VK_TRUE
;
322 cso
->depth_compare_op
= compare_op(depth_stencil_alpha
->depth
.func
);
325 if (depth_stencil_alpha
->depth
.bounds_test
) {
326 cso
->depth_bounds_test
= VK_TRUE
;
327 cso
->min_depth_bounds
= depth_stencil_alpha
->depth
.bounds_min
;
328 cso
->max_depth_bounds
= depth_stencil_alpha
->depth
.bounds_max
;
331 if (depth_stencil_alpha
->stencil
[0].enabled
) {
332 cso
->stencil_test
= VK_TRUE
;
333 cso
->stencil_front
= stencil_op_state(depth_stencil_alpha
->stencil
);
336 if (depth_stencil_alpha
->stencil
[0].enabled
)
337 cso
->stencil_back
= stencil_op_state(depth_stencil_alpha
->stencil
+ 1);
339 cso
->stencil_back
= cso
->stencil_front
;
341 cso
->depth_write
= depth_stencil_alpha
->depth
.writemask
;
347 zink_bind_depth_stencil_alpha_state(struct pipe_context
*pctx
, void *cso
)
349 zink_context(pctx
)->gfx_pipeline_state
.depth_stencil_alpha_state
= cso
;
353 zink_delete_depth_stencil_alpha_state(struct pipe_context
*pctx
,
354 void *depth_stencil_alpha
)
356 FREE(depth_stencil_alpha
);
360 round_to_granularity(float value
, float granularity
)
362 return (float)(round(value
/ granularity
) * granularity
);
366 zink_create_rasterizer_state(struct pipe_context
*pctx
,
367 const struct pipe_rasterizer_state
*rs_state
)
369 struct zink_screen
*screen
= zink_screen(pctx
->screen
);
371 struct zink_rasterizer_state
*state
= CALLOC_STRUCT(zink_rasterizer_state
);
375 state
->base
= *rs_state
;
377 assert(rs_state
->depth_clip_far
== rs_state
->depth_clip_near
);
378 state
->hw_state
.depth_clamp
= rs_state
->depth_clip_near
== 0;
379 state
->hw_state
.rasterizer_discard
= rs_state
->rasterizer_discard
;
381 assert(rs_state
->fill_front
<= PIPE_POLYGON_MODE_POINT
);
382 if (rs_state
->fill_back
!= rs_state
->fill_front
)
383 debug_printf("BUG: vulkan doesn't support different front and back fill modes\n");
384 state
->hw_state
.polygon_mode
= (VkPolygonMode
)rs_state
->fill_front
; // same values
385 state
->hw_state
.cull_mode
= (VkCullModeFlags
)rs_state
->cull_face
; // same bits
387 state
->hw_state
.front_face
= rs_state
->front_ccw
?
388 VK_FRONT_FACE_COUNTER_CLOCKWISE
:
389 VK_FRONT_FACE_CLOCKWISE
;
391 state
->offset_point
= rs_state
->offset_point
;
392 state
->offset_line
= rs_state
->offset_line
;
393 state
->offset_tri
= rs_state
->offset_tri
;
394 state
->offset_units
= rs_state
->offset_units
;
395 state
->offset_clamp
= rs_state
->offset_clamp
;
396 state
->offset_scale
= rs_state
->offset_scale
;
398 state
->line_width
= round_to_granularity(rs_state
->line_width
,
399 screen
->props
.limits
.lineWidthGranularity
);
405 zink_bind_rasterizer_state(struct pipe_context
*pctx
, void *cso
)
407 struct zink_context
*ctx
= zink_context(pctx
);
408 ctx
->rast_state
= cso
;
409 ctx
->gfx_pipeline_state
.rast_state
= &ctx
->rast_state
->hw_state
;
413 zink_delete_rasterizer_state(struct pipe_context
*pctx
, void *rs_state
)
419 zink_context_state_init(struct pipe_context
*pctx
)
421 pctx
->create_vertex_elements_state
= zink_create_vertex_elements_state
;
422 pctx
->bind_vertex_elements_state
= zink_bind_vertex_elements_state
;
423 pctx
->delete_vertex_elements_state
= zink_delete_vertex_elements_state
;
425 pctx
->create_blend_state
= zink_create_blend_state
;
426 pctx
->bind_blend_state
= zink_bind_blend_state
;
427 pctx
->delete_blend_state
= zink_delete_blend_state
;
429 pctx
->create_depth_stencil_alpha_state
= zink_create_depth_stencil_alpha_state
;
430 pctx
->bind_depth_stencil_alpha_state
= zink_bind_depth_stencil_alpha_state
;
431 pctx
->delete_depth_stencil_alpha_state
= zink_delete_depth_stencil_alpha_state
;
433 pctx
->create_rasterizer_state
= zink_create_rasterizer_state
;
434 pctx
->bind_rasterizer_state
= zink_bind_rasterizer_state
;
435 pctx
->delete_rasterizer_state
= zink_delete_rasterizer_state
;