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