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>
This commit is contained in:
parent
1a231ec805
commit
df302f5f90
|
@ -512,26 +512,36 @@ needs_vertex_reordering(struct d3d12_selection_context *sel_ctx, const struct pi
|
||||||
|
|
||||||
static nir_variable *
|
static nir_variable *
|
||||||
create_varying_from_info(nir_shader *nir, struct d3d12_varying_info *info,
|
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;
|
nir_variable *var;
|
||||||
char tmp[100];
|
char tmp[100];
|
||||||
|
|
||||||
snprintf(tmp, ARRAY_SIZE(tmp),
|
snprintf(tmp, ARRAY_SIZE(tmp),
|
||||||
mode == nir_var_shader_in ? "in_%d" : "out_%d",
|
mode == nir_var_shader_in ? "in_%d" : "out_%d",
|
||||||
info->vars[slot].driver_location);
|
info->slots[slot].vars[slot_frac].driver_location);
|
||||||
var = nir_variable_create(nir, mode, info->vars[slot].type, tmp);
|
var = nir_variable_create(nir, mode, info->slots[slot].types[slot_frac], tmp);
|
||||||
var->data.location = slot;
|
var->data.location = slot;
|
||||||
var->data.driver_location = info->vars[slot].driver_location;
|
var->data.location_frac = slot_frac;
|
||||||
var->data.interpolation = info->vars[slot].interpolation;
|
var->data.driver_location = info->slots[slot].vars[slot_frac].driver_location;
|
||||||
var->data.patch = info->vars[slot].patch;
|
var->data.interpolation = info->slots[slot].vars[slot_frac].interpolation;
|
||||||
var->data.compact = info->vars[slot].compact;
|
var->data.patch = info->slots[slot].patch;
|
||||||
|
var->data.compact = info->slots[slot].vars[slot_frac].compact;
|
||||||
if (patch)
|
if (patch)
|
||||||
var->data.location += VARYING_SLOT_PATCH0;
|
var->data.location += VARYING_SLOT_PATCH0;
|
||||||
|
|
||||||
return var;
|
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
|
static void
|
||||||
fill_varyings(struct d3d12_varying_info *info, nir_shader *s,
|
fill_varyings(struct d3d12_varying_info *info, nir_shader *s,
|
||||||
nir_variable_mode modes, uint64_t mask, bool patch)
|
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))
|
if (!(mask & slot_bit))
|
||||||
continue;
|
continue;
|
||||||
info->vars[slot].driver_location = var->data.driver_location;
|
info->slots[slot].types[var->data.location_frac] = var->type;
|
||||||
info->vars[slot].type = var->type;
|
info->slots[slot].patch = var->data.patch;
|
||||||
info->vars[slot].interpolation = var->data.interpolation;
|
auto& var_slot = info->slots[slot].vars[var->data.location_frac];
|
||||||
info->vars[slot].patch = var->data.patch;
|
var_slot.driver_location = var->data.driver_location;
|
||||||
info->vars[slot].compact = var->data.compact;
|
var_slot.interpolation = var->data.interpolation;
|
||||||
|
var_slot.compact = var->data.compact;
|
||||||
info->mask |= slot_bit;
|
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;
|
uint64_t mask = key.required_varying_inputs.mask & ~new_nir_variant->info.inputs_read;
|
||||||
while (mask) {
|
while (mask) {
|
||||||
int slot = u_bit_scan64(&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) {
|
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;
|
uint32_t patch_mask = (uint32_t)key.ds.required_patch_inputs.mask & ~new_nir_variant->info.patch_inputs_read;
|
||||||
while (patch_mask) {
|
while (patch_mask) {
|
||||||
int slot = u_bit_scan(&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,
|
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;
|
uint64_t mask = key.required_varying_outputs.mask & ~new_nir_variant->info.outputs_written;
|
||||||
while (mask) {
|
while (mask) {
|
||||||
int slot = u_bit_scan64(&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) {
|
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;
|
uint32_t patch_mask = (uint32_t)key.hs.required_patch_outputs.mask & ~new_nir_variant->info.patch_outputs_written;
|
||||||
while (patch_mask) {
|
while (patch_mask) {
|
||||||
int slot = u_bit_scan(&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,
|
dxil_reassign_driver_locations(new_nir_variant, nir_var_shader_out,
|
||||||
|
|
|
@ -70,12 +70,15 @@ d3d12_get_compiler_options(struct pipe_screen *screen,
|
||||||
|
|
||||||
struct d3d12_varying_info {
|
struct d3d12_varying_info {
|
||||||
struct {
|
struct {
|
||||||
const struct glsl_type *type;
|
const struct glsl_type *types[4];
|
||||||
unsigned interpolation:3; // INTERP_MODE_COUNT = 5
|
uint8_t location_frac_mask:2;
|
||||||
unsigned driver_location:6; // VARYING_SLOT_MAX = 64
|
uint8_t patch:1;
|
||||||
unsigned patch:1;
|
struct {
|
||||||
unsigned compact:1;
|
unsigned interpolation:3; // INTERP_MODE_COUNT = 5
|
||||||
} vars[VARYING_SLOT_MAX];
|
unsigned driver_location:6; // VARYING_SLOT_MAX = 64
|
||||||
|
unsigned compact:1;
|
||||||
|
} vars[4];
|
||||||
|
} slots[VARYING_SLOT_MAX];
|
||||||
uint64_t mask;
|
uint64_t mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -77,31 +77,40 @@ d3d12_make_passthrough_gs(struct d3d12_context *ctx, struct d3d12_gs_variant_key
|
||||||
|
|
||||||
/* Copy inputs to outputs. */
|
/* Copy inputs to outputs. */
|
||||||
while (varyings) {
|
while (varyings) {
|
||||||
nir_variable *in, *out;
|
|
||||||
char tmp[100];
|
char tmp[100];
|
||||||
const int i = u_bit_scan64(&varyings);
|
const int i = u_bit_scan64(&varyings);
|
||||||
|
|
||||||
snprintf(tmp, ARRAY_SIZE(tmp), "in_%d", key->varyings.vars[i].driver_location);
|
unsigned frac_slots = key->varyings.slots[i].location_frac_mask;
|
||||||
in = nir_variable_create(nir,
|
while (frac_slots) {
|
||||||
nir_var_shader_in,
|
nir_variable *in, *out;
|
||||||
glsl_array_type(key->varyings.vars[i].type, 1, false),
|
int j = u_bit_scan(&frac_slots);
|
||||||
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);
|
snprintf(tmp, ARRAY_SIZE(tmp), "in_%d", key->varyings.slots[i].vars[j].driver_location);
|
||||||
out = nir_variable_create(nir,
|
in = nir_variable_create(nir,
|
||||||
nir_var_shader_out,
|
nir_var_shader_in,
|
||||||
key->varyings.vars[i].type,
|
glsl_array_type(key->varyings.slots[i].types[j], 1, false),
|
||||||
tmp);
|
tmp);
|
||||||
out->data.location = i;
|
in->data.location = i;
|
||||||
out->data.driver_location = key->varyings.vars[i].driver_location;
|
in->data.location_frac = j;
|
||||||
out->data.interpolation = key->varyings.vars[i].interpolation;
|
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;
|
||||||
|
|
||||||
nir_deref_instr *in_value = nir_build_deref_array(&b, nir_build_deref_var(&b, in),
|
snprintf(tmp, ARRAY_SIZE(tmp), "out_%d", key->varyings.slots[i].vars[j].driver_location);
|
||||||
nir_imm_int(&b, 0));
|
out = nir_variable_create(nir,
|
||||||
nir_copy_deref(&b, nir_build_deref_var(&b, out), in_value);
|
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);
|
nir_emit_vertex(&b, 0);
|
||||||
|
@ -168,33 +177,41 @@ d3d12_begin_emit_primitives_gs(struct emit_primitives_context *emit_ctx,
|
||||||
char tmp[100];
|
char tmp[100];
|
||||||
const int i = u_bit_scan64(&varyings);
|
const int i = u_bit_scan64(&varyings);
|
||||||
|
|
||||||
snprintf(tmp, ARRAY_SIZE(tmp), "in_%d", emit_ctx->num_vars);
|
unsigned frac_slots = key->varyings.slots[i].location_frac_mask;
|
||||||
emit_ctx->in[emit_ctx->num_vars] = nir_variable_create(nir,
|
while (frac_slots) {
|
||||||
nir_var_shader_in,
|
int j = u_bit_scan(&frac_slots);
|
||||||
glsl_array_type(key->varyings.vars[i].type, 3, 0),
|
snprintf(tmp, ARRAY_SIZE(tmp), "in_%d", emit_ctx->num_vars);
|
||||||
tmp);
|
emit_ctx->in[emit_ctx->num_vars] = nir_variable_create(nir,
|
||||||
emit_ctx->in[emit_ctx->num_vars]->data.location = i;
|
nir_var_shader_in,
|
||||||
emit_ctx->in[emit_ctx->num_vars]->data.driver_location = key->varyings.vars[i].driver_location;
|
glsl_array_type(key->varyings.slots[i].types[j], 3, 0),
|
||||||
emit_ctx->in[emit_ctx->num_vars]->data.interpolation = key->varyings.vars[i].interpolation;
|
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 */
|
/* Don't create an output for the edge flag variable */
|
||||||
if (i == VARYING_SLOT_EDGE) {
|
if (i == VARYING_SLOT_EDGE) {
|
||||||
edgeflag_var = emit_ctx->in[emit_ctx->num_vars];
|
edgeflag_var = emit_ctx->in[emit_ctx->num_vars];
|
||||||
continue;
|
continue;
|
||||||
} else if (i == VARYING_SLOT_POS) {
|
} else if (i == VARYING_SLOT_POS) {
|
||||||
pos_var = emit_ctx->in[emit_ctx->num_vars];
|
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) {
|
if (key->has_front_face) {
|
||||||
|
|
|
@ -69,28 +69,30 @@ create_tess_ctrl_shader_variant(struct d3d12_context *ctx, struct d3d12_tcs_vari
|
||||||
|
|
||||||
while(varying_mask) {
|
while(varying_mask) {
|
||||||
int var_idx = u_bit_scan64(&varying_mask);
|
int var_idx = u_bit_scan64(&varying_mask);
|
||||||
auto var = &key->varyings.vars[var_idx];
|
auto slot = &key->varyings.slots[var_idx];
|
||||||
const struct glsl_type *type = var->type;
|
unsigned frac_mask = slot->location_frac_mask;
|
||||||
const struct glsl_type *in_type = var->type;
|
while (frac_mask) {
|
||||||
const struct glsl_type *out_type = var->type;
|
int frac = u_bit_scan(&frac_mask);
|
||||||
in_type = glsl_array_type(type, key->vertices_out, 0);
|
auto var = &slot->vars[frac];
|
||||||
out_type = glsl_array_type(type, key->vertices_out, 0);
|
const struct glsl_type *type = glsl_array_type(slot->types[frac], key->vertices_out, 0);
|
||||||
|
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
snprintf(buf, sizeof(buf), "in_%d", var->driver_location);
|
snprintf(buf, sizeof(buf), "in_%d", var->driver_location);
|
||||||
nir_variable *in = nir_variable_create(nir, nir_var_shader_in, in_type, buf);
|
nir_variable *in = nir_variable_create(nir, nir_var_shader_in, type, buf);
|
||||||
snprintf(buf, sizeof(buf), "out_%d", var->driver_location);
|
snprintf(buf, sizeof(buf), "out_%d", var->driver_location);
|
||||||
nir_variable *out = nir_variable_create(nir, nir_var_shader_out, out_type, buf);
|
nir_variable *out = nir_variable_create(nir, nir_var_shader_out, type, buf);
|
||||||
out->data.location = in->data.location = var_idx;
|
out->data.location = in->data.location = var_idx;
|
||||||
out->data.driver_location = in->data.driver_location = var->driver_location;
|
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++) {
|
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_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_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_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_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_store_deref(&b, out_array_var, load, 0xff);
|
||||||
nir_pop_if(&b, start_block);
|
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");
|
nir_variable *gl_TessLevelInner = nir_variable_create(nir, nir_var_shader_out, glsl_array_type(glsl_float_type(), 2, 0), "gl_TessLevelInner");
|
||||||
|
|
Loading…
Reference in New Issue