3393bcb25eac432aa441a35b25f2d3a81a30c0e6
[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 = 1,
218 .scissorCount = 1,
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 = &(VkPipelineDynamicStateCreateInfo) {
231 .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
232 .dynamicStateCount = 2,
233 .pDynamicStates = (VkDynamicState[]) {
234 VK_DYNAMIC_STATE_VIEWPORT,
235 VK_DYNAMIC_STATE_SCISSOR,
236 },
237 },
238 .renderPass = device->meta_state.fast_clear_flush.pass,
239 .subpass = 0,
240 },
241 &(struct radv_graphics_pipeline_create_info) {
242 .use_rectlist = true,
243 .custom_blend_mode = V_028808_CB_ELIMINATE_FAST_CLEAR,
244 },
245 &device->meta_state.alloc,
246 &device->meta_state.fast_clear_flush.cmask_eliminate_pipeline);
247 if (result != VK_SUCCESS)
248 goto cleanup;
249
250 result = radv_graphics_pipeline_create(device_h,
251 radv_pipeline_cache_to_handle(&device->meta_state.cache),
252 &(VkGraphicsPipelineCreateInfo) {
253 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
254 .stageCount = 2,
255 .pStages = stages,
256
257 .pVertexInputState = &vi_state,
258 .pInputAssemblyState = &ia_state,
259
260 .pViewportState = &(VkPipelineViewportStateCreateInfo) {
261 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
262 .viewportCount = 1,
263 .scissorCount = 1,
264 },
265 .pRasterizationState = &rs_state,
266 .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
267 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
268 .rasterizationSamples = 1,
269 .sampleShadingEnable = false,
270 .pSampleMask = NULL,
271 .alphaToCoverageEnable = false,
272 .alphaToOneEnable = false,
273 },
274 .pColorBlendState = &blend_state,
275 .pDynamicState = &(VkPipelineDynamicStateCreateInfo) {
276 .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
277 .dynamicStateCount = 2,
278 .pDynamicStates = (VkDynamicState[]) {
279 VK_DYNAMIC_STATE_VIEWPORT,
280 VK_DYNAMIC_STATE_SCISSOR,
281 },
282 },
283 .renderPass = device->meta_state.fast_clear_flush.pass,
284 .subpass = 0,
285 },
286 &(struct radv_graphics_pipeline_create_info) {
287 .use_rectlist = true,
288 .custom_blend_mode = V_028808_CB_FMASK_DECOMPRESS,
289 },
290 &device->meta_state.alloc,
291 &device->meta_state.fast_clear_flush.fmask_decompress_pipeline);
292 if (result != VK_SUCCESS)
293 goto cleanup_cmask;
294
295 goto cleanup;
296 cleanup_cmask:
297 radv_DestroyPipeline(device_h, device->meta_state.fast_clear_flush.cmask_eliminate_pipeline, &device->meta_state.alloc);
298 cleanup:
299 ralloc_free(fs_module.nir);
300 return result;
301 }
302
303 void
304 radv_device_finish_meta_fast_clear_flush_state(struct radv_device *device)
305 {
306 struct radv_meta_state *state = &device->meta_state;
307 VkDevice device_h = radv_device_to_handle(device);
308 VkRenderPass pass_h = device->meta_state.fast_clear_flush.pass;
309 const VkAllocationCallbacks *alloc = &device->meta_state.alloc;
310
311 if (pass_h)
312 radv_DestroyRenderPass(device_h, pass_h,
313 &device->meta_state.alloc);
314
315 VkPipeline pipeline_h = state->fast_clear_flush.cmask_eliminate_pipeline;
316 if (pipeline_h) {
317 radv_DestroyPipeline(device_h, pipeline_h, alloc);
318 }
319
320 pipeline_h = state->fast_clear_flush.fmask_decompress_pipeline;
321 if (pipeline_h) {
322 radv_DestroyPipeline(device_h, pipeline_h, alloc);
323 }
324 }
325
326 VkResult
327 radv_device_init_meta_fast_clear_flush_state(struct radv_device *device)
328 {
329 VkResult res = VK_SUCCESS;
330
331 zero(device->meta_state.fast_clear_flush);
332
333 struct radv_shader_module vs_module = { .nir = build_nir_vs() };
334 if (!vs_module.nir) {
335 /* XXX: Need more accurate error */
336 res = VK_ERROR_OUT_OF_HOST_MEMORY;
337 goto fail;
338 }
339
340 res = create_pass(device);
341 if (res != VK_SUCCESS)
342 goto fail;
343
344 VkShaderModule vs_module_h = radv_shader_module_to_handle(&vs_module);
345 res = create_pipeline(device, vs_module_h);
346 if (res != VK_SUCCESS)
347 goto fail;
348
349 goto cleanup;
350
351 fail:
352 radv_device_finish_meta_fast_clear_flush_state(device);
353
354 cleanup:
355 ralloc_free(vs_module.nir);
356
357 return res;
358 }
359
360 static void
361 emit_fast_clear_flush(struct radv_cmd_buffer *cmd_buffer,
362 const VkExtent2D *resolve_extent,
363 bool fmask_decompress)
364 {
365 struct radv_device *device = cmd_buffer->device;
366 VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
367 uint32_t offset;
368 const struct vertex_attrs vertex_data[3] = {
369 {
370 .position = {
371 -1.0,
372 -1.0,
373 },
374 },
375 {
376 .position = {
377 -1.0,
378 1.0,
379 },
380 },
381 {
382 .position = {
383 1.0,
384 -1.0,
385 },
386 },
387 };
388
389 radv_cmd_buffer_upload_data(cmd_buffer, sizeof(vertex_data), 16, vertex_data, &offset);
390 struct radv_buffer vertex_buffer = {
391 .device = device,
392 .size = sizeof(vertex_data),
393 .bo = cmd_buffer->upload.upload_bo,
394 .offset = offset,
395 };
396
397 VkBuffer vertex_buffer_h = radv_buffer_to_handle(&vertex_buffer);
398
399 radv_CmdBindVertexBuffers(cmd_buffer_h,
400 /*firstBinding*/ 0,
401 /*bindingCount*/ 1,
402 (VkBuffer[]) { vertex_buffer_h },
403 (VkDeviceSize[]) { 0 });
404
405 VkPipeline pipeline_h;
406 if (fmask_decompress)
407 pipeline_h = device->meta_state.fast_clear_flush.fmask_decompress_pipeline;
408 else
409 pipeline_h = device->meta_state.fast_clear_flush.cmask_eliminate_pipeline;
410 RADV_FROM_HANDLE(radv_pipeline, pipeline, pipeline_h);
411
412 if (cmd_buffer->state.pipeline != pipeline) {
413 radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
414 pipeline_h);
415 }
416
417 radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkViewport) {
418 .x = 0,
419 .y = 0,
420 .width = resolve_extent->width,
421 .height = resolve_extent->height,
422 .minDepth = 0.0f,
423 .maxDepth = 1.0f
424 });
425
426 radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkRect2D) {
427 .offset = (VkOffset2D) { 0, 0 },
428 .extent = (VkExtent2D) { resolve_extent->width, resolve_extent->height },
429 });
430
431 radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0);
432 cmd_buffer->state.flush_bits |= (RADV_CMD_FLAG_FLUSH_AND_INV_CB |
433 RADV_CMD_FLAG_FLUSH_AND_INV_CB_META);
434 }
435
436 /**
437 */
438 void
439 radv_fast_clear_flush_image_inplace(struct radv_cmd_buffer *cmd_buffer,
440 struct radv_image *image,
441 const VkImageSubresourceRange *subresourceRange)
442 {
443 struct radv_meta_saved_state saved_state;
444 struct radv_meta_saved_pass_state saved_pass_state;
445 VkDevice device_h = radv_device_to_handle(cmd_buffer->device);
446 VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
447 uint32_t layer_count = radv_get_layerCount(image, subresourceRange);
448
449 assert(cmd_buffer->queue_family_index == RADV_QUEUE_GENERAL);
450 radv_meta_save_pass(&saved_pass_state, cmd_buffer);
451 radv_meta_save_graphics_reset_vport_scissor(&saved_state, cmd_buffer);
452
453 for (uint32_t layer = 0; layer < layer_count; ++layer) {
454 struct radv_image_view iview;
455
456 radv_image_view_init(&iview, cmd_buffer->device,
457 &(VkImageViewCreateInfo) {
458 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
459 .image = radv_image_to_handle(image),
460 .viewType = radv_meta_get_view_type(image),
461 .format = image->vk_format,
462 .subresourceRange = {
463 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
464 .baseMipLevel = 0,
465 .levelCount = 1,
466 .baseArrayLayer = subresourceRange->baseArrayLayer + layer,
467 .layerCount = 1,
468 },
469 },
470 cmd_buffer, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
471
472 VkFramebuffer fb_h;
473 radv_CreateFramebuffer(device_h,
474 &(VkFramebufferCreateInfo) {
475 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
476 .attachmentCount = 1,
477 .pAttachments = (VkImageView[]) {
478 radv_image_view_to_handle(&iview)
479 },
480 .width = image->extent.width,
481 .height = image->extent.height,
482 .layers = 1
483 },
484 &cmd_buffer->pool->alloc,
485 &fb_h);
486
487 radv_CmdBeginRenderPass(cmd_buffer_h,
488 &(VkRenderPassBeginInfo) {
489 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
490 .renderPass = cmd_buffer->device->meta_state.fast_clear_flush.pass,
491 .framebuffer = fb_h,
492 .renderArea = {
493 .offset = {
494 0,
495 0,
496 },
497 .extent = {
498 image->extent.width,
499 image->extent.height,
500 }
501 },
502 .clearValueCount = 0,
503 .pClearValues = NULL,
504 },
505 VK_SUBPASS_CONTENTS_INLINE);
506
507 emit_fast_clear_flush(cmd_buffer,
508 &(VkExtent2D) { image->extent.width, image->extent.height },
509 image->fmask.size > 0);
510 radv_CmdEndRenderPass(cmd_buffer_h);
511
512 radv_DestroyFramebuffer(device_h, fb_h,
513 &cmd_buffer->pool->alloc);
514
515 }
516 radv_meta_restore(&saved_state, cmd_buffer);
517 radv_meta_restore_pass(&saved_pass_state, cmd_buffer);
518 }