mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-31 12:00:12 +01:00
zink: add handling for gs in ntv
this hooks up execution modes and the gs-specific instructions Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7139>
This commit is contained in:
parent
9671cd9215
commit
d656c600a3
4 changed files with 125 additions and 6 deletions
|
|
@ -39,6 +39,7 @@ struct ntv_context {
|
|||
SpvId GLSL_std_450;
|
||||
|
||||
gl_shader_stage stage;
|
||||
const struct zink_so_info *so_info;
|
||||
|
||||
SpvId ubos[128];
|
||||
size_t num_ubos;
|
||||
|
|
@ -1703,6 +1704,23 @@ emit_intrinsic(struct ntv_context *ctx, nir_intrinsic_instr *intr)
|
|||
emit_load_uint_input(ctx, intr, &ctx->invocation_id_var, "gl_InvocationId", SpvBuiltInInvocationId);
|
||||
break;
|
||||
|
||||
case nir_intrinsic_emit_vertex_with_counter:
|
||||
/* geometry shader emits copied xfb outputs just prior to EmitVertex(),
|
||||
* since that's the end of the shader
|
||||
*/
|
||||
if (ctx->so_info)
|
||||
emit_so_outputs(ctx, ctx->so_info);
|
||||
spirv_builder_emit_vertex(&ctx->builder);
|
||||
break;
|
||||
|
||||
case nir_intrinsic_set_vertex_and_primitive_count:
|
||||
/* do nothing */
|
||||
break;
|
||||
|
||||
case nir_intrinsic_end_primitive_with_counter:
|
||||
spirv_builder_end_primitive(&ctx->builder);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "emit_intrinsic: not implemented (%s)\n",
|
||||
nir_intrinsic_infos[intr->intrinsic].name);
|
||||
|
|
@ -2202,6 +2220,86 @@ emit_cf_list(struct ntv_context *ctx, struct exec_list *list)
|
|||
}
|
||||
}
|
||||
|
||||
static SpvExecutionMode
|
||||
get_input_prim_type_mode(uint16_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case GL_POINTS:
|
||||
return SpvExecutionModeInputPoints;
|
||||
case GL_LINES:
|
||||
case GL_LINE_LOOP:
|
||||
case GL_LINE_STRIP:
|
||||
return SpvExecutionModeInputLines;
|
||||
case GL_TRIANGLE_STRIP:
|
||||
case GL_TRIANGLES:
|
||||
case GL_TRIANGLE_FAN:
|
||||
return SpvExecutionModeTriangles;
|
||||
case GL_QUADS:
|
||||
case GL_QUAD_STRIP:
|
||||
return SpvExecutionModeQuads;
|
||||
break;
|
||||
case GL_POLYGON:
|
||||
unreachable("handle polygons in gs");
|
||||
break;
|
||||
case GL_LINES_ADJACENCY:
|
||||
case GL_LINE_STRIP_ADJACENCY:
|
||||
return SpvExecutionModeInputLinesAdjacency;
|
||||
case GL_TRIANGLES_ADJACENCY:
|
||||
case GL_TRIANGLE_STRIP_ADJACENCY:
|
||||
return SpvExecutionModeInputTrianglesAdjacency;
|
||||
break;
|
||||
case GL_ISOLINES:
|
||||
return SpvExecutionModeIsolines;
|
||||
default:
|
||||
debug_printf("unknown geometry shader input mode %u\n", type);
|
||||
unreachable("error!");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static SpvExecutionMode
|
||||
get_output_prim_type_mode(uint16_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case GL_POINTS:
|
||||
return SpvExecutionModeOutputPoints;
|
||||
case GL_LINES:
|
||||
case GL_LINE_LOOP:
|
||||
unreachable("GL_LINES/LINE_LOOP passed as gs output");
|
||||
break;
|
||||
case GL_LINE_STRIP:
|
||||
return SpvExecutionModeOutputLineStrip;
|
||||
case GL_TRIANGLE_STRIP:
|
||||
return SpvExecutionModeOutputTriangleStrip;
|
||||
case GL_TRIANGLES:
|
||||
case GL_TRIANGLE_FAN: //FIXME: not sure if right for output
|
||||
return SpvExecutionModeTriangles;
|
||||
case GL_QUADS:
|
||||
case GL_QUAD_STRIP:
|
||||
return SpvExecutionModeQuads;
|
||||
case GL_POLYGON:
|
||||
unreachable("handle polygons in gs");
|
||||
break;
|
||||
case GL_LINES_ADJACENCY:
|
||||
case GL_LINE_STRIP_ADJACENCY:
|
||||
unreachable("handle line adjacency in gs");
|
||||
break;
|
||||
case GL_TRIANGLES_ADJACENCY:
|
||||
case GL_TRIANGLE_STRIP_ADJACENCY:
|
||||
unreachable("handle triangle adjacency in gs");
|
||||
break;
|
||||
case GL_ISOLINES:
|
||||
return SpvExecutionModeIsolines;
|
||||
default:
|
||||
debug_printf("unknown geometry shader output mode %u\n", type);
|
||||
unreachable("error!");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct spirv_shader *
|
||||
nir_to_spirv(struct nir_shader *s, const struct zink_so_info *so_info,
|
||||
unsigned char *shader_slot_map, unsigned char *shader_slots_reserved)
|
||||
|
|
@ -2228,6 +2326,10 @@ nir_to_spirv(struct nir_shader *s, const struct zink_so_info *so_info,
|
|||
|
||||
case MESA_SHADER_GEOMETRY:
|
||||
spirv_builder_emit_cap(&ctx.builder, SpvCapabilityGeometry);
|
||||
if (s->info.gs.active_stream_mask)
|
||||
spirv_builder_emit_cap(&ctx.builder, SpvCapabilityGeometryStreams);
|
||||
if (s->info.outputs_written & BITFIELD64_BIT(VARYING_SLOT_PSIZ))
|
||||
spirv_builder_emit_cap(&ctx.builder, SpvCapabilityGeometryPointSize);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -2249,6 +2351,7 @@ nir_to_spirv(struct nir_shader *s, const struct zink_so_info *so_info,
|
|||
}
|
||||
|
||||
ctx.stage = s->info.stage;
|
||||
ctx.so_info = so_info;
|
||||
ctx.shader_slot_map = shader_slot_map;
|
||||
ctx.shader_slots_reserved = *shader_slots_reserved;
|
||||
ctx.GLSL_std_450 = spirv_builder_import(&ctx.builder, "GLSL.std.450");
|
||||
|
|
@ -2309,20 +2412,28 @@ nir_to_spirv(struct nir_shader *s, const struct zink_so_info *so_info,
|
|||
nir_var_mem_ssbo))
|
||||
emit_uniform(&ctx, var);
|
||||
|
||||
if (s->info.stage == MESA_SHADER_FRAGMENT) {
|
||||
switch (s->info.stage) {
|
||||
case MESA_SHADER_FRAGMENT:
|
||||
spirv_builder_emit_exec_mode(&ctx.builder, entry_point,
|
||||
SpvExecutionModeOriginUpperLeft);
|
||||
if (s->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_DEPTH))
|
||||
spirv_builder_emit_exec_mode(&ctx.builder, entry_point,
|
||||
SpvExecutionModeDepthReplacing);
|
||||
break;
|
||||
case MESA_SHADER_GEOMETRY:
|
||||
spirv_builder_emit_exec_mode(&ctx.builder, entry_point, get_input_prim_type_mode(s->info.gs.input_primitive));
|
||||
spirv_builder_emit_exec_mode(&ctx.builder, entry_point, get_output_prim_type_mode(s->info.gs.output_primitive));
|
||||
spirv_builder_emit_exec_mode_literal(&ctx.builder, entry_point, SpvExecutionModeInvocations, s->info.gs.invocations);
|
||||
spirv_builder_emit_exec_mode_literal(&ctx.builder, entry_point, SpvExecutionModeOutputVertices, s->info.gs.vertices_out);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (so_info && so_info->so_info.num_outputs) {
|
||||
spirv_builder_emit_cap(&ctx.builder, SpvCapabilityTransformFeedback);
|
||||
spirv_builder_emit_exec_mode(&ctx.builder, entry_point,
|
||||
SpvExecutionModeXfb);
|
||||
}
|
||||
|
||||
spirv_builder_function(&ctx.builder, entry_point, type_void,
|
||||
SpvFunctionControlMaskNone,
|
||||
type_main);
|
||||
|
|
@ -2369,7 +2480,8 @@ nir_to_spirv(struct nir_shader *s, const struct zink_so_info *so_info,
|
|||
|
||||
emit_cf_list(&ctx, &entry->body);
|
||||
|
||||
if (so_info)
|
||||
/* vertex shader emits copied xfb outputs at the end of the shader */
|
||||
if (so_info && ctx.stage == MESA_SHADER_VERTEX)
|
||||
emit_so_outputs(&ctx, so_info);
|
||||
|
||||
spirv_builder_return(&ctx.builder); // doesn't belong here, but whatevz
|
||||
|
|
|
|||
|
|
@ -221,7 +221,9 @@ zink_shader_compile(struct zink_screen *screen, struct zink_shader *zs,
|
|||
unsigned char *shader_slot_map, unsigned char *shader_slots_reserved)
|
||||
{
|
||||
VkShaderModule mod = VK_NULL_HANDLE;
|
||||
void *streamout = zs->streamout.so_info_slots ? &zs->streamout : NULL;
|
||||
void *streamout = NULL;
|
||||
if (zs->streamout.so_info_slots && (zs->nir->info.stage != MESA_SHADER_VERTEX || !zs->has_geometry_shader))
|
||||
streamout = &zs->streamout;
|
||||
struct spirv_shader *spirv = nir_to_spirv(zs->nir, streamout, shader_slot_map, shader_slots_reserved);
|
||||
assert(spirv);
|
||||
|
||||
|
|
@ -267,8 +269,10 @@ zink_shader_create(struct zink_screen *screen, struct nir_shader *nir,
|
|||
NIR_PASS_V(nir, nir_lower_uniforms_to_ubo, 16);
|
||||
NIR_PASS_V(nir, nir_lower_ubo_vec4);
|
||||
NIR_PASS_V(nir, nir_lower_clip_halfz);
|
||||
if (nir->info.stage == MESA_SHADER_VERTEX)
|
||||
if (nir->info.stage < MESA_SHADER_FRAGMENT)
|
||||
have_psiz = check_psiz(nir);
|
||||
if (nir->info.stage == MESA_SHADER_GEOMETRY)
|
||||
NIR_PASS_V(nir, nir_lower_gs_intrinsics, nir_lower_gs_intrinsics_per_stream);
|
||||
NIR_PASS_V(nir, nir_lower_regs_to_ssa);
|
||||
optimize_nir(nir);
|
||||
NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_function_temp, NULL);
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ struct zink_shader {
|
|||
} bindings[PIPE_MAX_CONSTANT_BUFFERS + PIPE_MAX_SHADER_SAMPLER_VIEWS];
|
||||
size_t num_bindings;
|
||||
struct set *programs;
|
||||
|
||||
bool has_geometry_shader; // vertex shaders need to know if a geometry shader exists
|
||||
};
|
||||
|
||||
VkShaderModule
|
||||
|
|
|
|||
|
|
@ -153,6 +153,7 @@ update_shader_modules(struct zink_context *ctx, struct zink_shader *stages[ZINK_
|
|||
prog->modules[type] = CALLOC_STRUCT(zink_shader_module);
|
||||
assert(prog->modules[type]);
|
||||
pipe_reference_init(&prog->modules[type]->reference, 1);
|
||||
dirty[i]->has_geometry_shader = dirty[MESA_SHADER_GEOMETRY] || stages[PIPE_SHADER_GEOMETRY];
|
||||
prog->modules[type]->shader = zink_shader_compile(zink_screen(ctx->base.screen), dirty[i],
|
||||
prog->shader_slot_map, &prog->shader_slots_reserved);
|
||||
} else if (stages[type]) /* reuse existing shader module */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue