From: Faith Ekstrand Date: Fri, 31 Mar 2023 16:44:09 +0000 (-0500) Subject: vulkan/meta: Insert a geometry shader when needed X-Git-Tag: upstream/23.3.3~4004 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=74e8be6545dd695f7e13c43632fd3b4c597c45dc;p=platform%2Fupstream%2Fmesa.git vulkan/meta: Insert a geometry shader when needed Part-of: --- diff --git a/src/vulkan/runtime/vk_meta.c b/src/vulkan/runtime/vk_meta.c index a6ccbf6..bcdc869 100644 --- a/src/vulkan/runtime/vk_meta.c +++ b/src/vulkan/runtime/vk_meta.c @@ -276,24 +276,46 @@ create_rect_list_pipeline(struct vk_device *device, VkGraphicsPipelineCreateInfo info_local = *info; - STACK_ARRAY(VkPipelineShaderStageCreateInfo, stages, info->stageCount + 1); - for (uint32_t i = 0; i < info->stageCount; i++) { - assert(info->pStages[i].stage != VK_SHADER_STAGE_VERTEX_BIT); - stages[i + 1] = info->pStages[i]; - } + /* We always configure for layered rendering for now */ + bool use_gs = meta->use_gs_for_layer; + + STACK_ARRAY(VkPipelineShaderStageCreateInfo, stages, + info->stageCount + 1 + use_gs); + uint32_t stage_count = 0; VkPipelineShaderStageNirCreateInfoMESA vs_nir_info = { .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_NIR_CREATE_INFO_MESA, - .nir = vk_meta_draw_rects_vs_nir(meta), + .nir = vk_meta_draw_rects_vs_nir(meta, use_gs), }; - stages[0] = (VkPipelineShaderStageCreateInfo) { + stages[stage_count++] = (VkPipelineShaderStageCreateInfo) { .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .pNext = &vs_nir_info, .stage = VK_SHADER_STAGE_VERTEX_BIT, .pName = "main", }; - info_local.stageCount = info->stageCount + 1; + VkPipelineShaderStageNirCreateInfoMESA gs_nir_info; + if (use_gs) { + gs_nir_info = (VkPipelineShaderStageNirCreateInfoMESA) { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_NIR_CREATE_INFO_MESA, + .nir = vk_meta_draw_rects_gs_nir(meta), + }; + stages[stage_count++] = (VkPipelineShaderStageCreateInfo) { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .pNext = &gs_nir_info, + .stage = VK_SHADER_STAGE_GEOMETRY_BIT, + .pName = "main", + }; + } + + for (uint32_t i = 0; i < info->stageCount; i++) { + assert(info->pStages[i].stage != VK_SHADER_STAGE_VERTEX_BIT); + if (use_gs) + assert(info->pStages[i].stage != VK_SHADER_STAGE_GEOMETRY_BIT); + stages[stage_count++] = info->pStages[i]; + } + + info_local.stageCount = stage_count; info_local.pStages = stages; info_local.pVertexInputState = &vk_meta_draw_rects_vi_state; info_local.pViewportState = &vk_meta_draw_rects_vs_state; diff --git a/src/vulkan/runtime/vk_meta.h b/src/vulkan/runtime/vk_meta.h index cac550e..da085bc 100644 --- a/src/vulkan/runtime/vk_meta.h +++ b/src/vulkan/runtime/vk_meta.h @@ -52,6 +52,7 @@ struct vk_meta_device { uint32_t max_bind_map_buffer_size_B; bool use_layered_rendering; + bool use_gs_for_layer; bool use_stencil_export; VkResult (*cmd_bind_map_buffer)(struct vk_command_buffer *cmd, diff --git a/src/vulkan/runtime/vk_meta_draw_rects.c b/src/vulkan/runtime/vk_meta_draw_rects.c index cba81e8..d0fd7fc 100644 --- a/src/vulkan/runtime/vk_meta_draw_rects.c +++ b/src/vulkan/runtime/vk_meta_draw_rects.c @@ -59,7 +59,7 @@ const VkPipelineViewportStateCreateInfo vk_meta_draw_rects_vs_state = { }; nir_shader * -vk_meta_draw_rects_vs_nir(struct vk_meta_device *device) +vk_meta_draw_rects_vs_nir(struct vk_meta_device *device, bool use_gs) { nir_builder build = nir_builder_init_simple_shader(MESA_SHADER_VERTEX, NULL, "vk-meta-draw-rects-vs"); @@ -69,13 +69,15 @@ vk_meta_draw_rects_vs_nir(struct vk_meta_device *device) glsl_uvec4_type(), "vtx_in"); in->data.location = VERT_ATTRIB_GENERIC0; - nir_variable *pos = nir_variable_create(b->shader, nir_var_shader_out, - glsl_vec4_type(), "gl_Position"); - pos->data.location = VARYING_SLOT_POS; + nir_variable *pos = + nir_variable_create(b->shader, nir_var_shader_out, glsl_vec4_type(), + use_gs ? "pos_out" : "gl_Position"); + pos->data.location = use_gs ? VARYING_SLOT_VAR0 : VARYING_SLOT_POS; - nir_variable *layer = nir_variable_create(b->shader, nir_var_shader_out, - glsl_int_type(), "gl_Layer"); - layer->data.location = VARYING_SLOT_LAYER; + nir_variable *layer = + nir_variable_create(b->shader, nir_var_shader_out, glsl_int_type(), + use_gs ? "layer_out" : "gl_Layer"); + layer->data.location = use_gs ? VARYING_SLOT_VAR1 : VARYING_SLOT_LAYER; nir_ssa_def *vtx = nir_load_var(b, in); nir_store_var(b, pos, nir_vec4(b, nir_channel(b, vtx, 0), @@ -83,6 +85,7 @@ vk_meta_draw_rects_vs_nir(struct vk_meta_device *device) nir_channel(b, vtx, 2), nir_imm_float(b, 1)), 0xf); + nir_store_var(b, layer, nir_iadd(b, nir_load_instance_id(b), nir_channel(b, vtx, 3)), 0x1); @@ -90,6 +93,58 @@ vk_meta_draw_rects_vs_nir(struct vk_meta_device *device) return b->shader; } +nir_shader * +vk_meta_draw_rects_gs_nir(struct vk_meta_device *device) +{ + nir_builder build = + nir_builder_init_simple_shader(MESA_SHADER_GEOMETRY, NULL, + "vk-meta-draw-rects-gs"); + nir_builder *b = &build; + + nir_variable *pos_in = + nir_variable_create(b->shader, nir_var_shader_in, + glsl_array_type(glsl_vec4_type(), 3, 0), "pos_in"); + pos_in->data.location = VARYING_SLOT_VAR0; + + nir_variable *layer_in = + nir_variable_create(b->shader, nir_var_shader_in, + glsl_array_type(glsl_int_type(), 3, 0), "layer_in"); + layer_in->data.location = VARYING_SLOT_VAR1; + + nir_variable *pos_out = + nir_variable_create(b->shader, nir_var_shader_out, + glsl_vec4_type(), "gl_Position"); + pos_out->data.location = VARYING_SLOT_POS; + + nir_variable *layer_out = + nir_variable_create(b->shader, nir_var_shader_out, + glsl_int_type(), "gl_Layer"); + layer_out->data.location = VARYING_SLOT_LAYER; + + for (unsigned i = 0; i < 3; i++) { + nir_deref_instr *pos_in_deref = + nir_build_deref_array_imm(b, nir_build_deref_var(b, pos_in), i); + nir_deref_instr *layer_in_deref = + nir_build_deref_array_imm(b, nir_build_deref_var(b, layer_in), i); + + nir_store_var(b, pos_out, nir_load_deref(b, pos_in_deref), 0xf); + nir_store_var(b, layer_out, nir_load_deref(b, layer_in_deref), 1); + nir_emit_vertex(b); + } + + nir_end_primitive(b); + + struct shader_info *info = &build.shader->info; + info->gs.input_primitive = MESA_PRIM_TRIANGLES; + info->gs.output_primitive = MESA_PRIM_TRIANGLE_STRIP; + info->gs.vertices_in = 3; + info->gs.vertices_out = 3; + info->gs.invocations = 1; + info->gs.active_stream_mask = 1; + + return b->shader; +} + struct vertex { float x, y, z; uint32_t layer; diff --git a/src/vulkan/runtime/vk_meta_private.h b/src/vulkan/runtime/vk_meta_private.h index e83d02f..a8b2a97 100644 --- a/src/vulkan/runtime/vk_meta_private.h +++ b/src/vulkan/runtime/vk_meta_private.h @@ -34,7 +34,11 @@ extern const VkPipelineVertexInputStateCreateInfo vk_meta_draw_rects_vi_state; extern const VkPipelineInputAssemblyStateCreateInfo vk_meta_draw_rects_ia_state; extern const VkPipelineViewportStateCreateInfo vk_meta_draw_rects_vs_state; -struct nir_shader *vk_meta_draw_rects_vs_nir(struct vk_meta_device *device); +struct nir_shader * +vk_meta_draw_rects_vs_nir(struct vk_meta_device *device, bool use_gs); + +struct nir_shader * +vk_meta_draw_rects_gs_nir(struct vk_meta_device *device); static inline void vk_meta_rendering_info_copy(struct vk_meta_rendering_info *dst,