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
)
38 struct zink_screen
*screen
= zink_screen(pctx
->screen
);
40 struct zink_vertex_elements_state
*ves
= CALLOC_STRUCT(zink_vertex_elements_state
);
44 int buffer_map
[PIPE_MAX_ATTRIBS
];
45 for (int i
= 0; i
< ARRAY_SIZE(buffer_map
); ++i
)
49 for (i
= 0; i
< num_elements
; ++i
) {
50 const struct pipe_vertex_element
*elem
= elements
+ i
;
51 assert(!elem
->instance_divisor
);
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
++;
58 binding
= buffer_map
[binding
];
61 ves
->bindings
[binding
].binding
= binding
;
62 ves
->bindings
[binding
].inputRate
= VK_VERTEX_INPUT_RATE_VERTEX
;
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
,
68 assert(ves
->hw_state
.attribs
[i
].format
!= VK_FORMAT_UNDEFINED
);
69 ves
->hw_state
.attribs
[i
].offset
= elem
->src_offset
;
72 ves
->hw_state
.num_bindings
= num_bindings
;
73 ves
->hw_state
.num_attribs
= num_elements
;
78 zink_bind_vertex_elements_state(struct pipe_context
*pctx
,
81 struct zink_context
*ctx
= zink_context(pctx
);
82 struct zink_gfx_pipeline_state
*state
= &ctx
->gfx_pipeline_state
;
83 ctx
->element_state
= cso
;
85 state
->element_state
= &ctx
->element_state
->hw_state
;
86 struct zink_vertex_elements_state
*ves
= cso
;
87 for (int i
= 0; i
< state
->element_state
->num_bindings
; ++i
) {
88 state
->bindings
[i
].binding
= ves
->bindings
[i
].binding
;
89 state
->bindings
[i
].inputRate
= ves
->bindings
[i
].inputRate
;
92 state
->element_state
= NULL
;
96 zink_delete_vertex_elements_state(struct pipe_context
*pctx
,
102 blend_factor(enum pipe_blendfactor factor
)
105 case PIPE_BLENDFACTOR_ONE
: return VK_BLEND_FACTOR_ONE
;
106 case PIPE_BLENDFACTOR_SRC_COLOR
: return VK_BLEND_FACTOR_SRC_COLOR
;
107 case PIPE_BLENDFACTOR_SRC_ALPHA
: return VK_BLEND_FACTOR_SRC_ALPHA
;
108 case PIPE_BLENDFACTOR_DST_ALPHA
: return VK_BLEND_FACTOR_DST_ALPHA
;
109 case PIPE_BLENDFACTOR_DST_COLOR
: return VK_BLEND_FACTOR_DST_COLOR
;
110 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
:
111 return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE
;
112 case PIPE_BLENDFACTOR_CONST_COLOR
: return VK_BLEND_FACTOR_CONSTANT_COLOR
;
113 case PIPE_BLENDFACTOR_CONST_ALPHA
: return VK_BLEND_FACTOR_CONSTANT_ALPHA
;
114 case PIPE_BLENDFACTOR_SRC1_COLOR
: return VK_BLEND_FACTOR_SRC1_COLOR
;
115 case PIPE_BLENDFACTOR_SRC1_ALPHA
: return VK_BLEND_FACTOR_SRC1_ALPHA
;
117 case PIPE_BLENDFACTOR_ZERO
: return VK_BLEND_FACTOR_ZERO
;
119 case PIPE_BLENDFACTOR_INV_SRC_COLOR
:
120 return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR
;
121 case PIPE_BLENDFACTOR_INV_SRC_ALPHA
:
122 return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA
;
123 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
124 return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA
;
125 case PIPE_BLENDFACTOR_INV_DST_COLOR
:
126 return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR
;
128 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
129 return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR
;
130 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
131 return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA
;
132 case PIPE_BLENDFACTOR_INV_SRC1_COLOR
:
133 return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR
;
134 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA
:
135 return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA
;
137 unreachable("unexpected blend factor");
142 need_blend_constants(enum pipe_blendfactor factor
)
145 case PIPE_BLENDFACTOR_CONST_COLOR
:
146 case PIPE_BLENDFACTOR_CONST_ALPHA
:
147 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
148 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
157 blend_op(enum pipe_blend_func func
)
160 case PIPE_BLEND_ADD
: return VK_BLEND_OP_ADD
;
161 case PIPE_BLEND_SUBTRACT
: return VK_BLEND_OP_SUBTRACT
;
162 case PIPE_BLEND_REVERSE_SUBTRACT
: return VK_BLEND_OP_REVERSE_SUBTRACT
;
163 case PIPE_BLEND_MIN
: return VK_BLEND_OP_MIN
;
164 case PIPE_BLEND_MAX
: return VK_BLEND_OP_MAX
;
166 unreachable("unexpected blend function");
170 logic_op(enum pipe_logicop func
)
173 case PIPE_LOGICOP_CLEAR
: return VK_LOGIC_OP_CLEAR
;
174 case PIPE_LOGICOP_NOR
: return VK_LOGIC_OP_NOR
;
175 case PIPE_LOGICOP_AND_INVERTED
: return VK_LOGIC_OP_AND_INVERTED
;
176 case PIPE_LOGICOP_COPY_INVERTED
: return VK_LOGIC_OP_COPY_INVERTED
;
177 case PIPE_LOGICOP_AND_REVERSE
: return VK_LOGIC_OP_AND_REVERSE
;
178 case PIPE_LOGICOP_INVERT
: return VK_LOGIC_OP_INVERT
;
179 case PIPE_LOGICOP_XOR
: return VK_LOGIC_OP_XOR
;
180 case PIPE_LOGICOP_NAND
: return VK_LOGIC_OP_NAND
;
181 case PIPE_LOGICOP_AND
: return VK_LOGIC_OP_AND
;
182 case PIPE_LOGICOP_EQUIV
: return VK_LOGIC_OP_EQUIVALENT
;
183 case PIPE_LOGICOP_NOOP
: return VK_LOGIC_OP_NO_OP
;
184 case PIPE_LOGICOP_OR_INVERTED
: return VK_LOGIC_OP_OR_INVERTED
;
185 case PIPE_LOGICOP_COPY
: return VK_LOGIC_OP_COPY
;
186 case PIPE_LOGICOP_OR_REVERSE
: return VK_LOGIC_OP_OR_REVERSE
;
187 case PIPE_LOGICOP_OR
: return VK_LOGIC_OP_OR
;
188 case PIPE_LOGICOP_SET
: return VK_LOGIC_OP_SET
;
190 unreachable("unexpected logicop function");
194 zink_create_blend_state(struct pipe_context
*pctx
,
195 const struct pipe_blend_state
*blend_state
)
197 struct zink_blend_state
*cso
= CALLOC_STRUCT(zink_blend_state
);
201 if (blend_state
->logicop_enable
) {
202 cso
->logicop_enable
= VK_TRUE
;
203 cso
->logicop_func
= logic_op(blend_state
->logicop_func
);
206 /* TODO: figure out what to do with dither (nothing is probably "OK" for now,
207 * as dithering is undefined in GL
210 /* TODO: these are multisampling-state, and should be set there instead of
211 * here, as that's closer tied to the update-frequency
213 cso
->alpha_to_coverage
= blend_state
->alpha_to_coverage
;
214 cso
->alpha_to_one
= blend_state
->alpha_to_one
;
216 cso
->need_blend_constants
= false;
218 for (int i
= 0; i
< PIPE_MAX_COLOR_BUFS
; ++i
) {
219 const struct pipe_rt_blend_state
*rt
= blend_state
->rt
;
220 if (blend_state
->independent_blend_enable
)
221 rt
= blend_state
->rt
+ i
;
223 VkPipelineColorBlendAttachmentState att
= { };
225 if (rt
->blend_enable
) {
226 att
.blendEnable
= VK_TRUE
;
227 att
.srcColorBlendFactor
= blend_factor(rt
->rgb_src_factor
);
228 att
.dstColorBlendFactor
= blend_factor(rt
->rgb_dst_factor
);
229 att
.colorBlendOp
= blend_op(rt
->rgb_func
);
230 att
.srcAlphaBlendFactor
= blend_factor(rt
->alpha_src_factor
);
231 att
.dstAlphaBlendFactor
= blend_factor(rt
->alpha_dst_factor
);
232 att
.alphaBlendOp
= blend_op(rt
->alpha_func
);
234 if (need_blend_constants(rt
->rgb_src_factor
) ||
235 need_blend_constants(rt
->rgb_dst_factor
) ||
236 need_blend_constants(rt
->alpha_src_factor
) ||
237 need_blend_constants(rt
->alpha_dst_factor
))
238 cso
->need_blend_constants
= true;
241 if (rt
->colormask
& PIPE_MASK_R
)
242 att
.colorWriteMask
|= VK_COLOR_COMPONENT_R_BIT
;
243 if (rt
->colormask
& PIPE_MASK_G
)
244 att
.colorWriteMask
|= VK_COLOR_COMPONENT_G_BIT
;
245 if (rt
->colormask
& PIPE_MASK_B
)
246 att
.colorWriteMask
|= VK_COLOR_COMPONENT_B_BIT
;
247 if (rt
->colormask
& PIPE_MASK_A
)
248 att
.colorWriteMask
|= VK_COLOR_COMPONENT_A_BIT
;
250 cso
->attachments
[i
] = att
;
257 zink_bind_blend_state(struct pipe_context
*pctx
, void *cso
)
259 zink_context(pctx
)->gfx_pipeline_state
.blend_state
= cso
;
263 zink_delete_blend_state(struct pipe_context
*pctx
, void *blend_state
)
269 compare_op(enum pipe_compare_func func
)
272 case PIPE_FUNC_NEVER
: return VK_COMPARE_OP_NEVER
;
273 case PIPE_FUNC_LESS
: return VK_COMPARE_OP_LESS
;
274 case PIPE_FUNC_EQUAL
: return VK_COMPARE_OP_EQUAL
;
275 case PIPE_FUNC_LEQUAL
: return VK_COMPARE_OP_LESS_OR_EQUAL
;
276 case PIPE_FUNC_GREATER
: return VK_COMPARE_OP_GREATER
;
277 case PIPE_FUNC_NOTEQUAL
: return VK_COMPARE_OP_NOT_EQUAL
;
278 case PIPE_FUNC_GEQUAL
: return VK_COMPARE_OP_GREATER_OR_EQUAL
;
279 case PIPE_FUNC_ALWAYS
: return VK_COMPARE_OP_ALWAYS
;
281 unreachable("unexpected func");
285 stencil_op(enum pipe_stencil_op op
)
288 case PIPE_STENCIL_OP_KEEP
: return VK_STENCIL_OP_KEEP
;
289 case PIPE_STENCIL_OP_ZERO
: return VK_STENCIL_OP_ZERO
;
290 case PIPE_STENCIL_OP_REPLACE
: return VK_STENCIL_OP_REPLACE
;
291 case PIPE_STENCIL_OP_INCR
: return VK_STENCIL_OP_INCREMENT_AND_CLAMP
;
292 case PIPE_STENCIL_OP_DECR
: return VK_STENCIL_OP_DECREMENT_AND_CLAMP
;
293 case PIPE_STENCIL_OP_INCR_WRAP
: return VK_STENCIL_OP_INCREMENT_AND_CLAMP
;
294 case PIPE_STENCIL_OP_DECR_WRAP
: return VK_STENCIL_OP_DECREMENT_AND_CLAMP
;
295 case PIPE_STENCIL_OP_INVERT
: return VK_STENCIL_OP_INVERT
;
297 unreachable("unexpected op");
300 static VkStencilOpState
301 stencil_op_state(const struct pipe_stencil_state
*src
)
303 VkStencilOpState ret
;
304 ret
.failOp
= stencil_op(src
->fail_op
);
305 ret
.passOp
= stencil_op(src
->zpass_op
);
306 ret
.depthFailOp
= stencil_op(src
->zfail_op
);
307 ret
.compareOp
= compare_op(src
->func
);
308 ret
.compareMask
= src
->valuemask
;
309 ret
.writeMask
= src
->writemask
;
310 ret
.reference
= 0; // not used: we'll use a dynamic state for this
315 zink_create_depth_stencil_alpha_state(struct pipe_context
*pctx
,
316 const struct pipe_depth_stencil_alpha_state
*depth_stencil_alpha
)
318 struct zink_depth_stencil_alpha_state
*cso
= CALLOC_STRUCT(zink_depth_stencil_alpha_state
);
322 if (depth_stencil_alpha
->depth
.enabled
) {
323 cso
->depth_test
= VK_TRUE
;
324 cso
->depth_compare_op
= compare_op(depth_stencil_alpha
->depth
.func
);
327 if (depth_stencil_alpha
->depth
.bounds_test
) {
328 cso
->depth_bounds_test
= VK_TRUE
;
329 cso
->min_depth_bounds
= depth_stencil_alpha
->depth
.bounds_min
;
330 cso
->max_depth_bounds
= depth_stencil_alpha
->depth
.bounds_max
;
333 if (depth_stencil_alpha
->stencil
[0].enabled
) {
334 cso
->stencil_test
= VK_TRUE
;
335 cso
->stencil_front
= stencil_op_state(depth_stencil_alpha
->stencil
);
338 if (depth_stencil_alpha
->stencil
[0].enabled
)
339 cso
->stencil_back
= stencil_op_state(depth_stencil_alpha
->stencil
+ 1);
341 cso
->stencil_back
= cso
->stencil_front
;
343 cso
->depth_write
= depth_stencil_alpha
->depth
.writemask
;
349 zink_bind_depth_stencil_alpha_state(struct pipe_context
*pctx
, void *cso
)
351 zink_context(pctx
)->gfx_pipeline_state
.depth_stencil_alpha_state
= cso
;
355 zink_delete_depth_stencil_alpha_state(struct pipe_context
*pctx
,
356 void *depth_stencil_alpha
)
358 FREE(depth_stencil_alpha
);
362 round_to_granularity(float value
, float granularity
)
364 return roundf(value
/ granularity
) * granularity
;
368 line_width(float width
, float granularity
, const float range
[2])
370 assert(granularity
>= 0);
371 assert(range
[0] <= range
[1]);
374 width
= round_to_granularity(width
, granularity
);
376 return CLAMP(width
, range
[0], range
[1]);
380 zink_create_rasterizer_state(struct pipe_context
*pctx
,
381 const struct pipe_rasterizer_state
*rs_state
)
383 struct zink_screen
*screen
= zink_screen(pctx
->screen
);
385 struct zink_rasterizer_state
*state
= CALLOC_STRUCT(zink_rasterizer_state
);
389 state
->base
= *rs_state
;
391 assert(rs_state
->depth_clip_far
== rs_state
->depth_clip_near
);
392 state
->hw_state
.depth_clamp
= rs_state
->depth_clip_near
== 0;
393 state
->hw_state
.rasterizer_discard
= rs_state
->rasterizer_discard
;
395 assert(rs_state
->fill_front
<= PIPE_POLYGON_MODE_POINT
);
396 if (rs_state
->fill_back
!= rs_state
->fill_front
)
397 debug_printf("BUG: vulkan doesn't support different front and back fill modes\n");
398 state
->hw_state
.polygon_mode
= (VkPolygonMode
)rs_state
->fill_front
; // same values
399 state
->hw_state
.cull_mode
= (VkCullModeFlags
)rs_state
->cull_face
; // same bits
401 state
->hw_state
.front_face
= rs_state
->front_ccw
?
402 VK_FRONT_FACE_COUNTER_CLOCKWISE
:
403 VK_FRONT_FACE_CLOCKWISE
;
405 state
->offset_point
= rs_state
->offset_point
;
406 state
->offset_line
= rs_state
->offset_line
;
407 state
->offset_tri
= rs_state
->offset_tri
;
408 state
->offset_units
= rs_state
->offset_units
;
409 state
->offset_clamp
= rs_state
->offset_clamp
;
410 state
->offset_scale
= rs_state
->offset_scale
;
412 state
->line_width
= line_width(rs_state
->line_width
,
413 screen
->props
.limits
.lineWidthGranularity
,
414 screen
->props
.limits
.lineWidthRange
);
420 zink_bind_rasterizer_state(struct pipe_context
*pctx
, void *cso
)
422 struct zink_context
*ctx
= zink_context(pctx
);
423 ctx
->rast_state
= cso
;
425 if (ctx
->rast_state
) {
426 ctx
->gfx_pipeline_state
.rast_state
= &ctx
->rast_state
->hw_state
;
427 ctx
->line_width
= ctx
->rast_state
->line_width
;
432 zink_delete_rasterizer_state(struct pipe_context
*pctx
, void *rs_state
)
438 zink_context_state_init(struct pipe_context
*pctx
)
440 pctx
->create_vertex_elements_state
= zink_create_vertex_elements_state
;
441 pctx
->bind_vertex_elements_state
= zink_bind_vertex_elements_state
;
442 pctx
->delete_vertex_elements_state
= zink_delete_vertex_elements_state
;
444 pctx
->create_blend_state
= zink_create_blend_state
;
445 pctx
->bind_blend_state
= zink_bind_blend_state
;
446 pctx
->delete_blend_state
= zink_delete_blend_state
;
448 pctx
->create_depth_stencil_alpha_state
= zink_create_depth_stencil_alpha_state
;
449 pctx
->bind_depth_stencil_alpha_state
= zink_bind_depth_stencil_alpha_state
;
450 pctx
->delete_depth_stencil_alpha_state
= zink_delete_depth_stencil_alpha_state
;
452 pctx
->create_rasterizer_state
= zink_create_rasterizer_state
;
453 pctx
->bind_rasterizer_state
= zink_bind_rasterizer_state
;
454 pctx
->delete_rasterizer_state
= zink_delete_rasterizer_state
;