tu: Don't use A6XX_PC_PRIMITIVE_CNTL_0::TESS_UPPER_LEFT_DOMAIN_ORIGIN

This field also affects triangle strip and triangle fan ordering, so we
would get the incorrect (D3D) order with tessellation and geometry
shaders both enabled. Instead flip clockwise/counterclockwise when
the domain origin is upper-left, as radv does.

Because the register is only emitted when tessellation is active which
forces sysmem, it shouldn't regress performance to emit it directly
instead of using a draw state. We're already very tight on draw states.

Cc: mesa-stable
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22301>
This commit is contained in:
Connor Abbott 2023-06-12 16:22:04 +02:00 committed by Marge Bot
parent df7be7323a
commit 5704d0ad27
4 changed files with 78 additions and 38 deletions

View file

@ -3069,6 +3069,23 @@ tu_CmdBindPipeline(VkCommandBuffer commandBuffer,
if (pipeline->output.rb_depth_cntl_disable)
cmd->state.dirty |= TU_CMD_DIRTY_DS;
if (pipeline->active_stages & MESA_SHADER_TESS_CTRL) {
if (!cmd->state.tess_params.valid ||
cmd->state.tess_params.output_upper_left !=
pipeline->program.tess_output_upper_left ||
cmd->state.tess_params.output_lower_left !=
pipeline->program.tess_output_lower_left ||
cmd->state.tess_params.spacing != pipeline->program.tess_spacing) {
cmd->state.tess_params.output_upper_left =
pipeline->program.tess_output_upper_left;
cmd->state.tess_params.output_lower_left =
pipeline->program.tess_output_lower_left;
cmd->state.tess_params.spacing = pipeline->program.tess_spacing;
cmd->state.tess_params.valid = true;
cmd->state.dirty |= TU_CMD_DIRTY_TESS_PARAMS;
}
}
}
VKAPI_ATTR void VKAPI_CALL
@ -5437,13 +5454,21 @@ tu6_draw_common(struct tu_cmd_buffer *cmd,
tu_cs_emit_regs(
cs,
A6XX_PC_PRIMITIVE_CNTL_0(.primitive_restart = primitive_restart,
.provoking_vtx_last = provoking_vtx_last,
.tess_upper_left_domain_origin =
tess_upper_left_domain_origin));
.provoking_vtx_last = provoking_vtx_last));
prim_params->valid = true;
prim_params->primitive_restart = primitive_restart;
prim_params->provoking_vtx_last = provoking_vtx_last;
prim_params->tess_upper_left_domain_origin = tess_upper_left_domain_origin;
cmd->state.dirty |= TU_CMD_DIRTY_TESS_PARAMS;
}
struct tu_tess_params *tess_params = &cmd->state.tess_params;
if (cmd->state.dirty & TU_CMD_DIRTY_TESS_PARAMS) {
tu_cs_emit_regs(cs, A6XX_PC_TESS_CNTL(
.spacing = tess_params->spacing,
.output = prim_params->tess_upper_left_domain_origin ?
tess_params->output_upper_left :
tess_params->output_lower_left));
}
/* Early exit if there is nothing to emit, saves CPU cycles */

View file

@ -69,8 +69,9 @@ enum tu_cmd_dirty_bits
TU_CMD_DIRTY_SCISSORS = BIT(12),
TU_CMD_DIRTY_BLEND = BIT(13),
TU_CMD_DIRTY_PATCH_CONTROL_POINTS = BIT(14),
TU_CMD_DIRTY_TESS_PARAMS = BIT(15),
/* all draw states were disabled and need to be re-enabled: */
TU_CMD_DIRTY_DRAW_STATE = BIT(15)
TU_CMD_DIRTY_DRAW_STATE = BIT(16)
};
/* There are only three cache domains we have to care about: the CCU, or
@ -273,6 +274,12 @@ struct tu_primitive_params {
bool tess_upper_left_domain_origin;
};
struct tu_tess_params {
bool valid;
enum a6xx_tess_output output_upper_left, output_lower_left;
enum a6xx_tess_spacing spacing;
};
/* This should be for state that is set inside a renderpass and used at
* renderpass end time, e.g. to decide whether to use sysmem. This needs
* special handling for secondary cmdbufs and suspending/resuming render
@ -547,6 +554,8 @@ struct tu_cmd_state
struct tu_primitive_params last_prim_params;
struct tu_tess_params tess_params;
uint64_t descriptor_buffer_iova[MAX_SETS];
};

View file

@ -1391,40 +1391,6 @@ tu6_emit_vpc(struct tu_cs *cs,
tu_cs_emit_pkt4(cs, REG_A6XX_PC_TESS_NUM_VERTEX, 1);
tu_cs_emit(cs, hs->tess.tcs_vertices_out);
/* In SPIR-V generated from GLSL, the tessellation primitive params are
* are specified in the tess eval shader, but in SPIR-V generated from
* HLSL, they are specified in the tess control shader. */
const struct ir3_shader_variant *tess =
ds->tess.spacing == TESS_SPACING_UNSPECIFIED ? hs : ds;
tu_cs_emit_pkt4(cs, REG_A6XX_PC_TESS_CNTL, 1);
enum a6xx_tess_output output;
if (tess->tess.point_mode)
output = TESS_POINTS;
else if (tess->tess.primitive_mode == TESS_PRIMITIVE_ISOLINES)
output = TESS_LINES;
else if (tess->tess.ccw)
output = TESS_CCW_TRIS;
else
output = TESS_CW_TRIS;
enum a6xx_tess_spacing spacing;
switch (tess->tess.spacing) {
case TESS_SPACING_EQUAL:
spacing = TESS_EQUAL;
break;
case TESS_SPACING_FRACTIONAL_ODD:
spacing = TESS_FRACTIONAL_ODD;
break;
case TESS_SPACING_FRACTIONAL_EVEN:
spacing = TESS_FRACTIONAL_EVEN;
break;
case TESS_SPACING_UNSPECIFIED:
default:
unreachable("invalid tess spacing");
}
tu_cs_emit(cs, A6XX_PC_TESS_CNTL_SPACING(spacing) |
A6XX_PC_TESS_CNTL_OUTPUT(output));
tu6_emit_link_map(cs, vs, hs, SB6_HS_SHADER);
tu6_emit_link_map(cs, hs, ds, SB6_DS_SHADER);
}
@ -4126,6 +4092,43 @@ tu_pipeline_builder_parse_shader_stages(struct tu_pipeline_builder *builder,
tu6_emit_patch_control_points(&cs, pipeline,
pipeline->tess.patch_control_points);
}
/* In SPIR-V generated from GLSL, the tessellation primitive params are
* are specified in the tess eval shader, but in SPIR-V generated from
* HLSL, they are specified in the tess control shader. */
const struct ir3_shader_variant *tess =
ds->tess.spacing == TESS_SPACING_UNSPECIFIED ? hs : ds;
if (tess->tess.point_mode) {
pipeline->program.tess_output_lower_left =
pipeline->program.tess_output_upper_left = TESS_POINTS;
} else if (tess->tess.primitive_mode == TESS_PRIMITIVE_ISOLINES) {
pipeline->program.tess_output_lower_left =
pipeline->program.tess_output_upper_left = TESS_LINES;
} else if (tess->tess.ccw) {
/* Tessellation orientation in HW is specified with a lower-left
* origin, we need to swap them if the origin is upper-left.
*/
pipeline->program.tess_output_lower_left = TESS_CCW_TRIS;
pipeline->program.tess_output_upper_left = TESS_CW_TRIS;
} else {
pipeline->program.tess_output_lower_left = TESS_CW_TRIS;
pipeline->program.tess_output_upper_left = TESS_CCW_TRIS;
}
switch (tess->tess.spacing) {
case TESS_SPACING_EQUAL:
pipeline->program.tess_spacing = TESS_EQUAL;
break;
case TESS_SPACING_FRACTIONAL_ODD:
pipeline->program.tess_spacing = TESS_FRACTIONAL_ODD;
break;
case TESS_SPACING_FRACTIONAL_EVEN:
pipeline->program.tess_spacing = TESS_FRACTIONAL_EVEN;
break;
case TESS_SPACING_UNSPECIFIED:
default:
unreachable("invalid tess spacing");
}
}
struct ir3_shader_variant *last_shader;

View file

@ -236,6 +236,9 @@ struct tu_pipeline
bool writes_viewport;
bool per_samp;
enum a6xx_tess_output tess_output_upper_left, tess_output_lower_left;
enum a6xx_tess_spacing tess_spacing;
} program;
struct