*/
enum direction { F, R };
+struct nir_schedule_class_dep {
+ int klass;
+ nir_schedule_node *node;
+ struct nir_schedule_class_dep *next;
+};
+
typedef struct {
nir_schedule_scoreboard *scoreboard;
nir_schedule_node *discard;
nir_schedule_node *jump;
+ struct nir_schedule_class_dep *class_deps;
+
enum direction dir;
} nir_deps_state;
return true;
}
+static struct nir_schedule_class_dep *
+nir_schedule_get_class_dep(nir_deps_state *state,
+ int klass)
+{
+ for (struct nir_schedule_class_dep *class_dep = state->class_deps;
+ class_dep != NULL;
+ class_dep = class_dep->next) {
+ if (class_dep->klass == klass)
+ return class_dep;
+ }
+
+ struct nir_schedule_class_dep *class_dep =
+ ralloc(state->reg_map, struct nir_schedule_class_dep);
+
+ class_dep->klass = klass;
+ class_dep->node = NULL;
+ class_dep->next = state->class_deps;
+
+ state->class_deps = class_dep;
+
+ return class_dep;
+}
+
static void
nir_schedule_intrinsic_deps(nir_deps_state *state,
nir_intrinsic_instr *instr)
{
nir_schedule_node *n = nir_schedule_get_node(state->scoreboard->instr_map,
&instr->instr);
+ const nir_schedule_options *options = state->scoreboard->options;
+ nir_schedule_dependency dep;
+
+ if (options->intrinsic_cb &&
+ options->intrinsic_cb(instr, &dep, options->intrinsic_cb_data)) {
+ struct nir_schedule_class_dep *class_dep =
+ nir_schedule_get_class_dep(state, dep.klass);
+
+ switch (dep.type) {
+ case NIR_SCHEDULE_READ_DEPENDENCY:
+ add_read_dep(state, class_dep->node, n);
+ break;
+ case NIR_SCHEDULE_WRITE_DEPENDENCY:
+ add_write_dep(state, &class_dep->node, n);
+ break;
+ }
+ }
switch (instr->intrinsic) {
case nir_intrinsic_load_uniform:
extern "C" {
#endif
+/**
+ * Struct filled in by the intrinsic_cb callback of nir_schedule_options to
+ * specify a backend-specific dependency on an intrinsic.
+ */
+typedef struct nir_schedule_dependency {
+ /* Which class of dependency this is. The meanings of the classes are
+ * specific to the backend. This must be less than
+ * NIR_SCHEDULE_N_DEPENDENCY_CLASSES.
+ */
+ int klass;
+ /* The type of dependency */
+ enum {
+ NIR_SCHEDULE_READ_DEPENDENCY,
+ NIR_SCHEDULE_WRITE_DEPENDENCY,
+ } type;
+} nir_schedule_dependency;
+
typedef struct nir_schedule_options {
/* On some hardware with some stages the inputs and outputs to the shader
* share the same memory. In that case the scheduler needs to ensure that
* will try to reduce register usage.
*/
int threshold;
+ /* Callback used to add custom dependencies on intrinsics. If it returns
+ * true then a dependency should be added and dep is filled in to describe
+ * it.
+ */
+ bool (* intrinsic_cb)(nir_intrinsic_instr *intr,
+ nir_schedule_dependency *dep,
+ void *user_data);
+ /* Data to pass to the callback */
+ void *intrinsic_cb_data;
} nir_schedule_options;
void nir_schedule(nir_shader *shader, const nir_schedule_options *options);