zink: Fix spirv stream 0 vertex emit for multistream shaders
authorSoroushIMG <soroush.kashani@imgtec.com>
Wed, 13 Jul 2022 10:59:05 +0000 (11:59 +0100)
committerMarge Bot <emma+marge@anholt.net>
Wed, 20 Jul 2022 00:19:38 +0000 (00:19 +0000)
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: 35e346f4280 ("zink: handle vertex streams")
Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17513>

src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c
src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c
src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h

index 370dffa..f206e52 100644 (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:
index 7272563..b1573e5 100644 (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));
 }
 
index 9c7faaf..01833ce 100644 (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