vulkan/meta: Insert a geometry shader when needed

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>
This commit is contained in:
Faith Ekstrand 2023-03-31 11:44:09 -05:00 committed by Marge Bot
parent af3400a957
commit 74e8be6545
4 changed files with 98 additions and 16 deletions

View file

@ -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;

View file

@ -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,

View file

@ -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;

View file

@ -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,