summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Natalie <jenatali@microsoft.com>2022-01-05 07:38:38 -0800
committerMarge Bot <emma+marge@anholt.net>2022-01-26 01:31:35 +0000
commitdf302f5f90ef6f83a8969d8c03576891339f7578 (patch)
tree3d327db2fcd20851652b36a1320aa5a6d2c7b3fd
parent1a231ec805ad837735b9d2dbdd5a4ead68484143 (diff)
d3d12: Update varying creation logic to handle location_frac
When multiple variables are packed into the same location, we need to re-construct variables that read/write the same components of that register so that the DXIL signature is correct. We could try to merge these variables, but getting the types right sounds harder than just preserving the multiple individual variables. Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Bill Kristiansen <billkris@microsoft.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14399>
-rw-r--r--src/gallium/drivers/d3d12/d3d12_compiler.cpp44
-rw-r--r--src/gallium/drivers/d3d12/d3d12_compiler.h15
-rw-r--r--src/gallium/drivers/d3d12/d3d12_gs_variant.cpp113
-rw-r--r--src/gallium/drivers/d3d12/d3d12_tcs_variant.cpp46
4 files changed, 126 insertions, 92 deletions
diff --git a/src/gallium/drivers/d3d12/d3d12_compiler.cpp b/src/gallium/drivers/d3d12/d3d12_compiler.cpp
index 345a1a3b739..53fc94ca9cb 100644
--- a/src/gallium/drivers/d3d12/d3d12_compiler.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_compiler.cpp
@@ -512,26 +512,36 @@ needs_vertex_reordering(struct d3d12_selection_context *sel_ctx, const struct pi
static nir_variable *
create_varying_from_info(nir_shader *nir, struct d3d12_varying_info *info,
- unsigned slot, nir_variable_mode mode, bool patch)
+ unsigned slot, unsigned slot_frac, nir_variable_mode mode, bool patch)
{
nir_variable *var;
char tmp[100];
snprintf(tmp, ARRAY_SIZE(tmp),
mode == nir_var_shader_in ? "in_%d" : "out_%d",
- info->vars[slot].driver_location);
- var = nir_variable_create(nir, mode, info->vars[slot].type, tmp);
+ info->slots[slot].vars[slot_frac].driver_location);
+ var = nir_variable_create(nir, mode, info->slots[slot].types[slot_frac], tmp);
var->data.location = slot;
- var->data.driver_location = info->vars[slot].driver_location;
- var->data.interpolation = info->vars[slot].interpolation;
- var->data.patch = info->vars[slot].patch;
- var->data.compact = info->vars[slot].compact;
+ var->data.location_frac = slot_frac;
+ var->data.driver_location = info->slots[slot].vars[slot_frac].driver_location;
+ var->data.interpolation = info->slots[slot].vars[slot_frac].interpolation;
+ var->data.patch = info->slots[slot].patch;
+ var->data.compact = info->slots[slot].vars[slot_frac].compact;
if (patch)
var->data.location += VARYING_SLOT_PATCH0;
return var;
}
+void
+create_varyings_from_info(nir_shader *nir, struct d3d12_varying_info *info,
+ unsigned slot, nir_variable_mode mode, bool patch)
+{
+ unsigned mask = info->slots[slot].location_frac_mask;
+ while (mask)
+ create_varying_from_info(nir, info, slot, u_bit_scan(&mask), mode, patch);
+}
+
static void
fill_varyings(struct d3d12_varying_info *info, nir_shader *s,
nir_variable_mode modes, uint64_t mask, bool patch)
@@ -547,12 +557,14 @@ fill_varyings(struct d3d12_varying_info *info, nir_shader *s,
if (!(mask & slot_bit))
continue;
- info->vars[slot].driver_location = var->data.driver_location;
- info->vars[slot].type = var->type;
- info->vars[slot].interpolation = var->data.interpolation;
- info->vars[slot].patch = var->data.patch;
- info->vars[slot].compact = var->data.compact;
+ info->slots[slot].types[var->data.location_frac] = var->type;
+ info->slots[slot].patch = var->data.patch;
+ auto& var_slot = info->slots[slot].vars[var->data.location_frac];
+ var_slot.driver_location = var->data.driver_location;
+ var_slot.interpolation = var->data.interpolation;
+ var_slot.compact = var->data.compact;
info->mask |= slot_bit;
+ info->slots[slot].location_frac_mask |= (1 << var->data.location_frac);
}
}
@@ -1066,14 +1078,14 @@ select_shader_variant(struct d3d12_selection_context *sel_ctx, d3d12_shader_sele
uint64_t mask = key.required_varying_inputs.mask & ~new_nir_variant->info.inputs_read;
while (mask) {
int slot = u_bit_scan64(&mask);
- create_varying_from_info(new_nir_variant, &key.required_varying_inputs, slot, nir_var_shader_in, false);
+ create_varyings_from_info(new_nir_variant, &key.required_varying_inputs, slot, nir_var_shader_in, false);
}
if (sel->stage == PIPE_SHADER_TESS_EVAL) {
uint32_t patch_mask = (uint32_t)key.ds.required_patch_inputs.mask & ~new_nir_variant->info.patch_inputs_read;
while (patch_mask) {
int slot = u_bit_scan(&patch_mask);
- create_varying_from_info(new_nir_variant, &key.ds.required_patch_inputs, slot, nir_var_shader_in, true);
+ create_varyings_from_info(new_nir_variant, &key.ds.required_patch_inputs, slot, nir_var_shader_in, true);
}
}
dxil_reassign_driver_locations(new_nir_variant, nir_var_shader_in,
@@ -1085,14 +1097,14 @@ select_shader_variant(struct d3d12_selection_context *sel_ctx, d3d12_shader_sele
uint64_t mask = key.required_varying_outputs.mask & ~new_nir_variant->info.outputs_written;
while (mask) {
int slot = u_bit_scan64(&mask);
- create_varying_from_info(new_nir_variant, &key.required_varying_outputs, slot, nir_var_shader_out, false);
+ create_varyings_from_info(new_nir_variant, &key.required_varying_outputs, slot, nir_var_shader_out, false);
}
if (sel->stage == PIPE_SHADER_TESS_CTRL) {
uint32_t patch_mask = (uint32_t)key.hs.required_patch_outputs.mask & ~new_nir_variant->info.patch_outputs_written;
while (patch_mask) {
int slot = u_bit_scan(&patch_mask);
- create_varying_from_info(new_nir_variant, &key.ds.required_patch_inputs, slot, nir_var_shader_out, true);
+ create_varyings_from_info(new_nir_variant, &key.ds.required_patch_inputs, slot, nir_var_shader_out, true);
}
}
dxil_reassign_driver_locations(new_nir_variant, nir_var_shader_out,
diff --git a/src/gallium/drivers/d3d12/d3d12_compiler.h b/src/gallium/drivers/d3d12/d3d12_compiler.h
index 6d670b9682c..fc5bfad8d6c 100644
--- a/src/gallium/drivers/d3d12/d3d12_compiler.h
+++ b/src/gallium/drivers/d3d12/d3d12_compiler.h
@@ -70,12 +70,15 @@ d3d12_get_compiler_options(struct pipe_screen *screen,
struct d3d12_varying_info {
struct {
- const struct glsl_type *type;
- unsigned interpolation:3; // INTERP_MODE_COUNT = 5
- unsigned driver_location:6; // VARYING_SLOT_MAX = 64
- unsigned patch:1;
- unsigned compact:1;
- } vars[VARYING_SLOT_MAX];
+ const struct glsl_type *types[4];
+ uint8_t location_frac_mask:2;
+ uint8_t patch:1;
+ struct {
+ unsigned interpolation:3; // INTERP_MODE_COUNT = 5
+ unsigned driver_location:6; // VARYING_SLOT_MAX = 64
+ unsigned compact:1;
+ } vars[4];
+ } slots[VARYING_SLOT_MAX];
uint64_t mask;
};
diff --git a/src/gallium/drivers/d3d12/d3d12_gs_variant.cpp b/src/gallium/drivers/d3d12/d3d12_gs_variant.cpp
index f3bb2f93edc..500a06b8b7c 100644
--- a/src/gallium/drivers/d3d12/d3d12_gs_variant.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_gs_variant.cpp
@@ -77,31 +77,40 @@ d3d12_make_passthrough_gs(struct d3d12_context *ctx, struct d3d12_gs_variant_key
/* Copy inputs to outputs. */
while (varyings) {
- nir_variable *in, *out;
char tmp[100];
const int i = u_bit_scan64(&varyings);
- snprintf(tmp, ARRAY_SIZE(tmp), "in_%d", key->varyings.vars[i].driver_location);
- in = nir_variable_create(nir,
- nir_var_shader_in,
- glsl_array_type(key->varyings.vars[i].type, 1, false),
- tmp);
- in->data.location = i;
- in->data.driver_location = key->varyings.vars[i].driver_location;
- in->data.interpolation = key->varyings.vars[i].interpolation;
-
- snprintf(tmp, ARRAY_SIZE(tmp), "out_%d", key->varyings.vars[i].driver_location);
- out = nir_variable_create(nir,
- nir_var_shader_out,
- key->varyings.vars[i].type,
- tmp);
- out->data.location = i;
- out->data.driver_location = key->varyings.vars[i].driver_location;
- out->data.interpolation = key->varyings.vars[i].interpolation;
-
- nir_deref_instr *in_value = nir_build_deref_array(&b, nir_build_deref_var(&b, in),
- nir_imm_int(&b, 0));
- nir_copy_deref(&b, nir_build_deref_var(&b, out), in_value);
+ unsigned frac_slots = key->varyings.slots[i].location_frac_mask;
+ while (frac_slots) {
+ nir_variable *in, *out;
+ int j = u_bit_scan(&frac_slots);
+
+ snprintf(tmp, ARRAY_SIZE(tmp), "in_%d", key->varyings.slots[i].vars[j].driver_location);
+ in = nir_variable_create(nir,
+ nir_var_shader_in,
+ glsl_array_type(key->varyings.slots[i].types[j], 1, false),
+ tmp);
+ in->data.location = i;
+ in->data.location_frac = j;
+ in->data.driver_location = key->varyings.slots[i].vars[j].driver_location;
+ in->data.interpolation = key->varyings.slots[i].vars[j].interpolation;
+ in->data.compact = key->varyings.slots[i].vars[j].compact;
+
+ snprintf(tmp, ARRAY_SIZE(tmp), "out_%d", key->varyings.slots[i].vars[j].driver_location);
+ out = nir_variable_create(nir,
+ nir_var_shader_out,
+ key->varyings.slots[i].types[j],
+ tmp);
+ out->data.location = i;
+ out->data.location_frac = j;
+ out->data.driver_location = key->varyings.slots[i].vars[j].driver_location;
+ out->data.interpolation = key->varyings.slots[i].vars[j].interpolation;
+ out->data.compact = key->varyings.slots[i].vars[j].compact;
+
+ nir_deref_instr *in_value = nir_build_deref_array(&b, nir_build_deref_var(&b, in),
+ nir_imm_int(&b, 0));
+ nir_copy_deref(&b, nir_build_deref_var(&b, out), in_value);
+ }
}
nir_emit_vertex(&b, 0);
@@ -168,33 +177,41 @@ d3d12_begin_emit_primitives_gs(struct emit_primitives_context *emit_ctx,
char tmp[100];
const int i = u_bit_scan64(&varyings);
- snprintf(tmp, ARRAY_SIZE(tmp), "in_%d", emit_ctx->num_vars);
- emit_ctx->in[emit_ctx->num_vars] = nir_variable_create(nir,
- nir_var_shader_in,
- glsl_array_type(key->varyings.vars[i].type, 3, 0),
- tmp);
- emit_ctx->in[emit_ctx->num_vars]->data.location = i;
- emit_ctx->in[emit_ctx->num_vars]->data.driver_location = key->varyings.vars[i].driver_location;
- emit_ctx->in[emit_ctx->num_vars]->data.interpolation = key->varyings.vars[i].interpolation;
-
- /* Don't create an output for the edge flag variable */
- if (i == VARYING_SLOT_EDGE) {
- edgeflag_var = emit_ctx->in[emit_ctx->num_vars];
- continue;
- } else if (i == VARYING_SLOT_POS) {
- pos_var = emit_ctx->in[emit_ctx->num_vars];
+ unsigned frac_slots = key->varyings.slots[i].location_frac_mask;
+ while (frac_slots) {
+ int j = u_bit_scan(&frac_slots);
+ snprintf(tmp, ARRAY_SIZE(tmp), "in_%d", emit_ctx->num_vars);
+ emit_ctx->in[emit_ctx->num_vars] = nir_variable_create(nir,
+ nir_var_shader_in,
+ glsl_array_type(key->varyings.slots[i].types[j], 3, 0),
+ tmp);
+ emit_ctx->in[emit_ctx->num_vars]->data.location = i;
+ emit_ctx->in[emit_ctx->num_vars]->data.location_frac = j;
+ emit_ctx->in[emit_ctx->num_vars]->data.driver_location = key->varyings.slots[i].vars[j].driver_location;
+ emit_ctx->in[emit_ctx->num_vars]->data.interpolation = key->varyings.slots[i].vars[j].interpolation;
+ emit_ctx->in[emit_ctx->num_vars]->data.compact = key->varyings.slots[i].vars[j].compact;
+
+ /* Don't create an output for the edge flag variable */
+ if (i == VARYING_SLOT_EDGE) {
+ edgeflag_var = emit_ctx->in[emit_ctx->num_vars];
+ continue;
+ } else if (i == VARYING_SLOT_POS) {
+ pos_var = emit_ctx->in[emit_ctx->num_vars];
+ }
+
+ snprintf(tmp, ARRAY_SIZE(tmp), "out_%d", emit_ctx->num_vars);
+ emit_ctx->out[emit_ctx->num_vars] = nir_variable_create(nir,
+ nir_var_shader_out,
+ key->varyings.slots[i].types[j],
+ tmp);
+ emit_ctx->out[emit_ctx->num_vars]->data.location = i;
+ emit_ctx->out[emit_ctx->num_vars]->data.location_frac = j;
+ emit_ctx->out[emit_ctx->num_vars]->data.driver_location = key->varyings.slots[i].vars[j].driver_location;
+ emit_ctx->out[emit_ctx->num_vars]->data.interpolation = key->varyings.slots[i].vars[j].interpolation;
+ emit_ctx->out[emit_ctx->num_vars]->data.compact = key->varyings.slots[i].vars[j].compact;
+
+ emit_ctx->num_vars++;
}
-
- snprintf(tmp, ARRAY_SIZE(tmp), "out_%d", emit_ctx->num_vars);
- emit_ctx->out[emit_ctx->num_vars] = nir_variable_create(nir,
- nir_var_shader_out,
- key->varyings.vars[i].type,
- tmp);
- emit_ctx->out[emit_ctx->num_vars]->data.location = i;
- emit_ctx->out[emit_ctx->num_vars]->data.driver_location = key->varyings.vars[i].driver_location;
- emit_ctx->out[emit_ctx->num_vars]->data.interpolation = key->varyings.vars[i].interpolation;
-
- emit_ctx->num_vars++;
}
if (key->has_front_face) {
diff --git a/src/gallium/drivers/d3d12/d3d12_tcs_variant.cpp b/src/gallium/drivers/d3d12/d3d12_tcs_variant.cpp
index 2f2bd903b66..1773ef488ff 100644
--- a/src/gallium/drivers/d3d12/d3d12_tcs_variant.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_tcs_variant.cpp
@@ -69,28 +69,30 @@ create_tess_ctrl_shader_variant(struct d3d12_context *ctx, struct d3d12_tcs_vari
while(varying_mask) {
int var_idx = u_bit_scan64(&varying_mask);
- auto var = &key->varyings.vars[var_idx];
- const struct glsl_type *type = var->type;
- const struct glsl_type *in_type = var->type;
- const struct glsl_type *out_type = var->type;
- in_type = glsl_array_type(type, key->vertices_out, 0);
- out_type = glsl_array_type(type, key->vertices_out, 0);
-
- char buf[1024];
- snprintf(buf, sizeof(buf), "in_%d", var->driver_location);
- nir_variable *in = nir_variable_create(nir, nir_var_shader_in, in_type, buf);
- snprintf(buf, sizeof(buf), "out_%d", var->driver_location);
- nir_variable *out = nir_variable_create(nir, nir_var_shader_out, out_type, buf);
- out->data.location = in->data.location = var_idx;
- out->data.driver_location = in->data.driver_location = var->driver_location;
-
- for (unsigned i = 0; i < key->vertices_out; i++) {
- nir_if *start_block = nir_push_if(&b, nir_ieq(&b, invocation_id, nir_imm_int(&b, i)));
- nir_deref_instr *in_array_var = nir_build_deref_array(&b, nir_build_deref_var(&b, in), invocation_id);
- nir_ssa_def *load = nir_load_deref(&b, in_array_var);
- nir_deref_instr *out_array_var = nir_build_deref_array_imm(&b, nir_build_deref_var(&b, out), i);
- nir_store_deref(&b, out_array_var, load, 0xff);
- nir_pop_if(&b, start_block);
+ auto slot = &key->varyings.slots[var_idx];
+ unsigned frac_mask = slot->location_frac_mask;
+ while (frac_mask) {
+ int frac = u_bit_scan(&frac_mask);
+ auto var = &slot->vars[frac];
+ const struct glsl_type *type = glsl_array_type(slot->types[frac], key->vertices_out, 0);
+
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "in_%d", var->driver_location);
+ nir_variable *in = nir_variable_create(nir, nir_var_shader_in, type, buf);
+ snprintf(buf, sizeof(buf), "out_%d", var->driver_location);
+ nir_variable *out = nir_variable_create(nir, nir_var_shader_out, type, buf);
+ out->data.location = in->data.location = var_idx;
+ out->data.location_frac = in->data.location_frac = frac;
+ out->data.driver_location = in->data.driver_location = var->driver_location;
+
+ for (unsigned i = 0; i < key->vertices_out; i++) {
+ nir_if *start_block = nir_push_if(&b, nir_ieq(&b, invocation_id, nir_imm_int(&b, i)));
+ nir_deref_instr *in_array_var = nir_build_deref_array(&b, nir_build_deref_var(&b, in), invocation_id);
+ nir_ssa_def *load = nir_load_deref(&b, in_array_var);
+ nir_deref_instr *out_array_var = nir_build_deref_array_imm(&b, nir_build_deref_var(&b, out), i);
+ nir_store_deref(&b, out_array_var, load, 0xff);
+ nir_pop_if(&b, start_block);
+ }
}
}
nir_variable *gl_TessLevelInner = nir_variable_create(nir, nir_var_shader_out, glsl_array_type(glsl_float_type(), 2, 0), "gl_TessLevelInner");