2024-07-12 13:52:46 -07:00
|
|
|
/*
|
|
|
|
|
* Copyright © 2010 Intel Corporation
|
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "brw_cfg.h"
|
|
|
|
|
#include "brw_eu.h"
|
2025-02-05 14:25:15 -08:00
|
|
|
#include "brw_shader.h"
|
2024-12-06 16:17:46 -08:00
|
|
|
#include "brw_generator.h"
|
2024-07-12 13:52:46 -07:00
|
|
|
#include "brw_nir.h"
|
|
|
|
|
#include "brw_private.h"
|
|
|
|
|
#include "dev/intel_debug.h"
|
|
|
|
|
#include "util/macros.h"
|
|
|
|
|
|
2024-07-12 17:42:48 -07:00
|
|
|
static void
|
2024-12-07 10:25:45 -08:00
|
|
|
brw_assign_tes_urb_setup(brw_shader &s)
|
2024-07-12 17:42:48 -07:00
|
|
|
{
|
|
|
|
|
assert(s.stage == MESA_SHADER_TESS_EVAL);
|
|
|
|
|
|
|
|
|
|
struct brw_vue_prog_data *vue_prog_data = brw_vue_prog_data(s.prog_data);
|
|
|
|
|
|
|
|
|
|
s.first_non_payload_grf += 8 * vue_prog_data->urb_read_length;
|
|
|
|
|
|
|
|
|
|
/* Rewrite all ATTR file references to HW_REGs. */
|
2024-12-07 00:23:07 -08:00
|
|
|
foreach_block_and_inst(block, brw_inst, inst, s.cfg) {
|
2024-07-12 17:42:48 -07:00
|
|
|
s.convert_attr_sources_to_hw_regs(inst);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-12 14:20:57 -07:00
|
|
|
static bool
|
2024-12-07 10:25:45 -08:00
|
|
|
run_tes(brw_shader &s)
|
2024-07-12 14:20:57 -07:00
|
|
|
{
|
|
|
|
|
assert(s.stage == MESA_SHADER_TESS_EVAL);
|
|
|
|
|
|
2024-12-06 22:13:36 -08:00
|
|
|
s.payload_ = new brw_tes_thread_payload(s);
|
2024-07-12 14:20:57 -07:00
|
|
|
|
2024-12-07 09:36:03 -08:00
|
|
|
brw_from_nir(&s);
|
2024-07-12 14:20:57 -07:00
|
|
|
|
|
|
|
|
if (s.failed)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
s.emit_urb_writes();
|
|
|
|
|
|
2024-07-12 17:08:46 -07:00
|
|
|
brw_calculate_cfg(s);
|
2024-07-12 14:20:57 -07:00
|
|
|
|
2024-12-06 11:37:57 -08:00
|
|
|
brw_optimize(s);
|
2024-07-12 14:20:57 -07:00
|
|
|
|
|
|
|
|
s.assign_curb_setup();
|
2024-07-12 17:42:48 -07:00
|
|
|
brw_assign_tes_urb_setup(s);
|
2024-07-12 14:20:57 -07:00
|
|
|
|
2024-12-06 11:37:57 -08:00
|
|
|
brw_lower_3src_null_dest(s);
|
|
|
|
|
brw_workaround_memory_fence_before_eot(s);
|
|
|
|
|
brw_workaround_emit_dummy_mov_instruction(s);
|
2024-07-12 14:20:57 -07:00
|
|
|
|
2024-07-12 16:55:33 -07:00
|
|
|
brw_allocate_registers(s, true /* allow_spilling */);
|
2024-07-12 14:20:57 -07:00
|
|
|
|
2024-12-06 11:37:57 -08:00
|
|
|
brw_workaround_source_arf_before_eot(s);
|
2024-10-19 12:53:21 +03:00
|
|
|
|
2024-07-12 14:20:57 -07:00
|
|
|
return !s.failed;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-12 13:52:46 -07:00
|
|
|
const unsigned *
|
|
|
|
|
brw_compile_tes(const struct brw_compiler *compiler,
|
|
|
|
|
brw_compile_tes_params *params)
|
|
|
|
|
{
|
|
|
|
|
const struct intel_device_info *devinfo = compiler->devinfo;
|
|
|
|
|
nir_shader *nir = params->base.nir;
|
|
|
|
|
const struct brw_tes_prog_key *key = params->key;
|
|
|
|
|
const struct intel_vue_map *input_vue_map = params->input_vue_map;
|
|
|
|
|
struct brw_tes_prog_data *prog_data = params->prog_data;
|
2025-01-22 13:06:33 -08:00
|
|
|
const unsigned dispatch_width = brw_geometry_stage_dispatch_width(compiler->devinfo);
|
2024-07-12 13:52:46 -07:00
|
|
|
|
|
|
|
|
const bool debug_enabled = brw_should_print_shader(nir, DEBUG_TES);
|
|
|
|
|
|
2025-02-12 12:42:08 +02:00
|
|
|
brw_prog_data_init(&prog_data->base.base, ¶ms->base);
|
2024-07-12 13:52:46 -07:00
|
|
|
|
|
|
|
|
nir->info.inputs_read = key->inputs_read;
|
|
|
|
|
nir->info.patch_inputs_read = key->patch_inputs_read;
|
|
|
|
|
|
2025-01-22 13:06:33 -08:00
|
|
|
brw_nir_apply_key(nir, compiler, &key->base, dispatch_width);
|
2024-07-12 13:52:46 -07:00
|
|
|
brw_nir_lower_tes_inputs(nir, input_vue_map);
|
|
|
|
|
brw_nir_lower_vue_outputs(nir);
|
|
|
|
|
brw_postprocess_nir(nir, compiler, debug_enabled,
|
|
|
|
|
key->base.robust_flags);
|
|
|
|
|
|
|
|
|
|
brw_compute_vue_map(devinfo, &prog_data->base.vue_map,
|
|
|
|
|
nir->info.outputs_written,
|
|
|
|
|
nir->info.separate_shader, 1);
|
|
|
|
|
|
|
|
|
|
unsigned output_size_bytes = prog_data->base.vue_map.num_slots * 4 * 4;
|
|
|
|
|
|
|
|
|
|
assert(output_size_bytes >= 1);
|
|
|
|
|
if (output_size_bytes > GFX7_MAX_DS_URB_ENTRY_SIZE_BYTES) {
|
|
|
|
|
params->base.error_str = ralloc_strdup(params->base.mem_ctx,
|
|
|
|
|
"DS outputs exceed maximum size");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prog_data->base.clip_distance_mask =
|
|
|
|
|
((1 << nir->info.clip_distance_array_size) - 1);
|
|
|
|
|
prog_data->base.cull_distance_mask =
|
|
|
|
|
((1 << nir->info.cull_distance_array_size) - 1) <<
|
|
|
|
|
nir->info.clip_distance_array_size;
|
|
|
|
|
|
|
|
|
|
prog_data->include_primitive_id =
|
|
|
|
|
BITSET_TEST(nir->info.system_values_read, SYSTEM_VALUE_PRIMITIVE_ID);
|
|
|
|
|
|
|
|
|
|
/* URB entry sizes are stored as a multiple of 64 bytes. */
|
|
|
|
|
prog_data->base.urb_entry_size = ALIGN(output_size_bytes, 64) / 64;
|
|
|
|
|
|
|
|
|
|
prog_data->base.urb_read_length = 0;
|
|
|
|
|
|
|
|
|
|
STATIC_ASSERT(INTEL_TESS_PARTITIONING_INTEGER == TESS_SPACING_EQUAL - 1);
|
|
|
|
|
STATIC_ASSERT(INTEL_TESS_PARTITIONING_ODD_FRACTIONAL ==
|
|
|
|
|
TESS_SPACING_FRACTIONAL_ODD - 1);
|
|
|
|
|
STATIC_ASSERT(INTEL_TESS_PARTITIONING_EVEN_FRACTIONAL ==
|
|
|
|
|
TESS_SPACING_FRACTIONAL_EVEN - 1);
|
|
|
|
|
|
|
|
|
|
prog_data->partitioning =
|
|
|
|
|
(enum intel_tess_partitioning) (nir->info.tess.spacing - 1);
|
|
|
|
|
|
|
|
|
|
switch (nir->info.tess._primitive_mode) {
|
|
|
|
|
case TESS_PRIMITIVE_QUADS:
|
|
|
|
|
prog_data->domain = INTEL_TESS_DOMAIN_QUAD;
|
|
|
|
|
break;
|
|
|
|
|
case TESS_PRIMITIVE_TRIANGLES:
|
|
|
|
|
prog_data->domain = INTEL_TESS_DOMAIN_TRI;
|
|
|
|
|
break;
|
|
|
|
|
case TESS_PRIMITIVE_ISOLINES:
|
|
|
|
|
prog_data->domain = INTEL_TESS_DOMAIN_ISOLINE;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
unreachable("invalid domain shader primitive mode");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nir->info.tess.point_mode) {
|
|
|
|
|
prog_data->output_topology = INTEL_TESS_OUTPUT_TOPOLOGY_POINT;
|
|
|
|
|
} else if (nir->info.tess._primitive_mode == TESS_PRIMITIVE_ISOLINES) {
|
|
|
|
|
prog_data->output_topology = INTEL_TESS_OUTPUT_TOPOLOGY_LINE;
|
|
|
|
|
} else {
|
|
|
|
|
/* Hardware winding order is backwards from OpenGL */
|
|
|
|
|
prog_data->output_topology =
|
|
|
|
|
nir->info.tess.ccw ? INTEL_TESS_OUTPUT_TOPOLOGY_TRI_CW
|
|
|
|
|
: INTEL_TESS_OUTPUT_TOPOLOGY_TRI_CCW;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (unlikely(debug_enabled)) {
|
|
|
|
|
fprintf(stderr, "TES Input ");
|
|
|
|
|
brw_print_vue_map(stderr, input_vue_map, MESA_SHADER_TESS_EVAL);
|
|
|
|
|
fprintf(stderr, "TES Output ");
|
|
|
|
|
brw_print_vue_map(stderr, &prog_data->base.vue_map,
|
|
|
|
|
MESA_SHADER_TESS_EVAL);
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-07 10:25:45 -08:00
|
|
|
brw_shader v(compiler, ¶ms->base, &key->base,
|
|
|
|
|
&prog_data->base.base, nir, dispatch_width,
|
|
|
|
|
params->base.stats != NULL, debug_enabled);
|
2024-07-12 14:20:57 -07:00
|
|
|
if (!run_tes(v)) {
|
2024-07-12 13:52:46 -07:00
|
|
|
params->base.error_str =
|
|
|
|
|
ralloc_strdup(params->base.mem_ctx, v.fail_msg);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(v.payload().num_regs % reg_unit(devinfo) == 0);
|
|
|
|
|
prog_data->base.base.dispatch_grf_start_reg = v.payload().num_regs / reg_unit(devinfo);
|
2024-09-18 14:32:58 -07:00
|
|
|
prog_data->base.base.grf_used = v.grf_used;
|
2024-07-12 13:52:46 -07:00
|
|
|
prog_data->base.dispatch_mode = INTEL_DISPATCH_MODE_SIMD8;
|
|
|
|
|
|
2024-12-06 16:33:35 -08:00
|
|
|
brw_generator g(compiler, ¶ms->base,
|
2024-07-12 13:52:46 -07:00
|
|
|
&prog_data->base.base, MESA_SHADER_TESS_EVAL);
|
|
|
|
|
if (unlikely(debug_enabled)) {
|
|
|
|
|
g.enable_debug(ralloc_asprintf(params->base.mem_ctx,
|
|
|
|
|
"%s tessellation evaluation shader %s",
|
|
|
|
|
nir->info.label ? nir->info.label
|
|
|
|
|
: "unnamed",
|
|
|
|
|
nir->info.name));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g.generate_code(v.cfg, dispatch_width, v.shader_stats,
|
|
|
|
|
v.performance_analysis.require(), params->base.stats);
|
|
|
|
|
|
|
|
|
|
g.add_const_data(nir->constant_data, nir->constant_data_size);
|
|
|
|
|
|
|
|
|
|
return g.get_assembly();
|
|
|
|
|
}
|