zink: Fix spirv stream 0 vertex emit for multistream shaders

Spirv spec does not allow the use of OpEmitVertex or OpEndPrimitive when there are multiple streams.
Instead emit the multi-stream version of these with stream set to 0.
This issue was seen when testing cts case KHR-GL46.transform_feedback.draw_xfb_stream_test

Fixes: 35e346f428 ("zink: handle vertex streams")
Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17513>
This commit is contained in:
SoroushIMG 2022-07-13 11:59:05 +01:00 committed by Marge Bot
parent 9ecc26ff27
commit 3dfd8e4d7d
3 changed files with 12 additions and 10 deletions

View file

@ -3060,7 +3060,8 @@ emit_intrinsic(struct ntv_context *ctx, nir_intrinsic_instr *intr)
*/
if (ctx->sinfo)
emit_so_outputs(ctx, ctx->sinfo);
spirv_builder_emit_vertex(&ctx->builder, nir_intrinsic_stream_id(intr));
spirv_builder_emit_vertex(&ctx->builder, nir_intrinsic_stream_id(intr),
ctx->nir->info.stage == MESA_SHADER_GEOMETRY && util_bitcount(ctx->nir->info.gs.active_stream_mask) > 1);
break;
case nir_intrinsic_set_vertex_and_primitive_count:
@ -3068,7 +3069,8 @@ emit_intrinsic(struct ntv_context *ctx, nir_intrinsic_instr *intr)
break;
case nir_intrinsic_end_primitive_with_counter:
spirv_builder_end_primitive(&ctx->builder, nir_intrinsic_stream_id(intr));
spirv_builder_end_primitive(&ctx->builder, nir_intrinsic_stream_id(intr),
ctx->nir->info.stage == MESA_SHADER_GEOMETRY && util_bitcount(ctx->nir->info.gs.active_stream_mask) > 1);
break;
case nir_intrinsic_load_helper_invocation:

View file

@ -255,32 +255,32 @@ spirv_builder_emit_builtin(struct spirv_builder *b, SpvId target,
}
void
spirv_builder_emit_vertex(struct spirv_builder *b, uint32_t stream)
spirv_builder_emit_vertex(struct spirv_builder *b, uint32_t stream, bool multistream)
{
unsigned words = 1;
SpvOp op = SpvOpEmitVertex;
if (stream > 0) {
if (multistream) {
op = SpvOpEmitStreamVertex;
words++;
}
spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
spirv_buffer_emit_word(&b->instructions, op | (words << 16));
if (stream)
if (multistream)
spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, stream));
}
void
spirv_builder_end_primitive(struct spirv_builder *b, uint32_t stream)
spirv_builder_end_primitive(struct spirv_builder *b, uint32_t stream, bool multistream)
{
unsigned words = 1;
SpvOp op = SpvOpEndPrimitive;
if (stream > 0) {
if (multistream || stream > 0) {
op = SpvOpEndStreamPrimitive;
words++;
}
spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
spirv_buffer_emit_word(&b->instructions, op | (words << 16));
if (stream)
if (multistream || stream > 0)
spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, stream));
}

View file

@ -460,7 +460,7 @@ spirv_builder_get_words(struct spirv_builder *b, uint32_t *words,
uint32_t *tcs_vertices_out_word);
void
spirv_builder_emit_vertex(struct spirv_builder *b, uint32_t stream);
spirv_builder_emit_vertex(struct spirv_builder *b, uint32_t stream, bool multistream);
void
spirv_builder_end_primitive(struct spirv_builder *b, uint32_t stream);
spirv_builder_end_primitive(struct spirv_builder *b, uint32_t stream, bool multistream);
#endif