nir_variable **inputs;
nir_variable **outputs;
+ nir_variable *samplers[PIPE_MAX_SAMPLERS];
+
+ nir_variable *input_var_face;
+ nir_variable *input_var_position;
/**
* Stack of nir_cursors where instructions should be pushed as we pop
return nir_fmov_alu(b, src, 4);
}
+static enum glsl_interp_mode
+ttn_translate_interp_mode(unsigned tgsi_interp)
+{
+ switch (tgsi_interp) {
+ case TGSI_INTERPOLATE_CONSTANT:
+ return INTERP_MODE_FLAT;
+ case TGSI_INTERPOLATE_LINEAR:
+ return INTERP_MODE_NOPERSPECTIVE;
+ case TGSI_INTERPOLATE_PERSPECTIVE:
+ return INTERP_MODE_SMOOTH;
+ case TGSI_INTERPOLATE_COLOR:
+ return INTERP_MODE_SMOOTH;
+ default:
+ unreachable("bad TGSI interpolation mode");
+ }
+}
+
static void
ttn_emit_declaration(struct ttn_compile *c)
{
if (c->scan->processor == PIPE_SHADER_FRAGMENT) {
if (decl->Semantic.Name == TGSI_SEMANTIC_FACE) {
- var->data.location = SYSTEM_VALUE_FRONT_FACE;
- var->data.mode = nir_var_system_value;
+ var->type = glsl_bool_type();
+ if (c->cap_face_is_sysval) {
+ var->data.mode = nir_var_system_value;
+ var->data.location = SYSTEM_VALUE_FRONT_FACE;
+ } else {
+ var->data.location = VARYING_SLOT_FACE;
+ }
+ c->input_var_face = var;
+ } else if (decl->Semantic.Name == TGSI_SEMANTIC_POSITION) {
+ if (c->cap_position_is_sysval) {
+ var->data.mode = nir_var_system_value;
+ var->data.location = SYSTEM_VALUE_FRAG_COORD;
+ } else {
+ var->data.location = VARYING_SLOT_POS;
+ }
+ c->input_var_position = var;
} else {
var->data.location =
tgsi_varying_semantic_to_slot(decl->Semantic.Name,
var->data.location = VERT_ATTRIB_GENERIC0 + idx;
}
var->data.index = 0;
-
- /* We definitely need to translate the interpolation field, because
- * nir_print will decode it.
- */
- switch (decl->Interp.Interpolate) {
- case TGSI_INTERPOLATE_CONSTANT:
- var->data.interpolation = INTERP_MODE_FLAT;
- break;
- case TGSI_INTERPOLATE_LINEAR:
- var->data.interpolation = INTERP_MODE_NOPERSPECTIVE;
- break;
- case TGSI_INTERPOLATE_PERSPECTIVE:
- var->data.interpolation = INTERP_MODE_SMOOTH;
- break;
- }
+ var->data.interpolation =
+ ttn_translate_interp_mode(decl->Interp.Interpolate);
exec_list_push_tail(&b->shader->inputs, &var->node);
c->inputs[idx] = var;
var->data.mode = nir_var_shader_out;
var->name = ralloc_asprintf(var, "out_%d", idx);
var->data.index = 0;
+ var->data.interpolation =
+ ttn_translate_interp_mode(decl->Interp.Interpolate);
if (c->scan->processor == PIPE_SHADER_FRAGMENT) {
switch (semantic_name) {
case TGSI_FILE_CONSTANT:
var->data.mode = nir_var_uniform;
var->name = ralloc_asprintf(var, "uniform_%d", idx);
+ var->data.location = idx;
exec_list_push_tail(&b->shader->uniforms, &var->node);
break;
}
/* Special case: Turn the frontface varying into a load of the
- * frontface intrinsic plus math, and appending the silly floats.
+ * frontface variable, and create the vector as required by TGSI.
*/
static nir_ssa_def *
ttn_emulate_tgsi_front_face(struct ttn_compile *c)
{
- nir_ssa_def *tgsi_frontface[4] = {
- nir_bcsel(&c->build,
- nir_load_front_face(&c->build, 1),
- nir_imm_float(&c->build, 1.0),
- nir_imm_float(&c->build, -1.0)),
- nir_imm_float(&c->build, 0.0),
- nir_imm_float(&c->build, 0.0),
- nir_imm_float(&c->build, 1.0),
- };
+ nir_ssa_def *tgsi_frontface[4];
+
+ if (c->cap_face_is_sysval) {
+ /* When it's a system value, it should be an integer vector: (F, 0, 0, 1)
+ * F is 0xffffffff if front-facing, 0 if not.
+ */
+
+ nir_ssa_def *frontface = nir_load_front_face(&c->build, 1);
+
+ tgsi_frontface[0] = nir_bcsel(&c->build,
+ frontface,
+ nir_imm_int(&c->build, 0xffffffff),
+ nir_imm_int(&c->build, 0));
+ tgsi_frontface[1] = nir_imm_int(&c->build, 0);
+ tgsi_frontface[2] = nir_imm_int(&c->build, 0);
+ tgsi_frontface[3] = nir_imm_int(&c->build, 1);
+ } else {
+ /* When it's an input, it should be a float vector: (F, 0.0, 0.0, 1.0)
+ * F is positive if front-facing, negative if not.
+ */
+
+ assert(c->input_var_face);
+ nir_ssa_def *frontface = nir_load_var(&c->build, c->input_var_face);
+
+ tgsi_frontface[0] = nir_bcsel(&c->build,
+ frontface,
+ nir_imm_float(&c->build, 1.0),
+ nir_imm_float(&c->build, -1.0));
+ tgsi_frontface[1] = nir_imm_float(&c->build, 0.0);
+ tgsi_frontface[2] = nir_imm_float(&c->build, 0.0);
+ tgsi_frontface[3] = nir_imm_float(&c->build, 1.0);
+ }
return nir_vec(&c->build, tgsi_frontface, 4);
}
op = nir_intrinsic_load_instance_id;
load = nir_load_instance_id(b);
break;
+ case TGSI_SEMANTIC_FACE:
+ assert(c->cap_face_is_sysval);
+ op = nir_intrinsic_load_front_face;
+ load = ttn_emulate_tgsi_front_face(c);
+ break;
+ case TGSI_SEMANTIC_POSITION:
+ assert(c->cap_position_is_sysval);
+ op = nir_intrinsic_load_frag_coord;
+ load = nir_load_frag_coord(b);
+ break;
default:
unreachable("bad system value");
}
case TGSI_FILE_INPUT:
if (c->scan->processor == PIPE_SHADER_FRAGMENT &&
c->scan->input_semantic_name[index] == TGSI_SEMANTIC_FACE) {
+ assert(!c->cap_face_is_sysval && c->input_var_face);
return nir_src_for_ssa(ttn_emulate_tgsi_front_face(c));
+ } else if (c->scan->processor == PIPE_SHADER_FRAGMENT &&
+ c->scan->input_semantic_name[index] == TGSI_SEMANTIC_POSITION) {
+ assert(!c->cap_position_is_sysval && c->input_var_position);
+ return nir_src_for_ssa(nir_load_var(&c->build, c->input_var_position));
} else {
/* Indirection on input arrays isn't supported by TTN. */
assert(!dim);
}
}
+static enum glsl_base_type
+base_type_for_alu_type(nir_alu_type type)
+{
+ type = nir_alu_type_get_base_type(type);
+
+ switch (type) {
+ case nir_type_float:
+ return GLSL_TYPE_FLOAT;
+ case nir_type_int:
+ return GLSL_TYPE_INT;
+ case nir_type_uint:
+ return GLSL_TYPE_UINT;
+ default:
+ unreachable("invalid type");
+ }
+}
+
+static nir_variable *
+get_sampler_var(struct ttn_compile *c, int binding,
+ enum glsl_sampler_dim dim,
+ bool is_shadow,
+ bool is_array,
+ enum glsl_base_type base_type)
+{
+ nir_variable *var = c->samplers[binding];
+ if (!var) {
+ const struct glsl_type *type =
+ glsl_sampler_type(dim, is_shadow, is_array, base_type);
+ var = nir_variable_create(c->build.shader, nir_var_uniform, type,
+ "sampler");
+ var->data.binding = binding;
+ var->data.explicit_binding = true;
+ c->samplers[binding] = var;
+ }
+
+ return var;
+}
+
static void
ttn_tex(struct ttn_compile *c, nir_alu_dest dest, nir_ssa_def **src)
{
num_srcs++;
}
+ /* Deref sources */
+ num_srcs += 2;
+
num_srcs += tgsi_inst->Texture.NumOffsets;
instr = nir_tex_instr_create(b->shader, num_srcs);
instr->coord_components++;
assert(tgsi_inst->Src[samp].Register.File == TGSI_FILE_SAMPLER);
- instr->texture_index = tgsi_inst->Src[samp].Register.Index;
- instr->sampler_index = tgsi_inst->Src[samp].Register.Index;
/* TODO if we supported any opc's which take an explicit SVIEW
* src, we would use that here instead. But for the "legacy"
* texture opc's the SVIEW index is same as SAMP index:
*/
- sview = instr->texture_index;
+ sview = tgsi_inst->Src[samp].Register.Index;
if (op == nir_texop_lod) {
instr->dest_type = nir_type_float;
instr->dest_type = nir_type_float;
}
+ nir_variable *var =
+ get_sampler_var(c, sview, instr->sampler_dim,
+ instr->is_shadow,
+ instr->is_array,
+ base_type_for_alu_type(instr->dest_type));
+
+ nir_deref_instr *deref = nir_build_deref_var(b, var);
+
unsigned src_number = 0;
+ instr->src[src_number].src = nir_src_for_ssa(&deref->dest.ssa);
+ instr->src[src_number].src_type = nir_tex_src_texture_deref;
+ src_number++;
+ instr->src[src_number].src = nir_src_for_ssa(&deref->dest.ssa);
+ instr->src[src_number].src_type = nir_tex_src_sampler_deref;
+ src_number++;
+
instr->src[src_number].src =
nir_src_for_ssa(nir_swizzle(b, src[0], SWIZ(X, Y, Z, W),
instr->coord_components, false));
}
assert(src_number == num_srcs);
+ assert(src_number == instr->num_srcs);
nir_ssa_dest_init(&instr->instr, &instr->dest,
nir_tex_instr_dest_size(instr),
struct tgsi_full_instruction *tgsi_inst = &c->token->FullInstruction;
nir_tex_instr *txs, *qlv;
- txs = nir_tex_instr_create(b->shader, 1);
+ txs = nir_tex_instr_create(b->shader, 2);
txs->op = nir_texop_txs;
setup_texture_info(txs, tgsi_inst->Texture.Texture);
- qlv = nir_tex_instr_create(b->shader, 0);
+ qlv = nir_tex_instr_create(b->shader, 1);
qlv->op = nir_texop_query_levels;
setup_texture_info(qlv, tgsi_inst->Texture.Texture);
assert(tgsi_inst->Src[1].Register.File == TGSI_FILE_SAMPLER);
- txs->texture_index = tgsi_inst->Src[1].Register.Index;
- qlv->texture_index = tgsi_inst->Src[1].Register.Index;
+ int tex_index = tgsi_inst->Src[1].Register.Index;
+
+ nir_variable *var =
+ get_sampler_var(c, tex_index, txs->sampler_dim,
+ txs->is_shadow,
+ txs->is_array,
+ base_type_for_alu_type(txs->dest_type));
+
+ nir_deref_instr *deref = nir_build_deref_var(b, var);
+
+ txs->src[0].src = nir_src_for_ssa(&deref->dest.ssa);
+ txs->src[0].src_type = nir_tex_src_texture_deref;
+
+ qlv->src[0].src = nir_src_for_ssa(&deref->dest.ssa);
+ qlv->src[0].src_type = nir_tex_src_texture_deref;
- /* only single src, the lod: */
- txs->src[0].src = nir_src_for_ssa(ttn_channel(b, src[0], X));
- txs->src[0].src_type = nir_tex_src_lod;
+ /* lod: */
+ txs->src[1].src = nir_src_for_ssa(ttn_channel(b, src[0], X));
+ txs->src[1].src_type = nir_tex_src_lod;
nir_ssa_dest_init(&txs->instr, &txs->dest,
nir_tex_instr_dest_size(txs), 32, NULL);
NIR_PASS(progress, nir, nir_opt_dce);
}
- NIR_PASS(progress, nir, nir_opt_if);
+ NIR_PASS(progress, nir, nir_opt_if, false);
NIR_PASS(progress, nir, nir_opt_dead_cf);
NIR_PASS(progress, nir, nir_opt_cse);
NIR_PASS(progress, nir, nir_opt_peephole_select, 8, true, true);
NIR_PASS_V(nir, nir_lower_global_vars_to_local);
NIR_PASS_V(nir, nir_split_var_copies);
NIR_PASS_V(nir, nir_lower_var_copies);
+ NIR_PASS_V(nir, nir_lower_system_values);
if (c->cap_packed_uniforms)
NIR_PASS_V(nir, nir_lower_uniforms_to_ubo, 16);