wip: crocus/rusticl/elk/hasvk local changes before h264 cherry-pick

This commit is contained in:
elwrcl committed 2026-07-21 14:26:36 +03:00
1 parent 60a99fd3d3
commit 7e82b85d19
35 files changed
+1177 -191

No files matched your search

+4
View File
@@ -172,6 +172,10 @@ elk_get_compiler_config_value(const struct elk_compiler *compiler)
unsigned
elk_prog_data_size(mesa_shader_stage stage)
{
if (stage == MESA_SHADER_KERNEL) {
stage = MESA_SHADER_COMPUTE;
}
static const size_t stage_sizes[] = {
[MESA_SHADER_VERTEX] = sizeof(struct elk_vs_prog_data),
[MESA_SHADER_TESS_CTRL] = sizeof(struct elk_tcs_prog_data),
+1
View File
@@ -1053,6 +1053,7 @@ struct elk_cs_prog_data {
* surface indices the CS-specific surfaces
*/
uint32_t work_groups_start;
uint32_t global_start; /* IVB: BTI for full-GTT global surface */
/** @} */
} binding_table;
};
+69 -6
View File
@@ -5114,6 +5114,31 @@ fs_nir_emit_intrinsic(nir_to_elk_state &ntb,
case nir_intrinsic_load_global:
case nir_intrinsic_load_global_constant: {
if (devinfo->ver < 8) {
elk_fs_reg dest = get_nir_def(ntb, instr->def);
const unsigned bit_size = instr->def.bit_size;
elk_fs_reg srcs[SURFACE_LOGICAL_NUM_SRCS];
/* IVB: use dedicated full-GTT surface for global access */
const struct elk_cs_prog_data *cs_pd =
elk_cs_prog_data(ntb.s.prog_data);
srcs[SURFACE_LOGICAL_SRC_SURFACE] = elk_imm_ud(cs_pd->binding_table.global_start);
srcs[SURFACE_LOGICAL_SRC_ADDRESS] = get_nir_src(ntb, instr->src[0]);
srcs[SURFACE_LOGICAL_SRC_IMM_DIMS] = elk_imm_ud(1);
srcs[SURFACE_LOGICAL_SRC_ALLOW_SAMPLE_MASK] = elk_imm_ud(0);
dest.type = elk_reg_type_from_bit_size(bit_size, ELK_REGISTER_TYPE_UD);
if (bit_size == 32 && nir_intrinsic_align(instr) >= 4) {
srcs[SURFACE_LOGICAL_SRC_IMM_ARG] = elk_imm_ud(instr->num_components);
elk_fs_inst *inst = bld.emit(ELK_SHADER_OPCODE_UNTYPED_SURFACE_READ_LOGICAL, dest, srcs, SURFACE_LOGICAL_NUM_SRCS);
inst->size_written = instr->num_components * s.dispatch_width * 4;
} else {
srcs[SURFACE_LOGICAL_SRC_IMM_ARG] = elk_imm_ud(bit_size);
elk_fs_reg read_result = bld.vgrf(ELK_REGISTER_TYPE_UD);
bld.emit(ELK_SHADER_OPCODE_BYTE_SCATTERED_READ_LOGICAL, read_result, srcs, SURFACE_LOGICAL_NUM_SRCS);
bld.MOV(dest, subscript(read_result, dest.type, 0));
}
break;
}
assert(devinfo->ver >= 8);
assert(instr->def.bit_size <= 32);
@@ -5150,13 +5175,34 @@ fs_nir_emit_intrinsic(nir_to_elk_state &ntb,
}
case nir_intrinsic_store_global: {
if (devinfo->ver < 8) {
const unsigned bit_size = nir_src_bit_size(instr->src[0]);
elk_fs_reg srcs[SURFACE_LOGICAL_NUM_SRCS];
/* IVB: use dedicated full-GTT surface for global access */
const struct elk_cs_prog_data *cs_pd =
elk_cs_prog_data(ntb.s.prog_data);
srcs[SURFACE_LOGICAL_SRC_SURFACE] = elk_imm_ud(cs_pd->binding_table.global_start);
srcs[SURFACE_LOGICAL_SRC_ADDRESS] = get_nir_src(ntb, instr->src[1]);
srcs[SURFACE_LOGICAL_SRC_IMM_DIMS] = elk_imm_ud(1);
srcs[SURFACE_LOGICAL_SRC_ALLOW_SAMPLE_MASK] = elk_imm_ud(1);
elk_fs_reg data = get_nir_src(ntb, instr->src[0]);
data.type = elk_reg_type_from_bit_size(bit_size, ELK_REGISTER_TYPE_UD);
if (bit_size == 32 && nir_intrinsic_align(instr) >= 4) {
srcs[SURFACE_LOGICAL_SRC_DATA] = data;
srcs[SURFACE_LOGICAL_SRC_IMM_ARG] = elk_imm_ud(instr->num_components);
bld.emit(ELK_SHADER_OPCODE_UNTYPED_SURFACE_WRITE_LOGICAL, elk_fs_reg(), srcs, SURFACE_LOGICAL_NUM_SRCS);
} else {
srcs[SURFACE_LOGICAL_SRC_IMM_ARG] = elk_imm_ud(bit_size);
srcs[SURFACE_LOGICAL_SRC_DATA] = bld.vgrf(ELK_REGISTER_TYPE_UD);
bld.MOV(srcs[SURFACE_LOGICAL_SRC_DATA], data);
bld.emit(ELK_SHADER_OPCODE_BYTE_SCATTERED_WRITE_LOGICAL, elk_fs_reg(), srcs, SURFACE_LOGICAL_NUM_SRCS);
}
break;
}
assert(devinfo->ver >= 8);
assert(nir_src_bit_size(instr->src[0]) <= 32);
assert(nir_intrinsic_write_mask(instr) ==
(1u << instr->num_components) - 1);
assert(nir_intrinsic_align(instr) > 0);
elk_fs_reg srcs[A64_LOGICAL_NUM_SRCS];
srcs[A64_LOGICAL_ADDRESS] = get_nir_src(ntb, instr->src[1]);
srcs[A64_LOGICAL_ENABLE_HELPERS] =
@@ -5523,6 +5569,7 @@ fs_nir_emit_intrinsic(nir_to_elk_state &ntb,
srcs[SURFACE_LOGICAL_SRC_SURFACE] =
elk_imm_ud(GFX8_BTI_STATELESS_NON_COHERENT);
} else {
/* IVB: use dedicated full-GTT surface instead of stateless BTI 255 */
srcs[SURFACE_LOGICAL_SRC_SURFACE] = elk_imm_ud(ELK_BTI_STATELESS);
}
@@ -6241,6 +6288,7 @@ static void
fs_nir_emit_global_atomic(nir_to_elk_state &ntb, const fs_builder &bld,
nir_intrinsic_instr *instr)
{
const intel_device_info *devinfo = ntb.devinfo;
enum elk_lsc_opcode op = elk_lsc_aop_for_nir_intrinsic(instr);
int num_data = lsc_op_num_data_values(op);
@@ -6262,6 +6310,20 @@ fs_nir_emit_global_atomic(nir_to_elk_state &ntb, const fs_builder &bld,
data = tmp;
}
if (devinfo->ver < 8) {
elk_fs_reg srcs[SURFACE_LOGICAL_NUM_SRCS];
srcs[SURFACE_LOGICAL_SRC_SURFACE] = elk_imm_ud(ELK_BTI_STATELESS);
srcs[SURFACE_LOGICAL_SRC_ADDRESS] = addr;
srcs[SURFACE_LOGICAL_SRC_IMM_DIMS] = elk_imm_ud(1);
srcs[SURFACE_LOGICAL_SRC_ALLOW_SAMPLE_MASK] = elk_imm_ud(1);
if (num_data >= 1)
srcs[SURFACE_LOGICAL_SRC_DATA] = data;
srcs[SURFACE_LOGICAL_SRC_IMM_ARG] = elk_imm_ud(op);
bld.emit(ELK_SHADER_OPCODE_UNTYPED_ATOMIC_LOGICAL, dest, srcs, SURFACE_LOGICAL_NUM_SRCS);
return;
}
elk_fs_reg srcs[A64_LOGICAL_NUM_SRCS];
srcs[A64_LOGICAL_ADDRESS] = addr;
srcs[A64_LOGICAL_SRC] = data;
@@ -6853,6 +6915,7 @@ fs_nir_emit_instr(nir_to_elk_state &ntb, nir_instr *instr)
fs_nir_emit_fs_intrinsic(ntb, nir_instr_as_intrinsic(instr));
break;
case MESA_SHADER_COMPUTE:
case MESA_SHADER_KERNEL:
fs_nir_emit_cs_intrinsic(ntb, nir_instr_as_intrinsic(instr));
break;
default:
@@ -1199,8 +1199,7 @@ lower_surface_logical_send(const fs_builder &bld, elk_fs_inst *inst)
if (is_typed_access || is_stateless) {
fs_builder ubld = bld.exec_all().group(8, 0);
header = ubld.vgrf(ELK_REGISTER_TYPE_UD);
if (is_stateless) {
assert(!is_surface_access);
if (is_stateless && !is_surface_access) {
ubld.emit(ELK_SHADER_OPCODE_SCRATCH_HEADER, header);
} else {
ubld.MOV(header, elk_imm_d(0));
+47 -7
View File
@@ -766,9 +766,12 @@ elk_nir_optimize(nir_shader *nir, bool is_scalar,
OPT(nir_remove_dead_variables, nir_var_function_temp, NULL);
}
static unsigned
lower_bit_size_callback(const nir_instr *instr, UNUSED void *data)
static unsigned
lower_bit_size_callback(const nir_instr *instr, void *data)
{
const struct elk_compiler *compiler = data;
const struct intel_device_info *devinfo = compiler->devinfo;
switch (instr->type) {
case nir_instr_type_alu: {
nir_alu_instr *alu = nir_instr_as_alu(instr);
@@ -785,9 +788,19 @@ lower_bit_size_callback(const nir_instr *instr, UNUSED void *data)
default:
break;
}
if (alu->def.bit_size >= 32)
return 0;
if (alu->def.bit_size == 16 &&
devinfo->ver < 8 &&
nir_op_infos[alu->op].output_type == nir_type_float) {
/* Gen7 has no native FP16 ALU/register support at all (see the
* empty HF entry in gfx7_hw_3src_type[] / gfx7_hw_type[] in
* elk_reg_type.c) -- unlike >=Gfx8, it cannot represent a
* 16-bit float operand or result under ANY circumstance, not
* just when inputs are mixed-width. Lower unconditionally,
* regardless of the source bit sizes, or elk_reg_type_to_hw_type()
* will hit an unencodable HF register type and assert.
*/
return 32;
}
/* Note: nir_op_iabs and nir_op_ineg are not lowered here because the
* 8-bit ABS or NEG instruction should eventually get copy propagated
@@ -805,7 +818,7 @@ lower_bit_size_callback(const nir_instr *instr, UNUSED void *data)
case nir_op_ffract:
case nir_op_fround_even:
case nir_op_ftrunc:
return 32;
return alu->def.bit_size < 32 ? 32 : 0;
case nir_op_frcp:
case nir_op_frsq:
case nir_op_fsqrt:
@@ -814,7 +827,13 @@ lower_bit_size_callback(const nir_instr *instr, UNUSED void *data)
case nir_op_flog2:
case nir_op_fsin:
case nir_op_fcos:
return 32;
/* Same issue as the idiv/umod/fceil group above: these
* transcendental ops need >=32-bit precision on Gen7, but if
* the source is already >=32-bit, unconditionally returning
* 32 here trips the nir_lower_bit_size assert (src->bit_size
* < bit_size fails when equal or the source is 64-bit).
*/
return alu->def.bit_size < 32 ? 32 : 0;
case nir_op_isign:
UNREACHABLE("Should have been lowered by nir_opt_algebraic.");
default:
@@ -1310,8 +1329,26 @@ get_mem_access_size_align(nir_intrinsic_op intrin, uint8_t bytes,
bool offset_is_const, enum gl_access_qualifier access,
const void *cb_data)
{
const struct intel_device_info *devinfo = cb_data;
const uint32_t align = nir_combined_align(align_mul, align_offset);
/* IVB (Gen7, verx10=70) has no byte-scattered dataport message --
* elk_dp_byte_scattered_rw_desc() asserts verx10 >= 75 (Haswell+).
* This is a real HW limitation, not a missing BTI like the global
* stateless case. Never request a sub-dword access on this hardware;
* always request dword granularity. nir_lower_mem_access_bit_sizes
* turns the mismatch into a shift+extract on the load side, and an
* atomic iand/ior read-modify-write on the store side (both already
* generic in the pass, we just need to ask for them). */
if (devinfo->verx10 < 75 && (align < 4 || bytes < 4)) {
return (nir_mem_access_size_align) {
.bit_size = 32,
.num_components = 1,
.align = 4,
.shift = nir_mem_access_shift_method_scalar,
};
}
switch (intrin) {
case nir_intrinsic_load_ssbo:
case nir_intrinsic_load_shared:
@@ -1401,6 +1438,7 @@ elk_vectorize_lower_mem_access(nir_shader *nir,
OPT(nir_opt_load_store_vectorize, &options);
}
const struct intel_device_info *devinfo = compiler->devinfo;
nir_lower_mem_access_bit_sizes_options mem_access_options = {
.modes = nir_var_mem_ssbo |
nir_var_mem_constant |
@@ -1409,6 +1447,8 @@ elk_vectorize_lower_mem_access(nir_shader *nir,
nir_var_mem_global |
nir_var_mem_shared,
.callback = get_mem_access_size_align,
.cb_data = devinfo,
.may_lower_unaligned_stores_to_atomics = devinfo->verx10 < 75,
};
OPT(nir_lower_mem_access_bit_sizes, &mem_access_options);
+8 -2
View File
@@ -220,10 +220,16 @@ elk_reg_type_to_hw_type(const struct intel_device_info *devinfo,
}
if (file == ELK_IMMEDIATE_VALUE) {
assert(table[type].imm_type != (enum hw_imm_type)INVALID);
if (table[type].imm_type == (enum hw_imm_type)INVALID) {
fprintf(stderr, "elk_reg_type_to_hw_type: INVALID imm_type! type=%d\n", type);
assert(0);
}
return table[type].imm_type;
} else {
assert(table[type].reg_type != (enum hw_reg_type)INVALID);
if (table[type].reg_type == (enum hw_reg_type)INVALID) {
fprintf(stderr, "elk_reg_type_to_hw_type: INVALID reg_type! type=%d\n", type);
assert(0);
}
return table[type].reg_type;
}
}
Binary file not shown.
Binary file not shown.
+95 -4
View File
@@ -274,9 +274,62 @@ anv_reloc_list_append(struct anv_reloc_list *list,
return VK_SUCCESS;
}
/*-----------------------------------------------------------------------*
* Functions related to anv_batch
*-----------------------------------------------------------------------*/
/* Like anv_reloc_list_append(), but only copies/rebases the relocations
* whose offset falls at or after @skip_bytes -- i.e. the ones that belong
* to the suffix of @other starting at that byte, which is what
* anv_batch_emit_batch_suffix() actually copies into @batch. Relocations
* before @skip_bytes belong to a region we are deliberately NOT emitting
* and must not be added (their target offset would land outside what we
* copied, corrupting the batch).
*/
static VkResult
anv_reloc_list_append_range(struct anv_reloc_list *list,
const VkAllocationCallbacks *alloc,
struct anv_reloc_list *other,
uint32_t skip_bytes, uint32_t offset)
{
uint32_t n = 0;
for (uint32_t i = 0; i < other->num_relocs; i++) {
if (other->relocs[i].offset >= skip_bytes)
n++;
}
if (n == 0) {
/* Still need to propagate BO dependencies: shaders/state referenced
* only from the skipped prefix may not be otherwise declared as
* used by this command buffer submission if this is the very first
* time this pipeline's group is touched in it.
*/
anv_reloc_list_grow_deps(list, alloc, other->dep_words);
for (uint32_t w = 0; w < other->dep_words; w++)
list->deps[w] |= other->deps[w];
return VK_SUCCESS;
}
VkResult result = anv_reloc_list_grow(list, alloc, n);
if (result != VK_SUCCESS)
return result;
uint32_t j = list->num_relocs;
for (uint32_t i = 0; i < other->num_relocs; i++) {
if (other->relocs[i].offset < skip_bytes)
continue;
list->relocs[j] = other->relocs[i];
list->relocs[j].offset += offset - skip_bytes;
list->reloc_bos[j] = other->reloc_bos[i];
j++;
}
assert(j == list->num_relocs + n);
list->num_relocs = j;
anv_reloc_list_grow_deps(list, alloc, other->dep_words);
for (uint32_t w = 0; w < other->dep_words; w++)
list->deps[w] |= other->deps[w];
return VK_SUCCESS;
}
void *
anv_batch_emit_dwords(struct anv_batch *batch, int num_dwords)
@@ -340,7 +393,45 @@ anv_batch_emit_batch(struct anv_batch *batch, struct anv_batch *other)
batch->next += size;
}
/*-----------------------------------------------------------------------*
void
anv_batch_emit_batch_suffix(struct anv_batch *batch, struct anv_batch *other,
uint32_t skip_bytes)
{
uint32_t full_size = other->next - other->start;
assert(skip_bytes <= full_size);
assert(skip_bytes % 4 == 0);
uint32_t size = full_size - skip_bytes;
if (size == 0)
return;
assert(size % 4 == 0);
if (batch->next + size > batch->end) {
VkResult result = batch->extend_cb(batch, batch->user_data);
if (result != VK_SUCCESS) {
anv_batch_set_error(batch, result);
return;
}
}
assert(batch->next + size <= batch->end);
VG(VALGRIND_CHECK_MEM_IS_DEFINED(other->start + skip_bytes, size));
memcpy(batch->next, other->start + skip_bytes, size);
uint32_t offset = batch->next - batch->start;
VkResult result = anv_reloc_list_append_range(batch->relocs, batch->alloc,
other->relocs,
skip_bytes, offset);
if (result != VK_SUCCESS) {
anv_batch_set_error(batch, result);
return;
}
batch->next += size;
}
/*-----------------------------------------------------------------------
* Functions related to anv_batch_bo
*-----------------------------------------------------------------------*/
+1 -6
View File
@@ -569,17 +569,12 @@ add_aux_surface_if_supported(struct anv_device *device,
return VK_SUCCESS;
}
if (device->info->ver == 7) {
anv_perf_warn(VK_LOG_OBJS(&image->vk.base), "Implement gfx7 HiZ");
return VK_SUCCESS;
}
if (image->vk.mip_levels > 1) {
anv_perf_warn(VK_LOG_OBJS(&image->vk.base), "Enable multi-LOD HiZ");
return VK_SUCCESS;
}
if (device->info->ver == 8 && image->vk.samples > 1) {
if (device->info->ver <= 8 && image->vk.samples > 1) {
anv_perf_warn(VK_LOG_OBJS(&image->vk.base),
"Enable gfx8 multisampled HiZ");
return VK_SUCCESS;
+51
View File
@@ -1339,6 +1339,17 @@ struct anv_batch {
void *anv_batch_emit_dwords(struct anv_batch *batch, int num_dwords);
void anv_batch_emit_batch(struct anv_batch *batch, struct anv_batch *other);
/* Like anv_batch_emit_batch(), but only copies the suffix of @other
* starting at byte offset @skip_bytes (and only appends/rebases the
* relocations that fall within that suffix). Gen7-only: used to skip
* re-emitting a pipeline's VS-stage instruction group when it is
* byte-identical to what's already programmed for the previous bind
* (see cmd_buffer_flush_gfx_state).
*/
void anv_batch_emit_batch_suffix(struct anv_batch *batch,
struct anv_batch *other,
uint32_t skip_bytes);
struct anv_address anv_batch_address(struct anv_batch *batch, void *batch_location);
static inline void
@@ -2399,6 +2410,30 @@ struct anv_cmd_graphics_state {
struct anv_graphics_pipeline *pipeline;
/** Last emitted URB configuration (Gen7 stall optimization) */
struct intel_urb_config last_urb_cfg;
bool urb_cfg_valid;
/**
* Gen7 VS-stage instruction group cache. Tracks the VS/TCS/TES/GS
* shader binaries AND the effective URB config (see last_urb_cfg
* above) of the pipeline for which the group (URB + VS + HS + DS +
* GS, plus the PRM-mandated depth-stall PIPE_CONTROL before them) was
* last fully emitted into this command buffer, so a subsequent bind
* can skip re-emitting the whole group when both match the previous
* bind. Shader pointers alone are not sufficient -- URB layout also
* depends on l3_config. Always present (not #if-guarded) so this
* struct's layout doesn't depend on GFX_VER; only read/written by
* Gen7 code paths, inert everywhere else.
*/
struct anv_shader_bin *vs_stage_key[4];
bool vs_stage_key_valid;
/** True once a stall satisfying the PRM's VS-associated-3DSTATE rule
* has been emitted for the *current* draw's pipeline flush. Used to
* decide whether a later VS-descriptor/push-constant update still
* needs its own stall (see cmd_buffer_flush_gfx_state). */
bool vs_stage_stall_emitted;
VkRenderingFlags rendering_flags;
VkRect2D render_area;
uint32_t layer_count;
@@ -2790,6 +2825,22 @@ struct anv_pipeline {
struct anv_graphics_pipeline {
struct anv_pipeline base;
/* URB configuration computed at pipeline creation time.
* Used to skip redundant URB re-emission and PIPE_CONTROL stalls on Gen7.
*/
struct intel_urb_config urb_cfg;
/* Byte length, from the start of base.batch, of the VS-stage
* instruction group (3DSTATE_URB_* + 3DSTATE_VS + 3DSTATE_HS +
* 3DSTATE_DS + 3DSTATE_GS, plus the PRM-mandated depth-stall
* PIPE_CONTROL emitted just before them). Computed unconditionally in
* genX(graphics_pipeline_emit) so this struct's layout doesn't depend
* on GFX_VER; only meaningful/consumed on Gen7 (0 elsewhere, since the
* reordering that makes the group a contiguous prefix of base.batch
* only happens for GFX_VER <= 7).
*/
uint32_t vs_stage_batch_size;
/* Shaders */
struct anv_shader_bin * shaders[ANV_GRAPHICS_SHADER_STAGE_COUNT];
+80 -2
View File
@@ -3352,8 +3352,84 @@ genX(cmd_buffer_flush_gfx_state)(struct anv_cmd_buffer *cmd_buffer)
}
}
#if GFX_VER <= 7
/* Reset for this flush cycle; set true below the moment a stall
* covering the PRM's VS-associated-3DSTATE rule has actually been
* emitted, whichever path ends up doing it. */
cmd_buffer->state.gfx.vs_stage_stall_emitted = false;
#endif
if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_PIPELINE) {
#if GFX_VER <= 7
/* Skip re-emitting the VS-stage instruction group (URB + VS + HS +
* DS + GS, plus its PRM-mandated depth-stall PIPE_CONTROL, all kept
* contiguous at the front of the pipeline's static batch -- see
* genX(graphics_pipeline_emit)) when it is byte-identical to what's
* already programmed. This requires BOTH the same VS/TCS/TES/GS
* shader binaries AND the same effective URB config as the last
* pipeline for which we fully emitted the group -- shader pointers
* alone are not enough, since URB start/entry-count also depends on
* l3_config (see the urb_unchanged check below). Two different
* VkPipeline objects that share the same shaders and l3_config
* (e.g. VulkanMod's opaque vs. cutout terrain pipelines, which only
* differ in rasterizer cull mode) hit this path every switch.
*/
struct anv_cmd_graphics_state *gfx_state = &cmd_buffer->state.gfx;
struct anv_shader_bin *new_key[4] = {
pipeline->shaders[MESA_SHADER_VERTEX],
pipeline->shaders[MESA_SHADER_TESS_CTRL],
pipeline->shaders[MESA_SHADER_TESS_EVAL],
pipeline->shaders[MESA_SHADER_GEOMETRY],
};
/* Same shaders alone is NOT sufficient: the actual URB byte layout
* (VSURBStartingAddress / VSNumberofURBEntries) also depends on
* l3_config (e.g. render target/attachment count shifts L3
* partitioning -- see intel_get_urb_config()), so two pipelines
* with byte-identical VS/HS/DS/GS shaders can still need a
* different URB layout. Must check both.
*/
bool urb_unchanged = gfx_state->urb_cfg_valid;
if (urb_unchanged) {
for (int s = MESA_SHADER_VERTEX; s <= MESA_SHADER_GEOMETRY; s++) {
if (intel_urb_setup_changed(&gfx_state->last_urb_cfg,
&pipeline->urb_cfg, s)) {
urb_unchanged = false;
break;
}
}
}
bool vs_stage_unchanged =
gfx_state->vs_stage_key_valid &&
memcmp(gfx_state->vs_stage_key, new_key, sizeof(new_key)) == 0 &&
urb_unchanged;
vs_stage_unchanged = false; /* DIAGNOSTIC: force full emit, see script header */
if (vs_stage_unchanged) {
anv_batch_emit_batch_suffix(&cmd_buffer->batch, &pipeline->base.batch,
pipeline->vs_stage_batch_size);
/* We skipped the group -- no stall owed for URB/VS/HS/DS/GS
* themselves, but if descriptors/push-constants are ALSO dirty
* this flush cycle, 3DSTATE_CONSTANT_VS /
* 3DSTATE_BINDING_TABLE_POINTER_VS are still about to be emitted
* below and are covered by the SAME PRM rule -- so do NOT mark
* vs_stage_stall_emitted here; let the check below decide.
*/
} else {
anv_batch_emit_batch(&cmd_buffer->batch, &pipeline->base.batch);
memcpy(gfx_state->vs_stage_key, new_key, sizeof(new_key));
gfx_state->vs_stage_key_valid = true;
gfx_state->last_urb_cfg = pipeline->urb_cfg;
gfx_state->urb_cfg_valid = true;
/* Full emit -- the PIPE_CONTROL baked into the pipeline's static
* batch (by emit_urb_setup) was actually sent, covering the
* whole PRM-mandated group for this flush cycle. */
gfx_state->vs_stage_stall_emitted = true;
}
#else
anv_batch_emit_batch(&cmd_buffer->batch, &pipeline->base.batch);
#endif
/* If the pipeline changed, we may need to re-allocate push constant
* space in the URB.
@@ -3362,8 +3438,9 @@ genX(cmd_buffer_flush_gfx_state)(struct anv_cmd_buffer *cmd_buffer)
}
#if GFX_VER <= 7
if (cmd_buffer->state.descriptors_dirty & VK_SHADER_STAGE_VERTEX_BIT ||
cmd_buffer->state.push_constants_dirty & VK_SHADER_STAGE_VERTEX_BIT) {
if (!cmd_buffer->state.gfx.vs_stage_stall_emitted &&
(cmd_buffer->state.descriptors_dirty & VK_SHADER_STAGE_VERTEX_BIT ||
cmd_buffer->state.push_constants_dirty & VK_SHADER_STAGE_VERTEX_BIT)) {
/* From the IVB PRM Vol. 2, Part 1, Section 3.2.1:
*
* "A PIPE_CONTROL with Post-Sync Operation set to 1h and a depth
@@ -3380,6 +3457,7 @@ genX(cmd_buffer_flush_gfx_state)(struct anv_cmd_buffer *cmd_buffer)
pc.Address = cmd_buffer->device->workaround_address;
anv_debug_dump_pc(pc);
}
cmd_buffer->state.gfx.vs_stage_stall_emitted = true;
}
#endif
+34
View File
@@ -325,6 +325,28 @@ emit_urb_setup(struct anv_graphics_pipeline *pipeline)
entry_size[i] = prog_data ? prog_data->urb_entry_size : 1;
}
#if GFX_VER <= 7
/* Compute and cache the *actual* URB config -- not just the shaders'
* requested entry sizes, but the real per-stage start offsets and
* entry counts, which also depend on l3_config (e.g. attachment/RT
* count can shift L3 partitioning). This is the correct, complete key
* for cmd_buffer_flush_gfx_state() to decide whether the VS-stage
* instruction group can be skipped on a later bind: two pipelines
* with byte-identical VS/HS/DS/GS shaders can still require a
* different URB layout if their l3_config differs -- comparing shader
* pointers alone is not sufficient.
*/
pipeline->urb_cfg = (struct intel_urb_config) {
.size = { entry_size[0], entry_size[1], entry_size[2], entry_size[3] },
};
bool urb_constrained;
intel_get_urb_config(pipeline->base.device->info, pipeline->base.l3_config,
pipeline->active_stages &
VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
pipeline->active_stages & VK_SHADER_STAGE_GEOMETRY_BIT,
&pipeline->urb_cfg, &urb_constrained);
#endif
genX(emit_urb_setup)(pipeline->base.device, &pipeline->base.batch,
pipeline->base.l3_config,
pipeline->active_stages, entry_size);
@@ -1827,6 +1849,16 @@ genX(graphics_pipeline_emit)(struct anv_graphics_pipeline *pipeline,
{
emit_urb_setup(pipeline);
/* DIAGNOSTIC v2: VS/HS/DS/GS reordering reverted -- back to vanilla
* emission position (after vertex_input, below). vs_stage_batch_size
* is set to 0 here since it's meaningless with the group no longer
* contiguous with URB; this is fine because diagnostic v1 already
* force-disabled the skip path that would have used it.
*/
#if GFX_VER <= 7
pipeline->vs_stage_batch_size = 0;
#endif
assert(state->rs != NULL);
emit_rs_state(pipeline, state->ia, state->rs, state->ms, state->rp);
emit_ms_state(pipeline, state->ms);
@@ -1856,6 +1888,8 @@ genX(graphics_pipeline_emit)(struct anv_graphics_pipeline *pipeline,
emit_vertex_input(pipeline, state->vi);
/* DIAGNOSTIC v2: always emit here (both Gen7 and Gen8+), matching
* vanilla hasvk's original position exactly. */
emit_3dstate_vs(pipeline);
emit_3dstate_hs_te_ds(pipeline, state->ts);
emit_3dstate_gs(pipeline, state->rs);
+6 -2
View File
@@ -232,7 +232,8 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
*/
if ((cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_PIPELINE) ||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_IA_PRIMITIVE_TOPOLOGY) ||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_CB_COLOR_WRITE_ENABLES)) {
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_CB_COLOR_WRITE_ENABLES) ||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_LINE_STIPPLE)) {
VkPolygonMode dynamic_raster_mode =
genX(raster_polygon_mode)(cmd_buffer->state.gfx.pipeline,
dyn->ia.primitive_topology);
@@ -243,10 +244,13 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
.ThreadDispatchEnable = anv_pipeline_has_stage(pipeline, MESA_SHADER_FRAGMENT) &&
(pipeline->force_fragment_thread_dispatch ||
!anv_cmd_buffer_all_color_write_masked(cmd_buffer)),
!anv_cmd_buffer_all_color_write_masked(cmd_buffer)),
.MultisampleRasterizationMode =
genX(ms_rasterization_mode)(pipeline,
dynamic_raster_mode),
#if GFX_VERx10 == 70
.LineStippleEnable = dyn->rs.line.stipple.enable,
#endif
};
GENX(3DSTATE_WM_pack)(NULL, dwords, &wm);