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