OSDN Git Service

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