#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_scan.h"
+#include "freedreno_lowering.h"
+
#include "fd3_compiler.h"
#include "fd3_program.h"
#include "fd3_util.h"
struct fd3_compile_context {
const struct tgsi_token *tokens;
+ bool free_tokens;
struct ir3_shader *ir;
struct fd3_shader_stateobj *so;
{
unsigned ret, base = 0;
struct tgsi_shader_info *info = &ctx->info;
+ const struct fd_lowering_config lconfig = {
+ .lower_DST = true,
+ .lower_XPD = true,
+ .lower_SCS = true,
+ .lower_LRP = true,
+ .lower_FRC = 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,
+ };
- ctx->tokens = tokens;
+ ctx->tokens = fd_transform_lowering(&lconfig, tokens, &ctx->info);
+ ctx->free_tokens = !!ctx->tokens;
+ if (!ctx->tokens) {
+ /* no lowering */
+ ctx->tokens = tokens;
+ }
ctx->ir = so->ir;
ctx->so = so;
ctx->next_inloc = 8;
memset(ctx->base_reg, 0, sizeof(ctx->base_reg));
- tgsi_scan_shader(tokens, &ctx->info);
-
#define FM(x) (1 << TGSI_FILE_##x)
/* optimize can't deal with relative addressing: */
if (info->indirect_files & (FM(TEMPORARY) | FM(INPUT) |
so->first_immediate = ctx->base_reg[TGSI_FILE_IMMEDIATE];
ctx->immediate_idx = 4 * (ctx->info.file_max[TGSI_FILE_IMMEDIATE] + 1);
- ret = tgsi_parse_init(&ctx->parser, tokens);
+ ret = tgsi_parse_init(&ctx->parser, ctx->tokens);
if (ret != TGSI_PARSE_OK)
return ret;
static void
compile_free(struct fd3_compile_context *ctx)
{
+ if (ctx->free_tokens)
+ free((void *)ctx->tokens);
tgsi_parse_free(&ctx->parser);
}
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_scan.h"
+#include "freedreno_lowering.h"
+
#include "fd3_compiler.h"
#include "fd3_program.h"
#include "fd3_util.h"
struct fd3_compile_context {
const struct tgsi_token *tokens;
+ bool free_tokens;
struct ir3_shader *ir;
struct ir3_block *block;
struct fd3_shader_stateobj *so;
{
unsigned ret, base = 0;
struct tgsi_shader_info *info = &ctx->info;
+ const struct fd_lowering_config lconfig = {
+ .lower_DST = true,
+ .lower_XPD = true,
+ .lower_SCS = true,
+ .lower_LRP = true,
+ .lower_FRC = 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,
+ };
- ctx->tokens = tokens;
+ ctx->tokens = fd_transform_lowering(&lconfig, tokens, &ctx->info);
+ ctx->free_tokens = !!ctx->tokens;
+ if (!ctx->tokens) {
+ /* no lowering */
+ ctx->tokens = tokens;
+ }
ctx->ir = so->ir;
ctx->block = ir3_block_create(ctx->ir, 0, 0, 0);
ctx->so = so;
regmask_init(&ctx->needs_sy);
memset(ctx->base_reg, 0, sizeof(ctx->base_reg));
- tgsi_scan_shader(tokens, &ctx->info);
-
/* Immediates go after constants: */
ctx->base_reg[TGSI_FILE_CONSTANT] = 0;
ctx->base_reg[TGSI_FILE_IMMEDIATE] =
so->first_immediate = ctx->base_reg[TGSI_FILE_IMMEDIATE];
ctx->immediate_idx = 4 * (ctx->info.file_max[TGSI_FILE_IMMEDIATE] + 1);
- ret = tgsi_parse_init(&ctx->parser, tokens);
+ ret = tgsi_parse_init(&ctx->parser, ctx->tokens);
if (ret != TGSI_PARSE_OK)
return ret;
static void
compile_free(struct fd3_compile_context *ctx)
{
+ if (ctx->free_tokens)
+ free((void *)ctx->tokens);
tgsi_parse_free(&ctx->parser);
}
struct fd_lowering_context {
struct tgsi_transform_context base;
- struct tgsi_shader_info info;
+ const struct fd_lowering_config *config;
+ struct tgsi_shader_info *info;
unsigned numtmp;
struct {
struct tgsi_full_src_register src;
if (!ctx->emitted_decls) {
struct tgsi_full_declaration decl;
struct tgsi_full_immediate immed;
- unsigned tmpbase = ctx->info.file_max[TGSI_FILE_TEMPORARY] + 1;
+ unsigned tmpbase = ctx->info->file_max[TGSI_FILE_TEMPORARY] + 1;
int i;
/* declare immediate: */
tctx->emit_immediate(tctx, &immed);
ctx->imm.Register.File = TGSI_FILE_IMMEDIATE;
- ctx->imm.Register.Index = ctx->info.immediate_count;
+ ctx->imm.Register.Index = ctx->info->immediate_count;
ctx->imm.Register.SwizzleX = TGSI_SWIZZLE_X;
ctx->imm.Register.SwizzleY = TGSI_SWIZZLE_Y;
ctx->imm.Register.SwizzleZ = TGSI_SWIZZLE_Z;
switch (inst->Instruction.Opcode) {
case TGSI_OPCODE_DST:
+ if (!ctx->config->lower_DST)
+ goto skip;
transform_dst(tctx, inst);
break;
case TGSI_OPCODE_XPD:
+ if (!ctx->config->lower_XPD)
+ goto skip;
transform_xpd(tctx, inst);
break;
case TGSI_OPCODE_SCS:
+ if (!ctx->config->lower_SCS)
+ goto skip;
transform_scs(tctx, inst);
break;
case TGSI_OPCODE_LRP:
+ if (!ctx->config->lower_LRP)
+ goto skip;
transform_lrp(tctx, inst);
break;
case TGSI_OPCODE_FRC:
+ if (!ctx->config->lower_FRC)
+ goto skip;
transform_frc(tctx, inst);
break;
case TGSI_OPCODE_POW:
+ if (!ctx->config->lower_POW)
+ goto skip;
transform_pow(tctx, inst);
break;
case TGSI_OPCODE_LIT:
+ if (!ctx->config->lower_LIT)
+ goto skip;
transform_lit(tctx, inst);
break;
case TGSI_OPCODE_EXP:
+ if (!ctx->config->lower_EXP)
+ goto skip;
transform_exp(tctx, inst);
break;
case TGSI_OPCODE_LOG:
+ if (!ctx->config->lower_LOG)
+ goto skip;
transform_log(tctx, inst);
break;
case TGSI_OPCODE_DP4:
+ if (!ctx->config->lower_DP4)
+ goto skip;
+ transform_dotp(tctx, inst);
+ break;
case TGSI_OPCODE_DP3:
+ if (!ctx->config->lower_DP3)
+ goto skip;
+ transform_dotp(tctx, inst);
+ break;
case TGSI_OPCODE_DPH:
+ if (!ctx->config->lower_DPH)
+ goto skip;
+ transform_dotp(tctx, inst);
+ break;
case TGSI_OPCODE_DP2:
+ if (!ctx->config->lower_DP2)
+ goto skip;
+ transform_dotp(tctx, inst);
+ break;
case TGSI_OPCODE_DP2A:
+ if (!ctx->config->lower_DP2A)
+ goto skip;
transform_dotp(tctx, inst);
break;
default:
+ skip:
tctx->emit_instruction(tctx, inst);
break;
}
}
+/* returns NULL if no lowering required, else returns the new
+ * tokens (which caller is required to free()). In either case
+ * returns the current info.
+ */
const struct tgsi_token *
-fd_transform_lowering(const struct tgsi_token *tokens)
+fd_transform_lowering(const struct fd_lowering_config *config,
+ const struct tgsi_token *tokens,
+ struct tgsi_shader_info *info)
{
struct fd_lowering_context ctx;
struct tgsi_token *newtoks;
memset(&ctx, 0, sizeof(ctx));
ctx.base.transform_instruction = transform_instr;
+ ctx.info = info;
+ ctx.config = config;
- tgsi_scan_shader(tokens, &ctx.info);
+ tgsi_scan_shader(tokens, info);
-#define OPCS(x) (ctx.info.opcode_count[TGSI_OPCODE_ ## x])
+#define OPCS(x) ((config->lower_ ## x) ? info->opcode_count[TGSI_OPCODE_ ## x] : 0)
/* if there are no instructions to lower, then we are done: */
if (!(OPCS(DST) ||
OPCS(XPD) ||
OPCS(DPH) ||
OPCS(DP2) ||
OPCS(DP2A)))
- return tokens;
+ return NULL;
#if 0 /* debug */
_debug_printf("BEFORE:");
newtoks = tgsi_alloc_tokens(newlen);
if (!newtoks)
- goto out;
+ return NULL;
tgsi_transform_shader(tokens, newtoks, newlen, &ctx.base);
+ tgsi_scan_shader(newtoks, info);
+
#if 0 /* debug */
_debug_printf("AFTER:");
tgsi_dump(newtoks, 0);
#endif
-out:
-// XXX caller frees orig tokens.. need to change the api around so
-// called by compiler.. compiler then would have to know to free
-// new tokens. Should be able to get rid of an extra tgsi_scan step..
-// but need to move the tgsi dump stuff into compiler then??
-// free((struct tgsi_token *)tokens);
return newtoks;
}
#define FREEDRENO_LOWERING_H_
#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_scan.h"
-const struct tgsi_token * fd_transform_lowering(const struct tgsi_token *tokens);
+struct fd_lowering_config {
+ /* Individual OPC lowerings, if lower_<opc> is TRUE then
+ * enable lowering of TGSI_OPCODE_<opc>
+ */
+ unsigned lower_DST : 1;
+ unsigned lower_XPD : 1;
+ unsigned lower_SCS : 1;
+ unsigned lower_LRP : 1;
+ unsigned lower_FRC : 1;
+ unsigned lower_POW : 1;
+ unsigned lower_LIT : 1;
+ unsigned lower_EXP : 1;
+ unsigned lower_LOG : 1;
+ unsigned lower_DP4 : 1;
+ unsigned lower_DP3 : 1;
+ unsigned lower_DPH : 1;
+ unsigned lower_DP2 : 1;
+ unsigned lower_DP2A : 1;
+};
+
+const struct tgsi_token * fd_transform_lowering(
+ const struct fd_lowering_config *config,
+ const struct tgsi_token *tokens,
+ struct tgsi_shader_info *info);
#endif /* FREEDRENO_LOWERING_H_ */