OSDN Git Service

anv/meta_resolve: Begin pass outside emit_resolve()
[android-x86/external-mesa.git] / src / vulkan / anv_meta_resolve.c
1 /*
2  * Copyright © 2016 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
27 #include "anv_meta.h"
28 #include "anv_private.h"
29 #include "glsl/nir/nir_builder.h"
30
31 /**
32  * Vertex attributes used by all pipelines.
33  */
34 struct vertex_attrs {
35    struct anv_vue_header vue_header;
36    float position[2]; /**< 3DPRIM_RECTLIST */
37    float tex_position[2];
38 };
39
40 static nir_shader *
41 build_nir_vs(void)
42 {
43    const struct glsl_type *vec4 = glsl_vec4_type();
44
45    nir_builder b;
46    nir_variable *a_position;
47    nir_variable *v_position;
48    nir_variable *a_tex_position;
49    nir_variable *v_tex_position;
50
51    nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_VERTEX, NULL);
52    b.shader->info.name = ralloc_strdup(b.shader, "meta_resolve_vs");
53
54    a_position = nir_variable_create(b.shader, nir_var_shader_in, vec4,
55                                     "a_position");
56    a_position->data.location = VERT_ATTRIB_GENERIC0;
57
58    v_position = nir_variable_create(b.shader, nir_var_shader_out, vec4,
59                                     "gl_Position");
60    v_position->data.location = VARYING_SLOT_POS;
61
62    a_tex_position = nir_variable_create(b.shader, nir_var_shader_in, vec4,
63                                     "a_tex_position");
64    a_tex_position->data.location = VERT_ATTRIB_GENERIC1;
65
66    v_tex_position = nir_variable_create(b.shader, nir_var_shader_out, vec4,
67                                     "v_tex_position");
68    v_tex_position->data.location = VARYING_SLOT_VAR0;
69
70    nir_copy_var(&b, v_position, a_position);
71    nir_copy_var(&b, v_tex_position, a_tex_position);
72
73    return b.shader;
74 }
75
76 static nir_shader *
77 build_nir_fs(uint32_t num_samples)
78 {
79    const struct glsl_type *vec4 = glsl_vec4_type();
80
81    const struct glsl_type *sampler2DMS =
82          glsl_sampler_type(GLSL_SAMPLER_DIM_MS,
83                            /*is_shadow*/ false,
84                            /*is_array*/ false,
85                            GLSL_TYPE_FLOAT);
86
87    nir_builder b;
88    nir_variable *u_tex; /* uniform sampler */
89    nir_variable *v_position; /* vec4, varying fragment position */
90    nir_variable *v_tex_position; /* vec4, varying texture coordinate */
91    nir_variable *f_color; /* vec4, fragment output color */
92    nir_ssa_def *accum; /* vec4, accumulation of sample values */
93
94    nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_FRAGMENT, NULL);
95    b.shader->info.name = ralloc_asprintf(b.shader,
96                                          "meta_resolve_fs_samples%02d",
97                                          num_samples);
98
99    u_tex = nir_variable_create(b.shader, nir_var_uniform, sampler2DMS,
100                                    "u_tex");
101    u_tex->data.descriptor_set = 0;
102    u_tex->data.binding = 0;
103
104    v_position = nir_variable_create(b.shader, nir_var_shader_in, vec4,
105                                      "v_position");
106    v_position->data.location = VARYING_SLOT_POS;
107
108    v_tex_position = nir_variable_create(b.shader, nir_var_shader_in, vec4,
109                                     "v_tex_position");
110    v_tex_position->data.location = VARYING_SLOT_VAR0;
111
112    f_color = nir_variable_create(b.shader, nir_var_shader_out, vec4,
113                                  "f_color");
114    f_color->data.location = FRAG_RESULT_DATA0;
115
116    accum = nir_imm_vec4(&b, 0, 0, 0, 0);
117
118    nir_ssa_def *tex_position_ivec =
119       nir_f2i(&b, nir_load_var(&b, v_tex_position));
120
121    for (uint32_t i = 0; i < num_samples; ++i) {
122       nir_tex_instr *tex;
123
124       tex = nir_tex_instr_create(b.shader, /*num_srcs*/ 2);
125       tex->sampler = nir_deref_var_create(tex, u_tex);
126       tex->sampler_dim = GLSL_SAMPLER_DIM_MS;
127       tex->op = nir_texop_txf_ms;
128       tex->src[0].src = nir_src_for_ssa(tex_position_ivec);
129       tex->src[0].src_type = nir_tex_src_coord;
130       tex->src[1].src = nir_src_for_ssa(nir_imm_int(&b, i));
131       tex->src[1].src_type = nir_tex_src_ms_index;
132       tex->dest_type = nir_type_float;
133       tex->is_array = false;
134       tex->coord_components = 3;
135       nir_ssa_dest_init(&tex->instr, &tex->dest, /*num_components*/ 4, "tex");
136       nir_builder_instr_insert(&b, &tex->instr);
137
138       accum = nir_fadd(&b, accum, &tex->dest.ssa);
139    }
140
141    accum = nir_fdiv(&b, accum, nir_imm_float(&b, num_samples));
142    nir_store_var(&b, f_color, accum, /*writemask*/ 4);
143
144    return b.shader;
145 }
146
147 static VkResult
148 create_pass(struct anv_device *device, VkRenderPass *pass_h)
149 {
150    VkResult result;
151    VkDevice device_h = anv_device_to_handle(device);
152    const VkAllocationCallbacks *alloc = &device->meta_state.alloc;
153
154    result = anv_CreateRenderPass(device_h,
155       &(VkRenderPassCreateInfo) {
156          .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
157          .attachmentCount = 1,
158          .pAttachments = &(VkAttachmentDescription) {
159             .format = VK_FORMAT_UNDEFINED, /* Our shaders don't care */
160             .samples = 1,
161             .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
162             .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
163             .initialLayout = VK_IMAGE_LAYOUT_GENERAL,
164             .finalLayout = VK_IMAGE_LAYOUT_GENERAL,
165          },
166          .subpassCount = 1,
167          .pSubpasses = &(VkSubpassDescription) {
168             .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
169             .inputAttachmentCount = 0,
170             .colorAttachmentCount = 1,
171             .pColorAttachments = &(VkAttachmentReference) {
172                .attachment = 0,
173                .layout = VK_IMAGE_LAYOUT_GENERAL,
174             },
175             .pResolveAttachments = NULL,
176             .pDepthStencilAttachment = &(VkAttachmentReference) {
177                .attachment = VK_ATTACHMENT_UNUSED,
178             },
179             .preserveAttachmentCount = 0,
180             .pPreserveAttachments = NULL,
181          },
182          .dependencyCount = 0,
183       },
184       alloc,
185       pass_h);
186
187    return result;
188 }
189
190 static VkResult
191 create_pipeline(struct anv_device *device,
192                 uint32_t num_samples,
193                 VkShaderModule vs_module_h,
194                 VkRenderPass pass_h,
195                 VkPipeline *pipeline_h)
196 {
197    VkResult result;
198    VkDevice device_h = anv_device_to_handle(device);
199
200    struct anv_shader_module fs_module = {
201       .nir = build_nir_fs(num_samples),
202    };
203
204    if (!fs_module.nir) {
205       /* XXX: Need more accurate error */
206       result = VK_ERROR_OUT_OF_HOST_MEMORY;
207       goto fail;
208    }
209
210    result = anv_graphics_pipeline_create(device_h,
211       VK_NULL_HANDLE,
212       &(VkGraphicsPipelineCreateInfo) {
213          .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
214          .stageCount = 2,
215          .pStages = (VkPipelineShaderStageCreateInfo[]) {
216             {
217                .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
218                .stage = VK_SHADER_STAGE_VERTEX_BIT,
219                .module = vs_module_h,
220                .pName = "main",
221             },
222             {
223                .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
224                .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
225                .module = anv_shader_module_to_handle(&fs_module),
226                .pName = "main",
227             },
228          },
229          .pVertexInputState = &(VkPipelineVertexInputStateCreateInfo) {
230             .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
231             .vertexBindingDescriptionCount = 1,
232             .pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) {
233                {
234                   .binding = 0,
235                   .stride = sizeof(struct vertex_attrs),
236                   .inputRate = VK_VERTEX_INPUT_RATE_VERTEX
237                },
238             },
239             .vertexAttributeDescriptionCount = 3,
240             .pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) {
241                {
242                   /* VUE Header */
243                   .location = 0,
244                   .binding = 0,
245                   .format = VK_FORMAT_R32G32B32A32_UINT,
246                   .offset = offsetof(struct vertex_attrs, vue_header),
247                },
248                {
249                   /* Position */
250                   .location = 1,
251                   .binding = 0,
252                   .format = VK_FORMAT_R32G32_SFLOAT,
253                   .offset = offsetof(struct vertex_attrs, position),
254                },
255                {
256                   /* Texture Coordinate */
257                   .location = 2,
258                   .binding = 0,
259                   .format = VK_FORMAT_R32G32_SFLOAT,
260                   .offset = offsetof(struct vertex_attrs, tex_position),
261                },
262             },
263          },
264          .pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) {
265             .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
266             .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
267             .primitiveRestartEnable = false,
268          },
269          .pViewportState = &(VkPipelineViewportStateCreateInfo) {
270             .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
271             .viewportCount = 1,
272             .scissorCount = 1,
273          },
274          .pRasterizationState = &(VkPipelineRasterizationStateCreateInfo) {
275             .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
276             .depthClampEnable = false,
277             .rasterizerDiscardEnable = false,
278             .polygonMode = VK_POLYGON_MODE_FILL,
279             .cullMode = VK_CULL_MODE_NONE,
280             .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
281          },
282          .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
283             .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
284             .rasterizationSamples = 1,
285             .sampleShadingEnable = false,
286             .pSampleMask = (VkSampleMask[]) { 0x1 },
287             .alphaToCoverageEnable = false,
288             .alphaToOneEnable = false,
289          },
290          .pColorBlendState = &(VkPipelineColorBlendStateCreateInfo) {
291             .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
292             .logicOpEnable = false,
293             .attachmentCount = 1,
294             .pAttachments = (VkPipelineColorBlendAttachmentState []) {
295                {
296                   .colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
297                                     VK_COLOR_COMPONENT_G_BIT |
298                                     VK_COLOR_COMPONENT_B_BIT |
299                                     VK_COLOR_COMPONENT_A_BIT,
300                },
301             },
302          },
303          .pDynamicState = &(VkPipelineDynamicStateCreateInfo) {
304             .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
305             .dynamicStateCount = 2,
306             .pDynamicStates = (VkDynamicState[]) {
307                VK_DYNAMIC_STATE_VIEWPORT,
308                VK_DYNAMIC_STATE_SCISSOR,
309             },
310          },
311          .layout = device->meta_state.resolve.pipeline_layout,
312          .renderPass = pass_h,
313          .subpass = 0,
314       },
315       &(struct anv_graphics_pipeline_create_info) {
316          .color_attachment_count = -1,
317          .use_repclear = false,
318          .disable_viewport = true,
319          .disable_scissor = true,
320          .disable_vs = true,
321          .use_rectlist = true
322       },
323       &device->meta_state.alloc,
324       pipeline_h);
325    if (result != VK_SUCCESS)
326       goto fail;
327
328    goto cleanup;
329
330 fail:
331    *pipeline_h = VK_NULL_HANDLE;
332
333 cleanup:
334    ralloc_free(fs_module.nir);
335    return result;
336 }
337
338 void
339 anv_device_finish_meta_resolve_state(struct anv_device *device)
340 {
341    struct anv_meta_state *state = &device->meta_state;
342    VkDevice device_h = anv_device_to_handle(device);
343    VkRenderPass pass_h = device->meta_state.resolve.pass;
344    VkPipelineLayout pipeline_layout_h = device->meta_state.resolve.pipeline_layout;
345    VkDescriptorSetLayout ds_layout_h = device->meta_state.resolve.ds_layout;
346    const VkAllocationCallbacks *alloc = &device->meta_state.alloc;
347
348    if (pass_h)
349       ANV_CALL(DestroyRenderPass)(device_h, pass_h,
350                                   &device->meta_state.alloc);
351
352    if (pipeline_layout_h)
353       ANV_CALL(DestroyPipelineLayout)(device_h, pipeline_layout_h, alloc);
354
355    if (ds_layout_h)
356       ANV_CALL(DestroyDescriptorSetLayout)(device_h, ds_layout_h, alloc);
357
358    for (uint32_t i = 0; i < ARRAY_SIZE(state->resolve.pipelines); ++i) {
359       VkPipeline pipeline_h = state->resolve.pipelines[i];
360
361       if (pipeline_h) {
362          ANV_CALL(DestroyPipeline)(device_h, pipeline_h, alloc);
363       }
364    }
365 }
366
367 VkResult
368 anv_device_init_meta_resolve_state(struct anv_device *device)
369 {
370    VkResult res = VK_SUCCESS;
371    VkDevice device_h = anv_device_to_handle(device);
372    const VkAllocationCallbacks *alloc = &device->meta_state.alloc;
373
374    const isl_sample_count_mask_t sample_count_mask =
375       isl_device_get_sample_counts(&device->isl_dev);
376
377    zero(device->meta_state.resolve);
378
379    struct anv_shader_module vs_module = { .nir = build_nir_vs() };
380    if (!vs_module.nir) {
381       /* XXX: Need more accurate error */
382       res = VK_ERROR_OUT_OF_HOST_MEMORY;
383       goto fail;
384    }
385
386    VkShaderModule vs_module_h = anv_shader_module_to_handle(&vs_module);
387
388    res = anv_CreateDescriptorSetLayout(device_h,
389       &(VkDescriptorSetLayoutCreateInfo) {
390          .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
391          .bindingCount = 1,
392          .pBindings = (VkDescriptorSetLayoutBinding[]) {
393             {
394                .binding = 0,
395                .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
396                .descriptorCount = 1,
397                .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
398             },
399          },
400       },
401       alloc,
402       &device->meta_state.resolve.ds_layout);
403    if (res != VK_SUCCESS)
404       goto fail;
405
406    res = anv_CreatePipelineLayout(device_h,
407       &(VkPipelineLayoutCreateInfo) {
408          .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
409          .setLayoutCount = 1,
410          .pSetLayouts = (VkDescriptorSetLayout[]) {
411             device->meta_state.resolve.ds_layout,
412          },
413       },
414       alloc,
415       &device->meta_state.resolve.pipeline_layout);
416    if (res != VK_SUCCESS)
417       goto fail;
418
419
420    res = create_pass(device, &device->meta_state.resolve.pass);
421    if (res != VK_SUCCESS)
422       goto fail;
423
424
425    for (uint32_t i = 0;
426         i < ARRAY_SIZE(device->meta_state.resolve.pipelines); ++i) {
427       uint32_t sample_count = 1 << i;
428
429       if (!(sample_count_mask & sample_count))
430          continue;
431
432       res = create_pipeline(device, sample_count, vs_module_h,
433                             device->meta_state.resolve.pass,
434                             &device->meta_state.resolve.pipelines[i]);
435       if (res != VK_SUCCESS)
436          goto fail;
437    }
438
439    goto cleanup;
440
441 fail:
442    anv_device_finish_meta_resolve_state(device);
443
444 cleanup:
445    ralloc_free(vs_module.nir);
446
447    return res;
448 }
449
450 static void
451 emit_resolve(struct anv_cmd_buffer *cmd_buffer,
452              struct anv_image_view *src_iview,
453              const VkOffset2D *src_offset,
454              struct anv_image_view *dest_iview,
455              const VkOffset2D *dest_offset,
456              const VkExtent2D *resolve_extent)
457 {
458    struct anv_device *device = cmd_buffer->device;
459    VkDevice device_h = anv_device_to_handle(device);
460    VkCommandBuffer cmd_buffer_h = anv_cmd_buffer_to_handle(cmd_buffer);
461    const struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
462    const struct anv_image *src_image = src_iview->image;
463    VkDescriptorPool dummy_desc_pool_h = (VkDescriptorPool) 1;
464    uint32_t samples_log2 = ffs(src_image->samples) - 1;
465
466    const struct vertex_attrs vertex_data[3] = {
467       {
468          .vue_header = {0},
469          .position = {
470             dest_offset->x + resolve_extent->width,
471             dest_offset->y + resolve_extent->height,
472          },
473          .tex_position = {
474             src_offset->x + resolve_extent->width,
475             src_offset->y + resolve_extent->height,
476          },
477       },
478       {
479          .vue_header = {0},
480          .position = {
481             dest_offset->x,
482             dest_offset->y + resolve_extent->height,
483          },
484          .tex_position = {
485             src_offset->x,
486             src_offset->y + resolve_extent->height,
487          },
488       },
489       {
490          .vue_header = {0},
491          .position = {
492             dest_offset->x,
493             dest_offset->y,
494          },
495          .tex_position = {
496             src_offset->x,
497             src_offset->y,
498          },
499       },
500    };
501
502    struct anv_state vertex_mem =
503       anv_cmd_buffer_emit_dynamic(cmd_buffer, vertex_data,
504                                   sizeof(vertex_data), 16);
505
506    struct anv_buffer vertex_buffer = {
507       .device = device,
508       .size = sizeof(vertex_data),
509       .bo = &cmd_buffer->dynamic_state_stream.block_pool->bo,
510       .offset = vertex_mem.offset,
511    };
512
513    VkBuffer vertex_buffer_h = anv_buffer_to_handle(&vertex_buffer);
514
515    anv_CmdBindVertexBuffers(cmd_buffer_h,
516       /*firstBinding*/ 0,
517       /*bindingCount*/ 1,
518       (VkBuffer[]) { vertex_buffer_h },
519       (VkDeviceSize[]) { 0 });
520
521    VkSampler sampler_h;
522    ANV_CALL(CreateSampler)(device_h,
523       &(VkSamplerCreateInfo) {
524          .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
525          .magFilter = VK_FILTER_NEAREST,
526          .minFilter = VK_FILTER_NEAREST,
527          .mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST,
528          .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
529          .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
530          .addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
531          .mipLodBias = 0.0,
532          .anisotropyEnable = false,
533          .compareEnable = false,
534          .minLod = 0.0,
535          .maxLod = 0.0,
536          .unnormalizedCoordinates = false,
537       },
538       &cmd_buffer->pool->alloc,
539       &sampler_h);
540
541    VkDescriptorSet desc_set_h;
542    anv_AllocateDescriptorSets(device_h,
543       &(VkDescriptorSetAllocateInfo) {
544          .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
545          .descriptorPool = dummy_desc_pool_h,
546          .descriptorSetCount = 1,
547          .pSetLayouts = (VkDescriptorSetLayout[]) {
548             device->meta_state.blit.ds_layout,
549          },
550       },
551       &desc_set_h);
552
553    ANV_FROM_HANDLE(anv_descriptor_set, desc_set, desc_set_h);
554
555    anv_UpdateDescriptorSets(device_h,
556       /*writeCount*/ 1,
557       (VkWriteDescriptorSet[]) {
558          {
559             .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
560             .dstSet = desc_set_h,
561             .dstBinding = 0,
562             .dstArrayElement = 0,
563             .descriptorCount = 1,
564             .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
565             .pImageInfo = (VkDescriptorImageInfo[]) {
566                {
567                   .sampler = sampler_h,
568                   .imageView = anv_image_view_to_handle(src_iview),
569                   .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
570                },
571             },
572          },
573       },
574       /*copyCount*/ 0,
575       /*copies */ NULL);
576
577    ANV_CALL(CmdSetViewport)(cmd_buffer_h,
578       /*firstViewport*/ 0,
579       /*viewportCount*/ 1,
580       (VkViewport[]) {
581          {
582             .x = 0,
583             .y = 0,
584             .width = fb->width,
585             .height = fb->height,
586             .minDepth = 0.0,
587             .maxDepth = 1.0,
588          },
589       });
590
591    ANV_CALL(CmdSetScissor)(cmd_buffer_h,
592       /*firstScissor*/ 0,
593       /*scissorCount*/ 1,
594       (VkRect2D[]) {
595          {
596             .offset = { 0, 0 },
597             .extent = (VkExtent2D) { fb->width, fb->height },
598          },
599       });
600
601    VkPipeline pipeline_h = device->meta_state.resolve.pipelines[samples_log2];
602    ANV_FROM_HANDLE(anv_pipeline, pipeline, pipeline_h);
603
604    if (cmd_buffer->state.pipeline != pipeline) {
605       anv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
606                           pipeline_h);
607    }
608
609    anv_CmdBindDescriptorSets(cmd_buffer_h,
610       VK_PIPELINE_BIND_POINT_GRAPHICS,
611       device->meta_state.resolve.pipeline_layout,
612       /*firstSet*/ 0,
613       /* setCount */ 1,
614       (VkDescriptorSet[]) {
615          desc_set_h,
616       },
617       /*copyCount*/ 0,
618       /*copies */ NULL);
619
620    ANV_CALL(CmdDraw)(cmd_buffer_h, 3, 1, 0, 0);
621
622    /* All objects below are consumed by the draw call. We may safely destroy
623     * them.
624     */
625    anv_descriptor_set_destroy(device, desc_set);
626    anv_DestroySampler(device_h, sampler_h,
627                       &cmd_buffer->pool->alloc);
628 }
629
630 void anv_CmdResolveImage(
631     VkCommandBuffer                             cmd_buffer_h,
632     VkImage                                     src_image_h,
633     VkImageLayout                               src_image_layout,
634     VkImage                                     dest_image_h,
635     VkImageLayout                               dest_image_layout,
636     uint32_t                                    region_count,
637     const VkImageResolve*                       regions)
638 {
639    ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmd_buffer_h);
640    ANV_FROM_HANDLE(anv_image, src_image, src_image_h);
641    ANV_FROM_HANDLE(anv_image, dest_image, dest_image_h);
642    struct anv_device *device = cmd_buffer->device;
643    struct anv_meta_saved_state state;
644    VkDevice device_h = anv_device_to_handle(device);
645
646    anv_meta_save(&state, cmd_buffer, 0);
647
648    assert(src_image->samples > 1);
649    assert(dest_image->samples == 1);
650
651    if (src_image->samples >= 16) {
652       /* See commit aa3f9aaf31e9056a255f9e0472ebdfdaa60abe54 for the
653        * glBlitFramebuffer workaround for samples >= 16.
654        */
655       anv_finishme("vkCmdResolveImage: need interpolation workaround when "
656                    "samples >= 16");
657    }
658
659    if (src_image->array_size > 1)
660       anv_finishme("vkCmdResolveImage: multisample array images");
661
662    for (uint32_t r = 0; r < region_count; ++r) {
663       const VkImageResolve *region = &regions[r];
664
665       /* From the Vulkan 1.0 spec:
666        *
667        *    - The aspectMask member of srcSubresource and dstSubresource must
668        *      only contain VK_IMAGE_ASPECT_COLOR_BIT
669        *
670        *    - The layerCount member of srcSubresource and dstSubresource must
671        *      match
672        */
673       assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
674       assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
675       assert(region->srcSubresource.layerCount ==
676              region->dstSubresource.layerCount);
677
678       const uint32_t src_base_layer =
679          anv_meta_get_iview_layer(src_image, &region->srcSubresource,
680                                   &region->srcOffset);
681
682       const uint32_t dest_base_layer =
683          anv_meta_get_iview_layer(dest_image, &region->dstSubresource,
684                                   &region->dstOffset);
685
686       for (uint32_t layer = 0; layer < region->srcSubresource.layerCount;
687            ++layer) {
688
689          struct anv_image_view src_iview;
690          anv_image_view_init(&src_iview, cmd_buffer->device,
691             &(VkImageViewCreateInfo) {
692                .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
693                .image = src_image_h,
694                .viewType = anv_meta_get_view_type(src_image),
695                .format = src_image->format->vk_format,
696                .subresourceRange = {
697                   .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
698                   .baseMipLevel = region->srcSubresource.mipLevel,
699                   .levelCount = 1,
700                   .baseArrayLayer = src_base_layer + layer,
701                   .layerCount = 1,
702                },
703             },
704             cmd_buffer, 0);
705
706          struct anv_image_view dest_iview;
707          anv_image_view_init(&dest_iview, cmd_buffer->device,
708             &(VkImageViewCreateInfo) {
709                .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
710                .image = dest_image_h,
711                .viewType = anv_meta_get_view_type(dest_image),
712                .format = dest_image->format->vk_format,
713                .subresourceRange = {
714                   .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
715                   .baseMipLevel = region->dstSubresource.mipLevel,
716                   .levelCount = 1,
717                   .baseArrayLayer = dest_base_layer + layer,
718                   .layerCount = 1,
719                },
720             },
721             cmd_buffer, 0);
722
723          VkFramebuffer fb_h;
724          anv_CreateFramebuffer(device_h,
725             &(VkFramebufferCreateInfo) {
726                .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
727                .attachmentCount = 1,
728                .pAttachments = (VkImageView[]) {
729                   anv_image_view_to_handle(&dest_iview),
730                },
731                .width = anv_minify(dest_image->extent.width,
732                                    region->dstSubresource.mipLevel),
733                .height = anv_minify(dest_image->extent.height,
734                                     region->dstSubresource.mipLevel),
735                .layers = 1
736             },
737             &cmd_buffer->pool->alloc,
738             &fb_h);
739
740          ANV_CALL(CmdBeginRenderPass)(cmd_buffer_h,
741             &(VkRenderPassBeginInfo) {
742                .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
743                .renderPass = device->meta_state.resolve.pass,
744                .framebuffer = fb_h,
745                .renderArea = {
746                   .offset = {
747                      region->dstOffset.x,
748                      region->dstOffset.y,
749                   },
750                   .extent = {
751                      region->extent.width,
752                      region->extent.height,
753                   }
754                },
755                .clearValueCount = 0,
756                .pClearValues = NULL,
757             },
758             VK_SUBPASS_CONTENTS_INLINE);
759
760          emit_resolve(cmd_buffer,
761              &src_iview,
762              &(VkOffset2D) {
763                .x = region->srcOffset.x,
764                .y = region->srcOffset.y,
765              },
766              &dest_iview,
767              &(VkOffset2D) {
768                .x = region->dstOffset.x,
769                .y = region->dstOffset.y,
770              },
771              &(VkExtent2D) {
772                .width = region->extent.width,
773                .height = region->extent.height,
774              });
775
776          ANV_CALL(CmdEndRenderPass)(cmd_buffer_h);
777
778          anv_DestroyFramebuffer(device_h, fb_h,
779                                 &cmd_buffer->pool->alloc);
780       }
781    }
782
783    anv_meta_restore(&state, cmd_buffer);
784 }