[virglrenderer-devel] [PATCH 08/12] arb_gpu_shader5: add support for interpolation instructions
Dave Airlie
airlied at gmail.com
Tue May 15 04:38:06 UTC 2018
From: Dave Airlie <airlied at redhat.com>
---
src/vrend_shader.c | 95 +++++++++++++++++++++++++++++++++++++++++++++---------
src/vrend_shader.h | 1 +
2 files changed, 80 insertions(+), 16 deletions(-)
diff --git a/src/vrend_shader.c b/src/vrend_shader.c
index 2585155..2161766 100644
--- a/src/vrend_shader.c
+++ b/src/vrend_shader.c
@@ -37,7 +37,7 @@ extern int vrend_dump_shaders;
/* start convert of tgsi to glsl */
-#define INTERP_PREFIX " "
+#define INTERP_PREFIX " "
#define INVARI_PREFIX "invariant"
struct vrend_shader_io {
@@ -153,6 +153,7 @@ struct dump_ctx {
bool uses_sample_shading;
bool uses_gpu_shader5;
bool write_mul_temp;
+ bool write_interp_temp;
};
static inline const char *tgsi_proc_to_prefix(int shader_type)
@@ -272,6 +273,7 @@ iter_declaration(struct tgsi_iterate_context *iter,
ctx->inputs[i].name = decl->Semantic.Name;
ctx->inputs[i].sid = decl->Semantic.Index;
ctx->inputs[i].interpolate = decl->Interp.Interpolate;
+ ctx->inputs[i].centroid = decl->Interp.Location == TGSI_INTERPOLATE_LOC_CENTROID;
ctx->inputs[i].first = decl->Range.First;
ctx->inputs[i].glsl_predefined_no_emit = false;
ctx->inputs[i].glsl_no_index = false;
@@ -1632,6 +1634,7 @@ iter_instruction(struct tgsi_iterate_context *iter,
bool override_no_wm[4];
bool dst_override_no_wm[2];
char *sret;
+ char interpSrc0[255], interpSwizzle0[10];
int ret;
bool tg4_has_component = false;
if (ctx->prog_type == -1)
@@ -1812,8 +1815,18 @@ iter_instruction(struct tgsi_iterate_context *iter,
if (stype == TGSI_TYPE_UNSIGNED &&
ctx->inputs[j].is_int)
srcstypeprefix = "";
- snprintf(srcs[i], 255, "%s(%s%s%s%s)",
- srcstypeprefix, prefix, ctx->inputs[j].glsl_name, arrayname, ctx->inputs[j].is_int ? "" : swizzle);
+
+ if (inst->Instruction.Opcode == TGSI_OPCODE_INTERP_SAMPLE && i == 1) {
+ snprintf(srcs[i], 255, "floatBitsToInt(%s%s%s%s)", prefix, ctx->inputs[j].glsl_name, arrayname, swizzle);
+ } else
+ snprintf(srcs[i], 255, "%s(%s%s%s%s)", srcstypeprefix, prefix, ctx->inputs[j].glsl_name, arrayname, ctx->inputs[j].is_int ? "" : swizzle);
+ }
+ if ((inst->Instruction.Opcode == TGSI_OPCODE_INTERP_SAMPLE ||
+ inst->Instruction.Opcode == TGSI_OPCODE_INTERP_OFFSET ||
+ inst->Instruction.Opcode == TGSI_OPCODE_INTERP_CENTROID) &&
+ i == 0) {
+ snprintf(interpSrc0, 255, "%s", ctx->inputs[j].glsl_name);
+ snprintf(interpSwizzle0, 10, "%s", swizzle);
}
override_no_wm[i] = ctx->inputs[j].override_no_wm;
break;
@@ -1823,6 +1836,11 @@ iter_instruction(struct tgsi_iterate_context *iter,
struct vrend_temp_range *range = find_temp_range(ctx, src->Register.Index);
if (!range)
return FALSE;
+ if (inst->Instruction.Opcode == TGSI_OPCODE_INTERP_SAMPLE && i == 1) {
+ stprefix = true;
+ stypeprefix = "floatBitsToInt";
+ }
+
if (src->Register.Indirect) {
snprintf(srcs[i], 255, "%s%c%stemp%d[addr0 + %d]%s%c", stypeprefix, stprefix ? '(' : ' ', prefix, range->first, src->Register.Index - range->first, swizzle, stprefix ? ')' : ' ');
} else
@@ -1839,7 +1857,9 @@ iter_instruction(struct tgsi_iterate_context *iter,
} else {
const char *csp;
ctx->has_ints = true;
- if (stype == TGSI_TYPE_FLOAT || stype == TGSI_TYPE_UNTYPED)
+ if (inst->Instruction.Opcode == TGSI_OPCODE_INTERP_SAMPLE && i == 1)
+ csp = "ivec4";
+ else if (stype == TGSI_TYPE_FLOAT || stype == TGSI_TYPE_UNTYPED)
csp = "uintBitsToFloat";
else if (stype == TGSI_TYPE_SIGNED)
csp = "ivec4";
@@ -1866,7 +1886,8 @@ iter_instruction(struct tgsi_iterate_context *iter,
const char *vtype = "vec4";
const char *imm_stypeprefix = stypeprefix;
- if ((inst->Instruction.Opcode == TGSI_OPCODE_TG4 && i == 1))
+ if ((inst->Instruction.Opcode == TGSI_OPCODE_TG4 && i == 1) ||
+ (inst->Instruction.Opcode == TGSI_OPCODE_INTERP_SAMPLE && i == 1))
stype = TGSI_TYPE_SIGNED;
if (imd->type == TGSI_IMM_UINT32 || imd->type == TGSI_IMM_INT32) {
@@ -2343,6 +2364,30 @@ iter_instruction(struct tgsi_iterate_context *iter,
EMIT_BUF_WITH_RET(ctx, buf);
break;
}
+ case TGSI_OPCODE_INTERP_CENTROID:
+ snprintf(buf, 255, "interp_temp = interpolateAtCentroid(%s);\n", interpSrc0);
+ EMIT_BUF_WITH_RET(ctx, buf);
+ snprintf(buf, 255, "%s = %s(%s(interp_temp%s));\n", dsts[0], dstconv, dtypeprefix, interpSwizzle0);
+ EMIT_BUF_WITH_RET(ctx, buf);
+ ctx->write_interp_temp = true;
+ ctx->uses_gpu_shader5 = true;
+ break;
+ case TGSI_OPCODE_INTERP_SAMPLE:
+ snprintf(buf, 255, "interp_temp = interpolateAtSample(%s, %s.x);\n", interpSrc0, srcs[1]);
+ EMIT_BUF_WITH_RET(ctx, buf);
+ snprintf(buf, 255, "%s = %s(%s(interp_temp%s));\n", dsts[0], dstconv, dtypeprefix, interpSwizzle0);
+ EMIT_BUF_WITH_RET(ctx, buf);
+ ctx->write_interp_temp = true;
+ ctx->uses_gpu_shader5 = true;
+ break;
+ case TGSI_OPCODE_INTERP_OFFSET:
+ snprintf(buf, 255, "interp_temp = interpolateAtOffset(%s, %s.xy);\n", interpSrc0, srcs[1]);
+ EMIT_BUF_WITH_RET(ctx, buf);
+ snprintf(buf, 255, "%s = %s(%s(interp_temp%s));\n", dsts[0], dstconv, dtypeprefix, interpSwizzle0);
+ EMIT_BUF_WITH_RET(ctx, buf);
+ ctx->write_interp_temp = true;
+ ctx->uses_gpu_shader5 = true;
+ break;
case TGSI_OPCODE_UMUL_HI:
snprintf(buf, 255, "umulExtended(%s, %s, umul_temp, mul_temp);\n", srcs[0], srcs[1]);
EMIT_BUF_WITH_RET(ctx, buf);
@@ -2541,13 +2586,20 @@ static const char *get_interp_string(struct vrend_shader_cfg *cfg, int interpola
}
}
+static const char *get_aux_string(struct vrend_shader_cfg *cfg, bool centroid)
+{
+ return centroid ? "centroid " : "";
+}
+
static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr)
{
int i;
char buf[255];
char postfix[8];
- const char *prefix = "";
+ const char *prefix = "", *auxprefix = "";
bool fcolor_emitted[2], bcolor_emitted[2];
+ int nsamp;
+ const char *sname = tgsi_proc_to_prefix(ctx->prog_type);
ctx->num_interps = 0;
if (ctx->so && ctx->so->num_outputs >= PIPE_MAX_SO_OUTPUTS) {
@@ -2595,6 +2647,7 @@ static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr)
prefix = get_interp_string(ctx->cfg, ctx->inputs[i].interpolate, ctx->key->flatshade);
if (!prefix)
prefix = "";
+ auxprefix = get_aux_string(ctx->cfg, ctx->inputs[i].centroid);
ctx->num_interps++;
}
@@ -2602,7 +2655,7 @@ static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr)
snprintf(postfix, 8, "[%d]", gs_input_prim_to_size(ctx->gs_in_prim));
} else
postfix[0] = 0;
- snprintf(buf, 255, "%sin vec4 %s%s;\n", prefix, ctx->inputs[i].glsl_name, postfix);
+ snprintf(buf, 255, "%s%sin vec4 %s%s;\n", prefix, auxprefix, ctx->inputs[i].glsl_name, postfix);
STRCAT_WITH_RET(glsl_hdr, buf);
}
}
@@ -2775,6 +2828,11 @@ static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr)
STRCAT_WITH_RET(glsl_hdr, buf);
}
+ if (ctx->write_interp_temp) {
+ snprintf(buf, 255, "vec4 interp_temp;\n");
+ STRCAT_WITH_RET(glsl_hdr, buf);
+ }
+
for (i = 0; i < ctx->num_address; i++) {
snprintf(buf, 255, "int addr%d;\n", i);
STRCAT_WITH_RET(glsl_hdr, buf);
@@ -2870,6 +2928,7 @@ static boolean fill_fragment_interpolants(struct dump_ctx *ctx, struct vrend_sha
sinfo->interpinfo[index].semantic_name = ctx->inputs[i].name;
sinfo->interpinfo[index].semantic_index = ctx->inputs[i].sid;
sinfo->interpinfo[index].interpolate = ctx->inputs[i].interpolate;
+ sinfo->interpinfo[index].centroid = ctx->inputs[i].centroid;
index++;
}
return TRUE;
@@ -3000,7 +3059,7 @@ char *vrend_convert_shader(struct vrend_shader_cfg *cfg,
static void replace_interp(char *program,
const char *var_name,
- const char *pstring)
+ const char *pstring, const char *auxstring)
{
char *ptr;
int mylen = strlen(INTERP_PREFIX) + strlen("out vec4 ");
@@ -3012,7 +3071,9 @@ static void replace_interp(char *program,
ptr -= mylen;
+ memset(ptr, ' ', strlen(INTERP_PREFIX));
memcpy(ptr, pstring, strlen(pstring));
+ memcpy(ptr + strlen(pstring), auxstring, strlen(auxstring));
}
bool vrend_patch_vertex_shader_interpolants(struct vrend_shader_cfg *cfg, char *program,
@@ -3020,7 +3081,7 @@ bool vrend_patch_vertex_shader_interpolants(struct vrend_shader_cfg *cfg, char *
struct vrend_shader_info *fs_info, const char *oprefix, bool flatshade)
{
int i;
- const char *pstring;
+ const char *pstring, *auxstring;
char glsl_name[64];
if (!vs_info || !fs_info)
return true;
@@ -3033,27 +3094,29 @@ bool vrend_patch_vertex_shader_interpolants(struct vrend_shader_cfg *cfg, char *
if (!pstring)
continue;
+ auxstring = get_aux_string(cfg, fs_info->interpinfo[i].centroid);
+
switch (fs_info->interpinfo[i].semantic_name) {
case TGSI_SEMANTIC_COLOR:
/* color is a bit trickier */
if (fs_info->glsl_ver < 140) {
if (fs_info->interpinfo[i].semantic_index == 1) {
- replace_interp(program, "gl_FrontSecondaryColor", pstring);
- replace_interp(program, "gl_BackSecondaryColor", pstring);
+ replace_interp(program, "gl_FrontSecondaryColor", pstring, auxstring);
+ replace_interp(program, "gl_BackSecondaryColor", pstring, auxstring);
} else {
- replace_interp(program, "gl_FrontColor", pstring);
- replace_interp(program, "gl_BackColor", pstring);
+ replace_interp(program, "gl_FrontColor", pstring, auxstring);
+ replace_interp(program, "gl_BackColor", pstring, auxstring);
}
} else {
snprintf(glsl_name, 64, "ex_c%d", fs_info->interpinfo[i].semantic_index);
- replace_interp(program, glsl_name, pstring);
+ replace_interp(program, glsl_name, pstring, auxstring);
snprintf(glsl_name, 64, "ex_bc%d", fs_info->interpinfo[i].semantic_index);
- replace_interp(program, glsl_name, pstring);
+ replace_interp(program, glsl_name, pstring, auxstring);
}
break;
case TGSI_SEMANTIC_GENERIC:
snprintf(glsl_name, 64, "%s_g%d", oprefix, fs_info->interpinfo[i].semantic_index);
- replace_interp(program, glsl_name, pstring);
+ replace_interp(program, glsl_name, pstring, auxstring);
break;
default:
fprintf(stderr,"unhandled semantic: %x\n", fs_info->interpinfo[i].semantic_name);
diff --git a/src/vrend_shader.h b/src/vrend_shader.h
index 681bfe2..230a3c1 100644
--- a/src/vrend_shader.h
+++ b/src/vrend_shader.h
@@ -32,6 +32,7 @@ struct vrend_interp_info {
int semantic_name;
int semantic_index;
int interpolate;
+ bool centroid;
};
struct vrend_shader_info {
--
2.14.3
More information about the virglrenderer-devel
mailing list