From d368d18527c7d44c2aab4b5443cb21980466da15 Mon Sep 17 00:00:00 2001 From: Shaun Ren Date: Mon, 26 May 2025 21:34:06 -0400 Subject: [PATCH] vkd3d-shader/hlsl: Generate vsir instructions for indexed output streams in geometry shaders. --- libs/vkd3d-shader/hlsl_codegen.c | 29 ++++++++++++++----- libs/vkd3d-shader/tpf.c | 2 ++ tests/hlsl/geometry-shader-syntax.shader_test | 6 ++-- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index c9c5da22d..ef412c9d8 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -8485,6 +8485,14 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p VKD3D_ASSERT(regset == HLSL_REGSET_SAMPLERS); *writemask = VKD3DSP_WRITEMASK_ALL; } + else if (regset == HLSL_REGSET_STREAM_OUTPUTS) + { + reg->type = VKD3DSPR_STREAM; + reg->dimension = VSIR_DIMENSION_NONE; + reg->idx[0].offset = var->regs[HLSL_REGSET_STREAM_OUTPUTS].index; + reg->idx_count = 1; + *writemask = VKD3DSP_WRITEMASK_ALL; + } else { unsigned int offset = deref->const_offset + var->buffer_offset; @@ -10835,20 +10843,27 @@ static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx, if (store->store_type != HLSL_RESOURCE_STORE) { - enum vkd3d_shader_opcode opcode = store->store_type == HLSL_RESOURCE_STREAM_APPEND - ? VKD3DSIH_EMIT : VKD3DSIH_CUT; + enum vkd3d_shader_opcode opcode; VKD3D_ASSERT(!store->value.node && !store->coords.node); VKD3D_ASSERT(store->resource.var->regs[HLSL_REGSET_STREAM_OUTPUTS].allocated); - if (store->resource.var->regs[HLSL_REGSET_STREAM_OUTPUTS].index) + if (hlsl_version_lt(ctx, 5, 0)) { - hlsl_fixme(ctx, &instr->loc, "Stream output operation with a nonzero stream index."); - return false; + opcode = store->store_type == HLSL_RESOURCE_STREAM_APPEND ? VKD3DSIH_EMIT : VKD3DSIH_CUT; + ins = generate_vsir_add_program_instruction(ctx, program, &store->node.loc, opcode, 0, 0); + return !!ins; } - ins = generate_vsir_add_program_instruction(ctx, program, &store->node.loc, opcode, 0, 0); - return !!ins; + opcode = store->store_type == HLSL_RESOURCE_STREAM_APPEND ? VKD3DSIH_EMIT_STREAM : VKD3DSIH_CUT_STREAM; + if (!(ins = generate_vsir_add_program_instruction(ctx, program, &store->node.loc, opcode, 0, 1))) + return false; + + if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program, &ins->src[0], + &store->resource, VKD3DSP_WRITEMASK_ALL, &instr->loc)) + return false; + + return true; } if (!store->resource.var->is_uniform) diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 8ed9fa031..19ca97cb4 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -4176,6 +4176,7 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ case VKD3DSIH_CASE: case VKD3DSIH_CONTINUE: case VKD3DSIH_CUT: + case VKD3DSIH_CUT_STREAM: case VKD3DSIH_DCL_STREAM: case VKD3DSIH_DEFAULT: case VKD3DSIH_DISCARD: @@ -4191,6 +4192,7 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ case VKD3DSIH_DSY_FINE: case VKD3DSIH_ELSE: case VKD3DSIH_EMIT: + case VKD3DSIH_EMIT_STREAM: case VKD3DSIH_ENDIF: case VKD3DSIH_ENDLOOP: case VKD3DSIH_ENDSWITCH: diff --git a/tests/hlsl/geometry-shader-syntax.shader_test b/tests/hlsl/geometry-shader-syntax.shader_test index be481a534..6fa833011 100644 --- a/tests/hlsl/geometry-shader-syntax.shader_test +++ b/tests/hlsl/geometry-shader-syntax.shader_test @@ -541,7 +541,7 @@ gs_data main(point gs_data vin[1], inout TriangleStream vout) } % Output streams with nonzero stream indices are only allowed with point streams, and with SM >= 5. -[geometry shader fail(sm<5) todo(sm>=5)] +[geometry shader fail(sm<5)] struct gs_data { float4 pos : SV_POSITION; @@ -610,7 +610,7 @@ void main(point gs_data vin[1], inout PointStream vout1, inout Triangle vout1.RestartStrip(); } -[geometry shader fail(sm<5) todo(sm>=5)] +[geometry shader fail(sm<5)] struct gs_data { float4 pos : SV_POSITION; @@ -623,7 +623,7 @@ void main(point gs_data vin[1], inout PointStream vout1, inout Triangle } % A maximum of 4 streams are allowed. -[geometry shader fail(sm<5) todo(sm>=5)] +[geometry shader fail(sm<5)] struct gs_data { float4 pos : SV_POSITION;