mesa/src/microsoft/spirv_to_dxil/dxil_spirv_nir.c

774 lines
27 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright © Microsoft Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "spirv_to_dxil.h"
#include "nir_to_dxil.h"
#include "dxil_nir.h"
#include "dxil_nir_lower_int_cubemaps.h"
#include "shader_enums.h"
#include "spirv/nir_spirv.h"
#include "util/blob.h"
#include "dxil_spirv_nir.h"
#include "git_sha1.h"
#include "vulkan/vulkan.h"
static void
shared_var_info(const struct glsl_type* type, unsigned* size, unsigned* align)
{
assert(glsl_type_is_vector_or_scalar(type));
uint32_t comp_size = glsl_type_is_boolean(type) ? 4 : glsl_get_bit_size(type) / 8;
unsigned length = glsl_get_vector_elements(type);
*size = comp_size * length;
*align = comp_size;
}
static nir_variable *
add_runtime_data_var(nir_shader *nir, unsigned desc_set, unsigned binding)
{
unsigned runtime_data_size =
nir->info.stage == MESA_SHADER_COMPUTE
? sizeof(struct dxil_spirv_compute_runtime_data)
: sizeof(struct dxil_spirv_vertex_runtime_data);
const struct glsl_type *array_type =
glsl_array_type(glsl_uint_type(), runtime_data_size / sizeof(unsigned),
sizeof(unsigned));
const struct glsl_struct_field field = {array_type, "arr"};
nir_variable *var = nir_variable_create(
nir, nir_var_mem_ubo,
glsl_struct_type(&field, 1, "runtime_data", false), "runtime_data");
var->data.descriptor_set = desc_set;
// Check that desc_set fits on descriptor_set
assert(var->data.descriptor_set == desc_set);
var->data.binding = binding;
var->data.how_declared = nir_var_hidden;
return var;
}
struct lower_system_values_data {
nir_address_format ubo_format;
unsigned desc_set;
unsigned binding;
};
static bool
lower_shader_system_values(struct nir_builder *builder, nir_instr *instr,
void *cb_data)
{
if (instr->type != nir_instr_type_intrinsic) {
return false;
}
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
/* All the intrinsics we care about are loads */
if (!nir_intrinsic_infos[intrin->intrinsic].has_dest)
return false;
assert(intrin->dest.is_ssa);
int offset = 0;
switch (intrin->intrinsic) {
case nir_intrinsic_load_num_workgroups:
offset =
offsetof(struct dxil_spirv_compute_runtime_data, group_count_x);
break;
case nir_intrinsic_load_first_vertex:
offset = offsetof(struct dxil_spirv_vertex_runtime_data, first_vertex);
break;
case nir_intrinsic_load_is_indexed_draw:
offset =
offsetof(struct dxil_spirv_vertex_runtime_data, is_indexed_draw);
break;
case nir_intrinsic_load_base_instance:
offset = offsetof(struct dxil_spirv_vertex_runtime_data, base_instance);
break;
case nir_intrinsic_load_draw_id:
offset = offsetof(struct dxil_spirv_vertex_runtime_data, draw_id);
break;
default:
return false;
}
struct lower_system_values_data *data =
(struct lower_system_values_data *)cb_data;
builder->cursor = nir_after_instr(instr);
nir_address_format ubo_format = data->ubo_format;
nir_ssa_def *index = nir_vulkan_resource_index(
builder, nir_address_format_num_components(ubo_format),
nir_address_format_bit_size(ubo_format),
nir_imm_int(builder, 0),
.desc_set = data->desc_set, .binding = data->binding,
.desc_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
nir_ssa_def *load_desc = nir_load_vulkan_descriptor(
builder, nir_address_format_num_components(ubo_format),
nir_address_format_bit_size(ubo_format),
index, .desc_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
nir_ssa_def *load_data = build_load_ubo_dxil(
builder, nir_channel(builder, load_desc, 0),
nir_imm_int(builder, offset),
nir_dest_num_components(intrin->dest), nir_dest_bit_size(intrin->dest));
nir_ssa_def_rewrite_uses(&intrin->dest.ssa, load_data);
nir_instr_remove(instr);
return true;
}
static bool
dxil_spirv_nir_lower_shader_system_values(nir_shader *shader,
nir_address_format ubo_format,
unsigned desc_set, unsigned binding)
{
struct lower_system_values_data data = {
.ubo_format = ubo_format,
.desc_set = desc_set,
.binding = binding,
};
return nir_shader_instructions_pass(shader, lower_shader_system_values,
nir_metadata_block_index |
nir_metadata_dominance |
nir_metadata_loop_analysis,
&data);
}
static nir_variable *
add_push_constant_var(nir_shader *nir, unsigned size, unsigned desc_set, unsigned binding)
{
/* Size must be a multiple of 16 as buffer load is loading 16 bytes at a time */
unsigned num_32bit_words = ALIGN_POT(size, 16) / 4;
const struct glsl_type *array_type =
glsl_array_type(glsl_uint_type(), num_32bit_words, 4);
const struct glsl_struct_field field = {array_type, "arr"};
nir_variable *var = nir_variable_create(
nir, nir_var_mem_ubo,
glsl_struct_type(&field, 1, "block", false), "push_constants");
var->data.descriptor_set = desc_set;
var->data.binding = binding;
var->data.how_declared = nir_var_hidden;
return var;
}
struct lower_load_push_constant_data {
nir_address_format ubo_format;
unsigned desc_set;
unsigned binding;
unsigned size;
};
static bool
lower_load_push_constant(struct nir_builder *builder, nir_instr *instr,
void *cb_data)
{
struct lower_load_push_constant_data *data =
(struct lower_load_push_constant_data *)cb_data;
if (instr->type != nir_instr_type_intrinsic)
return false;
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
/* All the intrinsics we care about are loads */
if (intrin->intrinsic != nir_intrinsic_load_push_constant)
return false;
uint32_t base = nir_intrinsic_base(intrin);
uint32_t range = nir_intrinsic_range(intrin);
data->size = MAX2(base + range, data->size);
builder->cursor = nir_after_instr(instr);
nir_address_format ubo_format = data->ubo_format;
nir_ssa_def *index = nir_vulkan_resource_index(
builder, nir_address_format_num_components(ubo_format),
nir_address_format_bit_size(ubo_format),
nir_imm_int(builder, 0),
.desc_set = data->desc_set, .binding = data->binding,
.desc_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
nir_ssa_def *load_desc = nir_load_vulkan_descriptor(
builder, nir_address_format_num_components(ubo_format),
nir_address_format_bit_size(ubo_format),
index, .desc_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
nir_ssa_def *offset = nir_ssa_for_src(builder, intrin->src[0], 1);
nir_ssa_def *load_data = build_load_ubo_dxil(
builder, nir_channel(builder, load_desc, 0),
nir_iadd_imm(builder, offset, base),
nir_dest_num_components(intrin->dest), nir_dest_bit_size(intrin->dest));
nir_ssa_def_rewrite_uses(&intrin->dest.ssa, load_data);
nir_instr_remove(instr);
return true;
}
static bool
dxil_spirv_nir_lower_load_push_constant(nir_shader *shader,
nir_address_format ubo_format,
unsigned desc_set, unsigned binding,
uint32_t *size)
{
bool ret;
struct lower_load_push_constant_data data = {
.ubo_format = ubo_format,
.desc_set = desc_set,
.binding = binding,
};
ret = nir_shader_instructions_pass(shader, lower_load_push_constant,
nir_metadata_block_index |
nir_metadata_dominance |
nir_metadata_loop_analysis,
&data);
*size = data.size;
assert(ret == (*size > 0));
return ret;
}
struct lower_yz_flip_data {
bool *reads_sysval_ubo;
const struct dxil_spirv_runtime_conf *rt_conf;
};
static bool
lower_yz_flip(struct nir_builder *builder, nir_instr *instr,
void *cb_data)
{
struct lower_yz_flip_data *data =
(struct lower_yz_flip_data *)cb_data;
if (instr->type != nir_instr_type_intrinsic)
return false;
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
if (intrin->intrinsic != nir_intrinsic_store_deref)
return false;
nir_variable *var = nir_intrinsic_get_var(intrin, 0);
if (var->data.mode != nir_var_shader_out ||
var->data.location != VARYING_SLOT_POS)
return false;
builder->cursor = nir_before_instr(instr);
const struct dxil_spirv_runtime_conf *rt_conf = data->rt_conf;
nir_ssa_def *pos = nir_ssa_for_src(builder, intrin->src[1], 4);
nir_ssa_def *y_pos = nir_channel(builder, pos, 1);
nir_ssa_def *z_pos = nir_channel(builder, pos, 2);
nir_ssa_def *y_flip_mask = NULL, *z_flip_mask = NULL, *dyn_yz_flip_mask = NULL;
if (rt_conf->yz_flip.mode & DXIL_SPIRV_YZ_FLIP_CONDITIONAL) {
// conditional YZ-flip. The flip bitmask is passed through the vertex
// runtime data UBO.
unsigned offset =
offsetof(struct dxil_spirv_vertex_runtime_data, yz_flip_mask);
nir_address_format ubo_format = nir_address_format_32bit_index_offset;
nir_ssa_def *index = nir_vulkan_resource_index(
builder, nir_address_format_num_components(ubo_format),
nir_address_format_bit_size(ubo_format),
nir_imm_int(builder, 0),
.desc_set = rt_conf->runtime_data_cbv.register_space,
.binding = rt_conf->runtime_data_cbv.base_shader_register,
.desc_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
nir_ssa_def *load_desc = nir_load_vulkan_descriptor(
builder, nir_address_format_num_components(ubo_format),
nir_address_format_bit_size(ubo_format),
index, .desc_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
dyn_yz_flip_mask =
build_load_ubo_dxil(builder,
nir_channel(builder, load_desc, 0),
nir_imm_int(builder, offset), 1, 32);
*data->reads_sysval_ubo = true;
}
if (rt_conf->yz_flip.mode & DXIL_SPIRV_Y_FLIP_UNCONDITIONAL)
y_flip_mask = nir_imm_int(builder, rt_conf->yz_flip.y_mask);
else if (rt_conf->yz_flip.mode & DXIL_SPIRV_Y_FLIP_CONDITIONAL)
y_flip_mask = nir_iand_imm(builder, dyn_yz_flip_mask, DXIL_SPIRV_Y_FLIP_MASK);
if (rt_conf->yz_flip.mode & DXIL_SPIRV_Z_FLIP_UNCONDITIONAL)
z_flip_mask = nir_imm_int(builder, rt_conf->yz_flip.z_mask);
else if (rt_conf->yz_flip.mode & DXIL_SPIRV_Z_FLIP_CONDITIONAL)
z_flip_mask = nir_ushr_imm(builder, dyn_yz_flip_mask, DXIL_SPIRV_Z_FLIP_SHIFT);
/* TODO: Multi-viewport */
if (y_flip_mask) {
nir_ssa_def *flip = nir_test_mask(builder, y_flip_mask, 1);
// Z-flip => pos.y = -pos.y
y_pos = nir_bcsel(builder, flip, nir_fneg(builder, y_pos), y_pos);
}
if (z_flip_mask) {
nir_ssa_def *flip = nir_test_mask(builder, z_flip_mask, 1);
// Z-flip => pos.z = -pos.z + 1.0f
z_pos = nir_bcsel(builder, flip,
nir_fadd_imm(builder, nir_fneg(builder, z_pos), 1.0f),
z_pos);
}
nir_ssa_def *def = nir_vec4(builder,
nir_channel(builder, pos, 0),
y_pos,
z_pos,
nir_channel(builder, pos, 3));
nir_instr_rewrite_src(&intrin->instr, &intrin->src[1], nir_src_for_ssa(def));
return true;
}
static bool
dxil_spirv_nir_lower_yz_flip(nir_shader *shader,
const struct dxil_spirv_runtime_conf *rt_conf,
bool *reads_sysval_ubo)
{
struct lower_yz_flip_data data = {
.rt_conf = rt_conf,
.reads_sysval_ubo = reads_sysval_ubo,
};
return nir_shader_instructions_pass(shader, lower_yz_flip,
nir_metadata_block_index |
nir_metadata_dominance |
nir_metadata_loop_analysis,
&data);
}
static bool
discard_psiz_access(struct nir_builder *builder, nir_instr *instr,
void *cb_data)
{
if (instr->type != nir_instr_type_intrinsic)
return false;
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
if (intrin->intrinsic != nir_intrinsic_store_deref &&
intrin->intrinsic != nir_intrinsic_load_deref)
return false;
nir_variable *var = nir_intrinsic_get_var(intrin, 0);
if (!var || var->data.mode != nir_var_shader_out ||
var->data.location != VARYING_SLOT_PSIZ)
return false;
builder->cursor = nir_before_instr(instr);
if (intrin->intrinsic == nir_intrinsic_load_deref)
nir_ssa_def_rewrite_uses(&intrin->dest.ssa, nir_imm_float(builder, 1.0));
nir_instr_remove(instr);
return true;
}
static bool
dxil_spirv_nir_discard_point_size_var(nir_shader *shader)
{
if (shader->info.stage != MESA_SHADER_VERTEX &&
shader->info.stage != MESA_SHADER_TESS_EVAL &&
shader->info.stage != MESA_SHADER_GEOMETRY)
return false;
nir_variable *psiz = NULL;
nir_foreach_shader_out_variable(var, shader) {
if (var->data.location == VARYING_SLOT_PSIZ) {
psiz = var;
break;
}
}
if (!psiz)
return false;
if (!nir_shader_instructions_pass(shader, discard_psiz_access,
nir_metadata_block_index |
nir_metadata_dominance |
nir_metadata_loop_analysis,
NULL))
return false;
nir_remove_dead_derefs(shader);
return true;
}
static bool
kill_undefined_varyings(struct nir_builder *b,
nir_instr *instr,
void *data)
{
const nir_shader *prev_stage_nir = data;
if (instr->type != nir_instr_type_intrinsic)
return false;
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
if (intr->intrinsic != nir_intrinsic_load_deref)
return false;
nir_variable *var = nir_intrinsic_get_var(intr, 0);
if (!var)
return false;
/* Ignore builtins for now, some of them get default values
* when not written from previous stages.
*/
if (var->data.location < VARYING_SLOT_VAR0)
return false;
uint32_t loc = var->data.patch ?
var->data.location - VARYING_SLOT_PATCH0 : var->data.location;
uint64_t written = var->data.patch ?
prev_stage_nir->info.patch_outputs_written :
prev_stage_nir->info.outputs_written;
if (BITFIELD64_BIT(loc) & written)
return false;
b->cursor = nir_after_instr(instr);
nir_ssa_def *undef =
nir_ssa_undef(b, nir_dest_num_components(intr->dest),
nir_dest_bit_size(intr->dest));
nir_ssa_def_rewrite_uses(&intr->dest.ssa, undef);
nir_instr_remove(instr);
return true;
}
static bool
dxil_spirv_nir_kill_undefined_varyings(nir_shader *shader,
const nir_shader *prev_stage_shader)
{
if (!nir_shader_instructions_pass(shader,
kill_undefined_varyings,
nir_metadata_dominance |
nir_metadata_block_index |
nir_metadata_loop_analysis,
(void *)prev_stage_shader))
return false;
nir_remove_dead_derefs(shader);
nir_remove_dead_variables(shader, nir_var_shader_in, NULL);
return true;
}
static bool
kill_unused_outputs(struct nir_builder *b,
nir_instr *instr,
void *data)
{
uint64_t kill_mask = *((uint64_t *)data);
if (instr->type != nir_instr_type_intrinsic)
return false;
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
if (intr->intrinsic != nir_intrinsic_store_deref)
return false;
nir_variable *var = nir_intrinsic_get_var(intr, 0);
if (!var || var->data.mode != nir_var_shader_out)
return false;
unsigned loc = var->data.patch ?
var->data.location - VARYING_SLOT_PATCH0 :
var->data.location;
if (!(BITFIELD64_BIT(loc) & kill_mask))
return false;
nir_instr_remove(instr);
return true;
}
static bool
dxil_spirv_nir_kill_unused_outputs(nir_shader *shader,
nir_shader *next_stage_shader)
{
uint64_t kill_var_mask =
shader->info.outputs_written & ~next_stage_shader->info.inputs_read;
bool progress = false;
/* Don't kill buitin vars */
kill_var_mask &= BITFIELD64_MASK(MAX_VARYING) << VARYING_SLOT_VAR0;
if (nir_shader_instructions_pass(shader,
kill_unused_outputs,
nir_metadata_dominance |
nir_metadata_block_index |
nir_metadata_loop_analysis,
(void *)&kill_var_mask))
progress = true;
if (shader->info.stage == MESA_SHADER_TESS_EVAL) {
kill_var_mask =
(shader->info.patch_outputs_written |
shader->info.patch_outputs_read) &
~next_stage_shader->info.patch_inputs_read;
if (nir_shader_instructions_pass(shader,
kill_unused_outputs,
nir_metadata_dominance |
nir_metadata_block_index |
nir_metadata_loop_analysis,
(void *)&kill_var_mask))
progress = true;
}
if (progress) {
nir_opt_dce(shader);
nir_remove_dead_derefs(shader);
nir_remove_dead_variables(shader, nir_var_shader_out, NULL);
}
return progress;
}
void
dxil_spirv_nir_link(nir_shader *nir, nir_shader *prev_stage_nir)
{
glsl_type_singleton_init_or_ref();
if (prev_stage_nir) {
NIR_PASS_V(nir, dxil_spirv_nir_kill_undefined_varyings, prev_stage_nir);
NIR_PASS_V(prev_stage_nir, dxil_spirv_nir_kill_unused_outputs, nir);
nir->info.inputs_read =
dxil_reassign_driver_locations(nir, nir_var_shader_in,
prev_stage_nir->info.outputs_written);
prev_stage_nir->info.outputs_written =
dxil_reassign_driver_locations(prev_stage_nir, nir_var_shader_out,
nir->info.inputs_read);
}
glsl_type_singleton_decref();
}
void
dxil_spirv_nir_passes(nir_shader *nir,
const struct dxil_spirv_runtime_conf *conf,
bool *requires_runtime_data)
{
glsl_type_singleton_init_or_ref();
NIR_PASS_V(nir, dxil_nir_lower_int_cubemaps, false);
NIR_PASS_V(nir, nir_lower_io_to_vector,
nir_var_shader_out |
(nir->info.stage != MESA_SHADER_VERTEX ? nir_var_shader_in : 0));
NIR_PASS_V(nir, nir_opt_combine_stores, nir_var_shader_out);
NIR_PASS_V(nir, nir_remove_dead_derefs);
const struct nir_lower_sysvals_to_varyings_options sysvals_to_varyings = {
.frag_coord = true,
.point_coord = true,
};
NIR_PASS_V(nir, nir_lower_sysvals_to_varyings, &sysvals_to_varyings);
NIR_PASS_V(nir, nir_lower_system_values);
// Force sample-rate shading if we're asked to.
if (conf->force_sample_rate_shading) {
assert(nir->info.stage == MESA_SHADER_FRAGMENT);
nir_foreach_shader_in_variable(var, nir)
var->data.sample = true;
}
if (conf->zero_based_vertex_instance_id) {
// vertex_id and instance_id should have already been transformed to
// base zero before spirv_to_dxil was called. Therefore, we can zero out
// base/firstVertex/Instance.
gl_system_value system_values[] = {SYSTEM_VALUE_FIRST_VERTEX,
SYSTEM_VALUE_BASE_VERTEX,
SYSTEM_VALUE_BASE_INSTANCE};
NIR_PASS_V(nir, dxil_nir_lower_system_values_to_zero, system_values,
ARRAY_SIZE(system_values));
}
*requires_runtime_data = false;
NIR_PASS(*requires_runtime_data, nir,
dxil_spirv_nir_lower_shader_system_values,
nir_address_format_32bit_index_offset,
conf->runtime_data_cbv.register_space,
conf->runtime_data_cbv.base_shader_register);
if (nir->info.stage == MESA_SHADER_FRAGMENT) {
NIR_PASS_V(nir, nir_lower_input_attachments,
&(nir_input_attachment_options){
.use_fragcoord_sysval = false,
.use_layer_id_sysval = true,
});
NIR_PASS_V(nir, dxil_nir_lower_discard_and_terminate);
NIR_PASS_V(nir, nir_lower_returns);
}
NIR_PASS_V(nir, nir_opt_deref);
if (conf->read_only_images_as_srvs) {
const nir_opt_access_options opt_access_options = {
.is_vulkan = true,
.infer_non_readable = true,
};
NIR_PASS_V(nir, nir_opt_access, &opt_access_options);
}
NIR_PASS_V(nir, dxil_spirv_nir_discard_point_size_var);
NIR_PASS_V(nir, nir_remove_dead_variables,
nir_var_shader_in | nir_var_shader_out |
nir_var_system_value | nir_var_mem_shared,
NULL);
uint32_t push_constant_size = 0;
NIR_PASS_V(nir, nir_lower_explicit_io, nir_var_mem_push_const,
nir_address_format_32bit_offset);
NIR_PASS_V(nir, dxil_spirv_nir_lower_load_push_constant,
nir_address_format_32bit_index_offset,
conf->push_constant_cbv.register_space,
conf->push_constant_cbv.base_shader_register,
&push_constant_size);
NIR_PASS_V(nir, nir_lower_explicit_io, nir_var_mem_ubo | nir_var_mem_ssbo,
nir_address_format_32bit_index_offset);
if (!nir->info.shared_memory_explicit_layout) {
NIR_PASS_V(nir, nir_lower_vars_to_explicit_types, nir_var_mem_shared,
shared_var_info);
}
NIR_PASS_V(nir, nir_lower_explicit_io, nir_var_mem_shared,
nir_address_format_32bit_offset_as_64bit);
NIR_PASS_V(nir, nir_lower_clip_cull_distance_arrays);
NIR_PASS_V(nir, nir_lower_io_to_temporaries, nir_shader_get_entrypoint(nir), 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_io_arrays_to_elements_no_indirects, false);
if (conf->yz_flip.mode != DXIL_SPIRV_YZ_FLIP_NONE) {
assert(nir->info.stage == MESA_SHADER_VERTEX ||
nir->info.stage == MESA_SHADER_GEOMETRY);
NIR_PASS_V(nir,
dxil_spirv_nir_lower_yz_flip,
conf, requires_runtime_data);
}
if (*requires_runtime_data) {
add_runtime_data_var(nir, conf->runtime_data_cbv.register_space,
conf->runtime_data_cbv.base_shader_register);
}
if (push_constant_size > 0) {
add_push_constant_var(nir, push_constant_size,
conf->push_constant_cbv.register_space,
conf->push_constant_cbv.base_shader_register);
}
NIR_PASS_V(nir, nir_lower_alu_to_scalar, NULL, NULL);
NIR_PASS_V(nir, nir_opt_dce);
NIR_PASS_V(nir, dxil_nir_lower_double_math);
{
bool progress;
do
{
progress = false;
NIR_PASS(progress, nir, nir_copy_prop);
NIR_PASS(progress, nir, nir_opt_copy_prop_vars);
NIR_PASS(progress, nir, nir_opt_deref);
NIR_PASS(progress, nir, nir_opt_dce);
NIR_PASS(progress, nir, nir_opt_undef);
NIR_PASS(progress, nir, nir_opt_constant_folding);
NIR_PASS(progress, nir, nir_opt_cse);
if (nir_opt_trivial_continues(nir)) {
progress = true;
NIR_PASS(progress, nir, nir_copy_prop);
NIR_PASS(progress, nir, nir_opt_dce);
}
NIR_PASS(progress, nir, nir_lower_vars_to_ssa);
NIR_PASS(progress, nir, nir_opt_algebraic);
} while (progress);
}
NIR_PASS_V(nir, nir_lower_readonly_images_to_tex, true);
nir_lower_tex_options lower_tex_options = {
.lower_invalid_implicit_lod = true,
};
NIR_PASS_V(nir, nir_lower_tex, &lower_tex_options);
NIR_PASS_V(nir, dxil_nir_lower_atomics_to_dxil);
NIR_PASS_V(nir, dxil_nir_split_clip_cull_distance);
NIR_PASS_V(nir, dxil_nir_lower_loads_stores_to_dxil);
NIR_PASS_V(nir, dxil_nir_split_typed_samplers);
NIR_PASS_V(nir, dxil_nir_lower_bool_input);
NIR_PASS_V(nir, dxil_nir_lower_ubo_array_one_to_static);
NIR_PASS_V(nir, nir_opt_dce);
NIR_PASS_V(nir, nir_remove_dead_derefs);
NIR_PASS_V(nir, nir_remove_dead_variables,
nir_var_uniform | nir_var_shader_in | nir_var_shader_out,
NULL);
if (nir->info.stage == MESA_SHADER_FRAGMENT) {
dxil_sort_ps_outputs(nir);
} else {
/* Dummy linking step so we get different driver_location
* assigned even if there's just a single vertex shader in the
* pipeline. The real linking happens in dxil_spirv_nir_link().
*/
nir->info.outputs_written =
dxil_reassign_driver_locations(nir, nir_var_shader_out, 0);
}
if (nir->info.stage == MESA_SHADER_VERTEX) {
nir_foreach_variable_with_modes(var, nir, nir_var_shader_in) {
/* spirv_to_dxil() only emits generic vertex attributes. */
assert(var->data.location >= VERT_ATTRIB_GENERIC0);
var->data.driver_location = var->data.location - VERT_ATTRIB_GENERIC0;
}
nir->info.inputs_read =
dxil_sort_by_driver_location(nir, nir_var_shader_in);
} else {
nir->info.inputs_read =
dxil_reassign_driver_locations(nir, nir_var_shader_in, 0);
}
nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
glsl_type_singleton_decref();
}