[Mesa-dev] [PATCH] radv: add support for layered clears
Bas Nieuwenhuizen
bas at basnieuwenhuizen.nl
Mon Jan 16 23:07:57 UTC 2017
Looks correct to me, but why don't we always use the layered clear?
I'd think the extra VS output doesn't really matter given the low
amount of geometry during clearing, and that would save some shader
variants, which we have a lot of already.
- Bas
On Mon, Jan 16, 2017 at 11:58 PM, Dave Airlie <airlied at gmail.com> wrote:
> 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
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list