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