OSDN Git Service

radv: add missing license file to radv_meta_bufimage.
[android-x86/external-mesa.git] / src / amd / vulkan / radv_meta_bufimage.c
1 /*
2  * Copyright © 2016 Red Hat.
3  * Copyright © 2016 Bas Nieuwenhuizen
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24 #include "radv_meta.h"
25 #include "nir/nir_builder.h"
26
27 /*
28  * Compute shader implementation of image->buffer copy.
29  */
30
31 static nir_shader *
32 build_nir_itob_compute_shader(struct radv_device *dev)
33 {
34         nir_builder b;
35         const struct glsl_type *sampler_type = glsl_sampler_type(GLSL_SAMPLER_DIM_2D,
36                                                                  false,
37                                                                  false,
38                                                                  GLSL_TYPE_FLOAT);
39         const struct glsl_type *img_type = glsl_sampler_type(GLSL_SAMPLER_DIM_BUF,
40                                                              false,
41                                                              false,
42                                                              GLSL_TYPE_FLOAT);
43         nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_COMPUTE, NULL);
44         b.shader->info.name = ralloc_strdup(b.shader, "meta_itob_cs");
45         b.shader->info.cs.local_size[0] = 16;
46         b.shader->info.cs.local_size[1] = 16;
47         b.shader->info.cs.local_size[2] = 1;
48         nir_variable *input_img = nir_variable_create(b.shader, nir_var_uniform,
49                                                       sampler_type, "s_tex");
50         input_img->data.descriptor_set = 0;
51         input_img->data.binding = 0;
52
53         nir_variable *output_img = nir_variable_create(b.shader, nir_var_uniform,
54                                                        img_type, "out_img");
55         output_img->data.descriptor_set = 0;
56         output_img->data.binding = 1;
57
58         nir_ssa_def *invoc_id = nir_load_system_value(&b, nir_intrinsic_load_local_invocation_id, 0);
59         nir_ssa_def *wg_id = nir_load_system_value(&b, nir_intrinsic_load_work_group_id, 0);
60         nir_ssa_def *block_size = nir_imm_ivec4(&b,
61                                                 b.shader->info.cs.local_size[0],
62                                                 b.shader->info.cs.local_size[1],
63                                                 b.shader->info.cs.local_size[2], 0);
64
65         nir_ssa_def *global_id = nir_iadd(&b, nir_imul(&b, wg_id, block_size), invoc_id);
66
67
68
69         nir_intrinsic_instr *offset = nir_intrinsic_instr_create(b.shader, nir_intrinsic_load_push_constant);
70         offset->src[0] = nir_src_for_ssa(nir_imm_int(&b, 0));
71         offset->num_components = 2;
72         nir_ssa_dest_init(&offset->instr, &offset->dest, 2, 32, "offset");
73         nir_builder_instr_insert(&b, &offset->instr);
74
75         nir_intrinsic_instr *stride = nir_intrinsic_instr_create(b.shader, nir_intrinsic_load_push_constant);
76         stride->src[0] = nir_src_for_ssa(nir_imm_int(&b, 8));
77         stride->num_components = 1;
78         nir_ssa_dest_init(&stride->instr, &stride->dest, 1, 32, "stride");
79         nir_builder_instr_insert(&b, &stride->instr);
80
81         nir_ssa_def *img_coord = nir_iadd(&b, global_id, &offset->dest.ssa);
82
83         nir_tex_instr *tex = nir_tex_instr_create(b.shader, 2);
84         tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
85         tex->op = nir_texop_txf;
86         tex->src[0].src_type = nir_tex_src_coord;
87         tex->src[0].src = nir_src_for_ssa(img_coord);
88         tex->src[1].src_type = nir_tex_src_lod;
89         tex->src[1].src = nir_src_for_ssa(nir_imm_int(&b, 0));
90         tex->dest_type = nir_type_float;
91         tex->is_array = false;
92         tex->coord_components = 2;
93         tex->texture = nir_deref_var_create(tex, input_img);
94         tex->sampler = NULL;
95
96         nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, "tex");
97         nir_builder_instr_insert(&b, &tex->instr);
98
99         nir_ssa_def *pos_x = nir_channel(&b, global_id, 0);
100         nir_ssa_def *pos_y = nir_channel(&b, global_id, 1);
101
102         nir_ssa_def *tmp = nir_imul(&b, pos_y, &stride->dest.ssa);
103         tmp = nir_iadd(&b, tmp, pos_x);
104
105         nir_ssa_def *coord = nir_vec4(&b, tmp, tmp, tmp, tmp);
106
107         nir_ssa_def *outval = &tex->dest.ssa;
108         nir_intrinsic_instr *store = nir_intrinsic_instr_create(b.shader, nir_intrinsic_image_store);
109         store->src[0] = nir_src_for_ssa(coord);
110         store->src[1] = nir_src_for_ssa(nir_ssa_undef(&b, 1, 32));
111         store->src[2] = nir_src_for_ssa(outval);
112         store->variables[0] = nir_deref_var_create(store, output_img);
113
114         nir_builder_instr_insert(&b, &store->instr);
115         return b.shader;
116 }
117
118 /* Image to buffer - don't write use image accessors */
119 static VkResult
120 radv_device_init_meta_itob_state(struct radv_device *device)
121 {
122         VkResult result;
123         struct radv_shader_module cs = { .nir = NULL };
124
125         zero(device->meta_state.itob);
126
127         cs.nir = build_nir_itob_compute_shader(device);
128
129         /*
130          * two descriptors one for the image being sampled
131          * one for the buffer being written.
132          */
133         VkDescriptorSetLayoutCreateInfo ds_create_info = {
134                 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
135                 .bindingCount = 2,
136                 .pBindings = (VkDescriptorSetLayoutBinding[]) {
137                         {
138                                 .binding = 0,
139                                 .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
140                                 .descriptorCount = 1,
141                                 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
142                                 .pImmutableSamplers = NULL
143                         },
144                         {
145                                 .binding = 1,
146                                 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
147                                 .descriptorCount = 1,
148                                 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
149                                 .pImmutableSamplers = NULL
150                         },
151                 }
152         };
153
154         result = radv_CreateDescriptorSetLayout(radv_device_to_handle(device),
155                                                 &ds_create_info,
156                                                 &device->meta_state.alloc,
157                                                 &device->meta_state.itob.img_ds_layout);
158         if (result != VK_SUCCESS)
159                 goto fail;
160
161
162         VkPipelineLayoutCreateInfo pl_create_info = {
163                 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
164                 .setLayoutCount = 1,
165                 .pSetLayouts = &device->meta_state.itob.img_ds_layout,
166                 .pushConstantRangeCount = 1,
167                 .pPushConstantRanges = &(VkPushConstantRange){VK_SHADER_STAGE_COMPUTE_BIT, 0, 12},
168         };
169
170         result = radv_CreatePipelineLayout(radv_device_to_handle(device),
171                                           &pl_create_info,
172                                           &device->meta_state.alloc,
173                                           &device->meta_state.itob.img_p_layout);
174         if (result != VK_SUCCESS)
175                 goto fail;
176
177         /* compute shader */
178
179         VkPipelineShaderStageCreateInfo pipeline_shader_stage = {
180                 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
181                 .stage = VK_SHADER_STAGE_COMPUTE_BIT,
182                 .module = radv_shader_module_to_handle(&cs),
183                 .pName = "main",
184                 .pSpecializationInfo = NULL,
185         };
186
187         VkComputePipelineCreateInfo vk_pipeline_info = {
188                 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
189                 .stage = pipeline_shader_stage,
190                 .flags = 0,
191                 .layout = device->meta_state.itob.img_p_layout,
192         };
193
194         result = radv_CreateComputePipelines(radv_device_to_handle(device),
195                                              radv_pipeline_cache_to_handle(&device->meta_state.cache),
196                                              1, &vk_pipeline_info, NULL,
197                                              &device->meta_state.itob.pipeline);
198         if (result != VK_SUCCESS)
199                 goto fail;
200
201         ralloc_free(cs.nir);
202         return VK_SUCCESS;
203 fail:
204         ralloc_free(cs.nir);
205         return result;
206 }
207
208 static void
209 radv_device_finish_meta_itob_state(struct radv_device *device)
210 {
211         if (device->meta_state.itob.img_p_layout) {
212                 radv_DestroyPipelineLayout(radv_device_to_handle(device),
213                                            device->meta_state.itob.img_p_layout,
214                                            &device->meta_state.alloc);
215         }
216         if (device->meta_state.itob.img_ds_layout) {
217                 radv_DestroyDescriptorSetLayout(radv_device_to_handle(device),
218                                                 device->meta_state.itob.img_ds_layout,
219                                                 &device->meta_state.alloc);
220         }
221         if (device->meta_state.itob.pipeline) {
222                 radv_DestroyPipeline(radv_device_to_handle(device),
223                                      device->meta_state.itob.pipeline,
224                                      &device->meta_state.alloc);
225         }
226 }
227
228 void
229 radv_device_finish_meta_bufimage_state(struct radv_device *device)
230 {
231         radv_device_finish_meta_itob_state(device);
232 }
233
234 VkResult
235 radv_device_init_meta_bufimage_state(struct radv_device *device)
236 {
237         VkResult result;
238
239         result = radv_device_init_meta_itob_state(device);
240         if (result != VK_SUCCESS)
241                 return result;
242         return VK_SUCCESS;
243 }
244
245 void
246 radv_meta_begin_bufimage(struct radv_cmd_buffer *cmd_buffer,
247                          struct radv_meta_saved_compute_state *save)
248 {
249         radv_meta_save_compute(save, cmd_buffer, 12);
250 }
251
252 void
253 radv_meta_end_bufimage(struct radv_cmd_buffer *cmd_buffer,
254                        struct radv_meta_saved_compute_state *save)
255 {
256         radv_meta_restore_compute(save, cmd_buffer, 12);
257 }
258
259 static void
260 create_iview(struct radv_cmd_buffer *cmd_buffer,
261              struct radv_meta_blit2d_surf *surf,
262              VkImageUsageFlags usage,
263              struct radv_image_view *iview)
264 {
265
266         radv_image_view_init(iview, cmd_buffer->device,
267                              &(VkImageViewCreateInfo) {
268                                      .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
269                                              .image = radv_image_to_handle(surf->image),
270                                              .viewType = VK_IMAGE_VIEW_TYPE_2D,
271                                              .format = surf->format,
272                                              .subresourceRange = {
273                                              .aspectMask = surf->aspect_mask,
274                                              .baseMipLevel = surf->level,
275                                              .levelCount = 1,
276                                              .baseArrayLayer = surf->layer,
277                                              .layerCount = 1
278                                      },
279                                              }, cmd_buffer, usage);
280 }
281
282 static void
283 create_bview(struct radv_cmd_buffer *cmd_buffer,
284              struct radv_buffer *buffer,
285              unsigned offset,
286              VkFormat format,
287              struct radv_buffer_view *bview)
288 {
289         radv_buffer_view_init(bview, cmd_buffer->device,
290                               &(VkBufferViewCreateInfo) {
291                                       .sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
292                                       .flags = 0,
293                                       .buffer = radv_buffer_to_handle(buffer),
294                                       .format = format,
295                                       .offset = offset,
296                                       .range = VK_WHOLE_SIZE,
297                               }, cmd_buffer);
298
299 }
300
301 struct itob_temps {
302         struct radv_image_view src_iview;
303
304         struct radv_buffer_view dst_bview;
305         VkDescriptorSet set;
306 };
307
308 static void
309 itob_bind_src_image(struct radv_cmd_buffer *cmd_buffer,
310                    struct radv_meta_blit2d_surf *src,
311                    struct radv_meta_blit2d_rect *rect,
312                    struct itob_temps *tmp)
313 {
314         create_iview(cmd_buffer, src, VK_IMAGE_USAGE_SAMPLED_BIT, &tmp->src_iview);
315 }
316
317 static void
318 itob_bind_dst_buffer(struct radv_cmd_buffer *cmd_buffer,
319                      struct radv_meta_blit2d_buffer *dst,
320                      struct radv_meta_blit2d_rect *rect,
321                      struct itob_temps *tmp)
322 {
323         create_bview(cmd_buffer, dst->buffer, dst->offset, dst->format, &tmp->dst_bview);
324 }
325
326 static void
327 itob_bind_descriptors(struct radv_cmd_buffer *cmd_buffer,
328                       struct itob_temps *tmp)
329 {
330         struct radv_device *device = cmd_buffer->device;
331         VkDevice vk_device = radv_device_to_handle(cmd_buffer->device);
332
333         radv_temp_descriptor_set_create(device, cmd_buffer,
334                                         device->meta_state.itob.img_ds_layout,
335                                         &tmp->set);
336
337         radv_UpdateDescriptorSets(vk_device,
338                                   2, /* writeCount */
339                                   (VkWriteDescriptorSet[]) {
340                                           {
341                                                   .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
342                                                   .dstSet = tmp->set,
343                                                   .dstBinding = 0,
344                                                   .dstArrayElement = 0,
345                                                   .descriptorCount = 1,
346                                                   .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
347                                                   .pImageInfo = (VkDescriptorImageInfo[]) {
348                                                           {
349                                                                   .sampler = NULL,
350                                                                   .imageView = radv_image_view_to_handle(&tmp->src_iview),
351                                                                   .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
352                                                           },
353                                                   }
354                                           },
355                                           {
356                                                   .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
357                                                   .dstSet = tmp->set,
358                                                   .dstBinding = 1,
359                                                   .dstArrayElement = 0,
360                                                   .descriptorCount = 1,
361                                                   .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
362                                                   .pTexelBufferView = (VkBufferView[])  { radv_buffer_view_to_handle(&tmp->dst_bview) },
363                                           }
364                                   }, 0, NULL);
365
366         radv_CmdBindDescriptorSets(radv_cmd_buffer_to_handle(cmd_buffer),
367                                    VK_PIPELINE_BIND_POINT_COMPUTE,
368                                    device->meta_state.itob.img_p_layout, 0, 1,
369                                    &tmp->set, 0, NULL);
370 }
371
372 static void
373 itob_unbind_src_image(struct radv_cmd_buffer *cmd_buffer,
374                       struct itob_temps *temps)
375 {
376 }
377
378 static void
379 bind_pipeline(struct radv_cmd_buffer *cmd_buffer)
380 {
381         VkPipeline pipeline =
382                 cmd_buffer->device->meta_state.itob.pipeline;
383
384         if (cmd_buffer->state.compute_pipeline != radv_pipeline_from_handle(pipeline)) {
385                 radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer),
386                                      VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
387         }
388 }
389
390 void
391 radv_meta_image_to_buffer(struct radv_cmd_buffer *cmd_buffer,
392                           struct radv_meta_blit2d_surf *src,
393                           struct radv_meta_blit2d_buffer *dst,
394                           unsigned num_rects,
395                           struct radv_meta_blit2d_rect *rects)
396 {
397         struct radv_device *device = cmd_buffer->device;
398
399         for (unsigned r = 0; r < num_rects; ++r) {
400                 struct itob_temps temps;
401
402                 itob_bind_src_image(cmd_buffer, src, &rects[r], &temps);
403                 itob_bind_dst_buffer(cmd_buffer, dst, &rects[r], &temps);
404                 itob_bind_descriptors(cmd_buffer, &temps);
405
406                 bind_pipeline(cmd_buffer);
407
408                 unsigned push_constants[3] = {
409                         rects[r].src_x,
410                         rects[r].src_y,
411                         dst->pitch
412                 };
413                 radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
414                                       device->meta_state.itob.img_p_layout,
415                                       VK_SHADER_STAGE_COMPUTE_BIT, 0, 12,
416                                       push_constants);
417
418                 radv_unaligned_dispatch(cmd_buffer, rects[r].width, rects[r].height, 1);
419                 radv_temp_descriptor_set_destroy(cmd_buffer->device, temps.set);
420                 itob_unbind_src_image(cmd_buffer, &temps);
421         }
422
423 }