radv: create pipeline layout objects for all meta operations
[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 "sid.h"
30
31 static VkResult
32 create_pass(struct radv_device *device)
33 {
34 VkResult result;
35 VkDevice device_h = radv_device_to_handle(device);
36 const VkAllocationCallbacks *alloc = &device->meta_state.alloc;
37 VkAttachmentDescription attachment;
38
39 attachment.format = VK_FORMAT_UNDEFINED;
40 attachment.samples = 1;
41 attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
42 attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
43 attachment.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
44 attachment.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
45
46 result = radv_CreateRenderPass(device_h,
47 &(VkRenderPassCreateInfo) {
48 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
49 .attachmentCount = 1,
50 .pAttachments = &attachment,
51 .subpassCount = 1,
52 .pSubpasses = &(VkSubpassDescription) {
53 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
54 .inputAttachmentCount = 0,
55 .colorAttachmentCount = 1,
56 .pColorAttachments = (VkAttachmentReference[]) {
57 {
58 .attachment = 0,
59 .layout = VK_IMAGE_LAYOUT_GENERAL,
60 },
61 },
62 .pResolveAttachments = NULL,
63 .pDepthStencilAttachment = &(VkAttachmentReference) {
64 .attachment = VK_ATTACHMENT_UNUSED,
65 },
66 .preserveAttachmentCount = 0,
67 .pPreserveAttachments = NULL,
68 },
69 .dependencyCount = 0,
70 },
71 alloc,
72 &device->meta_state.fast_clear_flush.pass);
73
74 return result;
75 }
76
77 static VkResult
78 create_pipeline_layout(struct radv_device *device, VkPipelineLayout *layout)
79 {
80 VkPipelineLayoutCreateInfo pl_create_info = {
81 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
82 .setLayoutCount = 0,
83 .pSetLayouts = NULL,
84 .pushConstantRangeCount = 0,
85 .pPushConstantRanges = NULL,
86 };
87
88 return radv_CreatePipelineLayout(radv_device_to_handle(device),
89 &pl_create_info,
90 &device->meta_state.alloc,
91 layout);
92 }
93
94 static VkResult
95 create_pipeline(struct radv_device *device,
96 VkShaderModule vs_module_h,
97 VkPipelineLayout layout)
98 {
99 VkResult result;
100 VkDevice device_h = radv_device_to_handle(device);
101
102 struct radv_shader_module fs_module = {
103 .nir = radv_meta_build_nir_fs_noop(),
104 };
105
106 if (!fs_module.nir) {
107 /* XXX: Need more accurate error */
108 result = VK_ERROR_OUT_OF_HOST_MEMORY;
109 goto cleanup;
110 }
111
112 const VkPipelineShaderStageCreateInfo stages[2] = {
113 {
114 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
115 .stage = VK_SHADER_STAGE_VERTEX_BIT,
116 .module = vs_module_h,
117 .pName = "main",
118 },
119 {
120 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
121 .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
122 .module = radv_shader_module_to_handle(&fs_module),
123 .pName = "main",
124 },
125 };
126
127 const VkPipelineVertexInputStateCreateInfo vi_state = {
128 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
129 .vertexBindingDescriptionCount = 0,
130 .vertexAttributeDescriptionCount = 0,
131 };
132
133 const VkPipelineInputAssemblyStateCreateInfo ia_state = {
134 .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
135 .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
136 .primitiveRestartEnable = false,
137 };
138
139 const VkPipelineColorBlendStateCreateInfo blend_state = {
140 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
141 .logicOpEnable = false,
142 .attachmentCount = 1,
143 .pAttachments = (VkPipelineColorBlendAttachmentState []) {
144 {
145 .colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
146 VK_COLOR_COMPONENT_G_BIT |
147 VK_COLOR_COMPONENT_B_BIT |
148 VK_COLOR_COMPONENT_A_BIT,
149 },
150 }
151 };
152 const VkPipelineRasterizationStateCreateInfo rs_state = {
153 .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
154 .depthClampEnable = false,
155 .rasterizerDiscardEnable = false,
156 .polygonMode = VK_POLYGON_MODE_FILL,
157 .cullMode = VK_CULL_MODE_NONE,
158 .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
159 };
160
161 result = radv_graphics_pipeline_create(device_h,
162 radv_pipeline_cache_to_handle(&device->meta_state.cache),
163 &(VkGraphicsPipelineCreateInfo) {
164 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
165 .stageCount = 2,
166 .pStages = stages,
167
168 .pVertexInputState = &vi_state,
169 .pInputAssemblyState = &ia_state,
170
171 .pViewportState = &(VkPipelineViewportStateCreateInfo) {
172 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
173 .viewportCount = 1,
174 .scissorCount = 1,
175 },
176 .pRasterizationState = &rs_state,
177 .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
178 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
179 .rasterizationSamples = 1,
180 .sampleShadingEnable = false,
181 .pSampleMask = NULL,
182 .alphaToCoverageEnable = false,
183 .alphaToOneEnable = false,
184 },
185 .pColorBlendState = &blend_state,
186 .pDynamicState = &(VkPipelineDynamicStateCreateInfo) {
187 .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
188 .dynamicStateCount = 2,
189 .pDynamicStates = (VkDynamicState[]) {
190 VK_DYNAMIC_STATE_VIEWPORT,
191 VK_DYNAMIC_STATE_SCISSOR,
192 },
193 },
194 .layout = layout,
195 .renderPass = device->meta_state.fast_clear_flush.pass,
196 .subpass = 0,
197 },
198 &(struct radv_graphics_pipeline_create_info) {
199 .use_rectlist = true,
200 .custom_blend_mode = V_028808_CB_ELIMINATE_FAST_CLEAR,
201 },
202 &device->meta_state.alloc,
203 &device->meta_state.fast_clear_flush.cmask_eliminate_pipeline);
204 if (result != VK_SUCCESS)
205 goto cleanup;
206
207 result = radv_graphics_pipeline_create(device_h,
208 radv_pipeline_cache_to_handle(&device->meta_state.cache),
209 &(VkGraphicsPipelineCreateInfo) {
210 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
211 .stageCount = 2,
212 .pStages = stages,
213
214 .pVertexInputState = &vi_state,
215 .pInputAssemblyState = &ia_state,
216
217 .pViewportState = &(VkPipelineViewportStateCreateInfo) {
218 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
219 .viewportCount = 1,
220 .scissorCount = 1,
221 },
222 .pRasterizationState = &rs_state,
223 .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
224 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
225 .rasterizationSamples = 1,
226 .sampleShadingEnable = false,
227 .pSampleMask = NULL,
228 .alphaToCoverageEnable = false,
229 .alphaToOneEnable = false,
230 },
231 .pColorBlendState = &blend_state,
232 .pDynamicState = &(VkPipelineDynamicStateCreateInfo) {
233 .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
234 .dynamicStateCount = 2,
235 .pDynamicStates = (VkDynamicState[]) {
236 VK_DYNAMIC_STATE_VIEWPORT,
237 VK_DYNAMIC_STATE_SCISSOR,
238 },
239 },
240 .layout = layout,
241 .renderPass = device->meta_state.fast_clear_flush.pass,
242 .subpass = 0,
243 },
244 &(struct radv_graphics_pipeline_create_info) {
245 .use_rectlist = true,
246 .custom_blend_mode = V_028808_CB_FMASK_DECOMPRESS,
247 },
248 &device->meta_state.alloc,
249 &device->meta_state.fast_clear_flush.fmask_decompress_pipeline);
250 if (result != VK_SUCCESS)
251 goto cleanup_cmask;
252
253 goto cleanup;
254 cleanup_cmask:
255 radv_DestroyPipeline(device_h, device->meta_state.fast_clear_flush.cmask_eliminate_pipeline, &device->meta_state.alloc);
256 cleanup:
257 ralloc_free(fs_module.nir);
258 return result;
259 }
260
261 void
262 radv_device_finish_meta_fast_clear_flush_state(struct radv_device *device)
263 {
264 struct radv_meta_state *state = &device->meta_state;
265
266 radv_DestroyRenderPass(radv_device_to_handle(device),
267 state->fast_clear_flush.pass, &state->alloc);
268 radv_DestroyPipelineLayout(radv_device_to_handle(device),
269 state->fast_clear_flush.p_layout,
270 &state->alloc);
271 radv_DestroyPipeline(radv_device_to_handle(device),
272 state->fast_clear_flush.cmask_eliminate_pipeline,
273 &state->alloc);
274 radv_DestroyPipeline(radv_device_to_handle(device),
275 state->fast_clear_flush.fmask_decompress_pipeline,
276 &state->alloc);
277 }
278
279 VkResult
280 radv_device_init_meta_fast_clear_flush_state(struct radv_device *device)
281 {
282 VkResult res = VK_SUCCESS;
283
284 struct radv_shader_module vs_module = { .nir = radv_meta_build_nir_vs_generate_vertices() };
285 if (!vs_module.nir) {
286 /* XXX: Need more accurate error */
287 res = VK_ERROR_OUT_OF_HOST_MEMORY;
288 goto fail;
289 }
290
291 res = create_pass(device);
292 if (res != VK_SUCCESS)
293 goto fail;
294
295 res = create_pipeline_layout(device,
296 &device->meta_state.fast_clear_flush.p_layout);
297 if (res != VK_SUCCESS)
298 goto fail;
299
300 VkShaderModule vs_module_h = radv_shader_module_to_handle(&vs_module);
301 res = create_pipeline(device, vs_module_h,
302 device->meta_state.fast_clear_flush.p_layout);
303 if (res != VK_SUCCESS)
304 goto fail;
305
306 goto cleanup;
307
308 fail:
309 radv_device_finish_meta_fast_clear_flush_state(device);
310
311 cleanup:
312 ralloc_free(vs_module.nir);
313
314 return res;
315 }
316
317 static void
318 emit_fast_clear_flush(struct radv_cmd_buffer *cmd_buffer,
319 const VkExtent2D *resolve_extent,
320 VkPipeline pipeline)
321 {
322 VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
323
324 radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
325 pipeline);
326
327 radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkViewport) {
328 .x = 0,
329 .y = 0,
330 .width = resolve_extent->width,
331 .height = resolve_extent->height,
332 .minDepth = 0.0f,
333 .maxDepth = 1.0f
334 });
335
336 radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkRect2D) {
337 .offset = (VkOffset2D) { 0, 0 },
338 .extent = (VkExtent2D) { resolve_extent->width, resolve_extent->height },
339 });
340
341 radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0);
342 cmd_buffer->state.flush_bits |= (RADV_CMD_FLAG_FLUSH_AND_INV_CB |
343 RADV_CMD_FLAG_FLUSH_AND_INV_CB_META);
344 }
345
346 static void
347 radv_emit_set_predication_state_from_image(struct radv_cmd_buffer *cmd_buffer,
348 struct radv_image *image, bool value)
349 {
350 uint64_t va = 0;
351
352 if (value) {
353 va = radv_buffer_get_va(image->bo) + image->offset;
354 va += image->dcc_pred_offset;
355 }
356
357 si_emit_set_predication_state(cmd_buffer, va);
358 }
359
360 /**
361 */
362 void
363 radv_fast_clear_flush_image_inplace(struct radv_cmd_buffer *cmd_buffer,
364 struct radv_image *image,
365 const VkImageSubresourceRange *subresourceRange)
366 {
367 struct radv_meta_saved_state saved_state;
368 VkDevice device_h = radv_device_to_handle(cmd_buffer->device);
369 VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
370 uint32_t layer_count = radv_get_layerCount(image, subresourceRange);
371 VkPipeline pipeline;
372
373 assert(cmd_buffer->queue_family_index == RADV_QUEUE_GENERAL);
374
375 radv_meta_save(&saved_state, cmd_buffer,
376 RADV_META_SAVE_GRAPHICS_PIPELINE |
377 RADV_META_SAVE_PASS);
378
379 if (image->fmask.size > 0) {
380 pipeline = cmd_buffer->device->meta_state.fast_clear_flush.fmask_decompress_pipeline;
381 } else {
382 pipeline = cmd_buffer->device->meta_state.fast_clear_flush.cmask_eliminate_pipeline;
383 }
384
385 if (image->surface.dcc_size) {
386 radv_emit_set_predication_state_from_image(cmd_buffer, image, true);
387 cmd_buffer->state.predicating = true;
388 }
389 for (uint32_t layer = 0; layer < layer_count; ++layer) {
390 struct radv_image_view iview;
391
392 radv_image_view_init(&iview, cmd_buffer->device,
393 &(VkImageViewCreateInfo) {
394 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
395 .image = radv_image_to_handle(image),
396 .viewType = radv_meta_get_view_type(image),
397 .format = image->vk_format,
398 .subresourceRange = {
399 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
400 .baseMipLevel = 0,
401 .levelCount = 1,
402 .baseArrayLayer = subresourceRange->baseArrayLayer + layer,
403 .layerCount = 1,
404 },
405 });
406
407 VkFramebuffer fb_h;
408 radv_CreateFramebuffer(device_h,
409 &(VkFramebufferCreateInfo) {
410 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
411 .attachmentCount = 1,
412 .pAttachments = (VkImageView[]) {
413 radv_image_view_to_handle(&iview)
414 },
415 .width = image->info.width,
416 .height = image->info.height,
417 .layers = 1
418 },
419 &cmd_buffer->pool->alloc,
420 &fb_h);
421
422 radv_CmdBeginRenderPass(cmd_buffer_h,
423 &(VkRenderPassBeginInfo) {
424 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
425 .renderPass = cmd_buffer->device->meta_state.fast_clear_flush.pass,
426 .framebuffer = fb_h,
427 .renderArea = {
428 .offset = {
429 0,
430 0,
431 },
432 .extent = {
433 image->info.width,
434 image->info.height,
435 }
436 },
437 .clearValueCount = 0,
438 .pClearValues = NULL,
439 },
440 VK_SUBPASS_CONTENTS_INLINE);
441
442 emit_fast_clear_flush(cmd_buffer,
443 &(VkExtent2D) { image->info.width, image->info.height },
444 pipeline);
445 radv_CmdEndRenderPass(cmd_buffer_h);
446
447 radv_DestroyFramebuffer(device_h, fb_h,
448 &cmd_buffer->pool->alloc);
449
450 }
451 if (image->surface.dcc_size) {
452 cmd_buffer->state.predicating = false;
453 radv_emit_set_predication_state_from_image(cmd_buffer, image, false);
454 }
455 radv_meta_restore(&saved_state, cmd_buffer);
456 }