diff --git a/src/microsoft/compiler/dxil_signature.c b/src/microsoft/compiler/dxil_signature.c index 0f042e57bc8..e10d1c4eb68 100644 --- a/src/microsoft/compiler/dxil_signature.c +++ b/src/microsoft/compiler/dxil_signature.c @@ -97,7 +97,7 @@ in_sysvalue_name(nir_variable *var) * to the semantic name string. Then these strings are dumped into the stream. */ static unsigned -get_additional_semantic_info(nir_variable *var, struct semantic_info *info, +get_additional_semantic_info(nir_shader *s, nir_variable *var, struct semantic_info *info, unsigned next_row, bool is_gs_shader) { const struct glsl_type *type = var->type; @@ -113,6 +113,24 @@ get_additional_semantic_info(nir_variable *var, struct semantic_info *info, info->start_row = info->index; } else if (is_depth || (info->kind == DXIL_SEM_PRIMITIVE_ID && is_gs_shader)) { info->start_row = -1; + } else if (var->data.compact) { + if (var->data.location_frac) { + info->start_row = next_row - 1; + } else { + info->start_row = next_row; + next_row++; + } + + assert(glsl_type_is_array(type) && info->kind == DXIL_SEM_CLIP_DISTANCE); + unsigned num_floats = glsl_get_aoa_size(type); + unsigned start_offset = (var->data.location - VARYING_SLOT_CLIP_DIST0) * 4 + + var->data.location_frac; + + if (start_offset >= s->info.clip_distance_array_size) { + info->kind = DXIL_SEM_CULL_DISTANCE; + snprintf(info->name, 64, "SV_CullDistance"); + } + info->cols = num_floats; } else { info->start_row = next_row; if (glsl_type_is_array(type) && is_gs_shader) @@ -126,9 +144,11 @@ get_additional_semantic_info(nir_variable *var, struct semantic_info *info, next_row += info->rows; } info->start_col = (uint8_t)var->data.location_frac; - if (glsl_type_is_array(type)) - type = glsl_get_array_element(type); - info->cols = (uint8_t)glsl_get_components(type); + if (!info->cols) { + if (glsl_type_is_array(type)) + type = glsl_get_array_element(type); + info->cols = (uint8_t)glsl_get_components(type); + } return next_row; } @@ -446,7 +466,7 @@ get_input_signature_group(struct dxil_module *mod, const struct dxil_mdnode **in struct semantic_info semantic = {0}; get_semantics(var, &semantic); mod->inputs[num_inputs].sysvalue = semantic.sysvalue_name; - *row_iter = get_additional_semantic_info(var, &semantic, *row_iter, is_gs_shader); + *row_iter = get_additional_semantic_info(s, var, &semantic, *row_iter, is_gs_shader); mod->inputs[num_inputs].name = ralloc_strdup(mod->ralloc_ctx, semantic.name); @@ -531,7 +551,7 @@ get_output_signature(struct dxil_module *mod, nir_shader *s) get_semantic_name(var, &semantic, var->type); mod->outputs[num_outputs].sysvalue = out_sysvalue_name(var); } - next_row = get_additional_semantic_info(var, &semantic, next_row, false); + next_row = get_additional_semantic_info(s, var, &semantic, next_row, false); mod->info.has_out_position |= semantic.kind== DXIL_SEM_POSITION; mod->info.has_out_depth |= semantic.kind == DXIL_SEM_DEPTH; diff --git a/src/microsoft/compiler/nir_to_dxil.c b/src/microsoft/compiler/nir_to_dxil.c index 37398c0c4d8..1c50a5d0c61 100644 --- a/src/microsoft/compiler/nir_to_dxil.c +++ b/src/microsoft/compiler/nir_to_dxil.c @@ -2448,6 +2448,8 @@ emit_store_output(struct ntd_context *ctx, nir_intrinsic_instr *intr, nir_variable *output) { nir_alu_type out_type = nir_get_nir_type_for_glsl_base_type(glsl_get_base_type(output->type)); + if (output->data.compact) + out_type = nir_type_float; enum overload_type overload = get_overload(out_type, 32); const struct dxil_func *func = dxil_get_function(&ctx->mod, "dx.op.storeOutput", overload); @@ -2459,15 +2461,26 @@ emit_store_output(struct ntd_context *ctx, nir_intrinsic_instr *intr, const struct dxil_value *row = dxil_module_get_int32_const(&ctx->mod, 0); bool success = true; - uint32_t writemask = nir_intrinsic_write_mask(intr); - for (unsigned i = 0; i < nir_src_num_components(intr->src[1]) && success; ++i) { - if (writemask & (1 << i)) { - const struct dxil_value *col = dxil_module_get_int8_const(&ctx->mod, i); - const struct dxil_value *value = get_src(ctx, &intr->src[1], i, out_type); - const struct dxil_value *args[] = { - opcode, output_id, row, col, value - }; - success &= dxil_emit_call_void(&ctx->mod, func, args, ARRAY_SIZE(args)); + if (output->data.compact) { + nir_deref_instr *array_deref = nir_instr_as_deref(intr->src[0].ssa->parent_instr); + unsigned array_index = nir_src_as_uint(array_deref->arr.index); + const struct dxil_value *col = dxil_module_get_int8_const(&ctx->mod, array_index); + const struct dxil_value *value = get_src(ctx, &intr->src[1], 0, out_type); + const struct dxil_value *args[] = { + opcode, output_id, row, col, value + }; + success = dxil_emit_call_void(&ctx->mod, func, args, ARRAY_SIZE(args)); + } else { + uint32_t writemask = nir_intrinsic_write_mask(intr); + for (unsigned i = 0; i < nir_src_num_components(intr->src[1]) && success; ++i) { + if (writemask & (1 << i)) { + const struct dxil_value *col = dxil_module_get_int8_const(&ctx->mod, i); + const struct dxil_value *value = get_src(ctx, &intr->src[1], i, out_type); + const struct dxil_value *args[] = { + opcode, output_id, row, col, value + }; + success &= dxil_emit_call_void(&ctx->mod, func, args, ARRAY_SIZE(args)); + } } } return success; @@ -2529,6 +2542,49 @@ emit_load_input_array(struct ntd_context *ctx, nir_intrinsic_instr *intr, nir_va return true; } +static bool +emit_load_compact_input_array(struct ntd_context *ctx, nir_intrinsic_instr *intr, nir_variable *var, nir_deref_instr *deref) +{ + assert(var); + const struct dxil_value *opcode = dxil_module_get_int32_const(&ctx->mod, DXIL_INTR_LOAD_INPUT); + const struct dxil_value *input_id = dxil_module_get_int32_const(&ctx->mod, var->data.driver_location); + const struct dxil_value *row = dxil_module_get_int32_const(&ctx->mod, 0); + const struct dxil_value *vertex_id; + + nir_src *col = &deref->arr.index; + nir_src_is_const(*col); + + if (ctx->mod.shader_kind == DXIL_GEOMETRY_SHADER) { + nir_deref_instr *deref_parent = nir_deref_instr_parent(deref); + assert(deref_parent->deref_type == nir_deref_type_array); + + vertex_id = get_src(ctx, &deref_parent->arr.index, 0, nir_type_int); + } else { + const struct dxil_type *int32_type = dxil_module_get_int_type(&ctx->mod, 32); + vertex_id = dxil_module_get_undef(&ctx->mod, int32_type); + } + + nir_alu_type out_type = nir_type_float; + enum overload_type overload = get_overload(out_type, 32); + + const struct dxil_func *func = dxil_get_function(&ctx->mod, "dx.op.loadInput", overload); + + if (!func) + return false; + + const struct dxil_value *comp = dxil_module_get_int8_const(&ctx->mod, nir_src_as_int(*col)); + + const struct dxil_value *args[] = { + opcode, input_id, row, comp, vertex_id + }; + + const struct dxil_value *retval = dxil_emit_call(&ctx->mod, func, args, ARRAY_SIZE(args)); + if (!retval) + return false; + store_dest(ctx, &intr->dest, 0, retval, out_type); + return true; +} + static bool emit_load_input_interpolated(struct ntd_context *ctx, nir_intrinsic_instr *intr, nir_variable *var) { @@ -2706,8 +2762,12 @@ emit_load_deref(struct ntd_context *ctx, nir_intrinsic_instr *intr) switch (var->data.mode) { case nir_var_shader_in: - if (glsl_type_is_array(var->type)) - return emit_load_input_array(ctx, intr, var, &deref->arr.index); + if (glsl_type_is_array(var->type)) { + if (var->data.compact) + return emit_load_compact_input_array(ctx, intr, var, deref); + else + return emit_load_input_array(ctx, intr, var, &deref->arr.index); + } return emit_load_input(ctx, intr, var); default: