spirv,nir: add new lod parameter to image_{load,store} intrinsics
[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.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 store->src[4] = nir_src_for_ssa(nir_imm_int(&b, 0));
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 < radv_get_layerCount(image, subresourceRange); 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 = vk_format_no_srgb(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 }, NULL);
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 1, /* 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_STORAGE_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
167 radv_unaligned_dispatch(cmd_buffer, image->info.width, image->info.height, 1);
168 }
169
170 radv_meta_restore(&saved_state, cmd_buffer);
171
172 cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_CS_PARTIAL_FLUSH |
173 RADV_CMD_FLAG_INV_L2;
174
175 /* Re-initialize FMASK in fully expanded mode. */
176 radv_initialize_fmask(cmd_buffer, image, subresourceRange);
177 }
178
179 void radv_device_finish_meta_fmask_expand_state(struct radv_device *device)
180 {
181 struct radv_meta_state *state = &device->meta_state;
182
183 for (uint32_t i = 0; i < MAX_SAMPLES_LOG2; ++i) {
184 radv_DestroyPipeline(radv_device_to_handle(device),
185 state->fmask_expand.pipeline[i],
186 &state->alloc);
187 }
188 radv_DestroyPipelineLayout(radv_device_to_handle(device),
189 state->fmask_expand.p_layout,
190 &state->alloc);
191
192 radv_DestroyDescriptorSetLayout(radv_device_to_handle(device),
193 state->fmask_expand.ds_layout,
194 &state->alloc);
195 }
196
197 static VkResult
198 create_fmask_expand_pipeline(struct radv_device *device,
199 int samples,
200 VkPipeline *pipeline)
201 {
202 struct radv_meta_state *state = &device->meta_state;
203 struct radv_shader_module cs = { .nir = NULL };
204 VkResult result;
205
206 cs.nir = build_fmask_expand_compute_shader(device, samples);
207
208 VkPipelineShaderStageCreateInfo pipeline_shader_stage = {
209 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
210 .stage = VK_SHADER_STAGE_COMPUTE_BIT,
211 .module = radv_shader_module_to_handle(&cs),
212 .pName = "main",
213 .pSpecializationInfo = NULL,
214 };
215
216 VkComputePipelineCreateInfo vk_pipeline_info = {
217 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
218 .stage = pipeline_shader_stage,
219 .flags = 0,
220 .layout = state->fmask_expand.p_layout,
221 };
222
223 result = radv_CreateComputePipelines(radv_device_to_handle(device),
224 radv_pipeline_cache_to_handle(&state->cache),
225 1, &vk_pipeline_info, NULL,
226 pipeline);
227
228 ralloc_free(cs.nir);
229 return result;
230 }
231
232 VkResult
233 radv_device_init_meta_fmask_expand_state(struct radv_device *device)
234 {
235 struct radv_meta_state *state = &device->meta_state;
236 VkResult result;
237
238 VkDescriptorSetLayoutCreateInfo ds_create_info = {
239 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
240 .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,
241 .bindingCount = 1,
242 .pBindings = (VkDescriptorSetLayoutBinding[]) {
243 {
244 .binding = 0,
245 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
246 .descriptorCount = 1,
247 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
248 .pImmutableSamplers = NULL
249 },
250 }
251 };
252
253 result = radv_CreateDescriptorSetLayout(radv_device_to_handle(device),
254 &ds_create_info, &state->alloc,
255 &state->fmask_expand.ds_layout);
256 if (result != VK_SUCCESS)
257 goto fail;
258
259 VkPipelineLayoutCreateInfo color_create_info = {
260 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
261 .setLayoutCount = 1,
262 .pSetLayouts = &state->fmask_expand.ds_layout,
263 .pushConstantRangeCount = 0,
264 .pPushConstantRanges = NULL,
265 };
266
267 result = radv_CreatePipelineLayout(radv_device_to_handle(device),
268 &color_create_info, &state->alloc,
269 &state->fmask_expand.p_layout);
270 if (result != VK_SUCCESS)
271 goto fail;
272
273 for (uint32_t i = 0; i < MAX_SAMPLES_LOG2; i++) {
274 uint32_t samples = 1 << i;
275 result = create_fmask_expand_pipeline(device, samples,
276 &state->fmask_expand.pipeline[i]);
277 if (result != VK_SUCCESS)
278 goto fail;
279 }
280
281 return VK_SUCCESS;
282 fail:
283 radv_device_finish_meta_fmask_expand_state(device);
284 return result;
285 }