1 /*
2 * Copyright © 2015 Intel Corporation
3 *
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 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
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
13 * Software.
14 *
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 NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include <assert.h>
25 #include <stdbool.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29
30 #include "anv_private.h"
31 #include "anv_measure.h"
32
33 #include "vk_util.h"
34
35 /** \file anv_cmd_buffer.c
36 *
37 * This file contains all of the stuff for emitting commands into a command
38 * buffer. This includes implementations of most of the vkCmd*
39 * entrypoints. This file is concerned entirely with state emission and
40 * not with the command buffer data structure itself. As far as this file
41 * is concerned, most of anv_cmd_buffer is magic.
42 */
43
44 static void
anv_cmd_state_init(struct anv_cmd_buffer * cmd_buffer)45 anv_cmd_state_init(struct anv_cmd_buffer *cmd_buffer)
46 {
47 struct anv_cmd_state *state = &cmd_buffer->state;
48
49 memset(state, 0, sizeof(*state));
50
51 state->current_pipeline = UINT32_MAX;
52 state->gfx.restart_index = UINT32_MAX;
53 state->gfx.dirty = 0;
54 }
55
56 static void
anv_cmd_pipeline_state_finish(struct anv_cmd_buffer * cmd_buffer,struct anv_cmd_pipeline_state * pipe_state)57 anv_cmd_pipeline_state_finish(struct anv_cmd_buffer *cmd_buffer,
58 struct anv_cmd_pipeline_state *pipe_state)
59 {
60 for (uint32_t i = 0; i < ARRAY_SIZE(pipe_state->push_descriptors); i++) {
61 if (pipe_state->push_descriptors[i]) {
62 anv_descriptor_set_layout_unref(cmd_buffer->device,
63 pipe_state->push_descriptors[i]->set.layout);
64 vk_free(&cmd_buffer->vk.pool->alloc, pipe_state->push_descriptors[i]);
65 }
66 }
67 }
68
69 static void
anv_cmd_state_finish(struct anv_cmd_buffer * cmd_buffer)70 anv_cmd_state_finish(struct anv_cmd_buffer *cmd_buffer)
71 {
72 struct anv_cmd_state *state = &cmd_buffer->state;
73
74 anv_cmd_pipeline_state_finish(cmd_buffer, &state->gfx.base);
75 anv_cmd_pipeline_state_finish(cmd_buffer, &state->compute.base);
76 }
77
78 static void
anv_cmd_state_reset(struct anv_cmd_buffer * cmd_buffer)79 anv_cmd_state_reset(struct anv_cmd_buffer *cmd_buffer)
80 {
81 anv_cmd_state_finish(cmd_buffer);
82 anv_cmd_state_init(cmd_buffer);
83 }
84
85 static VkResult
anv_create_cmd_buffer(struct vk_command_pool * pool,VkCommandBufferLevel level,struct vk_command_buffer ** cmd_buffer_out)86 anv_create_cmd_buffer(struct vk_command_pool *pool,
87 VkCommandBufferLevel level,
88 struct vk_command_buffer **cmd_buffer_out)
89 {
90 struct anv_device *device =
91 container_of(pool->base.device, struct anv_device, vk);
92 struct anv_cmd_buffer *cmd_buffer;
93 VkResult result;
94
95 cmd_buffer = vk_alloc(&pool->alloc, sizeof(*cmd_buffer), 8,
96 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
97 if (cmd_buffer == NULL)
98 return vk_error(pool, VK_ERROR_OUT_OF_HOST_MEMORY);
99
100 result = vk_command_buffer_init(pool, &cmd_buffer->vk,
101 &anv_cmd_buffer_ops, level);
102 if (result != VK_SUCCESS)
103 goto fail_alloc;
104
105 cmd_buffer->vk.dynamic_graphics_state.ms.sample_locations =
106 &cmd_buffer->state.gfx.sample_locations;
107
108 cmd_buffer->batch.status = VK_SUCCESS;
109
110 cmd_buffer->device = device;
111
112 assert(pool->queue_family_index < device->physical->queue.family_count);
113 cmd_buffer->queue_family =
114 &device->physical->queue.families[pool->queue_family_index];
115
116 result = anv_cmd_buffer_init_batch_bo_chain(cmd_buffer);
117 if (result != VK_SUCCESS)
118 goto fail_vk;
119
120 anv_state_stream_init(&cmd_buffer->surface_state_stream,
121 &device->surface_state_pool, 4096);
122 anv_state_stream_init(&cmd_buffer->dynamic_state_stream,
123 &device->dynamic_state_pool, 16384);
124 anv_state_stream_init(&cmd_buffer->general_state_stream,
125 &device->general_state_pool, 16384);
126
127 cmd_buffer->self_mod_locations = NULL;
128
129 anv_cmd_state_init(cmd_buffer);
130
131 anv_measure_init(cmd_buffer);
132
133 u_trace_init(&cmd_buffer->trace, &device->ds.trace_context);
134
135 *cmd_buffer_out = &cmd_buffer->vk;
136
137 return VK_SUCCESS;
138
139 fail_vk:
140 vk_command_buffer_finish(&cmd_buffer->vk);
141 fail_alloc:
142 vk_free2(&device->vk.alloc, &pool->alloc, cmd_buffer);
143
144 return result;
145 }
146
147 static void
anv_cmd_buffer_destroy(struct vk_command_buffer * vk_cmd_buffer)148 anv_cmd_buffer_destroy(struct vk_command_buffer *vk_cmd_buffer)
149 {
150 struct anv_cmd_buffer *cmd_buffer =
151 container_of(vk_cmd_buffer, struct anv_cmd_buffer, vk);
152
153 u_trace_fini(&cmd_buffer->trace);
154
155 anv_measure_destroy(cmd_buffer);
156
157 anv_cmd_buffer_fini_batch_bo_chain(cmd_buffer);
158
159 anv_state_stream_finish(&cmd_buffer->surface_state_stream);
160 anv_state_stream_finish(&cmd_buffer->dynamic_state_stream);
161 anv_state_stream_finish(&cmd_buffer->general_state_stream);
162
163 anv_cmd_state_finish(cmd_buffer);
164
165 vk_free(&cmd_buffer->vk.pool->alloc, cmd_buffer->self_mod_locations);
166
167 vk_command_buffer_finish(&cmd_buffer->vk);
168 vk_free(&cmd_buffer->vk.pool->alloc, cmd_buffer);
169 }
170
171 void
anv_cmd_buffer_reset(struct vk_command_buffer * vk_cmd_buffer,UNUSED VkCommandBufferResetFlags flags)172 anv_cmd_buffer_reset(struct vk_command_buffer *vk_cmd_buffer,
173 UNUSED VkCommandBufferResetFlags flags)
174 {
175 struct anv_cmd_buffer *cmd_buffer =
176 container_of(vk_cmd_buffer, struct anv_cmd_buffer, vk);
177
178 vk_command_buffer_reset(&cmd_buffer->vk);
179
180 cmd_buffer->usage_flags = 0;
181 cmd_buffer->perf_query_pool = NULL;
182 anv_cmd_buffer_reset_batch_bo_chain(cmd_buffer);
183 anv_cmd_state_reset(cmd_buffer);
184
185 anv_state_stream_finish(&cmd_buffer->surface_state_stream);
186 anv_state_stream_init(&cmd_buffer->surface_state_stream,
187 &cmd_buffer->device->surface_state_pool, 4096);
188
189 anv_state_stream_finish(&cmd_buffer->dynamic_state_stream);
190 anv_state_stream_init(&cmd_buffer->dynamic_state_stream,
191 &cmd_buffer->device->dynamic_state_pool, 16384);
192
193 anv_state_stream_finish(&cmd_buffer->general_state_stream);
194 anv_state_stream_init(&cmd_buffer->general_state_stream,
195 &cmd_buffer->device->general_state_pool, 16384);
196
197 anv_measure_reset(cmd_buffer);
198
199 u_trace_fini(&cmd_buffer->trace);
200 u_trace_init(&cmd_buffer->trace, &cmd_buffer->device->ds.trace_context);
201 }
202
203 const struct vk_command_buffer_ops anv_cmd_buffer_ops = {
204 .create = anv_create_cmd_buffer,
205 .reset = anv_cmd_buffer_reset,
206 .destroy = anv_cmd_buffer_destroy,
207 };
208
209 void
anv_cmd_buffer_emit_state_base_address(struct anv_cmd_buffer * cmd_buffer)210 anv_cmd_buffer_emit_state_base_address(struct anv_cmd_buffer *cmd_buffer)
211 {
212 const struct intel_device_info *devinfo = cmd_buffer->device->info;
213 anv_genX(devinfo, cmd_buffer_emit_state_base_address)(cmd_buffer);
214 }
215
216 void
anv_cmd_buffer_mark_image_written(struct anv_cmd_buffer * cmd_buffer,const struct anv_image * image,VkImageAspectFlagBits aspect,enum isl_aux_usage aux_usage,uint32_t level,uint32_t base_layer,uint32_t layer_count)217 anv_cmd_buffer_mark_image_written(struct anv_cmd_buffer *cmd_buffer,
218 const struct anv_image *image,
219 VkImageAspectFlagBits aspect,
220 enum isl_aux_usage aux_usage,
221 uint32_t level,
222 uint32_t base_layer,
223 uint32_t layer_count)
224 {
225 const struct intel_device_info *devinfo = cmd_buffer->device->info;
226 anv_genX(devinfo, cmd_buffer_mark_image_written)(cmd_buffer, image,
227 aspect, aux_usage,
228 level, base_layer,
229 layer_count);
230 }
231
232 void
anv_cmd_emit_conditional_render_predicate(struct anv_cmd_buffer * cmd_buffer)233 anv_cmd_emit_conditional_render_predicate(struct anv_cmd_buffer *cmd_buffer)
234 {
235 const struct intel_device_info *devinfo = cmd_buffer->device->info;
236 anv_genX(devinfo, cmd_emit_conditional_render_predicate)(cmd_buffer);
237 }
238
239 static bool
mem_update(void * dst,const void * src,size_t size)240 mem_update(void *dst, const void *src, size_t size)
241 {
242 if (memcmp(dst, src, size) == 0)
243 return false;
244
245 memcpy(dst, src, size);
246 return true;
247 }
248
249 static void
set_dirty_for_bind_map(struct anv_cmd_buffer * cmd_buffer,gl_shader_stage stage,const struct anv_pipeline_bind_map * map)250 set_dirty_for_bind_map(struct anv_cmd_buffer *cmd_buffer,
251 gl_shader_stage stage,
252 const struct anv_pipeline_bind_map *map)
253 {
254 assert(stage < ARRAY_SIZE(cmd_buffer->state.surface_sha1s));
255 if (mem_update(cmd_buffer->state.surface_sha1s[stage],
256 map->surface_sha1, sizeof(map->surface_sha1)))
257 cmd_buffer->state.descriptors_dirty |= mesa_to_vk_shader_stage(stage);
258
259 assert(stage < ARRAY_SIZE(cmd_buffer->state.sampler_sha1s));
260 if (mem_update(cmd_buffer->state.sampler_sha1s[stage],
261 map->sampler_sha1, sizeof(map->sampler_sha1)))
262 cmd_buffer->state.descriptors_dirty |= mesa_to_vk_shader_stage(stage);
263
264 assert(stage < ARRAY_SIZE(cmd_buffer->state.push_sha1s));
265 if (mem_update(cmd_buffer->state.push_sha1s[stage],
266 map->push_sha1, sizeof(map->push_sha1)))
267 cmd_buffer->state.push_constants_dirty |= mesa_to_vk_shader_stage(stage);
268 }
269
270 static inline uint32_t
ilog2_round_up(uint32_t value)271 ilog2_round_up(uint32_t value)
272 {
273 assert(value != 0);
274 return 32 - __builtin_clz(value - 1);
275 }
276
anv_CmdBindPipeline(VkCommandBuffer commandBuffer,VkPipelineBindPoint pipelineBindPoint,VkPipeline _pipeline)277 void anv_CmdBindPipeline(
278 VkCommandBuffer commandBuffer,
279 VkPipelineBindPoint pipelineBindPoint,
280 VkPipeline _pipeline)
281 {
282 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
283 ANV_FROM_HANDLE(anv_pipeline, pipeline, _pipeline);
284
285 switch (pipelineBindPoint) {
286 case VK_PIPELINE_BIND_POINT_COMPUTE: {
287 struct anv_compute_pipeline *compute_pipeline =
288 anv_pipeline_to_compute(pipeline);
289 if (cmd_buffer->state.compute.pipeline == compute_pipeline)
290 return;
291
292 cmd_buffer->state.compute.pipeline = compute_pipeline;
293 cmd_buffer->state.compute.pipeline_dirty = true;
294 set_dirty_for_bind_map(cmd_buffer, MESA_SHADER_COMPUTE,
295 &compute_pipeline->cs->bind_map);
296 break;
297 }
298
299 case VK_PIPELINE_BIND_POINT_GRAPHICS: {
300 struct anv_graphics_pipeline *gfx_pipeline =
301 anv_pipeline_to_graphics(pipeline);
302
303 /* Apply the non dynamic state from the pipeline */
304 vk_cmd_set_dynamic_graphics_state(&cmd_buffer->vk,
305 &gfx_pipeline->dynamic_state);
306
307 if (cmd_buffer->state.gfx.pipeline == gfx_pipeline)
308 return;
309
310 cmd_buffer->state.gfx.pipeline = gfx_pipeline;
311 cmd_buffer->state.gfx.vb_dirty |= gfx_pipeline->vb_used;
312 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_PIPELINE;
313
314 anv_foreach_stage(stage, gfx_pipeline->active_stages) {
315 set_dirty_for_bind_map(cmd_buffer, stage,
316 &gfx_pipeline->shaders[stage]->bind_map);
317 }
318 break;
319 }
320
321 default:
322 unreachable("invalid bind point");
323 break;
324 }
325 }
326
327 static void
anv_cmd_buffer_bind_descriptor_set(struct anv_cmd_buffer * cmd_buffer,VkPipelineBindPoint bind_point,struct anv_pipeline_layout * layout,uint32_t set_index,struct anv_descriptor_set * set,uint32_t * dynamic_offset_count,const uint32_t ** dynamic_offsets)328 anv_cmd_buffer_bind_descriptor_set(struct anv_cmd_buffer *cmd_buffer,
329 VkPipelineBindPoint bind_point,
330 struct anv_pipeline_layout *layout,
331 uint32_t set_index,
332 struct anv_descriptor_set *set,
333 uint32_t *dynamic_offset_count,
334 const uint32_t **dynamic_offsets)
335 {
336 /* Either we have no pool because it's a push descriptor or the pool is not
337 * host only :
338 *
339 * VUID-vkCmdBindDescriptorSets-pDescriptorSets-04616:
340 *
341 * "Each element of pDescriptorSets must not have been allocated from a
342 * VkDescriptorPool with the
343 * VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT flag set"
344 */
345 assert(!set->pool || !set->pool->host_only);
346
347 struct anv_descriptor_set_layout *set_layout =
348 layout->set[set_index].layout;
349
350 VkShaderStageFlags stages = set_layout->shader_stages;
351 struct anv_cmd_pipeline_state *pipe_state;
352
353 switch (bind_point) {
354 case VK_PIPELINE_BIND_POINT_GRAPHICS:
355 stages &= VK_SHADER_STAGE_ALL_GRAPHICS;
356 pipe_state = &cmd_buffer->state.gfx.base;
357 break;
358
359 case VK_PIPELINE_BIND_POINT_COMPUTE:
360 stages &= VK_SHADER_STAGE_COMPUTE_BIT;
361 pipe_state = &cmd_buffer->state.compute.base;
362 break;
363
364 default:
365 unreachable("invalid bind point");
366 }
367
368 VkShaderStageFlags dirty_stages = 0;
369 /* If it's a push descriptor set, we have to flag things as dirty
370 * regardless of whether or not the CPU-side data structure changed as we
371 * may have edited in-place.
372 */
373 if (pipe_state->descriptors[set_index] != set ||
374 anv_descriptor_set_is_push(set)) {
375 pipe_state->descriptors[set_index] = set;
376 dirty_stages |= stages;
377 }
378
379 if (dynamic_offsets) {
380 if (set_layout->dynamic_offset_count > 0) {
381 struct anv_push_constants *push = &pipe_state->push_constants;
382 uint32_t dynamic_offset_start =
383 layout->set[set_index].dynamic_offset_start;
384 uint32_t *push_offsets =
385 &push->dynamic_offsets[dynamic_offset_start];
386
387 /* Assert that everything is in range */
388 assert(set_layout->dynamic_offset_count <= *dynamic_offset_count);
389 assert(dynamic_offset_start + set_layout->dynamic_offset_count <=
390 ARRAY_SIZE(push->dynamic_offsets));
391
392 for (uint32_t i = 0; i < set_layout->dynamic_offset_count; i++) {
393 if (push_offsets[i] != (*dynamic_offsets)[i]) {
394 push_offsets[i] = (*dynamic_offsets)[i];
395 /* dynamic_offset_stages[] elements could contain blanket
396 * values like VK_SHADER_STAGE_ALL, so limit this to the
397 * binding point's bits.
398 */
399 dirty_stages |= set_layout->dynamic_offset_stages[i] & stages;
400 }
401 }
402
403 *dynamic_offsets += set_layout->dynamic_offset_count;
404 *dynamic_offset_count -= set_layout->dynamic_offset_count;
405 }
406 }
407
408 cmd_buffer->state.descriptors_dirty |= dirty_stages;
409 cmd_buffer->state.push_constants_dirty |= dirty_stages;
410 }
411
anv_CmdBindDescriptorSets(VkCommandBuffer commandBuffer,VkPipelineBindPoint pipelineBindPoint,VkPipelineLayout _layout,uint32_t firstSet,uint32_t descriptorSetCount,const VkDescriptorSet * pDescriptorSets,uint32_t dynamicOffsetCount,const uint32_t * pDynamicOffsets)412 void anv_CmdBindDescriptorSets(
413 VkCommandBuffer commandBuffer,
414 VkPipelineBindPoint pipelineBindPoint,
415 VkPipelineLayout _layout,
416 uint32_t firstSet,
417 uint32_t descriptorSetCount,
418 const VkDescriptorSet* pDescriptorSets,
419 uint32_t dynamicOffsetCount,
420 const uint32_t* pDynamicOffsets)
421 {
422 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
423 ANV_FROM_HANDLE(anv_pipeline_layout, layout, _layout);
424
425 assert(firstSet + descriptorSetCount <= MAX_SETS);
426
427 for (uint32_t i = 0; i < descriptorSetCount; i++) {
428 ANV_FROM_HANDLE(anv_descriptor_set, set, pDescriptorSets[i]);
429 anv_cmd_buffer_bind_descriptor_set(cmd_buffer, pipelineBindPoint,
430 layout, firstSet + i, set,
431 &dynamicOffsetCount,
432 &pDynamicOffsets);
433 }
434 }
435
anv_CmdBindVertexBuffers2(VkCommandBuffer commandBuffer,uint32_t firstBinding,uint32_t bindingCount,const VkBuffer * pBuffers,const VkDeviceSize * pOffsets,const VkDeviceSize * pSizes,const VkDeviceSize * pStrides)436 void anv_CmdBindVertexBuffers2(
437 VkCommandBuffer commandBuffer,
438 uint32_t firstBinding,
439 uint32_t bindingCount,
440 const VkBuffer* pBuffers,
441 const VkDeviceSize* pOffsets,
442 const VkDeviceSize* pSizes,
443 const VkDeviceSize* pStrides)
444 {
445 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
446 struct anv_vertex_binding *vb = cmd_buffer->state.vertex_bindings;
447
448 /* We have to defer setting up vertex buffer since we need the buffer
449 * stride from the pipeline. */
450
451 assert(firstBinding + bindingCount <= MAX_VBS);
452 for (uint32_t i = 0; i < bindingCount; i++) {
453 ANV_FROM_HANDLE(anv_buffer, buffer, pBuffers[i]);
454
455 if (buffer == NULL) {
456 vb[firstBinding + i] = (struct anv_vertex_binding) {
457 .buffer = NULL,
458 };
459 } else {
460 vb[firstBinding + i] = (struct anv_vertex_binding) {
461 .buffer = buffer,
462 .offset = pOffsets[i],
463 .size = vk_buffer_range(&buffer->vk, pOffsets[i],
464 pSizes ? pSizes[i] : VK_WHOLE_SIZE),
465 };
466 }
467 cmd_buffer->state.gfx.vb_dirty |= 1 << (firstBinding + i);
468 }
469
470 if (pStrides != NULL) {
471 vk_cmd_set_vertex_binding_strides(&cmd_buffer->vk, firstBinding,
472 bindingCount, pStrides);
473 }
474 }
475
anv_CmdBindTransformFeedbackBuffersEXT(VkCommandBuffer commandBuffer,uint32_t firstBinding,uint32_t bindingCount,const VkBuffer * pBuffers,const VkDeviceSize * pOffsets,const VkDeviceSize * pSizes)476 void anv_CmdBindTransformFeedbackBuffersEXT(
477 VkCommandBuffer commandBuffer,
478 uint32_t firstBinding,
479 uint32_t bindingCount,
480 const VkBuffer* pBuffers,
481 const VkDeviceSize* pOffsets,
482 const VkDeviceSize* pSizes)
483 {
484 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
485 struct anv_xfb_binding *xfb = cmd_buffer->state.xfb_bindings;
486
487 /* We have to defer setting up vertex buffer since we need the buffer
488 * stride from the pipeline. */
489
490 assert(firstBinding + bindingCount <= MAX_XFB_BUFFERS);
491 for (uint32_t i = 0; i < bindingCount; i++) {
492 if (pBuffers[i] == VK_NULL_HANDLE) {
493 xfb[firstBinding + i].buffer = NULL;
494 } else {
495 ANV_FROM_HANDLE(anv_buffer, buffer, pBuffers[i]);
496 xfb[firstBinding + i].buffer = buffer;
497 xfb[firstBinding + i].offset = pOffsets[i];
498 xfb[firstBinding + i].size =
499 vk_buffer_range(&buffer->vk, pOffsets[i],
500 pSizes ? pSizes[i] : VK_WHOLE_SIZE);
501 }
502 }
503 }
504
505 enum isl_format
anv_isl_format_for_descriptor_type(const struct anv_device * device,VkDescriptorType type)506 anv_isl_format_for_descriptor_type(const struct anv_device *device,
507 VkDescriptorType type)
508 {
509 switch (type) {
510 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
511 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
512 return device->physical->compiler->indirect_ubos_use_sampler ?
513 ISL_FORMAT_R32G32B32A32_FLOAT : ISL_FORMAT_RAW;
514
515 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
516 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
517 return ISL_FORMAT_RAW;
518
519 default:
520 unreachable("Invalid descriptor type");
521 }
522 }
523
524 struct anv_state
anv_cmd_buffer_emit_dynamic(struct anv_cmd_buffer * cmd_buffer,const void * data,uint32_t size,uint32_t alignment)525 anv_cmd_buffer_emit_dynamic(struct anv_cmd_buffer *cmd_buffer,
526 const void *data, uint32_t size, uint32_t alignment)
527 {
528 struct anv_state state;
529
530 state = anv_cmd_buffer_alloc_dynamic_state(cmd_buffer, size, alignment);
531 memcpy(state.map, data, size);
532
533 VG(VALGRIND_CHECK_MEM_IS_DEFINED(state.map, size));
534
535 return state;
536 }
537
538 struct anv_state
anv_cmd_buffer_merge_dynamic(struct anv_cmd_buffer * cmd_buffer,uint32_t * a,uint32_t * b,uint32_t dwords,uint32_t alignment)539 anv_cmd_buffer_merge_dynamic(struct anv_cmd_buffer *cmd_buffer,
540 uint32_t *a, uint32_t *b,
541 uint32_t dwords, uint32_t alignment)
542 {
543 struct anv_state state;
544 uint32_t *p;
545
546 state = anv_cmd_buffer_alloc_dynamic_state(cmd_buffer,
547 dwords * 4, alignment);
548 p = state.map;
549 for (uint32_t i = 0; i < dwords; i++)
550 p[i] = a[i] | b[i];
551
552 VG(VALGRIND_CHECK_MEM_IS_DEFINED(p, dwords * 4));
553
554 return state;
555 }
556
557 struct anv_state
anv_cmd_buffer_gfx_push_constants(struct anv_cmd_buffer * cmd_buffer)558 anv_cmd_buffer_gfx_push_constants(struct anv_cmd_buffer *cmd_buffer)
559 {
560 struct anv_push_constants *data =
561 &cmd_buffer->state.gfx.base.push_constants;
562
563 struct anv_state state =
564 anv_cmd_buffer_alloc_dynamic_state(cmd_buffer,
565 sizeof(struct anv_push_constants),
566 32 /* bottom 5 bits MBZ */);
567 memcpy(state.map, data, sizeof(struct anv_push_constants));
568
569 return state;
570 }
571
572 struct anv_state
anv_cmd_buffer_cs_push_constants(struct anv_cmd_buffer * cmd_buffer)573 anv_cmd_buffer_cs_push_constants(struct anv_cmd_buffer *cmd_buffer)
574 {
575 const struct intel_device_info *devinfo = cmd_buffer->device->info;
576 struct anv_push_constants *data =
577 &cmd_buffer->state.compute.base.push_constants;
578 struct anv_compute_pipeline *pipeline = cmd_buffer->state.compute.pipeline;
579 const struct elk_cs_prog_data *cs_prog_data = get_cs_prog_data(pipeline);
580 const struct anv_push_range *range = &pipeline->cs->bind_map.push_ranges[0];
581
582 const struct intel_cs_dispatch_info dispatch =
583 elk_cs_get_dispatch_info(devinfo, cs_prog_data, NULL);
584 const unsigned total_push_constants_size =
585 elk_cs_push_const_total_size(cs_prog_data, dispatch.threads);
586 if (total_push_constants_size == 0)
587 return (struct anv_state) { .offset = 0 };
588
589 const unsigned push_constant_alignment =
590 cmd_buffer->device->info->ver < 8 ? 32 : 64;
591 const unsigned aligned_total_push_constants_size =
592 ALIGN(total_push_constants_size, push_constant_alignment);
593 struct anv_state state =
594 anv_cmd_buffer_alloc_dynamic_state(cmd_buffer,
595 aligned_total_push_constants_size,
596 push_constant_alignment);
597
598 void *dst = state.map;
599 const void *src = (char *)data + (range->start * 32);
600
601 if (cs_prog_data->push.cross_thread.size > 0) {
602 memcpy(dst, src, cs_prog_data->push.cross_thread.size);
603 dst += cs_prog_data->push.cross_thread.size;
604 src += cs_prog_data->push.cross_thread.size;
605 }
606
607 if (cs_prog_data->push.per_thread.size > 0) {
608 for (unsigned t = 0; t < dispatch.threads; t++) {
609 memcpy(dst, src, cs_prog_data->push.per_thread.size);
610
611 uint32_t *subgroup_id = dst +
612 offsetof(struct anv_push_constants, cs.subgroup_id) -
613 (range->start * 32 + cs_prog_data->push.cross_thread.size);
614 *subgroup_id = t;
615
616 dst += cs_prog_data->push.per_thread.size;
617 }
618 }
619
620 return state;
621 }
622
anv_CmdPushConstants(VkCommandBuffer commandBuffer,VkPipelineLayout layout,VkShaderStageFlags stageFlags,uint32_t offset,uint32_t size,const void * pValues)623 void anv_CmdPushConstants(
624 VkCommandBuffer commandBuffer,
625 VkPipelineLayout layout,
626 VkShaderStageFlags stageFlags,
627 uint32_t offset,
628 uint32_t size,
629 const void* pValues)
630 {
631 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
632
633 if (stageFlags & VK_SHADER_STAGE_ALL_GRAPHICS) {
634 struct anv_cmd_pipeline_state *pipe_state =
635 &cmd_buffer->state.gfx.base;
636
637 memcpy(pipe_state->push_constants.client_data + offset, pValues, size);
638 }
639 if (stageFlags & VK_SHADER_STAGE_COMPUTE_BIT) {
640 struct anv_cmd_pipeline_state *pipe_state =
641 &cmd_buffer->state.compute.base;
642
643 memcpy(pipe_state->push_constants.client_data + offset, pValues, size);
644 }
645
646 cmd_buffer->state.push_constants_dirty |= stageFlags;
647 }
648
649 static struct anv_descriptor_set *
anv_cmd_buffer_push_descriptor_set(struct anv_cmd_buffer * cmd_buffer,VkPipelineBindPoint bind_point,struct anv_descriptor_set_layout * layout,uint32_t _set)650 anv_cmd_buffer_push_descriptor_set(struct anv_cmd_buffer *cmd_buffer,
651 VkPipelineBindPoint bind_point,
652 struct anv_descriptor_set_layout *layout,
653 uint32_t _set)
654 {
655 struct anv_cmd_pipeline_state *pipe_state;
656
657 switch (bind_point) {
658 case VK_PIPELINE_BIND_POINT_GRAPHICS:
659 pipe_state = &cmd_buffer->state.gfx.base;
660 break;
661
662 case VK_PIPELINE_BIND_POINT_COMPUTE:
663 pipe_state = &cmd_buffer->state.compute.base;
664 break;
665
666 default:
667 unreachable("invalid bind point");
668 }
669
670 struct anv_push_descriptor_set **push_set =
671 &pipe_state->push_descriptors[_set];
672
673 if (*push_set == NULL) {
674 *push_set = vk_zalloc(&cmd_buffer->vk.pool->alloc,
675 sizeof(struct anv_push_descriptor_set), 8,
676 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
677 if (*push_set == NULL) {
678 anv_batch_set_error(&cmd_buffer->batch, VK_ERROR_OUT_OF_HOST_MEMORY);
679 return NULL;
680 }
681 }
682
683 struct anv_descriptor_set *set = &(*push_set)->set;
684
685 if (set->layout != layout) {
686 if (set->layout)
687 anv_descriptor_set_layout_unref(cmd_buffer->device, set->layout);
688 anv_descriptor_set_layout_ref(layout);
689 set->layout = layout;
690 }
691 set->size = anv_descriptor_set_layout_size(layout, 0);
692 set->buffer_view_count = layout->buffer_view_count;
693 set->descriptor_count = layout->descriptor_count;
694 set->buffer_views = (*push_set)->buffer_views;
695
696 if (layout->descriptor_buffer_size &&
697 ((*push_set)->set_used_on_gpu ||
698 set->desc_mem.alloc_size < layout->descriptor_buffer_size)) {
699 /* The previous buffer is either actively used by some GPU command (so
700 * we can't modify it) or is too small. Allocate a new one.
701 */
702 struct anv_state desc_mem =
703 anv_state_stream_alloc(&cmd_buffer->dynamic_state_stream,
704 anv_descriptor_set_layout_descriptor_buffer_size(layout, 0),
705 ANV_UBO_ALIGNMENT);
706 if (set->desc_mem.alloc_size) {
707 /* TODO: Do we really need to copy all the time? */
708 memcpy(desc_mem.map, set->desc_mem.map,
709 MIN2(desc_mem.alloc_size, set->desc_mem.alloc_size));
710 }
711 set->desc_mem = desc_mem;
712
713 set->desc_addr = (struct anv_address) {
714 .bo = cmd_buffer->dynamic_state_stream.state_pool->block_pool.bo,
715 .offset = set->desc_mem.offset,
716 };
717
718 enum isl_format format =
719 anv_isl_format_for_descriptor_type(cmd_buffer->device,
720 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
721
722 const struct isl_device *isl_dev = &cmd_buffer->device->isl_dev;
723 set->desc_surface_state =
724 anv_state_stream_alloc(&cmd_buffer->surface_state_stream,
725 isl_dev->ss.size, isl_dev->ss.align);
726 anv_fill_buffer_surface_state(cmd_buffer->device,
727 set->desc_surface_state,
728 format, ISL_SWIZZLE_IDENTITY,
729 ISL_SURF_USAGE_CONSTANT_BUFFER_BIT,
730 set->desc_addr,
731 layout->descriptor_buffer_size, 1);
732 }
733
734 return set;
735 }
736
anv_CmdPushDescriptorSetKHR(VkCommandBuffer commandBuffer,VkPipelineBindPoint pipelineBindPoint,VkPipelineLayout _layout,uint32_t _set,uint32_t descriptorWriteCount,const VkWriteDescriptorSet * pDescriptorWrites)737 void anv_CmdPushDescriptorSetKHR(
738 VkCommandBuffer commandBuffer,
739 VkPipelineBindPoint pipelineBindPoint,
740 VkPipelineLayout _layout,
741 uint32_t _set,
742 uint32_t descriptorWriteCount,
743 const VkWriteDescriptorSet* pDescriptorWrites)
744 {
745 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
746 ANV_FROM_HANDLE(anv_pipeline_layout, layout, _layout);
747
748 assert(_set < MAX_SETS);
749
750 struct anv_descriptor_set_layout *set_layout = layout->set[_set].layout;
751
752 struct anv_descriptor_set *set =
753 anv_cmd_buffer_push_descriptor_set(cmd_buffer, pipelineBindPoint,
754 set_layout, _set);
755 if (!set)
756 return;
757
758 /* Go through the user supplied descriptors. */
759 for (uint32_t i = 0; i < descriptorWriteCount; i++) {
760 const VkWriteDescriptorSet *write = &pDescriptorWrites[i];
761
762 switch (write->descriptorType) {
763 case VK_DESCRIPTOR_TYPE_SAMPLER:
764 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
765 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
766 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
767 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
768 for (uint32_t j = 0; j < write->descriptorCount; j++) {
769 anv_descriptor_set_write_image_view(cmd_buffer->device, set,
770 write->pImageInfo + j,
771 write->descriptorType,
772 write->dstBinding,
773 write->dstArrayElement + j);
774 }
775 break;
776
777 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
778 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
779 for (uint32_t j = 0; j < write->descriptorCount; j++) {
780 ANV_FROM_HANDLE(anv_buffer_view, bview,
781 write->pTexelBufferView[j]);
782
783 anv_descriptor_set_write_buffer_view(cmd_buffer->device, set,
784 write->descriptorType,
785 bview,
786 write->dstBinding,
787 write->dstArrayElement + j);
788 }
789 break;
790
791 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
792 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
793 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
794 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
795 for (uint32_t j = 0; j < write->descriptorCount; j++) {
796 ANV_FROM_HANDLE(anv_buffer, buffer, write->pBufferInfo[j].buffer);
797
798 anv_descriptor_set_write_buffer(cmd_buffer->device, set,
799 &cmd_buffer->surface_state_stream,
800 write->descriptorType,
801 buffer,
802 write->dstBinding,
803 write->dstArrayElement + j,
804 write->pBufferInfo[j].offset,
805 write->pBufferInfo[j].range);
806 }
807 break;
808
809 default:
810 break;
811 }
812 }
813
814 anv_cmd_buffer_bind_descriptor_set(cmd_buffer, pipelineBindPoint,
815 layout, _set, set, NULL, NULL);
816 }
817
anv_CmdPushDescriptorSetWithTemplateKHR(VkCommandBuffer commandBuffer,VkDescriptorUpdateTemplate descriptorUpdateTemplate,VkPipelineLayout _layout,uint32_t _set,const void * pData)818 void anv_CmdPushDescriptorSetWithTemplateKHR(
819 VkCommandBuffer commandBuffer,
820 VkDescriptorUpdateTemplate descriptorUpdateTemplate,
821 VkPipelineLayout _layout,
822 uint32_t _set,
823 const void* pData)
824 {
825 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
826 VK_FROM_HANDLE(vk_descriptor_update_template, template,
827 descriptorUpdateTemplate);
828 ANV_FROM_HANDLE(anv_pipeline_layout, layout, _layout);
829
830 assert(_set < MAX_PUSH_DESCRIPTORS);
831
832 struct anv_descriptor_set_layout *set_layout = layout->set[_set].layout;
833
834 struct anv_descriptor_set *set =
835 anv_cmd_buffer_push_descriptor_set(cmd_buffer, template->bind_point,
836 set_layout, _set);
837 if (!set)
838 return;
839
840 anv_descriptor_set_write_template(cmd_buffer->device, set,
841 &cmd_buffer->surface_state_stream,
842 template,
843 pData);
844
845 anv_cmd_buffer_bind_descriptor_set(cmd_buffer, template->bind_point,
846 layout, _set, set, NULL, NULL);
847 }
848