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
;
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
;
93 state
->element_state
= NULL
;
97 zink_delete_vertex_elements_state(struct pipe_context
*pctx
,
103 blend_factor(enum pipe_blendfactor 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
;
118 case PIPE_BLENDFACTOR_ZERO
: return VK_BLEND_FACTOR_ZERO
;
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
;
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
;
138 unreachable("unexpected blend factor");
143 need_blend_constants(enum pipe_blendfactor 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
:
158 blend_op(enum pipe_blend_func 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
;
167 unreachable("unexpected blend function");
171 logic_op(enum pipe_logicop 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
;
191 unreachable("unexpected logicop function");
195 zink_create_blend_state(struct pipe_context
*pctx
,
196 const struct pipe_blend_state
*blend_state
)
198 struct zink_blend_state
*cso
= CALLOC_STRUCT(zink_blend_state
);
202 if (blend_state
->logicop_enable
) {
203 cso
->logicop_enable
= VK_TRUE
;
204 cso
->logicop_func
= logic_op(blend_state
->logicop_func
);
207 /* TODO: figure out what to do with dither (nothing is probably "OK" for now,
208 * as dithering is undefined in GL
211 /* TODO: these are multisampling-state, and should be set there instead of
212 * here, as that's closer tied to the update-frequency
214 cso
->alpha_to_coverage
= blend_state
->alpha_to_coverage
;
215 cso
->alpha_to_one
= blend_state
->alpha_to_one
;
217 cso
->need_blend_constants
= false;
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
;
224 VkPipelineColorBlendAttachmentState att
= { };
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
);
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;
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
;
251 cso
->attachments
[i
] = att
;
258 zink_bind_blend_state(struct pipe_context
*pctx
, void *cso
)
260 struct zink_gfx_pipeline_state
* state
= &zink_context(pctx
)->gfx_pipeline_state
;
262 if (state
->blend_state
!= cso
) {
263 state
->blend_state
= cso
;
269 zink_delete_blend_state(struct pipe_context
*pctx
, void *blend_state
)
275 compare_op(enum pipe_compare_func 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
;
287 unreachable("unexpected func");
291 stencil_op(enum pipe_stencil_op 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
;
303 unreachable("unexpected op");
306 static VkStencilOpState
307 stencil_op_state(const struct pipe_stencil_state
*src
)
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
321 zink_create_depth_stencil_alpha_state(struct pipe_context
*pctx
,
322 const struct pipe_depth_stencil_alpha_state
*depth_stencil_alpha
)
324 struct zink_depth_stencil_alpha_state
*cso
= CALLOC_STRUCT(zink_depth_stencil_alpha_state
);
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
);
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
;
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
);
344 if (depth_stencil_alpha
->stencil
[0].enabled
)
345 cso
->stencil_back
= stencil_op_state(depth_stencil_alpha
->stencil
+ 1);
347 cso
->stencil_back
= cso
->stencil_front
;
349 cso
->depth_write
= depth_stencil_alpha
->depth
.writemask
;
355 zink_bind_depth_stencil_alpha_state(struct pipe_context
*pctx
, void *cso
)
357 struct zink_gfx_pipeline_state
* state
= &zink_context(pctx
)->gfx_pipeline_state
;
359 if (state
->depth_stencil_alpha_state
!= cso
) {
360 state
->depth_stencil_alpha_state
= cso
;
366 zink_delete_depth_stencil_alpha_state(struct pipe_context
*pctx
,
367 void *depth_stencil_alpha
)
369 FREE(depth_stencil_alpha
);
373 round_to_granularity(float value
, float granularity
)
375 return roundf(value
/ granularity
) * granularity
;
379 line_width(float width
, float granularity
, const float range
[2])
381 assert(granularity
>= 0);
382 assert(range
[0] <= range
[1]);
385 width
= round_to_granularity(width
, granularity
);
387 return CLAMP(width
, range
[0], range
[1]);
391 zink_create_rasterizer_state(struct pipe_context
*pctx
,
392 const struct pipe_rasterizer_state
*rs_state
)
394 struct zink_screen
*screen
= zink_screen(pctx
->screen
);
396 struct zink_rasterizer_state
*state
= CALLOC_STRUCT(zink_rasterizer_state
);
400 state
->base
= *rs_state
;
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
;
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
412 state
->hw_state
.front_face
= rs_state
->front_ccw
?
413 VK_FRONT_FACE_COUNTER_CLOCKWISE
:
414 VK_FRONT_FACE_CLOCKWISE
;
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
;
423 state
->line_width
= line_width(rs_state
->line_width
,
424 screen
->props
.limits
.lineWidthGranularity
,
425 screen
->props
.limits
.lineWidthRange
);
431 zink_bind_rasterizer_state(struct pipe_context
*pctx
, void *cso
)
433 struct zink_context
*ctx
= zink_context(pctx
);
434 ctx
->rast_state
= cso
;
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;
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;
450 zink_delete_rasterizer_state(struct pipe_context
*pctx
, void *rs_state
)
456 zink_context_state_init(struct pipe_context
*pctx
)
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
;
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
;
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
;
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
;