radeonsi: move nir_shader_compiler_options into si_screen
[mesa.git] / src / gallium / drivers / zink / zink_draw.c
1 #include "zink_compiler.h"
2 #include "zink_context.h"
3 #include "zink_program.h"
4 #include "zink_resource.h"
5 #include "zink_screen.h"
6 #include "zink_state.h"
7
8 #include "indices/u_primconvert.h"
9 #include "util/hash_table.h"
10 #include "util/u_debug.h"
11 #include "util/u_helpers.h"
12 #include "util/u_inlines.h"
13 #include "util/u_prim.h"
14 #include "util/u_prim_restart.h"
15
16 static VkDescriptorSet
17 allocate_descriptor_set(struct zink_screen *screen,
18 struct zink_batch *batch,
19 struct zink_gfx_program *prog)
20 {
21 assert(batch->descs_left >= prog->num_descriptors);
22 VkDescriptorSetAllocateInfo dsai;
23 memset((void *)&dsai, 0, sizeof(dsai));
24 dsai.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
25 dsai.pNext = NULL;
26 dsai.descriptorPool = batch->descpool;
27 dsai.descriptorSetCount = 1;
28 dsai.pSetLayouts = &prog->dsl;
29
30 VkDescriptorSet desc_set;
31 if (vkAllocateDescriptorSets(screen->dev, &dsai, &desc_set) != VK_SUCCESS) {
32 debug_printf("ZINK: failed to allocate descriptor set :/");
33 return VK_NULL_HANDLE;
34 }
35
36 batch->descs_left -= prog->num_descriptors;
37 return desc_set;
38 }
39
40 static void
41 zink_emit_xfb_counter_barrier(struct zink_context *ctx)
42 {
43 /* Between the pause and resume there needs to be a memory barrier for the counter buffers
44 * with a source access of VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT
45 * at pipeline stage VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT
46 * to a destination access of VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT
47 * at pipeline stage VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT.
48 *
49 * - from VK_EXT_transform_feedback spec
50 */
51 VkBufferMemoryBarrier barriers[PIPE_MAX_SO_OUTPUTS] = {};
52 unsigned barrier_count = 0;
53
54 for (unsigned i = 0; i < ctx->num_so_targets; i++) {
55 struct zink_so_target *t = zink_so_target(ctx->so_targets[i]);
56 if (t->counter_buffer_valid) {
57 barriers[i].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
58 barriers[i].srcAccessMask = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT;
59 barriers[i].dstAccessMask = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT;
60 barriers[i].buffer = zink_resource(t->counter_buffer)->buffer;
61 barriers[i].size = VK_WHOLE_SIZE;
62 barrier_count++;
63 }
64 }
65 struct zink_batch *batch = zink_batch_no_rp(ctx);
66 vkCmdPipelineBarrier(batch->cmdbuf,
67 VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT,
68 VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,
69 0,
70 0, NULL,
71 barrier_count, barriers,
72 0, NULL
73 );
74 ctx->xfb_barrier = false;
75 }
76
77 static void
78 zink_emit_xfb_vertex_input_barrier(struct zink_context *ctx, struct zink_resource *res)
79 {
80 /* A pipeline barrier is required between using the buffers as
81 * transform feedback buffers and vertex buffers to
82 * ensure all writes to the transform feedback buffers are visible
83 * when the data is read as vertex attributes.
84 * The source access is VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT
85 * and the destination access is VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT
86 * for the pipeline stages VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT
87 * and VK_PIPELINE_STAGE_VERTEX_INPUT_BIT respectively.
88 *
89 * - 20.3.1. Drawing Transform Feedback
90 */
91 VkBufferMemoryBarrier barriers[1] = {};
92 barriers[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
93 barriers[0].srcAccessMask = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT;
94 barriers[0].dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
95 barriers[0].buffer = res->buffer;
96 barriers[0].size = VK_WHOLE_SIZE;
97 struct zink_batch *batch = zink_batch_no_rp(ctx);
98 zink_batch_reference_resoure(batch, res);
99 vkCmdPipelineBarrier(batch->cmdbuf,
100 VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT,
101 VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
102 0,
103 0, NULL,
104 ARRAY_SIZE(barriers), barriers,
105 0, NULL
106 );
107 res->needs_xfb_barrier = false;
108 }
109
110 static void
111 zink_emit_stream_output_targets(struct pipe_context *pctx)
112 {
113 struct zink_context *ctx = zink_context(pctx);
114 struct zink_screen *screen = zink_screen(pctx->screen);
115 struct zink_batch *batch = zink_curr_batch(ctx);
116 VkBuffer buffers[PIPE_MAX_SO_OUTPUTS];
117 VkDeviceSize buffer_offsets[PIPE_MAX_SO_OUTPUTS];
118 VkDeviceSize buffer_sizes[PIPE_MAX_SO_OUTPUTS];
119
120 for (unsigned i = 0; i < ctx->num_so_targets; i++) {
121 struct zink_so_target *t = (struct zink_so_target *)ctx->so_targets[i];
122 buffers[i] = zink_resource(t->base.buffer)->buffer;
123 zink_batch_reference_resoure(batch, zink_resource(t->base.buffer));
124 buffer_offsets[i] = t->base.buffer_offset;
125 buffer_sizes[i] = t->base.buffer_size;
126 }
127
128 screen->vk_CmdBindTransformFeedbackBuffersEXT(batch->cmdbuf, 0, ctx->num_so_targets,
129 buffers, buffer_offsets,
130 buffer_sizes);
131 ctx->dirty_so_targets = false;
132 }
133
134 static void
135 zink_bind_vertex_buffers(struct zink_batch *batch, struct zink_context *ctx)
136 {
137 VkBuffer buffers[PIPE_MAX_ATTRIBS];
138 VkDeviceSize buffer_offsets[PIPE_MAX_ATTRIBS];
139 const struct zink_vertex_elements_state *elems = ctx->element_state;
140 for (unsigned i = 0; i < elems->hw_state.num_bindings; i++) {
141 struct pipe_vertex_buffer *vb = ctx->buffers + ctx->element_state->binding_map[i];
142 assert(vb);
143 if (vb->buffer.resource) {
144 struct zink_resource *res = zink_resource(vb->buffer.resource);
145 buffers[i] = res->buffer;
146 buffer_offsets[i] = vb->buffer_offset;
147 zink_batch_reference_resoure(batch, res);
148 } else {
149 buffers[i] = zink_resource(ctx->dummy_buffer)->buffer;
150 buffer_offsets[i] = 0;
151 }
152 }
153
154 if (elems->hw_state.num_bindings > 0)
155 vkCmdBindVertexBuffers(batch->cmdbuf, 0,
156 elems->hw_state.num_bindings,
157 buffers, buffer_offsets);
158 }
159
160 static struct zink_gfx_program *
161 get_gfx_program(struct zink_context *ctx)
162 {
163 if (ctx->dirty_shader_stages) {
164 struct hash_entry *entry = _mesa_hash_table_search(ctx->program_cache,
165 ctx->gfx_stages);
166 if (!entry) {
167 struct zink_gfx_program *prog;
168 prog = zink_create_gfx_program(ctx, ctx->gfx_stages);
169 entry = _mesa_hash_table_insert(ctx->program_cache, prog->shaders, prog);
170 if (!entry)
171 return NULL;
172 }
173 ctx->curr_program = entry->data;
174 ctx->dirty_shader_stages = 0;
175 }
176
177 assert(ctx->curr_program);
178 return ctx->curr_program;
179 }
180
181 static bool
182 line_width_needed(enum pipe_prim_type reduced_prim,
183 VkPolygonMode polygon_mode)
184 {
185 switch (reduced_prim) {
186 case PIPE_PRIM_POINTS:
187 return false;
188
189 case PIPE_PRIM_LINES:
190 return true;
191
192 case PIPE_PRIM_TRIANGLES:
193 return polygon_mode == VK_POLYGON_MODE_LINE;
194
195 default:
196 unreachable("unexpected reduced prim");
197 }
198 }
199
200 static inline bool
201 restart_supported(enum pipe_prim_type mode)
202 {
203 return mode == PIPE_PRIM_LINE_STRIP || mode == PIPE_PRIM_TRIANGLE_STRIP || mode == PIPE_PRIM_TRIANGLE_FAN;
204 }
205
206 void
207 zink_draw_vbo(struct pipe_context *pctx,
208 const struct pipe_draw_info *dinfo)
209 {
210 struct zink_context *ctx = zink_context(pctx);
211 struct zink_screen *screen = zink_screen(pctx->screen);
212 struct zink_rasterizer_state *rast_state = ctx->rast_state;
213 struct zink_so_target *so_target = zink_so_target(dinfo->count_from_stream_output);
214 VkBuffer counter_buffers[PIPE_MAX_SO_OUTPUTS];
215 VkDeviceSize counter_buffer_offsets[PIPE_MAX_SO_OUTPUTS] = {};
216 bool need_index_buffer_unref = false;
217
218
219 if (dinfo->primitive_restart && !restart_supported(dinfo->mode)) {
220 util_draw_vbo_without_prim_restart(pctx, dinfo);
221 return;
222 }
223 if (dinfo->mode >= PIPE_PRIM_QUADS ||
224 dinfo->mode == PIPE_PRIM_LINE_LOOP) {
225 if (!u_trim_pipe_prim(dinfo->mode, (unsigned *)&dinfo->count))
226 return;
227
228 util_primconvert_save_rasterizer_state(ctx->primconvert, &rast_state->base);
229 util_primconvert_draw_vbo(ctx->primconvert, dinfo);
230 return;
231 }
232
233 struct zink_gfx_program *gfx_program = get_gfx_program(ctx);
234 if (!gfx_program)
235 return;
236
237 if (ctx->gfx_pipeline_state.primitive_restart != !!dinfo->primitive_restart)
238 ctx->gfx_pipeline_state.hash = 0;
239 ctx->gfx_pipeline_state.primitive_restart = !!dinfo->primitive_restart;
240
241 VkPipeline pipeline = zink_get_gfx_pipeline(screen, gfx_program,
242 &ctx->gfx_pipeline_state,
243 dinfo->mode);
244
245 enum pipe_prim_type reduced_prim = u_reduced_prim(dinfo->mode);
246
247 bool depth_bias = false;
248 switch (reduced_prim) {
249 case PIPE_PRIM_POINTS:
250 depth_bias = rast_state->offset_point;
251 break;
252
253 case PIPE_PRIM_LINES:
254 depth_bias = rast_state->offset_line;
255 break;
256
257 case PIPE_PRIM_TRIANGLES:
258 depth_bias = rast_state->offset_tri;
259 break;
260
261 default:
262 unreachable("unexpected reduced prim");
263 }
264
265 unsigned index_offset = 0;
266 struct pipe_resource *index_buffer = NULL;
267 if (dinfo->index_size > 0) {
268 uint32_t restart_index = util_prim_restart_index_from_size(dinfo->index_size);
269 if ((dinfo->primitive_restart && (dinfo->restart_index != restart_index)) ||
270 (!screen->have_EXT_index_type_uint8 && dinfo->index_size == 8)) {
271 util_translate_prim_restart_ib(pctx, dinfo, &index_buffer);
272 need_index_buffer_unref = true;
273 } else {
274 if (dinfo->has_user_indices) {
275 if (!util_upload_index_buffer(pctx, dinfo, &index_buffer, &index_offset, 4)) {
276 debug_printf("util_upload_index_buffer() failed\n");
277 return;
278 }
279 } else
280 index_buffer = dinfo->index.resource;
281 }
282 }
283
284 VkWriteDescriptorSet wds[PIPE_SHADER_TYPES * PIPE_MAX_CONSTANT_BUFFERS + PIPE_SHADER_TYPES * PIPE_MAX_SHADER_SAMPLER_VIEWS];
285 VkDescriptorBufferInfo buffer_infos[PIPE_SHADER_TYPES * PIPE_MAX_CONSTANT_BUFFERS];
286 VkDescriptorImageInfo image_infos[PIPE_SHADER_TYPES * PIPE_MAX_SHADER_SAMPLER_VIEWS];
287 int num_wds = 0, num_buffer_info = 0, num_image_info = 0;
288
289 struct zink_resource *transitions[PIPE_SHADER_TYPES * PIPE_MAX_SHADER_SAMPLER_VIEWS];
290 int num_transitions = 0;
291
292 for (int i = 0; i < ARRAY_SIZE(ctx->gfx_stages); i++) {
293 struct zink_shader *shader = ctx->gfx_stages[i];
294 if (!shader)
295 continue;
296
297 if (i == MESA_SHADER_VERTEX && ctx->num_so_targets) {
298 for (unsigned i = 0; i < ctx->num_so_targets; i++) {
299 struct zink_so_target *t = zink_so_target(ctx->so_targets[i]);
300 t->stride = shader->streamout.so_info.stride[i] * sizeof(uint32_t);
301 }
302 }
303
304 for (int j = 0; j < shader->num_bindings; j++) {
305 int index = shader->bindings[j].index;
306 if (shader->bindings[j].type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) {
307 assert(ctx->ubos[i][index].buffer_size > 0);
308 assert(ctx->ubos[i][index].buffer_size <= screen->props.limits.maxUniformBufferRange);
309 assert(ctx->ubos[i][index].buffer);
310 struct zink_resource *res = zink_resource(ctx->ubos[i][index].buffer);
311 buffer_infos[num_buffer_info].buffer = res->buffer;
312 buffer_infos[num_buffer_info].offset = ctx->ubos[i][index].buffer_offset;
313 buffer_infos[num_buffer_info].range = ctx->ubos[i][index].buffer_size;
314 wds[num_wds].pBufferInfo = buffer_infos + num_buffer_info;
315 ++num_buffer_info;
316 } else {
317 struct pipe_sampler_view *psampler_view = ctx->image_views[i][index];
318 assert(psampler_view);
319 struct zink_sampler_view *sampler_view = zink_sampler_view(psampler_view);
320
321 struct zink_resource *res = zink_resource(psampler_view->texture);
322 VkImageLayout layout = res->layout;
323 if (layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL &&
324 layout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL &&
325 layout != VK_IMAGE_LAYOUT_GENERAL) {
326 transitions[num_transitions++] = res;
327 layout = VK_IMAGE_LAYOUT_GENERAL;
328 }
329 image_infos[num_image_info].imageLayout = layout;
330 image_infos[num_image_info].imageView = sampler_view->image_view;
331 image_infos[num_image_info].sampler = ctx->samplers[i][index];
332 wds[num_wds].pImageInfo = image_infos + num_image_info;
333 ++num_image_info;
334 }
335
336 wds[num_wds].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
337 wds[num_wds].pNext = NULL;
338 wds[num_wds].dstBinding = shader->bindings[j].binding;
339 wds[num_wds].dstArrayElement = 0;
340 wds[num_wds].descriptorCount = 1;
341 wds[num_wds].descriptorType = shader->bindings[j].type;
342 ++num_wds;
343 }
344 }
345
346 struct zink_batch *batch;
347 if (num_transitions > 0) {
348 batch = zink_batch_no_rp(ctx);
349
350 for (int i = 0; i < num_transitions; ++i)
351 zink_resource_barrier(batch->cmdbuf, transitions[i],
352 transitions[i]->aspect,
353 VK_IMAGE_LAYOUT_GENERAL);
354 }
355
356 if (ctx->xfb_barrier)
357 zink_emit_xfb_counter_barrier(ctx);
358
359 if (ctx->dirty_so_targets)
360 zink_emit_stream_output_targets(pctx);
361
362 if (so_target && zink_resource(so_target->base.buffer)->needs_xfb_barrier)
363 zink_emit_xfb_vertex_input_barrier(ctx, zink_resource(so_target->base.buffer));
364
365
366 batch = zink_batch_rp(ctx);
367
368 if (batch->descs_left < gfx_program->num_descriptors) {
369 ctx->base.flush(&ctx->base, NULL, 0);
370 batch = zink_batch_rp(ctx);
371 assert(batch->descs_left >= gfx_program->num_descriptors);
372 }
373 zink_batch_reference_program(batch, ctx->curr_program);
374
375 VkDescriptorSet desc_set = allocate_descriptor_set(screen, batch,
376 gfx_program);
377 assert(desc_set != VK_NULL_HANDLE);
378
379 for (int i = 0; i < ARRAY_SIZE(ctx->gfx_stages); i++) {
380 struct zink_shader *shader = ctx->gfx_stages[i];
381 if (!shader)
382 continue;
383
384 for (int j = 0; j < shader->num_bindings; j++) {
385 int index = shader->bindings[j].index;
386 if (shader->bindings[j].type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) {
387 struct zink_resource *res = zink_resource(ctx->ubos[i][index].buffer);
388 zink_batch_reference_resoure(batch, res);
389 } else {
390 struct zink_sampler_view *sampler_view = zink_sampler_view(ctx->image_views[i][index]);
391 zink_batch_reference_sampler_view(batch, sampler_view);
392 }
393 }
394 }
395
396 vkCmdSetViewport(batch->cmdbuf, 0, ctx->num_viewports, ctx->viewports);
397 if (ctx->rast_state->base.scissor)
398 vkCmdSetScissor(batch->cmdbuf, 0, ctx->num_viewports, ctx->scissors);
399 else if (ctx->fb_state.width && ctx->fb_state.height) {
400 VkRect2D fb_scissor = {};
401 fb_scissor.extent.width = ctx->fb_state.width;
402 fb_scissor.extent.height = ctx->fb_state.height;
403 vkCmdSetScissor(batch->cmdbuf, 0, 1, &fb_scissor);
404 }
405
406 if (line_width_needed(reduced_prim, rast_state->hw_state.polygon_mode)) {
407 if (screen->feats.wideLines || ctx->line_width == 1.0f)
408 vkCmdSetLineWidth(batch->cmdbuf, ctx->line_width);
409 else
410 debug_printf("BUG: wide lines not supported, needs fallback!");
411 }
412
413 vkCmdSetStencilReference(batch->cmdbuf, VK_STENCIL_FACE_FRONT_BIT, ctx->stencil_ref.ref_value[0]);
414 vkCmdSetStencilReference(batch->cmdbuf, VK_STENCIL_FACE_BACK_BIT, ctx->stencil_ref.ref_value[1]);
415
416 if (depth_bias)
417 vkCmdSetDepthBias(batch->cmdbuf, rast_state->offset_units, rast_state->offset_clamp, rast_state->offset_scale);
418 else
419 vkCmdSetDepthBias(batch->cmdbuf, 0.0f, 0.0f, 0.0f);
420
421 if (ctx->gfx_pipeline_state.blend_state->need_blend_constants)
422 vkCmdSetBlendConstants(batch->cmdbuf, ctx->blend_constants);
423
424 if (num_wds > 0) {
425 for (int i = 0; i < num_wds; ++i)
426 wds[i].dstSet = desc_set;
427 vkUpdateDescriptorSets(screen->dev, num_wds, wds, 0, NULL);
428 }
429
430 vkCmdBindPipeline(batch->cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
431 vkCmdBindDescriptorSets(batch->cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS,
432 gfx_program->layout, 0, 1, &desc_set, 0, NULL);
433 zink_bind_vertex_buffers(batch, ctx);
434
435 if (ctx->num_so_targets) {
436 for (unsigned i = 0; i < ctx->num_so_targets; i++) {
437 struct zink_so_target *t = zink_so_target(ctx->so_targets[i]);
438 struct zink_resource *res = zink_resource(t->counter_buffer);
439 if (t->counter_buffer_valid) {
440 zink_batch_reference_resoure(batch, zink_resource(t->counter_buffer));
441 counter_buffers[i] = res->buffer;
442 counter_buffer_offsets[i] = t->counter_buffer_offset;
443 } else
444 counter_buffers[i] = VK_NULL_HANDLE;
445 }
446 screen->vk_CmdBeginTransformFeedbackEXT(batch->cmdbuf, 0, ctx->num_so_targets, counter_buffers, counter_buffer_offsets);
447 }
448
449 if (dinfo->index_size > 0) {
450 VkIndexType index_type;
451 unsigned index_size = dinfo->index_size;
452 if (need_index_buffer_unref)
453 /* index buffer will have been promoted from uint8 to uint16 in this case */
454 index_size = MAX2(index_size, 2);
455 switch (index_size) {
456 case 1:
457 assert(screen->have_EXT_index_type_uint8);
458 index_type = VK_INDEX_TYPE_UINT8_EXT;
459 break;
460 case 2:
461 index_type = VK_INDEX_TYPE_UINT16;
462 break;
463 case 4:
464 index_type = VK_INDEX_TYPE_UINT32;
465 break;
466 default:
467 unreachable("unknown index size!");
468 }
469 struct zink_resource *res = zink_resource(index_buffer);
470 vkCmdBindIndexBuffer(batch->cmdbuf, res->buffer, index_offset, index_type);
471 zink_batch_reference_resoure(batch, res);
472 vkCmdDrawIndexed(batch->cmdbuf,
473 dinfo->count, dinfo->instance_count,
474 need_index_buffer_unref ? 0 : dinfo->start, dinfo->index_bias, dinfo->start_instance);
475 } else {
476 if (so_target && screen->tf_props.transformFeedbackDraw) {
477 zink_batch_reference_resoure(batch, zink_resource(so_target->counter_buffer));
478 screen->vk_CmdDrawIndirectByteCountEXT(batch->cmdbuf, dinfo->instance_count, dinfo->start_instance,
479 zink_resource(so_target->counter_buffer)->buffer, so_target->counter_buffer_offset, 0,
480 MIN2(so_target->stride, screen->tf_props.maxTransformFeedbackBufferDataStride));
481 }
482 else
483 vkCmdDraw(batch->cmdbuf, dinfo->count, dinfo->instance_count, dinfo->start, dinfo->start_instance);
484 }
485
486 if (dinfo->index_size > 0 && (dinfo->has_user_indices || need_index_buffer_unref))
487 pipe_resource_reference(&index_buffer, NULL);
488
489 if (ctx->num_so_targets) {
490 for (unsigned i = 0; i < ctx->num_so_targets; i++) {
491 struct zink_so_target *t = zink_so_target(ctx->so_targets[i]);
492 counter_buffers[i] = zink_resource(t->counter_buffer)->buffer;
493 counter_buffer_offsets[i] = t->counter_buffer_offset;
494 t->counter_buffer_valid = true;
495 zink_resource(ctx->so_targets[i]->buffer)->needs_xfb_barrier = true;
496 }
497 screen->vk_CmdEndTransformFeedbackEXT(batch->cmdbuf, 0, ctx->num_so_targets, counter_buffers, counter_buffer_offsets);
498 }
499 }