#endif
struct vc4_key {
- struct pipe_shader_state *shader_state;
+ struct vc4_uncompiled_shader *shader_state;
struct {
enum pipe_format format;
unsigned compare_mode:1;
bool is_lines;
bool alpha_test;
bool point_coord_upper_left;
+ bool light_twoside;
uint8_t alpha_test_func;
uint32_t point_sprite_mask;
return dst;
}
+static struct qreg
+tgsi_to_qir_scalar(struct vc4_compile *c,
+ struct tgsi_full_instruction *tgsi_inst,
+ enum qop op, struct qreg *src, int i)
+{
+ struct qreg dst = qir_get_temp(c);
+ qir_emit(c, qir_inst(op, dst,
+ src[0 * 4 + 0],
+ c->undef));
+ return dst;
+}
+
static struct qreg
qir_srgb_decode(struct vc4_compile *c, struct qreg srgb)
{
src[2 * 4 + i]);
}
-static struct qreg
-tgsi_to_qir_lit(struct vc4_compile *c,
- struct tgsi_full_instruction *tgsi_inst,
- enum qop op, struct qreg *src, int i)
-{
- struct qreg x = src[0 * 4 + 0];
- struct qreg y = src[0 * 4 + 1];
- struct qreg w = src[0 * 4 + 3];
-
- switch (i) {
- case 0:
- case 3:
- return qir_uniform_f(c, 1.0);
- case 1:
- return qir_FMAX(c, src[0 * 4 + 0], qir_uniform_f(c, 0.0));
- case 2: {
- struct qreg zero = qir_uniform_f(c, 0.0);
-
- qir_SF(c, x);
- /* XXX: Clamp w to -128..128 */
- return qir_SEL_X_0_NC(c,
- qir_EXP2(c, qir_FMUL(c,
- w,
- qir_LOG2(c,
- qir_FMAX(c,
- y,
- zero)))));
- }
- default:
- assert(!"not reached");
- return c->undef;
- }
-}
-
static struct qreg
tgsi_to_qir_lrp(struct vc4_compile *c,
struct tgsi_full_instruction *tgsi_inst,
}
}
-static struct qreg
-tgsi_to_qir_pow(struct vc4_compile *c,
- struct tgsi_full_instruction *tgsi_inst,
- enum qop op, struct qreg *src, int i)
-{
- /* Note that this instruction replicates its result from the x channel
- */
- return qir_POW(c, src[0 * 4 + 0], src[1 * 4 + 0]);
-}
-
static struct qreg
tgsi_to_qir_trunc(struct vc4_compile *c,
struct tgsi_full_instruction *tgsi_inst,
trunc);
}
-static struct qreg
-tgsi_to_qir_dp(struct vc4_compile *c,
- struct tgsi_full_instruction *tgsi_inst,
- int num, struct qreg *src, int i)
-{
- struct qreg sum = qir_FMUL(c, src[0 * 4 + 0], src[1 * 4 + 0]);
- for (int j = 1; j < num; j++) {
- sum = qir_FADD(c, sum, qir_FMUL(c,
- src[0 * 4 + j],
- src[1 * 4 + j]));
- }
- return sum;
-}
-
-static struct qreg
-tgsi_to_qir_dp2(struct vc4_compile *c,
- struct tgsi_full_instruction *tgsi_inst,
- enum qop op, struct qreg *src, int i)
-{
- return tgsi_to_qir_dp(c, tgsi_inst, 2, src, i);
-}
-
-static struct qreg
-tgsi_to_qir_dp3(struct vc4_compile *c,
- struct tgsi_full_instruction *tgsi_inst,
- enum qop op, struct qreg *src, int i)
-{
- return tgsi_to_qir_dp(c, tgsi_inst, 3, src, i);
-}
-
-static struct qreg
-tgsi_to_qir_dp4(struct vc4_compile *c,
- struct tgsi_full_instruction *tgsi_inst,
- enum qop op, struct qreg *src, int i)
-{
- return tgsi_to_qir_dp(c, tgsi_inst, 4, src, i);
-}
-
static struct qreg
tgsi_to_qir_abs(struct vc4_compile *c,
struct tgsi_full_instruction *tgsi_inst,
struct tgsi_full_declaration *decl)
{
switch (decl->Declaration.File) {
- case TGSI_FILE_TEMPORARY:
+ case TGSI_FILE_TEMPORARY: {
+ uint32_t old_size = c->temps_array_size;
resize_qreg_array(c, &c->temps, &c->temps_array_size,
(decl->Range.Last + 1) * 4);
+
+ for (int i = old_size; i < c->temps_array_size; i++)
+ c->temps[i] = qir_uniform_ui(c, 0);
break;
+ }
case TGSI_FILE_INPUT:
resize_qreg_array(c, &c->inputs, &c->inputs_array_size,
[TGSI_OPCODE_CMP] = { 0, tgsi_to_qir_cmp },
[TGSI_OPCODE_MAD] = { 0, tgsi_to_qir_mad },
- [TGSI_OPCODE_DP2] = { 0, tgsi_to_qir_dp2 },
- [TGSI_OPCODE_DP3] = { 0, tgsi_to_qir_dp3 },
- [TGSI_OPCODE_DP4] = { 0, tgsi_to_qir_dp4 },
- [TGSI_OPCODE_RCP] = { QOP_RCP, tgsi_to_qir_alu },
- [TGSI_OPCODE_RSQ] = { QOP_RSQ, tgsi_to_qir_alu },
- [TGSI_OPCODE_EX2] = { QOP_EXP2, tgsi_to_qir_alu },
- [TGSI_OPCODE_LG2] = { QOP_LOG2, tgsi_to_qir_alu },
- [TGSI_OPCODE_LIT] = { 0, tgsi_to_qir_lit },
+ [TGSI_OPCODE_RCP] = { QOP_RCP, tgsi_to_qir_scalar },
+ [TGSI_OPCODE_RSQ] = { QOP_RSQ, tgsi_to_qir_scalar },
+ [TGSI_OPCODE_EX2] = { QOP_EXP2, tgsi_to_qir_scalar },
+ [TGSI_OPCODE_LG2] = { QOP_LOG2, tgsi_to_qir_scalar },
[TGSI_OPCODE_LRP] = { 0, tgsi_to_qir_lrp },
- [TGSI_OPCODE_POW] = { 0, tgsi_to_qir_pow },
[TGSI_OPCODE_TRUNC] = { 0, tgsi_to_qir_trunc },
[TGSI_OPCODE_FRC] = { 0, tgsi_to_qir_frc },
[TGSI_OPCODE_FLR] = { 0, tgsi_to_qir_flr },
int ret;
c->stage = stage;
-
- c->shader_state = key->shader_state;
- ret = tgsi_parse_init(&c->parser, c->shader_state->tokens);
- assert(ret == TGSI_PARSE_OK);
-
- if (vc4_debug & VC4_DEBUG_TGSI) {
- fprintf(stderr, "TGSI:\n");
- tgsi_dump(c->shader_state->tokens, 0);
- }
+ c->shader_state = &key->shader_state->base;
c->key = key;
switch (stage) {
break;
}
+ const struct tgsi_token *tokens = key->shader_state->base.tokens;
+ if (c->fs_key && c->fs_key->light_twoside) {
+ if (!key->shader_state->twoside_tokens) {
+ const struct tgsi_lowering_config lowering_config = {
+ .color_two_side = true,
+ };
+ struct tgsi_shader_info info;
+ key->shader_state->twoside_tokens =
+ tgsi_transform_lowering(&lowering_config,
+ key->shader_state->base.tokens,
+ &info);
+
+ /* If no transformation occurred, then NULL is
+ * returned and we just use our original tokens.
+ */
+ if (!key->shader_state->twoside_tokens) {
+ key->shader_state->twoside_tokens =
+ key->shader_state->base.tokens;
+ }
+ }
+ tokens = key->shader_state->twoside_tokens;
+ }
+
+ ret = tgsi_parse_init(&c->parser, tokens);
+ assert(ret == TGSI_PARSE_OK);
+
+ if (vc4_debug & VC4_DEBUG_TGSI) {
+ fprintf(stderr, "TGSI:\n");
+ tgsi_dump(tokens, 0);
+ }
+
while (!tgsi_parse_end_of_tokens(&c->parser)) {
tgsi_parse_token(&c->parser);
vc4_shader_state_create(struct pipe_context *pctx,
const struct pipe_shader_state *cso)
{
- struct pipe_shader_state *so = CALLOC_STRUCT(pipe_shader_state);
+ struct vc4_uncompiled_shader *so = CALLOC_STRUCT(vc4_uncompiled_shader);
if (!so)
return NULL;
.lower_DST = true,
.lower_XPD = true,
.lower_SCS = true,
+ .lower_POW = true,
+ .lower_LIT = true,
.lower_EXP = true,
.lower_LOG = true,
+ .lower_DP4 = true,
+ .lower_DP3 = true,
.lower_DPH = true,
+ .lower_DP2 = true,
.lower_DP2A = true,
};
struct tgsi_shader_info info;
- so->tokens = tgsi_transform_lowering(&lowering_config, cso->tokens, &info);
- if (!so->tokens)
- so->tokens = tgsi_dup_tokens(cso->tokens);
+ so->base.tokens = tgsi_transform_lowering(&lowering_config, cso->tokens, &info);
+ if (!so->base.tokens)
+ so->base.tokens = tgsi_dup_tokens(cso->tokens);
return so;
}
PIPE_SPRITE_COORD_UPPER_LEFT);
}
+ key->light_twoside = vc4->rasterizer->base.light_twoside;
+
vc4->prog.fs = util_hash_table_get(vc4->fs_cache, key);
if (vc4->prog.fs)
return;
struct delete_state {
struct vc4_context *vc4;
- struct pipe_shader_state *shader_state;
+ struct vc4_uncompiled_shader *shader_state;
};
static enum pipe_error
vc4_shader_state_delete(struct pipe_context *pctx, void *hwcso)
{
struct vc4_context *vc4 = vc4_context(pctx);
- struct pipe_shader_state *so = hwcso;
+ struct vc4_uncompiled_shader *so = hwcso;
struct delete_state del;
del.vc4 = vc4;
util_hash_table_foreach(vc4->fs_cache, fs_delete_from_cache, &del);
util_hash_table_foreach(vc4->vs_cache, vs_delete_from_cache, &del);
- free((void *)so->tokens);
+ if (so->twoside_tokens != so->base.tokens)
+ free((void *)so->twoside_tokens);
+ free((void *)so->base.tokens);
free(so);
}
struct pipe_sampler_view *texture = texstate->textures[unit];
struct vc4_resource *rsc = vc4_resource(texture->texture);
- bool is_cube = texture->target == PIPE_TEXTURE_CUBE;
-
cl_reloc(vc4, &vc4->uniforms, rsc->bo,
- rsc->slices[0].offset | texture->u.tex.last_level |
- is_cube << 9 |
- ((rsc->vc4_format & 7) << 4));
+ VC4_SET_FIELD(rsc->slices[0].offset >> 12, VC4_TEX_P0_OFFSET) |
+ VC4_SET_FIELD(texture->u.tex.last_level, VC4_TEX_P0_MIPLVLS) |
+ VC4_SET_FIELD(texture->target == PIPE_TEXTURE_CUBE,
+ VC4_TEX_P0_CMMODE) |
+ VC4_SET_FIELD(rsc->vc4_format & 7, VC4_TEX_P0_TYPE));
}
static void
struct vc4_resource *rsc = vc4_resource(texture->texture);
struct pipe_sampler_state *sampler = texstate->samplers[unit];
static const uint8_t minfilter_map[6] = {
- 2, 4, /* mipfilter nearest */
- 3, 5, /* mipfilter linear */
- 1, 0, /* mipfilter none */
+ VC4_TEX_P1_MINFILT_NEAR_MIP_NEAR,
+ VC4_TEX_P1_MINFILT_LIN_MIP_NEAR,
+ VC4_TEX_P1_MINFILT_NEAR_MIP_LIN,
+ VC4_TEX_P1_MINFILT_LIN_MIP_LIN,
+ VC4_TEX_P1_MINFILT_NEAREST,
+ VC4_TEX_P1_MINFILT_LINEAR,
};
static const uint32_t magfilter_map[] = {
- [PIPE_TEX_FILTER_NEAREST] = 1,
- [PIPE_TEX_FILTER_LINEAR] = 0,
+ [PIPE_TEX_FILTER_NEAREST] = VC4_TEX_P1_MAGFILT_NEAREST,
+ [PIPE_TEX_FILTER_LINEAR] = VC4_TEX_P1_MAGFILT_LINEAR,
};
bool either_nearest =
sampler->min_img_filter == PIPE_TEX_MIPFILTER_NEAREST);
cl_u32(&vc4->uniforms,
- ((rsc->vc4_format >> 4) << 31) |
- (texture->texture->height0 << 20) |
- (texture->texture->width0 << 8) |
- (magfilter_map[sampler->mag_img_filter] << 7) |
- (minfilter_map[sampler->min_mip_filter * 2 +
- sampler->min_img_filter] << 4) |
- (translate_wrap(sampler->wrap_t, either_nearest) << 2) |
- (translate_wrap(sampler->wrap_s, either_nearest) << 0));
+ VC4_SET_FIELD(rsc->vc4_format >> 4, VC4_TEX_P1_TYPE4) |
+ VC4_SET_FIELD(texture->texture->height0 & 2047,
+ VC4_TEX_P1_HEIGHT) |
+ VC4_SET_FIELD(texture->texture->width0 & 2047,
+ VC4_TEX_P1_WIDTH) |
+ VC4_SET_FIELD(magfilter_map[sampler->mag_img_filter],
+ VC4_TEX_P1_MAGFILT) |
+ VC4_SET_FIELD(minfilter_map[sampler->min_mip_filter * 2 +
+ sampler->min_img_filter],
+ VC4_TEX_P1_MINFILT) |
+ VC4_SET_FIELD(translate_wrap(sampler->wrap_s, either_nearest),
+ VC4_TEX_P1_WRAP_S) |
+ VC4_SET_FIELD(translate_wrap(sampler->wrap_t, either_nearest),
+ VC4_TEX_P1_WRAP_T));
}
static void
struct pipe_sampler_view *texture = texstate->textures[unit];
struct vc4_resource *rsc = vc4_resource(texture->texture);
- cl_u32(&vc4->uniforms, (1 << 30) | rsc->cube_map_stride);
+ cl_u32(&vc4->uniforms,
+ VC4_SET_FIELD(VC4_TEX_P2_PTYPE_CUBE_MAP_STRIDE,
+ VC4_TEX_P2_PTYPE) |
+ VC4_SET_FIELD(rsc->cube_map_stride >> 12, VC4_TEX_P2_CMST));
}