radv: add support for dynamic tessellation domain origin

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18882>
This commit is contained in:
Samuel Pitoiset
2022-05-31 11:04:49 +02:00
committed by Marge Bot
parent 6bf34e9f36
commit f22290949d
3 changed files with 114 additions and 67 deletions

View File

@@ -123,6 +123,7 @@ const struct radv_dynamic_state default_dynamic_state = {
.color_write_enable = 0u,
.patch_control_points = 0,
.polygon_mode = 0,
.tess_domain_origin = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT,
};
static void
@@ -258,6 +259,8 @@ radv_bind_dynamic_state(struct radv_cmd_buffer *cmd_buffer, const struct radv_dy
RADV_CMP_COPY(polygon_mode, RADV_DYNAMIC_POLYGON_MODE);
RADV_CMP_COPY(tess_domain_origin, RADV_DYNAMIC_TESS_DOMAIN_ORIGIN);
#undef RADV_CMP_COPY
cmd_buffer->state.dirty |= dest_mask;
@@ -1481,6 +1484,10 @@ radv_emit_graphics_pipeline(struct radv_cmd_buffer *cmd_buffer)
cmd_buffer->state.emitted_graphics_pipeline->cb_target_mask != pipeline->cb_target_mask)
cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_COLOR_WRITE_ENABLE;
if (!cmd_buffer->state.emitted_graphics_pipeline ||
cmd_buffer->state.emitted_graphics_pipeline->vgt_tf_param != pipeline->vgt_tf_param)
cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_TESS_DOMAIN_ORIGIN;
radeon_emit_array(cmd_buffer->cs, pipeline->base.cs.buf, pipeline->base.cs.cdw);
if (pipeline->has_ngg_culling &&
@@ -3292,6 +3299,34 @@ radv_emit_vertex_input(struct radv_cmd_buffer *cmd_buffer, bool pipeline_is_dirt
radv_save_vs_prolog(cmd_buffer, prolog);
}
static void
radv_emit_tess_domain_origin(struct radv_cmd_buffer *cmd_buffer)
{
struct radv_graphics_pipeline *pipeline = cmd_buffer->state.graphics_pipeline;
struct radv_shader *tes = radv_get_shader(&pipeline->base, MESA_SHADER_TESS_EVAL);
struct radv_dynamic_state *d = &cmd_buffer->state.dynamic;
unsigned vgt_tf_param = pipeline->vgt_tf_param;
unsigned topology;
if (tes->info.tes.point_mode) {
topology = V_028B6C_OUTPUT_POINT;
} else if (tes->info.tes._primitive_mode == TESS_PRIMITIVE_ISOLINES) {
topology = V_028B6C_OUTPUT_LINE;
} else {
bool ccw = tes->info.tes.ccw;
if (d->tess_domain_origin != VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT) {
ccw = !ccw;
}
topology = ccw ? V_028B6C_OUTPUT_TRIANGLE_CCW : V_028B6C_OUTPUT_TRIANGLE_CW;
}
vgt_tf_param |= S_028B6C_TOPOLOGY(topology);
radeon_set_context_reg(cmd_buffer->cs, R_028B6C_VGT_TF_PARAM, vgt_tf_param);
}
static void
radv_cmd_buffer_flush_dynamic_state(struct radv_cmd_buffer *cmd_buffer, bool pipeline_is_dirty)
{
@@ -3368,6 +3403,9 @@ radv_cmd_buffer_flush_dynamic_state(struct radv_cmd_buffer *cmd_buffer, bool pip
if (states & RADV_CMD_DIRTY_DYNAMIC_PATCH_CONTROL_POINTS)
radv_emit_patch_control_points(cmd_buffer);
if (states & RADV_CMD_DIRTY_DYNAMIC_TESS_DOMAIN_ORIGIN)
radv_emit_tess_domain_origin(cmd_buffer);
cmd_buffer->state.dirty &= ~states;
}
@@ -5772,6 +5810,18 @@ radv_CmdSetPolygonModeEXT(VkCommandBuffer commandBuffer, VkPolygonMode polygonMo
state->dirty |= RADV_CMD_DIRTY_DYNAMIC_POLYGON_MODE;
}
VKAPI_ATTR void VKAPI_CALL
radv_CmdSetTessellationDomainOriginEXT(VkCommandBuffer commandBuffer,
VkTessellationDomainOrigin domainOrigin)
{
RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
struct radv_cmd_state *state = &cmd_buffer->state;
state->dynamic.tess_domain_origin = domainOrigin;
state->dirty |= RADV_CMD_DIRTY_DYNAMIC_TESS_DOMAIN_ORIGIN;
}
VKAPI_ATTR void VKAPI_CALL
radv_CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount,
const VkCommandBuffer *pCmdBuffers)

View File

@@ -1396,7 +1396,7 @@ radv_pipeline_needed_dynamic_state(const struct radv_graphics_pipeline *pipeline
RADV_DYNAMIC_VERTEX_INPUT;
if (pipeline->active_stages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
states |= RADV_DYNAMIC_PATCH_CONTROL_POINTS;
states |= RADV_DYNAMIC_PATCH_CONTROL_POINTS | RADV_DYNAMIC_TESS_DOMAIN_ORIGIN;
return states;
}
@@ -1433,7 +1433,7 @@ radv_pipeline_needed_dynamic_state(const struct radv_graphics_pipeline *pipeline
states &= ~RADV_DYNAMIC_COLOR_WRITE_ENABLE;
if (!(pipeline->active_stages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT))
states &= ~RADV_DYNAMIC_PATCH_CONTROL_POINTS;
states &= ~(RADV_DYNAMIC_PATCH_CONTROL_POINTS | RADV_DYNAMIC_TESS_DOMAIN_ORIGIN);
return states;
}
@@ -1891,6 +1891,10 @@ radv_pipeline_init_dynamic_state(struct radv_graphics_pipeline *pipeline,
dynamic->polygon_mode = si_translate_fill(state->rs->polygon_mode);
}
if (states & RADV_DYNAMIC_TESS_DOMAIN_ORIGIN) {
dynamic->tess_domain_origin = state->ts->domain_origin;
}
pipeline->dynamic_state.mask = states;
}
@@ -5234,70 +5238,6 @@ radv_pipeline_emit_tess_shaders(struct radeon_cmdbuf *ctx_cs, struct radeon_cmdb
}
}
static void
radv_pipeline_emit_tess_state(struct radeon_cmdbuf *ctx_cs,
const struct radv_graphics_pipeline *pipeline,
const struct vk_graphics_pipeline_state *state)
{
const struct radv_physical_device *pdevice = pipeline->base.device->physical_device;
struct radv_shader *tes = radv_get_shader(&pipeline->base, MESA_SHADER_TESS_EVAL);
unsigned type = 0, partitioning = 0, topology = 0, distribution_mode = 0;
switch (tes->info.tes._primitive_mode) {
case TESS_PRIMITIVE_TRIANGLES:
type = V_028B6C_TESS_TRIANGLE;
break;
case TESS_PRIMITIVE_QUADS:
type = V_028B6C_TESS_QUAD;
break;
case TESS_PRIMITIVE_ISOLINES:
type = V_028B6C_TESS_ISOLINE;
break;
default:
break;
}
switch (tes->info.tes.spacing) {
case TESS_SPACING_EQUAL:
partitioning = V_028B6C_PART_INTEGER;
break;
case TESS_SPACING_FRACTIONAL_ODD:
partitioning = V_028B6C_PART_FRAC_ODD;
break;
case TESS_SPACING_FRACTIONAL_EVEN:
partitioning = V_028B6C_PART_FRAC_EVEN;
break;
default:
break;
}
bool ccw = tes->info.tes.ccw;
if (state->ts->domain_origin != VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT)
ccw = !ccw;
if (tes->info.tes.point_mode)
topology = V_028B6C_OUTPUT_POINT;
else if (tes->info.tes._primitive_mode == TESS_PRIMITIVE_ISOLINES)
topology = V_028B6C_OUTPUT_LINE;
else if (ccw)
topology = V_028B6C_OUTPUT_TRIANGLE_CCW;
else
topology = V_028B6C_OUTPUT_TRIANGLE_CW;
if (pdevice->rad_info.has_distributed_tess) {
if (pdevice->rad_info.family == CHIP_FIJI || pdevice->rad_info.family >= CHIP_POLARIS10)
distribution_mode = V_028B6C_TRAPEZOIDS;
else
distribution_mode = V_028B6C_DONUTS;
} else
distribution_mode = V_028B6C_NO_DIST;
radeon_set_context_reg(ctx_cs, R_028B6C_VGT_TF_PARAM,
S_028B6C_TYPE(type) | S_028B6C_PARTITIONING(partitioning) |
S_028B6C_TOPOLOGY(topology) |
S_028B6C_DISTRIBUTION_MODE(distribution_mode));
}
static void
radv_pipeline_emit_hw_gs(struct radeon_cmdbuf *ctx_cs, struct radeon_cmdbuf *cs,
const struct radv_graphics_pipeline *pipeline, const struct radv_shader *gs)
@@ -5890,7 +5830,6 @@ radv_pipeline_emit_pm4(struct radv_graphics_pipeline *pipeline,
if (radv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_CTRL)) {
radv_pipeline_emit_tess_shaders(ctx_cs, cs, pipeline);
radv_pipeline_emit_tess_state(ctx_cs, pipeline, state);
}
radv_pipeline_emit_geometry_shader(ctx_cs, cs, pipeline);
@@ -6093,6 +6032,54 @@ radv_pipeline_init_vgt_gs_out(struct radv_graphics_pipeline *pipeline,
return gs_out;
}
static void
radv_pipeline_init_tess_state(struct radv_graphics_pipeline *pipeline,
const struct vk_graphics_pipeline_state *state)
{
const struct radv_physical_device *pdevice = pipeline->base.device->physical_device;
struct radv_shader *tes = radv_get_shader(&pipeline->base, MESA_SHADER_TESS_EVAL);
unsigned type = 0, partitioning = 0, distribution_mode = 0;
switch (tes->info.tes._primitive_mode) {
case TESS_PRIMITIVE_TRIANGLES:
type = V_028B6C_TESS_TRIANGLE;
break;
case TESS_PRIMITIVE_QUADS:
type = V_028B6C_TESS_QUAD;
break;
case TESS_PRIMITIVE_ISOLINES:
type = V_028B6C_TESS_ISOLINE;
break;
default:
break;
}
switch (tes->info.tes.spacing) {
case TESS_SPACING_EQUAL:
partitioning = V_028B6C_PART_INTEGER;
break;
case TESS_SPACING_FRACTIONAL_ODD:
partitioning = V_028B6C_PART_FRAC_ODD;
break;
case TESS_SPACING_FRACTIONAL_EVEN:
partitioning = V_028B6C_PART_FRAC_EVEN;
break;
default:
break;
}
if (pdevice->rad_info.has_distributed_tess) {
if (pdevice->rad_info.family == CHIP_FIJI || pdevice->rad_info.family >= CHIP_POLARIS10)
distribution_mode = V_028B6C_TRAPEZOIDS;
else
distribution_mode = V_028B6C_DONUTS;
} else
distribution_mode = V_028B6C_NO_DIST;
pipeline->vgt_tf_param = S_028B6C_TYPE(type) | S_028B6C_PARTITIONING(partitioning) |
S_028B6C_DISTRIBUTION_MODE(distribution_mode);
}
static void
radv_pipeline_init_extra(struct radv_graphics_pipeline *pipeline,
const struct radv_graphics_pipeline_create_info *extra,
@@ -6285,6 +6272,10 @@ radv_graphics_pipeline_init(struct radv_graphics_pipeline *pipeline, struct radv
radv_pipeline_init_gs_ring_state(pipeline, &gs->info.gs_ring_info);
}
if (radv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_CTRL)) {
radv_pipeline_init_tess_state(pipeline, &state);
}
if (!radv_pipeline_has_stage(pipeline, MESA_SHADER_MESH))
radv_pipeline_init_vertex_input_state(pipeline, &state);

View File

@@ -1353,6 +1353,8 @@ struct radv_dynamic_state {
uint32_t patch_control_points;
uint32_t polygon_mode;
VkTessellationDomainOrigin tess_domain_origin;
};
extern const struct radv_dynamic_state default_dynamic_state;
@@ -2045,6 +2047,7 @@ struct radv_graphics_pipeline {
uint8_t next_vertex_stage : 8;
uint32_t vb_desc_usage_mask;
uint32_t vb_desc_alloc_size;
uint32_t vgt_tf_param;
/* Last pre-PS API stage */
gl_shader_stage last_vgt_api_stage;
@@ -3088,6 +3091,9 @@ si_translate_blend_logic_op(VkLogicOp op)
}
}
uint32_t radv_get_tess_output_topology(const struct radv_graphics_pipeline *pipeline,
VkTessellationDomainOrigin domain_origin);
ALWAYS_INLINE static bool
radv_is_streamout_enabled(struct radv_cmd_buffer *cmd_buffer)
{