From 2cad994e90a6ec20af764d6674b249d3e6dacfbc Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 15 May 2018 13:48:58 +1000 Subject: [PATCH] arb_gpu_shader5: add support for vertex streams. This adds support for the transform feedback vertex streams Tested-by: Gurchetan Singh Reviewed-by: Gurchetan Singh --- src/gallium/include/pipe/p_state.h | 1 + src/vrend_decode.c | 2 + src/vrend_renderer.c | 5 ++- src/vrend_shader.c | 61 +++++++++++++++++++++++++----- 4 files changed, 57 insertions(+), 12 deletions(-) diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h index 2b4d9e4..80be1b5 100644 --- a/src/gallium/include/pipe/p_state.h +++ b/src/gallium/include/pipe/p_state.h @@ -206,6 +206,7 @@ struct pipe_stream_output_info unsigned num_components:3; /** 1 to 4 */ unsigned output_buffer:3; /**< 0 to PIPE_MAX_SO_BUFFERS */ unsigned dst_offset:16; /**< offset into the buffer in dwords */ + unsigned stream:2; } output[PIPE_MAX_SO_OUTPUTS]; }; diff --git a/src/vrend_decode.c b/src/vrend_decode.c index 96f6077..1e31573 100644 --- a/src/vrend_decode.c +++ b/src/vrend_decode.c @@ -97,6 +97,8 @@ static int vrend_decode_create_shader(struct vrend_decode_ctx *ctx, so_info.output[i].num_components = (tmp >> 10) & 0x7; so_info.output[i].output_buffer = (tmp >> 13) & 0x7; so_info.output[i].dst_offset = (tmp >> 16) & 0xffff; + tmp = get_buf_entry(ctx, VIRGL_OBJ_SHADER_SO_OUTPUT0_SO(i)); + so_info.output[i].stream = (tmp & 0x3); } } shader_offset += 4 + (2 * num_so_outputs); diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index 5286695..e7fe8ea 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -771,13 +771,14 @@ static void dump_stream_out(struct pipe_stream_output_info *so) printf("\n"); printf("outputs:\n"); for (i = 0; i < so->num_outputs; i++) { - printf("\t%d: reg: %d sc: %d, nc: %d ob: %d do: %d\n", + printf("\t%d: reg: %d sc: %d, nc: %d ob: %d do: %d st: %d\n", i, so->output[i].register_index, so->output[i].start_component, so->output[i].num_components, so->output[i].output_buffer, - so->output[i].dst_offset); + so->output[i].dst_offset, + so->output[i].stream); } } diff --git a/src/vrend_shader.c b/src/vrend_shader.c index b2573d5..3ded04c 100644 --- a/src/vrend_shader.c +++ b/src/vrend_shader.c @@ -55,6 +55,7 @@ struct vrend_shader_io { bool override_no_wm; bool is_int; char glsl_name[64]; + unsigned stream; }; struct vrend_shader_sampler { @@ -930,6 +931,29 @@ static int emit_prescale(struct dump_ctx *ctx) return 0; } +static int prepare_so_movs(struct dump_ctx *ctx) +{ + int i; + for (i = 0; i < ctx->so->num_outputs; i++) { + ctx->write_so_outputs[i] = true; + if (ctx->so->output[i].start_component != 0) + continue; + if (ctx->so->output[i].num_components != 4) + continue; + if (ctx->outputs[ctx->so->output[i].register_index].name == TGSI_SEMANTIC_CLIPDIST) + continue; + if (ctx->outputs[ctx->so->output[i].register_index].name == TGSI_SEMANTIC_POSITION) + continue; + + ctx->outputs[ctx->so->output[i].register_index].stream = ctx->so->output[i].stream; + if (ctx->prog_type == TGSI_PROCESSOR_GEOMETRY && ctx->so->output[i].stream) + ctx->uses_gpu_shader5 = true; + + ctx->write_so_outputs[i] = false; + } + return 0; +} + static int emit_so_movs(struct dump_ctx *ctx) { char buf[255]; @@ -960,7 +984,7 @@ static int emit_so_movs(struct dump_ctx *ctx) } else writemask[0] = 0; - if (ctx->so->output[i].num_components == 4 && writemask[0] == 0 && !(ctx->outputs[ctx->so->output[i].register_index].name == TGSI_SEMANTIC_CLIPDIST) && !(ctx->outputs[ctx->so->output[i].register_index].name == TGSI_SEMANTIC_POSITION)) { + if (!ctx->write_so_outputs[i]) { if (ctx->so->output[i].register_index > ctx->num_outputs) ctx->so_names[i] = NULL; else if (ctx->outputs[ctx->so->output[i].register_index].name == TGSI_SEMANTIC_CLIPVERTEX && ctx->has_clipvertex) { @@ -968,13 +992,10 @@ static int emit_so_movs(struct dump_ctx *ctx) ctx->has_clipvertex_so = true; } else ctx->so_names[i] = strdup(ctx->outputs[ctx->so->output[i].register_index].glsl_name); - ctx->write_so_outputs[i] = false; - } else { char ntemp[8]; snprintf(ntemp, 8, "tfout%d", i); ctx->so_names[i] = strdup(ntemp); - ctx->write_so_outputs[i] = true; } if (ctx->so->output[i].num_components == 1) { if (ctx->outputs[ctx->so->output[i].register_index].is_int) @@ -1641,6 +1662,8 @@ iter_instruction(struct tgsi_iterate_context *iter, if (ret) return FALSE; } + if (ctx->so) + prepare_so_movs(ctx); } for (i = 0; i < inst->Instruction.NumDstRegs; i++) { const struct tgsi_full_dst_register *dst = &inst->Dst[i]; @@ -2263,7 +2286,8 @@ iter_instruction(struct tgsi_iterate_context *iter, snprintf(buf, 255, "break;\n"); EMIT_BUF_WITH_RET(ctx, buf); break; - case TGSI_OPCODE_EMIT: + case TGSI_OPCODE_EMIT: { + struct immed *imd = &ctx->imm[(inst->Src[0].Register.Index)]; if (ctx->so && ctx->key->gs_present) { emit_so_movs(ctx); } @@ -2273,13 +2297,24 @@ iter_instruction(struct tgsi_iterate_context *iter, ret = emit_prescale(ctx); if (ret) return FALSE; - snprintf(buf, 255, "EmitVertex();\n"); + if (imd->val[inst->Src[0].Register.SwizzleX].ui > 0) { + ctx->uses_gpu_shader5 = true; + snprintf(buf, 255, "EmitStreamVertex(%d);\n", imd->val[inst->Src[0].Register.SwizzleX].ui); + } else + snprintf(buf, 255, "EmitVertex();\n"); EMIT_BUF_WITH_RET(ctx, buf); break; - case TGSI_OPCODE_ENDPRIM: - snprintf(buf, 255, "EndPrimitive();\n"); + } + case TGSI_OPCODE_ENDPRIM: { + struct immed *imd = &ctx->imm[(inst->Src[0].Register.Index)]; + if (imd->val[inst->Src[0].Register.SwizzleX].ui > 0) { + ctx->uses_gpu_shader5 = true; + snprintf(buf, 255, "EndStreamPrimitive(%d);\n", imd->val[inst->Src[0].Register.SwizzleX].ui); + } else + snprintf(buf, 255, "EndPrimitive();\n"); EMIT_BUF_WITH_RET(ctx, buf); break; + } default: fprintf(stderr,"failed to convert opcode %d\n", inst->Instruction.Opcode); break; @@ -2510,7 +2545,10 @@ static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr) } else prefix = ""; /* ugly leave spaces to patch interp in later */ - snprintf(buf, 255, "%s%sout vec4 %s;\n", prefix, ctx->outputs[i].invariant ? "invariant " : "", ctx->outputs[i].glsl_name); + if (ctx->prog_type == TGSI_PROCESSOR_GEOMETRY && ctx->outputs[i].stream) + snprintf(buf, 255, "layout (stream = %d) %s%sout vec4 %s;\n", ctx->outputs[i].stream, prefix, ctx->outputs[i].invariant ? "invariant " : "", ctx->outputs[i].glsl_name); + else + snprintf(buf, 255, "%s%sout vec4 %s;\n", prefix, ctx->outputs[i].invariant ? "invariant " : "", ctx->outputs[i].glsl_name); STRCAT_WITH_RET(glsl_hdr, buf); } else if (ctx->outputs[i].invariant) { snprintf(buf, 255, "invariant %s;\n", ctx->outputs[i].glsl_name); @@ -2632,7 +2670,10 @@ static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr) snprintf(outtype, 6, "float"); else snprintf(outtype, 6, "vec%d", ctx->so->output[i].num_components); - snprintf(buf, 255, "out %s tfout%d;\n", outtype, i); + if (ctx->so->output[i].stream && ctx->prog_type == TGSI_PROCESSOR_GEOMETRY) + snprintf(buf, 255, "layout (stream=%d) out %s tfout%d;\n", ctx->so->output[i].stream, outtype, i); + else + snprintf(buf, 255, "out %s tfout%d;\n", outtype, i); STRCAT_WITH_RET(glsl_hdr, buf); } }