(*regs)[i] = c->undef;
}
-static struct qreg
-add_uniform(struct vc4_compile *c,
- enum quniform_contents contents,
- uint32_t data)
-{
- for (int i = 0; i < c->num_uniforms; i++) {
- if (c->uniform_contents[i] == contents &&
- c->uniform_data[i] == data) {
- return (struct qreg) { QFILE_UNIF, i };
- }
- }
-
- uint32_t uniform = c->num_uniforms++;
- struct qreg u = { QFILE_UNIF, uniform };
-
- if (uniform >= c->uniform_array_size) {
- c->uniform_array_size = MAX2(MAX2(16, uniform + 1),
- c->uniform_array_size * 2);
-
- c->uniform_data = reralloc(c, c->uniform_data,
- uint32_t,
- c->uniform_array_size);
- c->uniform_contents = reralloc(c, c->uniform_contents,
- enum quniform_contents,
- c->uniform_array_size);
- }
-
- c->uniform_contents[uniform] = contents;
- c->uniform_data[uniform] = data;
-
- return u;
-}
-
-static struct qreg
-get_temp_for_uniform(struct vc4_compile *c, enum quniform_contents contents,
- uint32_t data)
-{
- struct qreg u = add_uniform(c, contents, data);
- struct qreg t = qir_MOV(c, u);
- return t;
-}
-
-static struct qreg
-qir_uniform_ui(struct vc4_compile *c, uint32_t ui)
-{
- return get_temp_for_uniform(c, QUNIFORM_CONSTANT, ui);
-}
-
-static struct qreg
-qir_uniform_f(struct vc4_compile *c, float f)
-{
- return qir_uniform_ui(c, fui(f));
-}
-
static struct qreg
indirect_uniform_load(struct vc4_compile *c,
struct tgsi_full_src_register *src, int swiz)
indirect_offset = qir_MIN(c, indirect_offset, qir_uniform_ui(c, (range->dst_offset +
range->size - 4)));
- qir_TEX_DIRECT(c, indirect_offset, add_uniform(c, QUNIFORM_UBO_ADDR, 0));
+ qir_TEX_DIRECT(c, indirect_offset, qir_uniform(c, QUNIFORM_UBO_ADDR, 0));
struct qreg r4 = qir_TEX_RESULT(c);
c->num_texture_samples++;
return qir_MOV(c, r4);
if (src->Indirect) {
r = indirect_uniform_load(c, full_src, s);
} else {
- r = get_temp_for_uniform(c, QUNIFORM_UNIFORM,
- src->Index * 4 + s);
+ r = qir_uniform(c, QUNIFORM_UNIFORM, src->Index * 4 + s);
}
break;
case TGSI_FILE_INPUT:
}
}
+static inline struct qreg
+qir_SAT(struct vc4_compile *c, struct qreg val)
+{
+ return qir_FMAX(c,
+ qir_FMIN(c, val, qir_uniform_f(c, 1.0)),
+ qir_uniform_f(c, 0.0));
+}
+
static struct qreg
tgsi_to_qir_alu(struct vc4_compile *c,
struct tgsi_full_instruction *tgsi_inst,
struct tgsi_full_instruction *tgsi_inst,
enum qop op, struct qreg *src, int i)
{
- struct qreg src0_hi = qir_SHR(c, src[0 * 4 + i],
- qir_uniform_ui(c, 16));
- struct qreg src0_lo = qir_AND(c, src[0 * 4 + i],
- qir_uniform_ui(c, 0xffff));
- struct qreg src1_hi = qir_SHR(c, src[1 * 4 + i],
- qir_uniform_ui(c, 16));
- struct qreg src1_lo = qir_AND(c, src[1 * 4 + i],
- qir_uniform_ui(c, 0xffff));
+ struct qreg src0 = src[0 * 4 + i];
+ struct qreg src0_hi = qir_SHR(c, src0, qir_uniform_ui(c, 24));
+ struct qreg src1 = src[1 * 4 + i];
+ struct qreg src1_hi = qir_SHR(c, src1, qir_uniform_ui(c, 24));
- struct qreg hilo = qir_MUL24(c, src0_hi, src1_lo);
- struct qreg lohi = qir_MUL24(c, src0_lo, src1_hi);
- struct qreg lolo = qir_MUL24(c, src0_lo, src1_lo);
+ struct qreg hilo = qir_MUL24(c, src0_hi, src1);
+ struct qreg lohi = qir_MUL24(c, src0, src1_hi);
+ struct qreg lolo = qir_MUL24(c, src0, src1);
return qir_ADD(c, lolo, qir_SHL(c,
qir_ADD(c, hilo, lohi),
- qir_uniform_ui(c, 16)));
+ qir_uniform_ui(c, 24)));
}
static struct qreg
}
struct qreg texture_u[] = {
- add_uniform(c, QUNIFORM_TEXTURE_CONFIG_P0, unit),
- add_uniform(c, QUNIFORM_TEXTURE_CONFIG_P1, unit),
- add_uniform(c, QUNIFORM_CONSTANT, 0),
- add_uniform(c, QUNIFORM_CONSTANT, 0),
+ qir_uniform(c, QUNIFORM_TEXTURE_CONFIG_P0, unit),
+ qir_uniform(c, QUNIFORM_TEXTURE_CONFIG_P1, unit),
+ qir_uniform(c, QUNIFORM_CONSTANT, 0),
+ qir_uniform(c, QUNIFORM_CONSTANT, 0),
};
uint32_t next_texture_u = 0;
if (tgsi_inst->Texture.Texture == TGSI_TEXTURE_RECT ||
tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOWRECT) {
s = qir_FMUL(c, s,
- get_temp_for_uniform(c,
- QUNIFORM_TEXRECT_SCALE_X,
- unit));
+ qir_uniform(c, QUNIFORM_TEXRECT_SCALE_X, unit));
t = qir_FMUL(c, t,
- get_temp_for_uniform(c,
- QUNIFORM_TEXRECT_SCALE_Y,
- unit));
+ qir_uniform(c, QUNIFORM_TEXRECT_SCALE_Y, unit));
}
if (tgsi_inst->Texture.Texture == TGSI_TEXTURE_CUBE ||
tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE ||
is_txl) {
- texture_u[2] = add_uniform(c, QUNIFORM_TEXTURE_CONFIG_P2,
+ texture_u[2] = qir_uniform(c, QUNIFORM_TEXTURE_CONFIG_P2,
unit | (is_txl << 16));
}
c->key->tex[unit].wrap_s == PIPE_TEX_WRAP_CLAMP ||
c->key->tex[unit].wrap_t == PIPE_TEX_WRAP_CLAMP_TO_BORDER ||
c->key->tex[unit].wrap_t == PIPE_TEX_WRAP_CLAMP) {
- qir_TEX_R(c, get_temp_for_uniform(c, QUNIFORM_TEXTURE_BORDER_COLOR, unit),
+ qir_TEX_R(c, qir_uniform(c, QUNIFORM_TEXTURE_BORDER_COLOR, unit),
texture_u[next_texture_u++]);
}
if (c->key->tex[unit].wrap_s == PIPE_TEX_WRAP_CLAMP) {
- s = qir_FMIN(c, qir_FMAX(c, s, qir_uniform_f(c, 0.0)),
- qir_uniform_f(c, 1.0));
+ s = qir_SAT(c, s);
}
if (c->key->tex[unit].wrap_t == PIPE_TEX_WRAP_CLAMP) {
- t = qir_FMIN(c, qir_FMAX(c, t, qir_uniform_f(c, 0.0)),
- qir_uniform_f(c, 1.0));
+ t = qir_SAT(c, t);
}
qir_TEX_T(c, t, texture_u[next_texture_u++]);
uint32_t attr_size = util_format_get_blocksize(format);
struct qreg vpm_reads[4];
+ c->vattr_sizes[attr] = align(attr_size, 4);
for (int i = 0; i < align(attr_size, 4) / 4; i++) {
struct qreg vpm = { QFILE_VPM, attr * 4 + i };
vpm_reads[i] = qir_MOV(c, vpm);
}
case PIPE_BLENDFACTOR_CONST_COLOR:
return qir_FMUL(c, val,
- get_temp_for_uniform(c,
- QUNIFORM_BLEND_CONST_COLOR,
- channel));
+ qir_uniform(c, QUNIFORM_BLEND_CONST_COLOR,
+ channel));
case PIPE_BLENDFACTOR_CONST_ALPHA:
return qir_FMUL(c, val,
- get_temp_for_uniform(c,
- QUNIFORM_BLEND_CONST_COLOR,
- 3));
+ qir_uniform(c, QUNIFORM_BLEND_CONST_COLOR, 3));
case PIPE_BLENDFACTOR_ZERO:
return qir_uniform_f(c, 0.0);
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
return qir_FMUL(c, val,
qir_FSUB(c, qir_uniform_f(c, 1.0),
- get_temp_for_uniform(c,
- QUNIFORM_BLEND_CONST_COLOR,
- channel)));
+ qir_uniform(c,
+ QUNIFORM_BLEND_CONST_COLOR,
+ channel)));
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
return qir_FMUL(c, val,
qir_FSUB(c, qir_uniform_f(c, 1.0),
- get_temp_for_uniform(c,
- QUNIFORM_BLEND_CONST_COLOR,
- 3)));
+ qir_uniform(c,
+ QUNIFORM_BLEND_CONST_COLOR,
+ 3)));
default:
case PIPE_BLENDFACTOR_SRC1_COLOR:
return;
}
+ struct qreg clamped_src[4];
+ struct qreg clamped_dst[4];
+ for (int i = 0; i < 4; i++) {
+ clamped_src[i] = qir_SAT(c, src_color[i]);
+ clamped_dst[i] = qir_SAT(c, dst_color[i]);
+ }
+ src_color = clamped_src;
+ dst_color = clamped_dst;
+
struct qreg src_blend[4], dst_blend[4];
for (int i = 0; i < 3; i++) {
src_blend[i] = vc4_blend_channel(c,
alpha_test_discard(struct vc4_compile *c)
{
struct qreg src_alpha;
- struct qreg alpha_ref = get_temp_for_uniform(c, QUNIFORM_ALPHA_REF, 0);
+ struct qreg alpha_ref = qir_uniform(c, QUNIFORM_ALPHA_REF, 0);
if (!c->fs_key->alpha_test)
return;
blend_color[i] = qir_srgb_encode(c, blend_color[i]);
}
- /* If the bit isn't set in the color mask, then just return the
- * original dst color, instead.
- */
- for (int i = 0; i < 4; i++) {
- if (!(c->fs_key->blend.colormask & (1 << i))) {
- blend_color[i] = dst_color[i];
- }
- }
-
/* Debug: Sometimes you're getting a black output and just want to see
* if the FS is getting executed at all. Spam magenta into the color
* output.
qir_TLB_DISCARD_SETUP(c, c->discard);
if (c->fs_key->stencil_enabled) {
- qir_TLB_STENCIL_SETUP(c, add_uniform(c, QUNIFORM_STENCIL, 0));
+ qir_TLB_STENCIL_SETUP(c, qir_uniform(c, QUNIFORM_STENCIL, 0));
if (c->fs_key->stencil_twoside) {
- qir_TLB_STENCIL_SETUP(c, add_uniform(c, QUNIFORM_STENCIL, 1));
+ qir_TLB_STENCIL_SETUP(c, qir_uniform(c, QUNIFORM_STENCIL, 1));
}
if (c->fs_key->stencil_full_writemasks) {
- qir_TLB_STENCIL_SETUP(c, add_uniform(c, QUNIFORM_STENCIL, 2));
+ qir_TLB_STENCIL_SETUP(c, qir_uniform(c, QUNIFORM_STENCIL, 2));
}
}
packed_color = vc4_logicop(c, packed_color, packed_dst_color);
}
+ /* If the bit isn't set in the color mask, then just return the
+ * original dst color, instead.
+ */
+ uint32_t colormask = 0xffffffff;
+ for (int i = 0; i < 4; i++) {
+ if (format_swiz[i] < 4 &&
+ !(c->fs_key->blend.colormask & (1 << format_swiz[i]))) {
+ colormask &= ~(0xff << (i * 8));
+ }
+ }
+ if (colormask != 0xffffffff) {
+ packed_color = qir_OR(c,
+ qir_AND(c, packed_color,
+ qir_uniform_ui(c, colormask)),
+ qir_AND(c, packed_dst_color,
+ qir_uniform_ui(c, ~colormask)));
+ }
+
qir_emit(c, qir_inst(QOP_TLB_COLOR_WRITE, c->undef,
packed_color, c->undef));
}
for (int i = 0; i < 2; i++) {
struct qreg scale =
- add_uniform(c, QUNIFORM_VIEWPORT_X_SCALE + i, 0);
+ qir_uniform(c, QUNIFORM_VIEWPORT_X_SCALE + i, 0);
xyi[i] = qir_FTOI(c, qir_FMUL(c,
qir_FMUL(c,
static void
emit_zs_write(struct vc4_compile *c, struct qreg rcp_w)
{
- struct qreg zscale = add_uniform(c, QUNIFORM_VIEWPORT_Z_SCALE, 0);
- struct qreg zoffset = add_uniform(c, QUNIFORM_VIEWPORT_Z_OFFSET, 0);
+ struct qreg zscale = qir_uniform(c, QUNIFORM_VIEWPORT_Z_SCALE, 0);
+ struct qreg zoffset = qir_uniform(c, QUNIFORM_VIEWPORT_Z_OFFSET, 0);
qir_VPM_WRITE(c, qir_FADD(c, qir_FMUL(c, qir_FMUL(c,
c->outputs[c->output_position_index + 2],
{
struct qreg point_size;
- if (c->output_point_size_index)
+ if (c->output_point_size_index != -1)
point_size = c->outputs[c->output_point_size_index + 3];
else
point_size = qir_uniform_f(c, 1.0);
if (c->num_inputs)
return;
- for (int i = 0; i < 4; i++) {
- struct qreg vpm = { QFILE_VPM, 0 };
- (void)qir_MOV(c, vpm);
- c->num_inputs++;
- }
+ c->vattr_sizes[0] = 4;
+ struct qreg vpm = { QFILE_VPM, 0 };
+ (void)qir_MOV(c, vpm);
+ c->num_inputs++;
}
static void
for (int i = 0; i < 4; i++) {
struct qreg pos_chan = c->outputs[cv + i];
struct qreg ucp =
- add_uniform(c, QUNIFORM_USER_CLIP_PLANE,
+ qir_uniform(c, QUNIFORM_USER_CLIP_PLANE,
plane * 4 + i);
dist = qir_FADD(c, dist, qir_FMUL(c, pos_chan, ucp));
}
}
tgsi_parse_free(&c->parser);
+ if (vc4_debug & VC4_DEBUG_QIR) {
+ fprintf(stderr, "%s prog %d/%d pre-opt QIR:\n",
+ qir_get_stage_name(c->stage),
+ c->program_id, c->variant_id);
+ qir_dump(c);
+ }
qir_optimize(c);
+ qir_lower_uniforms(c);
if (vc4_debug & VC4_DEBUG_QIR) {
fprintf(stderr, "%s prog %d/%d QIR:\n",
}
} else {
shader->num_inputs = c->num_inputs;
+
+ shader->vattr_offsets[0] = 0;
+ for (int i = 0; i < 8; i++) {
+ shader->vattr_offsets[i + 1] =
+ shader->vattr_offsets[i] + c->vattr_sizes[i];
+
+ if (c->vattr_sizes[i])
+ shader->vattrs_live |= (1 << i);
+ }
}
copy_uniform_state_to_shader(shader, c);
VC4_DIRTY_RASTERIZER |
VC4_DIRTY_FRAGTEX |
VC4_DIRTY_TEXSTATE |
- VC4_DIRTY_PROG))) {
+ VC4_DIRTY_UNCOMPILED_FS))) {
return;
}
if (vc4->prog.fs == old_fs)
return;
+ vc4->dirty |= VC4_DIRTY_COMPILED_FS;
if (vc4->rasterizer->base.flatshade &&
old_fs && vc4->prog.fs->color_inputs != old_fs->color_inputs) {
vc4->dirty |= VC4_DIRTY_FLAT_SHADE_FLAGS;
VC4_DIRTY_VERTTEX |
VC4_DIRTY_TEXSTATE |
VC4_DIRTY_VTXSTATE |
- VC4_DIRTY_PROG))) {
+ VC4_DIRTY_UNCOMPILED_VS |
+ VC4_DIRTY_COMPILED_FS))) {
return;
}
texture->u.tex.first_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));
+ VC4_SET_FIELD(rsc->vc4_format & 15, VC4_TEX_P0_TYPE));
}
static void
case QUNIFORM_BLEND_CONST_COLOR:
cl_aligned_f(&vc4->uniforms,
- vc4->blend_color.color[uinfo->data[i]]);
+ CLAMP(vc4->blend_color.color[uinfo->data[i]], 0, 1));
break;
case QUNIFORM_STENCIL:
{
struct vc4_context *vc4 = vc4_context(pctx);
vc4->prog.bind_fs = hwcso;
- vc4->prog.dirty |= VC4_SHADER_DIRTY_FP;
- vc4->dirty |= VC4_DIRTY_PROG;
+ vc4->dirty |= VC4_DIRTY_UNCOMPILED_FS;
}
static void
{
struct vc4_context *vc4 = vc4_context(pctx);
vc4->prog.bind_vs = hwcso;
- vc4->prog.dirty |= VC4_SHADER_DIRTY_VP;
- vc4->dirty |= VC4_DIRTY_PROG;
+ vc4->dirty |= VC4_DIRTY_UNCOMPILED_VS;
}
void