radv: handle layered fast clears.
[mesa.git] / src / amd / vulkan / radv_meta_fast_clear.c
1 /*
2 * Copyright © 2016 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include <assert.h>
25 #include <stdbool.h>
26
27 #include "radv_meta.h"
28 #include "radv_private.h"
29 #include "nir/nir_builder.h"
30 #include "sid.h"
31 /**
32 * Vertex attributes used by all pipelines.
33 */
34 struct vertex_attrs {
35 float position[2]; /**< 3DPRIM_RECTLIST */
36 };
37
38 /* passthrough vertex shader */
39 static nir_shader *
40 build_nir_vs(void)
41 {
42 const struct glsl_type *vec4 = glsl_vec4_type();
43
44 nir_builder b;
45 nir_variable *a_position;
46 nir_variable *v_position;
47
48 nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_VERTEX, NULL);
49 b.shader->info->name = ralloc_strdup(b.shader, "meta_fast_clear_vs");
50
51 a_position = nir_variable_create(b.shader, nir_var_shader_in, vec4,
52 "a_position");
53 a_position->data.location = VERT_ATTRIB_GENERIC0;
54
55 v_position = nir_variable_create(b.shader, nir_var_shader_out, vec4,
56 "gl_Position");
57 v_position->data.location = VARYING_SLOT_POS;
58
59 nir_copy_var(&b, v_position, a_position);
60
61 return b.shader;
62 }
63
64 /* simple passthrough shader */
65 static nir_shader *
66 build_nir_fs(void)
67 {
68 nir_builder b;
69
70 nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_FRAGMENT, NULL);
71 b.shader->info->name = ralloc_asprintf(b.shader,
72 "meta_fast_clear_noop_fs");
73
74 return b.shader;
75 }
76
77 static VkResult
78 create_pass(struct radv_device *device)
79 {
80 VkResult result;
81 VkDevice device_h = radv_device_to_handle(device);
82 const VkAllocationCallbacks *alloc = &device->meta_state.alloc;
83 VkAttachmentDescription attachment;
84
85 attachment.format = VK_FORMAT_UNDEFINED;
86 attachment.samples = 1;
87 attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
88 attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
89 attachment.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
90 attachment.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
91
92 result = radv_CreateRenderPass(device_h,
93 &(VkRenderPassCreateInfo) {
94 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
95 .attachmentCount = 1,
96 .pAttachments = &attachment,
97 .subpassCount = 1,
98 .pSubpasses = &(VkSubpassDescription) {
99 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
100 .inputAttachmentCount = 0,
101 .colorAttachmentCount = 1,
102 .pColorAttachments = (VkAttachmentReference[]) {
103 {
104 .attachment = 0,
105 .layout = VK_IMAGE_LAYOUT_GENERAL,
106 },
107 },
108 .pResolveAttachments = NULL,
109 .pDepthStencilAttachment = &(VkAttachmentReference) {
110 .attachment = VK_ATTACHMENT_UNUSED,
111 },
112 .preserveAttachmentCount = 0,
113 .pPreserveAttachments = NULL,
114 },
115 .dependencyCount = 0,
116 },
117 alloc,
118 &device->meta_state.fast_clear_flush.pass);
119
120 return result;
121 }
122
123 static VkResult
124 create_pipeline(struct radv_device *device,
125 VkShaderModule vs_module_h)
126 {
127 VkResult result;
128 VkDevice device_h = radv_device_to_handle(device);
129
130 struct radv_shader_module fs_module = {
131 .nir = build_nir_fs(),
132 };
133
134 if (!fs_module.nir) {
135 /* XXX: Need more accurate error */
136 result = VK_ERROR_OUT_OF_HOST_MEMORY;
137 goto cleanup;
138 }
139
140 const VkPipelineShaderStageCreateInfo stages[2] = {
141 {
142 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
143 .stage = VK_SHADER_STAGE_VERTEX_BIT,
144 .module = vs_module_h,
145 .pName = "main",
146 },
147 {
148 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
149 .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
150 .module = radv_shader_module_to_handle(&fs_module),
151 .pName = "main",
152 },
153 };
154
155 const VkPipelineVertexInputStateCreateInfo vi_state = {
156 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
157 .vertexBindingDescriptionCount = 1,
158 .pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) {
159 {
160 .binding = 0,
161 .stride = sizeof(struct vertex_attrs),
162 .inputRate = VK_VERTEX_INPUT_RATE_VERTEX
163 },
164 },
165 .vertexAttributeDescriptionCount = 1,
166 .pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) {
167 {
168 /* Position */
169 .location = 0,
170 .binding = 0,
171 .format = VK_FORMAT_R32G32_SFLOAT,
172 .offset = offsetof(struct vertex_attrs, position),
173 },
174 }
175 };
176
177 const VkPipelineInputAssemblyStateCreateInfo ia_state = {
178 .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
179 .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
180 .primitiveRestartEnable = false,
181 };
182
183 const VkPipelineColorBlendStateCreateInfo blend_state = {
184 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
185 .logicOpEnable = false,
186 .attachmentCount = 1,
187 .pAttachments = (VkPipelineColorBlendAttachmentState []) {
188 {
189 .colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
190 VK_COLOR_COMPONENT_G_BIT |
191 VK_COLOR_COMPONENT_B_BIT |
192 VK_COLOR_COMPONENT_A_BIT,
193 },
194 }
195 };
196 const VkPipelineRasterizationStateCreateInfo rs_state = {
197 .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
198 .depthClampEnable = false,
199 .rasterizerDiscardEnable = false,
200 .polygonMode = VK_POLYGON_MODE_FILL,
201 .cullMode = VK_CULL_MODE_NONE,
202 .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
203 };
204
205 result = radv_graphics_pipeline_create(device_h,
206 radv_pipeline_cache_to_handle(&device->meta_state.cache),
207 &(VkGraphicsPipelineCreateInfo) {
208 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
209 .stageCount = 2,
210 .pStages = stages,
211
212 .pVertexInputState = &vi_state,
213 .pInputAssemblyState = &ia_state,
214
215 .pViewportState = &(VkPipelineViewportStateCreateInfo) {
216 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
217 .viewportCount = 0,
218 .scissorCount = 0,
219 },
220 .pRasterizationState = &rs_state,
221 .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
222 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
223 .rasterizationSamples = 1,
224 .sampleShadingEnable = false,
225 .pSampleMask = NULL,
226 .alphaToCoverageEnable = false,
227 .alphaToOneEnable = false,
228 },
229 .pColorBlendState = &blend_state,
230 .pDynamicState = NULL,
231 .renderPass = device->meta_state.fast_clear_flush.pass,
232 .subpass = 0,
233 },
234 &(struct radv_graphics_pipeline_create_info) {
235 .use_rectlist = true,
236 .custom_blend_mode = V_028808_CB_ELIMINATE_FAST_CLEAR,
237 },
238 &device->meta_state.alloc,
239 &device->meta_state.fast_clear_flush.cmask_eliminate_pipeline);
240 if (result != VK_SUCCESS)
241 goto cleanup;
242
243 result = radv_graphics_pipeline_create(device_h,
244 radv_pipeline_cache_to_handle(&device->meta_state.cache),
245 &(VkGraphicsPipelineCreateInfo) {
246 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
247 .stageCount = 2,
248 .pStages = stages,
249
250 .pVertexInputState = &vi_state,
251 .pInputAssemblyState = &ia_state,
252
253 .pViewportState = &(VkPipelineViewportStateCreateInfo) {
254 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
255 .viewportCount = 0,
256 .scissorCount = 0,
257 },
258 .pRasterizationState = &rs_state,
259 .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
260 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
261 .rasterizationSamples = 1,
262 .sampleShadingEnable = false,
263 .pSampleMask = NULL,
264 .alphaToCoverageEnable = false,
265 .alphaToOneEnable = false,
266 },
267 .pColorBlendState = &blend_state,
268 .pDynamicState = NULL,
269 .renderPass = device->meta_state.fast_clear_flush.pass,
270 .subpass = 0,
271 },
272 &(struct radv_graphics_pipeline_create_info) {
273 .use_rectlist = true,
274 .custom_blend_mode = V_028808_CB_FMASK_DECOMPRESS,
275 },
276 &device->meta_state.alloc,
277 &device->meta_state.fast_clear_flush.fmask_decompress_pipeline);
278 if (result != VK_SUCCESS)
279 goto cleanup_cmask;
280
281 goto cleanup;
282 cleanup_cmask:
283 radv_DestroyPipeline(device_h, device->meta_state.fast_clear_flush.cmask_eliminate_pipeline, &device->meta_state.alloc);
284 cleanup:
285 ralloc_free(fs_module.nir);
286 return result;
287 }
288
289 void
290 radv_device_finish_meta_fast_clear_flush_state(struct radv_device *device)
291 {
292 struct radv_meta_state *state = &device->meta_state;
293 VkDevice device_h = radv_device_to_handle(device);
294 VkRenderPass pass_h = device->meta_state.fast_clear_flush.pass;
295 const VkAllocationCallbacks *alloc = &device->meta_state.alloc;
296
297 if (pass_h)
298 radv_DestroyRenderPass(device_h, pass_h,
299 &device->meta_state.alloc);
300
301 VkPipeline pipeline_h = state->fast_clear_flush.cmask_eliminate_pipeline;
302 if (pipeline_h) {
303 radv_DestroyPipeline(device_h, pipeline_h, alloc);
304 }
305
306 pipeline_h = state->fast_clear_flush.fmask_decompress_pipeline;
307 if (pipeline_h) {
308 radv_DestroyPipeline(device_h, pipeline_h, alloc);
309 }
310 }
311
312 VkResult
313 radv_device_init_meta_fast_clear_flush_state(struct radv_device *device)
314 {
315 VkResult res = VK_SUCCESS;
316
317 zero(device->meta_state.fast_clear_flush);
318
319 struct radv_shader_module vs_module = { .nir = build_nir_vs() };
320 if (!vs_module.nir) {
321 /* XXX: Need more accurate error */
322 res = VK_ERROR_OUT_OF_HOST_MEMORY;
323 goto fail;
324 }
325
326 res = create_pass(device);
327 if (res != VK_SUCCESS)
328 goto fail;
329
330 VkShaderModule vs_module_h = radv_shader_module_to_handle(&vs_module);
331 res = create_pipeline(device, vs_module_h);
332 if (res != VK_SUCCESS)
333 goto fail;
334
335 goto cleanup;
336
337 fail:
338 radv_device_finish_meta_fast_clear_flush_state(device);
339
340 cleanup:
341 ralloc_free(vs_module.nir);
342
343 return res;
344 }
345
346 static void
347 emit_fast_clear_flush(struct radv_cmd_buffer *cmd_buffer,
348 const VkExtent2D *resolve_extent,
349 bool fmask_decompress)
350 {
351 struct radv_device *device = cmd_buffer->device;
352 VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
353 uint32_t offset;
354 const struct vertex_attrs vertex_data[3] = {
355 {
356 .position = {
357 0,
358 0,
359 },
360 },
361 {
362 .position = {
363 0,
364 resolve_extent->height,
365 },
366 },
367 {
368 .position = {
369 resolve_extent->width,
370 0,
371 },
372 },
373 };
374
375 cmd_buffer->state.flush_bits |= (RADV_CMD_FLAG_FLUSH_AND_INV_CB |
376 RADV_CMD_FLAG_FLUSH_AND_INV_CB_META);
377 radv_cmd_buffer_upload_data(cmd_buffer, sizeof(vertex_data), 16, vertex_data, &offset);
378 struct radv_buffer vertex_buffer = {
379 .device = device,
380 .size = sizeof(vertex_data),
381 .bo = cmd_buffer->upload.upload_bo,
382 .offset = offset,
383 };
384
385 VkBuffer vertex_buffer_h = radv_buffer_to_handle(&vertex_buffer);
386
387 radv_CmdBindVertexBuffers(cmd_buffer_h,
388 /*firstBinding*/ 0,
389 /*bindingCount*/ 1,
390 (VkBuffer[]) { vertex_buffer_h },
391 (VkDeviceSize[]) { 0 });
392
393 VkPipeline pipeline_h;
394 if (fmask_decompress)
395 pipeline_h = device->meta_state.fast_clear_flush.fmask_decompress_pipeline;
396 else
397 pipeline_h = device->meta_state.fast_clear_flush.cmask_eliminate_pipeline;
398 RADV_FROM_HANDLE(radv_pipeline, pipeline, pipeline_h);
399
400 if (cmd_buffer->state.pipeline != pipeline) {
401 radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
402 pipeline_h);
403 }
404
405 radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0);
406 cmd_buffer->state.flush_bits |= (RADV_CMD_FLAG_FLUSH_AND_INV_CB |
407 RADV_CMD_FLAG_FLUSH_AND_INV_CB_META);
408 si_emit_cache_flush(cmd_buffer);
409 }
410
411 /**
412 */
413 void
414 radv_fast_clear_flush_image_inplace(struct radv_cmd_buffer *cmd_buffer,
415 struct radv_image *image,
416 const VkImageSubresourceRange *subresourceRange)
417 {
418 struct radv_meta_saved_state saved_state;
419 struct radv_meta_saved_pass_state saved_pass_state;
420 VkDevice device_h = radv_device_to_handle(cmd_buffer->device);
421 VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
422
423 assert(cmd_buffer->queue_family_index == RADV_QUEUE_GENERAL);
424 radv_meta_save_pass(&saved_pass_state, cmd_buffer);
425 radv_meta_save_graphics_reset_vport_scissor(&saved_state, cmd_buffer);
426
427 for (uint32_t layer = 0; layer < subresourceRange->layerCount;
428 ++layer) {
429 struct radv_image_view iview;
430
431 radv_image_view_init(&iview, cmd_buffer->device,
432 &(VkImageViewCreateInfo) {
433 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
434 .image = radv_image_to_handle(image),
435 .viewType = radv_meta_get_view_type(image),
436 .format = image->vk_format,
437 .subresourceRange = {
438 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
439 .baseMipLevel = 0,
440 .levelCount = 1,
441 .baseArrayLayer = subresourceRange->baseArrayLayer + layer,
442 .layerCount = 1,
443 },
444 },
445 cmd_buffer, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
446
447 VkFramebuffer fb_h;
448 radv_CreateFramebuffer(device_h,
449 &(VkFramebufferCreateInfo) {
450 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
451 .attachmentCount = 1,
452 .pAttachments = (VkImageView[]) {
453 radv_image_view_to_handle(&iview)
454 },
455 .width = image->extent.width,
456 .height = image->extent.height,
457 .layers = 1
458 },
459 &cmd_buffer->pool->alloc,
460 &fb_h);
461
462 radv_CmdBeginRenderPass(cmd_buffer_h,
463 &(VkRenderPassBeginInfo) {
464 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
465 .renderPass = cmd_buffer->device->meta_state.fast_clear_flush.pass,
466 .framebuffer = fb_h,
467 .renderArea = {
468 .offset = {
469 0,
470 0,
471 },
472 .extent = {
473 image->extent.width,
474 image->extent.height,
475 }
476 },
477 .clearValueCount = 0,
478 .pClearValues = NULL,
479 },
480 VK_SUBPASS_CONTENTS_INLINE);
481
482 emit_fast_clear_flush(cmd_buffer,
483 &(VkExtent2D) { image->extent.width, image->extent.height },
484 image->fmask.size > 0);
485 radv_CmdEndRenderPass(cmd_buffer_h);
486
487 radv_DestroyFramebuffer(device_h, fb_h,
488 &cmd_buffer->pool->alloc);
489
490 }
491 radv_meta_restore(&saved_state, cmd_buffer);
492 radv_meta_restore_pass(&saved_pass_state, cmd_buffer);
493 }