• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2015 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  */
6 
7 #include "nir/nir_builder.h"
8 #include "radv_meta.h"
9 #include "vk_command_pool.h"
10 #include "vk_common_entrypoints.h"
11 
12 static nir_shader *
build_nir_vertex_shader(struct radv_device * dev)13 build_nir_vertex_shader(struct radv_device *dev)
14 {
15    const struct glsl_type *vec4 = glsl_vec4_type();
16    nir_builder b = radv_meta_init_shader(dev, MESA_SHADER_VERTEX, "meta_blit_vs");
17 
18    nir_variable *pos_out = nir_variable_create(b.shader, nir_var_shader_out, vec4, "gl_Position");
19    pos_out->data.location = VARYING_SLOT_POS;
20 
21    nir_variable *tex_pos_out = nir_variable_create(b.shader, nir_var_shader_out, vec4, "v_tex_pos");
22    tex_pos_out->data.location = VARYING_SLOT_VAR0;
23    tex_pos_out->data.interpolation = INTERP_MODE_SMOOTH;
24 
25    nir_def *outvec = nir_gen_rect_vertices(&b, NULL, NULL);
26 
27    nir_store_var(&b, pos_out, outvec, 0xf);
28 
29    nir_def *src_box = nir_load_push_constant(&b, 4, 32, nir_imm_int(&b, 0), .range = 16);
30    nir_def *src0_z = nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 0), .base = 16, .range = 4);
31 
32    nir_def *vertex_id = nir_load_vertex_id_zero_base(&b);
33 
34    /* vertex 0 - src0_x, src0_y, src0_z */
35    /* vertex 1 - src0_x, src1_y, src0_z*/
36    /* vertex 2 - src1_x, src0_y, src0_z */
37    /* so channel 0 is vertex_id != 2 ? src_x : src_x + w
38       channel 1 is vertex id != 1 ? src_y : src_y + w */
39 
40    nir_def *c0cmp = nir_ine_imm(&b, vertex_id, 2);
41    nir_def *c1cmp = nir_ine_imm(&b, vertex_id, 1);
42 
43    nir_def *comp[4];
44    comp[0] = nir_bcsel(&b, c0cmp, nir_channel(&b, src_box, 0), nir_channel(&b, src_box, 2));
45 
46    comp[1] = nir_bcsel(&b, c1cmp, nir_channel(&b, src_box, 1), nir_channel(&b, src_box, 3));
47    comp[2] = src0_z;
48    comp[3] = nir_imm_float(&b, 1.0);
49    nir_def *out_tex_vec = nir_vec(&b, comp, 4);
50    nir_store_var(&b, tex_pos_out, out_tex_vec, 0xf);
51    return b.shader;
52 }
53 
54 static nir_shader *
build_nir_copy_fragment_shader(struct radv_device * dev,enum glsl_sampler_dim tex_dim)55 build_nir_copy_fragment_shader(struct radv_device *dev, enum glsl_sampler_dim tex_dim)
56 {
57    const struct glsl_type *vec4 = glsl_vec4_type();
58    nir_builder b = radv_meta_init_shader(dev, MESA_SHADER_FRAGMENT, "meta_blit_fs.%d", tex_dim);
59 
60    nir_variable *tex_pos_in = nir_variable_create(b.shader, nir_var_shader_in, vec4, "v_tex_pos");
61    tex_pos_in->data.location = VARYING_SLOT_VAR0;
62 
63    /* Swizzle the array index which comes in as Z coordinate into the right
64     * position.
65     */
66    unsigned swz[] = {0, (tex_dim == GLSL_SAMPLER_DIM_1D ? 2 : 1), 2};
67    nir_def *const tex_pos =
68       nir_swizzle(&b, nir_load_var(&b, tex_pos_in), swz, (tex_dim == GLSL_SAMPLER_DIM_1D ? 2 : 3));
69 
70    const struct glsl_type *sampler_type =
71       glsl_sampler_type(tex_dim, false, tex_dim != GLSL_SAMPLER_DIM_3D, glsl_get_base_type(vec4));
72    nir_variable *sampler = nir_variable_create(b.shader, nir_var_uniform, sampler_type, "s_tex");
73    sampler->data.descriptor_set = 0;
74    sampler->data.binding = 0;
75 
76    nir_deref_instr *tex_deref = nir_build_deref_var(&b, sampler);
77    nir_def *color = nir_tex_deref(&b, tex_deref, tex_deref, tex_pos);
78 
79    nir_variable *color_out = nir_variable_create(b.shader, nir_var_shader_out, vec4, "f_color");
80    color_out->data.location = FRAG_RESULT_DATA0;
81    nir_store_var(&b, color_out, color, 0xf);
82 
83    return b.shader;
84 }
85 
86 static nir_shader *
build_nir_copy_fragment_shader_depth(struct radv_device * dev,enum glsl_sampler_dim tex_dim)87 build_nir_copy_fragment_shader_depth(struct radv_device *dev, enum glsl_sampler_dim tex_dim)
88 {
89    const struct glsl_type *vec4 = glsl_vec4_type();
90    nir_builder b = radv_meta_init_shader(dev, MESA_SHADER_FRAGMENT, "meta_blit_depth_fs.%d", tex_dim);
91 
92    nir_variable *tex_pos_in = nir_variable_create(b.shader, nir_var_shader_in, vec4, "v_tex_pos");
93    tex_pos_in->data.location = VARYING_SLOT_VAR0;
94 
95    /* Swizzle the array index which comes in as Z coordinate into the right
96     * position.
97     */
98    unsigned swz[] = {0, (tex_dim == GLSL_SAMPLER_DIM_1D ? 2 : 1), 2};
99    nir_def *const tex_pos =
100       nir_swizzle(&b, nir_load_var(&b, tex_pos_in), swz, (tex_dim == GLSL_SAMPLER_DIM_1D ? 2 : 3));
101 
102    const struct glsl_type *sampler_type =
103       glsl_sampler_type(tex_dim, false, tex_dim != GLSL_SAMPLER_DIM_3D, glsl_get_base_type(vec4));
104    nir_variable *sampler = nir_variable_create(b.shader, nir_var_uniform, sampler_type, "s_tex");
105    sampler->data.descriptor_set = 0;
106    sampler->data.binding = 0;
107 
108    nir_deref_instr *tex_deref = nir_build_deref_var(&b, sampler);
109    nir_def *color = nir_tex_deref(&b, tex_deref, tex_deref, tex_pos);
110 
111    nir_variable *color_out = nir_variable_create(b.shader, nir_var_shader_out, vec4, "f_color");
112    color_out->data.location = FRAG_RESULT_DEPTH;
113    nir_store_var(&b, color_out, color, 0x1);
114 
115    return b.shader;
116 }
117 
118 static nir_shader *
build_nir_copy_fragment_shader_stencil(struct radv_device * dev,enum glsl_sampler_dim tex_dim)119 build_nir_copy_fragment_shader_stencil(struct radv_device *dev, enum glsl_sampler_dim tex_dim)
120 {
121    const struct glsl_type *vec4 = glsl_vec4_type();
122    nir_builder b = radv_meta_init_shader(dev, MESA_SHADER_FRAGMENT, "meta_blit_stencil_fs.%d", tex_dim);
123 
124    nir_variable *tex_pos_in = nir_variable_create(b.shader, nir_var_shader_in, vec4, "v_tex_pos");
125    tex_pos_in->data.location = VARYING_SLOT_VAR0;
126 
127    /* Swizzle the array index which comes in as Z coordinate into the right
128     * position.
129     */
130    unsigned swz[] = {0, (tex_dim == GLSL_SAMPLER_DIM_1D ? 2 : 1), 2};
131    nir_def *const tex_pos =
132       nir_swizzle(&b, nir_load_var(&b, tex_pos_in), swz, (tex_dim == GLSL_SAMPLER_DIM_1D ? 2 : 3));
133 
134    const struct glsl_type *sampler_type =
135       glsl_sampler_type(tex_dim, false, tex_dim != GLSL_SAMPLER_DIM_3D, glsl_get_base_type(vec4));
136    nir_variable *sampler = nir_variable_create(b.shader, nir_var_uniform, sampler_type, "s_tex");
137    sampler->data.descriptor_set = 0;
138    sampler->data.binding = 0;
139 
140    nir_deref_instr *tex_deref = nir_build_deref_var(&b, sampler);
141    nir_def *color = nir_tex_deref(&b, tex_deref, tex_deref, tex_pos);
142 
143    nir_variable *color_out = nir_variable_create(b.shader, nir_var_shader_out, vec4, "f_color");
144    color_out->data.location = FRAG_RESULT_STENCIL;
145    nir_store_var(&b, color_out, color, 0x1);
146 
147    return b.shader;
148 }
149 
150 static enum glsl_sampler_dim
translate_sampler_dim(VkImageType type)151 translate_sampler_dim(VkImageType type)
152 {
153    switch (type) {
154    case VK_IMAGE_TYPE_1D:
155       return GLSL_SAMPLER_DIM_1D;
156    case VK_IMAGE_TYPE_2D:
157       return GLSL_SAMPLER_DIM_2D;
158    case VK_IMAGE_TYPE_3D:
159       return GLSL_SAMPLER_DIM_3D;
160    default:
161       unreachable("Unhandled image type");
162    }
163 }
164 
165 static VkResult
get_pipeline_layout(struct radv_device * device,VkPipelineLayout * layout_out)166 get_pipeline_layout(struct radv_device *device, VkPipelineLayout *layout_out)
167 {
168    enum radv_meta_object_key_type key = RADV_META_OBJECT_KEY_BLIT;
169 
170    const VkDescriptorSetLayoutBinding binding = {
171       .binding = 0,
172       .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
173       .descriptorCount = 1,
174       .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
175    };
176 
177    const VkDescriptorSetLayoutCreateInfo desc_info = {
178       .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
179       .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT,
180       .bindingCount = 1,
181       .pBindings = &binding,
182    };
183 
184    const VkPushConstantRange pc_range = {VK_SHADER_STAGE_VERTEX_BIT, 0, 20};
185 
186    return vk_meta_get_pipeline_layout(&device->vk, &device->meta_state.device, &desc_info, &pc_range, &key, sizeof(key),
187                                       layout_out);
188 }
189 
190 struct radv_blit_key {
191    enum radv_meta_object_key_type type;
192    VkImageAspectFlags aspects;
193    VkImageType image_type;
194    uint32_t fs_key;
195 };
196 
197 static VkResult
get_pipeline(struct radv_device * device,const struct radv_image_view * src_iview,const struct radv_image_view * dst_iview,VkPipeline * pipeline_out,VkPipelineLayout * layout_out)198 get_pipeline(struct radv_device *device, const struct radv_image_view *src_iview,
199              const struct radv_image_view *dst_iview, VkPipeline *pipeline_out, VkPipelineLayout *layout_out)
200 {
201    const VkImageAspectFlags aspect = src_iview->vk.aspects;
202    const struct radv_image *src_image = src_iview->image;
203    const struct radv_image *dst_image = dst_iview->image;
204    const enum glsl_sampler_dim tex_dim = translate_sampler_dim(src_image->vk.image_type);
205    struct radv_blit_key key;
206    VkResult result;
207 
208    result = get_pipeline_layout(device, layout_out);
209    if (result != VK_SUCCESS)
210       return result;
211 
212    memset(&key, 0, sizeof(key));
213    key.type = RADV_META_OBJECT_KEY_BLIT;
214    key.aspects = src_image->vk.aspects;
215    key.image_type = src_image->vk.image_type;
216 
217    if (src_image->vk.aspects == VK_IMAGE_ASPECT_COLOR_BIT)
218       key.fs_key = radv_format_meta_fs_key(device, dst_image->vk.format);
219 
220    VkPipeline pipeline_from_cache = vk_meta_lookup_pipeline(&device->meta_state.device, &key, sizeof(key));
221    if (pipeline_from_cache != VK_NULL_HANDLE) {
222       *pipeline_out = pipeline_from_cache;
223       return VK_SUCCESS;
224    }
225 
226    nir_shader *fs;
227    nir_shader *vs = build_nir_vertex_shader(device);
228 
229    switch (aspect) {
230    case VK_IMAGE_ASPECT_COLOR_BIT:
231       fs = build_nir_copy_fragment_shader(device, tex_dim);
232       break;
233    case VK_IMAGE_ASPECT_DEPTH_BIT:
234       fs = build_nir_copy_fragment_shader_depth(device, tex_dim);
235       break;
236    case VK_IMAGE_ASPECT_STENCIL_BIT:
237       fs = build_nir_copy_fragment_shader_stencil(device, tex_dim);
238       break;
239    default:
240       unreachable("Unhandled aspect");
241    }
242 
243    VkGraphicsPipelineCreateInfo pipeline_create_info = {
244       .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
245       .stageCount = 2,
246       .pStages =
247          (VkPipelineShaderStageCreateInfo[]){
248             {.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
249              .stage = VK_SHADER_STAGE_VERTEX_BIT,
250              .module = vk_shader_module_handle_from_nir(vs),
251              .pName = "main",
252              .pSpecializationInfo = NULL},
253             {.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
254              .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
255              .module = vk_shader_module_handle_from_nir(fs),
256              .pName = "main",
257              .pSpecializationInfo = NULL},
258          },
259       .pVertexInputState =
260          &(VkPipelineVertexInputStateCreateInfo){
261             .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
262             .vertexBindingDescriptionCount = 0,
263             .vertexAttributeDescriptionCount = 0,
264          },
265       .pInputAssemblyState =
266          &(VkPipelineInputAssemblyStateCreateInfo){
267             .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
268             .topology = VK_PRIMITIVE_TOPOLOGY_META_RECT_LIST_MESA,
269             .primitiveRestartEnable = false,
270          },
271       .pViewportState =
272          &(VkPipelineViewportStateCreateInfo){
273             .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
274             .viewportCount = 1,
275             .scissorCount = 1,
276          },
277       .pRasterizationState =
278          &(VkPipelineRasterizationStateCreateInfo){.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
279                                                    .rasterizerDiscardEnable = false,
280                                                    .polygonMode = VK_POLYGON_MODE_FILL,
281                                                    .cullMode = VK_CULL_MODE_NONE,
282                                                    .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
283                                                    .lineWidth = 1.0f},
284       .pMultisampleState =
285          &(VkPipelineMultisampleStateCreateInfo){
286             .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
287             .rasterizationSamples = 1,
288             .sampleShadingEnable = false,
289             .pSampleMask = (VkSampleMask[]){UINT32_MAX},
290          },
291       .pDynamicState =
292          &(VkPipelineDynamicStateCreateInfo){
293             .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
294             .dynamicStateCount = 2,
295             .pDynamicStates =
296                (VkDynamicState[]){
297                   VK_DYNAMIC_STATE_VIEWPORT,
298                   VK_DYNAMIC_STATE_SCISSOR,
299                },
300          },
301       .layout = *layout_out,
302    };
303 
304    VkPipelineColorBlendStateCreateInfo color_blend_info = {
305       .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
306       .attachmentCount = 1,
307       .pAttachments =
308          (VkPipelineColorBlendAttachmentState[]){
309             {.colorWriteMask = VK_COLOR_COMPONENT_A_BIT | VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
310                                VK_COLOR_COMPONENT_B_BIT},
311          },
312       .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}};
313 
314    VkPipelineDepthStencilStateCreateInfo depth_info = {
315       .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
316       .depthTestEnable = true,
317       .depthWriteEnable = true,
318       .depthCompareOp = VK_COMPARE_OP_ALWAYS,
319    };
320 
321    VkPipelineDepthStencilStateCreateInfo stencil_info = {
322       .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
323       .depthTestEnable = false,
324       .depthWriteEnable = false,
325       .stencilTestEnable = true,
326       .front = {.failOp = VK_STENCIL_OP_REPLACE,
327                 .passOp = VK_STENCIL_OP_REPLACE,
328                 .depthFailOp = VK_STENCIL_OP_REPLACE,
329                 .compareOp = VK_COMPARE_OP_ALWAYS,
330                 .compareMask = 0xff,
331                 .writeMask = 0xff,
332                 .reference = 0},
333       .back = {.failOp = VK_STENCIL_OP_REPLACE,
334                .passOp = VK_STENCIL_OP_REPLACE,
335                .depthFailOp = VK_STENCIL_OP_REPLACE,
336                .compareOp = VK_COMPARE_OP_ALWAYS,
337                .compareMask = 0xff,
338                .writeMask = 0xff,
339                .reference = 0},
340       .depthCompareOp = VK_COMPARE_OP_ALWAYS,
341    };
342 
343    struct vk_meta_rendering_info render = {0};
344 
345    switch (aspect) {
346    case VK_IMAGE_ASPECT_COLOR_BIT:
347       pipeline_create_info.pColorBlendState = &color_blend_info;
348       render.color_attachment_count = 1;
349       render.color_attachment_formats[0] = radv_fs_key_format_exemplars[key.fs_key];
350       break;
351    case VK_IMAGE_ASPECT_DEPTH_BIT:
352       pipeline_create_info.pDepthStencilState = &depth_info;
353       render.depth_attachment_format = VK_FORMAT_D32_SFLOAT;
354       break;
355    case VK_IMAGE_ASPECT_STENCIL_BIT:
356       pipeline_create_info.pDepthStencilState = &stencil_info;
357       render.stencil_attachment_format = VK_FORMAT_S8_UINT;
358       break;
359    default:
360       unreachable("Unhandled aspect");
361    }
362 
363    result = vk_meta_create_graphics_pipeline(&device->vk, &device->meta_state.device, &pipeline_create_info, &render,
364                                              &key, sizeof(key), pipeline_out);
365 
366    ralloc_free(vs);
367    ralloc_free(fs);
368    return result;
369 }
370 
371 static void
meta_emit_blit(struct radv_cmd_buffer * cmd_buffer,struct radv_image_view * src_iview,VkImageLayout src_image_layout,float src_offset_0[3],float src_offset_1[3],struct radv_image_view * dst_iview,VkImageLayout dst_image_layout,VkRect2D dst_box,VkSampler sampler)372 meta_emit_blit(struct radv_cmd_buffer *cmd_buffer, struct radv_image_view *src_iview, VkImageLayout src_image_layout,
373                float src_offset_0[3], float src_offset_1[3], struct radv_image_view *dst_iview,
374                VkImageLayout dst_image_layout, VkRect2D dst_box, VkSampler sampler)
375 {
376    struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
377    const struct radv_image *src_image = src_iview->image;
378    const struct radv_image *dst_image = dst_iview->image;
379    uint32_t src_width = u_minify(src_image->vk.extent.width, src_iview->vk.base_mip_level);
380    uint32_t src_height = u_minify(src_image->vk.extent.height, src_iview->vk.base_mip_level);
381    uint32_t src_depth = u_minify(src_image->vk.extent.depth, src_iview->vk.base_mip_level);
382    uint32_t dst_width = u_minify(dst_image->vk.extent.width, dst_iview->vk.base_mip_level);
383    uint32_t dst_height = u_minify(dst_image->vk.extent.height, dst_iview->vk.base_mip_level);
384    VkPipelineLayout layout;
385    VkPipeline pipeline;
386    VkResult result;
387 
388    assert(src_image->vk.samples == dst_image->vk.samples);
389 
390    result = get_pipeline(device, src_iview, dst_iview, &pipeline, &layout);
391    if (result != VK_SUCCESS) {
392       vk_command_buffer_set_error(&cmd_buffer->vk, result);
393       return;
394    }
395 
396    float vertex_push_constants[5] = {
397       src_offset_0[0] / (float)src_width,  src_offset_0[1] / (float)src_height, src_offset_1[0] / (float)src_width,
398       src_offset_1[1] / (float)src_height, src_offset_0[2] / (float)src_depth,
399    };
400 
401    vk_common_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer), layout, VK_SHADER_STAGE_VERTEX_BIT, 0, 20,
402                               vertex_push_constants);
403 
404    radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
405 
406    radv_meta_push_descriptor_set(cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, 1,
407                                  (VkWriteDescriptorSet[]){{.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
408                                                            .dstBinding = 0,
409                                                            .dstArrayElement = 0,
410                                                            .descriptorCount = 1,
411                                                            .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
412                                                            .pImageInfo = (VkDescriptorImageInfo[]){
413                                                               {
414                                                                  .sampler = sampler,
415                                                                  .imageView = radv_image_view_to_handle(src_iview),
416                                                                  .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
417                                                               },
418                                                            }}});
419 
420    VkRenderingInfo rendering_info = {
421       .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
422       .flags = VK_RENDERING_INPUT_ATTACHMENT_NO_CONCURRENT_WRITES_BIT_MESA,
423       .renderArea =
424          {
425             .offset = {0, 0},
426             .extent = {dst_width, dst_height},
427          },
428       .layerCount = 1,
429    };
430 
431    VkRenderingAttachmentInfo color_att;
432    if (src_image->vk.aspects == VK_IMAGE_ASPECT_COLOR_BIT) {
433       unsigned dst_layout = radv_meta_dst_layout_from_layout(dst_image_layout);
434 
435       color_att = (VkRenderingAttachmentInfo){
436          .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
437          .imageView = radv_image_view_to_handle(dst_iview),
438          .imageLayout = radv_meta_dst_layout_to_layout(dst_layout),
439          .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
440          .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
441       };
442       rendering_info.colorAttachmentCount = 1;
443       rendering_info.pColorAttachments = &color_att;
444    }
445 
446    VkRenderingAttachmentInfo depth_att;
447    if (src_image->vk.aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
448       enum radv_blit_ds_layout ds_layout = radv_meta_blit_ds_to_type(dst_image_layout);
449 
450       depth_att = (VkRenderingAttachmentInfo){
451          .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
452          .imageView = radv_image_view_to_handle(dst_iview),
453          .imageLayout = radv_meta_blit_ds_to_layout(ds_layout),
454          .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
455          .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
456       };
457       rendering_info.pDepthAttachment = &depth_att;
458    }
459 
460    VkRenderingAttachmentInfo stencil_att;
461    if (src_image->vk.aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
462       enum radv_blit_ds_layout ds_layout = radv_meta_blit_ds_to_type(dst_image_layout);
463 
464       stencil_att = (VkRenderingAttachmentInfo){
465          .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
466          .imageView = radv_image_view_to_handle(dst_iview),
467          .imageLayout = radv_meta_blit_ds_to_layout(ds_layout),
468          .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
469          .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
470       };
471       rendering_info.pStencilAttachment = &stencil_att;
472    }
473 
474    radv_CmdBeginRendering(radv_cmd_buffer_to_handle(cmd_buffer), &rendering_info);
475 
476    radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
477 
478    radv_CmdEndRendering(radv_cmd_buffer_to_handle(cmd_buffer));
479 }
480 
481 static bool
flip_coords(unsigned * src0,unsigned * src1,unsigned * dst0,unsigned * dst1)482 flip_coords(unsigned *src0, unsigned *src1, unsigned *dst0, unsigned *dst1)
483 {
484    bool flip = false;
485    if (*src0 > *src1) {
486       unsigned tmp = *src0;
487       *src0 = *src1;
488       *src1 = tmp;
489       flip = !flip;
490    }
491 
492    if (*dst0 > *dst1) {
493       unsigned tmp = *dst0;
494       *dst0 = *dst1;
495       *dst1 = tmp;
496       flip = !flip;
497    }
498    return flip;
499 }
500 
501 static void
blit_image(struct radv_cmd_buffer * cmd_buffer,struct radv_image * src_image,VkImageLayout src_image_layout,struct radv_image * dst_image,VkImageLayout dst_image_layout,const VkImageBlit2 * region,VkFilter filter)502 blit_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image, VkImageLayout src_image_layout,
503            struct radv_image *dst_image, VkImageLayout dst_image_layout, const VkImageBlit2 *region, VkFilter filter)
504 {
505    struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
506    const VkImageSubresourceLayers *src_res = &region->srcSubresource;
507    const VkImageSubresourceLayers *dst_res = &region->dstSubresource;
508    struct radv_meta_saved_state saved_state;
509    VkSampler sampler;
510 
511    /* From the Vulkan 1.0 spec:
512     *
513     *    vkCmdBlitImage must not be used for multisampled source or
514     *    destination images. Use vkCmdResolveImage for this purpose.
515     */
516    assert(src_image->vk.samples == 1);
517    assert(dst_image->vk.samples == 1);
518 
519    radv_CreateSampler(radv_device_to_handle(device),
520                       &(VkSamplerCreateInfo){
521                          .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
522                          .magFilter = filter,
523                          .minFilter = filter,
524                          .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
525                          .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
526                          .addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
527                       },
528                       &cmd_buffer->vk.pool->alloc, &sampler);
529 
530    /* VK_EXT_conditional_rendering says that blit commands should not be
531     * affected by conditional rendering.
532     */
533    radv_meta_save(&saved_state, cmd_buffer,
534                   RADV_META_SAVE_GRAPHICS_PIPELINE | RADV_META_SAVE_CONSTANTS | RADV_META_SAVE_DESCRIPTORS |
535                      RADV_META_SUSPEND_PREDICATING);
536 
537    unsigned dst_start, dst_end;
538    if (dst_image->vk.image_type == VK_IMAGE_TYPE_3D) {
539       assert(dst_res->baseArrayLayer == 0);
540       dst_start = region->dstOffsets[0].z;
541       dst_end = region->dstOffsets[1].z;
542    } else {
543       dst_start = dst_res->baseArrayLayer;
544       dst_end = dst_start + vk_image_subresource_layer_count(&dst_image->vk, dst_res);
545    }
546 
547    unsigned src_start, src_end;
548    if (src_image->vk.image_type == VK_IMAGE_TYPE_3D) {
549       assert(src_res->baseArrayLayer == 0);
550       src_start = region->srcOffsets[0].z;
551       src_end = region->srcOffsets[1].z;
552    } else {
553       src_start = src_res->baseArrayLayer;
554       src_end = src_start + vk_image_subresource_layer_count(&src_image->vk, src_res);
555    }
556 
557    bool flip_z = flip_coords(&src_start, &src_end, &dst_start, &dst_end);
558    float src_z_step = (float)(src_end - src_start) / (float)(dst_end - dst_start);
559 
560    /* There is no interpolation to the pixel center during
561     * rendering, so add the 0.5 offset ourselves here. */
562    float depth_center_offset = 0;
563    if (src_image->vk.image_type == VK_IMAGE_TYPE_3D)
564       depth_center_offset = 0.5 / (dst_end - dst_start) * (src_end - src_start);
565 
566    if (flip_z) {
567       src_start = src_end;
568       src_z_step *= -1;
569       depth_center_offset *= -1;
570    }
571 
572    unsigned src_x0 = region->srcOffsets[0].x;
573    unsigned src_x1 = region->srcOffsets[1].x;
574    unsigned dst_x0 = region->dstOffsets[0].x;
575    unsigned dst_x1 = region->dstOffsets[1].x;
576 
577    unsigned src_y0 = region->srcOffsets[0].y;
578    unsigned src_y1 = region->srcOffsets[1].y;
579    unsigned dst_y0 = region->dstOffsets[0].y;
580    unsigned dst_y1 = region->dstOffsets[1].y;
581 
582    VkRect2D dst_box;
583    dst_box.offset.x = MIN2(dst_x0, dst_x1);
584    dst_box.offset.y = MIN2(dst_y0, dst_y1);
585    dst_box.extent.width = dst_x1 - dst_x0;
586    dst_box.extent.height = dst_y1 - dst_y0;
587 
588    const VkOffset2D dst_offset_0 = {
589       .x = dst_x0,
590       .y = dst_y0,
591    };
592    const VkOffset2D dst_offset_1 = {
593       .x = dst_x1,
594       .y = dst_y1,
595    };
596 
597    radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1,
598                        &(VkViewport){.x = dst_offset_0.x,
599                                      .y = dst_offset_0.y,
600                                      .width = dst_offset_1.x - dst_offset_0.x,
601                                      .height = dst_offset_1.y - dst_offset_0.y,
602                                      .minDepth = 0.0f,
603                                      .maxDepth = 1.0f});
604 
605    radv_CmdSetScissor(
606       radv_cmd_buffer_to_handle(cmd_buffer), 0, 1,
607       &(VkRect2D){
608          .offset = (VkOffset2D){MIN2(dst_offset_0.x, dst_offset_1.x), MIN2(dst_offset_0.y, dst_offset_1.y)},
609          .extent = (VkExtent2D){abs(dst_offset_1.x - dst_offset_0.x), abs(dst_offset_1.y - dst_offset_0.y)},
610       });
611 
612    const unsigned num_layers = dst_end - dst_start;
613    for (unsigned i = 0; i < num_layers; i++) {
614       struct radv_image_view dst_iview, src_iview;
615 
616       float src_offset_0[3] = {
617          src_x0,
618          src_y0,
619          src_start + i * src_z_step + depth_center_offset,
620       };
621       float src_offset_1[3] = {
622          src_x1,
623          src_y1,
624          src_start + i * src_z_step + depth_center_offset,
625       };
626       const uint32_t dst_array_slice = dst_start + i;
627 
628       /* 3D images have just 1 layer */
629       const uint32_t src_array_slice = src_image->vk.image_type == VK_IMAGE_TYPE_3D ? 0 : src_start + i;
630 
631       radv_image_view_init(&dst_iview, device,
632                            &(VkImageViewCreateInfo){
633                               .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
634                               .image = radv_image_to_handle(dst_image),
635                               .viewType = radv_meta_get_view_type(dst_image),
636                               .format = dst_image->vk.format,
637                               .subresourceRange = {.aspectMask = dst_res->aspectMask,
638                                                    .baseMipLevel = dst_res->mipLevel,
639                                                    .levelCount = 1,
640                                                    .baseArrayLayer = dst_array_slice,
641                                                    .layerCount = 1},
642                            },
643                            NULL);
644       radv_image_view_init(&src_iview, device,
645                            &(VkImageViewCreateInfo){
646                               .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
647                               .image = radv_image_to_handle(src_image),
648                               .viewType = radv_meta_get_view_type(src_image),
649                               .format = src_image->vk.format,
650                               .subresourceRange = {.aspectMask = src_res->aspectMask,
651                                                    .baseMipLevel = src_res->mipLevel,
652                                                    .levelCount = 1,
653                                                    .baseArrayLayer = src_array_slice,
654                                                    .layerCount = 1},
655                            },
656                            NULL);
657       meta_emit_blit(cmd_buffer, &src_iview, src_image_layout, src_offset_0, src_offset_1, &dst_iview, dst_image_layout,
658                      dst_box, sampler);
659 
660       radv_image_view_finish(&dst_iview);
661       radv_image_view_finish(&src_iview);
662    }
663 
664    radv_meta_restore(&saved_state, cmd_buffer);
665 
666    radv_DestroySampler(radv_device_to_handle(device), sampler, &cmd_buffer->vk.pool->alloc);
667 }
668 
669 VKAPI_ATTR void VKAPI_CALL
radv_CmdBlitImage2(VkCommandBuffer commandBuffer,const VkBlitImageInfo2 * pBlitImageInfo)670 radv_CmdBlitImage2(VkCommandBuffer commandBuffer, const VkBlitImageInfo2 *pBlitImageInfo)
671 {
672    VK_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
673    VK_FROM_HANDLE(radv_image, src_image, pBlitImageInfo->srcImage);
674    VK_FROM_HANDLE(radv_image, dst_image, pBlitImageInfo->dstImage);
675 
676    for (unsigned r = 0; r < pBlitImageInfo->regionCount; r++) {
677       blit_image(cmd_buffer, src_image, pBlitImageInfo->srcImageLayout, dst_image, pBlitImageInfo->dstImageLayout,
678                  &pBlitImageInfo->pRegions[r], pBlitImageInfo->filter);
679    }
680 }
681