[Mesa-dev] [PATCH] radv: add support for layered clears

Dave Airlie airlied at gmail.com
Mon Jan 16 22:58:09 UTC 2017


From: Dave Airlie <airlied at redhat.com>

This uses vertex layer from instance id to clear the layers.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 src/amd/vulkan/radv_meta_clear.c | 150 ++++++++++++++++++++++++---------------
 src/amd/vulkan/radv_private.h    |  12 ++--
 2 files changed, 102 insertions(+), 60 deletions(-)

diff --git a/src/amd/vulkan/radv_meta_clear.c b/src/amd/vulkan/radv_meta_clear.c
index ff779ea..4a5fd74 100644
--- a/src/amd/vulkan/radv_meta_clear.c
+++ b/src/amd/vulkan/radv_meta_clear.c
@@ -48,7 +48,8 @@ enum {
 static void
 build_color_shaders(struct nir_shader **out_vs,
                     struct nir_shader **out_fs,
-                    uint32_t frag_output)
+		    uint32_t frag_output,
+		    bool layered)
 {
 	nir_builder vs_b;
 	nir_builder fs_b;
@@ -56,7 +57,7 @@ build_color_shaders(struct nir_shader **out_vs,
 	nir_builder_init_simple_shader(&vs_b, NULL, MESA_SHADER_VERTEX, NULL);
 	nir_builder_init_simple_shader(&fs_b, NULL, MESA_SHADER_FRAGMENT, NULL);
 
-	vs_b.shader->info->name = ralloc_strdup(vs_b.shader, "meta_clear_color_vs");
+	vs_b.shader->info->name = ralloc_strdup(vs_b.shader, layered ? "meta_clear_color_layer_vs" : "meta_clear_color_vs");
 	fs_b.shader->info->name = ralloc_strdup(fs_b.shader, "meta_clear_color_fs");
 
 	const struct glsl_type *position_type = glsl_vec4_type();
@@ -98,6 +99,18 @@ build_color_shaders(struct nir_shader **out_vs,
 	nir_copy_var(&vs_b, vs_out_color, vs_in_color);
 	nir_copy_var(&fs_b, fs_out_color, fs_in_color);
 
+	if (layered) {
+		const struct glsl_type *layer_type = glsl_int_type();
+		nir_variable *vs_out_layer =
+			nir_variable_create(vs_b.shader, nir_var_shader_out, layer_type,
+					    "v_layer");
+		vs_out_layer->data.location = VARYING_SLOT_LAYER;
+		vs_out_layer->data.interpolation = INTERP_MODE_FLAT;
+		nir_ssa_def *inst_id = nir_load_system_value(&vs_b, nir_intrinsic_load_instance_id, 0);
+
+		nir_store_var(&vs_b, vs_out_layer, inst_id, 0x1);
+	}
+
 	*out_vs = vs_b.shader;
 	*out_fs = fs_b.shader;
 }
@@ -196,9 +209,6 @@ create_pipeline(struct radv_device *device,
 					       alloc,
 					       &pipeline_h);
 
-	ralloc_free(vs_nir);
-	ralloc_free(fs_nir);
-
 	*pipeline = radv_pipeline_from_handle(pipeline_h);
 
 	return result;
@@ -247,13 +257,14 @@ static VkResult
 create_color_pipeline(struct radv_device *device,
 		      uint32_t samples,
                       uint32_t frag_output,
+		      bool layered,
                       struct radv_pipeline **pipeline,
 		      VkRenderPass pass)
 {
 	struct nir_shader *vs_nir;
 	struct nir_shader *fs_nir;
 	VkResult result;
-	build_color_shaders(&vs_nir, &fs_nir, frag_output);
+	build_color_shaders(&vs_nir, &fs_nir, frag_output, layered);
 
 	const VkPipelineVertexInputStateCreateInfo vi_state = {
 		.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
@@ -316,6 +327,9 @@ create_color_pipeline(struct radv_device *device,
 				 samples, vs_nir, fs_nir, &vi_state, &ds_state, &cb_state,
 				 &extra, &device->meta_state.alloc, pipeline);
 
+	ralloc_free(vs_nir);
+	ralloc_free(fs_nir);
+
 	return result;
 }
 
@@ -345,14 +359,17 @@ radv_device_finish_meta_clear_state(struct radv_device *device)
 
 	for (uint32_t i = 0; i < ARRAY_SIZE(state->clear); ++i) {
 		for (uint32_t j = 0; j < ARRAY_SIZE(state->clear[i].color_pipelines); ++j) {
-			destroy_pipeline(device, state->clear[i].color_pipelines[j]);
+			for (uint32_t k = 0; k < META_CLEAR_LAYER_COUNT; k++)
+				destroy_pipeline(device, state->clear[i].color_pipelines[j][k]);
 			destroy_render_pass(device, state->clear[i].render_pass[j]);
 		}
 
 		for (uint32_t j = 0; j < NUM_DEPTH_CLEAR_PIPELINES; j++) {
-			destroy_pipeline(device, state->clear[i].depth_only_pipeline[j]);
-			destroy_pipeline(device, state->clear[i].stencil_only_pipeline[j]);
-			destroy_pipeline(device, state->clear[i].depthstencil_pipeline[j]);
+			for (uint32_t k = 0; k < META_CLEAR_LAYER_COUNT; k++) {
+				destroy_pipeline(device, state->clear[i].depth_only_pipeline[j][k]);
+				destroy_pipeline(device, state->clear[i].stencil_only_pipeline[j][k]);
+				destroy_pipeline(device, state->clear[i].depthstencil_pipeline[j][k]);
+			}
 		}
 		destroy_render_pass(device, state->clear[i].depthstencil_rp);
 	}
@@ -378,12 +395,13 @@ emit_color_clear(struct radv_cmd_buffer *cmd_buffer,
 	VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
 	VkPipeline pipeline_h;
 	uint32_t offset;
+	int layer = (clear_rect->layerCount > 1) ? META_CLEAR_LAYERED : META_CLEAR_UNLAYERED;
 
 	if (fs_key == -1) {
 		radv_finishme("color clears incomplete");
 		return;
 	}
-	pipeline = device->meta_state.clear[samples_log2].color_pipelines[fs_key];
+	pipeline = device->meta_state.clear[samples_log2].color_pipelines[fs_key][layer];
 	pipeline_h = radv_pipeline_to_handle(pipeline);
 
 	if (!pipeline) {
@@ -447,21 +465,21 @@ emit_color_clear(struct radv_cmd_buffer *cmd_buffer,
 					   pipeline_h);
 	}
 
-	radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0);
+	radv_CmdDraw(cmd_buffer_h, 3, clear_rect->layerCount, 0, 0);
 
 	radv_cmd_buffer_set_subpass(cmd_buffer, subpass, false);
 }
 
 
 static void
-build_depthstencil_shader(struct nir_shader **out_vs, struct nir_shader **out_fs)
+build_depthstencil_shader(struct nir_shader **out_vs, struct nir_shader **out_fs, bool layered)
 {
 	nir_builder vs_b, fs_b;
 
 	nir_builder_init_simple_shader(&vs_b, NULL, MESA_SHADER_VERTEX, NULL);
 	nir_builder_init_simple_shader(&fs_b, NULL, MESA_SHADER_FRAGMENT, NULL);
 
-	vs_b.shader->info->name = ralloc_strdup(vs_b.shader, "meta_clear_depthstencil_vs");
+	vs_b.shader->info->name = ralloc_strdup(vs_b.shader, layered ? "meta_clear_layer_depthstencil_vs" : "meta_clear_depthstencil_vs");
 	fs_b.shader->info->name = ralloc_strdup(fs_b.shader, "meta_clear_depthstencil_fs");
 	const struct glsl_type *position_type = glsl_vec4_type();
 
@@ -477,6 +495,17 @@ build_depthstencil_shader(struct nir_shader **out_vs, struct nir_shader **out_fs
 
 	nir_copy_var(&vs_b, vs_out_pos, vs_in_pos);
 
+	if (layered) {
+		const struct glsl_type *layer_type = glsl_int_type();
+		nir_variable *vs_out_layer =
+			nir_variable_create(vs_b.shader, nir_var_shader_out, layer_type,
+					    "v_layer");
+		vs_out_layer->data.location = VARYING_SLOT_LAYER;
+		vs_out_layer->data.interpolation = INTERP_MODE_FLAT;
+		nir_ssa_def *inst_id = nir_load_system_value(&vs_b, nir_intrinsic_load_instance_id, 0);
+		nir_store_var(&vs_b, vs_out_layer, inst_id, 0x1);
+	}
+
 	*out_vs = vs_b.shader;
 	*out_fs = fs_b.shader;
 }
@@ -521,12 +550,13 @@ create_depthstencil_pipeline(struct radv_device *device,
                              VkImageAspectFlags aspects,
 			     uint32_t samples,
 			     int index,
+			     bool layered,
                              struct radv_pipeline **pipeline,
 			     VkRenderPass render_pass)
 {
 	struct nir_shader *vs_nir, *fs_nir;
 	VkResult result;
-	build_depthstencil_shader(&vs_nir, &fs_nir);
+	build_depthstencil_shader(&vs_nir, &fs_nir, layered);
 
 	const VkPipelineVertexInputStateCreateInfo vi_state = {
 		.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
@@ -588,6 +618,10 @@ create_depthstencil_pipeline(struct radv_device *device,
 	result = create_pipeline(device, radv_render_pass_from_handle(render_pass),
 				 samples, vs_nir, fs_nir, &vi_state, &ds_state, &cb_state,
 				 &extra, &device->meta_state.alloc, pipeline);
+
+	ralloc_free(vs_nir);
+	ralloc_free(fs_nir);
+
 	return result;
 }
 
@@ -619,7 +653,7 @@ pick_depthstencil_pipeline(struct radv_meta_state *meta_state,
 {
 	bool fast = depth_view_can_fast_clear(iview, layout, clear_rect);
 	int index = DEPTH_CLEAR_SLOW;
-
+	int layer = (clear_rect->layerCount > 1) ? META_CLEAR_LAYERED : META_CLEAR_UNLAYERED;
 	if (fast) {
 		/* we don't know the previous clear values, so we always have
 		 * the NO_EXPCLEAR path */
@@ -628,11 +662,11 @@ pick_depthstencil_pipeline(struct radv_meta_state *meta_state,
 
 	switch (aspects) {
 	case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT:
-		return meta_state->clear[samples_log2].depthstencil_pipeline[index];
+		return meta_state->clear[samples_log2].depthstencil_pipeline[index][layer];
 	case VK_IMAGE_ASPECT_DEPTH_BIT:
-		return meta_state->clear[samples_log2].depth_only_pipeline[index];
+		return meta_state->clear[samples_log2].depth_only_pipeline[index][layer];
 	case VK_IMAGE_ASPECT_STENCIL_BIT:
-		return meta_state->clear[samples_log2].stencil_only_pipeline[index];
+		return meta_state->clear[samples_log2].stencil_only_pipeline[index][layer];
 	}
 	unreachable("expected depth or stencil aspect");
 }
@@ -717,7 +751,7 @@ emit_depthstencil_clear(struct radv_cmd_buffer *cmd_buffer,
 	if (depth_view_can_fast_clear(iview, subpass->depth_stencil_attachment.layout, clear_rect))
 		radv_set_depth_clear_regs(cmd_buffer, iview->image, clear_value, aspects);
 
-	radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0);
+	radv_CmdDraw(cmd_buffer_h, 3, clear_rect->layerCount, 0, 0);
 }
 
 
@@ -747,18 +781,20 @@ radv_device_init_meta_clear_state(struct radv_device *device)
 		for (uint32_t j = 0; j < ARRAY_SIZE(pipeline_formats); ++j) {
 			VkFormat format = pipeline_formats[j];
 			unsigned fs_key = radv_format_meta_fs_key(format);
-			assert(!state->clear[i].color_pipelines[fs_key]);
 
 			res = create_color_renderpass(device, format, samples,
 						      &state->clear[i].render_pass[fs_key]);
 			if (res != VK_SUCCESS)
 				goto fail;
 
-			res = create_color_pipeline(device, samples, 0, &state->clear[i].color_pipelines[fs_key],
-						    state->clear[i].render_pass[fs_key]);
-			if (res != VK_SUCCESS)
-				goto fail;
+			for (uint32_t k = 0; k < META_CLEAR_LAYER_COUNT; ++k) {
+				assert(!state->clear[i].color_pipelines[fs_key][k]);
+				res = create_color_pipeline(device, samples, 0, k ? true : false, &state->clear[i].color_pipelines[fs_key][k],
+							    state->clear[i].render_pass[fs_key]);
 
+				if (res != VK_SUCCESS)
+					goto fail;
+			}
 		}
 
 		res = create_depthstencil_renderpass(device,
@@ -768,33 +804,38 @@ radv_device_init_meta_clear_state(struct radv_device *device)
 			goto fail;
 
 		for (uint32_t j = 0; j < NUM_DEPTH_CLEAR_PIPELINES; j++) {
-			res = create_depthstencil_pipeline(device,
-							   VK_IMAGE_ASPECT_DEPTH_BIT,
-							   samples,
-							   j,
-							   &state->clear[i].depth_only_pipeline[j],
-							   state->clear[i].depthstencil_rp);
-			if (res != VK_SUCCESS)
-				goto fail;
-
-			res = create_depthstencil_pipeline(device,
-							   VK_IMAGE_ASPECT_STENCIL_BIT,
-							   samples,
-							   j,
-							   &state->clear[i].stencil_only_pipeline[j],
-							   state->clear[i].depthstencil_rp);
-			if (res != VK_SUCCESS)
-				goto fail;
-
-			res = create_depthstencil_pipeline(device,
-							   VK_IMAGE_ASPECT_DEPTH_BIT |
-							   VK_IMAGE_ASPECT_STENCIL_BIT,
-							   samples,
-							   j,
-							   &state->clear[i].depthstencil_pipeline[j],
-							   state->clear[i].depthstencil_rp);
-			if (res != VK_SUCCESS)
-				goto fail;
+			for (uint32_t k = 0; k < META_CLEAR_LAYER_COUNT; ++k) {
+				res = create_depthstencil_pipeline(device,
+								   VK_IMAGE_ASPECT_DEPTH_BIT,
+								   samples,
+								   j,
+								   k ? true : false,
+								   &state->clear[i].depth_only_pipeline[j][k],
+								   state->clear[i].depthstencil_rp);
+				if (res != VK_SUCCESS)
+					goto fail;
+
+				res = create_depthstencil_pipeline(device,
+								   VK_IMAGE_ASPECT_STENCIL_BIT,
+								   samples,
+								   j,
+								   k ? true : false,
+								   &state->clear[i].stencil_only_pipeline[j][k],
+								   state->clear[i].depthstencil_rp);
+				if (res != VK_SUCCESS)
+					goto fail;
+
+				res = create_depthstencil_pipeline(device,
+								   VK_IMAGE_ASPECT_DEPTH_BIT |
+								   VK_IMAGE_ASPECT_STENCIL_BIT,
+								   samples,
+								   j,
+								   k ? true : false,
+								   &state->clear[i].depthstencil_pipeline[j][k],
+								   state->clear[i].depthstencil_rp);
+				if (res != VK_SUCCESS)
+					goto fail;
+			}
 		}
 	}
 	return VK_SUCCESS;
@@ -948,13 +989,10 @@ radv_cmd_buffer_clear_subpass(struct radv_cmd_buffer *cmd_buffer)
 
 	radv_meta_save_graphics_reset_vport_scissor(&saved_state, cmd_buffer);
 
-	if (cmd_state->framebuffer->layers > 1)
-		radv_finishme("clearing multi-layer framebuffer");
-
 	VkClearRect clear_rect = {
 		.rect = cmd_state->render_area,
 		.baseArrayLayer = 0,
-		.layerCount = 1, /* FINISHME: clear multi-layer framebuffer */
+		.layerCount = cmd_state->framebuffer->layers,
 	};
 
 	for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) {
diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
index 0b8f50a..7bc568d 100644
--- a/src/amd/vulkan/radv_private.h
+++ b/src/amd/vulkan/radv_private.h
@@ -337,6 +337,10 @@ radv_pipeline_cache_insert_shader(struct radv_pipeline_cache *cache,
 void radv_shader_variant_destroy(struct radv_device *device,
 				 struct radv_shader_variant *variant);
 
+#define META_CLEAR_UNLAYERED 0
+#define META_CLEAR_LAYERED 1
+#define META_CLEAR_LAYER_COUNT 2
+
 struct radv_meta_state {
 	VkAllocationCallbacks alloc;
 
@@ -347,12 +351,12 @@ struct radv_meta_state {
 	 */
 	struct {
 		VkRenderPass render_pass[NUM_META_FS_KEYS];
-		struct radv_pipeline *color_pipelines[NUM_META_FS_KEYS];
+		struct radv_pipeline *color_pipelines[NUM_META_FS_KEYS][META_CLEAR_LAYER_COUNT];
 
 		VkRenderPass depthstencil_rp;
-		struct radv_pipeline *depth_only_pipeline[NUM_DEPTH_CLEAR_PIPELINES];
-		struct radv_pipeline *stencil_only_pipeline[NUM_DEPTH_CLEAR_PIPELINES];
-		struct radv_pipeline *depthstencil_pipeline[NUM_DEPTH_CLEAR_PIPELINES];
+		struct radv_pipeline *depth_only_pipeline[NUM_DEPTH_CLEAR_PIPELINES][META_CLEAR_LAYER_COUNT];
+		struct radv_pipeline *stencil_only_pipeline[NUM_DEPTH_CLEAR_PIPELINES][META_CLEAR_LAYER_COUNT];
+		struct radv_pipeline *depthstencil_pipeline[NUM_DEPTH_CLEAR_PIPELINES][META_CLEAR_LAYER_COUNT];
 	} clear[1 + MAX_SAMPLES_LOG2];
 
 	struct {
-- 
2.9.3



More information about the mesa-dev mailing list