From 3dfd8e4d7dde2dfb749c4d115e7f37e5965d460c Mon Sep 17 00:00:00 2001 From: SoroushIMG Date: Wed, 13 Jul 2022 11:59:05 +0100 Subject: [PATCH] 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: 35e346f4280 ("zink: handle vertex streams") Reviewed-By: Mike Blumenkrantz Part-of: --- src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c | 6 ++++-- src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c | 12 ++++++------ src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h | 4 ++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c index 370dffa..f206e52 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c +++ b/src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c @@ -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: diff --git a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c index 7272563..b1573e5 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c +++ b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c @@ -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)); } diff --git a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h index 9c7faaf..01833ce 100644 --- a/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h +++ b/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h @@ -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 -- 2.7.4