vk: Stream surface state instead of using the surface pool
[mesa.git] / src / vulkan / meta.c
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 "private.h"
31 #include "glsl_helpers.h"
32
33 static void
34 anv_device_init_meta_clear_state(struct anv_device *device)
35 {
36 VkPipelineIaStateCreateInfo ia_create_info = {
37 .sType = VK_STRUCTURE_TYPE_PIPELINE_IA_STATE_CREATE_INFO,
38 .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
39 .disableVertexReuse = false,
40 .primitiveRestartEnable = false,
41 .primitiveRestartIndex = 0
42 };
43
44 /* We don't use a vertex shader for clearing, but instead build and pass
45 * the VUEs directly to the rasterization backend.
46 */
47 VkShader fs = GLSL_VK_SHADER(device, FRAGMENT,
48 out vec4 f_color;
49 flat in vec4 v_color;
50 void main()
51 {
52 f_color = v_color;
53 }
54 );
55
56 VkPipelineShaderStageCreateInfo fs_create_info = {
57 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
58 .pNext = &ia_create_info,
59 .shader = {
60 .stage = VK_SHADER_STAGE_FRAGMENT,
61 .shader = fs,
62 .linkConstBufferCount = 0,
63 .pLinkConstBufferInfo = NULL,
64 .pSpecializationInfo = NULL
65 }
66 };
67
68 /* We use instanced rendering to clear multiple render targets. We have two
69 * vertex buffers: the first vertex buffer holds per-vertex data and
70 * provides the vertices for the clear rectangle. The second one holds
71 * per-instance data, which consists of the VUE header (which selects the
72 * layer) and the color (Vulkan supports per-RT clear colors).
73 */
74 VkPipelineVertexInputCreateInfo vi_create_info = {
75 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_CREATE_INFO,
76 .pNext = &fs_create_info,
77 .bindingCount = 2,
78 .pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) {
79 {
80 .binding = 0,
81 .strideInBytes = 8,
82 .stepRate = VK_VERTEX_INPUT_STEP_RATE_VERTEX
83 },
84 {
85 .binding = 1,
86 .strideInBytes = 32,
87 .stepRate = VK_VERTEX_INPUT_STEP_RATE_INSTANCE
88 },
89 },
90 .attributeCount = 3,
91 .pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) {
92 {
93 /* VUE Header */
94 .location = 0,
95 .binding = 1,
96 .format = VK_FORMAT_R32G32B32A32_UINT,
97 .offsetInBytes = 0
98 },
99 {
100 /* Position */
101 .location = 1,
102 .binding = 0,
103 .format = VK_FORMAT_R32G32_SFLOAT,
104 .offsetInBytes = 0
105 },
106 {
107 /* Color */
108 .location = 2,
109 .binding = 1,
110 .format = VK_FORMAT_R32G32B32A32_SFLOAT,
111 .offsetInBytes = 16
112 }
113 }
114 };
115
116 VkPipelineRsStateCreateInfo rs_create_info = {
117 .sType = VK_STRUCTURE_TYPE_PIPELINE_RS_STATE_CREATE_INFO,
118 .pNext = &vi_create_info,
119 .depthClipEnable = true,
120 .rasterizerDiscardEnable = false,
121 .fillMode = VK_FILL_MODE_SOLID,
122 .cullMode = VK_CULL_MODE_NONE,
123 .frontFace = VK_FRONT_FACE_CCW
124 };
125
126 anv_pipeline_create((VkDevice) device,
127 &(VkGraphicsPipelineCreateInfo) {
128 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
129 .pNext = &rs_create_info,
130 .flags = 0,
131 .layout = 0
132 },
133 &(struct anv_pipeline_create_info) {
134 .use_repclear = true,
135 .disable_viewport = true,
136 .use_rectlist = true
137 },
138 &device->clear_state.pipeline);
139
140 anv_DestroyObject((VkDevice) device, VK_OBJECT_TYPE_SHADER, fs);
141
142 anv_CreateDynamicRasterState((VkDevice) device,
143 &(VkDynamicRsStateCreateInfo) {
144 .sType = VK_STRUCTURE_TYPE_DYNAMIC_RS_STATE_CREATE_INFO,
145 },
146 &device->clear_state.rs_state);
147 }
148
149 #define NUM_VB_USED 2
150 struct anv_saved_state {
151 struct anv_bindings bindings;
152 struct anv_bindings *old_bindings;
153 struct anv_pipeline *old_pipeline;
154 };
155
156 static void
157 anv_cmd_buffer_save(struct anv_cmd_buffer *cmd_buffer,
158 struct anv_saved_state *state)
159 {
160 state->old_bindings = cmd_buffer->bindings;
161 cmd_buffer->bindings = &state->bindings;
162 state->old_pipeline = cmd_buffer->pipeline;
163 }
164
165 static void
166 anv_cmd_buffer_restore(struct anv_cmd_buffer *cmd_buffer,
167 const struct anv_saved_state *state)
168 {
169 cmd_buffer->bindings = state->old_bindings;
170 cmd_buffer->pipeline = state->old_pipeline;
171
172 cmd_buffer->vb_dirty |= (1 << NUM_VB_USED) - 1;
173 cmd_buffer->dirty |= ANV_CMD_BUFFER_PIPELINE_DIRTY |
174 ANV_CMD_BUFFER_DESCRIPTOR_SET_DIRTY;
175 }
176
177 static void
178 anv_cmd_buffer_copy_render_targets(struct anv_cmd_buffer *cmd_buffer,
179 struct anv_saved_state *state)
180 {
181 struct anv_framebuffer *fb = cmd_buffer->framebuffer;
182 struct anv_bindings *old_bindings = state->old_bindings;
183 struct anv_bindings *bindings = cmd_buffer->bindings;
184
185 for (uint32_t i = 0; i < fb->color_attachment_count; i++) {
186 bindings->descriptors[VK_SHADER_STAGE_FRAGMENT].surfaces[i] =
187 old_bindings->descriptors[VK_SHADER_STAGE_FRAGMENT].surfaces[i];
188
189 bindings->descriptors[VK_SHADER_STAGE_FRAGMENT].relocs[i].bo =
190 old_bindings->descriptors[VK_SHADER_STAGE_FRAGMENT].relocs[i].bo;
191 bindings->descriptors[VK_SHADER_STAGE_FRAGMENT].relocs[i].offset =
192 old_bindings->descriptors[VK_SHADER_STAGE_FRAGMENT].relocs[i].offset;
193 }
194
195 cmd_buffer->dirty |= ANV_CMD_BUFFER_DESCRIPTOR_SET_DIRTY;
196 }
197
198 struct vue_header {
199 uint32_t Reserved;
200 uint32_t RTAIndex;
201 uint32_t ViewportIndex;
202 float PointWidth;
203 };
204
205 void
206 anv_cmd_buffer_clear(struct anv_cmd_buffer *cmd_buffer,
207 struct anv_render_pass *pass)
208 {
209 struct anv_device *device = cmd_buffer->device;
210 struct anv_framebuffer *fb = cmd_buffer->framebuffer;
211 struct anv_saved_state saved_state;
212 struct anv_state state;
213 uint32_t size;
214
215 struct instance_data {
216 struct vue_header vue_header;
217 float color[4];
218 } *instance_data;
219
220 if (pass->num_clear_layers == 0)
221 return;
222
223 const float vertex_data[] = {
224 /* Rect-list coordinates */
225 0.0, 0.0,
226 fb->width, 0.0,
227 fb->width, fb->height,
228
229 /* Align to 16 bytes */
230 0.0, 0.0,
231 };
232
233 size = sizeof(vertex_data) + pass->num_clear_layers * sizeof(instance_data[0]);
234 state = anv_state_stream_alloc(&cmd_buffer->surface_state_stream, size, 16);
235
236 memcpy(state.map, vertex_data, sizeof(vertex_data));
237 instance_data = state.map + sizeof(vertex_data);
238
239 for (uint32_t i = 0; i < pass->num_layers; i++) {
240 if (pass->layers[i].color_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
241 *instance_data++ = (struct instance_data) {
242 .vue_header = {
243 .RTAIndex = i,
244 .ViewportIndex = 0,
245 .PointWidth = 0.0
246 },
247 .color = {
248 pass->layers[i].clear_color.color.floatColor[0],
249 pass->layers[i].clear_color.color.floatColor[1],
250 pass->layers[i].clear_color.color.floatColor[2],
251 pass->layers[i].clear_color.color.floatColor[3],
252 }
253 };
254 }
255 }
256
257 struct anv_buffer vertex_buffer = {
258 .device = cmd_buffer->device,
259 .size = size,
260 .bo = &device->surface_state_block_pool.bo,
261 .offset = state.offset
262 };
263
264 anv_cmd_buffer_save(cmd_buffer, &saved_state);
265 anv_cmd_buffer_copy_render_targets(cmd_buffer, &saved_state);
266
267 anv_CmdBindVertexBuffers((VkCmdBuffer) cmd_buffer, 0, 2,
268 (VkBuffer[]) {
269 (VkBuffer) &vertex_buffer,
270 (VkBuffer) &vertex_buffer
271 },
272 (VkDeviceSize[]) {
273 0,
274 sizeof(vertex_data)
275 });
276
277 if ((VkPipeline) cmd_buffer->pipeline != device->clear_state.pipeline)
278 anv_CmdBindPipeline((VkCmdBuffer) cmd_buffer,
279 VK_PIPELINE_BIND_POINT_GRAPHICS, device->clear_state.pipeline);
280
281 /* We don't need anything here, only set if not already set. */
282 if (cmd_buffer->rs_state == NULL)
283 anv_CmdBindDynamicStateObject((VkCmdBuffer) cmd_buffer,
284 VK_STATE_BIND_POINT_RASTER,
285 device->clear_state.rs_state);
286
287 if (cmd_buffer->vp_state == NULL)
288 anv_CmdBindDynamicStateObject((VkCmdBuffer) cmd_buffer,
289 VK_STATE_BIND_POINT_VIEWPORT,
290 cmd_buffer->framebuffer->vp_state);
291
292 anv_CmdDraw((VkCmdBuffer) cmd_buffer, 0, 3, 0, pass->num_clear_layers);
293
294 /* Restore API state */
295 anv_cmd_buffer_restore(cmd_buffer, &saved_state);
296
297 }
298
299 static void
300 anv_device_init_meta_blit_state(struct anv_device *device)
301 {
302 VkPipelineIaStateCreateInfo ia_create_info = {
303 .sType = VK_STRUCTURE_TYPE_PIPELINE_IA_STATE_CREATE_INFO,
304 .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
305 .disableVertexReuse = false,
306 .primitiveRestartEnable = false,
307 .primitiveRestartIndex = 0
308 };
309
310 /* We don't use a vertex shader for clearing, but instead build and pass
311 * the VUEs directly to the rasterization backend. However, we do need
312 * to provide GLSL source for the vertex shader so that the compiler
313 * does not dead-code our inputs.
314 */
315 VkShader vs = GLSL_VK_SHADER(device, VERTEX,
316 in vec2 a_pos;
317 in vec2 a_tex_coord;
318 out vec4 v_tex_coord;
319 void main()
320 {
321 v_tex_coord = vec4(a_tex_coord, 0, 1);
322 gl_Position = vec4(a_pos, 0, 1);
323 }
324 );
325
326 VkShader fs = GLSL_VK_SHADER(device, FRAGMENT,
327 out vec4 f_color;
328 in vec4 v_tex_coord;
329 layout(set = 0, binding = 0) uniform sampler2D u_tex;
330 void main()
331 {
332 f_color = texture(u_tex, v_tex_coord.xy);
333 }
334 );
335
336 VkPipelineShaderStageCreateInfo vs_create_info = {
337 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
338 .pNext = &ia_create_info,
339 .shader = {
340 .stage = VK_SHADER_STAGE_VERTEX,
341 .shader = vs,
342 .linkConstBufferCount = 0,
343 .pLinkConstBufferInfo = NULL,
344 .pSpecializationInfo = NULL
345 }
346 };
347
348 VkPipelineShaderStageCreateInfo fs_create_info = {
349 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
350 .pNext = &vs_create_info,
351 .shader = {
352 .stage = VK_SHADER_STAGE_FRAGMENT,
353 .shader = fs,
354 .linkConstBufferCount = 0,
355 .pLinkConstBufferInfo = NULL,
356 .pSpecializationInfo = NULL
357 }
358 };
359
360 VkPipelineVertexInputCreateInfo vi_create_info = {
361 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_CREATE_INFO,
362 .pNext = &fs_create_info,
363 .bindingCount = 2,
364 .pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) {
365 {
366 .binding = 0,
367 .strideInBytes = 0,
368 .stepRate = VK_VERTEX_INPUT_STEP_RATE_VERTEX
369 },
370 {
371 .binding = 1,
372 .strideInBytes = 16,
373 .stepRate = VK_VERTEX_INPUT_STEP_RATE_VERTEX
374 },
375 },
376 .attributeCount = 3,
377 .pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) {
378 {
379 /* VUE Header */
380 .location = 0,
381 .binding = 0,
382 .format = VK_FORMAT_R32G32B32A32_UINT,
383 .offsetInBytes = 0
384 },
385 {
386 /* Position */
387 .location = 1,
388 .binding = 1,
389 .format = VK_FORMAT_R32G32_SFLOAT,
390 .offsetInBytes = 0
391 },
392 {
393 /* Texture Coordinate */
394 .location = 2,
395 .binding = 1,
396 .format = VK_FORMAT_R32G32_SFLOAT,
397 .offsetInBytes = 8
398 }
399 }
400 };
401
402 VkDescriptorSetLayoutCreateInfo ds_layout_info = {
403 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
404 .count = 1,
405 .pBinding = (VkDescriptorSetLayoutBinding[]) {
406 {
407 .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
408 .count = 1,
409 .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
410 .pImmutableSamplers = NULL
411 },
412 }
413 };
414 anv_CreateDescriptorSetLayout((VkDevice) device, &ds_layout_info,
415 &device->blit_state.ds_layout);
416
417 VkPipelineLayoutCreateInfo pipeline_layout_info = {
418 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
419 .descriptorSetCount = 1,
420 .pSetLayouts = &device->blit_state.ds_layout,
421 };
422
423 VkPipelineLayout pipeline_layout;
424 anv_CreatePipelineLayout((VkDevice) device, &pipeline_layout_info,
425 &pipeline_layout);
426
427 VkPipelineRsStateCreateInfo rs_create_info = {
428 .sType = VK_STRUCTURE_TYPE_PIPELINE_RS_STATE_CREATE_INFO,
429 .pNext = &vi_create_info,
430 .depthClipEnable = true,
431 .rasterizerDiscardEnable = false,
432 .fillMode = VK_FILL_MODE_SOLID,
433 .cullMode = VK_CULL_MODE_NONE,
434 .frontFace = VK_FRONT_FACE_CCW
435 };
436
437 VkGraphicsPipelineCreateInfo pipeline_info = {
438 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
439 .pNext = &rs_create_info,
440 .flags = 0,
441 .layout = pipeline_layout,
442 };
443
444 anv_pipeline_create((VkDevice) device, &pipeline_info,
445 &(struct anv_pipeline_create_info) {
446 .use_repclear = false,
447 .disable_viewport = true,
448 .disable_scissor = true,
449 .disable_vs = true,
450 .use_rectlist = true
451 },
452 &device->blit_state.pipeline);
453
454 anv_DestroyObject((VkDevice) device, VK_OBJECT_TYPE_SHADER, vs);
455 anv_DestroyObject((VkDevice) device, VK_OBJECT_TYPE_SHADER, fs);
456
457 anv_CreateDynamicRasterState((VkDevice) device,
458 &(VkDynamicRsStateCreateInfo) {
459 .sType = VK_STRUCTURE_TYPE_DYNAMIC_RS_STATE_CREATE_INFO,
460 },
461 &device->blit_state.rs_state);
462 }
463
464 static void
465 meta_prepare_blit(struct anv_cmd_buffer *cmd_buffer,
466 struct anv_saved_state *saved_state)
467 {
468 struct anv_device *device = cmd_buffer->device;
469
470 anv_cmd_buffer_save(cmd_buffer, saved_state);
471
472 if ((VkPipeline) cmd_buffer->pipeline != device->blit_state.pipeline)
473 anv_CmdBindPipeline((VkCmdBuffer) cmd_buffer,
474 VK_PIPELINE_BIND_POINT_GRAPHICS,
475 device->blit_state.pipeline);
476
477 /* We don't need anything here, only set if not already set. */
478 if (cmd_buffer->rs_state == NULL)
479 anv_CmdBindDynamicStateObject((VkCmdBuffer) cmd_buffer,
480 VK_STATE_BIND_POINT_RASTER,
481 device->blit_state.rs_state);
482 }
483
484 struct blit_region {
485 VkOffset3D src_offset;
486 VkExtent3D src_extent;
487 VkOffset3D dest_offset;
488 VkExtent3D dest_extent;
489 };
490
491 static void
492 meta_emit_blit(struct anv_cmd_buffer *cmd_buffer,
493 struct anv_surface_view *src,
494 VkOffset3D src_offset,
495 VkExtent3D src_extent,
496 struct anv_surface_view *dest,
497 VkOffset3D dest_offset,
498 VkExtent3D dest_extent)
499 {
500 struct anv_device *device = cmd_buffer->device;
501
502 struct blit_vb_data {
503 float pos[2];
504 float tex_coord[2];
505 } *vb_data;
506
507 unsigned vb_size = sizeof(struct vue_header) + 3 * sizeof(*vb_data);
508
509 struct anv_state vb_state =
510 anv_state_stream_alloc(&cmd_buffer->surface_state_stream, vb_size, 16);
511 memset(vb_state.map, 0, sizeof(struct vue_header));
512 vb_data = vb_state.map + sizeof(struct vue_header);
513
514 vb_data[0] = (struct blit_vb_data) {
515 .pos = {
516 dest_offset.x + dest_extent.width,
517 dest_offset.y + dest_extent.height,
518 },
519 .tex_coord = {
520 (float)(src_offset.x + src_extent.width) / (float)src->extent.width,
521 (float)(src_offset.y + src_extent.height) / (float)src->extent.height,
522 },
523 };
524
525 vb_data[1] = (struct blit_vb_data) {
526 .pos = {
527 dest_offset.x,
528 dest_offset.y + dest_extent.height,
529 },
530 .tex_coord = {
531 (float)src_offset.x / (float)src->extent.width,
532 (float)(src_offset.y + src_extent.height) / (float)src->extent.height,
533 },
534 };
535
536 vb_data[2] = (struct blit_vb_data) {
537 .pos = {
538 dest_offset.x,
539 dest_offset.y,
540 },
541 .tex_coord = {
542 (float)src_offset.x / (float)src->extent.width,
543 (float)src_offset.y / (float)src->extent.height,
544 },
545 };
546
547 struct anv_buffer vertex_buffer = {
548 .device = device,
549 .size = vb_size,
550 .bo = &device->surface_state_block_pool.bo,
551 .offset = vb_state.offset,
552 };
553
554 anv_CmdBindVertexBuffers((VkCmdBuffer) cmd_buffer, 0, 2,
555 (VkBuffer[]) {
556 (VkBuffer) &vertex_buffer,
557 (VkBuffer) &vertex_buffer
558 },
559 (VkDeviceSize[]) {
560 0,
561 sizeof(struct vue_header),
562 });
563
564 uint32_t count;
565 VkDescriptorSet set;
566 anv_AllocDescriptorSets((VkDevice) device, 0 /* pool */,
567 VK_DESCRIPTOR_SET_USAGE_ONE_SHOT,
568 1, &device->blit_state.ds_layout, &set, &count);
569 anv_UpdateDescriptors((VkDevice) device, set, 1,
570 (const void * []) {
571 &(VkUpdateImages) {
572 .sType = VK_STRUCTURE_TYPE_UPDATE_IMAGES,
573 .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
574 .binding = 0,
575 .count = 1,
576 .pImageViews = (VkImageViewAttachInfo[]) {
577 {
578 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_ATTACH_INFO,
579 .view = (VkImageView) src,
580 .layout = VK_IMAGE_LAYOUT_GENERAL,
581 }
582 }
583 }
584 });
585
586 struct anv_framebuffer *fb;
587 anv_CreateFramebuffer((VkDevice) device,
588 &(VkFramebufferCreateInfo) {
589 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
590 .colorAttachmentCount = 1,
591 .pColorAttachments = (VkColorAttachmentBindInfo[]) {
592 {
593 .view = (VkColorAttachmentView) dest,
594 .layout = VK_IMAGE_LAYOUT_GENERAL
595 }
596 },
597 .pDepthStencilAttachment = NULL,
598 .sampleCount = 1,
599 .width = dest->extent.width,
600 .height = dest->extent.height,
601 .layers = 1
602 }, (VkFramebuffer *)&fb);
603
604
605 VkRenderPass pass;
606 anv_CreateRenderPass((VkDevice )device,
607 &(VkRenderPassCreateInfo) {
608 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
609 .renderArea = { { 0, 0 }, { dest->extent.width, dest->extent.height } },
610 .colorAttachmentCount = 1,
611 .extent = { 0, },
612 .sampleCount = 1,
613 .layers = 1,
614 .pColorFormats = (VkFormat[]) { dest->format },
615 .pColorLayouts = (VkImageLayout[]) { VK_IMAGE_LAYOUT_GENERAL },
616 .pColorLoadOps = (VkAttachmentLoadOp[]) { VK_ATTACHMENT_LOAD_OP_LOAD },
617 .pColorStoreOps = (VkAttachmentStoreOp[]) { VK_ATTACHMENT_STORE_OP_STORE },
618 .pColorLoadClearValues = (VkClearColor[]) {
619 { .color = { .floatColor = { 1.0, 0.0, 0.0, 1.0 } }, .useRawValue = false }
620 },
621 .depthStencilFormat = VK_FORMAT_UNDEFINED,
622 }, &pass);
623
624 anv_CmdBeginRenderPass((VkCmdBuffer) cmd_buffer,
625 &(VkRenderPassBegin) {
626 .renderPass = pass,
627 .framebuffer = (VkFramebuffer) fb,
628 });
629
630 anv_CmdBindDynamicStateObject((VkCmdBuffer) cmd_buffer,
631 VK_STATE_BIND_POINT_VIEWPORT, fb->vp_state);
632
633 anv_CmdBindDescriptorSets((VkCmdBuffer) cmd_buffer,
634 VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 1,
635 &set, 0, NULL);
636
637 anv_CmdDraw((VkCmdBuffer) cmd_buffer, 0, 3, 0, 1);
638
639 anv_CmdEndRenderPass((VkCmdBuffer) cmd_buffer, pass);
640 }
641
642 static void
643 meta_finish_blit(struct anv_cmd_buffer *cmd_buffer,
644 const struct anv_saved_state *saved_state)
645 {
646 anv_cmd_buffer_restore(cmd_buffer, saved_state);
647 }
648
649 static VkFormat
650 vk_format_for_cpp(int cpp)
651 {
652 switch (cpp) {
653 case 1: return VK_FORMAT_R8_UINT;
654 case 2: return VK_FORMAT_R8G8_UINT;
655 case 3: return VK_FORMAT_R8G8B8_UINT;
656 case 4: return VK_FORMAT_R8G8B8A8_UINT;
657 case 6: return VK_FORMAT_R16G16B16_UINT;
658 case 8: return VK_FORMAT_R16G16B16A16_UINT;
659 case 12: return VK_FORMAT_R32G32B32_UINT;
660 case 16: return VK_FORMAT_R32G32B32A32_UINT;
661 default:
662 unreachable("Invalid format cpp");
663 }
664 }
665
666 static void
667 do_buffer_copy(struct anv_cmd_buffer *cmd_buffer,
668 struct anv_bo *src, uint64_t src_offset,
669 struct anv_bo *dest, uint64_t dest_offset,
670 int width, int height, VkFormat copy_format)
671 {
672 VkDevice vk_device = (VkDevice)cmd_buffer->device;
673
674 VkImageCreateInfo image_info = {
675 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
676 .imageType = VK_IMAGE_TYPE_2D,
677 .format = copy_format,
678 .extent = {
679 .width = width,
680 .height = height,
681 .depth = 1,
682 },
683 .mipLevels = 1,
684 .arraySize = 1,
685 .samples = 1,
686 .tiling = VK_IMAGE_TILING_LINEAR,
687 .usage = VK_IMAGE_USAGE_SAMPLED_BIT,
688 .flags = 0,
689 };
690
691 struct anv_image *src_image, *dest_image;
692 anv_CreateImage(vk_device, &image_info, (VkImage *)&src_image);
693 anv_CreateImage(vk_device, &image_info, (VkImage *)&dest_image);
694
695 /* We could use a vk call to bind memory, but that would require
696 * creating a dummy memory object etc. so there's really no point.
697 */
698 src_image->bo = src;
699 src_image->offset = src_offset;
700 dest_image->bo = dest;
701 dest_image->offset = dest_offset;
702
703 struct anv_surface_view src_view;
704 anv_image_view_init(&src_view, cmd_buffer->device,
705 &(VkImageViewCreateInfo) {
706 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
707 .image = (VkImage)src_image,
708 .viewType = VK_IMAGE_VIEW_TYPE_2D,
709 .format = copy_format,
710 .channels = {
711 VK_CHANNEL_SWIZZLE_R,
712 VK_CHANNEL_SWIZZLE_G,
713 VK_CHANNEL_SWIZZLE_B,
714 VK_CHANNEL_SWIZZLE_A
715 },
716 .subresourceRange = {
717 .aspect = VK_IMAGE_ASPECT_COLOR,
718 .baseMipLevel = 0,
719 .mipLevels = 1,
720 .baseArraySlice = 0,
721 .arraySize = 1
722 },
723 .minLod = 0
724 },
725 cmd_buffer);
726
727 struct anv_surface_view dest_view;
728 anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
729 &(VkColorAttachmentViewCreateInfo) {
730 .sType = VK_STRUCTURE_TYPE_COLOR_ATTACHMENT_VIEW_CREATE_INFO,
731 .image = (VkImage)dest_image,
732 .format = copy_format,
733 .mipLevel = 0,
734 .baseArraySlice = 0,
735 .arraySize = 1,
736 },
737 cmd_buffer);
738
739 meta_emit_blit(cmd_buffer,
740 &src_view,
741 (VkOffset3D) { 0, 0, 0 },
742 (VkExtent3D) { width, height, 1 },
743 &dest_view,
744 (VkOffset3D) { 0, 0, 0 },
745 (VkExtent3D) { width, height, 1 });
746 }
747
748 void anv_CmdCopyBuffer(
749 VkCmdBuffer cmdBuffer,
750 VkBuffer srcBuffer,
751 VkBuffer destBuffer,
752 uint32_t regionCount,
753 const VkBufferCopy* pRegions)
754 {
755 struct anv_cmd_buffer *cmd_buffer = (struct anv_cmd_buffer *)cmdBuffer;
756 struct anv_buffer *src_buffer = (struct anv_buffer *)srcBuffer;
757 struct anv_buffer *dest_buffer = (struct anv_buffer *)destBuffer;
758 struct anv_saved_state saved_state;
759
760 meta_prepare_blit(cmd_buffer, &saved_state);
761
762 for (unsigned r = 0; r < regionCount; r++) {
763 uint64_t src_offset = src_buffer->offset + pRegions[r].srcOffset;
764 uint64_t dest_offset = dest_buffer->offset + pRegions[r].destOffset;
765 uint64_t copy_size = pRegions[r].copySize;
766
767 /* First, we compute the biggest format that can be used with the
768 * given offsets and size.
769 */
770 int cpp = 16;
771
772 int fs = ffs(src_offset) - 1;
773 if (fs != -1)
774 cpp = MIN2(cpp, 1 << fs);
775 assert(src_offset % cpp == 0);
776
777 fs = ffs(dest_offset) - 1;
778 if (fs != -1)
779 cpp = MIN2(cpp, 1 << fs);
780 assert(dest_offset % cpp == 0);
781
782 fs = ffs(pRegions[r].copySize) - 1;
783 if (fs != -1)
784 cpp = MIN2(cpp, 1 << fs);
785 assert(pRegions[r].copySize % cpp == 0);
786
787 VkFormat copy_format = vk_format_for_cpp(cpp);
788
789 /* This is maximum possible width/height our HW can handle */
790 uint64_t max_surface_dim = 1 << 14;
791
792 /* First, we make a bunch of max-sized copies */
793 uint64_t max_copy_size = max_surface_dim * max_surface_dim * cpp;
794 while (copy_size > max_copy_size) {
795 do_buffer_copy(cmd_buffer, src_buffer->bo, src_offset,
796 dest_buffer->bo, dest_offset,
797 max_surface_dim, max_surface_dim, copy_format);
798 copy_size -= max_copy_size;
799 src_offset += max_copy_size;
800 dest_offset += max_copy_size;
801 }
802
803 uint64_t height = copy_size / (max_surface_dim * cpp);
804 assert(height < max_surface_dim);
805 if (height != 0) {
806 uint64_t rect_copy_size = height * max_surface_dim * cpp;
807 do_buffer_copy(cmd_buffer, src_buffer->bo, src_offset,
808 dest_buffer->bo, dest_offset,
809 max_surface_dim, height, copy_format);
810 copy_size -= rect_copy_size;
811 src_offset += rect_copy_size;
812 dest_offset += rect_copy_size;
813 }
814
815 if (copy_size != 0) {
816 do_buffer_copy(cmd_buffer, src_buffer->bo, src_offset,
817 dest_buffer->bo, dest_offset,
818 copy_size / cpp, 1, copy_format);
819 }
820 }
821
822 meta_finish_blit(cmd_buffer, &saved_state);
823 }
824
825 void anv_CmdCopyImage(
826 VkCmdBuffer cmdBuffer,
827 VkImage srcImage,
828 VkImageLayout srcImageLayout,
829 VkImage destImage,
830 VkImageLayout destImageLayout,
831 uint32_t regionCount,
832 const VkImageCopy* pRegions)
833 {
834 struct anv_cmd_buffer *cmd_buffer = (struct anv_cmd_buffer *)cmdBuffer;
835 struct anv_image *src_image = (struct anv_image *)srcImage;
836 struct anv_saved_state saved_state;
837
838 meta_prepare_blit(cmd_buffer, &saved_state);
839
840 for (unsigned r = 0; r < regionCount; r++) {
841 struct anv_surface_view src_view;
842 anv_image_view_init(&src_view, cmd_buffer->device,
843 &(VkImageViewCreateInfo) {
844 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
845 .image = srcImage,
846 .viewType = VK_IMAGE_VIEW_TYPE_2D,
847 .format = src_image->format,
848 .channels = {
849 VK_CHANNEL_SWIZZLE_R,
850 VK_CHANNEL_SWIZZLE_G,
851 VK_CHANNEL_SWIZZLE_B,
852 VK_CHANNEL_SWIZZLE_A
853 },
854 .subresourceRange = {
855 .aspect = pRegions[r].srcSubresource.aspect,
856 .baseMipLevel = pRegions[r].srcSubresource.mipLevel,
857 .mipLevels = 1,
858 .baseArraySlice = pRegions[r].srcSubresource.arraySlice,
859 .arraySize = 1
860 },
861 .minLod = 0
862 },
863 cmd_buffer);
864
865 struct anv_surface_view dest_view;
866 anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
867 &(VkColorAttachmentViewCreateInfo) {
868 .sType = VK_STRUCTURE_TYPE_COLOR_ATTACHMENT_VIEW_CREATE_INFO,
869 .image = destImage,
870 .format = src_image->format,
871 .mipLevel = pRegions[r].destSubresource.mipLevel,
872 .baseArraySlice = pRegions[r].destSubresource.arraySlice,
873 .arraySize = 1,
874 },
875 cmd_buffer);
876
877 meta_emit_blit(cmd_buffer,
878 &src_view,
879 pRegions[r].srcOffset,
880 pRegions[r].extent,
881 &dest_view,
882 pRegions[r].destOffset,
883 pRegions[r].extent);
884 }
885
886 meta_finish_blit(cmd_buffer, &saved_state);
887 }
888
889 void anv_CmdBlitImage(
890 VkCmdBuffer cmdBuffer,
891 VkImage srcImage,
892 VkImageLayout srcImageLayout,
893 VkImage destImage,
894 VkImageLayout destImageLayout,
895 uint32_t regionCount,
896 const VkImageBlit* pRegions)
897 {
898 struct anv_cmd_buffer *cmd_buffer = (struct anv_cmd_buffer *)cmdBuffer;
899 struct anv_image *src_image = (struct anv_image *)srcImage;
900 struct anv_image *dest_image = (struct anv_image *)destImage;
901 struct anv_saved_state saved_state;
902
903 meta_prepare_blit(cmd_buffer, &saved_state);
904
905 for (unsigned r = 0; r < regionCount; r++) {
906 struct anv_surface_view src_view;
907 anv_image_view_init(&src_view, cmd_buffer->device,
908 &(VkImageViewCreateInfo) {
909 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
910 .image = srcImage,
911 .viewType = VK_IMAGE_VIEW_TYPE_2D,
912 .format = src_image->format,
913 .channels = {
914 VK_CHANNEL_SWIZZLE_R,
915 VK_CHANNEL_SWIZZLE_G,
916 VK_CHANNEL_SWIZZLE_B,
917 VK_CHANNEL_SWIZZLE_A
918 },
919 .subresourceRange = {
920 .aspect = pRegions[r].srcSubresource.aspect,
921 .baseMipLevel = pRegions[r].srcSubresource.mipLevel,
922 .mipLevels = 1,
923 .baseArraySlice = pRegions[r].srcSubresource.arraySlice,
924 .arraySize = 1
925 },
926 .minLod = 0
927 },
928 cmd_buffer);
929
930 struct anv_surface_view dest_view;
931 anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
932 &(VkColorAttachmentViewCreateInfo) {
933 .sType = VK_STRUCTURE_TYPE_COLOR_ATTACHMENT_VIEW_CREATE_INFO,
934 .image = destImage,
935 .format = dest_image->format,
936 .mipLevel = pRegions[r].destSubresource.mipLevel,
937 .baseArraySlice = pRegions[r].destSubresource.arraySlice,
938 .arraySize = 1,
939 },
940 cmd_buffer);
941
942 meta_emit_blit(cmd_buffer,
943 &src_view,
944 pRegions[r].srcOffset,
945 pRegions[r].srcExtent,
946 &dest_view,
947 pRegions[r].destOffset,
948 pRegions[r].destExtent);
949 }
950
951 meta_finish_blit(cmd_buffer, &saved_state);
952 }
953
954 void anv_CmdCopyBufferToImage(
955 VkCmdBuffer cmdBuffer,
956 VkBuffer srcBuffer,
957 VkImage destImage,
958 VkImageLayout destImageLayout,
959 uint32_t regionCount,
960 const VkBufferImageCopy* pRegions)
961 {
962 struct anv_cmd_buffer *cmd_buffer = (struct anv_cmd_buffer *)cmdBuffer;
963 VkDevice vk_device = (VkDevice) cmd_buffer->device;
964 struct anv_buffer *src_buffer = (struct anv_buffer *)srcBuffer;
965 struct anv_image *dest_image = (struct anv_image *)destImage;
966 struct anv_saved_state saved_state;
967
968 meta_prepare_blit(cmd_buffer, &saved_state);
969
970 for (unsigned r = 0; r < regionCount; r++) {
971 struct anv_image *src_image;
972 anv_CreateImage(vk_device,
973 &(VkImageCreateInfo) {
974 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
975 .imageType = VK_IMAGE_TYPE_2D,
976 .format = dest_image->format,
977 .extent = {
978 .width = pRegions[r].imageExtent.width,
979 .height = pRegions[r].imageExtent.height,
980 .depth = 1,
981 },
982 .mipLevels = 1,
983 .arraySize = 1,
984 .samples = 1,
985 .tiling = VK_IMAGE_TILING_LINEAR,
986 .usage = VK_IMAGE_USAGE_SAMPLED_BIT,
987 .flags = 0,
988 }, (VkImage *)&src_image);
989
990 /* We could use a vk call to bind memory, but that would require
991 * creating a dummy memory object etc. so there's really no point.
992 */
993 src_image->bo = src_buffer->bo;
994 src_image->offset = src_buffer->offset + pRegions[r].bufferOffset;
995
996 struct anv_surface_view src_view;
997 anv_image_view_init(&src_view, cmd_buffer->device,
998 &(VkImageViewCreateInfo) {
999 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
1000 .image = (VkImage)src_image,
1001 .viewType = VK_IMAGE_VIEW_TYPE_2D,
1002 .format = dest_image->format,
1003 .channels = {
1004 VK_CHANNEL_SWIZZLE_R,
1005 VK_CHANNEL_SWIZZLE_G,
1006 VK_CHANNEL_SWIZZLE_B,
1007 VK_CHANNEL_SWIZZLE_A
1008 },
1009 .subresourceRange = {
1010 .aspect = pRegions[r].imageSubresource.aspect,
1011 .baseMipLevel = 0,
1012 .mipLevels = 1,
1013 .baseArraySlice = 0,
1014 .arraySize = 1
1015 },
1016 .minLod = 0
1017 },
1018 cmd_buffer);
1019
1020 struct anv_surface_view dest_view;
1021 anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
1022 &(VkColorAttachmentViewCreateInfo) {
1023 .sType = VK_STRUCTURE_TYPE_COLOR_ATTACHMENT_VIEW_CREATE_INFO,
1024 .image = (VkImage)dest_image,
1025 .format = dest_image->format,
1026 .mipLevel = pRegions[r].imageSubresource.mipLevel,
1027 .baseArraySlice = pRegions[r].imageSubresource.arraySlice,
1028 .arraySize = 1,
1029 },
1030 cmd_buffer);
1031
1032 meta_emit_blit(cmd_buffer,
1033 &src_view,
1034 (VkOffset3D) { 0, 0, 0 },
1035 pRegions[r].imageExtent,
1036 &dest_view,
1037 pRegions[r].imageOffset,
1038 pRegions[r].imageExtent);
1039 }
1040
1041 meta_finish_blit(cmd_buffer, &saved_state);
1042 }
1043
1044 void anv_CmdCopyImageToBuffer(
1045 VkCmdBuffer cmdBuffer,
1046 VkImage srcImage,
1047 VkImageLayout srcImageLayout,
1048 VkBuffer destBuffer,
1049 uint32_t regionCount,
1050 const VkBufferImageCopy* pRegions)
1051 {
1052 struct anv_cmd_buffer *cmd_buffer = (struct anv_cmd_buffer *)cmdBuffer;
1053 VkDevice vk_device = (VkDevice) cmd_buffer->device;
1054 struct anv_image *src_image = (struct anv_image *)srcImage;
1055 struct anv_buffer *dest_buffer = (struct anv_buffer *)destBuffer;
1056 struct anv_saved_state saved_state;
1057
1058 meta_prepare_blit(cmd_buffer, &saved_state);
1059
1060 for (unsigned r = 0; r < regionCount; r++) {
1061 struct anv_surface_view src_view;
1062 anv_image_view_init(&src_view, cmd_buffer->device,
1063 &(VkImageViewCreateInfo) {
1064 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
1065 .image = srcImage,
1066 .viewType = VK_IMAGE_VIEW_TYPE_2D,
1067 .format = src_image->format,
1068 .channels = {
1069 VK_CHANNEL_SWIZZLE_R,
1070 VK_CHANNEL_SWIZZLE_G,
1071 VK_CHANNEL_SWIZZLE_B,
1072 VK_CHANNEL_SWIZZLE_A
1073 },
1074 .subresourceRange = {
1075 .aspect = pRegions[r].imageSubresource.aspect,
1076 .baseMipLevel = pRegions[r].imageSubresource.mipLevel,
1077 .mipLevels = 1,
1078 .baseArraySlice = pRegions[r].imageSubresource.arraySlice,
1079 .arraySize = 1
1080 },
1081 .minLod = 0
1082 },
1083 cmd_buffer);
1084
1085 struct anv_image *dest_image;
1086 anv_CreateImage(vk_device,
1087 &(VkImageCreateInfo) {
1088 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
1089 .imageType = VK_IMAGE_TYPE_2D,
1090 .format = src_image->format,
1091 .extent = {
1092 .width = pRegions[r].imageExtent.width,
1093 .height = pRegions[r].imageExtent.height,
1094 .depth = 1,
1095 },
1096 .mipLevels = 1,
1097 .arraySize = 1,
1098 .samples = 1,
1099 .tiling = VK_IMAGE_TILING_LINEAR,
1100 .usage = VK_IMAGE_USAGE_SAMPLED_BIT,
1101 .flags = 0,
1102 }, (VkImage *)&dest_image);
1103
1104 /* We could use a vk call to bind memory, but that would require
1105 * creating a dummy memory object etc. so there's really no point.
1106 */
1107 dest_image->bo = dest_buffer->bo;
1108 dest_image->offset = dest_buffer->offset + pRegions[r].bufferOffset;
1109
1110 struct anv_surface_view dest_view;
1111 anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
1112 &(VkColorAttachmentViewCreateInfo) {
1113 .sType = VK_STRUCTURE_TYPE_COLOR_ATTACHMENT_VIEW_CREATE_INFO,
1114 .image = (VkImage)dest_image,
1115 .format = src_image->format,
1116 .mipLevel = 0,
1117 .baseArraySlice = 0,
1118 .arraySize = 1,
1119 },
1120 cmd_buffer);
1121
1122 meta_emit_blit(cmd_buffer,
1123 &src_view,
1124 pRegions[r].imageOffset,
1125 pRegions[r].imageExtent,
1126 &dest_view,
1127 (VkOffset3D) { 0, 0, 0 },
1128 pRegions[r].imageExtent);
1129 }
1130
1131 meta_finish_blit(cmd_buffer, &saved_state);
1132 }
1133
1134 void anv_CmdCloneImageData(
1135 VkCmdBuffer cmdBuffer,
1136 VkImage srcImage,
1137 VkImageLayout srcImageLayout,
1138 VkImage destImage,
1139 VkImageLayout destImageLayout)
1140 {
1141 stub();
1142 }
1143
1144 void anv_CmdUpdateBuffer(
1145 VkCmdBuffer cmdBuffer,
1146 VkBuffer destBuffer,
1147 VkDeviceSize destOffset,
1148 VkDeviceSize dataSize,
1149 const uint32_t* pData)
1150 {
1151 stub();
1152 }
1153
1154 void anv_CmdFillBuffer(
1155 VkCmdBuffer cmdBuffer,
1156 VkBuffer destBuffer,
1157 VkDeviceSize destOffset,
1158 VkDeviceSize fillSize,
1159 uint32_t data)
1160 {
1161 stub();
1162 }
1163
1164 void anv_CmdClearColorImage(
1165 VkCmdBuffer cmdBuffer,
1166 VkImage image,
1167 VkImageLayout imageLayout,
1168 const VkClearColor* color,
1169 uint32_t rangeCount,
1170 const VkImageSubresourceRange* pRanges)
1171 {
1172 stub();
1173 }
1174
1175 void anv_CmdClearDepthStencil(
1176 VkCmdBuffer cmdBuffer,
1177 VkImage image,
1178 VkImageLayout imageLayout,
1179 float depth,
1180 uint32_t stencil,
1181 uint32_t rangeCount,
1182 const VkImageSubresourceRange* pRanges)
1183 {
1184 stub();
1185 }
1186
1187 void anv_CmdResolveImage(
1188 VkCmdBuffer cmdBuffer,
1189 VkImage srcImage,
1190 VkImageLayout srcImageLayout,
1191 VkImage destImage,
1192 VkImageLayout destImageLayout,
1193 uint32_t regionCount,
1194 const VkImageResolve* pRegions)
1195 {
1196 stub();
1197 }
1198
1199 void
1200 anv_device_init_meta(struct anv_device *device)
1201 {
1202 anv_device_init_meta_clear_state(device);
1203 anv_device_init_meta_blit_state(device);
1204 }