• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *
build_nir_vs(void)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 *
build_nir_fs(void)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
create_pass(struct radv_device * device)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
create_pipeline(struct radv_device * device,VkShaderModule vs_module_h)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
radv_device_finish_meta_fast_clear_flush_state(struct radv_device * device)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
radv_device_init_meta_fast_clear_flush_state(struct radv_device * device)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
emit_fast_clear_flush(struct radv_cmd_buffer * cmd_buffer,const VkExtent2D * resolve_extent,bool fmask_decompress)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
radv_fast_clear_flush_image_inplace(struct radv_cmd_buffer * cmd_buffer,struct radv_image * image)414 radv_fast_clear_flush_image_inplace(struct radv_cmd_buffer *cmd_buffer,
415 				    struct radv_image *image)
416 {
417 	struct radv_meta_saved_state saved_state;
418 	struct radv_meta_saved_pass_state saved_pass_state;
419 	VkDevice device_h = radv_device_to_handle(cmd_buffer->device);
420 	VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
421 
422 	assert(cmd_buffer->queue_family_index == RADV_QUEUE_GENERAL);
423 	radv_meta_save_pass(&saved_pass_state, cmd_buffer);
424 	radv_meta_save_graphics_reset_vport_scissor(&saved_state, cmd_buffer);
425 
426 	struct radv_image_view iview;
427 	radv_image_view_init(&iview, cmd_buffer->device,
428 			     &(VkImageViewCreateInfo) {
429 				     .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
430 					     .image = radv_image_to_handle(image),
431 					     .format = image->vk_format,
432 					     .subresourceRange = {
433 						     .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
434 						     .baseMipLevel = 0,
435 						     .levelCount = 1,
436 						     .baseArrayLayer = 0,
437 						     .layerCount = 1,
438 					     },
439 				     },
440 				     cmd_buffer, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
441 
442 	VkFramebuffer fb_h;
443 	radv_CreateFramebuffer(device_h,
444 			       &(VkFramebufferCreateInfo) {
445 				       .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
446 				       .attachmentCount = 1,
447 				       .pAttachments = (VkImageView[]) {
448 					       radv_image_view_to_handle(&iview)
449 				       },
450 				       .width = image->extent.width,
451 				       .height = image->extent.height,
452 				       .layers = 1
453 			      },
454 			      &cmd_buffer->pool->alloc,
455 			      &fb_h);
456 
457 	radv_CmdBeginRenderPass(cmd_buffer_h,
458 				      &(VkRenderPassBeginInfo) {
459 					      .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
460 						      .renderPass = cmd_buffer->device->meta_state.fast_clear_flush.pass,
461 						      .framebuffer = fb_h,
462 						      .renderArea = {
463 						      .offset = {
464 							      0,
465 							      0,
466 						      },
467 						      .extent = {
468 							      image->extent.width,
469 							      image->extent.height,
470 						      }
471 					      },
472 					      .clearValueCount = 0,
473 					      .pClearValues = NULL,
474 				     },
475 				     VK_SUBPASS_CONTENTS_INLINE);
476 
477 	emit_fast_clear_flush(cmd_buffer,
478 			      &(VkExtent2D) { image->extent.width, image->extent.height },
479 			      image->fmask.size > 0);
480 	radv_CmdEndRenderPass(cmd_buffer_h);
481 
482 	radv_DestroyFramebuffer(device_h, fb_h,
483 				&cmd_buffer->pool->alloc);
484 
485 	radv_meta_restore(&saved_state, cmd_buffer);
486 	radv_meta_restore_pass(&saved_pass_state, cmd_buffer);
487 }
488