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