diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c index 8c3cf4d2610..fb451354163 100644 --- a/src/freedreno/ir3/ir3_compiler_nir.c +++ b/src/freedreno/ir3/ir3_compiler_nir.c @@ -5170,6 +5170,9 @@ setup_input(struct ir3_context *ctx, nir_intrinsic_instr *intr) unsigned idx = (n * 4) + i + frac; ctx->last_dst[i] = ctx->inputs[idx]; } + + if (slot >= VERT_ATTRIB_GENERIC0) + so->attr_in = MAX2(so->attr_in, slot - VERT_ATTRIB_GENERIC0 + 1); } } diff --git a/src/freedreno/ir3/ir3_shader.h b/src/freedreno/ir3/ir3_shader.h index ec04ae8170b..da72367643d 100644 --- a/src/freedreno/ir3/ir3_shader.h +++ b/src/freedreno/ir3/ir3_shader.h @@ -825,6 +825,11 @@ struct ir3_shader_variant { */ unsigned varying_in; + /* For vertex shaders, the number of generic attribute slots (i.e. 1 plus the + * max VERT_ATTRIB_GENERICn). + */ + unsigned attr_in; + /* Remapping table to map Image and SSBO to hw state: */ struct ir3_ibo_mapping image_mapping; diff --git a/src/freedreno/vulkan/tu_cmd_buffer.cc b/src/freedreno/vulkan/tu_cmd_buffer.cc index b11fb17134a..2949c06399b 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.cc +++ b/src/freedreno/vulkan/tu_cmd_buffer.cc @@ -5329,7 +5329,10 @@ TU_GENX(tu_EndCommandBuffer); static void tu_bind_vs(struct tu_cmd_buffer *cmd, struct tu_shader *vs) { - cmd->state.shaders[MESA_SHADER_VERTEX] = vs; + if (cmd->state.shaders[MESA_SHADER_VERTEX] != vs) { + cmd->state.shaders[MESA_SHADER_VERTEX] = vs; + cmd->state.dirty |= TU_CMD_DIRTY_VS; + } } static void diff --git a/src/freedreno/vulkan/tu_cmd_buffer.h b/src/freedreno/vulkan/tu_cmd_buffer.h index e8a4ed000ec..e16092edefb 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.h +++ b/src/freedreno/vulkan/tu_cmd_buffer.h @@ -81,6 +81,7 @@ enum tu_cmd_dirty_bits TU_CMD_DIRTY_SHADING_RATE = BIT(15), TU_CMD_DIRTY_DISABLE_FS = BIT(16), TU_CMD_DIRTY_TCS = BIT(17), + TU_CMD_DIRTY_VS = BIT(18), /* all draw states were disabled and need to be re-enabled: */ TU_CMD_DIRTY_DRAW_STATE = BIT(18) diff --git a/src/freedreno/vulkan/tu_pipeline.cc b/src/freedreno/vulkan/tu_pipeline.cc index 7114b4af1f1..a52a3eeeeac 100644 --- a/src/freedreno/vulkan/tu_pipeline.cc +++ b/src/freedreno/vulkan/tu_pipeline.cc @@ -2451,17 +2451,18 @@ static const enum mesa_vk_dynamic_graphics_state tu_vertex_input_state[] = { template static unsigned tu6_vertex_input_size(struct tu_device *dev, - const struct vk_vertex_input_state *vi) + const struct vk_vertex_input_state *vi, + unsigned attr_count) { - return 1 + 2 * util_last_bit(vi->attributes_valid); + return 1 + 2 * attr_count; } template static void tu6_emit_vertex_input(struct tu_cs *cs, - const struct vk_vertex_input_state *vi) + const struct vk_vertex_input_state *vi, + unsigned attr_count) { - unsigned attr_count = util_last_bit(vi->attributes_valid); if (attr_count != 0) tu_cs_emit_pkt4(cs, REG_A6XX_VFD_FETCH_INSTR_INSTR(0), attr_count * 2); @@ -3924,8 +3925,10 @@ tu_pipeline_builder_emit_state(struct tu_pipeline_builder *builder, } #define DRAW_STATE(name, id, ...) DRAW_STATE_COND(name, id, true, __VA_ARGS__) - DRAW_STATE(vertex_input, TU_DYNAMIC_STATE_VERTEX_INPUT, - builder->graphics_state.vi); + DRAW_STATE_COND(vertex_input, TU_DYNAMIC_STATE_VERTEX_INPUT, + pipeline->shaders[MESA_SHADER_VERTEX], + builder->graphics_state.vi, + pipeline->shaders[MESA_SHADER_VERTEX]->variant->attr_in); DRAW_STATE(vertex_stride, TU_DYNAMIC_STATE_VB_STRIDE, builder->graphics_state.vi); /* If (a) per-view viewport is used or (b) we don't know yet, then we need @@ -4188,8 +4191,10 @@ tu_emit_draw_state(struct tu_cmd_buffer *cmd) } #define DRAW_STATE(name, id, ...) DRAW_STATE_COND(name, id, false, __VA_ARGS__) - DRAW_STATE(vertex_input, TU_DYNAMIC_STATE_VERTEX_INPUT, - cmd->vk.dynamic_graphics_state.vi); + DRAW_STATE_COND(vertex_input, TU_DYNAMIC_STATE_VERTEX_INPUT, + cmd->state.dirty & TU_CMD_DIRTY_VS, + cmd->vk.dynamic_graphics_state.vi, + cmd->state.shaders[MESA_SHADER_VERTEX]->variant->attr_in); /* Vertex input stride is special because it's part of the vertex input in * the pipeline but a separate array when it's dynamic state so we have to diff --git a/src/freedreno/vulkan/tu_shader.cc b/src/freedreno/vulkan/tu_shader.cc index e5a89cf18b2..1b604c484b8 100644 --- a/src/freedreno/vulkan/tu_shader.cc +++ b/src/freedreno/vulkan/tu_shader.cc @@ -1982,7 +1982,6 @@ tu6_emit_vfd_dest(struct tu_cs *cs, const struct ir3_shader_variant *vs) { int32_t input_for_attr[MAX_VERTEX_ATTRIBS]; - uint32_t attr_count = 0; for (unsigned i = 0; i < MAX_VERTEX_ATTRIBS; i++) input_for_attr[i] = -1; @@ -1994,13 +1993,12 @@ tu6_emit_vfd_dest(struct tu_cs *cs, assert(vs->inputs[i].slot >= VERT_ATTRIB_GENERIC0); unsigned loc = vs->inputs[i].slot - VERT_ATTRIB_GENERIC0; input_for_attr[loc] = i; - attr_count = MAX2(attr_count, loc + 1); } tu_cs_emit_regs(cs, A6XX_VFD_CNTL_0( - .fetch_cnt = attr_count, /* decode_cnt for binning pass ? */ - .decode_cnt = attr_count)); + .fetch_cnt = vs->attr_in, /* decode_cnt for binning pass ? */ + .decode_cnt = vs->attr_in)); if (CHIP >= A8XX) { const uint32_t vertexid_regid = @@ -2016,15 +2014,15 @@ tu6_emit_vfd_dest(struct tu_cs *cs, (viewid_regid != INVALID_REG); tu_cs_emit_regs(cs, PC_VS_INPUT_CNTL(CHIP, - .instr_cnt = attr_count, + .instr_cnt = vs->attr_in, .sideband_cnt = sideband_count, )); } - if (attr_count) - tu_cs_emit_pkt4(cs, REG_A6XX_VFD_DEST_CNTL_INSTR(0), attr_count); + if (vs->attr_in) + tu_cs_emit_pkt4(cs, REG_A6XX_VFD_DEST_CNTL_INSTR(0), vs->attr_in); - for (unsigned i = 0; i < attr_count; i++) { + for (unsigned i = 0; i < vs->attr_in; i++) { if (input_for_attr[i] >= 0) { unsigned input_idx = input_for_attr[i]; tu_cs_emit(cs, A6XX_VFD_DEST_CNTL_INSTR(0,