spirv_to_dxil: Add support for non-zero vertex and instance indices

Since DXIL does not have a way to get the base/first vertex and base
instance as well as using a zero-based vertex index, these values need
to be passed in via a constant buffer.

Reviewed-by: Jesse Natalie <jenatali@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12707>
This commit is contained in:
Enrico Galli 2021-09-02 13:22:57 -07:00 committed by Marge Bot
parent 49ef896a5e
commit 398d591b65
2 changed files with 43 additions and 15 deletions

View file

@ -45,10 +45,14 @@ shared_var_info(const struct glsl_type* type, unsigned* size, unsigned* align)
static nir_variable *
add_runtime_data_var(nir_shader *nir, unsigned desc_set, unsigned binding)
{
const struct glsl_type *array_type = glsl_array_type(
glsl_uint_type(),
sizeof(struct dxil_spirv_compute_runtime_data) / sizeof(unsigned),
sizeof(unsigned));
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,
@ -89,6 +93,16 @@ lower_shader_system_values(struct nir_builder *builder, nir_instr *instr,
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;
default:
return false;
}
@ -164,8 +178,9 @@ spirv_to_dxil(const uint32_t *words, size_t word_count,
glsl_type_singleton_init_or_ref();
struct nir_shader_compiler_options nir_options = *dxil_get_nir_compiler_options();
// We will manually handle base_vertex
nir_options.lower_base_vertex = false;
// 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_shader *nir = spirv_to_nir(
words, word_count, (struct nir_spirv_specialization *)specializations,
@ -181,15 +196,16 @@ spirv_to_dxil(const uint32_t *words, size_t word_count,
NIR_PASS_V(nir, nir_lower_system_values);
// vertex_id and instance_id should have already been transformed to base
// zero before spirv_to_dxil was called. Also, WebGPU does not support
// 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));
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));
}
bool requires_runtime_data = false;
NIR_PASS(requires_runtime_data, nir,

View file

@ -90,11 +90,23 @@ struct dxil_spirv_compute_runtime_data {
uint32_t group_count_z;
};
/* This struct describes the layout of data expected in the CB bound to
* runtime_data_cbv during vertex stages */
struct dxil_spirv_vertex_runtime_data {
uint32_t first_vertex;
uint32_t base_instance;
bool is_indexed_draw;
};
struct dxil_spirv_runtime_conf {
struct {
uint32_t register_space;
uint32_t base_shader_register;
} runtime_data_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;
};
/**