spirv2dxil: Support passing first vertex / base instance to DXIL backend

These values now have 3 modes of operation so switch from a bool to an enum:
1. Zero
2. Native DXIL sysvals
3. "Runtime data" via a constant buffer or root constants

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28383>
This commit is contained in:
Jesse Natalie 2024-03-25 07:37:16 -07:00 committed by Marge Bot
parent 607720151f
commit 30b1a6750c
5 changed files with 24 additions and 11 deletions

View file

@ -213,6 +213,8 @@ lower_shader_system_values(struct nir_builder *builder, nir_instr *instr,
offsetof(struct dxil_spirv_compute_runtime_data, base_group_x);
break;
case nir_intrinsic_load_first_vertex:
if (conf->first_vertex_and_base_instance_mode == DXIL_SPIRV_SYSVAL_TYPE_NATIVE)
return false;
offset = offsetof(struct dxil_spirv_vertex_runtime_data, first_vertex);
break;
case nir_intrinsic_load_is_indexed_draw:
@ -220,6 +222,8 @@ lower_shader_system_values(struct nir_builder *builder, nir_instr *instr,
offsetof(struct dxil_spirv_vertex_runtime_data, is_indexed_draw);
break;
case nir_intrinsic_load_base_instance:
if (conf->first_vertex_and_base_instance_mode == DXIL_SPIRV_SYSVAL_TYPE_NATIVE)
return false;
offset = offsetof(struct dxil_spirv_vertex_runtime_data, base_instance);
break;
case nir_intrinsic_load_draw_id:
@ -887,7 +891,7 @@ dxil_spirv_nir_passes(nir_shader *nir,
NIR_PASS_V(nir, nir_lower_system_values);
nir_lower_compute_system_values_options compute_options = {
.has_base_workgroup_id = !conf->zero_based_compute_workgroup_id,
.has_base_workgroup_id = conf->workgroup_id_mode != DXIL_SPIRV_SYSVAL_TYPE_ZERO,
};
NIR_PASS_V(nir, nir_lower_compute_system_values, &compute_options);
NIR_PASS_V(nir, dxil_nir_lower_subgroup_id);
@ -917,7 +921,7 @@ dxil_spirv_nir_passes(nir_shader *nir,
nir->info.fs.uses_sample_shading = true;
}
if (conf->zero_based_vertex_instance_id) {
if (conf->first_vertex_and_base_instance_mode == DXIL_SPIRV_SYSVAL_TYPE_ZERO) {
// 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.

View file

@ -182,7 +182,7 @@ main(int argc, char **argv)
conf.runtime_data_cbv.register_space = 31;
conf.push_constant_cbv.base_shader_register = 0;
conf.push_constant_cbv.register_space = 30;
conf.zero_based_vertex_instance_id = true;
conf.first_vertex_and_base_instance_mode = DXIL_SPIRV_SYSVAL_TYPE_ZERO;
conf.declared_read_only_images_as_srvs = true;
conf.shader_model_max = SHADER_MODEL_6_2;
@ -218,6 +218,8 @@ main(int argc, char **argv)
break;
case 'm':
conf.shader_model_max = SHADER_MODEL_6_0 + atoi(optarg);
conf.first_vertex_and_base_instance_mode = conf.shader_model_max >= SHADER_MODEL_6_8 ?
DXIL_SPIRV_SYSVAL_TYPE_NATIVE : DXIL_SPIRV_SYSVAL_TYPE_ZERO;
break;
case 'x':
val_ver = DXIL_VALIDATOR_1_0 + atoi(optarg);

View file

@ -69,7 +69,7 @@ spirv_to_dxil(const uint32_t *words, size_t word_count,
dxil_get_nir_compiler_options(&nir_options, conf->shader_model_max, supported_bit_sizes, supported_bit_sizes);
// We will manually handle base_vertex when vertex_id and instance_id have
// have been already converted to zero-base.
nir_options.lower_base_vertex = !conf->zero_based_vertex_instance_id;
nir_options.lower_base_vertex = conf->first_vertex_and_base_instance_mode != DXIL_SPIRV_SYSVAL_TYPE_ZERO;
nir_shader *nir = spirv_to_nir(
words, word_count, (struct nir_spirv_specialization *)specializations,

View file

@ -141,6 +141,16 @@ enum dxil_spirv_yz_flip_mode {
#define DXIL_SPIRV_MAX_VIEWPORT 16
enum dxil_spirv_sysval_type {
// The sysval can be inlined in the shader as a constant zero
DXIL_SPIRV_SYSVAL_TYPE_ZERO,
// The sysval has a supported DXIL equivalent
DXIL_SPIRV_SYSVAL_TYPE_NATIVE,
// The sysval might be nonzero and has no DXIL equivalent, so it
// will need to be provided by the runtime_data constant buffer
DXIL_SPIRV_SYSVAL_TYPE_RUNTIME_DATA,
};
struct dxil_spirv_runtime_conf {
struct {
uint32_t register_space;
@ -152,11 +162,8 @@ struct dxil_spirv_runtime_conf {
uint32_t base_shader_register;
} push_constant_cbv;
// Set true if vertex and instance ids have already been converted to
// zero-based. Otherwise, runtime_data will be required to lower them.
bool zero_based_vertex_instance_id;
// Set true if workgroup base is known to be zero
bool zero_based_compute_workgroup_id;
enum dxil_spirv_sysval_type first_vertex_and_base_instance_mode;
enum dxil_spirv_sysval_type workgroup_id_mode;
struct {
// mode != DXIL_SPIRV_YZ_FLIP_NONE only valid on vertex/geometry stages.

View file

@ -238,8 +238,8 @@ dzn_pipeline_get_nir_shader(struct dzn_device *device,
.register_space = DZN_REGISTER_SPACE_PUSH_CONSTANT,
.base_shader_register = 0,
},
.zero_based_vertex_instance_id = false,
.zero_based_compute_workgroup_id = false,
.first_vertex_and_base_instance_mode = DXIL_SPIRV_SYSVAL_TYPE_RUNTIME_DATA,
.workgroup_id_mode = DXIL_SPIRV_SYSVAL_TYPE_RUNTIME_DATA,
.yz_flip = {
.mode = options->yz_flip_mode,
.y_mask = options->y_flip_mask,