OSDN Git Service

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