radv: rename and re-document cache flush flags
[mesa.git] / src / amd / vulkan / radv_meta_fmask_expand.c
1 /*
2 * Copyright © 2019 Valve Corporation
3 * Copyright © 2018 Red Hat
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
25 #include "radv_meta.h"
26 #include "radv_private.h"
27 #include "vk_format.h"
28
29 static nir_shader *
30 build_fmask_expand_compute_shader(struct radv_device *device, int samples)
31 {
32 nir_builder b;
33 char name[64];
34 const struct glsl_type *img_type =
35 glsl_sampler_type(GLSL_SAMPLER_DIM_MS, false, false,
36 GLSL_TYPE_FLOAT);
37
38 snprintf(name, 64, "meta_fmask_expand_cs-%d", samples);
39
40 nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_COMPUTE, NULL);
41 b.shader->info.name = ralloc_strdup(b.shader, name);
42 b.shader->info.cs.local_size[0] = 16;
43 b.shader->info.cs.local_size[1] = 16;
44 b.shader->info.cs.local_size[2] = 1;
45
46 nir_variable *input_img = nir_variable_create(b.shader, nir_var_uniform,
47 img_type, "s_tex");
48 input_img->data.descriptor_set = 0;
49 input_img->data.binding = 0;
50
51 nir_variable *output_img = nir_variable_create(b.shader, nir_var_uniform,
52 img_type, "out_img");
53 output_img->data.descriptor_set = 0;
54 output_img->data.binding = 0;
55 output_img->data.image.access = ACCESS_NON_READABLE;
56
57 nir_ssa_def *invoc_id = nir_load_local_invocation_id(&b);
58 nir_ssa_def *wg_id = nir_load_work_group_id(&b);
59 nir_ssa_def *block_size = nir_imm_ivec4(&b,
60 b.shader->info.cs.local_size[0],
61 b.shader->info.cs.local_size[1],
62 b.shader->info.cs.local_size[2], 0);
63
64 nir_ssa_def *global_id = nir_iadd(&b, nir_imul(&b, wg_id, block_size), invoc_id);
65
66 nir_ssa_def *input_img_deref = &nir_build_deref_var(&b, input_img)->dest.ssa;
67 nir_ssa_def *output_img_deref = &nir_build_deref_var(&b, output_img)->dest.ssa;
68
69 nir_tex_instr *tex_instr[8];
70 for (uint32_t i = 0; i < samples; i++) {
71 tex_instr[i] = nir_tex_instr_create(b.shader, 3);
72
73 nir_tex_instr *tex = tex_instr[i];
74 tex->sampler_dim = GLSL_SAMPLER_DIM_MS;
75 tex->op = nir_texop_txf_ms;
76 tex->src[0].src_type = nir_tex_src_coord;
77 tex->src[0].src = nir_src_for_ssa(nir_channels(&b, global_id, 0x3));
78 tex->src[1].src_type = nir_tex_src_ms_index;
79 tex->src[1].src = nir_src_for_ssa(nir_imm_int(&b, i));
80 tex->src[2].src_type = nir_tex_src_texture_deref;
81 tex->src[2].src = nir_src_for_ssa(input_img_deref);
82 tex->dest_type = nir_type_float;
83 tex->is_array = false;
84 tex->coord_components = 2;
85
86 nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, "tex");
87 nir_builder_instr_insert(&b, &tex->instr);
88 }
89
90 for (uint32_t i = 0; i < samples; i++) {
91 nir_ssa_def *outval = &tex_instr[i]->dest.ssa;
92
93 nir_intrinsic_instr *store =
94 nir_intrinsic_instr_create(b.shader,
95 nir_intrinsic_image_deref_store);
96 store->num_components = 4;
97 store->src[0] = nir_src_for_ssa(output_img_deref);
98 store->src[1] = nir_src_for_ssa(global_id);
99 store->src[2] = nir_src_for_ssa(nir_imm_int(&b, i));
100 store->src[3] = nir_src_for_ssa(outval);
101 nir_builder_instr_insert(&b, &store->instr);
102 }
103
104 return b.shader;
105 }
106
107 void
108 radv_expand_fmask_image_inplace(struct radv_cmd_buffer *cmd_buffer,
109 struct radv_image *image,
110 const VkImageSubresourceRange *subresourceRange)
111 {
112 struct radv_device *device = cmd_buffer->device;
113 struct radv_meta_saved_state saved_state;
114 const uint32_t samples = image->info.samples;
115 const uint32_t samples_log2 = ffs(samples) - 1;
116
117 radv_meta_save(&saved_state, cmd_buffer,
118 RADV_META_SAVE_COMPUTE_PIPELINE |
119 RADV_META_SAVE_DESCRIPTORS);
120
121 VkPipeline pipeline = device->meta_state.fmask_expand.pipeline[samples_log2];
122
123 radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer),
124 VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
125
126 for (unsigned l = 0; l < subresourceRange->layerCount; l++) {
127 struct radv_image_view iview;
128
129 radv_image_view_init(&iview, device,
130 &(VkImageViewCreateInfo) {
131 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
132 .image = radv_image_to_handle(image),
133 .viewType = radv_meta_get_view_type(image),
134 .format = vk_format_no_srgb(image->vk_format),
135 .subresourceRange = {
136 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
137 .baseMipLevel = 0,
138 .levelCount = 1,
139 .baseArrayLayer = subresourceRange->baseArrayLayer + l,
140 .layerCount = 1,
141 },
142 });
143
144 radv_meta_push_descriptor_set(cmd_buffer,
145 VK_PIPELINE_BIND_POINT_COMPUTE,
146 cmd_buffer->device->meta_state.fmask_expand.p_layout,
147 0, /* set */
148 1, /* descriptorWriteCount */
149 (VkWriteDescriptorSet[]) {
150 {
151 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
152 .dstBinding = 0,
153 .dstArrayElement = 0,
154 .descriptorCount = 1,
155 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
156 .pImageInfo = (VkDescriptorImageInfo[]) {
157 {
158 .sampler = VK_NULL_HANDLE,
159 .imageView = radv_image_view_to_handle(&iview),
160 .imageLayout = VK_IMAGE_LAYOUT_GENERAL
161 },
162 }
163 }
164 });
165
166 radv_unaligned_dispatch(cmd_buffer, image->info.width, image->info.height, 1);
167 }
168
169 radv_meta_restore(&saved_state, cmd_buffer);
170
171 cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_CS_PARTIAL_FLUSH |
172 RADV_CMD_FLAG_INV_L2;
173
174 /* Re-initialize FMASK in fully expanded mode. */
175 radv_initialize_fmask(cmd_buffer, image, subresourceRange);
176 }
177
178 void radv_device_finish_meta_fmask_expand_state(struct radv_device *device)
179 {
180 struct radv_meta_state *state = &device->meta_state;
181
182 for (uint32_t i = 0; i < MAX_SAMPLES_LOG2; ++i) {
183 radv_DestroyPipeline(radv_device_to_handle(device),
184 state->fmask_expand.pipeline[i],
185 &state->alloc);
186 }
187 radv_DestroyPipelineLayout(radv_device_to_handle(device),
188 state->fmask_expand.p_layout,
189 &state->alloc);
190
191 radv_DestroyDescriptorSetLayout(radv_device_to_handle(device),
192 state->fmask_expand.ds_layout,
193 &state->alloc);
194 }
195
196 static VkResult
197 create_fmask_expand_pipeline(struct radv_device *device,
198 int samples,
199 VkPipeline *pipeline)
200 {
201 struct radv_meta_state *state = &device->meta_state;
202 struct radv_shader_module cs = { .nir = NULL };
203 VkResult result;
204
205 cs.nir = build_fmask_expand_compute_shader(device, samples);
206
207 VkPipelineShaderStageCreateInfo pipeline_shader_stage = {
208 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
209 .stage = VK_SHADER_STAGE_COMPUTE_BIT,
210 .module = radv_shader_module_to_handle(&cs),
211 .pName = "main",
212 .pSpecializationInfo = NULL,
213 };
214
215 VkComputePipelineCreateInfo vk_pipeline_info = {
216 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
217 .stage = pipeline_shader_stage,
218 .flags = 0,
219 .layout = state->fmask_expand.p_layout,
220 };
221
222 result = radv_CreateComputePipelines(radv_device_to_handle(device),
223 radv_pipeline_cache_to_handle(&state->cache),
224 1, &vk_pipeline_info, NULL,
225 pipeline);
226
227 ralloc_free(cs.nir);
228 return result;
229 }
230
231 VkResult
232 radv_device_init_meta_fmask_expand_state(struct radv_device *device)
233 {
234 struct radv_meta_state *state = &device->meta_state;
235 VkResult result;
236
237 VkDescriptorSetLayoutCreateInfo ds_create_info = {
238 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
239 .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,
240 .bindingCount = 1,
241 .pBindings = (VkDescriptorSetLayoutBinding[]) {
242 {
243 .binding = 0,
244 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
245 .descriptorCount = 1,
246 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
247 .pImmutableSamplers = NULL
248 },
249 }
250 };
251
252 result = radv_CreateDescriptorSetLayout(radv_device_to_handle(device),
253 &ds_create_info, &state->alloc,
254 &state->fmask_expand.ds_layout);
255 if (result != VK_SUCCESS)
256 goto fail;
257
258 VkPipelineLayoutCreateInfo color_create_info = {
259 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
260 .setLayoutCount = 1,
261 .pSetLayouts = &state->fmask_expand.ds_layout,
262 .pushConstantRangeCount = 0,
263 .pPushConstantRanges = NULL,
264 };
265
266 result = radv_CreatePipelineLayout(radv_device_to_handle(device),
267 &color_create_info, &state->alloc,
268 &state->fmask_expand.p_layout);
269 if (result != VK_SUCCESS)
270 goto fail;
271
272 for (uint32_t i = 0; i < MAX_SAMPLES_LOG2; i++) {
273 uint32_t samples = 1 << i;
274 result = create_fmask_expand_pipeline(device, samples,
275 &state->fmask_expand.pipeline[i]);
276 if (result != VK_SUCCESS)
277 goto fail;
278 }
279
280 return VK_SUCCESS;
281 fail:
282 radv_device_finish_meta_fmask_expand_state(device);
283 return result;
284 }