#include "instr-a3xx.h"
#include "ir3.h"
+static void dump_reg(const char *name, uint32_t r)
+{
+ if (r != regid(63,0))
+ debug_printf("; %s: r%d.%c\n", name, r >> 2, "xyzw"[r & 0x3]);
+}
+
+static void dump_semantic(struct ir3_shader_variant *so,
+ unsigned sem, const char *name)
+{
+ uint32_t regid;
+ regid = ir3_find_output_regid(so, ir3_semantic_name(sem, 0));
+ dump_reg(name, regid);
+}
+
static void dump_info(struct ir3_shader_variant *so, const char *str)
{
- struct ir3_info info;
uint32_t *bin;
const char *type = (so->type == SHADER_VERTEX) ? "VERT" : "FRAG";
// for debug, dump some before/after info:
// TODO make gpu_id configurable on cmdline
- bin = ir3_assemble(so->ir, &info, 320);
+ bin = ir3_shader_assemble(so, 320);
if (fd_mesa_debug & FD_DBG_DISASM) {
struct ir3_block *block = so->ir->block;
struct ir3_register *reg;
}
}
- disasm_a3xx(bin, info.sizedwords, 0, so->type);
+ disasm_a3xx(bin, so->info.sizedwords, 0, so->type);
debug_printf("; %s: outputs:", type);
for (i = 0; i < so->outputs_count; i++) {
}
debug_printf("\n");
}
- debug_printf("; %s: %u instructions, %d half, %d full\n\n",
- type, info.instrs_count, info.max_half_reg + 1, info.max_reg + 1);
+
+ /* print generic shader info: */
+ debug_printf("; %s: %u instructions, %d half, %d full\n", type,
+ so->info.instrs_count,
+ so->info.max_half_reg + 1,
+ so->info.max_reg + 1);
+
+ /* print shader type specific info: */
+ switch (so->type) {
+ case SHADER_VERTEX:
+ dump_semantic(so, TGSI_SEMANTIC_POSITION, "pos");
+ dump_semantic(so, TGSI_SEMANTIC_PSIZE, "psize");
+ break;
+ case SHADER_FRAGMENT:
+ dump_reg("pos (bary)", so->pos_regid);
+ dump_semantic(so, TGSI_SEMANTIC_POSITION, "posz");
+ dump_semantic(so, TGSI_SEMANTIC_COLOR, "color");
+ /* these two are hard-coded since we don't know how to
+ * program them to anything but all 0's...
+ */
+ if (so->frag_coord)
+ debug_printf("; fragcoord: r0.x\n");
+ if (so->frag_face)
+ debug_printf("; fragface: hr0.x\n");
+ break;
+ case SHADER_COMPUTE:
+ break;
+ }
free(bin);
+
+ debug_printf("\n");
}
free(v);
}
+/* for vertex shader, the inputs are loaded into registers before the shader
+ * is executed, so max_regs from the shader instructions might not properly
+ * reflect the # of registers actually used, especially in case passthrough
+ * varyings.
+ *
+ * Likewise, for fragment shader, we can have some regs which are passed
+ * input values but never touched by the resulting shader (ie. as result
+ * of dead code elimination or simply because we don't know how to turn
+ * the reg off.
+ */
static void
-assemble_variant(struct ir3_shader_variant *v)
+fixup_regfootprint(struct ir3_shader_variant *v)
{
- struct fd_context *ctx = fd_context(v->shader->pctx);
- uint32_t gpu_id = ir3_shader_gpuid(v->shader);
- uint32_t sz, *bin;
-
- bin = ir3_assemble(v->ir, &v->info, gpu_id);
- sz = v->info.sizedwords * 4;
-
- v->bo = fd_bo_new(ctx->dev, sz,
- DRM_FREEDRENO_GEM_CACHE_WCOMBINE |
- DRM_FREEDRENO_GEM_TYPE_KMEM);
+ if (v->type == SHADER_VERTEX) {
+ unsigned i;
+ for (i = 0; i < v->inputs_count; i++) {
+ /* skip frag inputs fetch via bary.f since their reg's are
+ * not written by gpu before shader starts (and in fact the
+ * regid's might not even be valid)
+ */
+ if (v->inputs[i].bary)
+ continue;
+
+ if (v->inputs[i].compmask) {
+ int32_t regid = (v->inputs[i].regid + 3) >> 2;
+ v->info.max_reg = MAX2(v->info.max_reg, regid);
+ }
+ }
+ for (i = 0; i < v->outputs_count; i++) {
+ int32_t regid = (v->outputs[i].regid + 3) >> 2;
+ v->info.max_reg = MAX2(v->info.max_reg, regid);
+ }
+ } else if (v->type == SHADER_FRAGMENT) {
+ /* NOTE: not sure how to turn pos_regid off.. but this could
+ * be, for example, r1.x while max reg used by the shader is
+ * r0.*, in which case we need to fixup the reg footprint:
+ */
+ v->info.max_reg = MAX2(v->info.max_reg, v->pos_regid >> 2);
+ if (v->frag_coord)
+ debug_assert(v->info.max_reg >= 0); /* hard coded r0.x */
+ if (v->frag_face)
+ debug_assert(v->info.max_half_reg >= 0); /* hr0.x */
+ }
+}
- memcpy(fd_bo_map(v->bo), bin, sz);
+/* wrapper for ir3_assemble() which does some info fixup based on
+ * shader state. Non-static since used by ir3_cmdline too.
+ */
+void * ir3_shader_assemble(struct ir3_shader_variant *v, uint32_t gpu_id)
+{
+ void *bin;
- free(bin);
+ bin = ir3_assemble(v->ir, &v->info, gpu_id);
+ if (!bin)
+ return NULL;
if (gpu_id >= 400) {
v->instrlen = v->info.sizedwords / (2 * 16);
*/
v->constlen = MAX2(v->constlen, v->info.max_const + 1);
- /* no need to keep the ir around beyond this point: */
- ir3_destroy(v->ir);
- v->ir = NULL;
+ fixup_regfootprint(v);
+
+ return bin;
}
-/* for vertex shader, the inputs are loaded into registers before the shader
- * is executed, so max_regs from the shader instructions might not properly
- * reflect the # of registers actually used:
- */
static void
-fixup_vp_regfootprint(struct ir3_shader_variant *v)
+assemble_variant(struct ir3_shader_variant *v)
{
- unsigned i;
- for (i = 0; i < v->inputs_count; i++) {
- if (v->inputs[i].compmask) {
- int32_t regid = (v->inputs[i].regid + 3) >> 2;
- v->info.max_reg = MAX2(v->info.max_reg, regid);
- }
- }
- for (i = 0; i < v->outputs_count; i++) {
- int32_t regid = (v->outputs[i].regid + 3) >> 2;
- v->info.max_reg = MAX2(v->info.max_reg, regid);
- }
+ struct fd_context *ctx = fd_context(v->shader->pctx);
+ uint32_t gpu_id = ir3_shader_gpuid(v->shader);
+ uint32_t sz, *bin;
+
+ bin = ir3_shader_assemble(v, gpu_id);
+ sz = v->info.sizedwords * 4;
+
+ v->bo = fd_bo_new(ctx->dev, sz,
+ DRM_FREEDRENO_GEM_CACHE_WCOMBINE |
+ DRM_FREEDRENO_GEM_TYPE_KMEM);
+
+ memcpy(fd_bo_map(v->bo), bin, sz);
+
+ free(bin);
+
+ /* no need to keep the ir around beyond this point: */
+ ir3_destroy(v->ir);
+ v->ir = NULL;
}
/* reset before attempting to compile again.. */
goto fail;
}
- if (shader->type == SHADER_VERTEX)
- fixup_vp_regfootprint(v);
-
if (fd_mesa_debug & FD_DBG_DISASM) {
DBG("disassemble: type=%d, k={bp=%u,cts=%u,hp=%u}", v->type,
key.binning_pass, key.color_two_side, key.half_precision);